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? > > 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. 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.