> -----Original Message----- > From: gcc-patches-ow...@gcc.gnu.org [mailto:gcc-patches- > ow...@gcc.gnu.org] On Behalf Of Jiong Wang > Sent: Monday, September 15, 2014 11:28 PM > To: Zhenqiang Chen > Cc: gcc-patches@gcc.gnu.org; Jeff Law > Subject: Re: [PATCH, 2/2] shrink wrap a function with a single loop: split > live_edge > > 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?
According to the algorithm, next_block->next_bb (which is live_edge->dest) should have two predecessors. Live_in of next_block->next_bb would include live_out of the other edge, which is not necessary accurately. To be more accurate, you may need an intersection of df_get_live_out (bb) and df_get_live_in (next_block->next_bb). Thanks! -Zhenqiang > + 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++) > >