Validation And Compatibility#

After exporting Graph IR, use ONNX conversion readiness checks before conversion.

Ownership boundary#

  • Public API: MLX::ONNX.export_onnx_compatibility_report, MLX::ONNX.graph_ir_to_onnx_json, and MLX::ONNX.graph_ir_to_onnx.

  • Internal diagnostic API: MLX::ONNX::Native.ir_compatibility_report_json.

  • Runtime ownership: MLX::ONNX::Native.

Schema/topology errors surface during conversion#

graph_ir_to_onnx_json and graph_ir_to_onnx raise on malformed Graph IR payloads.

WebGPU/ONNX preflight#

MLX::ONNX.export_onnx_compatibility_report checks traced models directly and returns unsupported_ops without requiring intermediate Graph IR handling in Ruby.

report = MLX::ONNX.export_onnx_compatibility_report(fun, *args, **kwargs)
abort("unsupported ops: #{report.fetch('unsupported_ops').inspect}") unless report.fetch("unsupported_nodes").zero?

MLX::ONNX::Native.ir_compatibility_report_json summarizes conversion readiness and unsupported operations.

report = JSON.parse(
  MLX::ONNX::Native.ir_compatibility_report_json(payload)
)

puts "format=#{report.fetch('format')}" # => "webgpu_compat_report_v1"
puts "total_nodes=#{report.fetch('total_nodes')}"
puts "unsupported_nodes=#{report.fetch('unsupported_nodes')}"
puts "unsupported_ops=#{report.fetch('unsupported_ops').inspect}"

unless report.fetch("ready_for_stub_conversion")
  abort("Graph IR not ready for ONNX/WebGPU conversion")
end

Current MLX -> ONNX mapped ops#

The compatibility preflight and lowering path use native IR/ONNX mapping tables from the separate mlx-onnx repository (src/mappings.cpp and src/lowering.cpp). In this repository, that source is vendored under submodules/mlx-onnx.

Direct op mapping table#

MLX op

ONNX op

Add

Add

AddMM

Gemm

Subtract

Sub

Multiply

Mul

Square

Mul

Divide

Div

AsType

Cast

Exp

Exp

Expm1

Exp + Sub decomposition

Log

Log

Sin

Sin

Cos

Cos

Erf

Erf

ErfInv

ErfInv

Sqrt

Sqrt

Abs

Abs

Floor

Floor

Negative

Neg

Relu

Relu

Sigmoid

Sigmoid

Tanh

Tanh

LayerNorm

LayerNormalization

Softmax

Softmax

Greater

Greater

GreaterEqual

GreaterOrEqual

Less

Less

LessEqual

LessOrEqual

Equal

Equal

LogicalAnd

And

Select

Where

Full

Identity

RandomBits

RandomUniform

Matmul

MatMul

Reshape

Reshape

Flatten

Reshape

Unflatten

Reshape

Transpose

Transpose

Squeeze

Squeeze

ExpandDims

Unsqueeze

Broadcast

Expand

BitwiseBinary

BitwiseAnd / BitwiseOr / BitwiseXor / BitShift

Arange

Constant

ArgPartition

TopK (indices output cast to uint32)

AsStrided

Gather

RoPE

Identity

Concatenate

Concat

Convolution

Conv

ConvolutionTranspose

ConvTranspose

Gather

Gather

GatherAxis

GatherElements

GatherMM

Reshape + Gather + MatMul decomposition

Slice

Slice

SliceUpdate

ScatterND

Split

Split

LogAddExp

Max + Sub + Exp + Add + Log + Add decomposition

LogSumExp

ReduceLogSumExp

Pad

Pad

Scan

CumSum

ScatterAxis

ScatterElements

Maximum

Max

Minimum

Min

Power

Pow

Reduce code mapping#

Reduce lowering maps reducer codes as:

  • 0/1 (logical all/any) via Cast(BOOL) -> Cast(INT64) -> ReduceMin/ReduceMax -> Cast(BOOL)

  • 2 -> ReduceSum

  • 3 -> ReduceProd

  • 4 -> ReduceMin

  • 5 -> ReduceMax

Arg-reduce code mapping#

ArgReduce lowering maps reducer codes as:

  • 0 -> ArgMin

  • 1 -> ArgMax

MLX ops not yet mapped to ONNX#

Use the coverage artifact’s unsupported_ops_union as the current source of unmapped operations:

  • test/reports/ir_webgpu_coverage.json

  • generated by test/support/parity/generate_onnx_webgpu_coverage_report.rb

Current unmapped ops table#

MLX op (unmapped)

Source

Notes

(none)

unsupported_ops_union

Latest coverage artifact currently reports [].

Next step#

Continue with Graph IR To ONNX.