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] Avoid introducing TREE_OVERFLOWs in (T)(x&cst) -> (T)x & (T)cst optimization (PR middle-end/19857)


Hi!

The following patch (actually, any of the two hunks for this testcase) fixes
the execute testcase below.
I found two problems:
int i;
int foo (void)
{
  return i & ~(unsigned int) 3;
}
First is that
           if (change)
             return fold (build2 (BIT_AND_EXPR, type,
                                  fold_convert (type, and0),
                                  fold_convert (type, and1)));
folds (int) ((unsigned)i & ~(unsigned)3) into i & (int)~(unsigned)3 where
(int)~(unsigned)3 is -4 with TREE_OVERFLOW set.  But there is no overflow
in the original program, so we shouldn't IMHO create one as part of this
optimization.

Another problem is that
     case POINTER_TYPE:
     case REFERENCE_TYPE:
       if (integer_zerop (expr))
         expr = integer_zero_node;
       else
         expr = fold (build1 (CONVERT_EXPR,
                              lang_hooks.types.type_for_size (POINTER_SIZE, 0),
                              expr));

       return convert_to_integer (type, expr);
unconditionally converts to signed type as wide as pointer (== intptr_t)
instead of considering TYPE_UNSIGNED (type).

As the result of these 2, fold_truthop is presented with ll_mask and
ll_and_mask TREE_OVERFLOW -4 and given that gets confused into believing the whole
comparison is always 0.

Ok to commit if testing succeeds?

2005-02-15  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/19857
	* fold-const.c (fold): Don't optimize (T)(x & cst) to
	(T)x & (T)cst if (T)cst overflows.
	* convert.c (convert_to_integer) <case POINTER_TYPE>: Pass
	TYPE_UNSIGNED (type) as type_for_size's UNSIGNEDP argument.

	* gcc.dg/tree-ssa/20050215-1.c: New test.
	* gcc.c-torture/execute/20050215-1.c: New test.

--- gcc/fold-const.c.jj	2005-02-14 09:25:47.000000000 +0100
+++ gcc/fold-const.c	2005-02-14 12:04:02.000000000 +0100
@@ -6874,9 +6874,12 @@ fold (tree expr)
 #endif
 	    }
 	  if (change)
-	    return fold (build2 (BIT_AND_EXPR, type,
-				 fold_convert (type, and0),
-				 fold_convert (type, and1)));
+	    {
+	      tem = fold_convert (type, and1);
+	      if (! TREE_OVERFLOW (tem))
+		return fold (build2 (BIT_AND_EXPR, type,
+				     fold_convert (type, and0), tem));
+	    }
 	}
 
       /* Convert (T1)((T2)X op Y) into (T1)X op Y, for pointer types T1 and
--- gcc/convert.c.jj	2005-01-13 14:19:21.000000000 +0100
+++ gcc/convert.c	2005-02-15 11:45:22.417756363 +0100
@@ -387,7 +387,8 @@ convert_to_integer (tree type, tree expr
 	expr = integer_zero_node;
       else
 	expr = fold (build1 (CONVERT_EXPR,
-			     lang_hooks.types.type_for_size (POINTER_SIZE, 0),
+			     lang_hooks.types.type_for_size
+				(POINTER_SIZE, TYPE_UNSIGNED (type)),
 			     expr));
 
       return convert_to_integer (type, expr);
--- gcc/testsuite/gcc.c-torture/execute/20050215-1.c.jj	2005-02-15 12:03:27.893469319 +0100
+++ gcc/testsuite/gcc.c-torture/execute/20050215-1.c	2005-02-15 12:01:46.000000000 +0100
@@ -0,0 +1,25 @@
+/* PR middle-end/19857 */
+
+typedef struct { char c[8]; } V
+#ifdef __ELF__
+  __attribute__ ((aligned (8)))
+#endif
+  ;
+typedef __SIZE_TYPE__ size_t;
+V v;
+void abort (void);
+
+int
+main (void)
+{
+  V *w = &v;
+  if (((size_t) ((float *) ((size_t) w & ~(size_t) 3)) % 8) != 0
+      || ((size_t) w & 1))
+    {
+#ifndef __ELF__
+      if (((size_t) &v & 7) == 0)
+#endif
+	abort ();
+    }
+  return 0;
+}
--- gcc/testsuite/gcc.dg/tree-ssa/20050215-1.c.jj	2005-02-15 11:36:40.164715845 +0100
+++ gcc/testsuite/gcc.dg/tree-ssa/20050215-1.c	2005-02-15 11:39:35.777458621 +0100
@@ -0,0 +1,13 @@
+/* PR middle-end/19857 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+int i;
+int foo (void)
+{
+  return i & ~(unsigned int) 3;
+}
+
+/* Make sure the optimizers don't introduce overflow where one
+   did not exist in the original.  */
+/* { dg-final { scan-tree-dump-times "-0+4" 0 "optimized"} } */

	Jakub


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