[llvm] [LV] Use index type for base pointer computation in convertToStridedAccesses (PR #201070)

Luke Lau via llvm-commits llvm-commits at lists.llvm.org
Wed Jun 3 02:04:53 PDT 2026


================
@@ -7023,17 +7023,19 @@ void VPlanTransforms::convertToStridedAccesses(VPlan &Plan,
 
       VPBuilder Builder(LoadR);
       // Create the base pointer of strided access.
+      // TODO: reuse VPDerivedIVRecipe for base pointer computation when it
+      // supports a general VPValue as the start value.
       VPValue *StartVPV = vputils::getOrCreateVPValueForSCEVExpr(Plan, Start);
       VPValue *StrideInBytes = Plan.getOrAddLiveIn(Step->getValue());
       Type *IndexTy = Plan.getDataLayout().getIndexType(Ptr->getScalarType());
       assert(IndexTy == StrideInBytes->getScalarType() &&
              "Stride type from SCEV must match the index type");
-      VPValue *CanIVTyStride = Builder.createScalarSExtOrTrunc(
-          StrideInBytes, VectorLoop->getCanonicalIVType(), IndexTy,
-          DebugLoc::getUnknown());
+      VPValue *CanIV = Builder.createScalarSExtOrTrunc(
+          VectorLoop->getCanonicalIV(), IndexTy,
+          VectorLoop->getCanonicalIVType(), DebugLoc::getUnknown());
----------------
lukel97 wrote:

I think this is an example that showcases the issue:

```llvm
define void @canonical_iv_i64(ptr noalias %arr, ptr noalias %out, i64 %n) {
entry:
  br label %loop

loop:
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
  %ptr = getelementptr [1024 x i8], ptr %arr, i64 %iv
  %val = load i8, ptr %ptr
  store i8 %val, ptr %out
  %iv.next = add nuw i64 %iv, 1
  %ec = icmp ult i64 %iv.next, %n
  br i1 %ec, label %loop, label %exit

exit:
  ret void
}

```

Without strided accesses the IR is:

```llvm
vector.body:                                      ; preds = %vector.body, %vector.ph
  %vec.ind = phi <vscale x 8 x i64> [ %0, %vector.ph ], [ %vec.ind.next, %vector.body ]
  %avl = phi i64 [ %umax, %vector.ph ], [ %avl.next, %vector.body ]
  %1 = call i32 @llvm.experimental.get.vector.length.i64(i64 %avl, i32 8, i1 true)
  %2 = zext i32 %1 to i64
  %broadcast.splatinsert1 = insertelement <vscale x 8 x i64> poison, i64 %2, i64 0
  %broadcast.splat2 = shufflevector <vscale x 8 x i64> %broadcast.splatinsert1, <vscale x 8 x i64> poison, <vscale x 8 x i32> zeroinitializer
  %3 = getelementptr [1024 x i8], ptr %arr, <vscale x 8 x i64> %vec.ind
  %wide.masked.gather = call <vscale x 8 x i8> @llvm.vp.gather.nxv8i8.nxv8p0(<vscale x 8 x ptr> align 1 %3, <vscale x 8 x i1> splat (i1 true), i32 %1)
  call void @llvm.vp.scatter.nxv8i8.nxv8p0(<vscale x 8 x i8> %wide.masked.gather, <vscale x 8 x ptr> align 1 %broadcast.splat, <vscale x 8 x i1> splat (i1 true), i32 %1)
  %avl.next = sub nuw i64 %avl, %2
  %vec.ind.next = add nuw <vscale x 8 x i64> %vec.ind, %broadcast.splat2
  %4 = icmp eq i64 %avl.next, 0
  br i1 %4, label %middle.block, label %vector.body, !llvm.loop !0
```

Before this patch the offset is in i64:
```llvm
vector.body:                                      ; preds = %vector.body, %vector.ph
  %index = phi i64 [ 0, %vector.ph ], [ %current.iteration.next, %vector.body ]
  %avl = phi i64 [ %umax, %vector.ph ], [ %avl.next, %vector.body ]
  %0 = call i32 @llvm.experimental.get.vector.length.i64(i64 %avl, i32 16, i1 true)
  %1 = shl i64 %index, 10
  %2 = getelementptr i8, ptr %arr, i64 %1
  %3 = call <vscale x 16 x i8> @llvm.experimental.vp.strided.load.nxv16i8.p0.i32(ptr align 1 %2, i32 1024, <vscale x 16 x i1> splat (i1 true), i32 %0)
  call void @llvm.vp.scatter.nxv16i8.nxv16p0(<vscale x 16 x i8> %3, <vscale x 16 x ptr> align 1 %broadcast.splat, <vscale x 16 x i1> splat (i1 true), i32 %0)
  %4 = zext i32 %0 to i64
  %current.iteration.next = add i64 %4, %index
  %avl.next = sub nuw i64 %avl, %4
  %5 = icmp eq i64 %avl.next, 0
  br i1 %5, label %middle.block, label %vector.body, !llvm.loop !0
```

After it's truncated to i32:

```llvm
vector.body:                                      ; preds = %vector.body, %vector.ph
  %index = phi i64 [ 0, %vector.ph ], [ %current.iteration.next, %vector.body ]
  %avl = phi i64 [ %umax, %vector.ph ], [ %avl.next, %vector.body ]
  %0 = call i32 @llvm.experimental.get.vector.length.i64(i64 %avl, i32 16, i1 true)
  %1 = trunc i64 %index to i32
  %2 = shl i32 %1, 10
  %3 = getelementptr i8, ptr %arr, i32 %2
  %4 = call <vscale x 16 x i8> @llvm.experimental.vp.strided.load.nxv16i8.p0.i32(ptr align 1 %3, i32 1024, <vscale x 16 x i1> splat (i1 true), i32 %0)
  call void @llvm.vp.scatter.nxv16i8.nxv16p0(<vscale x 16 x i8> %4, <vscale x 16 x ptr> align 1 %broadcast.splat, <vscale x 16 x i1> splat (i1 true), i32 %0)
  %5 = zext i32 %0 to i64
  %current.iteration.next = add i64 %5, %index
  %avl.next = sub nuw i64 %avl, %5
  %6 = icmp eq i64 %avl.next, 0
  br i1 %6, label %middle.block, label %vector.body, !llvm.loop !0
```

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


More information about the llvm-commits mailing list