diff options
author | Alex Bradbury <asb@lowrisc.org> | 2019-01-12 07:43:06 +0000 |
---|---|---|
committer | Alex Bradbury <asb@lowrisc.org> | 2019-01-12 07:43:06 +0000 |
commit | 61aa940074da0ec60a105f1ab45b45bc9815633d (patch) | |
tree | f77238ae98112692722eb4abcd9ce0cdb4a7968e /llvm/lib/Target/RISCV/RISCVISelLowering.cpp | |
parent | d05eae7a7b24444c676238383037552816072052 (diff) | |
download | bcm5719-llvm-61aa940074da0ec60a105f1ab45b45bc9815633d.tar.gz bcm5719-llvm-61aa940074da0ec60a105f1ab45b45bc9815633d.zip |
[RISCV] Introduce codegen patterns for RV64M-only instructions
As discussed on llvm-dev
<http://lists.llvm.org/pipermail/llvm-dev/2018-December/128497.html>, we have
to be careful when trying to select the *w RV64M instructions. i32 is not a
legal type for RV64 in the RISC-V backend, so operations have been promoted by
the time they reach instruction selection. Information about whether the
operation was originally a 32-bit operations has been lost, and it's easy to
write incorrect patterns.
Similarly to the variable 32-bit shifts, a DAG combine on ANY_EXTEND will
produce a SIGN_EXTEND if this is likely to result in sdiv/udiv/urem being
selected (and so save instructions to sext/zext the input operands).
Differential Revision: https://reviews.llvm.org/D53230
llvm-svn: 350993
Diffstat (limited to 'llvm/lib/Target/RISCV/RISCVISelLowering.cpp')
-rw-r--r-- | llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 26 |
1 files changed, 21 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)); |