Message ID | 20240710140602.1707875-3-victor.donascimento@arm.com |
---|---|
State | New |
Headers | show |
Series | Make `dot_prod' a convert-type optab | expand |
Hi Victor, > -----Original Message----- > From: Victor Do Nascimento <victor.donascimento@arm.com> > Sent: Wednesday, July 10, 2024 3:06 PM > To: gcc-patches@gcc.gnu.org > Cc: Richard Sandiford <Richard.Sandiford@arm.com>; Richard Earnshaw > <Richard.Earnshaw@arm.com>; Victor Do Nascimento > <Victor.DoNascimento@arm.com> > Subject: [PATCH 02/10] autovectorizer: Add basic support for convert optabs > > Given the shift from modeling dot products as direct optabs to > treating them as conversion optabs, we make necessary changes to the > autovectorizer code to ensure that given the relevant tree code, > together with the input and output data modes, we can retrieve the > relevant optab and subsequently the insn_code for it. > > gcc/ChangeLog: > > * gimple-match-exports.cc (directly_supported_p): Add overload > for conversion-type optabs. > * gimple-match.h (directly_supported_p): Add new function > prototype. > * optabs.cc (expand_widen_pattern_expr): Make the > DOT_PROD_EXPR tree code use `find_widening_optab_handler' to > retrieve icode. > * tree-vect-loop.cc (vect_is_emulated_mixed_dot_prod): make it > call conversion-type overloaded `directly_supported_p'. > * tree-vect-patterns.cc (vect_supportable_conv_optab_p): New. > (vect_recog_dot_prod_pattern): s/direct/conv/ in call to > `vect_supportable_direct_optab_p'. > --- > gcc/gimple-match-exports.cc | 18 ++++++++++++++++ > gcc/gimple-match.h | 2 ++ > gcc/optabs.cc | 3 ++- > gcc/tree-vect-loop.cc | 1 + > gcc/tree-vect-patterns.cc | 43 +++++++++++++++++++++++++++++++++++-- > 5 files changed, 64 insertions(+), 3 deletions(-) > > diff --git a/gcc/gimple-match-exports.cc b/gcc/gimple-match-exports.cc > index aacf3ff0414..c079fa1fb19 100644 > --- a/gcc/gimple-match-exports.cc > +++ b/gcc/gimple-match-exports.cc > @@ -1381,6 +1381,24 @@ directly_supported_p (code_helper code, tree type, > optab_subtype query_type) > && direct_internal_fn_supported_p (ifn, type, OPTIMIZE_FOR_SPEED)); > } > > +/* As above, overloading the function for conversion-type optabs. */ > +bool > +directly_supported_p (code_helper code, tree type_out, tree type_in, > + optab_subtype query_type) > +{ > + > + if (code.is_tree_code ()) > + { > + convert_optab optab = optab_for_tree_code (tree_code (code), type_in, > + query_type); > + return (optab != unknown_optab > + && convert_optab_handler (optab, TYPE_MODE (type_out), > + TYPE_MODE (type_in)) != > CODE_FOR_nothing); > + } > + gcc_unreachable (); > +} > + Since the argument is a code_helper, why not provide the implementation for internal_fn as well, similar to the existing directly_supported_p. You can get the optab from an ifn with direct_internal_fn_optab. > /* A wrapper around the internal-fn.cc versions of get_conditional_internal_fn > for a code_helper CODE operating on type TYPE. */ > > diff --git a/gcc/gimple-match.h b/gcc/gimple-match.h > index d710fcbace2..0333a5db00a 100644 > --- a/gcc/gimple-match.h > +++ b/gcc/gimple-match.h > @@ -419,6 +419,8 @@ code_helper canonicalize_code (code_helper, tree); > > #ifdef GCC_OPTABS_TREE_H > bool directly_supported_p (code_helper, tree, optab_subtype = optab_default); > +bool directly_supported_p (code_helper, tree, tree, > + optab_subtype = optab_default); > #endif > > internal_fn get_conditional_internal_fn (code_helper, tree); > diff --git a/gcc/optabs.cc b/gcc/optabs.cc > index 185c5b1a705..32737fb80e8 100644 > --- a/gcc/optabs.cc > +++ b/gcc/optabs.cc > @@ -317,7 +317,8 @@ expand_widen_pattern_expr (const_sepops ops, rtx op0, > rtx op1, rtx wide_op, > widen_pattern_optab > = optab_for_tree_code (ops->code, TREE_TYPE (oprnd0), optab_default); > if (ops->code == WIDEN_MULT_PLUS_EXPR > - || ops->code == WIDEN_MULT_MINUS_EXPR) > + || ops->code == WIDEN_MULT_MINUS_EXPR > + || ops->code == DOT_PROD_EXPR) > icode = find_widening_optab_handler (widen_pattern_optab, > TYPE_MODE (TREE_TYPE (ops->op2)), > tmode0); > diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc > index a64b5082bd1..7e4c1e0f52e 100644 > --- a/gcc/tree-vect-loop.cc > +++ b/gcc/tree-vect-loop.cc > @@ -5289,6 +5289,7 @@ vect_is_emulated_mixed_dot_prod (stmt_vec_info > stmt_info) > > gcc_assert (STMT_VINFO_REDUC_VECTYPE_IN (stmt_info)); > return !directly_supported_p (DOT_PROD_EXPR, > + STMT_VINFO_VECTYPE (stmt_info), > STMT_VINFO_REDUC_VECTYPE_IN (stmt_info), > optab_vector_mixed_sign); > } > diff --git a/gcc/tree-vect-patterns.cc b/gcc/tree-vect-patterns.cc > index 86e893a1c43..c4dd627aa90 100644 > --- a/gcc/tree-vect-patterns.cc > +++ b/gcc/tree-vect-patterns.cc > @@ -248,6 +248,45 @@ vect_supportable_direct_optab_p (vec_info *vinfo, tree > otype, tree_code code, > return true; > } > > +/* Return true if the target supports a vector version of CODE, > + where CODE is known to map to a conversion optab with the given SUBTYPE. > + ITYPE specifies the type of (some of) the scalar inputs and OTYPE > + specifies the type of the scalar result. > + > + When returning true, set *VECOTYPE_OUT to the vector version of OTYPE. > + Also set *VECITYPE_OUT to the vector version of ITYPE if VECITYPE_OUT > + is nonnull. */ > + > +static bool > +vect_supportable_conv_optab_p (vec_info *vinfo, tree otype, tree_code code, > + tree itype, tree *vecotype_out, > + tree *vecitype_out = NULL, > + enum optab_subtype subtype = optab_default) > +{ > + tree vecitype = get_vectype_for_scalar_type (vinfo, itype); > + tree vecotype = get_vectype_for_scalar_type (vinfo, otype); > + if (!vecitype || !vecotype) > + return false; > + > + optab optab = optab_for_tree_code (code, vecitype, subtype); > + if (!optab) > + return false; > + > + insn_code icode = convert_optab_handler (optab, TYPE_MODE (vecotype), > + TYPE_MODE (vecitype)); > + > + if (icode == CODE_FOR_nothing > + || insn_data[icode].operand[0].mode != TYPE_MODE (vecotype) > + || insn_data[icode].operand[1].mode != TYPE_MODE (vecitype)) > + return false; > + > + *vecotype_out = vecotype; > + if (vecitype_out) > + *vecitype_out = vecitype; > + return true; > +} > + Aside from the creation of the vector modes, isn't the rest of this essentially what directly_supported_p does? Thanks for working on this, Tamar > + > /* Round bit precision PRECISION up to a full element. */ > > static unsigned int > @@ -1266,13 +1305,13 @@ vect_recog_dot_prod_pattern (vec_info *vinfo, > half_type = signed_type_for (half_type); > > tree half_vectype; > - if (!vect_supportable_direct_optab_p (vinfo, type, DOT_PROD_EXPR, half_type, > + if (!vect_supportable_conv_optab_p (vinfo, type, DOT_PROD_EXPR, half_type, > type_out, &half_vectype, subtype)) > { > /* We can emulate a mixed-sign dot-product using a sequence of > signed dot-products; see vect_emulate_mixed_dot_prod for details. */ > if (subtype != optab_vector_mixed_sign > - || !vect_supportable_direct_optab_p (vinfo, signed_type_for (type), > + || !vect_supportable_conv_optab_p (vinfo, signed_type_for (type), > DOT_PROD_EXPR, half_type, > type_out, &half_vectype, > optab_vector)) > -- > 2.34.1
diff --git a/gcc/gimple-match-exports.cc b/gcc/gimple-match-exports.cc index aacf3ff0414..c079fa1fb19 100644 --- a/gcc/gimple-match-exports.cc +++ b/gcc/gimple-match-exports.cc @@ -1381,6 +1381,24 @@ directly_supported_p (code_helper code, tree type, optab_subtype query_type) && direct_internal_fn_supported_p (ifn, type, OPTIMIZE_FOR_SPEED)); } +/* As above, overloading the function for conversion-type optabs. */ +bool +directly_supported_p (code_helper code, tree type_out, tree type_in, + optab_subtype query_type) +{ + + if (code.is_tree_code ()) + { + convert_optab optab = optab_for_tree_code (tree_code (code), type_in, + query_type); + return (optab != unknown_optab + && convert_optab_handler (optab, TYPE_MODE (type_out), + TYPE_MODE (type_in)) != CODE_FOR_nothing); + } + gcc_unreachable (); +} + + /* A wrapper around the internal-fn.cc versions of get_conditional_internal_fn for a code_helper CODE operating on type TYPE. */ diff --git a/gcc/gimple-match.h b/gcc/gimple-match.h index d710fcbace2..0333a5db00a 100644 --- a/gcc/gimple-match.h +++ b/gcc/gimple-match.h @@ -419,6 +419,8 @@ code_helper canonicalize_code (code_helper, tree); #ifdef GCC_OPTABS_TREE_H bool directly_supported_p (code_helper, tree, optab_subtype = optab_default); +bool directly_supported_p (code_helper, tree, tree, + optab_subtype = optab_default); #endif internal_fn get_conditional_internal_fn (code_helper, tree); diff --git a/gcc/optabs.cc b/gcc/optabs.cc index 185c5b1a705..32737fb80e8 100644 --- a/gcc/optabs.cc +++ b/gcc/optabs.cc @@ -317,7 +317,8 @@ expand_widen_pattern_expr (const_sepops ops, rtx op0, rtx op1, rtx wide_op, widen_pattern_optab = optab_for_tree_code (ops->code, TREE_TYPE (oprnd0), optab_default); if (ops->code == WIDEN_MULT_PLUS_EXPR - || ops->code == WIDEN_MULT_MINUS_EXPR) + || ops->code == WIDEN_MULT_MINUS_EXPR + || ops->code == DOT_PROD_EXPR) icode = find_widening_optab_handler (widen_pattern_optab, TYPE_MODE (TREE_TYPE (ops->op2)), tmode0); diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc index a64b5082bd1..7e4c1e0f52e 100644 --- a/gcc/tree-vect-loop.cc +++ b/gcc/tree-vect-loop.cc @@ -5289,6 +5289,7 @@ vect_is_emulated_mixed_dot_prod (stmt_vec_info stmt_info) gcc_assert (STMT_VINFO_REDUC_VECTYPE_IN (stmt_info)); return !directly_supported_p (DOT_PROD_EXPR, + STMT_VINFO_VECTYPE (stmt_info), STMT_VINFO_REDUC_VECTYPE_IN (stmt_info), optab_vector_mixed_sign); } diff --git a/gcc/tree-vect-patterns.cc b/gcc/tree-vect-patterns.cc index 86e893a1c43..c4dd627aa90 100644 --- a/gcc/tree-vect-patterns.cc +++ b/gcc/tree-vect-patterns.cc @@ -248,6 +248,45 @@ vect_supportable_direct_optab_p (vec_info *vinfo, tree otype, tree_code code, return true; } +/* Return true if the target supports a vector version of CODE, + where CODE is known to map to a conversion optab with the given SUBTYPE. + ITYPE specifies the type of (some of) the scalar inputs and OTYPE + specifies the type of the scalar result. + + When returning true, set *VECOTYPE_OUT to the vector version of OTYPE. + Also set *VECITYPE_OUT to the vector version of ITYPE if VECITYPE_OUT + is nonnull. */ + +static bool +vect_supportable_conv_optab_p (vec_info *vinfo, tree otype, tree_code code, + tree itype, tree *vecotype_out, + tree *vecitype_out = NULL, + enum optab_subtype subtype = optab_default) +{ + tree vecitype = get_vectype_for_scalar_type (vinfo, itype); + tree vecotype = get_vectype_for_scalar_type (vinfo, otype); + if (!vecitype || !vecotype) + return false; + + optab optab = optab_for_tree_code (code, vecitype, subtype); + if (!optab) + return false; + + insn_code icode = convert_optab_handler (optab, TYPE_MODE (vecotype), + TYPE_MODE (vecitype)); + + if (icode == CODE_FOR_nothing + || insn_data[icode].operand[0].mode != TYPE_MODE (vecotype) + || insn_data[icode].operand[1].mode != TYPE_MODE (vecitype)) + return false; + + *vecotype_out = vecotype; + if (vecitype_out) + *vecitype_out = vecitype; + return true; +} + + /* Round bit precision PRECISION up to a full element. */ static unsigned int @@ -1266,13 +1305,13 @@ vect_recog_dot_prod_pattern (vec_info *vinfo, half_type = signed_type_for (half_type); tree half_vectype; - if (!vect_supportable_direct_optab_p (vinfo, type, DOT_PROD_EXPR, half_type, + if (!vect_supportable_conv_optab_p (vinfo, type, DOT_PROD_EXPR, half_type, type_out, &half_vectype, subtype)) { /* We can emulate a mixed-sign dot-product using a sequence of signed dot-products; see vect_emulate_mixed_dot_prod for details. */ if (subtype != optab_vector_mixed_sign - || !vect_supportable_direct_optab_p (vinfo, signed_type_for (type), + || !vect_supportable_conv_optab_p (vinfo, signed_type_for (type), DOT_PROD_EXPR, half_type, type_out, &half_vectype, optab_vector))