[Bug tree-optimization/126531] New: Wrong code with ranger and exception handling

"ktkachov at gcc dot gnu.org via Gcc-bugs" <[email protected]>
Newsgroups gmane.comp.gcc.bugs
Message-ID <[email protected]/bugzilla/>
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126531

            Bug ID: 126531
           Summary: Wrong code with ranger and exception handling
           Product: gcc
           Version: 17.0
            Status: UNCONFIRMED
          Keywords: wrong-code
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: ktkachov at gcc dot gnu.org
  Target Milestone: ---

/* ranger_cache::range_from_dom (gcc/gimple-range-cache.cc:1784) applies an
   inferred range taken from a dominator block to a query block that is reached
   from that dominator through an EH edge.  The inference is accumulated at
line
   1820 and applied at line 1908 under
        if (!has_abnormal_call_or_eh_pred_edge_p (start_bb))
   which only inspects the predecessors of the query block.  The siblings guard
   the edge itself:
        ranger_cache::edge_range                gimple-range-cache.cc:1314
        gimple_ranger::range_on_edge            gimple-range.cc:281
            if ((e->flags & (EDGE_EH | EDGE_ABNORMAL)) == 0)

   g++, aborts at -O1 -O2 -O3 -Os.  Correct at -O0 and with
   -fno-tree-vrp -fno-thread-jumps -fno-tree-dominator-opts.  */

/* More than 16 bytes, so S is returned in memory.  *p becomes the return slot
   of the call and GIMPLE keeps a single statement "*p_7(D) = h (k_8(D));",
   a call that can throw whose store operand infers p != 0.  */

struct S { int a[8]; };

__attribute__((noipa)) S
h (int k)
{
  if (k)
    throw 1;                    /* Thrown before anything is stored.  */
  S s = {};
  s.a[0] = 5;
  return s;
}

__attribute__((noipa)) int
f (S *p, int k)
{
  int r = 0;
  try
    {
      *p = h (k);               /* Infers p != 0, but only if it completes.  */
      r = 1;
    }
  catch (...)
    {
      if (p == 0)               /* Must not fold: the store never ran.  */
        r = 12;
      else
        r = 2;
    }
  return r;
}

S obj;

int
main (void)
{
  if (f (&obj, 0) != 1)         /* Normal path, p is &obj.  */
    __builtin_abort ();
  if (f (0, 1) != 12)           /* h throws, no store, p is null.  */
    __builtin_abort ();
  return 0;
}

aborts on aarch64 as described in the comment and passes at -O0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.