[PATCH] A new HeapToStack allocation promotion pass

Duncan Sands duncan.sands at gmail.com
Fri Oct 4 10:06:16 PDT 2013


Hi Hal,

>> a function can never return without having the no-return attribute.
>
> In practice, agreed. no-return is a hint (for optimizations and also for removing useless frontend warnings). But what assumptions do we get to make about code reachability? A key question seems to be this: When DT->isReachableFromEntry returns true, do I need to go outside of the standard for it to be wrong, and if not, in what cases (maybe setjmp/longjmp)?

if the called function bar is no-return then you definitely can't do the
transform, because the correctness of the transform relies on the free that
follows the call to bar being executed (because that tells you that it wasn't
freed in the call to bar already).  I think that's clear.  The question is: if
the function is not marked no-return is the transform OK?

>
>>   For example:
>>
>>     void bar(int *x) {
>>          free(x);
>>          .. infinite loop ..
>>      }
>>
>> This comes up in PR965 too.
>>
>> Summary: no-return attribute => does not return.  The reverse
>> implication is
>> false.
>
> But we get to assume that all loops terminate, no?

Apparently not, this is PR965.  Also, there is no telling whether or not bar
calls "exit" or something like that.  If bar is defined in the same translation
unit, and calls "exit" in an obvious way, and the appropriate transform passes
have been run, then bar will have been marked no-return.  But what if bar is in
another translation unit, or calls some other function quz in another
translation unit that calls free then exit?  I think this transform can only be
done correctly if you can *prove* that bar returns, which probably means adding
an LLVM attribute for that ('does-return') and a pass that tries to deduce the
'does-return' attribute.  You can then do the transform if bar is does-return,
but otherwise you can't.  In PR965 I think 'does-return' was called 'finite' or
something like that.  The big problem is that most likely hardly any functions
will end up being marked 'does-return' because it is too hard to deduce...

Also, another issue is that this "back propagates" undefined behaviour in a big
way.  I mean, suppose bar does return, but also frees x.  Then before doing the
transform bar would execute properly, and only afterwards would the program
crash.  After the transform it will crash in bar, maybe much much earlier than
before.  While this is OK per the standard, it is still pretty obnoxious.

This seems equivalent to assuming that all functions return (unless they call 
exit, etc.). And you'd need to be quite deliberate here in order for the 
transformation to do the wrong thing (explicitly writing dead code that was 
known to be invalid except that it is unreachable). Does the standard say 
anything about that?

I didn't understand you here, got an example?  Forgetting about loops, how do
you tell if a function calls exit (or calls a function that calls a function
that calls exit)?

Ciao, Duncan.



More information about the llvm-commits mailing list