Index: llvm/trunk/include/llvm/Analysis/LazyValueInfo.h =================================================================== --- llvm/trunk/include/llvm/Analysis/LazyValueInfo.h +++ llvm/trunk/include/llvm/Analysis/LazyValueInfo.h @@ -100,8 +100,11 @@ /// Inform the analysis cache that we have erased a block. void eraseBlock(BasicBlock *BB); - /// Print the \LazyValueInfoCache. - void printCache(Function &F, raw_ostream &OS); + /// Print the \LazyValueInfo Analysis. + /// We pass in the DTree that is required for identifying which basic blocks + /// we can solve/print for, in the LVIPrinter. The DT is optional + /// in LVI, so we need to pass it here as an argument. + void printLVI(Function &F, DominatorTree &DTree, raw_ostream &OS); // For old PM pass. Delete once LazyValueInfoWrapperPass is gone. void releaseMemory(); Index: llvm/trunk/lib/Analysis/LazyValueInfo.cpp =================================================================== --- llvm/trunk/lib/Analysis/LazyValueInfo.cpp +++ llvm/trunk/lib/Analysis/LazyValueInfo.cpp @@ -364,7 +364,6 @@ /// This is the cache kept by LazyValueInfo which /// maintains information about queries across the clients' queries. class LazyValueInfoCache { - friend class LazyValueInfoAnnotatedWriter; /// This is all of the cached block information for exactly one Value*. /// The entries are sorted by the BasicBlock* of the /// entries, allowing us to do a lookup with a binary search. @@ -384,7 +383,6 @@ /// don't spend time removing unused blocks from our caches. DenseSet > SeenBlocks; - protected: /// This is all of the cached information for all values, /// mapped from Value* to key information. DenseMap> ValueCache; @@ -443,7 +441,6 @@ return BBI->second; } - void printCache(Function &F, raw_ostream &OS); /// clear - Empty the cache. void clear() { SeenBlocks.clear(); @@ -467,61 +464,6 @@ }; } - -namespace { - - /// An assembly annotator class to print LazyValueCache information in - /// comments. - class LazyValueInfoAnnotatedWriter : public AssemblyAnnotationWriter { - const LazyValueInfoCache* LVICache; - - public: - LazyValueInfoAnnotatedWriter(const LazyValueInfoCache *L) : LVICache(L) {} - - virtual void emitBasicBlockStartAnnot(const BasicBlock *BB, - formatted_raw_ostream &OS) { - auto ODI = LVICache->OverDefinedCache.find(const_cast(BB)); - if (ODI == LVICache->OverDefinedCache.end()) - return; - OS << "; OverDefined values for block are: \n"; - for (auto *V : ODI->second) - OS << ";" << *V << "\n"; - - // Find if there are latticevalues defined for arguments of the function. - auto *F = const_cast(BB->getParent()); - for (auto &Arg : F->args()) { - auto VI = LVICache->ValueCache.find_as(&Arg); - if (VI == LVICache->ValueCache.end()) - continue; - auto BBI = VI->second->BlockVals.find(const_cast(BB)); - if (BBI != VI->second->BlockVals.end()) - OS << "; CachedLatticeValue for: '" << *VI->first << "' is: '" - << BBI->second << "'\n"; - } - } - - virtual void emitInstructionAnnot(const Instruction *I, - formatted_raw_ostream &OS) { - - auto VI = LVICache->ValueCache.find_as(const_cast(I)); - if (VI == LVICache->ValueCache.end()) - return; - OS << "; CachedLatticeValues for: '" << *VI->first << "'\n"; - for (auto &BV : VI->second->BlockVals) { - OS << "; at beginning of BasicBlock: '"; - BV.first->printAsOperand(OS, false); - OS << "' LatticeVal: '" << BV.second << "' \n"; - } - } -}; -} - -void LazyValueInfoCache::printCache(Function &F, raw_ostream &OS) { - LazyValueInfoAnnotatedWriter Writer(this); - F.print(OS, &Writer); - -} - void LazyValueInfoCache::eraseValue(Value *V) { for (auto I = OverDefinedCache.begin(), E = OverDefinedCache.end(); I != E;) { // Copy and increment the iterator immediately so we can erase behind @@ -615,6 +557,30 @@ } } + +namespace { +/// An assembly annotator class to print LazyValueCache information in +/// comments. +class LazyValueInfoImpl; +class LazyValueInfoAnnotatedWriter : public AssemblyAnnotationWriter { + LazyValueInfoImpl *LVIImpl; + // While analyzing which blocks we can solve values for, we need the dominator + // information. Since this is an optional parameter in LVI, we require this + // DomTreeAnalysis pass in the printer pass, and pass the dominator + // tree to the LazyValueInfoAnnotatedWriter. + DominatorTree &DT; + +public: + LazyValueInfoAnnotatedWriter(LazyValueInfoImpl *L, DominatorTree &DTree) + : LVIImpl(L), DT(DTree) {} + + virtual void emitBasicBlockStartAnnot(const BasicBlock *BB, + formatted_raw_ostream &OS); + + virtual void emitInstructionAnnot(const Instruction *I, + formatted_raw_ostream &OS); +}; +} namespace { // The actual implementation of the lazy analysis and update. Note that the // inheritance from LazyValueInfoCache is intended to be temporary while @@ -693,9 +659,10 @@ TheCache.clear(); } - /// Printing the LazyValueInfoCache. - void printCache(Function &F, raw_ostream &OS) { - TheCache.printCache(F, OS); + /// Printing the LazyValueInfo Analysis. + void printLVI(Function &F, DominatorTree &DTree, raw_ostream &OS) { + LazyValueInfoAnnotatedWriter Writer(this, DTree); + F.print(OS, &Writer); } /// This is part of the update interface to inform the cache @@ -714,6 +681,7 @@ }; } // end anonymous namespace + void LazyValueInfoImpl::solve() { SmallVector, 8> StartingStack( BlockValueStack.begin(), BlockValueStack.end()); @@ -1890,12 +1858,65 @@ } -void LazyValueInfo::printCache(Function &F, raw_ostream &OS) { +void LazyValueInfo::printLVI(Function &F, DominatorTree &DTree, raw_ostream &OS) { if (PImpl) { - getImpl(PImpl, AC, DL, DT).printCache(F, OS); + getImpl(PImpl, AC, DL, DT).printLVI(F, DTree, OS); + } +} + +// Print the LVI for the function arguments at the start of each basic block. +void LazyValueInfoAnnotatedWriter::emitBasicBlockStartAnnot( + const BasicBlock *BB, formatted_raw_ostream &OS) { + // Find if there are latticevalues defined for arguments of the function. + auto *F = BB->getParent(); + for (auto &Arg : F->args()) { + LVILatticeVal Result = LVIImpl->getValueInBlock( + const_cast(&Arg), const_cast(BB)); + if (Result.isUndefined()) + continue; + OS << "; LatticeVal for: '" << Arg << "' is: " << Result << "\n"; } } +// This function prints the LVI analysis for the instruction I at the beginning +// of various basic blocks. It relies on calculated values that are stored in +// the LazyValueInfoCache, and in the absence of cached values, recalculte the +// LazyValueInfo for `I`, and print that info. +void LazyValueInfoAnnotatedWriter::emitInstructionAnnot( + const Instruction *I, formatted_raw_ostream &OS) { + + auto *ParentBB = I->getParent(); + SmallPtrSet BlocksContainingLVI; + // We can generate (solve) LVI values only for blocks that are dominated by + // the I's parent. However, to avoid generating LVI for all dominating blocks, + // that contain redundant/uninteresting information, we print LVI for + // blocks that may use this LVI information (such as immediate successor + // blocks, and blocks that contain uses of `I`). + auto printResult = [&](const BasicBlock *BB) { + if (!BlocksContainingLVI.insert(BB).second) + return; + LVILatticeVal Result = LVIImpl->getValueInBlock( + const_cast(I), const_cast(BB)); + OS << "; LatticeVal for: '" << *I << "' in BB: '"; + BB->printAsOperand(OS, false); + OS << "' is: " << Result << "\n"; + }; + + printResult(ParentBB); + // Print the LVI analysis results for the the immediate successor blocks, that + // are dominated by `ParentBB`. + for (auto *BBSucc : successors(ParentBB)) + if (DT.dominates(ParentBB, BBSucc)) + printResult(BBSucc); + + // Print LVI in blocks where `I` is used. + for (auto *U : I->users()) + if (auto *UseI = dyn_cast(U)) + if (!isa(UseI) || DT.dominates(ParentBB, UseI->getParent())) + printResult(UseI->getParent()); + +} + namespace { // Printer class for LazyValueInfo results. class LazyValueInfoPrinter : public FunctionPass { @@ -1908,12 +1929,16 @@ void getAnalysisUsage(AnalysisUsage &AU) const override { AU.setPreservesAll(); AU.addRequired(); + AU.addRequired(); } + // Get the mandatory dominator tree analysis and pass this in to the + // LVIPrinter. We cannot rely on the LVI's DT, since it's optional. bool runOnFunction(Function &F) override { dbgs() << "LVI for function '" << F.getName() << "':\n"; auto &LVI = getAnalysis().getLVI(); - LVI.printCache(F, dbgs()); + auto &DTree = getAnalysis().getDomTree(); + LVI.printLVI(F, DTree, dbgs()); return false; } }; Index: llvm/trunk/test/Analysis/LazyValueAnalysis/lvi-after-jumpthreading.ll =================================================================== --- llvm/trunk/test/Analysis/LazyValueAnalysis/lvi-after-jumpthreading.ll +++ llvm/trunk/test/Analysis/LazyValueAnalysis/lvi-after-jumpthreading.ll @@ -10,17 +10,23 @@ define i8 @test1(i32 %a, i32 %length) { ; CHECK-LABEL: LVI for function 'test1': entry: +; CHECK-LABEL: entry: +; CHECK-NEXT: ; LatticeVal for: 'i32 %a' is: overdefined +; CHECK-NEXT: ; LatticeVal for: 'i32 %length' is: overdefined br label %loop + ; CHECK-LABEL: backedge: -; CHECK-NEXT: ; CachedLatticeValues for: ' %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]' -; CHECK-DAG: ; at beginning of BasicBlock: '%backedge' LatticeVal: 'constantrange<0, 400>' -; CHECK-NEXT: %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ] -; CHECK-NEXT: ; CachedLatticeValues for: ' %iv.next = add nsw i32 %iv, 1' -; CHECK-NEXT: ; at beginning of BasicBlock: '%backedge' LatticeVal: 'constantrange<1, 401>' -; CHECK-NEXT: %iv.next = add nsw i32 %iv, 1 +; CHECK-NEXT: ; LatticeVal for: 'i32 %a' is: overdefined +; CHECK-NEXT: ; LatticeVal for: 'i32 %length' is: overdefined +; CHECK-NEXT: ; LatticeVal for: ' %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]' in BB: '%backedge' is: constantrange<0, 400> +; CHECK-NEXT: ; LatticeVal for: ' %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]' in BB: '%exit' is: constantrange<399, 400> +; CHECK-NEXT: %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ] +; CHECK-NEXT: ; LatticeVal for: ' %iv.next = add nsw i32 %iv, 1' in BB: '%backedge' is: constantrange<1, 401> +; CHECK-NEXT: ; LatticeVal for: ' %iv.next = add nsw i32 %iv, 1' in BB: '%exit' is: constantrange<400, 401> +; CHECK-NEXT: %iv.next = add nsw i32 %iv, 1 +; CHECK-NEXT: ; LatticeVal for: ' %cont = icmp slt i32 %iv.next, 400' in BB: '%backedge' is: overdefined +; CHECK-NEXT: ; LatticeVal for: ' %cont = icmp slt i32 %iv.next, 400' in BB: '%exit' is: constantrange<0, -1> ; CHECK-NEXT: %cont = icmp slt i32 %iv.next, 400 -; CHECK-NEXT: br i1 %cont, label %backedge, label %exit - ; CHECK-NOT: loop loop: %iv = phi i32 [0, %entry], [%iv.next, %backedge] @@ -36,46 +42,58 @@ ret i8 0 } - ; Here JT does not transform the code, but LVICache is populated during the processing of blocks. define i8 @test2(i32 %n) { ; CHECK-LABEL: LVI for function 'test2': ; CHECK-LABEL: entry: -; CHECK-LABEL: ; OverDefined values for block are: -; CHECK-NEXT: ;i32 %n +; CHECK-NEXT: ; LatticeVal for: 'i32 %n' is: overdefined ; CHECK-NEXT: br label %loop entry: br label %loop ; CHECK-LABEL: loop: -; CHECK-LABEL: ; OverDefined values for block are: -; CHECK-NEXT: ; %iv2 = phi i32 [ %n, %entry ], [ %iv2.next, %backedge ] -; CHECK-NEXT: ; CachedLatticeValues for: ' %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]' -; CHECK-DAG: ; at beginning of BasicBlock: '%loop' LatticeVal: 'constantrange<0, -2147483647>' -; CHECK-DAG: ; at beginning of BasicBlock: '%backedge' LatticeVal: 'constantrange<0, -2147483648>' -; CHECK-NEXT: %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ] -; CHECK: %cnd = and i1 %cnd1, %cnd2 -; CHECK: br i1 %cnd, label %backedge, label %exit +; CHECK-NEXT: ; LatticeVal for: 'i32 %n' is: overdefined +; CHECK-NEXT: ; LatticeVal for: ' %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]' in BB: '%loop' is: constantrange<0, -2147483647> +; CHECK-DAG: ; LatticeVal for: ' %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]' in BB: '%backedge' is: constantrange<0, -2147483648> +; CHECK-DAG: ; LatticeVal for: ' %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]' in BB: '%exit' is: constantrange<0, -2147483647> +; CHECK-NEXT: %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ] loop: %iv = phi i32 [0, %entry], [%iv.next, %backedge] +; CHECK-NEXT: ; LatticeVal for: ' %iv2 = phi i32 [ %n, %entry ], [ %iv2.next, %backedge ]' in BB: '%loop' is: overdefined +; CHECK-DAG: ; LatticeVal for: ' %iv2 = phi i32 [ %n, %entry ], [ %iv2.next, %backedge ]' in BB: '%backedge' is: constantrange<1, -2147483648> +; CHECK-DAG: ; LatticeVal for: ' %iv2 = phi i32 [ %n, %entry ], [ %iv2.next, %backedge ]' in BB: '%exit' is: overdefined +; CHECK-NEXT: %iv2 = phi i32 [ %n, %entry ], [ %iv2.next, %backedge ] %iv2 = phi i32 [%n, %entry], [%iv2.next, %backedge] + +; CHECK-NEXT: ; LatticeVal for: ' %cnd1 = icmp sge i32 %iv, 0' in BB: '%loop' is: overdefined +; CHECK-DAG: ; LatticeVal for: ' %cnd1 = icmp sge i32 %iv, 0' in BB: '%backedge' is: overdefined +; CHECK-DAG: ; LatticeVal for: ' %cnd1 = icmp sge i32 %iv, 0' in BB: '%exit' is: overdefined +; CHECK-NEXT: %cnd1 = icmp sge i32 %iv, 0 %cnd1 = icmp sge i32 %iv, 0 %cnd2 = icmp sgt i32 %iv2, 0 +; CHECK: %cnd2 = icmp sgt i32 %iv2, 0 +; CHECK: ; LatticeVal for: ' %cnd = and i1 %cnd1, %cnd2' in BB: '%loop' is: overdefined +; CHECK-DAG: ; LatticeVal for: ' %cnd = and i1 %cnd1, %cnd2' in BB: '%backedge' is: constantrange<-1, 0> +; CHECK-DAG: ; LatticeVal for: ' %cnd = and i1 %cnd1, %cnd2' in BB: '%exit' is: overdefined +; CHECK-NEXT: %cnd = and i1 %cnd1, %cnd2 %cnd = and i1 %cnd1, %cnd2 br i1 %cnd, label %backedge, label %exit ; CHECK-LABEL: backedge: -; CHECK-NEXT: ; CachedLatticeValues for: ' %iv.next = add nsw i32 %iv, 1' -; CHECK-NEXT: ; at beginning of BasicBlock: '%backedge' LatticeVal: 'constantrange<1, -2147483647>' -; CHECK-NEXT: %iv.next = add nsw i32 %iv, 1 -; CHECK-NEXT: %iv2.next = sub nsw i32 %iv2, 1 -; CHECK: %cont = and i1 %cont1, %cont2 -; CHECK: br i1 %cont, label %loop, label %exit +; CHECK-NEXT: ; LatticeVal for: 'i32 %n' is: overdefined +; CHECK-NEXT: ; LatticeVal for: ' %iv.next = add nsw i32 %iv, 1' in BB: '%backedge' is: constantrange<1, -2147483647> +; CHECK-NEXT: %iv.next = add nsw i32 %iv, 1 backedge: %iv.next = add nsw i32 %iv, 1 %iv2.next = sub nsw i32 %iv2, 1 +; CHECK: ; LatticeVal for: ' %cont1 = icmp slt i32 %iv.next, 400' in BB: '%backedge' is: overdefined +; CHECK-NEXT: %cont1 = icmp slt i32 %iv.next, 400 %cont1 = icmp slt i32 %iv.next, 400 +; CHECK-NEXT: ; LatticeVal for: ' %cont2 = icmp sgt i32 %iv2.next, 0' in BB: '%backedge' is: overdefined +; CHECK-NEXT: %cont2 = icmp sgt i32 %iv2.next, 0 %cont2 = icmp sgt i32 %iv2.next, 0 +; CHECK-NEXT: ; LatticeVal for: ' %cont = and i1 %cont1, %cont2' in BB: '%backedge' is: overdefined +; CHECK-NEXT: %cont = and i1 %cont1, %cont2 %cont = and i1 %cont1, %cont2 br i1 %cont, label %loop, label %exit