egraphs: a few miscellaneous compile-time optimizations. (#5072)
* egraphs: a few miscellaneous compile-time optimizations. These optimizations together are worth about a 2% compile-time reduction, as measured on one core with spidermonkey.wasm as an input, using `hyperfine` on `wasmtime compile`. The changes included are: - Some better pre-allocation (blockparams and side-effects concatenated list vecs); - Avoiding the indirection of storing list-of-types for every Pure and Inst node, when almost all nodes produce only a single result; instead, store arity and single type if it exists, and allow result projection nodes to fill in types otherwise; - Pack the `MemoryState` enum into one `u32` (this together with the above removal of the type slice allows `Node` to shrink from 48 bytes to 32 bytes); - always-inline an accessor (`entry` on `CtxHash`) that wasn't (`always(inline)` appears to be load-bearing, rather than just `inline`); - Split the update-analysis path into two hotpaths, one for the union case and one for the new-node case (and the former can avoid recomputing for the contained node when replacing a node with node-and-child eclass entry). * Review feedback. * Fix test build. * Fix to lowering when unused output with invalid type is present.
This commit is contained in:
@@ -66,7 +66,11 @@ enum ElabStackEntry {
|
||||
},
|
||||
/// Waiting for a result to return one projected value of a
|
||||
/// multi-value result.
|
||||
PendingProjection { canonical: Id, index: usize },
|
||||
PendingProjection {
|
||||
canonical: Id,
|
||||
index: usize,
|
||||
ty: Type,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
@@ -189,15 +193,15 @@ impl<'a> Elaborator<'a> {
|
||||
}
|
||||
|
||||
fn add_node(&mut self, node: &Node, args: &[Value], to_block: Block) -> ValueList {
|
||||
let (instdata, result_tys) = match node {
|
||||
Node::Pure { op, types, .. } | Node::Inst { op, types, .. } => (
|
||||
let (instdata, result_ty, arity) = match node {
|
||||
Node::Pure { op, ty, arity, .. } | Node::Inst { op, ty, arity, .. } => (
|
||||
op.with_args(args, &mut self.func.dfg.value_lists),
|
||||
types.as_slice(&self.node_ctx.types),
|
||||
),
|
||||
Node::Load { op, ty, .. } => (
|
||||
op.with_args(args, &mut self.func.dfg.value_lists),
|
||||
std::slice::from_ref(ty),
|
||||
*ty,
|
||||
*arity,
|
||||
),
|
||||
Node::Load { op, ty, .. } => {
|
||||
(op.with_args(args, &mut self.func.dfg.value_lists), *ty, 1)
|
||||
}
|
||||
_ => panic!("Cannot `add_node()` on block param or projection"),
|
||||
};
|
||||
let srcloc = match node {
|
||||
@@ -237,8 +241,12 @@ impl<'a> Elaborator<'a> {
|
||||
let inst = self.func.dfg.make_inst(instdata);
|
||||
self.func.srclocs[inst] = srcloc;
|
||||
|
||||
for &ty in result_tys {
|
||||
self.func.dfg.append_result(inst, ty);
|
||||
if arity == 1 {
|
||||
self.func.dfg.append_result(inst, result_ty);
|
||||
} else {
|
||||
for _ in 0..arity {
|
||||
self.func.dfg.append_result(inst, crate::ir::types::INVALID);
|
||||
}
|
||||
}
|
||||
|
||||
if is_terminator_group_inst {
|
||||
@@ -371,11 +379,15 @@ impl<'a> Elaborator<'a> {
|
||||
// the value we are projecting a part of, then
|
||||
// eventually return here (saving state with a
|
||||
// PendingProjection).
|
||||
if let Node::Result { value, result, .. } = node {
|
||||
if let Node::Result {
|
||||
value, result, ty, ..
|
||||
} = node
|
||||
{
|
||||
trace!(" -> result; pushing arg value {}", value);
|
||||
self.elab_stack.push(ElabStackEntry::PendingProjection {
|
||||
index: *result,
|
||||
canonical,
|
||||
ty: *ty,
|
||||
});
|
||||
self.elab_stack.push(ElabStackEntry::Start { id: *value });
|
||||
continue;
|
||||
@@ -493,7 +505,11 @@ impl<'a> Elaborator<'a> {
|
||||
// Push onto the elab-results stack.
|
||||
self.elab_result_stack.push(result)
|
||||
}
|
||||
&ElabStackEntry::PendingProjection { index, canonical } => {
|
||||
&ElabStackEntry::PendingProjection {
|
||||
ty,
|
||||
index,
|
||||
canonical,
|
||||
} => {
|
||||
self.elab_stack.pop();
|
||||
|
||||
// Grab the input from the elab-result stack.
|
||||
@@ -511,10 +527,12 @@ impl<'a> Elaborator<'a> {
|
||||
}
|
||||
};
|
||||
let values = values.as_slice(&self.func.dfg.value_lists);
|
||||
let value = values[index];
|
||||
self.func.dfg.fill_in_value_type(value, ty);
|
||||
let value = IdValue::Value {
|
||||
depth,
|
||||
block,
|
||||
value: values[index],
|
||||
value,
|
||||
};
|
||||
self.id_to_value.insert_if_absent(canonical, value.clone());
|
||||
|
||||
|
||||
Reference in New Issue
Block a user