[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