2007-08-27 Sandra Loosemore <sandra@codesourcery.com>
authorsandra <sandra@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 27 Aug 2007 13:34:14 +0000 (13:34 +0000)
committersandra <sandra@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 27 Aug 2007 13:34:14 +0000 (13:34 +0000)
    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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@127832 138bc75d-0d04-0410-961f-82ee72b054a4

12 files changed:
gcc/ChangeLog
gcc/alias.c
gcc/cfgloopanal.c
gcc/emit-rtl.c
gcc/expr.c
gcc/expr.h
gcc/optabs.c
gcc/regclass.c
gcc/reload1.c
gcc/rtl.h
gcc/toplev.c
gcc/toplev.h

index fe67c4f..e88e7c9 100644 (file)
@@ -1,3 +1,60 @@
+2007-08-27  Sandra Loosemore  <sandra@codesourcery.com>
+           David Ung  <davidu@mips.com>
+            Nigel Stephens <nigel@mips.com>
+
+       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.
+       
 2007-08-26  Chao-ying Fu  <fu@mips.com>
 
        * rtl.h (XCNMPFV): Preserve const-ness of parameters through use of
index 612139b..870fbc4 100644 (file)
@@ -2325,10 +2325,12 @@ output_dependence (const_rtx mem, const_rtx x)
 \f
 
 void
-init_alias_once (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 d6a74bf..c00d1c5 100644 (file)
@@ -334,6 +334,7 @@ init_set_costs (void)
   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 32dce93..6a4604d 100644 (file)
@@ -5260,6 +5260,74 @@ gen_rtx_CONST_VECTOR (enum machine_mode mode, rtvec v)
   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.  */
 
@@ -5270,9 +5338,6 @@ init_emit_once (int line_numbers)
   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, CONST_FIXED, and memory attribute
      hash tables.  */
   const_int_htab = htab_create_ggc (37, const_int_htab_hash,
@@ -5321,34 +5386,6 @@ init_emit_once (int line_numbers)
 
   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
@@ -5558,36 +5595,6 @@ init_emit_once (int line_numbers)
   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.
index 2112895..9f321c8 100644 (file)
@@ -243,11 +243,12 @@ enum insn_code sync_lock_release[NUM_MACHINE_MODES];
 #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.  */
+/* 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_once (void)
+init_expr_target (void)
 {
   rtx insn, pat;
   enum machine_mode mode;
index 24a391c..f9532ec 100644 (file)
@@ -352,9 +352,9 @@ extern rtx builtin_strncpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
 \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 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 4ef28aa..f2b47fc 100644 (file)
@@ -5563,7 +5563,7 @@ set_conv_libfunc (convert_optab optable, enum machine_mode tmode,
     convert_optab_handler (optable, tmode, fmode)->libfunc = 0;
 }
 
-/* Call this once to initialize the contents of the optabs
+/* Call this to initialize the contents of the optabs
    appropriately for the current target machine.  */
 
 void
index 81ac098..c41ec4d 100644 (file)
@@ -81,7 +81,7 @@ HARD_REG_SET fixed_reg_set;
 
 /* Data for initializing the above.  */
 
-static const char initial_fixed_regs[] = FIXED_REGISTERS;
+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.
@@ -100,7 +100,7 @@ HARD_REG_SET losing_caller_save_reg_set;
 
 /* Data for initializing the above.  */
 
-static const char initial_call_used_regs[] = CALL_USED_REGISTERS;
+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
@@ -108,7 +108,8 @@ static const char initial_call_used_regs[] = CALL_USED_REGISTERS;
    regs_invalidated_by_call.  */
 
 #ifdef CALL_REALLY_USED_REGISTERS
-char call_really_used_regs[] = 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
@@ -192,7 +193,11 @@ enum reg_class reg_class_superunion[N_REG_CLASSES][N_REG_CLASSES];
 
 /* Array containing all of the register names.  */
 
-const char * reg_names[] = 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.  */
 
@@ -230,6 +235,9 @@ static move_table *may_move_in_cost[MAX_MACHINE_MODE];
 
 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
@@ -298,19 +306,12 @@ init_reg_sets (void)
          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
+  /* 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.  */
@@ -319,7 +320,6 @@ static void
 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;
 
@@ -339,14 +339,14 @@ init_move_cost (enum machine_mode m)
          all_match &= (last_move_cost[i][j] == cost);
          last_move_cost[i][j] = cost;
        }
-  if (all_match && last_mode != -1)
+  if (all_match && last_mode_for_init_move_cost != -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];
+      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 = m;
+  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)
@@ -412,6 +412,31 @@ init_reg_sets_1 (void)
   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.  */
 
@@ -431,6 +456,7 @@ init_reg_sets_1 (void)
      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++)
@@ -453,6 +479,7 @@ init_reg_sets_1 (void)
      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++)
@@ -511,6 +538,7 @@ init_reg_sets_1 (void)
   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);
 
@@ -564,6 +592,18 @@ init_reg_sets_1 (void)
        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++)
@@ -582,14 +622,36 @@ init_reg_sets_1 (void)
             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).  */
+   (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_once (void)
+init_reg_modes_target (void)
 {
   int i, j;
 
@@ -611,8 +673,10 @@ init_reg_modes_once (void)
     }
 }
 
-/* Finish initializing the register sets and
-   initialize the register modes.  */
+/* 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)
@@ -782,11 +846,11 @@ fix_register (const char *name, int fixed, int call_used)
        }
       else
        {
-         fixed_regs[i] = fixed;
-         call_used_regs[i] = call_used;
+         initial_fixed_regs[i] = fixed;
+         initial_call_used_regs[i] = call_used;
 #ifdef CALL_REALLY_USED_REGISTERS
          if (fixed == 0)
-           call_really_used_regs[i] = call_used;
+           initial_call_really_used_regs[i] = call_used;
 #endif
        }
     }
@@ -1157,6 +1221,7 @@ init_reg_autoinc (void)
 #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 0d6b632..4178969 100644 (file)
@@ -448,7 +448,8 @@ static int reloads_conflict (int, int);
 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.  */
+/* 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 9f36cda..8599658 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -2077,6 +2077,7 @@ extern int get_max_uid (void);
 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);
@@ -2186,7 +2187,7 @@ extern void build_insn_chain (rtx);
 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_reg_modes_target (void);
 extern void init_regs (void);
 extern void init_fake_stack_mems (void);
 extern void init_reg_sets (void);
@@ -2254,7 +2255,7 @@ extern int canon_true_dependence (const_rtx, enum machine_mode, rtx, const_rtx,
 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_target (void);
 extern void init_alias_analysis (void);
 extern void end_alias_analysis (void);
 extern bool memory_modified_in_insn_p (const_rtx, const_rtx);
index c138c17..fe7918f 100644 (file)
@@ -1685,6 +1685,31 @@ target_supports_section_anchors_p (void)
   return true;
 }
 
+/* Default the align_* 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)
@@ -1730,23 +1755,6 @@ process_options (void)
   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)
@@ -1998,7 +2006,50 @@ process_options (void)
     }
 }
 
-/* Initialize the compiler back end.  */
+/* 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)
 {
@@ -2011,19 +2062,34 @@ backend_init (void)
                    || flag_test_coverage);
 
   init_rtlanal ();
-  init_regs ();
-  init_fake_stack_mems ();
-  init_alias_once ();
   init_inline_once ();
-  init_reload ();
   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 ();
-  init_expmed ();
-  if (flag_caller_saves)
-    init_caller_save ();
+
+  /* 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 ();
 }
 
@@ -2048,21 +2114,12 @@ lang_dependent_init (const char *name)
 
   init_asm_output (name);
 
-  /* These create various _DECL nodes, so need to be called after the
+  /* This creates various _DECL nodes, so needs 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 ();
+  /* 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.  */
@@ -2082,6 +2139,19 @@ lang_dependent_init (const char *name)
   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 906fd3d..2397dee 100644 (file)
@@ -101,6 +101,8 @@ extern void write_global_declarations (void);
 
 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;