Background
Excited to see the huge progress the community has made on the Relax TFLite frontend recently — many operators and tests have landed in the last few weeks. To keep pushing this forward, this issue tracks the remaining operator gap so contributors can pick up well-scoped items in parallel.
A. Good-first-issues — drop-in mappings
Workflow: add a handler, wire into convert_map (alphabetical within its region), add one verify(TestClass, Expected) test in tests/python/relax/test_frontend_tflite.py (pattern at L55). All target Relax ops already exist — no new op work needed.
B. Medium — may need new Relax op or non-trivial decomposition
Prefer composing with existing Relax ops over adding a new op. Only register a new relax.op.* when the semantics genuinely cannot be expressed by existing primitives (e.g. random generators, bit-level reinterpret). If a decomposition using existing ops is feasible, go with that — it's a smaller PR and avoids bloating the op set.
C. Fix partial implementations
These ops are already in convert_map but their handler raises OpNotImplemented on certain input patterns, making them unusable on real models that hit those patterns.
Contributor workflow
- Claim an item by commenting on this issue before starting, so we avoid duplicated work.
- Read a recent reference PR for handler + test style.
- Add the handler, register in
convert_map (alphabetical within its region).
- Add a structural-equal test following the
verify(TestClass, Expected) pattern (test_frontend_tflite.py:55). Nightly-gated E2E activates automatically via CI_ENV_NIGHTLY.
- Tag the PR title
[Relax][Frontend][TFLite].
cc @leandron
Background
Excited to see the huge progress the community has made on the Relax TFLite frontend recently — many operators and tests have landed in the last few weeks. To keep pushing this forward, this issue tracks the remaining operator gap so contributors can pick up well-scoped items in parallel.
A. Good-first-issues — drop-in mappings
Workflow: add a handler, wire into
convert_map(alphabetical within its region), add oneverify(TestClass, Expected)test intests/python/relax/test_frontend_tflite.py(pattern at L55). All target Relax ops already exist — no new op work needed.CUMSUM→relax.op.cumsumUNIQUE→relax.op.uniqueSCATTER_ND→relax.op.scatter_ndBROADCAST_TO→relax.op.broadcast_toSIGN→relax.op.signBITWISE_XOR→relax.op.bitwise_xorRIGHT_SHIFT→relax.op.right_shiftBUCKETIZE→relax.op.bucketizeEMBEDDING_LOOKUP→relax.op.takeSELECT_V2→relax.op.whereRELU_0_TO_1→relax.op.clipNON_MAX_SUPPRESSION_V4→ port from existingconvert_nms_v5B. Medium — may need new Relax op or non-trivial decomposition
Prefer composing with existing Relax ops over adding a new op. Only register a new
relax.op.*when the semantics genuinely cannot be expressed by existing primitives (e.g. random generators, bit-level reinterpret). If a decomposition using existing ops is feasible, go with that — it's a smaller PR and avoids bloating the op set.REDUCE_ANY— commented attflite_frontend.py:198; can be lowered torelax.op.maxon a bool tensor, no new op neededREDUCE_ALL— same, lower torelax.op.minon boolRANK— emitrelax.const(ndim)for static shapes; no op call neededATAN2— compose fromatan+sign+where, or addrelax.op.atan2for a cleaner implSEGMENT_SUM— reuserelax.op.scatter_ndwithreduction="add"(TFLite requires sorted segment ids)UNSORTED_SEGMENT_SUM—scatter_nd(reduction="add")UNSORTED_SEGMENT_MAX—scatter_nd(reduction="max")UNSORTED_SEGMENT_MIN—scatter_nd(reduction="min")UNSORTED_SEGMENT_PROD—scatter_nd(reduction="mul")DYNAMIC_UPDATE_SLICE— reuserelax.op.slice_scatterDILATE— likely needs a new op (or decompose viapad+strided_slice)MULTINOMIAL— wrap existingrelax.op.multinomial_from_uniform; blocked onRANDOM_UNIFORMRANDOM_STANDARD_NORMAL— needs a new random-generator op in RelaxRANDOM_UNIFORM— sameBITCAST— needs a new reinterpret/view opBROADCAST_ARGS— shape-level computation; consider static-shape-only path firstC. Fix partial implementations
These ops are already in
convert_mapbut their handler raisesOpNotImplementedon certain input patterns, making them unusable on real models that hit those patterns.RANGE— handler raises on dynamic scalar inputs (tflite_frontend.py:958); should lower torelax.op.arange.FILL— handler raises whendimsis non-constant (L1729); should lower torelax.op.fullwith a dynamic shapeSPLIT_V— handler raises whensize_splitsis non-constant (L2267); decompose into dynamic strided slices.NON_MAX_SUPPRESSION_V5— handler raises on soft-NMS (L3546); needssoft_nms_sigma != 0supportFAKE_QUANT— handler raises on some narrow-range vector configs (L3913)Contributor workflow
convert_map(alphabetical within its region).verify(TestClass, Expected)pattern (test_frontend_tflite.py:55). Nightly-gated E2E activates automatically viaCI_ENV_NIGHTLY.[Relax][Frontend][TFLite].cc @leandron