diff --git a/src/V3Ast.cpp b/src/V3Ast.cpp index 6115dabf8..e85a2f980 100644 --- a/src/V3Ast.cpp +++ b/src/V3Ast.cpp @@ -33,7 +33,7 @@ VL_DEFINE_DEBUG_FUNCTIONS; //====================================================================== // Statics -uint32_t VIsCached::s_cachedCntGbl = 1; +uint64_t VIsCached::s_cachedCntGbl = 1; uint64_t AstNode::s_editCntLast = 0; uint64_t AstNode::s_editCntGbl = 0; // Hot cache line diff --git a/src/V3Ast.h b/src/V3Ast.h index 38dba7714..7fb97634d 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -171,10 +171,9 @@ class VIsCached final { // Used in some nodes to cache results of boolean methods // If cachedCnt == 0, not cached // else if cachedCnt == s_cachedCntGbl, then m_state is if cached - uint32_t m_cachedCnt : 31; // Mark of when cache was computed - uint32_t m_state : 1; - static uint32_t s_cachedCntGbl; // Global computed count - static constexpr uint32_t MAX_CNT = (1UL << 31) - 1; // Max for m_cachedCnt + uint64_t m_cachedCnt : 63; // Mark of when cache was computed + uint64_t m_state : 1; + static uint64_t s_cachedCntGbl; // Global computed count public: VIsCached() @@ -192,7 +191,8 @@ public: } static void clearCacheTree() { ++s_cachedCntGbl; - UASSERT_STATIC(s_cachedCntGbl < MAX_CNT, "Overflow of cache counting"); + // 64 bits so won't overflow + // UASSERT_STATIC(s_cachedCntGbl < MAX_CNT, "Overflow of cache counting"); } }; @@ -1956,6 +1956,7 @@ public: uint64_t editCount() const { return m_editCount; } void editCountInc() { m_editCount = ++s_editCntGbl; // Preincrement, so can "watch AstNode::s_editCntGbl=##" + VIsCached::clearCacheTree(); // Any edit clears all caching } #else void editCountInc() { ++s_editCntGbl; } diff --git a/src/V3AstNodeExpr.h b/src/V3AstNodeExpr.h index 009e4478b..580c5e3ce 100644 --- a/src/V3AstNodeExpr.h +++ b/src/V3AstNodeExpr.h @@ -64,7 +64,6 @@ public: // Wrap This expression into an AstStmtExpr to denote it occurs in statement position inline AstStmtExpr* makeStmt(); - virtual void clearCachedPurity(){}; // Most nodes don't cache their purity }; class AstNodeBiop VL_NOT_FINAL : public AstNodeExpr { // Binary expression @@ -98,7 +97,6 @@ public: bool same(const AstNode*) const override { return true; } bool isPure() override; const char* broken() const override; - void clearCachedPurity() override; private: bool getPurityRecurse() const { return lhsp()->isPure() && rhsp()->isPure(); } @@ -265,7 +263,6 @@ public: string emitVerilog() final override { V3ERROR_NA_RETURN(""); } string emitC() final override { V3ERROR_NA_RETURN(""); } bool cleanOut() const final override { V3ERROR_NA_RETURN(true); } - void clearCachedPurity() override; private: bool getPurityRecurse() const; @@ -296,7 +293,6 @@ public: bool cleanOut() const final override { V3ERROR_NA_RETURN(true); } bool isPure() override; const char* broken() const override; - void clearCachedPurity() override; private: bool getPurityRecurse() const { @@ -340,7 +336,6 @@ public: bool same(const AstNode*) const override { return true; } bool isPure() override; const char* broken() const override; - void clearCachedPurity() override; private: bool getPurityRecurse() const { @@ -393,7 +388,6 @@ public: bool same(const AstNode*) const override { return true; } bool isPure() override; const char* broken() const override; - void clearCachedPurity() override; private: bool getPurityRecurse() const { @@ -473,7 +467,6 @@ public: bool same(const AstNode*) const override { return true; } bool isPure() override; const char* broken() const override; - void clearCachedPurity() override; }; class AstNodeSystemUniopD VL_NOT_FINAL : public AstNodeUniop { public: diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index 7ba41a926..ccd0c24ed 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -72,11 +72,6 @@ bool AstNodeFTaskRef::isPure() { } } -void AstNodeFTaskRef::clearCachedPurity() { - m_purity.clearCache(); - if (AstNodeExpr* const exprp = VN_CAST(backp(), NodeExpr)) exprp->clearCachedPurity(); -} - bool AstNodeFTaskRef::getPurityRecurse() const { AstNodeFTask* const taskp = this->taskp(); // Unlinked yet, so treat as impure @@ -152,11 +147,6 @@ const char* AstNodeUniop::broken() const { BROKEN_RTN(m_purity.isCached() && m_purity.get() != lhsp()->isPure()); return nullptr; } -void AstNodeUniop::clearCachedPurity() { - m_purity.clearCache(); - if (AstNodeExpr* const exprp = VN_CAST(backp(), NodeExpr)) exprp->clearCachedPurity(); -} - bool AstNodeBiop::isPure() { if (!m_purity.isCached()) m_purity.set(getPurityRecurse()); return m_purity.get(); @@ -165,10 +155,6 @@ const char* AstNodeBiop::broken() const { BROKEN_RTN(m_purity.isCached() && m_purity.get() != getPurityRecurse()); return nullptr; } -void AstNodeBiop::clearCachedPurity() { - m_purity.clearCache(); - if (AstNodeExpr* const exprp = VN_CAST(backp(), NodeExpr)) exprp->clearCachedPurity(); -} bool AstNodeTriop::isPure() { if (!m_purity.isCached()) m_purity.set(getPurityRecurse()); @@ -178,10 +164,6 @@ const char* AstNodeTriop::broken() const { BROKEN_RTN(m_purity.isCached() && m_purity.get() != getPurityRecurse()); return nullptr; } -void AstNodeTriop::clearCachedPurity() { - m_purity.clearCache(); - if (AstNodeExpr* const exprp = VN_CAST(backp(), NodeExpr)) exprp->clearCachedPurity(); -} bool AstNodePreSel::isPure() { if (!m_purity.isCached()) m_purity.set(getPurityRecurse()); @@ -191,10 +173,6 @@ const char* AstNodePreSel::broken() const { BROKEN_RTN(m_purity.isCached() && m_purity.get() != getPurityRecurse()); return nullptr; } -void AstNodePreSel::clearCachedPurity() { - m_purity.clearCache(); - if (AstNodeExpr* const exprp = VN_CAST(backp(), NodeExpr)) exprp->clearCachedPurity(); -} bool AstNodeQuadop::isPure() { if (!m_purity.isCached()) m_purity.set(getPurityRecurse()); @@ -204,10 +182,6 @@ const char* AstNodeQuadop::broken() const { BROKEN_RTN(m_purity.isCached() && m_purity.get() != getPurityRecurse()); return nullptr; } -void AstNodeQuadop::clearCachedPurity() { - m_purity.clearCache(); - if (AstNodeExpr* const exprp = VN_CAST(backp(), NodeExpr)) exprp->clearCachedPurity(); -} AstNodeCond::AstNodeCond(VNType t, FileLine* fl, AstNodeExpr* condp, AstNodeExpr* thenp, AstNodeExpr* elsep) diff --git a/src/V3Inline.cpp b/src/V3Inline.cpp index f704c9fb7..4735bc079 100644 --- a/src/V3Inline.cpp +++ b/src/V3Inline.cpp @@ -174,7 +174,7 @@ private: // MethodCalls not currently supported by inliner, so keep linked if (!nodep->classOrPackagep() && !VN_IS(nodep, MethodCall)) { nodep->taskp(nullptr); - nodep->clearCachedPurity(); + VIsCached::clearCacheTree(); } iterateChildren(nodep); } diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index 7ea95b46f..dd9a6548c 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -3726,6 +3726,7 @@ public: // Link class functions void V3LinkDot::linkDotGuts(AstNetlist* rootp, VLinkDotStep step) { + VIsCached::clearCacheTree(); // Avoid using any stale isPure if (debug() >= 5 || dumpTreeLevel() >= 9) { v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("prelinkdot.tree")); } diff --git a/src/V3Premit.cpp b/src/V3Premit.cpp index 40ffc1c9e..57a5c3826 100644 --- a/src/V3Premit.cpp +++ b/src/V3Premit.cpp @@ -331,7 +331,7 @@ private: // We're going to need the expression several times in the expanded code, // so might as well make it a common expression createDeepTemp(nodep->condp(), false); - nodep->clearCachedPurity(); + VIsCached::clearCacheTree(); } checkNode(nodep); } diff --git a/src/V3Scope.cpp b/src/V3Scope.cpp index c68b14fe8..c60a8c935 100644 --- a/src/V3Scope.cpp +++ b/src/V3Scope.cpp @@ -396,7 +396,7 @@ private: UINFO(9, " New pkg-taskref " << nodep << endl); } else if (!VN_IS(nodep, MethodCall)) { nodep->taskp(nullptr); - nodep->clearCachedPurity(); + VIsCached::clearCacheTree(); UINFO(9, " New pkg-taskref " << nodep << endl); } iterateChildren(nodep); diff --git a/src/V3Task.cpp b/src/V3Task.cpp index 576342885..5e1ce27a0 100644 --- a/src/V3Task.cpp +++ b/src/V3Task.cpp @@ -1469,9 +1469,9 @@ private: beginp = new AstExprStmt{nodep->fileline(), beginp, outrefp}; // AstExprStmt is currently treated as impure, so clear the cached purity of its // parents - nodep->clearCachedPurity(); nodep->replaceWith(beginp); VL_DO_DANGLING(nodep->deleteTree(), nodep); + VIsCached::clearCacheTree(); } else { insertBeforeStmt(nodep, beginp); if (nodep->taskp()->isFunction()) {