Aharrypotter opened a new pull request, #19879:
URL: https://github.com/apache/tvm/pull/19879

   ## Summary
   
   This PR extends the TFLite resource hashtable family from #19519 item G from
   "import + size" to a constant-foldable `HASHTABLE_FIND` subset. It builds on 
the
   static `HASHTABLE` / `HASHTABLE_IMPORT` import support added in #19639 and 
the
   `HASHTABLE_LOOKUP` converter from #19654.
   
   Relax has no string tensor type and no runtime hashtable operator, so this PR
   targets the only subset that can be lowered today: tables whose keys and 
values
   are constants imported in a `CALL_ONCE` init subgraph, queried by a constant
   string tensor. In that case the lookup is resolved at import time and 
emitted as
   a `relax.const`. Runtime string queries remain explicitly guarded instead of
   being lowered with incorrect semantics.
   
   ## Design
   
   ### Static String Tensor Decoding
   
   The frontend now decodes constant TFLite string tensors through a shared 
helper
   `_get_string_tensor_value`. It parses the TFLite string-tensor binary layout:
   
   ```text
   [count(i32)][offset_0 .. offset_count(i32)][utf8 string data]
   ```
   
   The helper validates the buffer length against the declared count, checks 
that
   offsets are in-bounds and monotonically non-decreasing, and verifies the 
decoded
   element count matches the tensor shape. This is reusable infrastructure for 
any
   future TFLite string support, independent of `HASHTABLE_FIND`.
   
   ### Hashtable Import State
   
   `HASHTABLE_IMPORT` now stores the actual constant keys and values (numeric or
   decoded string buffers) in shared conversion state, instead of only recording
   table metadata (size, key/value dtype). Duplicate keys are rejected, because 
the
   constant-fold lookup assumes a unique key mapping. The captured table is 
keyed by
   the same `table_id` / handle resolution used by `HASHTABLE` and 
`HASHTABLE_SIZE`,
   so a `CALL_ONCE` init subgraph and the main graph agree on the same logical
   table.
   
   ### Constant-Foldable Find
   
   `HASHTABLE_FIND` resolves the table handle through the importer-local handle 
map
   and the statically imported keys/values. For the supported subset it builds a
   Python key -> value map, applies the per-element default value, overwrites 
hits
   from the table, preserves the query tensor shape, and emits the result as a
   `relax.const`. The op produces no runtime Relax computation, which matches 
the
   fact that both the table and the query are compile-time constants.
   
   The supported subset is intentionally narrow and guard-first:
   
   - the table must be a constant `string -> int64` table imported via a 
supported
     `CALL_ONCE` `HASHTABLE_IMPORT`
   - the query tensor must be a constant string buffer
   - the default tensor must be a scalar or match the query shape
   
   ### String Graph Input Guard
   
   `TensorType.STRING` graph inputs are now rejected in `from_tflite` with a 
clear
   `OpNotImplemented` instead of a low-level FFI `unknown dtype string` error, 
since
   Relax cannot represent a string tensor. This is the path hit by runtime 
string
   queries for `HASHTABLE_FIND` and string-valued `HASHTABLE_LOOKUP`, so the 
guard
   gives a frontend-level diagnostic for both.
   
   ## Operator Support
   
   | Operator | TFLite options | Relax lowering | Supported subset |
   |---|---|---|---|
   | `HASHTABLE_IMPORT` | `HashtableImportOptions` | store constant keys/values 
in importer state | `CALL_ONCE` init, constant keys/values, no duplicate keys |
   | `HASHTABLE_FIND` | `HashtableFindOptions` | constant-fold to `relax.const` 
| constant `string -> int64` table + constant string query |
   
   ## Not Included
   
   - Runtime (non-constant) string queries and runtime hashtable lookup.
   - `int64 -> string` find, which would require string-typed Relax outputs.
   - Any general `TensorType.STRING` tensor representation in Relax.
   - A runtime Relax hashtable operator with string hashing / comparison.
   - Mutable runtime resource-state threading through Relax functions.
   
   These require core Relax support and are out of scope for the frontend.
   
   ## Tests
   
   The tests manually build minimal TFLite flatbuffers and compare the imported
   Relax IR with `tvm.ir.assert_structural_equal`. Unsupported patterns use
   `pytest.raises`.
   
   | Test | Coverage |
   |---|---|
   | `test_hashtable_call_once_import_find_string_to_int64` | constant `string 
-> int64` find folds to a `relax.const` |
   | `test_hashtable_call_once_import_find_string_to_int64_2d_query` | query 
shape preserved for a 2-D query |
   | `test_hashtable_call_once_import_find_int64_to_string_unsupported` | 
`int64 -> string` table rejected |
   | `test_hashtable_call_once_import_find_runtime_query_unsupported` | runtime 
string query rejected |
   | `test_hashtable_call_once_import_duplicate_keys_unsupported` | duplicate 
static keys rejected |
   | `test_hashtable_lookup_string_value_unsupported` | string graph input now 
gives a clean `OpNotImplemented` |
   
   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 "hashtable or resource or variable" -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
   14 passed, 535 deselected
   549 passed
   ```
   
   ## References
   
   - Issue #19519 item G: TFLite resource / variable / hashtable operators
   - PR #19639: TFLite resource variable and static hashtable import support
   - PR #19654: TFLite `HASHTABLE_LOOKUP` converter
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to