[llvm] [AArch64][SelectionDAG] Reduce redundant loads for constant <2 x i64> values (PR #214864)

Ethan Luis McDonough via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 24 16:48:22 PDT 2026


================
@@ -27721,6 +27710,56 @@ static SDValue
 performInterleavedStoreCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI,
                                SelectionDAG &DAG);
 
+// Rewrite store instructions that save constant <2 x i64> values as stp
+// instructions
+static SDValue splitStoreConstVector128(StoreSDNode *ST,
+                                        TargetLowering::DAGCombinerInfo &DCI,
+                                        SelectionDAG &DAG,
+                                        const AArch64Subtarget *Subtarget) {
+  SDValue Value = ST->getValue();
+  SDLoc DL(ST);
+
+  // Only process constant <2 x i64> vector values.
+  auto *BVN = dyn_cast<BuildVectorSDNode>(Value.getNode());
+  if (Value.getValueType() != MVT::v2i64 || !BVN ||
+      Value.getNumOperands() != 2 || !BVN->isConstant())
+    return SDValue();
+
+  if (!Value.hasOneUse() || ISD::isBuildVectorAllZeros(Value.getNode()))
+    return SDValue();
+
+  // For SVE targets, skip this optimization if the types have been legalized.
+  // We want to avoid transforming split vector stores so that they can be
+  // recombined later.
+  if (Subtarget->isSVEorStreamingSVEAvailable() &&
+      DCI.getDAGCombineLevel() != BeforeLegalizeTypes)
+    return SDValue();
+
+  // If SVE is supported, we stop if the pair's arithmetic sequence has a start
+  // or step value that could fit inside 5 bit imm. This is so that the build
+  // vector can later be rewritten as a SVE index instruction.
+  if (Subtarget->isSVEorStreamingSVEAvailable()) {
+    auto SeqInfo = BVN->isArithmeticSequence();
+    if (!SeqInfo || SeqInfo->first.isSignedIntN(5) ||
+        SeqInfo->second.isSignedIntN(5))
+      return SDValue();
+  }
+
+  // For non-SVE targets, continue if both values fit inside mov immediates.
+  else if (!AArch64_AM::isAnyMOVWMovAlias(Value.getConstantOperandVal(0), 64) ||
+           !AArch64_AM::isAnyMOVWMovAlias(Value.getConstantOperandVal(1), 64)) {
+    return SDValue();
+  }
----------------
EthanLuisMcDonough wrote:

I hadn't considered the impact this PR might have on hoisted values. Right now, this patch rewrites constant stores inside loops even if the invariant load is moved before the loop body. One solution to this issue might be to move this PR's logic into `AArch64LoadStoreOptimizer.cpp` and only rewrite the store if the constant load is in the same block.

Also, it seems like recent changes to how build vectors are lowered impact this PR as of now: be72d1bff9f3aab5626f16df0a585d3bb230b8e2

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


More information about the llvm-commits mailing list