[PATCH] A new HeapToStack allocation promotion pass
Nick Lewycky
nicholas at mxc.ca
Wed Oct 9 03:03:18 PDT 2013
Daniel Berlin wrote:
>
>
>
> On Sun, Oct 6, 2013 at 11:20 PM, Nick Lewycky <nicholas at mxc.ca
> <mailto:nicholas at mxc.ca>> wrote:
>
> Hal Finkel wrote:
>
>
> ----- Nick Lewycky<nicholas at mxc.ca <mailto:nicholas at mxc.ca>> wrote:
>
> 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
> backedges.
>
>
> Do you know how your loop detection could be fixed? Would it be
> sufficient to check that all backedges in the function had an
> associated Loop, and if any did not, return a conservative answer?
>
>
> Find backedges (J-edges) by looking at the CFG and checking which
> successors aren't strictly dominated according to the domtree. For
> each backedge, look up its Loop. If it doesn't have one, bail. (Note
> that the blocks may both be members of a loop, but that may be an
> outer loop incidentally containing both. You need to check that it's
> actually backedge of this loop, which is true when the branch
> destination is the loop header block.) Query SCEV for the loop trip
> count, if it doesn't know, bail.
>
> (Dan Berlin's answer on the thread is also correct, but forgot to
> address the issue of whether the found loops are finite. For any
> irreducible loop, there's no facility in LLVM that determines
> whether it will terminate.)
>
>
> Right, so as Hal pointed out to me privately, is it even worth doing
> anything other than bailing in the case of non-natural loops?
In the event of unnatural loops, drop the function and run like hell.
Nick
More information about the llvm-commits
mailing list