bb-reorder.c (find_traces_1_round): Fix off-by-one index.
authorEric Botcazou <ebotcazou@adacore.com>
Fri, 27 Oct 2017 22:55:59 +0000 (22:55 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Fri, 27 Oct 2017 22:55:59 +0000 (22:55 +0000)
* bb-reorder.c (find_traces_1_round): Fix off-by-one index.
Move comment around.  Do not reset best_edge for a copiable
destination if the copy would cause a partition change.
(better_edge_p): Remove redundant check.

From-SVN: r254188

gcc/ChangeLog
gcc/bb-reorder.c
gcc/testsuite/ChangeLog
gcc/testsuite/gnat.dg/opt68.adb [new file with mode: 0644]
gcc/testsuite/gnat.dg/opt68.ads [new file with mode: 0644]

index b403f06..b1b14be 100644 (file)
@@ -1,3 +1,10 @@
+2017-10-27  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * bb-reorder.c (find_traces_1_round): Fix off-by-one index.
+       Move comment around.  Do not reset best_edge for a copiable
+       destination if the copy would cause a partition change.
+       (better_edge_p): Remove redundant check.
+
 2017-10-27  Uros Bizjak  <ubizjak@gmail.com>
 
        * config/i386/i386-protos.h (ix86_fp_compare_mode): Remove prototype.
index dc2025f..cd95952 100644 (file)
@@ -529,7 +529,7 @@ find_traces_1_round (int branch_th, int exec_th, gcov_type count_th,
 
          if (dump_file)
            fprintf (dump_file, "Basic block %d was visited in trace %d\n",
-                    bb->index, *n_traces - 1);
+                    bb->index, *n_traces);
 
          ends_in_call = block_ends_with_call_p (bb);
 
@@ -545,6 +545,8 @@ find_traces_1_round (int branch_th, int exec_th, gcov_type count_th,
                  && bb_visited_trace (e->dest) != *n_traces)
                continue;
 
+             /* If partitioning hot/cold basic blocks, don't consider edges
+                that cross section boundaries.  */
              if (BB_PARTITION (e->dest) != BB_PARTITION (bb))
                continue;
 
@@ -574,9 +576,6 @@ find_traces_1_round (int branch_th, int exec_th, gcov_type count_th,
                      || e->count () < count_th) && (!for_size)))
                continue;
 
-             /* If partitioning hot/cold basic blocks, don't consider edges
-                that cross section boundaries.  */
-
              if (better_edge_p (bb, e, prob, freq, best_prob, best_freq,
                                 best_edge))
                {
@@ -586,12 +585,28 @@ find_traces_1_round (int branch_th, int exec_th, gcov_type count_th,
                }
            }
 
-         /* If the best destination has multiple predecessors, and can be
-            duplicated cheaper than a jump, don't allow it to be added
-            to a trace.  We'll duplicate it when connecting traces.  */
-         if (best_edge && EDGE_COUNT (best_edge->dest->preds) >= 2
+         /* If the best destination has multiple predecessors and can be
+            duplicated cheaper than a jump, don't allow it to be added to
+            a trace; we'll duplicate it when connecting the traces later.
+            However, we need to check that this duplication wouldn't leave
+            the best destination with only crossing predecessors, because
+            this would change its effective partition from hot to cold.  */
+         if (best_edge
+             && EDGE_COUNT (best_edge->dest->preds) >= 2
              && copy_bb_p (best_edge->dest, 0))
-           best_edge = NULL;
+           {
+             bool only_crossing_preds = true;
+             edge e;
+             edge_iterator ei;
+             FOR_EACH_EDGE (e, ei, best_edge->dest->preds)
+               if (e != best_edge && !(e->flags & EDGE_CROSSING))
+                 {
+                   only_crossing_preds = false;
+                   break;
+                 }
+             if (!only_crossing_preds)
+               best_edge = NULL;
+           }
 
          /* If the best destination has multiple successors or predecessors,
             don't allow it to be added when optimizing for size.  This makes
@@ -988,16 +1003,6 @@ better_edge_p (const_basic_block bb, const_edge e, profile_probability prob,
   else
     is_better_edge = false;
 
-  /* If we are doing hot/cold partitioning, make sure that we always favor
-     non-crossing edges over crossing edges.  */
-
-  if (!is_better_edge
-      && flag_reorder_blocks_and_partition
-      && cur_best_edge
-      && (cur_best_edge->flags & EDGE_CROSSING)
-      && !(e->flags & EDGE_CROSSING))
-    is_better_edge = true;
-
   return is_better_edge;
 }
 
index 9383607..58da3bb 100644 (file)
@@ -1,3 +1,7 @@
+2017-10-27  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gnat.dg/opt68.ad[sb]: New test.
+
 2017-10-27  Daniel Santos  <daniel.santos@pobox.com>
 
        * gcc.target/i386/pr82196-1.c (dg-options): Add -mno-avx.
diff --git a/gcc/testsuite/gnat.dg/opt68.adb b/gcc/testsuite/gnat.dg/opt68.adb
new file mode 100644 (file)
index 0000000..caf6b71
--- /dev/null
@@ -0,0 +1,53 @@
+-- { dg-do compile }
+-- { dg-options "-O3" }
+
+with Ada.Unchecked_Deallocation;
+
+package body Opt68 is
+
+  procedure Free
+    is new Ada.Unchecked_Deallocation (Queue_Element, A_Queue_Element);
+
+  procedure Copy (dest : in out Queue; src : Queue) is
+    d, s, pd, ps, t : A_Queue_Element;
+  begin
+    if src.sz /= 0 then
+      d := dest.front;
+      s := src.front;
+      while d /= null and s /= null loop
+        d.value := s.value;
+        pd := d;
+        ps := s;
+        d  := d.next;
+        s  := s.next;
+      end loop;
+      if src.sz = dest.sz then
+        return;
+      elsif s = null then
+        while d /= null loop
+          t := d.next;
+          Free (d);
+          d := t;
+        end loop;
+        dest.back      := pd;
+        dest.back.next := null;
+      else
+        if pd = null then
+          dest.front       := new Queue_Element;
+          dest.front.value := s.value;
+          s                := s.next;
+          pd               := dest.front;
+        end if;
+        while s /= null loop
+          pd.next       := new Queue_Element;
+          pd.next.value := s.value;
+          pd            := pd.next;
+          s             := s.next;
+        end loop;
+        dest.back := pd;
+      end if;
+      dest.sz := src.sz;
+    end if;
+  end;
+
+end Opt68;
diff --git a/gcc/testsuite/gnat.dg/opt68.ads b/gcc/testsuite/gnat.dg/opt68.ads
new file mode 100644 (file)
index 0000000..25e28a5
--- /dev/null
@@ -0,0 +1,26 @@
+with Ada.Finalization;
+
+package Opt68 is
+
+  type Cont is new Ada.Finalization.Controlled with null record;
+
+  type Element is record
+    C : Cont;
+  end record;
+
+  type Queue_Element;
+  type A_Queue_Element is access Queue_Element;
+  type Queue_Element is record
+    Value : Element;
+    Next  : A_Queue_Element;
+  end record;
+
+  type Queue is limited record
+    Sz    : Natural;
+    Front : A_Queue_Element;
+    Back  : A_Queue_Element;
+  end record;
+
+  procedure Copy (dest : in out Queue; src : Queue);
+
+end Opt68;