feat(mir): Phase 69-3 Fix MIR non-determinism with BTreeSet
Replace HashSet with BTreeSet for CFG predecessors/successors: - BasicBlock.predecessors: HashSet → BTreeSet - BasicBlock.successors: HashSet → BTreeSet - LoopFormOps.get_block_predecessors(): returns BTreeSet - BasicBlock.dominates(): takes &[BTreeSet<BasicBlockId>] This ensures deterministic PHI generation and test stability. Test results: - loop_with_continue_and_break tests: now deterministic (3/3 same output) - loopform tests: 14/14 PASS (no regressions) - merge_exit_with_classification tests: 3/3 PASS Technical changes (6 files): - basic_block.rs: BTreeSet types + new() initialization - loopform_builder.rs: trait signature + 2 mock implementations - phi_ops.rs: return type - json_v0_bridge/loop_.rs: return type Same pattern as Phase 25.1 (MirFunction.blocks HashMap → BTreeMap). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -6,7 +6,7 @@
|
||||
|
||||
use super::{EffectMask, MirInstruction, SpannedInstRef, SpannedInstruction, ValueId};
|
||||
use crate::ast::Span;
|
||||
use std::collections::HashSet;
|
||||
use std::collections::BTreeSet; // Phase 69-3: HashSet → BTreeSet for determinism
|
||||
use std::fmt;
|
||||
|
||||
/// Unique identifier for basic blocks within a function
|
||||
@ -60,10 +60,12 @@ pub struct BasicBlock {
|
||||
pub terminator_span: Option<Span>,
|
||||
|
||||
/// Predecessors in the control flow graph
|
||||
pub predecessors: HashSet<BasicBlockId>,
|
||||
/// Phase 69-3: BTreeSet for deterministic iteration order
|
||||
pub predecessors: BTreeSet<BasicBlockId>,
|
||||
|
||||
/// Successors in the control flow graph
|
||||
pub successors: HashSet<BasicBlockId>,
|
||||
/// Phase 69-3: BTreeSet for deterministic iteration order
|
||||
pub successors: BTreeSet<BasicBlockId>,
|
||||
|
||||
/// Combined effect mask for all instructions in this block
|
||||
pub effects: EffectMask,
|
||||
@ -84,8 +86,8 @@ impl BasicBlock {
|
||||
instruction_spans: Vec::new(),
|
||||
terminator: None,
|
||||
terminator_span: None,
|
||||
predecessors: HashSet::new(),
|
||||
successors: HashSet::new(),
|
||||
predecessors: BTreeSet::new(), // Phase 69-3: BTreeSet for determinism
|
||||
successors: BTreeSet::new(), // Phase 69-3: BTreeSet for determinism
|
||||
effects: EffectMask::PURE,
|
||||
reachable: false,
|
||||
sealed: false,
|
||||
@ -387,7 +389,8 @@ impl BasicBlock {
|
||||
}
|
||||
|
||||
/// Check if this block dominates another block (simplified check)
|
||||
pub fn dominates(&self, other: BasicBlockId, dominators: &[HashSet<BasicBlockId>]) -> bool {
|
||||
/// Phase 69-3: Changed to BTreeSet for determinism
|
||||
pub fn dominates(&self, other: BasicBlockId, dominators: &[BTreeSet<BasicBlockId>]) -> bool {
|
||||
if let Some(dom_set) = dominators.get(other.to_usize()) {
|
||||
dom_set.contains(&self.id)
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user