Repository: bytecodealliance/wasmtime
Pull request #5735 (2023-02-07 19:22:14)

Add some minor souper-harvested optimizations
I was playing around with souper recently on some wasms I had lying around and these are some optimization opportunities that popped out which seemed easy-enough to add to the egraph-based optimizations.

<!--

Please ensure that the following steps are all taken care of before submitting
the PR.

- [ ] This has been discussed in issue #..., or if not, please tell us why
  here.
- [ ] A short description of what this does, why it is needed; if the
  description becomes long, the matter should probably be discussed in an issue
  first.
- [ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
  If you don't know who could review this, please indicate so. The list of
  suggested reviewers on the right can help you.

Please ensure all communication adheres to the [code of
conduct](https://github.com/bytecodealliance/wasmtime/blob/master/CODE_OF_CONDUCT.md).
-->



Patch:
diff --git a/cranelift/codegen/src/opts/algebraic.isle b/cranelift/codegen/src/opts/algebraic.isle
index 061c61c51..e0f7fc465 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 817bffcd9..f0def3acc 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.
 ;;


Test patch:
diff --git a/cranelift/filetests/filetests/egraph/algebraic.clif b/cranelift/filetests/filetests/egraph/algebraic.clif
index 1962eb508..af8062d6a 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