/builds/2mk6rsew/0/parcoach/parcoach/src/aSSA/Utils.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | #include "Utils.h" |
2 | | #include "parcoach/Collectives.h" |
3 | | |
4 | | #include <sys/time.h> |
5 | | |
6 | | #include "llvm/IR/DebugInfo.h" |
7 | | #include "llvm/IR/DebugLoc.h" |
8 | | #include "llvm/IR/IRBuilder.h" |
9 | | #include "llvm/IR/InstIterator.h" |
10 | | #include "llvm/IR/IntrinsicInst.h" |
11 | | #include "llvm/Support/raw_ostream.h" |
12 | | |
13 | | #include <map> |
14 | | |
15 | | #define DEBUG_TYPE "hello" |
16 | | |
17 | | using namespace llvm; |
18 | | |
19 | 376k | bool isCallSite(llvm::Instruction const *Inst) { |
20 | 376k | return llvm::isa<llvm::CallBase>(Inst); |
21 | 376k | } |
22 | | |
23 | 100 | std::string getValueLabel(llvm::Value const *V) { |
24 | 100 | assert(!isa<Function>(V) && "Use F->getName for functions"); |
25 | | |
26 | 100 | std::string Label; |
27 | 100 | llvm::raw_string_ostream Rso(Label); |
28 | 100 | V->print(Rso); |
29 | 100 | size_t Pos = Label.find_first_of('='); |
30 | 100 | if (Pos != std::string::npos) { |
31 | 74 | Label = Label.substr(0, Pos); |
32 | 74 | } |
33 | 100 | return Label; |
34 | 100 | } |
35 | | |
36 | 26 | std::string getCallValueLabel(llvm::Value const *V) { |
37 | 26 | std::string Label; |
38 | 26 | llvm::raw_string_ostream Rso(Label); |
39 | 26 | V->print(Rso); |
40 | 26 | size_t Pos = Label.find_first_of('='); |
41 | 26 | if (Pos != std::string::npos) { |
42 | 20 | Label = Label.substr(Pos + 2); |
43 | 20 | } |
44 | 26 | return Label; |
45 | 26 | } |
46 | | |
47 | | /* |
48 | | * POSTDOMINANCE |
49 | | */ |
50 | | |
51 | | static std::map<BasicBlock *, std::unique_ptr<std::set<BasicBlock *>>> PdfCache; |
52 | | |
53 | | // PDF computation |
54 | | std::vector<BasicBlock *> postdominanceFrontier(PostDominatorTree &PDT, |
55 | 50.3k | BasicBlock *BB) { |
56 | 50.3k | std::vector<BasicBlock *> PDF; |
57 | | |
58 | 50.3k | auto &Cache = PdfCache[BB]; |
59 | 50.3k | if (Cache) { |
60 | 35.3k | for (BasicBlock *B : *Cache) { |
61 | 7.75k | PDF.push_back(B); |
62 | 7.75k | } |
63 | 35.3k | return PDF; |
64 | 35.3k | } |
65 | | |
66 | 15.0k | PDF.clear(); |
67 | 15.0k | DomTreeNode *DomNode = PDT.getNode(BB); |
68 | | |
69 | 33.7k | for (auto It = pred_begin(BB), Et = pred_end(BB); It != Et; ++It) { |
70 | | // does BB immediately dominate this predecessor? |
71 | 18.6k | DomTreeNode *ID = PDT[*It]; //->getIDom(); |
72 | 18.6k | if ((ID != nullptr) && ID->getIDom() != DomNode && *It != BB) { |
73 | 7.01k | PDF.push_back(*It); |
74 | 7.01k | } |
75 | 18.6k | } |
76 | 15.0k | for (DomTreeNode::const_iterator NI = DomNode->begin(), NE = DomNode->end(); |
77 | 28.2k | NI != NE; ++NI) { |
78 | 13.1k | DomTreeNode *IDominee = *NI; |
79 | 13.1k | std::vector<BasicBlock *> ChildDF = |
80 | 13.1k | postdominanceFrontier(PDT, IDominee->getBlock()); |
81 | 13.1k | std::vector<BasicBlock *>::const_iterator CDFI = ChildDF.begin(); |
82 | 13.1k | std::vector<BasicBlock *>::const_iterator CDFE = ChildDF.end(); |
83 | 20.8k | for (; CDFI != CDFE; ++CDFI) { |
84 | 7.72k | if (PDT[*CDFI]->getIDom() != DomNode && *CDFI != BB) { |
85 | 781 | PDF.push_back(*CDFI); |
86 | 781 | } |
87 | 7.72k | } |
88 | 13.1k | } |
89 | | |
90 | 15.0k | PdfCache[BB] = std::make_unique<std::set<BasicBlock *>>(); |
91 | 15.0k | PdfCache[BB]->insert(PDF.begin(), PDF.end()); |
92 | | |
93 | 15.0k | return PDF; |
94 | 50.3k | } |
95 | | |
96 | | static std::map<BasicBlock *, std::unique_ptr<std::set<BasicBlock *>>> |
97 | | IpdfCache; |
98 | | |
99 | | // PDF+ computation |
100 | | std::vector<BasicBlock *> |
101 | 50.9k | iterated_postdominance_frontier(PostDominatorTree &PDT, BasicBlock *BB) { |
102 | 50.9k | std::vector<BasicBlock *> IPDF; |
103 | | |
104 | 50.9k | auto &Cache = IpdfCache[BB]; |
105 | 50.9k | if (Cache) { |
106 | 22.8k | for (BasicBlock *B : *Cache) { |
107 | 22.8k | IPDF.push_back(B); |
108 | 22.8k | } |
109 | 21.6k | return IPDF; |
110 | 21.6k | } |
111 | | |
112 | 29.3k | IPDF = postdominanceFrontier(PDT, BB); |
113 | 29.3k | if (IPDF.empty()) { |
114 | 22.0k | return IPDF; |
115 | 22.0k | } |
116 | | |
117 | 7.30k | std::set<BasicBlock *> S; |
118 | 7.30k | S.insert(IPDF.begin(), IPDF.end()); |
119 | | |
120 | 7.30k | std::set<BasicBlock *> ToCompute; |
121 | 7.30k | std::set<BasicBlock *> ToComputeTmp; |
122 | 7.30k | ToCompute.insert(IPDF.begin(), IPDF.end()); |
123 | | |
124 | 7.30k | bool Changed = true; |
125 | 15.1k | while (Changed) { |
126 | 7.79k | Changed = false; |
127 | | |
128 | 15.6k | for (auto I = ToCompute.begin(), E = ToCompute.end(); I != E; ++I) { |
129 | 7.80k | std::vector<BasicBlock *> Tmp = postdominanceFrontier(PDT, *I); |
130 | 8.31k | for (auto J = Tmp.begin(), F = Tmp.end(); J != F; ++J) { |
131 | 509 | if ((S.insert(*J)).second) { |
132 | 494 | ToComputeTmp.insert(*J); |
133 | 494 | Changed = true; |
134 | 494 | } |
135 | 509 | } |
136 | 7.80k | } |
137 | | |
138 | 7.79k | ToCompute = ToComputeTmp; |
139 | 7.79k | ToComputeTmp.clear(); |
140 | 7.79k | } |
141 | | |
142 | 7.30k | IPDF.insert(IPDF.end(), S.begin(), S.end()); |
143 | | |
144 | 7.30k | IpdfCache[BB] = std::make_unique<std::set<BasicBlock *>>(); |
145 | 7.30k | IpdfCache[BB]->insert(IPDF.begin(), IPDF.end()); |
146 | | |
147 | 7.30k | return IPDF; |
148 | 29.3k | } |
149 | | |
150 | | std::set<llvm::Value const *> |
151 | 27.5k | computeIPDFPredicates(llvm::PostDominatorTree &PDT, llvm::BasicBlock *BB) { |
152 | 27.5k | std::set<llvm::Value const *> Preds; |
153 | | |
154 | | // Get IPDF |
155 | 27.5k | std::vector<BasicBlock *> IPDF = iterated_postdominance_frontier(PDT, BB); |
156 | | |
157 | 42.3k | for (unsigned N = 0; N < IPDF.size(); ++N) { |
158 | | // Push conditions of each BB in the IPDF |
159 | 14.7k | Instruction const *Term = IPDF[N]->getTerminator(); |
160 | 14.7k | assert(Term); |
161 | | |
162 | 14.7k | if (isa<BranchInst>(Term)) { |
163 | 14.7k | BranchInst const *Bi = cast<BranchInst>(Term); |
164 | 14.7k | assert(Bi); |
165 | | |
166 | 14.7k | if (Bi->isUnconditional()) { |
167 | 0 | continue; |
168 | 0 | } |
169 | | |
170 | 14.7k | Value const *Cond = Bi->getCondition(); |
171 | 14.7k | Preds.insert(Cond); |
172 | 14.7k | } else if (isa<SwitchInst>(Term)) { |
173 | 10 | SwitchInst const *SI = cast<SwitchInst>(Term); |
174 | 10 | assert(SI); |
175 | 10 | Value const *Cond = SI->getCondition(); |
176 | 10 | Preds.insert(Cond); |
177 | 10 | } |
178 | 14.7k | } |
179 | | |
180 | 27.5k | return Preds; |
181 | 27.5k | } |
182 | | |
183 | 2.57k | llvm::Value const *getBasicBlockCond(BasicBlock const *BB) { |
184 | 2.57k | Instruction const *Term = BB->getTerminator(); |
185 | 2.57k | assert(Term); |
186 | | |
187 | 2.57k | if (isa<BranchInst>(Term)) { |
188 | 2.57k | BranchInst const *Bi = cast<BranchInst>(Term); |
189 | 2.57k | assert(Bi); |
190 | | |
191 | 2.57k | if (Bi->isUnconditional()) { |
192 | 0 | return nullptr; |
193 | 0 | } |
194 | | |
195 | 2.57k | return Bi->getCondition(); |
196 | 2.57k | } |
197 | 0 | if (isa<SwitchInst>(Term)) { |
198 | 0 | SwitchInst const *SI = cast<SwitchInst>(Term); |
199 | 0 | assert(SI); |
200 | 0 | return SI->getCondition(); |
201 | 0 | } |
202 | | |
203 | 0 | return nullptr; |
204 | 0 | } |
205 | | |
206 | 0 | llvm::Value const *getReturnValue(llvm::Function const *F) { |
207 | 0 | Value const *Ret = NULL; |
208 | |
|
209 | 0 | for (auto I = inst_begin(F), E = inst_end(F); I != E; ++I) { |
210 | 0 | Instruction const *Inst = &*I; |
211 | |
|
212 | 0 | if (ReturnInst const *RI = dyn_cast<ReturnInst>(Inst)) { |
213 | 0 | assert(Ret == NULL && "There exists more than one return instruction"); |
214 | |
|
215 | 0 | Ret = RI->getReturnValue(); |
216 | 0 | } |
217 | 0 | } |
218 | |
|
219 | 0 | assert(Ret != NULL && "There is no return instruction"); |
220 | |
|
221 | 0 | return Ret; |
222 | 0 | } |
223 | | |
224 | 135k | bool isIntrinsicDbgFunction(llvm::Function const *F) { |
225 | 135k | return F != NULL && F->getName().startswith("llvm.dbg"); |
226 | 135k | } |
227 | | |
228 | 107k | bool isIntrinsicDbgInst(llvm::Instruction const *I) { |
229 | 107k | return isa<DbgInfoIntrinsic>(I); |
230 | 107k | } |
231 | | |
232 | 1.82k | bool functionDoesNotRet(llvm::Function const *F) { |
233 | 1.82k | std::vector<BasicBlock const *> ToVisit; |
234 | 1.82k | std::set<BasicBlock const *> Visited; |
235 | | |
236 | 1.82k | ToVisit.push_back(&F->getEntryBlock()); |
237 | | |
238 | 9.12k | while (!ToVisit.empty()) { |
239 | 9.12k | BasicBlock const *BB = ToVisit.back(); |
240 | 9.12k | ToVisit.pop_back(); |
241 | | |
242 | 150k | for (Instruction const &Inst : *BB) { |
243 | 150k | if (isa<ReturnInst>(Inst)) { |
244 | 1.82k | return false; |
245 | 1.82k | } |
246 | 150k | } |
247 | | |
248 | 19.9k | for (auto I = succ_begin(BB), E = succ_end(BB); I != E; ++I) { |
249 | 12.6k | BasicBlock const *Succ = *I; |
250 | 12.6k | if (Visited.find(Succ) == Visited.end()) { |
251 | 12.5k | ToVisit.push_back(Succ); |
252 | 12.5k | Visited.insert(Succ); |
253 | 12.5k | } |
254 | 12.6k | } |
255 | 7.29k | } |
256 | | |
257 | 0 | return true; |
258 | 1.82k | } |
259 | | |
260 | | unsigned getBBSetIntersectionSize(const std::set<BasicBlock const *> S1, |
261 | 0 | const std::set<BasicBlock const *> S2) { |
262 | 0 | unsigned Ret = 0; |
263 | |
|
264 | 0 | for (BasicBlock const *BB : S1) { |
265 | 0 | if (S2.find(BB) != S2.end()) { |
266 | 0 | Ret++; |
267 | 0 | } |
268 | 0 | } |
269 | |
|
270 | 0 | return Ret; |
271 | 0 | } |
272 | | |
273 | | unsigned getInstSetIntersectionSize(const std::set<Instruction const *> S1, |
274 | 0 | const std::set<Instruction const *> S2) { |
275 | 0 | unsigned Ret = 0; |
276 | |
|
277 | 0 | for (Instruction const *I : S1) { |
278 | 0 | if (S2.find(I) != S2.end()) { |
279 | 0 | Ret++; |
280 | 0 | } |
281 | 0 | } |
282 | |
|
283 | 0 | return Ret; |
284 | 0 | } |