From 282b898b210ec8f706aab4ab05065a2174dccc0b Mon Sep 17 00:00:00 2001 From: Pawel Kojma Date: Wed, 16 Sep 2026 17:23:34 +0200 Subject: [PATCH] Use VIsCached for checking purity of arguments in AstCMethodHard (#8350) --- src/V3AstNodeExpr.h | 10 ++++++---- src/V3AstNodes.cpp | 29 ++++++++++++----------------- 2 files changed, 18 insertions(+), 21 deletions(-) diff --git a/src/V3AstNodeExpr.h b/src/V3AstNodeExpr.h index ac931b6c0..5770118b2 100644 --- a/src/V3AstNodeExpr.h +++ b/src/V3AstNodeExpr.h @@ -750,7 +750,7 @@ class AstCMethodHard final : public AstNodeExpr { // @astgen op2 := pinsp : List[AstNodeExpr] // Arguments // @astgen op3 := withp : Optional[AstWith] // With clause VCMethod m_method; // Which method to call - bool m_pure = false; // Pure optimizable + VIsCached m_purity; // Pure optimizable bool m_usePtr = false; // Use '->' not '.' public: AstCMethodHard(FileLine* fl, AstNodeExpr* fromp, VCMethod method, AstNodeExpr* pinsp = nullptr) @@ -758,7 +758,6 @@ public: , m_method{method} { this->fromp(fromp); addPinsp(pinsp); - setPurity(); } ASTGEN_MEMBERS_AstCMethodHard; void dump(std::ostream& str) const override; @@ -768,7 +767,10 @@ public: const AstCMethodHard* const asamep = VN_DBG_AS(samep, CMethodHard); return (m_method == asamep->m_method); } - bool isPure() override { return m_pure; } + bool isPure() override { + if (!m_purity.isCached()) m_purity.set(getPurity()); + return m_purity.get(); + } int instrCount() const override; string emitVerilog() override { V3ERROR_NA_RETURN(""); } string emitC() override { V3ERROR_NA_RETURN(""); } @@ -779,7 +781,7 @@ public: void method(VCMethod value) { m_method = value; } private: - void setPurity(); + bool getPurity(); }; class AstCReset final : public AstNodeExpr { // Reset variable at startup diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index 6f1a78748..81b3d73da 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -588,39 +588,34 @@ void AstCFunc::dumpJson(std::ostream& str) const { } void AstCMethodHard::dump(std::ostream& str) const { Super::dump(str); - if (m_pure) str << " [PURE]"; + if (m_purity.get()) str << " [PURE]"; if (usePtr()) str << " [USEPTR]"; } void AstCMethodHard::dumpJson(std::ostream& str) const { - dumpJsonBoolIf(str, "pure", m_pure); + dumpJsonBoolIf(str, "pure", m_purity.get()); dumpJsonBoolIf(str, "usePtr", usePtr()); dumpJsonGen(str); } -int AstCMethodHard::instrCount() const { - return 0; // TODO -} -void AstCMethodHard::setPurity() { +bool AstCMethodHard::getPurity() { if (method() == VCMethod::DYN_AT_WRITE_APPEND || method() == VCMethod::DYN_AT_WRITE_APPEND_BACK) { - m_pure = false; // Treat atWriteAppend as pure if the argument is a loop iterator if (const AstNodeExpr* const argp = pinsp()) { if (const AstVarRef* const varrefp = VN_CAST(argp, VarRef)) { - if (varrefp->varp()->isUsedLoopIdx()) m_pure = true; + if (varrefp->varp()->isUsedLoopIdx()) return true; } } - return; + return false; } - m_pure = method().isPure(); - if (!m_pure) return; - if (!fromp()->isPure()) m_pure = false; - if (!m_pure) return; + if (!method().isPure()) return false; + if (!fromp()->isPure()) return false; for (AstNodeExpr* argp = pinsp(); argp; argp = VN_AS(argp->nextp(), NodeExpr)) { - if (!argp->isPure()) { - m_pure = false; - return; - } + if (!argp->isPure()) return false; } + return true; +} +int AstCMethodHard::instrCount() const { + return 0; // TODO } void AstCReset::dump(std::ostream& str) const { Super::dump(str);