Commit 730459c
authored
[Relax][Frontend][TFLite] Support dynamic RANGE scalar bounds (#19867)
## Summary
This PR adds Relax TFLite frontend support for dynamic (runtime) scalar
bounds
in the `RANGE` operator, addressing the `RANGE` "fix partial
implementations"
item from #19412 section C.
`convert_range` previously lowered only **constant** `start`, `limit`,
and
`delta` to `relax.op.arange` and raised `OpNotImplemented` for runtime
scalar
bounds (the guard added in #19401). Models that compute RANGE bounds at
runtime
could therefore not be imported. This PR makes the dynamic path work for
both
integer and float bounds, ascending or descending, without adding a new
Relax
op. The change is limited to the `RANGE` converter and its test.
#19813 added a batch of missing TFLite operator mappings but did not
touch this
partial-implementation item; this PR closes it.
## Design
### Dynamic scalar bounds via count-lift
`relax.op.arange` only accepts compile-time `PrimExpr` bounds. The
frontend
already has a runtime-scalar -> symbolic-dimension bridge
(`relax.op.tensor_to_shape` + `match_cast`, as used by
`_get_shape_expr_from_tensor`), so no new op is needed.
Rather than feed symbolic bounds straight into `arange`, the converter
computes
the element **count** in-graph and lifts that single value to one
symbolic
output dimension `L`, then rebuilds the values as `arange(0, L) * delta
+ start`.
Lifting the count (instead of the bounds) keeps the declared and runtime
output
lengths equal by construction: `arange`'s struct-info length formula
(`InferTypeArange`) has no negative-step branch, so feeding symbolic
bounds
directly would mis-declare descending ranges relative to the TOPI
runtime
length.
The count is `max(0, ceil((limit - start) / delta))`, computed per
dtype:
- **integer**: `-floor_divide(start - limit, delta)` — exact,
sign-agnostic, and
free of float-precision loss; equal to `ceil((limit - start) / delta)`.
- **float**: `ceil((limit - start) / delta)`.
Constant (all-bounds-constant) RANGE keeps the existing direct-`arange`
path
unchanged.
## Operator Support
| Operator | TFLite inputs | Relax lowering | Supported subset |
|---|---|---|---|
| `RANGE` | scalar `start`, `limit`, `delta` | `relax.op.arange`
(constant bounds); count-lift + `arange(0, L) * delta + start` (dynamic
bounds) | int and float, constant or runtime scalar bounds, ascending or
descending |
## Tests
The dynamic test compiles the imported module and runs it on the Relax
VM,
comparing the output against `numpy.arange`. The constant-bound
structural test
is unchanged.
| Test | Coverage |
|---|---|
| `test_range` | constant scalar bounds (existing, unchanged) |
| `test_range_dynamic_scalar_inputs` | runtime scalar bounds: int and
float, ascending and descending |
Local validation:
```bash
python -m ruff format --check \
python/tvm/relax/frontend/tflite/tflite_frontend.py \
tests/python/relax/test_frontend_tflite.py
python -m ruff check \
python/tvm/relax/frontend/tflite/tflite_frontend.py \
tests/python/relax/test_frontend_tflite.py
python -m pytest \
tests/python/relax/test_frontend_tflite.py -k range -q
python -m pytest \
tests/python/relax/test_frontend_tflite.py -q
```
Result:
```text
ruff format --check: 2 files already formatted
ruff check: All checks passed
range tests: 12 passed, 536 deselected
full TFLite pytest: 548 passed
```
## References
- Issue #19412 section C: fix partial TFLite operator implementations
(`RANGE`)
- PR #19401: added the `RANGE` dynamic-scalar guard and its test
- PR #18868: introduced the Relax TFLite frontend and `convert_range`1 parent fb1d8aa commit 730459c
2 files changed
Lines changed: 110 additions & 31 deletions
File tree
- python/tvm/relax/frontend/tflite
- tests/python/relax
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1542 | 1542 | | |
1543 | 1543 | | |
1544 | 1544 | | |
1545 | | - | |
| 1545 | + | |
| 1546 | + | |
| 1547 | + | |
| 1548 | + | |
| 1549 | + | |
| 1550 | + | |
| 1551 | + | |
1546 | 1552 | | |
1547 | 1553 | | |
1548 | 1554 | | |
| |||
1551 | 1557 | | |
1552 | 1558 | | |
1553 | 1559 | | |
1554 | | - | |
| 1560 | + | |
| 1561 | + | |
| 1562 | + | |
| 1563 | + | |
| 1564 | + | |
| 1565 | + | |
| 1566 | + | |
| 1567 | + | |
| 1568 | + | |
| 1569 | + | |
| 1570 | + | |
| 1571 | + | |
1555 | 1572 | | |
1556 | | - | |
1557 | | - | |
1558 | | - | |
1559 | | - | |
1560 | | - | |
1561 | | - | |
1562 | | - | |
1563 | | - | |
1564 | | - | |
1565 | | - | |
| 1573 | + | |
1566 | 1574 | | |
1567 | 1575 | | |
1568 | | - | |
1569 | 1576 | | |
1570 | 1577 | | |
1571 | 1578 | | |
1572 | 1579 | | |
1573 | | - | |
1574 | | - | |
1575 | | - | |
| 1580 | + | |
| 1581 | + | |
| 1582 | + | |
| 1583 | + | |
| 1584 | + | |
| 1585 | + | |
1576 | 1586 | | |
1577 | | - | |
1578 | | - | |
1579 | | - | |
1580 | | - | |
1581 | | - | |
| 1587 | + | |
| 1588 | + | |
1582 | 1589 | | |
1583 | | - | |
| 1590 | + | |
| 1591 | + | |
| 1592 | + | |
| 1593 | + | |
| 1594 | + | |
| 1595 | + | |
| 1596 | + | |
| 1597 | + | |
| 1598 | + | |
| 1599 | + | |
| 1600 | + | |
| 1601 | + | |
| 1602 | + | |
| 1603 | + | |
| 1604 | + | |
| 1605 | + | |
| 1606 | + | |
| 1607 | + | |
| 1608 | + | |
| 1609 | + | |
| 1610 | + | |
| 1611 | + | |
| 1612 | + | |
| 1613 | + | |
| 1614 | + | |
| 1615 | + | |
1584 | 1616 | | |
1585 | | - | |
| 1617 | + | |
| 1618 | + | |
| 1619 | + | |
| 1620 | + | |
| 1621 | + | |
| 1622 | + | |
| 1623 | + | |
| 1624 | + | |
| 1625 | + | |
| 1626 | + | |
| 1627 | + | |
| 1628 | + | |
| 1629 | + | |
| 1630 | + | |
| 1631 | + | |
| 1632 | + | |
| 1633 | + | |
| 1634 | + | |
| 1635 | + | |
| 1636 | + | |
| 1637 | + | |
| 1638 | + | |
| 1639 | + | |
1586 | 1640 | | |
1587 | 1641 | | |
1588 | 1642 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
717 | 717 | | |
718 | 718 | | |
719 | 719 | | |
720 | | - | |
721 | | - | |
| 720 | + | |
| 721 | + | |
| 722 | + | |
| 723 | + | |
| 724 | + | |
| 725 | + | |
| 726 | + | |
| 727 | + | |
| 728 | + | |
| 729 | + | |
| 730 | + | |
722 | 731 | | |
723 | 732 | | |
724 | 733 | | |
725 | 734 | | |
726 | | - | |
727 | | - | |
728 | | - | |
| 735 | + | |
| 736 | + | |
| 737 | + | |
729 | 738 | | |
730 | 739 | | |
731 | 740 | | |
732 | | - | |
| 741 | + | |
| 742 | + | |
| 743 | + | |
| 744 | + | |
| 745 | + | |
| 746 | + | |
| 747 | + | |
| 748 | + | |
| 749 | + | |
| 750 | + | |
| 751 | + | |
| 752 | + | |
| 753 | + | |
| 754 | + | |
| 755 | + | |
| 756 | + | |
| 757 | + | |
733 | 758 | | |
734 | | - | |
735 | | - | |
| 759 | + | |
| 760 | + | |
736 | 761 | | |
737 | 762 | | |
738 | 763 | | |
| |||
0 commit comments