This is an archive of the discontinued LLVM Phabricator instance.

[LoopVectorize][Fix] Crash when invariant store address is calculated inside loop
ClosedPublic

Authored by igor.kirillov on Sep 12 2022, 4:59 AM.

Details

Summary

Fixes #57572

Generally LICM pass is responsible for sinking out code that calculates
invariant address inside loop as it only needed to be calculated once.
But in rare case it does not happen we will not be vectorizing the
loop.

Diff Detail

Event Timeline

igor.kirillov created this revision.Sep 12 2022, 4:59 AM
Herald added a project: Restricted Project. · View Herald TranscriptSep 12 2022, 4:59 AM
igor.kirillov requested review of this revision.Sep 12 2022, 4:59 AM

Add an empty line to the test and a reference to the github issue

mgabka added a subscriber: mgabka.Sep 14 2022, 1:43 AM
mgabka added inline comments.Sep 21 2022, 8:22 AM
llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
938

nit: "check its" -> "check if"

llvm/test/Transforms/LoopVectorize/reduction-with-invariant-store.ll
517

nit: maybe better to call it : reduc_store_invariant_addr_not_hoisted ?

david-arm accepted this revision.Sep 21 2022, 8:29 AM

LGTM with nits addressed!

llvm/test/Transforms/LoopVectorize/reduction-with-invariant-store.ll
518

nit: I think this should be calculated instead of calucalated

This revision is now accepted and ready to land.Sep 21 2022, 8:29 AM
fhahn requested changes to this revision.Sep 21 2022, 9:37 AM

You could add something like Fixes #57572 to the description, so the issue will be auto-closed once the fix is pushed.

llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
955

I think the place for the check means we now may not vectorize cases we vectorized before, specifically if we have reductions and a store to an invariant address that's defined in the loop body that's not used by a reduction, as in the example below.

You likely want to drop the && !getReductionVars().empty()) { check above and only check the address if isInvariantStoreOfReduction is true.

define i32 @test(i32* %dst, i32* readonly %src) {
entry:
  br label %for.body

for.body:                                         ; preds = %for.body, %entry
  %sum = phi i32 [ 0, %entry ], [ %add, %for.body ]
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ]
  %gep.src = getelementptr inbounds i32, i32* %src, i64 %iv
  %0 = load i32, i32* %gep.src, align 4
  %add = add nsw i32 %sum, %0
  %gep.dst = getelementptr inbounds i32, i32* %dst, i64 42
  store i32 0, i32* %gep.dst, align 4
  %iv.next = add nuw nsw i64 %iv, 1
  %exitcond = icmp eq i64 %iv.next, 1000
  br i1 %exitcond, label %exit, label %for.body

exit:                                             ; preds = %for.body
  %add.lcssa = phi i32 [ %add, %for.body ]
  ret i32 %add.lcssa
}
This revision now requires changes to proceed.Sep 21 2022, 9:37 AM
igor.kirillov edited the summary of this revision. (Show Details)

Update commit message

fhahn accepted this revision.Sep 26 2022, 12:27 AM

LGTM with the inline comment addressed, thanks!

llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
955

To simplify the code, please add an early continue if the store is not isInvariantStoreOfReduction(SI) and remove the 2 separate checks on line 953 and 939

Please also add the test above to ensure the regression is guarded against.

This revision is now accepted and ready to land.Sep 26 2022, 12:27 AM

Refactor `isInvariantStoreOfReduction' check

igor.kirillov marked 5 inline comments as done.Sep 26 2022, 2:47 PM
This revision was landed with ongoing or failed builds.Sep 28 2022, 2:38 AM
This revision was automatically updated to reflect the committed changes.
fhahn added a comment.Sep 30 2022, 5:03 AM

Did you add the extra test for the regression in the original version of the patch? It looks like it wasn't included in 2d60d7ba1a26/

Did you add the extra test for the regression in the original version of the patch? It looks like it wasn't included in 2d60d7ba1a26/

Done - rGa94a8555/