[PATCH] Fix PR43949

Richard Guenther rguenther@suse.de
Mon May 3 16:11:00 GMT 2010


On Mon, 3 May 2010, Michael Matz wrote:

> Hi,
> 
> On Sat, 1 May 2010, Richard Guenther wrote:
> 
> > +   else if (code == TRUNC_MOD_EXPR
> > + 	   || code == FLOOR_MOD_EXPR
> > + 	   || code == CEIL_MOD_EXPR
> > + 	   || code == ROUND_MOD_EXPR)
> > +     {
> > +       bool sop = false;
> > +       if (vr0.type == VR_ANTI_RANGE
> > + 	  || vr1.type != VR_RANGE
> > + 	  || symbolic_range_p (&vr1)
> > + 	  || range_includes_zero_p (&vr1))
> > + 	{
> > + 	  set_value_range_to_varying (vr);
> > + 	  return;
> > + 	}
> > +       type = VR_RANGE;
> > +       max = int_const_binop (MINUS_EXPR, vr1.max, integer_one_node, 0);
> > +       if (vrp_expr_computes_nonnegative (op0, &sop)
> > + 	  && vrp_expr_computes_nonnegative (op1, &sop) && !sop)
> > + 	min = build_int_cst (TREE_TYPE (vr1.max), 0);
> > +       else
> > + 	min = fold_unary (NEGATE_EXPR, TREE_TYPE (max), max);
> > +     }
> 
> I still don't think this is fully correct.  In the first patch already
>   X % -C
> was mishandled (this is equivalent to X % C), because if the range of vr2 
> was e.g. [-5, -2] you would state that the result was -3 max, where in 
> reality it's 4 max.  This possibly is now fixed with the _UNSIGNED check.
> 
> But e.g. CEIL_MOD_EXPR would still be mishandled.  The result of 
> CEIL_MOD_EXPR is always <= 0.  ROUND_MOD_EXPR should also be mishandled 
> (its result can also be < 0).  FLOOR_MOD_EXPR was mishandled for negative 
> values I think (perhaps fixed with the _UNSIGNED check).
> 
> Currently we don't ever generate CEIL_MOD_EXPR AFAICS, but Ada can 
> generate ROUND_MOD_EXPR and FLOOR_MOD_EXPR.

Yeah.  The following was bootstrapped and tested on 
x86_64-unknown-linxu-gnu.

Richard.

2010-05-03  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/43949
	* tree-vrp.c (extract_range_from_binary_expr): Only handle
	TRUNC_MOD_EXPR.

Index: gcc/tree-vrp.c
===================================================================
*** gcc/tree-vrp.c	(revision 158988)
--- gcc/tree-vrp.c	(working copy)
*************** extract_range_from_binary_expr (value_ra
*** 2084,2092 ****
        && code != EXACT_DIV_EXPR
        && code != ROUND_DIV_EXPR
        && code != TRUNC_MOD_EXPR
-       && code != FLOOR_MOD_EXPR
-       && code != CEIL_MOD_EXPR
-       && code != ROUND_MOD_EXPR
        && code != RSHIFT_EXPR
        && code != MIN_EXPR
        && code != MAX_EXPR
--- 2084,2089 ----
*************** extract_range_from_binary_expr (value_ra
*** 2156,2164 ****
        && code != EXACT_DIV_EXPR
        && code != ROUND_DIV_EXPR
        && code != TRUNC_MOD_EXPR
-       && code != FLOOR_MOD_EXPR
-       && code != CEIL_MOD_EXPR
-       && code != ROUND_MOD_EXPR
        && (vr0.type == VR_VARYING
  	  || vr1.type == VR_VARYING
  	  || vr0.type != vr1.type
--- 2153,2158 ----
*************** extract_range_from_binary_expr (value_ra
*** 2509,2535 ****
  	    }
  	}
      }
!   else if (code == TRUNC_MOD_EXPR
! 	   || code == FLOOR_MOD_EXPR
! 	   || code == CEIL_MOD_EXPR
! 	   || code == ROUND_MOD_EXPR)
      {
        bool sop = false;
!       if (vr0.type == VR_ANTI_RANGE
! 	  || vr1.type != VR_RANGE
  	  || symbolic_range_p (&vr1)
! 	  || range_includes_zero_p (&vr1))
  	{
  	  set_value_range_to_varying (vr);
  	  return;
  	}
        type = VR_RANGE;
!       max = int_const_binop (MINUS_EXPR, vr1.max, integer_one_node, 0);
!       if (vrp_expr_computes_nonnegative (op0, &sop)
! 	  && vrp_expr_computes_nonnegative (op1, &sop) && !sop)
! 	min = build_int_cst (TREE_TYPE (vr1.max), 0);
        else
! 	min = fold_unary (NEGATE_EXPR, TREE_TYPE (max), max);
      }
    else if (code == MINUS_EXPR)
      {
--- 2503,2532 ----
  	    }
  	}
      }
!   else if (code == TRUNC_MOD_EXPR)
      {
        bool sop = false;
!       if (vr1.type != VR_RANGE
  	  || symbolic_range_p (&vr1)
! 	  || range_includes_zero_p (&vr1)
! 	  || vrp_val_is_min (vr1.min))
  	{
  	  set_value_range_to_varying (vr);
  	  return;
  	}
        type = VR_RANGE;
!       /* Compute MAX <|vr1.min|, |vr1.max|> - 1.  */
!       max = fold_unary_to_constant (ABS_EXPR, TREE_TYPE (vr1.min), vr1.min);
!       if (tree_int_cst_lt (max, vr1.max))
! 	max = vr1.max;
!       max = int_const_binop (MINUS_EXPR, max, integer_one_node, 0);
!       /* If the divisor is non-negative the modulus will be
! 	 non-negative as well.  */
!       if (TYPE_UNSIGNED (TREE_TYPE (max))
! 	  || vrp_expr_computes_nonnegative (op0, &sop) && !sop)
! 	min = build_int_cst (TREE_TYPE (max), 0);
        else
! 	min = fold_unary_to_constant (NEGATE_EXPR, TREE_TYPE (max), max);
      }
    else if (code == MINUS_EXPR)
      {



More information about the Gcc-patches mailing list