Skip to content

Commit e118fbb

Browse files
committed
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 ```
1 parent 29b23d4 commit e118fbb

6 files changed

Lines changed: 60 additions & 7 deletions

File tree

cranelift/codegen/src/egraph/elaborate.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ impl<'a> Elaborator<'a> {
277277
let value = self.func.dfg.resolve_aliases(value);
278278

279279
self.stats.elaborate_visit_node += 1;
280-
let canonical_value = self.eclasses.find(value);
280+
let canonical_value = self.eclasses.find_and_update(value);
281281
debug_assert_ne!(canonical_value, Value::reserved_value());
282282
trace!(
283283
"elaborate: value {} canonical {} before {}",
@@ -518,8 +518,9 @@ impl<'a> Elaborator<'a> {
518518
value: new_result,
519519
in_block: insert_block,
520520
};
521+
let canonical_result = self.eclasses.find_and_update(result);
521522
self.value_to_elaborated_value.insert_if_absent_with_depth(
522-
result,
523+
canonical_result,
523524
elab_value,
524525
scope_depth,
525526
);
@@ -545,8 +546,9 @@ impl<'a> Elaborator<'a> {
545546
value: result,
546547
in_block: insert_block,
547548
};
549+
let canonical_result = self.eclasses.find_and_update(result);
548550
self.value_to_elaborated_value.insert_if_absent_with_depth(
549-
result,
551+
canonical_result,
550552
elab_value,
551553
scope_depth,
552554
);
@@ -623,8 +625,9 @@ impl<'a> Elaborator<'a> {
623625
// map now.
624626
for &result in self.func.dfg.inst_results(inst) {
625627
trace!(" -> result {}", result);
628+
let canonical_result = self.eclasses.find_and_update(result);
626629
self.value_to_elaborated_value.insert_if_absent(
627-
result,
630+
canonical_result,
628631
ElaboratedValue {
629632
in_block: block,
630633
value: result,

cranelift/codegen/src/isa/x64/lower.isle

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2903,7 +2903,11 @@
29032903
(let ((cmp IcmpCondResult (invert_icmp_cond_result (emit_cmp cc a b))))
29042904
(side_effect (jmp_cond_icmp cmp taken not_taken))))
29052905

2906-
(rule 2 (lower_branch (brz (fcmp cc a b) _ _) (two_targets taken not_taken))
2906+
(rule 2 (lower_branch (brz (uextend (icmp cc a b)) _ _) (two_targets taken not_taken))
2907+
(let ((cmp IcmpCondResult (invert_icmp_cond_result (emit_cmp cc a b))))
2908+
(side_effect (jmp_cond_icmp cmp taken not_taken))))
2909+
2910+
(rule 2 (lower_branch (brz (uextend (fcmp cc a b)) _ _) (two_targets taken not_taken))
29072911
(let ((cmp FcmpCondResult (emit_fcmp (floatcc_inverse cc) a b)))
29082912
(side_effect (jmp_cond_fcmp cmp taken not_taken))))
29092913

@@ -2923,6 +2927,13 @@
29232927
(let ((cmp FcmpCondResult (emit_fcmp cc a b)))
29242928
(side_effect (jmp_cond_fcmp cmp taken not_taken))))
29252929

2930+
(rule 2 (lower_branch (brnz (uextend (icmp cc a b)) _ _) (two_targets taken not_taken))
2931+
(side_effect (jmp_cond_icmp (emit_cmp cc a b) taken not_taken)))
2932+
2933+
(rule 2 (lower_branch (brnz (uextend (fcmp cc a b)) _ _) (two_targets taken not_taken))
2934+
(let ((cmp FcmpCondResult (emit_fcmp cc a b)))
2935+
(side_effect (jmp_cond_fcmp cmp taken not_taken))))
2936+
29262937
(rule 1 (lower_branch (brnz val @ (value_type $I128) _ _) (two_targets taken not_taken))
29272938
(side_effect (jmp_cond_icmp (cmp_zero_i128 (CC.Z) val) taken not_taken)))
29282939

cranelift/codegen/src/isle_prelude.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -607,5 +607,11 @@ macro_rules! isle_common_prelude_methods {
607607
fn pack_value_array_3(&mut self, a: Value, b: Value, c: Value) -> ValueArray3 {
608608
[a, b, c]
609609
}
610+
611+
#[inline]
612+
fn intcc_invert(&mut self, cc: &IntCC) -> IntCC {
613+
use crate::ir::condcodes::CondCode;
614+
cc.inverse()
615+
}
610616
};
611617
}

cranelift/codegen/src/opts/algebraic.isle

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
;; can freely rewrite e.g. `x+y-y` to `x`.
88

99
;; uextend/sextend of a constant.
10-
(rule (simplify (uextend $I64 (iconst $I32 (u64_from_imm64 imm))))
11-
(iconst $I64 (imm64 (u64_uextend_u32 imm))))
10+
(rule (simplify (uextend ty (iconst _ (u64_from_imm64 imm))))
11+
(iconst ty (imm64 imm)))
1212
(rule (simplify (sextend $I64 (iconst $I32 (u64_from_imm64 imm))))
1313
(iconst $I64 (imm64 (u64_sextend_u32 imm))))
1414

@@ -185,3 +185,25 @@
185185
(remat x))
186186
(rule (simplify x @ (f64const _ _))
187187
(remat x))
188+
189+
;; Optimize icmp-of-icmp.
190+
(rule (simplify (icmp ty
191+
(IntCC.NotEqual)
192+
(uextend _ inner @ (icmp ty _ _ _))
193+
(iconst _ (u64_from_imm64 0))))
194+
(subsume inner))
195+
196+
(rule (simplify (icmp ty
197+
(IntCC.Equal)
198+
(uextend _ (icmp ty cc x y))
199+
(iconst _ (u64_from_imm64 0))))
200+
(subsume (icmp ty (intcc_invert cc) x y)))
201+
202+
;; Optimize select-of-uextend-of-icmp to select-of-icmp, because
203+
;; select can take an I8 condition too.
204+
(rule (simplify
205+
(select ty (uextend _ c @ (icmp _ _ _ _)) x y))
206+
(select ty c x y))
207+
(rule (simplify
208+
(select ty (uextend _ c @ (icmp _ _ _ _)) x y))
209+
(select ty c x y))

cranelift/codegen/src/opts/cprop.isle

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,5 +130,12 @@
130130
(bxor ty (bxor ty x k1 @ (iconst ty _)) k2 @ (iconst ty _)))
131131
(bxor ty x (bxor ty k1 k2)))
132132

133+
(rule (simplify
134+
(select ty (iconst _ (u64_from_imm64 (u64_nonzero _))) x y))
135+
x)
136+
(rule (simplify
137+
(select ty (iconst _ (u64_from_imm64 0)) x y))
138+
y)
139+
133140
;; TODO: fadd, fsub, fmul, fdiv, fneg, fabs
134141

cranelift/codegen/src/prelude.isle

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,10 @@
383383
(decl pure signed_cond_code (IntCC) IntCC)
384384
(extern constructor signed_cond_code signed_cond_code)
385385

386+
;; Constructor that inverts a condcode.
387+
(decl intcc_invert (IntCC) IntCC)
388+
(extern constructor intcc_invert intcc_invert)
389+
386390
;;;; Helpers for Working with TrapCode ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
387391

388392
(decl trap_code_division_by_zero () TrapCode)

0 commit comments

Comments
 (0)