Add composable C++ graph pattern rewriter (#33631)
### Description
<!-- Describe your changes. -->
Introduce an experimental, explicitly opt-in C++ graph pattern rewriter
in `onnxruntime::rewrite`, with documentation and component/integration
tests. This is infrastructure for authoring rewrites, not a production
fusion rollout; it is not registered among ORT's default optimizers.
- Provide independently usable `Pattern::MatchAt` / `VisitMatches` and
`Replacement::Instantiate` APIs, candidate-local `Match` bindings, C++
check-and-bind callbacks, rewrite rules, and a
`GraphTransformer`-compatible engine.
- Add a text DSL for connected DAG patterns and replacements, positional
multi-output bindings, constants and attributes, optional tensor slots,
type/shape constraints, immutable tensor constraints, and typed constant
readers.
- Support reusable named pattern libraries, hygienic nested calls,
interfaces, aliases and bounded source-order alternatives. Scoped
binding views expose the selected alternative; handwritten C++ views
illustrate usage without adding a code generator.
- Support optional attribute captures such as `perm : ints | None`,
distinguishing captured absence from unknown names, with nullable lookup
and replacement omission followed by schema default/required-attribute
validation.
- Preserve graph-output/external-user deletion boundaries,
provider/layer and explicit opset eligibility, candidate binding
isolation, deterministic rule priority, and staging/rollback before
committing a replacement. Replacement errors propagate rather than
silently retrying. Whole engine runs and subsequent `Graph::Resolve` are
not transactional.
- Document component contracts, borrowed graph lifetimes, Resolve
boundaries, bounded matching, diagnostics, opt-in integration, and
natural Transpose-composition plus small numerical fusion examples. No
MoE/QMoE lowering or sibling fusion changes are included.
Validation already performed on Windows CPU Release at implementation
commit `e5927feb856711fc0f4c06145a553c1c2675cdf9`; the subsequent head
`319fa38a679b3730ca7487c2269fa388dca58f2b` changes documentation
order/cross-links only:
```powershell
.\.venv\Scripts\python.exe tools\ci_build\build.py --config Release --build_dir C:\ortbuild\rewriter3 --build --parallel 12 --target onnxruntime_test_all --skip_submodule_sync --compile_no_warning_as_error --no_telemetry
```
Result: passed incremental Release build.
From `C:\ortbuild\rewriter3\Release\Release`:
```powershell
.\onnxruntime_test_all.exe --gtest_filter=PatternComponentTests.*:ReplacementComponentTests.*:MatchComponentTests.*:CheckAndBindComponentTests.*:PatternRewriterTests.*
```
Result: 155 tests passed across five suites, including component
contracts, numerical CPU equivalence, composition/alternative retry,
optional attributes, graph boundaries and replacement rollback.
Independent focused review additionally rebuilt the engine and
artifact-only harnesses, passed 100 grouped optional-attribute checks
plus existing component/dimension/positional checks, and compiled both
test translation units in normal and `DISABLE_CONTRIB_OPS`
configurations (four successful compiles). The reviewer also reran the
owner-built 155-test executable. These are local results, not upstream
CI results. No clean full runtime rebuild, disabled-contrib runtime
execution, or GPU validation was performed. Documentation checks
preserve all code examples and verify local anchors, fenced blocks,
heading order and `git diff --check`.
### Motivation and Context
<!-- - Why is this change required? What problem does it solve?
- If it fixes an open issue, please link to the issue here. -->
Graph rewrites combine recurring structural matching and graph-edit
safety logic with rule-specific semantic and kernel-support checks. This
separates those responsibilities: patterns describe structure, C++
check-and-bind functions establish applicability and prepare values,
replacements describe construction, and the engine handles ordered
application.
Standalone matching and fragment construction make each component
independently testable. Reusable pattern composition avoids duplicating
common graph forms while preserving local bindings and explicit
alternative selection. Semantic equivalence, arithmetic/dependent
constraints and kernel compatibility remain the rule author's
responsibility in C++; there are no higher-order pattern parameters,
general recursive backtracking, automatic C++ generation, or default
optimizer behavior changes.
This draft is submitted from the existing
`gramalingam:gramalingam-rewriter3` branch for upstream discussion. It
targets upstream `main` (the current default; `master` is no longer an
actual upstream branch) without rebasing the source branch.
---------
Signed-off-by: Ganesan Ramalingam <grama@microsoft.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: daf231a0-ce61-4a2b-9649-0f31e2296e4f