bridge(loop): exit PHI を SSOT へ統一(break/continue スナップショットの stack 化)+ ループ比較スモーク(bridge)追加\n\n- lowering.rs: ループ用 break/continue スナップショットを thread-local stack で管理(push/pop/record)\n- loop_.rs: continue/break スナップを取り込み、seal_incomplete_phis_with・build_exit_phis_with に委譲\n- smokes: bridge_loop_sum/break/continue を opt-in 追加(SMOKES_ENABLE_LOOP_BRIDGE=1)
This commit is contained in:
@ -4,6 +4,7 @@ use crate::mir::{
|
||||
MirPrinter, MirType, ValueId,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
use std::cell::RefCell;
|
||||
|
||||
// Split out merge/new_block helpers for readability (no behavior change)
|
||||
mod merge;
|
||||
@ -23,6 +24,41 @@ pub(super) struct LoopContext {
|
||||
pub(super) exit_bb: BasicBlockId,
|
||||
}
|
||||
|
||||
// Snapshot stacks for loop break/continue (per-nested-loop frame)
|
||||
thread_local! {
|
||||
static EXIT_SNAPSHOT_STACK: RefCell<Vec<Vec<(BasicBlockId, HashMap<String, ValueId>)>>> = RefCell::new(Vec::new());
|
||||
static CONT_SNAPSHOT_STACK: RefCell<Vec<Vec<(BasicBlockId, HashMap<String, ValueId>)>>> = RefCell::new(Vec::new());
|
||||
}
|
||||
|
||||
pub(super) fn push_loop_snapshot_frames() {
|
||||
EXIT_SNAPSHOT_STACK.with(|s| s.borrow_mut().push(Vec::new()));
|
||||
CONT_SNAPSHOT_STACK.with(|s| s.borrow_mut().push(Vec::new()));
|
||||
}
|
||||
|
||||
pub(super) fn pop_exit_snapshots() -> Vec<(BasicBlockId, HashMap<String, ValueId>)> {
|
||||
EXIT_SNAPSHOT_STACK.with(|s| s.borrow_mut().pop().unwrap_or_default())
|
||||
}
|
||||
|
||||
pub(super) fn pop_continue_snapshots() -> Vec<(BasicBlockId, HashMap<String, ValueId>)> {
|
||||
CONT_SNAPSHOT_STACK.with(|s| s.borrow_mut().pop().unwrap_or_default())
|
||||
}
|
||||
|
||||
fn record_exit_snapshot(cur_bb: BasicBlockId, vars: &HashMap<String, ValueId>) {
|
||||
EXIT_SNAPSHOT_STACK.with(|s| {
|
||||
if let Some(top) = s.borrow_mut().last_mut() {
|
||||
top.push((cur_bb, vars.clone()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn record_continue_snapshot(cur_bb: BasicBlockId, vars: &HashMap<String, ValueId>) {
|
||||
CONT_SNAPSHOT_STACK.with(|s| {
|
||||
if let Some(top) = s.borrow_mut().last_mut() {
|
||||
top.push((cur_bb, vars.clone()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(super) struct BridgeEnv {
|
||||
pub(super) throw_enabled: bool,
|
||||
@ -128,12 +164,16 @@ pub(super) fn lower_stmt_with_vars(
|
||||
}
|
||||
StmtV0::Break => {
|
||||
if let Some(ctx) = loop_stack.last().copied() {
|
||||
// snapshot variables at break
|
||||
record_exit_snapshot(cur_bb, vars);
|
||||
lower_break_stmt(f, cur_bb, ctx.exit_bb);
|
||||
}
|
||||
Ok(cur_bb)
|
||||
}
|
||||
StmtV0::Continue => {
|
||||
if let Some(ctx) = loop_stack.last().copied() {
|
||||
// snapshot variables at continue
|
||||
record_continue_snapshot(cur_bb, vars);
|
||||
lower_continue_stmt(f, cur_bb, ctx.cond_bb);
|
||||
}
|
||||
Ok(cur_bb)
|
||||
|
||||
@ -30,7 +30,7 @@ pub(super) fn lower_loop_stmt(
|
||||
}
|
||||
}
|
||||
|
||||
// 3) LoopPhiOps アダプタ
|
||||
// 3) LoopPhiOps アダプタ(準備用: preheader seed 専用)
|
||||
struct Ops<'a> {
|
||||
f: &'a mut MirFunction,
|
||||
vars: &'a mut HashMap<String, ValueId>,
|
||||
@ -81,6 +81,8 @@ pub(super) fn lower_loop_stmt(
|
||||
let mut incomplete = crate::mir::phi_core::loop_phi::prepare_loop_variables_with(
|
||||
&mut ops, cond_bb, cur_bb, &base_vars,
|
||||
)?;
|
||||
// Header snapshot for exit PHIs
|
||||
let header_vars_snapshot = ops.vars.clone();
|
||||
|
||||
let (cval, _cend) = super::expr::lower_expr_with_vars(env, ops.f, cond_bb, cond, ops.vars)?;
|
||||
if let Some(bb) = ops.f.get_block_mut(cond_bb) {
|
||||
@ -91,12 +93,19 @@ pub(super) fn lower_loop_stmt(
|
||||
});
|
||||
}
|
||||
let mut body_vars = ops.vars.clone();
|
||||
// open snapshot frames for nested break/continue
|
||||
super::push_loop_snapshot_frames();
|
||||
loop_stack.push(LoopContext { cond_bb, exit_bb });
|
||||
let bend_res = lower_stmt_list_with_vars(ops.f, body_bb, body, &mut body_vars, loop_stack, env);
|
||||
loop_stack.pop();
|
||||
let bend = bend_res?;
|
||||
// latch(body末尾)スナップショット
|
||||
block_var_maps.insert(bend, body_vars.clone());
|
||||
// collect snapshots for this loop level
|
||||
let continue_snaps = super::pop_continue_snapshots();
|
||||
let exit_snaps = super::pop_exit_snapshots();
|
||||
// latch(body末尾)スナップショットを別マップに構築
|
||||
let mut block_var_maps2: HashMap<BasicBlockId, HashMap<String, ValueId>> = HashMap::new();
|
||||
block_var_maps2.insert(cur_bb, base_vars.clone());
|
||||
block_var_maps2.insert(bend, body_vars.clone());
|
||||
if let Some(bb) = ops.f.get_block_mut(bend) {
|
||||
if !bb.is_terminated() {
|
||||
bb.set_terminator(MirInstruction::Jump { target: cond_bb });
|
||||
@ -110,14 +119,23 @@ pub(super) fn lower_loop_stmt(
|
||||
);
|
||||
if backedge_to_cond {
|
||||
// 5) header の不完全PHIを完成(latch + continue スナップショット集約)
|
||||
let continue_snaps: Vec<(BasicBlockId, HashMap<String, ValueId>)> = Vec::new();
|
||||
let mut ops_seal = Ops { f: ops.f, vars: ops.vars, block_var_maps: &block_var_maps2 };
|
||||
crate::mir::phi_core::loop_phi::seal_incomplete_phis_with(
|
||||
&mut ops,
|
||||
&mut ops_seal,
|
||||
cond_bb,
|
||||
bend,
|
||||
std::mem::take(&mut incomplete),
|
||||
&continue_snaps,
|
||||
)?;
|
||||
}
|
||||
// 6) exit PHIs(breakの合流 + headerからのフォールスルー)
|
||||
let mut ops_exit = Ops { f: ops.f, vars: ops.vars, block_var_maps: &block_var_maps2 };
|
||||
crate::mir::phi_core::loop_phi::build_exit_phis_with(
|
||||
&mut ops_exit,
|
||||
cond_bb,
|
||||
exit_bb,
|
||||
&header_vars_snapshot,
|
||||
&exit_snaps,
|
||||
)?;
|
||||
Ok(exit_bb)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user