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
6
7@gi = external global i32
8
9define 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
18;
19; RV64I-LABEL: constraint_r:
20; RV64I:       # %bb.0:
21; RV64I-NEXT:    lui a1, %hi(gi)
22; RV64I-NEXT:    lwu 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, i32* @gi
28  %2 = tail call i32 asm "add $0, $1, $2", "=r,r,r"(i32 %a, i32 %1)
29  ret i32 %2
30}
31
32define i32 @constraint_i(i32 %a) nounwind {
33; RV32I-LABEL: constraint_i:
34; RV32I:       # %bb.0:
35; RV32I-NEXT:    #APP
36; RV32I-NEXT:    addi a0, a0, 113
37; RV32I-NEXT:    #NO_APP
38; RV32I-NEXT:    ret
39;
40; RV64I-LABEL: constraint_i:
41; RV64I:       # %bb.0:
42; RV64I-NEXT:    #APP
43; RV64I-NEXT:    addi a0, a0, 113
44; RV64I-NEXT:    #NO_APP
45; RV64I-NEXT:    ret
46  %1 = load i32, i32* @gi
47  %2 = tail call i32 asm "addi $0, $1, $2", "=r,r,i"(i32 %a, i32 113)
48  ret i32 %2
49}
50
51define void @constraint_m(i32* %a) nounwind {
52; RV32I-LABEL: constraint_m:
53; RV32I:       # %bb.0:
54; RV32I-NEXT:    #APP
55; RV32I-NEXT:    #NO_APP
56; RV32I-NEXT:    ret
57;
58; RV64I-LABEL: constraint_m:
59; RV64I:       # %bb.0:
60; RV64I-NEXT:    #APP
61; RV64I-NEXT:    #NO_APP
62; RV64I-NEXT:    ret
63  call void asm sideeffect "", "=*m"(i32* %a)
64  ret void
65}
66
67define i32 @constraint_m2(i32* %a) nounwind {
68; RV32I-LABEL: constraint_m2:
69; RV32I:       # %bb.0:
70; RV32I-NEXT:    #APP
71; RV32I-NEXT:    lw a0, 0(a0)
72; RV32I-NEXT:    #NO_APP
73; RV32I-NEXT:    ret
74;
75; RV64I-LABEL: constraint_m2:
76; RV64I:       # %bb.0:
77; RV64I-NEXT:    #APP
78; RV64I-NEXT:    lw a0, 0(a0)
79; RV64I-NEXT:    #NO_APP
80; RV64I-NEXT:    ret
81  %1 = tail call i32 asm "lw $0, $1", "=r,*m"(i32* %a)
82  ret i32 %1
83}
84
85define void @constraint_I() nounwind {
86; RV32I-LABEL: constraint_I:
87; RV32I:       # %bb.0:
88; RV32I-NEXT:    #APP
89; RV32I-NEXT:    addi a0, a0, 2047
90; RV32I-NEXT:    #NO_APP
91; RV32I-NEXT:    #APP
92; RV32I-NEXT:    addi a0, a0, -2048
93; RV32I-NEXT:    #NO_APP
94; RV32I-NEXT:    ret
95;
96; RV64I-LABEL: constraint_I:
97; RV64I:       # %bb.0:
98; RV64I-NEXT:    #APP
99; RV64I-NEXT:    addi a0, a0, 2047
100; RV64I-NEXT:    #NO_APP
101; RV64I-NEXT:    #APP
102; RV64I-NEXT:    addi a0, a0, -2048
103; RV64I-NEXT:    #NO_APP
104; RV64I-NEXT:    ret
105  tail call void asm sideeffect "addi a0, a0, $0", "I"(i32 2047)
106  tail call void asm sideeffect "addi a0, a0, $0", "I"(i32 -2048)
107  ret void
108}
109
110define void @constraint_J() nounwind {
111; RV32I-LABEL: constraint_J:
112; RV32I:       # %bb.0:
113; RV32I-NEXT:    #APP
114; RV32I-NEXT:    addi a0, a0, 0
115; RV32I-NEXT:    #NO_APP
116; RV32I-NEXT:    ret
117;
118; RV64I-LABEL: constraint_J:
119; RV64I:       # %bb.0:
120; RV64I-NEXT:    #APP
121; RV64I-NEXT:    addi a0, a0, 0
122; RV64I-NEXT:    #NO_APP
123; RV64I-NEXT:    ret
124  tail call void asm sideeffect "addi a0, a0, $0", "J"(i32 0)
125  ret void
126}
127
128define void @constraint_K() nounwind {
129; RV32I-LABEL: constraint_K:
130; RV32I:       # %bb.0:
131; RV32I-NEXT:    #APP
132; RV32I-NEXT:    csrwi mstatus, 31
133; RV32I-NEXT:    #NO_APP
134; RV32I-NEXT:    #APP
135; RV32I-NEXT:    csrwi mstatus, 0
136; RV32I-NEXT:    #NO_APP
137; RV32I-NEXT:    ret
138;
139; RV64I-LABEL: constraint_K:
140; RV64I:       # %bb.0:
141; RV64I-NEXT:    #APP
142; RV64I-NEXT:    csrwi mstatus, 31
143; RV64I-NEXT:    #NO_APP
144; RV64I-NEXT:    #APP
145; RV64I-NEXT:    csrwi mstatus, 0
146; RV64I-NEXT:    #NO_APP
147; RV64I-NEXT:    ret
148  tail call void asm sideeffect "csrwi mstatus, $0", "K"(i32 31)
149  tail call void asm sideeffect "csrwi mstatus, $0", "K"(i32 0)
150  ret void
151}
152
153define void @constraint_A(i8* %a) nounwind {
154; RV32I-LABEL: constraint_A:
155; RV32I:       # %bb.0:
156; RV32I-NEXT:    #APP
157; RV32I-NEXT:    sb s0, 0(a0)
158; RV32I-NEXT:    #NO_APP
159; RV32I-NEXT:    #APP
160; RV32I-NEXT:    lb s1, 0(a0)
161; RV32I-NEXT:    #NO_APP
162; RV32I-NEXT:    ret
163;
164; RV64I-LABEL: constraint_A:
165; RV64I:       # %bb.0:
166; RV64I-NEXT:    #APP
167; RV64I-NEXT:    sb s0, 0(a0)
168; RV64I-NEXT:    #NO_APP
169; RV64I-NEXT:    #APP
170; RV64I-NEXT:    lb s1, 0(a0)
171; RV64I-NEXT:    #NO_APP
172; RV64I-NEXT:    ret
173  tail call void asm sideeffect "sb s0, $0", "*A"(i8* %a)
174  tail call void asm sideeffect "lb s1, $0", "*A"(i8* %a)
175  ret void
176}
177
178define i32 @modifier_z_zero(i32 %a) nounwind {
179; RV32I-LABEL: modifier_z_zero:
180; RV32I:       # %bb.0:
181; RV32I-NEXT:    #APP
182; RV32I-NEXT:    add a0, a0, zero
183; RV32I-NEXT:    #NO_APP
184; RV32I-NEXT:    ret
185;
186; RV64I-LABEL: modifier_z_zero:
187; RV64I:       # %bb.0:
188; RV64I-NEXT:    #APP
189; RV64I-NEXT:    add a0, a0, zero
190; RV64I-NEXT:    #NO_APP
191; RV64I-NEXT:    ret
192  %1 = tail call i32 asm "add $0, $1, ${2:z}", "=r,r,i"(i32 %a, i32 0)
193  ret i32 %1
194}
195
196define i32 @modifier_z_nonzero(i32 %a) nounwind {
197; RV32I-LABEL: modifier_z_nonzero:
198; RV32I:       # %bb.0:
199; RV32I-NEXT:    #APP
200; RV32I-NEXT:    add a0, a0, 1
201; RV32I-NEXT:    #NO_APP
202; RV32I-NEXT:    ret
203;
204; RV64I-LABEL: modifier_z_nonzero:
205; RV64I:       # %bb.0:
206; RV64I-NEXT:    #APP
207; RV64I-NEXT:    add a0, a0, 1
208; RV64I-NEXT:    #NO_APP
209; RV64I-NEXT:    ret
210  %1 = tail call i32 asm "add $0, $1, ${2:z}", "=r,r,i"(i32 %a, i32 1)
211  ret i32 %1
212}
213
214define i32 @modifier_i_imm(i32 %a) nounwind {
215; RV32I-LABEL: modifier_i_imm:
216; RV32I:       # %bb.0:
217; RV32I-NEXT:    #APP
218; RV32I-NEXT:    addi a0, a0, 1
219; RV32I-NEXT:    #NO_APP
220; RV32I-NEXT:    ret
221;
222; RV64I-LABEL: modifier_i_imm:
223; RV64I:       # %bb.0:
224; RV64I-NEXT:    #APP
225; RV64I-NEXT:    addi a0, a0, 1
226; RV64I-NEXT:    #NO_APP
227; RV64I-NEXT:    ret
228  %1 = tail call i32 asm "add${2:i} $0, $1, $2", "=r,r,ri"(i32 %a, i32 1)
229  ret i32 %1
230}
231
232define i32 @modifier_i_reg(i32 %a, i32 %b) nounwind {
233; RV32I-LABEL: modifier_i_reg:
234; RV32I:       # %bb.0:
235; RV32I-NEXT:    #APP
236; RV32I-NEXT:    add a0, a0, a1
237; RV32I-NEXT:    #NO_APP
238; RV32I-NEXT:    ret
239;
240; RV64I-LABEL: modifier_i_reg:
241; RV64I:       # %bb.0:
242; RV64I-NEXT:    #APP
243; RV64I-NEXT:    add a0, a0, a1
244; RV64I-NEXT:    #NO_APP
245; RV64I-NEXT:    ret
246  %1 = tail call i32 asm "add${2:i} $0, $1, $2", "=r,r,ri"(i32 %a, i32 %b)
247  ret i32 %1
248}
249
250define void @operand_global() nounwind {
251; RV32I-LABEL: operand_global:
252; RV32I:       # %bb.0:
253; RV32I-NEXT:    #APP
254; RV32I-NEXT:    .8byte gi
255; RV32I-NEXT:    #NO_APP
256; RV32I-NEXT:    ret
257;
258; RV64I-LABEL: operand_global:
259; RV64I:       # %bb.0:
260; RV64I-NEXT:    #APP
261; RV64I-NEXT:    .8byte gi
262; RV64I-NEXT:    #NO_APP
263; RV64I-NEXT:    ret
264  tail call void asm sideeffect ".8byte $0", "i"(i32* @gi)
265  ret void
266}
267
268define void @operand_block_address() nounwind {
269; RV32I-LABEL: operand_block_address:
270; RV32I:       # %bb.0:
271; RV32I-NEXT:    #APP
272; RV32I-NEXT:    j .Ltmp0
273; RV32I-NEXT:    #NO_APP
274; RV32I-NEXT:  .Ltmp0: # Block address taken
275; RV32I-NEXT:  # %bb.1: # %bb
276; RV32I-NEXT:    ret
277;
278; RV64I-LABEL: operand_block_address:
279; RV64I:       # %bb.0:
280; RV64I-NEXT:    #APP
281; RV64I-NEXT:    j .Ltmp0
282; RV64I-NEXT:    #NO_APP
283; RV64I-NEXT:  .Ltmp0: # Block address taken
284; RV64I-NEXT:  # %bb.1: # %bb
285; RV64I-NEXT:    ret
286  call void asm sideeffect "j $0", "i"(i8* blockaddress(@operand_block_address, %bb))
287  br label %bb
288bb:
289  ret void
290}
291
292; TODO: expand tests for more complex constraints, out of range immediates etc
293