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]

Re: [PATCH] Fix undefined behavior in the combiner


On Tue, 25 Mar 2014, Jakub Jelinek wrote:

> Hi!
> 
> simplify_compare_const is sometimes called with two CONST_INTs,
> which means mode is VOIDmode and mode_width is 0, but then it
> happily verifies that mode_width is <= HOST_BITS_PER_WIDE_INT
> and shits stuff by mode_width - 1 (i.e. -1).
> From what I can understand, some optimizations can be still
> performed even when we don't know the mode width, and sometimes
> the caller knows the mode of op0, so it makes sense to pass it down
> to let the function take it into account.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, tested also
> with --with-build-config=bootstrap-ubsan bootstrap.
> Ok for trunk?

Ok.

Thanks,
Richard.

> 2014-03-25  Jakub Jelinek  <jakub@redhat.com>
> 
> 	* combine.c (simplify_compare_const): Add MODE argument.
> 	Handle mode_width 0 as very large mode_width.
> 	(try_combine, simplify_comparison): Adjust callers.
> 
> --- gcc/combine.c.jj	2014-03-03 08:24:33.000000000 +0100
> +++ gcc/combine.c	2014-03-24 11:31:13.390695208 +0100
> @@ -446,7 +446,8 @@ static rtx simplify_shift_const (rtx, en
>  				 int);
>  static int recog_for_combine (rtx *, rtx, rtx *);
>  static rtx gen_lowpart_for_combine (enum machine_mode, rtx);
> -static enum rtx_code simplify_compare_const (enum rtx_code, rtx, rtx *);
> +static enum rtx_code simplify_compare_const (enum rtx_code, enum machine_mode,
> +					     rtx, rtx *);
>  static enum rtx_code simplify_comparison (enum rtx_code, rtx *, rtx *);
>  static void update_table_tick (rtx);
>  static void record_value_for_reg (rtx, rtx, rtx);
> @@ -2949,7 +2950,7 @@ try_combine (rtx i3, rtx i2, rtx i1, rtx
>  	{
>  	  compare_code = orig_compare_code = GET_CODE (*cc_use_loc);
>  	  compare_code = simplify_compare_const (compare_code,
> -						 op0, &op1);
> +						 GET_MODE (i2dest), op0, &op1);
>  	  target_canonicalize_comparison (&compare_code, &op0, &op1, 1);
>  	}
>  
> @@ -10817,9 +10818,9 @@ gen_lowpart_for_combine (enum machine_mo
>     *POP1 may be updated.  */
>  
>  static enum rtx_code
> -simplify_compare_const (enum rtx_code code, rtx op0, rtx *pop1)
> +simplify_compare_const (enum rtx_code code, enum machine_mode mode,
> +			rtx op0, rtx *pop1)
>  {
> -  enum machine_mode mode = GET_MODE (op0);
>    unsigned int mode_width = GET_MODE_PRECISION (mode);
>    HOST_WIDE_INT const_op = INTVAL (*pop1);
>  
> @@ -10835,7 +10836,7 @@ simplify_compare_const (enum rtx_code co
>    if (const_op
>        && (code == EQ || code == NE || code == GE || code == GEU
>  	  || code == LT || code == LTU)
> -      && mode_width <= HOST_BITS_PER_WIDE_INT
> +      && mode_width - 1 < HOST_BITS_PER_WIDE_INT
>        && exact_log2 (const_op & GET_MODE_MASK (mode)) >= 0
>        && (nonzero_bits (op0, mode)
>  	  == (unsigned HOST_WIDE_INT) (const_op & GET_MODE_MASK (mode))))
> @@ -10882,7 +10883,7 @@ simplify_compare_const (enum rtx_code co
>        /* If we are doing a <= 0 comparison on a value known to have
>  	 a zero sign bit, we can replace this with == 0.  */
>        else if (const_op == 0
> -	       && mode_width <= HOST_BITS_PER_WIDE_INT
> +	       && mode_width - 1 < HOST_BITS_PER_WIDE_INT
>  	       && (nonzero_bits (op0, mode)
>  		   & ((unsigned HOST_WIDE_INT) 1 << (mode_width - 1)))
>  	       == 0)
> @@ -10911,7 +10912,7 @@ simplify_compare_const (enum rtx_code co
>        /* If we are doing a > 0 comparison on a value known to have
>  	 a zero sign bit, we can replace this with != 0.  */
>        else if (const_op == 0
> -	       && mode_width <= HOST_BITS_PER_WIDE_INT
> +	       && mode_width - 1 < HOST_BITS_PER_WIDE_INT
>  	       && (nonzero_bits (op0, mode)
>  		   & ((unsigned HOST_WIDE_INT) 1 << (mode_width - 1)))
>  	       == 0)
> @@ -10927,7 +10928,7 @@ simplify_compare_const (enum rtx_code co
>  	  /* ... fall through ...  */
>  	}
>        /* (unsigned) < 0x80000000 is equivalent to >= 0.  */
> -      else if (mode_width <= HOST_BITS_PER_WIDE_INT
> +      else if (mode_width - 1 < HOST_BITS_PER_WIDE_INT
>  	       && (unsigned HOST_WIDE_INT) const_op
>  	       == (unsigned HOST_WIDE_INT) 1 << (mode_width - 1))
>  	{
> @@ -10943,7 +10944,7 @@ simplify_compare_const (enum rtx_code co
>        if (const_op == 0)
>  	code = EQ;
>        /* (unsigned) <= 0x7fffffff is equivalent to >= 0.  */
> -      else if (mode_width <= HOST_BITS_PER_WIDE_INT
> +      else if (mode_width - 1 < HOST_BITS_PER_WIDE_INT
>  	       && (unsigned HOST_WIDE_INT) const_op
>  	       == ((unsigned HOST_WIDE_INT) 1 << (mode_width - 1)) - 1)
>  	{
> @@ -10962,7 +10963,7 @@ simplify_compare_const (enum rtx_code co
>  	}
>  
>        /* (unsigned) >= 0x80000000 is equivalent to < 0.  */
> -      else if (mode_width <= HOST_BITS_PER_WIDE_INT
> +      else if (mode_width - 1 < HOST_BITS_PER_WIDE_INT
>  	       && (unsigned HOST_WIDE_INT) const_op
>  	       == (unsigned HOST_WIDE_INT) 1 << (mode_width - 1))
>  	{
> @@ -10978,7 +10979,7 @@ simplify_compare_const (enum rtx_code co
>        if (const_op == 0)
>  	code = NE;
>        /* (unsigned) > 0x7fffffff is equivalent to < 0.  */
> -      else if (mode_width <= HOST_BITS_PER_WIDE_INT
> +      else if (mode_width - 1 < HOST_BITS_PER_WIDE_INT
>  	       && (unsigned HOST_WIDE_INT) const_op
>  	       == ((unsigned HOST_WIDE_INT) 1 << (mode_width - 1)) - 1)
>  	{
> @@ -11185,7 +11186,7 @@ simplify_comparison (enum rtx_code code,
>  
>        /* Try to simplify the compare to constant, possibly changing the
>  	 comparison op, and/or changing op1 to zero.  */
> -      code = simplify_compare_const (code, op0, &op1);
> +      code = simplify_compare_const (code, mode, op0, &op1);
>        const_op = INTVAL (op1);
>  
>        /* Compute some predicates to simplify code below.  */
> 
> 	Jakub
> 
> 

-- 
Richard Biener <rguenther@suse.de>
SUSE / SUSE Labs
SUSE LINUX Products GmbH - Nuernberg - AG Nuernberg - HRB 16746
GF: Jeff Hawn, Jennifer Guild, Felix Imend"orffer


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