@@ -431,7 +431,7 @@ 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_clobber (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, rtx);
static bool gcse_constant_p (const_rtx);
static int oprs_unchanged_p (const_rtx, const_rtx, int);
static int oprs_anticipatable_p (const_rtx, const_rtx);
@@ -751,10 +751,10 @@ static basic_block current_bb;
/* See whether X, the source of a set, is something we want to consider for
- GCSE. */
+ GCSE in instruction INSN. */
static int
-want_to_gcse_p (rtx x)
+want_to_gcse_p (rtx x, rtx insn)
{
#ifdef STACK_REGS
/* On register stack architectures, don't GCSE constants from the
@@ -768,13 +768,35 @@ want_to_gcse_p (rtx x)
{
case REG:
case SUBREG:
- case CONST_INT:
case CONST_DOUBLE:
case CONST_FIXED:
case CONST_VECTOR:
case CALL:
return 0;
+ case CONST_INT:
+ case SYMBOL_REF:
+ /* If it takes a PARALLEL to set a constant or a symbol, try to gcse it.
+ Usually, (clobber (reg)) is the second part of the parallel.
+ We rely on rematerialization of constants to avoid excessive
+ register pressure.
+
+ ??? We would also like to GCSE/hoist non-parallel-looking constants
+ and symbol_refs on architectures which require load from constant
+ pools to get a constant into register, e.g., ARM.
+ We do not currently do that because IRA overestimates cost
+ of allocating a constant to memory, thus unnecessarily increasing
+ register pressure and causing spills. One side of this problem
+ is IRA using rtx_costs which are not particularly precise for
+ constants when optimizing for size. For a good example see
+ 300.twolf:ucxxo1.c from SPEC2000.
+
+ ??? Should we handle CONST_DOUBLE and CONST_FIXED similarly?
+ Will rematerialization handle them? */
+ if (GET_CODE (PATTERN (insn)) != PARALLEL)
+ return 0;
+ /* FALLTHRU */
+
default:
return can_assign_to_reg_without_clobbers_p (x);
}
@@ -1328,7 +1350,7 @@ hash_scan_set (rtx pat, rtx insn, struct hash_table_d *table)
&& !REG_P (src)
&& (table->set_p
? gcse_constant_p (XEXP (note, 0))
- : want_to_gcse_p (XEXP (note, 0))))
+ : want_to_gcse_p (XEXP (note, 0), insn)))
src = XEXP (note, 0), pat = gen_rtx_SET (VOIDmode, dest, src);
/* Only record sets of pseudo-regs in the hash table. */
@@ -1343,7 +1365,7 @@ hash_scan_set (rtx pat, rtx insn, struct hash_table_d *table)
can't do the same thing at the rtl level. */
&& !can_throw_internal (insn)
/* Is SET_SRC something we want to gcse? */
- && want_to_gcse_p (src)
+ && want_to_gcse_p (src, insn)
/* Don't CSE a nop. */
&& ! set_noop_p (pat)
/* Don't GCSE if it has attached REG_EQUIV note.
@@ -1404,7 +1426,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. */
&& !can_throw_internal (insn)
/* Is SET_DEST something we want to gcse? */
- && want_to_gcse_p (dest)
+ && want_to_gcse_p (dest, insn)
/* Don't CSE a nop. */
&& ! set_noop_p (pat)
/* Don't GCSE if it has attached REG_EQUIV note.