]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR tree-optimization/54295 (Widening multiply-accumulate operation uses wrong...
authorRichard Earnshaw <rearnsha@arm.com>
Mon, 20 Aug 2012 12:49:47 +0000 (12:49 +0000)
committerRichard Earnshaw <rearnsha@gcc.gnu.org>
Mon, 20 Aug 2012 12:49:47 +0000 (12:49 +0000)
PR tree-ssa/54295
* tree-ssa-math-opts.c (widening_mult_conversion_strippable_p):
New function.
(is_widening_mult_rhs_p): Use it.

* gcc.c-torture/execute/20120817-1.c: New test.

From-SVN: r190533

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/20120817-1.c [new file with mode: 0644]
gcc/tree-ssa-math-opts.c

index f892f00f2b7f098045eeaf3ef98914d4d42fdcf0..13e2b4c719e9c75c2f5ad0aec005d76143bd9044 100644 (file)
@@ -1,3 +1,10 @@
+2012-08-20  Richard Earnshaw  <rearnsha@arm.com>
+
+       PR tree-ssa/54295
+       * tree-ssa-math-opts.c (widening_mult_conversion_strippable_p):
+       New function.
+       (is_widening_mult_rhs_p): Use it.
+
 2012-08-20  Joseph Myers  <joseph@codesourcery.com>
 
        * configure.ac (ffs): Check for declaration.
index e9aaf243950c7401a2a8074dd4b08f36c6dbc656..f33149ae1b692253ace5979bd5852f22ee4fc674 100644 (file)
@@ -1,3 +1,8 @@
+2012-08-20  Richard Earnshaw  <rearnsha@arm.com>
+
+       PR tree-ssa/54295
+       * gcc.c-torture/execute/20120817-1.c: New test.
+
 2012-08-20  Richard Earnshaw  <rearnsha@arm.com>
 
        * gcc.target/arm/thumb-16bit-ops.c (f): This test uses a 16-bit
diff --git a/gcc/testsuite/gcc.c-torture/execute/20120817-1.c b/gcc/testsuite/gcc.c-torture/execute/20120817-1.c
new file mode 100644 (file)
index 0000000..8fb2820
--- /dev/null
@@ -0,0 +1,14 @@
+typedef unsigned long long u64;
+unsigned long foo = 0;
+u64 f() __attribute__((noinline));
+
+u64 f() {
+  return ((u64)40) + ((u64) 24) * (int)(foo - 1);
+}
+
+int main ()
+{
+  if (f () != 16)
+    abort ();
+  exit (0);
+}
index 0d6eeb69055f4fd80f79d47df003435d7525c64f..748bf2f1e4968078cd9897102aeccdc0b81bb69e 100644 (file)
@@ -1958,6 +1958,43 @@ struct gimple_opt_pass pass_optimize_bswap =
  }
 };
 
+/* Return true if stmt is a type conversion operation that can be stripped
+   when used in a widening multiply operation.  */
+static bool
+widening_mult_conversion_strippable_p (tree result_type, gimple stmt)
+{
+  enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
+
+  if (TREE_CODE (result_type) == INTEGER_TYPE)
+    {
+      tree op_type;
+      tree inner_op_type;
+
+      if (!CONVERT_EXPR_CODE_P (rhs_code))
+       return false;
+
+      op_type = TREE_TYPE (gimple_assign_lhs (stmt));
+
+      /* If the type of OP has the same precision as the result, then
+        we can strip this conversion.  The multiply operation will be
+        selected to create the correct extension as a by-product.  */
+      if (TYPE_PRECISION (result_type) == TYPE_PRECISION (op_type))
+       return true;
+
+      /* We can also strip a conversion if it preserves the signed-ness of
+        the operation and doesn't narrow the range.  */
+      inner_op_type = TREE_TYPE (gimple_assign_rhs1 (stmt));
+
+      if (TYPE_UNSIGNED (op_type) == TYPE_UNSIGNED (inner_op_type)
+         && TYPE_PRECISION (op_type) > TYPE_PRECISION (inner_op_type))
+       return true;
+
+      return false;
+    }
+
+  return rhs_code == FIXED_CONVERT_EXPR;
+}
+
 /* Return true if RHS is a suitable operand for a widening multiplication,
    assuming a target type of TYPE.
    There are two cases:
@@ -1982,9 +2019,7 @@ is_widening_mult_rhs_p (tree type, tree rhs, tree *type_out,
       if (is_gimple_assign (stmt))
        {
          rhs_code = gimple_assign_rhs_code (stmt);
-         if (TREE_CODE (type) == INTEGER_TYPE
-             ? !CONVERT_EXPR_CODE_P (rhs_code)
-             : rhs_code != FIXED_CONVERT_EXPR)
+         if (! widening_mult_conversion_strippable_p (type, stmt))
            rhs1 = rhs;
          else
            {