Skip to content

LlvmTpu 内在表

此页面上的所有计数、名称和地址适用于 libtpu-0.0.40-cp314 轮中的 libtpu.so(构建 ID 89edbbe81c5b328a958fe628a9f2207d,745 MB,ELF x86-64,未剥离)。其他 libtpu 构建每代都会添加/删除内部函数; 1356 数字与此版本完全相同。

摘要

TPU LLVM 后端公开 llvm.tpu.* 目标内在函数的平面命名空间 — SparseCore MLIR 方言 (mlir::sparse_core::*) 降低到的堆栈底部 IR 表面,并且 SelectionDAG 指令选择器与之匹配。本附录是该表面的主要枚举:正好 1356 个不同的内在函数,从符合操作的二进制文件中恢复了两种独立的方式(请参阅 §验证)。每个都是 ODS 注册的 MLIR 操作(C++ 类 tpu_X_Y_Z)和 LLVM 内部名称(llvm.tpu.X.Y.Z,下划线→点);两组是相同的。

这是参考目录,而不是算法页面。深层语义 - 槽位布局、降低机构、ISel 匹配器臂、每个引擎描述符编码 - 位于 sparsecore/isa/ 页面上,该表按系列交叉链接。在这里,重新实现者获得了空间的形状:系列、每个系列的确切数量、每个系列的代表性枚举子集,以及每个系列降低到的 LLO 操作/硬件单元/SparseCore 引擎。

最重要的结构事实:**llvm.tpu.* 表面是 SparseCore 内在 ISA,而不是 TensorCore。**它不包含 MXU/matmul 和 XLU/转置内在函数 - 这些通过单独的 tpu→LLO TensorCore ODS 路径。 llvm.tpu.* 系列以 SparseCore 嵌入流引擎为主(62%),详细信息请参见下面的 备注

为了重新实现,目录必须捕获:

  • 名称↔类双射 — 每个 llvm.tpu.X 内在函数都有一个 mlir::sparse_core::tpu_X 模型,反之亦然;打印名称字符串是带入后端的 LLVM 内部名称。
  • 功能分类 — 每个内在函数都属于 ~20 个家族中的一个;所列举的 20 个家庭恢复了 1356 个家庭中的 1341 个,其中约 15 个家庭处于中等置信度家庭边界(参见 §概览)。
  • 系列→硬件映射 — 每个系列降低到哪个 LLO 插槽/操作、SparseCore 计算单元或流引擎描述符,以及通过哪个通道。
  • 每代变异 - 新一代添加了内在函数(此版本是其目标世代的联合);计数是每个构建的快照。
总内在函数1356(两种方式确认,零错配)
印刷名称字符串1356 不同的 llvm.tpu.*.rodata
模型类别1356 个不同的 mlir::sparse_core::tpu_* RegisteredOperationName::Model vtable
名称↔类映射机械:tpu_X_Yllvm.tpu.X.Y(下划线→点)
注册registerLlvmTpuDialectOperations @0x146d0560,10批分注册商
方言mlir::sparse_core::LlvmTpuDialect(构造函数@0x146cde80)
MLIR→IR翻译convertOperation @0x13933e40createIntrinsicCall @0x1683f440
消耗下降通道LowerToSparseCoreLlvmPass::runOnOperation @0x13566d00
主导家庭llvm.tpu.stream.* — 834 次操作 (62%)
表面范围SparseCore — 无 MXU,无 XLU 内在函数

验证 {#verification}

1356这个数字不是凭信心得出的;它是来自该二进制文件的两个独立恢复的一致点。

  • 打印名称字符串。 .rodata 打印名称表包含 1356^llvm\.tpu\. 匹配的不同字符串(例如 llvm.tpu.addrspacecastllvm.tpu.stream.linear.gather.add.f32.hbm.to.tilespmem)。重新探测的注意事项:一些名称带有大写字母(scan2xNscan1xNf)——[a-z0-9_.] 字符类计数不足至 1060;正确的计数需要 [^"] 或明确的大写余量。
  • 模型类 vtables。 符号表保存 1356 不同的 mlir::sparse_core::tpu_* 类名(每个内在的 RegisteredOperationName::Model<…> 注册概念)。 vtable跨度运行tpu_16i1_to_32i1tpu_wrcbreg_tilespmem_base
  • 设置身份。 将每个类 tpu_X 映射到 llvm.tpu.X(下划线→点)并与字符串集进行比较会产生零不对称差异 - 每个模型都有一个打印名称,反之亦然。

注意 — 下面的每个系列子计数是来自打印名称字符串的字节 grep 总数,按名称前缀分类。少数操作是可双重分类的(例如,sc.permute 既是通道操作又是 SC 控制操作),因此两名分析师可能会在相邻系列之间转移一个或两个操作; 总数是准确的,并且主要系列(流、打包/解包、vld/vst、等待/观看、dma、扫描、转换)是准确的。带有歧义的家庭行被标记为 MEDIUM 信心。

注意 — llvm.tpu.* 表面包含无 MXU/matmul 且无 XLU/转置置换内在函数mat 的全表 grep 返回 0;对于 xlu/transp 返回 0。 MXU 和 XLU 操作名册是通过单独的 tpu→LLO 322-op ODS 路径(参见 isa/slot-mxu.mdisa/xlu-op-roster.md)而不是通过 llvm.tpu.* 实现的 TensorCore 概念。期望 llvm.tpu.matmul 的重新实现者将找不到它; SparseCore 上的 matmul 握手记录在 sparsecore/sc-mxu-handshake.md 中。此页面的系列仅是 SparseCore 矢量/标量/内存/流/同步/控制原语。


概览 — 族分类 {#at-a-glance--family-taxonomy}

每个内在函数都分配给一个系列。 20 个枚举的家族行恢复了 1356 个 grep 确认的名称中的 1341 个;其余 15 个位于相邻族之间的中等置信度边界上,并在显式余数行中进行携带,而不是强制分配。 LLO/HW 列是降低目标:SparseCore 重用它的 TensorCore 风格的 LLO 插槽/操作、SparseCore 特定的计算单元或 SparseCore 流引擎。状态:C = 在其他地方进行字节确认的编码,I = 由名称系列标识的引擎,操作码未单独进行字节转储。

家族#LLO操作/硬件单元St
流(聚集/分散/vreg)834SparseCore 流/分散引擎描述符 → LowerToSparseCoreLlvm → LLVM 调用I
打包/解包(子元素)87VPU 打包/拆包插槽 → llo.vpack* / llo.vunpack*C
矢量加载/存储74VPU 内存插槽 → llo.vector_{load,store}[_masked]C
信号量等待/观看47sflag V等待槽 → llo.vwait.{eq,ne,lt,le,gt,ge}[.done]C
DMA描述符40SparseCore DMA 引擎 cmd(3 个复杂度层)C
扫描/分段扫描/缩小32SparseCore 扫描单元(add/max/min × full/half/1xN/2xN × seg × index)I
矢量转换28VPU转换插槽 → llo.vcvt.*C
分配/分配24SparseCore分配器(smem/spmem/vmem/sflag/hbm/iova/timem/tilespmem/dreg/cbreg)C
信号量设置/添加(sflag)22sflag VSync 插槽 → llo.vsync.{add,set}[.done,.remote]C
超验/EUP22EUP VALU3推送(Alu3 op0 + 5位选择器)+ PopEupResultC
控制寄存器rd/set21标量 RdReg/SetReg → SCS 标量槽C
指针/寻址/循环-bc16LLVM inttoptr/ptrtoint/addrspace + 循环字节码C
地址空间广播16幸存的 @llvm.tpu.addrspacecast.* IR 内部调用(ID 0x33b10x33c0)C
标量 ALU / 标量内存14SCS 标量槽(移位、溢出加法、addcarry、add_high/low_f32)C
车道/子车道排列14VPU跨通道插槽 → llo.vrot.slane / vperm.sublane / sc.permuteC
CBREG /循环缓冲区12标量 CBREG 操作(ReadCbreg/WriteCbreg/AddCbreg/MoveCbreg/SLD/SST.cb)C
跟踪/遥测/sc-控制12SparseCore 控制/跟踪(strace、事件、周期计数、ssetpstate)C
排序/唯一/重复计数11SparseCore排序/重复数据删除单元(嵌入重复数据删除)I
任务/控制/结构10SparseCore 平铺任务 + 结构(task_dispatch、loop_*、barrier、nop)C
i1-掩模宽度转换5VPU mask slot — 矢量掩模宽度重新打包C
未分类余数(边界/杂项)15分布在中等置信度家族中 — 未单独列举I
总计1356

总和检查:834+87+74+47+40+32+28+24+22+22+21+16+16+14+14+12+12+11+10+5 = 1341; 20 个枚举家族恢复了 1356 个 grep 确认的名称中的 1341 个,在该分类法未单独存储的中等置信度家族边界上留下了 15 个内在函数(上面的“未分类剩余”行)。 1356总计是字节确认的真相;每个系列的划分是分析师分类,仅适用于 grep 锚定的系列(stream、pack/unpack、vld/vst、wait/watch、dma、scan、convert、alloca、sync、addrspacecast、i1-width)。


流引擎——主导家族 {#stream-engine-the-dominant-family}

1356 个内在函数中的 834 个 (62%) 是 llvm.tpu.stream.*:SparseCore 嵌入流/分散引擎。这是一个编码为不同操作的组合叉积 - 硬件流命令变体是通过操作标识而不是属性来选择的,因此类型系统带有 (pattern, verb, dtype, memspace) 选择。深层语义存在于 sparsecore/stream-gather-scatter.mdsparsecore/indirect-vreg-stream.md 上;不要在此处重现 834 行。

叉积轴

贡献计数
图案linear · strided · indirect线性 180 · 跨步 114 · 间接 540
动词vreg(聚集+分散)、gather(非vreg)、scatter(非vreg)vreg 360 · 聚集 246 · 分散 228
dtypebf16 · e4m3 · e5m2 · f32 · s16 · s32每个数据类型 111 个操作(×6 = 666 个数据类型)
_to_tilespmem · _to_spmem · _to_smem · _to_hbm4b · _to_hbmtilepmem 399 · spmem 210 · smem 27 · hbm4b 15 · hbm 15
修改器.cb.(CBREG 窗口)·.add(分散添加)·.np(无谓词)CB 窗口 556 / 834

命名模板

text
llvm.tpu.stream.<pattern>.[vreg.]{gather|scatter}.[cb.][add.]<dtype>.<src>.to.<dst>

e.g.  llvm.tpu.stream.linear.gather.add.f32.hbm.to.tilespmem
      (class tpu_stream_linear_gather_add_f32_hbm_to_tilespmem;
       create(OpBuilder&, Location, Value×6) — 6 SSA operands)

CBREG 窗口间接形式(556 个操作)使用 INDIRECT_OFFSET_SOURCE_CBREG 源进行嵌入表窗口(请参阅 sparsecore/cbreg.md)。间接收集将嵌入行从 HBM/SPMEM 表(由 CBREG 窗口偏移流索引)拉入图块本地 SPMEM;匹配的分散相加将累积的梯度推回原处。这些通过 LowerToSparseCoreLlvmPass @0x13566d00 将 LLVM 调用降低到流/分散引擎中。

明白了 — 没有带有属性选择器的单个 llvm.tpu.stream 操作。将流引擎建模为一个参数化操作的重新实现者将会与二进制文件不匹配,二进制文件将所有 834 个组合注册为单独的操作,并通过 ISel 匹配器中的操作标识来调度它们。 834 路爆炸就是编码。


打包/解包(子元素暂存) {#pack--unpack-subelement-staging}

87 操作。 VPU 打包/解包插槽 — 用于量化 MXU 源的子字节宽度分级。降低至 llo.vpack* / llo.vunpack*(参见 isa/pack-unpack-precision.mdisa/slot-vpu.md)。

代表内在它的作用是什么降低至
llvm.tpu.packc标量包压缩VPU包插槽
llvm.tpu.pack.c.b32.b16包 b32 → b16llo.vpack(宽度阶段)
llvm.tpu.pack.c.b16.b8包 b16 → b8llo.vpack
llvm.tpu.pack.c.b8.b4包 b8 → b4llo.vpack
llvm.tpu.pack.c.b4.b2包 b4 → b2llo.vpack
llvm.tpu.pack.c.b2.b1包 b2 → b1llo.vpack
llvm.tpu.pack.c.f32.bf16包 f32 → bf16llo.vpack
llvm.tpu.pack.c.bf16.e4m3包 bf16 → e4m3 (FP8)llo.vpack
llvm.tpu.pack.c.bf16.e5m2包 bf16 → e5m2 (FP8)llo.vpack
llvm.tpu.pack.c.bf16.s8 / .bf16.u8包 bf16 → s8/u8llo.vpack
llvm.tpu.pack.c.b16i1.b8i1面膜 b16i1 → b8i1VPU面膜包
llvm.tpu.unpack.*逆宽度扩展llo.vunpack

宽度阶梯为 b32 → b16 → b8 → b4 → b2 → b1,具有 FP8 (e4m3/e5m2) 和整数 (s8/u8) 端点用于量化。


矢量加载/存储(vmem/cb) {#vector-load--store-vmem--cb}

74 操作。 VPU 内存插槽 → llo.vector_{load,store}[_masked]sparsecore/vectorload-slot.mdsparsecore/vectorstore-slot.md 的语义; isa/slot-memory-load.md / isa/slot-memory-store.md 上的插槽编码。

该系列是 vld/vst 基础上的修改器叉积。每个负载都被屏蔽(.msk);商店添加分散 (.add) 和 FP8 商店包 (.e4m3/.e5m2)。

修改器含义
.msk屏蔽(谓词)- 存在于所有
.cbCBREG窗口地址
.upd更新后自动递增
.idx已索引(聚集/分散地址)
.strided跨步访问
.add分散添加(存储端减少)
.e4m3 / .e5m2FP8 存储包
.np无谓词快速变体
代表内在它的作用是什么
llvm.tpu.vld.msk屏蔽矢量加载
llvm.tpu.vld.msk.idx屏蔽索引(收集)负载
llvm.tpu.vld.msk.strided屏蔽跨步负载
llvm.tpu.vld.cb.mskCBREG 窗口屏蔽负载
llvm.tpu.vld.cb.upd.mskCBREG 窗口更新后屏蔽加载
llvm.tpu.vst.cb.mskCBREG 橱窗蒙面商店
llvm.tpu.vst.cb.msk.addCBREG 窗口屏蔽分散添加存储
llvm.tpu.vst.cb.msk.add.e4m3分散添加存储,FP8 封装
llvm.tpu.vst.cb.msk.idx.add索引分散添加存储

同步/等待/观看(sflagatomics) {#sync--wait--watch-sflag-atomics}

sflag(信号量标志)原子表面分为本页一起计数的子系列。字节确认联合 (^llvm\.tpu\.(sync|sfence|wait|watch|fetch)) 为 73 操作sync*/sfence = 25、wait* = 31、watch* = 16、fetch.and.add = 1。(上面的分类行对此进行了不同的划分 - 等待/观察= 47,同步设置/添加 = 22 — 三个 sync{donemov,pamov,readpa} 操作和 fetch.and.add 位于相邻行中。)所有这些都通过 VPU/SPU 同步/等待槽以 sflag 组为目标(请参阅 isa/slot-vpu.mdisa/slot-spu-scalar.md)。

同步/设置/添加 — 22 个操作 → llo.vsync.{add,set}

代表内在它的作用是什么
llvm.tpu.syncadd原子添加到 sflag
llvm.tpu.syncadd.done / .notdone添加 + 信号完成/未完成
llvm.tpu.syncadd.remote / .remote.done / .remote.doneinv通过 ICI 添加到对等核心的 sflag
llvm.tpu.syncadd.tile / .both / .other每块/双向/其他银行目标
llvm.tpu.syncset.done / .notdone / .both / .both.done原子集
llvm.tpu.syncset.remote[.done/.doneinv]通过 ICI 远程设置
llvm.tpu.syncset.tile[.done/.doneinv]每块套装
llvm.tpu.syncsetpa集,公共访问银行
llvm.tpu.sfencesflag 内存栅栏

等待/观看 — 47 次操作 → llo.vwait.{eq,ne,lt,le,gt,ge}[.done]

代表内在它的作用是什么
llvm.tpu.waiteq / waitne / waitlt / waitle / waitgt / waitge等待 sflag {==,!=,<,<=,>,>=} 阈值
llvm.tpu.wait{eq,ge,…}ordone等待或完成变体
llvm.tpu.wait{…}.yieldable定序器等待产量变体
llvm.tpu.wait{eq,ge,gt,lt,ne}.imem指令-内存-标志等待
llvm.tpu.waitdone / .yieldable等待完成信号
llvm.tpu.waitnotdone / .yieldable等待未完成
llvm.tpu.watch{eq,ne,lt,gt,…}[ordone]无阻塞手表臂
llvm.tpu.watch.wait / .wait.sel / .end / .end.sel监视寄存器生命周期
llvm.tpu.fetch.and.addsflag 读取-修改-写入 (V, V, V)

QUIRK — _remote 通过 ICI 路由到对等核心的 sflag(超大规模屏障路径),.tile/.pa 目标为每块/公共访问库,.doneinv 反转完成意义,并且.yieldable 让定序器在受阻时屈服。重新实现者必须将这些后缀视为不同的硬件行为,而不是装饰别名。


DMA 描述符生成器 {#dma-descriptor-builders}

40 操作。 SparseCore DMA 引擎命令构建器。命名为 llvm.tpu.dma.<src>.to.<dst>.sc.{simple,single.strided,general}。后缀是描述符复杂度层;该层由类型化创建操作数计数来确认。

等级后缀# 操作操作数(位置之后)
简单.sc.simple168 值(src、dst + 基数/偏移量/大小 + sflag)
单步.sc.single.strided1211 值(+1 步幅三倍)
通用.sc.general1216 值(+ 多暗淡步幅/尺寸)

src/dst 系列涵盖 hbmiovasmemspmemtimemsimem。代表:llvm.tpu.dma.hbm.to.spmem.sc.simplellvm.tpu.dma.spmem.to.hbm.sc.single.stridedllvm.tpu.dma.hbm.to.spmem.sc.general。 (iova src/dst 仅出现在 simple/single.strided 层中,而不出现在 general 中。)这些是高级 DmaSimpleStart / DmaSingleStridedStart / DmaGeneralStart 方言的 SparseCore 等效项操作;本质是后端转化为DMA引擎命令的后降低形式。


扫描/缩减(嵌入聚合) {#scan--reduce-embedding-aggregation}

32 操作。 SparseCore 扫描单元——嵌入聚合原语。 sparsecore/scan-datapath.mdsparsecore/segmented-scan.mdsparsecore/segmented-add-scan.md 上的深度数据路径。

该系列是一个干净的交叉产品:{add, max, min} × {scan1xN, scan2xN} × {seg, non-seg} × {index, value} × {f, i}

代表内在它的作用是什么
llvm.tpu.add.scan1xNf / .add.scan1xNi1×N 前缀和,浮点/整数
llvm.tpu.add.seg.scan1xNf分段1×N前缀和
llvm.tpu.add.full.scan2xN / .add.half.scan2xN2×N扫描,全/半
llvm.tpu.add.full.seg.scan2xN分段2×N全扫描
llvm.tpu.max.scan1xNf / .max.scan2xN最大扫描
llvm.tpu.max.index.scan1xNfargmax-索引扫描
llvm.tpu.max.seg.index.scan2xN分段argmax扫描
llvm.tpu.min.scan1xNi / .min.seg.scan2xN最小/分段最小扫描

.seg 标记分段(分段边界感知)扫描; .index 产生 arg-position 而不是值。


矢量转换 {#vector-convert}

28 操作。 VPU转换插槽→llo.vcvt.*(参见isa/slot-vpu.md)。 Float↔int 和 float↔narrow-float 转换,具有随机轮 (.sr) 和概率轮 (.pr) 变体。

代表内在它的作用是什么
llvm.tpu.vcvt.f32.bf16 / .f32.bf8 / .f32.hf16 / .f32.if8加宽窄浮点 → f32
llvm.tpu.vcvt.s32.f32 / .f32.s32int ↔ 浮点
llvm.tpu.vcvt.bf16.s4 / .bf16.s8 / .bf16.u4 / .bf16.u8dequant int → bf16
llvm.tpu.vcvt.s4.bf16 / .s8.bf16 / .u4.bf16 / .u8.bf16定量 bf16 → int
llvm.tpu.vcvt.sr.f32.bf16 / .sr.fptobf16随机回合收窄
llvm.tpu.vcvt.fptobf16 / .fptobf8 / .fptohf16 / .fptoif8浮点 → 窄浮点
llvm.tpu.cvt.fptosi / .cvt.pr.fptosi标量浮点数 → 有符号整数

分配/分配 {#alloca--allocate}

24 操作。 SparseCore 分配器 → 每个银行的分配。 tpu_alloca_*是堆栈式分配; tpu_allocate_* 是每个银行(包括 CBREG)的分配器。银行:smemspmemvmemsflaghbmiovatimemtilespmemdregcbreg,加上 _dyn(动态)和 _any(任何银行)。代表:llvm.tpu.alloca.smemllvm.tpu.alloca.sflagllvm.tpu.allocate.dregllvm.tpu.allocate.cbreg


超验/EUP {#transcendental--eup}

22 操作。扩展单元管道 (EUP) 超越 — VALU slot-3 push + pop 对。每个都以 1:1 的方式映射到 V5+ EUP 超越,其函数→选择器值在 isa/slot-eup-transcendental.md 上解码。推入的是VALU Alu3(操作码0x0 + 5位选择器);结果通过 VectorResult0 PopEupResult 槽排出。

内在 (+.macro)功能EUP选择器(F32 / Bf16)
llvm.tpu.rcp倒数0x15 / 0x1d
llvm.tpu.rsqrt倒数平方根0x10 / 0x0c
llvm.tpu.tanhtanh0x13 / 0x1b
llvm.tpu.sigshft移位 S 形0x14 / 0x1c
llvm.tpu.log2log20x12 / 0x1a
llvm.tpu.pow20x11 / 0x19
llvm.tpu.erf错误函数0x0e / 0x0f
llvm.tpu.sin正弦(Sinq)0x17 / 0x1e
llvm.tpu.cos余弦 (Cosq)0x18 / 0x1f

裸形式(llvm.tpu.sin)是原始EUP推送; .macro 形式(llvm.tpu.sin.macro,键入 (Type, Value) → 1 个结果,1 个操作数)是push+pop 宏。加上非配对的 EUP 操作:llvm.tpu.exponentllvm.tpu.significandllvm.tpu.vclass(FP 分类)、llvm.tpu.eup.pop(显式结果消耗)。


控制寄存器rd/set {#control-register-rd--set}

21 操作。标量控制寄存器读/写 → SCS 标量槽 RdReg/SetReg(参见 isa/slot-spu-scalar.md)。

代表内在寄存器读取/设置
llvm.tpu.rdreg.gtc.hi / .gtc.lo全局时间计数器(64 位,高/低)
llvm.tpu.rdreg.lcc.hi / .lcc.lo本地周期计数器
llvm.tpu.rdreg.crr.hi / .crr.lo核心资源计数器
llvm.tpu.rdreg.tid / .scid / .tag / .tbm / .tm线程/稀疏核心/标签/tile-base/tile-mask id
llvm.tpu.rdreg.fsr / .ddr / .dmacrdt / .btr / .yieldreq状态/信用/收益寄存器
llvm.tpu.setreg.sflagrange / .dmacrdt / .pdepth / .tag / .ifvalue配置sflag范围/DMA信用/谓词深度

指针/寻址/循环字节码 {#pointer--addressing--loop-bytecode}

16 操作。 LLVM inttoptr/ptrtoint/addrspace 加上循环字节码帮助程序。代表:llvm.tpu.inttoptrllvm.tpu.ptrtointllvm.tpu.make.restrict.ptrllvm.tpu.bc.load.aliaddrllvm.tpu.bc.store.aliaddrllvm.tpu.bc.select.predicatellvm.tpu.bc.extractvalue.loopindexllvm.tpu.bc.insertvalue.loopindexbc.*(循环字节码)操作在 ID 0x33d9/0x33daPerformDAGCombine 操作码 0x30 臂中处理。 (MEDIUM — 几个 bc.*loopindex 操作上任务/结构重叠的边界。)


AddrSpaceCast {#addrspacecast}

16 操作。 SparseCore 地址空间转换转换。这些系列的后端处理是端到端的字节跟踪,并纠正了一个常见的假设 - 它们作为幸存的 LLVM-IR 内部调用发出,而不是折叠到通用 IR addrspacecastISD::ADDRSPACECAST。对sparsecore/addrspacecast-isel.mdsparsecore/tile-id-cast.md进行深度处理。

全16

text
llvm.tpu.addrspacecast                          (plain, 1-operand)
llvm.tpu.addrspacecast.scs
llvm.tpu.addrspacecast.smem
llvm.tpu.addrspacecast.spmem
llvm.tpu.addrspacecast.tac
llvm.tpu.addrspacecast.tc
llvm.tpu.addrspacecast.tec
llvm.tpu.addrspacecast.scs.sflag.scs
llvm.tpu.addrspacecast.tec.sflag.tec
llvm.tpu.addrspacecast.smem.tile.scs
llvm.tpu.addrspacecast.smem.tile.tec
llvm.tpu.addrspacecast.sflag.tile.scs
llvm.tpu.addrspacecast.sflag.tile.tac
llvm.tpu.addrspacecast.sflag.tile.tec
llvm.tpu.addrspacecast.sflag.tile.sflag.scs
llvm.tpu.addrspacecast.sflag.tile.sflag.tec

普通转换为 1 操作数 (create(Type, Value));每核 (tec/tac/scs) 和平铺窗口形式需要额外的 i32tile-id 值。

排放和遣散

舞台网站行动
MLIR 操作 → IR 调用convertOperation @0x13933e40(16臂0x1393c4600x1393c8da)→蹦床@0x1393bf27createIntrinsicCall @0x1683f440发出 @llvm.tpu.addrspacecast.* IR 调用,固有 ID 0x33b10x33c0 (13233–13248) — 根据 IntrinsicNameTableStorage @0x4179440 的存储顺序进行字节验证(llvm.tpu.addrspacecast = ID 0x33b1;之前的 0x33b00x33bf 推导偏差了 1)
IR内在幸存(无转换)未降低至 ISD::ADDRSPACECAST (0xf4) — 无匹配臂,无 Select/LowerOp/Combine
放电通用 INTRINSIC_WO_CHAIN 折叠/消耗 SC 加载存储 ISel保值铸件被消费者吸收(推断)

注意 — SparseCore addrspacecast 内在函数不会成为 ISD::ADDRSPACECAST (0xf4) 节点。 0xf4 节点仅由真正的 IR addrspacecast 指令(通过 SelectionDAGBuilder::visitAddrSpaceCast @0x19333020getAddrSpaceCast @0x192e2360)产生,没有 TPU/SparseCore 代码发出 — 整个 .text 外部参照addrspacecast 构造函数将每个调用者放置在通用 LLVM 中,没有放置在 TPU/SC 频段中。铸造内在系列和 0xf4/0xf3 降低是两个独立的机制; 0xf40xf3 寄存器复制路径仅服务于通用 TensorCore 前端。 0x33b10x33c0 的唯一 ID 键控后端站点是:convertOperation 发出、Select 默认路由表 (@0xaec81ec idx 0x100x1fSelectCode默认)和 TPUVerifier::runImpl @0x13c54912(仅验证)。无下降部位。


标量 ALU / 标量内存 {#scalar-alu--scalar-mem}

14 操作。 SCS 标量槽 — 移位、溢出算术、进位、FP 分量加法。代表:llvm.tpu.shllllvm.tpu.shrallvm.tpu.shrlllvm.tpu.sshllollvm.tpu.sadd.ovllvm.tpu.ssub.ovllvm.tpu.sshla.ov(溢出标记加/减/移)、llvm.tpu.addcarryllvm.tpu.add.high.f32.bf16llvm.tpu.add.low.f32.bf16(bf16-分解-f32 添加一半)。 (MEDIUMadd.high/low.f32.bf16 也可以分组在 EUP/精度下。)


车道/子车道排列 {#lane--sublane-permute}

14 操作。 VPU 跨通道槽 — 子通道洗牌/旋转/排列和 SC 排列。代表:llvm.tpu.vrot.sublanellvm.tpu.vrot.sublane.downllvm.tpu.vperm.sublanellvm.tpu.vshift.insertllvm.tpu.sc.permutellvm.tpu.sc.mask.permute,加上vlaneseq序列生成器形式(llvm.tpu.vlaneseq.c.bf16.i.bf16.u32)。有关排列驱动的基数排序的使用,请参阅 sparsecore/rank-and-permute-radixsort.md。 (MEDIUMsc.permute/sc.mask.permute 跨式车道操作与 SC 控制。)


CBREG /循环缓冲区 {#cbreg--circular-buffer}

12 操作。标量 CBREG(循环缓冲区寄存器)操作驱动每组 16 个 CBREG 循环缓冲区,对 SMEM 和 TILE_SPMEM 进行窗口化。 sparsecore/cbreg.md 上的完整编码。

内在LLO 操作
llvm.tpu.rdcbreg.offset / .size / .smem.base / .tilespmem.baseReadCbreg (0x36), CbregMetadata {BASE=0,SIZE=1,OFFSET=2}
llvm.tpu.wrcbreg.offset / .size / .smem.base / .tilespmem.baseWriteCbreg (0x35)
llvm.tpu.cbreg.add.offset / .add.offset.in.placeAddCbreg(0x33,目标偏移)
llvm.tpu.copy.cbregMoveCbreg(转义0x00/子0x1b)
llvm.tpu.allocate.cbregCBREG 分配(每个 SCS/TAC/TEC 银行 16 个之一)
llvm.tpu.sld.cb / .sld.cb.updSLDCircularBuffer(0x3f / 0x3e.upd = 更新后)
llvm.tpu.sst.cb / .sst.cb.updSStoreCircularBuffer (0x3d / 0x3c)

双基(smem.basetilespmem.base)是双地址空间窗口:CBREG 窗口包括 SMEM 和 TILE_SPMEM。


跟踪/遥测/sc-control {#trace--telemetry--sc-control}

12 操作。 SparseCore 控制/跟踪和遥测。代表:llvm.tpu.sc.stracellvm.tpu.eventllvm.tpu.spill.debugllvm.tpu.mprefixllvm.tpu.read.global.cycle.countllvm.tpu.read.local.cycle.countllvm.tpu.ssetpstatellvm.tpu.sc.ssettmllvm.tpu.sc.dma.core.idllvm.tpu.sc.sint。 (MEDIUM — 任务/结构的边界。)


排序/唯一/重复计数 {#sort--unique--dupcount}

11 操作。 SparseCore 排序/去重单元 — 嵌入去重原语。请参见 sparsecore/dedup-multiplicity.mdsparsecore/rank-and-permute-radixsort.md

内在它的作用是什么
llvm.tpu.sort.ascdf / .ascdi升序排序,float / int
llvm.tpu.sort.dscdf / .dscdi降序排序,float / int
llvm.tpu.uniquef / .uniqueiunique-reduce, float / int
llvm.tpu.dupcntf / .dupcnti重复计数,浮点/整数
llvm.tpu.vmctz向量计数尾随零
llvm.tpu.vmpcnt.ones矢量掩码 popcount

任务/控制/结构 {#task--control--structural}

10 操作。 SparseCore 平铺任务 + 结构操作。代表:llvm.tpu.task.dispatchllvm.tpu.task.dispatch.clear.ibufllvm.tpu.loop.namellvm.tpu.loop.parallelllvm.tpu.barrierllvm.tpu.nopllvm.tpu.delayllvm.tpu.tileidllvm.tpu.halt.trapllvm.tpu.capture.hbm.stack/init.stacktpu_tileid 操作(类型为 (Type) → 0 操作数 id)读取 STILEID 寄存器;它是每核 addrspacecast 转换消耗的tile-id 源。 (MEDIUM — 与堆栈操作上的控制寄存器和指针系列重叠。)


i1-掩模宽度转换 {#i1-mask-width-conversion}

5 操作。 VPU mask slot — 矢量掩码宽度重新打包。全套:llvm.tpu.8i1.to.16i1llvm.tpu.8i1.to.32i1llvm.tpu.16i1.to.8i1llvm.tpu.16i1.to.32i1llvm.tpu.32i1.to.8i1。请参见 sparsecore/m-register-predicate.mdisa/slot-vcreate-mask-mregister.md


ODS操作数形状(代表性) 1356 中的

466 携带类型化的 create(OpBuilder&, Location, …),其参数列表是 ODS 声明;其他 890 使用通用默认构建器(从名称家族数量 + verifyInvariantsImpl 存在推断的形状)。 T = 结果类型,V = 值操作数。

内在(系列)创建参数(位置之后)形状
tpu_addrspacecast(地址空间广播)T, V1 个资源,1 个操作数
tpu_addrspacecast_smem(地址空间广播)T, V, V+平铺窗口
tpu_dma_*_sc_simple(DMA)V×88 字段描述符
tpu_dma_*_sc_single_strided(DMA)V×11+跨步三倍
tpu_dma_*_sc_general(DMA)V×16多调光
tpu_stream_*_{gather,scatter}_*(流)V×6流描述符
tpu_syncadd(同步)V, V标志,增量
tpu_syncadd_remote / syncset_remote(同步)V×5+dev/core/id
tpu_fetch_and_add(等待)V, V, Vsflag、addr、val
tpu_waitge / waiteq / …(等待)V, V标志,阈值
tpu_alloca_smem / alloca_sflag(分配)T, V结果,尺寸
tpu_rdcbreg_offset / rdcbreg_size (CBREG)T, V结果,cbreg
tpu_wrcbreg_offset (CBREG)T, V, VCBreg,值
tpu_cbreg_add_offset (CBREG)T, V, VCBEG,三角洲
tpu_inttoptr / ptrtoint (ptr)T, V结果,值
tpu_setreg_sflagrange(ctl-reg)V范围值
tpu_sin_macro / tpu_*_macro (EUP)T, V结果、操作数
tpu_tileid(任务/结构)T0-操作数id
tpu_barrier(任务/结构)V, V, V屏障参数
tpu_delay(任务/结构)V循环

890 个默认构建器操作(裸超越 tpu_sin/tpu_rcptpu_*i1_to_*i1scan2xN、打包/解包、vld/vstrdreg_* 计数器、sld_cbeup_pop)使用通用 (TypeRange, ValueRange, ArrayRef<NamedAttribute>) 构建器 — 推断结果类型 (SameOperandsAndResultType/InferType),按名称系列数量进行操作数计数。


默认构建器 Arity(从 ODS 特征包读取字节) {#default-builder-arity-byte-read-from-the-ods-trait-pack}

890 个默认构建器操作不需要需要从名称系列启发式猜测其操作数计数:TableGen 将结果计数和操作数计数特征烘焙到损坏的 Op<…> 类模板中,并且该模板名称以字节形式存在于符号表中。每个 tpu_* 操作都被实例化为

text
mlir::Op<sparse_core::tpu_NAME,
         OpTrait::ZeroRegions, OneResult|ZeroResults,
         OneTypedResult<mlir::Type>::Impl, ZeroSuccessors,
         OneOperand | ZeroOperands | NOperands<Lj N>::Impl,
         OpInvariants [, MemoryEffectOpInterface::Trait]>

并且该特征列表逐字显示在每个操作 getHasTraitFn / getFoldHookFn / printAssembly 回调符号(nm 代币 OpINS…sparse_core<len>tpu_NAME EJ … OpInvariants)内。操作数计数是文字 OneOperand (1)、ZeroOperands (0) 或 NOperands<Lj N> (N) 标记;结果计数为 OneResult (1) 与 ZeroResults (0)。不需要反汇编——元数是符号中的字符串。

注意 — 结果 TypeConstraint 不是该层的精炼 Vreg/Mask/Scalar/Ptr 谓词。 每个操作的结果特征都是通用的 OneTypedResult<mlir::Type>mlir::Type,不是寄存器类子类型。验证者主体(tpu_NAME::verifyInvariantsImpl)通过一个共享约束函数__mlir_ods_local_type_constraint_…llvm_tpu_ops1(例如@0x149de120)释放其单一结果类型检查,其整个主体是if (!LLVM::isCompatibleOuterType(t)) emitOpError(...)(call isCompatibleOuterType @0x17473060位于149de146,字节验证)。区分调用站点的 StringRef 参数只是诊断角色标签 — "result" (.rodata @0x84f7815) 与 "operand" (.rodata @0x86f4942),由 xxd 读取 — 而不是谓词选择器。 在此 MLIR 层中编码没有每操作 Vreg/Mask/Scalar/Ptr 结果约束;寄存器类细化仅存在于 ISel 下游消耗的 LLVM 内在签名中,而不存在于 ODS 验证器中。因此,这个间隙的“结果 TypeConstraint” 的一半 * 在这里每个操作都不是静态可分离的 - 每个叶子都携带相同的通用 LLVM 兼容类型结果检查。 (HIGH)

数量分布 — 1356 字节读取中的 1060 个

从每个操作的 Op<…> 符号中解析 OneResult/ZeroResults × OneOperand/ZeroOperands/NOperands<Lj N> 令牌可恢复精确的 (#results, #operands) 形状 1060不同的 tpu_* 操作(未列出的 296 个 Op<…> 包仅内联发出,并且不携带独立的回调符号;它们的数量遵循相同的名称系列模式)。完整的字节读取分布:

#res#操作数# 操作此桶中的主导家族
08358stream_{strided,indirect}_* (342) + dma_*_sc_simple 非 iova 窗口 (16)
11147裸EUP(sin / rcp / eup_pop / sigshft / exponent),unpackl / unpackuinttoptr/ptrtointi1-宽度铸件
06118stream_linear_* + sync{add,set}_remote_*
09114stream_indirect_vreg_vreg_*(聚集+分散)
1294sld_cbpack_c_*dupcnt{f,i}uniquefsshllovclasswrcbreg_*
0251syncadd/waiteq/…(标志、阈值)
0429跨步/多参数同步 + vst 变体
0126delay,单参数存储
1025tileid + 所有 rdreg_* 计数器(0 操作数寄存器读取)
0523同步/DMA 中间层
0321vst_msk 级商店、fetch_and_add 级、barrier
1314sort_{asc,dsc}d{f,i},3 操作数向量运算
01612dma_*_sc_general
1494 操作数类型操作
01110dma_*_sc_single_strided(非 iova)
006nop级零一切操作
0122dma_{hbm_to_iova,iova_to_hbm}_sc_single_strided(iova增加1个操作数)
1101tpu_sfence(10 个 sflag 操作数)

总和 = 1060。

字节验证的叶样本(直接从符号读取的令牌)

每行的 #res/#operands 是从该操作的损坏中提取的 OneResult/ZeroResultsOneOperand/ZeroOperands/NOperands<Lj N> 令牌nm 表中的 Op<…sparse_core…tpu_NAME EJ…OpInvariants> 回调符号 — 确切的字符串就是证据。

本征(类)结果代币操作数标记(#res,#opnd)
tpu_sin(裸EUP)OneResultOneOperand(1, 1)
tpu_addrspacecastOneResultOneOperand(1, 1)
tpu_tileidOneResultZeroOperands(1, 0)
tpu_vld_mskOneResultNOperands<Lj2>(1, 2)
tpu_sld_cbOneResultNOperands<Lj2>(1, 2)
tpu_pack_c_b32_b16OneResultNOperands<Lj2>(1, 2)
tpu_sort_ascdfOneResultNOperands<Lj3>(1, 3)
tpu_vst_mskZeroResultsNOperands<Lj3>(0, 3)
tpu_syncaddZeroResultsNOperands<Lj2>(0, 2)
tpu_stream_linear_gather_hbm_to_tilespmemZeroResultsNOperands<Lj6>(0, 6)
tpu_stream_strided_gather_hbm_to_tilespmemZeroResultsNOperands<Lj8>(0, 8)
tpu_stream_indirect_vreg_vreg_gather_hbm_to_tilespmemZeroResultsNOperands<Lj9>(0, 9)
tpu_dma_hbm_to_spmem_sc_single_stridedZeroResultsNOperands<Lj11>(0, 11)
tpu_dma_hbm_to_iova_sc_single_stridedZeroResultsNOperands<Lj12>(0, 12)
tpu_sfenceOneResultNOperands<Lj10>(1, 10)

QUIRK — 流系列统一 V×6 §流 类型创建示例显示 6 操作数线性形式,但字节读取元数将 834 个流操作分为 三个由寻址模式键入的操作数计数stream_linear_* = 6, stream_{strided,indirect}_* = 8,stream_indirect_vreg_vreg_* = 9。额外的操作数携带更复杂模式所需的步幅/索引/vreg 偏移源。使用固定的 6 操作数列表构建每个流操作的重新实现者将无法提供跨步/间接形式。同样,DMA single.strided 层通常为 11 个操作数,但当涉及 iova 端点时为 12 个(dma_hbm_to_iova / dma_iova_to_hbm),细化 §DMA 中的平坦“11 值”。

注意 - 覆盖范围,无静默上限。 15 个叶子在上面进行了字节验证(令牌直接从每个操作的损坏的 Op<…> 符号读取),跨越 EUP / addrspacecast / task / vld / cbreg / pack / sort / vst /sync /stream-{linear,strided,indirect-vreg} / dma-{单步,iova} / 栅栏系列。完整的 (#res, #operands) 形状是 1356 个操作中的 1060 个操作的字节读取(每个 Op<…> 包都作为独立的回调符号存在);上面的分布表是这 1060 个操作的精确普查。其余 296 个操作仅内联发出其特征包,并且不**单独转录 - 它们的数量遵循相同的名称家族布局(每个操作都相距一个 rg -o 'sparse_core…tpu_NAME EJ…OpInvariants' 令牌)。这完全涵盖了“890 个默认构建器操作”缺口的 arity 一半; 结果-TypeConstraint 一半由上述注释关闭(统一通用 mlir::Type + isCompatibleOuterType,无每操作 Vreg/Mask/Scalar/Ptr)。


Per-Intrinsic IntrProperties(LLVM属性表) {#per-intrinsic-intrproperties-llvm-attribute-table}

每个 llvm.tpu.* 内在函数都带有一个 IntrProperties 集 — IntrNoMem/IntrArgMemOnly/IntrReadMem/IntrWillReturn/… 位 TableGen 降低到由返回的 LLVM 函数属性列表中llvm::Intrinsic::getAttributes (@0x1da0b460)。这是后端的别名分析和调用调度契约。该集合可通过双表查找进行字节恢复;下面的示例是直接从这些表中读取的。

查找(从 getAttributes 字节解码)

getAttributes(ctx, ID, FT) 读取 IntrinsicsToAttributesMap(_ZL25IntrinsicsToAttributesMap @0x416fb30uint16_t[17648],每个 LLVM 内在 ID 一个条目,索引为 [ID−1])。打包后的 uint16 拆分:

字段解码站点(在getAttributes)
arg-attr-设置索引[8:0] (& 0x1ff)1da0b4ab: and $0x1ff,%ecxArgAttributesInfoTable @0x4178510(4 字节步长:1da0b4c0: movzwl 0x2(%rdx,%rsi,4))
fn-attr-集索引[15:9] (>> 9)1da0b564: shr $0x9,%esi; 0x7f =“无 fn 属性”哨兵 (1da0b567: cmp $0x7f)

fn-attr-set 索引通过 0xb550f54 处的跳转表(int32 相对偏移量,按集 ID 索引)选择 getIntrinsicFnAttributeSet (_ZL26getIntrinsicFnAttributeSet @0x1da0d460) 中的情况。每种情况都是 Attribute::get(ctx, AttrKind, 0) 调用 (@0x1d912ee0) 的固定序列,可选地后跟一个 Attribute::getWithMemoryEffects(ctx, ME) (@0x1d9139a0)。每次调用之前的 mov $0xNN,%esi 中的 AttrKind 立即数是 LLVM Attribute::AttrKind 枚举值; ME 立即数是 MemoryEffects 位掩码。

AttrKind 枚举值(从 mov $imm,%esi 操作数读取字节;根据符号表中二进制文件的 IRAttribute<AttrKind N>/AA*Impl 模板实例进行交叉检查的名称):0x2c=44 NoUnwind, 0x50=80 WillReturn,0x47=71 可推测(INFERRED 名称 — 枚举值字节读取,来自 NoMem+WillReturn 纯内在配对的名称;没有属性 AA 携带 71)。 MemoryEffects 位掩码(2 位/位置,ModRef = Ref(1)/Mod(2)/ModRef(3),位置 ArgMem/InaccessibleMem/其他):0x0=memory(none) (IntrNoMem)、0x555=memory(read) (IntrReadMem)、 0xaaa=memory(write)(IntrWriteMem)、0x3=memory(argmem: readwrite)(IntrArgMemOnly)、0x1=memory(argmem: read)0x2=memory(argmem: write)0xc=memory(inaccessiblemem: readwrite); 不存在 = 完全未建模的 ModRef(副作用)。

12 fn-attr 设置 llvm.tpu.* 表面使用

对所有 1356 个数据进行普查(从每个内在函数的映射条目中读取 fn-attr-set 索引;通过将其 getIntrinsicFnAttributeSet 情况跟踪到 AttributeSetNode::get 终结器 @0x1da0f134 来解码每个集合的内容):

套装# of 1356枚举属性记忆效应LLVM IntrProperties 简写
11215NoUnwindmemory(none)IntrNoMem
13128NoUnwindmemory(argmem: readwrite)IntrArgMemOnly
112843NoUnwindmemory(argmem: readwrite)IntrArgMemOnly
148NoUnwindmemory(argmem: read)IntrReadMem+IntrArgMemOnly
3211NoUnwindmemory(read)IntrReadMem
348未解除,将返回memory(write)IntrWriteMem+IntrWillReturn
3626未解除,将返回memory(write)IntrWriteMem+IntrWillReturn
838NoUnwindmemory(argmem: write)IntrWriteMem+IntrArgMemOnly
10850未解除,将返回,可推测memory(none)IntrNoMem+IntrWillReturn+IntrSpeculatable
11419NoUnwindmemory(inaccessiblemem: readwrite)IntrInaccessibleMemOnly
519NoUnwind(无)副作用(完整 ModRef)
1021NoUnwind(无)副作用(完整 ModRef)

总和:215+128+843+8+11+8+26+8+50+19+19+21 = 1356 — 确切地说,每个 llvm.tpu.* 内在映射到这 12 个集合之一。

字节验证的每叶样本(名称→ID→映射条目→集合)

每行:内在名称、其 LLVM 内在 ID(IntrinsicNameTableStorage @0x4179440 中的存储顺序索引,其中 not_intrinsic=0、llvm.abs=1,...)、从 IntrinsicsToAttributesMap[ID−1] 读取的 uint16 以及解码的 fn-attr-set。

内在ID地图 uint16fn 组已解决 IntrProperties
llvm.tpu.addrspacecast0x33b10x160111IntrNoMem
llvm.tpu.pack.c.b32.b160x34530x160111IntrNoMem
llvm.tpu.vcvt.f32.bf160x384e0x160111IntrNoMem
llvm.tpu.16i1.to.32i10x33a10x160111IntrNoMem
llvm.tpu.nop / llvm.tpu.delay / llvm.tpu.sfence0x160111IntrNoMem
llvm.tpu.dma.hbm.to.spmem.sc.simple0x34080x1afb13IntrArgMemOnly
llvm.tpu.dma.hbm.to.spmem.sc.general0x34070x1afa13IntrArgMemOnly
llvm.tpu.syncadd0x37e80x1a0113IntrArgMemOnly
llvm.tpu.waiteq0x38bb0x1a0113IntrArgMemOnly
llvm.tpu.stream.linear.gather.add.f32.hbm.to.tilespmem0x36ce0xe0ff112IntrArgMemOnly
llvm.tpu.vst.msk.idx.add(+所有索引分散存储)0x…ff/0xe0…112IntrArgMemOnly
llvm.tpu.vld.cb.msk / llvm.tpu.rdcbreg.offset / llvm.tpu.sin.macro0x346a/0x34980x400132IntrReadMem
llvm.tpu.vst.cb.msk.add / llvm.tpu.vst.cb.msk0x387e0x480136IntrWriteMem+IntrWillReturn
llvm.tpu.rcp / rsqrt / tanh / sort.ascdf / add.scan1xNf0x3468/0x349b/0x33ac0xd801108IntrNoMem+IntrWillReturn+IntrSpeculatable
llvm.tpu.rdreg.gtc.hi / read.global.cycle.count0x34740x140110副作用(完整 ModRef)
llvm.tpu.fetch.and.add / task.dispatch / eup.pop0x342d/0x38020x0a015副作用(完整 ModRef)

每个的映射 uint16 是文件偏移 0x416fb30 + (ID−1)*2 处的精确小端半字;例如ID 0x33b10x4176290 (= 0x416fb30 + (0x33b1−1)·2) → 0x1601arg = 0x1601 & 0x1ff = 1fnset = 0x1601 >> 9 = 11 处读取 01 16

注意 - 覆盖范围,无静默上限。 16 个代表性叶子在此处针对映射进行字节验证(跨越 addrspacecast / pack / Convert / mask-width / DMA /sync / wait / Stream / CBREG load+store / EUP-macro / transcendental / scan / sort / control-reg /atomic / task family),并且所有 12 个 fn-attr 集都在中进行字节解码来自 getIntrinsicFnAttributeSet 的完整。其余 1340 个内在函数的每叶集分配单独转录,但上面的 fn 集普查是精确的(总和为 1356)并且查找是确定性的:来自 IntrinsicNameTableStorage @0x4179440 存储顺序的 set = (IntrinsicsToAttributesMap[ID−1] >> 9)ID。重新实现者使用一个半字加载+一个表调度来读取任何叶子的 IntrProperties

明白了 — 主要的 fn 集是 112(843 个操作,≈ 所有 834 个流 + 9 个索引分散存储)= nounwind memory(argmem: readwrite) = IntrArgMemOnly不是 IntrNoMem。将流操作标记为 IntrNoMem(因为它们看起来像纯数据移动器)的重新实现者将让调度程序在它们实际读写的嵌入表中提升/CSE/死代码消除它们——这是一个正确性错误。流引擎接触参数指向的内存,因此 argmem: readwrite 是二进制文件的结论。相反,纯数学集 108 (rcp/rsqrt/tanh/sort/scan) 是唯一携带 IntrSpeculatable 的集​​ — 这​​些是可安全提升的集。


注册绑定

mlir::sparse_core::registerLlvmTpuDialectOperations @0x146d0560 尾调10批分注册商;每个 RegisteredOperationName::insert 约 135 个操作(TableGen 操作注册分为 ≤256 个操作批次,以限制每个函数实例化大小)。 10 × ~135 = 1356。

分注册商地址
registerLlvmTpuDialectOperations00x146d05c0
registerLlvmTpuDialectOperations10x1472bea0
registerLlvmTpuDialectOperations20x1478b500
registerLlvmTpuDialectOperations30x147e1c40
registerLlvmTpuDialectOperations40x14835b80
registerLlvmTpuDialectOperations50x148891c0
registerLlvmTpuDialectOperations60x148dc3c0
registerLlvmTpuDialectOperations70x1492d5c0
registerLlvmTpuDialectOperations80x14982d00
registerLlvmTpuDialectOperations90x149d88e0(最终批次)

注意 — 这些内在函数通过这个单独的 10 批次 LlvmTpuDialect 路径注册,不是通过高级 ScDialect 115 操作 addOperations @0x14594f60。仅跟踪 ScDialect 注册的重新实现者将看到内在表面“无明显”,并错过所有 1356。


每代变化

1356 计数是此构建目标各代的并集;每一代的内在表面都会增长。尺寸不同:

变异来源效果
新数据类型(FP8 e4m3/e5m2,窄整数)为每个数据类型添加流/转换/打包操作行
新流模式/内存空间扩展834路流跨积
新 EUP 超越选择器添加超验 + .macro
新地址空间添加了 addrspacecast 叶子变体
代门控操作较早的世代可能缺少名称(可到达的 getSequencerType / EmitX 世代调度门)

深层每代可达性位于 isa/sequencer-ops-per-gen.mdisa/v5plus-emitx-bit-positions.md 上。本附录快照了构建的完整注册集;针对单个世代的重新实现者必须根据该世代的 EmitX 调度来控制名称。


流命令是组合的,而不是按叶的 {#the-stream-command-is-composed-not-per-leaf}

834路llvm.tpu.stream.*爆炸是隐藏每叶的主要嫌疑人 数字命令表:834 个不同的操作看起来像834 个不同的硬件操作码。的 二进制文件另有说明。 SparseCore 流排序器使用的数字命令是 在编码时由四个正交 SparseCoreStream 原始位域组装;那里 不是由 (pattern,verb,dtype,memspace) 索引的静态数组,也没有每内部命令 常数。 834 个叶子折叠成 4 个寻址形式 × 一个 8 值动词 × 一个 dtype 位 × 内存空间枚举,打包到一个插槽中。通过读取编码器的数据证实了这一点 oneof 直接调度和每个字段访问器 — 地址为 gfc/TPU7x; .text VA==0xe63c000 处的文件偏移量。

编码器在表单上调度,而不是在叶子上

SparseCoreStreamEncoder::Encode @ 0x1eb9b4c0 通过读取原型来选择编码内容 oneof 鉴别器并将其限制在消息的字段计数处 — 不是 内在 ID 键控表:

text

1eb9b55e: mov    0x58(%r15),%eax        ; oneof discriminator (which addressing form)
1eb9b562: cmp    $0xa,%rax              ; bound = 0xa  → at most 11 cases (fields 0..10)
1eb9b566: ja     1eb9bd64               ; default/error arm
1eb9b571: lea    -0x13363470(%rip),%rcx ; jump table @0xb838108 (11 × int32 rel offsets)
1eb9b5a2: cmpl   $0x8,0x58(%r15)        ; field #8 == LinearStream
1eb9b5a7: lea    SparseCoreStream_LinearStream_globals_(%rip),%r12

.rodata 0xb838108 处的跳转表为 11 个条目(字段 0–10),并且 xxd 显示 条目 8/9/10 是唯一具有不同目标的条目 — 线性/跨步/间接形式 臂 — 而字段 0-7 共享默认臂。 745 MB 二进制注册 834 个独立的 流操作仍然通过 11-case 开关将它们全部路由:爆炸发生在 MLIR 操作中 名册,不在任何硬件命令表中。 (SCS 编码器边界为 0xa;TEC 编码器边界为 0xa;TEC 编码器边界为 0xa0xb 处界限以接纳仅 TEC 的 IndirectVregStream 第四种形式 — 请参阅 间接 Vreg 流。)

四个命令字段,每个字节都从其访问器进行验证

(pattern,verb,dtype,memspace) 元组的每个轴都是一个单独的位字段,具有自己的 GetConcatenatedValue/Matches 访问器。移位/掩码直接从 拆解是现场准确的槽位和宽度:

字段附件 @字节读取体槽位验证值
图案(表格)形式操作码0x1eb9aa60 线性(q[+0x18] & 0x7E0…<<52)==0x76…<<52位 53–58线性 = 0x76>>1 = 0x3b
0x1eb9aa80 跨步…==0x74…<<52位 53–58跨步 = 0x74>>1 = 0x3a
0x1eb9aaa0 间接…==0x72…<<52位 53–58间接 = 0x72>>1 = 0x39
动词StreamOpcode0x1eb9b3a0(d[+0x18] >> 9) & 7+0x18 位 9,w3GATHER=0 … SCATTER_FLOAT_ADD=6
dtypeGatherScatterAddIsB160x1eb9b3c0(d[+0x18] >> 0xc) & 1+0x18 位 12,w1bf16-add = 1,f32-add = 0
内存空间OffTileMemoryType0x1eb9b420(q[+0x10] >> 0x2f) & 7+0x10 位 47,w3SPMEM=0 · TILE_SPMEM_N=1 · HBM=2 · HBM_4B=3

工作样本 — 12 个代表性叶子和每个生成的 composed slot 命令。这 命令是元组(form, StreamOpcode, IsB16, OffTileMemoryType);没有一个整数是 按叶子分配,因此“命令”列是字节派生的字段组合:

流叶(模式 × 动词 × dtype × 内存空间)表格动词IsB16内存空间字节证据
stream_linear 聚集 → HBM,f320x3b002线性 Matches==0x76<<52; verb >>9&7=0
stream_linear_add 分散-f32-add → HBM0x3b602StreamOpcode>>9&7=6; IsB16>>0xc&1=0
stream_strided 聚集 → HBM,f320x3a002跨步 Matches==0x74<<52
stream_strided_add 分散-f32-add0x3a602形式 0x3a;动词6
stream_indirect 聚集 → HBM,f320x39002间接 Matches==0x72<<52
stream_indirect 聚集 → HBM_4B0x39003OffTileMemoryType>>0x2f&7=3
stream_indirect_add 分散-f32-add → HBM0x39602动词 6,IsB16 0
stream_indirect_add 分散-bf16-add → HBM0x39612IsB16>>0xc&1=1
stream_indirect 聚集-f32-add → HBM0x39202动词 GATHER_FLOAT_ADD=2
stream_indirect 聚集-int-添加 → HBM0x3912动词 GATHER_INTEGER_ADD=1
stream_indirect 分散 → SPMEM 池0x39400动词 SCATTER=4;内存空间 0
stream_indirect_vreg 聚集(仅限 TEC)0x38002TEC 绑定之一 0xb;形成第4种情况

注意 — 无静音盖;这是一个诚实的负面结果。834 中 流叶,0 具有单独字节转储的每叶命令整数,因为 不存在这样的整数 — 搜索在编码器的 11-case 处终止 oneof 开关 (cmp $0xa/$0xb) 和四个正交现场访问器。 是什么 字节验证:3 of 4 形式操作码(0x3b/0x3a/0x39 直接来自其 Matches 常数;第四个,IndirectVreg 0x38,记录在 同级页面 仅作为 TEC)和 所有四个 命令 字段的移位/掩码。因此,任何一个叶子的命令都可以从它的 (pattern,verb,dtype,memspace) 没有表的名称分解 — 但有表本身 不存在可转储。重新实现者必须通过打包这四个字段来构建插槽, 不是通过查找叶操作码。

明白了 — (verb, dtype, memspace) 与插槽中的操作标识无关。 两个 不同的内在函数(stream_indirectstream_indirect_add)仅在 3 位上有所不同 StreamOpcode 他们设置; bf16-vs-f32 的分割是一位,而不是具有两个操作码的两个操作; HBM-vs-HBM_4B 拆分是 memspace 枚举,而不是第三个操作系列。 834路ISel 花名册将这些编码为操作身份(请参阅 §Stream 陷阱 上面),但它们“收敛到”相同的四场槽。每叶“操作码”a 重新实现者可能期望的是 MLIR 层操作爆炸的产物,而不是 HW 命令 号。

深层字段语义、完整编码/解码位图和 StreamOpcode/OffTileMemoryType 枚举名单在 流聚集/分散 上直播;这个 部分的贡献证明了每叶命令间隙是一个“类别错误”—— 命令组成,组成就是上面的四个字段。


此处未列举的内容

本目录中的诚实差距:

  • 每叶流→HW 操作码解析为否定结果(参见 §流命令是组合的,而不是按叶的):没有 834 条目静态每叶命令表。 SparseCore 流定序器使用的数字槽命令是在降低时间组装的,由四个正交 SparseCoreStream 原型位域组成 — 一个 6 位寻址 form 操作码加上 3 位 verb (StreamOpcode)、一个 1 位 dtype 选择 (GatherScatterAddIsB16) 和一个 3 位 memspace (OffTileMemoryType) — 每个都由其自己确认的访问者读取。 (pattern,verb,dtype,memspace) 选择不是一个操作码;而是一个操作码。它是这些字段的笛卡尔集合。早期的 INFERRED“每叶操作码”框架是错误的:每叶没有任何字节转储,因为编码器开关仅限于 4 个表单,而不是 834 个叶。
  • 每固有 LLVM IntrProperties恢复(请参阅 §每内在 IntrProperties):表面使用的所有 12 个 fn-attr 集均经过字节解码,并且每集普查是准确的(总和为 1356); set = IntrinsicsToAttributesMap[ID−1] >> 9 查找是确定性的。只有 1340 个非采样 ID 的每叶分配不会单独转录(每个 ID 都加载一个半字)。 MLIR 侧的 OpInterface(MemoryEffect 285、AliasAnalysis 546、AccessGroup 180、Bytecode 188)是方言层的对应项。
  • 890 个默认构建器操作的精确数量 + 结果 TypeConstraint恢复数量(请参阅 §默认构建器数量):(#results, #operands) 形状是从每个操作的损坏的 Op<…OneResult/ZeroResults…OneOperand/NOperands<Lj N>…> 特征包(1356 个中的 1060 个)中字节读取的ops,并列出了完整的分布。结果 TypeConstraint 一半被解析为负结果:MLIR 层没有每操作 Vreg/Mask/Scalar/Ptr 谓词 - 每个结果特征都是通用的 OneTypedResult<mlir::Type>,验证者通过一个共享的isCompatibleOuterType检查;寄存器类细化仅由下游 LLVM 内在签名执行,而不由 ODS 验证程序执行。
  • 扫描/排序/独特引擎操作码位布局 — 按名称映射到 SparseCore 扫描/排序/重复数据删除单元;每个操作的硬件命令位布局未解码(SparseCore 特定的计算单元,而不是 TensorCore LLO 插槽)。
  • 完整的数字地址空间 ID 表AddressSpaceDescription 开关基数 (201) 和采样的 case 字符串已知;完整的 ID↔ 空间映射(以及 addrspacecast 叶子在哪些数字 ID 之间进行投射)需要完整的开关臂行走。

交叉引用