From cb5f038060817f45973ed62aa6a2585ca931f8d3 Mon Sep 17 00:00:00 2001 From: Geza Lore Date: Wed, 5 Nov 2025 15:55:30 +0000 Subject: [PATCH] Internals: Optimzie unlinking rest of list after head (tail) (#6643) AstNode::unlinkFrBackWithNext is O(n) if the subject node is not the head of the list. We sometimes want to unlink the rest of the list starting at the node after the head (e.g.: in V3Sched::util::splitCheck), this patch makes that O(1) as well. --- src/V3Ast.cpp | 13 ++++++++----- src/V3Ast.h | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) 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.