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