diff --git a/src/V3Ast.cpp b/src/V3Ast.cpp index f135d5fcc..3d36866e6 100644 --- a/src/V3Ast.cpp +++ b/src/V3Ast.cpp @@ -613,11 +613,14 @@ AstNode* AstNode::unlinkFrBackWithNext(VNRelinker* linkerp) { backp->m_nextp = nullptr; // Old list gets truncated // New list becomes a list upon itself - // Most common case is unlinking a entire operand tree - // (else we'd probably call unlinkFrBack without next) - // We may be in the middle of a list; we have no way to find head or tail! - AstNode* oldtailp = oldp; - while (oldtailp->m_nextp) oldtailp = oldtailp->m_nextp; + // Most common case is unlinking a entire operand tree, or all but the + // head (else we'd probably call unlinkFrBack without next) + AstNode* oldtailp = backp->m_headtailp; + if (!oldtailp) { + // We are in the middle of a list; we have no way to find head or tail in O(1) + oldtailp = oldp; + while (oldtailp->m_nextp) oldtailp = oldtailp->m_nextp; + } // Create new head/tail of old list AstNode* const oldheadp = oldtailp->m_headtailp; oldheadp->m_headtailp = oldp->m_backp; diff --git a/src/V3Ast.h b/src/V3Ast.h index 0b89c57a8..165e2ee44 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -427,7 +427,7 @@ class AstNode VL_NOT_FINAL { #endif AstNodeDType* m_dtypep = nullptr; // Data type of output or assignment (etc) - AstNode* m_headtailp; // When at begin/end of list, the opposite end of the list + AstNode* m_headtailp; // When at begin/end of list, the opposite end of the list, else nullptr FileLine* m_fileline; // Where it was declared #ifdef VL_DEBUG // Only keep track of the edit count in the node in the debug build.