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++)

Attachment: 1.dot.tar.bz2
Description: application/bzip

Reply via email to