Index: include/llvm/Analysis/LazyValueInfo.h =================================================================== --- include/llvm/Analysis/LazyValueInfo.h +++ include/llvm/Analysis/LazyValueInfo.h @@ -98,6 +98,9 @@ /// Inform the analysis cache that we have erased a block. void eraseBlock(BasicBlock *BB); + /// Print the \LazyValueInfoCache. + void printCache(const DataLayout &DL, raw_ostream &OS); + // For old PM pass. Delete once LazyValueInfoWrapperPass is gone. void releaseMemory(); Index: include/llvm/InitializePasses.h =================================================================== --- include/llvm/InitializePasses.h +++ include/llvm/InitializePasses.h @@ -178,6 +178,7 @@ void initializeLazyMachineBlockFrequencyInfoPassPass(PassRegistry&); void initializeLazyBlockFrequencyInfoPassPass(PassRegistry&); void initializeLazyValueInfoWrapperPassPass(PassRegistry&); +void initializeLazyValueInfoPrinterPass(PassRegistry&); void initializeLegalizerPass(PassRegistry&); void initializeLibCallsShrinkWrapLegacyPassPass(PassRegistry&); void initializeLintPass(PassRegistry&); Index: lib/Analysis/Analysis.cpp =================================================================== --- lib/Analysis/Analysis.cpp +++ lib/Analysis/Analysis.cpp @@ -57,6 +57,7 @@ initializeLazyBranchProbabilityInfoPassPass(Registry); initializeLazyBlockFrequencyInfoPassPass(Registry); initializeLazyValueInfoWrapperPassPass(Registry); + initializeLazyValueInfoPrinterPass(Registry); initializeLintPass(Registry); initializeLoopInfoWrapperPassPass(Registry); initializeMemDepPrinterPass(Registry); Index: lib/Analysis/LazyValueInfo.cpp =================================================================== --- lib/Analysis/LazyValueInfo.cpp +++ lib/Analysis/LazyValueInfo.cpp @@ -439,6 +439,22 @@ return BBI->second; } + // Printing the ValueCache. + void printCache(raw_ostream &OS) { + for (auto &VC : ValueCache) + for (auto &BV : VC.second->BlockVals) + OS << " For '" << *VC.first << "' the CachedLatticeValue is: '" + << BV.second << "' at the beginning of BasicBlock: '" + << BV.first->getName() << "'\n"; + OS << "Overdefined Values per basic block\n"; + for (auto &OC : OverDefinedCache) { + OS << "\nFor '" << OC.first->getName() + << "' the overdefined values are: "; + for (Value *V : OC.second) + OS << " ' " << *V << " '; "; + } + } + /// clear - Empty the cache. void clear() { SeenBlocks.clear(); @@ -633,6 +649,11 @@ TheCache.clear(); } + /// Printing the LazyValueInfoCache. + void printCache(raw_ostream &OS) { + TheCache.printCache(OS); + } + /// This is part of the update interface to inform the cache /// that a block has been deleted. void eraseBlock(BasicBlock *BB) { @@ -1824,3 +1845,40 @@ getImpl(PImpl, AC, &DL, DT).eraseBlock(BB); } } + + +void LazyValueInfo::printCache(const DataLayout &DL, raw_ostream &OS) { + if (PImpl) { + getImpl(PImpl, AC, &DL, DT).printCache(OS); + } +} + +namespace { +// Printer class for LazyValueInfo results. +class LazyValueInfoPrinter : public FunctionPass { +public: + static char ID; // Pass identification, replacement for typeid + LazyValueInfoPrinter() : FunctionPass(ID) { + initializeLazyValueInfoPrinterPass(*PassRegistry::getPassRegistry()); + } + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesAll(); + AU.addRequired(); + } + + bool runOnFunction(Function &F) override { + errs() << "LVI for function '" << F.getName() << "':\n"; + auto &LVI = getAnalysis().getLVI(); + LVI.printCache(F.getParent()->getDataLayout(), errs()); + return false; + } +}; +} + +char LazyValueInfoPrinter::ID = 0; +INITIALIZE_PASS_BEGIN(LazyValueInfoPrinter, "print-lazy-value-info", + "Lazy Value Info Printer Pass", false, true) +INITIALIZE_PASS_DEPENDENCY(LazyValueInfoWrapperPass) +INITIALIZE_PASS_END(LazyValueInfoPrinter, "print-lazy-value-info", + "Lazy Value Info Printer Pass", false, true) Index: test/Analysis/LazyValueAnalysis/lvi-after-jumpthreading.ll =================================================================== --- /dev/null +++ test/Analysis/LazyValueAnalysis/lvi-after-jumpthreading.ll @@ -0,0 +1,62 @@ +; RUN: opt < %s -jump-threading -print-lazy-value-info -disable-output 2>&1 | FileCheck %s + +; Testing LVI cache after jump-threading + +; Jump-threading transforms the IR below to one where +; loop and backedge basic blocks are merged into one. +; basic block (named backedge) with the branch being: +; %cont = icmp slt i32 %iv.next, 400 +; br i1 %cont, label %backedge, label %exit +define i8 @test1(i32 %a, i32 %length) { +; CHECK-LABEL: LVI for function 'test1': +; CHECK-DAG: For ' %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]' the CachedLatticeValue is: 'constantrange<0, 400>' at the beginning of BasicBlock: 'backedge' +; CHECK-DAG: For ' %iv.next = add nsw i32 %iv, 1' the CachedLatticeValue is: 'constantrange<1, 401>' at the beginning of BasicBlock: 'backedge' +entry: + br label %loop + +loop: + %iv = phi i32 [0, %entry], [%iv.next, %backedge] + %cnd = icmp sge i32 %iv, 0 + br i1 %cnd, label %backedge, label %exit + +backedge: + %iv.next = add nsw i32 %iv, 1 + %cont = icmp slt i32 %iv.next, 400 + br i1 %cont, label %loop, label %exit + +exit: + 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-DAG: For ' %iv.next = add nsw i32 %iv, 1' the CachedLatticeValue is: 'constantrange<1, -2147483647>' at the beginning of BasicBlock: 'backedge' +; CHECK-DAG: For ' %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]' the CachedLatticeValue is: 'constantrange<0, -2147483647>' at the beginning of BasicBlock: 'loop' +; CHECK-DAG: For ' %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]' the CachedLatticeValue is: 'constantrange<0, -2147483648>' at the beginning of BasicBlock: 'backedge' +; CHECK-LABEL: Overdefined Values per basic block +; CHECK-DAG: For 'loop' the overdefined values are: ' %iv2 = phi i32 [ %n, %entry ], [ %iv2.next, %backedge ] '; +; CHECK-DAG: For 'entry' the overdefined values are: ' i32 %n '; +entry: + br label %loop + +loop: + %iv = phi i32 [0, %entry], [%iv.next, %backedge] + %iv2 = phi i32 [%n, %entry], [%iv2.next, %backedge] + %cnd1 = icmp sge i32 %iv, 0 + %cnd2 = icmp sgt i32 %iv2, 0 + %cnd = and i1 %cnd1, %cnd2 + br i1 %cnd, label %backedge, label %exit + +backedge: + %iv.next = add nsw i32 %iv, 1 + %iv2.next = sub nsw i32 %iv2, 1 + %cont1 = icmp slt i32 %iv.next, 400 + %cont2 = icmp sgt i32 %iv2.next, 0 + %cont = and i1 %cont1, %cont2 + br i1 %cont, label %loop, label %exit + +exit: + ret i8 0 +}