This is the mail archive of the
mailing list for the GCC project.
[RFC] Problem with EH regs in global register allocation
- From: "Andreas Krebbel" <Andreas dot Krebbel at de dot ibm dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: matz at suse dot de
- Date: Thu, 13 Dec 2007 19:22:25 +0100
- Subject: [RFC] Problem with EH regs in global register allocation
on s390x I currently see a failure of the hash_data_map_rand testcase
of the libstdc++ testsuite when compiling with -march=z9-ec.
It looks to be related to greg not handling eh regs properly.
Last year I've added a piece of code to global_conflicts in order to
record conflicts between the eh regs and any live pseudo for basic
blocks with an eh edge:
These conflicts are properly recorded also for that testcase. I see
in the greg dump (on s390 r6, r7, r8 and r9 are used for eh):
roc adding 46<=>9
and also the dump done later in greg confirms this:
;; 46 conflicts: 47 50 51 48 137 52 59 60 61 62 79 143 142 99 84 104
102 101 89 86 159 90 110 106 103 83 72 70 71 44 68 66 67 43 75 65 63
78 129 128 157 5 4 53 0 1 2 3 4 5 6 7 8 9 10 12 14 16 17 18 19 20 21
but unfortunately the code in find_reg (global.c:1187) starting with:
/* If we haven't succeeded yet,
see if some hard reg that conflicts with us
was utilized poorly by local-alloc.
If so, kick out the regs that were put there by local-alloc
so we can use it instead. */
if (best_reg < 0 && !retrying
/* Let's not bother with multi-reg allocnos. */
&& allocno[num].size == 1
&& REG_BASIC_BLOCK (allocno[num].reg) == REG_BLOCK_GLOBAL)
finds out that r9 would be the best choice for r46 and reassigns r9 to
r46 assuming that all former users of r9 can be referred to a stack
Regno 9 better for global 46...
But this is of course not possible if r9 is set on an eh edge.
As a quick hack I've tried the attached patch which seems to fix the
problem. But this is overly pessimistic since we should only avoid
using the hard reg if it is really used on an eh edge.
Unfortunately the information that the conflict with the hard reg was
added due to its use on an eh edge is lost. In find_reg we only have
the hard_reg_conflicts bitmap which doesn't tell us anything about the
reason of the conflict.
*** gcc/global.c.orig 2007-11-21 10:49:17.000000000 +0100
--- gcc/global.c 2007-12-13 19:10:45.000000000 +0100
*************** along with GCC; see the file COPYING3.
*** 42,47 ****
--- 42,48 ----
+ #include "except.h"
/* This pass of the compiler performs global register allocation.
It assigns hard register numbers to all the pseudo registers
*************** find_reg (int num, HARD_REG_SET losers,
*** 1202,1207 ****
--- 1203,1220 ----
int regno = i;
+ #ifdef EH_RETURN_DATA_REGNO
+ if (current_function_has_exception_handlers ())
+ bool is_eh_reg = false;
+ unsigned int j;
+ for (j = 0; EH_RETURN_DATA_REGNO (j) != INVALID_REGNUM; j++)
+ if (EH_RETURN_DATA_REGNO (j) == (unsigned int)regno)
+ is_eh_reg = true;
+ if (is_eh_reg)
if (local_reg_n_refs[regno] != 0
/* Don't use a reg no good for this pseudo. */
&& ! TEST_HARD_REG_BIT (used2, regno)