This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
Re: possible bug in global allocation phase
- From: Jim Wilson <wilson at specifixinc dot com>
- To: Heiko Panther <heiko dot panther at web dot de>
- Cc: gcc-bugs at gcc dot gnu dot org, wilson at tuliptree dot org
- Date: Wed, 22 Oct 2003 13:00:25 -0700
- Subject: Re: possible bug in global allocation phase
- References: <3F958BB2.8070207@web.de>
Heiko Panther wrote:
TEST_HARD_REG_BIT(used, 32) returns 0 and thus r32 is believed to be
available. This happens because "used" is of type HARD_REG_SET.
HARD_REG_SET is a 32 bit integer type, so a test for nonexisting bits
will produce wrong results.
Yes, this looks like a legitimate bug to me. TEST_HARD_REG_BIT provokes
undefined/implementation defined behaviour if given an out-of-range
register number. We can get different behaviour for different targets here.
I see 3 uses of this idiom in global.c, 5 in reload.c, 5 in reload1.c,
and one in local.c. And that is just a quick check, I haven't tried
using grep yet, or trying to verify the count.
I think we need to fix all such occurences by adding a check against
FIRST_PSEUDO_REGISTER.
I have attached an incomplete example patch showing what I propose.
--
Jim Wilson, GNU Tools Support, http://www.SpecifixInc.com
Index: global.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/global.c,v
retrieving revision 1.94
diff -p -r1.94 global.c
*** global.c 19 Jul 2003 14:47:06 -0000 1.94
--- global.c 22 Oct 2003 19:54:03 -0000
*************** find_reg (int num, HARD_REG_SET losers,
*** 1051,1056 ****
--- 1051,1057 ----
int lim = regno + HARD_REGNO_NREGS (regno, mode);
for (j = regno + 1;
(j < lim
+ && j < FIRST_PSEUDO_REGISTER
&& ! TEST_HARD_REG_BIT (used, j));
j++);
if (j == lim)
*************** find_reg (int num, HARD_REG_SET losers,
*** 1098,1103 ****
--- 1099,1105 ----
int lim = i + HARD_REGNO_NREGS (i, mode);
for (j = i + 1;
(j < lim
+ && j < FIRST_PSEUDO_REGISTER
&& ! TEST_HARD_REG_BIT (used, j)
&& (REGNO_REG_CLASS (j)
== REGNO_REG_CLASS (best_reg + (j - i))
*************** find_reg (int num, HARD_REG_SET losers,
*** 1137,1142 ****
--- 1139,1145 ----
int lim = i + HARD_REGNO_NREGS (i, mode);
for (j = i + 1;
(j < lim
+ && j < FIRST_PSEUDO_REGISTER
&& ! TEST_HARD_REG_BIT (used, j)
&& (REGNO_REG_CLASS (j)
== REGNO_REG_CLASS (best_reg + (j - i))