On 08/05/14 09:07, Zhenqiang Chen wrote:
static bool move_insn_for_shrink_wrap (basic_block bb, rtx insn, const HARD_REG_SET uses, const HARD_REG_SET defs, - HARD_REG_SET *last_uses) + HARD_REG_SET *last_uses, + bool *split_p) { rtx set, src, dest; bitmap live_out, live_in, bb_uses, bb_defs; unsigned int i, dregno, end_dregno, sregno, end_sregno; basic_block next_block; + edge live_edge;/* Look for a simple register copy. */ set = single_set (insn); @@ -5582,17 +5589,31 @@ move_insn_for_shrink_wrap (basic_block bb, rtx insn, || overlaps_hard_reg_set_p (defs, GET_MODE (dest), dregno)) return false; - /* See whether there is a successor block to which we could move INSN. */ - next_block = next_block_for_reg (bb, dregno, end_dregno); - if (!next_block) + live_edge = next_block_for_reg (bb, dregno, end_dregno); + if (!live_edge) return false; + next_block = live_edge->dest; + /* If the destination register is referred in later insn, try to forward it. */ if (overlaps_hard_reg_set_p (*last_uses, GET_MODE (dest), dregno) && !try_copy_prop (bb, insn, src, dest, last_uses)) return false; + /* Create a new basic block on the edge. */ + if (EDGE_COUNT (next_block->preds) == 2) + { + next_block = split_edge (live_edge); + + bitmap_copy (df_get_live_in (next_block), df_get_live_out (bb));
(re-sent, looks like the first send not received by the server...) for the function "_IO_wdefault_xsputn" in glibc wgenops.c (.dot file attached) 174: NOTE_INSN_BASIC_BLOCK 21 are the new created basic block because of the sink of move instruction "ax:DI = 0" and split edge. but the live_in of this BB is copied from live_out of BB 2 which is too big, and actually prevent the later sink of "16: r12:DI=dx:DI". Should it be better to copy live_in from "next_block->next_bb" instead of live_out from "bb", as it will model what's needed more accurately? + bitmap_copy (df_get_live_in (next_block), df_get_live_in (next_block->next_bb)); After this modification, pass x86-64 bootstrap, and this function could be shrink-wrapped. -- Jiong
+ df_set_bb_dirty (next_block);
+
+ /* We should not split more than once for a function. */
+ gcc_assert (!(*split_p));
+ *split_p = true;
+ }
+
/* At this point we are committed to moving INSN, but let's try to
move it as far as we can. */
do
@@ -5610,7 +5631,10 @@ move_insn_for_shrink_wrap (basic_block bb, rtx insn,
{
for (i = dregno; i < end_dregno; i++)
{
- if (REGNO_REG_SET_P (bb_uses, i) || REGNO_REG_SET_P (bb_defs, i)
+
+ if (*split_p
+ || REGNO_REG_SET_P (bb_uses, i)
+ || REGNO_REG_SET_P (bb_defs, i)
|| REGNO_REG_SET_P (&DF_LIVE_BB_INFO (bb)->gen, i))
next_block = NULL;
CLEAR_REGNO_REG_SET (live_out, i);
@@ -5621,7 +5645,8 @@ move_insn_for_shrink_wrap (basic_block bb, rtx insn,
Either way, SRC is now live on entry. */
for (i = sregno; i < end_sregno; i++)
{
- if (REGNO_REG_SET_P (bb_defs, i)
+ if (*split_p
+ || REGNO_REG_SET_P (bb_defs, i)
|| REGNO_REG_SET_P (&DF_LIVE_BB_INFO (bb)->gen, i))
next_block = NULL;
SET_REGNO_REG_SET (live_out, i);
@@ -5650,21 +5675,31 @@ move_insn_for_shrink_wrap (basic_block bb, rtx insn,
/* If we don't need to add the move to BB, look for a single
successor block. */
if (next_block)
- next_block = next_block_for_reg (next_block, dregno, end_dregno);
+ {
+ live_edge = next_block_for_reg (next_block, dregno, end_dregno);
+ if (!live_edge || EDGE_COUNT (live_edge->dest->preds) > 1)
+ break;
+ next_block = live_edge->dest;
+ }
}
while (next_block);
- /* BB now defines DEST. It only uses the parts of DEST that overlap SRC
- (next loop). */
- for (i = dregno; i < end_dregno; i++)
+ /* For the new created basic block, there is no dataflow info at all.
+ So skip the following dataflow update and check. */
+ if (!(*split_p))
{
- CLEAR_REGNO_REG_SET (bb_uses, i);
- SET_REGNO_REG_SET (bb_defs, i);
- }
+ /* BB now defines DEST. It only uses the parts of DEST that overlap SRC
+ (next loop). */
+ for (i = dregno; i < end_dregno; i++)
+ {
+ CLEAR_REGNO_REG_SET (bb_uses, i);
+ SET_REGNO_REG_SET (bb_defs, i);
+ }
- /* BB now uses SRC. */
- for (i = sregno; i < end_sregno; i++)
- SET_REGNO_REG_SET (bb_uses, i);
+ /* BB now uses SRC. */
+ for (i = sregno; i < end_sregno; i++)
+ SET_REGNO_REG_SET (bb_uses, i);
+ }
emit_insn_after (PATTERN (insn), bb_note (bb));
delete_insn (insn);
@@ -5684,6 +5719,7 @@ prepare_shrink_wrap (basic_block entry_block)
rtx insn, curr, x;
HARD_REG_SET uses, defs, last_uses;
df_ref *ref;
+ bool split_p = false;
if (!JUMP_P (BB_END (entry_block)))
return;
@@ -5693,7 +5729,7 @@ prepare_shrink_wrap (basic_block entry_block)
FOR_BB_INSNS_REVERSE_SAFE (entry_block, insn, curr)
if (NONDEBUG_INSN_P (insn)
&& !move_insn_for_shrink_wrap (entry_block, insn, uses, defs,
- &last_uses))
+ &last_uses, &split_p))
{
/* Add all defined registers to DEFs. */
for (ref = DF_INSN_DEFS (insn); *ref; ref++)
1.dot.tar.bz2
Description: application/bzip
