2011-07-21 Andrew Stubbs <ams@codesourcery.com>
gcc/
* tree-ssa-math-opts.c (is_widening_mult_rhs_p): Handle constants
beyond conversions.
(convert_mult_to_widen): Create SSA_NAME for constant inputs.
(convert_plusminus_to_widen): Don't automatically reject inputs that are
not an SSA_NAME.
Create SSA_NAME for constant inputs.
gcc/testsuite/
* gcc.target/arm/wmul-11.c: New file.
* gcc.target/arm/wmul-12.c: New file.
* gcc.target/arm/wmul-13.c: New file.
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-require-effective-target arm_dsp } */
+
+long long
+foo (int *b)
+{
+ return 10 * (long long)*b;
+}
+
+/* { dg-final { scan-assembler "smull" } } */
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-require-effective-target arm_dsp } */
+
+long long
+foo (int *b, int *c)
+{
+ int tmp = *b * *c;
+ return 10 + (long long)tmp;
+}
+
+/* { dg-final { scan-assembler "smlal" } } */
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-require-effective-target arm_dsp } */
+
+long long
+foo (int *a, int *b)
+{
+ return *a + (long long)*b * 10;
+}
+
+/* { dg-final { scan-assembler "smlal" } } */
@@ -1997,6 +1997,13 @@ is_widening_mult_rhs_p (tree type, tree rhs, tree *type_out,
type1 = TREE_TYPE (rhs1);
}
+ if (TREE_CODE (rhs1) == INTEGER_CST)
+ {
+ *new_rhs_out = rhs1;
+ *type_out = NULL;
+ return true;
+ }
+
if (TREE_CODE (type1) != TREE_CODE (type)
|| TYPE_PRECISION (type1) * 2 > TYPE_PRECISION (type))
return false;
@@ -2152,7 +2159,8 @@ convert_mult_to_widen (gimple stmt, gimple_stmt_iterator *gsi)
for the opcode. This will be the full mode size. */
actual_precision = GET_MODE_PRECISION (actual_mode);
if (actual_precision != TYPE_PRECISION (type1)
- || from_unsigned1 != TYPE_UNSIGNED (type1))
+ || from_unsigned1 != TYPE_UNSIGNED (type1)
+ || TREE_CODE (rhs1) != SSA_NAME)
{
tmp = create_tmp_var (build_nonstandard_integer_type
(actual_precision, from_unsigned1),
@@ -2160,7 +2168,8 @@ convert_mult_to_widen (gimple stmt, gimple_stmt_iterator *gsi)
rhs1 = build_and_insert_cast (gsi, loc, tmp, rhs1);
}
if (actual_precision != TYPE_PRECISION (type2)
- || from_unsigned2 != TYPE_UNSIGNED (type2))
+ || from_unsigned2 != TYPE_UNSIGNED (type2)
+ || TREE_CODE (rhs2) != SSA_NAME)
{
/* Reuse the same type info, if possible. */
if (!tmp || from_unsigned1 != from_unsigned2)
@@ -2221,8 +2230,6 @@ convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt,
if (is_gimple_assign (rhs1_stmt))
rhs1_code = gimple_assign_rhs_code (rhs1_stmt);
}
- else
- return false;
if (TREE_CODE (rhs2) == SSA_NAME)
{
@@ -2230,8 +2237,6 @@ convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt,
if (is_gimple_assign (rhs2_stmt))
rhs2_code = gimple_assign_rhs_code (rhs2_stmt);
}
- else
- return false;
/* Allow for one conversion statement between the multiply
and addition/subtraction statement. If there are more than
@@ -2358,7 +2363,8 @@ convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt,
for the opcode. This will be the full mode size. */
actual_precision = GET_MODE_PRECISION (actual_mode);
if (actual_precision != TYPE_PRECISION (type1)
- || from_unsigned1 != TYPE_UNSIGNED (type1))
+ || from_unsigned1 != TYPE_UNSIGNED (type1)
+ || TREE_CODE (mult_rhs1) != SSA_NAME)
{
tmp = create_tmp_var (build_nonstandard_integer_type
(actual_precision, from_unsigned1),
@@ -2366,7 +2372,8 @@ convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt,
mult_rhs1 = build_and_insert_cast (gsi, loc, tmp, mult_rhs1);
}
if (actual_precision != TYPE_PRECISION (type2)
- || from_unsigned2 != TYPE_UNSIGNED (type2))
+ || from_unsigned2 != TYPE_UNSIGNED (type2)
+ || TREE_CODE (mult_rhs2) != SSA_NAME)
{
if (!tmp || from_unsigned1 != from_unsigned2)
tmp = create_tmp_var (build_nonstandard_integer_type