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" |