diff --git a/cranelift/codegen/src/opts/algebraic.isle b/cranelift/codegen/src/opts/algebraic.isle index 061c61c511..e0f7fc4654 100644 --- a/cranelift/codegen/src/opts/algebraic.isle +++ b/cranelift/codegen/src/opts/algebraic.isle @@ -289,3 +289,47 @@ (rule (simplify (bxor ty x (iconst ty k))) (if-let -1 (i64_sextend_imm64 ty k)) (bnot ty x)) + + +;; Masking the result of a comparison with 1 always results in the comparison +;; itself. Note that comparisons in wasm may sometimes be hidden behind +;; extensions. +(rule (simplify + (band (ty_int _) + cmp @ (icmp _ _ _ _) + (iconst _ (u64_from_imm64 1)))) + cmp) +(rule (simplify + (band (ty_int _) + extend @ (uextend _ (icmp _ _ _ _)) + (iconst _ (u64_from_imm64 1)))) + extend) + +;; `x < 0` is always false for unsigned integers, and `x >= 0` is always true +;; for unsigned integers, along with their reversals. +(rule (simplify + (icmp (fits_in_64 (ty_int ty)) + (IntCC.UnsignedLessThan) + _ + (iconst _ (u64_from_imm64 0)))) + (iconst ty (imm64 0))) +(rule (simplify + (icmp (fits_in_64 (ty_int ty)) + (IntCC.UnsignedGreaterThanOrEqual) + _ + (iconst _ (u64_from_imm64 0)))) + (iconst ty (imm64 1))) + +;; 32-bit integers zero-extended to 64-bit integers are never negative +(rule (simplify + (icmp (ty_int ty) + (IntCC.SignedLessThan) + (uextend $I64 x @ (value_type $I32)) + (iconst _ (u64_from_imm64 0)))) + (iconst ty (imm64 0))) +(rule (simplify + (icmp (ty_int ty) + (IntCC.SignedGreaterThanOrEqual) + (uextend $I64 x @ (value_type $I32)) + (iconst _ (u64_from_imm64 0)))) + (iconst ty (imm64 1))) diff --git a/cranelift/codegen/src/opts/cprop.isle b/cranelift/codegen/src/opts/cprop.isle index 817bffcd98..f0def3acca 100644 --- a/cranelift/codegen/src/opts/cprop.isle +++ b/cranelift/codegen/src/opts/cprop.isle @@ -110,6 +110,10 @@ (bxor ty k @ (iconst ty _) x)) (bxor ty x k)) +(rule (simplify + (icmp ty cc k @ (iconst _ _) x)) + (icmp ty (intcc_reverse cc) x k)) + ;; Canonicalize via associativity: reassociate to a right-heavy tree ;; for constants. ;; diff --git a/cranelift/filetests/filetests/egraph/algebraic.clif b/cranelift/filetests/filetests/egraph/algebraic.clif index 1962eb508f..af8062d6ad 100644 --- a/cranelift/filetests/filetests/egraph/algebraic.clif +++ b/cranelift/filetests/filetests/egraph/algebraic.clif @@ -251,3 +251,89 @@ block0(v1: i64): ; check: v5 = bnot v1 ; check: return v5 + +function %mask_icmp_result(i64, i64) -> i8 { +block0(v1: i64, v2: i64): + v3 = icmp ult v1, v2 + v4 = iconst.i8 1 + v5 = band v3, v4 + return v5 +} + +; check: v3 = icmp ult v1, v2 +; check: return v3 + +function %mask_icmp_extend_result(i64, i64) -> i64 { +block0(v1: i64, v2: i64): + v3 = icmp ult v1, v2 + v4 = uextend.i64 v3 + v5 = iconst.i64 1 + v6 = band v4, v5 + return v6 +} + +; check: v3 = icmp ult v1, v2 +; check: v4 = uextend.i64 v3 +; check: return v4 + +function %ult_zero_always_false(i64) -> i8 { +block0(v1: i64): + v2 = iconst.i64 0 + v3 = icmp ult v1, v2 + return v3 +} + +; check: v4 = iconst.i8 0 +; check: return v4 + +function %ugt_zero_always_false(i64) -> i8 { +block0(v1: i64): + v2 = iconst.i64 0 + v3 = icmp ugt v2, v1 + return v3 +} + +; check: v5 = iconst.i8 0 +; check: return v5 + +function %uge_zero_always_false(i64) -> i8 { +block0(v1: i64): + v2 = iconst.i64 0 + v3 = icmp uge v1, v2 + return v3 +} + +; check: v4 = iconst.i8 1 +; check: return v4 + +function %ule_zero_always_false(i64) -> i8 { +block0(v1: i64): + v2 = iconst.i64 0 + v3 = icmp ule v2, v1 + return v3 +} + +; check: v5 = iconst.i8 1 +; check: return v5 + +function %extend_always_above_zero(i32) -> i8 { +block0(v1: i32): + v2 = uextend.i64 v1 + v3 = iconst.i64 0 + v4 = icmp slt v2, v3 + return v4 +} + +; check: v5 = iconst.i8 0 +; check: return v5 + +function %extend_always_above_zero2(i32) -> i8 { +block0(v1: i32): + v2 = uextend.i64 v1 + v3 = iconst.i64 0 + v4 = icmp sge v2, v3 + return v4 +} + +; check: v5 = iconst.i8 1 +; check: return v5