From: Sandra Loosemore <sandra@codesourcery.com>
To: GCC Patches <gcc-patches@gcc.gnu.org>
Cc: David Ung <davidu@mips.com>, Nigel Stephens <nigel@mips.com>,
Richard Sandiford <richard@codesourcery.com>,
Ian Lance Taylor <iant@google.com>
Subject: revised PATCH: per-function back end reinitialization, part 1/2
Date: Mon, 30 Jul 2007 19:36:00 -0000 [thread overview]
Message-ID: <46AE3DA9.8080601@codesourcery.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 1121 bytes --]
When last we left this patch, the general consensus seemed to be that it needed
to be cleaned up to enforce better separation of the one-time versus
target-specific initialization parts during regular startup, and to use the same
function for target initialization during startup as during subsequent calls for
re-initialization to avoid bit-rot. See, for instance, previous discussion here:
http://gcc.gnu.org/ml/gcc-patches/2007-07/msg00763.html
http://gcc.gnu.org/ml/gcc-patches/2007-07/msg00850.html
I've now done that rewrite. This is the non-MIPS-specific part of the patch --
the MIPS-specific part, to implement selecting mips16/nomips16 on a per-function
basis, is almost unchanged from the previous version, and I'll repost that in a
separate message. Besides the MIPS testing (both with and without
-mflip-mips16), I also tried to bootstrap on i686, but that's been dying for me
with some unrelated error while building libjava. I did, however, verify that
there are no regressions in the gcc testsuite on i686.
OK to commit now? Or do I need to do another round of clean-up on it?
-Sandra
[-- Attachment #2: 11b-per-fn-reset.log --]
[-- Type: text/x-log, Size: 3000 bytes --]
2007-07-30 Sandra Loosemore <sandra@codesourcery.com>
David Ung <davidu@mips.com>
Nigel Stephens <nigel@mips.com>
gcc/
Add hooks for back-end reset on per-function basis.
* target-def.h (TARGET_PREPARE_FUNCTION_START): Define.
(TARGET_END_OF_FILE_CLEANUP): Define
(TARGET_INITIALIZER): Add entries for above symbols.
* target.h (struct gcc_target): Add prepare_function_start
and end_of_file_cleanup slots.
* doc/tm.texi (TARGET_PREPARE_FUNCTION_START): Document.
(TARGET_END_OF_FILE_CLEANUP): Likewise.
* function.c (prepare_function_start): Invoke prepare_function_start
target hook.
* toplev.c (compile_file): Invoke end_of_file_cleanup target hook.
(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.
* cfgloopanal.c (init_set_costs): Explicitly zero target_avail_regs.
* 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.
(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.
(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. 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.
[-- Attachment #3: 11b-per-fn-reset.patch --]
[-- Type: text/x-patch, Size: 33288 bytes --]
Index: gcc/target-def.h
===================================================================
*** gcc/target-def.h (revision 127016)
--- gcc/target-def.h (working copy)
***************
*** 471,476 ****
--- 471,484 ----
#define TARGET_MANGLE_TYPE hook_constcharptr_tree_null
#define TARGET_ALLOCATE_INITIAL_VALUE NULL
+ #ifndef TARGET_PREPARE_FUNCTION_START
+ #define TARGET_PREPARE_FUNCTION_START hook_void_tree
+ #endif
+
+ #ifndef TARGET_END_OF_FILE_CLEANUP
+ #define TARGET_END_OF_FILE_CLEANUP hook_void_void
+ #endif
+
#ifndef TARGET_INIT_LIBFUNCS
#define TARGET_INIT_LIBFUNCS hook_void_void
#endif
***************
*** 711,716 ****
--- 719,726 ----
TARGET_MAX_ANCHOR_OFFSET, \
TARGET_USE_ANCHORS_FOR_SYMBOL_P, \
TARGET_FUNCTION_OK_FOR_SIBCALL, \
+ TARGET_PREPARE_FUNCTION_START, \
+ TARGET_END_OF_FILE_CLEANUP, \
TARGET_IN_SMALL_DATA_P, \
TARGET_BINDS_LOCAL_P, \
TARGET_MANGLE_DECL_ASSEMBLER_NAME, \
Index: gcc/target.h
===================================================================
*** gcc/target.h (revision 127016)
--- gcc/target.h (working copy)
*************** struct gcc_target
*** 560,565 ****
--- 560,571 ----
this is an indirect call. */
bool (*function_ok_for_sibcall) (tree decl, tree exp);
+ /* Prepare for function RTL generation. */
+ void (* prepare_function_start) (tree);
+
+ /* Start RTL generation for cleanup at end of file. */
+ void (* end_of_file_cleanup) (void);
+
/* True if EXP should be placed in a "small data" section. */
bool (* in_small_data_p) (tree);
Index: gcc/doc/tm.texi
===================================================================
*** gcc/doc/tm.texi (revision 127016)
--- gcc/doc/tm.texi (working copy)
*************** The default value of this hook is @code{
*** 10046,10051 ****
--- 10046,10067 ----
allocation.
@end deftypefn
+ @deftypefn {Target Hook} void TARGET_PREPARE_FUNCTION_START (tree @var{decl})
+ The compiler invokes this hook as its first action in preparing to emit code
+ for the function declared by @var{decl}. You can define this function if
+ the back end needs to perform any initialization or reset actions on a
+ per-function basis. The default hook function does nothing.
+ @end deftypefn
+
+ @deftypefn {Target Hook} void TARGET_END_OF_FILE_CLEANUP (void)
+ The compiler invokes this hook after code generation for the last function
+ in the file has been completed, but before writing deferred declarations,
+ constants, debug information, and the like. If your back end uses
+ @code{TARGET_PREPARE_FUNCTION_START} to perform per-function reset
+ actions, it may also need to define this hook to clean up after the
+ last function. The default hook function does nothing.
+ @end deftypefn
+
@defmac TARGET_OBJECT_SUFFIX
Define this macro to be a C string representing the suffix for object
files on your target machine. If you do not define this macro, GCC will
Index: gcc/function.c
===================================================================
*** gcc/function.c (revision 127016)
--- gcc/function.c (working copy)
*************** allocate_struct_function (tree fndecl)
*** 3847,3852 ****
--- 3847,3854 ----
static void
prepare_function_start (tree fndecl)
{
+ (*targetm.prepare_function_start) (fndecl);
+
if (fndecl && DECL_STRUCT_FUNCTION (fndecl))
cfun = DECL_STRUCT_FUNCTION (fndecl);
else
Index: gcc/toplev.c
===================================================================
*** gcc/toplev.c (revision 127016)
--- gcc/toplev.c (working copy)
*************** compile_file (void)
*** 1053,1058 ****
--- 1053,1061 ----
if (flag_syntax_only)
return;
+ /* Tell the back end we've finished with processing functions. */
+ targetm.end_of_file_cleanup ();
+
lang_hooks.decls.final_write_globals ();
if (errorcount || sorrycount)
*************** target_supports_section_anchors_p (void)
*** 1677,1682 ****
--- 1680,1706 ----
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)
+ 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);
+ }
+
/* 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)
--- 1746,1751 ----
*************** process_options (void)
*** 1990,1996 ****
}
}
! /* Initialize the compiler back end. */
static void
backend_init (void)
{
--- 1997,2047 ----
}
}
! /* 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 ();
}
--- 2054,2088 ----
|| 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. */
--- 2107,2118 ----
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 ****
--- 2132,2151 ----
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 127016)
--- 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/cfgloopanal.c
===================================================================
*** gcc/cfgloopanal.c (revision 127016)
--- 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])
Index: gcc/expr.c
===================================================================
*** gcc/expr.c (revision 127016)
--- gcc/expr.c (working copy)
*************** enum insn_code sync_lock_release[NUM_MAC
*** 236,246 ****
#define SLOW_UNALIGNED_ACCESS(MODE, ALIGN) STRICT_ALIGNMENT
#endif
\f
! /* 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
\f
! /* 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 127016)
--- gcc/expr.h (working copy)
*************** extern void expand_builtin_trap (void);
*** 344,352 ****
\f
/* 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 ----
\f
/* 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 127016)
--- gcc/alias.c (working copy)
*************** output_dependence (rtx mem, rtx x)
*** 2324,2333 ****
\f
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 ----
\f
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 127016)
--- gcc/emit-rtl.c (working copy)
*************** gen_rtx_CONST_VECTOR (enum machine_mode
*** 5058,5063 ****
--- 5058,5134 ----
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.
+ 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);
+ 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)
*** 5068,5076 ****
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,
--- 5139,5144 ----
*************** init_emit_once (int line_numbers)
*** 5116,5149 ****
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
--- 5184,5189 ----
*************** init_emit_once (int line_numbers)
*** 5255,5290 ****
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);
}
\f
/* Produce exact duplicate of insn INSN after AFTER.
--- 5295,5300 ----
Index: gcc/regclass.c
===================================================================
*** gcc/regclass.c (revision 127016)
--- 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
*************** static move_table *may_move_in_cost[MAX_
*** 230,235 ****
--- 231,239 ----
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. */
--- 302,308 ----
*************** 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;
--- 311,316 ----
*************** 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)
--- 330,343 ----
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 ****
--- 403,429 ----
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
+
+ #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 ****
--- 443,449 ----
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 ****
--- 466,472 ----
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 ****
--- 525,531 ----
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 ****
--- 579,596 ----
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;
--- 609,644 ----
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)
--- 660,669 ----
}
}
! /* 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
}
}
--- 833,843 ----
}
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 ****
--- 1208,1214 ----
#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 127016)
--- 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 (rtx, e
*** 2225,2231 ****
extern int read_dependence (rtx, rtx);
extern int anti_dependence (rtx, rtx);
extern int output_dependence (rtx, 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 (rtx, rtx);
extern int anti_dependence (rtx, rtx);
extern int output_dependence (rtx, 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 127016)
--- 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);
\f
! /* 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);
\f
! /* 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)
next reply other threads:[~2007-07-30 19:35 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-07-30 19:36 Sandra Loosemore [this message]
2007-08-04 8:18 ` Richard Sandiford
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=46AE3DA9.8080601@codesourcery.com \
--to=sandra@codesourcery.com \
--cc=davidu@mips.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=iant@google.com \
--cc=nigel@mips.com \
--cc=richard@codesourcery.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).