common.opt (flag_ira_hoist_pressure): New.

gcc/ChangeLog
	* 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.

	gcc/testsuite/ChangeLog
	* testsuite/gcc.dg/hoist-register-pressure.c: New test.

From-SVN: r192604
This commit is contained in:
Bin Cheng 2012-10-19 05:42:24 +00:00 committed by Bin Cheng
parent 8cba9a0536
commit b11f0116d6
12 changed files with 430 additions and 42 deletions

View File

@ -1,3 +1,29 @@
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.

View File

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

View File

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

View File

@ -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);

View File

@ -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++)

View File

@ -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 ();
}

View File

@ -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 ();

View File

@ -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 *);

View File

@ -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 ();
}

View File

@ -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; )

View File

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

View File

@ -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;
}