/builds/2mk6rsew/0/parcoach/parcoach/src/include/parcoach/DepGraphDCF.h
Line | Count | Source |
1 | | #pragma once |
2 | | |
3 | | #include "parcoach/MemorySSA.h" |
4 | | |
5 | | #include "llvm/IR/InstVisitor.h" |
6 | | |
7 | | #include <optional> |
8 | | |
9 | | class PTACallGraphNode; |
10 | | namespace llvm { |
11 | | class raw_fd_ostream; |
12 | | } |
13 | | |
14 | | namespace parcoach { |
15 | | |
16 | | class DepGraphDCF : public llvm::InstVisitor<DepGraphDCF> { |
17 | | public: |
18 | | using VarSet = std::set<MSSAVar *>; |
19 | | using ConstVarSet = std::set<MSSAVar const *>; |
20 | | using ValueSet = std::set<llvm::Value const *>; |
21 | | |
22 | | DepGraphDCF(parcoach::MemorySSA *mssa, PTACallGraph const &CG, |
23 | | llvm::FunctionAnalysisManager &AM, llvm::Module &M, |
24 | | bool ContextInsensitive, bool noPtrDep = false, |
25 | | bool noPred = false, bool disablePhiElim = false); |
26 | | virtual ~DepGraphDCF(); |
27 | | |
28 | | void toDot(llvm::StringRef filename) const; |
29 | | void dotTaintPath(llvm::Value const *v, llvm::StringRef filename, |
30 | | llvm::Instruction const *collective) const; |
31 | | |
32 | | // FIXME: ideally we would have two classes: one analysis result, and one |
33 | | // visitor constructing this analysis result (so that the user can't "visit" |
34 | | // stuff manually and change the analysis' result). |
35 | | void visitBasicBlock(llvm::BasicBlock &BB); |
36 | | void visitAllocaInst(llvm::AllocaInst &I); |
37 | | void visitCmpInst(llvm::CmpInst &I); |
38 | | void visitFreezeInst(llvm::FreezeInst &I); |
39 | | void visitUnaryOperator(llvm::UnaryOperator &I); |
40 | | void visitLoadInst(llvm::LoadInst &I); |
41 | | void visitStoreInst(llvm::StoreInst &I); |
42 | | void visitGetElementPtrInst(llvm::GetElementPtrInst &I); |
43 | | void visitPHINode(llvm::PHINode &I); |
44 | | void visitCastInst(llvm::CastInst &I); |
45 | | void visitSelectInst(llvm::SelectInst &I); |
46 | | void visitBinaryOperator(llvm::BinaryOperator &I); |
47 | | void visitCallInst(llvm::CallInst &I); |
48 | | void visitExtractValueInst(llvm::ExtractValueInst &I); |
49 | | void visitExtractElementInst(llvm::ExtractElementInst &I); |
50 | | void visitInsertElementInst(llvm::InsertElementInst &I); |
51 | | void visitInsertValueInst(llvm::InsertValueInst &I); |
52 | | void visitShuffleVectorInst(llvm::ShuffleVectorInst &I); |
53 | | void visitTerminator(llvm::Instruction &I); |
54 | | static void visitInstruction(llvm::Instruction &I); |
55 | | |
56 | | bool isTaintedValue(llvm::Value const *v) const; |
57 | | |
58 | | void getCallInterIPDF(llvm::CallInst const *call, |
59 | | std::set<llvm::BasicBlock const *> &ipdf) const; |
60 | | |
61 | | private: |
62 | | void build(); |
63 | | void buildFunction(llvm::Function const *F); |
64 | | // Phi elimination pass. |
65 | | // A ssa Phi function can be eliminated if its operands are equivalent. |
66 | | // In this case operands are merged into a single node and the phi is replaced |
67 | | // with this single node. The phi elimination pass allows us to break the |
68 | | // dependency with phi predicates when its operands are the same, e.g.: |
69 | | // if (rank) |
70 | | // a = 0; |
71 | | // else |
72 | | // a = 0; |
73 | | void phiElimination(); |
74 | | |
75 | | void computeTaintedValuesContextInsensitive(); |
76 | | void computeTaintedValuesContextSensitive(); |
77 | | void computeTaintedValuesCSForEntry(PTACallGraphNode const *entry); |
78 | | |
79 | | parcoach::MemorySSA *mssa; |
80 | | PTACallGraph const &CG; |
81 | | |
82 | | llvm::Function const *curFunc; |
83 | | llvm::FunctionAnalysisManager &FAM; |
84 | | llvm::Module const &M; |
85 | | bool const ContextInsensitive; |
86 | | llvm::PostDominatorTree *PDT; |
87 | | |
88 | | /* Graph nodes */ |
89 | | |
90 | | // Map from a function to all its top-level variables nodes. |
91 | | llvm::ValueMap<llvm::Function const *, ValueSet> funcToLLVMNodesMap; |
92 | | // Map from a function to all its address taken ssa nodes. |
93 | | llvm::ValueMap<llvm::Function const *, VarSet> funcToSSANodesMap; |
94 | | std::set<llvm::Function const *> varArgNodes; |
95 | | |
96 | | /* Graph edges */ |
97 | | |
98 | | // top-level to top-level edges |
99 | | llvm::ValueMap<llvm::Value const *, ValueSet> llvmToLLVMChildren; |
100 | | llvm::ValueMap<llvm::Value const *, ValueSet> llvmToLLVMParents; |
101 | | |
102 | | // top-level to address-taken ssa edges |
103 | | llvm::ValueMap<llvm::Value const *, VarSet> llvmToSSAChildren; |
104 | | llvm::ValueMap<llvm::Value const *, VarSet> llvmToSSAParents; |
105 | | // address-taken ssa to top-level edges |
106 | | llvm::DenseMap<MSSAVar *, ValueSet> ssaToLLVMChildren; |
107 | | llvm::DenseMap<MSSAVar *, ValueSet> ssaToLLVMParents; |
108 | | |
109 | | // address-top ssa to address-taken ssa edges |
110 | | llvm::DenseMap<MSSAVar *, VarSet> ssaToSSAChildren; |
111 | | llvm::DenseMap<MSSAVar *, VarSet> ssaToSSAParents; |
112 | | |
113 | | static void enableMPI(); |
114 | | static void enableOMP(); |
115 | | static void enableUPC(); |
116 | | static void enableCUDA(); |
117 | | |
118 | | void addEdge(llvm::Value const *s, llvm::Value const *d); |
119 | | void addEdge(llvm::Value const *s, MSSAVar *d); |
120 | | void addEdge(MSSAVar *s, llvm::Value const *d); |
121 | | void addEdge(MSSAVar *s, MSSAVar *d); |
122 | | void removeEdge(llvm::Value const *s, llvm::Value const *d); |
123 | | void removeEdge(llvm::Value const *s, MSSAVar *d); |
124 | | void removeEdge(MSSAVar *s, llvm::Value const *d); |
125 | | void removeEdge(MSSAVar *s, MSSAVar *d); |
126 | | |
127 | | /* PDF+ call nodes and edges */ |
128 | | |
129 | | // map from a function to all its call instructions |
130 | | llvm::ValueMap<llvm::Function const *, ValueSet> funcToCallNodes; |
131 | | // map from call instructions to called functions |
132 | | llvm::ValueMap<llvm::Value const *, llvm::Function const *> callToFuncEdges; |
133 | | // map from a condition to call instructions depending on that condition. |
134 | | llvm::ValueMap<llvm::Value const *, ValueSet> condToCallEdges; |
135 | | |
136 | | // map from a function to all the call sites calling this function. |
137 | | llvm::ValueMap<llvm::Function const *, ValueSet> funcToCallSites; |
138 | | // map from a callsite to all its conditions. |
139 | | llvm::ValueMap<llvm::Value const *, ValueSet> callsiteToConds; |
140 | | |
141 | | /* tainted nodes */ |
142 | | ValueSet taintedLLVMNodes; |
143 | | ConstVarSet taintedSSANodes; |
144 | | |
145 | | ConstVarSet taintResetSSANodes; |
146 | | ConstVarSet ssaSources; |
147 | | ValueSet valueSources; |
148 | | |
149 | | void floodFunction(llvm::Function const *F); |
150 | | void floodFunctionFromFunction(llvm::Function const *to, |
151 | | llvm::Function const *from); |
152 | | void resetFunctionTaint(llvm::Function const *F); |
153 | | void computeFunctionCSTaintedConds(llvm::Function const *F); |
154 | | ValueSet taintedConditions; |
155 | | |
156 | | /* Graph construction for call sites*/ |
157 | | void connectCSMus(llvm::CallInst &I); |
158 | | void connectCSChis(llvm::CallInst &I); |
159 | | void connectCSEffectiveParameters(llvm::CallInst &I); |
160 | | void connectCSEffectiveParametersExt(llvm::CallInst &I, |
161 | | llvm::Function const *callee); |
162 | | void connectCSCalledReturnValue(llvm::CallInst &I); |
163 | | void connectCSRetChi(llvm::CallInst &I); |
164 | | |
165 | | // Two nodes are equivalent if they have exactly the same incoming and |
166 | | // outgoing edges and if none of them are phi nodes. |
167 | | bool areSSANodesEquivalent(MSSAVar *var1, MSSAVar *var2); |
168 | | |
169 | | // This function replaces phi with op1 and removes op2. |
170 | | void eliminatePhi(MSSAPhi *phi, std::vector<MSSAVar *> ops); |
171 | | |
172 | | void dotFunction(llvm::raw_fd_ostream &stream, llvm::Function const *F) const; |
173 | | void dotExtFunction(llvm::raw_fd_ostream &stream, |
174 | | llvm::Function const *F) const; |
175 | | std::string getNodeStyle(llvm::Value const *v) const; |
176 | | std::string getNodeStyle(MSSAVar const *v) const; |
177 | | static std::string getNodeStyle(llvm::Function const *f); |
178 | | static std::string getCallNodeStyle(llvm::Value const *v); |
179 | | |
180 | | struct DGDebugLoc { |
181 | | llvm::Function const *F; |
182 | | std::string filename; |
183 | | int line; |
184 | | |
185 | 6 | bool operator<(DGDebugLoc const &o) const { return line < o.line; } |
186 | | }; |
187 | | |
188 | | static bool getDGDebugLoc(llvm::Value const *v, DGDebugLoc &DL); |
189 | | static bool getDGDebugLoc(MSSAVar *v, DGDebugLoc &DL); |
190 | | static std::string getStringMsg(llvm::Value const *v); |
191 | | static std::string getStringMsg(MSSAVar *v); |
192 | | static bool getDebugTrace(std::vector<DGDebugLoc> &DLs, std::string &trace, |
193 | | llvm::Instruction const *collective); |
194 | | static void reorderAndRemoveDup(std::vector<DGDebugLoc> &DLs); |
195 | | |
196 | | /* options */ |
197 | | bool noPtrDep; |
198 | | bool noPred; |
199 | | bool disablePhiElim; |
200 | | }; |
201 | | |
202 | | class DepGraphDCFAnalysis |
203 | | : public llvm::AnalysisInfoMixin<DepGraphDCFAnalysis> { |
204 | | friend llvm::AnalysisInfoMixin<DepGraphDCFAnalysis>; |
205 | | static llvm::AnalysisKey Key; |
206 | | bool ContextInsensitive_; |
207 | | |
208 | | public: |
209 | | DepGraphDCFAnalysis(bool ContextInsensitive) |
210 | 1.82k | : ContextInsensitive_(ContextInsensitive){}; |
211 | | // We return a unique_ptr to ensure stability of the analysis' internal state. |
212 | | using Result = std::unique_ptr<DepGraphDCF>; |
213 | | Result run(llvm::Module &M, llvm::ModuleAnalysisManager &); |
214 | | }; |
215 | | } // namespace parcoach |