This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
PATCH: back end initialization reorganization
- From: Sandra Loosemore <sandra at codesourcery dot com>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Cc: Richard Sandiford <richard at codesourcery dot com>, David Ung <davidu at mips dot com>, Nigel Stephens <nigel at mips dot com>
- Date: Fri, 10 Aug 2007 18:45:03 -0400
- Subject: PATCH: back end initialization reorganization
This is part 1 of the 3-part patch set that allows selecting mips16/nomips16
mode on a per-function basis. This piece is non-MIPS-specific and includes the
reorganization of the back end initialization code into target-specific and
non-target-specific sections; the former might be invoked more than once if we
change modes on the target.
In addition to fixing the cosmetic issues Richard noted in the last version:
http://gcc.gnu.org/ml/gcc-patches/2007-08/msg00229.html
the main change from the last version I circulated is that I found some
regressions in my MIPS testing relating to reg_names[] being munged inside
CONDITIONAL_REGISTER_USAGE, so I added that to the list of things that needs to
be reinitialized. I'm not aware of any other outstanding issues with this
piece, and IMO is in a state where it could be considered for approval even if
the other two pieces of the patch set are not ready yet.
-Sandra
2007-08-10 Sandra Loosemore <sandra@codesourcery.com>
David Ung <davidu@mips.com>
Nigel Stephens <nigel@mips.com>
gcc/
Separate target-specific initialization from general
back-end initialization.
* toplev.c (init_alignments): New, split out from...
(process_options): ...here.
(backend_init_target): New, split out from...
(backend_init): ...here.
(lang_dependent_init_target): New, split out from...
(lang_dependent_init): ...here.
(target_reinit): New.
* toplev.h (target_reinit): Declare.
* expr.c (init_expr_target): Renamed from init_expr_once, since it
now can be called more than once. Update comments.
* expr.h (init_expr_target): Likewise.
* alias.c (init_alias_target): Renamed from init_alias_once, since it
now can be called more than once. Explicitly zero
static_reg_base_value.
* emit-rtl.c (init_emit_regs): New, split out from...
(init_emit_once): Here.
* regclass.c (initial_fixed_regs, initial_call_used_regs): Make
non-const, so that changes from command-line arguments can overwrite
values provided by the static initializers.
(initial_call_really_used_regs): New, used similarly to the above.
(initial_reg_names): Likewise.
(last_mode_for_init_move_cost): Promoted function-local static to
file-scope static to make it accessible outside init_move_cost.
(init_reg_sets): Do not initialize fixed_regs and call_used_regs yet.
Do not initialize inv_reg_alloc_order yet, either. Do initialize
reg_names since it is needed for parsing command-line options.
(init_move_cost): Use last_mode_for_init_move_cost instead of
function-local static.
(init_reg_sets_1): Initialize fixed_regs, call_used_regs, and
call_really_used_regs now. Reinitialize reg_names. Also
initialize inv_reg_alloc_order. Zero reg_class_subunion and
reg_class_superunion. Clear losing_caller_save_reg_set.
Preserve global registers if called more than once. Reset
move cost, may_move_in_cost, may_move_out_cost, and
last_mode_for_init_move_cost.
(init_reg_modes_target): Renamed from init_reg_modes_once, since it
can now be invoked more than once. Update comments.
(init_regs): Update comments.
(fix_register): Update initial_fixed_regs, initial_call_used_regs,
and initial_call_really_used_regs, instead of the non-initial
variables. This allows us to save the command-line register settings
after target reinitialization.
(init_reg_autoinc): Zero forbidden_inc_dec_classes.
* rtl.h (init_emit_regs): Declare.
(init_reg_modes_target, init_alias_target): Renamed as described
above.
* reload1.c (init_reload): Update comments.
* optabs.c (init_optabs): Likewise.
* cfgloopanal.c (init_set_costs): Explicitly zero target_avail_regs.
Index: gcc/toplev.c
===================================================================
*** gcc/toplev.c (revision 127325)
--- gcc/toplev.c (working copy)
*************** target_supports_section_anchors_p (void)
*** 1677,1682 ****
--- 1680,1710 ----
return true;
}
+ /* Default the algn_* variables to 1 if they're still unset, and
+ set up the align_*_log variables. */
+ static void
+ init_alignments (void)
+ {
+ if (align_loops <= 0)
+ align_loops = 1;
+ if (align_loops_max_skip > align_loops)
+ align_loops_max_skip = align_loops - 1;
+ align_loops_log = floor_log2 (align_loops * 2 - 1);
+ if (align_jumps <= 0)
+ align_jumps = 1;
+ if (align_jumps_max_skip > align_jumps)
+ align_jumps_max_skip = align_jumps - 1;
+ align_jumps_log = floor_log2 (align_jumps * 2 - 1);
+ if (align_labels <= 0)
+ align_labels = 1;
+ align_labels_log = floor_log2 (align_labels * 2 - 1);
+ if (align_labels_max_skip > align_labels)
+ align_labels_max_skip = align_labels - 1;
+ if (align_functions <= 0)
+ align_functions = 1;
+ align_functions_log = floor_log2 (align_functions * 2 - 1);
+ }
+
/* Process the options that have been parsed. */
static void
process_options (void)
*************** process_options (void)
*** 1722,1744 ****
else
aux_base_name = "gccaux";
- /* Set up the align_*_log variables, defaulting them to 1 if they
- were still unset. */
- if (align_loops <= 0) align_loops = 1;
- if (align_loops_max_skip > align_loops || !align_loops)
- align_loops_max_skip = align_loops - 1;
- align_loops_log = floor_log2 (align_loops * 2 - 1);
- if (align_jumps <= 0) align_jumps = 1;
- if (align_jumps_max_skip > align_jumps || !align_jumps)
- align_jumps_max_skip = align_jumps - 1;
- align_jumps_log = floor_log2 (align_jumps * 2 - 1);
- if (align_labels <= 0) align_labels = 1;
- align_labels_log = floor_log2 (align_labels * 2 - 1);
- if (align_labels_max_skip > align_labels || !align_labels)
- align_labels_max_skip = align_labels - 1;
- if (align_functions <= 0) align_functions = 1;
- align_functions_log = floor_log2 (align_functions * 2 - 1);
-
/* Unrolling all loops implies that standard loop unrolling must also
be done. */
if (flag_unroll_all_loops)
--- 1750,1755 ----
*************** process_options (void)
*** 1990,1996 ****
}
}
! /* Initialize the compiler back end. */
static void
backend_init (void)
{
--- 2001,2050 ----
}
}
! /* This function can be called multiple times to reinitialize the compiler
! back end when register classes or instruction sets have changed,
! before each function. */
! static void
! backend_init_target (void)
! {
! /* Initialize alignment variables. */
! init_alignments ();
!
! /* This reinitializes hard_frame_pointer, and calls init_reg_modes_target()
! to initialize reg_raw_mode[]. */
! init_emit_regs ();
!
! /* This invokes target hooks to set fixed_reg[] etc, which is
! mode-dependent. */
! init_regs ();
!
! /* This depends on stack_pointer_rtx. */
! init_fake_stack_mems ();
!
! /* Sets static_base_value[HARD_FRAME_POINTER_REGNUM], which is
! mode-dependent. */
! init_alias_target ();
!
! /* Depends on HARD_FRAME_POINTER_REGNUM. */
! init_reload ();
!
! /* The following initialization functions need to generate rtl, so
! provide a dummy function context for them. */
! init_dummy_function_start ();
!
! /* rtx_cost is mode-dependent, so cached values need to be recomputed
! on a mode change. */
! init_expmed ();
!
! /* We may need to recompute regno_save_code[] and regno_restore_code[]
! after a mode change as well. */
! if (flag_caller_saves)
! init_caller_save ();
! expand_dummy_function_end ();
! }
!
! /* Initialize the compiler back end. This function is called only once,
! when starting the compiler. */
static void
backend_init (void)
{
*************** backend_init (void)
*** 2003,2021 ****
|| flag_test_coverage);
init_rtlanal ();
- init_regs ();
- init_fake_stack_mems ();
- init_alias_once ();
init_inline_once ();
- init_reload ();
init_varasm_once ();
/* The following initialization functions need to generate rtl, so
provide a dummy function context for them. */
init_dummy_function_start ();
! init_expmed ();
! if (flag_caller_saves)
! init_caller_save ();
expand_dummy_function_end ();
}
--- 2057,2090 ----
|| flag_test_coverage);
init_rtlanal ();
init_inline_once ();
init_varasm_once ();
+ /* Initialize the target-specific back end pieces. */
+ backend_init_target ();
+ }
+
+ /* Initialize things that are both lang-dependent and target-dependent.
+ This function can be called more than once if target parameters change. */
+ static void
+ lang_dependent_init_target (void)
+ {
+ /* This creates various _DECL nodes, so needs to be called after the
+ front end is initialized. It also depends on the HAVE_xxx macros
+ generated from the target machine description. */
+ init_optabs ();
+
/* The following initialization functions need to generate rtl, so
provide a dummy function context for them. */
init_dummy_function_start ();
!
! /* Do the target-specific parts of expr initialization. */
! init_expr_target ();
!
! /* Although the actions of init_set_costs are language-independent,
! it uses optabs, so we cannot call it from backend_init. */
! init_set_costs ();
!
expand_dummy_function_end ();
}
*************** lang_dependent_init (const char *name)
*** 2040,2060 ****
init_asm_output (name);
! /* These create various _DECL nodes, so need to be called after the
front end is initialized. */
init_eh ();
- init_optabs ();
! /* The following initialization functions need to generate rtl, so
! provide a dummy function context for them. */
! init_dummy_function_start ();
! init_expr_once ();
!
! /* Although the actions of init_set_costs are language-independent,
! it uses optabs, so we cannot call it from backend_init. */
! init_set_costs ();
!
! expand_dummy_function_end ();
/* If dbx symbol table desired, initialize writing it and output the
predefined types. */
--- 2109,2120 ----
init_asm_output (name);
! /* This creates various _DECL nodes, so needs to be called after the
front end is initialized. */
init_eh ();
! /* Do the target-specific parts of the initialization. */
! lang_dependent_init_target ();
/* If dbx symbol table desired, initialize writing it and output the
predefined types. */
*************** lang_dependent_init (const char *name)
*** 2074,2079 ****
--- 2134,2152 ----
return 1;
}
+
+ /* Reinitialize everything when target parameters, such as register usage,
+ have changed. */
+ void
+ target_reinit (void)
+ {
+ /* Reinitialise RTL backend. */
+ backend_init_target ();
+
+ /* Reinitialize lang-dependent parts. */
+ lang_dependent_init_target ();
+ }
+
void
dump_memory_report (bool final)
{
Index: gcc/toplev.h
===================================================================
*** gcc/toplev.h (revision 127325)
--- gcc/toplev.h (working copy)
*************** extern void write_global_declarations (v
*** 101,106 ****
--- 101,108 ----
extern void dump_memory_report (bool);
+ extern void target_reinit (void);
+
/* A unique local time stamp, might be zero if none is available. */
extern unsigned local_tick;
Index: gcc/expr.c
===================================================================
*** gcc/expr.c (revision 127325)
--- gcc/expr.c (working copy)
*************** enum insn_code sync_lock_release[NUM_MAC
*** 236,246 ****
#define SLOW_UNALIGNED_ACCESS(MODE, ALIGN) STRICT_ALIGNMENT
#endif
! /* This is run once per compilation to set up which modes can be used
! directly in memory and to initialize the block move optab. */
void
! init_expr_once (void)
{
rtx insn, pat;
enum machine_mode mode;
--- 236,247 ----
#define SLOW_UNALIGNED_ACCESS(MODE, ALIGN) STRICT_ALIGNMENT
#endif
! /* This is run to set up which modes can be used
! directly in memory and to initialize the block move optab. It is run
! at the beginning of compilation and when the target is reinitialized. */
void
! init_expr_target (void)
{
rtx insn, pat;
enum machine_mode mode;
Index: gcc/expr.h
===================================================================
*** gcc/expr.h (revision 127325)
--- gcc/expr.h (working copy)
*************** extern void expand_builtin_trap (void);
*** 344,352 ****
/* Functions from expr.c: */
! /* This is run once per compilation to set up which modes can be used
! directly in memory and to initialize the block move optab. */
! extern void init_expr_once (void);
/* This is run at the start of compiling a function. */
extern void init_expr (void);
--- 344,352 ----
/* Functions from expr.c: */
! /* This is run during target initialization to set up which modes can be
! used directly in memory and to initialize the block move optab. */
! extern void init_expr_target (void);
/* This is run at the start of compiling a function. */
extern void init_expr (void);
Index: gcc/alias.c
===================================================================
*** gcc/alias.c (revision 127325)
--- gcc/alias.c (working copy)
*************** output_dependence (const_rtx mem, const_
*** 2324,2333 ****
void
! init_alias_once (void)
{
int i;
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
/* Check whether this register can hold an incoming pointer
argument. FUNCTION_ARG_REGNO_P tests outgoing register
--- 2324,2335 ----
void
! init_alias_target (void)
{
int i;
+ memset (static_reg_base_value, 0, sizeof static_reg_base_value);
+
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
/* Check whether this register can hold an incoming pointer
argument. FUNCTION_ARG_REGNO_P tests outgoing register
Index: gcc/emit-rtl.c
===================================================================
*** gcc/emit-rtl.c (revision 127325)
--- gcc/emit-rtl.c (working copy)
*************** gen_rtx_CONST_VECTOR (enum machine_mode
*** 5071,5076 ****
--- 5071,5144 ----
return gen_rtx_raw_CONST_VECTOR (mode, v);
}
+ /* Initialise global register information required by all functions. */
+
+ void
+ init_emit_regs (void)
+ {
+ int i;
+
+ /* Reset register attributes */
+ htab_empty (reg_attrs_htab);
+
+ /* We need reg_raw_mode, so initialize the modes now. */
+ init_reg_modes_target ();
+
+ /* Assign register numbers to the globally defined register rtx. */
+ pc_rtx = gen_rtx_PC (VOIDmode);
+ cc0_rtx = gen_rtx_CC0 (VOIDmode);
+ stack_pointer_rtx = gen_raw_REG (Pmode, STACK_POINTER_REGNUM);
+ frame_pointer_rtx = gen_raw_REG (Pmode, FRAME_POINTER_REGNUM);
+ hard_frame_pointer_rtx = gen_raw_REG (Pmode, HARD_FRAME_POINTER_REGNUM);
+ arg_pointer_rtx = gen_raw_REG (Pmode, ARG_POINTER_REGNUM);
+ virtual_incoming_args_rtx =
+ gen_raw_REG (Pmode, VIRTUAL_INCOMING_ARGS_REGNUM);
+ virtual_stack_vars_rtx =
+ gen_raw_REG (Pmode, VIRTUAL_STACK_VARS_REGNUM);
+ virtual_stack_dynamic_rtx =
+ gen_raw_REG (Pmode, VIRTUAL_STACK_DYNAMIC_REGNUM);
+ virtual_outgoing_args_rtx =
+ gen_raw_REG (Pmode, VIRTUAL_OUTGOING_ARGS_REGNUM);
+ virtual_cfa_rtx = gen_raw_REG (Pmode, VIRTUAL_CFA_REGNUM);
+
+ /* Initialize RTL for commonly used hard registers. These are
+ copied into regno_reg_rtx as we begin to compile each function. */
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ static_regno_reg_rtx[i] = gen_raw_REG (reg_raw_mode[i], i);
+
+ #ifdef RETURN_ADDRESS_POINTER_REGNUM
+ return_address_pointer_rtx
+ = gen_raw_REG (Pmode, RETURN_ADDRESS_POINTER_REGNUM);
+ #endif
+
+ #ifdef STATIC_CHAIN_REGNUM
+ static_chain_rtx = gen_rtx_REG (Pmode, STATIC_CHAIN_REGNUM);
+
+ #ifdef STATIC_CHAIN_INCOMING_REGNUM
+ if (STATIC_CHAIN_INCOMING_REGNUM != STATIC_CHAIN_REGNUM)
+ static_chain_incoming_rtx
+ = gen_rtx_REG (Pmode, STATIC_CHAIN_INCOMING_REGNUM);
+ else
+ #endif
+ static_chain_incoming_rtx = static_chain_rtx;
+ #endif
+
+ #ifdef STATIC_CHAIN
+ static_chain_rtx = STATIC_CHAIN;
+
+ #ifdef STATIC_CHAIN_INCOMING
+ static_chain_incoming_rtx = STATIC_CHAIN_INCOMING;
+ #else
+ static_chain_incoming_rtx = static_chain_rtx;
+ #endif
+ #endif
+
+ if ((unsigned) PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM)
+ pic_offset_table_rtx = gen_raw_REG (Pmode, PIC_OFFSET_TABLE_REGNUM);
+ else
+ pic_offset_table_rtx = NULL_RTX;
+ }
+
/* Create some permanent unique rtl objects shared between all functions.
LINE_NUMBERS is nonzero if line numbers are to be generated. */
*************** init_emit_once (int line_numbers)
*** 5081,5089 ****
enum machine_mode mode;
enum machine_mode double_mode;
- /* We need reg_raw_mode, so initialize the modes now. */
- init_reg_modes_once ();
-
/* Initialize the CONST_INT, CONST_DOUBLE, and memory attribute hash
tables. */
const_int_htab = htab_create_ggc (37, const_int_htab_hash,
--- 5149,5154 ----
*************** init_emit_once (int line_numbers)
*** 5129,5162 ****
ptr_mode = mode_for_size (POINTER_SIZE, GET_MODE_CLASS (Pmode), 0);
- /* Assign register numbers to the globally defined register rtx.
- This must be done at runtime because the register number field
- is in a union and some compilers can't initialize unions. */
-
- pc_rtx = gen_rtx_PC (VOIDmode);
- cc0_rtx = gen_rtx_CC0 (VOIDmode);
- stack_pointer_rtx = gen_raw_REG (Pmode, STACK_POINTER_REGNUM);
- frame_pointer_rtx = gen_raw_REG (Pmode, FRAME_POINTER_REGNUM);
- if (hard_frame_pointer_rtx == 0)
- hard_frame_pointer_rtx = gen_raw_REG (Pmode,
- HARD_FRAME_POINTER_REGNUM);
- if (arg_pointer_rtx == 0)
- arg_pointer_rtx = gen_raw_REG (Pmode, ARG_POINTER_REGNUM);
- virtual_incoming_args_rtx =
- gen_raw_REG (Pmode, VIRTUAL_INCOMING_ARGS_REGNUM);
- virtual_stack_vars_rtx =
- gen_raw_REG (Pmode, VIRTUAL_STACK_VARS_REGNUM);
- virtual_stack_dynamic_rtx =
- gen_raw_REG (Pmode, VIRTUAL_STACK_DYNAMIC_REGNUM);
- virtual_outgoing_args_rtx =
- gen_raw_REG (Pmode, VIRTUAL_OUTGOING_ARGS_REGNUM);
- virtual_cfa_rtx = gen_raw_REG (Pmode, VIRTUAL_CFA_REGNUM);
-
- /* Initialize RTL for commonly used hard registers. These are
- copied into regno_reg_rtx as we begin to compile each function. */
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- static_regno_reg_rtx[i] = gen_raw_REG (reg_raw_mode[i], i);
-
#ifdef INIT_EXPANDERS
/* This is to initialize {init|mark|free}_machine_status before the first
call to push_function_context_to. This is needed by the Chill front
--- 5194,5199 ----
*************** init_emit_once (int line_numbers)
*** 5324,5359 ****
const_tiny_rtx[0][(int) BImode] = const0_rtx;
if (STORE_FLAG_VALUE == 1)
const_tiny_rtx[1][(int) BImode] = const1_rtx;
-
- #ifdef RETURN_ADDRESS_POINTER_REGNUM
- return_address_pointer_rtx
- = gen_raw_REG (Pmode, RETURN_ADDRESS_POINTER_REGNUM);
- #endif
-
- #ifdef STATIC_CHAIN_REGNUM
- static_chain_rtx = gen_rtx_REG (Pmode, STATIC_CHAIN_REGNUM);
-
- #ifdef STATIC_CHAIN_INCOMING_REGNUM
- if (STATIC_CHAIN_INCOMING_REGNUM != STATIC_CHAIN_REGNUM)
- static_chain_incoming_rtx
- = gen_rtx_REG (Pmode, STATIC_CHAIN_INCOMING_REGNUM);
- else
- #endif
- static_chain_incoming_rtx = static_chain_rtx;
- #endif
-
- #ifdef STATIC_CHAIN
- static_chain_rtx = STATIC_CHAIN;
-
- #ifdef STATIC_CHAIN_INCOMING
- static_chain_incoming_rtx = STATIC_CHAIN_INCOMING;
- #else
- static_chain_incoming_rtx = static_chain_rtx;
- #endif
- #endif
-
- if ((unsigned) PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM)
- pic_offset_table_rtx = gen_raw_REG (Pmode, PIC_OFFSET_TABLE_REGNUM);
}
/* Produce exact duplicate of insn INSN after AFTER.
--- 5361,5366 ----
Index: gcc/regclass.c
===================================================================
*** gcc/regclass.c (revision 127325)
--- gcc/regclass.c (working copy)
*************** HARD_REG_SET fixed_reg_set;
*** 81,87 ****
/* Data for initializing the above. */
! static const char initial_fixed_regs[] = FIXED_REGISTERS;
/* Indexed by hard register number, contains 1 for registers
that are fixed use or are clobbered by function calls.
--- 81,87 ----
/* Data for initializing the above. */
! static char initial_fixed_regs[] = FIXED_REGISTERS;
/* Indexed by hard register number, contains 1 for registers
that are fixed use or are clobbered by function calls.
*************** HARD_REG_SET losing_caller_save_reg_set;
*** 100,106 ****
/* Data for initializing the above. */
! static const char initial_call_used_regs[] = CALL_USED_REGISTERS;
/* This is much like call_used_regs, except it doesn't have to
be a superset of FIXED_REGISTERS. This vector indicates
--- 100,106 ----
/* Data for initializing the above. */
! static char initial_call_used_regs[] = CALL_USED_REGISTERS;
/* This is much like call_used_regs, except it doesn't have to
be a superset of FIXED_REGISTERS. This vector indicates
*************** static const char initial_call_used_regs
*** 108,114 ****
regs_invalidated_by_call. */
#ifdef CALL_REALLY_USED_REGISTERS
! char call_really_used_regs[] = CALL_REALLY_USED_REGISTERS;
#endif
#ifdef CALL_REALLY_USED_REGISTERS
--- 108,115 ----
regs_invalidated_by_call. */
#ifdef CALL_REALLY_USED_REGISTERS
! static char initial_call_really_used_regs[] = CALL_REALLY_USED_REGISTERS;
! char call_really_used_regs[FIRST_PSEUDO_REGISTER];
#endif
#ifdef CALL_REALLY_USED_REGISTERS
*************** enum reg_class reg_class_superunion[N_RE
*** 192,198 ****
/* Array containing all of the register names. */
! const char * reg_names[] = REGISTER_NAMES;
/* Array containing all of the register class names. */
--- 193,203 ----
/* Array containing all of the register names. */
! const char * reg_names[FIRST_PSEUDO_REGISTER];
!
! /* Data for initializing the above. */
!
! const char * initial_reg_names[] = REGISTER_NAMES;
/* Array containing all of the register class names. */
*************** static move_table *may_move_in_cost[MAX_
*** 230,235 ****
--- 235,243 ----
static move_table *may_move_out_cost[MAX_MACHINE_MODE];
+ /* Keep track of the last mode we initialized move costs for. */
+ static int last_mode_for_init_move_cost;
+
#ifdef FORBIDDEN_INC_DEC_CLASSES
/* These are the classes that regs which are auto-incremented or decremented
*************** init_reg_sets (void)
*** 298,316 ****
SET_HARD_REG_BIT (reg_class_contents[i], j);
}
- /* Sanity check: make sure the target macros FIXED_REGISTERS and
- CALL_USED_REGISTERS had the right number of initializers. */
- gcc_assert (sizeof fixed_regs == sizeof initial_fixed_regs);
- gcc_assert (sizeof call_used_regs == sizeof initial_call_used_regs);
-
- memcpy (fixed_regs, initial_fixed_regs, sizeof fixed_regs);
- memcpy (call_used_regs, initial_call_used_regs, sizeof call_used_regs);
memset (global_regs, 0, sizeof global_regs);
! #ifdef REG_ALLOC_ORDER
! for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
! inv_reg_alloc_order[reg_alloc_order[i]] = i;
! #endif
}
/* Initialize may_move_cost and friends for mode M. */
--- 306,317 ----
SET_HARD_REG_BIT (reg_class_contents[i], j);
}
memset (global_regs, 0, sizeof global_regs);
! /* Processing of command-line options like -ffixed needs to know the
! initial set of register names, so initialize that now. */
! gcc_assert (sizeof reg_names == sizeof initial_reg_names);
! memcpy (reg_names, initial_reg_names, sizeof reg_names);
}
/* Initialize may_move_cost and friends for mode M. */
*************** static void
*** 319,325 ****
init_move_cost (enum machine_mode m)
{
static unsigned short last_move_cost[N_REG_CLASSES][N_REG_CLASSES];
- static int last_mode = -1;
bool all_match = true;
unsigned int i, j;
--- 320,325 ----
*************** init_move_cost (enum machine_mode m)
*** 339,352 ****
all_match &= (last_move_cost[i][j] == cost);
last_move_cost[i][j] = cost;
}
! if (all_match && last_mode != -1)
{
! move_cost[m] = move_cost[last_mode];
! may_move_in_cost[m] = may_move_in_cost[last_mode];
! may_move_out_cost[m] = may_move_out_cost[last_mode];
return;
}
! last_mode = m;
move_cost[m] = (move_table *)xmalloc (sizeof (move_table)
* N_REG_CLASSES);
may_move_in_cost[m] = (move_table *)xmalloc (sizeof (move_table)
--- 339,352 ----
all_match &= (last_move_cost[i][j] == cost);
last_move_cost[i][j] = cost;
}
! if (all_match && last_mode_for_init_move_cost != -1)
{
! move_cost[m] = move_cost[last_mode_for_init_move_cost];
! may_move_in_cost[m] = may_move_in_cost[last_mode_for_init_move_cost];
! may_move_out_cost[m] = may_move_out_cost[last_mode_for_init_move_cost];
return;
}
! last_mode_for_init_move_cost = m;
move_cost[m] = (move_table *)xmalloc (sizeof (move_table)
* N_REG_CLASSES);
may_move_in_cost[m] = (move_table *)xmalloc (sizeof (move_table)
*************** init_reg_sets_1 (void)
*** 412,417 ****
--- 412,442 ----
unsigned int i, j;
unsigned int /* enum machine_mode */ m;
+ /* Sanity check: make sure the target macros FIXED_REGISTERS and
+ CALL_USED_REGISTERS had the right number of initializers. */
+ gcc_assert (sizeof fixed_regs == sizeof initial_fixed_regs);
+ gcc_assert (sizeof call_used_regs == sizeof initial_call_used_regs);
+
+ memcpy (fixed_regs, initial_fixed_regs, sizeof fixed_regs);
+ memcpy (call_used_regs, initial_call_used_regs, sizeof call_used_regs);
+
+ /* Likewise for call_really_used_regs. */
+ #ifdef CALL_REALLY_USED_REGISTERS
+ gcc_assert (sizeof call_really_used_regs
+ == sizeof initial_call_really_used_regs);
+ memcpy (call_really_used_regs, initial_call_really_used_regs,
+ sizeof call_really_used_regs);
+ #endif
+
+ /* And similarly for reg_names. */
+ gcc_assert (sizeof reg_names == sizeof initial_reg_names);
+ memcpy (reg_names, initial_reg_names, sizeof reg_names);
+
+ #ifdef REG_ALLOC_ORDER
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ inv_reg_alloc_order[reg_alloc_order[i]] = i;
+ #endif
+
/* This macro allows the fixed or call-used registers
and the register classes to depend on target flags. */
*************** init_reg_sets_1 (void)
*** 431,436 ****
--- 456,462 ----
reg_class_subunion[I][J] gets the largest-numbered reg-class
that is contained in the union of classes I and J. */
+ memset (reg_class_subunion, 0, sizeof reg_class_subunion);
for (i = 0; i < N_REG_CLASSES; i++)
{
for (j = 0; j < N_REG_CLASSES; j++)
*************** init_reg_sets_1 (void)
*** 453,458 ****
--- 479,485 ----
reg_class_superunion[I][J] gets the smallest-numbered reg-class
containing the union of classes I and J. */
+ memset (reg_class_superunion, 0, sizeof reg_class_superunion);
for (i = 0; i < N_REG_CLASSES; i++)
{
for (j = 0; j < N_REG_CLASSES; j++)
*************** init_reg_sets_1 (void)
*** 511,516 ****
--- 538,544 ----
CLEAR_HARD_REG_SET (call_used_reg_set);
CLEAR_HARD_REG_SET (call_fixed_reg_set);
CLEAR_HARD_REG_SET (regs_invalidated_by_call);
+ CLEAR_HARD_REG_SET (losing_caller_save_reg_set);
memcpy (call_fixed_regs, fixed_regs, sizeof call_fixed_regs);
*************** init_reg_sets_1 (void)
*** 564,569 ****
--- 592,609 ----
SET_HARD_REG_BIT (regs_invalidated_by_call, i);
}
+ /* Preserve global registers if called more than once. */
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ {
+ if (global_regs[i])
+ {
+ fixed_regs[i] = call_used_regs[i] = call_fixed_regs[i] = 1;
+ SET_HARD_REG_BIT (fixed_reg_set, i);
+ SET_HARD_REG_BIT (call_used_reg_set, i);
+ SET_HARD_REG_BIT (call_fixed_reg_set, i);
+ }
+ }
+
memset (have_regs_of_mode, 0, sizeof (have_regs_of_mode));
memset (contains_reg_of_mode, 0, sizeof (contains_reg_of_mode));
for (m = 0; m < (unsigned int) MAX_MACHINE_MODE; m++)
*************** init_reg_sets_1 (void)
*** 582,595 ****
have_regs_of_mode [m] = 1;
}
}
}
/* Compute the table of register modes.
These values are used to record death information for individual registers
! (as opposed to a multi-register mode). */
void
! init_reg_modes_once (void)
{
int i, j;
--- 622,657 ----
have_regs_of_mode [m] = 1;
}
}
+
+ /* Reset move_cost and friends, making sure we only free shared
+ table entries once. */
+ for (i = 0; i < MAX_MACHINE_MODE; i++)
+ if (move_cost[i])
+ {
+ for (j = 0; j < i && move_cost[i] != move_cost[j]; j++)
+ ;
+ if (i == j)
+ {
+ free (move_cost[i]);
+ free (may_move_in_cost[i]);
+ free (may_move_out_cost[i]);
+ }
+ }
+ memset (move_cost, 0, sizeof move_cost);
+ memset (may_move_in_cost, 0, sizeof may_move_in_cost);
+ memset (may_move_out_cost, 0, sizeof may_move_out_cost);
+ last_mode_for_init_move_cost = -1;
}
/* Compute the table of register modes.
These values are used to record death information for individual registers
! (as opposed to a multi-register mode).
! This function might be invoked more than once, if the target has support
! for changing register usage conventions on a per-function basis.
! */
void
! init_reg_modes_target (void)
{
int i, j;
*************** init_reg_modes_once (void)
*** 611,618 ****
}
}
! /* Finish initializing the register sets and
! initialize the register modes. */
void
init_regs (void)
--- 673,682 ----
}
}
! /* Finish initializing the register sets and initialize the register modes.
! This function might be invoked more than once, if the target has support
! for changing register usage conventions on a per-function basis.
! */
void
init_regs (void)
*************** fix_register (const char *name, int fixe
*** 782,792 ****
}
else
{
! fixed_regs[i] = fixed;
! call_used_regs[i] = call_used;
#ifdef CALL_REALLY_USED_REGISTERS
if (fixed == 0)
! call_really_used_regs[i] = call_used;
#endif
}
}
--- 846,856 ----
}
else
{
! initial_fixed_regs[i] = fixed;
! initial_call_used_regs[i] = call_used;
#ifdef CALL_REALLY_USED_REGISTERS
if (fixed == 0)
! initial_call_really_used_regs[i] = call_used;
#endif
}
}
*************** init_reg_autoinc (void)
*** 1157,1162 ****
--- 1221,1227 ----
#ifdef FORBIDDEN_INC_DEC_CLASSES
int i;
+ memset (forbidden_inc_dec_class, 0, sizeof forbidden_inc_dec_classes);
for (i = 0; i < N_REG_CLASSES; i++)
{
rtx r = gen_rtx_raw_REG (VOIDmode, 0);
Index: gcc/rtl.h
===================================================================
*** gcc/rtl.h (revision 127325)
--- gcc/rtl.h (working copy)
*************** extern int get_max_uid (void);
*** 2048,2053 ****
--- 2048,2054 ----
extern int in_sequence_p (void);
extern void force_next_line_note (void);
extern void init_emit (void);
+ extern void init_emit_regs (void);
extern void init_emit_once (int);
extern void push_topmost_sequence (void);
extern void pop_topmost_sequence (void);
*************** extern void build_insn_chain (rtx);
*** 2157,2163 ****
extern int reg_classes_intersect_p (enum reg_class, enum reg_class);
extern int reg_class_subset_p (enum reg_class, enum reg_class);
extern void globalize_reg (int);
! extern void init_reg_modes_once (void);
extern void init_regs (void);
extern void init_fake_stack_mems (void);
extern void init_reg_sets (void);
--- 2158,2164 ----
extern int reg_classes_intersect_p (enum reg_class, enum reg_class);
extern int reg_class_subset_p (enum reg_class, enum reg_class);
extern void globalize_reg (int);
! extern void init_reg_modes_target (void);
extern void init_regs (void);
extern void init_fake_stack_mems (void);
extern void init_reg_sets (void);
*************** extern int canon_true_dependence (const_
*** 2225,2231 ****
extern int read_dependence (const_rtx, const_rtx);
extern int anti_dependence (const_rtx, const_rtx);
extern int output_dependence (const_rtx, const_rtx);
! extern void init_alias_once (void);
extern void init_alias_analysis (void);
extern void end_alias_analysis (void);
extern bool memory_modified_in_insn_p (rtx, rtx);
--- 2226,2232 ----
extern int read_dependence (const_rtx, const_rtx);
extern int anti_dependence (const_rtx, const_rtx);
extern int output_dependence (const_rtx, const_rtx);
! extern void init_alias_target (void);
extern void init_alias_analysis (void);
extern void end_alias_analysis (void);
extern bool memory_modified_in_insn_p (rtx, rtx);
Index: gcc/reload1.c
===================================================================
*** gcc/reload1.c (revision 127325)
--- gcc/reload1.c (working copy)
*************** static int reloads_conflict (int, int);
*** 448,454 ****
static rtx gen_reload (rtx, rtx, int, enum reload_type);
static rtx emit_insn_if_valid_for_reload (rtx);
! /* Initialize the reload pass once per compilation. */
void
init_reload (void)
--- 448,455 ----
static rtx gen_reload (rtx, rtx, int, enum reload_type);
static rtx emit_insn_if_valid_for_reload (rtx);
! /* Initialize the reload pass. This is called at the beginning of compilation
! and may be called again if the target is reinitialized. */
void
init_reload (void)
Index: gcc/optabs.c
===================================================================
*** gcc/optabs.c (revision 127325)
--- gcc/optabs.c (working copy)
*************** set_conv_libfunc (convert_optab optable,
*** 5563,5569 ****
convert_optab_handler (optable, tmode, fmode)->libfunc = 0;
}
! /* Call this once to initialize the contents of the optabs
appropriately for the current target machine. */
void
--- 5563,5569 ----
convert_optab_handler (optable, tmode, fmode)->libfunc = 0;
}
! /* Call this to initialize the contents of the optabs
appropriately for the current target machine. */
void
Index: gcc/cfgloopanal.c
===================================================================
*** gcc/cfgloopanal.c (revision 127325)
--- gcc/cfgloopanal.c (working copy)
*************** init_set_costs (void)
*** 334,339 ****
--- 334,340 ----
rtx mem = validize_mem (gen_rtx_MEM (SImode, addr));
unsigned i;
+ target_avail_regs = 0;
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if (TEST_HARD_REG_BIT (reg_class_contents[GENERAL_REGS], i)
&& !fixed_regs[i])