This is an archive of the discontinued LLVM Phabricator instance.

[JumpThreading] Fix a bug affecting guards and assumes
AbandonedPublic

Authored by reames on Jan 3 2017, 7:53 PM.

Details

Summary

This patch fixes an issue in jump threading where we'd sometimes use circular logic to fold the condition assumed or guarded to true. The code had an implicit assumption that a fact true at the end of a block must be true for all uses within the block. This is blatantly false. The net effect for guards was that we could remove a guard on a condition which wasn't actual true at runtime and miscompile.

I noticed this while working on another optimization patch. I'm a little terrified that we never noticed this previously.

Diff Detail

Event Timeline

reames updated this revision to Diff 82995.Jan 3 2017, 7:53 PM
reames retitled this revision from to [JumpThreading] Fix a bug affecting guards and assumes.
reames updated this object.
reames added reviewers: sanjoy, hfinkel, apilipenko.
reames added a subscriber: llvm-commits.
reames updated this revision to Diff 82996.Jan 3 2017, 7:55 PM

add files missed in initial diff

sanjoy requested changes to this revision.Jan 3 2017, 10:33 PM
sanjoy edited edge metadata.

Almost LGTM. Marking as needing changes to make sure we settle the replaceDominatedUsesWith issue before checking in.

lib/Transforms/Scalar/JumpThreading.cpp
834

Is this clang-formatted?

lib/Transforms/Utils/Local.cpp
1759

(In a separate change) What do you think about refactoring out a replaceUsesWithIf that takes a predicate to decide if a certain use needs to be replaced and change replaceNonLocalUsesWith and the two replaceDominatedUsesWith s to use it?

1764

Why not auto instead of Value::use_iterator?

1777

Stray newline?

1809

Please double check, but I don't think this is behavior equivalent. Today if we have

  br <cond>, left, merge

left:
  x = def()
  br merge

merge:
  t = phi(x, 42)

then replaceDominatedUsesWith(x, 100, DT, left) will not replace the use in the phi node. But with your change, we will get all of the uses in of x, including the one in the phi node.

The real problem here is that replaceDominatedUsesWith does not do what it says it does. Above the use of x in the phi node is, in fact, dominated by left, but since replaceDominatedUsesWith "decays" uses to instructions before checking dominance, that fact is lost.

In any case, if you want to make sure replaceNonLocalUsesWith is well tested, I'd nudge you towards adding a test or two in unittests/Transforms/Utils/Local.cpp.

test/Transforms/JumpThreading/assume.ll
89

I'd also add a test with an assume followed by a guard.

This revision now requires changes to proceed.Jan 3 2017, 10:33 PM
reames abandoned this revision.Jun 2 2017, 3:44 PM

Anna landed a patch which subsumes this one.