“复制合并的边界同样可算。若有 $u\leftarrow v$ 且二者不干涉,把它们分到同一寄存器可删除移动;若它们在某条异常路径上同时活跃,而分析漏掉异常边,合并会覆盖仍需的 $v$。从SS…”
形式陈述 ​
对块
SSA 消解在每条进入边
其语义是先读取全部旧源值,再同时写入全部目的。若边的源有多个后继且目标有多个前驱,该边是 critical edge;复制既不能无条件放在源块末尾,也不能放在目标块开头,通常先在CFG中插入只含复制的新块来拆边。
并行复制顺序化时,可反复选择一个不再作为未完成源的目的并发射复制。若剩余图形成环,必须用新鲜临时量保存一个旧值,再旋转复制。随后可做 coalescing,把不同时活跃且机器约束兼容的源、目的映射到同一位置以消掉复制;这项优化不是消解正确性的前提。
顺序化还要处理常量、自复制和扇出。
直觉
φ 在汇合块里写“我从哪条边来就取哪一个值”,普通机器却只会按顺序执行复制。消解的任务是把这句边相关选择搬回实际进入边,同时保留“多个 φ 一起发生”的快照语义。关键边拆分为复制提供只属于这一条路径的落脚点;临时量则为复制环保存即将被覆盖的旧值。
SSA 构造把多次赋值拆成版本,消解并不是简单删除下标。不同版本可能同时活跃,强行恢复同一源变量名会覆盖值。正确的输出允许继续保留许多不同临时量,只是不再含 φ 伪指令。
例子与边界
菱形汇合块有
复制环取
异常边和带边参数的调用返回同样要求边精确性。复制若可能陷阱或改变标志寄存器,就不再是纯粹的 φ 实现;后端必须选择语义上无额外观察的移动序列。仅比较最终普通返回值会漏掉新增陷阱或异常路径。
推论与应用
消解后的程序可交给传统活跃性分析与寄存器分配。coalescing 能减少复制,但只有在两个值的 live ranges 不冲突、寄存器类别相容且预着色约束不矛盾时才安全。过度合并可能使干涉图着色失败或改变调用约定要求的位置。
SSA 消解的正确性通常分解为三条局部引理:边拆分保持路径与观察;并行复制顺序化保持旧源快照;名字合并保持所有同时活跃值可区分。把三步混成一次大改写,会让错误究竟来自 CFG、复制调度还是分配约束难以定位。
若目标机器的移动可能改变条件码,而后继第一条分支仍读取旧 flags,复制插入点也会改变观察。后端可选不破坏 flags 的 move、在复制后重建比较,或把 flags 纳入活跃资源和并行复制约束。这个例子说明 out-of-SSA 不只操作抽象变量名;越接近机器层,隐式状态越必须进入证明。
参考资料
- Preston Briggs, Keith D. Cooper, Timothy J. Harvey, and L. Taylor Simpson, “Practical Improvements to the Construction and Destruction of Static Single Assignment Form,” Software: Practice and Experience 28(8), 1998, pp. 859–881.
- Vugranam C. Sreedhar, Roy Dz-Ching Ju, David M. Gillies, and Vatsa Santhanam, “Translating Out of Static Single Assignment Form,” in SAS 1999, LNCS 1694, pp. 194–210.
- Benoit Boissinot, Alain Darte, Fabrice Rastello, Benoit Dupont de Dinechin, and Christophe Guillon, “Revisiting Out-of-SSA Translation for Correctness, Code Quality and Efficiency,” CGO, 2009, pp. 114–125.