[PATCH] Avoid creating TREE_OVERFLOW constants in convert_to_integer (PR middle-end/26729)

Jakub Jelinek jakub@redhat.com
Wed Apr 19 22:30:00 GMT 2006


Hi!

convert_to_integer seems to optimize truncation (shouldn't that be solely
fold's job?), but during that can create integer overflowed constants that
mess optimizers later on.  The following patch fixes that by doing the same
that e.g. the C frontend does after calling convert - dropping the overflow
bit if it was introduced during the optimization.
Bootstrapped/regtested on x86_64-linux, ok for trunk/4.1?
I know Roger's patch might make this eventually unnecessary on the trunk,
still 4.1 branch is probably not going to have those changes.

2006-04-19  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/26729
	* convert.c (convert_to_integer): Ignore integer overflows when
	truncating.

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

--- gcc/convert.c.jj	2006-04-19 16:23:13.000000000 +0200
+++ gcc/convert.c	2006-04-19 17:11:43.000000000 +0200
@@ -616,6 +616,7 @@ convert_to_integer (tree type, tree expr
 		   (Otherwise would recurse infinitely in convert.  */
 		if (TYPE_PRECISION (typex) != inprec)
 		  {
+		    tree carg0, carg1;
 		    /* Don't do unsigned arithmetic where signed was wanted,
 		       or vice versa.
 		       Exception: if both of the original operands were
@@ -648,10 +649,29 @@ convert_to_integer (tree type, tree expr
 		      typex = lang_hooks.types.unsigned_type (typex);
 		    else
 		      typex = lang_hooks.types.signed_type (typex);
-		    return convert (type,
-				    fold_build2 (ex_form, typex,
-						 convert (typex, arg0),
-						 convert (typex, arg1)));
+		    carg0 = convert (typex, arg0);
+		    carg1 = convert (typex, arg1);
+		    /* Ignore integer overflows caused by the downcasts.  */
+		    if (TREE_CODE (carg0) == INTEGER_CST
+			&& (TREE_OVERFLOW (carg0)
+			    || TREE_CONSTANT_OVERFLOW (carg0))
+			&& (!CONSTANT_CLASS_P (arg0)
+			    || (!TREE_OVERFLOW (arg0)
+				&& !TREE_CONSTANT_OVERFLOW (arg0))))
+		      carg0 = build_int_cst_wide (typex,
+						  TREE_INT_CST_LOW (carg0),
+						  TREE_INT_CST_HIGH (carg0));
+		    if (TREE_CODE (carg1) == INTEGER_CST
+			&& (TREE_OVERFLOW (carg1)
+			    || TREE_CONSTANT_OVERFLOW (carg1))
+			&& (!CONSTANT_CLASS_P (arg1)
+			    || (!TREE_OVERFLOW (arg1)
+				&& !TREE_CONSTANT_OVERFLOW (arg1))))
+		      carg1 = build_int_cst_wide (typex,
+						  TREE_INT_CST_LOW (carg1),
+						  TREE_INT_CST_HIGH (carg1));
+		    return convert (type, fold_build2 (ex_form, typex,
+						       carg0, carg1));
 		  }
 	      }
 	  }
--- gcc/testsuite/gcc.c-torture/execute/20060419-1.c.jj	2006-04-19 17:15:12.000000000 +0200
+++ gcc/testsuite/gcc.c-torture/execute/20060419-1.c	2006-04-19 17:16:13.000000000 +0200
@@ -0,0 +1,17 @@
+/* PR middle-end/26729 */
+
+void abort (void);
+
+int
+foo (unsigned short x)
+{
+  return (x & 0x1) && (((unsigned short) (x & 0x8000)) == 0x8000);
+}
+
+int
+main (void)
+{
+  if (! foo (0x8001))
+    abort ();
+  return 0;
+}

	Jakub



More information about the Gcc-patches mailing list