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: avoid unnecessary register saves for setjmp


On Sat, Nov 22, 2003 at 02:36:56PM +0000, Richard Earnshaw wrote:
> > On Fri, 2003-11-21 at 19:08, Daniel Jacobowitz wrote:
> > > Here's the difficulty: changing the size of jmp_buf.
> > 
> > That is a good point.  Still, we shouldn't penalize targets that have
> > defined setjmp correctly.  So I suggest using NON_SAVING_SETJMP for
> > this.  This will do what you want if you define it for your target. 
> > I'll go ahead and fix NON_SAVING_SETJMP to make it usable.

If we do do this, is it relatively easy to make it a runtime switch
instead?  This would depend on compiler options.

> > > Sure - but that assumes that all unused call-saved registers are
> > > restored by the setjmp.  So then it is required to save registers to
> > > get reasonable behavior.
> > 
> > You are confusing two different issues here.  setjmp is not required to
> > restore call-used registers.  Thus any value stored in a register in
> > this function may not be restored when longjmp is called.  This is why
> > the C language standard says that local automatic non-volatile variables
> > may not be restored by longjmp.  However, setjmp is required to restore
> > the original context, and that means call-saved registers must be
> > restored.  A setjmp call is not allowed to clobber locals in the parent
> > function, which is what would happen if call-saved registers were not
> > restored.

But, as in many things, the division of labor between the compiler's
emitted call to setjmp and the setjmp implementation is weakly
specified.

       which is an array type suitable for holding the  information
       needed to restore a calling environment.  The environment of
       a  call  to  the  setjmp  macro  consists   of   information
       sufficient  for  a  call  to  the longjmp function to return
       execution to the correct block and invocation of that block,
       were  it  called recursively.  It does not include the state
       of the floating-point status flags, of open files, or of any
       other component of the abstract machine.

A setjmp which saves just a minimal number of registers in the jmp_buf
and runtime code which restores them from the stack if setjmp returns
non-zero, would satisfy the standard.  At least that's my reading; it
may well be wrong.

> In the EABI we've been developing for the ARM we've been very careful to 
> say that only the setjmp and longjmp functions can know the contents and 
> layout of a jmp_buf.  This allows a function to use co-processor registers 
> that are call saved and to be used in the middle of a call sequence 
> without upsetting any other conforming code.  Hence only the C library 
> needs to know the list of co-processors that are in use (and it is 
> entitled to enter into other private conspiracies to determine the 
> registers that need to be saved.  We've even designed the EH 
> implementation in a way that will allow this to work as well (the unwinder 
> will only try to execute instructions to access a particular co-processor 
> once it has found a description of that co-processor in the unwind list).

How do you intend to implement this in practice?  I'm not concerned
with the contents or layout of a jmp_buf; conforming programs can't get
at them.  But user programs declare jmp_buf, which implies that they
know its size.  And there's no way I can think of to dynamically
allocate additional space if the jmp_buf is insufficiently large.
Are you simply defining a very large jmp_buf for expansion?

This is the problem I encountered on both PowerPC and ARM.  I'm very
curious to hear any solutions to it.

> IMO gcc should not be trying to second guess the complete set of registers 
> that a setjmp/longjmp pair need to save and restore.  In otherwords we 
> should not be building in setjmp and longjmp (in any case, it's likely on 
> ARM that the library function will be more efficient, since it can use 
> load and store multiple instructions).

For new ABIs this is well and good.  For something like Altivec being
added to existing GNU/Linux systems, it's dramatically less good. 
Right now we either waste performance (before this patch) or violate
the Motorola specifications on which registers should be saved (after)
because the system library does not have room for Altivec in its
jmp_buf.

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer


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