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
This commit is contained in:
parent
2a7428c0c5
commit
b47ee38692
@ -1,3 +1,8 @@
|
||||
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.
|
||||
|
@ -1,3 +1,9 @@
|
||||
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
|
||||
|
22
gcc/testsuite/gcc.dg/tree-ssa/vrp43.c
Normal file
22
gcc/testsuite/gcc.dg/tree-ssa/vrp43.c
Normal file
@ -0,0 +1,22 @@
|
||||
/* { 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;
|
||||
}
|
30
gcc/testsuite/gcc.dg/tree-ssa/vrp44.c
Normal file
30
gcc/testsuite/gcc.dg/tree-ssa/vrp44.c
Normal file
@ -0,0 +1,30 @@
|
||||
/* { 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; }
|
19
gcc/testsuite/gcc.dg/tree-ssa/vrp45.c
Normal file
19
gcc/testsuite/gcc.dg/tree-ssa/vrp45.c
Normal file
@ -0,0 +1,19 @@
|
||||
/* { 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; }
|
||||
|
102
gcc/tree-vrp.c
102
gcc/tree-vrp.c
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user