Simplify UninitializedValues.cpp by removing logic to handle the previous (imprecise) representation
of '&&' and '||' in the CFG. This is no longer needed, and greatly simplifies the code. llvm-svn: 160494
This commit is contained in:
parent
aaf9735951
commit
6080d32194
|
@ -98,15 +98,12 @@ static bool isAlwaysUninit(const Value v) {
|
|||
namespace {
|
||||
|
||||
typedef llvm::PackedVector<Value, 2> ValueVector;
|
||||
typedef std::pair<ValueVector *, ValueVector *> BVPair;
|
||||
|
||||
class CFGBlockValues {
|
||||
const CFG &cfg;
|
||||
BVPair *vals;
|
||||
std::vector<ValueVector*> vals;
|
||||
ValueVector scratch;
|
||||
DeclToIndex declToIndex;
|
||||
|
||||
ValueVector &lazyCreate(ValueVector *&bv);
|
||||
public:
|
||||
CFGBlockValues(const CFG &cfg);
|
||||
~CFGBlockValues();
|
||||
|
@ -114,22 +111,19 @@ public:
|
|||
unsigned getNumEntries() const { return declToIndex.size(); }
|
||||
|
||||
void computeSetOfDeclarations(const DeclContext &dc);
|
||||
ValueVector &getValueVector(const CFGBlock *block,
|
||||
const CFGBlock *dstBlock);
|
||||
|
||||
BVPair &getValueVectors(const CFGBlock *block, bool shouldLazyCreate);
|
||||
ValueVector &getValueVector(const CFGBlock *block) {
|
||||
return *vals[block->getBlockID()];
|
||||
}
|
||||
|
||||
void setAllScratchValues(Value V);
|
||||
void mergeIntoScratch(ValueVector const &source, bool isFirst);
|
||||
bool updateValueVectorWithScratch(const CFGBlock *block);
|
||||
bool updateValueVectors(const CFGBlock *block, const BVPair &newVals);
|
||||
|
||||
bool hasNoDeclarations() const {
|
||||
return declToIndex.size() == 0;
|
||||
}
|
||||
|
||||
void resetScratch();
|
||||
ValueVector &getScratch() { return scratch; }
|
||||
|
||||
ValueVector::reference operator[](const VarDecl *vd);
|
||||
|
||||
|
@ -137,91 +131,29 @@ public:
|
|||
const VarDecl *vd) {
|
||||
const llvm::Optional<unsigned> &idx = declToIndex.getValueIndex(vd);
|
||||
assert(idx.hasValue());
|
||||
return getValueVector(block, dstBlock)[idx.getValue()];
|
||||
return getValueVector(block)[idx.getValue()];
|
||||
}
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
CFGBlockValues::CFGBlockValues(const CFG &c) : cfg(c), vals(0) {
|
||||
unsigned n = cfg.getNumBlockIDs();
|
||||
if (!n)
|
||||
return;
|
||||
vals = new std::pair<ValueVector*, ValueVector*>[n];
|
||||
memset((void*)vals, 0, sizeof(*vals) * n);
|
||||
}
|
||||
CFGBlockValues::CFGBlockValues(const CFG &c) : cfg(c), vals(0) {}
|
||||
|
||||
CFGBlockValues::~CFGBlockValues() {
|
||||
unsigned n = cfg.getNumBlockIDs();
|
||||
if (n == 0)
|
||||
return;
|
||||
for (unsigned i = 0; i < n; ++i) {
|
||||
delete vals[i].first;
|
||||
delete vals[i].second;
|
||||
}
|
||||
delete [] vals;
|
||||
for (std::vector<ValueVector*>::iterator I = vals.begin(), E = vals.end();
|
||||
I != E; ++I)
|
||||
delete *I;
|
||||
}
|
||||
|
||||
void CFGBlockValues::computeSetOfDeclarations(const DeclContext &dc) {
|
||||
declToIndex.computeMap(dc);
|
||||
scratch.resize(declToIndex.size());
|
||||
}
|
||||
|
||||
ValueVector &CFGBlockValues::lazyCreate(ValueVector *&bv) {
|
||||
if (!bv)
|
||||
bv = new ValueVector(declToIndex.size());
|
||||
return *bv;
|
||||
}
|
||||
|
||||
/// This function pattern matches for a '&&' or '||' that appears at
|
||||
/// the beginning of a CFGBlock that also (1) has a terminator and
|
||||
/// (2) has no other elements. If such an expression is found, it is returned.
|
||||
static const BinaryOperator *getLogicalOperatorInChain(const CFGBlock *block) {
|
||||
if (block->empty())
|
||||
return 0;
|
||||
|
||||
CFGElement front = block->front();
|
||||
const CFGStmt *cstmt = front.getAs<CFGStmt>();
|
||||
if (!cstmt)
|
||||
return 0;
|
||||
|
||||
const BinaryOperator *b = dyn_cast_or_null<BinaryOperator>(cstmt->getStmt());
|
||||
|
||||
if (!b || !b->isLogicalOp())
|
||||
return 0;
|
||||
|
||||
if (block->pred_size() == 2) {
|
||||
if (block->getTerminatorCondition() == b) {
|
||||
if (block->succ_size() == 2)
|
||||
return b;
|
||||
}
|
||||
else if (block->size() == 1)
|
||||
return b;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ValueVector &CFGBlockValues::getValueVector(const CFGBlock *block,
|
||||
const CFGBlock *dstBlock) {
|
||||
unsigned idx = block->getBlockID();
|
||||
if (dstBlock && getLogicalOperatorInChain(block)) {
|
||||
if (*block->succ_begin() == dstBlock)
|
||||
return lazyCreate(vals[idx].first);
|
||||
assert(*(block->succ_begin()+1) == dstBlock);
|
||||
return lazyCreate(vals[idx].second);
|
||||
}
|
||||
|
||||
assert(vals[idx].second == 0);
|
||||
return lazyCreate(vals[idx].first);
|
||||
}
|
||||
|
||||
BVPair &CFGBlockValues::getValueVectors(const clang::CFGBlock *block,
|
||||
bool shouldLazyCreate) {
|
||||
unsigned idx = block->getBlockID();
|
||||
lazyCreate(vals[idx].first);
|
||||
if (shouldLazyCreate)
|
||||
lazyCreate(vals[idx].second);
|
||||
return vals[idx];
|
||||
unsigned decls = declToIndex.size();
|
||||
scratch.resize(decls);
|
||||
unsigned n = cfg.getNumBlockIDs();
|
||||
if (!n)
|
||||
return;
|
||||
vals.resize(n);
|
||||
for (unsigned i = 0; i < n; ++i)
|
||||
vals[i] = new ValueVector(decls);
|
||||
}
|
||||
|
||||
#if DEBUG_LOGGING
|
||||
|
@ -249,7 +181,7 @@ void CFGBlockValues::mergeIntoScratch(ValueVector const &source,
|
|||
}
|
||||
|
||||
bool CFGBlockValues::updateValueVectorWithScratch(const CFGBlock *block) {
|
||||
ValueVector &dst = getValueVector(block, 0);
|
||||
ValueVector &dst = getValueVector(block);
|
||||
bool changed = (dst != scratch);
|
||||
if (changed)
|
||||
dst = scratch;
|
||||
|
@ -259,20 +191,6 @@ bool CFGBlockValues::updateValueVectorWithScratch(const CFGBlock *block) {
|
|||
return changed;
|
||||
}
|
||||
|
||||
bool CFGBlockValues::updateValueVectors(const CFGBlock *block,
|
||||
const BVPair &newVals) {
|
||||
BVPair &vals = getValueVectors(block, true);
|
||||
bool changed = *newVals.first != *vals.first ||
|
||||
*newVals.second != *vals.second;
|
||||
*vals.first = *newVals.first;
|
||||
*vals.second = *newVals.second;
|
||||
#if DEBUG_LOGGING
|
||||
printVector(block, *vals.first, 1);
|
||||
printVector(block, *vals.second, 2);
|
||||
#endif
|
||||
return changed;
|
||||
}
|
||||
|
||||
void CFGBlockValues::resetScratch() {
|
||||
scratch.reset();
|
||||
}
|
||||
|
@ -768,42 +686,15 @@ static bool runOnBlock(const CFGBlock *block, const CFG &cfg,
|
|||
const ClassifyRefs &classification,
|
||||
llvm::BitVector &wasAnalyzed,
|
||||
UninitVariablesHandler *handler = 0) {
|
||||
|
||||
wasAnalyzed[block->getBlockID()] = true;
|
||||
|
||||
if (const BinaryOperator *b = getLogicalOperatorInChain(block)) {
|
||||
CFGBlock::const_pred_iterator itr = block->pred_begin();
|
||||
BVPair vA = vals.getValueVectors(*itr, false);
|
||||
++itr;
|
||||
BVPair vB = vals.getValueVectors(*itr, false);
|
||||
|
||||
BVPair valsAB;
|
||||
|
||||
if (b->getOpcode() == BO_LAnd) {
|
||||
// Merge the 'F' bits from the first and second.
|
||||
vals.mergeIntoScratch(*(vA.second ? vA.second : vA.first), true);
|
||||
vals.mergeIntoScratch(*(vB.second ? vB.second : vB.first), false);
|
||||
valsAB.first = vA.first;
|
||||
valsAB.second = &vals.getScratch();
|
||||
} else {
|
||||
// Merge the 'T' bits from the first and second.
|
||||
assert(b->getOpcode() == BO_LOr);
|
||||
vals.mergeIntoScratch(*vA.first, true);
|
||||
vals.mergeIntoScratch(*vB.first, false);
|
||||
valsAB.first = &vals.getScratch();
|
||||
valsAB.second = vA.second ? vA.second : vA.first;
|
||||
}
|
||||
return vals.updateValueVectors(block, valsAB);
|
||||
}
|
||||
|
||||
// Default behavior: merge in values of predecessor blocks.
|
||||
vals.resetScratch();
|
||||
// Merge in values of predecessor blocks.
|
||||
bool isFirst = true;
|
||||
for (CFGBlock::const_pred_iterator I = block->pred_begin(),
|
||||
E = block->pred_end(); I != E; ++I) {
|
||||
const CFGBlock *pred = *I;
|
||||
if (wasAnalyzed[pred->getBlockID()]) {
|
||||
vals.mergeIntoScratch(vals.getValueVector(pred, block), isFirst);
|
||||
vals.mergeIntoScratch(vals.getValueVector(pred), isFirst);
|
||||
isFirst = false;
|
||||
}
|
||||
}
|
||||
|
@ -828,9 +719,6 @@ void clang::runUninitializedVariablesAnalysis(
|
|||
vals.computeSetOfDeclarations(dc);
|
||||
if (vals.hasNoDeclarations())
|
||||
return;
|
||||
#if DEBUG_LOGGING
|
||||
cfg.dump(dc.getParentASTContext().getLangOpts(), true);
|
||||
#endif
|
||||
|
||||
stats.NumVariablesAnalyzed = vals.getNumEntries();
|
||||
|
||||
|
@ -840,15 +728,10 @@ void clang::runUninitializedVariablesAnalysis(
|
|||
|
||||
// Mark all variables uninitialized at the entry.
|
||||
const CFGBlock &entry = cfg.getEntry();
|
||||
for (CFGBlock::const_succ_iterator i = entry.succ_begin(),
|
||||
e = entry.succ_end(); i != e; ++i) {
|
||||
if (const CFGBlock *succ = *i) {
|
||||
ValueVector &vec = vals.getValueVector(&entry, succ);
|
||||
const unsigned n = vals.getNumEntries();
|
||||
for (unsigned j = 0; j < n ; ++j) {
|
||||
vec[j] = Uninitialized;
|
||||
}
|
||||
}
|
||||
ValueVector &vec = vals.getValueVector(&entry);
|
||||
const unsigned n = vals.getNumEntries();
|
||||
for (unsigned j = 0; j < n ; ++j) {
|
||||
vec[j] = Uninitialized;
|
||||
}
|
||||
|
||||
// Proceed with the workist.
|
||||
|
|
Loading…
Reference in New Issue