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 problem in fold_binary


Hi,

I ran into a problem in fold_binary with a 3.4-based Ada compiler and, while I 
didn't manage to reproduce the wrong code bug with the mainline compiler, I 
think the problem is latent there too.

The failure mode is as follows: fold_binary is invoked on (64 > 127) where 64 
and 127 have the same unsigned QImode 7-bit precision integral type.  Then

       /* Comparisons with the highest or lowest possible integer of
	 the specified size will have known values.  */
       {
	int width = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (arg1)));

 	if (TREE_CODE (arg1) == INTEGER_CST
 	    && ! TREE_CONSTANT_OVERFLOW (arg1)
 	    && width <= 2 * HOST_BITS_PER_WIDE_INT
	    && (INTEGRAL_TYPE_P (TREE_TYPE (arg1))
		|| POINTER_TYPE_P (TREE_TYPE (arg1))))

Note that the size of the mode of the type is used, not its precision.  As a 
consequence, the whole logic to compute the highest or lowest possible 
integer is fooled and the natural folding is not triggered.  However, upon 
reaching

 	    else if (!in_gimple_form
 		     && TREE_INT_CST_HIGH (arg1) == signed_max_hi
 		     && TREE_INT_CST_LOW (arg1) == signed_max_lo
		     && TYPE_UNSIGNED (TREE_TYPE (arg1))
 		     /* signed_type does not work on pointer types.  */
		     && INTEGRAL_TYPE_P (TREE_TYPE (arg1)))
 	      {
 		/* The following case also applies to X < signed_max+1
 		   and X >= signed_max+1 because previous transformations.  */

127 happens to be the signed_max of any 8-bit unsigned type so the lines

		/* The following case also applies to X < signed_max+1
		   and X >= signed_max+1 because previous transformations.  */
		if (code == LE_EXPR || code == GT_EXPR)
		  {
		    tree st0, st1;
		    st0 = lang_hooks.types.signed_type (TREE_TYPE (arg0));
		    st1 = lang_hooks.types.signed_type (TREE_TYPE (arg1));
		    return fold_build2 (code == LE_EXPR ? GE_EXPR: LT_EXPR,
			       		type, fold_convert (st0, arg0),
			       	
are executed and yield

  -64 (overflow) < 0

which evaluates to true.


Proposed fix attached, tested on x86_64-suse-linux.  OK for mainline?


2006-11-05  Eric Botcazou  <ebotcazou@adacore.com>

	* fold-const.c (fold_binary) <LT_EXPR>: Use the precision of the
	type instead of the size of its mode to compute the highest and
	lowest possible values.  Still check the size of the mode before
	flipping the signedness of the comparison.


:ADDPATCH middle-end:

-- 
Eric Botcazou
Index: fold-const.c
===================================================================
--- fold-const.c	(revision 118450)
+++ fold-const.c	(working copy)
@@ -10917,15 +10917,15 @@ fold_binary (enum tree_code code, tree t
 	}
 
       /* Comparisons with the highest or lowest possible integer of
-	 the specified size will have known values.  */
+	 the specified precision will have known values.  */
       {
-	int width = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (arg1)));
+	tree arg1_type = TREE_TYPE (arg1);
+	unsigned int width = TYPE_PRECISION (arg1_type);
 
 	if (TREE_CODE (arg1) == INTEGER_CST
 	    && ! TREE_CONSTANT_OVERFLOW (arg1)
 	    && width <= 2 * HOST_BITS_PER_WIDE_INT
-	    && (INTEGRAL_TYPE_P (TREE_TYPE (arg1))
-		|| POINTER_TYPE_P (TREE_TYPE (arg1))))
+	    && (INTEGRAL_TYPE_P (arg1_type) || POINTER_TYPE_P (arg1_type)))
 	  {
 	    HOST_WIDE_INT signed_max_hi;
 	    unsigned HOST_WIDE_INT signed_max_lo;
@@ -10938,7 +10938,7 @@ fold_binary (enum tree_code code, tree t
 		signed_max_hi = 0;
 		max_hi = 0;
 
-		if (TYPE_UNSIGNED (TREE_TYPE (arg1)))
+		if (TYPE_UNSIGNED (arg1_type))
 		  {
 		    max_lo = ((unsigned HOST_WIDE_INT) 2 << (width - 1)) - 1;
 		    min_lo = 0;
@@ -10960,7 +10960,7 @@ fold_binary (enum tree_code code, tree t
 		max_lo = -1;
 		min_lo = 0;
 
-		if (TYPE_UNSIGNED (TREE_TYPE (arg1)))
+		if (TYPE_UNSIGNED (arg1_type))
 		  {
 		    max_hi = ((unsigned HOST_WIDE_INT) 2 << (width - 1)) - 1;
 		    min_hi = 0;
@@ -11046,9 +11046,11 @@ fold_binary (enum tree_code code, tree t
 	    else if (!in_gimple_form
 		     && TREE_INT_CST_HIGH (arg1) == signed_max_hi
 		     && TREE_INT_CST_LOW (arg1) == signed_max_lo
-		     && TYPE_UNSIGNED (TREE_TYPE (arg1))
+		     && TYPE_UNSIGNED (arg1_type)
+		     /* The sign bit is under the control of the mode.  */
+		     && width == GET_MODE_BITSIZE (TYPE_MODE (arg1_type))
 		     /* signed_type does not work on pointer types.  */
-		     && INTEGRAL_TYPE_P (TREE_TYPE (arg1)))
+		     && INTEGRAL_TYPE_P (arg1_type))
 	      {
 		/* The following case also applies to X < signed_max+1
 		   and X >= signed_max+1 because previous transformations.  */

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