[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