Value range propagation simplifies convergence in vrp_visit_phi_node by
setting minimum to TYPE_MIN when the computed minimum is smaller than
the previous minimum. This can however result in pessimistic value
ranges in some cases.

for example,

        unsigned int i;
        for (i = 0; i < 8; i++)
        {
          ....
        }

        # ivtmp_19 = PHI <ivtmp_17(5), 8(2)>
        ...
        <bb 5>:
        ivtmp_17 = ivtmp_19 - 1;
        if (ivtmp_17 != 0)
        ....
        goto <bb 5>;

min value of ivtmp_19  is simplified to 0 (in tree-vrp.c:8465) where as
it should have been 1. This prevents correct value ranges being
calculated for ivtmp_17 in the example.

We should be able to see the step (the difference from previous minimum
to computed minimum) and if there is scope for more iterations (computed
minimum is greater than step), and then we should be able set minimum to
do one more iteration and converge to the right minimum value.

Attached patch fixes this. Is this OK for stage-1?

Bootstrapped and regression tested on X86_64-unknown-linux-gnu with no
new regressions.

Thanks,
Kugan

gcc/

+2014-04-09  Kugan Vivekanandarajah  <kug...@linaro.org>
+
+       * tree-vrp.c (vrp_visit_phi_node) : Improve value ranges of loop
+       index when simplifying convergence towards minimum.
+

gcc/testsuite

+2014-04-09  Kugan Vivekanandarajah  <kug...@linaro.org>
+
+       * gcc.dg/tree-ssa/vrp91.c: New test
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp91.c 
b/gcc/testsuite/gcc.dg/tree-ssa/vrp91.c
index e69de29..26e857c 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/vrp91.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp91.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-S -O2 -fdump-tree-vrp2" } */
+
+unsigned short data;
+void foo ()
+{
+  unsigned char  x16;
+  unsigned int i;
+  for (i = 0; i < 8; i++)
+    {
+      x16 = data & 1;
+      data >>= 1;
+      if (x16 == 1)
+       {
+         data ^= 0x4;
+       }
+      data >>= 1;
+    }
+}
+
+/* { dg-final { scan-tree-dump "\\\[0, 7\\\]" "vrp2" } } */
+/* { dg-final { cleanup-tree-dump "vrp2" } } */
+
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 14f1526..c63f794 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -8461,7 +8461,30 @@ vrp_visit_phi_node (gimple phi)
        {
          if (!needs_overflow_infinity (TREE_TYPE (vr_result.min))
              || !vrp_var_may_overflow (lhs, phi))
-           vr_result.min = TYPE_MIN_VALUE (TREE_TYPE (vr_result.min));
+           {
+             tree step = ((cmp_min > 0) && TYPE_UNSIGNED (TREE_TYPE (lhs))) ?
+               int_const_binop (MINUS_EXPR, lhs_vr->min, vr_result.min) : 
NULL_TREE;
+
+             /* If the type minimum is zero, while avoiding repeated
+                iterations, let us stop at step and let the iterations take
+                it to zero (if necessary) from there.  This will improve
+                value ranges for cases like below, when the value range
+                for ivtemp_17 is [0, 7] and range for ivtmp_19 is [1, 8].
+
+               # ivtmp_19 = PHI <ivtmp_17(5), 8(2)>
+               ...
+               <bb 5>:
+               ivtmp_17 = ivtmp_19 - 1;
+               if (ivtmp_17 != 0)
+               ....
+               goto <bb 5>;
+             */
+             if ((cmp_min > 0) && (TYPE_UNSIGNED (TREE_TYPE (lhs)))
+                 && (tree_int_cst_compare (vr_result.min, step) != -1))
+               vr_result.min = step;
+             else
+               vr_result.min = TYPE_MIN_VALUE (TREE_TYPE (vr_result.min));
+           }
          else if (supports_overflow_infinity (TREE_TYPE (vr_result.min)))
            vr_result.min =
                negative_overflow_infinity (TREE_TYPE (vr_result.min));

Reply via email to