[llvm] [LV] Convert gather loads with constant stride into strided loads (PR #147297)

Luke Lau via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 26 01:20:54 PDT 2026


https://github.com/lukel97 commented:

I'm seeing a crash on SPEC CPU 2017, here's a reduced test case which might be good to include in this PR:

```llvm
; ModuleID = 'reduced.bc'
target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"
target triple = "riscv64-unknown-linux-gnu"

define void @_ZN6dealii8internal13Triangulation14Implementation18execute_refinementILi3EEEvRNS_13TriangulationILi3EXT_EEE(ptr %0, i64 %sub.ptr.sub.i3060) #0 {
entry:
  br label %for.cond785.preheader

for.cond785.preheader:                            ; preds = %for.cond785.preheader, %entry
  %conv77719316 = phi i64 [ %conv777, %for.cond785.preheader ], [ 0, %entry ]
  %q.019315 = phi i32 [ %inc817, %for.cond785.preheader ], [ 0, %entry ]
  %add.ptr.i3062 = getelementptr nusw [16 x i8], ptr %0, i64 %conv77719316
  %1 = load i32, ptr %add.ptr.i3062, align 4
  %arrayidx.i.1 = getelementptr i8, ptr %add.ptr.i3062, i64 4
  %2 = load i32, ptr %arrayidx.i.1, align 4
  %arrayidx.i.3 = getelementptr nusw i8, ptr %add.ptr.i3062, i64 12
  %3 = load i32, ptr %arrayidx.i.3, align 4
  store i32 0, ptr %add.ptr.i3062, align 4
  %inc817 = add i32 %q.019315, 1
  %conv777 = zext i32 %inc817 to i64
  %cmp782 = icmp ugt i64 %sub.ptr.sub.i3060, %conv777
  br i1 %cmp782, label %for.cond785.preheader, label %for.body823

for.body823:                                      ; preds = %for.cond785.preheader
  ret void
}

attributes #0 = { "target-features"="+v" }
```

The crash is coming from this cast to VPWidenMemoryRecipe bit in createInterleaveGroups:

```
void VPlanTransforms::createInterleaveGroups(
    VPlan &Plan,
    const SmallPtrSetImpl<const InterleaveGroup<Instruction> *>
        &InterleaveGroups,
    VPRecipeBuilder &RecipeBuilder, const bool &ScalarEpilogueAllowed) {
  if (InterleaveGroups.empty())
    return;

  // Interleave memory: for each Interleave Group we marked earlier as relevant
  // for this VPlan, replace the Recipes widening its memory instructions with a
  // single VPInterleaveRecipe at its insertion point.
  VPDominatorTree VPDT(Plan);
  for (const auto *IG : InterleaveGroups) {
    auto *Start =
        cast<VPWidenMemoryRecipe>(RecipeBuilder.getRecipe(IG->getMember(0)));
```

I'm guessing a NF=4 interleaved access is probably the more profitable option here. Off the top of my head I guess there's two ways we can handle this:

1) Bail in `convertToStridedAccesses` if the load is in an interleave group
2) Instead of `VPWidenMemIntrinsicRecipe`, make a `VPStridedLoadRecipe` which is a subclass of `VPWidenMemoryRecipe` so `createInterleaveGroups` can handle it

Maybe there's other ways around this. I don't have a strong opinion on this but 2) seems slightly nicer since we wouldn't need to plumb interleave groups through to `convertToStridedAccesses`

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


More information about the llvm-commits mailing list