Fix incorrect localization when encountering non-leaf functions.

Fixes #3286.
This commit is contained in:
Geza Lore
2022-04-09 20:30:39 +01:00
parent 9be4e7b576
commit c79ea88576
4 changed files with 129 additions and 5 deletions
+23 -5
View File
@@ -40,15 +40,15 @@ class LocalizeVisitor final : public VNVisitor {
private:
// NODE STATE
// AstVarScope::user1() -> Bool indicating VarScope is not optimizable.
// AstCFunc::user1() -> Bool indicating CFunc is not a leaf function.
// AstVarScope::user2() -> Bool indicating VarScope was fully assigned in the current
// function.
// AstVarScope::user3p() -> Set of CFuncs referencing this VarScope. (via m_accessors)
// AstCFunc::user4p() -> Multimap of 'VarScope -> VarRefs that reference that VarScope'
// in this function. (via m_references)
const VNUser1InUse m_inuser1;
const VNUser2InUse m_inuser2;
const VNUser3InUse m_inuser3;
const VNUser4InUse m_inuser4;
const VNUser1InUse m_user1InUse;
const VNUser3InUse m_user3InUse;
const VNUser4InUse m_user4InUse;
AstUser3Allocator<AstVarScope, std::unordered_set<AstCFunc*>> m_accessors;
AstUser4Allocator<AstCFunc, std::unordered_multimap<const AstVarScope*, AstVarRef*>>
@@ -69,6 +69,13 @@ private:
&& m_accessors(nodep).size() == 1); // .. a block temp used in a single CFunc
}
bool existsNonLeaf(const std::unordered_set<AstCFunc*>& funcps) {
for (const AstCFunc* const funcp : funcps) {
if (funcp->user1()) return true;
}
return false;
}
void moveVarScopes() {
for (AstVarScope* const nodep : m_varScopeps) {
if (!isOptimizable(nodep)) continue; // Not optimizable
@@ -76,6 +83,12 @@ private:
const std::unordered_set<AstCFunc*>& funcps = m_accessors(nodep);
if (funcps.empty()) continue; // No referencing functions at all
// If more than one referencing function, but not all are leaf
// functions, then don't localize, as one of the referencing
// functions might be calling another, which the current analysis
// cannot cope with. This should be rare (introduced by V3Depth).
if (funcps.size() > 1 && existsNonLeaf(funcps)) continue;
UINFO(4, "Localizing " << nodep << endl);
++m_statLocVars;
@@ -121,11 +134,16 @@ private:
{
m_cfuncp = nodep;
m_nodeDepth = 0;
AstNode::user2ClearTree(); // Check each function independently
const VNUser2InUse user2InUse;
iterateChildrenConst(nodep);
}
}
virtual void visit(AstCCall* nodep) override {
m_cfuncp->user1(true); // Mark caller as not a leaf function
iterateChildrenConst(nodep);
}
virtual void visit(AstNodeAssign* nodep) override {
// Analyze RHS first so "a = a + 1" is detected as a read before write
iterate(nodep->rhsp());