This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

revised PATCH: per-function back end reinitialization, part 1/2


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

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.

	

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
  
! /* 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 127016)
--- 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 127016)
--- gcc/alias.c	(working copy)
*************** output_dependence (rtx mem, rtx x)
*** 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 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);
  }
  
  /* 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);
  
! /* 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 Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]