[LVI] Take guards into account
Teach LVI to gather control dependant constraints from guards.
Reviewed By: sanjoy
Differential Revision: https://reviews.llvm.org/D23358
llvm-svn: 278518
diff --git a/llvm/lib/Analysis/LazyValueInfo.cpp b/llvm/lib/Analysis/LazyValueInfo.cpp
index 7a94048..04cce6b 100644
--- a/llvm/lib/Analysis/LazyValueInfo.cpp
+++ b/llvm/lib/Analysis/LazyValueInfo.cpp
@@ -26,6 +26,7 @@
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/PatternMatch.h"
#include "llvm/IR/ValueHandle.h"
@@ -471,8 +472,9 @@
BasicBlock *BB);
bool solveBlockValueCast(LVILatticeVal &BBLV, Instruction *BBI,
BasicBlock *BB);
- void intersectAssumeBlockValueConstantRange(Value *Val, LVILatticeVal &BBLV,
- Instruction *BBI);
+ void intersectAssumeOrGuardBlockValueConstantRange(Value *Val,
+ LVILatticeVal &BBLV,
+ Instruction *BBI);
void solve();
@@ -864,9 +866,8 @@
// If we can determine a constraint on the value given conditions assumed by
// the program, intersect those constraints with BBLV
-void LazyValueInfoCache::intersectAssumeBlockValueConstantRange(Value *Val,
- LVILatticeVal &BBLV,
- Instruction *BBI) {
+void LazyValueInfoCache::intersectAssumeOrGuardBlockValueConstantRange(
+ Value *Val, LVILatticeVal &BBLV, Instruction *BBI) {
BBI = BBI ? BBI : dyn_cast<Instruction>(Val);
if (!BBI)
return;
@@ -880,6 +881,20 @@
BBLV = intersect(BBLV, getValueFromCondition(Val, I->getArgOperand(0)));
}
+
+ // If guards are not used in the module, don't spend time looking for them
+ auto *GuardDecl = BBI->getModule()->getFunction(
+ Intrinsic::getName(Intrinsic::experimental_guard));
+ if (!GuardDecl || GuardDecl->use_empty())
+ return;
+
+ for (BasicBlock::iterator I = BBI->getIterator(),
+ E = BBI->getParent()->begin(); I != E; I--) {
+ Value *Cond = nullptr;
+ if (!match(&*I, m_Intrinsic<Intrinsic::experimental_guard>(m_Value(Cond))))
+ continue;
+ BBLV = intersect(BBLV, getValueFromCondition(Val, Cond));
+ }
}
bool LazyValueInfoCache::solveBlockValueSelect(LVILatticeVal &BBLV,
@@ -1043,7 +1058,8 @@
ConstantRange LHSRange = ConstantRange(OperandBitWidth);
if (hasBlockValue(BBI->getOperand(0), BB)) {
LVILatticeVal LHSVal = getBlockValue(BBI->getOperand(0), BB);
- intersectAssumeBlockValueConstantRange(BBI->getOperand(0), LHSVal, BBI);
+ intersectAssumeOrGuardBlockValueConstantRange(BBI->getOperand(0), LHSVal,
+ BBI);
if (LHSVal.isConstantRange())
LHSRange = LHSVal.getConstantRange();
}
@@ -1120,7 +1136,8 @@
ConstantRange LHSRange = ConstantRange(OperandBitWidth);
if (hasBlockValue(BBI->getOperand(0), BB)) {
LVILatticeVal LHSVal = getBlockValue(BBI->getOperand(0), BB);
- intersectAssumeBlockValueConstantRange(BBI->getOperand(0), LHSVal, BBI);
+ intersectAssumeOrGuardBlockValueConstantRange(BBI->getOperand(0), LHSVal,
+ BBI);
if (LHSVal.isConstantRange())
LHSRange = LHSVal.getConstantRange();
}
@@ -1363,7 +1380,8 @@
// Try to intersect ranges of the BB and the constraint on the edge.
LVILatticeVal InBlock = getBlockValue(Val, BBFrom);
- intersectAssumeBlockValueConstantRange(Val, InBlock, BBFrom->getTerminator());
+ intersectAssumeOrGuardBlockValueConstantRange(Val, InBlock,
+ BBFrom->getTerminator());
// We can use the context instruction (generically the ultimate instruction
// the calling pass is trying to simplify) here, even though the result of
// this function is generally cached when called from the solve* functions
@@ -1372,7 +1390,7 @@
// functions, the context instruction is not provided. When called from
// LazyValueInfoCache::getValueOnEdge, the context instruction is provided,
// but then the result is not cached.
- intersectAssumeBlockValueConstantRange(Val, InBlock, CxtI);
+ intersectAssumeOrGuardBlockValueConstantRange(Val, InBlock, CxtI);
Result = intersect(LocalResult, InBlock);
return true;
@@ -1389,7 +1407,7 @@
solve();
}
LVILatticeVal Result = getBlockValue(V, BB);
- intersectAssumeBlockValueConstantRange(V, Result, CxtI);
+ intersectAssumeOrGuardBlockValueConstantRange(V, Result, CxtI);
DEBUG(dbgs() << " Result = " << Result << "\n");
return Result;
@@ -1405,7 +1423,7 @@
LVILatticeVal Result = LVILatticeVal::getOverdefined();
if (auto *I = dyn_cast<Instruction>(V))
Result = getFromRangeMetadata(I);
- intersectAssumeBlockValueConstantRange(V, Result, CxtI);
+ intersectAssumeOrGuardBlockValueConstantRange(V, Result, CxtI);
DEBUG(dbgs() << " Result = " << Result << "\n");
return Result;