public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c/13133] New: Extraneous register-saves triggered by setjmp()
@ 2003-11-19 22:21 davidm at hpl dot hp dot com
2003-11-19 22:26 ` [Bug c/13133] " pinskia at gcc dot gnu dot org
` (11 more replies)
0 siblings, 12 replies; 13+ messages in thread
From: davidm at hpl dot hp dot com @ 2003-11-19 22:21 UTC (permalink / raw)
To: gcc-bugs
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
^ permalink raw reply [flat|nested] 13+ messages in thread
* [Bug c/13133] Extraneous register-saves triggered by setjmp()
2003-11-19 22:21 [Bug c/13133] New: Extraneous register-saves triggered by setjmp() davidm at hpl dot hp dot com
@ 2003-11-19 22:26 ` pinskia at gcc dot gnu dot org
2003-11-21 5:11 ` wilson at gcc dot gnu dot org
` (10 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: pinskia at gcc dot gnu dot org @ 2003-11-19 22:26 UTC (permalink / raw)
To: gcc-bugs
------- Additional Comments From pinskia at gcc dot gnu dot org 2003-11-19 22:26 -------
Yes and this happens on PPC and PPC64 also see PR 12817, with altivec the amount saved is huge
also.
--
What |Removed |Added
----------------------------------------------------------------------------
Status|UNCONFIRMED |NEW
Ever Confirmed| |1
Last reconfirmed|0000-00-00 00:00:00 |2003-11-19 22:26:23
date| |
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13133
^ permalink raw reply [flat|nested] 13+ messages in thread
* [Bug c/13133] Extraneous register-saves triggered by setjmp()
2003-11-19 22:21 [Bug c/13133] New: Extraneous register-saves triggered by setjmp() davidm at hpl dot hp dot com
2003-11-19 22:26 ` [Bug c/13133] " pinskia at gcc dot gnu dot org
@ 2003-11-21 5:11 ` wilson at gcc dot gnu dot org
2003-11-21 5:12 ` wilson at gcc dot gnu dot org
` (9 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: wilson at gcc dot gnu dot org @ 2003-11-21 5:11 UTC (permalink / raw)
To: gcc-bugs
------- Additional Comments From wilson at gcc dot gnu dot org 2003-11-21 05:11 -------
Mine.
--
What |Removed |Added
----------------------------------------------------------------------------
Status|NEW |ASSIGNED
Last reconfirmed|2003-11-19 22:26:23 |2003-11-21 05:11:36
date| |
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13133
^ permalink raw reply [flat|nested] 13+ messages in thread
* [Bug c/13133] Extraneous register-saves triggered by setjmp()
2003-11-19 22:21 [Bug c/13133] New: Extraneous register-saves triggered by setjmp() davidm at hpl dot hp dot com
2003-11-19 22:26 ` [Bug c/13133] " pinskia at gcc dot gnu dot org
2003-11-21 5:11 ` wilson at gcc dot gnu dot org
@ 2003-11-21 5:12 ` wilson at gcc dot gnu dot org
2003-11-21 5:49 ` cvs-commit at gcc dot gnu dot org
` (8 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: wilson at gcc dot gnu dot org @ 2003-11-21 5:12 UTC (permalink / raw)
To: gcc-bugs
------- Additional Comments From wilson at gcc dot gnu dot org 2003-11-21 05:12 -------
Let's try this again.
--
What |Removed |Added
----------------------------------------------------------------------------
AssignedTo|unassigned at gcc dot gnu |wilson at gcc dot gnu dot
|dot org |org
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13133
^ permalink raw reply [flat|nested] 13+ messages in thread
* [Bug c/13133] Extraneous register-saves triggered by setjmp()
2003-11-19 22:21 [Bug c/13133] New: Extraneous register-saves triggered by setjmp() davidm at hpl dot hp dot com
` (2 preceding siblings ...)
2003-11-21 5:12 ` wilson at gcc dot gnu dot org
@ 2003-11-21 5:49 ` cvs-commit at gcc dot gnu dot org
2003-11-21 5:53 ` wilson at gcc dot gnu dot org
` (7 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: cvs-commit at gcc dot gnu dot org @ 2003-11-21 5:49 UTC (permalink / raw)
To: gcc-bugs
------- Additional Comments From cvs-commit at gcc dot gnu dot org 2003-11-21 05:49 -------
Subject: Bug 13133
CVSROOT: /cvs/gcc
Module name: gcc
Changes by: wilson@gcc.gnu.org 2003-11-21 05:49:05
Modified files:
gcc : ChangeLog reload1.c
Log message:
PR c/13133
* reload1.c (reload): Delete special handling for setjmp.
Patches:
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&r1=2.1803&r2=2.1804
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/reload1.c.diff?cvsroot=gcc&r1=1.412&r2=1.413
--
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13133
^ permalink raw reply [flat|nested] 13+ messages in thread
* [Bug c/13133] Extraneous register-saves triggered by setjmp()
2003-11-19 22:21 [Bug c/13133] New: Extraneous register-saves triggered by setjmp() davidm at hpl dot hp dot com
` (3 preceding siblings ...)
2003-11-21 5:49 ` cvs-commit at gcc dot gnu dot org
@ 2003-11-21 5:53 ` wilson at gcc dot gnu dot org
2003-11-21 15:03 ` charlet at gcc dot gnu dot org
` (6 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: wilson at gcc dot gnu dot org @ 2003-11-21 5:53 UTC (permalink / raw)
To: gcc-bugs
------- Additional Comments From wilson at gcc dot gnu dot org 2003-11-21 05:53 -------
Patch checked in. See this message:
http://gcc.gnu.org/ml/gcc-patches/2003-11/msg01667.html
--
What |Removed |Added
----------------------------------------------------------------------------
Status|ASSIGNED |RESOLVED
Resolution| |FIXED
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13133
^ permalink raw reply [flat|nested] 13+ messages in thread
* [Bug c/13133] Extraneous register-saves triggered by setjmp()
2003-11-19 22:21 [Bug c/13133] New: Extraneous register-saves triggered by setjmp() davidm at hpl dot hp dot com
` (4 preceding siblings ...)
2003-11-21 5:53 ` wilson at gcc dot gnu dot org
@ 2003-11-21 15:03 ` charlet at gcc dot gnu dot org
2003-11-21 19:18 ` wilson at specifixinc dot com
` (5 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: charlet at gcc dot gnu dot org @ 2003-11-21 15:03 UTC (permalink / raw)
To: gcc-bugs
------- Additional Comments From charlet at gcc dot gnu dot org 2003-11-21 15:03 -------
It seems that this change broke all Ada targets that use setjmp for the
exception handling mechanism.
In particular, Ada IA64 builds started behaving in a very unreliable manner
around the date of the change.
If this is the case, seems like a high price to pay for an enhancement.
Arno
--
What |Removed |Added
----------------------------------------------------------------------------
CC| |kenner at vlsi1 dot ultra
| |dot nyu dot edu
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13133
^ permalink raw reply [flat|nested] 13+ messages in thread
* [Bug c/13133] Extraneous register-saves triggered by setjmp()
2003-11-19 22:21 [Bug c/13133] New: Extraneous register-saves triggered by setjmp() davidm at hpl dot hp dot com
` (5 preceding siblings ...)
2003-11-21 15:03 ` charlet at gcc dot gnu dot org
@ 2003-11-21 19:18 ` wilson at specifixinc dot com
2003-11-21 21:46 ` wilson at specifixinc dot com
` (4 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: wilson at specifixinc dot com @ 2003-11-21 19:18 UTC (permalink / raw)
To: gcc-bugs
------- Additional Comments From wilson at specifixinc dot com 2003-11-21 19:18 -------
Subject: Re: Extraneous register-saves triggered by setjmp()
On Fri, 2003-11-21 at 07:03, charlet at gcc dot gnu dot org wrote:
> It seems that this change broke all Ada targets that use setjmp for the
> exception handling mechanism.
There was a message from Andreas Schwab recently that mentioned that GNU
Ada was trying to use the builtin setjmp/longjmp exception handling
mechanism for IA-64. Because of complexities of the IA-64 architecture,
this is very unlikely to work. Ada needs to use the ABI defined
exception handling mechanism instead. This may be why IA-64 Ada is
failing. If there aren't any other targets that are failing, then the
problem may very well be in the Ada front end. Maybe the patch from
Andreas will fix this?
It may be that Ada broke because it was relying on an accidental
misfeature of gcc's setjmp implementation. It is certainly possible
that my patch exposed a latent problem with the Ada front end.
> In particular, Ada IA64 builds started behaving in a very unreliable manner
> around the date of the change.
I can do Ada builds on both my x86 and ia64 linux machines. I will take
a look. I've never run the Ada testsuite though. I will have to look
into how to do that.
> If this is the case, seems like a high price to pay for an enhancement.
This is an necessary fix for a serious performance regression.
--
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13133
^ permalink raw reply [flat|nested] 13+ messages in thread
* [Bug c/13133] Extraneous register-saves triggered by setjmp()
2003-11-19 22:21 [Bug c/13133] New: Extraneous register-saves triggered by setjmp() davidm at hpl dot hp dot com
` (6 preceding siblings ...)
2003-11-21 19:18 ` wilson at specifixinc dot com
@ 2003-11-21 21:46 ` wilson at specifixinc dot com
2003-11-22 0:32 ` wilson at specifixinc dot com
` (3 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: wilson at specifixinc dot com @ 2003-11-21 21:46 UTC (permalink / raw)
To: gcc-bugs
------- Additional Comments From wilson at specifixinc dot com 2003-11-21 21:46 -------
Subject: Re: Extraneous register-saves triggered by setjmp()
On Fri, 2003-11-21 at 07:03, charlet at gcc dot gnu dot org wrote:
> It seems that this change broke all Ada targets that use setjmp for the
> exception handling mechanism.
I got a report of an Ada failure on x86.
FAIL: cd92001
I plan to start with this one, and then look at the IA-64 problems.
--
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13133
^ permalink raw reply [flat|nested] 13+ messages in thread
* [Bug c/13133] Extraneous register-saves triggered by setjmp()
2003-11-19 22:21 [Bug c/13133] New: Extraneous register-saves triggered by setjmp() davidm at hpl dot hp dot com
` (7 preceding siblings ...)
2003-11-21 21:46 ` wilson at specifixinc dot com
@ 2003-11-22 0:32 ` wilson at specifixinc dot com
2003-11-24 8:59 ` segher at kernel dot crashing dot org
` (2 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: wilson at specifixinc dot com @ 2003-11-22 0:32 UTC (permalink / raw)
To: gcc-bugs
------- Additional Comments From wilson at specifixinc dot com 2003-11-22 00:31 -------
Subject: Re: Extraneous register-saves triggered by setjmp()
On Fri, 2003-11-21 at 13:46, wilson at specifixinc dot com wrote:
> I got a report of an Ada failure on x86.
> FAIL: cd92001
> I plan to start with this one, and then look at the IA-64 problems.
I wasn't able to reproduce this problem on my RHL 8 machine. I have a
tree last updated:
Fri Nov 21 05:53:29 UTC 2003
The failing tree was checked out a few hours later, but none of the
following patches look like they could break an Ada build. The bug was
reported against a system running debian unstable i686. I do not have
such a system immediately available. I'll update and double check my
tree, and make another attempt to reproduce this on my RHL8 system. I
have a spare machine I can attempt a debian install on, but that will
take some time.
--
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13133
^ permalink raw reply [flat|nested] 13+ messages in thread
* [Bug c/13133] Extraneous register-saves triggered by setjmp()
2003-11-19 22:21 [Bug c/13133] New: Extraneous register-saves triggered by setjmp() davidm at hpl dot hp dot com
` (8 preceding siblings ...)
2003-11-22 0:32 ` wilson at specifixinc dot com
@ 2003-11-24 8:59 ` segher at kernel dot crashing dot org
2003-12-04 9:49 ` pinskia at gcc dot gnu dot org
2004-01-15 22:40 ` pinskia at gcc dot gnu dot org
11 siblings, 0 replies; 13+ messages in thread
From: segher at kernel dot crashing dot org @ 2003-11-24 8:59 UTC (permalink / raw)
To: gcc-bugs
------- Additional Comments From segher at kernel dot crashing dot org 2003-11-24 08:59 -------
Subject: Re: Extraneous register-saves triggered by setjmp()
pinskia at gcc dot gnu dot org wrote:
> Yes and this happens on PPC and PPC64 also see PR 12817, with altivec the amount saved is huge
> also.
But please note that that PR is about a separate issue; when this is
fixed, PR12817 should not be closed without further investigation.
--
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13133
^ permalink raw reply [flat|nested] 13+ messages in thread
* [Bug c/13133] Extraneous register-saves triggered by setjmp()
2003-11-19 22:21 [Bug c/13133] New: Extraneous register-saves triggered by setjmp() davidm at hpl dot hp dot com
` (9 preceding siblings ...)
2003-11-24 8:59 ` segher at kernel dot crashing dot org
@ 2003-12-04 9:49 ` pinskia at gcc dot gnu dot org
2004-01-15 22:40 ` pinskia at gcc dot gnu dot org
11 siblings, 0 replies; 13+ messages in thread
From: pinskia at gcc dot gnu dot org @ 2003-12-04 9:49 UTC (permalink / raw)
To: gcc-bugs
--
What |Removed |Added
----------------------------------------------------------------------------
Target Milestone|--- |3.4
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13133
^ permalink raw reply [flat|nested] 13+ messages in thread
* [Bug c/13133] Extraneous register-saves triggered by setjmp()
2003-11-19 22:21 [Bug c/13133] New: Extraneous register-saves triggered by setjmp() davidm at hpl dot hp dot com
` (10 preceding siblings ...)
2003-12-04 9:49 ` pinskia at gcc dot gnu dot org
@ 2004-01-15 22:40 ` pinskia at gcc dot gnu dot org
11 siblings, 0 replies; 13+ messages in thread
From: pinskia at gcc dot gnu dot org @ 2004-01-15 22:40 UTC (permalink / raw)
To: gcc-bugs
------- Additional Comments From pinskia at gcc dot gnu dot org 2004-01-15 22:40 -------
*** Bug 13704 has been marked as a duplicate of this bug. ***
--
What |Removed |Added
----------------------------------------------------------------------------
CC| |oneill+gccbugs at cs dot hmc
| |dot edu
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13133
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2004-01-15 22:40 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-11-19 22:21 [Bug c/13133] New: Extraneous register-saves triggered by setjmp() davidm at hpl dot hp dot com
2003-11-19 22:26 ` [Bug c/13133] " pinskia at gcc dot gnu dot org
2003-11-21 5:11 ` wilson at gcc dot gnu dot org
2003-11-21 5:12 ` wilson at gcc dot gnu dot org
2003-11-21 5:49 ` cvs-commit at gcc dot gnu dot org
2003-11-21 5:53 ` wilson at gcc dot gnu dot org
2003-11-21 15:03 ` charlet at gcc dot gnu dot org
2003-11-21 19:18 ` wilson at specifixinc dot com
2003-11-21 21:46 ` wilson at specifixinc dot com
2003-11-22 0:32 ` wilson at specifixinc dot com
2003-11-24 8:59 ` segher at kernel dot crashing dot org
2003-12-04 9:49 ` pinskia at gcc dot gnu dot org
2004-01-15 22:40 ` pinskia at gcc dot gnu dot org
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).