This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[dataflow] make regscan a subpass of CSE
- From: Paolo Bonzini <paolo dot bonzini at lu dot unisi dot ch>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Thu, 29 Mar 2007 17:16:39 +0200
- Subject: [dataflow] make regscan a subpass of CSE
- Reply-to: bonzini at gnu dot org
This patch reduces the number of occasions in which the compiler
has to call regscan. It is compile-time neutral because
I had to move df before CSE, but it is a good cleanup and fixes
various failures.
It could provide speedups at -O0, but I didn't measure that.
I say so because we don't run regscan anymore at -O0 with
this patch.
regscan is currently run a dozen time during a compilation.
It computes the max_parallel quantity, it sets REG_N_SETS
and REG_N_REFS (which is actually something that dataflow
already does) and tries to set the REG_ATTRS and REG_POINTER
fields of a REG.
max_parallel is only necessary for global.c and can actually be
replaced with a VEC. Computing REG_N_SETS is necessary for alias
analysis, but df_analyze also sets it and it is called for
all passes that use alias analysis (except CSE1 and GCSE),
so alias analysis may also use DF_REG_DEF_COUNT instead.
Furthermore, instrumenting gcc and bootstrapping/regtesting
yields the following numbers for the only remaining task:
# of times
REG_ATTRS REG_POINTER
found set to 1
133 849364 321462 (after jump2)
134 307 22
135 65 56 (before cse1)
138 8305 7720 (after gcse)
140 51 307
148 6280 1539 (after loop-done)
150 220 41
163 99 125
As can be seen, regscan does something interesting
only three times: after jump2, after GCSE (actually
before the local CSE that GCSE includes), after loop
optimizations.
Furthermore, this information is unused between jump2
and cse1, so we can delay the first (and most important)
occurrence of regscan until just before CSE1. Likewise,
the information is unused between loop-done and CSE2.
Therefore, this patch:
1) moves DF initialization before CSE.
2) removes REG_N_SETS computation from regscan, and
adjusts alias analysis to use DF_REG_DEF_COUNT instead
3) calls reg_scan from cse_main
4) removes all other occurrences of reg_scan.
5) fixes some fallout from not running reg_scan at -O0.
Next part could be to see what's the performance fallout
from running reg_scan exactly once; it's as easy as
adding a bool argument to cse_main and I'll leave it
for later.
A previous version of the patch was tested on powerpc64 by
Kenny; this one was bootstrapped/regtested i686-pc-linux-gnu.
Paolo
2007-03-29 Paolo Bonzini <bonzini@gnu.org>
* Makefile.in (alias.o): Fix dependencies.
* alias.c (find_base_value, init_alias_analysis): Use
DF_REG_DEF_COUNT. Include df.h.
* cfg.c (dump_reg_info): Don't fail if reg_info not initialized.
* cse.c (cse_main): Assume dataflow initialized. Call reg_scan.
* gcse.c (gcse_main): Call df_analyze, remove call to reg_scan.
* local-alloc.c (rest_of_handle_local_alloc): Call allocate_reg_info
earlier.
* passes.c (init_optimization_passes): Initialize dataflow before CSE.
* global.c (n_reg_sets): Remove.
(reg_sets): Change to a VEC.
(mark_reg_store): Push onto reg_sets.
(global_conflicts): Assert reg_sets is empty, pop values out of it.
Don't allocate it nor free it here.
(global_alloc): Allocate reg_sets if necessary.
* see.c (rest_of_handle_see): Don't call reg_scan.
* tracer.c (rest_of_handle_tracer): Likewise.
* cfgcleanup.c (rest_of_handle_jump2): Likewise.
* bb-reorder.c (fix_edges_for_rarely_executed_code): Likewise.
* loop-init.c (rtl_loop_done): Likewise.
* ifcvt.c (rest_of_handle_if_conversion): Likewise.
* mode-switching.c (optimize_mode_switching): Remove useless
allocate_reg_info.
* lower-subreg.c (decompose_register): Don't call clear_reg_info_regno.
(decompose_multiword_subregs): Don't call reg_scan_update.
* web.c (rest_of_handle_web): Delete.
(pass_web): Use web_main as pass routine.
* regclass.c (max_parallel, max_set_parallel): Remove.
(reg_scan): Don't set them.
(reg_scan_update): Delete.
(reg_scan_mark_refs): Remove last parameter.
* rtl.h (max_parallel): Remove.
Index: gcc/see.c
===================================================================
--- gcc/see.c (revision 123155)
+++ gcc/see.c (working copy)
@@ -3821,8 +3821,6 @@ rest_of_handle_see (void)
no_new_pseudos = no_new_pseudos_bcp;
run_fast_dce ();
- reg_scan (get_insns (), max_reg_num ());
-
return 0;
}
Index: gcc/tracer.c
===================================================================
--- gcc/tracer.c (revision 123155)
+++ gcc/tracer.c (working copy)
@@ -394,7 +394,6 @@ rest_of_handle_tracer (void)
if (dump_file)
dump_flow_info (dump_file, dump_flags);
tracer (0);
- reg_scan (get_insns (), max_reg_num ());
return 0;
}
Index: gcc/cfg.c
===================================================================
--- gcc/cfg.c (revision 123155)
+++ gcc/cfg.c (working copy)
@@ -575,7 +575,7 @@ dump_reg_info (FILE *file)
fprintf (file, "%d registers.\n", max);
for (i = FIRST_PSEUDO_REGISTER; i < max; i++)
- if (REG_N_REFS (i))
+ if (VEC_index (reg_info_p, reg_n_info, i) && REG_N_REFS (i))
{
enum reg_class class, altclass;
Index: gcc/regs.h
===================================================================
--- gcc/regs.h (revision 123155)
+++ gcc/regs.h (working copy)
@@ -48,8 +48,7 @@ extern int max_regno;
/* Register information indexed by register number */
typedef struct reg_info_def
-{ /* fields set by reg_scan */
- /* fields set by reg_scan & flow_analysis */
+{ /* fields set by reg_scan & flow_analysis */
int sets; /* # of times (REG n) is set */
/* fields set by flow_analysis */
Index: gcc/mode-switching.c
===================================================================
--- gcc/mode-switching.c (revision 123155)
+++ gcc/mode-switching.c (working copy)
@@ -712,7 +712,6 @@ optimize_mode_switching (void)
return 0;
#endif
- allocate_reg_info (max_regno, FALSE, FALSE);
return 1;
}
Index: gcc/cse.c
===================================================================
--- gcc/cse.c (revision 123155)
+++ gcc/cse.c (working copy)
@@ -6237,12 +6237,10 @@ cse_main (rtx f ATTRIBUTE_UNUSED, int nr
int *rc_order = XNEWVEC (int, last_basic_block);
int i, n_blocks;
- if (df)
- {
- df_analyze ();
- df_set_flags (DF_DEFER_INSN_RESCAN);
- }
+ df_analyze ();
+ df_set_flags (DF_DEFER_INSN_RESCAN);
+ reg_scan (get_insns (), max_reg_num ());
init_cse_reg_info (nregs);
ebb_data.path = XNEWVEC (struct branch_path,
@@ -7043,11 +7041,10 @@ static unsigned int
rest_of_handle_cse (void)
{
int tem;
+
if (dump_file)
dump_flow_info (dump_file, dump_flags);
- reg_scan (get_insns (), max_reg_num ());
-
tem = cse_main (get_insns (), max_reg_num ());
/* If we are not running more CSE passes, then we are no longer
@@ -7076,6 +7073,7 @@ struct tree_opt_pass pass_cse =
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
+ TODO_df_finish |
TODO_dump_func |
TODO_ggc_collect |
TODO_verify_flow, /* todo_flags_finish */
@@ -7115,7 +7112,6 @@ rest_of_handle_cse2 (void)
cleanup_cfg (0);
timevar_pop (TV_JUMP);
}
- reg_scan (get_insns (), max_reg_num ());
cse_not_expected = 1;
return 0;
}
Index: gcc/web.c
===================================================================
--- gcc/web.c (revision 123155)
+++ gcc/web.c (working copy)
@@ -259,9 +259,16 @@ replace_ref (struct df_ref *ref, rtx reg
df_insn_rescan (DF_REF_INSN (ref));
}
+
+static bool
+gate_handle_web (void)
+{
+ return (optimize > 0 && flag_web);
+}
+
/* Main entry point. */
-static void
+static unsigned int
web_main (void)
{
struct web_entry *def_entry;
@@ -362,27 +369,14 @@ web_main (void)
free (def_entry);
free (use_entry);
free (used);
-}
-
-static bool
-gate_handle_web (void)
-{
- return (optimize > 0 && flag_web);
-}
-
-static unsigned int
-rest_of_handle_web (void)
-{
- web_main ();
- reg_scan (get_insns (), max_reg_num ());
return 0;
}
-
+
struct tree_opt_pass pass_web =
{
"web", /* name */
gate_handle_web, /* gate */
- rest_of_handle_web, /* execute */
+ web_main, /* execute */
NULL, /* sub */
NULL, /* next */
0, /* static_pass_number */
Index: gcc/loop-init.c
===================================================================
--- gcc/loop-init.c (revision 123155)
+++ gcc/loop-init.c (working copy)
@@ -217,7 +217,6 @@ rtl_loop_done (void)
cfg_layout_finalize ();
cleanup_cfg (0);
- reg_scan (get_insns (), max_reg_num ());
if (dump_file)
dump_flow_info (dump_file, dump_flags);
Index: gcc/global.c
===================================================================
--- gcc/global.c (revision 123155)
+++ gcc/global.c (working copy)
@@ -282,8 +282,7 @@ static struct { int allocno1, allocno2;}
/* Record all regs that are set in any one insn.
Communication from mark_reg_{store,clobber} and global_conflicts. */
-static rtx *regs_set;
-static int n_regs_set;
+static VEC(rtx, heap) *regs_set;
/* Return true if *LOC contains an asm. */
@@ -606,6 +605,10 @@ global_alloc (void)
if (max_allocno > 0)
{
+ /* Make a vector that mark_reg_{store,clobber} will store in. */
+ if (!regs_set)
+ regs_set = VEC_alloc (rtx, heap, 10);
+
/* Scan all the insns and compute the conflicts among allocnos
and between allocnos and hard regs. */
@@ -745,9 +748,6 @@ global_conflicts (void)
rtx insn;
int *block_start_allocnos;
- /* Make a vector that mark_reg_{store,clobber} will store in. */
- regs_set = XNEWVEC (rtx, max_parallel * 2);
-
block_start_allocnos = XNEWVEC (int, max_allocno);
FOR_EACH_BB (b)
@@ -872,13 +872,9 @@ global_conflicts (void)
RTX_CODE code = GET_CODE (insn);
rtx link;
- /* Make regs_set an empty set. */
-
- n_regs_set = 0;
-
+ gcc_assert (VEC_empty (rtx, regs_set));
if (code == INSN || code == CALL_INSN || code == JUMP_INSN)
{
-
#if 0
int i = 0;
for (link = REG_NOTES (insn);
@@ -953,10 +949,11 @@ global_conflicts (void)
/* Mark any registers set in INSN and then never used. */
- while (n_regs_set-- > 0)
+ while (!VEC_empty (rtx, regs_set))
{
+ rtx reg = VEC_pop (rtx, regs_set);
rtx note = find_regno_note (insn, REG_UNUSED,
- REGNO (regs_set[n_regs_set]));
+ REGNO (reg));
if (note)
mark_reg_death (XEXP (note, 0));
}
@@ -970,8 +967,8 @@ global_conflicts (void)
/* Clean up. */
free (block_start_allocnos);
- free (regs_set);
}
+
/* Expand the preference information by looking for cases where one allocno
dies in an insn that sets an allocno. If those two allocnos don't conflict,
merge any preferences between those allocnos. */
@@ -1577,7 +1574,7 @@ mark_reg_store (rtx reg, rtx setter, voi
if (!REG_P (reg))
return;
- regs_set[n_regs_set++] = reg;
+ VEC_safe_push (rtx, heap, regs_set, reg);
if (setter && GET_CODE (setter) != CLOBBER)
set_preference (reg, SET_SRC (setter));
Index: gcc/ifcvt.c
===================================================================
--- gcc/ifcvt.c (revision 123155)
+++ gcc/ifcvt.c (working copy)
@@ -4026,12 +4026,10 @@ rest_of_handle_if_conversion (void)
if (dump_file)
dump_flow_info (dump_file, dump_flags);
cleanup_cfg (CLEANUP_EXPENSIVE);
- reg_scan (get_insns (), max_reg_num ());
if_convert ();
}
cleanup_cfg (0);
- reg_scan (get_insns (), max_reg_num ());
return 0;
}
Index: gcc/local-alloc.c
===================================================================
--- gcc/local-alloc.c (revision 123155)
+++ gcc/local-alloc.c (working copy)
@@ -2494,6 +2494,12 @@ static unsigned int
rest_of_handle_local_alloc (void)
{
int rebuild_notes;
+ int max_regno = max_reg_num ();
+
+ /* Allocate the reg_renumber array. For non-optimizing compilation,
+ allocate the register info array too, because we have not
+ run neither dataflow nor regscan so far. */
+ allocate_reg_info (max_regno, !optimize, TRUE);
df_ri_add_problem (DF_RI_LIFE + DF_RI_SETJMP);
/* There is just too much going on in the register allocators to
@@ -2514,9 +2520,6 @@ rest_of_handle_local_alloc (void)
epilogue thus changing register elimination offsets. */
current_function_is_leaf = leaf_function_p ();
- /* Allocate the reg_renumber array. */
- allocate_reg_info (max_regno, FALSE, TRUE);
-
/* And the reg_equiv_memory_loc array. */
VEC_safe_grow (rtx, gc, reg_equiv_memory_loc_vec, max_regno);
memset (VEC_address (rtx, reg_equiv_memory_loc_vec), 0,
@@ -2525,7 +2528,7 @@ rest_of_handle_local_alloc (void)
allocate_initial_values (reg_equiv_memory_loc);
- regclass (get_insns (), max_reg_num ());
+ regclass (get_insns (), max_regno);
rebuild_notes = local_alloc ();
/* Local allocation may have turned an indirect jump into a direct
Index: gcc/gcse.c
===================================================================
--- gcc/gcse.c (revision 123155)
+++ gcc/gcse.c (working copy)
@@ -675,6 +675,8 @@ gcse_main (rtx f ATTRIBUTE_UNUSED)
successors and predecessors. */
max_gcse_regno = max_reg_num ();
+ df_analyze ();
+
if (dump_file)
dump_flow_info (dump_file, dump_flags);
@@ -6692,7 +6694,6 @@ rest_of_handle_gcse (void)
if (flag_expensive_optimizations)
{
timevar_push (TV_CSE);
- reg_scan (get_insns (), max_reg_num ());
tem2 = cse_main (get_insns (), max_reg_num ());
purge_all_dead_edges ();
delete_trivially_dead_insns (get_insns (), max_reg_num ());
Index: gcc/alias.c
===================================================================
--- gcc/alias.c (revision 123155)
+++ gcc/alias.c (working copy)
@@ -46,6 +46,7 @@ Software Foundation, 51 Franklin Street,
#include "varray.h"
#include "tree-pass.h"
#include "ipa-type-escape.h"
+#include "df.h"
/* The aliasing API provided here solves related but different problems:
@@ -839,7 +840,7 @@ find_base_value (rtx src)
/* If we're inside init_alias_analysis, use new_reg_base_value
to reduce the number of relaxation iterations. */
if (new_reg_base_value && new_reg_base_value[regno]
- && REG_N_SETS (regno) == 1)
+ && DF_REG_DEF_COUNT (regno) == 1)
return new_reg_base_value[regno];
if (VEC_index (rtx, reg_base_value, regno))
@@ -2432,7 +2433,7 @@ init_alias_analysis (void)
the optimization level or flag_expensive_optimizations.
We could propagate more information in the first pass by making use
- of REG_N_SETS to determine immediately that the alias information
+ of DF_REG_DEF_COUNT to determine immediately that the alias information
for a pseudo is "constant".
A program with an uninitialized variable can cause an infinite loop
@@ -2513,7 +2514,7 @@ init_alias_analysis (void)
note = find_reg_equal_equiv_note (insn);
if (note && REG_NOTE_KIND (note) == REG_EQUAL
- && REG_N_SETS (regno) != 1)
+ && DF_REG_DEF_COUNT (regno) != 1)
note = NULL_RTX;
if (note != NULL_RTX
@@ -2526,7 +2527,7 @@ init_alias_analysis (void)
set_reg_known_equiv_p (regno,
REG_NOTE_KIND (note) == REG_EQUIV);
}
- else if (REG_N_SETS (regno) == 1
+ else if (DF_REG_DEF_COUNT (regno) == 1
&& GET_CODE (src) == PLUS
&& REG_P (XEXP (src, 0))
&& (t = get_reg_known_value (REGNO (XEXP (src, 0))))
@@ -2536,7 +2537,7 @@ init_alias_analysis (void)
set_reg_known_value (regno, t);
set_reg_known_equiv_p (regno, 0);
}
- else if (REG_N_SETS (regno) == 1
+ else if (DF_REG_DEF_COUNT (regno) == 1
&& ! rtx_varies_p (src, 1))
{
set_reg_known_value (regno, src);
Index: gcc/lower-subreg.c
===================================================================
--- gcc/lower-subreg.c (revision 123155)
+++ gcc/lower-subreg.c (working copy)
@@ -352,7 +352,6 @@ decompose_register (unsigned int regno)
reg = regno_reg_rtx[regno];
regno_reg_rtx[regno] = NULL_RTX;
- clear_reg_info_regno (regno);
words = GET_MODE_SIZE (GET_MODE (reg));
words = (words + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
@@ -1058,7 +1057,6 @@ decompose_multiword_subregs (void)
if (!bitmap_empty_p (decomposable_context))
{
int hold_no_new_pseudos = no_new_pseudos;
- int max_regno = max_reg_num ();
sbitmap life_blocks;
sbitmap sub_blocks;
unsigned int i;
@@ -1171,10 +1169,7 @@ decompose_multiword_subregs (void)
}
if (changed)
- {
- SET_BIT (life_blocks, bb->index);
- reg_scan_update (insn, next, max_regno);
- }
+ SET_BIT (life_blocks, bb->index);
}
}
Index: gcc/cfgcleanup.c
===================================================================
--- gcc/cfgcleanup.c (revision 123155)
+++ gcc/cfgcleanup.c (working copy)
@@ -2341,7 +2341,6 @@ static unsigned int
rest_of_handle_jump2 (void)
{
delete_trivially_dead_insns (get_insns (), max_reg_num ());
- reg_scan (get_insns (), max_reg_num ());
if (dump_file)
dump_flow_info (dump_file, dump_flags);
cleanup_cfg ((optimize ? CLEANUP_EXPENSIVE : 0)
Index: gcc/regclass.c
===================================================================
--- gcc/regclass.c (revision 123155)
+++ gcc/regclass.c (working copy)
@@ -885,7 +885,7 @@ static void record_address_regs (enum ma
#ifdef FORBIDDEN_INC_DEC_CLASSES
static int auto_inc_dec_reg_p (rtx, enum machine_mode);
#endif
-static void reg_scan_mark_refs (rtx, rtx, unsigned int);
+static void reg_scan_mark_refs (rtx, rtx);
/* Wrapper around REGNO_OK_FOR_INDEX_P, to allow pseudo registers. */
@@ -2205,7 +2205,6 @@ static unsigned int reg_n_max;
void
allocate_reg_life_data (void)
{
- max_regno = max_reg_num ();
/* Recalculate the register space, in case it has grown. Old style
vector oriented regsets would set regset_{size,bytes} here also. */
allocate_reg_info (max_regno, FALSE, FALSE);
@@ -2226,6 +2225,7 @@ allocate_reg_info (size_t num_regs, int
size_t min = (new_p) ? 0 : reg_n_max;
struct reg_info_data *reg_data;
+ max_regno = max_reg_num ();
if (num_regs > regno_allocated)
{
size_t old_allocated = regno_allocated;
@@ -2368,19 +2368,6 @@ clear_reg_info_regno (unsigned int regno
REPEAT is nonzero the second time this is called. */
-/* Maximum number of parallel sets and clobbers in any insn in this fn.
- Always at least 3, since the combiner could put that many together
- and we want this to remain correct for all the remaining passes.
- This corresponds to the maximum number of times note_stores will call
- a function for any insn. */
-
-int max_parallel;
-
-/* Used as a temporary to record the largest number of registers in
- PARALLEL in a SET_DEST. This is added to max_parallel. */
-
-static int max_set_parallel;
-
void
reg_scan (rtx f, unsigned int nregs)
{
@@ -2389,60 +2376,27 @@ reg_scan (rtx f, unsigned int nregs)
timevar_push (TV_REG_SCAN);
allocate_reg_info (nregs, TRUE, FALSE);
- max_parallel = 3;
- max_set_parallel = 0;
-
for (insn = f; insn; insn = NEXT_INSN (insn))
if (INSN_P (insn))
{
- rtx pat = PATTERN (insn);
- if (GET_CODE (pat) == PARALLEL
- && XVECLEN (pat, 0) > max_parallel)
- max_parallel = XVECLEN (pat, 0);
- reg_scan_mark_refs (pat, insn, 0);
-
+ reg_scan_mark_refs (PATTERN (insn), insn);
if (REG_NOTES (insn))
- reg_scan_mark_refs (REG_NOTES (insn), insn, 0);
+ reg_scan_mark_refs (REG_NOTES (insn), insn);
}
- max_parallel += max_set_parallel;
-
timevar_pop (TV_REG_SCAN);
}
-/* Update 'regscan' information by looking at the insns
- from FIRST to LAST. Some new REGs have been created,
- and any REG with number greater than OLD_MAX_REGNO is
- such a REG. We only update information for those. */
-
-void
-reg_scan_update (rtx first, rtx last, unsigned int old_max_regno)
-{
- rtx insn;
-
- allocate_reg_info (max_reg_num (), FALSE, FALSE);
-
- for (insn = first; insn != last; insn = NEXT_INSN (insn))
- if (INSN_P (insn))
- {
- rtx pat = PATTERN (insn);
- if (GET_CODE (pat) == PARALLEL
- && XVECLEN (pat, 0) > max_parallel)
- max_parallel = XVECLEN (pat, 0);
- reg_scan_mark_refs (pat, insn, old_max_regno);
-
- if (REG_NOTES (insn))
- reg_scan_mark_refs (REG_NOTES (insn), insn, old_max_regno);
- }
-}
/* X is the expression to scan. INSN is the insn it appears in.
NOTE_FLAG is nonzero if X is from INSN's notes rather than its body.
We should only record information for REGs with numbers
greater than or equal to MIN_REGNO. */
+extern struct tree_opt_pass *current_pass;
+
static void
-reg_scan_mark_refs (rtx x, rtx insn, unsigned int min_regno)
+reg_scan_mark_refs (rtx x, rtx insn)
{
enum rtx_code code;
rtx dest;
@@ -2463,46 +2417,24 @@ reg_scan_mark_refs (rtx x, rtx insn, uns
case LABEL_REF:
case ADDR_VEC:
case ADDR_DIFF_VEC:
- return;
-
case REG:
- {
- unsigned int regno = REGNO (x);
-
- if (regno >= min_regno)
- {
- /* If we are called by reg_scan_update() (indicated by min_regno
- being set), we also need to update the reference count. */
- if (min_regno)
- REG_N_REFS (regno)++;
- }
- }
- break;
+ return;
case EXPR_LIST:
if (XEXP (x, 0))
- reg_scan_mark_refs (XEXP (x, 0), insn, min_regno);
+ reg_scan_mark_refs (XEXP (x, 0), insn);
if (XEXP (x, 1))
- reg_scan_mark_refs (XEXP (x, 1), insn, min_regno);
+ reg_scan_mark_refs (XEXP (x, 1), insn);
break;
case INSN_LIST:
if (XEXP (x, 1))
- reg_scan_mark_refs (XEXP (x, 1), insn, min_regno);
+ reg_scan_mark_refs (XEXP (x, 1), insn);
break;
case CLOBBER:
- {
- rtx reg = XEXP (x, 0);
- if (REG_P (reg)
- && REGNO (reg) >= min_regno)
- {
- REG_N_SETS (REGNO (reg))++;
- REG_N_REFS (REGNO (reg))++;
- }
- else if (MEM_P (reg))
- reg_scan_mark_refs (XEXP (reg, 0), insn, min_regno);
- }
+ if (MEM_P (XEXP (x, 0)))
+ reg_scan_mark_refs (XEXP (XEXP (x, 0), 0), insn);
break;
case SET:
@@ -2513,18 +2445,6 @@ reg_scan_mark_refs (rtx x, rtx insn, uns
dest = XEXP (dest, 0))
;
- /* For a PARALLEL, record the number of things (less the usual one for a
- SET) that are set. */
- if (GET_CODE (dest) == PARALLEL)
- max_set_parallel = MAX (max_set_parallel, XVECLEN (dest, 0) - 1);
-
- if (REG_P (dest)
- && REGNO (dest) >= min_regno)
- {
- REG_N_SETS (REGNO (dest))++;
- REG_N_REFS (REGNO (dest))++;
- }
-
/* If this is setting a pseudo from another pseudo or the sum of a
pseudo and a constant integer and the other pseudo is known to be
a pointer, set the destination to be a pointer as well.
@@ -2539,7 +2459,6 @@ reg_scan_mark_refs (rtx x, rtx insn, uns
if (REG_P (SET_DEST (x))
&& REGNO (SET_DEST (x)) >= FIRST_PSEUDO_REGISTER
- && REGNO (SET_DEST (x)) >= min_regno
/* If the destination pseudo is set more than once, then other
sets might not be to a pointer value (consider access to a
union in two threads of control in the presence of global
@@ -2575,7 +2494,7 @@ reg_scan_mark_refs (rtx x, rtx insn, uns
/* If this is setting a register from a register or from a simple
conversion of a register, propagate REG_EXPR. */
- if (REG_P (dest))
+ if (REG_P (dest) && !REG_ATTRS (dest))
{
rtx src = SET_SRC (x);
@@ -2585,9 +2504,9 @@ reg_scan_mark_refs (rtx x, rtx insn, uns
|| (GET_CODE (src) == SUBREG && subreg_lowpart_p (src)))
src = XEXP (src, 0);
- if (!REG_ATTRS (dest) && REG_P (src))
+ if (REG_P (src))
REG_ATTRS (dest) = REG_ATTRS (src);
- if (!REG_ATTRS (dest) && MEM_P (src))
+ if (MEM_P (src))
set_reg_attrs_from_mem (dest, src);
}
@@ -2600,12 +2519,12 @@ reg_scan_mark_refs (rtx x, rtx insn, uns
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
{
if (fmt[i] == 'e')
- reg_scan_mark_refs (XEXP (x, i), insn, min_regno);
+ reg_scan_mark_refs (XEXP (x, i), insn);
else if (fmt[i] == 'E' && XVEC (x, i) != 0)
{
int j;
for (j = XVECLEN (x, i) - 1; j >= 0; j--)
- reg_scan_mark_refs (XVECEXP (x, i, j), insn, min_regno);
+ reg_scan_mark_refs (XVECEXP (x, i, j), insn);
}
}
}
Index: gcc/rtl.h
===================================================================
--- gcc/rtl.h (revision 123155)
+++ gcc/rtl.h (working copy)
@@ -1760,12 +1760,6 @@ rtx remove_list_elem (rtx, rtx *);
/* regclass.c */
-/* Maximum number of parallel sets and clobbers in any insn in this fn.
- Always at least 3, since the combiner could put that many together
- and we want this to remain correct for all the remaining passes. */
-
-extern int max_parallel;
-
/* Free up register info memory. */
extern void free_reg_info (void);
@@ -2169,7 +2163,6 @@ extern void init_fake_stack_mems (void);
extern void init_reg_sets (void);
extern void regclass (rtx, int);
extern void reg_scan (rtx, unsigned int);
-extern void reg_scan_update (rtx, rtx, unsigned int);
extern void fix_register (const char *, int, int);
#ifdef HARD_CONST
extern void cannot_change_mode_set_regs (HARD_REG_SET *,
Index: gcc/bb-reorder.c
===================================================================
--- gcc/bb-reorder.c (revision 123155)
+++ gcc/bb-reorder.c (working copy)
@@ -1831,10 +1831,7 @@ fix_edges_for_rarely_executed_code (edge
well. */
if (!HAS_LONG_UNCOND_BRANCH)
- {
- fix_crossing_unconditional_branches ();
- reg_scan (get_insns (), max_reg_num ());
- }
+ fix_crossing_unconditional_branches ();
add_reg_crossing_jump_notes ();
}
Index: gcc/reg-stack.c
===================================================================
--- gcc/reg-stack.c (revision 123155)
+++ gcc/reg-stack.c (working copy)
@@ -167,6 +167,7 @@
#include "recog.h"
#include "output.h"
#include "basic-block.h"
+#include "cfglayout.h"
#include "varray.h"
#include "reload.h"
#include "ggc.h"
Index: gcc/Makefile.in
===================================================================
--- gcc/Makefile.in (revision 123155)
+++ gcc/Makefile.in (working copy)
@@ -2688,7 +2688,7 @@ alias.o : alias.c $(CONFIG_H) $(SYSTEM_H
$(FLAGS_H) hard-reg-set.h $(BASIC_BLOCK_H) $(REGS_H) toplev.h output.h \
$(ALIAS_H) $(EMIT_RTL_H) $(GGC_H) $(FUNCTION_H) cselib.h $(TREE_H) $(TM_P_H) \
langhooks.h $(TARGET_H) gt-alias.h $(TIMEVAR_H) $(CGRAPH_H) \
- $(SPLAY_TREE_H) $(VARRAY_H) $(IPA_TYPE_ESCAPE_H) tree-pass.h
+ $(SPLAY_TREE_H) $(VARRAY_H) $(IPA_TYPE_ESCAPE_H) $(DF_H) tree-pass.h
stack-ptr-mod.o : stack-ptr-mod.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(TREE_H) $(RTL_H) $(REGS_H) $(EXPR_H) tree-pass.h \
$(BASIC_BLOCK_H) $(FLAGS_H) output.h $(DF_H)
Index: gcc/passes.c
===================================================================
--- gcc/passes.c (revision 123155)
+++ gcc/passes.c (working copy)
@@ -690,8 +690,8 @@ init_optimization_passes (void)
NEXT_PASS (pass_into_cfg_layout_mode);
NEXT_PASS (pass_jump2);
NEXT_PASS (pass_lower_subreg);
- NEXT_PASS (pass_cse);
NEXT_PASS (pass_df_initialize);
+ NEXT_PASS (pass_cse);
NEXT_PASS (pass_rtl_fwprop);
NEXT_PASS (pass_gcse);
NEXT_PASS (pass_jump_bypass);