Skip to content

LlvmTpu 内在函数目录

本页中的每个地址、符号、偏移和字符串都逐字节精确读取自 libtpu-0.0.40-cp314 wheel 中的 libtpu.so(构建 libtpu_lts_20260413_b_RC00,BuildID md5 89edbbe81c5b328a958fe628a9f2207d,781,691,048 字节,未剥离符号.text/.rodata VMA == 文件偏移)。其他版本会不同;应把每个 VA 都视为绑定到该版本。

摘要

TPU 后端有两个不同的 op 表面。TensorCore 路径是含 86 个 op 的 tpu 目标方言,它降低到 322 个 mlir::llo::*Op,再下降到 LLO bundle(tpu → LLO ODS 降低 覆盖了这一下降过程)。本页记录的是另一个表面:LlvmTpuDialect,一个独立的 MLIR 方言,包含 1356 个 tpu_* 内在 op,它是 SparseCore(嵌入处理协处理器)的栈底指令表面。每个 op 注册为 mlir::sparse_core::tpu_X_Y_Z,并打印为 LLVM 内在函数名 llvm.tpu.X.Y.Z(下划线→点)。这些 op 不会降低到 LLO;它们通过 Lower to SparseCore LLVM 下降为真正的 LLVM-IR 内在函数调用,并到达 SparseCore LLVM 后端,在那里由 addrspacecast ISel 和各引擎的 ISel 匹配它们。

熟悉 LLVM 的读者应记住一个类比:这是一个以 MLIR 方言形式物化的 TableGen IntrinsicsTPU.td 表面。每个 llvm.tpu.* 名称都是一个 LLVM 内在函数;每个名称同时也是一个已注册的 MLIR op,携带标准的 23 槽 RegisteredOperationName::Model<Op> ABI。这两个视图是同一集合,并通过两种独立方式恢复出来(1356 个 Model<tpu_*> vtable,以及 1356 个 llvm.tpu.* 打印名字符串;在下划线→点映射下集合完全相同)。最主要的结构事实是:硬件变体由 op 身份编码,而不是由属性编码:1356 个 op 中有 834 个(62 %)属于 tpu_stream_* 嵌入 gather/scatter 家族,这是一个 {pattern × verb × dtype × memspace} 叉积,其中每个单元格都是独立注册的 op。stream op 没有 dtype 属性;dtype 在其名称中。

本页负责家族分类、各家族代表性签名,以及 ID 表组织(10 批次注册器)。它不会重新推导逐 cast 的地址空间 ISel(那是 addrspacecast ISel 的内容)、tpu 方言 ODS(那是 tpu → LLO ODS 降低 的内容),或 SparseCore 后端引擎编码(那些见 SparseCore ISA 槽位页面)。对于重新实现,契约是:

  • Model↔打印名对应关系 — 机械的 tpu_X_Yllvm.tpu.X.Y 映射,以及为什么它是零不匹配的 1:1 对应。
  • 20 类功能分类 — 按前缀对 1356 个中的 1348 个进行名称家族分组(每类大小均已逐字节确认;见 20 个类别);每类映射到其 SparseCore 引擎或 LLO/EmitX 目标。
  • ID 表组织 — 10 批次 registerLlvmTpuDialectOperations0..9 注册器、为何拆分,以及它与 115-op ScDialect 路径的区别。
  • ODS 形状恢复规则 — 带类型的 tpu_*::create 参数列表就是操作数/结果声明,并有已验证的逐家族元数。
方言类mlir::sparse_core::LlvmTpuDialect(ctor LlvmTpuDialectC1EPNS_11MLIRContextE
内在函数数量1356Model<tpu_*> vtables == llvm.tpu.* 字符串,集合完全相同)
注册器registerLlvmTpuDialectOperations @ 0x146d0560 → 尾调用 …Operations0..9
打印名规则C++ tpu_X_Y_Z ↔ intrinsic llvm.tpu.X.Y.Z_.);comm -23 == 0
地址空间LlvmTpuDialect::AddressSpaceDescription(int) @ 0x135462c0(base 0xc9=201,span 0x18)
消费 passLowerToSparseCoreLlvmPass::runOnOperation @ 0x13566d00lowerFunc @ 0x13568280
主导类别tpu_stream_*834 / 1356(SparseCore 嵌入 gather/scatter 引擎)
带类型 create 覆盖率466 / 1356 携带带类型的 create(从符号读出 ODS 形状);890 个默认 builder
置信度CONFIRMED(字节锚定)用于枚举/分类/注册;逐类 HW 目标按标注

双表面模型

目的

在目录之前,读者必须先理解为什么还存在第二个 TPU op 方言,以及为什么负责 tpu 方言→LLO 下降的页面不负责这一部分。这种拆分是结构性的,而非偶然:TensorCore 和 SparseCore 是两种不同机器,拥有不同 ISA,编译器也把它们建模为不同的 MLIR 方言。

拆分

tpu 方言(86 个 op)是 TensorCore 目标:matmul/MXU、VPU 向量 op、sequencer,经由 322 个 llo.*Op 类下降(tpu → LLO ODS 降低)并打包进 VLIW bundle。LlvmTpuDialect(1356 个 op,本页)是 SparseCore 目标:一个嵌入表流处理器,其原语包括间接 gather/scatter、sflag 原子、循环缓冲寄存器(CBREG),以及 SparseCore 内存池之间的地址空间 cast。SparseCore op 不会被打包进 LLO bundle,而是变成 LLVM-IR 内在函数调用,并由 SparseCore LLVM 后端生成代码。

注意 — 这 1356 个内在函数不会通过 115-op ScDialect 的 addOperations 路径(0x14594f60)注册;只扫描该路径的方言清单会认为 LlvmTpuDialect 是空的。内在函数通过独立的 10 批次 registerLlvmTpuDialectOperations 路径注册,该路径记录在 ID 表组织 中,也是它们的 RegisteredOperationName::Model<Op> vtable 被物化和验证的位置。

Model↔打印名对应关系

每个内在函数在二进制中存在两次,而且两种形式可以机械地互相转换:

c
// (a) the registered MLIR op — a RegisteredOperationName::Model<Op> vtable:
//        _ZTVN4mlir23RegisteredOperationName5ModelINS_11sparse_core11tpu_syncaddEEE
//     1356 such vtables for mlir::sparse_core::tpu_* classes.
// (b) the printed LLVM-intrinsic name string, in .rodata:
//        "llvm.tpu.syncadd"
//     1356 such strings.
//
// The map is purely lexical:
//     class  tpu_X_Y_Z   ->   intrinsic  llvm.tpu.X.Y.Z      // s/^tpu_/llvm.tpu./ ; s/_/./g
// Applying it to the class list and diffing against the string list:
//     comm -23 (mapped-classes) (string-list)  ==  0         // zero mismatch, both ways

因此,每个已注册 op 恰好有一个打印出的 llvm.tpu.* 名称,反之亦然。这是规范的、源自 IntrinsicsTPU.td 的表面:C++ 类是 ODS 注册的 MLIR op;llvm.tpu.* 字符串是它带入后端的 LLVM 内在函数名。

陷阱 — 点/下划线边界是前缀和字段分隔符,不是分词器。tpu_dma_hbm_to_tilespmem_sc_simplellvm.tpu.dma.hbm.to.tilespmem.sc.simple — 每个 _ 都会变成 .,包括 hbm_to_tilespmem 内部的那些。重新实现者若对 _to_ 做特殊处理,会使两个命名空间失去同步。


功能类别分类

目的

1356 个内在函数按名称家族前缀分成 20 个功能类别。大型清晰前缀类别(stream 834、pack/unpack 87、vld/vst 74、wait 47、dma 40、scan 32、vcvt 28、sync 25、alloca 24、rdreg/setreg 21、addrspacecast 16、sort 10、i1 5)已通过对打印名字符串集合执行 rg -c 逐字节确认;较小的边界类别(transcendental/EUP、scalar-ALU、ptr/addressing、shuffle、trace、CBREG、task)是名称家族估计,其精确成员无法用 grep 干净地隔离。这 20 个大小不是精确分区,它们覆盖 1356 个中的 1348 个(关于缺失的八个 op,见 20 个类别)。这是本页的核心重新实现工件:它告诉读者每个具名内在函数驱动哪个 SparseCore 硬件单元,而不必倾倒 1356 行。该分类通过名称家族分组恢复,并与打印名字符串集合交叉核对;逐类别硬件目标则连接到 SparseCore 引擎页面和 V5+ EmitX 位位置工作。

20 个类别 {#the-20-classes}

#ops = 类别大小;HW target = 它降低到的 SparseCore 引擎 / LLO 槽位;st = C(编码已在相邻页面字节确认)或 I(引擎已确认,逐叶 opcode 为推断)。

#ops功能类别(tpu_* 前缀)HW 目标 / 降低st
834sparsecore-stream(stream_*SparseCore stream/scatter 引擎描述符(linear/strided/indirect × gather/scatter/vreg,CBREG-windowed);→ 通过 LowerToSparseCoreLlvm 变成 LLVM 调用I
87pack / unpack(pack*, unpack*VPU pack/unpack 槽位 → llo.vpack*/llo.vunpack*;用于 MXU/quant 的子字节暂存(b32→b16→b8→b4→b2→b1,e4m3/e5m2/s8/u8)C
74vector load/store(vld*, vst*VPU mem 槽位 → llo.vector_{load,store}[_masked]_idx 索引式,_cb CBREG-windowed,_strided_add scatter,_np no-predicateC
47semaphore wait/watch(wait*, watch*sflag VWait 槽位 → llo.vwait.{eq,ne,lt,le,gt,ge}[.done]_yieldable=seq-yield,_imem=instr-mem,ordone=or-doneC
40DMA descriptor(dma_*_sc_*SparseCore DMA 引擎命令(simple/single_strided/general 层级);8/10/16 操作数描述符;参见 ScDialect DmaSimpleStartC
32scan / segment-scan / reduce({add,min,max}_*scan*SparseCore scan 单元(add/max/min × full/half/1xN/2xN × seg × index)— 嵌入聚合原语I
28vector convert(vcvt*, cvt*VPU convert 槽位 → llo.vcvt.*;f32↔bf16/bf8/hf16/if8/s4/s8/u4/u8;_sr=stochastic-round,_pr=probabilisticC
25semaphore set/add(syncadd*, syncset*, sfence, sync{donemov,pamov,readpa,setpa}sflag VSync 槽位 → llo.vsync.{add,set}[.done,.remote]_remote=ICI peer,_tile/_pa=tile/public bank,_doneinv=invert doneC
24transcendental / EUP(rcp,rsqrt,tanh,sin,cos,erf,log2,pow2,sigshftEUP VALU3 push(Alu3 op0 + 5-bit selector)+ PopEupResult;每个 bare + _macro push+pop 对C
24alloca / allocate(alloca*, allocate*SparseCore allocator(smem/spmem/vmem/sflag/hbm/iova/timem/tilesmem/tilespmem/dreg/cbreg + _dyn + _any);参见 ScDialect AllocaC
21control register rd/set(rdreg_*, setreg_*scalar RdReg/SetReg → SCS scalar 槽位;cycle counters、tid/scid/tag id regs、fsr/ddr/dmacrdt/sflagrangeC
19pointer / addressing / loop-bc(inttoptr,ptrtoint,bc_*,…)LLVM inttoptr/ptrtoint/addrspace + loop bytecode(bc_loop_*, bc_load/store_aliaddr, bc_select_predicate, make_restrict_ptrC
16addrspacecast(addrspacecast*LLVM addrspacecast → SparseCore 地址空间 ID(base 201;AddressSpaceDescription @ 0x135462c0C
14scalar ALU / scalar mem(shll,shra,sadd_ov,addcarry,…)SCS scalar 槽位:shll/shra/shrl/sshllo shifts、sadd_ov/ssub_ov/sshla_ov overflow-add、addcarry、add_{high,low}_f32C
14lane / sublane shuffle / permute(vrot_sublane,vperm,sc_permuteVPU cross-lane 槽位 → llo.vrot.slane/llo.vperm.sublane/llo.vslaneseq/vshift_insert/sc_mask_permuteC
12CBREG / circular-buffer(rdcbreg,wrcbreg,cbreg_add,…)scalar CBREG ops:rd/wr/add/copy CBREG {base,offset,size};16 CBREGs/bank,dual smem/tilespmem base,allocate_cbregC
12trace / telemetry / sc-control(sc_*,strace,event,read_*cycleSparseCore control/trace:strace/event/spill_debug/log/mprefix,read_{global,local}_cycle_count,ssetpstate/ssettmC
10sort / unique / dupcount(sort*,uniquef,dupcntf,vmpcntSparseCore sort/unique 单元:sort_{asc,dsc}d{f,i},uniquef/i,dupcntf/i,vmctz/vmpcnt_ones(embedding dedup)I
10task / control / structural(task_*,loop_*,barrier,nop,…)SparseCore tile-task + structural:task_dispatch、loop_{name,parallel}、barrier、nop、delay、clear_ibuf、halt_trap、tileidC
5i1-mask width conversion(*i1_to_*i1VPU mask 槽位:tpu_{8,16,32}i1_to_{8,16,32}i1 — vector-mask 宽度重打包C
text
834+87+74+47+40+32+28+25+24+24+21+19+16+14+14+12+12+10+10+5  =  1348   (of 1356)

注意 — 类别大小已逐个字节确认(对 llvm.tpu.* 字符串集合执行 rg -c),但这 20 行是名称家族分组,不是精确分区:它们合计为 1348,比 1356 总数少八个。缺口位于软边界类别(transcendental/EUP、scalar-ALU、ptr/addressing、trace、task),其中少数 op,例如 exponent*_macro 对,以及杂项 control/structural 内在函数,不落入任何单一前缀行。应把该分类视为按前缀覆盖 1356 个中的 1348 个,而不是已验证的 1:1 分区。sync 类别拆分为:9 个 syncadd* + 12 个 syncset* + sfence + 4 个 singleton = 25。

特性 — 五个最大类别(stream、pack/unpack、vld/vst、wait、dma)为 834+87+74+47+40 = 1082,占 1356 的 80 % — 该表面 80 % 是 SparseCore 数据移动,不是计算。transcendental/EUP 类有 24 个 op,scalar-ALU 类有 14 个;SparseCore 是一台 gather/scatter/sflag 机器,自身只做很少算术。重新实现者在分配工作量时应预期 stream-engine 描述符会主导工作,而不是数学运算。


Stream 家族(834 个 op)

目的

tpu_stream_* 家族占内在函数表面的 62 %,也是最重要的 SparseCore 原语:嵌入表 gather/scatter 引擎。它的 834 路爆炸并不是 834 个互不相关的 op,而是一个四轴叉积,其中每个单元格都是不同的已注册内在函数,因此逐 (pattern,verb,dtype,memspace) 的 stream-engine 命令由 IR 层面的 op 身份选择,而不是由运行时解码的属性选择。

叉积轴

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

  axis            values                                          how it splits the 834
  --------------------------------------------------------------------------------------
  pattern         linear (180) · strided (114) · indirect (540)   address-generation mode
  verb            vreg (360) · gather (246) · scatter (228)        direction / lane-spread
  dtype           bf16 · e4m3 · e5m2 · f32 · s16 · s32 (6)         exactly 111 ops each (6×111=666 dtyped)
  transfer        _to_tilespmem 399 · _to_spmem 210 · _to_smem 27  src→dst memspace pair
                  · _to_hbm4b 15 · _to_hbm 15
  modifier        _cb_ (CBREG-windowed, 556) · _add (scatter-add) · _np (no-predicate)

indirect pattern 占主导(540),因为它就是嵌入查找模式:索引流选择行。_cb_(CBREG-windowed)修饰符出现在 834 个中的 556 个上;这些窗口化形式使用 INDIRECT_OFFSET_SOURCE_CBREG 源进行嵌入表窗口化(见 CBREG)。gather 将行拉 tile-local SPMEM(因此 _to_tilespmem 是最大的传输桶);scatter/scatter-add 将累积梯度推回外部。

其编码的流水线

text
        HBM embedding table                         tile-local SPMEM
        ┌───────────────┐    indirect gather        ┌──────────────┐
        │ row 0         │ ── (CBREG-windowed) ─────▶ │ gathered rows│
        │ row 1         │    indexed by offset       │              │
        │ …             │    stream                  └──────┬───────┘
        └───────────────┘                                   │ compute (forward)
                ▲                                            ▼
                │  scatter-add (_add)                 ┌──────────────┐
                └──────── accumulate gradients ────── │ updated rows │
                                                      └──────────────┘

代表性签名

c
// tpu_stream_linear_gather_add_f32_hbm_to_tilespmem
//   ::create(OpBuilder&, Location, Value, Value, Value, Value, Value, Value)   // 6 operands
// tpu_stream_indirect_gather_add_bf16_hbm_to_tilespmem
//   ::create(OpBuilder&, Location, Value ×8)                                    // 8 operands
//
// The operand count tracks the pattern: linear/strided forms carry 6 SSA operands
// (src/dst handle + base/offset/size + sflag); the indirect forms carry 8
// (the extra two are the index/offset-stream + its CBREG window).

注意 — 所有 834 个逐叶内在函数→数字 stream-engine 命令只在类别→引擎层面推断。类别映射到 SparseCore stream 引擎,描述符操作数形状已逐字节恢复;逐 (pattern,verb,dtype,memspace) 的 HW 命令属于 SparseCore stream ISA,是 DMA 描述符的同级内容,并未对 834 个逐一字节倾倒。见 Stream Gather/Scatter


ODS 形状恢复

目的

每个内在函数的操作数/结果声明可以在没有 TableGen 源码的情况下从二进制中恢复,方法与 tpu → LLO ODS 降低 恢复 LLO 签名的方式相同:带类型的 create 符号经反混淆后的参数列表就是源码顺序中的 ODS 声明。

恢复规则

c
// create(OpBuilder&, Location, <ODS args in declaration order>)
//   mlir::Type   -> 1 explicit result type (inference-free op)
//   mlir::Value  -> 1 SSA operand
// Cross-checked against the op's NOperands<N> trait, which pins the operand count
// independently of the create arg list (e.g. tpu_syncadd carries NOperands<2>).

1356 个中有 466 个携带带类型的 create;其余 890 个使用通用的 (TypeRange, ValueRange, ArrayRef<NamedAttribute>) 默认 builder(结果类型通过 SameOperandsAndResultType/InferType 推断,操作数数量按名称家族元数确定)。已针对二进制验证的带类型形式:

intrinsic(class)create args(Location 之后)operands
tpu_addrspacecast(addrspacecast)Type, Value1 res, 1 opnd
tpu_addrspacecast_smem / _spmem / _*_tecType, Value, Value+ tile-window/base
tpu_dma_*_sc_simple(DMA)Value ×88-field descriptor
tpu_dma_*_sc_single_strided(DMA)Value ×10+ stride
tpu_dma_*_sc_general(DMA)Value ×16multi-dim
tpu_stream_linear_*(stream)Value ×6stream descriptor
tpu_stream_indirect_*(stream)Value ×8+ index/offset stream
tpu_syncadd(sync)Value, Valuesflag, delta
tpu_fetch_and_add(sync)Value, Value, Valuesflag, addr, value
tpu_*_macro(EUP,例如 tpu_sin_macroType, Value1 res, 1 opnd
tpu_rdcbreg_offset / _size(CBREG)Type, Valueresult, cbreg
tpu_wrcbreg_offset(CBREG)Type, Value, Valuecbreg, value
tpu_inttoptr / tpu_ptrtoint(ptr)Type, Valueresult, val

DMA _single_strided 层级携带 10 个 SSA 操作数:经反混淆的 tpu_dma_hbm_to_hbm_sc_single_strided::create 参数列表是 Value + 9×S5_(对先前 Value 类型的反向引用),使 stride 层级比 _simple 8 多两个操作数,并低于 _general 16。stream 家族同样不统一:linear/strided pattern 携带 6 个操作数,而 indirect pattern 携带 8 个,额外两个是 index/offset stream 及其 CBREG window。


ID 表组织 {#id-table-organisation}

目的

重新实现者必须复现 1356 个 op 如何注册进一个方言。答案是 10 批次注册器 — 一种 TableGen 模式,将一个逻辑上的 addOperations<…> 拆成十个函数,以限制每个函数的实例化大小。这就是本页的“ID 表”结构:内在函数 ID 按十个批次的注册顺序分配。

注册器

text
LlvmTpuDialect::initialize
  └─ registerLlvmTpuDialectOperations   @0x146d0560   ── tail-calls 10 sub-registrars:
       ├─ registerLlvmTpuDialectOperations0   @0x146d05c0
       ├─ registerLlvmTpuDialectOperations1   @0x1472bea0
       ├─ registerLlvmTpuDialectOperations2   @0x1478b500
       ├─ registerLlvmTpuDialectOperations3   @0x147e1c40
       ├─ registerLlvmTpuDialectOperations4   @0x14835b80
       ├─ registerLlvmTpuDialectOperations5   @0x148891c0
       ├─ registerLlvmTpuDialectOperations6   @0x148dc3c0
       ├─ registerLlvmTpuDialectOperations7   @0x1492d5c0
       ├─ registerLlvmTpuDialectOperations8   @0x14982d00
       └─ registerLlvmTpuDialectOperations9   @0x149d88e0   (last batch)
                                                ── 10 × ~135 ops  =  1356

每个批次都是一个可变参数 addOperations<tpu_X, tpu_Y, …>,为每个模板参数物化一个 RegisteredOperationName::Model<Op>,也就是标准 MLIR op 注册 ABI,只是拆分成了十个函数。该方言中没有单独的数字“intrinsic ID enum”表:op 的身份就是它的 TypeID/RegisteredOperationName,而打印出的 llvm.tpu.* 名称就是 LLVM translator 发出的 ID。Model vtable 跨越一个连续的 .data.rel.ro 区域(tpu_16i1_to_32i1tpu_wrcbreg_tilespmem_base)。

特性 — ≤256-op 的批次拆分是 TableGen 产物,不是语义分组。批次 N 不对应功能类别 N;同一家族的 op(例如 834 个 stream)按字母类别顺序散布在所有十个批次中。重新实现者不应假设批次成员关系除了“在这里注册这些约 135 个 op”之外还携带任何含义。

注册绑定

c
function registerLlvmTpuDialectOperations(LlvmTpuDialect *d):   // 0x146d0560
    registerLlvmTpuDialectOperations0(d);                       // each batch:
                                                           //   addOperations<tpu_A, tpu_B, …>(d)
    return registerLlvmTpuDialectOperations9(d);                //   -> RegisteredOperationName::insert ×135

方言类是 mlir::sparse_core::LlvmTpuDialect(ctor LlvmTpuDialectC1EPNS_11MLIRContextE)。它的配套 helper — AddressSpaceDescription(int) @ 0x135462c0GetAnyTypeFromAddressSpace(int)、attr parse/print 对,以及 target-CPU 属性谓词 — 是这些内在函数依赖的方言级机制,用于内存空间和目标解析。


桥接到 LLVM 后端

目的

这些内在函数不会停在 MLIR。LowerToSparseCoreLlvmPass 将每个 tpu_* op 重写为其 LLVM 方言形式,使 SparseCore LLVM 后端可以为它生成代码。本节命名该桥接,并指向负责每条降低分支的页面。

消费 pass

text
xla::tpu::sparse_core::CreateLowerToSparseCoreLlvmPass     @0x135667c0  ── factory
  └─ LowerToSparseCoreLlvmPass::runOnOperation             @0x13566d00  ── driver
       └─ lowerFunc                                        @0x13568280  ── per-op rewrite

按类别,降低分支各不相同:

classlowers toowned by
addrspacecast按 intrinsic ID 选择的 LLVM addrspacecast / INTRINSIC_WO_CHAINaddrspacecast ISel
transcendental / EUPEUP VALU3 push(Alu3 op0 + 5-bit selector)+ PopEupResultEUP 超越函数槽位
CBREGscalar CBREG ops(ReadCbreg 0x36 / WriteCbreg 0x35 / AddCbreg 0x33)CBREG
sparsecore-stream逐 (pattern,verb,dtype,memspace) 的 stream-engine 描述符Stream Gather/Scatter
sync / waitsflag VSync/VWait LLO opsVPU 槽位
pack/unpack, vcvt, vld/vst, permuteVPU 槽位 op(llo.v*VPU 槽位
scan / sort / uniqueSparseCore scan/sort/dedup 单元Scan 数据路径, Rank & Permute / Radixsort

注意 — addrspacecast 分支不是 ISD::ADDRSPACECAST(0xf4) 降低。SC cast 内在函数作为内在函数调用INTRINSIC_WO_CHAIN)存活到 LLVM-IR 中,不同于 TensorCore 前端真正的 addrspacecast 指令。关于完整的逐 cast from→to 映射,以及为什么把 SC cast 接入 LowerADDRSPACECAST 会产生一个因 CannotYetSelect 而陷入的后端,见 addrspacecast ISel


未恢复内容

给重新实现者的真实缺口:

  • 逐叶 stream-engine 命令(834 个 op)。 类别→引擎已确认,描述符操作数形状已恢复;逐 (pattern,verb,dtype,memspace) 的数字 HW 命令值没有单独逐字节倾倒。这是 SparseCore stream ISA,是 DMA 描述符的同级内容。
  • 逐内在函数 LLVM IntrProperties 位集。 每个 op 携带哪些 OpInterface 可从 interface-Model 符号观察到(AliasAnalysis 546、MemoryEffect 285、Bytecode 188、AccessGroup 180);驱动后端调度/别名分析的精确逐 op IntrNoMem/IntrArgMemOnly/IntrWillReturn 位集未转录。
  • 890 个默认 builder op 的精确元数 + 结果 TypeConstraint 已按名称家族和存在时的 NOperands<N> trait 恢复;逐 op verifyInvariantsImpl 字节解码(1-vs-2 操作数,Vreg/Mask/Scalar/Ptr 结果谓词)未穷尽遍历。
  • 完整的数字地址空间 ID 表。 AddressSpaceDescription switch base(201)和抽样 case 字符串(HBMAny, SflagAny, SflagTile, TileSmem,以及 Smem/Sflag/HBM/Dreg)已解码;完整 ID↔space 映射和 16 个 addrspacecast from→to ID 对在 addrspacecast ISel 中补全。
  • scan/sort/unique 引擎 opcode 编码(32+11 个 op)。 已按名称映射到 SparseCore scan/sort/dedup 单元;逐 op HW 命令位布局未解码(这些是 SparseCore 专用计算单元,不是 TensorCore LLO 槽位)。

交叉引用 {#cross-references}

  • tpu → LLO ODS 降低另一个表面:86-op tpu 方言降低到 322 个 llo.*Op 类;本页复用的从 create 恢复 ODS 的规则
  • TPU 编译器 — Part V 定位;SparseCore 降低位于五阶段下降中的位置
  • 降低到 SparseCore LLVM — 将这些内在函数转成 LLVM-IR 的消费 LowerToSparseCoreLlvmPass
  • Dot/Conv MXU 降低 — TensorCore matmul 降低,与 SparseCore stream 引擎形成对比
  • addrspacecast ISel — 指令选择处的 16 个 addrspacecast 内在函数;完整 from→to 地址空间映射
  • Stream Gather/Scatter — 834-op stream 家族的引擎侧细节
  • CBREG — CBREG 和 _cb_ stream 内在函数驱动的每 bank 16 个 CBREG 的循环缓冲区
  • Scan 数据路径 — 32 个 scan 内在函数瞄准的 scan/segment-scan 引擎
  • Rank & Permute / Radixsort — 11 个 sort 内在函数瞄准的 sort/unique/dedup 单元
  • EUP 超越函数槽位 — 24 个 transcendental 内在函数降低到的 EUP VALU3 push/pop
  • VPU 槽位 — pack/unpack、convert、load/store、permute 和 sync/wait 内在函数瞄准的 VPU 槽位 op
  • MXU 槽位 — pack/unpack 暂存馈入的 MXU bundle 槽位