You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
1. 设计结论
本 Pass 在
pto.vecscope/pto.strict_vecscope内分析pto.vlds和pto.vsts的 UB 访存 hazard,自动插入方向相关的pto.mem_bar。采用以下明确方案:
VecScopeMemBar目录;Analyze -> Plan -> Apply;scf.for;NoAlias时保守按MayAlias处理;本 Pass 只处理 Vector pipeline 内部的 UB 访问顺序,不替代现有跨 pipeline 的
set_flag/wait_flag、get_buf/rls_buf或pto.barrier同步。2. 支持范围
2.1 精确支持
pto.vecscope;pto.strict_vecscope;pto.vlds;pto.vsts;pto.vgather2、pto.vgatherb、pto.vgather2_bc,按 load 分类;pto.vscatter,按 store 分类;scf.for;scf.forlower bound、upper bound 和 step 的精确循环分析;arith.constant、arith.addi、arith.subi;arith.muli;affine.apply;pto.castptr、pto.addptr和稳定 symbolic root;pto.mem_bar;2.2 保守支持
下列情况不做精确 footprint,但不能漏掉 hazard:
vsts;处理原则是:只有能够证明
NoAlias才跳过,否则返回MayAlias。Gather/scatter 使用更严格的固定规则:不解析离散地址集合。只要一个访问对中任一
访问是 gather/scatter,且两边属于相同 memory space,该访问对的 alias 结果固定为
MayAlias。随后按访问方向生成 RAW/WAW/WAR hazard,并必须规划对应的VST_VLD、VST_VST或VLD_VST。RAR 仍不需要屏障。2.3 VecScope 访存类别与 MEM_BAR 范围
pto.vecscope/pto.strict_vecscope内不会产生 scalarld/st,因此本 Pass 只分析vector load/store 类访问。Gather 仍属于 vector load,scatter 仍属于 vector store,
不会引入新的 MEM_BAR kind。
PTO ISA 的
MemBarKind共定义 16 种,按VV、VS、SV、SS四个 family划分,每个 family 各 4 种。本 Pass 不处理含 scalar
ld/st的VS、SV、SSfamily,只需要识别和处理以下 4 种
VVMEM_BAR:VST_VLDVLD_VSTVST_VSTVV_ALL因此,本 Pass 主动分析并生成的定向 hazard 屏障是 3 种;连同
VV_ALL,需要识别、覆盖判断和幂等处理的
VVMEM_BAR kind 共 4 种。两个 vector load 之间是 RAR,包括 gather -> gather,不需要屏障。
2.4 限制与诊断
scf.if等分支内的跨路径 hazard;scf.while;pto.vldsx2/pto.vstsx2;遇到上述控制流时应报出明确诊断,不允许递归
walk()后错误线性化。3. Hazard 定义
设
P为动态执行中较早的访问,C为较晚的访问:VSTVLDVST_VLDVSTVSTVST_VSTVLDVSTVLD_VSTVLDVLDHazard 成立需要:
MustAlias、PartialAlias或MayAlias;4. 独立目录与文件结构
新建以下目录:
同时修改:
5. 模块职责
5.1
VecScopeMemBarIR定义 Pass 内部只读分析 IR:
schedule 只需要表达 sequence 和最多两层
scf.for。5.2
VecScopeMemoryFootprint负责:
5.3
VecScopeMemBarAnalysis负责:
mem_bar;不负责选择最终屏障,也不修改 IR。
5.4
VecScopeMemBarPlacement负责:
5.5
VecScopeMemBarCodegen负责:
pto.mem_bar;5.6 Pass Driver
PTOInsertVecScopeMemBarPass.cpp只负责串联三个阶段:6. 访问与地址模型
6.1 线性字节表达式
两层循环下的地址表示为:
6.2 Footprint
vlds/vsts的 offset 是元素单位:普通连续访问的宽度:
masked
vsts按完整 vreg footprint 保守处理。Gather/scatter 设置forcesMayAlias = true,不尝试用连续区间近似其离散地址集合。6.3 Access Occurrence
7. Alias 分析
7.1 三值结果
只有
NoAlias可以跳过 hazard。7.2 Root 判定
NoAlias;forcesMayAlias:MayAlias;NoAlias;MayAlias;MayAlias。不同 SSA pointer 不等价于不同 allocation,不能据此返回
NoAlias。7.3 同迭代比较
设:
计算:
如果
i/j系数全部抵消,D为常量,可直接比较半开区间。如果系数未抵消:
D在迭代域上的最小/最大值;NoAlias;MayAlias。半开区间比较必须使用 checked arithmetic 或
APInt,避免地址加长度溢出。8. 两层循环依赖分析
8.1 Hazard 分类
8.2 同迭代
分析:
要求 producer 的静态执行位置早于 consumer,并进行同迭代 alias 比较。
8.3 内层相邻迭代
分析:
consumer 地址替换为:
再与
P(i,j)比较。若 alias 且方向为 RAW/WAW/WAR,则 hazard 由内层 loop携带。
跨迭代 pair 允许 producer 和 consumer 是同一静态访问。
8.4 外层相邻迭代
不能比较:
因为下一次外层迭代时内层 induction variable 已重置。正确比较是:
对于规范
scf.for:如果内层 loop 可以 zero-trip,则需要分别考虑:
如果 inner bounds 或 trip count 无法精确求解,地址比较降级为
MayAlias。8.5 Carrying Loop
hazard 的 carrying loop 是 iteration distance 中第一个发生变化的循环维度:
carryingLoop是 placement 决定 backedge 插点的核心属性。8.6 不枚举运行时迭代
编译期不展开实际 iteration。Pass 只操作线性表达式、loop bounds 和 iteration
transition。
动态条件无法证明安全时保守产生 hazard。
9. Analysis 输出
Analysis 不负责:
MemBarOp;10. Placement 算法
10.1 Plan 表示
10.2 同迭代插点
对于同一 sequence block 中的 hazard
(P,C),合法插点是:同一 kind 使用最右端 interval-stabbing 贪心:遇到尚未覆盖的 hazard,在其 consumer
前插入。相同 anchor 和 kind 合并。
10.3 内层 loop-carried 插点
固定在 carrying inner loop 的 terminator 前:
相同 inner loop、相同 kind 的 hazard 合并。
10.4 外层 loop-carried 插点
固定在 carrying outer loop 的 terminator 前:
相同 outer loop、相同 kind 的 hazard 合并。外层 hazard 不能依赖 inner backedge
屏障,因为 inner loop 可能 zero-trip。
10.5 传递覆盖
Placement 建立访问级 happens-before 图:
VST_VLD:屏障前 store 到屏障后 load;VLD_VST:屏障前 load 到屏障后 store;VST_VST:屏障前 store 到屏障后 store;VV_ALL:屏障前 load/store 到屏障后 load/store。通过可达性判断 hazard 是否已被直接或传递覆盖。例如:
已经建立
S1 -> S2,因此不再插VST_VST。两层循环下,图边必须携带 scope:same-iteration、inner backedge 或 outer backedge。
只有处于相同动态 transition 上的边才能组成传递链。
10.6 合法性检查
每个 placement 必须满足:
11. Codegen
Codegen 先建立:
然后:
IRRewriter在 anchor 前创建pto.mem_bar;固定顺序建议:
若 ISA 对同点多屏障顺序有额外约束,实现前再确认。
12. MEM_BAR 副作用
PTO_MemBarOp必须声明MemoryEffectsOpInterface,否则 resultless barrier 可能被canonicalizer/CSE 删除。
ODS:
C++:
必须验证 canonicalizer、CSE 和 LICM 不删除或跨越该 barrier。
13. Pass 注册
在
include/PTO/Transforms/Passes.td增加:在
include/PTO/Transforms/Passes.h增加:std::unique_ptr<Pass> createPTOInsertVecScopeMemBarPass();14. Pipeline 接入
修改
tools/ptoas/ptoas.cpp:具体插在 soft post-update 之后、LICM 之前:
kernelModulePM.addNestedPass<func::FuncOp>( pto::createPTOInferVPTOVecScopePass()); if (enableSoftPostUpdate) kernelModulePM.addPass(pto::createVPTOSoftPostUpdatePass()); kernelModulePM.addNestedPass<func::FuncOp>( pto::createPTOInsertVecScopeMemBarPass()); kernelModulePM.addPass(createLoopInvariantCodeMotionPass());新 Pass 是
func::FuncOpPass,必须使用addNestedPass<func::FuncOp>()。如第一阶段使用 CLI 开关,开关只包围新 Pass,不能把它放进
if (enableSoftPostUpdate)。15. 复杂度
设:
N:vecscope 内vlds/vsts数量;L <= 2:循环深度;H:hazard 数量,最坏O(N^2)。分析复杂度:
由于
L <= 2,总分析复杂度为:Placement:
总体时间复杂度:
空间复杂度:
16. 测试计划
16.1 同迭代
S1 -> L1 -> S2只插VST_VLD + VLD_VST,不插冗余VST_VST;16.2 地址表达式
ai*i + aj*j + c;MayAlias;16.3 一层循环
16.4 两层循环
lastJ -> firstJ;16.5 限制与保守路径
scf.if含目标访存诊断;MayAlias并插入对应方向屏障;16.6 Pipeline 与副作用
17. 实现步骤
步骤 1:MEM_BAR 副作用
getEffects();步骤 2:独立内部 IR 与 schedule
VecScopeMemBarinclude/lib 目录;scf.forschedule;步骤 3:Footprint 与 alias
步骤 4:Hazard analysis
步骤 5:Placement 与冗余消除
步骤 6:Codegen 与 Pass 接入
步骤 7:完整验证
18. 验收标准
scf.for;lastJ -> firstJ;S1 -> L1 -> S2的冗余 WAW barrier;O(N^2);19. 待确认决策
MayAlias,还是实现简单范围推导;scf.if是否直接拒绝;--enable-vecscope-mem-bar显式开启;All reactions