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_i(i32 %a) nounwind {
60 ; RV32I-LABEL: constraint_i:
63 ; RV32I-NEXT: addi a0, a0, 113
67 ; RV64I-LABEL: constraint_i:
70 ; RV64I-NEXT: addi a0, a0, 113
73 %1 = load i32, ptr @gi
74 %2 = tail call i32 asm "addi $0, $1, $2", "=r,r,i"(i32 %a, i32 113)
78 define void @constraint_I() nounwind {
79 ; RV32I-LABEL: constraint_I:
82 ; RV32I-NEXT: addi a0, a0, 2047
85 ; RV32I-NEXT: addi a0, a0, -2048
89 ; RV64I-LABEL: constraint_I:
92 ; RV64I-NEXT: addi a0, a0, 2047
95 ; RV64I-NEXT: addi a0, a0, -2048
98 tail call void asm sideeffect "addi a0, a0, $0", "I"(i32 2047)
99 tail call void asm sideeffect "addi a0, a0, $0", "I"(i32 -2048)
103 define void @constraint_J() nounwind {
104 ; RV32I-LABEL: constraint_J:
107 ; RV32I-NEXT: addi a0, a0, 0
108 ; RV32I-NEXT: #NO_APP
111 ; RV64I-LABEL: constraint_J:
114 ; RV64I-NEXT: addi a0, a0, 0
115 ; RV64I-NEXT: #NO_APP
117 tail call void asm sideeffect "addi a0, a0, $0", "J"(i32 0)
121 define void @constraint_K() nounwind {
122 ; RV32I-LABEL: constraint_K:
125 ; RV32I-NEXT: csrwi mstatus, 31
126 ; RV32I-NEXT: #NO_APP
128 ; RV32I-NEXT: csrwi mstatus, 0
129 ; RV32I-NEXT: #NO_APP
132 ; RV64I-LABEL: constraint_K:
135 ; RV64I-NEXT: csrwi mstatus, 31
136 ; RV64I-NEXT: #NO_APP
138 ; RV64I-NEXT: csrwi mstatus, 0
139 ; RV64I-NEXT: #NO_APP
141 tail call void asm sideeffect "csrwi mstatus, $0", "K"(i32 31)
142 tail call void asm sideeffect "csrwi mstatus, $0", "K"(i32 0)
146 define i32 @modifier_z_zero(i32 %a) nounwind {
147 ; RV32I-LABEL: modifier_z_zero:
150 ; RV32I-NEXT: add a0, a0, zero
151 ; RV32I-NEXT: #NO_APP
154 ; RV64I-LABEL: modifier_z_zero:
157 ; RV64I-NEXT: add a0, a0, zero
158 ; RV64I-NEXT: #NO_APP
160 %1 = tail call i32 asm "add $0, $1, ${2:z}", "=r,r,i"(i32 %a, i32 0)
164 define i32 @modifier_z_nonzero(i32 %a) nounwind {
165 ; RV32I-LABEL: modifier_z_nonzero:
168 ; RV32I-NEXT: add a0, a0, 1
169 ; RV32I-NEXT: #NO_APP
172 ; RV64I-LABEL: modifier_z_nonzero:
175 ; RV64I-NEXT: add a0, a0, 1
176 ; RV64I-NEXT: #NO_APP
178 %1 = tail call i32 asm "add $0, $1, ${2:z}", "=r,r,i"(i32 %a, i32 1)
182 define i32 @modifier_i_imm(i32 %a) nounwind {
183 ; RV32I-LABEL: modifier_i_imm:
186 ; RV32I-NEXT: addi a0, a0, 1
187 ; RV32I-NEXT: #NO_APP
190 ; RV64I-LABEL: modifier_i_imm:
193 ; RV64I-NEXT: addi a0, a0, 1
194 ; RV64I-NEXT: #NO_APP
196 %1 = tail call i32 asm "add${2:i} $0, $1, $2", "=r,r,ri"(i32 %a, i32 1)
200 define i32 @modifier_i_reg(i32 %a, i32 %b) nounwind {
201 ; RV32I-LABEL: modifier_i_reg:
204 ; RV32I-NEXT: add a0, a0, a1
205 ; RV32I-NEXT: #NO_APP
208 ; RV64I-LABEL: modifier_i_reg:
211 ; RV64I-NEXT: add a0, a0, a1
212 ; RV64I-NEXT: #NO_APP
214 %1 = tail call i32 asm "add${2:i} $0, $1, $2", "=r,r,ri"(i32 %a, i32 %b)
218 define void @operand_global() nounwind {
219 ; RV32I-LABEL: operand_global:
222 ; RV32I-NEXT: .8byte gi
223 ; RV32I-NEXT: #NO_APP
226 ; RV64I-LABEL: operand_global:
229 ; RV64I-NEXT: .8byte gi
230 ; RV64I-NEXT: #NO_APP
232 tail call void asm sideeffect ".8byte $0", "i"(ptr @gi)
236 define void @operand_block_address() nounwind {
237 ; RV32I-LABEL: operand_block_address:
240 ; RV32I-NEXT: j .Ltmp0
241 ; RV32I-NEXT: #NO_APP
242 ; RV32I-NEXT: .Ltmp0: # Block address taken
243 ; RV32I-NEXT: # %bb.1: # %bb
246 ; RV64I-LABEL: operand_block_address:
249 ; RV64I-NEXT: j .Ltmp0
250 ; RV64I-NEXT: #NO_APP
251 ; RV64I-NEXT: .Ltmp0: # Block address taken
252 ; RV64I-NEXT: # %bb.1: # %bb
254 call void asm sideeffect "j $0", "i"(ptr blockaddress(@operand_block_address, %bb))
260 ; TODO: expand tests for more complex constraints, out of range immediates etc