Optimizations to egraph framework (#5391)

* Optimizations to egraph framework:

- Save elaborated results by canonical value, not latest value (union
  value). Previously we were artificially skipping and re-elaborating
  some values we already had because we were not finding them in the
  map.

- Make some changes to handling of icmp results: when icmp became
  I8-typed (when bools went away), many uses became `(uextend $I32 (icmp
  $I8 ...))`, and so patterns in lowering backends were no longer
  matching.

  This PR includes an x64-specific change to match `(brz (uextend (icmp
  ...)))` and similarly for `brnz`, but it also takes advantage of the
  ability to write rules easily in the egraph mid-end to rewrite selects
  with icmp inputs appropriately.

- Extend constprop to understand selects in the egraph mid-end.

With these changes, bz2.wasm sees a ~1% speedup, and spidermonkey.wasm
with a fib.js input sees a 16.8% speedup:

```
$ time taskset 1 target/release/wasmtime run --allow-precompiled --dir=. ./spidermonkey.base.cwasm ./fib.js
1346269
taskset 1 target/release/wasmtime run --allow-precompiled --dir=.  ./fib.js  2.14s user 0.01s system 99% cpu 2.148 total
$ time taskset 1 target/release/wasmtime run --allow-precompiled --dir=. ./spidermonkey.egraphs.cwasm ./fib.js
1346269
taskset 1 target/release/wasmtime run --allow-precompiled --dir=.  ./fib.js  1.78s user 0.01s system 99% cpu 1.788 total
```

* Review feedback.
This commit is contained in:
Chris Fallin
2022-12-07 13:23:13 -08:00
committed by GitHub
parent c5379051c4
commit 8c55b81300
8 changed files with 90 additions and 41 deletions

View File

@@ -277,7 +277,7 @@ impl<'a> Elaborator<'a> {
let value = self.func.dfg.resolve_aliases(value);
self.stats.elaborate_visit_node += 1;
let canonical_value = self.eclasses.find(value);
let canonical_value = self.eclasses.find_and_update(value);
debug_assert_ne!(canonical_value, Value::reserved_value());
trace!(
"elaborate: value {} canonical {} before {}",
@@ -518,8 +518,9 @@ impl<'a> Elaborator<'a> {
value: new_result,
in_block: insert_block,
};
let canonical_result = self.eclasses.find_and_update(result);
self.value_to_elaborated_value.insert_if_absent_with_depth(
result,
canonical_result,
elab_value,
scope_depth,
);
@@ -545,8 +546,9 @@ impl<'a> Elaborator<'a> {
value: result,
in_block: insert_block,
};
let canonical_result = self.eclasses.find_and_update(result);
self.value_to_elaborated_value.insert_if_absent_with_depth(
result,
canonical_result,
elab_value,
scope_depth,
);
@@ -623,8 +625,9 @@ impl<'a> Elaborator<'a> {
// map now.
for &result in self.func.dfg.inst_results(inst) {
trace!(" -> result {}", result);
let canonical_result = self.eclasses.find_and_update(result);
self.value_to_elaborated_value.insert_if_absent(
result,
canonical_result,
ElaboratedValue {
in_block: block,
value: result,