The testcase I'll attach is miscompiled on s390x with -m64 -O2 -mtune=z990 or -m64 -O2 -mtune=z9-109. The test function needs a base reg (so %r13 is loaded early and during flow2 the %r13 references actually make it into the assembler). But, during reload a TImode pseudo is reloaded into TI %r12 (and therefore clobbers %r13 too) and the testcase segfaults.
Created attachment 11638 [details] pr27959.c
Works just fine in GCC 3.4.x (in that case with -O2 -mtune=z990 which fails in 4.1.x as well) and works on the trunk too (but it is unclear whether that's just because reload chooses different registers by accident or if the problem has been really fixed).
On s390 we use a trick to make the literal pool base register available "on demand". It is defined as eliminable register which can be eliminated to itself with offset 0. When a reload round finds a r13 (literal pool base) it asks the back end whether it can be eliminated and the back end says no. So reload throws any pseudos out of r13 and marks it as bad_spill_regs_global hence it won't be used as a reload register. In your example there is no literal pool reference when entering reload. So the initial elimination step marks r13 as eliminable and therefore free to be used in reloads and it actually is used in a reload. In the second round reload forces a constant into the literal pool what creates a literal pool reference. When update_eliminables is called r13 is marked as cant_eliminate and the respective bit in bad_spill_regs_global is set. So far so good. Unfortunately reload seems to think that registers which were once good to be used in reloads will be good for future reloads as well - thats my impression at least. The bitmap used_spill_regs is not reset between the reload rounds. used_spill_regs is used in finish_spills to recalculate the spill_regs array which then contains r13 since it was used as reload reg in the first round. The following patch deletes all registers which are recognized by update_eliminables as eliminable_previous but cant_eliminate now from the used_spill_regs bitmap and fixes your testcase. Since reload is always a bit dodgy and tends to be unpredictable I would be interested in Ulrichs opinion about the patch. He knows much better whats going on in reload. So Ulrich do think this makes sense? Index: gcc/reload1.c =================================================================== *** gcc/reload1.c.orig 2006-06-09 13:12:39.000000000 +0200 --- gcc/reload1.c 2006-06-09 13:14:54.000000000 +0200 *************** reload (rtx first, int global) *** 987,992 **** --- 987,994 ---- HARD_REG_SET to_spill; CLEAR_HARD_REG_SET (to_spill); update_eliminables (&to_spill); + AND_COMPL_HARD_REG_SET(used_spill_regs, to_spill); + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) if (TEST_HARD_REG_BIT (to_spill, i)) {
Subject: Bug 27959 Author: krebbel Date: Wed Jun 14 09:24:44 2006 New Revision: 114636 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=114636 Log: 2006-06-14 Andreas Krebbel <krebbel1@de.ibm.com> PR middle-end/27959 * reload1.c (reload): Remove registers returned by update_eliminables from used_spill_regs. 2006-06-14 Andreas Krebbel <krebbel1@de.ibm.com> PR middle-end/27959 * gcc.dg/pr27959.c: New testcase. Added: branches/gcc-4_1-branch/gcc/testsuite/gcc.dg/pr27959.c Modified: branches/gcc-4_1-branch/gcc/ChangeLog branches/gcc-4_1-branch/gcc/reload1.c branches/gcc-4_1-branch/gcc/testsuite/ChangeLog
Subject: Bug 27959 Author: krebbel Date: Wed Jun 14 14:19:54 2006 New Revision: 114640 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=114640 Log: 2006-06-14 Andreas Krebbel <krebbel1@de.ibm.com> PR middle-end/27959 * reload1.c (reload): Remove registers returned by update_eliminables from used_spill_regs. 2006-06-14 Andreas Krebbel <krebbel1@de.ibm.com> PR middle-end/27959 * gcc.dg/pr27959.c: New testcase. Added: trunk/gcc/testsuite/gcc.dg/pr27959.c Modified: trunk/gcc/ChangeLog trunk/gcc/reload1.c trunk/gcc/testsuite/ChangeLog
Patch committed to mainline and gcc 4.1 branch.