This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [patch] Stay in cfglayout mode until after cse2
- From: Paolo Bonzini <bonzini at gnu dot org>
- To: gcc-patches at gcc dot gnu dot org
- Cc: gcc-patches at gcc dot gnu dot org, iant at google dot com, "Bonzini, Paolo" <paolo dot bonzini at lu dot unisi dot ch>
- Date: Wed, 14 Mar 2007 09:27:47 +0100
- Subject: Re: [patch] Stay in cfglayout mode until after cse2
- References: <200703132045.12399.steven@gcc.gnu.org>
Steven Bosscher wrote:
> Hi,
>
> This patch postpones going out of cfglayout mode until after cse2.
> It will probably stay there for a while, because combine is totally
> unprepared for cfglayout mode right now. Paolo Bonzini has fixes
> for this on the dataflow branch, but until that branch is merged,
> we'll have to go out of cfglayout mode before combine.
>
> The next hurdle will be regmove. I'm hoping a Google Summer of
> Code student will re-implement regmove (with my help if required)...
>
> This patch has been bootstrapped&tested on i686-pc-linux-gnu.
> OK for the trunk?
Once this hits dataflow branch, I'll re-regtest the patch for
combine (which currently bootstraps but has regressions).
Paolo
2007-03-14 Paolo Bonzini <bonzini@gnu.org>
* cfglayout.c (fixup_reorder_chain): Add a barrier when there
is a jump but no fallthrough edge -- I'm pretty confident that
this is not necessary, but I bootstrapped with this so I'm
including it.
* combine.c (find_single_use): Use CFG to go through EBBs.
(update_cfg_for_uncondjump): New.
(try_combine): Check for unconditional jumps after marking insns for
rescan. Use update_cfg_for_uncondjump.
(reg_dead_at_p): Stop at head of BB, don't go back to beginning of EBB.
(rest_of_handle_combine): Enter/exit cfglayout mode.
Index: cfglayout.c
===================================================================
--- cfglayout.c (revision 122655)
+++ cfglayout.c (working copy)
@@ -741,6 +741,10 @@ fixup_reorder_chain (void)
jump. In the 99% case, there should not have been a
fallthru edge. */
gcc_assert (returnjump_p (bb_end_insn) || !e_fall);
+
+ if (NEXT_INSN (bb_end_insn) == 0
+ || !BARRIER_P (NEXT_INSN (bb_end_insn)))
+ emit_barrier_after (bb_end_insn);
continue;
}
}
Index: combine.c
===================================================================
--- combine.c (revision 122655)
+++ combine.c (working copy)
@@ -103,6 +103,7 @@ Software Foundation, 51 Franklin Street,
#include "params.h"
#include "timevar.h"
#include "tree-pass.h"
+#include "cfglayout.h"
#include "df.h"
/* Number of attempts to combine instructions in this function. */
@@ -588,6 +589,7 @@ find_single_use_1 (rtx dest, rtx *loc)
static rtx *
find_single_use (rtx dest, rtx insn, rtx *ploc)
{
+ basic_block bb;
rtx next;
rtx *result;
rtx link;
@@ -610,23 +612,41 @@ find_single_use (rtx dest, rtx insn, rtx
if (!REG_P (dest))
return 0;
- for (next = next_nonnote_insn (insn);
- next != 0 && !LABEL_P (next);
- next = next_nonnote_insn (next))
- if (INSN_P (next) && dead_or_set_p (next, dest))
- {
- for (link = LOG_LINKS (next); link; link = XEXP (link, 1))
- if (XEXP (link, 0) == insn)
+ next = insn;
+ bb = BLOCK_FOR_INSN (next);
+ for (;;)
+ {
+ /* Follow an extended basic block. */
+ if (next == BB_END (bb))
+ {
+ if (!single_succ_p (bb))
+ break;
+ bb = single_succ (bb);
+ if (!single_pred_p (bb))
break;
+ next = BB_HEAD (bb);
+ }
+ else
+ next = NEXT_INSN (next);
- if (link)
- {
- result = find_single_use_1 (dest, &PATTERN (next));
- if (ploc)
- *ploc = next;
- return result;
- }
- }
+ if (!next)
+ break;
+
+ if (INSN_P (next) && dead_or_set_p (next, dest))
+ {
+ for (link = LOG_LINKS (next); link; link = XEXP (link, 1))
+ if (XEXP (link, 0) == insn)
+ break;
+
+ if (link)
+ {
+ result = find_single_use_1 (dest, &PATTERN (next));
+ if (ploc)
+ *ploc = next;
+ return result;
+ }
+ }
+ }
return 0;
}
@@ -2103,6 +2123,36 @@ reg_subword_p (rtx x, rtx reg)
&& GET_MODE_CLASS (GET_MODE (x)) == MODE_INT;
}
+static void
+update_cfg_for_uncondjump (rtx insn, bool fallthru)
+{
+ basic_block bb = BLOCK_FOR_INSN (insn);
+
+ if (current_ir_type () == IR_RTL_CFGLAYOUT)
+ {
+ /* For a (set (pc) (label_ref FOO)), we need to delete the insn *after*
+ removing the dead edges. Otherwise, we always keep the old fallthrough
+ edge, which is wrong. */
+ if (BB_END (bb) == insn)
+ purge_dead_edges (bb);
+
+ delete_insn (insn);
+ if (EDGE_COUNT (bb->succs) == 1)
+ single_succ_edge (bb)->flags |= EDGE_FALLTHRU;
+ }
+ else
+ {
+ if (fallthru)
+ delete_insn (insn);
+ else
+ {
+ /* Emit a BARRIER after the unconditional jump. */
+ if (NEXT_INSN (insn) == 0 || !BARRIER_P (NEXT_INSN (insn)))
+ emit_barrier_after (insn);
+ }
+ }
+}
+
/* Try to combine the insns I1 and I2 into I3.
Here I1 and I2 appear earlier than I3.
@@ -3679,43 +3729,8 @@ try_combine (rtx i3, rtx i2, rtx i1, int
if (newi2pat)
note_stores (newi2pat, set_nonzero_bits_and_sign_copies, NULL);
note_stores (newpat, set_nonzero_bits_and_sign_copies, NULL);
-
- /* Set new_direct_jump_p if a new return or simple jump instruction
- has been created.
-
- If I3 is now an unconditional jump, ensure that it has a
- BARRIER following it since it may have initially been a
- conditional jump. It may also be the last nonnote insn. */
-
- if (returnjump_p (i3) || any_uncondjump_p (i3))
- {
- *new_direct_jump_p = 1;
- mark_jump_label (PATTERN (i3), i3, 0);
-
- if ((temp = next_nonnote_insn (i3)) == NULL_RTX
- || !BARRIER_P (temp))
- emit_barrier_after (i3);
- }
-
- if (undobuf.other_insn != NULL_RTX
- && (returnjump_p (undobuf.other_insn)
- || any_uncondjump_p (undobuf.other_insn)))
- {
- *new_direct_jump_p = 1;
-
- if ((temp = next_nonnote_insn (undobuf.other_insn)) == NULL_RTX
- || !BARRIER_P (temp))
- emit_barrier_after (undobuf.other_insn);
- }
-
- /* An NOOP jump does not need barrier, but it does need cleaning up
- of CFG. */
- if (GET_CODE (newpat) == SET
- && SET_SRC (newpat) == pc_rtx
- && SET_DEST (newpat) == pc_rtx)
- *new_direct_jump_p = 1;
}
-
+
if (undobuf.other_insn != NULL_RTX)
{
if (dump_file)
@@ -3756,6 +3771,37 @@ try_combine (rtx i3, rtx i2, rtx i1, int
df_insn_rescan (i3);
}
+ /* Set new_direct_jump_p if a new return or simple jump instruction
+ has been created.
+
+ If I3 is now an unconditional jump, ensure that it has a
+ BARRIER following it since it may have initially been a
+ conditional jump. It may also be the last nonnote insn. */
+
+ if (returnjump_p (i3) || any_uncondjump_p (i3))
+ {
+ *new_direct_jump_p = 1;
+ mark_jump_label (PATTERN (i3), i3, 0);
+ update_cfg_for_uncondjump (i3, false);
+ }
+
+ if (undobuf.other_insn != NULL_RTX
+ && (returnjump_p (undobuf.other_insn)
+ || any_uncondjump_p (undobuf.other_insn)))
+ {
+ *new_direct_jump_p = 1;
+ update_cfg_for_uncondjump (undobuf.other_insn, false);
+ }
+
+ /* An NOOP also needs cleaning up of CFG. */
+ if (GET_CODE (newpat) == SET
+ && SET_SRC (newpat) == pc_rtx
+ && SET_DEST (newpat) == pc_rtx)
+ {
+ *new_direct_jump_p = 1;
+ update_cfg_for_uncondjump (i3, true);
+ }
+
combine_successes++;
undo_commit ();
@@ -11850,32 +11896,28 @@ reg_dead_at_p (rtx reg, rtx insn)
return 0;
}
- /* Scan backwards until we find a REG_DEAD note, SET, CLOBBER, label, or
- beginning of function. */
- for (; insn && !LABEL_P (insn) && !BARRIER_P (insn);
- insn = prev_nonnote_insn (insn))
- {
- note_stores (PATTERN (insn), reg_dead_at_p_1, NULL);
- if (reg_dead_flag)
- return reg_dead_flag == 1 ? 1 : 0;
+ /* Scan backwards until we find a REG_DEAD note, SET, CLOBBER, or
+ beginning of basic block. */
+ block = BLOCK_FOR_INSN (insn);
+ for (;;)
+ {
+ if (INSN_P (insn))
+ {
+ note_stores (PATTERN (insn), reg_dead_at_p_1, NULL);
+ if (reg_dead_flag)
+ return reg_dead_flag == 1 ? 1 : 0;
- if (find_regno_note (insn, REG_DEAD, reg_dead_regno))
- return 1;
- }
+ if (find_regno_note (insn, REG_DEAD, reg_dead_regno))
+ return 1;
+ }
- /* Get the basic block that we were in. */
- if (insn == 0)
- block = ENTRY_BLOCK_PTR->next_bb;
- else
- {
- FOR_EACH_BB (block)
- if (insn == BB_HEAD (block))
- break;
+ if (insn == BB_HEAD (block))
+ break;
- if (block == EXIT_BLOCK_PTR)
- return 0;
+ insn = PREV_INSN (insn);
}
+ /* Look at live-in sets for the basic block that we were in. */
for (i = reg_dead_regno; i < reg_dead_endregno; i++)
if (REGNO_REG_SET_P (DF_LIVE_IN (block), i))
return 0;
@@ -12935,6 +12977,9 @@ static unsigned int
rest_of_handle_combine (void)
{
int rebuild_jump_labels_after_combine;
+ basic_block bb;
+
+ cfg_layout_initialize (0);
df_set_flags (DF_LR_RUN_DCE + DF_DEFER_INSN_RESCAN);
df_ri_add_problem (DF_RI_LIFE);
@@ -12943,6 +12988,12 @@ rest_of_handle_combine (void)
rebuild_jump_labels_after_combine
= combine_instructions (get_insns (), max_reg_num ());
+ FOR_EACH_BB (bb)
+ if (bb->index >= NUM_FIXED_BLOCKS
+ && bb->next_bb->index >= NUM_FIXED_BLOCKS)
+ bb->aux = bb->next_bb;
+ cfg_layout_finalize ();
+
/* Combining insns may have turned an indirect jump into a
direct jump. Rebuild the JUMP_LABEL fields of jumping
instructions. */