diff mbox series

[V2,02/10] autovectorizer: Add basic support for convert optabs

Message ID 20240813124150.1168825-3-victor.donascimento@arm.com
State New
Headers show
Series optabs: Make all `*dot_prod_optab's modeled as conversions | expand

Commit Message

Victor Do Nascimento Aug. 13, 2024, 12:41 p.m. UTC
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 | 23 ++++++++++++++++++++
 gcc/gimple-match.h          |  2 ++
 gcc/optabs.cc               |  3 ++-
 gcc/tree-vect-loop.cc       |  1 +
 gcc/tree-vect-patterns.cc   | 43 +++++++++++++++++++++++++++++++++++--
 5 files changed, 69 insertions(+), 3 deletions(-)

Comments

Tamar Christina Aug. 14, 2024, 12:24 p.m. UTC | #1
Hi Victor,

> -----Original Message-----
> From: Victor Do Nascimento <victor.donascimento@arm.com>
> Sent: Tuesday, August 13, 2024 1:42 PM
> To: gcc-patches@gcc.gnu.org
> Cc: Tamar Christina <Tamar.Christina@arm.com>; claziss@gmail.com;
> hongtao.liu@intel.com; syq@gcc.gnu.org; bernds_cb1@t-online.de;
> aldyh@redhat.com; Victor Do Nascimento <Victor.DoNascimento@arm.com>
> Subject: [PATCH V2 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 | 23 ++++++++++++++++++++
>  gcc/gimple-match.h          |  2 ++
>  gcc/optabs.cc               |  3 ++-
>  gcc/tree-vect-loop.cc       |  1 +
>  gcc/tree-vect-patterns.cc   | 43 +++++++++++++++++++++++++++++++++++--
>  5 files changed, 69 insertions(+), 3 deletions(-)
> 
> diff --git a/gcc/gimple-match-exports.cc b/gcc/gimple-match-exports.cc
> index aacf3ff0414..d18497e7c83 100644
> --- a/gcc/gimple-match-exports.cc
> +++ b/gcc/gimple-match-exports.cc
> @@ -1381,6 +1381,29 @@ 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_assert (query_type == optab_default
> +	      || (query_type == optab_vector && VECTOR_TYPE_P (type_in))
> +	      || (query_type == optab_scalar && !VECTOR_TYPE_P (type_in)));
> +  internal_fn ifn = associated_internal_fn (combined_fn (code), type_in);
> +  return (direct_internal_fn_p (ifn)
> +	  && direct_internal_fn_supported_p (ifn, tree_pair (type_out, type_in),
> +					     OPTIMIZE_FOR_SPEED));
> +}
> +
> +
>  /* 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 6456220cdc9..5f3de7b72a8 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 f52de2b6972..3afedc9199b 100644
> --- a/gcc/tree-vect-patterns.cc
> +++ b/gcc/tree-vect-patterns.cc
> @@ -250,6 +250,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;
> +}

You never responded to the previous review for this change, so I have the same question.
You've now added directly_supported_p which takes a convert optab and calls convert_optab_handler
Which checks both mode.

So why does this function not use it?  It seems to be doing duplicate work and limits itself unnecessarily to tree_code.
It seems to me that this should take a code_helper, create the vector modes and call directly_supported_p, or am I missing something?

Thanks,
Tamar

> +
> +
>  /* Round bit precision PRECISION up to a full element.  */
> 
>  static unsigned int
> @@ -1270,13 +1309,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
Victor Do Nascimento Aug. 14, 2024, 1 p.m. UTC | #2
On 8/14/24 13:24, Tamar Christina wrote:
> Hi Victor,
> 
>> -----Original Message-----
>> From: Victor Do Nascimento <victor.donascimento@arm.com>
>> Sent: Tuesday, August 13, 2024 1:42 PM
>> To: gcc-patches@gcc.gnu.org
>> Cc: Tamar Christina <Tamar.Christina@arm.com>; claziss@gmail.com;
>> hongtao.liu@intel.com; syq@gcc.gnu.org; bernds_cb1@t-online.de;
>> aldyh@redhat.com; Victor Do Nascimento <Victor.DoNascimento@arm.com>
>> Subject: [PATCH V2 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 | 23 ++++++++++++++++++++
>>   gcc/gimple-match.h          |  2 ++
>>   gcc/optabs.cc               |  3 ++-
>>   gcc/tree-vect-loop.cc       |  1 +
>>   gcc/tree-vect-patterns.cc   | 43 +++++++++++++++++++++++++++++++++++--
>>   5 files changed, 69 insertions(+), 3 deletions(-)
>>
>> diff --git a/gcc/gimple-match-exports.cc b/gcc/gimple-match-exports.cc
>> index aacf3ff0414..d18497e7c83 100644
>> --- a/gcc/gimple-match-exports.cc
>> +++ b/gcc/gimple-match-exports.cc
>> @@ -1381,6 +1381,29 @@ 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_assert (query_type == optab_default
>> +	      || (query_type == optab_vector && VECTOR_TYPE_P (type_in))
>> +	      || (query_type == optab_scalar && !VECTOR_TYPE_P (type_in)));
>> +  internal_fn ifn = associated_internal_fn (combined_fn (code), type_in);
>> +  return (direct_internal_fn_p (ifn)
>> +	  && direct_internal_fn_supported_p (ifn, tree_pair (type_out, type_in),
>> +					     OPTIMIZE_FOR_SPEED));
>> +}
>> +
>> +
>>   /* 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 6456220cdc9..5f3de7b72a8 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 f52de2b6972..3afedc9199b 100644
>> --- a/gcc/tree-vect-patterns.cc
>> +++ b/gcc/tree-vect-patterns.cc
>> @@ -250,6 +250,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;
>> +}
> 
> You never responded to the previous review for this change, so I have the same question.
> You've now added directly_supported_p which takes a convert optab and calls convert_optab_handler
> Which checks both mode.

Darn, it seems I clearly missed the point of your feedback given in your 
previous review, with it having been seemingly overlooked upon my return 
from the summer break.

> So why does this function not use it?  It seems to be doing duplicate work and limits itself unnecessarily to tree_code.
> It seems to me that this should take a code_helper, create the vector modes and call directly_supported_p, or am I missing something?

Yes, there clearly is unnecessary code duplication we can do without and 
your approach does away with that quite nicely.  The use of the 
code_helper also makes for an easily-implementable improvement over the 
current way of handling things.

Thanks for taking the time to look over the code, greatly appreciated.

Cheers,
Victor

> Thanks,
> Tamar
> 
>> +
>> +
>>   /* Round bit precision PRECISION up to a full element.  */
>>
>>   static unsigned int
>> @@ -1270,13 +1309,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
>
Victor Do Nascimento Aug. 14, 2024, 2:10 p.m. UTC | #3
On 8/14/24 13:24, Tamar Christina wrote:

> It seems to me that this should take a code_helper, create the vector modes and call directly_supported_p, or am I missing something?

Ok. Having done some digging around in the git history, I see that 
`vect_supportable_direct_optab_p', upon which I based my implementation 
of `vect_supportable_conv_optab_p', was committed before you wrote the 
`directly_supported_p' function, which I guess explains why 
`vect_supportable_direct_optab_p' does not take advantage of the latter 
function to avoid code duplication.

I'd wrongly presumed that we'd have been aware of the existence of 
`directly_supported_p' when writing `vect_supportable_direct_optab_p', 
such that any apparent code duplication would have been a conscious 
choice by the author, thus making it a relevant design consideration in 
my own implementation.

Anyway, will submit updated patch shortly.

Cheers,
Victor
diff mbox series

Patch

diff --git a/gcc/gimple-match-exports.cc b/gcc/gimple-match-exports.cc
index aacf3ff0414..d18497e7c83 100644
--- a/gcc/gimple-match-exports.cc
+++ b/gcc/gimple-match-exports.cc
@@ -1381,6 +1381,29 @@  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_assert (query_type == optab_default
+	      || (query_type == optab_vector && VECTOR_TYPE_P (type_in))
+	      || (query_type == optab_scalar && !VECTOR_TYPE_P (type_in)));
+  internal_fn ifn = associated_internal_fn (combined_fn (code), type_in);
+  return (direct_internal_fn_p (ifn)
+	  && direct_internal_fn_supported_p (ifn, tree_pair (type_out, type_in),
+					     OPTIMIZE_FOR_SPEED));
+}
+
+
 /* 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 6456220cdc9..5f3de7b72a8 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 f52de2b6972..3afedc9199b 100644
--- a/gcc/tree-vect-patterns.cc
+++ b/gcc/tree-vect-patterns.cc
@@ -250,6 +250,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
@@ -1270,13 +1309,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))