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

            Bug ID: 85803
           Summary: [6/7/8/9 Regression] DSE removes live global store
           Product: gcc
           Version: 8.1.0
            Status: UNCONFIRMED
          Keywords: wrong-code
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: rguenth at gcc dot gnu.org
  Target Milestone: ---

Due to an algorithmic defect GIMPLE DSE removes the global store to *p in
the if (i == 42) condition.  This is because it relies on the presence of
virtual operands on _all_ use sites, including ones outside of the function.
One might think the

          if (ref_may_alias_global_p (ref))
            return DSE_STORE_LIVE;

protects such cases but that only works if no alternate definition site is
found.  That is, for this bug to trigger we need to have sth like

  if (..)
    exit-of-function-w/o-VUSE;
  # _2 = VDEF <_1>

GIMPLE_RESX is amongst the opcodes that (can?) exit the function but have
no associated virtual operands.

Testcase, fails at -O2 with GCC 5+ (didn't verify if with 4.9.4 the issue
is just latent for whatever reason):

#include <setjmp.h>
#include <signal.h>
#include <stdlib.h>

extern void maybethrow(void*);
int cond, *globp;
static inline void __attribute__((always_inline)) inlinethrow(void *p)
{
  *globp = 43;
}
int __attribute__((noinline,noclone)) foo (int *p, int i)
{
  if (i) {
      if (i == 42) {
          *p = 42;
          int local __attribute__((cleanup(inlinethrow)));
      }
      *p = 0;
  }
  *p = 1;
  return i + 1;
}

jmp_buf buf;
static void segv_handler(int seg)
{
  longjmp (buf, 1);
}
int x;
int main()
{
  struct sigaction sa, origsa;
  sa.sa_handler = segv_handler;
  sa.sa_flags = 0;
  sigemptyset(&sa.sa_mask);
  sigaction(SIGSEGV, &sa, NULL);

  if (!setjmp (buf))
    foo (&x, 42);
  if (x != 42)
    abort ();
  return 0;
}

I beleive the proper course of action is to make all function exiting
GIMPLE ops have a VUSE (and adjust ref_maybe_used_by_stmt_p accordingly
as it was done for GIMPLE_RETURN).

If you remove the above check in DSE (which should be redundant) you'll
see some more cleanup and EH tests fail.

Reply via email to