public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* avoid unnecessary register saves for setjmp
@ 2003-11-21  5:54 Jim Wilson
  2003-11-21 18:39 ` Daniel Jacobowitz
  2003-11-21 20:14 ` Geoff Keating
  0 siblings, 2 replies; 33+ messages in thread
From: Jim Wilson @ 2003-11-21  5:54 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1862 bytes --]

This is for PR c/13133.

Gcc saves and restores all call-saved registers around a call to
setjmp.  This is unnecessary, and is a performance regression from
gcc-3.0 and earlier.  This showed up on IA-64 as a libpthread
performance problem, as some critical paths in libpthread use setjmp,
and IA-64 has lots of registers that get saved and restored.  This has
also been reported as a problem for PowerPC with Altivec.  See PR 12817.

The code in question was originally added Feb 23, 1996 by Richard
Kenner.  He modified the builtin setjmp expander to emit a CONST_CALL_P
NOTE_INSN_SETJMP note, and he added code to reload to mark all call
saved registers as live when one of these notes was seen.

On Nov 1, 1997, Jeff Law deleted the code in the buildint setjmp
expander that was emitting the CONST_CALL_P NOTE_INSN_SETJMP note, but
the code in reload remained.  It now did nothing.  A little bit later,
the expander was modified to set current_function_has_nonlocal_label
which gives the same effect as the reload code, but in a way that flow
can understand.

On Aug 7, 2001, Jan Hubicka checked in a patch that removed
NOTE_INSN_SETJMP notes and replaced them with REG_SETJMP reg notes. 
When this change was made, the CONST_CALL_P test in the reload code was
lost, and now the code was enabled for every setjmp call, which was not
the intent of the code.

The proper fix here is to just delete the long obsolete reload code for
REG_SETJMP.

This was tested with a ia64-linux bootstrap and make check.  There were
no regressions.  This was also tested with the testcase in PR 13133.

I realize this is a bit risky, since running the testsuite does not
really test setjmp.  So I am interested in hearing about any problems
this might cause.

I have checked in the attached patch for this problem.
-- 
Jim Wilson, GNU Tools Support, http://www.SpecifixInc.com

[-- Attachment #2: patch.reload.setjmp --]
[-- Type: text/plain, Size: 1908 bytes --]

2003-11-20  James E Wilson  <wilson@specifixinc.com>

	PR c/13133
	* reload1.c (reload): Delete special handling for setjmp.

Index: reload1.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/reload1.c,v
retrieving revision 1.408
diff -p -r1.408 reload1.c
*** reload1.c	27 Oct 2003 10:52:46 -0000	1.408
--- reload1.c	16 Nov 2003 07:45:13 -0000
*************** reload (rtx first, int global)
*** 698,706 ****
    /* Look for REG_EQUIV notes; record what each pseudo is equivalent to.
       Also find all paradoxical subregs and find largest such for each pseudo.
       On machines with small register classes, record hard registers that
!      are used for user variables.  These can never be used for spills.
!      Also look for a "constant" REG_SETJMP.  This means that all
!      caller-saved registers must be marked live.  */
  
    num_eliminable_invariants = 0;
    for (insn = first; insn; insn = NEXT_INSN (insn))
--- 698,704 ----
    /* Look for REG_EQUIV notes; record what each pseudo is equivalent to.
       Also find all paradoxical subregs and find largest such for each pseudo.
       On machines with small register classes, record hard registers that
!      are used for user variables.  These can never be used for spills.  */
  
    num_eliminable_invariants = 0;
    for (insn = first; insn; insn = NEXT_INSN (insn))
*************** reload (rtx first, int global)
*** 713,724 ****
        if (INSN_P (insn) && GET_CODE (PATTERN (insn)) == USE
  	  && GET_MODE (insn) != VOIDmode)
  	PUT_MODE (insn, VOIDmode);
- 
-       if (GET_CODE (insn) == CALL_INSN
- 	  && find_reg_note (insn, REG_SETJMP, NULL))
- 	for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- 	  if (! call_used_regs[i])
- 	    regs_ever_live[i] = 1;
  
        if (set != 0 && GET_CODE (SET_DEST (set)) == REG)
  	{
--- 711,716 ----

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: avoid unnecessary register saves for setjmp
  2003-11-21  5:54 avoid unnecessary register saves for setjmp Jim Wilson
@ 2003-11-21 18:39 ` Daniel Jacobowitz
  2003-11-22  0:22   ` Jim Wilson
  2003-11-21 20:14 ` Geoff Keating
  1 sibling, 1 reply; 33+ messages in thread
From: Daniel Jacobowitz @ 2003-11-21 18:39 UTC (permalink / raw)
  To: Jim Wilson; +Cc: gcc-patches

On Thu, Nov 20, 2003 at 09:46:54PM -0800, Jim Wilson wrote:
> This is for PR c/13133.
> 
> Gcc saves and restores all call-saved registers around a call to
> setjmp.  This is unnecessary, and is a performance regression from
> gcc-3.0 and earlier.  This showed up on IA-64 as a libpthread
> performance problem, as some critical paths in libpthread use setjmp,
> and IA-64 has lots of registers that get saved and restored.  This has
> also been reported as a problem for PowerPC with Altivec.  See PR 12817.
> 
> The code in question was originally added Feb 23, 1996 by Richard
> Kenner.  He modified the builtin setjmp expander to emit a CONST_CALL_P
> NOTE_INSN_SETJMP note, and he added code to reload to mark all call
> saved registers as live when one of these notes was seen.
> 
> On Nov 1, 1997, Jeff Law deleted the code in the buildint setjmp
> expander that was emitting the CONST_CALL_P NOTE_INSN_SETJMP note, but
> the code in reload remained.  It now did nothing.  A little bit later,
> the expander was modified to set current_function_has_nonlocal_label
> which gives the same effect as the reload code, but in a way that flow
> can understand.
> 
> On Aug 7, 2001, Jan Hubicka checked in a patch that removed
> NOTE_INSN_SETJMP notes and replaced them with REG_SETJMP reg notes. 
> When this change was made, the CONST_CALL_P test in the reload code was
> lost, and now the code was enabled for every setjmp call, which was not
> the intent of the code.
> 
> The proper fix here is to just delete the long obsolete reload code for
> REG_SETJMP.
> 
> This was tested with a ia64-linux bootstrap and make check.  There were
> no regressions.  This was also tested with the testcase in PR 13133.
> 
> I realize this is a bit risky, since running the testsuite does not
> really test setjmp.  So I am interested in hearing about any problems
> this might cause.
> 
> I have checked in the attached patch for this problem.

Well, here's a problem it will cause.

I recently spent some time investigating this same code.  I was working
on an ARM target with the iWMMXt extension set, which includes a number
of additional registers.  The existing setjmp implementation on that
target did not save them, but things worked anyway; I dug, and this was
how.

Speaking of Altivec, at least the GNU/Linux glibc setjmp implementation
doesn't save Altivec registers either.  I posted a patch for this about
three years ago and it was never incorporated.  So we may see problems
reported from that side.

I discussed this on IRC with a few people; I don't remember who all of
them were, but definitely including H-P.  My conclusion from the
discussion was that the setjmp standard library function is _not_
mandated by C99 to save all registers.  I do not know of any psABI
documents which specify the saved registers either.  So I am a little
uncomfortable with your patch.


Er... actually, upon second inspection, the code I was referring to was
regs_live_at_setjmp in flow.c.  I'm not sure whether the code you are
removing from reload1.c will change the behavior I describe, after
all.

> 2003-11-20  James E Wilson  <wilson@specifixinc.com>
> 
> 	PR c/13133
> 	* reload1.c (reload): Delete special handling for setjmp.

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: avoid unnecessary register saves for setjmp
  2003-11-21  5:54 avoid unnecessary register saves for setjmp Jim Wilson
  2003-11-21 18:39 ` Daniel Jacobowitz
@ 2003-11-21 20:14 ` Geoff Keating
  2003-11-22  0:20   ` Jim Wilson
  2003-11-30  9:23   ` Jim Wilson
  1 sibling, 2 replies; 33+ messages in thread
From: Geoff Keating @ 2003-11-21 20:14 UTC (permalink / raw)
  To: Jim Wilson; +Cc: gcc-patches, Daniel Jacobowitz

Jim Wilson <wilson@specifixinc.com> writes:

> This is for PR c/13133.
> 
> Gcc saves and restores all call-saved registers around a call to
> setjmp.  This is unnecessary, and is a performance regression from
> gcc-3.0 and earlier.  This showed up on IA-64 as a libpthread
> performance problem, as some critical paths in libpthread use setjmp,
> and IA-64 has lots of registers that get saved and restored.  This has
> also been reported as a problem for PowerPC with Altivec.  See PR 12817.
> 
> The code in question was originally added Feb 23, 1996 by Richard
> Kenner.  He modified the builtin setjmp expander to emit a CONST_CALL_P
> NOTE_INSN_SETJMP note, and he added code to reload to mark all call
> saved registers as live when one of these notes was seen.
> 
> On Nov 1, 1997, Jeff Law deleted the code in the buildint setjmp
> expander that was emitting the CONST_CALL_P NOTE_INSN_SETJMP note, but
> the code in reload remained.  It now did nothing.  A little bit later,
> the expander was modified to set current_function_has_nonlocal_label
> which gives the same effect as the reload code, but in a way that flow
> can understand.
> 
> On Aug 7, 2001, Jan Hubicka checked in a patch that removed
> NOTE_INSN_SETJMP notes and replaced them with REG_SETJMP reg notes. 
> When this change was made, the CONST_CALL_P test in the reload code was
> lost, and now the code was enabled for every setjmp call, which was not
> the intent of the code.
> 
> The proper fix here is to just delete the long obsolete reload code for
> REG_SETJMP.
> 
> This was tested with a ia64-linux bootstrap and make check.  There were
> no regressions.  This was also tested with the testcase in PR 13133.
> 
> I realize this is a bit risky, since running the testsuite does not
> really test setjmp.  So I am interested in hearing about any problems
> this might cause.
> 
> I have checked in the attached patch for this problem.

I've looked at this some time in the past (I don't remember the exact
circumstances).  I came to the same conclusion as you, except in the
case when NON_SAVING_SETJMP is defined, when we do need to save any
call-saved registers.

This should also fix Daniel Jacobowitz's problems: targets can define
that macro to be 1 if the library's setjmp isn't complete.

-- 
- Geoffrey Keating <geoffk@geoffk.org>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: avoid unnecessary register saves for setjmp
  2003-11-21 20:14 ` Geoff Keating
@ 2003-11-22  0:20   ` Jim Wilson
  2003-11-30  9:23   ` Jim Wilson
  1 sibling, 0 replies; 33+ messages in thread
From: Jim Wilson @ 2003-11-22  0:20 UTC (permalink / raw)
  To: Geoff Keating; +Cc: gcc-patches, Daniel Jacobowitz

On Fri, 2003-11-21 at 12:11, Geoff Keating wrote:
> I've looked at this some time in the past (I don't remember the exact
> circumstances).  I came to the same conclusion as you, except in the
> case when NON_SAVING_SETJMP is defined, when we do need to save any
> call-saved registers.

There is code in final_start_function to do this.  However, this can
only work if you aren't using register elimination, and if you are
emitting assembly language prologues instead of using RTL patterns in
the md file.  So this could only work for old ports.

Checking, I see that the only port that uses NON_SAVING_SETJMP is the
x86 svr3 port, and I am fairly certain that is a dead port.  Yes, I see
it on Nathanael Nerode's obsolete list for 3.4.  Actually, it looks like
this is the only target that ever used this macro.

If we really need this to work, then we can move the code from
final_start_function to reload.  This will give code very similar to
what I just deleted, except that it tests NON_SAVING_SETJMP.

Or we can just obsolete all of the NON_SAVING_SETJMP support, as I
believe we don't need it anymore.  It seems very unlikely that we need
gcc to support systems with a broken setjmp() library function.  The
original definition of the macro might even have been based on a
misunderstanding of what setjmp does.

I think dropping the NON_SAVING_SETJMP support is the more sensible
solution.
-- 
Jim Wilson, GNU Tools Support, http://www.SpecifixInc.com

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: avoid unnecessary register saves for setjmp
  2003-11-21 18:39 ` Daniel Jacobowitz
@ 2003-11-22  0:22   ` Jim Wilson
  2003-11-22  3:57     ` Daniel Jacobowitz
  0 siblings, 1 reply; 33+ messages in thread
From: Jim Wilson @ 2003-11-22  0:22 UTC (permalink / raw)
  To: Daniel Jacobowitz; +Cc: gcc-patches

On Fri, 2003-11-21 at 09:55, Daniel Jacobowitz wrote:
> I recently spent some time investigating this same code.  I was working
> on an ARM target with the iWMMXt extension set, which includes a number
> of additional registers.  The existing setjmp implementation on that
> target did not save them, but things worked anyway; I dug, and this was
> how.

We could perhaps use NON_SAVING_SETJMP for this, but I think fixing
setjmp is a better solution.  Assuming it needs to save any of the
iWMMXt registers.

> Speaking of Altivec, at least the GNU/Linux glibc setjmp implementation
> doesn't save Altivec registers either.  I posted a patch for this about
> three years ago and it was never incorporated.  So we may see problems
> reported from that side.

PR 12817 is from people asking gcc to not save the altivec registers
around setjmp, because it isn't supposed to.  So at least some PowerPC
folks believe that this register saving is wrong.

> I discussed this on IRC with a few people; I don't remember who all of
> them were, but definitely including H-P.  My conclusion from the
> discussion was that the setjmp standard library function is _not_
> mandated by C99 to save all registers.  I do not know of any psABI
> documents which specify the saved registers either.  So I am a little
> uncomfortable with your patch.

Yes, setjmp is not required to save registers.  Gcc knows this, and
avoids allocating pseudos to registers if the pseudo lives across a
setjmp.  We don't need to save unused registers to make this work.
Also, keep in mind that gcc versions from 1.0 to 3.0.4 did not do this
extra saving, and setjmp worked fine for them.  Users have to use
volatile if they want a local variable to live across a setjmp call.

> Er... actually, upon second inspection, the code I was referring to was
> regs_live_at_setjmp in flow.c.  I'm not sure whether the code you are
> removing from reload1.c will change the behavior I describe, after
> all.

This code isn't affected by my patch.
-- 
Jim Wilson, GNU Tools Support, http://www.SpecifixInc.com

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: avoid unnecessary register saves for setjmp
  2003-11-22  0:22   ` Jim Wilson
@ 2003-11-22  3:57     ` Daniel Jacobowitz
  2003-11-22  9:06       ` Jim Wilson
  0 siblings, 1 reply; 33+ messages in thread
From: Daniel Jacobowitz @ 2003-11-22  3:57 UTC (permalink / raw)
  To: Jim Wilson; +Cc: gcc-patches

On Fri, Nov 21, 2003 at 04:20:29PM -0800, Jim Wilson wrote:
> On Fri, 2003-11-21 at 09:55, Daniel Jacobowitz wrote:
> > I recently spent some time investigating this same code.  I was working
> > on an ARM target with the iWMMXt extension set, which includes a number
> > of additional registers.  The existing setjmp implementation on that
> > target did not save them, but things worked anyway; I dug, and this was
> > how.
> 
> We could perhaps use NON_SAVING_SETJMP for this, but I think fixing
> setjmp is a better solution.  Assuming it needs to save any of the
> iWMMXt registers.
> 
> > Speaking of Altivec, at least the GNU/Linux glibc setjmp implementation
> > doesn't save Altivec registers either.  I posted a patch for this about
> > three years ago and it was never incorporated.  So we may see problems
> > reported from that side.
> 
> PR 12817 is from people asking gcc to not save the altivec registers
> around setjmp, because it isn't supposed to.  So at least some PowerPC
> folks believe that this register saving is wrong.

If your setjmp saves them, sure.

Here's the difficulty: changing the size of jmp_buf.  Lately (last
three years or so) there have been a rash of ISA extensions implemented
which would require incompatible changes to jmp_buf for a widely
deployed architecture.  This is remarkably painful.

> > I discussed this on IRC with a few people; I don't remember who all of
> > them were, but definitely including H-P.  My conclusion from the
> > discussion was that the setjmp standard library function is _not_
> > mandated by C99 to save all registers.  I do not know of any psABI
> > documents which specify the saved registers either.  So I am a little
> > uncomfortable with your patch.
> 
> Yes, setjmp is not required to save registers.  Gcc knows this, and
> avoids allocating pseudos to registers if the pseudo lives across a
> setjmp.  We don't need to save unused registers to make this work.

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.

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: avoid unnecessary register saves for setjmp
  2003-11-22  3:57     ` Daniel Jacobowitz
@ 2003-11-22  9:06       ` Jim Wilson
  2003-11-22 14:37         ` Richard Earnshaw
  0 siblings, 1 reply; 33+ messages in thread
From: Jim Wilson @ 2003-11-22  9:06 UTC (permalink / raw)
  To: Daniel Jacobowitz; +Cc: gcc-patches

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.

> 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.
-- 
Jim Wilson, GNU Tools Support, http://www.SpecifixInc.com

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: avoid unnecessary register saves for setjmp
  2003-11-22  9:06       ` Jim Wilson
@ 2003-11-22 14:37         ` Richard Earnshaw
  2003-11-22 16:33           ` Daniel Jacobowitz
  0 siblings, 1 reply; 33+ messages in thread
From: Richard Earnshaw @ 2003-11-22 14:37 UTC (permalink / raw)
  To: Jim Wilson; +Cc: Daniel Jacobowitz, gcc-patches, Richard.Earnshaw

> 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.
> 
> > 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.

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).

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).

R.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: avoid unnecessary register saves for setjmp
  2003-11-22 14:37         ` Richard Earnshaw
@ 2003-11-22 16:33           ` Daniel Jacobowitz
  2003-11-27  9:11             ` Zack Weinberg
  2003-11-28 14:02             ` Richard Earnshaw
  0 siblings, 2 replies; 33+ messages in thread
From: Daniel Jacobowitz @ 2003-11-22 16:33 UTC (permalink / raw)
  To: Richard.Earnshaw; +Cc: Jim Wilson, gcc-patches

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

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: avoid unnecessary register saves for setjmp
  2003-11-22 16:33           ` Daniel Jacobowitz
@ 2003-11-27  9:11             ` Zack Weinberg
  2003-11-27 17:11               ` Andrew Pinski
  2003-11-28 14:02             ` Richard Earnshaw
  1 sibling, 1 reply; 33+ messages in thread
From: Zack Weinberg @ 2003-11-27  9:11 UTC (permalink / raw)
  To: Richard.Earnshaw; +Cc: Jim Wilson, gcc-patches


I'm going to take this opportunity to throw in a suggestion I've made
before, which is that setjmp/longjmp should - always, not just when
special variants are used - be converted by the front end into
invocations of the exception-unwinding facility, which gives us tons
more control.  (Obviously this only works with DWARF2 exception
handling.)

zw

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: avoid unnecessary register saves for setjmp
  2003-11-27  9:11             ` Zack Weinberg
@ 2003-11-27 17:11               ` Andrew Pinski
  2003-11-27 18:23                 ` Zack Weinberg
  0 siblings, 1 reply; 33+ messages in thread
From: Andrew Pinski @ 2003-11-27 17:11 UTC (permalink / raw)
  To: Zack Weinberg; +Cc: Jim Wilson, gcc-patches, Andrew Pinski, Richard.Earnshaw

On Nov 27, 2003, at 00:01, Zack Weinberg wrote:
> I'm going to take this opportunity to throw in a suggestion I've made
> before, which is that setjmp/longjmp should - always, not just when
> special variants are used - be converted by the front end into
> invocations of the exception-unwinding facility, which gives us tons
> more control.  (Obviously this only works with DWARF2 exception
> handling.)


But what about backwards compatibility aka use of setjmp/longjmp 
through libraries,
I know that Foundation and AppKit (Objective-C libraries) uses 
setjmp/longjmp and
the Objective-C front-end emits it now with @try/@catch/@finally/@throw.
(Apple does want to change it to dwarf-2 exceptions but cannot because 
backwards
compatibility).

Thanks,
Andrew Pinski
apinski@apple.com
pinskia@gcc.gnu.org
pinskia@physics.uc.edu

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: avoid unnecessary register saves for setjmp
  2003-11-27 17:11               ` Andrew Pinski
@ 2003-11-27 18:23                 ` Zack Weinberg
  2003-11-28  5:15                   ` Geert Bosch
  2003-11-28 11:14                   ` Richard Earnshaw
  0 siblings, 2 replies; 33+ messages in thread
From: Zack Weinberg @ 2003-11-27 18:23 UTC (permalink / raw)
  To: Andrew Pinski; +Cc: Jim Wilson, gcc-patches, Richard.Earnshaw

Andrew Pinski <pinskia@physics.uc.edu> writes:

> On Nov 27, 2003, at 00:01, Zack Weinberg wrote:
>> I'm going to take this opportunity to throw in a suggestion I've made
>> before, which is that setjmp/longjmp should - always, not just when
>> special variants are used - be converted by the front end into
>> invocations of the exception-unwinding facility, which gives us tons
>> more control.  (Obviously this only works with DWARF2 exception
>> handling.)
>
> But what about backwards compatibility aka use of setjmp/longjmp
> through libraries,

This is a major stumbling block, yes.

zw

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: avoid unnecessary register saves for setjmp
  2003-11-27 18:23                 ` Zack Weinberg
@ 2003-11-28  5:15                   ` Geert Bosch
  2003-11-28 11:14                   ` Richard Earnshaw
  1 sibling, 0 replies; 33+ messages in thread
From: Geert Bosch @ 2003-11-28  5:15 UTC (permalink / raw)
  To: Zack Weinberg; +Cc: Jim Wilson, gcc-patches, Andrew Pinski, Richard.Earnshaw


On Nov 27, 2003, at 12:56, Zack Weinberg wrote:
>>> I'm going to take this opportunity to throw in a suggestion I've made
>>> before, which is that setjmp/longjmp should - always, not just when
>>> special variants are used - be converted by the front end into
>>> invocations of the exception-unwinding facility, which gives us tons
>>> more control.  (Obviously this only works with DWARF2 exception
>>> handling.)
>>
>> But what about backwards compatibility aka use of setjmp/longjmp
>> through libraries,
>
> This is a major stumbling block, yes.

Another issue is that traditional setjmp/longjmp is much faster than
exception-unwinding if a large number of longjmp calls is made.
I could agree with Zack that it is a good goal to have the default
be using DWARF2-based exception handling, but we should always have
the fallback option of using traditional setjmp/longjmp.

   -Geert

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: avoid unnecessary register saves for setjmp
  2003-11-27 18:23                 ` Zack Weinberg
  2003-11-28  5:15                   ` Geert Bosch
@ 2003-11-28 11:14                   ` Richard Earnshaw
  1 sibling, 0 replies; 33+ messages in thread
From: Richard Earnshaw @ 2003-11-28 11:14 UTC (permalink / raw)
  To: Zack Weinberg; +Cc: Andrew Pinski, Jim Wilson, gcc-patches, Richard.Earnshaw

> Andrew Pinski <pinskia@physics.uc.edu> writes:
> 
> > On Nov 27, 2003, at 00:01, Zack Weinberg wrote:
> >> I'm going to take this opportunity to throw in a suggestion I've made
> >> before, which is that setjmp/longjmp should - always, not just when
> >> special variants are used - be converted by the front end into
> >> invocations of the exception-unwinding facility, which gives us tons
> >> more control.  (Obviously this only works with DWARF2 exception
> >> handling.)
> >
> > But what about backwards compatibility aka use of setjmp/longjmp
> > through libraries,
> 
> This is a major stumbling block, yes.
> 
> zw

Not to mention compatibility with objects built with other compilers.

R.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: avoid unnecessary register saves for setjmp
  2003-11-22 16:33           ` Daniel Jacobowitz
  2003-11-27  9:11             ` Zack Weinberg
@ 2003-11-28 14:02             ` Richard Earnshaw
  1 sibling, 0 replies; 33+ messages in thread
From: Richard Earnshaw @ 2003-11-28 14:02 UTC (permalink / raw)
  To: Daniel Jacobowitz; +Cc: Richard.Earnshaw, Jim Wilson, gcc-patches


> > 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.

There's never a perfect solution to a situation like this.  The failure of 
history (and more recently of language standards bodies) to recognize that 
portable binaries have as much importance as portable source means that in 
the dark corners you are always doomed to failure.

The way we've approached the issue for the "ABI for the ARM Architecture" 
is to define a compliance model.  The model is fairly simple and basically 
divides into 2 categories.

In the "portable object" category, the trade-off is in the direction of 
portability over outright compliance to the language standards and 
performance.  Sometimes it's necessary to write your source code using a 
particular idiom in order to achieve maximum portability.  In other cases 
constants that the C standard says are compile-time literals may only be 
available as link-time constants.  You are also restricted as to the 
library functions you may call.  In general, for example, you can't 
include stdio.h in a portable object and have it do anything useful.  We 
believe that developers targeting the portable-objects market will be 
prepared to live with the restrictions because it's better than anything 
they could have otherwise.

In the "platform object" category, the trade-off is in the direction of 
compliance to the relevant standards.  You can use the full features of 
the language, but your object is tied to a particular platform.

setjmp is one of those functions that lies on the boundary between the two 
models.  If you are compiling for a particular platform, which has a 
strict ABI, then you can use a jmp_buf that is exactly right for that 
platform.  But if you are building a portable object, you have to be 
prepared to handle platforms with a lot of registers that need saving and 
restoring; it is however, possible to err on the side of caution and just 
say that any static jmp_buf must be at least as large as the jmp_buf used 
by any supported target system.  For a dynamic jmp_buf, if you are 
prepared to use dynamic allocation, and to use source-code modifications, 
then we've added a link-time constant that will tell you the exact size 
needed for the platform the code ends up running on.

As for the portable static size of a jmp_buf, we looked at the likely 
register needs given the current co-processor blocks in existence today, 
and concluded that we currently should allow for 32 double-words of memory 
(256 bytes, 8-byte aligned) for the buffer.  We've no proof that we will 
never need more, but sometimes you just have to make a judgement call.

We'd recommend that developers defining new open-platform ABIs use the 
portable size, since it then gives them maximum defence against future 
processor trends.

R.

Disclaimer: the ABI for the ARM Architecture" is still in draft form, so 
any specifics cited above may still be subject to change.  I don't expect 
them to, but the possibility does exist.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: avoid unnecessary register saves for setjmp
  2003-11-21 20:14 ` Geoff Keating
  2003-11-22  0:20   ` Jim Wilson
@ 2003-11-30  9:23   ` Jim Wilson
  1 sibling, 0 replies; 33+ messages in thread
From: Jim Wilson @ 2003-11-30  9:23 UTC (permalink / raw)
  To: Geoff Keating; +Cc: gcc-patches, Daniel Jacobowitz

On Fri, 2003-11-21 at 12:11, Geoff Keating wrote:
> I've looked at this some time in the past (I don't remember the exact
> circumstances).  I came to the same conclusion as you, except in the
> case when NON_SAVING_SETJMP is defined, when we do need to save any
> call-saved registers.

This is an attempt to make NON_SAVING_SETJMP work again, as I offered to do a
week ago before I caught the flu.

As mentioned before, the current code which sets regs_ever_live in
final_start_function only works if there is no register elimination, and if
the prologue/epilogue are emitted as assembly language.  This makes the code
work again by moving the code to reload.  The result is similar to the code
I deleted a week ago, except that it is only enabled if NON_SAVING_SETMP is
true.

There is only one port that defines NON_SAVING_SETJMP: i386-sysv.  It won't
build because of bit-rot, and it is on the list of targets to be obsoleted, and
I don't have access to it anyways.  So there is no good way to test this
change.

I tested this by building a i386-linux toolchain, with NON_SAVING_SETJMP set to
true and compiling a small testcase.  No registers are saved without this
patch.  With this patch, all call-saved regs are saved in the prologue and
restored in the epilogue.  There is code in function.c to avoid using registers
for locals in a function that calls setjmp when NON_SAVING_SETJMP is true, so
this is sufficient to ensure that gcc works even if setjmp doesn't save
registers.

To make sure I didn't introduce a stupid typo, I did 3 x86-linux bootstraps
with --enable-languages=c, one with NON_SAVING_SETMP undefined, one with it
defined to 0, and one with it defined to 1.

2003-11-29  James E Wilson  <wilson@specifixinc.com>

	* final.c (final_start_function): Delete code for NON_SAVING_SETJMP.
	* reload1.c (reload): Re-add it here.

Index: reload1.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/reload1.c,v
retrieving revision 1.413
diff -p -r1.413 reload1.c
*** reload1.c	21 Nov 2003 05:49:05 -0000	1.413
--- reload1.c	30 Nov 2003 05:12:16 -0000
*************** reload (rtx first, int global)
*** 673,678 ****
--- 673,689 ----
        if (! call_used_regs[i] && ! fixed_regs[i] && ! LOCAL_REGNO (i))
  	regs_ever_live[i] = 1;
  
+ #ifdef NON_SAVING_SETJMP
+   /* A function that calls setjmp should save and restore all the
+      call-saved registers on a system where longjmp clobbers them.  */
+   if (NON_SAVING_SETJMP && current_function_calls_setjmp)
+     {
+       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ 	if (! call_used_regs[i])
+ 	  regs_ever_live[i] = 1;
+     }
+ #endif
+ 
    /* Find all the pseudo registers that didn't get hard regs
       but do have known equivalent constants or memory slots.
       These include parameters (known equivalent to parameter slots)
Index: final.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/final.c,v
retrieving revision 1.294
diff -p -r1.294 final.c
*** final.c	1 Nov 2003 00:48:50 -0000	1.294
--- final.c	30 Nov 2003 05:12:19 -0000
*************** final_start_function (rtx first ATTRIBUT
*** 1336,1354 ****
  
    this_is_asm_operands = 0;
  
- #ifdef NON_SAVING_SETJMP
-   /* A function that calls setjmp should save and restore all the
-      call-saved registers on a system where longjmp clobbers them.  */
-   if (NON_SAVING_SETJMP && current_function_calls_setjmp)
-     {
-       int i;
- 
-       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- 	if (!call_used_regs[i])
- 	  regs_ever_live[i] = 1;
-     }
- #endif
- 
    last_filename = locator_file (prologue_locator);
    last_linenum = locator_line (prologue_locator);
  
--- 1336,1341 ----
-- 
Jim Wilson, GNU Tools Support, http://www.SpecifixInc.com

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: avoid unnecessary register saves for setjmp
  2003-11-22  4:13 Richard Kenner
@ 2003-12-01  3:29 ` Jim Wilson
  0 siblings, 0 replies; 33+ messages in thread
From: Jim Wilson @ 2003-12-01  3:29 UTC (permalink / raw)
  To: Richard Kenner; +Cc: gcc-patches

Richard Kenner wrote:
> Well, you certainly need to save all the caller-saved registers if there
> are any nonlocal gotos (which you have in the Ada exception case), but,
> as I understand this change, it still does.

This is handled by a different piece of code that I did not touch. 
reload() has a check for current_function_nonlocal_label, and if true, 
it marks call-saved registers as live, so that they will be saved and 
restored.
-- 
Jim Wilson, GNU Tools Support, http://www.SpecifixInc.com

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: avoid unnecessary register saves for setjmp
  2003-11-27 20:28             ` Chris Lattner
@ 2003-11-27 20:51               ` Gabriel Dos Reis
  0 siblings, 0 replies; 33+ messages in thread
From: Gabriel Dos Reis @ 2003-11-27 20:51 UTC (permalink / raw)
  To: Chris Lattner
  Cc: Zack Weinberg, Andrew Haley, Richard.Earnshaw, Jim Wilson, gcc-patches

Chris Lattner <sabre@nondot.org> writes:

| LIFO order.  I guess that people are used to not having longjmp work
| "correctly"? :)

Yup.  In effect, the C++ standard says nothing about mixing
setjmp/longjmp with notions like construction and destruction --
meaning it is undefined.  C++ tries to provide those non local gotos
in structrured manner through exception handling -- which gives better
guarantees. 

-- Gaby

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: avoid unnecessary register saves for setjmp
       [not found] <5cad8ef043da68f2a3332f00bd6a186a3fc6195b@mail.esmertec.com>
@ 2003-11-27 20:44 ` Chris Lattner
  0 siblings, 0 replies; 33+ messages in thread
From: Chris Lattner @ 2003-11-27 20:44 UTC (permalink / raw)
  To: Jan Vroonhof; +Cc: gcc-patches

> >> To be fair, an argument against this change is that it would break
> >> code that uses setjmp and longjmp to implement coroutine linkage.
> >> (The set/get/make/swapcontext calls are better for this, but that
> >> doesn't mean everyone uses them.)
>
> Doesn't it also convert longjmp from an O(1) in to an O(nr off stack frames)
> operation?

Yes, if you use unwinding to implement it.  You can obviously use SJLJ
to implement the exception runtime, retaining the same complexity.  The
normal design decision is to favor non-exceptional control flow, even if
that means changing exception throws to take O(n).  In practice, stack
unwinding is still very fast.

> > I don't believe that this is actually legal ANSI C.  You can only return
> > to a place that has been setjmp'd to, there is no way to 'construct' a
> > jmpbuf.  Likewise, you cannot setjmp, return from the setjmp'ing function,
> > then longjmp back to the 'dead' jmpbuf.
>
> It might not be ANSI C, but it does work on most systems for user
> level threading (essentially implementing swapcontext by direct
> manipulation of the jmbuf). There is lots of useful things people do
> with C that are not strictly ANSI/ISO C. In fact that kind of low
> level control is often exactly the reason to use C in the first place.

As Zach said, they should be using getcontext/swapcontext/makecontext.
jmpbuf's do not hold the entire register state for the processor.

-Chris

-- 
http://llvm.cs.uiuc.edu/
http://www.nondot.org/~sabre/Projects/

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: avoid unnecessary register saves for setjmp
  2003-11-27 11:01           ` Zack Weinberg
@ 2003-11-27 20:28             ` Chris Lattner
  2003-11-27 20:51               ` Gabriel Dos Reis
  0 siblings, 1 reply; 33+ messages in thread
From: Chris Lattner @ 2003-11-27 20:28 UTC (permalink / raw)
  To: Zack Weinberg; +Cc: Andrew Haley, Richard.Earnshaw, Jim Wilson, gcc-patches

On Thu, 27 Nov 2003, Zack Weinberg wrote:
> Chris Lattner <sabre@nondot.org> writes:
> > On Thu, 27 Nov 2003, Zack Weinberg wrote:
> > Also, ideally, longjmp should run cleanups in intervening stackframes,
> > which the LLVM implementation does, just like for pthreads cancellation.
>
> Right.  (The IA64 psABI seems to anticipate that some people expect it
> *not* to, by providing longjmp_unwind.)

Really?  That seems to be directly against the C++ notion of construction
and destruction: that non-heap objects are guaranteed to be destroyed in
LIFO order.  I guess that people are used to not having longjmp work
"correctly"? :)

-Chris

-- 
http://llvm.cs.uiuc.edu/
http://www.nondot.org/~sabre/Projects/

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: avoid unnecessary register saves for setjmp
  2003-11-27 10:15         ` Chris Lattner
  2003-11-27 11:01           ` Zack Weinberg
  2003-11-27 15:41           ` Jan Vroonhof
@ 2003-11-27 16:23           ` Jan Vroonhof
  2 siblings, 0 replies; 33+ messages in thread
From: Jan Vroonhof @ 2003-11-27 16:23 UTC (permalink / raw)
  To: Chris Lattner; +Cc: gcc-patches

The following message is a courtesy copy of an article
that has been posted to gmane.comp.gcc.patches as well.

Chris Lattner <sabre@nondot.org> writes:

>> To be fair, an argument against this change is that it would break
>> code that uses setjmp and longjmp to implement coroutine linkage.
>> (The set/get/make/swapcontext calls are better for this, but that
>> doesn't mean everyone uses them.)

Doesn't it also convert longjmp from an O(1) in to an O(nr off stack frames)
operation?

>
> I don't believe that this is actually legal ANSI C.  You can only return
> to a place that has been setjmp'd to, there is no way to 'construct' a
> jmpbuf.  Likewise, you cannot setjmp, return from the setjmp'ing function,
> then longjmp back to the 'dead' jmpbuf.

It might not be ANSI C, but it does work on most systems for user
level threading (essentially implementing swapcontext by direct
manipulation of the jmbuf). There is lots of useful things people do
with C that are not strictly ANSI/ISO C. In fact that kind of low
level control is often exactly the reason to use C in the first place.

Jan

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: avoid unnecessary register saves for setjmp
  2003-11-27 10:15         ` Chris Lattner
  2003-11-27 11:01           ` Zack Weinberg
@ 2003-11-27 15:41           ` Jan Vroonhof
  2003-11-27 16:23           ` Jan Vroonhof
  2 siblings, 0 replies; 33+ messages in thread
From: Jan Vroonhof @ 2003-11-27 15:41 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-patches

Chris Lattner <sabre@nondot.org> writes:

>> To be fair, an argument against this change is that it would break
>> code that uses setjmp and longjmp to implement coroutine linkage.
>> (The set/get/make/swapcontext calls are better for this, but that
>> doesn't mean everyone uses them.)

Doesn't it also convert longjmp from an O(1) in to an O(nr off stack frames)
operation?

>
> I don't believe that this is actually legal ANSI C.  You can only return
> to a place that has been setjmp'd to, there is no way to 'construct' a
> jmpbuf.  Likewise, you cannot setjmp, return from the setjmp'ing function,
> then longjmp back to the 'dead' jmpbuf.

It might not be ANSI C, but it does work on most systems for user
level threading (essentially implementing swapcontext by direct
manipulation of the jmbuf). There is lots of useful things people do
with C that are not strictly ANSI/ISO C. In fact that kind of low
level control is often exactly the reason to use C in the first place.

Jan

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: avoid unnecessary register saves for setjmp
  2003-11-27 10:15         ` Chris Lattner
@ 2003-11-27 11:01           ` Zack Weinberg
  2003-11-27 20:28             ` Chris Lattner
  2003-11-27 15:41           ` Jan Vroonhof
  2003-11-27 16:23           ` Jan Vroonhof
  2 siblings, 1 reply; 33+ messages in thread
From: Zack Weinberg @ 2003-11-27 11:01 UTC (permalink / raw)
  To: Chris Lattner; +Cc: Andrew Haley, Richard.Earnshaw, Jim Wilson, gcc-patches

Chris Lattner <sabre@nondot.org> writes:

> On Thu, 27 Nov 2003, Zack Weinberg wrote:
>
>> >From a language-design perspective it's desirable for x to have the
>> value 23 in both fragments.  (Leaving out the volatile on x is
>> intentional.)  Its being undefined in C is a source of hard-to-find
>> bugs.  It happens because longjmp() can't know which registers need
>> restoring, whereas the EH unwinder does know and can get it
>> (abstractly) right.  So by using the EH unwinder for longjmp we clean
>> up a nasty dark corner of the language.
>
> Also, ideally, longjmp should run cleanups in intervening stackframes,
> which the LLVM implementation does, just like for pthreads cancellation.

Right.  (The IA64 psABI seems to anticipate that some people expect it
*not* to, by providing longjmp_unwind.)

>> To be fair, an argument against this change is that it would break
>> code that uses setjmp and longjmp to implement coroutine linkage.
>> (The set/get/make/swapcontext calls are better for this, but that
>> doesn't mean everyone uses them.)
>
> I don't believe that this is actually legal ANSI C.  You can only return
> to a place that has been setjmp'd to, there is no way to 'construct' a
> jmpbuf.  Likewise, you cannot setjmp, return from the setjmp'ing function,
> then longjmp back to the 'dead' jmpbuf.

No, no it isn't.

zw

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: avoid unnecessary register saves for setjmp
  2003-11-27 10:31         ` Andrew Haley
@ 2003-11-27 10:53           ` Zack Weinberg
  0 siblings, 0 replies; 33+ messages in thread
From: Zack Weinberg @ 2003-11-27 10:53 UTC (permalink / raw)
  To: Andrew Haley; +Cc: gcc-patches

Andrew Haley <aph@redhat.com> writes:

> Zack Weinberg writes:
>
>  > So by using the EH unwinder for longjmp we clean
>  > up a nasty dark corner of the language.
>
> Do we really?  The value is still undefined according to 7.13.2.1 Para
> 3; all we're doing is making a gcc extension that such values are
> well-defined.

Yeah.  It just happens that this is the well-definition that papers
over the maximum number of bugs.

zw

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: avoid unnecessary register saves for setjmp
  2003-11-27 10:14       ` Zack Weinberg
  2003-11-27 10:15         ` Chris Lattner
@ 2003-11-27 10:31         ` Andrew Haley
  2003-11-27 10:53           ` Zack Weinberg
  1 sibling, 1 reply; 33+ messages in thread
From: Andrew Haley @ 2003-11-27 10:31 UTC (permalink / raw)
  To: Zack Weinberg; +Cc: gcc-patches

Zack Weinberg writes:

 > So by using the EH unwinder for longjmp we clean
 > up a nasty dark corner of the language.

Do we really?  The value is still undefined according to 7.13.2.1 Para
3; all we're doing is making a gcc extension that such values are
well-defined.

Andrew.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: avoid unnecessary register saves for setjmp
  2003-11-27 10:14       ` Zack Weinberg
@ 2003-11-27 10:15         ` Chris Lattner
  2003-11-27 11:01           ` Zack Weinberg
                             ` (2 more replies)
  2003-11-27 10:31         ` Andrew Haley
  1 sibling, 3 replies; 33+ messages in thread
From: Chris Lattner @ 2003-11-27 10:15 UTC (permalink / raw)
  To: Zack Weinberg; +Cc: Andrew Haley, Richard.Earnshaw, Jim Wilson, gcc-patches

On Thu, 27 Nov 2003, Zack Weinberg wrote:

> >From a language-design perspective it's desirable for x to have the
> value 23 in both fragments.  (Leaving out the volatile on x is
> intentional.)  Its being undefined in C is a source of hard-to-find
> bugs.  It happens because longjmp() can't know which registers need
> restoring, whereas the EH unwinder does know and can get it
> (abstractly) right.  So by using the EH unwinder for longjmp we clean
> up a nasty dark corner of the language.

Also, ideally, longjmp should run cleanups in intervening stackframes,
which the LLVM implementation does, just like for pthreads cancellation.

> To be fair, an argument against this change is that it would break
> code that uses setjmp and longjmp to implement coroutine linkage.
> (The set/get/make/swapcontext calls are better for this, but that
> doesn't mean everyone uses them.)

I don't believe that this is actually legal ANSI C.  You can only return
to a place that has been setjmp'd to, there is no way to 'construct' a
jmpbuf.  Likewise, you cannot setjmp, return from the setjmp'ing function,
then longjmp back to the 'dead' jmpbuf.

-Chris

-- 
http://llvm.cs.uiuc.edu/
http://www.nondot.org/~sabre/Projects/

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: avoid unnecessary register saves for setjmp
  2003-11-27  9:39     ` Andrew Haley
  2003-11-27  9:43       ` Chris Lattner
@ 2003-11-27 10:14       ` Zack Weinberg
  2003-11-27 10:15         ` Chris Lattner
  2003-11-27 10:31         ` Andrew Haley
  1 sibling, 2 replies; 33+ messages in thread
From: Zack Weinberg @ 2003-11-27 10:14 UTC (permalink / raw)
  To: Andrew Haley; +Cc: Chris Lattner, Richard.Earnshaw, Jim Wilson, gcc-patches

Andrew Haley <aph@redhat.com> writes:

> Well, okay: the front end has turned sjlj into exceptions, and the
> back end has turned it all back again.  We get the advantage of better
> analysis in the middle.  No problem there; I am only referring to
> user-visible changes.

I should say that the primary reason I think this would be a good
change for GCC's users (not just for internal-to-GCC reasons) is that
it makes the user-visible semantics of setjmp/longjmp much nicer.
Consider

void foo(jmp_buf env) { longjmp(env, 1); }

void bar(void)
{
  int x = 12;
  jmp_buf env;

  if (setjmp (env) == 0)
    {
      x = 23;
      foo();
    }
  else
    printf("%d\n", x);  // oops! value of x is undefined
}

versus

void foo(jmp_buf env) { throw 1; }

void bar(void)
{
  int x = 12;
  jmp_buf env;

  try
    {
      x = 23;
      foo();
    }
  catch (int)
    printf("%d\n", x);  // defined to print 23
}

From a language-design perspective it's desirable for x to have the
value 23 in both fragments.  (Leaving out the volatile on x is
intentional.)  Its being undefined in C is a source of hard-to-find
bugs.  It happens because longjmp() can't know which registers need
restoring, whereas the EH unwinder does know and can get it
(abstractly) right.  So by using the EH unwinder for longjmp we clean
up a nasty dark corner of the language.

To be fair, an argument against this change is that it would break
code that uses setjmp and longjmp to implement coroutine linkage.
(The set/get/make/swapcontext calls are better for this, but that
doesn't mean everyone uses them.)

zw

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: avoid unnecessary register saves for setjmp
  2003-11-27  9:39     ` Andrew Haley
@ 2003-11-27  9:43       ` Chris Lattner
  2003-11-27 10:14       ` Zack Weinberg
  1 sibling, 0 replies; 33+ messages in thread
From: Chris Lattner @ 2003-11-27  9:43 UTC (permalink / raw)
  To: Andrew Haley; +Cc: Zack Weinberg, Richard.Earnshaw, Jim Wilson, gcc-patches

On Thu, 27 Nov 2003, Andrew Haley wrote:
>  > Not at all.  For example, somewhat confusingly, the LLVM->C backend
>  > actually turns "stack unwinding" operations into setjmp/longjmp
>  > calls.  This is basically equivalent to SJLJ exception handling,
>  > with all of it's problems, but the point is that you don't _NEED_
>  > to include an unwinder.
>
> Well, okay: the front end has turned sjlj into exceptions, and the
> back end has turned it all back again.

It _can_ turn it all back again.  SJLJ is a horribly inefficient way to
implement exceptions in a C++ type of world (lots of dtors to run, catch
blocks, exception specs to check, etc).  For C it's probably fine.

> We get the advantage of better analysis in the middle.  No problem
> there; I am only referring to user-visible changes.

As far as user visible changes, the biggest problem is the change in ABI.

-Chris

-- 
http://llvm.cs.uiuc.edu/
http://www.nondot.org/~sabre/Projects/

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: avoid unnecessary register saves for setjmp
  2003-11-27  9:22   ` Chris Lattner
@ 2003-11-27  9:39     ` Andrew Haley
  2003-11-27  9:43       ` Chris Lattner
  2003-11-27 10:14       ` Zack Weinberg
  0 siblings, 2 replies; 33+ messages in thread
From: Andrew Haley @ 2003-11-27  9:39 UTC (permalink / raw)
  To: Chris Lattner; +Cc: Zack Weinberg, Richard.Earnshaw, Jim Wilson, gcc-patches

Chris Lattner writes:
 > On Thu, 27 Nov 2003, Andrew Haley wrote:
 > 
 > > Chris Lattner writes:
 > >  > Zack Weinberg said:
 > >  > > I'm going to take this opportunity to throw in a suggestion I've
 > >  > > made before, which is that setjmp/longjmp should - always, not
 > >  > > just when special variants are used - be converted by the front
 > >  > > end into invocations of the exception-unwinding facility, which
 > >  > > gives us tons more control.
 > >
 > > True.  But the obvious problem with this is that it places a burden on
 > > small applications (boot ROMs, say) that might only have a single
 > > setjmp/longjmp.  These would be forced to include the unwinder and all
 > > its baggage just for that.
 > 
 > Not at all.  For example, somewhat confusingly, the LLVM->C backend
 > actually turns "stack unwinding" operations into setjmp/longjmp
 > calls.  This is basically equivalent to SJLJ exception handling,
 > with all of it's problems, but the point is that you don't _NEED_
 > to include an unwinder.

Well, okay: the front end has turned sjlj into exceptions, and the
back end has turned it all back again.  We get the advantage of better
analysis in the middle.  No problem there; I am only referring to
user-visible changes.

Andrew.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: avoid unnecessary register saves for setjmp
  2003-11-27  9:21 ` Andrew Haley
@ 2003-11-27  9:22   ` Chris Lattner
  2003-11-27  9:39     ` Andrew Haley
  0 siblings, 1 reply; 33+ messages in thread
From: Chris Lattner @ 2003-11-27  9:22 UTC (permalink / raw)
  To: Andrew Haley; +Cc: Zack Weinberg, Richard.Earnshaw, Jim Wilson, gcc-patches

On Thu, 27 Nov 2003, Andrew Haley wrote:

> Chris Lattner writes:
>  > Zack Weinberg said:
>  > > I'm going to take this opportunity to throw in a suggestion I've
>  > > made before, which is that setjmp/longjmp should - always, not
>  > > just when special variants are used - be converted by the front
>  > > end into invocations of the exception-unwinding facility, which
>  > > gives us tons more control.
>
> True.  But the obvious problem with this is that it places a burden on
> small applications (boot ROMs, say) that might only have a single
> setjmp/longjmp.  These would be forced to include the unwinder and all
> its baggage just for that.

Not at all.  For example, somewhat confusingly, the LLVM->C backend
actually turns "stack unwinding" operations into setjmp/longjmp calls.
This is basically equivalent to SJLJ exception handling, with all of it's
problems, but the point is that you don't _NEED_ to include an unwinder.

The entire point of LLVM is to make these implementation decisions as
orthogonal as possible so that the end user can decide how they want EH
implemented.  *shrug*  setjmp/longjmp is just the C form of exception
handling.  Why represent it any differently?

-Chris

-- 
http://llvm.cs.uiuc.edu/
http://www.nondot.org/~sabre/Projects/

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: avoid unnecessary register saves for setjmp
  2003-11-27  9:19 Chris Lattner
@ 2003-11-27  9:21 ` Andrew Haley
  2003-11-27  9:22   ` Chris Lattner
  0 siblings, 1 reply; 33+ messages in thread
From: Andrew Haley @ 2003-11-27  9:21 UTC (permalink / raw)
  To: Zack Weinberg; +Cc: Chris Lattner, Richard.Earnshaw, Jim Wilson, gcc-patches

Chris Lattner writes:
 > 
 > Zack Weinberg said:

 > > I'm going to take this opportunity to throw in a suggestion I've
 > > made before, which is that setjmp/longjmp should - always, not
 > > just when special variants are used - be converted by the front
 > > end into invocations of the exception-unwinding facility, which
 > > gives us tons more control.

True.  But the obvious problem with this is that it places a burden on
small applications (boot ROMs, say) that might only have a single
setjmp/longjmp.  These would be forced to include the unwinder and all
its baggage just for that.

Andrew.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: avoid unnecessary register saves for setjmp
@ 2003-11-27  9:19 Chris Lattner
  2003-11-27  9:21 ` Andrew Haley
  0 siblings, 1 reply; 33+ messages in thread
From: Chris Lattner @ 2003-11-27  9:19 UTC (permalink / raw)
  To: Zack Weinberg; +Cc: Richard.Earnshaw, Jim Wilson, gcc-patches


Zack Weinberg said:
> I'm going to take this opportunity to throw in a suggestion I've made
> before, which is that setjmp/longjmp should - always, not just when
> special variants are used - be converted by the front end into
> invocations of the exception-unwinding facility, which gives us tons
> more control.

This is exactly what we do in LLVM, which makes a lot of things much
nicer.  For example, because it uses the normal EH facilities in LLVM,
inlining a longjmp'ing function into the setjmp'ing function automatically
turns the stack unwinding operation into a direct branch, same as normal
EH.

This allows us to do aggressive optimizations on both the setjmp'ing and
longjmp'ing functions: there are no special cases needed or optimizations
disabled.  The only negative of doing this is that it adds a lot of edges
to the CFG's of some functions, but you have to represent the possible
control flow SOMEHOW.  :)  Also, the normal LLVM EH pruner automatically
deletes the edges from function calls that provably cannot unwind, so it
gets rid of a lot of the problem.

Just food for thought,

-Chris

-- 
http://llvm.cs.uiuc.edu/
http://www.nondot.org/~sabre/Projects/

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: avoid unnecessary register saves for setjmp
@ 2003-11-22  4:13 Richard Kenner
  2003-12-01  3:29 ` Jim Wilson
  0 siblings, 1 reply; 33+ messages in thread
From: Richard Kenner @ 2003-11-22  4:13 UTC (permalink / raw)
  To: geoffk; +Cc: gcc-patches

    I've looked at this some time in the past (I don't remember the exact
    circumstances).  I came to the same conclusion as you, except in the
    case when NON_SAVING_SETJMP is defined, when we do need to save any
    call-saved registers.

Well, you certainly need to save all the caller-saved registers if there
are any nonlocal gotos (which you have in the Ada exception case), but,
as I understand this change, it still does.

^ permalink raw reply	[flat|nested] 33+ messages in thread

end of thread, other threads:[~2003-12-01  3:29 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-11-21  5:54 avoid unnecessary register saves for setjmp Jim Wilson
2003-11-21 18:39 ` Daniel Jacobowitz
2003-11-22  0:22   ` Jim Wilson
2003-11-22  3:57     ` Daniel Jacobowitz
2003-11-22  9:06       ` Jim Wilson
2003-11-22 14:37         ` Richard Earnshaw
2003-11-22 16:33           ` Daniel Jacobowitz
2003-11-27  9:11             ` Zack Weinberg
2003-11-27 17:11               ` Andrew Pinski
2003-11-27 18:23                 ` Zack Weinberg
2003-11-28  5:15                   ` Geert Bosch
2003-11-28 11:14                   ` Richard Earnshaw
2003-11-28 14:02             ` Richard Earnshaw
2003-11-21 20:14 ` Geoff Keating
2003-11-22  0:20   ` Jim Wilson
2003-11-30  9:23   ` Jim Wilson
2003-11-22  4:13 Richard Kenner
2003-12-01  3:29 ` Jim Wilson
2003-11-27  9:19 Chris Lattner
2003-11-27  9:21 ` Andrew Haley
2003-11-27  9:22   ` Chris Lattner
2003-11-27  9:39     ` Andrew Haley
2003-11-27  9:43       ` Chris Lattner
2003-11-27 10:14       ` Zack Weinberg
2003-11-27 10:15         ` Chris Lattner
2003-11-27 11:01           ` Zack Weinberg
2003-11-27 20:28             ` Chris Lattner
2003-11-27 20:51               ` Gabriel Dos Reis
2003-11-27 15:41           ` Jan Vroonhof
2003-11-27 16:23           ` Jan Vroonhof
2003-11-27 10:31         ` Andrew Haley
2003-11-27 10:53           ` Zack Weinberg
     [not found] <5cad8ef043da68f2a3332f00bd6a186a3fc6195b@mail.esmertec.com>
2003-11-27 20:44 ` Chris Lattner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).