Skip to content

Commit

Permalink
add ExprUsesArgs analysis
Browse files Browse the repository at this point in the history
  • Loading branch information
yihozhang committed Jan 27, 2024
1 parent 4f26ab3 commit 7d2c619
Show file tree
Hide file tree
Showing 3 changed files with 135 additions and 0 deletions.
129 changes: 129 additions & 0 deletions tree_unique_args/src/arg_used_analysis.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
use crate::ir::{Constructor, ESort, Purpose};
use strum::IntoEnumIterator;

fn arg_used_rule_for_ctor(ctor: Constructor) -> Option<String> {
if ctor == Constructor::Arg {
return Some(format!(
"
(rule (
(ExprUsesArgs-demand e)
(= e (Get (Arg id) i))
) (
(set (ExprUsesArgs e) (set-of i))
)
:ruleset always-run)"
));
}

let children_queries = ctor
.filter_map_fields(|field| match field.purpose {
Purpose::Static(_)
| Purpose::CapturingId
| Purpose::ReferencingId
| Purpose::CapturedExpr => None,
Purpose::SubExpr | Purpose::SubListExpr => {
let var = field.var();
let sort = field.sort().name();
Some(format!("(= args-{var} ({sort}UsesArgs {var}))"))
}
})
.join(" ");

let children_demand = ctor
.filter_map_fields(|field| match field.purpose {
Purpose::Static(_)
| Purpose::CapturingId
| Purpose::ReferencingId
| Purpose::CapturedExpr => None,
Purpose::SubExpr | Purpose::SubListExpr => {
let var = field.var();
let sort = field.sort().name();
Some(format!("({sort}UsesArgs-demand {var})"))
}
})
.join(" ");

let fields = ctor
.fields()
.into_iter()
.filter(|field| field.purpose == Purpose::SubExpr || field.purpose == Purpose::SubListExpr)
.collect::<Vec<_>>();
let union_expr = match fields.len() {
0 => return None,
1 => format!("args-{}", fields[0].var()),
_ => {
let mut union_expr = vec![];
let (last_field, fields) = fields.split_last().unwrap();
for field in fields {
let var = field.var();
union_expr.push(format!("(set-union args-{var} "));
}
union_expr.push(format!("args-{}", last_field.var()));
for _ in fields {
union_expr.push(")".into());
}
union_expr.join(" ")
}
};

let ctor_pattern = ctor.construct(|field| field.var());

let sort = ctor.sort().name();
Some(format!(
"
;; propagation of demand
(rule (
({sort}UsesArgs-demand e)
(= e {ctor_pattern})
) (
{children_demand}
)
:ruleset always-run)
;; collecting set of args
(rule (
({sort}UsesArgs-demand e)
(= e {ctor_pattern})
{children_queries}
) (
(set ({sort}UsesArgs e) {union_expr})
)
:ruleset always-run)"
))
}

pub(crate) fn arg_used_analysis_rules() -> Vec<String> {
ESort::iter()
.map(|sort| {
"
(function *UsesArgs (*) I64Set :merge (set-union old new))
(relation *UsesArgs-demand (*))
(rule ((*UsesArgs-demand e))
((set (*UsesArgs e) (set-empty))) :ruleset always-run)
"
.replace('*', sort.name())
})
.chain(Constructor::iter().filter_map(arg_used_rule_for_ctor))
.collect::<Vec<_>>()
}

#[test]
fn test_args_used_analysis() -> Result<(), egglog::Error> {
let build = &*"
(let id1 (Id (i64-fresh!)))
(let id2 (Id (i64-fresh!)))
(let expr1
(All (Parallel) (Pair (Let id2 (All (Parallel) (Pair (Get (Arg id1) 3)
(Num id1 1)))
(Get (Arg id2) 0))
(Add (Get (Arg id1) 1)
(Get (Arg id1) 2)))))
(ExprUsesArgs-demand expr1)
"
.to_string();
let check = "
(check (= (ExprUsesArgs expr1) (set-of 1 2 3)))
";
crate::run_test(build, check)
}
2 changes: 2 additions & 0 deletions tree_unique_args/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub(crate) mod arg_used_analysis;
pub mod ast;
pub(crate) mod body_contains;
pub(crate) mod conditional_invariant_code_motion;
Expand Down Expand Up @@ -137,6 +138,7 @@ pub fn run_test(build: &str, check: &str) -> Result {
&is_valid::rules().join("\n"),
&purity_analysis::purity_analysis_rules().join("\n"),
&body_contains::rules().join("\n"),
&arg_used_analysis::arg_used_analysis_rules().join("\n"),
&subst::subst_rules().join("\n"),
&deep_copy::deep_copy_rules().join("\n"),
include_str!("sugar.egg"),
Expand Down
4 changes: 4 additions & 0 deletions tree_unique_args/src/schema.egg
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
;; container definitions

(sort I64Set (Set i64))

; We could generate this from ir.rs, this manual version is just easier reference.

(sort IdSort)
Expand Down

0 comments on commit 7d2c619

Please sign in to comment.