Commit 20160347 by Maxim Kuvyrkov Committed by Maxim Kuvyrkov

gcse.c (struct expr:max_distance): New field.

	* gcse.c (struct expr:max_distance): New field.
	(doing_code_hoisting_p): New static variable.
	(want_to_gcse_p): Change signature.  Allow constrained hoisting of
	simple expressions, don't change behavior for PRE.  Set max_distance.
	(insert_expr_in_table): Set new max_distance field.
	(hash_scan_set): Update.
	(hoist_expr_reaches_here_p): Stop search after max_distance
	instructions.
	(find_occr_in_bb): New static function.  Use it in ...
	(hoist_code): Calculate sizes of basic block before any changes are
	done.  Pass max_distance to hoist_expr_reaches_here_p.
	(one_code_hoisting_pass): Set doing_code_hoisting_p.

	* params.def (PARAM_GCSE_COST_DISTANCE_RATIO,)
	(PARAM_GCSE_UNRESTRICTED_COST): New parameters.
	* params.h (GCSE_COST_DISTANCE_RATIO, GCSE_UNRESTRICTED_COST): New
	macros.
	* doc/invoke.texi (gcse-cost-distance-ratio, gcse-unrestricted-cost):
	Document.

From-SVN: r162589
parent 9b774782
2010-07-27 Maxim Kuvyrkov <maxim@codesourcery.com>
* gcse.c (struct expr:max_distance): New field.
(doing_code_hoisting_p): New static variable.
(want_to_gcse_p): Change signature. Allow constrained hoisting of
simple expressions, don't change behavior for PRE. Set max_distance.
(insert_expr_in_table): Set new max_distance field.
(hash_scan_set): Update.
(hoist_expr_reaches_here_p): Stop search after max_distance
instructions.
(find_occr_in_bb): New static function. Use it in ...
(hoist_code): Calculate sizes of basic block before any changes are
done. Pass max_distance to hoist_expr_reaches_here_p.
(one_code_hoisting_pass): Set doing_code_hoisting_p.
* params.def (PARAM_GCSE_COST_DISTANCE_RATIO,)
(PARAM_GCSE_UNRESTRICTED_COST): New parameters.
* params.h (GCSE_COST_DISTANCE_RATIO, GCSE_UNRESTRICTED_COST): New
macros.
* doc/invoke.texi (gcse-cost-distance-ratio, gcse-unrestricted-cost):
Document.
2010-07-27 Jeff Law <law@redhat.com> 2010-07-27 Jeff Law <law@redhat.com>
Maxim Kuvyrkov <maxim@codesourcery.com> Maxim Kuvyrkov <maxim@codesourcery.com>
......
...@@ -8243,6 +8243,23 @@ when @option{-ftree-vectorize} is used. The number of iterations after ...@@ -8243,6 +8243,23 @@ when @option{-ftree-vectorize} is used. The number of iterations after
vectorization needs to be greater than the value specified by this option vectorization needs to be greater than the value specified by this option
to allow vectorization. The default value is 0. to allow vectorization. The default value is 0.
@item gcse-cost-distance-ratio
Scaling factor in calculation of maximum distance an expression
can be moved by GCSE optimizations. This is currently supported only in
code hoisting pass. The bigger the ratio, the more agressive code hoisting
will be with simple expressions, i.e., the expressions which have cost
less than @option{gcse-unrestricted-cost}. Specifying 0 will disable
hoisting of simple expressions. The default value is 10.
@item gcse-unrestricted-cost
Cost, roughly measured as the cost of a single typical machine
instruction, at which GCSE optimizations will not constrain
the distance an expression can travel. This is currently
supported only in code hoisting pass. The lesser the cost,
the more aggressive code hoisting will be. Specifying 0 will
allow all expressions to travel unrestricted distances.
The default value is 3.
@item max-unrolled-insns @item max-unrolled-insns
The maximum number of instructions that a loop should have if that loop The maximum number of instructions that a loop should have if that loop
is unrolled, and if the loop is unrolled, it determines how many times is unrolled, and if the loop is unrolled, it determines how many times
......
...@@ -302,6 +302,12 @@ struct expr ...@@ -302,6 +302,12 @@ struct expr
The value is the newly created pseudo-reg to record a copy of the The value is the newly created pseudo-reg to record a copy of the
expression in all the places that reach the redundant copy. */ expression in all the places that reach the redundant copy. */
rtx reaching_reg; rtx reaching_reg;
/* Maximum distance in instructions this expression can travel.
We avoid moving simple expressions for more than a few instructions
to keep register pressure under control.
A value of "0" removes restrictions on how far the expression can
travel. */
int max_distance;
}; };
/* Occurrence of an expression. /* Occurrence of an expression.
...@@ -425,6 +431,9 @@ static int global_const_prop_count; ...@@ -425,6 +431,9 @@ static int global_const_prop_count;
/* Number of global copies propagated. */ /* Number of global copies propagated. */
static int global_copy_prop_count; static int global_copy_prop_count;
/* Doing code hoisting. */
static bool doing_code_hoisting_p = false;
/* For available exprs */ /* For available exprs */
static sbitmap *ae_kill; static sbitmap *ae_kill;
...@@ -438,12 +447,12 @@ static void hash_scan_insn (rtx, struct hash_table_d *); ...@@ -438,12 +447,12 @@ static void hash_scan_insn (rtx, struct hash_table_d *);
static void hash_scan_set (rtx, rtx, struct hash_table_d *); static void hash_scan_set (rtx, rtx, struct hash_table_d *);
static void hash_scan_clobber (rtx, rtx, struct hash_table_d *); static void hash_scan_clobber (rtx, rtx, struct hash_table_d *);
static void hash_scan_call (rtx, rtx, struct hash_table_d *); static void hash_scan_call (rtx, rtx, struct hash_table_d *);
static int want_to_gcse_p (rtx); static int want_to_gcse_p (rtx, int *);
static bool gcse_constant_p (const_rtx); static bool gcse_constant_p (const_rtx);
static int oprs_unchanged_p (const_rtx, const_rtx, int); static int oprs_unchanged_p (const_rtx, const_rtx, int);
static int oprs_anticipatable_p (const_rtx, const_rtx); static int oprs_anticipatable_p (const_rtx, const_rtx);
static int oprs_available_p (const_rtx, const_rtx); static int oprs_available_p (const_rtx, const_rtx);
static void insert_expr_in_table (rtx, enum machine_mode, rtx, int, int, static void insert_expr_in_table (rtx, enum machine_mode, rtx, int, int, int,
struct hash_table_d *); struct hash_table_d *);
static void insert_set_in_table (rtx, rtx, struct hash_table_d *); static void insert_set_in_table (rtx, rtx, struct hash_table_d *);
static unsigned int hash_expr (const_rtx, enum machine_mode, int *, int); static unsigned int hash_expr (const_rtx, enum machine_mode, int *, int);
...@@ -502,7 +511,8 @@ static void alloc_code_hoist_mem (int, int); ...@@ -502,7 +511,8 @@ static void alloc_code_hoist_mem (int, int);
static void free_code_hoist_mem (void); static void free_code_hoist_mem (void);
static void compute_code_hoist_vbeinout (void); static void compute_code_hoist_vbeinout (void);
static void compute_code_hoist_data (void); static void compute_code_hoist_data (void);
static int hoist_expr_reaches_here_p (basic_block, int, basic_block, char *); static int hoist_expr_reaches_here_p (basic_block, int, basic_block, char *,
int, int *);
static int hoist_code (void); static int hoist_code (void);
static int one_code_hoisting_pass (void); static int one_code_hoisting_pass (void);
static rtx process_insert_insn (struct expr *); static rtx process_insert_insn (struct expr *);
...@@ -758,7 +768,7 @@ static basic_block current_bb; ...@@ -758,7 +768,7 @@ static basic_block current_bb;
GCSE. */ GCSE. */
static int static int
want_to_gcse_p (rtx x) want_to_gcse_p (rtx x, int *max_distance_ptr)
{ {
#ifdef STACK_REGS #ifdef STACK_REGS
/* On register stack architectures, don't GCSE constants from the /* On register stack architectures, don't GCSE constants from the
...@@ -768,18 +778,67 @@ want_to_gcse_p (rtx x) ...@@ -768,18 +778,67 @@ want_to_gcse_p (rtx x)
x = avoid_constant_pool_reference (x); x = avoid_constant_pool_reference (x);
#endif #endif
/* GCSE'ing constants:
We do not specifically distinguish between constant and non-constant
expressions in PRE and Hoist. We use rtx_cost below to limit
the maximum distance simple expressions can travel.
Nevertheless, constants are much easier to GCSE, and, hence,
it is easy to overdo the optimizations. Usually, excessive PRE and
Hoisting of constant leads to increased register pressure.
RA can deal with this by rematerialing some of the constants.
Therefore, it is important that the back-end generates sets of constants
in a way that allows reload rematerialize them under high register
pressure, i.e., a pseudo register with REG_EQUAL to constant
is set only once. Failing to do so will result in IRA/reload
spilling such constants under high register pressure instead of
rematerializing them. */
switch (GET_CODE (x)) switch (GET_CODE (x))
{ {
case REG: case REG:
case SUBREG: case SUBREG:
case CALL:
return 0;
case CONST_INT: case CONST_INT:
case CONST_DOUBLE: case CONST_DOUBLE:
case CONST_FIXED: case CONST_FIXED:
case CONST_VECTOR: case CONST_VECTOR:
case CALL: if (!doing_code_hoisting_p)
return 0; /* Do not PRE constants. */
return 0;
/* FALLTHRU */
default: default:
if (doing_code_hoisting_p)
/* PRE doesn't implement max_distance restriction. */
{
int cost;
int max_distance;
gcc_assert (!optimize_function_for_speed_p (cfun)
&& optimize_function_for_size_p (cfun));
cost = rtx_cost (x, SET, 0);
if (cost < COSTS_N_INSNS (GCSE_UNRESTRICTED_COST))
{
max_distance = (GCSE_COST_DISTANCE_RATIO * cost) / 10;
if (max_distance == 0)
return 0;
gcc_assert (max_distance > 0);
}
else
max_distance = 0;
if (max_distance_ptr)
*max_distance_ptr = max_distance;
}
return can_assign_to_reg_without_clobbers_p (x); return can_assign_to_reg_without_clobbers_p (x);
} }
} }
...@@ -1093,11 +1152,14 @@ expr_equiv_p (const_rtx x, const_rtx y) ...@@ -1093,11 +1152,14 @@ expr_equiv_p (const_rtx x, const_rtx y)
It is only used if X is a CONST_INT. It is only used if X is a CONST_INT.
ANTIC_P is nonzero if X is an anticipatable expression. ANTIC_P is nonzero if X is an anticipatable expression.
AVAIL_P is nonzero if X is an available expression. */ AVAIL_P is nonzero if X is an available expression.
MAX_DISTANCE is the maximum distance in instructions this expression can
be moved. */
static void static void
insert_expr_in_table (rtx x, enum machine_mode mode, rtx insn, int antic_p, insert_expr_in_table (rtx x, enum machine_mode mode, rtx insn, int antic_p,
int avail_p, struct hash_table_d *table) int avail_p, int max_distance, struct hash_table_d *table)
{ {
int found, do_not_record_p; int found, do_not_record_p;
unsigned int hash; unsigned int hash;
...@@ -1140,7 +1202,11 @@ insert_expr_in_table (rtx x, enum machine_mode mode, rtx insn, int antic_p, ...@@ -1140,7 +1202,11 @@ insert_expr_in_table (rtx x, enum machine_mode mode, rtx insn, int antic_p,
cur_expr->next_same_hash = NULL; cur_expr->next_same_hash = NULL;
cur_expr->antic_occr = NULL; cur_expr->antic_occr = NULL;
cur_expr->avail_occr = NULL; cur_expr->avail_occr = NULL;
gcc_assert (max_distance >= 0);
cur_expr->max_distance = max_distance;
} }
else
gcc_assert (cur_expr->max_distance == max_distance);
/* Now record the occurrence(s). */ /* Now record the occurrence(s). */
if (antic_p) if (antic_p)
...@@ -1241,6 +1307,8 @@ insert_set_in_table (rtx x, rtx insn, struct hash_table_d *table) ...@@ -1241,6 +1307,8 @@ insert_set_in_table (rtx x, rtx insn, struct hash_table_d *table)
cur_expr->next_same_hash = NULL; cur_expr->next_same_hash = NULL;
cur_expr->antic_occr = NULL; cur_expr->antic_occr = NULL;
cur_expr->avail_occr = NULL; cur_expr->avail_occr = NULL;
/* Not used for set_p tables. */
cur_expr->max_distance = 0;
} }
/* Now record the occurrence. */ /* Now record the occurrence. */
...@@ -1310,6 +1378,7 @@ hash_scan_set (rtx pat, rtx insn, struct hash_table_d *table) ...@@ -1310,6 +1378,7 @@ hash_scan_set (rtx pat, rtx insn, struct hash_table_d *table)
{ {
unsigned int regno = REGNO (dest); unsigned int regno = REGNO (dest);
rtx tmp; rtx tmp;
int max_distance = 0;
/* See if a REG_EQUAL note shows this equivalent to a simpler expression. /* See if a REG_EQUAL note shows this equivalent to a simpler expression.
...@@ -1332,7 +1401,7 @@ hash_scan_set (rtx pat, rtx insn, struct hash_table_d *table) ...@@ -1332,7 +1401,7 @@ hash_scan_set (rtx pat, rtx insn, struct hash_table_d *table)
&& !REG_P (src) && !REG_P (src)
&& (table->set_p && (table->set_p
? gcse_constant_p (XEXP (note, 0)) ? gcse_constant_p (XEXP (note, 0))
: want_to_gcse_p (XEXP (note, 0)))) : want_to_gcse_p (XEXP (note, 0), NULL)))
src = XEXP (note, 0), pat = gen_rtx_SET (VOIDmode, dest, src); src = XEXP (note, 0), pat = gen_rtx_SET (VOIDmode, dest, src);
/* Only record sets of pseudo-regs in the hash table. */ /* Only record sets of pseudo-regs in the hash table. */
...@@ -1347,7 +1416,7 @@ hash_scan_set (rtx pat, rtx insn, struct hash_table_d *table) ...@@ -1347,7 +1416,7 @@ hash_scan_set (rtx pat, rtx insn, struct hash_table_d *table)
can't do the same thing at the rtl level. */ can't do the same thing at the rtl level. */
&& !can_throw_internal (insn) && !can_throw_internal (insn)
/* Is SET_SRC something we want to gcse? */ /* Is SET_SRC something we want to gcse? */
&& want_to_gcse_p (src) && want_to_gcse_p (src, &max_distance)
/* Don't CSE a nop. */ /* Don't CSE a nop. */
&& ! set_noop_p (pat) && ! set_noop_p (pat)
/* Don't GCSE if it has attached REG_EQUIV note. /* Don't GCSE if it has attached REG_EQUIV note.
...@@ -1371,7 +1440,8 @@ hash_scan_set (rtx pat, rtx insn, struct hash_table_d *table) ...@@ -1371,7 +1440,8 @@ hash_scan_set (rtx pat, rtx insn, struct hash_table_d *table)
int avail_p = (oprs_available_p (src, insn) int avail_p = (oprs_available_p (src, insn)
&& ! JUMP_P (insn)); && ! JUMP_P (insn));
insert_expr_in_table (src, GET_MODE (dest), insn, antic_p, avail_p, table); insert_expr_in_table (src, GET_MODE (dest), insn, antic_p, avail_p,
max_distance, table);
} }
/* Record sets for constant/copy propagation. */ /* Record sets for constant/copy propagation. */
...@@ -1408,7 +1478,7 @@ hash_scan_set (rtx pat, rtx insn, struct hash_table_d *table) ...@@ -1408,7 +1478,7 @@ hash_scan_set (rtx pat, rtx insn, struct hash_table_d *table)
do that easily for EH edges so disable GCSE on these for now. */ do that easily for EH edges so disable GCSE on these for now. */
&& !can_throw_internal (insn) && !can_throw_internal (insn)
/* Is SET_DEST something we want to gcse? */ /* Is SET_DEST something we want to gcse? */
&& want_to_gcse_p (dest) && want_to_gcse_p (dest, NULL)
/* Don't CSE a nop. */ /* Don't CSE a nop. */
&& ! set_noop_p (pat) && ! set_noop_p (pat)
/* Don't GCSE if it has attached REG_EQUIV note. /* Don't GCSE if it has attached REG_EQUIV note.
...@@ -1429,7 +1499,7 @@ hash_scan_set (rtx pat, rtx insn, struct hash_table_d *table) ...@@ -1429,7 +1499,7 @@ hash_scan_set (rtx pat, rtx insn, struct hash_table_d *table)
&& ! JUMP_P (insn); && ! JUMP_P (insn);
/* Record the memory expression (DEST) in the hash table. */ /* Record the memory expression (DEST) in the hash table. */
insert_expr_in_table (dest, GET_MODE (dest), insn, insert_expr_in_table (dest, GET_MODE (dest), insn, 0,
antic_p, avail_p, table); antic_p, avail_p, table);
} }
} }
...@@ -1516,8 +1586,8 @@ dump_hash_table (FILE *file, const char *name, struct hash_table_d *table) ...@@ -1516,8 +1586,8 @@ dump_hash_table (FILE *file, const char *name, struct hash_table_d *table)
if (flat_table[i] != 0) if (flat_table[i] != 0)
{ {
expr = flat_table[i]; expr = flat_table[i];
fprintf (file, "Index %d (hash value %d)\n ", fprintf (file, "Index %d (hash value %d; max distance %d)\n ",
expr->bitmap_index, hash_val[i]); expr->bitmap_index, hash_val[i], expr->max_distance);
print_rtl (file, expr->expr); print_rtl (file, expr->expr);
fprintf (file, "\n"); fprintf (file, "\n");
} }
...@@ -4208,6 +4278,8 @@ compute_code_hoist_data (void) ...@@ -4208,6 +4278,8 @@ compute_code_hoist_data (void)
/* Determine if the expression identified by EXPR_INDEX would /* Determine if the expression identified by EXPR_INDEX would
reach BB unimpared if it was placed at the end of EXPR_BB. 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.
It's unclear exactly what Muchnick meant by "unimpared". It seems It's unclear exactly what Muchnick meant by "unimpared". It seems
to me that the expression must either be computed or transparent in to me that the expression must either be computed or transparent in
...@@ -4220,12 +4292,24 @@ compute_code_hoist_data (void) ...@@ -4220,12 +4292,24 @@ compute_code_hoist_data (void)
paths. */ paths. */
static int static int
hoist_expr_reaches_here_p (basic_block expr_bb, int expr_index, basic_block bb, char *visited) hoist_expr_reaches_here_p (basic_block expr_bb, int expr_index, basic_block bb,
char *visited, int distance, int *bb_size)
{ {
edge pred; edge pred;
edge_iterator ei; edge_iterator ei;
int visited_allocated_locally = 0; 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];
if (distance <= 0)
return 0;
}
else
gcc_assert (distance == 0);
if (visited == NULL) if (visited == NULL)
{ {
...@@ -4254,8 +4338,8 @@ hoist_expr_reaches_here_p (basic_block expr_bb, int expr_index, basic_block bb, ...@@ -4254,8 +4338,8 @@ hoist_expr_reaches_here_p (basic_block expr_bb, int expr_index, basic_block bb,
else else
{ {
visited[pred_bb->index] = 1; visited[pred_bb->index] = 1;
if (! hoist_expr_reaches_here_p (expr_bb, expr_index, if (! hoist_expr_reaches_here_p (expr_bb, expr_index, pred_bb,
pred_bb, visited)) visited, distance, bb_size))
break; break;
} }
} }
...@@ -4265,6 +4349,17 @@ hoist_expr_reaches_here_p (basic_block expr_bb, int expr_index, basic_block bb, ...@@ -4265,6 +4349,17 @@ hoist_expr_reaches_here_p (basic_block expr_bb, int expr_index, basic_block bb,
return (pred == NULL); return (pred == NULL);
} }
/* Find occurence in BB. */
static struct occr *
find_occr_in_bb (struct occr *occr, basic_block bb)
{
/* Find the right occurrence of this expression. */
while (occr && BLOCK_FOR_INSN (occr->insn) != bb)
occr = occr->next;
return occr;
}
/* Actually perform code hoisting. */ /* Actually perform code hoisting. */
static int static int
...@@ -4275,6 +4370,8 @@ hoist_code (void) ...@@ -4275,6 +4370,8 @@ hoist_code (void)
unsigned int i,j; unsigned int i,j;
struct expr **index_map; struct expr **index_map;
struct expr *expr; struct expr *expr;
int *to_bb_head;
int *bb_size;
int changed = 0; int changed = 0;
sbitmap_vector_zero (hoist_exprs, last_basic_block); sbitmap_vector_zero (hoist_exprs, last_basic_block);
...@@ -4287,6 +4384,36 @@ hoist_code (void) ...@@ -4287,6 +4384,36 @@ hoist_code (void)
for (expr = expr_hash_table.table[i]; expr != NULL; expr = expr->next_same_hash) for (expr = expr_hash_table.table[i]; expr != NULL; expr = expr->next_same_hash)
index_map[expr->bitmap_index] = expr; index_map[expr->bitmap_index] = expr;
/* Calculate sizes of basic blocks and note how far
each instruction is from the start of its block. We then use this
data to restrict distance an expression can travel. */
to_bb_head = XCNEWVEC (int, get_max_uid ());
bb_size = XCNEWVEC (int, last_basic_block);
FOR_EACH_BB (bb)
{
rtx insn;
rtx bb_end;
int to_head;
insn = BB_HEAD (bb);
bb_end = BB_END (bb);
to_head = 0;
while (insn != bb_end)
{
/* Don't count debug instructions to avoid them affecting
decision choices. */
if (NONDEBUG_INSN_P (insn))
to_bb_head[INSN_UID (insn)] = to_head++;
insn = NEXT_INSN (insn);
}
bb_size[bb->index] = to_head;
}
/* Walk over each basic block looking for potentially hoistable /* Walk over each basic block looking for potentially hoistable
expressions, nothing gets hoisted from the entry block. */ expressions, nothing gets hoisted from the entry block. */
FOR_EACH_BB (bb) FOR_EACH_BB (bb)
...@@ -4308,6 +4435,10 @@ hoist_code (void) ...@@ -4308,6 +4435,10 @@ hoist_code (void)
computes the expression. */ computes the expression. */
for (j = 0; VEC_iterate (basic_block, domby, j, dominated); j++) for (j = 0; VEC_iterate (basic_block, domby, j, dominated); j++)
{ {
struct expr *expr = index_map[i];
struct occr *occr = NULL;
int max_distance;
/* Ignore self dominance. */ /* Ignore self dominance. */
if (bb == dominated) if (bb == dominated)
continue; continue;
...@@ -4317,12 +4448,30 @@ hoist_code (void) ...@@ -4317,12 +4448,30 @@ hoist_code (void)
if (!TEST_BIT (antloc[dominated->index], i)) if (!TEST_BIT (antloc[dominated->index], i))
continue; continue;
max_distance = expr->max_distance;
if (max_distance > 0)
{
struct occr *occr;
occr = find_occr_in_bb (expr->antic_occr, dominated);
gcc_assert (occr);
gcc_assert (NONDEBUG_INSN_P (occr->insn));
/* Adjust MAX_DISTANCE to account for the fact that
OCCR won't have to travel all of DOMINATED, but
only part of it. */
max_distance += (bb_size[dominated->index]
- to_bb_head[INSN_UID (occr->insn)]);
}
/* Note if the expression would reach the dominated block /* Note if the expression would reach the dominated block
unimpared if it was placed at the end of BB. unimpared if it was placed at the end of BB.
Keep track of how many times this expression is hoistable Keep track of how many times this expression is hoistable
from a dominated block into BB. */ from a dominated block into BB. */
if (hoist_expr_reaches_here_p (bb, i, dominated, NULL)) if (hoist_expr_reaches_here_p (bb, i, dominated, NULL,
max_distance, bb_size))
hoistable++; hoistable++;
} }
...@@ -4365,6 +4514,9 @@ hoist_code (void) ...@@ -4365,6 +4514,9 @@ hoist_code (void)
computes the expression. */ computes the expression. */
for (j = 0; VEC_iterate (basic_block, domby, j, dominated); j++) for (j = 0; VEC_iterate (basic_block, domby, j, dominated); j++)
{ {
struct expr *expr = index_map[i];
int max_distance;
/* Ignore self dominance. */ /* Ignore self dominance. */
if (bb == dominated) if (bb == dominated)
continue; continue;
...@@ -4375,23 +4527,42 @@ hoist_code (void) ...@@ -4375,23 +4527,42 @@ hoist_code (void)
if (!TEST_BIT (antloc[dominated->index], i)) if (!TEST_BIT (antloc[dominated->index], i))
continue; continue;
max_distance = expr->max_distance;
if (max_distance > 0)
{
occr = find_occr_in_bb (expr->antic_occr, dominated);
gcc_assert (occr);
gcc_assert (NONDEBUG_INSN_P (occr->insn));
/* Adjust MAX_DISTANCE to account for the fact that
OCCR won't have to travel all of DOMINATED, but
only part of it. */
max_distance += (bb_size[dominated->index]
- to_bb_head[INSN_UID (occr->insn)]);
}
/* The expression is computed in the dominated block and /* The expression is computed in the dominated block and
it would be safe to compute it at the start of the it would be safe to compute it at the start of the
dominated block. Now we have to determine if the dominated block. Now we have to determine if the
expression would reach the dominated block if it was expression would reach the dominated block if it was
placed at the end of BB. */ placed at the end of BB.
if (hoist_expr_reaches_here_p (bb, i, dominated, NULL)) Note: the fact that hoist_exprs has i-th bit set means
that /some/, not necesserilly all, occurences from
the dominated blocks can be hoisted to BB. Here we check
if a specific occurence can be hoisted to BB. */
if (hoist_expr_reaches_here_p (bb, i, dominated, NULL,
max_distance, bb_size))
{ {
struct expr *expr = index_map[i];
struct occr *occr = expr->antic_occr;
rtx insn; rtx insn;
rtx set; rtx set;
/* Find the right occurrence of this expression. */ if (!occr)
while (BLOCK_FOR_INSN (occr->insn) != dominated && occr) {
occr = occr->next; occr = find_occr_in_bb (expr->antic_occr, dominated);
gcc_assert (occr);
}
gcc_assert (occr);
insn = occr->insn; insn = occr->insn;
set = single_set (insn); set = single_set (insn);
gcc_assert (set); gcc_assert (set);
...@@ -4421,6 +4592,8 @@ hoist_code (void) ...@@ -4421,6 +4592,8 @@ hoist_code (void)
VEC_free (basic_block, heap, domby); VEC_free (basic_block, heap, domby);
} }
free (bb_size);
free (to_bb_head);
free (index_map); free (index_map);
return changed; return changed;
...@@ -4443,6 +4616,8 @@ one_code_hoisting_pass (void) ...@@ -4443,6 +4616,8 @@ one_code_hoisting_pass (void)
|| is_too_expensive (_("GCSE disabled"))) || is_too_expensive (_("GCSE disabled")))
return 0; return 0;
doing_code_hoisting_p = true;
/* We need alias. */ /* We need alias. */
init_alias_analysis (); init_alias_analysis ();
...@@ -4478,6 +4653,8 @@ one_code_hoisting_pass (void) ...@@ -4478,6 +4653,8 @@ one_code_hoisting_pass (void)
gcse_subst_count, gcse_create_count); gcse_subst_count, gcse_create_count);
} }
doing_code_hoisting_p = false;
return changed; return changed;
} }
......
...@@ -225,6 +225,21 @@ DEFPARAM(PARAM_GCSE_AFTER_RELOAD_CRITICAL_FRACTION, ...@@ -225,6 +225,21 @@ DEFPARAM(PARAM_GCSE_AFTER_RELOAD_CRITICAL_FRACTION,
"gcse-after-reload-critical-fraction", "gcse-after-reload-critical-fraction",
"The threshold ratio of critical edges execution count that permit performing redundancy elimination after reload", "The threshold ratio of critical edges execution count that permit performing redundancy elimination after reload",
10, 0, 0) 10, 0, 0)
/* GCSE will use GCSE_COST_DISTANCE_RATION as a scaling factor
to calculate maximum distance for which an expression is allowed to move
from its rtx_cost. */
DEFPARAM(PARAM_GCSE_COST_DISTANCE_RATIO,
"gcse-cost-distance-ratio",
"Scaling factor in calculation of maximum distance an expression can be moved by GCSE optimizations",
10, 0, 0)
/* GCSE won't restrict distance for which an expression with rtx_cost greater
than COSTS_N_INSN(GCSE_UNRESTRICTED_COST) is allowed to move. */
DEFPARAM(PARAM_GCSE_UNRESTRICTED_COST,
"gcse-unrestricted-cost",
"Cost at which GCSE optimizations will not constraint the distance an expression can travel",
3, 0, 0)
/* This parameter limits the number of insns in a loop that will be unrolled, /* This parameter limits the number of insns in a loop that will be unrolled,
and by how much the loop is unrolled. and by how much the loop is unrolled.
......
...@@ -125,6 +125,10 @@ typedef enum compiler_param ...@@ -125,6 +125,10 @@ typedef enum compiler_param
PARAM_VALUE (PARAM_GCSE_AFTER_RELOAD_PARTIAL_FRACTION) PARAM_VALUE (PARAM_GCSE_AFTER_RELOAD_PARTIAL_FRACTION)
#define GCSE_AFTER_RELOAD_CRITICAL_FRACTION \ #define GCSE_AFTER_RELOAD_CRITICAL_FRACTION \
PARAM_VALUE (PARAM_GCSE_AFTER_RELOAD_CRITICAL_FRACTION) PARAM_VALUE (PARAM_GCSE_AFTER_RELOAD_CRITICAL_FRACTION)
#define GCSE_COST_DISTANCE_RATIO \
PARAM_VALUE (PARAM_GCSE_COST_DISTANCE_RATIO)
#define GCSE_UNRESTRICTED_COST \
PARAM_VALUE (PARAM_GCSE_UNRESTRICTED_COST)
#define MAX_UNROLLED_INSNS \ #define MAX_UNROLLED_INSNS \
PARAM_VALUE (PARAM_MAX_UNROLLED_INSNS) PARAM_VALUE (PARAM_MAX_UNROLLED_INSNS)
#define MAX_SMS_LOOP_NUMBER \ #define MAX_SMS_LOOP_NUMBER \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment