Skip to content

[编译器问题] __blkc_bf16 类型在 TCOPYIN/TCOPYOUT 中因地址空间不兼容导致编译失败 #5

Description

@flaviomarix

问题描述

使用 Linx BlockISA 编译器(clang 15.0.4, target linx64v5-linux-musl)编译包含 TCOPYIN/TCOPYOUT 操作的 kernel 代码时,当数据类型为 __blkc_bf16(bf16 结构体类型),编译器报错:

error: no viable overloaded '='
  blkv_get_tile_ptr(dst)[index_tile] = src[index_gm];   // TCopyIn.hpp:109
  dst[index_gm] = blkv_get_tile_ptr(src)[index_tile];   // TCopyOut.hpp:81

具体错误信息:

candidate function (the implicit copy assignment operator) not viable: 'this' object is in address space '6', but method expects object in generic address space
candidate function (the implicit move assignment operator) not viable: 'this' object is in address space '6', but method expects object in generic address space

根本原因分析

  1. __blkc_bf16 是一个 struct(定义于 linx_blkc.h),继承自 __bf16_base,包含 short data 成员字段。其赋值操作依赖隐式的拷贝/移动赋值运算符(成员函数)。

  2. blkv_get_tile_ptr() 返回 __vbuf__(即 __attribute__((address_space(6)))指针,这意味着 tile 中的元素位于 地址空间 6(向量缓冲区专用地址空间)。

  3. TCOPYIN/TCOPYOUT 内部的全局内存指针 src/dst 位于 通用地址空间(address space 0)

  4. 赋值语句 blkv_get_tile_ptr(dst)[index_tile] = src[index_gm] 需要调用 __blkc_bf16 的拷贝赋值运算符,但该运算符的 this 参数(左侧,地址空间 6)与运算符期望的通用地址空间(address space 0)不匹配,导致编译失败。

  5. 对于 floatint 等标量类型,赋值是简单的值拷贝,不涉及成员函数调用,不受地址空间约束。而 __blkc_bf16struct,赋值会调用隐式成员函数,受地址空间限制。

复现步骤

编译命令

cd test/kernel/element_wise/gelu
make TESTCASE=gelu DTYPE=__bf16 tMs=2048 gMs=24*8*1024 SHAPE_NAME=24_8_1024 Approximate=false diss

完整编译命令展开

clang++ -c -target linx64v5-linux-musl -mlxbc -fenable-matrix -O2 \
  --sysroot=<toolchain_path>/sysroot \
  -isystem <toolchain_path>/sysroot/usr/include/c++/v1 \
  -D_LIBCPP_HAS_NO_THREADS -std=c++20 \
  -I<project>/include -I<project>/test/common -I<project>/kernels \
  -DDTYPE=__bf16 -DtMs=2048 -DgMs=24*8*1024 -DApproximate=false -D__linx \
  gelu.cpp -o gelu.o

对比:float 类型可以正常编译

make TESTCASE=gelu DTYPE=float tMs=2048 gMs=24*8*1024 SHAPE_NAME=24_8_1024 Approximate=false diss
# 编译成功(但 gelu.hpp 中的 .data 成员访问会报另一个错误,说明 float 和 __blkc_bf16 的处理方式不同)

完整编译错误输出

In file included from gelu.cpp:1:
In file included from <toolchain>/include/tileop-api/common/pto_tileop.hpp:5:
In file included from <toolchain>/include/tileop-api/common/tileop_api.hpp:4:
In file included from <toolchain>/include/tileop-api/common/tileop_api_impl.hpp:16:
<toolchain>/include/tileop-api/jcore/TCopyIn.hpp:109:38: error: no viable overloaded '='
  blkv_get_tile_ptr(dst)[index_tile] = src[index_gm];
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^ ~~~~~~~~~~~~~
  ...
  <toolchain>/include/linx_blkc.h:117:8: note: candidate function (the implicit copy assignment operator) not viable: 'this' object is in address space '6', but method expects object in generic address space
  <toolchain>/include/linx_blkc.h:117:8: note: candidate function (the implicit move assignment operator) not viable: 'this' object is in address space '6', but method expects object in generic address space

<toolchain>/include/tileop-api/jcore/TCopyOut.hpp:81:17: error: no viable overloaded '='
  dst[index_gm] = blkv_get_tile_ptr(src)[index_tile];
  ~~~~~~~~~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  ...
  <toolchain>/include/linx_blkc.h:117:8: note: candidate function (the implicit copy assignment operator) not viable: cannot bind reference in address space '6' to object in generic address space in 1st argument
  <toolchain>/include/linx_blkc.h:117:8: note: candidate function (the implicit move assignment operator) not viable: cannot bind reference in address space '6' to object in generic address space in 1st argument

影响范围

此问题影响所有使用 __blkc_bf16(以及其他类似的 blkc struct 类型,如 __fp8_e4m3__fp8_e5m2__tf32__hf32 等)作为数据类型进行 TCOPYIN/TCOPYOUT 操作的 kernel。这些 struct 类型都无法在 TCOPYIN/TCOPYOUT 中跨地址空间赋值。

修复建议

此问题需要在编译器/工具链侧修复,有两种思路:

方案 A:在 __blkc_bf16 等 struct 类型中添加跨地址空间的赋值运算符

linx_blkc.h 中为 __blkc_bf16(及其他类似 struct)添加支持地址空间 6 的赋值运算符重载,例如:

struct __blkc_bf16 : public __bf16_base {
  __blkc_bf16() = default;
  
  // 添加跨地址空间赋值运算符
  __blkc_bf16& __vbuf__ operator=(const __blkc_bf16& other) {
    data = other.data;
    return *this;
  }
  // 可能还需要 __vbuf__ 版本的拷贝构造等
};

方案 B:在 TCopyIn.hpp/TCopyOut.hpp 中对 struct 类型只拷贝其底层 .data 成员

对 blkc struct 类型,在赋值时只拷贝 .data 字段(标量类型,不受地址空间限制),而非整个结构体赋值:

// TCopyIn 中:
blkv_get_tile_ptr(dst)[index_tile].data = src[index_gm].data;

// TCopyOut 中:
dst[index_gm].data = blkv_get_tile_ptr(src)[index_tile].data;

关键文件说明

为方便复现和定位,以下文件已作为 issue 附件上传:

文件 说明
linx_blkc.h 编译器内置类型定义,__blkc_bf16 struct 定义所在(第117行),__vbuf__ 宏定义(第8行)
TCopyIn.hpp 编译器 tileop-api 库,TCopyIn_Vec_RowMajor 报错位置(第109行)
TCopyOut.hpp 编译器 tileop-api 库,TCopyOut_Vec_RowMajor 报错位置(第81行)
gelu.hpp 用户 kernel 代码,第115行调用 TCOPYIN,第119行调用 TCOPYOUT
gelu.cpp 用户测试代码入口,第71行调用 gelu 函数
Makefile 编译配置
Makefile.common 公共编译配置,定义编译器路径和编译选项

工具链版本信息

  • 编译器路径:compiler/toolchain/2026-06-22/linx_blockisa_llvm_musl/bin/clang++
  • clang 版本:15.0.4
  • target:linx64v5-linux-musl
  • 编译选项:-mlxbc -fenable-matrix -O2

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions