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