This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix MULT_HIGHPART_EXPR folding (PR tree-optimization/56918)


Hi!

The op1 - op2 line instead of multiplication is something that has been
introduced in C++ double_int changes, but without the 2 * TYPE_PRECISION
prec it would always return 0 or -1 anyway.  And, with wide_mul_with_sign
we can also handle 2 * HOST_BITS_PER_WIDE_INT precisions.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk/4.8?

2013-04-11  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/56918
	PR tree-optimization/56920
	* fold-const.c (int_const_binop_1): Use op1.mul_with_sign (op2, ...)
	instead of op1 - op2.  Pass 2 * TYPE_PRECISION (type) as second
	argument to rshift method.  For 2 * HOST_BITS_PER_WIDE_INT precision
	use wide_mul_with_sign method.

	* gcc.dg/vect/pr56918.c: New test.
	* gcc.dg/vect/pr56920.c: New test.

--- gcc/fold-const.c.jj	2013-04-11 09:36:41.000000000 +0200
+++ gcc/fold-const.c	2013-04-11 16:16:50.273545925 +0200
@@ -984,12 +984,16 @@ int_const_binop_1 (enum tree_code code,
       break;
 
     case MULT_HIGHPART_EXPR:
-      /* ??? Need quad precision, or an additional shift operand
-	 to the multiply primitive, to handle very large highparts.  */
       if (TYPE_PRECISION (type) > HOST_BITS_PER_WIDE_INT)
-	return NULL_TREE;
-      tmp = op1 - op2;
-      res = tmp.rshift (TYPE_PRECISION (type), TYPE_PRECISION (type), !uns);
+	{
+	  if (TYPE_PRECISION (type) != 2 * HOST_BITS_PER_WIDE_INT)
+	    return NULL_TREE;
+	  op1.wide_mul_with_sign (op2, false, &res, &overflow);
+	  break;
+	}
+      tmp = op1.mul_with_sign (op2, false, &overflow);
+      res
+	= tmp.rshift (TYPE_PRECISION (type), 2 * TYPE_PRECISION (type), !uns);
       break;
 
     case TRUNC_DIV_EXPR:
--- gcc/testsuite/gcc.dg/vect/pr56918.c.jj	2013-04-11 16:26:36.269168125 +0200
+++ gcc/testsuite/gcc.dg/vect/pr56918.c	2013-04-11 16:30:07.410945804 +0200
@@ -0,0 +1,31 @@
+/* PR tree-optimization/56918 */
+/* { dg-additional-options "-O3" } */
+
+#include "tree-vect.h"
+
+extern void abort (void);
+double data[8];
+
+__attribute__((noinline, noclone)) void
+foo ()
+{
+  int i;
+  for (i = 0; i < 8; ++i)
+    data[i] = ((i + 2) % 3) + 1;
+}
+
+int
+main ()
+{
+  int i;
+  check_vect ();
+  foo ();
+  if (data[0] != 3 || data[7] != 1)
+    abort ();
+  for (i = 1; i < 4; ++i)
+    if (data[i] != i || data[i + 3] != i)
+      abort ();
+  return 0;
+}
+
+/* { dg-final { cleanup-tree-dump "vect" } } */
--- gcc/testsuite/gcc.dg/vect/pr56920.c.jj	2013-04-11 17:16:48.570982675 +0200
+++ gcc/testsuite/gcc.dg/vect/pr56920.c	2013-04-11 17:17:28.310757853 +0200
@@ -0,0 +1,21 @@
+/* PR tree-optimization/56920 */
+/* { dg-additional-options "-O3" } */
+
+#include "tree-vect.h"
+
+extern void abort (void);
+
+int
+main ()
+{
+  unsigned int a[15], i;
+  check_vect ();
+  for (i = 0; i < 15; ++i)
+    a[i] = (i * 2) % 15;
+  for (i = 0; i < 15; ++i)
+    if (a[i] != (i * 2) % 15)
+      abort ();
+  return 0;
+}
+
+/* { dg-final { cleanup-tree-dump "vect" } } */

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]