Implementation: - Add make_pattern2_scope_manager() helper for DRY - Header conditions use ExprLowerer for supported patterns - Legacy fallback for unsupported patterns - Fail-Fast on supported patterns that fail Tests: - 4 new tests (all pass) - test_expr_lowerer_supports_simple_header_condition_i_less_literal - test_expr_lowerer_supports_header_condition_var_less_var - test_expr_lowerer_header_condition_generates_expected_instructions - test_pattern2_header_condition_via_exprlowerer Also: Archive old phase documentation (34k lines removed) ðĪ Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
49 KiB
Status: Historical
PHIįæãģãžããŪįŪąįčŦãŠããĄãŊãŋãŠãģã°čĻįŧ
ä―ææĨ: 2025-11-20 æįĩæīæ°: 2025-11-20 (Phase 26-BåŪäš) ãđããžãŋãđ: â Phase 1åŪäš / Phase 2-3åŪæ―äļ åŠå åšĶ: High įŪæĻ: PHIįæãģãžããŪäŋåŪæ§ãŧããđãåŪđææ§ãŧåŊčŠæ§ãŪåäļ
ð Executive Summary
įūåĻãŪPHIįæãģãžããŊįī2,916čĄãŦåãģãčĪæ°ãŪčēŽäŧŧãæ··åĻããĶããūããæŽčĻįŧã§ãŊãįŪąįčŦïžBox-FirstïžååãŦåšãĨããčēŽäŧŧãæįĒšãŦåéĒãã6ãĪãŪBoxãææĄããūãã
æåū ãããåđæ:
- ðŊ äŋåŪæ§åäļ: čēŽäŧŧãŪæįĒšåãŦããåĪæīå―ąéŋįŊåēãéåŪããã
- ⥠ããđãåŪđææ§: åBoxãįŽįŦããĶããđãã§ãã
- ð åŊčŠæ§åäļ: åBoxãŪå―đåēãäļįŪã§åãã
- ð ååĐįĻæ§: äŧãŪPHIįææčã§ãä―ŋãã
ð įūįķåæãŽããžã
æĒåãŪBoxåŪčĢ ïžåŪææļãŋâ ïž
| Boxå | čĄæ° | čēŽäŧŧ | įķæ |
|---|---|---|---|
| LocalScopeInspectorBox | 152 | åĪæ°åŪįūĐä―į―ŪãŪčŋ―č·Ą | â åŪå ĻįŪąåæļãŋ |
| LoopVarClassBox | 516 | åĪæ°4ãŦããīãŠåéĄ | â åŪå ĻįŪąåæļãŋ |
| LoopSnapshotMergeBox | 578 | ãđãããã·ã§ããããžãļįĩąäļįŪĄį | â åŪå ĻįŪąåæļãŋ |
åčĻ: 1,246čĄïžæĒãŦįŪąåæļãŋïž
įŪąåãããĶããŠãčēŽäŧŧé å
1. loopform_builder.rs (1,075čĄ) - čĪæ°čēŽäŧŧãæ··åĻ
| čēŽäŧŧ | čĄæ° | čĪéåšĶ | įŪąååŠå åšĶ |
|---|---|---|---|
| ValueIdåēãå―ãĶįŪĄį | ~100 | ä― | Medium |
| Header PHIįæ | ~50 | äļ | High |
| Latch PHIæīæ° | ~120 | éŦ | High |
| Exit PHIįæ | ~170 | æéŦ | Critical |
| Preheader Copyįæ | ~50 | ä― | Low |
| åĪæ°åéĄ | ~100 | äļ | Medium |
åéĄįđ:
- â Exit PHIįæãæãčĪéïž173čĄãŪ
build_exit_phisïž - â
seal_phisãčĪæ°ãŪčēŽäŧŧãæãĪïžHeader PHI + LatchåĪæīæ°ïž - â LocalScopeInspectorBox/LoopVarClassBoxãĻãŪéĢæšãæĢåĻ
2. if_phi.rs (298čĄ) - éĻåįįŪąå
| čēŽäŧŧ | įķæ | įŪąååŠå åšĶ |
|---|---|---|
| If/Else PHIįæ | ðĄ Traitäūå | Medium |
| åĪæ°åĪæīæĪåš | â éĒæ°åæļãŋ | Low |
| PHI mergeåĶį | ðĄ Traitäūå | Medium |
3. loop_phi.rs (265čĄ) - ãŽãŽã·ãž scaffold
ãđããžãŋãđ: Phase 31.x äŧĨéã§åéĪäšåŪ æĻåĨĻ: æ°čĶåŪčĢ ãŦãŊä―ŋįĻããŠã
ðŊ įŪąååčĢãŪčĐģįī°čĻčĻ
åŠå åšĶãããŠããŊãđ
âââââââââââââââââââââââââââââââââââââââââââ
High â PhiInputCollector BodyLocalPhiBuilder â
Effect â LoopSnapshotManager HeaderPhiBuilder â
â â
â ExitPhiBuilder (æéčĶ) â
Medium â â
Effect â ValueIdAllocator â
â â
âââââââââââââââââââââââââââââââââââââââââââ
Low Risk ââââââââââââââââââââââ High Risk
Option 1: PhiInputCollector â æåŠå åčĢ
čēŽäŧŧ
- PHIå ĨåãŪåé
- éčĪpredecessoråéĪïžsanitizeïž
- ååĪįļŪįīæéĐåïžoptimizeïž
čĻčĻ
/// PHIå
Ĩååéå°éBox
///
/// čĪæ°ãŪpredecessorããPHIå
ĨåãåéããæéĐåãéĐįĻããã
pub struct PhiInputCollector {
/// åéãããå
Ĩå: (predecessor, value)
inputs: Vec<(BasicBlockId, ValueId)>,
}
impl PhiInputCollector {
/// æ°ããcollectorãä―æ
pub fn new() -> Self {
Self { inputs: Vec::new() }
}
/// Preheaderå
Ĩåãčŋ―å
pub fn add_preheader(&mut self, block: BasicBlockId, value: ValueId) {
self.inputs.push((block, value));
}
/// Continue/Break snapshotå
Ĩåãčŋ―å
pub fn add_snapshot(&mut self, snapshot: &[(BasicBlockId, ValueId)]) {
self.inputs.extend_from_slice(snapshot);
}
/// Latchå
Ĩåãčŋ―å
pub fn add_latch(&mut self, block: BasicBlockId, value: ValueId) {
self.inputs.push((block, value));
}
/// å
ĨåããĩããŋãĪãšïžéčĪåéĪãã―ãžãïž
pub fn sanitize(&mut self) {
// æĒåãŪsanitize_inputsããļããŊãä―ŋįĻ
let mut seen: BTreeMap<BasicBlockId, ValueId> = BTreeMap::new();
for (bb, val) in self.inputs.iter() {
seen.insert(*bb, *val);
}
self.inputs = seen.into_iter().collect();
self.inputs.sort_by_key(|(bb, _)| bb.0);
}
/// ååĪæéĐå: å
ĻãĶåãåĪãŠãPHIäļčĶ
pub fn optimize_same_value(&self) -> Option<ValueId> {
if self.inputs.is_empty() {
return None;
}
if self.inputs.len() == 1 {
return Some(self.inputs[0].1);
}
let first_val = self.inputs[0].1;
if self.inputs.iter().all(|(_, val)| *val == first_val) {
Some(first_val)
} else {
None
}
}
/// æįĩįãŠå
Ĩåãååū
pub fn finalize(self) -> Vec<(BasicBlockId, ValueId)> {
self.inputs
}
}
čĐäūĄ
- ðŊ å―ąéŋįŊåē: äļ (loopform_builder.rs + loop_snapshot_merge.rs)
- ⥠åđæ: äļ (PHIå ĨååéããļããŊãŪįĩąäļ)
- â ïļ ãŠãđãŊ: ä― (æĒåéĒæ°ãįĩąåããã ã)
- ð åŪčĢ æé: å° (1-2æé)
åæļčĶčūžãŋ
- loopform_builder.rs: ~50čĄåæļ
- loop_snapshot_merge.rs: ~30čĄåæļ
- åčĻ: ~80čĄåæļ
Option 2: BodyLocalPhiBuilder â įŽŽ2åŠå åčĢ
čēŽäŧŧ
- BodyLocalåĪæ°ãŪPHIįæåĪåŪ
- BodyLocalInternalåĪæ°ãŪãđããã
- Exit PHIåčĢãŪããĢãŦãŋãŠãģã°
čĻčĻ
/// BodyLocalåĪæ°PHIįæå°éBox
///
/// BodyLocalExit/BodyLocalInternalåĪæ°ãåĪåŪãã
/// Exit PHIįæãŪčĶåĶãæąšåŪããã
pub struct BodyLocalPhiBuilder {
classifier: LoopVarClassBox,
inspector: LocalScopeInspectorBox,
}
impl BodyLocalPhiBuilder {
/// æ°ããbuilderãä―æ
pub fn new(
classifier: LoopVarClassBox,
inspector: LocalScopeInspectorBox,
) -> Self {
Self { classifier, inspector }
}
/// åĪæ°ãExit PHIãåŋ
čĶãĻãããåĪåŪ
///
/// # Returns
/// - `Some(PhiSpec)`: PHIįæãåŋ
čĶ
/// - `None`: PHIäļčĶïžBodyLocalInternalïž
pub fn should_generate_exit_phi(
&self,
var_name: &str,
pinned_vars: &[String],
carrier_vars: &[String],
exit_preds: &[BasicBlockId],
) -> bool {
let class = self.classifier.classify(
var_name,
pinned_vars,
carrier_vars,
&self.inspector,
exit_preds,
);
// BodyLocalInternal â Skip exit PHI
class.needs_exit_phi()
}
/// Exit PHIåčĢãããĢãŦãŋãŠãģã°
pub fn filter_exit_phi_candidates(
&self,
all_vars: &[String],
pinned_vars: &[String],
carrier_vars: &[String],
exit_preds: &[BasicBlockId],
) -> Vec<String> {
all_vars
.iter()
.filter(|var_name| {
self.should_generate_exit_phi(
var_name,
pinned_vars,
carrier_vars,
exit_preds,
)
})
.cloned()
.collect()
}
/// Inspectoråį
§ãååūïžãđãããã·ã§ããčĻéēįĻïž
pub fn inspector_mut(&mut self) -> &mut LocalScopeInspectorBox {
&mut self.inspector
}
}
čĐäūĄ
- ðŊ å―ąéŋįŊåē: äļ (loopform_builder.rsãŪbuild_exit_phisãŪäļéĻ)
- ⥠åđæ: äļ (BodyLocalåĶįãŪæįĒšå)
- â ïļ ãŠãđãŊ: ä― (æĒåBoxãŪįĩãŋåãã)
- ð åŪčĢ æé: å° (2-3æé)
åæļčĶčūžãŋ
- loopform_builder.rs: ~60čĄåæļïžbuild_exit_phiså ãŪåéĄããļããŊïž
- åčĻ: ~60čĄåæļ
Option 3: LoopSnapshotManager - ããžãŋæ§é įĩąäļ
čēŽäŧŧ
- Snapshotäŋåãŧååū
- Preheader/Exit/Continue snapshotãŪäļå įŪĄį
- SnapshotæŊčžïžåĪæ°åĪæīæĪåšïž
čĻčĻ
/// ãŦãžãSnapshotãŪäļå
įŪĄįBox
///
/// preheader/exit/continueæãŪvariable mapãäŋåãã
/// PHIįææãŦåŋ
čĶãŠsnapshotãæäūããã
pub struct LoopSnapshotManager {
/// PreheaderæįđãŪåĪæ°įķæ
preheader_snapshot: HashMap<String, ValueId>,
/// Exit predecessorããĻãŪsnapshot
exit_snapshots: Vec<(BasicBlockId, HashMap<String, ValueId>)>,
/// Continue predecessorããĻãŪsnapshot
continue_snapshots: Vec<(BasicBlockId, HashMap<String, ValueId>)>,
}
impl LoopSnapshotManager {
/// æ°ããmanagerãä―æ
pub fn new() -> Self {
Self {
preheader_snapshot: HashMap::new(),
exit_snapshots: Vec::new(),
continue_snapshots: Vec::new(),
}
}
/// Preheader snapshotãäŋå
pub fn save_preheader(&mut self, vars: HashMap<String, ValueId>) {
self.preheader_snapshot = vars;
}
/// Exit snapshotãčŋ―å
pub fn add_exit_snapshot(
&mut self,
block: BasicBlockId,
vars: HashMap<String, ValueId>,
) {
self.exit_snapshots.push((block, vars));
}
/// Continue snapshotãčŋ―å
pub fn add_continue_snapshot(
&mut self,
block: BasicBlockId,
vars: HashMap<String, ValueId>,
) {
self.continue_snapshots.push((block, vars));
}
/// Preheader snapshotãååū
pub fn preheader(&self) -> &HashMap<String, ValueId> {
&self.preheader_snapshot
}
/// Exit snapshotsãååū
pub fn exit_snapshots(&self) -> &[(BasicBlockId, HashMap<String, ValueId>)] {
&self.exit_snapshots
}
/// Continue snapshotsãååū
pub fn continue_snapshots(&self) -> &[(BasicBlockId, HashMap<String, ValueId>)] {
&self.continue_snapshots
}
/// åĪæ°ãpreheaderããåĪæīãããããã§ããŊ
pub fn is_modified(&self, var_name: &str, current_value: ValueId) -> bool {
self.preheader_snapshot
.get(var_name)
.map(|&preheader_val| preheader_val != current_value)
.unwrap_or(true) // æ°čĶåĪæ°ãŊåĪæīæąã
}
}
čĐäūĄ
- ðŊ å―ąéŋįŊåē: åΧ (builder.rs + loopform_builder.rs + loop_snapshot_merge.rs)
- ⥠åđæ: éŦ (SnapshotįŪĄįãŪäļå å)
- â ïļ ãŠãđãŊ: äļ (ããžãŋæ§é ãŪåĪæīãåŋ čĶ)
- ð åŪčĢ æé: äļ (4-6æé)
åæļčĶčūžãŋ
- builder.rs: ~50čĄåæļïžloop_header_stack/loop_exit_stackéĒéĢïž
- loopform_builder.rs: ~40čĄåæļïžpreheader_varsįŪĄįïž
- åčĻ: ~90čĄåæļ
Option 4: HeaderPhiBuilder - Header PHIå°éå
čēŽäŧŧ
- Header PHIįæ
- Preheaderå ĨåčĻåŪ
- LatchåĪæīæ°ïžsealæïž
čĻčĻ
/// Header PHIįæå°éBox
///
/// Loop headerã§ãŪPHI nodeãįæããsealããã
pub struct HeaderPhiBuilder {
/// PinnedåĪæ°ãŪPHIæ
å ą
pinned_phis: Vec<PinnedPhiInfo>,
/// CarrieråĪæ°ãŪPHIæ
å ą
carrier_phis: Vec<CarrierPhiInfo>,
}
#[derive(Debug, Clone)]
struct PinnedPhiInfo {
var_name: String,
phi_id: ValueId,
param_value: ValueId,
preheader_copy: ValueId,
}
#[derive(Debug, Clone)]
struct CarrierPhiInfo {
var_name: String,
phi_id: ValueId,
init_value: ValueId,
preheader_copy: ValueId,
}
impl HeaderPhiBuilder {
/// æ°ããbuilderãä―æ
pub fn new() -> Self {
Self {
pinned_phis: Vec::new(),
carrier_phis: Vec::new(),
}
}
/// PinnedåĪæ°ãŪPHIãæšå
pub fn prepare_pinned_phi(
&mut self,
var_name: String,
phi_id: ValueId,
param_value: ValueId,
preheader_copy: ValueId,
) {
self.pinned_phis.push(PinnedPhiInfo {
var_name,
phi_id,
param_value,
preheader_copy,
});
}
/// CarrieråĪæ°ãŪPHIãæšå
pub fn prepare_carrier_phi(
&mut self,
var_name: String,
phi_id: ValueId,
init_value: ValueId,
preheader_copy: ValueId,
) {
self.carrier_phis.push(CarrierPhiInfo {
var_name,
phi_id,
init_value,
preheader_copy,
});
}
/// Header PHIãįščĄ
pub fn emit_header_phis<O: LoopFormOps>(
&self,
ops: &mut O,
header_id: BasicBlockId,
preheader_id: BasicBlockId,
) -> Result<(), String> {
ops.set_current_block(header_id)?;
// Pinned PHIs
for phi in &self.pinned_phis {
ops.emit_phi(
phi.phi_id,
vec![(preheader_id, phi.preheader_copy)],
)?;
ops.update_var(phi.var_name.clone(), phi.phi_id);
}
// Carrier PHIs
for phi in &self.carrier_phis {
ops.emit_phi(
phi.phi_id,
vec![(preheader_id, phi.preheader_copy)],
)?;
ops.update_var(phi.var_name.clone(), phi.phi_id);
}
Ok(())
}
/// Seal PHIsïžlatch + continueå
Ĩåãčŋ―å ïž
pub fn seal_phis<O: LoopFormOps>(
&self,
ops: &mut O,
header_id: BasicBlockId,
preheader_id: BasicBlockId,
latch_id: BasicBlockId,
continue_snapshots: &[(BasicBlockId, HashMap<String, ValueId>)],
) -> Result<(), String> {
// Seal pinned PHIs
for phi in &self.pinned_phis {
let mut collector = PhiInputCollector::new();
collector.add_preheader(preheader_id, phi.preheader_copy);
// Continue inputs
for (cid, snapshot) in continue_snapshots {
if let Some(&value) = snapshot.get(&phi.var_name) {
collector.add_snapshot(&[(*cid, value)]);
}
}
// Latch input
let latch_value = ops
.get_variable_at_block(&phi.var_name, latch_id)
.unwrap_or(phi.phi_id);
collector.add_latch(latch_id, latch_value);
collector.sanitize();
// Optimize same-value PHI
if let Some(same_value) = collector.optimize_same_value() {
// Skip PHI update - loop-invariant
continue;
}
let inputs = collector.finalize();
ops.update_phi_inputs(header_id, phi.phi_id, inputs)?;
}
// Seal carrier PHIs (åæ§ãŪããļããŊ)
for phi in &self.carrier_phis {
// ... åæ§ãŪåĶį ...
}
Ok(())
}
}
čĐäūĄ
- ðŊ å―ąéŋįŊåē: äļ (loopform_builder.rsãŪäļéĻ)
- ⥠åđæ: äļ (Header PHIįæããļããŊãŪåéĒ)
- â ïļ ãŠãđãŊ: äļ (seal_phisããļããŊãĻãŪįĩąåãåŋ čĶ)
- ð åŪčĢ æé: äļ (4-5æé)
åæļčĶčūžãŋ
- loopform_builder.rs: ~150čĄåæļïžemit_header_phis + seal_phisãŪäļéĻïž
- åčĻ: ~150čĄåæļ
Option 5: ExitPhiBuilder ðĨ æéčĶãŧæčĪé
čēŽäŧŧ
- Exit PHIįæ
- Exit predecessorsæĪčĻž
- Phantom blockéĪåĪ
- Body-localåĪæ°ãŪåĶį
čĻčĻ
/// Exit PHIįæå°éBox
///
/// Loop exitæãŪPHI nodeãįæãããæãčĪéãŠčēŽäŧŧãæãĪã
pub struct ExitPhiBuilder {
snapshot_merger: LoopSnapshotMergeBox,
body_local_builder: BodyLocalPhiBuilder,
}
impl ExitPhiBuilder {
/// æ°ããbuilderãä―æ
pub fn new(
snapshot_merger: LoopSnapshotMergeBox,
body_local_builder: BodyLocalPhiBuilder,
) -> Self {
Self {
snapshot_merger,
body_local_builder,
}
}
/// Exit PHIsãįæ
pub fn build_exit_phis<O: LoopFormOps>(
&mut self,
ops: &mut O,
exit_id: BasicBlockId,
header_id: BasicBlockId,
branch_source_block: BasicBlockId,
header_vals: &HashMap<String, ValueId>,
exit_snapshots: &[(BasicBlockId, HashMap<String, ValueId>)],
pinned_vars: &[String],
carrier_vars: &[String],
) -> Result<(), String> {
ops.set_current_block(exit_id)?;
// 1. Exit predecessorsãååūïžCFGæĪčĻžïž
let exit_preds_set = ops.get_block_predecessors(exit_id);
let exit_preds: Vec<BasicBlockId> = exit_preds_set.iter().copied().collect();
// 2. Phantom blockãããĢãŦãŋãŠãģã°
let filtered_snapshots = self.filter_phantom_blocks(
exit_snapshots,
&exit_preds_set,
ops,
);
// 3. InspectorãŦåŪįūĐãčĻéē
let inspector = self.body_local_builder.inspector_mut();
for pinned_name in pinned_vars {
inspector.record_definition(pinned_name, header_id);
}
for carrier_name in carrier_vars {
inspector.record_definition(carrier_name, header_id);
}
for (block_id, snapshot) in &filtered_snapshots {
inspector.record_snapshot(*block_id, snapshot);
}
if exit_preds_set.contains(&branch_source_block) {
inspector.record_snapshot(branch_source_block, header_vals);
}
// 4. LoopSnapshotMergeBoxã§PHIå
Ĩåãįæ
let all_vars = self.snapshot_merger.merge_exit_with_classification(
header_id,
header_vals,
&filtered_snapshots,
&exit_preds,
pinned_vars,
carrier_vars,
inspector,
)?;
// 5. PHIįæïžoptimize + sanitizeéĐįĻïž
for (var_name, mut inputs) in all_vars {
if let Some(same_val) = self.snapshot_merger.optimize_same_value(&inputs) {
// ååĪPHI â įīæĨããĪãģã
ops.update_var(var_name, same_val);
} else {
// į°ãŠãåĪ â PHIįæ
self.snapshot_merger.sanitize_inputs(&mut inputs);
let phi_id = ops.new_value();
ops.emit_phi(phi_id, inputs)?;
ops.update_var(var_name, phi_id);
}
}
Ok(())
}
/// Phantom blockãããĢãŦãŋãŠãģã°
fn filter_phantom_blocks<O: LoopFormOps>(
&self,
exit_snapshots: &[(BasicBlockId, HashMap<String, ValueId>)],
exit_preds: &std::collections::HashSet<BasicBlockId>,
ops: &O,
) -> Vec<(BasicBlockId, HashMap<String, ValueId>)> {
let mut filtered = Vec::new();
for (block_id, snapshot) in exit_snapshots {
if !ops.block_exists(*block_id) {
continue; // Non-existent block
}
if !exit_preds.contains(block_id) {
continue; // Not a CFG predecessor
}
filtered.push((*block_id, snapshot.clone()));
}
filtered
}
}
čĐäūĄ
- ðŊ å―ąéŋįŊåē: åΧ (loopform_builder.rs + loop_snapshot_merge.rs)
- ⥠åđæ: éŦ (Exit PHIįæãŪčĪéããļããŊéįī)
- â ïļ ãŠãđãŊ: éŦ (čĪæ°ããĄãĪãŦãŦãūãããåĪæī)
- ð åŪčĢ æé: åΧ (6-8æé)
åæļčĶčūžãŋ
- loopform_builder.rs: ~170čĄåæļïžbuild_exit_phiså Ļä―ïž
- loop_snapshot_merge.rs: ~50čĄåæļïžmerge_exit_with_classificationį°ĄįĨåïž
- åčĻ: ~220čĄåæļ
Option 6: ValueIdAllocator - åŠå åšĶä―
čēŽäŧŧ
- ValueIdåēãå―ãĶ
- ãŦãĶãģãŋãžįŪĄį
- ããĐãĄãžãŋäšįī
čĻčĻ
/// ValueIdåēãå―ãĶå°éBox
///
/// LoopFormæ§įŊæãŪValueIdįŪĄįãæ―čąĄåã
pub struct ValueIdAllocator {
next_value_id: u32,
param_count: usize,
}
impl ValueIdAllocator {
/// æ°ããallocatorãä―æ
pub fn new(param_count: usize, existing_vars: &HashMap<String, ValueId>) -> Self {
let min_from_params = param_count as u32;
let min_from_vars = existing_vars.values().map(|v| v.0 + 1).max().unwrap_or(0);
Self {
next_value_id: min_from_params.max(min_from_vars),
param_count,
}
}
/// æ°ããValueIdãåēãå―ãĶ
pub fn allocate(&mut self) -> ValueId {
let id = ValueId(self.next_value_id);
self.next_value_id += 1;
id
}
/// ãŦãĶãģãŋãžãįđåŪãŪValueIdäŧĨéãŦčĻåŪ
pub fn ensure_after(&mut self, max_id: u32) {
if self.next_value_id <= max_id {
self.next_value_id = max_id + 1;
}
}
}
čĐäūĄ
- ðŊ å―ąéŋįŊåē: å° (loopform_builder.rsãŪãŋ)
- ⥠åđæ: ä― (æĒãŦLoopFormContextãããįĻåšĶæ―蹥å)
- â ïļ ãŠãđãŊ: ä―
- ð åŪčĢ æé: å° (1-2æé)
åæļčĶčūžãŋ
- loopform_builder.rs: ~20čĄåæļïžLoopFormContextãŪäļéĻïž
- åčĻ: ~20čĄåæļ
ð ãŠããĄãŊãŋãŠãģã°åŪčĄčĻįŧ
Phase 1: Quick Winsïžä―ãŠãđãŊãŧåģåđæ§ïž
æé: 1éąé įŪæĻ: ããđãåŪđææ§ãŪåäļããģãžãåæļ80-140čĄ
ãŋãđãŊ
-
PhiInputCollectoråŪčĢ (Priority: High, Risk: Low)
src/mir/phi_core/phi_input_collector.rsä―æ- PhiInputCollector structåŪčĢ
- add_preheader/add_snapshot/add_latchåŪčĢ
- sanitize/optimize_same_valueåŪčĢ
- åä―ããđãä―æïžããđããŦããŽããļ>90%ïž
- loopform_builder.rsã§ä―ŋįĻ
- loop_snapshot_merge.rsã§ä―ŋįĻ
- æĒåãŪsanitize_inputs/optimize_same_valueåéĪ
-
BodyLocalPhiBuilderåŪčĢ (Priority: High, Risk: Low)
src/mir/phi_core/body_local_phi_builder.rsä―æ- BodyLocalPhiBuilder structåŪčĢ
- should_generate_exit_phiåŪčĢ
- filter_exit_phi_candidatesåŪčĢ
- åä―ããđãä―æïžskip_whitespaceã·ããŠãŠåŦãïž
- loopform_builder.rsãŪbuild_exit_phisã§ä―ŋįĻ
- æĒåãŪåéĄããļããŊåéĪ
ææįĐ:
- â 2ãĪãŪæ°ããBoxïžåčĻ~300čĄïž
- â æĒåãģãžãåæļ: ~140čĄ
- â ããđããŦããŽããļ: >90%
- â ãããĨãĄãģã: åBoxãŪdocãģãĄãģãåŪå
Phase 2: æ§é æđåïžäļãŠãđãŊãŧåđæåΧïž
æé: 2éąé įŪæĻ: ããžãŋæ§é ãŪäļå åããģãžãåæļ240čĄ
ãŋãđãŊ
-
LoopSnapshotManageråŪčĢ (Priority: Medium, Risk: Medium)
src/mir/phi_core/loop_snapshot_manager.rsä―æ- LoopSnapshotManager structåŪčĢ
- save_preheader/add_exit_snapshot/add_continue_snapshotåŪčĢ
- is_modifiedåŪčĢ
- åä―ããđãä―æ
- builder.rsãŪloop_header_stack/loop_exit_stackåéĪ
- loopform_builder.rsãŪpreheader_varsåéĪ
- å ĻãŦãžãæ§įŊįŪæã§ä―ŋįĻ
-
HeaderPhiBuilderåŪčĢ (Priority: Medium, Risk: Medium)
src/mir/phi_core/header_phi_builder.rsä―æ- HeaderPhiBuilder structåŪčĢ
- prepare_pinned_phi/prepare_carrier_phiåŪčĢ
- emit_header_phisåŪčĢ
- seal_phisåŪčĢ ïžPhiInputCollectorä―ŋįĻïž
- åä―ããđãä―æ
- loopform_builder.rsãŪemit_header_phis/seal_phisåéĪ
ææįĐ:
- â 2ãĪãŪæ°ããBoxïžåčĻ~400čĄïž
- â æĒåãģãžãåæļ: ~240čĄ
- â ããžãŋæ§é ãŪäļå ååŪäš
- â Header PHIįæãŪåŪå ĻåéĒ
Phase 3: æéĢéĒæŧįĨïžéŦãŠãđãŊãŧæåΧåđæïž
æé: 2-3éąé įŪæĻ: Exit PHIįæãŪåŪå ĻåéĒããģãžãåæļ220čĄ
ãŋãđãŊ
- ExitPhiBuilderåŪčĢ
(Priority: Critical, Risk: High)
src/mir/phi_core/exit_phi_builder.rsä―æ- ExitPhiBuilder structåŪčĢ
- build_exit_phisåŪčĢ
- filter_phantom_blocksåŪčĢ
- å
æŽįããđããđãĪãžãä―æ
- æĢåļļįģŧ: 2 exit preds, 3 exit preds
- į°åļļįģŧ: Phantom block, CFGäļæīå
- skip_whitespaceã·ããŠãŠ
- BodyLocalExit vs BodyLocalInternal
- loopform_builder.rsãŪbuild_exit_phisåéĪïž173čĄïž
- loop_snapshot_merge.rsãŪmerge_exit_with_classificationį°ĄįĨå
- å ĻãŦãžãæ§įŊįŪæã§åä―įĒščŠ
ææįĐ:
- â 1ãĪãŪæ°ããBoxïžåčĻ~250čĄïž
- â æĒåãģãžãåæļ: ~220čĄ
- â Exit PHIįæãŪåŪå ĻåéĒ
- â æãčĪéãŠããļããŊãŪããđããŦããŽããļ>95%
Phase 4: äŧäļãïžãŠãã·ã§ããŦïž
æé: 1éąé įŪæĻ: æŪåéĻåãŪæéĐåããããĨãĄãģãåŪå
ãŋãđãŊ
-
ValueIdAllocatoråŪčĢ (Priority: Low, Risk: Low)
src/mir/phi_core/value_id_allocator.rsä―æ- ValueIdAllocator structåŪčĢ
- allocate/ensure_afteråŪčĢ
- loopform_builder.rsãŪLoopFormContextį―Ūãæã
-
ãããĨãĄãģãæīå
- įŪąįčŦéĐįĻååūãŪæŊčžåģä―æ
- äūåéĒäŋåģä―æïžBefore/Afterïž
- åŪčĢ ãŽãĪãä―æ
- åBoxãŪãĶãžãđãąãžãđéä―æ
ææįĐ:
- â ValueIdAllocatoråŪčĢ ïž~80čĄïž
- â æĒåãģãžãåæļ: ~20čĄ
- â åŪå ĻãŠãããĨãĄãģã
- â åŪčĢ ãŽãĪã
ð åæļåđæãūãĻã
ãģãžãåæļčĶčūžãŋ
| Phase | BoxåŪčĢ | åæļčĄæ° | įīåæļ | įīŊčĻåæļ |
|---|---|---|---|---|
| Phase 1 | PhiInputCollector BodyLocalPhiBuilder |
+300 | -140 | +160 |
| Phase 2 | LoopSnapshotManager HeaderPhiBuilder |
+400 | -240 | +160 |
| Phase 3 | ExitPhiBuilder | +250 | -220 | +30 |
| Phase 4 | ValueIdAllocator | +80 | -20 | +60 |
| åčĻ | 1,030čĄ | -620čĄ | +410čĄ |
æģĻčĻ:
- įīåæļãæĢãŪåĪ = ãģãžãéåĒå ïžæ§é åãŦããäļæįåĒå ïž
- ããããããđããŧãããĨãĄãģããŧäŋåŪæ§ãŊåįåäļ
- Phase 3åŪäšåūããããŠãæéĐåã§čŋ―å åæļåŊč―
äŋåŪæ§åäļææĻ
| ææĻ | įūįķ | įŪæĻ | æđåį |
|---|---|---|---|
| æåΧéĒæ°ãĩãĪãš | 173čĄ | 50čĄäŧĨäļ | 71%åæļ |
| čēŽäŧŧãŪåéĒ | æ··åĻ | åŪå ĻåéĒ | 100%æđå |
| ããđããŦããŽããļ | ~60% | >90% | +50%åäļ |
| åūŠį°įčĪéåšĶ | éŦ | ä― | æĻåŪ50%æđå |
ðŊ ããđãæĶįĨ
Phase 1ããđã
PhiInputCollector
#[cfg(test)]
mod phi_input_collector_tests {
use super::*;
#[test]
fn test_single_input_optimization() {
let mut collector = PhiInputCollector::new();
collector.add_preheader(BasicBlockId::new(0), ValueId::new(10));
assert_eq!(collector.optimize_same_value(), Some(ValueId::new(10)));
}
#[test]
fn test_same_value_optimization() {
let mut collector = PhiInputCollector::new();
collector.add_preheader(BasicBlockId::new(0), ValueId::new(10));
collector.add_latch(BasicBlockId::new(1), ValueId::new(10));
collector.add_snapshot(&[(BasicBlockId::new(2), ValueId::new(10))]);
assert_eq!(collector.optimize_same_value(), Some(ValueId::new(10)));
}
#[test]
fn test_different_values_no_optimization() {
let mut collector = PhiInputCollector::new();
collector.add_preheader(BasicBlockId::new(0), ValueId::new(10));
collector.add_latch(BasicBlockId::new(1), ValueId::new(20));
assert_eq!(collector.optimize_same_value(), None);
}
#[test]
fn test_sanitize_duplicates() {
let mut collector = PhiInputCollector::new();
collector.add_preheader(BasicBlockId::new(0), ValueId::new(10));
collector.add_preheader(BasicBlockId::new(0), ValueId::new(20)); // Duplicate
collector.sanitize();
let inputs = collector.finalize();
assert_eq!(inputs.len(), 1);
assert_eq!(inputs[0], (BasicBlockId::new(0), ValueId::new(20))); // Latest wins
}
#[test]
fn test_sanitize_sorting() {
let mut collector = PhiInputCollector::new();
collector.add_latch(BasicBlockId::new(2), ValueId::new(20));
collector.add_preheader(BasicBlockId::new(0), ValueId::new(10));
collector.add_snapshot(&[(BasicBlockId::new(1), ValueId::new(15))]);
collector.sanitize();
let inputs = collector.finalize();
// Should be sorted by BasicBlockId
assert_eq!(inputs[0].0, BasicBlockId::new(0));
assert_eq!(inputs[1].0, BasicBlockId::new(1));
assert_eq!(inputs[2].0, BasicBlockId::new(2));
}
}
BodyLocalPhiBuilder
#[cfg(test)]
mod body_local_phi_builder_tests {
use super::*;
#[test]
fn test_skip_whitespace_scenario() {
// Reproduce the exact skip_whitespace bug scenario
let mut inspector = LocalScopeInspectorBox::new();
let block_2 = BasicBlockId::new(2); // header / break path 1
let block_5 = BasicBlockId::new(5); // break path 2
// i, n, s in all blocks
for var in &["i", "n", "s"] {
inspector.record_definition(var, block_2);
inspector.record_definition(var, block_5);
}
// ch only in block 5
inspector.record_definition("ch", block_5);
let classifier = LoopVarClassBox::new();
let builder = BodyLocalPhiBuilder::new(classifier, inspector);
let exit_preds = vec![block_2, block_5];
let pinned = vec!["n".to_string(), "s".to_string()];
let carrier = vec!["i".to_string()];
// i, n, s should need exit PHI
assert!(builder.should_generate_exit_phi("i", &pinned, &carrier, &exit_preds));
assert!(builder.should_generate_exit_phi("n", &pinned, &carrier, &exit_preds));
assert!(builder.should_generate_exit_phi("s", &pinned, &carrier, &exit_preds));
// ch should NOT need exit PHI (BodyLocalInternal)
assert!(!builder.should_generate_exit_phi("ch", &pinned, &carrier, &exit_preds));
}
#[test]
fn test_filter_exit_phi_candidates() {
let mut inspector = LocalScopeInspectorBox::new();
let block_2 = BasicBlockId::new(2);
let block_5 = BasicBlockId::new(5);
inspector.record_definition("i", block_2);
inspector.record_definition("i", block_5);
inspector.record_definition("ch", block_5); // Only block 5
let classifier = LoopVarClassBox::new();
let builder = BodyLocalPhiBuilder::new(classifier, inspector);
let all_vars = vec!["i".to_string(), "ch".to_string()];
let exit_preds = vec![block_2, block_5];
let candidates = builder.filter_exit_phi_candidates(
&all_vars,
&[],
&["i".to_string()],
&exit_preds,
);
assert_eq!(candidates.len(), 1);
assert!(candidates.contains(&"i".to_string()));
assert!(!candidates.contains(&"ch".to_string()));
}
}
Phase 3 Critical Tests
ExitPhiBuilder
#[cfg(test)]
mod exit_phi_builder_tests {
use super::*;
#[test]
fn test_phantom_block_filtering() {
// Test that phantom blocks (from stale snapshots) are correctly filtered
// This is critical for preventing CFG inconsistencies
}
#[test]
fn test_exit_phi_with_two_predecessors() {
// Standard case: loop with 2 exit paths
}
#[test]
fn test_exit_phi_with_three_predecessors() {
// Complex case: loop with 3 exit paths
}
#[test]
fn test_body_local_exit_variable() {
// Variable defined in all exit paths â should get PHI
}
#[test]
fn test_body_local_internal_variable() {
// Variable defined in some (not all) exit paths â should NOT get PHI
}
#[test]
fn test_exit_phi_optimization() {
// Same-value optimization: all exit paths have same value â direct bind
}
}
ð ãããĨãĄãģãæĄ
įŪąįčŦéĐįĻååūãŪæŊčžåģ
Before: čēŽäŧŧæ··åĻïžįūįķïž
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â loopform_builder.rs (1,075 lines) â
â â
â ââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
â â prepare_structure() â â
â â - ValueIdåēãå―ãĶ âââââââââââââ â â
â â - Carrier/PinnedåéĄ âââââââââžââ â â
â â - Snapshotäŋå âââââââââââââââžââžââ â â
â ââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
â â â â â
â ââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
â â emit_header_phis() â â â â â
â â - Header PHIįæ ââââââââââââââââ â â â â
â ââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
â â â â
â ââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
â â seal_phis() â â â â
â â - Continueå
Ĩååé âââââââââââââââââ â â â
â â - LatchåĪæīæ° âââââââââââââââââââââââ â â
â â - PHI sanitize/optimize (éčĪ!) â â
â ââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
â â
â ââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
â â build_exit_phis() (173 lines!) â â
â â - Exit predecessorsæĪčĻž ââââââââ â â
â â - Phantom blockéĪåĪ ââââââââââââžââ â â
â â - Body-localåéĄ ââââââââââââââžââžââ â â
â â - InspectorčĻéē âââââââââââââââžââžââžââ â â
â â - Snapshot merge ââââââââââââââžââžââžââžââ â â
â â - PHI sanitize/optimize (éčĪ!)â â â â â â â
â ââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
â â â â â â â
â â čĪéåšĶ: éŦ â
â â ããđãå°éĢ â
â â äŋåŪæ§: ä― â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
After: čēŽäŧŧåéĒïžįŪæĻïž
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â PHI Generation Ecosystem (Box-First Architecture) â
â â
â ââââââââââââââââââââ ââââââââââââââââââââ â
â â LocalScope â â LoopVarClass â â
â â InspectorBox â â Box â â
â â (152 lines) â â (516 lines) â â
â â â â â â
â â â
åŪįūĐä―į―Ūčŋ―č·Ą â â â
4ãŦããīãŠåéĄ â â
â ââââââââââŽââââââââââ ââââââââââŽââââââââââ â
â â â â
â ââââââââââââŽâââââââââââ â
â â â
â ââââââââââââââââââââââââ â
â â BodyLocalPhiBuilder â â
â â (~150 lines) â â
â â â â
â â â
Exit PHIåĪåŪ â â
â â â
ããĢãŦãŋãŠãģã° â â
â ââââââââââââŽââââââââââââ â
â â â
â âââââââââââââââââââââžââââââââââââââââââââ â
â â PhiInputCollector â â â
â â (~100 lines) â â â
â â â â â
â â â
å
Ĩååé â â â
â â â
Sanitize â â â
â â â
Optimize â â â
â âââââââââââââââââââââ â â
â â â
â ââââââââââââââââââââââââââââââââââââââââžââââââââââââââââââ â
â â HeaderPhiBuilder â â â
â â (~200 lines) â â â
â â â â â
â â â
Header PHIįæ âââââââââââââââââââ â â
â â â
SealåĶį â â
â âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
â â
â âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
â â ExitPhiBuilder â â
â â (~250 lines) â â
â â â â
â â â
Exit PHIįæ â â
â â â
Phantom blockéĪåĪ â â
â â â
åŪå
ĻåéĒ â â
â âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
â â
â âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
â â LoopSnapshotManager â â
â â (~150 lines) â â
â â â â
â â â
Snapshotäļå
įŪĄį â â
â âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
â â
â â
čĪéåšĶ: ä―ïžåBox<100čĄïž â
â â
ããđãåŪđæïžįŽįŦããđãåŊč―ïž â
â â
äŋåŪæ§: éŦïžčēŽäŧŧæįĒšïž â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
äūåéĒäŋåģïžAfterïž
âââââââââââââââââââââââ
â LocalScopeInspector â
â Box â
ââââââââââââŽâââââââââââ
â
ââââââââââââīâââââââââââ
â LoopVarClassBox â
ââââââââââââŽâââââââââââ
â
ââââââââââââīâââââââââââ
âBodyLocalPhiBuilder â
ââââââââââââŽâââââââââââ
â
ââââââââââââââââââââââââžâââââââââââââââââââââââ
â â â
âââââââââīâââââââââ âââââââââââīâââââââââ ââââââââââīââââââââ
âPhiInputCollectorâ âHeaderPhiBuilder â âExitPhiBuilder â
ââââââââââââââââââ ââââââââââââââââââââ ââââââââââââââââââ
â â â
ââââââââââââââââââââââââžâââââââââââââââââââââââ
â
ââââââââââââīâââââââââââ
âLoopSnapshotManager â
âââââââââââââââââââââââ
äūåéĒäŋãŪåå:
- â äļä―BoxãŊäļä―BoxãŦäūåã§ãã
- â äļä―BoxãŊäļä―BoxãŦäūåããŠãïžåūŠį°äūåéēæĒïž
- â åãŽããŦBoxãŊįŽįŦïžæ°īåđģäūåãŠãïž
ðĄ åŪčĢ ãŽãĪãïžæŽĄãŪãŧãã·ã§ãģįĻïž
Phase 1 åŪčĢ æé
Step 1: PhiInputCollectoråŪčĢ
# 1. ããĄãĪãŦä―æ
touch src/mir/phi_core/phi_input_collector.rs
# 2. mod.rsãŦčŋ―å
echo "pub mod phi_input_collector;" >> src/mir/phi_core/mod.rs
# 3. ããģããŽãžãä―æïžäļčĻãŪčĻčĻããģããžïž
# 4. ããđãåŪčĢ
# 5. loopform_builder.rsã§ä―ŋįĻ
# 6. æĒåãģãžãåéĪ
Step 2: BodyLocalPhiBuilderåŪčĢ
# åæ§ãŪæé
touch src/mir/phi_core/body_local_phi_builder.rs
æĪčĻžãã§ããŊãŠãđã
Phase 1åŪäšæ â Phase 26-BåŪäš (2025-11-20)
- PhiInputCollectorãŪåä―ããđãå
Ļéé â
(
33186e1e) - BodyLocalPhiBuilderãŪåä―ããđãå
Ļéé â
(
54f6ce84) - skip_whitespaceã·ããŠãŠã§åä―įĒščŠ â (æĒįĨãŪåéĄãŊåĨIssue)
- æĒåãŪå ĻãđãĒãžãŊããđãéé â (mir_loopform_exit_phi 4/4 PASS)
- [~] ãģãžãåæļ: įŪæĻ140čĄéæ â åŪįļū+1čĄ (Phase 2-3ã§åΧåđ åæļäšåŪ)
- ãããĨãĄãģã: docãģãĄãģãåŪå â
åŪčĢ ææ:
- PhiInputCollector: įĩąäļPHIå Ĩååé (BTreeMapæąšåŪæ§įĒšäŋ)
- BodyLocalPhiBuilder: BodyLocalåĪæ°PHIįæå°éå
- įĩąååŪäš: loopform_builder/loop_builder/json_v0_bridgeå ĻåŊūåŋ
- ãģããã:
33186e1e,54f6ce84,05953387,26288b54
Phase 2åŪäšæ
- LoopSnapshotManagerãŪåä―ããđãå Ļéé
- HeaderPhiBuilderãŪåä―ããđãå Ļéé
- ããžãŋæ§é ãŪäļå åįĒščŠ
- æĒåãŪå ĻãđãĒãžãŊããđãéé
- ãģãžãåæļ: įīŊčĻ380čĄéæ
- äūåéĒäŋåģãŪæĢįĒšæ§įĒščŠ
Phase 3åŪäšæ
- ExitPhiBuilderãŪå æŽįããđãå Ļéé
- Phantom blockéĪåĪãŪåä―įĒščŠ
- BodyLocalExit/BodyLocalInternalåšåĨįĒščŠ
- æĒåãŪå ĻãđãĒãžãŊããđãéé
- ãģãžãåæļ: įīŊčĻ600čĄéæ
- čĪéåšĶæļŽåŪ: æåΧéĒæ°50čĄäŧĨäļįĒščŠ
ð įŪąįčŦãĻãŪæīåæ§įĒščŠ
įŪąįčŦ4åå
1. åéĒ (Separation)
- â PhiInputCollector: PHIå Ĩååéå°é
- â BodyLocalPhiBuilder: BodyLocalåĪåŪå°é
- â HeaderPhiBuilder: Header PHIå°é
- â ExitPhiBuilder: Exit PHIå°é
- â åBoxãŊåäļčēŽäŧŧãŪãŋ
2. åĒį (Boundary)
- â æįĒšãŠtraitåŪįūĐïžPhiMergeOps, LoopFormOpsïž
- â pub/privateãŪéĐåãŠä―ŋãåã
- â äūåéĒäŋãŪäļæđåæ§įĒšäŋ
- â æĻŠæđåãŪäūåãŠãïžæ°īåđģåéĒïž
3. åŊéæ§ (Reversibility)
- â åPhaseãŊįŽįŦïžPhase 1åĪąæã§ãPhase 2åŊč―ïž
- â Feature flagã§æŪĩéįæåđååŊč―
- â æĒååŪčĢ ãĻãŪäļĶčĄéįĻåŊč―ïžį§ŧčĄæéïž
- â ããžãŦãããŊåŪđæïžGitããžãđïž
4. ããđãåŪđææ§ (Testability)
- â åBoxãŪåä―ããđãåŊč―
- â Mockable traitčĻčĻ
- â ããđããŦããŽããļ>90%įŪæĻ
- â įĩąåããđããįŽįŦåŪčĄåŊč―
ð ãŠãđãŊåæãĻčŧ―æļį
ãŠãđãŊäļčͧ
| ãŠãđãŊ | å―ąéŋåšĶ | įšįįĒšį | čŧ―æļį |
|---|---|---|---|
| Phase 3åĪąæ | éŦ | äļ | Phase 1-2ã§åšįĪįĒšįŦãæŪĩéįį§ŧčĄ |
| ãããĐãžããģãđåĢå | äļ | ä― | ããģãããžãŊæļŽåŪãæéĐå |
| æĒåãã°ãŪéĄåĻå | äļ | äļ | å æŽįããđããæŪĩéįãŠãŠãžãđ |
| åŪčĢ æéčķ é | ä― | äļ | PhaseæŊãŦãŋãĪã ãããŊãđčĻåŪ |
Phase 3įđæãŪãŠãđãŊ
åéĄ: ExitPhiBuilderãæãčĪéïž173čĄãŪããļããŊį§ŧčĄïž
čŧ―æļį:
-
æŪĩéįåŪčĢ
- Step 1: Phantom blockéĪåĪãŪãŋåŪčĢ
- Step 2: Body-localåĶįčŋ―å
- Step 3: åŪå Ļį§ŧčĄ
-
äļĶčĄéįĻ
- į°åĒåĪæ°ã§æ°æ§åãæŋãåŊč―ãŦ
NYASH_USE_EXIT_PHI_BUILDER=1ã§æ°åŪčĢ æåđå- ãããĐãŦããŊæ§åŪčĢ ïžåŪå Ļæ§åŠå ïž
-
å æŽįããđã
- skip_whitespaceã·ããŠãŠåŋ é
- Phantom blockã·ããŠãŠåŋ é
- 3+ exit predsã·ããŠãŠåŋ é
ð ãūãĻã
ææĄå åŪđ
6ãĪãŪBoxãŦããPHIįæãģãžããŪåŪå ĻåéĒãææĄããūãïž
- PhiInputCollector - PHIå Ĩååéįĩąäļ
- BodyLocalPhiBuilder - BodyLocalåĪæ°åĶį
- LoopSnapshotManager - Snapshotäļå įŪĄį
- HeaderPhiBuilder - Header PHIå°éå
- ExitPhiBuilder - Exit PHIå°éåïžæéčĶïž
- ValueIdAllocator - ValueIdįŪĄįïžãŠãã·ã§ããŦïž
æåū åđæ
- ðŊ äŋåŪæ§: čēŽäŧŧæįĒšåãæåΧéĒæ°173čĄâ50čĄäŧĨäļ
- ⥠ããđãåŪđææ§: įŽįŦããđãåŊč―ããŦããŽããļ60%â90%
- ð åŊčŠæ§: åBoxãŪå―đåēäļįŪįįķ
- ð ååĐįĻæ§: äŧãŪPHIæčã§ãä―ŋįĻåŊč―
åŪčĢ åŠå é ä―
- Phase 1: PhiInputCollector + BodyLocalPhiBuilderïžåģåđæ§ïž
- Phase 2: LoopSnapshotManager + HeaderPhiBuilderïžæ§é æđåïž
- Phase 3: ExitPhiBuilderïžæéĢéĒãŧæåΧåđæïž
- Phase 4: ValueIdAllocator + ãããĨãĄãģãïžäŧäļãïž
æŽĄãŪãđããã
- æŽčĻįŧãŪãŽããĨãžïžãĶãžãķãžįĒščŠïž
- Phase 1įæåĪæ
- Phase 1åŪčĢ ïž1éąéäŧĨå ïž
- Phase 2åŪčĢ ïž2éąéäŧĨå ïž
- Phase 3åŪčĢ ïž3éąéäŧĨå ïž
įŪąįčŦååãŦåšãĨãæŪĩéįãŠããĄãŊãŋãŠãģã°ã§ãįĒšåŪãŦäŋåŪæ§ãåäļãããūãïž ð