Cleanup autopref scheduling
authorWilco Dijkstra <wdijkstr@arm.com>
Tue, 24 Oct 2017 17:21:19 +0000 (17:21 +0000)
committerWilco Dijkstra <wilco@gcc.gnu.org>
Tue, 24 Oct 2017 17:21:19 +0000 (17:21 +0000)
r253236 broke AArch64 bootstrap. Earlier revision r253071 changed scheduling
behaviour on AArch64 as autopref scheduling no longer checks the base.

This patch fixes the bootstrap failure and cleans up autopref scheduling.
The code is greatly simplified.  Sort accesses on the offset first, and
only if the offsets are the same fall back to other comparisons in
rank_for_schedule.  This doesn't at all restore the original behaviour
since we no longer compare the base address, but it now defines a total
sorting order.  More work will be required to improve the sorting so
that only loads/stores with the same base are affected.

    gcc/
PR rtl-optimization/82396
* gcc/haifa-sched.c (ready_sort_real): Remove qsort workaround.
(autopref_multipass_init): Simplify initialization.
(autopref_rank_data): Simplify sort order.
* gcc/sched-int.h (autopref_multipass_data_): Remove
multi_mem_insn_p, min_offset and max_offset.

From-SVN: r254056

gcc/ChangeLog
gcc/haifa-sched.c
gcc/sched-int.h

index 259dc01714a825a6f132b9b16d8cafe0f9fa36c6..e0ef3edb9da2663cf7ab89fec5987d61288a1eb3 100644 (file)
@@ -1,3 +1,12 @@
+2017-10-24  Wilco Dijkstra  <wdijkstr@arm.com>
+
+       PR rtl-optimization/82396
+       * gcc/haifa-sched.c (ready_sort_real): Remove qsort workaround.
+       (autopref_multipass_init): Simplify initialization.
+       (autopref_rank_data): Simplify sort order.
+       * gcc/sched-int.h (autopref_multipass_data_): Remove
+       multi_mem_insn_p, min_offset and max_offset.
+
 2017-10-24  Wilco Dijkstra  <wdijkstr@arm.com>
 
        PR middle-end/60580
index 0c73003ebcaabd30e1f357518e89d9b30d4ceac3..4b906a34b8bb6aac4ba76404828b8fab19638ce1 100644 (file)
@@ -3084,8 +3084,7 @@ ready_sort_real (struct ready_list *ready)
   if (n_ready_real == 2)
     swap_sort (first, n_ready_real);
   else if (n_ready_real > 2)
-    /* HACK: Disable qsort checking for now (PR82396).  */
-    (qsort) (first, n_ready_real, sizeof (rtx), rank_for_schedule);
+    qsort (first, n_ready_real, sizeof (rtx), rank_for_schedule);
 
   if (sched_verbose >= 4)
     {
@@ -5569,9 +5568,7 @@ autopref_multipass_init (const rtx_insn *insn, int write)
 
   gcc_assert (data->status == AUTOPREF_MULTIPASS_DATA_UNINITIALIZED);
   data->base = NULL_RTX;
-  data->min_offset = 0;
-  data->max_offset = 0;
-  data->multi_mem_insn_p = false;
+  data->offset = 0;
   /* Set insn entry initialized, but not relevant for auto-prefetcher.  */
   data->status = AUTOPREF_MULTIPASS_DATA_IRRELEVANT;
 
@@ -5586,10 +5583,9 @@ autopref_multipass_init (const rtx_insn *insn, int write)
     {
       int n_elems = XVECLEN (pat, 0);
 
-      int i = 0;
-      rtx prev_base = NULL_RTX;
-      int min_offset = 0;
-      int max_offset = 0;
+      int i, offset;
+      rtx base, prev_base = NULL_RTX;
+      int min_offset = INT_MAX;
 
       for (i = 0; i < n_elems; i++)
        {
@@ -5597,38 +5593,23 @@ autopref_multipass_init (const rtx_insn *insn, int write)
          if (GET_CODE (set) != SET)
            return;
 
-         rtx base = NULL_RTX;
-         int offset = 0;
          if (!analyze_set_insn_for_autopref (set, write, &base, &offset))
            return;
 
-         if (i == 0)
-           {
-             prev_base = base;
-             min_offset = offset;
-             max_offset = offset;
-           }
          /* Ensure that all memory operations in the PARALLEL use the same
             base register.  */
-         else if (REGNO (base) != REGNO (prev_base))
+         if (i > 0 && REGNO (base) != REGNO (prev_base))
            return;
-         else
-           {
-             min_offset = MIN (min_offset, offset);
-             max_offset = MAX (max_offset, offset);
-           }
+         prev_base = base;
+         min_offset = MIN (min_offset, offset);
        }
 
-      /* If we reached here then we have a valid PARALLEL of multiple memory
-        ops with prev_base as the base and min_offset and max_offset
-        containing the offsets range.  */
+      /* If we reached here then we have a valid PARALLEL of multiple memory ops
+        with prev_base as the base and min_offset containing the offset.  */
       gcc_assert (prev_base);
       data->base = prev_base;
-      data->min_offset = min_offset;
-      data->max_offset = max_offset;
-      data->multi_mem_insn_p = true;
+      data->offset = min_offset;
       data->status = AUTOPREF_MULTIPASS_DATA_NORMAL;
-
       return;
     }
 
@@ -5638,7 +5619,7 @@ autopref_multipass_init (const rtx_insn *insn, int write)
     return;
 
   if (!analyze_set_insn_for_autopref (set, write, &data->base,
-                                      &data->min_offset))
+                                      &data->offset))
     return;
 
   /* This insn is relevant for the auto-prefetcher.
@@ -5647,63 +5628,6 @@ autopref_multipass_init (const rtx_insn *insn, int write)
   data->status = AUTOPREF_MULTIPASS_DATA_NORMAL;
 }
 
-
-/* Helper for autopref_rank_for_schedule.  Given the data of two
-   insns relevant to the auto-prefetcher modelling code DATA1 and DATA2
-   return their comparison result.  Return 0 if there is no sensible
-   ranking order for the two insns.  */
-
-static int
-autopref_rank_data (autopref_multipass_data_t data1,
-                    autopref_multipass_data_t data2)
-{
-  /* Simple case when both insns are simple single memory ops.  */
-  if (!data1->multi_mem_insn_p && !data2->multi_mem_insn_p)
-    return data1->min_offset - data2->min_offset;
-
-  /* Two load/store multiple insns.  Return 0 if the offset ranges
-     overlap and the difference between the minimum offsets otherwise.  */
-  else if (data1->multi_mem_insn_p && data2->multi_mem_insn_p)
-    {
-      int min1 = data1->min_offset;
-      int max1 = data1->max_offset;
-      int min2 = data2->min_offset;
-      int max2 = data2->max_offset;
-
-      if (max1 < min2 || min1 > max2)
-       return min1 - min2;
-      else
-       return 0;
-    }
-
-  /* The other two cases is a pair of a load/store multiple and
-     a simple memory op.  Return 0 if the single op's offset is within the
-     range of the multi-op insn and the difference between the single offset
-     and the minimum offset of the multi-set insn otherwise.  */
-  else if (data1->multi_mem_insn_p && !data2->multi_mem_insn_p)
-    {
-      int max1 = data1->max_offset;
-      int min1 = data1->min_offset;
-
-      if (data2->min_offset >= min1
-         && data2->min_offset <= max1)
-       return 0;
-      else
-       return min1 - data2->min_offset;
-    }
-  else
-    {
-      int max2 = data2->max_offset;
-      int min2 = data2->min_offset;
-
-      if (data1->min_offset >= min2
-         && data1->min_offset <= max2)
-       return 0;
-      else
-       return data1->min_offset - min2;
-    }
-}
-
 /* Helper function for rank_for_schedule sorting.  */
 static int
 autopref_rank_for_schedule (const rtx_insn *insn1, const rtx_insn *insn2)
@@ -5726,7 +5650,7 @@ autopref_rank_for_schedule (const rtx_insn *insn1, const rtx_insn *insn2)
       int irrel2 = data2->status == AUTOPREF_MULTIPASS_DATA_IRRELEVANT;
 
       if (!irrel1 && !irrel2)
-       r = autopref_rank_data (data1, data2);
+       r = data1->offset - data2->offset;
       else
        r = irrel2 - irrel1;
     }
@@ -5754,7 +5678,7 @@ autopref_multipass_dfa_lookahead_guard_1 (const rtx_insn *insn1,
     return 0;
 
   if (rtx_equal_p (data1->base, data2->base)
-      && autopref_rank_data (data1, data2) > 0)
+      && data1->offset > data2->offset)
     {
       if (sched_verbose >= 2)
        {
index 2af8f9fc32c0085c18511bbc83ad52c6ec31f671..6832589e3d0ad9ed5937ab3e81f3573c2560fe67 100644 (file)
@@ -819,15 +819,8 @@ struct autopref_multipass_data_
   /* Base part of memory address.  */
   rtx base;
 
-  /* Memory offsets from the base.  For single simple sets
-     only min_offset is valid.  For multi-set insns min_offset
-     and max_offset record the minimum and maximum offsets from the same
-     base among the sets inside the PARALLEL.  */
-  int min_offset;
-  int max_offset;
-
-  /* True if this is a load/store-multiple instruction.  */
-  bool multi_mem_insn_p;
+  /* Memory offsets from the base.  */
+  int offset;
 
   /* Entry status.  */
   enum autopref_multipass_data_status status;