Home | History | Annotate | Download | only in Analysis
      1 //===- MemDepPrinter.cpp - Printer for MemoryDependenceAnalysis -----------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 //
     11 //===----------------------------------------------------------------------===//
     12 
     13 #include "llvm/Analysis/Passes.h"
     14 #include "llvm/ADT/SetVector.h"
     15 #include "llvm/Analysis/MemoryDependenceAnalysis.h"
     16 #include "llvm/IR/CallSite.h"
     17 #include "llvm/IR/InstIterator.h"
     18 #include "llvm/IR/LLVMContext.h"
     19 #include "llvm/Support/ErrorHandling.h"
     20 #include "llvm/Support/raw_ostream.h"
     21 using namespace llvm;
     22 
     23 namespace {
     24   struct MemDepPrinter : public FunctionPass {
     25     const Function *F;
     26 
     27     enum DepType {
     28       Clobber = 0,
     29       Def,
     30       NonFuncLocal,
     31       Unknown
     32     };
     33 
     34     static const char *const DepTypeStr[];
     35 
     36     typedef PointerIntPair<const Instruction *, 2, DepType> InstTypePair;
     37     typedef std::pair<InstTypePair, const BasicBlock *> Dep;
     38     typedef SmallSetVector<Dep, 4> DepSet;
     39     typedef DenseMap<const Instruction *, DepSet> DepSetMap;
     40     DepSetMap Deps;
     41 
     42     static char ID; // Pass identifcation, replacement for typeid
     43     MemDepPrinter() : FunctionPass(ID) {
     44       initializeMemDepPrinterPass(*PassRegistry::getPassRegistry());
     45     }
     46 
     47     bool runOnFunction(Function &F) override;
     48 
     49     void print(raw_ostream &OS, const Module * = nullptr) const override;
     50 
     51     void getAnalysisUsage(AnalysisUsage &AU) const override {
     52       AU.addRequiredTransitive<AliasAnalysis>();
     53       AU.addRequiredTransitive<MemoryDependenceAnalysis>();
     54       AU.setPreservesAll();
     55     }
     56 
     57     void releaseMemory() override {
     58       Deps.clear();
     59       F = nullptr;
     60     }
     61 
     62   private:
     63     static InstTypePair getInstTypePair(MemDepResult dep) {
     64       if (dep.isClobber())
     65         return InstTypePair(dep.getInst(), Clobber);
     66       if (dep.isDef())
     67         return InstTypePair(dep.getInst(), Def);
     68       if (dep.isNonFuncLocal())
     69         return InstTypePair(dep.getInst(), NonFuncLocal);
     70       assert(dep.isUnknown() && "unexpected dependence type");
     71       return InstTypePair(dep.getInst(), Unknown);
     72     }
     73     static InstTypePair getInstTypePair(const Instruction* inst, DepType type) {
     74       return InstTypePair(inst, type);
     75     }
     76   };
     77 }
     78 
     79 char MemDepPrinter::ID = 0;
     80 INITIALIZE_PASS_BEGIN(MemDepPrinter, "print-memdeps",
     81                       "Print MemDeps of function", false, true)
     82 INITIALIZE_PASS_DEPENDENCY(MemoryDependenceAnalysis)
     83 INITIALIZE_PASS_END(MemDepPrinter, "print-memdeps",
     84                       "Print MemDeps of function", false, true)
     85 
     86 FunctionPass *llvm::createMemDepPrinter() {
     87   return new MemDepPrinter();
     88 }
     89 
     90 const char *const MemDepPrinter::DepTypeStr[]
     91   = {"Clobber", "Def", "NonFuncLocal", "Unknown"};
     92 
     93 bool MemDepPrinter::runOnFunction(Function &F) {
     94   this->F = &F;
     95   MemoryDependenceAnalysis &MDA = getAnalysis<MemoryDependenceAnalysis>();
     96 
     97   // All this code uses non-const interfaces because MemDep is not
     98   // const-friendly, though nothing is actually modified.
     99   for (auto &I : inst_range(F)) {
    100     Instruction *Inst = &I;
    101 
    102     if (!Inst->mayReadFromMemory() && !Inst->mayWriteToMemory())
    103       continue;
    104 
    105     MemDepResult Res = MDA.getDependency(Inst);
    106     if (!Res.isNonLocal()) {
    107       Deps[Inst].insert(std::make_pair(getInstTypePair(Res),
    108                                        static_cast<BasicBlock *>(nullptr)));
    109     } else if (auto CS = CallSite(Inst)) {
    110       const MemoryDependenceAnalysis::NonLocalDepInfo &NLDI =
    111         MDA.getNonLocalCallDependency(CS);
    112 
    113       DepSet &InstDeps = Deps[Inst];
    114       for (MemoryDependenceAnalysis::NonLocalDepInfo::const_iterator
    115            I = NLDI.begin(), E = NLDI.end(); I != E; ++I) {
    116         const MemDepResult &Res = I->getResult();
    117         InstDeps.insert(std::make_pair(getInstTypePair(Res), I->getBB()));
    118       }
    119     } else {
    120       SmallVector<NonLocalDepResult, 4> NLDI;
    121       assert( (isa<LoadInst>(Inst) || isa<StoreInst>(Inst) ||
    122                isa<VAArgInst>(Inst)) && "Unknown memory instruction!");
    123       MDA.getNonLocalPointerDependency(Inst, NLDI);
    124 
    125       DepSet &InstDeps = Deps[Inst];
    126       for (SmallVectorImpl<NonLocalDepResult>::const_iterator
    127            I = NLDI.begin(), E = NLDI.end(); I != E; ++I) {
    128         const MemDepResult &Res = I->getResult();
    129         InstDeps.insert(std::make_pair(getInstTypePair(Res), I->getBB()));
    130       }
    131     }
    132   }
    133 
    134   return false;
    135 }
    136 
    137 void MemDepPrinter::print(raw_ostream &OS, const Module *M) const {
    138   for (const auto &I : inst_range(*F)) {
    139     const Instruction *Inst = &I;
    140 
    141     DepSetMap::const_iterator DI = Deps.find(Inst);
    142     if (DI == Deps.end())
    143       continue;
    144 
    145     const DepSet &InstDeps = DI->second;
    146 
    147     for (const auto &I : InstDeps) {
    148       const Instruction *DepInst = I.first.getPointer();
    149       DepType type = I.first.getInt();
    150       const BasicBlock *DepBB = I.second;
    151 
    152       OS << "    ";
    153       OS << DepTypeStr[type];
    154       if (DepBB) {
    155         OS << " in block ";
    156         DepBB->printAsOperand(OS, /*PrintType=*/false, M);
    157       }
    158       if (DepInst) {
    159         OS << " from: ";
    160         DepInst->print(OS);
    161       }
    162       OS << "\n";
    163     }
    164 
    165     Inst->print(OS);
    166     OS << "\n\n";
    167   }
    168 }
    169