phase29aa(p5): multi-pred return join when states match

This commit is contained in:
2025-12-28 04:43:19 +09:00
parent ca91be349d
commit 02c01758b3
4 changed files with 184 additions and 5 deletions

View File

@ -280,6 +280,101 @@ fn main() {
"jump_chain_single_pred",
);
// Case 3.7: Multi-predecessor Return with MATCHING states
// P5: すべての incoming end_state が完全一致する場合のみ ReturnCleanup を成立させる
let ptr = ValueId::new(370);
let v_shared = ValueId::new(23); // 同じValueIdを両predecessorで使用
let mut block_a = BasicBlock::new(BasicBlockId::new(0));
block_a.instructions = vec![MirInstruction::Store { value: v_shared, ptr }];
block_a.instruction_spans = vec![Span::unknown()];
block_a.terminator = Some(MirInstruction::Jump {
target: BasicBlockId::new(2),
edge_args: None,
});
block_a.terminator_span = Some(Span::unknown());
let mut block_b = BasicBlock::new(BasicBlockId::new(1));
block_b.instructions = vec![MirInstruction::Store { value: v_shared, ptr }];
block_b.instruction_spans = vec![Span::unknown()];
block_b.terminator = Some(MirInstruction::Jump {
target: BasicBlockId::new(2),
edge_args: None,
});
block_b.terminator_span = Some(Span::unknown());
let mut block_ret = BasicBlock::new(BasicBlockId::new(2));
block_ret.instructions = vec![];
block_ret.instruction_spans = vec![];
block_ret.terminator = Some(MirInstruction::Return { value: None });
block_ret.terminator_span = Some(Span::unknown());
let module = build_module_with_blocks(
vec![block_a, block_b, block_ret],
BasicBlockId::new(0),
"selfcheck_multi_pred_return_match",
"selfcheck_mod3p7",
);
assert_release_counts_in_blocks(
module,
"selfcheck_multi_pred_return_match",
1, // 全体で1Return blockのみ
&[
(BasicBlockId::new(0), 0), // Jump block: cleanup禁止
(BasicBlockId::new(1), 0), // Jump block: cleanup禁止
(BasicBlockId::new(2), 1), // Return block: multi-pred join成功
],
"multi_pred_return_match",
);
// Case 3.8: Multi-predecessor Return with MISMATCHING states (negative test)
// P5: state不一致 → join state を作らない → ReturnCleanup なし
let ptr = ValueId::new(380);
let v1 = ValueId::new(24);
let v2 = ValueId::new(25); // 異なるValueId → state不一致
let mut block_a = BasicBlock::new(BasicBlockId::new(0));
block_a.instructions = vec![MirInstruction::Store { value: v1, ptr }];
block_a.instruction_spans = vec![Span::unknown()];
block_a.terminator = Some(MirInstruction::Jump {
target: BasicBlockId::new(2),
edge_args: None,
});
block_a.terminator_span = Some(Span::unknown());
let mut block_b = BasicBlock::new(BasicBlockId::new(1));
block_b.instructions = vec![MirInstruction::Store { value: v2, ptr }]; // v2 != v1 → 不一致
block_b.instruction_spans = vec![Span::unknown()];
block_b.terminator = Some(MirInstruction::Jump {
target: BasicBlockId::new(2),
edge_args: None,
});
block_b.terminator_span = Some(Span::unknown());
let mut block_ret = BasicBlock::new(BasicBlockId::new(2));
block_ret.instructions = vec![];
block_ret.instruction_spans = vec![];
block_ret.terminator = Some(MirInstruction::Return { value: None });
block_ret.terminator_span = Some(Span::unknown());
let module = build_module_with_blocks(
vec![block_a, block_b, block_ret],
BasicBlockId::new(0),
"selfcheck_multi_pred_return_mismatch",
"selfcheck_mod3p8",
);
assert_release_counts_in_blocks(
module,
"selfcheck_multi_pred_return_mismatch",
0, // 全体で0join stateを作らないのでcleanupなし
&[
(BasicBlockId::new(0), 0), // Jump block: cleanup禁止
(BasicBlockId::new(1), 0), // Jump block: cleanup禁止
(BasicBlockId::new(2), 0), // Return block: state不一致 → join失敗
],
"multi_pred_return_mismatch",
);
// Case 4: Jump terminator should NOT inject block-end cleanup (unsafe cross-block)
let ptr = ValueId::new(400);
let v1 = ValueId::new(30);