feat(phi): __pin$変数の完全除外でValueId(313)→(300)に改善!
🎯 **Task先生の発見を実装**: - __pin$ temporary変数をBodyLocalInternalとして強制分類 - Writes収集から__pin$変数を除外(carrier誤判定防止) 📦 **変更ファイル**: - loop_var_classifier.rs: Priority 0で__pin$変数を自動BodyLocalInternal分類 - loop_builder.rs: Writes収集で__pin$除外 - loop_.rs (JSON): Writes収集で__pin$除外 ✅ **テスト結果**: 267 PASS / 1 FAIL(新規ユニットテスト追加) - test_classify_pin_temporary_variables: PASS ✅ - mir_funcscanner_skip_ws: ValueId(313)→(300)に改善(段階的進捗) 🔍 **ValueId未定義エラー改善履歴**: - 最初: ValueId(313) at BasicBlockId(201) - __pin$分類追加: ValueId(301) at BasicBlockId(210) - Writes除外: ValueId(300) at BasicBlockId(207) → 着実に減少中! 📋 **完了ステップ**: ✅ Step 5-1: Writes集合収集(__pin$除外追加) ✅ Step 5-2: ValueId比較ロジック ✅ Step 5-4: φ縮約実装 ✅ Step 5-5-A: PHI pred mismatch解決 ✅ Step 5-5-B-partial: __pin$変数問題部分解決 🎯 **次のステップ**: ValueId(300)根本原因特定(Continue merge PHI実装検討)
This commit is contained in:
@ -340,6 +340,12 @@ impl<'a> LoopBuilder<'a> {
|
|||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
let mut writes = HashSet::new();
|
let mut writes = HashSet::new();
|
||||||
for (name, &body_value) in &body_end_vars {
|
for (name, &body_value) in &body_end_vars {
|
||||||
|
// Skip __pin$ temporary variables - they are always BodyLocalInternal
|
||||||
|
// (Task先生の発見: これらをcarrier扱いすると未定義ValueIdエラーの原因になる)
|
||||||
|
if name.starts_with("__pin$") && name.contains("$@") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(&base_value) = current_vars.get(name) {
|
if let Some(&base_value) = current_vars.get(name) {
|
||||||
if body_value != base_value {
|
if body_value != base_value {
|
||||||
writes.insert(name.clone());
|
writes.insert(name.clone());
|
||||||
|
|||||||
@ -174,6 +174,14 @@ impl LoopVarClassBox {
|
|||||||
inspector: &LocalScopeInspectorBox,
|
inspector: &LocalScopeInspectorBox,
|
||||||
exit_preds: &[BasicBlockId],
|
exit_preds: &[BasicBlockId],
|
||||||
) -> LoopVarClass {
|
) -> LoopVarClass {
|
||||||
|
// Priority 0: __pin$ temporary variables are ALWAYS BodyLocalInternal
|
||||||
|
// Reason: These are compiler-generated temporaries for pinning expression values.
|
||||||
|
// They are defined inside loop bodies and should NEVER get exit PHIs.
|
||||||
|
// Task先生の発見: ValueId(289)等の未定義値エラーの根本原因!
|
||||||
|
if var_name.starts_with("__pin$") && var_name.contains("$@") {
|
||||||
|
return LoopVarClass::BodyLocalInternal;
|
||||||
|
}
|
||||||
|
|
||||||
// Priority 1: Check if it's a pinned variable
|
// Priority 1: Check if it's a pinned variable
|
||||||
if pinned_vars.iter().any(|p| p == var_name) {
|
if pinned_vars.iter().any(|p| p == var_name) {
|
||||||
return LoopVarClass::Pinned;
|
return LoopVarClass::Pinned;
|
||||||
@ -464,6 +472,39 @@ mod tests {
|
|||||||
assert!(!candidates.contains(&"ch".to_string())); // ← Option C: ch is filtered out!
|
assert!(!candidates.contains(&"ch".to_string())); // ← Option C: ch is filtered out!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Test Task先生の発見: __pin$ temporary variables should be BodyLocalInternal
|
||||||
|
#[test]
|
||||||
|
fn test_classify_pin_temporary_variables() {
|
||||||
|
let inspector = LocalScopeInspectorBox::new();
|
||||||
|
let classifier = LoopVarClassBox::new();
|
||||||
|
|
||||||
|
// __pin$ temporary variables should ALWAYS be BodyLocalInternal
|
||||||
|
// regardless of their definition locations
|
||||||
|
let pin_vars = vec![
|
||||||
|
"__pin$285$@binop_lhs",
|
||||||
|
"__pin$286$@binop_rhs",
|
||||||
|
"__pin$437$@binop_lhs",
|
||||||
|
"__pin$297$@assign",
|
||||||
|
];
|
||||||
|
|
||||||
|
for pin_var in pin_vars {
|
||||||
|
let class = classifier.classify(
|
||||||
|
pin_var,
|
||||||
|
&[], // Not pinned
|
||||||
|
&[], // Not carrier
|
||||||
|
&inspector,
|
||||||
|
&[], // No exit preds
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(class, LoopVarClass::BodyLocalInternal,
|
||||||
|
"Variable '{}' should be BodyLocalInternal", pin_var);
|
||||||
|
assert!(!class.needs_exit_phi(),
|
||||||
|
"Variable '{}' should NOT need exit PHI", pin_var);
|
||||||
|
assert!(!class.needs_header_phi(),
|
||||||
|
"Variable '{}' should NOT need header PHI", pin_var);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_description() {
|
fn test_description() {
|
||||||
assert_eq!(LoopVarClass::Pinned.description(), "Loop-crossing parameter");
|
assert_eq!(LoopVarClass::Pinned.description(), "Loop-crossing parameter");
|
||||||
|
|||||||
@ -276,6 +276,12 @@ pub(super) fn lower_loop_stmt(
|
|||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
let mut writes = HashSet::new();
|
let mut writes = HashSet::new();
|
||||||
for (name, &body_value) in &body_vars {
|
for (name, &body_value) in &body_vars {
|
||||||
|
// Skip __pin$ temporary variables - they are always BodyLocalInternal
|
||||||
|
// (Task先生の発見: これらをcarrier扱いすると未定義ValueIdエラーの原因になる)
|
||||||
|
if name.starts_with("__pin$") && name.contains("$@") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(&base_value) = base_vars.get(name) {
|
if let Some(&base_value) = base_vars.get(name) {
|
||||||
if body_value != base_value {
|
if body_value != base_value {
|
||||||
writes.insert(name.clone());
|
writes.insert(name.clone());
|
||||||
|
|||||||
Reference in New Issue
Block a user