https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86276
Richard Biener <rguenth at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Keywords| |alias, missed-optimization Status|UNCONFIRMED |NEW Last reconfirmed| |2018-06-22 CC| |rguenth at gcc dot gnu.org Ever confirmed|0 |1 --- Comment #1 from Richard Biener <rguenth at gcc dot gnu.org> --- <bb 2> [local count: 1073741825]: MEM[(struct _Vector_impl *)something_3(D)]._M_start = 0B; MEM[(struct _Vector_impl *)something_3(D)]._M_finish = 0B; MEM[(struct _Vector_impl *)something_3(D)]._M_end_of_storage = 0B; _26 = operator new (22); <bb 3> [local count: 354334802]: _23 = something_3(D)->D.15703._M_impl._M_start; if (_23 != 0B) Confirmed. So the reason we do not elide the NULL check is that GCC thinks that the call to operator new may clobber the return slot (well, generally clobber global memory). For malloc() we assume it cannot but IIRC operator new () may be overridden by the user and we could have (parts of) its implementation visible to GCC which means we do have to assume it reads/clobbers global memory. Note that we know that something_3(D) points to "local" memory but as you say we see the pointer is returned and thus since points-to analysis is flow-insensitive we have to assume it is already escaped at the call to operator new. I suppose we could handle returns specially but we have to beware of recursion here and cannot handle it specially for IPA points-to. So ... better points-to analysis to the rescue... (or somehow special-casing operator new similar to malloc)