Skip to content

fix(compile-hlo): lower layerNorm/rmsNorm/batchNorm to real stablehlo.reduce (compile on stock IREE) - #769

Merged
michalharakal merged 1 commit into
developfrom
fix/norm-converters-real-reduce
Jun 27, 2026
Merged

michalharakal merged 1 commit into
developfrom
fix/norm-converters-real-reduce

Conversation

@michalharakal

Copy link
Copy Markdown
Contributor

Problem

NeuralNetOperationsConverter lowered the normalization ops to MLIR that stock IREE cannot compile, so the native ops were effectively export-only:

  • convertLayerNorm / convertRmsNorm emitted stablehlo.custom_call @reduce_mean / @reduce_variance placeholders — no MLIR toolchain understands them, so iree-compile fails. (RMSNorm's only working end-to-end path was the NN-DSL primitive decomposition, not the converter op.) They also applied scale/offset with a bare stablehlo.multiply/add against a rank-1 [axisSize] operand — a shape mismatch (no broadcast_in_dim).
  • convertBatchNorm emitted stablehlo.batch_norm_training, whose result is a 3-tuple (output, mean, var) — the string emitter binds it to a single SSA value, which is invalid.

convertGroupNorm was already fixed (#752/#754) to use real stablehlo.reduce; this brings the other three in line.

Fix

Lower all three to real, compilable StableHLO, mirroring convertGroupNorm:

  • mean / variance via stablehlo.reduce (sum) + divide; variance = E[x²] − E[x]² (population, ddof=0).
  • broadcast_in_dim the reduced mean/std and the scale/offset (shape [axisSize] / (C,)) back to the input shape before the elementwise affine.
  • batchNorm decomposed to the same elementwise form: 5-operand inference (running mean/var) or 3-operand training (batch stats reduced over the non-feature axes). Dropped the batch_norm_* emission and the now-unused buildBatchNormOperation helper.

No @reduce_* custom-call stubs remain.

Validation

End-to-end on stock IREE 3.11.0 via the skainet-iree-conformance harness — the native ops now iree-compile → run → match numpy:

op max abs err
rmsNorm 0.0
layerNorm 1.2e-7
batchNorm 6e-8

Converter unit tests (LayerNormConverterTest, RmsNormConverterTest) updated to assert real stablehlo.reduce and the absence of @reduce_* custom calls; full skainet-compile-hlo:jvmTest suite green.

🤖 Generated with Claude Code

….reduce

convertLayerNorm and convertRmsNorm emitted stablehlo.custom_call @reduce_mean /
@reduce_variance placeholders that no MLIR toolchain can compile, so the native norm ops
were export-only — downstream users got modules that fail in iree-compile. (RMSNorm's only
working path was the NN-DSL primitive decomposition, not the converter op.) LayerNorm/RmsNorm
also applied scale/offset without a broadcast_in_dim, a shape mismatch for the usual
rank-1 affine params. BatchNorm emitted stablehlo.batch_norm_training, whose 3-tuple result
the string emitter can't bind to a single SSA value.

Lower all three to real, compilable StableHLO, matching convertGroupNorm (already fixed):
- mean/variance via stablehlo.reduce (sum) + divide; variance = E[x²] - E[x]² (ddof=0).
- broadcast_in_dim the reduced mean/std AND the scale/offset (shape [axisSize]/(C,)) back
  to the input shape before the elementwise affine.
- batchNorm decomposed to the same elementwise form: 5-operand inference (running mean/var)
  or 3-operand training (batch stats reduced over the non-feature axes); drop the
  batch_norm_* emission and the now-unused buildBatchNormOperation helper.

Validated end-to-end on stock IREE 3.11.0 (via the skainet-iree-conformance harness):
native layerNorm/rmsNorm/batchNorm now iree-compile, run, and match numpy
(max abs err 0 / 1.2e-7 / 6e-8). Converter unit tests updated to assert real
stablehlo.reduce and the absence of @reduce_* custom_calls.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@michalharakal
michalharakal merged commit ccfec35 into develop Jun 27, 2026
3 of 4 checks passed
@michalharakal
michalharakal deleted the fix/norm-converters-real-reduce branch June 27, 2026 18:27
MacOS pushed a commit to MacOS/SKaiNET that referenced this pull request Jul 10, 2026
Bumps VERSION_NAME 0.32.4 -> 0.33.0. Bundles the develop changes since 0.32.4:
GRU layer (SKaiNET-developers#772/SKaiNET-developers#217), upsample2d Bilinear + StableHLO export (SKaiNET-developers#771), the
autodiff dispatch correctness fix + 7 newly-differentiable ops + KSP coverage
guard (SKaiNET-developers#774), and norm converters lowering to real stablehlo.reduce (SKaiNET-developers#769).

Minor bump (not patch): TensorOps.sin/cos/convTranspose1d became abstract, a
source/binary-incompatible change for downstream TensorOps implementers.

Validated: full conformance suite (12/12 models + 33/33 ops) green end-to-end
on IREE llvm-cpu against this tree (via local-maven 0.32.5-localdev1).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

1 participant