llvm.org GIT mirror llvm / 78e3c90
Fix for 5.5 Parameter Passing --> Stage C: -- C.4 and C.5 statements, when NSAA is not equal to SP. -- C.1.cp statement for VA functions. Note: There are no VFP CPRCs in a variadic procedure. Before this patch "NSAA != 0" means "don't use GPRs anymore ". But there are some exceptions in AAPCS. 1. For non VA function: allocate all VFP regs for CPRC. When all VFPs are allocated CPRCs would be sent to stack, while non CPRCs may be still allocated in GRPs. 2. Check that for VA functions all params uses GPRs and then stack. No exceptions, no CPRCs here. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@180011 91177308-0d34-0410-b5e6-96231b3b80d8 Stepan Dyatkovskiy 7 years ago
6 changed file(s) with 192 addition(s) and 2 deletion(s). Raw diff Collapse all Expand all
7373 static const uint16_t HiRegList[] = { ARM::R0, ARM::R2 };
7474 static const uint16_t LoRegList[] = { ARM::R1, ARM::R3 };
7575 static const uint16_t ShadowRegList[] = { ARM::R0, ARM::R1 };
76 static const uint16_t GPRArgRegs[] = { ARM::R0, ARM::R1, ARM::R2, ARM::R3 };
7677
7778 unsigned Reg = State.AllocateReg(HiRegList, ShadowRegList, 2);
7879 if (Reg == 0) {
80
81 // If we had R3 unallocated only, now we still must to waste it.
82 Reg = State.AllocateReg(GPRArgRegs, 4);
83 assert((!Reg || Reg == ARM::R3) && "Wrong GPRs usage for f64");
84
7985 // For the 2nd half of a v2f64, do not just fail.
8086 if (CanFail)
8187 return false;
110110 // i64 is 8-aligned i32 here, so we may need to eat R1 as a pad register
111111 // (and the same is true for f64 if VFP is not enabled)
112112 CCIfType<[i32], CCIfAlign<"8", CCAssignToRegWithShadow<[R0, R2], [R0, R1]>>>,
113 CCIfType<[i32], CCIf<"State.getNextStackOffset() == 0 &&"
114 "ArgFlags.getOrigAlign() != 8",
113 CCIfType<[i32], CCIf<"ArgFlags.getOrigAlign() != 8",
115114 CCAssignToReg<[R0, R1, R2, R3]>>>,
116115
117116 CCIfType<[i32], CCIfAlign<"8", CCAssignToStackWithShadow<4, 8, R3>>>,
17371737 State->getCallOrPrologue() == Call) &&
17381738 "unhandled ParmContext");
17391739 if ((!State->isFirstByValRegValid()) &&
1740 (!Subtarget->isAAPCS_ABI() || State->getNextStackOffset() == 0) &&
17401741 (ARM::R0 <= reg) && (reg <= ARM::R3)) {
17411742 if (Subtarget->isAAPCS_ABI() && Align > 4) {
17421743 unsigned AlignInRegs = Align / 4;
0 ;Check 5.5 Parameter Passing --> Stage C --> C.4 statement, when NSAA is not
1 ;equal to SP.
2 ;
3 ; Our purpose: make NSAA != SP, and only after start to use GPRs.
4 ;
5 ;Co-Processor register candidates may be either in VFP or in stack, so after
6 ;all VFP are allocated, stack is used. We can use stack without GPR allocation
7 ;in that case, passing 9 f64 params, for example.
8 ;First eight params goes to d0-d7, ninth one goes to the stack.
9 ;Now, as 10th parameter, we pass i32, and it must go to R0.
10 ;
11 ;5.5 Parameter Passing, Stage C:
12 ;
13 ;C.2.cp If the argument is a CPRC then any co-processor registers in that class
14 ;that are unallocated are marked as unavailable. The NSAA is adjusted upwards
15 ;until it is correctly aligned for the argument and the argument is copied to
16 ;the memory at the adjusted NSAA. The NSAA is further incremented by the size
17 ;of the argument. The argument has now been allocated.
18 ;...
19 ;C.4 If the size in words of the argument is not more than r4 minus NCRN, the
20 ;argument is copied into core registers, starting at the NCRN. The NCRN is
21 ;incremented by the number of registers used. Successive registers hold the
22 ;parts of the argument they would hold if its value were loaded into those
23 ;registers from memory using an LDM instruction. The argument has now been
24 ;allocated.
25 ;
26 ;What is actually checked here:
27 ;Here we check that i32 param goes to r0.
28 ;
29 ;Current test-case was produced with command:
30 ;arm-linux-gnueabihf-clang -mcpu=cortex-a9 params-to-GPR.c -S -O1 -emit-llvm
31 ;
32 ;// params-to-GRP.c:
33 ;
34 ;void fooUseI32(unsigned);
35 ;
36 ;void foo(long double p0,
37 ; long double p1,
38 ; long double p2,
39 ; long double p3,
40 ; long double p4,
41 ; long double p5,
42 ; long double p6,
43 ; long double p7,
44 ; long double p8,
45 ; unsigned p9) {
46 ; fooUseI32(p9);
47 ;}
48 ;
49 ;void doFoo() {
50 ; foo( 1,2,3,4,5,6,7,8,9, 43 );
51 ;}
52
53 ;RUN: llc -mtriple=thumbv7-linux-gnueabihf -float-abi=hard < %s | FileCheck %s
54 ;
55 ;CHECK: foo:
56 ;CHECK-NOT: mov r0
57 ;CHECK-NOT: ldr r0
58 ;CHECK: bl fooUseI32
59 ;CHECK: doFoo:
60 ;CHECK: movs r0, #43
61 ;CHECK: bl foo
62
63 define void @foo(double %p0, ; --> D0
64 double %p1, ; --> D1
65 double %p2, ; --> D2
66 double %p3, ; --> D3
67 double %p4, ; --> D4
68 double %p5, ; --> D5
69 double %p6, ; --> D6
70 double %p7, ; --> D7
71 double %p8, ; --> Stack
72 i32 %p9) #0 { ; --> R0, not Stack+8
73 entry:
74 tail call void @fooUseI32(i32 %p9)
75 ret void
76 }
77
78 declare void @fooUseI32(i32)
79
80 define void @doFoo() {
81 entry:
82 tail call void @foo(double 23.0, ; --> D0
83 double 23.1, ; --> D1
84 double 23.2, ; --> D2
85 double 23.3, ; --> D3
86 double 23.4, ; --> D4
87 double 23.5, ; --> D5
88 double 23.6, ; --> D6
89 double 23.7, ; --> D7
90 double 23.8, ; --> Stack
91 i32 43) ; --> R0, not Stack+8
92 ret void
93 }
94
0 ;Check 5.5 Parameter Passing --> Stage C --> C.5 statement, when NSAA is not
1 ;equal to SP.
2 ;
3 ; Our purpose: make NSAA != SP, and only after start to use GPRs, then pass
4 ; byval parameter and check that it goes to stack only.
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 ;For more information,
13 ;please, read 5.5 Parameter Passing, Stage C, stages C.2.cp, C.4 and C.5
14 ;
15 ;
16 ;RUN: llc -mtriple=thumbv7-linux-gnueabihf -float-abi=hard < %s | FileCheck %s
17
18 %struct_t = type { i32, i32, i32, i32 }
19 @static_val = constant %struct_t { i32 777, i32 888, i32 999, i32 1000 }
20 declare void @fooUseStruct(%struct_t*)
21
22 define void @foo2(double %p0, ; --> D0
23 double %p1, ; --> D1
24 double %p2, ; --> D2
25 double %p3, ; --> D3
26 double %p4, ; --> D4
27 double %p5, ; --> D5
28 double %p6, ; --> D6
29 double %p7, ; --> D7
30 double %p8, ; --> Stack
31 i32 %p9, ; --> R0
32 %struct_t* byval %p10) ; --> Stack+8
33 {
34 entry:
35 ;CHECK: push.w {r11, lr}
36 ;CHECK-NOT: stm
37 ;CHECK: add r0, sp, #16
38 ;CHECK: bl fooUseStruct
39 call void @fooUseStruct(%struct_t* %p10)
40
41 ret void
42 }
43
44 define void @doFoo2() {
45 entry:
46 ;CHECK-NOT: ldm
47 tail call void @foo2(double 23.0, ; --> D0
48 double 23.1, ; --> D1
49 double 23.2, ; --> D2
50 double 23.3, ; --> D3
51 double 23.4, ; --> D4
52 double 23.5, ; --> D5
53 double 23.6, ; --> D6
54 double 23.7, ; --> D7
55 double 23.8, ; --> Stack
56 i32 43, ; --> R0, not Stack+8
57 %struct_t* byval @static_val) ; --> Stack+8, not R1
58 ret void
59 }
60
0 ;Check 5.5 Parameter Passing --> Stage C --> C.1.cp statement for VA functions.
1 ;Note: There are no VFP CPRCs in a variadic procedure.
2 ;Check that after %C was sent to stack, we set Next Core Register Number to R4.
3
4 ;This test is simplified IR version of
5 ;test-suite/SingleSource/UnitTests/2002-05-02-ManyArguments.c
6
7 ;RUN: llc -mtriple=thumbv7-linux-gnueabihf -float-abi=hard < %s | FileCheck %s
8
9 @.str = private unnamed_addr constant [13 x i8] c"%d %d %f %i\0A\00", align 1
10
11 ;CHECK: printfn:
12 define void @printfn(i32 %a, i16 signext %b, double %C, i8 signext %E) {
13 entry:
14 %conv = sext i16 %b to i32
15 %conv1 = sext i8 %E to i32
16 %call = tail call i32 (i8*, ...)* @printf(
17 i8* getelementptr inbounds ([13 x i8]* @.str, i32 0, i32 0), ; --> R0
18 i32 %a, ; --> R1
19 i32 %conv, ; --> R2
20 double %C, ; --> SP, NCRN := R4
21 ;CHECK: str r2, [sp, #8]
22 i32 %conv1) ; --> SP+8
23 ret void
24 }
25
26 declare i32 @printf(i8* nocapture, ...)
27