This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PING] Loop invariant motion and call-saved eh regs
- From: Andreas Krebbel <krebbel1 at de dot ibm dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 25 Aug 2006 13:12:53 +0200
- Subject: [PING] Loop invariant motion and call-saved eh regs
Hello,
the following patch fixes a problem for plattforms where
call-saved registers are used for exception handling (s390 and sparc).
http://gcc.gnu.org/ml/gcc-patches/2006-07/msg01060.html
See: http://gcc.gnu.org/ml/gcc-patches/2006-07/msg00767.html
for a description of the problem.
The proposed patch works around the real problem. A better fix would get
rid of the CLOBBERs issued for eh regs completely as in:
http://gcc.gnu.org/ml/gcc-patches/2006-07/msg00850.html
Unfortunately I couldn't get this working properly by now. There occur
problems when you have a throw in a catch block. In this case (and without
the eh reg CLOBBERs) flow considers the eh regs not to be altered between the use in
the second catch block and use in the throw/catch block. So a copy of an eh
reg created in the throw/catch block is happily used within the second catch
block.
I think what is missing is flow to be aware of eh regs being set on eh edges.
So neither the throw nor the catch block are responsible for the change of
the eh regs it is a property of the eh edge between the blocks!
I've tried to teach flow that with the attached patch but got a nasty miscompile
of libstdc++ which a havn't tracked down yet. Maybe I can get this working
for gcc 4.2. Otherwise please consider to accept the workaround patch although
it is not the best solution.
Bye,
-Andreas-
Index: gcc/flow.c
===================================================================
*** gcc/flow.c.orig 2006-08-08 10:28:32.000000000 +0200
--- gcc/flow.c 2006-08-10 11:14:07.000000000 +0200
*************** static void
*** 1029,1035 ****
calculate_global_regs_live (sbitmap blocks_in, sbitmap blocks_out, int flags)
{
basic_block *queue, *qhead, *qtail, *qend, bb;
! regset tmp, new_live_at_end, invalidated_by_call;
regset registers_made_dead;
bool failure_strategy_required = false;
int *block_accesses;
--- 1029,1035 ----
calculate_global_regs_live (sbitmap blocks_in, sbitmap blocks_out, int flags)
{
basic_block *queue, *qhead, *qtail, *qend, bb;
! regset tmp, new_live_at_end, invalidated_by_call, invalidated_by_eh_edge;
regset registers_made_dead;
bool failure_strategy_required = false;
int *block_accesses;
*************** calculate_global_regs_live (sbitmap bloc
*** 1054,1065 ****
--- 1054,1075 ----
new_live_at_end = ALLOC_REG_SET (®_obstack);
invalidated_by_call = ALLOC_REG_SET (®_obstack);
registers_made_dead = ALLOC_REG_SET (®_obstack);
+ invalidated_by_eh_edge = ALLOC_REG_SET (®_obstack);
/* Inconveniently, this is only readily available in hard reg set form. */
for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
if (TEST_HARD_REG_BIT (regs_invalidated_by_call, i))
SET_REGNO_REG_SET (invalidated_by_call, i);
+ /* The exception handling registes die at eh edges. */
+ for (i = 0; ; ++i)
+ {
+ unsigned regno = EH_RETURN_DATA_REGNO (i);
+ if (regno == INVALID_REGNUM)
+ break;
+ SET_REGNO_REG_SET (invalidated_by_eh_edge, regno);
+ }
+
/* Allocate space for the sets of local properties. */
local_sets = XCNEWVEC (bitmap, last_basic_block);
cond_local_sets = XCNEWVEC (bitmap, last_basic_block);
*************** calculate_global_regs_live (sbitmap bloc
*** 1189,1197 ****
/* ??? Abnormal call edges ignored for the moment, as this gets
confused by sibling call edges, which crashes reg-stack. */
if (e->flags & EDGE_EH)
! bitmap_ior_and_compl_into (new_live_at_end,
! sb->il.rtl->global_live_at_start,
! invalidated_by_call);
else
IOR_REG_SET (new_live_at_end, sb->il.rtl->global_live_at_start);
--- 1199,1210 ----
/* ??? Abnormal call edges ignored for the moment, as this gets
confused by sibling call edges, which crashes reg-stack. */
if (e->flags & EDGE_EH)
! {
! bitmap_ior_and_compl_into (new_live_at_end,
! sb->il.rtl->global_live_at_start,
! invalidated_by_call);
! AND_COMPL_REG_SET (new_live_at_end, invalidated_by_eh_edge);
! }
else
IOR_REG_SET (new_live_at_end, sb->il.rtl->global_live_at_start);