diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.h b/llvm/lib/Target/RISCV/RISCVISelLowering.h --- a/llvm/lib/Target/RISCV/RISCVISelLowering.h +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.h @@ -356,6 +356,11 @@ // 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/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -333,7 +333,7 @@ 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 @@ 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(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(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 @@ 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 @@ 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/RISCVInstrInfoZicond.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZicond.td --- 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 @@ //===----------------------------------------------------------------------===// 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 --- a/llvm/test/CodeGen/RISCV/condops.ll +++ b/llvm/test/CodeGen/RISCV/condops.ll @@ -527,20 +527,20 @@ ; ; 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 @@ ; ; 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 @@ ; ; 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 @@ ; ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 --- a/llvm/test/CodeGen/RISCV/select.ll +++ b/llvm/test/CodeGen/RISCV/select.ll @@ -851,8 +851,8 @@ ; ; 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 @@ ; ; 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 @@ ; ; 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