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:
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user