diff --git a/lib/Dialect/FIRRTL/Transforms/AdvancedLayerSink.cpp b/lib/Dialect/FIRRTL/Transforms/AdvancedLayerSink.cpp index a567e8cfac99..af3f16de78e1 100644 --- a/lib/Dialect/FIRRTL/Transforms/AdvancedLayerSink.cpp +++ b/lib/Dialect/FIRRTL/Transforms/AdvancedLayerSink.cpp @@ -111,9 +111,18 @@ class EffectInfo { }); } + /// Record whether the module-like op contains any effectful op. void update(FModuleLike moduleOp) { - if (!AnnotationSet(moduleOp).empty()) - return markEffectful(moduleOp); + // If the module op has any annotations, then we pretend the module contains + // some kind of important effect, so that we cannot sink its instances. + if (auto annos = getAnnotationsIfPresent(moduleOp)) + if (!annos.empty()) + return markEffectful(moduleOp); + + for (auto annos : moduleOp.getPortAnnotations()) + if (!cast(annos).empty()) + return markEffectful(moduleOp); + auto *op = moduleOp.getOperation(); // Regular modules may be pure. if (auto m = dyn_cast(op)) diff --git a/test/Dialect/FIRRTL/advanced-layer-sink.mlir b/test/Dialect/FIRRTL/advanced-layer-sink.mlir index 190922151546..73a1927b4e1b 100644 --- a/test/Dialect/FIRRTL/advanced-layer-sink.mlir +++ b/test/Dialect/FIRRTL/advanced-layer-sink.mlir @@ -715,3 +715,26 @@ firrtl.circuit "Sub" { } } } + +// Test that a port annotation on a module prevents us from sinking instances of +// that module into layerblocks. +firrtl.circuit "DoNotSinkInstanceOfModuleWithPortAnno" { + firrtl.layer @A bind {} + firrtl.module @ModuleWithPortAnno(out %out : !firrtl.uint<1>) + attributes { + portAnnotations = [ + [{class = "circt.FullResetAnnotation", resetType = "async"}] + ] + } + {} + + // CHECK: firrtl.module @DoNotSinkInstanceOfModuleWithPortAnno + firrtl.module @DoNotSinkInstanceOfModuleWithPortAnno() { + // CHECK-NEXT: firrtl.instance foo @ModuleWithPortAnn + %foo_out = firrtl.instance foo @ModuleWithPortAnno(out out : !firrtl.uint<1>) + // CHECK-NEXT: firrtl.layerblock + firrtl.layerblock @A { + "unknown"(%foo_out) : (!firrtl.uint<1>) -> () + } + } +}