summaryrefslogtreecommitdiff
path: root/lib/Analysis/LazyValueInfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Analysis/LazyValueInfo.cpp')
-rw-r--r--lib/Analysis/LazyValueInfo.cpp40
1 files changed, 36 insertions, 4 deletions
diff --git a/lib/Analysis/LazyValueInfo.cpp b/lib/Analysis/LazyValueInfo.cpp
index e6f586ac7029..f421d286e842 100644
--- a/lib/Analysis/LazyValueInfo.cpp
+++ b/lib/Analysis/LazyValueInfo.cpp
@@ -286,7 +286,7 @@ raw_ostream &operator<<(raw_ostream &OS, const LVILatticeVal &Val) {
<< Val.getConstantRange().getUpper() << '>';
return OS << "constant<" << *Val.getConstant() << '>';
}
-}
+} // namespace llvm
//===----------------------------------------------------------------------===//
// LazyValueInfoCache Decl
@@ -306,7 +306,7 @@ namespace {
deleted();
}
};
-}
+} // namespace
namespace {
/// This is the cache kept by LazyValueInfo which
@@ -1262,8 +1262,40 @@ LazyValueInfo::getPredicateAt(unsigned Pred, Value *V, Constant *C,
Instruction *CxtI) {
const DataLayout &DL = CxtI->getModule()->getDataLayout();
LVILatticeVal Result = getCache(PImpl, AC, &DL, DT).getValueAt(V, CxtI);
-
- return getPredicateResult(Pred, C, Result, DL, TLI);
+ Tristate Ret = getPredicateResult(Pred, C, Result, DL, TLI);
+ if (Ret != Unknown)
+ return Ret;
+
+ // TODO: Move this logic inside getValueAt so that it can be cached rather
+ // than re-queried on each call. This would also allow us to merge the
+ // underlying lattice values to get more information
+ if (CxtI) {
+ // For a comparison where the V is outside this block, it's possible
+ // that we've branched on it before. Look to see if the value is known
+ // on all incoming edges.
+ BasicBlock *BB = CxtI->getParent();
+ pred_iterator PI = pred_begin(BB), PE = pred_end(BB);
+ if (PI != PE &&
+ (!isa<Instruction>(V) ||
+ cast<Instruction>(V)->getParent() != BB)) {
+ // For predecessor edge, determine if the comparison is true or false
+ // on that edge. If they're all true or all false, we can conclude
+ // the value of the comparison in this block.
+ Tristate Baseline = getPredicateOnEdge(Pred, V, C, *PI, BB, CxtI);
+ if (Baseline != Unknown) {
+ // Check that all remaining incoming values match the first one.
+ while (++PI != PE) {
+ Tristate Ret = getPredicateOnEdge(Pred, V, C, *PI, BB, CxtI);
+ if (Ret != Baseline) break;
+ }
+ // If we terminated early, then one of the values didn't match.
+ if (PI == PE) {
+ return Baseline;
+ }
+ }
+ }
+ }
+ return Unknown;
}
void LazyValueInfo::threadEdge(BasicBlock *PredBB, BasicBlock *OldSucc,