Model decoder of Core 2/i7 for multipass scheduling.
authorMaxim Kuvyrkov <maxim@codesourcery.com>
Tue, 2 Nov 2010 16:02:09 +0000 (16:02 +0000)
committerMaxim Kuvyrkov <mkuvyrkov@gcc.gnu.org>
Tue, 2 Nov 2010 16:02:09 +0000 (16:02 +0000)
* config/i386/i386-protos.h (struct ix86_first_cycle_multipass_data_):
New type to hold target-specific data for multipass scheduling.
(TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DATA_T): Define.
* config/i386/i386.c (ia32_multipass_dfa_lookahead): Update for
Core 2/i7.
(core2i7_secondary_decoder_max_insn_size,)
(core2i7_secondary_ifetch_block_size, core2i7_ifetch_block_max_insns):
New static variables.
([const_]ix86_first_cycle_multipass_data_t): New typedefs.
([_]ix86_first_cycle_multipass_data): New static variable.
(core2i7_first_cycle_multipass_init, core2i7_dfa_poast_advance_cycle):
Implement targetm.sched hooks.
(core2i7_first_cycle_multipass_filter_ready_try): New static subroutine
of ...
(core2i7_first_cycle_multipass_{begin, issue, backtrack, end, fini}):
Implement new targetm.sched hooks.
(ix86_sched_init_global, TARGET_SCHED_INIT_GLOBAL): Define
targetm.sched hook to install multipass scheduling hooks on demand.

* doc/tm.texi.in: Document new targetm.sched hooks.
* doc/tm.texi: Regenerate.

* haifa-sched.c (TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DATA_T): Define.
(first_cycle_multipass_data_t): New typedef.
(struct choice_entry: target_data): New field.
(max_issue): Add first_cycle_insn_p parameter.  Call new target hooks
to allow target model restrictions not represented in DFA.
(choose_ready, schedule_block): Update.
(sched_extend_ready_list, sched_finish_ready_list): Call new target
hooks to initialize target-specific data for multipass scheduling.
* sched-int.h (max_issue): Update declaration.
* sel-sched.c (choose_best_insn): Update.
* target.def (first_cycle_multipass_{begin, issue, backtrack},)
(first_cycle_multipass_{init, fini}): Define and document new
targetm.sched hooks.

From-SVN: r166196

gcc/ChangeLog
gcc/config/i386/i386-protos.h
gcc/config/i386/i386.c
gcc/doc/tm.texi
gcc/doc/tm.texi.in
gcc/haifa-sched.c
gcc/sched-int.h
gcc/sel-sched.c
gcc/target.def

index b5d15ce51b620b24cfe030e4458cb019a95910dc..7f58b923164e4d51202354ddbbb7c63c8d6aa67b 100644 (file)
@@ -1,3 +1,43 @@
+2010-11-02  Maxim Kuvyrkov  <maxim@codesourcery.com>
+
+       Model decoder of Core 2/i7 for multipass scheduling.
+
+       * config/i386/i386-protos.h (struct ix86_first_cycle_multipass_data_):
+       New type to hold target-specific data for multipass scheduling.
+       (TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DATA_T): Define.
+       * config/i386/i386.c (ia32_multipass_dfa_lookahead): Update for
+       Core 2/i7.
+       (core2i7_secondary_decoder_max_insn_size,)
+       (core2i7_secondary_ifetch_block_size, core2i7_ifetch_block_max_insns):
+       New static variables.
+       ([const_]ix86_first_cycle_multipass_data_t): New typedefs.
+       ([_]ix86_first_cycle_multipass_data): New static variable.
+       (core2i7_first_cycle_multipass_init, core2i7_dfa_poast_advance_cycle):
+       Implement targetm.sched hooks.
+       (core2i7_first_cycle_multipass_filter_ready_try): New static subroutine
+       of ...
+       (core2i7_first_cycle_multipass_{begin, issue, backtrack, end, fini}):
+       Implement new targetm.sched hooks.
+       (ix86_sched_init_global, TARGET_SCHED_INIT_GLOBAL): Define
+       targetm.sched hook to install multipass scheduling hooks on demand.
+
+       * doc/tm.texi.in: Document new targetm.sched hooks.
+       * doc/tm.texi: Regenerate.
+
+       * haifa-sched.c (TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DATA_T): Define.
+       (first_cycle_multipass_data_t): New typedef.
+       (struct choice_entry: target_data): New field.
+       (max_issue): Add first_cycle_insn_p parameter.  Call new target hooks
+       to allow target model restrictions not represented in DFA.
+       (choose_ready, schedule_block): Update.
+       (sched_extend_ready_list, sched_finish_ready_list): Call new target
+       hooks to initialize target-specific data for multipass scheduling.
+       * sched-int.h (max_issue): Update declaration.
+       * sel-sched.c (choose_best_insn): Update.
+       * target.def (first_cycle_multipass_{begin, issue, backtrack},)
+       (first_cycle_multipass_{init, fini}): Define and document new
+       targetm.sched hooks.
+
 2010-11-02  Richard Guenther  <rguenther@suse.de>
 
        PR tree-optimization/46184
index f6f9071395f7d0ca23c34e9ccc537d8b7bce3e03..13b1394b4252d7e703a092ef124a2029e3af7ae1 100644 (file)
@@ -271,3 +271,21 @@ extern enum attr_cpu ix86_schedule;
 #endif
 
 extern const char * ix86_output_call_insn (rtx insn, rtx call_op, int addr_op);
+
+#ifdef RTX_CODE
+/* Target data for multipass lookahead scheduling.
+   Currently used for Core 2/i7 tuning.  */
+struct ix86_first_cycle_multipass_data_
+{
+  /* The length (in bytes) of ifetch block in this solution.  */
+  int ifetch_block_len;
+  /* Number of instructions in ifetch block in this solution.  */
+  int ifetch_block_n_insns;
+  /* Bitmap to remember changes to ready_try for backtracking.  */
+  sbitmap ready_try_change;
+  /* Size of the bitmap.  */
+  int ready_try_change_size;
+};
+# define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DATA_T     \
+  struct ix86_first_cycle_multipass_data_
+#endif /* RTX_CODE */
index eb3e623925db9e1716f3a82c07d47b5660dd8c88..bda8ed3f9cd5abc4fb51c80cab68c04afcd85c8d 100644 (file)
@@ -22273,11 +22273,264 @@ ia32_multipass_dfa_lookahead (void)
     case PROCESSOR_K6:
       return 1;
 
+    case PROCESSOR_CORE2:
+    case PROCESSOR_COREI7_32:
+    case PROCESSOR_COREI7_64:
+      /* Generally, we want haifa-sched:max_issue() to look ahead as far
+        as many instructions can be executed on a cycle, i.e.,
+        issue_rate.  I wonder why tuning for many CPUs does not do this.  */
+      return ix86_issue_rate ();
+
     default:
       return 0;
     }
 }
 
+\f
+
+/* Model decoder of Core 2/i7.
+   Below hooks for multipass scheduling (see haifa-sched.c:max_issue)
+   track the instruction fetch block boundaries and make sure that long
+   (9+ bytes) instructions are assigned to D0.  */
+
+/* Maximum length of an insn that can be handled by
+   a secondary decoder unit.  '8' for Core 2/i7.  */
+static int core2i7_secondary_decoder_max_insn_size;
+
+/* Ifetch block size, i.e., number of bytes decoder reads per cycle.
+   '16' for Core 2/i7.  */
+static int core2i7_ifetch_block_size;
+
+/* Maximum number of instructions decoder can handle per cycle.
+   '6' for Core 2/i7.  */
+static int core2i7_ifetch_block_max_insns;
+
+typedef struct ix86_first_cycle_multipass_data_ *
+  ix86_first_cycle_multipass_data_t;
+typedef const struct ix86_first_cycle_multipass_data_ *
+  const_ix86_first_cycle_multipass_data_t;
+
+/* A variable to store target state across calls to max_issue within
+   one cycle.  */
+static struct ix86_first_cycle_multipass_data_ _ix86_first_cycle_multipass_data,
+  *ix86_first_cycle_multipass_data = &_ix86_first_cycle_multipass_data;
+
+/* Initialize DATA.  */
+static void
+core2i7_first_cycle_multipass_init (void *_data)
+{
+  ix86_first_cycle_multipass_data_t data
+    = (ix86_first_cycle_multipass_data_t) _data;
+
+  data->ifetch_block_len = 0;
+  data->ifetch_block_n_insns = 0;
+  data->ready_try_change = NULL;
+  data->ready_try_change_size = 0;
+}
+
+/* Advancing the cycle; reset ifetch block counts.  */
+static void
+core2i7_dfa_post_advance_cycle (void)
+{
+  ix86_first_cycle_multipass_data_t data = ix86_first_cycle_multipass_data;
+
+  gcc_assert (data->ifetch_block_n_insns <= core2i7_ifetch_block_max_insns);
+
+  data->ifetch_block_len = 0;
+  data->ifetch_block_n_insns = 0;
+}
+
+static int min_insn_size (rtx);
+
+/* Filter out insns from ready_try that the core will not be able to issue
+   on current cycle due to decoder.  */
+static void
+core2i7_first_cycle_multipass_filter_ready_try
+(const_ix86_first_cycle_multipass_data_t data,
+ char *ready_try, int n_ready, bool first_cycle_insn_p)
+{
+  while (n_ready--)
+    {
+      rtx insn;
+      int insn_size;
+
+      if (ready_try[n_ready])
+       continue;
+
+      insn = get_ready_element (n_ready);
+      insn_size = min_insn_size (insn);
+
+      if (/* If this is a too long an insn for a secondary decoder ...  */
+         (!first_cycle_insn_p
+          && insn_size > core2i7_secondary_decoder_max_insn_size)
+         /* ... or it would not fit into the ifetch block ...  */
+         || data->ifetch_block_len + insn_size > core2i7_ifetch_block_size
+         /* ... or the decoder is full already ...  */
+         || data->ifetch_block_n_insns + 1 > core2i7_ifetch_block_max_insns)
+       /* ... mask the insn out.  */
+       {
+         ready_try[n_ready] = 1;
+
+         if (data->ready_try_change)
+           SET_BIT (data->ready_try_change, n_ready);
+       }
+    }
+}
+
+/* Prepare for a new round of multipass lookahead scheduling.  */
+static void
+core2i7_first_cycle_multipass_begin (void *_data, char *ready_try, int n_ready,
+                                    bool first_cycle_insn_p)
+{
+  ix86_first_cycle_multipass_data_t data
+    = (ix86_first_cycle_multipass_data_t) _data;
+  const_ix86_first_cycle_multipass_data_t prev_data
+    = ix86_first_cycle_multipass_data;
+
+  /* Restore the state from the end of the previous round.  */
+  data->ifetch_block_len = prev_data->ifetch_block_len;
+  data->ifetch_block_n_insns = prev_data->ifetch_block_n_insns;
+
+  /* Filter instructions that cannot be issued on current cycle due to
+     decoder restrictions.  */
+  core2i7_first_cycle_multipass_filter_ready_try (data, ready_try, n_ready,
+                                                 first_cycle_insn_p);
+}
+
+/* INSN is being issued in current solution.  Account for its impact on
+   the decoder model.  */
+static void
+core2i7_first_cycle_multipass_issue (void *_data, char *ready_try, int n_ready,
+                                    rtx insn, const void *_prev_data)
+{
+  ix86_first_cycle_multipass_data_t data
+    = (ix86_first_cycle_multipass_data_t) _data;
+  const_ix86_first_cycle_multipass_data_t prev_data
+    = (const_ix86_first_cycle_multipass_data_t) _prev_data;
+
+  int insn_size = min_insn_size (insn);
+
+  data->ifetch_block_len = prev_data->ifetch_block_len + insn_size;
+  data->ifetch_block_n_insns = prev_data->ifetch_block_n_insns + 1;
+  gcc_assert (data->ifetch_block_len <= core2i7_ifetch_block_size
+             && data->ifetch_block_n_insns <= core2i7_ifetch_block_max_insns);
+
+  /* Allocate or resize the bitmap for storing INSN's effect on ready_try.  */
+  if (!data->ready_try_change)
+    {
+      data->ready_try_change = sbitmap_alloc (n_ready);
+      data->ready_try_change_size = n_ready;
+    }
+  else if (data->ready_try_change_size < n_ready)
+    {
+      data->ready_try_change = sbitmap_resize (data->ready_try_change,
+                                              n_ready, 0);
+      data->ready_try_change_size = n_ready;
+    }
+  sbitmap_zero (data->ready_try_change);
+
+  /* Filter out insns from ready_try that the core will not be able to issue
+     on current cycle due to decoder.  */
+  core2i7_first_cycle_multipass_filter_ready_try (data, ready_try, n_ready,
+                                                 false);
+}
+
+/* Revert the effect on ready_try.  */
+static void
+core2i7_first_cycle_multipass_backtrack (const void *_data,
+                                        char *ready_try,
+                                        int n_ready ATTRIBUTE_UNUSED)
+{
+  const_ix86_first_cycle_multipass_data_t data
+    = (const_ix86_first_cycle_multipass_data_t) _data;
+  unsigned int i = 0;
+  sbitmap_iterator sbi;
+
+  gcc_assert (sbitmap_last_set_bit (data->ready_try_change) < n_ready);
+  EXECUTE_IF_SET_IN_SBITMAP (data->ready_try_change, 0, i, sbi)
+    {
+      ready_try[i] = 0;
+    }
+}
+
+/* Save the result of multipass lookahead scheduling for the next round.  */
+static void
+core2i7_first_cycle_multipass_end (const void *_data)
+{
+  const_ix86_first_cycle_multipass_data_t data
+    = (const_ix86_first_cycle_multipass_data_t) _data;
+  ix86_first_cycle_multipass_data_t next_data
+    = ix86_first_cycle_multipass_data;
+
+  if (data != NULL)
+    {
+      next_data->ifetch_block_len = data->ifetch_block_len;
+      next_data->ifetch_block_n_insns = data->ifetch_block_n_insns;
+    }
+}
+
+/* Deallocate target data.  */
+static void
+core2i7_first_cycle_multipass_fini (void *_data)
+{
+  ix86_first_cycle_multipass_data_t data
+    = (ix86_first_cycle_multipass_data_t) _data;
+
+  if (data->ready_try_change)
+    {
+      sbitmap_free (data->ready_try_change);
+      data->ready_try_change = NULL;
+      data->ready_try_change_size = 0;
+    }
+}
+
+/* Prepare for scheduling pass.  */
+static void
+ix86_sched_init_global (FILE *dump ATTRIBUTE_UNUSED,
+                       int verbose ATTRIBUTE_UNUSED,
+                       int max_uid ATTRIBUTE_UNUSED)
+{
+  /* Install scheduling hooks for current CPU.  Some of these hooks are used
+     in time-critical parts of the scheduler, so we only set them up when
+     they are actually used.  */
+  switch (ix86_tune)
+    {
+    case PROCESSOR_CORE2:
+    case PROCESSOR_COREI7_32:
+    case PROCESSOR_COREI7_64:
+      targetm.sched.dfa_post_advance_cycle
+       = core2i7_dfa_post_advance_cycle;
+      targetm.sched.first_cycle_multipass_init
+       = core2i7_first_cycle_multipass_init;
+      targetm.sched.first_cycle_multipass_begin
+       = core2i7_first_cycle_multipass_begin;
+      targetm.sched.first_cycle_multipass_issue
+       = core2i7_first_cycle_multipass_issue;
+      targetm.sched.first_cycle_multipass_backtrack
+       = core2i7_first_cycle_multipass_backtrack;
+      targetm.sched.first_cycle_multipass_end
+       = core2i7_first_cycle_multipass_end;
+      targetm.sched.first_cycle_multipass_fini
+       = core2i7_first_cycle_multipass_fini;
+
+      /* Set decoder parameters.  */
+      core2i7_secondary_decoder_max_insn_size = 8;
+      core2i7_ifetch_block_size = 16;
+      core2i7_ifetch_block_max_insns = 6;
+      break;
+
+    default:
+      targetm.sched.dfa_post_advance_cycle = NULL;
+      targetm.sched.first_cycle_multipass_init = NULL;
+      targetm.sched.first_cycle_multipass_begin = NULL;
+      targetm.sched.first_cycle_multipass_issue = NULL;
+      targetm.sched.first_cycle_multipass_backtrack = NULL;
+      targetm.sched.first_cycle_multipass_end = NULL;
+      targetm.sched.first_cycle_multipass_fini = NULL;
+      break;
+    }
+}
+
 \f
 /* Compute the alignment given to a constant that is being placed in memory.
    EXP is the constant and ALIGN is the alignment that the object would
@@ -34030,6 +34283,8 @@ ix86_autovectorize_vector_sizes (void)
 #undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA
 #define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA i386_asm_output_addr_const_extra 
 
+#undef TARGET_SCHED_INIT_GLOBAL
+#define TARGET_SCHED_INIT_GLOBAL ix86_sched_init_global
 #undef TARGET_SCHED_ADJUST_COST
 #define TARGET_SCHED_ADJUST_COST ix86_adjust_cost
 #undef TARGET_SCHED_ISSUE_RATE
index 9126d437aceea28984c6d9b41b7a447ee6dc60a9..7ce1c50f434eeecc681ca3e8246c677e3b60af87 100644 (file)
@@ -6654,6 +6654,33 @@ be issued.
 The default is that any ready insns can be chosen to be issued.
 @end deftypefn
 
+@deftypefn {Target Hook} void TARGET_SCHED_FIRST_CYCLE_MULTIPASS_BEGIN (void *@var{data}, char *@var{ready_try}, int @var{n_ready}, bool @var{first_cycle_insn_p})
+This hook prepares the target backend for a new round of multipass
+scheduling.
+@end deftypefn
+
+@deftypefn {Target Hook} void TARGET_SCHED_FIRST_CYCLE_MULTIPASS_ISSUE (void *@var{data}, char *@var{ready_try}, int @var{n_ready}, rtx @var{insn}, const void *@var{prev_data})
+This hook is called when multipass scheduling evaluates instruction INSN.
+@end deftypefn
+
+@deftypefn {Target Hook} void TARGET_SCHED_FIRST_CYCLE_MULTIPASS_BACKTRACK (const void *@var{data}, char *@var{ready_try}, int @var{n_ready})
+This is called when multipass scheduling backtracks from evaluation of
+an instruction.
+@end deftypefn
+
+@deftypefn {Target Hook} void TARGET_SCHED_FIRST_CYCLE_MULTIPASS_END (const void *@var{data})
+This hook notifies the target about the result of the concluded current
+round of multipass scheduling.
+@end deftypefn
+
+@deftypefn {Target Hook} void TARGET_SCHED_FIRST_CYCLE_MULTIPASS_INIT (void *@var{data})
+This hook initilizes target-specific data used in multipass scheduling.
+@end deftypefn
+
+@deftypefn {Target Hook} void TARGET_SCHED_FIRST_CYCLE_MULTIPASS_FINI (void *@var{data})
+This hook finilizes target-specific data used in multipass scheduling.
+@end deftypefn
+
 @deftypefn {Target Hook} int TARGET_SCHED_DFA_NEW_CYCLE (FILE *@var{dump}, int @var{verbose}, rtx @var{insn}, int @var{last_clock}, int @var{clock}, int *@var{sort_p})
 This hook is called by the insn scheduler before issuing @var{insn}
 on cycle @var{clock}.  If the hook returns nonzero,
index 2c36a7659068fc88bb1c882fc8f9de6a9df08e9a..23b38d3337f1d30d968c7280bb1d491da5249bc8 100644 (file)
@@ -6642,6 +6642,33 @@ be issued.
 The default is that any ready insns can be chosen to be issued.
 @end deftypefn
 
+@hook TARGET_SCHED_FIRST_CYCLE_MULTIPASS_BEGIN
+This hook prepares the target backend for a new round of multipass
+scheduling.
+@end deftypefn
+
+@hook TARGET_SCHED_FIRST_CYCLE_MULTIPASS_ISSUE
+This hook is called when multipass scheduling evaluates instruction INSN.
+@end deftypefn
+
+@hook TARGET_SCHED_FIRST_CYCLE_MULTIPASS_BACKTRACK
+This is called when multipass scheduling backtracks from evaluation of
+an instruction.
+@end deftypefn
+
+@hook TARGET_SCHED_FIRST_CYCLE_MULTIPASS_END
+This hook notifies the target about the result of the concluded current
+round of multipass scheduling.
+@end deftypefn
+
+@hook TARGET_SCHED_FIRST_CYCLE_MULTIPASS_INIT
+This hook initilizes target-specific data used in multipass scheduling.
+@end deftypefn
+
+@hook TARGET_SCHED_FIRST_CYCLE_MULTIPASS_FINI
+This hook finilizes target-specific data used in multipass scheduling.
+@end deftypefn
+
 @hook TARGET_SCHED_DFA_NEW_CYCLE
 This hook is called by the insn scheduler before issuing @var{insn}
 on cycle @var{clock}.  If the hook returns nonzero,
index 8fb988e2a628eda32be040436e53eb6f2674a4c2..434b760d07d59c140e7417599bde4ad4127a4dfc 100644 (file)
@@ -540,8 +540,6 @@ static void debug_ready_list (struct ready_list *);
 static rtx ready_remove (struct ready_list *, int);
 static void ready_remove_insn (rtx);
 
-static int choose_ready (struct ready_list *, rtx *);
-
 static void fix_inter_tick (rtx, rtx);
 static int fix_tick_ready (rtx);
 static void change_queue_index (rtx, int);
@@ -2390,6 +2388,12 @@ insn_finishes_cycle_p (rtx insn)
   return false;
 }
 
+/* Define type for target data used in multipass scheduling.  */
+#ifndef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DATA_T
+# define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DATA_T int
+#endif
+typedef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DATA_T first_cycle_multipass_data_t;
+
 /* The following structure describe an entry of the stack of choices.  */
 struct choice_entry
 {
@@ -2401,6 +2405,8 @@ struct choice_entry
   int n;
   /* State after issuing the insn.  */
   state_t state;
+  /* Target-specific data.  */
+  first_cycle_multipass_data_t target_data;
 };
 
 /* The following array is used to implement a stack of choices used in
@@ -2451,7 +2457,7 @@ static int cached_issue_rate = 0;
    CLOBBERs, etc must be filtered elsewhere.  */
 int
 max_issue (struct ready_list *ready, int privileged_n, state_t state,
-          int *index)
+          bool first_cycle_insn_p, int *index)
 {
   int n, i, all, n_ready, best, delay, tries_num;
   int more_issue;
@@ -2484,6 +2490,10 @@ max_issue (struct ready_list *ready, int privileged_n, state_t state,
   memcpy (top->state, state, dfa_state_size);
   top->rest = dfa_lookahead;
   top->n = 0;
+  if (targetm.sched.first_cycle_multipass_begin)
+    targetm.sched.first_cycle_multipass_begin (&top->target_data,
+                                              ready_try, n_ready,
+                                              first_cycle_insn_p);
 
   /* Count the number of the insns to search among.  */
   for (all = i = 0; i < n_ready; i++)
@@ -2542,6 +2552,11 @@ max_issue (struct ready_list *ready, int privileged_n, state_t state,
 
          /* Backtrack.  */
          ready_try [i] = 0;
+
+         if (targetm.sched.first_cycle_multipass_backtrack)
+           targetm.sched.first_cycle_multipass_backtrack (&top->target_data,
+                                                          ready_try, n_ready);
+
          top--;
          memcpy (state, top->state, dfa_state_size);
        }
@@ -2573,8 +2588,15 @@ max_issue (struct ready_list *ready, int privileged_n, state_t state,
              top->index = i;
              top->n = n;
              memcpy (top->state, state, dfa_state_size);
-
              ready_try [i] = 1;
+
+             if (targetm.sched.first_cycle_multipass_issue)
+               targetm.sched.first_cycle_multipass_issue (&top->target_data,
+                                                          ready_try, n_ready,
+                                                          insn,
+                                                          &((top - 1)
+                                                            ->target_data));
+
              i = -1;
            }
        }
@@ -2583,6 +2605,11 @@ max_issue (struct ready_list *ready, int privileged_n, state_t state,
       i++;
     }
 
+  if (targetm.sched.first_cycle_multipass_end)
+    targetm.sched.first_cycle_multipass_end (best != 0
+                                            ? &choice_stack[1].target_data
+                                            : NULL);
+
   /* Restore the original state of the DFA.  */
   memcpy (state, choice_stack->state, dfa_state_size);
 
@@ -2597,7 +2624,8 @@ max_issue (struct ready_list *ready, int privileged_n, state_t state,
    0 if INSN_PTR is set to point to the desirable insn,
    1 if choose_ready () should be restarted without advancing the cycle.  */
 static int
-choose_ready (struct ready_list *ready, rtx *insn_ptr)
+choose_ready (struct ready_list *ready, bool first_cycle_insn_p,
+             rtx *insn_ptr)
 {
   int lookahead;
 
@@ -2726,7 +2754,7 @@ choose_ready (struct ready_list *ready, rtx *insn_ptr)
                     (insn)));
          }
 
-      if (max_issue (ready, 1, curr_state, &index) == 0)
+      if (max_issue (ready, 1, curr_state, first_cycle_insn_p, &index) == 0)
        {
          *insn_ptr = ready_remove_first (ready);
          if (sched_verbose >= 4)
@@ -2754,7 +2782,8 @@ choose_ready (struct ready_list *ready, rtx *insn_ptr)
 void
 schedule_block (basic_block *target_bb)
 {
-  int i, first_cycle_insn_p;
+  int i;
+  bool first_cycle_insn_p;
   int can_issue_more;
   state_t temp_state = NULL;  /* It is used for multipass scheduling.  */
   int sort_p, advance, start_clock_var;
@@ -2960,7 +2989,7 @@ schedule_block (basic_block *target_bb)
       else
        can_issue_more = issue_rate;
 
-      first_cycle_insn_p = 1;
+      first_cycle_insn_p = true;
       cycle_issued_insns = 0;
       for (;;)
        {
@@ -3003,7 +3032,7 @@ schedule_block (basic_block *target_bb)
              int res;
 
              insn = NULL_RTX;
-             res = choose_ready (&ready, &insn);
+             res = choose_ready (&ready, first_cycle_insn_p, &insn);
 
              if (res < 0)
                /* Finish cycle.  */
@@ -3156,7 +3185,7 @@ schedule_block (basic_block *target_bb)
          if (advance != 0)
            break;
 
-         first_cycle_insn_p = 0;
+         first_cycle_insn_p = false;
 
          /* Sort the ready list based on priority.  This must be
             redone here, as schedule_insn may have readied additional
@@ -3952,7 +3981,13 @@ sched_extend_ready_list (int new_sched_ready_n_insns)
                             new_sched_ready_n_insns + 1);
 
   for (; i <= new_sched_ready_n_insns; i++)
-    choice_stack[i].state = xmalloc (dfa_state_size);
+    {
+      choice_stack[i].state = xmalloc (dfa_state_size);
+
+      if (targetm.sched.first_cycle_multipass_init)
+       targetm.sched.first_cycle_multipass_init (&(choice_stack[i]
+                                                   .target_data));
+    }
 
   sched_ready_n_insns = new_sched_ready_n_insns;
 }
@@ -3971,7 +4006,13 @@ sched_finish_ready_list (void)
   ready_try = NULL;
 
   for (i = 0; i <= sched_ready_n_insns; i++)
-    free (choice_stack [i].state);
+    {
+      if (targetm.sched.first_cycle_multipass_fini)
+       targetm.sched.first_cycle_multipass_fini (&(choice_stack[i]
+                                                   .target_data));
+
+      free (choice_stack [i].state);
+    }
   free (choice_stack);
   choice_stack = NULL;
 
index bea5aab5800ed2c39408f92c529785fc25fa80c3..68cfa23ee06af3036b944e50f4e357da5d711f3c 100644 (file)
@@ -195,7 +195,7 @@ struct ready_list
 extern char *ready_try;
 extern struct ready_list ready;
 
-extern int max_issue (struct ready_list *, int, state_t, int *);
+extern int max_issue (struct ready_list *, int, state_t, bool, int *);
 
 extern void ebb_compute_jump_reg_dependencies (rtx, regset, regset, regset);
 
index ce014ed7f556c7e99428fb35699dd0eee7145474..70e831d7cee4d35958e43923bec2c18d4480d936 100644 (file)
@@ -4320,8 +4320,9 @@ choose_best_insn (fence_t fence, int privileged_n, int *index)
   if (dfa_lookahead > 0)
     {
       cycle_issued_insns = FENCE_ISSUED_INSNS (fence);
+      /* TODO: pass equivalent of first_cycle_insn_p to max_issue ().  */
       can_issue = max_issue (&ready, privileged_n,
-                             FENCE_STATE (fence), index);
+                             FENCE_STATE (fence), true, index);
       if (sched_verbose >= 2)
         sel_print ("max_issue: we can issue %d insns, already did %d insns\n",
                    can_issue, FENCE_ISSUED_INSNS (fence));
index 98cea58c40ddc4514125cf13eddccc690f99bdaf..37ba3bc620e8c3ae39e6b161364b2d831323ac0c 100644 (file)
@@ -650,6 +650,84 @@ DEFHOOK
  "",
  int, (rtx insn), NULL)
 
+/* This hook prepares the target for a new round of multipass
+   scheduling.
+   DATA is a pointer to target-specific data used for multipass scheduling.
+   READY_TRY and N_READY represent the current state of search in the
+   optimization space.  The target can filter out instructions that
+   should not be tried during current round by setting corresponding
+   elements in READY_TRY to non-zero.
+   FIRST_CYCLE_INSN_P is true if this is the first round of multipass
+   scheduling on current cycle.  */
+DEFHOOK
+(first_cycle_multipass_begin,
+ "",
+ void, (void *data, char *ready_try, int n_ready, bool first_cycle_insn_p),
+ NULL)
+
+/* This hook is called when multipass scheduling evaluates instruction INSN.
+   DATA is a pointer to target-specific data that can be used to record effects
+   of INSN on CPU that are not described in DFA.
+   READY_TRY and N_READY represent the current state of search in the
+   optimization space.  The target can filter out instructions that
+   should not be tried after issueing INSN by setting corresponding
+   elements in READY_TRY to non-zero.
+   INSN is the instruction being evaluated.
+   PREV_DATA is a pointer to target-specific data corresponding
+   to a state before issueing INSN.  */
+DEFHOOK
+(first_cycle_multipass_issue,
+ "",
+ void, (void *data, char *ready_try, int n_ready, rtx insn,
+       const void *prev_data), NULL)
+
+/* This hook is called when multipass scheduling backtracks from evaluation of
+   instruction corresponding to DATA.
+   DATA is a pointer to target-specific data that stores the effects
+   of instruction from which the algorithm backtracks on CPU that are not
+   described in DFA.
+   READY_TRY and N_READY represent the current state of search in the
+   optimization space.  The target can filter out instructions that
+   should not be tried after issueing INSN by setting corresponding
+   elements in READY_TRY to non-zero.  */
+DEFHOOK
+(first_cycle_multipass_backtrack,
+ "",
+ void, (const void *data, char *ready_try, int n_ready), NULL)
+
+/* This hook notifies the target about the result of the concluded current
+   round of multipass scheduling.
+   DATA is a pointer.
+   If DATA is non-NULL it points to target-specific data used for multipass
+   scheduling which corresponds to instruction at the start of the chain of
+   the winning solution.  DATA is NULL when multipass scheduling cannot find
+   a good enough solution on current cycle and decides to retry later,
+   usually after advancing the cycle count.  */
+DEFHOOK
+(first_cycle_multipass_end,
+ "",
+ void, (const void *data), NULL)
+
+/* This hook is called to initialize target-specific data for multipass
+   scheduling after it has been allocated.
+   DATA is a pointer to target-specific data that stores the effects
+   of instruction from which the algorithm backtracks on CPU that are not
+   described in DFA.  */
+DEFHOOK
+(first_cycle_multipass_init,
+ "",
+ void, (void *data), NULL)
+
+/* This hook is called to finalize target-specific data for multipass
+   scheduling before it is deallocated.
+   DATA is a pointer to target-specific data that stores the effects
+   of instruction from which the algorithm backtracks on CPU that are not
+   described in DFA.  */
+DEFHOOK
+(first_cycle_multipass_fini,
+ "",
+ void, (void *data), NULL)
+
 /* The following member value is pointer to a function called by
    the insn scheduler before issuing insn passed as the third
    parameter on given cycle.  If the hook returns nonzero, the