memcpy (cond_op.ops, res_op->ops + 1, (num_ops - 1) * sizeof *cond_op.ops);
switch (num_ops - 2)
{
+ case 1:
+ if (!gimple_resimplify1 (seq, &cond_op, valueize))
+ return false;
+ break;
case 2:
if (!gimple_resimplify2 (seq, &cond_op, valueize))
return false;
T (BIT_IOR_EXPR, IFN_COND_IOR) \
T (BIT_XOR_EXPR, IFN_COND_XOR) \
T (LSHIFT_EXPR, IFN_COND_SHL) \
- T (RSHIFT_EXPR, IFN_COND_SHR)
+ T (RSHIFT_EXPR, IFN_COND_SHR) \
+ T (NEGATE_EXPR, IFN_COND_NEG)
/* Return a function that only performs CODE when a certain condition is met
and that uses a given fallback value otherwise. For example, if CODE is
DEF_INTERNAL_OPTAB_FN (COND_FNMA, ECF_CONST, cond_fnma, cond_ternary)
DEF_INTERNAL_OPTAB_FN (COND_FNMS, ECF_CONST, cond_fnms, cond_ternary)
+DEF_INTERNAL_OPTAB_FN (COND_NEG, ECF_CONST, cond_neg, cond_unary)
+
DEF_INTERNAL_OPTAB_FN (RSQRT, ECF_CONST, rsqrt, unary)
DEF_INTERNAL_OPTAB_FN (REDUC_PLUS, ECF_CONST | ECF_NOTHROW,
DEFINE_INT_AND_FLOAT_ROUND_FN (ROUND)
DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
+/* Unary operations and their associated IFN_COND_* function. */
+(define_operator_list UNCOND_UNARY
+ negate)
+(define_operator_list COND_UNARY
+ IFN_COND_NEG)
+
/* Binary operations and their associated IFN_COND_* function. */
(define_operator_list UNCOND_BINARY
plus minus
false, prec)); })
{ build_zero_cst (TREE_TYPE (@0)); }))))))))
+#if GIMPLE
+
+/* Simplify:
+ a = op a1
+ r = cond ? a : b
+ --> r = .COND_FN (cond, a, b)
+and,
+ a = op a1
+ r = cond ? b : a
+ --> r = .COND_FN (~cond, b, a). */
+
+(for uncond_op (UNCOND_UNARY)
+ cond_op (COND_UNARY)
+ (simplify
+ (vec_cond @0 (view_convert? (uncond_op@3 @1)) @2)
+ (with { tree op_type = TREE_TYPE (@3); }
+ (if (vectorized_internal_fn_supported_p (as_internal_fn (cond_op), op_type)
+ && is_truth_type_for (op_type, TREE_TYPE (@0)))
+ (cond_op @0 @1 @2))))
+ (simplify
+ (vec_cond @0 @1 (view_convert? (uncond_op@3 @2)))
+ (with { tree op_type = TREE_TYPE (@3); }
+ (if (vectorized_internal_fn_supported_p (as_internal_fn (cond_op), op_type)
+ && is_truth_type_for (op_type, TREE_TYPE (@0)))
+ (cond_op (bit_not @0) @2 @1)))))
+
/* Simplify:
a = a1 op a2
conditional internal functions must support the same comparisons
inside and outside a VEC_COND_EXPR. */
-#if GIMPLE
(for uncond_op (UNCOND_BINARY)
cond_op (COND_BINARY)
(simplify
OPTAB_D (cond_fms_optab, "cond_fms$a")
OPTAB_D (cond_fnma_optab, "cond_fnma$a")
OPTAB_D (cond_fnms_optab, "cond_fnms$a")
+OPTAB_D (cond_neg_optab, "cond_neg$a")
OPTAB_D (cmov_optab, "cmov$a6")
OPTAB_D (cstore_optab, "cstore$a4")
OPTAB_D (ctrap_optab, "ctrap$a4")
we're relying on combine to merge a SEL and an arithmetic operation,
and the SEL doesn't allow the "false" value to be zero when the "true"
value is a register. */
-/* { dg-final { scan-assembler-times {\tmovprfx\tz[0-9]+, z[0-9]+\n} 14 } } */
+/* { dg-final { scan-assembler-times {\tmovprfx\tz[0-9]+, z[0-9]+\n} 7 } } */
+/* { dg-final { scan-assembler-times {\tmovprfx\tz[0-9]+\.b, p[0-7]/z, z[0-9]+\.b} 1 } } */
+/* { dg-final { scan-assembler-times {\tmovprfx\tz[0-9]+\.h, p[0-7]/z, z[0-9]+\.h} 2 } } */
+/* { dg-final { scan-assembler-times {\tmovprfx\tz[0-9]+\.s, p[0-7]/z, z[0-9]+\.s} 2 } } */
+/* { dg-final { scan-assembler-times {\tmovprfx\tz[0-9]+\.d, p[0-7]/z, z[0-9]+\.d} 2 } } */
/* { dg-final { scan-assembler-not {\tmov\tz[^\n]*z} } } */
/* { dg-final { scan-assembler-not {\tsel\t} } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O3 -mcpu=generic+sve" } */
+
+typedef unsigned char uint8_t;
+
+static inline uint8_t
+x264_clip_uint8(uint8_t x)
+{
+ uint8_t t = -x;
+ uint8_t t1 = x & ~63;
+ return (t1 != 0) ? t : x;
+}
+
+void
+mc_weight(uint8_t *restrict dst, uint8_t *restrict src, int n)
+{
+ for (int x = 0; x < n*16; x++)
+ dst[x] = x264_clip_uint8(src[x]);
+}
+
+/* { dg-final { scan-assembler-not {\tsel} } } */