tree-ssa-math-opts.c (convert_plusminus_to_widen): Permit a single conversion statement separating multiply-and-accumulate.
2011-08-19 Andrew Stubbs <ams@codesourcery.com> gcc/ * tree-ssa-math-opts.c (convert_plusminus_to_widen): Permit a single conversion statement separating multiply-and-accumulate. gcc/testsuite/ * gcc.target/arm/wmul-5.c: New file. * gcc.target/arm/no-wmla-1.c: New file. From-SVN: r177904
This commit is contained in:
parent
2946bd342d
commit
cefb4d4f60
@ -1,3 +1,8 @@
|
||||
2011-08-19 Andrew Stubbs <ams@codesourcery.com>
|
||||
|
||||
* tree-ssa-math-opts.c (convert_plusminus_to_widen): Permit a single
|
||||
conversion statement separating multiply-and-accumulate.
|
||||
|
||||
2011-08-19 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
PR tree-optimization/50067
|
||||
|
@ -1,3 +1,8 @@
|
||||
2011-08-19 Andrew Stubbs <ams@codesourcery.com>
|
||||
|
||||
* gcc.target/arm/wmul-5.c: New file.
|
||||
* gcc.target/arm/no-wmla-1.c: New file.
|
||||
|
||||
2011-08-19 Andrew Stubbs <ams@codesourcery.com>
|
||||
|
||||
* gcc.target/arm/wmul-bitfield-1.c: New file.
|
||||
|
12
gcc/testsuite/gcc.target/arm/no-wmla-1.c
Normal file
12
gcc/testsuite/gcc.target/arm/no-wmla-1.c
Normal file
@ -0,0 +1,12 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2" } */
|
||||
/* { dg-require-effective-target arm_dsp } */
|
||||
|
||||
int
|
||||
foo (int a, short b, short c)
|
||||
{
|
||||
int bc = b * c;
|
||||
return a + (short)bc;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-assembler "\tmul\t" } } */
|
11
gcc/testsuite/gcc.target/arm/wmul-5.c
Normal file
11
gcc/testsuite/gcc.target/arm/wmul-5.c
Normal file
@ -0,0 +1,11 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2" } */
|
||||
/* { dg-require-effective-target arm_dsp } */
|
||||
|
||||
long long
|
||||
foo (long long a, char *b, char *c)
|
||||
{
|
||||
return a + *b * *c;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-assembler "umlal" } } */
|
@ -2136,6 +2136,7 @@ convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt,
|
||||
enum tree_code code)
|
||||
{
|
||||
gimple rhs1_stmt = NULL, rhs2_stmt = NULL;
|
||||
gimple conv1_stmt = NULL, conv2_stmt = NULL, conv_stmt;
|
||||
tree type, type1, type2, tmp;
|
||||
tree lhs, rhs1, rhs2, mult_rhs1, mult_rhs2, add_rhs;
|
||||
enum tree_code rhs1_code = ERROR_MARK, rhs2_code = ERROR_MARK;
|
||||
@ -2178,6 +2179,38 @@ convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt,
|
||||
else
|
||||
return false;
|
||||
|
||||
/* Allow for one conversion statement between the multiply
|
||||
and addition/subtraction statement. If there are more than
|
||||
one conversions then we assume they would invalidate this
|
||||
transformation. If that's not the case then they should have
|
||||
been folded before now. */
|
||||
if (CONVERT_EXPR_CODE_P (rhs1_code))
|
||||
{
|
||||
conv1_stmt = rhs1_stmt;
|
||||
rhs1 = gimple_assign_rhs1 (rhs1_stmt);
|
||||
if (TREE_CODE (rhs1) == SSA_NAME)
|
||||
{
|
||||
rhs1_stmt = SSA_NAME_DEF_STMT (rhs1);
|
||||
if (is_gimple_assign (rhs1_stmt))
|
||||
rhs1_code = gimple_assign_rhs_code (rhs1_stmt);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
if (CONVERT_EXPR_CODE_P (rhs2_code))
|
||||
{
|
||||
conv2_stmt = rhs2_stmt;
|
||||
rhs2 = gimple_assign_rhs1 (rhs2_stmt);
|
||||
if (TREE_CODE (rhs2) == SSA_NAME)
|
||||
{
|
||||
rhs2_stmt = SSA_NAME_DEF_STMT (rhs2);
|
||||
if (is_gimple_assign (rhs2_stmt))
|
||||
rhs2_code = gimple_assign_rhs_code (rhs2_stmt);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/* If code is WIDEN_MULT_EXPR then it would seem unnecessary to call
|
||||
is_widening_mult_p, but we still need the rhs returns.
|
||||
|
||||
@ -2191,6 +2224,7 @@ convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt,
|
||||
&type2, &mult_rhs2))
|
||||
return false;
|
||||
add_rhs = rhs2;
|
||||
conv_stmt = conv1_stmt;
|
||||
}
|
||||
else if (rhs2_code == MULT_EXPR || rhs2_code == WIDEN_MULT_EXPR)
|
||||
{
|
||||
@ -2198,6 +2232,7 @@ convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt,
|
||||
&type2, &mult_rhs2))
|
||||
return false;
|
||||
add_rhs = rhs1;
|
||||
conv_stmt = conv2_stmt;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
@ -2208,6 +2243,33 @@ convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt,
|
||||
if (TYPE_UNSIGNED (type1) != TYPE_UNSIGNED (type2))
|
||||
return false;
|
||||
|
||||
/* If there was a conversion between the multiply and addition
|
||||
then we need to make sure it fits a multiply-and-accumulate.
|
||||
The should be a single mode change which does not change the
|
||||
value. */
|
||||
if (conv_stmt)
|
||||
{
|
||||
tree from_type = TREE_TYPE (gimple_assign_rhs1 (conv_stmt));
|
||||
tree to_type = TREE_TYPE (gimple_assign_lhs (conv_stmt));
|
||||
int data_size = TYPE_PRECISION (type1) + TYPE_PRECISION (type2);
|
||||
bool is_unsigned = TYPE_UNSIGNED (type1) && TYPE_UNSIGNED (type2);
|
||||
|
||||
if (TYPE_PRECISION (from_type) > TYPE_PRECISION (to_type))
|
||||
{
|
||||
/* Conversion is a truncate. */
|
||||
if (TYPE_PRECISION (to_type) < data_size)
|
||||
return false;
|
||||
}
|
||||
else if (TYPE_PRECISION (from_type) < TYPE_PRECISION (to_type))
|
||||
{
|
||||
/* Conversion is an extend. Check it's the right sort. */
|
||||
if (TYPE_UNSIGNED (from_type) != is_unsigned
|
||||
&& !(is_unsigned && TYPE_PRECISION (from_type) > data_size))
|
||||
return false;
|
||||
}
|
||||
/* else convert is a no-op for our purposes. */
|
||||
}
|
||||
|
||||
/* Verify that the machine can perform a widening multiply
|
||||
accumulate in this mode/signedness combination, otherwise
|
||||
this transformation is likely to pessimize code. */
|
||||
|
Loading…
Reference in New Issue
Block a user