This is an archive of the discontinued LLVM Phabricator instance.

[DependenceAnalysis][PR52170] Conservative crash on overflowed loop backedge
Needs ReviewPublic

Authored by artemrad on Feb 8 2022, 9:52 AM.

Details

Summary

Fixing [PR52170]

The following commit (https://github.com/llvm/llvm-project/commit/7086025d6567562d31fadbaccf08b4fd72ec2100) enabled delinearization of fixed sized arrays. It is now possible to propagate SIV constraints to coupled subscripts in more cases, resulting in more accurate dependence analysis. When a SIV constraint is propagated we re-classify the other non-SIV subscripts. PR52170 describes a case where we hit buggy, superfluous code when doing this reclassification. This change removes this superfluous code.

The original purpose of the removed code (in checkSubscript()) was to make sure that checkUpperBound() was never called on loops whose index variable may overflow. The removed code was superfluous as checkSubscript() works on perfectly nested AddRecs. If a loop can overflow no AddRec can be created and hence checkSubscript() will return that the subscript in NonLinear, as it should.

Changes:

  • Removed superfluous code from checkSubscript()
  • Added a new LIT test to test that DA reports conservative dependencies when it cannot be determined if overflow will happen in the AddRec

Diff Detail

Event Timeline

artemrad created this revision.Feb 8 2022, 9:52 AM
artemrad requested review of this revision.Feb 8 2022, 9:52 AM
bmahjour added inline comments.Feb 8 2022, 10:31 AM
llvm/test/Analysis/DependenceAnalysis/TripCountOverflow.ll
36

Shouldn't %n be changed to i64 (while keeping %i as i32) so this test is more representative of the condition check being removed?

Please mention the bug number in the summary as well.

Do you know what was the purpose of the check was? Usually those are not added without reason. In particular, it seems that it has been added in rGc0661aeaf8daf371023cf5669be4bd9b428882d0. What if the code is called when not reclassfying a SIV reclassification?

SCEVs already do the overflow checks that the code was targeting.

Can you clarify? There is a reason why SCEVs have nsw/nuw flags.

SCEVs already do the overflow checks that the code was targeting.

Can you clarify? There is a reason why SCEVs have nsw/nuw flags.

If a SCEV detects that an overflow is possible it will not produce an AddRec. For example this is the SCEV produced for the simple example below {(4 + %array)<nuw>,+,4}<nuw><%for.outer>. Notice how the starting address is not a constant or a nested AddRec, but rather an expression.

define void @overflow(i32 %n) {
entry:
  %array = alloca [5 x i32], align 1
  br label %for.outer
for.outer:
  %i = phi i32 [ 0, %entry ], [ %i.add, %for.outer ]
  %i.add = add i32 %i, 1
  %i.ptr = getelementptr inbounds [5 x i32], [5 x i32]* %array, i32 0, i32 %i.add
  store i32 0, i32* %i.ptr, align 1
  %cmp = icmp slt i32 %i.add, %n
  br i1 %cmp, label %for.outer, label %other
other:
  ret void
}

Do you know what was the purpose of the check was? Usually those are not added without reason. In particular, it seems that it has been added in rGc0661aeaf8daf371023cf5669be4bd9b428882d0. What if the code is called when not reclassfying a SIV reclassification?

Purpose was to make sure that collectUpperBound() was never called on overflowing loops. More specifically that DA exited early if a loop that could possibly overflow was detected.
My claim is that the code I deleted was superfluous. CheckSubscript works on perfectly nested AddRecs. From the answer above we can see an AddRec would not be produced for a possibly overflowing index. The isLoopInvariant() checks inside the checkSubscript function would of already returned false for this SCEV (as they now do with my change). The deleted code was superfluous.

What if the code is called when not reclassifying a SIV reclassification?

You are correct my statement in the change description was too conservative. This code does get called when we do initial classification of subscripts. It works as intended providing an accurate classification of the subscript. The subscripts that could overflow get the NonLinear classification, and DA conservatively returns [*] for that subscript as it doesn't know how to deal with it.

artemrad updated this revision to Diff 407989.Feb 11 2022, 12:30 PM
artemrad edited the summary of this revision. (Show Details)
artemrad edited the summary of this revision. (Show Details)Feb 11 2022, 12:49 PM
artemrad marked an inline comment as done.

@bmahjour @Meinersbur Did I manage to address your concerns?

@bmahjour @Meinersbur Any other concerns about the change?

I'm generally in favour of this patch, but just not sure if there is (or should be) a guarantee that SCEV will NOT produce an AddRec in overflow situations. For example when a GEP has the inbounds attribute, the produced address after adding the index/offset cannot cause an unsigned overflow, so not sure why SCEV would produce different results depending on whether the index/offset could wrap! SCEV seems to produce an AddRec for the offset/index (eg. %i.add) regardless whether it could wrap or not. It's just the GEP that seems to be behaving the way you described.

nikic added a subscriber: nikic.Feb 25 2022, 1:34 PM

I'm generally in favour of this patch, but just not sure if there is (or should be) a guarantee that SCEV will NOT produce an AddRec in overflow situations. For example when a GEP has the inbounds attribute, the produced address after adding the index/offset cannot cause an unsigned overflow, so not sure why SCEV would produce different results depending on whether the index/offset could wrap! SCEV seems to produce an AddRec for the offset/index (eg. %i.add) regardless whether it could wrap or not. It's just the GEP that seems to be behaving the way you described.

Unless there is some DA-specific restriction involved here, AddRecs (including pointer AddRecs) in SCEV can definitely wrap.

Trying to understand the patch, I applied it and replaced return false with llvm_unreachable. Neither TripCountOverflow.ll, nor PR21585.ll trigger it. The only one that does is Transforms/LoopUnrollAndJam/dependencies_multidims.ll.

Herald added a project: Restricted Project. · View Herald TranscriptMar 29 2022, 6:07 PM