1/* Scheduler hooks for IA-32 which implement bdver1-4 specific logic.
2 Copyright (C) 1988-2017 Free Software Foundation, Inc.
3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 3, or (at your option)
9any later version.
10
11GCC is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along 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 "rtl.h"
25#include "tree.h"
26#include "cfghooks.h"
27#include "tm_p.h"
28#include "insn-config.h"
29#include "insn-attr.h"
30#include "recog.h"
31#include "target.h"
32#include "rtl-iter.h"
33#include "regset.h"
34#include "sched-int.h"
35
36/* The size of the dispatch window is the total number of bytes of
37 object code allowed in a window. */
38#define DISPATCH_WINDOW_SIZE 16
39
40/* Number of dispatch windows considered for scheduling. */
41#define MAX_DISPATCH_WINDOWS 3
42
43/* Maximum number of instructions in a window. */
44#define MAX_INSN 4
45
46/* Maximum number of immediate operands in a window. */
47#define MAX_IMM 4
48
49/* Maximum number of immediate bits allowed in a window. */
50#define MAX_IMM_SIZE 128
51
52/* Maximum number of 32 bit immediates allowed in a window. */
53#define MAX_IMM_32 4
54
55/* Maximum number of 64 bit immediates allowed in a window. */
56#define MAX_IMM_64 2
57
58/* Maximum total of loads or prefetches allowed in a window. */
59#define MAX_LOAD 2
60
61/* Maximum total of stores allowed in a window. */
62#define MAX_STORE 1
63
64#undef BIG
65#define BIG 100
66
67
68/* Dispatch groups. Istructions that affect the mix in a dispatch window. */
69enum dispatch_group {
70 disp_no_group = 0,
71 disp_load,
72 disp_store,
73 disp_load_store,
74 disp_prefetch,
75 disp_imm,
76 disp_imm_32,
77 disp_imm_64,
78 disp_branch,
79 disp_cmp,
80 disp_jcc,
81 disp_last
82};
83
84/* Number of allowable groups in a dispatch window. It is an array
85 indexed by dispatch_group enum. 100 is used as a big number,
86 because the number of these kind of operations does not have any
87 effect in dispatch window, but we need them for other reasons in
88 the table. */
89static unsigned int num_allowable_groups[disp_last] = {
90 0, 2, 1, 1, 2, 4, 4, 2, 1, BIG, BIG
91};
92
93char group_name[disp_last + 1][16] = {
94 "disp_no_group", "disp_load", "disp_store", "disp_load_store",
95 "disp_prefetch", "disp_imm", "disp_imm_32", "disp_imm_64",
96 "disp_branch", "disp_cmp", "disp_jcc", "disp_last"
97};
98
99/* Instruction path. */
100enum insn_path {
101 no_path = 0,
102 path_single, /* Single micro op. */
103 path_double, /* Double micro op. */
104 path_multi, /* Instructions with more than 2 micro op.. */
105 last_path
106};
107
108/* sched_insn_info defines a window to the instructions scheduled in
109 the basic block. It contains a pointer to the insn_info table and
110 the instruction scheduled.
111
112 Windows are allocated for each basic block and are linked
113 together. */
114typedef struct sched_insn_info_s {
115 rtx insn;
116 enum dispatch_group group;
117 enum insn_path path;
118 int byte_len;
119 int imm_bytes;
120} sched_insn_info;
121
122/* Linked list of dispatch windows. This is a two way list of
123 dispatch windows of a basic block. It contains information about
124 the number of uops in the window and the total number of
125 instructions and of bytes in the object code for this dispatch
126 window. */
127typedef struct dispatch_windows_s {
128 int num_insn; /* Number of insn in the window. */
129 int num_uops; /* Number of uops in the window. */
130 int window_size; /* Number of bytes in the window. */
131 int window_num; /* Window number between 0 or 1. */
132 int num_imm; /* Number of immediates in an insn. */
133 int num_imm_32; /* Number of 32 bit immediates in an insn. */
134 int num_imm_64; /* Number of 64 bit immediates in an insn. */
135 int imm_size; /* Total immediates in the window. */
136 int num_loads; /* Total memory loads in the window. */
137 int num_stores; /* Total memory stores in the window. */
138 int violation; /* Violation exists in window. */
139 sched_insn_info *window; /* Pointer to the window. */
140 struct dispatch_windows_s *next;
141 struct dispatch_windows_s *prev;
142} dispatch_windows;
143
144/* Immediate valuse used in an insn. */
145typedef struct imm_info_s
146 {
147 int imm;
148 int imm32;
149 int imm64;
150 } imm_info;
151
152static dispatch_windows *dispatch_window_list;
153static dispatch_windows *dispatch_window_list1;
154
155/* Get dispatch group of insn. */
156
157static enum dispatch_group
158get_mem_group (rtx_insn *insn)
159{
160 enum attr_memory memory;
161
162 if (INSN_CODE (insn) < 0)
163 return disp_no_group;
164 memory = get_attr_memory (insn);
165 if (memory == MEMORY_STORE)
166 return disp_store;
167
168 if (memory == MEMORY_LOAD)
169 return disp_load;
170
171 if (memory == MEMORY_BOTH)
172 return disp_load_store;
173
174 return disp_no_group;
175}
176
177/* Return true if insn is a compare instruction. */
178
179static bool
180is_cmp (rtx_insn *insn)
181{
182 enum attr_type type;
183
184 type = get_attr_type (insn);
185 return (type == TYPE_TEST
186 || type == TYPE_ICMP
187 || type == TYPE_FCMP
188 || GET_CODE (PATTERN (insn)) == COMPARE);
189}
190
191/* Return true if a dispatch violation encountered. */
192
193static bool
194dispatch_violation (void)
195{
196 if (dispatch_window_list->next)
197 return dispatch_window_list->next->violation;
198 return dispatch_window_list->violation;
199}
200
201/* Return true if insn is a branch instruction. */
202
203static bool
204is_branch (rtx_insn *insn)
205{
206 return (CALL_P (insn) || JUMP_P (insn));
207}
208
209/* Return true if insn is a prefetch instruction. */
210
211static bool
212is_prefetch (rtx_insn *insn)
213{
214 return NONJUMP_INSN_P (insn) && GET_CODE (PATTERN (insn)) == PREFETCH;
215}
216
217/* This function initializes a dispatch window and the list container holding a
218 pointer to the window. */
219
220static void
221init_window (int window_num)
222{
223 int i;
224 dispatch_windows *new_list;
225
226 if (window_num == 0)
227 new_list = dispatch_window_list;
228 else
229 new_list = dispatch_window_list1;
230
231 new_list->num_insn = 0;
232 new_list->num_uops = 0;
233 new_list->window_size = 0;
234 new_list->next = NULL;
235 new_list->prev = NULL;
236 new_list->window_num = window_num;
237 new_list->num_imm = 0;
238 new_list->num_imm_32 = 0;
239 new_list->num_imm_64 = 0;
240 new_list->imm_size = 0;
241 new_list->num_loads = 0;
242 new_list->num_stores = 0;
243 new_list->violation = false;
244
245 for (i = 0; i < MAX_INSN; i++)
246 {
247 new_list->window[i].insn = NULL;
248 new_list->window[i].group = disp_no_group;
249 new_list->window[i].path = no_path;
250 new_list->window[i].byte_len = 0;
251 new_list->window[i].imm_bytes = 0;
252 }
253 return;
254}
255
256/* This function allocates and initializes a dispatch window and the
257 list container holding a pointer to the window. */
258
259static dispatch_windows *
260allocate_window (void)
261{
262 dispatch_windows *new_list = XNEW (struct dispatch_windows_s);
263 new_list->window = XNEWVEC (struct sched_insn_info_s, MAX_INSN + 1);
264
265 return new_list;
266}
267
268/* This routine initializes the dispatch scheduling information. It
269 initiates building dispatch scheduler tables and constructs the
270 first dispatch window. */
271
272static void
273init_dispatch_sched (void)
274{
275 /* Allocate a dispatch list and a window. */
276 dispatch_window_list = allocate_window ();
277 dispatch_window_list1 = allocate_window ();
278 init_window (0);
279 init_window (1);
280}
281
282/* This function returns true if a branch is detected. End of a basic block
283 does not have to be a branch, but here we assume only branches end a
284 window. */
285
286static bool
287is_end_basic_block (enum dispatch_group group)
288{
289 return group == disp_branch;
290}
291
292/* This function is called when the end of a window processing is reached. */
293
294static void
295process_end_window (void)
296{
297 gcc_assert (dispatch_window_list->num_insn <= MAX_INSN);
298 if (dispatch_window_list->next)
299 {
300 gcc_assert (dispatch_window_list1->num_insn <= MAX_INSN);
301 gcc_assert (dispatch_window_list->window_size
302 + dispatch_window_list1->window_size <= 48);
303 init_window (1);
304 }
305 init_window (0);
306}
307
308/* Allocates a new dispatch window and adds it to WINDOW_LIST.
309 WINDOW_NUM is either 0 or 1. A maximum of two windows are generated
310 for 48 bytes of instructions. Note that these windows are not dispatch
311 windows that their sizes are DISPATCH_WINDOW_SIZE. */
312
313static dispatch_windows *
314allocate_next_window (int window_num)
315{
316 if (window_num == 0)
317 {
318 if (dispatch_window_list->next)
319 init_window (1);
320 init_window (0);
321 return dispatch_window_list;
322 }
323
324 dispatch_window_list->next = dispatch_window_list1;
325 dispatch_window_list1->prev = dispatch_window_list;
326
327 return dispatch_window_list1;
328}
329
330/* Compute number of immediate operands of an instruction. */
331
332static void
333find_constant (rtx in_rtx, imm_info *imm_values)
334{
335 if (INSN_P (in_rtx))
336 in_rtx = PATTERN (in_rtx);
337 subrtx_iterator::array_type array;
338 FOR_EACH_SUBRTX (iter, array, in_rtx, ALL)
339 if (const_rtx x = *iter)
340 switch (GET_CODE (x))
341 {
342 case CONST:
343 case SYMBOL_REF:
344 case CONST_INT:
345 (imm_values->imm)++;
346 if (x86_64_immediate_operand (CONST_CAST_RTX (x), SImode))
347 (imm_values->imm32)++;
348 else
349 (imm_values->imm64)++;
350 break;
351
352 case CONST_DOUBLE:
353 case CONST_WIDE_INT:
354 (imm_values->imm)++;
355 (imm_values->imm64)++;
356 break;
357
358 case CODE_LABEL:
359 if (LABEL_KIND (x) == LABEL_NORMAL)
360 {
361 (imm_values->imm)++;
362 (imm_values->imm32)++;
363 }
364 break;
365
366 default:
367 break;
368 }
369}
370
371/* Return total size of immediate operands of an instruction along with number
372 of corresponding immediate-operands. It initializes its parameters to zero
373 befor calling FIND_CONSTANT.
374 INSN is the input instruction. IMM is the total of immediates.
375 IMM32 is the number of 32 bit immediates. IMM64 is the number of 64
376 bit immediates. */
377
378static int
379get_num_immediates (rtx_insn *insn, int *imm, int *imm32, int *imm64)
380{
381 imm_info imm_values = {0, 0, 0};
382
383 find_constant (insn, &imm_values);
384 *imm = imm_values.imm;
385 *imm32 = imm_values.imm32;
386 *imm64 = imm_values.imm64;
387 return imm_values.imm32 * 4 + imm_values.imm64 * 8;
388}
389
390/* This function indicates if an operand of an instruction is an
391 immediate. */
392
393static bool
394has_immediate (rtx_insn *insn)
395{
396 int num_imm_operand;
397 int num_imm32_operand;
398 int num_imm64_operand;
399
400 if (insn)
401 return get_num_immediates (insn, &num_imm_operand, &num_imm32_operand,
402 &num_imm64_operand);
403 return false;
404}
405
406/* Return single or double path for instructions. */
407
408static enum insn_path
409get_insn_path (rtx_insn *insn)
410{
411 enum attr_amdfam10_decode path = get_attr_amdfam10_decode (insn);
412
413 if ((int)path == 0)
414 return path_single;
415
416 if ((int)path == 1)
417 return path_double;
418
419 return path_multi;
420}
421
422/* Return insn dispatch group. */
423
424static enum dispatch_group
425get_insn_group (rtx_insn *insn)
426{
427 enum dispatch_group group = get_mem_group (insn);
428 if (group)
429 return group;
430
431 if (is_branch (insn))
432 return disp_branch;
433
434 if (is_cmp (insn))
435 return disp_cmp;
436
437 if (has_immediate (insn))
438 return disp_imm;
439
440 if (is_prefetch (insn))
441 return disp_prefetch;
442
443 return disp_no_group;
444}
445
446/* Count number of GROUP restricted instructions in a dispatch
447 window WINDOW_LIST. */
448
449static int
450count_num_restricted (rtx_insn *insn, dispatch_windows *window_list)
451{
452 enum dispatch_group group = get_insn_group (insn);
453 int imm_size;
454 int num_imm_operand;
455 int num_imm32_operand;
456 int num_imm64_operand;
457
458 if (group == disp_no_group)
459 return 0;
460
461 if (group == disp_imm)
462 {
463 imm_size = get_num_immediates (insn, &num_imm_operand, &num_imm32_operand,
464 &num_imm64_operand);
465 if (window_list->imm_size + imm_size > MAX_IMM_SIZE
466 || num_imm_operand + window_list->num_imm > MAX_IMM
467 || (num_imm32_operand > 0
468 && (window_list->num_imm_32 + num_imm32_operand > MAX_IMM_32
469 || window_list->num_imm_64 * 2 + num_imm32_operand > MAX_IMM_32))
470 || (num_imm64_operand > 0
471 && (window_list->num_imm_64 + num_imm64_operand > MAX_IMM_64
472 || window_list->num_imm_32 + num_imm64_operand * 2 > MAX_IMM_32))
473 || (window_list->imm_size + imm_size == MAX_IMM_SIZE
474 && num_imm64_operand > 0
475 && ((window_list->num_imm_64 > 0
476 && window_list->num_insn >= 2)
477 || window_list->num_insn >= 3)))
478 return BIG;
479
480 return 1;
481 }
482
483 if ((group == disp_load_store
484 && (window_list->num_loads >= MAX_LOAD
485 || window_list->num_stores >= MAX_STORE))
486 || ((group == disp_load
487 || group == disp_prefetch)
488 && window_list->num_loads >= MAX_LOAD)
489 || (group == disp_store
490 && window_list->num_stores >= MAX_STORE))
491 return BIG;
492
493 return 1;
494}
495
496/* This function returns true if insn satisfies dispatch rules on the
497 last window scheduled. */
498
499static bool
500fits_dispatch_window (rtx_insn *insn)
501{
502 dispatch_windows *window_list = dispatch_window_list;
503 dispatch_windows *window_list_next = dispatch_window_list->next;
504 unsigned int num_restrict;
505 enum dispatch_group group = get_insn_group (insn);
506 enum insn_path path = get_insn_path (insn);
507 int sum;
508
509 /* Make disp_cmp and disp_jcc get scheduled at the latest. These
510 instructions should be given the lowest priority in the
511 scheduling process in Haifa scheduler to make sure they will be
512 scheduled in the same dispatch window as the reference to them. */
513 if (group == disp_jcc || group == disp_cmp)
514 return false;
515
516 /* Check nonrestricted. */
517 if (group == disp_no_group || group == disp_branch)
518 return true;
519
520 /* Get last dispatch window. */
521 if (window_list_next)
522 window_list = window_list_next;
523
524 if (window_list->window_num == 1)
525 {
526 sum = window_list->prev->window_size + window_list->window_size;
527
528 if (sum == 32
529 || (ix86_min_insn_size (insn) + sum) >= 48)
530 /* Window 1 is full. Go for next window. */
531 return true;
532 }
533
534 num_restrict = count_num_restricted (insn, window_list);
535
536 if (num_restrict > num_allowable_groups[group])
537 return false;
538
539 /* See if it fits in the first window. */
540 if (window_list->window_num == 0)
541 {
542 /* The first widow should have only single and double path
543 uops. */
544 if (path == path_double
545 && (window_list->num_uops + 2) > MAX_INSN)
546 return false;
547 else if (path != path_single)
548 return false;
549 }
550 return true;
551}
552
553/* Add an instruction INSN with NUM_UOPS micro-operations to the
554 dispatch window WINDOW_LIST. */
555
556static void
557add_insn_window (rtx_insn *insn, dispatch_windows *window_list, int num_uops)
558{
559 int byte_len = ix86_min_insn_size (insn);
560 int num_insn = window_list->num_insn;
561 int imm_size;
562 sched_insn_info *window = window_list->window;
563 enum dispatch_group group = get_insn_group (insn);
564 enum insn_path path = get_insn_path (insn);
565 int num_imm_operand;
566 int num_imm32_operand;
567 int num_imm64_operand;
568
569 if (!window_list->violation && group != disp_cmp
570 && !fits_dispatch_window (insn))
571 window_list->violation = true;
572
573 imm_size = get_num_immediates (insn, &num_imm_operand, &num_imm32_operand,
574 &num_imm64_operand);
575
576 /* Initialize window with new instruction. */
577 window[num_insn].insn = insn;
578 window[num_insn].byte_len = byte_len;
579 window[num_insn].group = group;
580 window[num_insn].path = path;
581 window[num_insn].imm_bytes = imm_size;
582
583 window_list->window_size += byte_len;
584 window_list->num_insn = num_insn + 1;
585 window_list->num_uops = window_list->num_uops + num_uops;
586 window_list->imm_size += imm_size;
587 window_list->num_imm += num_imm_operand;
588 window_list->num_imm_32 += num_imm32_operand;
589 window_list->num_imm_64 += num_imm64_operand;
590
591 if (group == disp_store)
592 window_list->num_stores += 1;
593 else if (group == disp_load
594 || group == disp_prefetch)
595 window_list->num_loads += 1;
596 else if (group == disp_load_store)
597 {
598 window_list->num_stores += 1;
599 window_list->num_loads += 1;
600 }
601}
602
603/* Adds a scheduled instruction, INSN, to the current dispatch window.
604 If the total bytes of instructions or the number of instructions in
605 the window exceed allowable, it allocates a new window. */
606
607static void
608add_to_dispatch_window (rtx_insn *insn)
609{
610 int byte_len;
611 dispatch_windows *window_list;
612 dispatch_windows *next_list;
613 dispatch_windows *window0_list;
614 enum insn_path path;
615 enum dispatch_group insn_group;
616 bool insn_fits;
617 int num_insn;
618 int num_uops;
619 int window_num;
620 int insn_num_uops;
621 int sum;
622
623 if (INSN_CODE (insn) < 0)
624 return;
625
626 byte_len = ix86_min_insn_size (insn);
627 window_list = dispatch_window_list;
628 next_list = window_list->next;
629 path = get_insn_path (insn);
630 insn_group = get_insn_group (insn);
631
632 /* Get the last dispatch window. */
633 if (next_list)
634 window_list = dispatch_window_list->next;
635
636 if (path == path_single)
637 insn_num_uops = 1;
638 else if (path == path_double)
639 insn_num_uops = 2;
640 else
641 insn_num_uops = (int) path;
642
643 /* If current window is full, get a new window.
644 Window number zero is full, if MAX_INSN uops are scheduled in it.
645 Window number one is full, if window zero's bytes plus window
646 one's bytes is 32, or if the bytes of the new instruction added
647 to the total makes it greater than 48, or it has already MAX_INSN
648 instructions in it. */
649 num_insn = window_list->num_insn;
650 num_uops = window_list->num_uops;
651 window_num = window_list->window_num;
652 insn_fits = fits_dispatch_window (insn);
653
654 if (num_insn >= MAX_INSN
655 || num_uops + insn_num_uops > MAX_INSN
656 || !(insn_fits))
657 {
658 window_num = ~window_num & 1;
659 window_list = allocate_next_window (window_num);
660 }
661
662 if (window_num == 0)
663 {
664 add_insn_window (insn, window_list, insn_num_uops);
665 if (window_list->num_insn >= MAX_INSN
666 && insn_group == disp_branch)
667 {
668 process_end_window ();
669 return;
670 }
671 }
672 else if (window_num == 1)
673 {
674 window0_list = window_list->prev;
675 sum = window0_list->window_size + window_list->window_size;
676 if (sum == 32
677 || (byte_len + sum) >= 48)
678 {
679 process_end_window ();
680 window_list = dispatch_window_list;
681 }
682
683 add_insn_window (insn, window_list, insn_num_uops);
684 }
685 else
686 gcc_unreachable ();
687
688 if (is_end_basic_block (insn_group))
689 {
690 /* End of basic block is reached do end-basic-block process. */
691 process_end_window ();
692 return;
693 }
694}
695
696/* Print the dispatch window, WINDOW_NUM, to FILE. */
697
698DEBUG_FUNCTION static void
699debug_dispatch_window_file (FILE *file, int window_num)
700{
701 dispatch_windows *list;
702 int i;
703
704 if (window_num == 0)
705 list = dispatch_window_list;
706 else
707 list = dispatch_window_list1;
708
709 fprintf (file, "Window #%d:\n", list->window_num);
710 fprintf (file, " num_insn = %d, num_uops = %d, window_size = %d\n",
711 list->num_insn, list->num_uops, list->window_size);
712 fprintf (file, " num_imm = %d, num_imm_32 = %d, num_imm_64 = %d, imm_size = %d\n",
713 list->num_imm, list->num_imm_32, list->num_imm_64, list->imm_size);
714
715 fprintf (file, " num_loads = %d, num_stores = %d\n", list->num_loads,
716 list->num_stores);
717 fprintf (file, " insn info:\n");
718
719 for (i = 0; i < MAX_INSN; i++)
720 {
721 if (!list->window[i].insn)
722 break;
723 fprintf (file, " group[%d] = %s, insn[%d] = %p, path[%d] = %d byte_len[%d] = %d, imm_bytes[%d] = %d\n",
724 i, group_name[list->window[i].group],
725 i, (void *)list->window[i].insn,
726 i, list->window[i].path,
727 i, list->window[i].byte_len,
728 i, list->window[i].imm_bytes);
729 }
730}
731
732/* Print to stdout a dispatch window. */
733
734DEBUG_FUNCTION void
735debug_dispatch_window (int window_num)
736{
737 debug_dispatch_window_file (stdout, window_num);
738}
739
740/* Print INSN dispatch information to FILE. */
741
742DEBUG_FUNCTION static void
743debug_insn_dispatch_info_file (FILE *file, rtx_insn *insn)
744{
745 int byte_len;
746 enum insn_path path;
747 enum dispatch_group group;
748 int imm_size;
749 int num_imm_operand;
750 int num_imm32_operand;
751 int num_imm64_operand;
752
753 if (INSN_CODE (insn) < 0)
754 return;
755
756 byte_len = ix86_min_insn_size (insn);
757 path = get_insn_path (insn);
758 group = get_insn_group (insn);
759 imm_size = get_num_immediates (insn, &num_imm_operand, &num_imm32_operand,
760 &num_imm64_operand);
761
762 fprintf (file, " insn info:\n");
763 fprintf (file, " group = %s, path = %d, byte_len = %d\n",
764 group_name[group], path, byte_len);
765 fprintf (file, " num_imm = %d, num_imm_32 = %d, num_imm_64 = %d, imm_size = %d\n",
766 num_imm_operand, num_imm32_operand, num_imm64_operand, imm_size);
767}
768
769/* Print to STDERR the status of the ready list with respect to
770 dispatch windows. */
771
772DEBUG_FUNCTION void
773debug_ready_dispatch (void)
774{
775 int i;
776 int no_ready = number_in_ready ();
777
778 fprintf (stdout, "Number of ready: %d\n", no_ready);
779
780 for (i = 0; i < no_ready; i++)
781 debug_insn_dispatch_info_file (stdout, get_ready_element (i));
782}
783
784/* This routine is the driver of the dispatch scheduler. */
785
786void
787ix86_bd_do_dispatch (rtx_insn *insn, int mode)
788{
789 if (mode == DISPATCH_INIT)
790 init_dispatch_sched ();
791 else if (mode == ADD_TO_DISPATCH_WINDOW)
792 add_to_dispatch_window (insn);
793}
794
795/* Return TRUE if Dispatch Scheduling is supported. */
796
797bool
798ix86_bd_has_dispatch (rtx_insn *insn, int action)
799{
800 /* Current implementation of dispatch scheduler models buldozer only. */
801 if ((TARGET_BDVER1 || TARGET_BDVER2 || TARGET_BDVER3
802 || TARGET_BDVER4) && flag_dispatch_scheduler)
803 switch (action)
804 {
805 default:
806 return false;
807
808 case IS_DISPATCH_ON:
809 return true;
810
811 case IS_CMP:
812 return is_cmp (insn);
813
814 case DISPATCH_VIOLATION:
815 return dispatch_violation ();
816
817 case FITS_DISPATCH_WINDOW:
818 return fits_dispatch_window (insn);
819 }
820
821 return false;
822}
823