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 @@ -188,6 +188,13 @@ setOperationAction(ISD::BRCOND, MVT::Other, Custom); setOperationAction(ISD::SELECT_CC, XLenVT, Expand); + setCondCodeAction(ISD::SETLE, XLenVT, Expand); + setCondCodeAction(ISD::SETGT, XLenVT, Custom); + setCondCodeAction(ISD::SETGE, XLenVT, Expand); + setCondCodeAction(ISD::SETULE, XLenVT, Expand); + setCondCodeAction(ISD::SETUGT, XLenVT, Custom); + setCondCodeAction(ISD::SETUGE, XLenVT, Expand); + setOperationAction({ISD::STACKSAVE, ISD::STACKRESTORE}, MVT::Other, Expand); setOperationAction(ISD::VASTART, MVT::Other, Custom); @@ -3590,8 +3597,63 @@ case ISD::MSTORE: case ISD::VP_STORE: return lowerMaskedStore(Op, DAG); - case ISD::SETCC: + case ISD::SELECT_CC: { + // This occurs because we custom legalize SETGT and SETUGT for setcc. That + // causes LegalizeDAG to think we need to custom legalize select_cc. Expand + // into separate SETCC+SELECT_CC just like LegalizeDAG. + SDValue Tmp1 = Op.getOperand(0); + SDValue Tmp2 = Op.getOperand(1); + SDValue True = Op.getOperand(2); + SDValue False = Op.getOperand(3); + EVT VT = Op.getValueType(); + SDValue CC = Op.getOperand(4); + EVT CmpVT = Tmp1.getValueType(); + EVT CCVT = + getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), CmpVT); + SDLoc DL(Op); + SDValue Cond = + DAG.getNode(ISD::SETCC, DL, CCVT, Tmp1, Tmp2, CC, Op->getFlags()); + return DAG.getSelect(DL, VT, Cond, True, False); + } + case ISD::SETCC: { + MVT OpVT = Op.getOperand(0).getSimpleValueType(); + if (OpVT.isScalarInteger()) { + MVT VT = Op.getSimpleValueType(); + SDValue LHS = Op.getOperand(0); + SDValue RHS = Op.getOperand(1); + ISD::CondCode CCVal = cast(Op.getOperand(2))->get(); + assert((CCVal == ISD::SETGT || CCVal == ISD::SETUGT) && + "Unexpected CondCode"); + // Swap the operands and condition code to SETLT/SETULT. + CCVal = ISD::getSetCCSwappedOperands(CCVal); + std::swap(LHS, RHS); + + SDLoc DL(Op); + // If the LHS is a constant, we're now forced to put it in a register. + // If the constant is in the range [-2049, 0) or (0, 2046], we can + // increment the constant and use slti(u)+xori without swapping the + // operands. This is equivalent to (set(u)ge OrigLHS, OrigRHS+1). + // FIXME: Is the one use check here necessary? It was copied when this + // was moved from an isel pattern. + if (isa(LHS) && RHS.hasOneUse()) { + int64_t Imm = cast(RHS)->getSExtValue(); + if (Imm != 0 && Imm != INT64_MAX && isInt<12>(Imm + 1)) { + // If the constant is -1 and this an unsigned compare, we can't + // increment the immediate but the result is always false. + if (Imm == -1 && CCVal == ISD::SETULT) + return DAG.getConstant(0, DL, VT); + SDValue SetCC = DAG.getSetCC( + DL, VT, RHS, DAG.getConstant(Imm + 1, DL, OpVT), CCVal); + return DAG.getLogicalNOT(DL, SetCC, VT); + } + } + + // Not a constant we could handle, create a swapped setcc. + return DAG.getSetCC(DL, VT, LHS, RHS, CCVal); + } + return lowerFixedLengthVectorSetccToRVV(Op, DAG); + } case ISD::ADD: return lowerToScalableOp(Op, DAG, RISCVISD::ADD_VL, /*HasMergeOp*/ true); case ISD::SUB: @@ -8304,6 +8366,17 @@ } } + // Fold (neg (xor (setcc), 1)) -> (add (setcc), -1) + // The is equivalent to 1-X and negating gives X-1. + if (isNullConstant(N0) && N1.getOpcode() == ISD::XOR && + N1.getOperand(0).getOpcode() == ISD::SETCC && + isOneConstant(N1.getOperand(1))) { + SDLoc dl(N); + EVT VT = N->getValueType(0); + return DAG.getNode(ISD::ADD, dl, VT, N1.getOperand(0), + DAG.getConstant(-1, dl, VT)); + } + // fold (sub x, (select lhs, rhs, cc, 0, y)) -> // (select lhs, rhs, cc, x, (sub x, y)) return combineSelectAndUse(N, N1, N0, DAG, /*AllOnes*/ false); diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td @@ -1272,51 +1272,6 @@ def : Pat<(setne GPR:$rs1, -2048), (SLTU X0, (XORI GPR:$rs1, -2048))>; def : Pat<(setne GPR:$rs1, -1), (SLTIU GPR:$rs1, -1)>; -def : Pat<(setugt GPR:$rs1, GPR:$rs2), (SLTU GPR:$rs2, GPR:$rs1)>; -def : Pat<(setuge GPR:$rs1, GPR:$rs2), (XORI (SLTU GPR:$rs1, GPR:$rs2), 1)>; -def : Pat<(setule GPR:$rs1, GPR:$rs2), (XORI (SLTU GPR:$rs2, GPR:$rs1), 1)>; -def : Pat<(setgt GPR:$rs1, GPR:$rs2), (SLT GPR:$rs2, GPR:$rs1)>; -def : Pat<(setge GPR:$rs1, GPR:$rs2), (XORI (SLT GPR:$rs1, GPR:$rs2), 1)>; -def : Pat<(setle GPR:$rs1, GPR:$rs2), (XORI (SLT GPR:$rs2, GPR:$rs1), 1)>; -def : Pat<(setgt GPR:$rs1, simm12_minus1_nonzero:$imm), - (XORI (SLTI GPR:$rs1, (ImmPlus1 simm12_minus1_nonzero:$imm)), 1)>; -def : Pat<(setugt GPR:$rs1, simm12_minus1_nonzero:$imm), - (XORI (SLTIU GPR:$rs1, (ImmPlus1 simm12_minus1_nonzero:$imm)), 1)>; - -// If negating a pattern that requires an XORI above, we can fold the XORI with -// the NEG. The XORI is equivalent to 1-X and negating gives X-1. -def : Pat<(ineg (setuge GPR:$rs1, GPR:$rs2)), - (ADDI (SLTU GPR:$rs1, GPR:$rs2), -1)>; -def : Pat<(ineg (setule GPR:$rs1, GPR:$rs2)), - (ADDI (SLTU GPR:$rs2, GPR:$rs1), -1)>; -def : Pat<(ineg (setge GPR:$rs1, GPR:$rs2)), - (ADDI (SLT GPR:$rs1, GPR:$rs2), -1)>; -def : Pat<(ineg (setle GPR:$rs1, GPR:$rs2)), - (ADDI (SLT GPR:$rs2, GPR:$rs1), -1)>; -def : Pat<(ineg (setgt GPR:$rs1, simm12_minus1_nonzero:$imm)), - (ADDI (SLTI GPR:$rs1, (ImmPlus1 simm12_minus1_nonzero:$imm)), -1)>; -def : Pat<(ineg (setugt GPR:$rs1, simm12_minus1_nonzero:$imm)), - (ADDI (SLTIU GPR:$rs1, (ImmPlus1 simm12_minus1_nonzero:$imm)), -1)>; - -def ineg_allwusers : PatFrag<(ops node:$src), - (ineg node:$src), [{ - return hasAllWUsers(Node); -}]>; - -let Predicates = [IsRV64] in { -def : Pat<(ineg_allwusers (setuge GPR:$rs1, GPR:$rs2)), - (ADDIW (SLTU GPR:$rs1, GPR:$rs2), -1)>; -def : Pat<(ineg_allwusers (setule GPR:$rs1, GPR:$rs2)), - (ADDIW (SLTU GPR:$rs2, GPR:$rs1), -1)>; -def : Pat<(ineg_allwusers (setge GPR:$rs1, GPR:$rs2)), - (ADDIW (SLT GPR:$rs1, GPR:$rs2), -1)>; -def : Pat<(ineg_allwusers (setle GPR:$rs1, GPR:$rs2)), - (ADDIW (SLT GPR:$rs2, GPR:$rs1), -1)>; -def : Pat<(ineg_allwusers (setgt GPR:$rs1, simm12_minus1_nonzero:$imm)), - (ADDIW (SLTI GPR:$rs1, (ImmPlus1 simm12_minus1_nonzero:$imm)), -1)>; -def : Pat<(ineg_allwusers (setugt GPR:$rs1, simm12_minus1_nonzero:$imm)), - (ADDIW (SLTIU GPR:$rs1, (ImmPlus1 simm12_minus1_nonzero:$imm)), -1)>; -} def IntCCtoRISCVCC : SDNodeXForm(N->getOperand(2))->get(); diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td @@ -997,20 +997,6 @@ (CMOV GPR:$rs1, (XOR GPR:$x, GPR:$y), GPR:$rs3)>; def : Pat<(select (XLenVT (seteq GPR:$x, GPR:$y)), GPR:$rs3, GPR:$rs1), (CMOV GPR:$rs1, (XOR GPR:$x, GPR:$y), GPR:$rs3)>; -def : Pat<(select (XLenVT (setuge GPR:$x, GPR:$y)), GPR:$rs3, GPR:$rs1), - (CMOV GPR:$rs1, (SLTU GPR:$x, GPR:$y), GPR:$rs3)>; -def : Pat<(select (XLenVT (setule GPR:$y, GPR:$x)), GPR:$rs3, GPR:$rs1), - (CMOV GPR:$rs1, (SLTU GPR:$x, GPR:$y), GPR:$rs3)>; -def : Pat<(select (XLenVT (setge GPR:$x, GPR:$y)), GPR:$rs3, GPR:$rs1), - (CMOV GPR:$rs1, (SLT GPR:$x, GPR:$y), GPR:$rs3)>; -def : Pat<(select (XLenVT (setle GPR:$y, GPR:$x)), GPR:$rs3, GPR:$rs1), - (CMOV GPR:$rs1, (SLT GPR:$x, GPR:$y), GPR:$rs3)>; - -// setge X, Imm is canonicalized to setgt X, (Imm - 1). -def : Pat<(select (XLenVT (setgt GPR:$x, simm12_minus1_nonzero:$imm)), GPR:$rs3, GPR:$rs1), - (CMOV GPR:$rs1, (SLTI GPR:$x, (ImmPlus1 simm12_minus1_nonzero:$imm)), GPR:$rs3)>; -def : Pat<(select (XLenVT (setugt GPR:$x, simm12_minus1_nonzero:$imm)), GPR:$rs3, GPR:$rs1), - (CMOV GPR:$rs1, (SLTIU GPR:$x, (ImmPlus1 simm12_minus1_nonzero:$imm)), GPR:$rs3)>; def : Pat<(select GPR:$rs2, GPR:$rs1, GPR:$rs3), (CMOV GPR:$rs1, GPR:$rs2, GPR:$rs3)>; diff --git a/llvm/test/CodeGen/RISCV/rv32zbt.ll b/llvm/test/CodeGen/RISCV/rv32zbt.ll --- a/llvm/test/CodeGen/RISCV/rv32zbt.ll +++ b/llvm/test/CodeGen/RISCV/rv32zbt.ll @@ -648,14 +648,12 @@ ; ; RV32ZBT-LABEL: cmov_sle_i64: ; RV32ZBT: # %bb.0: -; RV32ZBT-NEXT: xor t0, a3, a5 ; RV32ZBT-NEXT: sltu a2, a4, a2 -; RV32ZBT-NEXT: xori a2, a2, 1 +; RV32ZBT-NEXT: xor a4, a3, a5 ; RV32ZBT-NEXT: slt a3, a5, a3 -; RV32ZBT-NEXT: xori a3, a3, 1 -; RV32ZBT-NEXT: cmov a2, t0, a3, a2 -; RV32ZBT-NEXT: cmov a0, a2, a0, a6 -; RV32ZBT-NEXT: cmov a1, a2, a1, a7 +; RV32ZBT-NEXT: cmov a2, a4, a3, a2 +; RV32ZBT-NEXT: cmov a0, a2, a6, a0 +; RV32ZBT-NEXT: cmov a1, a2, a7, a1 ; RV32ZBT-NEXT: ret %tobool = icmp sle i64 %b, %c %cond = select i1 %tobool, i64 %a, i64 %d @@ -683,14 +681,12 @@ ; ; RV32ZBT-LABEL: cmov_sge_i64: ; RV32ZBT: # %bb.0: -; RV32ZBT-NEXT: xor t0, a3, a5 ; RV32ZBT-NEXT: sltu a2, a2, a4 -; RV32ZBT-NEXT: xori a2, a2, 1 +; RV32ZBT-NEXT: xor a4, a3, a5 ; RV32ZBT-NEXT: slt a3, a3, a5 -; RV32ZBT-NEXT: xori a3, a3, 1 -; RV32ZBT-NEXT: cmov a2, t0, a3, a2 -; RV32ZBT-NEXT: cmov a0, a2, a0, a6 -; RV32ZBT-NEXT: cmov a1, a2, a1, a7 +; RV32ZBT-NEXT: cmov a2, a4, a3, a2 +; RV32ZBT-NEXT: cmov a0, a2, a6, a0 +; RV32ZBT-NEXT: cmov a1, a2, a7, a1 ; RV32ZBT-NEXT: ret %tobool = icmp sge i64 %b, %c %cond = select i1 %tobool, i64 %a, i64 %d @@ -718,14 +714,12 @@ ; ; RV32ZBT-LABEL: cmov_ule_i64: ; RV32ZBT: # %bb.0: -; RV32ZBT-NEXT: xor t0, a3, a5 ; RV32ZBT-NEXT: sltu a2, a4, a2 -; RV32ZBT-NEXT: xori a2, a2, 1 +; RV32ZBT-NEXT: xor a4, a3, a5 ; RV32ZBT-NEXT: sltu a3, a5, a3 -; RV32ZBT-NEXT: xori a3, a3, 1 -; RV32ZBT-NEXT: cmov a2, t0, a3, a2 -; RV32ZBT-NEXT: cmov a0, a2, a0, a6 -; RV32ZBT-NEXT: cmov a1, a2, a1, a7 +; RV32ZBT-NEXT: cmov a2, a4, a3, a2 +; RV32ZBT-NEXT: cmov a0, a2, a6, a0 +; RV32ZBT-NEXT: cmov a1, a2, a7, a1 ; RV32ZBT-NEXT: ret %tobool = icmp ule i64 %b, %c %cond = select i1 %tobool, i64 %a, i64 %d @@ -753,14 +747,12 @@ ; ; RV32ZBT-LABEL: cmov_uge_i64: ; RV32ZBT: # %bb.0: -; RV32ZBT-NEXT: xor t0, a3, a5 ; RV32ZBT-NEXT: sltu a2, a2, a4 -; RV32ZBT-NEXT: xori a2, a2, 1 +; RV32ZBT-NEXT: xor a4, a3, a5 ; RV32ZBT-NEXT: sltu a3, a3, a5 -; RV32ZBT-NEXT: xori a3, a3, 1 -; RV32ZBT-NEXT: cmov a2, t0, a3, a2 -; RV32ZBT-NEXT: cmov a0, a2, a0, a6 -; RV32ZBT-NEXT: cmov a1, a2, a1, a7 +; RV32ZBT-NEXT: cmov a2, a4, a3, a2 +; RV32ZBT-NEXT: cmov a0, a2, a6, a0 +; RV32ZBT-NEXT: cmov a1, a2, a7, a1 ; RV32ZBT-NEXT: ret %tobool = icmp uge i64 %b, %c %cond = select i1 %tobool, i64 %a, i64 %d diff --git a/llvm/test/CodeGen/RISCV/select-cc.ll b/llvm/test/CodeGen/RISCV/select-cc.ll --- a/llvm/test/CodeGen/RISCV/select-cc.ll +++ b/llvm/test/CodeGen/RISCV/select-cc.ll @@ -478,11 +478,11 @@ ; ; RV32ZBT-LABEL: select_sge_int32min: ; RV32ZBT: # %bb.0: +; RV32ZBT-NEXT: li a6, -1 +; RV32ZBT-NEXT: slt a6, a6, a1 ; RV32ZBT-NEXT: slti a0, a0, 0 -; RV32ZBT-NEXT: addi a6, a1, 1 -; RV32ZBT-NEXT: slti a1, a1, 0 -; RV32ZBT-NEXT: xori a1, a1, 1 -; RV32ZBT-NEXT: cmov a1, a6, a1, a0 +; RV32ZBT-NEXT: addi a1, a1, 1 +; RV32ZBT-NEXT: cmov a1, a1, a6, a0 ; RV32ZBT-NEXT: cmov a0, a1, a2, a4 ; RV32ZBT-NEXT: cmov a1, a1, a3, a5 ; RV32ZBT-NEXT: ret diff --git a/llvm/test/CodeGen/RISCV/urem-seteq-illegal-types.ll b/llvm/test/CodeGen/RISCV/urem-seteq-illegal-types.ll --- a/llvm/test/CodeGen/RISCV/urem-seteq-illegal-types.ll +++ b/llvm/test/CodeGen/RISCV/urem-seteq-illegal-types.ll @@ -343,7 +343,8 @@ ; RV32-NEXT: slli a0, a0, 21 ; RV32-NEXT: srli a0, a0, 22 ; RV32-NEXT: or a0, a0, a1 -; RV32-NEXT: andi s3, a0, 2047 +; RV32-NEXT: andi a0, a0, 2047 +; RV32-NEXT: sltiu s3, a0, 342 ; RV32-NEXT: li a1, 819 ; RV32-NEXT: mv a0, s1 ; RV32-NEXT: call __mulsi3@plt @@ -356,9 +357,8 @@ ; RV32-NEXT: call __mulsi3@plt ; RV32-NEXT: addi a0, a0, -1463 ; RV32-NEXT: andi a0, a0, 2047 -; RV32-NEXT: sltiu a1, s3, 342 -; RV32-NEXT: addi a1, a1, -1 ; RV32-NEXT: sltiu a0, a0, 293 +; RV32-NEXT: addi a1, s3, -1 ; RV32-NEXT: addi a0, a0, -1 ; RV32-NEXT: neg a2, s1 ; RV32-NEXT: slli a2, a2, 21 @@ -401,7 +401,8 @@ ; RV64-NEXT: slli a0, a0, 53 ; RV64-NEXT: srli a0, a0, 54 ; RV64-NEXT: or a0, a0, a1 -; RV64-NEXT: andi s3, a0, 2047 +; RV64-NEXT: andi a0, a0, 2047 +; RV64-NEXT: sltiu s3, a0, 342 ; RV64-NEXT: li a1, 819 ; RV64-NEXT: mv a0, s2 ; RV64-NEXT: call __muldi3@plt @@ -414,9 +415,8 @@ ; RV64-NEXT: call __muldi3@plt ; RV64-NEXT: addiw a0, a0, -1463 ; RV64-NEXT: andi a0, a0, 2047 -; RV64-NEXT: sltiu a1, s3, 342 -; RV64-NEXT: addiw a1, a1, -1 ; RV64-NEXT: sltiu a0, a0, 293 +; RV64-NEXT: addiw a1, s3, -1 ; RV64-NEXT: addiw a0, a0, -1 ; RV64-NEXT: andi a1, a1, 2047 ; RV64-NEXT: andi a0, a0, 2047 @@ -452,6 +452,7 @@ ; RV32M-NEXT: srli a2, a2, 22 ; RV32M-NEXT: or a2, a2, a4 ; RV32M-NEXT: andi a2, a2, 2047 +; RV32M-NEXT: sltiu a2, a2, 342 ; RV32M-NEXT: li a4, 819 ; RV32M-NEXT: mul a1, a1, a4 ; RV32M-NEXT: addi a1, a1, -1638 @@ -462,9 +463,8 @@ ; RV32M-NEXT: mul a3, a3, a4 ; RV32M-NEXT: addi a3, a3, -1463 ; RV32M-NEXT: andi a3, a3, 2047 -; RV32M-NEXT: sltiu a2, a2, 342 -; RV32M-NEXT: addi a2, a2, -1 ; RV32M-NEXT: sltiu a3, a3, 293 +; RV32M-NEXT: addi a2, a2, -1 ; RV32M-NEXT: addi a3, a3, -1 ; RV32M-NEXT: neg a4, a1 ; RV32M-NEXT: slli a4, a4, 21 @@ -495,6 +495,7 @@ ; RV64M-NEXT: srli a1, a1, 54 ; RV64M-NEXT: or a1, a1, a4 ; RV64M-NEXT: andi a1, a1, 2047 +; RV64M-NEXT: sltiu a1, a1, 342 ; RV64M-NEXT: li a4, 819 ; RV64M-NEXT: mulw a3, a3, a4 ; RV64M-NEXT: addiw a3, a3, -1638 @@ -505,9 +506,8 @@ ; RV64M-NEXT: mulw a2, a2, a4 ; RV64M-NEXT: addiw a2, a2, -1463 ; RV64M-NEXT: andi a2, a2, 2047 -; RV64M-NEXT: sltiu a1, a1, 342 -; RV64M-NEXT: addiw a1, a1, -1 ; RV64M-NEXT: sltiu a2, a2, 293 +; RV64M-NEXT: addiw a1, a1, -1 ; RV64M-NEXT: addiw a2, a2, -1 ; RV64M-NEXT: andi a1, a1, 2047 ; RV64M-NEXT: andi a2, a2, 2047 diff --git a/llvm/test/CodeGen/RISCV/xaluo.ll b/llvm/test/CodeGen/RISCV/xaluo.ll --- a/llvm/test/CodeGen/RISCV/xaluo.ll +++ b/llvm/test/CodeGen/RISCV/xaluo.ll @@ -786,10 +786,9 @@ ; RV32-LABEL: usubo.i32.constant.lhs: ; RV32: # %bb.0: # %entry ; RV32-NEXT: li a2, -2 -; RV32-NEXT: sub a2, a2, a0 -; RV32-NEXT: addi a0, a2, 1 -; RV32-NEXT: seqz a0, a0 -; RV32-NEXT: sw a2, 0(a1) +; RV32-NEXT: sub a3, a2, a0 +; RV32-NEXT: sltu a0, a2, a3 +; RV32-NEXT: sw a3, 0(a1) ; RV32-NEXT: ret ; ; RV64-LABEL: usubo.i32.constant.lhs: @@ -804,10 +803,9 @@ ; RV32ZBA-LABEL: usubo.i32.constant.lhs: ; RV32ZBA: # %bb.0: # %entry ; RV32ZBA-NEXT: li a2, -2 -; RV32ZBA-NEXT: sub a2, a2, a0 -; RV32ZBA-NEXT: addi a0, a2, 1 -; RV32ZBA-NEXT: seqz a0, a0 -; RV32ZBA-NEXT: sw a2, 0(a1) +; RV32ZBA-NEXT: sub a3, a2, a0 +; RV32ZBA-NEXT: sltu a0, a2, a3 +; RV32ZBA-NEXT: sw a3, 0(a1) ; RV32ZBA-NEXT: ret ; ; RV64ZBA-LABEL: usubo.i32.constant.lhs: