[llvm] 2817873 - [RISCV] Fold (sext_inreg (setcc), i1) -> (sub 0, (setcc). (#154206)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 18 21:24:07 PDT 2025
Author: Craig Topper
Date: 2025-08-18T21:24:03-07:00
New Revision: 2817873082c05b061b198853d64602ff26ce7cfe
URL: https://github.com/llvm/llvm-project/commit/2817873082c05b061b198853d64602ff26ce7cfe
DIFF: https://github.com/llvm/llvm-project/commit/2817873082c05b061b198853d64602ff26ce7cfe.diff
LOG: [RISCV] Fold (sext_inreg (setcc), i1) -> (sub 0, (setcc). (#154206)
This helps the 3 vendor extensions that make sext_inreg i1 legal.
I'm delaying this until after LegalizeDAG since we normally have
sext_inreg i1 up until LegalizeDAG turns it into and+neg.
I also delayed the recently added (sext_inreg (xor (setcc), -1), i1)
combine. Though the xor isn't likely to appear before LegalizeDAG anyway.
Added:
Modified:
llvm/lib/Target/RISCV/RISCVISelLowering.cpp
llvm/test/CodeGen/RISCV/rv32xandesperf.ll
llvm/test/CodeGen/RISCV/rv32xtheadbb.ll
llvm/test/CodeGen/RISCV/rv64xandesperf.ll
llvm/test/CodeGen/RISCV/rv64xtheadbb.ll
llvm/test/CodeGen/RISCV/xqcibm-extract.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index ce03818b49502..8763f0091b8c2 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -16639,33 +16639,38 @@ static SDValue performSETCCCombine(SDNode *N, SelectionDAG &DAG,
}
static SDValue
-performSIGN_EXTEND_INREGCombine(SDNode *N, SelectionDAG &DAG,
+performSIGN_EXTEND_INREGCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI,
const RISCVSubtarget &Subtarget) {
+ SelectionDAG &DAG = DCI.DAG;
SDValue Src = N->getOperand(0);
EVT VT = N->getValueType(0);
EVT SrcVT = cast<VTSDNode>(N->getOperand(1))->getVT();
unsigned Opc = Src.getOpcode();
+ SDLoc DL(N);
// Fold (sext_inreg (fmv_x_anyexth X), i16) -> (fmv_x_signexth X)
// Don't do this with Zhinx. We need to explicitly sign extend the GPR.
if (Opc == RISCVISD::FMV_X_ANYEXTH && SrcVT.bitsGE(MVT::i16) &&
Subtarget.hasStdExtZfhmin())
- return DAG.getNode(RISCVISD::FMV_X_SIGNEXTH, SDLoc(N), VT,
- Src.getOperand(0));
+ return DAG.getNode(RISCVISD::FMV_X_SIGNEXTH, DL, VT, Src.getOperand(0));
// Fold (sext_inreg (shl X, Y), i32) -> (sllw X, Y) iff Y u< 32
if (Opc == ISD::SHL && Subtarget.is64Bit() && SrcVT == MVT::i32 &&
VT == MVT::i64 && !isa<ConstantSDNode>(Src.getOperand(1)) &&
DAG.computeKnownBits(Src.getOperand(1)).countMaxActiveBits() <= 5)
- return DAG.getNode(RISCVISD::SLLW, SDLoc(N), VT, Src.getOperand(0),
+ return DAG.getNode(RISCVISD::SLLW, DL, VT, Src.getOperand(0),
Src.getOperand(1));
+ // Fold (sext_inreg (setcc), i1) -> (sub 0, (setcc))
+ if (Opc == ISD::SETCC && SrcVT == MVT::i1 && DCI.isAfterLegalizeDAG())
+ return DAG.getNode(ISD::SUB, DL, VT, DAG.getConstant(0, DL, VT), Src);
+
// Fold (sext_inreg (xor (setcc), -1), i1) -> (add (setcc), -1)
if (Opc == ISD::XOR && SrcVT == MVT::i1 &&
isAllOnesConstant(Src.getOperand(1)) &&
- Src.getOperand(0).getOpcode() == ISD::SETCC)
- return DAG.getNode(ISD::ADD, SDLoc(N), VT, Src.getOperand(0),
- DAG.getAllOnesConstant(SDLoc(N), VT));
+ Src.getOperand(0).getOpcode() == ISD::SETCC && DCI.isAfterLegalizeDAG())
+ return DAG.getNode(ISD::ADD, DL, VT, Src.getOperand(0),
+ DAG.getAllOnesConstant(DL, VT));
return SDValue();
}
@@ -20088,7 +20093,7 @@ SDValue RISCVTargetLowering::PerformDAGCombine(SDNode *N,
case ISD::SETCC:
return performSETCCCombine(N, DAG, Subtarget);
case ISD::SIGN_EXTEND_INREG:
- return performSIGN_EXTEND_INREGCombine(N, DAG, Subtarget);
+ return performSIGN_EXTEND_INREGCombine(N, DCI, Subtarget);
case ISD::ZERO_EXTEND:
// Fold (zero_extend (fp_to_uint X)) to prevent forming fcvt+zexti32 during
// type legalization. This is safe because fp_to_uint produces poison if
diff --git a/llvm/test/CodeGen/RISCV/rv32xandesperf.ll b/llvm/test/CodeGen/RISCV/rv32xandesperf.ll
index 85666f70ce535..4a0cddb618a09 100644
--- a/llvm/test/CodeGen/RISCV/rv32xandesperf.ll
+++ b/llvm/test/CodeGen/RISCV/rv32xandesperf.ll
@@ -346,6 +346,31 @@ define zeroext i8 @sexti1_i32_setcc(i32 signext %a) {
ret i8 %sext
}
+; Make sure we don't use seqz+nds.bfos instead of snez+addi
+define i32 @sexti1_i32_setcc_2(i32 %a, i32 %b) {
+; CHECK-LABEL: sexti1_i32_setcc_2:
+; CHECK: # %bb.0:
+; CHECK-NEXT: xor a0, a0, a1
+; CHECK-NEXT: snez a0, a0
+; CHECK-NEXT: addi a0, a0, -1
+; CHECK-NEXT: ret
+ %icmp = icmp eq i32 %a, %b
+ %sext = sext i1 %icmp to i32
+ ret i32 %sext
+}
+
+; Make sure we don't use nds.bfos instead of neg.
+define i32 @sexti1_i32_setcc_3(i32 %a, i32 %b) {
+; CHECK-LABEL: sexti1_i32_setcc_3:
+; CHECK: # %bb.0:
+; CHECK-NEXT: slt a0, a0, a1
+; CHECK-NEXT: neg a0, a0
+; CHECK-NEXT: ret
+ %icmp = icmp slt i32 %a, %b
+ %sext = sext i1 %icmp to i32
+ ret i32 %sext
+}
+
define i32 @sexti8_i32(i32 %a) {
; CHECK-LABEL: sexti8_i32:
; CHECK: # %bb.0:
diff --git a/llvm/test/CodeGen/RISCV/rv32xtheadbb.ll b/llvm/test/CodeGen/RISCV/rv32xtheadbb.ll
index ec720e6d8f5b0..d561145711fd9 100644
--- a/llvm/test/CodeGen/RISCV/rv32xtheadbb.ll
+++ b/llvm/test/CodeGen/RISCV/rv32xtheadbb.ll
@@ -372,6 +372,44 @@ define zeroext i8 @sexti1_i32_setcc(i32 signext %a) {
ret i8 %sext
}
+; Make sure we don't use seqz+th.ext instead of snez+addi
+define i32 @sexti1_i32_setcc_2(i32 %a, i32 %b) {
+; RV32I-LABEL: sexti1_i32_setcc_2:
+; RV32I: # %bb.0:
+; RV32I-NEXT: xor a0, a0, a1
+; RV32I-NEXT: snez a0, a0
+; RV32I-NEXT: addi a0, a0, -1
+; RV32I-NEXT: ret
+;
+; RV32XTHEADBB-LABEL: sexti1_i32_setcc_2:
+; RV32XTHEADBB: # %bb.0:
+; RV32XTHEADBB-NEXT: xor a0, a0, a1
+; RV32XTHEADBB-NEXT: snez a0, a0
+; RV32XTHEADBB-NEXT: addi a0, a0, -1
+; RV32XTHEADBB-NEXT: ret
+ %icmp = icmp eq i32 %a, %b
+ %sext = sext i1 %icmp to i32
+ ret i32 %sext
+}
+
+; Make sure we don't use th.ext instead of neg.
+define i32 @sexti1_i32_setcc_3(i32 %a, i32 %b) {
+; RV32I-LABEL: sexti1_i32_setcc_3:
+; RV32I: # %bb.0:
+; RV32I-NEXT: slt a0, a0, a1
+; RV32I-NEXT: neg a0, a0
+; RV32I-NEXT: ret
+;
+; RV32XTHEADBB-LABEL: sexti1_i32_setcc_3:
+; RV32XTHEADBB: # %bb.0:
+; RV32XTHEADBB-NEXT: slt a0, a0, a1
+; RV32XTHEADBB-NEXT: neg a0, a0
+; RV32XTHEADBB-NEXT: ret
+ %icmp = icmp slt i32 %a, %b
+ %sext = sext i1 %icmp to i32
+ ret i32 %sext
+}
+
define i32 @sextb_i32(i32 %a) nounwind {
; RV32I-LABEL: sextb_i32:
; RV32I: # %bb.0:
diff --git a/llvm/test/CodeGen/RISCV/rv64xandesperf.ll b/llvm/test/CodeGen/RISCV/rv64xandesperf.ll
index 406e5247ae0dd..225495817ae16 100644
--- a/llvm/test/CodeGen/RISCV/rv64xandesperf.ll
+++ b/llvm/test/CodeGen/RISCV/rv64xandesperf.ll
@@ -290,6 +290,31 @@ define zeroext i8 @sexti1_i32_setcc(i32 signext %a) {
ret i8 %sext
}
+; Make sure we don't use seqz+nds.bfos instead of snez+addi
+define signext i32 @sexti1_i32_setcc_2(i32 signext %a, i32 signext %b) {
+; CHECK-LABEL: sexti1_i32_setcc_2:
+; CHECK: # %bb.0:
+; CHECK-NEXT: xor a0, a0, a1
+; CHECK-NEXT: snez a0, a0
+; CHECK-NEXT: addi a0, a0, -1
+; CHECK-NEXT: ret
+ %icmp = icmp eq i32 %a, %b
+ %sext = sext i1 %icmp to i32
+ ret i32 %sext
+}
+
+; Make sure we don't use nds.bfos instead of neg.
+define signext i32 @sexti1_i32_setcc_3(i32 signext %a, i32 signext %b) {
+; CHECK-LABEL: sexti1_i32_setcc_3:
+; CHECK: # %bb.0:
+; CHECK-NEXT: slt a0, a0, a1
+; CHECK-NEXT: neg a0, a0
+; CHECK-NEXT: ret
+ %icmp = icmp slt i32 %a, %b
+ %sext = sext i1 %icmp to i32
+ ret i32 %sext
+}
+
define signext i32 @sexti8_i32(i32 signext %a) {
; CHECK-LABEL: sexti8_i32:
; CHECK: # %bb.0:
@@ -360,6 +385,31 @@ define zeroext i8 @sexti1_i64_setcc(i64 %a) {
ret i8 %sext
}
+; Make sure we don't use seqz+nds.bfos instead of snez+addi
+define i64 @sexti1_i64_setcc_2(i64 %a, i64 %b) {
+; CHECK-LABEL: sexti1_i64_setcc_2:
+; CHECK: # %bb.0:
+; CHECK-NEXT: xor a0, a0, a1
+; CHECK-NEXT: snez a0, a0
+; CHECK-NEXT: addi a0, a0, -1
+; CHECK-NEXT: ret
+ %icmp = icmp eq i64 %a, %b
+ %sext = sext i1 %icmp to i64
+ ret i64 %sext
+}
+
+; Make sure we don't use nds.bfos instead of neg.
+define i64 @sexti1_i64_setcc_3(i64 %a, i64 %b) {
+; CHECK-LABEL: sexti1_i64_setcc_3:
+; CHECK: # %bb.0:
+; CHECK-NEXT: slt a0, a0, a1
+; CHECK-NEXT: neg a0, a0
+; CHECK-NEXT: ret
+ %icmp = icmp slt i64 %a, %b
+ %sext = sext i1 %icmp to i64
+ ret i64 %sext
+}
+
define i64 @sexti8_i64(i64 %a) {
; CHECK-LABEL: sexti8_i64:
; CHECK: # %bb.0:
diff --git a/llvm/test/CodeGen/RISCV/rv64xtheadbb.ll b/llvm/test/CodeGen/RISCV/rv64xtheadbb.ll
index 92d026b0ef1a5..d7c568bf4e019 100644
--- a/llvm/test/CodeGen/RISCV/rv64xtheadbb.ll
+++ b/llvm/test/CodeGen/RISCV/rv64xtheadbb.ll
@@ -729,6 +729,44 @@ define zeroext i8 @sexti1_i32_setcc(i32 signext %a) {
ret i8 %sext
}
+; Make sure we don't use seqz+th.ext instead of snez+addi
+define signext i32 @sexti1_i32_setcc_2(i32 signext %a, i32 signext %b) {
+; RV64I-LABEL: sexti1_i32_setcc_2:
+; RV64I: # %bb.0:
+; RV64I-NEXT: xor a0, a0, a1
+; RV64I-NEXT: snez a0, a0
+; RV64I-NEXT: addi a0, a0, -1
+; RV64I-NEXT: ret
+;
+; RV64XTHEADBB-LABEL: sexti1_i32_setcc_2:
+; RV64XTHEADBB: # %bb.0:
+; RV64XTHEADBB-NEXT: xor a0, a0, a1
+; RV64XTHEADBB-NEXT: snez a0, a0
+; RV64XTHEADBB-NEXT: addi a0, a0, -1
+; RV64XTHEADBB-NEXT: ret
+ %icmp = icmp eq i32 %a, %b
+ %sext = sext i1 %icmp to i32
+ ret i32 %sext
+}
+
+; Make sure we don't use th.ext instead of neg.
+define signext i32 @sexti1_i32_setcc_3(i32 signext %a, i32 signext %b) {
+; RV64I-LABEL: sexti1_i32_setcc_3:
+; RV64I: # %bb.0:
+; RV64I-NEXT: slt a0, a0, a1
+; RV64I-NEXT: neg a0, a0
+; RV64I-NEXT: ret
+;
+; RV64XTHEADBB-LABEL: sexti1_i32_setcc_3:
+; RV64XTHEADBB: # %bb.0:
+; RV64XTHEADBB-NEXT: slt a0, a0, a1
+; RV64XTHEADBB-NEXT: neg a0, a0
+; RV64XTHEADBB-NEXT: ret
+ %icmp = icmp slt i32 %a, %b
+ %sext = sext i1 %icmp to i32
+ ret i32 %sext
+}
+
define i64 @sexti1_i64(i64 %a) nounwind {
; RV64I-LABEL: sexti1_i64:
; RV64I: # %bb.0:
@@ -780,6 +818,44 @@ define zeroext i8 @sexti1_i64_setcc(i64 %a) {
ret i8 %sext
}
+; Make sure we don't use seqz+th.ext instead of snez+addi
+define i64 @sexti1_i64_setcc_2(i64 %a, i64 %b) {
+; RV64I-LABEL: sexti1_i64_setcc_2:
+; RV64I: # %bb.0:
+; RV64I-NEXT: xor a0, a0, a1
+; RV64I-NEXT: snez a0, a0
+; RV64I-NEXT: addi a0, a0, -1
+; RV64I-NEXT: ret
+;
+; RV64XTHEADBB-LABEL: sexti1_i64_setcc_2:
+; RV64XTHEADBB: # %bb.0:
+; RV64XTHEADBB-NEXT: xor a0, a0, a1
+; RV64XTHEADBB-NEXT: snez a0, a0
+; RV64XTHEADBB-NEXT: addi a0, a0, -1
+; RV64XTHEADBB-NEXT: ret
+ %icmp = icmp eq i64 %a, %b
+ %sext = sext i1 %icmp to i64
+ ret i64 %sext
+}
+
+; Make sure we don't use th.ext instead of neg.
+define i64 @sexti1_i64_setcc_3(i64 %a, i64 %b) {
+; RV64I-LABEL: sexti1_i64_setcc_3:
+; RV64I: # %bb.0:
+; RV64I-NEXT: slt a0, a0, a1
+; RV64I-NEXT: neg a0, a0
+; RV64I-NEXT: ret
+;
+; RV64XTHEADBB-LABEL: sexti1_i64_setcc_3:
+; RV64XTHEADBB: # %bb.0:
+; RV64XTHEADBB-NEXT: slt a0, a0, a1
+; RV64XTHEADBB-NEXT: neg a0, a0
+; RV64XTHEADBB-NEXT: ret
+ %icmp = icmp slt i64 %a, %b
+ %sext = sext i1 %icmp to i64
+ ret i64 %sext
+}
+
define signext i32 @sextb_i32(i32 signext %a) nounwind {
; RV64I-LABEL: sextb_i32:
; RV64I: # %bb.0:
diff --git a/llvm/test/CodeGen/RISCV/xqcibm-extract.ll b/llvm/test/CodeGen/RISCV/xqcibm-extract.ll
index fc3d8fe54602a..c2c9d077b2526 100644
--- a/llvm/test/CodeGen/RISCV/xqcibm-extract.ll
+++ b/llvm/test/CodeGen/RISCV/xqcibm-extract.ll
@@ -74,6 +74,56 @@ define zeroext i8 @sexti1_i32_setcc(i32 signext %a) {
ret i8 %sext
}
+; Make sure we don't use seqz+qc.ext instead of snez+addi
+define i32 @sexti1_i32_setcc_2(i32 %a, i32 %b) {
+; RV32I-LABEL: sexti1_i32_setcc_2:
+; RV32I: # %bb.0:
+; RV32I-NEXT: xor a0, a0, a1
+; RV32I-NEXT: snez a0, a0
+; RV32I-NEXT: addi a0, a0, -1
+; RV32I-NEXT: ret
+;
+; RV32XQCIBM-LABEL: sexti1_i32_setcc_2:
+; RV32XQCIBM: # %bb.0:
+; RV32XQCIBM-NEXT: xor a0, a0, a1
+; RV32XQCIBM-NEXT: snez a0, a0
+; RV32XQCIBM-NEXT: addi a0, a0, -1
+; RV32XQCIBM-NEXT: ret
+;
+; RV32XQCIBMZBB-LABEL: sexti1_i32_setcc_2:
+; RV32XQCIBMZBB: # %bb.0:
+; RV32XQCIBMZBB-NEXT: xor a0, a0, a1
+; RV32XQCIBMZBB-NEXT: snez a0, a0
+; RV32XQCIBMZBB-NEXT: addi a0, a0, -1
+; RV32XQCIBMZBB-NEXT: ret
+ %icmp = icmp eq i32 %a, %b
+ %sext = sext i1 %icmp to i32
+ ret i32 %sext
+}
+
+; Make sure we don't use qc.ext instead of neg.
+define i32 @sexti1_i32_setcc_3(i32 %a, i32 %b) {
+; RV32I-LABEL: sexti1_i32_setcc_3:
+; RV32I: # %bb.0:
+; RV32I-NEXT: slt a0, a0, a1
+; RV32I-NEXT: neg a0, a0
+; RV32I-NEXT: ret
+;
+; RV32XQCIBM-LABEL: sexti1_i32_setcc_3:
+; RV32XQCIBM: # %bb.0:
+; RV32XQCIBM-NEXT: slt a0, a0, a1
+; RV32XQCIBM-NEXT: neg a0, a0
+; RV32XQCIBM-NEXT: ret
+;
+; RV32XQCIBMZBB-LABEL: sexti1_i32_setcc_3:
+; RV32XQCIBMZBB: # %bb.0:
+; RV32XQCIBMZBB-NEXT: slt a0, a0, a1
+; RV32XQCIBMZBB-NEXT: neg a0, a0
+; RV32XQCIBMZBB-NEXT: ret
+ %icmp = icmp slt i32 %a, %b
+ %sext = sext i1 %icmp to i32
+ ret i32 %sext
+}
define i32 @sexti8_i32(i8 %a) nounwind {
; RV32I-LABEL: sexti8_i32:
More information about the llvm-commits
mailing list