Skip to content

Commit e9d6aed

Browse files
committed
[ImportVerilog] Capture analysis should skip reprocessing identical module instances (#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.
1 parent 2123093 commit e9d6aed

1 file changed

Lines changed: 11 additions & 1 deletion

File tree

lib/Conversion/ImportVerilog/CaptureAnalysis.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,9 @@ namespace {
8080
/// visiting enabled so that we recurse into all function bodies.
8181
struct CaptureWalker
8282
: public ASTVisitor<CaptureWalker, /*VisitStatements=*/true,
83-
/*VisitExpressions=*/true> {
83+
/*VisitExpressions=*/true,
84+
/*VisitBad=*/false,
85+
/*VisitCanonical=*/true> {
8486

8587
/// The function whose body we are currently inside, or nullptr if we are at
8688
/// a scope outside any function.
@@ -89,6 +91,8 @@ struct CaptureWalker
8991
/// Captured variables per function.
9092
CaptureMap capturedVars;
9193

94+
mlir::DenseSet<const InstanceBodySymbol *> visitedInstanceBodies;
95+
9296
/// Inverse call graph: maps each callee to the set of callers that call it.
9397
/// Used to propagate captures from callees to their callers. Uses MapVector
9498
/// for deterministic iteration order during propagation.
@@ -150,6 +154,12 @@ struct CaptureWalker
150154
visitDefault(expr);
151155
}
152156

157+
void handle(const InstanceBodySymbol &instance) {
158+
if (visitedInstanceBodies.insert(&instance).second) {
159+
visitDefault(instance);
160+
}
161+
}
162+
153163
/// Propagate captures transitively through the call graph. For each callee
154164
/// that has captures, push each captured variable upward through all
155165
/// transitive callers using a worklist. A captured variable is only

0 commit comments

Comments
 (0)