diff options
author | Richard Sandiford <richard.sandiford@linaro.org> | 2016-11-30 19:08:31 +0000 |
---|---|---|
committer | Richard Sandiford <richard.sandiford@linaro.org> | 2017-11-20 16:01:23 +0000 |
commit | 18653f9380f40d4e371c86bafce99c2754f3eb69 (patch) | |
tree | 685ec2800367f5752b06f5794796f4f19393a5dd | |
parent | cd6f54736df9dbd2c1c34d07ea25acbdde36e8ca (diff) | |
download | gcc-18653f9380f40d4e371c86bafce99c2754f3eb69.tar.gz |
Predicated arithmetic folds
[Branch only patch -- not intended for trunk in its current state]
This patch adds patterns for folding merge-predicated arithmetic of
the form "add/don't add" etc.
I'm not sure that the floating-point pattern is always correct for
-ftrapping-math.
-rw-r--r-- | gcc/config/aarch64/aarch64-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/aarch64/aarch64-sve.md | 26 | ||||
-rw-r--r-- | gcc/config/aarch64/aarch64.c | 39 | ||||
-rw-r--r-- | gcc/config/aarch64/iterators.md | 5 |
4 files changed, 71 insertions, 0 deletions
diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h index 0e388a61664..27a72bb33d0 100644 --- a/gcc/config/aarch64/aarch64-protos.h +++ b/gcc/config/aarch64/aarch64-protos.h @@ -499,6 +499,7 @@ void aarch64_gen_atomic_ldop (enum rtx_code, rtx, rtx, rtx, rtx, rtx); void aarch64_split_atomic_op (enum rtx_code, rtx, rtx, rtx, rtx, rtx, rtx); bool aarch64_gen_adjusted_ldpstp (rtx *, bool, scalar_mode, RTX_CODE); +bool aarch64_simd_identity_value (enum rtx_code, machine_mode, rtx); void aarch64_expand_sve_vec_cmp_int (rtx, rtx_code, rtx, rtx); bool aarch64_expand_sve_vec_cmp_float (rtx, rtx_code, rtx, rtx, bool); diff --git a/gcc/config/aarch64/aarch64-sve.md b/gcc/config/aarch64/aarch64-sve.md index d735359b294..0ab9c7b0ae8 100644 --- a/gcc/config/aarch64/aarch64-sve.md +++ b/gcc/config/aarch64/aarch64-sve.md @@ -1610,6 +1610,19 @@ "<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>" ) +(define_insn "*<optab><mode>3_cond" + [(set (match_operand:SVE_I 0 "register_operand" "=w") + (sve_predicated_comm_int_op:SVE_I + (unspec:SVE_I + [(match_operand:<VPRED> 1 "register_operand" "Upl") + (match_operand:SVE_I 2 "register_operand" "w") + (match_operand:SVE_I 3 "aarch64_constant_vector_operand")] + UNSPEC_SEL) + (match_operand:SVE_I 4 "register_operand" "0")))] + "TARGET_SVE && aarch64_simd_identity_value (<CODE>, <MODE>mode, operands[3])" + "<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %2.<Vetype>" +) + ;; Set operand 0 to the last active element in operand 3, or to tied ;; operand 1 if no elements are active. (define_insn "fold_extract_last_<mode>" @@ -2353,6 +2366,19 @@ "<sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>" ) +(define_insn "*<optab><mode>3_cond" + [(set (match_operand:SVE_F 0 "register_operand" "=w") + (sve_predicated_comm_fp_op:SVE_F + (unspec:SVE_F + [(match_operand:<VPRED> 1 "register_operand" "Upl") + (match_operand:SVE_F 2 "register_operand" "w") + (match_operand:SVE_F 3 "aarch64_constant_vector_operand")] + UNSPEC_SEL) + (match_operand:SVE_F 4 "register_operand" "0")))] + "TARGET_SVE && aarch64_simd_identity_value (<CODE>, <MODE>mode, operands[3])" + "<sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %2.<Vetype>" +) + ;; Shift an SVE vector left and insert a scalar into element 0. (define_insn "vec_shl_insert_<mode>" [(set (match_operand:SVE_ALL 0 "register_operand" "=w, w") diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 1335f55af25..254d3fce680 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -6434,6 +6434,45 @@ static const int aarch64_nzcv_codes[] = 0 /* NV, Any. */ }; +/* CODE is an rtx operation for which there is some identity I such that + (CODE:MODE V I) == (CODE:MODE I V) == V for all V of vector mode MODE. + Return true if X, which also has mode MODE, is that identity. */ + +bool +aarch64_simd_identity_value (enum rtx_code code, machine_mode mode, rtx x) +{ + scalar_mode inner_mode = GET_MODE_INNER (mode); + rtx elt; + switch (code) + { + case PLUS: + case UMAX: + case IOR: + case XOR: + return x == CONST0_RTX (mode); + + case UMIN: + case AND: + return x == CONSTM1_RTX (mode); + + case SMIN: + return (const_vec_duplicate_p (x, &elt) + && CONST_INT_P (elt) + && wi::eq_p (rtx_mode_t (elt, inner_mode), + wi::max_value (inner_mode, SIGNED))); + + case SMAX: + return (const_vec_duplicate_p (x, &elt) + && CONST_INT_P (elt) + && wi::eq_p (rtx_mode_t (elt, inner_mode), + wi::min_value (inner_mode, SIGNED))); + + default: + gcc_unreachable (); + } +} + + /* Print floating-point vector immediate operand X to F, negating it first if NEGATE is true. Return true on success, false if it isn't a constant we can handle. */ diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md index a94b068097d..df5965d7fac 100644 --- a/gcc/config/aarch64/iterators.md +++ b/gcc/config/aarch64/iterators.md @@ -1152,6 +1152,11 @@ ;; Unsigned comparison operators. (define_code_iterator FAC_COMPARISONS [lt le ge gt]) +;; Predicated commutative SVE ops +(define_code_iterator sve_predicated_comm_int_op [plus smin smax umin umax + and ior xor]) +(define_code_iterator sve_predicated_comm_fp_op [plus]) + ;; SVE integer unary operations. (define_code_iterator SVE_INT_UNARY [neg not popcount]) |