[llvm] 5c5a1a2 - [RISCV] Introduce RISCVISD::CZERO_{EQZ,NEZ} nodes produce them when zicond is present in lowerSELECT

Alex Bradbury via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 14 03:32:00 PDT 2023


Author: Alex Bradbury
Date: 2023-07-14T11:31:27+01:00
New Revision: 5c5a1a2927118eb9cc51c7b98c959a30524cc491

URL: https://github.com/llvm/llvm-project/commit/5c5a1a2927118eb9cc51c7b98c959a30524cc491
DIFF: https://github.com/llvm/llvm-project/commit/5c5a1a2927118eb9cc51c7b98c959a30524cc491.diff

LOG: [RISCV] Introduce RISCVISD::CZERO_{EQZ,NEZ} nodes produce them when zicond is present in lowerSELECT

This patch is a step towards altering how we handle the emission of
condops. Marking ISD::SELECT as legal is a major change in the codegen
path, and gives few options for maintaining the old codegen path when
it is believed to be better (e.g. a better branchless sequence is
possible using non-zicond instructions, or the branch-based sequence is
preferable).

This removes the existing SelectionDAG patterns and moves the logic into
lowerSELECT. Along some small codegen changes you'll note a few minor
regressions in the generated code quality - this are due to the fact
that by lowering the SELECT node early we miss out on combines that
would kick in later when setcc condcodes that aren't natively supported
have been expanded (thus exposing opportunities for optimisation by
performing logical negation and swapping truev/falsev). I've opted to
split out work that addresses these into follow-on patches (especially
as zicond is still 'experimental').

matchSetCC is a straight-forward translation from the version in
RISCVISelDAGToDAG. Ideally, in the future it can be converted to a
helper shared between both files.

Differential Revision: https://reviews.llvm.org/D155083

Added: 
    

Modified: 
    llvm/lib/Target/RISCV/RISCVISelLowering.cpp
    llvm/lib/Target/RISCV/RISCVISelLowering.h
    llvm/lib/Target/RISCV/RISCVInstrInfoZicond.td
    llvm/test/CodeGen/RISCV/condops.ll
    llvm/test/CodeGen/RISCV/select.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 76a1363a32cb41..45fcfdaca88867 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -333,7 +333,7 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
   if (Subtarget.is64Bit())
     setOperationAction(ISD::ABS, MVT::i32, Custom);
 
-  if (!Subtarget.hasStdExtZicond() && !Subtarget.hasVendorXVentanaCondOps() &&
+  if (!Subtarget.hasVendorXVentanaCondOps() &&
       !Subtarget.hasVendorXTHeadCondMov())
     setOperationAction(ISD::SELECT, XLenVT, Custom);
 
@@ -5762,6 +5762,63 @@ static SDValue combineSelectToBinOp(SDNode *N, SelectionDAG &DAG,
   return SDValue();
 }
 
+/// RISC-V doesn't have general instructions for integer setne/seteq, but we can
+/// check for equality with 0. This function emits nodes that convert the
+/// seteq/setne into something that can be compared with 0.
+/// Based on RISCVDAGToDAGISel::selectSETCC but modified to produce
+/// target-independent SelectionDAG nodes rather than machine nodes.
+static bool selectSETCC(SDValue N, ISD::CondCode ExpectedCCVal, SDValue &Val,
+                        SelectionDAG &DAG) {
+  assert(ISD::isIntEqualitySetCC(ExpectedCCVal) &&
+         "Unexpected condition code!");
+
+  // We're looking for a setcc.
+  if (N->getOpcode() != ISD::SETCC)
+    return false;
+
+  // Must be an equality comparison.
+  ISD::CondCode CCVal = cast<CondCodeSDNode>(N->getOperand(2))->get();
+  if (CCVal != ExpectedCCVal)
+    return false;
+
+  SDValue LHS = N->getOperand(0);
+  SDValue RHS = N->getOperand(1);
+
+  if (!LHS.getValueType().isInteger())
+    return false;
+
+  // If the RHS side is 0, we don't need any extra instructions, return the LHS.
+  if (isNullConstant(RHS)) {
+    Val = LHS;
+    return true;
+  }
+
+  SDLoc DL(N);
+
+  if (auto *C = dyn_cast<ConstantSDNode>(RHS)) {
+    int64_t CVal = C->getSExtValue();
+    // If the RHS is -2048, we can use xori to produce 0 if the LHS is -2048 and
+    // non-zero otherwise.
+    if (CVal == -2048) {
+      Val = DAG.getNode(ISD::XOR, DL, N->getValueType(0), LHS,
+                        DAG.getConstant(CVal, DL, N->getValueType(0)));
+      return true;
+    }
+    // If the RHS is [-2047,2048], we can use addi with -RHS to produce 0 if the
+    // LHS is equal to the RHS and non-zero otherwise.
+    if (isInt<12>(CVal) || CVal == 2048) {
+      Val = DAG.getNode(ISD::ADD, DL, N->getValueType(0), LHS,
+                        DAG.getConstant(-CVal, DL, N->getValueType(0)));
+      return true;
+    }
+  }
+
+  // If nothing else we can XOR the LHS and RHS to produce zero if they are
+  // equal and a non-zero value if they aren't.
+  Val = DAG.getNode(ISD::XOR, DL, N->getValueType(0), LHS, RHS);
+  return true;
+}
+
 SDValue RISCVTargetLowering::lowerSELECT(SDValue Op, SelectionDAG &DAG) const {
   SDValue CondV = Op.getOperand(0);
   SDValue TrueV = Op.getOperand(1);
@@ -5770,6 +5827,68 @@ SDValue RISCVTargetLowering::lowerSELECT(SDValue Op, SelectionDAG &DAG) const {
   MVT VT = Op.getSimpleValueType();
   MVT XLenVT = Subtarget.getXLenVT();
 
+  // When Zicond is present, emit CZERO_EQZ and CZERO_NEZ nodes to implement
+  // the SELECT. Performing the lowering here allows for greater control over
+  // when CZERO_{EQZ/NEZ} are used vs another branchless sequence or
+  // RISCVISD::SELECT_CC node (branch-based select).
+  if (Subtarget.hasStdExtZicond() && VT.isInteger()) {
+    SDValue NewCondV;
+    if (selectSETCC(CondV, ISD::SETNE, NewCondV, DAG)) {
+      if (isNullConstant(FalseV))
+        // (select (riscv_setne c), t, 0) -> (czero_eqz t, c)
+        return DAG.getNode(RISCVISD::CZERO_EQZ, DL, VT, TrueV, NewCondV);
+      else if (isNullConstant(TrueV))
+        // (select (riscv_setne c), 0, f) -> (czero_nez f, c)
+        return DAG.getNode(RISCVISD::CZERO_NEZ, DL, VT, FalseV, NewCondV);
+      // (select (riscv_setne c), t, f) -> (or (czero_eqz t, c), (czero_nez f,
+      // c)
+      return DAG.getNode(
+          ISD::OR, DL, VT,
+          DAG.getNode(RISCVISD::CZERO_EQZ, DL, VT, TrueV, NewCondV),
+          DAG.getNode(RISCVISD::CZERO_NEZ, DL, VT, FalseV, NewCondV));
+    }
+    if (selectSETCC(CondV, ISD::SETEQ, NewCondV, DAG)) {
+      if (isNullConstant(FalseV))
+        // (select (riscv_seteq c), t, 0) -> (czero_nez t, c)
+        return DAG.getNode(RISCVISD::CZERO_NEZ, DL, VT, TrueV, NewCondV);
+      else if (isNullConstant(TrueV))
+        // (select (riscv_seteq c), 0, f) -> (czero_eqz f, c)
+        return DAG.getNode(RISCVISD::CZERO_EQZ, DL, VT, FalseV, NewCondV);
+      // (select (riscv_seteq c), t, f) -> (or (czero_eqz f, c), (czero_nez t,
+      // c)
+      return DAG.getNode(
+          ISD::OR, DL, VT,
+          DAG.getNode(RISCVISD::CZERO_EQZ, DL, VT, FalseV, NewCondV),
+          DAG.getNode(RISCVISD::CZERO_NEZ, DL, VT, TrueV, NewCondV));
+    }
+    if (isNullConstant(FalseV)) {
+      // (select c, t, 0) -> (czero_eqz t, c)
+      return DAG.getNode(RISCVISD::CZERO_EQZ, DL, VT, TrueV, CondV);
+    }
+    if (isNullConstant(TrueV)) {
+      // (select c, 0, f) -> (czero_nez f, c)
+      return DAG.getNode(RISCVISD::CZERO_NEZ, DL, VT, FalseV, CondV);
+    }
+    if (TrueV.getOpcode() == ISD::AND &&
+        (TrueV.getOperand(0) == FalseV || TrueV.getOperand(1) == FalseV)) {
+      // (select c, (and f, x), f) -> (or (and f, x), (czero_nez f, c))
+      return DAG.getNode(
+          ISD::OR, DL, VT, TrueV,
+          DAG.getNode(RISCVISD::CZERO_NEZ, DL, VT, FalseV, CondV));
+    }
+    if (FalseV.getOpcode() == ISD::AND &&
+        (FalseV.getOperand(0) == TrueV || FalseV.getOperand(1) == TrueV)) {
+      // (select c, t, (and t, x)) -> (or (czero_eqz t, c), (and t, x))
+      return DAG.getNode(
+          ISD::OR, DL, VT, FalseV,
+          DAG.getNode(RISCVISD::CZERO_EQZ, DL, VT, TrueV, CondV));
+    }
+    // (select c, t, f) -> (or (czero_eqz t, c), (czero_nez f, c))
+    return DAG.getNode(ISD::OR, DL, VT,
+                       DAG.getNode(RISCVISD::CZERO_EQZ, DL, VT, TrueV, CondV),
+                       DAG.getNode(RISCVISD::CZERO_NEZ, DL, VT, FalseV, CondV));
+  }
+
   // Lower vector SELECTs to VSELECTs by splatting the condition.
   if (VT.isVector()) {
     MVT SplatCondVT = VT.changeVectorElementType(MVT::i1);
@@ -15901,6 +16020,8 @@ const char *RISCVTargetLowering::getTargetNodeName(unsigned Opcode) const {
   NODE_NAME_CASE(READ_CSR)
   NODE_NAME_CASE(WRITE_CSR)
   NODE_NAME_CASE(SWAP_CSR)
+  NODE_NAME_CASE(CZERO_EQZ)
+  NODE_NAME_CASE(CZERO_NEZ)
   }
   // clang-format on
   return nullptr;

diff  --git a/llvm/lib/Target/RISCV/RISCVISelLowering.h b/llvm/lib/Target/RISCV/RISCVISelLowering.h
index 7621911f697695..e016c1f456e7f4 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.h
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.h
@@ -356,6 +356,11 @@ enum NodeType : unsigned {
   // the value read before the modification and the new chain pointer.
   SWAP_CSR,
 
+  // Branchless select operations, matching the semantics of the instructions
+  // defined in zicond.
+  CZERO_EQZ,
+  CZERO_NEZ,
+
   // FP to 32 bit int conversions for RV64. These are used to keep track of the
   // result being sign extended to 64 bit. These saturate out of range inputs.
   STRICT_FCVT_W_RV64 = ISD::FIRST_TARGET_STRICTFP_OPCODE,

diff  --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZicond.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZicond.td
index 42b77be6804270..ab0b93d62af5f3 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoZicond.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZicond.td
@@ -13,6 +13,13 @@
 //
 //===----------------------------------------------------------------------===//
 
+//===----------------------------------------------------------------------===//
+// RISC-V specific DAG Nodes.
+//===----------------------------------------------------------------------===//
+
+def riscv_czero_eqz : SDNode<"RISCVISD::CZERO_EQZ", SDTIntBinOp>;
+def riscv_czero_nez : SDNode<"RISCVISD::CZERO_NEZ", SDTIntBinOp>;
+
 //===----------------------------------------------------------------------===//
 // Instructions
 //===----------------------------------------------------------------------===//
@@ -29,33 +36,8 @@ def CZERO_NEZ : ALU_rr<0b0000111, 0b111, "czero.nez">,
 //===----------------------------------------------------------------------===//
 
 let Predicates = [HasStdExtZicond] in {
-// Directly use CZERO_EQZ/CZERO_NEZ in case of any of the operands being 0.
-def : Pat<(XLenVT (select (XLenVT GPR:$rc), GPR:$rs1, 0)),
-          (CZERO_EQZ GPR:$rs1, GPR:$rc)>;
-def : Pat<(XLenVT (select (XLenVT GPR:$rc), 0, GPR:$rs1)),
-          (CZERO_NEZ GPR:$rs1, GPR:$rc)>;
-
-def : Pat<(XLenVT (select (riscv_setne (XLenVT GPR:$rc)), GPR:$rs1, 0)),
+def : Pat<(XLenVT (riscv_czero_eqz GPR:$rs1, GPR:$rc)),
           (CZERO_EQZ GPR:$rs1, GPR:$rc)>;
-def : Pat<(XLenVT (select (riscv_seteq (XLenVT GPR:$rc)), GPR:$rs1, 0)),
-          (CZERO_NEZ GPR:$rs1, GPR:$rc)>;
-def : Pat<(XLenVT (select (riscv_setne (XLenVT GPR:$rc)), 0, GPR:$rs1)),
+def : Pat<(XLenVT (riscv_czero_nez GPR:$rs1, GPR:$rc)),
           (CZERO_NEZ GPR:$rs1, GPR:$rc)>;
-def : Pat<(XLenVT (select (riscv_seteq (XLenVT GPR:$rc)), 0, GPR:$rs1)),
-          (CZERO_EQZ GPR:$rs1, GPR:$rc)>;
-
-// Conditional AND operation patterns.
-def : Pat<(XLenVT (select (XLenVT GPR:$rc), (and GPR:$rs1, GPR:$rs2), GPR:$rs1)),
-          (OR (AND $rs1, $rs2), (CZERO_NEZ $rs1, $rc))>;
-def : Pat<(XLenVT (select (XLenVT GPR:$rc), GPR:$rs1, (and GPR:$rs1, GPR:$rs2))),
-          (OR (AND $rs1, $rs2), (CZERO_EQZ $rs1, $rc))>;
-
-// Basic select pattern that selects between 2 registers.
-def : Pat<(XLenVT (select (XLenVT GPR:$rc), GPR:$rs1, GPR:$rs2)),
-          (OR (CZERO_EQZ $rs1, $rc), (CZERO_NEZ $rs2, $rc))>;
-
-def : Pat<(XLenVT (select (riscv_setne (XLenVT GPR:$rc)), GPR:$rs1, GPR:$rs2)),
-          (OR (CZERO_EQZ GPR:$rs1, GPR:$rc), (CZERO_NEZ GPR:$rs2, GPR:$rc))>;
-def : Pat<(XLenVT (select (riscv_seteq (XLenVT GPR:$rc)), GPR:$rs2, GPR:$rs1)),
-          (OR (CZERO_EQZ GPR:$rs1, GPR:$rc), (CZERO_NEZ GPR:$rs2, GPR:$rc))>;
 } // Predicates = [HasStdExtZicond]

diff  --git a/llvm/test/CodeGen/RISCV/condops.ll b/llvm/test/CodeGen/RISCV/condops.ll
index 1daa04a8ac372b..f5907321078f72 100644
--- a/llvm/test/CodeGen/RISCV/condops.ll
+++ b/llvm/test/CodeGen/RISCV/condops.ll
@@ -527,20 +527,20 @@ define i64 @and1(i1 zeroext %rc, i64 %rs1, i64 %rs2) {
 ;
 ; RV32ZICOND-LABEL: and1:
 ; RV32ZICOND:       # %bb.0:
-; RV32ZICOND-NEXT:    czero.nez a5, a1, a0
-; RV32ZICOND-NEXT:    and a1, a1, a3
-; RV32ZICOND-NEXT:    or a3, a1, a5
-; RV32ZICOND-NEXT:    czero.nez a0, a2, a0
-; RV32ZICOND-NEXT:    and a1, a2, a4
-; RV32ZICOND-NEXT:    or a1, a1, a0
+; RV32ZICOND-NEXT:    and a4, a2, a4
+; RV32ZICOND-NEXT:    and a3, a1, a3
+; RV32ZICOND-NEXT:    czero.nez a1, a1, a0
+; RV32ZICOND-NEXT:    or a3, a3, a1
+; RV32ZICOND-NEXT:    czero.nez a1, a2, a0
+; RV32ZICOND-NEXT:    or a1, a4, a1
 ; RV32ZICOND-NEXT:    mv a0, a3
 ; RV32ZICOND-NEXT:    ret
 ;
 ; RV64ZICOND-LABEL: and1:
 ; RV64ZICOND:       # %bb.0:
+; RV64ZICOND-NEXT:    and a2, a1, a2
 ; RV64ZICOND-NEXT:    czero.nez a0, a1, a0
-; RV64ZICOND-NEXT:    and a1, a1, a2
-; RV64ZICOND-NEXT:    or a0, a1, a0
+; RV64ZICOND-NEXT:    or a0, a2, a0
 ; RV64ZICOND-NEXT:    ret
   %and = and i64 %rs1, %rs2
   %sel = select i1 %rc, i64 %and, i64 %rs1
@@ -564,19 +564,19 @@ define i64 @and2(i1 zeroext %rc, i64 %rs1, i64 %rs2) {
 ;
 ; RV32ZICOND-LABEL: and2:
 ; RV32ZICOND:       # %bb.0:
-; RV32ZICOND-NEXT:    czero.nez a5, a3, a0
-; RV32ZICOND-NEXT:    and a1, a3, a1
-; RV32ZICOND-NEXT:    or a3, a1, a5
-; RV32ZICOND-NEXT:    czero.nez a0, a4, a0
-; RV32ZICOND-NEXT:    and a1, a4, a2
-; RV32ZICOND-NEXT:    or a1, a1, a0
-; RV32ZICOND-NEXT:    mv a0, a3
+; RV32ZICOND-NEXT:    and a5, a2, a4
+; RV32ZICOND-NEXT:    and a1, a1, a3
+; RV32ZICOND-NEXT:    czero.nez a2, a3, a0
+; RV32ZICOND-NEXT:    or a2, a1, a2
+; RV32ZICOND-NEXT:    czero.nez a1, a4, a0
+; RV32ZICOND-NEXT:    or a1, a5, a1
+; RV32ZICOND-NEXT:    mv a0, a2
 ; RV32ZICOND-NEXT:    ret
 ;
 ; RV64ZICOND-LABEL: and2:
 ; RV64ZICOND:       # %bb.0:
+; RV64ZICOND-NEXT:    and a1, a1, a2
 ; RV64ZICOND-NEXT:    czero.nez a0, a2, a0
-; RV64ZICOND-NEXT:    and a1, a2, a1
 ; RV64ZICOND-NEXT:    or a0, a1, a0
 ; RV64ZICOND-NEXT:    ret
   %and = and i64 %rs1, %rs2
@@ -601,20 +601,20 @@ define i64 @and3(i1 zeroext %rc, i64 %rs1, i64 %rs2) {
 ;
 ; RV32ZICOND-LABEL: and3:
 ; RV32ZICOND:       # %bb.0:
-; RV32ZICOND-NEXT:    czero.eqz a5, a1, a0
-; RV32ZICOND-NEXT:    and a1, a1, a3
-; RV32ZICOND-NEXT:    or a3, a1, a5
-; RV32ZICOND-NEXT:    czero.eqz a0, a2, a0
-; RV32ZICOND-NEXT:    and a1, a2, a4
-; RV32ZICOND-NEXT:    or a1, a1, a0
+; RV32ZICOND-NEXT:    and a4, a2, a4
+; RV32ZICOND-NEXT:    and a3, a1, a3
+; RV32ZICOND-NEXT:    czero.eqz a1, a1, a0
+; RV32ZICOND-NEXT:    or a3, a3, a1
+; RV32ZICOND-NEXT:    czero.eqz a1, a2, a0
+; RV32ZICOND-NEXT:    or a1, a4, a1
 ; RV32ZICOND-NEXT:    mv a0, a3
 ; RV32ZICOND-NEXT:    ret
 ;
 ; RV64ZICOND-LABEL: and3:
 ; RV64ZICOND:       # %bb.0:
+; RV64ZICOND-NEXT:    and a2, a1, a2
 ; RV64ZICOND-NEXT:    czero.eqz a0, a1, a0
-; RV64ZICOND-NEXT:    and a1, a1, a2
-; RV64ZICOND-NEXT:    or a0, a1, a0
+; RV64ZICOND-NEXT:    or a0, a2, a0
 ; RV64ZICOND-NEXT:    ret
   %and = and i64 %rs1, %rs2
   %sel = select i1 %rc, i64 %rs1, i64 %and
@@ -638,19 +638,19 @@ define i64 @and4(i1 zeroext %rc, i64 %rs1, i64 %rs2) {
 ;
 ; RV32ZICOND-LABEL: and4:
 ; RV32ZICOND:       # %bb.0:
-; RV32ZICOND-NEXT:    czero.eqz a5, a3, a0
-; RV32ZICOND-NEXT:    and a1, a3, a1
-; RV32ZICOND-NEXT:    or a3, a1, a5
-; RV32ZICOND-NEXT:    czero.eqz a0, a4, a0
-; RV32ZICOND-NEXT:    and a1, a4, a2
-; RV32ZICOND-NEXT:    or a1, a1, a0
-; RV32ZICOND-NEXT:    mv a0, a3
+; RV32ZICOND-NEXT:    and a5, a2, a4
+; RV32ZICOND-NEXT:    and a1, a1, a3
+; RV32ZICOND-NEXT:    czero.eqz a2, a3, a0
+; RV32ZICOND-NEXT:    or a2, a1, a2
+; RV32ZICOND-NEXT:    czero.eqz a1, a4, a0
+; RV32ZICOND-NEXT:    or a1, a5, a1
+; RV32ZICOND-NEXT:    mv a0, a2
 ; RV32ZICOND-NEXT:    ret
 ;
 ; RV64ZICOND-LABEL: and4:
 ; RV64ZICOND:       # %bb.0:
+; RV64ZICOND-NEXT:    and a1, a1, a2
 ; RV64ZICOND-NEXT:    czero.eqz a0, a2, a0
-; RV64ZICOND-NEXT:    and a1, a2, a1
 ; RV64ZICOND-NEXT:    or a0, a1, a0
 ; RV64ZICOND-NEXT:    ret
   %and = and i64 %rs1, %rs2
@@ -839,23 +839,26 @@ define i64 @setge(i64 %a, i64 %b, i64 %rs1, i64 %rs2) {
 ; RV32ZICOND:       # %bb.0:
 ; RV32ZICOND-NEXT:    xor t0, a1, a3
 ; RV32ZICOND-NEXT:    sltu a0, a0, a2
+; RV32ZICOND-NEXT:    xori a0, a0, 1
 ; RV32ZICOND-NEXT:    czero.nez a0, a0, t0
 ; RV32ZICOND-NEXT:    slt a1, a1, a3
+; RV32ZICOND-NEXT:    xori a1, a1, 1
 ; RV32ZICOND-NEXT:    czero.eqz a1, a1, t0
 ; RV32ZICOND-NEXT:    or a1, a1, a0
-; RV32ZICOND-NEXT:    czero.nez a0, a4, a1
-; RV32ZICOND-NEXT:    czero.eqz a2, a6, a1
+; RV32ZICOND-NEXT:    czero.nez a0, a6, a1
+; RV32ZICOND-NEXT:    czero.eqz a2, a4, a1
 ; RV32ZICOND-NEXT:    or a0, a2, a0
-; RV32ZICOND-NEXT:    czero.nez a2, a5, a1
-; RV32ZICOND-NEXT:    czero.eqz a1, a7, a1
+; RV32ZICOND-NEXT:    czero.nez a2, a7, a1
+; RV32ZICOND-NEXT:    czero.eqz a1, a5, a1
 ; RV32ZICOND-NEXT:    or a1, a1, a2
 ; RV32ZICOND-NEXT:    ret
 ;
 ; RV64ZICOND-LABEL: setge:
 ; RV64ZICOND:       # %bb.0:
 ; RV64ZICOND-NEXT:    slt a0, a0, a1
-; RV64ZICOND-NEXT:    czero.nez a1, a2, a0
-; RV64ZICOND-NEXT:    czero.eqz a0, a3, a0
+; RV64ZICOND-NEXT:    xori a0, a0, 1
+; RV64ZICOND-NEXT:    czero.nez a1, a3, a0
+; RV64ZICOND-NEXT:    czero.eqz a0, a2, a0
 ; RV64ZICOND-NEXT:    or a0, a0, a1
 ; RV64ZICOND-NEXT:    ret
   %rc = icmp sge i64 %a, %b
@@ -927,23 +930,26 @@ define i64 @setle(i64 %a, i64 %b, i64 %rs1, i64 %rs2) {
 ; RV32ZICOND:       # %bb.0:
 ; RV32ZICOND-NEXT:    xor t0, a1, a3
 ; RV32ZICOND-NEXT:    sltu a0, a2, a0
+; RV32ZICOND-NEXT:    xori a0, a0, 1
 ; RV32ZICOND-NEXT:    czero.nez a0, a0, t0
 ; RV32ZICOND-NEXT:    slt a1, a3, a1
+; RV32ZICOND-NEXT:    xori a1, a1, 1
 ; RV32ZICOND-NEXT:    czero.eqz a1, a1, t0
 ; RV32ZICOND-NEXT:    or a1, a1, a0
-; RV32ZICOND-NEXT:    czero.nez a0, a4, a1
-; RV32ZICOND-NEXT:    czero.eqz a2, a6, a1
+; RV32ZICOND-NEXT:    czero.nez a0, a6, a1
+; RV32ZICOND-NEXT:    czero.eqz a2, a4, a1
 ; RV32ZICOND-NEXT:    or a0, a2, a0
-; RV32ZICOND-NEXT:    czero.nez a2, a5, a1
-; RV32ZICOND-NEXT:    czero.eqz a1, a7, a1
+; RV32ZICOND-NEXT:    czero.nez a2, a7, a1
+; RV32ZICOND-NEXT:    czero.eqz a1, a5, a1
 ; RV32ZICOND-NEXT:    or a1, a1, a2
 ; RV32ZICOND-NEXT:    ret
 ;
 ; RV64ZICOND-LABEL: setle:
 ; RV64ZICOND:       # %bb.0:
 ; RV64ZICOND-NEXT:    slt a0, a1, a0
-; RV64ZICOND-NEXT:    czero.nez a1, a2, a0
-; RV64ZICOND-NEXT:    czero.eqz a0, a3, a0
+; RV64ZICOND-NEXT:    xori a0, a0, 1
+; RV64ZICOND-NEXT:    czero.nez a1, a3, a0
+; RV64ZICOND-NEXT:    czero.eqz a0, a2, a0
 ; RV64ZICOND-NEXT:    or a0, a0, a1
 ; RV64ZICOND-NEXT:    ret
   %rc = icmp sle i64 %a, %b
@@ -1015,23 +1021,26 @@ define i64 @setuge(i64 %a, i64 %b, i64 %rs1, i64 %rs2) {
 ; RV32ZICOND:       # %bb.0:
 ; RV32ZICOND-NEXT:    xor t0, a1, a3
 ; RV32ZICOND-NEXT:    sltu a0, a0, a2
+; RV32ZICOND-NEXT:    xori a0, a0, 1
 ; RV32ZICOND-NEXT:    czero.nez a0, a0, t0
 ; RV32ZICOND-NEXT:    sltu a1, a1, a3
+; RV32ZICOND-NEXT:    xori a1, a1, 1
 ; RV32ZICOND-NEXT:    czero.eqz a1, a1, t0
 ; RV32ZICOND-NEXT:    or a1, a1, a0
-; RV32ZICOND-NEXT:    czero.nez a0, a4, a1
-; RV32ZICOND-NEXT:    czero.eqz a2, a6, a1
+; RV32ZICOND-NEXT:    czero.nez a0, a6, a1
+; RV32ZICOND-NEXT:    czero.eqz a2, a4, a1
 ; RV32ZICOND-NEXT:    or a0, a2, a0
-; RV32ZICOND-NEXT:    czero.nez a2, a5, a1
-; RV32ZICOND-NEXT:    czero.eqz a1, a7, a1
+; RV32ZICOND-NEXT:    czero.nez a2, a7, a1
+; RV32ZICOND-NEXT:    czero.eqz a1, a5, a1
 ; RV32ZICOND-NEXT:    or a1, a1, a2
 ; RV32ZICOND-NEXT:    ret
 ;
 ; RV64ZICOND-LABEL: setuge:
 ; RV64ZICOND:       # %bb.0:
 ; RV64ZICOND-NEXT:    sltu a0, a0, a1
-; RV64ZICOND-NEXT:    czero.nez a1, a2, a0
-; RV64ZICOND-NEXT:    czero.eqz a0, a3, a0
+; RV64ZICOND-NEXT:    xori a0, a0, 1
+; RV64ZICOND-NEXT:    czero.nez a1, a3, a0
+; RV64ZICOND-NEXT:    czero.eqz a0, a2, a0
 ; RV64ZICOND-NEXT:    or a0, a0, a1
 ; RV64ZICOND-NEXT:    ret
   %rc = icmp uge i64 %a, %b
@@ -1103,23 +1112,26 @@ define i64 @setule(i64 %a, i64 %b, i64 %rs1, i64 %rs2) {
 ; RV32ZICOND:       # %bb.0:
 ; RV32ZICOND-NEXT:    xor t0, a1, a3
 ; RV32ZICOND-NEXT:    sltu a0, a2, a0
+; RV32ZICOND-NEXT:    xori a0, a0, 1
 ; RV32ZICOND-NEXT:    czero.nez a0, a0, t0
 ; RV32ZICOND-NEXT:    sltu a1, a3, a1
+; RV32ZICOND-NEXT:    xori a1, a1, 1
 ; RV32ZICOND-NEXT:    czero.eqz a1, a1, t0
 ; RV32ZICOND-NEXT:    or a1, a1, a0
-; RV32ZICOND-NEXT:    czero.nez a0, a4, a1
-; RV32ZICOND-NEXT:    czero.eqz a2, a6, a1
+; RV32ZICOND-NEXT:    czero.nez a0, a6, a1
+; RV32ZICOND-NEXT:    czero.eqz a2, a4, a1
 ; RV32ZICOND-NEXT:    or a0, a2, a0
-; RV32ZICOND-NEXT:    czero.nez a2, a5, a1
-; RV32ZICOND-NEXT:    czero.eqz a1, a7, a1
+; RV32ZICOND-NEXT:    czero.nez a2, a7, a1
+; RV32ZICOND-NEXT:    czero.eqz a1, a5, a1
 ; RV32ZICOND-NEXT:    or a1, a1, a2
 ; RV32ZICOND-NEXT:    ret
 ;
 ; RV64ZICOND-LABEL: setule:
 ; RV64ZICOND:       # %bb.0:
 ; RV64ZICOND-NEXT:    sltu a0, a1, a0
-; RV64ZICOND-NEXT:    czero.nez a1, a2, a0
-; RV64ZICOND-NEXT:    czero.eqz a0, a3, a0
+; RV64ZICOND-NEXT:    xori a0, a0, 1
+; RV64ZICOND-NEXT:    czero.nez a1, a3, a0
+; RV64ZICOND-NEXT:    czero.eqz a0, a2, a0
 ; RV64ZICOND-NEXT:    or a0, a0, a1
 ; RV64ZICOND-NEXT:    ret
   %rc = icmp ule i64 %a, %b

diff  --git a/llvm/test/CodeGen/RISCV/select.ll b/llvm/test/CodeGen/RISCV/select.ll
index 94b95b352e284e..7c49010a85c659 100644
--- a/llvm/test/CodeGen/RISCV/select.ll
+++ b/llvm/test/CodeGen/RISCV/select.ll
@@ -851,8 +851,8 @@ define i32 @select_and_1(i1 zeroext %cond, i32 %a, i32 %b) {
 ;
 ; CHECKZICOND-LABEL: select_and_1:
 ; CHECKZICOND:       # %bb.0: # %entry
+; CHECKZICOND-NEXT:    and a1, a1, a2
 ; CHECKZICOND-NEXT:    czero.nez a0, a2, a0
-; CHECKZICOND-NEXT:    and a1, a2, a1
 ; CHECKZICOND-NEXT:    or a0, a1, a0
 ; CHECKZICOND-NEXT:    ret
 entry:
@@ -889,9 +889,9 @@ define i32 @select_and_2(i1 zeroext %cond, i32 %a, i32 %b) {
 ;
 ; CHECKZICOND-LABEL: select_and_2:
 ; CHECKZICOND:       # %bb.0: # %entry
+; CHECKZICOND-NEXT:    and a2, a1, a2
 ; CHECKZICOND-NEXT:    czero.eqz a0, a1, a0
-; CHECKZICOND-NEXT:    and a1, a1, a2
-; CHECKZICOND-NEXT:    or a0, a1, a0
+; CHECKZICOND-NEXT:    or a0, a2, a0
 ; CHECKZICOND-NEXT:    ret
 entry:
   %c = and i32 %a, %b
@@ -928,10 +928,9 @@ define i32 @select_and_3(i1 zeroext %cond, i32 %a) {
 ;
 ; CHECKZICOND-LABEL: select_and_3:
 ; CHECKZICOND:       # %bb.0: # %entry
+; CHECKZICOND-NEXT:    andi a2, a1, 42
 ; CHECKZICOND-NEXT:    czero.eqz a0, a1, a0
-; CHECKZICOND-NEXT:    li a2, 42
-; CHECKZICOND-NEXT:    and a1, a1, a2
-; CHECKZICOND-NEXT:    or a0, a1, a0
+; CHECKZICOND-NEXT:    or a0, a2, a0
 ; CHECKZICOND-NEXT:    ret
 entry:
   %c = and i32 %a, 42


        


More information about the llvm-commits mailing list