[PATCH] A new HeapToStack allocation promotion pass

Nick Lewycky nicholas at mxc.ca
Fri Oct 4 11:57:07 PDT 2013


Hal Finkel wrote:
> ----- Original Message -----
>> (I am not on the list)
>>
>>> This adds a new optimization pass that can 'promote' malloc'd
>>> memory to
>>> stack-allocated memory when the lifetime of the allocation can be
>>> determined to be bounded by the execution of the function.
>>>
>>> To be specific, consider the following three cases:
>>>
>>> void bar(int *x);
>>>
>>> void foo1() {
>>>    int *x = malloc(16);
>>>    bar(x);
>>>    free(x);
>>> }
>>>
>>> In this case the malloc can be replaced by an alloca, and the free
>>> removed. Note that this is true even though the pointer 'x' is
>>> definitely
>>> captured (and may be recorded in global storage, etc.).
>>
>> Hello,
>>
>> this seems to rely on the fact that 'bar' returns normally, and thus
>> that
>> whenever malloc is executed, free will be as well. However, bar could
>> never return, or return abnormally by throwing an exception which
>> will
>> skip the call to free.
>>
>> void bar(int *x) {
>>     free(x);
>>     throw 42;
>> }
>>
>> will result in calling free on the stack. Now if there was a
>> destructor
>> calling free in foo1... Do you actually also consider exceptions when
>> you
>> test that all paths from malloc to the exits contain a call to free?
>> That
>> would only leave noreturn functions.
>
> Marc,
>
> Thanks!
>
> My understanding is that the extra control-flow from exception handling should be accounted for by the basic-block successor/predecessor information (because calling a function that might throw uses invoke, and then you see both the regular predecessor and the cleanup block as predecessors).

No, that's only true if the caller handles the extra control-flow. If 
you call (not invoke) a function, and the callee throws, then the 
exception propagates out of the caller, going up the stack until it hits 
the function that did use invoke.

Better is to check "nounwind". However, that is also not sufficient, 
because in llvm nounwind functions may call longjmp.

  I'll double-check that's correct. Also, you're right, I should check 
the function's does-not-return attribute also.

A function which is marked 'noreturn' is guaranteed to never return. A 
function not marked 'noreturn' may also not return -- it may terminate 
the program, longjmp, throw an exception, or loop infinitely.

Nick



More information about the llvm-commits mailing list