https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91859
Bug ID: 91859
Summary: Optnization -O2 removes valid and necessary code
Product: gcc
Version: 9.2.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: mingodad at gmail dot com
Target Milestone: ---
When compiling the sample bellow with g++9 (9.1 and 9.2) with optmization -O2
the generated code eliminates a valid and necessary code:
=====
#include <stdio.h>
#include <stdlib.h>
struct Expression {
Expression *next;
Expression *right;
void *operator new(size_t);
void operator delete(void *);
};
void * Expression::operator new(size_t sz)
{
return malloc(sz);
}
void Expression::operator delete(void *p)
{
Expression *e = (Expression*)p;
printf("%p : %p\n", e, e->next);
while(e->next)
{
Expression *f = e->next;
//pretend doing something
printf("delete is doing something with %p\n", e->next);
e = f;
}
free(p);
}
int main()
{
Expression *etmp, *ebase;
etmp = ebase = new Expression();
for(int i = 0; i < 10; ++i)
{
etmp->next = new Expression();
etmp->right = new Expression();
etmp->right->next = NULL;
etmp->next->right = new Expression();
etmp->next->right->next = NULL;
etmp->next->right->right = NULL;
etmp = etmp->next;
}
etmp->next = NULL;
Expression *e, *e0, *e1, *efirst, **ep;
if ((efirst = ebase)) {
ep = &e0;
while((e = efirst)) {
*ep = e1 = e->right;
efirst = e->next;
e->next = 0; //!! with -O2 this line is eliminated
delete e;
while((e = e1->next))
e1 = e;
ep = &e1->next;
}
}
return 0;
}
=====
To build:
=====
g++-8 -g -o gcc8-bug-no-optmization gcc9-bug.cpp
g++-8 -O2 -g -o gcc8-bug-O2 gcc9-bug.cpp
g++-9 -g -o gcc9-bug-no-optmization gcc9-bug.cpp
g++-9 -O2 -g -o gcc9-bug-O2 gcc9-bug.cpp
=====
Output:
=====
./gcc8-bug-no-optmization
0x560315ecc260 : (nil)
0x560315ecc280 : (nil)
0x560315ecc2e0 : (nil)
./gcc8-bug-O2
0x5562bab29260 : (nil)
0x5562bab29280 : (nil)
0x5562bab292e0 : (nil)
./gcc9-bug-no-optmization
0x557550cd0260 : (nil)
0x557550cd0280 : (nil)
0x557550cd02e0 : (nil)
./gcc9-bug-O2
0x5617642e3260 : 0x5617642e3280
delete is doing something with 0x5617642e3280
delete is doing something with 0x5617642e32e0
0x5617642e3280 : 0x5617642e32e0
delete is doing something with 0x5617642e32e0
0x5617642e32e0 : (nil)
=====
The sample code is similar to a production code that do some work inside the
custom delete if the "next" pointer is not NULL.
g++-8 and older works as we expect so far only gcc9 (9.1 and 9.2) changed the
generated code breaking our build.