Index: lib/Analysis/LazyValueInfo.cpp =================================================================== --- lib/Analysis/LazyValueInfo.cpp +++ lib/Analysis/LazyValueInfo.cpp @@ -345,6 +345,8 @@ /// Push BV onto BlockValueStack unless it's already in there. /// Returns true on success. bool pushBlockValue(const std::pair &BV) { + assert(!isa(BV.second) && + "Constants should not need to be pushed!"); if (!BlockValueSet.insert(BV).second) return false; // It's already in the stack. @@ -391,8 +393,11 @@ } public: - /// This is the query interface to determine the lattice - /// value for the specified Value* at the end of the specified block. + /// This is the query interface to determine the lattice value for the + /// specified Value* at the end of the specified block. Note that this + /// routine caches results internally based on what's known to be true at + /// the end of BB, but may return more precise results if the context + /// instruction is not the terminator of BB. LVILatticeVal getValueInBlock(Value *V, BasicBlock *BB, Instruction *CxtI = nullptr); @@ -565,12 +570,16 @@ // We can only analyze the definitions of certain classes of instructions // (integral binops and casts at the moment), so bail if this isn't one. - LVILatticeVal Result; if ((!isa(BBI) && !isa(BBI)) || - !BBI->getType()->isIntegerTy()) { - DEBUG(dbgs() << " compute BB '" << BB->getName() - << "' - overdefined because inst def found.\n"); - Res.markOverdefined(); + !BBI->getType()->isIntegerTy()) { + // If we haven't found any facts about this value, we need to return + // something conservatively correct. If we have found facts, we want to + // use them. + if (Res.isUndefined()) { + DEBUG(dbgs() << " compute BB '" << BB->getName() + << "' - overdefined because inst def found.\n"); + Res.markOverdefined(); + } insertResult(Val, BB, Res); return true; } @@ -773,6 +782,7 @@ } } + bool LazyValueInfoCache::solveBlockValueConstantRange(LVILatticeVal &BBLV, Instruction *BBI, BasicBlock *BB) { @@ -1024,9 +1034,13 @@ << BB->getName() << "'\n"); assert(BlockValueStack.empty() && BlockValueSet.empty()); - pushBlockValue(std::make_pair(BB, V)); - solve(); + // Unless a block value for V is known in BB, solve for it. Note that + // Constants will never take this path since they are always known. + if (!hasBlockValue(V, BB)) { + pushBlockValue(std::make_pair(BB, V)); + solve(); + } LVILatticeVal Result = getBlockValue(V, BB); mergeAssumeBlockValueConstantRange(V, Result, CxtI); @@ -1036,13 +1050,25 @@ LVILatticeVal LazyValueInfoCache::getValueAt(Value *V, Instruction *CxtI) { DEBUG(dbgs() << "LVI Getting value " << *V << " at '" - << CxtI->getName() << "'\n"); + << *CxtI << "'\n"); - LVILatticeVal Result; - if (auto *I = dyn_cast(V)) - Result = getFromRangeMetadata(I); - mergeAssumeBlockValueConstantRange(V, Result, CxtI); + auto *BB = CxtI->getParent(); + // Use the generic infrastructure to solve for the value in the required + // basic block if we can. + LVILatticeVal Result; + if (BB->getTerminator() == CxtI) + Result = getValueInBlock(V, BB, CxtI); + else { + // If we couldn't use the generic infrastructure (since context is not the + // terminator and facts true at the end of the basic block might not + // apply), handle some easy cases. + // TODO: We could extent this to use LVI to compute the result on the start + // of a basic block, and then intersect. + if (auto *I = dyn_cast(V)) + Result = getFromRangeMetadata(I); + mergeAssumeBlockValueConstantRange(V, Result, CxtI); + } DEBUG(dbgs() << " Result = " << Result << "\n"); return Result; } @@ -1177,7 +1203,7 @@ Instruction *CxtI) { const DataLayout &DL = BB->getModule()->getDataLayout(); LVILatticeVal Result = - getCache(PImpl, AC, &DL, DT).getValueInBlock(V, BB, CxtI); + getCache(PImpl, AC, &DL, DT).getValueInBlock(V, BB, CxtI); if (Result.isConstant()) return Result.getConstant(); Index: test/Transforms/CorrelatedValuePropagation/basic.ll =================================================================== --- test/Transforms/CorrelatedValuePropagation/basic.ll +++ test/Transforms/CorrelatedValuePropagation/basic.ll @@ -199,3 +199,34 @@ next: ret void } + +; The next two check for a subtle potential miscompile. In these examples, +; we can use assume facts to prove things about terminators, but can NOT use +; those those same facts for uses proceding the assume since control flow may +; never reach the assume. This is essentially checking that getValueInBlock +; from LVI correctly separates block facts and context specific facts. + +declare void @may_throw(i1) +declare void @llvm.assume(i1) + +define i1 @maythrow(i32 %p) { +; CHECK-LABEL: @maythrow +; CHECK: @may_throw(i1 %res) + %res = icmp eq i32 %p, 0 + call void @may_throw(i1 %res) + call void @llvm.assume(i1 %res) + ret i1 %res +} + +define i1 @maythrow2(i32 %p) { +; CHECK-LABEL: @maythrow2 +; CHECK: @may_throw(i1 %res) + %res = icmp eq i32 %p, 0 + call void @may_throw(i1 %res) + call void @llvm.assume(i1 %res) + br i1 %res, label %taken, label %untaken +taken: + ret i1 %res +untaken: + ret i1 %res +}