[Relax][Frontend][TFLite] Add initial StableHLO builtin operator support#19536
Merged
Conversation
…upport Add frontend mapping for 8 basic StableHLO TFLite builtin operators as pure unary/binary elementwise ops: - STABLEHLO_ABS, STABLEHLO_NEGATE (unary) - STABLEHLO_ADD, STABLEHLO_SUBTRACT, STABLEHLO_MULTIPLY, STABLEHLO_DIVIDE, STABLEHLO_MAXIMUM, STABLEHLO_MINIMUM (binary) Implementation uses dedicated _convert_stablehlo_unary / _convert_stablehlo_binary helpers that intentionally bypass TFLite fused-activation and QNN code paths, since StableHLO ops carry no TFLite-specific quantization or fused-activation metadata in their flatbuffer representation. Test coverage: 8 structural-equal tests with tvm.ir.assert_structural_equal.
…h ternary SELECT Extend the StableHLO TFLite frontend with all remaining pure elementwise operators that require no attribute parsing: - Unary: STABLEHLO_COSINE (cos), STABLEHLO_EXPONENTIAL (exp), STABLEHLO_FLOOR (floor), STABLEHLO_LOG (log), STABLEHLO_LOGISTIC (sigmoid), STABLEHLO_RSQRT (rsqrt), STABLEHLO_TANH (tanh) - Binary: STABLEHLO_AND (logical_and), STABLEHLO_OR (logical_or), STABLEHLO_POWER (power), STABLEHLO_SHIFT_LEFT (left_shift) - Ternary: STABLEHLO_SELECT (where) with dedicated _convert_stablehlo_ternary helper The existing _convert_stablehlo_unary and _convert_stablehlo_binary helpers are reused; only STABLEHLO_SELECT needs the new ternary converter since R.where requires a 3-input signature with bool condition dtype. Test coverage: 20 structural-equal tests (12 new, 8 from previous commit). The SELECT test uses inline flatbuffer construction to set the condition input dtype to BOOL, matching the R.where requirement.
…nOptions2 support Introduce the first batch of StableHLO TFLite builtin operators that require BuiltinOptions2 attribute parsing: - STABLEHLO_CONVERT → R.astype (reads output dtype from tensor metadata) - STABLEHLO_CLAMP → R.minimum(R.maximum(x, min), max) (arg reordering) - STABLEHLO_CONCATENATE → R.concat with StablehloConcatenateOptions - STABLEHLO_BROADCAST_IN_DIM → R.broadcast_to with broadcast dimensions - STABLEHLO_IOTA → R.arange + R.reshape + R.broadcast_to - STABLEHLO_COMPARE → R.equal/greater/less/... with 6 comparison directions Add _get_stablehlo_options helper for parsing BuiltinOptions2 flatbuffers. R.clip was considered for CLAMP but rejected because it only accepts scalar PrimValue min/max, not tensor inputs. Test coverage: 32 structural-equal tests (20 previous + 12 new) passed.
Add frontend mapping for two StableHLO TFLite builtin operators that manipulate tensor shapes: - STABLEHLO_PAD → R.nn.pad with constant mode. Parses EdgePaddingLow, EdgePaddingHigh, and InteriorPadding from StablehloPadOptions. Raises OpNotImplemented when interior (dilation) padding is non-zero. - STABLEHLO_DYNAMIC_SLICE → R.dynamic_strided_slice. Reads SliceSizes from StablehloDynamicSliceOptions and start indices from scalar tensor inputs. Begin/end/strides are constructed as int64 1D tensors. Both ops extend the BuiltinOptions2 parsing infrastructure introduced in the previous commit, adding vector-attribute (PAD) and dynamic-input (DYNAMIC_SLICE) patterns. Test coverage: 33 structural-equal tests passed (31 previous + 2 new).
…nt subset) Add frontend mapping for STABLEHLO_GATHER with a conservative take-equivalent implementation: - Parses 6 attributes from StablehloGatherOptions (OffsetDims, CollapsedSliceDims, StartIndexMap, IndexVectorDim, SliceSizes, IndicesAreSorted) - Only supports single-axis gather with index vector dim == rank(indices)-1 and slice_sizes matching R.take semantics - Validates offset_dims layout, output shape, and collapsed dims against expected R.take behavior; raises OpNotImplemented otherwise - Reshapes indices from [N, 1] to [N] before calling R.take Tests: 3 new (2 take-equivalent parametrized for axis 0/1, 1 error path for multi-dimensional start_index_map). Total: 38 stablehlo tests passed.
Contributor
There was a problem hiding this comment.
Code Review
This pull request implements support for a wide range of StableHLO operators in the TFLite frontend for TVM Relax, covering unary, binary, ternary, and more complex operations like gather and dynamic slice. The changes include the core conversion logic and comprehensive unit tests. Feedback points out a bug in a test helper function regarding FlatBuffers vector generation and suggests removing a redundant reshape call in the dynamic slice implementation.
tlopex
approved these changes
May 11, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR adds initial Relax TFLite frontend support for 29 StableHLO builtin
operators from #19519 item I.
The covered subset includes pure elementwise ops, BuiltinOptions2 /
metadata-based ops, simple shape-manipulation ops, and a take-equivalent subset
of
STABLEHLO_GATHER.StableHLO builtins carry no TFLite-specific quantization or fused-activation
metadata, so the implementation uses dedicated converter helpers that bypass the
existing TFLite elemwise/QNN code paths.
Relates to #19519.
Changes
Zero-attribute elementwise helpers
_convert_stablehlo_unary,_convert_stablehlo_binary, and_convert_stablehlo_ternaryfor pure elementwise mapping.ABS,NEGATE,COSINE,EXPONENTIAL,FLOOR,LOG,LOGISTIC,RSQRT,TANH), binary (ADD,SUBTRACT,MULTIPLY,DIVIDE,MAXIMUM,MINIMUM,POWER), ternary (SELECT→R.where),and dtype-dispatched bitwise/logical ops (
AND/OR→ logical ops forbool or bitwise ops for integer,
SHIFT_LEFT→R.left_shiftfor integer).BuiltinOptions2 infrastructure
_get_stablehlo_optionshelper for parsingBuiltinOptions2flatbufferswith enum validation via
getattr(BuiltinOptions2, options_cls.__name__).CONVERT→R.astype,CLAMP→R.minimum(R.maximum(...)),CONCATENATE→R.concat,BROADCAST_IN_DIM→R.reshape+R.broadcast_to,IOTA→R.arange+R.broadcast_to, andCOMPARE→ 6 comparison directions(
TOTALORDERraisesOpNotImplemented).Shape-manipulation ops
PAD→R.nn.padin constant mode. The initial PAD path supportsnon-negative edge padding with zero interior padding and a constant scalar
padding value. Interior padding, negative padding, and dynamic padding
values raise
OpNotImplemented.DYNAMIC_SLICE→R.dynamic_strided_slice. The initial path supportsconstant, in-bound start indices only. Runtime start indices and
out-of-bounds StableHLO clamping semantics are deferred.
Indexing op
GATHER→R.takefor the take-equivalent subset only.StablehloGatherOptionsattributes needed to validatethis subset:
offset_dims,collapsed_slice_dims,start_index_map,index_vector_dim, andslice_sizes.output shape against the expected
R.takelayout. Multi-dimensional andnon-take-equivalent gather patterns raise
OpNotImplemented.Not included
STABLEHLO_RESHAPE,STABLEHLO_TRANSPOSE, andSTABLEHLO_SLICEare leftto another contributor who expressed interest in those ops.
CBRT,REMAINDER,SCATTER,CONVOLUTION,DOT_GENERAL,REDUCE,REDUCE_WINDOW,DYNAMIC_UPDATE_SLICE,COMPOSITE,CUSTOM_CALL,RNG_BIT_GENERATOR,SORT, andWHILE.STABLEHLO_GATHERpatterns are alsodeferred to follow-up work.
Testing
All tests use manually-built minimal TFLite flatbuffers with
tvm.ir.assert_structural_equal. BuiltinOptions2 ops construct their optionsvia the FlatBuffers schema API, modeled after the existing DILATE test pattern.
Result
29 StableHLO operators registered in the Relax TFLite frontend.
44 StableHLO test cases covering all registered ops, including
structural-equal tests and unsupported/error-path checks:
COMPAREwithTOTALORDERPADwith interior padding, negative padding, and dynamic padding valuesDYNAMIC_SLICEwith runtime starts and out-of-bounds startsGATHERAll StableHLO TFLite frontend tests pass locally.
References
in the TFLite frontend tests