https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84084

            Bug ID: 84084
           Summary: -O2 Early VPR pass wrongly removes "ret" exit basic
                    block causing infinite loop/segfaults
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: romain.geissler at amadeus dot com
  Target Milestone: ---

Hi,

It looks like there is a regression in the Early VRP pass with -O2 that affects
at the very least gcc 7 and 8, but we could find strange behaviour up to gcc
4.8.

cat evrp-bug.c
#include <stdio.h>
//#include <iostream>

int main()
{
  int arr[2] = {1, 2};

  for (int i = 0, val; (val = arr[i]), i < 2; ++i)
  {
      printf("%i\n", val); // With this line, works with gcc <= 6, fails with
gcc >= 7
      //std::cout << val << std::endl; //With line line, works with gcc <= 4.7,
fails with gcc >= 4.8.
  }
}

First the C frontend and the C++ frontend disagrees. The C frontend correctly
compiles this, and even correctly find that "val = arr[i]" is UB when "i == 2"
(when -Wall is enabled)

https://godbolt.org/g/SG9SyU

<source>: In function 'main':
<source>:8:34: warning: array subscript 2 is above array bounds of 'int[2]'
[-Warray-bounds]
   for (int i = 0, val; (val = arr[i]), i < 2; ++i)
                               ~~~^~~
Compiler returned: 0

Execution correctly prints:
1
2

Now with the C++ frontend, things go wrong. First the UB behaviour is not
printed. The executation fails with an infinite loop and eventually a segfault

https://godbolt.org/g/9xnRX7

The reason for that is that the function epilog:
  xor eax, eax
  add rsp, 8
  ret

is missing when compiled with the C++ frontend. In our case, since "_start" is
placed by the linker just after "main", then each calls to "main" eventually
continue into "_start", which calls main again, each time increasing the stack
usage, and eventually segfaulting because of stack going out of bound.

Please note that depending on whether the inside loop is inlinable or not
(printf vs std::cout) then the regression either starts with gcc 4.8 or with
gcc 6.

This issue seems to be a wrong behavior from the early vrp pass. Note that
compiling with "-fno-tree-vrp" correctly works around the issue:
https://godbolt.org/g/EjvxQd

I am providing tree dumps generated with g++ (GCC) 7.2.1 20171022, gcc trunk
output might be slightly different.

Pass just before evrp:
cat evrp-bug.c.037t.fre1
;; Function int main() (main, funcdef_no=12, decl_uid=2833, cgraph_uid=12,
symbol_order=12)

int main() ()
{
  int val;
  int i;
  int arr[2];

  <bb 2> [0.00%]:
  arr[0] = 1;
  arr[1] = 2;
  # DEBUG i => 0

  <bb 3> [0.00%]:
  # i_1 = PHI <0(2), i_12(5)>
  # DEBUG i => i_1 
  val_7 = arr[i_1];
  # DEBUG val => val_7
  if (i_1 <= 1)
    goto <bb 4>; [0.00%]
  else
    goto <bb 6>; [0.00%]

  <bb 4> [0.00%]:
  printf ("%i\n", val_7);

  <bb 5> [0.00%]:
  i_12 = i_1 + 1;
  # DEBUG i => i_12
  goto <bb 3>; [0.00%]

  <bb 6> [0.00%]:
  arr ={v} {CLOBBER};
  return 0;

<L4> [0.00%]:
  arr ={v} {CLOBBER};
  resx 1

}

cat evrp-bug.c.038t.evrp
Then the evrp pass, which wrongly removes the exit basic block 6:
;; Function int main() (main, funcdef_no=12, decl_uid=2833, cgraph_uid=12,
symbol_order=12)

;; 2 loops found
;;
;; Loop 0
;;  header 0, latch 1
;;  depth 0, outer -1
;;  nodes: 0 1 2 3 4 5 6 7
;;
;; Loop 1
;;  header 3, latch 5
;;  depth 1, outer 0
;;  nodes: 3 5 4
;; 2 succs { 3 }
;; 3 succs { 4 6 }
;; 4 succs { 7 5 }
;; 5 succs { 3 }
;; 6 succs { 1 }
;; 7 succs { }

Value ranges after Early VRP:

i_1: [0, 1]
val_7: VARYING
i_12: [1, 2]


Removing basic block 6
Merging blocks 3 and 4
int main() ()
{
  int val;
  int i;
  int arr[2];

  <bb 2> [0.00%]:
  arr[0] = 1;
  arr[1] = 2;
  # DEBUG i => 0

  <bb 3> [0.00%]:
  # i_1 = PHI <0(2), i_12(4)>
  # DEBUG i => i_1
  val_7 = arr[i_1];
  # DEBUG val => val_7
  printf ("%i\n", val_7);

  <bb 4> [0.00%]:
  i_12 = i_1 + 1;
  # DEBUG i => i_12
  goto <bb 3>; [0.00%]

<L4> [0.00%]:
  arr ={v} {CLOBBER};
  resx 1

}

Can you please have a look at this regression ?

Chees,
Romain

Reply via email to