Line data Source code
1 : /* Instruction scheduling pass. Selective scheduler and pipeliner.
2 : Copyright (C) 2006-2026 Free Software Foundation, Inc.
3 :
4 : This file is part of GCC.
5 :
6 : GCC is free software; you can redistribute it and/or modify it under
7 : the terms of the GNU General Public License as published by the Free
8 : Software Foundation; either version 3, or (at your option) any later
9 : version.
10 :
11 : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 : WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 : for more details.
15 :
16 : You should have received a copy of the GNU General Public License
17 : along with GCC; see the file COPYING3. If not see
18 : <http://www.gnu.org/licenses/>. */
19 :
20 : #include "config.h"
21 : #include "system.h"
22 : #include "coretypes.h"
23 : #include "backend.h"
24 : #include "tree.h"
25 : #include "rtl.h"
26 : #include "df.h"
27 : #include "memmodel.h"
28 : #include "tm_p.h"
29 : #include "regs.h"
30 : #include "cfgbuild.h"
31 : #include "cfgcleanup.h"
32 : #include "insn-config.h"
33 : #include "insn-attr.h"
34 : #include "target.h"
35 : #include "sched-int.h"
36 : #include "rtlhooks-def.h"
37 : #include "ira.h"
38 : #include "ira-int.h"
39 : #include "rtl-iter.h"
40 :
41 : #ifdef INSN_SCHEDULING
42 : #include "regset.h"
43 : #include "cfgloop.h"
44 : #include "sel-sched-ir.h"
45 : #include "sel-sched-dump.h"
46 : #include "sel-sched.h"
47 : #include "dbgcnt.h"
48 : #include "function-abi.h"
49 :
50 : /* Implementation of selective scheduling approach.
51 : The below implementation follows the original approach with the following
52 : changes:
53 :
54 : o the scheduler works after register allocation (but can be also tuned
55 : to work before RA);
56 : o some instructions are not copied or register renamed;
57 : o conditional jumps are not moved with code duplication;
58 : o several jumps in one parallel group are not supported;
59 : o when pipelining outer loops, code motion through inner loops
60 : is not supported;
61 : o control and data speculation are supported;
62 : o some improvements for better compile time/performance were made.
63 :
64 : Terminology
65 : ===========
66 :
67 : A vinsn, or virtual insn, is an insn with additional data characterizing
68 : insn pattern, such as LHS, RHS, register sets used/set/clobbered, etc.
69 : Vinsns also act as smart pointers to save memory by reusing them in
70 : different expressions. A vinsn is described by vinsn_t type.
71 :
72 : An expression is a vinsn with additional data characterizing its properties
73 : at some point in the control flow graph. The data may be its usefulness,
74 : priority, speculative status, whether it was renamed/subsituted, etc.
75 : An expression is described by expr_t type.
76 :
77 : Availability set (av_set) is a set of expressions at a given control flow
78 : point. It is represented as av_set_t. The expressions in av sets are kept
79 : sorted in the terms of expr_greater_p function. It allows to truncate
80 : the set while leaving the best expressions.
81 :
82 : A fence is a point through which code motion is prohibited. On each step,
83 : we gather a parallel group of insns at a fence. It is possible to have
84 : multiple fences. A fence is represented via fence_t.
85 :
86 : A boundary is the border between the fence group and the rest of the code.
87 : Currently, we never have more than one boundary per fence, as we finalize
88 : the fence group when a jump is scheduled. A boundary is represented
89 : via bnd_t.
90 :
91 : High-level overview
92 : ===================
93 :
94 : The scheduler finds regions to schedule, schedules each one, and finalizes.
95 : The regions are formed starting from innermost loops, so that when the inner
96 : loop is pipelined, its prologue can be scheduled together with yet unprocessed
97 : outer loop. The rest of acyclic regions are found using extend_rgns:
98 : the blocks that are not yet allocated to any regions are traversed in top-down
99 : order, and a block is added to a region to which all its predecessors belong;
100 : otherwise, the block starts its own region.
101 :
102 : The main scheduling loop (sel_sched_region_2) consists of just
103 : scheduling on each fence and updating fences. For each fence,
104 : we fill a parallel group of insns (fill_insns) until some insns can be added.
105 : First, we compute available exprs (av-set) at the boundary of the current
106 : group. Second, we choose the best expression from it. If the stall is
107 : required to schedule any of the expressions, we advance the current cycle
108 : appropriately. So, the final group does not exactly correspond to a VLIW
109 : word. Third, we move the chosen expression to the boundary (move_op)
110 : and update the intermediate av sets and liveness sets. We quit fill_insns
111 : when either no insns left for scheduling or we have scheduled enough insns
112 : so we feel like advancing a scheduling point.
113 :
114 : Computing available expressions
115 : ===============================
116 :
117 : The computation (compute_av_set) is a bottom-up traversal. At each insn,
118 : we're moving the union of its successors' sets through it via
119 : moveup_expr_set. The dependent expressions are removed. Local
120 : transformations (substitution, speculation) are applied to move more
121 : exprs. Then the expr corresponding to the current insn is added.
122 : The result is saved on each basic block header.
123 :
124 : When traversing the CFG, we're moving down for no more than max_ws insns.
125 : Also, we do not move down to ineligible successors (is_ineligible_successor),
126 : which include moving along a back-edge, moving to already scheduled code,
127 : and moving to another fence. The first two restrictions are lifted during
128 : pipelining, which allows us to move insns along a back-edge. We always have
129 : an acyclic region for scheduling because we forbid motion through fences.
130 :
131 : Choosing the best expression
132 : ============================
133 :
134 : We sort the final availability set via sel_rank_for_schedule, then we remove
135 : expressions which are not yet ready (tick_check_p) or which dest registers
136 : cannot be used. For some of them, we choose another register via
137 : find_best_reg. To do this, we run find_used_regs to calculate the set of
138 : registers which cannot be used. The find_used_regs function performs
139 : a traversal of code motion paths for an expr. We consider for renaming
140 : only registers which are from the same regclass as the original one and
141 : using which does not interfere with any live ranges. Finally, we convert
142 : the resulting set to the ready list format and use max_issue and reorder*
143 : hooks similarly to the Haifa scheduler.
144 :
145 : Scheduling the best expression
146 : ==============================
147 :
148 : We run the move_op routine to perform the same type of code motion paths
149 : traversal as in find_used_regs. (These are working via the same driver,
150 : code_motion_path_driver.) When moving down the CFG, we look for original
151 : instruction that gave birth to a chosen expression. We undo
152 : the transformations performed on an expression via the history saved in it.
153 : When found, we remove the instruction or leave a reg-reg copy/speculation
154 : check if needed. On a way up, we insert bookkeeping copies at each join
155 : point. If a copy is not needed, it will be removed later during this
156 : traversal. We update the saved av sets and liveness sets on the way up, too.
157 :
158 : Finalizing the schedule
159 : =======================
160 :
161 : When pipelining, we reschedule the blocks from which insns were pipelined
162 : to get a tighter schedule. On Itanium, we also perform bundling via
163 : the same routine from ia64.cc.
164 :
165 : Dependence analysis changes
166 : ===========================
167 :
168 : We augmented the sched-deps.cc with hooks that get called when a particular
169 : dependence is found in a particular part of an insn. Using these hooks, we
170 : can do several actions such as: determine whether an insn can be moved through
171 : another (has_dependence_p, moveup_expr); find out whether an insn can be
172 : scheduled on the current cycle (tick_check_p); find out registers that
173 : are set/used/clobbered by an insn and find out all the strange stuff that
174 : restrict its movement, like SCHED_GROUP_P or CANT_MOVE (done in
175 : init_global_and_expr_for_insn).
176 :
177 : Initialization changes
178 : ======================
179 :
180 : There are parts of haifa-sched.cc, sched-deps.cc, and sched-rgn.cc that are
181 : reused in all of the schedulers. We have split up the initialization of data
182 : of such parts into different functions prefixed with scheduler type and
183 : postfixed with the type of data initialized: {,sel_,haifa_}sched_{init,finish},
184 : sched_rgn_init/finish, sched_deps_init/finish, sched_init_{luids/bbs}, etc.
185 : The same splitting is done with current_sched_info structure:
186 : dependence-related parts are in sched_deps_info, common part is in
187 : common_sched_info, and haifa/sel/etc part is in current_sched_info.
188 :
189 : Target contexts
190 : ===============
191 :
192 : As we now have multiple-point scheduling, this would not work with backends
193 : which save some of the scheduler state to use it in the target hooks.
194 : For this purpose, we introduce a concept of target contexts, which
195 : encapsulate such information. The backend should implement simple routines
196 : of allocating/freeing/setting such a context. The scheduler calls these
197 : as target hooks and handles the target context as an opaque pointer (similar
198 : to the DFA state type, state_t).
199 :
200 : Various speedups
201 : ================
202 :
203 : As the correct data dependence graph is not supported during scheduling (which
204 : is to be changed in mid-term), we cache as much of the dependence analysis
205 : results as possible to avoid reanalyzing. This includes: bitmap caches on
206 : each insn in stream of the region saying yes/no for a query with a pair of
207 : UIDs; hashtables with the previously done transformations on each insn in
208 : stream; a vector keeping a history of transformations on each expr.
209 :
210 : Also, we try to minimize the dependence context used on each fence to check
211 : whether the given expression is ready for scheduling by removing from it
212 : insns that are definitely completed the execution. The results of
213 : tick_check_p checks are also cached in a vector on each fence.
214 :
215 : We keep a valid liveness set on each insn in a region to avoid the high
216 : cost of recomputation on large basic blocks.
217 :
218 : Finally, we try to minimize the number of needed updates to the availability
219 : sets. The updates happen in two cases: when fill_insns terminates,
220 : we advance all fences and increase the stage number to show that the region
221 : has changed and the sets are to be recomputed; and when the next iteration
222 : of a loop in fill_insns happens (but this one reuses the saved av sets
223 : on bb headers.) Thus, we try to break the fill_insns loop only when
224 : "significant" number of insns from the current scheduling window was
225 : scheduled. This should be made a target param.
226 :
227 :
228 : TODO: correctly support the data dependence graph at all stages and get rid
229 : of all caches. This should speed up the scheduler.
230 : TODO: implement moving cond jumps with bookkeeping copies on both targets.
231 : TODO: tune the scheduler before RA so it does not create too much pseudos.
232 :
233 :
234 : References:
235 : S.-M. Moon and K. Ebcioglu. Parallelizing nonnumerical code with
236 : selective scheduling and software pipelining.
237 : ACM TOPLAS, Vol 19, No. 6, pages 853--898, Nov. 1997.
238 :
239 : Andrey Belevantsev, Maxim Kuvyrkov, Vladimir Makarov, Dmitry Melnik,
240 : and Dmitry Zhurikhin. An interblock VLIW-targeted instruction scheduler
241 : for GCC. In Proceedings of GCC Developers' Summit 2006.
242 :
243 : Arutyun Avetisyan, Andrey Belevantsev, and Dmitry Melnik. GCC Instruction
244 : Scheduler and Software Pipeliner on the Itanium Platform. EPIC-7 Workshop.
245 : http://rogue.colorado.edu/EPIC7/.
246 :
247 : */
248 :
249 : /* True when pipelining is enabled. */
250 : bool pipelining_p;
251 :
252 : /* True if bookkeeping is enabled. */
253 : bool bookkeeping_p;
254 :
255 : /* Maximum number of insns that are eligible for renaming. */
256 : int max_insns_to_rename;
257 :
258 :
259 : /* Definitions of local types and macros. */
260 :
261 : /* Represents possible outcomes of moving an expression through an insn. */
262 : enum MOVEUP_EXPR_CODE
263 : {
264 : /* The expression is not changed. */
265 : MOVEUP_EXPR_SAME,
266 :
267 : /* Not changed, but requires a new destination register. */
268 : MOVEUP_EXPR_AS_RHS,
269 :
270 : /* Cannot be moved. */
271 : MOVEUP_EXPR_NULL,
272 :
273 : /* Changed (substituted or speculated). */
274 : MOVEUP_EXPR_CHANGED
275 : };
276 :
277 : /* The container to be passed into rtx search & replace functions. */
278 : struct rtx_search_arg
279 : {
280 : /* What we are searching for. */
281 : rtx x;
282 :
283 : /* The occurrence counter. */
284 : int n;
285 : };
286 :
287 : typedef struct rtx_search_arg *rtx_search_arg_p;
288 :
289 : /* This struct contains precomputed hard reg sets that are needed when
290 : computing registers available for renaming. */
291 : struct hard_regs_data
292 : {
293 : /* For every mode, this stores registers available for use with
294 : that mode. */
295 : HARD_REG_SET regs_for_mode[NUM_MACHINE_MODES];
296 :
297 : /* True when regs_for_mode[mode] is initialized. */
298 : bool regs_for_mode_ok[NUM_MACHINE_MODES];
299 :
300 : /* For every register, it has regs that are ok to rename into it.
301 : The register in question is always set. If not, this means
302 : that the whole set is not computed yet. */
303 : HARD_REG_SET regs_for_rename[FIRST_PSEUDO_REGISTER];
304 :
305 : /* All registers that are used or call used. */
306 : HARD_REG_SET regs_ever_used;
307 :
308 : #ifdef STACK_REGS
309 : /* Stack registers. */
310 : HARD_REG_SET stack_regs;
311 : #endif
312 : };
313 :
314 : /* Holds the results of computation of available for renaming and
315 : unavailable hard registers. */
316 : struct reg_rename
317 : {
318 : /* These are unavailable due to calls crossing, globalness, etc. */
319 : HARD_REG_SET unavailable_hard_regs;
320 :
321 : /* These are *available* for renaming. */
322 : HARD_REG_SET available_for_renaming;
323 :
324 : /* The set of ABIs used by calls that the code motion path crosses. */
325 : unsigned int crossed_call_abis : NUM_ABI_IDS;
326 : };
327 :
328 : /* A global structure that contains the needed information about harg
329 : regs. */
330 : static struct hard_regs_data sel_hrd;
331 :
332 :
333 : /* This structure holds local data used in code_motion_path_driver hooks on
334 : the same or adjacent levels of recursion. Here we keep those parameters
335 : that are not used in code_motion_path_driver routine itself, but only in
336 : its hooks. Moreover, all parameters that can be modified in hooks are
337 : in this structure, so all other parameters passed explicitly to hooks are
338 : read-only. */
339 : struct cmpd_local_params
340 : {
341 : /* Local params used in move_op_* functions. */
342 :
343 : /* Edges for bookkeeping generation. */
344 : edge e1, e2;
345 :
346 : /* C_EXPR merged from all successors and locally allocated temporary C_EXPR. */
347 : expr_t c_expr_merged, c_expr_local;
348 :
349 : /* Local params used in fur_* functions. */
350 : /* Copy of the ORIGINAL_INSN list, stores the original insns already
351 : found before entering the current level of code_motion_path_driver. */
352 : def_list_t old_original_insns;
353 :
354 : /* Local params used in move_op_* functions. */
355 : /* True when we have removed last insn in the block which was
356 : also a boundary. Do not update anything or create bookkeeping copies. */
357 : BOOL_BITFIELD removed_last_insn : 1;
358 : };
359 :
360 : /* Stores the static parameters for move_op_* calls. */
361 : struct moveop_static_params
362 : {
363 : /* Destination register. */
364 : rtx dest;
365 :
366 : /* Current C_EXPR. */
367 : expr_t c_expr;
368 :
369 : /* An UID of expr_vliw which is to be moved up. If we find other exprs,
370 : they are to be removed. */
371 : int uid;
372 :
373 : /* This is initialized to the insn on which the driver stopped its traversal. */
374 : insn_t failed_insn;
375 :
376 : /* True if we scheduled an insn with different register. */
377 : bool was_renamed;
378 : };
379 :
380 : /* Stores the static parameters for fur_* calls. */
381 : struct fur_static_params
382 : {
383 : /* Set of registers unavailable on the code motion path. */
384 : regset used_regs;
385 :
386 : /* Pointer to the list of original insns definitions. */
387 : def_list_t *original_insns;
388 :
389 : /* The set of ABIs used by calls that the code motion path crosses. */
390 : unsigned int crossed_call_abis : NUM_ABI_IDS;
391 : };
392 :
393 : typedef struct fur_static_params *fur_static_params_p;
394 : typedef struct cmpd_local_params *cmpd_local_params_p;
395 : typedef struct moveop_static_params *moveop_static_params_p;
396 :
397 : /* Set of hooks and parameters that determine behavior specific to
398 : move_op or find_used_regs functions. */
399 : struct code_motion_path_driver_info_def
400 : {
401 : /* Called on enter to the basic block. */
402 : int (*on_enter) (insn_t, cmpd_local_params_p, void *, bool);
403 :
404 : /* Called when original expr is found. */
405 : void (*orig_expr_found) (insn_t, expr_t, cmpd_local_params_p, void *);
406 :
407 : /* Called while descending current basic block if current insn is not
408 : the original EXPR we're searching for. */
409 : bool (*orig_expr_not_found) (insn_t, av_set_t, void *);
410 :
411 : /* Function to merge C_EXPRes from different successors. */
412 : void (*merge_succs) (insn_t, insn_t, int, cmpd_local_params_p, void *);
413 :
414 : /* Function to finalize merge from different successors and possibly
415 : deallocate temporary data structures used for merging. */
416 : void (*after_merge_succs) (cmpd_local_params_p, void *);
417 :
418 : /* Called on the backward stage of recursion to do moveup_expr.
419 : Used only with move_op_*. */
420 : void (*ascend) (insn_t, void *);
421 :
422 : /* Called on the ascending pass, before returning from the current basic
423 : block or from the whole traversal. */
424 : void (*at_first_insn) (insn_t, cmpd_local_params_p, void *);
425 :
426 : /* When processing successors in move_op we need only descend into
427 : SUCCS_NORMAL successors, while in find_used_regs we need SUCCS_ALL. */
428 : int succ_flags;
429 :
430 : /* The routine name to print in dumps ("move_op" of "find_used_regs"). */
431 : const char *routine_name;
432 : };
433 :
434 : /* Global pointer to current hooks, either points to MOVE_OP_HOOKS or
435 : FUR_HOOKS. */
436 : struct code_motion_path_driver_info_def *code_motion_path_driver_info;
437 :
438 : /* Set of hooks for performing move_op and find_used_regs routines with
439 : code_motion_path_driver. */
440 : extern struct code_motion_path_driver_info_def move_op_hooks, fur_hooks;
441 :
442 : /* True if/when we want to emulate Haifa scheduler in the common code.
443 : This is used in sched_rgn_local_init and in various places in
444 : sched-deps.cc. */
445 : int sched_emulate_haifa_p;
446 :
447 : /* GLOBAL_LEVEL is used to discard information stored in basic block headers
448 : av_sets. Av_set of bb header is valid if its (bb header's) level is equal
449 : to GLOBAL_LEVEL. And invalid if lesser. This is primarily used to advance
450 : scheduling window. */
451 : int global_level;
452 :
453 : /* Current fences. */
454 : flist_t fences;
455 :
456 : /* True when separable insns should be scheduled as RHSes. */
457 : static bool enable_schedule_as_rhs_p;
458 :
459 : /* Used in verify_target_availability to assert that target reg is reported
460 : unavailabile by both TARGET_UNAVAILABLE and find_used_regs only if
461 : we haven't scheduled anything on the previous fence.
462 : if scheduled_something_on_previous_fence is true, TARGET_UNAVAILABLE can
463 : have more conservative value than the one returned by the
464 : find_used_regs, thus we shouldn't assert that these values are equal. */
465 : static bool scheduled_something_on_previous_fence;
466 :
467 : /* All newly emitted insns will have their uids greater than this value. */
468 : static int first_emitted_uid;
469 :
470 : /* Set of basic blocks that are forced to start new ebbs. This is a subset
471 : of all the ebb heads. */
472 : bitmap forced_ebb_heads;
473 :
474 : /* Blocks that need to be rescheduled after pipelining. */
475 : bitmap blocks_to_reschedule = NULL;
476 :
477 : /* True when the first lv set should be ignored when updating liveness. */
478 : static bool ignore_first = false;
479 :
480 : /* Number of insns max_issue has initialized data structures for. */
481 : static int max_issue_size = 0;
482 :
483 : /* Whether we can issue more instructions. */
484 : static int can_issue_more;
485 :
486 : /* Maximum software lookahead window size, reduced when rescheduling after
487 : pipelining. */
488 : static int max_ws;
489 :
490 : /* Number of insns scheduled in current region. */
491 : static int num_insns_scheduled;
492 :
493 : /* A vector of expressions is used to be able to sort them. */
494 : static vec<expr_t> vec_av_set;
495 :
496 : /* A vector of vinsns is used to hold temporary lists of vinsns. */
497 : typedef vec<vinsn_t> vinsn_vec_t;
498 :
499 : /* This vector has the exprs which may still present in av_sets, but actually
500 : can't be moved up due to bookkeeping created during code motion to another
501 : fence. See comment near the call to update_and_record_unavailable_insns
502 : for the detailed explanations. */
503 : static vinsn_vec_t vec_bookkeeping_blocked_vinsns = vinsn_vec_t ();
504 :
505 : /* This vector has vinsns which are scheduled with renaming on the first fence
506 : and then seen on the second. For expressions with such vinsns, target
507 : availability information may be wrong. */
508 : static vinsn_vec_t vec_target_unavailable_vinsns = vinsn_vec_t ();
509 :
510 : /* Vector to store temporary nops inserted in move_op to prevent removal
511 : of empty bbs. */
512 : static vec<insn_t> vec_temp_moveop_nops;
513 :
514 : /* These bitmaps record original instructions scheduled on the current
515 : iteration and bookkeeping copies created by them. */
516 : static bitmap current_originators = NULL;
517 : static bitmap current_copies = NULL;
518 :
519 : /* This bitmap marks the blocks visited by code_motion_path_driver so we don't
520 : visit them afterwards. */
521 : static bitmap code_motion_visited_blocks = NULL;
522 :
523 : /* Variables to accumulate different statistics. */
524 :
525 : /* The number of bookkeeping copies created. */
526 : static int stat_bookkeeping_copies;
527 :
528 : /* The number of insns that required bookkeeiping for their scheduling. */
529 : static int stat_insns_needed_bookkeeping;
530 :
531 : /* The number of insns that got renamed. */
532 : static int stat_renamed_scheduled;
533 :
534 : /* The number of substitutions made during scheduling. */
535 : static int stat_substitutions_total;
536 :
537 :
538 : /* Forward declarations of static functions. */
539 : static bool rtx_ok_for_substitution_p (rtx, rtx);
540 : static int sel_rank_for_schedule (const void *, const void *);
541 : static av_set_t find_sequential_best_exprs (bnd_t, expr_t, bool);
542 : static basic_block find_block_for_bookkeeping (edge e1, edge e2, bool lax);
543 :
544 : static rtx get_dest_from_orig_ops (av_set_t);
545 : static basic_block generate_bookkeeping_insn (expr_t, edge, edge);
546 : static bool find_used_regs (insn_t, av_set_t, regset, struct reg_rename *,
547 : def_list_t *);
548 : static bool move_op (insn_t, av_set_t, expr_t, rtx, expr_t, bool*);
549 : static int code_motion_path_driver (insn_t, av_set_t, ilist_t,
550 : cmpd_local_params_p, void *);
551 : static void sel_sched_region_1 (void);
552 : static void sel_sched_region_2 (int);
553 : static av_set_t compute_av_set_inside_bb (insn_t, ilist_t, int, bool);
554 :
555 : static void debug_state (state_t);
556 :
557 :
558 : /* Functions that work with fences. */
559 :
560 : /* Advance one cycle on FENCE. */
561 : static void
562 3348 : advance_one_cycle (fence_t fence)
563 : {
564 3348 : unsigned i;
565 3348 : int cycle;
566 3348 : rtx_insn *insn;
567 :
568 3348 : advance_state (FENCE_STATE (fence));
569 3348 : cycle = ++FENCE_CYCLE (fence);
570 3348 : FENCE_ISSUED_INSNS (fence) = 0;
571 3348 : FENCE_STARTS_CYCLE_P (fence) = 1;
572 3348 : can_issue_more = issue_rate;
573 3348 : FENCE_ISSUE_MORE (fence) = can_issue_more;
574 :
575 14373 : for (i = 0; vec_safe_iterate (FENCE_EXECUTING_INSNS (fence), i, &insn); )
576 : {
577 11025 : if (INSN_READY_CYCLE (insn) < cycle)
578 : {
579 2355 : remove_from_deps (FENCE_DC (fence), insn);
580 2355 : FENCE_EXECUTING_INSNS (fence)->unordered_remove (i);
581 2355 : continue;
582 : }
583 8670 : i++;
584 : }
585 3348 : if (sched_verbose >= 2)
586 : {
587 0 : sel_print ("Finished a cycle. Current cycle = %d\n", FENCE_CYCLE (fence));
588 0 : debug_state (FENCE_STATE (fence));
589 : }
590 3348 : }
591 :
592 : /* Returns true when SUCC in a fallthru bb of INSN, possibly
593 : skipping empty basic blocks. */
594 : static bool
595 108 : in_fallthru_bb_p (rtx_insn *insn, rtx succ)
596 : {
597 108 : basic_block bb = BLOCK_FOR_INSN (insn);
598 108 : edge e;
599 :
600 108 : if (bb == BLOCK_FOR_INSN (succ))
601 : return true;
602 :
603 108 : e = find_fallthru_edge_from (bb);
604 108 : if (e)
605 96 : bb = e->dest;
606 : else
607 : return false;
608 :
609 96 : while (sel_bb_empty_p (bb))
610 0 : bb = bb->next_bb;
611 :
612 96 : return bb == BLOCK_FOR_INSN (succ);
613 : }
614 :
615 : /* Construct successor fences from OLD_FENCEs and put them in NEW_FENCES.
616 : When a successor will continue a ebb, transfer all parameters of a fence
617 : to the new fence. ORIG_MAX_SEQNO is the maximal seqno before this round
618 : of scheduling helping to distinguish between the old and the new code. */
619 : static void
620 958 : extract_new_fences_from (flist_t old_fences, flist_tail_t new_fences,
621 : int orig_max_seqno)
622 : {
623 958 : bool was_here_p = false;
624 958 : insn_t insn = NULL;
625 958 : insn_t succ;
626 958 : succ_iterator si;
627 958 : ilist_iterator ii;
628 958 : fence_t fence = FLIST_FENCE (old_fences);
629 958 : basic_block bb;
630 :
631 : /* Get the only element of FENCE_BNDS (fence). */
632 1916 : FOR_EACH_INSN (insn, ii, FENCE_BNDS (fence))
633 : {
634 958 : gcc_assert (!was_here_p);
635 958 : was_here_p = true;
636 : }
637 958 : gcc_assert (was_here_p && insn != NULL_RTX);
638 :
639 : /* When in the "middle" of the block, just move this fence
640 : to the new list. */
641 958 : bb = BLOCK_FOR_INSN (insn);
642 958 : if (! sel_bb_end_p (insn)
643 1280 : || (single_succ_p (bb)
644 322 : && single_pred_p (single_succ (bb))))
645 : {
646 640 : insn_t succ;
647 :
648 640 : succ = (sel_bb_end_p (insn)
649 644 : ? sel_bb_head (single_succ (bb))
650 636 : : NEXT_INSN (insn));
651 :
652 640 : if (INSN_SEQNO (succ) > 0
653 640 : && INSN_SEQNO (succ) <= orig_max_seqno
654 1280 : && INSN_SCHED_TIMES (succ) <= 0)
655 : {
656 639 : FENCE_INSN (fence) = succ;
657 639 : move_fence_to_fences (old_fences, new_fences);
658 :
659 639 : if (sched_verbose >= 1)
660 0 : sel_print ("Fence %d continues as %d[%d] (state continue)\n",
661 0 : INSN_UID (insn), INSN_UID (succ), BLOCK_NUM (succ));
662 : }
663 640 : return;
664 : }
665 :
666 : /* Otherwise copy fence's structures to (possibly) multiple successors. */
667 711 : FOR_EACH_SUCC_1 (succ, si, insn, SUCCS_NORMAL | SUCCS_SKIP_TO_LOOP_EXITS)
668 : {
669 393 : int seqno = INSN_SEQNO (succ);
670 :
671 393 : if (seqno > 0 && seqno <= orig_max_seqno
672 393 : && (pipelining_p || INSN_SCHED_TIMES (succ) <= 0))
673 : {
674 269 : bool b = (in_same_ebb_p (insn, succ)
675 269 : || in_fallthru_bb_p (insn, succ));
676 :
677 269 : if (sched_verbose >= 1)
678 0 : sel_print ("Fence %d continues as %d[%d] (state %s)\n",
679 0 : INSN_UID (insn), INSN_UID (succ),
680 0 : BLOCK_NUM (succ), b ? "continue" : "reset");
681 :
682 269 : if (b)
683 178 : add_dirty_fence_to_fences (new_fences, succ, fence);
684 : else
685 : {
686 : /* Mark block of the SUCC as head of the new ebb. */
687 91 : bitmap_set_bit (forced_ebb_heads, BLOCK_NUM (succ));
688 91 : add_clean_fence_to_fences (new_fences, succ, fence);
689 : }
690 : }
691 : }
692 : }
693 :
694 :
695 : /* Functions to support substitution. */
696 :
697 : /* Returns whether INSN with dependence status DS is eligible for
698 : substitution, i.e. it's a copy operation x := y, and RHS that is
699 : moved up through this insn should be substituted. */
700 : static bool
701 1067 : can_substitute_through_p (insn_t insn, ds_t ds)
702 : {
703 : /* We can substitute only true dependencies. */
704 1067 : if ((ds & DEP_OUTPUT)
705 1066 : || (ds & DEP_ANTI)
706 941 : || ! INSN_RHS (insn)
707 1780 : || ! INSN_LHS (insn))
708 : return false;
709 :
710 : /* Now we just need to make sure the INSN_RHS consists of only one
711 : simple REG rtx. */
712 713 : if (REG_P (INSN_LHS (insn))
713 713 : && REG_P (INSN_RHS (insn)))
714 101 : return true;
715 : return false;
716 : }
717 :
718 : /* Substitute all occurrences of INSN's destination in EXPR' vinsn with INSN's
719 : source (if INSN is eligible for substitution). Returns TRUE if
720 : substitution was actually performed, FALSE otherwise. Substitution might
721 : be not performed because it's either EXPR' vinsn doesn't contain INSN's
722 : destination or the resulting insn is invalid for the target machine.
723 : When UNDO is true, perform unsubstitution instead (the difference is in
724 : the part of rtx on which validate_replace_rtx is called). */
725 : static bool
726 101 : substitute_reg_in_expr (expr_t expr, insn_t insn, bool undo)
727 : {
728 101 : rtx *where;
729 101 : bool new_insn_valid;
730 101 : vinsn_t *vi = &EXPR_VINSN (expr);
731 101 : bool has_rhs = VINSN_RHS (*vi) != NULL;
732 101 : rtx old, new_rtx;
733 :
734 : /* Do not try to replace in SET_DEST. Although we'll choose new
735 : register for the RHS, we don't want to change RHS' original reg.
736 : If the insn is not SET, we may still be able to substitute something
737 : in it, and if we're here (don't have deps), it doesn't write INSN's
738 : dest. */
739 101 : where = (has_rhs
740 101 : ? &VINSN_RHS (*vi)
741 0 : : &PATTERN (VINSN_INSN_RTX (*vi)));
742 101 : old = undo ? INSN_RHS (insn) : INSN_LHS (insn);
743 :
744 : /* Substitute if INSN has a form of x:=y and LHS(INSN) occurs in *VI. */
745 101 : if (rtx_ok_for_substitution_p (old, *where))
746 : {
747 88 : rtx_insn *new_insn;
748 88 : rtx *where_replace;
749 :
750 : /* We should copy these rtxes before substitution. */
751 88 : new_rtx = copy_rtx (undo ? INSN_LHS (insn) : INSN_RHS (insn));
752 88 : new_insn = create_copy_of_insn_rtx (VINSN_INSN_RTX (*vi));
753 :
754 : /* Where we'll replace.
755 : WHERE_REPLACE should point inside NEW_INSN, so INSN_RHS couldn't be
756 : used instead of SET_SRC. */
757 176 : where_replace = (has_rhs
758 88 : ? &SET_SRC (PATTERN (new_insn))
759 0 : : &PATTERN (new_insn));
760 :
761 88 : new_insn_valid
762 88 : = validate_replace_rtx_part_nosimplify (old, new_rtx, where_replace,
763 : new_insn);
764 :
765 : /* ??? Actually, constrain_operands result depends upon choice of
766 : destination register. E.g. if we allow single register to be an rhs,
767 : and if we try to move dx=ax(as rhs) through ax=dx, we'll result
768 : in invalid insn dx=dx, so we'll loose this rhs here.
769 : Just can't come up with significant testcase for this, so just
770 : leaving it for now. */
771 88 : if (new_insn_valid)
772 : {
773 64 : change_vinsn_in_expr (expr,
774 : create_vinsn_from_insn_rtx (new_insn, false));
775 :
776 : /* Do not allow clobbering the address register of speculative
777 : insns. */
778 64 : if ((EXPR_SPEC_DONE_DS (expr) & SPECULATIVE)
779 64 : && register_unavailable_p (VINSN_REG_USES (EXPR_VINSN (expr)),
780 : expr_dest_reg (expr)))
781 0 : EXPR_TARGET_AVAILABLE (expr) = false;
782 :
783 64 : return true;
784 : }
785 : else
786 : return false;
787 : }
788 : else
789 : return false;
790 : }
791 :
792 : /* Return the number of places WHAT appears within WHERE.
793 : Bail out when we found a reference occupying several hard registers. */
794 : static int
795 101 : count_occurrences_equiv (const_rtx what, const_rtx where)
796 : {
797 101 : int count = 0;
798 101 : subrtx_iterator::array_type array;
799 393 : FOR_EACH_SUBRTX (iter, array, where, NONCONST)
800 : {
801 305 : const_rtx x = *iter;
802 305 : if (REG_P (x) && REGNO (x) == REGNO (what))
803 : {
804 : /* Bail out if mode is different or more than one register is
805 : used. */
806 100 : if (GET_MODE (x) != GET_MODE (what) || REG_NREGS (x) > 1)
807 13 : return 0;
808 88 : count += 1;
809 : }
810 205 : else if (GET_CODE (x) == SUBREG
811 205 : && (!REG_P (SUBREG_REG (x))
812 2 : || REGNO (SUBREG_REG (x)) == REGNO (what)))
813 : /* ??? Do not support substituting regs inside subregs. In that case,
814 : simplify_subreg will be called by validate_replace_rtx, and
815 : unsubstitution will fail later. */
816 : return 0;
817 : }
818 88 : return count;
819 101 : }
820 :
821 : /* Returns TRUE if WHAT is found in WHERE rtx tree. */
822 : static bool
823 101 : rtx_ok_for_substitution_p (rtx what, rtx where)
824 : {
825 101 : return (count_occurrences_equiv (what, where) > 0);
826 : }
827 :
828 :
829 : /* Functions to support register renaming. */
830 :
831 : /* Substitute VI's set source with REGNO. Returns newly created pattern
832 : that has REGNO as its source. */
833 : static rtx_insn *
834 29 : create_insn_rtx_with_rhs (vinsn_t vi, rtx rhs_rtx)
835 : {
836 29 : rtx lhs_rtx;
837 29 : rtx pattern;
838 29 : rtx_insn *insn_rtx;
839 :
840 29 : lhs_rtx = copy_rtx (VINSN_LHS (vi));
841 :
842 29 : pattern = gen_rtx_SET (lhs_rtx, rhs_rtx);
843 29 : insn_rtx = create_insn_rtx_from_pattern (pattern, NULL_RTX);
844 :
845 29 : return insn_rtx;
846 : }
847 :
848 : /* Returns whether INSN's src can be replaced with register number
849 : NEW_SRC_REG. E.g. the following insn is valid for i386:
850 :
851 : (insn:HI 2205 6585 2207 727 ../../gcc/libiberty/regex.c:3337
852 : (set (mem/s:QI (plus:SI (plus:SI (reg/f:SI 7 sp)
853 : (reg:SI 0 ax [orig:770 c1 ] [770]))
854 : (const_int 288 [0x120])) [0 str S1 A8])
855 : (const_int 0 [0x0])) 43 {*movqi_1} (nil)
856 : (nil))
857 :
858 : But if we change (const_int 0 [0x0]) to (reg:QI 4 si), it will be invalid
859 : because of operand constraints:
860 :
861 : (define_insn "*movqi_1"
862 : [(set (match_operand:QI 0 "nonimmediate_operand" "=q,q ,q ,r,r ,?r,m")
863 : (match_operand:QI 1 "general_operand" " q,qn,qm,q,rn,qm,qn")
864 : )]
865 :
866 : So do constrain_operands here, before choosing NEW_SRC_REG as best
867 : reg for rhs. */
868 :
869 : static bool
870 166 : replace_src_with_reg_ok_p (insn_t insn, rtx new_src_reg)
871 : {
872 166 : vinsn_t vi = INSN_VINSN (insn);
873 166 : machine_mode mode;
874 166 : rtx dst_loc;
875 166 : bool res;
876 :
877 166 : gcc_assert (VINSN_SEPARABLE_P (vi));
878 :
879 166 : get_dest_and_mode (insn, &dst_loc, &mode);
880 166 : gcc_assert (mode == GET_MODE (new_src_reg));
881 :
882 166 : if (REG_P (dst_loc) && REGNO (new_src_reg) == REGNO (dst_loc))
883 : return true;
884 :
885 : /* See whether SET_SRC can be replaced with this register. */
886 166 : validate_change (insn, &SET_SRC (PATTERN (insn)), new_src_reg, 1);
887 166 : res = verify_changes (0);
888 166 : cancel_changes (0);
889 :
890 166 : return res;
891 : }
892 :
893 : /* Returns whether INSN still be valid after replacing it's DEST with
894 : register NEW_REG. */
895 : static bool
896 166 : replace_dest_with_reg_ok_p (insn_t insn, rtx new_reg)
897 : {
898 166 : vinsn_t vi = INSN_VINSN (insn);
899 166 : bool res;
900 :
901 : /* We should deal here only with separable insns. */
902 166 : gcc_assert (VINSN_SEPARABLE_P (vi));
903 166 : gcc_assert (GET_MODE (VINSN_LHS (vi)) == GET_MODE (new_reg));
904 :
905 : /* See whether SET_DEST can be replaced with this register. */
906 166 : validate_change (insn, &SET_DEST (PATTERN (insn)), new_reg, 1);
907 166 : res = verify_changes (0);
908 166 : cancel_changes (0);
909 :
910 166 : return res;
911 : }
912 :
913 : /* Create a pattern with rhs of VI and lhs of LHS_RTX. */
914 : static rtx_insn *
915 210 : create_insn_rtx_with_lhs (vinsn_t vi, rtx lhs_rtx)
916 : {
917 210 : rtx rhs_rtx;
918 210 : rtx pattern;
919 210 : rtx_insn *insn_rtx;
920 :
921 210 : rhs_rtx = copy_rtx (VINSN_RHS (vi));
922 :
923 210 : pattern = gen_rtx_SET (lhs_rtx, rhs_rtx);
924 210 : insn_rtx = create_insn_rtx_from_pattern (pattern, NULL_RTX);
925 :
926 210 : return insn_rtx;
927 : }
928 :
929 : /* Substitute lhs in the given expression EXPR for the register with number
930 : NEW_REGNO. SET_DEST may be arbitrary rtx, not only register. */
931 : static void
932 210 : replace_dest_with_reg_in_expr (expr_t expr, rtx new_reg)
933 : {
934 210 : rtx_insn *insn_rtx;
935 210 : vinsn_t vinsn;
936 :
937 210 : insn_rtx = create_insn_rtx_with_lhs (EXPR_VINSN (expr), new_reg);
938 210 : vinsn = create_vinsn_from_insn_rtx (insn_rtx, false);
939 :
940 210 : change_vinsn_in_expr (expr, vinsn);
941 210 : EXPR_WAS_RENAMED (expr) = 1;
942 210 : EXPR_TARGET_AVAILABLE (expr) = 1;
943 210 : }
944 :
945 : /* Returns whether VI writes either one of the USED_REGS registers or,
946 : if a register is a hard one, one of the UNAVAILABLE_HARD_REGS registers. */
947 : static bool
948 161 : vinsn_writes_one_of_regs_p (vinsn_t vi, regset used_regs,
949 : HARD_REG_SET unavailable_hard_regs)
950 : {
951 161 : unsigned regno;
952 161 : reg_set_iterator rsi;
953 :
954 221 : EXECUTE_IF_SET_IN_REG_SET (VINSN_REG_SETS (vi), 0, regno, rsi)
955 : {
956 161 : if (REGNO_REG_SET_P (used_regs, regno))
957 : return true;
958 60 : if (HARD_REGISTER_NUM_P (regno)
959 60 : && TEST_HARD_REG_BIT (unavailable_hard_regs, regno))
960 : return true;
961 : }
962 :
963 60 : EXECUTE_IF_SET_IN_REG_SET (VINSN_REG_CLOBBERS (vi), 0, regno, rsi)
964 : {
965 0 : if (REGNO_REG_SET_P (used_regs, regno))
966 : return true;
967 0 : if (HARD_REGISTER_NUM_P (regno)
968 0 : && TEST_HARD_REG_BIT (unavailable_hard_regs, regno))
969 : return true;
970 : }
971 :
972 : return false;
973 : }
974 :
975 : /* Returns register class of the output register in INSN.
976 : Returns NO_REGS for call insns because some targets have constraints on
977 : destination register of a call insn.
978 :
979 : Code adopted from regrename.cc::build_def_use. */
980 : static enum reg_class
981 2362 : get_reg_class (rtx_insn *insn)
982 : {
983 2362 : int i, n_ops;
984 :
985 2362 : extract_constrain_insn (insn);
986 2362 : preprocess_constraints (insn);
987 2362 : n_ops = recog_data.n_operands;
988 :
989 2362 : const operand_alternative *op_alt = which_op_alt ();
990 2362 : if (asm_noperands (PATTERN (insn)) > 0)
991 : {
992 0 : for (i = 0; i < n_ops; i++)
993 0 : if (recog_data.operand_type[i] == OP_OUT)
994 : {
995 0 : rtx *loc = recog_data.operand_loc[i];
996 0 : rtx op = *loc;
997 0 : enum reg_class cl = alternative_class (op_alt, i);
998 :
999 0 : if (REG_P (op)
1000 0 : && REGNO (op) == ORIGINAL_REGNO (op))
1001 0 : continue;
1002 :
1003 : return cl;
1004 : }
1005 : }
1006 2362 : else if (!CALL_P (insn))
1007 : {
1008 3430 : for (i = 0; i < n_ops + recog_data.n_dups; i++)
1009 : {
1010 2896 : int opn = i < n_ops ? i : recog_data.dup_num[i - n_ops];
1011 2896 : enum reg_class cl = alternative_class (op_alt, opn);
1012 :
1013 2896 : if (recog_data.operand_type[opn] == OP_OUT ||
1014 : recog_data.operand_type[opn] == OP_INOUT)
1015 : return cl;
1016 : }
1017 : }
1018 :
1019 : /* Insns like
1020 : (insn (set (reg:CCZ 17 flags) (compare:CCZ ...)))
1021 : may result in returning NO_REGS, cause flags is written implicitly through
1022 : CMP insn, which has no OP_OUT | OP_INOUT operands. */
1023 : return NO_REGS;
1024 : }
1025 :
1026 : /* Calculate HARD_REGNO_RENAME_OK data for REGNO. */
1027 : static void
1028 74 : init_hard_regno_rename (int regno)
1029 : {
1030 74 : int cur_reg;
1031 :
1032 74 : SET_HARD_REG_BIT (sel_hrd.regs_for_rename[regno], regno);
1033 :
1034 6882 : for (cur_reg = 0; cur_reg < FIRST_PSEUDO_REGISTER; cur_reg++)
1035 : {
1036 : /* We are not interested in renaming in other regs. */
1037 6808 : if (!TEST_HARD_REG_BIT (sel_hrd.regs_ever_used, cur_reg))
1038 391 : continue;
1039 :
1040 6417 : if (HARD_REGNO_RENAME_OK (regno, cur_reg))
1041 5233 : SET_HARD_REG_BIT (sel_hrd.regs_for_rename[regno], cur_reg);
1042 : }
1043 74 : }
1044 :
1045 : /* A wrapper around HARD_REGNO_RENAME_OK that will look into the hard regs
1046 : data first. */
1047 : static inline bool
1048 17327 : sel_hard_regno_rename_ok (int from ATTRIBUTE_UNUSED, int to ATTRIBUTE_UNUSED)
1049 : {
1050 : /* Check whether this is all calculated. */
1051 17327 : if (TEST_HARD_REG_BIT (sel_hrd.regs_for_rename[from], from))
1052 17253 : return TEST_HARD_REG_BIT (sel_hrd.regs_for_rename[from], to);
1053 :
1054 74 : init_hard_regno_rename (from);
1055 :
1056 74 : return TEST_HARD_REG_BIT (sel_hrd.regs_for_rename[from], to);
1057 : }
1058 :
1059 : /* Calculate set of registers that are capable of holding MODE. */
1060 : static void
1061 42 : init_regs_for_mode (machine_mode mode)
1062 : {
1063 42 : int cur_reg;
1064 :
1065 42 : CLEAR_HARD_REG_SET (sel_hrd.regs_for_mode[mode]);
1066 :
1067 3906 : for (cur_reg = 0; cur_reg < FIRST_PSEUDO_REGISTER; cur_reg++)
1068 : {
1069 3864 : int nregs;
1070 3864 : int i;
1071 :
1072 : /* See whether it accepts all modes that occur in
1073 : original insns. */
1074 3864 : if (!targetm.hard_regno_mode_ok (cur_reg, mode))
1075 1402 : continue;
1076 :
1077 2462 : nregs = hard_regno_nregs (cur_reg, mode);
1078 :
1079 3538 : for (i = nregs - 1; i >= 0; --i)
1080 2462 : if (fixed_regs[cur_reg + i]
1081 1622 : || global_regs[cur_reg + i]
1082 : /* Can't use regs which aren't saved by
1083 : the prologue. */
1084 1622 : || !TEST_HARD_REG_BIT (sel_hrd.regs_ever_used, cur_reg + i)
1085 : /* Can't use regs with non-null REG_BASE_VALUE, because adjusting
1086 : it affects aliasing globally and invalidates all AV sets. */
1087 3936 : || get_reg_base_value (cur_reg + i)
1088 : #ifdef LEAF_REGISTERS
1089 : /* We can't use a non-leaf register if we're in a
1090 : leaf function. */
1091 : || (crtl->is_leaf
1092 : && !LEAF_REGISTERS[cur_reg + i])
1093 : #endif
1094 : )
1095 : break;
1096 :
1097 2462 : if (i >= 0)
1098 1386 : continue;
1099 :
1100 : /* If the CUR_REG passed all the checks above,
1101 : then it's ok. */
1102 1076 : SET_HARD_REG_BIT (sel_hrd.regs_for_mode[mode], cur_reg);
1103 : }
1104 :
1105 42 : sel_hrd.regs_for_mode_ok[mode] = true;
1106 42 : }
1107 :
1108 : /* Init all register sets gathered in HRD. */
1109 : static void
1110 131 : init_hard_regs_data (void)
1111 : {
1112 131 : int cur_reg = 0;
1113 131 : int cur_mode = 0;
1114 :
1115 131 : CLEAR_HARD_REG_SET (sel_hrd.regs_ever_used);
1116 12183 : for (cur_reg = 0; cur_reg < FIRST_PSEUDO_REGISTER; cur_reg++)
1117 12052 : if (df_regs_ever_live_p (cur_reg)
1118 12052 : || crtl->abi->clobbers_full_reg_p (cur_reg))
1119 11048 : SET_HARD_REG_BIT (sel_hrd.regs_ever_used, cur_reg);
1120 :
1121 : /* Initialize registers that are valid based on mode when this is
1122 : really needed. */
1123 16375 : for (cur_mode = 0; cur_mode < NUM_MACHINE_MODES; cur_mode++)
1124 16244 : sel_hrd.regs_for_mode_ok[cur_mode] = false;
1125 :
1126 : /* Mark that all HARD_REGNO_RENAME_OK is not calculated. */
1127 12183 : for (cur_reg = 0; cur_reg < FIRST_PSEUDO_REGISTER; cur_reg++)
1128 12052 : CLEAR_HARD_REG_SET (sel_hrd.regs_for_rename[cur_reg]);
1129 :
1130 : #ifdef STACK_REGS
1131 1179 : CLEAR_HARD_REG_SET (sel_hrd.stack_regs);
1132 :
1133 1179 : for (cur_reg = FIRST_STACK_REG; cur_reg <= LAST_STACK_REG; cur_reg++)
1134 1048 : SET_HARD_REG_BIT (sel_hrd.stack_regs, cur_reg);
1135 : #endif
1136 131 : }
1137 :
1138 : /* Mark hardware regs in REG_RENAME_P that are not suitable
1139 : for renaming rhs in INSN due to hardware restrictions (register class,
1140 : modes compatibility etc). This doesn't affect original insn's dest reg,
1141 : if it isn't in USED_REGS. DEF is a definition insn of rhs for which the
1142 : destination register is sought. LHS (DEF->ORIG_INSN) may be REG or MEM.
1143 : Registers that are in used_regs are always marked in
1144 : unavailable_hard_regs as well. */
1145 :
1146 : static void
1147 3147 : mark_unavailable_hard_regs (def_t def, struct reg_rename *reg_rename_p,
1148 : regset used_regs ATTRIBUTE_UNUSED)
1149 : {
1150 3147 : machine_mode mode;
1151 3147 : enum reg_class cl = NO_REGS;
1152 3147 : rtx orig_dest;
1153 3147 : unsigned cur_reg, regno;
1154 3147 : hard_reg_set_iterator hrsi;
1155 :
1156 3147 : gcc_assert (GET_CODE (PATTERN (def->orig_insn)) == SET);
1157 3147 : gcc_assert (reg_rename_p);
1158 :
1159 3147 : orig_dest = SET_DEST (PATTERN (def->orig_insn));
1160 :
1161 : /* We have decided not to rename 'mem = something;' insns, as 'something'
1162 : is usually a register. */
1163 3147 : if (!REG_P (orig_dest))
1164 1319 : return;
1165 :
1166 3147 : regno = REGNO (orig_dest);
1167 :
1168 : /* If before reload, don't try to work with pseudos. */
1169 3147 : if (!reload_completed && !HARD_REGISTER_NUM_P (regno))
1170 : return;
1171 :
1172 2362 : if (reload_completed)
1173 2362 : cl = get_reg_class (def->orig_insn);
1174 :
1175 : /* Stop if the original register is one of the fixed_regs, global_regs or
1176 : frame pointer, or we could not discover its class. */
1177 2362 : if (fixed_regs[regno]
1178 1828 : || global_regs[regno]
1179 1828 : || (!HARD_FRAME_POINTER_IS_FRAME_POINTER && frame_pointer_needed
1180 39 : && regno == HARD_FRAME_POINTER_REGNUM)
1181 : || (HARD_FRAME_POINTER_IS_FRAME_POINTER && frame_pointer_needed
1182 : && regno == FRAME_POINTER_REGNUM)
1183 1828 : || (reload_completed && cl == NO_REGS))
1184 : {
1185 534 : SET_HARD_REG_SET (reg_rename_p->unavailable_hard_regs);
1186 :
1187 : /* Give a chance for original register, if it isn't in used_regs. */
1188 534 : if (!def->crossed_call_abis)
1189 534 : CLEAR_HARD_REG_BIT (reg_rename_p->unavailable_hard_regs, regno);
1190 :
1191 534 : return;
1192 : }
1193 :
1194 : /* If something allocated on stack in this function, mark frame pointer
1195 : register unavailable, considering also modes.
1196 : FIXME: it is enough to do this once per all original defs. */
1197 1828 : if (frame_pointer_needed)
1198 : {
1199 39 : add_to_hard_reg_set (®_rename_p->unavailable_hard_regs,
1200 39 : Pmode, FRAME_POINTER_REGNUM);
1201 :
1202 39 : if (!HARD_FRAME_POINTER_IS_FRAME_POINTER)
1203 39 : add_to_hard_reg_set (®_rename_p->unavailable_hard_regs,
1204 : Pmode, HARD_FRAME_POINTER_REGNUM);
1205 : }
1206 :
1207 : #ifdef STACK_REGS
1208 : /* For the stack registers the presence of FIRST_STACK_REG in USED_REGS
1209 : is equivalent to as if all stack regs were in this set.
1210 : I.e. no stack register can be renamed, and even if it's an original
1211 : register here we make sure it won't be lifted over it's previous def
1212 : (it's previous def will appear as if it's a FIRST_STACK_REG def.
1213 : The HARD_REGNO_RENAME_OK covers other cases in condition below. */
1214 1828 : if (IN_RANGE (REGNO (orig_dest), FIRST_STACK_REG, LAST_STACK_REG)
1215 1828 : && REGNO_REG_SET_P (used_regs, FIRST_STACK_REG))
1216 1828 : reg_rename_p->unavailable_hard_regs |= sel_hrd.stack_regs;
1217 : #endif
1218 :
1219 1828 : mode = GET_MODE (orig_dest);
1220 :
1221 : /* If there's a call on this path, make regs from full_reg_clobbers
1222 : unavailable.
1223 :
1224 : ??? It would be better to track the set of clobbered registers
1225 : directly, but that would be quite expensive in a def_t. */
1226 1828 : if (def->crossed_call_abis)
1227 455 : reg_rename_p->unavailable_hard_regs
1228 910 : |= call_clobbers_in_region (def->crossed_call_abis,
1229 910 : reg_class_contents[ALL_REGS], mode);
1230 :
1231 : /* Stop here before reload: we need FRAME_REGS, STACK_REGS, and
1232 : crossed_call_abis, but not register classes. */
1233 1828 : if (!reload_completed)
1234 : return;
1235 :
1236 : /* Leave regs as 'available' only from the current
1237 : register class. */
1238 1828 : reg_rename_p->available_for_renaming = reg_class_contents[cl];
1239 :
1240 : /* Leave only registers available for this mode. */
1241 1828 : if (!sel_hrd.regs_for_mode_ok[mode])
1242 42 : init_regs_for_mode (mode);
1243 1828 : reg_rename_p->available_for_renaming &= sel_hrd.regs_for_mode[mode];
1244 :
1245 : /* Leave only those that are ok to rename. */
1246 19155 : EXECUTE_IF_SET_IN_HARD_REG_SET (reg_rename_p->available_for_renaming,
1247 : 0, cur_reg, hrsi)
1248 : {
1249 17327 : int nregs;
1250 17327 : int i;
1251 :
1252 17327 : nregs = hard_regno_nregs (cur_reg, mode);
1253 17327 : gcc_assert (nregs > 0);
1254 :
1255 34654 : for (i = nregs - 1; i >= 0; --i)
1256 17327 : if (! sel_hard_regno_rename_ok (regno + i, cur_reg + i))
1257 : break;
1258 :
1259 17327 : if (i >= 0)
1260 0 : CLEAR_HARD_REG_BIT (reg_rename_p->available_for_renaming,
1261 : cur_reg);
1262 : }
1263 :
1264 1828 : reg_rename_p->available_for_renaming &= ~reg_rename_p->unavailable_hard_regs;
1265 :
1266 : /* Regno is always ok from the renaming part of view, but it really
1267 : could be in *unavailable_hard_regs already, so set it here instead
1268 : of there. */
1269 1828 : SET_HARD_REG_BIT (reg_rename_p->available_for_renaming, regno);
1270 : }
1271 :
1272 : /* reg_rename_tick[REG1] > reg_rename_tick[REG2] if REG1 was chosen as the
1273 : best register more recently than REG2. */
1274 : static int reg_rename_tick[FIRST_PSEUDO_REGISTER];
1275 :
1276 : /* Indicates the number of times renaming happened before the current one. */
1277 : static int reg_rename_this_tick;
1278 :
1279 : /* Choose the register among free, that is suitable for storing
1280 : the rhs value.
1281 :
1282 : ORIGINAL_INSNS is the list of insns where the operation (rhs)
1283 : originally appears. There could be multiple original operations
1284 : for single rhs since we moving it up and merging along different
1285 : paths.
1286 :
1287 : Some code is adapted from regrename.cc (regrename_optimize).
1288 : If original register is available, function returns it.
1289 : Otherwise it performs the checks, so the new register should
1290 : comply with the following:
1291 : - it should not violate any live ranges (such registers are in
1292 : REG_RENAME_P->available_for_renaming set);
1293 : - it should not be in the HARD_REGS_USED regset;
1294 : - it should be in the class compatible with original uses;
1295 : - it should not be clobbered through reference with different mode;
1296 : - if we're in the leaf function, then the new register should
1297 : not be in the LEAF_REGISTERS;
1298 : - etc.
1299 :
1300 : If several registers meet the conditions, the register with smallest
1301 : tick is returned to achieve more even register allocation.
1302 :
1303 : If original register seems to be ok, we set *IS_ORIG_REG_P_PTR to true.
1304 :
1305 : If no register satisfies the above conditions, NULL_RTX is returned. */
1306 : static rtx
1307 2340 : choose_best_reg_1 (HARD_REG_SET hard_regs_used,
1308 : struct reg_rename *reg_rename_p,
1309 : def_list_t original_insns, bool *is_orig_reg_p_ptr)
1310 : {
1311 2340 : int best_new_reg;
1312 2340 : unsigned cur_reg;
1313 2340 : machine_mode mode = VOIDmode;
1314 2340 : unsigned regno, i, n;
1315 2340 : hard_reg_set_iterator hrsi;
1316 2340 : def_list_iterator di;
1317 2340 : def_t def;
1318 :
1319 : /* If original register is available, return it. */
1320 2340 : *is_orig_reg_p_ptr = true;
1321 :
1322 4684 : FOR_EACH_DEF (def, di, original_insns)
1323 : {
1324 2350 : rtx orig_dest = SET_DEST (PATTERN (def->orig_insn));
1325 :
1326 2350 : gcc_assert (REG_P (orig_dest));
1327 :
1328 : /* Check that all original operations have the same mode.
1329 : This is done for the next loop; if we'd return from this
1330 : loop, we'd check only part of them, but in this case
1331 : it doesn't matter. */
1332 2350 : if (mode == VOIDmode)
1333 2340 : mode = GET_MODE (orig_dest);
1334 2350 : gcc_assert (mode == GET_MODE (orig_dest));
1335 :
1336 2350 : regno = REGNO (orig_dest);
1337 2356 : for (i = 0, n = REG_NREGS (orig_dest); i < n; i++)
1338 2350 : if (TEST_HARD_REG_BIT (hard_regs_used, regno + i))
1339 : break;
1340 :
1341 : /* All hard registers are available. */
1342 2350 : if (i == n)
1343 : {
1344 6 : gcc_assert (mode != VOIDmode);
1345 :
1346 : /* Hard registers should not be shared. */
1347 6 : return gen_rtx_REG (mode, regno);
1348 : }
1349 : }
1350 :
1351 2334 : *is_orig_reg_p_ptr = false;
1352 2334 : best_new_reg = -1;
1353 :
1354 : /* Among all available regs choose the register that was
1355 : allocated earliest. */
1356 19918 : EXECUTE_IF_SET_IN_HARD_REG_SET (reg_rename_p->available_for_renaming,
1357 : 0, cur_reg, hrsi)
1358 18115 : if (! TEST_HARD_REG_BIT (hard_regs_used, cur_reg))
1359 : {
1360 : /* Check that all hard regs for mode are available. */
1361 547 : for (i = 1, n = hard_regno_nregs (cur_reg, mode); i < n; i++)
1362 0 : if (TEST_HARD_REG_BIT (hard_regs_used, cur_reg + i)
1363 0 : || !TEST_HARD_REG_BIT (reg_rename_p->available_for_renaming,
1364 : cur_reg + i))
1365 : break;
1366 :
1367 547 : if (i < n)
1368 0 : continue;
1369 :
1370 : /* All hard registers are available. */
1371 547 : if (best_new_reg < 0
1372 1 : || reg_rename_tick[cur_reg] < reg_rename_tick[best_new_reg])
1373 : {
1374 547 : best_new_reg = cur_reg;
1375 :
1376 : /* Return immediately when we know there's no better reg. */
1377 547 : if (! reg_rename_tick[best_new_reg])
1378 : break;
1379 : }
1380 : }
1381 :
1382 2334 : if (best_new_reg >= 0)
1383 : {
1384 : /* Use the check from the above loop. */
1385 546 : gcc_assert (mode != VOIDmode);
1386 546 : return gen_rtx_REG (mode, best_new_reg);
1387 : }
1388 :
1389 : return NULL_RTX;
1390 : }
1391 :
1392 : /* A wrapper around choose_best_reg_1 () to verify that we make correct
1393 : assumptions about available registers in the function. */
1394 : static rtx
1395 2340 : choose_best_reg (HARD_REG_SET hard_regs_used, struct reg_rename *reg_rename_p,
1396 : def_list_t original_insns, bool *is_orig_reg_p_ptr)
1397 : {
1398 2340 : rtx best_reg = choose_best_reg_1 (hard_regs_used, reg_rename_p,
1399 : original_insns, is_orig_reg_p_ptr);
1400 :
1401 : /* FIXME loop over hard_regno_nregs here. */
1402 2340 : gcc_assert (best_reg == NULL_RTX
1403 : || TEST_HARD_REG_BIT (sel_hrd.regs_ever_used, REGNO (best_reg)));
1404 :
1405 2340 : return best_reg;
1406 : }
1407 :
1408 : /* Choose the pseudo register for storing rhs value. As this is supposed
1409 : to work before reload, we return either the original register or make
1410 : the new one. The parameters are the same that in choose_nest_reg_1
1411 : functions, except that USED_REGS may contain pseudos.
1412 : If we work with hard regs, check also REG_RENAME_P->UNAVAILABLE_HARD_REGS.
1413 :
1414 : TODO: take into account register pressure while doing this. Up to this
1415 : moment, this function would never return NULL for pseudos, but we should
1416 : not rely on this. */
1417 : static rtx
1418 289 : choose_best_pseudo_reg (regset used_regs,
1419 : struct reg_rename *reg_rename_p,
1420 : def_list_t original_insns, bool *is_orig_reg_p_ptr)
1421 : {
1422 289 : def_list_iterator i;
1423 289 : def_t def;
1424 289 : machine_mode mode = VOIDmode;
1425 289 : bool bad_hard_regs = false;
1426 :
1427 : /* We should not use this after reload. */
1428 289 : gcc_assert (!reload_completed);
1429 :
1430 : /* If original register is available, return it. */
1431 289 : *is_orig_reg_p_ptr = true;
1432 :
1433 1074 : FOR_EACH_DEF (def, i, original_insns)
1434 : {
1435 785 : rtx dest = SET_DEST (PATTERN (def->orig_insn));
1436 785 : int orig_regno;
1437 :
1438 785 : gcc_assert (REG_P (dest));
1439 :
1440 : /* Check that all original operations have the same mode. */
1441 785 : if (mode == VOIDmode)
1442 289 : mode = GET_MODE (dest);
1443 : else
1444 496 : gcc_assert (mode == GET_MODE (dest));
1445 785 : orig_regno = REGNO (dest);
1446 :
1447 : /* Check that nothing in used_regs intersects with orig_regno. When
1448 : we have a hard reg here, still loop over hard_regno_nregs. */
1449 785 : if (HARD_REGISTER_NUM_P (orig_regno))
1450 : {
1451 0 : int j, n;
1452 0 : for (j = 0, n = REG_NREGS (dest); j < n; j++)
1453 0 : if (REGNO_REG_SET_P (used_regs, orig_regno + j))
1454 : break;
1455 0 : if (j < n)
1456 0 : continue;
1457 : }
1458 : else
1459 : {
1460 785 : if (REGNO_REG_SET_P (used_regs, orig_regno))
1461 785 : continue;
1462 : }
1463 0 : if (HARD_REGISTER_NUM_P (orig_regno))
1464 : {
1465 0 : gcc_assert (df_regs_ever_live_p (orig_regno));
1466 :
1467 : /* For hard registers, we have to check hardware imposed
1468 : limitations (frame/stack registers, calls crossed). */
1469 0 : if (!TEST_HARD_REG_BIT (reg_rename_p->unavailable_hard_regs,
1470 : orig_regno))
1471 : {
1472 : /* Don't let register cross a call if it doesn't already
1473 : cross one. This condition is written in accordance with
1474 : that in sched-deps.cc sched_analyze_reg(). */
1475 0 : if (!reg_rename_p->crossed_call_abis
1476 0 : || REG_N_CALLS_CROSSED (orig_regno) > 0)
1477 0 : return gen_rtx_REG (mode, orig_regno);
1478 : }
1479 :
1480 : bad_hard_regs = true;
1481 : }
1482 : else
1483 : return dest;
1484 : }
1485 :
1486 289 : *is_orig_reg_p_ptr = false;
1487 :
1488 : /* We had some original hard registers that couldn't be used.
1489 : Those were likely special. Don't try to create a pseudo. */
1490 289 : if (bad_hard_regs)
1491 : return NULL_RTX;
1492 :
1493 : /* We haven't found a register from original operations. Get a new one.
1494 : FIXME: control register pressure somehow. */
1495 289 : {
1496 289 : rtx new_reg = gen_reg_rtx (mode);
1497 :
1498 289 : gcc_assert (mode != VOIDmode);
1499 :
1500 289 : max_regno = max_reg_num ();
1501 289 : maybe_extend_reg_info_p ();
1502 289 : REG_N_CALLS_CROSSED (REGNO (new_reg))
1503 289 : = reg_rename_p->crossed_call_abis ? 1 : 0;
1504 :
1505 289 : return new_reg;
1506 : }
1507 : }
1508 :
1509 : /* True when target of EXPR is available due to EXPR_TARGET_AVAILABLE,
1510 : USED_REGS and REG_RENAME_P->UNAVAILABLE_HARD_REGS. */
1511 : static void
1512 2629 : verify_target_availability (expr_t expr, regset used_regs,
1513 : struct reg_rename *reg_rename_p)
1514 : {
1515 2629 : unsigned n, i, regno;
1516 2629 : machine_mode mode;
1517 2629 : bool target_available, live_available, hard_available;
1518 :
1519 2629 : if (!REG_P (EXPR_LHS (expr)) || EXPR_TARGET_AVAILABLE (expr) < 0)
1520 : return;
1521 :
1522 2613 : regno = expr_dest_regno (expr);
1523 2613 : mode = GET_MODE (EXPR_LHS (expr));
1524 2613 : target_available = EXPR_TARGET_AVAILABLE (expr) == 1;
1525 2613 : n = HARD_REGISTER_NUM_P (regno) ? hard_regno_nregs (regno, mode) : 1;
1526 :
1527 2613 : live_available = hard_available = true;
1528 5226 : for (i = 0; i < n; i++)
1529 : {
1530 2613 : if (bitmap_bit_p (used_regs, regno + i))
1531 2527 : live_available = false;
1532 2613 : if (TEST_HARD_REG_BIT (reg_rename_p->unavailable_hard_regs, regno + i))
1533 325 : hard_available = false;
1534 : }
1535 :
1536 : /* When target is not available, it may be due to hard register
1537 : restrictions, e.g. crosses calls, so we check hard_available too. */
1538 2613 : if (target_available)
1539 11 : gcc_assert (live_available);
1540 : else
1541 : /* Check only if we haven't scheduled something on the previous fence,
1542 : cause due to MAX_SOFTWARE_LOOKAHEAD_WINDOW_SIZE issues
1543 : and having more than one fence, we may end having targ_un in a block
1544 : in which successors target register is actually available.
1545 :
1546 : The last condition handles the case when a dependence from a call insn
1547 : was created in sched-deps.cc for insns with destination registers that
1548 : never crossed a call before, but do cross one after our code motion.
1549 :
1550 : FIXME: in the latter case, we just uselessly called find_used_regs,
1551 : because we can't move this expression with any other register
1552 : as well. */
1553 2602 : gcc_assert (scheduled_something_on_previous_fence || !live_available
1554 : || !hard_available
1555 : || (!reload_completed
1556 : && reg_rename_p->crossed_call_abis
1557 : && REG_N_CALLS_CROSSED (regno) == 0));
1558 : }
1559 :
1560 : /* Collect unavailable registers due to liveness for EXPR from BNDS
1561 : into USED_REGS. Save additional information about available
1562 : registers and unavailable due to hardware restriction registers
1563 : into REG_RENAME_P structure. Save original insns into ORIGINAL_INSNS
1564 : list. */
1565 : static void
1566 2790 : collect_unavailable_regs_from_bnds (expr_t expr, blist_t bnds, regset used_regs,
1567 : struct reg_rename *reg_rename_p,
1568 : def_list_t *original_insns)
1569 : {
1570 5580 : for (; bnds; bnds = BLIST_NEXT (bnds))
1571 : {
1572 2790 : bool res;
1573 2790 : av_set_t orig_ops = NULL;
1574 2790 : bnd_t bnd = BLIST_BND (bnds);
1575 :
1576 : /* If the chosen best expr doesn't belong to current boundary,
1577 : skip it. */
1578 2790 : if (!av_set_is_in_p (BND_AV1 (bnd), EXPR_VINSN (expr)))
1579 0 : continue;
1580 :
1581 : /* Put in ORIG_OPS all exprs from this boundary that became
1582 : RES on top. */
1583 2790 : orig_ops = find_sequential_best_exprs (bnd, expr, false);
1584 :
1585 : /* Compute used regs and OR it into the USED_REGS. */
1586 2790 : res = find_used_regs (BND_TO (bnd), orig_ops, used_regs,
1587 : reg_rename_p, original_insns);
1588 :
1589 : /* FIXME: the assert is true until we'd have several boundaries. */
1590 2790 : gcc_assert (res);
1591 2790 : av_set_clear (&orig_ops);
1592 : }
1593 2790 : }
1594 :
1595 : /* Return TRUE if it is possible to replace LHSes of ORIG_INSNS with BEST_REG.
1596 : If BEST_REG is valid, replace LHS of EXPR with it. */
1597 : static bool
1598 161 : try_replace_dest_reg (ilist_t orig_insns, rtx best_reg, expr_t expr)
1599 : {
1600 : /* Try whether we'll be able to generate the insn
1601 : 'dest := best_reg' at the place of the original operation. */
1602 339 : for (; orig_insns; orig_insns = ILIST_NEXT (orig_insns))
1603 : {
1604 178 : insn_t orig_insn = DEF_LIST_DEF (orig_insns)->orig_insn;
1605 :
1606 178 : gcc_assert (EXPR_SEPARABLE_P (INSN_EXPR (orig_insn)));
1607 :
1608 178 : if (REGNO (best_reg) != REGNO (INSN_LHS (orig_insn))
1609 178 : && (! replace_src_with_reg_ok_p (orig_insn, best_reg)
1610 166 : || ! replace_dest_with_reg_ok_p (orig_insn, best_reg)))
1611 0 : return false;
1612 : }
1613 :
1614 : /* Make sure that EXPR has the right destination
1615 : register. */
1616 161 : if (expr_dest_regno (expr) != REGNO (best_reg))
1617 : {
1618 155 : rtx_insn *vinsn = EXPR_INSN_RTX (expr);
1619 155 : validate_change (vinsn, &SET_DEST (PATTERN (vinsn)), best_reg, 1);
1620 155 : bool res = verify_changes (0);
1621 155 : cancel_changes (0);
1622 155 : if (!res)
1623 : return false;
1624 155 : replace_dest_with_reg_in_expr (expr, best_reg);
1625 : }
1626 : else
1627 6 : EXPR_TARGET_AVAILABLE (expr) = 1;
1628 :
1629 : return true;
1630 : }
1631 :
1632 : /* Select and assign best register to EXPR searching from BNDS.
1633 : Set *IS_ORIG_REG_P to TRUE if original register was selected.
1634 : Return FALSE if no register can be chosen, which could happen when:
1635 : * EXPR_SEPARABLE_P is true but we were unable to find suitable register;
1636 : * EXPR_SEPARABLE_P is false but the insn sets/clobbers one of the registers
1637 : that are used on the moving path. */
1638 : static bool
1639 2790 : find_best_reg_for_expr (expr_t expr, blist_t bnds, bool *is_orig_reg_p)
1640 : {
1641 2790 : static struct reg_rename reg_rename_data;
1642 :
1643 2790 : regset used_regs;
1644 2790 : def_list_t original_insns = NULL;
1645 2790 : bool reg_ok;
1646 :
1647 2790 : *is_orig_reg_p = false;
1648 :
1649 : /* Don't bother to do anything if this insn doesn't set any registers. */
1650 2790 : if (bitmap_empty_p (VINSN_REG_SETS (EXPR_VINSN (expr)))
1651 2790 : && bitmap_empty_p (VINSN_REG_CLOBBERS (EXPR_VINSN (expr))))
1652 : return true;
1653 :
1654 2790 : used_regs = get_clear_regset_from_pool ();
1655 2790 : CLEAR_HARD_REG_SET (reg_rename_data.unavailable_hard_regs);
1656 :
1657 2790 : collect_unavailable_regs_from_bnds (expr, bnds, used_regs, ®_rename_data,
1658 : &original_insns);
1659 :
1660 : /* If after reload, make sure we're working with hard regs here. */
1661 2790 : if (flag_checking && reload_completed)
1662 : {
1663 2350 : reg_set_iterator rsi;
1664 2350 : unsigned i;
1665 :
1666 2350 : EXECUTE_IF_SET_IN_REG_SET (used_regs, FIRST_PSEUDO_REGISTER, i, rsi)
1667 0 : gcc_unreachable ();
1668 : }
1669 :
1670 2790 : if (EXPR_SEPARABLE_P (expr))
1671 : {
1672 2629 : rtx best_reg = NULL_RTX;
1673 : /* Check that we have computed availability of a target register
1674 : correctly. */
1675 2629 : verify_target_availability (expr, used_regs, ®_rename_data);
1676 :
1677 : /* Turn everything in hard regs after reload. */
1678 2629 : if (reload_completed)
1679 : {
1680 : HARD_REG_SET hard_regs_used;
1681 2340 : REG_SET_TO_HARD_REG_SET (hard_regs_used, used_regs);
1682 :
1683 : /* Join hard registers unavailable due to register class
1684 : restrictions and live range intersection. */
1685 2340 : hard_regs_used |= reg_rename_data.unavailable_hard_regs;
1686 :
1687 2340 : best_reg = choose_best_reg (hard_regs_used, ®_rename_data,
1688 : original_insns, is_orig_reg_p);
1689 : }
1690 : else
1691 289 : best_reg = choose_best_pseudo_reg (used_regs, ®_rename_data,
1692 : original_insns, is_orig_reg_p);
1693 :
1694 2629 : if (!best_reg)
1695 : reg_ok = false;
1696 841 : else if (*is_orig_reg_p)
1697 : {
1698 : /* In case of unification BEST_REG may be different from EXPR's LHS
1699 : when EXPR's LHS is unavailable, and there is another LHS among
1700 : ORIGINAL_INSNS. */
1701 6 : reg_ok = try_replace_dest_reg (original_insns, best_reg, expr);
1702 : }
1703 : else
1704 : {
1705 : /* Forbid renaming of low-cost insns. */
1706 835 : if (sel_vinsn_cost (EXPR_VINSN (expr)) < 2)
1707 : reg_ok = false;
1708 : else
1709 155 : reg_ok = try_replace_dest_reg (original_insns, best_reg, expr);
1710 : }
1711 : }
1712 : else
1713 : {
1714 : /* If !EXPR_SCHEDULE_AS_RHS (EXPR), just make sure INSN doesn't set
1715 : any of the HARD_REGS_USED set. */
1716 161 : if (vinsn_writes_one_of_regs_p (EXPR_VINSN (expr), used_regs,
1717 : reg_rename_data.unavailable_hard_regs))
1718 : {
1719 101 : reg_ok = false;
1720 101 : gcc_assert (EXPR_TARGET_AVAILABLE (expr) <= 0);
1721 : }
1722 : else
1723 : {
1724 60 : reg_ok = true;
1725 60 : gcc_assert (EXPR_TARGET_AVAILABLE (expr) != 0);
1726 : }
1727 : }
1728 :
1729 2790 : ilist_clear (&original_insns);
1730 2790 : return_regset_to_pool (used_regs);
1731 :
1732 2790 : return reg_ok;
1733 : }
1734 :
1735 :
1736 : /* Return true if dependence described by DS can be overcomed. */
1737 : static bool
1738 4646 : can_speculate_dep_p (ds_t ds)
1739 : {
1740 4646 : if (spec_info == NULL)
1741 : return false;
1742 :
1743 : /* Leave only speculative data. */
1744 0 : ds &= SPECULATIVE;
1745 :
1746 0 : if (ds == 0)
1747 : return false;
1748 :
1749 0 : {
1750 : /* FIXME: make sched-deps.cc produce only those non-hard dependencies,
1751 : that we can overcome. */
1752 0 : ds_t spec_mask = spec_info->mask;
1753 :
1754 0 : if ((ds & spec_mask) != ds)
1755 : return false;
1756 : }
1757 :
1758 0 : if (ds_weak (ds) < spec_info->data_weakness_cutoff)
1759 : return false;
1760 :
1761 : return true;
1762 : }
1763 :
1764 : /* Get a speculation check instruction.
1765 : C_EXPR is a speculative expression,
1766 : CHECK_DS describes speculations that should be checked,
1767 : ORIG_INSN is the original non-speculative insn in the stream. */
1768 : static insn_t
1769 0 : create_speculation_check (expr_t c_expr, ds_t check_ds, insn_t orig_insn)
1770 : {
1771 0 : rtx check_pattern;
1772 0 : rtx_insn *insn_rtx;
1773 0 : insn_t insn;
1774 0 : basic_block recovery_block;
1775 0 : rtx_insn *label;
1776 :
1777 : /* Create a recovery block if target is going to emit branchy check, or if
1778 : ORIG_INSN was speculative already. */
1779 0 : if (targetm.sched.needs_block_p (check_ds)
1780 0 : || EXPR_SPEC_DONE_DS (INSN_EXPR (orig_insn)) != 0)
1781 : {
1782 0 : recovery_block = sel_create_recovery_block (orig_insn);
1783 0 : label = BB_HEAD (recovery_block);
1784 : }
1785 : else
1786 : {
1787 : recovery_block = NULL;
1788 : label = NULL;
1789 : }
1790 :
1791 : /* Get pattern of the check. */
1792 0 : check_pattern = targetm.sched.gen_spec_check (EXPR_INSN_RTX (c_expr), label,
1793 : check_ds);
1794 :
1795 0 : gcc_assert (check_pattern != NULL);
1796 :
1797 : /* Emit check. */
1798 0 : insn_rtx = create_insn_rtx_from_pattern (check_pattern, label);
1799 :
1800 0 : insn = sel_gen_insn_from_rtx_after (insn_rtx, INSN_EXPR (orig_insn),
1801 0 : INSN_SEQNO (orig_insn), orig_insn);
1802 :
1803 : /* Make check to be non-speculative. */
1804 0 : EXPR_SPEC_DONE_DS (INSN_EXPR (insn)) = 0;
1805 0 : INSN_SPEC_CHECKED_DS (insn) = check_ds;
1806 :
1807 : /* Decrease priority of check by difference of load/check instruction
1808 : latencies. */
1809 0 : EXPR_PRIORITY (INSN_EXPR (insn)) -= (sel_vinsn_cost (INSN_VINSN (orig_insn))
1810 0 : - sel_vinsn_cost (INSN_VINSN (insn)));
1811 :
1812 : /* Emit copy of original insn (though with replaced target register,
1813 : if needed) to the recovery block. */
1814 0 : if (recovery_block != NULL)
1815 : {
1816 0 : rtx twin_rtx;
1817 :
1818 0 : twin_rtx = copy_rtx (PATTERN (EXPR_INSN_RTX (c_expr)));
1819 0 : twin_rtx = create_insn_rtx_from_pattern (twin_rtx, NULL_RTX);
1820 0 : sel_gen_recovery_insn_from_rtx_after (twin_rtx,
1821 0 : INSN_EXPR (orig_insn),
1822 0 : INSN_SEQNO (insn),
1823 0 : bb_note (recovery_block));
1824 : }
1825 :
1826 : /* If we've generated a data speculation check, make sure
1827 : that all the bookkeeping instruction we'll create during
1828 : this move_op () will allocate an ALAT entry so that the
1829 : check won't fail.
1830 : In case of control speculation we must convert C_EXPR to control
1831 : speculative mode, because failing to do so will bring us an exception
1832 : thrown by the non-control-speculative load. */
1833 0 : check_ds = ds_get_max_dep_weak (check_ds);
1834 0 : speculate_expr (c_expr, check_ds);
1835 :
1836 0 : return insn;
1837 : }
1838 :
1839 : /* True when INSN is a "regN = regN" copy. */
1840 : static bool
1841 28 : identical_copy_p (rtx_insn *insn)
1842 : {
1843 28 : rtx lhs, rhs, pat;
1844 :
1845 28 : pat = PATTERN (insn);
1846 :
1847 28 : if (GET_CODE (pat) != SET)
1848 : return false;
1849 :
1850 25 : lhs = SET_DEST (pat);
1851 25 : if (!REG_P (lhs))
1852 : return false;
1853 :
1854 25 : rhs = SET_SRC (pat);
1855 25 : if (!REG_P (rhs))
1856 : return false;
1857 :
1858 25 : return REGNO (lhs) == REGNO (rhs);
1859 : }
1860 :
1861 : /* Undo all transformations on *AV_PTR that were done when
1862 : moving through INSN. */
1863 : static void
1864 48771 : undo_transformations (av_set_t *av_ptr, rtx_insn *insn)
1865 : {
1866 48771 : av_set_iterator av_iter;
1867 48771 : expr_t expr;
1868 48771 : av_set_t new_set = NULL;
1869 :
1870 : /* First, kill any EXPR that uses registers set by an insn. This is
1871 : required for correctness. */
1872 146943 : FOR_EACH_EXPR_1 (expr, av_iter, av_ptr)
1873 49086 : if (!sched_insns_conditions_mutex_p (insn, EXPR_INSN_RTX (expr))
1874 49086 : && bitmap_intersect_p (INSN_REG_SETS (insn),
1875 49086 : VINSN_REG_USES (EXPR_VINSN (expr)))
1876 : /* When an insn looks like 'r1 = r1', we could substitute through
1877 : it, but the above condition will still hold. This happened with
1878 : gcc.c-torture/execute/961125-1.c. */
1879 49114 : && !identical_copy_p (insn))
1880 : {
1881 28 : if (sched_verbose >= 6)
1882 0 : sel_print ("Expr %d removed due to use/set conflict\n",
1883 0 : INSN_UID (EXPR_INSN_RTX (expr)));
1884 28 : av_set_iter_remove (&av_iter);
1885 : }
1886 :
1887 : /* Undo transformations looking at the history vector. */
1888 146887 : FOR_EACH_EXPR (expr, av_iter, *av_ptr)
1889 : {
1890 49058 : int index = find_in_history_vect (EXPR_HISTORY_OF_CHANGES (expr),
1891 : insn, EXPR_VINSN (expr), true);
1892 :
1893 49058 : if (index >= 0)
1894 : {
1895 166 : expr_history_def *phist;
1896 :
1897 166 : phist = &EXPR_HISTORY_OF_CHANGES (expr)[index];
1898 :
1899 166 : switch (phist->type)
1900 : {
1901 0 : case TRANS_SPECULATION:
1902 0 : {
1903 0 : ds_t old_ds, new_ds;
1904 :
1905 : /* Compute the difference between old and new speculative
1906 : statuses: that's what we need to check.
1907 : Earlier we used to assert that the status will really
1908 : change. This no longer works because only the probability
1909 : bits in the status may have changed during compute_av_set,
1910 : and in the case of merging different probabilities of the
1911 : same speculative status along different paths we do not
1912 : record this in the history vector. */
1913 0 : old_ds = phist->spec_ds;
1914 0 : new_ds = EXPR_SPEC_DONE_DS (expr);
1915 :
1916 0 : old_ds &= SPECULATIVE;
1917 0 : new_ds &= SPECULATIVE;
1918 0 : new_ds &= ~old_ds;
1919 :
1920 0 : EXPR_SPEC_TO_CHECK_DS (expr) |= new_ds;
1921 0 : break;
1922 : }
1923 166 : case TRANS_SUBSTITUTION:
1924 166 : {
1925 166 : expr_def _tmp_expr, *tmp_expr = &_tmp_expr;
1926 166 : vinsn_t new_vi;
1927 166 : bool add = true;
1928 :
1929 166 : new_vi = phist->old_expr_vinsn;
1930 :
1931 166 : gcc_assert (VINSN_SEPARABLE_P (new_vi)
1932 : == EXPR_SEPARABLE_P (expr));
1933 166 : copy_expr (tmp_expr, expr);
1934 :
1935 166 : if (vinsn_equal_p (phist->new_expr_vinsn,
1936 : EXPR_VINSN (tmp_expr)))
1937 166 : change_vinsn_in_expr (tmp_expr, new_vi);
1938 : else
1939 : /* This happens when we're unsubstituting on a bookkeeping
1940 : copy, which was in turn substituted. The history is wrong
1941 : in this case. Do it the hard way. */
1942 0 : add = substitute_reg_in_expr (tmp_expr, insn, true);
1943 166 : if (add)
1944 166 : av_set_add (&new_set, tmp_expr);
1945 166 : clear_expr (tmp_expr);
1946 166 : break;
1947 : }
1948 0 : default:
1949 0 : gcc_unreachable ();
1950 : }
1951 : }
1952 :
1953 : }
1954 :
1955 48771 : av_set_union_and_clear (av_ptr, &new_set, NULL);
1956 48771 : }
1957 :
1958 :
1959 : /* Moveup_* helpers for code motion and computing av sets. */
1960 :
1961 : /* Propagates EXPR inside an insn group through THROUGH_INSN.
1962 : The difference from the below function is that only substitution is
1963 : performed. */
1964 : static enum MOVEUP_EXPR_CODE
1965 0 : moveup_expr_inside_insn_group (expr_t expr, insn_t through_insn)
1966 : {
1967 0 : vinsn_t vi = EXPR_VINSN (expr);
1968 0 : ds_t *has_dep_p;
1969 0 : ds_t full_ds;
1970 :
1971 : /* Do this only inside insn group. */
1972 0 : gcc_assert (INSN_SCHED_CYCLE (through_insn) > 0);
1973 :
1974 0 : full_ds = has_dependence_p (expr, through_insn, &has_dep_p);
1975 0 : if (full_ds == 0)
1976 : return MOVEUP_EXPR_SAME;
1977 :
1978 : /* Substitution is the possible choice in this case. */
1979 0 : if (has_dep_p[DEPS_IN_RHS])
1980 : {
1981 : /* Can't substitute UNIQUE VINSNs. */
1982 0 : gcc_assert (!VINSN_UNIQUE_P (vi));
1983 :
1984 0 : if (can_substitute_through_p (through_insn,
1985 : has_dep_p[DEPS_IN_RHS])
1986 0 : && substitute_reg_in_expr (expr, through_insn, false))
1987 : {
1988 0 : EXPR_WAS_SUBSTITUTED (expr) = true;
1989 0 : return MOVEUP_EXPR_CHANGED;
1990 : }
1991 :
1992 : /* Don't care about this, as even true dependencies may be allowed
1993 : in an insn group. */
1994 0 : return MOVEUP_EXPR_SAME;
1995 : }
1996 :
1997 : /* This can catch output dependencies in COND_EXECs. */
1998 0 : if (has_dep_p[DEPS_IN_INSN])
1999 : return MOVEUP_EXPR_NULL;
2000 :
2001 : /* This is either an output or an anti dependence, which usually have
2002 : a zero latency. Allow this here, if we'd be wrong, tick_check_p
2003 : will fix this. */
2004 0 : gcc_assert (has_dep_p[DEPS_IN_LHS]);
2005 : return MOVEUP_EXPR_AS_RHS;
2006 : }
2007 :
2008 : /* True when a trapping EXPR cannot be moved through THROUGH_INSN. */
2009 : #define CANT_MOVE_TRAPPING(expr, through_insn) \
2010 : (VINSN_MAY_TRAP_P (EXPR_VINSN (expr)) \
2011 : && !sel_insn_has_single_succ_p ((through_insn), SUCCS_ALL) \
2012 : && !sel_insn_is_speculation_check (through_insn))
2013 :
2014 : /* True when a conflict on a target register was found during moveup_expr. */
2015 : static bool was_target_conflict = false;
2016 :
2017 : /* Return true when moving a debug INSN across THROUGH_INSN will
2018 : create a bookkeeping block. We don't want to create such blocks,
2019 : for they would cause codegen differences between compilations with
2020 : and without debug info. */
2021 :
2022 : static bool
2023 79 : moving_insn_creates_bookkeeping_block_p (insn_t insn,
2024 : insn_t through_insn)
2025 : {
2026 79 : basic_block bbi, bbt;
2027 79 : edge e1, e2;
2028 79 : edge_iterator ei1, ei2;
2029 :
2030 79 : if (!bookkeeping_can_be_created_if_moved_through_p (through_insn))
2031 : {
2032 59 : if (sched_verbose >= 9)
2033 0 : sel_print ("no bookkeeping required: ");
2034 59 : return false;
2035 : }
2036 :
2037 20 : bbi = BLOCK_FOR_INSN (insn);
2038 :
2039 20 : if (EDGE_COUNT (bbi->preds) == 1)
2040 : {
2041 1 : if (sched_verbose >= 9)
2042 0 : sel_print ("only one pred edge: ");
2043 1 : return true;
2044 : }
2045 :
2046 19 : bbt = BLOCK_FOR_INSN (through_insn);
2047 :
2048 36 : FOR_EACH_EDGE (e1, ei1, bbt->succs)
2049 : {
2050 62 : FOR_EACH_EDGE (e2, ei2, bbi->preds)
2051 : {
2052 45 : if (find_block_for_bookkeeping (e1, e2, true))
2053 : {
2054 10 : if (sched_verbose >= 9)
2055 0 : sel_print ("found existing block: ");
2056 10 : return false;
2057 : }
2058 : }
2059 : }
2060 :
2061 9 : if (sched_verbose >= 9)
2062 0 : sel_print ("would create bookkeeping block: ");
2063 :
2064 : return true;
2065 : }
2066 :
2067 : /* Return true when the conflict with newly created implicit clobbers
2068 : between EXPR and THROUGH_INSN is found because of renaming. */
2069 : static bool
2070 37 : implicit_clobber_conflict_p (insn_t through_insn, expr_t expr)
2071 : {
2072 37 : HARD_REG_SET temp;
2073 37 : rtx_insn *insn;
2074 37 : rtx reg, rhs, pat;
2075 37 : hard_reg_set_iterator hrsi;
2076 37 : unsigned regno;
2077 37 : bool valid;
2078 :
2079 : /* Make a new pseudo register. */
2080 37 : reg = gen_reg_rtx (GET_MODE (EXPR_LHS (expr)));
2081 37 : max_regno = max_reg_num ();
2082 37 : maybe_extend_reg_info_p ();
2083 :
2084 : /* Validate a change and bail out early. */
2085 37 : insn = EXPR_INSN_RTX (expr);
2086 37 : validate_change (insn, &SET_DEST (PATTERN (insn)), reg, true);
2087 37 : valid = verify_changes (0);
2088 37 : cancel_changes (0);
2089 37 : if (!valid)
2090 : {
2091 37 : if (sched_verbose >= 6)
2092 0 : sel_print ("implicit clobbers failed validation, ");
2093 37 : return true;
2094 : }
2095 :
2096 : /* Make a new insn with it. */
2097 0 : rhs = copy_rtx (VINSN_RHS (EXPR_VINSN (expr)));
2098 0 : pat = gen_rtx_SET (reg, rhs);
2099 0 : start_sequence ();
2100 0 : insn = emit_insn (pat);
2101 0 : end_sequence ();
2102 :
2103 : /* Calculate implicit clobbers. */
2104 0 : extract_insn (insn);
2105 0 : preprocess_constraints (insn);
2106 0 : alternative_mask prefrred = get_preferred_alternatives (insn);
2107 0 : ira_implicitly_set_insn_hard_regs (&temp, prefrred);
2108 0 : temp &= ~ira_no_alloc_regs;
2109 :
2110 : /* If any implicit clobber registers intersect with regular ones in
2111 : through_insn, we have a dependency and thus bail out. */
2112 0 : EXECUTE_IF_SET_IN_HARD_REG_SET (temp, 0, regno, hrsi)
2113 : {
2114 0 : vinsn_t vi = INSN_VINSN (through_insn);
2115 0 : if (bitmap_bit_p (VINSN_REG_SETS (vi), regno)
2116 0 : || bitmap_bit_p (VINSN_REG_CLOBBERS (vi), regno)
2117 0 : || bitmap_bit_p (VINSN_REG_USES (vi), regno))
2118 0 : return true;
2119 : }
2120 :
2121 : return false;
2122 : }
2123 :
2124 : /* Modifies EXPR so it can be moved through the THROUGH_INSN,
2125 : performing necessary transformations. Record the type of transformation
2126 : made in PTRANS_TYPE, when it is not NULL. When INSIDE_INSN_GROUP,
2127 : permit all dependencies except true ones, and try to remove those
2128 : too via forward substitution. All cases when a non-eliminable
2129 : non-zero cost dependency exists inside an insn group will be fixed
2130 : in tick_check_p instead. */
2131 : static enum MOVEUP_EXPR_CODE
2132 19305 : moveup_expr (expr_t expr, insn_t through_insn, bool inside_insn_group,
2133 : enum local_trans_type *ptrans_type)
2134 : {
2135 19305 : vinsn_t vi = EXPR_VINSN (expr);
2136 19305 : insn_t insn = VINSN_INSN_RTX (vi);
2137 19305 : bool was_changed = false;
2138 19305 : bool as_rhs = false;
2139 19305 : ds_t *has_dep_p;
2140 19305 : ds_t full_ds;
2141 :
2142 : /* ??? We use dependencies of non-debug insns on debug insns to
2143 : indicate that the debug insns need to be reset if the non-debug
2144 : insn is pulled ahead of it. It's hard to figure out how to
2145 : introduce such a notion in sel-sched, but it already fails to
2146 : support debug insns in other ways, so we just go ahead and
2147 : let the deug insns go corrupt for now. */
2148 19305 : if (DEBUG_INSN_P (through_insn) && !DEBUG_INSN_P (insn))
2149 : return MOVEUP_EXPR_SAME;
2150 :
2151 : /* When inside_insn_group, delegate to the helper. */
2152 19233 : if (inside_insn_group)
2153 0 : return moveup_expr_inside_insn_group (expr, through_insn);
2154 :
2155 : /* Deal with unique insns and control dependencies. */
2156 19233 : if (VINSN_UNIQUE_P (vi))
2157 : {
2158 : /* We can move jumps without side-effects or jumps that are
2159 : mutually exclusive with instruction THROUGH_INSN (all in cases
2160 : dependencies allow to do so and jump is not speculative). */
2161 1950 : if (control_flow_insn_p (insn))
2162 : {
2163 825 : basic_block fallthru_bb;
2164 :
2165 : /* Do not move checks and do not move jumps through other
2166 : jumps. */
2167 825 : if (control_flow_insn_p (through_insn)
2168 825 : || sel_insn_is_speculation_check (insn))
2169 2 : return MOVEUP_EXPR_NULL;
2170 :
2171 : /* Don't move jumps through CFG joins. */
2172 823 : if (bookkeeping_can_be_created_if_moved_through_p (through_insn))
2173 : return MOVEUP_EXPR_NULL;
2174 :
2175 : /* The jump should have a clear fallthru block, and
2176 : this block should be in the current region. */
2177 817 : if ((fallthru_bb = fallthru_bb_of_jump (insn)) == NULL
2178 817 : || ! in_current_region_p (fallthru_bb))
2179 646 : return MOVEUP_EXPR_NULL;
2180 :
2181 : /* And it should be mutually exclusive with through_insn. */
2182 171 : if (! sched_insns_conditions_mutex_p (insn, through_insn)
2183 171 : && ! DEBUG_INSN_P (through_insn))
2184 : return MOVEUP_EXPR_NULL;
2185 : }
2186 :
2187 : /* Don't move what we can't move. */
2188 1125 : if (EXPR_CANT_MOVE (expr)
2189 1125 : && BLOCK_FOR_INSN (through_insn) != BLOCK_FOR_INSN (insn))
2190 : return MOVEUP_EXPR_NULL;
2191 :
2192 : /* Don't move SCHED_GROUP instruction through anything.
2193 : If we don't force this, then it will be possible to start
2194 : scheduling a sched_group before all its dependencies are
2195 : resolved.
2196 : ??? Haifa deals with this issue by delaying the SCHED_GROUP
2197 : as late as possible through rank_for_schedule. */
2198 992 : if (SCHED_GROUP_P (insn))
2199 : return MOVEUP_EXPR_NULL;
2200 : }
2201 : else
2202 17283 : gcc_assert (!control_flow_insn_p (insn));
2203 :
2204 : /* Don't move debug insns if this would require bookkeeping. */
2205 18245 : if (DEBUG_INSN_P (insn)
2206 120 : && BLOCK_FOR_INSN (through_insn) != BLOCK_FOR_INSN (insn)
2207 18324 : && moving_insn_creates_bookkeeping_block_p (insn, through_insn))
2208 : return MOVEUP_EXPR_NULL;
2209 :
2210 : /* Deal with data dependencies. */
2211 18235 : was_target_conflict = false;
2212 18235 : full_ds = has_dependence_p (expr, through_insn, &has_dep_p);
2213 18235 : if (full_ds == 0)
2214 : {
2215 14034 : if (!CANT_MOVE_TRAPPING (expr, through_insn))
2216 14033 : return MOVEUP_EXPR_SAME;
2217 : }
2218 : else
2219 : {
2220 : /* We can move UNIQUE insn up only as a whole and unchanged,
2221 : so it shouldn't have any dependencies. */
2222 4201 : if (VINSN_UNIQUE_P (vi))
2223 : return MOVEUP_EXPR_NULL;
2224 : }
2225 :
2226 3580 : if (full_ds != 0 && can_speculate_dep_p (full_ds))
2227 : {
2228 0 : int res;
2229 :
2230 0 : res = speculate_expr (expr, full_ds);
2231 0 : if (res >= 0)
2232 : {
2233 : /* Speculation was successful. */
2234 0 : full_ds = 0;
2235 0 : was_changed = (res > 0);
2236 0 : if (res == 2)
2237 0 : was_target_conflict = true;
2238 0 : if (ptrans_type)
2239 0 : *ptrans_type = TRANS_SPECULATION;
2240 0 : sel_clear_has_dependence ();
2241 : }
2242 : }
2243 :
2244 3580 : if (has_dep_p[DEPS_IN_INSN])
2245 : /* We have some dependency that cannot be discarded. */
2246 : return MOVEUP_EXPR_NULL;
2247 :
2248 2803 : if (has_dep_p[DEPS_IN_LHS])
2249 : {
2250 : /* Only separable insns can be moved up with the new register.
2251 : Anyways, we should mark that the original register is
2252 : unavailable. */
2253 1970 : if (!enable_schedule_as_rhs_p || !EXPR_SEPARABLE_P (expr))
2254 : return MOVEUP_EXPR_NULL;
2255 :
2256 : /* When renaming a hard register to a pseudo before reload, extra
2257 : dependencies can occur from the implicit clobbers of the insn.
2258 : Filter out such cases here. */
2259 205 : if (!reload_completed && REG_P (EXPR_LHS (expr))
2260 205 : && HARD_REGISTER_P (EXPR_LHS (expr))
2261 1340 : && implicit_clobber_conflict_p (through_insn, expr))
2262 : {
2263 37 : if (sched_verbose >= 6)
2264 0 : sel_print ("implicit clobbers conflict detected, ");
2265 37 : return MOVEUP_EXPR_NULL;
2266 : }
2267 1266 : EXPR_TARGET_AVAILABLE (expr) = false;
2268 1266 : was_target_conflict = true;
2269 1266 : as_rhs = true;
2270 : }
2271 :
2272 : /* At this point we have either separable insns, that will be lifted
2273 : up only as RHSes, or non-separable insns with no dependency in lhs.
2274 : If dependency is in RHS, then try to perform substitution and move up
2275 : substituted RHS:
2276 :
2277 : Ex. 1: Ex.2
2278 : y = x; y = x;
2279 : z = y*2; y = y*2;
2280 :
2281 : In Ex.1 y*2 can be substituted for x*2 and the whole operation can be
2282 : moved above y=x assignment as z=x*2.
2283 :
2284 : In Ex.2 y*2 also can be substituted for x*2, but only the right hand
2285 : side can be moved because of the output dependency. The operation was
2286 : cropped to its rhs above. */
2287 2099 : if (has_dep_p[DEPS_IN_RHS])
2288 : {
2289 1067 : ds_t *rhs_dsp = &has_dep_p[DEPS_IN_RHS];
2290 :
2291 : /* Can't substitute UNIQUE VINSNs. */
2292 1067 : gcc_assert (!VINSN_UNIQUE_P (vi));
2293 :
2294 1067 : if (can_speculate_dep_p (*rhs_dsp))
2295 : {
2296 0 : int res;
2297 :
2298 0 : res = speculate_expr (expr, *rhs_dsp);
2299 0 : if (res >= 0)
2300 : {
2301 : /* Speculation was successful. */
2302 0 : *rhs_dsp = 0;
2303 0 : was_changed = (res > 0);
2304 0 : if (res == 2)
2305 0 : was_target_conflict = true;
2306 0 : if (ptrans_type)
2307 0 : *ptrans_type = TRANS_SPECULATION;
2308 : }
2309 : else
2310 : return MOVEUP_EXPR_NULL;
2311 : }
2312 1067 : else if (can_substitute_through_p (through_insn,
2313 : *rhs_dsp)
2314 1067 : && substitute_reg_in_expr (expr, through_insn, false))
2315 : {
2316 : /* ??? We cannot perform substitution AND speculation on the same
2317 : insn. */
2318 64 : gcc_assert (!was_changed);
2319 64 : was_changed = true;
2320 64 : if (ptrans_type)
2321 64 : *ptrans_type = TRANS_SUBSTITUTION;
2322 64 : EXPR_WAS_SUBSTITUTED (expr) = true;
2323 : }
2324 : else
2325 1003 : return MOVEUP_EXPR_NULL;
2326 : }
2327 :
2328 : /* Don't move trapping insns through jumps.
2329 : This check should be at the end to give a chance to control speculation
2330 : to perform its duties. */
2331 1096 : if (CANT_MOVE_TRAPPING (expr, through_insn))
2332 : return MOVEUP_EXPR_NULL;
2333 :
2334 1094 : return (was_changed
2335 1094 : ? MOVEUP_EXPR_CHANGED
2336 : : (as_rhs
2337 1030 : ? MOVEUP_EXPR_AS_RHS
2338 : : MOVEUP_EXPR_SAME));
2339 : }
2340 :
2341 : /* Try to look at bitmap caches for EXPR and INSN pair, return true
2342 : if successful. When INSIDE_INSN_GROUP, also try ignore dependencies
2343 : that can exist within a parallel group. Write to RES the resulting
2344 : code for moveup_expr. */
2345 : static bool
2346 179038 : try_bitmap_cache (expr_t expr, insn_t insn,
2347 : bool inside_insn_group,
2348 : enum MOVEUP_EXPR_CODE *res)
2349 : {
2350 179038 : int expr_uid = INSN_UID (EXPR_INSN_RTX (expr));
2351 :
2352 : /* First check whether we've analyzed this situation already. */
2353 179038 : if (bitmap_bit_p (INSN_ANALYZED_DEPS (insn), expr_uid))
2354 : {
2355 143386 : if (bitmap_bit_p (INSN_FOUND_DEPS (insn), expr_uid))
2356 : {
2357 39984 : if (sched_verbose >= 6)
2358 0 : sel_print ("removed (cached)\n");
2359 39984 : *res = MOVEUP_EXPR_NULL;
2360 39984 : return true;
2361 : }
2362 : else
2363 : {
2364 103402 : if (sched_verbose >= 6)
2365 0 : sel_print ("unchanged (cached)\n");
2366 103402 : *res = MOVEUP_EXPR_SAME;
2367 103402 : return true;
2368 : }
2369 : }
2370 35652 : else if (bitmap_bit_p (INSN_FOUND_DEPS (insn), expr_uid))
2371 : {
2372 16039 : if (inside_insn_group)
2373 : {
2374 0 : if (sched_verbose >= 6)
2375 0 : sel_print ("unchanged (as RHS, cached, inside insn group)\n");
2376 0 : *res = MOVEUP_EXPR_SAME;
2377 0 : return true;
2378 :
2379 : }
2380 : else
2381 16039 : EXPR_TARGET_AVAILABLE (expr) = false;
2382 :
2383 : /* This is the only case when propagation result can change over time,
2384 : as we can dynamically switch off scheduling as RHS. In this case,
2385 : just check the flag to reach the correct decision. */
2386 16039 : if (enable_schedule_as_rhs_p)
2387 : {
2388 15930 : if (sched_verbose >= 6)
2389 0 : sel_print ("unchanged (as RHS, cached)\n");
2390 15930 : *res = MOVEUP_EXPR_AS_RHS;
2391 15930 : return true;
2392 : }
2393 : else
2394 : {
2395 109 : if (sched_verbose >= 6)
2396 0 : sel_print ("removed (cached as RHS, but renaming"
2397 : " is now disabled)\n");
2398 109 : *res = MOVEUP_EXPR_NULL;
2399 109 : return true;
2400 : }
2401 : }
2402 :
2403 : return false;
2404 : }
2405 :
2406 : /* Try to look at bitmap caches for EXPR and INSN pair, return true
2407 : if successful. Write to RES the resulting code for moveup_expr. */
2408 : static bool
2409 19613 : try_transformation_cache (expr_t expr, insn_t insn,
2410 : enum MOVEUP_EXPR_CODE *res)
2411 : {
2412 19613 : struct transformed_insns *pti
2413 : = (struct transformed_insns *)
2414 19613 : htab_find_with_hash (INSN_TRANSFORMED_INSNS (insn),
2415 19613 : &EXPR_VINSN (expr),
2416 19613 : VINSN_HASH_RTX (EXPR_VINSN (expr)));
2417 19613 : if (pti)
2418 : {
2419 : /* This EXPR was already moved through this insn and was
2420 : changed as a result. Fetch the proper data from
2421 : the hashtable. */
2422 724 : insert_in_history_vect (&EXPR_HISTORY_OF_CHANGES (expr),
2423 362 : INSN_UID (insn), pti->type,
2424 : pti->vinsn_old, pti->vinsn_new,
2425 : EXPR_SPEC_DONE_DS (expr));
2426 :
2427 362 : if (INSN_IN_STREAM_P (VINSN_INSN_RTX (pti->vinsn_new)))
2428 2 : pti->vinsn_new = vinsn_copy (pti->vinsn_new, true);
2429 362 : change_vinsn_in_expr (expr, pti->vinsn_new);
2430 362 : if (pti->was_target_conflict)
2431 35 : EXPR_TARGET_AVAILABLE (expr) = false;
2432 362 : if (pti->type == TRANS_SPECULATION)
2433 : {
2434 0 : EXPR_SPEC_DONE_DS (expr) = pti->ds;
2435 0 : EXPR_NEEDS_SPEC_CHECK_P (expr) |= pti->needs_check;
2436 : }
2437 :
2438 362 : if (sched_verbose >= 6)
2439 : {
2440 0 : sel_print ("changed (cached): ");
2441 0 : dump_expr (expr);
2442 0 : sel_print ("\n");
2443 : }
2444 :
2445 362 : *res = MOVEUP_EXPR_CHANGED;
2446 362 : return true;
2447 : }
2448 :
2449 : return false;
2450 : }
2451 :
2452 : /* Update bitmap caches on INSN with result RES of propagating EXPR. */
2453 : static void
2454 19241 : update_bitmap_cache (expr_t expr, insn_t insn, bool inside_insn_group,
2455 : enum MOVEUP_EXPR_CODE res)
2456 : {
2457 19241 : int expr_uid = INSN_UID (EXPR_INSN_RTX (expr));
2458 :
2459 : /* Do not cache result of propagating jumps through an insn group,
2460 : as it is always true, which is not useful outside the group. */
2461 19241 : if (inside_insn_group)
2462 : return;
2463 :
2464 19241 : if (res == MOVEUP_EXPR_NULL)
2465 : {
2466 4106 : bitmap_set_bit (INSN_ANALYZED_DEPS (insn), expr_uid);
2467 4106 : bitmap_set_bit (INSN_FOUND_DEPS (insn), expr_uid);
2468 : }
2469 15135 : else if (res == MOVEUP_EXPR_SAME)
2470 : {
2471 14105 : bitmap_set_bit (INSN_ANALYZED_DEPS (insn), expr_uid);
2472 14105 : bitmap_clear_bit (INSN_FOUND_DEPS (insn), expr_uid);
2473 : }
2474 1030 : else if (res == MOVEUP_EXPR_AS_RHS)
2475 : {
2476 1030 : bitmap_clear_bit (INSN_ANALYZED_DEPS (insn), expr_uid);
2477 1030 : bitmap_set_bit (INSN_FOUND_DEPS (insn), expr_uid);
2478 : }
2479 : else
2480 0 : gcc_unreachable ();
2481 : }
2482 :
2483 : /* Update hashtable on INSN with changed EXPR, old EXPR_OLD_VINSN
2484 : and transformation type TRANS_TYPE. */
2485 : static void
2486 64 : update_transformation_cache (expr_t expr, insn_t insn,
2487 : bool inside_insn_group,
2488 : enum local_trans_type trans_type,
2489 : vinsn_t expr_old_vinsn)
2490 : {
2491 64 : struct transformed_insns *pti;
2492 :
2493 64 : if (inside_insn_group)
2494 : return;
2495 :
2496 64 : pti = XNEW (struct transformed_insns);
2497 64 : pti->vinsn_old = expr_old_vinsn;
2498 64 : pti->vinsn_new = EXPR_VINSN (expr);
2499 64 : pti->type = trans_type;
2500 64 : pti->was_target_conflict = was_target_conflict;
2501 64 : pti->ds = EXPR_SPEC_DONE_DS (expr);
2502 64 : pti->needs_check = EXPR_NEEDS_SPEC_CHECK_P (expr);
2503 64 : vinsn_attach (pti->vinsn_old);
2504 64 : vinsn_attach (pti->vinsn_new);
2505 64 : *((struct transformed_insns **)
2506 64 : htab_find_slot_with_hash (INSN_TRANSFORMED_INSNS (insn),
2507 64 : pti, VINSN_HASH_RTX (expr_old_vinsn),
2508 64 : INSERT)) = pti;
2509 : }
2510 :
2511 : /* Same as moveup_expr, but first looks up the result of
2512 : transformation in caches. */
2513 : static enum MOVEUP_EXPR_CODE
2514 179092 : moveup_expr_cached (expr_t expr, insn_t insn, bool inside_insn_group)
2515 : {
2516 179092 : enum MOVEUP_EXPR_CODE res;
2517 179092 : bool got_answer = false;
2518 :
2519 179092 : if (sched_verbose >= 6)
2520 : {
2521 0 : sel_print ("Moving ");
2522 0 : dump_expr (expr);
2523 0 : sel_print (" through %d: ", INSN_UID (insn));
2524 : }
2525 :
2526 179092 : if (DEBUG_INSN_P (EXPR_INSN_RTX (expr))
2527 296 : && BLOCK_FOR_INSN (EXPR_INSN_RTX (expr))
2528 179349 : && (sel_bb_head (BLOCK_FOR_INSN (EXPR_INSN_RTX (expr)))
2529 257 : == EXPR_INSN_RTX (expr)))
2530 : /* Don't use cached information for debug insns that are heads of
2531 : basic blocks. */;
2532 179038 : else if (try_bitmap_cache (expr, insn, inside_insn_group, &res))
2533 : /* When inside insn group, we do not want remove stores conflicting
2534 : with previosly issued loads. */
2535 159425 : got_answer = ! inside_insn_group || res != MOVEUP_EXPR_NULL;
2536 19613 : else if (try_transformation_cache (expr, insn, &res))
2537 : got_answer = true;
2538 :
2539 : if (! got_answer)
2540 : {
2541 : /* Invoke moveup_expr and record the results. */
2542 19305 : vinsn_t expr_old_vinsn = EXPR_VINSN (expr);
2543 19305 : ds_t expr_old_spec_ds = EXPR_SPEC_DONE_DS (expr);
2544 19305 : int expr_uid = INSN_UID (VINSN_INSN_RTX (expr_old_vinsn));
2545 19305 : bool unique_p = VINSN_UNIQUE_P (expr_old_vinsn);
2546 19305 : enum local_trans_type trans_type = TRANS_SUBSTITUTION;
2547 :
2548 : /* ??? Invent something better than this. We can't allow old_vinsn
2549 : to go, we need it for the history vector. */
2550 19305 : vinsn_attach (expr_old_vinsn);
2551 :
2552 19305 : res = moveup_expr (expr, insn, inside_insn_group,
2553 : &trans_type);
2554 19305 : switch (res)
2555 : {
2556 4106 : case MOVEUP_EXPR_NULL:
2557 4106 : update_bitmap_cache (expr, insn, inside_insn_group, res);
2558 4106 : if (sched_verbose >= 6)
2559 0 : sel_print ("removed\n");
2560 : break;
2561 :
2562 14105 : case MOVEUP_EXPR_SAME:
2563 14105 : update_bitmap_cache (expr, insn, inside_insn_group, res);
2564 14105 : if (sched_verbose >= 6)
2565 0 : sel_print ("unchanged\n");
2566 : break;
2567 :
2568 1030 : case MOVEUP_EXPR_AS_RHS:
2569 1030 : gcc_assert (!unique_p || inside_insn_group);
2570 1030 : update_bitmap_cache (expr, insn, inside_insn_group, res);
2571 1030 : if (sched_verbose >= 6)
2572 0 : sel_print ("unchanged (as RHS)\n");
2573 : break;
2574 :
2575 64 : case MOVEUP_EXPR_CHANGED:
2576 64 : gcc_assert (INSN_UID (EXPR_INSN_RTX (expr)) != expr_uid
2577 : || EXPR_SPEC_DONE_DS (expr) != expr_old_spec_ds);
2578 128 : insert_in_history_vect (&EXPR_HISTORY_OF_CHANGES (expr),
2579 64 : INSN_UID (insn), trans_type,
2580 : expr_old_vinsn, EXPR_VINSN (expr),
2581 : expr_old_spec_ds);
2582 64 : update_transformation_cache (expr, insn, inside_insn_group,
2583 : trans_type, expr_old_vinsn);
2584 64 : if (sched_verbose >= 6)
2585 : {
2586 0 : sel_print ("changed: ");
2587 0 : dump_expr (expr);
2588 0 : sel_print ("\n");
2589 : }
2590 : break;
2591 : default:
2592 : gcc_unreachable ();
2593 : }
2594 :
2595 19305 : vinsn_detach (expr_old_vinsn);
2596 : }
2597 :
2598 179092 : return res;
2599 : }
2600 :
2601 : /* Moves an av set AVP up through INSN, performing necessary
2602 : transformations. */
2603 : static void
2604 54166 : moveup_set_expr (av_set_t *avp, insn_t insn, bool inside_insn_group)
2605 : {
2606 54166 : av_set_iterator i;
2607 54166 : expr_t expr;
2608 :
2609 398916 : FOR_EACH_EXPR_1 (expr, i, avp)
2610 : {
2611 :
2612 172375 : switch (moveup_expr_cached (expr, insn, inside_insn_group))
2613 : {
2614 : case MOVEUP_EXPR_SAME:
2615 : case MOVEUP_EXPR_AS_RHS:
2616 : break;
2617 :
2618 44199 : case MOVEUP_EXPR_NULL:
2619 44199 : av_set_iter_remove (&i);
2620 44199 : break;
2621 :
2622 422 : case MOVEUP_EXPR_CHANGED:
2623 422 : expr = merge_with_other_exprs (avp, &i, expr);
2624 422 : break;
2625 :
2626 0 : default:
2627 0 : gcc_unreachable ();
2628 : }
2629 : }
2630 54166 : }
2631 :
2632 : /* Moves AVP set along PATH. */
2633 : static void
2634 5189 : moveup_set_inside_insn_group (av_set_t *avp, ilist_t path)
2635 : {
2636 5189 : int last_cycle;
2637 :
2638 5189 : if (sched_verbose >= 6)
2639 0 : sel_print ("Moving expressions up in the insn group...\n");
2640 5189 : if (! path)
2641 : return;
2642 0 : last_cycle = INSN_SCHED_CYCLE (ILIST_INSN (path));
2643 0 : while (path
2644 0 : && INSN_SCHED_CYCLE (ILIST_INSN (path)) == last_cycle)
2645 : {
2646 0 : moveup_set_expr (avp, ILIST_INSN (path), true);
2647 0 : path = ILIST_NEXT (path);
2648 : }
2649 : }
2650 :
2651 : /* Returns true if after moving EXPR along PATH it equals to EXPR_VLIW. */
2652 : static bool
2653 17841 : equal_after_moveup_path_p (expr_t expr, ilist_t path, expr_t expr_vliw)
2654 : {
2655 17841 : expr_def _tmp, *tmp = &_tmp;
2656 17841 : int last_cycle;
2657 17841 : bool res = true;
2658 :
2659 17841 : copy_expr_onside (tmp, expr);
2660 17841 : last_cycle = path ? INSN_SCHED_CYCLE (ILIST_INSN (path)) : 0;
2661 17841 : while (path
2662 17841 : && res
2663 17841 : && INSN_SCHED_CYCLE (ILIST_INSN (path)) == last_cycle)
2664 : {
2665 0 : res = (moveup_expr_cached (tmp, ILIST_INSN (path), true)
2666 : != MOVEUP_EXPR_NULL);
2667 0 : path = ILIST_NEXT (path);
2668 : }
2669 :
2670 17841 : if (res)
2671 : {
2672 17841 : vinsn_t tmp_vinsn = EXPR_VINSN (tmp);
2673 17841 : vinsn_t expr_vliw_vinsn = EXPR_VINSN (expr_vliw);
2674 :
2675 17841 : if (tmp_vinsn != expr_vliw_vinsn)
2676 10187 : res = vinsn_equal_p (tmp_vinsn, expr_vliw_vinsn);
2677 : }
2678 :
2679 17841 : clear_expr (tmp);
2680 17841 : return res;
2681 : }
2682 :
2683 :
2684 : /* Functions that compute av and lv sets. */
2685 :
2686 : /* Returns true if INSN is not a downward continuation of the given path P in
2687 : the current stage. */
2688 : static bool
2689 74580 : is_ineligible_successor (insn_t insn, ilist_t p)
2690 : {
2691 74580 : insn_t prev_insn;
2692 :
2693 : /* Check if insn is not deleted. */
2694 74580 : if (PREV_INSN (insn) && NEXT_INSN (PREV_INSN (insn)) != insn)
2695 0 : gcc_unreachable ();
2696 74580 : else if (NEXT_INSN (insn) && PREV_INSN (NEXT_INSN (insn)) != insn)
2697 0 : gcc_unreachable ();
2698 :
2699 : /* If it's the first insn visited, then the successor is ok. */
2700 74580 : if (!p)
2701 : return false;
2702 :
2703 60475 : prev_insn = ILIST_INSN (p);
2704 :
2705 60475 : if (/* a backward edge. */
2706 60475 : INSN_SEQNO (insn) < INSN_SEQNO (prev_insn)
2707 : /* is already visited. */
2708 59554 : || (INSN_SEQNO (insn) == INSN_SEQNO (prev_insn)
2709 3131 : && (ilist_is_in_p (p, insn)
2710 : /* We can reach another fence here and still seqno of insn
2711 : would be equal to seqno of prev_insn. This is possible
2712 : when prev_insn is a previously created bookkeeping copy.
2713 : In that case it'd get a seqno of insn. Thus, check here
2714 : whether insn is in current fence too. */
2715 3131 : || IN_CURRENT_FENCE_P (insn)))
2716 : /* Was already scheduled on this round. */
2717 59553 : || (INSN_SEQNO (insn) > INSN_SEQNO (prev_insn)
2718 56423 : && IN_CURRENT_FENCE_P (insn))
2719 : /* An insn from another fence could also be
2720 : scheduled earlier even if this insn is not in
2721 : a fence list right now. Check INSN_SCHED_CYCLE instead. */
2722 120023 : || (!pipelining_p
2723 20616 : && INSN_SCHED_TIMES (insn) > 0))
2724 950 : return true;
2725 : else
2726 : return false;
2727 : }
2728 :
2729 : /* Computes the av_set below the last bb insn INSN, doing all the 'dirty work'
2730 : of handling multiple successors and properly merging its av_sets. P is
2731 : the current path traversed. WS is the size of lookahead window.
2732 : Return the av set computed. */
2733 : static av_set_t
2734 8544 : compute_av_set_at_bb_end (insn_t insn, ilist_t p, int ws)
2735 : {
2736 8544 : struct succs_info *sinfo;
2737 8544 : av_set_t expr_in_all_succ_branches = NULL;
2738 8544 : int is;
2739 8544 : insn_t succ, zero_succ = NULL;
2740 8544 : av_set_t av1 = NULL;
2741 :
2742 8544 : gcc_assert (sel_bb_end_p (insn));
2743 :
2744 : /* Find different kind of successors needed for correct computing of
2745 : SPEC and TARGET_AVAILABLE attributes. */
2746 8544 : sinfo = compute_succs_info (insn, SUCCS_NORMAL);
2747 :
2748 : /* Debug output. */
2749 8544 : if (sched_verbose >= 6)
2750 : {
2751 0 : sel_print ("successors of bb end (%d): ", INSN_UID (insn));
2752 0 : dump_insn_vector (sinfo->succs_ok);
2753 0 : sel_print ("\n");
2754 0 : if (sinfo->succs_ok_n != sinfo->all_succs_n)
2755 0 : sel_print ("real successors num: %d\n", sinfo->all_succs_n);
2756 : }
2757 :
2758 : /* Add insn to the tail of current path. */
2759 8544 : ilist_add (&p, insn);
2760 :
2761 14835 : FOR_EACH_VEC_ELT (sinfo->succs_ok, is, succ)
2762 : {
2763 6291 : av_set_t succ_set;
2764 :
2765 : /* We will edit SUCC_SET and EXPR_SPEC field of its elements. */
2766 6291 : succ_set = compute_av_set_inside_bb (succ, p, ws, true);
2767 :
2768 12582 : av_set_split_usefulness (succ_set,
2769 6291 : sinfo->probs_ok[is],
2770 : sinfo->all_prob);
2771 :
2772 6291 : if (sinfo->all_succs_n > 1)
2773 : {
2774 : /* Find EXPR'es that came from *all* successors and save them
2775 : into expr_in_all_succ_branches. This set will be used later
2776 : for calculating speculation attributes of EXPR'es. */
2777 4506 : if (is == 0)
2778 : {
2779 3410 : expr_in_all_succ_branches = av_set_copy (succ_set);
2780 :
2781 : /* Remember the first successor for later. */
2782 3410 : zero_succ = succ;
2783 : }
2784 : else
2785 : {
2786 1096 : av_set_iterator i;
2787 1096 : expr_t expr;
2788 :
2789 8620 : FOR_EACH_EXPR_1 (expr, i, &expr_in_all_succ_branches)
2790 3762 : if (!av_set_is_in_p (succ_set, EXPR_VINSN (expr)))
2791 1845 : av_set_iter_remove (&i);
2792 : }
2793 : }
2794 :
2795 : /* Union the av_sets. Check liveness restrictions on target registers
2796 : in special case of two successors. */
2797 6291 : if (sinfo->succs_ok_n == 2 && is == 1)
2798 : {
2799 1096 : basic_block bb0 = BLOCK_FOR_INSN (zero_succ);
2800 1096 : basic_block bb1 = BLOCK_FOR_INSN (succ);
2801 :
2802 1096 : gcc_assert (BB_LV_SET_VALID_P (bb0) && BB_LV_SET_VALID_P (bb1));
2803 1096 : av_set_union_and_live (&av1, &succ_set,
2804 1096 : BB_LV_SET (bb0),
2805 1096 : BB_LV_SET (bb1),
2806 : insn);
2807 1096 : }
2808 : else
2809 5195 : av_set_union_and_clear (&av1, &succ_set, insn);
2810 : }
2811 :
2812 : /* Check liveness restrictions via hard way when there are more than
2813 : two successors. */
2814 8544 : if (sinfo->succs_ok_n > 2)
2815 0 : FOR_EACH_VEC_ELT (sinfo->succs_ok, is, succ)
2816 : {
2817 0 : basic_block succ_bb = BLOCK_FOR_INSN (succ);
2818 0 : av_set_t av_succ = (is_ineligible_successor (succ, p)
2819 0 : ? NULL
2820 0 : : BB_AV_SET (succ_bb));
2821 :
2822 0 : gcc_assert (BB_LV_SET_VALID_P (succ_bb));
2823 0 : mark_unavailable_targets (av1, av_succ, BB_LV_SET (succ_bb));
2824 : }
2825 :
2826 : /* Finally, check liveness restrictions on paths leaving the region. */
2827 8544 : if (sinfo->all_succs_n > sinfo->succs_ok_n)
2828 12916 : FOR_EACH_VEC_ELT (sinfo->succs_other, is, succ)
2829 7290 : mark_unavailable_targets
2830 7290 : (av1, NULL, BB_LV_SET (BLOCK_FOR_INSN (succ)));
2831 :
2832 8544 : if (sinfo->all_succs_n > 1)
2833 : {
2834 : av_set_iterator i;
2835 : expr_t expr;
2836 :
2837 : /* Increase the spec attribute of all EXPR'es that didn't come
2838 : from all successors. */
2839 17729 : FOR_EACH_EXPR (expr, i, av1)
2840 12837 : if (!av_set_is_in_p (expr_in_all_succ_branches, EXPR_VINSN (expr)))
2841 3318 : EXPR_SPEC (expr)++;
2842 :
2843 4892 : av_set_clear (&expr_in_all_succ_branches);
2844 :
2845 : /* Do not move conditional branches through other
2846 : conditional branches. So, remove all conditional
2847 : branches from av_set if current operator is a conditional
2848 : branch. */
2849 4892 : av_set_substract_cond_branches (&av1);
2850 : }
2851 :
2852 8544 : ilist_remove (&p);
2853 8544 : free_succs_info (sinfo);
2854 :
2855 8544 : if (sched_verbose >= 6)
2856 : {
2857 0 : sel_print ("av_succs (%d): ", INSN_UID (insn));
2858 0 : dump_av_set (av1);
2859 0 : sel_print ("\n");
2860 : }
2861 :
2862 8544 : return av1;
2863 : }
2864 :
2865 : /* This function computes av_set for the FIRST_INSN by dragging valid
2866 : av_set through all basic block insns either from the end of basic block
2867 : (computed using compute_av_set_at_bb_end) or from the insn on which
2868 : MAX_WS was exceeded. It uses compute_av_set_at_bb_end to compute av_set
2869 : below the basic block and handling conditional branches.
2870 : FIRST_INSN - the basic block head, P - path consisting of the insns
2871 : traversed on the way to the FIRST_INSN (the path is sparse, only bb heads
2872 : and bb ends are added to the path), WS - current window size,
2873 : NEED_COPY_P - true if we'll make a copy of av_set before returning it. */
2874 : static av_set_t
2875 12705 : compute_av_set_inside_bb (insn_t first_insn, ilist_t p, int ws,
2876 : bool need_copy_p)
2877 : {
2878 12705 : insn_t cur_insn;
2879 12705 : int end_ws = ws;
2880 12705 : insn_t bb_end = sel_bb_end (BLOCK_FOR_INSN (first_insn));
2881 12705 : insn_t after_bb_end = NEXT_INSN (bb_end);
2882 12705 : insn_t last_insn;
2883 12705 : av_set_t av = NULL;
2884 12705 : basic_block cur_bb = BLOCK_FOR_INSN (first_insn);
2885 :
2886 : /* Return NULL if insn is not on the legitimate downward path. */
2887 12705 : if (is_ineligible_successor (first_insn, p))
2888 : {
2889 488 : if (sched_verbose >= 6)
2890 0 : sel_print ("Insn %d is ineligible_successor\n", INSN_UID (first_insn));
2891 :
2892 488 : return NULL;
2893 : }
2894 :
2895 : /* If insn already has valid av(insn) computed, just return it. */
2896 12217 : if (AV_SET_VALID_P (first_insn))
2897 : {
2898 2796 : av_set_t av_set;
2899 :
2900 2796 : if (sel_bb_head_p (first_insn))
2901 2763 : av_set = BB_AV_SET (BLOCK_FOR_INSN (first_insn));
2902 : else
2903 : av_set = NULL;
2904 :
2905 2796 : if (sched_verbose >= 6)
2906 : {
2907 0 : sel_print ("Insn %d has a valid av set: ", INSN_UID (first_insn));
2908 0 : dump_av_set (av_set);
2909 0 : sel_print ("\n");
2910 : }
2911 :
2912 2796 : return need_copy_p ? av_set_copy (av_set) : av_set;
2913 : }
2914 :
2915 9421 : ilist_add (&p, first_insn);
2916 :
2917 : /* As the result after this loop have completed, in LAST_INSN we'll
2918 : have the insn which has valid av_set to start backward computation
2919 : from: it either will be NULL because on it the window size was exceeded
2920 : or other valid av_set as returned by compute_av_set for the last insn
2921 : of the basic block. */
2922 63646 : for (last_insn = first_insn; last_insn != after_bb_end;
2923 54225 : last_insn = NEXT_INSN (last_insn))
2924 : {
2925 : /* We may encounter valid av_set not only on bb_head, but also on
2926 : those insns on which previously MAX_WS was exceeded. */
2927 55102 : if (AV_SET_VALID_P (last_insn))
2928 : {
2929 247 : if (sched_verbose >= 6)
2930 0 : sel_print ("Insn %d has a valid empty av set\n", INSN_UID (last_insn));
2931 : break;
2932 : }
2933 :
2934 : /* The special case: the last insn of the BB may be an
2935 : ineligible_successor due to its SEQ_NO that was set on
2936 : it as a bookkeeping. */
2937 54855 : if (last_insn != first_insn
2938 54855 : && is_ineligible_successor (last_insn, p))
2939 : {
2940 459 : if (sched_verbose >= 6)
2941 0 : sel_print ("Insn %d is ineligible_successor\n", INSN_UID (last_insn));
2942 : break;
2943 : }
2944 :
2945 54396 : if (DEBUG_INSN_P (last_insn))
2946 132 : continue;
2947 :
2948 54264 : if (end_ws > max_ws)
2949 : {
2950 : /* We can reach max lookahead size at bb_header, so clean av_set
2951 : first. */
2952 171 : INSN_WS_LEVEL (last_insn) = global_level;
2953 :
2954 171 : if (sched_verbose >= 6)
2955 0 : sel_print ("Insn %d is beyond the software lookahead window size\n",
2956 0 : INSN_UID (last_insn));
2957 : break;
2958 : }
2959 :
2960 54093 : end_ws++;
2961 : }
2962 :
2963 : /* Get the valid av_set into AV above the LAST_INSN to start backward
2964 : computation from. It either will be empty av_set or av_set computed from
2965 : the successors on the last insn of the current bb. */
2966 9421 : if (last_insn != after_bb_end)
2967 : {
2968 877 : av = NULL;
2969 :
2970 : /* This is needed only to obtain av_sets that are identical to
2971 : those computed by the old compute_av_set version. */
2972 877 : if (last_insn == first_insn && !INSN_NOP_P (last_insn))
2973 17 : av_set_add (&av, INSN_EXPR (last_insn));
2974 : }
2975 : else
2976 : /* END_WS is always already increased by 1 if LAST_INSN == AFTER_BB_END. */
2977 8544 : av = compute_av_set_at_bb_end (bb_end, p, end_ws);
2978 :
2979 : /* Compute av_set in AV starting from below the LAST_INSN up to
2980 : location above the FIRST_INSN. */
2981 63646 : for (cur_insn = PREV_INSN (last_insn); cur_insn != PREV_INSN (first_insn);
2982 54225 : cur_insn = PREV_INSN (cur_insn))
2983 54225 : if (!INSN_NOP_P (cur_insn))
2984 : {
2985 54166 : expr_t expr;
2986 :
2987 54166 : moveup_set_expr (&av, cur_insn, false);
2988 :
2989 : /* If the expression for CUR_INSN is already in the set,
2990 : replace it by the new one. */
2991 54166 : expr = av_set_lookup (av, INSN_VINSN (cur_insn));
2992 54166 : if (expr != NULL)
2993 : {
2994 638 : clear_expr (expr);
2995 638 : copy_expr (expr, INSN_EXPR (cur_insn));
2996 : }
2997 : else
2998 53528 : av_set_add (&av, INSN_EXPR (cur_insn));
2999 : }
3000 :
3001 : /* Clear stale bb_av_set. */
3002 9421 : if (sel_bb_head_p (first_insn))
3003 : {
3004 5316 : av_set_clear (&BB_AV_SET (cur_bb));
3005 5316 : BB_AV_SET (cur_bb) = need_copy_p ? av_set_copy (av) : av;
3006 5316 : BB_AV_LEVEL (cur_bb) = global_level;
3007 : }
3008 :
3009 9421 : if (sched_verbose >= 6)
3010 : {
3011 0 : sel_print ("Computed av set for insn %d: ", INSN_UID (first_insn));
3012 0 : dump_av_set (av);
3013 0 : sel_print ("\n");
3014 : }
3015 :
3016 9421 : ilist_remove (&p);
3017 9421 : return av;
3018 : }
3019 :
3020 : /* Compute av set before INSN.
3021 : INSN - the current operation (actual rtx INSN)
3022 : P - the current path, which is list of insns visited so far
3023 : WS - software lookahead window size.
3024 : UNIQUE_P - TRUE, if returned av_set will be changed, hence
3025 : if we want to save computed av_set in s_i_d, we should make a copy of it.
3026 :
3027 : In the resulting set we will have only expressions that don't have delay
3028 : stalls and nonsubstitutable dependences. */
3029 : static av_set_t
3030 6414 : compute_av_set (insn_t insn, ilist_t p, int ws, bool unique_p)
3031 : {
3032 0 : return compute_av_set_inside_bb (insn, p, ws, unique_p);
3033 : }
3034 :
3035 : /* Propagate a liveness set LV through INSN. */
3036 : static void
3037 17121 : propagate_lv_set (regset lv, insn_t insn)
3038 : {
3039 17121 : gcc_assert (INSN_P (insn));
3040 :
3041 17121 : if (INSN_NOP_P (insn))
3042 : return;
3043 :
3044 17060 : df_simulate_one_insn_backwards (BLOCK_FOR_INSN (insn), insn, lv);
3045 : }
3046 :
3047 : /* Return livness set at the end of BB. */
3048 : static regset
3049 1741 : compute_live_after_bb (basic_block bb)
3050 : {
3051 1741 : edge e;
3052 1741 : edge_iterator ei;
3053 1741 : regset lv = get_clear_regset_from_pool ();
3054 :
3055 1741 : gcc_assert (!ignore_first);
3056 :
3057 4266 : FOR_EACH_EDGE (e, ei, bb->succs)
3058 2525 : if (sel_bb_empty_p (e->dest))
3059 : {
3060 15 : if (! BB_LV_SET_VALID_P (e->dest))
3061 : {
3062 0 : gcc_unreachable ();
3063 : gcc_assert (BB_LV_SET (e->dest) == NULL);
3064 : BB_LV_SET (e->dest) = compute_live_after_bb (e->dest);
3065 : BB_LV_SET_VALID_P (e->dest) = true;
3066 : }
3067 15 : IOR_REG_SET (lv, BB_LV_SET (e->dest));
3068 : }
3069 : else
3070 2510 : IOR_REG_SET (lv, compute_live (sel_bb_head (e->dest)));
3071 :
3072 1741 : return lv;
3073 : }
3074 :
3075 : /* Compute the set of all live registers at the point before INSN and save
3076 : it at INSN if INSN is bb header. */
3077 : regset
3078 17694 : compute_live (insn_t insn)
3079 : {
3080 17694 : basic_block bb = BLOCK_FOR_INSN (insn);
3081 17694 : insn_t final, temp;
3082 17694 : regset lv;
3083 :
3084 : /* Return the valid set if we're already on it. */
3085 17694 : if (!ignore_first)
3086 : {
3087 9339 : regset src = NULL;
3088 :
3089 9339 : if (sel_bb_head_p (insn) && BB_LV_SET_VALID_P (bb))
3090 5719 : src = BB_LV_SET (bb);
3091 : else
3092 : {
3093 3620 : gcc_assert (in_current_region_p (bb));
3094 3620 : if (INSN_LIVE_VALID_P (insn))
3095 3503 : src = INSN_LIVE (insn);
3096 : }
3097 :
3098 9222 : if (src)
3099 : {
3100 9222 : lv = get_regset_from_pool ();
3101 9222 : COPY_REG_SET (lv, src);
3102 :
3103 9222 : if (sel_bb_head_p (insn) && ! BB_LV_SET_VALID_P (bb))
3104 : {
3105 0 : COPY_REG_SET (BB_LV_SET (bb), lv);
3106 0 : BB_LV_SET_VALID_P (bb) = true;
3107 : }
3108 :
3109 9222 : return_regset_to_pool (lv);
3110 9222 : return lv;
3111 : }
3112 : }
3113 :
3114 : /* We've skipped the wrong lv_set. Don't skip the right one. */
3115 8472 : ignore_first = false;
3116 8472 : gcc_assert (in_current_region_p (bb));
3117 :
3118 : /* Find a valid LV set in this block or below, if needed.
3119 : Start searching from the next insn: either ignore_first is true, or
3120 : INSN doesn't have a correct live set. */
3121 8472 : temp = NEXT_INSN (insn);
3122 8472 : final = NEXT_INSN (BB_END (bb));
3123 18862 : while (temp != final && ! INSN_LIVE_VALID_P (temp))
3124 1918 : temp = NEXT_INSN (temp);
3125 8472 : if (temp == final)
3126 : {
3127 1741 : lv = compute_live_after_bb (bb);
3128 1741 : temp = PREV_INSN (temp);
3129 : }
3130 : else
3131 : {
3132 6731 : lv = get_regset_from_pool ();
3133 6731 : COPY_REG_SET (lv, INSN_LIVE (temp));
3134 : }
3135 :
3136 : /* Put correct lv sets on the insns which have bad sets. */
3137 8472 : final = PREV_INSN (insn);
3138 34065 : while (temp != final)
3139 : {
3140 17121 : propagate_lv_set (lv, temp);
3141 17121 : COPY_REG_SET (INSN_LIVE (temp), lv);
3142 17121 : INSN_LIVE_VALID_P (temp) = true;
3143 17121 : temp = PREV_INSN (temp);
3144 : }
3145 :
3146 : /* Also put it in a BB. */
3147 8472 : if (sel_bb_head_p (insn))
3148 : {
3149 2082 : basic_block bb = BLOCK_FOR_INSN (insn);
3150 :
3151 2082 : COPY_REG_SET (BB_LV_SET (bb), lv);
3152 2082 : BB_LV_SET_VALID_P (bb) = true;
3153 : }
3154 :
3155 : /* We return LV to the pool, but will not clear it there. Thus we can
3156 : legimatelly use LV till the next use of regset_pool_get (). */
3157 8472 : return_regset_to_pool (lv);
3158 8472 : return lv;
3159 : }
3160 :
3161 : /* Update liveness sets for INSN. */
3162 : static inline void
3163 8355 : update_liveness_on_insn (rtx_insn *insn)
3164 : {
3165 8355 : ignore_first = true;
3166 8355 : compute_live (insn);
3167 24 : }
3168 :
3169 : /* Compute liveness below INSN and write it into REGS. */
3170 : static inline void
3171 3894 : compute_live_below_insn (rtx_insn *insn, regset regs)
3172 : {
3173 3894 : rtx_insn *succ;
3174 3894 : succ_iterator si;
3175 :
3176 7788 : FOR_EACH_SUCC_1 (succ, si, insn, SUCCS_ALL)
3177 3894 : IOR_REG_SET (regs, compute_live (succ));
3178 3894 : }
3179 :
3180 : /* Update the data gathered in av and lv sets starting from INSN. */
3181 : static void
3182 1225 : update_data_sets (rtx_insn *insn)
3183 : {
3184 1225 : update_liveness_on_insn (insn);
3185 1225 : if (sel_bb_head_p (insn))
3186 : {
3187 1225 : gcc_assert (AV_LEVEL (insn) != 0);
3188 1225 : BB_AV_LEVEL (BLOCK_FOR_INSN (insn)) = -1;
3189 1225 : compute_av_set (insn, NULL, 0, 0);
3190 : }
3191 1225 : }
3192 :
3193 :
3194 : /* Helper for move_op () and find_used_regs ().
3195 : Return speculation type for which a check should be created on the place
3196 : of INSN. EXPR is one of the original ops we are searching for. */
3197 : static ds_t
3198 5155 : get_spec_check_type_for_insn (insn_t insn, expr_t expr)
3199 : {
3200 5155 : ds_t to_check_ds;
3201 5155 : ds_t already_checked_ds = EXPR_SPEC_DONE_DS (INSN_EXPR (insn));
3202 :
3203 5155 : to_check_ds = EXPR_SPEC_TO_CHECK_DS (expr);
3204 :
3205 5155 : if (targetm.sched.get_insn_checked_ds)
3206 0 : already_checked_ds |= targetm.sched.get_insn_checked_ds (insn);
3207 :
3208 5155 : if (spec_info != NULL
3209 0 : && (spec_info->flags & SEL_SCHED_SPEC_DONT_CHECK_CONTROL))
3210 0 : already_checked_ds |= BEGIN_CONTROL;
3211 :
3212 5155 : already_checked_ds = ds_get_speculation_types (already_checked_ds);
3213 :
3214 5155 : to_check_ds &= ~already_checked_ds;
3215 :
3216 5155 : return to_check_ds;
3217 : }
3218 :
3219 : /* Find the set of registers that are unavailable for storing expres
3220 : while moving ORIG_OPS up on the path starting from INSN due to
3221 : liveness (USED_REGS) or hardware restrictions (REG_RENAME_P).
3222 :
3223 : All the original operations found during the traversal are saved in the
3224 : ORIGINAL_INSNS list.
3225 :
3226 : REG_RENAME_P denotes the set of hardware registers that
3227 : cannot be used with renaming due to the register class restrictions,
3228 : mode restrictions and other (the register we'll choose should be
3229 : compatible class with the original uses, shouldn't be in call_used_regs,
3230 : should be HARD_REGNO_RENAME_OK etc).
3231 :
3232 : Returns TRUE if we've found all original insns, FALSE otherwise.
3233 :
3234 : This function utilizes code_motion_path_driver (formerly find_used_regs_1)
3235 : to traverse the code motion paths. This helper function finds registers
3236 : that are not available for storing expres while moving ORIG_OPS up on the
3237 : path starting from INSN. A register considered as used on the moving path,
3238 : if one of the following conditions is not satisfied:
3239 :
3240 : (1) a register not set or read on any path from xi to an instance of
3241 : the original operation,
3242 : (2) not among the live registers of the point immediately following the
3243 : first original operation on a given downward path, except for the
3244 : original target register of the operation,
3245 : (3) not live on the other path of any conditional branch that is passed
3246 : by the operation, in case original operations are not present on
3247 : both paths of the conditional branch.
3248 :
3249 : All the original operations found during the traversal are saved in the
3250 : ORIGINAL_INSNS list.
3251 :
3252 : REG_RENAME_P->CROSSED_CALL_ABIS is true, if there is a call insn on the path
3253 : from INSN to original insn. In this case CALL_USED_REG_SET will be added
3254 : to unavailable hard regs at the point original operation is found. */
3255 :
3256 : static bool
3257 2790 : find_used_regs (insn_t insn, av_set_t orig_ops, regset used_regs,
3258 : struct reg_rename *reg_rename_p, def_list_t *original_insns)
3259 : {
3260 2790 : def_list_iterator i;
3261 2790 : def_t def;
3262 2790 : int res;
3263 2790 : bool needs_spec_check_p = false;
3264 2790 : expr_t expr;
3265 2790 : av_set_iterator expr_iter;
3266 2790 : struct fur_static_params sparams;
3267 2790 : struct cmpd_local_params lparams;
3268 :
3269 : /* We haven't visited any blocks yet. */
3270 2790 : bitmap_clear (code_motion_visited_blocks);
3271 :
3272 : /* Init parameters for code_motion_path_driver. */
3273 2790 : sparams.crossed_call_abis = 0;
3274 2790 : sparams.original_insns = original_insns;
3275 2790 : sparams.used_regs = used_regs;
3276 :
3277 : /* Set the appropriate hooks and data. */
3278 2790 : code_motion_path_driver_info = &fur_hooks;
3279 :
3280 2790 : res = code_motion_path_driver (insn, orig_ops, NULL, &lparams, &sparams);
3281 :
3282 2790 : reg_rename_p->crossed_call_abis |= sparams.crossed_call_abis;
3283 :
3284 2790 : gcc_assert (res == 1);
3285 2790 : gcc_assert (original_insns && *original_insns);
3286 :
3287 : /* ??? We calculate whether an expression needs a check when computing
3288 : av sets. This information is not as precise as it could be due to
3289 : merging this bit in merge_expr. We can do better in find_used_regs,
3290 : but we want to avoid multiple traversals of the same code motion
3291 : paths. */
3292 9474 : FOR_EACH_EXPR (expr, expr_iter, orig_ops)
3293 2790 : needs_spec_check_p |= EXPR_NEEDS_SPEC_CHECK_P (expr);
3294 :
3295 : /* Mark hardware regs in REG_RENAME_P that are not suitable
3296 : for renaming expr in INSN due to hardware restrictions (register class,
3297 : modes compatibility etc). */
3298 6684 : FOR_EACH_DEF (def, i, *original_insns)
3299 : {
3300 3894 : vinsn_t vinsn = INSN_VINSN (def->orig_insn);
3301 :
3302 3894 : if (VINSN_SEPARABLE_P (vinsn))
3303 3147 : mark_unavailable_hard_regs (def, reg_rename_p, used_regs);
3304 :
3305 : /* Do not allow clobbering of ld.[sa] address in case some of the
3306 : original operations need a check. */
3307 3894 : if (needs_spec_check_p)
3308 0 : IOR_REG_SET (used_regs, VINSN_REG_USES (vinsn));
3309 : }
3310 :
3311 2790 : return true;
3312 : }
3313 :
3314 :
3315 : /* Functions to choose the best insn from available ones. */
3316 :
3317 : /* Adjusts the priority for EXPR using the backend *_adjust_priority hook. */
3318 : static int
3319 17883 : sel_target_adjust_priority (expr_t expr)
3320 : {
3321 17883 : int priority = EXPR_PRIORITY (expr);
3322 17883 : int new_priority;
3323 :
3324 17883 : if (targetm.sched.adjust_priority)
3325 17883 : new_priority = targetm.sched.adjust_priority (EXPR_INSN_RTX (expr), priority);
3326 : else
3327 : new_priority = priority;
3328 :
3329 : /* If the priority has changed, adjust EXPR_PRIORITY_ADJ accordingly. */
3330 17883 : EXPR_PRIORITY_ADJ (expr) = new_priority - EXPR_PRIORITY (expr);
3331 :
3332 17883 : if (sched_verbose >= 4)
3333 0 : sel_print ("sel_target_adjust_priority: insn %d, %d+%d = %d.\n",
3334 0 : INSN_UID (EXPR_INSN_RTX (expr)), EXPR_PRIORITY (expr),
3335 : EXPR_PRIORITY_ADJ (expr), new_priority);
3336 :
3337 17883 : return new_priority;
3338 : }
3339 :
3340 : /* Rank two available exprs for schedule. Never return 0 here. */
3341 : static int
3342 121309 : sel_rank_for_schedule (const void *x, const void *y)
3343 : {
3344 121309 : expr_t tmp = *(const expr_t *) y;
3345 121309 : expr_t tmp2 = *(const expr_t *) x;
3346 121309 : insn_t tmp_insn, tmp2_insn;
3347 121309 : vinsn_t tmp_vinsn, tmp2_vinsn;
3348 121309 : int val;
3349 :
3350 121309 : tmp_vinsn = EXPR_VINSN (tmp);
3351 121309 : tmp2_vinsn = EXPR_VINSN (tmp2);
3352 121309 : tmp_insn = EXPR_INSN_RTX (tmp);
3353 121309 : tmp2_insn = EXPR_INSN_RTX (tmp2);
3354 :
3355 : /* Schedule debug insns as early as possible. */
3356 121309 : if (DEBUG_INSN_P (tmp_insn) && !DEBUG_INSN_P (tmp2_insn))
3357 : return -1;
3358 121309 : else if (DEBUG_INSN_P (tmp2_insn))
3359 : return 1;
3360 :
3361 : /* Prefer SCHED_GROUP_P insns to any others. */
3362 121309 : if (SCHED_GROUP_P (tmp_insn) != SCHED_GROUP_P (tmp2_insn))
3363 : {
3364 1551 : if (VINSN_UNIQUE_P (tmp_vinsn) && VINSN_UNIQUE_P (tmp2_vinsn))
3365 0 : return SCHED_GROUP_P (tmp2_insn) ? 1 : -1;
3366 :
3367 : /* Now uniqueness means SCHED_GROUP_P is set, because schedule groups
3368 : cannot be cloned. */
3369 1551 : if (VINSN_UNIQUE_P (tmp2_vinsn))
3370 : return 1;
3371 : return -1;
3372 : }
3373 :
3374 : /* Discourage scheduling of speculative checks. */
3375 119758 : val = (sel_insn_is_speculation_check (tmp_insn)
3376 119758 : - sel_insn_is_speculation_check (tmp2_insn));
3377 119758 : if (val)
3378 : return val;
3379 :
3380 : /* Prefer not scheduled insn over scheduled one. */
3381 119758 : if (EXPR_SCHED_TIMES (tmp) > 0 || EXPR_SCHED_TIMES (tmp2) > 0)
3382 : {
3383 13315 : val = EXPR_SCHED_TIMES (tmp) - EXPR_SCHED_TIMES (tmp2);
3384 13315 : if (val)
3385 : return val;
3386 : }
3387 :
3388 : /* Prefer jump over non-jump instruction. */
3389 112346 : if (control_flow_insn_p (tmp_insn) && !control_flow_insn_p (tmp2_insn))
3390 : return -1;
3391 111863 : else if (control_flow_insn_p (tmp2_insn) && !control_flow_insn_p (tmp_insn))
3392 : return 1;
3393 :
3394 : /* Prefer an expr with non-zero usefulness. */
3395 111595 : int u1 = EXPR_USEFULNESS (tmp), u2 = EXPR_USEFULNESS (tmp2);
3396 :
3397 111595 : if (u1 == 0)
3398 : {
3399 226 : if (u2 == 0)
3400 : u1 = u2 = 1;
3401 : else
3402 : return 1;
3403 : }
3404 111369 : else if (u2 == 0)
3405 : return -1;
3406 :
3407 : /* Prefer an expr with greater priority. */
3408 111302 : val = (u2 * (EXPR_PRIORITY (tmp2) + EXPR_PRIORITY_ADJ (tmp2))
3409 111302 : - u1 * (EXPR_PRIORITY (tmp) + EXPR_PRIORITY_ADJ (tmp)));
3410 111302 : if (val)
3411 : return val;
3412 :
3413 38188 : if (spec_info != NULL && spec_info->mask != 0)
3414 : /* This code was taken from haifa-sched.cc: rank_for_schedule (). */
3415 : {
3416 0 : ds_t ds1, ds2;
3417 0 : dw_t dw1, dw2;
3418 0 : int dw;
3419 :
3420 0 : ds1 = EXPR_SPEC_DONE_DS (tmp);
3421 0 : if (ds1)
3422 0 : dw1 = ds_weak (ds1);
3423 : else
3424 : dw1 = NO_DEP_WEAK;
3425 :
3426 0 : ds2 = EXPR_SPEC_DONE_DS (tmp2);
3427 0 : if (ds2)
3428 0 : dw2 = ds_weak (ds2);
3429 : else
3430 : dw2 = NO_DEP_WEAK;
3431 :
3432 0 : dw = dw2 - dw1;
3433 0 : if (dw > (NO_DEP_WEAK / 8) || dw < -(NO_DEP_WEAK / 8))
3434 : return dw;
3435 : }
3436 :
3437 : /* Prefer an old insn to a bookkeeping insn. */
3438 38188 : if (INSN_UID (tmp_insn) < first_emitted_uid
3439 38188 : && INSN_UID (tmp2_insn) >= first_emitted_uid)
3440 : return -1;
3441 37754 : if (INSN_UID (tmp_insn) >= first_emitted_uid
3442 37754 : && INSN_UID (tmp2_insn) < first_emitted_uid)
3443 : return 1;
3444 :
3445 : /* Prefer an insn with smaller UID, as a last resort.
3446 : We can't safely use INSN_LUID as it is defined only for those insns
3447 : that are in the stream. */
3448 37466 : return INSN_UID (tmp_insn) - INSN_UID (tmp2_insn);
3449 : }
3450 :
3451 : /* Filter out expressions from av set pointed to by AV_PTR
3452 : that are pipelined too many times. */
3453 : static void
3454 7728 : process_pipelined_exprs (av_set_t *av_ptr)
3455 : {
3456 7728 : expr_t expr;
3457 7728 : av_set_iterator si;
3458 :
3459 : /* Don't pipeline already pipelined code as that would increase
3460 : number of unnecessary register moves. */
3461 44198 : FOR_EACH_EXPR_1 (expr, si, av_ptr)
3462 : {
3463 18235 : if (EXPR_SCHED_TIMES (expr)
3464 18235 : >= param_selsched_max_sched_times)
3465 114 : av_set_iter_remove (&si);
3466 : }
3467 7728 : }
3468 :
3469 : /* Filter speculative insns from AV_PTR if we don't want them. */
3470 : static void
3471 7728 : process_spec_exprs (av_set_t *av_ptr)
3472 : {
3473 7728 : expr_t expr;
3474 7728 : av_set_iterator si;
3475 :
3476 7728 : if (spec_info == NULL)
3477 7728 : return;
3478 :
3479 : /* Scan *AV_PTR to find out if we want to consider speculative
3480 : instructions for scheduling. */
3481 0 : FOR_EACH_EXPR_1 (expr, si, av_ptr)
3482 : {
3483 0 : ds_t ds;
3484 :
3485 0 : ds = EXPR_SPEC_DONE_DS (expr);
3486 :
3487 : /* The probability of a success is too low - don't speculate. */
3488 0 : if ((ds & SPECULATIVE)
3489 0 : && (ds_weak (ds) < spec_info->data_weakness_cutoff
3490 0 : || EXPR_USEFULNESS (expr) < spec_info->control_weakness_cutoff
3491 0 : || (pipelining_p && false
3492 : && (ds & DATA_SPEC)
3493 : && (ds & CONTROL_SPEC))))
3494 : {
3495 0 : av_set_iter_remove (&si);
3496 0 : continue;
3497 : }
3498 : }
3499 : }
3500 :
3501 : /* Search for any use-like insns in AV_PTR and decide on scheduling
3502 : them. Return one when found, and NULL otherwise.
3503 : Note that we check here whether a USE could be scheduled to avoid
3504 : an infinite loop later. */
3505 : static expr_t
3506 7728 : process_use_exprs (av_set_t *av_ptr)
3507 : {
3508 7728 : expr_t expr;
3509 7728 : av_set_iterator si;
3510 7728 : bool uses_present_p = false;
3511 7728 : bool try_uses_p = true;
3512 :
3513 43602 : FOR_EACH_EXPR_1 (expr, si, av_ptr)
3514 : {
3515 : /* This will also initialize INSN_CODE for later use. */
3516 18046 : if (recog_memoized (EXPR_INSN_RTX (expr)) < 0)
3517 : {
3518 : /* If we have a USE in *AV_PTR that was not scheduled yet,
3519 : do so because it will do good only. */
3520 130 : if (EXPR_SCHED_TIMES (expr) <= 0)
3521 : {
3522 127 : if (EXPR_TARGET_AVAILABLE (expr) == 1)
3523 : return expr;
3524 :
3525 18 : av_set_iter_remove (&si);
3526 : }
3527 : else
3528 : {
3529 3 : gcc_assert (pipelining_p);
3530 :
3531 : uses_present_p = true;
3532 : }
3533 : }
3534 : else
3535 : try_uses_p = false;
3536 : }
3537 :
3538 7619 : if (uses_present_p)
3539 : {
3540 : /* If we don't want to schedule any USEs right now and we have some
3541 : in *AV_PTR, remove them, else just return the first one found. */
3542 3 : if (!try_uses_p)
3543 : {
3544 29 : FOR_EACH_EXPR_1 (expr, si, av_ptr)
3545 13 : if (INSN_CODE (EXPR_INSN_RTX (expr)) < 0)
3546 3 : av_set_iter_remove (&si);
3547 : }
3548 : else
3549 : {
3550 0 : FOR_EACH_EXPR_1 (expr, si, av_ptr)
3551 : {
3552 0 : gcc_assert (INSN_CODE (EXPR_INSN_RTX (expr)) < 0);
3553 :
3554 0 : if (EXPR_TARGET_AVAILABLE (expr) == 1)
3555 : return expr;
3556 :
3557 0 : av_set_iter_remove (&si);
3558 : }
3559 : }
3560 : }
3561 :
3562 : return NULL;
3563 : }
3564 :
3565 : /* Lookup EXPR in VINSN_VEC and return TRUE if found. Also check patterns from
3566 : EXPR's history of changes. */
3567 : static bool
3568 35766 : vinsn_vec_has_expr_p (vinsn_vec_t vinsn_vec, expr_t expr)
3569 : {
3570 35766 : vinsn_t vinsn, expr_vinsn;
3571 35766 : int n;
3572 35766 : unsigned i;
3573 :
3574 : /* Start with checking expr itself and then proceed with all the old forms
3575 : of expr taken from its history vector. */
3576 35766 : for (i = 0, expr_vinsn = EXPR_VINSN (expr);
3577 36444 : expr_vinsn;
3578 72708 : expr_vinsn = (i < EXPR_HISTORY_OF_CHANGES (expr).length ()
3579 36354 : ? EXPR_HISTORY_OF_CHANGES (expr)[i++].old_expr_vinsn
3580 : : NULL))
3581 41842 : FOR_EACH_VEC_ELT (vinsn_vec, n, vinsn)
3582 2406 : if (VINSN_SEPARABLE_P (vinsn))
3583 : {
3584 2291 : if (vinsn_equal_p (vinsn, expr_vinsn))
3585 : return true;
3586 : }
3587 : else
3588 : {
3589 : /* For non-separable instructions, the blocking insn can have
3590 : another pattern due to substitution, and we can't choose
3591 : different register as in the above case. Check all registers
3592 : being written instead. */
3593 115 : if (bitmap_intersect_p (VINSN_REG_SETS (vinsn),
3594 115 : VINSN_REG_SETS (expr_vinsn)))
3595 : return true;
3596 : }
3597 :
3598 : return false;
3599 : }
3600 :
3601 : /* Return true if either of expressions from ORIG_OPS can be blocked
3602 : by previously created bookkeeping code. STATIC_PARAMS points to static
3603 : parameters of move_op. */
3604 : static bool
3605 0 : av_set_could_be_blocked_by_bookkeeping_p (av_set_t orig_ops, void *static_params)
3606 : {
3607 0 : expr_t expr;
3608 0 : av_set_iterator iter;
3609 0 : moveop_static_params_p sparams;
3610 :
3611 : /* This checks that expressions in ORIG_OPS are not blocked by bookkeeping
3612 : created while scheduling on another fence. */
3613 0 : FOR_EACH_EXPR (expr, iter, orig_ops)
3614 0 : if (vinsn_vec_has_expr_p (vec_bookkeeping_blocked_vinsns, expr))
3615 : return true;
3616 :
3617 0 : gcc_assert (code_motion_path_driver_info == &move_op_hooks);
3618 0 : sparams = (moveop_static_params_p) static_params;
3619 :
3620 : /* Expressions can be also blocked by bookkeeping created during current
3621 : move_op. */
3622 0 : if (bitmap_bit_p (current_copies, INSN_UID (sparams->failed_insn)))
3623 0 : FOR_EACH_EXPR (expr, iter, orig_ops)
3624 0 : if (moveup_expr_cached (expr, sparams->failed_insn, false) != MOVEUP_EXPR_NULL)
3625 : return true;
3626 :
3627 : /* Expressions in ORIG_OPS may have wrong destination register due to
3628 : renaming. Check with the right register instead. */
3629 0 : if (sparams->dest && REG_P (sparams->dest))
3630 : {
3631 0 : rtx reg = sparams->dest;
3632 0 : vinsn_t failed_vinsn = INSN_VINSN (sparams->failed_insn);
3633 :
3634 0 : if (register_unavailable_p (VINSN_REG_SETS (failed_vinsn), reg)
3635 0 : || register_unavailable_p (VINSN_REG_USES (failed_vinsn), reg)
3636 0 : || register_unavailable_p (VINSN_REG_CLOBBERS (failed_vinsn), reg))
3637 0 : return true;
3638 : }
3639 :
3640 : return false;
3641 : }
3642 :
3643 : /* Clear VINSN_VEC and detach vinsns. */
3644 : static void
3645 3472 : vinsn_vec_clear (vinsn_vec_t *vinsn_vec)
3646 : {
3647 3472 : unsigned len = vinsn_vec->length ();
3648 223 : if (len > 0)
3649 : {
3650 : vinsn_t vinsn;
3651 : int n;
3652 :
3653 75 : FOR_EACH_VEC_ELT (*vinsn_vec, n, vinsn)
3654 50 : vinsn_detach (vinsn);
3655 25 : vinsn_vec->block_remove (0, len);
3656 : }
3657 3472 : }
3658 :
3659 : /* Add the vinsn of EXPR to the VINSN_VEC. */
3660 : static void
3661 50 : vinsn_vec_add (vinsn_vec_t *vinsn_vec, expr_t expr)
3662 : {
3663 50 : vinsn_attach (EXPR_VINSN (expr));
3664 50 : vinsn_vec->safe_push (EXPR_VINSN (expr));
3665 50 : }
3666 :
3667 : /* Free the vector representing blocked expressions. */
3668 : static void
3669 1540 : vinsn_vec_free (vinsn_vec_t &vinsn_vec)
3670 : {
3671 0 : vinsn_vec.release ();
3672 0 : }
3673 :
3674 : /* Increase EXPR_PRIORITY_ADJ for INSN by AMOUNT. */
3675 :
3676 0 : void sel_add_to_insn_priority (rtx insn, int amount)
3677 : {
3678 0 : EXPR_PRIORITY_ADJ (INSN_EXPR (insn)) += amount;
3679 :
3680 0 : if (sched_verbose >= 2)
3681 0 : sel_print ("sel_add_to_insn_priority: insn %d, by %d (now %d+%d).\n",
3682 0 : INSN_UID (insn), amount, EXPR_PRIORITY (INSN_EXPR (insn)),
3683 0 : EXPR_PRIORITY_ADJ (INSN_EXPR (insn)));
3684 0 : }
3685 :
3686 : /* Turn AV into a vector, filter inappropriate insns and sort it. Return
3687 : true if there is something to schedule. BNDS and FENCE are current
3688 : boundaries and fence, respectively. If we need to stall for some cycles
3689 : before an expr from AV would become available, write this number to
3690 : *PNEED_STALL. */
3691 : static bool
3692 7619 : fill_vec_av_set (av_set_t av, blist_t bnds, fence_t fence,
3693 : int *pneed_stall)
3694 : {
3695 7619 : av_set_iterator si;
3696 7619 : expr_t expr;
3697 7619 : int sched_next_worked = 0, stalled, n;
3698 7619 : static int av_max_prio, est_ticks_till_branch;
3699 7619 : int min_need_stall = -1;
3700 7619 : deps_t dc = BND_DC (BLIST_BND (bnds));
3701 :
3702 : /* Bail out early when the ready list contained only USEs/CLOBBERs that are
3703 : already scheduled. */
3704 7619 : if (av == NULL)
3705 : return false;
3706 :
3707 : /* Empty vector from the previous stuff. */
3708 7619 : if (vec_av_set.length () > 0)
3709 5224 : vec_av_set.block_remove (0, vec_av_set.length ());
3710 :
3711 : /* Turn the set into a vector for sorting and call sel_target_adjust_priority
3712 : for each insn. */
3713 33121 : gcc_assert (vec_av_set.is_empty ());
3714 25502 : FOR_EACH_EXPR (expr, si, av)
3715 : {
3716 17883 : vec_av_set.safe_push (expr);
3717 :
3718 17883 : gcc_assert (EXPR_PRIORITY_ADJ (expr) == 0 || *pneed_stall);
3719 :
3720 : /* Adjust priority using target backend hook. */
3721 17883 : sel_target_adjust_priority (expr);
3722 : }
3723 :
3724 : /* Sort the vector. */
3725 7619 : vec_av_set.qsort (sel_rank_for_schedule);
3726 :
3727 : /* We record maximal priority of insns in av set for current instruction
3728 : group. */
3729 7619 : if (FENCE_STARTS_CYCLE_P (fence))
3730 3700 : av_max_prio = est_ticks_till_branch = INT_MIN;
3731 :
3732 : /* Filter out inappropriate expressions. Loop's direction is reversed to
3733 : visit "best" instructions first. We assume that vec::unordered_remove
3734 : moves last element in place of one being deleted. */
3735 33121 : for (n = vec_av_set.length () - 1, stalled = 0; n >= 0; n--)
3736 : {
3737 17883 : expr_t expr = vec_av_set[n];
3738 17883 : insn_t insn = EXPR_INSN_RTX (expr);
3739 17883 : signed char target_available;
3740 17883 : bool is_orig_reg_p = true;
3741 17883 : int need_cycles, new_prio;
3742 17883 : bool fence_insn_p = INSN_UID (insn) == INSN_UID (FENCE_INSN (fence));
3743 :
3744 : /* Don't allow any insns other than from SCHED_GROUP if we have one. */
3745 17883 : if (FENCE_SCHED_NEXT (fence) && insn != FENCE_SCHED_NEXT (fence))
3746 : {
3747 0 : vec_av_set.unordered_remove (n);
3748 7853 : continue;
3749 : }
3750 :
3751 : /* Set number of sched_next insns (just in case there
3752 : could be several). */
3753 17883 : if (FENCE_SCHED_NEXT (fence))
3754 0 : sched_next_worked++;
3755 :
3756 : /* Check all liveness requirements and try renaming.
3757 : FIXME: try to minimize calls to this. */
3758 17883 : target_available = EXPR_TARGET_AVAILABLE (expr);
3759 :
3760 : /* If insn was already scheduled on the current fence,
3761 : set TARGET_AVAILABLE to -1 no matter what expr's attribute says. */
3762 17883 : if (vinsn_vec_has_expr_p (vec_target_unavailable_vinsns, expr)
3763 17883 : && !fence_insn_p)
3764 17883 : target_available = -1;
3765 :
3766 : /* If the availability of the EXPR is invalidated by the insertion of
3767 : bookkeeping earlier, make sure that we won't choose this expr for
3768 : scheduling if it's not separable, and if it is separable, then
3769 : we have to recompute the set of available registers for it. */
3770 17883 : if (vinsn_vec_has_expr_p (vec_bookkeeping_blocked_vinsns, expr))
3771 : {
3772 17 : vec_av_set.unordered_remove (n);
3773 17 : if (sched_verbose >= 4)
3774 0 : sel_print ("Expr %d is blocked by bookkeeping inserted earlier\n",
3775 0 : INSN_UID (insn));
3776 17 : continue;
3777 : }
3778 :
3779 17866 : if (target_available == true)
3780 : {
3781 : /* Do nothing -- we can use an existing register. */
3782 13535 : is_orig_reg_p = EXPR_SEPARABLE_P (expr);
3783 : }
3784 8441 : else if (/* Non-separable instruction will never
3785 : get another register. */
3786 : (target_available == false
3787 4069 : && !EXPR_SEPARABLE_P (expr))
3788 : /* Don't try to find a register for low-priority expression. */
3789 4069 : || (int) vec_av_set.length () - 1 - n >= max_insns_to_rename
3790 : /* ??? FIXME: Don't try to rename data speculation. */
3791 2790 : || (EXPR_SPEC_DONE_DS (expr) & BEGIN_DATA)
3792 7121 : || ! find_best_reg_for_expr (expr, bnds, &is_orig_reg_p))
3793 : {
3794 4110 : vec_av_set.unordered_remove (n);
3795 4110 : if (sched_verbose >= 4)
3796 0 : sel_print ("Expr %d has no suitable target register\n",
3797 0 : INSN_UID (insn));
3798 :
3799 : /* A fence insn should not get here. */
3800 4110 : gcc_assert (!fence_insn_p);
3801 4110 : continue;
3802 : }
3803 :
3804 : /* At this point a fence insn should always be available. */
3805 13756 : gcc_assert (!fence_insn_p
3806 : || INSN_UID (FENCE_INSN (fence)) == INSN_UID (EXPR_INSN_RTX (expr)));
3807 :
3808 : /* Filter expressions that need to be renamed or speculated when
3809 : pipelining, because compensating register copies or speculation
3810 : checks are likely to be placed near the beginning of the loop,
3811 : causing a stall. */
3812 13756 : if (pipelining_p && EXPR_ORIG_SCHED_CYCLE (expr) > 0
3813 363 : && (!is_orig_reg_p || EXPR_SPEC_DONE_DS (expr) != 0))
3814 : {
3815 : /* Estimation of number of cycles until loop branch for
3816 : renaming/speculation to be successful. */
3817 162 : int need_n_ticks_till_branch = sel_vinsn_cost (EXPR_VINSN (expr));
3818 :
3819 162 : if ((int) current_loop_nest->ninsns < 9)
3820 : {
3821 11 : vec_av_set.unordered_remove (n);
3822 11 : if (sched_verbose >= 4)
3823 0 : sel_print ("Pipelining expr %d will likely cause stall\n",
3824 0 : INSN_UID (insn));
3825 11 : continue;
3826 : }
3827 :
3828 151 : if ((int) current_loop_nest->ninsns - num_insns_scheduled
3829 151 : < need_n_ticks_till_branch * issue_rate / 2
3830 30 : && est_ticks_till_branch < need_n_ticks_till_branch)
3831 : {
3832 16 : vec_av_set.unordered_remove (n);
3833 16 : if (sched_verbose >= 4)
3834 0 : sel_print ("Pipelining expr %d will likely cause stall\n",
3835 0 : INSN_UID (insn));
3836 16 : continue;
3837 : }
3838 : }
3839 :
3840 : /* We want to schedule speculation checks as late as possible. Discard
3841 : them from av set if there are instructions with higher priority. */
3842 13729 : if (sel_insn_is_speculation_check (insn)
3843 13729 : && EXPR_PRIORITY (expr) < av_max_prio)
3844 : {
3845 0 : stalled++;
3846 0 : min_need_stall = min_need_stall < 0 ? 1 : MIN (min_need_stall, 1);
3847 0 : vec_av_set.unordered_remove (n);
3848 0 : if (sched_verbose >= 4)
3849 0 : sel_print ("Delaying speculation check %d until its first use\n",
3850 0 : INSN_UID (insn));
3851 0 : continue;
3852 : }
3853 :
3854 : /* Ignore EXPRs available from pipelining to update AV_MAX_PRIO. */
3855 13729 : if (EXPR_ORIG_SCHED_CYCLE (expr) <= 0)
3856 12326 : av_max_prio = MAX (av_max_prio, EXPR_PRIORITY (expr));
3857 :
3858 : /* Don't allow any insns whose data is not yet ready.
3859 : Check first whether we've already tried them and failed. */
3860 13729 : if (INSN_UID (insn) < FENCE_READY_TICKS_SIZE (fence))
3861 : {
3862 13379 : need_cycles = (FENCE_READY_TICKS (fence)[INSN_UID (insn)]
3863 13379 : - FENCE_CYCLE (fence));
3864 13379 : if (EXPR_ORIG_SCHED_CYCLE (expr) <= 0)
3865 11992 : est_ticks_till_branch = MAX (est_ticks_till_branch,
3866 : EXPR_PRIORITY (expr) + need_cycles);
3867 :
3868 13379 : if (need_cycles > 0)
3869 : {
3870 1721 : stalled++;
3871 3442 : min_need_stall = (min_need_stall < 0
3872 1721 : ? need_cycles
3873 818 : : MIN (min_need_stall, need_cycles));
3874 1721 : vec_av_set.unordered_remove (n);
3875 :
3876 1721 : if (sched_verbose >= 4)
3877 0 : sel_print ("Expr %d is not ready until cycle %d (cached)\n",
3878 : INSN_UID (insn),
3879 0 : FENCE_READY_TICKS (fence)[INSN_UID (insn)]);
3880 1721 : continue;
3881 : }
3882 : }
3883 :
3884 : /* Now resort to dependence analysis to find whether EXPR might be
3885 : stalled due to dependencies from FENCE's context. */
3886 12008 : need_cycles = tick_check_p (expr, dc, fence);
3887 12008 : new_prio = EXPR_PRIORITY (expr) + EXPR_PRIORITY_ADJ (expr) + need_cycles;
3888 :
3889 12008 : if (EXPR_ORIG_SCHED_CYCLE (expr) <= 0)
3890 10707 : est_ticks_till_branch = MAX (est_ticks_till_branch,
3891 : new_prio);
3892 :
3893 12008 : if (need_cycles > 0)
3894 : {
3895 1978 : if (INSN_UID (insn) >= FENCE_READY_TICKS_SIZE (fence))
3896 : {
3897 92 : int new_size = INSN_UID (insn) * 3 / 2;
3898 :
3899 92 : FENCE_READY_TICKS (fence)
3900 92 : = (int *) xrecalloc (FENCE_READY_TICKS (fence),
3901 : new_size, FENCE_READY_TICKS_SIZE (fence),
3902 : sizeof (int));
3903 : }
3904 3956 : FENCE_READY_TICKS (fence)[INSN_UID (insn)]
3905 1978 : = FENCE_CYCLE (fence) + need_cycles;
3906 :
3907 1978 : stalled++;
3908 3956 : min_need_stall = (min_need_stall < 0
3909 1978 : ? need_cycles
3910 553 : : MIN (min_need_stall, need_cycles));
3911 :
3912 1978 : vec_av_set.unordered_remove (n);
3913 :
3914 1978 : if (sched_verbose >= 4)
3915 0 : sel_print ("Expr %d is not ready yet until cycle %d\n",
3916 : INSN_UID (insn),
3917 0 : FENCE_READY_TICKS (fence)[INSN_UID (insn)]);
3918 1978 : continue;
3919 1978 : }
3920 :
3921 10030 : if (sched_verbose >= 4)
3922 0 : sel_print ("Expr %d is ok\n", INSN_UID (insn));
3923 10030 : min_need_stall = 0;
3924 : }
3925 :
3926 : /* Clear SCHED_NEXT. */
3927 7619 : if (FENCE_SCHED_NEXT (fence))
3928 : {
3929 0 : gcc_assert (sched_next_worked == 1);
3930 0 : FENCE_SCHED_NEXT (fence) = NULL;
3931 : }
3932 :
3933 : /* No need to stall if this variable was not initialized. */
3934 7619 : if (min_need_stall < 0)
3935 : min_need_stall = 0;
3936 :
3937 7619 : if (vec_av_set.is_empty ())
3938 : {
3939 : /* We need to set *pneed_stall here, because later we skip this code
3940 : when ready list is empty. */
3941 1625 : *pneed_stall = min_need_stall;
3942 1625 : return false;
3943 : }
3944 : else
3945 5994 : gcc_assert (min_need_stall == 0);
3946 :
3947 : /* Sort the vector. */
3948 5994 : vec_av_set.qsort (sel_rank_for_schedule);
3949 :
3950 5994 : if (sched_verbose >= 4)
3951 : {
3952 0 : sel_print ("Total ready exprs: %d, stalled: %d\n",
3953 : vec_av_set.length (), stalled);
3954 0 : sel_print ("Sorted av set (%d): ", vec_av_set.length ());
3955 0 : FOR_EACH_VEC_ELT (vec_av_set, n, expr)
3956 0 : dump_expr (expr);
3957 0 : sel_print ("\n");
3958 : }
3959 :
3960 5994 : *pneed_stall = 0;
3961 5994 : return true;
3962 : }
3963 :
3964 : /* Convert a vectored and sorted av set to the ready list that
3965 : the rest of the backend wants to see. */
3966 : static void
3967 5994 : convert_vec_av_set_to_ready (void)
3968 : {
3969 5994 : int n;
3970 5994 : expr_t expr;
3971 :
3972 : /* Allocate and fill the ready list from the sorted vector. */
3973 5994 : ready.n_ready = vec_av_set.length ();
3974 5994 : ready.first = ready.n_ready - 1;
3975 :
3976 5994 : gcc_assert (ready.n_ready > 0);
3977 :
3978 5994 : if (ready.n_ready > max_issue_size)
3979 : {
3980 883 : max_issue_size = ready.n_ready;
3981 883 : sched_extend_ready_list (ready.n_ready);
3982 : }
3983 :
3984 16024 : FOR_EACH_VEC_ELT (vec_av_set, n, expr)
3985 : {
3986 10030 : vinsn_t vi = EXPR_VINSN (expr);
3987 10030 : insn_t insn = VINSN_INSN_RTX (vi);
3988 :
3989 10030 : ready_try[n] = 0;
3990 10030 : ready.vec[n] = insn;
3991 : }
3992 5994 : }
3993 :
3994 : /* Initialize ready list from *AV_PTR for the max_issue () call.
3995 : If any unrecognizable insn found in *AV_PTR, return it (and skip
3996 : max_issue). BND and FENCE are current boundary and fence,
3997 : respectively. If we need to stall for some cycles before an expr
3998 : from *AV_PTR would become available, write this number to *PNEED_STALL. */
3999 : static expr_t
4000 7728 : fill_ready_list (av_set_t *av_ptr, blist_t bnds, fence_t fence,
4001 : int *pneed_stall)
4002 : {
4003 7728 : expr_t expr;
4004 :
4005 : /* We do not support multiple boundaries per fence. */
4006 7728 : gcc_assert (BLIST_NEXT (bnds) == NULL);
4007 :
4008 : /* Process expressions required special handling, i.e. pipelined,
4009 : speculative and recog() < 0 expressions first. */
4010 7728 : process_pipelined_exprs (av_ptr);
4011 7728 : process_spec_exprs (av_ptr);
4012 :
4013 : /* A USE could be scheduled immediately. */
4014 7728 : expr = process_use_exprs (av_ptr);
4015 7728 : if (expr)
4016 : {
4017 109 : *pneed_stall = 0;
4018 109 : return expr;
4019 : }
4020 :
4021 : /* Turn the av set to a vector for sorting. */
4022 7619 : if (! fill_vec_av_set (*av_ptr, bnds, fence, pneed_stall))
4023 : {
4024 1625 : ready.n_ready = 0;
4025 1625 : return NULL;
4026 : }
4027 :
4028 : /* Build the final ready list. */
4029 5994 : convert_vec_av_set_to_ready ();
4030 5994 : return NULL;
4031 : }
4032 :
4033 : /* Wrapper for dfa_new_cycle (). Returns TRUE if cycle was advanced. */
4034 : static bool
4035 4901 : sel_dfa_new_cycle (insn_t insn, fence_t fence)
4036 : {
4037 4901 : int last_scheduled_cycle = FENCE_LAST_SCHEDULED_INSN (fence)
4038 4901 : ? INSN_SCHED_CYCLE (FENCE_LAST_SCHEDULED_INSN (fence))
4039 4901 : : FENCE_CYCLE (fence) - 1;
4040 4901 : bool res = false;
4041 4901 : int sort_p = 0;
4042 :
4043 4901 : if (!targetm.sched.dfa_new_cycle)
4044 : return false;
4045 :
4046 0 : memcpy (curr_state, FENCE_STATE (fence), dfa_state_size);
4047 :
4048 0 : while (!sort_p && targetm.sched.dfa_new_cycle (sched_dump, sched_verbose,
4049 : insn, last_scheduled_cycle,
4050 : FENCE_CYCLE (fence), &sort_p))
4051 : {
4052 0 : memcpy (FENCE_STATE (fence), curr_state, dfa_state_size);
4053 0 : advance_one_cycle (fence);
4054 0 : memcpy (curr_state, FENCE_STATE (fence), dfa_state_size);
4055 0 : res = true;
4056 : }
4057 :
4058 : return res;
4059 : }
4060 :
4061 : /* Invoke reorder* target hooks on the ready list. Return the number of insns
4062 : we can issue. FENCE is the current fence. */
4063 : static int
4064 5994 : invoke_reorder_hooks (fence_t fence)
4065 : {
4066 5994 : int issue_more;
4067 5994 : bool ran_hook = false;
4068 :
4069 : /* Call the reorder hook at the beginning of the cycle, and call
4070 : the reorder2 hook in the middle of the cycle. */
4071 5994 : if (FENCE_ISSUED_INSNS (fence) == 0)
4072 : {
4073 3475 : if (targetm.sched.reorder
4074 3475 : && !SCHED_GROUP_P (ready_element (&ready, 0))
4075 6593 : && ready.n_ready > 1)
4076 : {
4077 : /* Don't give reorder the most prioritized insn as it can break
4078 : pipelining. */
4079 903 : if (pipelining_p)
4080 290 : --ready.n_ready;
4081 :
4082 903 : issue_more
4083 903 : = targetm.sched.reorder (sched_dump, sched_verbose,
4084 : ready_lastpos (&ready),
4085 : &ready.n_ready, FENCE_CYCLE (fence));
4086 :
4087 903 : if (pipelining_p)
4088 290 : ++ready.n_ready;
4089 :
4090 : ran_hook = true;
4091 : }
4092 : else
4093 : /* Initialize can_issue_more for variable_issue. */
4094 2572 : issue_more = issue_rate;
4095 : }
4096 2519 : else if (targetm.sched.reorder2
4097 2519 : && !SCHED_GROUP_P (ready_element (&ready, 0)))
4098 : {
4099 0 : if (ready.n_ready == 1)
4100 0 : issue_more =
4101 0 : targetm.sched.reorder2 (sched_dump, sched_verbose,
4102 : ready_lastpos (&ready),
4103 : &ready.n_ready, FENCE_CYCLE (fence));
4104 : else
4105 : {
4106 0 : if (pipelining_p)
4107 0 : --ready.n_ready;
4108 :
4109 0 : issue_more =
4110 0 : targetm.sched.reorder2 (sched_dump, sched_verbose,
4111 0 : ready.n_ready
4112 0 : ? ready_lastpos (&ready) : NULL,
4113 : &ready.n_ready, FENCE_CYCLE (fence));
4114 :
4115 0 : if (pipelining_p)
4116 0 : ++ready.n_ready;
4117 : }
4118 :
4119 : ran_hook = true;
4120 : }
4121 : else
4122 2519 : issue_more = FENCE_ISSUE_MORE (fence);
4123 :
4124 : /* Ensure that ready list and vec_av_set are in line with each other,
4125 : i.e. vec_av_set[i] == ready_element (&ready, i). */
4126 5994 : if (issue_more && ran_hook)
4127 : {
4128 903 : int i, j, n;
4129 903 : rtx_insn **arr = ready.vec;
4130 903 : expr_t *vec = vec_av_set.address ();
4131 :
4132 3584 : for (i = 0, n = ready.n_ready; i < n; i++)
4133 2681 : if (EXPR_INSN_RTX (vec[i]) != arr[i])
4134 : {
4135 0 : for (j = i; j < n; j++)
4136 0 : if (EXPR_INSN_RTX (vec[j]) == arr[i])
4137 : break;
4138 0 : gcc_assert (j < n);
4139 :
4140 0 : std::swap (vec[i], vec[j]);
4141 : }
4142 : }
4143 :
4144 5994 : return issue_more;
4145 : }
4146 :
4147 : /* Return an EXPR corresponding to INDEX element of ready list, if
4148 : FOLLOW_READY_ELEMENT is true (i.e., an expr of
4149 : ready_element (&ready, INDEX) will be returned), and to INDEX element of
4150 : ready.vec otherwise. */
4151 : static inline expr_t
4152 28013 : find_expr_for_ready (int index, bool follow_ready_element)
4153 : {
4154 28013 : expr_t expr;
4155 28013 : int real_index;
4156 :
4157 28013 : real_index = follow_ready_element ? ready.first - index : index;
4158 :
4159 28013 : expr = vec_av_set[real_index];
4160 28013 : gcc_assert (ready.vec[real_index] == EXPR_INSN_RTX (expr));
4161 :
4162 28013 : return expr;
4163 : }
4164 :
4165 : /* Calculate insns worth trying via lookahead_guard hook. Return a number
4166 : of such insns found. */
4167 : static int
4168 4928 : invoke_dfa_lookahead_guard (void)
4169 : {
4170 4928 : int i, n;
4171 4928 : bool have_hook
4172 4928 : = targetm.sched.first_cycle_multipass_dfa_lookahead_guard != NULL;
4173 :
4174 4928 : if (sched_verbose >= 2)
4175 0 : sel_print ("ready after reorder: ");
4176 :
4177 13298 : for (i = 0, n = 0; i < ready.n_ready; i++)
4178 : {
4179 8370 : expr_t expr;
4180 8370 : insn_t insn;
4181 8370 : int r;
4182 :
4183 : /* In this loop insn is Ith element of the ready list given by
4184 : ready_element, not Ith element of ready.vec. */
4185 8370 : insn = ready_element (&ready, i);
4186 :
4187 8370 : if (! have_hook || i == 0)
4188 : r = 0;
4189 : else
4190 0 : r = targetm.sched.first_cycle_multipass_dfa_lookahead_guard (insn, i);
4191 :
4192 8370 : gcc_assert (INSN_CODE (insn) >= 0);
4193 :
4194 : /* Only insns with ready_try = 0 can get here
4195 : from fill_ready_list. */
4196 8370 : gcc_assert (ready_try [i] == 0);
4197 8370 : ready_try[i] = r;
4198 8370 : if (!r)
4199 8370 : n++;
4200 :
4201 8370 : expr = find_expr_for_ready (i, true);
4202 :
4203 8370 : if (sched_verbose >= 2)
4204 : {
4205 0 : dump_vinsn (EXPR_VINSN (expr));
4206 0 : sel_print (":%d; ", ready_try[i]);
4207 : }
4208 : }
4209 :
4210 4928 : if (sched_verbose >= 2)
4211 0 : sel_print ("\n");
4212 4928 : return n;
4213 : }
4214 :
4215 : /* Calculate the number of privileged insns and return it. */
4216 : static int
4217 4928 : calculate_privileged_insns (void)
4218 : {
4219 4928 : expr_t cur_expr, min_spec_expr = NULL;
4220 4928 : int privileged_n = 0, i;
4221 :
4222 13212 : for (i = 0; i < ready.n_ready; i++)
4223 : {
4224 8343 : if (ready_try[i])
4225 0 : continue;
4226 :
4227 8343 : if (! min_spec_expr)
4228 4928 : min_spec_expr = find_expr_for_ready (i, true);
4229 :
4230 8343 : cur_expr = find_expr_for_ready (i, true);
4231 :
4232 8343 : if (EXPR_SPEC (cur_expr) > EXPR_SPEC (min_spec_expr))
4233 : break;
4234 :
4235 8284 : ++privileged_n;
4236 : }
4237 :
4238 4928 : if (i == ready.n_ready)
4239 4869 : privileged_n = 0;
4240 :
4241 4928 : if (sched_verbose >= 2)
4242 0 : sel_print ("privileged_n: %d insns with SPEC %d\n",
4243 : privileged_n, privileged_n ? EXPR_SPEC (min_spec_expr) : -1);
4244 4928 : return privileged_n;
4245 : }
4246 :
4247 : /* Call the rest of the hooks after the choice was made. Return
4248 : the number of insns that still can be issued given that the current
4249 : number is ISSUE_MORE. FENCE and BEST_INSN are the current fence
4250 : and the insn chosen for scheduling, respectively. */
4251 : static int
4252 4901 : invoke_aftermath_hooks (fence_t fence, rtx_insn *best_insn, int issue_more)
4253 : {
4254 4901 : gcc_assert (INSN_P (best_insn));
4255 :
4256 : /* First, call dfa_new_cycle, and then variable_issue, if available. */
4257 4901 : sel_dfa_new_cycle (best_insn, fence);
4258 :
4259 4901 : if (targetm.sched.variable_issue)
4260 : {
4261 0 : memcpy (curr_state, FENCE_STATE (fence), dfa_state_size);
4262 0 : issue_more =
4263 0 : targetm.sched.variable_issue (sched_dump, sched_verbose, best_insn,
4264 : issue_more);
4265 0 : memcpy (FENCE_STATE (fence), curr_state, dfa_state_size);
4266 : }
4267 4901 : else if (!DEBUG_INSN_P (best_insn)
4268 4857 : && GET_CODE (PATTERN (best_insn)) != USE
4269 9713 : && GET_CODE (PATTERN (best_insn)) != CLOBBER)
4270 4802 : issue_more--;
4271 :
4272 4901 : return issue_more;
4273 : }
4274 :
4275 : /* Estimate the cost of issuing INSN on DFA state STATE. */
4276 : static int
4277 3192 : estimate_insn_cost (rtx_insn *insn, state_t state)
4278 : {
4279 3192 : static state_t temp = NULL;
4280 3192 : int cost;
4281 :
4282 3192 : if (!temp)
4283 54 : temp = xmalloc (dfa_state_size);
4284 :
4285 3192 : memcpy (temp, state, dfa_state_size);
4286 3192 : cost = state_transition (temp, insn);
4287 :
4288 3192 : if (cost < 0)
4289 : return 0;
4290 461 : else if (cost == 0)
4291 0 : return 1;
4292 : return cost;
4293 : }
4294 :
4295 : /* Return the cost of issuing EXPR on the FENCE as estimated by DFA.
4296 : This function properly handles ASMs, USEs etc. */
4297 : static int
4298 1580 : get_expr_cost (expr_t expr, fence_t fence)
4299 : {
4300 1580 : rtx_insn *insn = EXPR_INSN_RTX (expr);
4301 :
4302 1580 : if (recog_memoized (insn) < 0)
4303 : {
4304 0 : if (!FENCE_STARTS_CYCLE_P (fence)
4305 0 : && INSN_ASM_P (insn))
4306 : /* This is asm insn which is tryed to be issued on the
4307 : cycle not first. Issue it on the next cycle. */
4308 : return 1;
4309 : else
4310 : /* A USE insn, or something else we don't need to
4311 : understand. We can't pass these directly to
4312 : state_transition because it will trigger a
4313 : fatal error for unrecognizable insns. */
4314 0 : return 0;
4315 : }
4316 : else
4317 1580 : return estimate_insn_cost (insn, FENCE_STATE (fence));
4318 : }
4319 :
4320 : /* Find the best insn for scheduling, either via max_issue or just take
4321 : the most prioritized available. */
4322 : static int
4323 4928 : choose_best_insn (fence_t fence, int privileged_n, int *index)
4324 : {
4325 4928 : int can_issue = 0;
4326 :
4327 4928 : if (dfa_lookahead > 0)
4328 : {
4329 3517 : cycle_issued_insns = FENCE_ISSUED_INSNS (fence);
4330 : /* TODO: pass equivalent of first_cycle_insn_p to max_issue (). */
4331 3517 : can_issue = max_issue (&ready, privileged_n,
4332 : FENCE_STATE (fence), true, index);
4333 3517 : if (sched_verbose >= 2)
4334 0 : sel_print ("max_issue: we can issue %d insns, already did %d insns\n",
4335 : can_issue, FENCE_ISSUED_INSNS (fence));
4336 : }
4337 : else
4338 : {
4339 : /* We can't use max_issue; just return the first available element. */
4340 : int i;
4341 :
4342 1672 : for (i = 0; i < ready.n_ready; i++)
4343 : {
4344 1580 : expr_t expr = find_expr_for_ready (i, true);
4345 :
4346 1580 : if (get_expr_cost (expr, fence) < 1)
4347 : {
4348 1319 : can_issue = can_issue_more;
4349 1319 : *index = i;
4350 :
4351 1319 : if (sched_verbose >= 2)
4352 0 : sel_print ("using %dth insn from the ready list\n", i + 1);
4353 :
4354 : break;
4355 : }
4356 : }
4357 :
4358 1411 : if (i == ready.n_ready)
4359 : {
4360 92 : can_issue = 0;
4361 92 : *index = -1;
4362 : }
4363 : }
4364 :
4365 4928 : return can_issue;
4366 : }
4367 :
4368 : /* Choose the best expr from *AV_VLIW_PTR and a suitable register for it.
4369 : BNDS and FENCE are current boundaries and scheduling fence respectively.
4370 : Return the expr found and NULL if nothing can be issued atm.
4371 : Write to PNEED_STALL the number of cycles to stall if no expr was found. */
4372 : static expr_t
4373 7728 : find_best_expr (av_set_t *av_vliw_ptr, blist_t bnds, fence_t fence,
4374 : int *pneed_stall)
4375 : {
4376 7728 : expr_t best;
4377 :
4378 : /* Choose the best insn for scheduling via:
4379 : 1) sorting the ready list based on priority;
4380 : 2) calling the reorder hook;
4381 : 3) calling max_issue. */
4382 7728 : best = fill_ready_list (av_vliw_ptr, bnds, fence, pneed_stall);
4383 7728 : if (best == NULL && ready.n_ready > 0)
4384 : {
4385 5994 : int privileged_n, index;
4386 :
4387 5994 : can_issue_more = invoke_reorder_hooks (fence);
4388 5994 : if (can_issue_more > 0)
4389 : {
4390 : /* Try choosing the best insn until we find one that is could be
4391 : scheduled due to liveness restrictions on its destination register.
4392 : In the future, we'd like to choose once and then just probe insns
4393 : in the order of their priority. */
4394 4928 : invoke_dfa_lookahead_guard ();
4395 4928 : privileged_n = calculate_privileged_insns ();
4396 4928 : can_issue_more = choose_best_insn (fence, privileged_n, &index);
4397 4928 : if (can_issue_more)
4398 4792 : best = find_expr_for_ready (index, true);
4399 : }
4400 : /* We had some available insns, so if we can't issue them,
4401 : we have a stall. */
4402 5994 : if (can_issue_more == 0)
4403 : {
4404 1202 : best = NULL;
4405 1202 : *pneed_stall = 1;
4406 : }
4407 : }
4408 :
4409 7619 : if (best != NULL)
4410 : {
4411 4901 : can_issue_more = invoke_aftermath_hooks (fence, EXPR_INSN_RTX (best),
4412 : can_issue_more);
4413 4901 : if (targetm.sched.variable_issue
4414 0 : && can_issue_more == 0)
4415 0 : *pneed_stall = 1;
4416 : }
4417 :
4418 7728 : if (sched_verbose >= 2)
4419 : {
4420 0 : if (best != NULL)
4421 : {
4422 0 : sel_print ("Best expression (vliw form): ");
4423 0 : dump_expr (best);
4424 0 : sel_print ("; cycle %d\n", FENCE_CYCLE (fence));
4425 : }
4426 : else
4427 0 : sel_print ("No best expr found!\n");
4428 : }
4429 :
4430 7728 : return best;
4431 : }
4432 :
4433 :
4434 : /* Functions that implement the core of the scheduler. */
4435 :
4436 :
4437 : /* Emit an instruction from EXPR with SEQNO and VINSN after
4438 : PLACE_TO_INSERT. */
4439 : static insn_t
4440 419 : emit_insn_from_expr_after (expr_t expr, vinsn_t vinsn, int seqno,
4441 : insn_t place_to_insert)
4442 : {
4443 : /* This assert fails when we have identical instructions
4444 : one of which dominates the other. In this case move_op ()
4445 : finds the first instruction and doesn't search for second one.
4446 : The solution would be to compute av_set after the first found
4447 : insn and, if insn present in that set, continue searching.
4448 : For now we workaround this issue in move_op. */
4449 419 : gcc_assert (!INSN_IN_STREAM_P (EXPR_INSN_RTX (expr)));
4450 :
4451 419 : if (EXPR_WAS_RENAMED (expr))
4452 : {
4453 32 : unsigned regno = expr_dest_regno (expr);
4454 :
4455 32 : if (HARD_REGISTER_NUM_P (regno))
4456 : {
4457 18 : df_set_regs_ever_live (regno, true);
4458 18 : reg_rename_tick[regno] = ++reg_rename_this_tick;
4459 : }
4460 : }
4461 :
4462 419 : return sel_gen_insn_from_expr_after (expr, vinsn, seqno,
4463 419 : place_to_insert);
4464 : }
4465 :
4466 : /* Return TRUE if BB can hold bookkeeping code. */
4467 : static bool
4468 400 : block_valid_for_bookkeeping_p (basic_block bb)
4469 : {
4470 400 : insn_t bb_end = BB_END (bb);
4471 :
4472 400 : if (!in_current_region_p (bb) || EDGE_COUNT (bb->succs) > 1)
4473 : return false;
4474 :
4475 362 : if (INSN_P (bb_end))
4476 : {
4477 353 : if (INSN_SCHED_TIMES (bb_end) > 0)
4478 30 : return false;
4479 : }
4480 : else
4481 9 : gcc_assert (NOTE_INSN_BASIC_BLOCK_P (bb_end));
4482 :
4483 : return true;
4484 : }
4485 :
4486 : /* Attempt to find a block that can hold bookkeeping code for path(s) incoming
4487 : into E2->dest, except from E1->src (there may be a sequence of empty basic
4488 : blocks between E1->src and E2->dest). Return found block, or NULL if new
4489 : one must be created. If LAX holds, don't assume there is a simple path
4490 : from E1->src to E2->dest. */
4491 : static basic_block
4492 434 : find_block_for_bookkeeping (edge e1, edge e2, bool lax)
4493 : {
4494 434 : basic_block candidate_block = NULL;
4495 434 : edge e;
4496 :
4497 : /* Loop over edges from E1 to E2, inclusive. */
4498 444 : for (e = e1; !lax || e->dest != EXIT_BLOCK_PTR_FOR_FN (cfun); e =
4499 10 : EDGE_SUCC (e->dest, 0))
4500 : {
4501 444 : if (EDGE_COUNT (e->dest->preds) == 2)
4502 : {
4503 415 : if (candidate_block == NULL)
4504 592 : candidate_block = (EDGE_PRED (e->dest, 0) == e
4505 415 : ? EDGE_PRED (e->dest, 1)->src
4506 : : EDGE_PRED (e->dest, 0)->src);
4507 : else
4508 : /* Found additional edge leading to path from e1 to e2
4509 : from aside. */
4510 : return NULL;
4511 : }
4512 29 : else if (EDGE_COUNT (e->dest->preds) > 2)
4513 : /* Several edges leading to path from e1 to e2 from aside. */
4514 : return NULL;
4515 :
4516 431 : if (e == e2)
4517 400 : return ((!lax || candidate_block)
4518 400 : && block_valid_for_bookkeeping_p (candidate_block)
4519 400 : ? candidate_block
4520 : : NULL);
4521 :
4522 112 : if (lax && EDGE_COUNT (e->dest->succs) != 1)
4523 : return NULL;
4524 : }
4525 :
4526 : if (lax)
4527 : return NULL;
4528 :
4529 : gcc_unreachable ();
4530 : }
4531 :
4532 : /* Create new basic block for bookkeeping code for path(s) incoming into
4533 : E2->dest, except from E1->src. Return created block. */
4534 : static basic_block
4535 67 : create_block_for_bookkeeping (edge e1, edge e2)
4536 : {
4537 67 : basic_block new_bb, bb = e2->dest;
4538 :
4539 : /* Check that we don't spoil the loop structure. */
4540 67 : if (current_loop_nest)
4541 : {
4542 60 : basic_block latch = current_loop_nest->latch;
4543 :
4544 : /* We do not split header. */
4545 60 : gcc_assert (e2->dest != current_loop_nest->header);
4546 :
4547 : /* We do not redirect the only edge to the latch block. */
4548 74 : gcc_assert (e1->dest != latch
4549 : || !single_pred_p (latch)
4550 : || e1 != single_pred_edge (latch));
4551 : }
4552 :
4553 : /* Split BB to insert BOOK_INSN there. */
4554 67 : new_bb = sched_split_block (bb, NULL);
4555 :
4556 : /* Move note_list from the upper bb. */
4557 67 : gcc_assert (BB_NOTE_LIST (new_bb) == NULL_RTX);
4558 67 : BB_NOTE_LIST (new_bb) = BB_NOTE_LIST (bb);
4559 67 : BB_NOTE_LIST (bb) = NULL;
4560 :
4561 67 : gcc_assert (e2->dest == bb);
4562 :
4563 : /* Skip block for bookkeeping copy when leaving E1->src. */
4564 67 : if (e1->flags & EDGE_FALLTHRU)
4565 16 : sel_redirect_edge_and_branch_force (e1, new_bb);
4566 : else
4567 51 : sel_redirect_edge_and_branch (e1, new_bb);
4568 :
4569 67 : gcc_assert (e1->dest == new_bb);
4570 67 : gcc_assert (sel_bb_empty_p (bb));
4571 :
4572 : /* To keep basic block numbers in sync between debug and non-debug
4573 : compilations, we have to rotate blocks here. Consider that we
4574 : started from (a,b)->d, (c,d)->e, and d contained only debug
4575 : insns. It would have been removed before if the debug insns
4576 : weren't there, so we'd have split e rather than d. So what we do
4577 : now is to swap the block numbers of new_bb and
4578 : single_succ(new_bb) == e, so that the insns that were in e before
4579 : get the new block number. */
4580 :
4581 67 : if (MAY_HAVE_DEBUG_INSNS)
4582 : {
4583 0 : basic_block succ;
4584 0 : insn_t insn = sel_bb_head (new_bb);
4585 0 : insn_t last;
4586 :
4587 0 : if (DEBUG_INSN_P (insn)
4588 0 : && single_succ_p (new_bb)
4589 0 : && (succ = single_succ (new_bb))
4590 0 : && succ != EXIT_BLOCK_PTR_FOR_FN (cfun)
4591 0 : && DEBUG_INSN_P ((last = sel_bb_end (new_bb))))
4592 : {
4593 0 : while (insn != last && (DEBUG_INSN_P (insn) || NOTE_P (insn)))
4594 0 : insn = NEXT_INSN (insn);
4595 :
4596 0 : if (insn == last)
4597 : {
4598 0 : sel_global_bb_info_def gbi;
4599 0 : sel_region_bb_info_def rbi;
4600 :
4601 0 : if (sched_verbose >= 2)
4602 0 : sel_print ("Swapping block ids %i and %i\n",
4603 : new_bb->index, succ->index);
4604 :
4605 0 : std::swap (new_bb->index, succ->index);
4606 :
4607 0 : SET_BASIC_BLOCK_FOR_FN (cfun, new_bb->index, new_bb);
4608 0 : SET_BASIC_BLOCK_FOR_FN (cfun, succ->index, succ);
4609 :
4610 0 : memcpy (&gbi, SEL_GLOBAL_BB_INFO (new_bb), sizeof (gbi));
4611 0 : memcpy (SEL_GLOBAL_BB_INFO (new_bb), SEL_GLOBAL_BB_INFO (succ),
4612 : sizeof (gbi));
4613 0 : memcpy (SEL_GLOBAL_BB_INFO (succ), &gbi, sizeof (gbi));
4614 :
4615 0 : memcpy (&rbi, SEL_REGION_BB_INFO (new_bb), sizeof (rbi));
4616 0 : memcpy (SEL_REGION_BB_INFO (new_bb), SEL_REGION_BB_INFO (succ),
4617 : sizeof (rbi));
4618 0 : memcpy (SEL_REGION_BB_INFO (succ), &rbi, sizeof (rbi));
4619 :
4620 0 : std::swap (BLOCK_TO_BB (new_bb->index),
4621 0 : BLOCK_TO_BB (succ->index));
4622 :
4623 0 : std::swap (CONTAINING_RGN (new_bb->index),
4624 0 : CONTAINING_RGN (succ->index));
4625 :
4626 0 : for (int i = 0; i < current_nr_blocks; i++)
4627 0 : if (BB_TO_BLOCK (i) == succ->index)
4628 0 : BB_TO_BLOCK (i) = new_bb->index;
4629 0 : else if (BB_TO_BLOCK (i) == new_bb->index)
4630 0 : BB_TO_BLOCK (i) = succ->index;
4631 :
4632 0 : FOR_BB_INSNS (new_bb, insn)
4633 0 : if (INSN_P (insn))
4634 0 : EXPR_ORIG_BB_INDEX (INSN_EXPR (insn)) = new_bb->index;
4635 :
4636 0 : FOR_BB_INSNS (succ, insn)
4637 0 : if (INSN_P (insn))
4638 0 : EXPR_ORIG_BB_INDEX (INSN_EXPR (insn)) = succ->index;
4639 :
4640 0 : if (bitmap_clear_bit (code_motion_visited_blocks, new_bb->index))
4641 0 : bitmap_set_bit (code_motion_visited_blocks, succ->index);
4642 :
4643 0 : gcc_assert (LABEL_P (BB_HEAD (new_bb))
4644 : && LABEL_P (BB_HEAD (succ)));
4645 :
4646 0 : if (sched_verbose >= 4)
4647 0 : sel_print ("Swapping code labels %i and %i\n",
4648 : CODE_LABEL_NUMBER (BB_HEAD (new_bb)),
4649 : CODE_LABEL_NUMBER (BB_HEAD (succ)));
4650 :
4651 0 : std::swap (CODE_LABEL_NUMBER (BB_HEAD (new_bb)),
4652 0 : CODE_LABEL_NUMBER (BB_HEAD (succ)));
4653 : }
4654 : }
4655 : }
4656 :
4657 67 : return bb;
4658 : }
4659 :
4660 : /* Return insn after which we must insert bookkeeping code for path(s) incoming
4661 : into E2->dest, except from E1->src. If the returned insn immediately
4662 : precedes a fence, assign that fence to *FENCE_TO_REWIND. */
4663 : static insn_t
4664 389 : find_place_for_bookkeeping (edge e1, edge e2, fence_t *fence_to_rewind)
4665 : {
4666 389 : insn_t place_to_insert;
4667 : /* Find a basic block that can hold bookkeeping. If it can be found, do not
4668 : create new basic block, but insert bookkeeping there. */
4669 389 : basic_block book_block = find_block_for_bookkeeping (e1, e2, false);
4670 :
4671 389 : if (book_block)
4672 : {
4673 322 : place_to_insert = BB_END (book_block);
4674 :
4675 : /* Don't use a block containing only debug insns for
4676 : bookkeeping, this causes scheduling differences between debug
4677 : and non-debug compilations, for the block would have been
4678 : removed already. */
4679 322 : if (DEBUG_INSN_P (place_to_insert))
4680 : {
4681 2 : rtx_insn *insn = sel_bb_head (book_block);
4682 :
4683 4 : while (insn != place_to_insert &&
4684 2 : (DEBUG_INSN_P (insn) || NOTE_P (insn)))
4685 0 : insn = NEXT_INSN (insn);
4686 :
4687 2 : if (insn == place_to_insert)
4688 : book_block = NULL;
4689 : }
4690 : }
4691 :
4692 : if (!book_block)
4693 : {
4694 67 : book_block = create_block_for_bookkeeping (e1, e2);
4695 67 : place_to_insert = BB_END (book_block);
4696 67 : if (sched_verbose >= 9)
4697 0 : sel_print ("New block is %i, split from bookkeeping block %i\n",
4698 0 : EDGE_SUCC (book_block, 0)->dest->index, book_block->index);
4699 : }
4700 : else
4701 : {
4702 322 : if (sched_verbose >= 9)
4703 0 : sel_print ("Pre-existing bookkeeping block is %i\n", book_block->index);
4704 : }
4705 :
4706 389 : *fence_to_rewind = NULL;
4707 : /* If basic block ends with a jump, insert bookkeeping code right before it.
4708 : Notice if we are crossing a fence when taking PREV_INSN. */
4709 389 : if (INSN_P (place_to_insert) && control_flow_insn_p (place_to_insert))
4710 : {
4711 8 : *fence_to_rewind = flist_lookup (fences, place_to_insert);
4712 8 : place_to_insert = PREV_INSN (place_to_insert);
4713 : }
4714 :
4715 389 : return place_to_insert;
4716 : }
4717 :
4718 : /* Find a proper seqno for bookkeeing insn inserted at PLACE_TO_INSERT
4719 : for JOIN_POINT. */
4720 : static int
4721 389 : find_seqno_for_bookkeeping (insn_t place_to_insert, insn_t join_point)
4722 : {
4723 389 : int seqno;
4724 :
4725 : /* Check if we are about to insert bookkeeping copy before a jump, and use
4726 : jump's seqno for the copy; otherwise, use JOIN_POINT's seqno. */
4727 389 : rtx_insn *next = NEXT_INSN (place_to_insert);
4728 389 : if (INSN_P (next)
4729 : && JUMP_P (next)
4730 389 : && BLOCK_FOR_INSN (next) == BLOCK_FOR_INSN (place_to_insert))
4731 : {
4732 8 : gcc_assert (INSN_SCHED_TIMES (next) == 0);
4733 8 : seqno = INSN_SEQNO (next);
4734 : }
4735 381 : else if (INSN_SEQNO (join_point) > 0)
4736 : seqno = INSN_SEQNO (join_point);
4737 : else
4738 : {
4739 0 : seqno = get_seqno_by_preds (place_to_insert);
4740 :
4741 : /* Sometimes the fences can move in such a way that there will be
4742 : no instructions with positive seqno around this bookkeeping.
4743 : This means that there will be no way to get to it by a regular
4744 : fence movement. Never mind because we pick up such pieces for
4745 : rescheduling anyways, so any positive value will do for now. */
4746 0 : if (seqno < 0)
4747 : {
4748 0 : gcc_assert (pipelining_p);
4749 : seqno = 1;
4750 : }
4751 : }
4752 :
4753 389 : gcc_assert (seqno > 0);
4754 389 : return seqno;
4755 : }
4756 :
4757 : /* Insert bookkeeping copy of C_EXPS's insn after PLACE_TO_INSERT, assigning
4758 : NEW_SEQNO to it. Return created insn. */
4759 : static insn_t
4760 389 : emit_bookkeeping_insn (insn_t place_to_insert, expr_t c_expr, int new_seqno)
4761 : {
4762 389 : rtx_insn *new_insn_rtx = create_copy_of_insn_rtx (EXPR_INSN_RTX (c_expr));
4763 :
4764 389 : vinsn_t new_vinsn
4765 778 : = create_vinsn_from_insn_rtx (new_insn_rtx,
4766 389 : VINSN_UNIQUE_P (EXPR_VINSN (c_expr)));
4767 :
4768 389 : insn_t new_insn = emit_insn_from_expr_after (c_expr, new_vinsn, new_seqno,
4769 : place_to_insert);
4770 :
4771 389 : INSN_SCHED_TIMES (new_insn) = 0;
4772 389 : bitmap_set_bit (current_copies, INSN_UID (new_insn));
4773 :
4774 389 : return new_insn;
4775 : }
4776 :
4777 : /* Generate a bookkeeping copy of C_EXPR's insn for path(s) incoming into to
4778 : E2->dest, except from E1->src (there may be a sequence of empty blocks
4779 : between E1->src and E2->dest). Return block containing the copy.
4780 : All scheduler data is initialized for the newly created insn. */
4781 : static basic_block
4782 389 : generate_bookkeeping_insn (expr_t c_expr, edge e1, edge e2)
4783 : {
4784 389 : insn_t join_point, place_to_insert, new_insn;
4785 389 : int new_seqno;
4786 389 : bool need_to_exchange_data_sets;
4787 389 : fence_t fence_to_rewind;
4788 :
4789 389 : if (sched_verbose >= 4)
4790 0 : sel_print ("Generating bookkeeping insn (%d->%d)\n", e1->src->index,
4791 0 : e2->dest->index);
4792 :
4793 389 : join_point = sel_bb_head (e2->dest);
4794 389 : place_to_insert = find_place_for_bookkeeping (e1, e2, &fence_to_rewind);
4795 389 : new_seqno = find_seqno_for_bookkeeping (place_to_insert, join_point);
4796 389 : need_to_exchange_data_sets
4797 389 : = sel_bb_empty_p (BLOCK_FOR_INSN (place_to_insert));
4798 :
4799 389 : new_insn = emit_bookkeeping_insn (place_to_insert, c_expr, new_seqno);
4800 :
4801 389 : if (fence_to_rewind)
4802 0 : FENCE_INSN (fence_to_rewind) = new_insn;
4803 :
4804 : /* When inserting bookkeeping insn in new block, av sets should be
4805 : following: old basic block (that now holds bookkeeping) data sets are
4806 : the same as was before generation of bookkeeping, and new basic block
4807 : (that now hold all other insns of old basic block) data sets are
4808 : invalid. So exchange data sets for these basic blocks as sel_split_block
4809 : mistakenly exchanges them in this case. Cannot do it earlier because
4810 : when single instruction is added to new basic block it should hold NULL
4811 : lv_set. */
4812 389 : if (need_to_exchange_data_sets)
4813 76 : exchange_data_sets (BLOCK_FOR_INSN (new_insn),
4814 76 : BLOCK_FOR_INSN (join_point));
4815 :
4816 389 : stat_bookkeeping_copies++;
4817 389 : return BLOCK_FOR_INSN (new_insn);
4818 : }
4819 :
4820 : /* Remove from AV_PTR all insns that may need bookkeeping when scheduling
4821 : on FENCE, but we are unable to copy them. */
4822 : static void
4823 5189 : remove_insns_that_need_bookkeeping (fence_t fence, av_set_t *av_ptr)
4824 : {
4825 5189 : expr_t expr;
4826 5189 : av_set_iterator i;
4827 :
4828 : /* An expression does not need bookkeeping if it is available on all paths
4829 : from current block to original block and current block dominates
4830 : original block. We check availability on all paths by examining
4831 : EXPR_SPEC; this is not equivalent, because it may be positive even
4832 : if expr is available on all paths (but if expr is not available on
4833 : any path, EXPR_SPEC will be positive). */
4834 :
4835 30569 : FOR_EACH_EXPR_1 (expr, i, av_ptr)
4836 : {
4837 12690 : if (!control_flow_insn_p (EXPR_INSN_RTX (expr))
4838 11806 : && (!bookkeeping_p || VINSN_UNIQUE_P (EXPR_VINSN (expr)))
4839 14555 : && (EXPR_SPEC (expr)
4840 1848 : || !EXPR_ORIG_BB_INDEX (expr)
4841 1848 : || !dominated_by_p (CDI_DOMINATORS,
4842 1848 : BASIC_BLOCK_FOR_FN (cfun,
4843 : EXPR_ORIG_BB_INDEX (expr)),
4844 1848 : BLOCK_FOR_INSN (FENCE_INSN (fence)))))
4845 : {
4846 25 : if (sched_verbose >= 4)
4847 0 : sel_print ("Expr %d removed because it would need bookkeeping, which "
4848 0 : "cannot be created\n", INSN_UID (EXPR_INSN_RTX (expr)));
4849 25 : av_set_iter_remove (&i);
4850 : }
4851 : }
4852 5189 : }
4853 :
4854 : /* Moving conditional jump through some instructions.
4855 :
4856 : Consider example:
4857 :
4858 : ... <- current scheduling point
4859 : NOTE BASIC BLOCK: <- bb header
4860 : (p8) add r14=r14+0x9;;
4861 : (p8) mov [r14]=r23
4862 : (!p8) jump L1;;
4863 : NOTE BASIC BLOCK:
4864 : ...
4865 :
4866 : We can schedule jump one cycle earlier, than mov, because they cannot be
4867 : executed together as their predicates are mutually exclusive.
4868 :
4869 : This is done in this way: first, new fallthrough basic block is created
4870 : after jump (it is always can be done, because there already should be a
4871 : fallthrough block, where control flow goes in case of predicate being true -
4872 : in our example; otherwise there should be a dependence between those
4873 : instructions and jump and we cannot schedule jump right now);
4874 : next, all instructions between jump and current scheduling point are moved
4875 : to this new block. And the result is this:
4876 :
4877 : NOTE BASIC BLOCK:
4878 : (!p8) jump L1 <- current scheduling point
4879 : NOTE BASIC BLOCK: <- bb header
4880 : (p8) add r14=r14+0x9;;
4881 : (p8) mov [r14]=r23
4882 : NOTE BASIC BLOCK:
4883 : ...
4884 : */
4885 : static void
4886 0 : move_cond_jump (rtx_insn *insn, bnd_t bnd)
4887 : {
4888 0 : edge ft_edge;
4889 0 : basic_block block_from, block_next, block_new, block_bnd, bb;
4890 0 : rtx_insn *next, *prev, *link, *head;
4891 :
4892 0 : block_from = BLOCK_FOR_INSN (insn);
4893 0 : block_bnd = BLOCK_FOR_INSN (BND_TO (bnd));
4894 0 : prev = BND_TO (bnd);
4895 :
4896 : /* Moving of jump should not cross any other jumps or beginnings of new
4897 : basic blocks. The only exception is when we move a jump through
4898 : mutually exclusive insns along fallthru edges. */
4899 0 : if (flag_checking && block_from != block_bnd)
4900 : {
4901 0 : bb = block_from;
4902 0 : for (link = PREV_INSN (insn); link != PREV_INSN (prev);
4903 0 : link = PREV_INSN (link))
4904 : {
4905 0 : if (INSN_P (link))
4906 0 : gcc_assert (sched_insns_conditions_mutex_p (insn, link));
4907 0 : if (BLOCK_FOR_INSN (link) && BLOCK_FOR_INSN (link) != bb)
4908 : {
4909 0 : gcc_assert (single_pred (bb) == BLOCK_FOR_INSN (link));
4910 : bb = BLOCK_FOR_INSN (link);
4911 : }
4912 : }
4913 : }
4914 :
4915 : /* Jump is moved to the boundary. */
4916 0 : next = PREV_INSN (insn);
4917 0 : BND_TO (bnd) = insn;
4918 :
4919 0 : ft_edge = find_fallthru_edge_from (block_from);
4920 0 : block_next = ft_edge->dest;
4921 : /* There must be a fallthrough block (or where should go
4922 : control flow in case of false jump predicate otherwise?). */
4923 0 : gcc_assert (block_next);
4924 :
4925 : /* Create new empty basic block after source block. */
4926 0 : block_new = sel_split_edge (ft_edge);
4927 0 : gcc_assert (block_new->next_bb == block_next
4928 : && block_from->next_bb == block_new);
4929 :
4930 : /* Move all instructions except INSN to BLOCK_NEW. */
4931 0 : bb = block_bnd;
4932 0 : head = BB_HEAD (block_new);
4933 0 : while (bb != block_from->next_bb)
4934 : {
4935 0 : rtx_insn *from, *to;
4936 0 : from = bb == block_bnd ? prev : sel_bb_head (bb);
4937 0 : to = bb == block_from ? next : sel_bb_end (bb);
4938 :
4939 : /* The jump being moved can be the first insn in the block.
4940 : In this case we don't have to move anything in this block. */
4941 0 : if (NEXT_INSN (to) != from)
4942 : {
4943 0 : reorder_insns (from, to, head);
4944 :
4945 0 : for (link = to; link != head; link = PREV_INSN (link))
4946 0 : EXPR_ORIG_BB_INDEX (INSN_EXPR (link)) = block_new->index;
4947 : head = to;
4948 : }
4949 :
4950 : /* Cleanup possibly empty blocks left. */
4951 0 : block_next = bb->next_bb;
4952 0 : if (bb != block_from)
4953 0 : tidy_control_flow (bb, false);
4954 : bb = block_next;
4955 : }
4956 :
4957 : /* Assert there is no jump to BLOCK_NEW, only fallthrough edge. */
4958 0 : gcc_assert (NOTE_INSN_BASIC_BLOCK_P (BB_HEAD (block_new)));
4959 :
4960 0 : gcc_assert (!sel_bb_empty_p (block_from)
4961 : && !sel_bb_empty_p (block_new));
4962 :
4963 : /* Update data sets for BLOCK_NEW to represent that INSN and
4964 : instructions from the other branch of INSN is no longer
4965 : available at BLOCK_NEW. */
4966 0 : BB_AV_LEVEL (block_new) = global_level;
4967 0 : gcc_assert (BB_LV_SET (block_new) == NULL);
4968 0 : BB_LV_SET (block_new) = get_clear_regset_from_pool ();
4969 0 : update_data_sets (sel_bb_head (block_new));
4970 :
4971 : /* INSN is a new basic block header - so prepare its data
4972 : structures and update availability and liveness sets. */
4973 0 : update_data_sets (insn);
4974 :
4975 0 : if (sched_verbose >= 4)
4976 0 : sel_print ("Moving jump %d\n", INSN_UID (insn));
4977 0 : }
4978 :
4979 : /* Remove nops generated during move_op for preventing removal of empty
4980 : basic blocks. */
4981 : static void
4982 4901 : remove_temp_moveop_nops (bool full_tidying)
4983 : {
4984 4901 : int i;
4985 4901 : insn_t insn;
4986 :
4987 5241 : FOR_EACH_VEC_ELT (vec_temp_moveop_nops, i, insn)
4988 : {
4989 340 : gcc_assert (INSN_NOP_P (insn));
4990 340 : return_nop_to_pool (insn, full_tidying);
4991 : }
4992 :
4993 : /* Empty the vector. */
4994 4901 : if (vec_temp_moveop_nops.length () > 0)
4995 332 : vec_temp_moveop_nops.block_remove (0, vec_temp_moveop_nops.length ());
4996 4901 : }
4997 :
4998 : /* Records the maximal UID before moving up an instruction. Used for
4999 : distinguishing between bookkeeping copies and original insns. */
5000 : static int max_uid_before_move_op = 0;
5001 :
5002 : /* When true, we're always scheduling next insn on the already scheduled code
5003 : to get the right insn data for the following bundling or other passes. */
5004 : static int force_next_insn = 0;
5005 :
5006 : /* Remove from AV_VLIW_P all instructions but next when debug counter
5007 : tells us so. Next instruction is fetched from BNDS. */
5008 : static void
5009 5189 : remove_insns_for_debug (blist_t bnds, av_set_t *av_vliw_p)
5010 : {
5011 5189 : if (! dbg_cnt (sel_sched_insn_cnt) || force_next_insn)
5012 : /* Leave only the next insn in av_vliw. */
5013 : {
5014 0 : av_set_iterator av_it;
5015 0 : expr_t expr;
5016 0 : bnd_t bnd = BLIST_BND (bnds);
5017 0 : insn_t next = BND_TO (bnd);
5018 :
5019 0 : gcc_assert (BLIST_NEXT (bnds) == NULL);
5020 :
5021 0 : FOR_EACH_EXPR_1 (expr, av_it, av_vliw_p)
5022 0 : if (EXPR_INSN_RTX (expr) != next)
5023 0 : av_set_iter_remove (&av_it);
5024 : }
5025 5189 : }
5026 :
5027 : /* Compute available instructions on BNDS. FENCE is the current fence. Write
5028 : the computed set to *AV_VLIW_P. */
5029 : static void
5030 5189 : compute_av_set_on_boundaries (fence_t fence, blist_t bnds, av_set_t *av_vliw_p)
5031 : {
5032 5189 : if (sched_verbose >= 2)
5033 : {
5034 0 : sel_print ("Boundaries: ");
5035 0 : dump_blist (bnds);
5036 0 : sel_print ("\n");
5037 : }
5038 :
5039 10378 : for (; bnds; bnds = BLIST_NEXT (bnds))
5040 : {
5041 5189 : bnd_t bnd = BLIST_BND (bnds);
5042 5189 : av_set_t av1_copy;
5043 5189 : insn_t bnd_to = BND_TO (bnd);
5044 :
5045 : /* Rewind BND->TO to the basic block header in case some bookkeeping
5046 : instructions were inserted before BND->TO and it needs to be
5047 : adjusted. */
5048 5189 : if (sel_bb_head_p (bnd_to))
5049 1051 : gcc_assert (INSN_SCHED_TIMES (bnd_to) == 0);
5050 : else
5051 4138 : while (INSN_SCHED_TIMES (PREV_INSN (bnd_to)) == 0)
5052 : {
5053 0 : bnd_to = PREV_INSN (bnd_to);
5054 0 : if (sel_bb_head_p (bnd_to))
5055 : break;
5056 : }
5057 :
5058 5189 : if (BND_TO (bnd) != bnd_to)
5059 : {
5060 0 : gcc_assert (FENCE_INSN (fence) == BND_TO (bnd));
5061 0 : FENCE_INSN (fence) = bnd_to;
5062 0 : BND_TO (bnd) = bnd_to;
5063 : }
5064 :
5065 5189 : av_set_clear (&BND_AV (bnd));
5066 5189 : BND_AV (bnd) = compute_av_set (BND_TO (bnd), NULL, 0, true);
5067 :
5068 5189 : av_set_clear (&BND_AV1 (bnd));
5069 5189 : BND_AV1 (bnd) = av_set_copy (BND_AV (bnd));
5070 :
5071 5189 : moveup_set_inside_insn_group (&BND_AV1 (bnd), NULL);
5072 :
5073 5189 : av1_copy = av_set_copy (BND_AV1 (bnd));
5074 5189 : av_set_union_and_clear (av_vliw_p, &av1_copy, NULL);
5075 : }
5076 :
5077 5189 : if (sched_verbose >= 2)
5078 : {
5079 0 : sel_print ("Available exprs (vliw form): ");
5080 0 : dump_av_set (*av_vliw_p);
5081 0 : sel_print ("\n");
5082 : }
5083 5189 : }
5084 :
5085 : /* Calculate the sequential av set on BND corresponding to the EXPR_VLIW
5086 : expression. When FOR_MOVEOP is true, also replace the register of
5087 : expressions found with the register from EXPR_VLIW. */
5088 : static av_set_t
5089 7691 : find_sequential_best_exprs (bnd_t bnd, expr_t expr_vliw, bool for_moveop)
5090 : {
5091 7691 : av_set_t expr_seq = NULL;
5092 7691 : expr_t expr;
5093 7691 : av_set_iterator i;
5094 :
5095 17841 : FOR_EACH_EXPR (expr, i, BND_AV (bnd))
5096 : {
5097 17841 : if (equal_after_moveup_path_p (expr, NULL, expr_vliw))
5098 : {
5099 7691 : if (for_moveop)
5100 : {
5101 : /* The sequential expression has the right form to pass
5102 : to move_op except when renaming happened. Put the
5103 : correct register in EXPR then. */
5104 4901 : if (EXPR_SEPARABLE_P (expr) && REG_P (EXPR_LHS (expr)))
5105 : {
5106 1260 : if (expr_dest_regno (expr) != expr_dest_regno (expr_vliw))
5107 : {
5108 26 : replace_dest_with_reg_in_expr (expr, EXPR_LHS (expr_vliw));
5109 26 : stat_renamed_scheduled++;
5110 : }
5111 : /* Also put the correct TARGET_AVAILABLE bit on the expr.
5112 : This is needed when renaming came up with original
5113 : register. */
5114 1234 : else if (EXPR_TARGET_AVAILABLE (expr)
5115 1234 : != EXPR_TARGET_AVAILABLE (expr_vliw))
5116 : {
5117 2 : gcc_assert (EXPR_TARGET_AVAILABLE (expr_vliw) == 1);
5118 2 : EXPR_TARGET_AVAILABLE (expr) = 1;
5119 : }
5120 : }
5121 4901 : if (EXPR_WAS_SUBSTITUTED (expr))
5122 0 : stat_substitutions_total++;
5123 : }
5124 :
5125 7691 : av_set_add (&expr_seq, expr);
5126 :
5127 : /* With substitution inside insn group, it is possible
5128 : that more than one expression in expr_seq will correspond
5129 : to expr_vliw. In this case, choose one as the attempt to
5130 : move both leads to miscompiles. */
5131 7691 : break;
5132 : }
5133 : }
5134 :
5135 7691 : if (for_moveop && sched_verbose >= 2)
5136 : {
5137 0 : sel_print ("Best expression(s) (sequential form): ");
5138 0 : dump_av_set (expr_seq);
5139 0 : sel_print ("\n");
5140 : }
5141 :
5142 7691 : return expr_seq;
5143 : }
5144 :
5145 :
5146 : /* Move nop to previous block. */
5147 : static void ATTRIBUTE_UNUSED
5148 0 : move_nop_to_previous_block (insn_t nop, basic_block prev_bb)
5149 : {
5150 0 : insn_t prev_insn, next_insn;
5151 :
5152 0 : gcc_assert (sel_bb_head_p (nop)
5153 : && prev_bb == BLOCK_FOR_INSN (nop)->prev_bb);
5154 0 : rtx_note *note = bb_note (BLOCK_FOR_INSN (nop));
5155 0 : prev_insn = sel_bb_end (prev_bb);
5156 0 : next_insn = NEXT_INSN (nop);
5157 0 : gcc_assert (prev_insn != NULL_RTX
5158 : && PREV_INSN (note) == prev_insn);
5159 :
5160 0 : SET_NEXT_INSN (prev_insn) = nop;
5161 0 : SET_PREV_INSN (nop) = prev_insn;
5162 :
5163 0 : SET_PREV_INSN (note) = nop;
5164 0 : SET_NEXT_INSN (note) = next_insn;
5165 :
5166 0 : SET_NEXT_INSN (nop) = note;
5167 0 : SET_PREV_INSN (next_insn) = note;
5168 :
5169 0 : BB_END (prev_bb) = nop;
5170 0 : BLOCK_FOR_INSN (nop) = prev_bb;
5171 0 : }
5172 :
5173 : /* Prepare a place to insert the chosen expression on BND. */
5174 : static insn_t
5175 4901 : prepare_place_to_insert (bnd_t bnd)
5176 : {
5177 4901 : insn_t place_to_insert;
5178 :
5179 : /* Init place_to_insert before calling move_op, as the later
5180 : can possibly remove BND_TO (bnd). */
5181 4901 : if (/* If this is not the first insn scheduled. */
5182 4901 : BND_PTR (bnd))
5183 : {
5184 : /* Add it after last scheduled. */
5185 3215 : place_to_insert = ILIST_INSN (BND_PTR (bnd));
5186 3215 : if (DEBUG_INSN_P (place_to_insert))
5187 : {
5188 : ilist_t l = BND_PTR (bnd);
5189 162 : while ((l = ILIST_NEXT (l)) &&
5190 42 : DEBUG_INSN_P (ILIST_INSN (l)))
5191 : ;
5192 44 : if (!l)
5193 : place_to_insert = NULL;
5194 : }
5195 : }
5196 : else
5197 : place_to_insert = NULL;
5198 :
5199 : if (!place_to_insert)
5200 : {
5201 : /* Add it before BND_TO. The difference is in the
5202 : basic block, where INSN will be added. */
5203 1725 : place_to_insert = get_nop_from_pool (BND_TO (bnd));
5204 1725 : gcc_assert (BLOCK_FOR_INSN (place_to_insert)
5205 : == BLOCK_FOR_INSN (BND_TO (bnd)));
5206 : }
5207 :
5208 4901 : return place_to_insert;
5209 : }
5210 :
5211 : /* Find original instructions for EXPR_SEQ and move it to BND boundary.
5212 : Return the expression to emit in C_EXPR. */
5213 : static bool
5214 4901 : move_exprs_to_boundary (bnd_t bnd, expr_t expr_vliw,
5215 : av_set_t expr_seq, expr_t c_expr)
5216 : {
5217 4901 : bool b, should_move;
5218 4901 : unsigned book_uid;
5219 4901 : bitmap_iterator bi;
5220 4901 : int n_bookkeeping_copies_before_moveop;
5221 :
5222 : /* Make a move. This call will remove the original operation,
5223 : insert all necessary bookkeeping instructions and update the
5224 : data sets. After that all we have to do is add the operation
5225 : at before BND_TO (BND). */
5226 4901 : n_bookkeeping_copies_before_moveop = stat_bookkeeping_copies;
5227 4901 : max_uid_before_move_op = get_max_uid ();
5228 4901 : bitmap_clear (current_copies);
5229 4901 : bitmap_clear (current_originators);
5230 :
5231 4901 : b = move_op (BND_TO (bnd), expr_seq, expr_vliw,
5232 : get_dest_from_orig_ops (expr_seq), c_expr, &should_move);
5233 :
5234 : /* We should be able to find the expression we've chosen for
5235 : scheduling. */
5236 4901 : gcc_assert (b);
5237 :
5238 4901 : if (stat_bookkeeping_copies > n_bookkeeping_copies_before_moveop)
5239 136 : stat_insns_needed_bookkeeping++;
5240 :
5241 5114 : EXECUTE_IF_SET_IN_BITMAP (current_copies, 0, book_uid, bi)
5242 : {
5243 213 : unsigned uid;
5244 213 : bitmap_iterator bi;
5245 :
5246 : /* We allocate these bitmaps lazily. */
5247 213 : if (! INSN_ORIGINATORS_BY_UID (book_uid))
5248 213 : INSN_ORIGINATORS_BY_UID (book_uid) = BITMAP_ALLOC (NULL);
5249 :
5250 213 : bitmap_copy (INSN_ORIGINATORS_BY_UID (book_uid),
5251 : current_originators);
5252 :
5253 : /* Transitively add all originators' originators. */
5254 998 : EXECUTE_IF_SET_IN_BITMAP (current_originators, 0, uid, bi)
5255 785 : if (INSN_ORIGINATORS_BY_UID (uid))
5256 265 : bitmap_ior_into (INSN_ORIGINATORS_BY_UID (book_uid),
5257 265 : INSN_ORIGINATORS_BY_UID (uid));
5258 : }
5259 :
5260 4901 : return should_move;
5261 : }
5262 :
5263 :
5264 : /* Debug a DFA state as an array of bytes. */
5265 : static void
5266 0 : debug_state (state_t state)
5267 : {
5268 0 : unsigned char *p;
5269 0 : unsigned int i, size = dfa_state_size;
5270 :
5271 0 : sel_print ("state (%u):", size);
5272 0 : for (i = 0, p = (unsigned char *) state; i < size; i++)
5273 0 : sel_print (" %d", p[i]);
5274 0 : sel_print ("\n");
5275 0 : }
5276 :
5277 : /* Advance state on FENCE with INSN. Return true if INSN is
5278 : an ASM, and we should advance state once more. */
5279 : static bool
5280 4901 : advance_state_on_fence (fence_t fence, insn_t insn)
5281 : {
5282 4901 : bool asm_p;
5283 :
5284 4901 : if (recog_memoized (insn) >= 0)
5285 : {
5286 4792 : int res;
5287 4792 : state_t temp_state = alloca (dfa_state_size);
5288 :
5289 4792 : gcc_assert (!INSN_ASM_P (insn));
5290 4792 : asm_p = false;
5291 :
5292 4792 : memcpy (temp_state, FENCE_STATE (fence), dfa_state_size);
5293 4792 : res = state_transition (FENCE_STATE (fence), insn);
5294 4792 : gcc_assert (res < 0);
5295 :
5296 4792 : if (memcmp (temp_state, FENCE_STATE (fence), dfa_state_size))
5297 : {
5298 4722 : FENCE_ISSUED_INSNS (fence)++;
5299 :
5300 : /* We should never issue more than issue_rate insns. */
5301 4722 : if (FENCE_ISSUED_INSNS (fence) > issue_rate)
5302 0 : gcc_unreachable ();
5303 : }
5304 : }
5305 : else
5306 : {
5307 : /* This could be an ASM insn which we'd like to schedule
5308 : on the next cycle. */
5309 109 : asm_p = INSN_ASM_P (insn);
5310 109 : if (!FENCE_STARTS_CYCLE_P (fence) && asm_p)
5311 9 : advance_one_cycle (fence);
5312 : }
5313 :
5314 4901 : if (sched_verbose >= 2)
5315 0 : debug_state (FENCE_STATE (fence));
5316 4901 : if (!DEBUG_INSN_P (insn))
5317 4857 : FENCE_STARTS_CYCLE_P (fence) = 0;
5318 4901 : FENCE_ISSUE_MORE (fence) = can_issue_more;
5319 4901 : return asm_p;
5320 : }
5321 :
5322 : /* Update FENCE on which INSN was scheduled and this INSN, too. NEED_STALL
5323 : is nonzero if we need to stall after issuing INSN. */
5324 : static void
5325 4901 : update_fence_and_insn (fence_t fence, insn_t insn, int need_stall)
5326 : {
5327 4901 : bool asm_p;
5328 :
5329 : /* First, reflect that something is scheduled on this fence. */
5330 4901 : asm_p = advance_state_on_fence (fence, insn);
5331 4901 : FENCE_LAST_SCHEDULED_INSN (fence) = insn;
5332 4901 : vec_safe_push (FENCE_EXECUTING_INSNS (fence), insn);
5333 4901 : if (SCHED_GROUP_P (insn))
5334 : {
5335 361 : FENCE_SCHED_NEXT (fence) = INSN_SCHED_NEXT (insn);
5336 361 : SCHED_GROUP_P (insn) = 0;
5337 : }
5338 : else
5339 4540 : FENCE_SCHED_NEXT (fence) = NULL;
5340 4901 : if (INSN_UID (insn) < FENCE_READY_TICKS_SIZE (fence))
5341 4771 : FENCE_READY_TICKS (fence) [INSN_UID (insn)] = 0;
5342 :
5343 : /* Set instruction scheduling info. This will be used in bundling,
5344 : pipelining, tick computations etc. */
5345 4901 : ++INSN_SCHED_TIMES (insn);
5346 4901 : EXPR_TARGET_AVAILABLE (INSN_EXPR (insn)) = true;
5347 4901 : EXPR_ORIG_SCHED_CYCLE (INSN_EXPR (insn)) = FENCE_CYCLE (fence);
5348 4901 : INSN_AFTER_STALL_P (insn) = FENCE_AFTER_STALL_P (fence);
5349 4901 : INSN_SCHED_CYCLE (insn) = FENCE_CYCLE (fence);
5350 :
5351 : /* This does not account for adjust_cost hooks, just add the biggest
5352 : constant the hook may add to the latency. TODO: make this
5353 : a target dependent constant. */
5354 4901 : INSN_READY_CYCLE (insn)
5355 9802 : = INSN_SCHED_CYCLE (insn) + (INSN_CODE (insn) < 0
5356 9693 : ? 1
5357 4792 : : maximal_insn_latency (insn) + 1);
5358 :
5359 : /* Change these fields last, as they're used above. */
5360 4901 : FENCE_AFTER_STALL_P (fence) = 0;
5361 4901 : if (asm_p || need_stall)
5362 10 : advance_one_cycle (fence);
5363 :
5364 : /* Indicate that we've scheduled something on this fence. */
5365 4901 : FENCE_SCHEDULED_P (fence) = true;
5366 4901 : scheduled_something_on_previous_fence = true;
5367 :
5368 : /* Print debug information when insn's fields are updated. */
5369 4901 : if (sched_verbose >= 2)
5370 : {
5371 0 : sel_print ("Scheduling insn: ");
5372 0 : dump_insn_1 (insn, 1);
5373 0 : sel_print ("\n");
5374 : }
5375 4901 : }
5376 :
5377 : /* Update boundary BND (and, if needed, FENCE) with INSN, remove the
5378 : old boundary from BNDSP, add new boundaries to BNDS_TAIL_P and
5379 : return it. */
5380 : static blist_t *
5381 4901 : update_boundaries (fence_t fence, bnd_t bnd, insn_t insn, blist_t *bndsp,
5382 : blist_t *bnds_tailp)
5383 : {
5384 4901 : succ_iterator si;
5385 4901 : insn_t succ;
5386 :
5387 4901 : advance_deps_context (BND_DC (bnd), insn);
5388 9149 : FOR_EACH_SUCC_1 (succ, si, insn,
5389 : SUCCS_NORMAL | SUCCS_SKIP_TO_LOOP_EXITS)
5390 : {
5391 4248 : ilist_t ptr = ilist_copy (BND_PTR (bnd));
5392 :
5393 4248 : ilist_add (&ptr, insn);
5394 :
5395 44 : if (DEBUG_INSN_P (insn) && sel_bb_end_p (insn)
5396 4248 : && is_ineligible_successor (succ, ptr))
5397 : {
5398 0 : ilist_clear (&ptr);
5399 0 : continue;
5400 : }
5401 :
5402 4248 : if (FENCE_INSN (fence) == insn && !sel_bb_end_p (insn))
5403 : {
5404 2806 : if (sched_verbose >= 9)
5405 0 : sel_print ("Updating fence insn from %i to %i\n",
5406 0 : INSN_UID (insn), INSN_UID (succ));
5407 2806 : FENCE_INSN (fence) = succ;
5408 : }
5409 4248 : blist_add (bnds_tailp, succ, ptr, BND_DC (bnd));
5410 4248 : bnds_tailp = &BLIST_NEXT (*bnds_tailp);
5411 : }
5412 :
5413 4901 : blist_remove (bndsp);
5414 4901 : return bnds_tailp;
5415 : }
5416 :
5417 : /* Schedule EXPR_VLIW on BND. Return the insn emitted. */
5418 : static insn_t
5419 4901 : schedule_expr_on_boundary (bnd_t bnd, expr_t expr_vliw, int seqno)
5420 : {
5421 4901 : av_set_t expr_seq;
5422 4901 : expr_t c_expr = XALLOCA (expr_def);
5423 4901 : insn_t place_to_insert;
5424 4901 : insn_t insn;
5425 4901 : bool should_move;
5426 :
5427 4901 : expr_seq = find_sequential_best_exprs (bnd, expr_vliw, true);
5428 :
5429 : /* In case of scheduling a jump skipping some other instructions,
5430 : prepare CFG. After this, jump is at the boundary and can be
5431 : scheduled as usual insn by MOVE_OP. */
5432 4901 : if (vinsn_cond_branch_p (EXPR_VINSN (expr_vliw)))
5433 : {
5434 821 : insn = EXPR_INSN_RTX (expr_vliw);
5435 :
5436 : /* Speculative jumps are not handled. */
5437 821 : if (insn != BND_TO (bnd)
5438 821 : && !sel_insn_is_speculation_check (insn))
5439 0 : move_cond_jump (insn, bnd);
5440 : }
5441 :
5442 : /* Find a place for C_EXPR to schedule. */
5443 4901 : place_to_insert = prepare_place_to_insert (bnd);
5444 4901 : should_move = move_exprs_to_boundary (bnd, expr_vliw, expr_seq, c_expr);
5445 4901 : clear_expr (c_expr);
5446 :
5447 : /* Add the instruction. The corner case to care about is when
5448 : the expr_seq set has more than one expr, and we chose the one that
5449 : is not equal to expr_vliw. Then expr_vliw may be insn in stream, and
5450 : we can't use it. Generate the new vinsn. */
5451 4901 : if (INSN_IN_STREAM_P (EXPR_INSN_RTX (expr_vliw)))
5452 : {
5453 0 : vinsn_t vinsn_new;
5454 :
5455 0 : vinsn_new = vinsn_copy (EXPR_VINSN (expr_vliw), false);
5456 0 : change_vinsn_in_expr (expr_vliw, vinsn_new);
5457 0 : should_move = false;
5458 : }
5459 4901 : if (should_move)
5460 4871 : insn = sel_move_insn (expr_vliw, seqno, place_to_insert);
5461 : else
5462 30 : insn = emit_insn_from_expr_after (expr_vliw, NULL, seqno,
5463 : place_to_insert);
5464 :
5465 : /* Return the nops generated for preserving of data sets back
5466 : into pool. */
5467 4901 : if (INSN_NOP_P (place_to_insert))
5468 1725 : return_nop_to_pool (place_to_insert, !DEBUG_INSN_P (insn));
5469 4901 : remove_temp_moveop_nops (!DEBUG_INSN_P (insn));
5470 :
5471 4901 : av_set_clear (&expr_seq);
5472 :
5473 : /* Save the expression scheduled so to reset target availability if we'll
5474 : meet it later on the same fence. */
5475 4901 : if (EXPR_WAS_RENAMED (expr_vliw))
5476 28 : vinsn_vec_add (&vec_target_unavailable_vinsns, INSN_EXPR (insn));
5477 :
5478 : /* Check that the recent movement didn't destroyed loop
5479 : structure. */
5480 4901 : gcc_assert (!pipelining_p
5481 : || current_loop_nest == NULL
5482 : || loop_latch_edge (current_loop_nest));
5483 4901 : return insn;
5484 : }
5485 :
5486 : /* Stall for N cycles on FENCE. */
5487 : static void
5488 2827 : stall_for_cycles (fence_t fence, int n)
5489 : {
5490 2827 : int could_more;
5491 :
5492 2827 : could_more = n > 1 || FENCE_ISSUED_INSNS (fence) < issue_rate;
5493 6156 : while (n--)
5494 3329 : advance_one_cycle (fence);
5495 2827 : if (could_more)
5496 2666 : FENCE_AFTER_STALL_P (fence) = 1;
5497 2827 : }
5498 :
5499 : /* Gather a parallel group of insns at FENCE and assign their seqno
5500 : to SEQNO. All scheduled insns are gathered in SCHEDULED_INSNS_TAILPP
5501 : list for later recalculation of seqnos. */
5502 : static void
5503 1878 : fill_insns (fence_t fence, int seqno, ilist_t **scheduled_insns_tailpp)
5504 : {
5505 1878 : blist_t bnds = NULL, *bnds_tailp;
5506 1878 : av_set_t av_vliw = NULL;
5507 1878 : insn_t insn = FENCE_INSN (fence);
5508 :
5509 1878 : if (sched_verbose >= 2)
5510 0 : sel_print ("Starting fill_insns for insn %d, cycle %d\n",
5511 0 : INSN_UID (insn), FENCE_CYCLE (fence));
5512 :
5513 1878 : blist_add (&bnds, insn, NULL, FENCE_DC (fence));
5514 1878 : bnds_tailp = &BLIST_NEXT (bnds);
5515 1878 : set_target_context (FENCE_TC (fence));
5516 1878 : can_issue_more = FENCE_ISSUE_MORE (fence);
5517 1878 : target_bb = INSN_BB (insn);
5518 :
5519 : /* Do while we can add any operation to the current group. */
5520 5189 : do
5521 : {
5522 5189 : blist_t *bnds_tailp1, *bndsp;
5523 5189 : expr_t expr_vliw;
5524 5189 : int need_stall = false;
5525 5189 : int was_stall = 0, scheduled_insns = 0;
5526 5189 : int max_insns = pipelining_p ? issue_rate : 2 * issue_rate;
5527 5189 : int max_stall = pipelining_p ? 1 : 3;
5528 5189 : bool last_insn_was_debug = false;
5529 5189 : bool was_debug_bb_end_p = false;
5530 :
5531 5189 : compute_av_set_on_boundaries (fence, bnds, &av_vliw);
5532 5189 : remove_insns_that_need_bookkeeping (fence, &av_vliw);
5533 5189 : remove_insns_for_debug (bnds, &av_vliw);
5534 :
5535 : /* Return early if we have nothing to schedule. */
5536 5189 : if (av_vliw == NULL)
5537 : break;
5538 :
5539 : /* Choose the best expression and, if needed, destination register
5540 : for it. */
5541 7728 : do
5542 : {
5543 7728 : expr_vliw = find_best_expr (&av_vliw, bnds, fence, &need_stall);
5544 7728 : if (! expr_vliw && need_stall)
5545 : {
5546 : /* All expressions required a stall. Do not recompute av sets
5547 : as we'll get the same answer (modulo the insns between
5548 : the fence and its boundary, which will not be available for
5549 : pipelining).
5550 : If we are going to stall for too long, break to recompute av
5551 : sets and bring more insns for pipelining. */
5552 2827 : was_stall++;
5553 2827 : if (need_stall <= 3)
5554 2572 : stall_for_cycles (fence, need_stall);
5555 : else
5556 : {
5557 255 : stall_for_cycles (fence, 1);
5558 255 : break;
5559 : }
5560 : }
5561 : }
5562 2572 : while (! expr_vliw && need_stall);
5563 :
5564 : /* Now either we've selected expr_vliw or we have nothing to schedule. */
5565 5156 : if (!expr_vliw)
5566 : {
5567 255 : av_set_clear (&av_vliw);
5568 255 : break;
5569 : }
5570 :
5571 : bndsp = &bnds;
5572 : bnds_tailp1 = bnds_tailp;
5573 :
5574 9149 : do
5575 : /* This code will be executed only once until we'd have several
5576 : boundaries per fence. */
5577 : {
5578 9149 : bnd_t bnd = BLIST_BND (*bndsp);
5579 :
5580 9149 : if (!av_set_is_in_p (BND_AV1 (bnd), EXPR_VINSN (expr_vliw)))
5581 : {
5582 4248 : bndsp = &BLIST_NEXT (*bndsp);
5583 4248 : continue;
5584 : }
5585 :
5586 4901 : insn = schedule_expr_on_boundary (bnd, expr_vliw, seqno);
5587 4901 : last_insn_was_debug = DEBUG_INSN_P (insn);
5588 4901 : if (last_insn_was_debug)
5589 44 : was_debug_bb_end_p = (insn == BND_TO (bnd) && sel_bb_end_p (insn));
5590 4901 : update_fence_and_insn (fence, insn, need_stall);
5591 4901 : bnds_tailp = update_boundaries (fence, bnd, insn, bndsp, bnds_tailp);
5592 :
5593 : /* Add insn to the list of scheduled on this cycle instructions. */
5594 4901 : ilist_add (*scheduled_insns_tailpp, insn);
5595 4901 : *scheduled_insns_tailpp = &ILIST_NEXT (**scheduled_insns_tailpp);
5596 : }
5597 9149 : while (*bndsp != *bnds_tailp1);
5598 :
5599 4901 : av_set_clear (&av_vliw);
5600 4901 : if (!last_insn_was_debug)
5601 4857 : scheduled_insns++;
5602 :
5603 : /* We currently support information about candidate blocks only for
5604 : one 'target_bb' block. Hence we can't schedule after jump insn,
5605 : as this will bring two boundaries and, hence, necessity to handle
5606 : information for two or more blocks concurrently. */
5607 4857 : if ((last_insn_was_debug ? was_debug_bb_end_p : sel_bb_end_p (insn))
5608 3851 : || (was_stall
5609 1762 : && (was_stall >= max_stall
5610 1762 : || scheduled_insns >= max_insns)))
5611 : break;
5612 : }
5613 3311 : while (bnds);
5614 :
5615 1878 : gcc_assert (!FENCE_BNDS (fence));
5616 :
5617 : /* Update boundaries of the FENCE. */
5618 3103 : while (bnds)
5619 : {
5620 1225 : ilist_t ptr = BND_PTR (BLIST_BND (bnds));
5621 :
5622 1225 : if (ptr)
5623 : {
5624 1033 : insn = ILIST_INSN (ptr);
5625 :
5626 2066 : if (!ilist_is_in_p (FENCE_BNDS (fence), insn))
5627 958 : ilist_add (&FENCE_BNDS (fence), insn);
5628 : }
5629 :
5630 1225 : blist_remove (&bnds);
5631 : }
5632 :
5633 : /* Update target context on the fence. */
5634 1878 : reset_target_context (FENCE_TC (fence), false);
5635 1878 : }
5636 :
5637 : /* All exprs in ORIG_OPS must have the same destination register or memory.
5638 : Return that destination. */
5639 : static rtx
5640 4901 : get_dest_from_orig_ops (av_set_t orig_ops)
5641 : {
5642 4901 : rtx dest = NULL_RTX;
5643 4901 : av_set_iterator av_it;
5644 4901 : expr_t expr;
5645 4901 : bool first_p = true;
5646 :
5647 9802 : FOR_EACH_EXPR (expr, av_it, orig_ops)
5648 : {
5649 4901 : rtx x = EXPR_LHS (expr);
5650 :
5651 4901 : if (first_p)
5652 : {
5653 : first_p = false;
5654 : dest = x;
5655 : }
5656 : else
5657 0 : gcc_assert (dest == x
5658 : || (dest != NULL_RTX && x != NULL_RTX
5659 : && rtx_equal_p (dest, x)));
5660 : }
5661 :
5662 4901 : return dest;
5663 : }
5664 :
5665 : /* Update data sets for the bookkeeping block and record those expressions
5666 : which become no longer available after inserting this bookkeeping. */
5667 : static void
5668 389 : update_and_record_unavailable_insns (basic_block book_block)
5669 : {
5670 389 : av_set_iterator i;
5671 389 : av_set_t old_av_set = NULL;
5672 389 : expr_t cur_expr;
5673 389 : rtx_insn *bb_end = sel_bb_end (book_block);
5674 :
5675 : /* First, get correct liveness in the bookkeeping block. The problem is
5676 : the range between the bookeeping insn and the end of block. */
5677 389 : update_liveness_on_insn (bb_end);
5678 389 : if (control_flow_insn_p (bb_end))
5679 8 : update_liveness_on_insn (PREV_INSN (bb_end));
5680 :
5681 : /* If there's valid av_set on BOOK_BLOCK, then there might exist another
5682 : fence above, where we may choose to schedule an insn which is
5683 : actually blocked from moving up with the bookkeeping we create here. */
5684 389 : if (AV_SET_VALID_P (sel_bb_head (book_block)))
5685 : {
5686 320 : old_av_set = av_set_copy (BB_AV_SET (book_block));
5687 320 : update_data_sets (sel_bb_head (book_block));
5688 :
5689 : /* Traverse all the expressions in the old av_set and check whether
5690 : CUR_EXPR is in new AV_SET. */
5691 1774 : FOR_EACH_EXPR (cur_expr, i, old_av_set)
5692 : {
5693 1134 : expr_t new_expr = av_set_lookup (BB_AV_SET (book_block),
5694 : EXPR_VINSN (cur_expr));
5695 :
5696 1134 : if (! new_expr
5697 : /* In this case, we can just turn off the E_T_A bit, but we can't
5698 : represent this information with the current vector. */
5699 1119 : || EXPR_TARGET_AVAILABLE (new_expr)
5700 1119 : != EXPR_TARGET_AVAILABLE (cur_expr))
5701 : /* Unfortunately, the below code could be also fired up on
5702 : separable insns, e.g. when moving insns through the new
5703 : speculation check as in PR 53701. */
5704 22 : vinsn_vec_add (&vec_bookkeeping_blocked_vinsns, cur_expr);
5705 : }
5706 :
5707 320 : av_set_clear (&old_av_set);
5708 : }
5709 389 : }
5710 :
5711 : /* The main effect of this function is that sparams->c_expr is merged
5712 : with (or copied to) lparams->c_expr_merged. If there's only one successor,
5713 : we avoid merging anything by copying sparams->c_expr to lparams->c_expr_merged.
5714 : lparams->c_expr_merged is copied back to sparams->c_expr after all
5715 : successors has been traversed. lparams->c_expr_local is an expr allocated
5716 : on stack in the caller function, and is used if there is more than one
5717 : successor.
5718 :
5719 : SUCC is one of the SUCCS_NORMAL successors of INSN,
5720 : MOVEOP_DRV_CALL_RES is the result of call code_motion_path_driver on succ,
5721 : LPARAMS and STATIC_PARAMS contain the parameters described above. */
5722 : static void
5723 1002 : move_op_merge_succs (insn_t insn ATTRIBUTE_UNUSED,
5724 : insn_t succ ATTRIBUTE_UNUSED,
5725 : int moveop_drv_call_res,
5726 : cmpd_local_params_p lparams, void *static_params)
5727 : {
5728 1002 : moveop_static_params_p sparams = (moveop_static_params_p) static_params;
5729 :
5730 : /* Nothing to do, if original expr wasn't found below. */
5731 1002 : if (moveop_drv_call_res != 1)
5732 : return;
5733 :
5734 : /* If this is a first successor. */
5735 905 : if (!lparams->c_expr_merged)
5736 : {
5737 651 : lparams->c_expr_merged = sparams->c_expr;
5738 651 : sparams->c_expr = lparams->c_expr_local;
5739 : }
5740 : else
5741 : {
5742 : /* We must merge all found expressions to get reasonable
5743 : EXPR_SPEC_DONE_DS for the resulting insn. If we don't
5744 : do so then we can first find the expr with epsilon
5745 : speculation success probability and only then with the
5746 : good probability. As a result the insn will get epsilon
5747 : probability and will never be scheduled because of
5748 : weakness_cutoff in find_best_expr.
5749 :
5750 : We call merge_expr_data here instead of merge_expr
5751 : because due to speculation C_EXPR and X may have the
5752 : same insns with different speculation types. And as of
5753 : now such insns are considered non-equal.
5754 :
5755 : However, EXPR_SCHED_TIMES is different -- we must get
5756 : SCHED_TIMES from a real insn, not a bookkeeping copy.
5757 : We force this here. Instead, we may consider merging
5758 : SCHED_TIMES to the maximum instead of minimum in the
5759 : below function. */
5760 254 : int old_times = EXPR_SCHED_TIMES (lparams->c_expr_merged);
5761 :
5762 254 : merge_expr_data (lparams->c_expr_merged, sparams->c_expr, NULL);
5763 254 : if (EXPR_SCHED_TIMES (sparams->c_expr) == 0)
5764 254 : EXPR_SCHED_TIMES (lparams->c_expr_merged) = old_times;
5765 :
5766 254 : clear_expr (sparams->c_expr);
5767 : }
5768 : }
5769 :
5770 : /* Add used regs for the successor SUCC into SPARAMS->USED_REGS.
5771 :
5772 : SUCC is one of the SUCCS_NORMAL successors of INSN,
5773 : MOVEOP_DRV_CALL_RES is the result of call code_motion_path_driver on succ or 0,
5774 : if SUCC is one of SUCCS_BACK or SUCCS_OUT.
5775 : STATIC_PARAMS contain USED_REGS set. */
5776 : static void
5777 9985 : fur_merge_succs (insn_t insn ATTRIBUTE_UNUSED, insn_t succ,
5778 : int moveop_drv_call_res,
5779 : cmpd_local_params_p lparams ATTRIBUTE_UNUSED,
5780 : void *static_params)
5781 : {
5782 9985 : regset succ_live;
5783 9985 : fur_static_params_p sparams = (fur_static_params_p) static_params;
5784 :
5785 : /* Here we compute live regsets only for branches that do not lie
5786 : on the code motion paths. These branches correspond to value
5787 : MOVEOP_DRV_CALL_RES==0 and include SUCCS_BACK and SUCCS_OUT, though
5788 : for such branches code_motion_path_driver is not called. */
5789 9985 : if (moveop_drv_call_res != 0)
5790 : return;
5791 :
5792 : /* Mark all registers that do not meet the following condition:
5793 : (3) not live on the other path of any conditional branch
5794 : that is passed by the operation, in case original
5795 : operations are not present on both paths of the
5796 : conditional branch. */
5797 2934 : succ_live = compute_live (succ);
5798 2934 : IOR_REG_SET (sparams->used_regs, succ_live);
5799 : }
5800 :
5801 : /* This function is called after the last successor. Copies LP->C_EXPR_MERGED
5802 : into SP->CEXPR. */
5803 : static void
5804 651 : move_op_after_merge_succs (cmpd_local_params_p lp, void *sparams)
5805 : {
5806 651 : moveop_static_params_p sp = (moveop_static_params_p) sparams;
5807 :
5808 651 : sp->c_expr = lp->c_expr_merged;
5809 651 : }
5810 :
5811 : /* Track bookkeeping copies created, insns scheduled, and blocks for
5812 : rescheduling when INSN is found by move_op. */
5813 : static void
5814 5155 : track_scheduled_insns_and_blocks (rtx_insn *insn)
5815 : {
5816 : /* Even if this insn can be a copy that will be removed during current move_op,
5817 : we still need to count it as an originator. */
5818 5155 : bitmap_set_bit (current_originators, INSN_UID (insn));
5819 :
5820 5155 : if (!bitmap_clear_bit (current_copies, INSN_UID (insn)))
5821 : {
5822 : /* Note that original block needs to be rescheduled, as we pulled an
5823 : instruction out of it. */
5824 4979 : if (INSN_SCHED_TIMES (insn) > 0)
5825 80 : bitmap_set_bit (blocks_to_reschedule, BLOCK_FOR_INSN (insn)->index);
5826 4899 : else if (INSN_UID (insn) < first_emitted_uid && !DEBUG_INSN_P (insn))
5827 4681 : num_insns_scheduled++;
5828 : }
5829 :
5830 : /* For instructions we must immediately remove insn from the
5831 : stream, so subsequent update_data_sets () won't include this
5832 : insn into av_set.
5833 : For expr we must make insn look like "INSN_REG (insn) := c_expr". */
5834 5155 : if (INSN_UID (insn) > max_uid_before_move_op)
5835 174 : stat_bookkeeping_copies--;
5836 5155 : }
5837 :
5838 : /* Emit a register-register copy for INSN if needed. Return true if
5839 : emitted one. PARAMS is the move_op static parameters. */
5840 : static bool
5841 5155 : maybe_emit_renaming_copy (rtx_insn *insn,
5842 : moveop_static_params_p params)
5843 : {
5844 5155 : bool insn_emitted = false;
5845 5155 : rtx cur_reg;
5846 :
5847 : /* Bail out early when expression cannot be renamed at all. */
5848 5155 : if (!EXPR_SEPARABLE_P (params->c_expr))
5849 : return false;
5850 :
5851 1297 : cur_reg = expr_dest_reg (params->c_expr);
5852 1297 : gcc_assert (cur_reg && params->dest && REG_P (params->dest));
5853 :
5854 : /* If original operation has expr and the register chosen for
5855 : that expr is not original operation's dest reg, substitute
5856 : operation's right hand side with the register chosen. */
5857 1297 : if (REGNO (params->dest) != REGNO (cur_reg))
5858 : {
5859 29 : insn_t reg_move_insn, reg_move_insn_rtx;
5860 :
5861 29 : reg_move_insn_rtx = create_insn_rtx_with_rhs (INSN_VINSN (insn),
5862 : params->dest);
5863 87 : reg_move_insn = sel_gen_insn_from_rtx_after (reg_move_insn_rtx,
5864 29 : INSN_EXPR (insn),
5865 29 : INSN_SEQNO (insn),
5866 : insn);
5867 29 : EXPR_SPEC_DONE_DS (INSN_EXPR (reg_move_insn)) = 0;
5868 29 : replace_dest_with_reg_in_expr (params->c_expr, params->dest);
5869 :
5870 29 : insn_emitted = true;
5871 29 : params->was_renamed = true;
5872 : }
5873 :
5874 : return insn_emitted;
5875 : }
5876 :
5877 : /* Emit a speculative check for INSN speculated as EXPR if needed.
5878 : Return true if we've emitted one. PARAMS is the move_op static
5879 : parameters. */
5880 : static bool
5881 5155 : maybe_emit_speculative_check (rtx_insn *insn, expr_t expr,
5882 : moveop_static_params_p params)
5883 : {
5884 5155 : bool insn_emitted = false;
5885 5155 : insn_t x;
5886 5155 : ds_t check_ds;
5887 :
5888 5155 : check_ds = get_spec_check_type_for_insn (insn, expr);
5889 5155 : if (check_ds != 0)
5890 : {
5891 : /* A speculation check should be inserted. */
5892 0 : x = create_speculation_check (params->c_expr, check_ds, insn);
5893 0 : insn_emitted = true;
5894 : }
5895 : else
5896 : {
5897 5155 : EXPR_SPEC_DONE_DS (INSN_EXPR (insn)) = 0;
5898 5155 : x = insn;
5899 : }
5900 :
5901 5155 : gcc_assert (EXPR_SPEC_DONE_DS (INSN_EXPR (x)) == 0
5902 : && EXPR_SPEC_TO_CHECK_DS (INSN_EXPR (x)) == 0);
5903 5155 : return insn_emitted;
5904 : }
5905 :
5906 : /* Handle transformations that leave an insn in place of original
5907 : insn such as renaming/speculation. Return true if one of such
5908 : transformations actually happened, and we have emitted this insn. */
5909 : static bool
5910 5155 : handle_emitting_transformations (rtx_insn *insn, expr_t expr,
5911 : moveop_static_params_p params)
5912 : {
5913 5155 : bool insn_emitted = false;
5914 :
5915 5155 : insn_emitted = maybe_emit_renaming_copy (insn, params);
5916 5155 : insn_emitted |= maybe_emit_speculative_check (insn, expr, params);
5917 :
5918 5155 : return insn_emitted;
5919 : }
5920 :
5921 : /* If INSN is the only insn in the basic block (not counting JUMP,
5922 : which may be a jump to next insn, and DEBUG_INSNs), we want to
5923 : leave a NOP there till the return to fill_insns. */
5924 :
5925 : static bool
5926 5155 : need_nop_to_preserve_insn_bb (rtx_insn *insn)
5927 : {
5928 5155 : insn_t bb_head, bb_end, bb_next, in_next;
5929 5155 : basic_block bb = BLOCK_FOR_INSN (insn);
5930 :
5931 5155 : bb_head = sel_bb_head (bb);
5932 5155 : bb_end = sel_bb_end (bb);
5933 :
5934 5155 : if (bb_head == bb_end)
5935 : return true;
5936 :
5937 5230 : while (bb_head != bb_end && DEBUG_INSN_P (bb_head))
5938 132 : bb_head = NEXT_INSN (bb_head);
5939 :
5940 5098 : if (bb_head == bb_end)
5941 : return true;
5942 :
5943 5106 : while (bb_head != bb_end && DEBUG_INSN_P (bb_end))
5944 8 : bb_end = PREV_INSN (bb_end);
5945 :
5946 5098 : if (bb_head == bb_end)
5947 : return true;
5948 :
5949 5098 : bb_next = NEXT_INSN (bb_head);
5950 10232 : while (bb_next != bb_end && DEBUG_INSN_P (bb_next))
5951 36 : bb_next = NEXT_INSN (bb_next);
5952 :
5953 5098 : if (bb_next == bb_end && JUMP_P (bb_end))
5954 : return true;
5955 :
5956 4815 : in_next = NEXT_INSN (insn);
5957 9648 : while (DEBUG_INSN_P (in_next))
5958 18 : in_next = NEXT_INSN (in_next);
5959 :
5960 4815 : if (IN_CURRENT_FENCE_P (in_next))
5961 : return true;
5962 :
5963 : return false;
5964 : }
5965 :
5966 : /* Remove INSN from stream. When ONLY_DISCONNECT is true, its data
5967 : is not removed but reused when INSN is re-emitted. */
5968 : static void
5969 5155 : remove_insn_from_stream (rtx_insn *insn, bool only_disconnect)
5970 : {
5971 : /* If there's only one insn in the BB, make sure that a nop is
5972 : inserted into it, so the basic block won't disappear when we'll
5973 : delete INSN below with sel_remove_insn. It should also survive
5974 : till the return to fill_insns. */
5975 5155 : if (need_nop_to_preserve_insn_bb (insn))
5976 : {
5977 340 : insn_t nop = get_nop_from_pool (insn);
5978 340 : gcc_assert (INSN_NOP_P (nop));
5979 340 : vec_temp_moveop_nops.safe_push (nop);
5980 : }
5981 :
5982 5155 : sel_remove_insn (insn, only_disconnect, false);
5983 5155 : }
5984 :
5985 : /* This function is called when original expr is found.
5986 : INSN - current insn traversed, EXPR - the corresponding expr found.
5987 : LPARAMS is the local parameters of code modion driver, STATIC_PARAMS
5988 : is static parameters of move_op. */
5989 : static void
5990 5155 : move_op_orig_expr_found (insn_t insn, expr_t expr,
5991 : cmpd_local_params_p lparams ATTRIBUTE_UNUSED,
5992 : void *static_params)
5993 : {
5994 5155 : bool only_disconnect;
5995 5155 : moveop_static_params_p params = (moveop_static_params_p) static_params;
5996 :
5997 5155 : copy_expr_onside (params->c_expr, INSN_EXPR (insn));
5998 5155 : track_scheduled_insns_and_blocks (insn);
5999 5155 : handle_emitting_transformations (insn, expr, params);
6000 5155 : only_disconnect = params->uid == INSN_UID (insn);
6001 :
6002 : /* Mark that we've disconnected an insn. */
6003 5155 : if (only_disconnect)
6004 4871 : params->uid = -1;
6005 5155 : remove_insn_from_stream (insn, only_disconnect);
6006 5155 : }
6007 :
6008 : /* The function is called when original expr is found.
6009 : INSN - current insn traversed, EXPR - the corresponding expr found,
6010 : crossed_call_abis and original_insns in STATIC_PARAMS are updated. */
6011 : static void
6012 3894 : fur_orig_expr_found (insn_t insn, expr_t expr ATTRIBUTE_UNUSED,
6013 : cmpd_local_params_p lparams ATTRIBUTE_UNUSED,
6014 : void *static_params)
6015 : {
6016 3894 : fur_static_params_p params = (fur_static_params_p) static_params;
6017 3894 : regset tmp;
6018 :
6019 3894 : if (CALL_P (insn))
6020 0 : params->crossed_call_abis |= 1 << insn_callee_abi (insn).id ();
6021 :
6022 3894 : def_list_add (params->original_insns, insn, params->crossed_call_abis);
6023 :
6024 : /* Mark the registers that do not meet the following condition:
6025 : (2) not among the live registers of the point
6026 : immediately following the first original operation on
6027 : a given downward path, except for the original target
6028 : register of the operation. */
6029 3894 : tmp = get_clear_regset_from_pool ();
6030 3894 : compute_live_below_insn (insn, tmp);
6031 3894 : AND_COMPL_REG_SET (tmp, INSN_REG_SETS (insn));
6032 3894 : AND_COMPL_REG_SET (tmp, INSN_REG_CLOBBERS (insn));
6033 3894 : IOR_REG_SET (params->used_regs, tmp);
6034 3894 : return_regset_to_pool (tmp);
6035 :
6036 : /* (*1) We need to add to USED_REGS registers that are read by
6037 : INSN's lhs. This may lead to choosing wrong src register.
6038 : E.g. (scheduling const expr enabled):
6039 :
6040 : 429: ax=0x0 <- Can't use AX for this expr (0x0)
6041 : 433: dx=[bp-0x18]
6042 : 427: [ax+dx+0x1]=ax
6043 : REG_DEAD: ax
6044 : 168: di=dx
6045 : REG_DEAD: dx
6046 : */
6047 : /* FIXME: see comment above and enable MEM_P
6048 : in vinsn_separable_p. */
6049 3894 : gcc_assert (!VINSN_SEPARABLE_P (INSN_VINSN (insn))
6050 : || !MEM_P (INSN_LHS (insn)));
6051 3894 : }
6052 :
6053 : /* This function is called on the ascending pass, before returning from
6054 : current basic block. */
6055 : static void
6056 5806 : move_op_at_first_insn (insn_t insn, cmpd_local_params_p lparams,
6057 : void *static_params)
6058 : {
6059 5806 : moveop_static_params_p sparams = (moveop_static_params_p) static_params;
6060 5806 : basic_block book_block = NULL;
6061 :
6062 : /* When we have removed the boundary insn for scheduling, which also
6063 : happened to be the end insn in its bb, we don't need to update sets. */
6064 5806 : if (!lparams->removed_last_insn
6065 5035 : && lparams->e1
6066 6711 : && sel_bb_head_p (insn))
6067 : {
6068 : /* We should generate bookkeeping code only if we are not at the
6069 : top level of the move_op. */
6070 905 : if (sel_num_cfg_preds_gt_1 (insn))
6071 389 : book_block = generate_bookkeeping_insn (sparams->c_expr,
6072 : lparams->e1, lparams->e2);
6073 : /* Update data sets for the current insn. */
6074 905 : update_data_sets (insn);
6075 : }
6076 :
6077 : /* If bookkeeping code was inserted, we need to update av sets of basic
6078 : block that received bookkeeping. After generation of bookkeeping insn,
6079 : bookkeeping block does not contain valid av set because we are not following
6080 : the original algorithm in every detail with regards to e.g. renaming
6081 : simple reg-reg copies. Consider example:
6082 :
6083 : bookkeeping block scheduling fence
6084 : \ /
6085 : \ join /
6086 : ----------
6087 : | |
6088 : ----------
6089 : / \
6090 : / \
6091 : r1 := r2 r1 := r3
6092 :
6093 : We try to schedule insn "r1 := r3" on the current
6094 : scheduling fence. Also, note that av set of bookkeeping block
6095 : contain both insns "r1 := r2" and "r1 := r3". When the insn has
6096 : been scheduled, the CFG is as follows:
6097 :
6098 : r1 := r3 r1 := r3
6099 : bookkeeping block scheduling fence
6100 : \ /
6101 : \ join /
6102 : ----------
6103 : | |
6104 : ----------
6105 : / \
6106 : / \
6107 : r1 := r2
6108 :
6109 : Here, insn "r1 := r3" was scheduled at the current scheduling point
6110 : and bookkeeping code was generated at the bookeeping block. This
6111 : way insn "r1 := r2" is no longer available as a whole instruction
6112 : (but only as expr) ahead of insn "r1 := r3" in bookkeeping block.
6113 : This situation is handled by calling update_data_sets.
6114 :
6115 : Since update_data_sets is called only on the bookkeeping block, and
6116 : it also may have predecessors with av_sets, containing instructions that
6117 : are no longer available, we save all such expressions that become
6118 : unavailable during data sets update on the bookkeeping block in
6119 : VEC_BOOKKEEPING_BLOCKED_VINSNS. Later we avoid selecting such
6120 : expressions for scheduling. This allows us to avoid recomputation of
6121 : av_sets outside the code motion path. */
6122 :
6123 905 : if (book_block)
6124 389 : update_and_record_unavailable_insns (book_block);
6125 :
6126 : /* If INSN was previously marked for deletion, it's time to do it. */
6127 5806 : if (lparams->removed_last_insn)
6128 771 : insn = PREV_INSN (insn);
6129 :
6130 : /* Do not tidy control flow at the topmost moveop, as we can erroneously
6131 : kill a block with a single nop in which the insn should be emitted. */
6132 5806 : if (lparams->e1)
6133 905 : tidy_control_flow (BLOCK_FOR_INSN (insn), true);
6134 5806 : }
6135 :
6136 : /* This function is called on the ascending pass, before returning from the
6137 : current basic block. */
6138 : static void
6139 9375 : fur_at_first_insn (insn_t insn,
6140 : cmpd_local_params_p lparams ATTRIBUTE_UNUSED,
6141 : void *static_params ATTRIBUTE_UNUSED)
6142 : {
6143 9375 : gcc_assert (!sel_bb_head_p (insn) || AV_SET_VALID_P (insn)
6144 : || AV_LEVEL (insn) == -1);
6145 9375 : }
6146 :
6147 : /* Called on the backward stage of recursion to call moveup_expr for insn
6148 : and sparams->c_expr. */
6149 : static void
6150 6717 : move_op_ascend (insn_t insn, void *static_params)
6151 : {
6152 6717 : enum MOVEUP_EXPR_CODE res;
6153 6717 : moveop_static_params_p sparams = (moveop_static_params_p) static_params;
6154 :
6155 6717 : if (! INSN_NOP_P (insn))
6156 : {
6157 6717 : res = moveup_expr_cached (sparams->c_expr, insn, false);
6158 6717 : gcc_assert (res != MOVEUP_EXPR_NULL);
6159 : }
6160 :
6161 : /* Update liveness for this insn as it was invalidated. */
6162 6717 : update_liveness_on_insn (insn);
6163 6717 : }
6164 :
6165 : /* This function is called on enter to the basic block.
6166 : Returns TRUE if this block already have been visited and
6167 : code_motion_path_driver should return 1, FALSE otherwise. */
6168 : static int
6169 10535 : fur_on_enter (insn_t insn ATTRIBUTE_UNUSED, cmpd_local_params_p local_params,
6170 : void *static_params, bool visited_p)
6171 : {
6172 10535 : fur_static_params_p sparams = (fur_static_params_p) static_params;
6173 :
6174 10535 : if (visited_p)
6175 : {
6176 : /* If we have found something below this block, there should be at
6177 : least one insn in ORIGINAL_INSNS. */
6178 466 : gcc_assert (*sparams->original_insns);
6179 :
6180 : /* Adjust CROSSED_CALL_ABIS, since we may have come to this block along
6181 : different path. */
6182 466 : DEF_LIST_DEF (*sparams->original_insns)->crossed_call_abis
6183 466 : |= sparams->crossed_call_abis;
6184 : }
6185 : else
6186 10069 : local_params->old_original_insns = *sparams->original_insns;
6187 :
6188 10535 : return 1;
6189 : }
6190 :
6191 : /* Same as above but for move_op. */
6192 : static int
6193 5903 : move_op_on_enter (insn_t insn ATTRIBUTE_UNUSED,
6194 : cmpd_local_params_p local_params ATTRIBUTE_UNUSED,
6195 : void *static_params ATTRIBUTE_UNUSED, bool visited_p)
6196 : {
6197 5903 : if (visited_p)
6198 24 : return -1;
6199 : return 1;
6200 : }
6201 :
6202 : /* This function is called while descending current basic block if current
6203 : insn is not the original EXPR we're searching for.
6204 :
6205 : Return value: FALSE, if code_motion_path_driver should perform a local
6206 : cleanup and return 0 itself;
6207 : TRUE, if code_motion_path_driver should continue. */
6208 : static bool
6209 6717 : move_op_orig_expr_not_found (insn_t insn, av_set_t orig_ops ATTRIBUTE_UNUSED,
6210 : void *static_params)
6211 : {
6212 6717 : moveop_static_params_p sparams = (moveop_static_params_p) static_params;
6213 :
6214 6717 : sparams->failed_insn = insn;
6215 :
6216 : /* If we're scheduling separate expr, in order to generate correct code
6217 : we need to stop the search at bookkeeping code generated with the
6218 : same destination register or memory. */
6219 6717 : if (lhs_of_insn_equals_to_dest_p (insn, sparams->dest))
6220 0 : return false;
6221 : return true;
6222 : }
6223 :
6224 : /* This function is called while descending current basic block if current
6225 : insn is not the original EXPR we're searching for.
6226 :
6227 : Return value: TRUE (code_motion_path_driver should continue). */
6228 : static bool
6229 42054 : fur_orig_expr_not_found (insn_t insn, av_set_t orig_ops, void *static_params)
6230 : {
6231 42054 : bool mutexed;
6232 42054 : expr_t r;
6233 42054 : av_set_iterator avi;
6234 42054 : fur_static_params_p sparams = (fur_static_params_p) static_params;
6235 :
6236 42054 : if (CALL_P (insn))
6237 1217 : sparams->crossed_call_abis |= 1 << insn_callee_abi (insn).id ();
6238 40837 : else if (DEBUG_INSN_P (insn))
6239 : return true;
6240 :
6241 : /* If current insn we are looking at cannot be executed together
6242 : with original insn, then we can skip it safely.
6243 :
6244 : Example: ORIG_OPS = { (p6) r14 = sign_extend (r15); }
6245 : INSN = (!p6) r14 = r14 + 1;
6246 :
6247 : Here we can schedule ORIG_OP with lhs = r14, though only
6248 : looking at the set of used and set registers of INSN we must
6249 : forbid it. So, add set/used in INSN registers to the
6250 : untouchable set only if there is an insn in ORIG_OPS that can
6251 : affect INSN. */
6252 42051 : mutexed = true;
6253 42051 : FOR_EACH_EXPR (r, avi, orig_ops)
6254 42051 : if (!sched_insns_conditions_mutex_p (insn, EXPR_INSN_RTX (r)))
6255 : {
6256 : mutexed = false;
6257 : break;
6258 : }
6259 :
6260 : /* Mark all registers that do not meet the following condition:
6261 : (1) Not set or read on any path from xi to an instance of the
6262 : original operation. */
6263 42051 : if (!mutexed)
6264 : {
6265 42051 : IOR_REG_SET (sparams->used_regs, INSN_REG_SETS (insn));
6266 42051 : IOR_REG_SET (sparams->used_regs, INSN_REG_USES (insn));
6267 42051 : IOR_REG_SET (sparams->used_regs, INSN_REG_CLOBBERS (insn));
6268 : }
6269 :
6270 : return true;
6271 : }
6272 :
6273 : /* Hooks and data to perform move_op operations with code_motion_path_driver. */
6274 : struct code_motion_path_driver_info_def move_op_hooks = {
6275 : move_op_on_enter,
6276 : move_op_orig_expr_found,
6277 : move_op_orig_expr_not_found,
6278 : move_op_merge_succs,
6279 : move_op_after_merge_succs,
6280 : move_op_ascend,
6281 : move_op_at_first_insn,
6282 : SUCCS_NORMAL,
6283 : "move_op"
6284 : };
6285 :
6286 : /* Hooks and data to perform find_used_regs operations
6287 : with code_motion_path_driver. */
6288 : struct code_motion_path_driver_info_def fur_hooks = {
6289 : fur_on_enter,
6290 : fur_orig_expr_found,
6291 : fur_orig_expr_not_found,
6292 : fur_merge_succs,
6293 : NULL, /* fur_after_merge_succs */
6294 : NULL, /* fur_ascend */
6295 : fur_at_first_insn,
6296 : SUCCS_ALL,
6297 : "find_used_regs"
6298 : };
6299 :
6300 : /* Traverse all successors of INSN. For each successor that is SUCCS_NORMAL
6301 : code_motion_path_driver is called recursively. Original operation
6302 : was found at least on one path that is starting with one of INSN's
6303 : successors (this fact is asserted). ORIG_OPS is expressions we're looking
6304 : for, PATH is the path we've traversed, STATIC_PARAMS is the parameters
6305 : of either move_op or find_used_regs depending on the caller.
6306 :
6307 : Return 0 if we haven't found expression, 1 if we found it, -1 if we don't
6308 : know for sure at this point. */
6309 : static int
6310 6132 : code_motion_process_successors (insn_t insn, av_set_t orig_ops,
6311 : ilist_t path, void *static_params)
6312 : {
6313 6132 : int res = 0;
6314 6132 : succ_iterator succ_i;
6315 6132 : insn_t succ;
6316 6132 : basic_block bb;
6317 6132 : int old_index;
6318 6132 : unsigned old_succs;
6319 :
6320 6132 : struct cmpd_local_params lparams;
6321 6132 : expr_def _x;
6322 :
6323 6132 : lparams.c_expr_local = &_x;
6324 6132 : lparams.c_expr_merged = NULL;
6325 :
6326 : /* We need to process only NORMAL succs for move_op, and collect live
6327 : registers from ALL branches (including those leading out of the
6328 : region) for find_used_regs.
6329 :
6330 : In move_op, there can be a case when insn's bb number has changed
6331 : due to created bookkeeping. This happens very rare, as we need to
6332 : move expression from the beginning to the end of the same block.
6333 : Rescan successors in this case. */
6334 :
6335 6156 : rescan:
6336 6156 : bb = BLOCK_FOR_INSN (insn);
6337 6156 : old_index = bb->index;
6338 6156 : old_succs = EDGE_COUNT (bb->succs);
6339 :
6340 17119 : FOR_EACH_SUCC_1 (succ, succ_i, insn, code_motion_path_driver_info->succ_flags)
6341 : {
6342 10987 : int b;
6343 :
6344 10987 : lparams.e1 = succ_i.e1;
6345 10987 : lparams.e2 = succ_i.e2;
6346 :
6347 : /* Go deep into recursion only for NORMAL edges (non-backedges within the
6348 : current region). */
6349 10987 : if (succ_i.current_flags == SUCCS_NORMAL)
6350 8750 : b = code_motion_path_driver (succ, orig_ops, path, &lparams,
6351 : static_params);
6352 : else
6353 : b = 0;
6354 :
6355 : /* Merge c_expres found or unify live register sets from different
6356 : successors. */
6357 10987 : code_motion_path_driver_info->merge_succs (insn, succ, b, &lparams,
6358 : static_params);
6359 10987 : if (b == 1)
6360 : res = b;
6361 3031 : else if (b == -1 && res != 1)
6362 0 : res = b;
6363 :
6364 : /* We have simplified the control flow below this point. In this case,
6365 : the iterator becomes invalid. We need to try again.
6366 : If we have removed the insn itself, it could be only an
6367 : unconditional jump. Thus, do not rescan but break immediately --
6368 : we have already visited the only successor block. */
6369 10987 : if (!BLOCK_FOR_INSN (insn))
6370 : {
6371 0 : if (sched_verbose >= 6)
6372 0 : sel_print ("Not doing rescan: already visited the only successor"
6373 : " of block %d\n", old_index);
6374 : break;
6375 : }
6376 10987 : if (BLOCK_FOR_INSN (insn)->index != old_index
6377 21950 : || EDGE_COUNT (bb->succs) != old_succs)
6378 : {
6379 24 : if (sched_verbose >= 6)
6380 0 : sel_print ("Rescan: CFG was simplified below insn %d, block %d\n",
6381 0 : INSN_UID (insn), BLOCK_FOR_INSN (insn)->index);
6382 24 : insn = sel_bb_end (BLOCK_FOR_INSN (insn));
6383 24 : goto rescan;
6384 : }
6385 : }
6386 :
6387 : /* Here, RES==1 if original expr was found at least for one of the
6388 : successors. After the loop, RES may happen to have zero value
6389 : only if at some point the expr searched is present in av_set, but is
6390 : not found below. In most cases, this situation is an error.
6391 : The exception is when the original operation is blocked by
6392 : bookkeeping generated for another fence or for another path in current
6393 : move_op. */
6394 6132 : gcc_checking_assert (res == 1
6395 : || (res == 0
6396 : && av_set_could_be_blocked_by_bookkeeping_p (orig_ops, static_params))
6397 : || res == -1);
6398 :
6399 : /* Merge data, clean up, etc. */
6400 6132 : if (res != -1 && code_motion_path_driver_info->after_merge_succs)
6401 651 : code_motion_path_driver_info->after_merge_succs (&lparams, static_params);
6402 :
6403 6132 : return res;
6404 : }
6405 :
6406 :
6407 : /* Perform a cleanup when the driver is about to terminate. ORIG_OPS_P
6408 : is the pointer to the av set with expressions we were looking for,
6409 : PATH_P is the pointer to the traversed path. */
6410 : static inline void
6411 0 : code_motion_path_driver_cleanup (av_set_t *orig_ops_p, ilist_t *path_p)
6412 : {
6413 0 : ilist_remove (path_p);
6414 0 : av_set_clear (orig_ops_p);
6415 0 : }
6416 :
6417 : /* The driver function that implements move_op or find_used_regs
6418 : functionality dependent whether code_motion_path_driver_INFO is set to
6419 : &MOVE_OP_HOOKS or &FUR_HOOKS. This function implements the common parts
6420 : of code (CFG traversal etc) that are shared among both functions. INSN
6421 : is the insn we're starting the search from, ORIG_OPS are the expressions
6422 : we're searching for, PATH is traversed path, LOCAL_PARAMS_IN are local
6423 : parameters of the driver, and STATIC_PARAMS are static parameters of
6424 : the caller.
6425 :
6426 : Returns whether original instructions were found. Note that top-level
6427 : code_motion_path_driver always returns true. */
6428 : static int
6429 16441 : code_motion_path_driver (insn_t insn, av_set_t orig_ops, ilist_t path,
6430 : cmpd_local_params_p local_params_in,
6431 : void *static_params)
6432 : {
6433 16441 : expr_t expr = NULL;
6434 16441 : basic_block bb = BLOCK_FOR_INSN (insn);
6435 16441 : insn_t first_insn, original_insn, bb_tail, before_first;
6436 16441 : bool removed_last_insn = false;
6437 :
6438 16441 : if (sched_verbose >= 6)
6439 : {
6440 0 : sel_print ("%s (", code_motion_path_driver_info->routine_name);
6441 0 : dump_insn (insn);
6442 0 : sel_print (",");
6443 0 : dump_av_set (orig_ops);
6444 0 : sel_print (")\n");
6445 : }
6446 :
6447 16441 : gcc_assert (orig_ops);
6448 :
6449 : /* If no original operations exist below this insn, return immediately. */
6450 16441 : if (is_ineligible_successor (insn, path))
6451 : {
6452 3 : if (sched_verbose >= 6)
6453 0 : sel_print ("Insn %d is ineligible successor\n", INSN_UID (insn));
6454 3 : return false;
6455 : }
6456 :
6457 : /* The block can have invalid av set, in which case it was created earlier
6458 : during move_op. Return immediately. */
6459 16438 : if (sel_bb_head_p (insn))
6460 : {
6461 8914 : if (! AV_SET_VALID_P (insn))
6462 : {
6463 0 : if (sched_verbose >= 6)
6464 0 : sel_print ("Returned from block %d as it had invalid av set\n",
6465 : bb->index);
6466 0 : return false;
6467 : }
6468 :
6469 8914 : if (bitmap_bit_p (code_motion_visited_blocks, bb->index))
6470 : {
6471 : /* We have already found an original operation on this branch, do not
6472 : go any further and just return TRUE here. If we don't stop here,
6473 : function can have exponential behavior even on the small code
6474 : with many different paths (e.g. with data speculation and
6475 : recovery blocks). */
6476 490 : if (sched_verbose >= 6)
6477 0 : sel_print ("Block %d already visited in this traversal\n", bb->index);
6478 490 : if (code_motion_path_driver_info->on_enter)
6479 490 : return code_motion_path_driver_info->on_enter (insn,
6480 : local_params_in,
6481 : static_params,
6482 490 : true);
6483 : }
6484 : }
6485 :
6486 15948 : if (code_motion_path_driver_info->on_enter)
6487 15948 : code_motion_path_driver_info->on_enter (insn, local_params_in,
6488 : static_params, false);
6489 15948 : orig_ops = av_set_copy (orig_ops);
6490 :
6491 : /* Filter the orig_ops set. */
6492 15948 : if (AV_SET_VALID_P (insn))
6493 8424 : av_set_code_motion_filter (&orig_ops, AV_SET (insn));
6494 :
6495 : /* If no more original ops, return immediately. */
6496 15948 : if (!orig_ops)
6497 : {
6498 767 : if (sched_verbose >= 6)
6499 0 : sel_print ("No intersection with av set of block %d\n", bb->index);
6500 767 : return false;
6501 : }
6502 :
6503 : /* For non-speculative insns we have to leave only one form of the
6504 : original operation, because if we don't, we may end up with
6505 : different C_EXPRes and, consequently, with bookkeepings for different
6506 : expression forms along the same code motion path. That may lead to
6507 : generation of incorrect code. So for each code motion we stick to
6508 : the single form of the instruction, except for speculative insns
6509 : which we need to keep in different forms with all speculation
6510 : types. */
6511 15181 : av_set_leave_one_nonspec (&orig_ops);
6512 :
6513 : /* It is not possible that all ORIG_OPS are filtered out. */
6514 15181 : gcc_assert (orig_ops);
6515 :
6516 : /* It is enough to place only heads and tails of visited basic blocks into
6517 : the PATH. */
6518 15181 : ilist_add (&path, insn);
6519 15181 : first_insn = original_insn = insn;
6520 15181 : bb_tail = sel_bb_end (bb);
6521 :
6522 : /* Descend the basic block in search of the original expr; this part
6523 : corresponds to the part of the original move_op procedure executed
6524 : before the recursive call. */
6525 42639 : for (;;)
6526 : {
6527 : /* Look at the insn and decide if it could be an ancestor of currently
6528 : scheduling operation. If it is so, then the insn "dest = op" could
6529 : either be replaced with "dest = reg", because REG now holds the result
6530 : of OP, or just removed, if we've scheduled the insn as a whole.
6531 :
6532 : If this insn doesn't contain currently scheduling OP, then proceed
6533 : with searching and look at its successors. Operations we're searching
6534 : for could have changed when moving up through this insn via
6535 : substituting. In this case, perform unsubstitution on them first.
6536 :
6537 : When traversing the DAG below this insn is finished, insert
6538 : bookkeeping code, if the insn is a joint point, and remove
6539 : leftovers. */
6540 :
6541 57820 : expr = av_set_lookup (orig_ops, INSN_VINSN (insn));
6542 57820 : if (expr)
6543 : {
6544 9049 : insn_t last_insn = PREV_INSN (insn);
6545 :
6546 : /* We have found the original operation. */
6547 9049 : if (sched_verbose >= 6)
6548 0 : sel_print ("Found original operation at insn %d\n", INSN_UID (insn));
6549 :
6550 9049 : code_motion_path_driver_info->orig_expr_found
6551 9049 : (insn, expr, local_params_in, static_params);
6552 :
6553 : /* Step back, so on the way back we'll start traversing from the
6554 : previous insn (or we'll see that it's bb_note and skip that
6555 : loop). */
6556 9049 : if (insn == first_insn)
6557 : {
6558 4476 : first_insn = NEXT_INSN (last_insn);
6559 4476 : removed_last_insn = sel_bb_end_p (last_insn);
6560 : }
6561 : insn = last_insn;
6562 : break;
6563 : }
6564 : else
6565 : {
6566 : /* We haven't found the original expr, continue descending the basic
6567 : block. */
6568 48771 : if (code_motion_path_driver_info->orig_expr_not_found
6569 48771 : (insn, orig_ops, static_params))
6570 : {
6571 : /* Av set ops could have been changed when moving through this
6572 : insn. To find them below it, we have to un-substitute them. */
6573 48771 : undo_transformations (&orig_ops, insn);
6574 : }
6575 : else
6576 : {
6577 : /* Clean up and return, if the hook tells us to do so. It may
6578 : happen if we've encountered the previously created
6579 : bookkeeping. */
6580 0 : code_motion_path_driver_cleanup (&orig_ops, &path);
6581 0 : return -1;
6582 : }
6583 :
6584 48771 : gcc_assert (orig_ops);
6585 : }
6586 :
6587 : /* Stop at insn if we got to the end of BB. */
6588 48771 : if (insn == bb_tail)
6589 : break;
6590 :
6591 42639 : insn = NEXT_INSN (insn);
6592 42639 : }
6593 :
6594 : /* Here INSN either points to the insn before the original insn (may be
6595 : bb_note, if original insn was a bb_head) or to the bb_end. */
6596 15181 : if (!expr)
6597 : {
6598 6132 : int res;
6599 6132 : rtx_insn *last_insn = PREV_INSN (insn);
6600 6132 : bool added_to_path;
6601 :
6602 6132 : gcc_assert (insn == sel_bb_end (bb));
6603 :
6604 : /* Add bb tail to PATH (but it doesn't make any sense if it's a bb_head -
6605 : it's already in PATH then). */
6606 6132 : if (insn != first_insn)
6607 : {
6608 4938 : ilist_add (&path, insn);
6609 4938 : added_to_path = true;
6610 : }
6611 : else
6612 : added_to_path = false;
6613 :
6614 : /* Process_successors should be able to find at least one
6615 : successor for which code_motion_path_driver returns TRUE. */
6616 6132 : res = code_motion_process_successors (insn, orig_ops,
6617 : path, static_params);
6618 :
6619 : /* Jump in the end of basic block could have been removed or replaced
6620 : during code_motion_process_successors, so recompute insn as the
6621 : last insn in bb. */
6622 6132 : if (NEXT_INSN (last_insn) != insn)
6623 : {
6624 0 : insn = sel_bb_end (bb);
6625 0 : first_insn = sel_bb_head (bb);
6626 0 : if (first_insn != original_insn)
6627 : first_insn = original_insn;
6628 : }
6629 :
6630 : /* Remove bb tail from path. */
6631 6132 : if (added_to_path)
6632 4938 : ilist_remove (&path);
6633 :
6634 6132 : if (res != 1)
6635 : {
6636 : /* This is the case when one of the original expr is no longer available
6637 : due to bookkeeping created on this branch with the same register.
6638 : In the original algorithm, which doesn't have update_data_sets call
6639 : on a bookkeeping block, it would simply result in returning
6640 : FALSE when we've encountered a previously generated bookkeeping
6641 : insn in moveop_orig_expr_not_found. */
6642 0 : code_motion_path_driver_cleanup (&orig_ops, &path);
6643 0 : return res;
6644 : }
6645 : }
6646 :
6647 : /* Don't need it any more. */
6648 15181 : av_set_clear (&orig_ops);
6649 :
6650 : /* Backward pass: now, when we have C_EXPR computed, we'll drag it to
6651 : the beginning of the basic block. */
6652 15181 : before_first = PREV_INSN (first_insn);
6653 79133 : while (insn != before_first)
6654 : {
6655 48771 : if (code_motion_path_driver_info->ascend)
6656 6717 : code_motion_path_driver_info->ascend (insn, static_params);
6657 :
6658 48771 : insn = PREV_INSN (insn);
6659 : }
6660 :
6661 : /* Now we're at the bb head. */
6662 15181 : insn = first_insn;
6663 15181 : ilist_remove (&path);
6664 15181 : local_params_in->removed_last_insn = removed_last_insn;
6665 15181 : code_motion_path_driver_info->at_first_insn (insn, local_params_in, static_params);
6666 :
6667 : /* This should be the very last operation as at bb head we could change
6668 : the numbering by creating bookkeeping blocks. */
6669 15181 : if (removed_last_insn)
6670 771 : insn = PREV_INSN (insn);
6671 :
6672 : /* If we have simplified the control flow and removed the first jump insn,
6673 : there's no point in marking this block in the visited blocks bitmap. */
6674 15181 : if (BLOCK_FOR_INSN (insn))
6675 15181 : bitmap_set_bit (code_motion_visited_blocks, BLOCK_FOR_INSN (insn)->index);
6676 : return true;
6677 : }
6678 :
6679 : /* Move up the operations from ORIG_OPS set traversing the dag starting
6680 : from INSN. PATH represents the edges traversed so far.
6681 : DEST is the register chosen for scheduling the current expr. Insert
6682 : bookkeeping code in the join points. EXPR_VLIW is the chosen expression,
6683 : C_EXPR is how it looks like at the given cfg point.
6684 : Set *SHOULD_MOVE to indicate whether we have only disconnected
6685 : one of the insns found.
6686 :
6687 : Returns whether original instructions were found, which is asserted
6688 : to be true in the caller. */
6689 : static bool
6690 4901 : move_op (insn_t insn, av_set_t orig_ops, expr_t expr_vliw,
6691 : rtx dest, expr_t c_expr, bool *should_move)
6692 : {
6693 4901 : struct moveop_static_params sparams;
6694 4901 : struct cmpd_local_params lparams;
6695 4901 : int res;
6696 :
6697 : /* Init params for code_motion_path_driver. */
6698 4901 : sparams.dest = dest;
6699 4901 : sparams.c_expr = c_expr;
6700 4901 : sparams.uid = INSN_UID (EXPR_INSN_RTX (expr_vliw));
6701 4901 : sparams.failed_insn = NULL;
6702 4901 : sparams.was_renamed = false;
6703 4901 : lparams.e1 = NULL;
6704 :
6705 : /* We haven't visited any blocks yet. */
6706 4901 : bitmap_clear (code_motion_visited_blocks);
6707 :
6708 : /* Set appropriate hooks and data. */
6709 4901 : code_motion_path_driver_info = &move_op_hooks;
6710 4901 : res = code_motion_path_driver (insn, orig_ops, NULL, &lparams, &sparams);
6711 :
6712 4901 : gcc_assert (res != -1);
6713 :
6714 4901 : if (sparams.was_renamed)
6715 28 : EXPR_WAS_RENAMED (expr_vliw) = true;
6716 :
6717 4901 : *should_move = (sparams.uid == -1);
6718 :
6719 4901 : return res;
6720 : }
6721 :
6722 :
6723 : /* Functions that work with regions. */
6724 :
6725 : /* Current number of seqno used in init_seqno and init_seqno_1. */
6726 : static int cur_seqno;
6727 :
6728 : /* A helper for init_seqno. Traverse the region starting from BB and
6729 : compute seqnos for visited insns, marking visited bbs in VISITED_BBS.
6730 : Clear visited blocks from BLOCKS_TO_RESCHEDULE. */
6731 : static void
6732 1096 : init_seqno_1 (basic_block bb, sbitmap visited_bbs, bitmap blocks_to_reschedule)
6733 : {
6734 1096 : int bbi = BLOCK_TO_BB (bb->index);
6735 1096 : insn_t insn;
6736 1096 : insn_t succ_insn;
6737 1096 : succ_iterator si;
6738 :
6739 1096 : rtx_note *note = bb_note (bb);
6740 1096 : bitmap_set_bit (visited_bbs, bbi);
6741 1096 : if (blocks_to_reschedule)
6742 52 : bitmap_clear_bit (blocks_to_reschedule, bb->index);
6743 :
6744 1539 : FOR_EACH_SUCC_1 (succ_insn, si, BB_END (bb),
6745 : SUCCS_NORMAL | SUCCS_SKIP_TO_LOOP_EXITS)
6746 : {
6747 443 : basic_block succ = BLOCK_FOR_INSN (succ_insn);
6748 443 : int succ_bbi = BLOCK_TO_BB (succ->index);
6749 :
6750 443 : gcc_assert (in_current_region_p (succ));
6751 :
6752 443 : if (!bitmap_bit_p (visited_bbs, succ_bbi))
6753 : {
6754 306 : gcc_assert (succ_bbi > bbi);
6755 :
6756 306 : init_seqno_1 (succ, visited_bbs, blocks_to_reschedule);
6757 : }
6758 137 : else if (blocks_to_reschedule)
6759 19 : bitmap_set_bit (forced_ebb_heads, succ->index);
6760 : }
6761 :
6762 5954 : for (insn = BB_END (bb); insn != note; insn = PREV_INSN (insn))
6763 4858 : INSN_SEQNO (insn) = cur_seqno--;
6764 1096 : }
6765 :
6766 : /* Initialize seqnos for the current region. BLOCKS_TO_RESCHEDULE contains
6767 : blocks on which we're rescheduling when pipelining, FROM is the block where
6768 : traversing region begins (it may not be the head of the region when
6769 : pipelining, but the head of the loop instead).
6770 :
6771 : Returns the maximal seqno found. */
6772 : static int
6773 790 : init_seqno (bitmap blocks_to_reschedule, basic_block from)
6774 : {
6775 790 : bitmap_iterator bi;
6776 790 : unsigned bbi;
6777 :
6778 790 : auto_sbitmap visited_bbs (current_nr_blocks);
6779 :
6780 790 : if (blocks_to_reschedule)
6781 : {
6782 20 : bitmap_ones (visited_bbs);
6783 94 : EXECUTE_IF_SET_IN_BITMAP (blocks_to_reschedule, 0, bbi, bi)
6784 : {
6785 74 : gcc_assert (BLOCK_TO_BB (bbi) < current_nr_blocks);
6786 74 : bitmap_clear_bit (visited_bbs, BLOCK_TO_BB (bbi));
6787 : }
6788 : }
6789 : else
6790 : {
6791 770 : bitmap_clear (visited_bbs);
6792 770 : from = EBB_FIRST_BB (0);
6793 : }
6794 :
6795 790 : cur_seqno = sched_max_luid - 1;
6796 790 : init_seqno_1 (from, visited_bbs, blocks_to_reschedule);
6797 :
6798 : /* cur_seqno may be positive if the number of instructions is less than
6799 : sched_max_luid - 1 (when rescheduling or if some instructions have been
6800 : removed by the call to purge_empty_blocks in sel_sched_region_1). */
6801 790 : gcc_assert (cur_seqno >= 0);
6802 :
6803 790 : return sched_max_luid - 1;
6804 790 : }
6805 :
6806 : /* Initialize scheduling parameters for current region. */
6807 : static void
6808 770 : sel_setup_region_sched_flags (void)
6809 : {
6810 770 : enable_schedule_as_rhs_p = 1;
6811 770 : bookkeeping_p = 1;
6812 1540 : pipelining_p = (bookkeeping_p
6813 770 : && (flag_sel_sched_pipelining != 0)
6814 387 : && current_loop_nest != NULL
6815 56 : && loop_has_exit_edges (current_loop_nest));
6816 770 : max_insns_to_rename = param_selsched_insns_to_rename;
6817 770 : max_ws = MAX_WS;
6818 770 : }
6819 :
6820 : /* Return true if all basic blocks of current region are empty. */
6821 : static bool
6822 782 : current_region_empty_p (void)
6823 : {
6824 782 : int i;
6825 819 : for (i = 0; i < current_nr_blocks; i++)
6826 807 : if (! sel_bb_empty_p (BASIC_BLOCK_FOR_FN (cfun, BB_TO_BLOCK (i))))
6827 : return false;
6828 :
6829 : return true;
6830 : }
6831 :
6832 : /* Prepare and verify loop nest for pipelining. */
6833 : static void
6834 387 : setup_current_loop_nest (int rgn, bb_vec_t *bbs)
6835 : {
6836 387 : current_loop_nest = get_loop_nest_for_rgn (rgn);
6837 :
6838 387 : if (!current_loop_nest)
6839 : return;
6840 :
6841 : /* If this loop has any saved loop preheaders from nested loops,
6842 : add these basic blocks to the current region. */
6843 56 : sel_add_loop_preheaders (bbs);
6844 :
6845 : /* Check that we're starting with a valid information. */
6846 56 : gcc_assert (loop_latch_edge (current_loop_nest));
6847 56 : gcc_assert (LOOP_MARKED_FOR_PIPELINING_P (current_loop_nest));
6848 : }
6849 :
6850 : /* Compute instruction priorities for current region. */
6851 : static void
6852 770 : sel_compute_priorities (int rgn)
6853 : {
6854 770 : sched_rgn_compute_dependencies (rgn);
6855 :
6856 : /* Compute insn priorities in haifa style. Then free haifa style
6857 : dependencies that we've calculated for this. */
6858 770 : compute_priorities ();
6859 :
6860 770 : if (sched_verbose >= 5)
6861 0 : debug_rgn_dependencies (0);
6862 :
6863 770 : free_rgn_deps ();
6864 770 : }
6865 :
6866 : /* Init scheduling data for RGN. Returns true when this region should not
6867 : be scheduled. */
6868 : static bool
6869 782 : sel_region_init (int rgn)
6870 : {
6871 782 : int i;
6872 782 : bb_vec_t bbs;
6873 :
6874 782 : rgn_setup_region (rgn);
6875 :
6876 : /* Even if sched_is_disabled_for_current_region_p() is true, we still
6877 : do region initialization here so the region can be bundled correctly,
6878 : but we'll skip the scheduling in sel_sched_region (). */
6879 782 : if (current_region_empty_p ())
6880 : return true;
6881 :
6882 770 : bbs.create (current_nr_blocks);
6883 :
6884 2583 : for (i = 0; i < current_nr_blocks; i++)
6885 1043 : bbs.quick_push (BASIC_BLOCK_FOR_FN (cfun, BB_TO_BLOCK (i)));
6886 :
6887 770 : sel_init_bbs (bbs);
6888 :
6889 770 : if (flag_sel_sched_pipelining)
6890 387 : setup_current_loop_nest (rgn, &bbs);
6891 :
6892 770 : sel_setup_region_sched_flags ();
6893 :
6894 : /* Initialize luids and dependence analysis which both sel-sched and haifa
6895 : need. */
6896 770 : sched_init_luids (bbs);
6897 770 : sched_deps_init (false);
6898 :
6899 : /* Initialize haifa data. */
6900 770 : rgn_setup_sched_infos ();
6901 770 : sel_set_sched_flags ();
6902 770 : haifa_init_h_i_d (bbs);
6903 :
6904 770 : sel_compute_priorities (rgn);
6905 770 : init_deps_global ();
6906 :
6907 : /* Main initialization. */
6908 770 : sel_setup_sched_infos ();
6909 770 : sel_init_global_and_expr (bbs);
6910 :
6911 770 : bbs.release ();
6912 :
6913 770 : blocks_to_reschedule = BITMAP_ALLOC (NULL);
6914 :
6915 : /* Init correct liveness sets on each instruction of a single-block loop.
6916 : This is the only situation when we can't update liveness when calling
6917 : compute_live for the first insn of the loop. */
6918 770 : if (current_loop_nest)
6919 : {
6920 56 : int header =
6921 56 : (sel_is_loop_preheader_p (BASIC_BLOCK_FOR_FN (cfun, BB_TO_BLOCK (0)))
6922 56 : ? 1
6923 0 : : 0);
6924 :
6925 56 : if (current_nr_blocks == header + 1)
6926 16 : update_liveness_on_insn
6927 16 : (sel_bb_head (BASIC_BLOCK_FOR_FN (cfun, BB_TO_BLOCK (header))));
6928 : }
6929 :
6930 : /* Set hooks so that no newly generated insn will go out unnoticed. */
6931 770 : sel_register_cfg_hooks ();
6932 :
6933 : /* !!! We call target.sched.init () for the whole region, but we invoke
6934 : targetm.sched.finish () for every ebb. */
6935 770 : if (targetm.sched.init)
6936 : /* None of the arguments are actually used in any target. */
6937 0 : targetm.sched.init (sched_dump, sched_verbose, -1);
6938 :
6939 770 : first_emitted_uid = get_max_uid () + 1;
6940 770 : preheader_removed = false;
6941 :
6942 : /* Reset register allocation ticks array. */
6943 770 : memset (reg_rename_tick, 0, sizeof reg_rename_tick);
6944 770 : reg_rename_this_tick = 0;
6945 :
6946 770 : forced_ebb_heads = BITMAP_ALLOC (NULL);
6947 :
6948 770 : setup_nop_vinsn ();
6949 770 : current_copies = BITMAP_ALLOC (NULL);
6950 770 : current_originators = BITMAP_ALLOC (NULL);
6951 770 : code_motion_visited_blocks = BITMAP_ALLOC (NULL);
6952 :
6953 770 : return false;
6954 : }
6955 :
6956 : /* Simplify insns after the scheduling. */
6957 : static void
6958 770 : simplify_changed_insns (void)
6959 : {
6960 770 : int i;
6961 :
6962 1826 : for (i = 0; i < current_nr_blocks; i++)
6963 : {
6964 1056 : basic_block bb = BASIC_BLOCK_FOR_FN (cfun, BB_TO_BLOCK (i));
6965 1056 : rtx_insn *insn;
6966 :
6967 7274 : FOR_BB_INSNS (bb, insn)
6968 6218 : if (INSN_P (insn))
6969 : {
6970 4645 : expr_t expr = INSN_EXPR (insn);
6971 :
6972 4645 : if (EXPR_WAS_SUBSTITUTED (expr))
6973 0 : validate_simplify_insn (insn);
6974 : }
6975 : }
6976 770 : }
6977 :
6978 : /* Find boundaries of the EBB starting from basic block BB, marking blocks of
6979 : this EBB in SCHEDULED_BLOCKS and appropriately filling in HEAD, TAIL,
6980 : PREV_HEAD, and NEXT_TAIL fields of CURRENT_SCHED_INFO structure. */
6981 : static void
6982 610 : find_ebb_boundaries (basic_block bb, bitmap scheduled_blocks)
6983 : {
6984 610 : rtx_insn *head, *tail;
6985 610 : basic_block bb1 = bb;
6986 610 : if (sched_verbose >= 2)
6987 0 : sel_print ("Finishing schedule in bbs: ");
6988 :
6989 733 : do
6990 : {
6991 733 : bitmap_set_bit (scheduled_blocks, BLOCK_TO_BB (bb1->index));
6992 :
6993 733 : if (sched_verbose >= 2)
6994 0 : sel_print ("%d; ", bb1->index);
6995 : }
6996 733 : while (!bb_ends_ebb_p (bb1) && (bb1 = bb_next_bb (bb1)));
6997 :
6998 610 : if (sched_verbose >= 2)
6999 0 : sel_print ("\n");
7000 :
7001 610 : get_ebb_head_tail (bb, bb1, &head, &tail);
7002 :
7003 610 : current_sched_info->head = head;
7004 610 : current_sched_info->tail = tail;
7005 610 : current_sched_info->prev_head = PREV_INSN (head);
7006 610 : current_sched_info->next_tail = NEXT_INSN (tail);
7007 610 : }
7008 :
7009 : /* Regenerate INSN_SCHED_CYCLEs for insns of current EBB. */
7010 : static void
7011 104 : reset_sched_cycles_in_current_ebb (void)
7012 : {
7013 104 : int last_clock = 0;
7014 104 : int haifa_last_clock = -1;
7015 104 : int haifa_clock = 0;
7016 104 : int issued_insns = 0;
7017 104 : insn_t insn;
7018 :
7019 104 : if (targetm.sched.init)
7020 : {
7021 : /* None of the arguments are actually used in any target.
7022 : NB: We should have md_reset () hook for cases like this. */
7023 0 : targetm.sched.init (sched_dump, sched_verbose, -1);
7024 : }
7025 :
7026 104 : state_reset (curr_state);
7027 104 : advance_state (curr_state);
7028 :
7029 1260 : for (insn = current_sched_info->head;
7030 1260 : insn != current_sched_info->next_tail;
7031 1156 : insn = NEXT_INSN (insn))
7032 : {
7033 1156 : int cost, haifa_cost;
7034 1156 : int sort_p;
7035 1156 : bool asm_p, real_insn, after_stall, all_issued;
7036 1156 : int clock;
7037 :
7038 1156 : if (!INSN_P (insn))
7039 98 : continue;
7040 :
7041 1058 : asm_p = false;
7042 1058 : real_insn = recog_memoized (insn) >= 0;
7043 1058 : clock = INSN_SCHED_CYCLE (insn);
7044 :
7045 1058 : cost = clock - last_clock;
7046 :
7047 : /* Initialize HAIFA_COST. */
7048 1058 : if (! real_insn)
7049 : {
7050 5 : asm_p = INSN_ASM_P (insn);
7051 :
7052 5 : if (asm_p)
7053 : /* This is asm insn which *had* to be scheduled first
7054 : on the cycle. */
7055 : haifa_cost = 1;
7056 : else
7057 : /* This is a use/clobber insn. It should not change
7058 : cost. */
7059 2 : haifa_cost = 0;
7060 : }
7061 : else
7062 1053 : haifa_cost = estimate_insn_cost (insn, curr_state);
7063 :
7064 : /* Stall for whatever cycles we've stalled before. */
7065 1058 : after_stall = 0;
7066 1058 : if (INSN_AFTER_STALL_P (insn) && cost > haifa_cost)
7067 : {
7068 : haifa_cost = cost;
7069 : after_stall = 1;
7070 : }
7071 1058 : all_issued = issued_insns == issue_rate;
7072 1058 : if (haifa_cost == 0 && all_issued)
7073 0 : haifa_cost = 1;
7074 1058 : if (haifa_cost > 0)
7075 : {
7076 : int i = 0;
7077 :
7078 1498 : while (haifa_cost--)
7079 : {
7080 827 : advance_state (curr_state);
7081 827 : issued_insns = 0;
7082 827 : i++;
7083 :
7084 827 : if (sched_verbose >= 2)
7085 : {
7086 0 : sel_print ("advance_state (state_transition)\n");
7087 0 : debug_state (curr_state);
7088 : }
7089 :
7090 : /* The DFA may report that e.g. insn requires 2 cycles to be
7091 : issued, but on the next cycle it says that insn is ready
7092 : to go. Check this here. */
7093 827 : if (!after_stall
7094 827 : && real_insn
7095 186 : && haifa_cost > 0
7096 839 : && estimate_insn_cost (insn, curr_state) == 0)
7097 : break;
7098 :
7099 : /* When the data dependency stall is longer than the DFA stall,
7100 : and when we have issued exactly issue_rate insns and stalled,
7101 : it could be that after this longer stall the insn will again
7102 : become unavailable to the DFA restrictions. Looks strange
7103 : but happens e.g. on x86-64. So recheck DFA on the last
7104 : iteration. */
7105 827 : if ((after_stall || all_issued)
7106 : && real_insn
7107 691 : && haifa_cost == 0)
7108 547 : haifa_cost = estimate_insn_cost (insn, curr_state);
7109 : }
7110 :
7111 671 : haifa_clock += i;
7112 671 : if (sched_verbose >= 2)
7113 0 : sel_print ("haifa clock: %d\n", haifa_clock);
7114 : }
7115 : else
7116 : gcc_assert (haifa_cost == 0);
7117 :
7118 1058 : if (sched_verbose >= 2)
7119 0 : sel_print ("Haifa cost for insn %d: %d\n", INSN_UID (insn), haifa_cost);
7120 :
7121 1058 : if (targetm.sched.dfa_new_cycle)
7122 0 : while (targetm.sched.dfa_new_cycle (sched_dump, sched_verbose, insn,
7123 : haifa_last_clock, haifa_clock,
7124 : &sort_p))
7125 : {
7126 0 : advance_state (curr_state);
7127 0 : issued_insns = 0;
7128 0 : haifa_clock++;
7129 0 : if (sched_verbose >= 2)
7130 : {
7131 0 : sel_print ("advance_state (dfa_new_cycle)\n");
7132 0 : debug_state (curr_state);
7133 0 : sel_print ("haifa clock: %d\n", haifa_clock + 1);
7134 : }
7135 : }
7136 :
7137 1058 : if (real_insn)
7138 : {
7139 1053 : static state_t temp = NULL;
7140 :
7141 1053 : if (!temp)
7142 26 : temp = xmalloc (dfa_state_size);
7143 1053 : memcpy (temp, curr_state, dfa_state_size);
7144 :
7145 1053 : cost = state_transition (curr_state, insn);
7146 1053 : if (memcmp (temp, curr_state, dfa_state_size))
7147 1050 : issued_insns++;
7148 :
7149 1053 : if (sched_verbose >= 2)
7150 : {
7151 0 : sel_print ("scheduled insn %d, clock %d\n", INSN_UID (insn),
7152 : haifa_clock + 1);
7153 0 : debug_state (curr_state);
7154 : }
7155 1053 : gcc_assert (cost < 0);
7156 : }
7157 :
7158 1058 : if (targetm.sched.variable_issue)
7159 0 : targetm.sched.variable_issue (sched_dump, sched_verbose, insn, 0);
7160 :
7161 1058 : INSN_SCHED_CYCLE (insn) = haifa_clock;
7162 :
7163 1058 : last_clock = clock;
7164 1058 : haifa_last_clock = haifa_clock;
7165 : }
7166 104 : }
7167 :
7168 : /* Put TImode markers on insns starting a new issue group. */
7169 : static void
7170 610 : put_TImodes (void)
7171 : {
7172 610 : int last_clock = -1;
7173 610 : insn_t insn;
7174 :
7175 3931 : for (insn = current_sched_info->head; insn != current_sched_info->next_tail;
7176 3321 : insn = NEXT_INSN (insn))
7177 : {
7178 3321 : int cost, clock;
7179 :
7180 3321 : if (!INSN_P (insn))
7181 126 : continue;
7182 :
7183 3195 : clock = INSN_SCHED_CYCLE (insn);
7184 3195 : cost = (last_clock == -1) ? 1 : clock - last_clock;
7185 :
7186 2571 : gcc_assert (cost >= 0);
7187 :
7188 3195 : if (issue_rate > 1
7189 3195 : && GET_CODE (PATTERN (insn)) != USE
7190 6364 : && GET_CODE (PATTERN (insn)) != CLOBBER)
7191 : {
7192 3163 : if (reload_completed && cost > 0)
7193 2422 : PUT_MODE (insn, TImode);
7194 :
7195 : last_clock = clock;
7196 : }
7197 :
7198 3195 : if (sched_verbose >= 2)
7199 0 : sel_print ("Cost for insn %d is %d\n", INSN_UID (insn), cost);
7200 : }
7201 610 : }
7202 :
7203 : /* Perform MD_FINISH on EBBs comprising current region. When
7204 : RESET_SCHED_CYCLES_P is true, run a pass emulating the scheduler
7205 : to produce correct sched cycles on insns. */
7206 : static void
7207 531 : sel_region_target_finish (bool reset_sched_cycles_p)
7208 : {
7209 531 : int i;
7210 531 : bitmap scheduled_blocks = BITMAP_ALLOC (NULL);
7211 :
7212 1846 : for (i = 0; i < current_nr_blocks; i++)
7213 : {
7214 784 : if (bitmap_bit_p (scheduled_blocks, i))
7215 123 : continue;
7216 :
7217 : /* While pipelining outer loops, skip bundling for loop
7218 : preheaders. Those will be rescheduled in the outer loop. */
7219 661 : if (sel_is_loop_preheader_p (EBB_FIRST_BB (i)))
7220 51 : continue;
7221 :
7222 610 : find_ebb_boundaries (EBB_FIRST_BB (i), scheduled_blocks);
7223 :
7224 610 : if (no_real_insns_p (current_sched_info->head, current_sched_info->tail))
7225 0 : continue;
7226 :
7227 610 : if (reset_sched_cycles_p)
7228 104 : reset_sched_cycles_in_current_ebb ();
7229 :
7230 610 : if (targetm.sched.init)
7231 0 : targetm.sched.init (sched_dump, sched_verbose, -1);
7232 :
7233 610 : put_TImodes ();
7234 :
7235 610 : if (targetm.sched.finish)
7236 : {
7237 0 : targetm.sched.finish (sched_dump, sched_verbose);
7238 :
7239 : /* Extend luids so that insns generated by the target will
7240 : get zero luid. */
7241 0 : sched_extend_luids ();
7242 : }
7243 : }
7244 :
7245 531 : BITMAP_FREE (scheduled_blocks);
7246 531 : }
7247 :
7248 : /* Free the scheduling data for the current region. When RESET_SCHED_CYCLES_P
7249 : is true, make an additional pass emulating scheduler to get correct insn
7250 : cycles for md_finish calls. */
7251 : static void
7252 770 : sel_region_finish (bool reset_sched_cycles_p)
7253 : {
7254 770 : simplify_changed_insns ();
7255 770 : sched_finish_ready_list ();
7256 770 : free_nop_pool ();
7257 :
7258 : /* Free the vectors. */
7259 770 : vec_av_set.release ();
7260 770 : BITMAP_FREE (current_copies);
7261 770 : BITMAP_FREE (current_originators);
7262 770 : BITMAP_FREE (code_motion_visited_blocks);
7263 770 : vinsn_vec_free (vec_bookkeeping_blocked_vinsns);
7264 770 : vinsn_vec_free (vec_target_unavailable_vinsns);
7265 :
7266 : /* If LV_SET of the region head should be updated, do it now because
7267 : there will be no other chance. */
7268 770 : {
7269 770 : succ_iterator si;
7270 770 : insn_t insn;
7271 :
7272 1540 : FOR_EACH_SUCC_1 (insn, si, bb_note (EBB_FIRST_BB (0)),
7273 : SUCCS_NORMAL | SUCCS_SKIP_TO_LOOP_EXITS)
7274 : {
7275 770 : basic_block bb = BLOCK_FOR_INSN (insn);
7276 :
7277 770 : if (!BB_LV_SET_VALID_P (bb))
7278 0 : compute_live (insn);
7279 : }
7280 : }
7281 :
7282 : /* Emulate the Haifa scheduler for bundling. */
7283 770 : if (reload_completed)
7284 531 : sel_region_target_finish (reset_sched_cycles_p);
7285 :
7286 770 : sel_finish_global_and_expr ();
7287 :
7288 770 : BITMAP_FREE (forced_ebb_heads);
7289 :
7290 770 : free_nop_vinsn ();
7291 :
7292 770 : finish_deps_global ();
7293 770 : sched_finish_luids ();
7294 770 : h_d_i_d.release ();
7295 :
7296 770 : sel_finish_bbs ();
7297 770 : BITMAP_FREE (blocks_to_reschedule);
7298 :
7299 770 : sel_unregister_cfg_hooks ();
7300 :
7301 770 : max_issue_size = 0;
7302 770 : }
7303 :
7304 :
7305 : /* Functions that implement the scheduler driver. */
7306 :
7307 : /* Schedule a parallel instruction group on each of FENCES. MAX_SEQNO
7308 : is the current maximum seqno. SCHEDULED_INSNS_TAILPP is the list
7309 : of insns scheduled -- these would be postprocessed later. */
7310 : static void
7311 1736 : schedule_on_fences (flist_t fences, int max_seqno,
7312 : ilist_t **scheduled_insns_tailpp)
7313 : {
7314 1736 : flist_t old_fences = fences;
7315 :
7316 1736 : if (sched_verbose >= 1)
7317 : {
7318 0 : sel_print ("\nScheduling on fences: ");
7319 0 : dump_flist (fences);
7320 0 : sel_print ("\n");
7321 : }
7322 :
7323 1736 : scheduled_something_on_previous_fence = false;
7324 3614 : for (; fences; fences = FLIST_NEXT (fences))
7325 : {
7326 : fence_t fence = NULL;
7327 : int seqno = 0;
7328 : flist_t fences2;
7329 : bool first_p = true;
7330 :
7331 : /* Choose the next fence group to schedule.
7332 : The fact that insn can be scheduled only once
7333 : on the cycle is guaranteed by two properties:
7334 : 1. seqnos of parallel groups decrease with each iteration.
7335 : 2. If is_ineligible_successor () sees the larger seqno, it
7336 : checks if candidate insn is_in_current_fence_p (). */
7337 4070 : for (fences2 = old_fences; fences2; fences2 = FLIST_NEXT (fences2))
7338 : {
7339 2192 : fence_t f = FLIST_FENCE (fences2);
7340 :
7341 2192 : if (!FENCE_PROCESSED_P (f))
7342 : {
7343 2035 : int i = INSN_SEQNO (FENCE_INSN (f));
7344 :
7345 2035 : if (first_p || i > seqno)
7346 : {
7347 1947 : seqno = i;
7348 1947 : fence = f;
7349 1947 : first_p = false;
7350 : }
7351 : else
7352 : /* ??? Seqnos of different groups should be different. */
7353 : gcc_assert (1 || i != seqno);
7354 : }
7355 : }
7356 :
7357 1878 : gcc_assert (fence);
7358 :
7359 : /* As FENCE is nonnull, SEQNO is initialized. */
7360 1878 : seqno -= max_seqno + 1;
7361 1878 : fill_insns (fence, seqno, scheduled_insns_tailpp);
7362 1878 : FENCE_PROCESSED_P (fence) = true;
7363 : }
7364 :
7365 : /* All av_sets are invalidated by GLOBAL_LEVEL increase, thus we
7366 : don't need to keep bookkeeping-invalidated and target-unavailable
7367 : vinsns any more. */
7368 1736 : vinsn_vec_clear (&vec_bookkeeping_blocked_vinsns);
7369 1736 : vinsn_vec_clear (&vec_target_unavailable_vinsns);
7370 1736 : }
7371 :
7372 : /* Calculate MIN_SEQNO and MAX_SEQNO. */
7373 : static void
7374 1736 : find_min_max_seqno (flist_t fences, int *min_seqno, int *max_seqno)
7375 : {
7376 1736 : *min_seqno = *max_seqno = INSN_SEQNO (FENCE_INSN (FLIST_FENCE (fences)));
7377 :
7378 : /* The first element is already processed. */
7379 1878 : while ((fences = FLIST_NEXT (fences)))
7380 : {
7381 142 : int seqno = INSN_SEQNO (FENCE_INSN (FLIST_FENCE (fences)));
7382 :
7383 142 : if (*min_seqno > seqno)
7384 73 : *min_seqno = seqno;
7385 69 : else if (*max_seqno < seqno)
7386 64 : *max_seqno = seqno;
7387 : }
7388 1736 : }
7389 :
7390 : /* Calculate new fences from FENCES. Write the current time to PTIME. */
7391 : static flist_t
7392 1736 : calculate_new_fences (flist_t fences, int orig_max_seqno, int *ptime)
7393 : {
7394 1736 : flist_t old_fences = fences;
7395 1736 : struct flist_tail_def _new_fences, *new_fences = &_new_fences;
7396 1736 : int max_time = 0;
7397 :
7398 1736 : flist_tail_init (new_fences);
7399 3614 : for (; fences; fences = FLIST_NEXT (fences))
7400 : {
7401 1878 : fence_t fence = FLIST_FENCE (fences);
7402 1878 : insn_t insn;
7403 :
7404 1878 : if (!FENCE_BNDS (fence))
7405 : {
7406 : /* This fence doesn't have any successors. */
7407 920 : if (!FENCE_SCHEDULED_P (fence))
7408 : {
7409 : /* Nothing was scheduled on this fence. */
7410 192 : int seqno;
7411 :
7412 192 : insn = FENCE_INSN (fence);
7413 192 : seqno = INSN_SEQNO (insn);
7414 192 : gcc_assert (seqno > 0 && seqno <= orig_max_seqno);
7415 :
7416 192 : if (sched_verbose >= 1)
7417 0 : sel_print ("Fence %d[%d] has not changed\n",
7418 : INSN_UID (insn),
7419 0 : BLOCK_NUM (insn));
7420 192 : move_fence_to_fences (fences, new_fences);
7421 : }
7422 : }
7423 : else
7424 958 : extract_new_fences_from (fences, new_fences, orig_max_seqno);
7425 1878 : max_time = MAX (max_time, FENCE_CYCLE (fence));
7426 : }
7427 :
7428 1736 : flist_clear (&old_fences);
7429 1736 : *ptime = max_time;
7430 1736 : return FLIST_TAIL_HEAD (new_fences);
7431 : }
7432 :
7433 : /* Update seqnos of insns given by PSCHEDULED_INSNS. MIN_SEQNO and MAX_SEQNO
7434 : are the miminum and maximum seqnos of the group, HIGHEST_SEQNO_IN_USE is
7435 : the highest seqno used in a region. Return the updated highest seqno. */
7436 : static int
7437 1736 : update_seqnos_and_stage (int min_seqno, int max_seqno,
7438 : int highest_seqno_in_use,
7439 : ilist_t *pscheduled_insns)
7440 : {
7441 1736 : int new_hs;
7442 1736 : ilist_iterator ii;
7443 1736 : insn_t insn;
7444 :
7445 : /* Actually, new_hs is the seqno of the instruction, that was
7446 : scheduled first (i.e. it is the first one in SCHEDULED_INSNS). */
7447 1736 : if (*pscheduled_insns)
7448 : {
7449 1555 : new_hs = (INSN_SEQNO (ILIST_INSN (*pscheduled_insns))
7450 1555 : + highest_seqno_in_use + max_seqno - min_seqno + 2);
7451 1555 : gcc_assert (new_hs > highest_seqno_in_use);
7452 : }
7453 : else
7454 : new_hs = highest_seqno_in_use;
7455 :
7456 6637 : FOR_EACH_INSN (insn, ii, *pscheduled_insns)
7457 : {
7458 4901 : gcc_assert (INSN_SEQNO (insn) < 0);
7459 4901 : INSN_SEQNO (insn) += highest_seqno_in_use + max_seqno - min_seqno + 2;
7460 4901 : gcc_assert (INSN_SEQNO (insn) <= new_hs);
7461 :
7462 : /* When not pipelining, purge unneeded insn info on the scheduled insns.
7463 : For example, having reg_last array of INSN_DEPS_CONTEXT in memory may
7464 : require > 1GB of memory e.g. on limit-fnargs.c. */
7465 4901 : if (! pipelining_p)
7466 3640 : free_data_for_scheduled_insn (insn);
7467 : }
7468 :
7469 1736 : ilist_clear (pscheduled_insns);
7470 1736 : global_level++;
7471 :
7472 1736 : return new_hs;
7473 : }
7474 :
7475 : /* The main driver for scheduling a region. This function is responsible
7476 : for correct propagation of fences (i.e. scheduling points) and creating
7477 : a group of parallel insns at each of them. It also supports
7478 : pipelining. ORIG_MAX_SEQNO is the maximal seqno before this pass
7479 : of scheduling. */
7480 : static void
7481 790 : sel_sched_region_2 (int orig_max_seqno)
7482 : {
7483 790 : int highest_seqno_in_use = orig_max_seqno;
7484 790 : int max_time = 0;
7485 :
7486 790 : stat_bookkeeping_copies = 0;
7487 790 : stat_insns_needed_bookkeeping = 0;
7488 790 : stat_renamed_scheduled = 0;
7489 790 : stat_substitutions_total = 0;
7490 790 : num_insns_scheduled = 0;
7491 :
7492 2526 : while (fences)
7493 : {
7494 1736 : int min_seqno, max_seqno;
7495 1736 : ilist_t scheduled_insns = NULL;
7496 1736 : ilist_t *scheduled_insns_tailp = &scheduled_insns;
7497 :
7498 1736 : find_min_max_seqno (fences, &min_seqno, &max_seqno);
7499 1736 : schedule_on_fences (fences, max_seqno, &scheduled_insns_tailp);
7500 1736 : fences = calculate_new_fences (fences, orig_max_seqno, &max_time);
7501 1736 : highest_seqno_in_use = update_seqnos_and_stage (min_seqno, max_seqno,
7502 : highest_seqno_in_use,
7503 : &scheduled_insns);
7504 : }
7505 :
7506 790 : if (sched_verbose >= 1)
7507 : {
7508 0 : sel_print ("Total scheduling time: %d cycles\n", max_time);
7509 0 : sel_print ("Scheduled %d bookkeeping copies, %d insns needed "
7510 : "bookkeeping, %d insns renamed, %d insns substituted\n",
7511 : stat_bookkeeping_copies,
7512 : stat_insns_needed_bookkeeping,
7513 : stat_renamed_scheduled,
7514 : stat_substitutions_total);
7515 : }
7516 790 : }
7517 :
7518 : /* Schedule a region. When pipelining, search for possibly never scheduled
7519 : bookkeeping code and schedule it. Reschedule pipelined code without
7520 : pipelining after. */
7521 : static void
7522 770 : sel_sched_region_1 (void)
7523 : {
7524 770 : int orig_max_seqno;
7525 :
7526 : /* Remove empty blocks that might be in the region from the beginning. */
7527 770 : purge_empty_blocks ();
7528 :
7529 770 : orig_max_seqno = init_seqno (NULL, NULL);
7530 770 : gcc_assert (orig_max_seqno >= 1);
7531 :
7532 : /* When pipelining outer loops, create fences on the loop header,
7533 : not preheader. */
7534 770 : fences = NULL;
7535 770 : if (current_loop_nest)
7536 56 : init_fences (BB_END (EBB_FIRST_BB (0)));
7537 : else
7538 714 : init_fences (bb_note (EBB_FIRST_BB (0)));
7539 770 : global_level = 1;
7540 :
7541 770 : sel_sched_region_2 (orig_max_seqno);
7542 :
7543 770 : gcc_assert (fences == NULL);
7544 :
7545 770 : if (pipelining_p)
7546 : {
7547 54 : int i;
7548 54 : basic_block bb;
7549 54 : struct flist_tail_def _new_fences;
7550 54 : flist_tail_t new_fences = &_new_fences;
7551 54 : bool do_p = true;
7552 :
7553 54 : pipelining_p = false;
7554 54 : max_ws = MIN (max_ws, issue_rate * 3 / 2);
7555 54 : bookkeeping_p = false;
7556 54 : enable_schedule_as_rhs_p = false;
7557 :
7558 : /* Schedule newly created code, that has not been scheduled yet. */
7559 54 : do_p = true;
7560 :
7561 182 : while (do_p)
7562 : {
7563 514 : do_p = false;
7564 :
7565 514 : for (i = 0; i < current_nr_blocks; i++)
7566 : {
7567 440 : basic_block bb = EBB_FIRST_BB (i);
7568 :
7569 440 : if (bitmap_bit_p (blocks_to_reschedule, bb->index))
7570 : {
7571 74 : if (! bb_ends_ebb_p (bb))
7572 28 : bitmap_set_bit (blocks_to_reschedule, bb_next_bb (bb)->index);
7573 74 : if (sel_bb_empty_p (bb))
7574 : {
7575 0 : bitmap_clear_bit (blocks_to_reschedule, bb->index);
7576 0 : continue;
7577 : }
7578 74 : clear_outdated_rtx_info (bb);
7579 74 : if (sel_insn_is_speculation_check (BB_END (bb))
7580 74 : && JUMP_P (BB_END (bb)))
7581 0 : bitmap_set_bit (blocks_to_reschedule,
7582 0 : BRANCH_EDGE (bb)->dest->index);
7583 : }
7584 366 : else if (! sel_bb_empty_p (bb)
7585 366 : && INSN_SCHED_TIMES (sel_bb_head (bb)) <= 0)
7586 40 : bitmap_set_bit (blocks_to_reschedule, bb->index);
7587 : }
7588 :
7589 400 : for (i = 0; i < current_nr_blocks; i++)
7590 : {
7591 346 : bb = EBB_FIRST_BB (i);
7592 :
7593 : /* While pipelining outer loops, skip bundling for loop
7594 : preheaders. Those will be rescheduled in the outer
7595 : loop. */
7596 346 : if (sel_is_loop_preheader_p (bb))
7597 : {
7598 74 : clear_outdated_rtx_info (bb);
7599 74 : continue;
7600 : }
7601 :
7602 272 : if (bitmap_bit_p (blocks_to_reschedule, bb->index))
7603 : {
7604 20 : flist_tail_init (new_fences);
7605 :
7606 20 : orig_max_seqno = init_seqno (blocks_to_reschedule, bb);
7607 :
7608 : /* Mark BB as head of the new ebb. */
7609 20 : bitmap_set_bit (forced_ebb_heads, bb->index);
7610 :
7611 20 : gcc_assert (fences == NULL);
7612 :
7613 20 : init_fences (bb_note (bb));
7614 :
7615 20 : sel_sched_region_2 (orig_max_seqno);
7616 :
7617 20 : do_p = true;
7618 20 : break;
7619 : }
7620 : }
7621 : }
7622 : }
7623 770 : }
7624 :
7625 : /* Schedule the RGN region. */
7626 : void
7627 782 : sel_sched_region (int rgn)
7628 : {
7629 782 : bool schedule_p;
7630 782 : bool reset_sched_cycles_p;
7631 :
7632 782 : if (sel_region_init (rgn))
7633 : return;
7634 :
7635 770 : if (sched_verbose >= 1)
7636 0 : sel_print ("Scheduling region %d\n", rgn);
7637 :
7638 770 : schedule_p = (!sched_is_disabled_for_current_region_p ()
7639 770 : && dbg_cnt (sel_sched_region_cnt));
7640 770 : reset_sched_cycles_p = pipelining_p;
7641 770 : if (schedule_p)
7642 770 : sel_sched_region_1 ();
7643 : else
7644 : {
7645 : /* Schedule always selecting the next insn to make the correct data
7646 : for bundling or other later passes. */
7647 0 : pipelining_p = false;
7648 0 : reset_sched_cycles_p = false;
7649 0 : force_next_insn = 1;
7650 0 : sel_sched_region_1 ();
7651 0 : force_next_insn = 0;
7652 : }
7653 770 : sel_region_finish (reset_sched_cycles_p);
7654 : }
7655 :
7656 : /* Perform global init for the scheduler. */
7657 : static void
7658 131 : sel_global_init (void)
7659 : {
7660 : /* Remove empty blocks: their presence can break assumptions elsewhere,
7661 : e.g. the logic to invoke update_liveness_on_insn in sel_region_init. */
7662 131 : cleanup_cfg (0);
7663 :
7664 131 : calculate_dominance_info (CDI_DOMINATORS);
7665 131 : alloc_sched_pools ();
7666 :
7667 : /* Setup the infos for sched_init. */
7668 131 : sel_setup_sched_infos ();
7669 131 : setup_sched_dump ();
7670 :
7671 131 : sched_rgn_init (false);
7672 131 : sched_init ();
7673 :
7674 131 : sched_init_bbs ();
7675 : /* Reset AFTER_RECOVERY if it has been set by the 1st scheduler pass. */
7676 131 : after_recovery = 0;
7677 131 : can_issue_more = issue_rate;
7678 :
7679 131 : sched_extend_target ();
7680 131 : sched_deps_init (true);
7681 131 : setup_nop_and_exit_insns ();
7682 131 : sel_extend_global_bb_info ();
7683 131 : init_lv_sets ();
7684 131 : init_hard_regs_data ();
7685 131 : }
7686 :
7687 : /* Free the global data of the scheduler. */
7688 : static void
7689 131 : sel_global_finish (void)
7690 : {
7691 131 : free_bb_note_pool ();
7692 131 : free_lv_sets ();
7693 131 : sel_finish_global_bb_info ();
7694 :
7695 131 : free_regset_pool ();
7696 131 : free_nop_and_exit_insns ();
7697 :
7698 131 : sched_rgn_finish ();
7699 131 : sched_deps_finish ();
7700 131 : sched_finish ();
7701 :
7702 131 : if (current_loops)
7703 43 : sel_finish_pipelining ();
7704 :
7705 131 : free_sched_pools ();
7706 131 : free_dominance_info (CDI_DOMINATORS);
7707 131 : }
7708 :
7709 : /* Return true when we need to skip selective scheduling. Used for debugging. */
7710 : bool
7711 131 : maybe_skip_selective_scheduling (void)
7712 : {
7713 131 : return ! dbg_cnt (sel_sched_cnt);
7714 : }
7715 :
7716 : /* The entry point. */
7717 : void
7718 131 : run_selective_scheduling (void)
7719 : {
7720 131 : int rgn;
7721 :
7722 131 : if (n_basic_blocks_for_fn (cfun) == NUM_FIXED_BLOCKS)
7723 : return;
7724 :
7725 131 : sel_global_init ();
7726 :
7727 1044 : for (rgn = 0; rgn < nr_regions; rgn++)
7728 782 : sel_sched_region (rgn);
7729 :
7730 131 : sel_global_finish ();
7731 : }
7732 :
7733 : #endif
|