From 9a0f94faa4269ce5cfe93db3ec44f54e52b835e5 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Fri, 19 Dec 2025 00:38:47 +0000 Subject: [PATCH] Defer redirecting cell outputs when merging cells in `opt_merge` until after we've done a full pass over the cells. This avoids changing `assign_map` and `initvals`, which are inputs to the hash function for `known_cells`, while `known_cells` exists. Changing the hash function for a hashtable while it exists leads to confusing behavior. That also means the exact behavior of `opt_merge` cannot be reproduced by a parallel implementation. --- passes/opt/opt_merge.cc | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/passes/opt/opt_merge.cc b/passes/opt/opt_merge.cc index 6cdcbc822..89d725b9a 100644 --- a/passes/opt/opt_merge.cc +++ b/passes/opt/opt_merge.cc @@ -284,6 +284,7 @@ struct OptMergeWorker CellPtrHash, CellPtrEqual> known_cells (0, CellPtrHash(*this), CellPtrEqual(*this)); + std::vector redirects; for (auto cell : cells) { auto [cell_in_map, inserted] = known_cells.insert(cell); @@ -305,12 +306,7 @@ struct OptMergeWorker RTLIL::SigSpec other_sig = other_cell->getPort(it.first); log_debug(" Redirecting output %s: %s = %s\n", it.first, log_signal(it.second), log_signal(other_sig)); - Const init = initvals(other_sig); - initvals.remove_init(it.second); - initvals.remove_init(other_sig); - module->connect(RTLIL::SigSig(it.second, other_sig)); - assign_map.add(it.second, other_sig); - initvals.set_init(other_sig, init); + redirects.push_back(RTLIL::SigSig(it.second, std::move(other_sig))); } } log_debug(" Removing %s cell `%s' from module `%s'.\n", cell->type, cell->name, module->name); @@ -318,6 +314,14 @@ struct OptMergeWorker total_count++; } } + for (const RTLIL::SigSig &redirect : redirects) { + module->connect(redirect); + Const init = initvals(redirect.second); + initvals.remove_init(redirect.first); + initvals.remove_init(redirect.second); + assign_map.add(redirect.first, redirect.second); + initvals.set_init(redirect.second, init); + } } log_suppressed();