Commit b47ee386 by Richard Guenther Committed by Richard Biener

tree-vrp.c (extract_range_from_unary_expr): Handle all conversions.

2008-04-03  Richard Guenther  <rguenther@suse.de>

	* tree-vrp.c (extract_range_from_unary_expr): Handle all
	conversions.  Simplify code.

	* gcc.dg/tree-ssa/vrp43.c: New testcase.
	* gcc.dg/tree-ssa/vrp44.c: Likewise.
	* gcc.dg/tree-ssa/vrp45.c: Likewise.

From-SVN: r133866
parent 2a7428c0
2008-04-03 Richard Guenther <rguenther@suse.de>
* tree-vrp.c (extract_range_from_unary_expr): Handle all
conversions. Simplify code.
2008-04-03 Kaz Kojima <kkojima@gcc.gnu.org>
* config/sh/sh.c (sh_output_mi_thunk): Free cfun.
......
2008-04-03 Richard Guenther <rguenther@suse.de>
* gcc.dg/tree-ssa/vrp43.c: New testcase.
* gcc.dg/tree-ssa/vrp44.c: Likewise.
* gcc.dg/tree-ssa/vrp45.c: Likewise.
2008-04-03 Jakub Jelinek <jakub@redhat.com>
PR c++/35741
/* { dg-do run } */
/* { dg-options "-O2" } */
int __attribute__((noinline))
foo(int i)
{
if (i != 0)
{
char c = (char)i;
return c != 0;
}
return 0;
}
extern void abort (void);
int main()
{
if (foo(0xff00))
abort ();
return 0;
}
/* { dg-do link } */
/* { dg-options "-O2" } */
extern void link_error (void);
void test1(int i)
{
if (i >= -5 && i <= 8)
{
unsigned int j = i + 1;
if (j == -5)
link_error ();
if (j == 10)
link_error ();
}
}
void test2(unsigned int i)
{
if (i >= -5 || i <= 8)
{
int j = i;
if (j == -6)
link_error ();
if (j == 9)
link_error ();
}
}
int main() { return 0; }
/* { dg-do link } */
/* { dg-options "-O2" } */
extern void link_error (void);
void foo (int i)
{
if (i > -128 && i < 127)
{
unsigned char k = i;
if (k == 0x80)
link_error ();
if (k == 0x7f)
link_error ();
}
}
int main() { return 0; }
......@@ -2350,71 +2350,63 @@ extract_range_from_unary_expr (value_range_t *vr, enum tree_code code,
}
/* Handle unary expressions on integer ranges. */
if (code == NOP_EXPR || code == CONVERT_EXPR)
if ((code == NOP_EXPR
|| code == CONVERT_EXPR)
&& INTEGRAL_TYPE_P (type)
&& INTEGRAL_TYPE_P (TREE_TYPE (op0)))
{
tree inner_type = TREE_TYPE (op0);
tree outer_type = type;
/* If VR0 represents a simple range, then try to convert
the min and max values for the range to the same type
as OUTER_TYPE. If the results compare equal to VR0's
min and max values and the new min is still less than
or equal to the new max, then we can safely use the newly
computed range for EXPR. This allows us to compute
accurate ranges through many casts. */
if ((vr0.type == VR_RANGE
&& !overflow_infinity_range_p (&vr0))
|| (vr0.type == VR_VARYING
&& TYPE_PRECISION (outer_type) > TYPE_PRECISION (inner_type)))
/* Always use base-types here. This is important for the
correct signedness. */
if (TREE_TYPE (inner_type))
inner_type = TREE_TYPE (inner_type);
if (TREE_TYPE (outer_type))
outer_type = TREE_TYPE (outer_type);
/* If VR0 is varying and we increase the type precision, assume
a full range for the following transformation. */
if (vr0.type == VR_VARYING
&& TYPE_PRECISION (inner_type) < TYPE_PRECISION (outer_type))
{
tree new_min, new_max, orig_min, orig_max;
/* Convert the input operand min/max to OUTER_TYPE. If
the input has no range information, then use the min/max
for the input's type. */
if (vr0.type == VR_RANGE)
{
orig_min = vr0.min;
orig_max = vr0.max;
}
else
{
orig_min = TYPE_MIN_VALUE (inner_type);
orig_max = TYPE_MAX_VALUE (inner_type);
}
new_min = fold_convert (outer_type, orig_min);
new_max = fold_convert (outer_type, orig_max);
/* Verify the new min/max values are gimple values and
that they compare equal to the original input's
min/max values. */
if (is_gimple_val (new_min)
&& is_gimple_val (new_max)
&& tree_int_cst_equal (new_min, orig_min)
&& tree_int_cst_equal (new_max, orig_max)
&& (!is_overflow_infinity (new_min)
|| !is_overflow_infinity (new_max))
&& (cmp = compare_values (new_min, new_max)) <= 0
&& cmp >= -1)
{
set_value_range (vr, VR_RANGE, new_min, new_max, vr->equiv);
return;
}
vr0.type = VR_RANGE;
vr0.min = TYPE_MIN_VALUE (inner_type);
vr0.max = TYPE_MAX_VALUE (inner_type);
}
/* When converting types of different sizes, set the result to
VARYING. Things like sign extensions and precision loss may
change the range. For instance, if x_3 is of type 'long long
int' and 'y_5 = (unsigned short) x_3', if x_3 is ~[0, 0], it
is impossible to know at compile time whether y_5 will be
~[0, 0]. */
if (TYPE_SIZE (inner_type) != TYPE_SIZE (outer_type)
|| TYPE_PRECISION (inner_type) != TYPE_PRECISION (outer_type))
/* If VR0 is a constant range or anti-range and the conversion is
not truncating we can convert the min and max values and
canonicalize the resulting range. Otherwise we can do the
conversion if the size of the range is less than what the
precision of the target type can represent and the range is
not an anti-range. */
if ((vr0.type == VR_RANGE
|| vr0.type == VR_ANTI_RANGE)
&& TREE_CODE (vr0.min) == INTEGER_CST
&& TREE_CODE (vr0.max) == INTEGER_CST
&& !is_overflow_infinity (vr0.min)
&& !is_overflow_infinity (vr0.max)
&& (TYPE_PRECISION (outer_type) >= TYPE_PRECISION (inner_type)
|| (vr0.type == VR_RANGE
&& integer_zerop (int_const_binop (RSHIFT_EXPR,
int_const_binop (MINUS_EXPR, vr0.max, vr0.min, 0),
size_int (TYPE_PRECISION (outer_type)), 0)))))
{
set_value_range_to_varying (vr);
tree new_min, new_max;
new_min = force_fit_type_double (outer_type,
TREE_INT_CST_LOW (vr0.min),
TREE_INT_CST_HIGH (vr0.min), 0, 0);
new_max = force_fit_type_double (outer_type,
TREE_INT_CST_LOW (vr0.max),
TREE_INT_CST_HIGH (vr0.max), 0, 0);
set_and_canonicalize_value_range (vr, vr0.type,
new_min, new_max, NULL);
return;
}
set_value_range_to_varying (vr);
return;
}
/* Conversion of a VR_VARYING value to a wider type can result
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment