This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug c/13133] New: Extraneous register-saves triggered by setjmp()
- From: "davidm at hpl dot hp dot com" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: 19 Nov 2003 22:21:56 -0000
- Subject: [Bug c/13133] New: Extraneous register-saves triggered by setjmp()
- Reply-to: gcc-bugzilla at gcc dot gnu dot org
Calling setjmp() causes all kinds of registers to
get saved by GCC:
$ cat t.c
#include <setjmp.h>
jmp_buf j;
void
foo (void)
{
setjmp (j);
}
$ gcc -v
Reading specs from /opt/gcc-pre3.4/lib/gcc/ia64-hp-linux/3.4/specs
Configured with: ../gcc/configure --enable-shared --with-system-zlib --enable-n\
ls --without-included-gettext --enable-__cxa_atexit --enable-clocale=gnu --enab\
le-java-gc=boehm --enable-objc-gc --enable-languages=c --prefix=/opt/gcc-pre3.4\
ia64-hp-linux
Thread model: posix
gcc version 3.4 20031113 (experimental)
$ gcc -O2 -S t.c
$ cat t.s
.file "t.c"
.pred.safe_across_calls p1-p5,p16-p63
.text
.align 16
.global foo#
.proc foo#
foo:
.prologue
.mmb
alloc r16 = ar.pfs, 8, 80, 1, 0
adds r17 = -424, r12
nop 0
.mmi
adds r18 = -416, r12
.fframe 448
adds r12 = -448, r12
mov r21 = ar.lc
.mii
mov r19 = ar.unat
mov r20 = pr
addl r120 = @ltoffx(j#), r1
.mib
nop 0
mov r22 = b0
nop 0
;;
.mmi
ld8.mov r120 = [r120], j#
.savesp pr, 24
st8 [r17] = r20, 16
mov r23 = b1
.mii
nop 0
mov r24 = b2
mov r25 = b3
.mib
nop 0
mov r26 = b4
nop 0
.mii
.savesp ar.unat, 32
st8 [r18] = r19, 16
mov r27 = b5
;;
nop 0
.mmb
.savesp ar.pfs, 40
st8 [r17] = r16, 16
.savesp ar.lc, 48
st8 [r18] = r21, 16
nop 0
;;
.mmb
.mem.offset 392, 0
st8.spill [r17] = r1, 16
.mem.offset 392, 0
st8.spill [r17] = r1, 16
.save.g 0x1
.mem.offset 384, 0
st8.spill [r18] = r4, 16
nop 0
;;
.mmb
.save.g 0x2
.mem.offset 376, 0
st8.spill [r17] = r5, 16
.save.g 0x4
.mem.offset 368, 0
st8.spill [r18] = r6, 16
nop 0
;;
.mmb
.save.g 0x8
.mem.offset 360, 0
st8.spill [r17] = r7, 16
.savesp rp, 96
st8 [r18] = r22, 16
nop 0
;;
.mmb
.save.b 0x1
st8 [r17] = r23, 16
.save.b 0x2
st8 [r18] = r24, 16
nop 0
;;
.mmb
.save.b 0x4
st8 [r17] = r25, 16
.save.b 0x8
st8 [r18] = r26, 16
nop 0
;;
.mmb
.save.b 0x10
st8 [r17] = r27, 24
.save.f 0x1
stf.spill [r18] = f2, 32
nop 0
;;
.mmb
.save.f 0x2
stf.spill [r17] = f3, 32
.save.f 0x4
stf.spill [r18] = f4, 32
nop 0
;;
etc. etc.
Jim Wilson was kind enough to analyze this problem and offer a patch (see
below). I'd very much appreciate it if this problem could be fixed, since there
are performance-critical paths in libpthread which rely on setjmp().
From: Jim Wilson <wilson@tuliptree.org>
To: David Mosberger <davidm@hpl.hp.com>
Cc: rth@redhat.com, wilson@tuliptree.org
Subject: Re: weird saves triggered by setjmp()
Date: 15 Nov 2003 23:52:24 -0800
On Sat, 2003-11-15 at 11:13, David Mosberger wrote:
> The problem is that setjmp() causes all kinds of registers to
> get saved by GCC. Example is attached below.
Gcc does this for all targets. Though it is more noticeable for IA-64
because it has so many registers.
> It appears that GCC is saving every preserved integer/fp register?
Yes. Every call-saved register is marked as in use if a function
contains a call to setjmp or a related function.
Looking at this now, I see that the code was added between 2.7.2 and
2.8.1, and the intent was that we only did this for builtin setjmp
calls. This makes some sense, as builtin setjmp is added by the EH
mechanism, not the user, and hence the normal rules of setjmp clobbering
registers don't apply here, so we need to make an effort to save
registers that setjmp won't save. This code was added by Kenner.
Things got confused after that. The code originally tested for a
CONST_CALL_P NOTE_INSN_SETJMP. This was created in
expand_builtin_setjmp, and tested for in reload. The CONST_CALL_P note
disappeared in 2.95. It appears that it was deleted by Mike Stump, and
replaced with code to set nonlocal_goto_handler_labels instead. But the
code testing for the CONST_CALL_P note was still there in reload.
Then Jan Hubicka came along with a patch that replaced NOTE_INSN_SETJMP
with REG_SETJMP. When this happened, the CONST_CALL_P test was lost,
and now this reload code was enabled for all uses of setjmp. This
happened in gcc-3.1.
Given this analysis, it does look like it should be possible to just
delete the reload/setjmp code as obsolete. However, since this affects
setjmp, there is really no good way to test it, and hence we have to be
very careful about this change. I'd have to propose it, and try to get
some support from others, since we aren't supposed to be adding
destabilizing changes to gcc at this time.
* 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 ----
--
Summary: Extraneous register-saves triggered by setjmp()
Product: gcc
Version: 3.4
Status: UNCONFIRMED
Severity: enhancement
Priority: P2
Component: c
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: davidm at hpl dot hp dot com
CC: gcc-bugs at gcc dot gnu dot org
GCC host triplet: ia64-hp-linux
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13133