llvm-project/llvm/test/CodeGen/RISCV/xqcibm-insert.ll
Sudharsan Veeravalli c00b04a7e0
[RISCV] Generate QC_INSB/QC_INSBI instructions from OR of AND Imm (#154023)
Generate QC_INSB/QC_INSBI from `or (and X, MaskImm), OrImm` iff the
value being inserted only sets known zero bits. This is based on a
similar DAG to DAG transform done in `AArch64`.
2025-08-19 11:14:14 +05:30

347 lines
9.5 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefixes=RV32I
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcibm -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefixes=RV32IXQCIBM
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcibm,+zbs -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefixes=RV32IXQCIBMZBS
define i32 @test_ori(i32 %a) nounwind {
; RV32I-LABEL: test_ori:
; RV32I: # %bb.0:
; RV32I-NEXT: ori a0, a0, 511
; RV32I-NEXT: ret
;
; RV32IXQCIBM-LABEL: test_ori:
; RV32IXQCIBM: # %bb.0:
; RV32IXQCIBM-NEXT: ori a0, a0, 511
; RV32IXQCIBM-NEXT: ret
;
; RV32IXQCIBMZBS-LABEL: test_ori:
; RV32IXQCIBMZBS: # %bb.0:
; RV32IXQCIBMZBS-NEXT: ori a0, a0, 511
; RV32IXQCIBMZBS-NEXT: ret
%or = or i32 %a, 511
ret i32 %or
}
define i32 @test_insbi_mask(i32 %a) nounwind {
; RV32I-LABEL: test_insbi_mask:
; RV32I: # %bb.0:
; RV32I-NEXT: lui a1, 16
; RV32I-NEXT: addi a1, a1, -1
; RV32I-NEXT: or a0, a0, a1
; RV32I-NEXT: ret
;
; RV32IXQCIBM-LABEL: test_insbi_mask:
; RV32IXQCIBM: # %bb.0:
; RV32IXQCIBM-NEXT: qc.insbi a0, -1, 16, 0
; RV32IXQCIBM-NEXT: ret
;
; RV32IXQCIBMZBS-LABEL: test_insbi_mask:
; RV32IXQCIBMZBS: # %bb.0:
; RV32IXQCIBMZBS-NEXT: qc.insbi a0, -1, 16, 0
; RV32IXQCIBMZBS-NEXT: ret
%or = or i32 %a, 65535
ret i32 %or
}
define i32 @test_insbi_mask_mv(i32 %a, i32 %b) nounwind {
; RV32I-LABEL: test_insbi_mask_mv:
; RV32I: # %bb.0:
; RV32I-NEXT: lui a0, 16
; RV32I-NEXT: addi a0, a0, -1
; RV32I-NEXT: or a0, a1, a0
; RV32I-NEXT: ret
;
; RV32IXQCIBM-LABEL: test_insbi_mask_mv:
; RV32IXQCIBM: # %bb.0:
; RV32IXQCIBM-NEXT: mv a0, a1
; RV32IXQCIBM-NEXT: qc.insbi a0, -1, 16, 0
; RV32IXQCIBM-NEXT: ret
;
; RV32IXQCIBMZBS-LABEL: test_insbi_mask_mv:
; RV32IXQCIBMZBS: # %bb.0:
; RV32IXQCIBMZBS-NEXT: mv a0, a1
; RV32IXQCIBMZBS-NEXT: qc.insbi a0, -1, 16, 0
; RV32IXQCIBMZBS-NEXT: ret
%or = or i32 %b, 65535
ret i32 %or
}
define i32 @test_insbi_shifted_mask(i32 %a) nounwind {
; RV32I-LABEL: test_insbi_shifted_mask:
; RV32I: # %bb.0:
; RV32I-NEXT: lui a1, 15
; RV32I-NEXT: or a0, a0, a1
; RV32I-NEXT: ret
;
; RV32IXQCIBM-LABEL: test_insbi_shifted_mask:
; RV32IXQCIBM: # %bb.0:
; RV32IXQCIBM-NEXT: qc.insbi a0, -1, 4, 12
; RV32IXQCIBM-NEXT: ret
;
; RV32IXQCIBMZBS-LABEL: test_insbi_shifted_mask:
; RV32IXQCIBMZBS: # %bb.0:
; RV32IXQCIBMZBS-NEXT: qc.insbi a0, -1, 4, 12
; RV32IXQCIBMZBS-NEXT: ret
%or = or i32 %a, 61440
ret i32 %or
}
define i32 @test_insbi_shifted_mask_multiple_uses(i32 %a) nounwind {
; RV32I-LABEL: test_insbi_shifted_mask_multiple_uses:
; RV32I: # %bb.0:
; RV32I-NEXT: lui a1, 15
; RV32I-NEXT: or a1, a0, a1
; RV32I-NEXT: addi a0, a0, 10
; RV32I-NEXT: xor a0, a1, a0
; RV32I-NEXT: ret
;
; RV32IXQCIBM-LABEL: test_insbi_shifted_mask_multiple_uses:
; RV32IXQCIBM: # %bb.0:
; RV32IXQCIBM-NEXT: lui a1, 15
; RV32IXQCIBM-NEXT: or a1, a1, a0
; RV32IXQCIBM-NEXT: addi a0, a0, 10
; RV32IXQCIBM-NEXT: xor a0, a0, a1
; RV32IXQCIBM-NEXT: ret
;
; RV32IXQCIBMZBS-LABEL: test_insbi_shifted_mask_multiple_uses:
; RV32IXQCIBMZBS: # %bb.0:
; RV32IXQCIBMZBS-NEXT: lui a1, 15
; RV32IXQCIBMZBS-NEXT: or a1, a1, a0
; RV32IXQCIBMZBS-NEXT: addi a0, a0, 10
; RV32IXQCIBMZBS-NEXT: xor a0, a0, a1
; RV32IXQCIBMZBS-NEXT: ret
%or = or i32 %a, 61440
%add = add i32 %a, 10
%xor = xor i32 %or, %add
ret i32 %xor
}
define i32 @test_single_bit_set(i32 %a) nounwind {
; RV32I-LABEL: test_single_bit_set:
; RV32I: # %bb.0:
; RV32I-NEXT: lui a1, 1
; RV32I-NEXT: or a0, a0, a1
; RV32I-NEXT: ret
;
; RV32IXQCIBM-LABEL: test_single_bit_set:
; RV32IXQCIBM: # %bb.0:
; RV32IXQCIBM-NEXT: qc.insbi a0, -1, 1, 12
; RV32IXQCIBM-NEXT: ret
;
; RV32IXQCIBMZBS-LABEL: test_single_bit_set:
; RV32IXQCIBMZBS: # %bb.0:
; RV32IXQCIBMZBS-NEXT: bseti a0, a0, 12
; RV32IXQCIBMZBS-NEXT: ret
%or = or i32 %a, 4096
ret i32 %or
}
; Tests for INSB(I) generation from OR and AND
define i32 @test1(i32 %a) {
; RV32I-LABEL: test1:
; RV32I: # %bb.0:
; RV32I-NEXT: andi a0, a0, -16
; RV32I-NEXT: addi a0, a0, 5
; RV32I-NEXT: ret
;
; RV32IXQCIBM-LABEL: test1:
; RV32IXQCIBM: # %bb.0:
; RV32IXQCIBM-NEXT: qc.insbi a0, 5, 4, 0
; RV32IXQCIBM-NEXT: ret
;
; RV32IXQCIBMZBS-LABEL: test1:
; RV32IXQCIBMZBS: # %bb.0:
; RV32IXQCIBMZBS-NEXT: qc.insbi a0, 5, 4, 0
; RV32IXQCIBMZBS-NEXT: ret
%1 = and i32 %a, -16 ; 0xfffffff0
%2 = or i32 %1, 5 ; 0x00000005
ret i32 %2
}
define i32 @test2(i32 %a) {
; RV32I-LABEL: test2:
; RV32I: # %bb.0:
; RV32I-NEXT: lui a1, 1033216
; RV32I-NEXT: addi a1, a1, -1
; RV32I-NEXT: and a0, a0, a1
; RV32I-NEXT: lui a1, 10240
; RV32I-NEXT: or a0, a0, a1
; RV32I-NEXT: ret
;
; RV32IXQCIBM-LABEL: test2:
; RV32IXQCIBM: # %bb.0:
; RV32IXQCIBM-NEXT: qc.insbi a0, 10, 4, 22
; RV32IXQCIBM-NEXT: ret
;
; RV32IXQCIBMZBS-LABEL: test2:
; RV32IXQCIBMZBS: # %bb.0:
; RV32IXQCIBMZBS-NEXT: qc.insbi a0, 10, 4, 22
; RV32IXQCIBMZBS-NEXT: ret
%1 = and i32 %a, -62914561 ; 0xfc3fffff
%2 = or i32 %1, 41943040 ; 0x02800000
ret i32 %2
}
define i64 @test3(i64 %a) {
; RV32I-LABEL: test3:
; RV32I: # %bb.0:
; RV32I-NEXT: andi a0, a0, -8
; RV32I-NEXT: addi a0, a0, 5
; RV32I-NEXT: ret
;
; RV32IXQCIBM-LABEL: test3:
; RV32IXQCIBM: # %bb.0:
; RV32IXQCIBM-NEXT: qc.insbi a0, 5, 3, 0
; RV32IXQCIBM-NEXT: ret
;
; RV32IXQCIBMZBS-LABEL: test3:
; RV32IXQCIBMZBS: # %bb.0:
; RV32IXQCIBMZBS-NEXT: qc.insbi a0, 5, 3, 0
; RV32IXQCIBMZBS-NEXT: ret
%1 = and i64 %a, -8 ; 0xfffffffffffffff8
%2 = or i64 %1, 5 ; 0x0000000000000005
ret i64 %2
}
define i64 @test4(i64 %a) {
; RV32I-LABEL: test4:
; RV32I: # %bb.0:
; RV32I-NEXT: andi a0, a0, -255
; RV32I-NEXT: addi a0, a0, 18
; RV32I-NEXT: ret
;
; RV32IXQCIBM-LABEL: test4:
; RV32IXQCIBM: # %bb.0:
; RV32IXQCIBM-NEXT: qc.insbi a0, 9, 7, 1
; RV32IXQCIBM-NEXT: ret
;
; RV32IXQCIBMZBS-LABEL: test4:
; RV32IXQCIBMZBS: # %bb.0:
; RV32IXQCIBMZBS-NEXT: qc.insbi a0, 9, 7, 1
; RV32IXQCIBMZBS-NEXT: ret
%1 = and i64 %a, -255 ; 0xffffffffffffff01
%2 = or i64 %1, 18 ; 0x0000000000000012
ret i64 %2
}
define i32 @test5(i32 %a) {
; RV32I-LABEL: test5:
; RV32I: # %bb.0:
; RV32I-NEXT: andi a0, a0, -16
; RV32I-NEXT: addi a0, a0, 6
; RV32I-NEXT: ret
;
; RV32IXQCIBM-LABEL: test5:
; RV32IXQCIBM: # %bb.0:
; RV32IXQCIBM-NEXT: qc.insbi a0, 6, 4, 0
; RV32IXQCIBM-NEXT: ret
;
; RV32IXQCIBMZBS-LABEL: test5:
; RV32IXQCIBMZBS: # %bb.0:
; RV32IXQCIBMZBS-NEXT: qc.insbi a0, 6, 4, 0
; RV32IXQCIBMZBS-NEXT: ret
%1 = and i32 %a, 4294967280 ; 0xfffffff0
%2 = or i32 %1, 6 ; 0x00000006
ret i32 %2
}
define i32 @test6(i32 %a) {
; RV32I-LABEL: test6:
; RV32I: # %bb.0:
; RV32I-NEXT: lui a1, 1048320
; RV32I-NEXT: and a0, a0, a1
; RV32I-NEXT: lui a1, 182
; RV32I-NEXT: addi a1, a1, -1326
; RV32I-NEXT: or a0, a0, a1
; RV32I-NEXT: ret
;
; RV32IXQCIBM-LABEL: test6:
; RV32IXQCIBM: # %bb.0:
; RV32IXQCIBM-NEXT: lui a1, 182
; RV32IXQCIBM-NEXT: addi a1, a1, -1326
; RV32IXQCIBM-NEXT: qc.insb a0, a1, 20, 0
; RV32IXQCIBM-NEXT: ret
;
; RV32IXQCIBMZBS-LABEL: test6:
; RV32IXQCIBMZBS: # %bb.0:
; RV32IXQCIBMZBS-NEXT: lui a1, 182
; RV32IXQCIBMZBS-NEXT: addi a1, a1, -1326
; RV32IXQCIBMZBS-NEXT: qc.insb a0, a1, 20, 0
; RV32IXQCIBMZBS-NEXT: ret
%1 = and i32 %a, 4293918720 ; 0xfff00000
%2 = or i32 %1, 744146 ; 0x000b5ad2
ret i32 %2
}
define i32 @test7(i32 %a) {
; RV32I-LABEL: test7:
; RV32I: # %bb.0:
; RV32I-NEXT: lui a1, 1048320
; RV32I-NEXT: addi a1, a1, 1
; RV32I-NEXT: and a0, a0, a1
; RV32I-NEXT: lui a1, 182
; RV32I-NEXT: addi a1, a1, -1326
; RV32I-NEXT: or a0, a0, a1
; RV32I-NEXT: ret
;
; RV32IXQCIBM-LABEL: test7:
; RV32IXQCIBM: # %bb.0:
; RV32IXQCIBM-NEXT: lui a1, 91
; RV32IXQCIBM-NEXT: addi a1, a1, -663
; RV32IXQCIBM-NEXT: qc.insb a0, a1, 19, 1
; RV32IXQCIBM-NEXT: ret
;
; RV32IXQCIBMZBS-LABEL: test7:
; RV32IXQCIBMZBS: # %bb.0:
; RV32IXQCIBMZBS-NEXT: lui a1, 91
; RV32IXQCIBMZBS-NEXT: addi a1, a1, -663
; RV32IXQCIBMZBS-NEXT: qc.insb a0, a1, 19, 1
; RV32IXQCIBMZBS-NEXT: ret
%1 = and i32 %a, 4293918721 ; 0xfff00001
%2 = or i32 %1, 744146 ; 0x000b5ad2
ret i32 %2
}
define i64 @test8(i64 %a) {
; RV32I-LABEL: test8:
; RV32I: # %bb.0:
; RV32I-NEXT: lui a2, 1044480
; RV32I-NEXT: zext.b a0, a0
; RV32I-NEXT: and a1, a1, a2
; RV32I-NEXT: lui a2, 496944
; RV32I-NEXT: or a0, a0, a2
; RV32I-NEXT: lui a2, 9
; RV32I-NEXT: addi a2, a2, -170
; RV32I-NEXT: or a1, a1, a2
; RV32I-NEXT: ret
;
; RV32IXQCIBM-LABEL: test8:
; RV32IXQCIBM: # %bb.0:
; RV32IXQCIBM-NEXT: lui a2, 1941
; RV32IXQCIBM-NEXT: addi a2, a2, 768
; RV32IXQCIBM-NEXT: qc.insb a0, a2, 24, 8
; RV32IXQCIBM-NEXT: lui a2, 9
; RV32IXQCIBM-NEXT: addi a2, a2, -170
; RV32IXQCIBM-NEXT: qc.insb a1, a2, 24, 0
; RV32IXQCIBM-NEXT: ret
;
; RV32IXQCIBMZBS-LABEL: test8:
; RV32IXQCIBMZBS: # %bb.0:
; RV32IXQCIBMZBS-NEXT: lui a2, 1941
; RV32IXQCIBMZBS-NEXT: addi a2, a2, 768
; RV32IXQCIBMZBS-NEXT: qc.insb a0, a2, 24, 8
; RV32IXQCIBMZBS-NEXT: lui a2, 9
; RV32IXQCIBMZBS-NEXT: addi a2, a2, -170
; RV32IXQCIBMZBS-NEXT: qc.insb a1, a2, 24, 0
; RV32IXQCIBMZBS-NEXT: ret
%1 = and i64 %a, -72057594037927681 ; 0xff000000000000ff
%2 = or i64 %1, 157601565442048 ; 0x00008f5679530000
ret i64 %2
}