Skip to content

[None][refactor] AutoDeploy: make MLIR elementwise fusion pipeline xDSL-native - #15130

Open
suyoggupta wants to merge 1 commit into
NVIDIA:mainfrom
nv-auto-deploy:sg/mlir-fusion-xdsl-walker
Open

[None][refactor] AutoDeploy: make MLIR elementwise fusion pipeline xDSL-native#15130
suyoggupta wants to merge 1 commit into
NVIDIA:mainfrom
nv-auto-deploy:sg/mlir-fusion-xdsl-walker

Conversation

@suyoggupta

@suyoggupta suyoggupta commented Jun 9, 2026

Copy link
Copy Markdown
Collaborator

Description

Addresses the review on PR #12427 (comment r3019035416): the MLIR elementwise fusion pipeline was half-idiomatic. mlir/decompose.py already used xDSL's PatternRewriteWalker + GreedyRewritePatternApplier + RewritePattern, but the fusion half (subgraph_discovery.py + subgraph_replace.py) hand-rolled IR traversal, mutation, and cleanup — including block.erase_op(..., safe_erase=False), which suppresses use-def validation.

What changed

  • mlir/fusion/subgraph_replace.py: removed safe_erase=False. Subgraph ops are erased in reverse-topological order (consumers before producers); combined with the replace_by that redirects every external use, each op has no remaining uses at erase time, so the default safe_erase=True use-def check passes. Added an optional rewriter: PatternRewriter param — the walker path routes insertion/erasure through the rewriter; standalone callers (unit tests) keep using block ops.
  • mlir/fusion/fuse.py (new): run_fusion() + FusionStats, mirroring run_decomposition. A _FuseSubgraphPattern (RewritePattern) matches each subgraph's anchor (sg.ops[0]) and is driven by PatternRewriteWalker(apply_recursively=False). The transform _apply now simply calls run_fusion.
  • transform/library/mlir_elementwise_fusion.py: _apply slimmed — the manual for sg in subgraphs loop collapses into one run_fusion(...) call. Top-level pipeline now reads symmetrically: run_decompositionrun_fusion.

Why discovery stays custom (not the sketched root-walk)

Subgraph discovery deliberately remains the greedy union-find (plus _has_placement_conflict, the 64-input _split_subgraph, and Kahn topo-sort for hash stability). A root-anchored backward walk would (1) fragment maximal multi-output connected components into separate fusions (different hashes, more kernels) and (2) cannot express the dependent 64-input partitioning. So only iteration + mutation became xDSL-native. A forward walk preserves split-partition dependency order, so refresh_inputs() continues to work exactly as before.

Test Coverage

  • 3 new tests in tests/unittest/auto_deploy/singlegpu/mlir/test_elementwise_fusion_e2e.py exercise the run_fusion walker path: structural/metadata, low-rank skip, and a CUDA full FX roundtrip with numerical check.
  • Full MLIR unit suite: 46 passed (43 baseline + 3 new), including the CUDA roundtrip.
python3 -m pytest tests/unittest/auto_deploy/singlegpu/mlir/ -q

Docs

  • mlir/agent_learnings.md: new entry Fix the link to the documentation #15 documenting the port and the keep-discovery-custom rationale.
  • New ad-mlir-fusion-update Claude Code skill distilling the learnings log into an update/debug guide for the pass.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Documentation

    • Added comprehensive skill guide for MLIR elementwise fusion workflows, including validation procedures and operational guardrails.
  • New Features

    • Introduced optimized fusion pass with improved subgraph discovery and replacement logic.
  • Tests

    • Expanded test coverage for fusion operations, including low-rank subgraph handling and end-to-end roundtrip validation.

…SL-native

Addresses PR NVIDIA#12427 review (comment r3019035416): the fusion pipeline was
half-idiomatic — decompose.py used xDSL's PatternRewriteWalker but the fusion
half hand-rolled IR traversal, mutation, and cleanup, including
block.erase_op(safe_erase=False) which suppresses use-def validation.

Changes:
- subgraph_replace.py: remove safe_erase=False. Subgraph ops are erased in
  reverse-topological order (consumers before producers) after replace_by
  redirects external uses, so the default safe_erase=True check passes. Added
  an optional PatternRewriter param: the walker path routes insertion/erasure
  through the rewriter; standalone callers (unit tests) keep using block ops.
- New mlir/fusion/fuse.py: run_fusion() + FusionStats, mirroring
  run_decomposition. A _FuseSubgraphPattern (RewritePattern) matches each
  subgraph's anchor and is driven by PatternRewriteWalker(apply_recursively=
  False). The transform _apply now just calls run_fusion.

Discovery deliberately stays the custom greedy union-find (plus
placement-conflict detection, the 64-input split, and Kahn topo-sort for hash
stability): a root-anchored backward walk would fragment maximal multi-output
subgraphs and cannot express the dependent 64-input partitioning. Only
iteration and mutation become xDSL-native. A forward walk preserves partition
dependency order so refresh_inputs() still works.

Tests: 3 new tests in test_elementwise_fusion_e2e.py exercise the run_fusion
walker path (structural/metadata, low-rank skip, CUDA full FX roundtrip). Full
MLIR suite: 46 passed.

Also documents the change in mlir/agent_learnings.md (#15) and adds an
ad-mlir-fusion-update skill distilling that log into an update/debug guide.

Signed-off-by: Suyog Gupta <41447211+suyoggupta@users.noreply.github.com>
@suyoggupta
suyoggupta requested a review from a team as a code owner June 9, 2026 01:28
@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This PR refactors the MLIR elementwise fusion pass to use xDSL's PatternRewriteWalker instead of a manual discover-then-replace pipeline. It introduces a new walker-driven orchestrator (run_fusion), updates subgraph replacement to work with the rewriter API, integrates the new approach into the transform pipeline, and adds comprehensive test coverage and architectural documentation.

Changes

Walker-driven fusion pass refactoring

Layer / File(s) Summary
Fusion architecture documentation and invariants
.claude/skills/ad-mlir-fusion-update/SKILL.md, tensorrt_llm/_torch/auto_deploy/mlir/agent_learnings.md
Adds comprehensive skill documentation for the MLIR elementwise fusion pipeline including architecture map, 4-touchpoint rule for adding primitives, cardinal invariants (fail-safe skipping, erase ordering, forward-walk semantics, emitter rules, subgraph constraints), failure-mode triage, validation workflow, and operational guardrails. Also documents the migration to xDSL's PatternRewriteWalker in agent learnings with plumbing changes and custom discovery preservation.
Pattern rewrite walker and fusion orchestration
tensorrt_llm/_torch/auto_deploy/mlir/fusion/fuse.py
Implements the walker-driven fusion pass with FusionStats dataclass for tracking discovery/replacement/skip counts, rank constraint helpers, _FuseSubgraphPattern rewrite pattern that refreshes inputs and enforces tensor rank constraints with error handling, and run_fusion orchestrator performing single-pass greedy matching via PatternRewriteWalker.
Subgraph replacement with optional PatternRewriter
tensorrt_llm/_torch/auto_deploy/mlir/fusion/subgraph_replace.py
Updates replace_subgraph_with_fused_op to accept an optional PatternRewriter parameter, enabling walker-driven SSA-aware mutation with InsertPoint routing while remaining backward compatible with direct block mutation for unit tests. Changes erase semantics from safe_erase=False to default behavior.
Transform pipeline integration of walker fusion
tensorrt_llm/_torch/auto_deploy/transform/library/mlir_elementwise_fusion.py
Refactors MLIRElementwiseFusion._apply to replace manual discover-then-replace logic with a single run_fusion call, removing manual discovery/codegen/replacement imports while using returned FusionStats for logging and TransformInfo.num_matches reporting.
Test coverage for walker-driven fusion
tests/unittest/auto_deploy/singlegpu/mlir/test_elementwise_fusion_e2e.py
Adds three new tests: test_run_fusion_replaces_subgraph_and_records_metadata validates pattern matching and metadata recording, test_run_fusion_skips_low_rank_subgraph verifies rank-based skipping behavior, and test_run_fusion_full_fx_roundtrip performs CUDA-only end-to-end FX→MLIR→decompose→fuse→MLIR→FX roundtrip with output equivalence checks.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • marinayanov
  • crazydemo
  • mikeiovine
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the primary change: making the MLIR elementwise fusion pipeline xDSL-native. It is specific, concise, and accurately summarizes the refactor.
Description check ✅ Passed The PR description comprehensively covers what changed (three files refactored), why (alignment with xDSL patterns), design rationale (discovery stays custom), test coverage (3 new tests, 46 total passed), and documentation (agent_learnings.md + Claude skill). All key sections from the template are addressed.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
tests/unittest/auto_deploy/singlegpu/mlir/test_elementwise_fusion_e2e.py (1)

506-626: Coverage is sufficient for the walker-driven fusion refactor scope.

tests/unittest/auto_deploy/singlegpu/mlir/test_elementwise_fusion_e2e.py now covers:

  • walker replacement + metadata contract,
  • low-rank skip accounting,
  • CUDA FX→MLIR→run_fusion→FX numerical roundtrip.

No must-have follow-up test file is required for this PR layer.

As per coding guidelines, test reviews under tests/** should explicitly assess whether coverage is sufficient/insufficient for the changed behavior.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unittest/auto_deploy/singlegpu/mlir/test_elementwise_fusion_e2e.py`
around lines 506 - 626, The test file lacks an explicit coverage assessment
statement required by our guidelines; update
tests/unittest/auto_deploy/singlegpu/mlir/test_elementwise_fusion_e2e.py to
include a short explicit coverage assertion/comment indicating these three tests
(test_run_fusion_replaces_subgraph_and_records_metadata,
test_run_fusion_skips_low_rank_subgraph, test_run_fusion_full_fx_roundtrip)
collectively cover walker-driven fusion replacement, low-rank skipping, and CUDA
FX→MLIR→run_fusion→FX numerical roundtrip — add this as a one-line comment near
the top of the test file or immediately above the first of these test functions
so reviewers can see the coverage assessment.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.claude/skills/ad-mlir-fusion-update/SKILL.md:
- Around line 146-150: The example command doesn't explicitly enable the fusion
pass so it won't run with default settings; update the example invocation of
build_and_run_ad.py (the script name build_and_run_ad.py and the existing
--args.model flag) to include an explicit config overlay or flag that turns the
fusion transform on (for example append an explicit config-overlay or
--enable-fusion/--args.overlay JSON that sets the fusion pass to true) so the
docs demonstrate an end-to-end run that actually exercises the fusion pass.

---

Nitpick comments:
In `@tests/unittest/auto_deploy/singlegpu/mlir/test_elementwise_fusion_e2e.py`:
- Around line 506-626: The test file lacks an explicit coverage assessment
statement required by our guidelines; update
tests/unittest/auto_deploy/singlegpu/mlir/test_elementwise_fusion_e2e.py to
include a short explicit coverage assertion/comment indicating these three tests
(test_run_fusion_replaces_subgraph_and_records_metadata,
test_run_fusion_skips_low_rank_subgraph, test_run_fusion_full_fx_roundtrip)
collectively cover walker-driven fusion replacement, low-rank skipping, and CUDA
FX→MLIR→run_fusion→FX numerical roundtrip — add this as a one-line comment near
the top of the test file or immediately above the first of these test functions
so reviewers can see the coverage assessment.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: ab6a29b0-2bb1-4528-bee4-e0fec94eef19

📥 Commits

Reviewing files that changed from the base of the PR and between c1e9b00 and e1065be.

📒 Files selected for processing (6)
  • .claude/skills/ad-mlir-fusion-update/SKILL.md
  • tensorrt_llm/_torch/auto_deploy/mlir/agent_learnings.md
  • tensorrt_llm/_torch/auto_deploy/mlir/fusion/fuse.py
  • tensorrt_llm/_torch/auto_deploy/mlir/fusion/subgraph_replace.py
  • tensorrt_llm/_torch/auto_deploy/transform/library/mlir_elementwise_fusion.py
  • tests/unittest/auto_deploy/singlegpu/mlir/test_elementwise_fusion_e2e.py

Comment on lines +146 to +150
Then end-to-end (the pass is off by default — enable it or use a config overlay):

```bash
python examples/auto_deploy/build_and_run_ad.py --args.model=<HF_MODEL>
```

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Validation command should explicitly enable the fusion pass.

This command currently won’t exercise fusion when defaults are unchanged, because the same doc states the transform is disabled by default. Please include an explicit config overlay/flag in the example command.

Suggested doc tweak
- python examples/auto_deploy/build_and_run_ad.py --args.model=<HF_MODEL>
+ python examples/auto_deploy/build_and_run_ad.py \
+   --args.model=<HF_MODEL> \
+   --args.yaml-extra=<CONFIG_WITH_MLIR_ELEMENTWISE_FUSION_ENABLED>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.claude/skills/ad-mlir-fusion-update/SKILL.md around lines 146 - 150, The
example command doesn't explicitly enable the fusion pass so it won't run with
default settings; update the example invocation of build_and_run_ad.py (the
script name build_and_run_ad.py and the existing --args.model flag) to include
an explicit config overlay or flag that turns the fusion transform on (for
example append an explicit config-overlay or --enable-fusion/--args.overlay JSON
that sets the fusion pass to true) so the docs demonstrate an end-to-end run
that actually exercises the fusion pass.

@suyoggupta
suyoggupta requested a review from bmarimuthu-nv June 9, 2026 17:09
@suyoggupta

Copy link
Copy Markdown
Collaborator Author

/bot run

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #53169 [ run ] triggered by Bot. Commit: e1065be Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #53169 [ run ] completed with state SUCCESS. Commit: e1065be
/LLM/main/L0_MergeRequest_PR pipeline #42372 completed with status: 'SUCCESS'

CI Report

Link to invocation

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.

2 participants