diff options
author | Bjorn Pettersson <bjorn.a.pettersson@ericsson.com> | 2025-06-17 11:16:32 +0200 |
---|---|---|
committer | Bjorn Pettersson <bjorn.a.pettersson@ericsson.com> | 2025-06-17 13:15:07 +0200 |
commit | ef9547df04cbf0eb7e756a790f90a64704b57975 (patch) | |
tree | 40e6d81a8207a07a773511b3d0b538cf155c85f3 /llvm/lib/Target/RISCV/RISCVISelLowering.cpp | |
parent | 01f9dff61fb028f69493a44616014256dee5fb2a (diff) | |
download | llvm-users/bjope/prepare_1.zip llvm-users/bjope/prepare_1.tar.gz llvm-users/bjope/prepare_1.tar.bz2 |
[RISCV] Fold (add (srl x, n), (srl x, n)) into (srl x, n-1)users/bjope/prepare_1
This patch adds a new fold that will turn
(add (srl x, n), (srl x, n))
into
(srl x, n-1)
when bit n-1 is known to be zero in x.
This could perhaps be moved to generic DAGCombiner in the
future, but this patch adds it as a RISCV specific combine.
For RISCV it typically trigger for DAG nodes like this that
may be created by the legalizer:
t1: i32 = srl RISCVISD::READ_VLENB:i32, Constant:i32<2>
t2: i32 = add t1, t1
Got the idea when working on a solution for #141034, as it
may avoid some regressions otherwise caused by the fix being
prepared for that issue.
Diffstat (limited to 'llvm/lib/Target/RISCV/RISCVISelLowering.cpp')
-rw-r--r-- | llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index 7cfada6..046bc11 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -15240,12 +15240,42 @@ static SDValue combineAddOfBooleanXor(SDNode *N, SelectionDAG &DAG) { N0.getOperand(0)); } +// Try to turn (add (srl x, n), (srl x, n)) into (srl x, n-1). +// +// This combine could perhaps be moved to DAGCombiner. For RISCV this kind of +// pattern seem to appear in situations when x is READ_VLENB, which matches with +// the condition that the lsb of x need to be zero. +static SDValue combineAddSrl(SDNode *N, SelectionDAG &DAG) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + EVT VT = N->getValueType(0); + SDLoc DL(N); + + // Match (add (srl x, n), (srl x, n)). + if (N0 != N1 || N0.getOpcode() != ISD::SRL) + return SDValue(); + + // Need a srl that has constant shift amount of at least 1. + std::optional<uint64_t> ShAmt = DAG.getValidShiftAmount(N0); + if (!ShAmt || *ShAmt == 0) + return SDValue(); + + // Last bit shifted out by srl should be known zero. + if (!DAG.computeKnownBits(N0.getOperand(0)).Zero[*ShAmt - 1]) + return SDValue(); + + SDValue NewAmt = DAG.getShiftAmountConstant(*ShAmt - 1, VT, DL); + return DAG.getNode(ISD::SRL, DL, VT, N0.getOperand(0), NewAmt); +} + static SDValue performADDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget) { SelectionDAG &DAG = DCI.DAG; if (SDValue V = combineAddOfBooleanXor(N, DAG)) return V; + if (SDValue V = combineAddSrl(N, DAG)) + return V; if (SDValue V = transformAddImmMulImm(N, DAG, Subtarget)) return V; if (!DCI.isBeforeLegalize() && !DCI.isCalledByLegalizer()) { |