Fix purity calculation during V3Const simplifying Ast
This commit is contained in:
parent
46f8a659b3
commit
684aba0e90
|
|
@ -33,7 +33,7 @@ VL_DEFINE_DEBUG_FUNCTIONS;
|
||||||
//======================================================================
|
//======================================================================
|
||||||
// Statics
|
// Statics
|
||||||
|
|
||||||
uint32_t VIsCached::s_cachedCntGbl = 1;
|
uint64_t VIsCached::s_cachedCntGbl = 1;
|
||||||
|
|
||||||
uint64_t AstNode::s_editCntLast = 0;
|
uint64_t AstNode::s_editCntLast = 0;
|
||||||
uint64_t AstNode::s_editCntGbl = 0; // Hot cache line
|
uint64_t AstNode::s_editCntGbl = 0; // Hot cache line
|
||||||
|
|
|
||||||
11
src/V3Ast.h
11
src/V3Ast.h
|
|
@ -171,10 +171,9 @@ class VIsCached final {
|
||||||
// Used in some nodes to cache results of boolean methods
|
// Used in some nodes to cache results of boolean methods
|
||||||
// If cachedCnt == 0, not cached
|
// If cachedCnt == 0, not cached
|
||||||
// else if cachedCnt == s_cachedCntGbl, then m_state is if cached
|
// else if cachedCnt == s_cachedCntGbl, then m_state is if cached
|
||||||
uint32_t m_cachedCnt : 31; // Mark of when cache was computed
|
uint64_t m_cachedCnt : 63; // Mark of when cache was computed
|
||||||
uint32_t m_state : 1;
|
uint64_t m_state : 1;
|
||||||
static uint32_t s_cachedCntGbl; // Global computed count
|
static uint64_t s_cachedCntGbl; // Global computed count
|
||||||
static constexpr uint32_t MAX_CNT = (1UL << 31) - 1; // Max for m_cachedCnt
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
VIsCached()
|
VIsCached()
|
||||||
|
|
@ -192,7 +191,8 @@ public:
|
||||||
}
|
}
|
||||||
static void clearCacheTree() {
|
static void clearCacheTree() {
|
||||||
++s_cachedCntGbl;
|
++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; }
|
uint64_t editCount() const { return m_editCount; }
|
||||||
void editCountInc() {
|
void editCountInc() {
|
||||||
m_editCount = ++s_editCntGbl; // Preincrement, so can "watch AstNode::s_editCntGbl=##"
|
m_editCount = ++s_editCntGbl; // Preincrement, so can "watch AstNode::s_editCntGbl=##"
|
||||||
|
VIsCached::clearCacheTree(); // Any edit clears all caching
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
void editCountInc() { ++s_editCntGbl; }
|
void editCountInc() { ++s_editCntGbl; }
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,6 @@ public:
|
||||||
|
|
||||||
// Wrap This expression into an AstStmtExpr to denote it occurs in statement position
|
// Wrap This expression into an AstStmtExpr to denote it occurs in statement position
|
||||||
inline AstStmtExpr* makeStmt();
|
inline AstStmtExpr* makeStmt();
|
||||||
virtual void clearCachedPurity(){}; // Most nodes don't cache their purity
|
|
||||||
};
|
};
|
||||||
class AstNodeBiop VL_NOT_FINAL : public AstNodeExpr {
|
class AstNodeBiop VL_NOT_FINAL : public AstNodeExpr {
|
||||||
// Binary expression
|
// Binary expression
|
||||||
|
|
@ -98,7 +97,6 @@ public:
|
||||||
bool same(const AstNode*) const override { return true; }
|
bool same(const AstNode*) const override { return true; }
|
||||||
bool isPure() override;
|
bool isPure() override;
|
||||||
const char* broken() const override;
|
const char* broken() const override;
|
||||||
void clearCachedPurity() override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool getPurityRecurse() const { return lhsp()->isPure() && rhsp()->isPure(); }
|
bool getPurityRecurse() const { return lhsp()->isPure() && rhsp()->isPure(); }
|
||||||
|
|
@ -265,7 +263,6 @@ public:
|
||||||
string emitVerilog() final override { V3ERROR_NA_RETURN(""); }
|
string emitVerilog() final override { V3ERROR_NA_RETURN(""); }
|
||||||
string emitC() final override { V3ERROR_NA_RETURN(""); }
|
string emitC() final override { V3ERROR_NA_RETURN(""); }
|
||||||
bool cleanOut() const final override { V3ERROR_NA_RETURN(true); }
|
bool cleanOut() const final override { V3ERROR_NA_RETURN(true); }
|
||||||
void clearCachedPurity() override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool getPurityRecurse() const;
|
bool getPurityRecurse() const;
|
||||||
|
|
@ -296,7 +293,6 @@ public:
|
||||||
bool cleanOut() const final override { V3ERROR_NA_RETURN(true); }
|
bool cleanOut() const final override { V3ERROR_NA_RETURN(true); }
|
||||||
bool isPure() override;
|
bool isPure() override;
|
||||||
const char* broken() const override;
|
const char* broken() const override;
|
||||||
void clearCachedPurity() override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool getPurityRecurse() const {
|
bool getPurityRecurse() const {
|
||||||
|
|
@ -340,7 +336,6 @@ public:
|
||||||
bool same(const AstNode*) const override { return true; }
|
bool same(const AstNode*) const override { return true; }
|
||||||
bool isPure() override;
|
bool isPure() override;
|
||||||
const char* broken() const override;
|
const char* broken() const override;
|
||||||
void clearCachedPurity() override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool getPurityRecurse() const {
|
bool getPurityRecurse() const {
|
||||||
|
|
@ -393,7 +388,6 @@ public:
|
||||||
bool same(const AstNode*) const override { return true; }
|
bool same(const AstNode*) const override { return true; }
|
||||||
bool isPure() override;
|
bool isPure() override;
|
||||||
const char* broken() const override;
|
const char* broken() const override;
|
||||||
void clearCachedPurity() override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool getPurityRecurse() const {
|
bool getPurityRecurse() const {
|
||||||
|
|
@ -473,7 +467,6 @@ public:
|
||||||
bool same(const AstNode*) const override { return true; }
|
bool same(const AstNode*) const override { return true; }
|
||||||
bool isPure() override;
|
bool isPure() override;
|
||||||
const char* broken() const override;
|
const char* broken() const override;
|
||||||
void clearCachedPurity() override;
|
|
||||||
};
|
};
|
||||||
class AstNodeSystemUniopD VL_NOT_FINAL : public AstNodeUniop {
|
class AstNodeSystemUniopD VL_NOT_FINAL : public AstNodeUniop {
|
||||||
public:
|
public:
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
bool AstNodeFTaskRef::getPurityRecurse() const {
|
||||||
AstNodeFTask* const taskp = this->taskp();
|
AstNodeFTask* const taskp = this->taskp();
|
||||||
// Unlinked yet, so treat as impure
|
// 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());
|
BROKEN_RTN(m_purity.isCached() && m_purity.get() != lhsp()->isPure());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
void AstNodeUniop::clearCachedPurity() {
|
|
||||||
m_purity.clearCache();
|
|
||||||
if (AstNodeExpr* const exprp = VN_CAST(backp(), NodeExpr)) exprp->clearCachedPurity();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AstNodeBiop::isPure() {
|
bool AstNodeBiop::isPure() {
|
||||||
if (!m_purity.isCached()) m_purity.set(getPurityRecurse());
|
if (!m_purity.isCached()) m_purity.set(getPurityRecurse());
|
||||||
return m_purity.get();
|
return m_purity.get();
|
||||||
|
|
@ -165,10 +155,6 @@ const char* AstNodeBiop::broken() const {
|
||||||
BROKEN_RTN(m_purity.isCached() && m_purity.get() != getPurityRecurse());
|
BROKEN_RTN(m_purity.isCached() && m_purity.get() != getPurityRecurse());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
void AstNodeBiop::clearCachedPurity() {
|
|
||||||
m_purity.clearCache();
|
|
||||||
if (AstNodeExpr* const exprp = VN_CAST(backp(), NodeExpr)) exprp->clearCachedPurity();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AstNodeTriop::isPure() {
|
bool AstNodeTriop::isPure() {
|
||||||
if (!m_purity.isCached()) m_purity.set(getPurityRecurse());
|
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());
|
BROKEN_RTN(m_purity.isCached() && m_purity.get() != getPurityRecurse());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
void AstNodeTriop::clearCachedPurity() {
|
|
||||||
m_purity.clearCache();
|
|
||||||
if (AstNodeExpr* const exprp = VN_CAST(backp(), NodeExpr)) exprp->clearCachedPurity();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AstNodePreSel::isPure() {
|
bool AstNodePreSel::isPure() {
|
||||||
if (!m_purity.isCached()) m_purity.set(getPurityRecurse());
|
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());
|
BROKEN_RTN(m_purity.isCached() && m_purity.get() != getPurityRecurse());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
void AstNodePreSel::clearCachedPurity() {
|
|
||||||
m_purity.clearCache();
|
|
||||||
if (AstNodeExpr* const exprp = VN_CAST(backp(), NodeExpr)) exprp->clearCachedPurity();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AstNodeQuadop::isPure() {
|
bool AstNodeQuadop::isPure() {
|
||||||
if (!m_purity.isCached()) m_purity.set(getPurityRecurse());
|
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());
|
BROKEN_RTN(m_purity.isCached() && m_purity.get() != getPurityRecurse());
|
||||||
return nullptr;
|
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,
|
AstNodeCond::AstNodeCond(VNType t, FileLine* fl, AstNodeExpr* condp, AstNodeExpr* thenp,
|
||||||
AstNodeExpr* elsep)
|
AstNodeExpr* elsep)
|
||||||
|
|
|
||||||
|
|
@ -174,7 +174,7 @@ private:
|
||||||
// MethodCalls not currently supported by inliner, so keep linked
|
// MethodCalls not currently supported by inliner, so keep linked
|
||||||
if (!nodep->classOrPackagep() && !VN_IS(nodep, MethodCall)) {
|
if (!nodep->classOrPackagep() && !VN_IS(nodep, MethodCall)) {
|
||||||
nodep->taskp(nullptr);
|
nodep->taskp(nullptr);
|
||||||
nodep->clearCachedPurity();
|
VIsCached::clearCacheTree();
|
||||||
}
|
}
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3726,6 +3726,7 @@ public:
|
||||||
// Link class functions
|
// Link class functions
|
||||||
|
|
||||||
void V3LinkDot::linkDotGuts(AstNetlist* rootp, VLinkDotStep step) {
|
void V3LinkDot::linkDotGuts(AstNetlist* rootp, VLinkDotStep step) {
|
||||||
|
VIsCached::clearCacheTree(); // Avoid using any stale isPure
|
||||||
if (debug() >= 5 || dumpTreeLevel() >= 9) {
|
if (debug() >= 5 || dumpTreeLevel() >= 9) {
|
||||||
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("prelinkdot.tree"));
|
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("prelinkdot.tree"));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -331,7 +331,7 @@ private:
|
||||||
// We're going to need the expression several times in the expanded code,
|
// We're going to need the expression several times in the expanded code,
|
||||||
// so might as well make it a common expression
|
// so might as well make it a common expression
|
||||||
createDeepTemp(nodep->condp(), false);
|
createDeepTemp(nodep->condp(), false);
|
||||||
nodep->clearCachedPurity();
|
VIsCached::clearCacheTree();
|
||||||
}
|
}
|
||||||
checkNode(nodep);
|
checkNode(nodep);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -396,7 +396,7 @@ private:
|
||||||
UINFO(9, " New pkg-taskref " << nodep << endl);
|
UINFO(9, " New pkg-taskref " << nodep << endl);
|
||||||
} else if (!VN_IS(nodep, MethodCall)) {
|
} else if (!VN_IS(nodep, MethodCall)) {
|
||||||
nodep->taskp(nullptr);
|
nodep->taskp(nullptr);
|
||||||
nodep->clearCachedPurity();
|
VIsCached::clearCacheTree();
|
||||||
UINFO(9, " New pkg-taskref " << nodep << endl);
|
UINFO(9, " New pkg-taskref " << nodep << endl);
|
||||||
}
|
}
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
|
|
|
||||||
|
|
@ -1469,9 +1469,9 @@ private:
|
||||||
beginp = new AstExprStmt{nodep->fileline(), beginp, outrefp};
|
beginp = new AstExprStmt{nodep->fileline(), beginp, outrefp};
|
||||||
// AstExprStmt is currently treated as impure, so clear the cached purity of its
|
// AstExprStmt is currently treated as impure, so clear the cached purity of its
|
||||||
// parents
|
// parents
|
||||||
nodep->clearCachedPurity();
|
|
||||||
nodep->replaceWith(beginp);
|
nodep->replaceWith(beginp);
|
||||||
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
||||||
|
VIsCached::clearCacheTree();
|
||||||
} else {
|
} else {
|
||||||
insertBeforeStmt(nodep, beginp);
|
insertBeforeStmt(nodep, beginp);
|
||||||
if (nodep->taskp()->isFunction()) {
|
if (nodep->taskp()->isFunction()) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue