summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/flow.c
diff options
context:
space:
mode:
authorkan <kan@FreeBSD.org>2004-07-28 03:11:36 +0000
committerkan <kan@FreeBSD.org>2004-07-28 03:11:36 +0000
commit5e00ec74d8ce58f99801200d4d3d0412c7cc1b28 (patch)
tree052f4bb635f2bea2c5e350bd60c902be100a0d1e /contrib/gcc/flow.c
parent87b8398a7d9f9bf0e28bbcd54a4fc27db2125f38 (diff)
downloadFreeBSD-src-5e00ec74d8ce58f99801200d4d3d0412c7cc1b28.zip
FreeBSD-src-5e00ec74d8ce58f99801200d4d3d0412c7cc1b28.tar.gz
Gcc 3.4.2 20040728.
Diffstat (limited to 'contrib/gcc/flow.c')
-rw-r--r--contrib/gcc/flow.c753
1 files changed, 351 insertions, 402 deletions
diff --git a/contrib/gcc/flow.c b/contrib/gcc/flow.c
index 7882b25..90bc5f8 100644
--- a/contrib/gcc/flow.c
+++ b/contrib/gcc/flow.c
@@ -1,6 +1,6 @@
/* Data flow analysis for GNU compiler.
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
This file is part of GCC.
@@ -120,6 +120,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "tree.h"
#include "rtl.h"
#include "tm_p.h"
@@ -134,20 +136,11 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "toplev.h"
#include "recog.h"
#include "expr.h"
-#include "ssa.h"
#include "timevar.h"
#include "obstack.h"
#include "splay-tree.h"
-/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
- the stack pointer does not matter. The value is tested only in
- functions that have frame pointers.
- No definition is equivalent to always zero. */
-#ifndef EXIT_IGNORE_STACK
-#define EXIT_IGNORE_STACK 0
-#endif
-
#ifndef HAVE_epilogue
#define HAVE_epilogue 0
#endif
@@ -158,9 +151,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#define HAVE_sibcall_epilogue 0
#endif
-#ifndef LOCAL_REGNO
-#define LOCAL_REGNO(REGNO) 0
-#endif
#ifndef EPILOGUE_USES
#define EPILOGUE_USES(REGNO) 0
#endif
@@ -204,7 +194,7 @@ rtx regs_may_share;
/* Callback that determines if it's ok for a function to have no
noreturn attribute. */
-int (*lang_missing_noreturn_ok_p) PARAMS ((tree));
+int (*lang_missing_noreturn_ok_p) (tree);
/* Set of registers that may be eliminable. These are handled specially
in updating regs_ever_live. */
@@ -272,7 +262,7 @@ struct propagate_block_info
/* Nonzero if the value of CC0 is live. */
int cc0_live;
- /* Flags controling the set of information propagate_block collects. */
+ /* Flags controlling the set of information propagate_block collects. */
int flags;
};
@@ -284,65 +274,52 @@ static int ndead;
#define MAX_MEM_SET_LIST_LEN 100
/* Forward declarations */
-static int verify_wide_reg_1 PARAMS ((rtx *, void *));
-static void verify_wide_reg PARAMS ((int, basic_block));
-static void verify_local_live_at_start PARAMS ((regset, basic_block));
-static void notice_stack_pointer_modification_1 PARAMS ((rtx, rtx, void *));
-static void notice_stack_pointer_modification PARAMS ((rtx));
-static void mark_reg PARAMS ((rtx, void *));
-static void mark_regs_live_at_end PARAMS ((regset));
-static int set_phi_alternative_reg PARAMS ((rtx, int, int, void *));
-static void calculate_global_regs_live PARAMS ((sbitmap, sbitmap, int));
-static void propagate_block_delete_insn PARAMS ((rtx));
-static rtx propagate_block_delete_libcall PARAMS ((rtx, rtx));
-static int insn_dead_p PARAMS ((struct propagate_block_info *,
- rtx, int, rtx));
-static int libcall_dead_p PARAMS ((struct propagate_block_info *,
- rtx, rtx));
-static void mark_set_regs PARAMS ((struct propagate_block_info *,
- rtx, rtx));
-static void mark_set_1 PARAMS ((struct propagate_block_info *,
- enum rtx_code, rtx, rtx,
- rtx, int));
-static int find_regno_partial PARAMS ((rtx *, void *));
+static int verify_wide_reg_1 (rtx *, void *);
+static void verify_wide_reg (int, basic_block);
+static void verify_local_live_at_start (regset, basic_block);
+static void notice_stack_pointer_modification_1 (rtx, rtx, void *);
+static void notice_stack_pointer_modification (rtx);
+static void mark_reg (rtx, void *);
+static void mark_regs_live_at_end (regset);
+static void calculate_global_regs_live (sbitmap, sbitmap, int);
+static void propagate_block_delete_insn (rtx);
+static rtx propagate_block_delete_libcall (rtx, rtx);
+static int insn_dead_p (struct propagate_block_info *, rtx, int, rtx);
+static int libcall_dead_p (struct propagate_block_info *, rtx, rtx);
+static void mark_set_regs (struct propagate_block_info *, rtx, rtx);
+static void mark_set_1 (struct propagate_block_info *, enum rtx_code, rtx,
+ rtx, rtx, int);
+static int find_regno_partial (rtx *, void *);
#ifdef HAVE_conditional_execution
-static int mark_regno_cond_dead PARAMS ((struct propagate_block_info *,
- int, rtx));
-static void free_reg_cond_life_info PARAMS ((splay_tree_value));
-static int flush_reg_cond_reg_1 PARAMS ((splay_tree_node, void *));
-static void flush_reg_cond_reg PARAMS ((struct propagate_block_info *,
- int));
-static rtx elim_reg_cond PARAMS ((rtx, unsigned int));
-static rtx ior_reg_cond PARAMS ((rtx, rtx, int));
-static rtx not_reg_cond PARAMS ((rtx));
-static rtx and_reg_cond PARAMS ((rtx, rtx, int));
+static int mark_regno_cond_dead (struct propagate_block_info *, int, rtx);
+static void free_reg_cond_life_info (splay_tree_value);
+static int flush_reg_cond_reg_1 (splay_tree_node, void *);
+static void flush_reg_cond_reg (struct propagate_block_info *, int);
+static rtx elim_reg_cond (rtx, unsigned int);
+static rtx ior_reg_cond (rtx, rtx, int);
+static rtx not_reg_cond (rtx);
+static rtx and_reg_cond (rtx, rtx, int);
#endif
#ifdef AUTO_INC_DEC
-static void attempt_auto_inc PARAMS ((struct propagate_block_info *,
- rtx, rtx, rtx, rtx, rtx));
-static void find_auto_inc PARAMS ((struct propagate_block_info *,
- rtx, rtx));
-static int try_pre_increment_1 PARAMS ((struct propagate_block_info *,
- rtx));
-static int try_pre_increment PARAMS ((rtx, rtx, HOST_WIDE_INT));
+static void attempt_auto_inc (struct propagate_block_info *, rtx, rtx, rtx,
+ rtx, rtx);
+static void find_auto_inc (struct propagate_block_info *, rtx, rtx);
+static int try_pre_increment_1 (struct propagate_block_info *, rtx);
+static int try_pre_increment (rtx, rtx, HOST_WIDE_INT);
#endif
-static void mark_used_reg PARAMS ((struct propagate_block_info *,
- rtx, rtx, rtx));
-static void mark_used_regs PARAMS ((struct propagate_block_info *,
- rtx, rtx, rtx));
-void dump_flow_info PARAMS ((FILE *));
-void debug_flow_info PARAMS ((void));
-static void add_to_mem_set_list PARAMS ((struct propagate_block_info *,
- rtx));
-static int invalidate_mems_from_autoinc PARAMS ((rtx *, void *));
-static void invalidate_mems_from_set PARAMS ((struct propagate_block_info *,
- rtx));
-static void clear_log_links PARAMS ((sbitmap));
+static void mark_used_reg (struct propagate_block_info *, rtx, rtx, rtx);
+static void mark_used_regs (struct propagate_block_info *, rtx, rtx, rtx);
+void debug_flow_info (void);
+static void add_to_mem_set_list (struct propagate_block_info *, rtx);
+static int invalidate_mems_from_autoinc (rtx *, void *);
+static void invalidate_mems_from_set (struct propagate_block_info *, rtx);
+static void clear_log_links (sbitmap);
+static int count_or_remove_death_notes_bb (basic_block, int);
void
-check_function_return_warnings ()
+check_function_return_warnings (void)
{
if (warn_missing_noreturn
&& !TREE_THIS_VOLATILE (cfun->decl)
@@ -386,13 +363,12 @@ check_function_return_warnings ()
note associated with the BLOCK. */
rtx
-first_insn_after_basic_block_note (block)
- basic_block block;
+first_insn_after_basic_block_note (basic_block block)
{
rtx insn;
/* Get the first instruction in the block. */
- insn = block->head;
+ insn = BB_HEAD (block);
if (insn == NULL_RTX)
return NULL_RTX;
@@ -409,10 +385,7 @@ first_insn_after_basic_block_note (block)
to be used in accumulating flow info. */
void
-life_analysis (f, file, flags)
- rtx f;
- FILE *file;
- int flags;
+life_analysis (rtx f, FILE *file, int flags)
{
#ifdef ELIMINABLE_REGS
int i;
@@ -433,7 +406,8 @@ life_analysis (f, file, flags)
#ifdef CANNOT_CHANGE_MODE_CLASS
- bitmap_initialize (&subregs_of_mode, 1);
+ if (flags & PROP_REG_INFO)
+ bitmap_initialize (&subregs_of_mode, 1);
#endif
if (! optimize)
@@ -479,7 +453,10 @@ life_analysis (f, file, flags)
is not immediately handy. */
if (flags & PROP_REG_INFO)
- memset (regs_ever_live, 0, sizeof (regs_ever_live));
+ {
+ memset (regs_ever_live, 0, sizeof (regs_ever_live));
+ memset (regs_asm_clobbered, 0, sizeof (regs_asm_clobbered));
+ }
update_life_info (NULL, UPDATE_LIFE_GLOBAL, flags);
/* Clean up. */
@@ -500,9 +477,7 @@ life_analysis (f, file, flags)
word_mode. */
static int
-verify_wide_reg_1 (px, pregno)
- rtx *px;
- void *pregno;
+verify_wide_reg_1 (rtx *px, void *pregno)
{
rtx x = *px;
unsigned int regno = *(int *) pregno;
@@ -520,11 +495,9 @@ verify_wide_reg_1 (px, pregno)
of BB looking for register REGNO. */
static void
-verify_wide_reg (regno, bb)
- int regno;
- basic_block bb;
+verify_wide_reg (int regno, basic_block bb)
{
- rtx head = bb->head, end = bb->end;
+ rtx head = BB_HEAD (bb), end = BB_END (bb);
while (1)
{
@@ -553,9 +526,7 @@ verify_wide_reg (regno, bb)
changes in live_at_start during a local update. */
static void
-verify_local_live_at_start (new_live_at_start, bb)
- regset new_live_at_start;
- basic_block bb;
+verify_local_live_at_start (regset new_live_at_start, basic_block bb)
{
if (reload_completed)
{
@@ -605,7 +576,7 @@ verify_local_live_at_start (new_live_at_start, bb)
/* Updates life information starting with the basic blocks set in BLOCKS.
If BLOCKS is null, consider it to be the universal set.
- If EXTENT is UPDATE_LIFE_LOCAL, such as after splitting or peepholeing,
+ If EXTENT is UPDATE_LIFE_LOCAL, such as after splitting or peepholing,
we are only expecting local modifications to basic blocks. If we find
extra registers live at the beginning of a block, then we either killed
useful data, or we have a broken split that wants data not provided.
@@ -616,14 +587,14 @@ verify_local_live_at_start (new_live_at_start, bb)
generates subregs of a multi-word pseudo, current life analysis will
lose the kill. So we _can_ have a pseudo go live. How irritating.
+ It is also not true when a peephole decides that it doesn't need one
+ or more of the inputs.
+
Including PROP_REG_INFO does not properly refresh regs_ever_live
unless the caller resets it to zero. */
int
-update_life_info (blocks, extent, prop_flags)
- sbitmap blocks;
- enum update_life_extent extent;
- int prop_flags;
+update_life_info (sbitmap blocks, enum update_life_extent extent, int prop_flags)
{
regset tmp;
regset_head tmp_head;
@@ -686,6 +657,16 @@ update_life_info (blocks, extent, prop_flags)
partial improvement (see MAX_MEM_SET_LIST_LEN usage).
Further improvement may be possible. */
cleanup_cfg (CLEANUP_EXPENSIVE);
+
+ /* Zap the life information from the last round. If we don't
+ do this, we can wind up with registers that no longer appear
+ in the code being marked live at entry, which twiggs bogus
+ warnings from regno_uninitialized. */
+ FOR_EACH_BB (bb)
+ {
+ CLEAR_REG_SET (bb->global_live_at_start);
+ CLEAR_REG_SET (bb->global_live_at_end);
+ }
}
/* If asked, remove notes from the blocks we'll update. */
@@ -763,9 +744,7 @@ update_life_info (blocks, extent, prop_flags)
/* Update life information in all blocks where BB_DIRTY is set. */
int
-update_life_info_in_dirty_blocks (extent, prop_flags)
- enum update_life_extent extent;
- int prop_flags;
+update_life_info_in_dirty_blocks (enum update_life_extent extent, int prop_flags)
{
sbitmap update_life_blocks = sbitmap_alloc (last_basic_block);
int n = 0;
@@ -805,8 +784,7 @@ update_life_info_in_dirty_blocks (extent, prop_flags)
KEEP_HEAD_END_P is nonzero if basic_block_info is not to be freed. */
void
-free_basic_block_vars (keep_head_end_p)
- int keep_head_end_p;
+free_basic_block_vars (int keep_head_end_p)
{
if (! keep_head_end_p)
{
@@ -828,8 +806,7 @@ free_basic_block_vars (keep_head_end_p)
/* Delete any insns that copy a register to itself. */
int
-delete_noop_moves (f)
- rtx f ATTRIBUTE_UNUSED;
+delete_noop_moves (rtx f ATTRIBUTE_UNUSED)
{
rtx insn, next;
basic_block bb;
@@ -837,7 +814,7 @@ delete_noop_moves (f)
FOR_EACH_BB (bb)
{
- for (insn = bb->head; insn != NEXT_INSN (bb->end); insn = next)
+ for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb)); insn = next)
{
next = NEXT_INSN (insn);
if (INSN_P (insn) && noop_move_p (insn))
@@ -874,7 +851,7 @@ delete_noop_moves (f)
insns computing the destination, so we delay deleting and garbagecollect
them once life information is computed. */
void
-delete_dead_jumptables ()
+delete_dead_jumptables (void)
{
rtx insn, next;
for (insn = get_insns (); insn; insn = next)
@@ -899,10 +876,8 @@ delete_dead_jumptables ()
Only useful before prologues have been emitted. */
static void
-notice_stack_pointer_modification_1 (x, pat, data)
- rtx x;
- rtx pat ATTRIBUTE_UNUSED;
- void *data ATTRIBUTE_UNUSED;
+notice_stack_pointer_modification_1 (rtx x, rtx pat ATTRIBUTE_UNUSED,
+ void *data ATTRIBUTE_UNUSED)
{
if (x == stack_pointer_rtx
/* The stack pointer is only modified indirectly as the result
@@ -915,8 +890,7 @@ notice_stack_pointer_modification_1 (x, pat, data)
}
static void
-notice_stack_pointer_modification (f)
- rtx f;
+notice_stack_pointer_modification (rtx f)
{
rtx insn;
@@ -943,9 +917,7 @@ notice_stack_pointer_modification (f)
of their component registers set as well. */
static void
-mark_reg (reg, xset)
- rtx reg;
- void *xset;
+mark_reg (rtx reg, void *xset)
{
regset set = (regset) xset;
int regno = REGNO (reg);
@@ -966,14 +938,13 @@ mark_reg (reg, xset)
at the end of the last basic block. */
static void
-mark_regs_live_at_end (set)
- regset set;
+mark_regs_live_at_end (regset set)
{
unsigned int i;
/* If exiting needs the right stack value, consider the stack pointer
live at the end of the function. */
- if ((HAVE_epilogue && reload_completed)
+ if ((HAVE_epilogue && epilogue_completed)
|| ! EXIT_IGNORE_STACK
|| (! FRAME_POINTER_REQUIRED
&& ! current_function_calls_alloca
@@ -1001,7 +972,7 @@ mark_regs_live_at_end (set)
/* Many architectures have a GP register even without flag_pic.
Assume the pic register is not in use, or will be handled by
other means, if it is not fixed. */
- if (PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM
+ if ((unsigned) PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM
&& fixed_regs[PIC_OFFSET_TABLE_REGNUM])
SET_REGNO_REG_SET (set, PIC_OFFSET_TABLE_REGNUM);
#endif
@@ -1013,7 +984,7 @@ mark_regs_live_at_end (set)
if (global_regs[i] || EPILOGUE_USES (i))
SET_REGNO_REG_SET (set, i);
- if (HAVE_epilogue && reload_completed)
+ if (HAVE_epilogue && epilogue_completed)
{
/* Mark all call-saved registers that we actually used. */
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
@@ -1034,7 +1005,7 @@ mark_regs_live_at_end (set)
}
#endif
#ifdef EH_RETURN_STACKADJ_RTX
- if ((! HAVE_epilogue || ! reload_completed)
+ if ((! HAVE_epilogue || ! epilogue_completed)
&& current_function_calls_eh_return)
{
rtx tmp = EH_RETURN_STACKADJ_RTX;
@@ -1043,7 +1014,7 @@ mark_regs_live_at_end (set)
}
#endif
#ifdef EH_RETURN_HANDLER_RTX
- if ((! HAVE_epilogue || ! reload_completed)
+ if ((! HAVE_epilogue || ! epilogue_completed)
&& current_function_calls_eh_return)
{
rtx tmp = EH_RETURN_HANDLER_RTX;
@@ -1056,22 +1027,6 @@ mark_regs_live_at_end (set)
diddle_return_value (mark_reg, set);
}
-/* Callback function for for_each_successor_phi. DATA is a regset.
- Sets the SRC_REGNO, the regno of the phi alternative for phi node
- INSN, in the regset. */
-
-static int
-set_phi_alternative_reg (insn, dest_regno, src_regno, data)
- rtx insn ATTRIBUTE_UNUSED;
- int dest_regno ATTRIBUTE_UNUSED;
- int src_regno;
- void *data;
-{
- regset live = (regset) data;
- SET_REGNO_REG_SET (live, src_regno);
- return 0;
-}
-
/* Propagate global life info around the graph of basic blocks. Begin
considering blocks with their corresponding bit set in BLOCKS_IN.
If BLOCKS_IN is null, consider it the universal set.
@@ -1079,9 +1034,7 @@ set_phi_alternative_reg (insn, dest_regno, src_regno, data)
BLOCKS_OUT is set for every block that was changed. */
static void
-calculate_global_regs_live (blocks_in, blocks_out, flags)
- sbitmap blocks_in, blocks_out;
- int flags;
+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;
@@ -1109,7 +1062,7 @@ calculate_global_regs_live (blocks_in, blocks_out, flags)
/* Create a worklist. Allocate an extra slot for ENTRY_BLOCK, and one
because the `head == tail' style test for an empty queue doesn't
work with a full queue. */
- queue = (basic_block *) xmalloc ((n_basic_blocks + 2) * sizeof (*queue));
+ queue = xmalloc ((n_basic_blocks + 2) * sizeof (*queue));
qtail = queue;
qhead = qend = queue + n_basic_blocks + 2;
@@ -1230,19 +1183,11 @@ calculate_global_regs_live (blocks_in, blocks_out, flags)
/* Any constant, or pseudo with constant equivalences, may
require reloading from memory using the pic register. */
- if (PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM
+ if ((unsigned) PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM
&& fixed_regs[PIC_OFFSET_TABLE_REGNUM])
SET_REGNO_REG_SET (new_live_at_end, PIC_OFFSET_TABLE_REGNUM);
}
- /* Regs used in phi nodes are not included in
- global_live_at_start, since they are live only along a
- particular edge. Set those regs that are live because of a
- phi node alternative corresponding to this particular block. */
- if (in_ssa_form)
- for_each_successor_phi (bb, &set_phi_alternative_reg,
- new_live_at_end);
-
if (bb == ENTRY_BLOCK_PTR)
{
COPY_REG_SET (bb->global_live_at_end, new_live_at_end);
@@ -1393,9 +1338,7 @@ typedef struct {
part of an expression which only uses part of the register. Return
it in the structure passed in. */
static int
-find_regno_partial (ptr, data)
- rtx *ptr;
- void *data;
+find_regno_partial (rtx *ptr, void *data)
{
find_regno_partial_param *param = (find_regno_partial_param *)data;
unsigned reg = param->regno_to_find;
@@ -1440,7 +1383,7 @@ find_regno_partial (ptr, data)
bits we don't want. */
int
-initialize_uninitialized_subregs ()
+initialize_uninitialized_subregs (void)
{
rtx insn;
edge e;
@@ -1495,7 +1438,7 @@ initialize_uninitialized_subregs ()
of life analysis. Not static since used also for stupid life analysis. */
void
-allocate_bb_life_data ()
+allocate_bb_life_data (void)
{
basic_block bb;
@@ -1509,7 +1452,7 @@ allocate_bb_life_data ()
}
void
-allocate_reg_life_data ()
+allocate_reg_life_data (void)
{
int i;
@@ -1528,6 +1471,7 @@ allocate_reg_life_data ()
REG_N_DEATHS (i) = 0;
REG_N_CALLS_CROSSED (i) = 0;
REG_LIVE_LENGTH (i) = 0;
+ REG_FREQ (i) = 0;
REG_BASIC_BLOCK (i) = REG_BLOCK_UNKNOWN;
}
}
@@ -1535,8 +1479,7 @@ allocate_reg_life_data ()
/* Delete dead instructions for propagate_block. */
static void
-propagate_block_delete_insn (insn)
- rtx insn;
+propagate_block_delete_insn (rtx insn)
{
rtx inote = find_reg_note (insn, REG_LABEL, NULL_RTX);
@@ -1585,8 +1528,7 @@ propagate_block_delete_insn (insn)
before the libcall. */
static rtx
-propagate_block_delete_libcall ( insn, note)
- rtx insn, note;
+propagate_block_delete_libcall (rtx insn, rtx note)
{
rtx first = XEXP (note, 0);
rtx before = PREV_INSN (first);
@@ -1599,9 +1541,7 @@ propagate_block_delete_libcall ( insn, note)
/* Update the life-status of regs for one insn. Return the previous insn. */
rtx
-propagate_one_insn (pbi, insn)
- struct propagate_block_info *pbi;
- rtx insn;
+propagate_one_insn (struct propagate_block_info *pbi, rtx insn)
{
rtx prev = PREV_INSN (insn);
int flags = pbi->flags;
@@ -1659,23 +1599,23 @@ propagate_one_insn (pbi, insn)
as a whole is not dead, then we want to remove INSN, but
not the whole libcall sequence.
- However, we need to also remove the dangling REG_LIBCALL
+ However, we need to also remove the dangling REG_LIBCALL
note so that we do not have mis-matched LIBCALL/RETVAL
notes. In theory we could find a new location for the
- REG_RETVAL note, but it hardly seems worth the effort.
+ REG_RETVAL note, but it hardly seems worth the effort.
NOTE at this point will be the RETVAL note if it exists. */
if (note)
{
rtx libcall_note;
-
+
libcall_note
= find_reg_note (XEXP (note, 0), REG_LIBCALL, NULL_RTX);
remove_note (XEXP (note, 0), libcall_note);
}
/* Similarly if INSN contains a LIBCALL note, remove the
- dnagling REG_RETVAL note. */
+ dangling REG_RETVAL note. */
note = find_reg_note (insn, REG_LIBCALL, NULL_RTX);
if (note)
{
@@ -1799,8 +1739,9 @@ propagate_one_insn (pbi, insn)
current_function_return_rtx,
(rtx *) 0)))
{
+ enum rtx_code code = global_regs[i] ? SET : CLOBBER;
/* We do not want REG_UNUSED notes for these registers. */
- mark_set_1 (pbi, CLOBBER, regno_reg_rtx[i], cond, insn,
+ mark_set_1 (pbi, code, regno_reg_rtx[i], cond, insn,
pbi->flags & ~(PROP_DEATH_NOTES | PROP_REG_INFO));
}
}
@@ -1833,13 +1774,14 @@ propagate_one_insn (pbi, insn)
if (GET_CODE (PATTERN (insn)) == COND_EXEC)
cond = COND_EXEC_TEST (PATTERN (insn));
- /* Calls use their arguments. */
+ /* Calls use their arguments, and may clobber memory which
+ address involves some register. */
for (note = CALL_INSN_FUNCTION_USAGE (insn);
note;
note = XEXP (note, 1))
- if (GET_CODE (XEXP (note, 0)) == USE)
- mark_used_regs (pbi, XEXP (XEXP (note, 0), 0),
- cond, insn);
+ /* We find USE or CLOBBER entities in a FUNCTION_USAGE list: both
+ of which mark_used_regs knows how to handle. */
+ mark_used_regs (pbi, XEXP (XEXP (note, 0), 0), cond, insn);
/* The stack ptr is used (honorarily) by a CALL insn. */
SET_REGNO_REG_SET (pbi->reg_live, STACK_POINTER_REGNUM);
@@ -1866,10 +1808,8 @@ propagate_one_insn (pbi, insn)
the user can use the regsets provided here. */
struct propagate_block_info *
-init_propagate_block_info (bb, live, local_set, cond_local_set, flags)
- basic_block bb;
- regset live, local_set, cond_local_set;
- int flags;
+init_propagate_block_info (basic_block bb, regset live, regset local_set,
+ regset cond_local_set, int flags)
{
struct propagate_block_info *pbi = xmalloc (sizeof (*pbi));
@@ -1883,7 +1823,7 @@ init_propagate_block_info (bb, live, local_set, cond_local_set, flags)
pbi->flags = flags;
if (flags & (PROP_LOG_LINKS | PROP_AUTOINC))
- pbi->reg_next_use = (rtx *) xcalloc (max_reg_num (), sizeof (rtx));
+ pbi->reg_next_use = xcalloc (max_reg_num (), sizeof (rtx));
else
pbi->reg_next_use = NULL;
@@ -1894,16 +1834,15 @@ init_propagate_block_info (bb, live, local_set, cond_local_set, flags)
free_reg_cond_life_info);
pbi->reg_cond_reg = BITMAP_XMALLOC ();
- /* If this block ends in a conditional branch, for each register live
- from one side of the branch and not the other, record the register
- as conditionally dead. */
- if (GET_CODE (bb->end) == JUMP_INSN
- && any_condjump_p (bb->end))
+ /* If this block ends in a conditional branch, for each register
+ live from one side of the branch and not the other, record the
+ register as conditionally dead. */
+ if (GET_CODE (BB_END (bb)) == JUMP_INSN
+ && any_condjump_p (BB_END (bb)))
{
regset_head diff_head;
regset diff = INITIALIZE_REG_SET (diff_head);
basic_block bb_true, bb_false;
- rtx cond_true, cond_false, set_src;
int i;
/* Identify the successor blocks. */
@@ -1924,60 +1863,66 @@ init_propagate_block_info (bb, live, local_set, cond_local_set, flags)
else
{
/* This can happen with a conditional jump to the next insn. */
- if (JUMP_LABEL (bb->end) != bb_true->head)
+ if (JUMP_LABEL (BB_END (bb)) != BB_HEAD (bb_true))
abort ();
/* Simplest way to do nothing. */
bb_false = bb_true;
}
- /* Extract the condition from the branch. */
- set_src = SET_SRC (pc_set (bb->end));
- cond_true = XEXP (set_src, 0);
- cond_false = gen_rtx_fmt_ee (reverse_condition (GET_CODE (cond_true)),
- GET_MODE (cond_true), XEXP (cond_true, 0),
- XEXP (cond_true, 1));
- if (GET_CODE (XEXP (set_src, 1)) == PC)
- {
- rtx t = cond_false;
- cond_false = cond_true;
- cond_true = t;
- }
-
/* Compute which register lead different lives in the successors. */
if (bitmap_operation (diff, bb_true->global_live_at_start,
bb_false->global_live_at_start, BITMAP_XOR))
{
+ /* Extract the condition from the branch. */
+ rtx set_src = SET_SRC (pc_set (BB_END (bb)));
+ rtx cond_true = XEXP (set_src, 0);
rtx reg = XEXP (cond_true, 0);
if (GET_CODE (reg) == SUBREG)
reg = SUBREG_REG (reg);
- if (GET_CODE (reg) != REG)
- abort ();
+ /* We can only track conditional lifetimes if the condition is
+ in the form of a comparison of a register against zero.
+ If the condition is more complex than that, then it is safe
+ not to record any information. */
+ if (GET_CODE (reg) == REG
+ && XEXP (cond_true, 1) == const0_rtx)
+ {
+ rtx cond_false
+ = gen_rtx_fmt_ee (reverse_condition (GET_CODE (cond_true)),
+ GET_MODE (cond_true), XEXP (cond_true, 0),
+ XEXP (cond_true, 1));
+ if (GET_CODE (XEXP (set_src, 1)) == PC)
+ {
+ rtx t = cond_false;
+ cond_false = cond_true;
+ cond_true = t;
+ }
- SET_REGNO_REG_SET (pbi->reg_cond_reg, REGNO (reg));
+ SET_REGNO_REG_SET (pbi->reg_cond_reg, REGNO (reg));
- /* For each such register, mark it conditionally dead. */
- EXECUTE_IF_SET_IN_REG_SET
- (diff, 0, i,
- {
- struct reg_cond_life_info *rcli;
- rtx cond;
+ /* For each such register, mark it conditionally dead. */
+ EXECUTE_IF_SET_IN_REG_SET
+ (diff, 0, i,
+ {
+ struct reg_cond_life_info *rcli;
+ rtx cond;
- rcli = (struct reg_cond_life_info *) xmalloc (sizeof (*rcli));
+ rcli = xmalloc (sizeof (*rcli));
- if (REGNO_REG_SET_P (bb_true->global_live_at_start, i))
- cond = cond_false;
- else
- cond = cond_true;
- rcli->condition = cond;
- rcli->stores = const0_rtx;
- rcli->orig_condition = cond;
+ if (REGNO_REG_SET_P (bb_true->global_live_at_start, i))
+ cond = cond_false;
+ else
+ cond = cond_true;
+ rcli->condition = cond;
+ rcli->stores = const0_rtx;
+ rcli->orig_condition = cond;
- splay_tree_insert (pbi->reg_cond_dead, i,
- (splay_tree_value) rcli);
- });
+ splay_tree_insert (pbi->reg_cond_dead, i,
+ (splay_tree_value) rcli);
+ });
+ }
}
FREE_REG_SET (diff);
@@ -1999,7 +1944,7 @@ init_propagate_block_info (bb, live, local_set, cond_local_set, flags)
&& ! current_function_calls_eh_return)))
{
rtx insn, set;
- for (insn = bb->end; insn != bb->head; insn = PREV_INSN (insn))
+ for (insn = BB_END (bb); insn != BB_HEAD (bb); insn = PREV_INSN (insn))
if (GET_CODE (insn) == INSN
&& (set = single_set (insn))
&& GET_CODE (SET_DEST (set)) == MEM)
@@ -2007,13 +1952,6 @@ init_propagate_block_info (bb, live, local_set, cond_local_set, flags)
rtx mem = SET_DEST (set);
rtx canon_mem = canon_rtx (mem);
- /* This optimization is performed by faking a store to the
- memory at the end of the block. This doesn't work for
- unchanging memories because multiple stores to unchanging
- memory is illegal and alias analysis doesn't consider it. */
- if (RTX_UNCHANGING_P (canon_mem))
- continue;
-
if (XEXP (canon_mem, 0) == frame_pointer_rtx
|| (GET_CODE (XEXP (canon_mem, 0)) == PLUS
&& XEXP (XEXP (canon_mem, 0), 0) == frame_pointer_rtx
@@ -2028,8 +1966,7 @@ init_propagate_block_info (bb, live, local_set, cond_local_set, flags)
/* Release a propagate_block_info struct. */
void
-free_propagate_block_info (pbi)
- struct propagate_block_info *pbi;
+free_propagate_block_info (struct propagate_block_info *pbi)
{
free_EXPR_LIST_list (&pbi->mem_set_list);
@@ -2065,12 +2002,8 @@ free_propagate_block_info (pbi)
Return nonzero if an INSN is deleted (i.e. by dead code removal). */
int
-propagate_block (bb, live, local_set, cond_local_set, flags)
- basic_block bb;
- regset live;
- regset local_set;
- regset cond_local_set;
- int flags;
+propagate_block (basic_block bb, regset live, regset local_set,
+ regset cond_local_set, int flags)
{
struct propagate_block_info *pbi;
rtx insn, prev;
@@ -2091,7 +2024,7 @@ propagate_block (bb, live, local_set, cond_local_set, flags)
/* Scan the block an insn at a time from end to beginning. */
changed = 0;
- for (insn = bb->end;; insn = prev)
+ for (insn = BB_END (bb); ; insn = prev)
{
/* If this is a call to `setjmp' et al, warn if any
non-volatile datum is live. */
@@ -2101,9 +2034,12 @@ propagate_block (bb, live, local_set, cond_local_set, flags)
IOR_REG_SET (regs_live_at_setjmp, pbi->reg_live);
prev = propagate_one_insn (pbi, insn);
- changed |= NEXT_INSN (prev) != insn;
+ if (!prev)
+ changed |= insn != get_insns ();
+ else
+ changed |= NEXT_INSN (prev) != insn;
- if (insn == bb->head)
+ if (insn == BB_HEAD (bb))
break;
}
@@ -2122,11 +2058,8 @@ propagate_block (bb, live, local_set, cond_local_set, flags)
pertaining to the insn. */
static int
-insn_dead_p (pbi, x, call_ok, notes)
- struct propagate_block_info *pbi;
- rtx x;
- int call_ok;
- rtx notes ATTRIBUTE_UNUSED;
+insn_dead_p (struct propagate_block_info *pbi, rtx x, int call_ok,
+ rtx notes ATTRIBUTE_UNUSED)
{
enum rtx_code code = GET_CODE (x);
@@ -2190,7 +2123,7 @@ insn_dead_p (pbi, x, call_ok, notes)
rtx_equal_p does not check the alias set or flags, we also
must have the potential for them to conflict (anti_dependence). */
for (temp = pbi->mem_set_list; temp != 0; temp = XEXP (temp, 1))
- if (anti_dependence (r, XEXP (temp, 0)))
+ if (unchanging_anti_dependence (r, XEXP (temp, 0)))
{
rtx mem = XEXP (temp, 0);
@@ -2292,14 +2225,22 @@ insn_dead_p (pbi, x, call_ok, notes)
}
/* A CLOBBER of a pseudo-register that is dead serves no purpose. That
- is not necessarily true for hard registers. */
- else if (code == CLOBBER && GET_CODE (XEXP (x, 0)) == REG
- && REGNO (XEXP (x, 0)) >= FIRST_PSEUDO_REGISTER
- && ! REGNO_REG_SET_P (pbi->reg_live, REGNO (XEXP (x, 0))))
- return 1;
-
- /* We do not check other CLOBBER or USE here. An insn consisting of just
- a CLOBBER or just a USE should not be deleted. */
+ is not necessarily true for hard registers until after reload. */
+ else if (code == CLOBBER)
+ {
+ if (GET_CODE (XEXP (x, 0)) == REG
+ && (REGNO (XEXP (x, 0)) >= FIRST_PSEUDO_REGISTER
+ || reload_completed)
+ && ! REGNO_REG_SET_P (pbi->reg_live, REGNO (XEXP (x, 0))))
+ return 1;
+ }
+
+ /* ??? A base USE is a historical relic. It ought not be needed anymore.
+ Instances where it is still used are either (1) temporary and the USE
+ escaped the pass, (2) cruft and the USE need not be emitted anymore,
+ or (3) hiding bugs elsewhere that are not properly representing data
+ flow. */
+
return 0;
}
@@ -2319,10 +2260,7 @@ insn_dead_p (pbi, x, call_ok, notes)
NOTE is the REG_RETVAL note of the insn. */
static int
-libcall_dead_p (pbi, note, insn)
- struct propagate_block_info *pbi;
- rtx note;
- rtx insn;
+libcall_dead_p (struct propagate_block_info *pbi, rtx note, rtx insn)
{
rtx x = single_set (insn);
@@ -2376,8 +2314,7 @@ libcall_dead_p (pbi, note, insn)
fixed hard registers. */
int
-regno_uninitialized (regno)
- unsigned int regno;
+regno_uninitialized (unsigned int regno)
{
if (n_basic_blocks == 0
|| (regno < FIRST_PSEUDO_REGISTER
@@ -2386,7 +2323,7 @@ regno_uninitialized (regno)
|| FUNCTION_ARG_REGNO_P (regno))))
return 0;
- return REGNO_REG_SET_P (ENTRY_BLOCK_PTR->next_bb->global_live_at_start, regno);
+ return REGNO_REG_SET_P (ENTRY_BLOCK_PTR->global_live_at_end, regno);
}
/* 1 if register REGNO was alive at a place where `setjmp' was called
@@ -2394,23 +2331,20 @@ regno_uninitialized (regno)
Such regs may be clobbered by `longjmp'. */
int
-regno_clobbered_at_setjmp (regno)
- int regno;
+regno_clobbered_at_setjmp (int regno)
{
if (n_basic_blocks == 0)
return 0;
return ((REG_N_SETS (regno) > 1
- || REGNO_REG_SET_P (ENTRY_BLOCK_PTR->next_bb->global_live_at_start, regno))
+ || REGNO_REG_SET_P (ENTRY_BLOCK_PTR->global_live_at_end, regno))
&& REGNO_REG_SET_P (regs_live_at_setjmp, regno));
}
/* Add MEM to PBI->MEM_SET_LIST. MEM should be canonical. Respect the
maximal list size; look for overlaps in mode and select the largest. */
static void
-add_to_mem_set_list (pbi, mem)
- struct propagate_block_info *pbi;
- rtx mem;
+add_to_mem_set_list (struct propagate_block_info *pbi, rtx mem)
{
rtx i;
@@ -2457,9 +2391,7 @@ add_to_mem_set_list (pbi, mem)
to an address change. */
static int
-invalidate_mems_from_autoinc (px, data)
- rtx *px;
- void *data;
+invalidate_mems_from_autoinc (rtx *px, void *data)
{
rtx x = *px;
struct propagate_block_info *pbi = data;
@@ -2476,9 +2408,7 @@ invalidate_mems_from_autoinc (px, data)
/* EXP is a REG. Remove any dependent entries from pbi->mem_set_list. */
static void
-invalidate_mems_from_set (pbi, exp)
- struct propagate_block_info *pbi;
- rtx exp;
+invalidate_mems_from_set (struct propagate_block_info *pbi, rtx exp)
{
rtx temp = pbi->mem_set_list;
rtx prev = NULL_RTX;
@@ -2511,13 +2441,12 @@ invalidate_mems_from_set (pbi, exp)
FLAGS is the set of operations to perform. */
static void
-mark_set_regs (pbi, x, insn)
- struct propagate_block_info *pbi;
- rtx x, insn;
+mark_set_regs (struct propagate_block_info *pbi, rtx x, rtx insn)
{
rtx cond = NULL_RTX;
rtx link;
enum rtx_code code;
+ int flags = pbi->flags;
if (insn)
for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
@@ -2526,14 +2455,17 @@ mark_set_regs (pbi, x, insn)
mark_set_1 (pbi, SET, XEXP (link, 0),
(GET_CODE (x) == COND_EXEC
? COND_EXEC_TEST (x) : NULL_RTX),
- insn, pbi->flags);
+ insn, flags);
}
retry:
switch (code = GET_CODE (x))
{
case SET:
+ if (GET_CODE (XEXP (x, 1)) == ASM_OPERANDS)
+ flags |= PROP_ASM_SCAN;
+ /* Fall through */
case CLOBBER:
- mark_set_1 (pbi, code, SET_DEST (x), cond, insn, pbi->flags);
+ mark_set_1 (pbi, code, SET_DEST (x), cond, insn, flags);
return;
case COND_EXEC:
@@ -2545,7 +2477,9 @@ mark_set_regs (pbi, x, insn)
{
int i;
- for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
+ /* We must scan forwards. If we have an asm, we need to set
+ the PROP_ASM_SCAN flag before scanning the clobbers. */
+ for (i = 0; i < XVECLEN (x, 0); i++)
{
rtx sub = XVECEXP (x, 0, i);
switch (code = GET_CODE (sub))
@@ -2556,13 +2490,24 @@ mark_set_regs (pbi, x, insn)
cond = COND_EXEC_TEST (sub);
sub = COND_EXEC_CODE (sub);
- if (GET_CODE (sub) != SET && GET_CODE (sub) != CLOBBER)
- break;
- /* Fall through. */
+ if (GET_CODE (sub) == SET)
+ goto mark_set;
+ if (GET_CODE (sub) == CLOBBER)
+ goto mark_clob;
+ break;
case SET:
+ mark_set:
+ if (GET_CODE (XEXP (sub, 1)) == ASM_OPERANDS)
+ flags |= PROP_ASM_SCAN;
+ /* Fall through */
case CLOBBER:
- mark_set_1 (pbi, code, SET_DEST (sub), cond, insn, pbi->flags);
+ mark_clob:
+ mark_set_1 (pbi, code, SET_DEST (sub), cond, insn, flags);
+ break;
+
+ case ASM_OPERANDS:
+ flags |= PROP_ASM_SCAN;
break;
default:
@@ -2584,11 +2529,7 @@ mark_set_regs (pbi, x, insn)
will be the condition. */
static void
-mark_set_1 (pbi, code, reg, cond, insn, flags)
- struct propagate_block_info *pbi;
- enum rtx_code code;
- rtx reg, cond, insn;
- int flags;
+mark_set_1 (struct propagate_block_info *pbi, enum rtx_code code, rtx reg, rtx cond, rtx insn, int flags)
{
int regno_first = -1, regno_last = -1;
unsigned long not_dead = 0;
@@ -2790,6 +2731,9 @@ mark_set_1 (pbi, code, reg, cond, insn, flags)
{
for (i = regno_first; i <= regno_last; i++)
regs_ever_live[i] = 1;
+ if (flags & PROP_ASM_SCAN)
+ for (i = regno_first; i <= regno_last; i++)
+ regs_asm_clobbered[i] = 1;
}
else
{
@@ -2813,10 +2757,18 @@ mark_set_1 (pbi, code, reg, cond, insn, flags)
in ASM_OPERANDs. If these registers get replaced,
we might wind up changing the semantics of the insn,
even if reload can make what appear to be valid
- assignments later. */
+ assignments later.
+
+ We don't build a LOG_LINK for global registers to
+ or from a function call. We don't want to let
+ combine think that it knows what is going on with
+ global registers. */
if (y && (BLOCK_NUM (y) == blocknum)
&& (regno_first >= FIRST_PSEUDO_REGISTER
- || asm_noperands (PATTERN (y)) < 0))
+ || (asm_noperands (PATTERN (y)) < 0
+ && ! ((GET_CODE (insn) == CALL_INSN
+ || GET_CODE (y) == CALL_INSN)
+ && global_regs[regno_first]))))
LOG_LINKS (y) = alloc_INSN_LIST (insn, LOG_LINKS (y));
}
}
@@ -2875,6 +2827,14 @@ mark_set_1 (pbi, code, reg, cond, insn, flags)
{
if (flags & (PROP_LOG_LINKS | PROP_AUTOINC))
pbi->reg_next_use[regno_first] = 0;
+
+ if ((flags & PROP_REG_INFO) != 0
+ && (flags & PROP_ASM_SCAN) != 0
+ && regno_first < FIRST_PSEUDO_REGISTER)
+ {
+ for (i = regno_first; i <= regno_last; i++)
+ regs_asm_clobbered[i] = 1;
+ }
}
/* If this is the last pass and this is a SCRATCH, show it will be dying
@@ -2892,10 +2852,7 @@ mark_set_1 (pbi, code, reg, cond, insn, flags)
Return true if the register is now unconditionally dead. */
static int
-mark_regno_cond_dead (pbi, regno, cond)
- struct propagate_block_info *pbi;
- int regno;
- rtx cond;
+mark_regno_cond_dead (struct propagate_block_info *pbi, int regno, rtx cond)
{
/* If this is a store to a predicate register, the value of the
predicate is changing, we don't know that the predicate as seen
@@ -2925,7 +2882,7 @@ mark_regno_cond_dead (pbi, regno, cond)
/* The register was unconditionally live previously.
Record the current condition as the condition under
which it is dead. */
- rcli = (struct reg_cond_life_info *) xmalloc (sizeof (*rcli));
+ rcli = xmalloc (sizeof (*rcli));
rcli->condition = cond;
rcli->stores = cond;
rcli->orig_condition = const0_rtx;
@@ -2978,8 +2935,7 @@ mark_regno_cond_dead (pbi, regno, cond)
/* Called from splay_tree_delete for pbi->reg_cond_life. */
static void
-free_reg_cond_life_info (value)
- splay_tree_value value;
+free_reg_cond_life_info (splay_tree_value value)
{
struct reg_cond_life_info *rcli = (struct reg_cond_life_info *) value;
free (rcli);
@@ -2988,9 +2944,7 @@ free_reg_cond_life_info (value)
/* Helper function for flush_reg_cond_reg. */
static int
-flush_reg_cond_reg_1 (node, data)
- splay_tree_node node;
- void *data;
+flush_reg_cond_reg_1 (splay_tree_node node, void *data)
{
struct reg_cond_life_info *rcli;
int *xdata = (int *) data;
@@ -3022,9 +2976,7 @@ flush_reg_cond_reg_1 (node, data)
/* Flush all (sub) expressions referring to REGNO from REG_COND_LIVE. */
static void
-flush_reg_cond_reg (pbi, regno)
- struct propagate_block_info *pbi;
- int regno;
+flush_reg_cond_reg (struct propagate_block_info *pbi, int regno)
{
int pair[2];
@@ -3047,9 +2999,7 @@ flush_reg_cond_reg (pbi, regno)
ADD. */
static rtx
-ior_reg_cond (old, x, add)
- rtx old, x;
- int add;
+ior_reg_cond (rtx old, rtx x, int add)
{
rtx op0, op1;
@@ -3137,8 +3087,7 @@ ior_reg_cond (old, x, add)
}
static rtx
-not_reg_cond (x)
- rtx x;
+not_reg_cond (rtx x)
{
enum rtx_code x_code;
@@ -3162,9 +3111,7 @@ not_reg_cond (x)
}
static rtx
-and_reg_cond (old, x, add)
- rtx old, x;
- int add;
+and_reg_cond (rtx old, rtx x, int add)
{
rtx op0, op1;
@@ -3257,9 +3204,7 @@ and_reg_cond (old, x, add)
is used when the value of REGNO changes. */
static rtx
-elim_reg_cond (x, regno)
- rtx x;
- unsigned int regno;
+elim_reg_cond (rtx x, unsigned int regno)
{
rtx op0, op1;
@@ -3323,9 +3268,8 @@ elim_reg_cond (x, regno)
else. */
static void
-attempt_auto_inc (pbi, inc, insn, mem, incr, incr_reg)
- struct propagate_block_info *pbi;
- rtx inc, insn, mem, incr, incr_reg;
+attempt_auto_inc (struct propagate_block_info *pbi, rtx inc, rtx insn,
+ rtx mem, rtx incr, rtx incr_reg)
{
int regno = REGNO (incr_reg);
rtx set = single_set (incr);
@@ -3384,8 +3328,8 @@ attempt_auto_inc (pbi, inc, insn, mem, incr, incr_reg)
new insn(s) and do the updates. */
emit_insn_before (insns, insn);
- if (pbi->bb->head == insn)
- pbi->bb->head = insns;
+ if (BB_HEAD (pbi->bb) == insn)
+ BB_HEAD (pbi->bb) = insns;
/* INCR will become a NOTE and INSN won't contain a
use of INCR_REG. If a use of INCR_REG was just placed in
@@ -3467,10 +3411,7 @@ attempt_auto_inc (pbi, inc, insn, mem, incr, incr_reg)
reference. */
static void
-find_auto_inc (pbi, x, insn)
- struct propagate_block_info *pbi;
- rtx x;
- rtx insn;
+find_auto_inc (struct propagate_block_info *pbi, rtx x, rtx insn)
{
rtx addr = XEXP (x, 0);
HOST_WIDE_INT offset = 0;
@@ -3535,6 +3476,12 @@ find_auto_inc (pbi, x, insn)
addr,
inc_val)),
insn, x, incr, addr);
+ else if (HAVE_PRE_MODIFY_DISP && offset == INTVAL (inc_val))
+ attempt_auto_inc (pbi, gen_rtx_PRE_MODIFY (Pmode, addr,
+ gen_rtx_PLUS (Pmode,
+ addr,
+ inc_val)),
+ insn, x, incr, addr);
}
else if (GET_CODE (inc_val) == REG
&& ! reg_set_between_p (inc_val, PREV_INSN (insn),
@@ -3553,11 +3500,8 @@ find_auto_inc (pbi, x, insn)
#endif /* AUTO_INC_DEC */
static void
-mark_used_reg (pbi, reg, cond, insn)
- struct propagate_block_info *pbi;
- rtx reg;
- rtx cond ATTRIBUTE_UNUSED;
- rtx insn;
+mark_used_reg (struct propagate_block_info *pbi, rtx reg,
+ rtx cond ATTRIBUTE_UNUSED, rtx insn)
{
unsigned int regno_first, regno_last, i;
int some_was_live, some_was_dead, some_not_set;
@@ -3715,7 +3659,7 @@ mark_used_reg (pbi, reg, cond, insn)
{
/* The register was not previously live at all. Record
the condition under which it is still dead. */
- rcli = (struct reg_cond_life_info *) xmalloc (sizeof (*rcli));
+ rcli = xmalloc (sizeof (*rcli));
rcli->condition = not_reg_cond (cond);
rcli->stores = const0_rtx;
rcli->orig_condition = const0_rtx;
@@ -3745,9 +3689,7 @@ mark_used_reg (pbi, reg, cond, insn)
is not called. */
static void
-mark_used_regs (pbi, x, cond, insn)
- struct propagate_block_info *pbi;
- rtx x, cond, insn;
+mark_used_regs (struct propagate_block_info *pbi, rtx x, rtx cond, rtx insn)
{
RTX_CODE code;
int regno;
@@ -3803,7 +3745,7 @@ mark_used_regs (pbi, x, cond, insn)
while (temp)
{
next = XEXP (temp, 1);
- if (anti_dependence (XEXP (temp, 0), x))
+ if (unchanging_anti_dependence (XEXP (temp, 0), x))
{
/* Splice temp out of the list. */
if (prev)
@@ -3834,7 +3776,8 @@ mark_used_regs (pbi, x, cond, insn)
case SUBREG:
#ifdef CANNOT_CHANGE_MODE_CLASS
- if (GET_CODE (SUBREG_REG (x)) == REG
+ if ((flags & PROP_REG_INFO)
+ && GET_CODE (SUBREG_REG (x)) == REG
&& REGNO (SUBREG_REG (x)) >= FIRST_PSEUDO_REGISTER)
bitmap_set_bit (&subregs_of_mode, REGNO (SUBREG_REG (x))
* MAX_MACHINE_MODE
@@ -3883,7 +3826,8 @@ mark_used_regs (pbi, x, cond, insn)
|| GET_CODE (testreg) == SUBREG)
{
#ifdef CANNOT_CHANGE_MODE_CLASS
- if (GET_CODE (testreg) == SUBREG
+ if ((flags & PROP_REG_INFO)
+ && GET_CODE (testreg) == SUBREG
&& GET_CODE (SUBREG_REG (testreg)) == REG
&& REGNO (SUBREG_REG (testreg)) >= FIRST_PSEUDO_REGISTER)
bitmap_set_bit (&subregs_of_mode, REGNO (SUBREG_REG (testreg))
@@ -3981,14 +3925,6 @@ mark_used_regs (pbi, x, cond, insn)
x = COND_EXEC_CODE (x);
goto retry;
- case PHI:
- /* We _do_not_ want to scan operands of phi nodes. Operands of
- a phi function are evaluated only when control reaches this
- block along a particular edge. Therefore, regs that appear
- as arguments to phi should not be added to the global live at
- start. */
- return;
-
default:
break;
}
@@ -4024,9 +3960,7 @@ mark_used_regs (pbi, x, cond, insn)
#ifdef AUTO_INC_DEC
static int
-try_pre_increment_1 (pbi, insn)
- struct propagate_block_info *pbi;
- rtx insn;
+try_pre_increment_1 (struct propagate_block_info *pbi, rtx insn)
{
/* Find the next use of this reg. If in same basic block,
make it do pre-increment or pre-decrement if appropriate. */
@@ -4072,9 +4006,7 @@ try_pre_increment_1 (pbi, insn)
This checks all about the validity of the result of modifying INSN. */
static int
-try_pre_increment (insn, reg, amount)
- rtx insn, reg;
- HOST_WIDE_INT amount;
+try_pre_increment (rtx insn, rtx reg, HOST_WIDE_INT amount)
{
rtx use;
@@ -4152,10 +4084,7 @@ try_pre_increment (insn, reg, amount)
return (rtx) 1. */
rtx
-find_use_as_address (x, reg, plusconst)
- rtx x;
- rtx reg;
- HOST_WIDE_INT plusconst;
+find_use_as_address (rtx x, rtx reg, HOST_WIDE_INT plusconst)
{
enum rtx_code code = GET_CODE (x);
const char * const fmt = GET_RTX_FORMAT (code);
@@ -4214,9 +4143,7 @@ find_use_as_address (x, reg, plusconst)
This is part of making a debugging dump. */
void
-dump_regset (r, outf)
- regset r;
- FILE *outf;
+dump_regset (regset r, FILE *outf)
{
int i;
if (r == NULL)
@@ -4234,13 +4161,12 @@ dump_regset (r, outf)
});
}
-/* Print a human-reaable representation of R on the standard error
+/* Print a human-readable representation of R on the standard error
stream. This function is designed to be used from within the
debugger. */
void
-debug_regset (r)
- regset r;
+debug_regset (regset r)
{
dump_regset (r, stderr);
putc ('\n', stderr);
@@ -4266,9 +4192,7 @@ debug_regset (r)
possibly other information which is used by the register allocators. */
void
-recompute_reg_usage (f, loop_step)
- rtx f ATTRIBUTE_UNUSED;
- int loop_step ATTRIBUTE_UNUSED;
+recompute_reg_usage (rtx f ATTRIBUTE_UNUSED, int loop_step ATTRIBUTE_UNUSED)
{
allocate_reg_life_data ();
update_life_info (NULL, UPDATE_LIFE_LOCAL, PROP_REG_INFO);
@@ -4279,76 +4203,103 @@ recompute_reg_usage (f, loop_step)
of the number of registers that died. */
int
-count_or_remove_death_notes (blocks, kill)
- sbitmap blocks;
- int kill;
+count_or_remove_death_notes (sbitmap blocks, int kill)
{
int count = 0;
+ int i;
basic_block bb;
- FOR_EACH_BB_REVERSE (bb)
+
+ /* This used to be a loop over all the blocks with a membership test
+ inside the loop. That can be amazingly expensive on a large CFG
+ when only a small number of bits are set in BLOCKs (for example,
+ the calls from the scheduler typically have very few bits set).
+
+ For extra credit, someone should convert BLOCKS to a bitmap rather
+ than an sbitmap. */
+ if (blocks)
+ {
+ EXECUTE_IF_SET_IN_SBITMAP (blocks, 0, i,
+ {
+ count += count_or_remove_death_notes_bb (BASIC_BLOCK (i), kill);
+ });
+ }
+ else
{
- rtx insn;
+ FOR_EACH_BB (bb)
+ {
+ count += count_or_remove_death_notes_bb (bb, kill);
+ }
+ }
- if (blocks && ! TEST_BIT (blocks, bb->index))
- continue;
+ return count;
+}
+
+/* Optionally removes all the REG_DEAD and REG_UNUSED notes from basic
+ block BB. Returns a count of the number of registers that died. */
- for (insn = bb->head;; insn = NEXT_INSN (insn))
+static int
+count_or_remove_death_notes_bb (basic_block bb, int kill)
+{
+ int count = 0;
+ rtx insn;
+
+ for (insn = BB_HEAD (bb); ; insn = NEXT_INSN (insn))
+ {
+ if (INSN_P (insn))
{
- if (INSN_P (insn))
- {
- rtx *pprev = &REG_NOTES (insn);
- rtx link = *pprev;
+ rtx *pprev = &REG_NOTES (insn);
+ rtx link = *pprev;
- while (link)
+ while (link)
+ {
+ switch (REG_NOTE_KIND (link))
{
- switch (REG_NOTE_KIND (link))
+ case REG_DEAD:
+ if (GET_CODE (XEXP (link, 0)) == REG)
{
- case REG_DEAD:
- if (GET_CODE (XEXP (link, 0)) == REG)
- {
- rtx reg = XEXP (link, 0);
- int n;
-
- if (REGNO (reg) >= FIRST_PSEUDO_REGISTER)
- n = 1;
- else
- n = HARD_REGNO_NREGS (REGNO (reg), GET_MODE (reg));
- count += n;
- }
- /* Fall through. */
-
- case REG_UNUSED:
- if (kill)
- {
- rtx next = XEXP (link, 1);
- free_EXPR_LIST_node (link);
- *pprev = link = next;
- break;
- }
- /* Fall through. */
-
- default:
- pprev = &XEXP (link, 1);
- link = *pprev;
+ rtx reg = XEXP (link, 0);
+ int n;
+
+ if (REGNO (reg) >= FIRST_PSEUDO_REGISTER)
+ n = 1;
+ else
+ n = HARD_REGNO_NREGS (REGNO (reg), GET_MODE (reg));
+ count += n;
+ }
+
+ /* Fall through. */
+
+ case REG_UNUSED:
+ if (kill)
+ {
+ rtx next = XEXP (link, 1);
+ free_EXPR_LIST_node (link);
+ *pprev = link = next;
break;
}
+ /* Fall through. */
+
+ default:
+ pprev = &XEXP (link, 1);
+ link = *pprev;
+ break;
}
}
-
- if (insn == bb->end)
- break;
}
+
+ if (insn == BB_END (bb))
+ break;
}
return count;
}
+
/* Clear LOG_LINKS fields of insns in a selected blocks or whole chain
if blocks is NULL. */
static void
-clear_log_links (blocks)
- sbitmap blocks;
+clear_log_links (sbitmap blocks)
{
rtx insn;
int i;
@@ -4364,7 +4315,7 @@ clear_log_links (blocks)
{
basic_block bb = BASIC_BLOCK (i);
- for (insn = bb->head; insn != NEXT_INSN (bb->end);
+ for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
insn = NEXT_INSN (insn))
if (INSN_P (insn))
free_INSN_LIST_list (&LOG_LINKS (insn));
@@ -4377,9 +4328,7 @@ clear_log_links (blocks)
with moving single words, but probably isn't worth the trouble. */
void
-reg_set_to_hard_reg_set (to, from)
- HARD_REG_SET *to;
- bitmap from;
+reg_set_to_hard_reg_set (HARD_REG_SET *to, bitmap from)
{
int i;
OpenPOWER on IntegriCloud