]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/sel-sched-ir.c
[Ada] Fix documentation for GNAT.Command_Line.Exit_From_Command_Line
[thirdparty/gcc.git] / gcc / sel-sched-ir.c
index 26bc1422167305d5e0715c3ee0c4d7e0d885c232..bb8016bb530e5cba0148404357aa58bfb305500e 100644 (file)
@@ -1,5 +1,5 @@
 /* Instruction scheduling pass.  Selective scheduler and pipeliner.
-   Copyright (C) 2006-2016 Free Software Foundation, Inc.
+   Copyright (C) 2006-2019 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -61,7 +61,7 @@ struct succs_info current_succs;
 static struct common_sched_info_def sel_common_sched_info;
 
 /* The loop nest being pipelined.  */
-struct loop *current_loop_nest;
+class loop *current_loop_nest;
 
 /* LOOP_NESTS is a vector containing the corresponding loop nest for
    each region.  */
@@ -424,7 +424,7 @@ reset_target_context (tc_t tc, bool clean_p)
 }
 \f
 /* Functions to work with dependence contexts.
-   Dc (aka deps context, aka deps_t, aka struct deps_desc *) is short for dependence
+   Dc (aka deps context, aka deps_t, aka class deps_desc *) is short for dependence
    context.  It accumulates information about processed insns to decide if
    current insn is dependent on the processed ones.  */
 
@@ -440,7 +440,7 @@ copy_deps_context (deps_t to, deps_t from)
 static deps_t
 alloc_deps_context (void)
 {
-  return XNEW (struct deps_desc);
+  return XNEW (class deps_desc);
 }
 
 /* Allocate and initialize dep context.  */
@@ -703,11 +703,6 @@ merge_fences (fence_t f, insn_t insn,
       else
         if (candidate->src == BLOCK_FOR_INSN (last_scheduled_insn))
           {
-            /* Would be weird if same insn is successor of several fallthrough
-               edges.  */
-            gcc_assert (BLOCK_FOR_INSN (insn)->prev_bb
-                        != BLOCK_FOR_INSN (last_scheduled_insn_old));
-
             state_free (FENCE_STATE (f));
             FENCE_STATE (f) = state;
 
@@ -1324,7 +1319,7 @@ sel_insn_rtx_cost (rtx_insn *insn)
 }
 
 /* Return the cost of the VI.
-   !!! FIXME: Unify with haifa-sched.c: insn_cost ().  */
+   !!! FIXME: Unify with haifa-sched.c: insn_sched_cost ().  */
 int
 sel_vinsn_cost (vinsn_t vi)
 {
@@ -1837,8 +1832,12 @@ merge_expr_data (expr_t to, expr_t from, insn_t split_point)
   if (EXPR_PRIORITY (to) < EXPR_PRIORITY (from))
     EXPR_PRIORITY (to) = EXPR_PRIORITY (from);
 
-  if (EXPR_SCHED_TIMES (to) > EXPR_SCHED_TIMES (from))
-    EXPR_SCHED_TIMES (to) = EXPR_SCHED_TIMES (from);
+  /* We merge sched-times half-way to the larger value to avoid the endless
+     pipelining of unneeded insns.  The average seems to be good compromise
+     between pipelining opportunities and avoiding extra work.  */
+  if (EXPR_SCHED_TIMES (to) != EXPR_SCHED_TIMES (from))
+    EXPR_SCHED_TIMES (to) = ((EXPR_SCHED_TIMES (from) + EXPR_SCHED_TIMES (to)
+                             + 1) / 2);
 
   if (EXPR_ORIG_BB_INDEX (to) != EXPR_ORIG_BB_INDEX (from))
     EXPR_ORIG_BB_INDEX (to) = 0;
@@ -2750,7 +2749,7 @@ init_id_from_df (idata_t id, insn_t insn, bool force_unique_p)
 static void
 deps_init_id (idata_t id, insn_t insn, bool force_unique_p)
 {
-  struct deps_desc _dc, *dc = &_dc;
+  class deps_desc _dc, *dc = &_dc;
 
   deps_init_id_data.where = DEPS_IN_NOWHERE;
   deps_init_id_data.id = id;
@@ -3293,11 +3292,22 @@ has_dependence_note_mem_dep (rtx mem ATTRIBUTE_UNUSED,
 
 /* Note a dependence.  */
 static void
-has_dependence_note_dep (insn_t pro ATTRIBUTE_UNUSED,
-                        ds_t ds ATTRIBUTE_UNUSED)
-{
-  if (!sched_insns_conditions_mutex_p (has_dependence_data.pro,
-                                      VINSN_INSN_RTX (has_dependence_data.con)))
+has_dependence_note_dep (insn_t pro, ds_t ds ATTRIBUTE_UNUSED)
+{
+  insn_t real_pro = has_dependence_data.pro;
+  insn_t real_con = VINSN_INSN_RTX (has_dependence_data.con);
+
+  /* We do not allow for debug insns to move through others unless they
+     are at the start of bb.  This movement may create bookkeeping copies
+     that later would not be able to move up, violating the invariant
+     that a bookkeeping copy should be movable as the original insn.
+     Detect that here and allow that movement if we allowed it before
+     in the first place.  */
+  if (DEBUG_INSN_P (real_con) && !DEBUG_INSN_P (real_pro)
+      && INSN_UID (NEXT_INSN (pro)) == INSN_UID (real_con))
+    return;
+
+  if (!sched_insns_conditions_mutex_p (real_pro, real_con))
     {
       ds_t *dsp = &has_dependence_data.has_dep_p[has_dependence_data.where];
 
@@ -3380,7 +3390,7 @@ has_dependence_p (expr_t expr, insn_t pred, ds_t **has_dep_pp)
 {
   int i;
   ds_t ds;
-  struct deps_desc *dc;
+  class deps_desc *dc;
 
   if (INSN_SIMPLEJUMP_P (pred))
     /* Unconditional jump is just a transfer of control flow.
@@ -3767,7 +3777,7 @@ maybe_tidy_empty_bb (basic_block bb)
 
           if (!(e->flags & EDGE_FALLTHRU))
             {
-             /* We can not invalidate computed topological order by moving
+             /* We cannot invalidate computed topological order by moving
                 the edge destination block (E->SUCC) along a fallthru edge.
 
                 We will update dominators here only when we'll get
@@ -3839,9 +3849,13 @@ tidy_control_flow (basic_block xbb, bool full_tidying)
       && INSN_SCHED_TIMES (BB_END (xbb)) == 0
       && !IN_CURRENT_FENCE_P (BB_END (xbb)))
     {
-      if (sel_remove_insn (BB_END (xbb), false, false))
-        return true;
+      /* We used to call sel_remove_insn here that can trigger tidy_control_flow
+         before we fix up the fallthru edge.  Correct that ordering by
+        explicitly doing the latter before the former.  */
+      clear_expr (INSN_EXPR (BB_END (xbb)));
       tidy_fallthru_edge (EDGE_SUCC (xbb, 0));
+      if (tidy_control_flow (xbb, false))
+       return true;
     }
 
   first = sel_bb_head (xbb);
@@ -3890,6 +3904,19 @@ tidy_control_flow (basic_block xbb, bool full_tidying)
 
       gcc_assert (EDGE_SUCC (xbb->prev_bb, 0)->flags & EDGE_FALLTHRU);
 
+      /* We could have skipped some debug insns which did not get removed with the block,
+         and the seqnos could become incorrect.  Fix them up here.  */
+      if (MAY_HAVE_DEBUG_INSNS && (sel_bb_head (xbb) != first || sel_bb_end (xbb) != last))
+       {
+         if (!sel_bb_empty_p (xbb->prev_bb))
+           {
+             int prev_seqno = INSN_SEQNO (sel_bb_end (xbb->prev_bb));
+             if (prev_seqno > INSN_SEQNO (sel_bb_head (xbb)))
+               for (insn_t insn = sel_bb_head (xbb); insn != first; insn = NEXT_INSN (insn))
+                 INSN_SEQNO (insn) = prev_seqno + 1;
+           }
+       }
+
       /* It can turn out that after removing unused jump, basic block
          that contained that jump, becomes empty too.  In such case
          remove it too.  */
@@ -4747,7 +4774,11 @@ compute_succs_info (insn_t insn, short flags)
           sinfo->probs_ok.safe_push (
                    /* FIXME: Improve calculation when skipping
                        inner loop to exits.  */
-                    si.bb_end ? si.e1->probability : REG_BR_PROB_BASE);
+                    si.bb_end
+                   ? (si.e1->probability.initialized_p ()
+                       ? si.e1->probability.to_reg_br_prob_base ()
+                       : 0)
+                   : REG_BR_PROB_BASE);
           sinfo->succs_ok_n++;
         }
       else
@@ -4756,8 +4787,8 @@ compute_succs_info (insn_t insn, short flags)
       /* Compute all_prob.  */
       if (!si.bb_end)
         sinfo->all_prob = REG_BR_PROB_BASE;
-      else
-        sinfo->all_prob += si.e1->probability;
+      else if (si.e1->probability.initialized_p ())
+        sinfo->all_prob += si.e1->probability.to_reg_br_prob_base ();
 
       sinfo->all_succs_n++;
     }
@@ -5366,7 +5397,7 @@ change_loops_latches (basic_block from, basic_block to)
 
   if (current_loop_nest)
     {
-      struct loop *loop;
+      class loop *loop;
 
       for (loop = current_loop_nest; loop; loop = loop_outer (loop))
         if (considered_for_pipelining_p (loop) && loop->latch == from)
@@ -5606,6 +5637,8 @@ sel_redirect_edge_and_branch_force (edge e, basic_block to)
                           recompute_dominator (CDI_DOMINATORS, to));
   set_immediate_dominator (CDI_DOMINATORS, orig_dest,
                           recompute_dominator (CDI_DOMINATORS, orig_dest));
+  if (jump && sel_bb_head_p (jump))
+    compute_live (jump);
 }
 
 /* A wrapper for redirect_edge_and_branch.  Return TRUE if blocks connected by
@@ -5666,6 +5699,8 @@ sel_redirect_edge_and_branch (edge e, basic_block to)
       set_immediate_dominator (CDI_DOMINATORS, orig_dest,
                                recompute_dominator (CDI_DOMINATORS, orig_dest));
     }
+  if (jump && sel_bb_head_p (jump))
+    compute_live (jump);
   return recompute_toporder_p;
 }
 
@@ -5762,6 +5797,11 @@ create_copy_of_insn_rtx (rtx insn_rtx)
   res = create_insn_rtx_from_pattern (copy_rtx (PATTERN (insn_rtx)),
                                       NULL_RTX);
 
+  /* Locate the end of existing REG_NOTES in NEW_RTX.  */
+  rtx *ptail = &REG_NOTES (res);
+  while (*ptail != NULL_RTX)
+    ptail = &XEXP (*ptail, 1);
+
   /* 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.  */
@@ -5770,11 +5810,8 @@ create_copy_of_insn_rtx (rtx insn_rtx)
        && 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));
+       *ptail = duplicate_reg_note (link);
+       ptail = &XEXP (*ptail, 1);
       }
 
   return res;
@@ -5965,11 +6002,11 @@ bb_top_order_comparator (const void *x, const void *y)
 /* Create a region for LOOP and return its number.  If we don't want
    to pipeline LOOP, return -1.  */
 static int
-make_region_from_loop (struct loop *loop)
+make_region_from_loop (class loop *loop)
 {
   unsigned int i;
   int new_rgn_number = -1;
-  struct loop *inner;
+  class loop *inner;
 
   /* Basic block index, to be assigned to BLOCK_TO_BB.  */
   int bb_ord_index = 0;
@@ -6058,9 +6095,9 @@ make_region_from_loop_preheader (vec<basic_block> *&loop_blocks)
    pipelined before outer loops.  Returns true when a region for LOOP
    is created.  */
 static bool
-make_regions_from_loop_nest (struct loop *loop)
+make_regions_from_loop_nest (class loop *loop)
 {
-  struct loop *cur_loop;
+  class loop *cur_loop;
   int rgn_number;
 
   /* Traverse all inner nodes of the loop.  */
@@ -6096,7 +6133,7 @@ sel_init_pipelining (void)
   recompute_rev_top_order ();
 }
 
-/* Returns a struct loop for region RGN.  */
+/* Returns a class loop for region RGN.  */
 loop_p
 get_loop_nest_for_rgn (unsigned int rgn)
 {
@@ -6110,7 +6147,7 @@ get_loop_nest_for_rgn (unsigned int rgn)
 
 /* True when LOOP was included into pipelining regions.   */
 bool
-considered_for_pipelining_p (struct loop *loop)
+considered_for_pipelining_p (class loop *loop)
 {
   if (loop_depth (loop) == 0)
     return false;
@@ -6212,7 +6249,7 @@ make_regions_from_the_rest (void)
 /* Free data structures used in pipelining of loops.  */
 void sel_finish_pipelining (void)
 {
-  struct loop *loop;
+  class loop *loop;
 
   /* Release aux fields so we don't free them later by mistake.  */
   FOR_EACH_LOOP (loop, 0)
@@ -6287,7 +6324,7 @@ sel_is_loop_preheader_p (basic_block bb)
 {
   if (current_loop_nest)
     {
-      struct loop *outer;
+      class loop *outer;
 
       if (preheader_removed)
         return false;