diff options
-rw-r--r-- | gcc/ChangeLog | 26 | ||||
-rw-r--r-- | gcc/common.opt | 5 | ||||
-rw-r--r-- | gcc/doc/invoke.texi | 10 | ||||
-rw-r--r-- | gcc/gcse.c | 370 | ||||
-rw-r--r-- | gcc/haifa-sched.c | 2 | ||||
-rw-r--r-- | gcc/ira-costs.c | 9 | ||||
-rw-r--r-- | gcc/ira.c | 2 | ||||
-rw-r--r-- | gcc/ira.h | 4 | ||||
-rw-r--r-- | gcc/loop-invariant.c | 4 | ||||
-rw-r--r-- | gcc/regmove.c | 5 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/hoist-register-pressure.c | 31 |
12 files changed, 430 insertions, 42 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 93cc988..9b09aaa 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,31 @@ 2012-10-19 Bin Cheng <bin.cheng@arm.com> + * common.opt (flag_ira_hoist_pressure): New. + * doc/invoke.texi (-fira-hoist-pressure): Describe. + * ira-costs.c (ira_set_pseudo_classes): New parameter. + * ira.h: Update copyright dates. + (ira_set_pseudo_classes): Update prototype. + * haifa-sched.c (sched_init): Update call. + * ira.c (ira): Update call. + * regmove.c: Update copyright dates. + (regmove_optimize): Update call. + * loop-invariant.c: Update copyright dates. + (move_loop_invariants): Update call. + * gcse.c: (struct bb_data): New structure. + (BB_DATA): New macro. + (curr_bb, curr_reg_pressure): New static variables. + (should_hoist_expr_to_dom): Rename from hoist_expr_reaches_here_p. + Change parameter expr_index to expr. + New parameters pressure_class, nregs and hoisted_bbs. + Use reg pressure to determine the distance expr can be hoisted. + (hoist_code): Use reg pressure to direct the hoist process. + (get_regno_pressure_class, get_pressure_class_and_nregs) + (change_pressure, calculate_bb_reg_pressure): New. + (one_code_hoisting_pass): Calculate register pressure. Allocate + and free data. + +2012-10-19 Bin Cheng <bin.cheng@arm.com> + * gcse.c: Update copyright dates. (hoist_expr_reaches_here_p): Change parameter type from char * to sbitmap. diff --git a/gcc/common.opt b/gcc/common.opt index e21fb71..5b69aff 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -1392,6 +1392,11 @@ Enum(ira_region) String(all) Value(IRA_REGION_ALL) EnumValue Enum(ira_region) String(mixed) Value(IRA_REGION_MIXED) +fira-hoist-pressure +Common Report Var(flag_ira_hoist_pressure) Init(1) Optimization +Use IRA based register pressure calculation +in RTL hoist optimizations. + fira-loop-pressure Common Report Var(flag_ira_loop_pressure) Use IRA based register pressure calculation diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index f8c9230..a66dff1 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -372,7 +372,7 @@ Objective-C and Objective-C++ Dialects}. -finline-small-functions -fipa-cp -fipa-cp-clone @gol -fipa-pta -fipa-profile -fipa-pure-const -fipa-reference @gol -fira-algorithm=@var{algorithm} @gol --fira-region=@var{region} @gol +-fira-region=@var{region} -fira-hoist-pressure @gol -fira-loop-pressure -fno-ira-share-save-slots @gol -fno-ira-share-spill-slots -fira-verbose=@var{n} @gol -fivopts -fkeep-inline-functions -fkeep-static-consts @gol @@ -6996,6 +6996,14 @@ This typically results in the smallest code size, and is enabled by default for @end table +@item -fira-hoist-pressure +@opindex fira-hoist-pressure +Use IRA to evaluate register pressure in the code hoisting pass for +decisions to hoist expressions. This option usually results in smaller +code, but it can slow the compiler down. + +This option is enabled at level @option{-Os} for all targets. + @item -fira-loop-pressure @opindex fira-loop-pressure Use IRA to evaluate register pressure in loops for decisions to move @@ -20,9 +20,11 @@ along with GCC; see the file COPYING3. If not see /* TODO - reordering of memory allocation and freeing to be more space efficient - - do rough calc of how many regs are needed in each block, and a rough - calc of how many regs are available in each class and use that to - throttle back the code in cases where RTX_COST is minimal. + - simulate register pressure change of each basic block accurately during + hoist process. But I doubt the benefit since most expressions hoisted + are constant or address, which usually won't reduce register pressure. + - calc rough register pressure information and use the info to drive all + kinds of code motion (including code hoisting) in a unified way. */ /* References searched while implementing this. @@ -141,11 +143,12 @@ along with GCC; see the file COPYING3. If not see #include "diagnostic-core.h" #include "toplev.h" +#include "hard-reg-set.h" #include "rtl.h" #include "tree.h" #include "tm_p.h" #include "regs.h" -#include "hard-reg-set.h" +#include "ira.h" #include "flags.h" #include "insn-config.h" #include "recog.h" @@ -412,6 +415,22 @@ static bool doing_code_hoisting_p = false; /* For available exprs */ static sbitmap *ae_kill; +/* Data stored for each basic block. */ +struct bb_data +{ + /* Maximal register pressure inside basic block for given register class + (defined only for the pressure classes). */ + int max_reg_pressure[N_REG_CLASSES]; +}; + +#define BB_DATA(bb) ((struct bb_data *) (bb)->aux) + +static basic_block curr_bb; + +/* Current register pressure for each pressure class. */ +static int curr_reg_pressure[N_REG_CLASSES]; + + static void compute_can_copy (void); static void *gmalloc (size_t) ATTRIBUTE_MALLOC; static void *gcalloc (size_t, size_t) ATTRIBUTE_MALLOC; @@ -460,9 +479,11 @@ static void alloc_code_hoist_mem (int, int); static void free_code_hoist_mem (void); static void compute_code_hoist_vbeinout (void); static void compute_code_hoist_data (void); -static int hoist_expr_reaches_here_p (basic_block, int, basic_block, sbitmap, - int, int *); +static int should_hoist_expr_to_dom (basic_block, struct expr *, basic_block, + sbitmap, int, int *, enum reg_class, + int *, bitmap); static int hoist_code (void); +static enum reg_class get_pressure_class_and_nregs (rtx insn, int *nregs); static int one_code_hoisting_pass (void); static rtx process_insert_insn (struct expr *); static int pre_edge_insert (struct edge_list *, struct expr **); @@ -1858,7 +1879,7 @@ prune_expressions (bool pre_p) a basic block we should account for any side-effects of a subsequent jump instructions that could clobber the expression. It would be best to implement this check along the lines of - hoist_expr_reaches_here_p where the target block is already known + should_hoist_expr_to_dom where the target block is already known and, hence, there's no need to conservatively prune expressions on "intermediate" set-and-jump instructions. */ FOR_EACH_EDGE (e, ei, bb->preds) @@ -2826,10 +2847,21 @@ compute_code_hoist_data (void) fprintf (dump_file, "\n"); } -/* Determine if the expression identified by EXPR_INDEX would - reach BB unimpared if it was placed at the end of EXPR_BB. - Stop the search if the expression would need to be moved more - than DISTANCE instructions. +/* Determine if the expression EXPR should be hoisted to EXPR_BB up in + flow graph, if it can reach BB unimpared. Stop the search if the + expression would need to be moved more than DISTANCE instructions. + + DISTANCE is the number of instructions through which EXPR can be + hoisted up in flow graph. + + BB_SIZE points to an array which contains the number of instructions + for each basic block. + + PRESSURE_CLASS and NREGS are register class and number of hard registers + for storing EXPR. + + HOISTED_BBS points to a bitmap indicating basic blocks through which + EXPR is hoisted. It's unclear exactly what Muchnick meant by "unimpared". It seems to me that the expression must either be computed or transparent in @@ -2842,18 +2874,32 @@ compute_code_hoist_data (void) paths. */ static int -hoist_expr_reaches_here_p (basic_block expr_bb, int expr_index, basic_block bb, - sbitmap visited, int distance, int *bb_size) +should_hoist_expr_to_dom (basic_block expr_bb, struct expr *expr, + basic_block bb, sbitmap visited, int distance, + int *bb_size, enum reg_class pressure_class, + int *nregs, bitmap hoisted_bbs) { + unsigned int i; edge pred; edge_iterator ei; + sbitmap_iterator sbi; int visited_allocated_locally = 0; /* Terminate the search if distance, for which EXPR is allowed to move, is exhausted. */ if (distance > 0) { - distance -= bb_size[bb->index]; + /* Let EXPR be hoisted through basic block at no cost if the block + has low register pressure. An exception is constant expression, + because hoisting constant expr aggressively results in worse code. + The exception is made by the observation of CSiBE on ARM target, + while it has no obvious effect on other targets like x86, x86_64, + mips and powerpc. */ + if (!flag_ira_hoist_pressure + || (BB_DATA (bb)->max_reg_pressure[pressure_class] + >= ira_class_hard_regs_num[pressure_class] + || CONST_INT_P (expr->expr))) + distance -= bb_size[bb->index]; if (distance <= 0) return 0; @@ -2878,21 +2924,35 @@ hoist_expr_reaches_here_p (basic_block expr_bb, int expr_index, basic_block bb, continue; else if (TEST_BIT (visited, pred_bb->index)) continue; - - else if (! TEST_BIT (transp[pred_bb->index], expr_index)) + else if (! TEST_BIT (transp[pred_bb->index], expr->bitmap_index)) break; - /* Not killed. */ else { SET_BIT (visited, pred_bb->index); - if (! hoist_expr_reaches_here_p (expr_bb, expr_index, pred_bb, - visited, distance, bb_size)) + if (! should_hoist_expr_to_dom (expr_bb, expr, pred_bb, + visited, distance, bb_size, + pressure_class, nregs, hoisted_bbs)) break; } } if (visited_allocated_locally) - sbitmap_free (visited); + { + /* If EXPR can be hoisted to expr_bb, record basic blocks through + which EXPR is hoisted in hoisted_bbs. Also update register + pressure for basic blocks newly added in hoisted_bbs. */ + if (flag_ira_hoist_pressure && !pred) + { + EXECUTE_IF_SET_IN_SBITMAP (visited, 0, i, sbi) + if (!bitmap_bit_p (hoisted_bbs, i)) + { + bitmap_set_bit (hoisted_bbs, i); + BB_DATA (BASIC_BLOCK (i))->max_reg_pressure[pressure_class] + += *nregs; + } + } + sbitmap_free (visited); + } return (pred == NULL); } @@ -2909,7 +2969,44 @@ find_occr_in_bb (struct occr *occr, basic_block bb) return occr; } -/* Actually perform code hoisting. */ +/* Actually perform code hoisting. + + The code hoisting pass can hoist multiple computations of the same + expression along dominated path to a dominating basic block, like + from b2/b3 to b1 as depicted below: + + b1 ------ + /\ | + / \ | + bx by distance + / \ | + / \ | + b2 b3 ------ + + Unfortunately code hoisting generally extends the live range of an + output pseudo register, which increases register pressure and hurts + register allocation. To address this issue, an attribute MAX_DISTANCE + is computed and attached to each expression. The attribute is computed + from rtx cost of the corresponding expression and it's used to control + how long the expression can be hoisted up in flow graph. As the + expression is hoisted up in flow graph, GCC decreases its DISTANCE + and stops the hoist if DISTANCE reaches 0. + + Option "-fira-hoist-pressure" implements register pressure directed + hoist based on upper method. The rationale is: + 1. Calculate register pressure for each basic block by reusing IRA + facility. + 2. When expression is hoisted through one basic block, GCC checks + register pressure of the basic block and decrease DISTANCE only + when the register pressure is high. In other words, expression + will be hoisted through basic block with low register pressure + at no cost. + 3. Update register pressure information for basic blocks through + which expression is hoisted. + TODO: It is possible to have register pressure decreased because + of shrinked live ranges of input pseudo registers when hoisting + an expression. For now, this effect is not simulated and we just + increase register pressure for hoisted expressions. */ static int hoist_code (void) @@ -2918,12 +3015,18 @@ hoist_code (void) VEC (basic_block, heap) *dom_tree_walk; unsigned int dom_tree_walk_index; VEC (basic_block, heap) *domby; - unsigned int i,j; + unsigned int i, j, k; struct expr **index_map; struct expr *expr; int *to_bb_head; int *bb_size; int changed = 0; + struct bb_data *data; + /* Basic blocks that have occurrences reachable from BB. */ + bitmap from_bbs; + /* Basic blocks through which expr is hoisted. */ + bitmap hoisted_bbs = NULL; + bitmap_iterator bi; /* Compute a mapping from expression number (`bitmap_index') to hash table entry. */ @@ -2961,6 +3064,10 @@ hoist_code (void) && (EDGE_SUCC (ENTRY_BLOCK_PTR, 0)->dest == ENTRY_BLOCK_PTR->next_bb)); + from_bbs = BITMAP_ALLOC (NULL); + if (flag_ira_hoist_pressure) + hoisted_bbs = BITMAP_ALLOC (NULL); + dom_tree_walk = get_all_dominated_blocks (CDI_DOMINATORS, ENTRY_BLOCK_PTR->next_bb); @@ -2979,12 +3086,12 @@ hoist_code (void) { if (TEST_BIT (hoist_vbeout[bb->index], i)) { + int nregs = 0; + enum reg_class pressure_class = NO_REGS; /* Current expression. */ struct expr *expr = index_map[i]; /* Number of occurrences of EXPR that can be hoisted to BB. */ int hoistable = 0; - /* Basic blocks that have occurrences reachable from BB. */ - bitmap_head _from_bbs, *from_bbs = &_from_bbs; /* Occurrences reachable from BB. */ VEC (occr_t, heap) *occrs_to_hoist = NULL; /* We want to insert the expression into BB only once, so @@ -2992,8 +3099,6 @@ hoist_code (void) int insn_inserted_p; occr_t occr; - bitmap_initialize (from_bbs, 0); - /* If an expression is computed in BB and is available at end of BB, hoist all occurrences dominated by BB to BB. */ if (TEST_BIT (comp[bb->index], i)) @@ -3047,13 +3152,18 @@ hoist_code (void) max_distance += (bb_size[dominated->index] - to_bb_head[INSN_UID (occr->insn)]); - /* Note if the expression would reach the dominated block - unimpared if it was placed at the end of BB. + pressure_class = get_pressure_class_and_nregs (occr->insn, + &nregs); + + /* Note if the expression should be hoisted from the dominated + block to BB if it can reach DOMINATED unimpared. Keep track of how many times this expression is hoistable from a dominated block into BB. */ - if (hoist_expr_reaches_here_p (bb, i, dominated, NULL, - max_distance, bb_size)) + if (should_hoist_expr_to_dom (bb, expr, dominated, NULL, + max_distance, bb_size, + pressure_class, &nregs, + hoisted_bbs)) { hoistable++; VEC_safe_push (occr_t, heap, @@ -3094,6 +3204,28 @@ hoist_code (void) /* Punt, no point hoisting a single occurence. */ VEC_free (occr_t, heap, occrs_to_hoist); + if (flag_ira_hoist_pressure + && !VEC_empty (occr_t, occrs_to_hoist)) + { + /* Update register pressure for basic block to which expr + is hoisted. */ + data = BB_DATA (bb); + data->max_reg_pressure[pressure_class] += nregs; + } + else if (flag_ira_hoist_pressure) + { + /* Restore register pressure of basic block recorded in + hoisted_bbs when expr will not be hoisted. */ + EXECUTE_IF_SET_IN_BITMAP (hoisted_bbs, 0, k, bi) + { + data = BB_DATA (BASIC_BLOCK (k)); + data->max_reg_pressure[pressure_class] -= nregs; + } + } + + if (flag_ira_hoist_pressure) + bitmap_clear (hoisted_bbs); + insn_inserted_p = 0; /* Walk through occurrences of I'th expressions we want @@ -3142,6 +3274,10 @@ hoist_code (void) } VEC_free (basic_block, heap, dom_tree_walk); + BITMAP_FREE (from_bbs); + if (flag_ira_hoist_pressure) + BITMAP_FREE (hoisted_bbs); + free (bb_size); free (to_bb_head); free (index_map); @@ -3149,6 +3285,165 @@ hoist_code (void) return changed; } +/* Return pressure class and number of needed hard registers (through + *NREGS) of register REGNO. */ +static enum reg_class +get_regno_pressure_class (int regno, int *nregs) +{ + if (regno >= FIRST_PSEUDO_REGISTER) + { + enum reg_class pressure_class; + + pressure_class = reg_allocno_class (regno); + pressure_class = ira_pressure_class_translate[pressure_class]; + *nregs + = ira_reg_class_max_nregs[pressure_class][PSEUDO_REGNO_MODE (regno)]; + return pressure_class; + } + else if (! TEST_HARD_REG_BIT (ira_no_alloc_regs, regno) + && ! TEST_HARD_REG_BIT (eliminable_regset, regno)) + { + *nregs = 1; + return ira_pressure_class_translate[REGNO_REG_CLASS (regno)]; + } + else + { + *nregs = 0; + return NO_REGS; + } +} + +/* Return pressure class and number of hard registers (through *NREGS) + for destination of INSN. */ +static enum reg_class +get_pressure_class_and_nregs (rtx insn, int *nregs) +{ + rtx reg; + enum reg_class pressure_class; + rtx set = single_set (insn); + + /* Considered invariant insns have only one set. */ + gcc_assert (set != NULL_RTX); + reg = SET_DEST (set); + if (GET_CODE (reg) == SUBREG) + reg = SUBREG_REG (reg); + if (MEM_P (reg)) + { + *nregs = 0; + pressure_class = NO_REGS; + } + else + { + gcc_assert (REG_P (reg)); + pressure_class = reg_allocno_class (REGNO (reg)); + pressure_class = ira_pressure_class_translate[pressure_class]; + *nregs + = ira_reg_class_max_nregs[pressure_class][GET_MODE (SET_SRC (set))]; + } + return pressure_class; +} + +/* Increase (if INCR_P) or decrease current register pressure for + register REGNO. */ +static void +change_pressure (int regno, bool incr_p) +{ + int nregs; + enum reg_class pressure_class; + + pressure_class = get_regno_pressure_class (regno, &nregs); + if (! incr_p) + curr_reg_pressure[pressure_class] -= nregs; + else + { + curr_reg_pressure[pressure_class] += nregs; + if (BB_DATA (curr_bb)->max_reg_pressure[pressure_class] + < curr_reg_pressure[pressure_class]) + BB_DATA (curr_bb)->max_reg_pressure[pressure_class] + = curr_reg_pressure[pressure_class]; + } +} + +/* Calculate register pressure for each basic block by walking insns + from last to first. */ +static void +calculate_bb_reg_pressure (void) +{ + int i; + unsigned int j; + rtx insn; + basic_block bb; + bitmap curr_regs_live; + bitmap_iterator bi; + + + ira_setup_eliminable_regset (); + curr_regs_live = BITMAP_ALLOC (®_obstack); + FOR_EACH_BB (bb) + { + curr_bb = bb; + bitmap_copy (curr_regs_live, DF_LR_OUT (bb)); + for (i = 0; i < ira_pressure_classes_num; i++) + curr_reg_pressure[ira_pressure_classes[i]] = 0; + EXECUTE_IF_SET_IN_BITMAP (curr_regs_live, 0, j, bi) + change_pressure (j, true); + + FOR_BB_INSNS_REVERSE (bb, insn) + { + rtx dreg; + int regno; + df_ref *def_rec, *use_rec; + + if (! NONDEBUG_INSN_P (insn)) + continue; + + for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++) + { + dreg = DF_REF_REAL_REG (*def_rec); + gcc_assert (REG_P (dreg)); + regno = REGNO (dreg); + if (!(DF_REF_FLAGS (*def_rec) + & (DF_REF_PARTIAL | DF_REF_CONDITIONAL))) + { + if (bitmap_clear_bit (curr_regs_live, regno)) + change_pressure (regno, false); + } + } + + for (use_rec = DF_INSN_USES (insn); *use_rec; use_rec++) + { + dreg = DF_REF_REAL_REG (*use_rec); + gcc_assert (REG_P (dreg)); + regno = REGNO (dreg); + if (bitmap_set_bit (curr_regs_live, regno)) + change_pressure (regno, true); + } + } + } + BITMAP_FREE (curr_regs_live); + + if (dump_file == NULL) + return; + + fprintf (dump_file, "\nRegister Pressure: \n"); + FOR_EACH_BB (bb) + { + fprintf (dump_file, " Basic block %d: \n", bb->index); + for (i = 0; (int) i < ira_pressure_classes_num; i++) + { + enum reg_class pressure_class; + + pressure_class = ira_pressure_classes[i]; + if (BB_DATA (bb)->max_reg_pressure[pressure_class] == 0) + continue; + + fprintf (dump_file, " %s=%d\n", reg_class_names[pressure_class], + BB_DATA (bb)->max_reg_pressure[pressure_class]); + } + } + fprintf (dump_file, "\n"); +} + /* Top level routine to perform one code hoisting (aka unification) pass Return nonzero if a change was made. */ @@ -3168,6 +3463,16 @@ one_code_hoisting_pass (void) doing_code_hoisting_p = true; + /* Calculate register pressure for each basic block. */ + if (flag_ira_hoist_pressure) + { + regstat_init_n_sets_and_refs (); + ira_set_pseudo_classes (false, dump_file); + alloc_aux_for_blocks (sizeof (struct bb_data)); + calculate_bb_reg_pressure (); + regstat_free_n_sets_and_refs (); + } + /* We need alias. */ init_alias_analysis (); @@ -3188,6 +3493,11 @@ one_code_hoisting_pass (void) free_code_hoist_mem (); } + if (flag_ira_hoist_pressure) + { + free_aux_for_blocks (); + free_reg_info (); + } free_hash_table (&expr_hash_table); free_gcse_mem (); obstack_free (&gcse_obstack, NULL); diff --git a/gcc/haifa-sched.c b/gcc/haifa-sched.c index f45caf4..838d3a5 100644 --- a/gcc/haifa-sched.c +++ b/gcc/haifa-sched.c @@ -6633,7 +6633,7 @@ sched_init (void) /* We need info about pseudos for rtl dumps about pseudo classes and costs. */ regstat_init_n_sets_and_refs (); - ira_set_pseudo_classes (sched_verbose ? sched_dump : NULL); + ira_set_pseudo_classes (true, sched_verbose ? sched_dump : NULL); sched_regno_pressure_class = (enum reg_class *) xmalloc (max_regno * sizeof (enum reg_class)); for (i = 0; i < max_regno; i++) diff --git a/gcc/ira-costs.c b/gcc/ira-costs.c index 0c59b03..034eff8 100644 --- a/gcc/ira-costs.c +++ b/gcc/ira-costs.c @@ -2048,9 +2048,10 @@ ira_costs (void) ira_free (total_allocno_costs); } -/* Entry function which defines classes for pseudos. */ +/* Entry function which defines classes for pseudos. + Set pseudo_classes_defined_p only if DEFINE_PSEUDO_CLASSES is true. */ void -ira_set_pseudo_classes (FILE *dump_file) +ira_set_pseudo_classes (bool define_pseudo_classes, FILE *dump_file) { allocno_p = false; internal_flag_ira_verbose = flag_ira_verbose; @@ -2059,7 +2060,9 @@ ira_set_pseudo_classes (FILE *dump_file) initiate_regno_cost_classes (); find_costs_and_classes (dump_file); finish_regno_cost_classes (); - pseudo_classes_defined_p = true; + if (define_pseudo_classes) + pseudo_classes_defined_p = true; + finish_costs (); } @@ -4186,7 +4186,7 @@ ira (FILE *f) crtl->is_leaf = leaf_function_p (); if (resize_reg_info () && flag_ira_loop_pressure) - ira_set_pseudo_classes (ira_dump_file); + ira_set_pseudo_classes (true, ira_dump_file); rebuild_p = update_equiv_regs (); @@ -1,6 +1,6 @@ /* Communication between the Integrated Register Allocator (IRA) and the rest of the compiler. - Copyright (C) 2006, 2007, 2008, 2009, 2010 + Copyright (C) 2006, 2007, 2008, 2009, 2010, 2012 Free Software Foundation, Inc. Contributed by Vladimir Makarov <vmakarov@redhat.com>. @@ -131,7 +131,7 @@ extern void ira_init (void); extern void ira_finish_once (void); extern void ira_setup_eliminable_regset (void); extern rtx ira_eliminate_regs (rtx, enum machine_mode); -extern void ira_set_pseudo_classes (FILE *); +extern void ira_set_pseudo_classes (bool, FILE *); extern void ira_implicitly_set_insn_hard_regs (HARD_REG_SET *); extern void ira_sort_regnos_for_alter_reg (int *, int, unsigned int *); diff --git a/gcc/loop-invariant.c b/gcc/loop-invariant.c index 854b41c..996e6e3 100644 --- a/gcc/loop-invariant.c +++ b/gcc/loop-invariant.c @@ -1,5 +1,5 @@ /* RTL-level loop invariant motion. - Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 + Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012 Free Software Foundation, Inc. This file is part of GCC. @@ -1939,7 +1939,7 @@ move_loop_invariants (void) { df_analyze (); regstat_init_n_sets_and_refs (); - ira_set_pseudo_classes (dump_file); + ira_set_pseudo_classes (true, dump_file); calculate_loop_reg_pressure (); regstat_free_n_sets_and_refs (); } diff --git a/gcc/regmove.c b/gcc/regmove.c index 6ff8ef6..408366d 100644 --- a/gcc/regmove.c +++ b/gcc/regmove.c @@ -1,6 +1,7 @@ /* Move registers around to reduce number of move instructions needed. Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, + 2012 Free Software Foundation, Inc. This file is part of GCC. @@ -1237,7 +1238,7 @@ regmove_optimize (void) regstat_compute_ri (); if (flag_ira_loop_pressure) - ira_set_pseudo_classes (dump_file); + ira_set_pseudo_classes (true, dump_file); regno_src_regno = XNEWVEC (int, nregs); for (i = nregs; --i >= 0; ) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 31f487e..57d4383 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2012-10-19 Bin Cheng <bin.cheng@arm.com> + + * testsuite/gcc.dg/hoist-register-pressure.c: New test. + 2012-10-18 Paolo Carlini <paolo.carlini@oracle.com> PR c++/54501 diff --git a/gcc/testsuite/gcc.dg/hoist-register-pressure.c b/gcc/testsuite/gcc.dg/hoist-register-pressure.c new file mode 100644 index 0000000..6077f1e --- /dev/null +++ b/gcc/testsuite/gcc.dg/hoist-register-pressure.c @@ -0,0 +1,31 @@ +/* { dg-options "-Os -fdump-rtl-hoist" } */ +/* { dg-final { scan-rtl-dump "PRE/HOIST: end of bb .* copying expression" "hoist" } } */ + +#define BUF 100 +int a[BUF]; + +void com (int); +void bar (int); + +int foo (int x, int y, int z) +{ + /* "x+y" won't be hoisted if "-fira-hoist-pressure" is disabled, + because its rtx_cost is too small. */ + if (z) + { + a[1] = a[0] + a[2]; + a[2] = a[1] + a[3]; + a[3] = a[2] + a[4]; + a[4] = a[3] + a[5]; + a[5] = a[4] + a[6]; + a[6] = a[5] + a[7]; + a[7] = a[6] + a[8]; + com (x+y); + } + else + { + bar (x+y); + } + + return 0; +} |