OSDN Git Service

2012-09-11 Richard Guenther <rguenther@suse.de>
[pf3gnuchains/gcc-fork.git] / gcc / sel-sched-ir.c
index 4878460..e74fee2 100644 (file)
@@ -1,5 +1,5 @@
 /* Instruction scheduling pass.  Selective scheduler and pipeliner.
-   Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
+   Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -1745,6 +1745,11 @@ update_target_availability (expr_t to, expr_t from, insn_t split_point)
           else
             EXPR_TARGET_AVAILABLE (to) = -1;
         }
+      else if (EXPR_TARGET_AVAILABLE (from) == 0
+              && EXPR_LHS (from)
+              && REG_P (EXPR_LHS (from))
+              && REGNO (EXPR_LHS (to)) != REGNO (EXPR_LHS (from)))
+       EXPR_TARGET_AVAILABLE (to) = -1;
       else
         EXPR_TARGET_AVAILABLE (to) &= EXPR_TARGET_AVAILABLE (from);
     }
@@ -3653,7 +3658,7 @@ sel_recompute_toporder (void)
 static bool
 maybe_tidy_empty_bb (basic_block bb)
 {
-  basic_block succ_bb, pred_bb;
+  basic_block succ_bb, pred_bb, note_bb;
   VEC (basic_block, heap) *dom_bbs;
   edge e;
   edge_iterator ei;
@@ -3675,6 +3680,22 @@ maybe_tidy_empty_bb (basic_block bb)
   FOR_EACH_EDGE (e, ei, bb->preds)
     if (e->flags & EDGE_COMPLEX)
       return false;
+    else if (e->flags & EDGE_FALLTHRU)
+      {
+       rtx note;
+       /* If prev bb ends with asm goto, see if any of the
+          ASM_OPERANDS_LABELs don't point to the fallthru
+          label.  Do not attempt to redirect it in that case.  */
+       if (JUMP_P (BB_END (e->src))
+           && (note = extract_asm_operands (PATTERN (BB_END (e->src)))))
+         {
+           int i, n = ASM_OPERANDS_LABEL_LENGTH (note);
+
+           for (i = 0; i < n; ++i)
+             if (XEXP (ASM_OPERANDS_LABEL (note, i), 0) == BB_HEAD (bb))
+               return false;
+         }
+      }
 
   free_data_sets (bb);
 
@@ -3692,6 +3713,17 @@ maybe_tidy_empty_bb (basic_block bb)
   pred_bb = NULL;
   dom_bbs = NULL;
 
+  /* Save a pred/succ from the current region to attach the notes to.  */
+  note_bb = NULL;
+  FOR_EACH_EDGE (e, ei, bb->preds)
+    if (in_current_region_p (e->src))
+      {
+       note_bb = e->src;
+       break;
+      }
+  if (note_bb == NULL)
+    note_bb = succ_bb;
+
   /* Redirect all non-fallthru edges to the next bb.  */
   while (rescan_p)
     {
@@ -3741,10 +3773,8 @@ maybe_tidy_empty_bb (basic_block bb)
   else
     {
       /* This is a block without fallthru predecessor.  Just delete it.  */
-      gcc_assert (pred_bb != NULL);
-
-      if (in_current_region_p (pred_bb))
-       move_bb_info (pred_bb, bb);
+      gcc_assert (note_bb);
+      move_bb_info (note_bb, bb);
       remove_empty_bb (bb, true);
     }
 
@@ -5226,10 +5256,9 @@ sel_remove_bb (basic_block bb, bool remove_from_cfg_p)
 static void
 move_bb_info (basic_block merge_bb, basic_block empty_bb)
 {
-  gcc_assert (in_current_region_p (merge_bb));
-
-  concat_note_lists (BB_NOTE_LIST (empty_bb),
-                    &BB_NOTE_LIST (merge_bb));
+  if (in_current_region_p (merge_bb))
+    concat_note_lists (BB_NOTE_LIST (empty_bb),
+                      &BB_NOTE_LIST (merge_bb));
   BB_NOTE_LIST (empty_bb) = NULL_RTX;
 
 }
@@ -5718,7 +5747,7 @@ create_vinsn_from_insn_rtx (rtx insn_rtx, bool force_unique_p)
 rtx
 create_copy_of_insn_rtx (rtx insn_rtx)
 {
-  rtx res;
+  rtx res, link;
 
   if (DEBUG_INSN_P (insn_rtx))
     return create_insn_rtx_from_pattern (copy_rtx (PATTERN (insn_rtx)),
@@ -5728,6 +5757,22 @@ create_copy_of_insn_rtx (rtx insn_rtx)
 
   res = create_insn_rtx_from_pattern (copy_rtx (PATTERN (insn_rtx)),
                                       NULL_RTX);
+
+  /* Copy all REG_NOTES except REG_EQUAL/REG_EQUIV and REG_LABEL_OPERAND
+     since mark_jump_label will make them.  REG_LABEL_TARGETs are created
+     there too, but are supposed to be sticky, so we copy them.  */
+  for (link = REG_NOTES (insn_rtx); link; link = XEXP (link, 1))
+    if (REG_NOTE_KIND (link) != REG_LABEL_OPERAND
+       && REG_NOTE_KIND (link) != REG_EQUAL
+       && REG_NOTE_KIND (link) != REG_EQUIV)
+      {
+       if (GET_CODE (link) == EXPR_LIST)
+         add_reg_note (res, REG_NOTE_KIND (link),
+                       copy_insn_1 (XEXP (link, 0)));
+       else
+         add_reg_note (res, REG_NOTE_KIND (link), XEXP (link, 0));
+      }
+
   return res;
 }