This patch adds support for conditional multiplication and division.
It's mostly mechanical, but a few notes:
* The *_optab name and the .md names are the same as the unconditional
forms, just with "cond_" added to the front. This means we still
have the awkward difference between sdiv and div, etc.
* It was easier to retain the difference between integer and FP
division in the function names, given that they map to different
tree codes (TRUNC_DIV_EXPR and RDIV_EXPR).
* SVE has no direct support for IFN_COND_MOD, but it seemed more
consistent to add it anyway.
* Adding IFN_COND_MUL enables an extra fully-masked reduction
in gcc.dg/vect/pr53773.c.
* In practice we don't actually use the integer division forms without
if-conversion support (added by a later patch).
2018-05-25 Richard Sandiford <richard.sandiford@linaro.org>
gcc/
* doc/sourcebuild.texi (vect_double_cond_arith): Include
multiplication and division.
* doc/md.texi (cond_mul@var{m}, cond_div@var{m}, cond_mod@var{m})
(cond_udiv@var{m}, cond_umod@var{m}): Document.
* optabs.def (cond_smul_optab, cond_sdiv_optab, cond_smod_optab)
(cond_udiv_optab, cond_umod_optab): New optabs.
* internal-fn.def (IFN_COND_MUL, IFN_COND_DIV, IFN_COND_MOD)
(IFN_COND_RDIV): New internal functions.
* internal-fn.c (get_conditional_internal_fn): Handle TRUNC_DIV_EXPR,
TRUNC_MOD_EXPR and RDIV_EXPR.
* match.pd (UNCOND_BINARY, COND_BINARY): Handle them.
* config/aarch64/iterators.md (UNSPEC_COND_MUL, UNSPEC_COND_DIV):
New unspecs.
(SVE_INT_BINARY): Include mult.
(SVE_COND_FP_BINARY): Include UNSPEC_MUL and UNSPEC_DIV.
(optab, sve_int_op): Handle mult.
(optab, sve_fp_op, commutative): Handle UNSPEC_COND_MUL and
UNSPEC_COND_DIV.
* config/aarch64/aarch64-sve.md (cond_<optab><mode>): New pattern
for SVE_INT_BINARY_SD.
gcc/testsuite/
* lib/target-supports.exp
(check_effective_target_vect_double_cond_arith): Include
multiplication and division.
* gcc.dg/vect/pr53773.c: Do not expect a scalar tail when using
fully-masked loops with a fixed vector length.
* gcc.dg/vect/vect-cond-arith-1.c: Add multiplication and division
tests.
* gcc.target/aarch64/sve/vcond_8.c: Likewise.
* gcc.target/aarch64/sve/vcond_9.c: Likewise.
* gcc.target/aarch64/sve/vcond_12.c: Add multiplication tests.
From-SVN: r260713
+2018-05-25 Richard Sandiford <richard.sandiford@linaro.org>
+
+ * doc/sourcebuild.texi (vect_double_cond_arith): Include
+ multiplication and division.
+ * doc/md.texi (cond_mul@var{m}, cond_div@var{m}, cond_mod@var{m})
+ (cond_udiv@var{m}, cond_umod@var{m}): Document.
+ * optabs.def (cond_smul_optab, cond_sdiv_optab, cond_smod_optab)
+ (cond_udiv_optab, cond_umod_optab): New optabs.
+ * internal-fn.def (IFN_COND_MUL, IFN_COND_DIV, IFN_COND_MOD)
+ (IFN_COND_RDIV): New internal functions.
+ * internal-fn.c (get_conditional_internal_fn): Handle TRUNC_DIV_EXPR,
+ TRUNC_MOD_EXPR and RDIV_EXPR.
+ * match.pd (UNCOND_BINARY, COND_BINARY): Handle them.
+ * config/aarch64/iterators.md (UNSPEC_COND_MUL, UNSPEC_COND_DIV):
+ New unspecs.
+ (SVE_INT_BINARY): Include mult.
+ (SVE_COND_FP_BINARY): Include UNSPEC_MUL and UNSPEC_DIV.
+ (optab, sve_int_op): Handle mult.
+ (optab, sve_fp_op, commutative): Handle UNSPEC_COND_MUL and
+ UNSPEC_COND_DIV.
+ * config/aarch64/aarch64-sve.md (cond_<optab><mode>): New pattern
+ for SVE_INT_BINARY_SD.
+
2018-05-25 Richard Sandiford <richard.sandiford@linaro.org>
* config/aarch64/iterators.md (SVE_INT_BINARY_SD): New code iterator.
aarch64_sve_prepare_conditional_op (operands, 5, commutative_p);
})
+(define_expand "cond_<optab><mode>"
+ [(set (match_operand:SVE_SDI 0 "register_operand")
+ (unspec:SVE_SDI
+ [(match_operand:<VPRED> 1 "register_operand")
+ (SVE_INT_BINARY_SD:SVE_SDI
+ (match_operand:SVE_SDI 2 "register_operand")
+ (match_operand:SVE_SDI 3 "register_operand"))
+ (match_operand:SVE_SDI 4 "register_operand")]
+ UNSPEC_SEL))]
+ "TARGET_SVE"
+{
+ bool commutative_p = (GET_RTX_CLASS (<CODE>) == RTX_COMM_ARITH);
+ aarch64_sve_prepare_conditional_op (operands, 5, commutative_p);
+})
+
;; Predicated integer operations.
(define_insn "*cond_<optab><mode>"
[(set (match_operand:SVE_I 0 "register_operand" "=w")
"<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
)
+(define_insn "*cond_<optab><mode>"
+ [(set (match_operand:SVE_SDI 0 "register_operand" "=w")
+ (unspec:SVE_SDI
+ [(match_operand:<VPRED> 1 "register_operand" "Upl")
+ (SVE_INT_BINARY_SD:SVE_SDI
+ (match_operand:SVE_SDI 2 "register_operand" "0")
+ (match_operand:SVE_SDI 3 "register_operand" "w"))
+ (match_dup 2)]
+ UNSPEC_SEL))]
+ "TARGET_SVE"
+ "<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
+)
+
;; Predicated integer operations with the operands reversed.
(define_insn "*cond_<optab><mode>"
[(set (match_operand:SVE_I 0 "register_operand" "=w")
"<sve_int_op>r\t%0.<Vetype>, %1/m, %0.<Vetype>, %2.<Vetype>"
)
+(define_insn "*cond_<optab><mode>"
+ [(set (match_operand:SVE_SDI 0 "register_operand" "=w")
+ (unspec:SVE_SDI
+ [(match_operand:<VPRED> 1 "register_operand" "Upl")
+ (SVE_INT_BINARY_SD:SVE_SDI
+ (match_operand:SVE_SDI 2 "register_operand" "w")
+ (match_operand:SVE_SDI 3 "register_operand" "0"))
+ (match_dup 3)]
+ UNSPEC_SEL))]
+ "TARGET_SVE"
+ "<sve_int_op>r\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>"
UNSPEC_UMUL_HIGHPART ; Used in aarch64-sve.md.
UNSPEC_COND_ADD ; Used in aarch64-sve.md.
UNSPEC_COND_SUB ; Used in aarch64-sve.md.
+ UNSPEC_COND_MUL ; Used in aarch64-sve.md.
+ UNSPEC_COND_DIV ; Used in aarch64-sve.md.
UNSPEC_COND_MAX ; Used in aarch64-sve.md.
UNSPEC_COND_MIN ; Used in aarch64-sve.md.
UNSPEC_COND_LT ; Used in aarch64-sve.md.
;; SVE floating-point unary operations.
(define_code_iterator SVE_FP_UNARY [neg abs sqrt])
-(define_code_iterator SVE_INT_BINARY [plus minus smax umax smin umin
+(define_code_iterator SVE_INT_BINARY [plus minus mult smax umax smin umin
and ior xor])
(define_code_iterator SVE_INT_BINARY_REV [minus])
(neg "neg")
(plus "add")
(minus "sub")
+ (mult "mul")
(div "div")
(udiv "udiv")
(ss_plus "qadd")
;; The integer SVE instruction that implements an rtx code.
(define_code_attr sve_int_op [(plus "add")
(minus "sub")
+ (mult "mul")
(div "sdiv")
(udiv "udiv")
(neg "neg")
(define_int_iterator MUL_HIGHPART [UNSPEC_SMUL_HIGHPART UNSPEC_UMUL_HIGHPART])
(define_int_iterator SVE_COND_FP_BINARY [UNSPEC_COND_ADD UNSPEC_COND_SUB
+ UNSPEC_COND_MUL UNSPEC_COND_DIV
UNSPEC_COND_MAX UNSPEC_COND_MIN])
-(define_int_iterator SVE_COND_FP_BINARY_REV [UNSPEC_COND_SUB])
+(define_int_iterator SVE_COND_FP_BINARY_REV [UNSPEC_COND_SUB UNSPEC_COND_DIV])
(define_int_iterator SVE_COND_FP_CMP [UNSPEC_COND_LT UNSPEC_COND_LE
UNSPEC_COND_EQ UNSPEC_COND_NE
(UNSPEC_XORV "xor")
(UNSPEC_COND_ADD "add")
(UNSPEC_COND_SUB "sub")
+ (UNSPEC_COND_MUL "mul")
+ (UNSPEC_COND_DIV "div")
(UNSPEC_COND_MAX "smax")
(UNSPEC_COND_MIN "smin")])
(define_int_attr sve_fp_op [(UNSPEC_COND_ADD "fadd")
(UNSPEC_COND_SUB "fsub")
+ (UNSPEC_COND_MUL "fmul")
+ (UNSPEC_COND_DIV "fdiv")
(UNSPEC_COND_MAX "fmaxnm")
(UNSPEC_COND_MIN "fminnm")])
(define_int_attr commutative [(UNSPEC_COND_ADD "true")
(UNSPEC_COND_SUB "false")
+ (UNSPEC_COND_MUL "true")
+ (UNSPEC_COND_DIV "false")
(UNSPEC_COND_MIN "true")
(UNSPEC_COND_MAX "true")])
@cindex @code{cond_add@var{mode}} instruction pattern
@cindex @code{cond_sub@var{mode}} instruction pattern
+@cindex @code{cond_mul@var{mode}} instruction pattern
+@cindex @code{cond_div@var{mode}} instruction pattern
+@cindex @code{cond_udiv@var{mode}} instruction pattern
+@cindex @code{cond_mod@var{mode}} instruction pattern
+@cindex @code{cond_umod@var{mode}} instruction pattern
@cindex @code{cond_and@var{mode}} instruction pattern
@cindex @code{cond_ior@var{mode}} instruction pattern
@cindex @code{cond_xor@var{mode}} instruction pattern
@cindex @code{cond_umax@var{mode}} instruction pattern
@item @samp{cond_add@var{mode}}
@itemx @samp{cond_sub@var{mode}}
+@itemx @samp{cond_mul@var{mode}}
+@itemx @samp{cond_div@var{mode}}
+@itemx @samp{cond_udiv@var{mode}}
+@itemx @samp{cond_mod@var{mode}}
+@itemx @samp{cond_umod@var{mode}}
@itemx @samp{cond_and@var{mode}}
@itemx @samp{cond_ior@var{mode}}
@itemx @samp{cond_xor@var{mode}}
Target supports hardware vectors of @code{double}.
@item vect_double_cond_arith
-Target supports conditional addition, subtraction, minimum and maximum
-on vectors of @code{double}, via the @code{cond_} optabs.
+Target supports conditional addition, subtraction, multiplication,
+division, minimum and maximum on vectors of @code{double}, via the
+@code{cond_} optabs.
@item vect_element_align_preferred
The target's preferred vector alignment is the same as the element
return IFN_COND_MIN;
case MAX_EXPR:
return IFN_COND_MAX;
+ case TRUNC_DIV_EXPR:
+ return IFN_COND_DIV;
+ case TRUNC_MOD_EXPR:
+ return IFN_COND_MOD;
+ case RDIV_EXPR:
+ return IFN_COND_RDIV;
case BIT_AND_EXPR:
return IFN_COND_AND;
case BIT_IOR_EXPR:
DEF_INTERNAL_OPTAB_FN (COND_ADD, ECF_CONST, cond_add, cond_binary)
DEF_INTERNAL_OPTAB_FN (COND_SUB, ECF_CONST, cond_sub, cond_binary)
+DEF_INTERNAL_OPTAB_FN (COND_MUL, ECF_CONST, cond_smul, cond_binary)
+DEF_INTERNAL_SIGNED_OPTAB_FN (COND_DIV, ECF_CONST, first,
+ cond_sdiv, cond_udiv, cond_binary)
+DEF_INTERNAL_SIGNED_OPTAB_FN (COND_MOD, ECF_CONST, first,
+ cond_smod, cond_umod, cond_binary)
+DEF_INTERNAL_OPTAB_FN (COND_RDIV, ECF_CONST, cond_sdiv, cond_binary)
DEF_INTERNAL_SIGNED_OPTAB_FN (COND_MIN, ECF_CONST, first,
cond_smin, cond_umin, cond_binary)
DEF_INTERNAL_SIGNED_OPTAB_FN (COND_MAX, ECF_CONST, first,
/* Binary operations and their associated IFN_COND_* function. */
(define_operator_list UNCOND_BINARY
plus minus
+ mult trunc_div trunc_mod rdiv
min max
bit_and bit_ior bit_xor)
(define_operator_list COND_BINARY
IFN_COND_ADD IFN_COND_SUB
+ IFN_COND_MUL IFN_COND_DIV IFN_COND_MOD IFN_COND_RDIV
IFN_COND_MIN IFN_COND_MAX
IFN_COND_AND IFN_COND_IOR IFN_COND_XOR)
OPTAB_D (movcc_optab, "mov$acc")
OPTAB_D (cond_add_optab, "cond_add$a")
OPTAB_D (cond_sub_optab, "cond_sub$a")
+OPTAB_D (cond_smul_optab, "cond_mul$a")
+OPTAB_D (cond_sdiv_optab, "cond_div$a")
+OPTAB_D (cond_smod_optab, "cond_mod$a")
+OPTAB_D (cond_udiv_optab, "cond_udiv$a")
+OPTAB_D (cond_umod_optab, "cond_umod$a")
OPTAB_D (cond_and_optab, "cond_and$a")
OPTAB_D (cond_ior_optab, "cond_ior$a")
OPTAB_D (cond_xor_optab, "cond_xor$a")
+2018-05-25 Richard Sandiford <richard.sandiford@linaro.org>
+
+ * lib/target-supports.exp
+ (check_effective_target_vect_double_cond_arith): Include
+ multiplication and division.
+ * gcc.dg/vect/pr53773.c: Do not expect a scalar tail when using
+ fully-masked loops with a fixed vector length.
+ * gcc.dg/vect/vect-cond-arith-1.c: Add multiplication and division
+ tests.
+ * gcc.target/aarch64/sve/vcond_8.c: Likewise.
+ * gcc.target/aarch64/sve/vcond_9.c: Likewise.
+ * gcc.target/aarch64/sve/vcond_12.c: Add multiplication tests.
+
2018-05-25 Richard Sandiford <richard.sandiford@linaro.org>
* gcc.target/aarch64/sve/div_1.c: New test.
return integral+decimal;
}
-/* { dg-final { scan-tree-dump-times "\\* 10" 2 "optimized" } } */
+/* We can avoid a scalar tail when using fully-masked loops with a fixed
+ vector length. */
+/* { dg-final { scan-tree-dump-times "\\* 10" 2 "optimized" { target { { ! vect_fully_masked } || vect_variable_length } } } } */
+/* { dg-final { scan-tree-dump-times "\\* 10" 0 "optimized" { target { vect_fully_masked && { ! vect_variable_length } } } } } */
#define add(A, B) ((A) + (B))
#define sub(A, B) ((A) - (B))
+#define mul(A, B) ((A) * (B))
+#define div(A, B) ((A) / (B))
#define DEF(OP) \
void __attribute__ ((noipa)) \
#define FOR_EACH_OP(T) \
T (add) \
T (sub) \
+ T (mul) \
+ T (div) \
T (__builtin_fmax) \
T (__builtin_fmin)
/* { dg-final { scan-tree-dump { = \.COND_ADD} "optimized" { target vect_double_cond_arith } } } */
/* { dg-final { scan-tree-dump { = \.COND_SUB} "optimized" { target vect_double_cond_arith } } } */
+/* { dg-final { scan-tree-dump { = \.COND_MUL} "optimized" { target vect_double_cond_arith } } } */
+/* { dg-final { scan-tree-dump { = \.COND_RDIV} "optimized" { target vect_double_cond_arith } } } */
/* { dg-final { scan-tree-dump { = \.COND_MAX} "optimized" { target vect_double_cond_arith } } } */
/* { dg-final { scan-tree-dump { = \.COND_MIN} "optimized" { target vect_double_cond_arith } } } */
#define add(A, B) ((A) + (B))
#define sub(A, B) ((A) - (B))
+#define mul(A, B) ((A) * (B))
+#define div(A, B) ((A) / (B))
#define max(A, B) ((A) > (B) ? (A) : (B))
#define min(A, B) ((A) < (B) ? (A) : (B))
#define and(A, B) ((A) & (B))
#define FOR_EACH_INT_TYPE(T, TYPE) \
T (TYPE, TYPE, add) \
T (TYPE, TYPE, sub) \
+ T (TYPE, TYPE, mul) \
T (TYPE, TYPE, max) \
T (TYPE, TYPE, min) \
T (TYPE, TYPE, and) \
#define FOR_EACH_FP_TYPE(T, TYPE, CMPTYPE, SUFFIX) \
T (TYPE, CMPTYPE, add) \
T (TYPE, CMPTYPE, sub) \
+ T (TYPE, CMPTYPE, mul) \
+ /* No div because that gets converted into a mul anyway. */ \
T (TYPE, CMPTYPE, __builtin_fmax##SUFFIX) \
T (TYPE, CMPTYPE, __builtin_fmin##SUFFIX)
/* { dg-final { scan-assembler-not {\tmov\tz[0-9]+\.., z[0-9]+} } } */
-/* { dg-final { scan-assembler-times {\tsel\tz[0-9]+\.b,} 14 } } */
-/* { dg-final { scan-assembler-times {\tsel\tz[0-9]+\.h,} 18 } } */
-/* { dg-final { scan-assembler-times {\tsel\tz[0-9]+\.s,} 18 } } */
-/* { dg-final { scan-assembler-times {\tsel\tz[0-9]+\.d,} 18 } } */
+/* { dg-final { scan-assembler-times {\tsel\tz[0-9]+\.b,} 16 } } */
+/* { dg-final { scan-assembler-times {\tsel\tz[0-9]+\.h,} 21 } } */
+/* { dg-final { scan-assembler-times {\tsel\tz[0-9]+\.s,} 21 } } */
+/* { dg-final { scan-assembler-times {\tsel\tz[0-9]+\.d,} 21 } } */
/* { dg-final { scan-assembler-times {\tadd\tz[0-9]+\.b, p[0-7]/m,} 2 } } */
/* { dg-final { scan-assembler-times {\tadd\tz[0-9]+\.h, p[0-7]/m,} 2 } } */
/* { dg-final { scan-assembler-times {\tsub\tz[0-9]+\.s, p[0-7]/m,} 2 } } */
/* { dg-final { scan-assembler-times {\tsub\tz[0-9]+\.d, p[0-7]/m,} 2 } } */
+/* { dg-final { scan-assembler-times {\tmul\tz[0-9]+\.b, p[0-7]/m,} 2 } } */
+/* { dg-final { scan-assembler-times {\tmul\tz[0-9]+\.h, p[0-7]/m,} 2 } } */
+/* { dg-final { scan-assembler-times {\tmul\tz[0-9]+\.s, p[0-7]/m,} 2 } } */
+/* { dg-final { scan-assembler-times {\tmul\tz[0-9]+\.d, p[0-7]/m,} 2 } } */
+
/* { dg-final { scan-assembler-times {\tsmax\tz[0-9]+\.b, p[0-7]/m,} 1 } } */
/* { dg-final { scan-assembler-times {\tsmax\tz[0-9]+\.h, p[0-7]/m,} 1 } } */
/* { dg-final { scan-assembler-times {\tsmax\tz[0-9]+\.s, p[0-7]/m,} 1 } } */
/* { dg-final { scan-assembler-times {\tfsub\tz[0-9]+\.s, p[0-7]/m,} 1 } } */
/* { dg-final { scan-assembler-times {\tfsub\tz[0-9]+\.d, p[0-7]/m,} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmul\tz[0-9]+\.h, p[0-7]/m,} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmul\tz[0-9]+\.s, p[0-7]/m,} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmul\tz[0-9]+\.d, p[0-7]/m,} 1 } } */
+
/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.h, p[0-7]/m,} 1 } } */
/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.s, p[0-7]/m,} 1 } } */
/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.d, p[0-7]/m,} 1 } } */
#define add(A, B) ((A) + (B))
#define sub(A, B) ((A) - (B))
+#define mul(A, B) ((A) * (B))
+#define div(A, B) ((A) / (B))
#define max(A, B) ((A) > (B) ? (A) : (B))
#define min(A, B) ((A) < (B) ? (A) : (B))
#define and(A, B) ((A) & (B))
#define FOR_EACH_INT_TYPE(T, TYPE) \
T (TYPE, TYPE, add) \
T (TYPE, TYPE, sub) \
+ T (TYPE, TYPE, mul) \
T (TYPE, TYPE, max) \
T (TYPE, TYPE, min) \
T (TYPE, TYPE, and) \
#define FOR_EACH_FP_TYPE(T, TYPE, CMPTYPE, SUFFIX) \
T (TYPE, CMPTYPE, add) \
T (TYPE, CMPTYPE, sub) \
+ T (TYPE, CMPTYPE, mul) \
+ T (TYPE, CMPTYPE, div) \
T (TYPE, CMPTYPE, __builtin_fmax##SUFFIX) \
T (TYPE, CMPTYPE, __builtin_fmin##SUFFIX)
/* { dg-final { scan-assembler-times {\tsub\tz[0-9]+\.s, p[0-7]/m,} 2 } } */
/* { dg-final { scan-assembler-times {\tsub\tz[0-9]+\.d, p[0-7]/m,} 2 } } */
+/* { dg-final { scan-assembler-times {\tmul\tz[0-9]+\.b, p[0-7]/m,} 2 } } */
+/* { dg-final { scan-assembler-times {\tmul\tz[0-9]+\.h, p[0-7]/m,} 2 } } */
+/* { dg-final { scan-assembler-times {\tmul\tz[0-9]+\.s, p[0-7]/m,} 2 } } */
+/* { dg-final { scan-assembler-times {\tmul\tz[0-9]+\.d, p[0-7]/m,} 2 } } */
+
/* { dg-final { scan-assembler-times {\tsmax\tz[0-9]+\.b, p[0-7]/m,} 1 } } */
/* { dg-final { scan-assembler-times {\tsmax\tz[0-9]+\.h, p[0-7]/m,} 1 } } */
/* { dg-final { scan-assembler-times {\tsmax\tz[0-9]+\.s, p[0-7]/m,} 1 } } */
/* { dg-final { scan-assembler-times {\tfsub\tz[0-9]+\.s, p[0-7]/m,} 1 } } */
/* { dg-final { scan-assembler-times {\tfsub\tz[0-9]+\.d, p[0-7]/m,} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmul\tz[0-9]+\.h, p[0-7]/m,} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmul\tz[0-9]+\.s, p[0-7]/m,} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmul\tz[0-9]+\.d, p[0-7]/m,} 1 } } */
+
+/* { dg-final { scan-assembler-times {\tfdiv\tz[0-9]+\.h, p[0-7]/m,} 1 } } */
+/* { dg-final { scan-assembler-times {\tfdiv\tz[0-9]+\.s, p[0-7]/m,} 1 } } */
+/* { dg-final { scan-assembler-times {\tfdiv\tz[0-9]+\.d, p[0-7]/m,} 1 } } */
+
/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.h, p[0-7]/m,} 1 } } */
/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.s, p[0-7]/m,} 1 } } */
/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.d, p[0-7]/m,} 1 } } */
#define add(A, B) ((A) + (B))
#define sub(A, B) ((A) - (B))
+#define mul(A, B) ((A) * (B))
+#define div(A, B) ((A) / (B))
#define max(A, B) ((A) > (B) ? (A) : (B))
#define min(A, B) ((A) < (B) ? (A) : (B))
#define and(A, B) ((A) & (B))
#define FOR_EACH_INT_TYPE(T, TYPE) \
T (TYPE, TYPE, add) \
T (TYPE, TYPE, sub) \
+ T (TYPE, TYPE, mul) \
T (TYPE, TYPE, max) \
T (TYPE, TYPE, min) \
T (TYPE, TYPE, and) \
#define FOR_EACH_FP_TYPE(T, TYPE, CMPTYPE, SUFFIX) \
T (TYPE, CMPTYPE, add) \
T (TYPE, CMPTYPE, sub) \
+ T (TYPE, CMPTYPE, mul) \
+ T (TYPE, CMPTYPE, div) \
T (TYPE, CMPTYPE, __builtin_fmax##SUFFIX) \
T (TYPE, CMPTYPE, __builtin_fmin##SUFFIX)
/* { dg-final { scan-assembler-times {\tsubr\tz[0-9]+\.s, p[0-7]/m,} 2 } } */
/* { dg-final { scan-assembler-times {\tsubr\tz[0-9]+\.d, p[0-7]/m,} 2 } } */
+/* { dg-final { scan-assembler-times {\tmul\tz[0-9]+\.b, p[0-7]/m,} 2 } } */
+/* { dg-final { scan-assembler-times {\tmul\tz[0-9]+\.h, p[0-7]/m,} 2 } } */
+/* { dg-final { scan-assembler-times {\tmul\tz[0-9]+\.s, p[0-7]/m,} 2 } } */
+/* { dg-final { scan-assembler-times {\tmul\tz[0-9]+\.d, p[0-7]/m,} 2 } } */
+
/* { dg-final { scan-assembler-times {\tsmax\tz[0-9]+\.b, p[0-7]/m,} 1 } } */
/* { dg-final { scan-assembler-times {\tsmax\tz[0-9]+\.h, p[0-7]/m,} 1 } } */
/* { dg-final { scan-assembler-times {\tsmax\tz[0-9]+\.s, p[0-7]/m,} 1 } } */
/* { dg-final { scan-assembler-times {\tfsubr\tz[0-9]+\.s, p[0-7]/m,} 1 } } */
/* { dg-final { scan-assembler-times {\tfsubr\tz[0-9]+\.d, p[0-7]/m,} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmul\tz[0-9]+\.h, p[0-7]/m,} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmul\tz[0-9]+\.s, p[0-7]/m,} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmul\tz[0-9]+\.d, p[0-7]/m,} 1 } } */
+
+/* { dg-final { scan-assembler-times {\tfdivr\tz[0-9]+\.h, p[0-7]/m,} 1 } } */
+/* { dg-final { scan-assembler-times {\tfdivr\tz[0-9]+\.s, p[0-7]/m,} 1 } } */
+/* { dg-final { scan-assembler-times {\tfdivr\tz[0-9]+\.d, p[0-7]/m,} 1 } } */
+
/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.h, p[0-7]/m,} 1 } } */
/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.s, p[0-7]/m,} 1 } } */
/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.d, p[0-7]/m,} 1 } } */
return $et_vect_double_saved($et_index)
}
-# Return 1 if the target supports conditional addition, subtraction, minimum
-# and maximum on vectors of double, via the cond_ optabs. Return 0 otherwise.
+# Return 1 if the target supports conditional addition, subtraction,
+# multiplication, division, minimum and maximum on vectors of double,
+# via the cond_ optabs. Return 0 otherwise.
proc check_effective_target_vect_double_cond_arith { } {
return [check_effective_target_aarch64_sve]