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

            Bug ID: 126566
           Summary: [16/17 Regression] ICE in vec.h in phiopt
           Product: gcc
           Version: 17.0
            Status: UNCONFIRMED
          Keywords: ice-on-valid-code
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: ktkachov at gcc dot gnu.org
  Target Milestone: ---

/* ICE / out-of-bounds read.  gcc/tree-ssa-phiopt.cc:2444-2449,
   spaceship_replacement.

         cond3_bb = single_pred (cond2_bb);
         if (EDGE_COUNT (cond2_bb->succs) != 2)  <- should be cond3_bb
           return false;
         if (EDGE_SUCC (cond3_bb, 0)->dest == cond2_bb)
           {
             if (EDGE_SUCC (cond3_bb, 1)->dest != phi_bb)

   cond2_bb was already proved to have 2 successors at line 2316, so the
   guard is a no-op and cond3_bb is never constrained.  Here cond3_bb is the
   block holding "gp = &&lab;", which has a single successor, so
   EDGE_SUCC (cond3_bb, 1) reads one past the end of the edge vector.
   vec::operator[] only has a gcc_checking_assert, so a checking compiler
   ICEs and a release compiler uses an uninitialised edge pointer.

   The forced label keeps cond3_bb from being merged into cond2_bb; the
   "if (k)" arm supplies the fourth predecessor of phi_bb that selects the
   4-predecessor path.

        gcc -O1 / -O2 / -O3 / -Os
          internal compiler error: in operator[], at vec.h:911
          during GIMPLE pass: phiopt, from spaceship_replacement
        gcc -O2 -fno-ssa-phiopt    compiles clean  */

void *gp;

__attribute__((noipa)) int
f (int x, int y, int k)
{
  int c;
  if (k) { c = 0; goto out; }
  gp = &&lab;
lab:
  if (x < y) c = -1;
  else if (x > y) c = 1;
  else c = -128;
out:
  return c > 0;
}

int
main (void)
{
  if (f (1, 2, 0) != 0) __builtin_abort ();
  if (f (2, 1, 0) != 1) __builtin_abort ();
  return 0;
}

Reply via email to