diff --git a/cranelift/codegen/src/isle_prelude.rs b/cranelift/codegen/src/isle_prelude.rs index cf0caac323b3..1d512bf386fa 100644 --- a/cranelift/codegen/src/isle_prelude.rs +++ b/cranelift/codegen/src/isle_prelude.rs @@ -441,6 +441,11 @@ macro_rules! isle_common_prelude_methods { } } + #[inline] + fn u64_is_power_of_two(&mut self, x: u64) -> bool { + x.is_power_of_two() + } + #[inline] fn u64_from_bool(&mut self, b: bool) -> u64 { if b { diff --git a/cranelift/codegen/src/opts/algebraic.isle b/cranelift/codegen/src/opts/algebraic.isle index 3efa05dfe32e..40d5c03cf07f 100644 --- a/cranelift/codegen/src/opts/algebraic.isle +++ b/cranelift/codegen/src/opts/algebraic.isle @@ -59,6 +59,7 @@ (subsume zero)) ;; x/1 == x. +;; Currently not active: see issue #5908 (rule (simplify (sdiv ty x (iconst ty (u64_from_imm64 1)))) @@ -68,6 +69,17 @@ (iconst ty (u64_from_imm64 1)))) (subsume x)) +;; x%1 == 0. +;; Currently not active: see issue #5908 +(rule (simplify (urem ty x (iconst ty (u64_from_imm64 1)))) + (subsume (iconst ty (imm64 0)))) + +;; x%c == x&(c-1) when c is a power of 2. +;; Currently not active: see issue #5908 +(rule (simplify (urem ty x (iconst ty (u64_from_imm64 c)))) + (if-let $true (u64_is_power_of_two c)) + (band ty x (iconst ty (imm64 (u64_sub c 1))))) + ;; x>>0 == x<<0 == x rotr 0 == x rotl 0 == x. (rule (simplify (ishl ty x diff --git a/cranelift/codegen/src/prelude.isle b/cranelift/codegen/src/prelude.isle index ef2741570a83..4eb772de5e46 100644 --- a/cranelift/codegen/src/prelude.isle +++ b/cranelift/codegen/src/prelude.isle @@ -181,6 +181,9 @@ (decl pure u64_is_odd (u64) bool) (extern constructor u64_is_odd u64_is_odd) +(decl pure u64_is_power_of_two (u64) bool) +(extern constructor u64_is_power_of_two u64_is_power_of_two) + ;;;; `cranelift_codegen::ir::Type` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (extern const $I8 Type) diff --git a/cranelift/filetests/filetests/egraph/algebraic.clif b/cranelift/filetests/filetests/egraph/algebraic.clif index faae822feb8c..c5c4815b3b5c 100644 --- a/cranelift/filetests/filetests/egraph/algebraic.clif +++ b/cranelift/filetests/filetests/egraph/algebraic.clif @@ -240,6 +240,24 @@ block0(v0: i32): ; check: return v2 } +function %urem_x_1(i32) -> i32 { +block0(v0: i32): + v1 = iconst.i32 1 + v2 = urem v0, v1 + return v2 + ; check: v1 = iconst.i32 1 + ; check: v2 = urem v0, v1 +} + +function %urem_x_pow2(i32) -> i32 { +block0(v0: i32): + v1 = iconst.i32 2 + v2 = urem v0, v1 + return v2 + ; check: v1 = iconst.i32 2 + ; check: v2 = urem v0, v1 +} + function %or_and_y_with_not_y_i8(i8, i8) -> i8 { block0(v0: i8, v1: i8): v2 = band v0, v1