aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Guenther <rguenther@suse.de>2008-04-03 09:33:27 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2008-04-03 09:33:27 +0000
commitb47ee38692ad7393bdaf2c366a6734d7dd60e951 (patch)
treea2ae95848ad29834c4aebe2e2796e4c90590e0cb /gcc
parent2a7428c0c57b74cb4f0d7b497ec870132a3fb5d7 (diff)
downloadgcc-b47ee38692ad7393bdaf2c366a6734d7dd60e951.zip
gcc-b47ee38692ad7393bdaf2c366a6734d7dd60e951.tar.gz
gcc-b47ee38692ad7393bdaf2c366a6734d7dd60e951.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vrp43.c22
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vrp44.c30
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vrp45.c19
-rw-r--r--gcc/tree-vrp.c102
6 files changed, 129 insertions, 55 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 764c6fc..321dfb0 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index e291072..59bc95a 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp43.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp43.c
new file mode 100644
index 0000000..f475354
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp43.c
@@ -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;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp44.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp44.c
new file mode 100644
index 0000000..a2df852
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp44.c
@@ -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; }
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp45.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp45.c
new file mode 100644
index 0000000..7916d2d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp45.c
@@ -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; }
+
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 6563528..9741262 100644
--- a/gcc/tree-vrp.c
+++ b/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