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
{