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

This rewrite was introduced in #5676 and then reverted in #5682 due to a footgun
where we accidentally weren't actually checking the `y == !z` precondition. This
commit fixes the precondition check. It also fixes the arithmetic to be
correctly masked to the value type's width.

This reverts commit 268f6bfc1d.
This commit is contained in:
Nick Fitzgerald
2023-02-01 12:53:22 -08:00
committed by GitHub
parent 91b8a2c527
commit ffbbfbffce
5 changed files with 177 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) -> bool {
x == y
}
#[inline]
fn u64_is_zero(&mut self, value: u64) -> bool {
0 == value

View File

@@ -138,6 +138,34 @@
(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-let $true (u64_eq (u64_and (ty_mask ty) zk)
(u64_and (ty_mask ty) (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) bool)
(extern constructor u64_eq u64_eq)
(decl pure u64_sextend_u32 (u64) u64)
(extern constructor u64_sextend_u32 u64_sextend_u32)