aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog26
-rw-r--r--gcc/common.opt5
-rw-r--r--gcc/doc/invoke.texi10
-rw-r--r--gcc/gcse.c370
-rw-r--r--gcc/haifa-sched.c2
-rw-r--r--gcc/ira-costs.c9
-rw-r--r--gcc/ira.c2
-rw-r--r--gcc/ira.h4
-rw-r--r--gcc/loop-invariant.c4
-rw-r--r--gcc/regmove.c5
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/hoist-register-pressure.c31
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
diff --git a/gcc/gcse.c b/gcc/gcse.c
index 94f4beb..99e7685 100644
--- a/gcc/gcse.c
+++ b/gcc/gcse.c
@@ -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 (&reg_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 ();
}
diff --git a/gcc/ira.c b/gcc/ira.c
index a79a0dc..78b3f92 100644
--- a/gcc/ira.c
+++ b/gcc/ira.c
@@ -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 ();
diff --git a/gcc/ira.h b/gcc/ira.h
index 6870c4b..0cafdf4 100644
--- a/gcc/ira.h
+++ b/gcc/ira.h
@@ -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;
+}