clang API Documentation
00001 //===- ThreadSafetyTIL.cpp -------------------------------------*- C++ --*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT in the llvm repository for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 00010 #include "clang/Analysis/Analyses/ThreadSafetyTIL.h" 00011 #include "clang/Analysis/Analyses/ThreadSafetyTraverse.h" 00012 00013 namespace clang { 00014 namespace threadSafety { 00015 namespace til { 00016 00017 00018 StringRef getUnaryOpcodeString(TIL_UnaryOpcode Op) { 00019 switch (Op) { 00020 case UOP_Minus: return "-"; 00021 case UOP_BitNot: return "~"; 00022 case UOP_LogicNot: return "!"; 00023 } 00024 return ""; 00025 } 00026 00027 00028 StringRef getBinaryOpcodeString(TIL_BinaryOpcode Op) { 00029 switch (Op) { 00030 case BOP_Mul: return "*"; 00031 case BOP_Div: return "/"; 00032 case BOP_Rem: return "%"; 00033 case BOP_Add: return "+"; 00034 case BOP_Sub: return "-"; 00035 case BOP_Shl: return "<<"; 00036 case BOP_Shr: return ">>"; 00037 case BOP_BitAnd: return "&"; 00038 case BOP_BitXor: return "^"; 00039 case BOP_BitOr: return "|"; 00040 case BOP_Eq: return "=="; 00041 case BOP_Neq: return "!="; 00042 case BOP_Lt: return "<"; 00043 case BOP_Leq: return "<="; 00044 case BOP_LogicAnd: return "&&"; 00045 case BOP_LogicOr: return "||"; 00046 } 00047 return ""; 00048 } 00049 00050 00051 SExpr* Future::force() { 00052 Status = FS_evaluating; 00053 Result = compute(); 00054 Status = FS_done; 00055 return Result; 00056 } 00057 00058 00059 unsigned BasicBlock::addPredecessor(BasicBlock *Pred) { 00060 unsigned Idx = Predecessors.size(); 00061 Predecessors.reserveCheck(1, Arena); 00062 Predecessors.push_back(Pred); 00063 for (SExpr *E : Args) { 00064 if (Phi* Ph = dyn_cast<Phi>(E)) { 00065 Ph->values().reserveCheck(1, Arena); 00066 Ph->values().push_back(nullptr); 00067 } 00068 } 00069 return Idx; 00070 } 00071 00072 00073 void BasicBlock::reservePredecessors(unsigned NumPreds) { 00074 Predecessors.reserve(NumPreds, Arena); 00075 for (SExpr *E : Args) { 00076 if (Phi* Ph = dyn_cast<Phi>(E)) { 00077 Ph->values().reserve(NumPreds, Arena); 00078 } 00079 } 00080 } 00081 00082 00083 // If E is a variable, then trace back through any aliases or redundant 00084 // Phi nodes to find the canonical definition. 00085 const SExpr *getCanonicalVal(const SExpr *E) { 00086 while (true) { 00087 if (auto *V = dyn_cast<Variable>(E)) { 00088 if (V->kind() == Variable::VK_Let) { 00089 E = V->definition(); 00090 continue; 00091 } 00092 } 00093 if (const Phi *Ph = dyn_cast<Phi>(E)) { 00094 if (Ph->status() == Phi::PH_SingleVal) { 00095 E = Ph->values()[0]; 00096 continue; 00097 } 00098 } 00099 break; 00100 } 00101 return E; 00102 } 00103 00104 00105 // If E is a variable, then trace back through any aliases or redundant 00106 // Phi nodes to find the canonical definition. 00107 // The non-const version will simplify incomplete Phi nodes. 00108 SExpr *simplifyToCanonicalVal(SExpr *E) { 00109 while (true) { 00110 if (auto *V = dyn_cast<Variable>(E)) { 00111 if (V->kind() != Variable::VK_Let) 00112 return V; 00113 // Eliminate redundant variables, e.g. x = y, or x = 5, 00114 // but keep anything more complicated. 00115 if (til::ThreadSafetyTIL::isTrivial(V->definition())) { 00116 E = V->definition(); 00117 continue; 00118 } 00119 return V; 00120 } 00121 if (auto *Ph = dyn_cast<Phi>(E)) { 00122 if (Ph->status() == Phi::PH_Incomplete) 00123 simplifyIncompleteArg(Ph); 00124 // Eliminate redundant Phi nodes. 00125 if (Ph->status() == Phi::PH_SingleVal) { 00126 E = Ph->values()[0]; 00127 continue; 00128 } 00129 } 00130 return E; 00131 } 00132 } 00133 00134 00135 // Trace the arguments of an incomplete Phi node to see if they have the same 00136 // canonical definition. If so, mark the Phi node as redundant. 00137 // getCanonicalVal() will recursively call simplifyIncompletePhi(). 00138 void simplifyIncompleteArg(til::Phi *Ph) { 00139 assert(Ph && Ph->status() == Phi::PH_Incomplete); 00140 00141 // eliminate infinite recursion -- assume that this node is not redundant. 00142 Ph->setStatus(Phi::PH_MultiVal); 00143 00144 SExpr *E0 = simplifyToCanonicalVal(Ph->values()[0]); 00145 for (unsigned i=1, n=Ph->values().size(); i<n; ++i) { 00146 SExpr *Ei = simplifyToCanonicalVal(Ph->values()[i]); 00147 if (Ei == Ph) 00148 continue; // Recursive reference to itself. Don't count. 00149 if (Ei != E0) { 00150 return; // Status is already set to MultiVal. 00151 } 00152 } 00153 Ph->setStatus(Phi::PH_SingleVal); 00154 } 00155 00156 00157 // Renumbers the arguments and instructions to have unique, sequential IDs. 00158 int BasicBlock::renumberInstrs(int ID) { 00159 for (auto *Arg : Args) 00160 Arg->setID(this, ID++); 00161 for (auto *Instr : Instrs) 00162 Instr->setID(this, ID++); 00163 TermInstr->setID(this, ID++); 00164 return ID; 00165 } 00166 00167 // Sorts the CFGs blocks using a reverse post-order depth-first traversal. 00168 // Each block will be written into the Blocks array in order, and its BlockID 00169 // will be set to the index in the array. Sorting should start from the entry 00170 // block, and ID should be the total number of blocks. 00171 int BasicBlock::topologicalSort(SimpleArray<BasicBlock*>& Blocks, int ID) { 00172 if (Visited) return ID; 00173 Visited = true; 00174 for (auto *Block : successors()) 00175 ID = Block->topologicalSort(Blocks, ID); 00176 // set ID and update block array in place. 00177 // We may lose pointers to unreachable blocks. 00178 assert(ID > 0); 00179 BlockID = --ID; 00180 Blocks[BlockID] = this; 00181 return ID; 00182 } 00183 00184 // Performs a reverse topological traversal, starting from the exit block and 00185 // following back-edges. The dominator is serialized before any predecessors, 00186 // which guarantees that all blocks are serialized after their dominator and 00187 // before their post-dominator (because it's a reverse topological traversal). 00188 // ID should be initially set to 0. 00189 // 00190 // This sort assumes that (1) dominators have been computed, (2) there are no 00191 // critical edges, and (3) the entry block is reachable from the exit block 00192 // and no blocks are accessable via traversal of back-edges from the exit that 00193 // weren't accessable via forward edges from the entry. 00194 int BasicBlock::topologicalFinalSort(SimpleArray<BasicBlock*>& Blocks, int ID) { 00195 // Visited is assumed to have been set by the topologicalSort. This pass 00196 // assumes !Visited means that we've visited this node before. 00197 if (!Visited) return ID; 00198 Visited = false; 00199 if (DominatorNode.Parent) 00200 ID = DominatorNode.Parent->topologicalFinalSort(Blocks, ID); 00201 for (auto *Pred : Predecessors) 00202 ID = Pred->topologicalFinalSort(Blocks, ID); 00203 assert(static_cast<size_t>(ID) < Blocks.size()); 00204 BlockID = ID++; 00205 Blocks[BlockID] = this; 00206 return ID; 00207 } 00208 00209 // Computes the immediate dominator of the current block. Assumes that all of 00210 // its predecessors have already computed their dominators. This is achieved 00211 // by visiting the nodes in topological order. 00212 void BasicBlock::computeDominator() { 00213 BasicBlock *Candidate = nullptr; 00214 // Walk backwards from each predecessor to find the common dominator node. 00215 for (auto *Pred : Predecessors) { 00216 // Skip back-edges 00217 if (Pred->BlockID >= BlockID) continue; 00218 // If we don't yet have a candidate for dominator yet, take this one. 00219 if (Candidate == nullptr) { 00220 Candidate = Pred; 00221 continue; 00222 } 00223 // Walk the alternate and current candidate back to find a common ancestor. 00224 auto *Alternate = Pred; 00225 while (Alternate != Candidate) { 00226 if (Candidate->BlockID > Alternate->BlockID) 00227 Candidate = Candidate->DominatorNode.Parent; 00228 else 00229 Alternate = Alternate->DominatorNode.Parent; 00230 } 00231 } 00232 DominatorNode.Parent = Candidate; 00233 DominatorNode.SizeOfSubTree = 1; 00234 } 00235 00236 // Computes the immediate post-dominator of the current block. Assumes that all 00237 // of its successors have already computed their post-dominators. This is 00238 // achieved visiting the nodes in reverse topological order. 00239 void BasicBlock::computePostDominator() { 00240 BasicBlock *Candidate = nullptr; 00241 // Walk back from each predecessor to find the common post-dominator node. 00242 for (auto *Succ : successors()) { 00243 // Skip back-edges 00244 if (Succ->BlockID <= BlockID) continue; 00245 // If we don't yet have a candidate for post-dominator yet, take this one. 00246 if (Candidate == nullptr) { 00247 Candidate = Succ; 00248 continue; 00249 } 00250 // Walk the alternate and current candidate back to find a common ancestor. 00251 auto *Alternate = Succ; 00252 while (Alternate != Candidate) { 00253 if (Candidate->BlockID < Alternate->BlockID) 00254 Candidate = Candidate->PostDominatorNode.Parent; 00255 else 00256 Alternate = Alternate->PostDominatorNode.Parent; 00257 } 00258 } 00259 PostDominatorNode.Parent = Candidate; 00260 PostDominatorNode.SizeOfSubTree = 1; 00261 } 00262 00263 00264 // Renumber instructions in all blocks 00265 void SCFG::renumberInstrs() { 00266 int InstrID = 0; 00267 for (auto *Block : Blocks) 00268 InstrID = Block->renumberInstrs(InstrID); 00269 } 00270 00271 00272 static inline void computeNodeSize(BasicBlock *B, 00273 BasicBlock::TopologyNode BasicBlock::*TN) { 00274 BasicBlock::TopologyNode *N = &(B->*TN); 00275 if (N->Parent) { 00276 BasicBlock::TopologyNode *P = &(N->Parent->*TN); 00277 // Initially set ID relative to the (as yet uncomputed) parent ID 00278 N->NodeID = P->SizeOfSubTree; 00279 P->SizeOfSubTree += N->SizeOfSubTree; 00280 } 00281 } 00282 00283 static inline void computeNodeID(BasicBlock *B, 00284 BasicBlock::TopologyNode BasicBlock::*TN) { 00285 BasicBlock::TopologyNode *N = &(B->*TN); 00286 if (N->Parent) { 00287 BasicBlock::TopologyNode *P = &(N->Parent->*TN); 00288 N->NodeID += P->NodeID; // Fix NodeIDs relative to starting node. 00289 } 00290 } 00291 00292 00293 // Normalizes a CFG. Normalization has a few major components: 00294 // 1) Removing unreachable blocks. 00295 // 2) Computing dominators and post-dominators 00296 // 3) Topologically sorting the blocks into the "Blocks" array. 00297 void SCFG::computeNormalForm() { 00298 // Topologically sort the blocks starting from the entry block. 00299 int NumUnreachableBlocks = Entry->topologicalSort(Blocks, Blocks.size()); 00300 if (NumUnreachableBlocks > 0) { 00301 // If there were unreachable blocks shift everything down, and delete them. 00302 for (size_t I = NumUnreachableBlocks, E = Blocks.size(); I < E; ++I) { 00303 size_t NI = I - NumUnreachableBlocks; 00304 Blocks[NI] = Blocks[I]; 00305 Blocks[NI]->BlockID = NI; 00306 // FIXME: clean up predecessor pointers to unreachable blocks? 00307 } 00308 Blocks.drop(NumUnreachableBlocks); 00309 } 00310 00311 // Compute dominators. 00312 for (auto *Block : Blocks) 00313 Block->computeDominator(); 00314 00315 // Once dominators have been computed, the final sort may be performed. 00316 int NumBlocks = Exit->topologicalFinalSort(Blocks, 0); 00317 assert(static_cast<size_t>(NumBlocks) == Blocks.size()); 00318 (void) NumBlocks; 00319 00320 // Renumber the instructions now that we have a final sort. 00321 renumberInstrs(); 00322 00323 // Compute post-dominators and compute the sizes of each node in the 00324 // dominator tree. 00325 for (auto *Block : Blocks.reverse()) { 00326 Block->computePostDominator(); 00327 computeNodeSize(Block, &BasicBlock::DominatorNode); 00328 } 00329 // Compute the sizes of each node in the post-dominator tree and assign IDs in 00330 // the dominator tree. 00331 for (auto *Block : Blocks) { 00332 computeNodeID(Block, &BasicBlock::DominatorNode); 00333 computeNodeSize(Block, &BasicBlock::PostDominatorNode); 00334 } 00335 // Assign IDs in the post-dominator tree. 00336 for (auto *Block : Blocks.reverse()) { 00337 computeNodeID(Block, &BasicBlock::PostDominatorNode); 00338 } 00339 } 00340 00341 } // end namespace til 00342 } // end namespace threadSafety 00343 } // end namespace clang