Skip to content

[ImportVerilog] Capture analysis should skip reprocessing identical module instances#10338

Merged
jpienaar merged 3 commits into
llvm:mainfrom
rocallahan:capture-analysis-canonical-bodies
May 5, 2026
Merged

[ImportVerilog] Capture analysis should skip reprocessing identical module instances#10338
jpienaar merged 3 commits into
llvm:mainfrom
rocallahan:capture-analysis-canonical-bodies

Conversation

@rocallahan
Copy link
Copy Markdown
Contributor

@rocallahan rocallahan commented Apr 28, 2026

Currently capture analysis unconditionally descends into all module instance bodies. This forces slang to instantiate complete ASTs for all module instances, transitively. For large designs this does not scale. For example with one 7M LOC Verilog example, ImportVerilog consumes more than 200GB of memory before crashing with OOM.

Slang lets clients avoid this problem via "canonical instance bodies" that express deduplication. Setting VisitCanonical to true in the ASTVisitor template causes the InstanceBodySymbol visit to use the deduplicated canonical instance body (when available). For this analysis we don't need to re-analyze duplicate instance so we can just keep track of which bodies we've visited and avoid descending into already-visited bodies.

To make this work correctly we have to also ensure that MLIR generation uses the same canonical module bodies, so e.g. the SubroutineSymbols encountered during MLIR generation are the same SubroutineSymbols that CaptureAnalysis recorded. Currently the importer does its own module deduplication which might choose different slang AST module bodies. So, replace the importer's deduplication with slang's canonical module bodies.

rocallahan added a commit to rocallahan/circt that referenced this pull request Apr 28, 2026
…odule instances (llvm#10338)

Currently capture analysis unconditionally descends into all module instance
bodies. This forces slang to instantiate complete ASTs for all module
instances, transitively. For large designs this does not scale. For example
with one 7M LOC Verilog example, ImportVerilog consumes more than 200GB of
memory before crashing with OOM.

Slang lets clients avoid this problem via "canonical instance bodies"
that express deduplication. Setting `VisitCanonical` to true in the
`ASTVisitor` template causes the `InstanceBodySymbol` visit to use
the deduplicated canonical instance body (when available). For this
analysis we don't need to re-analyze duplicate instance so we can
just keep track of which bodies we've visited and avoid descending
into already-visited bodies.
@rocallahan rocallahan force-pushed the capture-analysis-canonical-bodies branch from 37701f3 to e9d6aed Compare April 28, 2026 00:34
@uenoku uenoku requested review from TaoBi22 and fabianschuiki April 28, 2026 01:04
rocallahan added a commit to rocallahan/circt that referenced this pull request Apr 28, 2026
…odule instances (llvm#10338)

Currently capture analysis unconditionally descends into all module instance
bodies. This forces slang to instantiate complete ASTs for all module
instances, transitively. For large designs this does not scale. For example
with one 7M LOC Verilog example, ImportVerilog consumes more than 200GB of
memory before crashing with OOM.

Slang lets clients avoid this problem via "canonical instance bodies"
that express deduplication. Setting `VisitCanonical` to true in the
`ASTVisitor` template causes the `InstanceBodySymbol` visit to use
the deduplicated canonical instance body (when available). For this
analysis we don't need to re-analyze duplicate instance so we can
just keep track of which bodies we've visited and avoid descending
into already-visited bodies.
@rocallahan rocallahan force-pushed the capture-analysis-canonical-bodies branch from e9d6aed to c206baf Compare April 28, 2026 03:32
Copy link
Copy Markdown
Member

@jpienaar jpienaar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh very nice! I think this can help me drop a lot of bookkeeping I added in another PR too. (seems I can't trigger circt-tests from https://github.com/circt/circt-tests/ which would rerun the larger verilog ones, I think that would help here)

Comment thread lib/Conversion/ImportVerilog/CaptureAnalysis.cpp
Comment thread lib/Conversion/ImportVerilog/ImportVerilogInternals.h
Comment thread lib/Conversion/ImportVerilog/Structure.cpp Outdated
Comment thread lib/Conversion/ImportVerilog/Structure.cpp Outdated
Copy link
Copy Markdown
Contributor

@fabianschuiki fabianschuiki left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is fantastic @rocallahan 🥳. I've been hoping to get rid of that ad-hoc deduplication in the importer at some point. Thanks for doing that! LGTM, modulo @jpienaar's comments.

slang already provides this for us. We should just use it.

Also, by using slang's canonical module bodies, analysis passes that
walk the slang AST can produce results that refer to specific
slang AST objects in canonical module bodies, and we know those
are the exact AST objects we're going to use to generate MLIR.
rocallahan added a commit to rocallahan/circt that referenced this pull request Apr 30, 2026
…odule instances (llvm#10338)

Currently capture analysis unconditionally descends into all module instance
bodies. This forces slang to instantiate complete ASTs for all module
instances, transitively. For large designs this does not scale. For example
with one 7M LOC Verilog example, ImportVerilog consumes more than 200GB of
memory before crashing with OOM.

Slang lets clients avoid this problem via "canonical instance bodies"
that express deduplication. Setting `VisitCanonical` to true in the
`ASTVisitor` template causes the `InstanceBodySymbol` visit to use
the deduplicated canonical instance body (when available). For this
analysis we don't need to re-analyze duplicate instance so we can
just keep track of which bodies we've visited and avoid descending
into already-visited bodies.
@rocallahan rocallahan force-pushed the capture-analysis-canonical-bodies branch from c206baf to e5d7501 Compare April 30, 2026 17:25
…odule instances (llvm#10338)

Currently capture analysis unconditionally descends into all module instance
bodies. This forces slang to instantiate complete ASTs for all module
instances, transitively. For large designs this does not scale. For example
with one 7M LOC Verilog example, ImportVerilog consumes more than 200GB of
memory before crashing with OOM.

Slang lets clients avoid this problem via "canonical instance bodies"
that express deduplication. Setting `VisitCanonical` to true in the
`ASTVisitor` template causes the `InstanceBodySymbol` visit to use
the deduplicated canonical instance body (when available). For this
analysis we don't need to re-analyze duplicate instances, so we can
just keep track of which bodies we've visited and avoid descending
into already-visited bodies.
@rocallahan rocallahan force-pushed the capture-analysis-canonical-bodies branch from e5d7501 to 5776404 Compare April 30, 2026 17:30
@fabianschuiki
Copy link
Copy Markdown
Contributor

Results of circt-tests run for 4b2d533 compared to results for 2123093: no change to test results.

@fabianschuiki
Copy link
Copy Markdown
Contributor

Results of circt-tests run for c206baf compared to results for 4b2d533: no change to test results.

@jpienaar jpienaar merged commit 95535c5 into llvm:main May 5, 2026
6 checks passed
rocallahan added a commit to rocallahan/circt that referenced this pull request May 5, 2026
…l module instances

Currently `HierarchicalNames` unconditionally descends into all module instance
bodies. This forces slang to instantiate complete ASTs for all module
instances, transitively. For large designs this does not scale. For example
with one 7M LOC Verilog example, ImportVerilog consumes more than 200GB of
memory before crashing with OOM.

So, use slang's canonical module bodies to avoid re-traversing identical modules.

With this fixed on top of PR llvm#10338, the aforementioned example is imported
quite quickly, consuming no more than 30GB of memory.
rocallahan added a commit to rocallahan/circt that referenced this pull request May 5, 2026
…l module instances

Currently `HierarchicalNames` unconditionally descends into all module instance
bodies. This forces slang to instantiate complete ASTs for all module
instances, transitively. For large designs this does not scale. For example
with one 7M LOC Verilog example, ImportVerilog consumes more than 200GB of
memory before crashing with OOM.

So, use slang's canonical module bodies to avoid re-traversing identical modules.

With this fixed on top of PR llvm#10338, the aforementioned example is imported
quite quickly, consuming no more than 30GB of memory.
jpienaar pushed a commit to rocallahan/circt that referenced this pull request May 14, 2026
…l module instances

Currently `HierarchicalNames` unconditionally descends into all module instance
bodies. This forces slang to instantiate complete ASTs for all module
instances, transitively. For large designs this does not scale. For example
with one 7M LOC Verilog example, ImportVerilog consumes more than 200GB of
memory before crashing with OOM.

So, use slang's canonical module bodies to avoid re-traversing identical modules.

With this fixed on top of PR llvm#10338, the aforementioned example is imported
quite quickly, consuming no more than 30GB of memory.
rocallahan added a commit to rocallahan/circt that referenced this pull request May 15, 2026
…l module instances

Currently `HierarchicalNames` unconditionally descends into all module instance
bodies. This forces slang to instantiate complete ASTs for all module
instances, transitively. For large designs this does not scale. For example
with one 7M LOC Verilog example, ImportVerilog consumes more than 200GB of
memory before crashing with OOM.

So, use slang's canonical module bodies to avoid re-traversing identical modules.

With this fixed on top of PR llvm#10338, the aforementioned example is imported
quite quickly, consuming no more than 30GB of memory.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants