[llvm] [LV] Support strided load with a stride of -1 (PR #128718)

Mel Chen via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 2 06:52:58 PDT 2025


================
@@ -2519,6 +2530,75 @@ void VPlanTransforms::dissolveLoopRegions(VPlan &Plan) {
     R->dissolveToCFGLoop();
 }
 
+void VPlanTransforms::convertToStridedAccesses(VPlan &Plan, VPCostContext &Ctx,
+                                               VFRange &Range) {
+  if (Plan.hasScalarVFOnly())
+    return;
+
+  SmallVector<VPRecipeBase *> ToErase;
+  for (VPBasicBlock *VPBB : VPBlockUtils::blocksOnly<VPBasicBlock>(
+           vp_depth_first_shallow(Plan.getVectorLoopRegion()->getEntry()))) {
+    for (VPRecipeBase &R : make_early_inc_range(*VPBB)) {
+      auto *MemR = dyn_cast<VPWidenMemoryRecipe>(&R);
+      // TODO: support strided store
+      // TODO: support strided accesses with stride not equal to -1
+      if (!MemR || !isa<VPWidenLoadRecipe>(MemR) || !MemR->isReverse())
+        continue;
+
+      Instruction &Ingredient = MemR->getIngredient();
+      Type *ElementTy = getLoadStoreType(&Ingredient);
+
+      auto IsProfitable = [&](ElementCount VF) -> bool {
+        Type *DataTy = toVectorTy(ElementTy, VF);
+        const Align Alignment = getLoadStoreAlignment(&Ingredient);
+        if (!Ctx.TTI.isLegalStridedLoadStore(DataTy, Alignment))
+          return false;
+        const InstructionCost CurrentCost = MemR->computeCost(VF, Ctx);
+        const InstructionCost StridedLoadStoreCost =
+            Ctx.TTI.getStridedMemoryOpCost(
+                Ingredient.getOpcode(), DataTy,
+                getLoadStorePointerOperand(&Ingredient), MemR->isMasked(),
----------------
Mel-Chen wrote:

`getStridedMemoryOpCost` falls back to `getGatherScatterOpCost` when the target doesn't support strided access.
```
  InstructionCost getStridedMemoryOpCost(unsigned Opcode, Type *DataTy,
                                         const Value *Ptr, bool VariableMask,
                                         Align Alignment,
                                         TTI::TargetCostKind CostKind,
                                         const Instruction *I) const override {
    // For a target without strided memory operations (or for an illegal
    // operation type on one which does), assume we lower to a gather/scatter
    // operation.  (Which may in turn be scalarized.)
    return thisT()->getGatherScatterOpCost(Opcode, DataTy, Ptr, VariableMask,
                                           Alignment, CostKind, I);
  }
```
Since `getGatherScatterOpCost` uses pointer operand, I went ahead with the latter approach you suggested.
8875c321ac05f6700b41baa377bdcca8efd45caf

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


More information about the llvm-commits mailing list