This fixes a crash caused by legal treating a scalable GEP as invariant,
but isUniformAfterVectorization does not handle GEPs.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Unit Tests
Event Timeline
I think there's a deeper logic issue here. I'm pretty sure this is a bug I introduced, so, sorry!
LoopAccessInfo::isUniform uses SCEV's notion of loop invariant. This is both things which are currently loop invariant, but also things whose computation is loop invariant (e.g. uniform).
As you noticed, VPReplicateRecipe::execute uses only whether the recipe was defined. This is essentially a proxy for whether an instructions *placement* was loop invariant. This explicitly *does not* reason about computation. (I think... this part of things I'm less confident in.)
I think the basic issue here is that a Recipe can correspond to the isUniform Value without itself being uniform-per-part or UniformAfterVectorization. So, I think your change is patching over a bug, not fixing one.
This patch does not solve the issue completely.
But I don't have expertise enough to comment on what needs to be fixed.
A simplified test case which still breaks the Loop vectorizer even after applying this candidate patch is as follows
test_loop2.ll
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" target triple = "aarch64-unknown-linux-gnu" define dso_local fastcc void @_test_loop2(i64 %init, i64 %n, i8* %store_dest) unnamed_addr #0 { br label %1. critedge5: ; preds = %1 ret void 1: ; preds = %0, %1 %2 = phi i64 [ %7, %1 ], [ %init, %0 ] %3 = sub nsw i64 %n, %2 %4 = trunc i64 %n to i8 %5 = add i64 %2, %3 %6 = getelementptr i8, i8* %store_dest, i64 %5 store i8 %4, i8* %6, align 1 %7 = add nsw i64 %2, 1 %8 = icmp sle i64 %7, 1000 br i1 %8, label %1, label %.critedge5 } attributes #0 = { "target-features"="+crc,+crypto,+fp-armv8,+neon,+sve,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8a" }
Issue an be reproduced by command
opt -passes=loop-vectorize test_loop2.ll
At the moment, isUniformAfterVectorization reasons about more than just placement by using information about uniform operands, but relies on uniforms being represented as uniform VPReplicateRecipes. I think the underlying issue is that we don't classify the GEP as uniform correctly. I put up D150991 to use Legal::isUniform to bring the reasoning during classification in line with isUniformMemOp which is used in other places.
Thanks, I added the new test in 07e5f57df4bf
llvm/lib/Transforms/Vectorize/VPlan.h | ||
---|---|---|
2710 | Propagating uniformity forwards on-demand from operands is fine, for GEPs or other non-phi recipes, where not cached as a result of SCEV/Divergence Analysis. Should this function still be "inline"? The "AfterVectorization" suffix should be dropped if favor of "onlyFirstLaneUsed()" above (independent of this patch). |
llvm/lib/Transforms/Vectorize/VPlan.h | ||
---|---|---|
2710 | Will move into VPlan.cpp now that this has grown and rename accordingly. |
Propagating uniformity forwards on-demand from operands is fine, for GEPs or other non-phi recipes, where not cached as a result of SCEV/Divergence Analysis.
Should this function still be "inline"?
The "AfterVectorization" suffix should be dropped if favor of "onlyFirstLaneUsed()" above (independent of this patch).