[llvm] [AArch64] Optimize vector multiplications by certain constants for v2i64 (PR #183827)

David Green via llvm-commits llvm-commits at lists.llvm.org
Fri Mar 6 03:19:56 PST 2026


================
@@ -5919,6 +5919,44 @@ static unsigned selectUmullSmull(SDValue &N0, SDValue &N1, SelectionDAG &DAG,
   return 0;
 }
 
+// Transform mul<v2i64, splat(2^n +-1)> into a SHL and ADD/SUB
+// this transormation is much faster when vector mul is not supported
+static SDValue convertMulToShlAdd(SDNode *N, SelectionDAG &DAG) {
+  const SDNode *Operand = N->getOperand(1).getNode();
+  APInt SplatValue;
+  ISD::isConstantSplatVector(Operand, SplatValue);
+
+  // Not a constant splat so should just stay as a mulitplcation operation
+  if (!SplatValue.getBoolValue())
+    return SDValue();
+
+  // If (Value - 1) is a power of 2, we need an ADD (e.g., 257)
+  bool NeedsAdd = (SplatValue - 1).isPowerOf2();
+  bool NeedsSub = (SplatValue + 1).isPowerOf2();
+
+  // If the constant is not (2^n + 1) or (2^n - 1), it would require
+  // more than one addition/subtraction. For v2i64, the cost of
+  // multiple vector adds/shifts often exceeds the cost of
+  // scalarization (moving to GPRs to use a single MUL).
+  if (!NeedsSub && !NeedsAdd)
+    return SDValue();
+
+  SDLoc DL(N);
+  EVT VT = N->getValueType(0);
+  SDValue LHS = N->getOperand(0);
+
+  unsigned ShiftAmt =
+      NeedsAdd ? (SplatValue - 1).logBase2() : (SplatValue + 1).logBase2();
+  SDValue VecShiftAmt = DAG.getConstant(ShiftAmt, DL, VT);
+  SDValue ShiftNode = DAG.getNode(ISD::SHL, DL, VT, LHS, VecShiftAmt);
+
+  // Emit: (LHS << ShiftAmt) +- LHS
+  if (NeedsAdd) {
+    return DAG.getNode(ISD::ADD, DL, VT, ShiftNode, LHS);
+  }
+  return DAG.getNode(ISD::SUB, DL, VT, ShiftNode, LHS);
----------------
davemgreen wrote:

return DAG.getNode(NeedsAdd ? ISD::ADD : ISD::SUB, ...);

https://github.com/llvm/llvm-project/pull/183827


More information about the llvm-commits mailing list