diff mbox

Fix get_mode_bounds for BImode (PR rtl-optimization/59649)

Message ID 20140108094707.GC892@tucnak.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek Jan. 8, 2014, 9:47 a.m. UTC
Hi!

The recent change to get_mode_bounds for partial mode, where
GET_MODE_PRECISION instead of GET_MODE_SIZE is now used, has broken
ia64 bootstrap.  The problem is that BImode is special cased in various
places, e.g. trunc_int_for_mode, so the two values of the mode are
0 and STORE_FLAG_VALUE (which is sometimes -1, sometimes (ia64 case) 1).

Now, two of the 3 get_mode_bounds callers use the same mode == target_mode
and when called with BImode, true, BImode, ... min_val is -1 and max_val is 0, 
but given the weirdo trunc_int_for_mode behavior which returns
STORE_FLAG_VALUE for value with low bit set and 0 otherwise, get_mode_bounds
actually returns min_rtx (const_int 1) and max_rtx (const_int 0).
This confuses the callers (in this case simplify-rtx.c) which then compares
the trueop1 value against the bounds to miscompile the code.

This patch fixes this by special casing BImode, so that we get the bounds
in the right order for BImode, ?, BImode and even for the case where
target_mode is wider ignores sign and returns 0, STORE_FLAG_VALUE or vice
versa in the right order.

Eric has kindly tested this on ia64.  Ok for trunk?

2014-01-08  Jakub Jelinek  <jakub@redhat.com>

	PR rtl-optimization/59649
	* stor-layout.c (get_mode_bounds): For BImode return
	0 and STORE_FLAG_VALUE.


	Jakub

Comments

Richard Biener Jan. 8, 2014, 9:55 a.m. UTC | #1
On Wed, 8 Jan 2014, Jakub Jelinek wrote:

> Hi!
> 
> The recent change to get_mode_bounds for partial mode, where
> GET_MODE_PRECISION instead of GET_MODE_SIZE is now used, has broken
> ia64 bootstrap.  The problem is that BImode is special cased in various
> places, e.g. trunc_int_for_mode, so the two values of the mode are
> 0 and STORE_FLAG_VALUE (which is sometimes -1, sometimes (ia64 case) 1).
> 
> Now, two of the 3 get_mode_bounds callers use the same mode == target_mode
> and when called with BImode, true, BImode, ... min_val is -1 and max_val is 0, 
> but given the weirdo trunc_int_for_mode behavior which returns
> STORE_FLAG_VALUE for value with low bit set and 0 otherwise, get_mode_bounds
> actually returns min_rtx (const_int 1) and max_rtx (const_int 0).
> This confuses the callers (in this case simplify-rtx.c) which then compares
> the trueop1 value against the bounds to miscompile the code.
> 
> This patch fixes this by special casing BImode, so that we get the bounds
> in the right order for BImode, ?, BImode and even for the case where
> target_mode is wider ignores sign and returns 0, STORE_FLAG_VALUE or vice
> versa in the right order.
> 
> Eric has kindly tested this on ia64.  Ok for trunk?

Ok.

Thanks,
Richard.

> 2014-01-08  Jakub Jelinek  <jakub@redhat.com>
> 
> 	PR rtl-optimization/59649
> 	* stor-layout.c (get_mode_bounds): For BImode return
> 	0 and STORE_FLAG_VALUE.
> 
> --- gcc/stor-layout.c.jj	2014-01-03 11:40:57.000000000 +0100
> +++ gcc/stor-layout.c	2014-01-07 18:59:39.056846684 +0100
> @@ -2821,7 +2821,21 @@ get_mode_bounds (enum machine_mode mode,
>  
>    gcc_assert (size <= HOST_BITS_PER_WIDE_INT);
>  
> -  if (sign)
> +  /* Special case BImode, which has values 0 and STORE_FLAG_VALUE.  */
> +  if (mode == BImode)
> +    {
> +      if (STORE_FLAG_VALUE < 0)
> +	{
> +	  min_val = STORE_FLAG_VALUE;
> +	  max_val = 0;
> +	}
> +      else
> +	{
> +	  min_val = 0;
> +	  max_val = STORE_FLAG_VALUE;
> +	}
> +    }
> +  else if (sign)
>      {
>        min_val = -((unsigned HOST_WIDE_INT) 1 << (size - 1));
>        max_val = ((unsigned HOST_WIDE_INT) 1 << (size - 1)) - 1;
> 
> 	Jakub
> 
>
diff mbox

Patch

--- gcc/stor-layout.c.jj	2014-01-03 11:40:57.000000000 +0100
+++ gcc/stor-layout.c	2014-01-07 18:59:39.056846684 +0100
@@ -2821,7 +2821,21 @@  get_mode_bounds (enum machine_mode mode,
 
   gcc_assert (size <= HOST_BITS_PER_WIDE_INT);
 
-  if (sign)
+  /* Special case BImode, which has values 0 and STORE_FLAG_VALUE.  */
+  if (mode == BImode)
+    {
+      if (STORE_FLAG_VALUE < 0)
+	{
+	  min_val = STORE_FLAG_VALUE;
+	  max_val = 0;
+	}
+      else
+	{
+	  min_val = 0;
+	  max_val = STORE_FLAG_VALUE;
+	}
+    }
+  else if (sign)
     {
       min_val = -((unsigned HOST_WIDE_INT) 1 << (size - 1));
       max_val = ((unsigned HOST_WIDE_INT) 1 << (size - 1)) - 1;