From b8c651c617d97316a4f2080daeffb0615bc8c058 Mon Sep 17 00:00:00 2001 From: vmakarov Date: Fri, 12 Jan 2007 22:08:10 +0000 Subject: [PATCH] 2007-01-12 Vladimir Makarov * doc/tm.texi (IRA_HARD_REGNO_ADD_COST_MULTIPLIER): New macro. * ira-conflicts.c (add_pseudo_copies): Add copy between output and died operand pseudos. * ira.c (setup_cover_classes, setup_class_translate): Define and call only when IRA_COVER_CLASSES is defined. (no_alloc_regs): Rename to no_unit_alloc_regs. (setup_eliminable_regset): Set up no_alloc_regs. * ira-costs.c (tune_pseudo_costs_and_cover_classes): Modify cost if IRA_HARD_REGNO_ADD_COST_MULTIPLIER is defined. * config/s390/s390.h (IRA_COVER_CLASSES, IRA_HARD_REGNO_ADD_COST_MULTIPLIER(regno)): Define. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/ira@120734 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 18 +++++++++++++ gcc/config/s390/s390.h | 24 +++++++++++++++++ gcc/doc/tm.texi | 10 +++++++ gcc/ira-conflicts.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++---- gcc/ira-costs.c | 5 ++++ gcc/ira.c | 46 +++++++++++++++++++++++--------- 6 files changed, 156 insertions(+), 18 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index cec58065297..ed13d68a54e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,21 @@ +2007-01-12 Vladimir Makarov + + * doc/tm.texi (IRA_HARD_REGNO_ADD_COST_MULTIPLIER): New macro. + + * ira-conflicts.c (add_pseudo_copies): Add copy between output and + died operand pseudos. + + * ira.c (setup_cover_classes, setup_class_translate): Define and + call only when IRA_COVER_CLASSES is defined. + (no_alloc_regs): Rename to no_unit_alloc_regs. + (setup_eliminable_regset): Set up no_alloc_regs. + + * ira-costs.c (tune_pseudo_costs_and_cover_classes): Modify cost + if IRA_HARD_REGNO_ADD_COST_MULTIPLIER is defined. + + * config/s390/s390.h (IRA_COVER_CLASSES, + IRA_HARD_REGNO_ADD_COST_MULTIPLIER(regno)): Define. + 2006-12-22 Vladimir Makarov * rtl.h (setup_reg_classes): New function prototype. diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h index ba7a036e1ec..5fef005d9af 100644 --- a/gcc/config/s390/s390.h +++ b/gcc/config/s390/s390.h @@ -437,6 +437,30 @@ enum reg_class { 0xffffffff, 0x0000003f }, /* ALL_REGS */ \ } +/* The following macro defines cover classes for Integrated Register + Allocator. Cover classes is a set of non-intersected register + classes covering all hard registers used for register allocation + purpose. Any move between two registers of a cover class should be + cheaper than load or store of the registers. The macro value is + array of register classes with LIM_REG_CLASSES used as the end + marker. */ + +#define IRA_COVER_CLASSES \ +{ \ + GENERAL_REGS, FP_REGS, CC_REGS, ACCESS_REGS, LIM_REG_CLASSES \ +} + +/* In some case register allocation order is not enough for IRA to + generate a good code. The following macro (if defined) increases + cost of REGNO for a pseudo approximately by pseudo usage frequency + multiplied by the macro value. + + We avoid usage of BASE_REGNUM by nonzero macro value because the + reload can decide not to use the hard register because some + constant was forced to be in memory. */ +#define IRA_HARD_REGNO_ADD_COST_MULTIPLIER(regno) \ + (regno == BASE_REGNUM ? 0.0 : 0.5) + /* Register -> class mapping. */ extern const enum reg_class regclass_map[FIRST_PSEUDO_REGISTER]; #define REGNO_REG_CLASS(REGNO) (regclass_map[REGNO]) diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 55b4b4c70bc..60d54cb5a12 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -1956,6 +1956,16 @@ The macro body should not assume anything about the contents of On most machines, it is not necessary to define this macro. @end defmac +@defmac IRA_HARD_REGNO_ADD_COST_MULTIPLIER (@var{regno}) +In some case register allocation order is not enough for the +Integrated Register Allocator (@acronym{IRA}) to generate a good code. +The following macro (if defined) increases cost of @var{regno} for a +pseudo approximately by pseudo usage frequency multiplied by the macro +value. + +On most machines, it is not necessary to define this macro. +@end defmac + @node Values in Registers @subsection How Values Fit in Registers diff --git a/gcc/ira-conflicts.c b/gcc/ira-conflicts.c index b14a877e6d5..1f02a9c1667 100644 --- a/gcc/ira-conflicts.c +++ b/gcc/ira-conflicts.c @@ -660,7 +660,7 @@ add_pseudo_copies (rtx insn) { rtx set, operand, dup; const char *str; - int commut_p; + int commut_p, bound_p; int i, j, freq, hard_regno, cost, index; copy_t cp; pseudo_t p; @@ -729,6 +729,7 @@ add_pseudo_copies (rtx insn) str = recog_data.constraints [i]; while (*str == ' ' && *str == '\t') str++; + bound_p = FALSE; for (j = 0, commut_p = FALSE; j < 2; j++, commut_p = TRUE) if ((dup = get_dup (i, commut_p)) != NULL_RTX && REG_P (dup) && GET_MODE (operand) == GET_MODE (dup)) @@ -758,16 +759,19 @@ add_pseudo_copies (rtx insn) if (index < 0) continue; if (HARD_REGISTER_P (operand)) - cost = (register_move_cost - [mode] [cover_class] [class] * freq); + cost + = register_move_cost [mode] [cover_class] [class]; else - cost = (register_move_cost - [mode] [class] [cover_class] * freq); + cost + = register_move_cost [mode] [class] [cover_class]; + cost *= freq; PSEUDO_HARD_REG_COSTS (p) [index] -= cost; PSEUDO_CONFLICT_HARD_REG_COSTS (p) [index] -= cost; + bound_p = TRUE; } else { + bound_p = TRUE; cp = add_pseudo_copy (curr_regno_pseudo_map [REGNO (dup)], curr_regno_pseudo_map [REGNO (operand)], @@ -776,6 +780,63 @@ add_pseudo_copies (rtx insn) (ira_curr_loop_tree_node->local_copies, cp->num); } } + if (bound_p) + continue; + /* If an operand dies, prefer its hard register for the + output operands by decreasing the hard register cost + or creating the corresponding pseudo copies. */ + for (j = 0; j < recog_data.n_operands; j++) + { + dup = recog_data.operand [j]; + + if (i == j || recog_data.operand_type [j] != OP_OUT + || !REG_P (dup)) + continue; + + if (HARD_REGISTER_NUM_P (REGNO (operand)) + || HARD_REGISTER_NUM_P (REGNO (dup))) + { + if (HARD_REGISTER_P (operand)) + { + if (HARD_REGISTER_P (dup)) + continue; + hard_regno = REGNO (operand); + p = curr_regno_pseudo_map [REGNO (dup)]; + } + else + { + hard_regno = REGNO (dup); + p = curr_regno_pseudo_map [REGNO (operand)]; + } + class = REGNO_REG_CLASS (hard_regno); + mode = PSEUDO_MODE (p); + cover_class = PSEUDO_COVER_CLASS (p); + if (! class_subset_p [class] [cover_class]) + continue; + index + = class_hard_reg_index [cover_class] [hard_regno]; + if (index < 0) + continue; + if (HARD_REGISTER_P (operand)) + cost + = register_move_cost [mode] [cover_class] [class]; + else + cost + = register_move_cost [mode] [class] [cover_class]; + cost *= (freq < 4 ? 1 : freq / 4); + PSEUDO_HARD_REG_COSTS (p) [index] -= cost; + PSEUDO_CONFLICT_HARD_REG_COSTS (p) [index] -= cost; + } + else + { + cp = add_pseudo_copy + (curr_regno_pseudo_map [REGNO (dup)], + curr_regno_pseudo_map [REGNO (operand)], + (freq < 4 ? 1 : freq / 4), NULL_RTX); + bitmap_set_bit + (ira_curr_loop_tree_node->local_copies, cp->num); + } + } } } } diff --git a/gcc/ira-costs.c b/gcc/ira-costs.c index acfcd816ef1..bb3598f9166 100644 --- a/gcc/ira-costs.c +++ b/gcc/ira-costs.c @@ -1370,6 +1370,11 @@ tune_pseudo_costs_and_cover_classes (void) cost += (PSEUDO_CALL_FREQ (p) * (memory_move_cost [mode] [class] [0] + memory_move_cost [mode] [class] [1])); +#ifdef IRA_HARD_REGNO_ADD_COST_MULTIPLIER + cost += ((memory_move_cost [mode] [class] [0] + + memory_move_cost [mode] [class] [1]) * PSEUDO_FREQ (p) + * IRA_HARD_REGNO_ADD_COST_MULTIPLIER (regno) / 2); +#endif reg_costs [j] += cost; if (min_cost > reg_costs [j]) min_cost = reg_costs [j]; diff --git a/gcc/ira.c b/gcc/ira.c index 6a3d4eb54f6..1fb9a99320c 100644 --- a/gcc/ira.c +++ b/gcc/ira.c @@ -99,8 +99,10 @@ static void setup_class_hard_regs (void); static void setup_available_class_regs (void); static void setup_alloc_regs (int); static void setup_reg_subclasses (void); +#ifdef IRA_COVER_CLASSES static void setup_cover_classes (void); static void setup_class_translate (void); +#endif static void print_class_cover (FILE *); static void find_reg_class_closure (void); static void setup_reg_class_nregs (void); @@ -240,6 +242,10 @@ setup_class_subset_and_move_costs (void) +/* Hard registers can not be used for the register allocator for all + functions of the current compile unit. */ +static HARD_REG_SET no_unit_alloc_regs; + /* Hard registers which can be used for the allocation of given register class. The order is defined by the allocation order. */ short class_hard_regs [N_REG_CLASSES] [FIRST_PSEUDO_REGISTER]; @@ -266,7 +272,7 @@ setup_class_hard_regs (void) for (cl = (int) N_REG_CLASSES - 1; cl >= 0; cl--) { COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents [cl]); - AND_COMPL_HARD_REG_SET (temp_hard_regset, no_alloc_regs); + AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs); CLEAR_HARD_REG_SET (processed_hard_reg_set); for (n = 0, i = 0; i < FIRST_PSEUDO_REGISTER; i++) { @@ -304,16 +310,13 @@ setup_available_class_regs (void) for (i = 0; i < N_REG_CLASSES; i++) { COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents [i]); - AND_COMPL_HARD_REG_SET (temp_hard_regset, no_alloc_regs); + AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs); for (j = 0; j < FIRST_PSEUDO_REGISTER; j++) if (TEST_HARD_REG_BIT (temp_hard_regset, j)) available_class_regs [i]++; } } -/* Hard registers can not be used for the register allocator. */ -HARD_REG_SET no_alloc_regs; - /* The function setting up different global variables defining hard registers for the allocation. It depends on USE_HARD_FRAME_P whose nonzero value means that we can use hard frame pointer for the @@ -321,9 +324,9 @@ HARD_REG_SET no_alloc_regs; static void setup_alloc_regs (int use_hard_frame_p) { - COPY_HARD_REG_SET (no_alloc_regs, fixed_reg_set); + COPY_HARD_REG_SET (no_unit_alloc_regs, fixed_reg_set); if (! use_hard_frame_p) - SET_HARD_REG_BIT (no_alloc_regs, HARD_FRAME_POINTER_REGNUM); + SET_HARD_REG_BIT (no_unit_alloc_regs, HARD_FRAME_POINTER_REGNUM); setup_class_hard_regs (); setup_available_class_regs (); } @@ -512,6 +515,8 @@ int reg_class_cover_size; enum reg_class reg_class_cover [N_REG_CLASSES]; +#ifdef IRA_COVER_CLASSES + /* The function checks IRA_COVER_CLASSES and sets the two global variables defined above. */ static void @@ -535,12 +540,15 @@ setup_cover_classes (void) ; } } +#endif /* Map of register classes to corresponding cover class containing the given class. If given class is not a subset of a cover class, we translate it into the cheapest cover class. */ enum reg_class class_translate [N_REG_CLASSES]; +#ifdef IRA_COVER_CLASSES + /* The function sets up array CLASS_TRANSLATE. */ static void setup_class_translate (void) @@ -610,6 +618,7 @@ setup_class_translate (void) class_translate [cl] = best_class; } } +#endif /* The function outputs all cover classes and the translation map into file F. */ @@ -642,8 +651,10 @@ static void find_reg_class_closure (void) { setup_reg_subclasses (); +#ifdef IRA_COVER_CLASSES setup_cover_classes (); setup_class_translate (); +#endif } @@ -728,7 +739,11 @@ init_ira_once (void) -/* The function sets up ELIMINABLE_REGSET and REGS_EVER_LIVE. */ +/* Function specific hard registers excluded from the allocation. */ +HARD_REG_SET no_alloc_regs; + +/* The function sets up ELIMINABLE_REGSET, NO_ALLOC_REGS, and + REGS_EVER_LIVE. */ static void setup_eliminable_regset (void) { @@ -741,6 +756,7 @@ setup_eliminable_regset (void) || (current_function_calls_alloca && EXIT_IGNORE_STACK) || FRAME_POINTER_REQUIRED); + COPY_HARD_REG_SET (no_alloc_regs, no_unit_alloc_regs); CLEAR_HARD_REG_SET (eliminable_regset); /* Build the regset of all eliminable registers and show we can't use those that we already know won't be eliminated. */ @@ -753,8 +769,10 @@ setup_eliminable_regset (void) if (! regs_asm_clobbered [eliminables [i].from]) { - if (! cannot_elim) SET_HARD_REG_BIT (eliminable_regset, eliminables [i].from); + + if (cannot_elim) + SET_HARD_REG_BIT (no_alloc_regs, eliminables[i].from); } else if (cannot_elim) error ("%s cannot be used in asm here", @@ -765,8 +783,9 @@ setup_eliminable_regset (void) #if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM if (! regs_asm_clobbered [HARD_FRAME_POINTER_REGNUM]) { - if (! need_fp) - SET_HARD_REG_BIT (eliminable_regset, HARD_FRAME_POINTER_REGNUM); + SET_HARD_REG_BIT (eliminable_regset, HARD_FRAME_POINTER_REGNUM); + if (need_fp) + SET_HARD_REG_BIT (no_alloc_regs, HARD_FRAME_POINTER_REGNUM); } else if (need_fp) error ("%s cannot be used in asm here", @@ -778,8 +797,9 @@ setup_eliminable_regset (void) #else if (! regs_asm_clobbered [FRAME_POINTER_REGNUM]) { - if (! need_fp) - SET_HARD_REG_BIT (eliminable_regset, FRAME_POINTER_REGNUM); + SET_HARD_REG_BIT (eliminable_regset, FRAME_POINTER_REGNUM); + if (need_fp) + SET_HARD_REG_BIT (no_alloc_regs, FRAME_POINTER_REGNUM); } else if (need_fp) error ("%s cannot be used in asm here", reg_names [FRAME_POINTER_REGNUM]); -- 2.11.4.GIT