This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug tree-optimization/85803] New: [6/7/8/9 Regression] DSE removes live global store
- From: "rguenth at gcc dot gnu.org" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Wed, 16 May 2018 10:06:14 +0000
- Subject: [Bug tree-optimization/85803] New: [6/7/8/9 Regression] DSE removes live global store
- Auto-submitted: auto-generated
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.