phase29aa(p7): deterministic ReleaseStrong values ordering

This commit is contained in:
2025-12-28 05:59:22 +09:00
parent ec1a84c465
commit d3cf73f2ae
4 changed files with 66 additions and 13 deletions

View File

@ -527,5 +527,52 @@ fn main() {
"branch_no_cleanup",
);
// Case 3.11: ReleaseStrong values are sorted (deterministic ordering)
// P7: 複数 ptr に異なる順序で store し、ReturnCleanup の values が昇順になることを検証
let ptr1 = ValueId::new(3111);
let ptr2 = ValueId::new(3112);
let v_high = ValueId::new(100); // 大きい index
let v_low = ValueId::new(50); // 小さい index
let mut block = BasicBlock::new(BasicBlockId::new(0));
block.instructions = vec![
MirInstruction::Store { value: v_high, ptr: ptr1 }, // 先に v100 を store
MirInstruction::Store { value: v_low, ptr: ptr2 }, // 後に v50 を store
];
block.instruction_spans = vec![Span::unknown(), Span::unknown()];
block.terminator = Some(MirInstruction::Return { value: None });
block.terminator_span = Some(Span::unknown());
let entry = block.id;
let module = build_module_with_block(block, "selfcheck_sorted_values", "selfcheck_mod3p11");
// 関数全体の ReleaseStrong が昇順であることを検証
assert_release_inserted(module.clone(), "selfcheck_sorted_values", entry, 1, "sorted_values_count");
assert_all_release_values_sorted(module, "selfcheck_sorted_values", "sorted_values_order");
println!("[PASS] rc_insertion_selfcheck");
}
fn assert_all_release_values_sorted(
mut module: MirModule,
func_name: &str,
label: &str,
) {
let _stats = insert_rc_instructions(&mut module);
let func = module.get_function(func_name).expect("function exists");
for (bid, bb) in &func.blocks {
for inst in &bb.instructions {
if let MirInstruction::ReleaseStrong { values } = inst {
for window in values.windows(2) {
if window[0] > window[1] {
eprintln!(
"[FAIL] {}: block {:?} values not sorted: {:?} > {:?}",
label, bid, window[0], window[1]
);
std::process::exit(1);
}
}
}
}
}
}

View File

@ -429,13 +429,8 @@ fn plan_rc_insertion_for_block(
}
if matches!(terminator, Some(MirInstruction::Return { .. })) && !ptr_to_value.is_empty() {
let release_values: Vec<ValueId> = {
let mut set = HashSet::new();
for v in ptr_to_value.values() {
set.insert(*v);
}
set.into_iter().collect()
};
// P7: HashSet 削除、sort+dedup は apply 側のヘルパーで処理される
let release_values: Vec<ValueId> = ptr_to_value.values().copied().collect();
if !release_values.is_empty() {
plan.drops.push(DropSite {
at: DropPoint::BeforeTerminator,
@ -448,6 +443,14 @@ fn plan_rc_insertion_for_block(
(plan, ptr_to_value)
}
/// P7: ReleaseStrong の values を決定的順序ValueId 昇順)にする
#[cfg(feature = "rc-insertion-minimal")]
fn sorted_release_values(mut values: Vec<ValueId>) -> Vec<ValueId> {
values.sort_unstable();
values.dedup();
values
}
#[cfg(feature = "rc-insertion-minimal")]
fn apply_rc_plan(
insts: Vec<MirInstruction>,
@ -490,7 +493,7 @@ fn apply_rc_plan(
for drop_site in drops_before_instr[idx].drain(..) {
let _ = drop_site.reason;
new_insts.push(MirInstruction::ReleaseStrong {
values: drop_site.values,
values: sorted_release_values(drop_site.values),
});
new_spans.push(span.clone());
stats.release_inserted += 1;
@ -510,7 +513,7 @@ fn apply_rc_plan(
for drop_site in drops_before_terminator {
let _ = drop_site.reason;
new_insts.push(MirInstruction::ReleaseStrong {
values: drop_site.values,
values: sorted_release_values(drop_site.values),
});
new_spans.push(span.clone());
stats.release_inserted += 1;