xref: /dragonfly/contrib/gcc-4.7/gcc/haifa-sched.c (revision 5ce9237c)
1e4b17023SJohn Marino /* Instruction scheduling pass.
2e4b17023SJohn Marino    Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
3e4b17023SJohn Marino    2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
4e4b17023SJohn Marino    Free Software Foundation, Inc.
5e4b17023SJohn Marino    Contributed by Michael Tiemann (tiemann@cygnus.com) Enhanced by,
6e4b17023SJohn Marino    and currently maintained by, Jim Wilson (wilson@cygnus.com)
7e4b17023SJohn Marino 
8e4b17023SJohn Marino This file is part of GCC.
9e4b17023SJohn Marino 
10e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under
11e4b17023SJohn Marino the terms of the GNU General Public License as published by the Free
12e4b17023SJohn Marino Software Foundation; either version 3, or (at your option) any later
13e4b17023SJohn Marino version.
14e4b17023SJohn Marino 
15e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or
17e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
18e4b17023SJohn Marino for more details.
19e4b17023SJohn Marino 
20e4b17023SJohn Marino You should have received a copy of the GNU General Public License
21e4b17023SJohn Marino along with GCC; see the file COPYING3.  If not see
22e4b17023SJohn Marino <http://www.gnu.org/licenses/>.  */
23e4b17023SJohn Marino 
24e4b17023SJohn Marino /* Instruction scheduling pass.  This file, along with sched-deps.c,
25e4b17023SJohn Marino    contains the generic parts.  The actual entry point is found for
26e4b17023SJohn Marino    the normal instruction scheduling pass is found in sched-rgn.c.
27e4b17023SJohn Marino 
28e4b17023SJohn Marino    We compute insn priorities based on data dependencies.  Flow
29e4b17023SJohn Marino    analysis only creates a fraction of the data-dependencies we must
30e4b17023SJohn Marino    observe: namely, only those dependencies which the combiner can be
31e4b17023SJohn Marino    expected to use.  For this pass, we must therefore create the
32e4b17023SJohn Marino    remaining dependencies we need to observe: register dependencies,
33e4b17023SJohn Marino    memory dependencies, dependencies to keep function calls in order,
34e4b17023SJohn Marino    and the dependence between a conditional branch and the setting of
35e4b17023SJohn Marino    condition codes are all dealt with here.
36e4b17023SJohn Marino 
37e4b17023SJohn Marino    The scheduler first traverses the data flow graph, starting with
38e4b17023SJohn Marino    the last instruction, and proceeding to the first, assigning values
39e4b17023SJohn Marino    to insn_priority as it goes.  This sorts the instructions
40e4b17023SJohn Marino    topologically by data dependence.
41e4b17023SJohn Marino 
42e4b17023SJohn Marino    Once priorities have been established, we order the insns using
43e4b17023SJohn Marino    list scheduling.  This works as follows: starting with a list of
44e4b17023SJohn Marino    all the ready insns, and sorted according to priority number, we
45e4b17023SJohn Marino    schedule the insn from the end of the list by placing its
46e4b17023SJohn Marino    predecessors in the list according to their priority order.  We
47e4b17023SJohn Marino    consider this insn scheduled by setting the pointer to the "end" of
48e4b17023SJohn Marino    the list to point to the previous insn.  When an insn has no
49e4b17023SJohn Marino    predecessors, we either queue it until sufficient time has elapsed
50e4b17023SJohn Marino    or add it to the ready list.  As the instructions are scheduled or
51e4b17023SJohn Marino    when stalls are introduced, the queue advances and dumps insns into
52e4b17023SJohn Marino    the ready list.  When all insns down to the lowest priority have
53e4b17023SJohn Marino    been scheduled, the critical path of the basic block has been made
54e4b17023SJohn Marino    as short as possible.  The remaining insns are then scheduled in
55e4b17023SJohn Marino    remaining slots.
56e4b17023SJohn Marino 
57e4b17023SJohn Marino    The following list shows the order in which we want to break ties
58e4b17023SJohn Marino    among insns in the ready list:
59e4b17023SJohn Marino 
60e4b17023SJohn Marino    1.  choose insn with the longest path to end of bb, ties
61e4b17023SJohn Marino    broken by
62e4b17023SJohn Marino    2.  choose insn with least contribution to register pressure,
63e4b17023SJohn Marino    ties broken by
64e4b17023SJohn Marino    3.  prefer in-block upon interblock motion, ties broken by
65e4b17023SJohn Marino    4.  prefer useful upon speculative motion, ties broken by
66e4b17023SJohn Marino    5.  choose insn with largest control flow probability, ties
67e4b17023SJohn Marino    broken by
68e4b17023SJohn Marino    6.  choose insn with the least dependences upon the previously
69e4b17023SJohn Marino    scheduled insn, or finally
70e4b17023SJohn Marino    7   choose the insn which has the most insns dependent on it.
71e4b17023SJohn Marino    8.  choose insn with lowest UID.
72e4b17023SJohn Marino 
73e4b17023SJohn Marino    Memory references complicate matters.  Only if we can be certain
74e4b17023SJohn Marino    that memory references are not part of the data dependency graph
75e4b17023SJohn Marino    (via true, anti, or output dependence), can we move operations past
76e4b17023SJohn Marino    memory references.  To first approximation, reads can be done
77e4b17023SJohn Marino    independently, while writes introduce dependencies.  Better
78e4b17023SJohn Marino    approximations will yield fewer dependencies.
79e4b17023SJohn Marino 
80e4b17023SJohn Marino    Before reload, an extended analysis of interblock data dependences
81e4b17023SJohn Marino    is required for interblock scheduling.  This is performed in
82e4b17023SJohn Marino    compute_block_backward_dependences ().
83e4b17023SJohn Marino 
84e4b17023SJohn Marino    Dependencies set up by memory references are treated in exactly the
85e4b17023SJohn Marino    same way as other dependencies, by using insn backward dependences
86e4b17023SJohn Marino    INSN_BACK_DEPS.  INSN_BACK_DEPS are translated into forward dependences
87e4b17023SJohn Marino    INSN_FORW_DEPS the purpose of forward list scheduling.
88e4b17023SJohn Marino 
89e4b17023SJohn Marino    Having optimized the critical path, we may have also unduly
90e4b17023SJohn Marino    extended the lifetimes of some registers.  If an operation requires
91e4b17023SJohn Marino    that constants be loaded into registers, it is certainly desirable
92e4b17023SJohn Marino    to load those constants as early as necessary, but no earlier.
93e4b17023SJohn Marino    I.e., it will not do to load up a bunch of registers at the
94e4b17023SJohn Marino    beginning of a basic block only to use them at the end, if they
95e4b17023SJohn Marino    could be loaded later, since this may result in excessive register
96e4b17023SJohn Marino    utilization.
97e4b17023SJohn Marino 
98e4b17023SJohn Marino    Note that since branches are never in basic blocks, but only end
99e4b17023SJohn Marino    basic blocks, this pass will not move branches.  But that is ok,
100e4b17023SJohn Marino    since we can use GNU's delayed branch scheduling pass to take care
101e4b17023SJohn Marino    of this case.
102e4b17023SJohn Marino 
103e4b17023SJohn Marino    Also note that no further optimizations based on algebraic
104e4b17023SJohn Marino    identities are performed, so this pass would be a good one to
105e4b17023SJohn Marino    perform instruction splitting, such as breaking up a multiply
106e4b17023SJohn Marino    instruction into shifts and adds where that is profitable.
107e4b17023SJohn Marino 
108e4b17023SJohn Marino    Given the memory aliasing analysis that this pass should perform,
109e4b17023SJohn Marino    it should be possible to remove redundant stores to memory, and to
110e4b17023SJohn Marino    load values from registers instead of hitting memory.
111e4b17023SJohn Marino 
112e4b17023SJohn Marino    Before reload, speculative insns are moved only if a 'proof' exists
113e4b17023SJohn Marino    that no exception will be caused by this, and if no live registers
114e4b17023SJohn Marino    exist that inhibit the motion (live registers constraints are not
115e4b17023SJohn Marino    represented by data dependence edges).
116e4b17023SJohn Marino 
117e4b17023SJohn Marino    This pass must update information that subsequent passes expect to
118e4b17023SJohn Marino    be correct.  Namely: reg_n_refs, reg_n_sets, reg_n_deaths,
119e4b17023SJohn Marino    reg_n_calls_crossed, and reg_live_length.  Also, BB_HEAD, BB_END.
120e4b17023SJohn Marino 
121e4b17023SJohn Marino    The information in the line number notes is carefully retained by
122e4b17023SJohn Marino    this pass.  Notes that refer to the starting and ending of
123e4b17023SJohn Marino    exception regions are also carefully retained by this pass.  All
124e4b17023SJohn Marino    other NOTE insns are grouped in their same relative order at the
125e4b17023SJohn Marino    beginning of basic blocks and regions that have been scheduled.  */
126e4b17023SJohn Marino 
127e4b17023SJohn Marino #include "config.h"
128e4b17023SJohn Marino #include "system.h"
129e4b17023SJohn Marino #include "coretypes.h"
130e4b17023SJohn Marino #include "tm.h"
131e4b17023SJohn Marino #include "diagnostic-core.h"
132e4b17023SJohn Marino #include "hard-reg-set.h"
133e4b17023SJohn Marino #include "rtl.h"
134e4b17023SJohn Marino #include "tm_p.h"
135e4b17023SJohn Marino #include "regs.h"
136e4b17023SJohn Marino #include "function.h"
137e4b17023SJohn Marino #include "flags.h"
138e4b17023SJohn Marino #include "insn-config.h"
139e4b17023SJohn Marino #include "insn-attr.h"
140e4b17023SJohn Marino #include "except.h"
141e4b17023SJohn Marino #include "recog.h"
142e4b17023SJohn Marino #include "sched-int.h"
143e4b17023SJohn Marino #include "target.h"
144e4b17023SJohn Marino #include "common/common-target.h"
145e4b17023SJohn Marino #include "output.h"
146e4b17023SJohn Marino #include "params.h"
147e4b17023SJohn Marino #include "vecprim.h"
148e4b17023SJohn Marino #include "dbgcnt.h"
149e4b17023SJohn Marino #include "cfgloop.h"
150e4b17023SJohn Marino #include "ira.h"
151e4b17023SJohn Marino #include "emit-rtl.h"  /* FIXME: Can go away once crtl is moved to rtl.h.  */
152e4b17023SJohn Marino #include "hashtab.h"
153e4b17023SJohn Marino 
154e4b17023SJohn Marino #ifdef INSN_SCHEDULING
155e4b17023SJohn Marino 
156e4b17023SJohn Marino /* issue_rate is the number of insns that can be scheduled in the same
157e4b17023SJohn Marino    machine cycle.  It can be defined in the config/mach/mach.h file,
158e4b17023SJohn Marino    otherwise we set it to 1.  */
159e4b17023SJohn Marino 
160e4b17023SJohn Marino int issue_rate;
161e4b17023SJohn Marino 
162e4b17023SJohn Marino /* This can be set to true by a backend if the scheduler should not
163e4b17023SJohn Marino    enable a DCE pass.  */
164e4b17023SJohn Marino bool sched_no_dce;
165e4b17023SJohn Marino 
166e4b17023SJohn Marino /* The current initiation interval used when modulo scheduling.  */
167e4b17023SJohn Marino static int modulo_ii;
168e4b17023SJohn Marino 
169e4b17023SJohn Marino /* The maximum number of stages we are prepared to handle.  */
170e4b17023SJohn Marino static int modulo_max_stages;
171e4b17023SJohn Marino 
172e4b17023SJohn Marino /* The number of insns that exist in each iteration of the loop.  We use this
173e4b17023SJohn Marino    to detect when we've scheduled all insns from the first iteration.  */
174e4b17023SJohn Marino static int modulo_n_insns;
175e4b17023SJohn Marino 
176e4b17023SJohn Marino /* The current count of insns in the first iteration of the loop that have
177e4b17023SJohn Marino    already been scheduled.  */
178e4b17023SJohn Marino static int modulo_insns_scheduled;
179e4b17023SJohn Marino 
180e4b17023SJohn Marino /* The maximum uid of insns from the first iteration of the loop.  */
181e4b17023SJohn Marino static int modulo_iter0_max_uid;
182e4b17023SJohn Marino 
183e4b17023SJohn Marino /* The number of times we should attempt to backtrack when modulo scheduling.
184e4b17023SJohn Marino    Decreased each time we have to backtrack.  */
185e4b17023SJohn Marino static int modulo_backtracks_left;
186e4b17023SJohn Marino 
187e4b17023SJohn Marino /* The stage in which the last insn from the original loop was
188e4b17023SJohn Marino    scheduled.  */
189e4b17023SJohn Marino static int modulo_last_stage;
190e4b17023SJohn Marino 
191e4b17023SJohn Marino /* sched-verbose controls the amount of debugging output the
192e4b17023SJohn Marino    scheduler prints.  It is controlled by -fsched-verbose=N:
193e4b17023SJohn Marino    N>0 and no -DSR : the output is directed to stderr.
194e4b17023SJohn Marino    N>=10 will direct the printouts to stderr (regardless of -dSR).
195e4b17023SJohn Marino    N=1: same as -dSR.
196e4b17023SJohn Marino    N=2: bb's probabilities, detailed ready list info, unit/insn info.
197e4b17023SJohn Marino    N=3: rtl at abort point, control-flow, regions info.
198e4b17023SJohn Marino    N=5: dependences info.  */
199e4b17023SJohn Marino 
200e4b17023SJohn Marino int sched_verbose = 0;
201e4b17023SJohn Marino 
202e4b17023SJohn Marino /* Debugging file.  All printouts are sent to dump, which is always set,
203e4b17023SJohn Marino    either to stderr, or to the dump listing file (-dRS).  */
204e4b17023SJohn Marino FILE *sched_dump = 0;
205e4b17023SJohn Marino 
206e4b17023SJohn Marino /* This is a placeholder for the scheduler parameters common
207e4b17023SJohn Marino    to all schedulers.  */
208e4b17023SJohn Marino struct common_sched_info_def *common_sched_info;
209e4b17023SJohn Marino 
210e4b17023SJohn Marino #define INSN_TICK(INSN)	(HID (INSN)->tick)
211e4b17023SJohn Marino #define INSN_EXACT_TICK(INSN) (HID (INSN)->exact_tick)
212e4b17023SJohn Marino #define INSN_TICK_ESTIMATE(INSN) (HID (INSN)->tick_estimate)
213e4b17023SJohn Marino #define INTER_TICK(INSN) (HID (INSN)->inter_tick)
214e4b17023SJohn Marino #define FEEDS_BACKTRACK_INSN(INSN) (HID (INSN)->feeds_backtrack_insn)
215e4b17023SJohn Marino #define SHADOW_P(INSN) (HID (INSN)->shadow_p)
216e4b17023SJohn Marino #define MUST_RECOMPUTE_SPEC_P(INSN) (HID (INSN)->must_recompute_spec)
217e4b17023SJohn Marino 
218e4b17023SJohn Marino /* If INSN_TICK of an instruction is equal to INVALID_TICK,
219e4b17023SJohn Marino    then it should be recalculated from scratch.  */
220e4b17023SJohn Marino #define INVALID_TICK (-(max_insn_queue_index + 1))
221e4b17023SJohn Marino /* The minimal value of the INSN_TICK of an instruction.  */
222e4b17023SJohn Marino #define MIN_TICK (-max_insn_queue_index)
223e4b17023SJohn Marino 
224e4b17023SJohn Marino /* List of important notes we must keep around.  This is a pointer to the
225e4b17023SJohn Marino    last element in the list.  */
226e4b17023SJohn Marino rtx note_list;
227e4b17023SJohn Marino 
228e4b17023SJohn Marino static struct spec_info_def spec_info_var;
229e4b17023SJohn Marino /* Description of the speculative part of the scheduling.
230e4b17023SJohn Marino    If NULL - no speculation.  */
231e4b17023SJohn Marino spec_info_t spec_info = NULL;
232e4b17023SJohn Marino 
233e4b17023SJohn Marino /* True, if recovery block was added during scheduling of current block.
234e4b17023SJohn Marino    Used to determine, if we need to fix INSN_TICKs.  */
235e4b17023SJohn Marino static bool haifa_recovery_bb_recently_added_p;
236e4b17023SJohn Marino 
237e4b17023SJohn Marino /* True, if recovery block was added during this scheduling pass.
238e4b17023SJohn Marino    Used to determine if we should have empty memory pools of dependencies
239e4b17023SJohn Marino    after finishing current region.  */
240e4b17023SJohn Marino bool haifa_recovery_bb_ever_added_p;
241e4b17023SJohn Marino 
242e4b17023SJohn Marino /* Counters of different types of speculative instructions.  */
243e4b17023SJohn Marino static int nr_begin_data, nr_be_in_data, nr_begin_control, nr_be_in_control;
244e4b17023SJohn Marino 
245e4b17023SJohn Marino /* Array used in {unlink, restore}_bb_notes.  */
246e4b17023SJohn Marino static rtx *bb_header = 0;
247e4b17023SJohn Marino 
248e4b17023SJohn Marino /* Basic block after which recovery blocks will be created.  */
249e4b17023SJohn Marino static basic_block before_recovery;
250e4b17023SJohn Marino 
251e4b17023SJohn Marino /* Basic block just before the EXIT_BLOCK and after recovery, if we have
252e4b17023SJohn Marino    created it.  */
253e4b17023SJohn Marino basic_block after_recovery;
254e4b17023SJohn Marino 
255e4b17023SJohn Marino /* FALSE if we add bb to another region, so we don't need to initialize it.  */
256e4b17023SJohn Marino bool adding_bb_to_current_region_p = true;
257e4b17023SJohn Marino 
258e4b17023SJohn Marino /* Queues, etc.  */
259e4b17023SJohn Marino 
260e4b17023SJohn Marino /* An instruction is ready to be scheduled when all insns preceding it
261e4b17023SJohn Marino    have already been scheduled.  It is important to ensure that all
262e4b17023SJohn Marino    insns which use its result will not be executed until its result
263e4b17023SJohn Marino    has been computed.  An insn is maintained in one of four structures:
264e4b17023SJohn Marino 
265e4b17023SJohn Marino    (P) the "Pending" set of insns which cannot be scheduled until
266e4b17023SJohn Marino    their dependencies have been satisfied.
267e4b17023SJohn Marino    (Q) the "Queued" set of insns that can be scheduled when sufficient
268e4b17023SJohn Marino    time has passed.
269e4b17023SJohn Marino    (R) the "Ready" list of unscheduled, uncommitted insns.
270e4b17023SJohn Marino    (S) the "Scheduled" list of insns.
271e4b17023SJohn Marino 
272e4b17023SJohn Marino    Initially, all insns are either "Pending" or "Ready" depending on
273e4b17023SJohn Marino    whether their dependencies are satisfied.
274e4b17023SJohn Marino 
275e4b17023SJohn Marino    Insns move from the "Ready" list to the "Scheduled" list as they
276e4b17023SJohn Marino    are committed to the schedule.  As this occurs, the insns in the
277e4b17023SJohn Marino    "Pending" list have their dependencies satisfied and move to either
278e4b17023SJohn Marino    the "Ready" list or the "Queued" set depending on whether
279e4b17023SJohn Marino    sufficient time has passed to make them ready.  As time passes,
280e4b17023SJohn Marino    insns move from the "Queued" set to the "Ready" list.
281e4b17023SJohn Marino 
282e4b17023SJohn Marino    The "Pending" list (P) are the insns in the INSN_FORW_DEPS of the
283e4b17023SJohn Marino    unscheduled insns, i.e., those that are ready, queued, and pending.
284e4b17023SJohn Marino    The "Queued" set (Q) is implemented by the variable `insn_queue'.
285e4b17023SJohn Marino    The "Ready" list (R) is implemented by the variables `ready' and
286e4b17023SJohn Marino    `n_ready'.
287e4b17023SJohn Marino    The "Scheduled" list (S) is the new insn chain built by this pass.
288e4b17023SJohn Marino 
289e4b17023SJohn Marino    The transition (R->S) is implemented in the scheduling loop in
290e4b17023SJohn Marino    `schedule_block' when the best insn to schedule is chosen.
291e4b17023SJohn Marino    The transitions (P->R and P->Q) are implemented in `schedule_insn' as
292e4b17023SJohn Marino    insns move from the ready list to the scheduled list.
293e4b17023SJohn Marino    The transition (Q->R) is implemented in 'queue_to_insn' as time
294e4b17023SJohn Marino    passes or stalls are introduced.  */
295e4b17023SJohn Marino 
296e4b17023SJohn Marino /* Implement a circular buffer to delay instructions until sufficient
297e4b17023SJohn Marino    time has passed.  For the new pipeline description interface,
298e4b17023SJohn Marino    MAX_INSN_QUEUE_INDEX is a power of two minus one which is not less
299e4b17023SJohn Marino    than maximal time of instruction execution computed by genattr.c on
300e4b17023SJohn Marino    the base maximal time of functional unit reservations and getting a
301e4b17023SJohn Marino    result.  This is the longest time an insn may be queued.  */
302e4b17023SJohn Marino 
303e4b17023SJohn Marino static rtx *insn_queue;
304e4b17023SJohn Marino static int q_ptr = 0;
305e4b17023SJohn Marino static int q_size = 0;
306e4b17023SJohn Marino #define NEXT_Q(X) (((X)+1) & max_insn_queue_index)
307e4b17023SJohn Marino #define NEXT_Q_AFTER(X, C) (((X)+C) & max_insn_queue_index)
308e4b17023SJohn Marino 
309e4b17023SJohn Marino #define QUEUE_SCHEDULED (-3)
310e4b17023SJohn Marino #define QUEUE_NOWHERE   (-2)
311e4b17023SJohn Marino #define QUEUE_READY     (-1)
312e4b17023SJohn Marino /* QUEUE_SCHEDULED - INSN is scheduled.
313e4b17023SJohn Marino    QUEUE_NOWHERE   - INSN isn't scheduled yet and is neither in
314e4b17023SJohn Marino    queue or ready list.
315e4b17023SJohn Marino    QUEUE_READY     - INSN is in ready list.
316e4b17023SJohn Marino    N >= 0 - INSN queued for X [where NEXT_Q_AFTER (q_ptr, X) == N] cycles.  */
317e4b17023SJohn Marino 
318e4b17023SJohn Marino #define QUEUE_INDEX(INSN) (HID (INSN)->queue_index)
319e4b17023SJohn Marino 
320e4b17023SJohn Marino /* The following variable value refers for all current and future
321e4b17023SJohn Marino    reservations of the processor units.  */
322e4b17023SJohn Marino state_t curr_state;
323e4b17023SJohn Marino 
324e4b17023SJohn Marino /* The following variable value is size of memory representing all
325e4b17023SJohn Marino    current and future reservations of the processor units.  */
326e4b17023SJohn Marino size_t dfa_state_size;
327e4b17023SJohn Marino 
328e4b17023SJohn Marino /* The following array is used to find the best insn from ready when
329e4b17023SJohn Marino    the automaton pipeline interface is used.  */
330e4b17023SJohn Marino char *ready_try = NULL;
331e4b17023SJohn Marino 
332e4b17023SJohn Marino /* The ready list.  */
333e4b17023SJohn Marino struct ready_list ready = {NULL, 0, 0, 0, 0};
334e4b17023SJohn Marino 
335e4b17023SJohn Marino /* The pointer to the ready list (to be removed).  */
336e4b17023SJohn Marino static struct ready_list *readyp = &ready;
337e4b17023SJohn Marino 
338e4b17023SJohn Marino /* Scheduling clock.  */
339e4b17023SJohn Marino static int clock_var;
340e4b17023SJohn Marino 
341e4b17023SJohn Marino /* Clock at which the previous instruction was issued.  */
342e4b17023SJohn Marino static int last_clock_var;
343e4b17023SJohn Marino 
344e4b17023SJohn Marino /* Set to true if, when queuing a shadow insn, we discover that it would be
345e4b17023SJohn Marino    scheduled too late.  */
346e4b17023SJohn Marino static bool must_backtrack;
347e4b17023SJohn Marino 
348e4b17023SJohn Marino /* The following variable value is number of essential insns issued on
349e4b17023SJohn Marino    the current cycle.  An insn is essential one if it changes the
350e4b17023SJohn Marino    processors state.  */
351e4b17023SJohn Marino int cycle_issued_insns;
352e4b17023SJohn Marino 
353e4b17023SJohn Marino /* This records the actual schedule.  It is built up during the main phase
354e4b17023SJohn Marino    of schedule_block, and afterwards used to reorder the insns in the RTL.  */
355e4b17023SJohn Marino static VEC(rtx, heap) *scheduled_insns;
356e4b17023SJohn Marino 
357e4b17023SJohn Marino static int may_trap_exp (const_rtx, int);
358e4b17023SJohn Marino 
359e4b17023SJohn Marino /* Nonzero iff the address is comprised from at most 1 register.  */
360e4b17023SJohn Marino #define CONST_BASED_ADDRESS_P(x)			\
361e4b17023SJohn Marino   (REG_P (x)					\
362e4b17023SJohn Marino    || ((GET_CODE (x) == PLUS || GET_CODE (x) == MINUS	\
363e4b17023SJohn Marino 	|| (GET_CODE (x) == LO_SUM))			\
364e4b17023SJohn Marino        && (CONSTANT_P (XEXP (x, 0))			\
365e4b17023SJohn Marino 	   || CONSTANT_P (XEXP (x, 1)))))
366e4b17023SJohn Marino 
367e4b17023SJohn Marino /* Returns a class that insn with GET_DEST(insn)=x may belong to,
368e4b17023SJohn Marino    as found by analyzing insn's expression.  */
369e4b17023SJohn Marino 
370e4b17023SJohn Marino 
371e4b17023SJohn Marino static int haifa_luid_for_non_insn (rtx x);
372e4b17023SJohn Marino 
373e4b17023SJohn Marino /* Haifa version of sched_info hooks common to all headers.  */
374e4b17023SJohn Marino const struct common_sched_info_def haifa_common_sched_info =
375e4b17023SJohn Marino   {
376e4b17023SJohn Marino     NULL, /* fix_recovery_cfg */
377e4b17023SJohn Marino     NULL, /* add_block */
378e4b17023SJohn Marino     NULL, /* estimate_number_of_insns */
379e4b17023SJohn Marino     haifa_luid_for_non_insn, /* luid_for_non_insn */
380e4b17023SJohn Marino     SCHED_PASS_UNKNOWN /* sched_pass_id */
381e4b17023SJohn Marino   };
382e4b17023SJohn Marino 
383e4b17023SJohn Marino /* Mapping from instruction UID to its Logical UID.  */
384e4b17023SJohn Marino VEC (int, heap) *sched_luids = NULL;
385e4b17023SJohn Marino 
386e4b17023SJohn Marino /* Next LUID to assign to an instruction.  */
387e4b17023SJohn Marino int sched_max_luid = 1;
388e4b17023SJohn Marino 
389e4b17023SJohn Marino /* Haifa Instruction Data.  */
390e4b17023SJohn Marino VEC (haifa_insn_data_def, heap) *h_i_d = NULL;
391e4b17023SJohn Marino 
392e4b17023SJohn Marino void (* sched_init_only_bb) (basic_block, basic_block);
393e4b17023SJohn Marino 
394e4b17023SJohn Marino /* Split block function.  Different schedulers might use different functions
395e4b17023SJohn Marino    to handle their internal data consistent.  */
396e4b17023SJohn Marino basic_block (* sched_split_block) (basic_block, rtx);
397e4b17023SJohn Marino 
398e4b17023SJohn Marino /* Create empty basic block after the specified block.  */
399e4b17023SJohn Marino basic_block (* sched_create_empty_bb) (basic_block);
400e4b17023SJohn Marino 
401e4b17023SJohn Marino static int
may_trap_exp(const_rtx x,int is_store)402e4b17023SJohn Marino may_trap_exp (const_rtx x, int is_store)
403e4b17023SJohn Marino {
404e4b17023SJohn Marino   enum rtx_code code;
405e4b17023SJohn Marino 
406e4b17023SJohn Marino   if (x == 0)
407e4b17023SJohn Marino     return TRAP_FREE;
408e4b17023SJohn Marino   code = GET_CODE (x);
409e4b17023SJohn Marino   if (is_store)
410e4b17023SJohn Marino     {
411e4b17023SJohn Marino       if (code == MEM && may_trap_p (x))
412e4b17023SJohn Marino 	return TRAP_RISKY;
413e4b17023SJohn Marino       else
414e4b17023SJohn Marino 	return TRAP_FREE;
415e4b17023SJohn Marino     }
416e4b17023SJohn Marino   if (code == MEM)
417e4b17023SJohn Marino     {
418e4b17023SJohn Marino       /* The insn uses memory:  a volatile load.  */
419e4b17023SJohn Marino       if (MEM_VOLATILE_P (x))
420e4b17023SJohn Marino 	return IRISKY;
421e4b17023SJohn Marino       /* An exception-free load.  */
422e4b17023SJohn Marino       if (!may_trap_p (x))
423e4b17023SJohn Marino 	return IFREE;
424e4b17023SJohn Marino       /* A load with 1 base register, to be further checked.  */
425e4b17023SJohn Marino       if (CONST_BASED_ADDRESS_P (XEXP (x, 0)))
426e4b17023SJohn Marino 	return PFREE_CANDIDATE;
427e4b17023SJohn Marino       /* No info on the load, to be further checked.  */
428e4b17023SJohn Marino       return PRISKY_CANDIDATE;
429e4b17023SJohn Marino     }
430e4b17023SJohn Marino   else
431e4b17023SJohn Marino     {
432e4b17023SJohn Marino       const char *fmt;
433e4b17023SJohn Marino       int i, insn_class = TRAP_FREE;
434e4b17023SJohn Marino 
435e4b17023SJohn Marino       /* Neither store nor load, check if it may cause a trap.  */
436e4b17023SJohn Marino       if (may_trap_p (x))
437e4b17023SJohn Marino 	return TRAP_RISKY;
438e4b17023SJohn Marino       /* Recursive step: walk the insn...  */
439e4b17023SJohn Marino       fmt = GET_RTX_FORMAT (code);
440e4b17023SJohn Marino       for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
441e4b17023SJohn Marino 	{
442e4b17023SJohn Marino 	  if (fmt[i] == 'e')
443e4b17023SJohn Marino 	    {
444e4b17023SJohn Marino 	      int tmp_class = may_trap_exp (XEXP (x, i), is_store);
445e4b17023SJohn Marino 	      insn_class = WORST_CLASS (insn_class, tmp_class);
446e4b17023SJohn Marino 	    }
447e4b17023SJohn Marino 	  else if (fmt[i] == 'E')
448e4b17023SJohn Marino 	    {
449e4b17023SJohn Marino 	      int j;
450e4b17023SJohn Marino 	      for (j = 0; j < XVECLEN (x, i); j++)
451e4b17023SJohn Marino 		{
452e4b17023SJohn Marino 		  int tmp_class = may_trap_exp (XVECEXP (x, i, j), is_store);
453e4b17023SJohn Marino 		  insn_class = WORST_CLASS (insn_class, tmp_class);
454e4b17023SJohn Marino 		  if (insn_class == TRAP_RISKY || insn_class == IRISKY)
455e4b17023SJohn Marino 		    break;
456e4b17023SJohn Marino 		}
457e4b17023SJohn Marino 	    }
458e4b17023SJohn Marino 	  if (insn_class == TRAP_RISKY || insn_class == IRISKY)
459e4b17023SJohn Marino 	    break;
460e4b17023SJohn Marino 	}
461e4b17023SJohn Marino       return insn_class;
462e4b17023SJohn Marino     }
463e4b17023SJohn Marino }
464e4b17023SJohn Marino 
465e4b17023SJohn Marino /* Classifies rtx X of an insn for the purpose of verifying that X can be
466e4b17023SJohn Marino    executed speculatively (and consequently the insn can be moved
467e4b17023SJohn Marino    speculatively), by examining X, returning:
468e4b17023SJohn Marino    TRAP_RISKY: store, or risky non-load insn (e.g. division by variable).
469e4b17023SJohn Marino    TRAP_FREE: non-load insn.
470e4b17023SJohn Marino    IFREE: load from a globally safe location.
471e4b17023SJohn Marino    IRISKY: volatile load.
472e4b17023SJohn Marino    PFREE_CANDIDATE, PRISKY_CANDIDATE: load that need to be checked for
473e4b17023SJohn Marino    being either PFREE or PRISKY.  */
474e4b17023SJohn Marino 
475e4b17023SJohn Marino static int
haifa_classify_rtx(const_rtx x)476e4b17023SJohn Marino haifa_classify_rtx (const_rtx x)
477e4b17023SJohn Marino {
478e4b17023SJohn Marino   int tmp_class = TRAP_FREE;
479e4b17023SJohn Marino   int insn_class = TRAP_FREE;
480e4b17023SJohn Marino   enum rtx_code code;
481e4b17023SJohn Marino 
482e4b17023SJohn Marino   if (GET_CODE (x) == PARALLEL)
483e4b17023SJohn Marino     {
484e4b17023SJohn Marino       int i, len = XVECLEN (x, 0);
485e4b17023SJohn Marino 
486e4b17023SJohn Marino       for (i = len - 1; i >= 0; i--)
487e4b17023SJohn Marino 	{
488e4b17023SJohn Marino 	  tmp_class = haifa_classify_rtx (XVECEXP (x, 0, i));
489e4b17023SJohn Marino 	  insn_class = WORST_CLASS (insn_class, tmp_class);
490e4b17023SJohn Marino 	  if (insn_class == TRAP_RISKY || insn_class == IRISKY)
491e4b17023SJohn Marino 	    break;
492e4b17023SJohn Marino 	}
493e4b17023SJohn Marino     }
494e4b17023SJohn Marino   else
495e4b17023SJohn Marino     {
496e4b17023SJohn Marino       code = GET_CODE (x);
497e4b17023SJohn Marino       switch (code)
498e4b17023SJohn Marino 	{
499e4b17023SJohn Marino 	case CLOBBER:
500e4b17023SJohn Marino 	  /* Test if it is a 'store'.  */
501e4b17023SJohn Marino 	  tmp_class = may_trap_exp (XEXP (x, 0), 1);
502e4b17023SJohn Marino 	  break;
503e4b17023SJohn Marino 	case SET:
504e4b17023SJohn Marino 	  /* Test if it is a store.  */
505e4b17023SJohn Marino 	  tmp_class = may_trap_exp (SET_DEST (x), 1);
506e4b17023SJohn Marino 	  if (tmp_class == TRAP_RISKY)
507e4b17023SJohn Marino 	    break;
508e4b17023SJohn Marino 	  /* Test if it is a load.  */
509e4b17023SJohn Marino 	  tmp_class =
510e4b17023SJohn Marino 	    WORST_CLASS (tmp_class,
511e4b17023SJohn Marino 			 may_trap_exp (SET_SRC (x), 0));
512e4b17023SJohn Marino 	  break;
513e4b17023SJohn Marino 	case COND_EXEC:
514e4b17023SJohn Marino 	  tmp_class = haifa_classify_rtx (COND_EXEC_CODE (x));
515e4b17023SJohn Marino 	  if (tmp_class == TRAP_RISKY)
516e4b17023SJohn Marino 	    break;
517e4b17023SJohn Marino 	  tmp_class = WORST_CLASS (tmp_class,
518e4b17023SJohn Marino 				   may_trap_exp (COND_EXEC_TEST (x), 0));
519e4b17023SJohn Marino 	  break;
520e4b17023SJohn Marino 	case TRAP_IF:
521e4b17023SJohn Marino 	  tmp_class = TRAP_RISKY;
522e4b17023SJohn Marino 	  break;
523e4b17023SJohn Marino 	default:;
524e4b17023SJohn Marino 	}
525e4b17023SJohn Marino       insn_class = tmp_class;
526e4b17023SJohn Marino     }
527e4b17023SJohn Marino 
528e4b17023SJohn Marino   return insn_class;
529e4b17023SJohn Marino }
530e4b17023SJohn Marino 
531e4b17023SJohn Marino int
haifa_classify_insn(const_rtx insn)532e4b17023SJohn Marino haifa_classify_insn (const_rtx insn)
533e4b17023SJohn Marino {
534e4b17023SJohn Marino   return haifa_classify_rtx (PATTERN (insn));
535e4b17023SJohn Marino }
536e4b17023SJohn Marino 
537e4b17023SJohn Marino /* After the scheduler initialization function has been called, this function
538e4b17023SJohn Marino    can be called to enable modulo scheduling.  II is the initiation interval
539e4b17023SJohn Marino    we should use, it affects the delays for delay_pairs that were recorded as
540e4b17023SJohn Marino    separated by a given number of stages.
541e4b17023SJohn Marino 
542e4b17023SJohn Marino    MAX_STAGES provides us with a limit
543e4b17023SJohn Marino    after which we give up scheduling; the caller must have unrolled at least
544e4b17023SJohn Marino    as many copies of the loop body and recorded delay_pairs for them.
545e4b17023SJohn Marino 
546e4b17023SJohn Marino    INSNS is the number of real (non-debug) insns in one iteration of
547e4b17023SJohn Marino    the loop.  MAX_UID can be used to test whether an insn belongs to
548e4b17023SJohn Marino    the first iteration of the loop; all of them have a uid lower than
549e4b17023SJohn Marino    MAX_UID.  */
550e4b17023SJohn Marino void
set_modulo_params(int ii,int max_stages,int insns,int max_uid)551e4b17023SJohn Marino set_modulo_params (int ii, int max_stages, int insns, int max_uid)
552e4b17023SJohn Marino {
553e4b17023SJohn Marino   modulo_ii = ii;
554e4b17023SJohn Marino   modulo_max_stages = max_stages;
555e4b17023SJohn Marino   modulo_n_insns = insns;
556e4b17023SJohn Marino   modulo_iter0_max_uid = max_uid;
557e4b17023SJohn Marino   modulo_backtracks_left = PARAM_VALUE (PARAM_MAX_MODULO_BACKTRACK_ATTEMPTS);
558e4b17023SJohn Marino }
559e4b17023SJohn Marino 
560e4b17023SJohn Marino /* A structure to record a pair of insns where the first one is a real
561e4b17023SJohn Marino    insn that has delay slots, and the second is its delayed shadow.
562e4b17023SJohn Marino    I1 is scheduled normally and will emit an assembly instruction,
563e4b17023SJohn Marino    while I2 describes the side effect that takes place at the
564e4b17023SJohn Marino    transition between cycles CYCLES and (CYCLES + 1) after I1.  */
565e4b17023SJohn Marino struct delay_pair
566e4b17023SJohn Marino {
567e4b17023SJohn Marino   struct delay_pair *next_same_i1;
568e4b17023SJohn Marino   rtx i1, i2;
569e4b17023SJohn Marino   int cycles;
570e4b17023SJohn Marino   /* When doing modulo scheduling, we a delay_pair can also be used to
571e4b17023SJohn Marino      show that I1 and I2 are the same insn in a different stage.  If that
572e4b17023SJohn Marino      is the case, STAGES will be nonzero.  */
573e4b17023SJohn Marino   int stages;
574e4b17023SJohn Marino };
575e4b17023SJohn Marino 
576e4b17023SJohn Marino /* Two hash tables to record delay_pairs, one indexed by I1 and the other
577e4b17023SJohn Marino    indexed by I2.  */
578e4b17023SJohn Marino static htab_t delay_htab;
579e4b17023SJohn Marino static htab_t delay_htab_i2;
580e4b17023SJohn Marino 
581e4b17023SJohn Marino /* Called through htab_traverse.  Walk the hashtable using I2 as
582e4b17023SJohn Marino    index, and delete all elements involving an UID higher than
583e4b17023SJohn Marino    that pointed to by *DATA.  */
584e4b17023SJohn Marino static int
htab_i2_traverse(void ** slot,void * data)585e4b17023SJohn Marino htab_i2_traverse (void **slot, void *data)
586e4b17023SJohn Marino {
587e4b17023SJohn Marino   int maxuid = *(int *)data;
588e4b17023SJohn Marino   struct delay_pair *p = *(struct delay_pair **)slot;
589e4b17023SJohn Marino   if (INSN_UID (p->i2) >= maxuid || INSN_UID (p->i1) >= maxuid)
590e4b17023SJohn Marino     {
591e4b17023SJohn Marino       htab_clear_slot (delay_htab_i2, slot);
592e4b17023SJohn Marino     }
593e4b17023SJohn Marino   return 1;
594e4b17023SJohn Marino }
595e4b17023SJohn Marino 
596e4b17023SJohn Marino /* Called through htab_traverse.  Walk the hashtable using I2 as
597e4b17023SJohn Marino    index, and delete all elements involving an UID higher than
598e4b17023SJohn Marino    that pointed to by *DATA.  */
599e4b17023SJohn Marino static int
htab_i1_traverse(void ** slot,void * data)600e4b17023SJohn Marino htab_i1_traverse (void **slot, void *data)
601e4b17023SJohn Marino {
602e4b17023SJohn Marino   int maxuid = *(int *)data;
603e4b17023SJohn Marino   struct delay_pair **pslot = (struct delay_pair **)slot;
604e4b17023SJohn Marino   struct delay_pair *p, *first, **pprev;
605e4b17023SJohn Marino 
606e4b17023SJohn Marino   if (INSN_UID ((*pslot)->i1) >= maxuid)
607e4b17023SJohn Marino     {
608e4b17023SJohn Marino       htab_clear_slot (delay_htab, slot);
609e4b17023SJohn Marino       return 1;
610e4b17023SJohn Marino     }
611e4b17023SJohn Marino   pprev = &first;
612e4b17023SJohn Marino   for (p = *pslot; p; p = p->next_same_i1)
613e4b17023SJohn Marino     {
614e4b17023SJohn Marino       if (INSN_UID (p->i2) < maxuid)
615e4b17023SJohn Marino 	{
616e4b17023SJohn Marino 	  *pprev = p;
617e4b17023SJohn Marino 	  pprev = &p->next_same_i1;
618e4b17023SJohn Marino 	}
619e4b17023SJohn Marino     }
620e4b17023SJohn Marino   *pprev = NULL;
621e4b17023SJohn Marino   if (first == NULL)
622e4b17023SJohn Marino     htab_clear_slot (delay_htab, slot);
623e4b17023SJohn Marino   else
624e4b17023SJohn Marino     *pslot = first;
625e4b17023SJohn Marino   return 1;
626e4b17023SJohn Marino }
627e4b17023SJohn Marino 
628e4b17023SJohn Marino /* Discard all delay pairs which involve an insn with an UID higher
629e4b17023SJohn Marino    than MAX_UID.  */
630e4b17023SJohn Marino void
discard_delay_pairs_above(int max_uid)631e4b17023SJohn Marino discard_delay_pairs_above (int max_uid)
632e4b17023SJohn Marino {
633e4b17023SJohn Marino   htab_traverse (delay_htab, htab_i1_traverse, &max_uid);
634e4b17023SJohn Marino   htab_traverse (delay_htab_i2, htab_i2_traverse, &max_uid);
635e4b17023SJohn Marino }
636e4b17023SJohn Marino 
637e4b17023SJohn Marino /* Returns a hash value for X (which really is a delay_pair), based on
638e4b17023SJohn Marino    hashing just I1.  */
639e4b17023SJohn Marino static hashval_t
delay_hash_i1(const void * x)640e4b17023SJohn Marino delay_hash_i1 (const void *x)
641e4b17023SJohn Marino {
642e4b17023SJohn Marino   return htab_hash_pointer (((const struct delay_pair *) x)->i1);
643e4b17023SJohn Marino }
644e4b17023SJohn Marino 
645e4b17023SJohn Marino /* Returns a hash value for X (which really is a delay_pair), based on
646e4b17023SJohn Marino    hashing just I2.  */
647e4b17023SJohn Marino static hashval_t
delay_hash_i2(const void * x)648e4b17023SJohn Marino delay_hash_i2 (const void *x)
649e4b17023SJohn Marino {
650e4b17023SJohn Marino   return htab_hash_pointer (((const struct delay_pair *) x)->i2);
651e4b17023SJohn Marino }
652e4b17023SJohn Marino 
653e4b17023SJohn Marino /* Return nonzero if I1 of pair X is the same as that of pair Y.  */
654e4b17023SJohn Marino static int
delay_i1_eq(const void * x,const void * y)655e4b17023SJohn Marino delay_i1_eq (const void *x, const void *y)
656e4b17023SJohn Marino {
657e4b17023SJohn Marino   return ((const struct delay_pair *) x)->i1 == y;
658e4b17023SJohn Marino }
659e4b17023SJohn Marino 
660e4b17023SJohn Marino /* Return nonzero if I2 of pair X is the same as that of pair Y.  */
661e4b17023SJohn Marino static int
delay_i2_eq(const void * x,const void * y)662e4b17023SJohn Marino delay_i2_eq (const void *x, const void *y)
663e4b17023SJohn Marino {
664e4b17023SJohn Marino   return ((const struct delay_pair *) x)->i2 == y;
665e4b17023SJohn Marino }
666e4b17023SJohn Marino 
667e4b17023SJohn Marino /* This function can be called by a port just before it starts the final
668e4b17023SJohn Marino    scheduling pass.  It records the fact that an instruction with delay
669e4b17023SJohn Marino    slots has been split into two insns, I1 and I2.  The first one will be
670e4b17023SJohn Marino    scheduled normally and initiates the operation.  The second one is a
671e4b17023SJohn Marino    shadow which must follow a specific number of cycles after I1; its only
672e4b17023SJohn Marino    purpose is to show the side effect that occurs at that cycle in the RTL.
673e4b17023SJohn Marino    If a JUMP_INSN or a CALL_INSN has been split, I1 should be a normal INSN,
674e4b17023SJohn Marino    while I2 retains the original insn type.
675e4b17023SJohn Marino 
676e4b17023SJohn Marino    There are two ways in which the number of cycles can be specified,
677e4b17023SJohn Marino    involving the CYCLES and STAGES arguments to this function.  If STAGES
678e4b17023SJohn Marino    is zero, we just use the value of CYCLES.  Otherwise, STAGES is a factor
679e4b17023SJohn Marino    which is multiplied by MODULO_II to give the number of cycles.  This is
680e4b17023SJohn Marino    only useful if the caller also calls set_modulo_params to enable modulo
681e4b17023SJohn Marino    scheduling.  */
682e4b17023SJohn Marino 
683e4b17023SJohn Marino void
record_delay_slot_pair(rtx i1,rtx i2,int cycles,int stages)684e4b17023SJohn Marino record_delay_slot_pair (rtx i1, rtx i2, int cycles, int stages)
685e4b17023SJohn Marino {
686e4b17023SJohn Marino   struct delay_pair *p = XNEW (struct delay_pair);
687e4b17023SJohn Marino   struct delay_pair **slot;
688e4b17023SJohn Marino 
689e4b17023SJohn Marino   p->i1 = i1;
690e4b17023SJohn Marino   p->i2 = i2;
691e4b17023SJohn Marino   p->cycles = cycles;
692e4b17023SJohn Marino   p->stages = stages;
693e4b17023SJohn Marino 
694e4b17023SJohn Marino   if (!delay_htab)
695e4b17023SJohn Marino     {
696e4b17023SJohn Marino       delay_htab = htab_create (10, delay_hash_i1, delay_i1_eq, NULL);
697e4b17023SJohn Marino       delay_htab_i2 = htab_create (10, delay_hash_i2, delay_i2_eq, free);
698e4b17023SJohn Marino     }
699e4b17023SJohn Marino   slot = ((struct delay_pair **)
700e4b17023SJohn Marino 	  htab_find_slot_with_hash (delay_htab, i1, htab_hash_pointer (i1),
701e4b17023SJohn Marino 				    INSERT));
702e4b17023SJohn Marino   p->next_same_i1 = *slot;
703e4b17023SJohn Marino   *slot = p;
704e4b17023SJohn Marino   slot = ((struct delay_pair **)
705e4b17023SJohn Marino 	  htab_find_slot_with_hash (delay_htab_i2, i2, htab_hash_pointer (i2),
706e4b17023SJohn Marino 				    INSERT));
707e4b17023SJohn Marino   *slot = p;
708e4b17023SJohn Marino }
709e4b17023SJohn Marino 
710e4b17023SJohn Marino /* Examine the delay pair hashtable to see if INSN is a shadow for another,
711e4b17023SJohn Marino    and return the other insn if so.  Return NULL otherwise.  */
712e4b17023SJohn Marino rtx
real_insn_for_shadow(rtx insn)713e4b17023SJohn Marino real_insn_for_shadow (rtx insn)
714e4b17023SJohn Marino {
715e4b17023SJohn Marino   struct delay_pair *pair;
716e4b17023SJohn Marino 
717e4b17023SJohn Marino   if (delay_htab == NULL)
718e4b17023SJohn Marino     return NULL_RTX;
719e4b17023SJohn Marino 
720e4b17023SJohn Marino   pair
721e4b17023SJohn Marino     = (struct delay_pair *)htab_find_with_hash (delay_htab_i2, insn,
722e4b17023SJohn Marino 						htab_hash_pointer (insn));
723e4b17023SJohn Marino   if (!pair || pair->stages > 0)
724e4b17023SJohn Marino     return NULL_RTX;
725e4b17023SJohn Marino   return pair->i1;
726e4b17023SJohn Marino }
727e4b17023SJohn Marino 
728e4b17023SJohn Marino /* For a pair P of insns, return the fixed distance in cycles from the first
729e4b17023SJohn Marino    insn after which the second must be scheduled.  */
730e4b17023SJohn Marino static int
pair_delay(struct delay_pair * p)731e4b17023SJohn Marino pair_delay (struct delay_pair *p)
732e4b17023SJohn Marino {
733e4b17023SJohn Marino   if (p->stages == 0)
734e4b17023SJohn Marino     return p->cycles;
735e4b17023SJohn Marino   else
736e4b17023SJohn Marino     return p->stages * modulo_ii;
737e4b17023SJohn Marino }
738e4b17023SJohn Marino 
739e4b17023SJohn Marino /* Given an insn INSN, add a dependence on its delayed shadow if it
740e4b17023SJohn Marino    has one.  Also try to find situations where shadows depend on each other
741e4b17023SJohn Marino    and add dependencies to the real insns to limit the amount of backtracking
742e4b17023SJohn Marino    needed.  */
743e4b17023SJohn Marino void
add_delay_dependencies(rtx insn)744e4b17023SJohn Marino add_delay_dependencies (rtx insn)
745e4b17023SJohn Marino {
746e4b17023SJohn Marino   struct delay_pair *pair;
747e4b17023SJohn Marino   sd_iterator_def sd_it;
748e4b17023SJohn Marino   dep_t dep;
749e4b17023SJohn Marino 
750e4b17023SJohn Marino   if (!delay_htab)
751e4b17023SJohn Marino     return;
752e4b17023SJohn Marino 
753e4b17023SJohn Marino   pair
754e4b17023SJohn Marino     = (struct delay_pair *)htab_find_with_hash (delay_htab_i2, insn,
755e4b17023SJohn Marino 						htab_hash_pointer (insn));
756e4b17023SJohn Marino   if (!pair)
757e4b17023SJohn Marino     return;
758e4b17023SJohn Marino   add_dependence (insn, pair->i1, REG_DEP_ANTI);
759e4b17023SJohn Marino   if (pair->stages)
760e4b17023SJohn Marino     return;
761e4b17023SJohn Marino 
762e4b17023SJohn Marino   FOR_EACH_DEP (pair->i2, SD_LIST_BACK, sd_it, dep)
763e4b17023SJohn Marino     {
764e4b17023SJohn Marino       rtx pro = DEP_PRO (dep);
765e4b17023SJohn Marino       struct delay_pair *other_pair
766e4b17023SJohn Marino 	= (struct delay_pair *)htab_find_with_hash (delay_htab_i2, pro,
767e4b17023SJohn Marino 						    htab_hash_pointer (pro));
768e4b17023SJohn Marino       if (!other_pair || other_pair->stages)
769e4b17023SJohn Marino 	continue;
770e4b17023SJohn Marino       if (pair_delay (other_pair) >= pair_delay (pair))
771e4b17023SJohn Marino 	{
772e4b17023SJohn Marino 	  if (sched_verbose >= 4)
773e4b17023SJohn Marino 	    {
774e4b17023SJohn Marino 	      fprintf (sched_dump, ";;\tadding dependence %d <- %d\n",
775e4b17023SJohn Marino 		       INSN_UID (other_pair->i1),
776e4b17023SJohn Marino 		       INSN_UID (pair->i1));
777e4b17023SJohn Marino 	      fprintf (sched_dump, ";;\tpair1 %d <- %d, cost %d\n",
778e4b17023SJohn Marino 		       INSN_UID (pair->i1),
779e4b17023SJohn Marino 		       INSN_UID (pair->i2),
780e4b17023SJohn Marino 		       pair_delay (pair));
781e4b17023SJohn Marino 	      fprintf (sched_dump, ";;\tpair2 %d <- %d, cost %d\n",
782e4b17023SJohn Marino 		       INSN_UID (other_pair->i1),
783e4b17023SJohn Marino 		       INSN_UID (other_pair->i2),
784e4b17023SJohn Marino 		       pair_delay (other_pair));
785e4b17023SJohn Marino 	    }
786e4b17023SJohn Marino 	  add_dependence (pair->i1, other_pair->i1, REG_DEP_ANTI);
787e4b17023SJohn Marino 	}
788e4b17023SJohn Marino     }
789e4b17023SJohn Marino }
790e4b17023SJohn Marino 
791e4b17023SJohn Marino /* Forward declarations.  */
792e4b17023SJohn Marino 
793e4b17023SJohn Marino static int priority (rtx);
794e4b17023SJohn Marino static int rank_for_schedule (const void *, const void *);
795e4b17023SJohn Marino static void swap_sort (rtx *, int);
796e4b17023SJohn Marino static void queue_insn (rtx, int, const char *);
797e4b17023SJohn Marino static int schedule_insn (rtx);
798e4b17023SJohn Marino static void adjust_priority (rtx);
799e4b17023SJohn Marino static void advance_one_cycle (void);
800e4b17023SJohn Marino static void extend_h_i_d (void);
801e4b17023SJohn Marino 
802e4b17023SJohn Marino 
803e4b17023SJohn Marino /* Notes handling mechanism:
804e4b17023SJohn Marino    =========================
805e4b17023SJohn Marino    Generally, NOTES are saved before scheduling and restored after scheduling.
806e4b17023SJohn Marino    The scheduler distinguishes between two types of notes:
807e4b17023SJohn Marino 
808e4b17023SJohn Marino    (1) LOOP_BEGIN, LOOP_END, SETJMP, EHREGION_BEG, EHREGION_END notes:
809e4b17023SJohn Marino    Before scheduling a region, a pointer to the note is added to the insn
810e4b17023SJohn Marino    that follows or precedes it.  (This happens as part of the data dependence
811e4b17023SJohn Marino    computation).  After scheduling an insn, the pointer contained in it is
812e4b17023SJohn Marino    used for regenerating the corresponding note (in reemit_notes).
813e4b17023SJohn Marino 
814e4b17023SJohn Marino    (2) All other notes (e.g. INSN_DELETED):  Before scheduling a block,
815e4b17023SJohn Marino    these notes are put in a list (in rm_other_notes() and
816e4b17023SJohn Marino    unlink_other_notes ()).  After scheduling the block, these notes are
817e4b17023SJohn Marino    inserted at the beginning of the block (in schedule_block()).  */
818e4b17023SJohn Marino 
819e4b17023SJohn Marino static void ready_add (struct ready_list *, rtx, bool);
820e4b17023SJohn Marino static rtx ready_remove_first (struct ready_list *);
821e4b17023SJohn Marino static rtx ready_remove_first_dispatch (struct ready_list *ready);
822e4b17023SJohn Marino 
823e4b17023SJohn Marino static void queue_to_ready (struct ready_list *);
824e4b17023SJohn Marino static int early_queue_to_ready (state_t, struct ready_list *);
825e4b17023SJohn Marino 
826e4b17023SJohn Marino static void debug_ready_list (struct ready_list *);
827e4b17023SJohn Marino 
828e4b17023SJohn Marino /* The following functions are used to implement multi-pass scheduling
829e4b17023SJohn Marino    on the first cycle.  */
830e4b17023SJohn Marino static rtx ready_remove (struct ready_list *, int);
831e4b17023SJohn Marino static void ready_remove_insn (rtx);
832e4b17023SJohn Marino 
833e4b17023SJohn Marino static void fix_inter_tick (rtx, rtx);
834e4b17023SJohn Marino static int fix_tick_ready (rtx);
835e4b17023SJohn Marino static void change_queue_index (rtx, int);
836e4b17023SJohn Marino 
837e4b17023SJohn Marino /* The following functions are used to implement scheduling of data/control
838e4b17023SJohn Marino    speculative instructions.  */
839e4b17023SJohn Marino 
840e4b17023SJohn Marino static void extend_h_i_d (void);
841e4b17023SJohn Marino static void init_h_i_d (rtx);
842e4b17023SJohn Marino static int haifa_speculate_insn (rtx, ds_t, rtx *);
843e4b17023SJohn Marino static void generate_recovery_code (rtx);
844e4b17023SJohn Marino static void process_insn_forw_deps_be_in_spec (rtx, rtx, ds_t);
845e4b17023SJohn Marino static void begin_speculative_block (rtx);
846e4b17023SJohn Marino static void add_to_speculative_block (rtx);
847e4b17023SJohn Marino static void init_before_recovery (basic_block *);
848e4b17023SJohn Marino static void create_check_block_twin (rtx, bool);
849e4b17023SJohn Marino static void fix_recovery_deps (basic_block);
850e4b17023SJohn Marino static bool haifa_change_pattern (rtx, rtx);
851e4b17023SJohn Marino static void dump_new_block_header (int, basic_block, rtx, rtx);
852e4b17023SJohn Marino static void restore_bb_notes (basic_block);
853e4b17023SJohn Marino static void fix_jump_move (rtx);
854e4b17023SJohn Marino static void move_block_after_check (rtx);
855e4b17023SJohn Marino static void move_succs (VEC(edge,gc) **, basic_block);
856e4b17023SJohn Marino static void sched_remove_insn (rtx);
857e4b17023SJohn Marino static void clear_priorities (rtx, rtx_vec_t *);
858e4b17023SJohn Marino static void calc_priorities (rtx_vec_t);
859e4b17023SJohn Marino static void add_jump_dependencies (rtx, rtx);
860e4b17023SJohn Marino 
861e4b17023SJohn Marino #endif /* INSN_SCHEDULING */
862e4b17023SJohn Marino 
863e4b17023SJohn Marino /* Point to state used for the current scheduling pass.  */
864e4b17023SJohn Marino struct haifa_sched_info *current_sched_info;
865e4b17023SJohn Marino 
866e4b17023SJohn Marino #ifndef INSN_SCHEDULING
867e4b17023SJohn Marino void
schedule_insns(void)868e4b17023SJohn Marino schedule_insns (void)
869e4b17023SJohn Marino {
870e4b17023SJohn Marino }
871e4b17023SJohn Marino #else
872e4b17023SJohn Marino 
873e4b17023SJohn Marino /* Do register pressure sensitive insn scheduling if the flag is set
874e4b17023SJohn Marino    up.  */
875e4b17023SJohn Marino bool sched_pressure_p;
876e4b17023SJohn Marino 
877e4b17023SJohn Marino /* Map regno -> its pressure class.  The map defined only when
878e4b17023SJohn Marino    SCHED_PRESSURE_P is true.  */
879e4b17023SJohn Marino enum reg_class *sched_regno_pressure_class;
880e4b17023SJohn Marino 
881e4b17023SJohn Marino /* The current register pressure.  Only elements corresponding pressure
882e4b17023SJohn Marino    classes are defined.  */
883e4b17023SJohn Marino static int curr_reg_pressure[N_REG_CLASSES];
884e4b17023SJohn Marino 
885e4b17023SJohn Marino /* Saved value of the previous array.  */
886e4b17023SJohn Marino static int saved_reg_pressure[N_REG_CLASSES];
887e4b17023SJohn Marino 
888e4b17023SJohn Marino /* Register living at given scheduling point.  */
889e4b17023SJohn Marino static bitmap curr_reg_live;
890e4b17023SJohn Marino 
891e4b17023SJohn Marino /* Saved value of the previous array.  */
892e4b17023SJohn Marino static bitmap saved_reg_live;
893e4b17023SJohn Marino 
894e4b17023SJohn Marino /* Registers mentioned in the current region.  */
895e4b17023SJohn Marino static bitmap region_ref_regs;
896e4b17023SJohn Marino 
897e4b17023SJohn Marino /* Initiate register pressure relative info for scheduling the current
898e4b17023SJohn Marino    region.  Currently it is only clearing register mentioned in the
899e4b17023SJohn Marino    current region.  */
900e4b17023SJohn Marino void
sched_init_region_reg_pressure_info(void)901e4b17023SJohn Marino sched_init_region_reg_pressure_info (void)
902e4b17023SJohn Marino {
903e4b17023SJohn Marino   bitmap_clear (region_ref_regs);
904e4b17023SJohn Marino }
905e4b17023SJohn Marino 
906e4b17023SJohn Marino /* Update current register pressure related info after birth (if
907e4b17023SJohn Marino    BIRTH_P) or death of register REGNO.  */
908e4b17023SJohn Marino static void
mark_regno_birth_or_death(int regno,bool birth_p)909e4b17023SJohn Marino mark_regno_birth_or_death (int regno, bool birth_p)
910e4b17023SJohn Marino {
911e4b17023SJohn Marino   enum reg_class pressure_class;
912e4b17023SJohn Marino 
913e4b17023SJohn Marino   pressure_class = sched_regno_pressure_class[regno];
914e4b17023SJohn Marino   if (regno >= FIRST_PSEUDO_REGISTER)
915e4b17023SJohn Marino     {
916e4b17023SJohn Marino       if (pressure_class != NO_REGS)
917e4b17023SJohn Marino 	{
918e4b17023SJohn Marino 	  if (birth_p)
919e4b17023SJohn Marino 	    {
920e4b17023SJohn Marino 	      bitmap_set_bit (curr_reg_live, regno);
921e4b17023SJohn Marino 	      curr_reg_pressure[pressure_class]
922e4b17023SJohn Marino 		+= (ira_reg_class_max_nregs
923e4b17023SJohn Marino 		    [pressure_class][PSEUDO_REGNO_MODE (regno)]);
924e4b17023SJohn Marino 	    }
925e4b17023SJohn Marino 	  else
926e4b17023SJohn Marino 	    {
927e4b17023SJohn Marino 	      bitmap_clear_bit (curr_reg_live, regno);
928e4b17023SJohn Marino 	      curr_reg_pressure[pressure_class]
929e4b17023SJohn Marino 		-= (ira_reg_class_max_nregs
930e4b17023SJohn Marino 		    [pressure_class][PSEUDO_REGNO_MODE (regno)]);
931e4b17023SJohn Marino 	    }
932e4b17023SJohn Marino 	}
933e4b17023SJohn Marino     }
934e4b17023SJohn Marino   else if (pressure_class != NO_REGS
935e4b17023SJohn Marino 	   && ! TEST_HARD_REG_BIT (ira_no_alloc_regs, regno))
936e4b17023SJohn Marino     {
937e4b17023SJohn Marino       if (birth_p)
938e4b17023SJohn Marino 	{
939e4b17023SJohn Marino 	  bitmap_set_bit (curr_reg_live, regno);
940e4b17023SJohn Marino 	  curr_reg_pressure[pressure_class]++;
941e4b17023SJohn Marino 	}
942e4b17023SJohn Marino       else
943e4b17023SJohn Marino 	{
944e4b17023SJohn Marino 	  bitmap_clear_bit (curr_reg_live, regno);
945e4b17023SJohn Marino 	  curr_reg_pressure[pressure_class]--;
946e4b17023SJohn Marino 	}
947e4b17023SJohn Marino     }
948e4b17023SJohn Marino }
949e4b17023SJohn Marino 
950e4b17023SJohn Marino /* Initiate current register pressure related info from living
951e4b17023SJohn Marino    registers given by LIVE.  */
952e4b17023SJohn Marino static void
initiate_reg_pressure_info(bitmap live)953e4b17023SJohn Marino initiate_reg_pressure_info (bitmap live)
954e4b17023SJohn Marino {
955e4b17023SJohn Marino   int i;
956e4b17023SJohn Marino   unsigned int j;
957e4b17023SJohn Marino   bitmap_iterator bi;
958e4b17023SJohn Marino 
959e4b17023SJohn Marino   for (i = 0; i < ira_pressure_classes_num; i++)
960e4b17023SJohn Marino     curr_reg_pressure[ira_pressure_classes[i]] = 0;
961e4b17023SJohn Marino   bitmap_clear (curr_reg_live);
962e4b17023SJohn Marino   EXECUTE_IF_SET_IN_BITMAP (live, 0, j, bi)
963e4b17023SJohn Marino     if (current_nr_blocks == 1 || bitmap_bit_p (region_ref_regs, j))
964e4b17023SJohn Marino       mark_regno_birth_or_death (j, true);
965e4b17023SJohn Marino }
966e4b17023SJohn Marino 
967e4b17023SJohn Marino /* Mark registers in X as mentioned in the current region.  */
968e4b17023SJohn Marino static void
setup_ref_regs(rtx x)969e4b17023SJohn Marino setup_ref_regs (rtx x)
970e4b17023SJohn Marino {
971e4b17023SJohn Marino   int i, j, regno;
972e4b17023SJohn Marino   const RTX_CODE code = GET_CODE (x);
973e4b17023SJohn Marino   const char *fmt;
974e4b17023SJohn Marino 
975e4b17023SJohn Marino   if (REG_P (x))
976e4b17023SJohn Marino     {
977e4b17023SJohn Marino       regno = REGNO (x);
978e4b17023SJohn Marino       if (HARD_REGISTER_NUM_P (regno))
979e4b17023SJohn Marino 	bitmap_set_range (region_ref_regs, regno,
980e4b17023SJohn Marino 			  hard_regno_nregs[regno][GET_MODE (x)]);
981e4b17023SJohn Marino       else
982e4b17023SJohn Marino 	bitmap_set_bit (region_ref_regs, REGNO (x));
983e4b17023SJohn Marino       return;
984e4b17023SJohn Marino     }
985e4b17023SJohn Marino   fmt = GET_RTX_FORMAT (code);
986e4b17023SJohn Marino   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
987e4b17023SJohn Marino     if (fmt[i] == 'e')
988e4b17023SJohn Marino       setup_ref_regs (XEXP (x, i));
989e4b17023SJohn Marino     else if (fmt[i] == 'E')
990e4b17023SJohn Marino       {
991e4b17023SJohn Marino 	for (j = 0; j < XVECLEN (x, i); j++)
992e4b17023SJohn Marino 	  setup_ref_regs (XVECEXP (x, i, j));
993e4b17023SJohn Marino       }
994e4b17023SJohn Marino }
995e4b17023SJohn Marino 
996e4b17023SJohn Marino /* Initiate current register pressure related info at the start of
997e4b17023SJohn Marino    basic block BB.  */
998e4b17023SJohn Marino static void
initiate_bb_reg_pressure_info(basic_block bb)999e4b17023SJohn Marino initiate_bb_reg_pressure_info (basic_block bb)
1000e4b17023SJohn Marino {
1001e4b17023SJohn Marino   unsigned int i ATTRIBUTE_UNUSED;
1002e4b17023SJohn Marino   rtx insn;
1003e4b17023SJohn Marino 
1004e4b17023SJohn Marino   if (current_nr_blocks > 1)
1005e4b17023SJohn Marino     FOR_BB_INSNS (bb, insn)
1006e4b17023SJohn Marino       if (NONDEBUG_INSN_P (insn))
1007e4b17023SJohn Marino 	setup_ref_regs (PATTERN (insn));
1008e4b17023SJohn Marino   initiate_reg_pressure_info (df_get_live_in (bb));
1009e4b17023SJohn Marino #ifdef EH_RETURN_DATA_REGNO
1010e4b17023SJohn Marino   if (bb_has_eh_pred (bb))
1011e4b17023SJohn Marino     for (i = 0; ; ++i)
1012e4b17023SJohn Marino       {
1013e4b17023SJohn Marino 	unsigned int regno = EH_RETURN_DATA_REGNO (i);
1014e4b17023SJohn Marino 
1015e4b17023SJohn Marino 	if (regno == INVALID_REGNUM)
1016e4b17023SJohn Marino 	  break;
1017e4b17023SJohn Marino 	if (! bitmap_bit_p (df_get_live_in (bb), regno))
1018e4b17023SJohn Marino 	  mark_regno_birth_or_death (regno, true);
1019e4b17023SJohn Marino       }
1020e4b17023SJohn Marino #endif
1021e4b17023SJohn Marino }
1022e4b17023SJohn Marino 
1023e4b17023SJohn Marino /* Save current register pressure related info.  */
1024e4b17023SJohn Marino static void
save_reg_pressure(void)1025e4b17023SJohn Marino save_reg_pressure (void)
1026e4b17023SJohn Marino {
1027e4b17023SJohn Marino   int i;
1028e4b17023SJohn Marino 
1029e4b17023SJohn Marino   for (i = 0; i < ira_pressure_classes_num; i++)
1030e4b17023SJohn Marino     saved_reg_pressure[ira_pressure_classes[i]]
1031e4b17023SJohn Marino       = curr_reg_pressure[ira_pressure_classes[i]];
1032e4b17023SJohn Marino   bitmap_copy (saved_reg_live, curr_reg_live);
1033e4b17023SJohn Marino }
1034e4b17023SJohn Marino 
1035e4b17023SJohn Marino /* Restore saved register pressure related info.  */
1036e4b17023SJohn Marino static void
restore_reg_pressure(void)1037e4b17023SJohn Marino restore_reg_pressure (void)
1038e4b17023SJohn Marino {
1039e4b17023SJohn Marino   int i;
1040e4b17023SJohn Marino 
1041e4b17023SJohn Marino   for (i = 0; i < ira_pressure_classes_num; i++)
1042e4b17023SJohn Marino     curr_reg_pressure[ira_pressure_classes[i]]
1043e4b17023SJohn Marino       = saved_reg_pressure[ira_pressure_classes[i]];
1044e4b17023SJohn Marino   bitmap_copy (curr_reg_live, saved_reg_live);
1045e4b17023SJohn Marino }
1046e4b17023SJohn Marino 
1047e4b17023SJohn Marino /* Return TRUE if the register is dying after its USE.  */
1048e4b17023SJohn Marino static bool
dying_use_p(struct reg_use_data * use)1049e4b17023SJohn Marino dying_use_p (struct reg_use_data *use)
1050e4b17023SJohn Marino {
1051e4b17023SJohn Marino   struct reg_use_data *next;
1052e4b17023SJohn Marino 
1053e4b17023SJohn Marino   for (next = use->next_regno_use; next != use; next = next->next_regno_use)
1054e4b17023SJohn Marino     if (NONDEBUG_INSN_P (next->insn)
1055e4b17023SJohn Marino 	&& QUEUE_INDEX (next->insn) != QUEUE_SCHEDULED)
1056e4b17023SJohn Marino       return false;
1057e4b17023SJohn Marino   return true;
1058e4b17023SJohn Marino }
1059e4b17023SJohn Marino 
1060e4b17023SJohn Marino /* Print info about the current register pressure and its excess for
1061e4b17023SJohn Marino    each pressure class.  */
1062e4b17023SJohn Marino static void
print_curr_reg_pressure(void)1063e4b17023SJohn Marino print_curr_reg_pressure (void)
1064e4b17023SJohn Marino {
1065e4b17023SJohn Marino   int i;
1066e4b17023SJohn Marino   enum reg_class cl;
1067e4b17023SJohn Marino 
1068e4b17023SJohn Marino   fprintf (sched_dump, ";;\t");
1069e4b17023SJohn Marino   for (i = 0; i < ira_pressure_classes_num; i++)
1070e4b17023SJohn Marino     {
1071e4b17023SJohn Marino       cl = ira_pressure_classes[i];
1072e4b17023SJohn Marino       gcc_assert (curr_reg_pressure[cl] >= 0);
1073e4b17023SJohn Marino       fprintf (sched_dump, "  %s:%d(%d)", reg_class_names[cl],
1074e4b17023SJohn Marino 	       curr_reg_pressure[cl],
1075e4b17023SJohn Marino 	       curr_reg_pressure[cl] - ira_available_class_regs[cl]);
1076e4b17023SJohn Marino     }
1077e4b17023SJohn Marino   fprintf (sched_dump, "\n");
1078e4b17023SJohn Marino }
1079e4b17023SJohn Marino 
1080e4b17023SJohn Marino /* Determine if INSN has a condition that is clobbered if a register
1081e4b17023SJohn Marino    in SET_REGS is modified.  */
1082e4b17023SJohn Marino static bool
cond_clobbered_p(rtx insn,HARD_REG_SET set_regs)1083e4b17023SJohn Marino cond_clobbered_p (rtx insn, HARD_REG_SET set_regs)
1084e4b17023SJohn Marino {
1085e4b17023SJohn Marino   rtx pat = PATTERN (insn);
1086e4b17023SJohn Marino   gcc_assert (GET_CODE (pat) == COND_EXEC);
1087e4b17023SJohn Marino   if (TEST_HARD_REG_BIT (set_regs, REGNO (XEXP (COND_EXEC_TEST (pat), 0))))
1088e4b17023SJohn Marino     {
1089e4b17023SJohn Marino       sd_iterator_def sd_it;
1090e4b17023SJohn Marino       dep_t dep;
1091e4b17023SJohn Marino       haifa_change_pattern (insn, ORIG_PAT (insn));
1092e4b17023SJohn Marino       FOR_EACH_DEP (insn, SD_LIST_BACK, sd_it, dep)
1093e4b17023SJohn Marino 	DEP_STATUS (dep) &= ~DEP_CANCELLED;
1094e4b17023SJohn Marino       TODO_SPEC (insn) = HARD_DEP;
1095e4b17023SJohn Marino       if (sched_verbose >= 2)
1096e4b17023SJohn Marino 	fprintf (sched_dump,
1097e4b17023SJohn Marino 		 ";;\t\tdequeue insn %s because of clobbered condition\n",
1098e4b17023SJohn Marino 		 (*current_sched_info->print_insn) (insn, 0));
1099e4b17023SJohn Marino       return true;
1100e4b17023SJohn Marino     }
1101e4b17023SJohn Marino 
1102e4b17023SJohn Marino   return false;
1103e4b17023SJohn Marino }
1104e4b17023SJohn Marino 
1105e4b17023SJohn Marino /* Look at the remaining dependencies for insn NEXT, and compute and return
1106e4b17023SJohn Marino    the TODO_SPEC value we should use for it.  This is called after one of
1107e4b17023SJohn Marino    NEXT's dependencies has been resolved.  */
1108e4b17023SJohn Marino 
1109e4b17023SJohn Marino static ds_t
recompute_todo_spec(rtx next)1110e4b17023SJohn Marino recompute_todo_spec (rtx next)
1111e4b17023SJohn Marino {
1112e4b17023SJohn Marino   ds_t new_ds;
1113e4b17023SJohn Marino   sd_iterator_def sd_it;
1114e4b17023SJohn Marino   dep_t dep, control_dep = NULL;
1115e4b17023SJohn Marino   int n_spec = 0;
1116e4b17023SJohn Marino   int n_control = 0;
1117e4b17023SJohn Marino   bool first_p = true;
1118e4b17023SJohn Marino 
1119e4b17023SJohn Marino   if (sd_lists_empty_p (next, SD_LIST_BACK))
1120e4b17023SJohn Marino     /* NEXT has all its dependencies resolved.  */
1121e4b17023SJohn Marino     return 0;
1122e4b17023SJohn Marino 
1123e4b17023SJohn Marino   if (!sd_lists_empty_p (next, SD_LIST_HARD_BACK))
1124e4b17023SJohn Marino     return HARD_DEP;
1125e4b17023SJohn Marino 
1126e4b17023SJohn Marino   /* Now we've got NEXT with speculative deps only.
1127e4b17023SJohn Marino      1. Look at the deps to see what we have to do.
1128e4b17023SJohn Marino      2. Check if we can do 'todo'.  */
1129e4b17023SJohn Marino   new_ds = 0;
1130e4b17023SJohn Marino 
1131e4b17023SJohn Marino   FOR_EACH_DEP (next, SD_LIST_BACK, sd_it, dep)
1132e4b17023SJohn Marino     {
1133e4b17023SJohn Marino       ds_t ds = DEP_STATUS (dep) & SPECULATIVE;
1134e4b17023SJohn Marino 
1135e4b17023SJohn Marino       if (DEBUG_INSN_P (DEP_PRO (dep)) && !DEBUG_INSN_P (next))
1136e4b17023SJohn Marino 	continue;
1137e4b17023SJohn Marino 
1138e4b17023SJohn Marino       if (ds)
1139e4b17023SJohn Marino 	{
1140e4b17023SJohn Marino 	  n_spec++;
1141e4b17023SJohn Marino 	  if (first_p)
1142e4b17023SJohn Marino 	    {
1143e4b17023SJohn Marino 	      first_p = false;
1144e4b17023SJohn Marino 
1145e4b17023SJohn Marino 	      new_ds = ds;
1146e4b17023SJohn Marino 	    }
1147e4b17023SJohn Marino 	  else
1148e4b17023SJohn Marino 	    new_ds = ds_merge (new_ds, ds);
1149e4b17023SJohn Marino 	}
1150e4b17023SJohn Marino       if (DEP_TYPE (dep) == REG_DEP_CONTROL)
1151e4b17023SJohn Marino 	{
1152e4b17023SJohn Marino 	  n_control++;
1153e4b17023SJohn Marino 	  control_dep = dep;
1154e4b17023SJohn Marino 	  DEP_STATUS (dep) &= ~DEP_CANCELLED;
1155e4b17023SJohn Marino 	}
1156e4b17023SJohn Marino     }
1157e4b17023SJohn Marino 
1158e4b17023SJohn Marino   if (n_control == 1 && n_spec == 0)
1159e4b17023SJohn Marino     {
1160e4b17023SJohn Marino       rtx pro, other, new_pat;
1161e4b17023SJohn Marino       rtx cond = NULL_RTX;
1162e4b17023SJohn Marino       bool success;
1163e4b17023SJohn Marino       rtx prev = NULL_RTX;
1164e4b17023SJohn Marino       int i;
1165e4b17023SJohn Marino       unsigned regno;
1166e4b17023SJohn Marino 
1167e4b17023SJohn Marino       if ((current_sched_info->flags & DO_PREDICATION) == 0
1168e4b17023SJohn Marino 	  || (ORIG_PAT (next) != NULL_RTX
1169e4b17023SJohn Marino 	      && PREDICATED_PAT (next) == NULL_RTX))
1170e4b17023SJohn Marino 	return HARD_DEP;
1171e4b17023SJohn Marino 
1172e4b17023SJohn Marino       pro = DEP_PRO (control_dep);
1173e4b17023SJohn Marino       other = real_insn_for_shadow (pro);
1174e4b17023SJohn Marino       if (other != NULL_RTX)
1175e4b17023SJohn Marino 	pro = other;
1176e4b17023SJohn Marino 
1177e4b17023SJohn Marino       cond = sched_get_reverse_condition_uncached (pro);
1178e4b17023SJohn Marino       regno = REGNO (XEXP (cond, 0));
1179e4b17023SJohn Marino 
1180e4b17023SJohn Marino       /* Find the last scheduled insn that modifies the condition register.
1181e4b17023SJohn Marino 	 We can stop looking once we find the insn we depend on through the
1182e4b17023SJohn Marino 	 REG_DEP_CONTROL; if the condition register isn't modified after it,
1183e4b17023SJohn Marino 	 we know that it still has the right value.  */
1184e4b17023SJohn Marino       if (QUEUE_INDEX (pro) == QUEUE_SCHEDULED)
1185e4b17023SJohn Marino 	FOR_EACH_VEC_ELT_REVERSE (rtx, scheduled_insns, i, prev)
1186e4b17023SJohn Marino 	  {
1187e4b17023SJohn Marino 	    HARD_REG_SET t;
1188e4b17023SJohn Marino 
1189e4b17023SJohn Marino 	    find_all_hard_reg_sets (prev, &t);
1190e4b17023SJohn Marino 	    if (TEST_HARD_REG_BIT (t, regno))
1191e4b17023SJohn Marino 	      return HARD_DEP;
1192e4b17023SJohn Marino 	    if (prev == pro)
1193e4b17023SJohn Marino 	      break;
1194e4b17023SJohn Marino 	  }
1195e4b17023SJohn Marino       if (ORIG_PAT (next) == NULL_RTX)
1196e4b17023SJohn Marino 	{
1197e4b17023SJohn Marino 	  ORIG_PAT (next) = PATTERN (next);
1198e4b17023SJohn Marino 
1199e4b17023SJohn Marino 	  new_pat = gen_rtx_COND_EXEC (VOIDmode, cond, PATTERN (next));
1200e4b17023SJohn Marino 	  success = haifa_change_pattern (next, new_pat);
1201e4b17023SJohn Marino 	  if (!success)
1202e4b17023SJohn Marino 	    return HARD_DEP;
1203e4b17023SJohn Marino 	  PREDICATED_PAT (next) = new_pat;
1204e4b17023SJohn Marino 	}
1205e4b17023SJohn Marino       else if (PATTERN (next) != PREDICATED_PAT (next))
1206e4b17023SJohn Marino 	{
1207e4b17023SJohn Marino 	  bool success = haifa_change_pattern (next,
1208e4b17023SJohn Marino 					       PREDICATED_PAT (next));
1209e4b17023SJohn Marino 	  gcc_assert (success);
1210e4b17023SJohn Marino 	}
1211e4b17023SJohn Marino       DEP_STATUS (control_dep) |= DEP_CANCELLED;
1212e4b17023SJohn Marino       return DEP_CONTROL;
1213e4b17023SJohn Marino     }
1214e4b17023SJohn Marino 
1215e4b17023SJohn Marino   if (PREDICATED_PAT (next) != NULL_RTX)
1216e4b17023SJohn Marino     {
1217e4b17023SJohn Marino       int tick = INSN_TICK (next);
1218e4b17023SJohn Marino       bool success = haifa_change_pattern (next,
1219e4b17023SJohn Marino 					   ORIG_PAT (next));
1220e4b17023SJohn Marino       INSN_TICK (next) = tick;
1221e4b17023SJohn Marino       gcc_assert (success);
1222e4b17023SJohn Marino     }
1223e4b17023SJohn Marino 
1224e4b17023SJohn Marino   /* We can't handle the case where there are both speculative and control
1225e4b17023SJohn Marino      dependencies, so we return HARD_DEP in such a case.  Also fail if
1226e4b17023SJohn Marino      we have speculative dependencies with not enough points, or more than
1227e4b17023SJohn Marino      one control dependency.  */
1228e4b17023SJohn Marino   if ((n_spec > 0 && n_control > 0)
1229e4b17023SJohn Marino       || (n_spec > 0
1230e4b17023SJohn Marino 	  /* Too few points?  */
1231e4b17023SJohn Marino 	  && ds_weak (new_ds) < spec_info->data_weakness_cutoff)
1232e4b17023SJohn Marino       || (n_control > 1))
1233e4b17023SJohn Marino     return HARD_DEP;
1234e4b17023SJohn Marino 
1235e4b17023SJohn Marino   return new_ds;
1236e4b17023SJohn Marino }
1237e4b17023SJohn Marino 
1238e4b17023SJohn Marino /* Pointer to the last instruction scheduled.  */
1239e4b17023SJohn Marino static rtx last_scheduled_insn;
1240e4b17023SJohn Marino 
1241e4b17023SJohn Marino /* Pointer to the last nondebug instruction scheduled within the
1242e4b17023SJohn Marino    block, or the prev_head of the scheduling block.  Used by
1243e4b17023SJohn Marino    rank_for_schedule, so that insns independent of the last scheduled
1244e4b17023SJohn Marino    insn will be preferred over dependent instructions.  */
1245e4b17023SJohn Marino static rtx last_nondebug_scheduled_insn;
1246e4b17023SJohn Marino 
1247e4b17023SJohn Marino /* Pointer that iterates through the list of unscheduled insns if we
1248e4b17023SJohn Marino    have a dbg_cnt enabled.  It always points at an insn prior to the
1249e4b17023SJohn Marino    first unscheduled one.  */
1250e4b17023SJohn Marino static rtx nonscheduled_insns_begin;
1251e4b17023SJohn Marino 
1252e4b17023SJohn Marino /* Cached cost of the instruction.  Use below function to get cost of the
1253e4b17023SJohn Marino    insn.  -1 here means that the field is not initialized.  */
1254e4b17023SJohn Marino #define INSN_COST(INSN)	(HID (INSN)->cost)
1255e4b17023SJohn Marino 
1256e4b17023SJohn Marino /* Compute cost of executing INSN.
1257e4b17023SJohn Marino    This is the number of cycles between instruction issue and
1258e4b17023SJohn Marino    instruction results.  */
1259e4b17023SJohn Marino int
insn_cost(rtx insn)1260e4b17023SJohn Marino insn_cost (rtx insn)
1261e4b17023SJohn Marino {
1262e4b17023SJohn Marino   int cost;
1263e4b17023SJohn Marino 
1264e4b17023SJohn Marino   if (sel_sched_p ())
1265e4b17023SJohn Marino     {
1266e4b17023SJohn Marino       if (recog_memoized (insn) < 0)
1267e4b17023SJohn Marino 	return 0;
1268e4b17023SJohn Marino 
1269e4b17023SJohn Marino       cost = insn_default_latency (insn);
1270e4b17023SJohn Marino       if (cost < 0)
1271e4b17023SJohn Marino 	cost = 0;
1272e4b17023SJohn Marino 
1273e4b17023SJohn Marino       return cost;
1274e4b17023SJohn Marino     }
1275e4b17023SJohn Marino 
1276e4b17023SJohn Marino   cost = INSN_COST (insn);
1277e4b17023SJohn Marino 
1278e4b17023SJohn Marino   if (cost < 0)
1279e4b17023SJohn Marino     {
1280e4b17023SJohn Marino       /* A USE insn, or something else we don't need to
1281e4b17023SJohn Marino 	 understand.  We can't pass these directly to
1282e4b17023SJohn Marino 	 result_ready_cost or insn_default_latency because it will
1283e4b17023SJohn Marino 	 trigger a fatal error for unrecognizable insns.  */
1284e4b17023SJohn Marino       if (recog_memoized (insn) < 0)
1285e4b17023SJohn Marino 	{
1286e4b17023SJohn Marino 	  INSN_COST (insn) = 0;
1287e4b17023SJohn Marino 	  return 0;
1288e4b17023SJohn Marino 	}
1289e4b17023SJohn Marino       else
1290e4b17023SJohn Marino 	{
1291e4b17023SJohn Marino 	  cost = insn_default_latency (insn);
1292e4b17023SJohn Marino 	  if (cost < 0)
1293e4b17023SJohn Marino 	    cost = 0;
1294e4b17023SJohn Marino 
1295e4b17023SJohn Marino 	  INSN_COST (insn) = cost;
1296e4b17023SJohn Marino 	}
1297e4b17023SJohn Marino     }
1298e4b17023SJohn Marino 
1299e4b17023SJohn Marino   return cost;
1300e4b17023SJohn Marino }
1301e4b17023SJohn Marino 
1302e4b17023SJohn Marino /* Compute cost of dependence LINK.
1303e4b17023SJohn Marino    This is the number of cycles between instruction issue and
1304e4b17023SJohn Marino    instruction results.
1305e4b17023SJohn Marino    ??? We also use this function to call recog_memoized on all insns.  */
1306e4b17023SJohn Marino int
dep_cost_1(dep_t link,dw_t dw)1307e4b17023SJohn Marino dep_cost_1 (dep_t link, dw_t dw)
1308e4b17023SJohn Marino {
1309e4b17023SJohn Marino   rtx insn = DEP_PRO (link);
1310e4b17023SJohn Marino   rtx used = DEP_CON (link);
1311e4b17023SJohn Marino   int cost;
1312e4b17023SJohn Marino 
1313e4b17023SJohn Marino   if (DEP_COST (link) != UNKNOWN_DEP_COST)
1314e4b17023SJohn Marino     return DEP_COST (link);
1315e4b17023SJohn Marino 
1316e4b17023SJohn Marino   if (delay_htab)
1317e4b17023SJohn Marino     {
1318e4b17023SJohn Marino       struct delay_pair *delay_entry;
1319e4b17023SJohn Marino       delay_entry
1320e4b17023SJohn Marino 	= (struct delay_pair *)htab_find_with_hash (delay_htab_i2, used,
1321e4b17023SJohn Marino 						    htab_hash_pointer (used));
1322e4b17023SJohn Marino       if (delay_entry)
1323e4b17023SJohn Marino 	{
1324e4b17023SJohn Marino 	  if (delay_entry->i1 == insn)
1325e4b17023SJohn Marino 	    {
1326e4b17023SJohn Marino 	      DEP_COST (link) = pair_delay (delay_entry);
1327e4b17023SJohn Marino 	      return DEP_COST (link);
1328e4b17023SJohn Marino 	    }
1329e4b17023SJohn Marino 	}
1330e4b17023SJohn Marino     }
1331e4b17023SJohn Marino 
1332e4b17023SJohn Marino   /* A USE insn should never require the value used to be computed.
1333e4b17023SJohn Marino      This allows the computation of a function's result and parameter
1334e4b17023SJohn Marino      values to overlap the return and call.  We don't care about the
1335e4b17023SJohn Marino      dependence cost when only decreasing register pressure.  */
1336e4b17023SJohn Marino   if (recog_memoized (used) < 0)
1337e4b17023SJohn Marino     {
1338e4b17023SJohn Marino       cost = 0;
1339e4b17023SJohn Marino       recog_memoized (insn);
1340e4b17023SJohn Marino     }
1341e4b17023SJohn Marino   else
1342e4b17023SJohn Marino     {
1343e4b17023SJohn Marino       enum reg_note dep_type = DEP_TYPE (link);
1344e4b17023SJohn Marino 
1345e4b17023SJohn Marino       cost = insn_cost (insn);
1346e4b17023SJohn Marino 
1347e4b17023SJohn Marino       if (INSN_CODE (insn) >= 0)
1348e4b17023SJohn Marino 	{
1349e4b17023SJohn Marino 	  if (dep_type == REG_DEP_ANTI)
1350e4b17023SJohn Marino 	    cost = 0;
1351e4b17023SJohn Marino 	  else if (dep_type == REG_DEP_OUTPUT)
1352e4b17023SJohn Marino 	    {
1353e4b17023SJohn Marino 	      cost = (insn_default_latency (insn)
1354e4b17023SJohn Marino 		      - insn_default_latency (used));
1355e4b17023SJohn Marino 	      if (cost <= 0)
1356e4b17023SJohn Marino 		cost = 1;
1357e4b17023SJohn Marino 	    }
1358e4b17023SJohn Marino 	  else if (bypass_p (insn))
1359e4b17023SJohn Marino 	    cost = insn_latency (insn, used);
1360e4b17023SJohn Marino 	}
1361e4b17023SJohn Marino 
1362e4b17023SJohn Marino 
1363e4b17023SJohn Marino       if (targetm.sched.adjust_cost_2)
1364e4b17023SJohn Marino 	cost = targetm.sched.adjust_cost_2 (used, (int) dep_type, insn, cost,
1365e4b17023SJohn Marino 					    dw);
1366e4b17023SJohn Marino       else if (targetm.sched.adjust_cost != NULL)
1367e4b17023SJohn Marino 	{
1368e4b17023SJohn Marino 	  /* This variable is used for backward compatibility with the
1369e4b17023SJohn Marino 	     targets.  */
1370e4b17023SJohn Marino 	  rtx dep_cost_rtx_link = alloc_INSN_LIST (NULL_RTX, NULL_RTX);
1371e4b17023SJohn Marino 
1372e4b17023SJohn Marino 	  /* Make it self-cycled, so that if some tries to walk over this
1373e4b17023SJohn Marino 	     incomplete list he/she will be caught in an endless loop.  */
1374e4b17023SJohn Marino 	  XEXP (dep_cost_rtx_link, 1) = dep_cost_rtx_link;
1375e4b17023SJohn Marino 
1376e4b17023SJohn Marino 	  /* Targets use only REG_NOTE_KIND of the link.  */
1377e4b17023SJohn Marino 	  PUT_REG_NOTE_KIND (dep_cost_rtx_link, DEP_TYPE (link));
1378e4b17023SJohn Marino 
1379e4b17023SJohn Marino 	  cost = targetm.sched.adjust_cost (used, dep_cost_rtx_link,
1380e4b17023SJohn Marino 					    insn, cost);
1381e4b17023SJohn Marino 
1382e4b17023SJohn Marino 	  free_INSN_LIST_node (dep_cost_rtx_link);
1383e4b17023SJohn Marino 	}
1384e4b17023SJohn Marino 
1385e4b17023SJohn Marino       if (cost < 0)
1386e4b17023SJohn Marino 	cost = 0;
1387e4b17023SJohn Marino     }
1388e4b17023SJohn Marino 
1389e4b17023SJohn Marino   DEP_COST (link) = cost;
1390e4b17023SJohn Marino   return cost;
1391e4b17023SJohn Marino }
1392e4b17023SJohn Marino 
1393e4b17023SJohn Marino /* Compute cost of dependence LINK.
1394e4b17023SJohn Marino    This is the number of cycles between instruction issue and
1395e4b17023SJohn Marino    instruction results.  */
1396e4b17023SJohn Marino int
dep_cost(dep_t link)1397e4b17023SJohn Marino dep_cost (dep_t link)
1398e4b17023SJohn Marino {
1399e4b17023SJohn Marino   return dep_cost_1 (link, 0);
1400e4b17023SJohn Marino }
1401e4b17023SJohn Marino 
1402e4b17023SJohn Marino /* Use this sel-sched.c friendly function in reorder2 instead of increasing
1403e4b17023SJohn Marino    INSN_PRIORITY explicitly.  */
1404e4b17023SJohn Marino void
increase_insn_priority(rtx insn,int amount)1405e4b17023SJohn Marino increase_insn_priority (rtx insn, int amount)
1406e4b17023SJohn Marino {
1407e4b17023SJohn Marino   if (!sel_sched_p ())
1408e4b17023SJohn Marino     {
1409e4b17023SJohn Marino       /* We're dealing with haifa-sched.c INSN_PRIORITY.  */
1410e4b17023SJohn Marino       if (INSN_PRIORITY_KNOWN (insn))
1411e4b17023SJohn Marino 	  INSN_PRIORITY (insn) += amount;
1412e4b17023SJohn Marino     }
1413e4b17023SJohn Marino   else
1414e4b17023SJohn Marino     {
1415e4b17023SJohn Marino       /* In sel-sched.c INSN_PRIORITY is not kept up to date.
1416e4b17023SJohn Marino 	 Use EXPR_PRIORITY instead. */
1417e4b17023SJohn Marino       sel_add_to_insn_priority (insn, amount);
1418e4b17023SJohn Marino     }
1419e4b17023SJohn Marino }
1420e4b17023SJohn Marino 
1421e4b17023SJohn Marino /* Return 'true' if DEP should be included in priority calculations.  */
1422e4b17023SJohn Marino static bool
contributes_to_priority_p(dep_t dep)1423e4b17023SJohn Marino contributes_to_priority_p (dep_t dep)
1424e4b17023SJohn Marino {
1425e4b17023SJohn Marino   if (DEBUG_INSN_P (DEP_CON (dep))
1426e4b17023SJohn Marino       || DEBUG_INSN_P (DEP_PRO (dep)))
1427e4b17023SJohn Marino     return false;
1428e4b17023SJohn Marino 
1429e4b17023SJohn Marino   /* Critical path is meaningful in block boundaries only.  */
1430e4b17023SJohn Marino   if (!current_sched_info->contributes_to_priority (DEP_CON (dep),
1431e4b17023SJohn Marino 						    DEP_PRO (dep)))
1432e4b17023SJohn Marino     return false;
1433e4b17023SJohn Marino 
1434e4b17023SJohn Marino   /* If flag COUNT_SPEC_IN_CRITICAL_PATH is set,
1435e4b17023SJohn Marino      then speculative instructions will less likely be
1436e4b17023SJohn Marino      scheduled.  That is because the priority of
1437e4b17023SJohn Marino      their producers will increase, and, thus, the
1438e4b17023SJohn Marino      producers will more likely be scheduled, thus,
1439e4b17023SJohn Marino      resolving the dependence.  */
1440e4b17023SJohn Marino   if (sched_deps_info->generate_spec_deps
1441e4b17023SJohn Marino       && !(spec_info->flags & COUNT_SPEC_IN_CRITICAL_PATH)
1442e4b17023SJohn Marino       && (DEP_STATUS (dep) & SPECULATIVE))
1443e4b17023SJohn Marino     return false;
1444e4b17023SJohn Marino 
1445e4b17023SJohn Marino   return true;
1446e4b17023SJohn Marino }
1447e4b17023SJohn Marino 
1448e4b17023SJohn Marino /* Compute the number of nondebug forward deps of an insn.  */
1449e4b17023SJohn Marino 
1450e4b17023SJohn Marino static int
dep_list_size(rtx insn)1451e4b17023SJohn Marino dep_list_size (rtx insn)
1452e4b17023SJohn Marino {
1453e4b17023SJohn Marino   sd_iterator_def sd_it;
1454e4b17023SJohn Marino   dep_t dep;
1455e4b17023SJohn Marino   int dbgcount = 0, nodbgcount = 0;
1456e4b17023SJohn Marino 
1457e4b17023SJohn Marino   if (!MAY_HAVE_DEBUG_INSNS)
1458e4b17023SJohn Marino     return sd_lists_size (insn, SD_LIST_FORW);
1459e4b17023SJohn Marino 
1460e4b17023SJohn Marino   FOR_EACH_DEP (insn, SD_LIST_FORW, sd_it, dep)
1461e4b17023SJohn Marino     {
1462e4b17023SJohn Marino       if (DEBUG_INSN_P (DEP_CON (dep)))
1463e4b17023SJohn Marino 	dbgcount++;
1464e4b17023SJohn Marino       else if (!DEBUG_INSN_P (DEP_PRO (dep)))
1465e4b17023SJohn Marino 	nodbgcount++;
1466e4b17023SJohn Marino     }
1467e4b17023SJohn Marino 
1468e4b17023SJohn Marino   gcc_assert (dbgcount + nodbgcount == sd_lists_size (insn, SD_LIST_FORW));
1469e4b17023SJohn Marino 
1470e4b17023SJohn Marino   return nodbgcount;
1471e4b17023SJohn Marino }
1472e4b17023SJohn Marino 
1473e4b17023SJohn Marino /* Compute the priority number for INSN.  */
1474e4b17023SJohn Marino static int
priority(rtx insn)1475e4b17023SJohn Marino priority (rtx insn)
1476e4b17023SJohn Marino {
1477e4b17023SJohn Marino   if (! INSN_P (insn))
1478e4b17023SJohn Marino     return 0;
1479e4b17023SJohn Marino 
1480e4b17023SJohn Marino   /* We should not be interested in priority of an already scheduled insn.  */
1481e4b17023SJohn Marino   gcc_assert (QUEUE_INDEX (insn) != QUEUE_SCHEDULED);
1482e4b17023SJohn Marino 
1483e4b17023SJohn Marino   if (!INSN_PRIORITY_KNOWN (insn))
1484e4b17023SJohn Marino     {
1485e4b17023SJohn Marino       int this_priority = -1;
1486e4b17023SJohn Marino 
1487e4b17023SJohn Marino       if (dep_list_size (insn) == 0)
1488e4b17023SJohn Marino 	/* ??? We should set INSN_PRIORITY to insn_cost when and insn has
1489e4b17023SJohn Marino 	   some forward deps but all of them are ignored by
1490e4b17023SJohn Marino 	   contributes_to_priority hook.  At the moment we set priority of
1491e4b17023SJohn Marino 	   such insn to 0.  */
1492e4b17023SJohn Marino 	this_priority = insn_cost (insn);
1493e4b17023SJohn Marino       else
1494e4b17023SJohn Marino 	{
1495e4b17023SJohn Marino 	  rtx prev_first, twin;
1496e4b17023SJohn Marino 	  basic_block rec;
1497e4b17023SJohn Marino 
1498e4b17023SJohn Marino 	  /* For recovery check instructions we calculate priority slightly
1499e4b17023SJohn Marino 	     different than that of normal instructions.  Instead of walking
1500e4b17023SJohn Marino 	     through INSN_FORW_DEPS (check) list, we walk through
1501e4b17023SJohn Marino 	     INSN_FORW_DEPS list of each instruction in the corresponding
1502e4b17023SJohn Marino 	     recovery block.  */
1503e4b17023SJohn Marino 
1504e4b17023SJohn Marino           /* Selective scheduling does not define RECOVERY_BLOCK macro.  */
1505e4b17023SJohn Marino 	  rec = sel_sched_p () ? NULL : RECOVERY_BLOCK (insn);
1506e4b17023SJohn Marino 	  if (!rec || rec == EXIT_BLOCK_PTR)
1507e4b17023SJohn Marino 	    {
1508e4b17023SJohn Marino 	      prev_first = PREV_INSN (insn);
1509e4b17023SJohn Marino 	      twin = insn;
1510e4b17023SJohn Marino 	    }
1511e4b17023SJohn Marino 	  else
1512e4b17023SJohn Marino 	    {
1513e4b17023SJohn Marino 	      prev_first = NEXT_INSN (BB_HEAD (rec));
1514e4b17023SJohn Marino 	      twin = PREV_INSN (BB_END (rec));
1515e4b17023SJohn Marino 	    }
1516e4b17023SJohn Marino 
1517e4b17023SJohn Marino 	  do
1518e4b17023SJohn Marino 	    {
1519e4b17023SJohn Marino 	      sd_iterator_def sd_it;
1520e4b17023SJohn Marino 	      dep_t dep;
1521e4b17023SJohn Marino 
1522e4b17023SJohn Marino 	      FOR_EACH_DEP (twin, SD_LIST_FORW, sd_it, dep)
1523e4b17023SJohn Marino 		{
1524e4b17023SJohn Marino 		  rtx next;
1525e4b17023SJohn Marino 		  int next_priority;
1526e4b17023SJohn Marino 
1527e4b17023SJohn Marino 		  next = DEP_CON (dep);
1528e4b17023SJohn Marino 
1529e4b17023SJohn Marino 		  if (BLOCK_FOR_INSN (next) != rec)
1530e4b17023SJohn Marino 		    {
1531e4b17023SJohn Marino 		      int cost;
1532e4b17023SJohn Marino 
1533e4b17023SJohn Marino 		      if (!contributes_to_priority_p (dep))
1534e4b17023SJohn Marino 			continue;
1535e4b17023SJohn Marino 
1536e4b17023SJohn Marino 		      if (twin == insn)
1537e4b17023SJohn Marino 			cost = dep_cost (dep);
1538e4b17023SJohn Marino 		      else
1539e4b17023SJohn Marino 			{
1540e4b17023SJohn Marino 			  struct _dep _dep1, *dep1 = &_dep1;
1541e4b17023SJohn Marino 
1542e4b17023SJohn Marino 			  init_dep (dep1, insn, next, REG_DEP_ANTI);
1543e4b17023SJohn Marino 
1544e4b17023SJohn Marino 			  cost = dep_cost (dep1);
1545e4b17023SJohn Marino 			}
1546e4b17023SJohn Marino 
1547e4b17023SJohn Marino 		      next_priority = cost + priority (next);
1548e4b17023SJohn Marino 
1549e4b17023SJohn Marino 		      if (next_priority > this_priority)
1550e4b17023SJohn Marino 			this_priority = next_priority;
1551e4b17023SJohn Marino 		    }
1552e4b17023SJohn Marino 		}
1553e4b17023SJohn Marino 
1554e4b17023SJohn Marino 	      twin = PREV_INSN (twin);
1555e4b17023SJohn Marino 	    }
1556e4b17023SJohn Marino 	  while (twin != prev_first);
1557e4b17023SJohn Marino 	}
1558e4b17023SJohn Marino 
1559e4b17023SJohn Marino       if (this_priority < 0)
1560e4b17023SJohn Marino 	{
1561e4b17023SJohn Marino 	  gcc_assert (this_priority == -1);
1562e4b17023SJohn Marino 
1563e4b17023SJohn Marino 	  this_priority = insn_cost (insn);
1564e4b17023SJohn Marino 	}
1565e4b17023SJohn Marino 
1566e4b17023SJohn Marino       INSN_PRIORITY (insn) = this_priority;
1567e4b17023SJohn Marino       INSN_PRIORITY_STATUS (insn) = 1;
1568e4b17023SJohn Marino     }
1569e4b17023SJohn Marino 
1570e4b17023SJohn Marino   return INSN_PRIORITY (insn);
1571e4b17023SJohn Marino }
1572e4b17023SJohn Marino 
1573e4b17023SJohn Marino /* Macros and functions for keeping the priority queue sorted, and
1574e4b17023SJohn Marino    dealing with queuing and dequeuing of instructions.  */
1575e4b17023SJohn Marino 
1576e4b17023SJohn Marino #define SCHED_SORT(READY, N_READY)                                   \
1577e4b17023SJohn Marino do { if ((N_READY) == 2)				             \
1578e4b17023SJohn Marino        swap_sort (READY, N_READY);			             \
1579e4b17023SJohn Marino      else if ((N_READY) > 2)                                         \
1580e4b17023SJohn Marino          qsort (READY, N_READY, sizeof (rtx), rank_for_schedule); }  \
1581e4b17023SJohn Marino while (0)
1582e4b17023SJohn Marino 
1583e4b17023SJohn Marino /* Setup info about the current register pressure impact of scheduling
1584e4b17023SJohn Marino    INSN at the current scheduling point.  */
1585e4b17023SJohn Marino static void
setup_insn_reg_pressure_info(rtx insn)1586e4b17023SJohn Marino setup_insn_reg_pressure_info (rtx insn)
1587e4b17023SJohn Marino {
1588e4b17023SJohn Marino   int i, change, before, after, hard_regno;
1589e4b17023SJohn Marino   int excess_cost_change;
1590e4b17023SJohn Marino   enum machine_mode mode;
1591e4b17023SJohn Marino   enum reg_class cl;
1592e4b17023SJohn Marino   struct reg_pressure_data *pressure_info;
1593e4b17023SJohn Marino   int *max_reg_pressure;
1594e4b17023SJohn Marino   struct reg_use_data *use;
1595e4b17023SJohn Marino   static int death[N_REG_CLASSES];
1596e4b17023SJohn Marino 
1597e4b17023SJohn Marino   gcc_checking_assert (!DEBUG_INSN_P (insn));
1598e4b17023SJohn Marino 
1599e4b17023SJohn Marino   excess_cost_change = 0;
1600e4b17023SJohn Marino   for (i = 0; i < ira_pressure_classes_num; i++)
1601e4b17023SJohn Marino     death[ira_pressure_classes[i]] = 0;
1602e4b17023SJohn Marino   for (use = INSN_REG_USE_LIST (insn); use != NULL; use = use->next_insn_use)
1603e4b17023SJohn Marino     if (dying_use_p (use))
1604e4b17023SJohn Marino       {
1605e4b17023SJohn Marino 	cl = sched_regno_pressure_class[use->regno];
1606e4b17023SJohn Marino 	if (use->regno < FIRST_PSEUDO_REGISTER)
1607e4b17023SJohn Marino 	  death[cl]++;
1608e4b17023SJohn Marino 	else
1609e4b17023SJohn Marino 	  death[cl]
1610e4b17023SJohn Marino 	    += ira_reg_class_max_nregs[cl][PSEUDO_REGNO_MODE (use->regno)];
1611e4b17023SJohn Marino       }
1612e4b17023SJohn Marino   pressure_info = INSN_REG_PRESSURE (insn);
1613e4b17023SJohn Marino   max_reg_pressure = INSN_MAX_REG_PRESSURE (insn);
1614e4b17023SJohn Marino   gcc_assert (pressure_info != NULL && max_reg_pressure != NULL);
1615e4b17023SJohn Marino   for (i = 0; i < ira_pressure_classes_num; i++)
1616e4b17023SJohn Marino     {
1617e4b17023SJohn Marino       cl = ira_pressure_classes[i];
1618e4b17023SJohn Marino       gcc_assert (curr_reg_pressure[cl] >= 0);
1619e4b17023SJohn Marino       change = (int) pressure_info[i].set_increase - death[cl];
1620e4b17023SJohn Marino       before = MAX (0, max_reg_pressure[i] - ira_available_class_regs[cl]);
1621e4b17023SJohn Marino       after = MAX (0, max_reg_pressure[i] + change
1622e4b17023SJohn Marino 		   - ira_available_class_regs[cl]);
1623e4b17023SJohn Marino       hard_regno = ira_class_hard_regs[cl][0];
1624e4b17023SJohn Marino       gcc_assert (hard_regno >= 0);
1625e4b17023SJohn Marino       mode = reg_raw_mode[hard_regno];
1626e4b17023SJohn Marino       excess_cost_change += ((after - before)
1627e4b17023SJohn Marino 			     * (ira_memory_move_cost[mode][cl][0]
1628e4b17023SJohn Marino 				+ ira_memory_move_cost[mode][cl][1]));
1629e4b17023SJohn Marino     }
1630e4b17023SJohn Marino   INSN_REG_PRESSURE_EXCESS_COST_CHANGE (insn) = excess_cost_change;
1631e4b17023SJohn Marino }
1632e4b17023SJohn Marino 
1633e4b17023SJohn Marino /* Returns a positive value if x is preferred; returns a negative value if
1634e4b17023SJohn Marino    y is preferred.  Should never return 0, since that will make the sort
1635e4b17023SJohn Marino    unstable.  */
1636e4b17023SJohn Marino 
1637e4b17023SJohn Marino static int
rank_for_schedule(const void * x,const void * y)1638e4b17023SJohn Marino rank_for_schedule (const void *x, const void *y)
1639e4b17023SJohn Marino {
1640e4b17023SJohn Marino   rtx tmp = *(const rtx *) y;
1641e4b17023SJohn Marino   rtx tmp2 = *(const rtx *) x;
1642e4b17023SJohn Marino   int tmp_class, tmp2_class;
1643e4b17023SJohn Marino   int val, priority_val, info_val;
1644e4b17023SJohn Marino 
1645e4b17023SJohn Marino   if (MAY_HAVE_DEBUG_INSNS)
1646e4b17023SJohn Marino     {
1647e4b17023SJohn Marino       /* Schedule debug insns as early as possible.  */
1648e4b17023SJohn Marino       if (DEBUG_INSN_P (tmp) && !DEBUG_INSN_P (tmp2))
1649e4b17023SJohn Marino 	return -1;
1650e4b17023SJohn Marino       else if (!DEBUG_INSN_P (tmp) && DEBUG_INSN_P (tmp2))
1651e4b17023SJohn Marino 	return 1;
1652e4b17023SJohn Marino       else if (DEBUG_INSN_P (tmp) && DEBUG_INSN_P (tmp2))
1653e4b17023SJohn Marino 	return INSN_LUID (tmp) - INSN_LUID (tmp2);
1654e4b17023SJohn Marino     }
1655e4b17023SJohn Marino 
1656e4b17023SJohn Marino   /* The insn in a schedule group should be issued the first.  */
1657e4b17023SJohn Marino   if (flag_sched_group_heuristic &&
1658e4b17023SJohn Marino       SCHED_GROUP_P (tmp) != SCHED_GROUP_P (tmp2))
1659e4b17023SJohn Marino     return SCHED_GROUP_P (tmp2) ? 1 : -1;
1660e4b17023SJohn Marino 
1661e4b17023SJohn Marino   /* Make sure that priority of TMP and TMP2 are initialized.  */
1662e4b17023SJohn Marino   gcc_assert (INSN_PRIORITY_KNOWN (tmp) && INSN_PRIORITY_KNOWN (tmp2));
1663e4b17023SJohn Marino 
1664e4b17023SJohn Marino   if (sched_pressure_p)
1665e4b17023SJohn Marino     {
1666e4b17023SJohn Marino       int diff;
1667e4b17023SJohn Marino 
1668e4b17023SJohn Marino       /* Prefer insn whose scheduling results in the smallest register
1669e4b17023SJohn Marino 	 pressure excess.  */
1670e4b17023SJohn Marino       if ((diff = (INSN_REG_PRESSURE_EXCESS_COST_CHANGE (tmp)
1671e4b17023SJohn Marino 		   + (INSN_TICK (tmp) > clock_var
1672e4b17023SJohn Marino 		      ? INSN_TICK (tmp) - clock_var : 0)
1673e4b17023SJohn Marino 		   - INSN_REG_PRESSURE_EXCESS_COST_CHANGE (tmp2)
1674e4b17023SJohn Marino 		   - (INSN_TICK (tmp2) > clock_var
1675e4b17023SJohn Marino 		      ? INSN_TICK (tmp2) - clock_var : 0))) != 0)
1676e4b17023SJohn Marino 	return diff;
1677e4b17023SJohn Marino     }
1678e4b17023SJohn Marino 
1679e4b17023SJohn Marino 
1680e4b17023SJohn Marino   if (sched_pressure_p
1681e4b17023SJohn Marino       && (INSN_TICK (tmp2) > clock_var || INSN_TICK (tmp) > clock_var))
1682e4b17023SJohn Marino     {
1683e4b17023SJohn Marino       if (INSN_TICK (tmp) <= clock_var)
1684e4b17023SJohn Marino 	return -1;
1685e4b17023SJohn Marino       else if (INSN_TICK (tmp2) <= clock_var)
1686e4b17023SJohn Marino 	return 1;
1687e4b17023SJohn Marino       else
1688e4b17023SJohn Marino 	return INSN_TICK (tmp) - INSN_TICK (tmp2);
1689e4b17023SJohn Marino     }
1690e4b17023SJohn Marino 
1691e4b17023SJohn Marino   /* If we are doing backtracking in this schedule, prefer insns that
1692e4b17023SJohn Marino      have forward dependencies with negative cost against an insn that
1693e4b17023SJohn Marino      was already scheduled.  */
1694e4b17023SJohn Marino   if (current_sched_info->flags & DO_BACKTRACKING)
1695e4b17023SJohn Marino     {
1696e4b17023SJohn Marino       priority_val = FEEDS_BACKTRACK_INSN (tmp2) - FEEDS_BACKTRACK_INSN (tmp);
1697e4b17023SJohn Marino       if (priority_val)
1698e4b17023SJohn Marino 	return priority_val;
1699e4b17023SJohn Marino     }
1700e4b17023SJohn Marino 
1701e4b17023SJohn Marino   /* Prefer insn with higher priority.  */
1702e4b17023SJohn Marino   priority_val = INSN_PRIORITY (tmp2) - INSN_PRIORITY (tmp);
1703e4b17023SJohn Marino 
1704e4b17023SJohn Marino   if (flag_sched_critical_path_heuristic && priority_val)
1705e4b17023SJohn Marino     return priority_val;
1706e4b17023SJohn Marino 
1707e4b17023SJohn Marino   /* Prefer speculative insn with greater dependencies weakness.  */
1708e4b17023SJohn Marino   if (flag_sched_spec_insn_heuristic && spec_info)
1709e4b17023SJohn Marino     {
1710e4b17023SJohn Marino       ds_t ds1, ds2;
1711e4b17023SJohn Marino       dw_t dw1, dw2;
1712e4b17023SJohn Marino       int dw;
1713e4b17023SJohn Marino 
1714e4b17023SJohn Marino       ds1 = TODO_SPEC (tmp) & SPECULATIVE;
1715e4b17023SJohn Marino       if (ds1)
1716e4b17023SJohn Marino 	dw1 = ds_weak (ds1);
1717e4b17023SJohn Marino       else
1718e4b17023SJohn Marino 	dw1 = NO_DEP_WEAK;
1719e4b17023SJohn Marino 
1720e4b17023SJohn Marino       ds2 = TODO_SPEC (tmp2) & SPECULATIVE;
1721e4b17023SJohn Marino       if (ds2)
1722e4b17023SJohn Marino 	dw2 = ds_weak (ds2);
1723e4b17023SJohn Marino       else
1724e4b17023SJohn Marino 	dw2 = NO_DEP_WEAK;
1725e4b17023SJohn Marino 
1726e4b17023SJohn Marino       dw = dw2 - dw1;
1727e4b17023SJohn Marino       if (dw > (NO_DEP_WEAK / 8) || dw < -(NO_DEP_WEAK / 8))
1728e4b17023SJohn Marino 	return dw;
1729e4b17023SJohn Marino     }
1730e4b17023SJohn Marino 
1731e4b17023SJohn Marino   info_val = (*current_sched_info->rank) (tmp, tmp2);
1732e4b17023SJohn Marino   if(flag_sched_rank_heuristic && info_val)
1733e4b17023SJohn Marino     return info_val;
1734e4b17023SJohn Marino 
1735e4b17023SJohn Marino   /* Compare insns based on their relation to the last scheduled
1736e4b17023SJohn Marino      non-debug insn.  */
1737e4b17023SJohn Marino   if (flag_sched_last_insn_heuristic && last_nondebug_scheduled_insn)
1738e4b17023SJohn Marino     {
1739e4b17023SJohn Marino       dep_t dep1;
1740e4b17023SJohn Marino       dep_t dep2;
1741e4b17023SJohn Marino       rtx last = last_nondebug_scheduled_insn;
1742e4b17023SJohn Marino 
1743e4b17023SJohn Marino       /* Classify the instructions into three classes:
1744e4b17023SJohn Marino          1) Data dependent on last schedule insn.
1745e4b17023SJohn Marino          2) Anti/Output dependent on last scheduled insn.
1746e4b17023SJohn Marino          3) Independent of last scheduled insn, or has latency of one.
1747e4b17023SJohn Marino          Choose the insn from the highest numbered class if different.  */
1748e4b17023SJohn Marino       dep1 = sd_find_dep_between (last, tmp, true);
1749e4b17023SJohn Marino 
1750e4b17023SJohn Marino       if (dep1 == NULL || dep_cost (dep1) == 1)
1751e4b17023SJohn Marino 	tmp_class = 3;
1752e4b17023SJohn Marino       else if (/* Data dependence.  */
1753e4b17023SJohn Marino 	       DEP_TYPE (dep1) == REG_DEP_TRUE)
1754e4b17023SJohn Marino 	tmp_class = 1;
1755e4b17023SJohn Marino       else
1756e4b17023SJohn Marino 	tmp_class = 2;
1757e4b17023SJohn Marino 
1758e4b17023SJohn Marino       dep2 = sd_find_dep_between (last, tmp2, true);
1759e4b17023SJohn Marino 
1760e4b17023SJohn Marino       if (dep2 == NULL || dep_cost (dep2)  == 1)
1761e4b17023SJohn Marino 	tmp2_class = 3;
1762e4b17023SJohn Marino       else if (/* Data dependence.  */
1763e4b17023SJohn Marino 	       DEP_TYPE (dep2) == REG_DEP_TRUE)
1764e4b17023SJohn Marino 	tmp2_class = 1;
1765e4b17023SJohn Marino       else
1766e4b17023SJohn Marino 	tmp2_class = 2;
1767e4b17023SJohn Marino 
1768e4b17023SJohn Marino       if ((val = tmp2_class - tmp_class))
1769e4b17023SJohn Marino 	return val;
1770e4b17023SJohn Marino     }
1771e4b17023SJohn Marino 
1772e4b17023SJohn Marino   /* Prefer the insn which has more later insns that depend on it.
1773e4b17023SJohn Marino      This gives the scheduler more freedom when scheduling later
1774e4b17023SJohn Marino      instructions at the expense of added register pressure.  */
1775e4b17023SJohn Marino 
1776e4b17023SJohn Marino   val = (dep_list_size (tmp2) - dep_list_size (tmp));
1777e4b17023SJohn Marino 
1778e4b17023SJohn Marino   if (flag_sched_dep_count_heuristic && val != 0)
1779e4b17023SJohn Marino     return val;
1780e4b17023SJohn Marino 
1781e4b17023SJohn Marino   /* If insns are equally good, sort by INSN_LUID (original insn order),
1782e4b17023SJohn Marino      so that we make the sort stable.  This minimizes instruction movement,
1783e4b17023SJohn Marino      thus minimizing sched's effect on debugging and cross-jumping.  */
1784e4b17023SJohn Marino   return INSN_LUID (tmp) - INSN_LUID (tmp2);
1785e4b17023SJohn Marino }
1786e4b17023SJohn Marino 
1787e4b17023SJohn Marino /* Resort the array A in which only element at index N may be out of order.  */
1788e4b17023SJohn Marino 
1789e4b17023SJohn Marino HAIFA_INLINE static void
swap_sort(rtx * a,int n)1790e4b17023SJohn Marino swap_sort (rtx *a, int n)
1791e4b17023SJohn Marino {
1792e4b17023SJohn Marino   rtx insn = a[n - 1];
1793e4b17023SJohn Marino   int i = n - 2;
1794e4b17023SJohn Marino 
1795e4b17023SJohn Marino   while (i >= 0 && rank_for_schedule (a + i, &insn) >= 0)
1796e4b17023SJohn Marino     {
1797e4b17023SJohn Marino       a[i + 1] = a[i];
1798e4b17023SJohn Marino       i -= 1;
1799e4b17023SJohn Marino     }
1800e4b17023SJohn Marino   a[i + 1] = insn;
1801e4b17023SJohn Marino }
1802e4b17023SJohn Marino 
1803e4b17023SJohn Marino /* Add INSN to the insn queue so that it can be executed at least
1804e4b17023SJohn Marino    N_CYCLES after the currently executing insn.  Preserve insns
1805e4b17023SJohn Marino    chain for debugging purposes.  REASON will be printed in debugging
1806e4b17023SJohn Marino    output.  */
1807e4b17023SJohn Marino 
1808e4b17023SJohn Marino HAIFA_INLINE static void
queue_insn(rtx insn,int n_cycles,const char * reason)1809e4b17023SJohn Marino queue_insn (rtx insn, int n_cycles, const char *reason)
1810e4b17023SJohn Marino {
1811e4b17023SJohn Marino   int next_q = NEXT_Q_AFTER (q_ptr, n_cycles);
1812e4b17023SJohn Marino   rtx link = alloc_INSN_LIST (insn, insn_queue[next_q]);
1813e4b17023SJohn Marino   int new_tick;
1814e4b17023SJohn Marino 
1815e4b17023SJohn Marino   gcc_assert (n_cycles <= max_insn_queue_index);
1816e4b17023SJohn Marino   gcc_assert (!DEBUG_INSN_P (insn));
1817e4b17023SJohn Marino 
1818e4b17023SJohn Marino   insn_queue[next_q] = link;
1819e4b17023SJohn Marino   q_size += 1;
1820e4b17023SJohn Marino 
1821e4b17023SJohn Marino   if (sched_verbose >= 2)
1822e4b17023SJohn Marino     {
1823e4b17023SJohn Marino       fprintf (sched_dump, ";;\t\tReady-->Q: insn %s: ",
1824e4b17023SJohn Marino 	       (*current_sched_info->print_insn) (insn, 0));
1825e4b17023SJohn Marino 
1826e4b17023SJohn Marino       fprintf (sched_dump, "queued for %d cycles (%s).\n", n_cycles, reason);
1827e4b17023SJohn Marino     }
1828e4b17023SJohn Marino 
1829e4b17023SJohn Marino   QUEUE_INDEX (insn) = next_q;
1830e4b17023SJohn Marino 
1831e4b17023SJohn Marino   if (current_sched_info->flags & DO_BACKTRACKING)
1832e4b17023SJohn Marino     {
1833e4b17023SJohn Marino       new_tick = clock_var + n_cycles;
1834e4b17023SJohn Marino       if (INSN_TICK (insn) == INVALID_TICK || INSN_TICK (insn) < new_tick)
1835e4b17023SJohn Marino 	INSN_TICK (insn) = new_tick;
1836e4b17023SJohn Marino 
1837e4b17023SJohn Marino       if (INSN_EXACT_TICK (insn) != INVALID_TICK
1838e4b17023SJohn Marino 	  && INSN_EXACT_TICK (insn) < clock_var + n_cycles)
1839e4b17023SJohn Marino 	{
1840e4b17023SJohn Marino 	  must_backtrack = true;
1841e4b17023SJohn Marino 	  if (sched_verbose >= 2)
1842e4b17023SJohn Marino 	    fprintf (sched_dump, ";;\t\tcausing a backtrack.\n");
1843e4b17023SJohn Marino 	}
1844e4b17023SJohn Marino     }
1845e4b17023SJohn Marino }
1846e4b17023SJohn Marino 
1847e4b17023SJohn Marino /* Remove INSN from queue.  */
1848e4b17023SJohn Marino static void
queue_remove(rtx insn)1849e4b17023SJohn Marino queue_remove (rtx insn)
1850e4b17023SJohn Marino {
1851e4b17023SJohn Marino   gcc_assert (QUEUE_INDEX (insn) >= 0);
1852e4b17023SJohn Marino   remove_free_INSN_LIST_elem (insn, &insn_queue[QUEUE_INDEX (insn)]);
1853e4b17023SJohn Marino   q_size--;
1854e4b17023SJohn Marino   QUEUE_INDEX (insn) = QUEUE_NOWHERE;
1855e4b17023SJohn Marino }
1856e4b17023SJohn Marino 
1857e4b17023SJohn Marino /* Return a pointer to the bottom of the ready list, i.e. the insn
1858e4b17023SJohn Marino    with the lowest priority.  */
1859e4b17023SJohn Marino 
1860e4b17023SJohn Marino rtx *
ready_lastpos(struct ready_list * ready)1861e4b17023SJohn Marino ready_lastpos (struct ready_list *ready)
1862e4b17023SJohn Marino {
1863e4b17023SJohn Marino   gcc_assert (ready->n_ready >= 1);
1864e4b17023SJohn Marino   return ready->vec + ready->first - ready->n_ready + 1;
1865e4b17023SJohn Marino }
1866e4b17023SJohn Marino 
1867e4b17023SJohn Marino /* Add an element INSN to the ready list so that it ends up with the
1868e4b17023SJohn Marino    lowest/highest priority depending on FIRST_P.  */
1869e4b17023SJohn Marino 
1870e4b17023SJohn Marino HAIFA_INLINE static void
ready_add(struct ready_list * ready,rtx insn,bool first_p)1871e4b17023SJohn Marino ready_add (struct ready_list *ready, rtx insn, bool first_p)
1872e4b17023SJohn Marino {
1873e4b17023SJohn Marino   if (!first_p)
1874e4b17023SJohn Marino     {
1875e4b17023SJohn Marino       if (ready->first == ready->n_ready)
1876e4b17023SJohn Marino 	{
1877e4b17023SJohn Marino 	  memmove (ready->vec + ready->veclen - ready->n_ready,
1878e4b17023SJohn Marino 		   ready_lastpos (ready),
1879e4b17023SJohn Marino 		   ready->n_ready * sizeof (rtx));
1880e4b17023SJohn Marino 	  ready->first = ready->veclen - 1;
1881e4b17023SJohn Marino 	}
1882e4b17023SJohn Marino       ready->vec[ready->first - ready->n_ready] = insn;
1883e4b17023SJohn Marino     }
1884e4b17023SJohn Marino   else
1885e4b17023SJohn Marino     {
1886e4b17023SJohn Marino       if (ready->first == ready->veclen - 1)
1887e4b17023SJohn Marino 	{
1888e4b17023SJohn Marino 	  if (ready->n_ready)
1889e4b17023SJohn Marino 	    /* ready_lastpos() fails when called with (ready->n_ready == 0).  */
1890e4b17023SJohn Marino 	    memmove (ready->vec + ready->veclen - ready->n_ready - 1,
1891e4b17023SJohn Marino 		     ready_lastpos (ready),
1892e4b17023SJohn Marino 		     ready->n_ready * sizeof (rtx));
1893e4b17023SJohn Marino 	  ready->first = ready->veclen - 2;
1894e4b17023SJohn Marino 	}
1895e4b17023SJohn Marino       ready->vec[++(ready->first)] = insn;
1896e4b17023SJohn Marino     }
1897e4b17023SJohn Marino 
1898e4b17023SJohn Marino   ready->n_ready++;
1899e4b17023SJohn Marino   if (DEBUG_INSN_P (insn))
1900e4b17023SJohn Marino     ready->n_debug++;
1901e4b17023SJohn Marino 
1902e4b17023SJohn Marino   gcc_assert (QUEUE_INDEX (insn) != QUEUE_READY);
1903e4b17023SJohn Marino   QUEUE_INDEX (insn) = QUEUE_READY;
1904e4b17023SJohn Marino 
1905e4b17023SJohn Marino   if (INSN_EXACT_TICK (insn) != INVALID_TICK
1906e4b17023SJohn Marino       && INSN_EXACT_TICK (insn) < clock_var)
1907e4b17023SJohn Marino     {
1908e4b17023SJohn Marino       must_backtrack = true;
1909e4b17023SJohn Marino     }
1910e4b17023SJohn Marino }
1911e4b17023SJohn Marino 
1912e4b17023SJohn Marino /* Remove the element with the highest priority from the ready list and
1913e4b17023SJohn Marino    return it.  */
1914e4b17023SJohn Marino 
1915e4b17023SJohn Marino HAIFA_INLINE static rtx
ready_remove_first(struct ready_list * ready)1916e4b17023SJohn Marino ready_remove_first (struct ready_list *ready)
1917e4b17023SJohn Marino {
1918e4b17023SJohn Marino   rtx t;
1919e4b17023SJohn Marino 
1920e4b17023SJohn Marino   gcc_assert (ready->n_ready);
1921e4b17023SJohn Marino   t = ready->vec[ready->first--];
1922e4b17023SJohn Marino   ready->n_ready--;
1923e4b17023SJohn Marino   if (DEBUG_INSN_P (t))
1924e4b17023SJohn Marino     ready->n_debug--;
1925e4b17023SJohn Marino   /* If the queue becomes empty, reset it.  */
1926e4b17023SJohn Marino   if (ready->n_ready == 0)
1927e4b17023SJohn Marino     ready->first = ready->veclen - 1;
1928e4b17023SJohn Marino 
1929e4b17023SJohn Marino   gcc_assert (QUEUE_INDEX (t) == QUEUE_READY);
1930e4b17023SJohn Marino   QUEUE_INDEX (t) = QUEUE_NOWHERE;
1931e4b17023SJohn Marino 
1932e4b17023SJohn Marino   return t;
1933e4b17023SJohn Marino }
1934e4b17023SJohn Marino 
1935e4b17023SJohn Marino /* The following code implements multi-pass scheduling for the first
1936e4b17023SJohn Marino    cycle.  In other words, we will try to choose ready insn which
1937e4b17023SJohn Marino    permits to start maximum number of insns on the same cycle.  */
1938e4b17023SJohn Marino 
1939e4b17023SJohn Marino /* Return a pointer to the element INDEX from the ready.  INDEX for
1940e4b17023SJohn Marino    insn with the highest priority is 0, and the lowest priority has
1941e4b17023SJohn Marino    N_READY - 1.  */
1942e4b17023SJohn Marino 
1943e4b17023SJohn Marino rtx
ready_element(struct ready_list * ready,int index)1944e4b17023SJohn Marino ready_element (struct ready_list *ready, int index)
1945e4b17023SJohn Marino {
1946e4b17023SJohn Marino   gcc_assert (ready->n_ready && index < ready->n_ready);
1947e4b17023SJohn Marino 
1948e4b17023SJohn Marino   return ready->vec[ready->first - index];
1949e4b17023SJohn Marino }
1950e4b17023SJohn Marino 
1951e4b17023SJohn Marino /* Remove the element INDEX from the ready list and return it.  INDEX
1952e4b17023SJohn Marino    for insn with the highest priority is 0, and the lowest priority
1953e4b17023SJohn Marino    has N_READY - 1.  */
1954e4b17023SJohn Marino 
1955e4b17023SJohn Marino HAIFA_INLINE static rtx
ready_remove(struct ready_list * ready,int index)1956e4b17023SJohn Marino ready_remove (struct ready_list *ready, int index)
1957e4b17023SJohn Marino {
1958e4b17023SJohn Marino   rtx t;
1959e4b17023SJohn Marino   int i;
1960e4b17023SJohn Marino 
1961e4b17023SJohn Marino   if (index == 0)
1962e4b17023SJohn Marino     return ready_remove_first (ready);
1963e4b17023SJohn Marino   gcc_assert (ready->n_ready && index < ready->n_ready);
1964e4b17023SJohn Marino   t = ready->vec[ready->first - index];
1965e4b17023SJohn Marino   ready->n_ready--;
1966e4b17023SJohn Marino   if (DEBUG_INSN_P (t))
1967e4b17023SJohn Marino     ready->n_debug--;
1968e4b17023SJohn Marino   for (i = index; i < ready->n_ready; i++)
1969e4b17023SJohn Marino     ready->vec[ready->first - i] = ready->vec[ready->first - i - 1];
1970e4b17023SJohn Marino   QUEUE_INDEX (t) = QUEUE_NOWHERE;
1971e4b17023SJohn Marino   return t;
1972e4b17023SJohn Marino }
1973e4b17023SJohn Marino 
1974e4b17023SJohn Marino /* Remove INSN from the ready list.  */
1975e4b17023SJohn Marino static void
ready_remove_insn(rtx insn)1976e4b17023SJohn Marino ready_remove_insn (rtx insn)
1977e4b17023SJohn Marino {
1978e4b17023SJohn Marino   int i;
1979e4b17023SJohn Marino 
1980e4b17023SJohn Marino   for (i = 0; i < readyp->n_ready; i++)
1981e4b17023SJohn Marino     if (ready_element (readyp, i) == insn)
1982e4b17023SJohn Marino       {
1983e4b17023SJohn Marino         ready_remove (readyp, i);
1984e4b17023SJohn Marino         return;
1985e4b17023SJohn Marino       }
1986e4b17023SJohn Marino   gcc_unreachable ();
1987e4b17023SJohn Marino }
1988e4b17023SJohn Marino 
1989e4b17023SJohn Marino /* Sort the ready list READY by ascending priority, using the SCHED_SORT
1990e4b17023SJohn Marino    macro.  */
1991e4b17023SJohn Marino 
1992e4b17023SJohn Marino void
ready_sort(struct ready_list * ready)1993e4b17023SJohn Marino ready_sort (struct ready_list *ready)
1994e4b17023SJohn Marino {
1995e4b17023SJohn Marino   int i;
1996e4b17023SJohn Marino   rtx *first = ready_lastpos (ready);
1997e4b17023SJohn Marino 
1998e4b17023SJohn Marino   if (sched_pressure_p)
1999e4b17023SJohn Marino     {
2000e4b17023SJohn Marino       for (i = 0; i < ready->n_ready; i++)
2001e4b17023SJohn Marino 	if (!DEBUG_INSN_P (first[i]))
2002e4b17023SJohn Marino 	  setup_insn_reg_pressure_info (first[i]);
2003e4b17023SJohn Marino     }
2004e4b17023SJohn Marino   SCHED_SORT (first, ready->n_ready);
2005e4b17023SJohn Marino }
2006e4b17023SJohn Marino 
2007e4b17023SJohn Marino /* PREV is an insn that is ready to execute.  Adjust its priority if that
2008e4b17023SJohn Marino    will help shorten or lengthen register lifetimes as appropriate.  Also
2009e4b17023SJohn Marino    provide a hook for the target to tweak itself.  */
2010e4b17023SJohn Marino 
2011e4b17023SJohn Marino HAIFA_INLINE static void
adjust_priority(rtx prev)2012e4b17023SJohn Marino adjust_priority (rtx prev)
2013e4b17023SJohn Marino {
2014e4b17023SJohn Marino   /* ??? There used to be code here to try and estimate how an insn
2015e4b17023SJohn Marino      affected register lifetimes, but it did it by looking at REG_DEAD
2016e4b17023SJohn Marino      notes, which we removed in schedule_region.  Nor did it try to
2017e4b17023SJohn Marino      take into account register pressure or anything useful like that.
2018e4b17023SJohn Marino 
2019e4b17023SJohn Marino      Revisit when we have a machine model to work with and not before.  */
2020e4b17023SJohn Marino 
2021e4b17023SJohn Marino   if (targetm.sched.adjust_priority)
2022e4b17023SJohn Marino     INSN_PRIORITY (prev) =
2023e4b17023SJohn Marino       targetm.sched.adjust_priority (prev, INSN_PRIORITY (prev));
2024e4b17023SJohn Marino }
2025e4b17023SJohn Marino 
2026e4b17023SJohn Marino /* Advance DFA state STATE on one cycle.  */
2027e4b17023SJohn Marino void
advance_state(state_t state)2028e4b17023SJohn Marino advance_state (state_t state)
2029e4b17023SJohn Marino {
2030e4b17023SJohn Marino   if (targetm.sched.dfa_pre_advance_cycle)
2031e4b17023SJohn Marino     targetm.sched.dfa_pre_advance_cycle ();
2032e4b17023SJohn Marino 
2033e4b17023SJohn Marino   if (targetm.sched.dfa_pre_cycle_insn)
2034e4b17023SJohn Marino     state_transition (state,
2035e4b17023SJohn Marino 		      targetm.sched.dfa_pre_cycle_insn ());
2036e4b17023SJohn Marino 
2037e4b17023SJohn Marino   state_transition (state, NULL);
2038e4b17023SJohn Marino 
2039e4b17023SJohn Marino   if (targetm.sched.dfa_post_cycle_insn)
2040e4b17023SJohn Marino     state_transition (state,
2041e4b17023SJohn Marino 		      targetm.sched.dfa_post_cycle_insn ());
2042e4b17023SJohn Marino 
2043e4b17023SJohn Marino   if (targetm.sched.dfa_post_advance_cycle)
2044e4b17023SJohn Marino     targetm.sched.dfa_post_advance_cycle ();
2045e4b17023SJohn Marino }
2046e4b17023SJohn Marino 
2047e4b17023SJohn Marino /* Advance time on one cycle.  */
2048e4b17023SJohn Marino HAIFA_INLINE static void
advance_one_cycle(void)2049e4b17023SJohn Marino advance_one_cycle (void)
2050e4b17023SJohn Marino {
2051e4b17023SJohn Marino   advance_state (curr_state);
2052e4b17023SJohn Marino   if (sched_verbose >= 6)
2053e4b17023SJohn Marino     fprintf (sched_dump, ";;\tAdvanced a state.\n");
2054e4b17023SJohn Marino }
2055e4b17023SJohn Marino 
2056e4b17023SJohn Marino /* Update register pressure after scheduling INSN.  */
2057e4b17023SJohn Marino static void
update_register_pressure(rtx insn)2058e4b17023SJohn Marino update_register_pressure (rtx insn)
2059e4b17023SJohn Marino {
2060e4b17023SJohn Marino   struct reg_use_data *use;
2061e4b17023SJohn Marino   struct reg_set_data *set;
2062e4b17023SJohn Marino 
2063e4b17023SJohn Marino   gcc_checking_assert (!DEBUG_INSN_P (insn));
2064e4b17023SJohn Marino 
2065e4b17023SJohn Marino   for (use = INSN_REG_USE_LIST (insn); use != NULL; use = use->next_insn_use)
2066e4b17023SJohn Marino     if (dying_use_p (use) && bitmap_bit_p (curr_reg_live, use->regno))
2067e4b17023SJohn Marino       mark_regno_birth_or_death (use->regno, false);
2068e4b17023SJohn Marino   for (set = INSN_REG_SET_LIST (insn); set != NULL; set = set->next_insn_set)
2069e4b17023SJohn Marino     mark_regno_birth_or_death (set->regno, true);
2070e4b17023SJohn Marino }
2071e4b17023SJohn Marino 
2072e4b17023SJohn Marino /* Set up or update (if UPDATE_P) max register pressure (see its
2073e4b17023SJohn Marino    meaning in sched-int.h::_haifa_insn_data) for all current BB insns
2074e4b17023SJohn Marino    after insn AFTER.  */
2075e4b17023SJohn Marino static void
setup_insn_max_reg_pressure(rtx after,bool update_p)2076e4b17023SJohn Marino setup_insn_max_reg_pressure (rtx after, bool update_p)
2077e4b17023SJohn Marino {
2078e4b17023SJohn Marino   int i, p;
2079e4b17023SJohn Marino   bool eq_p;
2080e4b17023SJohn Marino   rtx insn;
2081e4b17023SJohn Marino   static int max_reg_pressure[N_REG_CLASSES];
2082e4b17023SJohn Marino 
2083e4b17023SJohn Marino   save_reg_pressure ();
2084e4b17023SJohn Marino   for (i = 0; i < ira_pressure_classes_num; i++)
2085e4b17023SJohn Marino     max_reg_pressure[ira_pressure_classes[i]]
2086e4b17023SJohn Marino       = curr_reg_pressure[ira_pressure_classes[i]];
2087e4b17023SJohn Marino   for (insn = NEXT_INSN (after);
2088e4b17023SJohn Marino        insn != NULL_RTX && ! BARRIER_P (insn)
2089e4b17023SJohn Marino 	 && BLOCK_FOR_INSN (insn) == BLOCK_FOR_INSN (after);
2090e4b17023SJohn Marino        insn = NEXT_INSN (insn))
2091e4b17023SJohn Marino     if (NONDEBUG_INSN_P (insn))
2092e4b17023SJohn Marino       {
2093e4b17023SJohn Marino 	eq_p = true;
2094e4b17023SJohn Marino 	for (i = 0; i < ira_pressure_classes_num; i++)
2095e4b17023SJohn Marino 	  {
2096e4b17023SJohn Marino 	    p = max_reg_pressure[ira_pressure_classes[i]];
2097e4b17023SJohn Marino 	    if (INSN_MAX_REG_PRESSURE (insn)[i] != p)
2098e4b17023SJohn Marino 	      {
2099e4b17023SJohn Marino 		eq_p = false;
2100e4b17023SJohn Marino 		INSN_MAX_REG_PRESSURE (insn)[i]
2101e4b17023SJohn Marino 		  = max_reg_pressure[ira_pressure_classes[i]];
2102e4b17023SJohn Marino 	      }
2103e4b17023SJohn Marino 	  }
2104e4b17023SJohn Marino 	if (update_p && eq_p)
2105e4b17023SJohn Marino 	  break;
2106e4b17023SJohn Marino 	update_register_pressure (insn);
2107e4b17023SJohn Marino 	for (i = 0; i < ira_pressure_classes_num; i++)
2108e4b17023SJohn Marino 	  if (max_reg_pressure[ira_pressure_classes[i]]
2109e4b17023SJohn Marino 	      < curr_reg_pressure[ira_pressure_classes[i]])
2110e4b17023SJohn Marino 	    max_reg_pressure[ira_pressure_classes[i]]
2111e4b17023SJohn Marino 	      = curr_reg_pressure[ira_pressure_classes[i]];
2112e4b17023SJohn Marino       }
2113e4b17023SJohn Marino   restore_reg_pressure ();
2114e4b17023SJohn Marino }
2115e4b17023SJohn Marino 
2116e4b17023SJohn Marino /* Update the current register pressure after scheduling INSN.  Update
2117e4b17023SJohn Marino    also max register pressure for unscheduled insns of the current
2118e4b17023SJohn Marino    BB.  */
2119e4b17023SJohn Marino static void
update_reg_and_insn_max_reg_pressure(rtx insn)2120e4b17023SJohn Marino update_reg_and_insn_max_reg_pressure (rtx insn)
2121e4b17023SJohn Marino {
2122e4b17023SJohn Marino   int i;
2123e4b17023SJohn Marino   int before[N_REG_CLASSES];
2124e4b17023SJohn Marino 
2125e4b17023SJohn Marino   for (i = 0; i < ira_pressure_classes_num; i++)
2126e4b17023SJohn Marino     before[i] = curr_reg_pressure[ira_pressure_classes[i]];
2127e4b17023SJohn Marino   update_register_pressure (insn);
2128e4b17023SJohn Marino   for (i = 0; i < ira_pressure_classes_num; i++)
2129e4b17023SJohn Marino     if (curr_reg_pressure[ira_pressure_classes[i]] != before[i])
2130e4b17023SJohn Marino       break;
2131e4b17023SJohn Marino   if (i < ira_pressure_classes_num)
2132e4b17023SJohn Marino     setup_insn_max_reg_pressure (insn, true);
2133e4b17023SJohn Marino }
2134e4b17023SJohn Marino 
2135e4b17023SJohn Marino /* Set up register pressure at the beginning of basic block BB whose
2136e4b17023SJohn Marino    insns starting after insn AFTER.  Set up also max register pressure
2137e4b17023SJohn Marino    for all insns of the basic block.  */
2138e4b17023SJohn Marino void
sched_setup_bb_reg_pressure_info(basic_block bb,rtx after)2139e4b17023SJohn Marino sched_setup_bb_reg_pressure_info (basic_block bb, rtx after)
2140e4b17023SJohn Marino {
2141e4b17023SJohn Marino   gcc_assert (sched_pressure_p);
2142e4b17023SJohn Marino   initiate_bb_reg_pressure_info (bb);
2143e4b17023SJohn Marino   setup_insn_max_reg_pressure (after, false);
2144e4b17023SJohn Marino }
2145e4b17023SJohn Marino 
2146e4b17023SJohn Marino /* If doing predication while scheduling, verify whether INSN, which
2147e4b17023SJohn Marino    has just been scheduled, clobbers the conditions of any
2148e4b17023SJohn Marino    instructions that must be predicated in order to break their
2149e4b17023SJohn Marino    dependencies.  If so, remove them from the queues so that they will
2150e4b17023SJohn Marino    only be scheduled once their control dependency is resolved.  */
2151e4b17023SJohn Marino 
2152e4b17023SJohn Marino static void
check_clobbered_conditions(rtx insn)2153e4b17023SJohn Marino check_clobbered_conditions (rtx insn)
2154e4b17023SJohn Marino {
2155e4b17023SJohn Marino   HARD_REG_SET t;
2156e4b17023SJohn Marino   int i;
2157e4b17023SJohn Marino 
2158e4b17023SJohn Marino   if ((current_sched_info->flags & DO_PREDICATION) == 0)
2159e4b17023SJohn Marino     return;
2160e4b17023SJohn Marino 
2161e4b17023SJohn Marino   find_all_hard_reg_sets (insn, &t);
2162e4b17023SJohn Marino 
2163e4b17023SJohn Marino  restart:
2164e4b17023SJohn Marino   for (i = 0; i < ready.n_ready; i++)
2165e4b17023SJohn Marino     {
2166e4b17023SJohn Marino       rtx x = ready_element (&ready, i);
2167e4b17023SJohn Marino       if (TODO_SPEC (x) == DEP_CONTROL && cond_clobbered_p (x, t))
2168e4b17023SJohn Marino 	{
2169e4b17023SJohn Marino 	  ready_remove_insn (x);
2170e4b17023SJohn Marino 	  goto restart;
2171e4b17023SJohn Marino 	}
2172e4b17023SJohn Marino     }
2173e4b17023SJohn Marino   for (i = 0; i <= max_insn_queue_index; i++)
2174e4b17023SJohn Marino     {
2175e4b17023SJohn Marino       rtx link;
2176e4b17023SJohn Marino       int q = NEXT_Q_AFTER (q_ptr, i);
2177e4b17023SJohn Marino 
2178e4b17023SJohn Marino     restart_queue:
2179e4b17023SJohn Marino       for (link = insn_queue[q]; link; link = XEXP (link, 1))
2180e4b17023SJohn Marino 	{
2181e4b17023SJohn Marino 	  rtx x = XEXP (link, 0);
2182e4b17023SJohn Marino 	  if (TODO_SPEC (x) == DEP_CONTROL && cond_clobbered_p (x, t))
2183e4b17023SJohn Marino 	    {
2184e4b17023SJohn Marino 	      queue_remove (x);
2185e4b17023SJohn Marino 	      goto restart_queue;
2186e4b17023SJohn Marino 	    }
2187e4b17023SJohn Marino 	}
2188e4b17023SJohn Marino     }
2189e4b17023SJohn Marino }
2190e4b17023SJohn Marino 
2191e4b17023SJohn Marino /* A structure that holds local state for the loop in schedule_block.  */
2192e4b17023SJohn Marino struct sched_block_state
2193e4b17023SJohn Marino {
2194e4b17023SJohn Marino   /* True if no real insns have been scheduled in the current cycle.  */
2195e4b17023SJohn Marino   bool first_cycle_insn_p;
2196e4b17023SJohn Marino   /* True if a shadow insn has been scheduled in the current cycle, which
2197e4b17023SJohn Marino      means that no more normal insns can be issued.  */
2198e4b17023SJohn Marino   bool shadows_only_p;
2199e4b17023SJohn Marino   /* True if we're winding down a modulo schedule, which means that we only
2200e4b17023SJohn Marino      issue insns with INSN_EXACT_TICK set.  */
2201e4b17023SJohn Marino   bool modulo_epilogue;
2202e4b17023SJohn Marino   /* Initialized with the machine's issue rate every cycle, and updated
2203e4b17023SJohn Marino      by calls to the variable_issue hook.  */
2204e4b17023SJohn Marino   int can_issue_more;
2205e4b17023SJohn Marino };
2206e4b17023SJohn Marino 
2207e4b17023SJohn Marino /* INSN is the "currently executing insn".  Launch each insn which was
2208e4b17023SJohn Marino    waiting on INSN.  READY is the ready list which contains the insns
2209e4b17023SJohn Marino    that are ready to fire.  CLOCK is the current cycle.  The function
2210e4b17023SJohn Marino    returns necessary cycle advance after issuing the insn (it is not
2211e4b17023SJohn Marino    zero for insns in a schedule group).  */
2212e4b17023SJohn Marino 
2213e4b17023SJohn Marino static int
schedule_insn(rtx insn)2214e4b17023SJohn Marino schedule_insn (rtx insn)
2215e4b17023SJohn Marino {
2216e4b17023SJohn Marino   sd_iterator_def sd_it;
2217e4b17023SJohn Marino   dep_t dep;
2218e4b17023SJohn Marino   int i;
2219e4b17023SJohn Marino   int advance = 0;
2220e4b17023SJohn Marino 
2221e4b17023SJohn Marino   if (sched_verbose >= 1)
2222e4b17023SJohn Marino     {
2223e4b17023SJohn Marino       struct reg_pressure_data *pressure_info;
2224e4b17023SJohn Marino       char buf[2048];
2225e4b17023SJohn Marino 
2226e4b17023SJohn Marino       print_insn (buf, insn, 0);
2227e4b17023SJohn Marino       buf[40] = 0;
2228e4b17023SJohn Marino       fprintf (sched_dump, ";;\t%3i--> %-40s:", clock_var, buf);
2229e4b17023SJohn Marino 
2230e4b17023SJohn Marino       if (recog_memoized (insn) < 0)
2231e4b17023SJohn Marino 	fprintf (sched_dump, "nothing");
2232e4b17023SJohn Marino       else
2233e4b17023SJohn Marino 	print_reservation (sched_dump, insn);
2234e4b17023SJohn Marino       pressure_info = INSN_REG_PRESSURE (insn);
2235e4b17023SJohn Marino       if (pressure_info != NULL)
2236e4b17023SJohn Marino 	{
2237e4b17023SJohn Marino 	  fputc (':', sched_dump);
2238e4b17023SJohn Marino 	  for (i = 0; i < ira_pressure_classes_num; i++)
2239e4b17023SJohn Marino 	    fprintf (sched_dump, "%s%+d(%d)",
2240e4b17023SJohn Marino 		     reg_class_names[ira_pressure_classes[i]],
2241e4b17023SJohn Marino 		     pressure_info[i].set_increase, pressure_info[i].change);
2242e4b17023SJohn Marino 	}
2243e4b17023SJohn Marino       fputc ('\n', sched_dump);
2244e4b17023SJohn Marino     }
2245e4b17023SJohn Marino 
2246e4b17023SJohn Marino   if (sched_pressure_p && !DEBUG_INSN_P (insn))
2247e4b17023SJohn Marino     update_reg_and_insn_max_reg_pressure (insn);
2248e4b17023SJohn Marino 
2249e4b17023SJohn Marino   /* Scheduling instruction should have all its dependencies resolved and
2250e4b17023SJohn Marino      should have been removed from the ready list.  */
2251e4b17023SJohn Marino   gcc_assert (sd_lists_empty_p (insn, SD_LIST_HARD_BACK));
2252e4b17023SJohn Marino 
2253e4b17023SJohn Marino   /* Reset debug insns invalidated by moving this insn.  */
2254e4b17023SJohn Marino   if (MAY_HAVE_DEBUG_INSNS && !DEBUG_INSN_P (insn))
2255e4b17023SJohn Marino     for (sd_it = sd_iterator_start (insn, SD_LIST_BACK);
2256e4b17023SJohn Marino 	 sd_iterator_cond (&sd_it, &dep);)
2257e4b17023SJohn Marino       {
2258e4b17023SJohn Marino 	rtx dbg = DEP_PRO (dep);
2259e4b17023SJohn Marino 	struct reg_use_data *use, *next;
2260e4b17023SJohn Marino 
2261e4b17023SJohn Marino 	if (DEP_STATUS (dep) & DEP_CANCELLED)
2262e4b17023SJohn Marino 	  {
2263e4b17023SJohn Marino 	    sd_iterator_next (&sd_it);
2264e4b17023SJohn Marino 	    continue;
2265e4b17023SJohn Marino 	  }
2266e4b17023SJohn Marino 
2267e4b17023SJohn Marino 	gcc_assert (DEBUG_INSN_P (dbg));
2268e4b17023SJohn Marino 
2269e4b17023SJohn Marino 	if (sched_verbose >= 6)
2270e4b17023SJohn Marino 	  fprintf (sched_dump, ";;\t\tresetting: debug insn %d\n",
2271e4b17023SJohn Marino 		   INSN_UID (dbg));
2272e4b17023SJohn Marino 
2273e4b17023SJohn Marino 	/* ??? Rather than resetting the debug insn, we might be able
2274e4b17023SJohn Marino 	   to emit a debug temp before the just-scheduled insn, but
2275e4b17023SJohn Marino 	   this would involve checking that the expression at the
2276e4b17023SJohn Marino 	   point of the debug insn is equivalent to the expression
2277e4b17023SJohn Marino 	   before the just-scheduled insn.  They might not be: the
2278e4b17023SJohn Marino 	   expression in the debug insn may depend on other insns not
2279e4b17023SJohn Marino 	   yet scheduled that set MEMs, REGs or even other debug
2280e4b17023SJohn Marino 	   insns.  It's not clear that attempting to preserve debug
2281e4b17023SJohn Marino 	   information in these cases is worth the effort, given how
2282e4b17023SJohn Marino 	   uncommon these resets are and the likelihood that the debug
2283e4b17023SJohn Marino 	   temps introduced won't survive the schedule change.  */
2284e4b17023SJohn Marino 	INSN_VAR_LOCATION_LOC (dbg) = gen_rtx_UNKNOWN_VAR_LOC ();
2285e4b17023SJohn Marino 	df_insn_rescan (dbg);
2286e4b17023SJohn Marino 
2287e4b17023SJohn Marino 	/* Unknown location doesn't use any registers.  */
2288e4b17023SJohn Marino 	for (use = INSN_REG_USE_LIST (dbg); use != NULL; use = next)
2289e4b17023SJohn Marino 	  {
2290e4b17023SJohn Marino 	    struct reg_use_data *prev = use;
2291e4b17023SJohn Marino 
2292e4b17023SJohn Marino 	    /* Remove use from the cyclic next_regno_use chain first.  */
2293e4b17023SJohn Marino 	    while (prev->next_regno_use != use)
2294e4b17023SJohn Marino 	      prev = prev->next_regno_use;
2295e4b17023SJohn Marino 	    prev->next_regno_use = use->next_regno_use;
2296e4b17023SJohn Marino 	    next = use->next_insn_use;
2297e4b17023SJohn Marino 	    free (use);
2298e4b17023SJohn Marino 	  }
2299e4b17023SJohn Marino 	INSN_REG_USE_LIST (dbg) = NULL;
2300e4b17023SJohn Marino 
2301e4b17023SJohn Marino 	/* We delete rather than resolve these deps, otherwise we
2302e4b17023SJohn Marino 	   crash in sched_free_deps(), because forward deps are
2303e4b17023SJohn Marino 	   expected to be released before backward deps.  */
2304e4b17023SJohn Marino 	sd_delete_dep (sd_it);
2305e4b17023SJohn Marino       }
2306e4b17023SJohn Marino 
2307e4b17023SJohn Marino   gcc_assert (QUEUE_INDEX (insn) == QUEUE_NOWHERE);
2308e4b17023SJohn Marino   QUEUE_INDEX (insn) = QUEUE_SCHEDULED;
2309e4b17023SJohn Marino 
2310e4b17023SJohn Marino   gcc_assert (INSN_TICK (insn) >= MIN_TICK);
2311e4b17023SJohn Marino   if (INSN_TICK (insn) > clock_var)
2312e4b17023SJohn Marino     /* INSN has been prematurely moved from the queue to the ready list.
2313e4b17023SJohn Marino        This is possible only if following flag is set.  */
2314e4b17023SJohn Marino     gcc_assert (flag_sched_stalled_insns);
2315e4b17023SJohn Marino 
2316e4b17023SJohn Marino   /* ??? Probably, if INSN is scheduled prematurely, we should leave
2317e4b17023SJohn Marino      INSN_TICK untouched.  This is a machine-dependent issue, actually.  */
2318e4b17023SJohn Marino   INSN_TICK (insn) = clock_var;
2319e4b17023SJohn Marino 
2320e4b17023SJohn Marino   check_clobbered_conditions (insn);
2321e4b17023SJohn Marino 
2322e4b17023SJohn Marino   /* Update dependent instructions.  */
2323e4b17023SJohn Marino   for (sd_it = sd_iterator_start (insn, SD_LIST_FORW);
2324e4b17023SJohn Marino        sd_iterator_cond (&sd_it, &dep);)
2325e4b17023SJohn Marino     {
2326e4b17023SJohn Marino       rtx next = DEP_CON (dep);
2327e4b17023SJohn Marino       bool cancelled = (DEP_STATUS (dep) & DEP_CANCELLED) != 0;
2328e4b17023SJohn Marino 
2329e4b17023SJohn Marino       /* Resolve the dependence between INSN and NEXT.
2330e4b17023SJohn Marino 	 sd_resolve_dep () moves current dep to another list thus
2331e4b17023SJohn Marino 	 advancing the iterator.  */
2332e4b17023SJohn Marino       sd_resolve_dep (sd_it);
2333e4b17023SJohn Marino 
2334e4b17023SJohn Marino       if (cancelled)
2335e4b17023SJohn Marino 	{
2336e4b17023SJohn Marino 	  if (QUEUE_INDEX (next) != QUEUE_SCHEDULED)
2337e4b17023SJohn Marino 	    {
2338e4b17023SJohn Marino 	      int tick = INSN_TICK (next);
2339e4b17023SJohn Marino 	      gcc_assert (ORIG_PAT (next) != NULL_RTX);
2340e4b17023SJohn Marino 	      haifa_change_pattern (next, ORIG_PAT (next));
2341e4b17023SJohn Marino 	      INSN_TICK (next) = tick;
2342e4b17023SJohn Marino 	      if (sd_lists_empty_p (next, SD_LIST_BACK))
2343e4b17023SJohn Marino 		TODO_SPEC (next) = 0;
2344e4b17023SJohn Marino 	      else if (!sd_lists_empty_p (next, SD_LIST_HARD_BACK))
2345e4b17023SJohn Marino 		TODO_SPEC (next) = HARD_DEP;
2346e4b17023SJohn Marino 	    }
2347e4b17023SJohn Marino 	  continue;
2348e4b17023SJohn Marino 	}
2349e4b17023SJohn Marino 
2350e4b17023SJohn Marino       /* Don't bother trying to mark next as ready if insn is a debug
2351e4b17023SJohn Marino 	 insn.  If insn is the last hard dependency, it will have
2352e4b17023SJohn Marino 	 already been discounted.  */
2353e4b17023SJohn Marino       if (DEBUG_INSN_P (insn) && !DEBUG_INSN_P (next))
2354e4b17023SJohn Marino 	continue;
2355e4b17023SJohn Marino 
2356e4b17023SJohn Marino       if (!IS_SPECULATION_BRANCHY_CHECK_P (insn))
2357e4b17023SJohn Marino 	{
2358e4b17023SJohn Marino 	  int effective_cost;
2359e4b17023SJohn Marino 
2360e4b17023SJohn Marino 	  effective_cost = try_ready (next);
2361e4b17023SJohn Marino 
2362e4b17023SJohn Marino 	  if (effective_cost >= 0
2363e4b17023SJohn Marino 	      && SCHED_GROUP_P (next)
2364e4b17023SJohn Marino 	      && advance < effective_cost)
2365e4b17023SJohn Marino 	    advance = effective_cost;
2366e4b17023SJohn Marino 	}
2367e4b17023SJohn Marino       else
2368e4b17023SJohn Marino 	/* Check always has only one forward dependence (to the first insn in
2369e4b17023SJohn Marino 	   the recovery block), therefore, this will be executed only once.  */
2370e4b17023SJohn Marino 	{
2371e4b17023SJohn Marino 	  gcc_assert (sd_lists_empty_p (insn, SD_LIST_FORW));
2372e4b17023SJohn Marino 	  fix_recovery_deps (RECOVERY_BLOCK (insn));
2373e4b17023SJohn Marino 	}
2374e4b17023SJohn Marino     }
2375e4b17023SJohn Marino 
2376e4b17023SJohn Marino   /* Annotate the instruction with issue information -- TImode
2377e4b17023SJohn Marino      indicates that the instruction is expected not to be able
2378e4b17023SJohn Marino      to issue on the same cycle as the previous insn.  A machine
2379e4b17023SJohn Marino      may use this information to decide how the instruction should
2380e4b17023SJohn Marino      be aligned.  */
2381e4b17023SJohn Marino   if (issue_rate > 1
2382e4b17023SJohn Marino       && GET_CODE (PATTERN (insn)) != USE
2383e4b17023SJohn Marino       && GET_CODE (PATTERN (insn)) != CLOBBER
2384e4b17023SJohn Marino       && !DEBUG_INSN_P (insn))
2385e4b17023SJohn Marino     {
2386e4b17023SJohn Marino       if (reload_completed)
2387e4b17023SJohn Marino 	PUT_MODE (insn, clock_var > last_clock_var ? TImode : VOIDmode);
2388e4b17023SJohn Marino       last_clock_var = clock_var;
2389e4b17023SJohn Marino     }
2390e4b17023SJohn Marino 
2391e4b17023SJohn Marino   return advance;
2392e4b17023SJohn Marino }
2393e4b17023SJohn Marino 
2394e4b17023SJohn Marino /* Functions for handling of notes.  */
2395e4b17023SJohn Marino 
2396e4b17023SJohn Marino /* Add note list that ends on FROM_END to the end of TO_ENDP.  */
2397e4b17023SJohn Marino void
concat_note_lists(rtx from_end,rtx * to_endp)2398e4b17023SJohn Marino concat_note_lists (rtx from_end, rtx *to_endp)
2399e4b17023SJohn Marino {
2400e4b17023SJohn Marino   rtx from_start;
2401e4b17023SJohn Marino 
2402e4b17023SJohn Marino   /* It's easy when have nothing to concat.  */
2403e4b17023SJohn Marino   if (from_end == NULL)
2404e4b17023SJohn Marino     return;
2405e4b17023SJohn Marino 
2406e4b17023SJohn Marino   /* It's also easy when destination is empty.  */
2407e4b17023SJohn Marino   if (*to_endp == NULL)
2408e4b17023SJohn Marino     {
2409e4b17023SJohn Marino       *to_endp = from_end;
2410e4b17023SJohn Marino       return;
2411e4b17023SJohn Marino     }
2412e4b17023SJohn Marino 
2413e4b17023SJohn Marino   from_start = from_end;
2414e4b17023SJohn Marino   while (PREV_INSN (from_start) != NULL)
2415e4b17023SJohn Marino     from_start = PREV_INSN (from_start);
2416e4b17023SJohn Marino 
2417e4b17023SJohn Marino   PREV_INSN (from_start) = *to_endp;
2418e4b17023SJohn Marino   NEXT_INSN (*to_endp) = from_start;
2419e4b17023SJohn Marino   *to_endp = from_end;
2420e4b17023SJohn Marino }
2421e4b17023SJohn Marino 
2422e4b17023SJohn Marino /* Delete notes between HEAD and TAIL and put them in the chain
2423e4b17023SJohn Marino    of notes ended by NOTE_LIST.  */
2424e4b17023SJohn Marino void
remove_notes(rtx head,rtx tail)2425e4b17023SJohn Marino remove_notes (rtx head, rtx tail)
2426e4b17023SJohn Marino {
2427e4b17023SJohn Marino   rtx next_tail, insn, next;
2428e4b17023SJohn Marino 
2429e4b17023SJohn Marino   note_list = 0;
2430e4b17023SJohn Marino   if (head == tail && !INSN_P (head))
2431e4b17023SJohn Marino     return;
2432e4b17023SJohn Marino 
2433e4b17023SJohn Marino   next_tail = NEXT_INSN (tail);
2434e4b17023SJohn Marino   for (insn = head; insn != next_tail; insn = next)
2435e4b17023SJohn Marino     {
2436e4b17023SJohn Marino       next = NEXT_INSN (insn);
2437e4b17023SJohn Marino       if (!NOTE_P (insn))
2438e4b17023SJohn Marino 	continue;
2439e4b17023SJohn Marino 
2440e4b17023SJohn Marino       switch (NOTE_KIND (insn))
2441e4b17023SJohn Marino 	{
2442e4b17023SJohn Marino 	case NOTE_INSN_BASIC_BLOCK:
2443e4b17023SJohn Marino 	  continue;
2444e4b17023SJohn Marino 
2445e4b17023SJohn Marino 	case NOTE_INSN_EPILOGUE_BEG:
2446e4b17023SJohn Marino 	  if (insn != tail)
2447e4b17023SJohn Marino 	    {
2448e4b17023SJohn Marino 	      remove_insn (insn);
2449e4b17023SJohn Marino 	      add_reg_note (next, REG_SAVE_NOTE,
2450e4b17023SJohn Marino 			    GEN_INT (NOTE_INSN_EPILOGUE_BEG));
2451e4b17023SJohn Marino 	      break;
2452e4b17023SJohn Marino 	    }
2453e4b17023SJohn Marino 	  /* FALLTHRU */
2454e4b17023SJohn Marino 
2455e4b17023SJohn Marino 	default:
2456e4b17023SJohn Marino 	  remove_insn (insn);
2457e4b17023SJohn Marino 
2458e4b17023SJohn Marino 	  /* Add the note to list that ends at NOTE_LIST.  */
2459e4b17023SJohn Marino 	  PREV_INSN (insn) = note_list;
2460e4b17023SJohn Marino 	  NEXT_INSN (insn) = NULL_RTX;
2461e4b17023SJohn Marino 	  if (note_list)
2462e4b17023SJohn Marino 	    NEXT_INSN (note_list) = insn;
2463e4b17023SJohn Marino 	  note_list = insn;
2464e4b17023SJohn Marino 	  break;
2465e4b17023SJohn Marino 	}
2466e4b17023SJohn Marino 
2467e4b17023SJohn Marino       gcc_assert ((sel_sched_p () || insn != tail) && insn != head);
2468e4b17023SJohn Marino     }
2469e4b17023SJohn Marino }
2470e4b17023SJohn Marino 
2471e4b17023SJohn Marino /* A structure to record enough data to allow us to backtrack the scheduler to
2472e4b17023SJohn Marino    a previous state.  */
2473e4b17023SJohn Marino struct haifa_saved_data
2474e4b17023SJohn Marino {
2475e4b17023SJohn Marino   /* Next entry on the list.  */
2476e4b17023SJohn Marino   struct haifa_saved_data *next;
2477e4b17023SJohn Marino 
2478e4b17023SJohn Marino   /* Backtracking is associated with scheduling insns that have delay slots.
2479e4b17023SJohn Marino      DELAY_PAIR points to the structure that contains the insns involved, and
2480e4b17023SJohn Marino      the number of cycles between them.  */
2481e4b17023SJohn Marino   struct delay_pair *delay_pair;
2482e4b17023SJohn Marino 
2483e4b17023SJohn Marino   /* Data used by the frontend (e.g. sched-ebb or sched-rgn).  */
2484e4b17023SJohn Marino   void *fe_saved_data;
2485e4b17023SJohn Marino   /* Data used by the backend.  */
2486e4b17023SJohn Marino   void *be_saved_data;
2487e4b17023SJohn Marino 
2488e4b17023SJohn Marino   /* Copies of global state.  */
2489e4b17023SJohn Marino   int clock_var, last_clock_var;
2490e4b17023SJohn Marino   struct ready_list ready;
2491e4b17023SJohn Marino   state_t curr_state;
2492e4b17023SJohn Marino 
2493e4b17023SJohn Marino   rtx last_scheduled_insn;
2494e4b17023SJohn Marino   rtx last_nondebug_scheduled_insn;
2495e4b17023SJohn Marino   int cycle_issued_insns;
2496e4b17023SJohn Marino 
2497e4b17023SJohn Marino   /* Copies of state used in the inner loop of schedule_block.  */
2498e4b17023SJohn Marino   struct sched_block_state sched_block;
2499e4b17023SJohn Marino 
2500e4b17023SJohn Marino   /* We don't need to save q_ptr, as its value is arbitrary and we can set it
2501e4b17023SJohn Marino      to 0 when restoring.  */
2502e4b17023SJohn Marino   int q_size;
2503e4b17023SJohn Marino   rtx *insn_queue;
2504e4b17023SJohn Marino };
2505e4b17023SJohn Marino 
2506e4b17023SJohn Marino /* A record, in reverse order, of all scheduled insns which have delay slots
2507e4b17023SJohn Marino    and may require backtracking.  */
2508e4b17023SJohn Marino static struct haifa_saved_data *backtrack_queue;
2509e4b17023SJohn Marino 
2510e4b17023SJohn Marino /* For every dependency of INSN, set the FEEDS_BACKTRACK_INSN bit according
2511e4b17023SJohn Marino    to SET_P.  */
2512e4b17023SJohn Marino static void
mark_backtrack_feeds(rtx insn,int set_p)2513e4b17023SJohn Marino mark_backtrack_feeds (rtx insn, int set_p)
2514e4b17023SJohn Marino {
2515e4b17023SJohn Marino   sd_iterator_def sd_it;
2516e4b17023SJohn Marino   dep_t dep;
2517e4b17023SJohn Marino   FOR_EACH_DEP (insn, SD_LIST_HARD_BACK, sd_it, dep)
2518e4b17023SJohn Marino     {
2519e4b17023SJohn Marino       FEEDS_BACKTRACK_INSN (DEP_PRO (dep)) = set_p;
2520e4b17023SJohn Marino     }
2521e4b17023SJohn Marino }
2522e4b17023SJohn Marino 
2523e4b17023SJohn Marino /* Save the current scheduler state so that we can backtrack to it
2524e4b17023SJohn Marino    later if necessary.  PAIR gives the insns that make it necessary to
2525e4b17023SJohn Marino    save this point.  SCHED_BLOCK is the local state of schedule_block
2526e4b17023SJohn Marino    that need to be saved.  */
2527e4b17023SJohn Marino static void
save_backtrack_point(struct delay_pair * pair,struct sched_block_state sched_block)2528e4b17023SJohn Marino save_backtrack_point (struct delay_pair *pair,
2529e4b17023SJohn Marino 		      struct sched_block_state sched_block)
2530e4b17023SJohn Marino {
2531e4b17023SJohn Marino   int i;
2532e4b17023SJohn Marino   struct haifa_saved_data *save = XNEW (struct haifa_saved_data);
2533e4b17023SJohn Marino 
2534e4b17023SJohn Marino   save->curr_state = xmalloc (dfa_state_size);
2535e4b17023SJohn Marino   memcpy (save->curr_state, curr_state, dfa_state_size);
2536e4b17023SJohn Marino 
2537e4b17023SJohn Marino   save->ready.first = ready.first;
2538e4b17023SJohn Marino   save->ready.n_ready = ready.n_ready;
2539e4b17023SJohn Marino   save->ready.n_debug = ready.n_debug;
2540e4b17023SJohn Marino   save->ready.veclen = ready.veclen;
2541e4b17023SJohn Marino   save->ready.vec = XNEWVEC (rtx, ready.veclen);
2542e4b17023SJohn Marino   memcpy (save->ready.vec, ready.vec, ready.veclen * sizeof (rtx));
2543e4b17023SJohn Marino 
2544e4b17023SJohn Marino   save->insn_queue = XNEWVEC (rtx, max_insn_queue_index + 1);
2545e4b17023SJohn Marino   save->q_size = q_size;
2546e4b17023SJohn Marino   for (i = 0; i <= max_insn_queue_index; i++)
2547e4b17023SJohn Marino     {
2548e4b17023SJohn Marino       int q = NEXT_Q_AFTER (q_ptr, i);
2549e4b17023SJohn Marino       save->insn_queue[i] = copy_INSN_LIST (insn_queue[q]);
2550e4b17023SJohn Marino     }
2551e4b17023SJohn Marino 
2552e4b17023SJohn Marino   save->clock_var = clock_var;
2553e4b17023SJohn Marino   save->last_clock_var = last_clock_var;
2554e4b17023SJohn Marino   save->cycle_issued_insns = cycle_issued_insns;
2555e4b17023SJohn Marino   save->last_scheduled_insn = last_scheduled_insn;
2556e4b17023SJohn Marino   save->last_nondebug_scheduled_insn = last_nondebug_scheduled_insn;
2557e4b17023SJohn Marino 
2558e4b17023SJohn Marino   save->sched_block = sched_block;
2559e4b17023SJohn Marino 
2560e4b17023SJohn Marino   if (current_sched_info->save_state)
2561e4b17023SJohn Marino     save->fe_saved_data = (*current_sched_info->save_state) ();
2562e4b17023SJohn Marino 
2563e4b17023SJohn Marino   if (targetm.sched.alloc_sched_context)
2564e4b17023SJohn Marino     {
2565e4b17023SJohn Marino       save->be_saved_data = targetm.sched.alloc_sched_context ();
2566e4b17023SJohn Marino       targetm.sched.init_sched_context (save->be_saved_data, false);
2567e4b17023SJohn Marino     }
2568e4b17023SJohn Marino   else
2569e4b17023SJohn Marino     save->be_saved_data = NULL;
2570e4b17023SJohn Marino 
2571e4b17023SJohn Marino   save->delay_pair = pair;
2572e4b17023SJohn Marino 
2573e4b17023SJohn Marino   save->next = backtrack_queue;
2574e4b17023SJohn Marino   backtrack_queue = save;
2575e4b17023SJohn Marino 
2576e4b17023SJohn Marino   while (pair)
2577e4b17023SJohn Marino     {
2578e4b17023SJohn Marino       mark_backtrack_feeds (pair->i2, 1);
2579e4b17023SJohn Marino       INSN_TICK (pair->i2) = INVALID_TICK;
2580e4b17023SJohn Marino       INSN_EXACT_TICK (pair->i2) = clock_var + pair_delay (pair);
2581e4b17023SJohn Marino       SHADOW_P (pair->i2) = pair->stages == 0;
2582e4b17023SJohn Marino       pair = pair->next_same_i1;
2583e4b17023SJohn Marino     }
2584e4b17023SJohn Marino }
2585e4b17023SJohn Marino 
2586e4b17023SJohn Marino /* Walk the ready list and all queues. If any insns have unresolved backwards
2587e4b17023SJohn Marino    dependencies, these must be cancelled deps, broken by predication.  Set or
2588e4b17023SJohn Marino    clear (depending on SET) the DEP_CANCELLED bit in DEP_STATUS.  */
2589e4b17023SJohn Marino 
2590e4b17023SJohn Marino static void
toggle_cancelled_flags(bool set)2591e4b17023SJohn Marino toggle_cancelled_flags (bool set)
2592e4b17023SJohn Marino {
2593e4b17023SJohn Marino   int i;
2594e4b17023SJohn Marino   sd_iterator_def sd_it;
2595e4b17023SJohn Marino   dep_t dep;
2596e4b17023SJohn Marino 
2597e4b17023SJohn Marino   if (ready.n_ready > 0)
2598e4b17023SJohn Marino     {
2599e4b17023SJohn Marino       rtx *first = ready_lastpos (&ready);
2600e4b17023SJohn Marino       for (i = 0; i < ready.n_ready; i++)
2601e4b17023SJohn Marino 	FOR_EACH_DEP (first[i], SD_LIST_BACK, sd_it, dep)
2602e4b17023SJohn Marino 	  if (!DEBUG_INSN_P (DEP_PRO (dep)))
2603e4b17023SJohn Marino 	    {
2604e4b17023SJohn Marino 	      if (set)
2605e4b17023SJohn Marino 		DEP_STATUS (dep) |= DEP_CANCELLED;
2606e4b17023SJohn Marino 	      else
2607e4b17023SJohn Marino 		DEP_STATUS (dep) &= ~DEP_CANCELLED;
2608e4b17023SJohn Marino 	    }
2609e4b17023SJohn Marino     }
2610e4b17023SJohn Marino   for (i = 0; i <= max_insn_queue_index; i++)
2611e4b17023SJohn Marino     {
2612e4b17023SJohn Marino       int q = NEXT_Q_AFTER (q_ptr, i);
2613e4b17023SJohn Marino       rtx link;
2614e4b17023SJohn Marino       for (link = insn_queue[q]; link; link = XEXP (link, 1))
2615e4b17023SJohn Marino 	{
2616e4b17023SJohn Marino 	  rtx insn = XEXP (link, 0);
2617e4b17023SJohn Marino 	  FOR_EACH_DEP (insn, SD_LIST_BACK, sd_it, dep)
2618e4b17023SJohn Marino 	    if (!DEBUG_INSN_P (DEP_PRO (dep)))
2619e4b17023SJohn Marino 	      {
2620e4b17023SJohn Marino 		if (set)
2621e4b17023SJohn Marino 		  DEP_STATUS (dep) |= DEP_CANCELLED;
2622e4b17023SJohn Marino 		else
2623e4b17023SJohn Marino 		  DEP_STATUS (dep) &= ~DEP_CANCELLED;
2624e4b17023SJohn Marino 	      }
2625e4b17023SJohn Marino 	}
2626e4b17023SJohn Marino     }
2627e4b17023SJohn Marino }
2628e4b17023SJohn Marino 
2629e4b17023SJohn Marino /* Pop entries from the SCHEDULED_INSNS vector up to and including INSN.
2630e4b17023SJohn Marino    Restore their dependencies to an unresolved state, and mark them as
2631e4b17023SJohn Marino    queued nowhere.  */
2632e4b17023SJohn Marino 
2633e4b17023SJohn Marino static void
unschedule_insns_until(rtx insn)2634e4b17023SJohn Marino unschedule_insns_until (rtx insn)
2635e4b17023SJohn Marino {
2636e4b17023SJohn Marino   VEC (rtx, heap) *recompute_vec;
2637e4b17023SJohn Marino 
2638e4b17023SJohn Marino   recompute_vec = VEC_alloc (rtx, heap, 0);
2639e4b17023SJohn Marino 
2640e4b17023SJohn Marino   /* Make two passes over the insns to be unscheduled.  First, we clear out
2641e4b17023SJohn Marino      dependencies and other trivial bookkeeping.  */
2642e4b17023SJohn Marino   for (;;)
2643e4b17023SJohn Marino     {
2644e4b17023SJohn Marino       rtx last;
2645e4b17023SJohn Marino       sd_iterator_def sd_it;
2646e4b17023SJohn Marino       dep_t dep;
2647e4b17023SJohn Marino 
2648e4b17023SJohn Marino       last = VEC_pop (rtx, scheduled_insns);
2649e4b17023SJohn Marino 
2650e4b17023SJohn Marino       /* This will be changed by restore_backtrack_point if the insn is in
2651e4b17023SJohn Marino 	 any queue.  */
2652e4b17023SJohn Marino       QUEUE_INDEX (last) = QUEUE_NOWHERE;
2653e4b17023SJohn Marino       if (last != insn)
2654e4b17023SJohn Marino 	INSN_TICK (last) = INVALID_TICK;
2655e4b17023SJohn Marino 
2656e4b17023SJohn Marino       if (modulo_ii > 0 && INSN_UID (last) < modulo_iter0_max_uid)
2657e4b17023SJohn Marino 	modulo_insns_scheduled--;
2658e4b17023SJohn Marino 
2659e4b17023SJohn Marino       for (sd_it = sd_iterator_start (last, SD_LIST_RES_FORW);
2660e4b17023SJohn Marino 	   sd_iterator_cond (&sd_it, &dep);)
2661e4b17023SJohn Marino 	{
2662e4b17023SJohn Marino 	  rtx con = DEP_CON (dep);
2663e4b17023SJohn Marino 	  sd_unresolve_dep (sd_it);
2664e4b17023SJohn Marino 	  if (!MUST_RECOMPUTE_SPEC_P (con))
2665e4b17023SJohn Marino 	    {
2666e4b17023SJohn Marino 	      MUST_RECOMPUTE_SPEC_P (con) = 1;
2667e4b17023SJohn Marino 	      VEC_safe_push (rtx, heap, recompute_vec, con);
2668e4b17023SJohn Marino 	    }
2669e4b17023SJohn Marino 	}
2670e4b17023SJohn Marino 
2671e4b17023SJohn Marino       if (last == insn)
2672e4b17023SJohn Marino 	break;
2673e4b17023SJohn Marino     }
2674e4b17023SJohn Marino 
2675e4b17023SJohn Marino   /* A second pass, to update ready and speculation status for insns
2676e4b17023SJohn Marino      depending on the unscheduled ones.  The first pass must have
2677e4b17023SJohn Marino      popped the scheduled_insns vector up to the point where we
2678e4b17023SJohn Marino      restart scheduling, as recompute_todo_spec requires it to be
2679e4b17023SJohn Marino      up-to-date.  */
2680e4b17023SJohn Marino   while (!VEC_empty (rtx, recompute_vec))
2681e4b17023SJohn Marino     {
2682e4b17023SJohn Marino       rtx con;
2683e4b17023SJohn Marino 
2684e4b17023SJohn Marino       con = VEC_pop (rtx, recompute_vec);
2685e4b17023SJohn Marino       MUST_RECOMPUTE_SPEC_P (con) = 0;
2686e4b17023SJohn Marino       if (!sd_lists_empty_p (con, SD_LIST_HARD_BACK))
2687e4b17023SJohn Marino 	{
2688e4b17023SJohn Marino 	  TODO_SPEC (con) = HARD_DEP;
2689e4b17023SJohn Marino 	  INSN_TICK (con) = INVALID_TICK;
2690e4b17023SJohn Marino 	  if (PREDICATED_PAT (con) != NULL_RTX)
2691e4b17023SJohn Marino 	    haifa_change_pattern (con, ORIG_PAT (con));
2692e4b17023SJohn Marino 	}
2693e4b17023SJohn Marino       else if (QUEUE_INDEX (con) != QUEUE_SCHEDULED)
2694e4b17023SJohn Marino 	TODO_SPEC (con) = recompute_todo_spec (con);
2695e4b17023SJohn Marino     }
2696e4b17023SJohn Marino   VEC_free (rtx, heap, recompute_vec);
2697e4b17023SJohn Marino }
2698e4b17023SJohn Marino 
2699e4b17023SJohn Marino /* Restore scheduler state from the topmost entry on the backtracking queue.
2700e4b17023SJohn Marino    PSCHED_BLOCK_P points to the local data of schedule_block that we must
2701e4b17023SJohn Marino    overwrite with the saved data.
2702e4b17023SJohn Marino    The caller must already have called unschedule_insns_until.  */
2703e4b17023SJohn Marino 
2704e4b17023SJohn Marino static void
restore_last_backtrack_point(struct sched_block_state * psched_block)2705e4b17023SJohn Marino restore_last_backtrack_point (struct sched_block_state *psched_block)
2706e4b17023SJohn Marino {
2707e4b17023SJohn Marino   rtx link;
2708e4b17023SJohn Marino   int i;
2709e4b17023SJohn Marino   struct haifa_saved_data *save = backtrack_queue;
2710e4b17023SJohn Marino 
2711e4b17023SJohn Marino   backtrack_queue = save->next;
2712e4b17023SJohn Marino 
2713e4b17023SJohn Marino   if (current_sched_info->restore_state)
2714e4b17023SJohn Marino     (*current_sched_info->restore_state) (save->fe_saved_data);
2715e4b17023SJohn Marino 
2716e4b17023SJohn Marino   if (targetm.sched.alloc_sched_context)
2717e4b17023SJohn Marino     {
2718e4b17023SJohn Marino       targetm.sched.set_sched_context (save->be_saved_data);
2719e4b17023SJohn Marino       targetm.sched.free_sched_context (save->be_saved_data);
2720e4b17023SJohn Marino     }
2721e4b17023SJohn Marino 
2722e4b17023SJohn Marino   /* Clear the QUEUE_INDEX of everything in the ready list or one
2723e4b17023SJohn Marino      of the queues.  */
2724e4b17023SJohn Marino   if (ready.n_ready > 0)
2725e4b17023SJohn Marino     {
2726e4b17023SJohn Marino       rtx *first = ready_lastpos (&ready);
2727e4b17023SJohn Marino       for (i = 0; i < ready.n_ready; i++)
2728e4b17023SJohn Marino 	{
2729e4b17023SJohn Marino 	  rtx insn = first[i];
2730e4b17023SJohn Marino 	  QUEUE_INDEX (insn) = QUEUE_NOWHERE;
2731e4b17023SJohn Marino 	  INSN_TICK (insn) = INVALID_TICK;
2732e4b17023SJohn Marino 	}
2733e4b17023SJohn Marino     }
2734e4b17023SJohn Marino   for (i = 0; i <= max_insn_queue_index; i++)
2735e4b17023SJohn Marino     {
2736e4b17023SJohn Marino       int q = NEXT_Q_AFTER (q_ptr, i);
2737e4b17023SJohn Marino 
2738e4b17023SJohn Marino       for (link = insn_queue[q]; link; link = XEXP (link, 1))
2739e4b17023SJohn Marino 	{
2740e4b17023SJohn Marino 	  rtx x = XEXP (link, 0);
2741e4b17023SJohn Marino 	  QUEUE_INDEX (x) = QUEUE_NOWHERE;
2742e4b17023SJohn Marino 	  INSN_TICK (x) = INVALID_TICK;
2743e4b17023SJohn Marino 	}
2744e4b17023SJohn Marino       free_INSN_LIST_list (&insn_queue[q]);
2745e4b17023SJohn Marino     }
2746e4b17023SJohn Marino 
2747e4b17023SJohn Marino   free (ready.vec);
2748e4b17023SJohn Marino   ready = save->ready;
2749e4b17023SJohn Marino 
2750e4b17023SJohn Marino   if (ready.n_ready > 0)
2751e4b17023SJohn Marino     {
2752e4b17023SJohn Marino       rtx *first = ready_lastpos (&ready);
2753e4b17023SJohn Marino       for (i = 0; i < ready.n_ready; i++)
2754e4b17023SJohn Marino 	{
2755e4b17023SJohn Marino 	  rtx insn = first[i];
2756e4b17023SJohn Marino 	  QUEUE_INDEX (insn) = QUEUE_READY;
2757e4b17023SJohn Marino 	  TODO_SPEC (insn) = recompute_todo_spec (insn);
2758e4b17023SJohn Marino 	  INSN_TICK (insn) = save->clock_var;
2759e4b17023SJohn Marino 	}
2760e4b17023SJohn Marino     }
2761e4b17023SJohn Marino 
2762e4b17023SJohn Marino   q_ptr = 0;
2763e4b17023SJohn Marino   q_size = save->q_size;
2764e4b17023SJohn Marino   for (i = 0; i <= max_insn_queue_index; i++)
2765e4b17023SJohn Marino     {
2766e4b17023SJohn Marino       int q = NEXT_Q_AFTER (q_ptr, i);
2767e4b17023SJohn Marino 
2768e4b17023SJohn Marino       insn_queue[q] = save->insn_queue[q];
2769e4b17023SJohn Marino 
2770e4b17023SJohn Marino       for (link = insn_queue[q]; link; link = XEXP (link, 1))
2771e4b17023SJohn Marino 	{
2772e4b17023SJohn Marino 	  rtx x = XEXP (link, 0);
2773e4b17023SJohn Marino 	  QUEUE_INDEX (x) = i;
2774e4b17023SJohn Marino 	  TODO_SPEC (x) = recompute_todo_spec (x);
2775e4b17023SJohn Marino 	  INSN_TICK (x) = save->clock_var + i;
2776e4b17023SJohn Marino 	}
2777e4b17023SJohn Marino     }
2778e4b17023SJohn Marino   free (save->insn_queue);
2779e4b17023SJohn Marino 
2780e4b17023SJohn Marino   toggle_cancelled_flags (true);
2781e4b17023SJohn Marino 
2782e4b17023SJohn Marino   clock_var = save->clock_var;
2783e4b17023SJohn Marino   last_clock_var = save->last_clock_var;
2784e4b17023SJohn Marino   cycle_issued_insns = save->cycle_issued_insns;
2785e4b17023SJohn Marino   last_scheduled_insn = save->last_scheduled_insn;
2786e4b17023SJohn Marino   last_nondebug_scheduled_insn = save->last_nondebug_scheduled_insn;
2787e4b17023SJohn Marino 
2788e4b17023SJohn Marino   *psched_block = save->sched_block;
2789e4b17023SJohn Marino 
2790e4b17023SJohn Marino   memcpy (curr_state, save->curr_state, dfa_state_size);
2791e4b17023SJohn Marino   free (save->curr_state);
2792e4b17023SJohn Marino 
2793e4b17023SJohn Marino   mark_backtrack_feeds (save->delay_pair->i2, 0);
2794e4b17023SJohn Marino 
2795e4b17023SJohn Marino   free (save);
2796e4b17023SJohn Marino 
2797e4b17023SJohn Marino   for (save = backtrack_queue; save; save = save->next)
2798e4b17023SJohn Marino     {
2799e4b17023SJohn Marino       mark_backtrack_feeds (save->delay_pair->i2, 1);
2800e4b17023SJohn Marino     }
2801e4b17023SJohn Marino }
2802e4b17023SJohn Marino 
2803e4b17023SJohn Marino /* Discard all data associated with the topmost entry in the backtrack
2804e4b17023SJohn Marino    queue.  If RESET_TICK is false, we just want to free the data.  If true,
2805e4b17023SJohn Marino    we are doing this because we discovered a reason to backtrack.  In the
2806e4b17023SJohn Marino    latter case, also reset the INSN_TICK for the shadow insn.  */
2807e4b17023SJohn Marino static void
free_topmost_backtrack_point(bool reset_tick)2808e4b17023SJohn Marino free_topmost_backtrack_point (bool reset_tick)
2809e4b17023SJohn Marino {
2810e4b17023SJohn Marino   struct haifa_saved_data *save = backtrack_queue;
2811e4b17023SJohn Marino   int i;
2812e4b17023SJohn Marino 
2813e4b17023SJohn Marino   backtrack_queue = save->next;
2814e4b17023SJohn Marino 
2815e4b17023SJohn Marino   if (reset_tick)
2816e4b17023SJohn Marino     {
2817e4b17023SJohn Marino       struct delay_pair *pair = save->delay_pair;
2818e4b17023SJohn Marino       while (pair)
2819e4b17023SJohn Marino 	{
2820e4b17023SJohn Marino 	  INSN_TICK (pair->i2) = INVALID_TICK;
2821e4b17023SJohn Marino 	  INSN_EXACT_TICK (pair->i2) = INVALID_TICK;
2822e4b17023SJohn Marino 	  pair = pair->next_same_i1;
2823e4b17023SJohn Marino 	}
2824e4b17023SJohn Marino     }
2825e4b17023SJohn Marino   if (targetm.sched.free_sched_context)
2826e4b17023SJohn Marino     targetm.sched.free_sched_context (save->be_saved_data);
2827e4b17023SJohn Marino   if (current_sched_info->restore_state)
2828e4b17023SJohn Marino     free (save->fe_saved_data);
2829e4b17023SJohn Marino   for (i = 0; i <= max_insn_queue_index; i++)
2830e4b17023SJohn Marino     free_INSN_LIST_list (&save->insn_queue[i]);
2831e4b17023SJohn Marino   free (save->insn_queue);
2832e4b17023SJohn Marino   free (save->curr_state);
2833e4b17023SJohn Marino   free (save->ready.vec);
2834e4b17023SJohn Marino   free (save);
2835e4b17023SJohn Marino }
2836e4b17023SJohn Marino 
2837e4b17023SJohn Marino /* Free the entire backtrack queue.  */
2838e4b17023SJohn Marino static void
free_backtrack_queue(void)2839e4b17023SJohn Marino free_backtrack_queue (void)
2840e4b17023SJohn Marino {
2841e4b17023SJohn Marino   while (backtrack_queue)
2842e4b17023SJohn Marino     free_topmost_backtrack_point (false);
2843e4b17023SJohn Marino }
2844e4b17023SJohn Marino 
2845e4b17023SJohn Marino /* Compute INSN_TICK_ESTIMATE for INSN.  PROCESSED is a bitmap of
2846e4b17023SJohn Marino    instructions we've previously encountered, a set bit prevents
2847e4b17023SJohn Marino    recursion.  BUDGET is a limit on how far ahead we look, it is
2848e4b17023SJohn Marino    reduced on recursive calls.  Return true if we produced a good
2849e4b17023SJohn Marino    estimate, or false if we exceeded the budget.  */
2850e4b17023SJohn Marino static bool
estimate_insn_tick(bitmap processed,rtx insn,int budget)2851e4b17023SJohn Marino estimate_insn_tick (bitmap processed, rtx insn, int budget)
2852e4b17023SJohn Marino {
2853e4b17023SJohn Marino   sd_iterator_def sd_it;
2854e4b17023SJohn Marino   dep_t dep;
2855e4b17023SJohn Marino   int earliest = INSN_TICK (insn);
2856e4b17023SJohn Marino 
2857e4b17023SJohn Marino   FOR_EACH_DEP (insn, SD_LIST_BACK, sd_it, dep)
2858e4b17023SJohn Marino     {
2859e4b17023SJohn Marino       rtx pro = DEP_PRO (dep);
2860e4b17023SJohn Marino       int t;
2861e4b17023SJohn Marino 
2862e4b17023SJohn Marino       if (DEP_STATUS (dep) & DEP_CANCELLED)
2863e4b17023SJohn Marino 	continue;
2864e4b17023SJohn Marino 
2865e4b17023SJohn Marino       if (QUEUE_INDEX (pro) == QUEUE_SCHEDULED)
2866e4b17023SJohn Marino 	gcc_assert (INSN_TICK (pro) + dep_cost (dep) <= INSN_TICK (insn));
2867e4b17023SJohn Marino       else
2868e4b17023SJohn Marino 	{
2869e4b17023SJohn Marino 	  int cost = dep_cost (dep);
2870e4b17023SJohn Marino 	  if (cost >= budget)
2871e4b17023SJohn Marino 	    return false;
2872e4b17023SJohn Marino 	  if (!bitmap_bit_p (processed, INSN_LUID (pro)))
2873e4b17023SJohn Marino 	    {
2874e4b17023SJohn Marino 	      if (!estimate_insn_tick (processed, pro, budget - cost))
2875e4b17023SJohn Marino 		return false;
2876e4b17023SJohn Marino 	    }
2877e4b17023SJohn Marino 	  gcc_assert (INSN_TICK_ESTIMATE (pro) != INVALID_TICK);
2878e4b17023SJohn Marino 	  t = INSN_TICK_ESTIMATE (pro) + cost;
2879e4b17023SJohn Marino 	  if (earliest == INVALID_TICK || t > earliest)
2880e4b17023SJohn Marino 	    earliest = t;
2881e4b17023SJohn Marino 	}
2882e4b17023SJohn Marino     }
2883e4b17023SJohn Marino   bitmap_set_bit (processed, INSN_LUID (insn));
2884e4b17023SJohn Marino   INSN_TICK_ESTIMATE (insn) = earliest;
2885e4b17023SJohn Marino   return true;
2886e4b17023SJohn Marino }
2887e4b17023SJohn Marino 
2888e4b17023SJohn Marino /* Examine the pair of insns in P, and estimate (optimistically, assuming
2889e4b17023SJohn Marino    infinite resources) the cycle in which the delayed shadow can be issued.
2890e4b17023SJohn Marino    Return the number of cycles that must pass before the real insn can be
2891e4b17023SJohn Marino    issued in order to meet this constraint.  */
2892e4b17023SJohn Marino static int
estimate_shadow_tick(struct delay_pair * p)2893e4b17023SJohn Marino estimate_shadow_tick (struct delay_pair *p)
2894e4b17023SJohn Marino {
2895e4b17023SJohn Marino   bitmap_head processed;
2896e4b17023SJohn Marino   int t;
2897e4b17023SJohn Marino   bool cutoff;
2898e4b17023SJohn Marino   bitmap_initialize (&processed, 0);
2899e4b17023SJohn Marino 
2900e4b17023SJohn Marino   cutoff = !estimate_insn_tick (&processed, p->i2,
2901e4b17023SJohn Marino 				max_insn_queue_index + pair_delay (p));
2902e4b17023SJohn Marino   bitmap_clear (&processed);
2903e4b17023SJohn Marino   if (cutoff)
2904e4b17023SJohn Marino     return max_insn_queue_index;
2905e4b17023SJohn Marino   t = INSN_TICK_ESTIMATE (p->i2) - (clock_var + pair_delay (p) + 1);
2906e4b17023SJohn Marino   if (t > 0)
2907e4b17023SJohn Marino     return t;
2908e4b17023SJohn Marino   return 0;
2909e4b17023SJohn Marino }
2910e4b17023SJohn Marino 
2911e4b17023SJohn Marino /* If INSN has no unresolved backwards dependencies, add it to the schedule and
2912e4b17023SJohn Marino    recursively resolve all its forward dependencies.  */
2913e4b17023SJohn Marino static void
resolve_dependencies(rtx insn)2914e4b17023SJohn Marino resolve_dependencies (rtx insn)
2915e4b17023SJohn Marino {
2916e4b17023SJohn Marino   sd_iterator_def sd_it;
2917e4b17023SJohn Marino   dep_t dep;
2918e4b17023SJohn Marino 
2919e4b17023SJohn Marino   /* Don't use sd_lists_empty_p; it ignores debug insns.  */
2920e4b17023SJohn Marino   if (DEPS_LIST_FIRST (INSN_HARD_BACK_DEPS (insn)) != NULL
2921e4b17023SJohn Marino       || DEPS_LIST_FIRST (INSN_SPEC_BACK_DEPS (insn)) != NULL)
2922e4b17023SJohn Marino     return;
2923e4b17023SJohn Marino 
2924e4b17023SJohn Marino   if (sched_verbose >= 4)
2925e4b17023SJohn Marino     fprintf (sched_dump, ";;\tquickly resolving %d\n", INSN_UID (insn));
2926e4b17023SJohn Marino 
2927e4b17023SJohn Marino   if (QUEUE_INDEX (insn) >= 0)
2928e4b17023SJohn Marino     queue_remove (insn);
2929e4b17023SJohn Marino 
2930e4b17023SJohn Marino   VEC_safe_push (rtx, heap, scheduled_insns, insn);
2931e4b17023SJohn Marino 
2932e4b17023SJohn Marino   /* Update dependent instructions.  */
2933e4b17023SJohn Marino   for (sd_it = sd_iterator_start (insn, SD_LIST_FORW);
2934e4b17023SJohn Marino        sd_iterator_cond (&sd_it, &dep);)
2935e4b17023SJohn Marino     {
2936e4b17023SJohn Marino       rtx next = DEP_CON (dep);
2937e4b17023SJohn Marino 
2938e4b17023SJohn Marino       if (sched_verbose >= 4)
2939e4b17023SJohn Marino 	fprintf (sched_dump, ";;\t\tdep %d against %d\n", INSN_UID (insn),
2940e4b17023SJohn Marino 		 INSN_UID (next));
2941e4b17023SJohn Marino 
2942e4b17023SJohn Marino       /* Resolve the dependence between INSN and NEXT.
2943e4b17023SJohn Marino 	 sd_resolve_dep () moves current dep to another list thus
2944e4b17023SJohn Marino 	 advancing the iterator.  */
2945e4b17023SJohn Marino       sd_resolve_dep (sd_it);
2946e4b17023SJohn Marino 
2947e4b17023SJohn Marino       if (!IS_SPECULATION_BRANCHY_CHECK_P (insn))
2948e4b17023SJohn Marino 	{
2949e4b17023SJohn Marino 	  resolve_dependencies (next);
2950e4b17023SJohn Marino 	}
2951e4b17023SJohn Marino       else
2952e4b17023SJohn Marino 	/* Check always has only one forward dependence (to the first insn in
2953e4b17023SJohn Marino 	   the recovery block), therefore, this will be executed only once.  */
2954e4b17023SJohn Marino 	{
2955e4b17023SJohn Marino 	  gcc_assert (sd_lists_empty_p (insn, SD_LIST_FORW));
2956e4b17023SJohn Marino 	}
2957e4b17023SJohn Marino     }
2958e4b17023SJohn Marino }
2959e4b17023SJohn Marino 
2960e4b17023SJohn Marino 
2961e4b17023SJohn Marino /* Return the head and tail pointers of ebb starting at BEG and ending
2962e4b17023SJohn Marino    at END.  */
2963e4b17023SJohn Marino void
get_ebb_head_tail(basic_block beg,basic_block end,rtx * headp,rtx * tailp)2964e4b17023SJohn Marino get_ebb_head_tail (basic_block beg, basic_block end, rtx *headp, rtx *tailp)
2965e4b17023SJohn Marino {
2966e4b17023SJohn Marino   rtx beg_head = BB_HEAD (beg);
2967e4b17023SJohn Marino   rtx beg_tail = BB_END (beg);
2968e4b17023SJohn Marino   rtx end_head = BB_HEAD (end);
2969e4b17023SJohn Marino   rtx end_tail = BB_END (end);
2970e4b17023SJohn Marino 
2971e4b17023SJohn Marino   /* Don't include any notes or labels at the beginning of the BEG
2972e4b17023SJohn Marino      basic block, or notes at the end of the END basic blocks.  */
2973e4b17023SJohn Marino 
2974e4b17023SJohn Marino   if (LABEL_P (beg_head))
2975e4b17023SJohn Marino     beg_head = NEXT_INSN (beg_head);
2976e4b17023SJohn Marino 
2977e4b17023SJohn Marino   while (beg_head != beg_tail)
2978e4b17023SJohn Marino     if (NOTE_P (beg_head))
2979e4b17023SJohn Marino       beg_head = NEXT_INSN (beg_head);
2980e4b17023SJohn Marino     else if (DEBUG_INSN_P (beg_head))
2981e4b17023SJohn Marino       {
2982e4b17023SJohn Marino 	rtx note, next;
2983e4b17023SJohn Marino 
2984e4b17023SJohn Marino 	for (note = NEXT_INSN (beg_head);
2985e4b17023SJohn Marino 	     note != beg_tail;
2986e4b17023SJohn Marino 	     note = next)
2987e4b17023SJohn Marino 	  {
2988e4b17023SJohn Marino 	    next = NEXT_INSN (note);
2989e4b17023SJohn Marino 	    if (NOTE_P (note))
2990e4b17023SJohn Marino 	      {
2991e4b17023SJohn Marino 		if (sched_verbose >= 9)
2992e4b17023SJohn Marino 		  fprintf (sched_dump, "reorder %i\n", INSN_UID (note));
2993e4b17023SJohn Marino 
2994e4b17023SJohn Marino 		reorder_insns_nobb (note, note, PREV_INSN (beg_head));
2995e4b17023SJohn Marino 
2996e4b17023SJohn Marino 		if (BLOCK_FOR_INSN (note) != beg)
2997e4b17023SJohn Marino 		  df_insn_change_bb (note, beg);
2998e4b17023SJohn Marino 	      }
2999e4b17023SJohn Marino 	    else if (!DEBUG_INSN_P (note))
3000e4b17023SJohn Marino 	      break;
3001e4b17023SJohn Marino 	  }
3002e4b17023SJohn Marino 
3003e4b17023SJohn Marino 	break;
3004e4b17023SJohn Marino       }
3005e4b17023SJohn Marino     else
3006e4b17023SJohn Marino       break;
3007e4b17023SJohn Marino 
3008e4b17023SJohn Marino   *headp = beg_head;
3009e4b17023SJohn Marino 
3010e4b17023SJohn Marino   if (beg == end)
3011e4b17023SJohn Marino     end_head = beg_head;
3012e4b17023SJohn Marino   else if (LABEL_P (end_head))
3013e4b17023SJohn Marino     end_head = NEXT_INSN (end_head);
3014e4b17023SJohn Marino 
3015e4b17023SJohn Marino   while (end_head != end_tail)
3016e4b17023SJohn Marino     if (NOTE_P (end_tail))
3017e4b17023SJohn Marino       end_tail = PREV_INSN (end_tail);
3018e4b17023SJohn Marino     else if (DEBUG_INSN_P (end_tail))
3019e4b17023SJohn Marino       {
3020e4b17023SJohn Marino 	rtx note, prev;
3021e4b17023SJohn Marino 
3022e4b17023SJohn Marino 	for (note = PREV_INSN (end_tail);
3023e4b17023SJohn Marino 	     note != end_head;
3024e4b17023SJohn Marino 	     note = prev)
3025e4b17023SJohn Marino 	  {
3026e4b17023SJohn Marino 	    prev = PREV_INSN (note);
3027e4b17023SJohn Marino 	    if (NOTE_P (note))
3028e4b17023SJohn Marino 	      {
3029e4b17023SJohn Marino 		if (sched_verbose >= 9)
3030e4b17023SJohn Marino 		  fprintf (sched_dump, "reorder %i\n", INSN_UID (note));
3031e4b17023SJohn Marino 
3032e4b17023SJohn Marino 		reorder_insns_nobb (note, note, end_tail);
3033e4b17023SJohn Marino 
3034e4b17023SJohn Marino 		if (end_tail == BB_END (end))
3035e4b17023SJohn Marino 		  BB_END (end) = note;
3036e4b17023SJohn Marino 
3037e4b17023SJohn Marino 		if (BLOCK_FOR_INSN (note) != end)
3038e4b17023SJohn Marino 		  df_insn_change_bb (note, end);
3039e4b17023SJohn Marino 	      }
3040e4b17023SJohn Marino 	    else if (!DEBUG_INSN_P (note))
3041e4b17023SJohn Marino 	      break;
3042e4b17023SJohn Marino 	  }
3043e4b17023SJohn Marino 
3044e4b17023SJohn Marino 	break;
3045e4b17023SJohn Marino       }
3046e4b17023SJohn Marino     else
3047e4b17023SJohn Marino       break;
3048e4b17023SJohn Marino 
3049e4b17023SJohn Marino   *tailp = end_tail;
3050e4b17023SJohn Marino }
3051e4b17023SJohn Marino 
3052e4b17023SJohn Marino /* Return nonzero if there are no real insns in the range [ HEAD, TAIL ].  */
3053e4b17023SJohn Marino 
3054e4b17023SJohn Marino int
no_real_insns_p(const_rtx head,const_rtx tail)3055e4b17023SJohn Marino no_real_insns_p (const_rtx head, const_rtx tail)
3056e4b17023SJohn Marino {
3057e4b17023SJohn Marino   while (head != NEXT_INSN (tail))
3058e4b17023SJohn Marino     {
3059e4b17023SJohn Marino       if (!NOTE_P (head) && !LABEL_P (head))
3060e4b17023SJohn Marino 	return 0;
3061e4b17023SJohn Marino       head = NEXT_INSN (head);
3062e4b17023SJohn Marino     }
3063e4b17023SJohn Marino   return 1;
3064e4b17023SJohn Marino }
3065e4b17023SJohn Marino 
3066e4b17023SJohn Marino /* Restore-other-notes: NOTE_LIST is the end of a chain of notes
3067e4b17023SJohn Marino    previously found among the insns.  Insert them just before HEAD.  */
3068e4b17023SJohn Marino rtx
restore_other_notes(rtx head,basic_block head_bb)3069e4b17023SJohn Marino restore_other_notes (rtx head, basic_block head_bb)
3070e4b17023SJohn Marino {
3071e4b17023SJohn Marino   if (note_list != 0)
3072e4b17023SJohn Marino     {
3073e4b17023SJohn Marino       rtx note_head = note_list;
3074e4b17023SJohn Marino 
3075e4b17023SJohn Marino       if (head)
3076e4b17023SJohn Marino 	head_bb = BLOCK_FOR_INSN (head);
3077e4b17023SJohn Marino       else
3078e4b17023SJohn Marino 	head = NEXT_INSN (bb_note (head_bb));
3079e4b17023SJohn Marino 
3080e4b17023SJohn Marino       while (PREV_INSN (note_head))
3081e4b17023SJohn Marino 	{
3082e4b17023SJohn Marino 	  set_block_for_insn (note_head, head_bb);
3083e4b17023SJohn Marino 	  note_head = PREV_INSN (note_head);
3084e4b17023SJohn Marino 	}
3085e4b17023SJohn Marino       /* In the above cycle we've missed this note.  */
3086e4b17023SJohn Marino       set_block_for_insn (note_head, head_bb);
3087e4b17023SJohn Marino 
3088e4b17023SJohn Marino       PREV_INSN (note_head) = PREV_INSN (head);
3089e4b17023SJohn Marino       NEXT_INSN (PREV_INSN (head)) = note_head;
3090e4b17023SJohn Marino       PREV_INSN (head) = note_list;
3091e4b17023SJohn Marino       NEXT_INSN (note_list) = head;
3092e4b17023SJohn Marino 
3093e4b17023SJohn Marino       if (BLOCK_FOR_INSN (head) != head_bb)
3094e4b17023SJohn Marino 	BB_END (head_bb) = note_list;
3095e4b17023SJohn Marino 
3096e4b17023SJohn Marino       head = note_head;
3097e4b17023SJohn Marino     }
3098e4b17023SJohn Marino 
3099e4b17023SJohn Marino   return head;
3100e4b17023SJohn Marino }
3101e4b17023SJohn Marino 
3102e4b17023SJohn Marino /* Move insns that became ready to fire from queue to ready list.  */
3103e4b17023SJohn Marino 
3104e4b17023SJohn Marino static void
queue_to_ready(struct ready_list * ready)3105e4b17023SJohn Marino queue_to_ready (struct ready_list *ready)
3106e4b17023SJohn Marino {
3107e4b17023SJohn Marino   rtx insn;
3108e4b17023SJohn Marino   rtx link;
3109e4b17023SJohn Marino   rtx skip_insn;
3110e4b17023SJohn Marino 
3111e4b17023SJohn Marino   q_ptr = NEXT_Q (q_ptr);
3112e4b17023SJohn Marino 
3113e4b17023SJohn Marino   if (dbg_cnt (sched_insn) == false)
3114e4b17023SJohn Marino     {
3115e4b17023SJohn Marino       /* If debug counter is activated do not requeue the first
3116e4b17023SJohn Marino 	 nonscheduled insn.  */
3117e4b17023SJohn Marino       skip_insn = nonscheduled_insns_begin;
3118e4b17023SJohn Marino       do
3119e4b17023SJohn Marino 	{
3120e4b17023SJohn Marino 	  skip_insn = next_nonnote_nondebug_insn (skip_insn);
3121e4b17023SJohn Marino 	}
3122e4b17023SJohn Marino       while (QUEUE_INDEX (skip_insn) == QUEUE_SCHEDULED);
3123e4b17023SJohn Marino     }
3124e4b17023SJohn Marino   else
3125e4b17023SJohn Marino     skip_insn = NULL_RTX;
3126e4b17023SJohn Marino 
3127e4b17023SJohn Marino   /* Add all pending insns that can be scheduled without stalls to the
3128e4b17023SJohn Marino      ready list.  */
3129e4b17023SJohn Marino   for (link = insn_queue[q_ptr]; link; link = XEXP (link, 1))
3130e4b17023SJohn Marino     {
3131e4b17023SJohn Marino       insn = XEXP (link, 0);
3132e4b17023SJohn Marino       q_size -= 1;
3133e4b17023SJohn Marino 
3134e4b17023SJohn Marino       if (sched_verbose >= 2)
3135e4b17023SJohn Marino 	fprintf (sched_dump, ";;\t\tQ-->Ready: insn %s: ",
3136e4b17023SJohn Marino 		 (*current_sched_info->print_insn) (insn, 0));
3137e4b17023SJohn Marino 
3138e4b17023SJohn Marino       /* If the ready list is full, delay the insn for 1 cycle.
3139e4b17023SJohn Marino 	 See the comment in schedule_block for the rationale.  */
3140e4b17023SJohn Marino       if (!reload_completed
3141e4b17023SJohn Marino 	  && ready->n_ready - ready->n_debug > MAX_SCHED_READY_INSNS
3142e4b17023SJohn Marino 	  && !SCHED_GROUP_P (insn)
3143e4b17023SJohn Marino 	  && insn != skip_insn)
3144e4b17023SJohn Marino 	queue_insn (insn, 1, "ready full");
3145e4b17023SJohn Marino       else
3146e4b17023SJohn Marino 	{
3147e4b17023SJohn Marino 	  ready_add (ready, insn, false);
3148e4b17023SJohn Marino 	  if (sched_verbose >= 2)
3149e4b17023SJohn Marino 	    fprintf (sched_dump, "moving to ready without stalls\n");
3150e4b17023SJohn Marino         }
3151e4b17023SJohn Marino     }
3152e4b17023SJohn Marino   free_INSN_LIST_list (&insn_queue[q_ptr]);
3153e4b17023SJohn Marino 
3154e4b17023SJohn Marino   /* If there are no ready insns, stall until one is ready and add all
3155e4b17023SJohn Marino      of the pending insns at that point to the ready list.  */
3156e4b17023SJohn Marino   if (ready->n_ready == 0)
3157e4b17023SJohn Marino     {
3158e4b17023SJohn Marino       int stalls;
3159e4b17023SJohn Marino 
3160e4b17023SJohn Marino       for (stalls = 1; stalls <= max_insn_queue_index; stalls++)
3161e4b17023SJohn Marino 	{
3162e4b17023SJohn Marino 	  if ((link = insn_queue[NEXT_Q_AFTER (q_ptr, stalls)]))
3163e4b17023SJohn Marino 	    {
3164e4b17023SJohn Marino 	      for (; link; link = XEXP (link, 1))
3165e4b17023SJohn Marino 		{
3166e4b17023SJohn Marino 		  insn = XEXP (link, 0);
3167e4b17023SJohn Marino 		  q_size -= 1;
3168e4b17023SJohn Marino 
3169e4b17023SJohn Marino 		  if (sched_verbose >= 2)
3170e4b17023SJohn Marino 		    fprintf (sched_dump, ";;\t\tQ-->Ready: insn %s: ",
3171e4b17023SJohn Marino 			     (*current_sched_info->print_insn) (insn, 0));
3172e4b17023SJohn Marino 
3173e4b17023SJohn Marino 		  ready_add (ready, insn, false);
3174e4b17023SJohn Marino 		  if (sched_verbose >= 2)
3175e4b17023SJohn Marino 		    fprintf (sched_dump, "moving to ready with %d stalls\n", stalls);
3176e4b17023SJohn Marino 		}
3177e4b17023SJohn Marino 	      free_INSN_LIST_list (&insn_queue[NEXT_Q_AFTER (q_ptr, stalls)]);
3178e4b17023SJohn Marino 
3179e4b17023SJohn Marino 	      advance_one_cycle ();
3180e4b17023SJohn Marino 
3181e4b17023SJohn Marino 	      break;
3182e4b17023SJohn Marino 	    }
3183e4b17023SJohn Marino 
3184e4b17023SJohn Marino 	  advance_one_cycle ();
3185e4b17023SJohn Marino 	}
3186e4b17023SJohn Marino 
3187e4b17023SJohn Marino       q_ptr = NEXT_Q_AFTER (q_ptr, stalls);
3188e4b17023SJohn Marino       clock_var += stalls;
3189e4b17023SJohn Marino     }
3190e4b17023SJohn Marino }
3191e4b17023SJohn Marino 
3192e4b17023SJohn Marino /* Used by early_queue_to_ready.  Determines whether it is "ok" to
3193e4b17023SJohn Marino    prematurely move INSN from the queue to the ready list.  Currently,
3194e4b17023SJohn Marino    if a target defines the hook 'is_costly_dependence', this function
3195e4b17023SJohn Marino    uses the hook to check whether there exist any dependences which are
3196e4b17023SJohn Marino    considered costly by the target, between INSN and other insns that
3197e4b17023SJohn Marino    have already been scheduled.  Dependences are checked up to Y cycles
3198e4b17023SJohn Marino    back, with default Y=1; The flag -fsched-stalled-insns-dep=Y allows
3199e4b17023SJohn Marino    controlling this value.
3200e4b17023SJohn Marino    (Other considerations could be taken into account instead (or in
3201e4b17023SJohn Marino    addition) depending on user flags and target hooks.  */
3202e4b17023SJohn Marino 
3203e4b17023SJohn Marino static bool
ok_for_early_queue_removal(rtx insn)3204e4b17023SJohn Marino ok_for_early_queue_removal (rtx insn)
3205e4b17023SJohn Marino {
3206e4b17023SJohn Marino   if (targetm.sched.is_costly_dependence)
3207e4b17023SJohn Marino     {
3208e4b17023SJohn Marino       rtx prev_insn;
3209e4b17023SJohn Marino       int n_cycles;
3210e4b17023SJohn Marino       int i = VEC_length (rtx, scheduled_insns);
3211e4b17023SJohn Marino       for (n_cycles = flag_sched_stalled_insns_dep; n_cycles; n_cycles--)
3212e4b17023SJohn Marino 	{
3213e4b17023SJohn Marino 	  while (i-- > 0)
3214e4b17023SJohn Marino 	    {
3215e4b17023SJohn Marino 	      int cost;
3216e4b17023SJohn Marino 
3217e4b17023SJohn Marino 	      prev_insn = VEC_index (rtx, scheduled_insns, i);
3218e4b17023SJohn Marino 
3219e4b17023SJohn Marino 	      if (!NOTE_P (prev_insn))
3220e4b17023SJohn Marino 		{
3221e4b17023SJohn Marino 		  dep_t dep;
3222e4b17023SJohn Marino 
3223e4b17023SJohn Marino 		  dep = sd_find_dep_between (prev_insn, insn, true);
3224e4b17023SJohn Marino 
3225e4b17023SJohn Marino 		  if (dep != NULL)
3226e4b17023SJohn Marino 		    {
3227e4b17023SJohn Marino 		      cost = dep_cost (dep);
3228e4b17023SJohn Marino 
3229e4b17023SJohn Marino 		      if (targetm.sched.is_costly_dependence (dep, cost,
3230e4b17023SJohn Marino 				flag_sched_stalled_insns_dep - n_cycles))
3231e4b17023SJohn Marino 			return false;
3232e4b17023SJohn Marino 		    }
3233e4b17023SJohn Marino 		}
3234e4b17023SJohn Marino 
3235e4b17023SJohn Marino 	      if (GET_MODE (prev_insn) == TImode) /* end of dispatch group */
3236e4b17023SJohn Marino 		break;
3237e4b17023SJohn Marino 	    }
3238e4b17023SJohn Marino 
3239e4b17023SJohn Marino 	  if (i == 0)
3240e4b17023SJohn Marino 	    break;
3241e4b17023SJohn Marino 	}
3242e4b17023SJohn Marino     }
3243e4b17023SJohn Marino 
3244e4b17023SJohn Marino   return true;
3245e4b17023SJohn Marino }
3246e4b17023SJohn Marino 
3247e4b17023SJohn Marino 
3248e4b17023SJohn Marino /* Remove insns from the queue, before they become "ready" with respect
3249e4b17023SJohn Marino    to FU latency considerations.  */
3250e4b17023SJohn Marino 
3251e4b17023SJohn Marino static int
early_queue_to_ready(state_t state,struct ready_list * ready)3252e4b17023SJohn Marino early_queue_to_ready (state_t state, struct ready_list *ready)
3253e4b17023SJohn Marino {
3254e4b17023SJohn Marino   rtx insn;
3255e4b17023SJohn Marino   rtx link;
3256e4b17023SJohn Marino   rtx next_link;
3257e4b17023SJohn Marino   rtx prev_link;
3258e4b17023SJohn Marino   bool move_to_ready;
3259e4b17023SJohn Marino   int cost;
3260e4b17023SJohn Marino   state_t temp_state = alloca (dfa_state_size);
3261e4b17023SJohn Marino   int stalls;
3262e4b17023SJohn Marino   int insns_removed = 0;
3263e4b17023SJohn Marino 
3264e4b17023SJohn Marino   /*
3265e4b17023SJohn Marino      Flag '-fsched-stalled-insns=X' determines the aggressiveness of this
3266e4b17023SJohn Marino      function:
3267e4b17023SJohn Marino 
3268e4b17023SJohn Marino      X == 0: There is no limit on how many queued insns can be removed
3269e4b17023SJohn Marino              prematurely.  (flag_sched_stalled_insns = -1).
3270e4b17023SJohn Marino 
3271e4b17023SJohn Marino      X >= 1: Only X queued insns can be removed prematurely in each
3272e4b17023SJohn Marino 	     invocation.  (flag_sched_stalled_insns = X).
3273e4b17023SJohn Marino 
3274e4b17023SJohn Marino      Otherwise: Early queue removal is disabled.
3275e4b17023SJohn Marino          (flag_sched_stalled_insns = 0)
3276e4b17023SJohn Marino   */
3277e4b17023SJohn Marino 
3278e4b17023SJohn Marino   if (! flag_sched_stalled_insns)
3279e4b17023SJohn Marino     return 0;
3280e4b17023SJohn Marino 
3281e4b17023SJohn Marino   for (stalls = 0; stalls <= max_insn_queue_index; stalls++)
3282e4b17023SJohn Marino     {
3283e4b17023SJohn Marino       if ((link = insn_queue[NEXT_Q_AFTER (q_ptr, stalls)]))
3284e4b17023SJohn Marino 	{
3285e4b17023SJohn Marino 	  if (sched_verbose > 6)
3286e4b17023SJohn Marino 	    fprintf (sched_dump, ";; look at index %d + %d\n", q_ptr, stalls);
3287e4b17023SJohn Marino 
3288e4b17023SJohn Marino 	  prev_link = 0;
3289e4b17023SJohn Marino 	  while (link)
3290e4b17023SJohn Marino 	    {
3291e4b17023SJohn Marino 	      next_link = XEXP (link, 1);
3292e4b17023SJohn Marino 	      insn = XEXP (link, 0);
3293e4b17023SJohn Marino 	      if (insn && sched_verbose > 6)
3294e4b17023SJohn Marino 		print_rtl_single (sched_dump, insn);
3295e4b17023SJohn Marino 
3296e4b17023SJohn Marino 	      memcpy (temp_state, state, dfa_state_size);
3297e4b17023SJohn Marino 	      if (recog_memoized (insn) < 0)
3298e4b17023SJohn Marino 		/* non-negative to indicate that it's not ready
3299e4b17023SJohn Marino 		   to avoid infinite Q->R->Q->R... */
3300e4b17023SJohn Marino 		cost = 0;
3301e4b17023SJohn Marino 	      else
3302e4b17023SJohn Marino 		cost = state_transition (temp_state, insn);
3303e4b17023SJohn Marino 
3304e4b17023SJohn Marino 	      if (sched_verbose >= 6)
3305e4b17023SJohn Marino 		fprintf (sched_dump, "transition cost = %d\n", cost);
3306e4b17023SJohn Marino 
3307e4b17023SJohn Marino 	      move_to_ready = false;
3308e4b17023SJohn Marino 	      if (cost < 0)
3309e4b17023SJohn Marino 		{
3310e4b17023SJohn Marino 		  move_to_ready = ok_for_early_queue_removal (insn);
3311e4b17023SJohn Marino 		  if (move_to_ready == true)
3312e4b17023SJohn Marino 		    {
3313e4b17023SJohn Marino 		      /* move from Q to R */
3314e4b17023SJohn Marino 		      q_size -= 1;
3315e4b17023SJohn Marino 		      ready_add (ready, insn, false);
3316e4b17023SJohn Marino 
3317e4b17023SJohn Marino 		      if (prev_link)
3318e4b17023SJohn Marino 			XEXP (prev_link, 1) = next_link;
3319e4b17023SJohn Marino 		      else
3320e4b17023SJohn Marino 			insn_queue[NEXT_Q_AFTER (q_ptr, stalls)] = next_link;
3321e4b17023SJohn Marino 
3322e4b17023SJohn Marino 		      free_INSN_LIST_node (link);
3323e4b17023SJohn Marino 
3324e4b17023SJohn Marino 		      if (sched_verbose >= 2)
3325e4b17023SJohn Marino 			fprintf (sched_dump, ";;\t\tEarly Q-->Ready: insn %s\n",
3326e4b17023SJohn Marino 				 (*current_sched_info->print_insn) (insn, 0));
3327e4b17023SJohn Marino 
3328e4b17023SJohn Marino 		      insns_removed++;
3329e4b17023SJohn Marino 		      if (insns_removed == flag_sched_stalled_insns)
3330e4b17023SJohn Marino 			/* Remove no more than flag_sched_stalled_insns insns
3331e4b17023SJohn Marino 			   from Q at a time.  */
3332e4b17023SJohn Marino 			return insns_removed;
3333e4b17023SJohn Marino 		    }
3334e4b17023SJohn Marino 		}
3335e4b17023SJohn Marino 
3336e4b17023SJohn Marino 	      if (move_to_ready == false)
3337e4b17023SJohn Marino 		prev_link = link;
3338e4b17023SJohn Marino 
3339e4b17023SJohn Marino 	      link = next_link;
3340e4b17023SJohn Marino 	    } /* while link */
3341e4b17023SJohn Marino 	} /* if link */
3342e4b17023SJohn Marino 
3343e4b17023SJohn Marino     } /* for stalls.. */
3344e4b17023SJohn Marino 
3345e4b17023SJohn Marino   return insns_removed;
3346e4b17023SJohn Marino }
3347e4b17023SJohn Marino 
3348e4b17023SJohn Marino 
3349e4b17023SJohn Marino /* Print the ready list for debugging purposes.  Callable from debugger.  */
3350e4b17023SJohn Marino 
3351e4b17023SJohn Marino static void
debug_ready_list(struct ready_list * ready)3352e4b17023SJohn Marino debug_ready_list (struct ready_list *ready)
3353e4b17023SJohn Marino {
3354e4b17023SJohn Marino   rtx *p;
3355e4b17023SJohn Marino   int i;
3356e4b17023SJohn Marino 
3357e4b17023SJohn Marino   if (ready->n_ready == 0)
3358e4b17023SJohn Marino     {
3359e4b17023SJohn Marino       fprintf (sched_dump, "\n");
3360e4b17023SJohn Marino       return;
3361e4b17023SJohn Marino     }
3362e4b17023SJohn Marino 
3363e4b17023SJohn Marino   p = ready_lastpos (ready);
3364e4b17023SJohn Marino   for (i = 0; i < ready->n_ready; i++)
3365e4b17023SJohn Marino     {
3366e4b17023SJohn Marino       fprintf (sched_dump, "  %s:%d",
3367e4b17023SJohn Marino 	       (*current_sched_info->print_insn) (p[i], 0),
3368e4b17023SJohn Marino 	       INSN_LUID (p[i]));
3369e4b17023SJohn Marino       if (sched_pressure_p)
3370e4b17023SJohn Marino 	fprintf (sched_dump, "(cost=%d",
3371e4b17023SJohn Marino 		 INSN_REG_PRESSURE_EXCESS_COST_CHANGE (p[i]));
3372e4b17023SJohn Marino       if (INSN_TICK (p[i]) > clock_var)
3373e4b17023SJohn Marino 	fprintf (sched_dump, ":delay=%d", INSN_TICK (p[i]) - clock_var);
3374e4b17023SJohn Marino       if (sched_pressure_p)
3375e4b17023SJohn Marino 	fprintf (sched_dump, ")");
3376e4b17023SJohn Marino     }
3377e4b17023SJohn Marino   fprintf (sched_dump, "\n");
3378e4b17023SJohn Marino }
3379e4b17023SJohn Marino 
3380e4b17023SJohn Marino /* Search INSN for REG_SAVE_NOTE notes and convert them back into insn
3381e4b17023SJohn Marino    NOTEs.  This is used for NOTE_INSN_EPILOGUE_BEG, so that sched-ebb
3382e4b17023SJohn Marino    replaces the epilogue note in the correct basic block.  */
3383e4b17023SJohn Marino void
reemit_notes(rtx insn)3384e4b17023SJohn Marino reemit_notes (rtx insn)
3385e4b17023SJohn Marino {
3386e4b17023SJohn Marino   rtx note, last = insn;
3387e4b17023SJohn Marino 
3388e4b17023SJohn Marino   for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
3389e4b17023SJohn Marino     {
3390e4b17023SJohn Marino       if (REG_NOTE_KIND (note) == REG_SAVE_NOTE)
3391e4b17023SJohn Marino 	{
3392e4b17023SJohn Marino 	  enum insn_note note_type = (enum insn_note) INTVAL (XEXP (note, 0));
3393e4b17023SJohn Marino 
3394e4b17023SJohn Marino 	  last = emit_note_before (note_type, last);
3395e4b17023SJohn Marino 	  remove_note (insn, note);
3396e4b17023SJohn Marino 	}
3397e4b17023SJohn Marino     }
3398e4b17023SJohn Marino }
3399e4b17023SJohn Marino 
3400e4b17023SJohn Marino /* Move INSN.  Reemit notes if needed.  Update CFG, if needed.  */
3401e4b17023SJohn Marino static void
move_insn(rtx insn,rtx last,rtx nt)3402e4b17023SJohn Marino move_insn (rtx insn, rtx last, rtx nt)
3403e4b17023SJohn Marino {
3404e4b17023SJohn Marino   if (PREV_INSN (insn) != last)
3405e4b17023SJohn Marino     {
3406e4b17023SJohn Marino       basic_block bb;
3407e4b17023SJohn Marino       rtx note;
3408e4b17023SJohn Marino       int jump_p = 0;
3409e4b17023SJohn Marino 
3410e4b17023SJohn Marino       bb = BLOCK_FOR_INSN (insn);
3411e4b17023SJohn Marino 
3412e4b17023SJohn Marino       /* BB_HEAD is either LABEL or NOTE.  */
3413e4b17023SJohn Marino       gcc_assert (BB_HEAD (bb) != insn);
3414e4b17023SJohn Marino 
3415e4b17023SJohn Marino       if (BB_END (bb) == insn)
3416e4b17023SJohn Marino 	/* If this is last instruction in BB, move end marker one
3417e4b17023SJohn Marino 	   instruction up.  */
3418e4b17023SJohn Marino 	{
3419e4b17023SJohn Marino 	  /* Jumps are always placed at the end of basic block.  */
3420e4b17023SJohn Marino 	  jump_p = control_flow_insn_p (insn);
3421e4b17023SJohn Marino 
3422e4b17023SJohn Marino 	  gcc_assert (!jump_p
3423e4b17023SJohn Marino 		      || ((common_sched_info->sched_pass_id == SCHED_RGN_PASS)
3424e4b17023SJohn Marino 			  && IS_SPECULATION_BRANCHY_CHECK_P (insn))
3425e4b17023SJohn Marino 		      || (common_sched_info->sched_pass_id
3426e4b17023SJohn Marino 			  == SCHED_EBB_PASS));
3427e4b17023SJohn Marino 
3428e4b17023SJohn Marino 	  gcc_assert (BLOCK_FOR_INSN (PREV_INSN (insn)) == bb);
3429e4b17023SJohn Marino 
3430e4b17023SJohn Marino 	  BB_END (bb) = PREV_INSN (insn);
3431e4b17023SJohn Marino 	}
3432e4b17023SJohn Marino 
3433e4b17023SJohn Marino       gcc_assert (BB_END (bb) != last);
3434e4b17023SJohn Marino 
3435e4b17023SJohn Marino       if (jump_p)
3436e4b17023SJohn Marino 	/* We move the block note along with jump.  */
3437e4b17023SJohn Marino 	{
3438e4b17023SJohn Marino 	  gcc_assert (nt);
3439e4b17023SJohn Marino 
3440e4b17023SJohn Marino 	  note = NEXT_INSN (insn);
3441e4b17023SJohn Marino 	  while (NOTE_NOT_BB_P (note) && note != nt)
3442e4b17023SJohn Marino 	    note = NEXT_INSN (note);
3443e4b17023SJohn Marino 
3444e4b17023SJohn Marino 	  if (note != nt
3445e4b17023SJohn Marino 	      && (LABEL_P (note)
3446e4b17023SJohn Marino 		  || BARRIER_P (note)))
3447e4b17023SJohn Marino 	    note = NEXT_INSN (note);
3448e4b17023SJohn Marino 
3449e4b17023SJohn Marino 	  gcc_assert (NOTE_INSN_BASIC_BLOCK_P (note));
3450e4b17023SJohn Marino 	}
3451e4b17023SJohn Marino       else
3452e4b17023SJohn Marino 	note = insn;
3453e4b17023SJohn Marino 
3454e4b17023SJohn Marino       NEXT_INSN (PREV_INSN (insn)) = NEXT_INSN (note);
3455e4b17023SJohn Marino       PREV_INSN (NEXT_INSN (note)) = PREV_INSN (insn);
3456e4b17023SJohn Marino 
3457e4b17023SJohn Marino       NEXT_INSN (note) = NEXT_INSN (last);
3458e4b17023SJohn Marino       PREV_INSN (NEXT_INSN (last)) = note;
3459e4b17023SJohn Marino 
3460e4b17023SJohn Marino       NEXT_INSN (last) = insn;
3461e4b17023SJohn Marino       PREV_INSN (insn) = last;
3462e4b17023SJohn Marino 
3463e4b17023SJohn Marino       bb = BLOCK_FOR_INSN (last);
3464e4b17023SJohn Marino 
3465e4b17023SJohn Marino       if (jump_p)
3466e4b17023SJohn Marino 	{
3467e4b17023SJohn Marino 	  fix_jump_move (insn);
3468e4b17023SJohn Marino 
3469e4b17023SJohn Marino 	  if (BLOCK_FOR_INSN (insn) != bb)
3470e4b17023SJohn Marino 	    move_block_after_check (insn);
3471e4b17023SJohn Marino 
3472e4b17023SJohn Marino 	  gcc_assert (BB_END (bb) == last);
3473e4b17023SJohn Marino 	}
3474e4b17023SJohn Marino 
3475e4b17023SJohn Marino       df_insn_change_bb (insn, bb);
3476e4b17023SJohn Marino 
3477e4b17023SJohn Marino       /* Update BB_END, if needed.  */
3478e4b17023SJohn Marino       if (BB_END (bb) == last)
3479e4b17023SJohn Marino 	BB_END (bb) = insn;
3480e4b17023SJohn Marino     }
3481e4b17023SJohn Marino 
3482e4b17023SJohn Marino   SCHED_GROUP_P (insn) = 0;
3483e4b17023SJohn Marino }
3484e4b17023SJohn Marino 
3485e4b17023SJohn Marino /* Return true if scheduling INSN will finish current clock cycle.  */
3486e4b17023SJohn Marino static bool
insn_finishes_cycle_p(rtx insn)3487e4b17023SJohn Marino insn_finishes_cycle_p (rtx insn)
3488e4b17023SJohn Marino {
3489e4b17023SJohn Marino   if (SCHED_GROUP_P (insn))
3490e4b17023SJohn Marino     /* After issuing INSN, rest of the sched_group will be forced to issue
3491e4b17023SJohn Marino        in order.  Don't make any plans for the rest of cycle.  */
3492e4b17023SJohn Marino     return true;
3493e4b17023SJohn Marino 
3494e4b17023SJohn Marino   /* Finishing the block will, apparently, finish the cycle.  */
3495e4b17023SJohn Marino   if (current_sched_info->insn_finishes_block_p
3496e4b17023SJohn Marino       && current_sched_info->insn_finishes_block_p (insn))
3497e4b17023SJohn Marino     return true;
3498e4b17023SJohn Marino 
3499e4b17023SJohn Marino   return false;
3500e4b17023SJohn Marino }
3501e4b17023SJohn Marino 
3502e4b17023SJohn Marino /* Define type for target data used in multipass scheduling.  */
3503e4b17023SJohn Marino #ifndef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DATA_T
3504e4b17023SJohn Marino # define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DATA_T int
3505e4b17023SJohn Marino #endif
3506e4b17023SJohn Marino typedef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DATA_T first_cycle_multipass_data_t;
3507e4b17023SJohn Marino 
3508e4b17023SJohn Marino /* The following structure describe an entry of the stack of choices.  */
3509e4b17023SJohn Marino struct choice_entry
3510e4b17023SJohn Marino {
3511e4b17023SJohn Marino   /* Ordinal number of the issued insn in the ready queue.  */
3512e4b17023SJohn Marino   int index;
3513e4b17023SJohn Marino   /* The number of the rest insns whose issues we should try.  */
3514e4b17023SJohn Marino   int rest;
3515e4b17023SJohn Marino   /* The number of issued essential insns.  */
3516e4b17023SJohn Marino   int n;
3517e4b17023SJohn Marino   /* State after issuing the insn.  */
3518e4b17023SJohn Marino   state_t state;
3519e4b17023SJohn Marino   /* Target-specific data.  */
3520e4b17023SJohn Marino   first_cycle_multipass_data_t target_data;
3521e4b17023SJohn Marino };
3522e4b17023SJohn Marino 
3523e4b17023SJohn Marino /* The following array is used to implement a stack of choices used in
3524e4b17023SJohn Marino    function max_issue.  */
3525e4b17023SJohn Marino static struct choice_entry *choice_stack;
3526e4b17023SJohn Marino 
3527e4b17023SJohn Marino /* This holds the value of the target dfa_lookahead hook.  */
3528e4b17023SJohn Marino int dfa_lookahead;
3529e4b17023SJohn Marino 
3530e4b17023SJohn Marino /* The following variable value is maximal number of tries of issuing
3531e4b17023SJohn Marino    insns for the first cycle multipass insn scheduling.  We define
3532e4b17023SJohn Marino    this value as constant*(DFA_LOOKAHEAD**ISSUE_RATE).  We would not
3533e4b17023SJohn Marino    need this constraint if all real insns (with non-negative codes)
3534e4b17023SJohn Marino    had reservations because in this case the algorithm complexity is
3535e4b17023SJohn Marino    O(DFA_LOOKAHEAD**ISSUE_RATE).  Unfortunately, the dfa descriptions
3536e4b17023SJohn Marino    might be incomplete and such insn might occur.  For such
3537e4b17023SJohn Marino    descriptions, the complexity of algorithm (without the constraint)
3538e4b17023SJohn Marino    could achieve DFA_LOOKAHEAD ** N , where N is the queue length.  */
3539e4b17023SJohn Marino static int max_lookahead_tries;
3540e4b17023SJohn Marino 
3541e4b17023SJohn Marino /* The following value is value of hook
3542e4b17023SJohn Marino    `first_cycle_multipass_dfa_lookahead' at the last call of
3543e4b17023SJohn Marino    `max_issue'.  */
3544e4b17023SJohn Marino static int cached_first_cycle_multipass_dfa_lookahead = 0;
3545e4b17023SJohn Marino 
3546e4b17023SJohn Marino /* The following value is value of `issue_rate' at the last call of
3547e4b17023SJohn Marino    `sched_init'.  */
3548e4b17023SJohn Marino static int cached_issue_rate = 0;
3549e4b17023SJohn Marino 
3550e4b17023SJohn Marino /* The following function returns maximal (or close to maximal) number
3551e4b17023SJohn Marino    of insns which can be issued on the same cycle and one of which
3552e4b17023SJohn Marino    insns is insns with the best rank (the first insn in READY).  To
3553e4b17023SJohn Marino    make this function tries different samples of ready insns.  READY
3554e4b17023SJohn Marino    is current queue `ready'.  Global array READY_TRY reflects what
3555e4b17023SJohn Marino    insns are already issued in this try.  The function stops immediately,
3556e4b17023SJohn Marino    if it reached the such a solution, that all instruction can be issued.
3557e4b17023SJohn Marino    INDEX will contain index of the best insn in READY.  The following
3558e4b17023SJohn Marino    function is used only for first cycle multipass scheduling.
3559e4b17023SJohn Marino 
3560e4b17023SJohn Marino    PRIVILEGED_N >= 0
3561e4b17023SJohn Marino 
3562e4b17023SJohn Marino    This function expects recognized insns only.  All USEs,
3563e4b17023SJohn Marino    CLOBBERs, etc must be filtered elsewhere.  */
3564e4b17023SJohn Marino int
max_issue(struct ready_list * ready,int privileged_n,state_t state,bool first_cycle_insn_p,int * index)3565e4b17023SJohn Marino max_issue (struct ready_list *ready, int privileged_n, state_t state,
3566e4b17023SJohn Marino 	   bool first_cycle_insn_p, int *index)
3567e4b17023SJohn Marino {
3568e4b17023SJohn Marino   int n, i, all, n_ready, best, delay, tries_num;
3569e4b17023SJohn Marino   int more_issue;
3570e4b17023SJohn Marino   struct choice_entry *top;
3571e4b17023SJohn Marino   rtx insn;
3572e4b17023SJohn Marino 
3573e4b17023SJohn Marino   n_ready = ready->n_ready;
3574e4b17023SJohn Marino   gcc_assert (dfa_lookahead >= 1 && privileged_n >= 0
3575e4b17023SJohn Marino 	      && privileged_n <= n_ready);
3576e4b17023SJohn Marino 
3577e4b17023SJohn Marino   /* Init MAX_LOOKAHEAD_TRIES.  */
3578e4b17023SJohn Marino   if (cached_first_cycle_multipass_dfa_lookahead != dfa_lookahead)
3579e4b17023SJohn Marino     {
3580e4b17023SJohn Marino       cached_first_cycle_multipass_dfa_lookahead = dfa_lookahead;
3581e4b17023SJohn Marino       max_lookahead_tries = 100;
3582e4b17023SJohn Marino       for (i = 0; i < issue_rate; i++)
3583e4b17023SJohn Marino 	max_lookahead_tries *= dfa_lookahead;
3584e4b17023SJohn Marino     }
3585e4b17023SJohn Marino 
3586e4b17023SJohn Marino   /* Init max_points.  */
3587e4b17023SJohn Marino   more_issue = issue_rate - cycle_issued_insns;
3588e4b17023SJohn Marino   gcc_assert (more_issue >= 0);
3589e4b17023SJohn Marino 
3590e4b17023SJohn Marino   /* The number of the issued insns in the best solution.  */
3591e4b17023SJohn Marino   best = 0;
3592e4b17023SJohn Marino 
3593e4b17023SJohn Marino   top = choice_stack;
3594e4b17023SJohn Marino 
3595e4b17023SJohn Marino   /* Set initial state of the search.  */
3596e4b17023SJohn Marino   memcpy (top->state, state, dfa_state_size);
3597e4b17023SJohn Marino   top->rest = dfa_lookahead;
3598e4b17023SJohn Marino   top->n = 0;
3599e4b17023SJohn Marino   if (targetm.sched.first_cycle_multipass_begin)
3600e4b17023SJohn Marino     targetm.sched.first_cycle_multipass_begin (&top->target_data,
3601e4b17023SJohn Marino 					       ready_try, n_ready,
3602e4b17023SJohn Marino 					       first_cycle_insn_p);
3603e4b17023SJohn Marino 
3604e4b17023SJohn Marino   /* Count the number of the insns to search among.  */
3605e4b17023SJohn Marino   for (all = i = 0; i < n_ready; i++)
3606e4b17023SJohn Marino     if (!ready_try [i])
3607e4b17023SJohn Marino       all++;
3608e4b17023SJohn Marino 
3609e4b17023SJohn Marino   /* I is the index of the insn to try next.  */
3610e4b17023SJohn Marino   i = 0;
3611e4b17023SJohn Marino   tries_num = 0;
3612e4b17023SJohn Marino   for (;;)
3613e4b17023SJohn Marino     {
3614e4b17023SJohn Marino       if (/* If we've reached a dead end or searched enough of what we have
3615e4b17023SJohn Marino 	     been asked...  */
3616e4b17023SJohn Marino 	  top->rest == 0
3617e4b17023SJohn Marino 	  /* or have nothing else to try...  */
3618e4b17023SJohn Marino 	  || i >= n_ready
3619e4b17023SJohn Marino 	  /* or should not issue more.  */
3620e4b17023SJohn Marino 	  || top->n >= more_issue)
3621e4b17023SJohn Marino 	{
3622e4b17023SJohn Marino 	  /* ??? (... || i == n_ready).  */
3623e4b17023SJohn Marino 	  gcc_assert (i <= n_ready);
3624e4b17023SJohn Marino 
3625e4b17023SJohn Marino 	  /* We should not issue more than issue_rate instructions.  */
3626e4b17023SJohn Marino 	  gcc_assert (top->n <= more_issue);
3627e4b17023SJohn Marino 
3628e4b17023SJohn Marino 	  if (top == choice_stack)
3629e4b17023SJohn Marino 	    break;
3630e4b17023SJohn Marino 
3631e4b17023SJohn Marino 	  if (best < top - choice_stack)
3632e4b17023SJohn Marino 	    {
3633e4b17023SJohn Marino 	      if (privileged_n)
3634e4b17023SJohn Marino 		{
3635e4b17023SJohn Marino 		  n = privileged_n;
3636e4b17023SJohn Marino 		  /* Try to find issued privileged insn.  */
3637e4b17023SJohn Marino 		  while (n && !ready_try[--n])
3638e4b17023SJohn Marino 		    ;
3639e4b17023SJohn Marino 		}
3640e4b17023SJohn Marino 
3641e4b17023SJohn Marino 	      if (/* If all insns are equally good...  */
3642e4b17023SJohn Marino 		  privileged_n == 0
3643e4b17023SJohn Marino 		  /* Or a privileged insn will be issued.  */
3644e4b17023SJohn Marino 		  || ready_try[n])
3645e4b17023SJohn Marino 		/* Then we have a solution.  */
3646e4b17023SJohn Marino 		{
3647e4b17023SJohn Marino 		  best = top - choice_stack;
3648e4b17023SJohn Marino 		  /* This is the index of the insn issued first in this
3649e4b17023SJohn Marino 		     solution.  */
3650e4b17023SJohn Marino 		  *index = choice_stack [1].index;
3651e4b17023SJohn Marino 		  if (top->n == more_issue || best == all)
3652e4b17023SJohn Marino 		    break;
3653e4b17023SJohn Marino 		}
3654e4b17023SJohn Marino 	    }
3655e4b17023SJohn Marino 
3656e4b17023SJohn Marino 	  /* Set ready-list index to point to the last insn
3657e4b17023SJohn Marino 	     ('i++' below will advance it to the next insn).  */
3658e4b17023SJohn Marino 	  i = top->index;
3659e4b17023SJohn Marino 
3660e4b17023SJohn Marino 	  /* Backtrack.  */
3661e4b17023SJohn Marino 	  ready_try [i] = 0;
3662e4b17023SJohn Marino 
3663e4b17023SJohn Marino 	  if (targetm.sched.first_cycle_multipass_backtrack)
3664e4b17023SJohn Marino 	    targetm.sched.first_cycle_multipass_backtrack (&top->target_data,
3665e4b17023SJohn Marino 							   ready_try, n_ready);
3666e4b17023SJohn Marino 
3667e4b17023SJohn Marino 	  top--;
3668e4b17023SJohn Marino 	  memcpy (state, top->state, dfa_state_size);
3669e4b17023SJohn Marino 	}
3670e4b17023SJohn Marino       else if (!ready_try [i])
3671e4b17023SJohn Marino 	{
3672e4b17023SJohn Marino 	  tries_num++;
3673e4b17023SJohn Marino 	  if (tries_num > max_lookahead_tries)
3674e4b17023SJohn Marino 	    break;
3675e4b17023SJohn Marino 	  insn = ready_element (ready, i);
3676e4b17023SJohn Marino 	  delay = state_transition (state, insn);
3677e4b17023SJohn Marino 	  if (delay < 0)
3678e4b17023SJohn Marino 	    {
3679e4b17023SJohn Marino 	      if (state_dead_lock_p (state)
3680e4b17023SJohn Marino 		  || insn_finishes_cycle_p (insn))
3681e4b17023SJohn Marino 		/* We won't issue any more instructions in the next
3682e4b17023SJohn Marino 		   choice_state.  */
3683e4b17023SJohn Marino 		top->rest = 0;
3684e4b17023SJohn Marino 	      else
3685e4b17023SJohn Marino 		top->rest--;
3686e4b17023SJohn Marino 
3687e4b17023SJohn Marino 	      n = top->n;
3688e4b17023SJohn Marino 	      if (memcmp (top->state, state, dfa_state_size) != 0)
3689e4b17023SJohn Marino 		n++;
3690e4b17023SJohn Marino 
3691e4b17023SJohn Marino 	      /* Advance to the next choice_entry.  */
3692e4b17023SJohn Marino 	      top++;
3693e4b17023SJohn Marino 	      /* Initialize it.  */
3694e4b17023SJohn Marino 	      top->rest = dfa_lookahead;
3695e4b17023SJohn Marino 	      top->index = i;
3696e4b17023SJohn Marino 	      top->n = n;
3697e4b17023SJohn Marino 	      memcpy (top->state, state, dfa_state_size);
3698e4b17023SJohn Marino 	      ready_try [i] = 1;
3699e4b17023SJohn Marino 
3700e4b17023SJohn Marino 	      if (targetm.sched.first_cycle_multipass_issue)
3701e4b17023SJohn Marino 		targetm.sched.first_cycle_multipass_issue (&top->target_data,
3702e4b17023SJohn Marino 							   ready_try, n_ready,
3703e4b17023SJohn Marino 							   insn,
3704e4b17023SJohn Marino 							   &((top - 1)
3705e4b17023SJohn Marino 							     ->target_data));
3706e4b17023SJohn Marino 
3707e4b17023SJohn Marino 	      i = -1;
3708e4b17023SJohn Marino 	    }
3709e4b17023SJohn Marino 	}
3710e4b17023SJohn Marino 
3711e4b17023SJohn Marino       /* Increase ready-list index.  */
3712e4b17023SJohn Marino       i++;
3713e4b17023SJohn Marino     }
3714e4b17023SJohn Marino 
3715e4b17023SJohn Marino   if (targetm.sched.first_cycle_multipass_end)
3716e4b17023SJohn Marino     targetm.sched.first_cycle_multipass_end (best != 0
3717e4b17023SJohn Marino 					     ? &choice_stack[1].target_data
3718e4b17023SJohn Marino 					     : NULL);
3719e4b17023SJohn Marino 
3720e4b17023SJohn Marino   /* Restore the original state of the DFA.  */
3721e4b17023SJohn Marino   memcpy (state, choice_stack->state, dfa_state_size);
3722e4b17023SJohn Marino 
3723e4b17023SJohn Marino   return best;
3724e4b17023SJohn Marino }
3725e4b17023SJohn Marino 
3726e4b17023SJohn Marino /* The following function chooses insn from READY and modifies
3727e4b17023SJohn Marino    READY.  The following function is used only for first
3728e4b17023SJohn Marino    cycle multipass scheduling.
3729e4b17023SJohn Marino    Return:
3730e4b17023SJohn Marino    -1 if cycle should be advanced,
3731e4b17023SJohn Marino    0 if INSN_PTR is set to point to the desirable insn,
3732e4b17023SJohn Marino    1 if choose_ready () should be restarted without advancing the cycle.  */
3733e4b17023SJohn Marino static int
choose_ready(struct ready_list * ready,bool first_cycle_insn_p,rtx * insn_ptr)3734e4b17023SJohn Marino choose_ready (struct ready_list *ready, bool first_cycle_insn_p,
3735e4b17023SJohn Marino 	      rtx *insn_ptr)
3736e4b17023SJohn Marino {
3737e4b17023SJohn Marino   int lookahead;
3738e4b17023SJohn Marino 
3739e4b17023SJohn Marino   if (dbg_cnt (sched_insn) == false)
3740e4b17023SJohn Marino     {
3741e4b17023SJohn Marino       rtx insn = nonscheduled_insns_begin;
3742e4b17023SJohn Marino       do
3743e4b17023SJohn Marino 	{
3744e4b17023SJohn Marino 	  insn = next_nonnote_insn (insn);
3745e4b17023SJohn Marino 	}
3746e4b17023SJohn Marino       while (QUEUE_INDEX (insn) == QUEUE_SCHEDULED);
3747e4b17023SJohn Marino 
3748e4b17023SJohn Marino       if (QUEUE_INDEX (insn) == QUEUE_READY)
3749e4b17023SJohn Marino 	/* INSN is in the ready_list.  */
3750e4b17023SJohn Marino 	{
3751e4b17023SJohn Marino 	  nonscheduled_insns_begin = insn;
3752e4b17023SJohn Marino 	  ready_remove_insn (insn);
3753e4b17023SJohn Marino 	  *insn_ptr = insn;
3754e4b17023SJohn Marino 	  return 0;
3755e4b17023SJohn Marino 	}
3756e4b17023SJohn Marino 
3757e4b17023SJohn Marino       /* INSN is in the queue.  Advance cycle to move it to the ready list.  */
3758e4b17023SJohn Marino       return -1;
3759e4b17023SJohn Marino     }
3760e4b17023SJohn Marino 
3761e4b17023SJohn Marino   lookahead = 0;
3762e4b17023SJohn Marino 
3763e4b17023SJohn Marino   if (targetm.sched.first_cycle_multipass_dfa_lookahead)
3764e4b17023SJohn Marino     lookahead = targetm.sched.first_cycle_multipass_dfa_lookahead ();
3765e4b17023SJohn Marino   if (lookahead <= 0 || SCHED_GROUP_P (ready_element (ready, 0))
3766e4b17023SJohn Marino       || DEBUG_INSN_P (ready_element (ready, 0)))
3767e4b17023SJohn Marino     {
3768e4b17023SJohn Marino       if (targetm.sched.dispatch (NULL_RTX, IS_DISPATCH_ON))
3769e4b17023SJohn Marino 	*insn_ptr = ready_remove_first_dispatch (ready);
3770e4b17023SJohn Marino       else
3771e4b17023SJohn Marino 	*insn_ptr = ready_remove_first (ready);
3772e4b17023SJohn Marino 
3773e4b17023SJohn Marino       return 0;
3774e4b17023SJohn Marino     }
3775e4b17023SJohn Marino   else
3776e4b17023SJohn Marino     {
3777e4b17023SJohn Marino       /* Try to choose the better insn.  */
3778e4b17023SJohn Marino       int index = 0, i, n;
3779e4b17023SJohn Marino       rtx insn;
3780e4b17023SJohn Marino       int try_data = 1, try_control = 1;
3781e4b17023SJohn Marino       ds_t ts;
3782e4b17023SJohn Marino 
3783e4b17023SJohn Marino       insn = ready_element (ready, 0);
3784e4b17023SJohn Marino       if (INSN_CODE (insn) < 0)
3785e4b17023SJohn Marino 	{
3786e4b17023SJohn Marino 	  *insn_ptr = ready_remove_first (ready);
3787e4b17023SJohn Marino 	  return 0;
3788e4b17023SJohn Marino 	}
3789e4b17023SJohn Marino 
3790e4b17023SJohn Marino       if (spec_info
3791e4b17023SJohn Marino 	  && spec_info->flags & (PREFER_NON_DATA_SPEC
3792e4b17023SJohn Marino 				 | PREFER_NON_CONTROL_SPEC))
3793e4b17023SJohn Marino 	{
3794e4b17023SJohn Marino 	  for (i = 0, n = ready->n_ready; i < n; i++)
3795e4b17023SJohn Marino 	    {
3796e4b17023SJohn Marino 	      rtx x;
3797e4b17023SJohn Marino 	      ds_t s;
3798e4b17023SJohn Marino 
3799e4b17023SJohn Marino 	      x = ready_element (ready, i);
3800e4b17023SJohn Marino 	      s = TODO_SPEC (x);
3801e4b17023SJohn Marino 
3802e4b17023SJohn Marino 	      if (spec_info->flags & PREFER_NON_DATA_SPEC
3803e4b17023SJohn Marino 		  && !(s & DATA_SPEC))
3804e4b17023SJohn Marino 		{
3805e4b17023SJohn Marino 		  try_data = 0;
3806e4b17023SJohn Marino 		  if (!(spec_info->flags & PREFER_NON_CONTROL_SPEC)
3807e4b17023SJohn Marino 		      || !try_control)
3808e4b17023SJohn Marino 		    break;
3809e4b17023SJohn Marino 		}
3810e4b17023SJohn Marino 
3811e4b17023SJohn Marino 	      if (spec_info->flags & PREFER_NON_CONTROL_SPEC
3812e4b17023SJohn Marino 		  && !(s & CONTROL_SPEC))
3813e4b17023SJohn Marino 		{
3814e4b17023SJohn Marino 		  try_control = 0;
3815e4b17023SJohn Marino 		  if (!(spec_info->flags & PREFER_NON_DATA_SPEC) || !try_data)
3816e4b17023SJohn Marino 		    break;
3817e4b17023SJohn Marino 		}
3818e4b17023SJohn Marino 	    }
3819e4b17023SJohn Marino 	}
3820e4b17023SJohn Marino 
3821e4b17023SJohn Marino       ts = TODO_SPEC (insn);
3822e4b17023SJohn Marino       if ((ts & SPECULATIVE)
3823e4b17023SJohn Marino 	  && (((!try_data && (ts & DATA_SPEC))
3824e4b17023SJohn Marino 	       || (!try_control && (ts & CONTROL_SPEC)))
3825e4b17023SJohn Marino 	      || (targetm.sched.first_cycle_multipass_dfa_lookahead_guard_spec
3826e4b17023SJohn Marino 		  && !targetm.sched
3827e4b17023SJohn Marino 		  .first_cycle_multipass_dfa_lookahead_guard_spec (insn))))
3828e4b17023SJohn Marino 	/* Discard speculative instruction that stands first in the ready
3829e4b17023SJohn Marino 	   list.  */
3830e4b17023SJohn Marino 	{
3831e4b17023SJohn Marino 	  change_queue_index (insn, 1);
3832e4b17023SJohn Marino 	  return 1;
3833e4b17023SJohn Marino 	}
3834e4b17023SJohn Marino 
3835e4b17023SJohn Marino       ready_try[0] = 0;
3836e4b17023SJohn Marino 
3837e4b17023SJohn Marino       for (i = 1; i < ready->n_ready; i++)
3838e4b17023SJohn Marino 	{
3839e4b17023SJohn Marino 	  insn = ready_element (ready, i);
3840e4b17023SJohn Marino 
3841e4b17023SJohn Marino 	  ready_try [i]
3842e4b17023SJohn Marino 	    = ((!try_data && (TODO_SPEC (insn) & DATA_SPEC))
3843e4b17023SJohn Marino                || (!try_control && (TODO_SPEC (insn) & CONTROL_SPEC)));
3844e4b17023SJohn Marino 	}
3845e4b17023SJohn Marino 
3846e4b17023SJohn Marino       /* Let the target filter the search space.  */
3847e4b17023SJohn Marino       for (i = 1; i < ready->n_ready; i++)
3848e4b17023SJohn Marino 	if (!ready_try[i])
3849e4b17023SJohn Marino 	  {
3850e4b17023SJohn Marino 	    insn = ready_element (ready, i);
3851e4b17023SJohn Marino 
3852e4b17023SJohn Marino 	    /* If this insn is recognizable we should have already
3853e4b17023SJohn Marino 	       recognized it earlier.
3854e4b17023SJohn Marino 	       ??? Not very clear where this is supposed to be done.
3855e4b17023SJohn Marino 	       See dep_cost_1.  */
3856e4b17023SJohn Marino 	    gcc_checking_assert (INSN_CODE (insn) >= 0
3857e4b17023SJohn Marino 				 || recog_memoized (insn) < 0);
3858e4b17023SJohn Marino 
3859e4b17023SJohn Marino 	    ready_try [i]
3860e4b17023SJohn Marino 	      = (/* INSN_CODE check can be omitted here as it is also done later
3861e4b17023SJohn Marino 		    in max_issue ().  */
3862e4b17023SJohn Marino 		 INSN_CODE (insn) < 0
3863e4b17023SJohn Marino 		 || (targetm.sched.first_cycle_multipass_dfa_lookahead_guard
3864e4b17023SJohn Marino 		     && !targetm.sched.first_cycle_multipass_dfa_lookahead_guard
3865e4b17023SJohn Marino 		     (insn)));
3866e4b17023SJohn Marino 	  }
3867e4b17023SJohn Marino 
3868e4b17023SJohn Marino       if (max_issue (ready, 1, curr_state, first_cycle_insn_p, &index) == 0)
3869e4b17023SJohn Marino 	{
3870e4b17023SJohn Marino 	  *insn_ptr = ready_remove_first (ready);
3871e4b17023SJohn Marino 	  if (sched_verbose >= 4)
3872e4b17023SJohn Marino 	    fprintf (sched_dump, ";;\t\tChosen insn (but can't issue) : %s \n",
3873e4b17023SJohn Marino                      (*current_sched_info->print_insn) (*insn_ptr, 0));
3874e4b17023SJohn Marino 	  return 0;
3875e4b17023SJohn Marino 	}
3876e4b17023SJohn Marino       else
3877e4b17023SJohn Marino 	{
3878e4b17023SJohn Marino 	  if (sched_verbose >= 4)
3879e4b17023SJohn Marino 	    fprintf (sched_dump, ";;\t\tChosen insn : %s\n",
3880e4b17023SJohn Marino 		     (*current_sched_info->print_insn)
3881e4b17023SJohn Marino 		     (ready_element (ready, index), 0));
3882e4b17023SJohn Marino 
3883e4b17023SJohn Marino 	  *insn_ptr = ready_remove (ready, index);
3884e4b17023SJohn Marino 	  return 0;
3885e4b17023SJohn Marino 	}
3886e4b17023SJohn Marino     }
3887e4b17023SJohn Marino }
3888e4b17023SJohn Marino 
3889e4b17023SJohn Marino /* This function is called when we have successfully scheduled a
3890e4b17023SJohn Marino    block.  It uses the schedule stored in the scheduled_insns vector
3891e4b17023SJohn Marino    to rearrange the RTL.  PREV_HEAD is used as the anchor to which we
3892e4b17023SJohn Marino    append the scheduled insns; TAIL is the insn after the scheduled
3893e4b17023SJohn Marino    block.  TARGET_BB is the argument passed to schedule_block.  */
3894e4b17023SJohn Marino 
3895e4b17023SJohn Marino static void
commit_schedule(rtx prev_head,rtx tail,basic_block * target_bb)3896e4b17023SJohn Marino commit_schedule (rtx prev_head, rtx tail, basic_block *target_bb)
3897e4b17023SJohn Marino {
3898e4b17023SJohn Marino   unsigned int i;
3899e4b17023SJohn Marino   rtx insn;
3900e4b17023SJohn Marino 
3901e4b17023SJohn Marino   last_scheduled_insn = prev_head;
3902e4b17023SJohn Marino   for (i = 0;
3903e4b17023SJohn Marino        VEC_iterate (rtx, scheduled_insns, i, insn);
3904e4b17023SJohn Marino        i++)
3905e4b17023SJohn Marino     {
3906e4b17023SJohn Marino       if (control_flow_insn_p (last_scheduled_insn)
3907e4b17023SJohn Marino 	  || current_sched_info->advance_target_bb (*target_bb, insn))
3908e4b17023SJohn Marino 	{
3909e4b17023SJohn Marino 	  *target_bb = current_sched_info->advance_target_bb (*target_bb, 0);
3910e4b17023SJohn Marino 
3911e4b17023SJohn Marino 	  if (sched_verbose)
3912e4b17023SJohn Marino 	    {
3913e4b17023SJohn Marino 	      rtx x;
3914e4b17023SJohn Marino 
3915e4b17023SJohn Marino 	      x = next_real_insn (last_scheduled_insn);
3916e4b17023SJohn Marino 	      gcc_assert (x);
3917e4b17023SJohn Marino 	      dump_new_block_header (1, *target_bb, x, tail);
3918e4b17023SJohn Marino 	    }
3919e4b17023SJohn Marino 
3920e4b17023SJohn Marino 	  last_scheduled_insn = bb_note (*target_bb);
3921e4b17023SJohn Marino 	}
3922e4b17023SJohn Marino 
3923e4b17023SJohn Marino       if (current_sched_info->begin_move_insn)
3924e4b17023SJohn Marino 	(*current_sched_info->begin_move_insn) (insn, last_scheduled_insn);
3925e4b17023SJohn Marino       move_insn (insn, last_scheduled_insn,
3926e4b17023SJohn Marino 		 current_sched_info->next_tail);
3927e4b17023SJohn Marino       if (!DEBUG_INSN_P (insn))
3928e4b17023SJohn Marino 	reemit_notes (insn);
3929e4b17023SJohn Marino       last_scheduled_insn = insn;
3930e4b17023SJohn Marino     }
3931e4b17023SJohn Marino 
3932e4b17023SJohn Marino   VEC_truncate (rtx, scheduled_insns, 0);
3933e4b17023SJohn Marino }
3934e4b17023SJohn Marino 
3935e4b17023SJohn Marino /* Examine all insns on the ready list and queue those which can't be
3936e4b17023SJohn Marino    issued in this cycle.  TEMP_STATE is temporary scheduler state we
3937e4b17023SJohn Marino    can use as scratch space.  If FIRST_CYCLE_INSN_P is true, no insns
3938e4b17023SJohn Marino    have been issued for the current cycle, which means it is valid to
3939e4b17023SJohn Marino    issue an asm statement.
3940e4b17023SJohn Marino 
3941e4b17023SJohn Marino    If SHADOWS_ONLY_P is true, we eliminate all real insns and only
3942e4b17023SJohn Marino    leave those for which SHADOW_P is true.  If MODULO_EPILOGUE is true,
3943e4b17023SJohn Marino    we only leave insns which have an INSN_EXACT_TICK.  */
3944e4b17023SJohn Marino 
3945e4b17023SJohn Marino static void
prune_ready_list(state_t temp_state,bool first_cycle_insn_p,bool shadows_only_p,bool modulo_epilogue_p)3946e4b17023SJohn Marino prune_ready_list (state_t temp_state, bool first_cycle_insn_p,
3947e4b17023SJohn Marino 		  bool shadows_only_p, bool modulo_epilogue_p)
3948e4b17023SJohn Marino {
3949e4b17023SJohn Marino   int i;
3950e4b17023SJohn Marino   bool sched_group_found = false;
3951e4b17023SJohn Marino 
3952e4b17023SJohn Marino  restart:
3953e4b17023SJohn Marino   for (i = 0; i < ready.n_ready; i++)
3954e4b17023SJohn Marino     {
3955e4b17023SJohn Marino       rtx insn = ready_element (&ready, i);
3956e4b17023SJohn Marino       int cost = 0;
3957e4b17023SJohn Marino       const char *reason = "resource conflict";
3958e4b17023SJohn Marino 
3959e4b17023SJohn Marino       if (DEBUG_INSN_P (insn))
3960e4b17023SJohn Marino 	continue;
3961e4b17023SJohn Marino 
3962e4b17023SJohn Marino       if (SCHED_GROUP_P (insn) && !sched_group_found)
3963e4b17023SJohn Marino 	{
3964e4b17023SJohn Marino 	  sched_group_found = true;
3965e4b17023SJohn Marino 	  if (i > 0)
3966e4b17023SJohn Marino 	    goto restart;
3967e4b17023SJohn Marino 	}
3968e4b17023SJohn Marino 
3969e4b17023SJohn Marino       if (sched_group_found && !SCHED_GROUP_P (insn))
3970e4b17023SJohn Marino 	{
3971e4b17023SJohn Marino 	  cost = 1;
3972e4b17023SJohn Marino 	  reason = "not in sched group";
3973e4b17023SJohn Marino 	}
3974e4b17023SJohn Marino       else if (modulo_epilogue_p && INSN_EXACT_TICK (insn) == INVALID_TICK)
3975e4b17023SJohn Marino 	{
3976e4b17023SJohn Marino 	  cost = max_insn_queue_index;
3977e4b17023SJohn Marino 	  reason = "not an epilogue insn";
3978e4b17023SJohn Marino 	}
3979e4b17023SJohn Marino       else if (shadows_only_p && !SHADOW_P (insn))
3980e4b17023SJohn Marino 	{
3981e4b17023SJohn Marino 	  cost = 1;
3982e4b17023SJohn Marino 	  reason = "not a shadow";
3983e4b17023SJohn Marino 	}
3984e4b17023SJohn Marino       else if (recog_memoized (insn) < 0)
3985e4b17023SJohn Marino 	{
3986e4b17023SJohn Marino 	  if (!first_cycle_insn_p
3987e4b17023SJohn Marino 	      && (GET_CODE (PATTERN (insn)) == ASM_INPUT
3988e4b17023SJohn Marino 		  || asm_noperands (PATTERN (insn)) >= 0))
3989e4b17023SJohn Marino 	    cost = 1;
3990e4b17023SJohn Marino 	  reason = "asm";
3991e4b17023SJohn Marino 	}
3992e4b17023SJohn Marino       else if (sched_pressure_p)
3993e4b17023SJohn Marino 	cost = 0;
3994e4b17023SJohn Marino       else
3995e4b17023SJohn Marino 	{
3996e4b17023SJohn Marino 	  int delay_cost = 0;
3997e4b17023SJohn Marino 
3998e4b17023SJohn Marino 	  if (delay_htab)
3999e4b17023SJohn Marino 	    {
4000e4b17023SJohn Marino 	      struct delay_pair *delay_entry;
4001e4b17023SJohn Marino 	      delay_entry
4002e4b17023SJohn Marino 		= (struct delay_pair *)htab_find_with_hash (delay_htab, insn,
4003e4b17023SJohn Marino 							    htab_hash_pointer (insn));
4004e4b17023SJohn Marino 	      while (delay_entry && delay_cost == 0)
4005e4b17023SJohn Marino 		{
4006e4b17023SJohn Marino 		  delay_cost = estimate_shadow_tick (delay_entry);
4007e4b17023SJohn Marino 		  if (delay_cost > max_insn_queue_index)
4008e4b17023SJohn Marino 		    delay_cost = max_insn_queue_index;
4009e4b17023SJohn Marino 		  delay_entry = delay_entry->next_same_i1;
4010e4b17023SJohn Marino 		}
4011e4b17023SJohn Marino 	    }
4012e4b17023SJohn Marino 
4013e4b17023SJohn Marino 	  memcpy (temp_state, curr_state, dfa_state_size);
4014e4b17023SJohn Marino 	  cost = state_transition (temp_state, insn);
4015e4b17023SJohn Marino 	  if (cost < 0)
4016e4b17023SJohn Marino 	    cost = 0;
4017e4b17023SJohn Marino 	  else if (cost == 0)
4018e4b17023SJohn Marino 	    cost = 1;
4019e4b17023SJohn Marino 	  if (cost < delay_cost)
4020e4b17023SJohn Marino 	    {
4021e4b17023SJohn Marino 	      cost = delay_cost;
4022e4b17023SJohn Marino 	      reason = "shadow tick";
4023e4b17023SJohn Marino 	    }
4024e4b17023SJohn Marino 	}
4025e4b17023SJohn Marino       if (cost >= 1)
4026e4b17023SJohn Marino 	{
4027e4b17023SJohn Marino 	  ready_remove (&ready, i);
4028e4b17023SJohn Marino 	  queue_insn (insn, cost, reason);
4029e4b17023SJohn Marino 	  goto restart;
4030e4b17023SJohn Marino 	}
4031e4b17023SJohn Marino     }
4032e4b17023SJohn Marino }
4033e4b17023SJohn Marino 
4034e4b17023SJohn Marino /* Called when we detect that the schedule is impossible.  We examine the
4035e4b17023SJohn Marino    backtrack queue to find the earliest insn that caused this condition.  */
4036e4b17023SJohn Marino 
4037e4b17023SJohn Marino static struct haifa_saved_data *
verify_shadows(void)4038e4b17023SJohn Marino verify_shadows (void)
4039e4b17023SJohn Marino {
4040e4b17023SJohn Marino   struct haifa_saved_data *save, *earliest_fail = NULL;
4041e4b17023SJohn Marino   for (save = backtrack_queue; save; save = save->next)
4042e4b17023SJohn Marino     {
4043e4b17023SJohn Marino       int t;
4044e4b17023SJohn Marino       struct delay_pair *pair = save->delay_pair;
4045e4b17023SJohn Marino       rtx i1 = pair->i1;
4046e4b17023SJohn Marino 
4047e4b17023SJohn Marino       for (; pair; pair = pair->next_same_i1)
4048e4b17023SJohn Marino 	{
4049e4b17023SJohn Marino 	  rtx i2 = pair->i2;
4050e4b17023SJohn Marino 
4051e4b17023SJohn Marino 	  if (QUEUE_INDEX (i2) == QUEUE_SCHEDULED)
4052e4b17023SJohn Marino 	    continue;
4053e4b17023SJohn Marino 
4054e4b17023SJohn Marino 	  t = INSN_TICK (i1) + pair_delay (pair);
4055e4b17023SJohn Marino 	  if (t < clock_var)
4056e4b17023SJohn Marino 	    {
4057e4b17023SJohn Marino 	      if (sched_verbose >= 2)
4058e4b17023SJohn Marino 		fprintf (sched_dump,
4059e4b17023SJohn Marino 			 ";;\t\tfailed delay requirements for %d/%d (%d->%d)"
4060e4b17023SJohn Marino 			 ", not ready\n",
4061e4b17023SJohn Marino 			 INSN_UID (pair->i1), INSN_UID (pair->i2),
4062e4b17023SJohn Marino 			 INSN_TICK (pair->i1), INSN_EXACT_TICK (pair->i2));
4063e4b17023SJohn Marino 	      earliest_fail = save;
4064e4b17023SJohn Marino 	      break;
4065e4b17023SJohn Marino 	    }
4066e4b17023SJohn Marino 	  if (QUEUE_INDEX (i2) >= 0)
4067e4b17023SJohn Marino 	    {
4068e4b17023SJohn Marino 	      int queued_for = INSN_TICK (i2);
4069e4b17023SJohn Marino 
4070e4b17023SJohn Marino 	      if (t < queued_for)
4071e4b17023SJohn Marino 		{
4072e4b17023SJohn Marino 		  if (sched_verbose >= 2)
4073e4b17023SJohn Marino 		    fprintf (sched_dump,
4074e4b17023SJohn Marino 			     ";;\t\tfailed delay requirements for %d/%d"
4075e4b17023SJohn Marino 			     " (%d->%d), queued too late\n",
4076e4b17023SJohn Marino 			     INSN_UID (pair->i1), INSN_UID (pair->i2),
4077e4b17023SJohn Marino 			     INSN_TICK (pair->i1), INSN_EXACT_TICK (pair->i2));
4078e4b17023SJohn Marino 		  earliest_fail = save;
4079e4b17023SJohn Marino 		  break;
4080e4b17023SJohn Marino 		}
4081e4b17023SJohn Marino 	    }
4082e4b17023SJohn Marino 	}
4083e4b17023SJohn Marino     }
4084e4b17023SJohn Marino 
4085e4b17023SJohn Marino   return earliest_fail;
4086e4b17023SJohn Marino }
4087e4b17023SJohn Marino 
4088e4b17023SJohn Marino /* Use forward list scheduling to rearrange insns of block pointed to by
4089e4b17023SJohn Marino    TARGET_BB, possibly bringing insns from subsequent blocks in the same
4090e4b17023SJohn Marino    region.  */
4091e4b17023SJohn Marino 
4092e4b17023SJohn Marino bool
schedule_block(basic_block * target_bb)4093e4b17023SJohn Marino schedule_block (basic_block *target_bb)
4094e4b17023SJohn Marino {
4095e4b17023SJohn Marino   int i;
4096e4b17023SJohn Marino   bool success = modulo_ii == 0;
4097e4b17023SJohn Marino   struct sched_block_state ls;
4098e4b17023SJohn Marino   state_t temp_state = NULL;  /* It is used for multipass scheduling.  */
4099e4b17023SJohn Marino   int sort_p, advance, start_clock_var;
4100e4b17023SJohn Marino 
4101e4b17023SJohn Marino   /* Head/tail info for this block.  */
4102e4b17023SJohn Marino   rtx prev_head = current_sched_info->prev_head;
4103e4b17023SJohn Marino   rtx next_tail = current_sched_info->next_tail;
4104e4b17023SJohn Marino   rtx head = NEXT_INSN (prev_head);
4105e4b17023SJohn Marino   rtx tail = PREV_INSN (next_tail);
4106e4b17023SJohn Marino 
4107e4b17023SJohn Marino   /* We used to have code to avoid getting parameters moved from hard
4108e4b17023SJohn Marino      argument registers into pseudos.
4109e4b17023SJohn Marino 
4110e4b17023SJohn Marino      However, it was removed when it proved to be of marginal benefit
4111e4b17023SJohn Marino      and caused problems because schedule_block and compute_forward_dependences
4112e4b17023SJohn Marino      had different notions of what the "head" insn was.  */
4113e4b17023SJohn Marino 
4114e4b17023SJohn Marino   gcc_assert (head != tail || INSN_P (head));
4115e4b17023SJohn Marino 
4116e4b17023SJohn Marino   haifa_recovery_bb_recently_added_p = false;
4117e4b17023SJohn Marino 
4118e4b17023SJohn Marino   backtrack_queue = NULL;
4119e4b17023SJohn Marino 
4120e4b17023SJohn Marino   /* Debug info.  */
4121e4b17023SJohn Marino   if (sched_verbose)
4122e4b17023SJohn Marino     dump_new_block_header (0, *target_bb, head, tail);
4123e4b17023SJohn Marino 
4124e4b17023SJohn Marino   state_reset (curr_state);
4125e4b17023SJohn Marino 
4126e4b17023SJohn Marino   /* Clear the ready list.  */
4127e4b17023SJohn Marino   ready.first = ready.veclen - 1;
4128e4b17023SJohn Marino   ready.n_ready = 0;
4129e4b17023SJohn Marino   ready.n_debug = 0;
4130e4b17023SJohn Marino 
4131e4b17023SJohn Marino   /* It is used for first cycle multipass scheduling.  */
4132e4b17023SJohn Marino   temp_state = alloca (dfa_state_size);
4133e4b17023SJohn Marino 
4134e4b17023SJohn Marino   if (targetm.sched.init)
4135e4b17023SJohn Marino     targetm.sched.init (sched_dump, sched_verbose, ready.veclen);
4136e4b17023SJohn Marino 
4137e4b17023SJohn Marino   /* We start inserting insns after PREV_HEAD.  */
4138e4b17023SJohn Marino   last_scheduled_insn = nonscheduled_insns_begin = prev_head;
4139e4b17023SJohn Marino   last_nondebug_scheduled_insn = NULL_RTX;
4140e4b17023SJohn Marino 
4141e4b17023SJohn Marino   gcc_assert ((NOTE_P (last_scheduled_insn)
4142e4b17023SJohn Marino 	       || DEBUG_INSN_P (last_scheduled_insn))
4143e4b17023SJohn Marino 	      && BLOCK_FOR_INSN (last_scheduled_insn) == *target_bb);
4144e4b17023SJohn Marino 
4145e4b17023SJohn Marino   /* Initialize INSN_QUEUE.  Q_SIZE is the total number of insns in the
4146e4b17023SJohn Marino      queue.  */
4147e4b17023SJohn Marino   q_ptr = 0;
4148e4b17023SJohn Marino   q_size = 0;
4149e4b17023SJohn Marino 
4150e4b17023SJohn Marino   insn_queue = XALLOCAVEC (rtx, max_insn_queue_index + 1);
4151e4b17023SJohn Marino   memset (insn_queue, 0, (max_insn_queue_index + 1) * sizeof (rtx));
4152e4b17023SJohn Marino 
4153e4b17023SJohn Marino   /* Start just before the beginning of time.  */
4154e4b17023SJohn Marino   clock_var = -1;
4155e4b17023SJohn Marino 
4156e4b17023SJohn Marino   /* We need queue and ready lists and clock_var be initialized
4157e4b17023SJohn Marino      in try_ready () (which is called through init_ready_list ()).  */
4158e4b17023SJohn Marino   (*current_sched_info->init_ready_list) ();
4159e4b17023SJohn Marino 
4160e4b17023SJohn Marino   /* The algorithm is O(n^2) in the number of ready insns at any given
4161e4b17023SJohn Marino      time in the worst case.  Before reload we are more likely to have
4162e4b17023SJohn Marino      big lists so truncate them to a reasonable size.  */
4163e4b17023SJohn Marino   if (!reload_completed
4164e4b17023SJohn Marino       && ready.n_ready - ready.n_debug > MAX_SCHED_READY_INSNS)
4165e4b17023SJohn Marino     {
4166e4b17023SJohn Marino       ready_sort (&ready);
4167e4b17023SJohn Marino 
4168e4b17023SJohn Marino       /* Find first free-standing insn past MAX_SCHED_READY_INSNS.
4169e4b17023SJohn Marino          If there are debug insns, we know they're first.  */
4170e4b17023SJohn Marino       for (i = MAX_SCHED_READY_INSNS + ready.n_debug; i < ready.n_ready; i++)
4171e4b17023SJohn Marino 	if (!SCHED_GROUP_P (ready_element (&ready, i)))
4172e4b17023SJohn Marino 	  break;
4173e4b17023SJohn Marino 
4174e4b17023SJohn Marino       if (sched_verbose >= 2)
4175e4b17023SJohn Marino 	{
4176e4b17023SJohn Marino 	  fprintf (sched_dump,
4177e4b17023SJohn Marino 		   ";;\t\tReady list on entry: %d insns\n", ready.n_ready);
4178e4b17023SJohn Marino 	  fprintf (sched_dump,
4179e4b17023SJohn Marino 		   ";;\t\t before reload => truncated to %d insns\n", i);
4180e4b17023SJohn Marino 	}
4181e4b17023SJohn Marino 
4182e4b17023SJohn Marino       /* Delay all insns past it for 1 cycle.  If debug counter is
4183e4b17023SJohn Marino 	 activated make an exception for the insn right after
4184e4b17023SJohn Marino 	 nonscheduled_insns_begin.  */
4185e4b17023SJohn Marino       {
4186e4b17023SJohn Marino 	rtx skip_insn;
4187e4b17023SJohn Marino 
4188e4b17023SJohn Marino 	if (dbg_cnt (sched_insn) == false)
4189e4b17023SJohn Marino 	  skip_insn = next_nonnote_insn (nonscheduled_insns_begin);
4190e4b17023SJohn Marino 	else
4191e4b17023SJohn Marino 	  skip_insn = NULL_RTX;
4192e4b17023SJohn Marino 
4193e4b17023SJohn Marino 	while (i < ready.n_ready)
4194e4b17023SJohn Marino 	  {
4195e4b17023SJohn Marino 	    rtx insn;
4196e4b17023SJohn Marino 
4197e4b17023SJohn Marino 	    insn = ready_remove (&ready, i);
4198e4b17023SJohn Marino 
4199e4b17023SJohn Marino 	    if (insn != skip_insn)
4200e4b17023SJohn Marino 	      queue_insn (insn, 1, "list truncated");
4201e4b17023SJohn Marino 	  }
4202e4b17023SJohn Marino 	if (skip_insn)
4203e4b17023SJohn Marino 	  ready_add (&ready, skip_insn, true);
4204e4b17023SJohn Marino       }
4205e4b17023SJohn Marino     }
4206e4b17023SJohn Marino 
4207e4b17023SJohn Marino   /* Now we can restore basic block notes and maintain precise cfg.  */
4208e4b17023SJohn Marino   restore_bb_notes (*target_bb);
4209e4b17023SJohn Marino 
4210e4b17023SJohn Marino   last_clock_var = -1;
4211e4b17023SJohn Marino 
4212e4b17023SJohn Marino   advance = 0;
4213e4b17023SJohn Marino 
4214e4b17023SJohn Marino   gcc_assert (VEC_length (rtx, scheduled_insns) == 0);
4215e4b17023SJohn Marino   sort_p = TRUE;
4216e4b17023SJohn Marino   must_backtrack = false;
4217e4b17023SJohn Marino   modulo_insns_scheduled = 0;
4218e4b17023SJohn Marino 
4219e4b17023SJohn Marino   ls.modulo_epilogue = false;
4220e4b17023SJohn Marino 
4221e4b17023SJohn Marino   /* Loop until all the insns in BB are scheduled.  */
4222e4b17023SJohn Marino   while ((*current_sched_info->schedule_more_p) ())
4223e4b17023SJohn Marino     {
4224e4b17023SJohn Marino       do
4225e4b17023SJohn Marino 	{
4226e4b17023SJohn Marino 	  start_clock_var = clock_var;
4227e4b17023SJohn Marino 
4228e4b17023SJohn Marino 	  clock_var++;
4229e4b17023SJohn Marino 
4230e4b17023SJohn Marino 	  advance_one_cycle ();
4231e4b17023SJohn Marino 
4232e4b17023SJohn Marino 	  /* Add to the ready list all pending insns that can be issued now.
4233e4b17023SJohn Marino 	     If there are no ready insns, increment clock until one
4234e4b17023SJohn Marino 	     is ready and add all pending insns at that point to the ready
4235e4b17023SJohn Marino 	     list.  */
4236e4b17023SJohn Marino 	  queue_to_ready (&ready);
4237e4b17023SJohn Marino 
4238e4b17023SJohn Marino 	  gcc_assert (ready.n_ready);
4239e4b17023SJohn Marino 
4240e4b17023SJohn Marino 	  if (sched_verbose >= 2)
4241e4b17023SJohn Marino 	    {
4242e4b17023SJohn Marino 	      fprintf (sched_dump, ";;\t\tReady list after queue_to_ready:  ");
4243e4b17023SJohn Marino 	      debug_ready_list (&ready);
4244e4b17023SJohn Marino 	    }
4245e4b17023SJohn Marino 	  advance -= clock_var - start_clock_var;
4246e4b17023SJohn Marino 	}
4247e4b17023SJohn Marino       while (advance > 0);
4248e4b17023SJohn Marino 
4249e4b17023SJohn Marino       if (ls.modulo_epilogue)
4250e4b17023SJohn Marino 	{
4251e4b17023SJohn Marino 	  int stage = clock_var / modulo_ii;
4252e4b17023SJohn Marino 	  if (stage > modulo_last_stage * 2 + 2)
4253e4b17023SJohn Marino 	    {
4254e4b17023SJohn Marino 	      if (sched_verbose >= 2)
4255e4b17023SJohn Marino 		fprintf (sched_dump,
4256e4b17023SJohn Marino 			 ";;\t\tmodulo scheduled succeeded at II %d\n",
4257e4b17023SJohn Marino 			 modulo_ii);
4258e4b17023SJohn Marino 	      success = true;
4259e4b17023SJohn Marino 	      goto end_schedule;
4260e4b17023SJohn Marino 	    }
4261e4b17023SJohn Marino 	}
4262e4b17023SJohn Marino       else if (modulo_ii > 0)
4263e4b17023SJohn Marino 	{
4264e4b17023SJohn Marino 	  int stage = clock_var / modulo_ii;
4265e4b17023SJohn Marino 	  if (stage > modulo_max_stages)
4266e4b17023SJohn Marino 	    {
4267e4b17023SJohn Marino 	      if (sched_verbose >= 2)
4268e4b17023SJohn Marino 		fprintf (sched_dump,
4269e4b17023SJohn Marino 			 ";;\t\tfailing schedule due to excessive stages\n");
4270e4b17023SJohn Marino 	      goto end_schedule;
4271e4b17023SJohn Marino 	    }
4272e4b17023SJohn Marino 	  if (modulo_n_insns == modulo_insns_scheduled
4273e4b17023SJohn Marino 	      && stage > modulo_last_stage)
4274e4b17023SJohn Marino 	    {
4275e4b17023SJohn Marino 	      if (sched_verbose >= 2)
4276e4b17023SJohn Marino 		fprintf (sched_dump,
4277e4b17023SJohn Marino 			 ";;\t\tfound kernel after %d stages, II %d\n",
4278e4b17023SJohn Marino 			 stage, modulo_ii);
4279e4b17023SJohn Marino 	      ls.modulo_epilogue = true;
4280e4b17023SJohn Marino 	    }
4281e4b17023SJohn Marino 	}
4282e4b17023SJohn Marino 
4283e4b17023SJohn Marino       prune_ready_list (temp_state, true, false, ls.modulo_epilogue);
4284e4b17023SJohn Marino       if (ready.n_ready == 0)
4285e4b17023SJohn Marino 	continue;
4286e4b17023SJohn Marino       if (must_backtrack)
4287e4b17023SJohn Marino 	goto do_backtrack;
4288e4b17023SJohn Marino 
4289e4b17023SJohn Marino       ls.first_cycle_insn_p = true;
4290e4b17023SJohn Marino       ls.shadows_only_p = false;
4291e4b17023SJohn Marino       cycle_issued_insns = 0;
4292e4b17023SJohn Marino       ls.can_issue_more = issue_rate;
4293e4b17023SJohn Marino       for (;;)
4294e4b17023SJohn Marino 	{
4295e4b17023SJohn Marino 	  rtx insn;
4296e4b17023SJohn Marino 	  int cost;
4297e4b17023SJohn Marino 	  bool asm_p;
4298e4b17023SJohn Marino 
4299e4b17023SJohn Marino 	  if (sort_p && ready.n_ready > 0)
4300e4b17023SJohn Marino 	    {
4301e4b17023SJohn Marino 	      /* Sort the ready list based on priority.  This must be
4302e4b17023SJohn Marino 		 done every iteration through the loop, as schedule_insn
4303e4b17023SJohn Marino 		 may have readied additional insns that will not be
4304e4b17023SJohn Marino 		 sorted correctly.  */
4305e4b17023SJohn Marino 	      ready_sort (&ready);
4306e4b17023SJohn Marino 
4307e4b17023SJohn Marino 	      if (sched_verbose >= 2)
4308e4b17023SJohn Marino 		{
4309e4b17023SJohn Marino 		  fprintf (sched_dump, ";;\t\tReady list after ready_sort:  ");
4310e4b17023SJohn Marino 		  debug_ready_list (&ready);
4311e4b17023SJohn Marino 		}
4312e4b17023SJohn Marino 	    }
4313e4b17023SJohn Marino 
4314e4b17023SJohn Marino 	  /* We don't want md sched reorder to even see debug isns, so put
4315e4b17023SJohn Marino 	     them out right away.  */
4316e4b17023SJohn Marino 	  if (ready.n_ready && DEBUG_INSN_P (ready_element (&ready, 0))
4317e4b17023SJohn Marino 	      && (*current_sched_info->schedule_more_p) ())
4318e4b17023SJohn Marino 	    {
4319e4b17023SJohn Marino 	      while (ready.n_ready && DEBUG_INSN_P (ready_element (&ready, 0)))
4320e4b17023SJohn Marino 		{
4321e4b17023SJohn Marino 		  rtx insn = ready_remove_first (&ready);
4322e4b17023SJohn Marino 		  gcc_assert (DEBUG_INSN_P (insn));
4323e4b17023SJohn Marino 		  (*current_sched_info->begin_schedule_ready) (insn);
4324e4b17023SJohn Marino 		  VEC_safe_push (rtx, heap, scheduled_insns, insn);
4325e4b17023SJohn Marino 		  last_scheduled_insn = insn;
4326e4b17023SJohn Marino 		  advance = schedule_insn (insn);
4327e4b17023SJohn Marino 		  gcc_assert (advance == 0);
4328e4b17023SJohn Marino 		  if (ready.n_ready > 0)
4329e4b17023SJohn Marino 		    ready_sort (&ready);
4330e4b17023SJohn Marino 		}
4331e4b17023SJohn Marino 	    }
4332e4b17023SJohn Marino 
4333e4b17023SJohn Marino 	  if (ls.first_cycle_insn_p && !ready.n_ready)
4334e4b17023SJohn Marino 	    break;
4335e4b17023SJohn Marino 
4336e4b17023SJohn Marino 	resume_after_backtrack:
4337e4b17023SJohn Marino 	  /* Allow the target to reorder the list, typically for
4338e4b17023SJohn Marino 	     better instruction bundling.  */
4339e4b17023SJohn Marino 	  if (sort_p
4340e4b17023SJohn Marino 	      && (ready.n_ready == 0
4341e4b17023SJohn Marino 		  || !SCHED_GROUP_P (ready_element (&ready, 0))))
4342e4b17023SJohn Marino 	    {
4343e4b17023SJohn Marino 	      if (ls.first_cycle_insn_p && targetm.sched.reorder)
4344e4b17023SJohn Marino 		ls.can_issue_more
4345e4b17023SJohn Marino 		  = targetm.sched.reorder (sched_dump, sched_verbose,
4346e4b17023SJohn Marino 					   ready_lastpos (&ready),
4347e4b17023SJohn Marino 					   &ready.n_ready, clock_var);
4348e4b17023SJohn Marino 	      else if (!ls.first_cycle_insn_p && targetm.sched.reorder2)
4349e4b17023SJohn Marino 		ls.can_issue_more
4350e4b17023SJohn Marino 		  = targetm.sched.reorder2 (sched_dump, sched_verbose,
4351e4b17023SJohn Marino 					    ready.n_ready
4352e4b17023SJohn Marino 					    ? ready_lastpos (&ready) : NULL,
4353e4b17023SJohn Marino 					    &ready.n_ready, clock_var);
4354e4b17023SJohn Marino 	    }
4355e4b17023SJohn Marino 
4356e4b17023SJohn Marino 	restart_choose_ready:
4357e4b17023SJohn Marino 	  if (sched_verbose >= 2)
4358e4b17023SJohn Marino 	    {
4359e4b17023SJohn Marino 	      fprintf (sched_dump, ";;\tReady list (t = %3d):  ",
4360e4b17023SJohn Marino 		       clock_var);
4361e4b17023SJohn Marino 	      debug_ready_list (&ready);
4362e4b17023SJohn Marino 	      if (sched_pressure_p)
4363e4b17023SJohn Marino 		print_curr_reg_pressure ();
4364e4b17023SJohn Marino 	    }
4365e4b17023SJohn Marino 
4366e4b17023SJohn Marino 	  if (ready.n_ready == 0
4367e4b17023SJohn Marino 	      && ls.can_issue_more
4368e4b17023SJohn Marino 	      && reload_completed)
4369e4b17023SJohn Marino 	    {
4370e4b17023SJohn Marino 	      /* Allow scheduling insns directly from the queue in case
4371e4b17023SJohn Marino 		 there's nothing better to do (ready list is empty) but
4372e4b17023SJohn Marino 		 there are still vacant dispatch slots in the current cycle.  */
4373e4b17023SJohn Marino 	      if (sched_verbose >= 6)
4374e4b17023SJohn Marino 		fprintf (sched_dump,";;\t\tSecond chance\n");
4375e4b17023SJohn Marino 	      memcpy (temp_state, curr_state, dfa_state_size);
4376e4b17023SJohn Marino 	      if (early_queue_to_ready (temp_state, &ready))
4377e4b17023SJohn Marino 		ready_sort (&ready);
4378e4b17023SJohn Marino 	    }
4379e4b17023SJohn Marino 
4380e4b17023SJohn Marino 	  if (ready.n_ready == 0
4381e4b17023SJohn Marino 	      || !ls.can_issue_more
4382e4b17023SJohn Marino 	      || state_dead_lock_p (curr_state)
4383e4b17023SJohn Marino 	      || !(*current_sched_info->schedule_more_p) ())
4384e4b17023SJohn Marino 	    break;
4385e4b17023SJohn Marino 
4386e4b17023SJohn Marino 	  /* Select and remove the insn from the ready list.  */
4387e4b17023SJohn Marino 	  if (sort_p)
4388e4b17023SJohn Marino 	    {
4389e4b17023SJohn Marino 	      int res;
4390e4b17023SJohn Marino 
4391e4b17023SJohn Marino 	      insn = NULL_RTX;
4392e4b17023SJohn Marino 	      res = choose_ready (&ready, ls.first_cycle_insn_p, &insn);
4393e4b17023SJohn Marino 
4394e4b17023SJohn Marino 	      if (res < 0)
4395e4b17023SJohn Marino 		/* Finish cycle.  */
4396e4b17023SJohn Marino 		break;
4397e4b17023SJohn Marino 	      if (res > 0)
4398e4b17023SJohn Marino 		goto restart_choose_ready;
4399e4b17023SJohn Marino 
4400e4b17023SJohn Marino 	      gcc_assert (insn != NULL_RTX);
4401e4b17023SJohn Marino 	    }
4402e4b17023SJohn Marino 	  else
4403e4b17023SJohn Marino 	    insn = ready_remove_first (&ready);
4404e4b17023SJohn Marino 
4405e4b17023SJohn Marino 	  if (sched_pressure_p && INSN_TICK (insn) > clock_var)
4406e4b17023SJohn Marino 	    {
4407e4b17023SJohn Marino 	      ready_add (&ready, insn, true);
4408e4b17023SJohn Marino 	      advance = 1;
4409e4b17023SJohn Marino 	      break;
4410e4b17023SJohn Marino 	    }
4411e4b17023SJohn Marino 
4412e4b17023SJohn Marino 	  if (targetm.sched.dfa_new_cycle
4413e4b17023SJohn Marino 	      && targetm.sched.dfa_new_cycle (sched_dump, sched_verbose,
4414e4b17023SJohn Marino 					      insn, last_clock_var,
4415e4b17023SJohn Marino 					      clock_var, &sort_p))
4416e4b17023SJohn Marino 	    /* SORT_P is used by the target to override sorting
4417e4b17023SJohn Marino 	       of the ready list.  This is needed when the target
4418e4b17023SJohn Marino 	       has modified its internal structures expecting that
4419e4b17023SJohn Marino 	       the insn will be issued next.  As we need the insn
4420e4b17023SJohn Marino 	       to have the highest priority (so it will be returned by
4421e4b17023SJohn Marino 	       the ready_remove_first call above), we invoke
4422e4b17023SJohn Marino 	       ready_add (&ready, insn, true).
4423e4b17023SJohn Marino 	       But, still, there is one issue: INSN can be later
4424e4b17023SJohn Marino 	       discarded by scheduler's front end through
4425e4b17023SJohn Marino 	       current_sched_info->can_schedule_ready_p, hence, won't
4426e4b17023SJohn Marino 	       be issued next.  */
4427e4b17023SJohn Marino 	    {
4428e4b17023SJohn Marino 	      ready_add (&ready, insn, true);
4429e4b17023SJohn Marino               break;
4430e4b17023SJohn Marino 	    }
4431e4b17023SJohn Marino 
4432e4b17023SJohn Marino 	  sort_p = TRUE;
4433e4b17023SJohn Marino 
4434e4b17023SJohn Marino 	  if (current_sched_info->can_schedule_ready_p
4435e4b17023SJohn Marino 	      && ! (*current_sched_info->can_schedule_ready_p) (insn))
4436e4b17023SJohn Marino 	    /* We normally get here only if we don't want to move
4437e4b17023SJohn Marino 	       insn from the split block.  */
4438e4b17023SJohn Marino 	    {
4439e4b17023SJohn Marino 	      TODO_SPEC (insn) = HARD_DEP;
4440e4b17023SJohn Marino 	      goto restart_choose_ready;
4441e4b17023SJohn Marino 	    }
4442e4b17023SJohn Marino 
4443e4b17023SJohn Marino 	  if (delay_htab)
4444e4b17023SJohn Marino 	    {
4445e4b17023SJohn Marino 	      /* If this insn is the first part of a delay-slot pair, record a
4446e4b17023SJohn Marino 		 backtrack point.  */
4447e4b17023SJohn Marino 	      struct delay_pair *delay_entry;
4448e4b17023SJohn Marino 	      delay_entry
4449e4b17023SJohn Marino 		= (struct delay_pair *)htab_find_with_hash (delay_htab, insn,
4450e4b17023SJohn Marino 							    htab_hash_pointer (insn));
4451e4b17023SJohn Marino 	      if (delay_entry)
4452e4b17023SJohn Marino 		{
4453e4b17023SJohn Marino 		  save_backtrack_point (delay_entry, ls);
4454e4b17023SJohn Marino 		  if (sched_verbose >= 2)
4455e4b17023SJohn Marino 		    fprintf (sched_dump, ";;\t\tsaving backtrack point\n");
4456e4b17023SJohn Marino 		}
4457e4b17023SJohn Marino 	    }
4458e4b17023SJohn Marino 
4459e4b17023SJohn Marino 	  /* DECISION is made.  */
4460e4b17023SJohn Marino 
4461e4b17023SJohn Marino 	  if (modulo_ii > 0 && INSN_UID (insn) < modulo_iter0_max_uid)
4462e4b17023SJohn Marino 	    {
4463e4b17023SJohn Marino 	      modulo_insns_scheduled++;
4464e4b17023SJohn Marino 	      modulo_last_stage = clock_var / modulo_ii;
4465e4b17023SJohn Marino 	    }
4466e4b17023SJohn Marino           if (TODO_SPEC (insn) & SPECULATIVE)
4467e4b17023SJohn Marino             generate_recovery_code (insn);
4468e4b17023SJohn Marino 
4469e4b17023SJohn Marino 	  if (targetm.sched.dispatch (NULL_RTX, IS_DISPATCH_ON))
4470e4b17023SJohn Marino 	    targetm.sched.dispatch_do (insn, ADD_TO_DISPATCH_WINDOW);
4471e4b17023SJohn Marino 
4472e4b17023SJohn Marino 	  /* Update counters, etc in the scheduler's front end.  */
4473e4b17023SJohn Marino 	  (*current_sched_info->begin_schedule_ready) (insn);
4474e4b17023SJohn Marino 	  VEC_safe_push (rtx, heap, scheduled_insns, insn);
4475e4b17023SJohn Marino 	  gcc_assert (NONDEBUG_INSN_P (insn));
4476e4b17023SJohn Marino 	  last_nondebug_scheduled_insn = last_scheduled_insn = insn;
4477e4b17023SJohn Marino 
4478e4b17023SJohn Marino 	  if (recog_memoized (insn) >= 0)
4479e4b17023SJohn Marino 	    {
4480e4b17023SJohn Marino 	      memcpy (temp_state, curr_state, dfa_state_size);
4481e4b17023SJohn Marino 	      cost = state_transition (curr_state, insn);
4482e4b17023SJohn Marino 	      if (!sched_pressure_p)
4483e4b17023SJohn Marino 		gcc_assert (cost < 0);
4484e4b17023SJohn Marino 	      if (memcmp (temp_state, curr_state, dfa_state_size) != 0)
4485e4b17023SJohn Marino 		cycle_issued_insns++;
4486e4b17023SJohn Marino 	      asm_p = false;
4487e4b17023SJohn Marino 	    }
4488e4b17023SJohn Marino 	  else
4489e4b17023SJohn Marino 	    asm_p = (GET_CODE (PATTERN (insn)) == ASM_INPUT
4490e4b17023SJohn Marino 		     || asm_noperands (PATTERN (insn)) >= 0);
4491e4b17023SJohn Marino 
4492e4b17023SJohn Marino 	  if (targetm.sched.variable_issue)
4493e4b17023SJohn Marino 	    ls.can_issue_more =
4494e4b17023SJohn Marino 	      targetm.sched.variable_issue (sched_dump, sched_verbose,
4495e4b17023SJohn Marino 					    insn, ls.can_issue_more);
4496e4b17023SJohn Marino 	  /* A naked CLOBBER or USE generates no instruction, so do
4497e4b17023SJohn Marino 	     not count them against the issue rate.  */
4498e4b17023SJohn Marino 	  else if (GET_CODE (PATTERN (insn)) != USE
4499e4b17023SJohn Marino 		   && GET_CODE (PATTERN (insn)) != CLOBBER)
4500e4b17023SJohn Marino 	    ls.can_issue_more--;
4501e4b17023SJohn Marino 	  advance = schedule_insn (insn);
4502e4b17023SJohn Marino 
4503e4b17023SJohn Marino 	  if (SHADOW_P (insn))
4504e4b17023SJohn Marino 	    ls.shadows_only_p = true;
4505e4b17023SJohn Marino 
4506e4b17023SJohn Marino 	  /* After issuing an asm insn we should start a new cycle.  */
4507e4b17023SJohn Marino 	  if (advance == 0 && asm_p)
4508e4b17023SJohn Marino 	    advance = 1;
4509e4b17023SJohn Marino 
4510e4b17023SJohn Marino 	  if (must_backtrack)
4511e4b17023SJohn Marino 	    break;
4512e4b17023SJohn Marino 
4513e4b17023SJohn Marino 	  if (advance != 0)
4514e4b17023SJohn Marino 	    break;
4515e4b17023SJohn Marino 
4516e4b17023SJohn Marino 	  ls.first_cycle_insn_p = false;
4517e4b17023SJohn Marino 	  if (ready.n_ready > 0)
4518e4b17023SJohn Marino 	    prune_ready_list (temp_state, false, ls.shadows_only_p,
4519e4b17023SJohn Marino 			      ls.modulo_epilogue);
4520e4b17023SJohn Marino 	}
4521e4b17023SJohn Marino 
4522e4b17023SJohn Marino     do_backtrack:
4523e4b17023SJohn Marino       if (!must_backtrack)
4524e4b17023SJohn Marino 	for (i = 0; i < ready.n_ready; i++)
4525e4b17023SJohn Marino 	  {
4526e4b17023SJohn Marino 	    rtx insn = ready_element (&ready, i);
4527e4b17023SJohn Marino 	    if (INSN_EXACT_TICK (insn) == clock_var)
4528e4b17023SJohn Marino 	      {
4529e4b17023SJohn Marino 		must_backtrack = true;
4530e4b17023SJohn Marino 		clock_var++;
4531e4b17023SJohn Marino 		break;
4532e4b17023SJohn Marino 	      }
4533e4b17023SJohn Marino 	  }
4534e4b17023SJohn Marino       if (must_backtrack && modulo_ii > 0)
4535e4b17023SJohn Marino 	{
4536e4b17023SJohn Marino 	  if (modulo_backtracks_left == 0)
4537e4b17023SJohn Marino 	    goto end_schedule;
4538e4b17023SJohn Marino 	  modulo_backtracks_left--;
4539e4b17023SJohn Marino 	}
4540e4b17023SJohn Marino       while (must_backtrack)
4541e4b17023SJohn Marino 	{
4542e4b17023SJohn Marino 	  struct haifa_saved_data *failed;
4543e4b17023SJohn Marino 	  rtx failed_insn;
4544e4b17023SJohn Marino 
4545e4b17023SJohn Marino 	  must_backtrack = false;
4546e4b17023SJohn Marino 	  failed = verify_shadows ();
4547e4b17023SJohn Marino 	  gcc_assert (failed);
4548e4b17023SJohn Marino 
4549e4b17023SJohn Marino 	  failed_insn = failed->delay_pair->i1;
4550e4b17023SJohn Marino 	  toggle_cancelled_flags (false);
4551e4b17023SJohn Marino 	  unschedule_insns_until (failed_insn);
4552e4b17023SJohn Marino 	  while (failed != backtrack_queue)
4553e4b17023SJohn Marino 	    free_topmost_backtrack_point (true);
4554e4b17023SJohn Marino 	  restore_last_backtrack_point (&ls);
4555e4b17023SJohn Marino 	  if (sched_verbose >= 2)
4556e4b17023SJohn Marino 	    fprintf (sched_dump, ";;\t\trewind to cycle %d\n", clock_var);
4557e4b17023SJohn Marino 	  /* Delay by at least a cycle.  This could cause additional
4558e4b17023SJohn Marino 	     backtracking.  */
4559e4b17023SJohn Marino 	  queue_insn (failed_insn, 1, "backtracked");
4560e4b17023SJohn Marino 	  advance = 0;
4561e4b17023SJohn Marino 	  if (must_backtrack)
4562e4b17023SJohn Marino 	    continue;
4563e4b17023SJohn Marino 	  if (ready.n_ready > 0)
4564e4b17023SJohn Marino 	    goto resume_after_backtrack;
4565e4b17023SJohn Marino 	  else
4566e4b17023SJohn Marino 	    {
4567e4b17023SJohn Marino 	      if (clock_var == 0 && ls.first_cycle_insn_p)
4568e4b17023SJohn Marino 		goto end_schedule;
4569e4b17023SJohn Marino 	      advance = 1;
4570e4b17023SJohn Marino 	      break;
4571e4b17023SJohn Marino 	    }
4572e4b17023SJohn Marino 	}
4573e4b17023SJohn Marino     }
4574e4b17023SJohn Marino   if (ls.modulo_epilogue)
4575e4b17023SJohn Marino     success = true;
4576e4b17023SJohn Marino  end_schedule:
4577e4b17023SJohn Marino   if (modulo_ii > 0)
4578e4b17023SJohn Marino     {
4579e4b17023SJohn Marino       /* Once again, debug insn suckiness: they can be on the ready list
4580e4b17023SJohn Marino 	 even if they have unresolved dependencies.  To make our view
4581e4b17023SJohn Marino 	 of the world consistent, remove such "ready" insns.  */
4582e4b17023SJohn Marino     restart_debug_insn_loop:
4583e4b17023SJohn Marino       for (i = ready.n_ready - 1; i >= 0; i--)
4584e4b17023SJohn Marino 	{
4585e4b17023SJohn Marino 	  rtx x;
4586e4b17023SJohn Marino 
4587e4b17023SJohn Marino 	  x = ready_element (&ready, i);
4588e4b17023SJohn Marino 	  if (DEPS_LIST_FIRST (INSN_HARD_BACK_DEPS (x)) != NULL
4589e4b17023SJohn Marino 	      || DEPS_LIST_FIRST (INSN_SPEC_BACK_DEPS (x)) != NULL)
4590e4b17023SJohn Marino 	    {
4591e4b17023SJohn Marino 	      ready_remove (&ready, i);
4592e4b17023SJohn Marino 	      goto restart_debug_insn_loop;
4593e4b17023SJohn Marino 	    }
4594e4b17023SJohn Marino 	}
4595e4b17023SJohn Marino       for (i = ready.n_ready - 1; i >= 0; i--)
4596e4b17023SJohn Marino 	{
4597e4b17023SJohn Marino 	  rtx x;
4598e4b17023SJohn Marino 
4599e4b17023SJohn Marino 	  x = ready_element (&ready, i);
4600e4b17023SJohn Marino 	  resolve_dependencies (x);
4601e4b17023SJohn Marino 	}
4602e4b17023SJohn Marino       for (i = 0; i <= max_insn_queue_index; i++)
4603e4b17023SJohn Marino 	{
4604e4b17023SJohn Marino 	  rtx link;
4605e4b17023SJohn Marino 	  while ((link = insn_queue[i]) != NULL)
4606e4b17023SJohn Marino 	    {
4607e4b17023SJohn Marino 	      rtx x = XEXP (link, 0);
4608e4b17023SJohn Marino 	      insn_queue[i] = XEXP (link, 1);
4609e4b17023SJohn Marino 	      QUEUE_INDEX (x) = QUEUE_NOWHERE;
4610e4b17023SJohn Marino 	      free_INSN_LIST_node (link);
4611e4b17023SJohn Marino 	      resolve_dependencies (x);
4612e4b17023SJohn Marino 	    }
4613e4b17023SJohn Marino 	}
4614e4b17023SJohn Marino     }
4615e4b17023SJohn Marino 
4616e4b17023SJohn Marino   /* Debug info.  */
4617e4b17023SJohn Marino   if (sched_verbose)
4618e4b17023SJohn Marino     {
4619e4b17023SJohn Marino       fprintf (sched_dump, ";;\tReady list (final):  ");
4620e4b17023SJohn Marino       debug_ready_list (&ready);
4621e4b17023SJohn Marino     }
4622e4b17023SJohn Marino 
4623e4b17023SJohn Marino   if (modulo_ii == 0 && current_sched_info->queue_must_finish_empty)
4624e4b17023SJohn Marino     /* Sanity check -- queue must be empty now.  Meaningless if region has
4625e4b17023SJohn Marino        multiple bbs.  */
4626e4b17023SJohn Marino     gcc_assert (!q_size && !ready.n_ready && !ready.n_debug);
4627e4b17023SJohn Marino   else if (modulo_ii == 0)
4628e4b17023SJohn Marino     {
4629e4b17023SJohn Marino       /* We must maintain QUEUE_INDEX between blocks in region.  */
4630e4b17023SJohn Marino       for (i = ready.n_ready - 1; i >= 0; i--)
4631e4b17023SJohn Marino 	{
4632e4b17023SJohn Marino 	  rtx x;
4633e4b17023SJohn Marino 
4634e4b17023SJohn Marino 	  x = ready_element (&ready, i);
4635e4b17023SJohn Marino 	  QUEUE_INDEX (x) = QUEUE_NOWHERE;
4636e4b17023SJohn Marino 	  TODO_SPEC (x) = HARD_DEP;
4637e4b17023SJohn Marino 	}
4638e4b17023SJohn Marino 
4639e4b17023SJohn Marino       if (q_size)
4640e4b17023SJohn Marino 	for (i = 0; i <= max_insn_queue_index; i++)
4641e4b17023SJohn Marino 	  {
4642e4b17023SJohn Marino 	    rtx link;
4643e4b17023SJohn Marino 	    for (link = insn_queue[i]; link; link = XEXP (link, 1))
4644e4b17023SJohn Marino 	      {
4645e4b17023SJohn Marino 		rtx x;
4646e4b17023SJohn Marino 
4647e4b17023SJohn Marino 		x = XEXP (link, 0);
4648e4b17023SJohn Marino 		QUEUE_INDEX (x) = QUEUE_NOWHERE;
4649e4b17023SJohn Marino 		TODO_SPEC (x) = HARD_DEP;
4650e4b17023SJohn Marino 	      }
4651e4b17023SJohn Marino 	    free_INSN_LIST_list (&insn_queue[i]);
4652e4b17023SJohn Marino 	  }
4653e4b17023SJohn Marino     }
4654e4b17023SJohn Marino 
4655e4b17023SJohn Marino   if (success)
4656e4b17023SJohn Marino     {
4657e4b17023SJohn Marino       commit_schedule (prev_head, tail, target_bb);
4658e4b17023SJohn Marino       if (sched_verbose)
4659e4b17023SJohn Marino 	fprintf (sched_dump, ";;   total time = %d\n", clock_var);
4660e4b17023SJohn Marino     }
4661e4b17023SJohn Marino   else
4662e4b17023SJohn Marino     last_scheduled_insn = tail;
4663e4b17023SJohn Marino 
4664e4b17023SJohn Marino   VEC_truncate (rtx, scheduled_insns, 0);
4665e4b17023SJohn Marino 
4666e4b17023SJohn Marino   if (!current_sched_info->queue_must_finish_empty
4667e4b17023SJohn Marino       || haifa_recovery_bb_recently_added_p)
4668e4b17023SJohn Marino     {
4669e4b17023SJohn Marino       /* INSN_TICK (minimum clock tick at which the insn becomes
4670e4b17023SJohn Marino          ready) may be not correct for the insn in the subsequent
4671e4b17023SJohn Marino          blocks of the region.  We should use a correct value of
4672e4b17023SJohn Marino          `clock_var' or modify INSN_TICK.  It is better to keep
4673e4b17023SJohn Marino          clock_var value equal to 0 at the start of a basic block.
4674e4b17023SJohn Marino          Therefore we modify INSN_TICK here.  */
4675e4b17023SJohn Marino       fix_inter_tick (NEXT_INSN (prev_head), last_scheduled_insn);
4676e4b17023SJohn Marino     }
4677e4b17023SJohn Marino 
4678e4b17023SJohn Marino   if (targetm.sched.finish)
4679e4b17023SJohn Marino     {
4680e4b17023SJohn Marino       targetm.sched.finish (sched_dump, sched_verbose);
4681e4b17023SJohn Marino       /* Target might have added some instructions to the scheduled block
4682e4b17023SJohn Marino 	 in its md_finish () hook.  These new insns don't have any data
4683e4b17023SJohn Marino 	 initialized and to identify them we extend h_i_d so that they'll
4684e4b17023SJohn Marino 	 get zero luids.  */
4685e4b17023SJohn Marino       sched_extend_luids ();
4686e4b17023SJohn Marino     }
4687e4b17023SJohn Marino 
4688e4b17023SJohn Marino   if (sched_verbose)
4689e4b17023SJohn Marino     fprintf (sched_dump, ";;   new head = %d\n;;   new tail = %d\n\n",
4690e4b17023SJohn Marino 	     INSN_UID (head), INSN_UID (tail));
4691e4b17023SJohn Marino 
4692e4b17023SJohn Marino   /* Update head/tail boundaries.  */
4693e4b17023SJohn Marino   head = NEXT_INSN (prev_head);
4694e4b17023SJohn Marino   tail = last_scheduled_insn;
4695e4b17023SJohn Marino 
4696e4b17023SJohn Marino   head = restore_other_notes (head, NULL);
4697e4b17023SJohn Marino 
4698e4b17023SJohn Marino   current_sched_info->head = head;
4699e4b17023SJohn Marino   current_sched_info->tail = tail;
4700e4b17023SJohn Marino 
4701e4b17023SJohn Marino   free_backtrack_queue ();
4702e4b17023SJohn Marino 
4703e4b17023SJohn Marino   return success;
4704e4b17023SJohn Marino }
4705e4b17023SJohn Marino 
4706e4b17023SJohn Marino /* Set_priorities: compute priority of each insn in the block.  */
4707e4b17023SJohn Marino 
4708e4b17023SJohn Marino int
set_priorities(rtx head,rtx tail)4709e4b17023SJohn Marino set_priorities (rtx head, rtx tail)
4710e4b17023SJohn Marino {
4711e4b17023SJohn Marino   rtx insn;
4712e4b17023SJohn Marino   int n_insn;
4713e4b17023SJohn Marino   int sched_max_insns_priority =
4714e4b17023SJohn Marino 	current_sched_info->sched_max_insns_priority;
4715e4b17023SJohn Marino   rtx prev_head;
4716e4b17023SJohn Marino 
4717e4b17023SJohn Marino   if (head == tail && ! INSN_P (head))
4718e4b17023SJohn Marino     gcc_unreachable ();
4719e4b17023SJohn Marino 
4720e4b17023SJohn Marino   n_insn = 0;
4721e4b17023SJohn Marino 
4722e4b17023SJohn Marino   prev_head = PREV_INSN (head);
4723e4b17023SJohn Marino   for (insn = tail; insn != prev_head; insn = PREV_INSN (insn))
4724e4b17023SJohn Marino     {
4725e4b17023SJohn Marino       if (!INSN_P (insn))
4726e4b17023SJohn Marino 	continue;
4727e4b17023SJohn Marino 
4728e4b17023SJohn Marino       n_insn++;
4729e4b17023SJohn Marino       (void) priority (insn);
4730e4b17023SJohn Marino 
4731e4b17023SJohn Marino       gcc_assert (INSN_PRIORITY_KNOWN (insn));
4732e4b17023SJohn Marino 
4733e4b17023SJohn Marino       sched_max_insns_priority = MAX (sched_max_insns_priority,
4734e4b17023SJohn Marino 				      INSN_PRIORITY (insn));
4735e4b17023SJohn Marino     }
4736e4b17023SJohn Marino 
4737e4b17023SJohn Marino   current_sched_info->sched_max_insns_priority = sched_max_insns_priority;
4738e4b17023SJohn Marino 
4739e4b17023SJohn Marino   return n_insn;
4740e4b17023SJohn Marino }
4741e4b17023SJohn Marino 
4742e4b17023SJohn Marino /* Set dump and sched_verbose for the desired debugging output.  If no
4743e4b17023SJohn Marino    dump-file was specified, but -fsched-verbose=N (any N), print to stderr.
4744e4b17023SJohn Marino    For -fsched-verbose=N, N>=10, print everything to stderr.  */
4745e4b17023SJohn Marino void
setup_sched_dump(void)4746e4b17023SJohn Marino setup_sched_dump (void)
4747e4b17023SJohn Marino {
4748e4b17023SJohn Marino   sched_verbose = sched_verbose_param;
4749e4b17023SJohn Marino   if (sched_verbose_param == 0 && dump_file)
4750e4b17023SJohn Marino     sched_verbose = 1;
4751e4b17023SJohn Marino   sched_dump = ((sched_verbose_param >= 10 || !dump_file)
4752e4b17023SJohn Marino 		? stderr : dump_file);
4753e4b17023SJohn Marino }
4754e4b17023SJohn Marino 
4755e4b17023SJohn Marino /* Initialize some global state for the scheduler.  This function works
4756e4b17023SJohn Marino    with the common data shared between all the schedulers.  It is called
4757e4b17023SJohn Marino    from the scheduler specific initialization routine.  */
4758e4b17023SJohn Marino 
4759e4b17023SJohn Marino void
sched_init(void)4760e4b17023SJohn Marino sched_init (void)
4761e4b17023SJohn Marino {
4762e4b17023SJohn Marino   /* Disable speculative loads in their presence if cc0 defined.  */
4763e4b17023SJohn Marino #ifdef HAVE_cc0
4764e4b17023SJohn Marino   flag_schedule_speculative_load = 0;
4765e4b17023SJohn Marino #endif
4766e4b17023SJohn Marino 
4767e4b17023SJohn Marino   if (targetm.sched.dispatch (NULL_RTX, IS_DISPATCH_ON))
4768e4b17023SJohn Marino     targetm.sched.dispatch_do (NULL_RTX, DISPATCH_INIT);
4769e4b17023SJohn Marino 
4770e4b17023SJohn Marino   sched_pressure_p = (flag_sched_pressure && ! reload_completed
4771e4b17023SJohn Marino 		      && common_sched_info->sched_pass_id == SCHED_RGN_PASS);
4772e4b17023SJohn Marino 
4773e4b17023SJohn Marino   if (sched_pressure_p)
4774e4b17023SJohn Marino     ira_setup_eliminable_regset ();
4775e4b17023SJohn Marino 
4776e4b17023SJohn Marino   /* Initialize SPEC_INFO.  */
4777e4b17023SJohn Marino   if (targetm.sched.set_sched_flags)
4778e4b17023SJohn Marino     {
4779e4b17023SJohn Marino       spec_info = &spec_info_var;
4780e4b17023SJohn Marino       targetm.sched.set_sched_flags (spec_info);
4781e4b17023SJohn Marino 
4782e4b17023SJohn Marino       if (spec_info->mask != 0)
4783e4b17023SJohn Marino         {
4784e4b17023SJohn Marino           spec_info->data_weakness_cutoff =
4785e4b17023SJohn Marino             (PARAM_VALUE (PARAM_SCHED_SPEC_PROB_CUTOFF) * MAX_DEP_WEAK) / 100;
4786e4b17023SJohn Marino           spec_info->control_weakness_cutoff =
4787e4b17023SJohn Marino             (PARAM_VALUE (PARAM_SCHED_SPEC_PROB_CUTOFF)
4788e4b17023SJohn Marino              * REG_BR_PROB_BASE) / 100;
4789e4b17023SJohn Marino         }
4790e4b17023SJohn Marino       else
4791e4b17023SJohn Marino 	/* So we won't read anything accidentally.  */
4792e4b17023SJohn Marino 	spec_info = NULL;
4793e4b17023SJohn Marino 
4794e4b17023SJohn Marino     }
4795e4b17023SJohn Marino   else
4796e4b17023SJohn Marino     /* So we won't read anything accidentally.  */
4797e4b17023SJohn Marino     spec_info = 0;
4798e4b17023SJohn Marino 
4799e4b17023SJohn Marino   /* Initialize issue_rate.  */
4800e4b17023SJohn Marino   if (targetm.sched.issue_rate)
4801e4b17023SJohn Marino     issue_rate = targetm.sched.issue_rate ();
4802e4b17023SJohn Marino   else
4803e4b17023SJohn Marino     issue_rate = 1;
4804e4b17023SJohn Marino 
4805e4b17023SJohn Marino   if (cached_issue_rate != issue_rate)
4806e4b17023SJohn Marino     {
4807e4b17023SJohn Marino       cached_issue_rate = issue_rate;
4808e4b17023SJohn Marino       /* To invalidate max_lookahead_tries:  */
4809e4b17023SJohn Marino       cached_first_cycle_multipass_dfa_lookahead = 0;
4810e4b17023SJohn Marino     }
4811e4b17023SJohn Marino 
4812e4b17023SJohn Marino   if (targetm.sched.first_cycle_multipass_dfa_lookahead)
4813e4b17023SJohn Marino     dfa_lookahead = targetm.sched.first_cycle_multipass_dfa_lookahead ();
4814e4b17023SJohn Marino   else
4815e4b17023SJohn Marino     dfa_lookahead = 0;
4816e4b17023SJohn Marino 
4817e4b17023SJohn Marino   if (targetm.sched.init_dfa_pre_cycle_insn)
4818e4b17023SJohn Marino     targetm.sched.init_dfa_pre_cycle_insn ();
4819e4b17023SJohn Marino 
4820e4b17023SJohn Marino   if (targetm.sched.init_dfa_post_cycle_insn)
4821e4b17023SJohn Marino     targetm.sched.init_dfa_post_cycle_insn ();
4822e4b17023SJohn Marino 
4823e4b17023SJohn Marino   dfa_start ();
4824e4b17023SJohn Marino   dfa_state_size = state_size ();
4825e4b17023SJohn Marino 
4826e4b17023SJohn Marino   init_alias_analysis ();
4827e4b17023SJohn Marino 
4828e4b17023SJohn Marino   if (!sched_no_dce)
4829e4b17023SJohn Marino     df_set_flags (DF_LR_RUN_DCE);
4830e4b17023SJohn Marino   df_note_add_problem ();
4831e4b17023SJohn Marino 
4832e4b17023SJohn Marino   /* More problems needed for interloop dep calculation in SMS.  */
4833e4b17023SJohn Marino   if (common_sched_info->sched_pass_id == SCHED_SMS_PASS)
4834e4b17023SJohn Marino     {
4835e4b17023SJohn Marino       df_rd_add_problem ();
4836e4b17023SJohn Marino       df_chain_add_problem (DF_DU_CHAIN + DF_UD_CHAIN);
4837e4b17023SJohn Marino     }
4838e4b17023SJohn Marino 
4839e4b17023SJohn Marino   df_analyze ();
4840e4b17023SJohn Marino 
4841e4b17023SJohn Marino   /* Do not run DCE after reload, as this can kill nops inserted
4842e4b17023SJohn Marino      by bundling.  */
4843e4b17023SJohn Marino   if (reload_completed)
4844e4b17023SJohn Marino     df_clear_flags (DF_LR_RUN_DCE);
4845e4b17023SJohn Marino 
4846e4b17023SJohn Marino   regstat_compute_calls_crossed ();
4847e4b17023SJohn Marino 
4848e4b17023SJohn Marino   if (targetm.sched.init_global)
4849e4b17023SJohn Marino     targetm.sched.init_global (sched_dump, sched_verbose, get_max_uid () + 1);
4850e4b17023SJohn Marino 
4851e4b17023SJohn Marino   if (sched_pressure_p)
4852e4b17023SJohn Marino     {
4853e4b17023SJohn Marino       int i, max_regno = max_reg_num ();
4854e4b17023SJohn Marino 
4855e4b17023SJohn Marino       if (sched_dump != NULL)
4856e4b17023SJohn Marino 	/* We need info about pseudos for rtl dumps about pseudo
4857e4b17023SJohn Marino 	   classes and costs.  */
4858e4b17023SJohn Marino 	regstat_init_n_sets_and_refs ();
4859e4b17023SJohn Marino       ira_set_pseudo_classes (sched_verbose ? sched_dump : NULL);
4860e4b17023SJohn Marino       sched_regno_pressure_class
4861e4b17023SJohn Marino 	= (enum reg_class *) xmalloc (max_regno * sizeof (enum reg_class));
4862e4b17023SJohn Marino       for (i = 0; i < max_regno; i++)
4863e4b17023SJohn Marino 	sched_regno_pressure_class[i]
4864e4b17023SJohn Marino 	  = (i < FIRST_PSEUDO_REGISTER
4865e4b17023SJohn Marino 	     ? ira_pressure_class_translate[REGNO_REG_CLASS (i)]
4866e4b17023SJohn Marino 	     : ira_pressure_class_translate[reg_allocno_class (i)]);
4867e4b17023SJohn Marino       curr_reg_live = BITMAP_ALLOC (NULL);
4868e4b17023SJohn Marino       saved_reg_live = BITMAP_ALLOC (NULL);
4869e4b17023SJohn Marino       region_ref_regs = BITMAP_ALLOC (NULL);
4870e4b17023SJohn Marino     }
4871e4b17023SJohn Marino 
4872e4b17023SJohn Marino   curr_state = xmalloc (dfa_state_size);
4873e4b17023SJohn Marino }
4874e4b17023SJohn Marino 
4875e4b17023SJohn Marino static void haifa_init_only_bb (basic_block, basic_block);
4876e4b17023SJohn Marino 
4877e4b17023SJohn Marino /* Initialize data structures specific to the Haifa scheduler.  */
4878e4b17023SJohn Marino void
haifa_sched_init(void)4879e4b17023SJohn Marino haifa_sched_init (void)
4880e4b17023SJohn Marino {
4881e4b17023SJohn Marino   setup_sched_dump ();
4882e4b17023SJohn Marino   sched_init ();
4883e4b17023SJohn Marino 
4884e4b17023SJohn Marino   scheduled_insns = VEC_alloc (rtx, heap, 0);
4885e4b17023SJohn Marino 
4886e4b17023SJohn Marino   if (spec_info != NULL)
4887e4b17023SJohn Marino     {
4888e4b17023SJohn Marino       sched_deps_info->use_deps_list = 1;
4889e4b17023SJohn Marino       sched_deps_info->generate_spec_deps = 1;
4890e4b17023SJohn Marino     }
4891e4b17023SJohn Marino 
4892e4b17023SJohn Marino   /* Initialize luids, dependency caches, target and h_i_d for the
4893e4b17023SJohn Marino      whole function.  */
4894e4b17023SJohn Marino   {
4895e4b17023SJohn Marino     bb_vec_t bbs = VEC_alloc (basic_block, heap, n_basic_blocks);
4896e4b17023SJohn Marino     basic_block bb;
4897e4b17023SJohn Marino 
4898e4b17023SJohn Marino     sched_init_bbs ();
4899e4b17023SJohn Marino 
4900e4b17023SJohn Marino     FOR_EACH_BB (bb)
4901e4b17023SJohn Marino       VEC_quick_push (basic_block, bbs, bb);
4902e4b17023SJohn Marino     sched_init_luids (bbs);
4903e4b17023SJohn Marino     sched_deps_init (true);
4904e4b17023SJohn Marino     sched_extend_target ();
4905e4b17023SJohn Marino     haifa_init_h_i_d (bbs);
4906e4b17023SJohn Marino 
4907e4b17023SJohn Marino     VEC_free (basic_block, heap, bbs);
4908e4b17023SJohn Marino   }
4909e4b17023SJohn Marino 
4910e4b17023SJohn Marino   sched_init_only_bb = haifa_init_only_bb;
4911e4b17023SJohn Marino   sched_split_block = sched_split_block_1;
4912e4b17023SJohn Marino   sched_create_empty_bb = sched_create_empty_bb_1;
4913e4b17023SJohn Marino   haifa_recovery_bb_ever_added_p = false;
4914e4b17023SJohn Marino 
4915e4b17023SJohn Marino   nr_begin_data = nr_begin_control = nr_be_in_data = nr_be_in_control = 0;
4916e4b17023SJohn Marino   before_recovery = 0;
4917e4b17023SJohn Marino   after_recovery = 0;
4918e4b17023SJohn Marino 
4919e4b17023SJohn Marino   modulo_ii = 0;
4920e4b17023SJohn Marino }
4921e4b17023SJohn Marino 
4922e4b17023SJohn Marino /* Finish work with the data specific to the Haifa scheduler.  */
4923e4b17023SJohn Marino void
haifa_sched_finish(void)4924e4b17023SJohn Marino haifa_sched_finish (void)
4925e4b17023SJohn Marino {
4926e4b17023SJohn Marino   sched_create_empty_bb = NULL;
4927e4b17023SJohn Marino   sched_split_block = NULL;
4928e4b17023SJohn Marino   sched_init_only_bb = NULL;
4929e4b17023SJohn Marino 
4930e4b17023SJohn Marino   if (spec_info && spec_info->dump)
4931e4b17023SJohn Marino     {
4932e4b17023SJohn Marino       char c = reload_completed ? 'a' : 'b';
4933e4b17023SJohn Marino 
4934e4b17023SJohn Marino       fprintf (spec_info->dump,
4935e4b17023SJohn Marino 	       ";; %s:\n", current_function_name ());
4936e4b17023SJohn Marino 
4937e4b17023SJohn Marino       fprintf (spec_info->dump,
4938e4b17023SJohn Marino                ";; Procedure %cr-begin-data-spec motions == %d\n",
4939e4b17023SJohn Marino                c, nr_begin_data);
4940e4b17023SJohn Marino       fprintf (spec_info->dump,
4941e4b17023SJohn Marino                ";; Procedure %cr-be-in-data-spec motions == %d\n",
4942e4b17023SJohn Marino                c, nr_be_in_data);
4943e4b17023SJohn Marino       fprintf (spec_info->dump,
4944e4b17023SJohn Marino                ";; Procedure %cr-begin-control-spec motions == %d\n",
4945e4b17023SJohn Marino                c, nr_begin_control);
4946e4b17023SJohn Marino       fprintf (spec_info->dump,
4947e4b17023SJohn Marino                ";; Procedure %cr-be-in-control-spec motions == %d\n",
4948e4b17023SJohn Marino                c, nr_be_in_control);
4949e4b17023SJohn Marino     }
4950e4b17023SJohn Marino 
4951e4b17023SJohn Marino   VEC_free (rtx, heap, scheduled_insns);
4952e4b17023SJohn Marino 
4953e4b17023SJohn Marino   /* Finalize h_i_d, dependency caches, and luids for the whole
4954e4b17023SJohn Marino      function.  Target will be finalized in md_global_finish ().  */
4955e4b17023SJohn Marino   sched_deps_finish ();
4956e4b17023SJohn Marino   sched_finish_luids ();
4957e4b17023SJohn Marino   current_sched_info = NULL;
4958e4b17023SJohn Marino   sched_finish ();
4959e4b17023SJohn Marino }
4960e4b17023SJohn Marino 
4961e4b17023SJohn Marino /* Free global data used during insn scheduling.  This function works with
4962e4b17023SJohn Marino    the common data shared between the schedulers.  */
4963e4b17023SJohn Marino 
4964e4b17023SJohn Marino void
sched_finish(void)4965e4b17023SJohn Marino sched_finish (void)
4966e4b17023SJohn Marino {
4967e4b17023SJohn Marino   haifa_finish_h_i_d ();
4968e4b17023SJohn Marino   if (sched_pressure_p)
4969e4b17023SJohn Marino     {
4970e4b17023SJohn Marino       if (regstat_n_sets_and_refs != NULL)
4971e4b17023SJohn Marino 	regstat_free_n_sets_and_refs ();
4972e4b17023SJohn Marino       free (sched_regno_pressure_class);
4973e4b17023SJohn Marino       BITMAP_FREE (region_ref_regs);
4974e4b17023SJohn Marino       BITMAP_FREE (saved_reg_live);
4975e4b17023SJohn Marino       BITMAP_FREE (curr_reg_live);
4976e4b17023SJohn Marino     }
4977e4b17023SJohn Marino   free (curr_state);
4978e4b17023SJohn Marino 
4979e4b17023SJohn Marino   if (targetm.sched.finish_global)
4980e4b17023SJohn Marino     targetm.sched.finish_global (sched_dump, sched_verbose);
4981e4b17023SJohn Marino 
4982e4b17023SJohn Marino   end_alias_analysis ();
4983e4b17023SJohn Marino 
4984e4b17023SJohn Marino   regstat_free_calls_crossed ();
4985e4b17023SJohn Marino 
4986e4b17023SJohn Marino   dfa_finish ();
4987e4b17023SJohn Marino }
4988e4b17023SJohn Marino 
4989e4b17023SJohn Marino /* Free all delay_pair structures that were recorded.  */
4990e4b17023SJohn Marino void
free_delay_pairs(void)4991e4b17023SJohn Marino free_delay_pairs (void)
4992e4b17023SJohn Marino {
4993e4b17023SJohn Marino   if (delay_htab)
4994e4b17023SJohn Marino     {
4995e4b17023SJohn Marino       htab_empty (delay_htab);
4996e4b17023SJohn Marino       htab_empty (delay_htab_i2);
4997e4b17023SJohn Marino     }
4998e4b17023SJohn Marino }
4999e4b17023SJohn Marino 
5000e4b17023SJohn Marino /* Fix INSN_TICKs of the instructions in the current block as well as
5001e4b17023SJohn Marino    INSN_TICKs of their dependents.
5002e4b17023SJohn Marino    HEAD and TAIL are the begin and the end of the current scheduled block.  */
5003e4b17023SJohn Marino static void
fix_inter_tick(rtx head,rtx tail)5004e4b17023SJohn Marino fix_inter_tick (rtx head, rtx tail)
5005e4b17023SJohn Marino {
5006e4b17023SJohn Marino   /* Set of instructions with corrected INSN_TICK.  */
5007e4b17023SJohn Marino   bitmap_head processed;
5008e4b17023SJohn Marino   /* ??? It is doubtful if we should assume that cycle advance happens on
5009e4b17023SJohn Marino      basic block boundaries.  Basically insns that are unconditionally ready
5010e4b17023SJohn Marino      on the start of the block are more preferable then those which have
5011e4b17023SJohn Marino      a one cycle dependency over insn from the previous block.  */
5012e4b17023SJohn Marino   int next_clock = clock_var + 1;
5013e4b17023SJohn Marino 
5014e4b17023SJohn Marino   bitmap_initialize (&processed, 0);
5015e4b17023SJohn Marino 
5016e4b17023SJohn Marino   /* Iterates over scheduled instructions and fix their INSN_TICKs and
5017e4b17023SJohn Marino      INSN_TICKs of dependent instructions, so that INSN_TICKs are consistent
5018e4b17023SJohn Marino      across different blocks.  */
5019e4b17023SJohn Marino   for (tail = NEXT_INSN (tail); head != tail; head = NEXT_INSN (head))
5020e4b17023SJohn Marino     {
5021e4b17023SJohn Marino       if (INSN_P (head))
5022e4b17023SJohn Marino 	{
5023e4b17023SJohn Marino 	  int tick;
5024e4b17023SJohn Marino 	  sd_iterator_def sd_it;
5025e4b17023SJohn Marino 	  dep_t dep;
5026e4b17023SJohn Marino 
5027e4b17023SJohn Marino 	  tick = INSN_TICK (head);
5028e4b17023SJohn Marino 	  gcc_assert (tick >= MIN_TICK);
5029e4b17023SJohn Marino 
5030e4b17023SJohn Marino 	  /* Fix INSN_TICK of instruction from just scheduled block.  */
5031e4b17023SJohn Marino 	  if (bitmap_set_bit (&processed, INSN_LUID (head)))
5032e4b17023SJohn Marino 	    {
5033e4b17023SJohn Marino 	      tick -= next_clock;
5034e4b17023SJohn Marino 
5035e4b17023SJohn Marino 	      if (tick < MIN_TICK)
5036e4b17023SJohn Marino 		tick = MIN_TICK;
5037e4b17023SJohn Marino 
5038e4b17023SJohn Marino 	      INSN_TICK (head) = tick;
5039e4b17023SJohn Marino 	    }
5040e4b17023SJohn Marino 
5041*5ce9237cSJohn Marino 	  if (DEBUG_INSN_P (head))
5042*5ce9237cSJohn Marino 	    continue;
5043*5ce9237cSJohn Marino 
5044e4b17023SJohn Marino 	  FOR_EACH_DEP (head, SD_LIST_RES_FORW, sd_it, dep)
5045e4b17023SJohn Marino 	    {
5046e4b17023SJohn Marino 	      rtx next;
5047e4b17023SJohn Marino 
5048e4b17023SJohn Marino 	      next = DEP_CON (dep);
5049e4b17023SJohn Marino 	      tick = INSN_TICK (next);
5050e4b17023SJohn Marino 
5051e4b17023SJohn Marino 	      if (tick != INVALID_TICK
5052e4b17023SJohn Marino 		  /* If NEXT has its INSN_TICK calculated, fix it.
5053e4b17023SJohn Marino 		     If not - it will be properly calculated from
5054e4b17023SJohn Marino 		     scratch later in fix_tick_ready.  */
5055e4b17023SJohn Marino 		  && bitmap_set_bit (&processed, INSN_LUID (next)))
5056e4b17023SJohn Marino 		{
5057e4b17023SJohn Marino 		  tick -= next_clock;
5058e4b17023SJohn Marino 
5059e4b17023SJohn Marino 		  if (tick < MIN_TICK)
5060e4b17023SJohn Marino 		    tick = MIN_TICK;
5061e4b17023SJohn Marino 
5062e4b17023SJohn Marino 		  if (tick > INTER_TICK (next))
5063e4b17023SJohn Marino 		    INTER_TICK (next) = tick;
5064e4b17023SJohn Marino 		  else
5065e4b17023SJohn Marino 		    tick = INTER_TICK (next);
5066e4b17023SJohn Marino 
5067e4b17023SJohn Marino 		  INSN_TICK (next) = tick;
5068e4b17023SJohn Marino 		}
5069e4b17023SJohn Marino 	    }
5070e4b17023SJohn Marino 	}
5071e4b17023SJohn Marino     }
5072e4b17023SJohn Marino   bitmap_clear (&processed);
5073e4b17023SJohn Marino }
5074e4b17023SJohn Marino 
5075e4b17023SJohn Marino /* Check if NEXT is ready to be added to the ready or queue list.
5076e4b17023SJohn Marino    If "yes", add it to the proper list.
5077e4b17023SJohn Marino    Returns:
5078e4b17023SJohn Marino       -1 - is not ready yet,
5079e4b17023SJohn Marino        0 - added to the ready list,
5080e4b17023SJohn Marino    0 < N - queued for N cycles.  */
5081e4b17023SJohn Marino int
try_ready(rtx next)5082e4b17023SJohn Marino try_ready (rtx next)
5083e4b17023SJohn Marino {
5084e4b17023SJohn Marino   ds_t old_ts, new_ts;
5085e4b17023SJohn Marino 
5086e4b17023SJohn Marino   old_ts = TODO_SPEC (next);
5087e4b17023SJohn Marino 
5088e4b17023SJohn Marino   gcc_assert (!(old_ts & ~(SPECULATIVE | HARD_DEP | DEP_CONTROL))
5089e4b17023SJohn Marino 	      && ((old_ts & HARD_DEP)
5090e4b17023SJohn Marino 		  || (old_ts & SPECULATIVE)
5091e4b17023SJohn Marino 		  || (old_ts & DEP_CONTROL)));
5092e4b17023SJohn Marino 
5093e4b17023SJohn Marino   new_ts = recompute_todo_spec (next);
5094e4b17023SJohn Marino 
5095e4b17023SJohn Marino   if (new_ts & HARD_DEP)
5096e4b17023SJohn Marino     gcc_assert (new_ts == old_ts
5097e4b17023SJohn Marino 		&& QUEUE_INDEX (next) == QUEUE_NOWHERE);
5098e4b17023SJohn Marino   else if (current_sched_info->new_ready)
5099e4b17023SJohn Marino     new_ts = current_sched_info->new_ready (next, new_ts);
5100e4b17023SJohn Marino 
5101e4b17023SJohn Marino   /* * if !(old_ts & SPECULATIVE) (e.g. HARD_DEP or 0), then insn might
5102e4b17023SJohn Marino      have its original pattern or changed (speculative) one.  This is due
5103e4b17023SJohn Marino      to changing ebb in region scheduling.
5104e4b17023SJohn Marino      * But if (old_ts & SPECULATIVE), then we are pretty sure that insn
5105e4b17023SJohn Marino      has speculative pattern.
5106e4b17023SJohn Marino 
5107e4b17023SJohn Marino      We can't assert (!(new_ts & HARD_DEP) || new_ts == old_ts) here because
5108e4b17023SJohn Marino      control-speculative NEXT could have been discarded by sched-rgn.c
5109e4b17023SJohn Marino      (the same case as when discarded by can_schedule_ready_p ()).  */
5110e4b17023SJohn Marino 
5111e4b17023SJohn Marino   if ((new_ts & SPECULATIVE)
5112e4b17023SJohn Marino       /* If (old_ts == new_ts), then (old_ts & SPECULATIVE) and we don't
5113e4b17023SJohn Marino 	 need to change anything.  */
5114e4b17023SJohn Marino       && new_ts != old_ts)
5115e4b17023SJohn Marino     {
5116e4b17023SJohn Marino       int res;
5117e4b17023SJohn Marino       rtx new_pat;
5118e4b17023SJohn Marino 
5119e4b17023SJohn Marino       gcc_assert ((new_ts & SPECULATIVE) && !(new_ts & ~SPECULATIVE));
5120e4b17023SJohn Marino 
5121e4b17023SJohn Marino       res = haifa_speculate_insn (next, new_ts, &new_pat);
5122e4b17023SJohn Marino 
5123e4b17023SJohn Marino       switch (res)
5124e4b17023SJohn Marino 	{
5125e4b17023SJohn Marino 	case -1:
5126e4b17023SJohn Marino 	  /* It would be nice to change DEP_STATUS of all dependences,
5127e4b17023SJohn Marino 	     which have ((DEP_STATUS & SPECULATIVE) == new_ts) to HARD_DEP,
5128e4b17023SJohn Marino 	     so we won't reanalyze anything.  */
5129e4b17023SJohn Marino 	  new_ts = HARD_DEP;
5130e4b17023SJohn Marino 	  break;
5131e4b17023SJohn Marino 
5132e4b17023SJohn Marino 	case 0:
5133e4b17023SJohn Marino 	  /* We follow the rule, that every speculative insn
5134e4b17023SJohn Marino 	     has non-null ORIG_PAT.  */
5135e4b17023SJohn Marino 	  if (!ORIG_PAT (next))
5136e4b17023SJohn Marino 	    ORIG_PAT (next) = PATTERN (next);
5137e4b17023SJohn Marino 	  break;
5138e4b17023SJohn Marino 
5139e4b17023SJohn Marino 	case 1:
5140e4b17023SJohn Marino 	  if (!ORIG_PAT (next))
5141e4b17023SJohn Marino 	    /* If we gonna to overwrite the original pattern of insn,
5142e4b17023SJohn Marino 	       save it.  */
5143e4b17023SJohn Marino 	    ORIG_PAT (next) = PATTERN (next);
5144e4b17023SJohn Marino 
5145e4b17023SJohn Marino 	  res = haifa_change_pattern (next, new_pat);
5146e4b17023SJohn Marino 	  gcc_assert (res);
5147e4b17023SJohn Marino 	  break;
5148e4b17023SJohn Marino 
5149e4b17023SJohn Marino 	default:
5150e4b17023SJohn Marino 	  gcc_unreachable ();
5151e4b17023SJohn Marino 	}
5152e4b17023SJohn Marino     }
5153e4b17023SJohn Marino 
5154e4b17023SJohn Marino   /* We need to restore pattern only if (new_ts == 0), because otherwise it is
5155e4b17023SJohn Marino      either correct (new_ts & SPECULATIVE),
5156e4b17023SJohn Marino      or we simply don't care (new_ts & HARD_DEP).  */
5157e4b17023SJohn Marino 
5158e4b17023SJohn Marino   gcc_assert (!ORIG_PAT (next)
5159e4b17023SJohn Marino 	      || !IS_SPECULATION_BRANCHY_CHECK_P (next));
5160e4b17023SJohn Marino 
5161e4b17023SJohn Marino   TODO_SPEC (next) = new_ts;
5162e4b17023SJohn Marino 
5163e4b17023SJohn Marino   if (new_ts & HARD_DEP)
5164e4b17023SJohn Marino     {
5165e4b17023SJohn Marino       /* We can't assert (QUEUE_INDEX (next) == QUEUE_NOWHERE) here because
5166e4b17023SJohn Marino 	 control-speculative NEXT could have been discarded by sched-rgn.c
5167e4b17023SJohn Marino 	 (the same case as when discarded by can_schedule_ready_p ()).  */
5168e4b17023SJohn Marino       /*gcc_assert (QUEUE_INDEX (next) == QUEUE_NOWHERE);*/
5169e4b17023SJohn Marino 
5170e4b17023SJohn Marino       change_queue_index (next, QUEUE_NOWHERE);
5171e4b17023SJohn Marino 
5172e4b17023SJohn Marino       return -1;
5173e4b17023SJohn Marino     }
5174e4b17023SJohn Marino   else if (!(new_ts & BEGIN_SPEC)
5175e4b17023SJohn Marino 	   && ORIG_PAT (next) && PREDICATED_PAT (next) == NULL_RTX
5176e4b17023SJohn Marino 	   && !IS_SPECULATION_CHECK_P (next))
5177e4b17023SJohn Marino     /* We should change pattern of every previously speculative
5178e4b17023SJohn Marino        instruction - and we determine if NEXT was speculative by using
5179e4b17023SJohn Marino        ORIG_PAT field.  Except one case - speculation checks have ORIG_PAT
5180e4b17023SJohn Marino        pat too, so skip them.  */
5181e4b17023SJohn Marino     {
5182e4b17023SJohn Marino       bool success = haifa_change_pattern (next, ORIG_PAT (next));
5183e4b17023SJohn Marino       gcc_assert (success);
5184e4b17023SJohn Marino       ORIG_PAT (next) = 0;
5185e4b17023SJohn Marino     }
5186e4b17023SJohn Marino 
5187e4b17023SJohn Marino   if (sched_verbose >= 2)
5188e4b17023SJohn Marino     {
5189e4b17023SJohn Marino       fprintf (sched_dump, ";;\t\tdependencies resolved: insn %s",
5190e4b17023SJohn Marino                (*current_sched_info->print_insn) (next, 0));
5191e4b17023SJohn Marino 
5192e4b17023SJohn Marino       if (spec_info && spec_info->dump)
5193e4b17023SJohn Marino         {
5194e4b17023SJohn Marino           if (new_ts & BEGIN_DATA)
5195e4b17023SJohn Marino             fprintf (spec_info->dump, "; data-spec;");
5196e4b17023SJohn Marino           if (new_ts & BEGIN_CONTROL)
5197e4b17023SJohn Marino             fprintf (spec_info->dump, "; control-spec;");
5198e4b17023SJohn Marino           if (new_ts & BE_IN_CONTROL)
5199e4b17023SJohn Marino             fprintf (spec_info->dump, "; in-control-spec;");
5200e4b17023SJohn Marino         }
5201e4b17023SJohn Marino       if (TODO_SPEC (next) & DEP_CONTROL)
5202e4b17023SJohn Marino 	fprintf (sched_dump, " predicated");
5203e4b17023SJohn Marino       fprintf (sched_dump, "\n");
5204e4b17023SJohn Marino     }
5205e4b17023SJohn Marino 
5206e4b17023SJohn Marino   adjust_priority (next);
5207e4b17023SJohn Marino 
5208e4b17023SJohn Marino   return fix_tick_ready (next);
5209e4b17023SJohn Marino }
5210e4b17023SJohn Marino 
5211e4b17023SJohn Marino /* Calculate INSN_TICK of NEXT and add it to either ready or queue list.  */
5212e4b17023SJohn Marino static int
fix_tick_ready(rtx next)5213e4b17023SJohn Marino fix_tick_ready (rtx next)
5214e4b17023SJohn Marino {
5215e4b17023SJohn Marino   int tick, delay;
5216e4b17023SJohn Marino 
5217e4b17023SJohn Marino   if (!DEBUG_INSN_P (next) && !sd_lists_empty_p (next, SD_LIST_RES_BACK))
5218e4b17023SJohn Marino     {
5219e4b17023SJohn Marino       int full_p;
5220e4b17023SJohn Marino       sd_iterator_def sd_it;
5221e4b17023SJohn Marino       dep_t dep;
5222e4b17023SJohn Marino 
5223e4b17023SJohn Marino       tick = INSN_TICK (next);
5224e4b17023SJohn Marino       /* if tick is not equal to INVALID_TICK, then update
5225e4b17023SJohn Marino 	 INSN_TICK of NEXT with the most recent resolved dependence
5226e4b17023SJohn Marino 	 cost.  Otherwise, recalculate from scratch.  */
5227e4b17023SJohn Marino       full_p = (tick == INVALID_TICK);
5228e4b17023SJohn Marino 
5229e4b17023SJohn Marino       FOR_EACH_DEP (next, SD_LIST_RES_BACK, sd_it, dep)
5230e4b17023SJohn Marino         {
5231e4b17023SJohn Marino           rtx pro = DEP_PRO (dep);
5232e4b17023SJohn Marino           int tick1;
5233e4b17023SJohn Marino 
5234e4b17023SJohn Marino 	  gcc_assert (INSN_TICK (pro) >= MIN_TICK);
5235e4b17023SJohn Marino 
5236e4b17023SJohn Marino           tick1 = INSN_TICK (pro) + dep_cost (dep);
5237e4b17023SJohn Marino           if (tick1 > tick)
5238e4b17023SJohn Marino             tick = tick1;
5239e4b17023SJohn Marino 
5240e4b17023SJohn Marino 	  if (!full_p)
5241e4b17023SJohn Marino 	    break;
5242e4b17023SJohn Marino         }
5243e4b17023SJohn Marino     }
5244e4b17023SJohn Marino   else
5245e4b17023SJohn Marino     tick = -1;
5246e4b17023SJohn Marino 
5247e4b17023SJohn Marino   INSN_TICK (next) = tick;
5248e4b17023SJohn Marino 
5249e4b17023SJohn Marino   delay = tick - clock_var;
5250e4b17023SJohn Marino   if (delay <= 0 || sched_pressure_p)
5251e4b17023SJohn Marino     delay = QUEUE_READY;
5252e4b17023SJohn Marino 
5253e4b17023SJohn Marino   change_queue_index (next, delay);
5254e4b17023SJohn Marino 
5255e4b17023SJohn Marino   return delay;
5256e4b17023SJohn Marino }
5257e4b17023SJohn Marino 
5258e4b17023SJohn Marino /* Move NEXT to the proper queue list with (DELAY >= 1),
5259e4b17023SJohn Marino    or add it to the ready list (DELAY == QUEUE_READY),
5260e4b17023SJohn Marino    or remove it from ready and queue lists at all (DELAY == QUEUE_NOWHERE).  */
5261e4b17023SJohn Marino static void
change_queue_index(rtx next,int delay)5262e4b17023SJohn Marino change_queue_index (rtx next, int delay)
5263e4b17023SJohn Marino {
5264e4b17023SJohn Marino   int i = QUEUE_INDEX (next);
5265e4b17023SJohn Marino 
5266e4b17023SJohn Marino   gcc_assert (QUEUE_NOWHERE <= delay && delay <= max_insn_queue_index
5267e4b17023SJohn Marino 	      && delay != 0);
5268e4b17023SJohn Marino   gcc_assert (i != QUEUE_SCHEDULED);
5269e4b17023SJohn Marino 
5270e4b17023SJohn Marino   if ((delay > 0 && NEXT_Q_AFTER (q_ptr, delay) == i)
5271e4b17023SJohn Marino       || (delay < 0 && delay == i))
5272e4b17023SJohn Marino     /* We have nothing to do.  */
5273e4b17023SJohn Marino     return;
5274e4b17023SJohn Marino 
5275e4b17023SJohn Marino   /* Remove NEXT from wherever it is now.  */
5276e4b17023SJohn Marino   if (i == QUEUE_READY)
5277e4b17023SJohn Marino     ready_remove_insn (next);
5278e4b17023SJohn Marino   else if (i >= 0)
5279e4b17023SJohn Marino     queue_remove (next);
5280e4b17023SJohn Marino 
5281e4b17023SJohn Marino   /* Add it to the proper place.  */
5282e4b17023SJohn Marino   if (delay == QUEUE_READY)
5283e4b17023SJohn Marino     ready_add (readyp, next, false);
5284e4b17023SJohn Marino   else if (delay >= 1)
5285e4b17023SJohn Marino     queue_insn (next, delay, "change queue index");
5286e4b17023SJohn Marino 
5287e4b17023SJohn Marino   if (sched_verbose >= 2)
5288e4b17023SJohn Marino     {
5289e4b17023SJohn Marino       fprintf (sched_dump, ";;\t\ttick updated: insn %s",
5290e4b17023SJohn Marino 	       (*current_sched_info->print_insn) (next, 0));
5291e4b17023SJohn Marino 
5292e4b17023SJohn Marino       if (delay == QUEUE_READY)
5293e4b17023SJohn Marino 	fprintf (sched_dump, " into ready\n");
5294e4b17023SJohn Marino       else if (delay >= 1)
5295e4b17023SJohn Marino 	fprintf (sched_dump, " into queue with cost=%d\n", delay);
5296e4b17023SJohn Marino       else
5297e4b17023SJohn Marino 	fprintf (sched_dump, " removed from ready or queue lists\n");
5298e4b17023SJohn Marino     }
5299e4b17023SJohn Marino }
5300e4b17023SJohn Marino 
5301e4b17023SJohn Marino static int sched_ready_n_insns = -1;
5302e4b17023SJohn Marino 
5303e4b17023SJohn Marino /* Initialize per region data structures.  */
5304e4b17023SJohn Marino void
sched_extend_ready_list(int new_sched_ready_n_insns)5305e4b17023SJohn Marino sched_extend_ready_list (int new_sched_ready_n_insns)
5306e4b17023SJohn Marino {
5307e4b17023SJohn Marino   int i;
5308e4b17023SJohn Marino 
5309e4b17023SJohn Marino   if (sched_ready_n_insns == -1)
5310e4b17023SJohn Marino     /* At the first call we need to initialize one more choice_stack
5311e4b17023SJohn Marino        entry.  */
5312e4b17023SJohn Marino     {
5313e4b17023SJohn Marino       i = 0;
5314e4b17023SJohn Marino       sched_ready_n_insns = 0;
5315e4b17023SJohn Marino       VEC_reserve (rtx, heap, scheduled_insns, new_sched_ready_n_insns);
5316e4b17023SJohn Marino     }
5317e4b17023SJohn Marino   else
5318e4b17023SJohn Marino     i = sched_ready_n_insns + 1;
5319e4b17023SJohn Marino 
5320e4b17023SJohn Marino   ready.veclen = new_sched_ready_n_insns + issue_rate;
5321e4b17023SJohn Marino   ready.vec = XRESIZEVEC (rtx, ready.vec, ready.veclen);
5322e4b17023SJohn Marino 
5323e4b17023SJohn Marino   gcc_assert (new_sched_ready_n_insns >= sched_ready_n_insns);
5324e4b17023SJohn Marino 
5325e4b17023SJohn Marino   ready_try = (char *) xrecalloc (ready_try, new_sched_ready_n_insns,
5326e4b17023SJohn Marino                                   sched_ready_n_insns, sizeof (*ready_try));
5327e4b17023SJohn Marino 
5328e4b17023SJohn Marino   /* We allocate +1 element to save initial state in the choice_stack[0]
5329e4b17023SJohn Marino      entry.  */
5330e4b17023SJohn Marino   choice_stack = XRESIZEVEC (struct choice_entry, choice_stack,
5331e4b17023SJohn Marino 			     new_sched_ready_n_insns + 1);
5332e4b17023SJohn Marino 
5333e4b17023SJohn Marino   for (; i <= new_sched_ready_n_insns; i++)
5334e4b17023SJohn Marino     {
5335e4b17023SJohn Marino       choice_stack[i].state = xmalloc (dfa_state_size);
5336e4b17023SJohn Marino 
5337e4b17023SJohn Marino       if (targetm.sched.first_cycle_multipass_init)
5338e4b17023SJohn Marino 	targetm.sched.first_cycle_multipass_init (&(choice_stack[i]
5339e4b17023SJohn Marino 						    .target_data));
5340e4b17023SJohn Marino     }
5341e4b17023SJohn Marino 
5342e4b17023SJohn Marino   sched_ready_n_insns = new_sched_ready_n_insns;
5343e4b17023SJohn Marino }
5344e4b17023SJohn Marino 
5345e4b17023SJohn Marino /* Free per region data structures.  */
5346e4b17023SJohn Marino void
sched_finish_ready_list(void)5347e4b17023SJohn Marino sched_finish_ready_list (void)
5348e4b17023SJohn Marino {
5349e4b17023SJohn Marino   int i;
5350e4b17023SJohn Marino 
5351e4b17023SJohn Marino   free (ready.vec);
5352e4b17023SJohn Marino   ready.vec = NULL;
5353e4b17023SJohn Marino   ready.veclen = 0;
5354e4b17023SJohn Marino 
5355e4b17023SJohn Marino   free (ready_try);
5356e4b17023SJohn Marino   ready_try = NULL;
5357e4b17023SJohn Marino 
5358e4b17023SJohn Marino   for (i = 0; i <= sched_ready_n_insns; i++)
5359e4b17023SJohn Marino     {
5360e4b17023SJohn Marino       if (targetm.sched.first_cycle_multipass_fini)
5361e4b17023SJohn Marino 	targetm.sched.first_cycle_multipass_fini (&(choice_stack[i]
5362e4b17023SJohn Marino 						    .target_data));
5363e4b17023SJohn Marino 
5364e4b17023SJohn Marino       free (choice_stack [i].state);
5365e4b17023SJohn Marino     }
5366e4b17023SJohn Marino   free (choice_stack);
5367e4b17023SJohn Marino   choice_stack = NULL;
5368e4b17023SJohn Marino 
5369e4b17023SJohn Marino   sched_ready_n_insns = -1;
5370e4b17023SJohn Marino }
5371e4b17023SJohn Marino 
5372e4b17023SJohn Marino static int
haifa_luid_for_non_insn(rtx x)5373e4b17023SJohn Marino haifa_luid_for_non_insn (rtx x)
5374e4b17023SJohn Marino {
5375e4b17023SJohn Marino   gcc_assert (NOTE_P (x) || LABEL_P (x));
5376e4b17023SJohn Marino 
5377e4b17023SJohn Marino   return 0;
5378e4b17023SJohn Marino }
5379e4b17023SJohn Marino 
5380e4b17023SJohn Marino /* Generates recovery code for INSN.  */
5381e4b17023SJohn Marino static void
generate_recovery_code(rtx insn)5382e4b17023SJohn Marino generate_recovery_code (rtx insn)
5383e4b17023SJohn Marino {
5384e4b17023SJohn Marino   if (TODO_SPEC (insn) & BEGIN_SPEC)
5385e4b17023SJohn Marino     begin_speculative_block (insn);
5386e4b17023SJohn Marino 
5387e4b17023SJohn Marino   /* Here we have insn with no dependencies to
5388e4b17023SJohn Marino      instructions other then CHECK_SPEC ones.  */
5389e4b17023SJohn Marino 
5390e4b17023SJohn Marino   if (TODO_SPEC (insn) & BE_IN_SPEC)
5391e4b17023SJohn Marino     add_to_speculative_block (insn);
5392e4b17023SJohn Marino }
5393e4b17023SJohn Marino 
5394e4b17023SJohn Marino /* Helper function.
5395e4b17023SJohn Marino    Tries to add speculative dependencies of type FS between instructions
5396e4b17023SJohn Marino    in deps_list L and TWIN.  */
5397e4b17023SJohn Marino static void
process_insn_forw_deps_be_in_spec(rtx insn,rtx twin,ds_t fs)5398e4b17023SJohn Marino process_insn_forw_deps_be_in_spec (rtx insn, rtx twin, ds_t fs)
5399e4b17023SJohn Marino {
5400e4b17023SJohn Marino   sd_iterator_def sd_it;
5401e4b17023SJohn Marino   dep_t dep;
5402e4b17023SJohn Marino 
5403e4b17023SJohn Marino   FOR_EACH_DEP (insn, SD_LIST_FORW, sd_it, dep)
5404e4b17023SJohn Marino     {
5405e4b17023SJohn Marino       ds_t ds;
5406e4b17023SJohn Marino       rtx consumer;
5407e4b17023SJohn Marino 
5408e4b17023SJohn Marino       consumer = DEP_CON (dep);
5409e4b17023SJohn Marino 
5410e4b17023SJohn Marino       ds = DEP_STATUS (dep);
5411e4b17023SJohn Marino 
5412e4b17023SJohn Marino       if (/* If we want to create speculative dep.  */
5413e4b17023SJohn Marino 	  fs
5414e4b17023SJohn Marino 	  /* And we can do that because this is a true dep.  */
5415e4b17023SJohn Marino 	  && (ds & DEP_TYPES) == DEP_TRUE)
5416e4b17023SJohn Marino 	{
5417e4b17023SJohn Marino 	  gcc_assert (!(ds & BE_IN_SPEC));
5418e4b17023SJohn Marino 
5419e4b17023SJohn Marino 	  if (/* If this dep can be overcome with 'begin speculation'.  */
5420e4b17023SJohn Marino 	      ds & BEGIN_SPEC)
5421e4b17023SJohn Marino 	    /* Then we have a choice: keep the dep 'begin speculative'
5422e4b17023SJohn Marino 	       or transform it into 'be in speculative'.  */
5423e4b17023SJohn Marino 	    {
5424e4b17023SJohn Marino 	      if (/* In try_ready we assert that if insn once became ready
5425e4b17023SJohn Marino 		     it can be removed from the ready (or queue) list only
5426e4b17023SJohn Marino 		     due to backend decision.  Hence we can't let the
5427e4b17023SJohn Marino 		     probability of the speculative dep to decrease.  */
5428e4b17023SJohn Marino 		  ds_weak (ds) <= ds_weak (fs))
5429e4b17023SJohn Marino 		{
5430e4b17023SJohn Marino 		  ds_t new_ds;
5431e4b17023SJohn Marino 
5432e4b17023SJohn Marino 		  new_ds = (ds & ~BEGIN_SPEC) | fs;
5433e4b17023SJohn Marino 
5434e4b17023SJohn Marino 		  if (/* consumer can 'be in speculative'.  */
5435e4b17023SJohn Marino 		      sched_insn_is_legitimate_for_speculation_p (consumer,
5436e4b17023SJohn Marino 								  new_ds))
5437e4b17023SJohn Marino 		    /* Transform it to be in speculative.  */
5438e4b17023SJohn Marino 		    ds = new_ds;
5439e4b17023SJohn Marino 		}
5440e4b17023SJohn Marino 	    }
5441e4b17023SJohn Marino 	  else
5442e4b17023SJohn Marino 	    /* Mark the dep as 'be in speculative'.  */
5443e4b17023SJohn Marino 	    ds |= fs;
5444e4b17023SJohn Marino 	}
5445e4b17023SJohn Marino 
5446e4b17023SJohn Marino       {
5447e4b17023SJohn Marino 	dep_def _new_dep, *new_dep = &_new_dep;
5448e4b17023SJohn Marino 
5449e4b17023SJohn Marino 	init_dep_1 (new_dep, twin, consumer, DEP_TYPE (dep), ds);
5450e4b17023SJohn Marino 	sd_add_dep (new_dep, false);
5451e4b17023SJohn Marino       }
5452e4b17023SJohn Marino     }
5453e4b17023SJohn Marino }
5454e4b17023SJohn Marino 
5455e4b17023SJohn Marino /* Generates recovery code for BEGIN speculative INSN.  */
5456e4b17023SJohn Marino static void
begin_speculative_block(rtx insn)5457e4b17023SJohn Marino begin_speculative_block (rtx insn)
5458e4b17023SJohn Marino {
5459e4b17023SJohn Marino   if (TODO_SPEC (insn) & BEGIN_DATA)
5460e4b17023SJohn Marino     nr_begin_data++;
5461e4b17023SJohn Marino   if (TODO_SPEC (insn) & BEGIN_CONTROL)
5462e4b17023SJohn Marino     nr_begin_control++;
5463e4b17023SJohn Marino 
5464e4b17023SJohn Marino   create_check_block_twin (insn, false);
5465e4b17023SJohn Marino 
5466e4b17023SJohn Marino   TODO_SPEC (insn) &= ~BEGIN_SPEC;
5467e4b17023SJohn Marino }
5468e4b17023SJohn Marino 
5469e4b17023SJohn Marino static void haifa_init_insn (rtx);
5470e4b17023SJohn Marino 
5471e4b17023SJohn Marino /* Generates recovery code for BE_IN speculative INSN.  */
5472e4b17023SJohn Marino static void
add_to_speculative_block(rtx insn)5473e4b17023SJohn Marino add_to_speculative_block (rtx insn)
5474e4b17023SJohn Marino {
5475e4b17023SJohn Marino   ds_t ts;
5476e4b17023SJohn Marino   sd_iterator_def sd_it;
5477e4b17023SJohn Marino   dep_t dep;
5478e4b17023SJohn Marino   rtx twins = NULL;
5479e4b17023SJohn Marino   rtx_vec_t priorities_roots;
5480e4b17023SJohn Marino 
5481e4b17023SJohn Marino   ts = TODO_SPEC (insn);
5482e4b17023SJohn Marino   gcc_assert (!(ts & ~BE_IN_SPEC));
5483e4b17023SJohn Marino 
5484e4b17023SJohn Marino   if (ts & BE_IN_DATA)
5485e4b17023SJohn Marino     nr_be_in_data++;
5486e4b17023SJohn Marino   if (ts & BE_IN_CONTROL)
5487e4b17023SJohn Marino     nr_be_in_control++;
5488e4b17023SJohn Marino 
5489e4b17023SJohn Marino   TODO_SPEC (insn) &= ~BE_IN_SPEC;
5490e4b17023SJohn Marino   gcc_assert (!TODO_SPEC (insn));
5491e4b17023SJohn Marino 
5492e4b17023SJohn Marino   DONE_SPEC (insn) |= ts;
5493e4b17023SJohn Marino 
5494e4b17023SJohn Marino   /* First we convert all simple checks to branchy.  */
5495e4b17023SJohn Marino   for (sd_it = sd_iterator_start (insn, SD_LIST_SPEC_BACK);
5496e4b17023SJohn Marino        sd_iterator_cond (&sd_it, &dep);)
5497e4b17023SJohn Marino     {
5498e4b17023SJohn Marino       rtx check = DEP_PRO (dep);
5499e4b17023SJohn Marino 
5500e4b17023SJohn Marino       if (IS_SPECULATION_SIMPLE_CHECK_P (check))
5501e4b17023SJohn Marino 	{
5502e4b17023SJohn Marino 	  create_check_block_twin (check, true);
5503e4b17023SJohn Marino 
5504e4b17023SJohn Marino 	  /* Restart search.  */
5505e4b17023SJohn Marino 	  sd_it = sd_iterator_start (insn, SD_LIST_SPEC_BACK);
5506e4b17023SJohn Marino 	}
5507e4b17023SJohn Marino       else
5508e4b17023SJohn Marino 	/* Continue search.  */
5509e4b17023SJohn Marino 	sd_iterator_next (&sd_it);
5510e4b17023SJohn Marino     }
5511e4b17023SJohn Marino 
5512e4b17023SJohn Marino   priorities_roots = NULL;
5513e4b17023SJohn Marino   clear_priorities (insn, &priorities_roots);
5514e4b17023SJohn Marino 
5515e4b17023SJohn Marino   while (1)
5516e4b17023SJohn Marino     {
5517e4b17023SJohn Marino       rtx check, twin;
5518e4b17023SJohn Marino       basic_block rec;
5519e4b17023SJohn Marino 
5520e4b17023SJohn Marino       /* Get the first backward dependency of INSN.  */
5521e4b17023SJohn Marino       sd_it = sd_iterator_start (insn, SD_LIST_SPEC_BACK);
5522e4b17023SJohn Marino       if (!sd_iterator_cond (&sd_it, &dep))
5523e4b17023SJohn Marino 	/* INSN has no backward dependencies left.  */
5524e4b17023SJohn Marino 	break;
5525e4b17023SJohn Marino 
5526e4b17023SJohn Marino       gcc_assert ((DEP_STATUS (dep) & BEGIN_SPEC) == 0
5527e4b17023SJohn Marino 		  && (DEP_STATUS (dep) & BE_IN_SPEC) != 0
5528e4b17023SJohn Marino 		  && (DEP_STATUS (dep) & DEP_TYPES) == DEP_TRUE);
5529e4b17023SJohn Marino 
5530e4b17023SJohn Marino       check = DEP_PRO (dep);
5531e4b17023SJohn Marino 
5532e4b17023SJohn Marino       gcc_assert (!IS_SPECULATION_CHECK_P (check) && !ORIG_PAT (check)
5533e4b17023SJohn Marino 		  && QUEUE_INDEX (check) == QUEUE_NOWHERE);
5534e4b17023SJohn Marino 
5535e4b17023SJohn Marino       rec = BLOCK_FOR_INSN (check);
5536e4b17023SJohn Marino 
5537e4b17023SJohn Marino       twin = emit_insn_before (copy_insn (PATTERN (insn)), BB_END (rec));
5538e4b17023SJohn Marino       haifa_init_insn (twin);
5539e4b17023SJohn Marino 
5540e4b17023SJohn Marino       sd_copy_back_deps (twin, insn, true);
5541e4b17023SJohn Marino 
5542e4b17023SJohn Marino       if (sched_verbose && spec_info->dump)
5543e4b17023SJohn Marino         /* INSN_BB (insn) isn't determined for twin insns yet.
5544e4b17023SJohn Marino            So we can't use current_sched_info->print_insn.  */
5545e4b17023SJohn Marino         fprintf (spec_info->dump, ";;\t\tGenerated twin insn : %d/rec%d\n",
5546e4b17023SJohn Marino                  INSN_UID (twin), rec->index);
5547e4b17023SJohn Marino 
5548e4b17023SJohn Marino       twins = alloc_INSN_LIST (twin, twins);
5549e4b17023SJohn Marino 
5550e4b17023SJohn Marino       /* Add dependences between TWIN and all appropriate
5551e4b17023SJohn Marino 	 instructions from REC.  */
5552e4b17023SJohn Marino       FOR_EACH_DEP (insn, SD_LIST_SPEC_BACK, sd_it, dep)
5553e4b17023SJohn Marino 	{
5554e4b17023SJohn Marino 	  rtx pro = DEP_PRO (dep);
5555e4b17023SJohn Marino 
5556e4b17023SJohn Marino 	  gcc_assert (DEP_TYPE (dep) == REG_DEP_TRUE);
5557e4b17023SJohn Marino 
5558e4b17023SJohn Marino 	  /* INSN might have dependencies from the instructions from
5559e4b17023SJohn Marino 	     several recovery blocks.  At this iteration we process those
5560e4b17023SJohn Marino 	     producers that reside in REC.  */
5561e4b17023SJohn Marino 	  if (BLOCK_FOR_INSN (pro) == rec)
5562e4b17023SJohn Marino 	    {
5563e4b17023SJohn Marino 	      dep_def _new_dep, *new_dep = &_new_dep;
5564e4b17023SJohn Marino 
5565e4b17023SJohn Marino 	      init_dep (new_dep, pro, twin, REG_DEP_TRUE);
5566e4b17023SJohn Marino 	      sd_add_dep (new_dep, false);
5567e4b17023SJohn Marino 	    }
5568e4b17023SJohn Marino 	}
5569e4b17023SJohn Marino 
5570e4b17023SJohn Marino       process_insn_forw_deps_be_in_spec (insn, twin, ts);
5571e4b17023SJohn Marino 
5572e4b17023SJohn Marino       /* Remove all dependencies between INSN and insns in REC.  */
5573e4b17023SJohn Marino       for (sd_it = sd_iterator_start (insn, SD_LIST_SPEC_BACK);
5574e4b17023SJohn Marino 	   sd_iterator_cond (&sd_it, &dep);)
5575e4b17023SJohn Marino 	{
5576e4b17023SJohn Marino 	  rtx pro = DEP_PRO (dep);
5577e4b17023SJohn Marino 
5578e4b17023SJohn Marino 	  if (BLOCK_FOR_INSN (pro) == rec)
5579e4b17023SJohn Marino 	    sd_delete_dep (sd_it);
5580e4b17023SJohn Marino 	  else
5581e4b17023SJohn Marino 	    sd_iterator_next (&sd_it);
5582e4b17023SJohn Marino 	}
5583e4b17023SJohn Marino     }
5584e4b17023SJohn Marino 
5585e4b17023SJohn Marino   /* We couldn't have added the dependencies between INSN and TWINS earlier
5586e4b17023SJohn Marino      because that would make TWINS appear in the INSN_BACK_DEPS (INSN).  */
5587e4b17023SJohn Marino   while (twins)
5588e4b17023SJohn Marino     {
5589e4b17023SJohn Marino       rtx twin;
5590e4b17023SJohn Marino 
5591e4b17023SJohn Marino       twin = XEXP (twins, 0);
5592e4b17023SJohn Marino 
5593e4b17023SJohn Marino       {
5594e4b17023SJohn Marino 	dep_def _new_dep, *new_dep = &_new_dep;
5595e4b17023SJohn Marino 
5596e4b17023SJohn Marino 	init_dep (new_dep, insn, twin, REG_DEP_OUTPUT);
5597e4b17023SJohn Marino 	sd_add_dep (new_dep, false);
5598e4b17023SJohn Marino       }
5599e4b17023SJohn Marino 
5600e4b17023SJohn Marino       twin = XEXP (twins, 1);
5601e4b17023SJohn Marino       free_INSN_LIST_node (twins);
5602e4b17023SJohn Marino       twins = twin;
5603e4b17023SJohn Marino     }
5604e4b17023SJohn Marino 
5605e4b17023SJohn Marino   calc_priorities (priorities_roots);
5606e4b17023SJohn Marino   VEC_free (rtx, heap, priorities_roots);
5607e4b17023SJohn Marino }
5608e4b17023SJohn Marino 
5609e4b17023SJohn Marino /* Extends and fills with zeros (only the new part) array pointed to by P.  */
5610e4b17023SJohn Marino void *
xrecalloc(void * p,size_t new_nmemb,size_t old_nmemb,size_t size)5611e4b17023SJohn Marino xrecalloc (void *p, size_t new_nmemb, size_t old_nmemb, size_t size)
5612e4b17023SJohn Marino {
5613e4b17023SJohn Marino   gcc_assert (new_nmemb >= old_nmemb);
5614e4b17023SJohn Marino   p = XRESIZEVAR (void, p, new_nmemb * size);
5615e4b17023SJohn Marino   memset (((char *) p) + old_nmemb * size, 0, (new_nmemb - old_nmemb) * size);
5616e4b17023SJohn Marino   return p;
5617e4b17023SJohn Marino }
5618e4b17023SJohn Marino 
5619e4b17023SJohn Marino /* Helper function.
5620e4b17023SJohn Marino    Find fallthru edge from PRED.  */
5621e4b17023SJohn Marino edge
find_fallthru_edge_from(basic_block pred)5622e4b17023SJohn Marino find_fallthru_edge_from (basic_block pred)
5623e4b17023SJohn Marino {
5624e4b17023SJohn Marino   edge e;
5625e4b17023SJohn Marino   basic_block succ;
5626e4b17023SJohn Marino 
5627e4b17023SJohn Marino   succ = pred->next_bb;
5628e4b17023SJohn Marino   gcc_assert (succ->prev_bb == pred);
5629e4b17023SJohn Marino 
5630e4b17023SJohn Marino   if (EDGE_COUNT (pred->succs) <= EDGE_COUNT (succ->preds))
5631e4b17023SJohn Marino     {
5632e4b17023SJohn Marino       e = find_fallthru_edge (pred->succs);
5633e4b17023SJohn Marino 
5634e4b17023SJohn Marino       if (e)
5635e4b17023SJohn Marino 	{
5636e4b17023SJohn Marino 	  gcc_assert (e->dest == succ);
5637e4b17023SJohn Marino 	  return e;
5638e4b17023SJohn Marino 	}
5639e4b17023SJohn Marino     }
5640e4b17023SJohn Marino   else
5641e4b17023SJohn Marino     {
5642e4b17023SJohn Marino       e = find_fallthru_edge (succ->preds);
5643e4b17023SJohn Marino 
5644e4b17023SJohn Marino       if (e)
5645e4b17023SJohn Marino 	{
5646e4b17023SJohn Marino 	  gcc_assert (e->src == pred);
5647e4b17023SJohn Marino 	  return e;
5648e4b17023SJohn Marino 	}
5649e4b17023SJohn Marino     }
5650e4b17023SJohn Marino 
5651e4b17023SJohn Marino   return NULL;
5652e4b17023SJohn Marino }
5653e4b17023SJohn Marino 
5654e4b17023SJohn Marino /* Extend per basic block data structures.  */
5655e4b17023SJohn Marino static void
sched_extend_bb(void)5656e4b17023SJohn Marino sched_extend_bb (void)
5657e4b17023SJohn Marino {
5658e4b17023SJohn Marino   rtx insn;
5659e4b17023SJohn Marino 
5660e4b17023SJohn Marino   /* The following is done to keep current_sched_info->next_tail non null.  */
5661e4b17023SJohn Marino   insn = BB_END (EXIT_BLOCK_PTR->prev_bb);
5662e4b17023SJohn Marino   if (NEXT_INSN (insn) == 0
5663e4b17023SJohn Marino       || (!NOTE_P (insn)
5664e4b17023SJohn Marino 	  && !LABEL_P (insn)
5665e4b17023SJohn Marino 	  /* Don't emit a NOTE if it would end up before a BARRIER.  */
5666e4b17023SJohn Marino 	  && !BARRIER_P (NEXT_INSN (insn))))
5667e4b17023SJohn Marino     {
5668e4b17023SJohn Marino       rtx note = emit_note_after (NOTE_INSN_DELETED, insn);
5669e4b17023SJohn Marino       /* Make insn appear outside BB.  */
5670e4b17023SJohn Marino       set_block_for_insn (note, NULL);
5671e4b17023SJohn Marino       BB_END (EXIT_BLOCK_PTR->prev_bb) = insn;
5672e4b17023SJohn Marino     }
5673e4b17023SJohn Marino }
5674e4b17023SJohn Marino 
5675e4b17023SJohn Marino /* Init per basic block data structures.  */
5676e4b17023SJohn Marino void
sched_init_bbs(void)5677e4b17023SJohn Marino sched_init_bbs (void)
5678e4b17023SJohn Marino {
5679e4b17023SJohn Marino   sched_extend_bb ();
5680e4b17023SJohn Marino }
5681e4b17023SJohn Marino 
5682e4b17023SJohn Marino /* Initialize BEFORE_RECOVERY variable.  */
5683e4b17023SJohn Marino static void
init_before_recovery(basic_block * before_recovery_ptr)5684e4b17023SJohn Marino init_before_recovery (basic_block *before_recovery_ptr)
5685e4b17023SJohn Marino {
5686e4b17023SJohn Marino   basic_block last;
5687e4b17023SJohn Marino   edge e;
5688e4b17023SJohn Marino 
5689e4b17023SJohn Marino   last = EXIT_BLOCK_PTR->prev_bb;
5690e4b17023SJohn Marino   e = find_fallthru_edge_from (last);
5691e4b17023SJohn Marino 
5692e4b17023SJohn Marino   if (e)
5693e4b17023SJohn Marino     {
5694e4b17023SJohn Marino       /* We create two basic blocks:
5695e4b17023SJohn Marino          1. Single instruction block is inserted right after E->SRC
5696e4b17023SJohn Marino          and has jump to
5697e4b17023SJohn Marino          2. Empty block right before EXIT_BLOCK.
5698e4b17023SJohn Marino          Between these two blocks recovery blocks will be emitted.  */
5699e4b17023SJohn Marino 
5700e4b17023SJohn Marino       basic_block single, empty;
5701e4b17023SJohn Marino       rtx x, label;
5702e4b17023SJohn Marino 
5703e4b17023SJohn Marino       /* If the fallthrough edge to exit we've found is from the block we've
5704e4b17023SJohn Marino 	 created before, don't do anything more.  */
5705e4b17023SJohn Marino       if (last == after_recovery)
5706e4b17023SJohn Marino 	return;
5707e4b17023SJohn Marino 
5708e4b17023SJohn Marino       adding_bb_to_current_region_p = false;
5709e4b17023SJohn Marino 
5710e4b17023SJohn Marino       single = sched_create_empty_bb (last);
5711e4b17023SJohn Marino       empty = sched_create_empty_bb (single);
5712e4b17023SJohn Marino 
5713e4b17023SJohn Marino       /* Add new blocks to the root loop.  */
5714e4b17023SJohn Marino       if (current_loops != NULL)
5715e4b17023SJohn Marino 	{
5716e4b17023SJohn Marino 	  add_bb_to_loop (single, VEC_index (loop_p, current_loops->larray, 0));
5717e4b17023SJohn Marino 	  add_bb_to_loop (empty, VEC_index (loop_p, current_loops->larray, 0));
5718e4b17023SJohn Marino 	}
5719e4b17023SJohn Marino 
5720e4b17023SJohn Marino       single->count = last->count;
5721e4b17023SJohn Marino       empty->count = last->count;
5722e4b17023SJohn Marino       single->frequency = last->frequency;
5723e4b17023SJohn Marino       empty->frequency = last->frequency;
5724e4b17023SJohn Marino       BB_COPY_PARTITION (single, last);
5725e4b17023SJohn Marino       BB_COPY_PARTITION (empty, last);
5726e4b17023SJohn Marino 
5727e4b17023SJohn Marino       redirect_edge_succ (e, single);
5728e4b17023SJohn Marino       make_single_succ_edge (single, empty, 0);
5729e4b17023SJohn Marino       make_single_succ_edge (empty, EXIT_BLOCK_PTR,
5730e4b17023SJohn Marino 			     EDGE_FALLTHRU | EDGE_CAN_FALLTHRU);
5731e4b17023SJohn Marino 
5732e4b17023SJohn Marino       label = block_label (empty);
5733e4b17023SJohn Marino       x = emit_jump_insn_after (gen_jump (label), BB_END (single));
5734e4b17023SJohn Marino       JUMP_LABEL (x) = label;
5735e4b17023SJohn Marino       LABEL_NUSES (label)++;
5736e4b17023SJohn Marino       haifa_init_insn (x);
5737e4b17023SJohn Marino 
5738e4b17023SJohn Marino       emit_barrier_after (x);
5739e4b17023SJohn Marino 
5740e4b17023SJohn Marino       sched_init_only_bb (empty, NULL);
5741e4b17023SJohn Marino       sched_init_only_bb (single, NULL);
5742e4b17023SJohn Marino       sched_extend_bb ();
5743e4b17023SJohn Marino 
5744e4b17023SJohn Marino       adding_bb_to_current_region_p = true;
5745e4b17023SJohn Marino       before_recovery = single;
5746e4b17023SJohn Marino       after_recovery = empty;
5747e4b17023SJohn Marino 
5748e4b17023SJohn Marino       if (before_recovery_ptr)
5749e4b17023SJohn Marino         *before_recovery_ptr = before_recovery;
5750e4b17023SJohn Marino 
5751e4b17023SJohn Marino       if (sched_verbose >= 2 && spec_info->dump)
5752e4b17023SJohn Marino         fprintf (spec_info->dump,
5753e4b17023SJohn Marino 		 ";;\t\tFixed fallthru to EXIT : %d->>%d->%d->>EXIT\n",
5754e4b17023SJohn Marino                  last->index, single->index, empty->index);
5755e4b17023SJohn Marino     }
5756e4b17023SJohn Marino   else
5757e4b17023SJohn Marino     before_recovery = last;
5758e4b17023SJohn Marino }
5759e4b17023SJohn Marino 
5760e4b17023SJohn Marino /* Returns new recovery block.  */
5761e4b17023SJohn Marino basic_block
sched_create_recovery_block(basic_block * before_recovery_ptr)5762e4b17023SJohn Marino sched_create_recovery_block (basic_block *before_recovery_ptr)
5763e4b17023SJohn Marino {
5764e4b17023SJohn Marino   rtx label;
5765e4b17023SJohn Marino   rtx barrier;
5766e4b17023SJohn Marino   basic_block rec;
5767e4b17023SJohn Marino 
5768e4b17023SJohn Marino   haifa_recovery_bb_recently_added_p = true;
5769e4b17023SJohn Marino   haifa_recovery_bb_ever_added_p = true;
5770e4b17023SJohn Marino 
5771e4b17023SJohn Marino   init_before_recovery (before_recovery_ptr);
5772e4b17023SJohn Marino 
5773e4b17023SJohn Marino   barrier = get_last_bb_insn (before_recovery);
5774e4b17023SJohn Marino   gcc_assert (BARRIER_P (barrier));
5775e4b17023SJohn Marino 
5776e4b17023SJohn Marino   label = emit_label_after (gen_label_rtx (), barrier);
5777e4b17023SJohn Marino 
5778e4b17023SJohn Marino   rec = create_basic_block (label, label, before_recovery);
5779e4b17023SJohn Marino 
5780e4b17023SJohn Marino   /* A recovery block always ends with an unconditional jump.  */
5781e4b17023SJohn Marino   emit_barrier_after (BB_END (rec));
5782e4b17023SJohn Marino 
5783e4b17023SJohn Marino   if (BB_PARTITION (before_recovery) != BB_UNPARTITIONED)
5784e4b17023SJohn Marino     BB_SET_PARTITION (rec, BB_COLD_PARTITION);
5785e4b17023SJohn Marino 
5786e4b17023SJohn Marino   if (sched_verbose && spec_info->dump)
5787e4b17023SJohn Marino     fprintf (spec_info->dump, ";;\t\tGenerated recovery block rec%d\n",
5788e4b17023SJohn Marino              rec->index);
5789e4b17023SJohn Marino 
5790e4b17023SJohn Marino   return rec;
5791e4b17023SJohn Marino }
5792e4b17023SJohn Marino 
5793e4b17023SJohn Marino /* Create edges: FIRST_BB -> REC; FIRST_BB -> SECOND_BB; REC -> SECOND_BB
5794e4b17023SJohn Marino    and emit necessary jumps.  */
5795e4b17023SJohn Marino void
sched_create_recovery_edges(basic_block first_bb,basic_block rec,basic_block second_bb)5796e4b17023SJohn Marino sched_create_recovery_edges (basic_block first_bb, basic_block rec,
5797e4b17023SJohn Marino 			     basic_block second_bb)
5798e4b17023SJohn Marino {
5799e4b17023SJohn Marino   rtx label;
5800e4b17023SJohn Marino   rtx jump;
5801e4b17023SJohn Marino   int edge_flags;
5802e4b17023SJohn Marino 
5803e4b17023SJohn Marino   /* This is fixing of incoming edge.  */
5804e4b17023SJohn Marino   /* ??? Which other flags should be specified?  */
5805e4b17023SJohn Marino   if (BB_PARTITION (first_bb) != BB_PARTITION (rec))
5806e4b17023SJohn Marino     /* Partition type is the same, if it is "unpartitioned".  */
5807e4b17023SJohn Marino     edge_flags = EDGE_CROSSING;
5808e4b17023SJohn Marino   else
5809e4b17023SJohn Marino     edge_flags = 0;
5810e4b17023SJohn Marino 
5811e4b17023SJohn Marino   make_edge (first_bb, rec, edge_flags);
5812e4b17023SJohn Marino   label = block_label (second_bb);
5813e4b17023SJohn Marino   jump = emit_jump_insn_after (gen_jump (label), BB_END (rec));
5814e4b17023SJohn Marino   JUMP_LABEL (jump) = label;
5815e4b17023SJohn Marino   LABEL_NUSES (label)++;
5816e4b17023SJohn Marino 
5817e4b17023SJohn Marino   if (BB_PARTITION (second_bb) != BB_PARTITION (rec))
5818e4b17023SJohn Marino     /* Partition type is the same, if it is "unpartitioned".  */
5819e4b17023SJohn Marino     {
5820e4b17023SJohn Marino       /* Rewritten from cfgrtl.c.  */
5821e4b17023SJohn Marino       if (flag_reorder_blocks_and_partition
5822e4b17023SJohn Marino 	  && targetm_common.have_named_sections)
5823e4b17023SJohn Marino 	{
5824e4b17023SJohn Marino 	  /* We don't need the same note for the check because
5825e4b17023SJohn Marino 	     any_condjump_p (check) == true.  */
5826e4b17023SJohn Marino 	  add_reg_note (jump, REG_CROSSING_JUMP, NULL_RTX);
5827e4b17023SJohn Marino 	}
5828e4b17023SJohn Marino       edge_flags = EDGE_CROSSING;
5829e4b17023SJohn Marino     }
5830e4b17023SJohn Marino   else
5831e4b17023SJohn Marino     edge_flags = 0;
5832e4b17023SJohn Marino 
5833e4b17023SJohn Marino   make_single_succ_edge (rec, second_bb, edge_flags);
5834e4b17023SJohn Marino   if (dom_info_available_p (CDI_DOMINATORS))
5835e4b17023SJohn Marino     set_immediate_dominator (CDI_DOMINATORS, rec, first_bb);
5836e4b17023SJohn Marino }
5837e4b17023SJohn Marino 
5838e4b17023SJohn Marino /* This function creates recovery code for INSN.  If MUTATE_P is nonzero,
5839e4b17023SJohn Marino    INSN is a simple check, that should be converted to branchy one.  */
5840e4b17023SJohn Marino static void
create_check_block_twin(rtx insn,bool mutate_p)5841e4b17023SJohn Marino create_check_block_twin (rtx insn, bool mutate_p)
5842e4b17023SJohn Marino {
5843e4b17023SJohn Marino   basic_block rec;
5844e4b17023SJohn Marino   rtx label, check, twin;
5845e4b17023SJohn Marino   ds_t fs;
5846e4b17023SJohn Marino   sd_iterator_def sd_it;
5847e4b17023SJohn Marino   dep_t dep;
5848e4b17023SJohn Marino   dep_def _new_dep, *new_dep = &_new_dep;
5849e4b17023SJohn Marino   ds_t todo_spec;
5850e4b17023SJohn Marino 
5851e4b17023SJohn Marino   gcc_assert (ORIG_PAT (insn) != NULL_RTX);
5852e4b17023SJohn Marino 
5853e4b17023SJohn Marino   if (!mutate_p)
5854e4b17023SJohn Marino     todo_spec = TODO_SPEC (insn);
5855e4b17023SJohn Marino   else
5856e4b17023SJohn Marino     {
5857e4b17023SJohn Marino       gcc_assert (IS_SPECULATION_SIMPLE_CHECK_P (insn)
5858e4b17023SJohn Marino 		  && (TODO_SPEC (insn) & SPECULATIVE) == 0);
5859e4b17023SJohn Marino 
5860e4b17023SJohn Marino       todo_spec = CHECK_SPEC (insn);
5861e4b17023SJohn Marino     }
5862e4b17023SJohn Marino 
5863e4b17023SJohn Marino   todo_spec &= SPECULATIVE;
5864e4b17023SJohn Marino 
5865e4b17023SJohn Marino   /* Create recovery block.  */
5866e4b17023SJohn Marino   if (mutate_p || targetm.sched.needs_block_p (todo_spec))
5867e4b17023SJohn Marino     {
5868e4b17023SJohn Marino       rec = sched_create_recovery_block (NULL);
5869e4b17023SJohn Marino       label = BB_HEAD (rec);
5870e4b17023SJohn Marino     }
5871e4b17023SJohn Marino   else
5872e4b17023SJohn Marino     {
5873e4b17023SJohn Marino       rec = EXIT_BLOCK_PTR;
5874e4b17023SJohn Marino       label = NULL_RTX;
5875e4b17023SJohn Marino     }
5876e4b17023SJohn Marino 
5877e4b17023SJohn Marino   /* Emit CHECK.  */
5878e4b17023SJohn Marino   check = targetm.sched.gen_spec_check (insn, label, todo_spec);
5879e4b17023SJohn Marino 
5880e4b17023SJohn Marino   if (rec != EXIT_BLOCK_PTR)
5881e4b17023SJohn Marino     {
5882e4b17023SJohn Marino       /* To have mem_reg alive at the beginning of second_bb,
5883e4b17023SJohn Marino 	 we emit check BEFORE insn, so insn after splitting
5884e4b17023SJohn Marino 	 insn will be at the beginning of second_bb, which will
5885e4b17023SJohn Marino 	 provide us with the correct life information.  */
5886e4b17023SJohn Marino       check = emit_jump_insn_before (check, insn);
5887e4b17023SJohn Marino       JUMP_LABEL (check) = label;
5888e4b17023SJohn Marino       LABEL_NUSES (label)++;
5889e4b17023SJohn Marino     }
5890e4b17023SJohn Marino   else
5891e4b17023SJohn Marino     check = emit_insn_before (check, insn);
5892e4b17023SJohn Marino 
5893e4b17023SJohn Marino   /* Extend data structures.  */
5894e4b17023SJohn Marino   haifa_init_insn (check);
5895e4b17023SJohn Marino 
5896e4b17023SJohn Marino   /* CHECK is being added to current region.  Extend ready list.  */
5897e4b17023SJohn Marino   gcc_assert (sched_ready_n_insns != -1);
5898e4b17023SJohn Marino   sched_extend_ready_list (sched_ready_n_insns + 1);
5899e4b17023SJohn Marino 
5900e4b17023SJohn Marino   if (current_sched_info->add_remove_insn)
5901e4b17023SJohn Marino     current_sched_info->add_remove_insn (insn, 0);
5902e4b17023SJohn Marino 
5903e4b17023SJohn Marino   RECOVERY_BLOCK (check) = rec;
5904e4b17023SJohn Marino 
5905e4b17023SJohn Marino   if (sched_verbose && spec_info->dump)
5906e4b17023SJohn Marino     fprintf (spec_info->dump, ";;\t\tGenerated check insn : %s\n",
5907e4b17023SJohn Marino              (*current_sched_info->print_insn) (check, 0));
5908e4b17023SJohn Marino 
5909e4b17023SJohn Marino   gcc_assert (ORIG_PAT (insn));
5910e4b17023SJohn Marino 
5911e4b17023SJohn Marino   /* Initialize TWIN (twin is a duplicate of original instruction
5912e4b17023SJohn Marino      in the recovery block).  */
5913e4b17023SJohn Marino   if (rec != EXIT_BLOCK_PTR)
5914e4b17023SJohn Marino     {
5915e4b17023SJohn Marino       sd_iterator_def sd_it;
5916e4b17023SJohn Marino       dep_t dep;
5917e4b17023SJohn Marino 
5918e4b17023SJohn Marino       FOR_EACH_DEP (insn, SD_LIST_RES_BACK, sd_it, dep)
5919e4b17023SJohn Marino 	if ((DEP_STATUS (dep) & DEP_OUTPUT) != 0)
5920e4b17023SJohn Marino 	  {
5921e4b17023SJohn Marino 	    struct _dep _dep2, *dep2 = &_dep2;
5922e4b17023SJohn Marino 
5923e4b17023SJohn Marino 	    init_dep (dep2, DEP_PRO (dep), check, REG_DEP_TRUE);
5924e4b17023SJohn Marino 
5925e4b17023SJohn Marino 	    sd_add_dep (dep2, true);
5926e4b17023SJohn Marino 	  }
5927e4b17023SJohn Marino 
5928e4b17023SJohn Marino       twin = emit_insn_after (ORIG_PAT (insn), BB_END (rec));
5929e4b17023SJohn Marino       haifa_init_insn (twin);
5930e4b17023SJohn Marino 
5931e4b17023SJohn Marino       if (sched_verbose && spec_info->dump)
5932e4b17023SJohn Marino 	/* INSN_BB (insn) isn't determined for twin insns yet.
5933e4b17023SJohn Marino 	   So we can't use current_sched_info->print_insn.  */
5934e4b17023SJohn Marino 	fprintf (spec_info->dump, ";;\t\tGenerated twin insn : %d/rec%d\n",
5935e4b17023SJohn Marino 		 INSN_UID (twin), rec->index);
5936e4b17023SJohn Marino     }
5937e4b17023SJohn Marino   else
5938e4b17023SJohn Marino     {
5939e4b17023SJohn Marino       ORIG_PAT (check) = ORIG_PAT (insn);
5940e4b17023SJohn Marino       HAS_INTERNAL_DEP (check) = 1;
5941e4b17023SJohn Marino       twin = check;
5942e4b17023SJohn Marino       /* ??? We probably should change all OUTPUT dependencies to
5943e4b17023SJohn Marino 	 (TRUE | OUTPUT).  */
5944e4b17023SJohn Marino     }
5945e4b17023SJohn Marino 
5946e4b17023SJohn Marino   /* Copy all resolved back dependencies of INSN to TWIN.  This will
5947e4b17023SJohn Marino      provide correct value for INSN_TICK (TWIN).  */
5948e4b17023SJohn Marino   sd_copy_back_deps (twin, insn, true);
5949e4b17023SJohn Marino 
5950e4b17023SJohn Marino   if (rec != EXIT_BLOCK_PTR)
5951e4b17023SJohn Marino     /* In case of branchy check, fix CFG.  */
5952e4b17023SJohn Marino     {
5953e4b17023SJohn Marino       basic_block first_bb, second_bb;
5954e4b17023SJohn Marino       rtx jump;
5955e4b17023SJohn Marino 
5956e4b17023SJohn Marino       first_bb = BLOCK_FOR_INSN (check);
5957e4b17023SJohn Marino       second_bb = sched_split_block (first_bb, check);
5958e4b17023SJohn Marino 
5959e4b17023SJohn Marino       sched_create_recovery_edges (first_bb, rec, second_bb);
5960e4b17023SJohn Marino 
5961e4b17023SJohn Marino       sched_init_only_bb (second_bb, first_bb);
5962e4b17023SJohn Marino       sched_init_only_bb (rec, EXIT_BLOCK_PTR);
5963e4b17023SJohn Marino 
5964e4b17023SJohn Marino       jump = BB_END (rec);
5965e4b17023SJohn Marino       haifa_init_insn (jump);
5966e4b17023SJohn Marino     }
5967e4b17023SJohn Marino 
5968e4b17023SJohn Marino   /* Move backward dependences from INSN to CHECK and
5969e4b17023SJohn Marino      move forward dependences from INSN to TWIN.  */
5970e4b17023SJohn Marino 
5971e4b17023SJohn Marino   /* First, create dependencies between INSN's producers and CHECK & TWIN.  */
5972e4b17023SJohn Marino   FOR_EACH_DEP (insn, SD_LIST_BACK, sd_it, dep)
5973e4b17023SJohn Marino     {
5974e4b17023SJohn Marino       rtx pro = DEP_PRO (dep);
5975e4b17023SJohn Marino       ds_t ds;
5976e4b17023SJohn Marino 
5977e4b17023SJohn Marino       /* If BEGIN_DATA: [insn ~~TRUE~~> producer]:
5978e4b17023SJohn Marino 	 check --TRUE--> producer  ??? or ANTI ???
5979e4b17023SJohn Marino 	 twin  --TRUE--> producer
5980e4b17023SJohn Marino 	 twin  --ANTI--> check
5981e4b17023SJohn Marino 
5982e4b17023SJohn Marino 	 If BEGIN_CONTROL: [insn ~~ANTI~~> producer]:
5983e4b17023SJohn Marino 	 check --ANTI--> producer
5984e4b17023SJohn Marino 	 twin  --ANTI--> producer
5985e4b17023SJohn Marino 	 twin  --ANTI--> check
5986e4b17023SJohn Marino 
5987e4b17023SJohn Marino 	 If BE_IN_SPEC: [insn ~~TRUE~~> producer]:
5988e4b17023SJohn Marino 	 check ~~TRUE~~> producer
5989e4b17023SJohn Marino 	 twin  ~~TRUE~~> producer
5990e4b17023SJohn Marino 	 twin  --ANTI--> check  */
5991e4b17023SJohn Marino 
5992e4b17023SJohn Marino       ds = DEP_STATUS (dep);
5993e4b17023SJohn Marino 
5994e4b17023SJohn Marino       if (ds & BEGIN_SPEC)
5995e4b17023SJohn Marino 	{
5996e4b17023SJohn Marino 	  gcc_assert (!mutate_p);
5997e4b17023SJohn Marino 	  ds &= ~BEGIN_SPEC;
5998e4b17023SJohn Marino 	}
5999e4b17023SJohn Marino 
6000e4b17023SJohn Marino       init_dep_1 (new_dep, pro, check, DEP_TYPE (dep), ds);
6001e4b17023SJohn Marino       sd_add_dep (new_dep, false);
6002e4b17023SJohn Marino 
6003e4b17023SJohn Marino       if (rec != EXIT_BLOCK_PTR)
6004e4b17023SJohn Marino 	{
6005e4b17023SJohn Marino 	  DEP_CON (new_dep) = twin;
6006e4b17023SJohn Marino 	  sd_add_dep (new_dep, false);
6007e4b17023SJohn Marino 	}
6008e4b17023SJohn Marino     }
6009e4b17023SJohn Marino 
6010e4b17023SJohn Marino   /* Second, remove backward dependencies of INSN.  */
6011e4b17023SJohn Marino   for (sd_it = sd_iterator_start (insn, SD_LIST_SPEC_BACK);
6012e4b17023SJohn Marino        sd_iterator_cond (&sd_it, &dep);)
6013e4b17023SJohn Marino     {
6014e4b17023SJohn Marino       if ((DEP_STATUS (dep) & BEGIN_SPEC)
6015e4b17023SJohn Marino 	  || mutate_p)
6016e4b17023SJohn Marino 	/* We can delete this dep because we overcome it with
6017e4b17023SJohn Marino 	   BEGIN_SPECULATION.  */
6018e4b17023SJohn Marino 	sd_delete_dep (sd_it);
6019e4b17023SJohn Marino       else
6020e4b17023SJohn Marino 	sd_iterator_next (&sd_it);
6021e4b17023SJohn Marino     }
6022e4b17023SJohn Marino 
6023e4b17023SJohn Marino   /* Future Speculations.  Determine what BE_IN speculations will be like.  */
6024e4b17023SJohn Marino   fs = 0;
6025e4b17023SJohn Marino 
6026e4b17023SJohn Marino   /* Fields (DONE_SPEC (x) & BEGIN_SPEC) and CHECK_SPEC (x) are set only
6027e4b17023SJohn Marino      here.  */
6028e4b17023SJohn Marino 
6029e4b17023SJohn Marino   gcc_assert (!DONE_SPEC (insn));
6030e4b17023SJohn Marino 
6031e4b17023SJohn Marino   if (!mutate_p)
6032e4b17023SJohn Marino     {
6033e4b17023SJohn Marino       ds_t ts = TODO_SPEC (insn);
6034e4b17023SJohn Marino 
6035e4b17023SJohn Marino       DONE_SPEC (insn) = ts & BEGIN_SPEC;
6036e4b17023SJohn Marino       CHECK_SPEC (check) = ts & BEGIN_SPEC;
6037e4b17023SJohn Marino 
6038e4b17023SJohn Marino       /* Luckiness of future speculations solely depends upon initial
6039e4b17023SJohn Marino 	 BEGIN speculation.  */
6040e4b17023SJohn Marino       if (ts & BEGIN_DATA)
6041e4b17023SJohn Marino 	fs = set_dep_weak (fs, BE_IN_DATA, get_dep_weak (ts, BEGIN_DATA));
6042e4b17023SJohn Marino       if (ts & BEGIN_CONTROL)
6043e4b17023SJohn Marino 	fs = set_dep_weak (fs, BE_IN_CONTROL,
6044e4b17023SJohn Marino 			   get_dep_weak (ts, BEGIN_CONTROL));
6045e4b17023SJohn Marino     }
6046e4b17023SJohn Marino   else
6047e4b17023SJohn Marino     CHECK_SPEC (check) = CHECK_SPEC (insn);
6048e4b17023SJohn Marino 
6049e4b17023SJohn Marino   /* Future speculations: call the helper.  */
6050e4b17023SJohn Marino   process_insn_forw_deps_be_in_spec (insn, twin, fs);
6051e4b17023SJohn Marino 
6052e4b17023SJohn Marino   if (rec != EXIT_BLOCK_PTR)
6053e4b17023SJohn Marino     {
6054e4b17023SJohn Marino       /* Which types of dependencies should we use here is,
6055e4b17023SJohn Marino 	 generally, machine-dependent question...  But, for now,
6056e4b17023SJohn Marino 	 it is not.  */
6057e4b17023SJohn Marino 
6058e4b17023SJohn Marino       if (!mutate_p)
6059e4b17023SJohn Marino 	{
6060e4b17023SJohn Marino 	  init_dep (new_dep, insn, check, REG_DEP_TRUE);
6061e4b17023SJohn Marino 	  sd_add_dep (new_dep, false);
6062e4b17023SJohn Marino 
6063e4b17023SJohn Marino 	  init_dep (new_dep, insn, twin, REG_DEP_OUTPUT);
6064e4b17023SJohn Marino 	  sd_add_dep (new_dep, false);
6065e4b17023SJohn Marino 	}
6066e4b17023SJohn Marino       else
6067e4b17023SJohn Marino 	{
6068e4b17023SJohn Marino 	  if (spec_info->dump)
6069e4b17023SJohn Marino 	    fprintf (spec_info->dump, ";;\t\tRemoved simple check : %s\n",
6070e4b17023SJohn Marino 		     (*current_sched_info->print_insn) (insn, 0));
6071e4b17023SJohn Marino 
6072e4b17023SJohn Marino 	  /* Remove all dependencies of the INSN.  */
6073e4b17023SJohn Marino 	  {
6074e4b17023SJohn Marino 	    sd_it = sd_iterator_start (insn, (SD_LIST_FORW
6075e4b17023SJohn Marino 					      | SD_LIST_BACK
6076e4b17023SJohn Marino 					      | SD_LIST_RES_BACK));
6077e4b17023SJohn Marino 	    while (sd_iterator_cond (&sd_it, &dep))
6078e4b17023SJohn Marino 	      sd_delete_dep (sd_it);
6079e4b17023SJohn Marino 	  }
6080e4b17023SJohn Marino 
6081e4b17023SJohn Marino 	  /* If former check (INSN) already was moved to the ready (or queue)
6082e4b17023SJohn Marino 	     list, add new check (CHECK) there too.  */
6083e4b17023SJohn Marino 	  if (QUEUE_INDEX (insn) != QUEUE_NOWHERE)
6084e4b17023SJohn Marino 	    try_ready (check);
6085e4b17023SJohn Marino 
6086e4b17023SJohn Marino 	  /* Remove old check from instruction stream and free its
6087e4b17023SJohn Marino 	     data.  */
6088e4b17023SJohn Marino 	  sched_remove_insn (insn);
6089e4b17023SJohn Marino 	}
6090e4b17023SJohn Marino 
6091e4b17023SJohn Marino       init_dep (new_dep, check, twin, REG_DEP_ANTI);
6092e4b17023SJohn Marino       sd_add_dep (new_dep, false);
6093e4b17023SJohn Marino     }
6094e4b17023SJohn Marino   else
6095e4b17023SJohn Marino     {
6096e4b17023SJohn Marino       init_dep_1 (new_dep, insn, check, REG_DEP_TRUE, DEP_TRUE | DEP_OUTPUT);
6097e4b17023SJohn Marino       sd_add_dep (new_dep, false);
6098e4b17023SJohn Marino     }
6099e4b17023SJohn Marino 
6100e4b17023SJohn Marino   if (!mutate_p)
6101e4b17023SJohn Marino     /* Fix priorities.  If MUTATE_P is nonzero, this is not necessary,
6102e4b17023SJohn Marino        because it'll be done later in add_to_speculative_block.  */
6103e4b17023SJohn Marino     {
6104e4b17023SJohn Marino       rtx_vec_t priorities_roots = NULL;
6105e4b17023SJohn Marino 
6106e4b17023SJohn Marino       clear_priorities (twin, &priorities_roots);
6107e4b17023SJohn Marino       calc_priorities (priorities_roots);
6108e4b17023SJohn Marino       VEC_free (rtx, heap, priorities_roots);
6109e4b17023SJohn Marino     }
6110e4b17023SJohn Marino }
6111e4b17023SJohn Marino 
6112e4b17023SJohn Marino /* Removes dependency between instructions in the recovery block REC
6113e4b17023SJohn Marino    and usual region instructions.  It keeps inner dependences so it
6114e4b17023SJohn Marino    won't be necessary to recompute them.  */
6115e4b17023SJohn Marino static void
fix_recovery_deps(basic_block rec)6116e4b17023SJohn Marino fix_recovery_deps (basic_block rec)
6117e4b17023SJohn Marino {
6118e4b17023SJohn Marino   rtx note, insn, jump, ready_list = 0;
6119e4b17023SJohn Marino   bitmap_head in_ready;
6120e4b17023SJohn Marino   rtx link;
6121e4b17023SJohn Marino 
6122e4b17023SJohn Marino   bitmap_initialize (&in_ready, 0);
6123e4b17023SJohn Marino 
6124e4b17023SJohn Marino   /* NOTE - a basic block note.  */
6125e4b17023SJohn Marino   note = NEXT_INSN (BB_HEAD (rec));
6126e4b17023SJohn Marino   gcc_assert (NOTE_INSN_BASIC_BLOCK_P (note));
6127e4b17023SJohn Marino   insn = BB_END (rec);
6128e4b17023SJohn Marino   gcc_assert (JUMP_P (insn));
6129e4b17023SJohn Marino   insn = PREV_INSN (insn);
6130e4b17023SJohn Marino 
6131e4b17023SJohn Marino   do
6132e4b17023SJohn Marino     {
6133e4b17023SJohn Marino       sd_iterator_def sd_it;
6134e4b17023SJohn Marino       dep_t dep;
6135e4b17023SJohn Marino 
6136e4b17023SJohn Marino       for (sd_it = sd_iterator_start (insn, SD_LIST_FORW);
6137e4b17023SJohn Marino 	   sd_iterator_cond (&sd_it, &dep);)
6138e4b17023SJohn Marino 	{
6139e4b17023SJohn Marino 	  rtx consumer = DEP_CON (dep);
6140e4b17023SJohn Marino 
6141e4b17023SJohn Marino 	  if (BLOCK_FOR_INSN (consumer) != rec)
6142e4b17023SJohn Marino 	    {
6143e4b17023SJohn Marino 	      sd_delete_dep (sd_it);
6144e4b17023SJohn Marino 
6145e4b17023SJohn Marino 	      if (bitmap_set_bit (&in_ready, INSN_LUID (consumer)))
6146e4b17023SJohn Marino 		ready_list = alloc_INSN_LIST (consumer, ready_list);
6147e4b17023SJohn Marino 	    }
6148e4b17023SJohn Marino 	  else
6149e4b17023SJohn Marino 	    {
6150e4b17023SJohn Marino 	      gcc_assert ((DEP_STATUS (dep) & DEP_TYPES) == DEP_TRUE);
6151e4b17023SJohn Marino 
6152e4b17023SJohn Marino 	      sd_iterator_next (&sd_it);
6153e4b17023SJohn Marino 	    }
6154e4b17023SJohn Marino 	}
6155e4b17023SJohn Marino 
6156e4b17023SJohn Marino       insn = PREV_INSN (insn);
6157e4b17023SJohn Marino     }
6158e4b17023SJohn Marino   while (insn != note);
6159e4b17023SJohn Marino 
6160e4b17023SJohn Marino   bitmap_clear (&in_ready);
6161e4b17023SJohn Marino 
6162e4b17023SJohn Marino   /* Try to add instructions to the ready or queue list.  */
6163e4b17023SJohn Marino   for (link = ready_list; link; link = XEXP (link, 1))
6164e4b17023SJohn Marino     try_ready (XEXP (link, 0));
6165e4b17023SJohn Marino   free_INSN_LIST_list (&ready_list);
6166e4b17023SJohn Marino 
6167e4b17023SJohn Marino   /* Fixing jump's dependences.  */
6168e4b17023SJohn Marino   insn = BB_HEAD (rec);
6169e4b17023SJohn Marino   jump = BB_END (rec);
6170e4b17023SJohn Marino 
6171e4b17023SJohn Marino   gcc_assert (LABEL_P (insn));
6172e4b17023SJohn Marino   insn = NEXT_INSN (insn);
6173e4b17023SJohn Marino 
6174e4b17023SJohn Marino   gcc_assert (NOTE_INSN_BASIC_BLOCK_P (insn));
6175e4b17023SJohn Marino   add_jump_dependencies (insn, jump);
6176e4b17023SJohn Marino }
6177e4b17023SJohn Marino 
6178e4b17023SJohn Marino /* Change pattern of INSN to NEW_PAT.  Invalidate cached haifa
6179e4b17023SJohn Marino    instruction data.  */
6180e4b17023SJohn Marino static bool
haifa_change_pattern(rtx insn,rtx new_pat)6181e4b17023SJohn Marino haifa_change_pattern (rtx insn, rtx new_pat)
6182e4b17023SJohn Marino {
6183e4b17023SJohn Marino   sd_iterator_def sd_it;
6184e4b17023SJohn Marino   dep_t dep;
6185e4b17023SJohn Marino   int t;
6186e4b17023SJohn Marino 
6187e4b17023SJohn Marino   t = validate_change (insn, &PATTERN (insn), new_pat, 0);
6188e4b17023SJohn Marino   if (!t)
6189e4b17023SJohn Marino     return false;
6190e4b17023SJohn Marino   dfa_clear_single_insn_cache (insn);
6191e4b17023SJohn Marino 
6192e4b17023SJohn Marino   sd_it = sd_iterator_start (insn,
6193e4b17023SJohn Marino 			     SD_LIST_FORW | SD_LIST_BACK | SD_LIST_RES_BACK);
6194e4b17023SJohn Marino   while (sd_iterator_cond (&sd_it, &dep))
6195e4b17023SJohn Marino     {
6196e4b17023SJohn Marino       DEP_COST (dep) = UNKNOWN_DEP_COST;
6197e4b17023SJohn Marino       sd_iterator_next (&sd_it);
6198e4b17023SJohn Marino     }
6199e4b17023SJohn Marino 
6200e4b17023SJohn Marino   /* Invalidate INSN_COST, so it'll be recalculated.  */
6201e4b17023SJohn Marino   INSN_COST (insn) = -1;
6202e4b17023SJohn Marino   /* Invalidate INSN_TICK, so it'll be recalculated.  */
6203e4b17023SJohn Marino   INSN_TICK (insn) = INVALID_TICK;
6204e4b17023SJohn Marino   return true;
6205e4b17023SJohn Marino }
6206e4b17023SJohn Marino 
6207e4b17023SJohn Marino /* -1 - can't speculate,
6208e4b17023SJohn Marino    0 - for speculation with REQUEST mode it is OK to use
6209e4b17023SJohn Marino    current instruction pattern,
6210e4b17023SJohn Marino    1 - need to change pattern for *NEW_PAT to be speculative.  */
6211e4b17023SJohn Marino int
sched_speculate_insn(rtx insn,ds_t request,rtx * new_pat)6212e4b17023SJohn Marino sched_speculate_insn (rtx insn, ds_t request, rtx *new_pat)
6213e4b17023SJohn Marino {
6214e4b17023SJohn Marino   gcc_assert (current_sched_info->flags & DO_SPECULATION
6215e4b17023SJohn Marino               && (request & SPECULATIVE)
6216e4b17023SJohn Marino 	      && sched_insn_is_legitimate_for_speculation_p (insn, request));
6217e4b17023SJohn Marino 
6218e4b17023SJohn Marino   if ((request & spec_info->mask) != request)
6219e4b17023SJohn Marino     return -1;
6220e4b17023SJohn Marino 
6221e4b17023SJohn Marino   if (request & BE_IN_SPEC
6222e4b17023SJohn Marino       && !(request & BEGIN_SPEC))
6223e4b17023SJohn Marino     return 0;
6224e4b17023SJohn Marino 
6225e4b17023SJohn Marino   return targetm.sched.speculate_insn (insn, request, new_pat);
6226e4b17023SJohn Marino }
6227e4b17023SJohn Marino 
6228e4b17023SJohn Marino static int
haifa_speculate_insn(rtx insn,ds_t request,rtx * new_pat)6229e4b17023SJohn Marino haifa_speculate_insn (rtx insn, ds_t request, rtx *new_pat)
6230e4b17023SJohn Marino {
6231e4b17023SJohn Marino   gcc_assert (sched_deps_info->generate_spec_deps
6232e4b17023SJohn Marino 	      && !IS_SPECULATION_CHECK_P (insn));
6233e4b17023SJohn Marino 
6234e4b17023SJohn Marino   if (HAS_INTERNAL_DEP (insn)
6235e4b17023SJohn Marino       || SCHED_GROUP_P (insn))
6236e4b17023SJohn Marino     return -1;
6237e4b17023SJohn Marino 
6238e4b17023SJohn Marino   return sched_speculate_insn (insn, request, new_pat);
6239e4b17023SJohn Marino }
6240e4b17023SJohn Marino 
6241e4b17023SJohn Marino /* Print some information about block BB, which starts with HEAD and
6242e4b17023SJohn Marino    ends with TAIL, before scheduling it.
6243e4b17023SJohn Marino    I is zero, if scheduler is about to start with the fresh ebb.  */
6244e4b17023SJohn Marino static void
dump_new_block_header(int i,basic_block bb,rtx head,rtx tail)6245e4b17023SJohn Marino dump_new_block_header (int i, basic_block bb, rtx head, rtx tail)
6246e4b17023SJohn Marino {
6247e4b17023SJohn Marino   if (!i)
6248e4b17023SJohn Marino     fprintf (sched_dump,
6249e4b17023SJohn Marino 	     ";;   ======================================================\n");
6250e4b17023SJohn Marino   else
6251e4b17023SJohn Marino     fprintf (sched_dump,
6252e4b17023SJohn Marino 	     ";;   =====================ADVANCING TO=====================\n");
6253e4b17023SJohn Marino   fprintf (sched_dump,
6254e4b17023SJohn Marino 	   ";;   -- basic block %d from %d to %d -- %s reload\n",
6255e4b17023SJohn Marino 	   bb->index, INSN_UID (head), INSN_UID (tail),
6256e4b17023SJohn Marino 	   (reload_completed ? "after" : "before"));
6257e4b17023SJohn Marino   fprintf (sched_dump,
6258e4b17023SJohn Marino 	   ";;   ======================================================\n");
6259e4b17023SJohn Marino   fprintf (sched_dump, "\n");
6260e4b17023SJohn Marino }
6261e4b17023SJohn Marino 
6262e4b17023SJohn Marino /* Unlink basic block notes and labels and saves them, so they
6263e4b17023SJohn Marino    can be easily restored.  We unlink basic block notes in EBB to
6264e4b17023SJohn Marino    provide back-compatibility with the previous code, as target backends
6265e4b17023SJohn Marino    assume, that there'll be only instructions between
6266e4b17023SJohn Marino    current_sched_info->{head and tail}.  We restore these notes as soon
6267e4b17023SJohn Marino    as we can.
6268e4b17023SJohn Marino    FIRST (LAST) is the first (last) basic block in the ebb.
6269e4b17023SJohn Marino    NB: In usual case (FIRST == LAST) nothing is really done.  */
6270e4b17023SJohn Marino void
unlink_bb_notes(basic_block first,basic_block last)6271e4b17023SJohn Marino unlink_bb_notes (basic_block first, basic_block last)
6272e4b17023SJohn Marino {
6273e4b17023SJohn Marino   /* We DON'T unlink basic block notes of the first block in the ebb.  */
6274e4b17023SJohn Marino   if (first == last)
6275e4b17023SJohn Marino     return;
6276e4b17023SJohn Marino 
6277e4b17023SJohn Marino   bb_header = XNEWVEC (rtx, last_basic_block);
6278e4b17023SJohn Marino 
6279e4b17023SJohn Marino   /* Make a sentinel.  */
6280e4b17023SJohn Marino   if (last->next_bb != EXIT_BLOCK_PTR)
6281e4b17023SJohn Marino     bb_header[last->next_bb->index] = 0;
6282e4b17023SJohn Marino 
6283e4b17023SJohn Marino   first = first->next_bb;
6284e4b17023SJohn Marino   do
6285e4b17023SJohn Marino     {
6286e4b17023SJohn Marino       rtx prev, label, note, next;
6287e4b17023SJohn Marino 
6288e4b17023SJohn Marino       label = BB_HEAD (last);
6289e4b17023SJohn Marino       if (LABEL_P (label))
6290e4b17023SJohn Marino 	note = NEXT_INSN (label);
6291e4b17023SJohn Marino       else
6292e4b17023SJohn Marino 	note = label;
6293e4b17023SJohn Marino       gcc_assert (NOTE_INSN_BASIC_BLOCK_P (note));
6294e4b17023SJohn Marino 
6295e4b17023SJohn Marino       prev = PREV_INSN (label);
6296e4b17023SJohn Marino       next = NEXT_INSN (note);
6297e4b17023SJohn Marino       gcc_assert (prev && next);
6298e4b17023SJohn Marino 
6299e4b17023SJohn Marino       NEXT_INSN (prev) = next;
6300e4b17023SJohn Marino       PREV_INSN (next) = prev;
6301e4b17023SJohn Marino 
6302e4b17023SJohn Marino       bb_header[last->index] = label;
6303e4b17023SJohn Marino 
6304e4b17023SJohn Marino       if (last == first)
6305e4b17023SJohn Marino 	break;
6306e4b17023SJohn Marino 
6307e4b17023SJohn Marino       last = last->prev_bb;
6308e4b17023SJohn Marino     }
6309e4b17023SJohn Marino   while (1);
6310e4b17023SJohn Marino }
6311e4b17023SJohn Marino 
6312e4b17023SJohn Marino /* Restore basic block notes.
6313e4b17023SJohn Marino    FIRST is the first basic block in the ebb.  */
6314e4b17023SJohn Marino static void
restore_bb_notes(basic_block first)6315e4b17023SJohn Marino restore_bb_notes (basic_block first)
6316e4b17023SJohn Marino {
6317e4b17023SJohn Marino   if (!bb_header)
6318e4b17023SJohn Marino     return;
6319e4b17023SJohn Marino 
6320e4b17023SJohn Marino   /* We DON'T unlink basic block notes of the first block in the ebb.  */
6321e4b17023SJohn Marino   first = first->next_bb;
6322e4b17023SJohn Marino   /* Remember: FIRST is actually a second basic block in the ebb.  */
6323e4b17023SJohn Marino 
6324e4b17023SJohn Marino   while (first != EXIT_BLOCK_PTR
6325e4b17023SJohn Marino 	 && bb_header[first->index])
6326e4b17023SJohn Marino     {
6327e4b17023SJohn Marino       rtx prev, label, note, next;
6328e4b17023SJohn Marino 
6329e4b17023SJohn Marino       label = bb_header[first->index];
6330e4b17023SJohn Marino       prev = PREV_INSN (label);
6331e4b17023SJohn Marino       next = NEXT_INSN (prev);
6332e4b17023SJohn Marino 
6333e4b17023SJohn Marino       if (LABEL_P (label))
6334e4b17023SJohn Marino 	note = NEXT_INSN (label);
6335e4b17023SJohn Marino       else
6336e4b17023SJohn Marino 	note = label;
6337e4b17023SJohn Marino       gcc_assert (NOTE_INSN_BASIC_BLOCK_P (note));
6338e4b17023SJohn Marino 
6339e4b17023SJohn Marino       bb_header[first->index] = 0;
6340e4b17023SJohn Marino 
6341e4b17023SJohn Marino       NEXT_INSN (prev) = label;
6342e4b17023SJohn Marino       NEXT_INSN (note) = next;
6343e4b17023SJohn Marino       PREV_INSN (next) = note;
6344e4b17023SJohn Marino 
6345e4b17023SJohn Marino       first = first->next_bb;
6346e4b17023SJohn Marino     }
6347e4b17023SJohn Marino 
6348e4b17023SJohn Marino   free (bb_header);
6349e4b17023SJohn Marino   bb_header = 0;
6350e4b17023SJohn Marino }
6351e4b17023SJohn Marino 
6352e4b17023SJohn Marino /* Helper function.
6353e4b17023SJohn Marino    Fix CFG after both in- and inter-block movement of
6354e4b17023SJohn Marino    control_flow_insn_p JUMP.  */
6355e4b17023SJohn Marino static void
fix_jump_move(rtx jump)6356e4b17023SJohn Marino fix_jump_move (rtx jump)
6357e4b17023SJohn Marino {
6358e4b17023SJohn Marino   basic_block bb, jump_bb, jump_bb_next;
6359e4b17023SJohn Marino 
6360e4b17023SJohn Marino   bb = BLOCK_FOR_INSN (PREV_INSN (jump));
6361e4b17023SJohn Marino   jump_bb = BLOCK_FOR_INSN (jump);
6362e4b17023SJohn Marino   jump_bb_next = jump_bb->next_bb;
6363e4b17023SJohn Marino 
6364e4b17023SJohn Marino   gcc_assert (common_sched_info->sched_pass_id == SCHED_EBB_PASS
6365e4b17023SJohn Marino 	      || IS_SPECULATION_BRANCHY_CHECK_P (jump));
6366e4b17023SJohn Marino 
6367e4b17023SJohn Marino   if (!NOTE_INSN_BASIC_BLOCK_P (BB_END (jump_bb_next)))
6368e4b17023SJohn Marino     /* if jump_bb_next is not empty.  */
6369e4b17023SJohn Marino     BB_END (jump_bb) = BB_END (jump_bb_next);
6370e4b17023SJohn Marino 
6371e4b17023SJohn Marino   if (BB_END (bb) != PREV_INSN (jump))
6372e4b17023SJohn Marino     /* Then there are instruction after jump that should be placed
6373e4b17023SJohn Marino        to jump_bb_next.  */
6374e4b17023SJohn Marino     BB_END (jump_bb_next) = BB_END (bb);
6375e4b17023SJohn Marino   else
6376e4b17023SJohn Marino     /* Otherwise jump_bb_next is empty.  */
6377e4b17023SJohn Marino     BB_END (jump_bb_next) = NEXT_INSN (BB_HEAD (jump_bb_next));
6378e4b17023SJohn Marino 
6379e4b17023SJohn Marino   /* To make assertion in move_insn happy.  */
6380e4b17023SJohn Marino   BB_END (bb) = PREV_INSN (jump);
6381e4b17023SJohn Marino 
6382e4b17023SJohn Marino   update_bb_for_insn (jump_bb_next);
6383e4b17023SJohn Marino }
6384e4b17023SJohn Marino 
6385e4b17023SJohn Marino /* Fix CFG after interblock movement of control_flow_insn_p JUMP.  */
6386e4b17023SJohn Marino static void
move_block_after_check(rtx jump)6387e4b17023SJohn Marino move_block_after_check (rtx jump)
6388e4b17023SJohn Marino {
6389e4b17023SJohn Marino   basic_block bb, jump_bb, jump_bb_next;
6390e4b17023SJohn Marino   VEC(edge,gc) *t;
6391e4b17023SJohn Marino 
6392e4b17023SJohn Marino   bb = BLOCK_FOR_INSN (PREV_INSN (jump));
6393e4b17023SJohn Marino   jump_bb = BLOCK_FOR_INSN (jump);
6394e4b17023SJohn Marino   jump_bb_next = jump_bb->next_bb;
6395e4b17023SJohn Marino 
6396e4b17023SJohn Marino   update_bb_for_insn (jump_bb);
6397e4b17023SJohn Marino 
6398e4b17023SJohn Marino   gcc_assert (IS_SPECULATION_CHECK_P (jump)
6399e4b17023SJohn Marino 	      || IS_SPECULATION_CHECK_P (BB_END (jump_bb_next)));
6400e4b17023SJohn Marino 
6401e4b17023SJohn Marino   unlink_block (jump_bb_next);
6402e4b17023SJohn Marino   link_block (jump_bb_next, bb);
6403e4b17023SJohn Marino 
6404e4b17023SJohn Marino   t = bb->succs;
6405e4b17023SJohn Marino   bb->succs = 0;
6406e4b17023SJohn Marino   move_succs (&(jump_bb->succs), bb);
6407e4b17023SJohn Marino   move_succs (&(jump_bb_next->succs), jump_bb);
6408e4b17023SJohn Marino   move_succs (&t, jump_bb_next);
6409e4b17023SJohn Marino 
6410e4b17023SJohn Marino   df_mark_solutions_dirty ();
6411e4b17023SJohn Marino 
6412e4b17023SJohn Marino   common_sched_info->fix_recovery_cfg
6413e4b17023SJohn Marino     (bb->index, jump_bb->index, jump_bb_next->index);
6414e4b17023SJohn Marino }
6415e4b17023SJohn Marino 
6416e4b17023SJohn Marino /* Helper function for move_block_after_check.
6417e4b17023SJohn Marino    This functions attaches edge vector pointed to by SUCCSP to
6418e4b17023SJohn Marino    block TO.  */
6419e4b17023SJohn Marino static void
move_succs(VEC (edge,gc)** succsp,basic_block to)6420e4b17023SJohn Marino move_succs (VEC(edge,gc) **succsp, basic_block to)
6421e4b17023SJohn Marino {
6422e4b17023SJohn Marino   edge e;
6423e4b17023SJohn Marino   edge_iterator ei;
6424e4b17023SJohn Marino 
6425e4b17023SJohn Marino   gcc_assert (to->succs == 0);
6426e4b17023SJohn Marino 
6427e4b17023SJohn Marino   to->succs = *succsp;
6428e4b17023SJohn Marino 
6429e4b17023SJohn Marino   FOR_EACH_EDGE (e, ei, to->succs)
6430e4b17023SJohn Marino     e->src = to;
6431e4b17023SJohn Marino 
6432e4b17023SJohn Marino   *succsp = 0;
6433e4b17023SJohn Marino }
6434e4b17023SJohn Marino 
6435e4b17023SJohn Marino /* Remove INSN from the instruction stream.
6436e4b17023SJohn Marino    INSN should have any dependencies.  */
6437e4b17023SJohn Marino static void
sched_remove_insn(rtx insn)6438e4b17023SJohn Marino sched_remove_insn (rtx insn)
6439e4b17023SJohn Marino {
6440e4b17023SJohn Marino   sd_finish_insn (insn);
6441e4b17023SJohn Marino 
6442e4b17023SJohn Marino   change_queue_index (insn, QUEUE_NOWHERE);
6443e4b17023SJohn Marino   current_sched_info->add_remove_insn (insn, 1);
6444e4b17023SJohn Marino   remove_insn (insn);
6445e4b17023SJohn Marino }
6446e4b17023SJohn Marino 
6447e4b17023SJohn Marino /* Clear priorities of all instructions, that are forward dependent on INSN.
6448e4b17023SJohn Marino    Store in vector pointed to by ROOTS_PTR insns on which priority () should
6449e4b17023SJohn Marino    be invoked to initialize all cleared priorities.  */
6450e4b17023SJohn Marino static void
clear_priorities(rtx insn,rtx_vec_t * roots_ptr)6451e4b17023SJohn Marino clear_priorities (rtx insn, rtx_vec_t *roots_ptr)
6452e4b17023SJohn Marino {
6453e4b17023SJohn Marino   sd_iterator_def sd_it;
6454e4b17023SJohn Marino   dep_t dep;
6455e4b17023SJohn Marino   bool insn_is_root_p = true;
6456e4b17023SJohn Marino 
6457e4b17023SJohn Marino   gcc_assert (QUEUE_INDEX (insn) != QUEUE_SCHEDULED);
6458e4b17023SJohn Marino 
6459e4b17023SJohn Marino   FOR_EACH_DEP (insn, SD_LIST_BACK, sd_it, dep)
6460e4b17023SJohn Marino     {
6461e4b17023SJohn Marino       rtx pro = DEP_PRO (dep);
6462e4b17023SJohn Marino 
6463e4b17023SJohn Marino       if (INSN_PRIORITY_STATUS (pro) >= 0
6464e4b17023SJohn Marino 	  && QUEUE_INDEX (insn) != QUEUE_SCHEDULED)
6465e4b17023SJohn Marino 	{
6466e4b17023SJohn Marino 	  /* If DEP doesn't contribute to priority then INSN itself should
6467e4b17023SJohn Marino 	     be added to priority roots.  */
6468e4b17023SJohn Marino 	  if (contributes_to_priority_p (dep))
6469e4b17023SJohn Marino 	    insn_is_root_p = false;
6470e4b17023SJohn Marino 
6471e4b17023SJohn Marino 	  INSN_PRIORITY_STATUS (pro) = -1;
6472e4b17023SJohn Marino 	  clear_priorities (pro, roots_ptr);
6473e4b17023SJohn Marino 	}
6474e4b17023SJohn Marino     }
6475e4b17023SJohn Marino 
6476e4b17023SJohn Marino   if (insn_is_root_p)
6477e4b17023SJohn Marino     VEC_safe_push (rtx, heap, *roots_ptr, insn);
6478e4b17023SJohn Marino }
6479e4b17023SJohn Marino 
6480e4b17023SJohn Marino /* Recompute priorities of instructions, whose priorities might have been
6481e4b17023SJohn Marino    changed.  ROOTS is a vector of instructions whose priority computation will
6482e4b17023SJohn Marino    trigger initialization of all cleared priorities.  */
6483e4b17023SJohn Marino static void
calc_priorities(rtx_vec_t roots)6484e4b17023SJohn Marino calc_priorities (rtx_vec_t roots)
6485e4b17023SJohn Marino {
6486e4b17023SJohn Marino   int i;
6487e4b17023SJohn Marino   rtx insn;
6488e4b17023SJohn Marino 
6489e4b17023SJohn Marino   FOR_EACH_VEC_ELT (rtx, roots, i, insn)
6490e4b17023SJohn Marino     priority (insn);
6491e4b17023SJohn Marino }
6492e4b17023SJohn Marino 
6493e4b17023SJohn Marino 
6494e4b17023SJohn Marino /* Add dependences between JUMP and other instructions in the recovery
6495e4b17023SJohn Marino    block.  INSN is the first insn the recovery block.  */
6496e4b17023SJohn Marino static void
add_jump_dependencies(rtx insn,rtx jump)6497e4b17023SJohn Marino add_jump_dependencies (rtx insn, rtx jump)
6498e4b17023SJohn Marino {
6499e4b17023SJohn Marino   do
6500e4b17023SJohn Marino     {
6501e4b17023SJohn Marino       insn = NEXT_INSN (insn);
6502e4b17023SJohn Marino       if (insn == jump)
6503e4b17023SJohn Marino 	break;
6504e4b17023SJohn Marino 
6505e4b17023SJohn Marino       if (dep_list_size (insn) == 0)
6506e4b17023SJohn Marino 	{
6507e4b17023SJohn Marino 	  dep_def _new_dep, *new_dep = &_new_dep;
6508e4b17023SJohn Marino 
6509e4b17023SJohn Marino 	  init_dep (new_dep, insn, jump, REG_DEP_ANTI);
6510e4b17023SJohn Marino 	  sd_add_dep (new_dep, false);
6511e4b17023SJohn Marino 	}
6512e4b17023SJohn Marino     }
6513e4b17023SJohn Marino   while (1);
6514e4b17023SJohn Marino 
6515e4b17023SJohn Marino   gcc_assert (!sd_lists_empty_p (jump, SD_LIST_BACK));
6516e4b17023SJohn Marino }
6517e4b17023SJohn Marino 
6518e4b17023SJohn Marino /* Extend data structures for logical insn UID.  */
6519e4b17023SJohn Marino void
sched_extend_luids(void)6520e4b17023SJohn Marino sched_extend_luids (void)
6521e4b17023SJohn Marino {
6522e4b17023SJohn Marino   int new_luids_max_uid = get_max_uid () + 1;
6523e4b17023SJohn Marino 
6524e4b17023SJohn Marino   VEC_safe_grow_cleared (int, heap, sched_luids, new_luids_max_uid);
6525e4b17023SJohn Marino }
6526e4b17023SJohn Marino 
6527e4b17023SJohn Marino /* Initialize LUID for INSN.  */
6528e4b17023SJohn Marino void
sched_init_insn_luid(rtx insn)6529e4b17023SJohn Marino sched_init_insn_luid (rtx insn)
6530e4b17023SJohn Marino {
6531e4b17023SJohn Marino   int i = INSN_P (insn) ? 1 : common_sched_info->luid_for_non_insn (insn);
6532e4b17023SJohn Marino   int luid;
6533e4b17023SJohn Marino 
6534e4b17023SJohn Marino   if (i >= 0)
6535e4b17023SJohn Marino     {
6536e4b17023SJohn Marino       luid = sched_max_luid;
6537e4b17023SJohn Marino       sched_max_luid += i;
6538e4b17023SJohn Marino     }
6539e4b17023SJohn Marino   else
6540e4b17023SJohn Marino     luid = -1;
6541e4b17023SJohn Marino 
6542e4b17023SJohn Marino   SET_INSN_LUID (insn, luid);
6543e4b17023SJohn Marino }
6544e4b17023SJohn Marino 
6545e4b17023SJohn Marino /* Initialize luids for BBS.
6546e4b17023SJohn Marino    The hook common_sched_info->luid_for_non_insn () is used to determine
6547e4b17023SJohn Marino    if notes, labels, etc. need luids.  */
6548e4b17023SJohn Marino void
sched_init_luids(bb_vec_t bbs)6549e4b17023SJohn Marino sched_init_luids (bb_vec_t bbs)
6550e4b17023SJohn Marino {
6551e4b17023SJohn Marino   int i;
6552e4b17023SJohn Marino   basic_block bb;
6553e4b17023SJohn Marino 
6554e4b17023SJohn Marino   sched_extend_luids ();
6555e4b17023SJohn Marino   FOR_EACH_VEC_ELT (basic_block, bbs, i, bb)
6556e4b17023SJohn Marino     {
6557e4b17023SJohn Marino       rtx insn;
6558e4b17023SJohn Marino 
6559e4b17023SJohn Marino       FOR_BB_INSNS (bb, insn)
6560e4b17023SJohn Marino 	sched_init_insn_luid (insn);
6561e4b17023SJohn Marino     }
6562e4b17023SJohn Marino }
6563e4b17023SJohn Marino 
6564e4b17023SJohn Marino /* Free LUIDs.  */
6565e4b17023SJohn Marino void
sched_finish_luids(void)6566e4b17023SJohn Marino sched_finish_luids (void)
6567e4b17023SJohn Marino {
6568e4b17023SJohn Marino   VEC_free (int, heap, sched_luids);
6569e4b17023SJohn Marino   sched_max_luid = 1;
6570e4b17023SJohn Marino }
6571e4b17023SJohn Marino 
6572e4b17023SJohn Marino /* Return logical uid of INSN.  Helpful while debugging.  */
6573e4b17023SJohn Marino int
insn_luid(rtx insn)6574e4b17023SJohn Marino insn_luid (rtx insn)
6575e4b17023SJohn Marino {
6576e4b17023SJohn Marino   return INSN_LUID (insn);
6577e4b17023SJohn Marino }
6578e4b17023SJohn Marino 
6579e4b17023SJohn Marino /* Extend per insn data in the target.  */
6580e4b17023SJohn Marino void
sched_extend_target(void)6581e4b17023SJohn Marino sched_extend_target (void)
6582e4b17023SJohn Marino {
6583e4b17023SJohn Marino   if (targetm.sched.h_i_d_extended)
6584e4b17023SJohn Marino     targetm.sched.h_i_d_extended ();
6585e4b17023SJohn Marino }
6586e4b17023SJohn Marino 
6587e4b17023SJohn Marino /* Extend global scheduler structures (those, that live across calls to
6588e4b17023SJohn Marino    schedule_block) to include information about just emitted INSN.  */
6589e4b17023SJohn Marino static void
extend_h_i_d(void)6590e4b17023SJohn Marino extend_h_i_d (void)
6591e4b17023SJohn Marino {
6592e4b17023SJohn Marino   int reserve = (get_max_uid () + 1
6593e4b17023SJohn Marino                  - VEC_length (haifa_insn_data_def, h_i_d));
6594e4b17023SJohn Marino   if (reserve > 0
6595e4b17023SJohn Marino       && ! VEC_space (haifa_insn_data_def, h_i_d, reserve))
6596e4b17023SJohn Marino     {
6597e4b17023SJohn Marino       VEC_safe_grow_cleared (haifa_insn_data_def, heap, h_i_d,
6598e4b17023SJohn Marino                              3 * get_max_uid () / 2);
6599e4b17023SJohn Marino       sched_extend_target ();
6600e4b17023SJohn Marino     }
6601e4b17023SJohn Marino }
6602e4b17023SJohn Marino 
6603e4b17023SJohn Marino /* Initialize h_i_d entry of the INSN with default values.
6604e4b17023SJohn Marino    Values, that are not explicitly initialized here, hold zero.  */
6605e4b17023SJohn Marino static void
init_h_i_d(rtx insn)6606e4b17023SJohn Marino init_h_i_d (rtx insn)
6607e4b17023SJohn Marino {
6608e4b17023SJohn Marino   if (INSN_LUID (insn) > 0)
6609e4b17023SJohn Marino     {
6610e4b17023SJohn Marino       INSN_COST (insn) = -1;
6611e4b17023SJohn Marino       QUEUE_INDEX (insn) = QUEUE_NOWHERE;
6612e4b17023SJohn Marino       INSN_TICK (insn) = INVALID_TICK;
6613e4b17023SJohn Marino       INSN_EXACT_TICK (insn) = INVALID_TICK;
6614e4b17023SJohn Marino       INTER_TICK (insn) = INVALID_TICK;
6615e4b17023SJohn Marino       TODO_SPEC (insn) = HARD_DEP;
6616e4b17023SJohn Marino     }
6617e4b17023SJohn Marino }
6618e4b17023SJohn Marino 
6619e4b17023SJohn Marino /* Initialize haifa_insn_data for BBS.  */
6620e4b17023SJohn Marino void
haifa_init_h_i_d(bb_vec_t bbs)6621e4b17023SJohn Marino haifa_init_h_i_d (bb_vec_t bbs)
6622e4b17023SJohn Marino {
6623e4b17023SJohn Marino   int i;
6624e4b17023SJohn Marino   basic_block bb;
6625e4b17023SJohn Marino 
6626e4b17023SJohn Marino   extend_h_i_d ();
6627e4b17023SJohn Marino   FOR_EACH_VEC_ELT (basic_block, bbs, i, bb)
6628e4b17023SJohn Marino     {
6629e4b17023SJohn Marino       rtx insn;
6630e4b17023SJohn Marino 
6631e4b17023SJohn Marino       FOR_BB_INSNS (bb, insn)
6632e4b17023SJohn Marino 	init_h_i_d (insn);
6633e4b17023SJohn Marino     }
6634e4b17023SJohn Marino }
6635e4b17023SJohn Marino 
6636e4b17023SJohn Marino /* Finalize haifa_insn_data.  */
6637e4b17023SJohn Marino void
haifa_finish_h_i_d(void)6638e4b17023SJohn Marino haifa_finish_h_i_d (void)
6639e4b17023SJohn Marino {
6640e4b17023SJohn Marino   int i;
6641e4b17023SJohn Marino   haifa_insn_data_t data;
6642e4b17023SJohn Marino   struct reg_use_data *use, *next;
6643e4b17023SJohn Marino 
6644e4b17023SJohn Marino   FOR_EACH_VEC_ELT (haifa_insn_data_def, h_i_d, i, data)
6645e4b17023SJohn Marino     {
6646e4b17023SJohn Marino       free (data->reg_pressure);
6647e4b17023SJohn Marino       for (use = data->reg_use_list; use != NULL; use = next)
6648e4b17023SJohn Marino 	{
6649e4b17023SJohn Marino 	  next = use->next_insn_use;
6650e4b17023SJohn Marino 	  free (use);
6651e4b17023SJohn Marino 	}
6652e4b17023SJohn Marino     }
6653e4b17023SJohn Marino   VEC_free (haifa_insn_data_def, heap, h_i_d);
6654e4b17023SJohn Marino }
6655e4b17023SJohn Marino 
6656e4b17023SJohn Marino /* Init data for the new insn INSN.  */
6657e4b17023SJohn Marino static void
haifa_init_insn(rtx insn)6658e4b17023SJohn Marino haifa_init_insn (rtx insn)
6659e4b17023SJohn Marino {
6660e4b17023SJohn Marino   gcc_assert (insn != NULL);
6661e4b17023SJohn Marino 
6662e4b17023SJohn Marino   sched_extend_luids ();
6663e4b17023SJohn Marino   sched_init_insn_luid (insn);
6664e4b17023SJohn Marino   sched_extend_target ();
6665e4b17023SJohn Marino   sched_deps_init (false);
6666e4b17023SJohn Marino   extend_h_i_d ();
6667e4b17023SJohn Marino   init_h_i_d (insn);
6668e4b17023SJohn Marino 
6669e4b17023SJohn Marino   if (adding_bb_to_current_region_p)
6670e4b17023SJohn Marino     {
6671e4b17023SJohn Marino       sd_init_insn (insn);
6672e4b17023SJohn Marino 
6673e4b17023SJohn Marino       /* Extend dependency caches by one element.  */
6674e4b17023SJohn Marino       extend_dependency_caches (1, false);
6675e4b17023SJohn Marino     }
6676e4b17023SJohn Marino   if (sched_pressure_p)
6677e4b17023SJohn Marino     init_insn_reg_pressure_info (insn);
6678e4b17023SJohn Marino }
6679e4b17023SJohn Marino 
6680e4b17023SJohn Marino /* Init data for the new basic block BB which comes after AFTER.  */
6681e4b17023SJohn Marino static void
haifa_init_only_bb(basic_block bb,basic_block after)6682e4b17023SJohn Marino haifa_init_only_bb (basic_block bb, basic_block after)
6683e4b17023SJohn Marino {
6684e4b17023SJohn Marino   gcc_assert (bb != NULL);
6685e4b17023SJohn Marino 
6686e4b17023SJohn Marino   sched_init_bbs ();
6687e4b17023SJohn Marino 
6688e4b17023SJohn Marino   if (common_sched_info->add_block)
6689e4b17023SJohn Marino     /* This changes only data structures of the front-end.  */
6690e4b17023SJohn Marino     common_sched_info->add_block (bb, after);
6691e4b17023SJohn Marino }
6692e4b17023SJohn Marino 
6693e4b17023SJohn Marino /* A generic version of sched_split_block ().  */
6694e4b17023SJohn Marino basic_block
sched_split_block_1(basic_block first_bb,rtx after)6695e4b17023SJohn Marino sched_split_block_1 (basic_block first_bb, rtx after)
6696e4b17023SJohn Marino {
6697e4b17023SJohn Marino   edge e;
6698e4b17023SJohn Marino 
6699e4b17023SJohn Marino   e = split_block (first_bb, after);
6700e4b17023SJohn Marino   gcc_assert (e->src == first_bb);
6701e4b17023SJohn Marino 
6702e4b17023SJohn Marino   /* sched_split_block emits note if *check == BB_END.  Probably it
6703e4b17023SJohn Marino      is better to rip that note off.  */
6704e4b17023SJohn Marino 
6705e4b17023SJohn Marino   return e->dest;
6706e4b17023SJohn Marino }
6707e4b17023SJohn Marino 
6708e4b17023SJohn Marino /* A generic version of sched_create_empty_bb ().  */
6709e4b17023SJohn Marino basic_block
sched_create_empty_bb_1(basic_block after)6710e4b17023SJohn Marino sched_create_empty_bb_1 (basic_block after)
6711e4b17023SJohn Marino {
6712e4b17023SJohn Marino   return create_empty_bb (after);
6713e4b17023SJohn Marino }
6714e4b17023SJohn Marino 
6715e4b17023SJohn Marino /* Insert PAT as an INSN into the schedule and update the necessary data
6716e4b17023SJohn Marino    structures to account for it. */
6717e4b17023SJohn Marino rtx
sched_emit_insn(rtx pat)6718e4b17023SJohn Marino sched_emit_insn (rtx pat)
6719e4b17023SJohn Marino {
6720e4b17023SJohn Marino   rtx insn = emit_insn_before (pat, nonscheduled_insns_begin);
6721e4b17023SJohn Marino   haifa_init_insn (insn);
6722e4b17023SJohn Marino 
6723e4b17023SJohn Marino   if (current_sched_info->add_remove_insn)
6724e4b17023SJohn Marino     current_sched_info->add_remove_insn (insn, 0);
6725e4b17023SJohn Marino 
6726e4b17023SJohn Marino   (*current_sched_info->begin_schedule_ready) (insn);
6727e4b17023SJohn Marino   VEC_safe_push (rtx, heap, scheduled_insns, insn);
6728e4b17023SJohn Marino 
6729e4b17023SJohn Marino   last_scheduled_insn = insn;
6730e4b17023SJohn Marino   return insn;
6731e4b17023SJohn Marino }
6732e4b17023SJohn Marino 
6733e4b17023SJohn Marino /* This function returns a candidate satisfying dispatch constraints from
6734e4b17023SJohn Marino    the ready list.  */
6735e4b17023SJohn Marino 
6736e4b17023SJohn Marino static rtx
ready_remove_first_dispatch(struct ready_list * ready)6737e4b17023SJohn Marino ready_remove_first_dispatch (struct ready_list *ready)
6738e4b17023SJohn Marino {
6739e4b17023SJohn Marino   int i;
6740e4b17023SJohn Marino   rtx insn = ready_element (ready, 0);
6741e4b17023SJohn Marino 
6742e4b17023SJohn Marino   if (ready->n_ready == 1
6743e4b17023SJohn Marino       || INSN_CODE (insn) < 0
6744e4b17023SJohn Marino       || !INSN_P (insn)
6745e4b17023SJohn Marino       || !active_insn_p (insn)
6746e4b17023SJohn Marino       || targetm.sched.dispatch (insn, FITS_DISPATCH_WINDOW))
6747e4b17023SJohn Marino     return ready_remove_first (ready);
6748e4b17023SJohn Marino 
6749e4b17023SJohn Marino   for (i = 1; i < ready->n_ready; i++)
6750e4b17023SJohn Marino     {
6751e4b17023SJohn Marino       insn = ready_element (ready, i);
6752e4b17023SJohn Marino 
6753e4b17023SJohn Marino       if (INSN_CODE (insn) < 0
6754e4b17023SJohn Marino 	  || !INSN_P (insn)
6755e4b17023SJohn Marino 	  || !active_insn_p (insn))
6756e4b17023SJohn Marino 	continue;
6757e4b17023SJohn Marino 
6758e4b17023SJohn Marino       if (targetm.sched.dispatch (insn, FITS_DISPATCH_WINDOW))
6759e4b17023SJohn Marino 	{
6760e4b17023SJohn Marino 	  /* Return ith element of ready.  */
6761e4b17023SJohn Marino 	  insn = ready_remove (ready, i);
6762e4b17023SJohn Marino 	  return insn;
6763e4b17023SJohn Marino 	}
6764e4b17023SJohn Marino     }
6765e4b17023SJohn Marino 
6766e4b17023SJohn Marino   if (targetm.sched.dispatch (NULL_RTX, DISPATCH_VIOLATION))
6767e4b17023SJohn Marino     return ready_remove_first (ready);
6768e4b17023SJohn Marino 
6769e4b17023SJohn Marino   for (i = 1; i < ready->n_ready; i++)
6770e4b17023SJohn Marino     {
6771e4b17023SJohn Marino       insn = ready_element (ready, i);
6772e4b17023SJohn Marino 
6773e4b17023SJohn Marino       if (INSN_CODE (insn) < 0
6774e4b17023SJohn Marino 	  || !INSN_P (insn)
6775e4b17023SJohn Marino 	  || !active_insn_p (insn))
6776e4b17023SJohn Marino 	continue;
6777e4b17023SJohn Marino 
6778e4b17023SJohn Marino       /* Return i-th element of ready.  */
6779e4b17023SJohn Marino       if (targetm.sched.dispatch (insn, IS_CMP))
6780e4b17023SJohn Marino 	return ready_remove (ready, i);
6781e4b17023SJohn Marino     }
6782e4b17023SJohn Marino 
6783e4b17023SJohn Marino   return ready_remove_first (ready);
6784e4b17023SJohn Marino }
6785e4b17023SJohn Marino 
6786e4b17023SJohn Marino /* Get number of ready insn in the ready list.  */
6787e4b17023SJohn Marino 
6788e4b17023SJohn Marino int
number_in_ready(void)6789e4b17023SJohn Marino number_in_ready (void)
6790e4b17023SJohn Marino {
6791e4b17023SJohn Marino   return ready.n_ready;
6792e4b17023SJohn Marino }
6793e4b17023SJohn Marino 
6794e4b17023SJohn Marino /* Get number of ready's in the ready list.  */
6795e4b17023SJohn Marino 
6796e4b17023SJohn Marino rtx
get_ready_element(int i)6797e4b17023SJohn Marino get_ready_element (int i)
6798e4b17023SJohn Marino {
6799e4b17023SJohn Marino   return ready_element (&ready, i);
6800e4b17023SJohn Marino }
6801e4b17023SJohn Marino 
6802e4b17023SJohn Marino #endif /* INSN_SCHEDULING */
6803