Skip to content

Commit

Permalink
Merge branch 'main' into yihozhang-fix-subsume2
Browse files Browse the repository at this point in the history
  • Loading branch information
saulshanabrook authored Dec 26, 2024
2 parents 9684208 + ca4f533 commit 4820561
Show file tree
Hide file tree
Showing 37 changed files with 1,501 additions and 1,404 deletions.
7 changes: 0 additions & 7 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 5 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,6 @@ lazy_static = "1.4"
num = "0.4.3"
smallvec = "1.11"

generic_symbolic_expressions = "5.0.4"

egraph-serialize = { version = "0.2.0", default-features = false }

# binary dependencies
Expand Down Expand Up @@ -84,3 +82,8 @@ libtest-mimic = "0.6.1"

[profile.release]
incremental = true

# https://github.com/mstange/samply/?tab=readme-ov-file#turn-on-debug-info-for-full-stacks
[profile.profiling]
inherits = "release"
debug = true
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,22 @@ We use 50ms as our cutoff currently, any benchmarks shorter than that are ignore
any benchmarks with have changes > 1% when they haven't been modified. Note that all the ignoring is done manually,
so if you add another example that's short, an admin on the codspeed project will need to manually ignore it.

## Profiling

One way to profile egglog is to use [samply](https://github.com/mstange/samply/). Here's how you can use it:

```bash
# install samply
cargo install --locked samply
# build a profile build which includes debug symbols
cargo build --profile profiling
# run the egglog file and profile
samply record ./target/profiling/egglog tests/extract-vec-bench.egg
# [optional] run the egglog file without logging or printing messages, which can help reduce the stdout
# when you are profiling extracting a large expression
env RUST_LOG=error samply record ./target/profiling/egglog --dont-print-messages tests/extract-vec-bench.egg
```

# Documentation

To view documentation, run `cargo doc --open`.
Expand Down
13 changes: 10 additions & 3 deletions benches/example_benchmarks.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
use codspeed_criterion_compat::{criterion_group, criterion_main, Criterion};
use egglog::EGraph;

fn run_example(filename: &str, program: &str) {
EGraph::default()
fn run_example(filename: &str, program: &str, no_messages: bool) {
let mut egraph = EGraph::default();
if no_messages {
egraph.disable_messages();
}
egraph
.parse_and_run_program(Some(filename.to_owned()), program)
.unwrap();
}
Expand All @@ -17,7 +21,10 @@ pub fn criterion_benchmark(c: &mut Criterion) {
let name = path.file_stem().unwrap().to_string_lossy().to_string();
let filename = path.to_string_lossy().to_string();
let program = std::fs::read_to_string(&filename).unwrap();
c.bench_function(&name, |b| b.iter(|| run_example(&filename, &program)));
let no_messages = path_string.contains("no-messages");
c.bench_function(&name, |b| {
b.iter(|| run_example(&filename, &program, no_messages))
});
}
}

Expand Down
34 changes: 20 additions & 14 deletions src/actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -339,9 +339,12 @@ impl EGraph {
let variants = values[1].bits as i64;
if variants == 0 {
let (cost, term) = self.extract(values[0], &mut termdag, sort);
let extracted = termdag.to_string(&term);
log::info!("extracted with cost {cost}: {extracted}");
self.print_msg(extracted);
// dont turn termdag into a string if we have messages disabled for performance reasons
if self.messages_enabled() {
let extracted = termdag.to_string(&term);
log::info!("extracted with cost {cost}: {extracted}");
self.print_msg(extracted);
}
self.extract_report = Some(ExtractReport::Best {
termdag,
cost,
Expand All @@ -353,17 +356,20 @@ impl EGraph {
}
let terms =
self.extract_variants(sort, values[0], variants as usize, &mut termdag);
log::info!("extracted variants:");
let mut msg = String::default();
msg += "(\n";
assert!(!terms.is_empty());
for expr in &terms {
let str = termdag.to_string(expr);
log::info!(" {str}");
msg += &format!(" {str}\n");
// Same as above, avoid turning termdag into a string if we have messages disabled for performance
if self.messages_enabled() {
log::info!("extracted variants:");
let mut msg = String::default();
msg += "(\n";
assert!(!terms.is_empty());
for expr in &terms {
let str = termdag.to_string(expr);
log::info!(" {str}");
msg += &format!(" {str}\n");
}
msg += ")";
self.print_msg(msg);
}
msg += ")";
self.print_msg(msg);
self.extract_report = Some(ExtractReport::Variants { termdag, terms });
}

Expand All @@ -372,7 +378,7 @@ impl EGraph {
Instruction::Panic(msg) => panic!("Panic: {msg}"),
Instruction::Literal(lit) => match lit {
Literal::Int(i) => stack.push(Value::from(*i)),
Literal::F64(f) => stack.push(Value::from(*f)),
Literal::Float(f) => stack.push(Value::from(*f)),
Literal::String(s) => stack.push(Value::from(*s)),
Literal::Bool(b) => stack.push(Value::from(*b)),
Literal::Unit => stack.push(Value::unit()),
Expand Down
64 changes: 32 additions & 32 deletions src/ast/desugar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ use crate::*;
/// makes rules into a SSA-like format (see [`NormFact`]).
pub(crate) fn desugar_program(
program: Vec<Command>,
symbol_gen: &mut SymbolGen,
parser: &mut Parser,
seminaive_transform: bool,
) -> Result<Vec<NCommand>, Error> {
let mut res = vec![];
for command in program {
let desugared = desugar_command(command, symbol_gen, seminaive_transform)?;
let desugared = desugar_command(command, parser, seminaive_transform)?;
res.extend(desugared);
}
Ok(res)
Expand All @@ -22,7 +22,7 @@ pub(crate) fn desugar_program(
/// makes rules into a SSA-like format (see [`NormFact`]).
pub(crate) fn desugar_command(
command: Command,
symbol_gen: &mut SymbolGen,
parser: &mut Parser,
seminaive_transform: bool,
) -> Result<Vec<NCommand>, Error> {
let res = match command {
Expand Down Expand Up @@ -50,15 +50,9 @@ pub(crate) fn desugar_command(
cost,
unextractable,
))],
Command::Relation {
span,
constructor,
inputs,
} => vec![NCommand::Function(FunctionDecl::relation(
span,
constructor,
inputs,
))],
Command::Relation { span, name, inputs } => vec![NCommand::Function(
FunctionDecl::relation(span, name, inputs),
)],
Command::Datatype {
span,
name,
Expand Down Expand Up @@ -108,28 +102,28 @@ pub(crate) fn desugar_command(

res
}
Command::Rewrite(ruleset, rewrite, subsume) => {
desugar_rewrite(ruleset, rewrite_name(&rewrite).into(), &rewrite, subsume)
Command::Rewrite(ruleset, ref rewrite, subsume) => {
desugar_rewrite(ruleset, rule_name(&command), rewrite, subsume)
}
Command::BiRewrite(ruleset, rewrite) => {
desugar_birewrite(ruleset, rewrite_name(&rewrite).into(), &rewrite)
Command::BiRewrite(ruleset, ref rewrite) => {
desugar_birewrite(ruleset, rule_name(&command), rewrite)
}
Command::Include(span, file) => {
let s = std::fs::read_to_string(&file)
.unwrap_or_else(|_| panic!("{span} Failed to read file {file}"));
return desugar_program(
parse_program(Some(file), &s)?,
symbol_gen,
parse_program(Some(file), &s, parser)?,
parser,
seminaive_transform,
);
}
Command::Rule {
ruleset,
mut name,
rule,
ref rule,
} => {
if name == "".into() {
name = rule.to_string().replace('\"', "'").into();
name = rule_name(&command);
}

let result = vec![NCommand::NormRule {
Expand All @@ -150,7 +144,7 @@ pub(crate) fn desugar_command(
span,
expr,
schedule,
} => desugar_simplify(&expr, &schedule, span, symbol_gen),
} => desugar_simplify(&expr, &schedule, span, parser),
Command::RunSchedule(sched) => {
vec![NCommand::RunSchedule(sched.clone())]
}
Expand All @@ -177,14 +171,15 @@ pub(crate) fn desugar_command(
// ((extract {fresh} {variants}))
// :ruleset {fresh_ruleset})
// (run {fresh_ruleset} 1)
let fresh = symbol_gen.fresh(&"desugar_qextract_var".into());
let fresh_ruleset = symbol_gen.fresh(&"desugar_qextract_ruleset".into());
let fresh_rulename = symbol_gen.fresh(&"desugar_qextract_rulename".into());
let fresh = parser.symbol_gen.fresh(&"desugar_qextract_var".into());
let fresh_ruleset = parser.symbol_gen.fresh(&"desugar_qextract_ruleset".into());
let fresh_rulename = parser.symbol_gen.fresh(&"desugar_qextract_rulename".into());
let rule = Rule {
span: span.clone(),
body: vec![Fact::Eq(
span.clone(),
vec![Expr::Var(span.clone(), fresh), expr.clone()],
Expr::Var(span.clone(), fresh),
expr.clone(),
)],
head: Actions::singleton(Action::Extract(
span.clone(),
Expand Down Expand Up @@ -223,7 +218,7 @@ pub(crate) fn desugar_command(
vec![NCommand::Pop(span, num)]
}
Command::Fail(span, cmd) => {
let mut desugared = desugar_command(*cmd, symbol_gen, seminaive_transform)?;
let mut desugared = desugar_command(*cmd, parser, seminaive_transform)?;

let last = desugared.pop().unwrap();
desugared.push(NCommand::Fail(span, Box::new(last)));
Expand Down Expand Up @@ -293,7 +288,8 @@ fn desugar_rewrite(
span: span.clone(),
body: [Fact::Eq(
span.clone(),
vec![Expr::Var(span, var), rewrite.lhs.clone()],
Expr::Var(span, var),
rewrite.lhs.clone(),
)]
.into_iter()
.chain(rewrite.conditions.clone())
Expand Down Expand Up @@ -326,10 +322,10 @@ fn desugar_simplify(
expr: &Expr,
schedule: &Schedule,
span: Span,
symbol_gen: &mut SymbolGen,
parser: &mut Parser,
) -> Vec<NCommand> {
let mut res = vec![NCommand::Push(1)];
let lhs = symbol_gen.fresh(&"desugar_simplify".into());
let lhs = parser.symbol_gen.fresh(&"desugar_simplify".into());
res.push(NCommand::CoreAction(Action::Let(
span.clone(),
lhs,
Expand All @@ -343,7 +339,7 @@ fn desugar_simplify(
variants: 0,
expr: Expr::Var(span.clone(), lhs),
},
symbol_gen,
parser,
false,
)
.unwrap(),
Expand All @@ -353,6 +349,10 @@ fn desugar_simplify(
res
}

pub(crate) fn rewrite_name(rewrite: &Rewrite) -> String {
rewrite.to_string().replace('\"', "'")
pub fn rule_name<Head, Leaf>(command: &GenericCommand<Head, Leaf>) -> Symbol
where
Head: Clone + Display,
Leaf: Clone + PartialEq + Eq + Hash + Display,
{
command.to_string().replace('\"', "'").into()
}
42 changes: 11 additions & 31 deletions src/ast/expr.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
use super::ToSexp;
use crate::{core::ResolvedCall, *};
use ordered_float::OrderedFloat;
use std::{fmt::Display, hash::Hasher};

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone)]
pub enum Literal {
Int(i64),
F64(OrderedFloat<f64>),
Float(OrderedFloat<f64>),
String(Symbol),
Bool(bool),
Unit,
Expand All @@ -33,14 +32,14 @@ macro_rules! impl_from {
}

impl_from!(Int(i64));
impl_from!(F64(OrderedFloat<f64>));
impl_from!(Float(OrderedFloat<f64>));
impl_from!(String(Symbol));

impl Display for Literal {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match &self {
Literal::Int(i) => Display::fmt(i, f),
Literal::F64(n) => {
Literal::Float(n) => {
// need to display with decimal if there is none
let str = n.to_string();
if let Ok(_num) = str.parse::<i64>() {
Expand Down Expand Up @@ -97,12 +96,6 @@ impl Display for ResolvedVar {
}
}

impl ToSexp for ResolvedVar {
fn to_sexp(&self) -> Sexp {
Sexp::Symbol(self.name.to_string())
}
}

pub type Expr = GenericExpr<Symbol, Symbol>;
/// A generated expression is an expression that is generated by the system
/// and does not have annotations.
Expand Down Expand Up @@ -250,31 +243,18 @@ impl<Head: Clone + Display, Leaf: Hash + Clone + Display + Eq> GenericExpr<Head,
}
}

impl<Head: Display, Leaf: Display> GenericExpr<Head, Leaf> {
/// Converts this expression into a
/// s-expression (symbolic expression).
/// Example: `(Add (Add 2 3) 4)`
pub fn to_sexp(&self) -> Sexp {
let res = match self {
GenericExpr::Lit(_ann, lit) => Sexp::Symbol(lit.to_string()),
GenericExpr::Var(_ann, v) => Sexp::Symbol(v.to_string()),
GenericExpr::Call(_ann, op, children) => Sexp::List(
vec![Sexp::Symbol(op.to_string())]
.into_iter()
.chain(children.iter().map(|c| c.to_sexp()))
.collect(),
),
};
res
}
}

impl<Head, Leaf> Display for GenericExpr<Head, Leaf>
where
Head: Display,
Leaf: Display,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.to_sexp())
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
match self {
GenericExpr::Lit(_ann, lit) => write!(f, "{lit}"),
GenericExpr::Var(_ann, var) => write!(f, "{var}"),
GenericExpr::Call(_ann, op, children) => {
write!(f, "({} {})", op, ListDisplay(children, " "))
}
}
}
}
Loading

0 comments on commit 4820561

Please sign in to comment.