[PATCH] A new HeapToStack allocation promotion pass

Nick Lewycky nicholas at mxc.ca
Sat Oct 5 01:44:15 PDT 2013

Hal Finkel wrote:
> ----- Original Message -----
>> 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.
> It looks like I could use your 'halting' attribute. What's the status on that?

I'm not working on it.

There's an infrastructure problem in LLVM that makes this hard. You want 
to use the function analyses and the call graph analysis for SCCs. 
Logically this fits into a CGSCC pass but you can't put it there because 
those can't depend on function passes. Your options are to either make 
the whole thing a module pass (bad, doesn't get interwoven as part of 
the inliner run) or to have the CGSCC pass depend on a really hokey 
module pass which uses the function pass.

This is the same problem Chandler is fixing with his PassManager 
rewrite, with the goal of letting the inliner use the function passes.

Also, the "is there a loop local to this function" detection in my patch 
is wrong, it was detecting presence of natural loops, not presence of 


More information about the llvm-commits mailing list