diff options
Diffstat (limited to 'contrib/llvm/lib/Analysis/LazyValueInfo.cpp')
-rw-r--r-- | contrib/llvm/lib/Analysis/LazyValueInfo.cpp | 964 |
1 files changed, 500 insertions, 464 deletions
diff --git a/contrib/llvm/lib/Analysis/LazyValueInfo.cpp b/contrib/llvm/lib/Analysis/LazyValueInfo.cpp index 3ce667f..d442310 100644 --- a/contrib/llvm/lib/Analysis/LazyValueInfo.cpp +++ b/contrib/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" @@ -50,7 +51,7 @@ namespace llvm { FunctionPass *createLazyValueInfoPass() { return new LazyValueInfoWrapperPass(); } } -char LazyValueAnalysis::PassID; +AnalysisKey LazyValueAnalysis::Key; //===----------------------------------------------------------------------===// // LVILatticeVal @@ -70,12 +71,14 @@ class LVILatticeVal { /// "nothing known yet". undefined, - /// This Value has a specific constant value. (For integers, constantrange - /// is used instead.) + /// This Value has a specific constant value. (For constant integers, + /// constantrange is used instead. Integer typed constantexprs can appear + /// as constant.) constant, - /// This Value is known to not have the specified value. (For integers, - /// constantrange is used instead.) + /// This Value is known to not have the specified value. (For constant + /// integers, constantrange is used instead. As above, integer typed + /// constantexprs can appear here.) notconstant, /// The Value falls within this range. (Used only for integer typed values.) @@ -139,37 +142,37 @@ public: return Range; } - /// Return true if this is a change in status. - bool markOverdefined() { +private: + void markOverdefined() { if (isOverdefined()) - return false; + return; Tag = overdefined; - return true; } - /// Return true if this is a change in status. - bool markConstant(Constant *V) { + void markConstant(Constant *V) { assert(V && "Marking constant with NULL"); - if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) - return markConstantRange(ConstantRange(CI->getValue())); + if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) { + markConstantRange(ConstantRange(CI->getValue())); + return; + } if (isa<UndefValue>(V)) - return false; + return; assert((!isConstant() || getConstant() == V) && "Marking constant with different value"); assert(isUndefined()); Tag = constant; Val = V; - return true; } - /// Return true if this is a change in status. - bool markNotConstant(Constant *V) { + void markNotConstant(Constant *V) { assert(V && "Marking constant with NULL"); - if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) - return markConstantRange(ConstantRange(CI->getValue()+1, CI->getValue())); + if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) { + markConstantRange(ConstantRange(CI->getValue()+1, CI->getValue())); + return; + } if (isa<UndefValue>(V)) - return false; + return; assert((!isConstant() || getConstant() != V) && "Marking constant !constant with same value"); @@ -178,100 +181,70 @@ public: assert(isUndefined() || isConstant()); Tag = notconstant; Val = V; - return true; } - /// Return true if this is a change in status. - bool markConstantRange(ConstantRange NewR) { + void markConstantRange(ConstantRange NewR) { if (isConstantRange()) { if (NewR.isEmptySet()) - return markOverdefined(); - - bool changed = Range != NewR; - Range = std::move(NewR); - return changed; + markOverdefined(); + else { + Range = std::move(NewR); + } + return; } assert(isUndefined()); if (NewR.isEmptySet()) - return markOverdefined(); - - Tag = constantrange; - Range = std::move(NewR); - return true; + markOverdefined(); + else { + Tag = constantrange; + Range = std::move(NewR); + } } +public: + /// Merge the specified lattice value into this one, updating this /// one and returning true if anything changed. - bool mergeIn(const LVILatticeVal &RHS, const DataLayout &DL) { - if (RHS.isUndefined() || isOverdefined()) return false; - if (RHS.isOverdefined()) return markOverdefined(); + void mergeIn(const LVILatticeVal &RHS, const DataLayout &DL) { + if (RHS.isUndefined() || isOverdefined()) + return; + if (RHS.isOverdefined()) { + markOverdefined(); + return; + } if (isUndefined()) { - Tag = RHS.Tag; - Val = RHS.Val; - Range = RHS.Range; - return true; + *this = RHS; + return; } if (isConstant()) { - if (RHS.isConstant()) { - if (Val == RHS.Val) - return false; - return markOverdefined(); - } - - if (RHS.isNotConstant()) { - if (Val == RHS.Val) - return markOverdefined(); - - // Unless we can prove that the two Constants are different, we must - // move to overdefined. - if (ConstantInt *Res = - dyn_cast<ConstantInt>(ConstantFoldCompareInstOperands( - CmpInst::ICMP_NE, getConstant(), RHS.getNotConstant(), DL))) - if (Res->isOne()) - return markNotConstant(RHS.getNotConstant()); - - return markOverdefined(); - } - - return markOverdefined(); + if (RHS.isConstant() && Val == RHS.Val) + return; + markOverdefined(); + return; } if (isNotConstant()) { - if (RHS.isConstant()) { - if (Val == RHS.Val) - return markOverdefined(); - - // Unless we can prove that the two Constants are different, we must - // move to overdefined. - if (ConstantInt *Res = - dyn_cast<ConstantInt>(ConstantFoldCompareInstOperands( - CmpInst::ICMP_NE, getNotConstant(), RHS.getConstant(), DL))) - if (Res->isOne()) - return false; - - return markOverdefined(); - } - - if (RHS.isNotConstant()) { - if (Val == RHS.Val) - return false; - return markOverdefined(); - } - - return markOverdefined(); + if (RHS.isNotConstant() && Val == RHS.Val) + return; + markOverdefined(); + return; } assert(isConstantRange() && "New LVILattice type?"); - if (!RHS.isConstantRange()) - return markOverdefined(); - + if (!RHS.isConstantRange()) { + // We can get here if we've encountered a constantexpr of integer type + // and merge it with a constantrange. + markOverdefined(); + return; + } ConstantRange NewR = Range.unionWith(RHS.getConstantRange()); if (NewR.isFullSet()) - return markOverdefined(); - return markConstantRange(NewR); + markOverdefined(); + else + markConstantRange(NewR); } }; @@ -366,6 +339,9 @@ namespace { /// A callback value handle updates the cache when values are erased. class LazyValueInfoCache; struct LVIValueHandle final : public CallbackVH { + // Needs to access getValPtr(), which is protected. + friend struct DenseMapInfo<LVIValueHandle>; + LazyValueInfoCache *Parent; LVIValueHandle(Value *V, LazyValueInfoCache *P) @@ -376,7 +352,7 @@ namespace { deleted(); } }; -} +} // end anonymous namespace namespace { /// This is the cache kept by LazyValueInfo which @@ -387,12 +363,15 @@ namespace { /// entries, allowing us to do a lookup with a binary search. /// Over-defined lattice values are recorded in OverDefinedCache to reduce /// memory overhead. - typedef SmallDenseMap<AssertingVH<BasicBlock>, LVILatticeVal, 4> - ValueCacheEntryTy; + struct ValueCacheEntryTy { + ValueCacheEntryTy(Value *V, LazyValueInfoCache *P) : Handle(V, P) {} + LVIValueHandle Handle; + SmallDenseMap<AssertingVH<BasicBlock>, LVILatticeVal, 4> BlockVals; + }; /// This is all of the cached information for all values, /// mapped from Value* to key information. - std::map<LVIValueHandle, ValueCacheEntryTy> ValueCache; + DenseMap<Value *, std::unique_ptr<ValueCacheEntryTy>> ValueCache; /// This tracks, on a per-block basis, the set of values that are /// over-defined at the end of that block. @@ -404,6 +383,183 @@ namespace { /// don't spend time removing unused blocks from our caches. DenseSet<AssertingVH<BasicBlock> > SeenBlocks; + public: + void insertResult(Value *Val, BasicBlock *BB, const LVILatticeVal &Result) { + SeenBlocks.insert(BB); + + // Insert over-defined values into their own cache to reduce memory + // overhead. + if (Result.isOverdefined()) + OverDefinedCache[BB].insert(Val); + else { + auto It = ValueCache.find_as(Val); + if (It == ValueCache.end()) { + ValueCache[Val] = make_unique<ValueCacheEntryTy>(Val, this); + It = ValueCache.find_as(Val); + assert(It != ValueCache.end() && "Val was just added to the map!"); + } + It->second->BlockVals[BB] = Result; + } + } + + bool isOverdefined(Value *V, BasicBlock *BB) const { + auto ODI = OverDefinedCache.find(BB); + + if (ODI == OverDefinedCache.end()) + return false; + + return ODI->second.count(V); + } + + bool hasCachedValueInfo(Value *V, BasicBlock *BB) const { + if (isOverdefined(V, BB)) + return true; + + auto I = ValueCache.find_as(V); + if (I == ValueCache.end()) + return false; + + return I->second->BlockVals.count(BB); + } + + LVILatticeVal getCachedValueInfo(Value *V, BasicBlock *BB) const { + if (isOverdefined(V, BB)) + return LVILatticeVal::getOverdefined(); + + auto I = ValueCache.find_as(V); + if (I == ValueCache.end()) + return LVILatticeVal(); + auto BBI = I->second->BlockVals.find(BB); + if (BBI == I->second->BlockVals.end()) + return LVILatticeVal(); + return BBI->second; + } + + /// clear - Empty the cache. + void clear() { + SeenBlocks.clear(); + ValueCache.clear(); + OverDefinedCache.clear(); + } + + /// Inform the cache that a given value has been deleted. + void eraseValue(Value *V); + + /// This is part of the update interface to inform the cache + /// that a block has been deleted. + void eraseBlock(BasicBlock *BB); + + /// Updates the cache to remove any influence an overdefined value in + /// OldSucc might have (unless also overdefined in NewSucc). This just + /// flushes elements from the cache and does not add any. + void threadEdgeImpl(BasicBlock *OldSucc,BasicBlock *NewSucc); + + friend struct LVIValueHandle; + }; +} + +void LazyValueInfoCache::eraseValue(Value *V) { + SmallVector<AssertingVH<BasicBlock>, 4> ToErase; + for (auto &I : OverDefinedCache) { + SmallPtrSetImpl<Value *> &ValueSet = I.second; + ValueSet.erase(V); + if (ValueSet.empty()) + ToErase.push_back(I.first); + } + for (auto &BB : ToErase) + OverDefinedCache.erase(BB); + + ValueCache.erase(V); +} + +void LVIValueHandle::deleted() { + // This erasure deallocates *this, so it MUST happen after we're done + // using any and all members of *this. + Parent->eraseValue(*this); +} + +void LazyValueInfoCache::eraseBlock(BasicBlock *BB) { + // Shortcut if we have never seen this block. + DenseSet<AssertingVH<BasicBlock> >::iterator I = SeenBlocks.find(BB); + if (I == SeenBlocks.end()) + return; + SeenBlocks.erase(I); + + auto ODI = OverDefinedCache.find(BB); + if (ODI != OverDefinedCache.end()) + OverDefinedCache.erase(ODI); + + for (auto &I : ValueCache) + I.second->BlockVals.erase(BB); +} + +void LazyValueInfoCache::threadEdgeImpl(BasicBlock *OldSucc, + BasicBlock *NewSucc) { + // When an edge in the graph has been threaded, values that we could not + // determine a value for before (i.e. were marked overdefined) may be + // possible to solve now. We do NOT try to proactively update these values. + // Instead, we clear their entries from the cache, and allow lazy updating to + // recompute them when needed. + + // The updating process is fairly simple: we need to drop cached info + // for all values that were marked overdefined in OldSucc, and for those same + // values in any successor of OldSucc (except NewSucc) in which they were + // also marked overdefined. + std::vector<BasicBlock*> worklist; + worklist.push_back(OldSucc); + + auto I = OverDefinedCache.find(OldSucc); + if (I == OverDefinedCache.end()) + return; // Nothing to process here. + SmallVector<Value *, 4> ValsToClear(I->second.begin(), I->second.end()); + + // Use a worklist to perform a depth-first search of OldSucc's successors. + // NOTE: We do not need a visited list since any blocks we have already + // visited will have had their overdefined markers cleared already, and we + // thus won't loop to their successors. + while (!worklist.empty()) { + BasicBlock *ToUpdate = worklist.back(); + worklist.pop_back(); + + // Skip blocks only accessible through NewSucc. + if (ToUpdate == NewSucc) continue; + + // If a value was marked overdefined in OldSucc, and is here too... + auto OI = OverDefinedCache.find(ToUpdate); + if (OI == OverDefinedCache.end()) + continue; + SmallPtrSetImpl<Value *> &ValueSet = OI->second; + + bool changed = false; + for (Value *V : ValsToClear) { + if (!ValueSet.erase(V)) + continue; + + // If we removed anything, then we potentially need to update + // blocks successors too. + changed = true; + + if (ValueSet.empty()) { + OverDefinedCache.erase(OI); + break; + } + } + + if (!changed) continue; + + worklist.insert(worklist.end(), succ_begin(ToUpdate), succ_end(ToUpdate)); + } +} + +namespace { + // The actual implementation of the lazy analysis and update. Note that the + // inheritance from LazyValueInfoCache is intended to be temporary while + // splitting the code and then transitioning to a has-a relationship. + class LazyValueInfoImpl { + + /// Cached results from previous queries + LazyValueInfoCache TheCache; + /// This stack holds the state of the value solver during a query. /// It basically emulates the callstack of the naive /// recursive value lookup process. @@ -428,19 +584,6 @@ namespace { const DataLayout &DL; ///< A mandatory DataLayout DominatorTree *DT; ///< An optional DT pointer. - friend struct LVIValueHandle; - - void insertResult(Value *Val, BasicBlock *BB, const LVILatticeVal &Result) { - SeenBlocks.insert(BB); - - // Insert over-defined values into their own cache to reduce memory - // overhead. - if (Result.isOverdefined()) - OverDefinedCache[BB].insert(Val); - else - lookup(Val)[BB] = Result; - } - LVILatticeVal getBlockValue(Value *Val, BasicBlock *BB); bool getEdgeValue(Value *V, BasicBlock *F, BasicBlock *T, LVILatticeVal &Result, Instruction *CxtI = nullptr); @@ -450,6 +593,7 @@ namespace { // returned means that the work item was not completely processed and must // be revisited after going through the new items. bool solveBlockValue(Value *Val, BasicBlock *BB); + bool solveBlockValueImpl(LVILatticeVal &Res, Value *Val, BasicBlock *BB); bool solveBlockValueNonLocal(LVILatticeVal &BBLV, Value *Val, BasicBlock *BB); bool solveBlockValuePHINode(LVILatticeVal &BBLV, PHINode *PN, BasicBlock *BB); bool solveBlockValueSelect(LVILatticeVal &BBLV, SelectInst *S, @@ -458,43 +602,12 @@ namespace { BasicBlock *BB); bool solveBlockValueCast(LVILatticeVal &BBLV, Instruction *BBI, BasicBlock *BB); - void intersectAssumeBlockValueConstantRange(Value *Val, LVILatticeVal &BBLV, + void intersectAssumeOrGuardBlockValueConstantRange(Value *Val, + LVILatticeVal &BBLV, Instruction *BBI); void solve(); - ValueCacheEntryTy &lookup(Value *V) { - return ValueCache[LVIValueHandle(V, this)]; - } - - bool isOverdefined(Value *V, BasicBlock *BB) const { - auto ODI = OverDefinedCache.find(BB); - - if (ODI == OverDefinedCache.end()) - return false; - - return ODI->second.count(V); - } - - bool hasCachedValueInfo(Value *V, BasicBlock *BB) { - if (isOverdefined(V, BB)) - return true; - - LVIValueHandle ValHandle(V, this); - auto I = ValueCache.find(ValHandle); - if (I == ValueCache.end()) - return false; - - return I->second.count(BB); - } - - LVILatticeVal getCachedValueInfo(Value *V, BasicBlock *BB) { - if (isOverdefined(V, BB)) - return LVILatticeVal::getOverdefined(); - - return lookup(V)[BB]; - } - public: /// This is the query interface to determine the lattice /// value for the specified Value* at the end of the specified block. @@ -511,60 +624,28 @@ namespace { LVILatticeVal getValueOnEdge(Value *V, BasicBlock *FromBB,BasicBlock *ToBB, Instruction *CxtI = nullptr); - /// This is the update interface to inform the cache that an edge from - /// PredBB to OldSucc has been threaded to be from PredBB to NewSucc. - void threadEdge(BasicBlock *PredBB,BasicBlock *OldSucc,BasicBlock *NewSucc); + /// Complete flush all previously computed values + void clear() { + TheCache.clear(); + } /// This is part of the update interface to inform the cache /// that a block has been deleted. - void eraseBlock(BasicBlock *BB); - - /// clear - Empty the cache. - void clear() { - SeenBlocks.clear(); - ValueCache.clear(); - OverDefinedCache.clear(); + void eraseBlock(BasicBlock *BB) { + TheCache.eraseBlock(BB); } - LazyValueInfoCache(AssumptionCache *AC, const DataLayout &DL, + /// This is the update interface to inform the cache that an edge from + /// PredBB to OldSucc has been threaded to be from PredBB to NewSucc. + void threadEdge(BasicBlock *PredBB,BasicBlock *OldSucc,BasicBlock *NewSucc); + + LazyValueInfoImpl(AssumptionCache *AC, const DataLayout &DL, DominatorTree *DT = nullptr) : AC(AC), DL(DL), DT(DT) {} }; } // end anonymous namespace -void LVIValueHandle::deleted() { - SmallVector<AssertingVH<BasicBlock>, 4> ToErase; - for (auto &I : Parent->OverDefinedCache) { - SmallPtrSetImpl<Value *> &ValueSet = I.second; - if (ValueSet.count(getValPtr())) - ValueSet.erase(getValPtr()); - if (ValueSet.empty()) - ToErase.push_back(I.first); - } - for (auto &BB : ToErase) - Parent->OverDefinedCache.erase(BB); - - // This erasure deallocates *this, so it MUST happen after we're done - // using any and all members of *this. - Parent->ValueCache.erase(*this); -} - -void LazyValueInfoCache::eraseBlock(BasicBlock *BB) { - // Shortcut if we have never seen this block. - DenseSet<AssertingVH<BasicBlock> >::iterator I = SeenBlocks.find(BB); - if (I == SeenBlocks.end()) - return; - SeenBlocks.erase(I); - - auto ODI = OverDefinedCache.find(BB); - if (ODI != OverDefinedCache.end()) - OverDefinedCache.erase(ODI); - - for (auto &I : ValueCache) - I.second.erase(BB); -} - -void LazyValueInfoCache::solve() { +void LazyValueInfoImpl::solve() { while (!BlockValueStack.empty()) { std::pair<BasicBlock*, Value*> &e = BlockValueStack.top(); assert(BlockValueSet.count(e) && "Stack value should be in BlockValueSet!"); @@ -572,11 +653,11 @@ void LazyValueInfoCache::solve() { if (solveBlockValue(e.second, e.first)) { // The work item was completely processed. assert(BlockValueStack.top() == e && "Nothing should have been pushed!"); - assert(hasCachedValueInfo(e.second, e.first) && + assert(TheCache.hasCachedValueInfo(e.second, e.first) && "Result should be in cache!"); DEBUG(dbgs() << "POP " << *e.second << " in " << e.first->getName() - << " = " << getCachedValueInfo(e.second, e.first) << "\n"); + << " = " << TheCache.getCachedValueInfo(e.second, e.first) << "\n"); BlockValueStack.pop(); BlockValueSet.erase(e); @@ -587,21 +668,20 @@ void LazyValueInfoCache::solve() { } } -bool LazyValueInfoCache::hasBlockValue(Value *Val, BasicBlock *BB) { +bool LazyValueInfoImpl::hasBlockValue(Value *Val, BasicBlock *BB) { // If already a constant, there is nothing to compute. if (isa<Constant>(Val)) return true; - return hasCachedValueInfo(Val, BB); + return TheCache.hasCachedValueInfo(Val, BB); } -LVILatticeVal LazyValueInfoCache::getBlockValue(Value *Val, BasicBlock *BB) { +LVILatticeVal LazyValueInfoImpl::getBlockValue(Value *Val, BasicBlock *BB) { // If already a constant, there is nothing to compute. if (Constant *VC = dyn_cast<Constant>(Val)) return LVILatticeVal::get(VC); - SeenBlocks.insert(BB); - return getCachedValueInfo(Val, BB); + return TheCache.getCachedValueInfo(Val, BB); } static LVILatticeVal getFromRangeMetadata(Instruction *BBI) { @@ -610,7 +690,7 @@ static LVILatticeVal getFromRangeMetadata(Instruction *BBI) { case Instruction::Load: case Instruction::Call: case Instruction::Invoke: - if (MDNode *Ranges = BBI->getMetadata(LLVMContext::MD_range)) + if (MDNode *Ranges = BBI->getMetadata(LLVMContext::MD_range)) if (isa<IntegerType>(BBI->getType())) { return LVILatticeVal::getRange(getConstantRangeFromMetadata(*Ranges)); } @@ -620,14 +700,14 @@ static LVILatticeVal getFromRangeMetadata(Instruction *BBI) { return LVILatticeVal::getOverdefined(); } -bool LazyValueInfoCache::solveBlockValue(Value *Val, BasicBlock *BB) { +bool LazyValueInfoImpl::solveBlockValue(Value *Val, BasicBlock *BB) { if (isa<Constant>(Val)) return true; - if (hasCachedValueInfo(Val, BB)) { + if (TheCache.hasCachedValueInfo(Val, BB)) { // If we have a cached value, use that. DEBUG(dbgs() << " reuse BB '" << BB->getName() - << "' val=" << getCachedValueInfo(Val, BB) << '\n'); + << "' val=" << TheCache.getCachedValueInfo(Val, BB) << '\n'); // Since we're reusing a cached value, we don't need to update the // OverDefinedCache. The cache will have been properly updated whenever the @@ -638,28 +718,26 @@ bool LazyValueInfoCache::solveBlockValue(Value *Val, BasicBlock *BB) { // Hold off inserting this value into the Cache in case we have to return // false and come back later. LVILatticeVal Res; + if (!solveBlockValueImpl(Res, Val, BB)) + // Work pushed, will revisit + return false; + + TheCache.insertResult(Val, BB, Res); + return true; +} + +bool LazyValueInfoImpl::solveBlockValueImpl(LVILatticeVal &Res, + Value *Val, BasicBlock *BB) { Instruction *BBI = dyn_cast<Instruction>(Val); - if (!BBI || BBI->getParent() != BB) { - if (!solveBlockValueNonLocal(Res, Val, BB)) - return false; - insertResult(Val, BB, Res); - return true; - } + if (!BBI || BBI->getParent() != BB) + return solveBlockValueNonLocal(Res, Val, BB); - if (PHINode *PN = dyn_cast<PHINode>(BBI)) { - if (!solveBlockValuePHINode(Res, PN, BB)) - return false; - insertResult(Val, BB, Res); - return true; - } + if (PHINode *PN = dyn_cast<PHINode>(BBI)) + return solveBlockValuePHINode(Res, PN, BB); - if (auto *SI = dyn_cast<SelectInst>(BBI)) { - if (!solveBlockValueSelect(Res, SI, BB)) - return false; - insertResult(Val, BB, Res); - return true; - } + if (auto *SI = dyn_cast<SelectInst>(BBI)) + return solveBlockValueSelect(Res, SI, BB); // If this value is a nonnull pointer, record it's range and bailout. Note // that for all other pointer typed values, we terminate the search at the @@ -673,29 +751,20 @@ bool LazyValueInfoCache::solveBlockValue(Value *Val, BasicBlock *BB) { PointerType *PT = dyn_cast<PointerType>(BBI->getType()); if (PT && isKnownNonNull(BBI)) { Res = LVILatticeVal::getNot(ConstantPointerNull::get(PT)); - insertResult(Val, BB, Res); return true; } if (BBI->getType()->isIntegerTy()) { - if (isa<CastInst>(BBI)) { - if (!solveBlockValueCast(Res, BBI, BB)) - return false; - insertResult(Val, BB, Res); - return true; - } + if (isa<CastInst>(BBI)) + return solveBlockValueCast(Res, BBI, BB); + BinaryOperator *BO = dyn_cast<BinaryOperator>(BBI); - if (BO && isa<ConstantInt>(BO->getOperand(1))) { - if (!solveBlockValueBinaryOp(Res, BBI, BB)) - return false; - insertResult(Val, BB, Res); - return true; - } + if (BO && isa<ConstantInt>(BO->getOperand(1))) + return solveBlockValueBinaryOp(Res, BBI, BB); } DEBUG(dbgs() << " compute BB '" << BB->getName() << "' - unknown inst def found.\n"); Res = getFromRangeMetadata(BBI); - insertResult(Val, BB, Res); return true; } @@ -748,7 +817,7 @@ static bool isObjectDereferencedInBlock(Value *Val, BasicBlock *BB) { return false; } -bool LazyValueInfoCache::solveBlockValueNonLocal(LVILatticeVal &BBLV, +bool LazyValueInfoImpl::solveBlockValueNonLocal(LVILatticeVal &BBLV, Value *Val, BasicBlock *BB) { LVILatticeVal Result; // Start Undefined. @@ -763,7 +832,7 @@ bool LazyValueInfoCache::solveBlockValueNonLocal(LVILatticeVal &BBLV, PointerType *PTy = cast<PointerType>(Val->getType()); Result = LVILatticeVal::getNot(ConstantPointerNull::get(PTy)); } else { - Result.markOverdefined(); + Result = LVILatticeVal::getOverdefined(); } BBLV = Result; return true; @@ -785,7 +854,7 @@ bool LazyValueInfoCache::solveBlockValueNonLocal(LVILatticeVal &BBLV, if (Result.isOverdefined()) { DEBUG(dbgs() << " compute BB '" << BB->getName() << "' - overdefined because of pred (non local).\n"); - // Bofore giving up, see if we can prove the pointer non-null local to + // Before giving up, see if we can prove the pointer non-null local to // this particular block. if (Val->getType()->isPointerTy() && isObjectDereferencedInBlock(Val, BB)) { @@ -806,7 +875,7 @@ bool LazyValueInfoCache::solveBlockValueNonLocal(LVILatticeVal &BBLV, return true; } -bool LazyValueInfoCache::solveBlockValuePHINode(LVILatticeVal &BBLV, +bool LazyValueInfoImpl::solveBlockValuePHINode(LVILatticeVal &BBLV, PHINode *PN, BasicBlock *BB) { LVILatticeVal Result; // Start Undefined. @@ -845,64 +914,70 @@ bool LazyValueInfoCache::solveBlockValuePHINode(LVILatticeVal &BBLV, return true; } -static bool getValueFromFromCondition(Value *Val, ICmpInst *ICI, - LVILatticeVal &Result, - bool isTrueDest = true); +static LVILatticeVal getValueFromCondition(Value *Val, Value *Cond, + bool isTrueDest = true); // 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 LazyValueInfoImpl::intersectAssumeOrGuardBlockValueConstantRange( + Value *Val, LVILatticeVal &BBLV, Instruction *BBI) { BBI = BBI ? BBI : dyn_cast<Instruction>(Val); if (!BBI) return; - for (auto &AssumeVH : AC->assumptions()) { + for (auto &AssumeVH : AC->assumptionsFor(Val)) { if (!AssumeVH) continue; auto *I = cast<CallInst>(AssumeVH); if (!isValidAssumeForContext(I, BBI, DT)) continue; - Value *C = I->getArgOperand(0); - if (ICmpInst *ICI = dyn_cast<ICmpInst>(C)) { - LVILatticeVal Result; - if (getValueFromFromCondition(Val, ICI, Result)) - BBLV = intersect(BBLV, Result); - } + 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 (Instruction &I : make_range(BBI->getIterator().getReverse(), + BBI->getParent()->rend())) { + Value *Cond = nullptr; + if (match(&I, m_Intrinsic<Intrinsic::experimental_guard>(m_Value(Cond)))) + BBLV = intersect(BBLV, getValueFromCondition(Val, Cond)); } } -bool LazyValueInfoCache::solveBlockValueSelect(LVILatticeVal &BBLV, +bool LazyValueInfoImpl::solveBlockValueSelect(LVILatticeVal &BBLV, SelectInst *SI, BasicBlock *BB) { // Recurse on our inputs if needed if (!hasBlockValue(SI->getTrueValue(), BB)) { if (pushBlockValue(std::make_pair(BB, SI->getTrueValue()))) return false; - BBLV.markOverdefined(); + BBLV = LVILatticeVal::getOverdefined(); return true; } LVILatticeVal TrueVal = getBlockValue(SI->getTrueValue(), BB); // If we hit overdefined, don't ask more queries. We want to avoid poisoning // extra slots in the table if we can. if (TrueVal.isOverdefined()) { - BBLV.markOverdefined(); + BBLV = LVILatticeVal::getOverdefined(); return true; } if (!hasBlockValue(SI->getFalseValue(), BB)) { if (pushBlockValue(std::make_pair(BB, SI->getFalseValue()))) return false; - BBLV.markOverdefined(); + BBLV = LVILatticeVal::getOverdefined(); return true; } LVILatticeVal FalseVal = getBlockValue(SI->getFalseValue(), BB); // If we hit overdefined, don't ask more queries. We want to avoid poisoning // extra slots in the table if we can. if (FalseVal.isOverdefined()) { - BBLV.markOverdefined(); + BBLV = LVILatticeVal::getOverdefined(); return true; } @@ -916,22 +991,22 @@ bool LazyValueInfoCache::solveBlockValueSelect(LVILatticeVal &BBLV, // ValueTracking getting smarter looking back past our immediate inputs.) if (SelectPatternResult::isMinOrMax(SPR.Flavor) && LHS == SI->getTrueValue() && RHS == SI->getFalseValue()) { - switch (SPR.Flavor) { - default: - llvm_unreachable("unexpected minmax type!"); - case SPF_SMIN: /// Signed minimum - BBLV.markConstantRange(TrueCR.smin(FalseCR)); - return true; - case SPF_UMIN: /// Unsigned minimum - BBLV.markConstantRange(TrueCR.umin(FalseCR)); - return true; - case SPF_SMAX: /// Signed maximum - BBLV.markConstantRange(TrueCR.smax(FalseCR)); - return true; - case SPF_UMAX: /// Unsigned maximum - BBLV.markConstantRange(TrueCR.umax(FalseCR)); - return true; - }; + ConstantRange ResultCR = [&]() { + switch (SPR.Flavor) { + default: + llvm_unreachable("unexpected minmax type!"); + case SPF_SMIN: /// Signed minimum + return TrueCR.smin(FalseCR); + case SPF_UMIN: /// Unsigned minimum + return TrueCR.umin(FalseCR); + case SPF_SMAX: /// Signed maximum + return TrueCR.smax(FalseCR); + case SPF_UMAX: /// Unsigned maximum + return TrueCR.umax(FalseCR); + }; + }(); + BBLV = LVILatticeVal::getRange(ResultCR); + return true; } // TODO: ABS, NABS from the SelectPatternResult @@ -940,27 +1015,21 @@ bool LazyValueInfoCache::solveBlockValueSelect(LVILatticeVal &BBLV, // Can we constrain the facts about the true and false values by using the // condition itself? This shows up with idioms like e.g. select(a > 5, a, 5). // TODO: We could potentially refine an overdefined true value above. - if (auto *ICI = dyn_cast<ICmpInst>(SI->getCondition())) { - LVILatticeVal TrueValTaken, FalseValTaken; - if (!getValueFromFromCondition(SI->getTrueValue(), ICI, - TrueValTaken, true)) - TrueValTaken.markOverdefined(); - if (!getValueFromFromCondition(SI->getFalseValue(), ICI, - FalseValTaken, false)) - FalseValTaken.markOverdefined(); - - TrueVal = intersect(TrueVal, TrueValTaken); - FalseVal = intersect(FalseVal, FalseValTaken); - - - // Handle clamp idioms such as: - // %24 = constantrange<0, 17> - // %39 = icmp eq i32 %24, 0 - // %40 = add i32 %24, -1 - // %siv.next = select i1 %39, i32 16, i32 %40 - // %siv.next = constantrange<0, 17> not <-1, 17> - // In general, this can handle any clamp idiom which tests the edge - // condition via an equality or inequality. + Value *Cond = SI->getCondition(); + TrueVal = intersect(TrueVal, + getValueFromCondition(SI->getTrueValue(), Cond, true)); + FalseVal = intersect(FalseVal, + getValueFromCondition(SI->getFalseValue(), Cond, false)); + + // Handle clamp idioms such as: + // %24 = constantrange<0, 17> + // %39 = icmp eq i32 %24, 0 + // %40 = add i32 %24, -1 + // %siv.next = select i1 %39, i32 16, i32 %40 + // %siv.next = constantrange<0, 17> not <-1, 17> + // In general, this can handle any clamp idiom which tests the edge + // condition via an equality or inequality. + if (auto *ICI = dyn_cast<ICmpInst>(Cond)) { ICmpInst::Predicate Pred = ICI->getPredicate(); Value *A = ICI->getOperand(0); if (ConstantInt *CIBase = dyn_cast<ConstantInt>(ICI->getOperand(1))) { @@ -1001,13 +1070,13 @@ bool LazyValueInfoCache::solveBlockValueSelect(LVILatticeVal &BBLV, return true; } -bool LazyValueInfoCache::solveBlockValueCast(LVILatticeVal &BBLV, +bool LazyValueInfoImpl::solveBlockValueCast(LVILatticeVal &BBLV, Instruction *BBI, BasicBlock *BB) { if (!BBI->getOperand(0)->getType()->isSized()) { // Without knowing how wide the input is, we can't analyze it in any useful // way. - BBLV.markOverdefined(); + BBLV = LVILatticeVal::getOverdefined(); return true; } @@ -1024,7 +1093,7 @@ bool LazyValueInfoCache::solveBlockValueCast(LVILatticeVal &BBLV, // Unhandled instructions are overdefined. DEBUG(dbgs() << " compute BB '" << BB->getName() << "' - overdefined (unknown cast).\n"); - BBLV.markOverdefined(); + BBLV = LVILatticeVal::getOverdefined(); return true; } @@ -1041,7 +1110,8 @@ bool LazyValueInfoCache::solveBlockValueCast(LVILatticeVal &BBLV, 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(); } @@ -1052,31 +1122,12 @@ bool LazyValueInfoCache::solveBlockValueCast(LVILatticeVal &BBLV, // NOTE: We're currently limited by the set of operations that ConstantRange // can evaluate symbolically. Enhancing that set will allows us to analyze // more definitions. - LVILatticeVal Result; - switch (BBI->getOpcode()) { - case Instruction::Trunc: - Result.markConstantRange(LHSRange.truncate(ResultBitWidth)); - break; - case Instruction::SExt: - Result.markConstantRange(LHSRange.signExtend(ResultBitWidth)); - break; - case Instruction::ZExt: - Result.markConstantRange(LHSRange.zeroExtend(ResultBitWidth)); - break; - case Instruction::BitCast: - Result.markConstantRange(LHSRange); - break; - default: - // Should be dead if the code above is correct - llvm_unreachable("inconsistent with above"); - break; - } - - BBLV = Result; + auto CastOp = (Instruction::CastOps) BBI->getOpcode(); + BBLV = LVILatticeVal::getRange(LHSRange.castOp(CastOp, ResultBitWidth)); return true; } -bool LazyValueInfoCache::solveBlockValueBinaryOp(LVILatticeVal &BBLV, +bool LazyValueInfoImpl::solveBlockValueBinaryOp(LVILatticeVal &BBLV, Instruction *BBI, BasicBlock *BB) { @@ -1101,7 +1152,7 @@ bool LazyValueInfoCache::solveBlockValueBinaryOp(LVILatticeVal &BBLV, // Unhandled instructions are overdefined. DEBUG(dbgs() << " compute BB '" << BB->getName() << "' - overdefined (unknown binary operator).\n"); - BBLV.markOverdefined(); + BBLV = LVILatticeVal::getOverdefined(); return true; }; @@ -1118,7 +1169,8 @@ bool LazyValueInfoCache::solveBlockValueBinaryOp(LVILatticeVal &BBLV, 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(); } @@ -1129,82 +1181,114 @@ bool LazyValueInfoCache::solveBlockValueBinaryOp(LVILatticeVal &BBLV, // NOTE: We're currently limited by the set of operations that ConstantRange // can evaluate symbolically. Enhancing that set will allows us to analyze // more definitions. - LVILatticeVal Result; - switch (BBI->getOpcode()) { - case Instruction::Add: - Result.markConstantRange(LHSRange.add(RHSRange)); - break; - case Instruction::Sub: - Result.markConstantRange(LHSRange.sub(RHSRange)); - break; - case Instruction::Mul: - Result.markConstantRange(LHSRange.multiply(RHSRange)); - break; - case Instruction::UDiv: - Result.markConstantRange(LHSRange.udiv(RHSRange)); - break; - case Instruction::Shl: - Result.markConstantRange(LHSRange.shl(RHSRange)); - break; - case Instruction::LShr: - Result.markConstantRange(LHSRange.lshr(RHSRange)); - break; - case Instruction::And: - Result.markConstantRange(LHSRange.binaryAnd(RHSRange)); - break; - case Instruction::Or: - Result.markConstantRange(LHSRange.binaryOr(RHSRange)); - break; - default: - // Should be dead if the code above is correct - llvm_unreachable("inconsistent with above"); - break; - } - - BBLV = Result; + auto BinOp = (Instruction::BinaryOps) BBI->getOpcode(); + BBLV = LVILatticeVal::getRange(LHSRange.binaryOp(BinOp, RHSRange)); return true; } -bool getValueFromFromCondition(Value *Val, ICmpInst *ICI, - LVILatticeVal &Result, bool isTrueDest) { - assert(ICI && "precondition"); - if (isa<Constant>(ICI->getOperand(1))) { - if (ICI->isEquality() && ICI->getOperand(0) == Val) { +static LVILatticeVal getValueFromICmpCondition(Value *Val, ICmpInst *ICI, + bool isTrueDest) { + Value *LHS = ICI->getOperand(0); + Value *RHS = ICI->getOperand(1); + CmpInst::Predicate Predicate = ICI->getPredicate(); + + if (isa<Constant>(RHS)) { + if (ICI->isEquality() && LHS == Val) { // We know that V has the RHS constant if this is a true SETEQ or // false SETNE. - if (isTrueDest == (ICI->getPredicate() == ICmpInst::ICMP_EQ)) - Result = LVILatticeVal::get(cast<Constant>(ICI->getOperand(1))); + if (isTrueDest == (Predicate == ICmpInst::ICMP_EQ)) + return LVILatticeVal::get(cast<Constant>(RHS)); else - Result = LVILatticeVal::getNot(cast<Constant>(ICI->getOperand(1))); - return true; + return LVILatticeVal::getNot(cast<Constant>(RHS)); } + } - // Recognize the range checking idiom that InstCombine produces. - // (X-C1) u< C2 --> [C1, C1+C2) - ConstantInt *NegOffset = nullptr; - if (ICI->getPredicate() == ICmpInst::ICMP_ULT) - match(ICI->getOperand(0), m_Add(m_Specific(Val), - m_ConstantInt(NegOffset))); - - ConstantInt *CI = dyn_cast<ConstantInt>(ICI->getOperand(1)); - if (CI && (ICI->getOperand(0) == Val || NegOffset)) { - // Calculate the range of values that are allowed by the comparison - ConstantRange CmpRange(CI->getValue()); - ConstantRange TrueValues = - ConstantRange::makeAllowedICmpRegion(ICI->getPredicate(), CmpRange); + if (!Val->getType()->isIntegerTy()) + return LVILatticeVal::getOverdefined(); + + // Use ConstantRange::makeAllowedICmpRegion in order to determine the possible + // range of Val guaranteed by the condition. Recognize comparisons in the from + // of: + // icmp <pred> Val, ... + // icmp <pred> (add Val, Offset), ... + // The latter is the range checking idiom that InstCombine produces. Subtract + // the offset from the allowed range for RHS in this case. + + // Val or (add Val, Offset) can be on either hand of the comparison + if (LHS != Val && !match(LHS, m_Add(m_Specific(Val), m_ConstantInt()))) { + std::swap(LHS, RHS); + Predicate = CmpInst::getSwappedPredicate(Predicate); + } - if (NegOffset) // Apply the offset from above. - TrueValues = TrueValues.subtract(NegOffset->getValue()); + ConstantInt *Offset = nullptr; + if (LHS != Val) + match(LHS, m_Add(m_Specific(Val), m_ConstantInt(Offset))); + + if (LHS == Val || Offset) { + // Calculate the range of values that are allowed by the comparison + ConstantRange RHSRange(RHS->getType()->getIntegerBitWidth(), + /*isFullSet=*/true); + if (ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) + RHSRange = ConstantRange(CI->getValue()); + else if (Instruction *I = dyn_cast<Instruction>(RHS)) + if (auto *Ranges = I->getMetadata(LLVMContext::MD_range)) + RHSRange = getConstantRangeFromMetadata(*Ranges); + + // If we're interested in the false dest, invert the condition + CmpInst::Predicate Pred = + isTrueDest ? Predicate : CmpInst::getInversePredicate(Predicate); + ConstantRange TrueValues = + ConstantRange::makeAllowedICmpRegion(Pred, RHSRange); - // If we're interested in the false dest, invert the condition. - if (!isTrueDest) TrueValues = TrueValues.inverse(); + if (Offset) // Apply the offset from above. + TrueValues = TrueValues.subtract(Offset->getValue()); - Result = LVILatticeVal::getRange(std::move(TrueValues)); - return true; - } + return LVILatticeVal::getRange(std::move(TrueValues)); } - return false; + return LVILatticeVal::getOverdefined(); +} + +static LVILatticeVal +getValueFromCondition(Value *Val, Value *Cond, bool isTrueDest, + DenseMap<Value*, LVILatticeVal> &Visited); + +static LVILatticeVal +getValueFromConditionImpl(Value *Val, Value *Cond, bool isTrueDest, + DenseMap<Value*, LVILatticeVal> &Visited) { + if (ICmpInst *ICI = dyn_cast<ICmpInst>(Cond)) + return getValueFromICmpCondition(Val, ICI, isTrueDest); + + // Handle conditions in the form of (cond1 && cond2), we know that on the + // true dest path both of the conditions hold. + if (!isTrueDest) + return LVILatticeVal::getOverdefined(); + + BinaryOperator *BO = dyn_cast<BinaryOperator>(Cond); + if (!BO || BO->getOpcode() != BinaryOperator::And) + return LVILatticeVal::getOverdefined(); + + auto RHS = getValueFromCondition(Val, BO->getOperand(0), isTrueDest, Visited); + auto LHS = getValueFromCondition(Val, BO->getOperand(1), isTrueDest, Visited); + return intersect(RHS, LHS); +} + +static LVILatticeVal +getValueFromCondition(Value *Val, Value *Cond, bool isTrueDest, + DenseMap<Value*, LVILatticeVal> &Visited) { + auto I = Visited.find(Cond); + if (I != Visited.end()) + return I->second; + + auto Result = getValueFromConditionImpl(Val, Cond, isTrueDest, Visited); + Visited[Cond] = Result; + return Result; +} + +LVILatticeVal getValueFromCondition(Value *Val, Value *Cond, bool isTrueDest) { + assert(Cond && "precondition"); + DenseMap<Value*, LVILatticeVal> Visited; + return getValueFromCondition(Val, Cond, isTrueDest, Visited); } /// \brief Compute the value of Val on the edge BBFrom -> BBTo. Returns false if @@ -1233,9 +1317,9 @@ static bool getEdgeValueLocal(Value *Val, BasicBlock *BBFrom, // If the condition of the branch is an equality comparison, we may be // able to infer the value. - if (ICmpInst *ICI = dyn_cast<ICmpInst>(BI->getCondition())) - if (getValueFromFromCondition(Val, ICI, Result, isTrueDest)) - return true; + Result = getValueFromCondition(Val, BI->getCondition(), isTrueDest); + if (!Result.isOverdefined()) + return true; } } @@ -1267,7 +1351,7 @@ static bool getEdgeValueLocal(Value *Val, BasicBlock *BBFrom, /// \brief Compute the value of Val on the edge BBFrom -> BBTo or the value at /// the basic block if the edge does not constrain Val. -bool LazyValueInfoCache::getEdgeValue(Value *Val, BasicBlock *BBFrom, +bool LazyValueInfoImpl::getEdgeValue(Value *Val, BasicBlock *BBFrom, BasicBlock *BBTo, LVILatticeVal &Result, Instruction *CxtI) { // If already a constant, there is nothing to compute. @@ -1280,7 +1364,7 @@ bool LazyValueInfoCache::getEdgeValue(Value *Val, BasicBlock *BBFrom, if (!getEdgeValueLocal(Val, BBFrom, BBTo, LocalResult)) // If we couldn't constrain the value on the edge, LocalResult doesn't // provide any information. - LocalResult.markOverdefined(); + LocalResult = LVILatticeVal::getOverdefined(); if (hasSingleValue(LocalResult)) { // Can't get any more precise here @@ -1298,39 +1382,40 @@ bool LazyValueInfoCache::getEdgeValue(Value *Val, BasicBlock *BBFrom, // 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 // (and that cached result might be used with queries using a different // context instruction), because when this function is called from the solve* // functions, the context instruction is not provided. When called from - // LazyValueInfoCache::getValueOnEdge, the context instruction is provided, + // LazyValueInfoImpl::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; } -LVILatticeVal LazyValueInfoCache::getValueInBlock(Value *V, BasicBlock *BB, +LVILatticeVal LazyValueInfoImpl::getValueInBlock(Value *V, BasicBlock *BB, Instruction *CxtI) { DEBUG(dbgs() << "LVI Getting block end value " << *V << " at '" << BB->getName() << "'\n"); assert(BlockValueStack.empty() && BlockValueSet.empty()); if (!hasBlockValue(V, BB)) { - pushBlockValue(std::make_pair(BB, V)); + pushBlockValue(std::make_pair(BB, V)); solve(); } LVILatticeVal Result = getBlockValue(V, BB); - intersectAssumeBlockValueConstantRange(V, Result, CxtI); + intersectAssumeOrGuardBlockValueConstantRange(V, Result, CxtI); DEBUG(dbgs() << " Result = " << Result << "\n"); return Result; } -LVILatticeVal LazyValueInfoCache::getValueAt(Value *V, Instruction *CxtI) { +LVILatticeVal LazyValueInfoImpl::getValueAt(Value *V, Instruction *CxtI) { DEBUG(dbgs() << "LVI Getting value " << *V << " at '" << CxtI->getName() << "'\n"); @@ -1340,13 +1425,13 @@ LVILatticeVal LazyValueInfoCache::getValueAt(Value *V, Instruction *CxtI) { 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; } -LVILatticeVal LazyValueInfoCache:: +LVILatticeVal LazyValueInfoImpl:: getValueOnEdge(Value *V, BasicBlock *FromBB, BasicBlock *ToBB, Instruction *CxtI) { DEBUG(dbgs() << "LVI Getting edge value " << *V << " from '" @@ -1364,75 +1449,24 @@ getValueOnEdge(Value *V, BasicBlock *FromBB, BasicBlock *ToBB, return Result; } -void LazyValueInfoCache::threadEdge(BasicBlock *PredBB, BasicBlock *OldSucc, - BasicBlock *NewSucc) { - // When an edge in the graph has been threaded, values that we could not - // determine a value for before (i.e. were marked overdefined) may be - // possible to solve now. We do NOT try to proactively update these values. - // Instead, we clear their entries from the cache, and allow lazy updating to - // recompute them when needed. - - // The updating process is fairly simple: we need to drop cached info - // for all values that were marked overdefined in OldSucc, and for those same - // values in any successor of OldSucc (except NewSucc) in which they were - // also marked overdefined. - std::vector<BasicBlock*> worklist; - worklist.push_back(OldSucc); - - auto I = OverDefinedCache.find(OldSucc); - if (I == OverDefinedCache.end()) - return; // Nothing to process here. - SmallVector<Value *, 4> ValsToClear(I->second.begin(), I->second.end()); - - // Use a worklist to perform a depth-first search of OldSucc's successors. - // NOTE: We do not need a visited list since any blocks we have already - // visited will have had their overdefined markers cleared already, and we - // thus won't loop to their successors. - while (!worklist.empty()) { - BasicBlock *ToUpdate = worklist.back(); - worklist.pop_back(); - - // Skip blocks only accessible through NewSucc. - if (ToUpdate == NewSucc) continue; - - bool changed = false; - for (Value *V : ValsToClear) { - // If a value was marked overdefined in OldSucc, and is here too... - auto OI = OverDefinedCache.find(ToUpdate); - if (OI == OverDefinedCache.end()) - continue; - SmallPtrSetImpl<Value *> &ValueSet = OI->second; - if (!ValueSet.count(V)) - continue; - - ValueSet.erase(V); - if (ValueSet.empty()) - OverDefinedCache.erase(OI); - - // If we removed anything, then we potentially need to update - // blocks successors too. - changed = true; - } - - if (!changed) continue; - - worklist.insert(worklist.end(), succ_begin(ToUpdate), succ_end(ToUpdate)); - } +void LazyValueInfoImpl::threadEdge(BasicBlock *PredBB, BasicBlock *OldSucc, + BasicBlock *NewSucc) { + TheCache.threadEdgeImpl(OldSucc, NewSucc); } //===----------------------------------------------------------------------===// // LazyValueInfo Impl //===----------------------------------------------------------------------===// -/// This lazily constructs the LazyValueInfoCache. -static LazyValueInfoCache &getCache(void *&PImpl, AssumptionCache *AC, - const DataLayout *DL, - DominatorTree *DT = nullptr) { +/// This lazily constructs the LazyValueInfoImpl. +static LazyValueInfoImpl &getImpl(void *&PImpl, AssumptionCache *AC, + const DataLayout *DL, + DominatorTree *DT = nullptr) { if (!PImpl) { assert(DL && "getCache() called with a null DataLayout"); - PImpl = new LazyValueInfoCache(AC, *DL, DT); + PImpl = new LazyValueInfoImpl(AC, *DL, DT); } - return *static_cast<LazyValueInfoCache*>(PImpl); + return *static_cast<LazyValueInfoImpl*>(PImpl); } bool LazyValueInfoWrapperPass::runOnFunction(Function &F) { @@ -1445,7 +1479,7 @@ bool LazyValueInfoWrapperPass::runOnFunction(Function &F) { Info.TLI = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(); if (Info.PImpl) - getCache(Info.PImpl, Info.AC, &DL, Info.DT).clear(); + getImpl(Info.PImpl, Info.AC, &DL, Info.DT).clear(); // Fully lazy. return false; @@ -1464,7 +1498,7 @@ LazyValueInfo::~LazyValueInfo() { releaseMemory(); } void LazyValueInfo::releaseMemory() { // If the cache was allocated, free it. if (PImpl) { - delete &getCache(PImpl, AC, nullptr); + delete &getImpl(PImpl, AC, nullptr); PImpl = nullptr; } } @@ -1479,7 +1513,6 @@ LazyValueInfo LazyValueAnalysis::run(Function &F, FunctionAnalysisManager &FAM) return LazyValueInfo(&AC, &TLI, DT); } - /// Returns true if we can statically tell that this value will never be a /// "useful" constant. In practice, this means we've got something like an /// alloca or a malloc call for which a comparison against a constant can @@ -1502,7 +1535,7 @@ Constant *LazyValueInfo::getConstant(Value *V, BasicBlock *BB, const DataLayout &DL = BB->getModule()->getDataLayout(); LVILatticeVal Result = - getCache(PImpl, AC, &DL, DT).getValueInBlock(V, BB, CxtI); + getImpl(PImpl, AC, &DL, DT).getValueInBlock(V, BB, CxtI); if (Result.isConstant()) return Result.getConstant(); @@ -1520,12 +1553,15 @@ ConstantRange LazyValueInfo::getConstantRange(Value *V, BasicBlock *BB, unsigned Width = V->getType()->getIntegerBitWidth(); const DataLayout &DL = BB->getModule()->getDataLayout(); LVILatticeVal Result = - getCache(PImpl, AC, &DL, DT).getValueInBlock(V, BB, CxtI); - assert(!Result.isConstant()); + getImpl(PImpl, AC, &DL, DT).getValueInBlock(V, BB, CxtI); if (Result.isUndefined()) return ConstantRange(Width, /*isFullSet=*/false); if (Result.isConstantRange()) return Result.getConstantRange(); + // We represent ConstantInt constants as constant ranges but other kinds + // of integer constants, i.e. ConstantExpr will be tagged as constants + assert(!(Result.isConstant() && isa<ConstantInt>(Result.getConstant())) && + "ConstantInt value must be represented as constantrange"); return ConstantRange(Width, /*isFullSet=*/true); } @@ -1536,7 +1572,7 @@ Constant *LazyValueInfo::getConstantOnEdge(Value *V, BasicBlock *FromBB, Instruction *CxtI) { const DataLayout &DL = FromBB->getModule()->getDataLayout(); LVILatticeVal Result = - getCache(PImpl, AC, &DL, DT).getValueOnEdge(V, FromBB, ToBB, CxtI); + getImpl(PImpl, AC, &DL, DT).getValueOnEdge(V, FromBB, ToBB, CxtI); if (Result.isConstant()) return Result.getConstant(); @@ -1583,8 +1619,8 @@ static LazyValueInfo::Tristate getPredicateResult(unsigned Pred, Constant *C, } // Handle more complex predicates. - ConstantRange TrueValues = - ICmpInst::makeConstantRange((ICmpInst::Predicate)Pred, CI->getValue()); + ConstantRange TrueValues = ConstantRange::makeExactICmpRegion( + (ICmpInst::Predicate)Pred, CI->getValue()); if (TrueValues.contains(CR)) return LazyValueInfo::True; if (TrueValues.inverse().contains(CR)) @@ -1624,7 +1660,7 @@ LazyValueInfo::getPredicateOnEdge(unsigned Pred, Value *V, Constant *C, Instruction *CxtI) { const DataLayout &DL = FromBB->getModule()->getDataLayout(); LVILatticeVal Result = - getCache(PImpl, AC, &DL, DT).getValueOnEdge(V, FromBB, ToBB, CxtI); + getImpl(PImpl, AC, &DL, DT).getValueOnEdge(V, FromBB, ToBB, CxtI); return getPredicateResult(Pred, C, Result, DL, TLI); } @@ -1644,7 +1680,7 @@ LazyValueInfo::getPredicateAt(unsigned Pred, Value *V, Constant *C, return LazyValueInfo::True; } const DataLayout &DL = CxtI->getModule()->getDataLayout(); - LVILatticeVal Result = getCache(PImpl, AC, &DL, DT).getValueAt(V, CxtI); + LVILatticeVal Result = getImpl(PImpl, AC, &DL, DT).getValueAt(V, CxtI); Tristate Ret = getPredicateResult(Pred, C, Result, DL, TLI); if (Ret != Unknown) return Ret; @@ -1703,7 +1739,7 @@ LazyValueInfo::getPredicateAt(unsigned Pred, Value *V, Constant *C, } if (Baseline != Unknown) return Baseline; - } + } // 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 @@ -1734,13 +1770,13 @@ void LazyValueInfo::threadEdge(BasicBlock *PredBB, BasicBlock *OldSucc, BasicBlock *NewSucc) { if (PImpl) { const DataLayout &DL = PredBB->getModule()->getDataLayout(); - getCache(PImpl, AC, &DL, DT).threadEdge(PredBB, OldSucc, NewSucc); + getImpl(PImpl, AC, &DL, DT).threadEdge(PredBB, OldSucc, NewSucc); } } void LazyValueInfo::eraseBlock(BasicBlock *BB) { if (PImpl) { const DataLayout &DL = BB->getModule()->getDataLayout(); - getCache(PImpl, AC, &DL, DT).eraseBlock(BB); + getImpl(PImpl, AC, &DL, DT).eraseBlock(BB); } } |