This is an archive of the discontinued LLVM Phabricator instance.

[LoopAccessAnalysis][SVE] Bail out for scalable vectors
ClosedPublic

Authored by peterwaller-arm on Nov 18 2021, 5:34 AM.

Details

Summary

The supplied test case, reduced from real world code, crashes with a
'Invalid size request on a scalable vector.' error.

Since it's similar in spirit to an existing LAA test, rename the file to
generalize it to both.

Diff Detail

Event Timeline

peterwaller-arm requested review of this revision.Nov 18 2021, 5:34 AM
Herald added a project: Restricted Project. · View Herald TranscriptNov 18 2021, 5:34 AM
david-arm added inline comments.Nov 18 2021, 5:43 AM
llvm/test/Analysis/LoopAccessAnalysis/scalable-vector-regression-tests.ll
23

Is it possible to clean this test up a bit here?

i.e. do something like:

entry:
  br label %vector.body

vector.body:
  %ind = phi i64 [ 0, %entry ], [ %ind.next, %vector.body ]
  ...
  %ind.next = add i64, %ind, 1
  br i1 %cmp, %vector.body, %end

end:
  ret i1 false

I'm just a bit worried about the strength of the test given the br i1 false and br i1 true lines in here. Also, having proper named labels like vector.body or loop.body makes it a bit more readable I think.

llvm/test/Analysis/LoopAccessAnalysis/scalable-vector-regression-tests.ll
23

Thanks for your nice suggestions.

I'm just a bit worried about the strength of the test given the br i1 false and br i1 true lines in here.

I tried feeding in an i1 %cond parameter, and branching conditionally on that parameter, but then the testcase fails to reproduce the issue. I also tried having the branch depend on the output of the load, and storing an unguessable value from a parameter, but that didn't work either.

Tempted to leave it as br i1 true for the vector body, unless you strongly counsel otherwise; but I will first try a bit harder to determine why the desired code paths aren't hit in that case.

madhur13490 added inline comments.
llvm/lib/Analysis/LoopAccessAnalysis.cpp
1111

I think braces are not required. You can hoist the comment above "if" block. It doesn't harm readability.

llvm/lib/Analysis/LoopAccessAnalysis.cpp
1111

You are right, thanks! I've been programming too much rust recently :)

The fix looks valid, but maybe you can update the comment a bit to better describe the different scenarios.

llvm/lib/Analysis/LoopAccessAnalysis.cpp
1112

I think there are three possible scenarios to consider:

  1. The pointer has a scalable stride (e.g. the PHI is updated with getetelemenptr <vscale x 2 x i64>, <vscale x 2 x i64>*, i64 1 each iteration of the loop), at which point the Step will not be a SCEVConstant, but rather a SCEVUnknown.
  2. Case 1, but LAA has replaced the symbolic stride by 1 under the predicate that vscale = 1.
  3. The case you have in your tests, where the pointer stride is actually fixed (e.g. Step = {nullptr, +, 1}) and the object is scalable.

For case 1, the dyn_cast on line 1096 would fail. That means the code is already conservative.
For case 2, we could do some extra work to recognize there is a predicate that checks that vscale == 1, and use getKnownMinSize() and allow the code-path here to continue.
For case 3, we can bail out and no further work is required (meaning that the 'yet' can be removed from the comment).

Sorry if I'm being a bit nitpicky, but I think the 'not yet supported' is already the case today, and your comment is a bit misleading in that the 'yet' at this point in the code only applies to 2.

Maybe it's worth capturing these scenarios somewhere in a comment?

llvm/test/Analysis/LoopAccessAnalysis/scalable-vector-regression-tests.ll
24

nit: can you give these names instead of numbers?

Matt added a subscriber: Matt.Nov 21 2021, 1:19 PM
  • Remove comment, replace with debug print statement (per other bailouts above)

For the tests:

  • Introduce input pointer parameter
  • Introduce a loop counter variable
  • Use named bb/insts
  • Add another test with scalable vector pointer as input (as opposed to an i8* as input, like before)
peterwaller-arm marked 3 inline comments as done.Nov 22 2021, 8:24 AM
peterwaller-arm added inline comments.
llvm/lib/Analysis/LoopAccessAnalysis.cpp
1112

Looking at it, I don't think I observed the dyn_cast on 1096 fail. So with respect to your request I'm uncertain exactly what I am documenting right now (all the scalable cases I've tried appear to flow through the new debug statement) and I've chosen to leave that out. Hope that's OK but can revisit if requested.

Run clang-format.

paulwalker-arm added inline comments.Nov 23 2021, 9:00 AM
llvm/lib/Analysis/LoopAccessAnalysis.cpp
1111–1114

At the top of this function I can see

if (AccessTy->isAggregateType()) {
  LLVM_DEBUG(dbgs() << "LAA: Bad stride - Not a pointer to a scalar type"
                    << *Ptr << "\n");
  return 0;
}

So my question is why not just add a check immediate after this for isa<ScalableVector>(AccessTy)?

  • Add -S to opt line (output is not checked, but llvm-lit -v output looks funny without it)
  • Address review comment, move bailout to top.
peterwaller-arm marked an inline comment as done.Nov 23 2021, 9:12 AM
peterwaller-arm added inline comments.
llvm/lib/Analysis/LoopAccessAnalysis.cpp
1111–1114

My thinking was to plant the bailout logic near the site that would need to be updated should this get extended, but your suggestion makes sense to me, so done.

paulwalker-arm accepted this revision.Nov 23 2021, 9:28 AM

A couple of things to consider but otherwise looks good.

llvm/lib/Analysis/LoopAccessAnalysis.cpp
1046

Looking at the other messages suggests "LAA: Bad stride - scalable object: " would be more consistent.

llvm/test/Analysis/LoopAccessAnalysis/scalable-vector-regression-tests.ll
3–5

To me this suggest this wants to be a REQUIRES: asserts test where the debug messages are verified to be produced/not produced as expected.

This revision is now accepted and ready to land.Nov 23 2021, 9:28 AM
sdesmalen accepted this revision.Nov 23 2021, 9:36 AM
sdesmalen added inline comments.
llvm/lib/Analysis/LoopAccessAnalysis.cpp
1112

I'd expect that dyn_cast to fail if there's a bitcast in the loop:

%ind_ptr_i8 = bitcast <vscale x 16 x i8>* %ind_ptr to i8*
store i8 0, i8* %ind_ptr_i8
%next_ptr = getelementptr inbounds <vscale x 16 x i8>, <vscale x 16 x i8>* %ind_ptr, i64 1

That would create a SCEV with scalable stride: {%start,+,sizeof(<vscale x 16 x i8>)}.

peterwaller-arm marked 3 inline comments as done.Nov 24 2021, 4:52 AM
peterwaller-arm added inline comments.
llvm/lib/Analysis/LoopAccessAnalysis.cpp
1112

It does, but replaceSymbolicStrideSCEV appears to replace that:

LAA: Replacing SCEV: {%input_ptr,+,sizeof(<vscale x 16 x i8>)}<nw><%vector.body> by: {%input_ptr,+,1}<nw><%vector.body>

So my read is that it doesn't bail out there, however I have not fully chased this yet.

Use REQUIRES: asserts, check debug output lines.

Missed in previous update:

  • Update debug message text for consistenc with surrounding messages.

I made a bit of a mess of the updates here, managing to update one thing but
not the other. This patch should keep everything consistent. I've also removed
the label from the first test which was previously existing and exists to check
if opt exits with a fatal error.

This revision was landed with ongoing or failed builds.Nov 24 2021, 7:52 AM
This revision was automatically updated to reflect the committed changes.
llvm/lib/Analysis/LoopAccessAnalysis.cpp