Message ID | 20191001132709.87257-3-iii@linux.ibm.com |
---|---|
State | New |
Headers | show |
Series | S/390: Use signaling FP comparison instructions | expand |
Ilya Leoshkevich <iii@linux.ibm.com> writes: > z13 supports only non-signaling vector comparisons. This means we > cannot vectorize LT, LE, GT, GE and LTGT when compiling for z13. > However, we cannot express this restriction today: the code only checks > whether vcond$a$b optab exists, which does not contain information about > the operation. > > Introduce a function that checks whether back-end supports vector > comparisons with individual rtx codes by matching vcond expander's third > argument with a fake comparison with the corresponding rtx code. > > gcc/ChangeLog: > > 2019-08-27 Ilya Leoshkevich <iii@linux.ibm.com> > > PR target/77918 > * optabs-tree.c (vcond_icode_p): New function. > (vcond_eq_icode_p): New function. > (expand_vec_cond_expr_p): Use vcond_icode_p and > vcond_eq_icode_p. > * optabs.c (can_vcond_compare_p): New function. > (get_rtx_code): Use get_rtx_code_safe. > (get_rtx_code_safe): New function. > * optabs.h (can_vcond_compare_p): New function. > (get_rtx_code_safe): Likewise. > --- > gcc/optabs-tree.c | 37 +++++++++++++++++++++++++++++++------ > gcc/optabs.c | 38 ++++++++++++++++++++++++++++++++++---- > gcc/optabs.h | 7 +++++++ > 3 files changed, 72 insertions(+), 10 deletions(-) > > diff --git a/gcc/optabs-tree.c b/gcc/optabs-tree.c > index 8157798cc71..7f505c9cdee 100644 > --- a/gcc/optabs-tree.c > +++ b/gcc/optabs-tree.c > @@ -23,7 +23,10 @@ along with GCC; see the file COPYING3. If not see > #include "coretypes.h" > #include "target.h" > #include "insn-codes.h" > +#include "rtl.h" > #include "tree.h" > +#include "memmodel.h" > +#include "optabs.h" > #include "optabs-tree.h" > #include "stor-layout.h" > > @@ -329,6 +332,28 @@ expand_vec_cmp_expr_p (tree value_type, tree mask_type, enum tree_code code) > return false; > } > > +/* Return true iff vcond_optab/vcondu_optab support the given tree > + comparison. */ Realise it's a bit repetitive in the context of this patch, but... /* Return true iff vcond_optab/vcondu_optab can handle a vector comparison for code CODE, comparing operands of type CMP_OP_TYPE and producing a result of type VALUE_TYPE. */ > + > +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)); > +} > + > +/* Return true iff vcondeq_optab supports the given tree comparison. */ Same idea here. > + > +static bool > +vcond_eq_icode_p (tree value_type, tree cmp_op_type, enum tree_code code) > +{ > + if (code != EQ_EXPR && code != NE_EXPR) > + return false; > + > + return get_vcond_eq_icode (TYPE_MODE (value_type), TYPE_MODE (cmp_op_type)) > + != CODE_FOR_nothing; > +} > + > /* Return TRUE iff, appropriate vector insns are available > for vector cond expr with vector type VALUE_TYPE and a comparison > with operand vector types in CMP_OP_TYPE. */ > @@ -347,14 +372,14 @@ expand_vec_cond_expr_p (tree value_type, tree cmp_op_type, enum tree_code code) > || maybe_ne (GET_MODE_NUNITS (value_mode), GET_MODE_NUNITS (cmp_op_mode))) > return false; > > - if (get_vcond_icode (TYPE_MODE (value_type), TYPE_MODE (cmp_op_type), > - TYPE_UNSIGNED (cmp_op_type)) == CODE_FOR_nothing > - && ((code != EQ_EXPR && code != NE_EXPR) > - || get_vcond_eq_icode (TYPE_MODE (value_type), > - TYPE_MODE (cmp_op_type)) == CODE_FOR_nothing)) > + if (get_rtx_code_safe (code, TYPE_UNSIGNED (cmp_op_type)) > + == LAST_AND_UNUSED_RTX_CODE) > + /* This may happen, for example, if code == SSA_NAME, in which case we > + cannot be certain whether a vector insn is available. */ > return false; I think this should just be: if (TREE_CODE_CLASS (tcode) != tcc_comparison) return false; OK with those changes and without the introduction of get_rtx_code_safe. Thanks, Richard
> Am 03.10.2019 um 14:42 schrieb Richard Sandiford <richard.sandiford@arm.com>: > > Ilya Leoshkevich <iii@linux.ibm.com> writes: >> z13 supports only non-signaling vector comparisons. This means we >> cannot vectorize LT, LE, GT, GE and LTGT when compiling for z13. >> However, we cannot express this restriction today: the code only checks >> whether vcond$a$b optab exists, which does not contain information about >> the operation. >> >> Introduce a function that checks whether back-end supports vector >> comparisons with individual rtx codes by matching vcond expander's third >> argument with a fake comparison with the corresponding rtx code. >> >> gcc/ChangeLog: >> >> 2019-08-27 Ilya Leoshkevich <iii@linux.ibm.com> >> >> PR target/77918 >> * optabs-tree.c (vcond_icode_p): New function. >> (vcond_eq_icode_p): New function. >> (expand_vec_cond_expr_p): Use vcond_icode_p and >> vcond_eq_icode_p. >> * optabs.c (can_vcond_compare_p): New function. >> (get_rtx_code): Use get_rtx_code_safe. >> (get_rtx_code_safe): New function. >> * optabs.h (can_vcond_compare_p): New function. >> (get_rtx_code_safe): Likewise. >> --- >> gcc/optabs-tree.c | 37 +++++++++++++++++++++++++++++++------ >> gcc/optabs.c | 38 ++++++++++++++++++++++++++++++++++---- >> gcc/optabs.h | 7 +++++++ >> 3 files changed, 72 insertions(+), 10 deletions(-) >> >> diff --git a/gcc/optabs-tree.c b/gcc/optabs-tree.c >> index 8157798cc71..7f505c9cdee 100644 >> --- a/gcc/optabs-tree.c >> +++ b/gcc/optabs-tree.c >> @@ -23,7 +23,10 @@ along with GCC; see the file COPYING3. If not see >> #include "coretypes.h" >> #include "target.h" >> #include "insn-codes.h" >> +#include "rtl.h" >> #include "tree.h" >> +#include "memmodel.h" >> +#include "optabs.h" >> #include "optabs-tree.h" >> #include "stor-layout.h" >> >> @@ -329,6 +332,28 @@ expand_vec_cmp_expr_p (tree value_type, tree mask_type, enum tree_code code) >> return false; >> } >> >> +/* Return true iff vcond_optab/vcondu_optab support the given tree >> + comparison. */ > > Realise it's a bit repetitive in the context of this patch, but... > > /* Return true iff vcond_optab/vcondu_optab can handle a vector > comparison for code CODE, comparing operands of type CMP_OP_TYPE and > producing a result of type VALUE_TYPE. */ > >> + >> +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)); >> +} >> + >> +/* Return true iff vcondeq_optab supports the given tree comparison. */ > > Same idea here. > >> + >> +static bool >> +vcond_eq_icode_p (tree value_type, tree cmp_op_type, enum tree_code code) >> +{ >> + if (code != EQ_EXPR && code != NE_EXPR) >> + return false; >> + >> + return get_vcond_eq_icode (TYPE_MODE (value_type), TYPE_MODE (cmp_op_type)) >> + != CODE_FOR_nothing; >> +} >> + >> /* Return TRUE iff, appropriate vector insns are available >> for vector cond expr with vector type VALUE_TYPE and a comparison >> with operand vector types in CMP_OP_TYPE. */ >> @@ -347,14 +372,14 @@ expand_vec_cond_expr_p (tree value_type, tree cmp_op_type, enum tree_code code) >> || maybe_ne (GET_MODE_NUNITS (value_mode), GET_MODE_NUNITS (cmp_op_mode))) >> return false; >> >> - if (get_vcond_icode (TYPE_MODE (value_type), TYPE_MODE (cmp_op_type), >> - TYPE_UNSIGNED (cmp_op_type)) == CODE_FOR_nothing >> - && ((code != EQ_EXPR && code != NE_EXPR) >> - || get_vcond_eq_icode (TYPE_MODE (value_type), >> - TYPE_MODE (cmp_op_type)) == CODE_FOR_nothing)) >> + if (get_rtx_code_safe (code, TYPE_UNSIGNED (cmp_op_type)) >> + == LAST_AND_UNUSED_RTX_CODE) >> + /* This may happen, for example, if code == SSA_NAME, in which case we >> + cannot be certain whether a vector insn is available. */ >> return false; > > I think this should just be: > > if (TREE_CODE_CLASS (tcode) != tcc_comparison) > return false; > > OK with those changes and without the introduction of get_rtx_code_safe. Thanks! I've made the changes, retested, and committed the result as https://gcc.gnu.org/viewcvs/gcc?view=revision&revision=276660 alongside https://gcc.gnu.org/viewcvs/gcc?view=revision&revision=276659 which Richard B. has approved as well. Now only the main S/390 bits remain.. Best regards, Ilya
diff --git a/gcc/optabs-tree.c b/gcc/optabs-tree.c index 8157798cc71..7f505c9cdee 100644 --- a/gcc/optabs-tree.c +++ b/gcc/optabs-tree.c @@ -23,7 +23,10 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "target.h" #include "insn-codes.h" +#include "rtl.h" #include "tree.h" +#include "memmodel.h" +#include "optabs.h" #include "optabs-tree.h" #include "stor-layout.h" @@ -329,6 +332,28 @@ expand_vec_cmp_expr_p (tree value_type, tree mask_type, enum tree_code code) return false; } +/* Return true iff vcond_optab/vcondu_optab support the given tree + comparison. */ + +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)); +} + +/* Return true iff vcondeq_optab supports the given tree comparison. */ + +static bool +vcond_eq_icode_p (tree value_type, tree cmp_op_type, enum tree_code code) +{ + if (code != EQ_EXPR && code != NE_EXPR) + return false; + + return get_vcond_eq_icode (TYPE_MODE (value_type), TYPE_MODE (cmp_op_type)) + != CODE_FOR_nothing; +} + /* Return TRUE iff, appropriate vector insns are available for vector cond expr with vector type VALUE_TYPE and a comparison with operand vector types in CMP_OP_TYPE. */ @@ -347,14 +372,14 @@ expand_vec_cond_expr_p (tree value_type, tree cmp_op_type, enum tree_code code) || maybe_ne (GET_MODE_NUNITS (value_mode), GET_MODE_NUNITS (cmp_op_mode))) return false; - if (get_vcond_icode (TYPE_MODE (value_type), TYPE_MODE (cmp_op_type), - TYPE_UNSIGNED (cmp_op_type)) == CODE_FOR_nothing - && ((code != EQ_EXPR && code != NE_EXPR) - || get_vcond_eq_icode (TYPE_MODE (value_type), - TYPE_MODE (cmp_op_type)) == CODE_FOR_nothing)) + if (get_rtx_code_safe (code, TYPE_UNSIGNED (cmp_op_type)) + == LAST_AND_UNUSED_RTX_CODE) + /* This may happen, for example, if code == SSA_NAME, in which case we + cannot be certain whether a vector insn is available. */ return false; - return true; + return vcond_icode_p (value_type, cmp_op_type, code) + || vcond_eq_icode_p (value_type, cmp_op_type, code); } /* Use the current target and options to initialize diff --git a/gcc/optabs.c b/gcc/optabs.c index 35921e691f9..d759449846e 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -3819,6 +3819,25 @@ 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. */ + +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); +} + /* This function is called when we are going to emit a compare instruction that compares the values found in X and Y, using the rtl operator COMPARISON. @@ -5348,11 +5367,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 - or unsigned operation code. */ +/* Return rtx code for TCODE or LAST_AND_UNUSED_RTX_CODE if it has no RTL + counterpart. Use UNSIGNEDP to select signed or unsigned operation code. */ enum rtx_code -get_rtx_code (enum tree_code tcode, bool unsignedp) +get_rtx_code_safe (enum tree_code tcode, bool unsignedp) { enum rtx_code code; switch (tcode) @@ -5410,11 +5429,22 @@ get_rtx_code (enum tree_code tcode, bool unsignedp) break; default: - gcc_unreachable (); + code = LAST_AND_UNUSED_RTX_CODE; + break; } return code; } +/* Like get_rtx_code_safe, but asserts when given unsupported tree codes. */ + +enum rtx_code +get_rtx_code (enum tree_code tcode, bool unsignedp) +{ + enum rtx_code code = get_rtx_code_safe (tcode, unsignedp); + gcc_assert (code != LAST_AND_UNUSED_RTX_CODE); + 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 897bb5d4443..4cebe231191 100644 --- a/gcc/optabs.h +++ b/gcc/optabs.h @@ -242,6 +242,12 @@ enum can_compare_purpose (without splitting it into pieces). */ 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. */ +extern bool can_vcond_compare_p (enum rtx_code, machine_mode, machine_mode); + extern rtx prepare_operand (enum insn_code, rtx, int, machine_mode, machine_mode, int); /* Emit a pair of rtl insns to compare two rtx's and to jump @@ -356,6 +362,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_safe (enum tree_code tcode, bool unsignedp); extern enum rtx_code get_rtx_code (enum tree_code tcode, bool unsignedp); #endif /* GCC_OPTABS_H */