diff options
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 26 | ||||
-rw-r--r-- | llvm/lib/Target/RISCV/RISCVInstrInfoM.td | 31 |
2 files changed, 52 insertions, 5 deletions
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index ca6fbb16e55..508dcbd009e 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -525,6 +525,20 @@ static bool isVariableShift(SDValue Val) { } } +// Returns true if the given node is an sdiv, udiv, or urem with non-constant +// operands. +static bool isVariableSDivUDivURem(SDValue Val) { + switch (Val.getOpcode()) { + default: + return false; + case ISD::SDIV: + case ISD::UDIV: + case ISD::UREM: + return Val.getOperand(0).getOpcode() != ISD::Constant && + Val.getOperand(1).getOpcode() != ISD::Constant; + } +} + SDValue RISCVTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const { SelectionDAG &DAG = DCI.DAG; @@ -552,12 +566,14 @@ SDValue RISCVTargetLowering::PerformDAGCombine(SDNode *N, N, DAG.getNode(N->getOpcode(), DL, LHS.getValueType(), LHS, NewRHS)); } case ISD::ANY_EXTEND: { - // If any-extending an i32 variable-length shift to i64, then instead - // sign-extend in order to increase the chance of being able to select the - // sllw/srlw/sraw instruction. + // If any-extending an i32 variable-length shift or sdiv/udiv/urem to i64, + // then instead sign-extend in order to increase the chance of being able + // to select the sllw/srlw/sraw/divw/divuw/remuw instructions. SDValue Src = N->getOperand(0); - if (N->getValueType(0) != MVT::i64 || Src.getValueType() != MVT::i32 || - !isVariableShift(Src)) + if (N->getValueType(0) != MVT::i64 || Src.getValueType() != MVT::i32) + break; + if (!isVariableShift(Src) && + !(Subtarget.hasStdExtM() && isVariableSDivUDivURem(Src))) break; SDLoc DL(N); return DCI.CombineTo(N, DAG.getNode(ISD::SIGN_EXTEND, DL, MVT::i64, Src)); diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoM.td b/llvm/lib/Target/RISCV/RISCVInstrInfoM.td index 2dd10ada400..05dd3311ad5 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoM.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoM.td @@ -49,3 +49,34 @@ def : PatGprGpr<udiv, DIVU>; def : PatGprGpr<srem, REM>; def : PatGprGpr<urem, REMU>; } // Predicates = [HasStdExtM] + +let Predicates = [HasStdExtM, IsRV64] in { +def : Pat<(sext_inreg (mul GPR:$rs1, GPR:$rs2), i32), + (MULW GPR:$rs1, GPR:$rs2)>; +def : Pat<(sext_inreg (sdiv (sexti32 GPR:$rs1), + (sexti32 GPR:$rs2)), i32), + (DIVW GPR:$rs1, GPR:$rs2)>; +def : Pat<(zexti32 (sdiv (sexti32 GPR:$rs1), + (sexti32 GPR:$rs2))), + (SRLI (SLLI (DIVW GPR:$rs1, GPR:$rs2), 32), 32)>; +def : Pat<(sext_inreg (udiv (zexti32 GPR:$rs1), (zexti32 GPR:$rs2)), i32), + (DIVUW GPR:$rs1, GPR:$rs2)>; +// It's cheaper to perform a divuw and zero-extend the result than to +// zero-extend both inputs to a udiv. +def : Pat<(udiv (and GPR:$rs1, 0xffffffff), (and GPR:$rs2, 0xffffffff)), + (SRLI (SLLI (DIVUW GPR:$rs1, GPR:$rs2), 32), 32)>; +// Although the sexti32 operands may not have originated from an i32 srem, +// this pattern is safe as it is impossible for two sign extended inputs to +// produce a result where res[63:32]=0 and res[31]=1. +def : Pat<(srem (sexti32 GPR:$rs1), (sexti32 GPR:$rs2)), + (REMW GPR:$rs1, GPR:$rs2)>; +def : Pat<(sext_inreg (srem (sexti32 GPR:$rs1), + (sexti32 GPR:$rs2)), i32), + (REMW GPR:$rs1, GPR:$rs2)>; +def : Pat<(sext_inreg (urem (zexti32 GPR:$rs1), (zexti32 GPR:$rs2)), i32), + (REMUW GPR:$rs1, GPR:$rs2)>; +// It's cheaper to perform a remuw and zero-extend the result than to +// zero-extend both inputs to a urem. +def : Pat<(urem (and GPR:$rs1, 0xffffffff), (and GPR:$rs2, 0xffffffff)), + (SRLI (SLLI (REMUW GPR:$rs1, GPR:$rs2), 32), 32)>; +} // Predicates = [HasStdExtM, IsRV64] |