[llvm] [RISCV] Add combine for shadd family of instructions. (PR #130829)
Craig Topper via llvm-commits
llvm-commits at lists.llvm.org
Tue Mar 11 14:47:21 PDT 2025
================
@@ -14306,6 +14312,87 @@ static SDValue transformAddShlImm(SDNode *N, SelectionDAG &DAG,
return DAG.getNode(ISD::SHL, DL, VT, SHADD, DAG.getConstant(Bits, DL, VT));
}
+// Check if this SDValue is an add immediate and then
+static bool checkAddiForShift(SDValue AddI) {
+ // Based on testing it seems that performance degrades if the ADDI has
+ // more than 2 uses.
+ if (AddI->use_size() > 2)
+ return false;
+
+ ConstantSDNode *AddConst = dyn_cast<ConstantSDNode>(AddI->getOperand(1));
+ if (!AddConst)
+ return false;
+
+ SDValue SHLVal = AddI->getOperand(0);
+ if (SHLVal->getOpcode() != ISD::SHL)
+ return false;
+
+ ConstantSDNode *ShiftNode = dyn_cast<ConstantSDNode>(SHLVal->getOperand(1));
+ if (!ShiftNode)
+ return false;
+
+ auto ShiftVal = ShiftNode->getSExtValue();
+ if (ShiftVal != 1 && ShiftVal != 2 && ShiftVal != 3)
+ return false;
+
+ return true;
+}
+
+// Optimize (add (add (shl x, c0), c1), y) ->
+// (ADDI (SH*ADD y, x), c1), if c0 equals to [1|2|3].
+static SDValue combineShlAddIAdd(SDNode *N, SelectionDAG &DAG,
+ const RISCVSubtarget &Subtarget) {
+ if (!ReassocShlAddiAdd)
+ return SDValue();
+
+ // Perform this optimization only in the zba extension.
+ if (!Subtarget.hasStdExtZba())
+ return SDValue();
+
+ // Skip for vector types and larger types.
+ EVT VT = N->getValueType(0);
+ if (VT.isVector() || VT.getSizeInBits() > Subtarget.getXLen())
+ return SDValue();
+
+ // Looking for a reg-reg add and not an addi.
+ auto *Op1 = dyn_cast<ConstantSDNode>(N->getOperand(1));
+ if (Op1)
+ return SDValue();
+ SDValue AddI;
+ SDValue Other;
+
+ if (N->getOperand(0)->getOpcode() == ISD::ADD &&
+ N->getOperand(1)->getOpcode() == ISD::ADD) {
+ AddI = N->getOperand(0);
+ Other = N->getOperand(1);
+ if (!checkAddiForShift(AddI)) {
+ AddI = N->getOperand(1);
+ Other = N->getOperand(0);
+ }
+ } else if (N->getOperand(0)->getOpcode() == ISD::ADD) {
+ AddI = N->getOperand(0);
+ Other = N->getOperand(1);
+ } else if (N->getOperand(1)->getOpcode() == ISD::ADD) {
+ AddI = N->getOperand(1);
+ Other = N->getOperand(0);
+ } else
+ return SDValue();
+
+ if (!checkAddiForShift(AddI))
+ return SDValue();
+
+ auto *AddConst = dyn_cast<ConstantSDNode>(AddI->getOperand(1));
----------------
topperc wrote:
dyn_cast -> cast if it can't fail.
https://github.com/llvm/llvm-project/pull/130829
More information about the llvm-commits
mailing list