phase29af(p2+p3): regression entrypoint + carrier layout ssot

This commit is contained in:
2025-12-29 05:44:59 +09:00
parent 9bc9454726
commit bd4937d89d
11 changed files with 168 additions and 43 deletions

View File

@ -0,0 +1,48 @@
use crate::mir::join_ir::lowering::inline_boundary::JoinInlineBoundary;
/// Phase 29af P3: Boundary carrier layout SSOT (order only).
///
/// Order rule:
/// - loop_var (if any) first
/// - then carriers (from carrier_info if present, otherwise exit_bindings order)
#[derive(Debug, Clone)]
pub struct BoundaryCarrierLayout {
ordered_names: Vec<String>,
}
impl BoundaryCarrierLayout {
pub fn from_boundary(boundary: &JoinInlineBoundary) -> Self {
let mut ordered_names = Vec::new();
if let Some(loop_var) = boundary.loop_var_name.as_deref() {
ordered_names.push(loop_var.to_string());
}
if let Some(ref carrier_info) = boundary.carrier_info {
for carrier in carrier_info.carriers.iter() {
ordered_names.push(carrier.name.clone());
}
} else {
for binding in boundary.exit_bindings.iter() {
if boundary.loop_var_name.as_deref() == Some(binding.carrier_name.as_str()) {
continue;
}
ordered_names.push(binding.carrier_name.clone());
}
}
Self { ordered_names }
}
pub fn ordered_names(&self) -> Vec<&str> {
self.ordered_names.iter().map(|name| name.as_str()).collect()
}
pub fn ordered_arg_index(&self, name: &str) -> Option<usize> {
self.ordered_names.iter().position(|n| n == name)
}
pub fn len(&self) -> usize {
self.ordered_names.len()
}
}

View File

@ -1,4 +1,5 @@
use crate::mir::join_ir::lowering::inline_boundary::JoinInlineBoundary;
use crate::mir::builder::control_flow::joinir::merge::boundary_carrier_layout::BoundaryCarrierLayout;
use crate::mir::ValueId;
use std::collections::BTreeSet;
@ -37,6 +38,20 @@ pub(in crate::mir::builder::control_flow::joinir::merge) fn verify_boundary_hygi
}
if let Some(carrier_info) = &boundary.carrier_info {
let expected_len =
carrier_info.carriers.len() + if boundary.loop_var_name.is_some() { 1 } else { 0 };
let layout_len = BoundaryCarrierLayout::from_boundary(boundary).len();
if expected_len != layout_len {
return Err(error_tags::freeze_with_hint(
"phase29af/boundary_hygiene/layout_len",
&format!(
"boundary carrier layout len {} does not match carrier_info len {}",
layout_len, expected_len
),
"ensure loop_var + carriers ordering is consistent with carrier_info",
));
}
let mut carrier_names = BTreeSet::new();
carrier_names.insert(carrier_info.loop_var_name.clone());

View File

@ -14,6 +14,7 @@
mod block_allocator;
mod block_remapper; // Phase 284 P1: Block ID remap SSOT
mod boundary_carrier_layout; // Phase 29af P3: Carrier order SSOT
mod boundary_logging; // Phase 287 P0.5: Boundary logging consolidation
mod carrier_init_builder;
mod config;

View File

@ -8,6 +8,7 @@
use crate::mir::builder::control_flow::joinir::merge::loop_header_phi_info::LoopHeaderPhiInfo;
use crate::mir::builder::control_flow::joinir::merge::tail_call_classifier::TailCallKind;
use crate::mir::builder::control_flow::joinir::merge::boundary_carrier_layout::BoundaryCarrierLayout;
use crate::mir::join_ir::lowering::inline_boundary::JoinInlineBoundary;
use crate::mir::{BasicBlockId, ValueId};
use crate::mir::builder::control_flow::joinir::merge::dev_log;
@ -34,6 +35,9 @@ pub(in crate::mir::builder::control_flow::joinir::merge) fn record_if_backedge(
return;
}
let layout = BoundaryCarrierLayout::from_boundary(boundary);
let ordered_carriers = layout.ordered_names();
if let Some(loop_var_name) = &boundary.loop_var_name {
debug_assert!(
!args.is_empty(),
@ -55,35 +59,20 @@ pub(in crate::mir::builder::control_flow::joinir::merge) fn record_if_backedge(
}
}
}
if let Some(&latch_value) = args.first() {
loop_header_phi_info.set_latch_incoming(loop_var_name, new_block_id, latch_value);
if let Some(idx) = layout.ordered_arg_index(loop_var_name) {
if let Some(&latch_value) = args.get(idx) {
loop_header_phi_info.set_latch_incoming(loop_var_name, new_block_id, latch_value);
}
}
}
// Other carriers (excluding loop_var)
let mut carrier_arg_idx = if boundary.loop_var_name.is_some() { 1 } else { 0 };
if let Some(ref carrier_info) = boundary.carrier_info {
for carrier in carrier_info.carriers.iter() {
if boundary.loop_var_name.as_deref() == Some(carrier.name.as_str()) {
continue;
}
if let Some(&latch_value) = args.get(carrier_arg_idx) {
loop_header_phi_info.set_latch_incoming(&carrier.name, new_block_id, latch_value);
carrier_arg_idx += 1;
}
for (idx, carrier_name) in ordered_carriers.iter().enumerate() {
if boundary.loop_var_name.as_deref() == Some(*carrier_name) {
continue;
}
} else {
for binding in boundary.exit_bindings.iter() {
if let Some(ref loop_var) = boundary.loop_var_name {
if &binding.carrier_name == loop_var {
continue;
}
}
if let Some(&latch_value) = args.get(carrier_arg_idx) {
loop_header_phi_info.set_latch_incoming(&binding.carrier_name, new_block_id, latch_value);
carrier_arg_idx += 1;
}
if let Some(&latch_value) = args.get(idx) {
loop_header_phi_info.set_latch_incoming(carrier_name, new_block_id, latch_value);
}
}

View File

@ -5,6 +5,7 @@
//! - Record latch incoming in one place for BackEdge
use crate::mir::builder::control_flow::joinir::merge::contract_checks::is_entry_like_source;
use crate::mir::builder::control_flow::joinir::merge::boundary_carrier_layout::BoundaryCarrierLayout;
use crate::mir::builder::control_flow::joinir::merge::loop_header_phi_info::LoopHeaderPhiInfo;
use crate::mir::builder::control_flow::joinir::merge::rewriter::latch_incoming_recorder;
use crate::mir::builder::control_flow::joinir::merge::tail_call_classifier::TailCallKind;
@ -38,29 +39,17 @@ pub(super) fn record_latch_incoming_if_backedge(
let mut latch_args: Vec<ValueId> = Vec::new();
let mut loop_var_updated = false;
let mut ordered_carriers: Vec<&str> = Vec::new();
let mut other_phi_dsts: std::collections::BTreeSet<ValueId> =
std::collections::BTreeSet::new();
if let Some(loop_var) = boundary.loop_var_name.as_deref() {
ordered_carriers.push(loop_var);
for (name, entry) in loop_header_phi_info.carrier_phis.iter() {
if name.as_str() != loop_var {
other_phi_dsts.insert(entry.phi_dst);
}
}
}
if let Some(ref carrier_info) = boundary.carrier_info {
for carrier in carrier_info.carriers.iter() {
ordered_carriers.push(carrier.name.as_str());
}
} else {
for binding in boundary.exit_bindings.iter() {
if boundary.loop_var_name.as_deref() == Some(binding.carrier_name.as_str()) {
continue;
}
ordered_carriers.push(binding.carrier_name.as_str());
}
}
let layout = BoundaryCarrierLayout::from_boundary(boundary);
let ordered_carriers = layout.ordered_names();
for (idx, carrier_name) in ordered_carriers.iter().enumerate() {
let phi_dst = match loop_header_phi_info.get_carrier_phi(carrier_name) {