Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add splat simplify opt for various ops #6851

Merged
merged 9 commits into from
Aug 18, 2023
73 changes: 71 additions & 2 deletions cranelift/codegen/src/opts/vector.isle
Original file line number Diff line number Diff line change
@@ -1,8 +1,77 @@
;; Lift a splat outside of an int-to-float conversion to try to open up
;; For various ops lift a splat outside of the op to try to open up
;; optimization opportunities with scalars.
;;
;; NB: this is also required for correctness at this time due to #6562
;; NB: for int-to-float conversion op this simplification is also
;; required for correctness at this time due to #6562
(rule (simplify (fcvt_from_uint float_vector_ty (splat _ x)))
(splat float_vector_ty (fcvt_from_uint (lane_type float_vector_ty) x)))
(rule (simplify (fcvt_from_sint float_vector_ty (splat _ x)))
(splat float_vector_ty (fcvt_from_sint (lane_type float_vector_ty) x)))

(rule (simplify (band ty (splat ty x) (splat ty y)))
(splat ty (band (lane_type ty) x y)))

(rule (simplify (bor ty (splat ty x) (splat ty y)))
(splat ty (bor (lane_type ty) x y)))

(rule (simplify (bxor ty (splat ty x) (splat ty y)))
(splat ty (bxor (lane_type ty) x y)))

(rule (simplify (bnot ty (splat ty x)))
(splat ty (bnot (lane_type ty) x)))

(rule (simplify (iadd ty (splat ty x) (splat ty y)))
(splat ty (iadd (lane_type ty) x y)))

(rule (simplify (isub ty (splat ty x) (splat ty y)))
(splat ty (isub (lane_type ty) x y)))

(rule (simplify (imul ty (splat ty x) (splat ty y)))
(splat ty (imul (lane_type ty) x y)))

(rule (simplify (smulhi ty (splat ty x) (splat ty y)))
(splat ty (smulhi (lane_type ty) x y)))

(rule (simplify (umulhi ty (splat ty x) (splat ty y)))
(splat ty (umulhi (lane_type ty) x y)))

(rule (simplify (ineg ty (splat ty x)))
(splat ty (ineg (lane_type ty) x)))

(rule (simplify (iabs ty (splat ty x)))
(splat ty (iabs (lane_type ty) x)))

(rule (simplify (popcnt ty (splat ty x)))
(splat ty (popcnt (lane_type ty) x)))

(rule (simplify (smin ty (splat ty x) (splat ty y)))
(splat ty (smin (lane_type ty) x y)))

(rule (simplify (umin ty (splat ty x) (splat ty y)))
(splat ty (umin (lane_type ty) x y)))

(rule (simplify (smax ty (splat ty x) (splat ty y)))
(splat ty (smax (lane_type ty) x y)))

(rule (simplify (umax ty (splat ty x) (splat ty y)))
(splat ty (umax (lane_type ty) x y)))

(rule (simplify (avg_round ty (splat ty x) (splat ty y)))
(splat ty (avg_round (lane_type ty) x y)))
gurry marked this conversation as resolved.
Show resolved Hide resolved

;; The second operand of shift and rotate ops is
;; scalar so splat opt applies only to the first
(rule (simplify (rotl ty (splat ty x) y))
(splat ty (rotl (lane_type ty) x y)))

(rule (simplify (rotr ty (splat ty x) y))
(splat ty (rotr (lane_type ty) x y)))

(rule (simplify (ishl ty (splat ty x) y))
(splat ty (ishl (lane_type ty) x y)))

(rule (simplify (ushr ty (splat ty x) y))
(splat ty (ushr (lane_type ty) x y)))

(rule (simplify (sshr ty (splat ty x) y))
(splat ty (sshr (lane_type ty) x y)))
236 changes: 236 additions & 0 deletions cranelift/filetests/filetests/egraph/simd-splat-simplify.clif
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
test optimize
set opt_level=speed
target x86_64

function %band_splat_into_splat_band(i64, i64) -> i64x2 {
block0(v0: i64, v1: i64):
v2 = splat.i64x2 v0
v3 = splat.i64x2 v1
v4 = band.i64x2 v2, v3
return v4
; check: v5 = band v0, v1
; check: v6 = splat.i64x2 v5
; check: return v6
}

function %bor_splat_into_splat_bor(i64, i64) -> i64x2 {
block0(v0: i64, v1: i64):
v2 = splat.i64x2 v0
v3 = splat.i64x2 v1
v4 = bor.i64x2 v2, v3
return v4
; check: v5 = bor v0, v1
; check: v6 = splat.i64x2 v5
; check: return v6
}

function %bxor_splat_into_splat_bxor(i64, i64) -> i64x2 {
block0(v0: i64, v1: i64):
v2 = splat.i64x2 v0
v3 = splat.i64x2 v1
v4 = bxor.i64x2 v2, v3
return v4
; check: v5 = bxor v0, v1
; check: v6 = splat.i64x2 v5
; check: return v6
}

function %bnot_splat_into_splat_bnot(i64) -> i64x2 {
block0(v0: i64):
v1 = splat.i64x2 v0
v2 = bnot.i64x2 v1
return v2
; check: v3 = bnot v0
; check: v4 = splat.i64x2 v3
; check: return v4
}

function %iadd_splat_into_splat_iadd(i64, i64) -> i64x2 {
block0(v0: i64, v1: i64):
v2 = splat.i64x2 v0
v3 = splat.i64x2 v1
v4 = iadd.i64x2 v2, v3
return v4
; check: v5 = iadd v0, v1
; check: v6 = splat.i64x2 v5
; check: return v6
}

function %isub_splat_into_splat_isub(i64, i64) -> i64x2 {
block0(v0: i64, v1: i64):
v2 = splat.i64x2 v0
v3 = splat.i64x2 v1
v4 = isub.i64x2 v2, v3
return v4
; check: v5 = isub v0, v1
; check: v6 = splat.i64x2 v5
; check: return v6
}

function %imul_splat_into_splat_imul(i64, i64) -> i64x2 {
block0(v0: i64, v1: i64):
v2 = splat.i64x2 v0
v3 = splat.i64x2 v1
v4 = imul.i64x2 v2, v3
return v4
; check: v5 = imul v0, v1
; check: v6 = splat.i64x2 v5
; check: return v6
}

function %smulhi_splat_into_splat_smulhi(i64, i64) -> i64x2 {
block0(v0: i64, v1: i64):
v2 = splat.i64x2 v0
v3 = splat.i64x2 v1
v4 = smulhi.i64x2 v2, v3
return v4
; check: v5 = smulhi v0, v1
; check: v6 = splat.i64x2 v5
; check: return v6
}

function %umulhi_splat_into_splat_umulhi(i64, i64) -> i64x2 {
block0(v0: i64, v1: i64):
v2 = splat.i64x2 v0
v3 = splat.i64x2 v1
v4 = umulhi.i64x2 v2, v3
return v4
; check: v5 = umulhi v0, v1
; check: v6 = splat.i64x2 v5
; check: return v6
}

function %ineg_splat_into_splat_ineg(i64) -> i64x2 {
block0(v0: i64):
v1 = splat.i64x2 v0
v2 = ineg.i64x2 v1
return v2
; check: v3 = ineg v0
; check: v4 = splat.i64x2 v3
; check: return v4
}

function %iabs_splat_into_splat_iabs(i64) -> i64x2 {
block0(v0: i64):
v1 = splat.i64x2 v0
v2 = iabs.i64x2 v1
return v2
; check: v3 = iabs v0
; check: v4 = splat.i64x2 v3
; check: return v4
}

function %popcnt_splat_into_splat_popcnt(i64) -> i64x2 {
block0(v0: i64):
v1 = splat.i64x2 v0
v2 = popcnt.i64x2 v1
return v2
; check: v3 = popcnt v0
; check: v4 = splat.i64x2 v3
; check: return v4
}

function %smin_splat_into_splat_smin(i64, i64) -> i64x2 {
block0(v0: i64, v1: i64):
v2 = splat.i64x2 v0
v3 = splat.i64x2 v1
v4 = smin.i64x2 v2, v3
return v4
; check: v5 = smin v0, v1
; check: v6 = splat.i64x2 v5
; check: return v6
}

function %umin_splat_into_splat_umin(i64, i64) -> i64x2 {
block0(v0: i64, v1: i64):
v2 = splat.i64x2 v0
v3 = splat.i64x2 v1
v4 = umin.i64x2 v2, v3
return v4
; check: v5 = umin v0, v1
; check: v6 = splat.i64x2 v5
; check: return v6
}

function %smax_splat_into_splat_smax(i64, i64) -> i64x2 {
block0(v0: i64, v1: i64):
v2 = splat.i64x2 v0
v3 = splat.i64x2 v1
v4 = smax.i64x2 v2, v3
return v4
; check: v5 = smax v0, v1
; check: v6 = splat.i64x2 v5
; check: return v6
}

function %umax_splat_into_splat_umax(i64, i64) -> i64x2 {
block0(v0: i64, v1: i64):
v2 = splat.i64x2 v0
v3 = splat.i64x2 v1
v4 = umax.i64x2 v2, v3
return v4
; check: v5 = umax v0, v1
; check: v6 = splat.i64x2 v5
; check: return v6
}

function %avg_round_splat_into_splat_avg_round(i64, i64) -> i64x2 {
block0(v0: i64, v1: i64):
v2 = splat.i64x2 v0
v3 = splat.i64x2 v1
v4 = avg_round.i64x2 v2, v3
return v4
; check: v5 = avg_round v0, v1
; check: v6 = splat.i64x2 v5
; check: return v6
}

function %rotl_splat_into_splat_rotl(i64, i64) -> i64x2 {
block0(v0: i64, v1: i64):
v2 = splat.i64x2 v0
v3 = rotl.i64x2 v2, v1
return v3
; check: v4 = rotl v0, v1
; check: v5 = splat.i64x2 v4
; check: return v5
}

function %rotr_splat_into_splat_rotr(i64, i64) -> i64x2 {
block0(v0: i64, v1: i64):
v2 = splat.i64x2 v0
v3 = rotr.i64x2 v2, v1
return v3
; check: v4 = rotr v0, v1
; check: v5 = splat.i64x2 v4
; check: return v5
}

function %ishl_splat_into_splat_ishl(i64, i64) -> i64x2 {
block0(v0: i64, v1: i64):
v2 = splat.i64x2 v0
v3 = ishl.i64x2 v2, v1
return v3
; check: v4 = ishl v0, v1
; check: v5 = splat.i64x2 v4
; check: return v5
}

function %ushr_splat_into_splat_ushr(i64, i64) -> i64x2 {
block0(v0: i64, v1: i64):
v2 = splat.i64x2 v0
v3 = ushr.i64x2 v2, v1
return v3
; check: v4 = ushr v0, v1
; check: v5 = splat.i64x2 v4
; check: return v5
}

function %sshr_splat_into_splat_sshr(i64, i64) -> i64x2 {
block0(v0: i64, v1: i64):
v2 = splat.i64x2 v0
v3 = sshr.i64x2 v2, v1
return v3
; check: v4 = sshr v0, v1
; check: v5 = splat.i64x2 v4
; check: return v5
}