]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/llvm/lib/Analysis/MemDepPrinter.cpp
Merge ^/head r357408 through r357661.
[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/InitializePasses.h"
18 #include "llvm/Support/ErrorHandling.h"
19 #include "llvm/Support/raw_ostream.h"
20 using namespace llvm;
21
22 namespace {
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
78 char MemDepPrinter::ID = 0;
79 INITIALIZE_PASS_BEGIN(MemDepPrinter, "print-memdeps",
80                       "Print MemDeps of function", false, true)
81 INITIALIZE_PASS_DEPENDENCY(MemoryDependenceWrapperPass)
82 INITIALIZE_PASS_END(MemDepPrinter, "print-memdeps",
83                       "Print MemDeps of function", false, true)
84
85 FunctionPass *llvm::createMemDepPrinter() {
86   return new MemDepPrinter();
87 }
88
89 const char *const MemDepPrinter::DepTypeStr[]
90   = {"Clobber", "Def", "NonFuncLocal", "Unknown"};
91
92 bool 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
134 void 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 }