https://gcc.gnu.org/bugzilla/show_bug.cgi?id=62217
Bug ID: 62217 Summary: Extra iteration peeled during cunroll. Makes VRP warn. Product: gcc Version: 4.9.2 Status: UNCONFIRMED Severity: normal Priority: P3 Component: tree-optimization Assignee: unassigned at gcc dot gnu.org Reporter: kyukhin at gcc dot gnu.org Suppose we have a test: typedef struct { unsigned data; } s1; s1 g_x[4]; extern void foo (s1 *x1, s1 *x2, int a, int b) { int i; for(i = 0; i < a; i++) if(i == b) g_x[i] = *x1; else g_x[i] = *x2; } $ ./build-x86_64-linux/gcc/xgcc -B./build-x86_64-linux/gcc -O3 -Wall -S x1.c x1.c: In function ‘foo’: x1.c:9:10: warning: array subscript is above array bounds [-Warray-bounds] g_x[i] = *x1; ^ Which come from second pass of VRP: # i_14 = PHI <4(14)> if (b_6(D) == 4) goto <bb 17>; else goto <bb 18>; <bb 17>: g_x[4] = *x1_7(D); i_11 = 5; goto <bb 3>; <bb 18>: __builtin_unreachable (); VRP checker fairly warns that g_x[4] is out-of-bounds mem ref. This code was generated by tree-ssa-loop-ivcanon.c I do not completely understand logic of cunroll pass, however dumps say: Loop 1 iterates at most 4 times. ... x1.c:7:3: note: loop with 5 iterations completely unrolled Last iteration exit edge was proved true. Forced statement unreachable: g_x[i_14] = *x2_9(D); In function `try_unroll_loop_completely' argument `maxiter' equals to 4, which is correct. Then (through n_unroll var) this value is passed to `gimple_duplicate_loop_to_header_edge' routine, which perform the peeling. This routine as far as I understand perform peel `n_unroll' copies from original loop, resulting to (n_unroll+1) overall copies (including original loop). I think of 2 solutions: - Reduce peel number by 1 - Improve remove_exits_and_undefined_stmts (), which correctly insert `gcc_unreachable' for `false' part of the if-stmt on 5-th iteration. It obviously don't warns, when limit is reduced: ./build-x86_64-linux/gcc/xgcc -B./build-x86_64-linux/gcc -O3 -Wall -msse3 -c -m32 x1.c --param max-completely-peel-times=3