| Index: gcc/gcc/reginfo.c
|
| diff --git a/gcc/gcc/reginfo.c b/gcc/gcc/reginfo.c
|
| index e579c281aa3a65c592e7f389b6efd80a8b54443c..bf43d702da55f43073b4c5baa7a8150557a05a9e 100644
|
| --- a/gcc/gcc/reginfo.c
|
| +++ b/gcc/gcc/reginfo.c
|
| @@ -101,13 +101,11 @@ char call_really_used_regs[] = CALL_REALLY_USED_REGISTERS;
|
| #endif
|
|
|
|
|
| -/* Indexed by hard register number, contains 1 for registers that are
|
| - fixed use or call used registers that cannot hold quantities across
|
| - calls even if we are willing to save and restore them. call fixed
|
| - registers are a subset of call used registers. */
|
| -char call_fixed_regs[FIRST_PSEUDO_REGISTER];
|
| +/* Contains registers that are fixed use -- i.e. in fixed_reg_set -- or
|
| + a function value return register or TARGET_STRUCT_VALUE_RTX or
|
| + STATIC_CHAIN_REGNUM. These are the registers that cannot hold quantities
|
| + across calls even if we are willing to save and restore them. */
|
|
|
| -/* The same info as a HARD_REG_SET. */
|
| HARD_REG_SET call_fixed_reg_set;
|
|
|
| /* Indexed by hard register number, contains 1 for registers
|
| @@ -277,7 +275,8 @@ init_move_cost (enum machine_mode m)
|
| cost = 65535;
|
| else
|
| {
|
| - cost = REGISTER_MOVE_COST (m, i, j);
|
| + cost = REGISTER_MOVE_COST (m, (enum reg_class) i,
|
| + (enum reg_class) j);
|
| gcc_assert (cost < 65535);
|
| }
|
| all_match &= (last_move_cost[i][j] == cost);
|
| @@ -327,12 +326,12 @@ init_move_cost (enum machine_mode m)
|
| gcc_assert (cost <= 65535);
|
| move_cost[m][i][j] = cost;
|
|
|
| - if (reg_class_subset_p (i, j))
|
| + if (reg_class_subset_p ((enum reg_class) i, (enum reg_class) j))
|
| may_move_in_cost[m][i][j] = 0;
|
| else
|
| may_move_in_cost[m][i][j] = cost;
|
|
|
| - if (reg_class_subset_p (j, i))
|
| + if (reg_class_subset_p ((enum reg_class) j, (enum reg_class) i))
|
| may_move_out_cost[m][i][j] = 0;
|
| else
|
| may_move_out_cost[m][i][j] = cost;
|
| @@ -514,8 +513,6 @@ init_reg_sets_1 (void)
|
| else
|
| CLEAR_REG_SET (regs_invalidated_by_call_regset);
|
|
|
| - memcpy (call_fixed_regs, fixed_regs, sizeof call_fixed_regs);
|
| -
|
| for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
|
| {
|
| /* call_used_regs must include fixed_regs. */
|
| @@ -530,8 +527,6 @@ init_reg_sets_1 (void)
|
|
|
| if (call_used_regs[i])
|
| SET_HARD_REG_BIT (call_used_reg_set, i);
|
| - if (call_fixed_regs[i])
|
| - SET_HARD_REG_BIT (call_fixed_reg_set, i);
|
|
|
| /* There are a couple of fixed registers that we know are safe to
|
| exclude from being clobbered by calls:
|
| @@ -570,12 +565,14 @@ init_reg_sets_1 (void)
|
| }
|
| }
|
|
|
| + COPY_HARD_REG_SET(call_fixed_reg_set, fixed_reg_set);
|
| +
|
| /* 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;
|
| + fixed_regs[i] = call_used_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);
|
| @@ -589,11 +586,13 @@ init_reg_sets_1 (void)
|
| HARD_REG_SET ok_regs;
|
| CLEAR_HARD_REG_SET (ok_regs);
|
| for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
|
| - if (!fixed_regs [j] && HARD_REGNO_MODE_OK (j, m))
|
| + if (!fixed_regs [j] && HARD_REGNO_MODE_OK (j, (enum machine_mode) m))
|
| SET_HARD_REG_BIT (ok_regs, j);
|
| -
|
| +
|
| for (i = 0; i < N_REG_CLASSES; i++)
|
| - if ((unsigned) CLASS_MAX_NREGS (i, m) <= reg_class_size[i]
|
| + if (((unsigned) CLASS_MAX_NREGS ((enum reg_class) i,
|
| + (enum machine_mode) m)
|
| + <= reg_class_size[i])
|
| && hard_reg_set_intersect_p (ok_regs, reg_class_contents[i]))
|
| {
|
| contains_reg_of_mode [i][m] = 1;
|
| @@ -667,6 +666,8 @@ void
|
| reinit_regs (void)
|
| {
|
| init_regs ();
|
| + /* caller_save needs to be re-initialized. */
|
| + caller_save_initialized_p = false;
|
| ira_init ();
|
| }
|
|
|
| @@ -676,9 +677,9 @@ void
|
| init_fake_stack_mems (void)
|
| {
|
| int i;
|
| -
|
| +
|
| for (i = 0; i < MAX_MACHINE_MODE; i++)
|
| - top_of_stack[i] = gen_rtx_MEM (i, stack_pointer_rtx);
|
| + top_of_stack[i] = gen_rtx_MEM ((enum machine_mode) i, stack_pointer_rtx);
|
| }
|
|
|
|
|
| @@ -867,7 +868,7 @@ globalize_reg (int i)
|
| if (fixed_regs[i])
|
| return;
|
|
|
| - fixed_regs[i] = call_used_regs[i] = call_fixed_regs[i] = 1;
|
| + fixed_regs[i] = call_used_regs[i] = 1;
|
| #ifdef CALL_REALLY_USED_REGISTERS
|
| call_really_used_regs[i] = 1;
|
| #endif
|
| @@ -895,12 +896,19 @@ struct reg_pref
|
| but since it is recommended that there be a class corresponding to the
|
| union of most major pair of classes, that generality is not required. */
|
| char altclass;
|
| +
|
| + /* coverclass is a register class that IRA uses for allocating
|
| + the pseudo. */
|
| + char coverclass;
|
| };
|
|
|
| /* Record preferences of each pseudo. This is available after RA is
|
| run. */
|
| static struct reg_pref *reg_pref;
|
|
|
| +/* Current size of reg_info. */
|
| +static int reg_info_size;
|
| +
|
| /* Return the reg_class in which pseudo reg number REGNO is best allocated.
|
| This function is sometimes called before the info has been computed.
|
| When that happens, just return GENERAL_REGS, which is innocuous. */
|
| @@ -922,65 +930,53 @@ reg_alternate_class (int regno)
|
| return (enum reg_class) reg_pref[regno].altclass;
|
| }
|
|
|
| -/* Initialize some global data for this pass. */
|
| -static unsigned int
|
| -reginfo_init (void)
|
| +/* Return the reg_class which is used by IRA for its allocation. */
|
| +enum reg_class
|
| +reg_cover_class (int regno)
|
| {
|
| - if (df)
|
| - df_compute_regs_ever_live (true);
|
| -
|
| - /* This prevents dump_flow_info from losing if called
|
| - before reginfo is run. */
|
| - reg_pref = NULL;
|
| + if (reg_pref == 0)
|
| + return NO_REGS;
|
|
|
| - /* No more global register variables may be declared. */
|
| - no_global_reg_vars = 1;
|
| - return 1;
|
| + return (enum reg_class) reg_pref[regno].coverclass;
|
| }
|
|
|
| -struct rtl_opt_pass pass_reginfo_init =
|
| -{
|
| - {
|
| - RTL_PASS,
|
| - "reginfo", /* name */
|
| - NULL, /* gate */
|
| - reginfo_init, /* execute */
|
| - NULL, /* sub */
|
| - NULL, /* next */
|
| - 0, /* static_pass_number */
|
| - 0, /* tv_id */
|
| - 0, /* properties_required */
|
| - 0, /* properties_provided */
|
| - 0, /* properties_destroyed */
|
| - 0, /* todo_flags_start */
|
| - 0 /* todo_flags_finish */
|
| - }
|
| -};
|
| -
|
|
|
|
|
| /* Allocate space for reg info. */
|
| -void
|
| +static void
|
| allocate_reg_info (void)
|
| {
|
| - int size = max_reg_num ();
|
| -
|
| + reg_info_size = max_reg_num ();
|
| gcc_assert (! reg_pref && ! reg_renumber);
|
| - reg_renumber = XNEWVEC (short, size);
|
| - reg_pref = XCNEWVEC (struct reg_pref, size);
|
| - memset (reg_renumber, -1, size * sizeof (short));
|
| + reg_renumber = XNEWVEC (short, reg_info_size);
|
| + reg_pref = XCNEWVEC (struct reg_pref, reg_info_size);
|
| + memset (reg_renumber, -1, reg_info_size * sizeof (short));
|
| }
|
|
|
|
|
| -/* Resize reg info. The new elements will be uninitialized. */
|
| -void
|
| +/* Resize reg info. The new elements will be uninitialized. Return
|
| + TRUE if new elements (for new pseudos) were added. */
|
| +bool
|
| resize_reg_info (void)
|
| {
|
| - int size = max_reg_num ();
|
| + int old;
|
|
|
| + if (reg_pref == NULL)
|
| + {
|
| + allocate_reg_info ();
|
| + return true;
|
| + }
|
| + if (reg_info_size == max_reg_num ())
|
| + return false;
|
| + old = reg_info_size;
|
| + reg_info_size = max_reg_num ();
|
| gcc_assert (reg_pref && reg_renumber);
|
| - reg_renumber = XRESIZEVEC (short, reg_renumber, size);
|
| - reg_pref = XRESIZEVEC (struct reg_pref, reg_pref, size);
|
| + reg_renumber = XRESIZEVEC (short, reg_renumber, reg_info_size);
|
| + reg_pref = XRESIZEVEC (struct reg_pref, reg_pref, reg_info_size);
|
| + memset (reg_pref + old, -1,
|
| + (reg_info_size - old) * sizeof (struct reg_pref));
|
| + memset (reg_renumber + old, -1, (reg_info_size - old) * sizeof (short));
|
| + return true;
|
| }
|
|
|
|
|
| @@ -1001,19 +997,55 @@ free_reg_info (void)
|
| }
|
| }
|
|
|
| +/* Initialize some global data for this pass. */
|
| +static unsigned int
|
| +reginfo_init (void)
|
| +{
|
| + if (df)
|
| + df_compute_regs_ever_live (true);
|
| +
|
| + /* This prevents dump_flow_info from losing if called
|
| + before reginfo is run. */
|
| + reg_pref = NULL;
|
| + /* No more global register variables may be declared. */
|
| + no_global_reg_vars = 1;
|
| + return 1;
|
| +}
|
| +
|
| +struct rtl_opt_pass pass_reginfo_init =
|
| +{
|
| + {
|
| + RTL_PASS,
|
| + "reginfo", /* name */
|
| + NULL, /* gate */
|
| + reginfo_init, /* execute */
|
| + NULL, /* sub */
|
| + NULL, /* next */
|
| + 0, /* static_pass_number */
|
| + TV_NONE, /* tv_id */
|
| + 0, /* properties_required */
|
| + 0, /* properties_provided */
|
| + 0, /* properties_destroyed */
|
| + 0, /* todo_flags_start */
|
| + 0 /* todo_flags_finish */
|
| + }
|
| +};
|
|
|
|
|
|
|
| -/* Set up preferred and alternate classes for REGNO as PREFCLASS and
|
| - ALTCLASS. */
|
| +/* Set up preferred, alternate, and cover classes for REGNO as
|
| + PREFCLASS, ALTCLASS, and COVERCLASS. */
|
| void
|
| setup_reg_classes (int regno,
|
| - enum reg_class prefclass, enum reg_class altclass)
|
| + enum reg_class prefclass, enum reg_class altclass,
|
| + enum reg_class coverclass)
|
| {
|
| if (reg_pref == NULL)
|
| return;
|
| + gcc_assert (reg_info_size == max_reg_num ());
|
| reg_pref[regno].prefclass = prefclass;
|
| reg_pref[regno].altclass = altclass;
|
| + reg_pref[regno].coverclass = coverclass;
|
| }
|
|
|
|
|
| @@ -1123,7 +1155,7 @@ reg_scan_mark_refs (rtx x, rtx insn)
|
| && REG_POINTER (SET_SRC (x)))
|
| || ((GET_CODE (SET_SRC (x)) == PLUS
|
| || GET_CODE (SET_SRC (x)) == LO_SUM)
|
| - && GET_CODE (XEXP (SET_SRC (x), 1)) == CONST_INT
|
| + && CONST_INT_P (XEXP (SET_SRC (x), 1))
|
| && REG_P (XEXP (SET_SRC (x), 0))
|
| && REG_POINTER (XEXP (SET_SRC (x), 0)))
|
| || GET_CODE (SET_SRC (x)) == CONST
|
| @@ -1268,7 +1300,7 @@ record_subregs_of_mode (rtx subreg)
|
| }
|
|
|
| /* Call record_subregs_of_mode for all the subregs in X. */
|
| -static void
|
| +static void
|
| find_subregs_of_mode (rtx x)
|
| {
|
| enum rtx_code code = GET_CODE (x);
|
| @@ -1277,7 +1309,7 @@ find_subregs_of_mode (rtx x)
|
|
|
| if (code == SUBREG)
|
| record_subregs_of_mode (x);
|
| -
|
| +
|
| /* Time for some deep diving. */
|
| for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
|
| {
|
| @@ -1292,7 +1324,7 @@ find_subregs_of_mode (rtx x)
|
| }
|
| }
|
|
|
| -static unsigned int
|
| +void
|
| init_subregs_of_mode (void)
|
| {
|
| basic_block bb;
|
| @@ -1307,36 +1339,6 @@ init_subregs_of_mode (void)
|
| FOR_BB_INSNS (bb, insn)
|
| if (INSN_P (insn))
|
| find_subregs_of_mode (PATTERN (insn));
|
| -
|
| - return 0;
|
| -}
|
| -
|
| -/* Set bits in *USED which correspond to registers which can't change
|
| - their mode from FROM to any mode in which REGNO was
|
| - encountered. */
|
| -void
|
| -cannot_change_mode_set_regs (HARD_REG_SET *used, enum machine_mode from,
|
| - unsigned int regno)
|
| -{
|
| - struct subregs_of_mode_node dummy, *node;
|
| - enum machine_mode to;
|
| - unsigned char mask;
|
| - unsigned int i;
|
| -
|
| - gcc_assert (subregs_of_mode);
|
| - dummy.block = regno & -8;
|
| - node = (struct subregs_of_mode_node *)
|
| - htab_find_with_hash (subregs_of_mode, &dummy, dummy.block);
|
| - if (node == NULL)
|
| - return;
|
| -
|
| - mask = 1 << (regno & 7);
|
| - for (to = VOIDmode; to < NUM_MACHINE_MODES; to++)
|
| - if (node->modes[to] & mask)
|
| - for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
|
| - if (!TEST_HARD_REG_BIT (*used, i)
|
| - && REG_CANNOT_CHANGE_MODE_P (i, from, to))
|
| - SET_HARD_REG_BIT (*used, i);
|
| }
|
|
|
| /* Return 1 if REGNO has had an invalid mode change in CLASS from FROM
|
| @@ -1347,7 +1349,7 @@ invalid_mode_change_p (unsigned int regno,
|
| enum machine_mode from)
|
| {
|
| struct subregs_of_mode_node dummy, *node;
|
| - enum machine_mode to;
|
| + unsigned int to;
|
| unsigned char mask;
|
|
|
| gcc_assert (subregs_of_mode);
|
| @@ -1360,80 +1362,28 @@ invalid_mode_change_p (unsigned int regno,
|
| mask = 1 << (regno & 7);
|
| for (to = VOIDmode; to < NUM_MACHINE_MODES; to++)
|
| if (node->modes[to] & mask)
|
| - if (CANNOT_CHANGE_MODE_CLASS (from, to, rclass))
|
| + if (CANNOT_CHANGE_MODE_CLASS (from, (enum machine_mode) to, rclass))
|
| return true;
|
|
|
| return false;
|
| }
|
|
|
| -static unsigned int
|
| +void
|
| finish_subregs_of_mode (void)
|
| {
|
| htab_delete (subregs_of_mode);
|
| subregs_of_mode = 0;
|
| - return 0;
|
| }
|
| #else
|
| -static unsigned int
|
| +void
|
| init_subregs_of_mode (void)
|
| {
|
| - return 0;
|
| }
|
| -static unsigned int
|
| +void
|
| finish_subregs_of_mode (void)
|
| {
|
| - return 0;
|
| }
|
|
|
| #endif /* CANNOT_CHANGE_MODE_CLASS */
|
|
|
| -static bool
|
| -gate_subregs_of_mode_init (void)
|
| -{
|
| -#ifdef CANNOT_CHANGE_MODE_CLASS
|
| - return true;
|
| -#else
|
| - return false;
|
| -#endif
|
| -}
|
| -
|
| -struct rtl_opt_pass pass_subregs_of_mode_init =
|
| -{
|
| - {
|
| - RTL_PASS,
|
| - "subregs_of_mode_init", /* name */
|
| - gate_subregs_of_mode_init, /* gate */
|
| - init_subregs_of_mode, /* execute */
|
| - NULL, /* sub */
|
| - NULL, /* next */
|
| - 0, /* static_pass_number */
|
| - 0, /* tv_id */
|
| - 0, /* properties_required */
|
| - 0, /* properties_provided */
|
| - 0, /* properties_destroyed */
|
| - 0, /* todo_flags_start */
|
| - 0 /* todo_flags_finish */
|
| - }
|
| -};
|
| -
|
| -struct rtl_opt_pass pass_subregs_of_mode_finish =
|
| -{
|
| - {
|
| - RTL_PASS,
|
| - "subregs_of_mode_finish", /* name */
|
| - gate_subregs_of_mode_init, /* gate */
|
| - finish_subregs_of_mode, /* execute */
|
| - NULL, /* sub */
|
| - NULL, /* next */
|
| - 0, /* static_pass_number */
|
| - 0, /* tv_id */
|
| - 0, /* properties_required */
|
| - 0, /* properties_provided */
|
| - 0, /* properties_destroyed */
|
| - 0, /* todo_flags_start */
|
| - 0 /* todo_flags_finish */
|
| - }
|
| -};
|
| -
|
| -
|
| #include "gt-reginfo.h"
|
|
|