This commit adds constant-propagation optimizations for `splat`-of-constant to produce a `vconst` node. This should help later hoisting these constants out of loops if it shows up in wasm.
198 lines
6.7 KiB
Common Lisp
198 lines
6.7 KiB
Common Lisp
;; Constant propagation.
|
|
|
|
(rule (simplify
|
|
(iadd (fits_in_64 ty)
|
|
(iconst ty (u64_from_imm64 k1))
|
|
(iconst ty (u64_from_imm64 k2))))
|
|
(subsume (iconst ty (imm64_masked ty (u64_add k1 k2)))))
|
|
|
|
(rule (simplify
|
|
(isub (fits_in_64 ty)
|
|
(iconst ty (u64_from_imm64 k1))
|
|
(iconst ty (u64_from_imm64 k2))))
|
|
(subsume (iconst ty (imm64_masked ty (u64_sub k1 k2)))))
|
|
|
|
(rule (simplify
|
|
(imul (fits_in_64 ty)
|
|
(iconst ty (u64_from_imm64 k1))
|
|
(iconst ty (u64_from_imm64 k2))))
|
|
(subsume (iconst ty (imm64_masked ty (u64_mul k1 k2)))))
|
|
|
|
(rule (simplify
|
|
(sdiv (fits_in_64 ty)
|
|
(iconst ty (u64_from_imm64 k1))
|
|
(iconst ty (u64_from_imm64 k2))))
|
|
(if-let d (u64_sdiv k1 k2))
|
|
(subsume (iconst ty (imm64_masked ty d))))
|
|
|
|
(rule (simplify
|
|
(udiv (fits_in_64 ty)
|
|
(iconst ty (u64_from_imm64 k1))
|
|
(iconst ty (u64_from_imm64 k2))))
|
|
(if-let d (u64_udiv k1 k2))
|
|
(subsume (iconst ty (imm64_masked ty d))))
|
|
|
|
(rule (simplify
|
|
(bor (fits_in_64 ty)
|
|
(iconst ty (u64_from_imm64 k1))
|
|
(iconst ty (u64_from_imm64 k2))))
|
|
(subsume (iconst ty (imm64_masked ty (u64_or k1 k2)))))
|
|
|
|
(rule (simplify
|
|
(band (fits_in_64 ty)
|
|
(iconst ty (u64_from_imm64 k1))
|
|
(iconst ty (u64_from_imm64 k2))))
|
|
(subsume (iconst ty (imm64_masked ty (u64_and k1 k2)))))
|
|
|
|
(rule (simplify
|
|
(bxor (fits_in_64 ty)
|
|
(iconst ty (u64_from_imm64 k1))
|
|
(iconst ty (u64_from_imm64 k2))))
|
|
(subsume (iconst ty (imm64_masked ty (u64_xor k1 k2)))))
|
|
|
|
(rule (simplify
|
|
(bnot (fits_in_64 ty)
|
|
(iconst ty (u64_from_imm64 k))))
|
|
(subsume (iconst ty (imm64_masked ty (u64_not k)))))
|
|
|
|
(rule (simplify (ishl (fits_in_64 ty)
|
|
(iconst ty k1)
|
|
(iconst _ k2)))
|
|
(subsume (iconst ty (imm64_shl ty k1 k2))))
|
|
|
|
(rule (simplify (ushr (fits_in_64 ty)
|
|
(iconst ty k1)
|
|
(iconst _ k2)))
|
|
(subsume (iconst ty (imm64_ushr ty k1 k2))))
|
|
|
|
(rule (simplify (sshr (fits_in_64 ty)
|
|
(iconst ty k1)
|
|
(iconst _ k2)))
|
|
(subsume (iconst ty (imm64_sshr ty k1 k2))))
|
|
|
|
(rule (simplify (uextend (fits_in_64 wide) (iconst narrow imm)))
|
|
(subsume (iconst wide (imm64 (u64_uextend_imm64 narrow imm)))))
|
|
|
|
(rule (simplify (sextend (fits_in_64 wide) (iconst narrow imm)))
|
|
(subsume (iconst wide (imm64_masked wide (i64_as_u64 (i64_sextend_imm64 narrow imm))))))
|
|
|
|
(rule (simplify
|
|
(icmp result_ty
|
|
cc
|
|
(iconst ty k1)
|
|
(iconst ty k2)))
|
|
(subsume (iconst result_ty (imm64_icmp ty cc k1 k2))))
|
|
|
|
|
|
;; Canonicalize via commutativity: push immediates to the right.
|
|
;;
|
|
;; (op k x) --> (op x k)
|
|
|
|
(rule (simplify
|
|
(iadd ty k @ (iconst ty _) x))
|
|
(iadd ty x k))
|
|
;; sub is not commutative, but we can flip the args and negate the
|
|
;; whole thing.
|
|
(rule (simplify
|
|
(isub ty k @ (iconst ty _) x))
|
|
(ineg ty (isub ty x k)))
|
|
(rule (simplify
|
|
(imul ty k @ (iconst ty _) x))
|
|
(imul ty x k))
|
|
|
|
(rule (simplify
|
|
(bor ty k @ (iconst ty _) x))
|
|
(bor ty x k))
|
|
(rule (simplify
|
|
(band ty k @ (iconst ty _) x))
|
|
(band ty x k))
|
|
(rule (simplify
|
|
(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.
|
|
;;
|
|
;; (op (op x k) k) --> (op x (op k k))
|
|
|
|
(rule (simplify
|
|
(iadd ty (iadd ty x k1 @ (iconst ty _)) k2 @ (iconst ty _)))
|
|
(iadd ty x (iadd ty k1 k2)))
|
|
;; sub is not directly associative, but we can flip a sub to an add to
|
|
;; make it work:
|
|
;; - (sub (sub x k1) k2) -> (sub x (add k1 k2))
|
|
;; - (sub (sub k1 x) k2) -> (sub (sub k1 k2) x)
|
|
;; - (sub (add x k1) k2) -> (sub x (sub k2 k1))
|
|
;; - (add (sub x k1) k2) -> (add x (sub k2 k1))
|
|
;; - (add (sub k1 x) k2) -> (sub (add k1 k2) x)
|
|
(rule (simplify (isub ty
|
|
(isub ty x (iconst ty (u64_from_imm64 k1)))
|
|
(iconst ty (u64_from_imm64 k2))))
|
|
(isub ty x (iconst ty (imm64_masked ty (u64_add k1 k2)))))
|
|
(rule (simplify (isub ty
|
|
(isub ty (iconst ty (u64_from_imm64 k1)) x)
|
|
(iconst ty (u64_from_imm64 k2))))
|
|
(isub ty (iconst ty (imm64_masked ty (u64_sub k1 k2))) x))
|
|
(rule (simplify (isub ty
|
|
(iadd ty x (iconst ty (u64_from_imm64 k1)))
|
|
(iconst ty (u64_from_imm64 k2))))
|
|
(isub ty x (iconst ty (imm64_masked ty (u64_sub k2 k1)))))
|
|
(rule (simplify (iadd ty
|
|
(isub ty x (iconst ty (u64_from_imm64 k1)))
|
|
(iconst ty (u64_from_imm64 k2))))
|
|
(iadd ty x (iconst ty (imm64_masked ty (u64_sub k2 k1)))))
|
|
(rule (simplify (iadd ty
|
|
(isub ty (iconst ty (u64_from_imm64 k1)) x)
|
|
(iconst ty (u64_from_imm64 k2))))
|
|
(isub ty (iconst ty (imm64_masked ty (u64_add k1 k2))) x))
|
|
|
|
(rule (simplify
|
|
(imul ty (imul ty x k1 @ (iconst ty _)) k2 @ (iconst ty _)))
|
|
(imul ty x (imul ty k1 k2)))
|
|
(rule (simplify
|
|
(bor ty (bor ty x k1 @ (iconst ty _)) k2 @ (iconst ty _)))
|
|
(bor ty x (bor ty k1 k2)))
|
|
(rule (simplify
|
|
(band ty (band ty x k1 @ (iconst ty _)) k2 @ (iconst ty _)))
|
|
(band ty x (band ty k1 k2)))
|
|
(rule (simplify
|
|
(bxor ty (bxor ty x k1 @ (iconst ty _)) k2 @ (iconst ty _)))
|
|
(bxor ty x (bxor ty k1 k2)))
|
|
|
|
(rule (simplify
|
|
(select ty (iconst _ (u64_from_imm64 (u64_nonzero _))) x y))
|
|
x)
|
|
(rule (simplify
|
|
(select ty (iconst _ (u64_from_imm64 0)) x y))
|
|
y)
|
|
|
|
;; TODO: fadd, fsub, fmul, fdiv, fneg, fabs
|
|
|
|
;; A splat of a constant can become a direct `vconst` with the appropriate bit
|
|
;; pattern.
|
|
(rule (simplify (splat dst (iconst $I8 n)))
|
|
(vconst dst (splat8 (u64_uextend_imm64 $I8 n))))
|
|
(rule (simplify (splat dst (iconst $I16 n)))
|
|
(vconst dst (splat16 (u64_uextend_imm64 $I16 n))))
|
|
(rule (simplify (splat dst (iconst $I32 n)))
|
|
(vconst dst (splat32 (u64_uextend_imm64 $I32 n))))
|
|
(rule (simplify (splat dst (iconst $I64 n)))
|
|
(vconst dst (splat64 (u64_uextend_imm64 $I64 n))))
|
|
(rule (simplify (splat dst (f32const _ (u32_from_ieee32 n))))
|
|
(vconst dst (splat32 n)))
|
|
(rule (simplify (splat dst (f64const _ (u64_from_ieee64 n))))
|
|
(vconst dst (splat64 n)))
|
|
|
|
(decl splat8 (u64) Constant)
|
|
(rule (splat8 n) (splat16 (u64_or n (u64_shl n 8))))
|
|
(decl splat16 (u64) Constant)
|
|
(rule (splat16 n) (splat32 (u64_or n (u64_shl n 16))))
|
|
(decl splat32 (u64) Constant)
|
|
(rule (splat32 n) (splat64 (u64_or n (u64_shl n 32))))
|
|
(decl splat64 (u64) Constant)
|
|
(extern constructor splat64 splat64)
|