Add an "else" argument to IFN_COND_* functions

Richard Biener richard.guenther@gmail.com
Thu May 24 10:17:00 GMT 2018


On Thu, May 24, 2018 at 10:37 AM Richard Sandiford <
richard.sandiford@linaro.org> wrote:

> As suggested by Richard B, this patch changes the IFN_COND_*
> functions so that they take the else value of the ?: operation
> as a final argument, rather than always using argument 1.

> All current callers will still use the equivalent of argument 1,
> so this patch makes the SVE code assert that for now.  Later patches
> add the general case.

> This relies on the earlier "Try harder to preserve operand ties in
> maybe_legitimize_operands"
> https://gcc.gnu.org/ml/gcc-patches/2018-05/msg01199.html

> Tested on aarch64-linux-gnu (with and without SVE), aarch64_be-elf
> and x86_64-linux-gnu.  OK for the non-AArch64 bits?

OK.

Thanks,
Richard.

> Thanks,
> Richard


> 2018-05-24  Richard Sandiford  <richard.sandiford@linaro.org>

> gcc/
>          * doc/md.texi: Update the documentation of the cond_* optabs
>          to mention the new final operand.  Fix GET_MODE_NUNITS call.
>          Describe the scalar case too.
>          * internal-fn.def (IFN_EXTRACT_LAST): Change type to fold_left.
>          * internal-fn.c (expand_cond_unary_optab_fn): Expect 3 operands
>          instead of 2.
>          (expand_cond_binary_optab_fn): Expect 4 operands instead of 3.
>          (get_conditional_internal_fn): Update comment.
>          * tree-vect-loop.c (vectorizable_reduction): Pass the original
>          accumulator value as a final argument to conditional functions.
>          * config/aarch64/aarch64-sve.md (cond_<optab><mode>): Turn into
>          a define_expand and add an "else" operand.  Assert for now that
>          the else operand is equal to operand 2.  Use SVE_INT_BINARY and
>          SVE_COND_FP_BINARY instead of SVE_COND_INT_OP and SVE_COND_FP_OP.
>          (*cond_<optab><mode>): New patterns.
>          * config/aarch64/iterators.md (UNSPEC_COND_SMAX, UNSPEC_COND_UMAX)
>          (UNSPEC_COND_SMIN, UNSPEC_COND_UMIN, UNSPEC_COND_AND,
UNSPEC_COND_ORR)
>          (UNSPEC_COND_EOR): Delete.
>          (optab): Remove associated mappings.
>          (SVE_INT_BINARY): New code iterator.
>          (sve_int_op): Remove int attribute and add "minus" to the code
>          attribute.
>          (SVE_COND_INT_OP): Delete.
>          (SVE_COND_FP_OP): Rename to...
>          (SVE_COND_FP_BINARY): ...this.

> Index: gcc/doc/md.texi
> ===================================================================
> --- gcc/doc/md.texi     2018-05-24 09:31:46.687834412 +0100
> +++ gcc/doc/md.texi     2018-05-24 09:32:10.522816506 +0100
> @@ -6349,13 +6349,21 @@ operand 0, otherwise (operand 2 + operan
>   @itemx @samp{cond_smax@var{mode}}
>   @itemx @samp{cond_umin@var{mode}}
>   @itemx @samp{cond_umax@var{mode}}
> -Perform an elementwise operation on vector operands 2 and 3,
> -under the control of the vector mask in operand 1, and store the result
> -in operand 0.  This is equivalent to:
> +When operand 1 is true, perform an operation on operands 2 and 3 and
> +store the result in operand 0, otherwise store operand 4 in operand 0.
> +The operation works elementwise if the operands are vectors.
> +
> +The scalar case is equivalent to:
> +
> +@smallexample
> +op0 = op1 ? op2 @var{op} op3 : op4;
> +@end smallexample
> +
> +while the vector case is equivalent to:

>   @smallexample
> -for (i = 0; i < GET_MODE_NUNITS (@var{n}); i++)
> -  op0[i] = op1[i] ? op2[i] @var{op} op3[i] : op2[i];
> +for (i = 0; i < GET_MODE_NUNITS (@var{m}); i++)
> +  op0[i] = op1[i] ? op2[i] @var{op} op3[i] : op4[i];
>   @end smallexample

>   where, for example, @var{op} is @code{+} for @samp{cond_add@var{mode}}.
> @@ -6364,8 +6372,9 @@ When defined for floating-point modes, t
>   are not interpreted if @var{op1[i]} is false, just like they would not
>   be in a normal C @samp{?:} condition.

> -Operands 0, 2 and 3 all have mode @var{m}, while operand 1 has the mode
> -returned by @code{TARGET_VECTORIZE_GET_MASK_MODE}.
> +Operands 0, 2, 3 and 4 all have mode @var{m}.  Operand 1 is a scalar
> +integer if @var{m} is scalar, otherwise it has the mode returned by
> +@code{TARGET_VECTORIZE_GET_MASK_MODE}.

>   @cindex @code{neg@var{mode}cc} instruction pattern
>   @item @samp{neg@var{mode}cc}
> Index: gcc/internal-fn.def
> ===================================================================
> --- gcc/internal-fn.def 2018-05-24 09:31:46.687834412 +0100
> +++ gcc/internal-fn.def 2018-05-24 09:32:10.522816506 +0100
> @@ -173,7 +173,7 @@ DEF_INTERNAL_OPTAB_FN (REDUC_XOR, ECF_CO

>   /* Extract the last active element from a vector.  */
>   DEF_INTERNAL_OPTAB_FN (EXTRACT_LAST, ECF_CONST | ECF_NOTHROW,
> -                      extract_last, cond_unary)
> +                      extract_last, fold_left)

>   /* Same, but return the first argument if no elements are active.  */
>   DEF_INTERNAL_OPTAB_FN (FOLD_EXTRACT_LAST, ECF_CONST | ECF_NOTHROW,
> Index: gcc/internal-fn.c
> ===================================================================
> --- gcc/internal-fn.c   2018-05-24 09:31:46.687834412 +0100
> +++ gcc/internal-fn.c   2018-05-24 09:32:10.522816506 +0100
> @@ -2988,10 +2988,10 @@ #define expand_ternary_optab_fn(FN, STMT
>     expand_direct_optab_fn (FN, STMT, OPTAB, 3)

>   #define expand_cond_unary_optab_fn(FN, STMT, OPTAB) \
> -  expand_direct_optab_fn (FN, STMT, OPTAB, 2)
> +  expand_direct_optab_fn (FN, STMT, OPTAB, 3)

>   #define expand_cond_binary_optab_fn(FN, STMT, OPTAB) \
> -  expand_direct_optab_fn (FN, STMT, OPTAB, 3)
> +  expand_direct_optab_fn (FN, STMT, OPTAB, 4)

>   #define expand_fold_extract_optab_fn(FN, STMT, OPTAB) \
>     expand_direct_optab_fn (FN, STMT, OPTAB, 3)
> @@ -3219,12 +3219,19 @@ #define DEF_INTERNAL_FN(CODE, FLAGS, FNS
>     0
>   };

> -/* Return a function that performs the conditional form of CODE, i.e.:
> +/* 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
> +   a binary operation associated with conditional function FN:
> +
> +     LHS = FN (COND, A, B, ELSE)
> +
> +   is equivalent to the C expression:
> +
> +     LHS = COND ? A CODE B : ELSE;

> -     LHS = RHS1 ? RHS2 CODE RHS3 : RHS2
> +   operating elementwise if the operands are vectors.

> -   (operating elementwise if the operands are vectors).  Return IFN_LAST
> -   if no such function exists.  */
> +   Return IFN_LAST if no such function exists.  */

>   internal_fn
>   get_conditional_internal_fn (tree_code code)
> Index: gcc/tree-vect-loop.c
> ===================================================================
> --- gcc/tree-vect-loop.c        2018-05-24 09:31:46.687834412 +0100
> +++ gcc/tree-vect-loop.c        2018-05-24 09:32:10.523816456 +0100
> @@ -7222,8 +7222,9 @@ vectorizable_reduction (gimple *stmt, gi
>                  }
>                tree mask = vect_get_loop_mask (gsi, masks, vec_num *
ncopies,
>                                                vectype_in, i * ncopies +
j);
> -             gcall *call = gimple_build_call_internal (cond_fn, 3, mask,
> -                                                       vop[0], vop[1]);
> +             gcall *call = gimple_build_call_internal (cond_fn, 4, mask,
> +                                                       vop[0], vop[1],
> +                                                       vop[0]);
>                new_temp = make_ssa_name (vec_dest, call);
>                gimple_call_set_lhs (call, new_temp);
>                gimple_call_set_nothrow (call, true);
> Index: gcc/config/aarch64/aarch64-sve.md
> ===================================================================
> --- gcc/config/aarch64/aarch64-sve.md   2018-05-24 09:32:03.433159783
+0100
> +++ gcc/config/aarch64/aarch64-sve.md   2018-05-24 09:32:10.521816556
+0100
> @@ -1787,14 +1787,31 @@ (define_insn "*<maxmin_uns><mode>3"
>     "<maxmin_uns_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
>   )

> +;; Predicated integer operations with select.
> +(define_expand "cond_<optab><mode>"
> +  [(set (match_operand:SVE_I 0 "register_operand")
> +       (unspec:SVE_I
> +         [(match_operand:<VPRED> 1 "register_operand")
> +          (SVE_INT_BINARY:SVE_I
> +            (match_operand:SVE_I 2 "register_operand")
> +            (match_operand:SVE_I 3 "register_operand"))
> +          (match_operand:SVE_I 4 "register_operand")]
> +         UNSPEC_SEL))]
> +  "TARGET_SVE"
> +{
> +  gcc_assert (rtx_equal_p (operands[2], operands[4]));
> +})
> +
>   ;; Predicated integer operations.
> -(define_insn "cond_<optab><mode>"
> +(define_insn "*cond_<optab><mode>"
>     [(set (match_operand:SVE_I 0 "register_operand" "=w")
>          (unspec:SVE_I
>            [(match_operand:<VPRED> 1 "register_operand" "Upl")
> -          (match_operand:SVE_I 2 "register_operand" "0")
> -          (match_operand:SVE_I 3 "register_operand" "w")]
> -         SVE_COND_INT_OP))]
> +          (SVE_INT_BINARY:SVE_I
> +            (match_operand:SVE_I 2 "register_operand" "0")
> +            (match_operand:SVE_I 3 "register_operand" "w"))
> +          (match_dup 2)]
> +         UNSPEC_SEL))]
>     "TARGET_SVE"
>     "<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
>   )
> @@ -2566,14 +2583,35 @@ (define_expand "vec_pack_<su>fix_trunc_v
>     }
>   )

> +;; Predicated floating-point operations with select.
> +(define_expand "cond_<optab><mode>"
> +  [(set (match_operand:SVE_F 0 "register_operand")
> +       (unspec:SVE_F
> +         [(match_operand:<VPRED> 1 "register_operand")
> +          (unspec:SVE_F
> +            [(match_dup 1)
> +             (match_operand:SVE_F 2 "register_operand")
> +             (match_operand:SVE_F 3 "register_operand")]
> +            SVE_COND_FP_BINARY)
> +          (match_operand:SVE_F 4 "register_operand")]
> +         UNSPEC_SEL))]
> +  "TARGET_SVE"
> +{
> +  gcc_assert (rtx_equal_p (operands[2], operands[4]));
> +})
> +
>   ;; Predicated floating-point operations.
> -(define_insn "cond_<optab><mode>"
> +(define_insn "*cond_<optab><mode>"
>     [(set (match_operand:SVE_F 0 "register_operand" "=w")
>          (unspec:SVE_F
>            [(match_operand:<VPRED> 1 "register_operand" "Upl")
> -          (match_operand:SVE_F 2 "register_operand" "0")
> -          (match_operand:SVE_F 3 "register_operand" "w")]
> -         SVE_COND_FP_OP))]
> +          (unspec:SVE_F
> +            [(match_dup 1)
> +             (match_operand:SVE_F 2 "register_operand" "0")
> +             (match_operand:SVE_F 3 "register_operand" "w")]
> +            SVE_COND_FP_BINARY)
> +          (match_dup 2)]
> +         UNSPEC_SEL))]
>     "TARGET_SVE"
>     "<sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
>   )
> Index: gcc/config/aarch64/iterators.md
> ===================================================================
> --- gcc/config/aarch64/iterators.md     2018-05-24 09:32:03.433159783
+0100
> +++ gcc/config/aarch64/iterators.md     2018-05-24 09:32:10.521816556
+0100
> @@ -464,13 +464,6 @@ (define_c_enum "unspec"
>       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_SMAX   ; Used in aarch64-sve.md.
> -    UNSPEC_COND_UMAX   ; Used in aarch64-sve.md.
> -    UNSPEC_COND_SMIN   ; Used in aarch64-sve.md.
> -    UNSPEC_COND_UMIN   ; Used in aarch64-sve.md.
> -    UNSPEC_COND_AND    ; Used in aarch64-sve.md.
> -    UNSPEC_COND_ORR    ; Used in aarch64-sve.md.
> -    UNSPEC_COND_EOR    ; Used in aarch64-sve.md.
>       UNSPEC_COND_LT     ; Used in aarch64-sve.md.
>       UNSPEC_COND_LE     ; Used in aarch64-sve.md.
>       UNSPEC_COND_EQ     ; Used in aarch64-sve.md.
> @@ -1207,6 +1200,9 @@ (define_code_iterator SVE_INT_UNARY [neg
>   ;; 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
> +                                     and ior xor])
> +
>   (define_code_iterator SVE_INT_BINARY_SD [div udiv])

>   ;; SVE integer comparisons.
> @@ -1381,6 +1377,7 @@ (define_mode_attr lconst_atomic [(QI "K"

>   ;; The integer SVE instruction that implements an rtx code.
>   (define_code_attr sve_int_op [(plus "add")
> +                             (minus "sub")
>                                (div "sdiv")
>                                (udiv "udiv")
>                                (neg "neg")
> @@ -1538,14 +1535,7 @@ (define_int_iterator UNPACK_UNSIGNED [UN

>   (define_int_iterator MUL_HIGHPART [UNSPEC_SMUL_HIGHPART
UNSPEC_UMUL_HIGHPART])

> -(define_int_iterator SVE_COND_INT_OP [UNSPEC_COND_ADD UNSPEC_COND_SUB
> -                                     UNSPEC_COND_SMAX UNSPEC_COND_UMAX
> -                                     UNSPEC_COND_SMIN UNSPEC_COND_UMIN
> -                                     UNSPEC_COND_AND
> -                                     UNSPEC_COND_ORR
> -                                     UNSPEC_COND_EOR])
> -
> -(define_int_iterator SVE_COND_FP_OP [UNSPEC_COND_ADD UNSPEC_COND_SUB])
> +(define_int_iterator SVE_COND_FP_BINARY [UNSPEC_COND_ADD
UNSPEC_COND_SUB])

>   (define_int_iterator SVE_COND_FP_CMP [UNSPEC_COND_LT UNSPEC_COND_LE
>                                        UNSPEC_COND_EQ UNSPEC_COND_NE
> @@ -1575,14 +1565,7 @@ (define_int_attr optab [(UNSPEC_ANDF "an
>                          (UNSPEC_IORV "ior")
>                          (UNSPEC_XORV "xor")
>                          (UNSPEC_COND_ADD "add")
> -                       (UNSPEC_COND_SUB "sub")
> -                       (UNSPEC_COND_SMAX "smax")
> -                       (UNSPEC_COND_UMAX "umax")
> -                       (UNSPEC_COND_SMIN "smin")
> -                       (UNSPEC_COND_UMIN "umin")
> -                       (UNSPEC_COND_AND "and")
> -                       (UNSPEC_COND_ORR "ior")
> -                       (UNSPEC_COND_EOR "xor")])
> +                       (UNSPEC_COND_SUB "sub")])

>   (define_int_attr  maxmin_uns [(UNSPEC_UMAXV "umax")
>                                (UNSPEC_UMINV "umin")
> @@ -1793,15 +1776,5 @@ (define_int_attr cmp_op [(UNSPEC_COND_LT
>                           (UNSPEC_COND_GE "ge")
>                           (UNSPEC_COND_GT "gt")])

> -(define_int_attr sve_int_op [(UNSPEC_COND_ADD "add")
> -                            (UNSPEC_COND_SUB "sub")
> -                            (UNSPEC_COND_SMAX "smax")
> -                            (UNSPEC_COND_UMAX "umax")
> -                            (UNSPEC_COND_SMIN "smin")
> -                            (UNSPEC_COND_UMIN "umin")
> -                            (UNSPEC_COND_AND "and")
> -                            (UNSPEC_COND_ORR "orr")
> -                            (UNSPEC_COND_EOR "eor")])
> -
>   (define_int_attr sve_fp_op [(UNSPEC_COND_ADD "fadd")
>                              (UNSPEC_COND_SUB "fsub")])



More information about the Gcc-patches mailing list