Skip to content

feat(hipsr): add hipsr.compute and hipsr.compute_yield ops - #615

Open
zpye wants to merge 7 commits into
mainfrom
feat/hipsr-compute-op
Open

feat(hipsr): add hipsr.compute and hipsr.compute_yield ops#615
zpye wants to merge 7 commits into
mainfrom
feat/hipsr-compute-op

Conversation

@zpye

@zpye zpye commented Jul 31, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds hipsr.compute and hipsr.compute_yield. hipsr.compute is a DPS op whose isolated single-block region groups the operations that implement one high-level computation, so an ONNX op needing several tensor or shape operations stays a single hipsr op.

Operands follow the rest of the dialect: inputs and inits take Hipsr_TensorOrDeviceMemRef, matching matmul, add, expand and cast, and hipsr.compute_yield takes ranked tensors to match the op's results.

Verification comes entirely from traits and interfaces, so there is no hand-written verifier. DestinationStyleOpInterface ties each tensor init to the result in the same position, RegionBranchOpInterface checks both control-flow edges, IsolatedFromAbove rejects boundary crossings, and SingleBlockImplicitTerminator pins the single block and its terminator.

Ops only: nothing emits one yet, so no existing behavior changes.

@github-actions

Copy link
Copy Markdown

Thanks for opening a PR!

This project follows LLVM's incremental-development and AI-tool-use
guidance. See CONTRIBUTING.md
for the project workflow.

Before requesting review, please check that:

  1. The change is focused. Substantial work links the relevant issue
    or design discussion.
  2. The PR documents relevant test results and updates affected
    documentation.
  3. If AI tools provided substantial assistance, the description
    explains what was assisted and how it was validated, and commit
    trailers identify the tool. The contributor has reviewed and
    understands the result.

Reviewers are assigned through
CODEOWNERS where ownership
is configured.

@zpye
zpye marked this pull request as ready for review July 31, 2026 11:33
@github-actions

github-actions Bot commented Jul 31, 2026

Copy link
Copy Markdown

L2 Accuracy Results (EP vs CPU)

Model Combined L2 Total Elems Skipped NaN/Inf
conv_test_hybrid 4.8668E-07 64 0
GroupQueryAttention_seq256 25.2366 2621440 0
MatMulNBits_o_seq128 259.906 368640 0
QMoE_seq128 34.957 368640 0

Threshold: 0.01 | Run: 3518 - Commit: 768d132

@github-actions

github-actions Bot commented Jul 31, 2026

Copy link
Copy Markdown

MorphiZen EP Performance Results

Model QPS Session (s) 1st Infer (ms) CPU% Mem (MB)
full_model_seq128 7.51 6.38 357 3 1243
GroupQueryAttention_seq128 4406.05 1.67447 10 6 311
matmul_down_seq128 507.40 2.48 72 4 352

EPContext Export Performance

Model QPS Session (s) 1st Infer (ms) CPU% Mem (MB)
full_model_seq128 7.52 46.59 360 3 15590

EPContext Import Performance

Model QPS Session (s) 1st Infer (ms) CPU% Mem (MB)
full_model_seq128 7.52 9.56 357 3 15760

OGA Benchmark Results

Model Warmup Reps Prompt Len Gen Tokens TTFT (ms) TPS Peak Mem (GB) GPU Mem (GB)
gpt-oss-20b-webgpu-int4-rtn-block-32 1 5 128 128 161.4 74.3 1.33 13.57
Llama-3.1-8B-awq-g128-int4-asym-fp16-onnx-dml 1 5 128 128 328.9 41.1 1.22 6.43

OGA Wheel Smoke (Python benchmark_e2e.py)

Model TTFT (ms) TPS
Llama-3.1-8B-awq-g128-int4-asym-fp16-onnx-dml 193 39.7

Run: 3518 - Commit: 768d132

wcy123
wcy123 previously approved these changes Jul 31, 2026

@wcy123 wcy123 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM

Minor observation: inputs defined as Variadic<AnyType> is overly permissive - should be Variadic<Hipsr_TensorOrDeviceMemRef> to match the design. The test case @multi_result passes an index input which would then be invalid and should be fixed.

zpye and others added 7 commits July 31, 2026 08:23
hipsr.compute groups the operations that implement one high-level
computation into a single DPS op with an isolated body region, so an ONNX
op needing several tensor or shape operations does not leave intermediate
values in the enclosing block. A hipsr.placeholder accepts only block
arguments and constant or placeholder results as inputs, so loose
intermediates would otherwise block placeholder-based output shaping.

The op carries no hand-written verifier. Every rule the design proposed
checking by hand already comes from a trait or interface: SizedRegion<1>
and SingleBlock for the block count, SingleBlockImplicitTerminator for
the terminator, RegionBranchOpInterface for both control-flow edges,
DestinationStyleOpInterface for init and result tying, and
IsolatedFromAbove for boundary crossings. test/lit/Dialect/Hipsr/
compute.mlir asserts the message each mechanism emits.

Two traits from the design are left out on purpose.
PromotableRegionOpInterface does not exist in the pinned MLIR, and the
Promotable* family it resembles is Mem2Reg/SROA slot promotion rather
than region flattening. ConditionallySpeculatable only feeds isPure,
whose consumers are LICM and related hoisting paths; the hipsr pipeline
has no loops to hoist a compute out of, and RecursiveMemoryEffects
already lets dead-code elimination erase an unused one.

This step adds the ops only, with no conversion-pattern users and no
bufferization model, so a compute that reached one-shot bufferize would
fail. That is unreachable today because -hipsr-bufferize does not exist.

Made-with: Cursor
Co-authored-by: Cursor <cursoragent@cursor.com>
The getEntrySuccessorOperands comment restated the operand order the op
description already documents and the roundtrip test already asserts, and
the neighbouring PoolDomainOp implementation carries no such comment.

Two negative LIT cases described the custom form's behaviour instead of
the case in front of them. Both now use the one-line phrasing that
pool-domain.mlir and placeholder-invalid.mlir use for the same checks.

Made-with: Cursor
Co-authored-by: Cursor <cursoragent@cursor.com>
The placeholder-input rule was written as a subjunctive clause chain that
took two readings to parse. It now states the constraint directly.

The DPS paragraph opened by saying the outs inits are the destinations,
which is what the term already means, so only the tying rule remains.

The trait paragraph claimed isolation keeps "stock MLIR passes correct",
which says little. It now uses the explicit-and-verifiable wording that
HipsrPoolDomainOp.td uses for the same pair, and names
AutomaticAllocationScope instead of describing it.

Made-with: Cursor
Co-authored-by: Cursor <cursoragent@cursor.com>
HipsrComputeYieldOp.td explained that its operands are optional so the
implicit terminator prints as a bare mnemonic. HipsrEmptyYieldOp.td
carries the identical format string with no such note, and the builder
two lines below already says the terminator is implicit.

HipsrComputeOp.td noted that result types follow the body after ':' as in
the other hipsr DPS ops. Those ops, HipsrCastOp.td among them, do not
comment their own use of ':', so the note explained conformity rather
than anything specific to this op. The optional-operand-group note stays,
since it is what makes 'ins() outs()' legal.

Made-with: Cursor
Co-authored-by: Cursor <cursoragent@cursor.com>
The remaining note said both operand lists are optional groups so an
empty one prints as 'ins()'. The optional markers in the format say that,
and compute.mlir covers the empty case. HipsrCastOp.td and the other DPS
ops leave their formats uncommented.

Made-with: Cursor
Co-authored-by: Cursor <cursoragent@cursor.com>
hipsr.compute_yield took Variadic<AnyType> while hipsr.compute declares
Variadic<AnyRankedTensor> results, so the operand type was looser than
the values it can legally carry.

The parent's RegionBranchOpInterface check still reports first for every
reachable input, since MLIR verifies the compute op's traits before
recursing into its region, so this adds no new diagnostic. It states the
contract where the op is defined.

Made-with: Cursor
Co-authored-by: Cursor <cursoragent@cursor.com>
Review on #615 noted Variadic<AnyType> inputs are looser than the design.
They were also the outlier in the dialect: matmul, add, expand and cast
take Hipsr_TensorOrDeviceMemRef, and placeholder takes AnyRankedTensor.
Only pool_domain uses AnyType, and it groups operations rather than
carrying tensor data.

@multi_result forwarded an index to show a non-tensor input crossing the
boundary. It now forwards a rank-0 tensor, which keeps the multi-input
operand-segment coverage and adds a rank the suite did not have, and a
new negative case pins the rejection of a scalar input.

Made-with: Cursor
Co-authored-by: Cursor <cursoragent@cursor.com>
@zpye
zpye force-pushed the feat/hipsr-compute-op branch from 8522653 to 768d132 Compare July 31, 2026 13:29
@zpye
zpye requested a review from amd-bqiao as a code owner July 31, 2026 13:29
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