mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-26 11:41:13 +08:00
perf: DCE 两入口零删除时跳过 mark-sweep 重建
This commit is contained in:
@@ -35,7 +35,10 @@ pub fn dce(f: &mut IRFunction) {
|
|||||||
let dead = keep.iter().filter(|k| !**k).count();
|
let dead = keep.iter().filter(|k| !**k).count();
|
||||||
dce_info!("DCE: removing {} dead instructions", dead);
|
dce_info!("DCE: removing {} dead instructions", dead);
|
||||||
// Pass C:mark-sweep 一次性重建 insts + label_pos 重映射。
|
// Pass C:mark-sweep 一次性重建 insts + label_pos 重映射。
|
||||||
rebuild::pass_c_sweep(f, &keep);
|
// keep 全真时重建为恒等变换(新旧下标相同、label 重映射为恒等),零删除直接跳过。
|
||||||
|
if dead > 0 {
|
||||||
|
rebuild::pass_c_sweep(f, &keep);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 精确二轮:liveness 驱动的死指令 + 局部死 STORE_VAR 删除。
|
/// 精确二轮:liveness 驱动的死指令 + 局部死 STORE_VAR 删除。
|
||||||
@@ -53,6 +56,9 @@ pub fn dce_precise(f: &mut IRFunction, live: &LiveInfo) {
|
|||||||
}
|
}
|
||||||
let mut keep = vec![true; f.insts.len()];
|
let mut keep = vec![true; f.insts.len()];
|
||||||
precise_sweep::pass_dead_with_liveness(f, live, &mut keep);
|
precise_sweep::pass_dead_with_liveness(f, live, &mut keep);
|
||||||
// mark-sweep 一次性重建
|
// keep 全真时重建为恒等变换,零删除直接跳过;重建条件与快速路径守卫同源(仅 keep 计数)。
|
||||||
rebuild::pass_c_sweep(f, &keep);
|
let dead = keep.iter().filter(|k| !**k).count();
|
||||||
|
if dead > 0 {
|
||||||
|
rebuild::pass_c_sweep(f, &keep);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,3 +55,25 @@ fn if_else_both_branches_reachable_kept() {
|
|||||||
assert_eq!(f.label_pos, vec![Some(3), Some(4)], "存活 label 重映射到新下标");
|
assert_eq!(f.label_pos, vec![Some(3), Some(4)], "存活 label 重映射到新下标");
|
||||||
assert_eq!(f.label_count, 2, "label_count 保持原值,不参与重建");
|
assert_eq!(f.label_count, 2, "label_count 保持原值,不参与重建");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 全存活函数:含 label 与 nested 的函数过 dce 后 insts 与 label_pos 逐位不变。
|
||||||
|
/// 零删除时 Pass C 重建为恒等变换,快速路径跳过重建后输出须与执行前逐位一致。
|
||||||
|
#[test]
|
||||||
|
fn all_live_function_unchanged() {
|
||||||
|
let mut f = IRFunction::new();
|
||||||
|
f.insts.push(Inst::load_const(Operand::Reg(1), 0)); // 0: label 0 目标,值被 CALL 使用
|
||||||
|
f.insts.push(Inst::call(Operand::Reg(2), Operand::Reg(1), Operand::Reg(3), 1)); // 1: 非纯,永不删
|
||||||
|
f.insts
|
||||||
|
.push(Inst::new(OpCode::RETURN, Operand::Reg(2), Operand::None, Operand::None)); // 2
|
||||||
|
f.label_pos = vec![Some(0)];
|
||||||
|
f.label_count = 1;
|
||||||
|
f.nested.push(IRFunction::new()); // nested 不递归不回收
|
||||||
|
|
||||||
|
let before_insts = f.insts.clone();
|
||||||
|
let before_labels = f.label_pos.clone();
|
||||||
|
dce(&mut f);
|
||||||
|
assert_eq!(f.insts, before_insts, "全存活时 insts 逐位不变");
|
||||||
|
assert_eq!(f.label_pos, before_labels, "全存活时 label_pos 逐位不变");
|
||||||
|
assert_eq!(f.label_count, 1, "label_count 保持原值");
|
||||||
|
assert_eq!(f.nested.len(), 1, "nested 不触碰");
|
||||||
|
}
|
||||||
|
|||||||
@@ -235,3 +235,32 @@ fn empty_function_unchanged() {
|
|||||||
dce_precise(&mut f, &live);
|
dce_precise(&mut f, &live);
|
||||||
assert!(f.insts.is_empty());
|
assert!(f.insts.is_empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 零删除快速路径:live 集全活时 dce_precise 输出逐位不变。
|
||||||
|
/// 标记后 keep 全真,Pass C 重建为恒等变换,跳过重建须与执行前逐位一致。
|
||||||
|
#[test]
|
||||||
|
fn all_live_precise_unchanged() {
|
||||||
|
let mut f = IRFunction::new();
|
||||||
|
f.insts.push(Inst::load_const(Operand::Reg(1), 0)); // 0: label 0 目标,r1 后续活
|
||||||
|
f.insts.push(Inst::new(
|
||||||
|
oxide_bytecode::opcode::OpCode::STORE_VAR,
|
||||||
|
Operand::Reg(2),
|
||||||
|
Operand::Reg(1),
|
||||||
|
Operand::Imm(0),
|
||||||
|
)); // 1: r2 后续活
|
||||||
|
f.insts.push(Inst::new(
|
||||||
|
oxide_bytecode::opcode::OpCode::RETURN,
|
||||||
|
Operand::Reg(2),
|
||||||
|
Operand::None,
|
||||||
|
Operand::None,
|
||||||
|
)); // 2
|
||||||
|
f.label_pos = vec![Some(0)];
|
||||||
|
f.label_count = 1;
|
||||||
|
|
||||||
|
let before_insts = f.insts.clone();
|
||||||
|
let before_labels = f.label_pos.clone();
|
||||||
|
// 全活:每个 def 寄存器都在其 live_after 中
|
||||||
|
run_precise(&mut f, &[&[1, 2], &[2], &[]], 5);
|
||||||
|
assert_eq!(f.insts, before_insts, "全活时 insts 逐位不变");
|
||||||
|
assert_eq!(f.label_pos, before_labels, "全活时 label_pos 逐位不变");
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user