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/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"
22 struct MemDepPrinter
: public FunctionPass
{
32 static const char *const DepTypeStr
[];
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
;
40 static char ID
; // Pass identifcation, replacement for typeid
41 MemDepPrinter() : FunctionPass(ID
) {
42 initializeMemDepPrinterPass(*PassRegistry::getPassRegistry());
45 bool runOnFunction(Function
&F
) override
;
47 void print(raw_ostream
&OS
, const Module
* = nullptr) const override
;
49 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
50 AU
.addRequiredTransitive
<AAResultsWrapperPass
>();
51 AU
.addRequiredTransitive
<MemoryDependenceWrapperPass
>();
55 void releaseMemory() override
{
61 static InstTypePair
getInstTypePair(MemDepResult dep
) {
63 return InstTypePair(dep
.getInst(), Clobber
);
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
);
71 static InstTypePair
getInstTypePair(const Instruction
* inst
, DepType type
) {
72 return InstTypePair(inst
, type
);
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)
84 FunctionPass
*llvm::createMemDepPrinter() {
85 return new MemDepPrinter();
88 const char *const MemDepPrinter::DepTypeStr
[]
89 = {"Clobber", "Def", "NonFuncLocal", "Unknown"};
91 bool MemDepPrinter::runOnFunction(Function
&F
) {
93 MemoryDependenceResults
&MDA
= getAnalysis
<MemoryDependenceWrapperPass
>().getMemDep();
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
;
100 if (!Inst
->mayReadFromMemory() && !Inst
->mayWriteToMemory())
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
);
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()));
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
);
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()));
133 void MemDepPrinter::print(raw_ostream
&OS
, const Module
*M
) const {
134 for (const auto &I
: instructions(*F
)) {
135 const Instruction
*Inst
= &I
;
137 DepSetMap::const_iterator DI
= Deps
.find(Inst
);
138 if (DI
== Deps
.end())
141 const DepSet
&InstDeps
= DI
->second
;
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
;
149 OS
<< DepTypeStr
[type
];
152 DepBB
->printAsOperand(OS
, /*PrintType=*/false, M
);