http://gcc.gnu.org/bugzilla/show_bug.cgi?id=19831

--- Comment #15 from Marc Glisse <glisse at gcc dot gnu.org> ---
See the discussion that starts at:
http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20130923/188747.html

(it continues in the following weeks) for optimization 2 of comment #14 in
clang. The key idea is that if, in the function where malloc is called, we can
check that on all paths (including EH) to the exit of the function free is
called on the return value of malloc, then we can replace malloc and all the
corresponding free with a stack allocation (whether we want to, depending on
the size, is a different issue). Of course there are some details like: if we
test whether malloc returned 0, that's one branch where we don't need free,
etc.

Also, the optimization can make a crash happen much earlier:
p=malloc(n);fun(p);free(p);
where fun calls free, would normally fail in the second free (double-free) and
will instead fail in fun (free of a pointer to the stack). I think that's fine,
but people may be surprised if there are a lot of side-effects (I/O for
instance) between the 2 free.

The hardest part here is deciding whether we always reach a free (this is how
we prove that there is no hidden call to realloc/free). There could be an
infinite loop in between. Any function we call might itself have an infinite
loop or call exit. And worst of all, there might be a call to longjmp. That
seems to make it impossible to perform the optimization when there is a
function call, in all but the most contrived cases (a call to setjmp between
malloc and the function call, or in C++ if the EH landing pad for the call
contains a non-inlined call to a non-trivial destructor).

So to make this possible, the first thing to do seems to forbid longjmp:
-fno-longjmp.

But even then it is still hard to know if regular functions always return
(infinite loops, exit). There are *LOOPING_CONST_OR_PURE* flags in gcc (and a
hardcoded list of builtins in call_may_noreturn_p), we could generalize them to
a may_not_return / always_returns flag (and associated attribute), that gcc
could recursively infer on many functions (a similar no_longjmp flag could also
be added to avoid the need for -fno-longjmp). I think this is the most
promising direction.

Assuming that we never do the things that would break the optimization (call
realloc or free in a function that won't return) seems too complicated to
explain properly, so I wouldn't even propose a -fI-promise-it-is-ok.

Reply via email to