blob: 9490c68c8efd729d30adf29ecf687b97ef9ae91a [file] [log] [blame]
Jan Voung28068ad2015-07-31 12:58:46 -07001; This tries to create variables with very large stack offsets.
2; This requires a lot of variables/register pressure. To simplify this
3; we assume poor register allocation from Om1, and a flag that forces
4; the frame to add K amount of unused stack for testing.
5; We only need to test ARM and other architectures which have limited space
6; for specifying an offset within an instruction.
7
Jim Stichnoth033dda72016-10-03 07:56:25 -07008; RUN: %if --need=target_ARM32 \
9; RUN: --command %p2i --filetype=obj --disassemble --target arm32 \
10; RUN: -i %s --args -Om1 --test-stack-extra 4096 \
Karl Schimpf57d31ac2015-10-07 09:53:12 -070011; RUN: -allow-externally-defined-symbols \
Jim Stichnoth033dda72016-10-03 07:56:25 -070012; RUN: | %if --need=target_ARM32 \
Jan Voung28068ad2015-07-31 12:58:46 -070013; RUN: --command FileCheck --check-prefix ARM32 %s
14
15declare i64 @dummy(i32 %t1, i32 %t2, i32 %t3, i64 %t4, i64 %t5)
16
17; Test a function that requires lots of stack (due to test flag), and uses
18; SP as the base register (originally).
19define internal i64 @lotsOfStack(i32 %a, i32 %b, i32 %c, i32 %d) {
20entry:
21 %t1 = xor i32 %a, %b
22 %t2 = or i32 %c, %d
23 %cmp = icmp eq i32 %t1, %t2
24 br i1 %cmp, label %br_1, label %br_2
25
26br_1:
27 %x1 = zext i32 %t1 to i64
28 %y1 = ashr i64 %x1, 17
29 ; Use some stack during the call, so that references to %t1 and %t2's
30 ; stack slots require stack adjustment.
31 %r1 = call i64 @dummy(i32 123, i32 321, i32 %t2, i64 %x1, i64 %y1)
32 %z1 = sub i64 %r1, %y1
33 br label %end
34
35br_2:
36 %x2 = zext i32 %t2 to i64
37 %y2 = and i64 %x2, 123
38 %r2 = call i64 @dummy(i32 123, i32 321, i32 %t2, i64 %x2, i64 %y2)
39 %z2 = and i64 %r2, %y2
40 br label %end
41
42end:
43 %x3 = phi i64 [ %x1, %br_1 ], [ %x2, %br_2 ]
44 %z3 = phi i64 [ %z1, %br_1 ], [ %z2, %br_2 ]
45 %r3 = and i64 %x3, %z3
46 ret i64 %r3
47}
48; ARM32-LABEL: lotsOfStack
49; ARM32-NOT: mov fp, sp
50; ARM32: movw ip, #4{{.*}}
51; ARM32-NEXT: sub sp, sp, ip
John Portof4198542015-11-20 14:17:23 -080052; ARM32: movw ip, #4248
Jan Voung28068ad2015-07-31 12:58:46 -070053; ARM32-NEXT: add ip, sp, ip
54; ARM32-NOT: movw ip
55; %t2 is the result of the "or", and %t2 will be passed via r1 to the call.
56; Use that to check the stack offset of %t2. The first offset and the
57; later offset right before the call should be 16 bytes apart,
58; because of the sub sp, sp, #16.
59; ARM32: orr [[REG:r.*]], {{.*}},
60; I.e., the slot for t2 is (sp0 + 4232 - 20) == sp0 + 4212.
61; ARM32: str [[REG]], [ip, #-20]
62; ARM32: b {{[a-f0-9]+}}
63; Now skip ahead to where the call in br_1 begins, to check how %t2 is used.
John Portof4198542015-11-20 14:17:23 -080064; ARM32: movw ip, #4232
Jan Voung28068ad2015-07-31 12:58:46 -070065; ARM32-NEXT: add ip, sp, ip
Jan Voung28068ad2015-07-31 12:58:46 -070066; ARM32: ldr r2, [ip, #-4]
John Portob82d79a2016-03-01 06:11:05 -080067; ARM32: bl {{.*}} dummy
Jan Voung28068ad2015-07-31 12:58:46 -070068; The call clobbers ip, so we need to re-create the base register.
69; ARM32: movw ip, #4{{.*}}
70; ARM32: b {{[a-f0-9]+}}
John Portob82d79a2016-03-01 06:11:05 -080071; ARM32: bl {{.*}} dummy
Jan Voung28068ad2015-07-31 12:58:46 -070072
73; Similar, but test a function that uses FP as the base register (originally).
74define internal i64 @usesFrameReg(i32 %a, i32 %b, i32 %c, i32 %d) {
75entry:
76 %p = alloca i8, i32 %d, align 4
77 %t1 = xor i32 %a, %b
78 %t2 = or i32 %c, %d
79 %cmp = icmp eq i32 %t1, %t2
80 br i1 %cmp, label %br_1, label %br_2
81
82br_1:
83 %x1 = zext i32 %t1 to i64
84 %y1 = ashr i64 %x1, 17
85 %p32 = ptrtoint i8* %p to i32
86 %r1 = call i64 @dummy(i32 %p32, i32 321, i32 %t2, i64 %x1, i64 %y1)
87 %z1 = sub i64 %r1, %y1
88 br label %end
89
90br_2:
91 %x2 = zext i32 %t2 to i64
92 %y2 = and i64 %x2, 123
93 %r2 = call i64 @dummy(i32 123, i32 321, i32 %d, i64 %x2, i64 %y2)
94 %z2 = and i64 %r2, %y2
95 br label %end
96
97end:
98 %x3 = phi i64 [ %x1, %br_1 ], [ %x2, %br_2 ]
99 %z3 = phi i64 [ %z1, %br_1 ], [ %z2, %br_2 ]
100 %r3 = and i64 %x3, %z3
101 ret i64 %r3
102}
103; ARM32-LABEL: usesFrameReg
104; ARM32: mov fp, sp
105; ARM32: movw ip, #4{{.*}}
106; ARM32-NEXT: sub sp, sp, ip
107; ARM32: movw ip, #4100
108; ARM32-NEXT: sub ip, fp, ip
109; ARM32-NOT: movw ip
110; %t2 is the result of the "or", and %t2 will be passed via r1 to the call.
111; Use that to check the stack offset of %t2. It should be the same offset
112; even after sub sp, sp, #16, because the base register was originally
113; the FP and not the SP.
114; ARM32: orr [[REG:r.*]], {{.*}},
115; I.e., the slot for t2 is (fp0 - 4100 -24) == fp0 - 4124
116; ARM32: str [[REG]], [ip, #-24]
117; ARM32: b {{[a-f0-9]+}}
118; Now skip ahead to where the call in br_1 begins, to check how %t2 is used.
119; ARM32: movw ip, #4120
120; ARM32-NEXT: sub ip, fp, ip
Jan Voung28068ad2015-07-31 12:58:46 -0700121; ARM32: ldr r2, [ip, #-4]
John Portob82d79a2016-03-01 06:11:05 -0800122; ARM32: bl {{.*}} dummy
Jan Voung28068ad2015-07-31 12:58:46 -0700123; The call clobbers ip, so we need to re-create the base register.
124; ARM32: movw ip, #4{{.*}}
125; ARM32: b {{[a-f0-9]+}}
John Portob82d79a2016-03-01 06:11:05 -0800126; ARM32: bl {{.*}} dummy