clang: lib/Analysis/ThreadSafetyTIL.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
11#include "llvm/Support/Casting.h"
12#include
13#include
14
15using namespace clang;
16using namespace threadSafety;
17using namespace til;
18
20 switch (Op) {
24 }
25 return {};
26}
27
29 switch (Op) {
35 case BOP_Shl: return "<<";
36 case BOP_Shr: return ">>";
40 case BOP_Eq: return "==";
41 case BOP_Neq: return "!=";
42 case BOP_Lt: return "<";
43 case BOP_Leq: return "<=";
44 case BOP_Cmp: return "<=>";
47 }
48 return {};
49}
50
51SExpr* Future::force() {
55 return Result;
56}
57
59 unsigned Idx = Predecessors.size();
62 for (auto *E : Args) {
63 if (auto *Ph = dyn_cast(E)) {
64 Ph->values().reserveCheck(1, Arena);
65 Ph->values().push_back(nullptr);
66 }
67 }
68 return Idx;
69}
70
72 Predecessors.reserve(NumPreds, Arena);
73 for (auto *E : Args) {
74 if (auto *Ph = dyn_cast(E)) {
75 Ph->values().reserve(NumPreds, Arena);
76 }
77 }
78}
79
80
81
83 while (true) {
84 if (const auto *V = dyn_cast(E)) {
87 continue;
88 }
89 }
90 if (const auto *Ph = dyn_cast(E)) {
92 E = Ph->values()[0];
93 continue;
94 }
95 }
96 break;
97 }
98 return E;
99}
100
101
102
103
105 while (true) {
106 if (auto *V = dyn_cast(E)) {
108 return V;
109
110
113 continue;
114 }
115 return V;
116 }
117 if (auto *Ph = dyn_cast(E)) {
120
122 E = Ph->values()[0];
123 continue;
124 }
125 }
126 return E;
127 }
128}
129
130
131
132
135
136
138
140 for (unsigned i = 1, n = Ph->values().size(); i < n; ++i) {
142 if (Ei == Ph)
143 continue;
144 if (Ei != E0) {
145 return;
146 }
147 }
149}
150
151
152unsigned BasicBlock::renumberInstrs(unsigned ID) {
153 for (auto *Arg : Args)
154 Arg->setID(this, ID++);
155 for (auto *Instr : Instrs)
156 Instr->setID(this, ID++);
157 TermInstr->setID(this, ID++);
158 return ID;
159}
160
161
162
163
164
166 unsigned ID) {
167 if (Visited) return ID;
168 Visited = true;
170 ID = Block->topologicalSort(Blocks, ID);
171
172
173 assert(ID > 0);
174 BlockID = --ID;
175 Blocks[BlockID] = this;
176 return ID;
177}
178
179
180
181
182
183
184
185
186
187
188
190 unsigned ID) {
191
192
193 if (!Visited) return ID;
194 Visited = false;
195 if (DominatorNode.Parent)
196 ID = DominatorNode.Parent->topologicalFinalSort(Blocks, ID);
197 for (auto *Pred : Predecessors)
198 ID = Pred->topologicalFinalSort(Blocks, ID);
199 assert(static_cast<size_t>(ID) < Blocks.size());
200 BlockID = ID++;
201 Blocks[BlockID] = this;
202 return ID;
203}
204
205
206
207
208void BasicBlock::computeDominator() {
210
211 for (auto *Pred : Predecessors) {
212
213 if (Pred->BlockID >= BlockID) continue;
214
215 if (Candidate == nullptr) {
216 Candidate = Pred;
217 continue;
218 }
219
220 auto *Alternate = Pred;
221 while (Alternate != Candidate) {
222 if (Candidate->BlockID > Alternate->BlockID)
223 Candidate = Candidate->DominatorNode.Parent;
224 else
225 Alternate = Alternate->DominatorNode.Parent;
226 }
227 }
228 DominatorNode.Parent = Candidate;
230}
231
232
233
234
235void BasicBlock::computePostDominator() {
237
239
240 if (Succ->BlockID <= BlockID) continue;
241
242 if (Candidate == nullptr) {
243 Candidate = Succ;
244 continue;
245 }
246
247 auto *Alternate = Succ;
248 while (Alternate != Candidate) {
249 if (Candidate->BlockID < Alternate->BlockID)
250 Candidate = Candidate->PostDominatorNode.Parent;
251 else
252 Alternate = Alternate->PostDominatorNode.Parent;
253 }
254 }
255 PostDominatorNode.Parent = Candidate;
257}
258
259
260void SCFG::renumberInstrs() {
261 unsigned InstrID = 0;
262 for (auto *Block : Blocks)
263 InstrID = Block->renumberInstrs(InstrID);
264}
265
271
272 N->NodeID = P->SizeOfSubTree;
274 }
275}
276
283 }
284}
285
286
287
288
289
291
292 unsigned NumUnreachableBlocks = Entry->topologicalSort(Blocks, Blocks.size());
293 if (NumUnreachableBlocks > 0) {
294
295 for (unsigned I = NumUnreachableBlocks, E = Blocks.size(); I < E; ++I) {
296 unsigned NI = I - NumUnreachableBlocks;
297 Blocks[NI] = Blocks[I];
298 Blocks[NI]->BlockID = NI;
299
300 }
301 Blocks.drop(NumUnreachableBlocks);
302 }
303
304
305 for (auto *Block : Blocks)
306 Block->computeDominator();
307
308
309 unsigned NumBlocks = Exit->topologicalFinalSort(Blocks, 0);
310 assert(static_cast<size_t>(NumBlocks) == Blocks.size());
311 (void) NumBlocks;
312
313
314 renumberInstrs();
315
316
317
318 for (auto *Block : Blocks.reverse()) {
319 Block->computePostDominator();
321 }
322
323
324 for (auto *Block : Blocks) {
327 }
328
329 for (auto *Block : Blocks.reverse()) {
331 }
332}
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
static void computeNodeSize(BasicBlock *B, BasicBlock::TopologyNode BasicBlock::*TN)
static void computeNodeID(BasicBlock *B, BasicBlock::TopologyNode BasicBlock::*TN)
A basic block is part of an SCFG.
unsigned addPredecessor(BasicBlock *Pred)
ArrayRef< BasicBlock * > successors()
void reservePredecessors(unsigned NumPreds)
virtual SExpr * compute()
Phi Node, for code in SSA form.
const ValArray & values() const
Base class for AST nodes in the typed intermediate language.
void setID(BasicBlock *B, unsigned id)
Set the basic block and instruction ID for this expression.
void reserve(size_t Ncp, MemRegionRef A)
void push_back(const T &Elem)
void reserveCheck(size_t N, MemRegionRef A)
bool isTrivial(const SExpr *E)
TIL_UnaryOpcode
Opcode for unary arithmetic operations.
void simplifyIncompleteArg(til::Phi *Ph)
StringRef getBinaryOpcodeString(TIL_BinaryOpcode Op)
Return the name of a binary opcode.
StringRef getUnaryOpcodeString(TIL_UnaryOpcode Op)
Return the name of a unary opcode.
TIL_BinaryOpcode
Opcode for binary arithmetic operations.
SExpr * simplifyToCanonicalVal(SExpr *E)
const SExpr * getCanonicalVal(const SExpr *E)
The JSON file list parser is used to communicate input to InstallAPI.