Thread Safety Analysis: major update to thread safety TIL.

Numerous changes, including:
  * Changed the way variables and instructions are handled in basic blocks to
    be more efficient.
  * Eliminated SExprRef.
  * Simplified futures.
  * Fixed documentation.
  * Compute dominator and post dominator trees.

llvm-svn: 217556
This commit is contained in:
DeLesley Hutchins
2014-09-10 22:12:52 +00:00
parent a00a6526dc
commit 4e38f100b5
8 changed files with 914 additions and 765 deletions

View File

@@ -63,11 +63,9 @@ std::string getSourceLiteralString(const clang::Expr *CE) {
namespace til {
// Return true if E is a variable that points to an incomplete Phi node.
static bool isIncompleteVar(const SExpr *E) {
if (const auto *V = dyn_cast<Variable>(E)) {
if (const auto *Ph = dyn_cast<Phi>(V->definition()))
return Ph->status() == Phi::PH_Incomplete;
}
static bool isIncompletePhi(const SExpr *E) {
if (const auto *Ph = dyn_cast<Phi>(E))
return Ph->status() == Phi::PH_Incomplete;
return false;
}
@@ -320,6 +318,8 @@ til::SExpr *SExprBuilder::translateCXXThisExpr(const CXXThisExpr *TE,
const ValueDecl *getValueDeclFromSExpr(const til::SExpr *E) {
if (auto *V = dyn_cast<til::Variable>(E))
return V->clangDecl();
if (auto *Ph = dyn_cast<til::Phi>(E))
return Ph->clangDecl();
if (auto *P = dyn_cast<til::Project>(E))
return P->clangDecl();
if (auto *L = dyn_cast<til::LiteralPtr>(E))
@@ -641,14 +641,14 @@ SExprBuilder::translateDeclStmt(const DeclStmt *S, CallingContext *Ctx) {
// If E is trivial returns E.
til::SExpr *SExprBuilder::addStatement(til::SExpr* E, const Stmt *S,
const ValueDecl *VD) {
if (!E || !CurrentBB || til::ThreadSafetyTIL::isTrivial(E))
if (!E || !CurrentBB || E->block() || til::ThreadSafetyTIL::isTrivial(E))
return E;
til::Variable *V = new (Arena) til::Variable(E, VD);
CurrentInstructions.push_back(V);
if (VD)
E = new (Arena) til::Variable(E, VD);
CurrentInstructions.push_back(E);
if (S)
insertStmt(S, V);
return V;
insertStmt(S, E);
return E;
}
@@ -705,11 +705,11 @@ 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()) {
til::SExpr *CurrE = CurrentLVarMap[i].second;
if (CurrE->block() == CurrentBB) {
// 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());
til::Phi *Ph = dyn_cast<til::Phi>(CurrE);
assert(Ph && "Expecting Phi node.");
if (E)
Ph->values()[ArgIndex] = E;
@@ -718,27 +718,26 @@ void SExprBuilder::makePhiNodeVar(unsigned i, unsigned NPreds, til::SExpr *E) {
// Make a new phi node: phi(..., E)
// All phi args up to the current index are set to the current value.
til::SExpr *CurrE = CurrentLVarMap[i].second;
til::Phi *Ph = new (Arena) til::Phi(Arena, NPreds);
Ph->values().setValues(NPreds, nullptr);
for (unsigned PIdx = 0; PIdx < ArgIndex; ++PIdx)
Ph->values()[PIdx] = CurrE;
if (E)
Ph->values()[ArgIndex] = E;
Ph->setClangDecl(CurrentLVarMap[i].first);
// If E is from a back-edge, or either E or CurrE are incomplete, then
// mark this node as incomplete; we may need to remove it later.
if (!E || isIncompleteVar(E) || isIncompleteVar(CurrE)) {
if (!E || isIncompletePhi(E) || isIncompletePhi(CurrE)) {
Ph->setStatus(til::Phi::PH_Incomplete);
}
// Add Phi node to current block, and update CurrentLVarMap[i]
auto *Var = new (Arena) til::Variable(Ph, CurrentLVarMap[i].first);
CurrentArguments.push_back(Var);
CurrentArguments.push_back(Ph);
if (Ph->status() == til::Phi::PH_Incomplete)
IncompleteArgs.push_back(Var);
IncompleteArgs.push_back(Ph);
CurrentLVarMap.makeWritable();
CurrentLVarMap.elem(i).second = Var;
CurrentLVarMap.elem(i).second = Ph;
}
@@ -812,15 +811,13 @@ void SExprBuilder::mergePhiNodesBackEdge(const CFGBlock *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());
for (til::SExpr *PE : BB->arguments()) {
til::Phi *Ph = dyn_cast_or_null<til::Phi>(PE);
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());
til::SExpr *E = lookupVarDecl(Ph->clangDecl());
assert(E && "Couldn't find local variable for Phi node.");
Ph->values()[ArgIndex] = E;
}
}
@@ -899,8 +896,8 @@ void SExprBuilder::enterCFGBlockBody(const CFGBlock *B) {
// Push those arguments onto the basic block.
CurrentBB->arguments().reserve(
static_cast<unsigned>(CurrentArguments.size()), Arena);
for (auto *V : CurrentArguments)
CurrentBB->addArgument(V);
for (auto *A : CurrentArguments)
CurrentBB->addArgument(A);
}
@@ -934,7 +931,7 @@ void SExprBuilder::exitCFGBlockBody(const CFGBlock *B) {
til::BasicBlock *BB = *It ? lookupBlock(*It) : nullptr;
// TODO: set index
unsigned Idx = BB ? BB->findPredecessorIndex(CurrentBB) : 0;
til::SExpr *Tm = new (Arena) til::Goto(BB, Idx);
auto *Tm = new (Arena) til::Goto(BB, Idx);
CurrentBB->setTerminator(Tm);
}
else if (N == 2) {
@@ -942,9 +939,8 @@ void SExprBuilder::exitCFGBlockBody(const CFGBlock *B) {
til::BasicBlock *BB1 = *It ? lookupBlock(*It) : nullptr;
++It;
til::BasicBlock *BB2 = *It ? lookupBlock(*It) : nullptr;
unsigned Idx1 = BB1 ? BB1->findPredecessorIndex(CurrentBB) : 0;
unsigned Idx2 = BB2 ? BB2->findPredecessorIndex(CurrentBB) : 0;
til::SExpr *Tm = new (Arena) til::Branch(C, BB1, BB2, Idx1, Idx2);
// FIXME: make sure these arent' critical edges.
auto *Tm = new (Arena) til::Branch(C, BB1, BB2);
CurrentBB->setTerminator(Tm);
}
}
@@ -971,10 +967,9 @@ void SExprBuilder::exitCFGBlock(const CFGBlock *B) {
void SExprBuilder::exitCFG(const CFGBlock *Last) {
for (auto *V : IncompleteArgs) {
til::Phi *Ph = dyn_cast<til::Phi>(V->definition());
if (Ph && Ph->status() == til::Phi::PH_Incomplete)
simplifyIncompleteArg(V, Ph);
for (auto *Ph : IncompleteArgs) {
if (Ph->status() == til::Phi::PH_Incomplete)
simplifyIncompleteArg(Ph);
}
CurrentArguments.clear();