1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \
3 ; RUN: | FileCheck %s -check-prefix=RV32I
4 ; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
5 ; RUN: | FileCheck %s -check-prefix=RV64I
7 ; Materializing constants
9 ; TODO: It would be preferable if anyext constant returns were sign rather
10 ; than zero extended. See PR39092. For now, mark returns as explicitly signext
11 ; (this matches what Clang would generate for equivalent C/C++ anyway).
13 define signext i32 @zero() nounwind {
16 ; RV32I-NEXT: mv a0, zero
21 ; RV64I-NEXT: mv a0, zero
26 define signext i32 @pos_small() nounwind {
27 ; RV32I-LABEL: pos_small:
29 ; RV32I-NEXT: addi a0, zero, 2047
32 ; RV64I-LABEL: pos_small:
34 ; RV64I-NEXT: addi a0, zero, 2047
39 define signext i32 @neg_small() nounwind {
40 ; RV32I-LABEL: neg_small:
42 ; RV32I-NEXT: addi a0, zero, -2048
45 ; RV64I-LABEL: neg_small:
47 ; RV64I-NEXT: addi a0, zero, -2048
52 define signext i32 @pos_i32() nounwind {
53 ; RV32I-LABEL: pos_i32:
55 ; RV32I-NEXT: lui a0, 423811
56 ; RV32I-NEXT: addi a0, a0, -1297
59 ; RV64I-LABEL: pos_i32:
61 ; RV64I-NEXT: lui a0, 423811
62 ; RV64I-NEXT: addiw a0, a0, -1297
67 define signext i32 @neg_i32() nounwind {
68 ; RV32I-LABEL: neg_i32:
70 ; RV32I-NEXT: lui a0, 912092
71 ; RV32I-NEXT: addi a0, a0, -273
74 ; RV64I-LABEL: neg_i32:
76 ; RV64I-NEXT: lui a0, 912092
77 ; RV64I-NEXT: addiw a0, a0, -273
82 define signext i32 @pos_i32_hi20_only() nounwind {
83 ; RV32I-LABEL: pos_i32_hi20_only:
85 ; RV32I-NEXT: lui a0, 16
88 ; RV64I-LABEL: pos_i32_hi20_only:
90 ; RV64I-NEXT: lui a0, 16
92 ret i32 65536 ; 0x10000
95 define signext i32 @neg_i32_hi20_only() nounwind {
96 ; RV32I-LABEL: neg_i32_hi20_only:
98 ; RV32I-NEXT: lui a0, 1048560
101 ; RV64I-LABEL: neg_i32_hi20_only:
103 ; RV64I-NEXT: lui a0, 1048560
105 ret i32 -65536 ; -0x10000
108 ; This can be materialized with ADDI+SLLI, improving compressibility.
110 define signext i32 @imm_left_shifted_addi() nounwind {
111 ; RV32I-LABEL: imm_left_shifted_addi:
113 ; RV32I-NEXT: lui a0, 32
114 ; RV32I-NEXT: addi a0, a0, -64
117 ; RV64I-LABEL: imm_left_shifted_addi:
119 ; RV64I-NEXT: lui a0, 32
120 ; RV64I-NEXT: addiw a0, a0, -64
122 ret i32 131008 ; 0x1FFC0
125 ; This can be materialized with ADDI+SRLI, improving compressibility.
127 define signext i32 @imm_right_shifted_addi() nounwind {
128 ; RV32I-LABEL: imm_right_shifted_addi:
130 ; RV32I-NEXT: lui a0, 524288
131 ; RV32I-NEXT: addi a0, a0, -1
134 ; RV64I-LABEL: imm_right_shifted_addi:
136 ; RV64I-NEXT: lui a0, 524288
137 ; RV64I-NEXT: addiw a0, a0, -1
139 ret i32 2147483647 ; 0x7FFFFFFF
142 ; This can be materialized with LUI+SRLI, improving compressibility.
144 define signext i32 @imm_right_shifted_lui() nounwind {
145 ; RV32I-LABEL: imm_right_shifted_lui:
147 ; RV32I-NEXT: lui a0, 56
148 ; RV32I-NEXT: addi a0, a0, 580
151 ; RV64I-LABEL: imm_right_shifted_lui:
153 ; RV64I-NEXT: lui a0, 56
154 ; RV64I-NEXT: addiw a0, a0, 580
156 ret i32 229956 ; 0x38244
159 define i64 @imm64_1() nounwind {
160 ; RV32I-LABEL: imm64_1:
162 ; RV32I-NEXT: lui a0, 524288
163 ; RV32I-NEXT: mv a1, zero
166 ; RV64I-LABEL: imm64_1:
168 ; RV64I-NEXT: addi a0, zero, 1
169 ; RV64I-NEXT: slli a0, a0, 31
171 ret i64 2147483648 ; 0x8000_0000
174 define i64 @imm64_2() nounwind {
175 ; RV32I-LABEL: imm64_2:
177 ; RV32I-NEXT: addi a0, zero, -1
178 ; RV32I-NEXT: mv a1, zero
181 ; RV64I-LABEL: imm64_2:
183 ; RV64I-NEXT: addi a0, zero, -1
184 ; RV64I-NEXT: srli a0, a0, 32
186 ret i64 4294967295 ; 0xFFFF_FFFF
189 define i64 @imm64_3() nounwind {
190 ; RV32I-LABEL: imm64_3:
192 ; RV32I-NEXT: addi a1, zero, 1
193 ; RV32I-NEXT: mv a0, zero
196 ; RV64I-LABEL: imm64_3:
198 ; RV64I-NEXT: addi a0, zero, 1
199 ; RV64I-NEXT: slli a0, a0, 32
201 ret i64 4294967296 ; 0x1_0000_0000
204 define i64 @imm64_4() nounwind {
205 ; RV32I-LABEL: imm64_4:
207 ; RV32I-NEXT: lui a1, 524288
208 ; RV32I-NEXT: mv a0, zero
211 ; RV64I-LABEL: imm64_4:
213 ; RV64I-NEXT: addi a0, zero, -1
214 ; RV64I-NEXT: slli a0, a0, 63
216 ret i64 9223372036854775808 ; 0x8000_0000_0000_0000
219 define i64 @imm64_5() nounwind {
220 ; RV32I-LABEL: imm64_5:
222 ; RV32I-NEXT: lui a1, 524288
223 ; RV32I-NEXT: mv a0, zero
226 ; RV64I-LABEL: imm64_5:
228 ; RV64I-NEXT: addi a0, zero, -1
229 ; RV64I-NEXT: slli a0, a0, 63
231 ret i64 -9223372036854775808 ; 0x8000_0000_0000_0000
234 define i64 @imm64_6() nounwind {
235 ; RV32I-LABEL: imm64_6:
237 ; RV32I-NEXT: lui a0, 74565
238 ; RV32I-NEXT: addi a1, a0, 1656
239 ; RV32I-NEXT: mv a0, zero
242 ; RV64I-LABEL: imm64_6:
244 ; RV64I-NEXT: lui a0, 9321
245 ; RV64I-NEXT: addiw a0, a0, -1329
246 ; RV64I-NEXT: slli a0, a0, 35
248 ret i64 1311768464867721216 ; 0x1234_5678_0000_0000
251 define i64 @imm64_7() nounwind {
252 ; RV32I-LABEL: imm64_7:
254 ; RV32I-NEXT: lui a0, 45056
255 ; RV32I-NEXT: addi a0, a0, 15
256 ; RV32I-NEXT: lui a1, 458752
259 ; RV64I-LABEL: imm64_7:
261 ; RV64I-NEXT: addi a0, zero, 7
262 ; RV64I-NEXT: slli a0, a0, 36
263 ; RV64I-NEXT: addi a0, a0, 11
264 ; RV64I-NEXT: slli a0, a0, 24
265 ; RV64I-NEXT: addi a0, a0, 15
267 ret i64 8070450532432478223 ; 0x7000_0000_0B00_000F
270 ; TODO: it can be preferable to put constants that are expensive to materialise
271 ; into the constant pool, especially for -Os.
272 define i64 @imm64_8() nounwind {
273 ; RV32I-LABEL: imm64_8:
275 ; RV32I-NEXT: lui a0, 633806
276 ; RV32I-NEXT: addi a0, a0, -272
277 ; RV32I-NEXT: lui a1, 74565
278 ; RV32I-NEXT: addi a1, a1, 1656
281 ; RV64I-LABEL: imm64_8:
283 ; RV64I-NEXT: lui a0, 583
284 ; RV64I-NEXT: addiw a0, a0, -1875
285 ; RV64I-NEXT: slli a0, a0, 14
286 ; RV64I-NEXT: addi a0, a0, -947
287 ; RV64I-NEXT: slli a0, a0, 12
288 ; RV64I-NEXT: addi a0, a0, 1511
289 ; RV64I-NEXT: slli a0, a0, 13
290 ; RV64I-NEXT: addi a0, a0, -272
292 ret i64 1311768467463790320 ; 0x1234_5678_9ABC_DEF0
295 define i64 @imm64_9() nounwind {
296 ; RV32I-LABEL: imm64_9:
298 ; RV32I-NEXT: addi a0, zero, -1
299 ; RV32I-NEXT: addi a1, zero, -1
302 ; RV64I-LABEL: imm64_9:
304 ; RV64I-NEXT: addi a0, zero, -1
309 ; Various cases where extraneous ADDIs can be inserted where a (left shifted)
312 define i64 @imm_left_shifted_lui_1() nounwind {
313 ; RV32I-LABEL: imm_left_shifted_lui_1:
315 ; RV32I-NEXT: lui a0, 524290
316 ; RV32I-NEXT: mv a1, zero
319 ; RV64I-LABEL: imm_left_shifted_lui_1:
321 ; RV64I-NEXT: lui a0, 262145
322 ; RV64I-NEXT: slli a0, a0, 1
324 ret i64 2147491840 ; 0x8000_2000
327 define i64 @imm_left_shifted_lui_2() nounwind {
328 ; RV32I-LABEL: imm_left_shifted_lui_2:
330 ; RV32I-NEXT: lui a0, 4
331 ; RV32I-NEXT: addi a1, zero, 1
334 ; RV64I-LABEL: imm_left_shifted_lui_2:
336 ; RV64I-NEXT: lui a0, 262145
337 ; RV64I-NEXT: slli a0, a0, 2
339 ret i64 4294983680 ; 0x1_0000_4000
342 define i64 @imm_left_shifted_lui_3() nounwind {
343 ; RV32I-LABEL: imm_left_shifted_lui_3:
345 ; RV32I-NEXT: lui a0, 1
346 ; RV32I-NEXT: addi a1, a0, 1
347 ; RV32I-NEXT: mv a0, zero
350 ; RV64I-LABEL: imm_left_shifted_lui_3:
352 ; RV64I-NEXT: lui a0, 4097
353 ; RV64I-NEXT: slli a0, a0, 20
355 ret i64 17596481011712 ; 0x1001_0000_0000
358 ; Various cases where extraneous ADDIs can be inserted where a (right shifted)
359 ; LUI suffices, or where multiple ADDIs can be used instead of a single LUI.
361 define i64 @imm_right_shifted_lui_1() nounwind {
362 ; RV32I-LABEL: imm_right_shifted_lui_1:
364 ; RV32I-NEXT: lui a0, 1048575
365 ; RV32I-NEXT: addi a0, a0, 1
366 ; RV32I-NEXT: lui a1, 16
367 ; RV32I-NEXT: addi a1, a1, -1
370 ; RV64I-LABEL: imm_right_shifted_lui_1:
372 ; RV64I-NEXT: lui a0, 983056
373 ; RV64I-NEXT: srli a0, a0, 16
375 ret i64 281474976706561 ; 0xFFFF_FFFF_F001
378 define i64 @imm_right_shifted_lui_2() nounwind {
379 ; RV32I-LABEL: imm_right_shifted_lui_2:
381 ; RV32I-NEXT: lui a0, 1048575
382 ; RV32I-NEXT: addi a0, a0, 1
383 ; RV32I-NEXT: addi a1, zero, 255
386 ; RV64I-LABEL: imm_right_shifted_lui_2:
388 ; RV64I-NEXT: lui a0, 1044481
389 ; RV64I-NEXT: slli a0, a0, 12
390 ; RV64I-NEXT: srli a0, a0, 24
392 ret i64 1099511623681 ; 0xFF_FFFF_F001
395 ; We can materialize the upper bits with a single (shifted) LUI, but that option
396 ; can be missed due to the lower bits, which aren't just 1s or just 0s.
398 define i64 @imm_decoupled_lui_addi() nounwind {
399 ; RV32I-LABEL: imm_decoupled_lui_addi:
401 ; RV32I-NEXT: addi a0, zero, -3
402 ; RV32I-NEXT: lui a1, 1
405 ; RV64I-LABEL: imm_decoupled_lui_addi:
407 ; RV64I-NEXT: lui a0, 4097
408 ; RV64I-NEXT: slli a0, a0, 20
409 ; RV64I-NEXT: addi a0, a0, -3
411 ret i64 17596481011709 ; 0x1000_FFFF_FFFD
414 ; This constant can be materialized for RV64 with LUI+SRLI+XORI.
416 define i64 @imm_end_xori_1() nounwind {
417 ; RV32I-LABEL: imm_end_xori_1:
419 ; RV32I-NEXT: lui a0, 8192
420 ; RV32I-NEXT: addi a0, a0, -1
421 ; RV32I-NEXT: lui a1, 917504
424 ; RV64I-LABEL: imm_end_xori_1:
426 ; RV64I-NEXT: addi a0, zero, -1
427 ; RV64I-NEXT: slli a0, a0, 36
428 ; RV64I-NEXT: addi a0, a0, 1
429 ; RV64I-NEXT: slli a0, a0, 25
430 ; RV64I-NEXT: addi a0, a0, -1
432 ret i64 -2305843009180139521 ; 0xE000_0000_01FF_FFFF
435 ; This constant can be materialized for RV64 with ADDI+SLLI+ADDI+ADDI.
437 define i64 @imm_end_2addi_1() nounwind {
438 ; RV32I-LABEL: imm_end_2addi_1:
440 ; RV32I-NEXT: lui a0, 1048575
441 ; RV32I-NEXT: addi a0, a0, 2047
442 ; RV32I-NEXT: lui a1, 1048512
443 ; RV32I-NEXT: addi a1, a1, 127
446 ; RV64I-LABEL: imm_end_2addi_1:
448 ; RV64I-NEXT: addi a0, zero, -2047
449 ; RV64I-NEXT: slli a0, a0, 27
450 ; RV64I-NEXT: addi a0, a0, -1
451 ; RV64I-NEXT: slli a0, a0, 12
452 ; RV64I-NEXT: addi a0, a0, 2047
454 ret i64 -1125350151030785 ; 0xFFFC_007F_FFFF_F7FF
457 ; This constant can be more efficiently materialized for RV64 if we use two
458 ; registers instead of one.
460 define i64 @imm_2reg_1() nounwind {
461 ; RV32I-LABEL: imm_2reg_1:
463 ; RV32I-NEXT: lui a0, 74565
464 ; RV32I-NEXT: addi a0, a0, 1656
465 ; RV32I-NEXT: lui a1, 983040
468 ; RV64I-LABEL: imm_2reg_1:
470 ; RV64I-NEXT: addi a0, zero, -1
471 ; RV64I-NEXT: slli a0, a0, 35
472 ; RV64I-NEXT: addi a0, a0, 9
473 ; RV64I-NEXT: slli a0, a0, 13
474 ; RV64I-NEXT: addi a0, a0, 837
475 ; RV64I-NEXT: slli a0, a0, 12
476 ; RV64I-NEXT: addi a0, a0, 1656
478 ret i64 -1152921504301427080 ; 0xF000_0000_1234_5678
481 ; FIXME: This should use a single ADDI for the immediate.
482 define void @imm_store_i16_neg1(i16* %p) nounwind {
483 ; RV32I-LABEL: imm_store_i16_neg1:
485 ; RV32I-NEXT: addi a1, zero, -1
486 ; RV32I-NEXT: sh a1, 0(a0)
489 ; RV64I-LABEL: imm_store_i16_neg1:
491 ; RV64I-NEXT: addi a1, zero, -1
492 ; RV64I-NEXT: sh a1, 0(a0)
494 store i16 -1, i16* %p
498 ; FIXME: This should use a single ADDI for the immediate.
499 define void @imm_store_i32_neg1(i32* %p) nounwind {
500 ; RV32I-LABEL: imm_store_i32_neg1:
502 ; RV32I-NEXT: addi a1, zero, -1
503 ; RV32I-NEXT: sw a1, 0(a0)
506 ; RV64I-LABEL: imm_store_i32_neg1:
508 ; RV64I-NEXT: addi a1, zero, -1
509 ; RV64I-NEXT: sw a1, 0(a0)
511 store i32 -1, i32* %p