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.

Reply via email to