1 //===- MemDepPrinter.cpp - Printer for MemoryDependenceAnalysis -----------===//
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
7 //===----------------------------------------------------------------------===//
10 //===----------------------------------------------------------------------===//
12 #include "llvm/ADT/SetVector.h"
13 #include "llvm/Analysis/AliasAnalysis.h"
14 #include "llvm/Analysis/MemoryDependenceAnalysis.h"
15 #include "llvm/Analysis/Passes.h"
16 #include "llvm/IR/InstIterator.h"
17 #include "llvm/IR/Instructions.h"
18 #include "llvm/IR/LLVMContext.h"
19 #include "llvm/InitializePasses.h"
20 #include "llvm/Support/ErrorHandling.h"
21 #include "llvm/Support/raw_ostream.h"
26 struct MemDepPrinter
: public FunctionPass
{
36 static const char *const DepTypeStr
[];
38 typedef PointerIntPair
<const Instruction
*, 2, DepType
> InstTypePair
;
39 typedef std::pair
<InstTypePair
, const BasicBlock
*> Dep
;
40 typedef SmallSetVector
<Dep
, 4> DepSet
;
41 typedef DenseMap
<const Instruction
*, DepSet
> DepSetMap
;
44 static char ID
; // Pass identifcation, replacement for typeid
45 MemDepPrinter() : FunctionPass(ID
) {
46 initializeMemDepPrinterPass(*PassRegistry::getPassRegistry());
49 bool runOnFunction(Function
&F
) override
;
51 void print(raw_ostream
&OS
, const Module
* = nullptr) const override
;
53 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
54 AU
.addRequiredTransitive
<AAResultsWrapperPass
>();
55 AU
.addRequiredTransitive
<MemoryDependenceWrapperPass
>();
59 void releaseMemory() override
{
65 static InstTypePair
getInstTypePair(MemDepResult dep
) {
67 return InstTypePair(dep
.getInst(), Clobber
);
69 return InstTypePair(dep
.getInst(), Def
);
70 if (dep
.isNonFuncLocal())
71 return InstTypePair(dep
.getInst(), NonFuncLocal
);
72 assert(dep
.isUnknown() && "unexpected dependence type");
73 return InstTypePair(dep
.getInst(), Unknown
);
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)
85 FunctionPass
*llvm::createMemDepPrinter() {
86 return new MemDepPrinter();
89 const char *const MemDepPrinter::DepTypeStr
[]
90 = {"Clobber", "Def", "NonFuncLocal", "Unknown"};
92 bool MemDepPrinter::runOnFunction(Function
&F
) {
94 MemoryDependenceResults
&MDA
= getAnalysis
<MemoryDependenceWrapperPass
>().getMemDep();
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
;
101 if (!Inst
->mayReadFromMemory() && !Inst
->mayWriteToMemory())
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
);
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()));
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
);
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()));
134 void MemDepPrinter::print(raw_ostream
&OS
, const Module
*M
) const {
135 for (const auto &I
: instructions(*F
)) {
136 const Instruction
*Inst
= &I
;
138 DepSetMap::const_iterator DI
= Deps
.find(Inst
);
139 if (DI
== Deps
.end())
142 const DepSet
&InstDeps
= DI
->second
;
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
;
150 OS
<< DepTypeStr
[type
];
153 DepBB
->printAsOperand(OS
, /*PrintType=*/false, M
);