[patch] convert.c: Fix PR tree-optimization/25125. (Take 3)

Kazu Hirata kazu@codesourcery.com
Mon Dec 26 21:18:00 GMT 2005


Hi,

Attached is a patch to fix PR tree-optimization/25125.

Consider

unsigned short
f (short a)
{
  short b;

  if (a > 0)
    return 0;
  b = ((int) a) + - (int) 32768;
  return b;
}

Here is a sequent of events that are relevant to the bug.

1. convert.c:convert_to_integer changes the type of the addition in
   "b = ...;" from signed int to signed short.  That is, we now have
   b = a + -32768, where '+' is done in signed short.

2. Since the result of overflow is undefined for signed operations, VRP
   assumes that b is in range [-INF, -32768], which is really -32768.
   Note that the return type is unsigned short, so
   "(unsigned short) -32768" comes out to be 32768.  In short, for all
   a <= 0, this function returns 32768, which is wrong.

The patch solves this problem by narrowing the addition to an unsigned
type (instead of a signed type) to avoid signed-overflow
undefinedness.  Of course, the result is cast back to the original
signed type.

One drawback of this approach is that some vectorization testcases
rely on this transformation.  gcc.dg/vect/vect-7.c, for example, has a
statement like so:

  s.a[i] = s.b[i] + 100;

For some reason, this patch does not affect vect-35.c even though the
previous version of this patch did.  For now, I've XFAILed those
vectorization testcases that fail with this patch.

Tested on x86_64-pc-linux-gnu.  OK to apply?

Kazu Hirata

2005-12-26  Kazu Hirata  <kazu@codesourcery.com>

	PR tree-optimization/25125
	* convert.c (convert_to_integer): Don't narrow the type of a
	PLUX_EXPR or MINUS_EXPR if !flag_wrapv and the unwidened type
	is signed.

2005-12-26  Kazu Hirata  <kazu@codesourcery.com>

	PR tree-optimization/25125
	* gcc.dg/vect/vect-35.c, gcc.dg/vect/vect-7.c,
	gcc.dg/vect/vect-reduc-2char.c,
	gcc.dg/vect/vect-reduc-2short.c: XFAIL.
	* gcc.c-torture/execute/pr25125.c: New.

Index: convert.c
===================================================================
--- convert.c	(revision 109050)
+++ convert.c	(working copy)
@@ -628,7 +628,17 @@ convert_to_integer (tree type, tree expr
 				|| ex_form == RSHIFT_EXPR
 				|| ex_form == LROTATE_EXPR
 				|| ex_form == RROTATE_EXPR))
-			|| ex_form == LSHIFT_EXPR)
+			|| ex_form == LSHIFT_EXPR
+			/* If we have !flag_wrapv, and either ARG0 or
+			   ARG1 is of a signed type, we have to do
+			   PLUS_EXPR or MINUS_EXPR in an unsigned
+			   type.  Otherwise, we would introduce
+			   signed-overflow undefinedness.  */
+			|| (!flag_wrapv
+			    && (ex_form == PLUS_EXPR
+				|| ex_form == MINUS_EXPR)
+			    && (!TYPE_UNSIGNED (TREE_TYPE (arg0))
+				|| !TYPE_UNSIGNED (TREE_TYPE (arg1)))))
 		      typex = lang_hooks.types.unsigned_type (typex);
 		    else
 		      typex = lang_hooks.types.signed_type (typex);
Index: testsuite/gcc.dg/vect/vect-7.c
===================================================================
--- testsuite/gcc.dg/vect/vect-7.c	(revision 108853)
+++ testsuite/gcc.dg/vect/vect-7.c	(working copy)
@@ -46,6 +46,6 @@ int main (void)
 }
 
 /* Fails for 32-bit targets that don't vectorize PLUS.  */
-/* { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" } } */
+/* { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" { xfail *-*-* } } } */
 /* { dg-final { scan-tree-dump-times "Vectorizing an unaligned access" 0 "vect" } } */
 /* { dg-final { cleanup-tree-dump "vect" } } */
Index: testsuite/gcc.dg/vect/vect-reduc-2char.c
===================================================================
--- testsuite/gcc.dg/vect/vect-reduc-2char.c	(revision 108853)
+++ testsuite/gcc.dg/vect/vect-reduc-2char.c	(working copy)
@@ -45,5 +45,5 @@ int main (void)
   return 0;
 }
 
-/* { dg-final { scan-tree-dump-times "vectorized 3 loops" 1 "vect" { xfail vect_no_int_max } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 3 loops" 1 "vect" { xfail *-*-* } } } */
 /* { dg-final { cleanup-tree-dump "vect" } } */
Index: testsuite/gcc.dg/vect/vect-reduc-2short.c
===================================================================
--- testsuite/gcc.dg/vect/vect-reduc-2short.c	(revision 108853)
+++ testsuite/gcc.dg/vect/vect-reduc-2short.c	(working copy)
@@ -44,5 +44,5 @@ int main (void)
   return 0;
 }
 
-/* { dg-final { scan-tree-dump-times "vectorized 3 loops" 1 "vect" { xfail vect_no_int_max } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 3 loops" 1 "vect" { xfail *-*-* } } } */
 /* { dg-final { cleanup-tree-dump "vect" } } */
Index: testsuite/gcc.c-torture/execute/pr25125.c
===================================================================
--- /dev/null	2005-09-01 09:08:28.063949816 -0700
+++ testsuite/gcc.c-torture/execute/pr25125.c	2005-12-19 06:29:51.774368122 -0800
@@ -0,0 +1,27 @@
+extern void exit (int);
+extern void abort (void);
+extern unsigned short f (short a) __attribute__((__noinline__));
+
+unsigned short
+f (short a)
+{
+  short b;
+
+  if (a > 0)
+    return 0;
+  b = ((int) a) + - (int) 32768;
+  return b;
+}
+
+int
+main (void)
+{
+  if (sizeof (short) < 2
+      || sizeof (short) >= sizeof (int))
+    exit (0);
+
+  if (f (-32767) != 1)
+    abort ();
+
+  exit (0);
+}



More information about the Gcc-patches mailing list