This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: Ongoing problems with resource.c changes
- To: Jeffrey A Law <law at cygnus dot com>
- Subject: Re: Ongoing problems with resource.c changes
- From: Richard Henderson <rth at cygnus dot com>
- Date: Mon, 1 Nov 1999 19:42:15 -0800
- Cc: gcc at gcc dot gnu dot org
- References: <6422.941511457@upchuck>
On Mon, Nov 01, 1999 at 07:57:37PM -0700, Jeffrey A Law wrote:
> Apparently the ADDR_VEC insn isn't actually within the bb->head/end bounds
> for its basic block and thus compute_bb_for_insn never initializes an entry
> in basic_block_for_insn for the ADDR_VEC.
Give this a shot -- I've just fired off a Sparc bootstrap. I'll
find out if it worked after dinner.
This is Jan's patch with minor modifications to cope with the above.
r~
Index: recog.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/recog.c,v
retrieving revision 1.51
diff -c -p -d -r1.51 recog.c
*** recog.c 1999/11/01 01:11:21 1.51
--- recog.c 1999/11/02 03:40:22
*************** peephole2_optimize (dump_file)
*** 2719,2725 ****
way we'll not need to keep searching forward from the beginning of
basic blocks to find register life info. */
! init_resource_info (NULL);
blocks = sbitmap_alloc (n_basic_blocks);
sbitmap_zero (blocks);
--- 2719,2725 ----
way we'll not need to keep searching forward from the beginning of
basic blocks to find register life info. */
! init_resource_info (NULL, 1);
blocks = sbitmap_alloc (n_basic_blocks);
sbitmap_zero (blocks);
Index: reorg.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/reorg.c,v
retrieving revision 1.41
diff -c -p -d -r1.41 reorg.c
*** reorg.c 1999/11/01 23:19:44 1.41
--- reorg.c 1999/11/02 03:40:22
*************** dbr_schedule (first, file)
*** 3567,3573 ****
redirect_jump (insn, target);
}
! init_resource_info (epilogue_insn);
/* Show we haven't computed an end-of-function label yet. */
end_of_function_label = 0;
--- 3567,3573 ----
redirect_jump (insn, target);
}
! init_resource_info (epilogue_insn, 0);
/* Show we haven't computed an end-of-function label yet. */
end_of_function_label = 0;
Index: resource.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/resource.c,v
retrieving revision 1.19
diff -c -p -d -r1.19 resource.c
*** resource.c 1999/10/28 19:30:02 1.19
--- resource.c 1999/11/02 03:40:22
*************** static HARD_REG_SET current_live_regs;
*** 72,83 ****
--- 72,87 ----
Also only used by the next two functions. */
static HARD_REG_SET pending_dead_regs;
+
+ /* True when REG_DEAD notes and the CFG may be trusted. */
+ static int cfg_is_reliable;
static void update_live_status PROTO ((rtx, rtx, void *));
static rtx next_insn_no_annul PROTO ((rtx));
static rtx find_dead_or_set_registers PROTO ((rtx, struct resources*,
rtx*, int, struct resources,
struct resources));
+ static int resource_bb_for_insn PROTO ((rtx));
/* Utility function called from mark_target_live_regs via note_stores.
It deadens any CLOBBERed registers and livens any SET registers. */
*************** mark_set_resources (x, res, in_dest, inc
*** 750,755 ****
--- 754,804 ----
}
}
+ static int
+ resource_bb_for_insn (insn)
+ rtx insn;
+ {
+ basic_block bb = NULL;
+
+ /* ??? Special case for ADDR_VEC, which isn't strictly inside a
+ block at all, but is really part of the previous block. */
+ if (GET_CODE (insn) == JUMP_INSN
+ && (GET_CODE (PATTERN (insn)) == ADDR_VEC
+ || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC))
+ insn = prev_real_insn (insn);
+
+ if (INSN_UID (insn) < (int) VARRAY_SIZE (basic_block_for_insn))
+ bb = BLOCK_FOR_INSN (insn);
+
+ /* We've hit some newly created insn. Search backward for known
+ insn; we ought to hit at least BASIC_BLOCK note when CFG is
+ not corrupt. */
+ if (bb == NULL)
+ {
+ insn = PREV_INSN (insn);
+ while (GET_CODE (insn) != CODE_LABEL
+ && GET_CODE (insn) != JUMP_INSN)
+ {
+ if (INSN_UID (insn) < (int) VARRAY_SIZE (basic_block_for_insn))
+ {
+ bb = BLOCK_FOR_INSN (insn);
+ break;
+ }
+ insn = PREV_INSN (insn);
+ }
+ }
+
+ if (bb != NULL)
+ {
+ set_block_for_insn (insn, bb);
+ return bb->index;
+ }
+ else if (cfg_is_reliable)
+ abort ();
+ else
+ return -1;
+ }
+
/* Set the resources that are live at TARGET.
If TARGET is zero, we refer to the end of the current function and can
*************** mark_set_resources (x, res, in_dest, inc
*** 760,765 ****
--- 809,818 ----
reload and jump optimization, which occur after the basic block information
has been computed.
+ In case CFG_IS_RELIABLE is nonzero, we expect life information to
+ be correct. This can be used for example by peephole2 pass done
+ after flow2.
+
Accordingly, we proceed as follows::
We find the previous BARRIER and look at all immediately following labels
*************** mark_set_resources (x, res, in_dest, inc
*** 778,783 ****
--- 831,837 ----
updated by such things as find_equiv_reg. So keep track of registers
marked as dead that haven't been assigned to, and mark them dead at the
next CODE_LABEL since reload and jump won't propagate values across labels.
+ In case CFG_IS_RELIABLE, believe to REG_DEAD notes.
If we cannot find the start of a basic block (should be a very rare
case, if it can happen at all), mark everything as potentially live.
*************** mark_target_live_regs (insns, target, re
*** 832,840 ****
b = tinfo->block;
}
! if (b == -1
! && INSN_UID (target) < (int) VARRAY_SIZE (basic_block_for_insn))
! b = BLOCK_NUM (target);
if (target_hash_table != NULL)
{
--- 886,893 ----
b = tinfo->block;
}
! if (b == -1)
! b = resource_bb_for_insn (target);
if (target_hash_table != NULL)
{
*************** mark_target_live_regs (insns, target, re
*** 868,897 ****
if (b != -1)
{
regset regs_live = BASIC_BLOCK (b)->global_live_at_start;
- int j;
- int regno;
rtx start_insn, stop_insn;
! /* Compute hard regs live at start of block -- this is the real hard regs
! marked live, plus live pseudo regs that have been renumbered to
! hard regs. */
REG_SET_TO_HARD_REG_SET (current_live_regs, regs_live);
- EXECUTE_IF_SET_IN_REG_SET
- (regs_live, FIRST_PSEUDO_REGISTER, i,
- {
- if ((regno = reg_renumber[i]) >= 0)
- for (j = regno;
- j < regno + HARD_REGNO_NREGS (regno,
- PSEUDO_REGNO_MODE (i));
- j++)
- SET_HARD_REG_BIT (current_live_regs, j);
- });
-
/* Get starting and ending insn, handling the case where each might
be a SEQUENCE. */
! start_insn = (b == 0 ? insns : BLOCK_HEAD (b));
stop_insn = target;
if (GET_CODE (start_insn) == INSN
--- 921,943 ----
if (b != -1)
{
regset regs_live = BASIC_BLOCK (b)->global_live_at_start;
rtx start_insn, stop_insn;
! /* Compute hard regs live at start of block */
REG_SET_TO_HARD_REG_SET (current_live_regs, regs_live);
/* Get starting and ending insn, handling the case where each might
be a SEQUENCE. */
! if (cfg_is_reliable)
! {
! start_insn = BLOCK_HEAD (b);
! if (GET_CODE (start_insn) == CODE_LABEL)
! start_insn = NEXT_INSN (start_insn);
! }
! else
! start_insn = (b == 0 ? insns : BLOCK_HEAD (b));
!
stop_insn = target;
if (GET_CODE (start_insn) == INSN
*************** mark_target_live_regs (insns, target, re
*** 971,977 ****
GET_MODE (XEXP (link, 0))));
for (i = first_regno; i < last_regno; i++)
! SET_HARD_REG_BIT (pending_dead_regs, i);
}
note_stores (PATTERN (real_insn), update_live_status, NULL);
--- 1017,1028 ----
GET_MODE (XEXP (link, 0))));
for (i = first_regno; i < last_regno; i++)
! {
! if (cfg_is_reliable)
! CLEAR_HARD_REG_BIT (current_live_regs, i);
! else
! SET_HARD_REG_BIT (pending_dead_regs, i);
! }
}
note_stores (PATTERN (real_insn), update_live_status, NULL);
*************** mark_target_live_regs (insns, target, re
*** 996,1001 ****
--- 1047,1054 ----
else if (GET_CODE (real_insn) == CODE_LABEL)
{
+ if (cfg_is_reliable)
+ abort();
/* A label clobbers the pending dead registers since neither
reload nor jump will propagate a value across a label. */
AND_COMPL_HARD_REG_SET (current_live_regs, pending_dead_regs);
*************** mark_target_live_regs (insns, target, re
*** 1021,1061 ****
/* We didn't find the start of a basic block. Assume everything
in use. This should happen only extremely rarely. */
SET_HARD_REG_SET (res->regs);
-
- CLEAR_RESOURCE (&set);
- CLEAR_RESOURCE (&needed);
-
- jump_insn = find_dead_or_set_registers (target, res, &jump_target, 0,
- set, needed);
! /* If we hit an unconditional branch, we have another way of finding out
! what is live: we can see what is live at the branch target and include
! anything used but not set before the branch. The only things that are
! live are those that are live using the above test and the test below. */
! if (jump_insn)
{
- struct resources new_resources;
- rtx stop_insn = next_active_insn (jump_insn);
-
- mark_target_live_regs (insns, next_active_insn (jump_target),
- &new_resources);
CLEAR_RESOURCE (&set);
CLEAR_RESOURCE (&needed);
! /* Include JUMP_INSN in the needed registers. */
! for (insn = target; insn != stop_insn; insn = next_active_insn (insn))
{
! mark_referenced_resources (insn, &needed, 1);
! COPY_HARD_REG_SET (scratch, needed.regs);
! AND_COMPL_HARD_REG_SET (scratch, set.regs);
! IOR_HARD_REG_SET (new_resources.regs, scratch);
! mark_set_resources (insn, &set, 0, 1);
! }
! AND_HARD_REG_SET (res->regs, new_resources.regs);
}
if (tinfo != NULL)
--- 1074,1127 ----
/* We didn't find the start of a basic block. Assume everything
in use. This should happen only extremely rarely. */
SET_HARD_REG_SET (res->regs);
! /* With reliable flow info we ought to get accurate info by checking
! the basic block. */
! if (!cfg_is_reliable)
{
CLEAR_RESOURCE (&set);
CLEAR_RESOURCE (&needed);
! jump_insn = find_dead_or_set_registers (target, res, &jump_target, 0,
! set, needed);
!
! /* If we hit an unconditional branch, we have another way of finding out
! what is live: we can see what is live at the branch target and include
! anything used but not set before the branch. The only things that are
! live are those that are live using the above test and the test below. */
!
! if (jump_insn)
{
! struct resources new_resources;
! rtx stop_insn = next_active_insn (jump_insn);
! mark_target_live_regs (insns, next_active_insn (jump_target),
! &new_resources);
! CLEAR_RESOURCE (&set);
! CLEAR_RESOURCE (&needed);
! /* Include JUMP_INSN in the needed registers. */
! for (insn = target; insn != stop_insn; insn = next_active_insn (insn))
! {
! mark_referenced_resources (insn, &needed, 1);
! COPY_HARD_REG_SET (scratch, needed.regs);
! AND_COMPL_HARD_REG_SET (scratch, set.regs);
! IOR_HARD_REG_SET (new_resources.regs, scratch);
!
! mark_set_resources (insn, &set, 0, 1);
! }
!
! if (cfg_is_reliable)
! {
! GO_IF_HARD_REG_SUBSET (res->regs, new_resources.regs, win);
! abort();
! win:
! }
!
! AND_HARD_REG_SET (res->regs, new_resources.regs);
! }
}
if (tinfo != NULL)
*************** mark_target_live_regs (insns, target, re
*** 1068,1078 ****
This should be invoked before the first call to mark_target_live_regs. */
void
! init_resource_info (epilogue_insn)
rtx epilogue_insn;
{
int i;
/* Indicate what resources are required to be valid at the end of the current
function. The condition code never is and memory always is. If the
frame pointer is needed, it is and so is the stack pointer unless
--- 1134,1146 ----
This should be invoked before the first call to mark_target_live_regs. */
void
! init_resource_info (epilogue_insn, reliable)
rtx epilogue_insn;
+ int reliable;
{
int i;
+ cfg_is_reliable = reliable;
/* Indicate what resources are required to be valid at the end of the current
function. The condition code never is and memory always is. If the
frame pointer is needed, it is and so is the stack pointer unless
*************** void
*** 1187,1194 ****
incr_ticks_for_insn (insn)
rtx insn;
{
! int b = BLOCK_NUM (insn);
!
if (b != -1)
bb_ticks[b]++;
}
--- 1255,1261 ----
incr_ticks_for_insn (insn)
rtx insn;
{
! int b = resource_bb_for_insn (insn);
if (b != -1)
bb_ticks[b]++;
}
Index: resource.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/resource.h,v
retrieving revision 1.4
diff -c -p -d -r1.4 resource.h
*** resource.h 1999/10/05 05:00:55 1.4
--- resource.h 1999/11/02 03:40:22
*************** extern void mark_referenced_resources PR
*** 40,46 ****
extern void clear_hashed_info_for_insn PROTO((rtx));
extern void incr_ticks_for_insn PROTO((rtx));
extern void mark_end_of_function_resources PROTO ((rtx, int));
! extern void init_resource_info PROTO((rtx));
extern void free_resource_info PROTO((void));
extern rtx find_free_register PROTO((rtx, rtx, const char *, int,
HARD_REG_SET *));
--- 40,46 ----
extern void clear_hashed_info_for_insn PROTO((rtx));
extern void incr_ticks_for_insn PROTO((rtx));
extern void mark_end_of_function_resources PROTO ((rtx, int));
! extern void init_resource_info PROTO((rtx, int));
extern void free_resource_info PROTO((void));
extern rtx find_free_register PROTO((rtx, rtx, const char *, int,
HARD_REG_SET *));