Message ID | 20201126192609.284642-1-iii@linux.ibm.com |
---|---|
State | New |
Headers | show |
Series | Introduce can_vec_cmp_compare_p | expand |
On Thu, Nov 26, 2020 at 8:27 PM Ilya Leoshkevich via Gcc-patches <gcc-patches@gcc.gnu.org> 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 <iii@linux.ibm.com> > > * 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 >
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,