xref: /llvm-project/llvm/test/CodeGen/ARM/ipra.ll (revision 8ed8353fc45e3906f7fd8dde1072bce7b54aca62)
1*8ed8353fSOliver Stannard; RUN: llc -mtriple armv7a--none-eabi < %s              | FileCheck %s --check-prefix=CHECK --check-prefix=DISABLED
2*8ed8353fSOliver Stannard; RUN: llc -mtriple armv7a--none-eabi < %s -enable-ipra | FileCheck %s --check-prefix=CHECK --check-prefix=ENABLED
3*8ed8353fSOliver Stannard
4*8ed8353fSOliver Stannarddefine void @leaf()  {
5*8ed8353fSOliver Stannardentry:
6*8ed8353fSOliver Stannard  tail call void asm sideeffect "", ""()
7*8ed8353fSOliver Stannard  ret void
8*8ed8353fSOliver Stannard}
9*8ed8353fSOliver Stannard
10*8ed8353fSOliver Stannarddefine void @leaf_r3() {
11*8ed8353fSOliver Stannardentry:
12*8ed8353fSOliver Stannard  tail call void asm sideeffect "", "~{r3}"()
13*8ed8353fSOliver Stannard  ret void
14*8ed8353fSOliver Stannard}
15*8ed8353fSOliver Stannard
16*8ed8353fSOliver Stannarddefine void @leaf_r4() {
17*8ed8353fSOliver Stannardentry:
18*8ed8353fSOliver Stannard  tail call void asm sideeffect "", "~{r4}"()
19*8ed8353fSOliver Stannard  ret void
20*8ed8353fSOliver Stannard}
21*8ed8353fSOliver Stannard
22*8ed8353fSOliver Stannarddefine void @leaf_s0() {
23*8ed8353fSOliver Stannardentry:
24*8ed8353fSOliver Stannard  tail call void asm sideeffect "", "~{s0}"()
25*8ed8353fSOliver Stannard  ret void
26*8ed8353fSOliver Stannard}
27*8ed8353fSOliver Stannard
28*8ed8353fSOliver Stannarddefine void @leaf_d0() {
29*8ed8353fSOliver Stannardentry:
30*8ed8353fSOliver Stannard  tail call void asm sideeffect "", "~{d0}"()
31*8ed8353fSOliver Stannard  ret void
32*8ed8353fSOliver Stannard}
33*8ed8353fSOliver Stannard
34*8ed8353fSOliver Stannard; r3 is normally caller-saved, but with IPRA we can see that it isn't used in
35*8ed8353fSOliver Stannard; the callee, so can leave a live value in it.
36*8ed8353fSOliver Stannarddefine void @test_r3_presrved() {
37*8ed8353fSOliver Stannard; CHECK-LABEL: test_r3_presrved:
38*8ed8353fSOliver Stannardentry:
39*8ed8353fSOliver Stannard; CHECK: ASM1: r3
40*8ed8353fSOliver Stannard; DISABLED: mov [[TEMP:r[0-9]+]], r3
41*8ed8353fSOliver Stannard; ENABLED-NOT: r3
42*8ed8353fSOliver Stannard; CHECK: bl      leaf
43*8ed8353fSOliver Stannard; DISABLED: mov r3, [[TEMP]]
44*8ed8353fSOliver Stannard; ENABLED-NOT: r3
45*8ed8353fSOliver Stannard; CHECK: ASM2: r3
46*8ed8353fSOliver Stannard  %a = tail call i32 asm sideeffect "// ASM1: $0", "={r3},0"(i32 undef)
47*8ed8353fSOliver Stannard  tail call void @leaf()
48*8ed8353fSOliver Stannard  %b = tail call i32 asm sideeffect "// ASM2: $0", "={r3},0"(i32 %a)
49*8ed8353fSOliver Stannard  ret void
50*8ed8353fSOliver Stannard}
51*8ed8353fSOliver Stannard
52*8ed8353fSOliver Stannard; Same as above, but r3 is clobbered in the callee, so it is clobbered by the
53*8ed8353fSOliver Stannard; call as normal.
54*8ed8353fSOliver Stannarddefine void @test_r3_clobbered() {
55*8ed8353fSOliver Stannard; CHECK-LABEL: test_r3_clobbered:
56*8ed8353fSOliver Stannardentry:
57*8ed8353fSOliver Stannard; CHECK: ASM1: r3
58*8ed8353fSOliver Stannard; CHECK: mov [[TEMP:r[0-9]+]], r3
59*8ed8353fSOliver Stannard; CHECK: bl      leaf
60*8ed8353fSOliver Stannard; CHECK: mov r3, [[TEMP]]
61*8ed8353fSOliver Stannard; CHECK: ASM2: r3
62*8ed8353fSOliver Stannard  %a = tail call i32 asm sideeffect "// ASM1: $0", "={r3},0"(i32 undef)
63*8ed8353fSOliver Stannard  tail call void @leaf_r3()
64*8ed8353fSOliver Stannard  %b = tail call i32 asm sideeffect "// ASM2: $0", "={r3},0"(i32 %a)
65*8ed8353fSOliver Stannard  ret void
66*8ed8353fSOliver Stannard}
67*8ed8353fSOliver Stannard
68*8ed8353fSOliver Stannard; r4 is a callee-saved register, so IPRA has no effect.
69*8ed8353fSOliver Stannarddefine void @test_r4_preserved() {
70*8ed8353fSOliver Stannard; CHECK-LABEL: test_r4_preserved:
71*8ed8353fSOliver Stannardentry:
72*8ed8353fSOliver Stannard; CHECK: ASM1: r4
73*8ed8353fSOliver Stannard; CHECK-NOT: r4
74*8ed8353fSOliver Stannard; CHECK: bl      leaf
75*8ed8353fSOliver Stannard; CHECK-NOT: r4
76*8ed8353fSOliver Stannard; CHECK: ASM2: r4
77*8ed8353fSOliver Stannard  %a = tail call i32 asm sideeffect "// ASM1: $0", "={r4},0"(i32 undef)
78*8ed8353fSOliver Stannard  tail call void @leaf()
79*8ed8353fSOliver Stannard  %b = tail call i32 asm sideeffect "// ASM2: $0", "={r4},0"(i32 %a)
80*8ed8353fSOliver Stannard  ret void
81*8ed8353fSOliver Stannard}
82*8ed8353fSOliver Stannarddefine void @test_r4_clobbered() {
83*8ed8353fSOliver Stannard; CHECK-LABEL: test_r4_clobbered:
84*8ed8353fSOliver Stannardentry:
85*8ed8353fSOliver Stannard; CHECK: ASM1: r4
86*8ed8353fSOliver Stannard; CHECK-NOT: r4
87*8ed8353fSOliver Stannard; CHECK: bl      leaf_r4
88*8ed8353fSOliver Stannard; CHECK-NOT: r4
89*8ed8353fSOliver Stannard; CHECK: ASM2: r4
90*8ed8353fSOliver Stannard  %a = tail call i32 asm sideeffect "// ASM1: $0", "={r4},0"(i32 undef)
91*8ed8353fSOliver Stannard  tail call void @leaf_r4()
92*8ed8353fSOliver Stannard  %b = tail call i32 asm sideeffect "// ASM2: $0", "={r4},0"(i32 %a)
93*8ed8353fSOliver Stannard  ret void
94*8ed8353fSOliver Stannard}
95*8ed8353fSOliver Stannard
96*8ed8353fSOliver Stannard; r12 is the intra-call scratch register, so we have to assume it is clobbered
97*8ed8353fSOliver Stannard; even if we can see that the callee does not touch it.
98*8ed8353fSOliver Stannarddefine void @test_r12() {
99*8ed8353fSOliver Stannard; CHECK-LABEL: test_r12:
100*8ed8353fSOliver Stannardentry:
101*8ed8353fSOliver Stannard; CHECK: ASM1: r12
102*8ed8353fSOliver Stannard; CHECK: mov [[TEMP:r[0-9]+]], r12
103*8ed8353fSOliver Stannard; CHECK: bl      leaf
104*8ed8353fSOliver Stannard; CHECK: mov r12, [[TEMP]]
105*8ed8353fSOliver Stannard; CHECK: ASM2: r12
106*8ed8353fSOliver Stannard  %a = tail call i32 asm sideeffect "// ASM1: $0", "={r12},0"(i32 undef)
107*8ed8353fSOliver Stannard  tail call void @leaf()
108*8ed8353fSOliver Stannard  %b = tail call i32 asm sideeffect "// ASM2: $0", "={r12},0"(i32 %a)
109*8ed8353fSOliver Stannard  ret void
110*8ed8353fSOliver Stannard}
111*8ed8353fSOliver Stannard
112*8ed8353fSOliver Stannard; s0 and d0 are caller-saved, IPRA allows us to keep them live in the caller if
113*8ed8353fSOliver Stannard; the callee doesn't modify them.
114*8ed8353fSOliver Stannarddefine void @test_s0_preserved() {
115*8ed8353fSOliver Stannard; CHECK-LABEL: test_s0_preserved:
116*8ed8353fSOliver Stannardentry:
117*8ed8353fSOliver Stannard; CHECK: ASM1: s0
118*8ed8353fSOliver Stannard; DISABLED: vmov.f32 [[TEMP:s[0-9]+]], s0
119*8ed8353fSOliver Stannard; ENABLED-NOT: s0
120*8ed8353fSOliver Stannard; CHECK: bl      leaf
121*8ed8353fSOliver Stannard; DISABLED: vmov.f32 s0, [[TEMP]]
122*8ed8353fSOliver Stannard; ENABLED-NOT: s0
123*8ed8353fSOliver Stannard; CHECK: ASM2: s0
124*8ed8353fSOliver Stannard  %a = tail call float asm sideeffect "// ASM1: $0", "={s0},0"(float undef)
125*8ed8353fSOliver Stannard  tail call void @leaf()
126*8ed8353fSOliver Stannard  %b = tail call float asm sideeffect "// ASM2: $0", "={s0},0"(float %a)
127*8ed8353fSOliver Stannard  ret void
128*8ed8353fSOliver Stannard}
129*8ed8353fSOliver Stannard
130*8ed8353fSOliver Stannarddefine void @test_s0_clobbered() {
131*8ed8353fSOliver Stannard; CHECK-LABEL: test_s0_clobbered:
132*8ed8353fSOliver Stannardentry:
133*8ed8353fSOliver Stannard; CHECK: ASM1: s0
134*8ed8353fSOliver Stannard; CHECK: vmov.f32 [[TEMP:s[0-9]+]], s0
135*8ed8353fSOliver Stannard; CHECK: bl      leaf_s0
136*8ed8353fSOliver Stannard; CHECK: vmov.f32 s0, [[TEMP]]
137*8ed8353fSOliver Stannard; CHECK: ASM2: s0
138*8ed8353fSOliver Stannard  %a = tail call float asm sideeffect "// ASM1: $0", "={s0},0"(float undef)
139*8ed8353fSOliver Stannard  tail call void @leaf_s0()
140*8ed8353fSOliver Stannard  %b = tail call float asm sideeffect "// ASM2: $0", "={s0},0"(float %a)
141*8ed8353fSOliver Stannard  ret void
142*8ed8353fSOliver Stannard}
143*8ed8353fSOliver Stannard
144*8ed8353fSOliver Stannarddefine void @test_d0_preserved() {
145*8ed8353fSOliver Stannard; CHECK-LABEL: test_d0_preserved:
146*8ed8353fSOliver Stannardentry:
147*8ed8353fSOliver Stannard; CHECK: ASM1: d0
148*8ed8353fSOliver Stannard; DISABLED: vmov.f64 [[TEMP:d[0-9]+]], d0
149*8ed8353fSOliver Stannard; ENABLED-NOT: d0
150*8ed8353fSOliver Stannard; CHECK: bl      leaf
151*8ed8353fSOliver Stannard; DISABLED: vmov.f64 d0, [[TEMP]]
152*8ed8353fSOliver Stannard; ENABLED-NOT: d0
153*8ed8353fSOliver Stannard; CHECK: ASM2: d0
154*8ed8353fSOliver Stannard  %a = tail call double asm sideeffect "// ASM1: $0", "={d0},0"(double undef)
155*8ed8353fSOliver Stannard  tail call void @leaf()
156*8ed8353fSOliver Stannard  %b = tail call double asm sideeffect "// ASM2: $0", "={d0},0"(double %a)
157*8ed8353fSOliver Stannard  ret void
158*8ed8353fSOliver Stannard}
159*8ed8353fSOliver Stannard
160*8ed8353fSOliver Stannarddefine void @test_d0_clobbered() {
161*8ed8353fSOliver Stannard; CHECK-LABEL: test_d0_clobbered:
162*8ed8353fSOliver Stannardentry:
163*8ed8353fSOliver Stannard; CHECK: ASM1: d0
164*8ed8353fSOliver Stannard; CHECK: vmov.f64 [[TEMP:d[0-9]+]], d0
165*8ed8353fSOliver Stannard; CHECK: bl      leaf_d0
166*8ed8353fSOliver Stannard; CHECK: vmov.f64 d0, [[TEMP]]
167*8ed8353fSOliver Stannard; CHECK: ASM2: d0
168*8ed8353fSOliver Stannard  %a = tail call double asm sideeffect "// ASM1: $0", "={d0},0"(double undef)
169*8ed8353fSOliver Stannard  tail call void @leaf_d0()
170*8ed8353fSOliver Stannard  %b = tail call double asm sideeffect "// ASM2: $0", "={d0},0"(double %a)
171*8ed8353fSOliver Stannard  ret void
172*8ed8353fSOliver Stannard}
173*8ed8353fSOliver Stannard
174*8ed8353fSOliver Stannard; s0 and d0 overlap, so clobbering one in the callee prevents the other from
175*8ed8353fSOliver Stannard; being kept live across the call.
176*8ed8353fSOliver Stannarddefine void @test_s0_clobber_d0() {
177*8ed8353fSOliver Stannard; CHECK-LABEL: test_s0_clobber_d0:
178*8ed8353fSOliver Stannardentry:
179*8ed8353fSOliver Stannard; CHECK: ASM1: s0
180*8ed8353fSOliver Stannard; CHECK: vmov.f32 [[TEMP:s[0-9]+]], s0
181*8ed8353fSOliver Stannard; CHECK: bl      leaf_d0
182*8ed8353fSOliver Stannard; CHECK: vmov.f32 s0, [[TEMP]]
183*8ed8353fSOliver Stannard; CHECK: ASM2: s0
184*8ed8353fSOliver Stannard  %a = tail call float asm sideeffect "// ASM1: $0", "={s0},0"(float undef)
185*8ed8353fSOliver Stannard  tail call void @leaf_d0()
186*8ed8353fSOliver Stannard  %b = tail call float asm sideeffect "// ASM2: $0", "={s0},0"(float %a)
187*8ed8353fSOliver Stannard  ret void
188*8ed8353fSOliver Stannard}
189*8ed8353fSOliver Stannard
190*8ed8353fSOliver Stannarddefine void @test_d0_clobber_s0() {
191*8ed8353fSOliver Stannard; CHECK-LABEL: test_d0_clobber_s0:
192*8ed8353fSOliver Stannardentry:
193*8ed8353fSOliver Stannard; CHECK: ASM1: d0
194*8ed8353fSOliver Stannard; CHECK: vmov.f64 [[TEMP:d[0-9]+]], d0
195*8ed8353fSOliver Stannard; CHECK: bl      leaf_s0
196*8ed8353fSOliver Stannard; CHECK: vmov.f64 d0, [[TEMP]]
197*8ed8353fSOliver Stannard; CHECK: ASM2: d0
198*8ed8353fSOliver Stannard  %a = tail call double asm sideeffect "// ASM1: $0", "={d0},0"(double undef)
199*8ed8353fSOliver Stannard  tail call void @leaf_s0()
200*8ed8353fSOliver Stannard  %b = tail call double asm sideeffect "// ASM2: $0", "={d0},0"(double %a)
201*8ed8353fSOliver Stannard  ret void
202*8ed8353fSOliver Stannard}
203