summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Target/RISCV/RISCVISelLowering.cpp26
-rw-r--r--llvm/lib/Target/RISCV/RISCVInstrInfoM.td31
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]
OpenPOWER on IntegriCloud