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:
12 ; RV32I-NEXT: lui a1, %hi(gi)
13 ; RV32I-NEXT: lw a1, %lo(gi)(a1)
15 ; RV32I-NEXT: add a0, a0, a1
19 ; RV64I-LABEL: constraint_r:
21 ; RV64I-NEXT: lui a1, %hi(gi)
22 ; RV64I-NEXT: lw a1, %lo(gi)(a1)
24 ; RV64I-NEXT: add a0, a0, a1
27 %1 = load i32, ptr @gi
28 %2 = tail call i32 asm "add $0, $1, $2", "=r,r,r"(i32 %a, i32 %1)
32 ; Don't allow 'x0' for 'r'. Some instructions have a different behavior when
34 define i32 @constraint_r_zero(i32 %a) nounwind {
35 ; RV32I-LABEL: constraint_r_zero:
37 ; RV32I-NEXT: lui a0, %hi(gi)
38 ; RV32I-NEXT: lw a0, %lo(gi)(a0)
39 ; RV32I-NEXT: li a1, 0
41 ; RV32I-NEXT: add a0, a1, a0
45 ; RV64I-LABEL: constraint_r_zero:
47 ; RV64I-NEXT: lui a0, %hi(gi)
48 ; RV64I-NEXT: lw a0, %lo(gi)(a0)
49 ; RV64I-NEXT: li a1, 0
51 ; RV64I-NEXT: add a0, a1, a0
54 %1 = load i32, ptr @gi
55 %2 = tail call i32 asm "add $0, $1, $2", "=r,r,r"(i32 0, i32 %1)
59 define i32 @constraint_cr(i32 %a) nounwind {
60 ; RV32I-LABEL: constraint_cr:
62 ; RV32I-NEXT: lui a1, %hi(gi)
63 ; RV32I-NEXT: lw a1, %lo(gi)(a1)
65 ; RV32I-NEXT: c.add a0, a0, a1
69 ; RV64I-LABEL: constraint_cr:
71 ; RV64I-NEXT: lui a1, %hi(gi)
72 ; RV64I-NEXT: lw a1, %lo(gi)(a1)
74 ; RV64I-NEXT: c.add a0, a0, a1
77 %1 = load i32, ptr @gi
78 %2 = tail call i32 asm "c.add $0, $1, $2", "=^cr,0,^cr"(i32 %a, i32 %1)
82 define i32 @constraint_i(i32 %a) nounwind {
83 ; RV32I-LABEL: constraint_i:
86 ; RV32I-NEXT: addi a0, a0, 113
90 ; RV64I-LABEL: constraint_i:
93 ; RV64I-NEXT: addi a0, a0, 113
96 %1 = load i32, ptr @gi
97 %2 = tail call i32 asm "addi $0, $1, $2", "=r,r,i"(i32 %a, i32 113)
101 define void @constraint_I() nounwind {
102 ; RV32I-LABEL: constraint_I:
105 ; RV32I-NEXT: addi a0, a0, 2047
106 ; RV32I-NEXT: #NO_APP
108 ; RV32I-NEXT: addi a0, a0, -2048
109 ; RV32I-NEXT: #NO_APP
112 ; RV64I-LABEL: constraint_I:
115 ; RV64I-NEXT: addi a0, a0, 2047
116 ; RV64I-NEXT: #NO_APP
118 ; RV64I-NEXT: addi a0, a0, -2048
119 ; RV64I-NEXT: #NO_APP
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)
126 define void @constraint_J() nounwind {
127 ; RV32I-LABEL: constraint_J:
130 ; RV32I-NEXT: addi a0, a0, 0
131 ; RV32I-NEXT: #NO_APP
134 ; RV64I-LABEL: constraint_J:
137 ; RV64I-NEXT: addi a0, a0, 0
138 ; RV64I-NEXT: #NO_APP
140 tail call void asm sideeffect "addi a0, a0, $0", "J"(i32 0)
144 define void @constraint_K() nounwind {
145 ; RV32I-LABEL: constraint_K:
148 ; RV32I-NEXT: csrwi mstatus, 31
149 ; RV32I-NEXT: #NO_APP
151 ; RV32I-NEXT: csrwi mstatus, 0
152 ; RV32I-NEXT: #NO_APP
155 ; RV64I-LABEL: constraint_K:
158 ; RV64I-NEXT: csrwi mstatus, 31
159 ; RV64I-NEXT: #NO_APP
161 ; RV64I-NEXT: csrwi mstatus, 0
162 ; RV64I-NEXT: #NO_APP
164 tail call void asm sideeffect "csrwi mstatus, $0", "K"(i32 31)
165 tail call void asm sideeffect "csrwi mstatus, $0", "K"(i32 0)
169 define i32 @modifier_z_zero(i32 %a) nounwind {
170 ; RV32I-LABEL: modifier_z_zero:
173 ; RV32I-NEXT: add a0, a0, zero
174 ; RV32I-NEXT: #NO_APP
177 ; RV64I-LABEL: modifier_z_zero:
180 ; RV64I-NEXT: add a0, a0, zero
181 ; RV64I-NEXT: #NO_APP
183 %1 = tail call i32 asm "add $0, $1, ${2:z}", "=r,r,i"(i32 %a, i32 0)
187 define i32 @modifier_z_nonzero(i32 %a) nounwind {
188 ; RV32I-LABEL: modifier_z_nonzero:
191 ; RV32I-NEXT: add a0, a0, 1
192 ; RV32I-NEXT: #NO_APP
195 ; RV64I-LABEL: modifier_z_nonzero:
198 ; RV64I-NEXT: add a0, a0, 1
199 ; RV64I-NEXT: #NO_APP
201 %1 = tail call i32 asm "add $0, $1, ${2:z}", "=r,r,i"(i32 %a, i32 1)
205 define i32 @modifier_i_imm(i32 %a) nounwind {
206 ; RV32I-LABEL: modifier_i_imm:
209 ; RV32I-NEXT: addi a0, a0, 1
210 ; RV32I-NEXT: #NO_APP
213 ; RV64I-LABEL: modifier_i_imm:
216 ; RV64I-NEXT: addi a0, a0, 1
217 ; RV64I-NEXT: #NO_APP
219 %1 = tail call i32 asm "add${2:i} $0, $1, $2", "=r,r,ri"(i32 %a, i32 1)
223 define i32 @modifier_i_reg(i32 %a, i32 %b) nounwind {
224 ; RV32I-LABEL: modifier_i_reg:
227 ; RV32I-NEXT: add a0, a0, a1
228 ; RV32I-NEXT: #NO_APP
231 ; RV64I-LABEL: modifier_i_reg:
234 ; RV64I-NEXT: add a0, a0, a1
235 ; RV64I-NEXT: #NO_APP
237 %1 = tail call i32 asm "add${2:i} $0, $1, $2", "=r,r,ri"(i32 %a, i32 %b)
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:
248 ; RV32I-NEXT: .insn 0x4, 0x33 | (10 << 7) | (10 << 15) | (11 << 20)
249 ; RV32I-NEXT: #NO_APP
252 ; RV64I-LABEL: modifier_N_reg:
255 ; RV64I-NEXT: .insn 0x4, 0x33 | (10 << 7) | (10 << 15) | (11 << 20)
256 ; RV64I-NEXT: #NO_APP
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)
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
266 define i32 @modifier_N_with_cr_reg(i32 %a, i32 %b) nounwind {
267 ; RV32I-LABEL: modifier_N_with_cr_reg:
270 ; RV32I-NEXT: .insn 0x2, 0x9422 | (10 << 7) | (11 << 2)
271 ; RV32I-NEXT: #NO_APP
274 ; RV64I-LABEL: modifier_N_with_cr_reg:
277 ; RV64I-NEXT: .insn 0x2, 0x9422 | (10 << 7) | (11 << 2)
278 ; RV64I-NEXT: #NO_APP
280 %1 = tail call i32 asm ".insn 0x2, 0x9422 | (${0:N} << 7) | (${2:N} << 2)", "=^cr,0,^cr"(i32 %a, i32 %b)
284 define void @operand_global() nounwind {
285 ; RV32I-LABEL: operand_global:
288 ; RV32I-NEXT: .8byte gi
289 ; RV32I-NEXT: #NO_APP
292 ; RV64I-LABEL: operand_global:
295 ; RV64I-NEXT: .8byte gi
296 ; RV64I-NEXT: #NO_APP
298 tail call void asm sideeffect ".8byte $0", "i"(ptr @gi)
302 define void @operand_block_address() nounwind {
303 ; RV32I-LABEL: operand_block_address:
306 ; RV32I-NEXT: j .Ltmp0
307 ; RV32I-NEXT: #NO_APP
308 ; RV32I-NEXT: .Ltmp0: # Block address taken
309 ; RV32I-NEXT: # %bb.1: # %bb
312 ; RV64I-LABEL: operand_block_address:
315 ; RV64I-NEXT: j .Ltmp0
316 ; RV64I-NEXT: #NO_APP
317 ; RV64I-NEXT: .Ltmp0: # Block address taken
318 ; RV64I-NEXT: # %bb.1: # %bb
320 call void asm sideeffect "j $0", "i"(ptr blockaddress(@operand_block_address, %bb))
326 ; TODO: expand tests for more complex constraints, out of range immediates etc