This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [patch] Fix bug in cleaning parameters after function call


Josef Zlomek wrote:
when compiling attached testcase on i686 I noticed that the stack adjustment
in the block containing the last call to foo2 is different when
reached from different edges.

I had to use -mtune=pentium, we don't use stack push/pop for i686.


I think the analysis here is incomplete.

This code originally came from a patch by Jan.
http://gcc.gnu.org/ml/gcc-patches/2000-02/msg00747.html
The reasoning here isn't hard to figure out. If we know that we need a stack adjust anyways, then try to combine it with a pending stack adjust, thus possibly saving an instruction.


However, your patch makes us emit the pending stack adjust always, causing us to emit an extra instruction in some cases. This is undesirable.

The real problem here is a little more complex. Note that in your testcase without your patch at the second foo2 call, there is 16 bytes pushed on the stack that is never popped. This is a result of the fact that we defer stack pops as long as we can. If we defer them across a no return call, then there is no place to put them, so we live with the fact that no return calls can waste stack space.

The other part of this is noting that the new expanded cross jumping code can optimize two calls to the same no return function if they have the common code sequences before them. So one no return call gets converted to a branch to the other. However, given the fact that no return calls can have wasted stack space, and that different calls can have different amounts of wasted stack space, this now gives us the situation where a branch source and branch target can have different stack sizes. This is the problem that you are reporting as a bug.

I see 3 things we can do about this
1) We can live with the fact that branches to no return calls generated by cross jumping can have different stack sizes on the source and dest blocks.
2) We can disable cross jumping of no return calls.
3) We can disable pending stack adjust across no return calls.


If we do need a fix, and it does seem a bit risky to accept the current situation, then 3 is perhaps the best fix.

In order to implement 3, we need expand_calls to check ECF_NORETURN and if true, force out all pending stack adjusts, and then call NO_DEFER_POP. This would probably have to be done somewhere early in the routine.

Note that we partly get 2 if Jan's patch to remove cross jumping from -O (and maybe also -O2?) gets approved. However, we would still have the problem with -Os, so it would still need to be dealt with.
--
Jim Wilson, GNU Tools Support, http://www.SpecifixInc.com



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]