aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
diff options
context:
space:
mode:
authorBjorn Pettersson <bjorn.a.pettersson@ericsson.com>2025-06-17 11:16:32 +0200
committerBjorn Pettersson <bjorn.a.pettersson@ericsson.com>2025-06-17 13:15:07 +0200
commitef9547df04cbf0eb7e756a790f90a64704b57975 (patch)
tree40e6d81a8207a07a773511b3d0b538cf155c85f3 /llvm/lib/Target/RISCV/RISCVISelLowering.cpp
parent01f9dff61fb028f69493a44616014256dee5fb2a (diff)
downloadllvm-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.cpp30
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()) {