https://gcc.gnu.org/bugzilla/show_bug.cgi?id=19831
--- Comment #20 from Richard Biener <rguenth at gcc dot gnu.org> --- The original cases are all fixed but what remains is us failing to elide void f () { void *p = __builtin_malloc (1); if (!p) __builtin_abort (); __builtin_free (p); } if that's even desirable. Note that we mark the abort() call as necessary since it has side-effects which is contrary to this expectation. If you think of, say, extern int alloc_fails; extern int alloc_success; void f () { void *p = __builtin_malloc (1); if (!p) alloc_fails++; else alloc_success++; __builtin_free (p); } then the question is really whether we may assume that malloc does not return NULL. We can then avoid marking 'p' necessary on NULL checks on malloc returned pointers and upon DCEing the malloc/free pair replace the def of 'p' with a non-zero constant. Related would be to play similar things with realloc - replace void *p = realloc (q, n); free (p); with free (q); and void *p = realloc (q, n); if (p == q) not_copied++; free (p); with void *p = q; if (p == q) not_copied++; free(q); so here we'd not only have to deal with != NULL but other pointer equality checks.