Thread Safety Analysis:  Update SSA pass to handle loops.

llvm-svn: 206676
diff --git a/clang/lib/Analysis/ThreadSafetyCommon.cpp b/clang/lib/Analysis/ThreadSafetyCommon.cpp
index 02c9e8d..6545bb1 100644
--- a/clang/lib/Analysis/ThreadSafetyCommon.cpp
+++ b/clang/lib/Analysis/ThreadSafetyCommon.cpp
@@ -46,10 +46,6 @@
   return nullptr;
 }
 
-void SExprBuilder::insertStmt(const Stmt *S, til::Variable *V) {
-  SMap.insert(std::make_pair(S, V));
-}
-
 
 til::SCFG *SExprBuilder::buildCFG(CFGWalker &Walker) {
   Walker.walk(*this);
@@ -354,6 +350,7 @@
 }
 
 
+
 // If (E) is non-trivial, then add it to the current basic block, and
 // update the statement map so that S refers to E.  Returns a new variable
 // that refers to E.
@@ -366,8 +363,7 @@
     return E;
 
   til::Variable *V = new (Arena) til::Variable(E, VD);
-  V->setID(CurrentBlockID, CurrentVarID++);
-  CurrentBB->addInstr(V);
+  CurrentInstructions.push_back(V);
   if (S)
     insertStmt(S, V);
   return V;
@@ -376,9 +372,11 @@
 
 // Returns the current value of VD, if known, and nullptr otherwise.
 til::SExpr *SExprBuilder::lookupVarDecl(const ValueDecl *VD) {
-  auto It = IdxMap.find(VD);
-  if (It != IdxMap.end())
-    return CurrentNameMap[It->second].second;
+  auto It = LVarIdxMap.find(VD);
+  if (It != LVarIdxMap.end()) {
+    assert(CurrentLVarMap[It->second].first == VD);
+    return CurrentLVarMap[It->second].second;
+  }
   return nullptr;
 }
 
@@ -396,9 +394,9 @@
 // Adds a new variable declaration.
 til::SExpr *SExprBuilder::addVarDecl(const ValueDecl *VD, til::SExpr *E) {
   maybeUpdateVD(E, VD);
-  IdxMap.insert(std::make_pair(VD, CurrentNameMap.size()));
-  CurrentNameMap.makeWritable();
-  CurrentNameMap.push_back(std::make_pair(VD, E));
+  LVarIdxMap.insert(std::make_pair(VD, CurrentLVarMap.size()));
+  CurrentLVarMap.makeWritable();
+  CurrentLVarMap.push_back(std::make_pair(VD, E));
   return E;
 }
 
@@ -406,76 +404,151 @@
 // Updates a current variable declaration.  (E.g. by assignment)
 til::SExpr *SExprBuilder::updateVarDecl(const ValueDecl *VD, til::SExpr *E) {
   maybeUpdateVD(E, VD);
-  auto It = IdxMap.find(VD);
-  if (It == IdxMap.end()) {
+  auto It = LVarIdxMap.find(VD);
+  if (It == LVarIdxMap.end()) {
     til::SExpr *Ptr = new (Arena) til::LiteralPtr(VD);
     til::SExpr *St  = new (Arena) til::Store(Ptr, E);
     return St;
   }
-  CurrentNameMap.makeWritable();
-  CurrentNameMap.elem(It->second).second = E;
+  CurrentLVarMap.makeWritable();
+  CurrentLVarMap.elem(It->second).second = E;
   return E;
 }
 
 
-// Merge values from Map into the current entry map.
-void SExprBuilder::mergeEntryMap(NameVarMap Map) {
-  assert(CurrentBlockInfo && "Not processing a block!");
+// Return true if the given expression represents a possibly unnecessary
+// variable: i.e. a variable that references a Phi node that may be removed.
+inline bool isIncompleteVar(til::SExpr *E) {
+  if (!E)
+    return true;  // Null values are used on unknown backedges.
+  if (til::Variable *V = dyn_cast<til::Variable>(E)) {
+    if (til::Phi *Ph = dyn_cast<til::Phi>(V->definition()))
+      return Ph->incomplete();
+  }
+  return false;
+}
 
-  if (!CurrentNameMap.valid()) {
-    // Steal Map, using copy-on-write.
-    CurrentNameMap = std::move(Map);
+
+// Make a Phi node in the current block for the i^th variable in CurrentVarMap.
+// If E != null, sets Phi[CurrentBlockInfo->ArgIndex] = E.
+// If E == null, this is a backedge and will be set later.
+void SExprBuilder::makePhiNodeVar(unsigned i, unsigned NPreds, til::SExpr *E) {
+  unsigned ArgIndex = CurrentBlockInfo->ProcessedPredecessors;
+  assert(ArgIndex > 0 && ArgIndex < NPreds);
+
+  til::Variable *V = dyn_cast<til::Variable>(CurrentLVarMap[i].second);
+  if (V && V->getBlockID() == CurrentBB->blockID()) {
+    // We already have a Phi node in the current block,
+    // so just add the new variable to the Phi node.
+    til::Phi *Ph = dyn_cast<til::Phi>(V->definition());
+    assert(Ph && "Expecting Phi node.");
+    if (E)
+      Ph->values()[ArgIndex] = E;
+    if (!Ph->incomplete() && isIncompleteVar(E))
+      Ph->setIncomplete(true);
     return;
   }
-  if (CurrentNameMap.sameAs(Map))
+
+  // Make a new phi node: phi(..., E)
+  // All phi args up to the current index are set to the current value.
+  til::Phi *Ph = new (Arena) til::Phi(Arena, NPreds);
+  Ph->values().setValues(NPreds, nullptr);
+  for (unsigned PIdx = 0; PIdx < ArgIndex; ++PIdx)
+    Ph->values()[PIdx] = CurrentLVarMap[i].second;
+  if (E)
+    Ph->values()[ArgIndex] = E;
+  if (isIncompleteVar(E))
+    Ph->setIncomplete(true);
+
+  // Add Phi node to current block, and update CurrentLVarMap[i]
+  auto *Var = new (Arena) til::Variable(Ph, CurrentLVarMap[i].first);
+  CurrentArguments.push_back(Var);
+
+  CurrentLVarMap.makeWritable();
+  CurrentLVarMap.elem(i).second = Var;
+}
+
+
+// Merge values from Map into the current variable map.
+// This will construct Phi nodes in the current basic block as necessary.
+void SExprBuilder::mergeEntryMap(LVarDefinitionMap Map) {
+  assert(CurrentBlockInfo && "Not processing a block!");
+
+  if (!CurrentLVarMap.valid()) {
+    // Steal Map, using copy-on-write.
+    CurrentLVarMap = std::move(Map);
+    return;
+  }
+  if (CurrentLVarMap.sameAs(Map))
     return;  // Easy merge: maps from different predecessors are unchanged.
 
-  unsigned ESz = CurrentNameMap.size();
+  unsigned NPreds = CurrentBB->numPredecessors();
+  unsigned ESz = CurrentLVarMap.size();
   unsigned MSz = Map.size();
-  unsigned Sz = std::max(ESz, MSz);
-  bool W = CurrentNameMap.writable();
+  unsigned Sz  = std::min(ESz, MSz);
+
   for (unsigned i=0; i<Sz; ++i) {
-    if (CurrentNameMap[i].first != Map[i].first) {
-      if (!W)
-        CurrentNameMap.makeWritable();
-      CurrentNameMap.downsize(i);
+    if (CurrentLVarMap[i].first != Map[i].first) {
+      // We've reached the end of variables in common.
+      CurrentLVarMap.makeWritable();
+      CurrentLVarMap.downsize(i);
       break;
     }
-    if (CurrentNameMap[i].second != Map[i].second) {
-      til::Variable *V =
-        dyn_cast<til::Variable>(CurrentNameMap[i].second);
-      if (V && V->getBlockID() == CurrentBB->blockID()) {
-        // We already have a Phi node, so add the new variable.
-        til::Phi *Ph = dyn_cast<til::Phi>(V->definition());
-        assert(Ph && "Expecting Phi node.");
-        Ph->values()[CurrentArgIndex] = Map[i].second;
-      }
-      else {
-        if (!W)
-          CurrentNameMap.makeWritable();
-        unsigned NPreds = CurrentBB->numPredecessors();
-        assert(CurrentArgIndex > 0 && CurrentArgIndex < NPreds);
-
-        // Make a new phi node.  All phi args up to the current index must
-        // be the same, and equal to the current NameMap value.
-        auto *Ph = new (Arena) til::Phi(Arena, NPreds);
-        Ph->values().setValues(NPreds, nullptr);
-        for (unsigned PIdx = 0; PIdx < CurrentArgIndex; ++PIdx)
-          Ph->values()[PIdx] = CurrentNameMap[i].second;
-        Ph->values()[CurrentArgIndex] = Map[i].second;
-
-        // Add phi node to current basic block.
-        auto *Var = new (Arena) til::Variable(Ph, CurrentNameMap[i].first);
-        Var->setID(CurrentBlockID, CurrentVarID++);
-        CurrentBB->addArgument(Var);
-        CurrentNameMap.elem(i).second = Var;
-      }
-    }
+    if (CurrentLVarMap[i].second != Map[i].second)
+      makePhiNodeVar(i, NPreds, Map[i].second);
   }
   if (ESz > MSz) {
-    if (!W)
-      CurrentNameMap.makeWritable();
-    CurrentNameMap.downsize(Map.size());
+    CurrentLVarMap.makeWritable();
+    CurrentLVarMap.downsize(Map.size());
+  }
+}
+
+
+// Merge a back edge into the current variable map.
+// This will create phi nodes for all variables in the variable map.
+void SExprBuilder::mergeEntryMapBackEdge() {
+  // We don't have definitions for variables on the backedge, because we
+  // haven't gotten that far in the CFG.  Thus, when encountering a back edge,
+  // we conservatively create Phi nodes for all variables.  Unnecessary Phi
+  // nodes will be marked as incomplete, and stripped out at the end.
+  //
+  // An Phi node is unnecessary if it only refers to itself and one other
+  // variable, e.g. x = Phi(y, y, x)  can be reduced to x = y.
+
+  assert(CurrentBlockInfo && "Not processing a block!");
+
+  if (CurrentBlockInfo->HasBackEdges)
+    return;
+  CurrentBlockInfo->HasBackEdges = true;
+
+  CurrentLVarMap.makeWritable();
+  unsigned Sz = CurrentLVarMap.size();
+  unsigned NPreds = CurrentBB->numPredecessors();
+
+  for (unsigned i=0; i < Sz; ++i) {
+    makePhiNodeVar(i, NPreds, nullptr);
+  }
+}
+
+
+// Update the phi nodes that were initially created for a back edge
+// once the variable definitions have been computed.
+// I.e., merge the current variable map into the phi nodes for Blk.
+void SExprBuilder::mergePhiNodesBackEdge(const CFGBlock *Blk) {
+  til::BasicBlock *BB = lookupBlock(Blk);
+  unsigned ArgIndex = BBInfo[Blk->getBlockID()].ProcessedPredecessors;
+  assert(ArgIndex > 0 && ArgIndex < BB->numPredecessors());
+
+  for (til::Variable *V : BB->arguments()) {
+    til::Phi *Ph = dyn_cast_or_null<til::Phi>(V->definition());
+    assert(Ph && "Expecting Phi Node.");
+    assert(Ph->values()[ArgIndex] == nullptr && "Wrong index for back edge.");
+    assert(V->clangDecl() && "No local variable for Phi node.");
+
+    til::SExpr *E = lookupVarDecl(V->clangDecl());
+    assert(E && "Couldn't find local variable for Phi node.");
+
+    Ph->values()[ArgIndex] = E;
   }
 }
 
@@ -488,53 +561,60 @@
   Scfg = new (Arena) til::SCFG(Arena, NBlocks);
 
   // allocate all basic blocks immediately, to handle forward references.
-  BlockMap.reserve(NBlocks);
   BBInfo.resize(NBlocks);
+  BlockMap.resize(NBlocks, nullptr);
+  // create map from clang blockID to til::BasicBlocks
   for (auto *B : *Cfg) {
     auto *BB = new (Arena) til::BasicBlock(Arena, 0, B->size());
-    BlockMap.push_back(BB);
+    BlockMap[B->getBlockID()] = BB;
   }
   CallCtx = new SExprBuilder::CallingContext(D);
 }
 
 
-
 void SExprBuilder::enterCFGBlock(const CFGBlock *B) {
   // Intialize TIL basic block and add it to the CFG.
   CurrentBB = BlockMap[B->getBlockID()];
-  CurrentBB->setBlockID(CurrentBlockID);
   CurrentBB->setNumPredecessors(B->pred_size());
   Scfg->add(CurrentBB);
 
   CurrentBlockInfo = &BBInfo[B->getBlockID()];
-  CurrentVarID = 0;
-  CurrentArgIndex = 0;
+  CurrentArguments.clear();
+  CurrentInstructions.clear();
 
-  assert(!CurrentNameMap.valid() && "CurrentNameMap already initialized.");
+  // CurrentLVarMap is moved to ExitMap on block exit.
+  assert(!CurrentLVarMap.valid() && "CurrentLVarMap already initialized.");
 }
 
 
 void SExprBuilder::handlePredecessor(const CFGBlock *Pred) {
-  // Compute CurrentNameMap on entry from ExitMaps of predecessors
+  // Compute CurrentLVarMap on entry from ExitMaps of predecessors
 
   BlockInfo *PredInfo = &BBInfo[Pred->getBlockID()];
-  assert(PredInfo->SuccessorsToProcess > 0);
+  assert(PredInfo->UnprocessedSuccessors > 0);
 
-  if (--PredInfo->SuccessorsToProcess == 0)
+  if (--PredInfo->UnprocessedSuccessors == 0)
     mergeEntryMap(std::move(PredInfo->ExitMap));
   else
     mergeEntryMap(PredInfo->ExitMap.clone());
 
-  ++CurrentArgIndex;
+  ++CurrentBlockInfo->ProcessedPredecessors;
 }
 
 
 void SExprBuilder::handlePredecessorBackEdge(const CFGBlock *Pred) {
-  CurrentBlockInfo->HasBackEdges = true;
+  mergeEntryMapBackEdge();
 }
 
 
-void SExprBuilder::enterCFGBlockBody(const CFGBlock *B) { }
+void SExprBuilder::enterCFGBlockBody(const CFGBlock *B) {
+  // The merge*() methods have created arguments.
+  // Push those arguments onto the basic block.
+  CurrentBB->arguments().reserve(
+    static_cast<unsigned>(CurrentArguments.size()), Arena);
+  for (auto *V : CurrentArguments)
+    CurrentBB->addArgument(V);
+}
 
 
 void SExprBuilder::handleStatement(const Stmt *S) {
@@ -555,19 +635,25 @@
 
 
 void SExprBuilder::exitCFGBlockBody(const CFGBlock *B) {
+  CurrentBB->instructions().reserve(
+    static_cast<unsigned>(CurrentInstructions.size()), Arena);
+  for (auto *V : CurrentInstructions)
+    CurrentBB->addInstruction(V);
+
+  // Create an appropriate terminator
   unsigned N = B->succ_size();
   auto It = B->succ_begin();
   if (N == 1) {
-    til::BasicBlock *BB = *It ? BlockMap[(*It)->getBlockID()] : nullptr;
+    til::BasicBlock *BB = *It ? lookupBlock(*It) : nullptr;
     // TODO: set index
     til::SExpr *Tm = new (Arena) til::Goto(BB, 0);
     CurrentBB->setTerminator(Tm);
   }
   else if (N == 2) {
     til::SExpr *C = translate(B->getTerminatorCondition(true), CallCtx);
-    til::BasicBlock *BB1 = *It ? BlockMap[(*It)->getBlockID()] : nullptr;
+    til::BasicBlock *BB1 = *It ? lookupBlock(*It) : nullptr;
     ++It;
-    til::BasicBlock *BB2 = *It ? BlockMap[(*It)->getBlockID()] : nullptr;
+    til::BasicBlock *BB2 = *It ? lookupBlock(*It) : nullptr;
     // TODO: set conditional, set index
     til::SExpr *Tm = new (Arena) til::Branch(C, BB1, BB2);
     CurrentBB->setTerminator(Tm);
@@ -576,28 +662,26 @@
 
 
 void SExprBuilder::handleSuccessor(const CFGBlock *Succ) {
-  ++CurrentBlockInfo->SuccessorsToProcess;
+  ++CurrentBlockInfo->UnprocessedSuccessors;
 }
 
 
 void SExprBuilder::handleSuccessorBackEdge(const CFGBlock *Succ) {
-
+  mergePhiNodesBackEdge(Succ);
+  ++BBInfo[Succ->getBlockID()].ProcessedPredecessors;
 }
 
 
 void SExprBuilder::exitCFGBlock(const CFGBlock *B) {
-  CurrentBlockInfo->ExitMap = std::move(CurrentNameMap);
-  CurrentBlockID++;
+  CurrentBlockInfo->ExitMap = std::move(CurrentLVarMap);
   CurrentBB = nullptr;
   CurrentBlockInfo = nullptr;
 }
 
 
 void SExprBuilder::exitCFG(const CFGBlock *Last) {
-  CurrentBlockID = 0;
-  CurrentVarID = 0;
-  CurrentArgIndex = 0;
-  delete CallCtx;
+  CurrentArguments.clear();
+  CurrentInstructions.clear();
 }