chore: Phase 25.1 完了 - LoopForm v2/Stage1 CLI/環境変数削減 + Phase 26-D からの変更
Phase 25.1 完了成果: - ✅ LoopForm v2 テスト・ドキュメント・コメント完備 - 4ケース(A/B/C/D)完全テストカバレッジ - 最小再現ケース作成(SSAバグ調査用) - SSOT文書作成(loopform_ssot.md) - 全ソースに [LoopForm] コメントタグ追加 - ✅ Stage-1 CLI デバッグ環境構築 - stage1_cli.hako 実装 - stage1_bridge.rs ブリッジ実装 - デバッグツール作成(stage1_debug.sh/stage1_minimal.sh) - アーキテクチャ改善提案文書 - ✅ 環境変数削減計画策定 - 25変数の完全調査・分類 - 6段階削減ロードマップ(25→5、80%削減) - 即時削除可能変数特定(NYASH_CONFIG/NYASH_DEBUG) Phase 26-D からの累積変更: - PHI実装改善(ExitPhiBuilder/HeaderPhiBuilder等) - MIRビルダーリファクタリング - 型伝播・最適化パス改善 - その他約300ファイルの累積変更 🎯 技術的成果: - SSAバグ根本原因特定(条件分岐内loop変数変更) - Region+next_iパターン適用完了(UsingCollectorBox等) - LoopFormパターン文書化・テスト化完了 - セルフホスティング基盤強化 Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: ChatGPT <noreply@openai.com> Co-Authored-By: Task Assistant <task@anthropic.com>
This commit is contained in:
@ -31,28 +31,38 @@ impl MirBuilder {
|
||||
let changed_set: HashSet<String> = conservative.changed_vars.iter().cloned().collect();
|
||||
|
||||
// Use PhiMergeHelper for unified variable merging
|
||||
let mut helper = super::phi_merge::PhiMergeHelper::new(
|
||||
self,
|
||||
then_exit_block_opt,
|
||||
else_exit_block_opt,
|
||||
);
|
||||
let mut helper =
|
||||
super::phi_merge::PhiMergeHelper::new(self, then_exit_block_opt, else_exit_block_opt);
|
||||
helper.merge_all_vars(pre_if_snapshot, then_map_end, else_map_end_opt, skip_var)?;
|
||||
|
||||
// Ensure pinned synthetic slots ("__pin$...") have a block-local definition at the merge,
|
||||
// even if their values did not change across branches. This avoids undefined uses when
|
||||
// subsequent blocks re-use pinned values without modifications.
|
||||
for (pin_name, pre_val) in pre_if_snapshot.iter() {
|
||||
if !pin_name.starts_with("__pin$") { continue; }
|
||||
if skip_var.map(|s| s == pin_name.as_str()).unwrap_or(false) { continue; }
|
||||
if changed_set.contains(pin_name) { continue; }
|
||||
let then_v = then_map_end.get(pin_name.as_str()).copied().unwrap_or(*pre_val);
|
||||
if !pin_name.starts_with("__pin$") {
|
||||
continue;
|
||||
}
|
||||
if skip_var.map(|s| s == pin_name.as_str()).unwrap_or(false) {
|
||||
continue;
|
||||
}
|
||||
if changed_set.contains(pin_name) {
|
||||
continue;
|
||||
}
|
||||
let then_v = then_map_end
|
||||
.get(pin_name.as_str())
|
||||
.copied()
|
||||
.unwrap_or(*pre_val);
|
||||
let else_v = else_map_end_opt
|
||||
.as_ref()
|
||||
.and_then(|m| m.get(pin_name.as_str()).copied())
|
||||
.unwrap_or(*pre_val);
|
||||
let mut inputs: Vec<(super::BasicBlockId, super::ValueId)> = Vec::new();
|
||||
if let Some(tp) = then_exit_block_opt { inputs.push((tp, then_v)); }
|
||||
if let Some(ep) = else_exit_block_opt { inputs.push((ep, else_v)); }
|
||||
if let Some(tp) = then_exit_block_opt {
|
||||
inputs.push((tp, then_v));
|
||||
}
|
||||
if let Some(ep) = else_exit_block_opt {
|
||||
inputs.push((ep, else_v));
|
||||
}
|
||||
match inputs.len() {
|
||||
0 => {}
|
||||
1 => {
|
||||
@ -60,15 +70,27 @@ impl MirBuilder {
|
||||
self.variable_map.insert(pin_name.clone(), v);
|
||||
}
|
||||
_ => {
|
||||
if let Some(func) = self.current_function.as_mut() { func.update_cfg(); }
|
||||
if let (Some(func), Some(cur_bb)) = (&self.current_function, self.current_block) {
|
||||
crate::mir::phi_core::common::debug_verify_phi_inputs(func, cur_bb, &inputs);
|
||||
if let Some(func) = self.current_function.as_mut() {
|
||||
func.update_cfg();
|
||||
}
|
||||
if let (Some(func), Some(cur_bb)) = (&self.current_function, self.current_block)
|
||||
{
|
||||
crate::mir::phi_core::common::debug_verify_phi_inputs(
|
||||
func, cur_bb, &inputs,
|
||||
);
|
||||
}
|
||||
let merged = self.next_value_id();
|
||||
if let (Some(func), Some(cur_bb)) = (self.current_function.as_mut(), self.current_block) {
|
||||
crate::mir::ssot::cf_common::insert_phi_at_head(func, cur_bb, merged, inputs);
|
||||
if let (Some(func), Some(cur_bb)) =
|
||||
(self.current_function.as_mut(), self.current_block)
|
||||
{
|
||||
crate::mir::ssot::cf_common::insert_phi_at_head(
|
||||
func, cur_bb, merged, inputs,
|
||||
);
|
||||
} else {
|
||||
self.emit_instruction(MirInstruction::Phi { dst: merged, inputs })?;
|
||||
self.emit_instruction(MirInstruction::Phi {
|
||||
dst: merged,
|
||||
inputs,
|
||||
})?;
|
||||
}
|
||||
self.variable_map.insert(pin_name.clone(), merged);
|
||||
}
|
||||
@ -95,7 +117,8 @@ impl MirBuilder {
|
||||
) -> Result<ValueId, String> {
|
||||
// If only the then-branch assigns a variable (e.g., `if c { x = ... }`) and the else
|
||||
// does not assign the same variable, bind that variable to a Phi of (then_value, pre_if_value).
|
||||
let assigned_var_then = crate::mir::phi_core::if_phi::extract_assigned_var(then_ast_for_analysis);
|
||||
let assigned_var_then =
|
||||
crate::mir::phi_core::if_phi::extract_assigned_var(then_ast_for_analysis);
|
||||
let assigned_var_else = else_ast_for_analysis
|
||||
.as_ref()
|
||||
.and_then(|a| crate::mir::phi_core::if_phi::extract_assigned_var(a));
|
||||
@ -131,8 +154,12 @@ impl MirBuilder {
|
||||
};
|
||||
// Build inputs from reachable predecessors only
|
||||
let mut inputs: Vec<(BasicBlockId, ValueId)> = Vec::new();
|
||||
if let Some(tp) = then_exit_block_opt { inputs.push((tp, then_value_for_var)); }
|
||||
if let Some(ep) = else_exit_block_opt { inputs.push((ep, else_value_for_var)); }
|
||||
if let Some(tp) = then_exit_block_opt {
|
||||
inputs.push((tp, then_value_for_var));
|
||||
}
|
||||
if let Some(ep) = else_exit_block_opt {
|
||||
inputs.push((ep, else_value_for_var));
|
||||
}
|
||||
match inputs.len() {
|
||||
0 => {}
|
||||
1 => {
|
||||
@ -142,9 +169,14 @@ impl MirBuilder {
|
||||
return Ok(inputs[0].1);
|
||||
}
|
||||
_ => {
|
||||
if let Some(func) = self.current_function.as_mut() { func.update_cfg(); }
|
||||
if let (Some(func), Some(cur_bb)) = (&self.current_function, self.current_block) {
|
||||
crate::mir::phi_core::common::debug_verify_phi_inputs(func, cur_bb, &inputs);
|
||||
if let Some(func) = self.current_function.as_mut() {
|
||||
func.update_cfg();
|
||||
}
|
||||
if let (Some(func), Some(cur_bb)) = (&self.current_function, self.current_block)
|
||||
{
|
||||
crate::mir::phi_core::common::debug_verify_phi_inputs(
|
||||
func, cur_bb, &inputs,
|
||||
);
|
||||
}
|
||||
self.insert_phi_with_dst(result_val, inputs)?;
|
||||
}
|
||||
@ -154,10 +186,15 @@ impl MirBuilder {
|
||||
} else {
|
||||
// No variable assignment pattern detected – just emit Phi for expression result
|
||||
let mut inputs: Vec<(BasicBlockId, ValueId)> = Vec::new();
|
||||
if let Some(tp) = then_exit_block_opt { inputs.push((tp, then_value_raw)); }
|
||||
if let Some(ep) = else_exit_block_opt { inputs.push((ep, else_value_raw)); }
|
||||
if let Some(tp) = then_exit_block_opt {
|
||||
inputs.push((tp, then_value_raw));
|
||||
}
|
||||
if let Some(ep) = else_exit_block_opt {
|
||||
inputs.push((ep, else_value_raw));
|
||||
}
|
||||
match inputs.len() {
|
||||
0 => { /* leave result_val as fresh, but unused; synthesize void */
|
||||
0 => {
|
||||
/* leave result_val as fresh, but unused; synthesize void */
|
||||
let v = crate::mir::builder::emission::constant::emit_void(self);
|
||||
return Ok(v);
|
||||
}
|
||||
@ -165,9 +202,14 @@ impl MirBuilder {
|
||||
return Ok(inputs[0].1);
|
||||
}
|
||||
_ => {
|
||||
if let Some(func) = self.current_function.as_mut() { func.update_cfg(); }
|
||||
if let (Some(func), Some(cur_bb)) = (&self.current_function, self.current_block) {
|
||||
crate::mir::phi_core::common::debug_verify_phi_inputs(func, cur_bb, &inputs);
|
||||
if let Some(func) = self.current_function.as_mut() {
|
||||
func.update_cfg();
|
||||
}
|
||||
if let (Some(func), Some(cur_bb)) = (&self.current_function, self.current_block)
|
||||
{
|
||||
crate::mir::phi_core::common::debug_verify_phi_inputs(
|
||||
func, cur_bb, &inputs,
|
||||
);
|
||||
}
|
||||
self.insert_phi_with_dst(result_val, inputs)?;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user