[(6/7)] More widening multiply-and-accumulate pattern matching

Submitted by Andrew Stubbs on July 4, 2011, 2:31 p.m.

Details

Message ID 4E11CEDF.6060004@codesourcery.com
State New
Headers show

Commit Message

Andrew Stubbs July 4, 2011, 2:31 p.m.
On 28/06/11 16:30, Andrew Stubbs wrote:
> On 23/06/11 15:42, Andrew Stubbs wrote:
>> This patch fixes the case where widening multiply-and-accumulate were
>> not recognised because the multiplication itself is not actually
>> widening.
>>
>> This can happen when you have "DI + SI * SI" - the multiplication will
>> be done in SImode as a non-widening multiply, and it's only the final
>> accumulate step that is widening.
>>
>> This was not recognised for two reasons:
>>
>> 1. is_widening_mult_p inferred the output type from the multiply
>> statement, which in not useful in this case.
>>
>> 2. The inputs to the multiply instruction may not have been converted at
>> all (because they're not being widened), so the pattern match failed.
>>
>> The patch fixes these issues by making the output type explicit, and by
>> permitting unconverted inputs (the types are still checked, so this is
>> safe).
>>
>> OK?
>
> This update fixes Janis' testsuite issue.

This updates the context changed by my update to patch 3.

The content of this patch has not changed.

Andrew

Comments

Richard Guenther July 7, 2011, 10:13 a.m.
On Mon, Jul 4, 2011 at 4:31 PM, Andrew Stubbs <ams@codesourcery.com> wrote:
> On 28/06/11 16:30, Andrew Stubbs wrote:
>>
>> On 23/06/11 15:42, Andrew Stubbs wrote:
>>>
>>> This patch fixes the case where widening multiply-and-accumulate were
>>> not recognised because the multiplication itself is not actually
>>> widening.
>>>
>>> This can happen when you have "DI + SI * SI" - the multiplication will
>>> be done in SImode as a non-widening multiply, and it's only the final
>>> accumulate step that is widening.
>>>
>>> This was not recognised for two reasons:
>>>
>>> 1. is_widening_mult_p inferred the output type from the multiply
>>> statement, which in not useful in this case.
>>>
>>> 2. The inputs to the multiply instruction may not have been converted at
>>> all (because they're not being widened), so the pattern match failed.
>>>
>>> The patch fixes these issues by making the output type explicit, and by
>>> permitting unconverted inputs (the types are still checked, so this is
>>> safe).
>>>
>>> OK?
>>
>> This update fixes Janis' testsuite issue.
>
> This updates the context changed by my update to patch 3.
>
> The content of this patch has not changed.

Ok.

Thanks,
Richard.

> Andrew
>

Patch hide | download patch | download mbox

2011-07-04  Andrew Stubbs  <ams@codesourcery.com>

	gcc/
	* tree-ssa-math-opts.c (is_widening_mult_rhs_p): Add new argument
	'type'.
	Use 'type' from caller, not inferred from 'rhs'.
	Don't reject non-conversion statements. Do return lhs in this case.
	(is_widening_mult_p): Add new argument 'type'.
	Use 'type' from caller, not inferred from 'stmt'.
	Pass type to is_widening_mult_rhs_p.
	(convert_mult_to_widen): Pass type to is_widening_mult_p.
	(convert_plusminus_to_widen): Likewise.

	gcc/testsuite/
	* gcc.target/arm/wmul-8.c: New file.

--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/wmul-8.c
@@ -0,0 +1,10 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=armv7-a" } */
+
+long long
+foo (long long a, int *b, int *c)
+{
+  return a + *b * *c;
+}
+
+/* { dg-final { scan-assembler "smlal" } } */
--- a/gcc/tree-ssa-math-opts.c
+++ b/gcc/tree-ssa-math-opts.c
@@ -1963,7 +1963,8 @@  struct gimple_opt_pass pass_optimize_bswap =
  }
 };
 
-/* Return true if RHS is a suitable operand for a widening multiplication.
+/* Return true if RHS is a suitable operand for a widening multiplication,
+   assuming a target type of TYPE.
    There are two cases:
 
      - RHS makes some value at least twice as wide.  Store that value
@@ -1973,32 +1974,32 @@  struct gimple_opt_pass pass_optimize_bswap =
        but leave *TYPE_OUT untouched.  */
 
 static bool
-is_widening_mult_rhs_p (tree rhs, tree *type_out, tree *new_rhs_out)
+is_widening_mult_rhs_p (tree type, tree rhs, tree *type_out,
+			tree *new_rhs_out)
 {
   gimple stmt;
-  tree type, type1, rhs1;
+  tree type1, rhs1;
   enum tree_code rhs_code;
 
   if (TREE_CODE (rhs) == SSA_NAME)
     {
-      type = TREE_TYPE (rhs);
       stmt = SSA_NAME_DEF_STMT (rhs);
       if (!is_gimple_assign (stmt))
 	return false;
 
-      rhs_code = gimple_assign_rhs_code (stmt);
-      if (TREE_CODE (type) == INTEGER_TYPE
-	  ? !CONVERT_EXPR_CODE_P (rhs_code)
-	  : rhs_code != FIXED_CONVERT_EXPR)
-	return false;
-
       rhs1 = gimple_assign_rhs1 (stmt);
       type1 = TREE_TYPE (rhs1);
       if (TREE_CODE (type1) != TREE_CODE (type)
 	  || TYPE_PRECISION (type1) * 2 > TYPE_PRECISION (type))
 	return false;
 
-      *new_rhs_out = rhs1;
+      rhs_code = gimple_assign_rhs_code (stmt);
+      if (TREE_CODE (type) == INTEGER_TYPE
+	  ? !CONVERT_EXPR_CODE_P (rhs_code)
+	  : rhs_code != FIXED_CONVERT_EXPR)
+	*new_rhs_out = gimple_assign_lhs (stmt);
+      else
+	*new_rhs_out = rhs1;
       *type_out = type1;
       return true;
     }
@@ -2013,28 +2014,27 @@  is_widening_mult_rhs_p (tree rhs, tree *type_out, tree *new_rhs_out)
   return false;
 }
 
-/* Return true if STMT performs a widening multiplication.  If so,
-   store the unwidened types of the operands in *TYPE1_OUT and *TYPE2_OUT
-   respectively.  Also fill *RHS1_OUT and *RHS2_OUT such that converting
-   those operands to types *TYPE1_OUT and *TYPE2_OUT would give the
-   operands of the multiplication.  */
+/* Return true if STMT performs a widening multiplication, assuming the
+   output type is TYPE.  If so, store the unwidened types of the operands
+   in *TYPE1_OUT and *TYPE2_OUT respectively.  Also fill *RHS1_OUT and
+   *RHS2_OUT such that converting those operands to types *TYPE1_OUT
+   and *TYPE2_OUT would give the operands of the multiplication.  */
 
 static bool
-is_widening_mult_p (gimple stmt,
+is_widening_mult_p (tree type, gimple stmt,
 		    tree *type1_out, tree *rhs1_out,
 		    tree *type2_out, tree *rhs2_out)
 {
-  tree type;
-
-  type = TREE_TYPE (gimple_assign_lhs (stmt));
   if (TREE_CODE (type) != INTEGER_TYPE
       && TREE_CODE (type) != FIXED_POINT_TYPE)
     return false;
 
-  if (!is_widening_mult_rhs_p (gimple_assign_rhs1 (stmt), type1_out, rhs1_out))
+  if (!is_widening_mult_rhs_p (type, gimple_assign_rhs1 (stmt), type1_out,
+			       rhs1_out))
     return false;
 
-  if (!is_widening_mult_rhs_p (gimple_assign_rhs2 (stmt), type2_out, rhs2_out))
+  if (!is_widening_mult_rhs_p (type, gimple_assign_rhs2 (stmt), type2_out,
+			       rhs2_out))
     return false;
 
   if (*type1_out == NULL)
@@ -2084,7 +2084,7 @@  convert_mult_to_widen (gimple stmt, gimple_stmt_iterator *gsi)
   if (TREE_CODE (type) != INTEGER_TYPE)
     return false;
 
-  if (!is_widening_mult_p (stmt, &type1, &rhs1, &type2, &rhs2))
+  if (!is_widening_mult_p (type, stmt, &type1, &rhs1, &type2, &rhs2))
     return false;
 
   to_mode = TYPE_MODE (type);
@@ -2280,7 +2280,7 @@  convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt,
 
   if (code == PLUS_EXPR && rhs1_code == MULT_EXPR)
     {
-      if (!is_widening_mult_p (rhs1_stmt, &type1, &mult_rhs1,
+      if (!is_widening_mult_p (type, rhs1_stmt, &type1, &mult_rhs1,
 			       &type2, &mult_rhs2))
 	return false;
       mult_rhs = rhs1;
@@ -2288,7 +2288,7 @@  convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt,
     }
   else if (rhs2_code == MULT_EXPR)
     {
-      if (!is_widening_mult_p (rhs2_stmt, &type1, &mult_rhs1,
+      if (!is_widening_mult_p (type, rhs2_stmt, &type1, &mult_rhs1,
 			       &type2, &mult_rhs2))
 	return false;
       mult_rhs = rhs2;