2012-07-13 Richard Guenther <rguenther@suse.de>
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 13 Jul 2012 11:21:39 +0000 (11:21 +0000)
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 13 Jul 2012 11:21:39 +0000 (11:21 +0000)
PR tree-optimization/53922
* tree-vrp.c (value_inside_range): Change prototype to take
min/max instead of value-range.
(range_includes_zero_p): Likewise.  Return the result from
value_inside_range.
(extract_range_from_binary_expr_1): Adjust to handle dont-know
return value from range_includes_zero_p.
(extract_range_from_unary_expr_1): Likewise.
(compare_range_with_value): Likewise.
(vrp_meet_1): Likewise.

* gcc.dg/torture/pr53922.c: New testcase.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@189461 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/torture/pr53922.c [new file with mode: 0644]
gcc/tree-vrp.c

index e900a2a..f7b303a 100644 (file)
@@ -1,3 +1,16 @@
+2012-07-13  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/53922
+       * tree-vrp.c (value_inside_range): Change prototype to take
+       min/max instead of value-range.
+       (range_includes_zero_p): Likewise.  Return the result from
+       value_inside_range.
+       (extract_range_from_binary_expr_1): Adjust to handle dont-know
+       return value from range_includes_zero_p.
+       (extract_range_from_unary_expr_1): Likewise.
+       (compare_range_with_value): Likewise.
+       (vrp_meet_1): Likewise.
+
 2012-07-13  Bill Schmidt  <wschmidt@linux.ibm.com>
 
        * doc/tm.texi: Regenerate.
index 0e2b8f3..c628663 100644 (file)
@@ -1,3 +1,8 @@
+2012-07-13  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/53922
+       * gcc.dg/torture/pr53922.c: New testcase.
+
 2012-07-13  Hans-Peter Nilsson  <hp@axis.com>
 
        PR rtl-optimization/53908
diff --git a/gcc/testsuite/gcc.dg/torture/pr53922.c b/gcc/testsuite/gcc.dg/torture/pr53922.c
new file mode 100644 (file)
index 0000000..e42d1c7
--- /dev/null
@@ -0,0 +1,22 @@
+/* { dg-do run } */
+/* { dg-require-weak "" } */
+
+int x(int a)
+{
+  return a;
+}
+int y(int a) __attribute__ ((weak));
+int g = 0;
+int main()
+{
+  int (*scan_func)(int);
+  if (g)
+    scan_func = x;
+  else
+    scan_func = y;
+
+  if (scan_func)
+    g = scan_func(10);
+
+  return 0;
+}
index 32c5afa..0ce9a74 100644 (file)
@@ -1339,41 +1339,25 @@ compare_values (tree val1, tree val2)
 }
 
 
-/* Return 1 if VAL is inside value range VR (VR->MIN <= VAL <= VR->MAX),
-          0 if VAL is not inside VR,
+/* Return 1 if VAL is inside value range MIN <= VAL <= MAX,
+          0 if VAL is not inside [MIN, MAX],
         -2 if we cannot tell either way.
 
-   FIXME, the current semantics of this functions are a bit quirky
-         when taken in the context of VRP.  In here we do not care
-         about VR's type.  If VR is the anti-range ~[3, 5] the call
-         value_inside_range (4, VR) will return 1.
-
-         This is counter-intuitive in a strict sense, but the callers
-         currently expect this.  They are calling the function
-         merely to determine whether VR->MIN <= VAL <= VR->MAX.  The
-         callers are applying the VR_RANGE/VR_ANTI_RANGE semantics
-         themselves.
-
-         This also applies to value_ranges_intersect_p and
-         range_includes_zero_p.  The semantics of VR_RANGE and
-         VR_ANTI_RANGE should be encoded here, but that also means
-         adapting the users of these functions to the new semantics.
-
    Benchmark compile/20001226-1.c compilation time after changing this
    function.  */
 
 static inline int
-value_inside_range (tree val, value_range_t * vr)
+value_inside_range (tree val, tree min, tree max)
 {
   int cmp1, cmp2;
 
-  cmp1 = operand_less_p (val, vr->min);
+  cmp1 = operand_less_p (val, min);
   if (cmp1 == -2)
     return -2;
   if (cmp1 == 1)
     return 0;
 
-  cmp2 = operand_less_p (vr->max, val);
+  cmp2 = operand_less_p (max, val);
   if (cmp2 == -2)
     return -2;
 
@@ -1402,23 +1386,14 @@ value_ranges_intersect_p (value_range_t *vr0, value_range_t *vr1)
 }
 
 
-/* Return true if VR includes the value zero, false otherwise.  FIXME,
-   currently this will return false for an anti-range like ~[-4, 3].
-   This will be wrong when the semantics of value_inside_range are
-   modified (currently the users of this function expect these
-   semantics).  */
+/* Return 1 if [MIN, MAX] includes the value zero, 0 if it does not
+   include the value zero, -2 if we cannot tell.  */
 
-static inline bool
-range_includes_zero_p (value_range_t *vr)
+static inline int
+range_includes_zero_p (tree min, tree max)
 {
-  tree zero;
-
-  gcc_assert (vr->type != VR_UNDEFINED
-              && vr->type != VR_VARYING
-             && !symbolic_range_p (vr));
-
-  zero = build_int_cst (TREE_TYPE (vr->min), 0);
-  return (value_inside_range (zero, vr) == 1);
+  tree zero = build_int_cst (TREE_TYPE (min), 0);
+  return value_inside_range (zero, min, max);
 }
 
 /* Return true if *VR is know to only contain nonnegative values.  */
@@ -2641,7 +2616,7 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
             gives [min / 4, max / 4] range.  */
          if (vr1.type == VR_RANGE
              && !symbolic_range_p (&vr1)
-             && !range_includes_zero_p (&vr1))
+             && range_includes_zero_p (vr1.min, vr1.max) == 0)
            {
              vr0.type = type = VR_RANGE;
              vr0.min = vrp_val_min (expr_type);
@@ -2658,8 +2633,7 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
         not eliminate a division by zero.  */
       if (cfun->can_throw_non_call_exceptions
          && (vr1.type != VR_RANGE
-             || symbolic_range_p (&vr1)
-             || range_includes_zero_p (&vr1)))
+             || range_includes_zero_p (vr1.min, vr1.max) != 0))
        {
          set_value_range_to_varying (vr);
          return;
@@ -2670,8 +2644,7 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
         include 0.  */
       if (vr0.type == VR_RANGE
          && (vr1.type != VR_RANGE
-             || symbolic_range_p (&vr1)
-             || range_includes_zero_p (&vr1)))
+             || range_includes_zero_p (vr1.min, vr1.max) != 0))
        {
          tree zero = build_int_cst (TREE_TYPE (vr0.min), 0);
          int cmp;
@@ -2723,8 +2696,7 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
   else if (code == TRUNC_MOD_EXPR)
     {
       if (vr1.type != VR_RANGE
-         || symbolic_range_p (&vr1)
-         || range_includes_zero_p (&vr1)
+         || range_includes_zero_p (vr1.min, vr1.max) != 0
          || vrp_val_is_min (vr1.min))
        {
          set_value_range_to_varying (vr);
@@ -3159,7 +3131,7 @@ extract_range_from_unary_expr_1 (value_range_t *vr,
         ~[-INF, min(MIN, MAX)].  */
       if (vr0.type == VR_ANTI_RANGE)
        {
-         if (range_includes_zero_p (&vr0))
+         if (range_includes_zero_p (vr0.min, vr0.max) == 1)
            {
              /* Take the lower of the two values.  */
              if (cmp != 1)
@@ -3210,7 +3182,7 @@ extract_range_from_unary_expr_1 (value_range_t *vr,
 
       /* If the range contains zero then we know that the minimum value in the
          range will be zero.  */
-      else if (range_includes_zero_p (&vr0))
+      else if (range_includes_zero_p (vr0.min, vr0.max) == 1)
        {
          if (cmp == 1)
            max = min;
@@ -3812,7 +3784,7 @@ compare_range_with_value (enum tree_code comp, value_range_t *vr, tree val,
        return NULL_TREE;
 
       /* ~[VAL_1, VAL_2] OP VAL is known if VAL_1 <= VAL <= VAL_2.  */
-      if (value_inside_range (val, vr) == 1)
+      if (value_inside_range (val, vr->min, vr->max) == 1)
        return (comp == NE_EXPR) ? boolean_true_node : boolean_false_node;
 
       return NULL_TREE;
@@ -7548,12 +7520,14 @@ vrp_meet_1 (value_range_t *vr0, value_range_t *vr1)
         anti-range.  FIXME, all this nonsense about distinguishing
         anti-ranges from ranges is necessary because of the odd
         semantics of range_includes_zero_p and friends.  */
-      if (!symbolic_range_p (&saved)
-         && ((saved.type == VR_RANGE && !range_includes_zero_p (&saved))
-             || (saved.type == VR_ANTI_RANGE && range_includes_zero_p (&saved)))
-         && !symbolic_range_p (vr1)
-         && ((vr1->type == VR_RANGE && !range_includes_zero_p (vr1))
-             || (vr1->type == VR_ANTI_RANGE && range_includes_zero_p (vr1))))
+      if (((saved.type == VR_RANGE
+           && range_includes_zero_p (saved.min, saved.max) == 0)
+          || (saved.type == VR_ANTI_RANGE
+              && range_includes_zero_p (saved.min, saved.max) == 1))
+         && ((vr1->type == VR_RANGE
+              && range_includes_zero_p (vr1->min, vr1->max) == 0)
+             || (vr1->type == VR_ANTI_RANGE
+                 && range_includes_zero_p (vr1->min, vr1->max) == 1)))
        {
          set_value_range_to_nonnull (vr0, TREE_TYPE (saved.min));