summaryrefslogtreecommitdiffstats
path: root/gnu/llvm/tools/clang/lib/Analysis/LiveVariables.cpp
diff options
context:
space:
mode:
authorpatrick <patrick@openbsd.org>2019-01-27 16:42:12 +0000
committerpatrick <patrick@openbsd.org>2019-01-27 16:42:12 +0000
commitb773203fb58f3ef282fb69c832d8710cab5bc82d (patch)
treee75913f147570fbd75169647b144df85b88a038c /gnu/llvm/tools/clang/lib/Analysis/LiveVariables.cpp
parenttweak errno in previous (diff)
downloadwireguard-openbsd-b773203fb58f3ef282fb69c832d8710cab5bc82d.tar.xz
wireguard-openbsd-b773203fb58f3ef282fb69c832d8710cab5bc82d.zip
Import LLVM 7.0.1 release including clang, lld and lldb.
Diffstat (limited to 'gnu/llvm/tools/clang/lib/Analysis/LiveVariables.cpp')
-rw-r--r--gnu/llvm/tools/clang/lib/Analysis/LiveVariables.cpp163
1 files changed, 99 insertions, 64 deletions
diff --git a/gnu/llvm/tools/clang/lib/Analysis/LiveVariables.cpp b/gnu/llvm/tools/clang/lib/Analysis/LiveVariables.cpp
index 4752c2b020a..05bc1a5d102 100644
--- a/gnu/llvm/tools/clang/lib/Analysis/LiveVariables.cpp
+++ b/gnu/llvm/tools/clang/lib/Analysis/LiveVariables.cpp
@@ -39,7 +39,7 @@ public:
: enqueuedBlocks(cfg.getNumBlockIDs()),
POV(Ctx.getAnalysis<PostOrderCFGView>()),
worklist(POV->getComparator()) {}
-
+
void enqueueBlock(const CFGBlock *block);
void enqueuePredecessors(const CFGBlock *block);
@@ -73,16 +73,17 @@ const CFGBlock *DataflowWorklist::dequeue() {
namespace {
class LiveVariablesImpl {
-public:
+public:
AnalysisDeclContext &analysisContext;
llvm::ImmutableSet<const Stmt *>::Factory SSetFact;
llvm::ImmutableSet<const VarDecl *>::Factory DSetFact;
+ llvm::ImmutableSet<const BindingDecl *>::Factory BSetFact;
llvm::DenseMap<const CFGBlock *, LiveVariables::LivenessValues> blocksEndToLiveness;
llvm::DenseMap<const CFGBlock *, LiveVariables::LivenessValues> blocksBeginToLiveness;
llvm::DenseMap<const Stmt *, LiveVariables::LivenessValues> stmtsToLiveness;
llvm::DenseMap<const DeclRefExpr *, unsigned> inAssignment;
const bool killAtAssign;
-
+
LiveVariables::LivenessValues
merge(LiveVariables::LivenessValues valsA,
LiveVariables::LivenessValues valsB);
@@ -97,6 +98,7 @@ public:
: analysisContext(ac),
SSetFact(false), // Do not canonicalize ImmutableSets by default.
DSetFact(false), // This is a *major* performance win.
+ BSetFact(false),
killAtAssign(KillAtAssign) {}
};
}
@@ -114,6 +116,12 @@ bool LiveVariables::LivenessValues::isLive(const Stmt *S) const {
}
bool LiveVariables::LivenessValues::isLive(const VarDecl *D) const {
+ if (const auto *DD = dyn_cast<DecompositionDecl>(D)) {
+ bool alive = false;
+ for (const BindingDecl *BD : DD->bindings())
+ alive |= liveBindings.contains(BD);
+ return alive;
+ }
return liveDecls.contains(D);
}
@@ -122,7 +130,7 @@ namespace {
SET mergeSets(SET A, SET B) {
if (A.isEmpty())
return B;
-
+
for (typename SET::iterator it = B.begin(), ei = B.end(); it != ei; ++it) {
A = A.add(*it);
}
@@ -134,25 +142,30 @@ void LiveVariables::Observer::anchor() { }
LiveVariables::LivenessValues
LiveVariablesImpl::merge(LiveVariables::LivenessValues valsA,
- LiveVariables::LivenessValues valsB) {
-
+ LiveVariables::LivenessValues valsB) {
+
llvm::ImmutableSetRef<const Stmt *>
SSetRefA(valsA.liveStmts.getRootWithoutRetain(), SSetFact.getTreeFactory()),
SSetRefB(valsB.liveStmts.getRootWithoutRetain(), SSetFact.getTreeFactory());
-
-
+
+
llvm::ImmutableSetRef<const VarDecl *>
DSetRefA(valsA.liveDecls.getRootWithoutRetain(), DSetFact.getTreeFactory()),
DSetRefB(valsB.liveDecls.getRootWithoutRetain(), DSetFact.getTreeFactory());
-
+
+ llvm::ImmutableSetRef<const BindingDecl *>
+ BSetRefA(valsA.liveBindings.getRootWithoutRetain(), BSetFact.getTreeFactory()),
+ BSetRefB(valsB.liveBindings.getRootWithoutRetain(), BSetFact.getTreeFactory());
SSetRefA = mergeSets(SSetRefA, SSetRefB);
DSetRefA = mergeSets(DSetRefA, DSetRefB);
-
+ BSetRefA = mergeSets(BSetRefA, BSetRefB);
+
// asImmutableSet() canonicalizes the tree, allowing us to do an easy
// comparison afterwards.
return LiveVariables::LivenessValues(SSetRefA.asImmutableSet(),
- DSetRefA.asImmutableSet());
+ DSetRefA.asImmutableSet(),
+ BSetRefA.asImmutableSet());
}
bool LiveVariables::LivenessValues::equals(const LivenessValues &V) const {
@@ -198,7 +211,7 @@ public:
void VisitBinaryOperator(BinaryOperator *BO);
void VisitBlockExpr(BlockExpr *BE);
- void VisitDeclRefExpr(DeclRefExpr *DR);
+ void VisitDeclRefExpr(DeclRefExpr *DR);
void VisitDeclStmt(DeclStmt *DS);
void VisitObjCForCollectionStmt(ObjCForCollectionStmt *OS);
void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *UE);
@@ -213,7 +226,7 @@ static const VariableArrayType *FindVA(QualType Ty) {
if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(VT))
if (VAT->getSizeExpr())
return VAT;
-
+
ty = VT->getElementType().getTypePtr();
}
@@ -223,7 +236,7 @@ static const VariableArrayType *FindVA(QualType Ty) {
static const Stmt *LookThroughStmt(const Stmt *S) {
while (S) {
if (const Expr *Ex = dyn_cast<Expr>(S))
- S = Ex->IgnoreParens();
+ S = Ex->IgnoreParens();
if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(S)) {
S = EWC->getSubExpr();
continue;
@@ -246,15 +259,15 @@ static void AddLiveStmt(llvm::ImmutableSet<const Stmt *> &Set,
void TransferFunctions::Visit(Stmt *S) {
if (observer)
observer->observeStmt(S, currentBlock, val);
-
+
StmtVisitor<TransferFunctions>::Visit(S);
-
+
if (isa<Expr>(S)) {
val.liveStmts = LV.SSetFact.remove(val.liveStmts, S);
}
// Mark all children expressions live.
-
+
switch (S->getStmtClass()) {
default:
break;
@@ -322,28 +335,37 @@ void TransferFunctions::Visit(Stmt *S) {
}
}
+static bool writeShouldKill(const VarDecl *VD) {
+ return VD && !VD->getType()->isReferenceType() &&
+ !isAlwaysAlive(VD);
+}
+
void TransferFunctions::VisitBinaryOperator(BinaryOperator *B) {
if (B->isAssignmentOp()) {
if (!LV.killAtAssign)
return;
-
+
// Assigning to a variable?
Expr *LHS = B->getLHS()->IgnoreParens();
-
- if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(LHS))
- if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
- // Assignments to references don't kill the ref's address
- if (VD->getType()->isReferenceType())
- return;
-
- if (!isAlwaysAlive(VD)) {
- // The variable is now dead.
+
+ if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(LHS)) {
+ const Decl* D = DR->getDecl();
+ bool Killed = false;
+
+ if (const BindingDecl* BD = dyn_cast<BindingDecl>(D)) {
+ Killed = !BD->getType()->isReferenceType();
+ if (Killed)
+ val.liveBindings = LV.BSetFact.remove(val.liveBindings, BD);
+ } else if (const auto *VD = dyn_cast<VarDecl>(D)) {
+ Killed = writeShouldKill(VD);
+ if (Killed)
val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD);
- }
- if (observer)
- observer->observerKill(DR);
}
+
+ if (Killed && observer)
+ observer->observerKill(DR);
+ }
}
}
@@ -357,17 +379,27 @@ void TransferFunctions::VisitBlockExpr(BlockExpr *BE) {
}
void TransferFunctions::VisitDeclRefExpr(DeclRefExpr *DR) {
- if (const VarDecl *D = dyn_cast<VarDecl>(DR->getDecl()))
- if (!isAlwaysAlive(D) && LV.inAssignment.find(DR) == LV.inAssignment.end())
- val.liveDecls = LV.DSetFact.add(val.liveDecls, D);
+ const Decl* D = DR->getDecl();
+ bool InAssignment = LV.inAssignment[DR];
+ if (const auto *BD = dyn_cast<BindingDecl>(D)) {
+ if (!InAssignment)
+ val.liveBindings = LV.BSetFact.add(val.liveBindings, BD);
+ } else if (const auto *VD = dyn_cast<VarDecl>(D)) {
+ if (!InAssignment && !isAlwaysAlive(VD))
+ val.liveDecls = LV.DSetFact.add(val.liveDecls, VD);
+ }
}
void TransferFunctions::VisitDeclStmt(DeclStmt *DS) {
- for (const auto *DI : DS->decls())
- if (const auto *VD = dyn_cast<VarDecl>(DI)) {
+ for (const auto *DI : DS->decls()) {
+ if (const auto *DD = dyn_cast<DecompositionDecl>(DI)) {
+ for (const auto *BD : DD->bindings())
+ val.liveBindings = LV.BSetFact.remove(val.liveBindings, BD);
+ } else if (const auto *VD = dyn_cast<VarDecl>(DI)) {
if (!isAlwaysAlive(VD))
val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD);
}
+ }
}
void TransferFunctions::VisitObjCForCollectionStmt(ObjCForCollectionStmt *OS) {
@@ -382,7 +414,7 @@ void TransferFunctions::VisitObjCForCollectionStmt(ObjCForCollectionStmt *OS) {
else if ((DR = dyn_cast<DeclRefExpr>(cast<Expr>(element)->IgnoreParens()))) {
VD = cast<VarDecl>(DR->getDecl());
}
-
+
if (VD) {
val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD);
if (observer && DR)
@@ -412,22 +444,24 @@ void TransferFunctions::VisitUnaryOperator(UnaryOperator *UO) {
// since a ++/-- acts as both a kill and a "use".
if (!observer)
return;
-
+
switch (UO->getOpcode()) {
default:
return;
case UO_PostInc:
- case UO_PostDec:
+ case UO_PostDec:
case UO_PreInc:
case UO_PreDec:
break;
}
-
- if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(UO->getSubExpr()->IgnoreParens()))
- if (isa<VarDecl>(DR->getDecl())) {
+
+ if (auto *DR = dyn_cast<DeclRefExpr>(UO->getSubExpr()->IgnoreParens())) {
+ const Decl *D = DR->getDecl();
+ if (isa<VarDecl>(D) || isa<BindingDecl>(D)) {
// Treat ++/-- as a kill.
observer->observerKill(DR);
}
+ }
}
LiveVariables::LivenessValues
@@ -436,11 +470,11 @@ LiveVariablesImpl::runOnBlock(const CFGBlock *block,
LiveVariables::Observer *obs) {
TransferFunctions TF(*this, val, obs, block);
-
+
// Visit the terminator (if any).
if (const Stmt *term = block->getTerminator())
TF.Visit(const_cast<Stmt*>(term));
-
+
// Apply the transfer function for all Stmts in the block.
for (CFGBlock::const_reverse_iterator it = block->rbegin(),
ei = block->rend(); it != ei; ++it) {
@@ -454,7 +488,7 @@ LiveVariablesImpl::runOnBlock(const CFGBlock *block,
if (!elem.getAs<CFGStmt>())
continue;
-
+
const Stmt *S = elem.castAs<CFGStmt>().getStmt();
TF.Visit(const_cast<Stmt*>(S));
stmtsToLiveness[S] = val;
@@ -465,10 +499,10 @@ LiveVariablesImpl::runOnBlock(const CFGBlock *block,
void LiveVariables::runOnAllBlocks(LiveVariables::Observer &obs) {
const CFG *cfg = getImpl(impl).analysisContext.getCFG();
for (CFG::const_iterator it = cfg->begin(), ei = cfg->end(); it != ei; ++it)
- getImpl(impl).runOnBlock(*it, getImpl(impl).blocksEndToLiveness[*it], &obs);
+ getImpl(impl).runOnBlock(*it, getImpl(impl).blocksEndToLiveness[*it], &obs);
}
-LiveVariables::LiveVariables(void *im) : impl(im) {}
+LiveVariables::LiveVariables(void *im) : impl(im) {}
LiveVariables::~LiveVariables() {
delete (LiveVariablesImpl*) impl;
@@ -499,7 +533,7 @@ LiveVariables::computeLiveness(AnalysisDeclContext &AC,
for (CFG::const_iterator it = cfg->begin(), ei = cfg->end(); it != ei; ++it) {
const CFGBlock *block = *it;
worklist.enqueueBlock(block);
-
+
// FIXME: Scan for DeclRefExprs using in the LHS of an assignment.
// We need to do this because we lack context in the reverse analysis
// to determine if a DeclRefExpr appears in such a context, and thus
@@ -508,10 +542,10 @@ LiveVariables::computeLiveness(AnalysisDeclContext &AC,
for (CFGBlock::const_iterator bi = block->begin(), be = block->end();
bi != be; ++bi) {
if (Optional<CFGStmt> cs = bi->getAs<CFGStmt>()) {
- if (const BinaryOperator *BO =
- dyn_cast<BinaryOperator>(cs->getStmt())) {
+ const Stmt* stmt = cs->getStmt();
+ if (const auto *BO = dyn_cast<BinaryOperator>(stmt)) {
if (BO->getOpcode() == BO_Assign) {
- if (const DeclRefExpr *DR =
+ if (const auto *DR =
dyn_cast<DeclRefExpr>(BO->getLHS()->IgnoreParens())) {
LV->inAssignment[DR] = 1;
}
@@ -520,35 +554,35 @@ LiveVariables::computeLiveness(AnalysisDeclContext &AC,
}
}
}
-
+
while (const CFGBlock *block = worklist.dequeue()) {
// Determine if the block's end value has changed. If not, we
// have nothing left to do for this block.
LivenessValues &prevVal = LV->blocksEndToLiveness[block];
-
+
// Merge the values of all successor blocks.
LivenessValues val;
for (CFGBlock::const_succ_iterator it = block->succ_begin(),
ei = block->succ_end(); it != ei; ++it) {
- if (const CFGBlock *succ = *it) {
+ if (const CFGBlock *succ = *it) {
val = LV->merge(val, LV->blocksBeginToLiveness[succ]);
}
}
-
+
if (!everAnalyzedBlock[block->getBlockID()])
everAnalyzedBlock[block->getBlockID()] = true;
else if (prevVal.equals(val))
continue;
prevVal = val;
-
+
// Update the dataflow value for the start of this block.
LV->blocksBeginToLiveness[block] = LV->runOnBlock(block, val);
-
+
// Enqueue the value to the predecessors.
worklist.enqueuePredecessors(block);
}
-
+
return new LiveVariables(LV);
}
@@ -561,9 +595,9 @@ void LiveVariablesImpl::dumpBlockLiveness(const SourceManager &M) {
for (llvm::DenseMap<const CFGBlock *, LiveVariables::LivenessValues>::iterator
it = blocksEndToLiveness.begin(), ei = blocksEndToLiveness.end();
it != ei; ++it) {
- vec.push_back(it->first);
+ vec.push_back(it->first);
}
- std::sort(vec.begin(), vec.end(), [](const CFGBlock *A, const CFGBlock *B) {
+ llvm::sort(vec.begin(), vec.end(), [](const CFGBlock *A, const CFGBlock *B) {
return A->getBlockID() < B->getBlockID();
});
@@ -573,17 +607,18 @@ void LiveVariablesImpl::dumpBlockLiveness(const SourceManager &M) {
it = vec.begin(), ei = vec.end(); it != ei; ++it) {
llvm::errs() << "\n[ B" << (*it)->getBlockID()
<< " (live variables at block exit) ]\n";
-
+
LiveVariables::LivenessValues vals = blocksEndToLiveness[*it];
declVec.clear();
-
+
for (llvm::ImmutableSet<const VarDecl *>::iterator si =
vals.liveDecls.begin(),
se = vals.liveDecls.end(); si != se; ++si) {
- declVec.push_back(*si);
+ declVec.push_back(*si);
}
- std::sort(declVec.begin(), declVec.end(), [](const Decl *A, const Decl *B) {
+ llvm::sort(declVec.begin(), declVec.end(),
+ [](const Decl *A, const Decl *B) {
return A->getLocStart() < B->getLocStart();
});
@@ -595,7 +630,7 @@ void LiveVariablesImpl::dumpBlockLiveness(const SourceManager &M) {
llvm::errs() << ">\n";
}
}
- llvm::errs() << "\n";
+ llvm::errs() << "\n";
}
const void *LiveVariables::getTag() { static int x; return &x; }