Commit d9cf932c by Vladimir Makarov Committed by Vladimir Makarov

common.opt (flra-remat): New.

2014-11-12  Vladimir Makarov  <vmakarov@redhat.com>

	* common.opt (flra-remat): New.
	* opts.c (default_options_table): Add entry for flra_remat.
	* timevar_def (TV_LRA_REMAT): New.
	* doc/invoke.texi (-flra-remat): Add description of the new
	option.
	* doc/passes.texi (-flra-remat): Remove lra-equivs.c and
	lra-saves.c.  Add lra-remat.c.
	* Makefile.in (OBJS): Add lra-remat.o.
	* lra-remat.c: New file.
	* lra.c: Add info about the rematerialization pass in the top
	comment.
	(collect_non_operand_hard_regs, add_regs_to_insn_regno_info):
	Process unallocatable regs too.
	(lra_constraint_new_insn_uid_start): Remove.
	(lra): Add code for calling rematerialization sub-pass.
	* lra-int.h (lra_constraint_new_insn_uid_start): Remove.
	(lra_constrain_insn, lra_remat): New prototypes.
	(lra_eliminate_regs_1): Add parameter.
	* lra-lives.c (make_hard_regno_born, make_hard_regno_dead):
	Process unallocatable hard regs too.
	(process_bb_lives): Ditto.
	* lra-spills.c (remove_pseudos): Add argument to
	lra_eliminate_regs_1 call.
	* lra-eliminations.c (lra_eliminate_regs_1): Add parameter.  Use it
	for sp offset calculation.
	(lra_eliminate_regs): Add argument for lra_eliminate_regs_1 call.
	(eliminate_regs_in_insn): Add parameter.  Use it for sp offset
	calculation.
	(process_insn_for_elimination): Add argument for
	eliminate_regs_in_insn call.
	* lra-constraints.c (get_equiv_with_elimination):  Add argument
	for lra_eliminate_regs_1 call.
	(process_addr_reg): Add parameter.  Use it.
	(process_address_1): Ditto.  Add argument for process_addr_reg
	call.
	(process_address): Ditto.
	(curr_insn_transform): Add parameter.  Use it.  Add argument for
	process_address calls.
	(lra_constrain_insn): New function.
	(lra_constraints): Add argument for curr_insn_transform call.

From-SVN: r217458
parent 778e02fd
2014-11-12 Vladimir Makarov <vmakarov@redhat.com>
* common.opt (flra-remat): New.
* opts.c (default_options_table): Add entry for flra_remat.
* timevar_def (TV_LRA_REMAT): New.
* doc/invoke.texi (-flra-remat): Add description of the new
option.
* doc/passes.texi (-flra-remat): Remove lra-equivs.c and
lra-saves.c. Add lra-remat.c.
* Makefile.in (OBJS): Add lra-remat.o.
* lra-remat.c: New file.
* lra.c: Add info about the rematerialization pass in the top
comment.
(collect_non_operand_hard_regs, add_regs_to_insn_regno_info):
Process unallocatable regs too.
(lra_constraint_new_insn_uid_start): Remove.
(lra): Add code for calling rematerialization sub-pass.
* lra-int.h (lra_constraint_new_insn_uid_start): Remove.
(lra_constrain_insn, lra_remat): New prototypes.
(lra_eliminate_regs_1): Add parameter.
* lra-lives.c (make_hard_regno_born, make_hard_regno_dead):
Process unallocatable hard regs too.
(process_bb_lives): Ditto.
* lra-spills.c (remove_pseudos): Add argument to
lra_eliminate_regs_1 call.
* lra-eliminations.c (lra_eliminate_regs_1): Add parameter. Use it
for sp offset calculation.
(lra_eliminate_regs): Add argument for lra_eliminate_regs_1 call.
(eliminate_regs_in_insn): Add parameter. Use it for sp offset
calculation.
(process_insn_for_elimination): Add argument for
eliminate_regs_in_insn call.
* lra-constraints.c (get_equiv_with_elimination): Add argument
for lra_eliminate_regs_1 call.
(process_addr_reg): Add parameter. Use it.
(process_address_1): Ditto. Add argument for process_addr_reg
call.
(process_address): Ditto.
(curr_insn_transform): Add parameter. Use it. Add argument for
process_address calls.
(lra_constrain_insn): New function.
(lra_constraints): Add argument for curr_insn_transform call.
2014-11-13 Manuel López-Ibáñez <manu@gcc.gnu.org>
* opts-global.c (postpone_unknown_option_warning): Fix spelling.
......@@ -1304,6 +1304,7 @@ OBJS = \
lra-constraints.o \
lra-eliminations.o \
lra-lives.o \
lra-remat.o \
lra-spills.o \
lto-cgraph.o \
lto-streamer.o \
......
......@@ -1551,6 +1551,10 @@ floop-optimize
Common Ignore
Does nothing. Preserved for backward compatibility.
flra-remat
Common Report Var(flag_lra_remat) Optimization
Do CFG-sensitive rematerialization in LRA
flto
Common
Enable link-time optimization.
......
......@@ -392,7 +392,7 @@ Objective-C and Objective-C++ Dialects}.
-fisolate-erroneous-paths-dereference -fisolate-erroneous-paths-attribute @gol
-fivopts -fkeep-inline-functions -fkeep-static-consts -flive-range-shrinkage @gol
-floop-block -floop-interchange -floop-strip-mine -floop-nest-optimize @gol
-floop-parallelize-all -flto -flto-compression-level @gol
-floop-parallelize-all -flra-remat -flto -flto-compression-level @gol
-flto-partition=@var{alg} -flto-report -flto-report-wpa -fmerge-all-constants @gol
-fmerge-constants -fmodulo-sched -fmodulo-sched-allow-regmoves @gol
-fmove-loop-invariants -fno-branch-count-reg @gol
......@@ -7183,6 +7183,7 @@ also turns on the following optimization flags:
-fipa-sra @gol
-fipa-icf @gol
-fisolate-erroneous-paths-dereference @gol
-flra-remat @gol
-foptimize-sibling-calls @gol
-foptimize-strlen @gol
-fpartial-inlining @gol
......@@ -7811,6 +7812,14 @@ Control the verbosity of the dump file for the integrated register allocator.
The default value is 5. If the value @var{n} is greater or equal to 10,
the dump output is sent to stderr using the same format as @var{n} minus 10.
@item -flra-remat
@opindex fcaller-saves
Enable CFG-sensitive rematerialization in LRA. Instead of loading
values of spilled pseudos, LRA tries to rematerialize (recalculate)
values if it is profitable.
Enabled at levels @option{-O2}, @option{-O3}, @option{-Os}.
@item -fdelayed-branch
@opindex fdelayed-branch
If supported for the target machine, attempt to reorder instructions
......
......@@ -911,10 +911,10 @@ Source files are @file{reload.c} and @file{reload1.c}, plus the header
This pass is a modern replacement of the reload pass. Source files
are @file{lra.c}, @file{lra-assign.c}, @file{lra-coalesce.c},
@file{lra-constraints.c}, @file{lra-eliminations.c},
@file{lra-equivs.c}, @file{lra-lives.c}, @file{lra-saves.c},
@file{lra-spills.c}, the header @file{lra-int.h} used for
communication between them, and the header @file{lra.h} used for
communication between LRA and the rest of compiler.
@file{lra-lives.c}, @file{lra-remat.c}, @file{lra-spills.c}, the
header @file{lra-int.h} used for communication between them, and the
header @file{lra.h} used for communication between LRA and the rest of
compiler.
Unlike the reload pass, intermediate LRA decisions are reflected in
RTL as much as possible. This reduces the number of target-dependent
......
......@@ -298,7 +298,8 @@ get_elimination (rtx reg)
a change in the offset between the eliminable register and its
substitution if UPDATE_P, or the full offset if FULL_P, or
otherwise zero. If FULL_P, we also use the SP offsets for
elimination to SP.
elimination to SP. If UPDATE_P, use UPDATE_SP_OFFSET for updating
offsets of register elimnable to SP.
MEM_MODE is the mode of an enclosing MEM. We need this to know how
much to adjust a register for, e.g., PRE_DEC. Also, if we are
......@@ -311,7 +312,8 @@ get_elimination (rtx reg)
sp offset. */
rtx
lra_eliminate_regs_1 (rtx_insn *insn, rtx x, machine_mode mem_mode,
bool subst_p, bool update_p, bool full_p)
bool subst_p, bool update_p,
HOST_WIDE_INT update_sp_offset, bool full_p)
{
enum rtx_code code = GET_CODE (x);
struct lra_elim_table *ep;
......@@ -346,7 +348,10 @@ lra_eliminate_regs_1 (rtx_insn *insn, rtx x, machine_mode mem_mode,
rtx to = subst_p ? ep->to_rtx : ep->from_rtx;
if (update_p)
return plus_constant (Pmode, to, ep->offset - ep->previous_offset);
return plus_constant (Pmode, to,
ep->offset - ep->previous_offset
+ (ep->to_rtx == stack_pointer_rtx
? update_sp_offset : 0));
else if (full_p)
return plus_constant (Pmode, to,
ep->offset
......@@ -373,7 +378,10 @@ lra_eliminate_regs_1 (rtx_insn *insn, rtx x, machine_mode mem_mode,
return gen_rtx_PLUS (Pmode, to, XEXP (x, 1));
offset = (update_p
? ep->offset - ep->previous_offset : ep->offset);
? ep->offset - ep->previous_offset
+ (ep->to_rtx == stack_pointer_rtx
? update_sp_offset : 0)
: ep->offset);
if (full_p && insn != NULL_RTX && ep->to_rtx == stack_pointer_rtx)
offset -= lra_get_insn_recog_data (insn)->sp_offset;
if (CONST_INT_P (XEXP (x, 1))
......@@ -402,9 +410,11 @@ lra_eliminate_regs_1 (rtx_insn *insn, rtx x, machine_mode mem_mode,
{
rtx new0 = lra_eliminate_regs_1 (insn, XEXP (x, 0), mem_mode,
subst_p, update_p, full_p);
subst_p, update_p,
update_sp_offset, full_p);
rtx new1 = lra_eliminate_regs_1 (insn, XEXP (x, 1), mem_mode,
subst_p, update_p, full_p);
subst_p, update_p,
update_sp_offset, full_p);
if (new0 != XEXP (x, 0) || new1 != XEXP (x, 1))
return form_sum (new0, new1);
......@@ -423,11 +433,12 @@ lra_eliminate_regs_1 (rtx_insn *insn, rtx x, machine_mode mem_mode,
rtx to = subst_p ? ep->to_rtx : ep->from_rtx;
if (update_p)
return
plus_constant (Pmode,
gen_rtx_MULT (Pmode, to, XEXP (x, 1)),
(ep->offset - ep->previous_offset)
* INTVAL (XEXP (x, 1)));
return plus_constant (Pmode,
gen_rtx_MULT (Pmode, to, XEXP (x, 1)),
(ep->offset - ep->previous_offset
+ (ep->to_rtx == stack_pointer_rtx
? update_sp_offset : 0))
* INTVAL (XEXP (x, 1)));
else if (full_p)
{
HOST_WIDE_INT offset = ep->offset;
......@@ -459,10 +470,12 @@ lra_eliminate_regs_1 (rtx_insn *insn, rtx x, machine_mode mem_mode,
case LE: case LT: case LEU: case LTU:
{
rtx new0 = lra_eliminate_regs_1 (insn, XEXP (x, 0), mem_mode,
subst_p, update_p, full_p);
subst_p, update_p,
update_sp_offset, full_p);
rtx new1 = XEXP (x, 1)
? lra_eliminate_regs_1 (insn, XEXP (x, 1), mem_mode,
subst_p, update_p, full_p) : 0;
subst_p, update_p,
update_sp_offset, full_p) : 0;
if (new0 != XEXP (x, 0) || new1 != XEXP (x, 1))
return gen_rtx_fmt_ee (code, GET_MODE (x), new0, new1);
......@@ -475,7 +488,8 @@ lra_eliminate_regs_1 (rtx_insn *insn, rtx x, machine_mode mem_mode,
if (XEXP (x, 0))
{
new_rtx = lra_eliminate_regs_1 (insn, XEXP (x, 0), mem_mode,
subst_p, update_p, full_p);
subst_p, update_p,
update_sp_offset, full_p);
if (new_rtx != XEXP (x, 0))
{
/* If this is a REG_DEAD note, it is not valid anymore.
......@@ -484,7 +498,8 @@ lra_eliminate_regs_1 (rtx_insn *insn, rtx x, machine_mode mem_mode,
if (REG_NOTE_KIND (x) == REG_DEAD)
return (XEXP (x, 1)
? lra_eliminate_regs_1 (insn, XEXP (x, 1), mem_mode,
subst_p, update_p, full_p)
subst_p, update_p,
update_sp_offset, full_p)
: NULL_RTX);
x = alloc_reg_note (REG_NOTE_KIND (x), new_rtx, XEXP (x, 1));
......@@ -501,7 +516,8 @@ lra_eliminate_regs_1 (rtx_insn *insn, rtx x, machine_mode mem_mode,
if (XEXP (x, 1))
{
new_rtx = lra_eliminate_regs_1 (insn, XEXP (x, 1), mem_mode,
subst_p, update_p, full_p);
subst_p, update_p,
update_sp_offset, full_p);
if (new_rtx != XEXP (x, 1))
return
gen_rtx_fmt_ee (GET_CODE (x), GET_MODE (x),
......@@ -528,8 +544,8 @@ lra_eliminate_regs_1 (rtx_insn *insn, rtx x, machine_mode mem_mode,
&& XEXP (XEXP (x, 1), 0) == XEXP (x, 0))
{
rtx new_rtx = lra_eliminate_regs_1 (insn, XEXP (XEXP (x, 1), 1),
mem_mode,
subst_p, update_p, full_p);
mem_mode, subst_p, update_p,
update_sp_offset, full_p);
if (new_rtx != XEXP (XEXP (x, 1), 1))
return gen_rtx_fmt_ee (code, GET_MODE (x), XEXP (x, 0),
......@@ -553,14 +569,16 @@ lra_eliminate_regs_1 (rtx_insn *insn, rtx x, machine_mode mem_mode,
case PARITY:
case BSWAP:
new_rtx = lra_eliminate_regs_1 (insn, XEXP (x, 0), mem_mode,
subst_p, update_p, full_p);
subst_p, update_p,
update_sp_offset, full_p);
if (new_rtx != XEXP (x, 0))
return gen_rtx_fmt_e (code, GET_MODE (x), new_rtx);
return x;
case SUBREG:
new_rtx = lra_eliminate_regs_1 (insn, SUBREG_REG (x), mem_mode,
subst_p, update_p, full_p);
subst_p, update_p,
update_sp_offset, full_p);
if (new_rtx != SUBREG_REG (x))
{
......@@ -598,12 +616,12 @@ lra_eliminate_regs_1 (rtx_insn *insn, rtx x, machine_mode mem_mode,
replace_equiv_address_nv
(x,
lra_eliminate_regs_1 (insn, XEXP (x, 0), GET_MODE (x),
subst_p, update_p, full_p));
subst_p, update_p, update_sp_offset, full_p));
case USE:
/* Handle insn_list USE that a call to a pure function may generate. */
new_rtx = lra_eliminate_regs_1 (insn, XEXP (x, 0), VOIDmode,
subst_p, update_p, full_p);
subst_p, update_p, update_sp_offset, full_p);
if (new_rtx != XEXP (x, 0))
return gen_rtx_USE (GET_MODE (x), new_rtx);
return x;
......@@ -624,7 +642,8 @@ lra_eliminate_regs_1 (rtx_insn *insn, rtx x, machine_mode mem_mode,
if (*fmt == 'e')
{
new_rtx = lra_eliminate_regs_1 (insn, XEXP (x, i), mem_mode,
subst_p, update_p, full_p);
subst_p, update_p,
update_sp_offset, full_p);
if (new_rtx != XEXP (x, i) && ! copied)
{
x = shallow_copy_rtx (x);
......@@ -638,7 +657,8 @@ lra_eliminate_regs_1 (rtx_insn *insn, rtx x, machine_mode mem_mode,
for (j = 0; j < XVECLEN (x, i); j++)
{
new_rtx = lra_eliminate_regs_1 (insn, XVECEXP (x, i, j), mem_mode,
subst_p, update_p, full_p);
subst_p, update_p,
update_sp_offset, full_p);
if (new_rtx != XVECEXP (x, i, j) && ! copied_vec)
{
rtvec new_v = gen_rtvec_v (XVECLEN (x, i),
......@@ -665,7 +685,7 @@ rtx
lra_eliminate_regs (rtx x, machine_mode mem_mode,
rtx insn ATTRIBUTE_UNUSED)
{
return lra_eliminate_regs_1 (NULL, x, mem_mode, true, false, true);
return lra_eliminate_regs_1 (NULL, x, mem_mode, true, false, 0, true);
}
/* Stack pointer offset before the current insn relative to one at the
......@@ -850,13 +870,15 @@ remove_reg_equal_offset_note (rtx insn, rtx what)
If REPLACE_P is false, just update the offsets while keeping the
base register the same. If FIRST_P, use the sp offset for
elimination to sp. Attach the note about used elimination for
insns setting frame pointer to update elimination easy (without
parsing already generated elimination insns to find offset
previously used) in future. */
elimination to sp. Otherwise, use UPDATE_SP_OFFSET for this.
Attach the note about used elimination for insns setting frame
pointer to update elimination easy (without parsing already
generated elimination insns to find offset previously used) in
future. */
static void
eliminate_regs_in_insn (rtx_insn *insn, bool replace_p, bool first_p)
void
eliminate_regs_in_insn (rtx_insn *insn, bool replace_p, bool first_p,
HOST_WIDE_INT update_sp_offset)
{
int icode = recog_memoized (insn);
rtx old_set = single_set (insn);
......@@ -986,8 +1008,13 @@ eliminate_regs_in_insn (rtx_insn *insn, bool replace_p, bool first_p)
if (! replace_p)
{
offset += (ep->offset - ep->previous_offset);
if (first_p && ep->to_rtx == stack_pointer_rtx)
offset -= lra_get_insn_recog_data (insn)->sp_offset;
if (ep->to_rtx == stack_pointer_rtx)
{
if (first_p)
offset -= lra_get_insn_recog_data (insn)->sp_offset;
else
offset += update_sp_offset;
}
offset = trunc_int_for_mode (offset, GET_MODE (plus_cst_src));
}
......@@ -1061,7 +1088,7 @@ eliminate_regs_in_insn (rtx_insn *insn, bool replace_p, bool first_p)
substed_operand[i]
= lra_eliminate_regs_1 (insn, *id->operand_loc[i], VOIDmode,
replace_p, ! replace_p && ! first_p,
first_p);
update_sp_offset, first_p);
if (substed_operand[i] != orig_operand[i])
validate_p = true;
}
......@@ -1349,7 +1376,7 @@ lra_eliminate_reg_if_possible (rtx *loc)
static void
process_insn_for_elimination (rtx_insn *insn, bool final_p, bool first_p)
{
eliminate_regs_in_insn (insn, final_p, first_p);
eliminate_regs_in_insn (insn, final_p, first_p, 0);
if (! final_p)
{
/* Check that insn changed its code. This is a case when a move
......
......@@ -328,7 +328,6 @@ extern bitmap_head lra_inheritance_pseudos;
extern bitmap_head lra_split_regs;
extern bitmap_head lra_subreg_reload_pseudos;
extern bitmap_head lra_optional_reload_pseudos;
extern int lra_constraint_new_insn_uid_start;
/* lra-constraints.c: */
......@@ -339,6 +338,7 @@ extern int lra_constraint_iter;
extern bool lra_risky_transformations_p;
extern int lra_inheritance_iter;
extern int lra_undo_inheritance_iter;
extern bool lra_constrain_insn (rtx_insn *);
extern bool lra_constraints (bool);
extern void lra_constraints_init (void);
extern void lra_constraints_finish (void);
......@@ -389,13 +389,17 @@ extern bool lra_need_for_spills_p (void);
extern void lra_spill (void);
extern void lra_final_code_change (void);
/* lra-remat.c: */
extern bool lra_remat (void);
/* lra-elimination.c: */
extern void lra_debug_elim_table (void);
extern int lra_get_elimination_hard_regno (int);
extern rtx lra_eliminate_regs_1 (rtx_insn *, rtx, machine_mode, bool,
bool, bool);
extern rtx lra_eliminate_regs_1 (rtx_insn *, rtx, machine_mode,
bool, bool, HOST_WIDE_INT, bool);
extern void eliminate_regs_in_insn (rtx_insn *insn, bool, bool, HOST_WIDE_INT);
extern void lra_eliminate (bool, bool);
extern void lra_eliminate_reg_if_possible (rtx *);
......
......@@ -252,8 +252,7 @@ make_hard_regno_born (int regno)
unsigned int i;
lra_assert (regno < FIRST_PSEUDO_REGISTER);
if (TEST_HARD_REG_BIT (lra_no_alloc_regs, regno)
|| TEST_HARD_REG_BIT (hard_regs_live, regno))
if (TEST_HARD_REG_BIT (hard_regs_live, regno))
return;
SET_HARD_REG_BIT (hard_regs_live, regno);
sparseset_set_bit (start_living, regno);
......@@ -267,8 +266,7 @@ static void
make_hard_regno_dead (int regno)
{
lra_assert (regno < FIRST_PSEUDO_REGISTER);
if (TEST_HARD_REG_BIT (lra_no_alloc_regs, regno)
|| ! TEST_HARD_REG_BIT (hard_regs_live, regno))
if (! TEST_HARD_REG_BIT (hard_regs_live, regno))
return;
sparseset_set_bit (start_dying, regno);
CLEAR_HARD_REG_BIT (hard_regs_live, regno);
......@@ -662,7 +660,6 @@ process_bb_lives (basic_block bb, int &curr_point)
sparseset_clear (pseudos_live_through_setjumps);
REG_SET_TO_HARD_REG_SET (hard_regs_live, reg_live_out);
AND_COMPL_HARD_REG_SET (hard_regs_live, eliminable_regset);
AND_COMPL_HARD_REG_SET (hard_regs_live, lra_no_alloc_regs);
EXECUTE_IF_SET_IN_BITMAP (reg_live_out, FIRST_PSEUDO_REGISTER, j, bi)
mark_pseudo_live (j, curr_point);
......
This diff is collapsed. Click to expand it.
......@@ -445,7 +445,7 @@ remove_pseudos (rtx *loc, rtx_insn *insn)
{
rtx x = lra_eliminate_regs_1 (insn, pseudo_slots[i].mem,
GET_MODE (pseudo_slots[i].mem),
false, false, true);
0, false, false, true);
*loc = x != pseudo_slots[i].mem ? x : copy_rtx (x);
}
return;
......
......@@ -37,6 +37,7 @@ along with GCC; see the file COPYING3. If not see
generated;
o Some pseudos might be spilled to assign hard registers to
new reload pseudos;
o Recalculating spilled pseudo values (rematerialization);
o Changing spilled pseudos to stack memory or their equivalences;
o Allocation stack memory changes the address displacement and
new iteration is needed.
......@@ -57,19 +58,26 @@ along with GCC; see the file COPYING3. If not see
----------- | ---------------- |
| | |
| V New |
---------------- No ------------ pseudos -------------------
| Spilled pseudo | change |Constraints:| or insns | Inheritance/split |
| to memory |<-------| RTL |--------->| transformations |
| substitution | | transfor- | | in EBB scope |
---------------- | mations | -------------------
| ------------
V
-------------------------
| Hard regs substitution, |
| devirtalization, and |------> Finish
| restoring scratches got |
| memory |
-------------------------
| ------------ pseudos -------------------
| |Constraints:| or insns | Inheritance/split |
| | RTL |--------->| transformations |
| | transfor- | | in EBB scope |
| substi- | mations | -------------------
| tutions ------------
| | No change
---------------- V
| Spilled pseudo | -------------------
| to memory |<----| Rematerialization |
| substitution | -------------------
----------------
| No susbtitions
V
-------------------------
| Hard regs substitution, |
| devirtalization, and |------> Finish
| restoring scratches got |
| memory |
-------------------------
To speed up the process:
o We process only insns affected by changes on previous
......@@ -849,38 +857,38 @@ collect_non_operand_hard_regs (rtx *x, lra_insn_recog_data_t data,
{
if ((regno = REGNO (op)) >= FIRST_PSEUDO_REGISTER)
return list;
/* Process all regs even unallocatable ones as we need info
about all regs for rematerialization pass. */
for (last = regno + hard_regno_nregs[regno][mode];
regno < last;
regno++)
if (! TEST_HARD_REG_BIT (lra_no_alloc_regs, regno)
|| TEST_HARD_REG_BIT (eliminable_regset, regno))
{
for (curr = list; curr != NULL; curr = curr->next)
if (curr->regno == regno && curr->subreg_p == subreg_p
&& curr->biggest_mode == mode)
{
if (curr->type != type)
curr->type = OP_INOUT;
if (curr->early_clobber != early_clobber)
curr->early_clobber = true;
break;
}
if (curr == NULL)
{
for (curr = list; curr != NULL; curr = curr->next)
if (curr->regno == regno && curr->subreg_p == subreg_p
&& curr->biggest_mode == mode)
{
/* This is a new hard regno or the info can not be
integrated into the found structure. */
if (curr->type != type)
curr->type = OP_INOUT;
if (curr->early_clobber != early_clobber)
curr->early_clobber = true;
break;
}
if (curr == NULL)
{
/* This is a new hard regno or the info can not be
integrated into the found structure. */
#ifdef STACK_REGS
early_clobber
= (early_clobber
/* This clobber is to inform popping floating
point stack only. */
&& ! (FIRST_STACK_REG <= regno
&& regno <= LAST_STACK_REG));
early_clobber
= (early_clobber
/* This clobber is to inform popping floating
point stack only. */
&& ! (FIRST_STACK_REG <= regno
&& regno <= LAST_STACK_REG));
#endif
list = new_insn_reg (data->insn, regno, type, mode, subreg_p,
early_clobber, list);
}
}
list = new_insn_reg (data->insn, regno, type, mode, subreg_p,
early_clobber, list);
}
}
return list;
}
switch (code)
......@@ -1456,10 +1464,8 @@ add_regs_to_insn_regno_info (lra_insn_recog_data_t data, rtx x, int uid,
if (REG_P (x))
{
regno = REGNO (x);
if (regno < FIRST_PSEUDO_REGISTER
&& TEST_HARD_REG_BIT (lra_no_alloc_regs, regno)
&& ! TEST_HARD_REG_BIT (eliminable_regset, regno))
return;
/* Process all regs even unallocatable ones as we need info about
all regs for rematerialization pass. */
expand_reg_info ();
if (bitmap_set_bit (&lra_reg_info[regno].insn_bitmap, uid))
{
......@@ -2152,9 +2158,6 @@ bitmap_head lra_optional_reload_pseudos;
pass. */
bitmap_head lra_subreg_reload_pseudos;
/* First UID of insns generated before a new spill pass. */
int lra_constraint_new_insn_uid_start;
/* File used for output of LRA debug information. */
FILE *lra_dump_file;
......@@ -2252,7 +2255,6 @@ lra (FILE *f)
lra_curr_reload_num = 0;
push_insns (get_last_insn (), NULL);
/* It is needed for the 1st coalescing. */
lra_constraint_new_insn_uid_start = get_max_uid ();
bitmap_initialize (&lra_inheritance_pseudos, &reg_obstack);
bitmap_initialize (&lra_split_regs, &reg_obstack);
bitmap_initialize (&lra_optional_reload_pseudos, &reg_obstack);
......@@ -2345,12 +2347,21 @@ lra (FILE *f)
lra_create_live_ranges (lra_reg_spill_p);
live_p = true;
}
/* Now we know what pseudos should be spilled. Try to
rematerialize them first. */
if (lra_remat ())
{
/* We need full live info -- see the comment above. */
lra_create_live_ranges (lra_reg_spill_p);
live_p = true;
if (! lra_need_for_spills_p ())
break;
}
lra_spill ();
/* Assignment of stack slots changes elimination offsets for
some eliminations. So update the offsets here. */
lra_eliminate (false, false);
lra_constraint_new_regno_start = max_reg_num ();
lra_constraint_new_insn_uid_start = get_max_uid ();
lra_assignment_iter_after_spill = 0;
}
restore_scratches ();
......
......@@ -500,6 +500,7 @@ static const struct default_options default_options_table[] =
{ OPT_LEVELS_2_PLUS, OPT_fipa_icf, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_fisolate_erroneous_paths_dereference, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_fuse_caller_save, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_flra_remat, NULL, 1 },
/* -O3 optimizations. */
{ OPT_LEVELS_3_PLUS, OPT_ftree_loop_distribute_patterns, NULL, 1 },
......
......@@ -237,6 +237,7 @@ DEFTIMEVAR (TV_LRA_INHERITANCE , "LRA reload inheritance")
DEFTIMEVAR (TV_LRA_CREATE_LIVE_RANGES, "LRA create live ranges")
DEFTIMEVAR (TV_LRA_ASSIGN , "LRA hard reg assignment")
DEFTIMEVAR (TV_LRA_COALESCE , "LRA coalesce pseudo regs")
DEFTIMEVAR (TV_LRA_REMAT , "LRA rematerialization")
DEFTIMEVAR (TV_RELOAD , "reload")
DEFTIMEVAR (TV_RELOAD_CSE_REGS , "reload CSE regs")
DEFTIMEVAR (TV_GCSE_AFTER_RELOAD , "load CSE after reload")
......
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