diff --git a/src/V3Ast.cpp b/src/V3Ast.cpp index d64fda835..a2144f15e 100644 --- a/src/V3Ast.cpp +++ b/src/V3Ast.cpp @@ -94,6 +94,15 @@ void AstNode::init() { m_user5Cnt = 0; } +AstNode* AstNode::abovep() const { + // m_headtailp only valid at beginning or end of list + // Avoid supporting at other locations as would require walking + // list which is likely to cause performance issues. + UASSERT_OBJ(!m_nextp || firstAbovep(), this, "abovep() not allowed when in midlist"); + const AstNode* firstp = firstAbovep() ? this : m_headtailp; + return firstp->backp(); +} + string AstNode::encodeName(const string& namein) { // Encode signal name raw from parser, then not called again on same signal string out; diff --git a/src/V3Ast.h b/src/V3Ast.h index 77b092e4c..f8ebc2afb 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -1243,6 +1243,7 @@ public: const char* typeName() const { return type().ascii(); } // See also prettyTypeName AstNode* nextp() const { return m_nextp; } AstNode* backp() const { return m_backp; } + AstNode* abovep() const; // Parent node above, only when no nextp() as otherwise slow AstNode* op1p() const { return m_op1p; } AstNode* op2p() const { return m_op2p; } AstNode* op3p() const { return m_op3p; } diff --git a/src/V3Const.cpp b/src/V3Const.cpp index 925c74192..0cc2c266f 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -2180,7 +2180,20 @@ private: virtual void visit(AstJumpGo* nodep) { iterateChildren(nodep); m_hasJumpGo = true; - if (m_doExpensive) { nodep->labelp()->user4(true); } + if (m_doExpensive) { + // If last statement in a jump label we have JumpLabel(...., JumpGo) + // Often caused by "return" in a Verilog function. The Go is pointless, remove. + if (!nodep->nextp()) { + if (AstJumpLabel* aboveLabelp = VN_CAST(nodep->abovep(), JumpLabel)) { + if (aboveLabelp == nodep->labelp()) { + UINFO(4, "JUMPGO => last remove "<unlinkFrBack()->deleteTree(); VL_DANGLING(nodep); + return; + } + } + } + nodep->labelp()->user4(true); + } } virtual void visit(AstJumpLabel* nodep) {