forked from OSchip/llvm-project
Further reduce "-fsyntax-only -Wuninitialized" time on sqlite3.c by another 2.5% using intelligent pruning of blocks during the final reporting pass.
llvm-svn: 168257
This commit is contained in:
parent
15443ee70f
commit
778a6ed358
|
|
@ -426,13 +426,13 @@ class TransferFunctions : public StmtVisitor<TransferFunctions> {
|
||||||
AnalysisDeclContext ∾
|
AnalysisDeclContext ∾
|
||||||
const ClassifyRefs &classification;
|
const ClassifyRefs &classification;
|
||||||
ObjCNoReturn objCNoRet;
|
ObjCNoReturn objCNoRet;
|
||||||
UninitVariablesHandler *handler;
|
UninitVariablesHandler &handler;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TransferFunctions(CFGBlockValues &vals, const CFG &cfg,
|
TransferFunctions(CFGBlockValues &vals, const CFG &cfg,
|
||||||
const CFGBlock *block, AnalysisDeclContext &ac,
|
const CFGBlock *block, AnalysisDeclContext &ac,
|
||||||
const ClassifyRefs &classification,
|
const ClassifyRefs &classification,
|
||||||
UninitVariablesHandler *handler)
|
UninitVariablesHandler &handler)
|
||||||
: vals(vals), cfg(cfg), block(block), ac(ac),
|
: vals(vals), cfg(cfg), block(block), ac(ac),
|
||||||
classification(classification), objCNoRet(ac.getASTContext()),
|
classification(classification), objCNoRet(ac.getASTContext()),
|
||||||
handler(handler) {}
|
handler(handler) {}
|
||||||
|
|
@ -589,11 +589,9 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransferFunctions::reportUse(const Expr *ex, const VarDecl *vd) {
|
void TransferFunctions::reportUse(const Expr *ex, const VarDecl *vd) {
|
||||||
if (!handler)
|
|
||||||
return;
|
|
||||||
Value v = vals[vd];
|
Value v = vals[vd];
|
||||||
if (isUninitialized(v))
|
if (isUninitialized(v))
|
||||||
handler->handleUseOfUninitVariable(vd, getUninitUse(ex, vd, v));
|
handler.handleUseOfUninitVariable(vd, getUninitUse(ex, vd, v));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransferFunctions::VisitObjCForCollectionStmt(ObjCForCollectionStmt *FS) {
|
void TransferFunctions::VisitObjCForCollectionStmt(ObjCForCollectionStmt *FS) {
|
||||||
|
|
@ -654,8 +652,7 @@ void TransferFunctions::VisitDeclRefExpr(DeclRefExpr *dr) {
|
||||||
vals[cast<VarDecl>(dr->getDecl())] = Initialized;
|
vals[cast<VarDecl>(dr->getDecl())] = Initialized;
|
||||||
break;
|
break;
|
||||||
case ClassifyRefs::SelfInit:
|
case ClassifyRefs::SelfInit:
|
||||||
if (handler)
|
handler.handleSelfInit(cast<VarDecl>(dr->getDecl()));
|
||||||
handler->handleSelfInit(cast<VarDecl>(dr->getDecl()));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -721,7 +718,7 @@ static bool runOnBlock(const CFGBlock *block, const CFG &cfg,
|
||||||
AnalysisDeclContext &ac, CFGBlockValues &vals,
|
AnalysisDeclContext &ac, CFGBlockValues &vals,
|
||||||
const ClassifyRefs &classification,
|
const ClassifyRefs &classification,
|
||||||
llvm::BitVector &wasAnalyzed,
|
llvm::BitVector &wasAnalyzed,
|
||||||
UninitVariablesHandler *handler = 0) {
|
UninitVariablesHandler &handler) {
|
||||||
wasAnalyzed[block->getBlockID()] = true;
|
wasAnalyzed[block->getBlockID()] = true;
|
||||||
vals.resetScratch();
|
vals.resetScratch();
|
||||||
// Merge in values of predecessor blocks.
|
// Merge in values of predecessor blocks.
|
||||||
|
|
@ -745,6 +742,43 @@ static bool runOnBlock(const CFGBlock *block, const CFG &cfg,
|
||||||
return vals.updateValueVectorWithScratch(block);
|
return vals.updateValueVectorWithScratch(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// PruneBlocksHandler is a special UninitVariablesHandler that is used
|
||||||
|
/// to detect when a CFGBlock has any *potential* use of an uninitialized
|
||||||
|
/// variable. It is mainly used to prune out work during the final
|
||||||
|
/// reporting pass.
|
||||||
|
namespace {
|
||||||
|
struct PruneBlocksHandler : public UninitVariablesHandler {
|
||||||
|
PruneBlocksHandler(unsigned numBlocks)
|
||||||
|
: hadUse(numBlocks, false), hadAnyUse(false),
|
||||||
|
currentBlock(0) {}
|
||||||
|
|
||||||
|
virtual ~PruneBlocksHandler() {}
|
||||||
|
|
||||||
|
/// Records if a CFGBlock had a potential use of an uninitialized variable.
|
||||||
|
llvm::BitVector hadUse;
|
||||||
|
|
||||||
|
/// Records if any CFGBlock had a potential use of an uninitialized variable.
|
||||||
|
bool hadAnyUse;
|
||||||
|
|
||||||
|
/// The current block to scribble use information.
|
||||||
|
unsigned currentBlock;
|
||||||
|
|
||||||
|
virtual void handleUseOfUninitVariable(const VarDecl *vd,
|
||||||
|
const UninitUse &use) {
|
||||||
|
hadUse[currentBlock] = true;
|
||||||
|
hadAnyUse = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Called when the uninitialized variable analysis detects the
|
||||||
|
/// idiom 'int x = x'. All other uses of 'x' within the initializer
|
||||||
|
/// are handled by handleUseOfUninitVariable.
|
||||||
|
virtual void handleSelfInit(const VarDecl *vd) {
|
||||||
|
hadUse[currentBlock] = true;
|
||||||
|
hadAnyUse = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
void clang::runUninitializedVariablesAnalysis(
|
void clang::runUninitializedVariablesAnalysis(
|
||||||
const DeclContext &dc,
|
const DeclContext &dc,
|
||||||
const CFG &cfg,
|
const CFG &cfg,
|
||||||
|
|
@ -776,22 +810,28 @@ void clang::runUninitializedVariablesAnalysis(
|
||||||
worklist.enqueueSuccessors(&cfg.getEntry());
|
worklist.enqueueSuccessors(&cfg.getEntry());
|
||||||
llvm::BitVector wasAnalyzed(cfg.getNumBlockIDs(), false);
|
llvm::BitVector wasAnalyzed(cfg.getNumBlockIDs(), false);
|
||||||
wasAnalyzed[cfg.getEntry().getBlockID()] = true;
|
wasAnalyzed[cfg.getEntry().getBlockID()] = true;
|
||||||
|
PruneBlocksHandler PBH(cfg.getNumBlockIDs());
|
||||||
|
|
||||||
while (const CFGBlock *block = worklist.dequeue()) {
|
while (const CFGBlock *block = worklist.dequeue()) {
|
||||||
|
PBH.currentBlock = block->getBlockID();
|
||||||
|
|
||||||
// Did the block change?
|
// Did the block change?
|
||||||
bool changed = runOnBlock(block, cfg, ac, vals,
|
bool changed = runOnBlock(block, cfg, ac, vals,
|
||||||
classification, wasAnalyzed);
|
classification, wasAnalyzed, PBH);
|
||||||
++stats.NumBlockVisits;
|
++stats.NumBlockVisits;
|
||||||
if (changed || !previouslyVisited[block->getBlockID()])
|
if (changed || !previouslyVisited[block->getBlockID()])
|
||||||
worklist.enqueueSuccessors(block);
|
worklist.enqueueSuccessors(block);
|
||||||
previouslyVisited[block->getBlockID()] = true;
|
previouslyVisited[block->getBlockID()] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!PBH.hadAnyUse)
|
||||||
|
return;
|
||||||
|
|
||||||
// Run through the blocks one more time, and report uninitialized variabes.
|
// Run through the blocks one more time, and report uninitialized variabes.
|
||||||
for (CFG::const_iterator BI = cfg.begin(), BE = cfg.end(); BI != BE; ++BI) {
|
for (CFG::const_iterator BI = cfg.begin(), BE = cfg.end(); BI != BE; ++BI) {
|
||||||
const CFGBlock *block = *BI;
|
const CFGBlock *block = *BI;
|
||||||
if (wasAnalyzed[block->getBlockID()]) {
|
if (PBH.hadUse[block->getBlockID()]) {
|
||||||
runOnBlock(block, cfg, ac, vals, classification, wasAnalyzed, &handler);
|
runOnBlock(block, cfg, ac, vals, classification, wasAnalyzed, handler);
|
||||||
++stats.NumBlockVisits;
|
++stats.NumBlockVisits;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue