From ff6f17ca521b5e3f46acca5b93036313a620afba Mon Sep 17 00:00:00 2001 From: Karl Meakin Date: Tue, 21 Mar 2023 22:13:00 +0000 Subject: [PATCH] ISLE: add synonyms for all variations of `icmp` (#6081) --- cranelift/codegen/src/opts/algebraic.isle | 229 +++++++--------------- cranelift/codegen/src/prelude.isle | 30 +++ cranelift/codegen/src/prelude_opt.isle | 11 ++ 3 files changed, 111 insertions(+), 159 deletions(-) diff --git a/cranelift/codegen/src/opts/algebraic.isle b/cranelift/codegen/src/opts/algebraic.isle index 6bc0492498..8cab77bd44 100644 --- a/cranelift/codegen/src/opts/algebraic.isle +++ b/cranelift/codegen/src/opts/algebraic.isle @@ -323,14 +323,12 @@ (remat x)) ;; Optimize icmp-of-icmp. -(rule (simplify (icmp ty - (IntCC.NotEqual) +(rule (simplify (ne ty (uextend _ inner @ (icmp ty _ _ _)) (iconst _ (u64_from_imm64 0)))) (subsume inner)) -(rule (simplify (icmp ty - (IntCC.Equal) +(rule (simplify (eq ty (uextend _ (icmp ty cc x y)) (iconst _ (u64_from_imm64 0)))) (subsume (icmp ty (intcc_inverse cc) x y))) @@ -346,36 +344,16 @@ ;; `x == x` is always true for integers; `x != x` is false. Strict ;; inequalities are false, and loose inequalities are true. -(rule (simplify - (icmp (fits_in_64 (ty_int ty)) (IntCC.Equal) x x)) - (iconst ty (imm64 1))) -(rule (simplify - (icmp (fits_in_64 (ty_int ty)) (IntCC.NotEqual) x x)) - (iconst ty (imm64 0))) -(rule (simplify - (icmp (fits_in_64 (ty_int ty)) (IntCC.UnsignedGreaterThan) x x)) - (iconst ty (imm64 0))) -(rule (simplify - (icmp (fits_in_64 (ty_int ty)) (IntCC.UnsignedGreaterThanOrEqual) x x)) - (iconst ty (imm64 1))) -(rule (simplify - (icmp (fits_in_64 (ty_int ty)) (IntCC.SignedGreaterThan) x x)) - (iconst ty (imm64 0))) -(rule (simplify - (icmp (fits_in_64 (ty_int ty)) (IntCC.SignedGreaterThanOrEqual) x x)) - (iconst ty (imm64 1))) -(rule (simplify - (icmp (fits_in_64 (ty_int ty)) (IntCC.UnsignedLessThan) x x)) - (iconst ty (imm64 0))) -(rule (simplify - (icmp (fits_in_64 (ty_int ty)) (IntCC.UnsignedLessThanOrEqual) x x)) - (iconst ty (imm64 1))) -(rule (simplify - (icmp (fits_in_64 (ty_int ty)) (IntCC.SignedLessThan) x x)) - (iconst ty (imm64 0))) -(rule (simplify - (icmp (fits_in_64 (ty_int ty)) (IntCC.SignedLessThanOrEqual) x x)) - (iconst ty (imm64 1))) +(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))) ;; (x ^ -1) can be replaced with the `bnot` instruction (rule (simplify (bxor ty x (iconst ty k))) @@ -399,215 +377,148 @@ ;; ult(x, 0) == false. (rule (simplify - (icmp (fits_in_64 (ty_int bty)) (IntCC.UnsignedLessThan) x zero @ (iconst _ (u64_from_imm64 0)))) + (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 - (icmp (fits_in_64 (ty_int bty)) (IntCC.UnsignedLessThanOrEqual) x zero @ (iconst _ (u64_from_imm64 0)))) - (icmp bty (IntCC.Equal) x zero)) + (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 - (icmp (fits_in_64 (ty_int bty)) (IntCC.UnsignedGreaterThan) x zero @ (iconst _ (u64_from_imm64 0)))) - (icmp bty (IntCC.NotEqual) x zero)) + (ugt (fits_in_64 (ty_int bty)) x zero @ (iconst _ (u64_from_imm64 0)))) + (ne bty x zero)) ;; uge(x, 0) == true. (rule (simplify - (icmp (fits_in_64 (ty_int bty)) (IntCC.UnsignedGreaterThanOrEqual) x zero @ (iconst _ (u64_from_imm64 0)))) + (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 - (icmp (fits_in_64 (ty_int bty)) (IntCC.UnsignedLessThan) x umax @ (iconst cty (u64_from_imm64 y)))) + (ult (fits_in_64 (ty_int bty)) x umax @ (iconst cty (u64_from_imm64 y)))) (if-let $true (u64_eq y (ty_umax cty))) - (icmp bty (IntCC.NotEqual) x umax)) + (ne bty x umax)) ;; ule(x, UMAX) == true. (rule (simplify - (icmp (fits_in_64 (ty_int bty)) (IntCC.UnsignedLessThanOrEqual) x umax @ (iconst cty (u64_from_imm64 y)))) + (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 - (icmp (fits_in_64 (ty_int bty)) (IntCC.UnsignedGreaterThan) x umax @ (iconst cty (u64_from_imm64 y)))) + (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 - (icmp (fits_in_64 (ty_int bty)) (IntCC.UnsignedGreaterThanOrEqual) x umax @ (iconst cty (u64_from_imm64 y)))) + (uge (fits_in_64 (ty_int bty)) x umax @ (iconst cty (u64_from_imm64 y)))) (if-let $true (u64_eq y (ty_umax cty))) - (icmp bty (IntCC.Equal) x umax)) + (eq bty x umax)) ;; slt(x, SMIN) == false. (rule (simplify - (icmp (fits_in_64 (ty_int bty)) (IntCC.SignedLessThan) x smin @ (iconst cty (u64_from_imm64 y)))) + (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 - (icmp (fits_in_64 (ty_int bty)) (IntCC.SignedLessThanOrEqual) x smin @ (iconst cty (u64_from_imm64 y)))) + (sle (fits_in_64 (ty_int bty)) x smin @ (iconst cty (u64_from_imm64 y)))) (if-let $true (u64_eq y (ty_smin cty))) - (icmp bty (IntCC.Equal) x smin)) + (eq bty x smin)) ;; sgt(x, SMIN) == ne(x, SMIN). (rule (simplify - (icmp (fits_in_64 (ty_int bty)) (IntCC.SignedGreaterThan) x smin @ (iconst cty (u64_from_imm64 y)))) + (sgt (fits_in_64 (ty_int bty)) x smin @ (iconst cty (u64_from_imm64 y)))) (if-let $true (u64_eq y (ty_smin cty))) - (icmp bty (IntCC.NotEqual) x smin)) + (ne bty x smin)) ;; sge(x, SMIN) == true. (rule (simplify - (icmp (fits_in_64 (ty_int bty)) (IntCC.SignedGreaterThanOrEqual) x smin @ (iconst cty (u64_from_imm64 y)))) + (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 - (icmp (fits_in_64 (ty_int bty)) (IntCC.SignedLessThan) x smax @ (iconst cty (u64_from_imm64 y)))) + (slt (fits_in_64 (ty_int bty)) x smax @ (iconst cty (u64_from_imm64 y)))) (if-let $true (u64_eq y (ty_smax cty))) - (icmp bty (IntCC.NotEqual) x smax)) + (ne bty x smax)) ;; sle(x, SMAX) == true. (rule (simplify - (icmp (fits_in_64 (ty_int bty)) (IntCC.SignedLessThanOrEqual) x smax @ (iconst cty (u64_from_imm64 y)))) + (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 - (icmp (fits_in_64 (ty_int bty)) (IntCC.SignedGreaterThan) x smax @ (iconst cty (u64_from_imm64 y)))) + (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 - (icmp (fits_in_64 (ty_int bty)) (IntCC.SignedGreaterThanOrEqual) x smax @ (iconst cty (u64_from_imm64 y)))) + (sge (fits_in_64 (ty_int bty)) x smax @ (iconst cty (u64_from_imm64 y)))) (if-let $true (u64_eq y (ty_smax cty))) - (icmp bty (IntCC.Equal) x smax)) + (eq bty x smax)) ;; 32-bit integers zero-extended to 64-bit integers are never negative (rule (simplify - (icmp (ty_int ty) - (IntCC.SignedLessThan) + (slt ty (uextend $I64 x @ (value_type $I32)) (iconst _ (u64_from_imm64 0)))) (iconst ty (imm64 0))) (rule (simplify - (icmp (ty_int ty) - (IntCC.SignedGreaterThanOrEqual) + (sge ty (uextend $I64 x @ (value_type $I32)) (iconst _ (u64_from_imm64 0)))) (iconst ty (imm64 1))) ;; Transform select-of-icmp into {u,s}{min,max} instructions where possible. -(rule (simplify - (select ty (icmp _ (IntCC.SignedGreaterThan) x y) x y)) - (smax ty x y)) -(rule (simplify - (select ty (icmp _ (IntCC.SignedGreaterThanOrEqual) x y) x y)) - (smax ty x y)) -(rule (simplify - (select ty (icmp _ (IntCC.UnsignedGreaterThan) x y) x y)) - (umax ty x y)) -(rule (simplify - (select ty (icmp _ (IntCC.UnsignedGreaterThanOrEqual) x y) x y)) - (umax ty x y)) -(rule (simplify - (select ty (icmp _ (IntCC.SignedLessThan) x y) x y)) - (smin ty x y)) -(rule (simplify - (select ty (icmp _ (IntCC.SignedLessThanOrEqual) x y) x y)) - (smin ty x y)) -(rule (simplify - (select ty (icmp _ (IntCC.UnsignedLessThan) x y) x y)) - (umin ty x y)) -(rule (simplify - (select ty (icmp _ (IntCC.UnsignedLessThanOrEqual) x y) x y)) - (umin ty x y)) - +(rule (simplify (select ty (sgt _ x y) x y)) (smax ty x y)) +(rule (simplify (select ty (sge _ x y) x y)) (smax ty x y)) +(rule (simplify (select ty (ugt _ x y) x y)) (umax ty x y)) +(rule (simplify (select ty (uge _ x y) x y)) (umax ty x y)) +(rule (simplify (select ty (slt _ x y) x y)) (smin ty x y)) +(rule (simplify (select ty (sle _ x y) x y)) (smin ty x y)) +(rule (simplify (select ty (ult _ x y) x y)) (umin ty x y)) +(rule (simplify (select ty (ule _ x y) x y)) (umin ty x y)) ;; These are the same rules as above, but when the operands for select are swapped -(rule (simplify - (select ty (icmp _ (IntCC.SignedLessThan) x y) y x)) - (smax ty x y)) -(rule (simplify - (select ty (icmp _ (IntCC.SignedLessThanOrEqual) x y) y x)) - (smax ty x y)) -(rule (simplify - (select ty (icmp _ (IntCC.UnsignedLessThan) x y) y x)) - (umax ty x y)) -(rule (simplify - (select ty (icmp _ (IntCC.UnsignedLessThanOrEqual) x y) y x)) - (umax ty x y)) -(rule (simplify - (select ty (icmp _ (IntCC.SignedGreaterThan) x y) y x)) - (smin ty x y)) -(rule (simplify - (select ty (icmp _ (IntCC.SignedGreaterThanOrEqual) x y) y x)) - (smin ty x y)) -(rule (simplify - (select ty (icmp _ (IntCC.UnsignedGreaterThan) x y) y x)) - (umin ty x y)) -(rule (simplify - (select ty (icmp _ (IntCC.UnsignedGreaterThanOrEqual) x y) y x)) - (umin ty x y)) +(rule (simplify (select ty (slt _ x y) y x)) (smax ty x y)) +(rule (simplify (select ty (sle _ x y) y x)) (smax ty x y)) +(rule (simplify (select ty (ult _ x y) y x)) (umax ty x y)) +(rule (simplify (select ty (ule _ x y) y x)) (umax ty x y)) +(rule (simplify (select ty (sgt _ x y) y x)) (smin ty x y)) +(rule (simplify (select ty (sge _ x y) y x)) (smin ty x y)) +(rule (simplify (select ty (ugt _ x y) y x)) (umin ty x y)) +(rule (simplify (select ty (uge _ x y) y x)) (umin ty x y)) ;; Transform bitselect-of-icmp into {u,s}{min,max} instructions where possible. -(rule (simplify - (bitselect ty (icmp _ (IntCC.SignedGreaterThan) x y) x y)) - (smax ty x y)) -(rule (simplify - (bitselect ty (icmp _ (IntCC.SignedGreaterThanOrEqual) x y) x y)) - (smax ty x y)) -(rule (simplify - (bitselect ty (icmp _ (IntCC.UnsignedGreaterThan) x y) x y)) - (umax ty x y)) -(rule (simplify - (bitselect ty (icmp _ (IntCC.UnsignedGreaterThanOrEqual) x y) x y)) - (umax ty x y)) -(rule (simplify - (bitselect ty (icmp _ (IntCC.SignedLessThan) x y) x y)) - (smin ty x y)) -(rule (simplify - (bitselect ty (icmp _ (IntCC.SignedLessThanOrEqual) x y) x y)) - (smin ty x y)) -(rule (simplify - (bitselect ty (icmp _ (IntCC.UnsignedLessThan) x y) x y)) - (umin ty x y)) -(rule (simplify - (bitselect ty (icmp _ (IntCC.UnsignedLessThanOrEqual) x y) x y)) - (umin ty x y)) +(rule (simplify (bitselect ty (sgt _ x y) x y)) (smax ty x y)) +(rule (simplify (bitselect ty (sge _ x y) x y)) (smax ty x y)) +(rule (simplify (bitselect ty (ugt _ x y) x y)) (umax ty x y)) +(rule (simplify (bitselect ty (uge _ x y) x y)) (umax ty x y)) +(rule (simplify (bitselect ty (slt _ x y) x y)) (smin ty x y)) +(rule (simplify (bitselect ty (sle _ x y) x y)) (smin ty x y)) +(rule (simplify (bitselect ty (ult _ x y) x y)) (umin ty x y)) +(rule (simplify (bitselect ty (ule _ x y) x y)) (umin ty x y)) ;; These are the same rules as above, but when the operands for select are swapped -(rule (simplify - (bitselect ty (icmp _ (IntCC.SignedLessThan) x y) y x)) - (smax ty x y)) -(rule (simplify - (bitselect ty (icmp _ (IntCC.SignedLessThanOrEqual) x y) y x)) - (smax ty x y)) -(rule (simplify - (bitselect ty (icmp _ (IntCC.UnsignedLessThan) x y) y x)) - (umax ty x y)) -(rule (simplify - (bitselect ty (icmp _ (IntCC.UnsignedLessThanOrEqual) x y) y x)) - (umax ty x y)) -(rule (simplify - (bitselect ty (icmp _ (IntCC.SignedGreaterThan) x y) y x)) - (smin ty x y)) -(rule (simplify - (bitselect ty (icmp _ (IntCC.SignedGreaterThanOrEqual) x y) y x)) - (smin ty x y)) -(rule (simplify - (bitselect ty (icmp _ (IntCC.UnsignedGreaterThan) x y) y x)) - (umin ty x y)) -(rule (simplify - (bitselect ty (icmp _ (IntCC.UnsignedGreaterThanOrEqual) x y) y x)) - (umin ty x y)) +(rule (simplify (bitselect ty (slt _ x y) y x)) (smax ty x y)) +(rule (simplify (bitselect ty (sle _ x y) y x)) (smax ty x y)) +(rule (simplify (bitselect ty (ult _ x y) y x)) (umax ty x y)) +(rule (simplify (bitselect ty (ule _ x y) y x)) (umax ty x y)) +(rule (simplify (bitselect ty (sgt _ x y) y x)) (smin ty x y)) +(rule (simplify (bitselect ty (sge _ x y) y x)) (smin ty x y)) +(rule (simplify (bitselect ty (ugt _ x y) y x)) (umin ty x y)) +(rule (simplify (bitselect ty (uge _ x y) y x)) (umin ty x y)) ;; For floats convert fcmp lt into pseudo_min and gt into pseudo_max ;; diff --git a/cranelift/codegen/src/prelude.isle b/cranelift/codegen/src/prelude.isle index 8228f72dd5..2c19e8a849 100644 --- a/cranelift/codegen/src/prelude.isle +++ b/cranelift/codegen/src/prelude.isle @@ -282,6 +282,36 @@ ;;;; Helper Clif Extractors ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +(decl eq (Type Value Value) Value) +(extractor (eq ty x y) (icmp ty (IntCC.Equal) x y)) + +(decl ne (Type Value Value) Value) +(extractor (ne ty x y) (icmp ty (IntCC.NotEqual) x y)) + +(decl ult (Type Value Value) Value) +(extractor (ult ty x y) (icmp ty (IntCC.UnsignedLessThan) x y)) + +(decl ule (Type Value Value) Value) +(extractor (ule ty x y) (icmp ty (IntCC.UnsignedLessThanOrEqual) x y)) + +(decl ugt (Type Value Value) Value) +(extractor (ugt ty x y) (icmp ty (IntCC.UnsignedGreaterThan) x y)) + +(decl uge (Type Value Value) Value) +(extractor (uge ty x y) (icmp ty (IntCC.UnsignedGreaterThanOrEqual) x y)) + +(decl slt (Type Value Value) Value) +(extractor (slt ty x y) (icmp ty (IntCC.SignedLessThan) x y)) + +(decl sle (Type Value Value) Value) +(extractor (sle ty x y) (icmp ty (IntCC.SignedLessThanOrEqual) x y)) + +(decl sgt (Type Value Value) Value) +(extractor (sgt ty x y) (icmp ty (IntCC.SignedGreaterThan) x y)) + +(decl sge (Type Value Value) Value) +(extractor (sge ty x y) (icmp ty (IntCC.SignedGreaterThanOrEqual) x y)) + ;; An extractor that only matches types that can fit in 16 bits. (decl fits_in_16 (Type) Type) (extern extractor fits_in_16 fits_in_16) diff --git a/cranelift/codegen/src/prelude_opt.isle b/cranelift/codegen/src/prelude_opt.isle index d3fc0d1bb4..099930f5b3 100644 --- a/cranelift/codegen/src/prelude_opt.isle +++ b/cranelift/codegen/src/prelude_opt.isle @@ -17,6 +17,17 @@ (decl value_array_3_ctor (Value Value Value) ValueArray3) (extern constructor value_array_3_ctor value_array_3_ctor) +(rule (eq ty x y) (icmp ty (IntCC.Equal) x y)) +(rule (ne ty x y) (icmp ty (IntCC.NotEqual) x y)) +(rule (ult ty x y) (icmp ty (IntCC.UnsignedLessThan) x y)) +(rule (ule ty x y) (icmp ty (IntCC.UnsignedLessThanOrEqual) x y)) +(rule (ugt ty x y) (icmp ty (IntCC.UnsignedGreaterThan) x y)) +(rule (uge ty x y) (icmp ty (IntCC.UnsignedGreaterThanOrEqual) x y)) +(rule (slt ty x y) (icmp ty (IntCC.SignedLessThan) x y)) +(rule (sle ty x y) (icmp ty (IntCC.SignedLessThanOrEqual) x y)) +(rule (sgt ty x y) (icmp ty (IntCC.SignedGreaterThan) x y)) +(rule (sge ty x y) (icmp ty (IntCC.SignedGreaterThanOrEqual) x y)) + ;;;;; optimization toplevel ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; The main matcher rule invoked by the toplevel driver.