Skip to content

Add GraphBuilder.subgraph() and TensorType.to_ir() for control-flow ops#2824

Merged
gramalingam merged 4 commits intomainfrom
rama/graph
Feb 25, 2026
Merged

Add GraphBuilder.subgraph() and TensorType.to_ir() for control-flow ops#2824
gramalingam merged 4 commits intomainfrom
rama/graph

Conversation

@gramalingam
Copy link
Collaborator

@gramalingam gramalingam commented Feb 24, 2026

Summary:

Adds utilities to simplify building ONNX control-flow ops (Scan, Loop, If) that use graph-valued attributes.

New: TensorType.to_ir()

Converts tensor-type annotations to ir.TypeAndShape, enabling the convenient FLOAT[1024] / FLOAT['M', 'N'] /
FLOAT[...] notation wherever a type spec is needed.

New: GraphBuilder.subgraph()

Builds an ir.Graph suitable for use as a graph-valued attribute. The body is defined by a trace function fn(op,
*inputs) — the same imperative style as the outer graph. The opset version is inherited from the parent GraphBuilder
.

   def cumsum_body(op, state, x_i):
       new_state = op.Add(state, x_i)
       return new_state, new_state

   body = builder.subgraph(
       cumsum_body,
       input_types=[FLOAT[4], FLOAT[4]],
       output_types=[FLOAT[4], FLOAT[4]],
       name="cumsum_body",
   )

   final_state, partial_sums = op.Scan(
       init_state, sequence,
       body=body,
       num_scan_inputs=1,
       _outputs=2,
   )

Files changed:

  • onnxscript/onnx_types.py — Add TensorType.to_ir() classmethod
  • onnxscript/_internal/builder.py — Add GraphBuilder.subgraph() method + TypeSpec / _resolve_type_spec helpers
  • onnxscript/onnx_types_test.py — New test file for TensorType.to_ir()
  • onnxscript/_internal/builder_test.py — Tests for GraphBuilder.subgraph()
  • docs/tutorial/builder/graph_builder.md — New Building Subgraphs for Control-Flow Ops section with Scan example

gramalingam and others added 4 commits February 24, 2026 14:53
- Add TensorType.to_ir() classmethod in onnx_types.py that converts
  tensor-type annotations (e.g. FLOAT[1024], FLOAT['M','N'], FLOAT[...])
  to ir.TypeAndShape.

- Add GraphBuilder.subgraph(trace_fn, input_types, output_types, *, name)
  method in builder.py. Builds an ir.Graph suitable for use as a
  graph-valued attribute to control-flow ops like Scan, Loop, and If.
  Opset version is inherited from the parent GraphBuilder. Accepts both
  ir.TypeAndShape and TensorType subclasses as type specs via the
  TypeSpec / _resolve_type_spec helpers.

- Add TensorTypeToIrTest and BuildSubgraphTest test classes in
  builder_test.py (13 new tests).

- Document the new feature in docs/tutorial/builder/graph_builder.md
  with a 'Building Subgraphs for Control-Flow Ops' section including a
  cumulative-sum Scan example.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…attr

Replace the duck-typed hasattr(spec, 'to_ir') check with an explicit
isinstance/issubclass check against TensorType. This makes the accepted
types clear and produces a better error message for invalid inputs.

TensorType is imported lazily inside the function to avoid a potential
circular import (onnxscript.__init__ imports onnx_types before builder,
but a top-level import in builder.py could break if builder were ever
imported directly first).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Tests for TensorType.to_ir() belong alongside onnx_types.py, not in the
builder test module. Remove the now-unused INT64 import from builder_test.py.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@gramalingam gramalingam changed the title Rama/graph Add GraphBuilder.subgraph() and TensorType.to_ir() for control-flow ops Feb 24, 2026
@codecov
Copy link

codecov bot commented Feb 24, 2026

Codecov Report

❌ Patch coverage is 97.60000% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 71.78%. Comparing base (f6a7de1) to head (53ed438).
⚠️ Report is 1 commits behind head on main.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
onnxscript/onnx_types_test.py 94.28% 1 Missing and 1 partial ⚠️
onnxscript/_internal/builder_test.py 98.11% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2824      +/-   ##
==========================================
+ Coverage   71.66%   71.78%   +0.11%     
==========================================
  Files         238      239       +1     
  Lines       28864    28989     +125     
  Branches     2849     2859      +10     
==========================================
+ Hits        20686    20809     +123     
- Misses       7207     7209       +2     
  Partials      971      971              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Collaborator

@justinchuby justinchuby left a comment

Choose a reason for hiding this comment

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

Nice! Thanks

@justinchuby
Copy link
Collaborator

Is there an option to not specify input_types and output_types? I don't think they are required for sub-graphs, right?

@gramalingam
Copy link
Collaborator Author

Is there an option to not specify input_types and output_types? I don't think they are required for sub-graphs, right?

Yes, that would be useful. I thought about it, but decided to leave it as strict for now. Will get back to it later.

@gramalingam gramalingam merged commit ef2bc22 into main Feb 25, 2026
33 checks passed
@gramalingam gramalingam deleted the rama/graph branch February 25, 2026 00:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Development

Successfully merging this pull request may close these issues.

2 participants