Skip to content

Issue: 工具链更新后两处回归阻断全部编译(BLayout::ND2M 笔误 + B.DIM 立即数 matcher 拒收) #77

Description

@lvhao7896

Issue: 工具链更新后两处回归阻断全部编译(BLayout::ND2M 笔误 + B.DIM 立即数 matcher 拒收)

  • 日期: 2026-09-06
  • 组件: linx toolchain (LLVM LinxV5 后端 + Linx-TileOP-API 头文件)
  • 类型: 功能性 bug(编译期/汇编期,非代码生成质量)
  • 严重度: High(阻断所有包含 TileOP 头文件的翻译单元;参考内核同样无法编译)

摘要

一次工具链更新(output/ 重建)引入两个独立回归,二者叠加后 任何 使用
tileop-api 的内核都无法编译。更新前同一份源码可干净编译并产出 ELF。

# 回归 层级 触发条件 现态
1 BLayout::ND2M16/BLayout::ND2M32 枚举作用域笔误 头文件(phase-1 名查找) 任何 TU 包含 template_asm.hpp 安装副本已临时改对;源未改
2 B.DIM <立即数> 被汇编器 matcher 拒收 汇编器后端 / 头文件约束 任何 TLOAD/TMULS 等模板的 valid_row/valid_col 为编译期常量 未修,无法在内核侧规避

环境

  • 编译器: output/linx_blockisa_llvm_musl/bin/clang++(clang 15.0.4,target linx64v5-unknown-linux-musl
  • 头文件根: output/linx_blockisa_llvm_musl/lib/clang/15.0.4/include/tileop-api/
  • 受影响内核(复现用):
    • SuperNPUBench/benchmark/one-level-arch/kernels/multi_thread/fa/fa_opt.hpp
    • SuperNPUBench/benchmark/one-level-arch/test/kernel/multi_thread/fa/src/fa_2d_unroll_gmma.cpp(参考内核,未改动)
  • 典型编译命令:
    export COMPILER_DIR=/Users/blacktraker/Programming/gitproj/DV4/linx-toolchain-build/output/linx_blockisa_llvm_musl/bin
    make -C benchmark/one-level-arch/test/kernel/multi_thread/fa diss \
        TESTCASE=fa_opt|fa_2d_unroll_gmma \
        COMPILER_DIR="$COMPILER_DIR" FA_MODE=FP32_VECFP32 \
        Sq=256 Skv=256 Tm=128 Tk=128 X_dim=1 Y_dim=1 OBJ_ROOT=/tmp/<build>
    

现象

回归 1:BLayout::ND2M16 / BLayout::ND2M32 笔误

template_asm.hpp:8949-8950TIMG2COL 模板内:

[Layout] "i"(tile_shape_out::BFractal == BLayout::CubeM16 ?
                     BLayout::ND2M16 : BLayout::ND2M32),

ND2M16/ND2M32 实为无作用域枚举 LayoutCvtEnumcommon/layout.hpp:64)的成员,不属于 enum class BLayoutlayout.hpp:35,成员仅 RowMajor/ColMajor/CubeM16/CubeM32/CubeN8)。此处误抄了条件里 BLayout::CubeM16 的前缀。

报错(fa_opt 根本未调用 TIMG2COL 也被拦下):

template_asm.hpp:8950:26: error: no member named 'ND2M16' in 'pto::BLayout'; did you mean simply 'ND2M16'?
template_asm.hpp:8950:44: error: no member named 'ND2M32' in 'pto::BLayout'; did you mean simply 'ND2M32'?
layout.hpp:79:3: note: 'ND2M16' declared here   // LayoutCvtEnum
layout.hpp:78:3: note: 'ND2M32' declared here   // LayoutCvtEnum

为什么所有 TU 都炸:BLayout::ND2M16 是不依赖模板参数的受限名,按
[temp.nondep] 在模板定义点(phase-1)即做名字查找与绑定,不要求 TIMG2COL
被实例化。因此任何包含该头文件的翻译单元都会在 phase-1 失败。

回归 2:B.DIM <立即数> Match Instruction Error

修补回归 1 后编译继续,撞到汇编期错误。来自工具链自身TLOAD/TMULS
模板,fa_opt 与参考内核 fa_2d_unroll_gmma 同样失败、模式一致

template_asm.hpp:2027:6: error: Match Instruction Error!   "B.DIM %[VCOL], 0, ->lb0\n"
<inline asm>:2:1: B.DIM 128, 0, ->lb0        # TLOAD,valid_col=128
template_asm.hpp:2028:6: error: Match Instruction Error!   "B.DIM %[VROW], 0, ->lb1\n"
<inline asm>:3:1: B.DIM 128, 0, ->lb1        # TLOAD,valid_row=128
template_asm.hpp:8062:6: error: Match Instruction Error!   "B.DIM %2, 0, ->lb0\n"
<inline asm>:2:1: B.DIM 128, 0, ->lb0        # TMULS,valid_col=128
template_asm.hpp:8063:6: error: Match Instruction Error!   "B.DIM %3, 0, ->lb1\n"
<inline asm>:3:1: B.DIM 32, 0, ->lb1         # TMULS,valid_row=32 (tW: 32×128)
template_asm.hpp:169/170   B.DIM 128/32 ...   # 另一处 TLOAD 变体

被拒收的立即数值都是内核 tile 的有效维度(128、32),更新前同样源码可编译。

根因分析

回归 1

BLayout(enum class)与 LayoutCvtEnum(无作用域 enum)是两个不同枚举,
ND2M16/ND2M32 属于后者。template_asm.hpp:8950 把它们误写成 BLayout::
前缀(疑似从条件 BLayout::CubeM16 复制粘贴)。属头文件笔误,phase-1 命名查找
失败,阻断所有翻译单元。

回归 2

TLOADtemplate_asm.hpp:2015-2041)等模板把 tile 的 valid_col/valid_row
"ri"(寄存器或立即数)约束送入 B.DIM 第一操作数:

const size_t valid_col = dst.GetValidCol();
const size_t valid_row = dst.GetValidRow();
asm volatile(
  "BSTART.TLSU TLOAD, %D[SrcType]\n"
  "B.DIM %[VCOL], 0, ->lb0\n"     // VCOL = "ri"(valid_col)
  "B.DIM %[VROW], 0, ->lb1\n"     // VROW = "ri"(valid_row)
  "B.DIM zero, %c[COL], ->lb2\n"  // COL = "i"(常量, 用 %c 修饰)
  ...

valid_col/valid_row 为编译期常量(fa_opt 的 128×128 Q/K/V、32×128 的
tW 等),LLVM 常量折叠把它物化为裸立即数,于是汇编文本变成
B.DIM 128, 0, ->lb0。新汇编器的指令 matcher 不再接受 B.DIM <立即数> 形式,
Match Instruction Error

对照:同一指令第三行的 B.DIM zero, %c[COL], ->lb2%c 修饰符输出常量
B.DIM zero, 128, ->lb2),不报错——说明问题不在"128 这个值越界",
而在"第一操作数位置出现裸立即数"这条匹配路径被新 matcher 移除/未实现。

波及面

  • B.DIM %<...> + "ri" 模式在 template_asm.hpp 中有 284 处,其中约
    235 处"ri" 约束。这是工具链级约定,波及 TLOAD/TSTORE/TCVT/
    TMULS/TROWMAX/TROWSUM 等几乎所有 tile 操作模板。任何 valid 维度为
    编译期常量的内核都会命中。
  • 参考内核 fa_2d_unroll_gmma(未改动)在新编译器下报与 fa_opt 完全相同
    B.DIM 128/32 错误,证明为工具链全局回归,与 fa_opt 实现无关。

责任归属

  • 回归 1:Linx-TileOP-API 头文件笔误(template_asm.hpp:8950),属明确 bug。
  • 回归 2:新汇编器后端B.DIM 指令 matcher 不接受第一操作数为立即数;
    与头文件 "ri" 约束共同作用触发。是后端 matcher 回归,还是头文件约束
    本应为 "r"(强制寄存器)而旧汇编器过于宽松,需工具链维护者定夺——但
    从用户内核侧无法规避(相关 B.DIM 全在工具链模板里)。

临时处理与建议修复

回归 1(已临时改对安装副本)

  • 临时:已把 output/.../include/tileop-api/jcore/template_asm.hpp:8950
    BLayout::ND2M16/BLayout::ND2M32 改为 LayoutCvtEnum::ND2M16/
    LayoutCvtEnum::ND2M32。仅改了安装产物,重编工具链会被覆盖。
  • 建议源侧修复:在工具链对应文件作同样一行修正即可。

回归 2(未修,无法在内核侧规避)

二选一,由工具链维护者判定:

  1. 汇编器后端恢复 B.DIM 第一操作数接受立即数(恢复旧 matcher 行为);
  2. 或将相关模板的 "ri" 约束改为 "r"(强制寄存器,规避物化为立即数)。
    该改动面大(约 235 处),但机械一致;需评估对代码生成质量的影响。

在回归 2 修复前,建议回滚本次工具链更新至可编译状态,以恢复日常构建与
gfrun 回归。

复现

cd /Users/blacktraker/Programming/gitproj/DV4/SuperNPUBench
export COMPILER_DIR=/Users/blacktraker/Programming/gitproj/DV4/linx-toolchain-build/output/linx_blockisa_llvm_musl/bin

# fa_opt(优化 FA 内核)
make -C benchmark/one-level-arch/test/kernel/multi_thread/fa diss \
    TESTCASE=fa_opt COMPILER_DIR="$COMPILER_DIR" FA_MODE=FP32_VECFP32 \
    Sq=256 Skv=256 Tm=128 Tk=128 X_dim=1 Y_dim=1 OBJ_ROOT=/tmp/fa_opt_v4

# 参考内核(未改动,更新前可编译)
make -C benchmark/one-level-arch/test/kernel/multi_thread/fa \
    TESTCASE=fa_2d_unroll_gmma COMPILER_DIR="$COMPILER_DIR" FA_MODE=FP32_VECFP32 \
    Sq=256 Skv=256 Tm=128 Tk=128 X_dim=1 Y_dim=1 OBJ_ROOT=/tmp/fa_ref_v4

# 观察:
#  - 回归1:template_asm.hpp:8950 no member named 'ND2M16' in 'pto::BLayout'
#  - 回归2:template_asm.hpp:2027/2028/8062/8063/169/170 Match Instruction Error
#           + <inline asm> B.DIM 128/32, 0, ->lb0|lb1
#  - 两者均出现在 fa_opt 与 fa_2d_unroll_gmma 上,模式一致。

附:fa_opt 侧未改动

fa_opt.hpp / fa_opt.cpp 与上一可编译状态(OBJ_ROOT=/tmp/fa_opt_v3,旧编译器)
一致,未为本次更新做任何调整;上一状态编译干净,反汇编已验证
TMATMUL=8, TCVT=0, B.TRB=0(无 transpose_b)。本次失败完全由工具链回归造成。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions