summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@linaro.org>2016-11-30 19:08:31 +0000
committerRichard Sandiford <richard.sandiford@linaro.org>2017-11-20 16:01:23 +0000
commit18653f9380f40d4e371c86bafce99c2754f3eb69 (patch)
tree685ec2800367f5752b06f5794796f4f19393a5dd
parentcd6f54736df9dbd2c1c34d07ea25acbdde36e8ca (diff)
downloadgcc-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.h1
-rw-r--r--gcc/config/aarch64/aarch64-sve.md26
-rw-r--r--gcc/config/aarch64/aarch64.c39
-rw-r--r--gcc/config/aarch64/iterators.md5
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])