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