summaryrefslogtreecommitdiff
path: root/gcc/ira.c
diff options
context:
space:
mode:
authoramodra <amodra@138bc75d-0d04-0410-961f-82ee72b054a4>2016-04-29 23:59:22 +0000
committeramodra <amodra@138bc75d-0d04-0410-961f-82ee72b054a4>2016-04-29 23:59:22 +0000
commit0327cdb06d2e564321ae16b218dcb99614680198 (patch)
treec2be77324502170b735717d52975e6d41b0bebd3 /gcc/ira.c
parent1b8aec7f81a946e9b63c50be3e24dfc4e8b2fdb9 (diff)
downloadgcc-0327cdb06d2e564321ae16b218dcb99614680198.tar.gz
ira.c use DF infrastructure for combine_and_move_insns
This patch actually improves generated code, because REG_DEAD notes used by the old insn scan are not always present. On x86_64, see gcc/wide-int-print.o:print_hex for an example of a function that is smaller and uses one less callee saved reg. * ira.c (combine_and_move_insns): Rather than scanning insns, use DF infrastucture to find use and def insns. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@235660 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/ira.c')
-rw-r--r--gcc/ira.c195
1 files changed, 86 insertions, 109 deletions
diff --git a/gcc/ira.c b/gcc/ira.c
index 91225f6be2c..44a1ef09aa8 100644
--- a/gcc/ira.c
+++ b/gcc/ira.c
@@ -3630,142 +3630,119 @@ add_store_equivs (void)
static void
combine_and_move_insns (void)
{
- rtx_insn *insn;
- basic_block bb;
- int loop_depth;
bitmap cleared_regs = BITMAP_ALLOC (NULL);
+ int max = max_reg_num ();
- FOR_EACH_BB_REVERSE_FN (bb, cfun)
+ for (int regno = FIRST_PSEUDO_REGISTER; regno < max; regno++)
{
- loop_depth = bb_loop_depth (bb);
- for (insn = BB_END (bb);
- insn != PREV_INSN (BB_HEAD (bb));
- insn = PREV_INSN (insn))
- {
- rtx link;
+ if (!reg_equiv[regno].replace)
+ continue;
- if (! INSN_P (insn))
- continue;
+ rtx_insn *use_insn = 0;
+ for (df_ref use = DF_REG_USE_CHAIN (regno);
+ use;
+ use = DF_REF_NEXT_REG (use))
+ if (DF_REF_INSN_INFO (use))
+ {
+ if (DEBUG_INSN_P (DF_REF_INSN (use)))
+ continue;
+ gcc_assert (!use_insn);
+ use_insn = DF_REF_INSN (use);
+ }
+ gcc_assert (use_insn);
- /* Don't substitute into jumps. indirect_jump_optimize does
- this for anything we are prepared to handle. */
- if (JUMP_P (insn))
- continue;
+ /* Don't substitute into jumps. indirect_jump_optimize does
+ this for anything we are prepared to handle. */
+ if (JUMP_P (use_insn))
+ continue;
- for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
- {
- if (REG_NOTE_KIND (link) == REG_DEAD
- /* Make sure this insn still refers to the register. */
- && reg_mentioned_p (XEXP (link, 0), PATTERN (insn)))
- {
- int regno = REGNO (XEXP (link, 0));
- rtx equiv_insn;
+ df_ref def = DF_REG_DEF_CHAIN (regno);
+ gcc_assert (DF_REG_DEF_COUNT (regno) == 1 && DF_REF_INSN_INFO (def));
+ rtx_insn *def_insn = DF_REF_INSN (def);
- if (! reg_equiv[regno].replace
- || reg_equiv[regno].loop_depth < (short) loop_depth)
- continue;
+ /* We may not move instructions that can throw, since that
+ changes basic block boundaries and we are not prepared to
+ adjust the CFG to match. */
+ if (can_throw_internal (def_insn))
+ continue;
- /* reg_equiv[REGNO].replace gets set only when
- REG_N_REFS[REGNO] is 2, i.e. the register is set
- once and used once. (If it were only set, but
- not used, flow would have deleted the setting
- insns.) Hence there can only be one insn in
- reg_equiv[REGNO].init_insns. */
- gcc_assert (reg_equiv[regno].init_insns
- && !XEXP (reg_equiv[regno].init_insns, 1));
- equiv_insn = XEXP (reg_equiv[regno].init_insns, 0);
-
- /* We may not move instructions that can throw, since
- that changes basic block boundaries and we are not
- prepared to adjust the CFG to match. */
- if (can_throw_internal (equiv_insn))
- continue;
+ basic_block use_bb = BLOCK_FOR_INSN (use_insn);
+ basic_block def_bb = BLOCK_FOR_INSN (def_insn);
+ if (bb_loop_depth (use_bb) > bb_loop_depth (def_bb))
+ continue;
- if (asm_noperands (PATTERN (equiv_insn)) < 0
- && validate_replace_rtx (regno_reg_rtx[regno],
- *(reg_equiv[regno].src_p), insn))
- {
- rtx equiv_link;
- rtx last_link;
- rtx note;
-
- /* Find the last note. */
- for (last_link = link; XEXP (last_link, 1);
- last_link = XEXP (last_link, 1))
- ;
-
- /* Append the REG_DEAD notes from equiv_insn. */
- equiv_link = REG_NOTES (equiv_insn);
- while (equiv_link)
- {
- note = equiv_link;
- equiv_link = XEXP (equiv_link, 1);
- if (REG_NOTE_KIND (note) == REG_DEAD)
- {
- remove_note (equiv_insn, note);
- XEXP (last_link, 1) = note;
- XEXP (note, 1) = NULL_RTX;
- last_link = note;
- }
- }
+ if (asm_noperands (PATTERN (def_insn)) < 0
+ && validate_replace_rtx (regno_reg_rtx[regno],
+ *reg_equiv[regno].src_p, use_insn))
+ {
+ rtx link;
+ /* Append the REG_DEAD notes from def_insn. */
+ for (rtx *p = &REG_NOTES (def_insn); (link = *p) != 0; )
+ {
+ if (REG_NOTE_KIND (XEXP (link, 0)) == REG_DEAD)
+ {
+ *p = XEXP (link, 1);
+ XEXP (link, 1) = REG_NOTES (use_insn);
+ REG_NOTES (use_insn) = link;
+ }
+ else
+ p = &XEXP (link, 1);
+ }
- remove_death (regno, insn);
- SET_REG_N_REFS (regno, 0);
- REG_FREQ (regno) = 0;
- delete_insn (equiv_insn);
+ remove_death (regno, use_insn);
+ SET_REG_N_REFS (regno, 0);
+ REG_FREQ (regno) = 0;
+ delete_insn (def_insn);
- reg_equiv[regno].init_insns
- = reg_equiv[regno].init_insns->next ();
+ reg_equiv[regno].init_insns = NULL;
+ ira_reg_equiv[regno].init_insns = NULL;
+ bitmap_set_bit (cleared_regs, regno);
+ }
- ira_reg_equiv[regno].init_insns = NULL;
- bitmap_set_bit (cleared_regs, regno);
- }
- /* Move the initialization of the register to just before
- INSN. Update the flow information. */
- else if (prev_nondebug_insn (insn) != equiv_insn)
- {
- rtx_insn *new_insn;
+ /* Move the initialization of the register to just before
+ USE_INSN. Update the flow information. */
+ else if (prev_nondebug_insn (use_insn) != def_insn)
+ {
+ rtx_insn *new_insn;
- new_insn = emit_insn_before (PATTERN (equiv_insn), insn);
- REG_NOTES (new_insn) = REG_NOTES (equiv_insn);
- REG_NOTES (equiv_insn) = 0;
- /* Rescan it to process the notes. */
- df_insn_rescan (new_insn);
+ new_insn = emit_insn_before (PATTERN (def_insn), use_insn);
+ REG_NOTES (new_insn) = REG_NOTES (def_insn);
+ REG_NOTES (def_insn) = 0;
+ /* Rescan it to process the notes. */
+ df_insn_rescan (new_insn);
- /* Make sure this insn is recognized before
- reload begins, otherwise
- eliminate_regs_in_insn will die. */
- INSN_CODE (new_insn) = INSN_CODE (equiv_insn);
+ /* Make sure this insn is recognized before reload begins,
+ otherwise eliminate_regs_in_insn will die. */
+ INSN_CODE (new_insn) = INSN_CODE (def_insn);
- delete_insn (equiv_insn);
+ delete_insn (def_insn);
- XEXP (reg_equiv[regno].init_insns, 0) = new_insn;
+ XEXP (reg_equiv[regno].init_insns, 0) = new_insn;
- REG_BASIC_BLOCK (regno) = bb->index;
- REG_N_CALLS_CROSSED (regno) = 0;
- REG_FREQ_CALLS_CROSSED (regno) = 0;
- REG_N_THROWING_CALLS_CROSSED (regno) = 0;
- REG_LIVE_LENGTH (regno) = 2;
+ REG_BASIC_BLOCK (regno) = use_bb->index;
+ REG_N_CALLS_CROSSED (regno) = 0;
+ REG_FREQ_CALLS_CROSSED (regno) = 0;
+ REG_N_THROWING_CALLS_CROSSED (regno) = 0;
+ REG_LIVE_LENGTH (regno) = 2;
- if (insn == BB_HEAD (bb))
- BB_HEAD (bb) = PREV_INSN (insn);
+ if (use_insn == BB_HEAD (use_bb))
+ BB_HEAD (use_bb) = new_insn;
- ira_reg_equiv[regno].init_insns
- = gen_rtx_INSN_LIST (VOIDmode, new_insn, NULL_RTX);
- bitmap_set_bit (cleared_regs, regno);
- }
- }
- }
+ ira_reg_equiv[regno].init_insns
+ = gen_rtx_INSN_LIST (VOIDmode, new_insn, NULL_RTX);
+ bitmap_set_bit (cleared_regs, regno);
}
}
if (!bitmap_empty_p (cleared_regs))
{
+ basic_block bb;
+
FOR_EACH_BB_FN (bb, cfun)
{
bitmap_and_compl_into (DF_LR_IN (bb), cleared_regs);
bitmap_and_compl_into (DF_LR_OUT (bb), cleared_regs);
- if (! df_live)
+ if (!df_live)
continue;
bitmap_and_compl_into (DF_LIVE_IN (bb), cleared_regs);
bitmap_and_compl_into (DF_LIVE_OUT (bb), cleared_regs);
@@ -3773,7 +3750,7 @@ combine_and_move_insns (void)
/* Last pass - adjust debug insns referencing cleared regs. */
if (MAY_HAVE_DEBUG_INSNS)
- for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ for (rtx_insn *insn = get_insns (); insn; insn = NEXT_INSN (insn))
if (DEBUG_INSN_P (insn))
{
rtx old_loc = INSN_VAR_LOCATION_LOC (insn);