clang API Documentation

ThreadSafetyTIL.cpp
Go to the documentation of this file.
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