Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions llvm/lib/Target/RISCV/RISCVInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -1694,6 +1694,20 @@ multiclass SelectCC_GPR_riirr<DAGOperand valty, DAGOperand imm> {
valty:$truev, valty:$falsev), []>;
}

let Predicates = [IsRV32] in {
def : Pat<(i32 (seteq (i32 (and GPR:$rs1, 0xffffffff80000000)), 0)),
(XORI (i32 (SRLI GPR:$rs1, 31)), 1)>;
def : Pat<(i32 (setlt (i32 GPR:$rs1), 0)), (SRLI GPR:$rs1, 31)>; // compressible
}
let Predicates = [IsRV64] in {
def : Pat<(i64 (seteq (i64 (and GPR:$rs1, 0x8000000000000000)), 0)),
(XORI (i64 (SRLI GPR:$rs1, 63)), 1)>;
def : Pat<(i64 (seteq (i64 (and GPR:$rs1, 0x0000000080000000)), 0)),
(XORI (i64 (SRLIW GPR:$rs1, 31)), 1)>;
def : Pat<(i64 (setlt (i64 GPR:$rs1), 0)), (SRLI GPR:$rs1, 63)>; // compressible
def : Pat<(i64 (setlt (sext_inreg GPR:$rs1, i32), 0)), (SRLIW GPR:$rs1, 31)>;
}

/// Branches and jumps

// Match `riscv_brcc` and lower to the appropriate RISC-V branch instruction.
Expand Down
10 changes: 4 additions & 6 deletions llvm/test/CodeGen/RISCV/GlobalISel/double-fcmp.ll
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ define i32 @fcmp_olt(double %a, double %b) nounwind {
; RV32I-NEXT: addi sp, sp, -16
; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
; RV32I-NEXT: call __ltdf2
; RV32I-NEXT: slti a0, a0, 0
; RV32I-NEXT: srli a0, a0, 31
; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; RV32I-NEXT: addi sp, sp, 16
; RV32I-NEXT: ret
Expand All @@ -148,8 +148,7 @@ define i32 @fcmp_olt(double %a, double %b) nounwind {
; RV64I-NEXT: addi sp, sp, -16
; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
; RV64I-NEXT: call __ltdf2
; RV64I-NEXT: sext.w a0, a0
; RV64I-NEXT: slti a0, a0, 0
; RV64I-NEXT: srliw a0, a0, 31
; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
; RV64I-NEXT: addi sp, sp, 16
; RV64I-NEXT: ret
Expand Down Expand Up @@ -446,7 +445,7 @@ define i32 @fcmp_ult(double %a, double %b) nounwind {
; RV32I-NEXT: addi sp, sp, -16
; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
; RV32I-NEXT: call __gedf2
; RV32I-NEXT: slti a0, a0, 0
; RV32I-NEXT: srli a0, a0, 31
; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; RV32I-NEXT: addi sp, sp, 16
; RV32I-NEXT: ret
Expand All @@ -456,8 +455,7 @@ define i32 @fcmp_ult(double %a, double %b) nounwind {
; RV64I-NEXT: addi sp, sp, -16
; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
; RV64I-NEXT: call __gedf2
; RV64I-NEXT: sext.w a0, a0
; RV64I-NEXT: slti a0, a0, 0
; RV64I-NEXT: srliw a0, a0, 31
; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
; RV64I-NEXT: addi sp, sp, 16
; RV64I-NEXT: ret
Expand Down
10 changes: 4 additions & 6 deletions llvm/test/CodeGen/RISCV/GlobalISel/float-fcmp.ll
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ define i32 @fcmp_olt(float %a, float %b) nounwind {
; RV32I-NEXT: addi sp, sp, -16
; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
; RV32I-NEXT: call __ltsf2
; RV32I-NEXT: slti a0, a0, 0
; RV32I-NEXT: srli a0, a0, 31
; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; RV32I-NEXT: addi sp, sp, 16
; RV32I-NEXT: ret
Expand All @@ -148,8 +148,7 @@ define i32 @fcmp_olt(float %a, float %b) nounwind {
; RV64I-NEXT: addi sp, sp, -16
; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
; RV64I-NEXT: call __ltsf2
; RV64I-NEXT: sext.w a0, a0
; RV64I-NEXT: slti a0, a0, 0
; RV64I-NEXT: srliw a0, a0, 31
; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
; RV64I-NEXT: addi sp, sp, 16
; RV64I-NEXT: ret
Expand Down Expand Up @@ -431,7 +430,7 @@ define i32 @fcmp_ult(float %a, float %b) nounwind {
; RV32I-NEXT: addi sp, sp, -16
; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
; RV32I-NEXT: call __gesf2
; RV32I-NEXT: slti a0, a0, 0
; RV32I-NEXT: srli a0, a0, 31
; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; RV32I-NEXT: addi sp, sp, 16
; RV32I-NEXT: ret
Expand All @@ -441,8 +440,7 @@ define i32 @fcmp_ult(float %a, float %b) nounwind {
; RV64I-NEXT: addi sp, sp, -16
; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
; RV64I-NEXT: call __gesf2
; RV64I-NEXT: sext.w a0, a0
; RV64I-NEXT: slti a0, a0, 0
; RV64I-NEXT: srliw a0, a0, 31
; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
; RV64I-NEXT: addi sp, sp, 16
; RV64I-NEXT: ret
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/CodeGen/RISCV/alu64.ll
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ define i64 @slti(i64 %a) nounwind {
; RV32I: # %bb.0:
; RV32I-NEXT: beqz a1, .LBB1_2
; RV32I-NEXT: # %bb.1:
; RV32I-NEXT: slti a0, a1, 0
; RV32I-NEXT: srli a0, a1, 31
; RV32I-NEXT: li a1, 0
; RV32I-NEXT: ret
; RV32I-NEXT: .LBB1_2:
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/CodeGen/RISCV/arith-with-overflow.ll
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ define i1 @sadd(i32 %a, i32 %b, ptr %c) nounwind {
; RV32I: # %bb.0: # %entry
; RV32I-NEXT: add a3, a0, a1
; RV32I-NEXT: slt a0, a3, a0
; RV32I-NEXT: slti a1, a1, 0
; RV32I-NEXT: srli a1, a1, 31
; RV32I-NEXT: xor a0, a1, a0
; RV32I-NEXT: sw a3, 0(a2)
; RV32I-NEXT: ret
Expand Down
82 changes: 78 additions & 4 deletions llvm/test/CodeGen/RISCV/bittest.ll
Original file line number Diff line number Diff line change
Expand Up @@ -187,14 +187,14 @@ define i64 @bittest_31_i64(i64 %a) nounwind {
;
; RV64ZBS-LABEL: bittest_31_i64:
; RV64ZBS: # %bb.0:
; RV64ZBS-NEXT: not a0, a0
; RV64ZBS-NEXT: bexti a0, a0, 31
; RV64ZBS-NEXT: srliw a0, a0, 31
; RV64ZBS-NEXT: xori a0, a0, 1
; RV64ZBS-NEXT: ret
;
; RV64XTHEADBS-LABEL: bittest_31_i64:
; RV64XTHEADBS: # %bb.0:
; RV64XTHEADBS-NEXT: not a0, a0
; RV64XTHEADBS-NEXT: th.tst a0, a0, 31
; RV64XTHEADBS-NEXT: srliw a0, a0, 31
; RV64XTHEADBS-NEXT: xori a0, a0, 1
; RV64XTHEADBS-NEXT: ret
%shr = lshr i64 %a, 31
%not = xor i64 %shr, -1
Expand Down Expand Up @@ -3507,3 +3507,77 @@ define void @bit_64_1_nz_branch_i64(i64 %0) {
5:
ret void
}

define i32 @bittest_31_andeq0_i64(i64 %x) {
; RV32-LABEL: bittest_31_andeq0_i64:
; RV32: # %bb.0:
; RV32-NEXT: srli a0, a0, 31
; RV32-NEXT: xori a0, a0, 1
; RV32-NEXT: ret
;
; RV64-LABEL: bittest_31_andeq0_i64:
; RV64: # %bb.0:
; RV64-NEXT: srliw a0, a0, 31
; RV64-NEXT: xori a0, a0, 1
; RV64-NEXT: ret
%and = and i64 %x, 2147483648
%cmp = icmp eq i64 %and, 0
%conv = zext i1 %cmp to i32
ret i32 %conv
}

define i32 @bittest_63_andeq0_i64(i64 %x) {
; RV32-LABEL: bittest_63_andeq0_i64:
; RV32: # %bb.0:
; RV32-NEXT: srli a1, a1, 31
; RV32-NEXT: xori a0, a1, 1
; RV32-NEXT: ret
;
; RV64-LABEL: bittest_63_andeq0_i64:
; RV64: # %bb.0:
; RV64-NEXT: srli a0, a0, 63
; RV64-NEXT: xori a0, a0, 1
; RV64-NEXT: ret
%and = and i64 %x, 9223372036854775808
Copy link
Collaborator

@topperc topperc Aug 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pfusik Do you have examples of this pattern occurring? It seems non-canonical according to InstCombine.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://github.com/dtcxzyw/llvm-codegen-benchmark

git log -p result/rvb23u64/586de7845635f863.S
git log -p result/rvb23u64/7745cd85035067d4.S
git log -p result/rvb23u64/9b1bd6b7968eafd8.S

%cmp = icmp eq i64 %and, 0
%conv = zext i1 %cmp to i32
ret i32 %conv
}

define i32 @bittest_31_slt0_i32(i32 %x, i1 %y) {
; RV32-LABEL: bittest_31_slt0_i32:
; RV32: # %bb.0:
; RV32-NEXT: srli a0, a0, 31
; RV32-NEXT: and a0, a0, a1
; RV32-NEXT: ret
;
; RV64-LABEL: bittest_31_slt0_i32:
; RV64: # %bb.0:
; RV64-NEXT: srliw a0, a0, 31
; RV64-NEXT: and a0, a0, a1
; RV64-NEXT: ret
%cmp = icmp slt i32 %x, 0
%and = and i1 %cmp, %y
%ext = zext i1 %and to i32
ret i32 %ext
}

define i32 @bittest_63_slt0_i64(i32 %x, i1 %y) {
; RV32-LABEL: bittest_63_slt0_i64:
; RV32: # %bb.0:
; RV32-NEXT: srai a0, a0, 31
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Future optimization opportunity: this srai was and still is redundant.

; RV32-NEXT: srli a0, a0, 31
; RV32-NEXT: and a0, a0, a1
; RV32-NEXT: ret
;
; RV64-LABEL: bittest_63_slt0_i64:
; RV64: # %bb.0:
; RV64-NEXT: srliw a0, a0, 31
; RV64-NEXT: and a0, a0, a1
; RV64-NEXT: ret
%ext = sext i32 %x to i64
%cmp = icmp slt i64 %ext, 0
%and = and i1 %cmp, %y
%cond = zext i1 %and to i32
ret i32 %cond
}
6 changes: 3 additions & 3 deletions llvm/test/CodeGen/RISCV/condbinops.ll
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,7 @@ define i64 @shl64(i64 %x, i64 %y, i1 %c) {
; RV32ZICOND-NEXT: addi a4, a2, -32
; RV32ZICOND-NEXT: sll a1, a1, a2
; RV32ZICOND-NEXT: not a2, a2
; RV32ZICOND-NEXT: slti a4, a4, 0
; RV32ZICOND-NEXT: srli a4, a4, 31
; RV32ZICOND-NEXT: srl a2, a3, a2
; RV32ZICOND-NEXT: czero.nez a3, a0, a4
; RV32ZICOND-NEXT: or a1, a1, a2
Expand Down Expand Up @@ -534,7 +534,7 @@ define i64 @ashr64(i64 %x, i64 %y, i1 %c) {
; RV32ZICOND-NEXT: addi a4, a2, -32
; RV32ZICOND-NEXT: srl a0, a0, a2
; RV32ZICOND-NEXT: not a2, a2
; RV32ZICOND-NEXT: slti a4, a4, 0
; RV32ZICOND-NEXT: srli a4, a4, 31
; RV32ZICOND-NEXT: sll a2, a3, a2
; RV32ZICOND-NEXT: czero.nez a3, a1, a4
; RV32ZICOND-NEXT: or a0, a0, a2
Expand Down Expand Up @@ -610,7 +610,7 @@ define i64 @lshr64(i64 %x, i64 %y, i1 %c) {
; RV32ZICOND-NEXT: addi a4, a2, -32
; RV32ZICOND-NEXT: srl a0, a0, a2
; RV32ZICOND-NEXT: not a2, a2
; RV32ZICOND-NEXT: slti a4, a4, 0
; RV32ZICOND-NEXT: srli a4, a4, 31
; RV32ZICOND-NEXT: sll a2, a3, a2
; RV32ZICOND-NEXT: czero.nez a3, a1, a4
; RV32ZICOND-NEXT: or a0, a0, a2
Expand Down
38 changes: 19 additions & 19 deletions llvm/test/CodeGen/RISCV/double-convert.ll
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,7 @@ define i32 @fcvt_wu_d_sat(double %a) nounwind {
; RV32I-NEXT: li a2, 0
; RV32I-NEXT: li a3, 0
; RV32I-NEXT: call __gedf2
; RV32I-NEXT: slti a0, a0, 0
; RV32I-NEXT: srli a0, a0, 31
; RV32I-NEXT: addi s3, a0, -1
; RV32I-NEXT: mv a0, s1
; RV32I-NEXT: mv a1, s0
Expand Down Expand Up @@ -446,8 +446,8 @@ define i32 @fcvt_wu_d_sat(double %a) nounwind {
; RV64I-NEXT: srli a0, a0, 32
; RV64I-NEXT: j .LBB6_3
; RV64I-NEXT: .LBB6_2:
; RV64I-NEXT: slti a0, s0, 0
; RV64I-NEXT: addi a0, a0, -1
; RV64I-NEXT: srli s0, s0, 63
; RV64I-NEXT: addi a0, s0, -1
; RV64I-NEXT: and a0, a0, s1
; RV64I-NEXT: .LBB6_3: # %start
; RV64I-NEXT: ld ra, 24(sp) # 8-byte Folded Reload
Expand Down Expand Up @@ -819,7 +819,7 @@ define i64 @fcvt_l_d_sat(double %a) nounwind {
; RV32I-NEXT: mv a3, s0
; RV32I-NEXT: call __unorddf2
; RV32I-NEXT: snez a0, a0
; RV32I-NEXT: slti a1, s4, 0
; RV32I-NEXT: srli a1, s4, 31
; RV32I-NEXT: sgtz a2, s2
; RV32I-NEXT: addi a0, a0, -1
; RV32I-NEXT: addi a3, a1, -1
Expand Down Expand Up @@ -1029,7 +1029,7 @@ define i64 @fcvt_lu_d_sat(double %a) nounwind {
; RV32I-NEXT: li a2, 0
; RV32I-NEXT: li a3, 0
; RV32I-NEXT: call __gedf2
; RV32I-NEXT: slti a0, a0, 0
; RV32I-NEXT: srli a0, a0, 31
; RV32I-NEXT: addi s3, a0, -1
; RV32I-NEXT: mv a0, s1
; RV32I-NEXT: mv a1, s0
Expand All @@ -1055,7 +1055,7 @@ define i64 @fcvt_lu_d_sat(double %a) nounwind {
; RV64I-NEXT: mv s0, a0
; RV64I-NEXT: li a1, 0
; RV64I-NEXT: call __gedf2
; RV64I-NEXT: slti a0, a0, 0
; RV64I-NEXT: srli a0, a0, 63
; RV64I-NEXT: addi s1, a0, -1
; RV64I-NEXT: mv a0, s0
; RV64I-NEXT: call __fixunsdfdi
Expand Down Expand Up @@ -1898,9 +1898,9 @@ define zeroext i16 @fcvt_wu_s_sat_i16(double %a) nounwind {
; RV32I-NEXT: mv a0, a1
; RV32I-NEXT: j .LBB28_3
; RV32I-NEXT: .LBB28_2:
; RV32I-NEXT: slti a2, s0, 0
; RV32I-NEXT: addi a2, a2, -1
; RV32I-NEXT: and a0, a2, a0
; RV32I-NEXT: srli s0, s0, 31
; RV32I-NEXT: addi s0, s0, -1
; RV32I-NEXT: and a0, s0, a0
; RV32I-NEXT: .LBB28_3: # %start
; RV32I-NEXT: and a0, a0, a1
; RV32I-NEXT: lw ra, 28(sp) # 4-byte Folded Reload
Expand Down Expand Up @@ -1937,8 +1937,8 @@ define zeroext i16 @fcvt_wu_s_sat_i16(double %a) nounwind {
; RV64I-NEXT: mv a0, a1
; RV64I-NEXT: j .LBB28_3
; RV64I-NEXT: .LBB28_2:
; RV64I-NEXT: slti a0, s0, 0
; RV64I-NEXT: addi a0, a0, -1
; RV64I-NEXT: srli s0, s0, 63
; RV64I-NEXT: addi a0, s0, -1
; RV64I-NEXT: and a0, a0, s1
; RV64I-NEXT: .LBB28_3: # %start
; RV64I-NEXT: and a0, a0, a1
Expand Down Expand Up @@ -2271,9 +2271,9 @@ define zeroext i8 @fcvt_wu_s_sat_i8(double %a) nounwind {
; RV32I-NEXT: li a0, 255
; RV32I-NEXT: j .LBB32_3
; RV32I-NEXT: .LBB32_2:
; RV32I-NEXT: slti a1, s0, 0
; RV32I-NEXT: addi a1, a1, -1
; RV32I-NEXT: and a0, a1, a0
; RV32I-NEXT: srli s0, s0, 31
; RV32I-NEXT: addi s0, s0, -1
; RV32I-NEXT: and a0, s0, a0
; RV32I-NEXT: .LBB32_3: # %start
; RV32I-NEXT: zext.b a0, a0
; RV32I-NEXT: lw ra, 28(sp) # 4-byte Folded Reload
Expand Down Expand Up @@ -2307,8 +2307,8 @@ define zeroext i8 @fcvt_wu_s_sat_i8(double %a) nounwind {
; RV64I-NEXT: li a0, 255
; RV64I-NEXT: j .LBB32_3
; RV64I-NEXT: .LBB32_2:
; RV64I-NEXT: slti a0, s0, 0
; RV64I-NEXT: addi a0, a0, -1
; RV64I-NEXT: srli s0, s0, 63
; RV64I-NEXT: addi a0, s0, -1
; RV64I-NEXT: and a0, a0, s1
; RV64I-NEXT: .LBB32_3: # %start
; RV64I-NEXT: zext.b a0, a0
Expand Down Expand Up @@ -2386,7 +2386,7 @@ define zeroext i32 @fcvt_wu_d_sat_zext(double %a) nounwind {
; RV32I-NEXT: li a2, 0
; RV32I-NEXT: li a3, 0
; RV32I-NEXT: call __gedf2
; RV32I-NEXT: slti a0, a0, 0
; RV32I-NEXT: srli a0, a0, 31
; RV32I-NEXT: addi s3, a0, -1
; RV32I-NEXT: mv a0, s1
; RV32I-NEXT: mv a1, s0
Expand Down Expand Up @@ -2427,8 +2427,8 @@ define zeroext i32 @fcvt_wu_d_sat_zext(double %a) nounwind {
; RV64I-NEXT: srli a0, a0, 32
; RV64I-NEXT: j .LBB33_3
; RV64I-NEXT: .LBB33_2:
; RV64I-NEXT: slti a0, s0, 0
; RV64I-NEXT: addi a0, a0, -1
; RV64I-NEXT: srli s0, s0, 63
; RV64I-NEXT: addi a0, s0, -1
; RV64I-NEXT: and a0, a0, s1
; RV64I-NEXT: .LBB33_3: # %start
; RV64I-NEXT: slli a0, a0, 32
Expand Down
Loading