Cranelift: Rewrite or(and(x, y), not(y)) => or(x, not(y)) (#5676)

Co-authored-by: Rainy Sinclair <844493+itsrainy@users.noreply.github.com>
This commit is contained in:
Nick Fitzgerald
2023-01-31 14:44:45 -08:00
committed by GitHub
parent e82995f03c
commit 8c9eb9939b
5 changed files with 112 additions and 1 deletions

View File

@@ -109,6 +109,11 @@ macro_rules! isle_common_prelude_methods {
!x
}
#[inline]
fn u64_eq(&mut self, x: u64, y: u64) -> u64 {
u64::from(x == y)
}
#[inline]
fn u64_is_zero(&mut self, value: u64) -> bool {
0 == value

View File

@@ -138,6 +138,33 @@
(rule (simplify (bnot ty (band t x y)))
(bor ty (bnot ty x) (bnot ty y)))
;; `or(and(x, y), not(y)) == or(x, not(y))`
(rule (simplify (bor ty
(band ty x y)
z @ (bnot ty y)))
(bor ty x z))
;; Duplicate the rule but swap the `bor` operands because `bor` is
;; commutative. We could, of course, add a `simplify` rule to do the commutative
;; swap for all `bor`s but this will bloat the e-graph with many e-nodes. It is
;; cheaper to have additional rules, rather than additional e-nodes, because we
;; amortize their cost via ISLE's smart codegen.
(rule (simplify (bor ty
z @ (bnot ty y)
(band ty x y)))
(bor ty x z))
;; `or(and(x, y), not(y)) == or(x, not(y))` specialized for constants, since
;; otherwise we may not know that `z == not(y)` since we don't generally expand
;; constants in the e-graph.
;;
;; (No need to duplicate for commutative `bor` for this constant version because
;; we move constants to the right.)
(rule (simplify (bor ty
(band ty x (iconst ty (u64_from_imm64 y)))
z @ (iconst ty (u64_from_imm64 zk))))
(if (u64_eq zk (u64_not y)))
(bor ty x z))
;; x*2 == 2*x == x+x.
(rule (simplify (imul ty x (iconst _ (simm32 2))))
(iadd ty x x))

View File

@@ -141,6 +141,9 @@
(decl pure u64_not (u64) u64)
(extern constructor u64_not u64_not)
(decl pure u64_eq (u64 u64) u64)
(extern constructor u64_eq u64_eq)
(decl pure u64_sextend_u32 (u64) u64)
(extern constructor u64_sextend_u32 u64_sextend_u32)