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