On Thu, Nov 26, 2020 at 8:27 PM Ilya Leoshkevich via Gcc-patches
<[email protected]> wrote:
>
> Bootstrapped and regtested on x86_64-redhat-linux and
> s390x-redhat-linux. Ok for master?
OK/
Thanks,
Richard.
>
>
> This is the same as dcd2ca63ec5c ("Introduce can_vcond_compare_p
> function"), but for vec_cmp. The reason it's needed is that since
> 5d9ade39b872 ("IBM Z: Fix PR97326: Enable fp compares in vec_cmp")
> and 4acba4859013 ("IBM Z: Restrict vec_cmp<m><n> on z13") s390's vec_cmp
> expander advertises that it supports floating point comparisons except
> signaling ones on z13, but the common code ignores the latter
> restriction.
>
> gcc/ChangeLog:
>
> 2020-11-25 Ilya Leoshkevich <[email protected]>
>
> * optabs-tree.c (vec_cmp_icode_p): New function.
> (vec_cmp_eq_icode_p): New function.
> (expand_vec_cmp_expr_p): Use vec_cmp_icode_p and
> vec_cmp_eq_icode_p.
> (vcond_icode_p): Use get_rtx_code_1, just to be uniform with
> vec_cmp_icode_p.
> * optabs.c (unsigned_optab_p): New function.
> (insn_predicate_matches_p): New function.
> (can_vec_cmp_compare_p): New function.
> (can_vcond_compare_p): Use unsigned_optab_p and
> insn_predicate_matches_p.
> (get_rtx_code): Use get_rtx_code_1.
> (get_rtx_code_1): Version of get_rtx_code that returns UNKNOWN
> instead of asserting.
> * optabs.h (can_vec_cmp_compare_p): New function.
> (get_rtx_code_1): New function.
> ---
> gcc/optabs-tree.c | 47 ++++++++++++++++++++++------
> gcc/optabs.c | 78 ++++++++++++++++++++++++++++++++++++++---------
> gcc/optabs.h | 12 ++++++--
> 3 files changed, 109 insertions(+), 28 deletions(-)
>
> diff --git a/gcc/optabs-tree.c b/gcc/optabs-tree.c
> index b797d018c84..a8968f3dd1a 100644
> --- a/gcc/optabs-tree.c
> +++ b/gcc/optabs-tree.c
> @@ -337,6 +337,35 @@ supportable_convert_operation (enum tree_code code,
> return false;
> }
>
> +/* Return true iff vec_cmp_optab/vec_cmpu_optab can handle a vector
> comparison
> + for code CODE, comparing operands of type VALUE_TYPE and producing a
> result
> + of type MASK_TYPE. */
> +
> +static bool
> +vec_cmp_icode_p (tree value_type, tree mask_type, enum tree_code code)
> +{
> + enum rtx_code rcode = get_rtx_code_1 (code, TYPE_UNSIGNED (value_type));
> + if (rcode == UNKNOWN)
> + return false;
> +
> + return can_vec_cmp_compare_p (rcode, TYPE_MODE (value_type),
> + TYPE_MODE (mask_type));
> +}
> +
> +/* Return true iff vec_cmpeq_optab can handle a vector comparison for code
> + CODE, comparing operands of type VALUE_TYPE and producing a result of type
> + MASK_TYPE. */
> +
> +static bool
> +vec_cmp_eq_icode_p (tree value_type, tree mask_type, enum tree_code code)
> +{
> + if (code != EQ_EXPR && code != NE_EXPR)
> + return false;
> +
> + return get_vec_cmp_eq_icode (TYPE_MODE (value_type), TYPE_MODE (mask_type))
> + != CODE_FOR_nothing;
> +}
> +
> /* Return TRUE if appropriate vector insn is available
> for vector comparison expr with vector type VALUE_TYPE
> and resulting mask with MASK_TYPE. */
> @@ -344,14 +373,8 @@ supportable_convert_operation (enum tree_code code,
> bool
> expand_vec_cmp_expr_p (tree value_type, tree mask_type, enum tree_code code)
> {
> - if (get_vec_cmp_icode (TYPE_MODE (value_type), TYPE_MODE (mask_type),
> - TYPE_UNSIGNED (value_type)) != CODE_FOR_nothing)
> - return true;
> - if ((code == EQ_EXPR || code == NE_EXPR)
> - && (get_vec_cmp_eq_icode (TYPE_MODE (value_type), TYPE_MODE
> (mask_type))
> - != CODE_FOR_nothing))
> - return true;
> - return false;
> + return vec_cmp_icode_p (value_type, mask_type, code)
> + || vec_cmp_eq_icode_p (value_type, mask_type, code);
> }
>
> /* Return true iff vcond_optab/vcondu_optab can handle a vector
> @@ -361,8 +384,12 @@ expand_vec_cmp_expr_p (tree value_type, tree mask_type,
> enum tree_code code)
> static bool
> vcond_icode_p (tree value_type, tree cmp_op_type, enum tree_code code)
> {
> - return can_vcond_compare_p (get_rtx_code (code, TYPE_UNSIGNED
> (cmp_op_type)),
> - TYPE_MODE (value_type), TYPE_MODE
> (cmp_op_type));
> + enum rtx_code rcode = get_rtx_code_1 (code, TYPE_UNSIGNED (cmp_op_type));
> + if (rcode == UNKNOWN)
> + return false;
> +
> + return can_vcond_compare_p (rcode, TYPE_MODE (value_type),
> + TYPE_MODE (cmp_op_type));
> }
>
> /* Return true iff vcondeq_optab can handle a vector comparison for code
> CODE,
> diff --git a/gcc/optabs.c b/gcc/optabs.c
> index 1820b91877a..76045596980 100644
> --- a/gcc/optabs.c
> +++ b/gcc/optabs.c
> @@ -3834,23 +3834,59 @@ can_compare_p (enum rtx_code code, machine_mode mode,
> return 0;
> }
>
> -/* Return whether the backend can emit a vector comparison for code CODE,
> - comparing operands of mode CMP_OP_MODE and producing a result with
> - VALUE_MODE. */
> +/* Return whether RTL code CODE corresponds to an unsigned optab. */
> +
> +static bool
> +unsigned_optab_p (enum rtx_code code)
> +{
> + return code == LTU || code == LEU || code == GTU || code == GEU;
> +}
> +
> +/* Return whether the backend-emitted comparison for code CODE, comparing
> + operands of mode VALUE_MODE and producing a result with MASK_MODE, matches
> + operand OPNO of pattern ICODE. */
> +
> +static bool
> +insn_predicate_matches_p (enum insn_code icode, unsigned int opno,
> + enum rtx_code code, machine_mode mask_mode,
> + machine_mode value_mode)
> +{
> + rtx reg1 = alloca_raw_REG (value_mode, LAST_VIRTUAL_REGISTER + 1);
> + rtx reg2 = alloca_raw_REG (value_mode, LAST_VIRTUAL_REGISTER + 2);
> + rtx test = alloca_rtx_fmt_ee (code, mask_mode, reg1, reg2);
> + return insn_operand_matches (icode, opno, test);
> +}
> +
> +/* Return whether the backend can emit a vector comparison (vec_cmp/vec_cmpu)
> + for code CODE, comparing operands of mode VALUE_MODE and producing a
> result
> + with MASK_MODE. */
> +
> +bool
> +can_vec_cmp_compare_p (enum rtx_code code, machine_mode value_mode,
> + machine_mode mask_mode)
> +{
> + enum insn_code icode
> + = get_vec_cmp_icode (value_mode, mask_mode, unsigned_optab_p (code));
> + if (icode == CODE_FOR_nothing)
> + return false;
> +
> + return insn_predicate_matches_p (icode, 1, code, mask_mode, value_mode);
> +}
> +
> +/* Return whether the backend can emit a vector comparison (vcond/vcondu) for
> + code CODE, comparing operands of mode CMP_OP_MODE and producing a result
> + with VALUE_MODE. */
>
> bool
> can_vcond_compare_p (enum rtx_code code, machine_mode value_mode,
> machine_mode cmp_op_mode)
> {
> - enum insn_code icode;
> - bool unsigned_p = (code == LTU || code == LEU || code == GTU || code ==
> GEU);
> - rtx reg1 = alloca_raw_REG (cmp_op_mode, LAST_VIRTUAL_REGISTER + 1);
> - rtx reg2 = alloca_raw_REG (cmp_op_mode, LAST_VIRTUAL_REGISTER + 2);
> - rtx test = alloca_rtx_fmt_ee (code, value_mode, reg1, reg2);
> -
> - return (icode = get_vcond_icode (value_mode, cmp_op_mode, unsigned_p))
> - != CODE_FOR_nothing
> - && insn_operand_matches (icode, 3, test);
> + enum insn_code icode
> + = get_vcond_icode (value_mode, cmp_op_mode, unsigned_optab_p (code));
> + if (icode == CODE_FOR_nothing)
> + return false;
> +
> + return insn_predicate_matches_p (icode, 3, code, value_mode, cmp_op_mode);
> }
>
> /* Return whether the backend can emit vector set instructions for inserting
> @@ -5403,11 +5439,11 @@ gen_cond_trap (enum rtx_code code, rtx op1, rtx op2,
> rtx tcode)
> return insn;
> }
>
> -/* Return rtx code for TCODE. Use UNSIGNEDP to select signed
> +/* Return rtx code for TCODE or UNKNOWN. Use UNSIGNEDP to select signed
> or unsigned operation code. */
>
> enum rtx_code
> -get_rtx_code (enum tree_code tcode, bool unsignedp)
> +get_rtx_code_1 (enum tree_code tcode, bool unsignedp)
> {
> enum rtx_code code;
> switch (tcode)
> @@ -5465,11 +5501,23 @@ get_rtx_code (enum tree_code tcode, bool unsignedp)
> break;
>
> default:
> - gcc_unreachable ();
> + code = UNKNOWN;
> + break;
> }
> return code;
> }
>
> +/* Return rtx code for TCODE. Use UNSIGNEDP to select signed
> + or unsigned operation code. */
> +
> +enum rtx_code
> +get_rtx_code (enum tree_code tcode, bool unsignedp)
> +{
> + enum rtx_code code = get_rtx_code_1 (tcode, unsignedp);
> + gcc_assert (code != UNKNOWN);
> + return code;
> +}
> +
> /* Return a comparison rtx of mode CMP_MODE for COND. Use UNSIGNEDP to
> select signed or unsigned operators. OPNO holds the index of the
> first comparison operand for insn ICODE. Do not generate the
> diff --git a/gcc/optabs.h b/gcc/optabs.h
> index bfa10c8f71b..84aaa7a9a02 100644
> --- a/gcc/optabs.h
> +++ b/gcc/optabs.h
> @@ -244,9 +244,14 @@ enum can_compare_purpose
> extern int can_compare_p (enum rtx_code, machine_mode,
> enum can_compare_purpose);
>
> -/* Return whether the backend can emit a vector comparison for code CODE,
> - comparing operands of mode CMP_OP_MODE and producing a result with
> - VALUE_MODE. */
> +/* Return whether the backend can emit a vector comparison (vec_cmp/vec_cmpu)
> + for code CODE, comparing operands of mode VALUE_MODE and producing a
> result
> + with MASK_MODE. */
> +extern bool can_vec_cmp_compare_p (enum rtx_code, machine_mode,
> machine_mode);
> +
> +/* Return whether the backend can emit a vector comparison (vcond/vcondu) for
> + code CODE, comparing operands of mode CMP_OP_MODE and producing a result
> + with VALUE_MODE. */
> extern bool can_vcond_compare_p (enum rtx_code, machine_mode, machine_mode);
>
> /* Return whether the backend can emit vector set instructions for inserting
> @@ -366,6 +371,7 @@ extern void expand_insn (enum insn_code icode, unsigned
> int nops,
> extern void expand_jump_insn (enum insn_code icode, unsigned int nops,
> class expand_operand *ops);
>
> +extern enum rtx_code get_rtx_code_1 (enum tree_code tcode, bool unsignedp);
> extern enum rtx_code get_rtx_code (enum tree_code tcode, bool unsignedp);
> extern rtx vector_compare_rtx (machine_mode cmp_mode, enum tree_code tcode,
> tree t_op0, tree t_op1, bool unsignedp,
> --
> 2.25.4
>