Have isKnownNotFullPoison be smarter around control flow
Summary:
(... while still not using a PostDomTree)
The way we use isKnownNotFullPoison from SCEV today, the new CFG walking
logic will not trigger for any realistic cases -- it will kick in only
for situations where we could have merged the contiguous basic blocks
anyway[0], since the poison generating instruction dominates all of its
non-PHI uses (which are the only uses we consider right now).
However, having this change in place will allow a later bugfix to break
fewer llvm-lit tests.
[0]: i.e. cases where block A branches to block B and B is A's only
successor and A is B's only predecessor.
Reviewers: broune, bjarke.roune
Subscribers: mcrosier, llvm-commits
Differential Revision: http://reviews.llvm.org/D19212
llvm-svn: 267175
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 8d52a18..5ada78a 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -3543,26 +3543,44 @@
// Set of instructions that we have proved will yield poison if PoisonI
// does.
SmallSet<const Value *, 16> YieldsPoison;
+ SmallSet<const BasicBlock *, 4> Visited;
YieldsPoison.insert(PoisonI);
+ Visited.insert(PoisonI->getParent());
- for (BasicBlock::const_iterator I = PoisonI->getIterator(), E = BB->end();
- I != E; ++I) {
- if (&*I != PoisonI) {
- const Value *NotPoison = getGuaranteedNonFullPoisonOp(&*I);
- if (NotPoison != nullptr && YieldsPoison.count(NotPoison)) return true;
- if (!isGuaranteedToTransferExecutionToSuccessor(&*I))
- return false;
- }
+ BasicBlock::const_iterator Begin = PoisonI->getIterator(), End = BB->end();
- // Mark poison that propagates from I through uses of I.
- if (YieldsPoison.count(&*I)) {
- for (const User *User : I->users()) {
- const Instruction *UserI = cast<Instruction>(User);
- if (UserI->getParent() == BB && propagatesFullPoison(UserI))
- YieldsPoison.insert(User);
+ unsigned Iter = 0;
+ while (Iter++ < MaxDepth) {
+ for (auto &I : make_range(Begin, End)) {
+ if (&I != PoisonI) {
+ const Value *NotPoison = getGuaranteedNonFullPoisonOp(&I);
+ if (NotPoison != nullptr && YieldsPoison.count(NotPoison))
+ return true;
+ if (!isGuaranteedToTransferExecutionToSuccessor(&I))
+ return false;
+ }
+
+ // Mark poison that propagates from I through uses of I.
+ if (YieldsPoison.count(&I)) {
+ for (const User *User : I.users()) {
+ const Instruction *UserI = cast<Instruction>(User);
+ if (propagatesFullPoison(UserI))
+ YieldsPoison.insert(User);
+ }
}
}
- }
+
+ if (auto *NextBB = BB->getSingleSuccessor()) {
+ if (Visited.insert(NextBB).second) {
+ BB = NextBB;
+ Begin = BB->getFirstNonPHI()->getIterator();
+ End = BB->end();
+ continue;
+ }
+ }
+
+ break;
+ };
return false;
}