Span trace utilities and runner source hint
This commit is contained in:
@ -180,11 +180,11 @@ impl BodyLocalPhiBuilder {
|
||||
}
|
||||
|
||||
if enable_live_rescue {
|
||||
if matches!(class, super::loop_var_classifier::LoopVarClass::BodyLocalInternal)
|
||||
&& live_at_exit.contains(*var_name)
|
||||
&& self
|
||||
.inspector
|
||||
.is_available_in_all(var_name, exit_preds)
|
||||
if matches!(
|
||||
class,
|
||||
super::loop_var_classifier::LoopVarClass::BodyLocalInternal
|
||||
) && live_at_exit.contains(*var_name)
|
||||
&& self.inspector.is_available_in_all(var_name, exit_preds)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -370,7 +370,7 @@ mod tests {
|
||||
&pinned,
|
||||
&carrier,
|
||||
&[BasicBlockId(2), BasicBlockId(5)],
|
||||
&live_at_exit, // Phase 26-F-4
|
||||
&live_at_exit, // Phase 26-F-4
|
||||
);
|
||||
|
||||
// Expected: s, idx, n (ch is BodyLocalInternal → filtered out)
|
||||
@ -406,8 +406,13 @@ mod tests {
|
||||
// Phase 26-F-4: empty live_at_exit(live情報なし)
|
||||
let live_at_exit = std::collections::BTreeSet::new();
|
||||
|
||||
let phi_vars =
|
||||
builder.filter_exit_phi_candidates(&all_vars, &pinned, &carrier, &exit_preds, &live_at_exit);
|
||||
let phi_vars = builder.filter_exit_phi_candidates(
|
||||
&all_vars,
|
||||
&pinned,
|
||||
&carrier,
|
||||
&exit_preds,
|
||||
&live_at_exit,
|
||||
);
|
||||
|
||||
// Expected: s, idx (ch filtered out!)
|
||||
assert_eq!(phi_vars.len(), 2);
|
||||
@ -474,8 +479,13 @@ mod tests {
|
||||
// Phase 26-F-4: empty live_at_exit(live情報なし)
|
||||
let live_at_exit = std::collections::BTreeSet::new();
|
||||
|
||||
let phi_vars =
|
||||
builder.filter_exit_phi_candidates(&all_vars, &pinned, &[], &[BasicBlockId(5)], &live_at_exit);
|
||||
let phi_vars = builder.filter_exit_phi_candidates(
|
||||
&all_vars,
|
||||
&pinned,
|
||||
&[],
|
||||
&[BasicBlockId(5)],
|
||||
&live_at_exit,
|
||||
);
|
||||
|
||||
// Only s should remain
|
||||
assert_eq!(phi_vars.len(), 1);
|
||||
|
||||
@ -27,7 +27,7 @@ impl ConservativeMerge {
|
||||
/// * `then_end` - then-branch終了時の変数マップ
|
||||
/// * `else_end_opt` - else-branch終了時の変数マップ(Noneの場合はempty else)
|
||||
pub fn analyze(
|
||||
pre_if: &BTreeMap<String, ValueId>, // Phase 25.1: BTreeMap化
|
||||
pre_if: &BTreeMap<String, ValueId>, // Phase 25.1: BTreeMap化
|
||||
then_end: &BTreeMap<String, ValueId>, // Phase 25.1: BTreeMap化
|
||||
else_end_opt: &Option<BTreeMap<String, ValueId>>, // Phase 25.1: BTreeMap化
|
||||
) -> Self {
|
||||
|
||||
@ -18,8 +18,8 @@ use std::collections::{BTreeMap, BTreeSet};
|
||||
use super::body_local_phi_builder::BodyLocalPhiBuilder;
|
||||
use super::loop_exit_liveness::{ExitLivenessProvider, LoopExitLivenessBox}; // Phase 26-F-4
|
||||
use super::loop_snapshot_merge::LoopSnapshotMergeBox;
|
||||
use super::phi_invariants::PhiInvariantsBox;
|
||||
use super::phi_input_collector::PhiInputCollector;
|
||||
use super::phi_invariants::PhiInvariantsBox;
|
||||
|
||||
/// Exit PHI生成専門Box
|
||||
///
|
||||
@ -76,8 +76,7 @@ impl ExitPhiBuilder {
|
||||
/// ```
|
||||
pub fn new(body_local_builder: BodyLocalPhiBuilder) -> Self {
|
||||
// 環境変数で簡易 MirScan 版を opt-in できるようにする
|
||||
let use_scan =
|
||||
std::env::var("NYASH_EXIT_LIVE_ENABLE").ok().as_deref() == Some("1");
|
||||
let use_scan = std::env::var("NYASH_EXIT_LIVE_ENABLE").ok().as_deref() == Some("1");
|
||||
if use_scan {
|
||||
Self::with_liveness(
|
||||
body_local_builder,
|
||||
@ -185,16 +184,19 @@ impl ExitPhiBuilder {
|
||||
|
||||
// Phase 26-F/G: ExitLivenessProvider で live_at_exit を計算(MirQuery 経由)
|
||||
let query = crate::mir::MirQueryBox::new(ops.mir_function());
|
||||
let live_at_exit = self
|
||||
.liveness_provider
|
||||
.compute_live_at_exit(&query, exit_id, header_vals, exit_snapshots);
|
||||
let live_at_exit = self.liveness_provider.compute_live_at_exit(
|
||||
&query,
|
||||
exit_id,
|
||||
header_vals,
|
||||
exit_snapshots,
|
||||
);
|
||||
|
||||
let phi_vars = self.body_local_builder.filter_exit_phi_candidates(
|
||||
&required_vars.iter().cloned().collect::<Vec<_>>(),
|
||||
pinned_vars,
|
||||
carrier_vars,
|
||||
&exit_preds,
|
||||
&live_at_exit, // Phase 26-F-4: live_at_exit 追加
|
||||
&live_at_exit, // Phase 26-F-4: live_at_exit 追加
|
||||
);
|
||||
|
||||
// Fail-Fast invariant(共通箱経由):
|
||||
@ -361,12 +363,9 @@ impl<T: crate::mir::phi_core::loopform_builder::LoopFormOps> LoopFormOps for T {
|
||||
}
|
||||
|
||||
fn get_block_predecessors(&self, block_id: BasicBlockId) -> BTreeSet<BasicBlockId> {
|
||||
crate::mir::phi_core::loopform_builder::LoopFormOps::get_block_predecessors(
|
||||
self,
|
||||
block_id,
|
||||
)
|
||||
.into_iter()
|
||||
.collect()
|
||||
crate::mir::phi_core::loopform_builder::LoopFormOps::get_block_predecessors(self, block_id)
|
||||
.into_iter()
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn block_exists(&self, block_id: BasicBlockId) -> bool {
|
||||
|
||||
@ -181,7 +181,9 @@ impl HeaderPhiBuilder {
|
||||
pub fn new() -> Self {
|
||||
// Phase 27.4-B/27.4C Cleanup: JoinIR 実験フラグのチェック(ログ出力のみ、挙動変更なし)
|
||||
if crate::mir::join_ir::env_flag_is_1("NYASH_JOINIR_HEADER_EXP") {
|
||||
eprintln!("[HeaderPhiBuilder] JoinIR experiment flag is ON (NYASH_JOINIR_HEADER_EXP=1)");
|
||||
eprintln!(
|
||||
"[HeaderPhiBuilder] JoinIR experiment flag is ON (NYASH_JOINIR_HEADER_EXP=1)"
|
||||
);
|
||||
}
|
||||
Self::default()
|
||||
}
|
||||
|
||||
@ -24,8 +24,8 @@
|
||||
//! - **橋渡し**: IfPhiContext経由で最小限の情報伝達(箱離婚)
|
||||
//! - **Fail-Fast**: 不正入力は即座にエラー
|
||||
|
||||
use crate::mir::{BasicBlockId, ValueId};
|
||||
use crate::mir::phi_core::phi_builder_box::IfPhiContext;
|
||||
use crate::mir::{BasicBlockId, ValueId};
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
/// If Body-Local Merge Box
|
||||
@ -105,7 +105,7 @@ impl IfBodyLocalMergeBox {
|
||||
then_end: &BTreeMap<String, ValueId>,
|
||||
else_end_opt: &Option<BTreeMap<String, ValueId>>,
|
||||
_reachable_preds: &[BasicBlockId],
|
||||
if_context: &IfPhiContext, // Phase 26-F-3: ループ内コンテキスト
|
||||
if_context: &IfPhiContext, // Phase 26-F-3: ループ内コンテキスト
|
||||
) -> Vec<String> {
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
@ -117,7 +117,8 @@ impl IfBodyLocalMergeBox {
|
||||
// 1. 両腕に存在する変数名を収集(決定的順序)
|
||||
let then_names: BTreeSet<&String> = then_end.keys().collect();
|
||||
let else_names: BTreeSet<&String> = else_end.keys().collect();
|
||||
let common_names: BTreeSet<&String> = then_names.intersection(&else_names).copied().collect();
|
||||
let common_names: BTreeSet<&String> =
|
||||
then_names.intersection(&else_names).copied().collect();
|
||||
|
||||
// Phase 26-F-3: ループ内モードで片腕のみのcarrier変数も追加
|
||||
let mut candidate_names_set = common_names.clone();
|
||||
@ -207,7 +208,7 @@ mod tests {
|
||||
&then_end,
|
||||
&Some(else_end),
|
||||
&[BasicBlockId(1), BasicBlockId(2)],
|
||||
&default_if_context(), // Phase 26-F-3: コンテキスト追加
|
||||
&default_if_context(), // Phase 26-F-3: コンテキスト追加
|
||||
);
|
||||
|
||||
assert_eq!(candidates, vec!["x".to_string()]);
|
||||
@ -228,7 +229,7 @@ mod tests {
|
||||
&then_end,
|
||||
&Some(else_end),
|
||||
&[BasicBlockId(1), BasicBlockId(2)],
|
||||
&default_if_context(), // Phase 26-F-3: コンテキスト追加
|
||||
&default_if_context(), // Phase 26-F-3: コンテキスト追加
|
||||
);
|
||||
|
||||
// 片腕のみ → BodyLocalInternal相当 → 候補なし
|
||||
@ -252,7 +253,7 @@ mod tests {
|
||||
&then_end,
|
||||
&Some(else_end),
|
||||
&[BasicBlockId(1), BasicBlockId(2)],
|
||||
&default_if_context(), // Phase 26-F-3: コンテキスト追加
|
||||
&default_if_context(), // Phase 26-F-3: コンテキスト追加
|
||||
);
|
||||
|
||||
// 値が変わってない → φ不要
|
||||
@ -279,7 +280,7 @@ mod tests {
|
||||
&then_end,
|
||||
&Some(else_end),
|
||||
&[BasicBlockId(1), BasicBlockId(2)],
|
||||
&loop_context(vec!["i"]), // i はキャリア変数
|
||||
&loop_context(vec!["i"]), // i はキャリア変数
|
||||
);
|
||||
|
||||
// ループ内モード: carrier変数iは片腕のみでもPHI候補に
|
||||
@ -296,18 +297,18 @@ mod tests {
|
||||
pre_if.insert("i".to_string(), ValueId(10));
|
||||
|
||||
let mut then_end = BTreeMap::new();
|
||||
then_end.insert("ch".to_string(), ValueId(5)); // ch は then のみ
|
||||
then_end.insert("ch".to_string(), ValueId(5)); // ch は then のみ
|
||||
then_end.insert("i".to_string(), ValueId(20));
|
||||
|
||||
let mut else_end = BTreeMap::new();
|
||||
else_end.insert("i".to_string(), ValueId(30)); // i は else にも
|
||||
else_end.insert("i".to_string(), ValueId(30)); // i は else にも
|
||||
|
||||
let candidates = IfBodyLocalMergeBox::compute_if_merge_phi_candidates(
|
||||
&pre_if,
|
||||
&then_end,
|
||||
&Some(else_end),
|
||||
&[BasicBlockId(1), BasicBlockId(2)],
|
||||
&loop_context(vec!["i"]), // i のみキャリア
|
||||
&loop_context(vec!["i"]), // i のみキャリア
|
||||
);
|
||||
|
||||
// i はキャリア → 候補に含まれる
|
||||
@ -329,7 +330,7 @@ mod tests {
|
||||
&then_end,
|
||||
&None,
|
||||
&[BasicBlockId(1)],
|
||||
&default_if_context(), // Phase 26-F-3: コンテキスト追加
|
||||
&default_if_context(), // Phase 26-F-3: コンテキスト追加
|
||||
);
|
||||
|
||||
// empty else → 何も絞らない
|
||||
|
||||
@ -201,10 +201,7 @@ impl ExitLivenessProvider for MirScanExitLiveness {
|
||||
header_vals: &BTreeMap<String, ValueId>,
|
||||
exit_snapshots: &[(BasicBlockId, BTreeMap<String, ValueId>)],
|
||||
) -> BTreeSet<String> {
|
||||
let trace = std::env::var("NYASH_EXIT_LIVENESS_TRACE")
|
||||
.ok()
|
||||
.as_deref()
|
||||
== Some("1");
|
||||
let trace = std::env::var("NYASH_EXIT_LIVENESS_TRACE").ok().as_deref() == Some("1");
|
||||
|
||||
// 対象ブロック集合(exit と break preds)
|
||||
let mut targets: BTreeSet<BasicBlockId> = BTreeSet::new();
|
||||
@ -325,13 +322,14 @@ mod tests {
|
||||
snap2.insert("i".to_string(), ValueId(50));
|
||||
snap2.insert("pname".to_string(), ValueId(60));
|
||||
|
||||
let exit_snapshots = vec![
|
||||
(BasicBlockId(100), snap1),
|
||||
(BasicBlockId(200), snap2),
|
||||
];
|
||||
let exit_snapshots = vec![(BasicBlockId(100), snap1), (BasicBlockId(200), snap2)];
|
||||
|
||||
let live_at_exit =
|
||||
liveness_box.compute_live_at_exit(&query, BasicBlockId(0), &header_vals, &exit_snapshots);
|
||||
let live_at_exit = liveness_box.compute_live_at_exit(
|
||||
&query,
|
||||
BasicBlockId(0),
|
||||
&header_vals,
|
||||
&exit_snapshots,
|
||||
);
|
||||
|
||||
// Phase 1: 空の live_at_exit(MIRスキャン実装待ち)
|
||||
assert_eq!(live_at_exit.len(), 0);
|
||||
@ -345,8 +343,12 @@ mod tests {
|
||||
let header_vals = BTreeMap::new();
|
||||
let exit_snapshots = vec![];
|
||||
|
||||
let live_at_exit =
|
||||
liveness_box.compute_live_at_exit(&query, BasicBlockId(0), &header_vals, &exit_snapshots);
|
||||
let live_at_exit = liveness_box.compute_live_at_exit(
|
||||
&query,
|
||||
BasicBlockId(0),
|
||||
&header_vals,
|
||||
&exit_snapshots,
|
||||
);
|
||||
|
||||
assert_eq!(live_at_exit.len(), 0);
|
||||
}
|
||||
@ -365,13 +367,14 @@ mod tests {
|
||||
let mut snap2 = BTreeMap::new();
|
||||
snap2.insert("i".to_string(), ValueId(30)); // 重複
|
||||
|
||||
let exit_snapshots = vec![
|
||||
(BasicBlockId(100), snap1),
|
||||
(BasicBlockId(200), snap2),
|
||||
];
|
||||
let exit_snapshots = vec![(BasicBlockId(100), snap1), (BasicBlockId(200), snap2)];
|
||||
|
||||
let live_at_exit =
|
||||
liveness_box.compute_live_at_exit(&query, BasicBlockId(0), &header_vals, &exit_snapshots);
|
||||
let live_at_exit = liveness_box.compute_live_at_exit(
|
||||
&query,
|
||||
BasicBlockId(0),
|
||||
&header_vals,
|
||||
&exit_snapshots,
|
||||
);
|
||||
|
||||
// Phase 1: 空の live_at_exit(MIRスキャン実装待ち)
|
||||
assert_eq!(live_at_exit.len(), 0);
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
|
||||
use crate::mir::{BasicBlockId, ValueId};
|
||||
use std::collections::BTreeMap; // Phase 25.1: 決定性確保
|
||||
// Phase 25.1: BTreeMap → BTreeMap(決定性確保・内部使用のみ)
|
||||
// Phase 25.1: BTreeMap → BTreeMap(決定性確保・内部使用のみ)
|
||||
|
||||
/// ループSnapshotの一元管理Box
|
||||
///
|
||||
@ -104,7 +104,8 @@ impl LoopSnapshotManager {
|
||||
// Phase 25.1: BTreeMap → BTreeMap(決定性確保・内部変換)
|
||||
pub fn add_exit_snapshot(&mut self, block: BasicBlockId, vars: BTreeMap<String, ValueId>) {
|
||||
// Convert BTreeMap to BTreeMap for deterministic iteration
|
||||
self.exit_snapshots.push((block, vars.into_iter().collect()));
|
||||
self.exit_snapshots
|
||||
.push((block, vars.into_iter().collect()));
|
||||
}
|
||||
|
||||
/// Add continue snapshot
|
||||
@ -120,7 +121,8 @@ impl LoopSnapshotManager {
|
||||
// Phase 25.1: BTreeMap → BTreeMap(決定性確保・内部変換)
|
||||
pub fn add_continue_snapshot(&mut self, block: BasicBlockId, vars: BTreeMap<String, ValueId>) {
|
||||
// Convert BTreeMap to BTreeMap for deterministic iteration
|
||||
self.continue_snapshots.push((block, vars.into_iter().collect()));
|
||||
self.continue_snapshots
|
||||
.push((block, vars.into_iter().collect()));
|
||||
}
|
||||
|
||||
/// Get preheader snapshot
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
|
||||
use crate::mir::{BasicBlockId, ValueId};
|
||||
use std::collections::{BTreeMap, BTreeSet}; // Phase 25.1: 決定性確保
|
||||
// Phase 25.1: BTreeMap → BTreeMap(決定性確保・内部使用のみ)
|
||||
// Phase 25.1: BTreeMap → BTreeMap(決定性確保・内部使用のみ)
|
||||
|
||||
// Option C PHI bug fix: Use box-based classification
|
||||
use super::local_scope_inspector::LocalScopeInspectorBox;
|
||||
|
||||
@ -332,7 +332,7 @@ impl LoopFormBuilder {
|
||||
latch_id: BasicBlockId,
|
||||
continue_snapshots: &[(BasicBlockId, BTreeMap<String, ValueId>)],
|
||||
_writes: &std::collections::HashSet<String>, // Step 5-1/5-2: Reserved for future optimization
|
||||
header_bypass: bool, // Phase 27.4C: Header φ バイパスフラグ
|
||||
header_bypass: bool, // Phase 27.4C: Header φ バイパスフラグ
|
||||
) -> Result<(), String> {
|
||||
let debug = std::env::var("NYASH_LOOPFORM_DEBUG").is_ok();
|
||||
|
||||
@ -442,8 +442,9 @@ impl LoopFormBuilder {
|
||||
continue;
|
||||
}
|
||||
|
||||
carrier.latch_value =
|
||||
ops.get_variable_at_block(&carrier.name, latch_id).ok_or_else(|| {
|
||||
carrier.latch_value = ops
|
||||
.get_variable_at_block(&carrier.name, latch_id)
|
||||
.ok_or_else(|| {
|
||||
format!(
|
||||
"carrier '{}' not found at latch {:?}",
|
||||
carrier.name, latch_id
|
||||
|
||||
@ -212,12 +212,8 @@ impl PhiBuilderBox {
|
||||
}
|
||||
|
||||
// Compute modified variables (決定的順序: BTreeSet使用)
|
||||
let modified_vars = self.compute_modified_names_if(
|
||||
pre_snapshot,
|
||||
then_end,
|
||||
&else_end_opt,
|
||||
if_shape,
|
||||
);
|
||||
let modified_vars =
|
||||
self.compute_modified_names_if(pre_snapshot, then_end, &else_end_opt, if_shape);
|
||||
|
||||
for var_name in modified_vars {
|
||||
// Conservative strategy: get values with void fallback
|
||||
@ -302,10 +298,14 @@ impl PhiBuilderBox {
|
||||
let else_end_owned = else_end_opt.map(|m| m.clone());
|
||||
|
||||
// Phase 26-F-3: IfPhiContextを取得(デフォルト: ループ外)
|
||||
let if_context = self.if_context.as_ref().cloned().unwrap_or_else(|| IfPhiContext {
|
||||
in_loop_body: false,
|
||||
loop_carrier_names: std::collections::BTreeSet::new(),
|
||||
});
|
||||
let if_context = self
|
||||
.if_context
|
||||
.as_ref()
|
||||
.cloned()
|
||||
.unwrap_or_else(|| IfPhiContext {
|
||||
in_loop_body: false,
|
||||
loop_carrier_names: std::collections::BTreeSet::new(),
|
||||
});
|
||||
|
||||
// Phase 26-F-2/F-3: IfBodyLocalMergeBoxでif-merge専用のφ候補決定
|
||||
let candidates = IfBodyLocalMergeBox::compute_if_merge_phi_candidates(
|
||||
@ -313,7 +313,7 @@ impl PhiBuilderBox {
|
||||
then_end,
|
||||
&else_end_owned,
|
||||
&reachable_preds,
|
||||
&if_context, // Phase 26-F-3: コンテキスト渡し
|
||||
&if_context, // Phase 26-F-3: コンテキスト渡し
|
||||
);
|
||||
|
||||
// Debug trace
|
||||
|
||||
Reference in New Issue
Block a user