[NFC] Fix quadratic LexicalScopes::constructScopeNest

We sometimes have functions with large numbers of sibling basic
blocks (usually with an error path exit from each one). This was
triggering the qudratic behavior in this function - after visiting
each child llvm would re-scan the parent from the beginning again. We
modify the work stack to record the next index to be worked on
alongside the pointer. This avoids the need to linearly search for
the next unfinished child.

Differential Revision: https://reviews.llvm.org/D80029
This commit is contained in:
Jan-Willem Maessen 2020-06-08 18:38:16 +01:00 committed by Jeremy Morse
parent caa2fddce7
commit 3610d31e7a
1 changed files with 13 additions and 13 deletions

View File

@ -230,24 +230,24 @@ LexicalScopes::getOrCreateAbstractScope(const DILocalScope *Scope) {
return &I->second; return &I->second;
} }
/// constructScopeNest /// constructScopeNest - Traverse the Scope tree depth-first, storing
/// traversal state in WorkStack and recording the depth-first
/// numbering (setDFSIn, setDFSOut) for edge classification.
void LexicalScopes::constructScopeNest(LexicalScope *Scope) { void LexicalScopes::constructScopeNest(LexicalScope *Scope) {
assert(Scope && "Unable to calculate scope dominance graph!"); assert(Scope && "Unable to calculate scope dominance graph!");
SmallVector<LexicalScope *, 4> WorkStack; SmallVector<std::pair<LexicalScope *, size_t>, 4> WorkStack;
WorkStack.push_back(Scope); WorkStack.push_back(std::make_pair(Scope, 0));
unsigned Counter = 0; unsigned Counter = 0;
while (!WorkStack.empty()) { while (!WorkStack.empty()) {
LexicalScope *WS = WorkStack.back(); auto &ScopePosition = WorkStack.back();
LexicalScope *WS = ScopePosition.first;
size_t ChildNum = ScopePosition.second++;
const SmallVectorImpl<LexicalScope *> &Children = WS->getChildren(); const SmallVectorImpl<LexicalScope *> &Children = WS->getChildren();
bool visitedChildren = false; if (ChildNum < Children.size()) {
for (auto &ChildScope : Children) auto &ChildScope = Children[ChildNum];
if (!ChildScope->getDFSOut()) { WorkStack.push_back(std::make_pair(ChildScope, 0));
WorkStack.push_back(ChildScope); ChildScope->setDFSIn(++Counter);
visitedChildren = true; } else {
ChildScope->setDFSIn(++Counter);
break;
}
if (!visitedChildren) {
WorkStack.pop_back(); WorkStack.pop_back();
WS->setDFSOut(++Counter); WS->setDFSOut(++Counter);
} }