xref: /dragonfly/contrib/gcc-8.0/gcc/haifa-sched.c (revision 38fd1498)
1*38fd1498Szrj /* Instruction scheduling pass.
2*38fd1498Szrj    Copyright (C) 1992-2018 Free Software Foundation, Inc.
3*38fd1498Szrj    Contributed by Michael Tiemann (tiemann@cygnus.com) Enhanced by,
4*38fd1498Szrj    and currently maintained by, Jim Wilson (wilson@cygnus.com)
5*38fd1498Szrj 
6*38fd1498Szrj This file is part of GCC.
7*38fd1498Szrj 
8*38fd1498Szrj GCC is free software; you can redistribute it and/or modify it under
9*38fd1498Szrj the terms of the GNU General Public License as published by the Free
10*38fd1498Szrj Software Foundation; either version 3, or (at your option) any later
11*38fd1498Szrj version.
12*38fd1498Szrj 
13*38fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14*38fd1498Szrj WARRANTY; without even the implied warranty of MERCHANTABILITY or
15*38fd1498Szrj FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16*38fd1498Szrj for more details.
17*38fd1498Szrj 
18*38fd1498Szrj You should have received a copy of the GNU General Public License
19*38fd1498Szrj along with GCC; see the file COPYING3.  If not see
20*38fd1498Szrj <http://www.gnu.org/licenses/>.  */
21*38fd1498Szrj 
22*38fd1498Szrj /* Instruction scheduling pass.  This file, along with sched-deps.c,
23*38fd1498Szrj    contains the generic parts.  The actual entry point for
24*38fd1498Szrj    the normal instruction scheduling pass is found in sched-rgn.c.
25*38fd1498Szrj 
26*38fd1498Szrj    We compute insn priorities based on data dependencies.  Flow
27*38fd1498Szrj    analysis only creates a fraction of the data-dependencies we must
28*38fd1498Szrj    observe: namely, only those dependencies which the combiner can be
29*38fd1498Szrj    expected to use.  For this pass, we must therefore create the
30*38fd1498Szrj    remaining dependencies we need to observe: register dependencies,
31*38fd1498Szrj    memory dependencies, dependencies to keep function calls in order,
32*38fd1498Szrj    and the dependence between a conditional branch and the setting of
33*38fd1498Szrj    condition codes are all dealt with here.
34*38fd1498Szrj 
35*38fd1498Szrj    The scheduler first traverses the data flow graph, starting with
36*38fd1498Szrj    the last instruction, and proceeding to the first, assigning values
37*38fd1498Szrj    to insn_priority as it goes.  This sorts the instructions
38*38fd1498Szrj    topologically by data dependence.
39*38fd1498Szrj 
40*38fd1498Szrj    Once priorities have been established, we order the insns using
41*38fd1498Szrj    list scheduling.  This works as follows: starting with a list of
42*38fd1498Szrj    all the ready insns, and sorted according to priority number, we
43*38fd1498Szrj    schedule the insn from the end of the list by placing its
44*38fd1498Szrj    predecessors in the list according to their priority order.  We
45*38fd1498Szrj    consider this insn scheduled by setting the pointer to the "end" of
46*38fd1498Szrj    the list to point to the previous insn.  When an insn has no
47*38fd1498Szrj    predecessors, we either queue it until sufficient time has elapsed
48*38fd1498Szrj    or add it to the ready list.  As the instructions are scheduled or
49*38fd1498Szrj    when stalls are introduced, the queue advances and dumps insns into
50*38fd1498Szrj    the ready list.  When all insns down to the lowest priority have
51*38fd1498Szrj    been scheduled, the critical path of the basic block has been made
52*38fd1498Szrj    as short as possible.  The remaining insns are then scheduled in
53*38fd1498Szrj    remaining slots.
54*38fd1498Szrj 
55*38fd1498Szrj    The following list shows the order in which we want to break ties
56*38fd1498Szrj    among insns in the ready list:
57*38fd1498Szrj 
58*38fd1498Szrj    1.  choose insn with the longest path to end of bb, ties
59*38fd1498Szrj    broken by
60*38fd1498Szrj    2.  choose insn with least contribution to register pressure,
61*38fd1498Szrj    ties broken by
62*38fd1498Szrj    3.  prefer in-block upon interblock motion, ties broken by
63*38fd1498Szrj    4.  prefer useful upon speculative motion, ties broken by
64*38fd1498Szrj    5.  choose insn with largest control flow probability, ties
65*38fd1498Szrj    broken by
66*38fd1498Szrj    6.  choose insn with the least dependences upon the previously
67*38fd1498Szrj    scheduled insn, or finally
68*38fd1498Szrj    7   choose the insn which has the most insns dependent on it.
69*38fd1498Szrj    8.  choose insn with lowest UID.
70*38fd1498Szrj 
71*38fd1498Szrj    Memory references complicate matters.  Only if we can be certain
72*38fd1498Szrj    that memory references are not part of the data dependency graph
73*38fd1498Szrj    (via true, anti, or output dependence), can we move operations past
74*38fd1498Szrj    memory references.  To first approximation, reads can be done
75*38fd1498Szrj    independently, while writes introduce dependencies.  Better
76*38fd1498Szrj    approximations will yield fewer dependencies.
77*38fd1498Szrj 
78*38fd1498Szrj    Before reload, an extended analysis of interblock data dependences
79*38fd1498Szrj    is required for interblock scheduling.  This is performed in
80*38fd1498Szrj    compute_block_dependences ().
81*38fd1498Szrj 
82*38fd1498Szrj    Dependencies set up by memory references are treated in exactly the
83*38fd1498Szrj    same way as other dependencies, by using insn backward dependences
84*38fd1498Szrj    INSN_BACK_DEPS.  INSN_BACK_DEPS are translated into forward dependences
85*38fd1498Szrj    INSN_FORW_DEPS for the purpose of forward list scheduling.
86*38fd1498Szrj 
87*38fd1498Szrj    Having optimized the critical path, we may have also unduly
88*38fd1498Szrj    extended the lifetimes of some registers.  If an operation requires
89*38fd1498Szrj    that constants be loaded into registers, it is certainly desirable
90*38fd1498Szrj    to load those constants as early as necessary, but no earlier.
91*38fd1498Szrj    I.e., it will not do to load up a bunch of registers at the
92*38fd1498Szrj    beginning of a basic block only to use them at the end, if they
93*38fd1498Szrj    could be loaded later, since this may result in excessive register
94*38fd1498Szrj    utilization.
95*38fd1498Szrj 
96*38fd1498Szrj    Note that since branches are never in basic blocks, but only end
97*38fd1498Szrj    basic blocks, this pass will not move branches.  But that is ok,
98*38fd1498Szrj    since we can use GNU's delayed branch scheduling pass to take care
99*38fd1498Szrj    of this case.
100*38fd1498Szrj 
101*38fd1498Szrj    Also note that no further optimizations based on algebraic
102*38fd1498Szrj    identities are performed, so this pass would be a good one to
103*38fd1498Szrj    perform instruction splitting, such as breaking up a multiply
104*38fd1498Szrj    instruction into shifts and adds where that is profitable.
105*38fd1498Szrj 
106*38fd1498Szrj    Given the memory aliasing analysis that this pass should perform,
107*38fd1498Szrj    it should be possible to remove redundant stores to memory, and to
108*38fd1498Szrj    load values from registers instead of hitting memory.
109*38fd1498Szrj 
110*38fd1498Szrj    Before reload, speculative insns are moved only if a 'proof' exists
111*38fd1498Szrj    that no exception will be caused by this, and if no live registers
112*38fd1498Szrj    exist that inhibit the motion (live registers constraints are not
113*38fd1498Szrj    represented by data dependence edges).
114*38fd1498Szrj 
115*38fd1498Szrj    This pass must update information that subsequent passes expect to
116*38fd1498Szrj    be correct.  Namely: reg_n_refs, reg_n_sets, reg_n_deaths,
117*38fd1498Szrj    reg_n_calls_crossed, and reg_live_length.  Also, BB_HEAD, BB_END.
118*38fd1498Szrj 
119*38fd1498Szrj    The information in the line number notes is carefully retained by
120*38fd1498Szrj    this pass.  Notes that refer to the starting and ending of
121*38fd1498Szrj    exception regions are also carefully retained by this pass.  All
122*38fd1498Szrj    other NOTE insns are grouped in their same relative order at the
123*38fd1498Szrj    beginning of basic blocks and regions that have been scheduled.  */
124*38fd1498Szrj 
125*38fd1498Szrj #include "config.h"
126*38fd1498Szrj #include "system.h"
127*38fd1498Szrj #include "coretypes.h"
128*38fd1498Szrj #include "backend.h"
129*38fd1498Szrj #include "target.h"
130*38fd1498Szrj #include "rtl.h"
131*38fd1498Szrj #include "cfghooks.h"
132*38fd1498Szrj #include "df.h"
133*38fd1498Szrj #include "memmodel.h"
134*38fd1498Szrj #include "tm_p.h"
135*38fd1498Szrj #include "insn-config.h"
136*38fd1498Szrj #include "regs.h"
137*38fd1498Szrj #include "ira.h"
138*38fd1498Szrj #include "recog.h"
139*38fd1498Szrj #include "insn-attr.h"
140*38fd1498Szrj #include "cfgrtl.h"
141*38fd1498Szrj #include "cfgbuild.h"
142*38fd1498Szrj #include "sched-int.h"
143*38fd1498Szrj #include "common/common-target.h"
144*38fd1498Szrj #include "params.h"
145*38fd1498Szrj #include "dbgcnt.h"
146*38fd1498Szrj #include "cfgloop.h"
147*38fd1498Szrj #include "dumpfile.h"
148*38fd1498Szrj #include "print-rtl.h"
149*38fd1498Szrj 
150*38fd1498Szrj #ifdef INSN_SCHEDULING
151*38fd1498Szrj 
152*38fd1498Szrj /* True if we do register pressure relief through live-range
153*38fd1498Szrj    shrinkage.  */
154*38fd1498Szrj static bool live_range_shrinkage_p;
155*38fd1498Szrj 
156*38fd1498Szrj /* Switch on live range shrinkage.  */
157*38fd1498Szrj void
initialize_live_range_shrinkage(void)158*38fd1498Szrj initialize_live_range_shrinkage (void)
159*38fd1498Szrj {
160*38fd1498Szrj   live_range_shrinkage_p = true;
161*38fd1498Szrj }
162*38fd1498Szrj 
163*38fd1498Szrj /* Switch off live range shrinkage.  */
164*38fd1498Szrj void
finish_live_range_shrinkage(void)165*38fd1498Szrj finish_live_range_shrinkage (void)
166*38fd1498Szrj {
167*38fd1498Szrj   live_range_shrinkage_p = false;
168*38fd1498Szrj }
169*38fd1498Szrj 
170*38fd1498Szrj /* issue_rate is the number of insns that can be scheduled in the same
171*38fd1498Szrj    machine cycle.  It can be defined in the config/mach/mach.h file,
172*38fd1498Szrj    otherwise we set it to 1.  */
173*38fd1498Szrj 
174*38fd1498Szrj int issue_rate;
175*38fd1498Szrj 
176*38fd1498Szrj /* This can be set to true by a backend if the scheduler should not
177*38fd1498Szrj    enable a DCE pass.  */
178*38fd1498Szrj bool sched_no_dce;
179*38fd1498Szrj 
180*38fd1498Szrj /* The current initiation interval used when modulo scheduling.  */
181*38fd1498Szrj static int modulo_ii;
182*38fd1498Szrj 
183*38fd1498Szrj /* The maximum number of stages we are prepared to handle.  */
184*38fd1498Szrj static int modulo_max_stages;
185*38fd1498Szrj 
186*38fd1498Szrj /* The number of insns that exist in each iteration of the loop.  We use this
187*38fd1498Szrj    to detect when we've scheduled all insns from the first iteration.  */
188*38fd1498Szrj static int modulo_n_insns;
189*38fd1498Szrj 
190*38fd1498Szrj /* The current count of insns in the first iteration of the loop that have
191*38fd1498Szrj    already been scheduled.  */
192*38fd1498Szrj static int modulo_insns_scheduled;
193*38fd1498Szrj 
194*38fd1498Szrj /* The maximum uid of insns from the first iteration of the loop.  */
195*38fd1498Szrj static int modulo_iter0_max_uid;
196*38fd1498Szrj 
197*38fd1498Szrj /* The number of times we should attempt to backtrack when modulo scheduling.
198*38fd1498Szrj    Decreased each time we have to backtrack.  */
199*38fd1498Szrj static int modulo_backtracks_left;
200*38fd1498Szrj 
201*38fd1498Szrj /* The stage in which the last insn from the original loop was
202*38fd1498Szrj    scheduled.  */
203*38fd1498Szrj static int modulo_last_stage;
204*38fd1498Szrj 
205*38fd1498Szrj /* sched-verbose controls the amount of debugging output the
206*38fd1498Szrj    scheduler prints.  It is controlled by -fsched-verbose=N:
207*38fd1498Szrj    N=0: no debugging output.
208*38fd1498Szrj    N=1: default value.
209*38fd1498Szrj    N=2: bb's probabilities, detailed ready list info, unit/insn info.
210*38fd1498Szrj    N=3: rtl at abort point, control-flow, regions info.
211*38fd1498Szrj    N=5: dependences info.  */
212*38fd1498Szrj int sched_verbose = 0;
213*38fd1498Szrj 
214*38fd1498Szrj /* Debugging file.  All printouts are sent to dump. */
215*38fd1498Szrj FILE *sched_dump = 0;
216*38fd1498Szrj 
217*38fd1498Szrj /* This is a placeholder for the scheduler parameters common
218*38fd1498Szrj    to all schedulers.  */
219*38fd1498Szrj struct common_sched_info_def *common_sched_info;
220*38fd1498Szrj 
221*38fd1498Szrj #define INSN_TICK(INSN)	(HID (INSN)->tick)
222*38fd1498Szrj #define INSN_EXACT_TICK(INSN) (HID (INSN)->exact_tick)
223*38fd1498Szrj #define INSN_TICK_ESTIMATE(INSN) (HID (INSN)->tick_estimate)
224*38fd1498Szrj #define INTER_TICK(INSN) (HID (INSN)->inter_tick)
225*38fd1498Szrj #define FEEDS_BACKTRACK_INSN(INSN) (HID (INSN)->feeds_backtrack_insn)
226*38fd1498Szrj #define SHADOW_P(INSN) (HID (INSN)->shadow_p)
227*38fd1498Szrj #define MUST_RECOMPUTE_SPEC_P(INSN) (HID (INSN)->must_recompute_spec)
228*38fd1498Szrj /* Cached cost of the instruction.  Use insn_sched_cost to get cost of the
229*38fd1498Szrj    insn.  -1 here means that the field is not initialized.  */
230*38fd1498Szrj #define INSN_COST(INSN)	(HID (INSN)->cost)
231*38fd1498Szrj 
232*38fd1498Szrj /* If INSN_TICK of an instruction is equal to INVALID_TICK,
233*38fd1498Szrj    then it should be recalculated from scratch.  */
234*38fd1498Szrj #define INVALID_TICK (-(max_insn_queue_index + 1))
235*38fd1498Szrj /* The minimal value of the INSN_TICK of an instruction.  */
236*38fd1498Szrj #define MIN_TICK (-max_insn_queue_index)
237*38fd1498Szrj 
238*38fd1498Szrj /* Original order of insns in the ready list.
239*38fd1498Szrj    Used to keep order of normal insns while separating DEBUG_INSNs.  */
240*38fd1498Szrj #define INSN_RFS_DEBUG_ORIG_ORDER(INSN) (HID (INSN)->rfs_debug_orig_order)
241*38fd1498Szrj 
242*38fd1498Szrj /* The deciding reason for INSN's place in the ready list.  */
243*38fd1498Szrj #define INSN_LAST_RFS_WIN(INSN) (HID (INSN)->last_rfs_win)
244*38fd1498Szrj 
245*38fd1498Szrj /* List of important notes we must keep around.  This is a pointer to the
246*38fd1498Szrj    last element in the list.  */
247*38fd1498Szrj rtx_insn *note_list;
248*38fd1498Szrj 
249*38fd1498Szrj static struct spec_info_def spec_info_var;
250*38fd1498Szrj /* Description of the speculative part of the scheduling.
251*38fd1498Szrj    If NULL - no speculation.  */
252*38fd1498Szrj spec_info_t spec_info = NULL;
253*38fd1498Szrj 
254*38fd1498Szrj /* True, if recovery block was added during scheduling of current block.
255*38fd1498Szrj    Used to determine, if we need to fix INSN_TICKs.  */
256*38fd1498Szrj static bool haifa_recovery_bb_recently_added_p;
257*38fd1498Szrj 
258*38fd1498Szrj /* True, if recovery block was added during this scheduling pass.
259*38fd1498Szrj    Used to determine if we should have empty memory pools of dependencies
260*38fd1498Szrj    after finishing current region.  */
261*38fd1498Szrj bool haifa_recovery_bb_ever_added_p;
262*38fd1498Szrj 
263*38fd1498Szrj /* Counters of different types of speculative instructions.  */
264*38fd1498Szrj static int nr_begin_data, nr_be_in_data, nr_begin_control, nr_be_in_control;
265*38fd1498Szrj 
266*38fd1498Szrj /* Array used in {unlink, restore}_bb_notes.  */
267*38fd1498Szrj static rtx_insn **bb_header = 0;
268*38fd1498Szrj 
269*38fd1498Szrj /* Basic block after which recovery blocks will be created.  */
270*38fd1498Szrj static basic_block before_recovery;
271*38fd1498Szrj 
272*38fd1498Szrj /* Basic block just before the EXIT_BLOCK and after recovery, if we have
273*38fd1498Szrj    created it.  */
274*38fd1498Szrj basic_block after_recovery;
275*38fd1498Szrj 
276*38fd1498Szrj /* FALSE if we add bb to another region, so we don't need to initialize it.  */
277*38fd1498Szrj bool adding_bb_to_current_region_p = true;
278*38fd1498Szrj 
279*38fd1498Szrj /* Queues, etc.  */
280*38fd1498Szrj 
281*38fd1498Szrj /* An instruction is ready to be scheduled when all insns preceding it
282*38fd1498Szrj    have already been scheduled.  It is important to ensure that all
283*38fd1498Szrj    insns which use its result will not be executed until its result
284*38fd1498Szrj    has been computed.  An insn is maintained in one of four structures:
285*38fd1498Szrj 
286*38fd1498Szrj    (P) the "Pending" set of insns which cannot be scheduled until
287*38fd1498Szrj    their dependencies have been satisfied.
288*38fd1498Szrj    (Q) the "Queued" set of insns that can be scheduled when sufficient
289*38fd1498Szrj    time has passed.
290*38fd1498Szrj    (R) the "Ready" list of unscheduled, uncommitted insns.
291*38fd1498Szrj    (S) the "Scheduled" list of insns.
292*38fd1498Szrj 
293*38fd1498Szrj    Initially, all insns are either "Pending" or "Ready" depending on
294*38fd1498Szrj    whether their dependencies are satisfied.
295*38fd1498Szrj 
296*38fd1498Szrj    Insns move from the "Ready" list to the "Scheduled" list as they
297*38fd1498Szrj    are committed to the schedule.  As this occurs, the insns in the
298*38fd1498Szrj    "Pending" list have their dependencies satisfied and move to either
299*38fd1498Szrj    the "Ready" list or the "Queued" set depending on whether
300*38fd1498Szrj    sufficient time has passed to make them ready.  As time passes,
301*38fd1498Szrj    insns move from the "Queued" set to the "Ready" list.
302*38fd1498Szrj 
303*38fd1498Szrj    The "Pending" list (P) are the insns in the INSN_FORW_DEPS of the
304*38fd1498Szrj    unscheduled insns, i.e., those that are ready, queued, and pending.
305*38fd1498Szrj    The "Queued" set (Q) is implemented by the variable `insn_queue'.
306*38fd1498Szrj    The "Ready" list (R) is implemented by the variables `ready' and
307*38fd1498Szrj    `n_ready'.
308*38fd1498Szrj    The "Scheduled" list (S) is the new insn chain built by this pass.
309*38fd1498Szrj 
310*38fd1498Szrj    The transition (R->S) is implemented in the scheduling loop in
311*38fd1498Szrj    `schedule_block' when the best insn to schedule is chosen.
312*38fd1498Szrj    The transitions (P->R and P->Q) are implemented in `schedule_insn' as
313*38fd1498Szrj    insns move from the ready list to the scheduled list.
314*38fd1498Szrj    The transition (Q->R) is implemented in 'queue_to_insn' as time
315*38fd1498Szrj    passes or stalls are introduced.  */
316*38fd1498Szrj 
317*38fd1498Szrj /* Implement a circular buffer to delay instructions until sufficient
318*38fd1498Szrj    time has passed.  For the new pipeline description interface,
319*38fd1498Szrj    MAX_INSN_QUEUE_INDEX is a power of two minus one which is not less
320*38fd1498Szrj    than maximal time of instruction execution computed by genattr.c on
321*38fd1498Szrj    the base maximal time of functional unit reservations and getting a
322*38fd1498Szrj    result.  This is the longest time an insn may be queued.  */
323*38fd1498Szrj 
324*38fd1498Szrj static rtx_insn_list **insn_queue;
325*38fd1498Szrj static int q_ptr = 0;
326*38fd1498Szrj static int q_size = 0;
327*38fd1498Szrj #define NEXT_Q(X) (((X)+1) & max_insn_queue_index)
328*38fd1498Szrj #define NEXT_Q_AFTER(X, C) (((X)+C) & max_insn_queue_index)
329*38fd1498Szrj 
330*38fd1498Szrj #define QUEUE_SCHEDULED (-3)
331*38fd1498Szrj #define QUEUE_NOWHERE   (-2)
332*38fd1498Szrj #define QUEUE_READY     (-1)
333*38fd1498Szrj /* QUEUE_SCHEDULED - INSN is scheduled.
334*38fd1498Szrj    QUEUE_NOWHERE   - INSN isn't scheduled yet and is neither in
335*38fd1498Szrj    queue or ready list.
336*38fd1498Szrj    QUEUE_READY     - INSN is in ready list.
337*38fd1498Szrj    N >= 0 - INSN queued for X [where NEXT_Q_AFTER (q_ptr, X) == N] cycles.  */
338*38fd1498Szrj 
339*38fd1498Szrj #define QUEUE_INDEX(INSN) (HID (INSN)->queue_index)
340*38fd1498Szrj 
341*38fd1498Szrj /* The following variable value refers for all current and future
342*38fd1498Szrj    reservations of the processor units.  */
343*38fd1498Szrj state_t curr_state;
344*38fd1498Szrj 
345*38fd1498Szrj /* The following variable value is size of memory representing all
346*38fd1498Szrj    current and future reservations of the processor units.  */
347*38fd1498Szrj size_t dfa_state_size;
348*38fd1498Szrj 
349*38fd1498Szrj /* The following array is used to find the best insn from ready when
350*38fd1498Szrj    the automaton pipeline interface is used.  */
351*38fd1498Szrj signed char *ready_try = NULL;
352*38fd1498Szrj 
353*38fd1498Szrj /* The ready list.  */
354*38fd1498Szrj struct ready_list ready = {NULL, 0, 0, 0, 0};
355*38fd1498Szrj 
356*38fd1498Szrj /* The pointer to the ready list (to be removed).  */
357*38fd1498Szrj static struct ready_list *readyp = &ready;
358*38fd1498Szrj 
359*38fd1498Szrj /* Scheduling clock.  */
360*38fd1498Szrj static int clock_var;
361*38fd1498Szrj 
362*38fd1498Szrj /* Clock at which the previous instruction was issued.  */
363*38fd1498Szrj static int last_clock_var;
364*38fd1498Szrj 
365*38fd1498Szrj /* Set to true if, when queuing a shadow insn, we discover that it would be
366*38fd1498Szrj    scheduled too late.  */
367*38fd1498Szrj static bool must_backtrack;
368*38fd1498Szrj 
369*38fd1498Szrj /* The following variable value is number of essential insns issued on
370*38fd1498Szrj    the current cycle.  An insn is essential one if it changes the
371*38fd1498Szrj    processors state.  */
372*38fd1498Szrj int cycle_issued_insns;
373*38fd1498Szrj 
374*38fd1498Szrj /* This records the actual schedule.  It is built up during the main phase
375*38fd1498Szrj    of schedule_block, and afterwards used to reorder the insns in the RTL.  */
376*38fd1498Szrj static vec<rtx_insn *> scheduled_insns;
377*38fd1498Szrj 
378*38fd1498Szrj static int may_trap_exp (const_rtx, int);
379*38fd1498Szrj 
380*38fd1498Szrj /* Nonzero iff the address is comprised from at most 1 register.  */
381*38fd1498Szrj #define CONST_BASED_ADDRESS_P(x)			\
382*38fd1498Szrj   (REG_P (x)					\
383*38fd1498Szrj    || ((GET_CODE (x) == PLUS || GET_CODE (x) == MINUS	\
384*38fd1498Szrj 	|| (GET_CODE (x) == LO_SUM))			\
385*38fd1498Szrj        && (CONSTANT_P (XEXP (x, 0))			\
386*38fd1498Szrj 	   || CONSTANT_P (XEXP (x, 1)))))
387*38fd1498Szrj 
388*38fd1498Szrj /* Returns a class that insn with GET_DEST(insn)=x may belong to,
389*38fd1498Szrj    as found by analyzing insn's expression.  */
390*38fd1498Szrj 
391*38fd1498Szrj 
392*38fd1498Szrj static int haifa_luid_for_non_insn (rtx x);
393*38fd1498Szrj 
394*38fd1498Szrj /* Haifa version of sched_info hooks common to all headers.  */
395*38fd1498Szrj const struct common_sched_info_def haifa_common_sched_info =
396*38fd1498Szrj   {
397*38fd1498Szrj     NULL, /* fix_recovery_cfg */
398*38fd1498Szrj     NULL, /* add_block */
399*38fd1498Szrj     NULL, /* estimate_number_of_insns */
400*38fd1498Szrj     haifa_luid_for_non_insn, /* luid_for_non_insn */
401*38fd1498Szrj     SCHED_PASS_UNKNOWN /* sched_pass_id */
402*38fd1498Szrj   };
403*38fd1498Szrj 
404*38fd1498Szrj /* Mapping from instruction UID to its Logical UID.  */
405*38fd1498Szrj vec<int> sched_luids;
406*38fd1498Szrj 
407*38fd1498Szrj /* Next LUID to assign to an instruction.  */
408*38fd1498Szrj int sched_max_luid = 1;
409*38fd1498Szrj 
410*38fd1498Szrj /* Haifa Instruction Data.  */
411*38fd1498Szrj vec<haifa_insn_data_def> h_i_d;
412*38fd1498Szrj 
413*38fd1498Szrj void (* sched_init_only_bb) (basic_block, basic_block);
414*38fd1498Szrj 
415*38fd1498Szrj /* Split block function.  Different schedulers might use different functions
416*38fd1498Szrj    to handle their internal data consistent.  */
417*38fd1498Szrj basic_block (* sched_split_block) (basic_block, rtx);
418*38fd1498Szrj 
419*38fd1498Szrj /* Create empty basic block after the specified block.  */
420*38fd1498Szrj basic_block (* sched_create_empty_bb) (basic_block);
421*38fd1498Szrj 
422*38fd1498Szrj /* Return the number of cycles until INSN is expected to be ready.
423*38fd1498Szrj    Return zero if it already is.  */
424*38fd1498Szrj static int
insn_delay(rtx_insn * insn)425*38fd1498Szrj insn_delay (rtx_insn *insn)
426*38fd1498Szrj {
427*38fd1498Szrj   return MAX (INSN_TICK (insn) - clock_var, 0);
428*38fd1498Szrj }
429*38fd1498Szrj 
430*38fd1498Szrj static int
may_trap_exp(const_rtx x,int is_store)431*38fd1498Szrj may_trap_exp (const_rtx x, int is_store)
432*38fd1498Szrj {
433*38fd1498Szrj   enum rtx_code code;
434*38fd1498Szrj 
435*38fd1498Szrj   if (x == 0)
436*38fd1498Szrj     return TRAP_FREE;
437*38fd1498Szrj   code = GET_CODE (x);
438*38fd1498Szrj   if (is_store)
439*38fd1498Szrj     {
440*38fd1498Szrj       if (code == MEM && may_trap_p (x))
441*38fd1498Szrj 	return TRAP_RISKY;
442*38fd1498Szrj       else
443*38fd1498Szrj 	return TRAP_FREE;
444*38fd1498Szrj     }
445*38fd1498Szrj   if (code == MEM)
446*38fd1498Szrj     {
447*38fd1498Szrj       /* The insn uses memory:  a volatile load.  */
448*38fd1498Szrj       if (MEM_VOLATILE_P (x))
449*38fd1498Szrj 	return IRISKY;
450*38fd1498Szrj       /* An exception-free load.  */
451*38fd1498Szrj       if (!may_trap_p (x))
452*38fd1498Szrj 	return IFREE;
453*38fd1498Szrj       /* A load with 1 base register, to be further checked.  */
454*38fd1498Szrj       if (CONST_BASED_ADDRESS_P (XEXP (x, 0)))
455*38fd1498Szrj 	return PFREE_CANDIDATE;
456*38fd1498Szrj       /* No info on the load, to be further checked.  */
457*38fd1498Szrj       return PRISKY_CANDIDATE;
458*38fd1498Szrj     }
459*38fd1498Szrj   else
460*38fd1498Szrj     {
461*38fd1498Szrj       const char *fmt;
462*38fd1498Szrj       int i, insn_class = TRAP_FREE;
463*38fd1498Szrj 
464*38fd1498Szrj       /* Neither store nor load, check if it may cause a trap.  */
465*38fd1498Szrj       if (may_trap_p (x))
466*38fd1498Szrj 	return TRAP_RISKY;
467*38fd1498Szrj       /* Recursive step: walk the insn...  */
468*38fd1498Szrj       fmt = GET_RTX_FORMAT (code);
469*38fd1498Szrj       for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
470*38fd1498Szrj 	{
471*38fd1498Szrj 	  if (fmt[i] == 'e')
472*38fd1498Szrj 	    {
473*38fd1498Szrj 	      int tmp_class = may_trap_exp (XEXP (x, i), is_store);
474*38fd1498Szrj 	      insn_class = WORST_CLASS (insn_class, tmp_class);
475*38fd1498Szrj 	    }
476*38fd1498Szrj 	  else if (fmt[i] == 'E')
477*38fd1498Szrj 	    {
478*38fd1498Szrj 	      int j;
479*38fd1498Szrj 	      for (j = 0; j < XVECLEN (x, i); j++)
480*38fd1498Szrj 		{
481*38fd1498Szrj 		  int tmp_class = may_trap_exp (XVECEXP (x, i, j), is_store);
482*38fd1498Szrj 		  insn_class = WORST_CLASS (insn_class, tmp_class);
483*38fd1498Szrj 		  if (insn_class == TRAP_RISKY || insn_class == IRISKY)
484*38fd1498Szrj 		    break;
485*38fd1498Szrj 		}
486*38fd1498Szrj 	    }
487*38fd1498Szrj 	  if (insn_class == TRAP_RISKY || insn_class == IRISKY)
488*38fd1498Szrj 	    break;
489*38fd1498Szrj 	}
490*38fd1498Szrj       return insn_class;
491*38fd1498Szrj     }
492*38fd1498Szrj }
493*38fd1498Szrj 
494*38fd1498Szrj /* Classifies rtx X of an insn for the purpose of verifying that X can be
495*38fd1498Szrj    executed speculatively (and consequently the insn can be moved
496*38fd1498Szrj    speculatively), by examining X, returning:
497*38fd1498Szrj    TRAP_RISKY: store, or risky non-load insn (e.g. division by variable).
498*38fd1498Szrj    TRAP_FREE: non-load insn.
499*38fd1498Szrj    IFREE: load from a globally safe location.
500*38fd1498Szrj    IRISKY: volatile load.
501*38fd1498Szrj    PFREE_CANDIDATE, PRISKY_CANDIDATE: load that need to be checked for
502*38fd1498Szrj    being either PFREE or PRISKY.  */
503*38fd1498Szrj 
504*38fd1498Szrj static int
haifa_classify_rtx(const_rtx x)505*38fd1498Szrj haifa_classify_rtx (const_rtx x)
506*38fd1498Szrj {
507*38fd1498Szrj   int tmp_class = TRAP_FREE;
508*38fd1498Szrj   int insn_class = TRAP_FREE;
509*38fd1498Szrj   enum rtx_code code;
510*38fd1498Szrj 
511*38fd1498Szrj   if (GET_CODE (x) == PARALLEL)
512*38fd1498Szrj     {
513*38fd1498Szrj       int i, len = XVECLEN (x, 0);
514*38fd1498Szrj 
515*38fd1498Szrj       for (i = len - 1; i >= 0; i--)
516*38fd1498Szrj 	{
517*38fd1498Szrj 	  tmp_class = haifa_classify_rtx (XVECEXP (x, 0, i));
518*38fd1498Szrj 	  insn_class = WORST_CLASS (insn_class, tmp_class);
519*38fd1498Szrj 	  if (insn_class == TRAP_RISKY || insn_class == IRISKY)
520*38fd1498Szrj 	    break;
521*38fd1498Szrj 	}
522*38fd1498Szrj     }
523*38fd1498Szrj   else
524*38fd1498Szrj     {
525*38fd1498Szrj       code = GET_CODE (x);
526*38fd1498Szrj       switch (code)
527*38fd1498Szrj 	{
528*38fd1498Szrj 	case CLOBBER:
529*38fd1498Szrj 	  /* Test if it is a 'store'.  */
530*38fd1498Szrj 	  tmp_class = may_trap_exp (XEXP (x, 0), 1);
531*38fd1498Szrj 	  break;
532*38fd1498Szrj 	case SET:
533*38fd1498Szrj 	  /* Test if it is a store.  */
534*38fd1498Szrj 	  tmp_class = may_trap_exp (SET_DEST (x), 1);
535*38fd1498Szrj 	  if (tmp_class == TRAP_RISKY)
536*38fd1498Szrj 	    break;
537*38fd1498Szrj 	  /* Test if it is a load.  */
538*38fd1498Szrj 	  tmp_class =
539*38fd1498Szrj 	    WORST_CLASS (tmp_class,
540*38fd1498Szrj 			 may_trap_exp (SET_SRC (x), 0));
541*38fd1498Szrj 	  break;
542*38fd1498Szrj 	case COND_EXEC:
543*38fd1498Szrj 	  tmp_class = haifa_classify_rtx (COND_EXEC_CODE (x));
544*38fd1498Szrj 	  if (tmp_class == TRAP_RISKY)
545*38fd1498Szrj 	    break;
546*38fd1498Szrj 	  tmp_class = WORST_CLASS (tmp_class,
547*38fd1498Szrj 				   may_trap_exp (COND_EXEC_TEST (x), 0));
548*38fd1498Szrj 	  break;
549*38fd1498Szrj 	case TRAP_IF:
550*38fd1498Szrj 	  tmp_class = TRAP_RISKY;
551*38fd1498Szrj 	  break;
552*38fd1498Szrj 	default:;
553*38fd1498Szrj 	}
554*38fd1498Szrj       insn_class = tmp_class;
555*38fd1498Szrj     }
556*38fd1498Szrj 
557*38fd1498Szrj   return insn_class;
558*38fd1498Szrj }
559*38fd1498Szrj 
560*38fd1498Szrj int
haifa_classify_insn(const_rtx insn)561*38fd1498Szrj haifa_classify_insn (const_rtx insn)
562*38fd1498Szrj {
563*38fd1498Szrj   return haifa_classify_rtx (PATTERN (insn));
564*38fd1498Szrj }
565*38fd1498Szrj 
566*38fd1498Szrj /* After the scheduler initialization function has been called, this function
567*38fd1498Szrj    can be called to enable modulo scheduling.  II is the initiation interval
568*38fd1498Szrj    we should use, it affects the delays for delay_pairs that were recorded as
569*38fd1498Szrj    separated by a given number of stages.
570*38fd1498Szrj 
571*38fd1498Szrj    MAX_STAGES provides us with a limit
572*38fd1498Szrj    after which we give up scheduling; the caller must have unrolled at least
573*38fd1498Szrj    as many copies of the loop body and recorded delay_pairs for them.
574*38fd1498Szrj 
575*38fd1498Szrj    INSNS is the number of real (non-debug) insns in one iteration of
576*38fd1498Szrj    the loop.  MAX_UID can be used to test whether an insn belongs to
577*38fd1498Szrj    the first iteration of the loop; all of them have a uid lower than
578*38fd1498Szrj    MAX_UID.  */
579*38fd1498Szrj void
set_modulo_params(int ii,int max_stages,int insns,int max_uid)580*38fd1498Szrj set_modulo_params (int ii, int max_stages, int insns, int max_uid)
581*38fd1498Szrj {
582*38fd1498Szrj   modulo_ii = ii;
583*38fd1498Szrj   modulo_max_stages = max_stages;
584*38fd1498Szrj   modulo_n_insns = insns;
585*38fd1498Szrj   modulo_iter0_max_uid = max_uid;
586*38fd1498Szrj   modulo_backtracks_left = PARAM_VALUE (PARAM_MAX_MODULO_BACKTRACK_ATTEMPTS);
587*38fd1498Szrj }
588*38fd1498Szrj 
589*38fd1498Szrj /* A structure to record a pair of insns where the first one is a real
590*38fd1498Szrj    insn that has delay slots, and the second is its delayed shadow.
591*38fd1498Szrj    I1 is scheduled normally and will emit an assembly instruction,
592*38fd1498Szrj    while I2 describes the side effect that takes place at the
593*38fd1498Szrj    transition between cycles CYCLES and (CYCLES + 1) after I1.  */
594*38fd1498Szrj struct delay_pair
595*38fd1498Szrj {
596*38fd1498Szrj   struct delay_pair *next_same_i1;
597*38fd1498Szrj   rtx_insn *i1, *i2;
598*38fd1498Szrj   int cycles;
599*38fd1498Szrj   /* When doing modulo scheduling, we a delay_pair can also be used to
600*38fd1498Szrj      show that I1 and I2 are the same insn in a different stage.  If that
601*38fd1498Szrj      is the case, STAGES will be nonzero.  */
602*38fd1498Szrj   int stages;
603*38fd1498Szrj };
604*38fd1498Szrj 
605*38fd1498Szrj /* Helpers for delay hashing.  */
606*38fd1498Szrj 
607*38fd1498Szrj struct delay_i1_hasher : nofree_ptr_hash <delay_pair>
608*38fd1498Szrj {
609*38fd1498Szrj   typedef void *compare_type;
610*38fd1498Szrj   static inline hashval_t hash (const delay_pair *);
611*38fd1498Szrj   static inline bool equal (const delay_pair *, const void *);
612*38fd1498Szrj };
613*38fd1498Szrj 
614*38fd1498Szrj /* Returns a hash value for X, based on hashing just I1.  */
615*38fd1498Szrj 
616*38fd1498Szrj inline hashval_t
hash(const delay_pair * x)617*38fd1498Szrj delay_i1_hasher::hash (const delay_pair *x)
618*38fd1498Szrj {
619*38fd1498Szrj   return htab_hash_pointer (x->i1);
620*38fd1498Szrj }
621*38fd1498Szrj 
622*38fd1498Szrj /* Return true if I1 of pair X is the same as that of pair Y.  */
623*38fd1498Szrj 
624*38fd1498Szrj inline bool
equal(const delay_pair * x,const void * y)625*38fd1498Szrj delay_i1_hasher::equal (const delay_pair *x, const void *y)
626*38fd1498Szrj {
627*38fd1498Szrj   return x->i1 == y;
628*38fd1498Szrj }
629*38fd1498Szrj 
630*38fd1498Szrj struct delay_i2_hasher : free_ptr_hash <delay_pair>
631*38fd1498Szrj {
632*38fd1498Szrj   typedef void *compare_type;
633*38fd1498Szrj   static inline hashval_t hash (const delay_pair *);
634*38fd1498Szrj   static inline bool equal (const delay_pair *, const void *);
635*38fd1498Szrj };
636*38fd1498Szrj 
637*38fd1498Szrj /* Returns a hash value for X, based on hashing just I2.  */
638*38fd1498Szrj 
639*38fd1498Szrj inline hashval_t
hash(const delay_pair * x)640*38fd1498Szrj delay_i2_hasher::hash (const delay_pair *x)
641*38fd1498Szrj {
642*38fd1498Szrj   return htab_hash_pointer (x->i2);
643*38fd1498Szrj }
644*38fd1498Szrj 
645*38fd1498Szrj /* Return true if I2 of pair X is the same as that of pair Y.  */
646*38fd1498Szrj 
647*38fd1498Szrj inline bool
equal(const delay_pair * x,const void * y)648*38fd1498Szrj delay_i2_hasher::equal (const delay_pair *x, const void *y)
649*38fd1498Szrj {
650*38fd1498Szrj   return x->i2 == y;
651*38fd1498Szrj }
652*38fd1498Szrj 
653*38fd1498Szrj /* Two hash tables to record delay_pairs, one indexed by I1 and the other
654*38fd1498Szrj    indexed by I2.  */
655*38fd1498Szrj static hash_table<delay_i1_hasher> *delay_htab;
656*38fd1498Szrj static hash_table<delay_i2_hasher> *delay_htab_i2;
657*38fd1498Szrj 
658*38fd1498Szrj /* Called through htab_traverse.  Walk the hashtable using I2 as
659*38fd1498Szrj    index, and delete all elements involving an UID higher than
660*38fd1498Szrj    that pointed to by *DATA.  */
661*38fd1498Szrj int
haifa_htab_i2_traverse(delay_pair ** slot,int * data)662*38fd1498Szrj haifa_htab_i2_traverse (delay_pair **slot, int *data)
663*38fd1498Szrj {
664*38fd1498Szrj   int maxuid = *data;
665*38fd1498Szrj   struct delay_pair *p = *slot;
666*38fd1498Szrj   if (INSN_UID (p->i2) >= maxuid || INSN_UID (p->i1) >= maxuid)
667*38fd1498Szrj     {
668*38fd1498Szrj       delay_htab_i2->clear_slot (slot);
669*38fd1498Szrj     }
670*38fd1498Szrj   return 1;
671*38fd1498Szrj }
672*38fd1498Szrj 
673*38fd1498Szrj /* Called through htab_traverse.  Walk the hashtable using I2 as
674*38fd1498Szrj    index, and delete all elements involving an UID higher than
675*38fd1498Szrj    that pointed to by *DATA.  */
676*38fd1498Szrj int
haifa_htab_i1_traverse(delay_pair ** pslot,int * data)677*38fd1498Szrj haifa_htab_i1_traverse (delay_pair **pslot, int *data)
678*38fd1498Szrj {
679*38fd1498Szrj   int maxuid = *data;
680*38fd1498Szrj   struct delay_pair *p, *first, **pprev;
681*38fd1498Szrj 
682*38fd1498Szrj   if (INSN_UID ((*pslot)->i1) >= maxuid)
683*38fd1498Szrj     {
684*38fd1498Szrj       delay_htab->clear_slot (pslot);
685*38fd1498Szrj       return 1;
686*38fd1498Szrj     }
687*38fd1498Szrj   pprev = &first;
688*38fd1498Szrj   for (p = *pslot; p; p = p->next_same_i1)
689*38fd1498Szrj     {
690*38fd1498Szrj       if (INSN_UID (p->i2) < maxuid)
691*38fd1498Szrj 	{
692*38fd1498Szrj 	  *pprev = p;
693*38fd1498Szrj 	  pprev = &p->next_same_i1;
694*38fd1498Szrj 	}
695*38fd1498Szrj     }
696*38fd1498Szrj   *pprev = NULL;
697*38fd1498Szrj   if (first == NULL)
698*38fd1498Szrj     delay_htab->clear_slot (pslot);
699*38fd1498Szrj   else
700*38fd1498Szrj     *pslot = first;
701*38fd1498Szrj   return 1;
702*38fd1498Szrj }
703*38fd1498Szrj 
704*38fd1498Szrj /* Discard all delay pairs which involve an insn with an UID higher
705*38fd1498Szrj    than MAX_UID.  */
706*38fd1498Szrj void
discard_delay_pairs_above(int max_uid)707*38fd1498Szrj discard_delay_pairs_above (int max_uid)
708*38fd1498Szrj {
709*38fd1498Szrj   delay_htab->traverse <int *, haifa_htab_i1_traverse> (&max_uid);
710*38fd1498Szrj   delay_htab_i2->traverse <int *, haifa_htab_i2_traverse> (&max_uid);
711*38fd1498Szrj }
712*38fd1498Szrj 
713*38fd1498Szrj /* This function can be called by a port just before it starts the final
714*38fd1498Szrj    scheduling pass.  It records the fact that an instruction with delay
715*38fd1498Szrj    slots has been split into two insns, I1 and I2.  The first one will be
716*38fd1498Szrj    scheduled normally and initiates the operation.  The second one is a
717*38fd1498Szrj    shadow which must follow a specific number of cycles after I1; its only
718*38fd1498Szrj    purpose is to show the side effect that occurs at that cycle in the RTL.
719*38fd1498Szrj    If a JUMP_INSN or a CALL_INSN has been split, I1 should be a normal INSN,
720*38fd1498Szrj    while I2 retains the original insn type.
721*38fd1498Szrj 
722*38fd1498Szrj    There are two ways in which the number of cycles can be specified,
723*38fd1498Szrj    involving the CYCLES and STAGES arguments to this function.  If STAGES
724*38fd1498Szrj    is zero, we just use the value of CYCLES.  Otherwise, STAGES is a factor
725*38fd1498Szrj    which is multiplied by MODULO_II to give the number of cycles.  This is
726*38fd1498Szrj    only useful if the caller also calls set_modulo_params to enable modulo
727*38fd1498Szrj    scheduling.  */
728*38fd1498Szrj 
729*38fd1498Szrj void
record_delay_slot_pair(rtx_insn * i1,rtx_insn * i2,int cycles,int stages)730*38fd1498Szrj record_delay_slot_pair (rtx_insn *i1, rtx_insn *i2, int cycles, int stages)
731*38fd1498Szrj {
732*38fd1498Szrj   struct delay_pair *p = XNEW (struct delay_pair);
733*38fd1498Szrj   struct delay_pair **slot;
734*38fd1498Szrj 
735*38fd1498Szrj   p->i1 = i1;
736*38fd1498Szrj   p->i2 = i2;
737*38fd1498Szrj   p->cycles = cycles;
738*38fd1498Szrj   p->stages = stages;
739*38fd1498Szrj 
740*38fd1498Szrj   if (!delay_htab)
741*38fd1498Szrj     {
742*38fd1498Szrj       delay_htab = new hash_table<delay_i1_hasher> (10);
743*38fd1498Szrj       delay_htab_i2 = new hash_table<delay_i2_hasher> (10);
744*38fd1498Szrj     }
745*38fd1498Szrj   slot = delay_htab->find_slot_with_hash (i1, htab_hash_pointer (i1), INSERT);
746*38fd1498Szrj   p->next_same_i1 = *slot;
747*38fd1498Szrj   *slot = p;
748*38fd1498Szrj   slot = delay_htab_i2->find_slot (p, INSERT);
749*38fd1498Szrj   *slot = p;
750*38fd1498Szrj }
751*38fd1498Szrj 
752*38fd1498Szrj /* Examine the delay pair hashtable to see if INSN is a shadow for another,
753*38fd1498Szrj    and return the other insn if so.  Return NULL otherwise.  */
754*38fd1498Szrj rtx_insn *
real_insn_for_shadow(rtx_insn * insn)755*38fd1498Szrj real_insn_for_shadow (rtx_insn *insn)
756*38fd1498Szrj {
757*38fd1498Szrj   struct delay_pair *pair;
758*38fd1498Szrj 
759*38fd1498Szrj   if (!delay_htab)
760*38fd1498Szrj     return NULL;
761*38fd1498Szrj 
762*38fd1498Szrj   pair = delay_htab_i2->find_with_hash (insn, htab_hash_pointer (insn));
763*38fd1498Szrj   if (!pair || pair->stages > 0)
764*38fd1498Szrj     return NULL;
765*38fd1498Szrj   return pair->i1;
766*38fd1498Szrj }
767*38fd1498Szrj 
768*38fd1498Szrj /* For a pair P of insns, return the fixed distance in cycles from the first
769*38fd1498Szrj    insn after which the second must be scheduled.  */
770*38fd1498Szrj static int
pair_delay(struct delay_pair * p)771*38fd1498Szrj pair_delay (struct delay_pair *p)
772*38fd1498Szrj {
773*38fd1498Szrj   if (p->stages == 0)
774*38fd1498Szrj     return p->cycles;
775*38fd1498Szrj   else
776*38fd1498Szrj     return p->stages * modulo_ii;
777*38fd1498Szrj }
778*38fd1498Szrj 
779*38fd1498Szrj /* Given an insn INSN, add a dependence on its delayed shadow if it
780*38fd1498Szrj    has one.  Also try to find situations where shadows depend on each other
781*38fd1498Szrj    and add dependencies to the real insns to limit the amount of backtracking
782*38fd1498Szrj    needed.  */
783*38fd1498Szrj void
add_delay_dependencies(rtx_insn * insn)784*38fd1498Szrj add_delay_dependencies (rtx_insn *insn)
785*38fd1498Szrj {
786*38fd1498Szrj   struct delay_pair *pair;
787*38fd1498Szrj   sd_iterator_def sd_it;
788*38fd1498Szrj   dep_t dep;
789*38fd1498Szrj 
790*38fd1498Szrj   if (!delay_htab)
791*38fd1498Szrj     return;
792*38fd1498Szrj 
793*38fd1498Szrj   pair = delay_htab_i2->find_with_hash (insn, htab_hash_pointer (insn));
794*38fd1498Szrj   if (!pair)
795*38fd1498Szrj     return;
796*38fd1498Szrj   add_dependence (insn, pair->i1, REG_DEP_ANTI);
797*38fd1498Szrj   if (pair->stages)
798*38fd1498Szrj     return;
799*38fd1498Szrj 
800*38fd1498Szrj   FOR_EACH_DEP (pair->i2, SD_LIST_BACK, sd_it, dep)
801*38fd1498Szrj     {
802*38fd1498Szrj       rtx_insn *pro = DEP_PRO (dep);
803*38fd1498Szrj       struct delay_pair *other_pair
804*38fd1498Szrj 	= delay_htab_i2->find_with_hash (pro, htab_hash_pointer (pro));
805*38fd1498Szrj       if (!other_pair || other_pair->stages)
806*38fd1498Szrj 	continue;
807*38fd1498Szrj       if (pair_delay (other_pair) >= pair_delay (pair))
808*38fd1498Szrj 	{
809*38fd1498Szrj 	  if (sched_verbose >= 4)
810*38fd1498Szrj 	    {
811*38fd1498Szrj 	      fprintf (sched_dump, ";;\tadding dependence %d <- %d\n",
812*38fd1498Szrj 		       INSN_UID (other_pair->i1),
813*38fd1498Szrj 		       INSN_UID (pair->i1));
814*38fd1498Szrj 	      fprintf (sched_dump, ";;\tpair1 %d <- %d, cost %d\n",
815*38fd1498Szrj 		       INSN_UID (pair->i1),
816*38fd1498Szrj 		       INSN_UID (pair->i2),
817*38fd1498Szrj 		       pair_delay (pair));
818*38fd1498Szrj 	      fprintf (sched_dump, ";;\tpair2 %d <- %d, cost %d\n",
819*38fd1498Szrj 		       INSN_UID (other_pair->i1),
820*38fd1498Szrj 		       INSN_UID (other_pair->i2),
821*38fd1498Szrj 		       pair_delay (other_pair));
822*38fd1498Szrj 	    }
823*38fd1498Szrj 	  add_dependence (pair->i1, other_pair->i1, REG_DEP_ANTI);
824*38fd1498Szrj 	}
825*38fd1498Szrj     }
826*38fd1498Szrj }
827*38fd1498Szrj 
828*38fd1498Szrj /* Forward declarations.  */
829*38fd1498Szrj 
830*38fd1498Szrj static int priority (rtx_insn *);
831*38fd1498Szrj static int autopref_rank_for_schedule (const rtx_insn *, const rtx_insn *);
832*38fd1498Szrj static int rank_for_schedule (const void *, const void *);
833*38fd1498Szrj static void swap_sort (rtx_insn **, int);
834*38fd1498Szrj static void queue_insn (rtx_insn *, int, const char *);
835*38fd1498Szrj static int schedule_insn (rtx_insn *);
836*38fd1498Szrj static void adjust_priority (rtx_insn *);
837*38fd1498Szrj static void advance_one_cycle (void);
838*38fd1498Szrj static void extend_h_i_d (void);
839*38fd1498Szrj 
840*38fd1498Szrj 
841*38fd1498Szrj /* Notes handling mechanism:
842*38fd1498Szrj    =========================
843*38fd1498Szrj    Generally, NOTES are saved before scheduling and restored after scheduling.
844*38fd1498Szrj    The scheduler distinguishes between two types of notes:
845*38fd1498Szrj 
846*38fd1498Szrj    (1) LOOP_BEGIN, LOOP_END, SETJMP, EHREGION_BEG, EHREGION_END notes:
847*38fd1498Szrj    Before scheduling a region, a pointer to the note is added to the insn
848*38fd1498Szrj    that follows or precedes it.  (This happens as part of the data dependence
849*38fd1498Szrj    computation).  After scheduling an insn, the pointer contained in it is
850*38fd1498Szrj    used for regenerating the corresponding note (in reemit_notes).
851*38fd1498Szrj 
852*38fd1498Szrj    (2) All other notes (e.g. INSN_DELETED):  Before scheduling a block,
853*38fd1498Szrj    these notes are put in a list (in rm_other_notes() and
854*38fd1498Szrj    unlink_other_notes ()).  After scheduling the block, these notes are
855*38fd1498Szrj    inserted at the beginning of the block (in schedule_block()).  */
856*38fd1498Szrj 
857*38fd1498Szrj static void ready_add (struct ready_list *, rtx_insn *, bool);
858*38fd1498Szrj static rtx_insn *ready_remove_first (struct ready_list *);
859*38fd1498Szrj static rtx_insn *ready_remove_first_dispatch (struct ready_list *ready);
860*38fd1498Szrj 
861*38fd1498Szrj static void queue_to_ready (struct ready_list *);
862*38fd1498Szrj static int early_queue_to_ready (state_t, struct ready_list *);
863*38fd1498Szrj 
864*38fd1498Szrj /* The following functions are used to implement multi-pass scheduling
865*38fd1498Szrj    on the first cycle.  */
866*38fd1498Szrj static rtx_insn *ready_remove (struct ready_list *, int);
867*38fd1498Szrj static void ready_remove_insn (rtx_insn *);
868*38fd1498Szrj 
869*38fd1498Szrj static void fix_inter_tick (rtx_insn *, rtx_insn *);
870*38fd1498Szrj static int fix_tick_ready (rtx_insn *);
871*38fd1498Szrj static void change_queue_index (rtx_insn *, int);
872*38fd1498Szrj 
873*38fd1498Szrj /* The following functions are used to implement scheduling of data/control
874*38fd1498Szrj    speculative instructions.  */
875*38fd1498Szrj 
876*38fd1498Szrj static void extend_h_i_d (void);
877*38fd1498Szrj static void init_h_i_d (rtx_insn *);
878*38fd1498Szrj static int haifa_speculate_insn (rtx_insn *, ds_t, rtx *);
879*38fd1498Szrj static void generate_recovery_code (rtx_insn *);
880*38fd1498Szrj static void process_insn_forw_deps_be_in_spec (rtx_insn *, rtx_insn *, ds_t);
881*38fd1498Szrj static void begin_speculative_block (rtx_insn *);
882*38fd1498Szrj static void add_to_speculative_block (rtx_insn *);
883*38fd1498Szrj static void init_before_recovery (basic_block *);
884*38fd1498Szrj static void create_check_block_twin (rtx_insn *, bool);
885*38fd1498Szrj static void fix_recovery_deps (basic_block);
886*38fd1498Szrj static bool haifa_change_pattern (rtx_insn *, rtx);
887*38fd1498Szrj static void dump_new_block_header (int, basic_block, rtx_insn *, rtx_insn *);
888*38fd1498Szrj static void restore_bb_notes (basic_block);
889*38fd1498Szrj static void fix_jump_move (rtx_insn *);
890*38fd1498Szrj static void move_block_after_check (rtx_insn *);
891*38fd1498Szrj static void move_succs (vec<edge, va_gc> **, basic_block);
892*38fd1498Szrj static void sched_remove_insn (rtx_insn *);
893*38fd1498Szrj static void clear_priorities (rtx_insn *, rtx_vec_t *);
894*38fd1498Szrj static void calc_priorities (rtx_vec_t);
895*38fd1498Szrj static void add_jump_dependencies (rtx_insn *, rtx_insn *);
896*38fd1498Szrj 
897*38fd1498Szrj #endif /* INSN_SCHEDULING */
898*38fd1498Szrj 
899*38fd1498Szrj /* Point to state used for the current scheduling pass.  */
900*38fd1498Szrj struct haifa_sched_info *current_sched_info;
901*38fd1498Szrj 
902*38fd1498Szrj #ifndef INSN_SCHEDULING
903*38fd1498Szrj void
schedule_insns(void)904*38fd1498Szrj schedule_insns (void)
905*38fd1498Szrj {
906*38fd1498Szrj }
907*38fd1498Szrj #else
908*38fd1498Szrj 
909*38fd1498Szrj /* Do register pressure sensitive insn scheduling if the flag is set
910*38fd1498Szrj    up.  */
911*38fd1498Szrj enum sched_pressure_algorithm sched_pressure;
912*38fd1498Szrj 
913*38fd1498Szrj /* Map regno -> its pressure class.  The map defined only when
914*38fd1498Szrj    SCHED_PRESSURE != SCHED_PRESSURE_NONE.  */
915*38fd1498Szrj enum reg_class *sched_regno_pressure_class;
916*38fd1498Szrj 
917*38fd1498Szrj /* The current register pressure.  Only elements corresponding pressure
918*38fd1498Szrj    classes are defined.  */
919*38fd1498Szrj static int curr_reg_pressure[N_REG_CLASSES];
920*38fd1498Szrj 
921*38fd1498Szrj /* Saved value of the previous array.  */
922*38fd1498Szrj static int saved_reg_pressure[N_REG_CLASSES];
923*38fd1498Szrj 
924*38fd1498Szrj /* Register living at given scheduling point.  */
925*38fd1498Szrj static bitmap curr_reg_live;
926*38fd1498Szrj 
927*38fd1498Szrj /* Saved value of the previous array.  */
928*38fd1498Szrj static bitmap saved_reg_live;
929*38fd1498Szrj 
930*38fd1498Szrj /* Registers mentioned in the current region.  */
931*38fd1498Szrj static bitmap region_ref_regs;
932*38fd1498Szrj 
933*38fd1498Szrj /* Temporary bitmap used for SCHED_PRESSURE_MODEL.  */
934*38fd1498Szrj static bitmap tmp_bitmap;
935*38fd1498Szrj 
936*38fd1498Szrj /* Effective number of available registers of a given class (see comment
937*38fd1498Szrj    in sched_pressure_start_bb).  */
938*38fd1498Szrj static int sched_class_regs_num[N_REG_CLASSES];
939*38fd1498Szrj /* Number of call_saved_regs and fixed_regs.  Helpers for calculating of
940*38fd1498Szrj    sched_class_regs_num.  */
941*38fd1498Szrj static int call_saved_regs_num[N_REG_CLASSES];
942*38fd1498Szrj static int fixed_regs_num[N_REG_CLASSES];
943*38fd1498Szrj 
944*38fd1498Szrj /* Initiate register pressure relative info for scheduling the current
945*38fd1498Szrj    region.  Currently it is only clearing register mentioned in the
946*38fd1498Szrj    current region.  */
947*38fd1498Szrj void
sched_init_region_reg_pressure_info(void)948*38fd1498Szrj sched_init_region_reg_pressure_info (void)
949*38fd1498Szrj {
950*38fd1498Szrj   bitmap_clear (region_ref_regs);
951*38fd1498Szrj }
952*38fd1498Szrj 
953*38fd1498Szrj /* PRESSURE[CL] describes the pressure on register class CL.  Update it
954*38fd1498Szrj    for the birth (if BIRTH_P) or death (if !BIRTH_P) of register REGNO.
955*38fd1498Szrj    LIVE tracks the set of live registers; if it is null, assume that
956*38fd1498Szrj    every birth or death is genuine.  */
957*38fd1498Szrj static inline void
mark_regno_birth_or_death(bitmap live,int * pressure,int regno,bool birth_p)958*38fd1498Szrj mark_regno_birth_or_death (bitmap live, int *pressure, int regno, bool birth_p)
959*38fd1498Szrj {
960*38fd1498Szrj   enum reg_class pressure_class;
961*38fd1498Szrj 
962*38fd1498Szrj   pressure_class = sched_regno_pressure_class[regno];
963*38fd1498Szrj   if (regno >= FIRST_PSEUDO_REGISTER)
964*38fd1498Szrj     {
965*38fd1498Szrj       if (pressure_class != NO_REGS)
966*38fd1498Szrj 	{
967*38fd1498Szrj 	  if (birth_p)
968*38fd1498Szrj 	    {
969*38fd1498Szrj 	      if (!live || bitmap_set_bit (live, regno))
970*38fd1498Szrj 		pressure[pressure_class]
971*38fd1498Szrj 		  += (ira_reg_class_max_nregs
972*38fd1498Szrj 		      [pressure_class][PSEUDO_REGNO_MODE (regno)]);
973*38fd1498Szrj 	    }
974*38fd1498Szrj 	  else
975*38fd1498Szrj 	    {
976*38fd1498Szrj 	      if (!live || bitmap_clear_bit (live, regno))
977*38fd1498Szrj 		pressure[pressure_class]
978*38fd1498Szrj 		  -= (ira_reg_class_max_nregs
979*38fd1498Szrj 		      [pressure_class][PSEUDO_REGNO_MODE (regno)]);
980*38fd1498Szrj 	    }
981*38fd1498Szrj 	}
982*38fd1498Szrj     }
983*38fd1498Szrj   else if (pressure_class != NO_REGS
984*38fd1498Szrj 	   && ! TEST_HARD_REG_BIT (ira_no_alloc_regs, regno))
985*38fd1498Szrj     {
986*38fd1498Szrj       if (birth_p)
987*38fd1498Szrj 	{
988*38fd1498Szrj 	  if (!live || bitmap_set_bit (live, regno))
989*38fd1498Szrj 	    pressure[pressure_class]++;
990*38fd1498Szrj 	}
991*38fd1498Szrj       else
992*38fd1498Szrj 	{
993*38fd1498Szrj 	  if (!live || bitmap_clear_bit (live, regno))
994*38fd1498Szrj 	    pressure[pressure_class]--;
995*38fd1498Szrj 	}
996*38fd1498Szrj     }
997*38fd1498Szrj }
998*38fd1498Szrj 
999*38fd1498Szrj /* Initiate current register pressure related info from living
1000*38fd1498Szrj    registers given by LIVE.  */
1001*38fd1498Szrj static void
initiate_reg_pressure_info(bitmap live)1002*38fd1498Szrj initiate_reg_pressure_info (bitmap live)
1003*38fd1498Szrj {
1004*38fd1498Szrj   int i;
1005*38fd1498Szrj   unsigned int j;
1006*38fd1498Szrj   bitmap_iterator bi;
1007*38fd1498Szrj 
1008*38fd1498Szrj   for (i = 0; i < ira_pressure_classes_num; i++)
1009*38fd1498Szrj     curr_reg_pressure[ira_pressure_classes[i]] = 0;
1010*38fd1498Szrj   bitmap_clear (curr_reg_live);
1011*38fd1498Szrj   EXECUTE_IF_SET_IN_BITMAP (live, 0, j, bi)
1012*38fd1498Szrj     if (sched_pressure == SCHED_PRESSURE_MODEL
1013*38fd1498Szrj 	|| current_nr_blocks == 1
1014*38fd1498Szrj 	|| bitmap_bit_p (region_ref_regs, j))
1015*38fd1498Szrj       mark_regno_birth_or_death (curr_reg_live, curr_reg_pressure, j, true);
1016*38fd1498Szrj }
1017*38fd1498Szrj 
1018*38fd1498Szrj /* Mark registers in X as mentioned in the current region.  */
1019*38fd1498Szrj static void
setup_ref_regs(rtx x)1020*38fd1498Szrj setup_ref_regs (rtx x)
1021*38fd1498Szrj {
1022*38fd1498Szrj   int i, j;
1023*38fd1498Szrj   const RTX_CODE code = GET_CODE (x);
1024*38fd1498Szrj   const char *fmt;
1025*38fd1498Szrj 
1026*38fd1498Szrj   if (REG_P (x))
1027*38fd1498Szrj     {
1028*38fd1498Szrj       bitmap_set_range (region_ref_regs, REGNO (x), REG_NREGS (x));
1029*38fd1498Szrj       return;
1030*38fd1498Szrj     }
1031*38fd1498Szrj   fmt = GET_RTX_FORMAT (code);
1032*38fd1498Szrj   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
1033*38fd1498Szrj     if (fmt[i] == 'e')
1034*38fd1498Szrj       setup_ref_regs (XEXP (x, i));
1035*38fd1498Szrj     else if (fmt[i] == 'E')
1036*38fd1498Szrj       {
1037*38fd1498Szrj 	for (j = 0; j < XVECLEN (x, i); j++)
1038*38fd1498Szrj 	  setup_ref_regs (XVECEXP (x, i, j));
1039*38fd1498Szrj       }
1040*38fd1498Szrj }
1041*38fd1498Szrj 
1042*38fd1498Szrj /* Initiate current register pressure related info at the start of
1043*38fd1498Szrj    basic block BB.  */
1044*38fd1498Szrj static void
initiate_bb_reg_pressure_info(basic_block bb)1045*38fd1498Szrj initiate_bb_reg_pressure_info (basic_block bb)
1046*38fd1498Szrj {
1047*38fd1498Szrj   unsigned int i ATTRIBUTE_UNUSED;
1048*38fd1498Szrj   rtx_insn *insn;
1049*38fd1498Szrj 
1050*38fd1498Szrj   if (current_nr_blocks > 1)
1051*38fd1498Szrj     FOR_BB_INSNS (bb, insn)
1052*38fd1498Szrj       if (NONDEBUG_INSN_P (insn))
1053*38fd1498Szrj 	setup_ref_regs (PATTERN (insn));
1054*38fd1498Szrj   initiate_reg_pressure_info (df_get_live_in (bb));
1055*38fd1498Szrj   if (bb_has_eh_pred (bb))
1056*38fd1498Szrj     for (i = 0; ; ++i)
1057*38fd1498Szrj       {
1058*38fd1498Szrj 	unsigned int regno = EH_RETURN_DATA_REGNO (i);
1059*38fd1498Szrj 
1060*38fd1498Szrj 	if (regno == INVALID_REGNUM)
1061*38fd1498Szrj 	  break;
1062*38fd1498Szrj 	if (! bitmap_bit_p (df_get_live_in (bb), regno))
1063*38fd1498Szrj 	  mark_regno_birth_or_death (curr_reg_live, curr_reg_pressure,
1064*38fd1498Szrj 				     regno, true);
1065*38fd1498Szrj       }
1066*38fd1498Szrj }
1067*38fd1498Szrj 
1068*38fd1498Szrj /* Save current register pressure related info.  */
1069*38fd1498Szrj static void
save_reg_pressure(void)1070*38fd1498Szrj save_reg_pressure (void)
1071*38fd1498Szrj {
1072*38fd1498Szrj   int i;
1073*38fd1498Szrj 
1074*38fd1498Szrj   for (i = 0; i < ira_pressure_classes_num; i++)
1075*38fd1498Szrj     saved_reg_pressure[ira_pressure_classes[i]]
1076*38fd1498Szrj       = curr_reg_pressure[ira_pressure_classes[i]];
1077*38fd1498Szrj   bitmap_copy (saved_reg_live, curr_reg_live);
1078*38fd1498Szrj }
1079*38fd1498Szrj 
1080*38fd1498Szrj /* Restore saved register pressure related info.  */
1081*38fd1498Szrj static void
restore_reg_pressure(void)1082*38fd1498Szrj restore_reg_pressure (void)
1083*38fd1498Szrj {
1084*38fd1498Szrj   int i;
1085*38fd1498Szrj 
1086*38fd1498Szrj   for (i = 0; i < ira_pressure_classes_num; i++)
1087*38fd1498Szrj     curr_reg_pressure[ira_pressure_classes[i]]
1088*38fd1498Szrj       = saved_reg_pressure[ira_pressure_classes[i]];
1089*38fd1498Szrj   bitmap_copy (curr_reg_live, saved_reg_live);
1090*38fd1498Szrj }
1091*38fd1498Szrj 
1092*38fd1498Szrj /* Return TRUE if the register is dying after its USE.  */
1093*38fd1498Szrj static bool
dying_use_p(struct reg_use_data * use)1094*38fd1498Szrj dying_use_p (struct reg_use_data *use)
1095*38fd1498Szrj {
1096*38fd1498Szrj   struct reg_use_data *next;
1097*38fd1498Szrj 
1098*38fd1498Szrj   for (next = use->next_regno_use; next != use; next = next->next_regno_use)
1099*38fd1498Szrj     if (NONDEBUG_INSN_P (next->insn)
1100*38fd1498Szrj 	&& QUEUE_INDEX (next->insn) != QUEUE_SCHEDULED)
1101*38fd1498Szrj       return false;
1102*38fd1498Szrj   return true;
1103*38fd1498Szrj }
1104*38fd1498Szrj 
1105*38fd1498Szrj /* Print info about the current register pressure and its excess for
1106*38fd1498Szrj    each pressure class.  */
1107*38fd1498Szrj static void
print_curr_reg_pressure(void)1108*38fd1498Szrj print_curr_reg_pressure (void)
1109*38fd1498Szrj {
1110*38fd1498Szrj   int i;
1111*38fd1498Szrj   enum reg_class cl;
1112*38fd1498Szrj 
1113*38fd1498Szrj   fprintf (sched_dump, ";;\t");
1114*38fd1498Szrj   for (i = 0; i < ira_pressure_classes_num; i++)
1115*38fd1498Szrj     {
1116*38fd1498Szrj       cl = ira_pressure_classes[i];
1117*38fd1498Szrj       gcc_assert (curr_reg_pressure[cl] >= 0);
1118*38fd1498Szrj       fprintf (sched_dump, "  %s:%d(%d)", reg_class_names[cl],
1119*38fd1498Szrj 	       curr_reg_pressure[cl],
1120*38fd1498Szrj 	       curr_reg_pressure[cl] - sched_class_regs_num[cl]);
1121*38fd1498Szrj     }
1122*38fd1498Szrj   fprintf (sched_dump, "\n");
1123*38fd1498Szrj }
1124*38fd1498Szrj 
1125*38fd1498Szrj /* Determine if INSN has a condition that is clobbered if a register
1126*38fd1498Szrj    in SET_REGS is modified.  */
1127*38fd1498Szrj static bool
cond_clobbered_p(rtx_insn * insn,HARD_REG_SET set_regs)1128*38fd1498Szrj cond_clobbered_p (rtx_insn *insn, HARD_REG_SET set_regs)
1129*38fd1498Szrj {
1130*38fd1498Szrj   rtx pat = PATTERN (insn);
1131*38fd1498Szrj   gcc_assert (GET_CODE (pat) == COND_EXEC);
1132*38fd1498Szrj   if (TEST_HARD_REG_BIT (set_regs, REGNO (XEXP (COND_EXEC_TEST (pat), 0))))
1133*38fd1498Szrj     {
1134*38fd1498Szrj       sd_iterator_def sd_it;
1135*38fd1498Szrj       dep_t dep;
1136*38fd1498Szrj       haifa_change_pattern (insn, ORIG_PAT (insn));
1137*38fd1498Szrj       FOR_EACH_DEP (insn, SD_LIST_BACK, sd_it, dep)
1138*38fd1498Szrj 	DEP_STATUS (dep) &= ~DEP_CANCELLED;
1139*38fd1498Szrj       TODO_SPEC (insn) = HARD_DEP;
1140*38fd1498Szrj       if (sched_verbose >= 2)
1141*38fd1498Szrj 	fprintf (sched_dump,
1142*38fd1498Szrj 		 ";;\t\tdequeue insn %s because of clobbered condition\n",
1143*38fd1498Szrj 		 (*current_sched_info->print_insn) (insn, 0));
1144*38fd1498Szrj       return true;
1145*38fd1498Szrj     }
1146*38fd1498Szrj 
1147*38fd1498Szrj   return false;
1148*38fd1498Szrj }
1149*38fd1498Szrj 
1150*38fd1498Szrj /* This function should be called after modifying the pattern of INSN,
1151*38fd1498Szrj    to update scheduler data structures as needed.  */
1152*38fd1498Szrj static void
update_insn_after_change(rtx_insn * insn)1153*38fd1498Szrj update_insn_after_change (rtx_insn *insn)
1154*38fd1498Szrj {
1155*38fd1498Szrj   sd_iterator_def sd_it;
1156*38fd1498Szrj   dep_t dep;
1157*38fd1498Szrj 
1158*38fd1498Szrj   dfa_clear_single_insn_cache (insn);
1159*38fd1498Szrj 
1160*38fd1498Szrj   sd_it = sd_iterator_start (insn,
1161*38fd1498Szrj 			     SD_LIST_FORW | SD_LIST_BACK | SD_LIST_RES_BACK);
1162*38fd1498Szrj   while (sd_iterator_cond (&sd_it, &dep))
1163*38fd1498Szrj     {
1164*38fd1498Szrj       DEP_COST (dep) = UNKNOWN_DEP_COST;
1165*38fd1498Szrj       sd_iterator_next (&sd_it);
1166*38fd1498Szrj     }
1167*38fd1498Szrj 
1168*38fd1498Szrj   /* Invalidate INSN_COST, so it'll be recalculated.  */
1169*38fd1498Szrj   INSN_COST (insn) = -1;
1170*38fd1498Szrj   /* Invalidate INSN_TICK, so it'll be recalculated.  */
1171*38fd1498Szrj   INSN_TICK (insn) = INVALID_TICK;
1172*38fd1498Szrj 
1173*38fd1498Szrj   /* Invalidate autoprefetch data entry.  */
1174*38fd1498Szrj   INSN_AUTOPREF_MULTIPASS_DATA (insn)[0].status
1175*38fd1498Szrj     = AUTOPREF_MULTIPASS_DATA_UNINITIALIZED;
1176*38fd1498Szrj   INSN_AUTOPREF_MULTIPASS_DATA (insn)[1].status
1177*38fd1498Szrj     = AUTOPREF_MULTIPASS_DATA_UNINITIALIZED;
1178*38fd1498Szrj }
1179*38fd1498Szrj 
1180*38fd1498Szrj 
1181*38fd1498Szrj /* Two VECs, one to hold dependencies for which pattern replacements
1182*38fd1498Szrj    need to be applied or restored at the start of the next cycle, and
1183*38fd1498Szrj    another to hold an integer that is either one, to apply the
1184*38fd1498Szrj    corresponding replacement, or zero to restore it.  */
1185*38fd1498Szrj static vec<dep_t> next_cycle_replace_deps;
1186*38fd1498Szrj static vec<int> next_cycle_apply;
1187*38fd1498Szrj 
1188*38fd1498Szrj static void apply_replacement (dep_t, bool);
1189*38fd1498Szrj static void restore_pattern (dep_t, bool);
1190*38fd1498Szrj 
1191*38fd1498Szrj /* Look at the remaining dependencies for insn NEXT, and compute and return
1192*38fd1498Szrj    the TODO_SPEC value we should use for it.  This is called after one of
1193*38fd1498Szrj    NEXT's dependencies has been resolved.
1194*38fd1498Szrj    We also perform pattern replacements for predication, and for broken
1195*38fd1498Szrj    replacement dependencies.  The latter is only done if FOR_BACKTRACK is
1196*38fd1498Szrj    false.  */
1197*38fd1498Szrj 
1198*38fd1498Szrj static ds_t
recompute_todo_spec(rtx_insn * next,bool for_backtrack)1199*38fd1498Szrj recompute_todo_spec (rtx_insn *next, bool for_backtrack)
1200*38fd1498Szrj {
1201*38fd1498Szrj   ds_t new_ds;
1202*38fd1498Szrj   sd_iterator_def sd_it;
1203*38fd1498Szrj   dep_t dep, modify_dep = NULL;
1204*38fd1498Szrj   int n_spec = 0;
1205*38fd1498Szrj   int n_control = 0;
1206*38fd1498Szrj   int n_replace = 0;
1207*38fd1498Szrj   bool first_p = true;
1208*38fd1498Szrj 
1209*38fd1498Szrj   if (sd_lists_empty_p (next, SD_LIST_BACK))
1210*38fd1498Szrj     /* NEXT has all its dependencies resolved.  */
1211*38fd1498Szrj     return 0;
1212*38fd1498Szrj 
1213*38fd1498Szrj   if (!sd_lists_empty_p (next, SD_LIST_HARD_BACK))
1214*38fd1498Szrj     return HARD_DEP;
1215*38fd1498Szrj 
1216*38fd1498Szrj   /* If NEXT is intended to sit adjacent to this instruction, we don't
1217*38fd1498Szrj      want to try to break any dependencies.  Treat it as a HARD_DEP.  */
1218*38fd1498Szrj   if (SCHED_GROUP_P (next))
1219*38fd1498Szrj     return HARD_DEP;
1220*38fd1498Szrj 
1221*38fd1498Szrj   /* Now we've got NEXT with speculative deps only.
1222*38fd1498Szrj      1. Look at the deps to see what we have to do.
1223*38fd1498Szrj      2. Check if we can do 'todo'.  */
1224*38fd1498Szrj   new_ds = 0;
1225*38fd1498Szrj 
1226*38fd1498Szrj   FOR_EACH_DEP (next, SD_LIST_BACK, sd_it, dep)
1227*38fd1498Szrj     {
1228*38fd1498Szrj       rtx_insn *pro = DEP_PRO (dep);
1229*38fd1498Szrj       ds_t ds = DEP_STATUS (dep) & SPECULATIVE;
1230*38fd1498Szrj 
1231*38fd1498Szrj       if (DEBUG_INSN_P (pro) && !DEBUG_INSN_P (next))
1232*38fd1498Szrj 	continue;
1233*38fd1498Szrj 
1234*38fd1498Szrj       if (ds)
1235*38fd1498Szrj 	{
1236*38fd1498Szrj 	  n_spec++;
1237*38fd1498Szrj 	  if (first_p)
1238*38fd1498Szrj 	    {
1239*38fd1498Szrj 	      first_p = false;
1240*38fd1498Szrj 
1241*38fd1498Szrj 	      new_ds = ds;
1242*38fd1498Szrj 	    }
1243*38fd1498Szrj 	  else
1244*38fd1498Szrj 	    new_ds = ds_merge (new_ds, ds);
1245*38fd1498Szrj 	}
1246*38fd1498Szrj       else if (DEP_TYPE (dep) == REG_DEP_CONTROL)
1247*38fd1498Szrj 	{
1248*38fd1498Szrj 	  if (QUEUE_INDEX (pro) != QUEUE_SCHEDULED)
1249*38fd1498Szrj 	    {
1250*38fd1498Szrj 	      n_control++;
1251*38fd1498Szrj 	      modify_dep = dep;
1252*38fd1498Szrj 	    }
1253*38fd1498Szrj 	  DEP_STATUS (dep) &= ~DEP_CANCELLED;
1254*38fd1498Szrj 	}
1255*38fd1498Szrj       else if (DEP_REPLACE (dep) != NULL)
1256*38fd1498Szrj 	{
1257*38fd1498Szrj 	  if (QUEUE_INDEX (pro) != QUEUE_SCHEDULED)
1258*38fd1498Szrj 	    {
1259*38fd1498Szrj 	      n_replace++;
1260*38fd1498Szrj 	      modify_dep = dep;
1261*38fd1498Szrj 	    }
1262*38fd1498Szrj 	  DEP_STATUS (dep) &= ~DEP_CANCELLED;
1263*38fd1498Szrj 	}
1264*38fd1498Szrj     }
1265*38fd1498Szrj 
1266*38fd1498Szrj   if (n_replace > 0 && n_control == 0 && n_spec == 0)
1267*38fd1498Szrj     {
1268*38fd1498Szrj       if (!dbg_cnt (sched_breakdep))
1269*38fd1498Szrj 	return HARD_DEP;
1270*38fd1498Szrj       FOR_EACH_DEP (next, SD_LIST_BACK, sd_it, dep)
1271*38fd1498Szrj 	{
1272*38fd1498Szrj 	  struct dep_replacement *desc = DEP_REPLACE (dep);
1273*38fd1498Szrj 	  if (desc != NULL)
1274*38fd1498Szrj 	    {
1275*38fd1498Szrj 	      if (desc->insn == next && !for_backtrack)
1276*38fd1498Szrj 		{
1277*38fd1498Szrj 		  gcc_assert (n_replace == 1);
1278*38fd1498Szrj 		  apply_replacement (dep, true);
1279*38fd1498Szrj 		}
1280*38fd1498Szrj 	      DEP_STATUS (dep) |= DEP_CANCELLED;
1281*38fd1498Szrj 	    }
1282*38fd1498Szrj 	}
1283*38fd1498Szrj       return 0;
1284*38fd1498Szrj     }
1285*38fd1498Szrj 
1286*38fd1498Szrj   else if (n_control == 1 && n_replace == 0 && n_spec == 0)
1287*38fd1498Szrj     {
1288*38fd1498Szrj       rtx_insn *pro, *other;
1289*38fd1498Szrj       rtx new_pat;
1290*38fd1498Szrj       rtx cond = NULL_RTX;
1291*38fd1498Szrj       bool success;
1292*38fd1498Szrj       rtx_insn *prev = NULL;
1293*38fd1498Szrj       int i;
1294*38fd1498Szrj       unsigned regno;
1295*38fd1498Szrj 
1296*38fd1498Szrj       if ((current_sched_info->flags & DO_PREDICATION) == 0
1297*38fd1498Szrj 	  || (ORIG_PAT (next) != NULL_RTX
1298*38fd1498Szrj 	      && PREDICATED_PAT (next) == NULL_RTX))
1299*38fd1498Szrj 	return HARD_DEP;
1300*38fd1498Szrj 
1301*38fd1498Szrj       pro = DEP_PRO (modify_dep);
1302*38fd1498Szrj       other = real_insn_for_shadow (pro);
1303*38fd1498Szrj       if (other != NULL_RTX)
1304*38fd1498Szrj 	pro = other;
1305*38fd1498Szrj 
1306*38fd1498Szrj       cond = sched_get_reverse_condition_uncached (pro);
1307*38fd1498Szrj       regno = REGNO (XEXP (cond, 0));
1308*38fd1498Szrj 
1309*38fd1498Szrj       /* Find the last scheduled insn that modifies the condition register.
1310*38fd1498Szrj 	 We can stop looking once we find the insn we depend on through the
1311*38fd1498Szrj 	 REG_DEP_CONTROL; if the condition register isn't modified after it,
1312*38fd1498Szrj 	 we know that it still has the right value.  */
1313*38fd1498Szrj       if (QUEUE_INDEX (pro) == QUEUE_SCHEDULED)
1314*38fd1498Szrj 	FOR_EACH_VEC_ELT_REVERSE (scheduled_insns, i, prev)
1315*38fd1498Szrj 	  {
1316*38fd1498Szrj 	    HARD_REG_SET t;
1317*38fd1498Szrj 
1318*38fd1498Szrj 	    find_all_hard_reg_sets (prev, &t, true);
1319*38fd1498Szrj 	    if (TEST_HARD_REG_BIT (t, regno))
1320*38fd1498Szrj 	      return HARD_DEP;
1321*38fd1498Szrj 	    if (prev == pro)
1322*38fd1498Szrj 	      break;
1323*38fd1498Szrj 	  }
1324*38fd1498Szrj       if (ORIG_PAT (next) == NULL_RTX)
1325*38fd1498Szrj 	{
1326*38fd1498Szrj 	  ORIG_PAT (next) = PATTERN (next);
1327*38fd1498Szrj 
1328*38fd1498Szrj 	  new_pat = gen_rtx_COND_EXEC (VOIDmode, cond, PATTERN (next));
1329*38fd1498Szrj 	  success = haifa_change_pattern (next, new_pat);
1330*38fd1498Szrj 	  if (!success)
1331*38fd1498Szrj 	    return HARD_DEP;
1332*38fd1498Szrj 	  PREDICATED_PAT (next) = new_pat;
1333*38fd1498Szrj 	}
1334*38fd1498Szrj       else if (PATTERN (next) != PREDICATED_PAT (next))
1335*38fd1498Szrj 	{
1336*38fd1498Szrj 	  bool success = haifa_change_pattern (next,
1337*38fd1498Szrj 					       PREDICATED_PAT (next));
1338*38fd1498Szrj 	  gcc_assert (success);
1339*38fd1498Szrj 	}
1340*38fd1498Szrj       DEP_STATUS (modify_dep) |= DEP_CANCELLED;
1341*38fd1498Szrj       return DEP_CONTROL;
1342*38fd1498Szrj     }
1343*38fd1498Szrj 
1344*38fd1498Szrj   if (PREDICATED_PAT (next) != NULL_RTX)
1345*38fd1498Szrj     {
1346*38fd1498Szrj       int tick = INSN_TICK (next);
1347*38fd1498Szrj       bool success = haifa_change_pattern (next,
1348*38fd1498Szrj 					   ORIG_PAT (next));
1349*38fd1498Szrj       INSN_TICK (next) = tick;
1350*38fd1498Szrj       gcc_assert (success);
1351*38fd1498Szrj     }
1352*38fd1498Szrj 
1353*38fd1498Szrj   /* We can't handle the case where there are both speculative and control
1354*38fd1498Szrj      dependencies, so we return HARD_DEP in such a case.  Also fail if
1355*38fd1498Szrj      we have speculative dependencies with not enough points, or more than
1356*38fd1498Szrj      one control dependency.  */
1357*38fd1498Szrj   if ((n_spec > 0 && (n_control > 0 || n_replace > 0))
1358*38fd1498Szrj       || (n_spec > 0
1359*38fd1498Szrj 	  /* Too few points?  */
1360*38fd1498Szrj 	  && ds_weak (new_ds) < spec_info->data_weakness_cutoff)
1361*38fd1498Szrj       || n_control > 0
1362*38fd1498Szrj       || n_replace > 0)
1363*38fd1498Szrj     return HARD_DEP;
1364*38fd1498Szrj 
1365*38fd1498Szrj   return new_ds;
1366*38fd1498Szrj }
1367*38fd1498Szrj 
1368*38fd1498Szrj /* Pointer to the last instruction scheduled.  */
1369*38fd1498Szrj static rtx_insn *last_scheduled_insn;
1370*38fd1498Szrj 
1371*38fd1498Szrj /* Pointer to the last nondebug instruction scheduled within the
1372*38fd1498Szrj    block, or the prev_head of the scheduling block.  Used by
1373*38fd1498Szrj    rank_for_schedule, so that insns independent of the last scheduled
1374*38fd1498Szrj    insn will be preferred over dependent instructions.  */
1375*38fd1498Szrj static rtx_insn *last_nondebug_scheduled_insn;
1376*38fd1498Szrj 
1377*38fd1498Szrj /* Pointer that iterates through the list of unscheduled insns if we
1378*38fd1498Szrj    have a dbg_cnt enabled.  It always points at an insn prior to the
1379*38fd1498Szrj    first unscheduled one.  */
1380*38fd1498Szrj static rtx_insn *nonscheduled_insns_begin;
1381*38fd1498Szrj 
1382*38fd1498Szrj /* Compute cost of executing INSN.
1383*38fd1498Szrj    This is the number of cycles between instruction issue and
1384*38fd1498Szrj    instruction results.  */
1385*38fd1498Szrj int
insn_sched_cost(rtx_insn * insn)1386*38fd1498Szrj insn_sched_cost (rtx_insn *insn)
1387*38fd1498Szrj {
1388*38fd1498Szrj   int cost;
1389*38fd1498Szrj 
1390*38fd1498Szrj   if (sched_fusion)
1391*38fd1498Szrj     return 0;
1392*38fd1498Szrj 
1393*38fd1498Szrj   if (sel_sched_p ())
1394*38fd1498Szrj     {
1395*38fd1498Szrj       if (recog_memoized (insn) < 0)
1396*38fd1498Szrj 	return 0;
1397*38fd1498Szrj 
1398*38fd1498Szrj       cost = insn_default_latency (insn);
1399*38fd1498Szrj       if (cost < 0)
1400*38fd1498Szrj 	cost = 0;
1401*38fd1498Szrj 
1402*38fd1498Szrj       return cost;
1403*38fd1498Szrj     }
1404*38fd1498Szrj 
1405*38fd1498Szrj   cost = INSN_COST (insn);
1406*38fd1498Szrj 
1407*38fd1498Szrj   if (cost < 0)
1408*38fd1498Szrj     {
1409*38fd1498Szrj       /* A USE insn, or something else we don't need to
1410*38fd1498Szrj 	 understand.  We can't pass these directly to
1411*38fd1498Szrj 	 result_ready_cost or insn_default_latency because it will
1412*38fd1498Szrj 	 trigger a fatal error for unrecognizable insns.  */
1413*38fd1498Szrj       if (recog_memoized (insn) < 0)
1414*38fd1498Szrj 	{
1415*38fd1498Szrj 	  INSN_COST (insn) = 0;
1416*38fd1498Szrj 	  return 0;
1417*38fd1498Szrj 	}
1418*38fd1498Szrj       else
1419*38fd1498Szrj 	{
1420*38fd1498Szrj 	  cost = insn_default_latency (insn);
1421*38fd1498Szrj 	  if (cost < 0)
1422*38fd1498Szrj 	    cost = 0;
1423*38fd1498Szrj 
1424*38fd1498Szrj 	  INSN_COST (insn) = cost;
1425*38fd1498Szrj 	}
1426*38fd1498Szrj     }
1427*38fd1498Szrj 
1428*38fd1498Szrj   return cost;
1429*38fd1498Szrj }
1430*38fd1498Szrj 
1431*38fd1498Szrj /* Compute cost of dependence LINK.
1432*38fd1498Szrj    This is the number of cycles between instruction issue and
1433*38fd1498Szrj    instruction results.
1434*38fd1498Szrj    ??? We also use this function to call recog_memoized on all insns.  */
1435*38fd1498Szrj int
dep_cost_1(dep_t link,dw_t dw)1436*38fd1498Szrj dep_cost_1 (dep_t link, dw_t dw)
1437*38fd1498Szrj {
1438*38fd1498Szrj   rtx_insn *insn = DEP_PRO (link);
1439*38fd1498Szrj   rtx_insn *used = DEP_CON (link);
1440*38fd1498Szrj   int cost;
1441*38fd1498Szrj 
1442*38fd1498Szrj   if (DEP_COST (link) != UNKNOWN_DEP_COST)
1443*38fd1498Szrj     return DEP_COST (link);
1444*38fd1498Szrj 
1445*38fd1498Szrj   if (delay_htab)
1446*38fd1498Szrj     {
1447*38fd1498Szrj       struct delay_pair *delay_entry;
1448*38fd1498Szrj       delay_entry
1449*38fd1498Szrj 	= delay_htab_i2->find_with_hash (used, htab_hash_pointer (used));
1450*38fd1498Szrj       if (delay_entry)
1451*38fd1498Szrj 	{
1452*38fd1498Szrj 	  if (delay_entry->i1 == insn)
1453*38fd1498Szrj 	    {
1454*38fd1498Szrj 	      DEP_COST (link) = pair_delay (delay_entry);
1455*38fd1498Szrj 	      return DEP_COST (link);
1456*38fd1498Szrj 	    }
1457*38fd1498Szrj 	}
1458*38fd1498Szrj     }
1459*38fd1498Szrj 
1460*38fd1498Szrj   /* A USE insn should never require the value used to be computed.
1461*38fd1498Szrj      This allows the computation of a function's result and parameter
1462*38fd1498Szrj      values to overlap the return and call.  We don't care about the
1463*38fd1498Szrj      dependence cost when only decreasing register pressure.  */
1464*38fd1498Szrj   if (recog_memoized (used) < 0)
1465*38fd1498Szrj     {
1466*38fd1498Szrj       cost = 0;
1467*38fd1498Szrj       recog_memoized (insn);
1468*38fd1498Szrj     }
1469*38fd1498Szrj   else
1470*38fd1498Szrj     {
1471*38fd1498Szrj       enum reg_note dep_type = DEP_TYPE (link);
1472*38fd1498Szrj 
1473*38fd1498Szrj       cost = insn_sched_cost (insn);
1474*38fd1498Szrj 
1475*38fd1498Szrj       if (INSN_CODE (insn) >= 0)
1476*38fd1498Szrj 	{
1477*38fd1498Szrj 	  if (dep_type == REG_DEP_ANTI)
1478*38fd1498Szrj 	    cost = 0;
1479*38fd1498Szrj 	  else if (dep_type == REG_DEP_OUTPUT)
1480*38fd1498Szrj 	    {
1481*38fd1498Szrj 	      cost = (insn_default_latency (insn)
1482*38fd1498Szrj 		      - insn_default_latency (used));
1483*38fd1498Szrj 	      if (cost <= 0)
1484*38fd1498Szrj 		cost = 1;
1485*38fd1498Szrj 	    }
1486*38fd1498Szrj 	  else if (bypass_p (insn))
1487*38fd1498Szrj 	    cost = insn_latency (insn, used);
1488*38fd1498Szrj 	}
1489*38fd1498Szrj 
1490*38fd1498Szrj 
1491*38fd1498Szrj       if (targetm.sched.adjust_cost)
1492*38fd1498Szrj 	cost = targetm.sched.adjust_cost (used, (int) dep_type, insn, cost,
1493*38fd1498Szrj 					  dw);
1494*38fd1498Szrj 
1495*38fd1498Szrj       if (cost < 0)
1496*38fd1498Szrj 	cost = 0;
1497*38fd1498Szrj     }
1498*38fd1498Szrj 
1499*38fd1498Szrj   DEP_COST (link) = cost;
1500*38fd1498Szrj   return cost;
1501*38fd1498Szrj }
1502*38fd1498Szrj 
1503*38fd1498Szrj /* Compute cost of dependence LINK.
1504*38fd1498Szrj    This is the number of cycles between instruction issue and
1505*38fd1498Szrj    instruction results.  */
1506*38fd1498Szrj int
dep_cost(dep_t link)1507*38fd1498Szrj dep_cost (dep_t link)
1508*38fd1498Szrj {
1509*38fd1498Szrj   return dep_cost_1 (link, 0);
1510*38fd1498Szrj }
1511*38fd1498Szrj 
1512*38fd1498Szrj /* Use this sel-sched.c friendly function in reorder2 instead of increasing
1513*38fd1498Szrj    INSN_PRIORITY explicitly.  */
1514*38fd1498Szrj void
increase_insn_priority(rtx_insn * insn,int amount)1515*38fd1498Szrj increase_insn_priority (rtx_insn *insn, int amount)
1516*38fd1498Szrj {
1517*38fd1498Szrj   if (!sel_sched_p ())
1518*38fd1498Szrj     {
1519*38fd1498Szrj       /* We're dealing with haifa-sched.c INSN_PRIORITY.  */
1520*38fd1498Szrj       if (INSN_PRIORITY_KNOWN (insn))
1521*38fd1498Szrj 	  INSN_PRIORITY (insn) += amount;
1522*38fd1498Szrj     }
1523*38fd1498Szrj   else
1524*38fd1498Szrj     {
1525*38fd1498Szrj       /* In sel-sched.c INSN_PRIORITY is not kept up to date.
1526*38fd1498Szrj 	 Use EXPR_PRIORITY instead. */
1527*38fd1498Szrj       sel_add_to_insn_priority (insn, amount);
1528*38fd1498Szrj     }
1529*38fd1498Szrj }
1530*38fd1498Szrj 
1531*38fd1498Szrj /* Return 'true' if DEP should be included in priority calculations.  */
1532*38fd1498Szrj static bool
contributes_to_priority_p(dep_t dep)1533*38fd1498Szrj contributes_to_priority_p (dep_t dep)
1534*38fd1498Szrj {
1535*38fd1498Szrj   if (DEBUG_INSN_P (DEP_CON (dep))
1536*38fd1498Szrj       || DEBUG_INSN_P (DEP_PRO (dep)))
1537*38fd1498Szrj     return false;
1538*38fd1498Szrj 
1539*38fd1498Szrj   /* Critical path is meaningful in block boundaries only.  */
1540*38fd1498Szrj   if (!current_sched_info->contributes_to_priority (DEP_CON (dep),
1541*38fd1498Szrj 						    DEP_PRO (dep)))
1542*38fd1498Szrj     return false;
1543*38fd1498Szrj 
1544*38fd1498Szrj   if (DEP_REPLACE (dep) != NULL)
1545*38fd1498Szrj     return false;
1546*38fd1498Szrj 
1547*38fd1498Szrj   /* If flag COUNT_SPEC_IN_CRITICAL_PATH is set,
1548*38fd1498Szrj      then speculative instructions will less likely be
1549*38fd1498Szrj      scheduled.  That is because the priority of
1550*38fd1498Szrj      their producers will increase, and, thus, the
1551*38fd1498Szrj      producers will more likely be scheduled, thus,
1552*38fd1498Szrj      resolving the dependence.  */
1553*38fd1498Szrj   if (sched_deps_info->generate_spec_deps
1554*38fd1498Szrj       && !(spec_info->flags & COUNT_SPEC_IN_CRITICAL_PATH)
1555*38fd1498Szrj       && (DEP_STATUS (dep) & SPECULATIVE))
1556*38fd1498Szrj     return false;
1557*38fd1498Szrj 
1558*38fd1498Szrj   return true;
1559*38fd1498Szrj }
1560*38fd1498Szrj 
1561*38fd1498Szrj /* Compute the number of nondebug deps in list LIST for INSN.  */
1562*38fd1498Szrj 
1563*38fd1498Szrj static int
dep_list_size(rtx_insn * insn,sd_list_types_def list)1564*38fd1498Szrj dep_list_size (rtx_insn *insn, sd_list_types_def list)
1565*38fd1498Szrj {
1566*38fd1498Szrj   sd_iterator_def sd_it;
1567*38fd1498Szrj   dep_t dep;
1568*38fd1498Szrj   int dbgcount = 0, nodbgcount = 0;
1569*38fd1498Szrj 
1570*38fd1498Szrj   if (!MAY_HAVE_DEBUG_INSNS)
1571*38fd1498Szrj     return sd_lists_size (insn, list);
1572*38fd1498Szrj 
1573*38fd1498Szrj   FOR_EACH_DEP (insn, list, sd_it, dep)
1574*38fd1498Szrj     {
1575*38fd1498Szrj       if (DEBUG_INSN_P (DEP_CON (dep)))
1576*38fd1498Szrj 	dbgcount++;
1577*38fd1498Szrj       else if (!DEBUG_INSN_P (DEP_PRO (dep)))
1578*38fd1498Szrj 	nodbgcount++;
1579*38fd1498Szrj     }
1580*38fd1498Szrj 
1581*38fd1498Szrj   gcc_assert (dbgcount + nodbgcount == sd_lists_size (insn, list));
1582*38fd1498Szrj 
1583*38fd1498Szrj   return nodbgcount;
1584*38fd1498Szrj }
1585*38fd1498Szrj 
1586*38fd1498Szrj bool sched_fusion;
1587*38fd1498Szrj 
1588*38fd1498Szrj /* Compute the priority number for INSN.  */
1589*38fd1498Szrj static int
priority(rtx_insn * insn)1590*38fd1498Szrj priority (rtx_insn *insn)
1591*38fd1498Szrj {
1592*38fd1498Szrj   if (! INSN_P (insn))
1593*38fd1498Szrj     return 0;
1594*38fd1498Szrj 
1595*38fd1498Szrj   /* We should not be interested in priority of an already scheduled insn.  */
1596*38fd1498Szrj   gcc_assert (QUEUE_INDEX (insn) != QUEUE_SCHEDULED);
1597*38fd1498Szrj 
1598*38fd1498Szrj   if (!INSN_PRIORITY_KNOWN (insn))
1599*38fd1498Szrj     {
1600*38fd1498Szrj       int this_priority = -1;
1601*38fd1498Szrj 
1602*38fd1498Szrj       if (sched_fusion)
1603*38fd1498Szrj 	{
1604*38fd1498Szrj 	  int this_fusion_priority;
1605*38fd1498Szrj 
1606*38fd1498Szrj 	  targetm.sched.fusion_priority (insn, FUSION_MAX_PRIORITY,
1607*38fd1498Szrj 					 &this_fusion_priority, &this_priority);
1608*38fd1498Szrj 	  INSN_FUSION_PRIORITY (insn) = this_fusion_priority;
1609*38fd1498Szrj 	}
1610*38fd1498Szrj       else if (dep_list_size (insn, SD_LIST_FORW) == 0)
1611*38fd1498Szrj 	/* ??? We should set INSN_PRIORITY to insn_sched_cost when and insn
1612*38fd1498Szrj 	   has some forward deps but all of them are ignored by
1613*38fd1498Szrj 	   contributes_to_priority hook.  At the moment we set priority of
1614*38fd1498Szrj 	   such insn to 0.  */
1615*38fd1498Szrj 	this_priority = insn_sched_cost (insn);
1616*38fd1498Szrj       else
1617*38fd1498Szrj 	{
1618*38fd1498Szrj 	  rtx_insn *prev_first, *twin;
1619*38fd1498Szrj 	  basic_block rec;
1620*38fd1498Szrj 
1621*38fd1498Szrj 	  /* For recovery check instructions we calculate priority slightly
1622*38fd1498Szrj 	     different than that of normal instructions.  Instead of walking
1623*38fd1498Szrj 	     through INSN_FORW_DEPS (check) list, we walk through
1624*38fd1498Szrj 	     INSN_FORW_DEPS list of each instruction in the corresponding
1625*38fd1498Szrj 	     recovery block.  */
1626*38fd1498Szrj 
1627*38fd1498Szrj           /* Selective scheduling does not define RECOVERY_BLOCK macro.  */
1628*38fd1498Szrj 	  rec = sel_sched_p () ? NULL : RECOVERY_BLOCK (insn);
1629*38fd1498Szrj 	  if (!rec || rec == EXIT_BLOCK_PTR_FOR_FN (cfun))
1630*38fd1498Szrj 	    {
1631*38fd1498Szrj 	      prev_first = PREV_INSN (insn);
1632*38fd1498Szrj 	      twin = insn;
1633*38fd1498Szrj 	    }
1634*38fd1498Szrj 	  else
1635*38fd1498Szrj 	    {
1636*38fd1498Szrj 	      prev_first = NEXT_INSN (BB_HEAD (rec));
1637*38fd1498Szrj 	      twin = PREV_INSN (BB_END (rec));
1638*38fd1498Szrj 	    }
1639*38fd1498Szrj 
1640*38fd1498Szrj 	  do
1641*38fd1498Szrj 	    {
1642*38fd1498Szrj 	      sd_iterator_def sd_it;
1643*38fd1498Szrj 	      dep_t dep;
1644*38fd1498Szrj 
1645*38fd1498Szrj 	      FOR_EACH_DEP (twin, SD_LIST_FORW, sd_it, dep)
1646*38fd1498Szrj 		{
1647*38fd1498Szrj 		  rtx_insn *next;
1648*38fd1498Szrj 		  int next_priority;
1649*38fd1498Szrj 
1650*38fd1498Szrj 		  next = DEP_CON (dep);
1651*38fd1498Szrj 
1652*38fd1498Szrj 		  if (BLOCK_FOR_INSN (next) != rec)
1653*38fd1498Szrj 		    {
1654*38fd1498Szrj 		      int cost;
1655*38fd1498Szrj 
1656*38fd1498Szrj 		      if (!contributes_to_priority_p (dep))
1657*38fd1498Szrj 			continue;
1658*38fd1498Szrj 
1659*38fd1498Szrj 		      if (twin == insn)
1660*38fd1498Szrj 			cost = dep_cost (dep);
1661*38fd1498Szrj 		      else
1662*38fd1498Szrj 			{
1663*38fd1498Szrj 			  struct _dep _dep1, *dep1 = &_dep1;
1664*38fd1498Szrj 
1665*38fd1498Szrj 			  init_dep (dep1, insn, next, REG_DEP_ANTI);
1666*38fd1498Szrj 
1667*38fd1498Szrj 			  cost = dep_cost (dep1);
1668*38fd1498Szrj 			}
1669*38fd1498Szrj 
1670*38fd1498Szrj 		      next_priority = cost + priority (next);
1671*38fd1498Szrj 
1672*38fd1498Szrj 		      if (next_priority > this_priority)
1673*38fd1498Szrj 			this_priority = next_priority;
1674*38fd1498Szrj 		    }
1675*38fd1498Szrj 		}
1676*38fd1498Szrj 
1677*38fd1498Szrj 	      twin = PREV_INSN (twin);
1678*38fd1498Szrj 	    }
1679*38fd1498Szrj 	  while (twin != prev_first);
1680*38fd1498Szrj 	}
1681*38fd1498Szrj 
1682*38fd1498Szrj       if (this_priority < 0)
1683*38fd1498Szrj 	{
1684*38fd1498Szrj 	  gcc_assert (this_priority == -1);
1685*38fd1498Szrj 
1686*38fd1498Szrj 	  this_priority = insn_sched_cost (insn);
1687*38fd1498Szrj 	}
1688*38fd1498Szrj 
1689*38fd1498Szrj       INSN_PRIORITY (insn) = this_priority;
1690*38fd1498Szrj       INSN_PRIORITY_STATUS (insn) = 1;
1691*38fd1498Szrj     }
1692*38fd1498Szrj 
1693*38fd1498Szrj   return INSN_PRIORITY (insn);
1694*38fd1498Szrj }
1695*38fd1498Szrj 
1696*38fd1498Szrj /* Macros and functions for keeping the priority queue sorted, and
1697*38fd1498Szrj    dealing with queuing and dequeuing of instructions.  */
1698*38fd1498Szrj 
1699*38fd1498Szrj /* For each pressure class CL, set DEATH[CL] to the number of registers
1700*38fd1498Szrj    in that class that die in INSN.  */
1701*38fd1498Szrj 
1702*38fd1498Szrj static void
calculate_reg_deaths(rtx_insn * insn,int * death)1703*38fd1498Szrj calculate_reg_deaths (rtx_insn *insn, int *death)
1704*38fd1498Szrj {
1705*38fd1498Szrj   int i;
1706*38fd1498Szrj   struct reg_use_data *use;
1707*38fd1498Szrj 
1708*38fd1498Szrj   for (i = 0; i < ira_pressure_classes_num; i++)
1709*38fd1498Szrj     death[ira_pressure_classes[i]] = 0;
1710*38fd1498Szrj   for (use = INSN_REG_USE_LIST (insn); use != NULL; use = use->next_insn_use)
1711*38fd1498Szrj     if (dying_use_p (use))
1712*38fd1498Szrj       mark_regno_birth_or_death (0, death, use->regno, true);
1713*38fd1498Szrj }
1714*38fd1498Szrj 
1715*38fd1498Szrj /* Setup info about the current register pressure impact of scheduling
1716*38fd1498Szrj    INSN at the current scheduling point.  */
1717*38fd1498Szrj static void
setup_insn_reg_pressure_info(rtx_insn * insn)1718*38fd1498Szrj setup_insn_reg_pressure_info (rtx_insn *insn)
1719*38fd1498Szrj {
1720*38fd1498Szrj   int i, change, before, after, hard_regno;
1721*38fd1498Szrj   int excess_cost_change;
1722*38fd1498Szrj   machine_mode mode;
1723*38fd1498Szrj   enum reg_class cl;
1724*38fd1498Szrj   struct reg_pressure_data *pressure_info;
1725*38fd1498Szrj   int *max_reg_pressure;
1726*38fd1498Szrj   static int death[N_REG_CLASSES];
1727*38fd1498Szrj 
1728*38fd1498Szrj   gcc_checking_assert (!DEBUG_INSN_P (insn));
1729*38fd1498Szrj 
1730*38fd1498Szrj   excess_cost_change = 0;
1731*38fd1498Szrj   calculate_reg_deaths (insn, death);
1732*38fd1498Szrj   pressure_info = INSN_REG_PRESSURE (insn);
1733*38fd1498Szrj   max_reg_pressure = INSN_MAX_REG_PRESSURE (insn);
1734*38fd1498Szrj   gcc_assert (pressure_info != NULL && max_reg_pressure != NULL);
1735*38fd1498Szrj   for (i = 0; i < ira_pressure_classes_num; i++)
1736*38fd1498Szrj     {
1737*38fd1498Szrj       cl = ira_pressure_classes[i];
1738*38fd1498Szrj       gcc_assert (curr_reg_pressure[cl] >= 0);
1739*38fd1498Szrj       change = (int) pressure_info[i].set_increase - death[cl];
1740*38fd1498Szrj       before = MAX (0, max_reg_pressure[i] - sched_class_regs_num[cl]);
1741*38fd1498Szrj       after = MAX (0, max_reg_pressure[i] + change
1742*38fd1498Szrj 		   - sched_class_regs_num[cl]);
1743*38fd1498Szrj       hard_regno = ira_class_hard_regs[cl][0];
1744*38fd1498Szrj       gcc_assert (hard_regno >= 0);
1745*38fd1498Szrj       mode = reg_raw_mode[hard_regno];
1746*38fd1498Szrj       excess_cost_change += ((after - before)
1747*38fd1498Szrj 			     * (ira_memory_move_cost[mode][cl][0]
1748*38fd1498Szrj 				+ ira_memory_move_cost[mode][cl][1]));
1749*38fd1498Szrj     }
1750*38fd1498Szrj   INSN_REG_PRESSURE_EXCESS_COST_CHANGE (insn) = excess_cost_change;
1751*38fd1498Szrj }
1752*38fd1498Szrj 
1753*38fd1498Szrj /* This is the first page of code related to SCHED_PRESSURE_MODEL.
1754*38fd1498Szrj    It tries to make the scheduler take register pressure into account
1755*38fd1498Szrj    without introducing too many unnecessary stalls.  It hooks into the
1756*38fd1498Szrj    main scheduling algorithm at several points:
1757*38fd1498Szrj 
1758*38fd1498Szrj     - Before scheduling starts, model_start_schedule constructs a
1759*38fd1498Szrj       "model schedule" for the current block.  This model schedule is
1760*38fd1498Szrj       chosen solely to keep register pressure down.  It does not take the
1761*38fd1498Szrj       target's pipeline or the original instruction order into account,
1762*38fd1498Szrj       except as a tie-breaker.  It also doesn't work to a particular
1763*38fd1498Szrj       pressure limit.
1764*38fd1498Szrj 
1765*38fd1498Szrj       This model schedule gives us an idea of what pressure can be
1766*38fd1498Szrj       achieved for the block and gives us an example of a schedule that
1767*38fd1498Szrj       keeps to that pressure.  It also makes the final schedule less
1768*38fd1498Szrj       dependent on the original instruction order.  This is important
1769*38fd1498Szrj       because the original order can either be "wide" (many values live
1770*38fd1498Szrj       at once, such as in user-scheduled code) or "narrow" (few values
1771*38fd1498Szrj       live at once, such as after loop unrolling, where several
1772*38fd1498Szrj       iterations are executed sequentially).
1773*38fd1498Szrj 
1774*38fd1498Szrj       We do not apply this model schedule to the rtx stream.  We simply
1775*38fd1498Szrj       record it in model_schedule.  We also compute the maximum pressure,
1776*38fd1498Szrj       MP, that was seen during this schedule.
1777*38fd1498Szrj 
1778*38fd1498Szrj     - Instructions are added to the ready queue even if they require
1779*38fd1498Szrj       a stall.  The length of the stall is instead computed as:
1780*38fd1498Szrj 
1781*38fd1498Szrj 	 MAX (INSN_TICK (INSN) - clock_var, 0)
1782*38fd1498Szrj 
1783*38fd1498Szrj       (= insn_delay).  This allows rank_for_schedule to choose between
1784*38fd1498Szrj       introducing a deliberate stall or increasing pressure.
1785*38fd1498Szrj 
1786*38fd1498Szrj     - Before sorting the ready queue, model_set_excess_costs assigns
1787*38fd1498Szrj       a pressure-based cost to each ready instruction in the queue.
1788*38fd1498Szrj       This is the instruction's INSN_REG_PRESSURE_EXCESS_COST_CHANGE
1789*38fd1498Szrj       (ECC for short) and is effectively measured in cycles.
1790*38fd1498Szrj 
1791*38fd1498Szrj     - rank_for_schedule ranks instructions based on:
1792*38fd1498Szrj 
1793*38fd1498Szrj 	ECC (insn) + insn_delay (insn)
1794*38fd1498Szrj 
1795*38fd1498Szrj       then as:
1796*38fd1498Szrj 
1797*38fd1498Szrj 	insn_delay (insn)
1798*38fd1498Szrj 
1799*38fd1498Szrj       So, for example, an instruction X1 with an ECC of 1 that can issue
1800*38fd1498Szrj       now will win over an instruction X0 with an ECC of zero that would
1801*38fd1498Szrj       introduce a stall of one cycle.  However, an instruction X2 with an
1802*38fd1498Szrj       ECC of 2 that can issue now will lose to both X0 and X1.
1803*38fd1498Szrj 
1804*38fd1498Szrj     - When an instruction is scheduled, model_recompute updates the model
1805*38fd1498Szrj       schedule with the new pressures (some of which might now exceed the
1806*38fd1498Szrj       original maximum pressure MP).  model_update_limit_points then searches
1807*38fd1498Szrj       for the new point of maximum pressure, if not already known.  */
1808*38fd1498Szrj 
1809*38fd1498Szrj /* Used to separate high-verbosity debug information for SCHED_PRESSURE_MODEL
1810*38fd1498Szrj    from surrounding debug information.  */
1811*38fd1498Szrj #define MODEL_BAR \
1812*38fd1498Szrj   ";;\t\t+------------------------------------------------------\n"
1813*38fd1498Szrj 
1814*38fd1498Szrj /* Information about the pressure on a particular register class at a
1815*38fd1498Szrj    particular point of the model schedule.  */
1816*38fd1498Szrj struct model_pressure_data {
1817*38fd1498Szrj   /* The pressure at this point of the model schedule, or -1 if the
1818*38fd1498Szrj      point is associated with an instruction that has already been
1819*38fd1498Szrj      scheduled.  */
1820*38fd1498Szrj   int ref_pressure;
1821*38fd1498Szrj 
1822*38fd1498Szrj   /* The maximum pressure during or after this point of the model schedule.  */
1823*38fd1498Szrj   int max_pressure;
1824*38fd1498Szrj };
1825*38fd1498Szrj 
1826*38fd1498Szrj /* Per-instruction information that is used while building the model
1827*38fd1498Szrj    schedule.  Here, "schedule" refers to the model schedule rather
1828*38fd1498Szrj    than the main schedule.  */
1829*38fd1498Szrj struct model_insn_info {
1830*38fd1498Szrj   /* The instruction itself.  */
1831*38fd1498Szrj   rtx_insn *insn;
1832*38fd1498Szrj 
1833*38fd1498Szrj   /* If this instruction is in model_worklist, these fields link to the
1834*38fd1498Szrj      previous (higher-priority) and next (lower-priority) instructions
1835*38fd1498Szrj      in the list.  */
1836*38fd1498Szrj   struct model_insn_info *prev;
1837*38fd1498Szrj   struct model_insn_info *next;
1838*38fd1498Szrj 
1839*38fd1498Szrj   /* While constructing the schedule, QUEUE_INDEX describes whether an
1840*38fd1498Szrj      instruction has already been added to the schedule (QUEUE_SCHEDULED),
1841*38fd1498Szrj      is in model_worklist (QUEUE_READY), or neither (QUEUE_NOWHERE).
1842*38fd1498Szrj      old_queue records the value that QUEUE_INDEX had before scheduling
1843*38fd1498Szrj      started, so that we can restore it once the schedule is complete.  */
1844*38fd1498Szrj   int old_queue;
1845*38fd1498Szrj 
1846*38fd1498Szrj   /* The relative importance of an unscheduled instruction.  Higher
1847*38fd1498Szrj      values indicate greater importance.  */
1848*38fd1498Szrj   unsigned int model_priority;
1849*38fd1498Szrj 
1850*38fd1498Szrj   /* The length of the longest path of satisfied true dependencies
1851*38fd1498Szrj      that leads to this instruction.  */
1852*38fd1498Szrj   unsigned int depth;
1853*38fd1498Szrj 
1854*38fd1498Szrj   /* The length of the longest path of dependencies of any kind
1855*38fd1498Szrj      that leads from this instruction.  */
1856*38fd1498Szrj   unsigned int alap;
1857*38fd1498Szrj 
1858*38fd1498Szrj   /* The number of predecessor nodes that must still be scheduled.  */
1859*38fd1498Szrj   int unscheduled_preds;
1860*38fd1498Szrj };
1861*38fd1498Szrj 
1862*38fd1498Szrj /* Information about the pressure limit for a particular register class.
1863*38fd1498Szrj    This structure is used when applying a model schedule to the main
1864*38fd1498Szrj    schedule.  */
1865*38fd1498Szrj struct model_pressure_limit {
1866*38fd1498Szrj   /* The maximum register pressure seen in the original model schedule.  */
1867*38fd1498Szrj   int orig_pressure;
1868*38fd1498Szrj 
1869*38fd1498Szrj   /* The maximum register pressure seen in the current model schedule
1870*38fd1498Szrj      (which excludes instructions that have already been scheduled).  */
1871*38fd1498Szrj   int pressure;
1872*38fd1498Szrj 
1873*38fd1498Szrj   /* The point of the current model schedule at which PRESSURE is first
1874*38fd1498Szrj      reached.  It is set to -1 if the value needs to be recomputed.  */
1875*38fd1498Szrj   int point;
1876*38fd1498Szrj };
1877*38fd1498Szrj 
1878*38fd1498Szrj /* Describes a particular way of measuring register pressure.  */
1879*38fd1498Szrj struct model_pressure_group {
1880*38fd1498Szrj   /* Index PCI describes the maximum pressure on ira_pressure_classes[PCI].  */
1881*38fd1498Szrj   struct model_pressure_limit limits[N_REG_CLASSES];
1882*38fd1498Szrj 
1883*38fd1498Szrj   /* Index (POINT * ira_num_pressure_classes + PCI) describes the pressure
1884*38fd1498Szrj      on register class ira_pressure_classes[PCI] at point POINT of the
1885*38fd1498Szrj      current model schedule.  A POINT of model_num_insns describes the
1886*38fd1498Szrj      pressure at the end of the schedule.  */
1887*38fd1498Szrj   struct model_pressure_data *model;
1888*38fd1498Szrj };
1889*38fd1498Szrj 
1890*38fd1498Szrj /* Index POINT gives the instruction at point POINT of the model schedule.
1891*38fd1498Szrj    This array doesn't change during main scheduling.  */
1892*38fd1498Szrj static vec<rtx_insn *> model_schedule;
1893*38fd1498Szrj 
1894*38fd1498Szrj /* The list of instructions in the model worklist, sorted in order of
1895*38fd1498Szrj    decreasing priority.  */
1896*38fd1498Szrj static struct model_insn_info *model_worklist;
1897*38fd1498Szrj 
1898*38fd1498Szrj /* Index I describes the instruction with INSN_LUID I.  */
1899*38fd1498Szrj static struct model_insn_info *model_insns;
1900*38fd1498Szrj 
1901*38fd1498Szrj /* The number of instructions in the model schedule.  */
1902*38fd1498Szrj static int model_num_insns;
1903*38fd1498Szrj 
1904*38fd1498Szrj /* The index of the first instruction in model_schedule that hasn't yet been
1905*38fd1498Szrj    added to the main schedule, or model_num_insns if all of them have.  */
1906*38fd1498Szrj static int model_curr_point;
1907*38fd1498Szrj 
1908*38fd1498Szrj /* Describes the pressure before each instruction in the model schedule.  */
1909*38fd1498Szrj static struct model_pressure_group model_before_pressure;
1910*38fd1498Szrj 
1911*38fd1498Szrj /* The first unused model_priority value (as used in model_insn_info).  */
1912*38fd1498Szrj static unsigned int model_next_priority;
1913*38fd1498Szrj 
1914*38fd1498Szrj 
1915*38fd1498Szrj /* The model_pressure_data for ira_pressure_classes[PCI] in GROUP
1916*38fd1498Szrj    at point POINT of the model schedule.  */
1917*38fd1498Szrj #define MODEL_PRESSURE_DATA(GROUP, POINT, PCI) \
1918*38fd1498Szrj   (&(GROUP)->model[(POINT) * ira_pressure_classes_num + (PCI)])
1919*38fd1498Szrj 
1920*38fd1498Szrj /* The maximum pressure on ira_pressure_classes[PCI] in GROUP at or
1921*38fd1498Szrj    after point POINT of the model schedule.  */
1922*38fd1498Szrj #define MODEL_MAX_PRESSURE(GROUP, POINT, PCI) \
1923*38fd1498Szrj   (MODEL_PRESSURE_DATA (GROUP, POINT, PCI)->max_pressure)
1924*38fd1498Szrj 
1925*38fd1498Szrj /* The pressure on ira_pressure_classes[PCI] in GROUP at point POINT
1926*38fd1498Szrj    of the model schedule.  */
1927*38fd1498Szrj #define MODEL_REF_PRESSURE(GROUP, POINT, PCI) \
1928*38fd1498Szrj   (MODEL_PRESSURE_DATA (GROUP, POINT, PCI)->ref_pressure)
1929*38fd1498Szrj 
1930*38fd1498Szrj /* Information about INSN that is used when creating the model schedule.  */
1931*38fd1498Szrj #define MODEL_INSN_INFO(INSN) \
1932*38fd1498Szrj   (&model_insns[INSN_LUID (INSN)])
1933*38fd1498Szrj 
1934*38fd1498Szrj /* The instruction at point POINT of the model schedule.  */
1935*38fd1498Szrj #define MODEL_INSN(POINT) \
1936*38fd1498Szrj   (model_schedule[POINT])
1937*38fd1498Szrj 
1938*38fd1498Szrj 
1939*38fd1498Szrj /* Return INSN's index in the model schedule, or model_num_insns if it
1940*38fd1498Szrj    doesn't belong to that schedule.  */
1941*38fd1498Szrj 
1942*38fd1498Szrj static int
model_index(rtx_insn * insn)1943*38fd1498Szrj model_index (rtx_insn *insn)
1944*38fd1498Szrj {
1945*38fd1498Szrj   if (INSN_MODEL_INDEX (insn) == 0)
1946*38fd1498Szrj     return model_num_insns;
1947*38fd1498Szrj   return INSN_MODEL_INDEX (insn) - 1;
1948*38fd1498Szrj }
1949*38fd1498Szrj 
1950*38fd1498Szrj /* Make sure that GROUP->limits is up-to-date for the current point
1951*38fd1498Szrj    of the model schedule.  */
1952*38fd1498Szrj 
1953*38fd1498Szrj static void
model_update_limit_points_in_group(struct model_pressure_group * group)1954*38fd1498Szrj model_update_limit_points_in_group (struct model_pressure_group *group)
1955*38fd1498Szrj {
1956*38fd1498Szrj   int pci, max_pressure, point;
1957*38fd1498Szrj 
1958*38fd1498Szrj   for (pci = 0; pci < ira_pressure_classes_num; pci++)
1959*38fd1498Szrj     {
1960*38fd1498Szrj       /* We may have passed the final point at which the pressure in
1961*38fd1498Szrj 	 group->limits[pci].pressure was reached.  Update the limit if so.  */
1962*38fd1498Szrj       max_pressure = MODEL_MAX_PRESSURE (group, model_curr_point, pci);
1963*38fd1498Szrj       group->limits[pci].pressure = max_pressure;
1964*38fd1498Szrj 
1965*38fd1498Szrj       /* Find the point at which MAX_PRESSURE is first reached.  We need
1966*38fd1498Szrj 	 to search in three cases:
1967*38fd1498Szrj 
1968*38fd1498Szrj 	 - We've already moved past the previous pressure point.
1969*38fd1498Szrj 	   In this case we search forward from model_curr_point.
1970*38fd1498Szrj 
1971*38fd1498Szrj 	 - We scheduled the previous point of maximum pressure ahead of
1972*38fd1498Szrj 	   its position in the model schedule, but doing so didn't bring
1973*38fd1498Szrj 	   the pressure point earlier.  In this case we search forward
1974*38fd1498Szrj 	   from that previous pressure point.
1975*38fd1498Szrj 
1976*38fd1498Szrj 	 - Scheduling an instruction early caused the maximum pressure
1977*38fd1498Szrj 	   to decrease.  In this case we will have set the pressure
1978*38fd1498Szrj 	   point to -1, and we search forward from model_curr_point.  */
1979*38fd1498Szrj       point = MAX (group->limits[pci].point, model_curr_point);
1980*38fd1498Szrj       while (point < model_num_insns
1981*38fd1498Szrj 	     && MODEL_REF_PRESSURE (group, point, pci) < max_pressure)
1982*38fd1498Szrj 	point++;
1983*38fd1498Szrj       group->limits[pci].point = point;
1984*38fd1498Szrj 
1985*38fd1498Szrj       gcc_assert (MODEL_REF_PRESSURE (group, point, pci) == max_pressure);
1986*38fd1498Szrj       gcc_assert (MODEL_MAX_PRESSURE (group, point, pci) == max_pressure);
1987*38fd1498Szrj     }
1988*38fd1498Szrj }
1989*38fd1498Szrj 
1990*38fd1498Szrj /* Make sure that all register-pressure limits are up-to-date for the
1991*38fd1498Szrj    current position in the model schedule.  */
1992*38fd1498Szrj 
1993*38fd1498Szrj static void
model_update_limit_points(void)1994*38fd1498Szrj model_update_limit_points (void)
1995*38fd1498Szrj {
1996*38fd1498Szrj   model_update_limit_points_in_group (&model_before_pressure);
1997*38fd1498Szrj }
1998*38fd1498Szrj 
1999*38fd1498Szrj /* Return the model_index of the last unscheduled use in chain USE
2000*38fd1498Szrj    outside of USE's instruction.  Return -1 if there are no other uses,
2001*38fd1498Szrj    or model_num_insns if the register is live at the end of the block.  */
2002*38fd1498Szrj 
2003*38fd1498Szrj static int
model_last_use_except(struct reg_use_data * use)2004*38fd1498Szrj model_last_use_except (struct reg_use_data *use)
2005*38fd1498Szrj {
2006*38fd1498Szrj   struct reg_use_data *next;
2007*38fd1498Szrj   int last, index;
2008*38fd1498Szrj 
2009*38fd1498Szrj   last = -1;
2010*38fd1498Szrj   for (next = use->next_regno_use; next != use; next = next->next_regno_use)
2011*38fd1498Szrj     if (NONDEBUG_INSN_P (next->insn)
2012*38fd1498Szrj 	&& QUEUE_INDEX (next->insn) != QUEUE_SCHEDULED)
2013*38fd1498Szrj       {
2014*38fd1498Szrj 	index = model_index (next->insn);
2015*38fd1498Szrj 	if (index == model_num_insns)
2016*38fd1498Szrj 	  return model_num_insns;
2017*38fd1498Szrj 	if (last < index)
2018*38fd1498Szrj 	  last = index;
2019*38fd1498Szrj       }
2020*38fd1498Szrj   return last;
2021*38fd1498Szrj }
2022*38fd1498Szrj 
2023*38fd1498Szrj /* An instruction with model_index POINT has just been scheduled, and it
2024*38fd1498Szrj    adds DELTA to the pressure on ira_pressure_classes[PCI] after POINT - 1.
2025*38fd1498Szrj    Update MODEL_REF_PRESSURE (GROUP, POINT, PCI) and
2026*38fd1498Szrj    MODEL_MAX_PRESSURE (GROUP, POINT, PCI) accordingly.  */
2027*38fd1498Szrj 
2028*38fd1498Szrj static void
model_start_update_pressure(struct model_pressure_group * group,int point,int pci,int delta)2029*38fd1498Szrj model_start_update_pressure (struct model_pressure_group *group,
2030*38fd1498Szrj 			     int point, int pci, int delta)
2031*38fd1498Szrj {
2032*38fd1498Szrj   int next_max_pressure;
2033*38fd1498Szrj 
2034*38fd1498Szrj   if (point == model_num_insns)
2035*38fd1498Szrj     {
2036*38fd1498Szrj       /* The instruction wasn't part of the model schedule; it was moved
2037*38fd1498Szrj 	 from a different block.  Update the pressure for the end of
2038*38fd1498Szrj 	 the model schedule.  */
2039*38fd1498Szrj       MODEL_REF_PRESSURE (group, point, pci) += delta;
2040*38fd1498Szrj       MODEL_MAX_PRESSURE (group, point, pci) += delta;
2041*38fd1498Szrj     }
2042*38fd1498Szrj   else
2043*38fd1498Szrj     {
2044*38fd1498Szrj       /* Record that this instruction has been scheduled.  Nothing now
2045*38fd1498Szrj 	 changes between POINT and POINT + 1, so get the maximum pressure
2046*38fd1498Szrj 	 from the latter.  If the maximum pressure decreases, the new
2047*38fd1498Szrj 	 pressure point may be before POINT.  */
2048*38fd1498Szrj       MODEL_REF_PRESSURE (group, point, pci) = -1;
2049*38fd1498Szrj       next_max_pressure = MODEL_MAX_PRESSURE (group, point + 1, pci);
2050*38fd1498Szrj       if (MODEL_MAX_PRESSURE (group, point, pci) > next_max_pressure)
2051*38fd1498Szrj 	{
2052*38fd1498Szrj 	  MODEL_MAX_PRESSURE (group, point, pci) = next_max_pressure;
2053*38fd1498Szrj 	  if (group->limits[pci].point == point)
2054*38fd1498Szrj 	    group->limits[pci].point = -1;
2055*38fd1498Szrj 	}
2056*38fd1498Szrj     }
2057*38fd1498Szrj }
2058*38fd1498Szrj 
2059*38fd1498Szrj /* Record that scheduling a later instruction has changed the pressure
2060*38fd1498Szrj    at point POINT of the model schedule by DELTA (which might be 0).
2061*38fd1498Szrj    Update GROUP accordingly.  Return nonzero if these changes might
2062*38fd1498Szrj    trigger changes to previous points as well.  */
2063*38fd1498Szrj 
2064*38fd1498Szrj static int
model_update_pressure(struct model_pressure_group * group,int point,int pci,int delta)2065*38fd1498Szrj model_update_pressure (struct model_pressure_group *group,
2066*38fd1498Szrj 		       int point, int pci, int delta)
2067*38fd1498Szrj {
2068*38fd1498Szrj   int ref_pressure, max_pressure, next_max_pressure;
2069*38fd1498Szrj 
2070*38fd1498Szrj   /* If POINT hasn't yet been scheduled, update its pressure.  */
2071*38fd1498Szrj   ref_pressure = MODEL_REF_PRESSURE (group, point, pci);
2072*38fd1498Szrj   if (ref_pressure >= 0 && delta != 0)
2073*38fd1498Szrj     {
2074*38fd1498Szrj       ref_pressure += delta;
2075*38fd1498Szrj       MODEL_REF_PRESSURE (group, point, pci) = ref_pressure;
2076*38fd1498Szrj 
2077*38fd1498Szrj       /* Check whether the maximum pressure in the overall schedule
2078*38fd1498Szrj 	 has increased.  (This means that the MODEL_MAX_PRESSURE of
2079*38fd1498Szrj 	 every point <= POINT will need to increase too; see below.)  */
2080*38fd1498Szrj       if (group->limits[pci].pressure < ref_pressure)
2081*38fd1498Szrj 	group->limits[pci].pressure = ref_pressure;
2082*38fd1498Szrj 
2083*38fd1498Szrj       /* If we are at maximum pressure, and the maximum pressure
2084*38fd1498Szrj 	 point was previously unknown or later than POINT,
2085*38fd1498Szrj 	 bring it forward.  */
2086*38fd1498Szrj       if (group->limits[pci].pressure == ref_pressure
2087*38fd1498Szrj 	  && !IN_RANGE (group->limits[pci].point, 0, point))
2088*38fd1498Szrj 	group->limits[pci].point = point;
2089*38fd1498Szrj 
2090*38fd1498Szrj       /* If POINT used to be the point of maximum pressure, but isn't
2091*38fd1498Szrj 	 any longer, we need to recalculate it using a forward walk.  */
2092*38fd1498Szrj       if (group->limits[pci].pressure > ref_pressure
2093*38fd1498Szrj 	  && group->limits[pci].point == point)
2094*38fd1498Szrj 	group->limits[pci].point = -1;
2095*38fd1498Szrj     }
2096*38fd1498Szrj 
2097*38fd1498Szrj   /* Update the maximum pressure at POINT.  Changes here might also
2098*38fd1498Szrj      affect the maximum pressure at POINT - 1.  */
2099*38fd1498Szrj   next_max_pressure = MODEL_MAX_PRESSURE (group, point + 1, pci);
2100*38fd1498Szrj   max_pressure = MAX (ref_pressure, next_max_pressure);
2101*38fd1498Szrj   if (MODEL_MAX_PRESSURE (group, point, pci) != max_pressure)
2102*38fd1498Szrj     {
2103*38fd1498Szrj       MODEL_MAX_PRESSURE (group, point, pci) = max_pressure;
2104*38fd1498Szrj       return 1;
2105*38fd1498Szrj     }
2106*38fd1498Szrj   return 0;
2107*38fd1498Szrj }
2108*38fd1498Szrj 
2109*38fd1498Szrj /* INSN has just been scheduled.  Update the model schedule accordingly.  */
2110*38fd1498Szrj 
2111*38fd1498Szrj static void
model_recompute(rtx_insn * insn)2112*38fd1498Szrj model_recompute (rtx_insn *insn)
2113*38fd1498Szrj {
2114*38fd1498Szrj   struct {
2115*38fd1498Szrj     int last_use;
2116*38fd1498Szrj     int regno;
2117*38fd1498Szrj   } uses[FIRST_PSEUDO_REGISTER + MAX_RECOG_OPERANDS];
2118*38fd1498Szrj   struct reg_use_data *use;
2119*38fd1498Szrj   struct reg_pressure_data *reg_pressure;
2120*38fd1498Szrj   int delta[N_REG_CLASSES];
2121*38fd1498Szrj   int pci, point, mix, new_last, cl, ref_pressure, queue;
2122*38fd1498Szrj   unsigned int i, num_uses, num_pending_births;
2123*38fd1498Szrj   bool print_p;
2124*38fd1498Szrj 
2125*38fd1498Szrj   /* The destinations of INSN were previously live from POINT onwards, but are
2126*38fd1498Szrj      now live from model_curr_point onwards.  Set up DELTA accordingly.  */
2127*38fd1498Szrj   point = model_index (insn);
2128*38fd1498Szrj   reg_pressure = INSN_REG_PRESSURE (insn);
2129*38fd1498Szrj   for (pci = 0; pci < ira_pressure_classes_num; pci++)
2130*38fd1498Szrj     {
2131*38fd1498Szrj       cl = ira_pressure_classes[pci];
2132*38fd1498Szrj       delta[cl] = reg_pressure[pci].set_increase;
2133*38fd1498Szrj     }
2134*38fd1498Szrj 
2135*38fd1498Szrj   /* Record which registers previously died at POINT, but which now die
2136*38fd1498Szrj      before POINT.  Adjust DELTA so that it represents the effect of
2137*38fd1498Szrj      this change after POINT - 1.  Set NUM_PENDING_BIRTHS to the number of
2138*38fd1498Szrj      registers that will be born in the range [model_curr_point, POINT).  */
2139*38fd1498Szrj   num_uses = 0;
2140*38fd1498Szrj   num_pending_births = 0;
2141*38fd1498Szrj   bitmap_clear (tmp_bitmap);
2142*38fd1498Szrj   for (use = INSN_REG_USE_LIST (insn); use != NULL; use = use->next_insn_use)
2143*38fd1498Szrj     {
2144*38fd1498Szrj       new_last = model_last_use_except (use);
2145*38fd1498Szrj       if (new_last < point && bitmap_set_bit (tmp_bitmap, use->regno))
2146*38fd1498Szrj 	{
2147*38fd1498Szrj 	  gcc_assert (num_uses < ARRAY_SIZE (uses));
2148*38fd1498Szrj 	  uses[num_uses].last_use = new_last;
2149*38fd1498Szrj 	  uses[num_uses].regno = use->regno;
2150*38fd1498Szrj 	  /* This register is no longer live after POINT - 1.  */
2151*38fd1498Szrj 	  mark_regno_birth_or_death (NULL, delta, use->regno, false);
2152*38fd1498Szrj 	  num_uses++;
2153*38fd1498Szrj 	  if (new_last >= 0)
2154*38fd1498Szrj 	    num_pending_births++;
2155*38fd1498Szrj 	}
2156*38fd1498Szrj     }
2157*38fd1498Szrj 
2158*38fd1498Szrj   /* Update the MODEL_REF_PRESSURE and MODEL_MAX_PRESSURE for POINT.
2159*38fd1498Szrj      Also set each group pressure limit for POINT.  */
2160*38fd1498Szrj   for (pci = 0; pci < ira_pressure_classes_num; pci++)
2161*38fd1498Szrj     {
2162*38fd1498Szrj       cl = ira_pressure_classes[pci];
2163*38fd1498Szrj       model_start_update_pressure (&model_before_pressure,
2164*38fd1498Szrj 				   point, pci, delta[cl]);
2165*38fd1498Szrj     }
2166*38fd1498Szrj 
2167*38fd1498Szrj   /* Walk the model schedule backwards, starting immediately before POINT.  */
2168*38fd1498Szrj   print_p = false;
2169*38fd1498Szrj   if (point != model_curr_point)
2170*38fd1498Szrj     do
2171*38fd1498Szrj       {
2172*38fd1498Szrj 	point--;
2173*38fd1498Szrj 	insn = MODEL_INSN (point);
2174*38fd1498Szrj 	queue = QUEUE_INDEX (insn);
2175*38fd1498Szrj 
2176*38fd1498Szrj 	if (queue != QUEUE_SCHEDULED)
2177*38fd1498Szrj 	  {
2178*38fd1498Szrj 	    /* DELTA describes the effect of the move on the register pressure
2179*38fd1498Szrj 	       after POINT.  Make it describe the effect on the pressure
2180*38fd1498Szrj 	       before POINT.  */
2181*38fd1498Szrj 	    i = 0;
2182*38fd1498Szrj 	    while (i < num_uses)
2183*38fd1498Szrj 	      {
2184*38fd1498Szrj 		if (uses[i].last_use == point)
2185*38fd1498Szrj 		  {
2186*38fd1498Szrj 		    /* This register is now live again.  */
2187*38fd1498Szrj 		    mark_regno_birth_or_death (NULL, delta,
2188*38fd1498Szrj 					       uses[i].regno, true);
2189*38fd1498Szrj 
2190*38fd1498Szrj 		    /* Remove this use from the array.  */
2191*38fd1498Szrj 		    uses[i] = uses[num_uses - 1];
2192*38fd1498Szrj 		    num_uses--;
2193*38fd1498Szrj 		    num_pending_births--;
2194*38fd1498Szrj 		  }
2195*38fd1498Szrj 		else
2196*38fd1498Szrj 		  i++;
2197*38fd1498Szrj 	      }
2198*38fd1498Szrj 
2199*38fd1498Szrj 	    if (sched_verbose >= 5)
2200*38fd1498Szrj 	      {
2201*38fd1498Szrj 		if (!print_p)
2202*38fd1498Szrj 		  {
2203*38fd1498Szrj 		    fprintf (sched_dump, MODEL_BAR);
2204*38fd1498Szrj 		    fprintf (sched_dump, ";;\t\t| New pressure for model"
2205*38fd1498Szrj 			     " schedule\n");
2206*38fd1498Szrj 		    fprintf (sched_dump, MODEL_BAR);
2207*38fd1498Szrj 		    print_p = true;
2208*38fd1498Szrj 		  }
2209*38fd1498Szrj 
2210*38fd1498Szrj 		fprintf (sched_dump, ";;\t\t| %3d %4d %-30s ",
2211*38fd1498Szrj 			 point, INSN_UID (insn),
2212*38fd1498Szrj 			 str_pattern_slim (PATTERN (insn)));
2213*38fd1498Szrj 		for (pci = 0; pci < ira_pressure_classes_num; pci++)
2214*38fd1498Szrj 		  {
2215*38fd1498Szrj 		    cl = ira_pressure_classes[pci];
2216*38fd1498Szrj 		    ref_pressure = MODEL_REF_PRESSURE (&model_before_pressure,
2217*38fd1498Szrj 						       point, pci);
2218*38fd1498Szrj 		    fprintf (sched_dump, " %s:[%d->%d]",
2219*38fd1498Szrj 			     reg_class_names[ira_pressure_classes[pci]],
2220*38fd1498Szrj 			     ref_pressure, ref_pressure + delta[cl]);
2221*38fd1498Szrj 		  }
2222*38fd1498Szrj 		fprintf (sched_dump, "\n");
2223*38fd1498Szrj 	      }
2224*38fd1498Szrj 	  }
2225*38fd1498Szrj 
2226*38fd1498Szrj 	/* Adjust the pressure at POINT.  Set MIX to nonzero if POINT - 1
2227*38fd1498Szrj 	   might have changed as well.  */
2228*38fd1498Szrj 	mix = num_pending_births;
2229*38fd1498Szrj 	for (pci = 0; pci < ira_pressure_classes_num; pci++)
2230*38fd1498Szrj 	  {
2231*38fd1498Szrj 	    cl = ira_pressure_classes[pci];
2232*38fd1498Szrj 	    mix |= delta[cl];
2233*38fd1498Szrj 	    mix |= model_update_pressure (&model_before_pressure,
2234*38fd1498Szrj 					  point, pci, delta[cl]);
2235*38fd1498Szrj 	  }
2236*38fd1498Szrj       }
2237*38fd1498Szrj     while (mix && point > model_curr_point);
2238*38fd1498Szrj 
2239*38fd1498Szrj   if (print_p)
2240*38fd1498Szrj     fprintf (sched_dump, MODEL_BAR);
2241*38fd1498Szrj }
2242*38fd1498Szrj 
2243*38fd1498Szrj /* After DEP, which was cancelled, has been resolved for insn NEXT,
2244*38fd1498Szrj    check whether the insn's pattern needs restoring.  */
2245*38fd1498Szrj static bool
must_restore_pattern_p(rtx_insn * next,dep_t dep)2246*38fd1498Szrj must_restore_pattern_p (rtx_insn *next, dep_t dep)
2247*38fd1498Szrj {
2248*38fd1498Szrj   if (QUEUE_INDEX (next) == QUEUE_SCHEDULED)
2249*38fd1498Szrj     return false;
2250*38fd1498Szrj 
2251*38fd1498Szrj   if (DEP_TYPE (dep) == REG_DEP_CONTROL)
2252*38fd1498Szrj     {
2253*38fd1498Szrj       gcc_assert (ORIG_PAT (next) != NULL_RTX);
2254*38fd1498Szrj       gcc_assert (next == DEP_CON (dep));
2255*38fd1498Szrj     }
2256*38fd1498Szrj   else
2257*38fd1498Szrj     {
2258*38fd1498Szrj       struct dep_replacement *desc = DEP_REPLACE (dep);
2259*38fd1498Szrj       if (desc->insn != next)
2260*38fd1498Szrj 	{
2261*38fd1498Szrj 	  gcc_assert (*desc->loc == desc->orig);
2262*38fd1498Szrj 	  return false;
2263*38fd1498Szrj 	}
2264*38fd1498Szrj     }
2265*38fd1498Szrj   return true;
2266*38fd1498Szrj }
2267*38fd1498Szrj 
2268*38fd1498Szrj /* model_spill_cost (CL, P, P') returns the cost of increasing the
2269*38fd1498Szrj    pressure on CL from P to P'.  We use this to calculate a "base ECC",
2270*38fd1498Szrj    baseECC (CL, X), for each pressure class CL and each instruction X.
2271*38fd1498Szrj    Supposing X changes the pressure on CL from P to P', and that the
2272*38fd1498Szrj    maximum pressure on CL in the current model schedule is MP', then:
2273*38fd1498Szrj 
2274*38fd1498Szrj    * if X occurs before or at the next point of maximum pressure in
2275*38fd1498Szrj      the model schedule and P' > MP', then:
2276*38fd1498Szrj 
2277*38fd1498Szrj        baseECC (CL, X) = model_spill_cost (CL, MP, P')
2278*38fd1498Szrj 
2279*38fd1498Szrj      The idea is that the pressure after scheduling a fixed set of
2280*38fd1498Szrj      instructions -- in this case, the set up to and including the
2281*38fd1498Szrj      next maximum pressure point -- is going to be the same regardless
2282*38fd1498Szrj      of the order; we simply want to keep the intermediate pressure
2283*38fd1498Szrj      under control.  Thus X has a cost of zero unless scheduling it
2284*38fd1498Szrj      now would exceed MP'.
2285*38fd1498Szrj 
2286*38fd1498Szrj      If all increases in the set are by the same amount, no zero-cost
2287*38fd1498Szrj      instruction will ever cause the pressure to exceed MP'.  However,
2288*38fd1498Szrj      if X is instead moved past an instruction X' with pressure in the
2289*38fd1498Szrj      range (MP' - (P' - P), MP'), the pressure at X' will increase
2290*38fd1498Szrj      beyond MP'.  Since baseECC is very much a heuristic anyway,
2291*38fd1498Szrj      it doesn't seem worth the overhead of tracking cases like these.
2292*38fd1498Szrj 
2293*38fd1498Szrj      The cost of exceeding MP' is always based on the original maximum
2294*38fd1498Szrj      pressure MP.  This is so that going 2 registers over the original
2295*38fd1498Szrj      limit has the same cost regardless of whether it comes from two
2296*38fd1498Szrj      separate +1 deltas or from a single +2 delta.
2297*38fd1498Szrj 
2298*38fd1498Szrj    * if X occurs after the next point of maximum pressure in the model
2299*38fd1498Szrj      schedule and P' > P, then:
2300*38fd1498Szrj 
2301*38fd1498Szrj        baseECC (CL, X) = model_spill_cost (CL, MP, MP' + (P' - P))
2302*38fd1498Szrj 
2303*38fd1498Szrj      That is, if we move X forward across a point of maximum pressure,
2304*38fd1498Szrj      and if X increases the pressure by P' - P, then we conservatively
2305*38fd1498Szrj      assume that scheduling X next would increase the maximum pressure
2306*38fd1498Szrj      by P' - P.  Again, the cost of doing this is based on the original
2307*38fd1498Szrj      maximum pressure MP, for the same reason as above.
2308*38fd1498Szrj 
2309*38fd1498Szrj    * if P' < P, P > MP, and X occurs at or after the next point of
2310*38fd1498Szrj      maximum pressure, then:
2311*38fd1498Szrj 
2312*38fd1498Szrj        baseECC (CL, X) = -model_spill_cost (CL, MAX (MP, P'), P)
2313*38fd1498Szrj 
2314*38fd1498Szrj      That is, if we have already exceeded the original maximum pressure MP,
2315*38fd1498Szrj      and if X might reduce the maximum pressure again -- or at least push
2316*38fd1498Szrj      it further back, and thus allow more scheduling freedom -- it is given
2317*38fd1498Szrj      a negative cost to reflect the improvement.
2318*38fd1498Szrj 
2319*38fd1498Szrj    * otherwise,
2320*38fd1498Szrj 
2321*38fd1498Szrj        baseECC (CL, X) = 0
2322*38fd1498Szrj 
2323*38fd1498Szrj      In this case, X is not expected to affect the maximum pressure MP',
2324*38fd1498Szrj      so it has zero cost.
2325*38fd1498Szrj 
2326*38fd1498Szrj    We then create a combined value baseECC (X) that is the sum of
2327*38fd1498Szrj    baseECC (CL, X) for each pressure class CL.
2328*38fd1498Szrj 
2329*38fd1498Szrj    baseECC (X) could itself be used as the ECC value described above.
2330*38fd1498Szrj    However, this is often too conservative, in the sense that it
2331*38fd1498Szrj    tends to make high-priority instructions that increase pressure
2332*38fd1498Szrj    wait too long in cases where introducing a spill would be better.
2333*38fd1498Szrj    For this reason the final ECC is a priority-adjusted form of
2334*38fd1498Szrj    baseECC (X).  Specifically, we calculate:
2335*38fd1498Szrj 
2336*38fd1498Szrj      P (X) = INSN_PRIORITY (X) - insn_delay (X) - baseECC (X)
2337*38fd1498Szrj      baseP = MAX { P (X) | baseECC (X) <= 0 }
2338*38fd1498Szrj 
2339*38fd1498Szrj    Then:
2340*38fd1498Szrj 
2341*38fd1498Szrj      ECC (X) = MAX (MIN (baseP - P (X), baseECC (X)), 0)
2342*38fd1498Szrj 
2343*38fd1498Szrj    Thus an instruction's effect on pressure is ignored if it has a high
2344*38fd1498Szrj    enough priority relative to the ones that don't increase pressure.
2345*38fd1498Szrj    Negative values of baseECC (X) do not increase the priority of X
2346*38fd1498Szrj    itself, but they do make it harder for other instructions to
2347*38fd1498Szrj    increase the pressure further.
2348*38fd1498Szrj 
2349*38fd1498Szrj    This pressure cost is deliberately timid.  The intention has been
2350*38fd1498Szrj    to choose a heuristic that rarely interferes with the normal list
2351*38fd1498Szrj    scheduler in cases where that scheduler would produce good code.
2352*38fd1498Szrj    We simply want to curb some of its worst excesses.  */
2353*38fd1498Szrj 
2354*38fd1498Szrj /* Return the cost of increasing the pressure in class CL from FROM to TO.
2355*38fd1498Szrj 
2356*38fd1498Szrj    Here we use the very simplistic cost model that every register above
2357*38fd1498Szrj    sched_class_regs_num[CL] has a spill cost of 1.  We could use other
2358*38fd1498Szrj    measures instead, such as one based on MEMORY_MOVE_COST.  However:
2359*38fd1498Szrj 
2360*38fd1498Szrj       (1) In order for an instruction to be scheduled, the higher cost
2361*38fd1498Szrj 	  would need to be justified in a single saving of that many stalls.
2362*38fd1498Szrj 	  This is overly pessimistic, because the benefit of spilling is
2363*38fd1498Szrj 	  often to avoid a sequence of several short stalls rather than
2364*38fd1498Szrj 	  a single long one.
2365*38fd1498Szrj 
2366*38fd1498Szrj       (2) The cost is still arbitrary.  Because we are not allocating
2367*38fd1498Szrj 	  registers during scheduling, we have no way of knowing for
2368*38fd1498Szrj 	  sure how many memory accesses will be required by each spill,
2369*38fd1498Szrj 	  where the spills will be placed within the block, or even
2370*38fd1498Szrj 	  which block(s) will contain the spills.
2371*38fd1498Szrj 
2372*38fd1498Szrj    So a higher cost than 1 is often too conservative in practice,
2373*38fd1498Szrj    forcing blocks to contain unnecessary stalls instead of spill code.
2374*38fd1498Szrj    The simple cost below seems to be the best compromise.  It reduces
2375*38fd1498Szrj    the interference with the normal list scheduler, which helps make
2376*38fd1498Szrj    it more suitable for a default-on option.  */
2377*38fd1498Szrj 
2378*38fd1498Szrj static int
model_spill_cost(int cl,int from,int to)2379*38fd1498Szrj model_spill_cost (int cl, int from, int to)
2380*38fd1498Szrj {
2381*38fd1498Szrj   from = MAX (from, sched_class_regs_num[cl]);
2382*38fd1498Szrj   return MAX (to, from) - from;
2383*38fd1498Szrj }
2384*38fd1498Szrj 
2385*38fd1498Szrj /* Return baseECC (ira_pressure_classes[PCI], POINT), given that
2386*38fd1498Szrj    P = curr_reg_pressure[ira_pressure_classes[PCI]] and that
2387*38fd1498Szrj    P' = P + DELTA.  */
2388*38fd1498Szrj 
2389*38fd1498Szrj static int
model_excess_group_cost(struct model_pressure_group * group,int point,int pci,int delta)2390*38fd1498Szrj model_excess_group_cost (struct model_pressure_group *group,
2391*38fd1498Szrj 			 int point, int pci, int delta)
2392*38fd1498Szrj {
2393*38fd1498Szrj   int pressure, cl;
2394*38fd1498Szrj 
2395*38fd1498Szrj   cl = ira_pressure_classes[pci];
2396*38fd1498Szrj   if (delta < 0 && point >= group->limits[pci].point)
2397*38fd1498Szrj     {
2398*38fd1498Szrj       pressure = MAX (group->limits[pci].orig_pressure,
2399*38fd1498Szrj 		      curr_reg_pressure[cl] + delta);
2400*38fd1498Szrj       return -model_spill_cost (cl, pressure, curr_reg_pressure[cl]);
2401*38fd1498Szrj     }
2402*38fd1498Szrj 
2403*38fd1498Szrj   if (delta > 0)
2404*38fd1498Szrj     {
2405*38fd1498Szrj       if (point > group->limits[pci].point)
2406*38fd1498Szrj 	pressure = group->limits[pci].pressure + delta;
2407*38fd1498Szrj       else
2408*38fd1498Szrj 	pressure = curr_reg_pressure[cl] + delta;
2409*38fd1498Szrj 
2410*38fd1498Szrj       if (pressure > group->limits[pci].pressure)
2411*38fd1498Szrj 	return model_spill_cost (cl, group->limits[pci].orig_pressure,
2412*38fd1498Szrj 				 pressure);
2413*38fd1498Szrj     }
2414*38fd1498Szrj 
2415*38fd1498Szrj   return 0;
2416*38fd1498Szrj }
2417*38fd1498Szrj 
2418*38fd1498Szrj /* Return baseECC (MODEL_INSN (INSN)).  Dump the costs to sched_dump
2419*38fd1498Szrj    if PRINT_P.  */
2420*38fd1498Szrj 
2421*38fd1498Szrj static int
model_excess_cost(rtx_insn * insn,bool print_p)2422*38fd1498Szrj model_excess_cost (rtx_insn *insn, bool print_p)
2423*38fd1498Szrj {
2424*38fd1498Szrj   int point, pci, cl, cost, this_cost, delta;
2425*38fd1498Szrj   struct reg_pressure_data *insn_reg_pressure;
2426*38fd1498Szrj   int insn_death[N_REG_CLASSES];
2427*38fd1498Szrj 
2428*38fd1498Szrj   calculate_reg_deaths (insn, insn_death);
2429*38fd1498Szrj   point = model_index (insn);
2430*38fd1498Szrj   insn_reg_pressure = INSN_REG_PRESSURE (insn);
2431*38fd1498Szrj   cost = 0;
2432*38fd1498Szrj 
2433*38fd1498Szrj   if (print_p)
2434*38fd1498Szrj     fprintf (sched_dump, ";;\t\t| %3d %4d | %4d %+3d |", point,
2435*38fd1498Szrj 	     INSN_UID (insn), INSN_PRIORITY (insn), insn_delay (insn));
2436*38fd1498Szrj 
2437*38fd1498Szrj   /* Sum up the individual costs for each register class.  */
2438*38fd1498Szrj   for (pci = 0; pci < ira_pressure_classes_num; pci++)
2439*38fd1498Szrj     {
2440*38fd1498Szrj       cl = ira_pressure_classes[pci];
2441*38fd1498Szrj       delta = insn_reg_pressure[pci].set_increase - insn_death[cl];
2442*38fd1498Szrj       this_cost = model_excess_group_cost (&model_before_pressure,
2443*38fd1498Szrj 					   point, pci, delta);
2444*38fd1498Szrj       cost += this_cost;
2445*38fd1498Szrj       if (print_p)
2446*38fd1498Szrj 	fprintf (sched_dump, " %s:[%d base cost %d]",
2447*38fd1498Szrj 		 reg_class_names[cl], delta, this_cost);
2448*38fd1498Szrj     }
2449*38fd1498Szrj 
2450*38fd1498Szrj   if (print_p)
2451*38fd1498Szrj     fprintf (sched_dump, "\n");
2452*38fd1498Szrj 
2453*38fd1498Szrj   return cost;
2454*38fd1498Szrj }
2455*38fd1498Szrj 
2456*38fd1498Szrj /* Dump the next points of maximum pressure for GROUP.  */
2457*38fd1498Szrj 
2458*38fd1498Szrj static void
model_dump_pressure_points(struct model_pressure_group * group)2459*38fd1498Szrj model_dump_pressure_points (struct model_pressure_group *group)
2460*38fd1498Szrj {
2461*38fd1498Szrj   int pci, cl;
2462*38fd1498Szrj 
2463*38fd1498Szrj   fprintf (sched_dump, ";;\t\t|  pressure points");
2464*38fd1498Szrj   for (pci = 0; pci < ira_pressure_classes_num; pci++)
2465*38fd1498Szrj     {
2466*38fd1498Szrj       cl = ira_pressure_classes[pci];
2467*38fd1498Szrj       fprintf (sched_dump, " %s:[%d->%d at ", reg_class_names[cl],
2468*38fd1498Szrj 	       curr_reg_pressure[cl], group->limits[pci].pressure);
2469*38fd1498Szrj       if (group->limits[pci].point < model_num_insns)
2470*38fd1498Szrj 	fprintf (sched_dump, "%d:%d]", group->limits[pci].point,
2471*38fd1498Szrj 		 INSN_UID (MODEL_INSN (group->limits[pci].point)));
2472*38fd1498Szrj       else
2473*38fd1498Szrj 	fprintf (sched_dump, "end]");
2474*38fd1498Szrj     }
2475*38fd1498Szrj   fprintf (sched_dump, "\n");
2476*38fd1498Szrj }
2477*38fd1498Szrj 
2478*38fd1498Szrj /* Set INSN_REG_PRESSURE_EXCESS_COST_CHANGE for INSNS[0...COUNT-1].  */
2479*38fd1498Szrj 
2480*38fd1498Szrj static void
model_set_excess_costs(rtx_insn ** insns,int count)2481*38fd1498Szrj model_set_excess_costs (rtx_insn **insns, int count)
2482*38fd1498Szrj {
2483*38fd1498Szrj   int i, cost, priority_base, priority;
2484*38fd1498Szrj   bool print_p;
2485*38fd1498Szrj 
2486*38fd1498Szrj   /* Record the baseECC value for each instruction in the model schedule,
2487*38fd1498Szrj      except that negative costs are converted to zero ones now rather than
2488*38fd1498Szrj      later.  Do not assign a cost to debug instructions, since they must
2489*38fd1498Szrj      not change code-generation decisions.  Experiments suggest we also
2490*38fd1498Szrj      get better results by not assigning a cost to instructions from
2491*38fd1498Szrj      a different block.
2492*38fd1498Szrj 
2493*38fd1498Szrj      Set PRIORITY_BASE to baseP in the block comment above.  This is the
2494*38fd1498Szrj      maximum priority of the "cheap" instructions, which should always
2495*38fd1498Szrj      include the next model instruction.  */
2496*38fd1498Szrj   priority_base = 0;
2497*38fd1498Szrj   print_p = false;
2498*38fd1498Szrj   for (i = 0; i < count; i++)
2499*38fd1498Szrj     if (INSN_MODEL_INDEX (insns[i]))
2500*38fd1498Szrj       {
2501*38fd1498Szrj 	if (sched_verbose >= 6 && !print_p)
2502*38fd1498Szrj 	  {
2503*38fd1498Szrj 	    fprintf (sched_dump, MODEL_BAR);
2504*38fd1498Szrj 	    fprintf (sched_dump, ";;\t\t| Pressure costs for ready queue\n");
2505*38fd1498Szrj 	    model_dump_pressure_points (&model_before_pressure);
2506*38fd1498Szrj 	    fprintf (sched_dump, MODEL_BAR);
2507*38fd1498Szrj 	    print_p = true;
2508*38fd1498Szrj 	  }
2509*38fd1498Szrj 	cost = model_excess_cost (insns[i], print_p);
2510*38fd1498Szrj 	if (cost <= 0)
2511*38fd1498Szrj 	  {
2512*38fd1498Szrj 	    priority = INSN_PRIORITY (insns[i]) - insn_delay (insns[i]) - cost;
2513*38fd1498Szrj 	    priority_base = MAX (priority_base, priority);
2514*38fd1498Szrj 	    cost = 0;
2515*38fd1498Szrj 	  }
2516*38fd1498Szrj 	INSN_REG_PRESSURE_EXCESS_COST_CHANGE (insns[i]) = cost;
2517*38fd1498Szrj       }
2518*38fd1498Szrj   if (print_p)
2519*38fd1498Szrj     fprintf (sched_dump, MODEL_BAR);
2520*38fd1498Szrj 
2521*38fd1498Szrj   /* Use MAX (baseECC, 0) and baseP to calculcate ECC for each
2522*38fd1498Szrj      instruction.  */
2523*38fd1498Szrj   for (i = 0; i < count; i++)
2524*38fd1498Szrj     {
2525*38fd1498Szrj       cost = INSN_REG_PRESSURE_EXCESS_COST_CHANGE (insns[i]);
2526*38fd1498Szrj       priority = INSN_PRIORITY (insns[i]) - insn_delay (insns[i]);
2527*38fd1498Szrj       if (cost > 0 && priority > priority_base)
2528*38fd1498Szrj 	{
2529*38fd1498Szrj 	  cost += priority_base - priority;
2530*38fd1498Szrj 	  INSN_REG_PRESSURE_EXCESS_COST_CHANGE (insns[i]) = MAX (cost, 0);
2531*38fd1498Szrj 	}
2532*38fd1498Szrj     }
2533*38fd1498Szrj }
2534*38fd1498Szrj 
2535*38fd1498Szrj 
2536*38fd1498Szrj /* Enum of rank_for_schedule heuristic decisions.  */
2537*38fd1498Szrj enum rfs_decision {
2538*38fd1498Szrj   RFS_LIVE_RANGE_SHRINK1, RFS_LIVE_RANGE_SHRINK2,
2539*38fd1498Szrj   RFS_SCHED_GROUP, RFS_PRESSURE_DELAY, RFS_PRESSURE_TICK,
2540*38fd1498Szrj   RFS_FEEDS_BACKTRACK_INSN, RFS_PRIORITY, RFS_SPECULATION,
2541*38fd1498Szrj   RFS_SCHED_RANK, RFS_LAST_INSN, RFS_PRESSURE_INDEX,
2542*38fd1498Szrj   RFS_DEP_COUNT, RFS_TIE, RFS_FUSION, RFS_N };
2543*38fd1498Szrj 
2544*38fd1498Szrj /* Corresponding strings for print outs.  */
2545*38fd1498Szrj static const char *rfs_str[RFS_N] = {
2546*38fd1498Szrj   "RFS_LIVE_RANGE_SHRINK1", "RFS_LIVE_RANGE_SHRINK2",
2547*38fd1498Szrj   "RFS_SCHED_GROUP", "RFS_PRESSURE_DELAY", "RFS_PRESSURE_TICK",
2548*38fd1498Szrj   "RFS_FEEDS_BACKTRACK_INSN", "RFS_PRIORITY", "RFS_SPECULATION",
2549*38fd1498Szrj   "RFS_SCHED_RANK", "RFS_LAST_INSN", "RFS_PRESSURE_INDEX",
2550*38fd1498Szrj   "RFS_DEP_COUNT", "RFS_TIE", "RFS_FUSION" };
2551*38fd1498Szrj 
2552*38fd1498Szrj /* Statistical breakdown of rank_for_schedule decisions.  */
2553*38fd1498Szrj struct rank_for_schedule_stats_t { unsigned stats[RFS_N]; };
2554*38fd1498Szrj static rank_for_schedule_stats_t rank_for_schedule_stats;
2555*38fd1498Szrj 
2556*38fd1498Szrj /* Return the result of comparing insns TMP and TMP2 and update
2557*38fd1498Szrj    Rank_For_Schedule statistics.  */
2558*38fd1498Szrj static int
rfs_result(enum rfs_decision decision,int result,rtx tmp,rtx tmp2)2559*38fd1498Szrj rfs_result (enum rfs_decision decision, int result, rtx tmp, rtx tmp2)
2560*38fd1498Szrj {
2561*38fd1498Szrj   ++rank_for_schedule_stats.stats[decision];
2562*38fd1498Szrj   if (result < 0)
2563*38fd1498Szrj     INSN_LAST_RFS_WIN (tmp) = decision;
2564*38fd1498Szrj   else if (result > 0)
2565*38fd1498Szrj     INSN_LAST_RFS_WIN (tmp2) = decision;
2566*38fd1498Szrj   else
2567*38fd1498Szrj     gcc_unreachable ();
2568*38fd1498Szrj   return result;
2569*38fd1498Szrj }
2570*38fd1498Szrj 
2571*38fd1498Szrj /* Sorting predicate to move DEBUG_INSNs to the top of ready list, while
2572*38fd1498Szrj    keeping normal insns in original order.  */
2573*38fd1498Szrj 
2574*38fd1498Szrj static int
rank_for_schedule_debug(const void * x,const void * y)2575*38fd1498Szrj rank_for_schedule_debug (const void *x, const void *y)
2576*38fd1498Szrj {
2577*38fd1498Szrj   rtx_insn *tmp = *(rtx_insn * const *) y;
2578*38fd1498Szrj   rtx_insn *tmp2 = *(rtx_insn * const *) x;
2579*38fd1498Szrj 
2580*38fd1498Szrj   /* Schedule debug insns as early as possible.  */
2581*38fd1498Szrj   if (DEBUG_INSN_P (tmp) && !DEBUG_INSN_P (tmp2))
2582*38fd1498Szrj     return -1;
2583*38fd1498Szrj   else if (!DEBUG_INSN_P (tmp) && DEBUG_INSN_P (tmp2))
2584*38fd1498Szrj     return 1;
2585*38fd1498Szrj   else if (DEBUG_INSN_P (tmp) && DEBUG_INSN_P (tmp2))
2586*38fd1498Szrj     return INSN_LUID (tmp) - INSN_LUID (tmp2);
2587*38fd1498Szrj   else
2588*38fd1498Szrj     return INSN_RFS_DEBUG_ORIG_ORDER (tmp2) - INSN_RFS_DEBUG_ORIG_ORDER (tmp);
2589*38fd1498Szrj }
2590*38fd1498Szrj 
2591*38fd1498Szrj /* Returns a positive value if x is preferred; returns a negative value if
2592*38fd1498Szrj    y is preferred.  Should never return 0, since that will make the sort
2593*38fd1498Szrj    unstable.  */
2594*38fd1498Szrj 
2595*38fd1498Szrj static int
rank_for_schedule(const void * x,const void * y)2596*38fd1498Szrj rank_for_schedule (const void *x, const void *y)
2597*38fd1498Szrj {
2598*38fd1498Szrj   rtx_insn *tmp = *(rtx_insn * const *) y;
2599*38fd1498Szrj   rtx_insn *tmp2 = *(rtx_insn * const *) x;
2600*38fd1498Szrj   int tmp_class, tmp2_class;
2601*38fd1498Szrj   int val, priority_val, info_val, diff;
2602*38fd1498Szrj 
2603*38fd1498Szrj   if (live_range_shrinkage_p)
2604*38fd1498Szrj     {
2605*38fd1498Szrj       /* Don't use SCHED_PRESSURE_MODEL -- it results in much worse
2606*38fd1498Szrj 	 code.  */
2607*38fd1498Szrj       gcc_assert (sched_pressure == SCHED_PRESSURE_WEIGHTED);
2608*38fd1498Szrj       if ((INSN_REG_PRESSURE_EXCESS_COST_CHANGE (tmp) < 0
2609*38fd1498Szrj 	   || INSN_REG_PRESSURE_EXCESS_COST_CHANGE (tmp2) < 0)
2610*38fd1498Szrj 	  && (diff = (INSN_REG_PRESSURE_EXCESS_COST_CHANGE (tmp)
2611*38fd1498Szrj 		      - INSN_REG_PRESSURE_EXCESS_COST_CHANGE (tmp2))) != 0)
2612*38fd1498Szrj 	return rfs_result (RFS_LIVE_RANGE_SHRINK1, diff, tmp, tmp2);
2613*38fd1498Szrj       /* Sort by INSN_LUID (original insn order), so that we make the
2614*38fd1498Szrj 	 sort stable.  This minimizes instruction movement, thus
2615*38fd1498Szrj 	 minimizing sched's effect on debugging and cross-jumping.  */
2616*38fd1498Szrj       return rfs_result (RFS_LIVE_RANGE_SHRINK2,
2617*38fd1498Szrj 			 INSN_LUID (tmp) - INSN_LUID (tmp2), tmp, tmp2);
2618*38fd1498Szrj     }
2619*38fd1498Szrj 
2620*38fd1498Szrj   /* The insn in a schedule group should be issued the first.  */
2621*38fd1498Szrj   if (flag_sched_group_heuristic &&
2622*38fd1498Szrj       SCHED_GROUP_P (tmp) != SCHED_GROUP_P (tmp2))
2623*38fd1498Szrj     return rfs_result (RFS_SCHED_GROUP, SCHED_GROUP_P (tmp2) ? 1 : -1,
2624*38fd1498Szrj 		       tmp, tmp2);
2625*38fd1498Szrj 
2626*38fd1498Szrj   /* Make sure that priority of TMP and TMP2 are initialized.  */
2627*38fd1498Szrj   gcc_assert (INSN_PRIORITY_KNOWN (tmp) && INSN_PRIORITY_KNOWN (tmp2));
2628*38fd1498Szrj 
2629*38fd1498Szrj   if (sched_fusion)
2630*38fd1498Szrj     {
2631*38fd1498Szrj       /* The instruction that has the same fusion priority as the last
2632*38fd1498Szrj 	 instruction is the instruction we picked next.  If that is not
2633*38fd1498Szrj 	 the case, we sort ready list firstly by fusion priority, then
2634*38fd1498Szrj 	 by priority, and at last by INSN_LUID.  */
2635*38fd1498Szrj       int a = INSN_FUSION_PRIORITY (tmp);
2636*38fd1498Szrj       int b = INSN_FUSION_PRIORITY (tmp2);
2637*38fd1498Szrj       int last = -1;
2638*38fd1498Szrj 
2639*38fd1498Szrj       if (last_nondebug_scheduled_insn
2640*38fd1498Szrj 	  && !NOTE_P (last_nondebug_scheduled_insn)
2641*38fd1498Szrj 	  && BLOCK_FOR_INSN (tmp)
2642*38fd1498Szrj 	       == BLOCK_FOR_INSN (last_nondebug_scheduled_insn))
2643*38fd1498Szrj 	last = INSN_FUSION_PRIORITY (last_nondebug_scheduled_insn);
2644*38fd1498Szrj 
2645*38fd1498Szrj       if (a != last && b != last)
2646*38fd1498Szrj 	{
2647*38fd1498Szrj 	  if (a == b)
2648*38fd1498Szrj 	    {
2649*38fd1498Szrj 	      a = INSN_PRIORITY (tmp);
2650*38fd1498Szrj 	      b = INSN_PRIORITY (tmp2);
2651*38fd1498Szrj 	    }
2652*38fd1498Szrj 	  if (a != b)
2653*38fd1498Szrj 	    return rfs_result (RFS_FUSION, b - a, tmp, tmp2);
2654*38fd1498Szrj 	  else
2655*38fd1498Szrj 	    return rfs_result (RFS_FUSION,
2656*38fd1498Szrj 			       INSN_LUID (tmp) - INSN_LUID (tmp2), tmp, tmp2);
2657*38fd1498Szrj 	}
2658*38fd1498Szrj       else if (a == b)
2659*38fd1498Szrj 	{
2660*38fd1498Szrj 	  gcc_assert (last_nondebug_scheduled_insn
2661*38fd1498Szrj 		      && !NOTE_P (last_nondebug_scheduled_insn));
2662*38fd1498Szrj 	  last = INSN_PRIORITY (last_nondebug_scheduled_insn);
2663*38fd1498Szrj 
2664*38fd1498Szrj 	  a = abs (INSN_PRIORITY (tmp) - last);
2665*38fd1498Szrj 	  b = abs (INSN_PRIORITY (tmp2) - last);
2666*38fd1498Szrj 	  if (a != b)
2667*38fd1498Szrj 	    return rfs_result (RFS_FUSION, a - b, tmp, tmp2);
2668*38fd1498Szrj 	  else
2669*38fd1498Szrj 	    return rfs_result (RFS_FUSION,
2670*38fd1498Szrj 			       INSN_LUID (tmp) - INSN_LUID (tmp2), tmp, tmp2);
2671*38fd1498Szrj 	}
2672*38fd1498Szrj       else if (a == last)
2673*38fd1498Szrj 	return rfs_result (RFS_FUSION, -1, tmp, tmp2);
2674*38fd1498Szrj       else
2675*38fd1498Szrj 	return rfs_result (RFS_FUSION, 1, tmp, tmp2);
2676*38fd1498Szrj     }
2677*38fd1498Szrj 
2678*38fd1498Szrj   if (sched_pressure != SCHED_PRESSURE_NONE)
2679*38fd1498Szrj     {
2680*38fd1498Szrj       /* Prefer insn whose scheduling results in the smallest register
2681*38fd1498Szrj 	 pressure excess.  */
2682*38fd1498Szrj       if ((diff = (INSN_REG_PRESSURE_EXCESS_COST_CHANGE (tmp)
2683*38fd1498Szrj 		   + insn_delay (tmp)
2684*38fd1498Szrj 		   - INSN_REG_PRESSURE_EXCESS_COST_CHANGE (tmp2)
2685*38fd1498Szrj 		   - insn_delay (tmp2))))
2686*38fd1498Szrj 	return rfs_result (RFS_PRESSURE_DELAY, diff, tmp, tmp2);
2687*38fd1498Szrj     }
2688*38fd1498Szrj 
2689*38fd1498Szrj   if (sched_pressure != SCHED_PRESSURE_NONE
2690*38fd1498Szrj       && (INSN_TICK (tmp2) > clock_var || INSN_TICK (tmp) > clock_var)
2691*38fd1498Szrj       && INSN_TICK (tmp2) != INSN_TICK (tmp))
2692*38fd1498Szrj     {
2693*38fd1498Szrj       diff = INSN_TICK (tmp) - INSN_TICK (tmp2);
2694*38fd1498Szrj       return rfs_result (RFS_PRESSURE_TICK, diff, tmp, tmp2);
2695*38fd1498Szrj     }
2696*38fd1498Szrj 
2697*38fd1498Szrj   /* If we are doing backtracking in this schedule, prefer insns that
2698*38fd1498Szrj      have forward dependencies with negative cost against an insn that
2699*38fd1498Szrj      was already scheduled.  */
2700*38fd1498Szrj   if (current_sched_info->flags & DO_BACKTRACKING)
2701*38fd1498Szrj     {
2702*38fd1498Szrj       priority_val = FEEDS_BACKTRACK_INSN (tmp2) - FEEDS_BACKTRACK_INSN (tmp);
2703*38fd1498Szrj       if (priority_val)
2704*38fd1498Szrj 	return rfs_result (RFS_FEEDS_BACKTRACK_INSN, priority_val, tmp, tmp2);
2705*38fd1498Szrj     }
2706*38fd1498Szrj 
2707*38fd1498Szrj   /* Prefer insn with higher priority.  */
2708*38fd1498Szrj   priority_val = INSN_PRIORITY (tmp2) - INSN_PRIORITY (tmp);
2709*38fd1498Szrj 
2710*38fd1498Szrj   if (flag_sched_critical_path_heuristic && priority_val)
2711*38fd1498Szrj     return rfs_result (RFS_PRIORITY, priority_val, tmp, tmp2);
2712*38fd1498Szrj 
2713*38fd1498Szrj   if (PARAM_VALUE (PARAM_SCHED_AUTOPREF_QUEUE_DEPTH) >= 0)
2714*38fd1498Szrj     {
2715*38fd1498Szrj       int autopref = autopref_rank_for_schedule (tmp, tmp2);
2716*38fd1498Szrj       if (autopref != 0)
2717*38fd1498Szrj 	return autopref;
2718*38fd1498Szrj     }
2719*38fd1498Szrj 
2720*38fd1498Szrj   /* Prefer speculative insn with greater dependencies weakness.  */
2721*38fd1498Szrj   if (flag_sched_spec_insn_heuristic && spec_info)
2722*38fd1498Szrj     {
2723*38fd1498Szrj       ds_t ds1, ds2;
2724*38fd1498Szrj       dw_t dw1, dw2;
2725*38fd1498Szrj       int dw;
2726*38fd1498Szrj 
2727*38fd1498Szrj       ds1 = TODO_SPEC (tmp) & SPECULATIVE;
2728*38fd1498Szrj       if (ds1)
2729*38fd1498Szrj 	dw1 = ds_weak (ds1);
2730*38fd1498Szrj       else
2731*38fd1498Szrj 	dw1 = NO_DEP_WEAK;
2732*38fd1498Szrj 
2733*38fd1498Szrj       ds2 = TODO_SPEC (tmp2) & SPECULATIVE;
2734*38fd1498Szrj       if (ds2)
2735*38fd1498Szrj 	dw2 = ds_weak (ds2);
2736*38fd1498Szrj       else
2737*38fd1498Szrj 	dw2 = NO_DEP_WEAK;
2738*38fd1498Szrj 
2739*38fd1498Szrj       dw = dw2 - dw1;
2740*38fd1498Szrj       if (dw > (NO_DEP_WEAK / 8) || dw < -(NO_DEP_WEAK / 8))
2741*38fd1498Szrj 	return rfs_result (RFS_SPECULATION, dw, tmp, tmp2);
2742*38fd1498Szrj     }
2743*38fd1498Szrj 
2744*38fd1498Szrj   info_val = (*current_sched_info->rank) (tmp, tmp2);
2745*38fd1498Szrj   if (flag_sched_rank_heuristic && info_val)
2746*38fd1498Szrj     return rfs_result (RFS_SCHED_RANK, info_val, tmp, tmp2);
2747*38fd1498Szrj 
2748*38fd1498Szrj   /* Compare insns based on their relation to the last scheduled
2749*38fd1498Szrj      non-debug insn.  */
2750*38fd1498Szrj   if (flag_sched_last_insn_heuristic && last_nondebug_scheduled_insn)
2751*38fd1498Szrj     {
2752*38fd1498Szrj       dep_t dep1;
2753*38fd1498Szrj       dep_t dep2;
2754*38fd1498Szrj       rtx_insn *last = last_nondebug_scheduled_insn;
2755*38fd1498Szrj 
2756*38fd1498Szrj       /* Classify the instructions into three classes:
2757*38fd1498Szrj          1) Data dependent on last schedule insn.
2758*38fd1498Szrj          2) Anti/Output dependent on last scheduled insn.
2759*38fd1498Szrj          3) Independent of last scheduled insn, or has latency of one.
2760*38fd1498Szrj          Choose the insn from the highest numbered class if different.  */
2761*38fd1498Szrj       dep1 = sd_find_dep_between (last, tmp, true);
2762*38fd1498Szrj 
2763*38fd1498Szrj       if (dep1 == NULL || dep_cost (dep1) == 1)
2764*38fd1498Szrj 	tmp_class = 3;
2765*38fd1498Szrj       else if (/* Data dependence.  */
2766*38fd1498Szrj 	       DEP_TYPE (dep1) == REG_DEP_TRUE)
2767*38fd1498Szrj 	tmp_class = 1;
2768*38fd1498Szrj       else
2769*38fd1498Szrj 	tmp_class = 2;
2770*38fd1498Szrj 
2771*38fd1498Szrj       dep2 = sd_find_dep_between (last, tmp2, true);
2772*38fd1498Szrj 
2773*38fd1498Szrj       if (dep2 == NULL || dep_cost (dep2)  == 1)
2774*38fd1498Szrj 	tmp2_class = 3;
2775*38fd1498Szrj       else if (/* Data dependence.  */
2776*38fd1498Szrj 	       DEP_TYPE (dep2) == REG_DEP_TRUE)
2777*38fd1498Szrj 	tmp2_class = 1;
2778*38fd1498Szrj       else
2779*38fd1498Szrj 	tmp2_class = 2;
2780*38fd1498Szrj 
2781*38fd1498Szrj       if ((val = tmp2_class - tmp_class))
2782*38fd1498Szrj 	return rfs_result (RFS_LAST_INSN, val, tmp, tmp2);
2783*38fd1498Szrj     }
2784*38fd1498Szrj 
2785*38fd1498Szrj   /* Prefer instructions that occur earlier in the model schedule.  */
2786*38fd1498Szrj   if (sched_pressure == SCHED_PRESSURE_MODEL)
2787*38fd1498Szrj     {
2788*38fd1498Szrj       diff = model_index (tmp) - model_index (tmp2);
2789*38fd1498Szrj       if (diff != 0)
2790*38fd1498Szrj 	return rfs_result (RFS_PRESSURE_INDEX, diff, tmp, tmp2);
2791*38fd1498Szrj     }
2792*38fd1498Szrj 
2793*38fd1498Szrj   /* Prefer the insn which has more later insns that depend on it.
2794*38fd1498Szrj      This gives the scheduler more freedom when scheduling later
2795*38fd1498Szrj      instructions at the expense of added register pressure.  */
2796*38fd1498Szrj 
2797*38fd1498Szrj   val = (dep_list_size (tmp2, SD_LIST_FORW)
2798*38fd1498Szrj 	 - dep_list_size (tmp, SD_LIST_FORW));
2799*38fd1498Szrj 
2800*38fd1498Szrj   if (flag_sched_dep_count_heuristic && val != 0)
2801*38fd1498Szrj     return rfs_result (RFS_DEP_COUNT, val, tmp, tmp2);
2802*38fd1498Szrj 
2803*38fd1498Szrj   /* If insns are equally good, sort by INSN_LUID (original insn order),
2804*38fd1498Szrj      so that we make the sort stable.  This minimizes instruction movement,
2805*38fd1498Szrj      thus minimizing sched's effect on debugging and cross-jumping.  */
2806*38fd1498Szrj   return rfs_result (RFS_TIE, INSN_LUID (tmp) - INSN_LUID (tmp2), tmp, tmp2);
2807*38fd1498Szrj }
2808*38fd1498Szrj 
2809*38fd1498Szrj /* Resort the array A in which only element at index N may be out of order.  */
2810*38fd1498Szrj 
2811*38fd1498Szrj HAIFA_INLINE static void
swap_sort(rtx_insn ** a,int n)2812*38fd1498Szrj swap_sort (rtx_insn **a, int n)
2813*38fd1498Szrj {
2814*38fd1498Szrj   rtx_insn *insn = a[n - 1];
2815*38fd1498Szrj   int i = n - 2;
2816*38fd1498Szrj 
2817*38fd1498Szrj   while (i >= 0 && rank_for_schedule (a + i, &insn) >= 0)
2818*38fd1498Szrj     {
2819*38fd1498Szrj       a[i + 1] = a[i];
2820*38fd1498Szrj       i -= 1;
2821*38fd1498Szrj     }
2822*38fd1498Szrj   a[i + 1] = insn;
2823*38fd1498Szrj }
2824*38fd1498Szrj 
2825*38fd1498Szrj /* Add INSN to the insn queue so that it can be executed at least
2826*38fd1498Szrj    N_CYCLES after the currently executing insn.  Preserve insns
2827*38fd1498Szrj    chain for debugging purposes.  REASON will be printed in debugging
2828*38fd1498Szrj    output.  */
2829*38fd1498Szrj 
2830*38fd1498Szrj HAIFA_INLINE static void
queue_insn(rtx_insn * insn,int n_cycles,const char * reason)2831*38fd1498Szrj queue_insn (rtx_insn *insn, int n_cycles, const char *reason)
2832*38fd1498Szrj {
2833*38fd1498Szrj   int next_q = NEXT_Q_AFTER (q_ptr, n_cycles);
2834*38fd1498Szrj   rtx_insn_list *link = alloc_INSN_LIST (insn, insn_queue[next_q]);
2835*38fd1498Szrj   int new_tick;
2836*38fd1498Szrj 
2837*38fd1498Szrj   gcc_assert (n_cycles <= max_insn_queue_index);
2838*38fd1498Szrj   gcc_assert (!DEBUG_INSN_P (insn));
2839*38fd1498Szrj 
2840*38fd1498Szrj   insn_queue[next_q] = link;
2841*38fd1498Szrj   q_size += 1;
2842*38fd1498Szrj 
2843*38fd1498Szrj   if (sched_verbose >= 2)
2844*38fd1498Szrj     {
2845*38fd1498Szrj       fprintf (sched_dump, ";;\t\tReady-->Q: insn %s: ",
2846*38fd1498Szrj 	       (*current_sched_info->print_insn) (insn, 0));
2847*38fd1498Szrj 
2848*38fd1498Szrj       fprintf (sched_dump, "queued for %d cycles (%s).\n", n_cycles, reason);
2849*38fd1498Szrj     }
2850*38fd1498Szrj 
2851*38fd1498Szrj   QUEUE_INDEX (insn) = next_q;
2852*38fd1498Szrj 
2853*38fd1498Szrj   if (current_sched_info->flags & DO_BACKTRACKING)
2854*38fd1498Szrj     {
2855*38fd1498Szrj       new_tick = clock_var + n_cycles;
2856*38fd1498Szrj       if (INSN_TICK (insn) == INVALID_TICK || INSN_TICK (insn) < new_tick)
2857*38fd1498Szrj 	INSN_TICK (insn) = new_tick;
2858*38fd1498Szrj 
2859*38fd1498Szrj       if (INSN_EXACT_TICK (insn) != INVALID_TICK
2860*38fd1498Szrj 	  && INSN_EXACT_TICK (insn) < clock_var + n_cycles)
2861*38fd1498Szrj 	{
2862*38fd1498Szrj 	  must_backtrack = true;
2863*38fd1498Szrj 	  if (sched_verbose >= 2)
2864*38fd1498Szrj 	    fprintf (sched_dump, ";;\t\tcausing a backtrack.\n");
2865*38fd1498Szrj 	}
2866*38fd1498Szrj     }
2867*38fd1498Szrj }
2868*38fd1498Szrj 
2869*38fd1498Szrj /* Remove INSN from queue.  */
2870*38fd1498Szrj static void
queue_remove(rtx_insn * insn)2871*38fd1498Szrj queue_remove (rtx_insn *insn)
2872*38fd1498Szrj {
2873*38fd1498Szrj   gcc_assert (QUEUE_INDEX (insn) >= 0);
2874*38fd1498Szrj   remove_free_INSN_LIST_elem (insn, &insn_queue[QUEUE_INDEX (insn)]);
2875*38fd1498Szrj   q_size--;
2876*38fd1498Szrj   QUEUE_INDEX (insn) = QUEUE_NOWHERE;
2877*38fd1498Szrj }
2878*38fd1498Szrj 
2879*38fd1498Szrj /* Return a pointer to the bottom of the ready list, i.e. the insn
2880*38fd1498Szrj    with the lowest priority.  */
2881*38fd1498Szrj 
2882*38fd1498Szrj rtx_insn **
ready_lastpos(struct ready_list * ready)2883*38fd1498Szrj ready_lastpos (struct ready_list *ready)
2884*38fd1498Szrj {
2885*38fd1498Szrj   gcc_assert (ready->n_ready >= 1);
2886*38fd1498Szrj   return ready->vec + ready->first - ready->n_ready + 1;
2887*38fd1498Szrj }
2888*38fd1498Szrj 
2889*38fd1498Szrj /* Add an element INSN to the ready list so that it ends up with the
2890*38fd1498Szrj    lowest/highest priority depending on FIRST_P.  */
2891*38fd1498Szrj 
2892*38fd1498Szrj HAIFA_INLINE static void
ready_add(struct ready_list * ready,rtx_insn * insn,bool first_p)2893*38fd1498Szrj ready_add (struct ready_list *ready, rtx_insn *insn, bool first_p)
2894*38fd1498Szrj {
2895*38fd1498Szrj   if (!first_p)
2896*38fd1498Szrj     {
2897*38fd1498Szrj       if (ready->first == ready->n_ready)
2898*38fd1498Szrj 	{
2899*38fd1498Szrj 	  memmove (ready->vec + ready->veclen - ready->n_ready,
2900*38fd1498Szrj 		   ready_lastpos (ready),
2901*38fd1498Szrj 		   ready->n_ready * sizeof (rtx));
2902*38fd1498Szrj 	  ready->first = ready->veclen - 1;
2903*38fd1498Szrj 	}
2904*38fd1498Szrj       ready->vec[ready->first - ready->n_ready] = insn;
2905*38fd1498Szrj     }
2906*38fd1498Szrj   else
2907*38fd1498Szrj     {
2908*38fd1498Szrj       if (ready->first == ready->veclen - 1)
2909*38fd1498Szrj 	{
2910*38fd1498Szrj 	  if (ready->n_ready)
2911*38fd1498Szrj 	    /* ready_lastpos() fails when called with (ready->n_ready == 0).  */
2912*38fd1498Szrj 	    memmove (ready->vec + ready->veclen - ready->n_ready - 1,
2913*38fd1498Szrj 		     ready_lastpos (ready),
2914*38fd1498Szrj 		     ready->n_ready * sizeof (rtx));
2915*38fd1498Szrj 	  ready->first = ready->veclen - 2;
2916*38fd1498Szrj 	}
2917*38fd1498Szrj       ready->vec[++(ready->first)] = insn;
2918*38fd1498Szrj     }
2919*38fd1498Szrj 
2920*38fd1498Szrj   ready->n_ready++;
2921*38fd1498Szrj   if (DEBUG_INSN_P (insn))
2922*38fd1498Szrj     ready->n_debug++;
2923*38fd1498Szrj 
2924*38fd1498Szrj   gcc_assert (QUEUE_INDEX (insn) != QUEUE_READY);
2925*38fd1498Szrj   QUEUE_INDEX (insn) = QUEUE_READY;
2926*38fd1498Szrj 
2927*38fd1498Szrj   if (INSN_EXACT_TICK (insn) != INVALID_TICK
2928*38fd1498Szrj       && INSN_EXACT_TICK (insn) < clock_var)
2929*38fd1498Szrj     {
2930*38fd1498Szrj       must_backtrack = true;
2931*38fd1498Szrj     }
2932*38fd1498Szrj }
2933*38fd1498Szrj 
2934*38fd1498Szrj /* Remove the element with the highest priority from the ready list and
2935*38fd1498Szrj    return it.  */
2936*38fd1498Szrj 
2937*38fd1498Szrj HAIFA_INLINE static rtx_insn *
ready_remove_first(struct ready_list * ready)2938*38fd1498Szrj ready_remove_first (struct ready_list *ready)
2939*38fd1498Szrj {
2940*38fd1498Szrj   rtx_insn *t;
2941*38fd1498Szrj 
2942*38fd1498Szrj   gcc_assert (ready->n_ready);
2943*38fd1498Szrj   t = ready->vec[ready->first--];
2944*38fd1498Szrj   ready->n_ready--;
2945*38fd1498Szrj   if (DEBUG_INSN_P (t))
2946*38fd1498Szrj     ready->n_debug--;
2947*38fd1498Szrj   /* If the queue becomes empty, reset it.  */
2948*38fd1498Szrj   if (ready->n_ready == 0)
2949*38fd1498Szrj     ready->first = ready->veclen - 1;
2950*38fd1498Szrj 
2951*38fd1498Szrj   gcc_assert (QUEUE_INDEX (t) == QUEUE_READY);
2952*38fd1498Szrj   QUEUE_INDEX (t) = QUEUE_NOWHERE;
2953*38fd1498Szrj 
2954*38fd1498Szrj   return t;
2955*38fd1498Szrj }
2956*38fd1498Szrj 
2957*38fd1498Szrj /* The following code implements multi-pass scheduling for the first
2958*38fd1498Szrj    cycle.  In other words, we will try to choose ready insn which
2959*38fd1498Szrj    permits to start maximum number of insns on the same cycle.  */
2960*38fd1498Szrj 
2961*38fd1498Szrj /* Return a pointer to the element INDEX from the ready.  INDEX for
2962*38fd1498Szrj    insn with the highest priority is 0, and the lowest priority has
2963*38fd1498Szrj    N_READY - 1.  */
2964*38fd1498Szrj 
2965*38fd1498Szrj rtx_insn *
ready_element(struct ready_list * ready,int index)2966*38fd1498Szrj ready_element (struct ready_list *ready, int index)
2967*38fd1498Szrj {
2968*38fd1498Szrj   gcc_assert (ready->n_ready && index < ready->n_ready);
2969*38fd1498Szrj 
2970*38fd1498Szrj   return ready->vec[ready->first - index];
2971*38fd1498Szrj }
2972*38fd1498Szrj 
2973*38fd1498Szrj /* Remove the element INDEX from the ready list and return it.  INDEX
2974*38fd1498Szrj    for insn with the highest priority is 0, and the lowest priority
2975*38fd1498Szrj    has N_READY - 1.  */
2976*38fd1498Szrj 
2977*38fd1498Szrj HAIFA_INLINE static rtx_insn *
ready_remove(struct ready_list * ready,int index)2978*38fd1498Szrj ready_remove (struct ready_list *ready, int index)
2979*38fd1498Szrj {
2980*38fd1498Szrj   rtx_insn *t;
2981*38fd1498Szrj   int i;
2982*38fd1498Szrj 
2983*38fd1498Szrj   if (index == 0)
2984*38fd1498Szrj     return ready_remove_first (ready);
2985*38fd1498Szrj   gcc_assert (ready->n_ready && index < ready->n_ready);
2986*38fd1498Szrj   t = ready->vec[ready->first - index];
2987*38fd1498Szrj   ready->n_ready--;
2988*38fd1498Szrj   if (DEBUG_INSN_P (t))
2989*38fd1498Szrj     ready->n_debug--;
2990*38fd1498Szrj   for (i = index; i < ready->n_ready; i++)
2991*38fd1498Szrj     ready->vec[ready->first - i] = ready->vec[ready->first - i - 1];
2992*38fd1498Szrj   QUEUE_INDEX (t) = QUEUE_NOWHERE;
2993*38fd1498Szrj   return t;
2994*38fd1498Szrj }
2995*38fd1498Szrj 
2996*38fd1498Szrj /* Remove INSN from the ready list.  */
2997*38fd1498Szrj static void
ready_remove_insn(rtx_insn * insn)2998*38fd1498Szrj ready_remove_insn (rtx_insn *insn)
2999*38fd1498Szrj {
3000*38fd1498Szrj   int i;
3001*38fd1498Szrj 
3002*38fd1498Szrj   for (i = 0; i < readyp->n_ready; i++)
3003*38fd1498Szrj     if (ready_element (readyp, i) == insn)
3004*38fd1498Szrj       {
3005*38fd1498Szrj         ready_remove (readyp, i);
3006*38fd1498Szrj         return;
3007*38fd1498Szrj       }
3008*38fd1498Szrj   gcc_unreachable ();
3009*38fd1498Szrj }
3010*38fd1498Szrj 
3011*38fd1498Szrj /* Calculate difference of two statistics set WAS and NOW.
3012*38fd1498Szrj    Result returned in WAS.  */
3013*38fd1498Szrj static void
rank_for_schedule_stats_diff(rank_for_schedule_stats_t * was,const rank_for_schedule_stats_t * now)3014*38fd1498Szrj rank_for_schedule_stats_diff (rank_for_schedule_stats_t *was,
3015*38fd1498Szrj 			      const rank_for_schedule_stats_t *now)
3016*38fd1498Szrj {
3017*38fd1498Szrj   for (int i = 0; i < RFS_N; ++i)
3018*38fd1498Szrj     was->stats[i] = now->stats[i] - was->stats[i];
3019*38fd1498Szrj }
3020*38fd1498Szrj 
3021*38fd1498Szrj /* Print rank_for_schedule statistics.  */
3022*38fd1498Szrj static void
print_rank_for_schedule_stats(const char * prefix,const rank_for_schedule_stats_t * stats,struct ready_list * ready)3023*38fd1498Szrj print_rank_for_schedule_stats (const char *prefix,
3024*38fd1498Szrj 			       const rank_for_schedule_stats_t *stats,
3025*38fd1498Szrj 			       struct ready_list *ready)
3026*38fd1498Szrj {
3027*38fd1498Szrj   for (int i = 0; i < RFS_N; ++i)
3028*38fd1498Szrj     if (stats->stats[i])
3029*38fd1498Szrj       {
3030*38fd1498Szrj 	fprintf (sched_dump, "%s%20s: %u", prefix, rfs_str[i], stats->stats[i]);
3031*38fd1498Szrj 
3032*38fd1498Szrj 	if (ready != NULL)
3033*38fd1498Szrj 	  /* Print out insns that won due to RFS_<I>.  */
3034*38fd1498Szrj 	  {
3035*38fd1498Szrj 	    rtx_insn **p = ready_lastpos (ready);
3036*38fd1498Szrj 
3037*38fd1498Szrj 	    fprintf (sched_dump, ":");
3038*38fd1498Szrj 	    /* Start with 1 since least-priority insn didn't have any wins.  */
3039*38fd1498Szrj 	    for (int j = 1; j < ready->n_ready; ++j)
3040*38fd1498Szrj 	      if (INSN_LAST_RFS_WIN (p[j]) == i)
3041*38fd1498Szrj 		fprintf (sched_dump, " %s",
3042*38fd1498Szrj 			 (*current_sched_info->print_insn) (p[j], 0));
3043*38fd1498Szrj 	  }
3044*38fd1498Szrj 	fprintf (sched_dump, "\n");
3045*38fd1498Szrj       }
3046*38fd1498Szrj }
3047*38fd1498Szrj 
3048*38fd1498Szrj /* Separate DEBUG_INSNS from normal insns.  DEBUG_INSNs go to the end
3049*38fd1498Szrj    of array.  */
3050*38fd1498Szrj static void
ready_sort_debug(struct ready_list * ready)3051*38fd1498Szrj ready_sort_debug (struct ready_list *ready)
3052*38fd1498Szrj {
3053*38fd1498Szrj   int i;
3054*38fd1498Szrj   rtx_insn **first = ready_lastpos (ready);
3055*38fd1498Szrj 
3056*38fd1498Szrj   for (i = 0; i < ready->n_ready; ++i)
3057*38fd1498Szrj     if (!DEBUG_INSN_P (first[i]))
3058*38fd1498Szrj       INSN_RFS_DEBUG_ORIG_ORDER (first[i]) = i;
3059*38fd1498Szrj 
3060*38fd1498Szrj   qsort (first, ready->n_ready, sizeof (rtx), rank_for_schedule_debug);
3061*38fd1498Szrj }
3062*38fd1498Szrj 
3063*38fd1498Szrj /* Sort non-debug insns in the ready list READY by ascending priority.
3064*38fd1498Szrj    Assumes that all debug insns are separated from the real insns.  */
3065*38fd1498Szrj static void
ready_sort_real(struct ready_list * ready)3066*38fd1498Szrj ready_sort_real (struct ready_list *ready)
3067*38fd1498Szrj {
3068*38fd1498Szrj   int i;
3069*38fd1498Szrj   rtx_insn **first = ready_lastpos (ready);
3070*38fd1498Szrj   int n_ready_real = ready->n_ready - ready->n_debug;
3071*38fd1498Szrj 
3072*38fd1498Szrj   if (sched_pressure == SCHED_PRESSURE_WEIGHTED)
3073*38fd1498Szrj     for (i = 0; i < n_ready_real; ++i)
3074*38fd1498Szrj       setup_insn_reg_pressure_info (first[i]);
3075*38fd1498Szrj   else if (sched_pressure == SCHED_PRESSURE_MODEL
3076*38fd1498Szrj 	   && model_curr_point < model_num_insns)
3077*38fd1498Szrj     model_set_excess_costs (first, n_ready_real);
3078*38fd1498Szrj 
3079*38fd1498Szrj   rank_for_schedule_stats_t stats1;
3080*38fd1498Szrj   if (sched_verbose >= 4)
3081*38fd1498Szrj     stats1 = rank_for_schedule_stats;
3082*38fd1498Szrj 
3083*38fd1498Szrj   if (n_ready_real == 2)
3084*38fd1498Szrj     swap_sort (first, n_ready_real);
3085*38fd1498Szrj   else if (n_ready_real > 2)
3086*38fd1498Szrj     qsort (first, n_ready_real, sizeof (rtx), rank_for_schedule);
3087*38fd1498Szrj 
3088*38fd1498Szrj   if (sched_verbose >= 4)
3089*38fd1498Szrj     {
3090*38fd1498Szrj       rank_for_schedule_stats_diff (&stats1, &rank_for_schedule_stats);
3091*38fd1498Szrj       print_rank_for_schedule_stats (";;\t\t", &stats1, ready);
3092*38fd1498Szrj     }
3093*38fd1498Szrj }
3094*38fd1498Szrj 
3095*38fd1498Szrj /* Sort the ready list READY by ascending priority.  */
3096*38fd1498Szrj static void
ready_sort(struct ready_list * ready)3097*38fd1498Szrj ready_sort (struct ready_list *ready)
3098*38fd1498Szrj {
3099*38fd1498Szrj   if (ready->n_debug > 0)
3100*38fd1498Szrj     ready_sort_debug (ready);
3101*38fd1498Szrj   else
3102*38fd1498Szrj     ready_sort_real (ready);
3103*38fd1498Szrj }
3104*38fd1498Szrj 
3105*38fd1498Szrj /* PREV is an insn that is ready to execute.  Adjust its priority if that
3106*38fd1498Szrj    will help shorten or lengthen register lifetimes as appropriate.  Also
3107*38fd1498Szrj    provide a hook for the target to tweak itself.  */
3108*38fd1498Szrj 
3109*38fd1498Szrj HAIFA_INLINE static void
adjust_priority(rtx_insn * prev)3110*38fd1498Szrj adjust_priority (rtx_insn *prev)
3111*38fd1498Szrj {
3112*38fd1498Szrj   /* ??? There used to be code here to try and estimate how an insn
3113*38fd1498Szrj      affected register lifetimes, but it did it by looking at REG_DEAD
3114*38fd1498Szrj      notes, which we removed in schedule_region.  Nor did it try to
3115*38fd1498Szrj      take into account register pressure or anything useful like that.
3116*38fd1498Szrj 
3117*38fd1498Szrj      Revisit when we have a machine model to work with and not before.  */
3118*38fd1498Szrj 
3119*38fd1498Szrj   if (targetm.sched.adjust_priority)
3120*38fd1498Szrj     INSN_PRIORITY (prev) =
3121*38fd1498Szrj       targetm.sched.adjust_priority (prev, INSN_PRIORITY (prev));
3122*38fd1498Szrj }
3123*38fd1498Szrj 
3124*38fd1498Szrj /* Advance DFA state STATE on one cycle.  */
3125*38fd1498Szrj void
advance_state(state_t state)3126*38fd1498Szrj advance_state (state_t state)
3127*38fd1498Szrj {
3128*38fd1498Szrj   if (targetm.sched.dfa_pre_advance_cycle)
3129*38fd1498Szrj     targetm.sched.dfa_pre_advance_cycle ();
3130*38fd1498Szrj 
3131*38fd1498Szrj   if (targetm.sched.dfa_pre_cycle_insn)
3132*38fd1498Szrj     state_transition (state,
3133*38fd1498Szrj 		      targetm.sched.dfa_pre_cycle_insn ());
3134*38fd1498Szrj 
3135*38fd1498Szrj   state_transition (state, NULL);
3136*38fd1498Szrj 
3137*38fd1498Szrj   if (targetm.sched.dfa_post_cycle_insn)
3138*38fd1498Szrj     state_transition (state,
3139*38fd1498Szrj 		      targetm.sched.dfa_post_cycle_insn ());
3140*38fd1498Szrj 
3141*38fd1498Szrj   if (targetm.sched.dfa_post_advance_cycle)
3142*38fd1498Szrj     targetm.sched.dfa_post_advance_cycle ();
3143*38fd1498Szrj }
3144*38fd1498Szrj 
3145*38fd1498Szrj /* Advance time on one cycle.  */
3146*38fd1498Szrj HAIFA_INLINE static void
advance_one_cycle(void)3147*38fd1498Szrj advance_one_cycle (void)
3148*38fd1498Szrj {
3149*38fd1498Szrj   advance_state (curr_state);
3150*38fd1498Szrj   if (sched_verbose >= 4)
3151*38fd1498Szrj     fprintf (sched_dump, ";;\tAdvance the current state.\n");
3152*38fd1498Szrj }
3153*38fd1498Szrj 
3154*38fd1498Szrj /* Update register pressure after scheduling INSN.  */
3155*38fd1498Szrj static void
update_register_pressure(rtx_insn * insn)3156*38fd1498Szrj update_register_pressure (rtx_insn *insn)
3157*38fd1498Szrj {
3158*38fd1498Szrj   struct reg_use_data *use;
3159*38fd1498Szrj   struct reg_set_data *set;
3160*38fd1498Szrj 
3161*38fd1498Szrj   gcc_checking_assert (!DEBUG_INSN_P (insn));
3162*38fd1498Szrj 
3163*38fd1498Szrj   for (use = INSN_REG_USE_LIST (insn); use != NULL; use = use->next_insn_use)
3164*38fd1498Szrj     if (dying_use_p (use))
3165*38fd1498Szrj       mark_regno_birth_or_death (curr_reg_live, curr_reg_pressure,
3166*38fd1498Szrj 				 use->regno, false);
3167*38fd1498Szrj   for (set = INSN_REG_SET_LIST (insn); set != NULL; set = set->next_insn_set)
3168*38fd1498Szrj     mark_regno_birth_or_death (curr_reg_live, curr_reg_pressure,
3169*38fd1498Szrj 			       set->regno, true);
3170*38fd1498Szrj }
3171*38fd1498Szrj 
3172*38fd1498Szrj /* Set up or update (if UPDATE_P) max register pressure (see its
3173*38fd1498Szrj    meaning in sched-int.h::_haifa_insn_data) for all current BB insns
3174*38fd1498Szrj    after insn AFTER.  */
3175*38fd1498Szrj static void
setup_insn_max_reg_pressure(rtx_insn * after,bool update_p)3176*38fd1498Szrj setup_insn_max_reg_pressure (rtx_insn *after, bool update_p)
3177*38fd1498Szrj {
3178*38fd1498Szrj   int i, p;
3179*38fd1498Szrj   bool eq_p;
3180*38fd1498Szrj   rtx_insn *insn;
3181*38fd1498Szrj   static int max_reg_pressure[N_REG_CLASSES];
3182*38fd1498Szrj 
3183*38fd1498Szrj   save_reg_pressure ();
3184*38fd1498Szrj   for (i = 0; i < ira_pressure_classes_num; i++)
3185*38fd1498Szrj     max_reg_pressure[ira_pressure_classes[i]]
3186*38fd1498Szrj       = curr_reg_pressure[ira_pressure_classes[i]];
3187*38fd1498Szrj   for (insn = NEXT_INSN (after);
3188*38fd1498Szrj        insn != NULL_RTX && ! BARRIER_P (insn)
3189*38fd1498Szrj 	 && BLOCK_FOR_INSN (insn) == BLOCK_FOR_INSN (after);
3190*38fd1498Szrj        insn = NEXT_INSN (insn))
3191*38fd1498Szrj     if (NONDEBUG_INSN_P (insn))
3192*38fd1498Szrj       {
3193*38fd1498Szrj 	eq_p = true;
3194*38fd1498Szrj 	for (i = 0; i < ira_pressure_classes_num; i++)
3195*38fd1498Szrj 	  {
3196*38fd1498Szrj 	    p = max_reg_pressure[ira_pressure_classes[i]];
3197*38fd1498Szrj 	    if (INSN_MAX_REG_PRESSURE (insn)[i] != p)
3198*38fd1498Szrj 	      {
3199*38fd1498Szrj 		eq_p = false;
3200*38fd1498Szrj 		INSN_MAX_REG_PRESSURE (insn)[i]
3201*38fd1498Szrj 		  = max_reg_pressure[ira_pressure_classes[i]];
3202*38fd1498Szrj 	      }
3203*38fd1498Szrj 	  }
3204*38fd1498Szrj 	if (update_p && eq_p)
3205*38fd1498Szrj 	  break;
3206*38fd1498Szrj 	update_register_pressure (insn);
3207*38fd1498Szrj 	for (i = 0; i < ira_pressure_classes_num; i++)
3208*38fd1498Szrj 	  if (max_reg_pressure[ira_pressure_classes[i]]
3209*38fd1498Szrj 	      < curr_reg_pressure[ira_pressure_classes[i]])
3210*38fd1498Szrj 	    max_reg_pressure[ira_pressure_classes[i]]
3211*38fd1498Szrj 	      = curr_reg_pressure[ira_pressure_classes[i]];
3212*38fd1498Szrj       }
3213*38fd1498Szrj   restore_reg_pressure ();
3214*38fd1498Szrj }
3215*38fd1498Szrj 
3216*38fd1498Szrj /* Update the current register pressure after scheduling INSN.  Update
3217*38fd1498Szrj    also max register pressure for unscheduled insns of the current
3218*38fd1498Szrj    BB.  */
3219*38fd1498Szrj static void
update_reg_and_insn_max_reg_pressure(rtx_insn * insn)3220*38fd1498Szrj update_reg_and_insn_max_reg_pressure (rtx_insn *insn)
3221*38fd1498Szrj {
3222*38fd1498Szrj   int i;
3223*38fd1498Szrj   int before[N_REG_CLASSES];
3224*38fd1498Szrj 
3225*38fd1498Szrj   for (i = 0; i < ira_pressure_classes_num; i++)
3226*38fd1498Szrj     before[i] = curr_reg_pressure[ira_pressure_classes[i]];
3227*38fd1498Szrj   update_register_pressure (insn);
3228*38fd1498Szrj   for (i = 0; i < ira_pressure_classes_num; i++)
3229*38fd1498Szrj     if (curr_reg_pressure[ira_pressure_classes[i]] != before[i])
3230*38fd1498Szrj       break;
3231*38fd1498Szrj   if (i < ira_pressure_classes_num)
3232*38fd1498Szrj     setup_insn_max_reg_pressure (insn, true);
3233*38fd1498Szrj }
3234*38fd1498Szrj 
3235*38fd1498Szrj /* Set up register pressure at the beginning of basic block BB whose
3236*38fd1498Szrj    insns starting after insn AFTER.  Set up also max register pressure
3237*38fd1498Szrj    for all insns of the basic block.  */
3238*38fd1498Szrj void
sched_setup_bb_reg_pressure_info(basic_block bb,rtx_insn * after)3239*38fd1498Szrj sched_setup_bb_reg_pressure_info (basic_block bb, rtx_insn *after)
3240*38fd1498Szrj {
3241*38fd1498Szrj   gcc_assert (sched_pressure == SCHED_PRESSURE_WEIGHTED);
3242*38fd1498Szrj   initiate_bb_reg_pressure_info (bb);
3243*38fd1498Szrj   setup_insn_max_reg_pressure (after, false);
3244*38fd1498Szrj }
3245*38fd1498Szrj 
3246*38fd1498Szrj /* If doing predication while scheduling, verify whether INSN, which
3247*38fd1498Szrj    has just been scheduled, clobbers the conditions of any
3248*38fd1498Szrj    instructions that must be predicated in order to break their
3249*38fd1498Szrj    dependencies.  If so, remove them from the queues so that they will
3250*38fd1498Szrj    only be scheduled once their control dependency is resolved.  */
3251*38fd1498Szrj 
3252*38fd1498Szrj static void
check_clobbered_conditions(rtx_insn * insn)3253*38fd1498Szrj check_clobbered_conditions (rtx_insn *insn)
3254*38fd1498Szrj {
3255*38fd1498Szrj   HARD_REG_SET t;
3256*38fd1498Szrj   int i;
3257*38fd1498Szrj 
3258*38fd1498Szrj   if ((current_sched_info->flags & DO_PREDICATION) == 0)
3259*38fd1498Szrj     return;
3260*38fd1498Szrj 
3261*38fd1498Szrj   find_all_hard_reg_sets (insn, &t, true);
3262*38fd1498Szrj 
3263*38fd1498Szrj  restart:
3264*38fd1498Szrj   for (i = 0; i < ready.n_ready; i++)
3265*38fd1498Szrj     {
3266*38fd1498Szrj       rtx_insn *x = ready_element (&ready, i);
3267*38fd1498Szrj       if (TODO_SPEC (x) == DEP_CONTROL && cond_clobbered_p (x, t))
3268*38fd1498Szrj 	{
3269*38fd1498Szrj 	  ready_remove_insn (x);
3270*38fd1498Szrj 	  goto restart;
3271*38fd1498Szrj 	}
3272*38fd1498Szrj     }
3273*38fd1498Szrj   for (i = 0; i <= max_insn_queue_index; i++)
3274*38fd1498Szrj     {
3275*38fd1498Szrj       rtx_insn_list *link;
3276*38fd1498Szrj       int q = NEXT_Q_AFTER (q_ptr, i);
3277*38fd1498Szrj 
3278*38fd1498Szrj     restart_queue:
3279*38fd1498Szrj       for (link = insn_queue[q]; link; link = link->next ())
3280*38fd1498Szrj 	{
3281*38fd1498Szrj 	  rtx_insn *x = link->insn ();
3282*38fd1498Szrj 	  if (TODO_SPEC (x) == DEP_CONTROL && cond_clobbered_p (x, t))
3283*38fd1498Szrj 	    {
3284*38fd1498Szrj 	      queue_remove (x);
3285*38fd1498Szrj 	      goto restart_queue;
3286*38fd1498Szrj 	    }
3287*38fd1498Szrj 	}
3288*38fd1498Szrj     }
3289*38fd1498Szrj }
3290*38fd1498Szrj 
3291*38fd1498Szrj /* Return (in order):
3292*38fd1498Szrj 
3293*38fd1498Szrj    - positive if INSN adversely affects the pressure on one
3294*38fd1498Szrj      register class
3295*38fd1498Szrj 
3296*38fd1498Szrj    - negative if INSN reduces the pressure on one register class
3297*38fd1498Szrj 
3298*38fd1498Szrj    - 0 if INSN doesn't affect the pressure on any register class.  */
3299*38fd1498Szrj 
3300*38fd1498Szrj static int
model_classify_pressure(struct model_insn_info * insn)3301*38fd1498Szrj model_classify_pressure (struct model_insn_info *insn)
3302*38fd1498Szrj {
3303*38fd1498Szrj   struct reg_pressure_data *reg_pressure;
3304*38fd1498Szrj   int death[N_REG_CLASSES];
3305*38fd1498Szrj   int pci, cl, sum;
3306*38fd1498Szrj 
3307*38fd1498Szrj   calculate_reg_deaths (insn->insn, death);
3308*38fd1498Szrj   reg_pressure = INSN_REG_PRESSURE (insn->insn);
3309*38fd1498Szrj   sum = 0;
3310*38fd1498Szrj   for (pci = 0; pci < ira_pressure_classes_num; pci++)
3311*38fd1498Szrj     {
3312*38fd1498Szrj       cl = ira_pressure_classes[pci];
3313*38fd1498Szrj       if (death[cl] < reg_pressure[pci].set_increase)
3314*38fd1498Szrj 	return 1;
3315*38fd1498Szrj       sum += reg_pressure[pci].set_increase - death[cl];
3316*38fd1498Szrj     }
3317*38fd1498Szrj   return sum;
3318*38fd1498Szrj }
3319*38fd1498Szrj 
3320*38fd1498Szrj /* Return true if INSN1 should come before INSN2 in the model schedule.  */
3321*38fd1498Szrj 
3322*38fd1498Szrj static int
model_order_p(struct model_insn_info * insn1,struct model_insn_info * insn2)3323*38fd1498Szrj model_order_p (struct model_insn_info *insn1, struct model_insn_info *insn2)
3324*38fd1498Szrj {
3325*38fd1498Szrj   unsigned int height1, height2;
3326*38fd1498Szrj   unsigned int priority1, priority2;
3327*38fd1498Szrj 
3328*38fd1498Szrj   /* Prefer instructions with a higher model priority.  */
3329*38fd1498Szrj   if (insn1->model_priority != insn2->model_priority)
3330*38fd1498Szrj     return insn1->model_priority > insn2->model_priority;
3331*38fd1498Szrj 
3332*38fd1498Szrj   /* Combine the length of the longest path of satisfied true dependencies
3333*38fd1498Szrj      that leads to each instruction (depth) with the length of the longest
3334*38fd1498Szrj      path of any dependencies that leads from the instruction (alap).
3335*38fd1498Szrj      Prefer instructions with the greatest combined length.  If the combined
3336*38fd1498Szrj      lengths are equal, prefer instructions with the greatest depth.
3337*38fd1498Szrj 
3338*38fd1498Szrj      The idea is that, if we have a set S of "equal" instructions that each
3339*38fd1498Szrj      have ALAP value X, and we pick one such instruction I, any true-dependent
3340*38fd1498Szrj      successors of I that have ALAP value X - 1 should be preferred over S.
3341*38fd1498Szrj      This encourages the schedule to be "narrow" rather than "wide".
3342*38fd1498Szrj      However, if I is a low-priority instruction that we decided to
3343*38fd1498Szrj      schedule because of its model_classify_pressure, and if there
3344*38fd1498Szrj      is a set of higher-priority instructions T, the aforementioned
3345*38fd1498Szrj      successors of I should not have the edge over T.  */
3346*38fd1498Szrj   height1 = insn1->depth + insn1->alap;
3347*38fd1498Szrj   height2 = insn2->depth + insn2->alap;
3348*38fd1498Szrj   if (height1 != height2)
3349*38fd1498Szrj     return height1 > height2;
3350*38fd1498Szrj   if (insn1->depth != insn2->depth)
3351*38fd1498Szrj     return insn1->depth > insn2->depth;
3352*38fd1498Szrj 
3353*38fd1498Szrj   /* We have no real preference between INSN1 an INSN2 as far as attempts
3354*38fd1498Szrj      to reduce pressure go.  Prefer instructions with higher priorities.  */
3355*38fd1498Szrj   priority1 = INSN_PRIORITY (insn1->insn);
3356*38fd1498Szrj   priority2 = INSN_PRIORITY (insn2->insn);
3357*38fd1498Szrj   if (priority1 != priority2)
3358*38fd1498Szrj     return priority1 > priority2;
3359*38fd1498Szrj 
3360*38fd1498Szrj   /* Use the original rtl sequence as a tie-breaker.  */
3361*38fd1498Szrj   return insn1 < insn2;
3362*38fd1498Szrj }
3363*38fd1498Szrj 
3364*38fd1498Szrj /* Add INSN to the model worklist immediately after PREV.  Add it to the
3365*38fd1498Szrj    beginning of the list if PREV is null.  */
3366*38fd1498Szrj 
3367*38fd1498Szrj static void
model_add_to_worklist_at(struct model_insn_info * insn,struct model_insn_info * prev)3368*38fd1498Szrj model_add_to_worklist_at (struct model_insn_info *insn,
3369*38fd1498Szrj 			  struct model_insn_info *prev)
3370*38fd1498Szrj {
3371*38fd1498Szrj   gcc_assert (QUEUE_INDEX (insn->insn) == QUEUE_NOWHERE);
3372*38fd1498Szrj   QUEUE_INDEX (insn->insn) = QUEUE_READY;
3373*38fd1498Szrj 
3374*38fd1498Szrj   insn->prev = prev;
3375*38fd1498Szrj   if (prev)
3376*38fd1498Szrj     {
3377*38fd1498Szrj       insn->next = prev->next;
3378*38fd1498Szrj       prev->next = insn;
3379*38fd1498Szrj     }
3380*38fd1498Szrj   else
3381*38fd1498Szrj     {
3382*38fd1498Szrj       insn->next = model_worklist;
3383*38fd1498Szrj       model_worklist = insn;
3384*38fd1498Szrj     }
3385*38fd1498Szrj   if (insn->next)
3386*38fd1498Szrj     insn->next->prev = insn;
3387*38fd1498Szrj }
3388*38fd1498Szrj 
3389*38fd1498Szrj /* Remove INSN from the model worklist.  */
3390*38fd1498Szrj 
3391*38fd1498Szrj static void
model_remove_from_worklist(struct model_insn_info * insn)3392*38fd1498Szrj model_remove_from_worklist (struct model_insn_info *insn)
3393*38fd1498Szrj {
3394*38fd1498Szrj   gcc_assert (QUEUE_INDEX (insn->insn) == QUEUE_READY);
3395*38fd1498Szrj   QUEUE_INDEX (insn->insn) = QUEUE_NOWHERE;
3396*38fd1498Szrj 
3397*38fd1498Szrj   if (insn->prev)
3398*38fd1498Szrj     insn->prev->next = insn->next;
3399*38fd1498Szrj   else
3400*38fd1498Szrj     model_worklist = insn->next;
3401*38fd1498Szrj   if (insn->next)
3402*38fd1498Szrj     insn->next->prev = insn->prev;
3403*38fd1498Szrj }
3404*38fd1498Szrj 
3405*38fd1498Szrj /* Add INSN to the model worklist.  Start looking for a suitable position
3406*38fd1498Szrj    between neighbors PREV and NEXT, testing at most MAX_SCHED_READY_INSNS
3407*38fd1498Szrj    insns either side.  A null PREV indicates the beginning of the list and
3408*38fd1498Szrj    a null NEXT indicates the end.  */
3409*38fd1498Szrj 
3410*38fd1498Szrj static void
model_add_to_worklist(struct model_insn_info * insn,struct model_insn_info * prev,struct model_insn_info * next)3411*38fd1498Szrj model_add_to_worklist (struct model_insn_info *insn,
3412*38fd1498Szrj 		       struct model_insn_info *prev,
3413*38fd1498Szrj 		       struct model_insn_info *next)
3414*38fd1498Szrj {
3415*38fd1498Szrj   int count;
3416*38fd1498Szrj 
3417*38fd1498Szrj   count = MAX_SCHED_READY_INSNS;
3418*38fd1498Szrj   if (count > 0 && prev && model_order_p (insn, prev))
3419*38fd1498Szrj     do
3420*38fd1498Szrj       {
3421*38fd1498Szrj 	count--;
3422*38fd1498Szrj 	prev = prev->prev;
3423*38fd1498Szrj       }
3424*38fd1498Szrj     while (count > 0 && prev && model_order_p (insn, prev));
3425*38fd1498Szrj   else
3426*38fd1498Szrj     while (count > 0 && next && model_order_p (next, insn))
3427*38fd1498Szrj       {
3428*38fd1498Szrj 	count--;
3429*38fd1498Szrj 	prev = next;
3430*38fd1498Szrj 	next = next->next;
3431*38fd1498Szrj       }
3432*38fd1498Szrj   model_add_to_worklist_at (insn, prev);
3433*38fd1498Szrj }
3434*38fd1498Szrj 
3435*38fd1498Szrj /* INSN may now have a higher priority (in the model_order_p sense)
3436*38fd1498Szrj    than before.  Move it up the worklist if necessary.  */
3437*38fd1498Szrj 
3438*38fd1498Szrj static void
model_promote_insn(struct model_insn_info * insn)3439*38fd1498Szrj model_promote_insn (struct model_insn_info *insn)
3440*38fd1498Szrj {
3441*38fd1498Szrj   struct model_insn_info *prev;
3442*38fd1498Szrj   int count;
3443*38fd1498Szrj 
3444*38fd1498Szrj   prev = insn->prev;
3445*38fd1498Szrj   count = MAX_SCHED_READY_INSNS;
3446*38fd1498Szrj   while (count > 0 && prev && model_order_p (insn, prev))
3447*38fd1498Szrj     {
3448*38fd1498Szrj       count--;
3449*38fd1498Szrj       prev = prev->prev;
3450*38fd1498Szrj     }
3451*38fd1498Szrj   if (prev != insn->prev)
3452*38fd1498Szrj     {
3453*38fd1498Szrj       model_remove_from_worklist (insn);
3454*38fd1498Szrj       model_add_to_worklist_at (insn, prev);
3455*38fd1498Szrj     }
3456*38fd1498Szrj }
3457*38fd1498Szrj 
3458*38fd1498Szrj /* Add INSN to the end of the model schedule.  */
3459*38fd1498Szrj 
3460*38fd1498Szrj static void
model_add_to_schedule(rtx_insn * insn)3461*38fd1498Szrj model_add_to_schedule (rtx_insn *insn)
3462*38fd1498Szrj {
3463*38fd1498Szrj   unsigned int point;
3464*38fd1498Szrj 
3465*38fd1498Szrj   gcc_assert (QUEUE_INDEX (insn) == QUEUE_NOWHERE);
3466*38fd1498Szrj   QUEUE_INDEX (insn) = QUEUE_SCHEDULED;
3467*38fd1498Szrj 
3468*38fd1498Szrj   point = model_schedule.length ();
3469*38fd1498Szrj   model_schedule.quick_push (insn);
3470*38fd1498Szrj   INSN_MODEL_INDEX (insn) = point + 1;
3471*38fd1498Szrj }
3472*38fd1498Szrj 
3473*38fd1498Szrj /* Analyze the instructions that are to be scheduled, setting up
3474*38fd1498Szrj    MODEL_INSN_INFO (...) and model_num_insns accordingly.  Add ready
3475*38fd1498Szrj    instructions to model_worklist.  */
3476*38fd1498Szrj 
3477*38fd1498Szrj static void
model_analyze_insns(void)3478*38fd1498Szrj model_analyze_insns (void)
3479*38fd1498Szrj {
3480*38fd1498Szrj   rtx_insn *start, *end, *iter;
3481*38fd1498Szrj   sd_iterator_def sd_it;
3482*38fd1498Szrj   dep_t dep;
3483*38fd1498Szrj   struct model_insn_info *insn, *con;
3484*38fd1498Szrj 
3485*38fd1498Szrj   model_num_insns = 0;
3486*38fd1498Szrj   start = PREV_INSN (current_sched_info->next_tail);
3487*38fd1498Szrj   end = current_sched_info->prev_head;
3488*38fd1498Szrj   for (iter = start; iter != end; iter = PREV_INSN (iter))
3489*38fd1498Szrj     if (NONDEBUG_INSN_P (iter))
3490*38fd1498Szrj       {
3491*38fd1498Szrj 	insn = MODEL_INSN_INFO (iter);
3492*38fd1498Szrj 	insn->insn = iter;
3493*38fd1498Szrj 	FOR_EACH_DEP (iter, SD_LIST_FORW, sd_it, dep)
3494*38fd1498Szrj 	  {
3495*38fd1498Szrj 	    con = MODEL_INSN_INFO (DEP_CON (dep));
3496*38fd1498Szrj 	    if (con->insn && insn->alap < con->alap + 1)
3497*38fd1498Szrj 	      insn->alap = con->alap + 1;
3498*38fd1498Szrj 	  }
3499*38fd1498Szrj 
3500*38fd1498Szrj 	insn->old_queue = QUEUE_INDEX (iter);
3501*38fd1498Szrj 	QUEUE_INDEX (iter) = QUEUE_NOWHERE;
3502*38fd1498Szrj 
3503*38fd1498Szrj 	insn->unscheduled_preds = dep_list_size (iter, SD_LIST_HARD_BACK);
3504*38fd1498Szrj 	if (insn->unscheduled_preds == 0)
3505*38fd1498Szrj 	  model_add_to_worklist (insn, NULL, model_worklist);
3506*38fd1498Szrj 
3507*38fd1498Szrj 	model_num_insns++;
3508*38fd1498Szrj       }
3509*38fd1498Szrj }
3510*38fd1498Szrj 
3511*38fd1498Szrj /* The global state describes the register pressure at the start of the
3512*38fd1498Szrj    model schedule.  Initialize GROUP accordingly.  */
3513*38fd1498Szrj 
3514*38fd1498Szrj static void
model_init_pressure_group(struct model_pressure_group * group)3515*38fd1498Szrj model_init_pressure_group (struct model_pressure_group *group)
3516*38fd1498Szrj {
3517*38fd1498Szrj   int pci, cl;
3518*38fd1498Szrj 
3519*38fd1498Szrj   for (pci = 0; pci < ira_pressure_classes_num; pci++)
3520*38fd1498Szrj     {
3521*38fd1498Szrj       cl = ira_pressure_classes[pci];
3522*38fd1498Szrj       group->limits[pci].pressure = curr_reg_pressure[cl];
3523*38fd1498Szrj       group->limits[pci].point = 0;
3524*38fd1498Szrj     }
3525*38fd1498Szrj   /* Use index model_num_insns to record the state after the last
3526*38fd1498Szrj      instruction in the model schedule.  */
3527*38fd1498Szrj   group->model = XNEWVEC (struct model_pressure_data,
3528*38fd1498Szrj 			  (model_num_insns + 1) * ira_pressure_classes_num);
3529*38fd1498Szrj }
3530*38fd1498Szrj 
3531*38fd1498Szrj /* Record that MODEL_REF_PRESSURE (GROUP, POINT, PCI) is PRESSURE.
3532*38fd1498Szrj    Update the maximum pressure for the whole schedule.  */
3533*38fd1498Szrj 
3534*38fd1498Szrj static void
model_record_pressure(struct model_pressure_group * group,int point,int pci,int pressure)3535*38fd1498Szrj model_record_pressure (struct model_pressure_group *group,
3536*38fd1498Szrj 		       int point, int pci, int pressure)
3537*38fd1498Szrj {
3538*38fd1498Szrj   MODEL_REF_PRESSURE (group, point, pci) = pressure;
3539*38fd1498Szrj   if (group->limits[pci].pressure < pressure)
3540*38fd1498Szrj     {
3541*38fd1498Szrj       group->limits[pci].pressure = pressure;
3542*38fd1498Szrj       group->limits[pci].point = point;
3543*38fd1498Szrj     }
3544*38fd1498Szrj }
3545*38fd1498Szrj 
3546*38fd1498Szrj /* INSN has just been added to the end of the model schedule.  Record its
3547*38fd1498Szrj    register-pressure information.  */
3548*38fd1498Szrj 
3549*38fd1498Szrj static void
model_record_pressures(struct model_insn_info * insn)3550*38fd1498Szrj model_record_pressures (struct model_insn_info *insn)
3551*38fd1498Szrj {
3552*38fd1498Szrj   struct reg_pressure_data *reg_pressure;
3553*38fd1498Szrj   int point, pci, cl, delta;
3554*38fd1498Szrj   int death[N_REG_CLASSES];
3555*38fd1498Szrj 
3556*38fd1498Szrj   point = model_index (insn->insn);
3557*38fd1498Szrj   if (sched_verbose >= 2)
3558*38fd1498Szrj     {
3559*38fd1498Szrj       if (point == 0)
3560*38fd1498Szrj 	{
3561*38fd1498Szrj 	  fprintf (sched_dump, "\n;;\tModel schedule:\n;;\n");
3562*38fd1498Szrj 	  fprintf (sched_dump, ";;\t| idx insn | mpri hght dpth prio |\n");
3563*38fd1498Szrj 	}
3564*38fd1498Szrj       fprintf (sched_dump, ";;\t| %3d %4d | %4d %4d %4d %4d | %-30s ",
3565*38fd1498Szrj 	       point, INSN_UID (insn->insn), insn->model_priority,
3566*38fd1498Szrj 	       insn->depth + insn->alap, insn->depth,
3567*38fd1498Szrj 	       INSN_PRIORITY (insn->insn),
3568*38fd1498Szrj 	       str_pattern_slim (PATTERN (insn->insn)));
3569*38fd1498Szrj     }
3570*38fd1498Szrj   calculate_reg_deaths (insn->insn, death);
3571*38fd1498Szrj   reg_pressure = INSN_REG_PRESSURE (insn->insn);
3572*38fd1498Szrj   for (pci = 0; pci < ira_pressure_classes_num; pci++)
3573*38fd1498Szrj     {
3574*38fd1498Szrj       cl = ira_pressure_classes[pci];
3575*38fd1498Szrj       delta = reg_pressure[pci].set_increase - death[cl];
3576*38fd1498Szrj       if (sched_verbose >= 2)
3577*38fd1498Szrj 	fprintf (sched_dump, " %s:[%d,%+d]", reg_class_names[cl],
3578*38fd1498Szrj 		 curr_reg_pressure[cl], delta);
3579*38fd1498Szrj       model_record_pressure (&model_before_pressure, point, pci,
3580*38fd1498Szrj 			     curr_reg_pressure[cl]);
3581*38fd1498Szrj     }
3582*38fd1498Szrj   if (sched_verbose >= 2)
3583*38fd1498Szrj     fprintf (sched_dump, "\n");
3584*38fd1498Szrj }
3585*38fd1498Szrj 
3586*38fd1498Szrj /* All instructions have been added to the model schedule.  Record the
3587*38fd1498Szrj    final register pressure in GROUP and set up all MODEL_MAX_PRESSUREs.  */
3588*38fd1498Szrj 
3589*38fd1498Szrj static void
model_record_final_pressures(struct model_pressure_group * group)3590*38fd1498Szrj model_record_final_pressures (struct model_pressure_group *group)
3591*38fd1498Szrj {
3592*38fd1498Szrj   int point, pci, max_pressure, ref_pressure, cl;
3593*38fd1498Szrj 
3594*38fd1498Szrj   for (pci = 0; pci < ira_pressure_classes_num; pci++)
3595*38fd1498Szrj     {
3596*38fd1498Szrj       /* Record the final pressure for this class.  */
3597*38fd1498Szrj       cl = ira_pressure_classes[pci];
3598*38fd1498Szrj       point = model_num_insns;
3599*38fd1498Szrj       ref_pressure = curr_reg_pressure[cl];
3600*38fd1498Szrj       model_record_pressure (group, point, pci, ref_pressure);
3601*38fd1498Szrj 
3602*38fd1498Szrj       /* Record the original maximum pressure.  */
3603*38fd1498Szrj       group->limits[pci].orig_pressure = group->limits[pci].pressure;
3604*38fd1498Szrj 
3605*38fd1498Szrj       /* Update the MODEL_MAX_PRESSURE for every point of the schedule.  */
3606*38fd1498Szrj       max_pressure = ref_pressure;
3607*38fd1498Szrj       MODEL_MAX_PRESSURE (group, point, pci) = max_pressure;
3608*38fd1498Szrj       while (point > 0)
3609*38fd1498Szrj 	{
3610*38fd1498Szrj 	  point--;
3611*38fd1498Szrj 	  ref_pressure = MODEL_REF_PRESSURE (group, point, pci);
3612*38fd1498Szrj 	  max_pressure = MAX (max_pressure, ref_pressure);
3613*38fd1498Szrj 	  MODEL_MAX_PRESSURE (group, point, pci) = max_pressure;
3614*38fd1498Szrj 	}
3615*38fd1498Szrj     }
3616*38fd1498Szrj }
3617*38fd1498Szrj 
3618*38fd1498Szrj /* Update all successors of INSN, given that INSN has just been scheduled.  */
3619*38fd1498Szrj 
3620*38fd1498Szrj static void
model_add_successors_to_worklist(struct model_insn_info * insn)3621*38fd1498Szrj model_add_successors_to_worklist (struct model_insn_info *insn)
3622*38fd1498Szrj {
3623*38fd1498Szrj   sd_iterator_def sd_it;
3624*38fd1498Szrj   struct model_insn_info *con;
3625*38fd1498Szrj   dep_t dep;
3626*38fd1498Szrj 
3627*38fd1498Szrj   FOR_EACH_DEP (insn->insn, SD_LIST_FORW, sd_it, dep)
3628*38fd1498Szrj     {
3629*38fd1498Szrj       con = MODEL_INSN_INFO (DEP_CON (dep));
3630*38fd1498Szrj       /* Ignore debug instructions, and instructions from other blocks.  */
3631*38fd1498Szrj       if (con->insn)
3632*38fd1498Szrj 	{
3633*38fd1498Szrj 	  con->unscheduled_preds--;
3634*38fd1498Szrj 
3635*38fd1498Szrj 	  /* Update the depth field of each true-dependent successor.
3636*38fd1498Szrj 	     Increasing the depth gives them a higher priority than
3637*38fd1498Szrj 	     before.  */
3638*38fd1498Szrj 	  if (DEP_TYPE (dep) == REG_DEP_TRUE && con->depth < insn->depth + 1)
3639*38fd1498Szrj 	    {
3640*38fd1498Szrj 	      con->depth = insn->depth + 1;
3641*38fd1498Szrj 	      if (QUEUE_INDEX (con->insn) == QUEUE_READY)
3642*38fd1498Szrj 		model_promote_insn (con);
3643*38fd1498Szrj 	    }
3644*38fd1498Szrj 
3645*38fd1498Szrj 	  /* If this is a true dependency, or if there are no remaining
3646*38fd1498Szrj 	     dependencies for CON (meaning that CON only had non-true
3647*38fd1498Szrj 	     dependencies), make sure that CON is on the worklist.
3648*38fd1498Szrj 	     We don't bother otherwise because it would tend to fill the
3649*38fd1498Szrj 	     worklist with a lot of low-priority instructions that are not
3650*38fd1498Szrj 	     yet ready to issue.  */
3651*38fd1498Szrj 	  if ((con->depth > 0 || con->unscheduled_preds == 0)
3652*38fd1498Szrj 	      && QUEUE_INDEX (con->insn) == QUEUE_NOWHERE)
3653*38fd1498Szrj 	    model_add_to_worklist (con, insn, insn->next);
3654*38fd1498Szrj 	}
3655*38fd1498Szrj     }
3656*38fd1498Szrj }
3657*38fd1498Szrj 
3658*38fd1498Szrj /* Give INSN a higher priority than any current instruction, then give
3659*38fd1498Szrj    unscheduled predecessors of INSN a higher priority still.  If any of
3660*38fd1498Szrj    those predecessors are not on the model worklist, do the same for its
3661*38fd1498Szrj    predecessors, and so on.  */
3662*38fd1498Szrj 
3663*38fd1498Szrj static void
model_promote_predecessors(struct model_insn_info * insn)3664*38fd1498Szrj model_promote_predecessors (struct model_insn_info *insn)
3665*38fd1498Szrj {
3666*38fd1498Szrj   struct model_insn_info *pro, *first;
3667*38fd1498Szrj   sd_iterator_def sd_it;
3668*38fd1498Szrj   dep_t dep;
3669*38fd1498Szrj 
3670*38fd1498Szrj   if (sched_verbose >= 7)
3671*38fd1498Szrj     fprintf (sched_dump, ";;\t+--- priority of %d = %d, priority of",
3672*38fd1498Szrj 	     INSN_UID (insn->insn), model_next_priority);
3673*38fd1498Szrj   insn->model_priority = model_next_priority++;
3674*38fd1498Szrj   model_remove_from_worklist (insn);
3675*38fd1498Szrj   model_add_to_worklist_at (insn, NULL);
3676*38fd1498Szrj 
3677*38fd1498Szrj   first = NULL;
3678*38fd1498Szrj   for (;;)
3679*38fd1498Szrj     {
3680*38fd1498Szrj       FOR_EACH_DEP (insn->insn, SD_LIST_HARD_BACK, sd_it, dep)
3681*38fd1498Szrj 	{
3682*38fd1498Szrj 	  pro = MODEL_INSN_INFO (DEP_PRO (dep));
3683*38fd1498Szrj 	  /* The first test is to ignore debug instructions, and instructions
3684*38fd1498Szrj 	     from other blocks.  */
3685*38fd1498Szrj 	  if (pro->insn
3686*38fd1498Szrj 	      && pro->model_priority != model_next_priority
3687*38fd1498Szrj 	      && QUEUE_INDEX (pro->insn) != QUEUE_SCHEDULED)
3688*38fd1498Szrj 	    {
3689*38fd1498Szrj 	      pro->model_priority = model_next_priority;
3690*38fd1498Szrj 	      if (sched_verbose >= 7)
3691*38fd1498Szrj 		fprintf (sched_dump, " %d", INSN_UID (pro->insn));
3692*38fd1498Szrj 	      if (QUEUE_INDEX (pro->insn) == QUEUE_READY)
3693*38fd1498Szrj 		{
3694*38fd1498Szrj 		  /* PRO is already in the worklist, but it now has
3695*38fd1498Szrj 		     a higher priority than before.  Move it at the
3696*38fd1498Szrj 		     appropriate place.  */
3697*38fd1498Szrj 		  model_remove_from_worklist (pro);
3698*38fd1498Szrj 		  model_add_to_worklist (pro, NULL, model_worklist);
3699*38fd1498Szrj 		}
3700*38fd1498Szrj 	      else
3701*38fd1498Szrj 		{
3702*38fd1498Szrj 		  /* PRO isn't in the worklist.  Recursively process
3703*38fd1498Szrj 		     its predecessors until we find one that is.  */
3704*38fd1498Szrj 		  pro->next = first;
3705*38fd1498Szrj 		  first = pro;
3706*38fd1498Szrj 		}
3707*38fd1498Szrj 	    }
3708*38fd1498Szrj 	}
3709*38fd1498Szrj       if (!first)
3710*38fd1498Szrj 	break;
3711*38fd1498Szrj       insn = first;
3712*38fd1498Szrj       first = insn->next;
3713*38fd1498Szrj     }
3714*38fd1498Szrj   if (sched_verbose >= 7)
3715*38fd1498Szrj     fprintf (sched_dump, " = %d\n", model_next_priority);
3716*38fd1498Szrj   model_next_priority++;
3717*38fd1498Szrj }
3718*38fd1498Szrj 
3719*38fd1498Szrj /* Pick one instruction from model_worklist and process it.  */
3720*38fd1498Szrj 
3721*38fd1498Szrj static void
model_choose_insn(void)3722*38fd1498Szrj model_choose_insn (void)
3723*38fd1498Szrj {
3724*38fd1498Szrj   struct model_insn_info *insn, *fallback;
3725*38fd1498Szrj   int count;
3726*38fd1498Szrj 
3727*38fd1498Szrj   if (sched_verbose >= 7)
3728*38fd1498Szrj     {
3729*38fd1498Szrj       fprintf (sched_dump, ";;\t+--- worklist:\n");
3730*38fd1498Szrj       insn = model_worklist;
3731*38fd1498Szrj       count = MAX_SCHED_READY_INSNS;
3732*38fd1498Szrj       while (count > 0 && insn)
3733*38fd1498Szrj 	{
3734*38fd1498Szrj 	  fprintf (sched_dump, ";;\t+---   %d [%d, %d, %d, %d]\n",
3735*38fd1498Szrj 		   INSN_UID (insn->insn), insn->model_priority,
3736*38fd1498Szrj 		   insn->depth + insn->alap, insn->depth,
3737*38fd1498Szrj 		   INSN_PRIORITY (insn->insn));
3738*38fd1498Szrj 	  count--;
3739*38fd1498Szrj 	  insn = insn->next;
3740*38fd1498Szrj 	}
3741*38fd1498Szrj     }
3742*38fd1498Szrj 
3743*38fd1498Szrj   /* Look for a ready instruction whose model_classify_priority is zero
3744*38fd1498Szrj      or negative, picking the highest-priority one.  Adding such an
3745*38fd1498Szrj      instruction to the schedule now should do no harm, and may actually
3746*38fd1498Szrj      do some good.
3747*38fd1498Szrj 
3748*38fd1498Szrj      Failing that, see whether there is an instruction with the highest
3749*38fd1498Szrj      extant model_priority that is not yet ready, but which would reduce
3750*38fd1498Szrj      pressure if it became ready.  This is designed to catch cases like:
3751*38fd1498Szrj 
3752*38fd1498Szrj        (set (mem (reg R1)) (reg R2))
3753*38fd1498Szrj 
3754*38fd1498Szrj      where the instruction is the last remaining use of R1 and where the
3755*38fd1498Szrj      value of R2 is not yet available (or vice versa).  The death of R1
3756*38fd1498Szrj      means that this instruction already reduces pressure.  It is of
3757*38fd1498Szrj      course possible that the computation of R2 involves other registers
3758*38fd1498Szrj      that are hard to kill, but such cases are rare enough for this
3759*38fd1498Szrj      heuristic to be a win in general.
3760*38fd1498Szrj 
3761*38fd1498Szrj      Failing that, just pick the highest-priority instruction in the
3762*38fd1498Szrj      worklist.  */
3763*38fd1498Szrj   count = MAX_SCHED_READY_INSNS;
3764*38fd1498Szrj   insn = model_worklist;
3765*38fd1498Szrj   fallback = 0;
3766*38fd1498Szrj   for (;;)
3767*38fd1498Szrj     {
3768*38fd1498Szrj       if (count == 0 || !insn)
3769*38fd1498Szrj 	{
3770*38fd1498Szrj 	  insn = fallback ? fallback : model_worklist;
3771*38fd1498Szrj 	  break;
3772*38fd1498Szrj 	}
3773*38fd1498Szrj       if (insn->unscheduled_preds)
3774*38fd1498Szrj 	{
3775*38fd1498Szrj 	  if (model_worklist->model_priority == insn->model_priority
3776*38fd1498Szrj 	      && !fallback
3777*38fd1498Szrj 	      && model_classify_pressure (insn) < 0)
3778*38fd1498Szrj 	    fallback = insn;
3779*38fd1498Szrj 	}
3780*38fd1498Szrj       else
3781*38fd1498Szrj 	{
3782*38fd1498Szrj 	  if (model_classify_pressure (insn) <= 0)
3783*38fd1498Szrj 	    break;
3784*38fd1498Szrj 	}
3785*38fd1498Szrj       count--;
3786*38fd1498Szrj       insn = insn->next;
3787*38fd1498Szrj     }
3788*38fd1498Szrj 
3789*38fd1498Szrj   if (sched_verbose >= 7 && insn != model_worklist)
3790*38fd1498Szrj     {
3791*38fd1498Szrj       if (insn->unscheduled_preds)
3792*38fd1498Szrj 	fprintf (sched_dump, ";;\t+--- promoting insn %d, with dependencies\n",
3793*38fd1498Szrj 		 INSN_UID (insn->insn));
3794*38fd1498Szrj       else
3795*38fd1498Szrj 	fprintf (sched_dump, ";;\t+--- promoting insn %d, which is ready\n",
3796*38fd1498Szrj 		 INSN_UID (insn->insn));
3797*38fd1498Szrj     }
3798*38fd1498Szrj   if (insn->unscheduled_preds)
3799*38fd1498Szrj     /* INSN isn't yet ready to issue.  Give all its predecessors the
3800*38fd1498Szrj        highest priority.  */
3801*38fd1498Szrj     model_promote_predecessors (insn);
3802*38fd1498Szrj   else
3803*38fd1498Szrj     {
3804*38fd1498Szrj       /* INSN is ready.  Add it to the end of model_schedule and
3805*38fd1498Szrj 	 process its successors.  */
3806*38fd1498Szrj       model_add_successors_to_worklist (insn);
3807*38fd1498Szrj       model_remove_from_worklist (insn);
3808*38fd1498Szrj       model_add_to_schedule (insn->insn);
3809*38fd1498Szrj       model_record_pressures (insn);
3810*38fd1498Szrj       update_register_pressure (insn->insn);
3811*38fd1498Szrj     }
3812*38fd1498Szrj }
3813*38fd1498Szrj 
3814*38fd1498Szrj /* Restore all QUEUE_INDEXs to the values that they had before
3815*38fd1498Szrj    model_start_schedule was called.  */
3816*38fd1498Szrj 
3817*38fd1498Szrj static void
model_reset_queue_indices(void)3818*38fd1498Szrj model_reset_queue_indices (void)
3819*38fd1498Szrj {
3820*38fd1498Szrj   unsigned int i;
3821*38fd1498Szrj   rtx_insn *insn;
3822*38fd1498Szrj 
3823*38fd1498Szrj   FOR_EACH_VEC_ELT (model_schedule, i, insn)
3824*38fd1498Szrj     QUEUE_INDEX (insn) = MODEL_INSN_INFO (insn)->old_queue;
3825*38fd1498Szrj }
3826*38fd1498Szrj 
3827*38fd1498Szrj /* We have calculated the model schedule and spill costs.  Print a summary
3828*38fd1498Szrj    to sched_dump.  */
3829*38fd1498Szrj 
3830*38fd1498Szrj static void
model_dump_pressure_summary(void)3831*38fd1498Szrj model_dump_pressure_summary (void)
3832*38fd1498Szrj {
3833*38fd1498Szrj   int pci, cl;
3834*38fd1498Szrj 
3835*38fd1498Szrj   fprintf (sched_dump, ";; Pressure summary:");
3836*38fd1498Szrj   for (pci = 0; pci < ira_pressure_classes_num; pci++)
3837*38fd1498Szrj     {
3838*38fd1498Szrj       cl = ira_pressure_classes[pci];
3839*38fd1498Szrj       fprintf (sched_dump, " %s:%d", reg_class_names[cl],
3840*38fd1498Szrj 	       model_before_pressure.limits[pci].pressure);
3841*38fd1498Szrj     }
3842*38fd1498Szrj   fprintf (sched_dump, "\n\n");
3843*38fd1498Szrj }
3844*38fd1498Szrj 
3845*38fd1498Szrj /* Initialize the SCHED_PRESSURE_MODEL information for the current
3846*38fd1498Szrj    scheduling region.  */
3847*38fd1498Szrj 
3848*38fd1498Szrj static void
model_start_schedule(basic_block bb)3849*38fd1498Szrj model_start_schedule (basic_block bb)
3850*38fd1498Szrj {
3851*38fd1498Szrj   model_next_priority = 1;
3852*38fd1498Szrj   model_schedule.create (sched_max_luid);
3853*38fd1498Szrj   model_insns = XCNEWVEC (struct model_insn_info, sched_max_luid);
3854*38fd1498Szrj 
3855*38fd1498Szrj   gcc_assert (bb == BLOCK_FOR_INSN (NEXT_INSN (current_sched_info->prev_head)));
3856*38fd1498Szrj   initiate_reg_pressure_info (df_get_live_in (bb));
3857*38fd1498Szrj 
3858*38fd1498Szrj   model_analyze_insns ();
3859*38fd1498Szrj   model_init_pressure_group (&model_before_pressure);
3860*38fd1498Szrj   while (model_worklist)
3861*38fd1498Szrj     model_choose_insn ();
3862*38fd1498Szrj   gcc_assert (model_num_insns == (int) model_schedule.length ());
3863*38fd1498Szrj   if (sched_verbose >= 2)
3864*38fd1498Szrj     fprintf (sched_dump, "\n");
3865*38fd1498Szrj 
3866*38fd1498Szrj   model_record_final_pressures (&model_before_pressure);
3867*38fd1498Szrj   model_reset_queue_indices ();
3868*38fd1498Szrj 
3869*38fd1498Szrj   XDELETEVEC (model_insns);
3870*38fd1498Szrj 
3871*38fd1498Szrj   model_curr_point = 0;
3872*38fd1498Szrj   initiate_reg_pressure_info (df_get_live_in (bb));
3873*38fd1498Szrj   if (sched_verbose >= 1)
3874*38fd1498Szrj     model_dump_pressure_summary ();
3875*38fd1498Szrj }
3876*38fd1498Szrj 
3877*38fd1498Szrj /* Free the information associated with GROUP.  */
3878*38fd1498Szrj 
3879*38fd1498Szrj static void
model_finalize_pressure_group(struct model_pressure_group * group)3880*38fd1498Szrj model_finalize_pressure_group (struct model_pressure_group *group)
3881*38fd1498Szrj {
3882*38fd1498Szrj   XDELETEVEC (group->model);
3883*38fd1498Szrj }
3884*38fd1498Szrj 
3885*38fd1498Szrj /* Free the information created by model_start_schedule.  */
3886*38fd1498Szrj 
3887*38fd1498Szrj static void
model_end_schedule(void)3888*38fd1498Szrj model_end_schedule (void)
3889*38fd1498Szrj {
3890*38fd1498Szrj   model_finalize_pressure_group (&model_before_pressure);
3891*38fd1498Szrj   model_schedule.release ();
3892*38fd1498Szrj }
3893*38fd1498Szrj 
3894*38fd1498Szrj /* Prepare reg pressure scheduling for basic block BB.  */
3895*38fd1498Szrj static void
sched_pressure_start_bb(basic_block bb)3896*38fd1498Szrj sched_pressure_start_bb (basic_block bb)
3897*38fd1498Szrj {
3898*38fd1498Szrj   /* Set the number of available registers for each class taking into account
3899*38fd1498Szrj      relative probability of current basic block versus function prologue and
3900*38fd1498Szrj      epilogue.
3901*38fd1498Szrj      * If the basic block executes much more often than the prologue/epilogue
3902*38fd1498Szrj      (e.g., inside a hot loop), then cost of spill in the prologue is close to
3903*38fd1498Szrj      nil, so the effective number of available registers is
3904*38fd1498Szrj      (ira_class_hard_regs_num[cl] - fixed_regs_num[cl] - 0).
3905*38fd1498Szrj      * If the basic block executes as often as the prologue/epilogue,
3906*38fd1498Szrj      then spill in the block is as costly as in the prologue, so the effective
3907*38fd1498Szrj      number of available registers is
3908*38fd1498Szrj      (ira_class_hard_regs_num[cl] - fixed_regs_num[cl]
3909*38fd1498Szrj       - call_saved_regs_num[cl]).
3910*38fd1498Szrj      Note that all-else-equal, we prefer to spill in the prologue, since that
3911*38fd1498Szrj      allows "extra" registers for other basic blocks of the function.
3912*38fd1498Szrj      * If the basic block is on the cold path of the function and executes
3913*38fd1498Szrj      rarely, then we should always prefer to spill in the block, rather than
3914*38fd1498Szrj      in the prologue/epilogue.  The effective number of available register is
3915*38fd1498Szrj      (ira_class_hard_regs_num[cl] - fixed_regs_num[cl]
3916*38fd1498Szrj       - call_saved_regs_num[cl]).  */
3917*38fd1498Szrj   {
3918*38fd1498Szrj     int i;
3919*38fd1498Szrj     int entry_freq = ENTRY_BLOCK_PTR_FOR_FN (cfun)->count.to_frequency (cfun);
3920*38fd1498Szrj     int bb_freq = bb->count.to_frequency (cfun);
3921*38fd1498Szrj 
3922*38fd1498Szrj     if (bb_freq == 0)
3923*38fd1498Szrj       {
3924*38fd1498Szrj 	if (entry_freq == 0)
3925*38fd1498Szrj 	  entry_freq = bb_freq = 1;
3926*38fd1498Szrj       }
3927*38fd1498Szrj     if (bb_freq < entry_freq)
3928*38fd1498Szrj       bb_freq = entry_freq;
3929*38fd1498Szrj 
3930*38fd1498Szrj     for (i = 0; i < ira_pressure_classes_num; ++i)
3931*38fd1498Szrj       {
3932*38fd1498Szrj 	enum reg_class cl = ira_pressure_classes[i];
3933*38fd1498Szrj 	sched_class_regs_num[cl] = ira_class_hard_regs_num[cl]
3934*38fd1498Szrj 				   - fixed_regs_num[cl];
3935*38fd1498Szrj 	sched_class_regs_num[cl]
3936*38fd1498Szrj 	  -= (call_saved_regs_num[cl] * entry_freq) / bb_freq;
3937*38fd1498Szrj       }
3938*38fd1498Szrj   }
3939*38fd1498Szrj 
3940*38fd1498Szrj   if (sched_pressure == SCHED_PRESSURE_MODEL)
3941*38fd1498Szrj     model_start_schedule (bb);
3942*38fd1498Szrj }
3943*38fd1498Szrj 
3944*38fd1498Szrj /* A structure that holds local state for the loop in schedule_block.  */
3945*38fd1498Szrj struct sched_block_state
3946*38fd1498Szrj {
3947*38fd1498Szrj   /* True if no real insns have been scheduled in the current cycle.  */
3948*38fd1498Szrj   bool first_cycle_insn_p;
3949*38fd1498Szrj   /* True if a shadow insn has been scheduled in the current cycle, which
3950*38fd1498Szrj      means that no more normal insns can be issued.  */
3951*38fd1498Szrj   bool shadows_only_p;
3952*38fd1498Szrj   /* True if we're winding down a modulo schedule, which means that we only
3953*38fd1498Szrj      issue insns with INSN_EXACT_TICK set.  */
3954*38fd1498Szrj   bool modulo_epilogue;
3955*38fd1498Szrj   /* Initialized with the machine's issue rate every cycle, and updated
3956*38fd1498Szrj      by calls to the variable_issue hook.  */
3957*38fd1498Szrj   int can_issue_more;
3958*38fd1498Szrj };
3959*38fd1498Szrj 
3960*38fd1498Szrj /* INSN is the "currently executing insn".  Launch each insn which was
3961*38fd1498Szrj    waiting on INSN.  READY is the ready list which contains the insns
3962*38fd1498Szrj    that are ready to fire.  CLOCK is the current cycle.  The function
3963*38fd1498Szrj    returns necessary cycle advance after issuing the insn (it is not
3964*38fd1498Szrj    zero for insns in a schedule group).  */
3965*38fd1498Szrj 
3966*38fd1498Szrj static int
schedule_insn(rtx_insn * insn)3967*38fd1498Szrj schedule_insn (rtx_insn *insn)
3968*38fd1498Szrj {
3969*38fd1498Szrj   sd_iterator_def sd_it;
3970*38fd1498Szrj   dep_t dep;
3971*38fd1498Szrj   int i;
3972*38fd1498Szrj   int advance = 0;
3973*38fd1498Szrj 
3974*38fd1498Szrj   if (sched_verbose >= 1)
3975*38fd1498Szrj     {
3976*38fd1498Szrj       struct reg_pressure_data *pressure_info;
3977*38fd1498Szrj       fprintf (sched_dump, ";;\t%3i--> %s %-40s:",
3978*38fd1498Szrj 	       clock_var, (*current_sched_info->print_insn) (insn, 1),
3979*38fd1498Szrj 	       str_pattern_slim (PATTERN (insn)));
3980*38fd1498Szrj 
3981*38fd1498Szrj       if (recog_memoized (insn) < 0)
3982*38fd1498Szrj 	fprintf (sched_dump, "nothing");
3983*38fd1498Szrj       else
3984*38fd1498Szrj 	print_reservation (sched_dump, insn);
3985*38fd1498Szrj       pressure_info = INSN_REG_PRESSURE (insn);
3986*38fd1498Szrj       if (pressure_info != NULL)
3987*38fd1498Szrj 	{
3988*38fd1498Szrj 	  fputc (':', sched_dump);
3989*38fd1498Szrj 	  for (i = 0; i < ira_pressure_classes_num; i++)
3990*38fd1498Szrj 	    fprintf (sched_dump, "%s%s%+d(%d)",
3991*38fd1498Szrj 		     scheduled_insns.length () > 1
3992*38fd1498Szrj 		     && INSN_LUID (insn)
3993*38fd1498Szrj 		     < INSN_LUID (scheduled_insns[scheduled_insns.length () - 2]) ? "@" : "",
3994*38fd1498Szrj 		     reg_class_names[ira_pressure_classes[i]],
3995*38fd1498Szrj 		     pressure_info[i].set_increase, pressure_info[i].change);
3996*38fd1498Szrj 	}
3997*38fd1498Szrj       if (sched_pressure == SCHED_PRESSURE_MODEL
3998*38fd1498Szrj 	  && model_curr_point < model_num_insns
3999*38fd1498Szrj 	  && model_index (insn) == model_curr_point)
4000*38fd1498Szrj 	fprintf (sched_dump, ":model %d", model_curr_point);
4001*38fd1498Szrj       fputc ('\n', sched_dump);
4002*38fd1498Szrj     }
4003*38fd1498Szrj 
4004*38fd1498Szrj   if (sched_pressure == SCHED_PRESSURE_WEIGHTED && !DEBUG_INSN_P (insn))
4005*38fd1498Szrj     update_reg_and_insn_max_reg_pressure (insn);
4006*38fd1498Szrj 
4007*38fd1498Szrj   /* Scheduling instruction should have all its dependencies resolved and
4008*38fd1498Szrj      should have been removed from the ready list.  */
4009*38fd1498Szrj   gcc_assert (sd_lists_empty_p (insn, SD_LIST_HARD_BACK));
4010*38fd1498Szrj 
4011*38fd1498Szrj   /* Reset debug insns invalidated by moving this insn.  */
4012*38fd1498Szrj   if (MAY_HAVE_DEBUG_BIND_INSNS && !DEBUG_INSN_P (insn))
4013*38fd1498Szrj     for (sd_it = sd_iterator_start (insn, SD_LIST_BACK);
4014*38fd1498Szrj 	 sd_iterator_cond (&sd_it, &dep);)
4015*38fd1498Szrj       {
4016*38fd1498Szrj 	rtx_insn *dbg = DEP_PRO (dep);
4017*38fd1498Szrj 	struct reg_use_data *use, *next;
4018*38fd1498Szrj 
4019*38fd1498Szrj 	if (DEP_STATUS (dep) & DEP_CANCELLED)
4020*38fd1498Szrj 	  {
4021*38fd1498Szrj 	    sd_iterator_next (&sd_it);
4022*38fd1498Szrj 	    continue;
4023*38fd1498Szrj 	  }
4024*38fd1498Szrj 
4025*38fd1498Szrj 	gcc_assert (DEBUG_BIND_INSN_P (dbg));
4026*38fd1498Szrj 
4027*38fd1498Szrj 	if (sched_verbose >= 6)
4028*38fd1498Szrj 	  fprintf (sched_dump, ";;\t\tresetting: debug insn %d\n",
4029*38fd1498Szrj 		   INSN_UID (dbg));
4030*38fd1498Szrj 
4031*38fd1498Szrj 	/* ??? Rather than resetting the debug insn, we might be able
4032*38fd1498Szrj 	   to emit a debug temp before the just-scheduled insn, but
4033*38fd1498Szrj 	   this would involve checking that the expression at the
4034*38fd1498Szrj 	   point of the debug insn is equivalent to the expression
4035*38fd1498Szrj 	   before the just-scheduled insn.  They might not be: the
4036*38fd1498Szrj 	   expression in the debug insn may depend on other insns not
4037*38fd1498Szrj 	   yet scheduled that set MEMs, REGs or even other debug
4038*38fd1498Szrj 	   insns.  It's not clear that attempting to preserve debug
4039*38fd1498Szrj 	   information in these cases is worth the effort, given how
4040*38fd1498Szrj 	   uncommon these resets are and the likelihood that the debug
4041*38fd1498Szrj 	   temps introduced won't survive the schedule change.  */
4042*38fd1498Szrj 	INSN_VAR_LOCATION_LOC (dbg) = gen_rtx_UNKNOWN_VAR_LOC ();
4043*38fd1498Szrj 	df_insn_rescan (dbg);
4044*38fd1498Szrj 
4045*38fd1498Szrj 	/* Unknown location doesn't use any registers.  */
4046*38fd1498Szrj 	for (use = INSN_REG_USE_LIST (dbg); use != NULL; use = next)
4047*38fd1498Szrj 	  {
4048*38fd1498Szrj 	    struct reg_use_data *prev = use;
4049*38fd1498Szrj 
4050*38fd1498Szrj 	    /* Remove use from the cyclic next_regno_use chain first.  */
4051*38fd1498Szrj 	    while (prev->next_regno_use != use)
4052*38fd1498Szrj 	      prev = prev->next_regno_use;
4053*38fd1498Szrj 	    prev->next_regno_use = use->next_regno_use;
4054*38fd1498Szrj 	    next = use->next_insn_use;
4055*38fd1498Szrj 	    free (use);
4056*38fd1498Szrj 	  }
4057*38fd1498Szrj 	INSN_REG_USE_LIST (dbg) = NULL;
4058*38fd1498Szrj 
4059*38fd1498Szrj 	/* We delete rather than resolve these deps, otherwise we
4060*38fd1498Szrj 	   crash in sched_free_deps(), because forward deps are
4061*38fd1498Szrj 	   expected to be released before backward deps.  */
4062*38fd1498Szrj 	sd_delete_dep (sd_it);
4063*38fd1498Szrj       }
4064*38fd1498Szrj 
4065*38fd1498Szrj   gcc_assert (QUEUE_INDEX (insn) == QUEUE_NOWHERE);
4066*38fd1498Szrj   QUEUE_INDEX (insn) = QUEUE_SCHEDULED;
4067*38fd1498Szrj 
4068*38fd1498Szrj   if (sched_pressure == SCHED_PRESSURE_MODEL
4069*38fd1498Szrj       && model_curr_point < model_num_insns
4070*38fd1498Szrj       && NONDEBUG_INSN_P (insn))
4071*38fd1498Szrj     {
4072*38fd1498Szrj       if (model_index (insn) == model_curr_point)
4073*38fd1498Szrj 	do
4074*38fd1498Szrj 	  model_curr_point++;
4075*38fd1498Szrj 	while (model_curr_point < model_num_insns
4076*38fd1498Szrj 	       && (QUEUE_INDEX (MODEL_INSN (model_curr_point))
4077*38fd1498Szrj 		   == QUEUE_SCHEDULED));
4078*38fd1498Szrj       else
4079*38fd1498Szrj 	model_recompute (insn);
4080*38fd1498Szrj       model_update_limit_points ();
4081*38fd1498Szrj       update_register_pressure (insn);
4082*38fd1498Szrj       if (sched_verbose >= 2)
4083*38fd1498Szrj 	print_curr_reg_pressure ();
4084*38fd1498Szrj     }
4085*38fd1498Szrj 
4086*38fd1498Szrj   gcc_assert (INSN_TICK (insn) >= MIN_TICK);
4087*38fd1498Szrj   if (INSN_TICK (insn) > clock_var)
4088*38fd1498Szrj     /* INSN has been prematurely moved from the queue to the ready list.
4089*38fd1498Szrj        This is possible only if following flags are set.  */
4090*38fd1498Szrj     gcc_assert (flag_sched_stalled_insns || sched_fusion);
4091*38fd1498Szrj 
4092*38fd1498Szrj   /* ??? Probably, if INSN is scheduled prematurely, we should leave
4093*38fd1498Szrj      INSN_TICK untouched.  This is a machine-dependent issue, actually.  */
4094*38fd1498Szrj   INSN_TICK (insn) = clock_var;
4095*38fd1498Szrj 
4096*38fd1498Szrj   check_clobbered_conditions (insn);
4097*38fd1498Szrj 
4098*38fd1498Szrj   /* Update dependent instructions.  First, see if by scheduling this insn
4099*38fd1498Szrj      now we broke a dependence in a way that requires us to change another
4100*38fd1498Szrj      insn.  */
4101*38fd1498Szrj   for (sd_it = sd_iterator_start (insn, SD_LIST_SPEC_BACK);
4102*38fd1498Szrj        sd_iterator_cond (&sd_it, &dep); sd_iterator_next (&sd_it))
4103*38fd1498Szrj     {
4104*38fd1498Szrj       struct dep_replacement *desc = DEP_REPLACE (dep);
4105*38fd1498Szrj       rtx_insn *pro = DEP_PRO (dep);
4106*38fd1498Szrj       if (QUEUE_INDEX (pro) != QUEUE_SCHEDULED
4107*38fd1498Szrj 	  && desc != NULL && desc->insn == pro)
4108*38fd1498Szrj 	apply_replacement (dep, false);
4109*38fd1498Szrj     }
4110*38fd1498Szrj 
4111*38fd1498Szrj   /* Go through and resolve forward dependencies.  */
4112*38fd1498Szrj   for (sd_it = sd_iterator_start (insn, SD_LIST_FORW);
4113*38fd1498Szrj        sd_iterator_cond (&sd_it, &dep);)
4114*38fd1498Szrj     {
4115*38fd1498Szrj       rtx_insn *next = DEP_CON (dep);
4116*38fd1498Szrj       bool cancelled = (DEP_STATUS (dep) & DEP_CANCELLED) != 0;
4117*38fd1498Szrj 
4118*38fd1498Szrj       /* Resolve the dependence between INSN and NEXT.
4119*38fd1498Szrj 	 sd_resolve_dep () moves current dep to another list thus
4120*38fd1498Szrj 	 advancing the iterator.  */
4121*38fd1498Szrj       sd_resolve_dep (sd_it);
4122*38fd1498Szrj 
4123*38fd1498Szrj       if (cancelled)
4124*38fd1498Szrj 	{
4125*38fd1498Szrj 	  if (must_restore_pattern_p (next, dep))
4126*38fd1498Szrj 	    restore_pattern (dep, false);
4127*38fd1498Szrj 	  continue;
4128*38fd1498Szrj 	}
4129*38fd1498Szrj 
4130*38fd1498Szrj       /* Don't bother trying to mark next as ready if insn is a debug
4131*38fd1498Szrj 	 insn.  If insn is the last hard dependency, it will have
4132*38fd1498Szrj 	 already been discounted.  */
4133*38fd1498Szrj       if (DEBUG_INSN_P (insn) && !DEBUG_INSN_P (next))
4134*38fd1498Szrj 	continue;
4135*38fd1498Szrj 
4136*38fd1498Szrj       if (!IS_SPECULATION_BRANCHY_CHECK_P (insn))
4137*38fd1498Szrj 	{
4138*38fd1498Szrj 	  int effective_cost;
4139*38fd1498Szrj 
4140*38fd1498Szrj 	  effective_cost = try_ready (next);
4141*38fd1498Szrj 
4142*38fd1498Szrj 	  if (effective_cost >= 0
4143*38fd1498Szrj 	      && SCHED_GROUP_P (next)
4144*38fd1498Szrj 	      && advance < effective_cost)
4145*38fd1498Szrj 	    advance = effective_cost;
4146*38fd1498Szrj 	}
4147*38fd1498Szrj       else
4148*38fd1498Szrj 	/* Check always has only one forward dependence (to the first insn in
4149*38fd1498Szrj 	   the recovery block), therefore, this will be executed only once.  */
4150*38fd1498Szrj 	{
4151*38fd1498Szrj 	  gcc_assert (sd_lists_empty_p (insn, SD_LIST_FORW));
4152*38fd1498Szrj 	  fix_recovery_deps (RECOVERY_BLOCK (insn));
4153*38fd1498Szrj 	}
4154*38fd1498Szrj     }
4155*38fd1498Szrj 
4156*38fd1498Szrj   /* Annotate the instruction with issue information -- TImode
4157*38fd1498Szrj      indicates that the instruction is expected not to be able
4158*38fd1498Szrj      to issue on the same cycle as the previous insn.  A machine
4159*38fd1498Szrj      may use this information to decide how the instruction should
4160*38fd1498Szrj      be aligned.  */
4161*38fd1498Szrj   if (issue_rate > 1
4162*38fd1498Szrj       && GET_CODE (PATTERN (insn)) != USE
4163*38fd1498Szrj       && GET_CODE (PATTERN (insn)) != CLOBBER
4164*38fd1498Szrj       && !DEBUG_INSN_P (insn))
4165*38fd1498Szrj     {
4166*38fd1498Szrj       if (reload_completed)
4167*38fd1498Szrj 	PUT_MODE (insn, clock_var > last_clock_var ? TImode : VOIDmode);
4168*38fd1498Szrj       last_clock_var = clock_var;
4169*38fd1498Szrj     }
4170*38fd1498Szrj 
4171*38fd1498Szrj   if (nonscheduled_insns_begin != NULL_RTX)
4172*38fd1498Szrj     /* Indicate to debug counters that INSN is scheduled.  */
4173*38fd1498Szrj     nonscheduled_insns_begin = insn;
4174*38fd1498Szrj 
4175*38fd1498Szrj   return advance;
4176*38fd1498Szrj }
4177*38fd1498Szrj 
4178*38fd1498Szrj /* Functions for handling of notes.  */
4179*38fd1498Szrj 
4180*38fd1498Szrj /* Add note list that ends on FROM_END to the end of TO_ENDP.  */
4181*38fd1498Szrj void
concat_note_lists(rtx_insn * from_end,rtx_insn ** to_endp)4182*38fd1498Szrj concat_note_lists (rtx_insn *from_end, rtx_insn **to_endp)
4183*38fd1498Szrj {
4184*38fd1498Szrj   rtx_insn *from_start;
4185*38fd1498Szrj 
4186*38fd1498Szrj   /* It's easy when have nothing to concat.  */
4187*38fd1498Szrj   if (from_end == NULL)
4188*38fd1498Szrj     return;
4189*38fd1498Szrj 
4190*38fd1498Szrj   /* It's also easy when destination is empty.  */
4191*38fd1498Szrj   if (*to_endp == NULL)
4192*38fd1498Szrj     {
4193*38fd1498Szrj       *to_endp = from_end;
4194*38fd1498Szrj       return;
4195*38fd1498Szrj     }
4196*38fd1498Szrj 
4197*38fd1498Szrj   from_start = from_end;
4198*38fd1498Szrj   while (PREV_INSN (from_start) != NULL)
4199*38fd1498Szrj     from_start = PREV_INSN (from_start);
4200*38fd1498Szrj 
4201*38fd1498Szrj   SET_PREV_INSN (from_start) = *to_endp;
4202*38fd1498Szrj   SET_NEXT_INSN (*to_endp) = from_start;
4203*38fd1498Szrj   *to_endp = from_end;
4204*38fd1498Szrj }
4205*38fd1498Szrj 
4206*38fd1498Szrj /* Delete notes between HEAD and TAIL and put them in the chain
4207*38fd1498Szrj    of notes ended by NOTE_LIST.  */
4208*38fd1498Szrj void
remove_notes(rtx_insn * head,rtx_insn * tail)4209*38fd1498Szrj remove_notes (rtx_insn *head, rtx_insn *tail)
4210*38fd1498Szrj {
4211*38fd1498Szrj   rtx_insn *next_tail, *insn, *next;
4212*38fd1498Szrj 
4213*38fd1498Szrj   note_list = 0;
4214*38fd1498Szrj   if (head == tail && !INSN_P (head))
4215*38fd1498Szrj     return;
4216*38fd1498Szrj 
4217*38fd1498Szrj   next_tail = NEXT_INSN (tail);
4218*38fd1498Szrj   for (insn = head; insn != next_tail; insn = next)
4219*38fd1498Szrj     {
4220*38fd1498Szrj       next = NEXT_INSN (insn);
4221*38fd1498Szrj       if (!NOTE_P (insn))
4222*38fd1498Szrj 	continue;
4223*38fd1498Szrj 
4224*38fd1498Szrj       switch (NOTE_KIND (insn))
4225*38fd1498Szrj 	{
4226*38fd1498Szrj 	case NOTE_INSN_BASIC_BLOCK:
4227*38fd1498Szrj 	  continue;
4228*38fd1498Szrj 
4229*38fd1498Szrj 	case NOTE_INSN_EPILOGUE_BEG:
4230*38fd1498Szrj 	  if (insn != tail)
4231*38fd1498Szrj 	    {
4232*38fd1498Szrj 	      remove_insn (insn);
4233*38fd1498Szrj 	      add_reg_note (next, REG_SAVE_NOTE,
4234*38fd1498Szrj 			    GEN_INT (NOTE_INSN_EPILOGUE_BEG));
4235*38fd1498Szrj 	      break;
4236*38fd1498Szrj 	    }
4237*38fd1498Szrj 	  /* FALLTHRU */
4238*38fd1498Szrj 
4239*38fd1498Szrj 	default:
4240*38fd1498Szrj 	  remove_insn (insn);
4241*38fd1498Szrj 
4242*38fd1498Szrj 	  /* Add the note to list that ends at NOTE_LIST.  */
4243*38fd1498Szrj 	  SET_PREV_INSN (insn) = note_list;
4244*38fd1498Szrj 	  SET_NEXT_INSN (insn) = NULL_RTX;
4245*38fd1498Szrj 	  if (note_list)
4246*38fd1498Szrj 	    SET_NEXT_INSN (note_list) = insn;
4247*38fd1498Szrj 	  note_list = insn;
4248*38fd1498Szrj 	  break;
4249*38fd1498Szrj 	}
4250*38fd1498Szrj 
4251*38fd1498Szrj       gcc_assert ((sel_sched_p () || insn != tail) && insn != head);
4252*38fd1498Szrj     }
4253*38fd1498Szrj }
4254*38fd1498Szrj 
4255*38fd1498Szrj /* A structure to record enough data to allow us to backtrack the scheduler to
4256*38fd1498Szrj    a previous state.  */
4257*38fd1498Szrj struct haifa_saved_data
4258*38fd1498Szrj {
4259*38fd1498Szrj   /* Next entry on the list.  */
4260*38fd1498Szrj   struct haifa_saved_data *next;
4261*38fd1498Szrj 
4262*38fd1498Szrj   /* Backtracking is associated with scheduling insns that have delay slots.
4263*38fd1498Szrj      DELAY_PAIR points to the structure that contains the insns involved, and
4264*38fd1498Szrj      the number of cycles between them.  */
4265*38fd1498Szrj   struct delay_pair *delay_pair;
4266*38fd1498Szrj 
4267*38fd1498Szrj   /* Data used by the frontend (e.g. sched-ebb or sched-rgn).  */
4268*38fd1498Szrj   void *fe_saved_data;
4269*38fd1498Szrj   /* Data used by the backend.  */
4270*38fd1498Szrj   void *be_saved_data;
4271*38fd1498Szrj 
4272*38fd1498Szrj   /* Copies of global state.  */
4273*38fd1498Szrj   int clock_var, last_clock_var;
4274*38fd1498Szrj   struct ready_list ready;
4275*38fd1498Szrj   state_t curr_state;
4276*38fd1498Szrj 
4277*38fd1498Szrj   rtx_insn *last_scheduled_insn;
4278*38fd1498Szrj   rtx_insn *last_nondebug_scheduled_insn;
4279*38fd1498Szrj   rtx_insn *nonscheduled_insns_begin;
4280*38fd1498Szrj   int cycle_issued_insns;
4281*38fd1498Szrj 
4282*38fd1498Szrj   /* Copies of state used in the inner loop of schedule_block.  */
4283*38fd1498Szrj   struct sched_block_state sched_block;
4284*38fd1498Szrj 
4285*38fd1498Szrj   /* We don't need to save q_ptr, as its value is arbitrary and we can set it
4286*38fd1498Szrj      to 0 when restoring.  */
4287*38fd1498Szrj   int q_size;
4288*38fd1498Szrj   rtx_insn_list **insn_queue;
4289*38fd1498Szrj 
4290*38fd1498Szrj   /* Describe pattern replacements that occurred since this backtrack point
4291*38fd1498Szrj      was queued.  */
4292*38fd1498Szrj   vec<dep_t> replacement_deps;
4293*38fd1498Szrj   vec<int> replace_apply;
4294*38fd1498Szrj 
4295*38fd1498Szrj   /* A copy of the next-cycle replacement vectors at the time of the backtrack
4296*38fd1498Szrj      point.  */
4297*38fd1498Szrj   vec<dep_t> next_cycle_deps;
4298*38fd1498Szrj   vec<int> next_cycle_apply;
4299*38fd1498Szrj };
4300*38fd1498Szrj 
4301*38fd1498Szrj /* A record, in reverse order, of all scheduled insns which have delay slots
4302*38fd1498Szrj    and may require backtracking.  */
4303*38fd1498Szrj static struct haifa_saved_data *backtrack_queue;
4304*38fd1498Szrj 
4305*38fd1498Szrj /* For every dependency of INSN, set the FEEDS_BACKTRACK_INSN bit according
4306*38fd1498Szrj    to SET_P.  */
4307*38fd1498Szrj static void
mark_backtrack_feeds(rtx_insn * insn,int set_p)4308*38fd1498Szrj mark_backtrack_feeds (rtx_insn *insn, int set_p)
4309*38fd1498Szrj {
4310*38fd1498Szrj   sd_iterator_def sd_it;
4311*38fd1498Szrj   dep_t dep;
4312*38fd1498Szrj   FOR_EACH_DEP (insn, SD_LIST_HARD_BACK, sd_it, dep)
4313*38fd1498Szrj     {
4314*38fd1498Szrj       FEEDS_BACKTRACK_INSN (DEP_PRO (dep)) = set_p;
4315*38fd1498Szrj     }
4316*38fd1498Szrj }
4317*38fd1498Szrj 
4318*38fd1498Szrj /* Save the current scheduler state so that we can backtrack to it
4319*38fd1498Szrj    later if necessary.  PAIR gives the insns that make it necessary to
4320*38fd1498Szrj    save this point.  SCHED_BLOCK is the local state of schedule_block
4321*38fd1498Szrj    that need to be saved.  */
4322*38fd1498Szrj static void
save_backtrack_point(struct delay_pair * pair,struct sched_block_state sched_block)4323*38fd1498Szrj save_backtrack_point (struct delay_pair *pair,
4324*38fd1498Szrj 		      struct sched_block_state sched_block)
4325*38fd1498Szrj {
4326*38fd1498Szrj   int i;
4327*38fd1498Szrj   struct haifa_saved_data *save = XNEW (struct haifa_saved_data);
4328*38fd1498Szrj 
4329*38fd1498Szrj   save->curr_state = xmalloc (dfa_state_size);
4330*38fd1498Szrj   memcpy (save->curr_state, curr_state, dfa_state_size);
4331*38fd1498Szrj 
4332*38fd1498Szrj   save->ready.first = ready.first;
4333*38fd1498Szrj   save->ready.n_ready = ready.n_ready;
4334*38fd1498Szrj   save->ready.n_debug = ready.n_debug;
4335*38fd1498Szrj   save->ready.veclen = ready.veclen;
4336*38fd1498Szrj   save->ready.vec = XNEWVEC (rtx_insn *, ready.veclen);
4337*38fd1498Szrj   memcpy (save->ready.vec, ready.vec, ready.veclen * sizeof (rtx));
4338*38fd1498Szrj 
4339*38fd1498Szrj   save->insn_queue = XNEWVEC (rtx_insn_list *, max_insn_queue_index + 1);
4340*38fd1498Szrj   save->q_size = q_size;
4341*38fd1498Szrj   for (i = 0; i <= max_insn_queue_index; i++)
4342*38fd1498Szrj     {
4343*38fd1498Szrj       int q = NEXT_Q_AFTER (q_ptr, i);
4344*38fd1498Szrj       save->insn_queue[i] = copy_INSN_LIST (insn_queue[q]);
4345*38fd1498Szrj     }
4346*38fd1498Szrj 
4347*38fd1498Szrj   save->clock_var = clock_var;
4348*38fd1498Szrj   save->last_clock_var = last_clock_var;
4349*38fd1498Szrj   save->cycle_issued_insns = cycle_issued_insns;
4350*38fd1498Szrj   save->last_scheduled_insn = last_scheduled_insn;
4351*38fd1498Szrj   save->last_nondebug_scheduled_insn = last_nondebug_scheduled_insn;
4352*38fd1498Szrj   save->nonscheduled_insns_begin = nonscheduled_insns_begin;
4353*38fd1498Szrj 
4354*38fd1498Szrj   save->sched_block = sched_block;
4355*38fd1498Szrj 
4356*38fd1498Szrj   save->replacement_deps.create (0);
4357*38fd1498Szrj   save->replace_apply.create (0);
4358*38fd1498Szrj   save->next_cycle_deps = next_cycle_replace_deps.copy ();
4359*38fd1498Szrj   save->next_cycle_apply = next_cycle_apply.copy ();
4360*38fd1498Szrj 
4361*38fd1498Szrj   if (current_sched_info->save_state)
4362*38fd1498Szrj     save->fe_saved_data = (*current_sched_info->save_state) ();
4363*38fd1498Szrj 
4364*38fd1498Szrj   if (targetm.sched.alloc_sched_context)
4365*38fd1498Szrj     {
4366*38fd1498Szrj       save->be_saved_data = targetm.sched.alloc_sched_context ();
4367*38fd1498Szrj       targetm.sched.init_sched_context (save->be_saved_data, false);
4368*38fd1498Szrj     }
4369*38fd1498Szrj   else
4370*38fd1498Szrj     save->be_saved_data = NULL;
4371*38fd1498Szrj 
4372*38fd1498Szrj   save->delay_pair = pair;
4373*38fd1498Szrj 
4374*38fd1498Szrj   save->next = backtrack_queue;
4375*38fd1498Szrj   backtrack_queue = save;
4376*38fd1498Szrj 
4377*38fd1498Szrj   while (pair)
4378*38fd1498Szrj     {
4379*38fd1498Szrj       mark_backtrack_feeds (pair->i2, 1);
4380*38fd1498Szrj       INSN_TICK (pair->i2) = INVALID_TICK;
4381*38fd1498Szrj       INSN_EXACT_TICK (pair->i2) = clock_var + pair_delay (pair);
4382*38fd1498Szrj       SHADOW_P (pair->i2) = pair->stages == 0;
4383*38fd1498Szrj       pair = pair->next_same_i1;
4384*38fd1498Szrj     }
4385*38fd1498Szrj }
4386*38fd1498Szrj 
4387*38fd1498Szrj /* Walk the ready list and all queues. If any insns have unresolved backwards
4388*38fd1498Szrj    dependencies, these must be cancelled deps, broken by predication.  Set or
4389*38fd1498Szrj    clear (depending on SET) the DEP_CANCELLED bit in DEP_STATUS.  */
4390*38fd1498Szrj 
4391*38fd1498Szrj static void
toggle_cancelled_flags(bool set)4392*38fd1498Szrj toggle_cancelled_flags (bool set)
4393*38fd1498Szrj {
4394*38fd1498Szrj   int i;
4395*38fd1498Szrj   sd_iterator_def sd_it;
4396*38fd1498Szrj   dep_t dep;
4397*38fd1498Szrj 
4398*38fd1498Szrj   if (ready.n_ready > 0)
4399*38fd1498Szrj     {
4400*38fd1498Szrj       rtx_insn **first = ready_lastpos (&ready);
4401*38fd1498Szrj       for (i = 0; i < ready.n_ready; i++)
4402*38fd1498Szrj 	FOR_EACH_DEP (first[i], SD_LIST_BACK, sd_it, dep)
4403*38fd1498Szrj 	  if (!DEBUG_INSN_P (DEP_PRO (dep)))
4404*38fd1498Szrj 	    {
4405*38fd1498Szrj 	      if (set)
4406*38fd1498Szrj 		DEP_STATUS (dep) |= DEP_CANCELLED;
4407*38fd1498Szrj 	      else
4408*38fd1498Szrj 		DEP_STATUS (dep) &= ~DEP_CANCELLED;
4409*38fd1498Szrj 	    }
4410*38fd1498Szrj     }
4411*38fd1498Szrj   for (i = 0; i <= max_insn_queue_index; i++)
4412*38fd1498Szrj     {
4413*38fd1498Szrj       int q = NEXT_Q_AFTER (q_ptr, i);
4414*38fd1498Szrj       rtx_insn_list *link;
4415*38fd1498Szrj       for (link = insn_queue[q]; link; link = link->next ())
4416*38fd1498Szrj 	{
4417*38fd1498Szrj 	  rtx_insn *insn = link->insn ();
4418*38fd1498Szrj 	  FOR_EACH_DEP (insn, SD_LIST_BACK, sd_it, dep)
4419*38fd1498Szrj 	    if (!DEBUG_INSN_P (DEP_PRO (dep)))
4420*38fd1498Szrj 	      {
4421*38fd1498Szrj 		if (set)
4422*38fd1498Szrj 		  DEP_STATUS (dep) |= DEP_CANCELLED;
4423*38fd1498Szrj 		else
4424*38fd1498Szrj 		  DEP_STATUS (dep) &= ~DEP_CANCELLED;
4425*38fd1498Szrj 	      }
4426*38fd1498Szrj 	}
4427*38fd1498Szrj     }
4428*38fd1498Szrj }
4429*38fd1498Szrj 
4430*38fd1498Szrj /* Undo the replacements that have occurred after backtrack point SAVE
4431*38fd1498Szrj    was placed.  */
4432*38fd1498Szrj static void
undo_replacements_for_backtrack(struct haifa_saved_data * save)4433*38fd1498Szrj undo_replacements_for_backtrack (struct haifa_saved_data *save)
4434*38fd1498Szrj {
4435*38fd1498Szrj   while (!save->replacement_deps.is_empty ())
4436*38fd1498Szrj     {
4437*38fd1498Szrj       dep_t dep = save->replacement_deps.pop ();
4438*38fd1498Szrj       int apply_p = save->replace_apply.pop ();
4439*38fd1498Szrj 
4440*38fd1498Szrj       if (apply_p)
4441*38fd1498Szrj 	restore_pattern (dep, true);
4442*38fd1498Szrj       else
4443*38fd1498Szrj 	apply_replacement (dep, true);
4444*38fd1498Szrj     }
4445*38fd1498Szrj   save->replacement_deps.release ();
4446*38fd1498Szrj   save->replace_apply.release ();
4447*38fd1498Szrj }
4448*38fd1498Szrj 
4449*38fd1498Szrj /* Pop entries from the SCHEDULED_INSNS vector up to and including INSN.
4450*38fd1498Szrj    Restore their dependencies to an unresolved state, and mark them as
4451*38fd1498Szrj    queued nowhere.  */
4452*38fd1498Szrj 
4453*38fd1498Szrj static void
unschedule_insns_until(rtx_insn * insn)4454*38fd1498Szrj unschedule_insns_until (rtx_insn *insn)
4455*38fd1498Szrj {
4456*38fd1498Szrj   auto_vec<rtx_insn *> recompute_vec;
4457*38fd1498Szrj 
4458*38fd1498Szrj   /* Make two passes over the insns to be unscheduled.  First, we clear out
4459*38fd1498Szrj      dependencies and other trivial bookkeeping.  */
4460*38fd1498Szrj   for (;;)
4461*38fd1498Szrj     {
4462*38fd1498Szrj       rtx_insn *last;
4463*38fd1498Szrj       sd_iterator_def sd_it;
4464*38fd1498Szrj       dep_t dep;
4465*38fd1498Szrj 
4466*38fd1498Szrj       last = scheduled_insns.pop ();
4467*38fd1498Szrj 
4468*38fd1498Szrj       /* This will be changed by restore_backtrack_point if the insn is in
4469*38fd1498Szrj 	 any queue.  */
4470*38fd1498Szrj       QUEUE_INDEX (last) = QUEUE_NOWHERE;
4471*38fd1498Szrj       if (last != insn)
4472*38fd1498Szrj 	INSN_TICK (last) = INVALID_TICK;
4473*38fd1498Szrj 
4474*38fd1498Szrj       if (modulo_ii > 0 && INSN_UID (last) < modulo_iter0_max_uid)
4475*38fd1498Szrj 	modulo_insns_scheduled--;
4476*38fd1498Szrj 
4477*38fd1498Szrj       for (sd_it = sd_iterator_start (last, SD_LIST_RES_FORW);
4478*38fd1498Szrj 	   sd_iterator_cond (&sd_it, &dep);)
4479*38fd1498Szrj 	{
4480*38fd1498Szrj 	  rtx_insn *con = DEP_CON (dep);
4481*38fd1498Szrj 	  sd_unresolve_dep (sd_it);
4482*38fd1498Szrj 	  if (!MUST_RECOMPUTE_SPEC_P (con))
4483*38fd1498Szrj 	    {
4484*38fd1498Szrj 	      MUST_RECOMPUTE_SPEC_P (con) = 1;
4485*38fd1498Szrj 	      recompute_vec.safe_push (con);
4486*38fd1498Szrj 	    }
4487*38fd1498Szrj 	}
4488*38fd1498Szrj 
4489*38fd1498Szrj       if (last == insn)
4490*38fd1498Szrj 	break;
4491*38fd1498Szrj     }
4492*38fd1498Szrj 
4493*38fd1498Szrj   /* A second pass, to update ready and speculation status for insns
4494*38fd1498Szrj      depending on the unscheduled ones.  The first pass must have
4495*38fd1498Szrj      popped the scheduled_insns vector up to the point where we
4496*38fd1498Szrj      restart scheduling, as recompute_todo_spec requires it to be
4497*38fd1498Szrj      up-to-date.  */
4498*38fd1498Szrj   while (!recompute_vec.is_empty ())
4499*38fd1498Szrj     {
4500*38fd1498Szrj       rtx_insn *con;
4501*38fd1498Szrj 
4502*38fd1498Szrj       con = recompute_vec.pop ();
4503*38fd1498Szrj       MUST_RECOMPUTE_SPEC_P (con) = 0;
4504*38fd1498Szrj       if (!sd_lists_empty_p (con, SD_LIST_HARD_BACK))
4505*38fd1498Szrj 	{
4506*38fd1498Szrj 	  TODO_SPEC (con) = HARD_DEP;
4507*38fd1498Szrj 	  INSN_TICK (con) = INVALID_TICK;
4508*38fd1498Szrj 	  if (PREDICATED_PAT (con) != NULL_RTX)
4509*38fd1498Szrj 	    haifa_change_pattern (con, ORIG_PAT (con));
4510*38fd1498Szrj 	}
4511*38fd1498Szrj       else if (QUEUE_INDEX (con) != QUEUE_SCHEDULED)
4512*38fd1498Szrj 	TODO_SPEC (con) = recompute_todo_spec (con, true);
4513*38fd1498Szrj     }
4514*38fd1498Szrj }
4515*38fd1498Szrj 
4516*38fd1498Szrj /* Restore scheduler state from the topmost entry on the backtracking queue.
4517*38fd1498Szrj    PSCHED_BLOCK_P points to the local data of schedule_block that we must
4518*38fd1498Szrj    overwrite with the saved data.
4519*38fd1498Szrj    The caller must already have called unschedule_insns_until.  */
4520*38fd1498Szrj 
4521*38fd1498Szrj static void
restore_last_backtrack_point(struct sched_block_state * psched_block)4522*38fd1498Szrj restore_last_backtrack_point (struct sched_block_state *psched_block)
4523*38fd1498Szrj {
4524*38fd1498Szrj   int i;
4525*38fd1498Szrj   struct haifa_saved_data *save = backtrack_queue;
4526*38fd1498Szrj 
4527*38fd1498Szrj   backtrack_queue = save->next;
4528*38fd1498Szrj 
4529*38fd1498Szrj   if (current_sched_info->restore_state)
4530*38fd1498Szrj     (*current_sched_info->restore_state) (save->fe_saved_data);
4531*38fd1498Szrj 
4532*38fd1498Szrj   if (targetm.sched.alloc_sched_context)
4533*38fd1498Szrj     {
4534*38fd1498Szrj       targetm.sched.set_sched_context (save->be_saved_data);
4535*38fd1498Szrj       targetm.sched.free_sched_context (save->be_saved_data);
4536*38fd1498Szrj     }
4537*38fd1498Szrj 
4538*38fd1498Szrj   /* Do this first since it clobbers INSN_TICK of the involved
4539*38fd1498Szrj      instructions.  */
4540*38fd1498Szrj   undo_replacements_for_backtrack (save);
4541*38fd1498Szrj 
4542*38fd1498Szrj   /* Clear the QUEUE_INDEX of everything in the ready list or one
4543*38fd1498Szrj      of the queues.  */
4544*38fd1498Szrj   if (ready.n_ready > 0)
4545*38fd1498Szrj     {
4546*38fd1498Szrj       rtx_insn **first = ready_lastpos (&ready);
4547*38fd1498Szrj       for (i = 0; i < ready.n_ready; i++)
4548*38fd1498Szrj 	{
4549*38fd1498Szrj 	  rtx_insn *insn = first[i];
4550*38fd1498Szrj 	  QUEUE_INDEX (insn) = QUEUE_NOWHERE;
4551*38fd1498Szrj 	  INSN_TICK (insn) = INVALID_TICK;
4552*38fd1498Szrj 	}
4553*38fd1498Szrj     }
4554*38fd1498Szrj   for (i = 0; i <= max_insn_queue_index; i++)
4555*38fd1498Szrj     {
4556*38fd1498Szrj       int q = NEXT_Q_AFTER (q_ptr, i);
4557*38fd1498Szrj 
4558*38fd1498Szrj       for (rtx_insn_list *link = insn_queue[q]; link; link = link->next ())
4559*38fd1498Szrj 	{
4560*38fd1498Szrj 	  rtx_insn *x = link->insn ();
4561*38fd1498Szrj 	  QUEUE_INDEX (x) = QUEUE_NOWHERE;
4562*38fd1498Szrj 	  INSN_TICK (x) = INVALID_TICK;
4563*38fd1498Szrj 	}
4564*38fd1498Szrj       free_INSN_LIST_list (&insn_queue[q]);
4565*38fd1498Szrj     }
4566*38fd1498Szrj 
4567*38fd1498Szrj   free (ready.vec);
4568*38fd1498Szrj   ready = save->ready;
4569*38fd1498Szrj 
4570*38fd1498Szrj   if (ready.n_ready > 0)
4571*38fd1498Szrj     {
4572*38fd1498Szrj       rtx_insn **first = ready_lastpos (&ready);
4573*38fd1498Szrj       for (i = 0; i < ready.n_ready; i++)
4574*38fd1498Szrj 	{
4575*38fd1498Szrj 	  rtx_insn *insn = first[i];
4576*38fd1498Szrj 	  QUEUE_INDEX (insn) = QUEUE_READY;
4577*38fd1498Szrj 	  TODO_SPEC (insn) = recompute_todo_spec (insn, true);
4578*38fd1498Szrj 	  INSN_TICK (insn) = save->clock_var;
4579*38fd1498Szrj 	}
4580*38fd1498Szrj     }
4581*38fd1498Szrj 
4582*38fd1498Szrj   q_ptr = 0;
4583*38fd1498Szrj   q_size = save->q_size;
4584*38fd1498Szrj   for (i = 0; i <= max_insn_queue_index; i++)
4585*38fd1498Szrj     {
4586*38fd1498Szrj       int q = NEXT_Q_AFTER (q_ptr, i);
4587*38fd1498Szrj 
4588*38fd1498Szrj       insn_queue[q] = save->insn_queue[q];
4589*38fd1498Szrj 
4590*38fd1498Szrj       for (rtx_insn_list *link = insn_queue[q]; link; link = link->next ())
4591*38fd1498Szrj 	{
4592*38fd1498Szrj 	  rtx_insn *x = link->insn ();
4593*38fd1498Szrj 	  QUEUE_INDEX (x) = i;
4594*38fd1498Szrj 	  TODO_SPEC (x) = recompute_todo_spec (x, true);
4595*38fd1498Szrj 	  INSN_TICK (x) = save->clock_var + i;
4596*38fd1498Szrj 	}
4597*38fd1498Szrj     }
4598*38fd1498Szrj   free (save->insn_queue);
4599*38fd1498Szrj 
4600*38fd1498Szrj   toggle_cancelled_flags (true);
4601*38fd1498Szrj 
4602*38fd1498Szrj   clock_var = save->clock_var;
4603*38fd1498Szrj   last_clock_var = save->last_clock_var;
4604*38fd1498Szrj   cycle_issued_insns = save->cycle_issued_insns;
4605*38fd1498Szrj   last_scheduled_insn = save->last_scheduled_insn;
4606*38fd1498Szrj   last_nondebug_scheduled_insn = save->last_nondebug_scheduled_insn;
4607*38fd1498Szrj   nonscheduled_insns_begin = save->nonscheduled_insns_begin;
4608*38fd1498Szrj 
4609*38fd1498Szrj   *psched_block = save->sched_block;
4610*38fd1498Szrj 
4611*38fd1498Szrj   memcpy (curr_state, save->curr_state, dfa_state_size);
4612*38fd1498Szrj   free (save->curr_state);
4613*38fd1498Szrj 
4614*38fd1498Szrj   mark_backtrack_feeds (save->delay_pair->i2, 0);
4615*38fd1498Szrj 
4616*38fd1498Szrj   gcc_assert (next_cycle_replace_deps.is_empty ());
4617*38fd1498Szrj   next_cycle_replace_deps = save->next_cycle_deps.copy ();
4618*38fd1498Szrj   next_cycle_apply = save->next_cycle_apply.copy ();
4619*38fd1498Szrj 
4620*38fd1498Szrj   free (save);
4621*38fd1498Szrj 
4622*38fd1498Szrj   for (save = backtrack_queue; save; save = save->next)
4623*38fd1498Szrj     {
4624*38fd1498Szrj       mark_backtrack_feeds (save->delay_pair->i2, 1);
4625*38fd1498Szrj     }
4626*38fd1498Szrj }
4627*38fd1498Szrj 
4628*38fd1498Szrj /* Discard all data associated with the topmost entry in the backtrack
4629*38fd1498Szrj    queue.  If RESET_TICK is false, we just want to free the data.  If true,
4630*38fd1498Szrj    we are doing this because we discovered a reason to backtrack.  In the
4631*38fd1498Szrj    latter case, also reset the INSN_TICK for the shadow insn.  */
4632*38fd1498Szrj static void
free_topmost_backtrack_point(bool reset_tick)4633*38fd1498Szrj free_topmost_backtrack_point (bool reset_tick)
4634*38fd1498Szrj {
4635*38fd1498Szrj   struct haifa_saved_data *save = backtrack_queue;
4636*38fd1498Szrj   int i;
4637*38fd1498Szrj 
4638*38fd1498Szrj   backtrack_queue = save->next;
4639*38fd1498Szrj 
4640*38fd1498Szrj   if (reset_tick)
4641*38fd1498Szrj     {
4642*38fd1498Szrj       struct delay_pair *pair = save->delay_pair;
4643*38fd1498Szrj       while (pair)
4644*38fd1498Szrj 	{
4645*38fd1498Szrj 	  INSN_TICK (pair->i2) = INVALID_TICK;
4646*38fd1498Szrj 	  INSN_EXACT_TICK (pair->i2) = INVALID_TICK;
4647*38fd1498Szrj 	  pair = pair->next_same_i1;
4648*38fd1498Szrj 	}
4649*38fd1498Szrj       undo_replacements_for_backtrack (save);
4650*38fd1498Szrj     }
4651*38fd1498Szrj   else
4652*38fd1498Szrj     {
4653*38fd1498Szrj       save->replacement_deps.release ();
4654*38fd1498Szrj       save->replace_apply.release ();
4655*38fd1498Szrj     }
4656*38fd1498Szrj 
4657*38fd1498Szrj   if (targetm.sched.free_sched_context)
4658*38fd1498Szrj     targetm.sched.free_sched_context (save->be_saved_data);
4659*38fd1498Szrj   if (current_sched_info->restore_state)
4660*38fd1498Szrj     free (save->fe_saved_data);
4661*38fd1498Szrj   for (i = 0; i <= max_insn_queue_index; i++)
4662*38fd1498Szrj     free_INSN_LIST_list (&save->insn_queue[i]);
4663*38fd1498Szrj   free (save->insn_queue);
4664*38fd1498Szrj   free (save->curr_state);
4665*38fd1498Szrj   free (save->ready.vec);
4666*38fd1498Szrj   free (save);
4667*38fd1498Szrj }
4668*38fd1498Szrj 
4669*38fd1498Szrj /* Free the entire backtrack queue.  */
4670*38fd1498Szrj static void
free_backtrack_queue(void)4671*38fd1498Szrj free_backtrack_queue (void)
4672*38fd1498Szrj {
4673*38fd1498Szrj   while (backtrack_queue)
4674*38fd1498Szrj     free_topmost_backtrack_point (false);
4675*38fd1498Szrj }
4676*38fd1498Szrj 
4677*38fd1498Szrj /* Apply a replacement described by DESC.  If IMMEDIATELY is false, we
4678*38fd1498Szrj    may have to postpone the replacement until the start of the next cycle,
4679*38fd1498Szrj    at which point we will be called again with IMMEDIATELY true.  This is
4680*38fd1498Szrj    only done for machines which have instruction packets with explicit
4681*38fd1498Szrj    parallelism however.  */
4682*38fd1498Szrj static void
apply_replacement(dep_t dep,bool immediately)4683*38fd1498Szrj apply_replacement (dep_t dep, bool immediately)
4684*38fd1498Szrj {
4685*38fd1498Szrj   struct dep_replacement *desc = DEP_REPLACE (dep);
4686*38fd1498Szrj   if (!immediately && targetm.sched.exposed_pipeline && reload_completed)
4687*38fd1498Szrj     {
4688*38fd1498Szrj       next_cycle_replace_deps.safe_push (dep);
4689*38fd1498Szrj       next_cycle_apply.safe_push (1);
4690*38fd1498Szrj     }
4691*38fd1498Szrj   else
4692*38fd1498Szrj     {
4693*38fd1498Szrj       bool success;
4694*38fd1498Szrj 
4695*38fd1498Szrj       if (QUEUE_INDEX (desc->insn) == QUEUE_SCHEDULED)
4696*38fd1498Szrj 	return;
4697*38fd1498Szrj 
4698*38fd1498Szrj       if (sched_verbose >= 5)
4699*38fd1498Szrj 	fprintf (sched_dump, "applying replacement for insn %d\n",
4700*38fd1498Szrj 		 INSN_UID (desc->insn));
4701*38fd1498Szrj 
4702*38fd1498Szrj       success = validate_change (desc->insn, desc->loc, desc->newval, 0);
4703*38fd1498Szrj       gcc_assert (success);
4704*38fd1498Szrj 
4705*38fd1498Szrj       update_insn_after_change (desc->insn);
4706*38fd1498Szrj       if ((TODO_SPEC (desc->insn) & (HARD_DEP | DEP_POSTPONED)) == 0)
4707*38fd1498Szrj 	fix_tick_ready (desc->insn);
4708*38fd1498Szrj 
4709*38fd1498Szrj       if (backtrack_queue != NULL)
4710*38fd1498Szrj 	{
4711*38fd1498Szrj 	  backtrack_queue->replacement_deps.safe_push (dep);
4712*38fd1498Szrj 	  backtrack_queue->replace_apply.safe_push (1);
4713*38fd1498Szrj 	}
4714*38fd1498Szrj     }
4715*38fd1498Szrj }
4716*38fd1498Szrj 
4717*38fd1498Szrj /* We have determined that a pattern involved in DEP must be restored.
4718*38fd1498Szrj    If IMMEDIATELY is false, we may have to postpone the replacement
4719*38fd1498Szrj    until the start of the next cycle, at which point we will be called
4720*38fd1498Szrj    again with IMMEDIATELY true.  */
4721*38fd1498Szrj static void
restore_pattern(dep_t dep,bool immediately)4722*38fd1498Szrj restore_pattern (dep_t dep, bool immediately)
4723*38fd1498Szrj {
4724*38fd1498Szrj   rtx_insn *next = DEP_CON (dep);
4725*38fd1498Szrj   int tick = INSN_TICK (next);
4726*38fd1498Szrj 
4727*38fd1498Szrj   /* If we already scheduled the insn, the modified version is
4728*38fd1498Szrj      correct.  */
4729*38fd1498Szrj   if (QUEUE_INDEX (next) == QUEUE_SCHEDULED)
4730*38fd1498Szrj     return;
4731*38fd1498Szrj 
4732*38fd1498Szrj   if (!immediately && targetm.sched.exposed_pipeline && reload_completed)
4733*38fd1498Szrj     {
4734*38fd1498Szrj       next_cycle_replace_deps.safe_push (dep);
4735*38fd1498Szrj       next_cycle_apply.safe_push (0);
4736*38fd1498Szrj       return;
4737*38fd1498Szrj     }
4738*38fd1498Szrj 
4739*38fd1498Szrj 
4740*38fd1498Szrj   if (DEP_TYPE (dep) == REG_DEP_CONTROL)
4741*38fd1498Szrj     {
4742*38fd1498Szrj       if (sched_verbose >= 5)
4743*38fd1498Szrj 	fprintf (sched_dump, "restoring pattern for insn %d\n",
4744*38fd1498Szrj 		 INSN_UID (next));
4745*38fd1498Szrj       haifa_change_pattern (next, ORIG_PAT (next));
4746*38fd1498Szrj     }
4747*38fd1498Szrj   else
4748*38fd1498Szrj     {
4749*38fd1498Szrj       struct dep_replacement *desc = DEP_REPLACE (dep);
4750*38fd1498Szrj       bool success;
4751*38fd1498Szrj 
4752*38fd1498Szrj       if (sched_verbose >= 5)
4753*38fd1498Szrj 	fprintf (sched_dump, "restoring pattern for insn %d\n",
4754*38fd1498Szrj 		 INSN_UID (desc->insn));
4755*38fd1498Szrj       tick = INSN_TICK (desc->insn);
4756*38fd1498Szrj 
4757*38fd1498Szrj       success = validate_change (desc->insn, desc->loc, desc->orig, 0);
4758*38fd1498Szrj       gcc_assert (success);
4759*38fd1498Szrj       update_insn_after_change (desc->insn);
4760*38fd1498Szrj       if (backtrack_queue != NULL)
4761*38fd1498Szrj 	{
4762*38fd1498Szrj 	  backtrack_queue->replacement_deps.safe_push (dep);
4763*38fd1498Szrj 	  backtrack_queue->replace_apply.safe_push (0);
4764*38fd1498Szrj 	}
4765*38fd1498Szrj     }
4766*38fd1498Szrj   INSN_TICK (next) = tick;
4767*38fd1498Szrj   if (TODO_SPEC (next) == DEP_POSTPONED)
4768*38fd1498Szrj     return;
4769*38fd1498Szrj 
4770*38fd1498Szrj   if (sd_lists_empty_p (next, SD_LIST_BACK))
4771*38fd1498Szrj     TODO_SPEC (next) = 0;
4772*38fd1498Szrj   else if (!sd_lists_empty_p (next, SD_LIST_HARD_BACK))
4773*38fd1498Szrj     TODO_SPEC (next) = HARD_DEP;
4774*38fd1498Szrj }
4775*38fd1498Szrj 
4776*38fd1498Szrj /* Perform pattern replacements that were queued up until the next
4777*38fd1498Szrj    cycle.  */
4778*38fd1498Szrj static void
perform_replacements_new_cycle(void)4779*38fd1498Szrj perform_replacements_new_cycle (void)
4780*38fd1498Szrj {
4781*38fd1498Szrj   int i;
4782*38fd1498Szrj   dep_t dep;
4783*38fd1498Szrj   FOR_EACH_VEC_ELT (next_cycle_replace_deps, i, dep)
4784*38fd1498Szrj     {
4785*38fd1498Szrj       int apply_p = next_cycle_apply[i];
4786*38fd1498Szrj       if (apply_p)
4787*38fd1498Szrj 	apply_replacement (dep, true);
4788*38fd1498Szrj       else
4789*38fd1498Szrj 	restore_pattern (dep, true);
4790*38fd1498Szrj     }
4791*38fd1498Szrj   next_cycle_replace_deps.truncate (0);
4792*38fd1498Szrj   next_cycle_apply.truncate (0);
4793*38fd1498Szrj }
4794*38fd1498Szrj 
4795*38fd1498Szrj /* Compute INSN_TICK_ESTIMATE for INSN.  PROCESSED is a bitmap of
4796*38fd1498Szrj    instructions we've previously encountered, a set bit prevents
4797*38fd1498Szrj    recursion.  BUDGET is a limit on how far ahead we look, it is
4798*38fd1498Szrj    reduced on recursive calls.  Return true if we produced a good
4799*38fd1498Szrj    estimate, or false if we exceeded the budget.  */
4800*38fd1498Szrj static bool
estimate_insn_tick(bitmap processed,rtx_insn * insn,int budget)4801*38fd1498Szrj estimate_insn_tick (bitmap processed, rtx_insn *insn, int budget)
4802*38fd1498Szrj {
4803*38fd1498Szrj   sd_iterator_def sd_it;
4804*38fd1498Szrj   dep_t dep;
4805*38fd1498Szrj   int earliest = INSN_TICK (insn);
4806*38fd1498Szrj 
4807*38fd1498Szrj   FOR_EACH_DEP (insn, SD_LIST_BACK, sd_it, dep)
4808*38fd1498Szrj     {
4809*38fd1498Szrj       rtx_insn *pro = DEP_PRO (dep);
4810*38fd1498Szrj       int t;
4811*38fd1498Szrj 
4812*38fd1498Szrj       if (DEP_STATUS (dep) & DEP_CANCELLED)
4813*38fd1498Szrj 	continue;
4814*38fd1498Szrj 
4815*38fd1498Szrj       if (QUEUE_INDEX (pro) == QUEUE_SCHEDULED)
4816*38fd1498Szrj 	gcc_assert (INSN_TICK (pro) + dep_cost (dep) <= INSN_TICK (insn));
4817*38fd1498Szrj       else
4818*38fd1498Szrj 	{
4819*38fd1498Szrj 	  int cost = dep_cost (dep);
4820*38fd1498Szrj 	  if (cost >= budget)
4821*38fd1498Szrj 	    return false;
4822*38fd1498Szrj 	  if (!bitmap_bit_p (processed, INSN_LUID (pro)))
4823*38fd1498Szrj 	    {
4824*38fd1498Szrj 	      if (!estimate_insn_tick (processed, pro, budget - cost))
4825*38fd1498Szrj 		return false;
4826*38fd1498Szrj 	    }
4827*38fd1498Szrj 	  gcc_assert (INSN_TICK_ESTIMATE (pro) != INVALID_TICK);
4828*38fd1498Szrj 	  t = INSN_TICK_ESTIMATE (pro) + cost;
4829*38fd1498Szrj 	  if (earliest == INVALID_TICK || t > earliest)
4830*38fd1498Szrj 	    earliest = t;
4831*38fd1498Szrj 	}
4832*38fd1498Szrj     }
4833*38fd1498Szrj   bitmap_set_bit (processed, INSN_LUID (insn));
4834*38fd1498Szrj   INSN_TICK_ESTIMATE (insn) = earliest;
4835*38fd1498Szrj   return true;
4836*38fd1498Szrj }
4837*38fd1498Szrj 
4838*38fd1498Szrj /* Examine the pair of insns in P, and estimate (optimistically, assuming
4839*38fd1498Szrj    infinite resources) the cycle in which the delayed shadow can be issued.
4840*38fd1498Szrj    Return the number of cycles that must pass before the real insn can be
4841*38fd1498Szrj    issued in order to meet this constraint.  */
4842*38fd1498Szrj static int
estimate_shadow_tick(struct delay_pair * p)4843*38fd1498Szrj estimate_shadow_tick (struct delay_pair *p)
4844*38fd1498Szrj {
4845*38fd1498Szrj   auto_bitmap processed;
4846*38fd1498Szrj   int t;
4847*38fd1498Szrj   bool cutoff;
4848*38fd1498Szrj 
4849*38fd1498Szrj   cutoff = !estimate_insn_tick (processed, p->i2,
4850*38fd1498Szrj 				max_insn_queue_index + pair_delay (p));
4851*38fd1498Szrj   if (cutoff)
4852*38fd1498Szrj     return max_insn_queue_index;
4853*38fd1498Szrj   t = INSN_TICK_ESTIMATE (p->i2) - (clock_var + pair_delay (p) + 1);
4854*38fd1498Szrj   if (t > 0)
4855*38fd1498Szrj     return t;
4856*38fd1498Szrj   return 0;
4857*38fd1498Szrj }
4858*38fd1498Szrj 
4859*38fd1498Szrj /* If INSN has no unresolved backwards dependencies, add it to the schedule and
4860*38fd1498Szrj    recursively resolve all its forward dependencies.  */
4861*38fd1498Szrj static void
resolve_dependencies(rtx_insn * insn)4862*38fd1498Szrj resolve_dependencies (rtx_insn *insn)
4863*38fd1498Szrj {
4864*38fd1498Szrj   sd_iterator_def sd_it;
4865*38fd1498Szrj   dep_t dep;
4866*38fd1498Szrj 
4867*38fd1498Szrj   /* Don't use sd_lists_empty_p; it ignores debug insns.  */
4868*38fd1498Szrj   if (DEPS_LIST_FIRST (INSN_HARD_BACK_DEPS (insn)) != NULL
4869*38fd1498Szrj       || DEPS_LIST_FIRST (INSN_SPEC_BACK_DEPS (insn)) != NULL)
4870*38fd1498Szrj     return;
4871*38fd1498Szrj 
4872*38fd1498Szrj   if (sched_verbose >= 4)
4873*38fd1498Szrj     fprintf (sched_dump, ";;\tquickly resolving %d\n", INSN_UID (insn));
4874*38fd1498Szrj 
4875*38fd1498Szrj   if (QUEUE_INDEX (insn) >= 0)
4876*38fd1498Szrj     queue_remove (insn);
4877*38fd1498Szrj 
4878*38fd1498Szrj   scheduled_insns.safe_push (insn);
4879*38fd1498Szrj 
4880*38fd1498Szrj   /* Update dependent instructions.  */
4881*38fd1498Szrj   for (sd_it = sd_iterator_start (insn, SD_LIST_FORW);
4882*38fd1498Szrj        sd_iterator_cond (&sd_it, &dep);)
4883*38fd1498Szrj     {
4884*38fd1498Szrj       rtx_insn *next = DEP_CON (dep);
4885*38fd1498Szrj 
4886*38fd1498Szrj       if (sched_verbose >= 4)
4887*38fd1498Szrj 	fprintf (sched_dump, ";;\t\tdep %d against %d\n", INSN_UID (insn),
4888*38fd1498Szrj 		 INSN_UID (next));
4889*38fd1498Szrj 
4890*38fd1498Szrj       /* Resolve the dependence between INSN and NEXT.
4891*38fd1498Szrj 	 sd_resolve_dep () moves current dep to another list thus
4892*38fd1498Szrj 	 advancing the iterator.  */
4893*38fd1498Szrj       sd_resolve_dep (sd_it);
4894*38fd1498Szrj 
4895*38fd1498Szrj       if (!IS_SPECULATION_BRANCHY_CHECK_P (insn))
4896*38fd1498Szrj 	{
4897*38fd1498Szrj 	  resolve_dependencies (next);
4898*38fd1498Szrj 	}
4899*38fd1498Szrj       else
4900*38fd1498Szrj 	/* Check always has only one forward dependence (to the first insn in
4901*38fd1498Szrj 	   the recovery block), therefore, this will be executed only once.  */
4902*38fd1498Szrj 	{
4903*38fd1498Szrj 	  gcc_assert (sd_lists_empty_p (insn, SD_LIST_FORW));
4904*38fd1498Szrj 	}
4905*38fd1498Szrj     }
4906*38fd1498Szrj }
4907*38fd1498Szrj 
4908*38fd1498Szrj 
4909*38fd1498Szrj /* Return the head and tail pointers of ebb starting at BEG and ending
4910*38fd1498Szrj    at END.  */
4911*38fd1498Szrj void
get_ebb_head_tail(basic_block beg,basic_block end,rtx_insn ** headp,rtx_insn ** tailp)4912*38fd1498Szrj get_ebb_head_tail (basic_block beg, basic_block end,
4913*38fd1498Szrj 		   rtx_insn **headp, rtx_insn **tailp)
4914*38fd1498Szrj {
4915*38fd1498Szrj   rtx_insn *beg_head = BB_HEAD (beg);
4916*38fd1498Szrj   rtx_insn * beg_tail = BB_END (beg);
4917*38fd1498Szrj   rtx_insn * end_head = BB_HEAD (end);
4918*38fd1498Szrj   rtx_insn * end_tail = BB_END (end);
4919*38fd1498Szrj 
4920*38fd1498Szrj   /* Don't include any notes or labels at the beginning of the BEG
4921*38fd1498Szrj      basic block, or notes at the end of the END basic blocks.  */
4922*38fd1498Szrj 
4923*38fd1498Szrj   if (LABEL_P (beg_head))
4924*38fd1498Szrj     beg_head = NEXT_INSN (beg_head);
4925*38fd1498Szrj 
4926*38fd1498Szrj   while (beg_head != beg_tail)
4927*38fd1498Szrj     if (NOTE_P (beg_head))
4928*38fd1498Szrj       beg_head = NEXT_INSN (beg_head);
4929*38fd1498Szrj     else if (DEBUG_INSN_P (beg_head))
4930*38fd1498Szrj       {
4931*38fd1498Szrj 	rtx_insn * note, *next;
4932*38fd1498Szrj 
4933*38fd1498Szrj 	for (note = NEXT_INSN (beg_head);
4934*38fd1498Szrj 	     note != beg_tail;
4935*38fd1498Szrj 	     note = next)
4936*38fd1498Szrj 	  {
4937*38fd1498Szrj 	    next = NEXT_INSN (note);
4938*38fd1498Szrj 	    if (NOTE_P (note))
4939*38fd1498Szrj 	      {
4940*38fd1498Szrj 		if (sched_verbose >= 9)
4941*38fd1498Szrj 		  fprintf (sched_dump, "reorder %i\n", INSN_UID (note));
4942*38fd1498Szrj 
4943*38fd1498Szrj 		reorder_insns_nobb (note, note, PREV_INSN (beg_head));
4944*38fd1498Szrj 
4945*38fd1498Szrj 		if (BLOCK_FOR_INSN (note) != beg)
4946*38fd1498Szrj 		  df_insn_change_bb (note, beg);
4947*38fd1498Szrj 	      }
4948*38fd1498Szrj 	    else if (!DEBUG_INSN_P (note))
4949*38fd1498Szrj 	      break;
4950*38fd1498Szrj 	  }
4951*38fd1498Szrj 
4952*38fd1498Szrj 	break;
4953*38fd1498Szrj       }
4954*38fd1498Szrj     else
4955*38fd1498Szrj       break;
4956*38fd1498Szrj 
4957*38fd1498Szrj   *headp = beg_head;
4958*38fd1498Szrj 
4959*38fd1498Szrj   if (beg == end)
4960*38fd1498Szrj     end_head = beg_head;
4961*38fd1498Szrj   else if (LABEL_P (end_head))
4962*38fd1498Szrj     end_head = NEXT_INSN (end_head);
4963*38fd1498Szrj 
4964*38fd1498Szrj   while (end_head != end_tail)
4965*38fd1498Szrj     if (NOTE_P (end_tail))
4966*38fd1498Szrj       end_tail = PREV_INSN (end_tail);
4967*38fd1498Szrj     else if (DEBUG_INSN_P (end_tail))
4968*38fd1498Szrj       {
4969*38fd1498Szrj 	rtx_insn * note, *prev;
4970*38fd1498Szrj 
4971*38fd1498Szrj 	for (note = PREV_INSN (end_tail);
4972*38fd1498Szrj 	     note != end_head;
4973*38fd1498Szrj 	     note = prev)
4974*38fd1498Szrj 	  {
4975*38fd1498Szrj 	    prev = PREV_INSN (note);
4976*38fd1498Szrj 	    if (NOTE_P (note))
4977*38fd1498Szrj 	      {
4978*38fd1498Szrj 		if (sched_verbose >= 9)
4979*38fd1498Szrj 		  fprintf (sched_dump, "reorder %i\n", INSN_UID (note));
4980*38fd1498Szrj 
4981*38fd1498Szrj 		reorder_insns_nobb (note, note, end_tail);
4982*38fd1498Szrj 
4983*38fd1498Szrj 		if (end_tail == BB_END (end))
4984*38fd1498Szrj 		  BB_END (end) = note;
4985*38fd1498Szrj 
4986*38fd1498Szrj 		if (BLOCK_FOR_INSN (note) != end)
4987*38fd1498Szrj 		  df_insn_change_bb (note, end);
4988*38fd1498Szrj 	      }
4989*38fd1498Szrj 	    else if (!DEBUG_INSN_P (note))
4990*38fd1498Szrj 	      break;
4991*38fd1498Szrj 	  }
4992*38fd1498Szrj 
4993*38fd1498Szrj 	break;
4994*38fd1498Szrj       }
4995*38fd1498Szrj     else
4996*38fd1498Szrj       break;
4997*38fd1498Szrj 
4998*38fd1498Szrj   *tailp = end_tail;
4999*38fd1498Szrj }
5000*38fd1498Szrj 
5001*38fd1498Szrj /* Return nonzero if there are no real insns in the range [ HEAD, TAIL ].  */
5002*38fd1498Szrj 
5003*38fd1498Szrj int
no_real_insns_p(const rtx_insn * head,const rtx_insn * tail)5004*38fd1498Szrj no_real_insns_p (const rtx_insn *head, const rtx_insn *tail)
5005*38fd1498Szrj {
5006*38fd1498Szrj   while (head != NEXT_INSN (tail))
5007*38fd1498Szrj     {
5008*38fd1498Szrj       if (!NOTE_P (head) && !LABEL_P (head))
5009*38fd1498Szrj 	return 0;
5010*38fd1498Szrj       head = NEXT_INSN (head);
5011*38fd1498Szrj     }
5012*38fd1498Szrj   return 1;
5013*38fd1498Szrj }
5014*38fd1498Szrj 
5015*38fd1498Szrj /* Restore-other-notes: NOTE_LIST is the end of a chain of notes
5016*38fd1498Szrj    previously found among the insns.  Insert them just before HEAD.  */
5017*38fd1498Szrj rtx_insn *
restore_other_notes(rtx_insn * head,basic_block head_bb)5018*38fd1498Szrj restore_other_notes (rtx_insn *head, basic_block head_bb)
5019*38fd1498Szrj {
5020*38fd1498Szrj   if (note_list != 0)
5021*38fd1498Szrj     {
5022*38fd1498Szrj       rtx_insn *note_head = note_list;
5023*38fd1498Szrj 
5024*38fd1498Szrj       if (head)
5025*38fd1498Szrj 	head_bb = BLOCK_FOR_INSN (head);
5026*38fd1498Szrj       else
5027*38fd1498Szrj 	head = NEXT_INSN (bb_note (head_bb));
5028*38fd1498Szrj 
5029*38fd1498Szrj       while (PREV_INSN (note_head))
5030*38fd1498Szrj 	{
5031*38fd1498Szrj 	  set_block_for_insn (note_head, head_bb);
5032*38fd1498Szrj 	  note_head = PREV_INSN (note_head);
5033*38fd1498Szrj 	}
5034*38fd1498Szrj       /* In the above cycle we've missed this note.  */
5035*38fd1498Szrj       set_block_for_insn (note_head, head_bb);
5036*38fd1498Szrj 
5037*38fd1498Szrj       SET_PREV_INSN (note_head) = PREV_INSN (head);
5038*38fd1498Szrj       SET_NEXT_INSN (PREV_INSN (head)) = note_head;
5039*38fd1498Szrj       SET_PREV_INSN (head) = note_list;
5040*38fd1498Szrj       SET_NEXT_INSN (note_list) = head;
5041*38fd1498Szrj 
5042*38fd1498Szrj       if (BLOCK_FOR_INSN (head) != head_bb)
5043*38fd1498Szrj 	BB_END (head_bb) = note_list;
5044*38fd1498Szrj 
5045*38fd1498Szrj       head = note_head;
5046*38fd1498Szrj     }
5047*38fd1498Szrj 
5048*38fd1498Szrj   return head;
5049*38fd1498Szrj }
5050*38fd1498Szrj 
5051*38fd1498Szrj /* When we know we are going to discard the schedule due to a failed attempt
5052*38fd1498Szrj    at modulo scheduling, undo all replacements.  */
5053*38fd1498Szrj static void
undo_all_replacements(void)5054*38fd1498Szrj undo_all_replacements (void)
5055*38fd1498Szrj {
5056*38fd1498Szrj   rtx_insn *insn;
5057*38fd1498Szrj   int i;
5058*38fd1498Szrj 
5059*38fd1498Szrj   FOR_EACH_VEC_ELT (scheduled_insns, i, insn)
5060*38fd1498Szrj     {
5061*38fd1498Szrj       sd_iterator_def sd_it;
5062*38fd1498Szrj       dep_t dep;
5063*38fd1498Szrj 
5064*38fd1498Szrj       /* See if we must undo a replacement.  */
5065*38fd1498Szrj       for (sd_it = sd_iterator_start (insn, SD_LIST_RES_FORW);
5066*38fd1498Szrj 	   sd_iterator_cond (&sd_it, &dep); sd_iterator_next (&sd_it))
5067*38fd1498Szrj 	{
5068*38fd1498Szrj 	  struct dep_replacement *desc = DEP_REPLACE (dep);
5069*38fd1498Szrj 	  if (desc != NULL)
5070*38fd1498Szrj 	    validate_change (desc->insn, desc->loc, desc->orig, 0);
5071*38fd1498Szrj 	}
5072*38fd1498Szrj     }
5073*38fd1498Szrj }
5074*38fd1498Szrj 
5075*38fd1498Szrj /* Return first non-scheduled insn in the current scheduling block.
5076*38fd1498Szrj    This is mostly used for debug-counter purposes.  */
5077*38fd1498Szrj static rtx_insn *
first_nonscheduled_insn(void)5078*38fd1498Szrj first_nonscheduled_insn (void)
5079*38fd1498Szrj {
5080*38fd1498Szrj   rtx_insn *insn = (nonscheduled_insns_begin != NULL_RTX
5081*38fd1498Szrj 		    ? nonscheduled_insns_begin
5082*38fd1498Szrj 		    : current_sched_info->prev_head);
5083*38fd1498Szrj 
5084*38fd1498Szrj   do
5085*38fd1498Szrj     {
5086*38fd1498Szrj       insn = next_nonnote_nondebug_insn (insn);
5087*38fd1498Szrj     }
5088*38fd1498Szrj   while (QUEUE_INDEX (insn) == QUEUE_SCHEDULED);
5089*38fd1498Szrj 
5090*38fd1498Szrj   return insn;
5091*38fd1498Szrj }
5092*38fd1498Szrj 
5093*38fd1498Szrj /* Move insns that became ready to fire from queue to ready list.  */
5094*38fd1498Szrj 
5095*38fd1498Szrj static void
queue_to_ready(struct ready_list * ready)5096*38fd1498Szrj queue_to_ready (struct ready_list *ready)
5097*38fd1498Szrj {
5098*38fd1498Szrj   rtx_insn *insn;
5099*38fd1498Szrj   rtx_insn_list *link;
5100*38fd1498Szrj   rtx_insn *skip_insn;
5101*38fd1498Szrj 
5102*38fd1498Szrj   q_ptr = NEXT_Q (q_ptr);
5103*38fd1498Szrj 
5104*38fd1498Szrj   if (dbg_cnt (sched_insn) == false)
5105*38fd1498Szrj     /* If debug counter is activated do not requeue the first
5106*38fd1498Szrj        nonscheduled insn.  */
5107*38fd1498Szrj     skip_insn = first_nonscheduled_insn ();
5108*38fd1498Szrj   else
5109*38fd1498Szrj     skip_insn = NULL;
5110*38fd1498Szrj 
5111*38fd1498Szrj   /* Add all pending insns that can be scheduled without stalls to the
5112*38fd1498Szrj      ready list.  */
5113*38fd1498Szrj   for (link = insn_queue[q_ptr]; link; link = link->next ())
5114*38fd1498Szrj     {
5115*38fd1498Szrj       insn = link->insn ();
5116*38fd1498Szrj       q_size -= 1;
5117*38fd1498Szrj 
5118*38fd1498Szrj       if (sched_verbose >= 2)
5119*38fd1498Szrj 	fprintf (sched_dump, ";;\t\tQ-->Ready: insn %s: ",
5120*38fd1498Szrj 		 (*current_sched_info->print_insn) (insn, 0));
5121*38fd1498Szrj 
5122*38fd1498Szrj       /* If the ready list is full, delay the insn for 1 cycle.
5123*38fd1498Szrj 	 See the comment in schedule_block for the rationale.  */
5124*38fd1498Szrj       if (!reload_completed
5125*38fd1498Szrj 	  && (ready->n_ready - ready->n_debug > MAX_SCHED_READY_INSNS
5126*38fd1498Szrj 	      || (sched_pressure == SCHED_PRESSURE_MODEL
5127*38fd1498Szrj 		  /* Limit pressure recalculations to MAX_SCHED_READY_INSNS
5128*38fd1498Szrj 		     instructions too.  */
5129*38fd1498Szrj 		  && model_index (insn) > (model_curr_point
5130*38fd1498Szrj 					   + MAX_SCHED_READY_INSNS)))
5131*38fd1498Szrj 	  && !(sched_pressure == SCHED_PRESSURE_MODEL
5132*38fd1498Szrj 	       && model_curr_point < model_num_insns
5133*38fd1498Szrj 	       /* Always allow the next model instruction to issue.  */
5134*38fd1498Szrj 	       && model_index (insn) == model_curr_point)
5135*38fd1498Szrj 	  && !SCHED_GROUP_P (insn)
5136*38fd1498Szrj 	  && insn != skip_insn)
5137*38fd1498Szrj 	{
5138*38fd1498Szrj 	  if (sched_verbose >= 2)
5139*38fd1498Szrj 	    fprintf (sched_dump, "keeping in queue, ready full\n");
5140*38fd1498Szrj 	  queue_insn (insn, 1, "ready full");
5141*38fd1498Szrj 	}
5142*38fd1498Szrj       else
5143*38fd1498Szrj 	{
5144*38fd1498Szrj 	  ready_add (ready, insn, false);
5145*38fd1498Szrj 	  if (sched_verbose >= 2)
5146*38fd1498Szrj 	    fprintf (sched_dump, "moving to ready without stalls\n");
5147*38fd1498Szrj         }
5148*38fd1498Szrj     }
5149*38fd1498Szrj   free_INSN_LIST_list (&insn_queue[q_ptr]);
5150*38fd1498Szrj 
5151*38fd1498Szrj   /* If there are no ready insns, stall until one is ready and add all
5152*38fd1498Szrj      of the pending insns at that point to the ready list.  */
5153*38fd1498Szrj   if (ready->n_ready == 0)
5154*38fd1498Szrj     {
5155*38fd1498Szrj       int stalls;
5156*38fd1498Szrj 
5157*38fd1498Szrj       for (stalls = 1; stalls <= max_insn_queue_index; stalls++)
5158*38fd1498Szrj 	{
5159*38fd1498Szrj 	  if ((link = insn_queue[NEXT_Q_AFTER (q_ptr, stalls)]))
5160*38fd1498Szrj 	    {
5161*38fd1498Szrj 	      for (; link; link = link->next ())
5162*38fd1498Szrj 		{
5163*38fd1498Szrj 		  insn = link->insn ();
5164*38fd1498Szrj 		  q_size -= 1;
5165*38fd1498Szrj 
5166*38fd1498Szrj 		  if (sched_verbose >= 2)
5167*38fd1498Szrj 		    fprintf (sched_dump, ";;\t\tQ-->Ready: insn %s: ",
5168*38fd1498Szrj 			     (*current_sched_info->print_insn) (insn, 0));
5169*38fd1498Szrj 
5170*38fd1498Szrj 		  ready_add (ready, insn, false);
5171*38fd1498Szrj 		  if (sched_verbose >= 2)
5172*38fd1498Szrj 		    fprintf (sched_dump, "moving to ready with %d stalls\n", stalls);
5173*38fd1498Szrj 		}
5174*38fd1498Szrj 	      free_INSN_LIST_list (&insn_queue[NEXT_Q_AFTER (q_ptr, stalls)]);
5175*38fd1498Szrj 
5176*38fd1498Szrj 	      advance_one_cycle ();
5177*38fd1498Szrj 
5178*38fd1498Szrj 	      break;
5179*38fd1498Szrj 	    }
5180*38fd1498Szrj 
5181*38fd1498Szrj 	  advance_one_cycle ();
5182*38fd1498Szrj 	}
5183*38fd1498Szrj 
5184*38fd1498Szrj       q_ptr = NEXT_Q_AFTER (q_ptr, stalls);
5185*38fd1498Szrj       clock_var += stalls;
5186*38fd1498Szrj       if (sched_verbose >= 2)
5187*38fd1498Szrj 	fprintf (sched_dump, ";;\tAdvancing clock by %d cycle[s] to %d\n",
5188*38fd1498Szrj 		 stalls, clock_var);
5189*38fd1498Szrj     }
5190*38fd1498Szrj }
5191*38fd1498Szrj 
5192*38fd1498Szrj /* Used by early_queue_to_ready.  Determines whether it is "ok" to
5193*38fd1498Szrj    prematurely move INSN from the queue to the ready list.  Currently,
5194*38fd1498Szrj    if a target defines the hook 'is_costly_dependence', this function
5195*38fd1498Szrj    uses the hook to check whether there exist any dependences which are
5196*38fd1498Szrj    considered costly by the target, between INSN and other insns that
5197*38fd1498Szrj    have already been scheduled.  Dependences are checked up to Y cycles
5198*38fd1498Szrj    back, with default Y=1; The flag -fsched-stalled-insns-dep=Y allows
5199*38fd1498Szrj    controlling this value.
5200*38fd1498Szrj    (Other considerations could be taken into account instead (or in
5201*38fd1498Szrj    addition) depending on user flags and target hooks.  */
5202*38fd1498Szrj 
5203*38fd1498Szrj static bool
ok_for_early_queue_removal(rtx_insn * insn)5204*38fd1498Szrj ok_for_early_queue_removal (rtx_insn *insn)
5205*38fd1498Szrj {
5206*38fd1498Szrj   if (targetm.sched.is_costly_dependence)
5207*38fd1498Szrj     {
5208*38fd1498Szrj       int n_cycles;
5209*38fd1498Szrj       int i = scheduled_insns.length ();
5210*38fd1498Szrj       for (n_cycles = flag_sched_stalled_insns_dep; n_cycles; n_cycles--)
5211*38fd1498Szrj 	{
5212*38fd1498Szrj 	  while (i-- > 0)
5213*38fd1498Szrj 	    {
5214*38fd1498Szrj 	      int cost;
5215*38fd1498Szrj 
5216*38fd1498Szrj 	      rtx_insn *prev_insn = scheduled_insns[i];
5217*38fd1498Szrj 
5218*38fd1498Szrj 	      if (!NOTE_P (prev_insn))
5219*38fd1498Szrj 		{
5220*38fd1498Szrj 		  dep_t dep;
5221*38fd1498Szrj 
5222*38fd1498Szrj 		  dep = sd_find_dep_between (prev_insn, insn, true);
5223*38fd1498Szrj 
5224*38fd1498Szrj 		  if (dep != NULL)
5225*38fd1498Szrj 		    {
5226*38fd1498Szrj 		      cost = dep_cost (dep);
5227*38fd1498Szrj 
5228*38fd1498Szrj 		      if (targetm.sched.is_costly_dependence (dep, cost,
5229*38fd1498Szrj 				flag_sched_stalled_insns_dep - n_cycles))
5230*38fd1498Szrj 			return false;
5231*38fd1498Szrj 		    }
5232*38fd1498Szrj 		}
5233*38fd1498Szrj 
5234*38fd1498Szrj 	      if (GET_MODE (prev_insn) == TImode) /* end of dispatch group */
5235*38fd1498Szrj 		break;
5236*38fd1498Szrj 	    }
5237*38fd1498Szrj 
5238*38fd1498Szrj 	  if (i == 0)
5239*38fd1498Szrj 	    break;
5240*38fd1498Szrj 	}
5241*38fd1498Szrj     }
5242*38fd1498Szrj 
5243*38fd1498Szrj   return true;
5244*38fd1498Szrj }
5245*38fd1498Szrj 
5246*38fd1498Szrj 
5247*38fd1498Szrj /* Remove insns from the queue, before they become "ready" with respect
5248*38fd1498Szrj    to FU latency considerations.  */
5249*38fd1498Szrj 
5250*38fd1498Szrj static int
early_queue_to_ready(state_t state,struct ready_list * ready)5251*38fd1498Szrj early_queue_to_ready (state_t state, struct ready_list *ready)
5252*38fd1498Szrj {
5253*38fd1498Szrj   rtx_insn *insn;
5254*38fd1498Szrj   rtx_insn_list *link;
5255*38fd1498Szrj   rtx_insn_list *next_link;
5256*38fd1498Szrj   rtx_insn_list *prev_link;
5257*38fd1498Szrj   bool move_to_ready;
5258*38fd1498Szrj   int cost;
5259*38fd1498Szrj   state_t temp_state = alloca (dfa_state_size);
5260*38fd1498Szrj   int stalls;
5261*38fd1498Szrj   int insns_removed = 0;
5262*38fd1498Szrj 
5263*38fd1498Szrj   /*
5264*38fd1498Szrj      Flag '-fsched-stalled-insns=X' determines the aggressiveness of this
5265*38fd1498Szrj      function:
5266*38fd1498Szrj 
5267*38fd1498Szrj      X == 0: There is no limit on how many queued insns can be removed
5268*38fd1498Szrj              prematurely.  (flag_sched_stalled_insns = -1).
5269*38fd1498Szrj 
5270*38fd1498Szrj      X >= 1: Only X queued insns can be removed prematurely in each
5271*38fd1498Szrj 	     invocation.  (flag_sched_stalled_insns = X).
5272*38fd1498Szrj 
5273*38fd1498Szrj      Otherwise: Early queue removal is disabled.
5274*38fd1498Szrj          (flag_sched_stalled_insns = 0)
5275*38fd1498Szrj   */
5276*38fd1498Szrj 
5277*38fd1498Szrj   if (! flag_sched_stalled_insns)
5278*38fd1498Szrj     return 0;
5279*38fd1498Szrj 
5280*38fd1498Szrj   for (stalls = 0; stalls <= max_insn_queue_index; stalls++)
5281*38fd1498Szrj     {
5282*38fd1498Szrj       if ((link = insn_queue[NEXT_Q_AFTER (q_ptr, stalls)]))
5283*38fd1498Szrj 	{
5284*38fd1498Szrj 	  if (sched_verbose > 6)
5285*38fd1498Szrj 	    fprintf (sched_dump, ";; look at index %d + %d\n", q_ptr, stalls);
5286*38fd1498Szrj 
5287*38fd1498Szrj 	  prev_link = 0;
5288*38fd1498Szrj 	  while (link)
5289*38fd1498Szrj 	    {
5290*38fd1498Szrj 	      next_link = link->next ();
5291*38fd1498Szrj 	      insn = link->insn ();
5292*38fd1498Szrj 	      if (insn && sched_verbose > 6)
5293*38fd1498Szrj 		print_rtl_single (sched_dump, insn);
5294*38fd1498Szrj 
5295*38fd1498Szrj 	      memcpy (temp_state, state, dfa_state_size);
5296*38fd1498Szrj 	      if (recog_memoized (insn) < 0)
5297*38fd1498Szrj 		/* non-negative to indicate that it's not ready
5298*38fd1498Szrj 		   to avoid infinite Q->R->Q->R... */
5299*38fd1498Szrj 		cost = 0;
5300*38fd1498Szrj 	      else
5301*38fd1498Szrj 		cost = state_transition (temp_state, insn);
5302*38fd1498Szrj 
5303*38fd1498Szrj 	      if (sched_verbose >= 6)
5304*38fd1498Szrj 		fprintf (sched_dump, "transition cost = %d\n", cost);
5305*38fd1498Szrj 
5306*38fd1498Szrj 	      move_to_ready = false;
5307*38fd1498Szrj 	      if (cost < 0)
5308*38fd1498Szrj 		{
5309*38fd1498Szrj 		  move_to_ready = ok_for_early_queue_removal (insn);
5310*38fd1498Szrj 		  if (move_to_ready == true)
5311*38fd1498Szrj 		    {
5312*38fd1498Szrj 		      /* move from Q to R */
5313*38fd1498Szrj 		      q_size -= 1;
5314*38fd1498Szrj 		      ready_add (ready, insn, false);
5315*38fd1498Szrj 
5316*38fd1498Szrj 		      if (prev_link)
5317*38fd1498Szrj 			XEXP (prev_link, 1) = next_link;
5318*38fd1498Szrj 		      else
5319*38fd1498Szrj 			insn_queue[NEXT_Q_AFTER (q_ptr, stalls)] = next_link;
5320*38fd1498Szrj 
5321*38fd1498Szrj 		      free_INSN_LIST_node (link);
5322*38fd1498Szrj 
5323*38fd1498Szrj 		      if (sched_verbose >= 2)
5324*38fd1498Szrj 			fprintf (sched_dump, ";;\t\tEarly Q-->Ready: insn %s\n",
5325*38fd1498Szrj 				 (*current_sched_info->print_insn) (insn, 0));
5326*38fd1498Szrj 
5327*38fd1498Szrj 		      insns_removed++;
5328*38fd1498Szrj 		      if (insns_removed == flag_sched_stalled_insns)
5329*38fd1498Szrj 			/* Remove no more than flag_sched_stalled_insns insns
5330*38fd1498Szrj 			   from Q at a time.  */
5331*38fd1498Szrj 			return insns_removed;
5332*38fd1498Szrj 		    }
5333*38fd1498Szrj 		}
5334*38fd1498Szrj 
5335*38fd1498Szrj 	      if (move_to_ready == false)
5336*38fd1498Szrj 		prev_link = link;
5337*38fd1498Szrj 
5338*38fd1498Szrj 	      link = next_link;
5339*38fd1498Szrj 	    } /* while link */
5340*38fd1498Szrj 	} /* if link */
5341*38fd1498Szrj 
5342*38fd1498Szrj     } /* for stalls.. */
5343*38fd1498Szrj 
5344*38fd1498Szrj   return insns_removed;
5345*38fd1498Szrj }
5346*38fd1498Szrj 
5347*38fd1498Szrj 
5348*38fd1498Szrj /* Print the ready list for debugging purposes.
5349*38fd1498Szrj    If READY_TRY is non-zero then only print insns that max_issue
5350*38fd1498Szrj    will consider.  */
5351*38fd1498Szrj static void
debug_ready_list_1(struct ready_list * ready,signed char * ready_try)5352*38fd1498Szrj debug_ready_list_1 (struct ready_list *ready, signed char *ready_try)
5353*38fd1498Szrj {
5354*38fd1498Szrj   rtx_insn **p;
5355*38fd1498Szrj   int i;
5356*38fd1498Szrj 
5357*38fd1498Szrj   if (ready->n_ready == 0)
5358*38fd1498Szrj     {
5359*38fd1498Szrj       fprintf (sched_dump, "\n");
5360*38fd1498Szrj       return;
5361*38fd1498Szrj     }
5362*38fd1498Szrj 
5363*38fd1498Szrj   p = ready_lastpos (ready);
5364*38fd1498Szrj   for (i = 0; i < ready->n_ready; i++)
5365*38fd1498Szrj     {
5366*38fd1498Szrj       if (ready_try != NULL && ready_try[ready->n_ready - i - 1])
5367*38fd1498Szrj 	continue;
5368*38fd1498Szrj 
5369*38fd1498Szrj       fprintf (sched_dump, "  %s:%d",
5370*38fd1498Szrj 	       (*current_sched_info->print_insn) (p[i], 0),
5371*38fd1498Szrj 	       INSN_LUID (p[i]));
5372*38fd1498Szrj       if (sched_pressure != SCHED_PRESSURE_NONE)
5373*38fd1498Szrj 	fprintf (sched_dump, "(cost=%d",
5374*38fd1498Szrj 		 INSN_REG_PRESSURE_EXCESS_COST_CHANGE (p[i]));
5375*38fd1498Szrj       fprintf (sched_dump, ":prio=%d", INSN_PRIORITY (p[i]));
5376*38fd1498Szrj       if (INSN_TICK (p[i]) > clock_var)
5377*38fd1498Szrj 	fprintf (sched_dump, ":delay=%d", INSN_TICK (p[i]) - clock_var);
5378*38fd1498Szrj       if (sched_pressure == SCHED_PRESSURE_MODEL)
5379*38fd1498Szrj 	fprintf (sched_dump, ":idx=%d",
5380*38fd1498Szrj 		 model_index (p[i]));
5381*38fd1498Szrj       if (sched_pressure != SCHED_PRESSURE_NONE)
5382*38fd1498Szrj 	fprintf (sched_dump, ")");
5383*38fd1498Szrj     }
5384*38fd1498Szrj   fprintf (sched_dump, "\n");
5385*38fd1498Szrj }
5386*38fd1498Szrj 
5387*38fd1498Szrj /* Print the ready list.  Callable from debugger.  */
5388*38fd1498Szrj static void
debug_ready_list(struct ready_list * ready)5389*38fd1498Szrj debug_ready_list (struct ready_list *ready)
5390*38fd1498Szrj {
5391*38fd1498Szrj   debug_ready_list_1 (ready, NULL);
5392*38fd1498Szrj }
5393*38fd1498Szrj 
5394*38fd1498Szrj /* Search INSN for REG_SAVE_NOTE notes and convert them back into insn
5395*38fd1498Szrj    NOTEs.  This is used for NOTE_INSN_EPILOGUE_BEG, so that sched-ebb
5396*38fd1498Szrj    replaces the epilogue note in the correct basic block.  */
5397*38fd1498Szrj void
reemit_notes(rtx_insn * insn)5398*38fd1498Szrj reemit_notes (rtx_insn *insn)
5399*38fd1498Szrj {
5400*38fd1498Szrj   rtx note;
5401*38fd1498Szrj   rtx_insn *last = insn;
5402*38fd1498Szrj 
5403*38fd1498Szrj   for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
5404*38fd1498Szrj     {
5405*38fd1498Szrj       if (REG_NOTE_KIND (note) == REG_SAVE_NOTE)
5406*38fd1498Szrj 	{
5407*38fd1498Szrj 	  enum insn_note note_type = (enum insn_note) INTVAL (XEXP (note, 0));
5408*38fd1498Szrj 
5409*38fd1498Szrj 	  last = emit_note_before (note_type, last);
5410*38fd1498Szrj 	  remove_note (insn, note);
5411*38fd1498Szrj 	}
5412*38fd1498Szrj     }
5413*38fd1498Szrj }
5414*38fd1498Szrj 
5415*38fd1498Szrj /* Move INSN.  Reemit notes if needed.  Update CFG, if needed.  */
5416*38fd1498Szrj static void
move_insn(rtx_insn * insn,rtx_insn * last,rtx nt)5417*38fd1498Szrj move_insn (rtx_insn *insn, rtx_insn *last, rtx nt)
5418*38fd1498Szrj {
5419*38fd1498Szrj   if (PREV_INSN (insn) != last)
5420*38fd1498Szrj     {
5421*38fd1498Szrj       basic_block bb;
5422*38fd1498Szrj       rtx_insn *note;
5423*38fd1498Szrj       int jump_p = 0;
5424*38fd1498Szrj 
5425*38fd1498Szrj       bb = BLOCK_FOR_INSN (insn);
5426*38fd1498Szrj 
5427*38fd1498Szrj       /* BB_HEAD is either LABEL or NOTE.  */
5428*38fd1498Szrj       gcc_assert (BB_HEAD (bb) != insn);
5429*38fd1498Szrj 
5430*38fd1498Szrj       if (BB_END (bb) == insn)
5431*38fd1498Szrj 	/* If this is last instruction in BB, move end marker one
5432*38fd1498Szrj 	   instruction up.  */
5433*38fd1498Szrj 	{
5434*38fd1498Szrj 	  /* Jumps are always placed at the end of basic block.  */
5435*38fd1498Szrj 	  jump_p = control_flow_insn_p (insn);
5436*38fd1498Szrj 
5437*38fd1498Szrj 	  gcc_assert (!jump_p
5438*38fd1498Szrj 		      || ((common_sched_info->sched_pass_id == SCHED_RGN_PASS)
5439*38fd1498Szrj 			  && IS_SPECULATION_BRANCHY_CHECK_P (insn))
5440*38fd1498Szrj 		      || (common_sched_info->sched_pass_id
5441*38fd1498Szrj 			  == SCHED_EBB_PASS));
5442*38fd1498Szrj 
5443*38fd1498Szrj 	  gcc_assert (BLOCK_FOR_INSN (PREV_INSN (insn)) == bb);
5444*38fd1498Szrj 
5445*38fd1498Szrj 	  BB_END (bb) = PREV_INSN (insn);
5446*38fd1498Szrj 	}
5447*38fd1498Szrj 
5448*38fd1498Szrj       gcc_assert (BB_END (bb) != last);
5449*38fd1498Szrj 
5450*38fd1498Szrj       if (jump_p)
5451*38fd1498Szrj 	/* We move the block note along with jump.  */
5452*38fd1498Szrj 	{
5453*38fd1498Szrj 	  gcc_assert (nt);
5454*38fd1498Szrj 
5455*38fd1498Szrj 	  note = NEXT_INSN (insn);
5456*38fd1498Szrj 	  while (NOTE_NOT_BB_P (note) && note != nt)
5457*38fd1498Szrj 	    note = NEXT_INSN (note);
5458*38fd1498Szrj 
5459*38fd1498Szrj 	  if (note != nt
5460*38fd1498Szrj 	      && (LABEL_P (note)
5461*38fd1498Szrj 		  || BARRIER_P (note)))
5462*38fd1498Szrj 	    note = NEXT_INSN (note);
5463*38fd1498Szrj 
5464*38fd1498Szrj 	  gcc_assert (NOTE_INSN_BASIC_BLOCK_P (note));
5465*38fd1498Szrj 	}
5466*38fd1498Szrj       else
5467*38fd1498Szrj 	note = insn;
5468*38fd1498Szrj 
5469*38fd1498Szrj       SET_NEXT_INSN (PREV_INSN (insn)) = NEXT_INSN (note);
5470*38fd1498Szrj       SET_PREV_INSN (NEXT_INSN (note)) = PREV_INSN (insn);
5471*38fd1498Szrj 
5472*38fd1498Szrj       SET_NEXT_INSN (note) = NEXT_INSN (last);
5473*38fd1498Szrj       SET_PREV_INSN (NEXT_INSN (last)) = note;
5474*38fd1498Szrj 
5475*38fd1498Szrj       SET_NEXT_INSN (last) = insn;
5476*38fd1498Szrj       SET_PREV_INSN (insn) = last;
5477*38fd1498Szrj 
5478*38fd1498Szrj       bb = BLOCK_FOR_INSN (last);
5479*38fd1498Szrj 
5480*38fd1498Szrj       if (jump_p)
5481*38fd1498Szrj 	{
5482*38fd1498Szrj 	  fix_jump_move (insn);
5483*38fd1498Szrj 
5484*38fd1498Szrj 	  if (BLOCK_FOR_INSN (insn) != bb)
5485*38fd1498Szrj 	    move_block_after_check (insn);
5486*38fd1498Szrj 
5487*38fd1498Szrj 	  gcc_assert (BB_END (bb) == last);
5488*38fd1498Szrj 	}
5489*38fd1498Szrj 
5490*38fd1498Szrj       df_insn_change_bb (insn, bb);
5491*38fd1498Szrj 
5492*38fd1498Szrj       /* Update BB_END, if needed.  */
5493*38fd1498Szrj       if (BB_END (bb) == last)
5494*38fd1498Szrj 	BB_END (bb) = insn;
5495*38fd1498Szrj     }
5496*38fd1498Szrj 
5497*38fd1498Szrj   SCHED_GROUP_P (insn) = 0;
5498*38fd1498Szrj }
5499*38fd1498Szrj 
5500*38fd1498Szrj /* Return true if scheduling INSN will finish current clock cycle.  */
5501*38fd1498Szrj static bool
insn_finishes_cycle_p(rtx_insn * insn)5502*38fd1498Szrj insn_finishes_cycle_p (rtx_insn *insn)
5503*38fd1498Szrj {
5504*38fd1498Szrj   if (SCHED_GROUP_P (insn))
5505*38fd1498Szrj     /* After issuing INSN, rest of the sched_group will be forced to issue
5506*38fd1498Szrj        in order.  Don't make any plans for the rest of cycle.  */
5507*38fd1498Szrj     return true;
5508*38fd1498Szrj 
5509*38fd1498Szrj   /* Finishing the block will, apparently, finish the cycle.  */
5510*38fd1498Szrj   if (current_sched_info->insn_finishes_block_p
5511*38fd1498Szrj       && current_sched_info->insn_finishes_block_p (insn))
5512*38fd1498Szrj     return true;
5513*38fd1498Szrj 
5514*38fd1498Szrj   return false;
5515*38fd1498Szrj }
5516*38fd1498Szrj 
5517*38fd1498Szrj /* Helper for autopref_multipass_init.  Given a SET in PAT and whether
5518*38fd1498Szrj    we're expecting a memory WRITE or not, check that the insn is relevant to
5519*38fd1498Szrj    the autoprefetcher modelling code.  Return true iff that is the case.
5520*38fd1498Szrj    If it is relevant, record the base register of the memory op in BASE and
5521*38fd1498Szrj    the offset in OFFSET.  */
5522*38fd1498Szrj 
5523*38fd1498Szrj static bool
analyze_set_insn_for_autopref(rtx pat,bool write,rtx * base,int * offset)5524*38fd1498Szrj analyze_set_insn_for_autopref (rtx pat, bool write, rtx *base, int *offset)
5525*38fd1498Szrj {
5526*38fd1498Szrj   if (GET_CODE (pat) != SET)
5527*38fd1498Szrj     return false;
5528*38fd1498Szrj 
5529*38fd1498Szrj   rtx mem = write ? SET_DEST (pat) : SET_SRC (pat);
5530*38fd1498Szrj   if (!MEM_P (mem))
5531*38fd1498Szrj     return false;
5532*38fd1498Szrj 
5533*38fd1498Szrj   struct address_info info;
5534*38fd1498Szrj   decompose_mem_address (&info, mem);
5535*38fd1498Szrj 
5536*38fd1498Szrj   /* TODO: Currently only (base+const) addressing is supported.  */
5537*38fd1498Szrj   if (info.base == NULL || !REG_P (*info.base)
5538*38fd1498Szrj       || (info.disp != NULL && !CONST_INT_P (*info.disp)))
5539*38fd1498Szrj     return false;
5540*38fd1498Szrj 
5541*38fd1498Szrj   *base = *info.base;
5542*38fd1498Szrj   *offset = info.disp ? INTVAL (*info.disp) : 0;
5543*38fd1498Szrj   return true;
5544*38fd1498Szrj }
5545*38fd1498Szrj 
5546*38fd1498Szrj /* Functions to model cache auto-prefetcher.
5547*38fd1498Szrj 
5548*38fd1498Szrj    Some of the CPUs have cache auto-prefetcher, which /seems/ to initiate
5549*38fd1498Szrj    memory prefetches if it sees instructions with consequitive memory accesses
5550*38fd1498Szrj    in the instruction stream.  Details of such hardware units are not published,
5551*38fd1498Szrj    so we can only guess what exactly is going on there.
5552*38fd1498Szrj    In the scheduler, we model abstract auto-prefetcher.  If there are memory
5553*38fd1498Szrj    insns in the ready list (or the queue) that have same memory base, but
5554*38fd1498Szrj    different offsets, then we delay the insns with larger offsets until insns
5555*38fd1498Szrj    with smaller offsets get scheduled.  If PARAM_SCHED_AUTOPREF_QUEUE_DEPTH
5556*38fd1498Szrj    is "1", then we look at the ready list; if it is N>1, then we also look
5557*38fd1498Szrj    through N-1 queue entries.
5558*38fd1498Szrj    If the param is N>=0, then rank_for_schedule will consider auto-prefetching
5559*38fd1498Szrj    among its heuristics.
5560*38fd1498Szrj    Param value of "-1" disables modelling of the auto-prefetcher.  */
5561*38fd1498Szrj 
5562*38fd1498Szrj /* Initialize autoprefetcher model data for INSN.  */
5563*38fd1498Szrj static void
autopref_multipass_init(const rtx_insn * insn,int write)5564*38fd1498Szrj autopref_multipass_init (const rtx_insn *insn, int write)
5565*38fd1498Szrj {
5566*38fd1498Szrj   autopref_multipass_data_t data = &INSN_AUTOPREF_MULTIPASS_DATA (insn)[write];
5567*38fd1498Szrj 
5568*38fd1498Szrj   gcc_assert (data->status == AUTOPREF_MULTIPASS_DATA_UNINITIALIZED);
5569*38fd1498Szrj   data->base = NULL_RTX;
5570*38fd1498Szrj   data->offset = 0;
5571*38fd1498Szrj   /* Set insn entry initialized, but not relevant for auto-prefetcher.  */
5572*38fd1498Szrj   data->status = AUTOPREF_MULTIPASS_DATA_IRRELEVANT;
5573*38fd1498Szrj 
5574*38fd1498Szrj   rtx pat = PATTERN (insn);
5575*38fd1498Szrj 
5576*38fd1498Szrj   /* We have a multi-set insn like a load-multiple or store-multiple.
5577*38fd1498Szrj      We care about these as long as all the memory ops inside the PARALLEL
5578*38fd1498Szrj      have the same base register.  We care about the minimum and maximum
5579*38fd1498Szrj      offsets from that base but don't check for the order of those offsets
5580*38fd1498Szrj      within the PARALLEL insn itself.  */
5581*38fd1498Szrj   if (GET_CODE (pat) == PARALLEL)
5582*38fd1498Szrj     {
5583*38fd1498Szrj       int n_elems = XVECLEN (pat, 0);
5584*38fd1498Szrj 
5585*38fd1498Szrj       int i, offset;
5586*38fd1498Szrj       rtx base, prev_base = NULL_RTX;
5587*38fd1498Szrj       int min_offset = INT_MAX;
5588*38fd1498Szrj 
5589*38fd1498Szrj       for (i = 0; i < n_elems; i++)
5590*38fd1498Szrj 	{
5591*38fd1498Szrj 	  rtx set = XVECEXP (pat, 0, i);
5592*38fd1498Szrj 	  if (GET_CODE (set) != SET)
5593*38fd1498Szrj 	    return;
5594*38fd1498Szrj 
5595*38fd1498Szrj 	  if (!analyze_set_insn_for_autopref (set, write, &base, &offset))
5596*38fd1498Szrj 	    return;
5597*38fd1498Szrj 
5598*38fd1498Szrj 	  /* Ensure that all memory operations in the PARALLEL use the same
5599*38fd1498Szrj 	     base register.  */
5600*38fd1498Szrj 	  if (i > 0 && REGNO (base) != REGNO (prev_base))
5601*38fd1498Szrj 	    return;
5602*38fd1498Szrj 	  prev_base = base;
5603*38fd1498Szrj 	  min_offset = MIN (min_offset, offset);
5604*38fd1498Szrj 	}
5605*38fd1498Szrj 
5606*38fd1498Szrj       /* If we reached here then we have a valid PARALLEL of multiple memory ops
5607*38fd1498Szrj 	 with prev_base as the base and min_offset containing the offset.  */
5608*38fd1498Szrj       gcc_assert (prev_base);
5609*38fd1498Szrj       data->base = prev_base;
5610*38fd1498Szrj       data->offset = min_offset;
5611*38fd1498Szrj       data->status = AUTOPREF_MULTIPASS_DATA_NORMAL;
5612*38fd1498Szrj       return;
5613*38fd1498Szrj     }
5614*38fd1498Szrj 
5615*38fd1498Szrj   /* Otherwise this is a single set memory operation.  */
5616*38fd1498Szrj   rtx set = single_set (insn);
5617*38fd1498Szrj   if (set == NULL_RTX)
5618*38fd1498Szrj     return;
5619*38fd1498Szrj 
5620*38fd1498Szrj   if (!analyze_set_insn_for_autopref (set, write, &data->base,
5621*38fd1498Szrj 				       &data->offset))
5622*38fd1498Szrj     return;
5623*38fd1498Szrj 
5624*38fd1498Szrj   /* This insn is relevant for the auto-prefetcher.
5625*38fd1498Szrj      The base and offset fields will have been filled in the
5626*38fd1498Szrj      analyze_set_insn_for_autopref call above.  */
5627*38fd1498Szrj   data->status = AUTOPREF_MULTIPASS_DATA_NORMAL;
5628*38fd1498Szrj }
5629*38fd1498Szrj 
5630*38fd1498Szrj /* Helper function for rank_for_schedule sorting.  */
5631*38fd1498Szrj static int
autopref_rank_for_schedule(const rtx_insn * insn1,const rtx_insn * insn2)5632*38fd1498Szrj autopref_rank_for_schedule (const rtx_insn *insn1, const rtx_insn *insn2)
5633*38fd1498Szrj {
5634*38fd1498Szrj   int r = 0;
5635*38fd1498Szrj   for (int write = 0; write < 2 && !r; ++write)
5636*38fd1498Szrj     {
5637*38fd1498Szrj       autopref_multipass_data_t data1
5638*38fd1498Szrj 	= &INSN_AUTOPREF_MULTIPASS_DATA (insn1)[write];
5639*38fd1498Szrj       autopref_multipass_data_t data2
5640*38fd1498Szrj 	= &INSN_AUTOPREF_MULTIPASS_DATA (insn2)[write];
5641*38fd1498Szrj 
5642*38fd1498Szrj       if (data1->status == AUTOPREF_MULTIPASS_DATA_UNINITIALIZED)
5643*38fd1498Szrj 	autopref_multipass_init (insn1, write);
5644*38fd1498Szrj 
5645*38fd1498Szrj       if (data2->status == AUTOPREF_MULTIPASS_DATA_UNINITIALIZED)
5646*38fd1498Szrj 	autopref_multipass_init (insn2, write);
5647*38fd1498Szrj 
5648*38fd1498Szrj       int irrel1 = data1->status == AUTOPREF_MULTIPASS_DATA_IRRELEVANT;
5649*38fd1498Szrj       int irrel2 = data2->status == AUTOPREF_MULTIPASS_DATA_IRRELEVANT;
5650*38fd1498Szrj 
5651*38fd1498Szrj       if (!irrel1 && !irrel2)
5652*38fd1498Szrj 	r = data1->offset - data2->offset;
5653*38fd1498Szrj       else
5654*38fd1498Szrj 	r = irrel2 - irrel1;
5655*38fd1498Szrj     }
5656*38fd1498Szrj 
5657*38fd1498Szrj   return r;
5658*38fd1498Szrj }
5659*38fd1498Szrj 
5660*38fd1498Szrj /* True if header of debug dump was printed.  */
5661*38fd1498Szrj static bool autopref_multipass_dfa_lookahead_guard_started_dump_p;
5662*38fd1498Szrj 
5663*38fd1498Szrj /* Helper for autopref_multipass_dfa_lookahead_guard.
5664*38fd1498Szrj    Return "1" if INSN1 should be delayed in favor of INSN2.  */
5665*38fd1498Szrj static int
autopref_multipass_dfa_lookahead_guard_1(const rtx_insn * insn1,const rtx_insn * insn2,int write)5666*38fd1498Szrj autopref_multipass_dfa_lookahead_guard_1 (const rtx_insn *insn1,
5667*38fd1498Szrj 					  const rtx_insn *insn2, int write)
5668*38fd1498Szrj {
5669*38fd1498Szrj   autopref_multipass_data_t data1
5670*38fd1498Szrj     = &INSN_AUTOPREF_MULTIPASS_DATA (insn1)[write];
5671*38fd1498Szrj   autopref_multipass_data_t data2
5672*38fd1498Szrj     = &INSN_AUTOPREF_MULTIPASS_DATA (insn2)[write];
5673*38fd1498Szrj 
5674*38fd1498Szrj   if (data2->status == AUTOPREF_MULTIPASS_DATA_UNINITIALIZED)
5675*38fd1498Szrj     autopref_multipass_init (insn2, write);
5676*38fd1498Szrj   if (data2->status == AUTOPREF_MULTIPASS_DATA_IRRELEVANT)
5677*38fd1498Szrj     return 0;
5678*38fd1498Szrj 
5679*38fd1498Szrj   if (rtx_equal_p (data1->base, data2->base)
5680*38fd1498Szrj       && data1->offset > data2->offset)
5681*38fd1498Szrj     {
5682*38fd1498Szrj       if (sched_verbose >= 2)
5683*38fd1498Szrj 	{
5684*38fd1498Szrj           if (!autopref_multipass_dfa_lookahead_guard_started_dump_p)
5685*38fd1498Szrj 	    {
5686*38fd1498Szrj 	      fprintf (sched_dump,
5687*38fd1498Szrj 		       ";;\t\tnot trying in max_issue due to autoprefetch "
5688*38fd1498Szrj 		       "model: ");
5689*38fd1498Szrj 	      autopref_multipass_dfa_lookahead_guard_started_dump_p = true;
5690*38fd1498Szrj 	    }
5691*38fd1498Szrj 
5692*38fd1498Szrj 	  fprintf (sched_dump, " %d(%d)", INSN_UID (insn1), INSN_UID (insn2));
5693*38fd1498Szrj 	}
5694*38fd1498Szrj 
5695*38fd1498Szrj       return 1;
5696*38fd1498Szrj     }
5697*38fd1498Szrj 
5698*38fd1498Szrj   return 0;
5699*38fd1498Szrj }
5700*38fd1498Szrj 
5701*38fd1498Szrj /* General note:
5702*38fd1498Szrj 
5703*38fd1498Szrj    We could have also hooked autoprefetcher model into
5704*38fd1498Szrj    first_cycle_multipass_backtrack / first_cycle_multipass_issue hooks
5705*38fd1498Szrj    to enable intelligent selection of "[r1+0]=r2; [r1+4]=r3" on the same cycle
5706*38fd1498Szrj    (e.g., once "[r1+0]=r2" is issued in max_issue(), "[r1+4]=r3" gets
5707*38fd1498Szrj    unblocked).  We don't bother about this yet because target of interest
5708*38fd1498Szrj    (ARM Cortex-A15) can issue only 1 memory operation per cycle.  */
5709*38fd1498Szrj 
5710*38fd1498Szrj /* Implementation of first_cycle_multipass_dfa_lookahead_guard hook.
5711*38fd1498Szrj    Return "1" if INSN1 should not be considered in max_issue due to
5712*38fd1498Szrj    auto-prefetcher considerations.  */
5713*38fd1498Szrj int
autopref_multipass_dfa_lookahead_guard(rtx_insn * insn1,int ready_index)5714*38fd1498Szrj autopref_multipass_dfa_lookahead_guard (rtx_insn *insn1, int ready_index)
5715*38fd1498Szrj {
5716*38fd1498Szrj   int r = 0;
5717*38fd1498Szrj 
5718*38fd1498Szrj   /* Exit early if the param forbids this or if we're not entering here through
5719*38fd1498Szrj      normal haifa scheduling.  This can happen if selective scheduling is
5720*38fd1498Szrj      explicitly enabled.  */
5721*38fd1498Szrj   if (!insn_queue || PARAM_VALUE (PARAM_SCHED_AUTOPREF_QUEUE_DEPTH) <= 0)
5722*38fd1498Szrj     return 0;
5723*38fd1498Szrj 
5724*38fd1498Szrj   if (sched_verbose >= 2 && ready_index == 0)
5725*38fd1498Szrj     autopref_multipass_dfa_lookahead_guard_started_dump_p = false;
5726*38fd1498Szrj 
5727*38fd1498Szrj   for (int write = 0; write < 2; ++write)
5728*38fd1498Szrj     {
5729*38fd1498Szrj       autopref_multipass_data_t data1
5730*38fd1498Szrj 	= &INSN_AUTOPREF_MULTIPASS_DATA (insn1)[write];
5731*38fd1498Szrj 
5732*38fd1498Szrj       if (data1->status == AUTOPREF_MULTIPASS_DATA_UNINITIALIZED)
5733*38fd1498Szrj 	autopref_multipass_init (insn1, write);
5734*38fd1498Szrj       if (data1->status == AUTOPREF_MULTIPASS_DATA_IRRELEVANT)
5735*38fd1498Szrj 	continue;
5736*38fd1498Szrj 
5737*38fd1498Szrj       if (ready_index == 0
5738*38fd1498Szrj 	  && data1->status == AUTOPREF_MULTIPASS_DATA_DONT_DELAY)
5739*38fd1498Szrj 	/* We allow only a single delay on priviledged instructions.
5740*38fd1498Szrj 	   Doing otherwise would cause infinite loop.  */
5741*38fd1498Szrj 	{
5742*38fd1498Szrj 	  if (sched_verbose >= 2)
5743*38fd1498Szrj 	    {
5744*38fd1498Szrj 	      if (!autopref_multipass_dfa_lookahead_guard_started_dump_p)
5745*38fd1498Szrj 		{
5746*38fd1498Szrj 		  fprintf (sched_dump,
5747*38fd1498Szrj 			   ";;\t\tnot trying in max_issue due to autoprefetch "
5748*38fd1498Szrj 			   "model: ");
5749*38fd1498Szrj 		  autopref_multipass_dfa_lookahead_guard_started_dump_p = true;
5750*38fd1498Szrj 		}
5751*38fd1498Szrj 
5752*38fd1498Szrj 	      fprintf (sched_dump, " *%d*", INSN_UID (insn1));
5753*38fd1498Szrj 	    }
5754*38fd1498Szrj 	  continue;
5755*38fd1498Szrj 	}
5756*38fd1498Szrj 
5757*38fd1498Szrj       for (int i2 = 0; i2 < ready.n_ready; ++i2)
5758*38fd1498Szrj 	{
5759*38fd1498Szrj 	  rtx_insn *insn2 = get_ready_element (i2);
5760*38fd1498Szrj 	  if (insn1 == insn2)
5761*38fd1498Szrj 	    continue;
5762*38fd1498Szrj 	  r = autopref_multipass_dfa_lookahead_guard_1 (insn1, insn2, write);
5763*38fd1498Szrj 	  if (r)
5764*38fd1498Szrj 	    {
5765*38fd1498Szrj 	      if (ready_index == 0)
5766*38fd1498Szrj 		{
5767*38fd1498Szrj 		  r = -1;
5768*38fd1498Szrj 		  data1->status = AUTOPREF_MULTIPASS_DATA_DONT_DELAY;
5769*38fd1498Szrj 		}
5770*38fd1498Szrj 	      goto finish;
5771*38fd1498Szrj 	    }
5772*38fd1498Szrj 	}
5773*38fd1498Szrj 
5774*38fd1498Szrj       if (PARAM_VALUE (PARAM_SCHED_AUTOPREF_QUEUE_DEPTH) == 1)
5775*38fd1498Szrj 	continue;
5776*38fd1498Szrj 
5777*38fd1498Szrj       /* Everything from the current queue slot should have been moved to
5778*38fd1498Szrj 	 the ready list.  */
5779*38fd1498Szrj       gcc_assert (insn_queue[NEXT_Q_AFTER (q_ptr, 0)] == NULL_RTX);
5780*38fd1498Szrj 
5781*38fd1498Szrj       int n_stalls = PARAM_VALUE (PARAM_SCHED_AUTOPREF_QUEUE_DEPTH) - 1;
5782*38fd1498Szrj       if (n_stalls > max_insn_queue_index)
5783*38fd1498Szrj 	n_stalls = max_insn_queue_index;
5784*38fd1498Szrj 
5785*38fd1498Szrj       for (int stalls = 1; stalls <= n_stalls; ++stalls)
5786*38fd1498Szrj 	{
5787*38fd1498Szrj 	  for (rtx_insn_list *link = insn_queue[NEXT_Q_AFTER (q_ptr, stalls)];
5788*38fd1498Szrj 	       link != NULL_RTX;
5789*38fd1498Szrj 	       link = link->next ())
5790*38fd1498Szrj 	    {
5791*38fd1498Szrj 	      rtx_insn *insn2 = link->insn ();
5792*38fd1498Szrj 	      r = autopref_multipass_dfa_lookahead_guard_1 (insn1, insn2,
5793*38fd1498Szrj 							    write);
5794*38fd1498Szrj 	      if (r)
5795*38fd1498Szrj 		{
5796*38fd1498Szrj 		  /* Queue INSN1 until INSN2 can issue.  */
5797*38fd1498Szrj 		  r = -stalls;
5798*38fd1498Szrj 		  if (ready_index == 0)
5799*38fd1498Szrj 		    data1->status = AUTOPREF_MULTIPASS_DATA_DONT_DELAY;
5800*38fd1498Szrj 		  goto finish;
5801*38fd1498Szrj 		}
5802*38fd1498Szrj 	    }
5803*38fd1498Szrj 	}
5804*38fd1498Szrj     }
5805*38fd1498Szrj 
5806*38fd1498Szrj     finish:
5807*38fd1498Szrj   if (sched_verbose >= 2
5808*38fd1498Szrj       && autopref_multipass_dfa_lookahead_guard_started_dump_p
5809*38fd1498Szrj       && (ready_index == ready.n_ready - 1 || r < 0))
5810*38fd1498Szrj     /* This does not /always/ trigger.  We don't output EOL if the last
5811*38fd1498Szrj        insn is not recognized (INSN_CODE < 0) and lookahead_guard is not
5812*38fd1498Szrj        called.  We can live with this.  */
5813*38fd1498Szrj     fprintf (sched_dump, "\n");
5814*38fd1498Szrj 
5815*38fd1498Szrj   return r;
5816*38fd1498Szrj }
5817*38fd1498Szrj 
5818*38fd1498Szrj /* Define type for target data used in multipass scheduling.  */
5819*38fd1498Szrj #ifndef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DATA_T
5820*38fd1498Szrj # define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DATA_T int
5821*38fd1498Szrj #endif
5822*38fd1498Szrj typedef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DATA_T first_cycle_multipass_data_t;
5823*38fd1498Szrj 
5824*38fd1498Szrj /* The following structure describe an entry of the stack of choices.  */
5825*38fd1498Szrj struct choice_entry
5826*38fd1498Szrj {
5827*38fd1498Szrj   /* Ordinal number of the issued insn in the ready queue.  */
5828*38fd1498Szrj   int index;
5829*38fd1498Szrj   /* The number of the rest insns whose issues we should try.  */
5830*38fd1498Szrj   int rest;
5831*38fd1498Szrj   /* The number of issued essential insns.  */
5832*38fd1498Szrj   int n;
5833*38fd1498Szrj   /* State after issuing the insn.  */
5834*38fd1498Szrj   state_t state;
5835*38fd1498Szrj   /* Target-specific data.  */
5836*38fd1498Szrj   first_cycle_multipass_data_t target_data;
5837*38fd1498Szrj };
5838*38fd1498Szrj 
5839*38fd1498Szrj /* The following array is used to implement a stack of choices used in
5840*38fd1498Szrj    function max_issue.  */
5841*38fd1498Szrj static struct choice_entry *choice_stack;
5842*38fd1498Szrj 
5843*38fd1498Szrj /* This holds the value of the target dfa_lookahead hook.  */
5844*38fd1498Szrj int dfa_lookahead;
5845*38fd1498Szrj 
5846*38fd1498Szrj /* The following variable value is maximal number of tries of issuing
5847*38fd1498Szrj    insns for the first cycle multipass insn scheduling.  We define
5848*38fd1498Szrj    this value as constant*(DFA_LOOKAHEAD**ISSUE_RATE).  We would not
5849*38fd1498Szrj    need this constraint if all real insns (with non-negative codes)
5850*38fd1498Szrj    had reservations because in this case the algorithm complexity is
5851*38fd1498Szrj    O(DFA_LOOKAHEAD**ISSUE_RATE).  Unfortunately, the dfa descriptions
5852*38fd1498Szrj    might be incomplete and such insn might occur.  For such
5853*38fd1498Szrj    descriptions, the complexity of algorithm (without the constraint)
5854*38fd1498Szrj    could achieve DFA_LOOKAHEAD ** N , where N is the queue length.  */
5855*38fd1498Szrj static int max_lookahead_tries;
5856*38fd1498Szrj 
5857*38fd1498Szrj /* The following function returns maximal (or close to maximal) number
5858*38fd1498Szrj    of insns which can be issued on the same cycle and one of which
5859*38fd1498Szrj    insns is insns with the best rank (the first insn in READY).  To
5860*38fd1498Szrj    make this function tries different samples of ready insns.  READY
5861*38fd1498Szrj    is current queue `ready'.  Global array READY_TRY reflects what
5862*38fd1498Szrj    insns are already issued in this try.  The function stops immediately,
5863*38fd1498Szrj    if it reached the such a solution, that all instruction can be issued.
5864*38fd1498Szrj    INDEX will contain index of the best insn in READY.  The following
5865*38fd1498Szrj    function is used only for first cycle multipass scheduling.
5866*38fd1498Szrj 
5867*38fd1498Szrj    PRIVILEGED_N >= 0
5868*38fd1498Szrj 
5869*38fd1498Szrj    This function expects recognized insns only.  All USEs,
5870*38fd1498Szrj    CLOBBERs, etc must be filtered elsewhere.  */
5871*38fd1498Szrj int
max_issue(struct ready_list * ready,int privileged_n,state_t state,bool first_cycle_insn_p,int * index)5872*38fd1498Szrj max_issue (struct ready_list *ready, int privileged_n, state_t state,
5873*38fd1498Szrj 	   bool first_cycle_insn_p, int *index)
5874*38fd1498Szrj {
5875*38fd1498Szrj   int n, i, all, n_ready, best, delay, tries_num;
5876*38fd1498Szrj   int more_issue;
5877*38fd1498Szrj   struct choice_entry *top;
5878*38fd1498Szrj   rtx_insn *insn;
5879*38fd1498Szrj 
5880*38fd1498Szrj   if (sched_fusion)
5881*38fd1498Szrj     return 0;
5882*38fd1498Szrj 
5883*38fd1498Szrj   n_ready = ready->n_ready;
5884*38fd1498Szrj   gcc_assert (dfa_lookahead >= 1 && privileged_n >= 0
5885*38fd1498Szrj 	      && privileged_n <= n_ready);
5886*38fd1498Szrj 
5887*38fd1498Szrj   /* Init MAX_LOOKAHEAD_TRIES.  */
5888*38fd1498Szrj   if (max_lookahead_tries == 0)
5889*38fd1498Szrj     {
5890*38fd1498Szrj       max_lookahead_tries = 100;
5891*38fd1498Szrj       for (i = 0; i < issue_rate; i++)
5892*38fd1498Szrj 	max_lookahead_tries *= dfa_lookahead;
5893*38fd1498Szrj     }
5894*38fd1498Szrj 
5895*38fd1498Szrj   /* Init max_points.  */
5896*38fd1498Szrj   more_issue = issue_rate - cycle_issued_insns;
5897*38fd1498Szrj   gcc_assert (more_issue >= 0);
5898*38fd1498Szrj 
5899*38fd1498Szrj   /* The number of the issued insns in the best solution.  */
5900*38fd1498Szrj   best = 0;
5901*38fd1498Szrj 
5902*38fd1498Szrj   top = choice_stack;
5903*38fd1498Szrj 
5904*38fd1498Szrj   /* Set initial state of the search.  */
5905*38fd1498Szrj   memcpy (top->state, state, dfa_state_size);
5906*38fd1498Szrj   top->rest = dfa_lookahead;
5907*38fd1498Szrj   top->n = 0;
5908*38fd1498Szrj   if (targetm.sched.first_cycle_multipass_begin)
5909*38fd1498Szrj     targetm.sched.first_cycle_multipass_begin (&top->target_data,
5910*38fd1498Szrj 					       ready_try, n_ready,
5911*38fd1498Szrj 					       first_cycle_insn_p);
5912*38fd1498Szrj 
5913*38fd1498Szrj   /* Count the number of the insns to search among.  */
5914*38fd1498Szrj   for (all = i = 0; i < n_ready; i++)
5915*38fd1498Szrj     if (!ready_try [i])
5916*38fd1498Szrj       all++;
5917*38fd1498Szrj 
5918*38fd1498Szrj   if (sched_verbose >= 2)
5919*38fd1498Szrj     {
5920*38fd1498Szrj       fprintf (sched_dump, ";;\t\tmax_issue among %d insns:", all);
5921*38fd1498Szrj       debug_ready_list_1 (ready, ready_try);
5922*38fd1498Szrj     }
5923*38fd1498Szrj 
5924*38fd1498Szrj   /* I is the index of the insn to try next.  */
5925*38fd1498Szrj   i = 0;
5926*38fd1498Szrj   tries_num = 0;
5927*38fd1498Szrj   for (;;)
5928*38fd1498Szrj     {
5929*38fd1498Szrj       if (/* If we've reached a dead end or searched enough of what we have
5930*38fd1498Szrj 	     been asked...  */
5931*38fd1498Szrj 	  top->rest == 0
5932*38fd1498Szrj 	  /* or have nothing else to try...  */
5933*38fd1498Szrj 	  || i >= n_ready
5934*38fd1498Szrj 	  /* or should not issue more.  */
5935*38fd1498Szrj 	  || top->n >= more_issue)
5936*38fd1498Szrj 	{
5937*38fd1498Szrj 	  /* ??? (... || i == n_ready).  */
5938*38fd1498Szrj 	  gcc_assert (i <= n_ready);
5939*38fd1498Szrj 
5940*38fd1498Szrj 	  /* We should not issue more than issue_rate instructions.  */
5941*38fd1498Szrj 	  gcc_assert (top->n <= more_issue);
5942*38fd1498Szrj 
5943*38fd1498Szrj 	  if (top == choice_stack)
5944*38fd1498Szrj 	    break;
5945*38fd1498Szrj 
5946*38fd1498Szrj 	  if (best < top - choice_stack)
5947*38fd1498Szrj 	    {
5948*38fd1498Szrj 	      if (privileged_n)
5949*38fd1498Szrj 		{
5950*38fd1498Szrj 		  n = privileged_n;
5951*38fd1498Szrj 		  /* Try to find issued privileged insn.  */
5952*38fd1498Szrj 		  while (n && !ready_try[--n])
5953*38fd1498Szrj 		    ;
5954*38fd1498Szrj 		}
5955*38fd1498Szrj 
5956*38fd1498Szrj 	      if (/* If all insns are equally good...  */
5957*38fd1498Szrj 		  privileged_n == 0
5958*38fd1498Szrj 		  /* Or a privileged insn will be issued.  */
5959*38fd1498Szrj 		  || ready_try[n])
5960*38fd1498Szrj 		/* Then we have a solution.  */
5961*38fd1498Szrj 		{
5962*38fd1498Szrj 		  best = top - choice_stack;
5963*38fd1498Szrj 		  /* This is the index of the insn issued first in this
5964*38fd1498Szrj 		     solution.  */
5965*38fd1498Szrj 		  *index = choice_stack [1].index;
5966*38fd1498Szrj 		  if (top->n == more_issue || best == all)
5967*38fd1498Szrj 		    break;
5968*38fd1498Szrj 		}
5969*38fd1498Szrj 	    }
5970*38fd1498Szrj 
5971*38fd1498Szrj 	  /* Set ready-list index to point to the last insn
5972*38fd1498Szrj 	     ('i++' below will advance it to the next insn).  */
5973*38fd1498Szrj 	  i = top->index;
5974*38fd1498Szrj 
5975*38fd1498Szrj 	  /* Backtrack.  */
5976*38fd1498Szrj 	  ready_try [i] = 0;
5977*38fd1498Szrj 
5978*38fd1498Szrj 	  if (targetm.sched.first_cycle_multipass_backtrack)
5979*38fd1498Szrj 	    targetm.sched.first_cycle_multipass_backtrack (&top->target_data,
5980*38fd1498Szrj 							   ready_try, n_ready);
5981*38fd1498Szrj 
5982*38fd1498Szrj 	  top--;
5983*38fd1498Szrj 	  memcpy (state, top->state, dfa_state_size);
5984*38fd1498Szrj 	}
5985*38fd1498Szrj       else if (!ready_try [i])
5986*38fd1498Szrj 	{
5987*38fd1498Szrj 	  tries_num++;
5988*38fd1498Szrj 	  if (tries_num > max_lookahead_tries)
5989*38fd1498Szrj 	    break;
5990*38fd1498Szrj 	  insn = ready_element (ready, i);
5991*38fd1498Szrj 	  delay = state_transition (state, insn);
5992*38fd1498Szrj 	  if (delay < 0)
5993*38fd1498Szrj 	    {
5994*38fd1498Szrj 	      if (state_dead_lock_p (state)
5995*38fd1498Szrj 		  || insn_finishes_cycle_p (insn))
5996*38fd1498Szrj 		/* We won't issue any more instructions in the next
5997*38fd1498Szrj 		   choice_state.  */
5998*38fd1498Szrj 		top->rest = 0;
5999*38fd1498Szrj 	      else
6000*38fd1498Szrj 		top->rest--;
6001*38fd1498Szrj 
6002*38fd1498Szrj 	      n = top->n;
6003*38fd1498Szrj 	      if (memcmp (top->state, state, dfa_state_size) != 0)
6004*38fd1498Szrj 		n++;
6005*38fd1498Szrj 
6006*38fd1498Szrj 	      /* Advance to the next choice_entry.  */
6007*38fd1498Szrj 	      top++;
6008*38fd1498Szrj 	      /* Initialize it.  */
6009*38fd1498Szrj 	      top->rest = dfa_lookahead;
6010*38fd1498Szrj 	      top->index = i;
6011*38fd1498Szrj 	      top->n = n;
6012*38fd1498Szrj 	      memcpy (top->state, state, dfa_state_size);
6013*38fd1498Szrj 	      ready_try [i] = 1;
6014*38fd1498Szrj 
6015*38fd1498Szrj 	      if (targetm.sched.first_cycle_multipass_issue)
6016*38fd1498Szrj 		targetm.sched.first_cycle_multipass_issue (&top->target_data,
6017*38fd1498Szrj 							   ready_try, n_ready,
6018*38fd1498Szrj 							   insn,
6019*38fd1498Szrj 							   &((top - 1)
6020*38fd1498Szrj 							     ->target_data));
6021*38fd1498Szrj 
6022*38fd1498Szrj 	      i = -1;
6023*38fd1498Szrj 	    }
6024*38fd1498Szrj 	}
6025*38fd1498Szrj 
6026*38fd1498Szrj       /* Increase ready-list index.  */
6027*38fd1498Szrj       i++;
6028*38fd1498Szrj     }
6029*38fd1498Szrj 
6030*38fd1498Szrj   if (targetm.sched.first_cycle_multipass_end)
6031*38fd1498Szrj     targetm.sched.first_cycle_multipass_end (best != 0
6032*38fd1498Szrj 					     ? &choice_stack[1].target_data
6033*38fd1498Szrj 					     : NULL);
6034*38fd1498Szrj 
6035*38fd1498Szrj   /* Restore the original state of the DFA.  */
6036*38fd1498Szrj   memcpy (state, choice_stack->state, dfa_state_size);
6037*38fd1498Szrj 
6038*38fd1498Szrj   return best;
6039*38fd1498Szrj }
6040*38fd1498Szrj 
6041*38fd1498Szrj /* The following function chooses insn from READY and modifies
6042*38fd1498Szrj    READY.  The following function is used only for first
6043*38fd1498Szrj    cycle multipass scheduling.
6044*38fd1498Szrj    Return:
6045*38fd1498Szrj    -1 if cycle should be advanced,
6046*38fd1498Szrj    0 if INSN_PTR is set to point to the desirable insn,
6047*38fd1498Szrj    1 if choose_ready () should be restarted without advancing the cycle.  */
6048*38fd1498Szrj static int
choose_ready(struct ready_list * ready,bool first_cycle_insn_p,rtx_insn ** insn_ptr)6049*38fd1498Szrj choose_ready (struct ready_list *ready, bool first_cycle_insn_p,
6050*38fd1498Szrj 	      rtx_insn **insn_ptr)
6051*38fd1498Szrj {
6052*38fd1498Szrj   if (dbg_cnt (sched_insn) == false)
6053*38fd1498Szrj     {
6054*38fd1498Szrj       if (nonscheduled_insns_begin == NULL_RTX)
6055*38fd1498Szrj 	nonscheduled_insns_begin = current_sched_info->prev_head;
6056*38fd1498Szrj 
6057*38fd1498Szrj       rtx_insn *insn = first_nonscheduled_insn ();
6058*38fd1498Szrj 
6059*38fd1498Szrj       if (QUEUE_INDEX (insn) == QUEUE_READY)
6060*38fd1498Szrj 	/* INSN is in the ready_list.  */
6061*38fd1498Szrj 	{
6062*38fd1498Szrj 	  ready_remove_insn (insn);
6063*38fd1498Szrj 	  *insn_ptr = insn;
6064*38fd1498Szrj 	  return 0;
6065*38fd1498Szrj 	}
6066*38fd1498Szrj 
6067*38fd1498Szrj       /* INSN is in the queue.  Advance cycle to move it to the ready list.  */
6068*38fd1498Szrj       gcc_assert (QUEUE_INDEX (insn) >= 0);
6069*38fd1498Szrj       return -1;
6070*38fd1498Szrj     }
6071*38fd1498Szrj 
6072*38fd1498Szrj   if (dfa_lookahead <= 0 || SCHED_GROUP_P (ready_element (ready, 0))
6073*38fd1498Szrj       || DEBUG_INSN_P (ready_element (ready, 0)))
6074*38fd1498Szrj     {
6075*38fd1498Szrj       if (targetm.sched.dispatch (NULL, IS_DISPATCH_ON))
6076*38fd1498Szrj 	*insn_ptr = ready_remove_first_dispatch (ready);
6077*38fd1498Szrj       else
6078*38fd1498Szrj 	*insn_ptr = ready_remove_first (ready);
6079*38fd1498Szrj 
6080*38fd1498Szrj       return 0;
6081*38fd1498Szrj     }
6082*38fd1498Szrj   else
6083*38fd1498Szrj     {
6084*38fd1498Szrj       /* Try to choose the best insn.  */
6085*38fd1498Szrj       int index = 0, i;
6086*38fd1498Szrj       rtx_insn *insn;
6087*38fd1498Szrj 
6088*38fd1498Szrj       insn = ready_element (ready, 0);
6089*38fd1498Szrj       if (INSN_CODE (insn) < 0)
6090*38fd1498Szrj 	{
6091*38fd1498Szrj 	  *insn_ptr = ready_remove_first (ready);
6092*38fd1498Szrj 	  return 0;
6093*38fd1498Szrj 	}
6094*38fd1498Szrj 
6095*38fd1498Szrj       /* Filter the search space.  */
6096*38fd1498Szrj       for (i = 0; i < ready->n_ready; i++)
6097*38fd1498Szrj 	{
6098*38fd1498Szrj 	  ready_try[i] = 0;
6099*38fd1498Szrj 
6100*38fd1498Szrj 	  insn = ready_element (ready, i);
6101*38fd1498Szrj 
6102*38fd1498Szrj 	  /* If this insn is recognizable we should have already
6103*38fd1498Szrj 	     recognized it earlier.
6104*38fd1498Szrj 	     ??? Not very clear where this is supposed to be done.
6105*38fd1498Szrj 	     See dep_cost_1.  */
6106*38fd1498Szrj 	  gcc_checking_assert (INSN_CODE (insn) >= 0
6107*38fd1498Szrj 			       || recog_memoized (insn) < 0);
6108*38fd1498Szrj 	  if (INSN_CODE (insn) < 0)
6109*38fd1498Szrj 	    {
6110*38fd1498Szrj 	      /* Non-recognized insns at position 0 are handled above.  */
6111*38fd1498Szrj 	      gcc_assert (i > 0);
6112*38fd1498Szrj 	      ready_try[i] = 1;
6113*38fd1498Szrj 	      continue;
6114*38fd1498Szrj 	    }
6115*38fd1498Szrj 
6116*38fd1498Szrj 	  if (targetm.sched.first_cycle_multipass_dfa_lookahead_guard)
6117*38fd1498Szrj 	    {
6118*38fd1498Szrj 	      ready_try[i]
6119*38fd1498Szrj 		= (targetm.sched.first_cycle_multipass_dfa_lookahead_guard
6120*38fd1498Szrj 		    (insn, i));
6121*38fd1498Szrj 
6122*38fd1498Szrj 	      if (ready_try[i] < 0)
6123*38fd1498Szrj 		/* Queue instruction for several cycles.
6124*38fd1498Szrj 		   We need to restart choose_ready as we have changed
6125*38fd1498Szrj 		   the ready list.  */
6126*38fd1498Szrj 		{
6127*38fd1498Szrj 		  change_queue_index (insn, -ready_try[i]);
6128*38fd1498Szrj 		  return 1;
6129*38fd1498Szrj 		}
6130*38fd1498Szrj 
6131*38fd1498Szrj 	      /* Make sure that we didn't end up with 0'th insn filtered out.
6132*38fd1498Szrj 		 Don't be tempted to make life easier for backends and just
6133*38fd1498Szrj 		 requeue 0'th insn if (ready_try[0] == 0) and restart
6134*38fd1498Szrj 		 choose_ready.  Backends should be very considerate about
6135*38fd1498Szrj 		 requeueing instructions -- especially the highest priority
6136*38fd1498Szrj 		 one at position 0.  */
6137*38fd1498Szrj 	      gcc_assert (ready_try[i] == 0 || i > 0);
6138*38fd1498Szrj 	      if (ready_try[i])
6139*38fd1498Szrj 		continue;
6140*38fd1498Szrj 	    }
6141*38fd1498Szrj 
6142*38fd1498Szrj 	  gcc_assert (ready_try[i] == 0);
6143*38fd1498Szrj 	  /* INSN made it through the scrutiny of filters!  */
6144*38fd1498Szrj 	}
6145*38fd1498Szrj 
6146*38fd1498Szrj       if (max_issue (ready, 1, curr_state, first_cycle_insn_p, &index) == 0)
6147*38fd1498Szrj 	{
6148*38fd1498Szrj 	  *insn_ptr = ready_remove_first (ready);
6149*38fd1498Szrj 	  if (sched_verbose >= 4)
6150*38fd1498Szrj 	    fprintf (sched_dump, ";;\t\tChosen insn (but can't issue) : %s \n",
6151*38fd1498Szrj                      (*current_sched_info->print_insn) (*insn_ptr, 0));
6152*38fd1498Szrj 	  return 0;
6153*38fd1498Szrj 	}
6154*38fd1498Szrj       else
6155*38fd1498Szrj 	{
6156*38fd1498Szrj 	  if (sched_verbose >= 4)
6157*38fd1498Szrj 	    fprintf (sched_dump, ";;\t\tChosen insn : %s\n",
6158*38fd1498Szrj 		     (*current_sched_info->print_insn)
6159*38fd1498Szrj 		     (ready_element (ready, index), 0));
6160*38fd1498Szrj 
6161*38fd1498Szrj 	  *insn_ptr = ready_remove (ready, index);
6162*38fd1498Szrj 	  return 0;
6163*38fd1498Szrj 	}
6164*38fd1498Szrj     }
6165*38fd1498Szrj }
6166*38fd1498Szrj 
6167*38fd1498Szrj /* This function is called when we have successfully scheduled a
6168*38fd1498Szrj    block.  It uses the schedule stored in the scheduled_insns vector
6169*38fd1498Szrj    to rearrange the RTL.  PREV_HEAD is used as the anchor to which we
6170*38fd1498Szrj    append the scheduled insns; TAIL is the insn after the scheduled
6171*38fd1498Szrj    block.  TARGET_BB is the argument passed to schedule_block.  */
6172*38fd1498Szrj 
6173*38fd1498Szrj static void
commit_schedule(rtx_insn * prev_head,rtx_insn * tail,basic_block * target_bb)6174*38fd1498Szrj commit_schedule (rtx_insn *prev_head, rtx_insn *tail, basic_block *target_bb)
6175*38fd1498Szrj {
6176*38fd1498Szrj   unsigned int i;
6177*38fd1498Szrj   rtx_insn *insn;
6178*38fd1498Szrj 
6179*38fd1498Szrj   last_scheduled_insn = prev_head;
6180*38fd1498Szrj   for (i = 0;
6181*38fd1498Szrj        scheduled_insns.iterate (i, &insn);
6182*38fd1498Szrj        i++)
6183*38fd1498Szrj     {
6184*38fd1498Szrj       if (control_flow_insn_p (last_scheduled_insn)
6185*38fd1498Szrj 	  || current_sched_info->advance_target_bb (*target_bb, insn))
6186*38fd1498Szrj 	{
6187*38fd1498Szrj 	  *target_bb = current_sched_info->advance_target_bb (*target_bb, 0);
6188*38fd1498Szrj 
6189*38fd1498Szrj 	  if (sched_verbose)
6190*38fd1498Szrj 	    {
6191*38fd1498Szrj 	      rtx_insn *x;
6192*38fd1498Szrj 
6193*38fd1498Szrj 	      x = next_real_insn (last_scheduled_insn);
6194*38fd1498Szrj 	      gcc_assert (x);
6195*38fd1498Szrj 	      dump_new_block_header (1, *target_bb, x, tail);
6196*38fd1498Szrj 	    }
6197*38fd1498Szrj 
6198*38fd1498Szrj 	  last_scheduled_insn = bb_note (*target_bb);
6199*38fd1498Szrj 	}
6200*38fd1498Szrj 
6201*38fd1498Szrj       if (current_sched_info->begin_move_insn)
6202*38fd1498Szrj 	(*current_sched_info->begin_move_insn) (insn, last_scheduled_insn);
6203*38fd1498Szrj       move_insn (insn, last_scheduled_insn,
6204*38fd1498Szrj 		 current_sched_info->next_tail);
6205*38fd1498Szrj       if (!DEBUG_INSN_P (insn))
6206*38fd1498Szrj 	reemit_notes (insn);
6207*38fd1498Szrj       last_scheduled_insn = insn;
6208*38fd1498Szrj     }
6209*38fd1498Szrj 
6210*38fd1498Szrj   scheduled_insns.truncate (0);
6211*38fd1498Szrj }
6212*38fd1498Szrj 
6213*38fd1498Szrj /* Examine all insns on the ready list and queue those which can't be
6214*38fd1498Szrj    issued in this cycle.  TEMP_STATE is temporary scheduler state we
6215*38fd1498Szrj    can use as scratch space.  If FIRST_CYCLE_INSN_P is true, no insns
6216*38fd1498Szrj    have been issued for the current cycle, which means it is valid to
6217*38fd1498Szrj    issue an asm statement.
6218*38fd1498Szrj 
6219*38fd1498Szrj    If SHADOWS_ONLY_P is true, we eliminate all real insns and only
6220*38fd1498Szrj    leave those for which SHADOW_P is true.  If MODULO_EPILOGUE is true,
6221*38fd1498Szrj    we only leave insns which have an INSN_EXACT_TICK.  */
6222*38fd1498Szrj 
6223*38fd1498Szrj static void
prune_ready_list(state_t temp_state,bool first_cycle_insn_p,bool shadows_only_p,bool modulo_epilogue_p)6224*38fd1498Szrj prune_ready_list (state_t temp_state, bool first_cycle_insn_p,
6225*38fd1498Szrj 		  bool shadows_only_p, bool modulo_epilogue_p)
6226*38fd1498Szrj {
6227*38fd1498Szrj   int i, pass;
6228*38fd1498Szrj   bool sched_group_found = false;
6229*38fd1498Szrj   int min_cost_group = 0;
6230*38fd1498Szrj 
6231*38fd1498Szrj   if (sched_fusion)
6232*38fd1498Szrj     return;
6233*38fd1498Szrj 
6234*38fd1498Szrj   for (i = 0; i < ready.n_ready; i++)
6235*38fd1498Szrj     {
6236*38fd1498Szrj       rtx_insn *insn = ready_element (&ready, i);
6237*38fd1498Szrj       if (SCHED_GROUP_P (insn))
6238*38fd1498Szrj 	{
6239*38fd1498Szrj 	  sched_group_found = true;
6240*38fd1498Szrj 	  break;
6241*38fd1498Szrj 	}
6242*38fd1498Szrj     }
6243*38fd1498Szrj 
6244*38fd1498Szrj   /* Make two passes if there's a SCHED_GROUP_P insn; make sure to handle
6245*38fd1498Szrj      such an insn first and note its cost.  If at least one SCHED_GROUP_P insn
6246*38fd1498Szrj      gets queued, then all other insns get queued for one cycle later.  */
6247*38fd1498Szrj   for (pass = sched_group_found ? 0 : 1; pass < 2; )
6248*38fd1498Szrj     {
6249*38fd1498Szrj       int n = ready.n_ready;
6250*38fd1498Szrj       for (i = 0; i < n; i++)
6251*38fd1498Szrj 	{
6252*38fd1498Szrj 	  rtx_insn *insn = ready_element (&ready, i);
6253*38fd1498Szrj 	  int cost = 0;
6254*38fd1498Szrj 	  const char *reason = "resource conflict";
6255*38fd1498Szrj 
6256*38fd1498Szrj 	  if (DEBUG_INSN_P (insn))
6257*38fd1498Szrj 	    continue;
6258*38fd1498Szrj 
6259*38fd1498Szrj 	  if (sched_group_found && !SCHED_GROUP_P (insn)
6260*38fd1498Szrj 	      && ((pass == 0) || (min_cost_group >= 1)))
6261*38fd1498Szrj 	    {
6262*38fd1498Szrj 	      if (pass == 0)
6263*38fd1498Szrj 		continue;
6264*38fd1498Szrj 	      cost = min_cost_group;
6265*38fd1498Szrj 	      reason = "not in sched group";
6266*38fd1498Szrj 	    }
6267*38fd1498Szrj 	  else if (modulo_epilogue_p
6268*38fd1498Szrj 		   && INSN_EXACT_TICK (insn) == INVALID_TICK)
6269*38fd1498Szrj 	    {
6270*38fd1498Szrj 	      cost = max_insn_queue_index;
6271*38fd1498Szrj 	      reason = "not an epilogue insn";
6272*38fd1498Szrj 	    }
6273*38fd1498Szrj 	  else if (shadows_only_p && !SHADOW_P (insn))
6274*38fd1498Szrj 	    {
6275*38fd1498Szrj 	      cost = 1;
6276*38fd1498Szrj 	      reason = "not a shadow";
6277*38fd1498Szrj 	    }
6278*38fd1498Szrj 	  else if (recog_memoized (insn) < 0)
6279*38fd1498Szrj 	    {
6280*38fd1498Szrj 	      if (!first_cycle_insn_p
6281*38fd1498Szrj 		  && (GET_CODE (PATTERN (insn)) == ASM_INPUT
6282*38fd1498Szrj 		      || asm_noperands (PATTERN (insn)) >= 0))
6283*38fd1498Szrj 		cost = 1;
6284*38fd1498Szrj 	      reason = "asm";
6285*38fd1498Szrj 	    }
6286*38fd1498Szrj 	  else if (sched_pressure != SCHED_PRESSURE_NONE)
6287*38fd1498Szrj 	    {
6288*38fd1498Szrj 	      if (sched_pressure == SCHED_PRESSURE_MODEL
6289*38fd1498Szrj 		  && INSN_TICK (insn) <= clock_var)
6290*38fd1498Szrj 		{
6291*38fd1498Szrj 		  memcpy (temp_state, curr_state, dfa_state_size);
6292*38fd1498Szrj 		  if (state_transition (temp_state, insn) >= 0)
6293*38fd1498Szrj 		    INSN_TICK (insn) = clock_var + 1;
6294*38fd1498Szrj 		}
6295*38fd1498Szrj 	      cost = 0;
6296*38fd1498Szrj 	    }
6297*38fd1498Szrj 	  else
6298*38fd1498Szrj 	    {
6299*38fd1498Szrj 	      int delay_cost = 0;
6300*38fd1498Szrj 
6301*38fd1498Szrj 	      if (delay_htab)
6302*38fd1498Szrj 		{
6303*38fd1498Szrj 		  struct delay_pair *delay_entry;
6304*38fd1498Szrj 		  delay_entry
6305*38fd1498Szrj 		    = delay_htab->find_with_hash (insn,
6306*38fd1498Szrj 						  htab_hash_pointer (insn));
6307*38fd1498Szrj 		  while (delay_entry && delay_cost == 0)
6308*38fd1498Szrj 		    {
6309*38fd1498Szrj 		      delay_cost = estimate_shadow_tick (delay_entry);
6310*38fd1498Szrj 		      if (delay_cost > max_insn_queue_index)
6311*38fd1498Szrj 			delay_cost = max_insn_queue_index;
6312*38fd1498Szrj 		      delay_entry = delay_entry->next_same_i1;
6313*38fd1498Szrj 		    }
6314*38fd1498Szrj 		}
6315*38fd1498Szrj 
6316*38fd1498Szrj 	      memcpy (temp_state, curr_state, dfa_state_size);
6317*38fd1498Szrj 	      cost = state_transition (temp_state, insn);
6318*38fd1498Szrj 	      if (cost < 0)
6319*38fd1498Szrj 		cost = 0;
6320*38fd1498Szrj 	      else if (cost == 0)
6321*38fd1498Szrj 		cost = 1;
6322*38fd1498Szrj 	      if (cost < delay_cost)
6323*38fd1498Szrj 		{
6324*38fd1498Szrj 		  cost = delay_cost;
6325*38fd1498Szrj 		  reason = "shadow tick";
6326*38fd1498Szrj 		}
6327*38fd1498Szrj 	    }
6328*38fd1498Szrj 	  if (cost >= 1)
6329*38fd1498Szrj 	    {
6330*38fd1498Szrj 	      if (SCHED_GROUP_P (insn) && cost > min_cost_group)
6331*38fd1498Szrj 		min_cost_group = cost;
6332*38fd1498Szrj 	      ready_remove (&ready, i);
6333*38fd1498Szrj 	      /* Normally we'd want to queue INSN for COST cycles.  However,
6334*38fd1498Szrj 		 if SCHED_GROUP_P is set, then we must ensure that nothing
6335*38fd1498Szrj 		 else comes between INSN and its predecessor.  If there is
6336*38fd1498Szrj 		 some other insn ready to fire on the next cycle, then that
6337*38fd1498Szrj 		 invariant would be broken.
6338*38fd1498Szrj 
6339*38fd1498Szrj 		 So when SCHED_GROUP_P is set, just queue this insn for a
6340*38fd1498Szrj 		 single cycle.  */
6341*38fd1498Szrj 	      queue_insn (insn, SCHED_GROUP_P (insn) ? 1 : cost, reason);
6342*38fd1498Szrj 	      if (i + 1 < n)
6343*38fd1498Szrj 		break;
6344*38fd1498Szrj 	    }
6345*38fd1498Szrj 	}
6346*38fd1498Szrj       if (i == n)
6347*38fd1498Szrj 	pass++;
6348*38fd1498Szrj     }
6349*38fd1498Szrj }
6350*38fd1498Szrj 
6351*38fd1498Szrj /* Called when we detect that the schedule is impossible.  We examine the
6352*38fd1498Szrj    backtrack queue to find the earliest insn that caused this condition.  */
6353*38fd1498Szrj 
6354*38fd1498Szrj static struct haifa_saved_data *
verify_shadows(void)6355*38fd1498Szrj verify_shadows (void)
6356*38fd1498Szrj {
6357*38fd1498Szrj   struct haifa_saved_data *save, *earliest_fail = NULL;
6358*38fd1498Szrj   for (save = backtrack_queue; save; save = save->next)
6359*38fd1498Szrj     {
6360*38fd1498Szrj       int t;
6361*38fd1498Szrj       struct delay_pair *pair = save->delay_pair;
6362*38fd1498Szrj       rtx_insn *i1 = pair->i1;
6363*38fd1498Szrj 
6364*38fd1498Szrj       for (; pair; pair = pair->next_same_i1)
6365*38fd1498Szrj 	{
6366*38fd1498Szrj 	  rtx_insn *i2 = pair->i2;
6367*38fd1498Szrj 
6368*38fd1498Szrj 	  if (QUEUE_INDEX (i2) == QUEUE_SCHEDULED)
6369*38fd1498Szrj 	    continue;
6370*38fd1498Szrj 
6371*38fd1498Szrj 	  t = INSN_TICK (i1) + pair_delay (pair);
6372*38fd1498Szrj 	  if (t < clock_var)
6373*38fd1498Szrj 	    {
6374*38fd1498Szrj 	      if (sched_verbose >= 2)
6375*38fd1498Szrj 		fprintf (sched_dump,
6376*38fd1498Szrj 			 ";;\t\tfailed delay requirements for %d/%d (%d->%d)"
6377*38fd1498Szrj 			 ", not ready\n",
6378*38fd1498Szrj 			 INSN_UID (pair->i1), INSN_UID (pair->i2),
6379*38fd1498Szrj 			 INSN_TICK (pair->i1), INSN_EXACT_TICK (pair->i2));
6380*38fd1498Szrj 	      earliest_fail = save;
6381*38fd1498Szrj 	      break;
6382*38fd1498Szrj 	    }
6383*38fd1498Szrj 	  if (QUEUE_INDEX (i2) >= 0)
6384*38fd1498Szrj 	    {
6385*38fd1498Szrj 	      int queued_for = INSN_TICK (i2);
6386*38fd1498Szrj 
6387*38fd1498Szrj 	      if (t < queued_for)
6388*38fd1498Szrj 		{
6389*38fd1498Szrj 		  if (sched_verbose >= 2)
6390*38fd1498Szrj 		    fprintf (sched_dump,
6391*38fd1498Szrj 			     ";;\t\tfailed delay requirements for %d/%d"
6392*38fd1498Szrj 			     " (%d->%d), queued too late\n",
6393*38fd1498Szrj 			     INSN_UID (pair->i1), INSN_UID (pair->i2),
6394*38fd1498Szrj 			     INSN_TICK (pair->i1), INSN_EXACT_TICK (pair->i2));
6395*38fd1498Szrj 		  earliest_fail = save;
6396*38fd1498Szrj 		  break;
6397*38fd1498Szrj 		}
6398*38fd1498Szrj 	    }
6399*38fd1498Szrj 	}
6400*38fd1498Szrj     }
6401*38fd1498Szrj 
6402*38fd1498Szrj   return earliest_fail;
6403*38fd1498Szrj }
6404*38fd1498Szrj 
6405*38fd1498Szrj /* Print instructions together with useful scheduling information between
6406*38fd1498Szrj    HEAD and TAIL (inclusive).  */
6407*38fd1498Szrj static void
dump_insn_stream(rtx_insn * head,rtx_insn * tail)6408*38fd1498Szrj dump_insn_stream (rtx_insn *head, rtx_insn *tail)
6409*38fd1498Szrj {
6410*38fd1498Szrj   fprintf (sched_dump, ";;\t| insn | prio |\n");
6411*38fd1498Szrj 
6412*38fd1498Szrj   rtx_insn *next_tail = NEXT_INSN (tail);
6413*38fd1498Szrj   for (rtx_insn *insn = head; insn != next_tail; insn = NEXT_INSN (insn))
6414*38fd1498Szrj     {
6415*38fd1498Szrj       int priority = NOTE_P (insn) ? 0 : INSN_PRIORITY (insn);
6416*38fd1498Szrj       const char *pattern = (NOTE_P (insn)
6417*38fd1498Szrj 			     ? "note"
6418*38fd1498Szrj 			     : str_pattern_slim (PATTERN (insn)));
6419*38fd1498Szrj 
6420*38fd1498Szrj       fprintf (sched_dump, ";;\t| %4d | %4d | %-30s ",
6421*38fd1498Szrj 	       INSN_UID (insn), priority, pattern);
6422*38fd1498Szrj 
6423*38fd1498Szrj       if (sched_verbose >= 4)
6424*38fd1498Szrj 	{
6425*38fd1498Szrj 	  if (NOTE_P (insn) || LABEL_P (insn) || recog_memoized (insn) < 0)
6426*38fd1498Szrj 	    fprintf (sched_dump, "nothing");
6427*38fd1498Szrj 	  else
6428*38fd1498Szrj 	    print_reservation (sched_dump, insn);
6429*38fd1498Szrj 	}
6430*38fd1498Szrj       fprintf (sched_dump, "\n");
6431*38fd1498Szrj     }
6432*38fd1498Szrj }
6433*38fd1498Szrj 
6434*38fd1498Szrj /* Use forward list scheduling to rearrange insns of block pointed to by
6435*38fd1498Szrj    TARGET_BB, possibly bringing insns from subsequent blocks in the same
6436*38fd1498Szrj    region.  */
6437*38fd1498Szrj 
6438*38fd1498Szrj bool
schedule_block(basic_block * target_bb,state_t init_state)6439*38fd1498Szrj schedule_block (basic_block *target_bb, state_t init_state)
6440*38fd1498Szrj {
6441*38fd1498Szrj   int i;
6442*38fd1498Szrj   bool success = modulo_ii == 0;
6443*38fd1498Szrj   struct sched_block_state ls;
6444*38fd1498Szrj   state_t temp_state = NULL;  /* It is used for multipass scheduling.  */
6445*38fd1498Szrj   int sort_p, advance, start_clock_var;
6446*38fd1498Szrj 
6447*38fd1498Szrj   /* Head/tail info for this block.  */
6448*38fd1498Szrj   rtx_insn *prev_head = current_sched_info->prev_head;
6449*38fd1498Szrj   rtx_insn *next_tail = current_sched_info->next_tail;
6450*38fd1498Szrj   rtx_insn *head = NEXT_INSN (prev_head);
6451*38fd1498Szrj   rtx_insn *tail = PREV_INSN (next_tail);
6452*38fd1498Szrj 
6453*38fd1498Szrj   if ((current_sched_info->flags & DONT_BREAK_DEPENDENCIES) == 0
6454*38fd1498Szrj       && sched_pressure != SCHED_PRESSURE_MODEL && !sched_fusion)
6455*38fd1498Szrj     find_modifiable_mems (head, tail);
6456*38fd1498Szrj 
6457*38fd1498Szrj   /* We used to have code to avoid getting parameters moved from hard
6458*38fd1498Szrj      argument registers into pseudos.
6459*38fd1498Szrj 
6460*38fd1498Szrj      However, it was removed when it proved to be of marginal benefit
6461*38fd1498Szrj      and caused problems because schedule_block and compute_forward_dependences
6462*38fd1498Szrj      had different notions of what the "head" insn was.  */
6463*38fd1498Szrj 
6464*38fd1498Szrj   gcc_assert (head != tail || INSN_P (head));
6465*38fd1498Szrj 
6466*38fd1498Szrj   haifa_recovery_bb_recently_added_p = false;
6467*38fd1498Szrj 
6468*38fd1498Szrj   backtrack_queue = NULL;
6469*38fd1498Szrj 
6470*38fd1498Szrj   /* Debug info.  */
6471*38fd1498Szrj   if (sched_verbose)
6472*38fd1498Szrj     {
6473*38fd1498Szrj       dump_new_block_header (0, *target_bb, head, tail);
6474*38fd1498Szrj 
6475*38fd1498Szrj       if (sched_verbose >= 2)
6476*38fd1498Szrj 	{
6477*38fd1498Szrj 	  dump_insn_stream (head, tail);
6478*38fd1498Szrj 	  memset (&rank_for_schedule_stats, 0,
6479*38fd1498Szrj 		  sizeof (rank_for_schedule_stats));
6480*38fd1498Szrj 	}
6481*38fd1498Szrj     }
6482*38fd1498Szrj 
6483*38fd1498Szrj   if (init_state == NULL)
6484*38fd1498Szrj     state_reset (curr_state);
6485*38fd1498Szrj   else
6486*38fd1498Szrj     memcpy (curr_state, init_state, dfa_state_size);
6487*38fd1498Szrj 
6488*38fd1498Szrj   /* Clear the ready list.  */
6489*38fd1498Szrj   ready.first = ready.veclen - 1;
6490*38fd1498Szrj   ready.n_ready = 0;
6491*38fd1498Szrj   ready.n_debug = 0;
6492*38fd1498Szrj 
6493*38fd1498Szrj   /* It is used for first cycle multipass scheduling.  */
6494*38fd1498Szrj   temp_state = alloca (dfa_state_size);
6495*38fd1498Szrj 
6496*38fd1498Szrj   if (targetm.sched.init)
6497*38fd1498Szrj     targetm.sched.init (sched_dump, sched_verbose, ready.veclen);
6498*38fd1498Szrj 
6499*38fd1498Szrj   /* We start inserting insns after PREV_HEAD.  */
6500*38fd1498Szrj   last_scheduled_insn = prev_head;
6501*38fd1498Szrj   last_nondebug_scheduled_insn = NULL;
6502*38fd1498Szrj   nonscheduled_insns_begin = NULL;
6503*38fd1498Szrj 
6504*38fd1498Szrj   gcc_assert ((NOTE_P (last_scheduled_insn)
6505*38fd1498Szrj 	       || DEBUG_INSN_P (last_scheduled_insn))
6506*38fd1498Szrj 	      && BLOCK_FOR_INSN (last_scheduled_insn) == *target_bb);
6507*38fd1498Szrj 
6508*38fd1498Szrj   /* Initialize INSN_QUEUE.  Q_SIZE is the total number of insns in the
6509*38fd1498Szrj      queue.  */
6510*38fd1498Szrj   q_ptr = 0;
6511*38fd1498Szrj   q_size = 0;
6512*38fd1498Szrj 
6513*38fd1498Szrj   insn_queue = XALLOCAVEC (rtx_insn_list *, max_insn_queue_index + 1);
6514*38fd1498Szrj   memset (insn_queue, 0, (max_insn_queue_index + 1) * sizeof (rtx));
6515*38fd1498Szrj 
6516*38fd1498Szrj   /* Start just before the beginning of time.  */
6517*38fd1498Szrj   clock_var = -1;
6518*38fd1498Szrj 
6519*38fd1498Szrj   /* We need queue and ready lists and clock_var be initialized
6520*38fd1498Szrj      in try_ready () (which is called through init_ready_list ()).  */
6521*38fd1498Szrj   (*current_sched_info->init_ready_list) ();
6522*38fd1498Szrj 
6523*38fd1498Szrj   if (sched_pressure)
6524*38fd1498Szrj     sched_pressure_start_bb (*target_bb);
6525*38fd1498Szrj 
6526*38fd1498Szrj   /* The algorithm is O(n^2) in the number of ready insns at any given
6527*38fd1498Szrj      time in the worst case.  Before reload we are more likely to have
6528*38fd1498Szrj      big lists so truncate them to a reasonable size.  */
6529*38fd1498Szrj   if (!reload_completed
6530*38fd1498Szrj       && ready.n_ready - ready.n_debug > MAX_SCHED_READY_INSNS)
6531*38fd1498Szrj     {
6532*38fd1498Szrj       ready_sort_debug (&ready);
6533*38fd1498Szrj       ready_sort_real (&ready);
6534*38fd1498Szrj 
6535*38fd1498Szrj       /* Find first free-standing insn past MAX_SCHED_READY_INSNS.
6536*38fd1498Szrj          If there are debug insns, we know they're first.  */
6537*38fd1498Szrj       for (i = MAX_SCHED_READY_INSNS + ready.n_debug; i < ready.n_ready; i++)
6538*38fd1498Szrj 	if (!SCHED_GROUP_P (ready_element (&ready, i)))
6539*38fd1498Szrj 	  break;
6540*38fd1498Szrj 
6541*38fd1498Szrj       if (sched_verbose >= 2)
6542*38fd1498Szrj 	{
6543*38fd1498Szrj 	  fprintf (sched_dump,
6544*38fd1498Szrj 		   ";;\t\tReady list on entry: %d insns:  ", ready.n_ready);
6545*38fd1498Szrj 	  debug_ready_list (&ready);
6546*38fd1498Szrj 	  fprintf (sched_dump,
6547*38fd1498Szrj 		   ";;\t\t before reload => truncated to %d insns\n", i);
6548*38fd1498Szrj 	}
6549*38fd1498Szrj 
6550*38fd1498Szrj       /* Delay all insns past it for 1 cycle.  If debug counter is
6551*38fd1498Szrj 	 activated make an exception for the insn right after
6552*38fd1498Szrj 	 nonscheduled_insns_begin.  */
6553*38fd1498Szrj       {
6554*38fd1498Szrj 	rtx_insn *skip_insn;
6555*38fd1498Szrj 
6556*38fd1498Szrj 	if (dbg_cnt (sched_insn) == false)
6557*38fd1498Szrj 	  skip_insn = first_nonscheduled_insn ();
6558*38fd1498Szrj 	else
6559*38fd1498Szrj 	  skip_insn = NULL;
6560*38fd1498Szrj 
6561*38fd1498Szrj 	while (i < ready.n_ready)
6562*38fd1498Szrj 	  {
6563*38fd1498Szrj 	    rtx_insn *insn;
6564*38fd1498Szrj 
6565*38fd1498Szrj 	    insn = ready_remove (&ready, i);
6566*38fd1498Szrj 
6567*38fd1498Szrj 	    if (insn != skip_insn)
6568*38fd1498Szrj 	      queue_insn (insn, 1, "list truncated");
6569*38fd1498Szrj 	  }
6570*38fd1498Szrj 	if (skip_insn)
6571*38fd1498Szrj 	  ready_add (&ready, skip_insn, true);
6572*38fd1498Szrj       }
6573*38fd1498Szrj     }
6574*38fd1498Szrj 
6575*38fd1498Szrj   /* Now we can restore basic block notes and maintain precise cfg.  */
6576*38fd1498Szrj   restore_bb_notes (*target_bb);
6577*38fd1498Szrj 
6578*38fd1498Szrj   last_clock_var = -1;
6579*38fd1498Szrj 
6580*38fd1498Szrj   advance = 0;
6581*38fd1498Szrj 
6582*38fd1498Szrj   gcc_assert (scheduled_insns.length () == 0);
6583*38fd1498Szrj   sort_p = TRUE;
6584*38fd1498Szrj   must_backtrack = false;
6585*38fd1498Szrj   modulo_insns_scheduled = 0;
6586*38fd1498Szrj 
6587*38fd1498Szrj   ls.modulo_epilogue = false;
6588*38fd1498Szrj   ls.first_cycle_insn_p = true;
6589*38fd1498Szrj 
6590*38fd1498Szrj   /* Loop until all the insns in BB are scheduled.  */
6591*38fd1498Szrj   while ((*current_sched_info->schedule_more_p) ())
6592*38fd1498Szrj     {
6593*38fd1498Szrj       perform_replacements_new_cycle ();
6594*38fd1498Szrj       do
6595*38fd1498Szrj 	{
6596*38fd1498Szrj 	  start_clock_var = clock_var;
6597*38fd1498Szrj 
6598*38fd1498Szrj 	  clock_var++;
6599*38fd1498Szrj 
6600*38fd1498Szrj 	  advance_one_cycle ();
6601*38fd1498Szrj 
6602*38fd1498Szrj 	  /* Add to the ready list all pending insns that can be issued now.
6603*38fd1498Szrj 	     If there are no ready insns, increment clock until one
6604*38fd1498Szrj 	     is ready and add all pending insns at that point to the ready
6605*38fd1498Szrj 	     list.  */
6606*38fd1498Szrj 	  queue_to_ready (&ready);
6607*38fd1498Szrj 
6608*38fd1498Szrj 	  gcc_assert (ready.n_ready);
6609*38fd1498Szrj 
6610*38fd1498Szrj 	  if (sched_verbose >= 2)
6611*38fd1498Szrj 	    {
6612*38fd1498Szrj 	      fprintf (sched_dump, ";;\t\tReady list after queue_to_ready:");
6613*38fd1498Szrj 	      debug_ready_list (&ready);
6614*38fd1498Szrj 	    }
6615*38fd1498Szrj 	  advance -= clock_var - start_clock_var;
6616*38fd1498Szrj 	}
6617*38fd1498Szrj       while (advance > 0);
6618*38fd1498Szrj 
6619*38fd1498Szrj       if (ls.modulo_epilogue)
6620*38fd1498Szrj 	{
6621*38fd1498Szrj 	  int stage = clock_var / modulo_ii;
6622*38fd1498Szrj 	  if (stage > modulo_last_stage * 2 + 2)
6623*38fd1498Szrj 	    {
6624*38fd1498Szrj 	      if (sched_verbose >= 2)
6625*38fd1498Szrj 		fprintf (sched_dump,
6626*38fd1498Szrj 			 ";;\t\tmodulo scheduled succeeded at II %d\n",
6627*38fd1498Szrj 			 modulo_ii);
6628*38fd1498Szrj 	      success = true;
6629*38fd1498Szrj 	      goto end_schedule;
6630*38fd1498Szrj 	    }
6631*38fd1498Szrj 	}
6632*38fd1498Szrj       else if (modulo_ii > 0)
6633*38fd1498Szrj 	{
6634*38fd1498Szrj 	  int stage = clock_var / modulo_ii;
6635*38fd1498Szrj 	  if (stage > modulo_max_stages)
6636*38fd1498Szrj 	    {
6637*38fd1498Szrj 	      if (sched_verbose >= 2)
6638*38fd1498Szrj 		fprintf (sched_dump,
6639*38fd1498Szrj 			 ";;\t\tfailing schedule due to excessive stages\n");
6640*38fd1498Szrj 	      goto end_schedule;
6641*38fd1498Szrj 	    }
6642*38fd1498Szrj 	  if (modulo_n_insns == modulo_insns_scheduled
6643*38fd1498Szrj 	      && stage > modulo_last_stage)
6644*38fd1498Szrj 	    {
6645*38fd1498Szrj 	      if (sched_verbose >= 2)
6646*38fd1498Szrj 		fprintf (sched_dump,
6647*38fd1498Szrj 			 ";;\t\tfound kernel after %d stages, II %d\n",
6648*38fd1498Szrj 			 stage, modulo_ii);
6649*38fd1498Szrj 	      ls.modulo_epilogue = true;
6650*38fd1498Szrj 	    }
6651*38fd1498Szrj 	}
6652*38fd1498Szrj 
6653*38fd1498Szrj       prune_ready_list (temp_state, true, false, ls.modulo_epilogue);
6654*38fd1498Szrj       if (ready.n_ready == 0)
6655*38fd1498Szrj 	continue;
6656*38fd1498Szrj       if (must_backtrack)
6657*38fd1498Szrj 	goto do_backtrack;
6658*38fd1498Szrj 
6659*38fd1498Szrj       ls.shadows_only_p = false;
6660*38fd1498Szrj       cycle_issued_insns = 0;
6661*38fd1498Szrj       ls.can_issue_more = issue_rate;
6662*38fd1498Szrj       for (;;)
6663*38fd1498Szrj 	{
6664*38fd1498Szrj 	  rtx_insn *insn;
6665*38fd1498Szrj 	  int cost;
6666*38fd1498Szrj 	  bool asm_p;
6667*38fd1498Szrj 
6668*38fd1498Szrj 	  if (sort_p && ready.n_ready > 0)
6669*38fd1498Szrj 	    {
6670*38fd1498Szrj 	      /* Sort the ready list based on priority.  This must be
6671*38fd1498Szrj 		 done every iteration through the loop, as schedule_insn
6672*38fd1498Szrj 		 may have readied additional insns that will not be
6673*38fd1498Szrj 		 sorted correctly.  */
6674*38fd1498Szrj 	      ready_sort (&ready);
6675*38fd1498Szrj 
6676*38fd1498Szrj 	      if (sched_verbose >= 2)
6677*38fd1498Szrj 		{
6678*38fd1498Szrj 		  fprintf (sched_dump,
6679*38fd1498Szrj 			   ";;\t\tReady list after ready_sort:    ");
6680*38fd1498Szrj 		  debug_ready_list (&ready);
6681*38fd1498Szrj 		}
6682*38fd1498Szrj 	    }
6683*38fd1498Szrj 
6684*38fd1498Szrj 	  /* We don't want md sched reorder to even see debug isns, so put
6685*38fd1498Szrj 	     them out right away.  */
6686*38fd1498Szrj 	  if (ready.n_ready && DEBUG_INSN_P (ready_element (&ready, 0))
6687*38fd1498Szrj 	      && (*current_sched_info->schedule_more_p) ())
6688*38fd1498Szrj 	    {
6689*38fd1498Szrj 	      while (ready.n_ready && DEBUG_INSN_P (ready_element (&ready, 0)))
6690*38fd1498Szrj 		{
6691*38fd1498Szrj 		  rtx_insn *insn = ready_remove_first (&ready);
6692*38fd1498Szrj 		  gcc_assert (DEBUG_INSN_P (insn));
6693*38fd1498Szrj 		  (*current_sched_info->begin_schedule_ready) (insn);
6694*38fd1498Szrj 		  scheduled_insns.safe_push (insn);
6695*38fd1498Szrj 		  last_scheduled_insn = insn;
6696*38fd1498Szrj 		  advance = schedule_insn (insn);
6697*38fd1498Szrj 		  gcc_assert (advance == 0);
6698*38fd1498Szrj 		  if (ready.n_ready > 0)
6699*38fd1498Szrj 		    ready_sort (&ready);
6700*38fd1498Szrj 		}
6701*38fd1498Szrj 	    }
6702*38fd1498Szrj 
6703*38fd1498Szrj 	  if (ls.first_cycle_insn_p && !ready.n_ready)
6704*38fd1498Szrj 	    break;
6705*38fd1498Szrj 
6706*38fd1498Szrj 	resume_after_backtrack:
6707*38fd1498Szrj 	  /* Allow the target to reorder the list, typically for
6708*38fd1498Szrj 	     better instruction bundling.  */
6709*38fd1498Szrj 	  if (sort_p
6710*38fd1498Szrj 	      && (ready.n_ready == 0
6711*38fd1498Szrj 		  || !SCHED_GROUP_P (ready_element (&ready, 0))))
6712*38fd1498Szrj 	    {
6713*38fd1498Szrj 	      if (ls.first_cycle_insn_p && targetm.sched.reorder)
6714*38fd1498Szrj 		ls.can_issue_more
6715*38fd1498Szrj 		  = targetm.sched.reorder (sched_dump, sched_verbose,
6716*38fd1498Szrj 					   ready_lastpos (&ready),
6717*38fd1498Szrj 					   &ready.n_ready, clock_var);
6718*38fd1498Szrj 	      else if (!ls.first_cycle_insn_p && targetm.sched.reorder2)
6719*38fd1498Szrj 		ls.can_issue_more
6720*38fd1498Szrj 		  = targetm.sched.reorder2 (sched_dump, sched_verbose,
6721*38fd1498Szrj 					    ready.n_ready
6722*38fd1498Szrj 					    ? ready_lastpos (&ready) : NULL,
6723*38fd1498Szrj 					    &ready.n_ready, clock_var);
6724*38fd1498Szrj 	    }
6725*38fd1498Szrj 
6726*38fd1498Szrj 	restart_choose_ready:
6727*38fd1498Szrj 	  if (sched_verbose >= 2)
6728*38fd1498Szrj 	    {
6729*38fd1498Szrj 	      fprintf (sched_dump, ";;\tReady list (t = %3d):  ",
6730*38fd1498Szrj 		       clock_var);
6731*38fd1498Szrj 	      debug_ready_list (&ready);
6732*38fd1498Szrj 	      if (sched_pressure == SCHED_PRESSURE_WEIGHTED)
6733*38fd1498Szrj 		print_curr_reg_pressure ();
6734*38fd1498Szrj 	    }
6735*38fd1498Szrj 
6736*38fd1498Szrj 	  if (ready.n_ready == 0
6737*38fd1498Szrj 	      && ls.can_issue_more
6738*38fd1498Szrj 	      && reload_completed)
6739*38fd1498Szrj 	    {
6740*38fd1498Szrj 	      /* Allow scheduling insns directly from the queue in case
6741*38fd1498Szrj 		 there's nothing better to do (ready list is empty) but
6742*38fd1498Szrj 		 there are still vacant dispatch slots in the current cycle.  */
6743*38fd1498Szrj 	      if (sched_verbose >= 6)
6744*38fd1498Szrj 		fprintf (sched_dump,";;\t\tSecond chance\n");
6745*38fd1498Szrj 	      memcpy (temp_state, curr_state, dfa_state_size);
6746*38fd1498Szrj 	      if (early_queue_to_ready (temp_state, &ready))
6747*38fd1498Szrj 		ready_sort (&ready);
6748*38fd1498Szrj 	    }
6749*38fd1498Szrj 
6750*38fd1498Szrj 	  if (ready.n_ready == 0
6751*38fd1498Szrj 	      || !ls.can_issue_more
6752*38fd1498Szrj 	      || state_dead_lock_p (curr_state)
6753*38fd1498Szrj 	      || !(*current_sched_info->schedule_more_p) ())
6754*38fd1498Szrj 	    break;
6755*38fd1498Szrj 
6756*38fd1498Szrj 	  /* Select and remove the insn from the ready list.  */
6757*38fd1498Szrj 	  if (sort_p)
6758*38fd1498Szrj 	    {
6759*38fd1498Szrj 	      int res;
6760*38fd1498Szrj 
6761*38fd1498Szrj 	      insn = NULL;
6762*38fd1498Szrj 	      res = choose_ready (&ready, ls.first_cycle_insn_p, &insn);
6763*38fd1498Szrj 
6764*38fd1498Szrj 	      if (res < 0)
6765*38fd1498Szrj 		/* Finish cycle.  */
6766*38fd1498Szrj 		break;
6767*38fd1498Szrj 	      if (res > 0)
6768*38fd1498Szrj 		goto restart_choose_ready;
6769*38fd1498Szrj 
6770*38fd1498Szrj 	      gcc_assert (insn != NULL_RTX);
6771*38fd1498Szrj 	    }
6772*38fd1498Szrj 	  else
6773*38fd1498Szrj 	    insn = ready_remove_first (&ready);
6774*38fd1498Szrj 
6775*38fd1498Szrj 	  if (sched_pressure != SCHED_PRESSURE_NONE
6776*38fd1498Szrj 	      && INSN_TICK (insn) > clock_var)
6777*38fd1498Szrj 	    {
6778*38fd1498Szrj 	      ready_add (&ready, insn, true);
6779*38fd1498Szrj 	      advance = 1;
6780*38fd1498Szrj 	      break;
6781*38fd1498Szrj 	    }
6782*38fd1498Szrj 
6783*38fd1498Szrj 	  if (targetm.sched.dfa_new_cycle
6784*38fd1498Szrj 	      && targetm.sched.dfa_new_cycle (sched_dump, sched_verbose,
6785*38fd1498Szrj 					      insn, last_clock_var,
6786*38fd1498Szrj 					      clock_var, &sort_p))
6787*38fd1498Szrj 	    /* SORT_P is used by the target to override sorting
6788*38fd1498Szrj 	       of the ready list.  This is needed when the target
6789*38fd1498Szrj 	       has modified its internal structures expecting that
6790*38fd1498Szrj 	       the insn will be issued next.  As we need the insn
6791*38fd1498Szrj 	       to have the highest priority (so it will be returned by
6792*38fd1498Szrj 	       the ready_remove_first call above), we invoke
6793*38fd1498Szrj 	       ready_add (&ready, insn, true).
6794*38fd1498Szrj 	       But, still, there is one issue: INSN can be later
6795*38fd1498Szrj 	       discarded by scheduler's front end through
6796*38fd1498Szrj 	       current_sched_info->can_schedule_ready_p, hence, won't
6797*38fd1498Szrj 	       be issued next.  */
6798*38fd1498Szrj 	    {
6799*38fd1498Szrj 	      ready_add (&ready, insn, true);
6800*38fd1498Szrj               break;
6801*38fd1498Szrj 	    }
6802*38fd1498Szrj 
6803*38fd1498Szrj 	  sort_p = TRUE;
6804*38fd1498Szrj 
6805*38fd1498Szrj 	  if (current_sched_info->can_schedule_ready_p
6806*38fd1498Szrj 	      && ! (*current_sched_info->can_schedule_ready_p) (insn))
6807*38fd1498Szrj 	    /* We normally get here only if we don't want to move
6808*38fd1498Szrj 	       insn from the split block.  */
6809*38fd1498Szrj 	    {
6810*38fd1498Szrj 	      TODO_SPEC (insn) = DEP_POSTPONED;
6811*38fd1498Szrj 	      goto restart_choose_ready;
6812*38fd1498Szrj 	    }
6813*38fd1498Szrj 
6814*38fd1498Szrj 	  if (delay_htab)
6815*38fd1498Szrj 	    {
6816*38fd1498Szrj 	      /* If this insn is the first part of a delay-slot pair, record a
6817*38fd1498Szrj 		 backtrack point.  */
6818*38fd1498Szrj 	      struct delay_pair *delay_entry;
6819*38fd1498Szrj 	      delay_entry
6820*38fd1498Szrj 		= delay_htab->find_with_hash (insn, htab_hash_pointer (insn));
6821*38fd1498Szrj 	      if (delay_entry)
6822*38fd1498Szrj 		{
6823*38fd1498Szrj 		  save_backtrack_point (delay_entry, ls);
6824*38fd1498Szrj 		  if (sched_verbose >= 2)
6825*38fd1498Szrj 		    fprintf (sched_dump, ";;\t\tsaving backtrack point\n");
6826*38fd1498Szrj 		}
6827*38fd1498Szrj 	    }
6828*38fd1498Szrj 
6829*38fd1498Szrj 	  /* DECISION is made.  */
6830*38fd1498Szrj 
6831*38fd1498Szrj 	  if (modulo_ii > 0 && INSN_UID (insn) < modulo_iter0_max_uid)
6832*38fd1498Szrj 	    {
6833*38fd1498Szrj 	      modulo_insns_scheduled++;
6834*38fd1498Szrj 	      modulo_last_stage = clock_var / modulo_ii;
6835*38fd1498Szrj 	    }
6836*38fd1498Szrj           if (TODO_SPEC (insn) & SPECULATIVE)
6837*38fd1498Szrj             generate_recovery_code (insn);
6838*38fd1498Szrj 
6839*38fd1498Szrj 	  if (targetm.sched.dispatch (NULL, IS_DISPATCH_ON))
6840*38fd1498Szrj 	    targetm.sched.dispatch_do (insn, ADD_TO_DISPATCH_WINDOW);
6841*38fd1498Szrj 
6842*38fd1498Szrj 	  /* Update counters, etc in the scheduler's front end.  */
6843*38fd1498Szrj 	  (*current_sched_info->begin_schedule_ready) (insn);
6844*38fd1498Szrj 	  scheduled_insns.safe_push (insn);
6845*38fd1498Szrj 	  gcc_assert (NONDEBUG_INSN_P (insn));
6846*38fd1498Szrj 	  last_nondebug_scheduled_insn = last_scheduled_insn = insn;
6847*38fd1498Szrj 
6848*38fd1498Szrj 	  if (recog_memoized (insn) >= 0)
6849*38fd1498Szrj 	    {
6850*38fd1498Szrj 	      memcpy (temp_state, curr_state, dfa_state_size);
6851*38fd1498Szrj 	      cost = state_transition (curr_state, insn);
6852*38fd1498Szrj 	      if (sched_pressure != SCHED_PRESSURE_WEIGHTED && !sched_fusion)
6853*38fd1498Szrj 		gcc_assert (cost < 0);
6854*38fd1498Szrj 	      if (memcmp (temp_state, curr_state, dfa_state_size) != 0)
6855*38fd1498Szrj 		cycle_issued_insns++;
6856*38fd1498Szrj 	      asm_p = false;
6857*38fd1498Szrj 	    }
6858*38fd1498Szrj 	  else
6859*38fd1498Szrj 	    asm_p = (GET_CODE (PATTERN (insn)) == ASM_INPUT
6860*38fd1498Szrj 		     || asm_noperands (PATTERN (insn)) >= 0);
6861*38fd1498Szrj 
6862*38fd1498Szrj 	  if (targetm.sched.variable_issue)
6863*38fd1498Szrj 	    ls.can_issue_more =
6864*38fd1498Szrj 	      targetm.sched.variable_issue (sched_dump, sched_verbose,
6865*38fd1498Szrj 					    insn, ls.can_issue_more);
6866*38fd1498Szrj 	  /* A naked CLOBBER or USE generates no instruction, so do
6867*38fd1498Szrj 	     not count them against the issue rate.  */
6868*38fd1498Szrj 	  else if (GET_CODE (PATTERN (insn)) != USE
6869*38fd1498Szrj 		   && GET_CODE (PATTERN (insn)) != CLOBBER)
6870*38fd1498Szrj 	    ls.can_issue_more--;
6871*38fd1498Szrj 	  advance = schedule_insn (insn);
6872*38fd1498Szrj 
6873*38fd1498Szrj 	  if (SHADOW_P (insn))
6874*38fd1498Szrj 	    ls.shadows_only_p = true;
6875*38fd1498Szrj 
6876*38fd1498Szrj 	  /* After issuing an asm insn we should start a new cycle.  */
6877*38fd1498Szrj 	  if (advance == 0 && asm_p)
6878*38fd1498Szrj 	    advance = 1;
6879*38fd1498Szrj 
6880*38fd1498Szrj 	  if (must_backtrack)
6881*38fd1498Szrj 	    break;
6882*38fd1498Szrj 
6883*38fd1498Szrj 	  if (advance != 0)
6884*38fd1498Szrj 	    break;
6885*38fd1498Szrj 
6886*38fd1498Szrj 	  ls.first_cycle_insn_p = false;
6887*38fd1498Szrj 	  if (ready.n_ready > 0)
6888*38fd1498Szrj 	    prune_ready_list (temp_state, false, ls.shadows_only_p,
6889*38fd1498Szrj 			      ls.modulo_epilogue);
6890*38fd1498Szrj 	}
6891*38fd1498Szrj 
6892*38fd1498Szrj     do_backtrack:
6893*38fd1498Szrj       if (!must_backtrack)
6894*38fd1498Szrj 	for (i = 0; i < ready.n_ready; i++)
6895*38fd1498Szrj 	  {
6896*38fd1498Szrj 	    rtx_insn *insn = ready_element (&ready, i);
6897*38fd1498Szrj 	    if (INSN_EXACT_TICK (insn) == clock_var)
6898*38fd1498Szrj 	      {
6899*38fd1498Szrj 		must_backtrack = true;
6900*38fd1498Szrj 		clock_var++;
6901*38fd1498Szrj 		break;
6902*38fd1498Szrj 	      }
6903*38fd1498Szrj 	  }
6904*38fd1498Szrj       if (must_backtrack && modulo_ii > 0)
6905*38fd1498Szrj 	{
6906*38fd1498Szrj 	  if (modulo_backtracks_left == 0)
6907*38fd1498Szrj 	    goto end_schedule;
6908*38fd1498Szrj 	  modulo_backtracks_left--;
6909*38fd1498Szrj 	}
6910*38fd1498Szrj       while (must_backtrack)
6911*38fd1498Szrj 	{
6912*38fd1498Szrj 	  struct haifa_saved_data *failed;
6913*38fd1498Szrj 	  rtx_insn *failed_insn;
6914*38fd1498Szrj 
6915*38fd1498Szrj 	  must_backtrack = false;
6916*38fd1498Szrj 	  failed = verify_shadows ();
6917*38fd1498Szrj 	  gcc_assert (failed);
6918*38fd1498Szrj 
6919*38fd1498Szrj 	  failed_insn = failed->delay_pair->i1;
6920*38fd1498Szrj 	  /* Clear these queues.  */
6921*38fd1498Szrj 	  perform_replacements_new_cycle ();
6922*38fd1498Szrj 	  toggle_cancelled_flags (false);
6923*38fd1498Szrj 	  unschedule_insns_until (failed_insn);
6924*38fd1498Szrj 	  while (failed != backtrack_queue)
6925*38fd1498Szrj 	    free_topmost_backtrack_point (true);
6926*38fd1498Szrj 	  restore_last_backtrack_point (&ls);
6927*38fd1498Szrj 	  if (sched_verbose >= 2)
6928*38fd1498Szrj 	    fprintf (sched_dump, ";;\t\trewind to cycle %d\n", clock_var);
6929*38fd1498Szrj 	  /* Delay by at least a cycle.  This could cause additional
6930*38fd1498Szrj 	     backtracking.  */
6931*38fd1498Szrj 	  queue_insn (failed_insn, 1, "backtracked");
6932*38fd1498Szrj 	  advance = 0;
6933*38fd1498Szrj 	  if (must_backtrack)
6934*38fd1498Szrj 	    continue;
6935*38fd1498Szrj 	  if (ready.n_ready > 0)
6936*38fd1498Szrj 	    goto resume_after_backtrack;
6937*38fd1498Szrj 	  else
6938*38fd1498Szrj 	    {
6939*38fd1498Szrj 	      if (clock_var == 0 && ls.first_cycle_insn_p)
6940*38fd1498Szrj 		goto end_schedule;
6941*38fd1498Szrj 	      advance = 1;
6942*38fd1498Szrj 	      break;
6943*38fd1498Szrj 	    }
6944*38fd1498Szrj 	}
6945*38fd1498Szrj       ls.first_cycle_insn_p = true;
6946*38fd1498Szrj     }
6947*38fd1498Szrj   if (ls.modulo_epilogue)
6948*38fd1498Szrj     success = true;
6949*38fd1498Szrj  end_schedule:
6950*38fd1498Szrj   if (!ls.first_cycle_insn_p || advance)
6951*38fd1498Szrj     advance_one_cycle ();
6952*38fd1498Szrj   perform_replacements_new_cycle ();
6953*38fd1498Szrj   if (modulo_ii > 0)
6954*38fd1498Szrj     {
6955*38fd1498Szrj       /* Once again, debug insn suckiness: they can be on the ready list
6956*38fd1498Szrj 	 even if they have unresolved dependencies.  To make our view
6957*38fd1498Szrj 	 of the world consistent, remove such "ready" insns.  */
6958*38fd1498Szrj     restart_debug_insn_loop:
6959*38fd1498Szrj       for (i = ready.n_ready - 1; i >= 0; i--)
6960*38fd1498Szrj 	{
6961*38fd1498Szrj 	  rtx_insn *x;
6962*38fd1498Szrj 
6963*38fd1498Szrj 	  x = ready_element (&ready, i);
6964*38fd1498Szrj 	  if (DEPS_LIST_FIRST (INSN_HARD_BACK_DEPS (x)) != NULL
6965*38fd1498Szrj 	      || DEPS_LIST_FIRST (INSN_SPEC_BACK_DEPS (x)) != NULL)
6966*38fd1498Szrj 	    {
6967*38fd1498Szrj 	      ready_remove (&ready, i);
6968*38fd1498Szrj 	      goto restart_debug_insn_loop;
6969*38fd1498Szrj 	    }
6970*38fd1498Szrj 	}
6971*38fd1498Szrj       for (i = ready.n_ready - 1; i >= 0; i--)
6972*38fd1498Szrj 	{
6973*38fd1498Szrj 	  rtx_insn *x;
6974*38fd1498Szrj 
6975*38fd1498Szrj 	  x = ready_element (&ready, i);
6976*38fd1498Szrj 	  resolve_dependencies (x);
6977*38fd1498Szrj 	}
6978*38fd1498Szrj       for (i = 0; i <= max_insn_queue_index; i++)
6979*38fd1498Szrj 	{
6980*38fd1498Szrj 	  rtx_insn_list *link;
6981*38fd1498Szrj 	  while ((link = insn_queue[i]) != NULL)
6982*38fd1498Szrj 	    {
6983*38fd1498Szrj 	      rtx_insn *x = link->insn ();
6984*38fd1498Szrj 	      insn_queue[i] = link->next ();
6985*38fd1498Szrj 	      QUEUE_INDEX (x) = QUEUE_NOWHERE;
6986*38fd1498Szrj 	      free_INSN_LIST_node (link);
6987*38fd1498Szrj 	      resolve_dependencies (x);
6988*38fd1498Szrj 	    }
6989*38fd1498Szrj 	}
6990*38fd1498Szrj     }
6991*38fd1498Szrj 
6992*38fd1498Szrj   if (!success)
6993*38fd1498Szrj     undo_all_replacements ();
6994*38fd1498Szrj 
6995*38fd1498Szrj   /* Debug info.  */
6996*38fd1498Szrj   if (sched_verbose)
6997*38fd1498Szrj     {
6998*38fd1498Szrj       fprintf (sched_dump, ";;\tReady list (final):  ");
6999*38fd1498Szrj       debug_ready_list (&ready);
7000*38fd1498Szrj     }
7001*38fd1498Szrj 
7002*38fd1498Szrj   if (modulo_ii == 0 && current_sched_info->queue_must_finish_empty)
7003*38fd1498Szrj     /* Sanity check -- queue must be empty now.  Meaningless if region has
7004*38fd1498Szrj        multiple bbs.  */
7005*38fd1498Szrj     gcc_assert (!q_size && !ready.n_ready && !ready.n_debug);
7006*38fd1498Szrj   else if (modulo_ii == 0)
7007*38fd1498Szrj     {
7008*38fd1498Szrj       /* We must maintain QUEUE_INDEX between blocks in region.  */
7009*38fd1498Szrj       for (i = ready.n_ready - 1; i >= 0; i--)
7010*38fd1498Szrj 	{
7011*38fd1498Szrj 	  rtx_insn *x;
7012*38fd1498Szrj 
7013*38fd1498Szrj 	  x = ready_element (&ready, i);
7014*38fd1498Szrj 	  QUEUE_INDEX (x) = QUEUE_NOWHERE;
7015*38fd1498Szrj 	  TODO_SPEC (x) = HARD_DEP;
7016*38fd1498Szrj 	}
7017*38fd1498Szrj 
7018*38fd1498Szrj       if (q_size)
7019*38fd1498Szrj 	for (i = 0; i <= max_insn_queue_index; i++)
7020*38fd1498Szrj 	  {
7021*38fd1498Szrj 	    rtx_insn_list *link;
7022*38fd1498Szrj 	    for (link = insn_queue[i]; link; link = link->next ())
7023*38fd1498Szrj 	      {
7024*38fd1498Szrj 		rtx_insn *x;
7025*38fd1498Szrj 
7026*38fd1498Szrj 		x = link->insn ();
7027*38fd1498Szrj 		QUEUE_INDEX (x) = QUEUE_NOWHERE;
7028*38fd1498Szrj 		TODO_SPEC (x) = HARD_DEP;
7029*38fd1498Szrj 	      }
7030*38fd1498Szrj 	    free_INSN_LIST_list (&insn_queue[i]);
7031*38fd1498Szrj 	  }
7032*38fd1498Szrj     }
7033*38fd1498Szrj 
7034*38fd1498Szrj   if (sched_pressure == SCHED_PRESSURE_MODEL)
7035*38fd1498Szrj     model_end_schedule ();
7036*38fd1498Szrj 
7037*38fd1498Szrj   if (success)
7038*38fd1498Szrj     {
7039*38fd1498Szrj       commit_schedule (prev_head, tail, target_bb);
7040*38fd1498Szrj       if (sched_verbose)
7041*38fd1498Szrj 	fprintf (sched_dump, ";;   total time = %d\n", clock_var);
7042*38fd1498Szrj     }
7043*38fd1498Szrj   else
7044*38fd1498Szrj     last_scheduled_insn = tail;
7045*38fd1498Szrj 
7046*38fd1498Szrj   scheduled_insns.truncate (0);
7047*38fd1498Szrj 
7048*38fd1498Szrj   if (!current_sched_info->queue_must_finish_empty
7049*38fd1498Szrj       || haifa_recovery_bb_recently_added_p)
7050*38fd1498Szrj     {
7051*38fd1498Szrj       /* INSN_TICK (minimum clock tick at which the insn becomes
7052*38fd1498Szrj          ready) may be not correct for the insn in the subsequent
7053*38fd1498Szrj          blocks of the region.  We should use a correct value of
7054*38fd1498Szrj          `clock_var' or modify INSN_TICK.  It is better to keep
7055*38fd1498Szrj          clock_var value equal to 0 at the start of a basic block.
7056*38fd1498Szrj          Therefore we modify INSN_TICK here.  */
7057*38fd1498Szrj       fix_inter_tick (NEXT_INSN (prev_head), last_scheduled_insn);
7058*38fd1498Szrj     }
7059*38fd1498Szrj 
7060*38fd1498Szrj   if (targetm.sched.finish)
7061*38fd1498Szrj     {
7062*38fd1498Szrj       targetm.sched.finish (sched_dump, sched_verbose);
7063*38fd1498Szrj       /* Target might have added some instructions to the scheduled block
7064*38fd1498Szrj 	 in its md_finish () hook.  These new insns don't have any data
7065*38fd1498Szrj 	 initialized and to identify them we extend h_i_d so that they'll
7066*38fd1498Szrj 	 get zero luids.  */
7067*38fd1498Szrj       sched_extend_luids ();
7068*38fd1498Szrj     }
7069*38fd1498Szrj 
7070*38fd1498Szrj   /* Update head/tail boundaries.  */
7071*38fd1498Szrj   head = NEXT_INSN (prev_head);
7072*38fd1498Szrj   tail = last_scheduled_insn;
7073*38fd1498Szrj 
7074*38fd1498Szrj   if (sched_verbose)
7075*38fd1498Szrj     {
7076*38fd1498Szrj       fprintf (sched_dump, ";;   new head = %d\n;;   new tail = %d\n",
7077*38fd1498Szrj 	       INSN_UID (head), INSN_UID (tail));
7078*38fd1498Szrj 
7079*38fd1498Szrj       if (sched_verbose >= 2)
7080*38fd1498Szrj 	{
7081*38fd1498Szrj 	  dump_insn_stream (head, tail);
7082*38fd1498Szrj 	  print_rank_for_schedule_stats (";; TOTAL ", &rank_for_schedule_stats,
7083*38fd1498Szrj 					 NULL);
7084*38fd1498Szrj 	}
7085*38fd1498Szrj 
7086*38fd1498Szrj       fprintf (sched_dump, "\n");
7087*38fd1498Szrj     }
7088*38fd1498Szrj 
7089*38fd1498Szrj   head = restore_other_notes (head, NULL);
7090*38fd1498Szrj 
7091*38fd1498Szrj   current_sched_info->head = head;
7092*38fd1498Szrj   current_sched_info->tail = tail;
7093*38fd1498Szrj 
7094*38fd1498Szrj   free_backtrack_queue ();
7095*38fd1498Szrj 
7096*38fd1498Szrj   return success;
7097*38fd1498Szrj }
7098*38fd1498Szrj 
7099*38fd1498Szrj /* Set_priorities: compute priority of each insn in the block.  */
7100*38fd1498Szrj 
7101*38fd1498Szrj int
set_priorities(rtx_insn * head,rtx_insn * tail)7102*38fd1498Szrj set_priorities (rtx_insn *head, rtx_insn *tail)
7103*38fd1498Szrj {
7104*38fd1498Szrj   rtx_insn *insn;
7105*38fd1498Szrj   int n_insn;
7106*38fd1498Szrj   int sched_max_insns_priority =
7107*38fd1498Szrj 	current_sched_info->sched_max_insns_priority;
7108*38fd1498Szrj   rtx_insn *prev_head;
7109*38fd1498Szrj 
7110*38fd1498Szrj   if (head == tail && ! INSN_P (head))
7111*38fd1498Szrj     gcc_unreachable ();
7112*38fd1498Szrj 
7113*38fd1498Szrj   n_insn = 0;
7114*38fd1498Szrj 
7115*38fd1498Szrj   prev_head = PREV_INSN (head);
7116*38fd1498Szrj   for (insn = tail; insn != prev_head; insn = PREV_INSN (insn))
7117*38fd1498Szrj     {
7118*38fd1498Szrj       if (!INSN_P (insn))
7119*38fd1498Szrj 	continue;
7120*38fd1498Szrj 
7121*38fd1498Szrj       n_insn++;
7122*38fd1498Szrj       (void) priority (insn);
7123*38fd1498Szrj 
7124*38fd1498Szrj       gcc_assert (INSN_PRIORITY_KNOWN (insn));
7125*38fd1498Szrj 
7126*38fd1498Szrj       sched_max_insns_priority = MAX (sched_max_insns_priority,
7127*38fd1498Szrj 				      INSN_PRIORITY (insn));
7128*38fd1498Szrj     }
7129*38fd1498Szrj 
7130*38fd1498Szrj   current_sched_info->sched_max_insns_priority = sched_max_insns_priority;
7131*38fd1498Szrj 
7132*38fd1498Szrj   return n_insn;
7133*38fd1498Szrj }
7134*38fd1498Szrj 
7135*38fd1498Szrj /* Set sched_dump and sched_verbose for the desired debugging output. */
7136*38fd1498Szrj void
setup_sched_dump(void)7137*38fd1498Szrj setup_sched_dump (void)
7138*38fd1498Szrj {
7139*38fd1498Szrj   sched_verbose = sched_verbose_param;
7140*38fd1498Szrj   sched_dump = dump_file;
7141*38fd1498Szrj   if (!dump_file)
7142*38fd1498Szrj     sched_verbose = 0;
7143*38fd1498Szrj }
7144*38fd1498Szrj 
7145*38fd1498Szrj /* Allocate data for register pressure sensitive scheduling.  */
7146*38fd1498Szrj static void
alloc_global_sched_pressure_data(void)7147*38fd1498Szrj alloc_global_sched_pressure_data (void)
7148*38fd1498Szrj {
7149*38fd1498Szrj   if (sched_pressure != SCHED_PRESSURE_NONE)
7150*38fd1498Szrj     {
7151*38fd1498Szrj       int i, max_regno = max_reg_num ();
7152*38fd1498Szrj 
7153*38fd1498Szrj       if (sched_dump != NULL)
7154*38fd1498Szrj 	/* We need info about pseudos for rtl dumps about pseudo
7155*38fd1498Szrj 	   classes and costs.  */
7156*38fd1498Szrj 	regstat_init_n_sets_and_refs ();
7157*38fd1498Szrj       ira_set_pseudo_classes (true, sched_verbose ? sched_dump : NULL);
7158*38fd1498Szrj       sched_regno_pressure_class
7159*38fd1498Szrj 	= (enum reg_class *) xmalloc (max_regno * sizeof (enum reg_class));
7160*38fd1498Szrj       for (i = 0; i < max_regno; i++)
7161*38fd1498Szrj 	sched_regno_pressure_class[i]
7162*38fd1498Szrj 	  = (i < FIRST_PSEUDO_REGISTER
7163*38fd1498Szrj 	     ? ira_pressure_class_translate[REGNO_REG_CLASS (i)]
7164*38fd1498Szrj 	     : ira_pressure_class_translate[reg_allocno_class (i)]);
7165*38fd1498Szrj       curr_reg_live = BITMAP_ALLOC (NULL);
7166*38fd1498Szrj       if (sched_pressure == SCHED_PRESSURE_WEIGHTED)
7167*38fd1498Szrj 	{
7168*38fd1498Szrj 	  saved_reg_live = BITMAP_ALLOC (NULL);
7169*38fd1498Szrj 	  region_ref_regs = BITMAP_ALLOC (NULL);
7170*38fd1498Szrj 	}
7171*38fd1498Szrj       if (sched_pressure == SCHED_PRESSURE_MODEL)
7172*38fd1498Szrj 	tmp_bitmap = BITMAP_ALLOC (NULL);
7173*38fd1498Szrj 
7174*38fd1498Szrj       /* Calculate number of CALL_SAVED_REGS and FIXED_REGS in register classes
7175*38fd1498Szrj 	 that we calculate register pressure for.  */
7176*38fd1498Szrj       for (int c = 0; c < ira_pressure_classes_num; ++c)
7177*38fd1498Szrj 	{
7178*38fd1498Szrj 	  enum reg_class cl = ira_pressure_classes[c];
7179*38fd1498Szrj 
7180*38fd1498Szrj 	  call_saved_regs_num[cl] = 0;
7181*38fd1498Szrj 	  fixed_regs_num[cl] = 0;
7182*38fd1498Szrj 
7183*38fd1498Szrj 	  for (int i = 0; i < ira_class_hard_regs_num[cl]; ++i)
7184*38fd1498Szrj 	    if (!call_used_regs[ira_class_hard_regs[cl][i]])
7185*38fd1498Szrj 	      ++call_saved_regs_num[cl];
7186*38fd1498Szrj 	    else if (fixed_regs[ira_class_hard_regs[cl][i]])
7187*38fd1498Szrj 	      ++fixed_regs_num[cl];
7188*38fd1498Szrj 	}
7189*38fd1498Szrj     }
7190*38fd1498Szrj }
7191*38fd1498Szrj 
7192*38fd1498Szrj /*  Free data for register pressure sensitive scheduling.  Also called
7193*38fd1498Szrj     from schedule_region when stopping sched-pressure early.  */
7194*38fd1498Szrj void
free_global_sched_pressure_data(void)7195*38fd1498Szrj free_global_sched_pressure_data (void)
7196*38fd1498Szrj {
7197*38fd1498Szrj   if (sched_pressure != SCHED_PRESSURE_NONE)
7198*38fd1498Szrj     {
7199*38fd1498Szrj       if (regstat_n_sets_and_refs != NULL)
7200*38fd1498Szrj 	regstat_free_n_sets_and_refs ();
7201*38fd1498Szrj       if (sched_pressure == SCHED_PRESSURE_WEIGHTED)
7202*38fd1498Szrj 	{
7203*38fd1498Szrj 	  BITMAP_FREE (region_ref_regs);
7204*38fd1498Szrj 	  BITMAP_FREE (saved_reg_live);
7205*38fd1498Szrj 	}
7206*38fd1498Szrj       if (sched_pressure == SCHED_PRESSURE_MODEL)
7207*38fd1498Szrj 	BITMAP_FREE (tmp_bitmap);
7208*38fd1498Szrj       BITMAP_FREE (curr_reg_live);
7209*38fd1498Szrj       free (sched_regno_pressure_class);
7210*38fd1498Szrj     }
7211*38fd1498Szrj }
7212*38fd1498Szrj 
7213*38fd1498Szrj /* Initialize some global state for the scheduler.  This function works
7214*38fd1498Szrj    with the common data shared between all the schedulers.  It is called
7215*38fd1498Szrj    from the scheduler specific initialization routine.  */
7216*38fd1498Szrj 
7217*38fd1498Szrj void
sched_init(void)7218*38fd1498Szrj sched_init (void)
7219*38fd1498Szrj {
7220*38fd1498Szrj   /* Disable speculative loads in their presence if cc0 defined.  */
7221*38fd1498Szrj   if (HAVE_cc0)
7222*38fd1498Szrj   flag_schedule_speculative_load = 0;
7223*38fd1498Szrj 
7224*38fd1498Szrj   if (targetm.sched.dispatch (NULL, IS_DISPATCH_ON))
7225*38fd1498Szrj     targetm.sched.dispatch_do (NULL, DISPATCH_INIT);
7226*38fd1498Szrj 
7227*38fd1498Szrj   if (live_range_shrinkage_p)
7228*38fd1498Szrj     sched_pressure = SCHED_PRESSURE_WEIGHTED;
7229*38fd1498Szrj   else if (flag_sched_pressure
7230*38fd1498Szrj 	   && !reload_completed
7231*38fd1498Szrj 	   && common_sched_info->sched_pass_id == SCHED_RGN_PASS)
7232*38fd1498Szrj     sched_pressure = ((enum sched_pressure_algorithm)
7233*38fd1498Szrj 		      PARAM_VALUE (PARAM_SCHED_PRESSURE_ALGORITHM));
7234*38fd1498Szrj   else
7235*38fd1498Szrj     sched_pressure = SCHED_PRESSURE_NONE;
7236*38fd1498Szrj 
7237*38fd1498Szrj   if (sched_pressure != SCHED_PRESSURE_NONE)
7238*38fd1498Szrj     ira_setup_eliminable_regset ();
7239*38fd1498Szrj 
7240*38fd1498Szrj   /* Initialize SPEC_INFO.  */
7241*38fd1498Szrj   if (targetm.sched.set_sched_flags)
7242*38fd1498Szrj     {
7243*38fd1498Szrj       spec_info = &spec_info_var;
7244*38fd1498Szrj       targetm.sched.set_sched_flags (spec_info);
7245*38fd1498Szrj 
7246*38fd1498Szrj       if (spec_info->mask != 0)
7247*38fd1498Szrj         {
7248*38fd1498Szrj           spec_info->data_weakness_cutoff =
7249*38fd1498Szrj             (PARAM_VALUE (PARAM_SCHED_SPEC_PROB_CUTOFF) * MAX_DEP_WEAK) / 100;
7250*38fd1498Szrj           spec_info->control_weakness_cutoff =
7251*38fd1498Szrj             (PARAM_VALUE (PARAM_SCHED_SPEC_PROB_CUTOFF)
7252*38fd1498Szrj              * REG_BR_PROB_BASE) / 100;
7253*38fd1498Szrj         }
7254*38fd1498Szrj       else
7255*38fd1498Szrj 	/* So we won't read anything accidentally.  */
7256*38fd1498Szrj 	spec_info = NULL;
7257*38fd1498Szrj 
7258*38fd1498Szrj     }
7259*38fd1498Szrj   else
7260*38fd1498Szrj     /* So we won't read anything accidentally.  */
7261*38fd1498Szrj     spec_info = 0;
7262*38fd1498Szrj 
7263*38fd1498Szrj   /* Initialize issue_rate.  */
7264*38fd1498Szrj   if (targetm.sched.issue_rate)
7265*38fd1498Szrj     issue_rate = targetm.sched.issue_rate ();
7266*38fd1498Szrj   else
7267*38fd1498Szrj     issue_rate = 1;
7268*38fd1498Szrj 
7269*38fd1498Szrj   if (targetm.sched.first_cycle_multipass_dfa_lookahead
7270*38fd1498Szrj       /* Don't use max_issue with reg_pressure scheduling.  Multipass
7271*38fd1498Szrj 	 scheduling and reg_pressure scheduling undo each other's decisions.  */
7272*38fd1498Szrj       && sched_pressure == SCHED_PRESSURE_NONE)
7273*38fd1498Szrj     dfa_lookahead = targetm.sched.first_cycle_multipass_dfa_lookahead ();
7274*38fd1498Szrj   else
7275*38fd1498Szrj     dfa_lookahead = 0;
7276*38fd1498Szrj 
7277*38fd1498Szrj   /* Set to "0" so that we recalculate.  */
7278*38fd1498Szrj   max_lookahead_tries = 0;
7279*38fd1498Szrj 
7280*38fd1498Szrj   if (targetm.sched.init_dfa_pre_cycle_insn)
7281*38fd1498Szrj     targetm.sched.init_dfa_pre_cycle_insn ();
7282*38fd1498Szrj 
7283*38fd1498Szrj   if (targetm.sched.init_dfa_post_cycle_insn)
7284*38fd1498Szrj     targetm.sched.init_dfa_post_cycle_insn ();
7285*38fd1498Szrj 
7286*38fd1498Szrj   dfa_start ();
7287*38fd1498Szrj   dfa_state_size = state_size ();
7288*38fd1498Szrj 
7289*38fd1498Szrj   init_alias_analysis ();
7290*38fd1498Szrj 
7291*38fd1498Szrj   if (!sched_no_dce)
7292*38fd1498Szrj     df_set_flags (DF_LR_RUN_DCE);
7293*38fd1498Szrj   df_note_add_problem ();
7294*38fd1498Szrj 
7295*38fd1498Szrj   /* More problems needed for interloop dep calculation in SMS.  */
7296*38fd1498Szrj   if (common_sched_info->sched_pass_id == SCHED_SMS_PASS)
7297*38fd1498Szrj     {
7298*38fd1498Szrj       df_rd_add_problem ();
7299*38fd1498Szrj       df_chain_add_problem (DF_DU_CHAIN + DF_UD_CHAIN);
7300*38fd1498Szrj     }
7301*38fd1498Szrj 
7302*38fd1498Szrj   df_analyze ();
7303*38fd1498Szrj 
7304*38fd1498Szrj   /* Do not run DCE after reload, as this can kill nops inserted
7305*38fd1498Szrj      by bundling.  */
7306*38fd1498Szrj   if (reload_completed)
7307*38fd1498Szrj     df_clear_flags (DF_LR_RUN_DCE);
7308*38fd1498Szrj 
7309*38fd1498Szrj   regstat_compute_calls_crossed ();
7310*38fd1498Szrj 
7311*38fd1498Szrj   if (targetm.sched.init_global)
7312*38fd1498Szrj     targetm.sched.init_global (sched_dump, sched_verbose, get_max_uid () + 1);
7313*38fd1498Szrj 
7314*38fd1498Szrj   alloc_global_sched_pressure_data ();
7315*38fd1498Szrj 
7316*38fd1498Szrj   curr_state = xmalloc (dfa_state_size);
7317*38fd1498Szrj }
7318*38fd1498Szrj 
7319*38fd1498Szrj static void haifa_init_only_bb (basic_block, basic_block);
7320*38fd1498Szrj 
7321*38fd1498Szrj /* Initialize data structures specific to the Haifa scheduler.  */
7322*38fd1498Szrj void
haifa_sched_init(void)7323*38fd1498Szrj haifa_sched_init (void)
7324*38fd1498Szrj {
7325*38fd1498Szrj   setup_sched_dump ();
7326*38fd1498Szrj   sched_init ();
7327*38fd1498Szrj 
7328*38fd1498Szrj   scheduled_insns.create (0);
7329*38fd1498Szrj 
7330*38fd1498Szrj   if (spec_info != NULL)
7331*38fd1498Szrj     {
7332*38fd1498Szrj       sched_deps_info->use_deps_list = 1;
7333*38fd1498Szrj       sched_deps_info->generate_spec_deps = 1;
7334*38fd1498Szrj     }
7335*38fd1498Szrj 
7336*38fd1498Szrj   /* Initialize luids, dependency caches, target and h_i_d for the
7337*38fd1498Szrj      whole function.  */
7338*38fd1498Szrj   {
7339*38fd1498Szrj     sched_init_bbs ();
7340*38fd1498Szrj 
7341*38fd1498Szrj     auto_vec<basic_block> bbs (n_basic_blocks_for_fn (cfun));
7342*38fd1498Szrj     basic_block bb;
7343*38fd1498Szrj     FOR_EACH_BB_FN (bb, cfun)
7344*38fd1498Szrj       bbs.quick_push (bb);
7345*38fd1498Szrj     sched_init_luids (bbs);
7346*38fd1498Szrj     sched_deps_init (true);
7347*38fd1498Szrj     sched_extend_target ();
7348*38fd1498Szrj     haifa_init_h_i_d (bbs);
7349*38fd1498Szrj   }
7350*38fd1498Szrj 
7351*38fd1498Szrj   sched_init_only_bb = haifa_init_only_bb;
7352*38fd1498Szrj   sched_split_block = sched_split_block_1;
7353*38fd1498Szrj   sched_create_empty_bb = sched_create_empty_bb_1;
7354*38fd1498Szrj   haifa_recovery_bb_ever_added_p = false;
7355*38fd1498Szrj 
7356*38fd1498Szrj   nr_begin_data = nr_begin_control = nr_be_in_data = nr_be_in_control = 0;
7357*38fd1498Szrj   before_recovery = 0;
7358*38fd1498Szrj   after_recovery = 0;
7359*38fd1498Szrj 
7360*38fd1498Szrj   modulo_ii = 0;
7361*38fd1498Szrj }
7362*38fd1498Szrj 
7363*38fd1498Szrj /* Finish work with the data specific to the Haifa scheduler.  */
7364*38fd1498Szrj void
haifa_sched_finish(void)7365*38fd1498Szrj haifa_sched_finish (void)
7366*38fd1498Szrj {
7367*38fd1498Szrj   sched_create_empty_bb = NULL;
7368*38fd1498Szrj   sched_split_block = NULL;
7369*38fd1498Szrj   sched_init_only_bb = NULL;
7370*38fd1498Szrj 
7371*38fd1498Szrj   if (spec_info && spec_info->dump)
7372*38fd1498Szrj     {
7373*38fd1498Szrj       char c = reload_completed ? 'a' : 'b';
7374*38fd1498Szrj 
7375*38fd1498Szrj       fprintf (spec_info->dump,
7376*38fd1498Szrj 	       ";; %s:\n", current_function_name ());
7377*38fd1498Szrj 
7378*38fd1498Szrj       fprintf (spec_info->dump,
7379*38fd1498Szrj                ";; Procedure %cr-begin-data-spec motions == %d\n",
7380*38fd1498Szrj                c, nr_begin_data);
7381*38fd1498Szrj       fprintf (spec_info->dump,
7382*38fd1498Szrj                ";; Procedure %cr-be-in-data-spec motions == %d\n",
7383*38fd1498Szrj                c, nr_be_in_data);
7384*38fd1498Szrj       fprintf (spec_info->dump,
7385*38fd1498Szrj                ";; Procedure %cr-begin-control-spec motions == %d\n",
7386*38fd1498Szrj                c, nr_begin_control);
7387*38fd1498Szrj       fprintf (spec_info->dump,
7388*38fd1498Szrj                ";; Procedure %cr-be-in-control-spec motions == %d\n",
7389*38fd1498Szrj                c, nr_be_in_control);
7390*38fd1498Szrj     }
7391*38fd1498Szrj 
7392*38fd1498Szrj   scheduled_insns.release ();
7393*38fd1498Szrj 
7394*38fd1498Szrj   /* Finalize h_i_d, dependency caches, and luids for the whole
7395*38fd1498Szrj      function.  Target will be finalized in md_global_finish ().  */
7396*38fd1498Szrj   sched_deps_finish ();
7397*38fd1498Szrj   sched_finish_luids ();
7398*38fd1498Szrj   current_sched_info = NULL;
7399*38fd1498Szrj   insn_queue = NULL;
7400*38fd1498Szrj   sched_finish ();
7401*38fd1498Szrj }
7402*38fd1498Szrj 
7403*38fd1498Szrj /* Free global data used during insn scheduling.  This function works with
7404*38fd1498Szrj    the common data shared between the schedulers.  */
7405*38fd1498Szrj 
7406*38fd1498Szrj void
sched_finish(void)7407*38fd1498Szrj sched_finish (void)
7408*38fd1498Szrj {
7409*38fd1498Szrj   haifa_finish_h_i_d ();
7410*38fd1498Szrj   free_global_sched_pressure_data ();
7411*38fd1498Szrj   free (curr_state);
7412*38fd1498Szrj 
7413*38fd1498Szrj   if (targetm.sched.finish_global)
7414*38fd1498Szrj     targetm.sched.finish_global (sched_dump, sched_verbose);
7415*38fd1498Szrj 
7416*38fd1498Szrj   end_alias_analysis ();
7417*38fd1498Szrj 
7418*38fd1498Szrj   regstat_free_calls_crossed ();
7419*38fd1498Szrj 
7420*38fd1498Szrj   dfa_finish ();
7421*38fd1498Szrj }
7422*38fd1498Szrj 
7423*38fd1498Szrj /* Free all delay_pair structures that were recorded.  */
7424*38fd1498Szrj void
free_delay_pairs(void)7425*38fd1498Szrj free_delay_pairs (void)
7426*38fd1498Szrj {
7427*38fd1498Szrj   if (delay_htab)
7428*38fd1498Szrj     {
7429*38fd1498Szrj       delay_htab->empty ();
7430*38fd1498Szrj       delay_htab_i2->empty ();
7431*38fd1498Szrj     }
7432*38fd1498Szrj }
7433*38fd1498Szrj 
7434*38fd1498Szrj /* Fix INSN_TICKs of the instructions in the current block as well as
7435*38fd1498Szrj    INSN_TICKs of their dependents.
7436*38fd1498Szrj    HEAD and TAIL are the begin and the end of the current scheduled block.  */
7437*38fd1498Szrj static void
fix_inter_tick(rtx_insn * head,rtx_insn * tail)7438*38fd1498Szrj fix_inter_tick (rtx_insn *head, rtx_insn *tail)
7439*38fd1498Szrj {
7440*38fd1498Szrj   /* Set of instructions with corrected INSN_TICK.  */
7441*38fd1498Szrj   auto_bitmap processed;
7442*38fd1498Szrj   /* ??? It is doubtful if we should assume that cycle advance happens on
7443*38fd1498Szrj      basic block boundaries.  Basically insns that are unconditionally ready
7444*38fd1498Szrj      on the start of the block are more preferable then those which have
7445*38fd1498Szrj      a one cycle dependency over insn from the previous block.  */
7446*38fd1498Szrj   int next_clock = clock_var + 1;
7447*38fd1498Szrj 
7448*38fd1498Szrj   /* Iterates over scheduled instructions and fix their INSN_TICKs and
7449*38fd1498Szrj      INSN_TICKs of dependent instructions, so that INSN_TICKs are consistent
7450*38fd1498Szrj      across different blocks.  */
7451*38fd1498Szrj   for (tail = NEXT_INSN (tail); head != tail; head = NEXT_INSN (head))
7452*38fd1498Szrj     {
7453*38fd1498Szrj       if (INSN_P (head))
7454*38fd1498Szrj 	{
7455*38fd1498Szrj 	  int tick;
7456*38fd1498Szrj 	  sd_iterator_def sd_it;
7457*38fd1498Szrj 	  dep_t dep;
7458*38fd1498Szrj 
7459*38fd1498Szrj 	  tick = INSN_TICK (head);
7460*38fd1498Szrj 	  gcc_assert (tick >= MIN_TICK);
7461*38fd1498Szrj 
7462*38fd1498Szrj 	  /* Fix INSN_TICK of instruction from just scheduled block.  */
7463*38fd1498Szrj 	  if (bitmap_set_bit (processed, INSN_LUID (head)))
7464*38fd1498Szrj 	    {
7465*38fd1498Szrj 	      tick -= next_clock;
7466*38fd1498Szrj 
7467*38fd1498Szrj 	      if (tick < MIN_TICK)
7468*38fd1498Szrj 		tick = MIN_TICK;
7469*38fd1498Szrj 
7470*38fd1498Szrj 	      INSN_TICK (head) = tick;
7471*38fd1498Szrj 	    }
7472*38fd1498Szrj 
7473*38fd1498Szrj 	  if (DEBUG_INSN_P (head))
7474*38fd1498Szrj 	    continue;
7475*38fd1498Szrj 
7476*38fd1498Szrj 	  FOR_EACH_DEP (head, SD_LIST_RES_FORW, sd_it, dep)
7477*38fd1498Szrj 	    {
7478*38fd1498Szrj 	      rtx_insn *next;
7479*38fd1498Szrj 
7480*38fd1498Szrj 	      next = DEP_CON (dep);
7481*38fd1498Szrj 	      tick = INSN_TICK (next);
7482*38fd1498Szrj 
7483*38fd1498Szrj 	      if (tick != INVALID_TICK
7484*38fd1498Szrj 		  /* If NEXT has its INSN_TICK calculated, fix it.
7485*38fd1498Szrj 		     If not - it will be properly calculated from
7486*38fd1498Szrj 		     scratch later in fix_tick_ready.  */
7487*38fd1498Szrj 		  && bitmap_set_bit (processed, INSN_LUID (next)))
7488*38fd1498Szrj 		{
7489*38fd1498Szrj 		  tick -= next_clock;
7490*38fd1498Szrj 
7491*38fd1498Szrj 		  if (tick < MIN_TICK)
7492*38fd1498Szrj 		    tick = MIN_TICK;
7493*38fd1498Szrj 
7494*38fd1498Szrj 		  if (tick > INTER_TICK (next))
7495*38fd1498Szrj 		    INTER_TICK (next) = tick;
7496*38fd1498Szrj 		  else
7497*38fd1498Szrj 		    tick = INTER_TICK (next);
7498*38fd1498Szrj 
7499*38fd1498Szrj 		  INSN_TICK (next) = tick;
7500*38fd1498Szrj 		}
7501*38fd1498Szrj 	    }
7502*38fd1498Szrj 	}
7503*38fd1498Szrj     }
7504*38fd1498Szrj }
7505*38fd1498Szrj 
7506*38fd1498Szrj /* Check if NEXT is ready to be added to the ready or queue list.
7507*38fd1498Szrj    If "yes", add it to the proper list.
7508*38fd1498Szrj    Returns:
7509*38fd1498Szrj       -1 - is not ready yet,
7510*38fd1498Szrj        0 - added to the ready list,
7511*38fd1498Szrj    0 < N - queued for N cycles.  */
7512*38fd1498Szrj int
try_ready(rtx_insn * next)7513*38fd1498Szrj try_ready (rtx_insn *next)
7514*38fd1498Szrj {
7515*38fd1498Szrj   ds_t old_ts, new_ts;
7516*38fd1498Szrj 
7517*38fd1498Szrj   old_ts = TODO_SPEC (next);
7518*38fd1498Szrj 
7519*38fd1498Szrj   gcc_assert (!(old_ts & ~(SPECULATIVE | HARD_DEP | DEP_CONTROL | DEP_POSTPONED))
7520*38fd1498Szrj 	      && (old_ts == HARD_DEP
7521*38fd1498Szrj 		  || old_ts == DEP_POSTPONED
7522*38fd1498Szrj 		  || (old_ts & SPECULATIVE)
7523*38fd1498Szrj 		  || old_ts == DEP_CONTROL));
7524*38fd1498Szrj 
7525*38fd1498Szrj   new_ts = recompute_todo_spec (next, false);
7526*38fd1498Szrj 
7527*38fd1498Szrj   if (new_ts & (HARD_DEP | DEP_POSTPONED))
7528*38fd1498Szrj     gcc_assert (new_ts == old_ts
7529*38fd1498Szrj 		&& QUEUE_INDEX (next) == QUEUE_NOWHERE);
7530*38fd1498Szrj   else if (current_sched_info->new_ready)
7531*38fd1498Szrj     new_ts = current_sched_info->new_ready (next, new_ts);
7532*38fd1498Szrj 
7533*38fd1498Szrj   /* * if !(old_ts & SPECULATIVE) (e.g. HARD_DEP or 0), then insn might
7534*38fd1498Szrj      have its original pattern or changed (speculative) one.  This is due
7535*38fd1498Szrj      to changing ebb in region scheduling.
7536*38fd1498Szrj      * But if (old_ts & SPECULATIVE), then we are pretty sure that insn
7537*38fd1498Szrj      has speculative pattern.
7538*38fd1498Szrj 
7539*38fd1498Szrj      We can't assert (!(new_ts & HARD_DEP) || new_ts == old_ts) here because
7540*38fd1498Szrj      control-speculative NEXT could have been discarded by sched-rgn.c
7541*38fd1498Szrj      (the same case as when discarded by can_schedule_ready_p ()).  */
7542*38fd1498Szrj 
7543*38fd1498Szrj   if ((new_ts & SPECULATIVE)
7544*38fd1498Szrj       /* If (old_ts == new_ts), then (old_ts & SPECULATIVE) and we don't
7545*38fd1498Szrj 	 need to change anything.  */
7546*38fd1498Szrj       && new_ts != old_ts)
7547*38fd1498Szrj     {
7548*38fd1498Szrj       int res;
7549*38fd1498Szrj       rtx new_pat;
7550*38fd1498Szrj 
7551*38fd1498Szrj       gcc_assert ((new_ts & SPECULATIVE) && !(new_ts & ~SPECULATIVE));
7552*38fd1498Szrj 
7553*38fd1498Szrj       res = haifa_speculate_insn (next, new_ts, &new_pat);
7554*38fd1498Szrj 
7555*38fd1498Szrj       switch (res)
7556*38fd1498Szrj 	{
7557*38fd1498Szrj 	case -1:
7558*38fd1498Szrj 	  /* It would be nice to change DEP_STATUS of all dependences,
7559*38fd1498Szrj 	     which have ((DEP_STATUS & SPECULATIVE) == new_ts) to HARD_DEP,
7560*38fd1498Szrj 	     so we won't reanalyze anything.  */
7561*38fd1498Szrj 	  new_ts = HARD_DEP;
7562*38fd1498Szrj 	  break;
7563*38fd1498Szrj 
7564*38fd1498Szrj 	case 0:
7565*38fd1498Szrj 	  /* We follow the rule, that every speculative insn
7566*38fd1498Szrj 	     has non-null ORIG_PAT.  */
7567*38fd1498Szrj 	  if (!ORIG_PAT (next))
7568*38fd1498Szrj 	    ORIG_PAT (next) = PATTERN (next);
7569*38fd1498Szrj 	  break;
7570*38fd1498Szrj 
7571*38fd1498Szrj 	case 1:
7572*38fd1498Szrj 	  if (!ORIG_PAT (next))
7573*38fd1498Szrj 	    /* If we gonna to overwrite the original pattern of insn,
7574*38fd1498Szrj 	       save it.  */
7575*38fd1498Szrj 	    ORIG_PAT (next) = PATTERN (next);
7576*38fd1498Szrj 
7577*38fd1498Szrj 	  res = haifa_change_pattern (next, new_pat);
7578*38fd1498Szrj 	  gcc_assert (res);
7579*38fd1498Szrj 	  break;
7580*38fd1498Szrj 
7581*38fd1498Szrj 	default:
7582*38fd1498Szrj 	  gcc_unreachable ();
7583*38fd1498Szrj 	}
7584*38fd1498Szrj     }
7585*38fd1498Szrj 
7586*38fd1498Szrj   /* We need to restore pattern only if (new_ts == 0), because otherwise it is
7587*38fd1498Szrj      either correct (new_ts & SPECULATIVE),
7588*38fd1498Szrj      or we simply don't care (new_ts & HARD_DEP).  */
7589*38fd1498Szrj 
7590*38fd1498Szrj   gcc_assert (!ORIG_PAT (next)
7591*38fd1498Szrj 	      || !IS_SPECULATION_BRANCHY_CHECK_P (next));
7592*38fd1498Szrj 
7593*38fd1498Szrj   TODO_SPEC (next) = new_ts;
7594*38fd1498Szrj 
7595*38fd1498Szrj   if (new_ts & (HARD_DEP | DEP_POSTPONED))
7596*38fd1498Szrj     {
7597*38fd1498Szrj       /* We can't assert (QUEUE_INDEX (next) == QUEUE_NOWHERE) here because
7598*38fd1498Szrj 	 control-speculative NEXT could have been discarded by sched-rgn.c
7599*38fd1498Szrj 	 (the same case as when discarded by can_schedule_ready_p ()).  */
7600*38fd1498Szrj       /*gcc_assert (QUEUE_INDEX (next) == QUEUE_NOWHERE);*/
7601*38fd1498Szrj 
7602*38fd1498Szrj       change_queue_index (next, QUEUE_NOWHERE);
7603*38fd1498Szrj 
7604*38fd1498Szrj       return -1;
7605*38fd1498Szrj     }
7606*38fd1498Szrj   else if (!(new_ts & BEGIN_SPEC)
7607*38fd1498Szrj 	   && ORIG_PAT (next) && PREDICATED_PAT (next) == NULL_RTX
7608*38fd1498Szrj 	   && !IS_SPECULATION_CHECK_P (next))
7609*38fd1498Szrj     /* We should change pattern of every previously speculative
7610*38fd1498Szrj        instruction - and we determine if NEXT was speculative by using
7611*38fd1498Szrj        ORIG_PAT field.  Except one case - speculation checks have ORIG_PAT
7612*38fd1498Szrj        pat too, so skip them.  */
7613*38fd1498Szrj     {
7614*38fd1498Szrj       bool success = haifa_change_pattern (next, ORIG_PAT (next));
7615*38fd1498Szrj       gcc_assert (success);
7616*38fd1498Szrj       ORIG_PAT (next) = 0;
7617*38fd1498Szrj     }
7618*38fd1498Szrj 
7619*38fd1498Szrj   if (sched_verbose >= 2)
7620*38fd1498Szrj     {
7621*38fd1498Szrj       fprintf (sched_dump, ";;\t\tdependencies resolved: insn %s",
7622*38fd1498Szrj                (*current_sched_info->print_insn) (next, 0));
7623*38fd1498Szrj 
7624*38fd1498Szrj       if (spec_info && spec_info->dump)
7625*38fd1498Szrj         {
7626*38fd1498Szrj           if (new_ts & BEGIN_DATA)
7627*38fd1498Szrj             fprintf (spec_info->dump, "; data-spec;");
7628*38fd1498Szrj           if (new_ts & BEGIN_CONTROL)
7629*38fd1498Szrj             fprintf (spec_info->dump, "; control-spec;");
7630*38fd1498Szrj           if (new_ts & BE_IN_CONTROL)
7631*38fd1498Szrj             fprintf (spec_info->dump, "; in-control-spec;");
7632*38fd1498Szrj         }
7633*38fd1498Szrj       if (TODO_SPEC (next) & DEP_CONTROL)
7634*38fd1498Szrj 	fprintf (sched_dump, " predicated");
7635*38fd1498Szrj       fprintf (sched_dump, "\n");
7636*38fd1498Szrj     }
7637*38fd1498Szrj 
7638*38fd1498Szrj   adjust_priority (next);
7639*38fd1498Szrj 
7640*38fd1498Szrj   return fix_tick_ready (next);
7641*38fd1498Szrj }
7642*38fd1498Szrj 
7643*38fd1498Szrj /* Calculate INSN_TICK of NEXT and add it to either ready or queue list.  */
7644*38fd1498Szrj static int
fix_tick_ready(rtx_insn * next)7645*38fd1498Szrj fix_tick_ready (rtx_insn *next)
7646*38fd1498Szrj {
7647*38fd1498Szrj   int tick, delay;
7648*38fd1498Szrj 
7649*38fd1498Szrj   if (!DEBUG_INSN_P (next) && !sd_lists_empty_p (next, SD_LIST_RES_BACK))
7650*38fd1498Szrj     {
7651*38fd1498Szrj       int full_p;
7652*38fd1498Szrj       sd_iterator_def sd_it;
7653*38fd1498Szrj       dep_t dep;
7654*38fd1498Szrj 
7655*38fd1498Szrj       tick = INSN_TICK (next);
7656*38fd1498Szrj       /* if tick is not equal to INVALID_TICK, then update
7657*38fd1498Szrj 	 INSN_TICK of NEXT with the most recent resolved dependence
7658*38fd1498Szrj 	 cost.  Otherwise, recalculate from scratch.  */
7659*38fd1498Szrj       full_p = (tick == INVALID_TICK);
7660*38fd1498Szrj 
7661*38fd1498Szrj       FOR_EACH_DEP (next, SD_LIST_RES_BACK, sd_it, dep)
7662*38fd1498Szrj         {
7663*38fd1498Szrj           rtx_insn *pro = DEP_PRO (dep);
7664*38fd1498Szrj           int tick1;
7665*38fd1498Szrj 
7666*38fd1498Szrj 	  gcc_assert (INSN_TICK (pro) >= MIN_TICK);
7667*38fd1498Szrj 
7668*38fd1498Szrj           tick1 = INSN_TICK (pro) + dep_cost (dep);
7669*38fd1498Szrj           if (tick1 > tick)
7670*38fd1498Szrj             tick = tick1;
7671*38fd1498Szrj 
7672*38fd1498Szrj 	  if (!full_p)
7673*38fd1498Szrj 	    break;
7674*38fd1498Szrj         }
7675*38fd1498Szrj     }
7676*38fd1498Szrj   else
7677*38fd1498Szrj     tick = -1;
7678*38fd1498Szrj 
7679*38fd1498Szrj   INSN_TICK (next) = tick;
7680*38fd1498Szrj 
7681*38fd1498Szrj   delay = tick - clock_var;
7682*38fd1498Szrj   if (delay <= 0 || sched_pressure != SCHED_PRESSURE_NONE || sched_fusion)
7683*38fd1498Szrj     delay = QUEUE_READY;
7684*38fd1498Szrj 
7685*38fd1498Szrj   change_queue_index (next, delay);
7686*38fd1498Szrj 
7687*38fd1498Szrj   return delay;
7688*38fd1498Szrj }
7689*38fd1498Szrj 
7690*38fd1498Szrj /* Move NEXT to the proper queue list with (DELAY >= 1),
7691*38fd1498Szrj    or add it to the ready list (DELAY == QUEUE_READY),
7692*38fd1498Szrj    or remove it from ready and queue lists at all (DELAY == QUEUE_NOWHERE).  */
7693*38fd1498Szrj static void
change_queue_index(rtx_insn * next,int delay)7694*38fd1498Szrj change_queue_index (rtx_insn *next, int delay)
7695*38fd1498Szrj {
7696*38fd1498Szrj   int i = QUEUE_INDEX (next);
7697*38fd1498Szrj 
7698*38fd1498Szrj   gcc_assert (QUEUE_NOWHERE <= delay && delay <= max_insn_queue_index
7699*38fd1498Szrj 	      && delay != 0);
7700*38fd1498Szrj   gcc_assert (i != QUEUE_SCHEDULED);
7701*38fd1498Szrj 
7702*38fd1498Szrj   if ((delay > 0 && NEXT_Q_AFTER (q_ptr, delay) == i)
7703*38fd1498Szrj       || (delay < 0 && delay == i))
7704*38fd1498Szrj     /* We have nothing to do.  */
7705*38fd1498Szrj     return;
7706*38fd1498Szrj 
7707*38fd1498Szrj   /* Remove NEXT from wherever it is now.  */
7708*38fd1498Szrj   if (i == QUEUE_READY)
7709*38fd1498Szrj     ready_remove_insn (next);
7710*38fd1498Szrj   else if (i >= 0)
7711*38fd1498Szrj     queue_remove (next);
7712*38fd1498Szrj 
7713*38fd1498Szrj   /* Add it to the proper place.  */
7714*38fd1498Szrj   if (delay == QUEUE_READY)
7715*38fd1498Szrj     ready_add (readyp, next, false);
7716*38fd1498Szrj   else if (delay >= 1)
7717*38fd1498Szrj     queue_insn (next, delay, "change queue index");
7718*38fd1498Szrj 
7719*38fd1498Szrj   if (sched_verbose >= 2)
7720*38fd1498Szrj     {
7721*38fd1498Szrj       fprintf (sched_dump, ";;\t\ttick updated: insn %s",
7722*38fd1498Szrj 	       (*current_sched_info->print_insn) (next, 0));
7723*38fd1498Szrj 
7724*38fd1498Szrj       if (delay == QUEUE_READY)
7725*38fd1498Szrj 	fprintf (sched_dump, " into ready\n");
7726*38fd1498Szrj       else if (delay >= 1)
7727*38fd1498Szrj 	fprintf (sched_dump, " into queue with cost=%d\n", delay);
7728*38fd1498Szrj       else
7729*38fd1498Szrj 	fprintf (sched_dump, " removed from ready or queue lists\n");
7730*38fd1498Szrj     }
7731*38fd1498Szrj }
7732*38fd1498Szrj 
7733*38fd1498Szrj static int sched_ready_n_insns = -1;
7734*38fd1498Szrj 
7735*38fd1498Szrj /* Initialize per region data structures.  */
7736*38fd1498Szrj void
sched_extend_ready_list(int new_sched_ready_n_insns)7737*38fd1498Szrj sched_extend_ready_list (int new_sched_ready_n_insns)
7738*38fd1498Szrj {
7739*38fd1498Szrj   int i;
7740*38fd1498Szrj 
7741*38fd1498Szrj   if (sched_ready_n_insns == -1)
7742*38fd1498Szrj     /* At the first call we need to initialize one more choice_stack
7743*38fd1498Szrj        entry.  */
7744*38fd1498Szrj     {
7745*38fd1498Szrj       i = 0;
7746*38fd1498Szrj       sched_ready_n_insns = 0;
7747*38fd1498Szrj       scheduled_insns.reserve (new_sched_ready_n_insns);
7748*38fd1498Szrj     }
7749*38fd1498Szrj   else
7750*38fd1498Szrj     i = sched_ready_n_insns + 1;
7751*38fd1498Szrj 
7752*38fd1498Szrj   ready.veclen = new_sched_ready_n_insns + issue_rate;
7753*38fd1498Szrj   ready.vec = XRESIZEVEC (rtx_insn *, ready.vec, ready.veclen);
7754*38fd1498Szrj 
7755*38fd1498Szrj   gcc_assert (new_sched_ready_n_insns >= sched_ready_n_insns);
7756*38fd1498Szrj 
7757*38fd1498Szrj   ready_try = (signed char *) xrecalloc (ready_try, new_sched_ready_n_insns,
7758*38fd1498Szrj 					 sched_ready_n_insns,
7759*38fd1498Szrj 					 sizeof (*ready_try));
7760*38fd1498Szrj 
7761*38fd1498Szrj   /* We allocate +1 element to save initial state in the choice_stack[0]
7762*38fd1498Szrj      entry.  */
7763*38fd1498Szrj   choice_stack = XRESIZEVEC (struct choice_entry, choice_stack,
7764*38fd1498Szrj 			     new_sched_ready_n_insns + 1);
7765*38fd1498Szrj 
7766*38fd1498Szrj   for (; i <= new_sched_ready_n_insns; i++)
7767*38fd1498Szrj     {
7768*38fd1498Szrj       choice_stack[i].state = xmalloc (dfa_state_size);
7769*38fd1498Szrj 
7770*38fd1498Szrj       if (targetm.sched.first_cycle_multipass_init)
7771*38fd1498Szrj 	targetm.sched.first_cycle_multipass_init (&(choice_stack[i]
7772*38fd1498Szrj 						    .target_data));
7773*38fd1498Szrj     }
7774*38fd1498Szrj 
7775*38fd1498Szrj   sched_ready_n_insns = new_sched_ready_n_insns;
7776*38fd1498Szrj }
7777*38fd1498Szrj 
7778*38fd1498Szrj /* Free per region data structures.  */
7779*38fd1498Szrj void
sched_finish_ready_list(void)7780*38fd1498Szrj sched_finish_ready_list (void)
7781*38fd1498Szrj {
7782*38fd1498Szrj   int i;
7783*38fd1498Szrj 
7784*38fd1498Szrj   free (ready.vec);
7785*38fd1498Szrj   ready.vec = NULL;
7786*38fd1498Szrj   ready.veclen = 0;
7787*38fd1498Szrj 
7788*38fd1498Szrj   free (ready_try);
7789*38fd1498Szrj   ready_try = NULL;
7790*38fd1498Szrj 
7791*38fd1498Szrj   for (i = 0; i <= sched_ready_n_insns; i++)
7792*38fd1498Szrj     {
7793*38fd1498Szrj       if (targetm.sched.first_cycle_multipass_fini)
7794*38fd1498Szrj 	targetm.sched.first_cycle_multipass_fini (&(choice_stack[i]
7795*38fd1498Szrj 						    .target_data));
7796*38fd1498Szrj 
7797*38fd1498Szrj       free (choice_stack [i].state);
7798*38fd1498Szrj     }
7799*38fd1498Szrj   free (choice_stack);
7800*38fd1498Szrj   choice_stack = NULL;
7801*38fd1498Szrj 
7802*38fd1498Szrj   sched_ready_n_insns = -1;
7803*38fd1498Szrj }
7804*38fd1498Szrj 
7805*38fd1498Szrj static int
haifa_luid_for_non_insn(rtx x)7806*38fd1498Szrj haifa_luid_for_non_insn (rtx x)
7807*38fd1498Szrj {
7808*38fd1498Szrj   gcc_assert (NOTE_P (x) || LABEL_P (x));
7809*38fd1498Szrj 
7810*38fd1498Szrj   return 0;
7811*38fd1498Szrj }
7812*38fd1498Szrj 
7813*38fd1498Szrj /* Generates recovery code for INSN.  */
7814*38fd1498Szrj static void
generate_recovery_code(rtx_insn * insn)7815*38fd1498Szrj generate_recovery_code (rtx_insn *insn)
7816*38fd1498Szrj {
7817*38fd1498Szrj   if (TODO_SPEC (insn) & BEGIN_SPEC)
7818*38fd1498Szrj     begin_speculative_block (insn);
7819*38fd1498Szrj 
7820*38fd1498Szrj   /* Here we have insn with no dependencies to
7821*38fd1498Szrj      instructions other then CHECK_SPEC ones.  */
7822*38fd1498Szrj 
7823*38fd1498Szrj   if (TODO_SPEC (insn) & BE_IN_SPEC)
7824*38fd1498Szrj     add_to_speculative_block (insn);
7825*38fd1498Szrj }
7826*38fd1498Szrj 
7827*38fd1498Szrj /* Helper function.
7828*38fd1498Szrj    Tries to add speculative dependencies of type FS between instructions
7829*38fd1498Szrj    in deps_list L and TWIN.  */
7830*38fd1498Szrj static void
process_insn_forw_deps_be_in_spec(rtx_insn * insn,rtx_insn * twin,ds_t fs)7831*38fd1498Szrj process_insn_forw_deps_be_in_spec (rtx_insn *insn, rtx_insn *twin, ds_t fs)
7832*38fd1498Szrj {
7833*38fd1498Szrj   sd_iterator_def sd_it;
7834*38fd1498Szrj   dep_t dep;
7835*38fd1498Szrj 
7836*38fd1498Szrj   FOR_EACH_DEP (insn, SD_LIST_FORW, sd_it, dep)
7837*38fd1498Szrj     {
7838*38fd1498Szrj       ds_t ds;
7839*38fd1498Szrj       rtx_insn *consumer;
7840*38fd1498Szrj 
7841*38fd1498Szrj       consumer = DEP_CON (dep);
7842*38fd1498Szrj 
7843*38fd1498Szrj       ds = DEP_STATUS (dep);
7844*38fd1498Szrj 
7845*38fd1498Szrj       if (/* If we want to create speculative dep.  */
7846*38fd1498Szrj 	  fs
7847*38fd1498Szrj 	  /* And we can do that because this is a true dep.  */
7848*38fd1498Szrj 	  && (ds & DEP_TYPES) == DEP_TRUE)
7849*38fd1498Szrj 	{
7850*38fd1498Szrj 	  gcc_assert (!(ds & BE_IN_SPEC));
7851*38fd1498Szrj 
7852*38fd1498Szrj 	  if (/* If this dep can be overcome with 'begin speculation'.  */
7853*38fd1498Szrj 	      ds & BEGIN_SPEC)
7854*38fd1498Szrj 	    /* Then we have a choice: keep the dep 'begin speculative'
7855*38fd1498Szrj 	       or transform it into 'be in speculative'.  */
7856*38fd1498Szrj 	    {
7857*38fd1498Szrj 	      if (/* In try_ready we assert that if insn once became ready
7858*38fd1498Szrj 		     it can be removed from the ready (or queue) list only
7859*38fd1498Szrj 		     due to backend decision.  Hence we can't let the
7860*38fd1498Szrj 		     probability of the speculative dep to decrease.  */
7861*38fd1498Szrj 		  ds_weak (ds) <= ds_weak (fs))
7862*38fd1498Szrj 		{
7863*38fd1498Szrj 		  ds_t new_ds;
7864*38fd1498Szrj 
7865*38fd1498Szrj 		  new_ds = (ds & ~BEGIN_SPEC) | fs;
7866*38fd1498Szrj 
7867*38fd1498Szrj 		  if (/* consumer can 'be in speculative'.  */
7868*38fd1498Szrj 		      sched_insn_is_legitimate_for_speculation_p (consumer,
7869*38fd1498Szrj 								  new_ds))
7870*38fd1498Szrj 		    /* Transform it to be in speculative.  */
7871*38fd1498Szrj 		    ds = new_ds;
7872*38fd1498Szrj 		}
7873*38fd1498Szrj 	    }
7874*38fd1498Szrj 	  else
7875*38fd1498Szrj 	    /* Mark the dep as 'be in speculative'.  */
7876*38fd1498Szrj 	    ds |= fs;
7877*38fd1498Szrj 	}
7878*38fd1498Szrj 
7879*38fd1498Szrj       {
7880*38fd1498Szrj 	dep_def _new_dep, *new_dep = &_new_dep;
7881*38fd1498Szrj 
7882*38fd1498Szrj 	init_dep_1 (new_dep, twin, consumer, DEP_TYPE (dep), ds);
7883*38fd1498Szrj 	sd_add_dep (new_dep, false);
7884*38fd1498Szrj       }
7885*38fd1498Szrj     }
7886*38fd1498Szrj }
7887*38fd1498Szrj 
7888*38fd1498Szrj /* Generates recovery code for BEGIN speculative INSN.  */
7889*38fd1498Szrj static void
begin_speculative_block(rtx_insn * insn)7890*38fd1498Szrj begin_speculative_block (rtx_insn *insn)
7891*38fd1498Szrj {
7892*38fd1498Szrj   if (TODO_SPEC (insn) & BEGIN_DATA)
7893*38fd1498Szrj     nr_begin_data++;
7894*38fd1498Szrj   if (TODO_SPEC (insn) & BEGIN_CONTROL)
7895*38fd1498Szrj     nr_begin_control++;
7896*38fd1498Szrj 
7897*38fd1498Szrj   create_check_block_twin (insn, false);
7898*38fd1498Szrj 
7899*38fd1498Szrj   TODO_SPEC (insn) &= ~BEGIN_SPEC;
7900*38fd1498Szrj }
7901*38fd1498Szrj 
7902*38fd1498Szrj static void haifa_init_insn (rtx_insn *);
7903*38fd1498Szrj 
7904*38fd1498Szrj /* Generates recovery code for BE_IN speculative INSN.  */
7905*38fd1498Szrj static void
add_to_speculative_block(rtx_insn * insn)7906*38fd1498Szrj add_to_speculative_block (rtx_insn *insn)
7907*38fd1498Szrj {
7908*38fd1498Szrj   ds_t ts;
7909*38fd1498Szrj   sd_iterator_def sd_it;
7910*38fd1498Szrj   dep_t dep;
7911*38fd1498Szrj   auto_vec<rtx_insn *, 10> twins;
7912*38fd1498Szrj 
7913*38fd1498Szrj   ts = TODO_SPEC (insn);
7914*38fd1498Szrj   gcc_assert (!(ts & ~BE_IN_SPEC));
7915*38fd1498Szrj 
7916*38fd1498Szrj   if (ts & BE_IN_DATA)
7917*38fd1498Szrj     nr_be_in_data++;
7918*38fd1498Szrj   if (ts & BE_IN_CONTROL)
7919*38fd1498Szrj     nr_be_in_control++;
7920*38fd1498Szrj 
7921*38fd1498Szrj   TODO_SPEC (insn) &= ~BE_IN_SPEC;
7922*38fd1498Szrj   gcc_assert (!TODO_SPEC (insn));
7923*38fd1498Szrj 
7924*38fd1498Szrj   DONE_SPEC (insn) |= ts;
7925*38fd1498Szrj 
7926*38fd1498Szrj   /* First we convert all simple checks to branchy.  */
7927*38fd1498Szrj   for (sd_it = sd_iterator_start (insn, SD_LIST_SPEC_BACK);
7928*38fd1498Szrj        sd_iterator_cond (&sd_it, &dep);)
7929*38fd1498Szrj     {
7930*38fd1498Szrj       rtx_insn *check = DEP_PRO (dep);
7931*38fd1498Szrj 
7932*38fd1498Szrj       if (IS_SPECULATION_SIMPLE_CHECK_P (check))
7933*38fd1498Szrj 	{
7934*38fd1498Szrj 	  create_check_block_twin (check, true);
7935*38fd1498Szrj 
7936*38fd1498Szrj 	  /* Restart search.  */
7937*38fd1498Szrj 	  sd_it = sd_iterator_start (insn, SD_LIST_SPEC_BACK);
7938*38fd1498Szrj 	}
7939*38fd1498Szrj       else
7940*38fd1498Szrj 	/* Continue search.  */
7941*38fd1498Szrj 	sd_iterator_next (&sd_it);
7942*38fd1498Szrj     }
7943*38fd1498Szrj 
7944*38fd1498Szrj   auto_vec<rtx_insn *> priorities_roots;
7945*38fd1498Szrj   clear_priorities (insn, &priorities_roots);
7946*38fd1498Szrj 
7947*38fd1498Szrj   while (1)
7948*38fd1498Szrj     {
7949*38fd1498Szrj       rtx_insn *check, *twin;
7950*38fd1498Szrj       basic_block rec;
7951*38fd1498Szrj 
7952*38fd1498Szrj       /* Get the first backward dependency of INSN.  */
7953*38fd1498Szrj       sd_it = sd_iterator_start (insn, SD_LIST_SPEC_BACK);
7954*38fd1498Szrj       if (!sd_iterator_cond (&sd_it, &dep))
7955*38fd1498Szrj 	/* INSN has no backward dependencies left.  */
7956*38fd1498Szrj 	break;
7957*38fd1498Szrj 
7958*38fd1498Szrj       gcc_assert ((DEP_STATUS (dep) & BEGIN_SPEC) == 0
7959*38fd1498Szrj 		  && (DEP_STATUS (dep) & BE_IN_SPEC) != 0
7960*38fd1498Szrj 		  && (DEP_STATUS (dep) & DEP_TYPES) == DEP_TRUE);
7961*38fd1498Szrj 
7962*38fd1498Szrj       check = DEP_PRO (dep);
7963*38fd1498Szrj 
7964*38fd1498Szrj       gcc_assert (!IS_SPECULATION_CHECK_P (check) && !ORIG_PAT (check)
7965*38fd1498Szrj 		  && QUEUE_INDEX (check) == QUEUE_NOWHERE);
7966*38fd1498Szrj 
7967*38fd1498Szrj       rec = BLOCK_FOR_INSN (check);
7968*38fd1498Szrj 
7969*38fd1498Szrj       twin = emit_insn_before (copy_insn (PATTERN (insn)), BB_END (rec));
7970*38fd1498Szrj       haifa_init_insn (twin);
7971*38fd1498Szrj 
7972*38fd1498Szrj       sd_copy_back_deps (twin, insn, true);
7973*38fd1498Szrj 
7974*38fd1498Szrj       if (sched_verbose && spec_info->dump)
7975*38fd1498Szrj         /* INSN_BB (insn) isn't determined for twin insns yet.
7976*38fd1498Szrj            So we can't use current_sched_info->print_insn.  */
7977*38fd1498Szrj         fprintf (spec_info->dump, ";;\t\tGenerated twin insn : %d/rec%d\n",
7978*38fd1498Szrj                  INSN_UID (twin), rec->index);
7979*38fd1498Szrj 
7980*38fd1498Szrj       twins.safe_push (twin);
7981*38fd1498Szrj 
7982*38fd1498Szrj       /* Add dependences between TWIN and all appropriate
7983*38fd1498Szrj 	 instructions from REC.  */
7984*38fd1498Szrj       FOR_EACH_DEP (insn, SD_LIST_SPEC_BACK, sd_it, dep)
7985*38fd1498Szrj 	{
7986*38fd1498Szrj 	  rtx_insn *pro = DEP_PRO (dep);
7987*38fd1498Szrj 
7988*38fd1498Szrj 	  gcc_assert (DEP_TYPE (dep) == REG_DEP_TRUE);
7989*38fd1498Szrj 
7990*38fd1498Szrj 	  /* INSN might have dependencies from the instructions from
7991*38fd1498Szrj 	     several recovery blocks.  At this iteration we process those
7992*38fd1498Szrj 	     producers that reside in REC.  */
7993*38fd1498Szrj 	  if (BLOCK_FOR_INSN (pro) == rec)
7994*38fd1498Szrj 	    {
7995*38fd1498Szrj 	      dep_def _new_dep, *new_dep = &_new_dep;
7996*38fd1498Szrj 
7997*38fd1498Szrj 	      init_dep (new_dep, pro, twin, REG_DEP_TRUE);
7998*38fd1498Szrj 	      sd_add_dep (new_dep, false);
7999*38fd1498Szrj 	    }
8000*38fd1498Szrj 	}
8001*38fd1498Szrj 
8002*38fd1498Szrj       process_insn_forw_deps_be_in_spec (insn, twin, ts);
8003*38fd1498Szrj 
8004*38fd1498Szrj       /* Remove all dependencies between INSN and insns in REC.  */
8005*38fd1498Szrj       for (sd_it = sd_iterator_start (insn, SD_LIST_SPEC_BACK);
8006*38fd1498Szrj 	   sd_iterator_cond (&sd_it, &dep);)
8007*38fd1498Szrj 	{
8008*38fd1498Szrj 	  rtx_insn *pro = DEP_PRO (dep);
8009*38fd1498Szrj 
8010*38fd1498Szrj 	  if (BLOCK_FOR_INSN (pro) == rec)
8011*38fd1498Szrj 	    sd_delete_dep (sd_it);
8012*38fd1498Szrj 	  else
8013*38fd1498Szrj 	    sd_iterator_next (&sd_it);
8014*38fd1498Szrj 	}
8015*38fd1498Szrj     }
8016*38fd1498Szrj 
8017*38fd1498Szrj   /* We couldn't have added the dependencies between INSN and TWINS earlier
8018*38fd1498Szrj      because that would make TWINS appear in the INSN_BACK_DEPS (INSN).  */
8019*38fd1498Szrj   unsigned int i;
8020*38fd1498Szrj   rtx_insn *twin;
8021*38fd1498Szrj   FOR_EACH_VEC_ELT_REVERSE (twins, i, twin)
8022*38fd1498Szrj     {
8023*38fd1498Szrj       dep_def _new_dep, *new_dep = &_new_dep;
8024*38fd1498Szrj 
8025*38fd1498Szrj       init_dep (new_dep, insn, twin, REG_DEP_OUTPUT);
8026*38fd1498Szrj       sd_add_dep (new_dep, false);
8027*38fd1498Szrj     }
8028*38fd1498Szrj 
8029*38fd1498Szrj   calc_priorities (priorities_roots);
8030*38fd1498Szrj }
8031*38fd1498Szrj 
8032*38fd1498Szrj /* Extends and fills with zeros (only the new part) array pointed to by P.  */
8033*38fd1498Szrj void *
xrecalloc(void * p,size_t new_nmemb,size_t old_nmemb,size_t size)8034*38fd1498Szrj xrecalloc (void *p, size_t new_nmemb, size_t old_nmemb, size_t size)
8035*38fd1498Szrj {
8036*38fd1498Szrj   gcc_assert (new_nmemb >= old_nmemb);
8037*38fd1498Szrj   p = XRESIZEVAR (void, p, new_nmemb * size);
8038*38fd1498Szrj   memset (((char *) p) + old_nmemb * size, 0, (new_nmemb - old_nmemb) * size);
8039*38fd1498Szrj   return p;
8040*38fd1498Szrj }
8041*38fd1498Szrj 
8042*38fd1498Szrj /* Helper function.
8043*38fd1498Szrj    Find fallthru edge from PRED.  */
8044*38fd1498Szrj edge
find_fallthru_edge_from(basic_block pred)8045*38fd1498Szrj find_fallthru_edge_from (basic_block pred)
8046*38fd1498Szrj {
8047*38fd1498Szrj   edge e;
8048*38fd1498Szrj   basic_block succ;
8049*38fd1498Szrj 
8050*38fd1498Szrj   succ = pred->next_bb;
8051*38fd1498Szrj   gcc_assert (succ->prev_bb == pred);
8052*38fd1498Szrj 
8053*38fd1498Szrj   if (EDGE_COUNT (pred->succs) <= EDGE_COUNT (succ->preds))
8054*38fd1498Szrj     {
8055*38fd1498Szrj       e = find_fallthru_edge (pred->succs);
8056*38fd1498Szrj 
8057*38fd1498Szrj       if (e)
8058*38fd1498Szrj 	{
8059*38fd1498Szrj 	  gcc_assert (e->dest == succ);
8060*38fd1498Szrj 	  return e;
8061*38fd1498Szrj 	}
8062*38fd1498Szrj     }
8063*38fd1498Szrj   else
8064*38fd1498Szrj     {
8065*38fd1498Szrj       e = find_fallthru_edge (succ->preds);
8066*38fd1498Szrj 
8067*38fd1498Szrj       if (e)
8068*38fd1498Szrj 	{
8069*38fd1498Szrj 	  gcc_assert (e->src == pred);
8070*38fd1498Szrj 	  return e;
8071*38fd1498Szrj 	}
8072*38fd1498Szrj     }
8073*38fd1498Szrj 
8074*38fd1498Szrj   return NULL;
8075*38fd1498Szrj }
8076*38fd1498Szrj 
8077*38fd1498Szrj /* Extend per basic block data structures.  */
8078*38fd1498Szrj static void
sched_extend_bb(void)8079*38fd1498Szrj sched_extend_bb (void)
8080*38fd1498Szrj {
8081*38fd1498Szrj   /* The following is done to keep current_sched_info->next_tail non null.  */
8082*38fd1498Szrj   rtx_insn *end = BB_END (EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb);
8083*38fd1498Szrj   rtx_insn *insn = DEBUG_INSN_P (end) ? prev_nondebug_insn (end) : end;
8084*38fd1498Szrj   if (NEXT_INSN (end) == 0
8085*38fd1498Szrj       || (!NOTE_P (insn)
8086*38fd1498Szrj 	  && !LABEL_P (insn)
8087*38fd1498Szrj 	  /* Don't emit a NOTE if it would end up before a BARRIER.  */
8088*38fd1498Szrj 	  && !BARRIER_P (next_nondebug_insn (end))))
8089*38fd1498Szrj     {
8090*38fd1498Szrj       rtx_note *note = emit_note_after (NOTE_INSN_DELETED, end);
8091*38fd1498Szrj       /* Make note appear outside BB.  */
8092*38fd1498Szrj       set_block_for_insn (note, NULL);
8093*38fd1498Szrj       BB_END (EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb) = end;
8094*38fd1498Szrj     }
8095*38fd1498Szrj }
8096*38fd1498Szrj 
8097*38fd1498Szrj /* Init per basic block data structures.  */
8098*38fd1498Szrj void
sched_init_bbs(void)8099*38fd1498Szrj sched_init_bbs (void)
8100*38fd1498Szrj {
8101*38fd1498Szrj   sched_extend_bb ();
8102*38fd1498Szrj }
8103*38fd1498Szrj 
8104*38fd1498Szrj /* Initialize BEFORE_RECOVERY variable.  */
8105*38fd1498Szrj static void
init_before_recovery(basic_block * before_recovery_ptr)8106*38fd1498Szrj init_before_recovery (basic_block *before_recovery_ptr)
8107*38fd1498Szrj {
8108*38fd1498Szrj   basic_block last;
8109*38fd1498Szrj   edge e;
8110*38fd1498Szrj 
8111*38fd1498Szrj   last = EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb;
8112*38fd1498Szrj   e = find_fallthru_edge_from (last);
8113*38fd1498Szrj 
8114*38fd1498Szrj   if (e)
8115*38fd1498Szrj     {
8116*38fd1498Szrj       /* We create two basic blocks:
8117*38fd1498Szrj          1. Single instruction block is inserted right after E->SRC
8118*38fd1498Szrj          and has jump to
8119*38fd1498Szrj          2. Empty block right before EXIT_BLOCK.
8120*38fd1498Szrj          Between these two blocks recovery blocks will be emitted.  */
8121*38fd1498Szrj 
8122*38fd1498Szrj       basic_block single, empty;
8123*38fd1498Szrj 
8124*38fd1498Szrj       /* If the fallthrough edge to exit we've found is from the block we've
8125*38fd1498Szrj 	 created before, don't do anything more.  */
8126*38fd1498Szrj       if (last == after_recovery)
8127*38fd1498Szrj 	return;
8128*38fd1498Szrj 
8129*38fd1498Szrj       adding_bb_to_current_region_p = false;
8130*38fd1498Szrj 
8131*38fd1498Szrj       single = sched_create_empty_bb (last);
8132*38fd1498Szrj       empty = sched_create_empty_bb (single);
8133*38fd1498Szrj 
8134*38fd1498Szrj       /* Add new blocks to the root loop.  */
8135*38fd1498Szrj       if (current_loops != NULL)
8136*38fd1498Szrj 	{
8137*38fd1498Szrj 	  add_bb_to_loop (single, (*current_loops->larray)[0]);
8138*38fd1498Szrj 	  add_bb_to_loop (empty, (*current_loops->larray)[0]);
8139*38fd1498Szrj 	}
8140*38fd1498Szrj 
8141*38fd1498Szrj       single->count = last->count;
8142*38fd1498Szrj       empty->count = last->count;
8143*38fd1498Szrj       BB_COPY_PARTITION (single, last);
8144*38fd1498Szrj       BB_COPY_PARTITION (empty, last);
8145*38fd1498Szrj 
8146*38fd1498Szrj       redirect_edge_succ (e, single);
8147*38fd1498Szrj       make_single_succ_edge (single, empty, 0);
8148*38fd1498Szrj       make_single_succ_edge (empty, EXIT_BLOCK_PTR_FOR_FN (cfun),
8149*38fd1498Szrj 			     EDGE_FALLTHRU);
8150*38fd1498Szrj 
8151*38fd1498Szrj       rtx_code_label *label = block_label (empty);
8152*38fd1498Szrj       rtx_jump_insn *x = emit_jump_insn_after (targetm.gen_jump (label),
8153*38fd1498Szrj 					       BB_END (single));
8154*38fd1498Szrj       JUMP_LABEL (x) = label;
8155*38fd1498Szrj       LABEL_NUSES (label)++;
8156*38fd1498Szrj       haifa_init_insn (x);
8157*38fd1498Szrj 
8158*38fd1498Szrj       emit_barrier_after (x);
8159*38fd1498Szrj 
8160*38fd1498Szrj       sched_init_only_bb (empty, NULL);
8161*38fd1498Szrj       sched_init_only_bb (single, NULL);
8162*38fd1498Szrj       sched_extend_bb ();
8163*38fd1498Szrj 
8164*38fd1498Szrj       adding_bb_to_current_region_p = true;
8165*38fd1498Szrj       before_recovery = single;
8166*38fd1498Szrj       after_recovery = empty;
8167*38fd1498Szrj 
8168*38fd1498Szrj       if (before_recovery_ptr)
8169*38fd1498Szrj         *before_recovery_ptr = before_recovery;
8170*38fd1498Szrj 
8171*38fd1498Szrj       if (sched_verbose >= 2 && spec_info->dump)
8172*38fd1498Szrj         fprintf (spec_info->dump,
8173*38fd1498Szrj 		 ";;\t\tFixed fallthru to EXIT : %d->>%d->%d->>EXIT\n",
8174*38fd1498Szrj                  last->index, single->index, empty->index);
8175*38fd1498Szrj     }
8176*38fd1498Szrj   else
8177*38fd1498Szrj     before_recovery = last;
8178*38fd1498Szrj }
8179*38fd1498Szrj 
8180*38fd1498Szrj /* Returns new recovery block.  */
8181*38fd1498Szrj basic_block
sched_create_recovery_block(basic_block * before_recovery_ptr)8182*38fd1498Szrj sched_create_recovery_block (basic_block *before_recovery_ptr)
8183*38fd1498Szrj {
8184*38fd1498Szrj   rtx_insn *barrier;
8185*38fd1498Szrj   basic_block rec;
8186*38fd1498Szrj 
8187*38fd1498Szrj   haifa_recovery_bb_recently_added_p = true;
8188*38fd1498Szrj   haifa_recovery_bb_ever_added_p = true;
8189*38fd1498Szrj 
8190*38fd1498Szrj   init_before_recovery (before_recovery_ptr);
8191*38fd1498Szrj 
8192*38fd1498Szrj   barrier = get_last_bb_insn (before_recovery);
8193*38fd1498Szrj   gcc_assert (BARRIER_P (barrier));
8194*38fd1498Szrj 
8195*38fd1498Szrj   rtx_insn *label = emit_label_after (gen_label_rtx (), barrier);
8196*38fd1498Szrj 
8197*38fd1498Szrj   rec = create_basic_block (label, label, before_recovery);
8198*38fd1498Szrj 
8199*38fd1498Szrj   /* A recovery block always ends with an unconditional jump.  */
8200*38fd1498Szrj   emit_barrier_after (BB_END (rec));
8201*38fd1498Szrj 
8202*38fd1498Szrj   if (BB_PARTITION (before_recovery) != BB_UNPARTITIONED)
8203*38fd1498Szrj     BB_SET_PARTITION (rec, BB_COLD_PARTITION);
8204*38fd1498Szrj 
8205*38fd1498Szrj   if (sched_verbose && spec_info->dump)
8206*38fd1498Szrj     fprintf (spec_info->dump, ";;\t\tGenerated recovery block rec%d\n",
8207*38fd1498Szrj              rec->index);
8208*38fd1498Szrj 
8209*38fd1498Szrj   return rec;
8210*38fd1498Szrj }
8211*38fd1498Szrj 
8212*38fd1498Szrj /* Create edges: FIRST_BB -> REC; FIRST_BB -> SECOND_BB; REC -> SECOND_BB
8213*38fd1498Szrj    and emit necessary jumps.  */
8214*38fd1498Szrj void
sched_create_recovery_edges(basic_block first_bb,basic_block rec,basic_block second_bb)8215*38fd1498Szrj sched_create_recovery_edges (basic_block first_bb, basic_block rec,
8216*38fd1498Szrj 			     basic_block second_bb)
8217*38fd1498Szrj {
8218*38fd1498Szrj   int edge_flags;
8219*38fd1498Szrj 
8220*38fd1498Szrj   /* This is fixing of incoming edge.  */
8221*38fd1498Szrj   /* ??? Which other flags should be specified?  */
8222*38fd1498Szrj   if (BB_PARTITION (first_bb) != BB_PARTITION (rec))
8223*38fd1498Szrj     /* Partition type is the same, if it is "unpartitioned".  */
8224*38fd1498Szrj     edge_flags = EDGE_CROSSING;
8225*38fd1498Szrj   else
8226*38fd1498Szrj     edge_flags = 0;
8227*38fd1498Szrj 
8228*38fd1498Szrj   edge e2 = single_succ_edge (first_bb);
8229*38fd1498Szrj   edge e = make_edge (first_bb, rec, edge_flags);
8230*38fd1498Szrj 
8231*38fd1498Szrj   /* TODO: The actual probability can be determined and is computed as
8232*38fd1498Szrj      'todo_spec' variable in create_check_block_twin and
8233*38fd1498Szrj      in sel-sched.c `check_ds' in create_speculation_check.  */
8234*38fd1498Szrj   e->probability = profile_probability::very_unlikely ();
8235*38fd1498Szrj   rec->count = e->count ();
8236*38fd1498Szrj   e2->probability = e->probability.invert ();
8237*38fd1498Szrj 
8238*38fd1498Szrj   rtx_code_label *label = block_label (second_bb);
8239*38fd1498Szrj   rtx_jump_insn *jump = emit_jump_insn_after (targetm.gen_jump (label),
8240*38fd1498Szrj 					      BB_END (rec));
8241*38fd1498Szrj   JUMP_LABEL (jump) = label;
8242*38fd1498Szrj   LABEL_NUSES (label)++;
8243*38fd1498Szrj 
8244*38fd1498Szrj   if (BB_PARTITION (second_bb) != BB_PARTITION (rec))
8245*38fd1498Szrj     /* Partition type is the same, if it is "unpartitioned".  */
8246*38fd1498Szrj     {
8247*38fd1498Szrj       /* Rewritten from cfgrtl.c.  */
8248*38fd1498Szrj       if (crtl->has_bb_partition && targetm_common.have_named_sections)
8249*38fd1498Szrj 	{
8250*38fd1498Szrj 	  /* We don't need the same note for the check because
8251*38fd1498Szrj 	     any_condjump_p (check) == true.  */
8252*38fd1498Szrj 	  CROSSING_JUMP_P (jump) = 1;
8253*38fd1498Szrj 	}
8254*38fd1498Szrj       edge_flags = EDGE_CROSSING;
8255*38fd1498Szrj     }
8256*38fd1498Szrj   else
8257*38fd1498Szrj     edge_flags = 0;
8258*38fd1498Szrj 
8259*38fd1498Szrj   make_single_succ_edge (rec, second_bb, edge_flags);
8260*38fd1498Szrj   if (dom_info_available_p (CDI_DOMINATORS))
8261*38fd1498Szrj     set_immediate_dominator (CDI_DOMINATORS, rec, first_bb);
8262*38fd1498Szrj }
8263*38fd1498Szrj 
8264*38fd1498Szrj /* This function creates recovery code for INSN.  If MUTATE_P is nonzero,
8265*38fd1498Szrj    INSN is a simple check, that should be converted to branchy one.  */
8266*38fd1498Szrj static void
create_check_block_twin(rtx_insn * insn,bool mutate_p)8267*38fd1498Szrj create_check_block_twin (rtx_insn *insn, bool mutate_p)
8268*38fd1498Szrj {
8269*38fd1498Szrj   basic_block rec;
8270*38fd1498Szrj   rtx_insn *label, *check, *twin;
8271*38fd1498Szrj   rtx check_pat;
8272*38fd1498Szrj   ds_t fs;
8273*38fd1498Szrj   sd_iterator_def sd_it;
8274*38fd1498Szrj   dep_t dep;
8275*38fd1498Szrj   dep_def _new_dep, *new_dep = &_new_dep;
8276*38fd1498Szrj   ds_t todo_spec;
8277*38fd1498Szrj 
8278*38fd1498Szrj   gcc_assert (ORIG_PAT (insn) != NULL_RTX);
8279*38fd1498Szrj 
8280*38fd1498Szrj   if (!mutate_p)
8281*38fd1498Szrj     todo_spec = TODO_SPEC (insn);
8282*38fd1498Szrj   else
8283*38fd1498Szrj     {
8284*38fd1498Szrj       gcc_assert (IS_SPECULATION_SIMPLE_CHECK_P (insn)
8285*38fd1498Szrj 		  && (TODO_SPEC (insn) & SPECULATIVE) == 0);
8286*38fd1498Szrj 
8287*38fd1498Szrj       todo_spec = CHECK_SPEC (insn);
8288*38fd1498Szrj     }
8289*38fd1498Szrj 
8290*38fd1498Szrj   todo_spec &= SPECULATIVE;
8291*38fd1498Szrj 
8292*38fd1498Szrj   /* Create recovery block.  */
8293*38fd1498Szrj   if (mutate_p || targetm.sched.needs_block_p (todo_spec))
8294*38fd1498Szrj     {
8295*38fd1498Szrj       rec = sched_create_recovery_block (NULL);
8296*38fd1498Szrj       label = BB_HEAD (rec);
8297*38fd1498Szrj     }
8298*38fd1498Szrj   else
8299*38fd1498Szrj     {
8300*38fd1498Szrj       rec = EXIT_BLOCK_PTR_FOR_FN (cfun);
8301*38fd1498Szrj       label = NULL;
8302*38fd1498Szrj     }
8303*38fd1498Szrj 
8304*38fd1498Szrj   /* Emit CHECK.  */
8305*38fd1498Szrj   check_pat = targetm.sched.gen_spec_check (insn, label, todo_spec);
8306*38fd1498Szrj 
8307*38fd1498Szrj   if (rec != EXIT_BLOCK_PTR_FOR_FN (cfun))
8308*38fd1498Szrj     {
8309*38fd1498Szrj       /* To have mem_reg alive at the beginning of second_bb,
8310*38fd1498Szrj 	 we emit check BEFORE insn, so insn after splitting
8311*38fd1498Szrj 	 insn will be at the beginning of second_bb, which will
8312*38fd1498Szrj 	 provide us with the correct life information.  */
8313*38fd1498Szrj       check = emit_jump_insn_before (check_pat, insn);
8314*38fd1498Szrj       JUMP_LABEL (check) = label;
8315*38fd1498Szrj       LABEL_NUSES (label)++;
8316*38fd1498Szrj     }
8317*38fd1498Szrj   else
8318*38fd1498Szrj     check = emit_insn_before (check_pat, insn);
8319*38fd1498Szrj 
8320*38fd1498Szrj   /* Extend data structures.  */
8321*38fd1498Szrj   haifa_init_insn (check);
8322*38fd1498Szrj 
8323*38fd1498Szrj   /* CHECK is being added to current region.  Extend ready list.  */
8324*38fd1498Szrj   gcc_assert (sched_ready_n_insns != -1);
8325*38fd1498Szrj   sched_extend_ready_list (sched_ready_n_insns + 1);
8326*38fd1498Szrj 
8327*38fd1498Szrj   if (current_sched_info->add_remove_insn)
8328*38fd1498Szrj     current_sched_info->add_remove_insn (insn, 0);
8329*38fd1498Szrj 
8330*38fd1498Szrj   RECOVERY_BLOCK (check) = rec;
8331*38fd1498Szrj 
8332*38fd1498Szrj   if (sched_verbose && spec_info->dump)
8333*38fd1498Szrj     fprintf (spec_info->dump, ";;\t\tGenerated check insn : %s\n",
8334*38fd1498Szrj              (*current_sched_info->print_insn) (check, 0));
8335*38fd1498Szrj 
8336*38fd1498Szrj   gcc_assert (ORIG_PAT (insn));
8337*38fd1498Szrj 
8338*38fd1498Szrj   /* Initialize TWIN (twin is a duplicate of original instruction
8339*38fd1498Szrj      in the recovery block).  */
8340*38fd1498Szrj   if (rec != EXIT_BLOCK_PTR_FOR_FN (cfun))
8341*38fd1498Szrj     {
8342*38fd1498Szrj       sd_iterator_def sd_it;
8343*38fd1498Szrj       dep_t dep;
8344*38fd1498Szrj 
8345*38fd1498Szrj       FOR_EACH_DEP (insn, SD_LIST_RES_BACK, sd_it, dep)
8346*38fd1498Szrj 	if ((DEP_STATUS (dep) & DEP_OUTPUT) != 0)
8347*38fd1498Szrj 	  {
8348*38fd1498Szrj 	    struct _dep _dep2, *dep2 = &_dep2;
8349*38fd1498Szrj 
8350*38fd1498Szrj 	    init_dep (dep2, DEP_PRO (dep), check, REG_DEP_TRUE);
8351*38fd1498Szrj 
8352*38fd1498Szrj 	    sd_add_dep (dep2, true);
8353*38fd1498Szrj 	  }
8354*38fd1498Szrj 
8355*38fd1498Szrj       twin = emit_insn_after (ORIG_PAT (insn), BB_END (rec));
8356*38fd1498Szrj       haifa_init_insn (twin);
8357*38fd1498Szrj 
8358*38fd1498Szrj       if (sched_verbose && spec_info->dump)
8359*38fd1498Szrj 	/* INSN_BB (insn) isn't determined for twin insns yet.
8360*38fd1498Szrj 	   So we can't use current_sched_info->print_insn.  */
8361*38fd1498Szrj 	fprintf (spec_info->dump, ";;\t\tGenerated twin insn : %d/rec%d\n",
8362*38fd1498Szrj 		 INSN_UID (twin), rec->index);
8363*38fd1498Szrj     }
8364*38fd1498Szrj   else
8365*38fd1498Szrj     {
8366*38fd1498Szrj       ORIG_PAT (check) = ORIG_PAT (insn);
8367*38fd1498Szrj       HAS_INTERNAL_DEP (check) = 1;
8368*38fd1498Szrj       twin = check;
8369*38fd1498Szrj       /* ??? We probably should change all OUTPUT dependencies to
8370*38fd1498Szrj 	 (TRUE | OUTPUT).  */
8371*38fd1498Szrj     }
8372*38fd1498Szrj 
8373*38fd1498Szrj   /* Copy all resolved back dependencies of INSN to TWIN.  This will
8374*38fd1498Szrj      provide correct value for INSN_TICK (TWIN).  */
8375*38fd1498Szrj   sd_copy_back_deps (twin, insn, true);
8376*38fd1498Szrj 
8377*38fd1498Szrj   if (rec != EXIT_BLOCK_PTR_FOR_FN (cfun))
8378*38fd1498Szrj     /* In case of branchy check, fix CFG.  */
8379*38fd1498Szrj     {
8380*38fd1498Szrj       basic_block first_bb, second_bb;
8381*38fd1498Szrj       rtx_insn *jump;
8382*38fd1498Szrj 
8383*38fd1498Szrj       first_bb = BLOCK_FOR_INSN (check);
8384*38fd1498Szrj       second_bb = sched_split_block (first_bb, check);
8385*38fd1498Szrj 
8386*38fd1498Szrj       sched_create_recovery_edges (first_bb, rec, second_bb);
8387*38fd1498Szrj 
8388*38fd1498Szrj       sched_init_only_bb (second_bb, first_bb);
8389*38fd1498Szrj       sched_init_only_bb (rec, EXIT_BLOCK_PTR_FOR_FN (cfun));
8390*38fd1498Szrj 
8391*38fd1498Szrj       jump = BB_END (rec);
8392*38fd1498Szrj       haifa_init_insn (jump);
8393*38fd1498Szrj     }
8394*38fd1498Szrj 
8395*38fd1498Szrj   /* Move backward dependences from INSN to CHECK and
8396*38fd1498Szrj      move forward dependences from INSN to TWIN.  */
8397*38fd1498Szrj 
8398*38fd1498Szrj   /* First, create dependencies between INSN's producers and CHECK & TWIN.  */
8399*38fd1498Szrj   FOR_EACH_DEP (insn, SD_LIST_BACK, sd_it, dep)
8400*38fd1498Szrj     {
8401*38fd1498Szrj       rtx_insn *pro = DEP_PRO (dep);
8402*38fd1498Szrj       ds_t ds;
8403*38fd1498Szrj 
8404*38fd1498Szrj       /* If BEGIN_DATA: [insn ~~TRUE~~> producer]:
8405*38fd1498Szrj 	 check --TRUE--> producer  ??? or ANTI ???
8406*38fd1498Szrj 	 twin  --TRUE--> producer
8407*38fd1498Szrj 	 twin  --ANTI--> check
8408*38fd1498Szrj 
8409*38fd1498Szrj 	 If BEGIN_CONTROL: [insn ~~ANTI~~> producer]:
8410*38fd1498Szrj 	 check --ANTI--> producer
8411*38fd1498Szrj 	 twin  --ANTI--> producer
8412*38fd1498Szrj 	 twin  --ANTI--> check
8413*38fd1498Szrj 
8414*38fd1498Szrj 	 If BE_IN_SPEC: [insn ~~TRUE~~> producer]:
8415*38fd1498Szrj 	 check ~~TRUE~~> producer
8416*38fd1498Szrj 	 twin  ~~TRUE~~> producer
8417*38fd1498Szrj 	 twin  --ANTI--> check  */
8418*38fd1498Szrj 
8419*38fd1498Szrj       ds = DEP_STATUS (dep);
8420*38fd1498Szrj 
8421*38fd1498Szrj       if (ds & BEGIN_SPEC)
8422*38fd1498Szrj 	{
8423*38fd1498Szrj 	  gcc_assert (!mutate_p);
8424*38fd1498Szrj 	  ds &= ~BEGIN_SPEC;
8425*38fd1498Szrj 	}
8426*38fd1498Szrj 
8427*38fd1498Szrj       init_dep_1 (new_dep, pro, check, DEP_TYPE (dep), ds);
8428*38fd1498Szrj       sd_add_dep (new_dep, false);
8429*38fd1498Szrj 
8430*38fd1498Szrj       if (rec != EXIT_BLOCK_PTR_FOR_FN (cfun))
8431*38fd1498Szrj 	{
8432*38fd1498Szrj 	  DEP_CON (new_dep) = twin;
8433*38fd1498Szrj 	  sd_add_dep (new_dep, false);
8434*38fd1498Szrj 	}
8435*38fd1498Szrj     }
8436*38fd1498Szrj 
8437*38fd1498Szrj   /* Second, remove backward dependencies of INSN.  */
8438*38fd1498Szrj   for (sd_it = sd_iterator_start (insn, SD_LIST_SPEC_BACK);
8439*38fd1498Szrj        sd_iterator_cond (&sd_it, &dep);)
8440*38fd1498Szrj     {
8441*38fd1498Szrj       if ((DEP_STATUS (dep) & BEGIN_SPEC)
8442*38fd1498Szrj 	  || mutate_p)
8443*38fd1498Szrj 	/* We can delete this dep because we overcome it with
8444*38fd1498Szrj 	   BEGIN_SPECULATION.  */
8445*38fd1498Szrj 	sd_delete_dep (sd_it);
8446*38fd1498Szrj       else
8447*38fd1498Szrj 	sd_iterator_next (&sd_it);
8448*38fd1498Szrj     }
8449*38fd1498Szrj 
8450*38fd1498Szrj   /* Future Speculations.  Determine what BE_IN speculations will be like.  */
8451*38fd1498Szrj   fs = 0;
8452*38fd1498Szrj 
8453*38fd1498Szrj   /* Fields (DONE_SPEC (x) & BEGIN_SPEC) and CHECK_SPEC (x) are set only
8454*38fd1498Szrj      here.  */
8455*38fd1498Szrj 
8456*38fd1498Szrj   gcc_assert (!DONE_SPEC (insn));
8457*38fd1498Szrj 
8458*38fd1498Szrj   if (!mutate_p)
8459*38fd1498Szrj     {
8460*38fd1498Szrj       ds_t ts = TODO_SPEC (insn);
8461*38fd1498Szrj 
8462*38fd1498Szrj       DONE_SPEC (insn) = ts & BEGIN_SPEC;
8463*38fd1498Szrj       CHECK_SPEC (check) = ts & BEGIN_SPEC;
8464*38fd1498Szrj 
8465*38fd1498Szrj       /* Luckiness of future speculations solely depends upon initial
8466*38fd1498Szrj 	 BEGIN speculation.  */
8467*38fd1498Szrj       if (ts & BEGIN_DATA)
8468*38fd1498Szrj 	fs = set_dep_weak (fs, BE_IN_DATA, get_dep_weak (ts, BEGIN_DATA));
8469*38fd1498Szrj       if (ts & BEGIN_CONTROL)
8470*38fd1498Szrj 	fs = set_dep_weak (fs, BE_IN_CONTROL,
8471*38fd1498Szrj 			   get_dep_weak (ts, BEGIN_CONTROL));
8472*38fd1498Szrj     }
8473*38fd1498Szrj   else
8474*38fd1498Szrj     CHECK_SPEC (check) = CHECK_SPEC (insn);
8475*38fd1498Szrj 
8476*38fd1498Szrj   /* Future speculations: call the helper.  */
8477*38fd1498Szrj   process_insn_forw_deps_be_in_spec (insn, twin, fs);
8478*38fd1498Szrj 
8479*38fd1498Szrj   if (rec != EXIT_BLOCK_PTR_FOR_FN (cfun))
8480*38fd1498Szrj     {
8481*38fd1498Szrj       /* Which types of dependencies should we use here is,
8482*38fd1498Szrj 	 generally, machine-dependent question...  But, for now,
8483*38fd1498Szrj 	 it is not.  */
8484*38fd1498Szrj 
8485*38fd1498Szrj       if (!mutate_p)
8486*38fd1498Szrj 	{
8487*38fd1498Szrj 	  init_dep (new_dep, insn, check, REG_DEP_TRUE);
8488*38fd1498Szrj 	  sd_add_dep (new_dep, false);
8489*38fd1498Szrj 
8490*38fd1498Szrj 	  init_dep (new_dep, insn, twin, REG_DEP_OUTPUT);
8491*38fd1498Szrj 	  sd_add_dep (new_dep, false);
8492*38fd1498Szrj 	}
8493*38fd1498Szrj       else
8494*38fd1498Szrj 	{
8495*38fd1498Szrj 	  if (spec_info->dump)
8496*38fd1498Szrj 	    fprintf (spec_info->dump, ";;\t\tRemoved simple check : %s\n",
8497*38fd1498Szrj 		     (*current_sched_info->print_insn) (insn, 0));
8498*38fd1498Szrj 
8499*38fd1498Szrj 	  /* Remove all dependencies of the INSN.  */
8500*38fd1498Szrj 	  {
8501*38fd1498Szrj 	    sd_it = sd_iterator_start (insn, (SD_LIST_FORW
8502*38fd1498Szrj 					      | SD_LIST_BACK
8503*38fd1498Szrj 					      | SD_LIST_RES_BACK));
8504*38fd1498Szrj 	    while (sd_iterator_cond (&sd_it, &dep))
8505*38fd1498Szrj 	      sd_delete_dep (sd_it);
8506*38fd1498Szrj 	  }
8507*38fd1498Szrj 
8508*38fd1498Szrj 	  /* If former check (INSN) already was moved to the ready (or queue)
8509*38fd1498Szrj 	     list, add new check (CHECK) there too.  */
8510*38fd1498Szrj 	  if (QUEUE_INDEX (insn) != QUEUE_NOWHERE)
8511*38fd1498Szrj 	    try_ready (check);
8512*38fd1498Szrj 
8513*38fd1498Szrj 	  /* Remove old check from instruction stream and free its
8514*38fd1498Szrj 	     data.  */
8515*38fd1498Szrj 	  sched_remove_insn (insn);
8516*38fd1498Szrj 	}
8517*38fd1498Szrj 
8518*38fd1498Szrj       init_dep (new_dep, check, twin, REG_DEP_ANTI);
8519*38fd1498Szrj       sd_add_dep (new_dep, false);
8520*38fd1498Szrj     }
8521*38fd1498Szrj   else
8522*38fd1498Szrj     {
8523*38fd1498Szrj       init_dep_1 (new_dep, insn, check, REG_DEP_TRUE, DEP_TRUE | DEP_OUTPUT);
8524*38fd1498Szrj       sd_add_dep (new_dep, false);
8525*38fd1498Szrj     }
8526*38fd1498Szrj 
8527*38fd1498Szrj   if (!mutate_p)
8528*38fd1498Szrj     /* Fix priorities.  If MUTATE_P is nonzero, this is not necessary,
8529*38fd1498Szrj        because it'll be done later in add_to_speculative_block.  */
8530*38fd1498Szrj     {
8531*38fd1498Szrj       auto_vec<rtx_insn *> priorities_roots;
8532*38fd1498Szrj 
8533*38fd1498Szrj       clear_priorities (twin, &priorities_roots);
8534*38fd1498Szrj       calc_priorities (priorities_roots);
8535*38fd1498Szrj     }
8536*38fd1498Szrj }
8537*38fd1498Szrj 
8538*38fd1498Szrj /* Removes dependency between instructions in the recovery block REC
8539*38fd1498Szrj    and usual region instructions.  It keeps inner dependences so it
8540*38fd1498Szrj    won't be necessary to recompute them.  */
8541*38fd1498Szrj static void
fix_recovery_deps(basic_block rec)8542*38fd1498Szrj fix_recovery_deps (basic_block rec)
8543*38fd1498Szrj {
8544*38fd1498Szrj   rtx_insn *note, *insn, *jump;
8545*38fd1498Szrj   auto_vec<rtx_insn *, 10> ready_list;
8546*38fd1498Szrj   auto_bitmap in_ready;
8547*38fd1498Szrj 
8548*38fd1498Szrj   /* NOTE - a basic block note.  */
8549*38fd1498Szrj   note = NEXT_INSN (BB_HEAD (rec));
8550*38fd1498Szrj   gcc_assert (NOTE_INSN_BASIC_BLOCK_P (note));
8551*38fd1498Szrj   insn = BB_END (rec);
8552*38fd1498Szrj   gcc_assert (JUMP_P (insn));
8553*38fd1498Szrj   insn = PREV_INSN (insn);
8554*38fd1498Szrj 
8555*38fd1498Szrj   do
8556*38fd1498Szrj     {
8557*38fd1498Szrj       sd_iterator_def sd_it;
8558*38fd1498Szrj       dep_t dep;
8559*38fd1498Szrj 
8560*38fd1498Szrj       for (sd_it = sd_iterator_start (insn, SD_LIST_FORW);
8561*38fd1498Szrj 	   sd_iterator_cond (&sd_it, &dep);)
8562*38fd1498Szrj 	{
8563*38fd1498Szrj 	  rtx_insn *consumer = DEP_CON (dep);
8564*38fd1498Szrj 
8565*38fd1498Szrj 	  if (BLOCK_FOR_INSN (consumer) != rec)
8566*38fd1498Szrj 	    {
8567*38fd1498Szrj 	      sd_delete_dep (sd_it);
8568*38fd1498Szrj 
8569*38fd1498Szrj 	      if (bitmap_set_bit (in_ready, INSN_LUID (consumer)))
8570*38fd1498Szrj 		ready_list.safe_push (consumer);
8571*38fd1498Szrj 	    }
8572*38fd1498Szrj 	  else
8573*38fd1498Szrj 	    {
8574*38fd1498Szrj 	      gcc_assert ((DEP_STATUS (dep) & DEP_TYPES) == DEP_TRUE);
8575*38fd1498Szrj 
8576*38fd1498Szrj 	      sd_iterator_next (&sd_it);
8577*38fd1498Szrj 	    }
8578*38fd1498Szrj 	}
8579*38fd1498Szrj 
8580*38fd1498Szrj       insn = PREV_INSN (insn);
8581*38fd1498Szrj     }
8582*38fd1498Szrj   while (insn != note);
8583*38fd1498Szrj 
8584*38fd1498Szrj   /* Try to add instructions to the ready or queue list.  */
8585*38fd1498Szrj   unsigned int i;
8586*38fd1498Szrj   rtx_insn *temp;
8587*38fd1498Szrj   FOR_EACH_VEC_ELT_REVERSE (ready_list, i, temp)
8588*38fd1498Szrj     try_ready (temp);
8589*38fd1498Szrj 
8590*38fd1498Szrj   /* Fixing jump's dependences.  */
8591*38fd1498Szrj   insn = BB_HEAD (rec);
8592*38fd1498Szrj   jump = BB_END (rec);
8593*38fd1498Szrj 
8594*38fd1498Szrj   gcc_assert (LABEL_P (insn));
8595*38fd1498Szrj   insn = NEXT_INSN (insn);
8596*38fd1498Szrj 
8597*38fd1498Szrj   gcc_assert (NOTE_INSN_BASIC_BLOCK_P (insn));
8598*38fd1498Szrj   add_jump_dependencies (insn, jump);
8599*38fd1498Szrj }
8600*38fd1498Szrj 
8601*38fd1498Szrj /* Change pattern of INSN to NEW_PAT.  Invalidate cached haifa
8602*38fd1498Szrj    instruction data.  */
8603*38fd1498Szrj static bool
haifa_change_pattern(rtx_insn * insn,rtx new_pat)8604*38fd1498Szrj haifa_change_pattern (rtx_insn *insn, rtx new_pat)
8605*38fd1498Szrj {
8606*38fd1498Szrj   int t;
8607*38fd1498Szrj 
8608*38fd1498Szrj   t = validate_change (insn, &PATTERN (insn), new_pat, 0);
8609*38fd1498Szrj   if (!t)
8610*38fd1498Szrj     return false;
8611*38fd1498Szrj 
8612*38fd1498Szrj   update_insn_after_change (insn);
8613*38fd1498Szrj   return true;
8614*38fd1498Szrj }
8615*38fd1498Szrj 
8616*38fd1498Szrj /* -1 - can't speculate,
8617*38fd1498Szrj    0 - for speculation with REQUEST mode it is OK to use
8618*38fd1498Szrj    current instruction pattern,
8619*38fd1498Szrj    1 - need to change pattern for *NEW_PAT to be speculative.  */
8620*38fd1498Szrj int
sched_speculate_insn(rtx_insn * insn,ds_t request,rtx * new_pat)8621*38fd1498Szrj sched_speculate_insn (rtx_insn *insn, ds_t request, rtx *new_pat)
8622*38fd1498Szrj {
8623*38fd1498Szrj   gcc_assert (current_sched_info->flags & DO_SPECULATION
8624*38fd1498Szrj               && (request & SPECULATIVE)
8625*38fd1498Szrj 	      && sched_insn_is_legitimate_for_speculation_p (insn, request));
8626*38fd1498Szrj 
8627*38fd1498Szrj   if ((request & spec_info->mask) != request)
8628*38fd1498Szrj     return -1;
8629*38fd1498Szrj 
8630*38fd1498Szrj   if (request & BE_IN_SPEC
8631*38fd1498Szrj       && !(request & BEGIN_SPEC))
8632*38fd1498Szrj     return 0;
8633*38fd1498Szrj 
8634*38fd1498Szrj   return targetm.sched.speculate_insn (insn, request, new_pat);
8635*38fd1498Szrj }
8636*38fd1498Szrj 
8637*38fd1498Szrj static int
haifa_speculate_insn(rtx_insn * insn,ds_t request,rtx * new_pat)8638*38fd1498Szrj haifa_speculate_insn (rtx_insn *insn, ds_t request, rtx *new_pat)
8639*38fd1498Szrj {
8640*38fd1498Szrj   gcc_assert (sched_deps_info->generate_spec_deps
8641*38fd1498Szrj 	      && !IS_SPECULATION_CHECK_P (insn));
8642*38fd1498Szrj 
8643*38fd1498Szrj   if (HAS_INTERNAL_DEP (insn)
8644*38fd1498Szrj       || SCHED_GROUP_P (insn))
8645*38fd1498Szrj     return -1;
8646*38fd1498Szrj 
8647*38fd1498Szrj   return sched_speculate_insn (insn, request, new_pat);
8648*38fd1498Szrj }
8649*38fd1498Szrj 
8650*38fd1498Szrj /* Print some information about block BB, which starts with HEAD and
8651*38fd1498Szrj    ends with TAIL, before scheduling it.
8652*38fd1498Szrj    I is zero, if scheduler is about to start with the fresh ebb.  */
8653*38fd1498Szrj static void
dump_new_block_header(int i,basic_block bb,rtx_insn * head,rtx_insn * tail)8654*38fd1498Szrj dump_new_block_header (int i, basic_block bb, rtx_insn *head, rtx_insn *tail)
8655*38fd1498Szrj {
8656*38fd1498Szrj   if (!i)
8657*38fd1498Szrj     fprintf (sched_dump,
8658*38fd1498Szrj 	     ";;   ======================================================\n");
8659*38fd1498Szrj   else
8660*38fd1498Szrj     fprintf (sched_dump,
8661*38fd1498Szrj 	     ";;   =====================ADVANCING TO=====================\n");
8662*38fd1498Szrj   fprintf (sched_dump,
8663*38fd1498Szrj 	   ";;   -- basic block %d from %d to %d -- %s reload\n",
8664*38fd1498Szrj 	   bb->index, INSN_UID (head), INSN_UID (tail),
8665*38fd1498Szrj 	   (reload_completed ? "after" : "before"));
8666*38fd1498Szrj   fprintf (sched_dump,
8667*38fd1498Szrj 	   ";;   ======================================================\n");
8668*38fd1498Szrj   fprintf (sched_dump, "\n");
8669*38fd1498Szrj }
8670*38fd1498Szrj 
8671*38fd1498Szrj /* Unlink basic block notes and labels and saves them, so they
8672*38fd1498Szrj    can be easily restored.  We unlink basic block notes in EBB to
8673*38fd1498Szrj    provide back-compatibility with the previous code, as target backends
8674*38fd1498Szrj    assume, that there'll be only instructions between
8675*38fd1498Szrj    current_sched_info->{head and tail}.  We restore these notes as soon
8676*38fd1498Szrj    as we can.
8677*38fd1498Szrj    FIRST (LAST) is the first (last) basic block in the ebb.
8678*38fd1498Szrj    NB: In usual case (FIRST == LAST) nothing is really done.  */
8679*38fd1498Szrj void
unlink_bb_notes(basic_block first,basic_block last)8680*38fd1498Szrj unlink_bb_notes (basic_block first, basic_block last)
8681*38fd1498Szrj {
8682*38fd1498Szrj   /* We DON'T unlink basic block notes of the first block in the ebb.  */
8683*38fd1498Szrj   if (first == last)
8684*38fd1498Szrj     return;
8685*38fd1498Szrj 
8686*38fd1498Szrj   bb_header = XNEWVEC (rtx_insn *, last_basic_block_for_fn (cfun));
8687*38fd1498Szrj 
8688*38fd1498Szrj   /* Make a sentinel.  */
8689*38fd1498Szrj   if (last->next_bb != EXIT_BLOCK_PTR_FOR_FN (cfun))
8690*38fd1498Szrj     bb_header[last->next_bb->index] = 0;
8691*38fd1498Szrj 
8692*38fd1498Szrj   first = first->next_bb;
8693*38fd1498Szrj   do
8694*38fd1498Szrj     {
8695*38fd1498Szrj       rtx_insn *prev, *label, *note, *next;
8696*38fd1498Szrj 
8697*38fd1498Szrj       label = BB_HEAD (last);
8698*38fd1498Szrj       if (LABEL_P (label))
8699*38fd1498Szrj 	note = NEXT_INSN (label);
8700*38fd1498Szrj       else
8701*38fd1498Szrj 	note = label;
8702*38fd1498Szrj       gcc_assert (NOTE_INSN_BASIC_BLOCK_P (note));
8703*38fd1498Szrj 
8704*38fd1498Szrj       prev = PREV_INSN (label);
8705*38fd1498Szrj       next = NEXT_INSN (note);
8706*38fd1498Szrj       gcc_assert (prev && next);
8707*38fd1498Szrj 
8708*38fd1498Szrj       SET_NEXT_INSN (prev) = next;
8709*38fd1498Szrj       SET_PREV_INSN (next) = prev;
8710*38fd1498Szrj 
8711*38fd1498Szrj       bb_header[last->index] = label;
8712*38fd1498Szrj 
8713*38fd1498Szrj       if (last == first)
8714*38fd1498Szrj 	break;
8715*38fd1498Szrj 
8716*38fd1498Szrj       last = last->prev_bb;
8717*38fd1498Szrj     }
8718*38fd1498Szrj   while (1);
8719*38fd1498Szrj }
8720*38fd1498Szrj 
8721*38fd1498Szrj /* Restore basic block notes.
8722*38fd1498Szrj    FIRST is the first basic block in the ebb.  */
8723*38fd1498Szrj static void
restore_bb_notes(basic_block first)8724*38fd1498Szrj restore_bb_notes (basic_block first)
8725*38fd1498Szrj {
8726*38fd1498Szrj   if (!bb_header)
8727*38fd1498Szrj     return;
8728*38fd1498Szrj 
8729*38fd1498Szrj   /* We DON'T unlink basic block notes of the first block in the ebb.  */
8730*38fd1498Szrj   first = first->next_bb;
8731*38fd1498Szrj   /* Remember: FIRST is actually a second basic block in the ebb.  */
8732*38fd1498Szrj 
8733*38fd1498Szrj   while (first != EXIT_BLOCK_PTR_FOR_FN (cfun)
8734*38fd1498Szrj 	 && bb_header[first->index])
8735*38fd1498Szrj     {
8736*38fd1498Szrj       rtx_insn *prev, *label, *note, *next;
8737*38fd1498Szrj 
8738*38fd1498Szrj       label = bb_header[first->index];
8739*38fd1498Szrj       prev = PREV_INSN (label);
8740*38fd1498Szrj       next = NEXT_INSN (prev);
8741*38fd1498Szrj 
8742*38fd1498Szrj       if (LABEL_P (label))
8743*38fd1498Szrj 	note = NEXT_INSN (label);
8744*38fd1498Szrj       else
8745*38fd1498Szrj 	note = label;
8746*38fd1498Szrj       gcc_assert (NOTE_INSN_BASIC_BLOCK_P (note));
8747*38fd1498Szrj 
8748*38fd1498Szrj       bb_header[first->index] = 0;
8749*38fd1498Szrj 
8750*38fd1498Szrj       SET_NEXT_INSN (prev) = label;
8751*38fd1498Szrj       SET_NEXT_INSN (note) = next;
8752*38fd1498Szrj       SET_PREV_INSN (next) = note;
8753*38fd1498Szrj 
8754*38fd1498Szrj       first = first->next_bb;
8755*38fd1498Szrj     }
8756*38fd1498Szrj 
8757*38fd1498Szrj   free (bb_header);
8758*38fd1498Szrj   bb_header = 0;
8759*38fd1498Szrj }
8760*38fd1498Szrj 
8761*38fd1498Szrj /* Helper function.
8762*38fd1498Szrj    Fix CFG after both in- and inter-block movement of
8763*38fd1498Szrj    control_flow_insn_p JUMP.  */
8764*38fd1498Szrj static void
fix_jump_move(rtx_insn * jump)8765*38fd1498Szrj fix_jump_move (rtx_insn *jump)
8766*38fd1498Szrj {
8767*38fd1498Szrj   basic_block bb, jump_bb, jump_bb_next;
8768*38fd1498Szrj 
8769*38fd1498Szrj   bb = BLOCK_FOR_INSN (PREV_INSN (jump));
8770*38fd1498Szrj   jump_bb = BLOCK_FOR_INSN (jump);
8771*38fd1498Szrj   jump_bb_next = jump_bb->next_bb;
8772*38fd1498Szrj 
8773*38fd1498Szrj   gcc_assert (common_sched_info->sched_pass_id == SCHED_EBB_PASS
8774*38fd1498Szrj 	      || IS_SPECULATION_BRANCHY_CHECK_P (jump));
8775*38fd1498Szrj 
8776*38fd1498Szrj   if (!NOTE_INSN_BASIC_BLOCK_P (BB_END (jump_bb_next)))
8777*38fd1498Szrj     /* if jump_bb_next is not empty.  */
8778*38fd1498Szrj     BB_END (jump_bb) = BB_END (jump_bb_next);
8779*38fd1498Szrj 
8780*38fd1498Szrj   if (BB_END (bb) != PREV_INSN (jump))
8781*38fd1498Szrj     /* Then there are instruction after jump that should be placed
8782*38fd1498Szrj        to jump_bb_next.  */
8783*38fd1498Szrj     BB_END (jump_bb_next) = BB_END (bb);
8784*38fd1498Szrj   else
8785*38fd1498Szrj     /* Otherwise jump_bb_next is empty.  */
8786*38fd1498Szrj     BB_END (jump_bb_next) = NEXT_INSN (BB_HEAD (jump_bb_next));
8787*38fd1498Szrj 
8788*38fd1498Szrj   /* To make assertion in move_insn happy.  */
8789*38fd1498Szrj   BB_END (bb) = PREV_INSN (jump);
8790*38fd1498Szrj 
8791*38fd1498Szrj   update_bb_for_insn (jump_bb_next);
8792*38fd1498Szrj }
8793*38fd1498Szrj 
8794*38fd1498Szrj /* Fix CFG after interblock movement of control_flow_insn_p JUMP.  */
8795*38fd1498Szrj static void
move_block_after_check(rtx_insn * jump)8796*38fd1498Szrj move_block_after_check (rtx_insn *jump)
8797*38fd1498Szrj {
8798*38fd1498Szrj   basic_block bb, jump_bb, jump_bb_next;
8799*38fd1498Szrj   vec<edge, va_gc> *t;
8800*38fd1498Szrj 
8801*38fd1498Szrj   bb = BLOCK_FOR_INSN (PREV_INSN (jump));
8802*38fd1498Szrj   jump_bb = BLOCK_FOR_INSN (jump);
8803*38fd1498Szrj   jump_bb_next = jump_bb->next_bb;
8804*38fd1498Szrj 
8805*38fd1498Szrj   update_bb_for_insn (jump_bb);
8806*38fd1498Szrj 
8807*38fd1498Szrj   gcc_assert (IS_SPECULATION_CHECK_P (jump)
8808*38fd1498Szrj 	      || IS_SPECULATION_CHECK_P (BB_END (jump_bb_next)));
8809*38fd1498Szrj 
8810*38fd1498Szrj   unlink_block (jump_bb_next);
8811*38fd1498Szrj   link_block (jump_bb_next, bb);
8812*38fd1498Szrj 
8813*38fd1498Szrj   t = bb->succs;
8814*38fd1498Szrj   bb->succs = 0;
8815*38fd1498Szrj   move_succs (&(jump_bb->succs), bb);
8816*38fd1498Szrj   move_succs (&(jump_bb_next->succs), jump_bb);
8817*38fd1498Szrj   move_succs (&t, jump_bb_next);
8818*38fd1498Szrj 
8819*38fd1498Szrj   df_mark_solutions_dirty ();
8820*38fd1498Szrj 
8821*38fd1498Szrj   common_sched_info->fix_recovery_cfg
8822*38fd1498Szrj     (bb->index, jump_bb->index, jump_bb_next->index);
8823*38fd1498Szrj }
8824*38fd1498Szrj 
8825*38fd1498Szrj /* Helper function for move_block_after_check.
8826*38fd1498Szrj    This functions attaches edge vector pointed to by SUCCSP to
8827*38fd1498Szrj    block TO.  */
8828*38fd1498Szrj static void
move_succs(vec<edge,va_gc> ** succsp,basic_block to)8829*38fd1498Szrj move_succs (vec<edge, va_gc> **succsp, basic_block to)
8830*38fd1498Szrj {
8831*38fd1498Szrj   edge e;
8832*38fd1498Szrj   edge_iterator ei;
8833*38fd1498Szrj 
8834*38fd1498Szrj   gcc_assert (to->succs == 0);
8835*38fd1498Szrj 
8836*38fd1498Szrj   to->succs = *succsp;
8837*38fd1498Szrj 
8838*38fd1498Szrj   FOR_EACH_EDGE (e, ei, to->succs)
8839*38fd1498Szrj     e->src = to;
8840*38fd1498Szrj 
8841*38fd1498Szrj   *succsp = 0;
8842*38fd1498Szrj }
8843*38fd1498Szrj 
8844*38fd1498Szrj /* Remove INSN from the instruction stream.
8845*38fd1498Szrj    INSN should have any dependencies.  */
8846*38fd1498Szrj static void
sched_remove_insn(rtx_insn * insn)8847*38fd1498Szrj sched_remove_insn (rtx_insn *insn)
8848*38fd1498Szrj {
8849*38fd1498Szrj   sd_finish_insn (insn);
8850*38fd1498Szrj 
8851*38fd1498Szrj   change_queue_index (insn, QUEUE_NOWHERE);
8852*38fd1498Szrj   current_sched_info->add_remove_insn (insn, 1);
8853*38fd1498Szrj   delete_insn (insn);
8854*38fd1498Szrj }
8855*38fd1498Szrj 
8856*38fd1498Szrj /* Clear priorities of all instructions, that are forward dependent on INSN.
8857*38fd1498Szrj    Store in vector pointed to by ROOTS_PTR insns on which priority () should
8858*38fd1498Szrj    be invoked to initialize all cleared priorities.  */
8859*38fd1498Szrj static void
clear_priorities(rtx_insn * insn,rtx_vec_t * roots_ptr)8860*38fd1498Szrj clear_priorities (rtx_insn *insn, rtx_vec_t *roots_ptr)
8861*38fd1498Szrj {
8862*38fd1498Szrj   sd_iterator_def sd_it;
8863*38fd1498Szrj   dep_t dep;
8864*38fd1498Szrj   bool insn_is_root_p = true;
8865*38fd1498Szrj 
8866*38fd1498Szrj   gcc_assert (QUEUE_INDEX (insn) != QUEUE_SCHEDULED);
8867*38fd1498Szrj 
8868*38fd1498Szrj   FOR_EACH_DEP (insn, SD_LIST_BACK, sd_it, dep)
8869*38fd1498Szrj     {
8870*38fd1498Szrj       rtx_insn *pro = DEP_PRO (dep);
8871*38fd1498Szrj 
8872*38fd1498Szrj       if (INSN_PRIORITY_STATUS (pro) >= 0
8873*38fd1498Szrj 	  && QUEUE_INDEX (insn) != QUEUE_SCHEDULED)
8874*38fd1498Szrj 	{
8875*38fd1498Szrj 	  /* If DEP doesn't contribute to priority then INSN itself should
8876*38fd1498Szrj 	     be added to priority roots.  */
8877*38fd1498Szrj 	  if (contributes_to_priority_p (dep))
8878*38fd1498Szrj 	    insn_is_root_p = false;
8879*38fd1498Szrj 
8880*38fd1498Szrj 	  INSN_PRIORITY_STATUS (pro) = -1;
8881*38fd1498Szrj 	  clear_priorities (pro, roots_ptr);
8882*38fd1498Szrj 	}
8883*38fd1498Szrj     }
8884*38fd1498Szrj 
8885*38fd1498Szrj   if (insn_is_root_p)
8886*38fd1498Szrj     roots_ptr->safe_push (insn);
8887*38fd1498Szrj }
8888*38fd1498Szrj 
8889*38fd1498Szrj /* Recompute priorities of instructions, whose priorities might have been
8890*38fd1498Szrj    changed.  ROOTS is a vector of instructions whose priority computation will
8891*38fd1498Szrj    trigger initialization of all cleared priorities.  */
8892*38fd1498Szrj static void
calc_priorities(rtx_vec_t roots)8893*38fd1498Szrj calc_priorities (rtx_vec_t roots)
8894*38fd1498Szrj {
8895*38fd1498Szrj   int i;
8896*38fd1498Szrj   rtx_insn *insn;
8897*38fd1498Szrj 
8898*38fd1498Szrj   FOR_EACH_VEC_ELT (roots, i, insn)
8899*38fd1498Szrj     priority (insn);
8900*38fd1498Szrj }
8901*38fd1498Szrj 
8902*38fd1498Szrj 
8903*38fd1498Szrj /* Add dependences between JUMP and other instructions in the recovery
8904*38fd1498Szrj    block.  INSN is the first insn the recovery block.  */
8905*38fd1498Szrj static void
add_jump_dependencies(rtx_insn * insn,rtx_insn * jump)8906*38fd1498Szrj add_jump_dependencies (rtx_insn *insn, rtx_insn *jump)
8907*38fd1498Szrj {
8908*38fd1498Szrj   do
8909*38fd1498Szrj     {
8910*38fd1498Szrj       insn = NEXT_INSN (insn);
8911*38fd1498Szrj       if (insn == jump)
8912*38fd1498Szrj 	break;
8913*38fd1498Szrj 
8914*38fd1498Szrj       if (dep_list_size (insn, SD_LIST_FORW) == 0)
8915*38fd1498Szrj 	{
8916*38fd1498Szrj 	  dep_def _new_dep, *new_dep = &_new_dep;
8917*38fd1498Szrj 
8918*38fd1498Szrj 	  init_dep (new_dep, insn, jump, REG_DEP_ANTI);
8919*38fd1498Szrj 	  sd_add_dep (new_dep, false);
8920*38fd1498Szrj 	}
8921*38fd1498Szrj     }
8922*38fd1498Szrj   while (1);
8923*38fd1498Szrj 
8924*38fd1498Szrj   gcc_assert (!sd_lists_empty_p (jump, SD_LIST_BACK));
8925*38fd1498Szrj }
8926*38fd1498Szrj 
8927*38fd1498Szrj /* Extend data structures for logical insn UID.  */
8928*38fd1498Szrj void
sched_extend_luids(void)8929*38fd1498Szrj sched_extend_luids (void)
8930*38fd1498Szrj {
8931*38fd1498Szrj   int new_luids_max_uid = get_max_uid () + 1;
8932*38fd1498Szrj 
8933*38fd1498Szrj   sched_luids.safe_grow_cleared (new_luids_max_uid);
8934*38fd1498Szrj }
8935*38fd1498Szrj 
8936*38fd1498Szrj /* Initialize LUID for INSN.  */
8937*38fd1498Szrj void
sched_init_insn_luid(rtx_insn * insn)8938*38fd1498Szrj sched_init_insn_luid (rtx_insn *insn)
8939*38fd1498Szrj {
8940*38fd1498Szrj   int i = INSN_P (insn) ? 1 : common_sched_info->luid_for_non_insn (insn);
8941*38fd1498Szrj   int luid;
8942*38fd1498Szrj 
8943*38fd1498Szrj   if (i >= 0)
8944*38fd1498Szrj     {
8945*38fd1498Szrj       luid = sched_max_luid;
8946*38fd1498Szrj       sched_max_luid += i;
8947*38fd1498Szrj     }
8948*38fd1498Szrj   else
8949*38fd1498Szrj     luid = -1;
8950*38fd1498Szrj 
8951*38fd1498Szrj   SET_INSN_LUID (insn, luid);
8952*38fd1498Szrj }
8953*38fd1498Szrj 
8954*38fd1498Szrj /* Initialize luids for BBS.
8955*38fd1498Szrj    The hook common_sched_info->luid_for_non_insn () is used to determine
8956*38fd1498Szrj    if notes, labels, etc. need luids.  */
8957*38fd1498Szrj void
sched_init_luids(bb_vec_t bbs)8958*38fd1498Szrj sched_init_luids (bb_vec_t bbs)
8959*38fd1498Szrj {
8960*38fd1498Szrj   int i;
8961*38fd1498Szrj   basic_block bb;
8962*38fd1498Szrj 
8963*38fd1498Szrj   sched_extend_luids ();
8964*38fd1498Szrj   FOR_EACH_VEC_ELT (bbs, i, bb)
8965*38fd1498Szrj     {
8966*38fd1498Szrj       rtx_insn *insn;
8967*38fd1498Szrj 
8968*38fd1498Szrj       FOR_BB_INSNS (bb, insn)
8969*38fd1498Szrj 	sched_init_insn_luid (insn);
8970*38fd1498Szrj     }
8971*38fd1498Szrj }
8972*38fd1498Szrj 
8973*38fd1498Szrj /* Free LUIDs.  */
8974*38fd1498Szrj void
sched_finish_luids(void)8975*38fd1498Szrj sched_finish_luids (void)
8976*38fd1498Szrj {
8977*38fd1498Szrj   sched_luids.release ();
8978*38fd1498Szrj   sched_max_luid = 1;
8979*38fd1498Szrj }
8980*38fd1498Szrj 
8981*38fd1498Szrj /* Return logical uid of INSN.  Helpful while debugging.  */
8982*38fd1498Szrj int
insn_luid(rtx_insn * insn)8983*38fd1498Szrj insn_luid (rtx_insn *insn)
8984*38fd1498Szrj {
8985*38fd1498Szrj   return INSN_LUID (insn);
8986*38fd1498Szrj }
8987*38fd1498Szrj 
8988*38fd1498Szrj /* Extend per insn data in the target.  */
8989*38fd1498Szrj void
sched_extend_target(void)8990*38fd1498Szrj sched_extend_target (void)
8991*38fd1498Szrj {
8992*38fd1498Szrj   if (targetm.sched.h_i_d_extended)
8993*38fd1498Szrj     targetm.sched.h_i_d_extended ();
8994*38fd1498Szrj }
8995*38fd1498Szrj 
8996*38fd1498Szrj /* Extend global scheduler structures (those, that live across calls to
8997*38fd1498Szrj    schedule_block) to include information about just emitted INSN.  */
8998*38fd1498Szrj static void
extend_h_i_d(void)8999*38fd1498Szrj extend_h_i_d (void)
9000*38fd1498Szrj {
9001*38fd1498Szrj   int reserve = (get_max_uid () + 1 - h_i_d.length ());
9002*38fd1498Szrj   if (reserve > 0
9003*38fd1498Szrj       && ! h_i_d.space (reserve))
9004*38fd1498Szrj     {
9005*38fd1498Szrj       h_i_d.safe_grow_cleared (3 * get_max_uid () / 2);
9006*38fd1498Szrj       sched_extend_target ();
9007*38fd1498Szrj     }
9008*38fd1498Szrj }
9009*38fd1498Szrj 
9010*38fd1498Szrj /* Initialize h_i_d entry of the INSN with default values.
9011*38fd1498Szrj    Values, that are not explicitly initialized here, hold zero.  */
9012*38fd1498Szrj static void
init_h_i_d(rtx_insn * insn)9013*38fd1498Szrj init_h_i_d (rtx_insn *insn)
9014*38fd1498Szrj {
9015*38fd1498Szrj   if (INSN_LUID (insn) > 0)
9016*38fd1498Szrj     {
9017*38fd1498Szrj       INSN_COST (insn) = -1;
9018*38fd1498Szrj       QUEUE_INDEX (insn) = QUEUE_NOWHERE;
9019*38fd1498Szrj       INSN_TICK (insn) = INVALID_TICK;
9020*38fd1498Szrj       INSN_EXACT_TICK (insn) = INVALID_TICK;
9021*38fd1498Szrj       INTER_TICK (insn) = INVALID_TICK;
9022*38fd1498Szrj       TODO_SPEC (insn) = HARD_DEP;
9023*38fd1498Szrj       INSN_AUTOPREF_MULTIPASS_DATA (insn)[0].status
9024*38fd1498Szrj 	= AUTOPREF_MULTIPASS_DATA_UNINITIALIZED;
9025*38fd1498Szrj       INSN_AUTOPREF_MULTIPASS_DATA (insn)[1].status
9026*38fd1498Szrj 	= AUTOPREF_MULTIPASS_DATA_UNINITIALIZED;
9027*38fd1498Szrj     }
9028*38fd1498Szrj }
9029*38fd1498Szrj 
9030*38fd1498Szrj /* Initialize haifa_insn_data for BBS.  */
9031*38fd1498Szrj void
haifa_init_h_i_d(bb_vec_t bbs)9032*38fd1498Szrj haifa_init_h_i_d (bb_vec_t bbs)
9033*38fd1498Szrj {
9034*38fd1498Szrj   int i;
9035*38fd1498Szrj   basic_block bb;
9036*38fd1498Szrj 
9037*38fd1498Szrj   extend_h_i_d ();
9038*38fd1498Szrj   FOR_EACH_VEC_ELT (bbs, i, bb)
9039*38fd1498Szrj     {
9040*38fd1498Szrj       rtx_insn *insn;
9041*38fd1498Szrj 
9042*38fd1498Szrj       FOR_BB_INSNS (bb, insn)
9043*38fd1498Szrj 	init_h_i_d (insn);
9044*38fd1498Szrj     }
9045*38fd1498Szrj }
9046*38fd1498Szrj 
9047*38fd1498Szrj /* Finalize haifa_insn_data.  */
9048*38fd1498Szrj void
haifa_finish_h_i_d(void)9049*38fd1498Szrj haifa_finish_h_i_d (void)
9050*38fd1498Szrj {
9051*38fd1498Szrj   int i;
9052*38fd1498Szrj   haifa_insn_data_t data;
9053*38fd1498Szrj   reg_use_data *use, *next_use;
9054*38fd1498Szrj   reg_set_data *set, *next_set;
9055*38fd1498Szrj 
9056*38fd1498Szrj   FOR_EACH_VEC_ELT (h_i_d, i, data)
9057*38fd1498Szrj     {
9058*38fd1498Szrj       free (data->max_reg_pressure);
9059*38fd1498Szrj       free (data->reg_pressure);
9060*38fd1498Szrj       for (use = data->reg_use_list; use != NULL; use = next_use)
9061*38fd1498Szrj 	{
9062*38fd1498Szrj 	  next_use = use->next_insn_use;
9063*38fd1498Szrj 	  free (use);
9064*38fd1498Szrj 	}
9065*38fd1498Szrj       for (set = data->reg_set_list; set != NULL; set = next_set)
9066*38fd1498Szrj 	{
9067*38fd1498Szrj 	  next_set = set->next_insn_set;
9068*38fd1498Szrj 	  free (set);
9069*38fd1498Szrj 	}
9070*38fd1498Szrj 
9071*38fd1498Szrj     }
9072*38fd1498Szrj   h_i_d.release ();
9073*38fd1498Szrj }
9074*38fd1498Szrj 
9075*38fd1498Szrj /* Init data for the new insn INSN.  */
9076*38fd1498Szrj static void
haifa_init_insn(rtx_insn * insn)9077*38fd1498Szrj haifa_init_insn (rtx_insn *insn)
9078*38fd1498Szrj {
9079*38fd1498Szrj   gcc_assert (insn != NULL);
9080*38fd1498Szrj 
9081*38fd1498Szrj   sched_extend_luids ();
9082*38fd1498Szrj   sched_init_insn_luid (insn);
9083*38fd1498Szrj   sched_extend_target ();
9084*38fd1498Szrj   sched_deps_init (false);
9085*38fd1498Szrj   extend_h_i_d ();
9086*38fd1498Szrj   init_h_i_d (insn);
9087*38fd1498Szrj 
9088*38fd1498Szrj   if (adding_bb_to_current_region_p)
9089*38fd1498Szrj     {
9090*38fd1498Szrj       sd_init_insn (insn);
9091*38fd1498Szrj 
9092*38fd1498Szrj       /* Extend dependency caches by one element.  */
9093*38fd1498Szrj       extend_dependency_caches (1, false);
9094*38fd1498Szrj     }
9095*38fd1498Szrj   if (sched_pressure != SCHED_PRESSURE_NONE)
9096*38fd1498Szrj     init_insn_reg_pressure_info (insn);
9097*38fd1498Szrj }
9098*38fd1498Szrj 
9099*38fd1498Szrj /* Init data for the new basic block BB which comes after AFTER.  */
9100*38fd1498Szrj static void
haifa_init_only_bb(basic_block bb,basic_block after)9101*38fd1498Szrj haifa_init_only_bb (basic_block bb, basic_block after)
9102*38fd1498Szrj {
9103*38fd1498Szrj   gcc_assert (bb != NULL);
9104*38fd1498Szrj 
9105*38fd1498Szrj   sched_init_bbs ();
9106*38fd1498Szrj 
9107*38fd1498Szrj   if (common_sched_info->add_block)
9108*38fd1498Szrj     /* This changes only data structures of the front-end.  */
9109*38fd1498Szrj     common_sched_info->add_block (bb, after);
9110*38fd1498Szrj }
9111*38fd1498Szrj 
9112*38fd1498Szrj /* A generic version of sched_split_block ().  */
9113*38fd1498Szrj basic_block
sched_split_block_1(basic_block first_bb,rtx after)9114*38fd1498Szrj sched_split_block_1 (basic_block first_bb, rtx after)
9115*38fd1498Szrj {
9116*38fd1498Szrj   edge e;
9117*38fd1498Szrj 
9118*38fd1498Szrj   e = split_block (first_bb, after);
9119*38fd1498Szrj   gcc_assert (e->src == first_bb);
9120*38fd1498Szrj 
9121*38fd1498Szrj   /* sched_split_block emits note if *check == BB_END.  Probably it
9122*38fd1498Szrj      is better to rip that note off.  */
9123*38fd1498Szrj 
9124*38fd1498Szrj   return e->dest;
9125*38fd1498Szrj }
9126*38fd1498Szrj 
9127*38fd1498Szrj /* A generic version of sched_create_empty_bb ().  */
9128*38fd1498Szrj basic_block
sched_create_empty_bb_1(basic_block after)9129*38fd1498Szrj sched_create_empty_bb_1 (basic_block after)
9130*38fd1498Szrj {
9131*38fd1498Szrj   return create_empty_bb (after);
9132*38fd1498Szrj }
9133*38fd1498Szrj 
9134*38fd1498Szrj /* Insert PAT as an INSN into the schedule and update the necessary data
9135*38fd1498Szrj    structures to account for it. */
9136*38fd1498Szrj rtx_insn *
sched_emit_insn(rtx pat)9137*38fd1498Szrj sched_emit_insn (rtx pat)
9138*38fd1498Szrj {
9139*38fd1498Szrj   rtx_insn *insn = emit_insn_before (pat, first_nonscheduled_insn ());
9140*38fd1498Szrj   haifa_init_insn (insn);
9141*38fd1498Szrj 
9142*38fd1498Szrj   if (current_sched_info->add_remove_insn)
9143*38fd1498Szrj     current_sched_info->add_remove_insn (insn, 0);
9144*38fd1498Szrj 
9145*38fd1498Szrj   (*current_sched_info->begin_schedule_ready) (insn);
9146*38fd1498Szrj   scheduled_insns.safe_push (insn);
9147*38fd1498Szrj 
9148*38fd1498Szrj   last_scheduled_insn = insn;
9149*38fd1498Szrj   return insn;
9150*38fd1498Szrj }
9151*38fd1498Szrj 
9152*38fd1498Szrj /* This function returns a candidate satisfying dispatch constraints from
9153*38fd1498Szrj    the ready list.  */
9154*38fd1498Szrj 
9155*38fd1498Szrj static rtx_insn *
ready_remove_first_dispatch(struct ready_list * ready)9156*38fd1498Szrj ready_remove_first_dispatch (struct ready_list *ready)
9157*38fd1498Szrj {
9158*38fd1498Szrj   int i;
9159*38fd1498Szrj   rtx_insn *insn = ready_element (ready, 0);
9160*38fd1498Szrj 
9161*38fd1498Szrj   if (ready->n_ready == 1
9162*38fd1498Szrj       || !INSN_P (insn)
9163*38fd1498Szrj       || INSN_CODE (insn) < 0
9164*38fd1498Szrj       || !active_insn_p (insn)
9165*38fd1498Szrj       || targetm.sched.dispatch (insn, FITS_DISPATCH_WINDOW))
9166*38fd1498Szrj     return ready_remove_first (ready);
9167*38fd1498Szrj 
9168*38fd1498Szrj   for (i = 1; i < ready->n_ready; i++)
9169*38fd1498Szrj     {
9170*38fd1498Szrj       insn = ready_element (ready, i);
9171*38fd1498Szrj 
9172*38fd1498Szrj       if (!INSN_P (insn)
9173*38fd1498Szrj 	  || INSN_CODE (insn) < 0
9174*38fd1498Szrj 	  || !active_insn_p (insn))
9175*38fd1498Szrj 	continue;
9176*38fd1498Szrj 
9177*38fd1498Szrj       if (targetm.sched.dispatch (insn, FITS_DISPATCH_WINDOW))
9178*38fd1498Szrj 	{
9179*38fd1498Szrj 	  /* Return ith element of ready.  */
9180*38fd1498Szrj 	  insn = ready_remove (ready, i);
9181*38fd1498Szrj 	  return insn;
9182*38fd1498Szrj 	}
9183*38fd1498Szrj     }
9184*38fd1498Szrj 
9185*38fd1498Szrj   if (targetm.sched.dispatch (NULL, DISPATCH_VIOLATION))
9186*38fd1498Szrj     return ready_remove_first (ready);
9187*38fd1498Szrj 
9188*38fd1498Szrj   for (i = 1; i < ready->n_ready; i++)
9189*38fd1498Szrj     {
9190*38fd1498Szrj       insn = ready_element (ready, i);
9191*38fd1498Szrj 
9192*38fd1498Szrj       if (!INSN_P (insn)
9193*38fd1498Szrj 	  || INSN_CODE (insn) < 0
9194*38fd1498Szrj 	  || !active_insn_p (insn))
9195*38fd1498Szrj 	continue;
9196*38fd1498Szrj 
9197*38fd1498Szrj       /* Return i-th element of ready.  */
9198*38fd1498Szrj       if (targetm.sched.dispatch (insn, IS_CMP))
9199*38fd1498Szrj 	return ready_remove (ready, i);
9200*38fd1498Szrj     }
9201*38fd1498Szrj 
9202*38fd1498Szrj   return ready_remove_first (ready);
9203*38fd1498Szrj }
9204*38fd1498Szrj 
9205*38fd1498Szrj /* Get number of ready insn in the ready list.  */
9206*38fd1498Szrj 
9207*38fd1498Szrj int
number_in_ready(void)9208*38fd1498Szrj number_in_ready (void)
9209*38fd1498Szrj {
9210*38fd1498Szrj   return ready.n_ready;
9211*38fd1498Szrj }
9212*38fd1498Szrj 
9213*38fd1498Szrj /* Get number of ready's in the ready list.  */
9214*38fd1498Szrj 
9215*38fd1498Szrj rtx_insn *
get_ready_element(int i)9216*38fd1498Szrj get_ready_element (int i)
9217*38fd1498Szrj {
9218*38fd1498Szrj   return ready_element (&ready, i);
9219*38fd1498Szrj }
9220*38fd1498Szrj 
9221*38fd1498Szrj #endif /* INSN_SCHEDULING */
9222