phase29an(p12): project exitmap kinds into canonical facts
This commit is contained in:
@ -2,21 +2,31 @@
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
use crate::mir::builder::control_flow::plan::facts::feature_facts::ExitUsageFacts;
|
||||
use crate::mir::builder::control_flow::plan::facts::feature_facts::{
|
||||
ExitKindFacts, ExitUsageFacts,
|
||||
};
|
||||
use crate::mir::builder::control_flow::plan::facts::skeleton_facts::SkeletonKind;
|
||||
use crate::mir::builder::control_flow::plan::facts::LoopFacts;
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub(in crate::mir::builder) struct CanonicalLoopFacts {
|
||||
pub facts: LoopFacts,
|
||||
pub skeleton_kind: SkeletonKind,
|
||||
pub exit_usage: ExitUsageFacts,
|
||||
pub exit_kinds_present: BTreeSet<ExitKindFacts>,
|
||||
}
|
||||
|
||||
pub(in crate::mir::builder) fn canonicalize_loop_facts(facts: LoopFacts) -> CanonicalLoopFacts {
|
||||
CanonicalLoopFacts {
|
||||
skeleton_kind: facts.skeleton.kind,
|
||||
exit_usage: facts.features.exit_usage.clone(),
|
||||
exit_kinds_present: facts
|
||||
.features
|
||||
.exit_map
|
||||
.as_ref()
|
||||
.map(|map| map.kinds_present.clone())
|
||||
.unwrap_or_default(),
|
||||
facts,
|
||||
}
|
||||
}
|
||||
@ -25,11 +35,15 @@ pub(in crate::mir::builder) fn canonicalize_loop_facts(facts: LoopFacts) -> Cano
|
||||
mod tests {
|
||||
use super::canonicalize_loop_facts;
|
||||
use crate::ast::{ASTNode, BinaryOperator, LiteralValue, Span};
|
||||
use crate::mir::builder::control_flow::plan::facts::feature_facts::{
|
||||
ExitKindFacts, ExitMapFacts, ExitUsageFacts, LoopFeatureFacts,
|
||||
};
|
||||
use crate::mir::builder::control_flow::plan::facts::loop_facts::LoopFacts;
|
||||
use crate::mir::builder::control_flow::plan::facts::scan_shapes::{
|
||||
ConditionShape, StepShape,
|
||||
};
|
||||
use crate::mir::builder::control_flow::plan::facts::skeleton_facts::SkeletonKind;
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
fn v(name: &str) -> ASTNode {
|
||||
ASTNode::Variable {
|
||||
@ -47,23 +61,26 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn canonical_projects_skeleton_and_exit_usage() {
|
||||
let mut kinds_present = BTreeSet::new();
|
||||
kinds_present.insert(ExitKindFacts::Break);
|
||||
kinds_present.insert(ExitKindFacts::Continue);
|
||||
kinds_present.insert(ExitKindFacts::Return);
|
||||
let facts = LoopFacts {
|
||||
condition_shape: ConditionShape::Unknown,
|
||||
step_shape: StepShape::Unknown,
|
||||
skeleton: crate::mir::builder::control_flow::plan::facts::skeleton_facts::SkeletonFacts {
|
||||
kind: SkeletonKind::Loop,
|
||||
},
|
||||
features:
|
||||
crate::mir::builder::control_flow::plan::facts::feature_facts::LoopFeatureFacts {
|
||||
exit_usage:
|
||||
crate::mir::builder::control_flow::plan::facts::feature_facts::ExitUsageFacts {
|
||||
has_break: true,
|
||||
has_continue: true,
|
||||
has_return: true,
|
||||
},
|
||||
value_join: None,
|
||||
cleanup: None,
|
||||
features: LoopFeatureFacts {
|
||||
exit_usage: ExitUsageFacts {
|
||||
has_break: true,
|
||||
has_continue: true,
|
||||
has_return: true,
|
||||
},
|
||||
exit_map: Some(ExitMapFacts { kinds_present }),
|
||||
value_join: None,
|
||||
cleanup: None,
|
||||
},
|
||||
scan_with_init: None,
|
||||
split_scan: None,
|
||||
pattern1_simplewhile: None,
|
||||
@ -80,6 +97,34 @@ mod tests {
|
||||
assert!(canonical.exit_usage.has_break);
|
||||
assert!(canonical.exit_usage.has_continue);
|
||||
assert!(canonical.exit_usage.has_return);
|
||||
assert_eq!(canonical.exit_kinds_present.len(), 3);
|
||||
assert!(canonical.exit_kinds_present.contains(&ExitKindFacts::Break));
|
||||
assert!(canonical.exit_kinds_present.contains(&ExitKindFacts::Continue));
|
||||
assert!(canonical.exit_kinds_present.contains(&ExitKindFacts::Return));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn canonical_projects_empty_exit_kinds_present() {
|
||||
let facts = LoopFacts {
|
||||
condition_shape: ConditionShape::Unknown,
|
||||
step_shape: StepShape::Unknown,
|
||||
skeleton: crate::mir::builder::control_flow::plan::facts::skeleton_facts::SkeletonFacts {
|
||||
kind: SkeletonKind::Loop,
|
||||
},
|
||||
features: LoopFeatureFacts::default(),
|
||||
scan_with_init: None,
|
||||
split_scan: None,
|
||||
pattern1_simplewhile: None,
|
||||
pattern3_ifphi: None,
|
||||
pattern4_continue: None,
|
||||
pattern5_infinite_early_exit: None,
|
||||
pattern8_bool_predicate_scan: None,
|
||||
pattern9_accum_const_loop: None,
|
||||
pattern2_break: None,
|
||||
pattern2_loopbodylocal: None,
|
||||
};
|
||||
let canonical = canonicalize_loop_facts(facts);
|
||||
assert!(canonical.exit_kinds_present.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -90,8 +135,7 @@ mod tests {
|
||||
skeleton: crate::mir::builder::control_flow::plan::facts::skeleton_facts::SkeletonFacts {
|
||||
kind: SkeletonKind::Loop,
|
||||
},
|
||||
features:
|
||||
crate::mir::builder::control_flow::plan::facts::feature_facts::LoopFeatureFacts::default(),
|
||||
features: LoopFeatureFacts::default(),
|
||||
scan_with_init: None,
|
||||
split_scan: None,
|
||||
pattern1_simplewhile: Some(
|
||||
|
||||
@ -4,9 +4,12 @@
|
||||
|
||||
use crate::ast::ASTNode;
|
||||
|
||||
use crate::mir::builder::control_flow::plan::facts::feature_facts::ExitUsageFacts;
|
||||
use crate::mir::builder::control_flow::plan::facts::feature_facts::{
|
||||
ExitKindFacts, ExitUsageFacts,
|
||||
};
|
||||
use crate::mir::builder::control_flow::plan::facts::skeleton_facts::SkeletonKind;
|
||||
use crate::mir::builder::control_flow::plan::normalize::CanonicalLoopFacts;
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use super::candidates::{CandidateSet, PlanCandidate};
|
||||
use super::context::PlannerContext;
|
||||
@ -84,7 +87,26 @@ fn infer_exit_usage(facts: &CanonicalLoopFacts) -> Option<ExitUsageFacts> {
|
||||
}
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
fn debug_assert_exit_usage_matches_plan(plan: &DomainPlan, exit_usage: &ExitUsageFacts) {
|
||||
fn debug_assert_exit_usage_matches_plan(
|
||||
plan: &DomainPlan,
|
||||
exit_usage: &ExitUsageFacts,
|
||||
exit_kinds_present: &BTreeSet<ExitKindFacts>,
|
||||
) {
|
||||
debug_assert_eq!(
|
||||
exit_usage.has_break,
|
||||
exit_kinds_present.contains(&ExitKindFacts::Break),
|
||||
"exit usage break presence mismatch"
|
||||
);
|
||||
debug_assert_eq!(
|
||||
exit_usage.has_continue,
|
||||
exit_kinds_present.contains(&ExitKindFacts::Continue),
|
||||
"exit usage continue presence mismatch"
|
||||
);
|
||||
debug_assert_eq!(
|
||||
exit_usage.has_return,
|
||||
exit_kinds_present.contains(&ExitKindFacts::Return),
|
||||
"exit usage return presence mismatch"
|
||||
);
|
||||
match plan {
|
||||
DomainPlan::Pattern1SimpleWhile(_) => {
|
||||
debug_assert!(
|
||||
@ -111,7 +133,12 @@ fn debug_assert_exit_usage_matches_plan(plan: &DomainPlan, exit_usage: &ExitUsag
|
||||
}
|
||||
|
||||
#[cfg(not(debug_assertions))]
|
||||
fn debug_assert_exit_usage_matches_plan(_plan: &DomainPlan, _exit_usage: &ExitUsageFacts) {}
|
||||
fn debug_assert_exit_usage_matches_plan(
|
||||
_plan: &DomainPlan,
|
||||
_exit_usage: &ExitUsageFacts,
|
||||
_exit_kinds_present: &BTreeSet<ExitKindFacts>,
|
||||
) {
|
||||
}
|
||||
|
||||
fn push_scan_with_init(candidates: &mut CandidateSet, facts: &CanonicalLoopFacts) {
|
||||
let Some(scan) = &facts.facts.scan_with_init else {
|
||||
@ -170,7 +197,7 @@ fn push_pattern2_break(candidates: &mut CandidateSet, facts: &CanonicalLoopFacts
|
||||
loop_increment: pattern2.loop_increment.clone(),
|
||||
promotion,
|
||||
});
|
||||
debug_assert_exit_usage_matches_plan(&plan, &facts.exit_usage);
|
||||
debug_assert_exit_usage_matches_plan(&plan, &facts.exit_usage, &facts.exit_kinds_present);
|
||||
candidates.push(PlanCandidate {
|
||||
plan,
|
||||
rule: "loop/pattern2_break",
|
||||
@ -207,7 +234,7 @@ fn push_pattern4_continue(candidates: &mut CandidateSet, facts: &CanonicalLoopFa
|
||||
carrier_updates: pattern4.carrier_updates.clone(),
|
||||
loop_increment: pattern4.loop_increment.clone(),
|
||||
});
|
||||
debug_assert_exit_usage_matches_plan(&plan, &facts.exit_usage);
|
||||
debug_assert_exit_usage_matches_plan(&plan, &facts.exit_usage, &facts.exit_kinds_present);
|
||||
candidates.push(PlanCandidate {
|
||||
plan,
|
||||
rule: "loop/pattern4_continue",
|
||||
@ -227,7 +254,7 @@ fn push_pattern5_infinite_early_exit(candidates: &mut CandidateSet, facts: &Cano
|
||||
carrier_update: pattern5.carrier_update.clone(),
|
||||
loop_increment: pattern5.loop_increment.clone(),
|
||||
});
|
||||
debug_assert_exit_usage_matches_plan(&plan, &facts.exit_usage);
|
||||
debug_assert_exit_usage_matches_plan(&plan, &facts.exit_usage, &facts.exit_kinds_present);
|
||||
candidates.push(PlanCandidate {
|
||||
plan,
|
||||
rule: "loop/pattern5_infinite_early_exit",
|
||||
@ -290,7 +317,7 @@ fn push_pattern1_simplewhile(
|
||||
condition: pattern1.condition.clone(),
|
||||
loop_increment: pattern1.loop_increment.clone(),
|
||||
});
|
||||
debug_assert_exit_usage_matches_plan(&plan, &facts.exit_usage);
|
||||
debug_assert_exit_usage_matches_plan(&plan, &facts.exit_usage, &facts.exit_kinds_present);
|
||||
candidates.push(PlanCandidate {
|
||||
plan,
|
||||
rule: "loop/pattern1_simplewhile",
|
||||
@ -304,7 +331,7 @@ mod tests {
|
||||
ConditionShape, StepShape,
|
||||
};
|
||||
use crate::mir::builder::control_flow::plan::facts::feature_facts::{
|
||||
ExitUsageFacts, LoopFeatureFacts,
|
||||
ExitKindFacts, ExitMapFacts, ExitUsageFacts, LoopFeatureFacts,
|
||||
};
|
||||
use crate::mir::builder::control_flow::plan::facts::loop_facts::{
|
||||
LoopFacts, ScanWithInitFacts, SplitScanFacts,
|
||||
@ -337,7 +364,7 @@ mod tests {
|
||||
use crate::mir::builder::control_flow::plan::normalize::canonicalize_loop_facts;
|
||||
use crate::mir::builder::control_flow::plan::{Pattern2PromotionHint, Pattern5ExitKind};
|
||||
use crate::ast::{ASTNode, BinaryOperator, LiteralValue, Span};
|
||||
use std::collections::BTreeMap;
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
|
||||
fn v(name: &str) -> ASTNode {
|
||||
ASTNode::Variable {
|
||||
@ -353,6 +380,30 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
fn feature_facts_with_usage(exit_usage: ExitUsageFacts) -> LoopFeatureFacts {
|
||||
let mut kinds_present = BTreeSet::new();
|
||||
if exit_usage.has_return {
|
||||
kinds_present.insert(ExitKindFacts::Return);
|
||||
}
|
||||
if exit_usage.has_break {
|
||||
kinds_present.insert(ExitKindFacts::Break);
|
||||
}
|
||||
if exit_usage.has_continue {
|
||||
kinds_present.insert(ExitKindFacts::Continue);
|
||||
}
|
||||
let exit_map = if kinds_present.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(ExitMapFacts { kinds_present })
|
||||
};
|
||||
LoopFeatureFacts {
|
||||
exit_usage,
|
||||
exit_map,
|
||||
value_join: None,
|
||||
cleanup: None,
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn planner_builds_split_scan_plan_from_facts() {
|
||||
let facts = LoopFacts {
|
||||
@ -462,15 +513,11 @@ mod tests {
|
||||
skeleton: SkeletonFacts {
|
||||
kind: SkeletonKind::Loop,
|
||||
},
|
||||
features: LoopFeatureFacts {
|
||||
exit_usage: ExitUsageFacts {
|
||||
has_break: true,
|
||||
has_continue: false,
|
||||
has_return: false,
|
||||
},
|
||||
value_join: None,
|
||||
cleanup: None,
|
||||
},
|
||||
features: feature_facts_with_usage(ExitUsageFacts {
|
||||
has_break: true,
|
||||
has_continue: false,
|
||||
has_return: false,
|
||||
}),
|
||||
scan_with_init: Some(ScanWithInitFacts {
|
||||
loop_var: "i".to_string(),
|
||||
haystack: "s".to_string(),
|
||||
@ -647,15 +694,11 @@ mod tests {
|
||||
skeleton: SkeletonFacts {
|
||||
kind: SkeletonKind::Loop,
|
||||
},
|
||||
features: LoopFeatureFacts {
|
||||
exit_usage: ExitUsageFacts {
|
||||
has_break: true,
|
||||
has_continue: false,
|
||||
has_return: false,
|
||||
},
|
||||
value_join: None,
|
||||
cleanup: None,
|
||||
},
|
||||
features: feature_facts_with_usage(ExitUsageFacts {
|
||||
has_break: true,
|
||||
has_continue: false,
|
||||
has_return: false,
|
||||
}),
|
||||
scan_with_init: None,
|
||||
split_scan: None,
|
||||
pattern1_simplewhile: None,
|
||||
@ -702,15 +745,11 @@ mod tests {
|
||||
skeleton: SkeletonFacts {
|
||||
kind: SkeletonKind::Loop,
|
||||
},
|
||||
features: LoopFeatureFacts {
|
||||
exit_usage: ExitUsageFacts {
|
||||
has_break: true,
|
||||
has_continue: false,
|
||||
has_return: false,
|
||||
},
|
||||
value_join: None,
|
||||
cleanup: None,
|
||||
},
|
||||
features: feature_facts_with_usage(ExitUsageFacts {
|
||||
has_break: true,
|
||||
has_continue: false,
|
||||
has_return: false,
|
||||
}),
|
||||
scan_with_init: None,
|
||||
split_scan: None,
|
||||
pattern1_simplewhile: Some(Pattern1SimpleWhileFacts {
|
||||
@ -834,15 +873,11 @@ mod tests {
|
||||
skeleton: SkeletonFacts {
|
||||
kind: SkeletonKind::Loop,
|
||||
},
|
||||
features: LoopFeatureFacts {
|
||||
exit_usage: ExitUsageFacts {
|
||||
has_break: false,
|
||||
has_continue: true,
|
||||
has_return: false,
|
||||
},
|
||||
value_join: None,
|
||||
cleanup: None,
|
||||
},
|
||||
features: feature_facts_with_usage(ExitUsageFacts {
|
||||
has_break: false,
|
||||
has_continue: true,
|
||||
has_return: false,
|
||||
}),
|
||||
scan_with_init: None,
|
||||
split_scan: None,
|
||||
pattern1_simplewhile: None,
|
||||
@ -893,15 +928,11 @@ mod tests {
|
||||
skeleton: SkeletonFacts {
|
||||
kind: SkeletonKind::Loop,
|
||||
},
|
||||
features: LoopFeatureFacts {
|
||||
exit_usage: ExitUsageFacts {
|
||||
has_break: false,
|
||||
has_continue: false,
|
||||
has_return: true,
|
||||
},
|
||||
value_join: None,
|
||||
cleanup: None,
|
||||
},
|
||||
features: feature_facts_with_usage(ExitUsageFacts {
|
||||
has_break: false,
|
||||
has_continue: false,
|
||||
has_return: true,
|
||||
}),
|
||||
scan_with_init: None,
|
||||
split_scan: None,
|
||||
pattern1_simplewhile: None,
|
||||
@ -953,15 +984,11 @@ mod tests {
|
||||
skeleton: SkeletonFacts {
|
||||
kind: SkeletonKind::Loop,
|
||||
},
|
||||
features: LoopFeatureFacts {
|
||||
exit_usage: ExitUsageFacts {
|
||||
has_break: true,
|
||||
has_continue: false,
|
||||
has_return: false,
|
||||
},
|
||||
value_join: None,
|
||||
cleanup: None,
|
||||
},
|
||||
features: feature_facts_with_usage(ExitUsageFacts {
|
||||
has_break: true,
|
||||
has_continue: false,
|
||||
has_return: false,
|
||||
}),
|
||||
scan_with_init: None,
|
||||
split_scan: None,
|
||||
pattern1_simplewhile: None,
|
||||
|
||||
Reference in New Issue
Block a user