mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-24 02:31:13 +08:00
perf: 逐指令活集拍平为单一位集加消费方维度守卫同步
This commit is contained in:
@@ -29,5 +29,6 @@ pub fn liveness(f: &IRFunction, cfg: &Cfg) -> LiveInfo {
|
||||
block_live_out: block_out,
|
||||
inst_live_before: inst_before,
|
||||
inst_live_after: inst_after,
|
||||
words: (reg_count + 1).div_ceil(64),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,25 +4,29 @@
|
||||
//! 由 dataflow 求上界)。位 r 落在第 `r >> 6` 字的 `r & 63` 位;越界位恒 0(消费方
|
||||
//! 用 `bitset_get` 越界返回 false 对齐旧 `Vec<bool>::get` 语义)。四字段语义:
|
||||
//! - `block_live_in` / `block_live_out`:块级数据流迭代结果(精确 DCE 消费)
|
||||
//! - `inst_live_before` / `inst_live_after`:逐指令活集(RegAlloc 干涉图消费 live_before)
|
||||
//! - `inst_live_before` / `inst_live_after`:逐指令活集(RegAlloc 干涉图消费 live_before),
|
||||
//! 拍平为单一 `Vec<u64>`,长度 N×words,消费方按 i×words 切片取指
|
||||
|
||||
/// liveness 输出:块级 liveIn/liveOut + 逐指令 live_before/live_after。
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct LiveInfo {
|
||||
pub block_live_in: Vec<Vec<u64>>,
|
||||
pub block_live_out: Vec<Vec<u64>>,
|
||||
pub inst_live_before: Vec<Vec<u64>>,
|
||||
pub inst_live_after: Vec<Vec<u64>>,
|
||||
pub inst_live_before: Vec<u64>,
|
||||
pub inst_live_after: Vec<u64>,
|
||||
/// 位集字数(`(reg_count+1).div_ceil(64)`);空 LiveInfo 为 0,消费方守卫据此判过期。
|
||||
pub words: usize,
|
||||
}
|
||||
|
||||
impl LiveInfo {
|
||||
/// 构造空 LiveInfo:全空 vec,等价于 Default。
|
||||
/// 构造空 LiveInfo:全空 vec,words 为 0,等价于 Default。
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
block_live_in: Vec::new(),
|
||||
block_live_out: Vec::new(),
|
||||
inst_live_before: Vec::new(),
|
||||
inst_live_after: Vec::new(),
|
||||
words: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -60,6 +64,7 @@ mod tests {
|
||||
assert!(info.block_live_out.is_empty());
|
||||
assert!(info.inst_live_before.is_empty());
|
||||
assert!(info.inst_live_after.is_empty());
|
||||
assert_eq!(info.words, 0, "空 LiveInfo 的 words 为 0(守卫判过期依据)");
|
||||
let default = LiveInfo::default();
|
||||
assert!(default.block_live_in.is_empty());
|
||||
assert!(default.block_live_out.is_empty());
|
||||
|
||||
@@ -6,25 +6,28 @@
|
||||
//! live_before 错误剔除。Exception 目标块入口 reg 0 隐式 def 在此截断,并以
|
||||
//! `debug_assert_eq!(live, block_live_in[b])` 校验与 dataflow 一致性。
|
||||
//!
|
||||
//! 位集为 `u64` 压缩(与 dataflow 同 words 布局),逐指令集经 `copy_from_slice` 落地。
|
||||
//! 位集为 `u64` 压缩(与 dataflow 同 words 布局),逐指令集拍平为单一 `Vec<u64>`
|
||||
//! (长度 N×words)经 `copy_from_slice` 落地。
|
||||
|
||||
use oxide_cfg::Cfg;
|
||||
use oxide_ir::IRFunction;
|
||||
|
||||
use crate::live_info::{bitset_clear, bitset_set};
|
||||
|
||||
/// 逐指令 liveness:返回 (inst_live_before, inst_live_after),长度 = insts.len()。
|
||||
/// 逐指令 liveness:返回 (inst_live_before, inst_live_after),拍平为单一 `Vec<u64>`,
|
||||
/// 长度 = insts.len() × words。
|
||||
pub(super) fn inst_liveness(
|
||||
f: &IRFunction, cfg: &Cfg, block_live_out: &[Vec<u64>], block_live_in: &[Vec<u64>], reg_count: usize,
|
||||
) -> (Vec<Vec<u64>>, Vec<Vec<u64>>) {
|
||||
) -> (Vec<u64>, Vec<u64>) {
|
||||
let words = (reg_count + 1).div_ceil(64);
|
||||
let mut before = vec![vec![0u64; words]; f.insts.len()];
|
||||
let mut after = vec![vec![0u64; words]; f.insts.len()];
|
||||
let n = f.insts.len();
|
||||
let mut before = vec![0u64; n * words];
|
||||
let mut after = vec![0u64; n * words];
|
||||
let exc_targets = crate::dataflow::exception_target_blocks(cfg);
|
||||
for (b, block) in cfg.blocks.iter().enumerate() {
|
||||
let mut live = block_live_out[b].clone(); // 从块级 liveOut 出发(非 liveIn)
|
||||
for i in block.inst_range.clone().rev() {
|
||||
after[i].copy_from_slice(&live);
|
||||
after[i * words..(i + 1) * words].copy_from_slice(&live);
|
||||
// kill 先于 gen:本指令先写后读。COMPOUND_ADD 等读-写同寄存器指令的
|
||||
// uses 含 Rd,见 oxide_ir::contract 的 def/use 约定。
|
||||
if let Some(d) = f.insts[i].def_reg() {
|
||||
@@ -33,7 +36,7 @@ pub(super) fn inst_liveness(
|
||||
for u in f.insts[i].use_regs() {
|
||||
bitset_set(&mut live, u as usize);
|
||||
}
|
||||
before[i].copy_from_slice(&live);
|
||||
before[i * words..(i + 1) * words].copy_from_slice(&live);
|
||||
}
|
||||
// Exception 目标块:入口 reg 0 隐式 def(异常展开写 regs[0])截断无 def use。
|
||||
// preds 是 Vec<BBId>(无 EdgeKind),从源块 succs 侧检测 Exception 边。
|
||||
@@ -69,11 +72,12 @@ mod tests {
|
||||
let cfg = oxide_cfg::build_cfg(&f);
|
||||
let (live_in, live_out, rc) = block_liveness(&f, &cfg);
|
||||
let (before, after) = inst_liveness(&f, &cfg, &live_out, &live_in, rc);
|
||||
assert!(bitset_get(&after[0], 2), "ADD 后 r2 存活(RETURN 用)");
|
||||
assert!(bitset_get(&before[0], 0) && bitset_get(&before[0], 1), "ADD 前 r0、r1 存活");
|
||||
assert!(!bitset_get(&before[0], 2), "ADD 前 r2 不死");
|
||||
assert!(after[1].iter().all(|&w| w == 0), "RETURN 后无存活");
|
||||
assert!(bitset_get(&before[1], 2), "RETURN 前 r2 存活");
|
||||
let words = (rc + 1).div_ceil(64);
|
||||
assert!(bitset_get(&after[0..words], 2), "ADD 后 r2 存活(RETURN 用)");
|
||||
assert!(bitset_get(&before[0..words], 0) && bitset_get(&before[0..words], 1), "ADD 前 r0、r1 存活");
|
||||
assert!(!bitset_get(&before[0..words], 2), "ADD 前 r2 不死");
|
||||
assert!(after[words..2 * words].iter().all(|&w| w == 0), "RETURN 后无存活");
|
||||
assert!(bitset_get(&before[words..2 * words], 2), "RETURN 前 r2 存活");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -88,8 +92,9 @@ mod tests {
|
||||
let cfg = oxide_cfg::build_cfg(&f);
|
||||
let (live_in, live_out, rc) = block_liveness(&f, &cfg);
|
||||
let (before, _) = inst_liveness(&f, &cfg, &live_out, &live_in, rc);
|
||||
assert!(bitset_get(&before[0], 1), "COMPOUND_ADD 前 r1 旧值在读(kill 先于 gen)");
|
||||
assert!(bitset_get(&before[0], 2), "COMPOUND_ADD 前 r2 存活");
|
||||
let words = (rc + 1).div_ceil(64);
|
||||
assert!(bitset_get(&before[0..words], 1), "COMPOUND_ADD 前 r1 旧值在读(kill 先于 gen)");
|
||||
assert!(bitset_get(&before[0..words], 2), "COMPOUND_ADD 前 r2 存活");
|
||||
assert!(bitset_get(&live_in[0], 1) && bitset_get(&live_in[0], 2), "块级 liveIn 含 r1、r2");
|
||||
}
|
||||
|
||||
@@ -107,9 +112,10 @@ mod tests {
|
||||
let cfg = oxide_cfg::build_cfg(&f);
|
||||
let (live_in, live_out, rc) = block_liveness(&f, &cfg);
|
||||
let (before, after) = inst_liveness(&f, &cfg, &live_out, &live_in, rc);
|
||||
assert!(bitset_get(&before[1], 0), "LOAD_VAR 前读 CALL 结果 reg0");
|
||||
assert!(bitset_get(&after[0], 0), "CALL 后 reg0 存活(结果)");
|
||||
assert!(!bitset_get(&before[0], 0), "CALL 前 reg0 不死(区间仅 [CALL, LOAD_VAR))");
|
||||
let words = (rc + 1).div_ceil(64);
|
||||
assert!(bitset_get(&before[words..2 * words], 0), "LOAD_VAR 前读 CALL 结果 reg0");
|
||||
assert!(bitset_get(&after[0..words], 0), "CALL 后 reg0 存活(结果)");
|
||||
assert!(!bitset_get(&before[0..words], 0), "CALL 前 reg0 不死(区间仅 [CALL, LOAD_VAR))");
|
||||
assert!(!bitset_get(&live_in[0], 0), "reg0 不污染块入口");
|
||||
}
|
||||
|
||||
@@ -132,7 +138,11 @@ mod tests {
|
||||
let cfg = oxide_cfg::build_cfg(&f);
|
||||
let (live_in, live_out, rc) = block_liveness(&f, &cfg);
|
||||
let (before, _) = inst_liveness(&f, &cfg, &live_out, &live_in, rc);
|
||||
assert!(bitset_get(&before[3], 0), "catch 块内 STORE_VAR 读 reg0(异常值,正确)");
|
||||
let words = (rc + 1).div_ceil(64);
|
||||
assert!(
|
||||
bitset_get(&before[3 * words..4 * words], 0),
|
||||
"catch 块内 STORE_VAR 读 reg0(异常值,正确)"
|
||||
);
|
||||
let catch_block = cfg.blocks.iter().position(|b| b.inst_range == (3..5usize)).unwrap();
|
||||
assert!(!bitset_get(&live_in[catch_block], 0), "catch 块入口 reg0 被隐式 def 截断");
|
||||
assert!(!bitset_get(&live_in[0], 0), "try 块(entry)reg0 不污染入口");
|
||||
|
||||
@@ -16,8 +16,12 @@ fn smoke(src: &str) {
|
||||
let (info, cfg, inst_len) = run_liveness(src);
|
||||
assert_eq!(info.block_live_in.len(), cfg.blocks.len(), "block 维度一致");
|
||||
assert_eq!(info.block_live_out.len(), cfg.blocks.len(), "block 维度一致");
|
||||
assert_eq!(info.inst_live_before.len(), inst_len, "inst 维度一致");
|
||||
assert_eq!(info.inst_live_after.len(), inst_len, "inst 维度一致");
|
||||
assert_eq!(
|
||||
info.inst_live_before.len(),
|
||||
inst_len * info.words,
|
||||
"inst 维度一致(拍平后长度 = N×words)"
|
||||
);
|
||||
assert_eq!(info.inst_live_after.len(), inst_len * info.words, "inst 维度一致(拍平后长度 = N×words)");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user