xref: /aosp_15_r20/external/clang/lib/Analysis/ThreadSafetyTIL.cpp (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li //===- ThreadSafetyTIL.cpp -------------------------------------*- C++ --*-===//
2*67e74705SXin Li //
3*67e74705SXin Li //                     The LLVM Compiler Infrastructure
4*67e74705SXin Li //
5*67e74705SXin Li // This file is distributed under the University of Illinois Open Source
6*67e74705SXin Li // License. See LICENSE.TXT in the llvm repository for details.
7*67e74705SXin Li //
8*67e74705SXin Li //===----------------------------------------------------------------------===//
9*67e74705SXin Li 
10*67e74705SXin Li #include "clang/Analysis/Analyses/ThreadSafetyTIL.h"
11*67e74705SXin Li #include "clang/Analysis/Analyses/ThreadSafetyTraverse.h"
12*67e74705SXin Li using namespace clang;
13*67e74705SXin Li using namespace threadSafety;
14*67e74705SXin Li using namespace til;
15*67e74705SXin Li 
getUnaryOpcodeString(TIL_UnaryOpcode Op)16*67e74705SXin Li StringRef til::getUnaryOpcodeString(TIL_UnaryOpcode Op) {
17*67e74705SXin Li   switch (Op) {
18*67e74705SXin Li     case UOP_Minus:    return "-";
19*67e74705SXin Li     case UOP_BitNot:   return "~";
20*67e74705SXin Li     case UOP_LogicNot: return "!";
21*67e74705SXin Li   }
22*67e74705SXin Li   return "";
23*67e74705SXin Li }
24*67e74705SXin Li 
getBinaryOpcodeString(TIL_BinaryOpcode Op)25*67e74705SXin Li StringRef til::getBinaryOpcodeString(TIL_BinaryOpcode Op) {
26*67e74705SXin Li   switch (Op) {
27*67e74705SXin Li     case BOP_Mul:      return "*";
28*67e74705SXin Li     case BOP_Div:      return "/";
29*67e74705SXin Li     case BOP_Rem:      return "%";
30*67e74705SXin Li     case BOP_Add:      return "+";
31*67e74705SXin Li     case BOP_Sub:      return "-";
32*67e74705SXin Li     case BOP_Shl:      return "<<";
33*67e74705SXin Li     case BOP_Shr:      return ">>";
34*67e74705SXin Li     case BOP_BitAnd:   return "&";
35*67e74705SXin Li     case BOP_BitXor:   return "^";
36*67e74705SXin Li     case BOP_BitOr:    return "|";
37*67e74705SXin Li     case BOP_Eq:       return "==";
38*67e74705SXin Li     case BOP_Neq:      return "!=";
39*67e74705SXin Li     case BOP_Lt:       return "<";
40*67e74705SXin Li     case BOP_Leq:      return "<=";
41*67e74705SXin Li     case BOP_LogicAnd: return "&&";
42*67e74705SXin Li     case BOP_LogicOr:  return "||";
43*67e74705SXin Li   }
44*67e74705SXin Li   return "";
45*67e74705SXin Li }
46*67e74705SXin Li 
47*67e74705SXin Li 
force()48*67e74705SXin Li SExpr* Future::force() {
49*67e74705SXin Li   Status = FS_evaluating;
50*67e74705SXin Li   Result = compute();
51*67e74705SXin Li   Status = FS_done;
52*67e74705SXin Li   return Result;
53*67e74705SXin Li }
54*67e74705SXin Li 
55*67e74705SXin Li 
addPredecessor(BasicBlock * Pred)56*67e74705SXin Li unsigned BasicBlock::addPredecessor(BasicBlock *Pred) {
57*67e74705SXin Li   unsigned Idx = Predecessors.size();
58*67e74705SXin Li   Predecessors.reserveCheck(1, Arena);
59*67e74705SXin Li   Predecessors.push_back(Pred);
60*67e74705SXin Li   for (SExpr *E : Args) {
61*67e74705SXin Li     if (Phi* Ph = dyn_cast<Phi>(E)) {
62*67e74705SXin Li       Ph->values().reserveCheck(1, Arena);
63*67e74705SXin Li       Ph->values().push_back(nullptr);
64*67e74705SXin Li     }
65*67e74705SXin Li   }
66*67e74705SXin Li   return Idx;
67*67e74705SXin Li }
68*67e74705SXin Li 
69*67e74705SXin Li 
reservePredecessors(unsigned NumPreds)70*67e74705SXin Li void BasicBlock::reservePredecessors(unsigned NumPreds) {
71*67e74705SXin Li   Predecessors.reserve(NumPreds, Arena);
72*67e74705SXin Li   for (SExpr *E : Args) {
73*67e74705SXin Li     if (Phi* Ph = dyn_cast<Phi>(E)) {
74*67e74705SXin Li       Ph->values().reserve(NumPreds, Arena);
75*67e74705SXin Li     }
76*67e74705SXin Li   }
77*67e74705SXin Li }
78*67e74705SXin Li 
79*67e74705SXin Li 
80*67e74705SXin Li // If E is a variable, then trace back through any aliases or redundant
81*67e74705SXin Li // Phi nodes to find the canonical definition.
getCanonicalVal(const SExpr * E)82*67e74705SXin Li const SExpr *til::getCanonicalVal(const SExpr *E) {
83*67e74705SXin Li   while (true) {
84*67e74705SXin Li     if (auto *V = dyn_cast<Variable>(E)) {
85*67e74705SXin Li       if (V->kind() == Variable::VK_Let) {
86*67e74705SXin Li         E = V->definition();
87*67e74705SXin Li         continue;
88*67e74705SXin Li       }
89*67e74705SXin Li     }
90*67e74705SXin Li     if (const Phi *Ph = dyn_cast<Phi>(E)) {
91*67e74705SXin Li       if (Ph->status() == Phi::PH_SingleVal) {
92*67e74705SXin Li         E = Ph->values()[0];
93*67e74705SXin Li         continue;
94*67e74705SXin Li       }
95*67e74705SXin Li     }
96*67e74705SXin Li     break;
97*67e74705SXin Li   }
98*67e74705SXin Li   return E;
99*67e74705SXin Li }
100*67e74705SXin Li 
101*67e74705SXin Li 
102*67e74705SXin Li // If E is a variable, then trace back through any aliases or redundant
103*67e74705SXin Li // Phi nodes to find the canonical definition.
104*67e74705SXin Li // The non-const version will simplify incomplete Phi nodes.
simplifyToCanonicalVal(SExpr * E)105*67e74705SXin Li SExpr *til::simplifyToCanonicalVal(SExpr *E) {
106*67e74705SXin Li   while (true) {
107*67e74705SXin Li     if (auto *V = dyn_cast<Variable>(E)) {
108*67e74705SXin Li       if (V->kind() != Variable::VK_Let)
109*67e74705SXin Li         return V;
110*67e74705SXin Li       // Eliminate redundant variables, e.g. x = y, or x = 5,
111*67e74705SXin Li       // but keep anything more complicated.
112*67e74705SXin Li       if (til::ThreadSafetyTIL::isTrivial(V->definition())) {
113*67e74705SXin Li         E = V->definition();
114*67e74705SXin Li         continue;
115*67e74705SXin Li       }
116*67e74705SXin Li       return V;
117*67e74705SXin Li     }
118*67e74705SXin Li     if (auto *Ph = dyn_cast<Phi>(E)) {
119*67e74705SXin Li       if (Ph->status() == Phi::PH_Incomplete)
120*67e74705SXin Li         simplifyIncompleteArg(Ph);
121*67e74705SXin Li       // Eliminate redundant Phi nodes.
122*67e74705SXin Li       if (Ph->status() == Phi::PH_SingleVal) {
123*67e74705SXin Li         E = Ph->values()[0];
124*67e74705SXin Li         continue;
125*67e74705SXin Li       }
126*67e74705SXin Li     }
127*67e74705SXin Li     return E;
128*67e74705SXin Li   }
129*67e74705SXin Li }
130*67e74705SXin Li 
131*67e74705SXin Li 
132*67e74705SXin Li // Trace the arguments of an incomplete Phi node to see if they have the same
133*67e74705SXin Li // canonical definition.  If so, mark the Phi node as redundant.
134*67e74705SXin Li // getCanonicalVal() will recursively call simplifyIncompletePhi().
simplifyIncompleteArg(til::Phi * Ph)135*67e74705SXin Li void til::simplifyIncompleteArg(til::Phi *Ph) {
136*67e74705SXin Li   assert(Ph && Ph->status() == Phi::PH_Incomplete);
137*67e74705SXin Li 
138*67e74705SXin Li   // eliminate infinite recursion -- assume that this node is not redundant.
139*67e74705SXin Li   Ph->setStatus(Phi::PH_MultiVal);
140*67e74705SXin Li 
141*67e74705SXin Li   SExpr *E0 = simplifyToCanonicalVal(Ph->values()[0]);
142*67e74705SXin Li   for (unsigned i=1, n=Ph->values().size(); i<n; ++i) {
143*67e74705SXin Li     SExpr *Ei = simplifyToCanonicalVal(Ph->values()[i]);
144*67e74705SXin Li     if (Ei == Ph)
145*67e74705SXin Li       continue;  // Recursive reference to itself.  Don't count.
146*67e74705SXin Li     if (Ei != E0) {
147*67e74705SXin Li       return;    // Status is already set to MultiVal.
148*67e74705SXin Li     }
149*67e74705SXin Li   }
150*67e74705SXin Li   Ph->setStatus(Phi::PH_SingleVal);
151*67e74705SXin Li }
152*67e74705SXin Li 
153*67e74705SXin Li 
154*67e74705SXin Li // Renumbers the arguments and instructions to have unique, sequential IDs.
renumberInstrs(int ID)155*67e74705SXin Li int BasicBlock::renumberInstrs(int ID) {
156*67e74705SXin Li   for (auto *Arg : Args)
157*67e74705SXin Li     Arg->setID(this, ID++);
158*67e74705SXin Li   for (auto *Instr : Instrs)
159*67e74705SXin Li     Instr->setID(this, ID++);
160*67e74705SXin Li   TermInstr->setID(this, ID++);
161*67e74705SXin Li   return ID;
162*67e74705SXin Li }
163*67e74705SXin Li 
164*67e74705SXin Li // Sorts the CFGs blocks using a reverse post-order depth-first traversal.
165*67e74705SXin Li // Each block will be written into the Blocks array in order, and its BlockID
166*67e74705SXin Li // will be set to the index in the array.  Sorting should start from the entry
167*67e74705SXin Li // block, and ID should be the total number of blocks.
topologicalSort(SimpleArray<BasicBlock * > & Blocks,int ID)168*67e74705SXin Li int BasicBlock::topologicalSort(SimpleArray<BasicBlock*>& Blocks, int ID) {
169*67e74705SXin Li   if (Visited) return ID;
170*67e74705SXin Li   Visited = true;
171*67e74705SXin Li   for (auto *Block : successors())
172*67e74705SXin Li     ID = Block->topologicalSort(Blocks, ID);
173*67e74705SXin Li   // set ID and update block array in place.
174*67e74705SXin Li   // We may lose pointers to unreachable blocks.
175*67e74705SXin Li   assert(ID > 0);
176*67e74705SXin Li   BlockID = --ID;
177*67e74705SXin Li   Blocks[BlockID] = this;
178*67e74705SXin Li   return ID;
179*67e74705SXin Li }
180*67e74705SXin Li 
181*67e74705SXin Li // Performs a reverse topological traversal, starting from the exit block and
182*67e74705SXin Li // following back-edges.  The dominator is serialized before any predecessors,
183*67e74705SXin Li // which guarantees that all blocks are serialized after their dominator and
184*67e74705SXin Li // before their post-dominator (because it's a reverse topological traversal).
185*67e74705SXin Li // ID should be initially set to 0.
186*67e74705SXin Li //
187*67e74705SXin Li // This sort assumes that (1) dominators have been computed, (2) there are no
188*67e74705SXin Li // critical edges, and (3) the entry block is reachable from the exit block
189*67e74705SXin Li // and no blocks are accessable via traversal of back-edges from the exit that
190*67e74705SXin Li // weren't accessable via forward edges from the entry.
topologicalFinalSort(SimpleArray<BasicBlock * > & Blocks,int ID)191*67e74705SXin Li int BasicBlock::topologicalFinalSort(SimpleArray<BasicBlock*>& Blocks, int ID) {
192*67e74705SXin Li   // Visited is assumed to have been set by the topologicalSort.  This pass
193*67e74705SXin Li   // assumes !Visited means that we've visited this node before.
194*67e74705SXin Li   if (!Visited) return ID;
195*67e74705SXin Li   Visited = false;
196*67e74705SXin Li   if (DominatorNode.Parent)
197*67e74705SXin Li     ID = DominatorNode.Parent->topologicalFinalSort(Blocks, ID);
198*67e74705SXin Li   for (auto *Pred : Predecessors)
199*67e74705SXin Li     ID = Pred->topologicalFinalSort(Blocks, ID);
200*67e74705SXin Li   assert(static_cast<size_t>(ID) < Blocks.size());
201*67e74705SXin Li   BlockID = ID++;
202*67e74705SXin Li   Blocks[BlockID] = this;
203*67e74705SXin Li   return ID;
204*67e74705SXin Li }
205*67e74705SXin Li 
206*67e74705SXin Li // Computes the immediate dominator of the current block.  Assumes that all of
207*67e74705SXin Li // its predecessors have already computed their dominators.  This is achieved
208*67e74705SXin Li // by visiting the nodes in topological order.
computeDominator()209*67e74705SXin Li void BasicBlock::computeDominator() {
210*67e74705SXin Li   BasicBlock *Candidate = nullptr;
211*67e74705SXin Li   // Walk backwards from each predecessor to find the common dominator node.
212*67e74705SXin Li   for (auto *Pred : Predecessors) {
213*67e74705SXin Li     // Skip back-edges
214*67e74705SXin Li     if (Pred->BlockID >= BlockID) continue;
215*67e74705SXin Li     // If we don't yet have a candidate for dominator yet, take this one.
216*67e74705SXin Li     if (Candidate == nullptr) {
217*67e74705SXin Li       Candidate = Pred;
218*67e74705SXin Li       continue;
219*67e74705SXin Li     }
220*67e74705SXin Li     // Walk the alternate and current candidate back to find a common ancestor.
221*67e74705SXin Li     auto *Alternate = Pred;
222*67e74705SXin Li     while (Alternate != Candidate) {
223*67e74705SXin Li       if (Candidate->BlockID > Alternate->BlockID)
224*67e74705SXin Li         Candidate = Candidate->DominatorNode.Parent;
225*67e74705SXin Li       else
226*67e74705SXin Li         Alternate = Alternate->DominatorNode.Parent;
227*67e74705SXin Li     }
228*67e74705SXin Li   }
229*67e74705SXin Li   DominatorNode.Parent = Candidate;
230*67e74705SXin Li   DominatorNode.SizeOfSubTree = 1;
231*67e74705SXin Li }
232*67e74705SXin Li 
233*67e74705SXin Li // Computes the immediate post-dominator of the current block.  Assumes that all
234*67e74705SXin Li // of its successors have already computed their post-dominators.  This is
235*67e74705SXin Li // achieved visiting the nodes in reverse topological order.
computePostDominator()236*67e74705SXin Li void BasicBlock::computePostDominator() {
237*67e74705SXin Li   BasicBlock *Candidate = nullptr;
238*67e74705SXin Li   // Walk back from each predecessor to find the common post-dominator node.
239*67e74705SXin Li   for (auto *Succ : successors()) {
240*67e74705SXin Li     // Skip back-edges
241*67e74705SXin Li     if (Succ->BlockID <= BlockID) continue;
242*67e74705SXin Li     // If we don't yet have a candidate for post-dominator yet, take this one.
243*67e74705SXin Li     if (Candidate == nullptr) {
244*67e74705SXin Li       Candidate = Succ;
245*67e74705SXin Li       continue;
246*67e74705SXin Li     }
247*67e74705SXin Li     // Walk the alternate and current candidate back to find a common ancestor.
248*67e74705SXin Li     auto *Alternate = Succ;
249*67e74705SXin Li     while (Alternate != Candidate) {
250*67e74705SXin Li       if (Candidate->BlockID < Alternate->BlockID)
251*67e74705SXin Li         Candidate = Candidate->PostDominatorNode.Parent;
252*67e74705SXin Li       else
253*67e74705SXin Li         Alternate = Alternate->PostDominatorNode.Parent;
254*67e74705SXin Li     }
255*67e74705SXin Li   }
256*67e74705SXin Li   PostDominatorNode.Parent = Candidate;
257*67e74705SXin Li   PostDominatorNode.SizeOfSubTree = 1;
258*67e74705SXin Li }
259*67e74705SXin Li 
260*67e74705SXin Li 
261*67e74705SXin Li // Renumber instructions in all blocks
renumberInstrs()262*67e74705SXin Li void SCFG::renumberInstrs() {
263*67e74705SXin Li   int InstrID = 0;
264*67e74705SXin Li   for (auto *Block : Blocks)
265*67e74705SXin Li     InstrID = Block->renumberInstrs(InstrID);
266*67e74705SXin Li }
267*67e74705SXin Li 
268*67e74705SXin Li 
computeNodeSize(BasicBlock * B,BasicBlock::TopologyNode BasicBlock::* TN)269*67e74705SXin Li static inline void computeNodeSize(BasicBlock *B,
270*67e74705SXin Li                                    BasicBlock::TopologyNode BasicBlock::*TN) {
271*67e74705SXin Li   BasicBlock::TopologyNode *N = &(B->*TN);
272*67e74705SXin Li   if (N->Parent) {
273*67e74705SXin Li     BasicBlock::TopologyNode *P = &(N->Parent->*TN);
274*67e74705SXin Li     // Initially set ID relative to the (as yet uncomputed) parent ID
275*67e74705SXin Li     N->NodeID = P->SizeOfSubTree;
276*67e74705SXin Li     P->SizeOfSubTree += N->SizeOfSubTree;
277*67e74705SXin Li   }
278*67e74705SXin Li }
279*67e74705SXin Li 
computeNodeID(BasicBlock * B,BasicBlock::TopologyNode BasicBlock::* TN)280*67e74705SXin Li static inline void computeNodeID(BasicBlock *B,
281*67e74705SXin Li                                  BasicBlock::TopologyNode BasicBlock::*TN) {
282*67e74705SXin Li   BasicBlock::TopologyNode *N = &(B->*TN);
283*67e74705SXin Li   if (N->Parent) {
284*67e74705SXin Li     BasicBlock::TopologyNode *P = &(N->Parent->*TN);
285*67e74705SXin Li     N->NodeID += P->NodeID;    // Fix NodeIDs relative to starting node.
286*67e74705SXin Li   }
287*67e74705SXin Li }
288*67e74705SXin Li 
289*67e74705SXin Li 
290*67e74705SXin Li // Normalizes a CFG.  Normalization has a few major components:
291*67e74705SXin Li // 1) Removing unreachable blocks.
292*67e74705SXin Li // 2) Computing dominators and post-dominators
293*67e74705SXin Li // 3) Topologically sorting the blocks into the "Blocks" array.
computeNormalForm()294*67e74705SXin Li void SCFG::computeNormalForm() {
295*67e74705SXin Li   // Topologically sort the blocks starting from the entry block.
296*67e74705SXin Li   int NumUnreachableBlocks = Entry->topologicalSort(Blocks, Blocks.size());
297*67e74705SXin Li   if (NumUnreachableBlocks > 0) {
298*67e74705SXin Li     // If there were unreachable blocks shift everything down, and delete them.
299*67e74705SXin Li     for (size_t I = NumUnreachableBlocks, E = Blocks.size(); I < E; ++I) {
300*67e74705SXin Li       size_t NI = I - NumUnreachableBlocks;
301*67e74705SXin Li       Blocks[NI] = Blocks[I];
302*67e74705SXin Li       Blocks[NI]->BlockID = NI;
303*67e74705SXin Li       // FIXME: clean up predecessor pointers to unreachable blocks?
304*67e74705SXin Li     }
305*67e74705SXin Li     Blocks.drop(NumUnreachableBlocks);
306*67e74705SXin Li   }
307*67e74705SXin Li 
308*67e74705SXin Li   // Compute dominators.
309*67e74705SXin Li   for (auto *Block : Blocks)
310*67e74705SXin Li     Block->computeDominator();
311*67e74705SXin Li 
312*67e74705SXin Li   // Once dominators have been computed, the final sort may be performed.
313*67e74705SXin Li   int NumBlocks = Exit->topologicalFinalSort(Blocks, 0);
314*67e74705SXin Li   assert(static_cast<size_t>(NumBlocks) == Blocks.size());
315*67e74705SXin Li   (void) NumBlocks;
316*67e74705SXin Li 
317*67e74705SXin Li   // Renumber the instructions now that we have a final sort.
318*67e74705SXin Li   renumberInstrs();
319*67e74705SXin Li 
320*67e74705SXin Li   // Compute post-dominators and compute the sizes of each node in the
321*67e74705SXin Li   // dominator tree.
322*67e74705SXin Li   for (auto *Block : Blocks.reverse()) {
323*67e74705SXin Li     Block->computePostDominator();
324*67e74705SXin Li     computeNodeSize(Block, &BasicBlock::DominatorNode);
325*67e74705SXin Li   }
326*67e74705SXin Li   // Compute the sizes of each node in the post-dominator tree and assign IDs in
327*67e74705SXin Li   // the dominator tree.
328*67e74705SXin Li   for (auto *Block : Blocks) {
329*67e74705SXin Li     computeNodeID(Block, &BasicBlock::DominatorNode);
330*67e74705SXin Li     computeNodeSize(Block, &BasicBlock::PostDominatorNode);
331*67e74705SXin Li   }
332*67e74705SXin Li   // Assign IDs in the post-dominator tree.
333*67e74705SXin Li   for (auto *Block : Blocks.reverse()) {
334*67e74705SXin Li     computeNodeID(Block, &BasicBlock::PostDominatorNode);
335*67e74705SXin Li   }
336*67e74705SXin Li }
337