[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