Why doesn't GCC optimize out deletion of null pointers in C++?

Viewed 6936

Consider a simple program:

int main() {
  int* ptr = nullptr;
  delete ptr;
}

With GCC (7.2), there is a call instruction regarding to operator delete in the resulting program. With Clang and Intel compilers, there are no such instructions, the null pointer deletion is completely optimized out (-O2 in all cases). You can test here: https://godbolt.org/g/JmdoJi.

I wonder whether such an optimization can be somehow turned on with GCC? (My broader motivation stems from a problem of custom swap vs std::swap for movable types, where deletion of null pointers can represent a performance penalty in the second case; see https://stackoverflow.com/a/45689282/580083 for details.)

UPDATE

To clarify my motivation for the question: If I use just delete ptr; without if (ptr) guard in a move assignment operator and a destructor of some class, then std::swap with objects of that class yields 3 call instructions with GCC. This might be a considerable performance penalty, e.g., when sorting an array of such objects.

Moreover, I can write if (ptr) delete ptr; everywhere, but wonder, whether this cannot be a performance penalty as well, since delete expression needs to check ptr as well. But, here, I guess, compilers will generate a single check only.

Also, I really like the possibility to call delete without the guard and it was a surprise for me, that it could yield different (performance) outcomes.

UPDATE

I just did a simple benchmark, namely sorting objects, which invoke delete in their move assignment operator and destructor. The source is here: https://godbolt.org/g/7zGUvo

Running times of std::sort measured with GCC 7.1 and -O2 flag on Xeon E2680v3:

There is a bug in the linked code, it compares pointers, not pointed values. Corrected results are as follows:

  1. without if guard: 17.6 [s] 40.8 [s],
  2. with if guard: 10.6 [s] 31.5 [s],
  3. with if guard and custom swap: 10.4 [s] 31.3 [s].

These results were absolutely consistent across many runs with minimal deviation. The performance difference between first two cases is significant and I wouldn't say that this is some "exceedingly rare corner case" like code.

6 Answers
Related