Add TCI#970
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces the tci (tile consecutive index) operation across the PTO dialect, PTODSL, and the A5 tile library templates, along with corresponding integration tests. The feedback highlights a critical regression in vci where removing the type check breaks support for 16-bit integer types, and suggests expanding test coverage to include these 16-bit types as well as removing an unused helper function in the test file.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| raw_index = unwrap_surface_value(index) | ||
| if not hasattr(raw_index, "type"): | ||
| raw_index = _coerce_i32(raw_index, context="vci(index)") | ||
| raw_index = _coerce_i32(raw_index, context="vci(index)") |
There was a problem hiding this comment.
Unconditionally coercing raw_index to i32 by removing the if not hasattr(raw_index, "type"): check breaks support for non-i32 data types (such as i16 and ui16). When vci is called with an i16 or ui16 index, it will now be forced to i32, returning an i32 vector (e.g., vector<8xi32>). This results in a type and shape mismatch when stored into an i16 or ui16 tile (which expects vector<16xi16>). Please restore the conditional check so that only Python constants (which lack a .type attribute) are coerced to i32.
| raw_index = _coerce_i32(raw_index, context="vci(index)") | |
| if not hasattr(raw_index, "type"): | |
| raw_index = _coerce_i32(raw_index, context="vci(index)") |
| CASE_SHAPES = [ | ||
| ("i32_1x7", pto.i32, (1, 7), False), | ||
| ("i32_1x7_desc", pto.i32, (1, 7), True), | ||
| ("i32_1x128", pto.i32, (1, 128), False), | ||
| ("i32_1x128_desc", pto.i32, (1, 128), True), | ||
| ("ui32_1x128", pto.ui32, (1, 128), False), | ||
| ] |
There was a problem hiding this comment.
The template_tci template in ptodsl/ptodsl/tilelib/templates/a5/tci.py supports i16 and ui16 data types in addition to i32 and ui32. However, the test suite currently only covers i32 and ui32 shapes. To ensure full test coverage and prevent regressions for 16-bit integer types, please add i16 and ui16 test cases to CASE_SHAPES.
| CASE_SHAPES = [ | |
| ("i32_1x7", pto.i32, (1, 7), False), | |
| ("i32_1x7_desc", pto.i32, (1, 7), True), | |
| ("i32_1x128", pto.i32, (1, 128), False), | |
| ("i32_1x128_desc", pto.i32, (1, 128), True), | |
| ("ui32_1x128", pto.ui32, (1, 128), False), | |
| ] | |
| CASE_SHAPES = [ | |
| ("i32_1x7", pto.i32, (1, 7), False), | |
| ("i32_1x7_desc", pto.i32, (1, 7), True), | |
| ("i32_1x128", pto.i32, (1, 128), False), | |
| ("i32_1x128_desc", pto.i32, (1, 128), True), | |
| ("ui32_1x128", pto.ui32, (1, 128), False), | |
| ("i16_1x128", pto.i16, (1, 128), False), | |
| ("ui16_1x128", pto.ui16, (1, 128), False), | |
| ] |
| def _get_data_size(dtype): | ||
| """Return the element size in bytes for a given numpy dtype.""" | ||
| return np.dtype(dtype).itemsize |
e67f54c to
28a74ce
Compare
| return false; | ||
| }; | ||
|
|
||
| return isA5Target() ? ::mlir::pto::PIPE::PIPE_V |
There was a problem hiding this comment.
根据PTO_IR_Manual.md的定义,pto.tci就是PIPE_V的OP,不需要根据target判断
| ### 8.1.13 Tile windowing and tile-level matmul | ||
| ### 8.1.13 Contiguous integer sequence | ||
|
|
||
| #### `pto.tci(start: ScalarType, dst: Tile, *, tmp: Tile | None = None, descending: bool = False) -> None` |
There was a problem hiding this comment.
DSL的接口名称应该是pto.tile.ci
| | Bitwise | `tile.bit_not`, `tile.bit_and`, `tile.bit_or`, `tile.bit_xor`, `tile.bit_shl`, `tile.bit_shr`, `tile.bit_ands`, `tile.bit_ors`, `tile.bit_xors`, `tile.bit_shls`, `tile.bit_shrs` | | ||
| | Partial elementwise | `tile.partadd`, `tile.partmul`, `tile.partmax`, `tile.partmin` | | ||
| | Fill/padding | `tile.fillpad`, `tile.fillpad_expand`, `tile.fillpad_inplace` | | ||
| | Contiguous integer sequence | `tile.tci` | |
| import ptodsl.tilelib as tilelib | ||
|
|
||
|
|
||
| def _row_is_one(**context): |
There was a problem hiding this comment.
这个写法不是很优雅,而且检查了所有tile的valid shape,tmp在A5上一般是个空tile。可以参考这个方案改:
tilelib 的 constraints.py 里已有明确惯例:constraint 写成工厂函数,显式传入 operand 名,按 f"{name}_valid_shape" 精确取 key——参考现有的 require_same_valid_shape(constraints.py:284):
def require_same_valid_shape(*operand_names):
def _require_same_valid_shape(**context):
shapes = [context.get(f"{name}_valid_shape") for name in operand_names]
...
return _require_same_valid_shape_row_is_one 丑就丑在违背了这条惯例:不看 operand 名,改用后缀扫描整个 context(于是 tmp 的 valid_shape 也被误伤,还隐式耦合了 context 的命名约定)。顺这个模式加一个工厂即可:
# constraints.py
def require_valid_rows(operand_name, rows):
"""Require operand ``operand_name`` to have valid_shape[0] == rows."""
def _require_valid_rows(**context):
shape = context.get(f"{operand_name}_valid_shape")
return shape is not None and shape[0] == rows
return _require_valid_rows模板里就变成一行声明式的写法:
constraints=[
tilelib.check_memory_space("ub"),
tilelib.check_layout("row_major"),
tilelib.check_s_layout("none_box"),
tilelib.require_valid_rows("dst", 1),
],好处:
- 只查
dst,tmp传多行 tile 也不会被误拒——顺手修掉了之前 review 里第 5 条缺陷; - 语义在调用点一眼可读("dst 必须是单行"),不用去读一个遍历 context 的闭包;
- 与
check_memory_space/require_same_valid_shape等现有 helper 形态一致,且可复用(后面若有别的单行/单列 op 直接复用)。
记得把它加进 constraints.py 的 __all__(和 require_same_valid_shape 一起导出)。如果想更通用一点,也可以做成 require_valid_shape("dst", rows=1) 或接受谓词的形式,但就当前需求而言 require_valid_rows("dst", 1) 最简单、最够用。
| def tci(start, dst, *, tmp=None, descending=False): | ||
| """``pto.tci`` – generate contiguous integer sequence into dst tile (DPS).""" | ||
| _pto.tci( | ||
| _unwrap_optional_integer(start), | ||
| unwrap_surface_value(dst), | ||
| tmp=None if tmp is None else unwrap_surface_value(tmp), | ||
| descending=descending, | ||
| ) |
There was a problem hiding this comment.
新增DSL接口需要在DSL侧也添加相应的单元测试,确保新OP能正确lowering,位置:test_jit_compile.py
|
|
||
|
|
||
| def _make_inputs(name, dtype): | ||
| rng_seed = hash(name) & 0xFFFFFFFF |
There was a problem hiding this comment.
Python 的 hash() 对 str 默认受 PYTHONHASHSEED 随机化影响,每个进程种子不同,一旦 CI 失败无法按种子复现。应改用稳定哈希(zlib.crc32(name.encode()))或固定映射。
No description provided.