[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