This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
PATCH: find_dead_or_set_registers vs. EH
- To: gcc-patches at gcc dot gnu dot org
- Subject: PATCH: find_dead_or_set_registers vs. EH
- From: Mark Mitchell <mark at codesourcery dot com>
- Date: Thu, 25 May 2000 10:56:47 -0700
- Organization: CodeSourcery, LLC
The function mark_target_regs_live is supposed to figure out which
hard registers are live at a given instruction. The algorithm used
there is pretty obscure. First, it scans forward from some earlier
basic block. Then, it scans past the instruction, following jumps.
That second scan is broken because it assumes that, in the absence of
a jump, there is no control-flow change. That's false when using
exceptions. This patch fixes the bug.
But, there's a more global question. Why use this obscure algorithm
when the simple:
- Find the end of the basic block
- Take the set of registers known to be live there
- Work backwards, marking used registers as live, and set registers
as dead
would seem to work just fine?
If nobody objects, I'll probably convert this code to use the simpler
algorithm, based on Alex's code in conflict_graph_compute. (That code
deals with pseudos, and depends on SSA form, but the basic ideas are
applicable.)
Thanks,
--
Mark Mitchell mark@codesourcery.com
CodeSourcery, LLC http://www.codesourcery.com
2000-05-25 Mark Mitchell <mark@codesourcery.com>
* except.h (can_throw): Declare it.
* except.c (can_throw): Give it external linkage.
* resource.c (find_dead_or_set_registers): Use can_throw.
Index: except.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/except.c,v
retrieving revision 1.130
diff -c -p -r1.130 except.c
*** except.c 2000/05/20 19:45:33 1.130
--- except.c 2000/05/25 07:57:06
*************** static void start_dynamic_cleanup PARAMS
*** 463,469 ****
static void start_dynamic_handler PARAMS ((void));
static void expand_rethrow PARAMS ((rtx));
static void output_exception_table_entry PARAMS ((FILE *, int));
- static int can_throw PARAMS ((rtx));
static rtx scan_region PARAMS ((rtx, int, int *));
static void eh_regs PARAMS ((rtx *, rtx *, rtx *, int));
static void set_insn_eh_region PARAMS ((rtx *, int));
--- 463,468 ----
*************** free_eh_status (f)
*** 2643,2654 ****
}
/* This section is for the exception handling specific optimization
! pass. First are the internal routines, and then the main
! optimization pass. */
/* Determine if the given INSN can throw an exception. */
! static int
can_throw (insn)
rtx insn;
{
--- 2642,2652 ----
}
/* This section is for the exception handling specific optimization
! pass. */
/* Determine if the given INSN can throw an exception. */
! int
can_throw (insn)
rtx insn;
{
Index: except.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/except.h,v
retrieving revision 1.39
diff -c -p -r1.39 except.h
*** except.h 2000/03/19 18:25:24 1.39
--- except.h 2000/05/25 07:57:06
*************** extern struct label_node *outer_context_
*** 430,435 ****
--- 430,439 ----
extern rtx exception_handler_labels;
+ /* Determine if the given INSN can throw an exception. */
+
+ extern int can_throw PARAMS ((rtx));
+
/* Return nonzero if nothing in this function can throw. */
extern int nothrow_function_p PARAMS ((void));
Index: resource.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/resource.c,v
retrieving revision 1.28
diff -c -p -r1.28 resource.c
*** resource.c 2000/03/27 21:50:15 1.28
--- resource.c 2000/05/25 07:57:13
*************** find_dead_or_set_registers (target, res,
*** 422,427 ****
--- 422,435 ----
rtx this_jump_insn = insn;
next = NEXT_INSN (insn);
+
+ /* If this instruction can throw an exception, then we don't
+ know where we might end up next. That means that we have to
+ assume that whatever we have already marked as live really is
+ live. */
+ if (can_throw (insn))
+ break;
+
switch (GET_CODE (insn))
{
case CODE_LABEL: