On Wed, Jan 25, 2017 at 5:30 PM, Bin Cheng <[email protected]> wrote:
> 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?
The patch looks heuristically good though, for a < limit we chose
[MIN, limit - 1]
rather than [MIN, +INF - 1] which would be a non-varying integer range (and we
usually prefer those). So maybe restrict it to LE/GE_EXPR? That also fixes
pr31521.c but unfortunately regresses your new testcase again... so much for
heuristics ;)
You are correct about limitations in operand_less_p and improvements there
are of course welcome. Btw, I played with
Index: gcc/tree-vrp.c
===================================================================
--- gcc/tree-vrp.c (revision 244920)
+++ gcc/tree-vrp.c (working copy)
@@ -1663,7 +1663,12 @@ extract_range_for_var_from_comparison_ex
{
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
+ && ((cond_code == LE_EXPR
+ && vrp_val_is_max (limit_vr->max)
+ && compare_values (limit_vr->min, limit_vr->max) != 0)
+ || is_overflow_infinity (limit_vr->max))))
max = limit;
else
{
@@ -1703,7 +1708,12 @@ extract_range_for_var_from_comparison_ex
{
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
+ && ((cond_code == GE_EXPR
+ && vrp_val_is_min (limit_vr->min)
+ && compare_values (limit_vr->min, limit_vr->max) != 0)
+ || is_overflow_infinity (limit_vr->min))))
min = limit;
else
{
note the overflow_infinity case which would make us drop to varying below.
Thanks,
Richard.
> Thanks,
> bin
>
> 2017-01-24 Bin Cheng <[email protected]>
>
> 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 <[email protected]>
>
> PR tree-optimization/71437
> * gcc.dg/tree-ssa/pr71437.c: New test.