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