Hi,
As analyzed in PR71437, it's a missed PRE issue due to missed jump threading,
and then due to inaccurate VRP information.  In function 
extract_range_for_var_from_comparison_expr,
we compute range for variable "a" under condition that comparison like "a <= 
limit"
is true.  It extracts limit's range information and set range [MIN, 
limit_vr->max] to var.
This is inaccurate when limit_vr->max is MAX.  In this case the final range 
computed
is [MIN, MAX] which is VARYING.  In fact, symbolic range info [MIN, limit] is 
better here.
This patch fixes PR71437 by making such change.  It also handles ">=" cases.

Bootstrap and test on x86_64 and AArch64 finished.  All tests are OK except test
gcc.dg/tree-ssa/pr31521.c.  I further investigated it and believe it's another 
missed
optimization in VRP.  Basically, operand_less_p is weak in handling symbolic 
value
range.  Given below value ranges:
x: [1, INF+]
a: [-INF, x - 1]
b: [0, INF+]
It doesn't know that "x - 1 < INF+" must be true, thus (intersect a b) is [0, x 
- 1].
I believe there may be other places in which symbolic value range is not handled
properly.  So any comment?

Thanks,
bin

2017-01-24  Bin Cheng  <bin.ch...@arm.com>

        PR tree-optimization/71437
        * tree-vrp.c (extract_range_for_var_from_comparison_expr): Prefer
        symbolic range form if limit has no useful range information.

gcc/testsuite/ChangeLog
2017-01-24  Bin Cheng  <bin.ch...@arm.com>

        PR tree-optimization/71437
        * gcc.dg/tree-ssa/pr71437.c: New test.
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr71437.c 
b/gcc/testsuite/gcc.dg/tree-ssa/pr71437.c
new file mode 100644
index 0000000..66a5405
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr71437.c
@@ -0,0 +1,42 @@
+/* { dg-do compile } */
+/* { dg-options "-ffast-math -O3 -fdump-tree-vrp1-details" } */
+
+int I = 50, J = 50;
+int S, L;
+const int *pL;
+const int *pS;
+
+void bar (float, float);
+
+void foo (int K)
+{
+  int k, i, j;
+  static float LD, SD;
+  for (k = 0 ; k < K; k++)
+    {
+        for( i = 0 ; i < ( I - 1 ) ; i++ )
+        {
+            if( ( L < pL[i+1] ) && ( L >= pL[i] ) )
+              break ;
+        }
+
+        if( i == ( I - 1 ) )
+          L = pL[i] ;
+        LD = (float)( L - pL[i] ) /
+                        (float)( pL[i + 1] - pL[i] ) ;
+
+        for( j = 0 ; j < ( J-1 ) ; j++ )
+        {
+            if( ( S < pS[j+1] ) && ( S >= pS[j] ) )
+              break ;
+        }
+
+        if( j == ( J - 1 ) )
+          S = pS[j] ;
+        SD = (float)( S - pS[j] ) /
+                         (float)( pS[j + 1] - pS[j] ) ;
+
+       bar (LD, SD);
+    }
+}
+/* { dg-final { scan-tree-dump-times "Threaded jump " 2 "vrp1" } } */
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index ac37d3f..fc3f9a9 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -1663,7 +1663,10 @@ extract_range_for_var_from_comparison_expr (tree var, 
enum tree_code cond_code,
     {
       min = TYPE_MIN_VALUE (type);
 
-      if (limit_vr == NULL || limit_vr->type == VR_ANTI_RANGE)
+      if (limit_vr == NULL || limit_vr->type == VR_ANTI_RANGE
+         || (limit_vr->type == VR_RANGE
+             && vrp_val_is_max (limit_vr->max)
+             && compare_values (limit_vr->min, limit_vr->max) != 0))
        max = limit;
       else
        {
@@ -1703,7 +1706,10 @@ extract_range_for_var_from_comparison_expr (tree var, 
enum tree_code cond_code,
     {
       max = TYPE_MAX_VALUE (type);
 
-      if (limit_vr == NULL || limit_vr->type == VR_ANTI_RANGE)
+      if (limit_vr == NULL || limit_vr->type == VR_ANTI_RANGE
+         || (limit_vr->type == VR_RANGE
+             && vrp_val_is_min (limit_vr->min)
+             && compare_values (limit_vr->min, limit_vr->max) != 0))
        min = limit;
       else
        {

Reply via email to