[PATCH] D101722: [SCEV] Don't require ControlsExit for gt/lt NoWrap

Philip Reames via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed May 19 11:02:24 PDT 2021


reames added a comment.

@nikic I'm going to try to expand a bit on my current thinking, but this may be easier to discuss on a call.  Back and forth with instant clarification seems quite useful.  :)

All of the following will use the same example you did.  Specifically:
loop:

  %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ]
  %iv.inc = add nsw i32 %iv, 3
  call void @may_exit()
  %becond = icmp ne i32 %iv.inc, 46
  br i1 %becond, label %loop, label %leave

There are two interrelated sources of exit count information here:

1. If the exit is actually taken.
2. If the loop must hit UB.

As you pointed out, in this example without the nsw flag, this is an infinite loop.  As such, part (a) contributes nothing to our analysis.  Part (b) gives us an exit count of UINT32_MAX udiv 3 - because we can prove that a) poison is produced on that iteration and b) that poison reaches a UB triggering instruction.

In the current code, computeBECount also relies on wrapping being impossible (either by proof or by assumption) with it's reasoning about delta offsets.  (I have separate reason to believe there's potentially a latent bug somewhere here, but haven't yet found it.)  Note that this is still computing part (a) above, it isn't really computing (b) per se.  This is one reason I'm really nervous about your change.

When reasoning, I think we need to carefully distinguish how we use part (b) facts.  In particular, we need to distinguish the case where we know that UB would trigger on EC=x for this exit, and the case where the loop is guaranteed to exit through this exit (and thus *must* trigger UB).  For the first, we can clearly report UINT32_MAX udiv 3 as an exit count for this exit without considering any other exit or the structure of the loop.  For the second, we need the fact that this exit is the only exit and there are no abnormal exits to return anything less.  But interestingly, if we can return anything less, we can also return any arbitrary value (e.g. 0) because we have now proven this loop *must* execute UB.  (On this example, we can not do this last bit because @may_exit may be an abnormal exit.)

Hopefully I didn't make any critical mistakes in the above.  This stuff is subtle and confusing.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D101722/new/

https://reviews.llvm.org/D101722



More information about the llvm-commits mailing list