[PATCH] ScalarEvolution incorrectly assumes that the start of certain add recurrences don't overflow

Sanjoy Das sanjoy at playingwithpointers.com
Fri Feb 6 22:43:07 PST 2015

> (where you also need to make sure that both are not nullptr). If the exit block is also the latch block, then there is no early-exit problem.

It depends on how you interpret poison semantics -- if you pretend that an `add nsw` "cannot" overflow then the above is sufficient.  But if you interpret poison to cause UB when you *use* the poison, then the above condition is not enough:  you could exit from the latch block in the first iteration, and not have a use of the overflowed `nsw` add and hence could not conclude that the addition would not overflow (since having an unused overflowed nsw add is okay).  In other words, the early exit could be as late as the latch block if the only use of the `add nsw` is the phi for the add recurrence:

  define i64 @foo(i32 %start, i32 %low.limit, i32 %high.limit) {
  ; CHECK-LABEL: Classifying expressions for: @foo
    %postinc.start = add i32 %start, 1
    br label %loop
    %idx = phi i32 [ %start, %entry ], [ %idx.inc, %loop ]
    %postinc = phi i32 [ %postinc.start, %entry ], [ %postinc.inc, %loop ]
    %postinc.inc = add nsw i32 %postinc, 1
    %postinc.sext = sext i32 %postinc to i64
    %break.early = icmp slt i32 %postinc, %low.limit
    %idx.inc = add nsw i32 %idx, 1
    br i1 %break.early, label %loop, label %early.exit
    ret i64 %postinc.sext

The only way out, AFAICT, is to prove that the backedge is taken at least once, because this means (assuming the pre-inc is `{S,+,X}<nsw>`) there has been a use of `add nsw S, X` in the phi node for the recurrence (even if the phi node has itself not been used).  But depending on how you interpret poison semantics, that may not be enough either.

All of this reasoning is shaky because currently LLVM does not have a consistent semantics for poison.  We may have to revisit this reasoning once it does :)



More information about the llvm-commits mailing list