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