Home | History | Annotate | Download | only in ARM
      1 ;Check 5.5 Parameter Passing --> Stage C --> C.4 statement, when NSAA is not
      2 ;equal to SP.
      3 ;
      4 ; Our purpose: make NSAA != SP, and only after start to use GPRs. 
      5 ;
      6 ;Co-Processor register candidates may be either in VFP or in stack, so after
      7 ;all VFP are allocated, stack is used. We can use stack without GPR allocation
      8 ;in that case, passing 9 f64 params, for example.
      9 ;First eight params goes to d0-d7, ninth one goes to the stack.
     10 ;Now, as 10th parameter, we pass i32, and it must go to R0.
     11 ;
     12 ;5.5 Parameter Passing, Stage C:
     13 ;
     14 ;C.2.cp If the argument is a CPRC then any co-processor registers in that class
     15 ;that are unallocated are marked as unavailable. The NSAA is adjusted upwards
     16 ;until it is correctly aligned for the argument and the argument is copied to
     17 ;the memory at the adjusted NSAA. The NSAA is further incremented by the size
     18 ;of the argument. The argument has now been allocated.
     19 ;...
     20 ;C.4 If the size in words of the argument is not more than r4 minus NCRN, the
     21 ;argument is copied into core registers, starting at the NCRN. The NCRN is
     22 ;incremented by the number of registers used. Successive registers hold the
     23 ;parts of the argument they would hold if its value were loaded into those
     24 ;registers from memory using an LDM instruction. The argument has now been
     25 ;allocated.
     26 ;
     27 ;What is actually checked here:
     28 ;Here we check that i32 param goes to r0.
     29 ;
     30 ;Current test-case was produced with command:
     31 ;arm-linux-gnueabihf-clang -mcpu=cortex-a9 params-to-GPR.c -S -O1 -emit-llvm
     32 ;
     33 ;// params-to-GRP.c:
     34 ;
     35 ;void fooUseI32(unsigned);
     36 ;
     37 ;void foo(long double p0,
     38 ;         long double p1,
     39 ;         long double p2,
     40 ;         long double p3,
     41 ;         long double p4,
     42 ;         long double p5,
     43 ;         long double p6,
     44 ;         long double p7,
     45 ;         long double p8,
     46 ;         unsigned p9) {
     47 ;  fooUseI32(p9);
     48 ;}
     49 ;
     50 ;void doFoo() {
     51 ;  foo( 1,2,3,4,5,6,7,8,9, 43 );
     52 ;}
     53 
     54 ;RUN: llc -mtriple=thumbv7-linux-gnueabihf -float-abi=hard < %s | FileCheck %s
     55 ;
     56 ;CHECK-LABEL:     foo:
     57 ;CHECK-NOT:     mov r0
     58 ;CHECK-NOT:     ldr r0
     59 ;CHECK:         bl fooUseI32
     60 ;CHECK-LABEL:     doFoo:
     61 ;CHECK:         movs    r0, #43
     62 ;CHECK:         bl      foo
     63 
     64 define void @foo(double %p0, ; --> D0
     65                  double %p1, ; --> D1
     66 		 double %p2, ; --> D2
     67 		 double %p3, ; --> D3
     68 		 double %p4, ; --> D4
     69 		 double %p5, ; --> D5
     70 		 double %p6, ; --> D6
     71 		 double %p7, ; --> D7
     72 		 double %p8, ; --> Stack
     73 		 i32 %p9) #0 { ; --> R0, not Stack+8
     74 entry:
     75   call void @fooUseI32(i32 %p9)
     76   ret void
     77 }
     78 
     79 declare void @fooUseI32(i32)
     80 
     81 define void @doFoo() {
     82 entry:
     83   tail call void @foo(double 23.0, ; --> D0
     84                       double 23.1, ; --> D1
     85 		      double 23.2, ; --> D2
     86                       double 23.3, ; --> D3
     87                       double 23.4, ; --> D4
     88                       double 23.5, ; --> D5
     89                       double 23.6, ; --> D6
     90                       double 23.7, ; --> D7
     91                       double 23.8, ; --> Stack
     92                       i32 43)      ; --> R0, not Stack+8
     93   ret void
     94 }
     95 
     96