+2019-08-14 Richard Sandiford <richard.sandiford@arm.com>
+
+ * config/aarch64/predicates.md (aarch64_sve_float_maxmin_immediate)
+ (aarch64_sve_float_maxmin_operand): New predicates.
+ * config/aarch64/constraints.md (vsB): New constraint.
+ (vsM): Fix typo.
+ * config/aarch64/iterators.md (sve_pred_fp_rhs2_operand): Use
+ aarch64_sve_float_maxmin_operand for UNSPEC_COND_FMAXNM and
+ UNSPEC_COND_FMINNM.
+ * config/aarch64/aarch64-sve.md (<maxmin_uns><SVE_F:mode>3):
+ Use aarch64_sve_float_maxmin_operand for operand 2.
+ (*<SVE_COND_FP_MAXMIN_PUBLIC:optab><SVE_F:mode>3): Likewise.
+ Add alternatives for the constant forms.
+
2019-08-14 Richard Sandiford <richard.sandiford@arm.com>
* config/aarch64/constraints.md (vsb): New constraint.
[(match_dup 3)
(const_int SVE_RELAXED_GP)
(match_operand:SVE_F 1 "register_operand")
- (match_operand:SVE_F 2 "register_operand")]
+ (match_operand:SVE_F 2 "aarch64_sve_float_maxmin_operand")]
SVE_COND_FP_MAXMIN_PUBLIC))]
"TARGET_SVE"
{
;; Predicated floating-point maximum/minimum.
(define_insn "*<optab><mode>3"
- [(set (match_operand:SVE_F 0 "register_operand" "=w, ?&w")
+ [(set (match_operand:SVE_F 0 "register_operand" "=w, w, ?&w, ?&w")
(unspec:SVE_F
- [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
+ [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl, Upl")
(match_operand:SI 4 "aarch64_sve_gp_strictness")
- (match_operand:SVE_F 2 "register_operand" "%0, w")
- (match_operand:SVE_F 3 "register_operand" "w, w")]
+ (match_operand:SVE_F 2 "register_operand" "%0, 0, w, w")
+ (match_operand:SVE_F 3 "aarch64_sve_float_maxmin_operand" "vsB, w, vsB, w")]
SVE_COND_FP_MAXMIN_PUBLIC))]
"TARGET_SVE"
"@
+ <sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, #%3
<sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
+ movprfx\t%0, %2\;<sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, #%3
movprfx\t%0, %2\;<sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
- [(set_attr "movprfx" "*,yes")]
+ [(set_attr "movprfx" "*,*,yes,yes")]
)
;; Merging forms are handled through SVE_COND_FP_BINARY.
and FSUB operations."
(match_operand 0 "aarch64_sve_float_arith_immediate"))
+;; "B" for "bound".
+(define_constraint "vsB"
+ "@internal
+ A constraint that matches an immediate operand valid for SVE FMAX
+ and FMIN operations."
+ (match_operand 0 "aarch64_sve_float_maxmin_immediate"))
+
(define_constraint "vsM"
"@internal
- A constraint that matches an imediate operand valid for SVE FMUL
+ A constraint that matches an immediate operand valid for SVE FMUL
operations."
(match_operand 0 "aarch64_sve_float_mul_immediate"))
(define_int_attr sve_pred_fp_rhs2_operand
[(UNSPEC_COND_FADD "aarch64_sve_float_arith_with_sub_operand")
(UNSPEC_COND_FDIV "register_operand")
- (UNSPEC_COND_FMAXNM "register_operand")
- (UNSPEC_COND_FMINNM "register_operand")
+ (UNSPEC_COND_FMAXNM "aarch64_sve_float_maxmin_operand")
+ (UNSPEC_COND_FMINNM "aarch64_sve_float_maxmin_operand")
(UNSPEC_COND_FMUL "aarch64_sve_float_mul_operand")
(UNSPEC_COND_FSUB "register_operand")])
(and (match_code "const,const_vector")
(match_test "aarch64_sve_float_mul_immediate_p (op)")))
+(define_predicate "aarch64_sve_float_maxmin_immediate"
+ (and (match_code "const_vector")
+ (ior (match_test "op == CONST0_RTX (GET_MODE (op))")
+ (match_test "op == CONST1_RTX (GET_MODE (op))"))))
+
(define_predicate "aarch64_sve_arith_operand"
(ior (match_operand 0 "register_operand")
(match_operand 0 "aarch64_sve_arith_immediate")))
(ior (match_operand 0 "register_operand")
(match_operand 0 "aarch64_sve_float_mul_immediate")))
+(define_predicate "aarch64_sve_float_maxmin_operand"
+ (ior (match_operand 0 "register_operand")
+ (match_operand 0 "aarch64_sve_float_maxmin_immediate")))
+
(define_predicate "aarch64_sve_vec_perm_operand"
(ior (match_operand 0 "register_operand")
(match_operand 0 "aarch64_constant_vector_operand")))
+2019-08-14 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.target/aarch64/sve/fmaxnm_1.c: New test.
+ * gcc.target/aarch64/sve/fminnm_1.c: Likewise.
+
2019-08-14 Richard Sandiford <richard.sandiford@arm.com>
* gcc.target/aarch64/sve/smax_1.c: New test.
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include <stdint.h>
+
+#ifndef FN
+#define FN(X) __builtin_fmax##X
+#endif
+
+#define DEF_LOOP(FN, TYPE, NAME, CONST) \
+ void __attribute__ ((noipa)) \
+ test_##TYPE##_##NAME (TYPE *__restrict x, \
+ TYPE *__restrict y, int n) \
+ { \
+ for (int i = 0; i < n; ++i) \
+ x[i] = FN (y[i], CONST); \
+ }
+
+#define TEST_TYPE(T, FN, TYPE) \
+ T (FN, TYPE, zero, 0) \
+ T (FN, TYPE, one, 1) \
+ T (FN, TYPE, two, 2)
+
+#define TEST_ALL(T) \
+ TEST_TYPE (T, FN (f16), _Float16) \
+ TEST_TYPE (T, FN (f32), float) \
+ TEST_TYPE (T, FN (f64), double)
+
+TEST_ALL (DEF_LOOP)
+
+/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #0\.0\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #0\.0\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.d, p[0-7]/m, z[0-9]+\.d, #0\.0\n} 1 } } */
+
+/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #1\.0\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #1\.0\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.d, p[0-7]/m, z[0-9]+\.d, #1\.0\n} 1 } } */
+
+/* { dg-final { scan-assembler-times {\tfmov\tz[0-9]+\.h, #2\.0} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmov\tz[0-9]+\.s, #2\.0} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmov\tz[0-9]+\.d, #2\.0} 1 } } */
+
+/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, z[0-9]+\.h\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, z[0-9]+\.s\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.d, p[0-7]/m, z[0-9]+\.d, z[0-9]+\.d\n} 1 } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#define FN(X) __builtin_fmin##X
+#include "fmaxnm_1.c"
+
+/* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #0\.0\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #0\.0\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.d, p[0-7]/m, z[0-9]+\.d, #0\.0\n} 1 } } */
+
+/* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #1\.0\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #1\.0\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.d, p[0-7]/m, z[0-9]+\.d, #1\.0\n} 1 } } */
+
+/* { dg-final { scan-assembler-times {\tfmov\tz[0-9]+\.h, #2\.0} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmov\tz[0-9]+\.s, #2\.0} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmov\tz[0-9]+\.d, #2\.0} 1 } } */
+
+/* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, z[0-9]+\.h\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, z[0-9]+\.s\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.d, p[0-7]/m, z[0-9]+\.d, z[0-9]+\.d\n} 1 } } */