From 45e1f8884b628e268784748ae71c00f871de8ed6 Mon Sep 17 00:00:00 2001 From: Alex Light Date: Fri, 22 May 2026 14:02:16 -0700 Subject: [PATCH] Add VisibilityAnnotator to dump IR with visibility information. This change introduces a new class, `VisibilityAnnotator`, which is an `IrAnnotator` that can be used to dump the IR with annotations showing the visibility BDD for each node. The `VisibilityAnalysis` class now provides an `annotator()` method to create an instance of this annotator. A test case is updated to demonstrate the use of the annotator by recording the annotated IR. This creates output like: ``` fn MutuallyExclusivePrioritySelectCases(op: bits[1] id=1 visible[1], x: bits[4] id=2 visible[1], y: bits[4] id=3 visible[1]) -> bits[4] { add.4: bits[4] = add(x, y, id=4) visible[x0] sub.5: bits[4] = sub(x, y, id=5) visible[!x0] ret priority_sel.6: bits[4] = priority_sel(op, cases=[add.4], default=sub.5, id=6) visible[1] } ``` PiperOrigin-RevId: 919849429 --- xls/passes/visibility_analysis.cc | 12 ++++++++++++ xls/passes/visibility_analysis.h | 18 ++++++++++++++++++ xls/passes/visibility_analysis_test.cc | 2 ++ 3 files changed, 32 insertions(+) diff --git a/xls/passes/visibility_analysis.cc b/xls/passes/visibility_analysis.cc index 7715e237bf..30132ebf61 100644 --- a/xls/passes/visibility_analysis.cc +++ b/xls/passes/visibility_analysis.cc @@ -35,6 +35,7 @@ #include "xls/common/status/status_macros.h" #include "xls/data_structures/binary_decision_diagram.h" #include "xls/ir/bits.h" +#include "xls/ir/ir_annotator.h" #include "xls/ir/node.h" #include "xls/ir/nodes.h" #include "xls/ir/op.h" @@ -747,6 +748,17 @@ BddNodeIndex VisibilityAnalysis::ConservativeVisibilityByPruningEdges( return bdd_query_engine_->bdd().one(); } +VisibilityAnnotator VisibilityAnalysis::annotator() const { + return VisibilityAnnotator(this); +} + +Annotation VisibilityAnnotator::NodeAnnotation(Node* node) const { + return Annotation{ + .suffix = absl::StrFormat( + "visible[%s]", + vis_->bdd_query_engine()->bdd().ToStringDnf(*vis_->GetInfo(node)))}; +} + BddNodeIndex VisibilityAnalysis::VisibilityOfNearestPostDominator( Node* node) const { // If querying with exclusions, do not rely on the post dominator fallback diff --git a/xls/passes/visibility_analysis.h b/xls/passes/visibility_analysis.h index f6a7bcb982..c962382398 100644 --- a/xls/passes/visibility_analysis.h +++ b/xls/passes/visibility_analysis.h @@ -30,6 +30,7 @@ #include "absl/types/span.h" #include "xls/data_structures/binary_decision_diagram.h" #include "xls/ir/change_listener.h" +#include "xls/ir/ir_annotator.h" #include "xls/ir/node.h" #include "xls/ir/nodes.h" #include "xls/passes/bdd_evaluator.h" @@ -178,6 +179,8 @@ class NodeImpactOnVisibilityAnalysis : public LazyNodeData { } }; +class VisibilityAnnotator; + // The visibility of a node is the BDD expression that, if true, indicates that // the node's value propagates outside of the function or proc. // @@ -228,6 +231,11 @@ class VisibilityAnalysis : public LazyNodeData { BddNodeIndex VisibilityOfNearestPostDominator(Node* node) const; + const BddQueryEngine* bdd_query_engine() const { return bdd_query_engine_; } + + // Get an annotator for the IR this analsysis is performed on. + VisibilityAnnotator annotator() const; + protected: BddNodeIndex ComputeInfo( Node* node, @@ -331,6 +339,16 @@ class SingleSelectVisibilityAnalysis void UserRemoved(Node* node, Node* user) override; }; +class VisibilityAnnotator : public IrAnnotator { + public: + VisibilityAnnotator(const VisibilityAnalysis* vis) : vis_(vis) {} + + Annotation NodeAnnotation(Node* node) const override; + + private: + const VisibilityAnalysis* vis_; +}; + } // namespace xls #endif // XLS_PASSES_VISIBILITY_ANALYSIS_H_ diff --git a/xls/passes/visibility_analysis_test.cc b/xls/passes/visibility_analysis_test.cc index 0557cd6d17..3ac8c0b6e1 100644 --- a/xls/passes/visibility_analysis_test.cc +++ b/xls/passes/visibility_analysis_test.cc @@ -797,6 +797,7 @@ TEST_F(VisibilityAnalysisTest, MutuallyExclusivePrioritySelectCases) { XLS_ASSERT_OK_AND_ASSIGN( auto visibility, VisibilityAnalysis::Create(&operand_visibility, bdd_engine.get(), &post_dom)); + RecordProperty("ir", f->DumpIr(visibility->annotator())); EXPECT_TRUE(visibility->IsMutuallyExclusive(add.node(), sub.node())); } @@ -856,6 +857,7 @@ TEST_F(VisibilityAnalysisTest, StateUsedInPredicateIsVisible) { auto visibility, VisibilityAnalysis::Create(&operand_visibility, bdd_engine.get(), &post_dom)); + RecordProperty("ir", f->DumpIr(visibility->annotator())); auto pred_bdd_node = bdd_engine->GetBddNode(TreeBitLocation(pred.node(), 0)); ASSERT_TRUE(pred_bdd_node.has_value()); EXPECT_EQ(*visibility->GetInfo(input.node()), pred_bdd_node.value())