On Tue, Nov 7, 2017 at 1:17 PM, Bin.Cheng <amker.ch...@gmail.com> wrote:
> On Tue, Nov 7, 2017 at 10:44 AM, Richard Biener
> <richard.guent...@gmail.com> wrote:
>> On Fri, Nov 3, 2017 at 1:35 PM, Bin Cheng <bin.ch...@arm.com> wrote:
>>> Hi,
>>> This is a simple patch exploiting more undefined pointer overflow behavior 
>>> in
>>> loop niter analysis.  Originally, it only supports POINTER_PLUS_EXPR if the
>>> offset part is IV.  This patch also handles the case if pointer is IV.  With
>>> this patch, the while(true) loop in test can be removed by cddce pass now.
>>>
>>> Bootstrap and test on x86_64 and AArch64.  This patch introduces two 
>>> failures:
>>> FAIL: g++.dg/pr79095-1.C  -std=gnu++98 (test for excess errors)
>>> FAIL: g++.dg/pr79095-2.C  -std=gnu++11 (test for excess errors)
>>> I believe this exposes inaccurate value range information issue.  For below 
>>> code:
>>> /* { dg-do compile } */
>>> /* { dg-options "-Wall -O3" } */
>>>
>>> typedef long unsigned int size_t;
>>>
>>> inline void
>>> fill (int *p, size_t n, int)
>>> {
>>>   while (n--)
>>>     *p++ = 0;
>>> }
>>>
>>> struct B
>>> {
>>>   int* p0, *p1, *p2;
>>>
>>>   size_t size () const {
>>>     return size_t (p1 - p0);
>>>   }
>>>
>>>   void resize (size_t n) {
>>>     if (n > size())
>>>       append (n - size());
>>>   }
>>>
>>>   void append (size_t n)
>>>   {
>>>     if (size_t (p2 - p1) >= n)   {
>>>       fill (p1, n, 0);
>>>     }
>>>   }
>>> };
>>>
>>> void foo (B &b)
>>> {
>>>   if (b.size () != 0)
>>>     b.resize (b.size () - 1);
>>> }
>>>
>>> GCC gives below warning with this patch:
>>> pr79095-1.C: In function ‘void foo(B&)’:
>>> pr79095-1.C:10:7: warning: iteration 4611686018427387903 invokes undefined 
>>> behavior [-Waggressive-loop-optimizations]
>>>      *p++ = 0;
>>>       ~^~
>>> pr79095-1.C:9:11: note: within this loop
>>>    while (n--)
>>>            ^~
>>>
>>> Problem is VRP should understand that it's never the case with condition:
>>>   (size_t (p2 - p1) >= n)
>>> in function B::append.
>>>
>>> So, any comment?

Does it warn when not inlining fill()?  Isn't the issue that one test
tests p2 - p1 and
the loop goes from p1 to p1 + (p1 - p0)?

What kind of optimization do we apply to the loop in fill?

>> I'm looking hard but I can't see you changed anything in
>> infer_loop_bounds_from_pointer_arith
>> besides adding a expr_invariant_in_loop_p (loop, rhs2) check.
> yes, that's enough for this fix?
>
> -  ptr = gimple_assign_rhs1 (stmt);
> -  if (!expr_invariant_in_loop_p (loop, ptr))
> +  rhs2 = gimple_assign_rhs2 (stmt);
> +  if (TYPE_PRECISION (type) != TYPE_PRECISION (TREE_TYPE (rhs2)))
>      return;
>
> -  var = gimple_assign_rhs2 (stmt);
> -  if (TYPE_PRECISION (type) != TYPE_PRECISION (TREE_TYPE (var)))
> +  rhs1 = gimple_assign_rhs1 (stmt);
> +  if (!expr_invariant_in_loop_p (loop, rhs1)
> +      && !expr_invariant_in_loop_p (loop, rhs2))
>      return;
>
> Before this change, the function skips if ptr in "res = ptr +p offset"
> is non-invariant.  This change only skips if both ptr and offset are
> non-invariant, thus the PR is handled.

Ah, of course.  Thanks for the explanation.

> Thanks,
> bin
>
>
>>
>> What am I missing?
>>
>> Richard.
>>
>>> Thanks,
>>> bin
>>> 2017-11-02  Bin Cheng  <bin.ch...@arm.com>
>>>
>>>         PR tree-optimization/82776
>>>         * tree-ssa-loop-niter.c (infer_loop_bounds_from_pointer_arith): 
>>> Handle
>>>         POINTER_PLUS_EXPR in which the pointer is an IV.
>>>         (infer_loop_bounds_from_signedness): Refine comment.
>>>
>>> gcc/testsuite
>>> 2017-11-02  Bin Cheng  <bin.ch...@arm.com>
>>>
>>>         PR tree-optimization/82776
>>>         * g++.dg/pr82776.C: New test.
>>>         * gcc.dg/tree-ssa/split-path-6.c: Refine test.

Reply via email to