xref: /llvm-project/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-inline-asm.ll (revision 72a60e770cee713a47876483798747cb7db58da6)
1; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
2; RUN: llc -mtriple=aarch64-darwin-ios13 -O0 -global-isel -stop-after=irtranslator -verify-machineinstrs -o - %s | FileCheck %s
3
4define void @asm_simple_memory_clobber() {
5  ; CHECK-LABEL: name: asm_simple_memory_clobber
6  ; CHECK: bb.1 (%ir-block.0):
7  ; CHECK-NEXT:   INLINEASM &"", 25 /* sideeffect mayload maystore attdialect */, !0
8  ; CHECK-NEXT:   INLINEASM &"", 1 /* sideeffect attdialect */, !0
9  ; CHECK-NEXT:   RET_ReallyLR
10  call void asm sideeffect "", "~{memory}"(), !srcloc !0
11  call void asm sideeffect "", ""(), !srcloc !0
12  ret void
13}
14
15!0 = !{i32 70}
16
17define void @asm_simple_register_clobber() {
18  ; CHECK-LABEL: name: asm_simple_register_clobber
19  ; CHECK: bb.1 (%ir-block.0):
20  ; CHECK-NEXT:   INLINEASM &"mov x0, 7", 1 /* sideeffect attdialect */, 12 /* clobber */, implicit-def early-clobber $x0, !0
21  ; CHECK-NEXT:   RET_ReallyLR
22  call void asm sideeffect "mov x0, 7", "~{x0}"(), !srcloc !0
23  ret void
24}
25
26define i64 @asm_register_early_clobber() {
27  ; CHECK-LABEL: name: asm_register_early_clobber
28  ; CHECK: bb.1 (%ir-block.0):
29  ; CHECK-NEXT:   INLINEASM &"mov $0, 7; mov $1, 7", 1 /* sideeffect attdialect */, {{[0-9]+}} /* regdef-ec:GPR64common */, def early-clobber %0, {{[0-9]+}} /* regdef-ec:GPR64common */, def early-clobber %1, !0
30  ; CHECK-NEXT:   [[COPY:%[0-9]+]]:_(s64) = COPY %0
31  ; CHECK-NEXT:   [[COPY1:%[0-9]+]]:_(s64) = COPY %1
32  ; CHECK-NEXT:   [[ADD:%[0-9]+]]:_(s64) = G_ADD [[COPY]], [[COPY1]]
33  ; CHECK-NEXT:   $x0 = COPY [[ADD]](s64)
34  ; CHECK-NEXT:   RET_ReallyLR implicit $x0
35  call { i64, i64 } asm sideeffect "mov $0, 7; mov $1, 7", "=&r,=&r"(), !srcloc !0
36  %asmresult = extractvalue { i64, i64 } %1, 0
37  %asmresult1 = extractvalue { i64, i64 } %1, 1
38  %add = add i64 %asmresult, %asmresult1
39  ret i64 %add
40}
41
42define i32 @test_specific_register_output() nounwind ssp {
43  ; CHECK-LABEL: name: test_specific_register_output
44  ; CHECK: bb.1.entry:
45  ; CHECK-NEXT:   INLINEASM &"mov ${0:w}, 7", 0 /* attdialect */, 10 /* regdef */, implicit-def $w0
46  ; CHECK-NEXT:   [[COPY:%[0-9]+]]:_(s32) = COPY $w0
47  ; CHECK-NEXT:   $w0 = COPY [[COPY]](s32)
48  ; CHECK-NEXT:   RET_ReallyLR implicit $w0
49entry:
50  %0 = tail call i32 asm "mov ${0:w}, 7", "={w0}"() nounwind
51  ret i32 %0
52}
53
54define i32 @test_single_register_output() nounwind ssp {
55  ; CHECK-LABEL: name: test_single_register_output
56  ; CHECK: bb.1.entry:
57  ; CHECK-NEXT:   INLINEASM &"mov ${0:w}, 7", 0 /* attdialect */, {{[0-9]+}} /* regdef:GPR32common */, def %0
58  ; CHECK-NEXT:   [[COPY:%[0-9]+]]:_(s32) = COPY %0
59  ; CHECK-NEXT:   $w0 = COPY [[COPY]](s32)
60  ; CHECK-NEXT:   RET_ReallyLR implicit $w0
61entry:
62  %0 = tail call i32 asm "mov ${0:w}, 7", "=r"() nounwind
63  ret i32 %0
64}
65
66define i64 @test_single_register_output_s64() nounwind ssp {
67  ; CHECK-LABEL: name: test_single_register_output_s64
68  ; CHECK: bb.1.entry:
69  ; CHECK-NEXT:   INLINEASM &"mov $0, 7", 0 /* attdialect */, {{[0-9]+}} /* regdef:GPR64common */, def %0
70  ; CHECK-NEXT:   [[COPY:%[0-9]+]]:_(s64) = COPY %0
71  ; CHECK-NEXT:   $x0 = COPY [[COPY]](s64)
72  ; CHECK-NEXT:   RET_ReallyLR implicit $x0
73entry:
74  %0 = tail call i64 asm "mov $0, 7", "=r"() nounwind
75  ret i64 %0
76}
77
78; Check support for returning several floats
79define float @test_multiple_register_outputs_same() #0 {
80  ; CHECK-LABEL: name: test_multiple_register_outputs_same
81  ; CHECK: bb.1 (%ir-block.0):
82  ; CHECK-NEXT:   INLINEASM &"mov $0, #0; mov $1, #0", 0 /* attdialect */, {{[0-9]+}} /* regdef:GPR32common */, def %0, {{[0-9]+}} /* regdef:GPR32common */, def %1
83  ; CHECK-NEXT:   [[COPY:%[0-9]+]]:_(s32) = COPY %0
84  ; CHECK-NEXT:   [[COPY1:%[0-9]+]]:_(s32) = COPY %1
85  ; CHECK-NEXT:   [[FADD:%[0-9]+]]:_(s32) = G_FADD [[COPY]], [[COPY1]]
86  ; CHECK-NEXT:   $s0 = COPY [[FADD]](s32)
87  ; CHECK-NEXT:   RET_ReallyLR implicit $s0
88  %1 = call { float, float } asm "mov $0, #0; mov $1, #0", "=r,=r"()
89  %asmresult = extractvalue { float, float } %1, 0
90  %asmresult1 = extractvalue { float, float } %1, 1
91  %add = fadd float %asmresult, %asmresult1
92  ret float %add
93}
94
95; Check support for returning several floats
96define double @test_multiple_register_outputs_mixed() #0 {
97  ; CHECK-LABEL: name: test_multiple_register_outputs_mixed
98  ; CHECK: bb.1 (%ir-block.0):
99  ; CHECK-NEXT:   INLINEASM &"mov $0, #0; mov $1, #0", 0 /* attdialect */, {{[0-9]+}} /* regdef:GPR32common */, def %0, {{[0-9]+}} /* regdef:FPR64 */, def %1
100  ; CHECK-NEXT:   [[COPY:%[0-9]+]]:_(s32) = COPY %0
101  ; CHECK-NEXT:   [[COPY1:%[0-9]+]]:_(s64) = COPY %1
102  ; CHECK-NEXT:   $d0 = COPY [[COPY1]](s64)
103  ; CHECK-NEXT:   RET_ReallyLR implicit $d0
104  %1 = call { float, double } asm "mov $0, #0; mov $1, #0", "=r,=w"()
105  %asmresult = extractvalue { float, double } %1, 1
106  ret double %asmresult
107}
108
109define i32 @test_specific_register_output_trunc() nounwind ssp {
110  ; CHECK-LABEL: name: test_specific_register_output_trunc
111  ; CHECK: bb.1.entry:
112  ; CHECK-NEXT:   INLINEASM &"mov ${0:w}, 7", 0 /* attdialect */, 10 /* regdef */, implicit-def $x0
113  ; CHECK-NEXT:   [[COPY:%[0-9]+]]:_(s64) = COPY $x0
114  ; CHECK-NEXT:   [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64)
115  ; CHECK-NEXT:   $w0 = COPY [[TRUNC]](s32)
116  ; CHECK-NEXT:   RET_ReallyLR implicit $w0
117entry:
118  %0 = tail call i32 asm "mov ${0:w}, 7", "={x0}"() nounwind
119  ret i32 %0
120}
121
122define zeroext i8 @test_register_output_trunc(ptr %src) nounwind {
123  ; CHECK-LABEL: name: test_register_output_trunc
124  ; CHECK: bb.1.entry:
125  ; CHECK-NEXT:   liveins: $x0
126  ; CHECK-NEXT: {{  $}}
127  ; CHECK-NEXT:   [[COPY:%[0-9]+]]:_(p0) = COPY $x0
128  ; CHECK-NEXT:   INLINEASM &"mov ${0:w}, 32", 0 /* attdialect */, {{[0-9]+}} /* regdef:GPR32common */, def %1
129  ; CHECK-NEXT:   [[COPY1:%[0-9]+]]:_(s32) = COPY %1
130  ; CHECK-NEXT:   [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY1]](s32)
131  ; CHECK-NEXT:   [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[TRUNC]](s8)
132  ; CHECK-NEXT:   $w0 = COPY [[ZEXT]](s32)
133  ; CHECK-NEXT:   RET_ReallyLR implicit $w0
134entry:
135  %0 = tail call i8 asm "mov ${0:w}, 32", "=r"() nounwind
136  ret i8 %0
137}
138
139define float @test_vector_output() nounwind {
140  ; CHECK-LABEL: name: test_vector_output
141  ; CHECK: bb.1 (%ir-block.0):
142  ; CHECK-NEXT:   [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
143  ; CHECK-NEXT:   INLINEASM &"fmov ${0}.2s, #1.0", 1 /* sideeffect attdialect */, 10 /* regdef */, implicit-def $d14
144  ; CHECK-NEXT:   [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $d14
145  ; CHECK-NEXT:   [[EVEC:%[0-9]+]]:_(s32) = G_EXTRACT_VECTOR_ELT [[COPY]](<2 x s32>), [[C]](s64)
146  ; CHECK-NEXT:   $s0 = COPY [[EVEC]](s32)
147  ; CHECK-NEXT:   RET_ReallyLR implicit $s0
148  %1 = tail call <2 x float> asm sideeffect "fmov ${0}.2s, #1.0", "={v14}"() nounwind
149  %2 = extractelement <2 x float> %1, i32 0
150  ret float %2
151}
152
153define void @test_input_register_imm() {
154  ; CHECK-LABEL: name: test_input_register_imm
155  ; CHECK: bb.1 (%ir-block.0):
156  ; CHECK-NEXT:   [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 42
157  ; CHECK-NEXT:   [[COPY:%[0-9]+]]:gpr64common = COPY [[C]](s64)
158  ; CHECK-NEXT:   INLINEASM &"mov x0, $0", 1 /* sideeffect attdialect */, {{[0-9]+}} /* reguse:GPR64common */, [[COPY]]
159  ; CHECK-NEXT:   RET_ReallyLR
160  call void asm sideeffect "mov x0, $0", "r"(i64 42)
161  ret void
162}
163
164; Make sure that boolean immediates are properly (zero) extended.
165define i32 @test_boolean_imm_ext() {
166  ; CHECK-LABEL: name: test_boolean_imm_ext
167  ; CHECK: bb.1.entry:
168  ; CHECK-NEXT:   [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
169  ; CHECK-NEXT:   INLINEASM &"#TEST 42 + ${0:c} - .\0A\09", 9 /* sideeffect mayload attdialect */, 13 /* imm */, 1
170  ; CHECK-NEXT:   $w0 = COPY [[C]](s32)
171  ; CHECK-NEXT:   RET_ReallyLR implicit $w0
172entry:
173  tail call void asm sideeffect "#TEST 42 + ${0:c} - .\0A\09", "i"(i1 true)
174  ret i32 1
175}
176
177define void @test_input_imm() {
178  ; CHECK-LABEL: name: test_input_imm
179  ; CHECK: bb.1 (%ir-block.0):
180  ; CHECK-NEXT:   INLINEASM &"mov x0, $0", 9 /* sideeffect mayload attdialect */, 13 /* imm */, 42
181  ; CHECK-NEXT:   RET_ReallyLR
182  call void asm sideeffect "mov x0, $0", "i"(i64 42)
183  ret void
184}
185
186define zeroext i8 @test_input_register(ptr %src) nounwind {
187  ; CHECK-LABEL: name: test_input_register
188  ; CHECK: bb.1.entry:
189  ; CHECK-NEXT:   liveins: $x0
190  ; CHECK-NEXT: {{  $}}
191  ; CHECK-NEXT:   [[COPY:%[0-9]+]]:_(p0) = COPY $x0
192  ; CHECK-NEXT:   [[COPY1:%[0-9]+]]:gpr64common = COPY [[COPY]](p0)
193  ; CHECK-NEXT:   INLINEASM &"ldtrb ${0:w}, [$1]", 0 /* attdialect */, {{[0-9]+}} /* regdef:GPR32common */, def %1, {{[0-9]+}} /* reguse:GPR64common */, [[COPY1]]
194  ; CHECK-NEXT:   [[COPY2:%[0-9]+]]:_(s32) = COPY %1
195  ; CHECK-NEXT:   [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY2]](s32)
196  ; CHECK-NEXT:   [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[TRUNC]](s8)
197  ; CHECK-NEXT:   $w0 = COPY [[ZEXT]](s32)
198  ; CHECK-NEXT:   RET_ReallyLR implicit $w0
199entry:
200  %0 = tail call i8 asm "ldtrb ${0:w}, [$1]", "=r,r"(ptr %src) nounwind
201  ret i8 %0
202}
203
204define i32 @test_memory_constraint(ptr %a) nounwind {
205  ; CHECK-LABEL: name: test_memory_constraint
206  ; CHECK: bb.1 (%ir-block.0):
207  ; CHECK-NEXT:   liveins: $x0
208  ; CHECK-NEXT: {{  $}}
209  ; CHECK-NEXT:   [[COPY:%[0-9]+]]:_(p0) = COPY $x0
210  ; CHECK-NEXT:   INLINEASM &"ldr $0, $1", 8 /* mayload attdialect */, {{[0-9]+}} /* regdef:GPR32common */, def %1, 262158 /* mem:m */, [[COPY]](p0)
211  ; CHECK-NEXT:   [[COPY1:%[0-9]+]]:_(s32) = COPY %1
212  ; CHECK-NEXT:   $w0 = COPY [[COPY1]](s32)
213  ; CHECK-NEXT:   RET_ReallyLR implicit $w0
214  %1 = tail call i32 asm "ldr $0, $1", "=r,*m"(ptr elementtype(i32) %a)
215  ret i32 %1
216}
217
218define i16 @test_anyext_input() {
219  ; CHECK-LABEL: name: test_anyext_input
220  ; CHECK: bb.1 (%ir-block.0):
221  ; CHECK-NEXT:   [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 1
222  ; CHECK-NEXT:   [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[C]](s16)
223  ; CHECK-NEXT:   [[COPY:%[0-9]+]]:gpr32common = COPY [[ANYEXT]](s32)
224  ; CHECK-NEXT:   INLINEASM &"", 1 /* sideeffect attdialect */, {{[0-9]+}} /* regdef:GPR32common */, def %0, {{[0-9]+}} /* reguse:GPR32common */, [[COPY]]
225  ; CHECK-NEXT:   [[COPY1:%[0-9]+]]:_(s32) = COPY %0
226  ; CHECK-NEXT:   [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32)
227  ; CHECK-NEXT:   [[ANYEXT1:%[0-9]+]]:_(s32) = G_ANYEXT [[TRUNC]](s16)
228  ; CHECK-NEXT:   $w0 = COPY [[ANYEXT1]](s32)
229  ; CHECK-NEXT:   RET_ReallyLR implicit $w0
230  %1 = call i16 asm sideeffect "", "=r,r"(i16 1)
231  ret i16 %1
232}
233
234define i16 @test_anyext_input_with_matching_constraint() {
235  ; CHECK-LABEL: name: test_anyext_input_with_matching_constraint
236  ; CHECK: bb.1 (%ir-block.0):
237  ; CHECK-NEXT:   [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 1
238  ; CHECK-NEXT:   [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[C]](s16)
239  ; CHECK-NEXT:   [[COPY:%[0-9]+]]:gpr32common = COPY [[ANYEXT]](s32)
240  ; CHECK-NEXT:   INLINEASM &"", 1 /* sideeffect attdialect */, {{[0-9]+}} /* regdef:GPR32common */, def %0, 2147483657 /* reguse tiedto:$0 */, [[COPY]](tied-def 3)
241  ; CHECK-NEXT:   [[COPY1:%[0-9]+]]:_(s32) = COPY %0
242  ; CHECK-NEXT:   [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32)
243  ; CHECK-NEXT:   [[ANYEXT1:%[0-9]+]]:_(s32) = G_ANYEXT [[TRUNC]](s16)
244  ; CHECK-NEXT:   $w0 = COPY [[ANYEXT1]](s32)
245  ; CHECK-NEXT:   RET_ReallyLR implicit $w0
246  %1 = call i16 asm sideeffect "", "=r,0"(i16 1)
247  ret i16 %1
248}
249
250define i64 @test_input_with_matching_constraint_to_physical_register() {
251  ; CHECK-LABEL: name: test_input_with_matching_constraint_to_physical_register
252  ; CHECK: bb.1 (%ir-block.0):
253  ; CHECK-NEXT:   [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
254  ; CHECK-NEXT:   INLINEASM &"", 0 /* attdialect */, 10 /* regdef */, implicit-def $x2, 2147483657 /* reguse tiedto:$0 */, [[C]](tied-def 3)(s64)
255  ; CHECK-NEXT:   [[COPY:%[0-9]+]]:_(s64) = COPY $x2
256  ; CHECK-NEXT:   $x0 = COPY [[COPY]](s64)
257  ; CHECK-NEXT:   RET_ReallyLR implicit $x0
258  %1 = tail call i64 asm "", "={x2},0"(i64 0)
259  ret i64 %1
260}
261