[TTI] getTypeBasedIntrinsicInstrCost - add basic handling for strided load/store...
[llvm-project.git] / llvm / test / CodeGen / RISCV / inline-asm.ll
blob79266743a1d05170e553e4d3617d72a9a85414b7
1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -mtriple=riscv32 -verify-machineinstrs -no-integrated-as < %s \
3 ; RUN:   | FileCheck -check-prefix=RV32I %s
4 ; RUN: llc -mtriple=riscv64 -verify-machineinstrs -no-integrated-as < %s \
5 ; RUN:   | FileCheck -check-prefix=RV64I %s
7 @gi = external global i32
9 define i32 @constraint_r(i32 %a) nounwind {
10 ; RV32I-LABEL: constraint_r:
11 ; RV32I:       # %bb.0:
12 ; RV32I-NEXT:    lui a1, %hi(gi)
13 ; RV32I-NEXT:    lw a1, %lo(gi)(a1)
14 ; RV32I-NEXT:    #APP
15 ; RV32I-NEXT:    add a0, a0, a1
16 ; RV32I-NEXT:    #NO_APP
17 ; RV32I-NEXT:    ret
19 ; RV64I-LABEL: constraint_r:
20 ; RV64I:       # %bb.0:
21 ; RV64I-NEXT:    lui a1, %hi(gi)
22 ; RV64I-NEXT:    lw a1, %lo(gi)(a1)
23 ; RV64I-NEXT:    #APP
24 ; RV64I-NEXT:    add a0, a0, a1
25 ; RV64I-NEXT:    #NO_APP
26 ; RV64I-NEXT:    ret
27   %1 = load i32, ptr @gi
28   %2 = tail call i32 asm "add $0, $1, $2", "=r,r,r"(i32 %a, i32 %1)
29   ret i32 %2
32 ; Don't allow 'x0' for 'r'. Some instructions have a different behavior when
33 ; x0 is encoded.
34 define i32 @constraint_r_zero(i32 %a) nounwind {
35 ; RV32I-LABEL: constraint_r_zero:
36 ; RV32I:       # %bb.0:
37 ; RV32I-NEXT:    lui a0, %hi(gi)
38 ; RV32I-NEXT:    lw a0, %lo(gi)(a0)
39 ; RV32I-NEXT:    li a1, 0
40 ; RV32I-NEXT:    #APP
41 ; RV32I-NEXT:    add a0, a1, a0
42 ; RV32I-NEXT:    #NO_APP
43 ; RV32I-NEXT:    ret
45 ; RV64I-LABEL: constraint_r_zero:
46 ; RV64I:       # %bb.0:
47 ; RV64I-NEXT:    lui a0, %hi(gi)
48 ; RV64I-NEXT:    lw a0, %lo(gi)(a0)
49 ; RV64I-NEXT:    li a1, 0
50 ; RV64I-NEXT:    #APP
51 ; RV64I-NEXT:    add a0, a1, a0
52 ; RV64I-NEXT:    #NO_APP
53 ; RV64I-NEXT:    ret
54   %1 = load i32, ptr @gi
55   %2 = tail call i32 asm "add $0, $1, $2", "=r,r,r"(i32 0, i32 %1)
56   ret i32 %2
59 define i32 @constraint_cr(i32 %a) nounwind {
60 ; RV32I-LABEL: constraint_cr:
61 ; RV32I:       # %bb.0:
62 ; RV32I-NEXT:    lui a1, %hi(gi)
63 ; RV32I-NEXT:    lw a1, %lo(gi)(a1)
64 ; RV32I-NEXT:    #APP
65 ; RV32I-NEXT:    c.add a0, a0, a1
66 ; RV32I-NEXT:    #NO_APP
67 ; RV32I-NEXT:    ret
69 ; RV64I-LABEL: constraint_cr:
70 ; RV64I:       # %bb.0:
71 ; RV64I-NEXT:    lui a1, %hi(gi)
72 ; RV64I-NEXT:    lw a1, %lo(gi)(a1)
73 ; RV64I-NEXT:    #APP
74 ; RV64I-NEXT:    c.add a0, a0, a1
75 ; RV64I-NEXT:    #NO_APP
76 ; RV64I-NEXT:    ret
77   %1 = load i32, ptr @gi
78   %2 = tail call i32 asm "c.add $0, $1, $2", "=^cr,0,^cr"(i32 %a, i32 %1)
79   ret i32 %2
82 define i32 @constraint_i(i32 %a) nounwind {
83 ; RV32I-LABEL: constraint_i:
84 ; RV32I:       # %bb.0:
85 ; RV32I-NEXT:    #APP
86 ; RV32I-NEXT:    addi a0, a0, 113
87 ; RV32I-NEXT:    #NO_APP
88 ; RV32I-NEXT:    ret
90 ; RV64I-LABEL: constraint_i:
91 ; RV64I:       # %bb.0:
92 ; RV64I-NEXT:    #APP
93 ; RV64I-NEXT:    addi a0, a0, 113
94 ; RV64I-NEXT:    #NO_APP
95 ; RV64I-NEXT:    ret
96   %1 = load i32, ptr @gi
97   %2 = tail call i32 asm "addi $0, $1, $2", "=r,r,i"(i32 %a, i32 113)
98   ret i32 %2
101 define void @constraint_I() nounwind {
102 ; RV32I-LABEL: constraint_I:
103 ; RV32I:       # %bb.0:
104 ; RV32I-NEXT:    #APP
105 ; RV32I-NEXT:    addi a0, a0, 2047
106 ; RV32I-NEXT:    #NO_APP
107 ; RV32I-NEXT:    #APP
108 ; RV32I-NEXT:    addi a0, a0, -2048
109 ; RV32I-NEXT:    #NO_APP
110 ; RV32I-NEXT:    ret
112 ; RV64I-LABEL: constraint_I:
113 ; RV64I:       # %bb.0:
114 ; RV64I-NEXT:    #APP
115 ; RV64I-NEXT:    addi a0, a0, 2047
116 ; RV64I-NEXT:    #NO_APP
117 ; RV64I-NEXT:    #APP
118 ; RV64I-NEXT:    addi a0, a0, -2048
119 ; RV64I-NEXT:    #NO_APP
120 ; RV64I-NEXT:    ret
121   tail call void asm sideeffect "addi a0, a0, $0", "I"(i32 2047)
122   tail call void asm sideeffect "addi a0, a0, $0", "I"(i32 -2048)
123   ret void
126 define void @constraint_J() nounwind {
127 ; RV32I-LABEL: constraint_J:
128 ; RV32I:       # %bb.0:
129 ; RV32I-NEXT:    #APP
130 ; RV32I-NEXT:    addi a0, a0, 0
131 ; RV32I-NEXT:    #NO_APP
132 ; RV32I-NEXT:    ret
134 ; RV64I-LABEL: constraint_J:
135 ; RV64I:       # %bb.0:
136 ; RV64I-NEXT:    #APP
137 ; RV64I-NEXT:    addi a0, a0, 0
138 ; RV64I-NEXT:    #NO_APP
139 ; RV64I-NEXT:    ret
140   tail call void asm sideeffect "addi a0, a0, $0", "J"(i32 0)
141   ret void
144 define void @constraint_K() nounwind {
145 ; RV32I-LABEL: constraint_K:
146 ; RV32I:       # %bb.0:
147 ; RV32I-NEXT:    #APP
148 ; RV32I-NEXT:    csrwi mstatus, 31
149 ; RV32I-NEXT:    #NO_APP
150 ; RV32I-NEXT:    #APP
151 ; RV32I-NEXT:    csrwi mstatus, 0
152 ; RV32I-NEXT:    #NO_APP
153 ; RV32I-NEXT:    ret
155 ; RV64I-LABEL: constraint_K:
156 ; RV64I:       # %bb.0:
157 ; RV64I-NEXT:    #APP
158 ; RV64I-NEXT:    csrwi mstatus, 31
159 ; RV64I-NEXT:    #NO_APP
160 ; RV64I-NEXT:    #APP
161 ; RV64I-NEXT:    csrwi mstatus, 0
162 ; RV64I-NEXT:    #NO_APP
163 ; RV64I-NEXT:    ret
164   tail call void asm sideeffect "csrwi mstatus, $0", "K"(i32 31)
165   tail call void asm sideeffect "csrwi mstatus, $0", "K"(i32 0)
166   ret void
169 define i32 @modifier_z_zero(i32 %a) nounwind {
170 ; RV32I-LABEL: modifier_z_zero:
171 ; RV32I:       # %bb.0:
172 ; RV32I-NEXT:    #APP
173 ; RV32I-NEXT:    add a0, a0, zero
174 ; RV32I-NEXT:    #NO_APP
175 ; RV32I-NEXT:    ret
177 ; RV64I-LABEL: modifier_z_zero:
178 ; RV64I:       # %bb.0:
179 ; RV64I-NEXT:    #APP
180 ; RV64I-NEXT:    add a0, a0, zero
181 ; RV64I-NEXT:    #NO_APP
182 ; RV64I-NEXT:    ret
183   %1 = tail call i32 asm "add $0, $1, ${2:z}", "=r,r,i"(i32 %a, i32 0)
184   ret i32 %1
187 define i32 @modifier_z_nonzero(i32 %a) nounwind {
188 ; RV32I-LABEL: modifier_z_nonzero:
189 ; RV32I:       # %bb.0:
190 ; RV32I-NEXT:    #APP
191 ; RV32I-NEXT:    add a0, a0, 1
192 ; RV32I-NEXT:    #NO_APP
193 ; RV32I-NEXT:    ret
195 ; RV64I-LABEL: modifier_z_nonzero:
196 ; RV64I:       # %bb.0:
197 ; RV64I-NEXT:    #APP
198 ; RV64I-NEXT:    add a0, a0, 1
199 ; RV64I-NEXT:    #NO_APP
200 ; RV64I-NEXT:    ret
201   %1 = tail call i32 asm "add $0, $1, ${2:z}", "=r,r,i"(i32 %a, i32 1)
202   ret i32 %1
205 define i32 @modifier_i_imm(i32 %a) nounwind {
206 ; RV32I-LABEL: modifier_i_imm:
207 ; RV32I:       # %bb.0:
208 ; RV32I-NEXT:    #APP
209 ; RV32I-NEXT:    addi a0, a0, 1
210 ; RV32I-NEXT:    #NO_APP
211 ; RV32I-NEXT:    ret
213 ; RV64I-LABEL: modifier_i_imm:
214 ; RV64I:       # %bb.0:
215 ; RV64I-NEXT:    #APP
216 ; RV64I-NEXT:    addi a0, a0, 1
217 ; RV64I-NEXT:    #NO_APP
218 ; RV64I-NEXT:    ret
219   %1 = tail call i32 asm "add${2:i} $0, $1, $2", "=r,r,ri"(i32 %a, i32 1)
220   ret i32 %1
223 define i32 @modifier_i_reg(i32 %a, i32 %b) nounwind {
224 ; RV32I-LABEL: modifier_i_reg:
225 ; RV32I:       # %bb.0:
226 ; RV32I-NEXT:    #APP
227 ; RV32I-NEXT:    add a0, a0, a1
228 ; RV32I-NEXT:    #NO_APP
229 ; RV32I-NEXT:    ret
231 ; RV64I-LABEL: modifier_i_reg:
232 ; RV64I:       # %bb.0:
233 ; RV64I-NEXT:    #APP
234 ; RV64I-NEXT:    add a0, a0, a1
235 ; RV64I-NEXT:    #NO_APP
236 ; RV64I-NEXT:    ret
237   %1 = tail call i32 asm "add${2:i} $0, $1, $2", "=r,r,ri"(i32 %a, i32 %b)
238   ret i32 %1
241 ;; `.insn 0x4, 0x33 | (${0:N} << 7) | (${1:N} << 15) | (${2:N} << 20)` is the
242 ;; raw encoding of `add`
244 define i32 @modifier_N_reg(i32 %a, i32 %b) nounwind {
245 ; RV32I-LABEL: modifier_N_reg:
246 ; RV32I:       # %bb.0:
247 ; RV32I-NEXT:    #APP
248 ; RV32I-NEXT:    .insn 0x4, 0x33 | (10 << 7) | (10 << 15) | (11 << 20)
249 ; RV32I-NEXT:    #NO_APP
250 ; RV32I-NEXT:    ret
252 ; RV64I-LABEL: modifier_N_reg:
253 ; RV64I:       # %bb.0:
254 ; RV64I-NEXT:    #APP
255 ; RV64I-NEXT:    .insn 0x4, 0x33 | (10 << 7) | (10 << 15) | (11 << 20)
256 ; RV64I-NEXT:    #NO_APP
257 ; RV64I-NEXT:    ret
258   %1 = tail call i32 asm ".insn 0x4, 0x33 | (${0:N} << 7) | (${1:N} << 15) | (${2:N} << 20)", "=r,r,r"(i32 %a, i32 %b)
259   ret i32 %1
262 ;; `.insn 0x2, 0x9422 | (${0:N} << 7) | (${2:N} << 2)` is the raw encoding of
263 ;; `c.add` (note the constraint that the first input should be the same as the
264 ;; output).
266 define i32 @modifier_N_with_cr_reg(i32 %a, i32 %b) nounwind {
267 ; RV32I-LABEL: modifier_N_with_cr_reg:
268 ; RV32I:       # %bb.0:
269 ; RV32I-NEXT:    #APP
270 ; RV32I-NEXT:    .insn 0x2, 0x9422 | (10 << 7) | (11 << 2)
271 ; RV32I-NEXT:    #NO_APP
272 ; RV32I-NEXT:    ret
274 ; RV64I-LABEL: modifier_N_with_cr_reg:
275 ; RV64I:       # %bb.0:
276 ; RV64I-NEXT:    #APP
277 ; RV64I-NEXT:    .insn 0x2, 0x9422 | (10 << 7) | (11 << 2)
278 ; RV64I-NEXT:    #NO_APP
279 ; RV64I-NEXT:    ret
280   %1 = tail call i32 asm ".insn 0x2, 0x9422 | (${0:N} << 7) | (${2:N} << 2)", "=^cr,0,^cr"(i32 %a, i32 %b)
281   ret i32 %1
284 define void @operand_global() nounwind {
285 ; RV32I-LABEL: operand_global:
286 ; RV32I:       # %bb.0:
287 ; RV32I-NEXT:    #APP
288 ; RV32I-NEXT:    .8byte gi
289 ; RV32I-NEXT:    #NO_APP
290 ; RV32I-NEXT:    ret
292 ; RV64I-LABEL: operand_global:
293 ; RV64I:       # %bb.0:
294 ; RV64I-NEXT:    #APP
295 ; RV64I-NEXT:    .8byte gi
296 ; RV64I-NEXT:    #NO_APP
297 ; RV64I-NEXT:    ret
298   tail call void asm sideeffect ".8byte $0", "i"(ptr @gi)
299   ret void
302 define void @operand_block_address() nounwind {
303 ; RV32I-LABEL: operand_block_address:
304 ; RV32I:       # %bb.0:
305 ; RV32I-NEXT:    #APP
306 ; RV32I-NEXT:    j .Ltmp0
307 ; RV32I-NEXT:    #NO_APP
308 ; RV32I-NEXT:  .Ltmp0: # Block address taken
309 ; RV32I-NEXT:  # %bb.1: # %bb
310 ; RV32I-NEXT:    ret
312 ; RV64I-LABEL: operand_block_address:
313 ; RV64I:       # %bb.0:
314 ; RV64I-NEXT:    #APP
315 ; RV64I-NEXT:    j .Ltmp0
316 ; RV64I-NEXT:    #NO_APP
317 ; RV64I-NEXT:  .Ltmp0: # Block address taken
318 ; RV64I-NEXT:  # %bb.1: # %bb
319 ; RV64I-NEXT:    ret
320   call void asm sideeffect "j $0", "i"(ptr blockaddress(@operand_block_address, %bb))
321   br label %bb
323   ret void
326 ; TODO: expand tests for more complex constraints, out of range immediates etc