diff options
Diffstat (limited to 'clang/lib/Analysis/ThreadSafetyCommon.cpp')
| -rw-r--r-- | clang/lib/Analysis/ThreadSafetyCommon.cpp | 124 |
1 files changed, 85 insertions, 39 deletions
diff --git a/clang/lib/Analysis/ThreadSafetyCommon.cpp b/clang/lib/Analysis/ThreadSafetyCommon.cpp index eae2552f051..cf9a7b8bf37 100644 --- a/clang/lib/Analysis/ThreadSafetyCommon.cpp +++ b/clang/lib/Analysis/ThreadSafetyCommon.cpp @@ -47,11 +47,12 @@ SExpr *getCanonicalVal(SExpr *E) { if (V->kind() != Variable::VK_Let) return V; D = V->definition(); - if (auto *V2 = dyn_cast<Variable>(D)) { + auto *V2 = dyn_cast<Variable>(D); + if (V2) V = V2; - continue; - } - } while(false); + else + break; + } while (true); if (ThreadSafetyTIL::isTrivial(D)) return D; @@ -75,7 +76,7 @@ SExpr *getCanonicalVal(SExpr *E) { // canonical definition. If so, mark the Phi node as redundant. // getCanonicalVal() will recursively call simplifyIncompletePhi(). void simplifyIncompleteArg(Variable *V, til::Phi *Ph) { - assert(!Ph && Ph->status() == Phi::PH_Incomplete); + assert(Ph && Ph->status() == Phi::PH_Incomplete); // eliminate infinite recursion -- assume that this node is not redundant. Ph->setStatus(Phi::PH_MultiVal); @@ -90,8 +91,21 @@ void simplifyIncompleteArg(Variable *V, til::Phi *Ph) { } } Ph->setStatus(Phi::PH_SingleVal); + // Eliminate Redundant Phi node. + V->setDefinition(Ph->values()[0]); } + +// Return true if E is a variable that points to an incomplete Phi node. +inline bool isIncompleteVar(SExpr *E) { + if (Variable *V = dyn_cast<Variable>(E)) { + if (Phi *Ph = dyn_cast<Phi>(V->definition())) + return Ph->status() == Phi::PH_Incomplete; + } + return false; +} + + } // end namespace til @@ -140,6 +154,7 @@ til::SExpr *SExprBuilder::translate(const Stmt *S, CallingContext *Ctx) { case Stmt::UnaryOperatorClass: return translateUnaryOperator(cast<UnaryOperator>(S), Ctx); case Stmt::BinaryOperatorClass: + case Stmt::CompoundAssignOperatorClass: return translateBinaryOperator(cast<BinaryOperator>(S), Ctx); case Stmt::ArraySubscriptExprClass: @@ -277,6 +292,32 @@ til::SExpr *SExprBuilder::translateUnaryOperator(const UnaryOperator *UO, } +til::SExpr *SExprBuilder::translateBinAssign(til::TIL_BinaryOpcode Op, + const BinaryOperator *BO, + CallingContext *Ctx) { + const Expr *LHS = BO->getLHS(); + const Expr *RHS = BO->getRHS(); + til::SExpr *E0 = translate(LHS, Ctx); + til::SExpr *E1 = translate(RHS, Ctx); + + const ValueDecl *VD = nullptr; + til::SExpr *CV = nullptr; + if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(LHS)) { + VD = DRE->getDecl(); + CV = lookupVarDecl(VD); + } + + if (Op != BO_Assign) { + til::SExpr *Arg = CV ? CV : new (Arena) til::Load(E0); + E1 = new (Arena) til::BinaryOp(Op, Arg, E1); + E1 = addStatement(E1, nullptr, VD); + } + if (VD && CV) + return updateVarDecl(VD, E1); + return new (Arena) til::Store(E0, E1); +} + + til::SExpr *SExprBuilder::translateBinaryOperator(const BinaryOperator *BO, CallingContext *Ctx) { switch (BO->getOpcode()) { @@ -306,35 +347,24 @@ til::SExpr *SExprBuilder::translateBinaryOperator(const BinaryOperator *BO, til::BinaryOp(BO->getOpcode(), translate(BO->getLHS(), Ctx), translate(BO->getRHS(), Ctx)); - case BO_Assign: { - const Expr *LHS = BO->getLHS(); - if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(LHS)) { - const Expr *RHS = BO->getRHS(); - til::SExpr *E1 = translate(RHS, Ctx); - return updateVarDecl(DRE->getDecl(), E1); - } - til::SExpr *E0 = translate(LHS, Ctx); - til::SExpr *E1 = translate(BO->getRHS(), Ctx); - return new (Arena) til::Store(E0, E1); - } - case BO_MulAssign: - case BO_DivAssign: - case BO_RemAssign: - case BO_AddAssign: - case BO_SubAssign: - case BO_ShlAssign: - case BO_ShrAssign: - case BO_AndAssign: - case BO_XorAssign: - case BO_OrAssign: - return new (Arena) til::Undefined(BO); + case BO_Assign: return translateBinAssign(BO_Assign, BO, Ctx); + case BO_MulAssign: return translateBinAssign(BO_Mul, BO, Ctx); + case BO_DivAssign: return translateBinAssign(BO_Div, BO, Ctx); + case BO_RemAssign: return translateBinAssign(BO_Rem, BO, Ctx); + case BO_AddAssign: return translateBinAssign(BO_Add, BO, Ctx); + case BO_SubAssign: return translateBinAssign(BO_Sub, BO, Ctx); + case BO_ShlAssign: return translateBinAssign(BO_Shl, BO, Ctx); + case BO_ShrAssign: return translateBinAssign(BO_Shr, BO, Ctx); + case BO_AndAssign: return translateBinAssign(BO_And, BO, Ctx); + case BO_XorAssign: return translateBinAssign(BO_Xor, BO, Ctx); + case BO_OrAssign: return translateBinAssign(BO_Or, BO, Ctx); case BO_Comma: - // TODO: handle LHS + // The clang CFG should have already processed both sides. return translate(BO->getRHS(), Ctx); - } return new (Arena) til::Undefined(BO); + } } @@ -495,14 +525,16 @@ 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] = CurrentLVarMap[i].second; + Ph->values()[PIdx] = CurrE; if (E) Ph->values()[ArgIndex] = E; - if (!E) { - // This is a non-minimal SSA node, which may be removed later. + // 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)) { Ph->setStatus(til::Phi::PH_Incomplete); } @@ -601,8 +633,7 @@ void SExprBuilder::mergePhiNodesBackEdge(const CFGBlock *Blk) { } - -void SExprBuilder::enterCFG(CFG *Cfg, const NamedDecl *D, +void SExprBuilder::enterCFG(CFG *Cfg, const FunctionDecl *FD, const CFGBlock *First) { // Perform initial setup operations. unsigned NBlocks = Cfg->getNumBlockIDs(); @@ -616,22 +647,35 @@ void SExprBuilder::enterCFG(CFG *Cfg, const NamedDecl *D, auto *BB = new (Arena) til::BasicBlock(Arena, 0, B->size()); BlockMap[B->getBlockID()] = BB; } - CallCtx = new SExprBuilder::CallingContext(D); + CallCtx = new SExprBuilder::CallingContext(FD); + + CurrentBB = lookupBlock(&Cfg->getEntry()); + for (auto *Pm : FD->parameters()) { + QualType T = Pm->getType(); + if (!T.isTrivialType(Pm->getASTContext())) + continue; + + // Add parameters to local variable map. + // FIXME: right now we emulate params with loads; that should be fixed. + til::SExpr *Lp = new (Arena) til::LiteralPtr(Pm); + til::SExpr *Ld = new (Arena) til::Load(Lp); + til::SExpr *V = addStatement(Ld, nullptr, Pm); + addVarDecl(Pm, V); + } } void SExprBuilder::enterCFGBlock(const CFGBlock *B) { // Intialize TIL basic block and add it to the CFG. - CurrentBB = BlockMap[B->getBlockID()]; + CurrentBB = lookupBlock(B); CurrentBB->setNumPredecessors(B->pred_size()); Scfg->add(CurrentBB); CurrentBlockInfo = &BBInfo[B->getBlockID()]; - CurrentArguments.clear(); - CurrentInstructions.clear(); // CurrentLVarMap is moved to ExitMap on block exit. - assert(!CurrentLVarMap.valid() && "CurrentLVarMap already initialized."); + // FIXME: the entry block will hold function parameters. + // assert(!CurrentLVarMap.valid() && "CurrentLVarMap already initialized."); } @@ -721,6 +765,8 @@ void SExprBuilder::handleSuccessorBackEdge(const CFGBlock *Succ) { void SExprBuilder::exitCFGBlock(const CFGBlock *B) { + CurrentArguments.clear(); + CurrentInstructions.clear(); CurrentBlockInfo->ExitMap = std::move(CurrentLVarMap); CurrentBB = nullptr; CurrentBlockInfo = nullptr; |

