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

Reply via email to