| ;; `icmp`-related rewrites |
| |
| ;; `x == x` is always true for integers; `x != x` is false. Strict |
| ;; inequalities are false, and loose inequalities are true. |
| (rule (simplify (eq (fits_in_64 (ty_int ty)) x x)) (iconst ty (imm64 1))) |
| (rule (simplify (ne (fits_in_64 (ty_int ty)) x x)) (iconst ty (imm64 0))) |
| (rule (simplify (ugt (fits_in_64 (ty_int ty)) x x)) (iconst ty (imm64 0))) |
| (rule (simplify (uge (fits_in_64 (ty_int ty)) x x)) (iconst ty (imm64 1))) |
| (rule (simplify (sgt (fits_in_64 (ty_int ty)) x x)) (iconst ty (imm64 0))) |
| (rule (simplify (sge (fits_in_64 (ty_int ty)) x x)) (iconst ty (imm64 1))) |
| (rule (simplify (ult (fits_in_64 (ty_int ty)) x x)) (iconst ty (imm64 0))) |
| (rule (simplify (ule (fits_in_64 (ty_int ty)) x x)) (iconst ty (imm64 1))) |
| (rule (simplify (slt (fits_in_64 (ty_int ty)) x x)) (iconst ty (imm64 0))) |
| (rule (simplify (sle (fits_in_64 (ty_int ty)) x x)) (iconst ty (imm64 1))) |
| |
| ;; Optimize icmp-of-icmp. |
| (rule (simplify (ne ty |
| (uextend _ inner @ (icmp ty _ _ _)) |
| (iconst _ (u64_from_imm64 0)))) |
| (subsume inner)) |
| |
| (rule (simplify (eq ty |
| (uextend _ (icmp ty cc x y)) |
| (iconst _ (u64_from_imm64 0)))) |
| (subsume (icmp ty (intcc_inverse cc) x y))) |
| |
| ;; Optimize select-of-uextend-of-icmp to select-of-icmp, because |
| ;; select can take an I8 condition too. |
| (rule (simplify |
| (select ty (uextend _ c @ (icmp _ _ _ _)) x y)) |
| (select ty c x y)) |
| (rule (simplify |
| (select ty (uextend _ c @ (icmp _ _ _ _)) x y)) |
| (select ty c x y)) |
| |
| ;; 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) |
| |
| ;; Comparisons against largest/smallest signed/unsigned values: |
| ;; ult(x, 0) == false. |
| (rule (simplify (ult (fits_in_64 (ty_int bty)) x zero @ (iconst _ (u64_from_imm64 0)))) |
| (subsume (iconst bty (imm64 0)))) |
| |
| ;; ule(x, 0) == eq(x, 0) |
| (rule (simplify (ule (fits_in_64 (ty_int bty)) x zero @ (iconst _ (u64_from_imm64 0)))) |
| (eq bty x zero)) |
| |
| ;; ugt(x, 0) == ne(x, 0). |
| (rule (simplify (ugt (fits_in_64 (ty_int bty)) x zero @ (iconst _ (u64_from_imm64 0)))) |
| (ne bty x zero)) |
| |
| ;; uge(x, 0) == true. |
| (rule (simplify (uge (fits_in_64 (ty_int bty)) x zero @ (iconst _ (u64_from_imm64 0)))) |
| (subsume (iconst bty (imm64 1)))) |
| |
| ;; ult(x, UMAX) == ne(x, UMAX). |
| (rule (simplify (ult (fits_in_64 (ty_int bty)) x umax @ (iconst cty (u64_from_imm64 y)))) |
| (if-let $true (u64_eq y (ty_umax cty))) |
| (ne bty x umax)) |
| |
| ;; ule(x, UMAX) == true. |
| (rule (simplify (ule (fits_in_64 (ty_int bty)) x umax @ (iconst cty (u64_from_imm64 y)))) |
| (if-let $true (u64_eq y (ty_umax cty))) |
| (subsume (iconst bty (imm64 1)))) |
| |
| ;; ugt(x, UMAX) == false. |
| (rule (simplify (ugt (fits_in_64 (ty_int bty)) x umax @ (iconst cty (u64_from_imm64 y)))) |
| (if-let $true (u64_eq y (ty_umax cty))) |
| (subsume (iconst bty (imm64 0)))) |
| |
| ;; uge(x, UMAX) == eq(x, UMAX). |
| (rule (simplify (uge (fits_in_64 (ty_int bty)) x umax @ (iconst cty (u64_from_imm64 y)))) |
| (if-let $true (u64_eq y (ty_umax cty))) |
| (eq bty x umax)) |
| |
| ;; slt(x, SMIN) == false. |
| (rule (simplify (slt (fits_in_64 (ty_int bty)) x smin @ (iconst cty (u64_from_imm64 y)))) |
| (if-let $true (u64_eq y (ty_smin cty))) |
| (subsume (iconst bty (imm64 0)))) |
| |
| ;; sle(x, SMIN) == eq(x, SMIN). |
| (rule (simplify (sle (fits_in_64 (ty_int bty)) x smin @ (iconst cty (u64_from_imm64 y)))) |
| (if-let $true (u64_eq y (ty_smin cty))) |
| (eq bty x smin)) |
| |
| ;; sgt(x, SMIN) == ne(x, SMIN). |
| (rule (simplify (sgt (fits_in_64 (ty_int bty)) x smin @ (iconst cty (u64_from_imm64 y)))) |
| (if-let $true (u64_eq y (ty_smin cty))) |
| (ne bty x smin)) |
| |
| ;; sge(x, SMIN) == true. |
| (rule (simplify (sge (fits_in_64 (ty_int bty)) x smin @ (iconst cty (u64_from_imm64 y)))) |
| (if-let $true (u64_eq y (ty_smin cty))) |
| (subsume (iconst bty (imm64 1)))) |
| |
| ;; slt(x, SMAX) == ne(x, SMAX). |
| (rule (simplify (slt (fits_in_64 (ty_int bty)) x smax @ (iconst cty (u64_from_imm64 y)))) |
| (if-let $true (u64_eq y (ty_smax cty))) |
| (ne bty x smax)) |
| |
| ;; sle(x, SMAX) == true. |
| (rule (simplify (sle (fits_in_64 (ty_int bty)) x smax @ (iconst cty (u64_from_imm64 y)))) |
| (if-let $true (u64_eq y (ty_smax cty))) |
| (subsume (iconst bty (imm64 1)))) |
| |
| ;; sgt(x, SMAX) == false. |
| (rule (simplify (sgt (fits_in_64 (ty_int bty)) x smax @ (iconst cty (u64_from_imm64 y)))) |
| (if-let $true (u64_eq y (ty_smax cty))) |
| (subsume (iconst bty (imm64 0)))) |
| |
| ;; sge(x, SMAX) == eq(x, SMAX). |
| (rule (simplify (sge (fits_in_64 (ty_int bty)) x smax @ (iconst cty (u64_from_imm64 y)))) |
| (if-let $true (u64_eq y (ty_smax cty))) |
| (eq bty x smax)) |
| |
| ;; `band`/`bor` of 2 comparisons: |
| (rule (simplify (band ty (icmp ty cc1 x y) (icmp ty cc2 x y))) |
| (if-let signed (intcc_comparable cc1 cc2)) |
| (compose_icmp ty (u64_and (decompose_intcc cc1) (decompose_intcc cc2)) signed x y)) |
| |
| (rule (simplify (bor ty (icmp ty cc1 x y) (icmp ty cc2 x y))) |
| (if-let signed (intcc_comparable cc1 cc2)) |
| (compose_icmp ty (u64_or (decompose_intcc cc1) (decompose_intcc cc2)) signed x y)) |
| |
| (decl pure partial intcc_comparable (IntCC IntCC) bool) |
| (rule (intcc_comparable x y) |
| (if-let (u64_nonzero class) (u64_and (intcc_class x) (intcc_class y))) |
| (u64_eq 2 class)) |
| |
| (decl pure decompose_intcc (IntCC) u64) |
| (rule (decompose_intcc (IntCC.Equal)) 1) |
| (rule (decompose_intcc (IntCC.UnsignedLessThan)) 2) |
| (rule (decompose_intcc (IntCC.SignedLessThan)) 2) |
| (rule (decompose_intcc (IntCC.UnsignedLessThanOrEqual)) 3) |
| (rule (decompose_intcc (IntCC.SignedLessThanOrEqual)) 3) |
| (rule (decompose_intcc (IntCC.UnsignedGreaterThan)) 4) |
| (rule (decompose_intcc (IntCC.SignedGreaterThan)) 4) |
| (rule (decompose_intcc (IntCC.UnsignedGreaterThanOrEqual)) 5) |
| (rule (decompose_intcc (IntCC.SignedGreaterThanOrEqual)) 5) |
| (rule (decompose_intcc (IntCC.NotEqual)) 6) |
| |
| (decl compose_icmp (Type u64 bool Value Value) Value) |
| (rule (compose_icmp ty 0 _ _ _) (subsume (iconst ty (imm64 0)))) |
| (rule (compose_icmp ty 1 _ x y) (icmp ty (IntCC.Equal) x y)) |
| (rule (compose_icmp ty 2 $false x y) (icmp ty (IntCC.UnsignedLessThan) x y)) |
| (rule (compose_icmp ty 2 $true x y) (icmp ty (IntCC.SignedLessThan) x y)) |
| (rule (compose_icmp ty 3 $false x y) (icmp ty (IntCC.UnsignedLessThanOrEqual) x y)) |
| (rule (compose_icmp ty 3 $true x y) (icmp ty (IntCC.SignedLessThanOrEqual) x y)) |
| (rule (compose_icmp ty 4 $false x y) (icmp ty (IntCC.UnsignedGreaterThan) x y)) |
| (rule (compose_icmp ty 4 $true x y) (icmp ty (IntCC.SignedGreaterThan) x y)) |
| (rule (compose_icmp ty 5 $false x y) (icmp ty (IntCC.UnsignedGreaterThanOrEqual) x y)) |
| (rule (compose_icmp ty 5 $true x y) (icmp ty (IntCC.SignedGreaterThanOrEqual) x y)) |
| (rule (compose_icmp ty 6 _ x y) (icmp ty (IntCC.NotEqual) x y)) |
| (rule (compose_icmp ty 7 _ _ _) (subsume (iconst ty (imm64 1)))) |
| |
| (decl pure intcc_class (IntCC) u64) |
| (rule (intcc_class (IntCC.UnsignedLessThan)) 1) |
| (rule (intcc_class (IntCC.UnsignedLessThanOrEqual)) 1) |
| (rule (intcc_class (IntCC.UnsignedGreaterThan)) 1) |
| (rule (intcc_class (IntCC.UnsignedGreaterThanOrEqual)) 1) |
| (rule (intcc_class (IntCC.SignedLessThan)) 2) |
| (rule (intcc_class (IntCC.SignedLessThanOrEqual)) 2) |
| (rule (intcc_class (IntCC.SignedGreaterThan)) 2) |
| (rule (intcc_class (IntCC.SignedGreaterThanOrEqual)) 2) |
| (rule (intcc_class (IntCC.Equal)) 3) |
| (rule (intcc_class (IntCC.NotEqual)) 3) |