refactor(joinir): Phase 222.5-E - Merge/Boundary HashMap → BTreeMap
Convert 10 medium-priority locations to BTreeMap for determinism: Merge System (6 locations): - instruction_rewriter.rs: value_to_func_name, function_params, function_entry_map, local_block_map - value_collector.rs: value_to_func_name, function_params, function_entry_map ID Remapper (2 locations): - joinir_id_remapper.rs: block_map, value_map Boundary Injector (2 locations): - joinir_inline_boundary_injector.rs: value_map (param & return) Impact: - Changed files: 4 - Changed lines: +36, -24 (net +12) - Tests: 849/856 PASS (no regression) - Determinism: Merge/Boundary processing now deterministic Combined with Phase 222.5-D (13 high-priority locations), JoinIR pipeline now uses BTreeMap uniformly across all critical paths (Pattern/Merge/Boundary/ValueId allocation). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@ -13,7 +13,7 @@ use crate::mir::join_ir::lowering::inline_boundary::JoinInlineBoundary;
|
|||||||
use super::loop_header_phi_info::LoopHeaderPhiInfo;
|
use super::loop_header_phi_info::LoopHeaderPhiInfo;
|
||||||
use super::tail_call_classifier::{TailCallKind, classify_tail_call};
|
use super::tail_call_classifier::{TailCallKind, classify_tail_call};
|
||||||
use super::merge_result::MergeResult;
|
use super::merge_result::MergeResult;
|
||||||
use std::collections::HashMap;
|
use std::collections::BTreeMap; // Phase 222.5-E: HashMap → BTreeMap for determinism
|
||||||
|
|
||||||
/// Phase 179-A: Exit continuation function name (MIR convention)
|
/// Phase 179-A: Exit continuation function name (MIR convention)
|
||||||
/// This is the standard name for k_exit continuations in JoinIR → MIR lowering
|
/// This is the standard name for k_exit continuations in JoinIR → MIR lowering
|
||||||
@ -44,8 +44,8 @@ pub(super) fn merge_and_rewrite(
|
|||||||
builder: &mut crate::mir::builder::MirBuilder,
|
builder: &mut crate::mir::builder::MirBuilder,
|
||||||
mir_module: &MirModule,
|
mir_module: &MirModule,
|
||||||
remapper: &mut JoinIrIdRemapper,
|
remapper: &mut JoinIrIdRemapper,
|
||||||
value_to_func_name: &HashMap<ValueId, String>,
|
value_to_func_name: &BTreeMap<ValueId, String>, // Phase 222.5-E: HashMap → BTreeMap for determinism
|
||||||
function_params: &HashMap<String, Vec<ValueId>>,
|
function_params: &BTreeMap<String, Vec<ValueId>>, // Phase 222.5-E: HashMap → BTreeMap for determinism
|
||||||
boundary: Option<&JoinInlineBoundary>,
|
boundary: Option<&JoinInlineBoundary>,
|
||||||
loop_header_phi_info: &mut LoopHeaderPhiInfo,
|
loop_header_phi_info: &mut LoopHeaderPhiInfo,
|
||||||
exit_block_id: BasicBlockId,
|
exit_block_id: BasicBlockId,
|
||||||
@ -68,7 +68,8 @@ pub(super) fn merge_and_rewrite(
|
|||||||
std::collections::BTreeMap::new();
|
std::collections::BTreeMap::new();
|
||||||
|
|
||||||
// Build function_entry_map for Call→Jump conversion
|
// Build function_entry_map for Call→Jump conversion
|
||||||
let mut function_entry_map: HashMap<String, BasicBlockId> = HashMap::new();
|
// Phase 222.5-E: HashMap → BTreeMap for determinism
|
||||||
|
let mut function_entry_map: BTreeMap<String, BasicBlockId> = BTreeMap::new();
|
||||||
for (func_name, func) in &mir_module.functions {
|
for (func_name, func) in &mir_module.functions {
|
||||||
let entry_block_new = remapper
|
let entry_block_new = remapper
|
||||||
.get_block(func_name, func.entry_block)
|
.get_block(func_name, func.entry_block)
|
||||||
@ -121,7 +122,8 @@ pub(super) fn merge_and_rewrite(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build a local block map for this function (for remap_instruction compatibility)
|
// Build a local block map for this function (for remap_instruction compatibility)
|
||||||
let mut local_block_map: HashMap<BasicBlockId, BasicBlockId> = HashMap::new();
|
// Phase 222.5-E: HashMap → BTreeMap for determinism
|
||||||
|
let mut local_block_map: BTreeMap<BasicBlockId, BasicBlockId> = BTreeMap::new();
|
||||||
for old_block_id in func.blocks.keys() {
|
for old_block_id in func.blocks.keys() {
|
||||||
let new_block_id = remapper
|
let new_block_id = remapper
|
||||||
.get_block(func_name, *old_block_id)
|
.get_block(func_name, *old_block_id)
|
||||||
@ -687,8 +689,9 @@ pub(super) fn merge_and_rewrite(
|
|||||||
.get_block(entry_func_name, entry_func.entry_block)
|
.get_block(entry_func_name, entry_func.entry_block)
|
||||||
.ok_or_else(|| format!("Entry block not found for {}", entry_func_name))?;
|
.ok_or_else(|| format!("Entry block not found for {}", entry_func_name))?;
|
||||||
|
|
||||||
// Create HashMap from remapper for BoundaryInjector (temporary adapter)
|
// Create BTreeMap from remapper for BoundaryInjector (temporary adapter)
|
||||||
let mut value_map_for_injector = HashMap::new();
|
// Phase 222.5-E: HashMap → BTreeMap for determinism
|
||||||
|
let mut value_map_for_injector = BTreeMap::new();
|
||||||
|
|
||||||
// Phase 171-fix: Add join_inputs to value_map
|
// Phase 171-fix: Add join_inputs to value_map
|
||||||
for join_in in &boundary.join_inputs {
|
for join_in in &boundary.join_inputs {
|
||||||
|
|||||||
@ -7,7 +7,8 @@
|
|||||||
|
|
||||||
use crate::mir::{MirInstruction, MirModule, ValueId};
|
use crate::mir::{MirInstruction, MirModule, ValueId};
|
||||||
use crate::mir::builder::joinir_id_remapper::JoinIrIdRemapper;
|
use crate::mir::builder::joinir_id_remapper::JoinIrIdRemapper;
|
||||||
use std::collections::{BTreeSet, HashMap};
|
use std::collections::BTreeSet; // Phase 222.5-E: HashMap → BTreeMap for determinism
|
||||||
|
use std::collections::BTreeMap; // Phase 222.5-E: HashMap → BTreeMap for determinism
|
||||||
|
|
||||||
/// Phase 2: Collect all ValueIds used across ALL functions (Phase 189)
|
/// Phase 2: Collect all ValueIds used across ALL functions (Phase 189)
|
||||||
///
|
///
|
||||||
@ -21,8 +22,8 @@ pub(super) fn collect_values(
|
|||||||
) -> Result<
|
) -> Result<
|
||||||
(
|
(
|
||||||
BTreeSet<ValueId>,
|
BTreeSet<ValueId>,
|
||||||
HashMap<ValueId, String>,
|
BTreeMap<ValueId, String>, // Phase 222.5-E: HashMap → BTreeMap for determinism
|
||||||
HashMap<String, Vec<ValueId>>,
|
BTreeMap<String, Vec<ValueId>>, // Phase 222.5-E: HashMap → BTreeMap for determinism
|
||||||
),
|
),
|
||||||
String,
|
String,
|
||||||
> {
|
> {
|
||||||
@ -33,11 +34,13 @@ pub(super) fn collect_values(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut used_values: BTreeSet<ValueId> = BTreeSet::new();
|
let mut used_values: BTreeSet<ValueId> = BTreeSet::new();
|
||||||
let mut value_to_func_name: HashMap<ValueId, String> = HashMap::new();
|
// Phase 222.5-E: HashMap → BTreeMap for determinism
|
||||||
let mut function_params: HashMap<String, Vec<ValueId>> = HashMap::new();
|
let mut value_to_func_name: BTreeMap<ValueId, String> = BTreeMap::new();
|
||||||
|
let mut function_params: BTreeMap<String, Vec<ValueId>> = BTreeMap::new();
|
||||||
|
|
||||||
// Build function_entry_map for tracking function names
|
// Build function_entry_map for tracking function names
|
||||||
let function_entry_map: HashMap<String, ()> = mir_module
|
// Phase 222.5-E: HashMap → BTreeMap for determinism
|
||||||
|
let function_entry_map: BTreeMap<String, ()> = mir_module
|
||||||
.functions
|
.functions
|
||||||
.keys()
|
.keys()
|
||||||
.map(|name| (name.clone(), ()))
|
.map(|name| (name.clone(), ()))
|
||||||
|
|||||||
@ -5,22 +5,25 @@
|
|||||||
//! - JoinIR fragment → host MIR への ID変換
|
//! - JoinIR fragment → host MIR への ID変換
|
||||||
//! - 決定性を重視した実装
|
//! - 決定性を重視した実装
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::BTreeMap; // Phase 222.5-E: HashMap → BTreeMap for determinism
|
||||||
use crate::mir::{BasicBlock, BasicBlockId, MirInstruction, ValueId};
|
use crate::mir::{BasicBlock, BasicBlockId, MirInstruction, ValueId};
|
||||||
|
|
||||||
/// JoinIR ID space を host MIR ID space に変換する
|
/// JoinIR ID space を host MIR ID space に変換する
|
||||||
pub struct JoinIrIdRemapper {
|
pub struct JoinIrIdRemapper {
|
||||||
/// (func_name, old_block_id) → new_block_id のマッピング
|
/// (func_name, old_block_id) → new_block_id のマッピング
|
||||||
block_map: HashMap<(String, BasicBlockId), BasicBlockId>,
|
/// Phase 222.5-E: HashMap → BTreeMap for determinism
|
||||||
|
block_map: BTreeMap<(String, BasicBlockId), BasicBlockId>,
|
||||||
/// old_value_id → new_value_id のマッピング
|
/// old_value_id → new_value_id のマッピング
|
||||||
value_map: HashMap<ValueId, ValueId>,
|
/// Phase 222.5-E: HashMap → BTreeMap for determinism
|
||||||
|
value_map: BTreeMap<ValueId, ValueId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl JoinIrIdRemapper {
|
impl JoinIrIdRemapper {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
block_map: HashMap::new(),
|
// Phase 222.5-E: HashMap → BTreeMap for determinism
|
||||||
value_map: HashMap::new(),
|
block_map: BTreeMap::new(),
|
||||||
|
value_map: BTreeMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
//! - Entry block への Copy instruction 挿入
|
//! - Entry block への Copy instruction 挿入
|
||||||
//! - SSA 値空間の接続
|
//! - SSA 値空間の接続
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::BTreeMap; // Phase 222.5-E: HashMap → BTreeMap for determinism
|
||||||
use crate::mir::{BasicBlockId, MirFunction, MirInstruction, ValueId};
|
use crate::mir::{BasicBlockId, MirFunction, MirInstruction, ValueId};
|
||||||
use crate::mir::join_ir::lowering::inline_boundary::JoinInlineBoundary;
|
use crate::mir::join_ir::lowering::inline_boundary::JoinInlineBoundary;
|
||||||
|
|
||||||
@ -49,16 +49,17 @@ impl BoundaryInjector {
|
|||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
///
|
///
|
||||||
/// Returns a HashMap mapping original ValueIds to their reallocated ValueIds
|
/// Returns a BTreeMap mapping original ValueIds to their reallocated ValueIds
|
||||||
/// (only for condition_bindings that had collisions).
|
/// (only for condition_bindings that had collisions).
|
||||||
|
/// Phase 222.5-E: HashMap → BTreeMap for determinism
|
||||||
pub fn inject_boundary_copies(
|
pub fn inject_boundary_copies(
|
||||||
func: &mut MirFunction,
|
func: &mut MirFunction,
|
||||||
entry_block_id: BasicBlockId,
|
entry_block_id: BasicBlockId,
|
||||||
boundary: &JoinInlineBoundary,
|
boundary: &JoinInlineBoundary,
|
||||||
value_map: &HashMap<ValueId, ValueId>,
|
value_map: &BTreeMap<ValueId, ValueId>, // Phase 222.5-E: HashMap → BTreeMap for determinism
|
||||||
phi_dst_ids: &std::collections::HashSet<ValueId>,
|
phi_dst_ids: &std::collections::HashSet<ValueId>,
|
||||||
debug: bool,
|
debug: bool,
|
||||||
) -> Result<HashMap<ValueId, ValueId>, String> {
|
) -> Result<BTreeMap<ValueId, ValueId>, String> { // Phase 222.5-E: HashMap → BTreeMap for determinism
|
||||||
// Phase 33-20: When loop_var_name is set, ALL join_inputs are handled by header PHIs
|
// Phase 33-20: When loop_var_name is set, ALL join_inputs are handled by header PHIs
|
||||||
// This includes the loop variable AND all other carriers from exit_bindings.
|
// This includes the loop variable AND all other carriers from exit_bindings.
|
||||||
// We skip ALL join_inputs Copy instructions, only condition_bindings remain.
|
// We skip ALL join_inputs Copy instructions, only condition_bindings remain.
|
||||||
@ -73,7 +74,8 @@ impl BoundaryInjector {
|
|||||||
let total_inputs = effective_join_inputs + boundary.condition_bindings.len();
|
let total_inputs = effective_join_inputs + boundary.condition_bindings.len();
|
||||||
if total_inputs == 0 {
|
if total_inputs == 0 {
|
||||||
// No inputs to process, return empty reallocations map
|
// No inputs to process, return empty reallocations map
|
||||||
return Ok(HashMap::new());
|
// Phase 222.5-E: HashMap → BTreeMap for determinism
|
||||||
|
return Ok(BTreeMap::new());
|
||||||
}
|
}
|
||||||
|
|
||||||
if debug {
|
if debug {
|
||||||
@ -98,7 +100,8 @@ impl BoundaryInjector {
|
|||||||
|
|
||||||
// Phase 177-3 Option B: First pass - allocate all new ValueIds for PHI collisions
|
// Phase 177-3 Option B: First pass - allocate all new ValueIds for PHI collisions
|
||||||
// We need to do this BEFORE acquiring the entry_block reference to avoid borrow conflicts
|
// We need to do this BEFORE acquiring the entry_block reference to avoid borrow conflicts
|
||||||
let mut reallocations = HashMap::new();
|
// Phase 222.5-E: HashMap → BTreeMap for determinism
|
||||||
|
let mut reallocations = BTreeMap::new();
|
||||||
|
|
||||||
for binding in &boundary.condition_bindings {
|
for binding in &boundary.condition_bindings {
|
||||||
let remapped_join = value_map.get(&binding.join_value).copied().unwrap_or(binding.join_value);
|
let remapped_join = value_map.get(&binding.join_value).copied().unwrap_or(binding.join_value);
|
||||||
|
|||||||
Reference in New Issue
Block a user