LCOV - code coverage report
Current view: top level - gcc/config/i386 - x86-tune-sched-bd.c (source / functions) Hit Total Coverage
Test: gcc.info Lines: 226 333 67.9 %
Date: 2020-03-28 11:57:23 Functions: 16 26 61.5 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /* Scheduler hooks for IA-32 which implement bdver1-4 specific logic.
       2                 :            :    Copyright (C) 1988-2020 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                 :         54 : get_mem_group (rtx_insn *insn)
     161                 :            : {
     162                 :         54 :   enum attr_memory memory;
     163                 :            : 
     164                 :         54 :   if (INSN_CODE (insn) < 0)
     165                 :            :     return disp_no_group;
     166                 :         54 :   memory = get_attr_memory (insn);
     167                 :         54 :   if (memory == MEMORY_STORE)
     168                 :            :     return disp_store;
     169                 :            : 
     170                 :         48 :   if (memory == MEMORY_LOAD)
     171                 :            :     return disp_load;
     172                 :            : 
     173                 :         42 :   if (memory == MEMORY_BOTH)
     174                 :          0 :     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                 :         38 : is_cmp (rtx_insn *insn)
     183                 :            : {
     184                 :         38 :   enum attr_type type;
     185                 :            : 
     186                 :         38 :   type = get_attr_type (insn);
     187                 :         38 :   return (type == TYPE_TEST
     188                 :         38 :           || type == TYPE_ICMP
     189                 :         38 :           || type == TYPE_FCMP
     190                 :         38 :           || GET_CODE (PATTERN (insn)) == COMPARE);
     191                 :            : }
     192                 :            : 
     193                 :            : /* Return true if a dispatch violation encountered.  */
     194                 :            : 
     195                 :            : static bool
     196                 :          0 : dispatch_violation (void)
     197                 :            : {
     198                 :          0 :   if (dispatch_window_list->next)
     199                 :          0 :     return dispatch_window_list->next->violation;
     200                 :          0 :   return dispatch_window_list->violation;
     201                 :            : }
     202                 :            : 
     203                 :            : /* Return true if insn is a branch instruction.  */
     204                 :            : 
     205                 :            : static bool
     206                 :         42 : is_branch (rtx_insn *insn)
     207                 :            : {
     208                 :         42 :   return (CALL_P (insn) || JUMP_P (insn));
     209                 :            : }
     210                 :            : 
     211                 :            : /* Return true if insn is a prefetch instruction.  */
     212                 :            : 
     213                 :            : static bool
     214                 :         32 : is_prefetch (rtx_insn *insn)
     215                 :            : {
     216                 :         32 :   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                 :          7 : init_window (int window_num)
     224                 :            : {
     225                 :          7 :   int i;
     226                 :          7 :   dispatch_windows *new_list;
     227                 :            : 
     228                 :          7 :   if (window_num == 0)
     229                 :          4 :     new_list = dispatch_window_list;
     230                 :            :   else
     231                 :          3 :     new_list = dispatch_window_list1;
     232                 :            : 
     233                 :          7 :   new_list->num_insn = 0;
     234                 :          7 :   new_list->num_uops = 0;
     235                 :          7 :   new_list->window_size = 0;
     236                 :          7 :   new_list->next = NULL;
     237                 :          7 :   new_list->prev = NULL;
     238                 :          7 :   new_list->window_num = window_num;
     239                 :          7 :   new_list->num_imm = 0;
     240                 :          7 :   new_list->num_imm_32 = 0;
     241                 :          7 :   new_list->num_imm_64 = 0;
     242                 :          7 :   new_list->imm_size = 0;
     243                 :          7 :   new_list->num_loads = 0;
     244                 :          7 :   new_list->num_stores = 0;
     245                 :          7 :   new_list->violation = false;
     246                 :            : 
     247                 :         35 :   for (i = 0; i < MAX_INSN; i++)
     248                 :            :     {
     249                 :         28 :       new_list->window[i].insn = NULL;
     250                 :         28 :       new_list->window[i].group = disp_no_group;
     251                 :         28 :       new_list->window[i].path = no_path;
     252                 :         28 :       new_list->window[i].byte_len = 0;
     253                 :         28 :       new_list->window[i].imm_bytes = 0;
     254                 :            :     }
     255                 :          7 :   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                 :          6 : allocate_window (void)
     263                 :            : {
     264                 :          6 :   dispatch_windows *new_list = XNEW (struct dispatch_windows_s);
     265                 :          6 :   new_list->window = XNEWVEC (struct sched_insn_info_s, MAX_INSN + 1);
     266                 :            : 
     267                 :          6 :   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                 :          3 : init_dispatch_sched (void)
     276                 :            : {
     277                 :            :   /* Allocate a dispatch list and a window.  */
     278                 :          3 :   dispatch_window_list = allocate_window ();
     279                 :          3 :   dispatch_window_list1 = allocate_window ();
     280                 :          3 :   init_window (0);
     281                 :          3 :   init_window (1);
     282                 :          3 : }
     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                 :         11 : is_end_basic_block (enum dispatch_group group)
     290                 :            : {
     291                 :         11 :   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                 :          1 : process_end_window (void)
     298                 :            : {
     299                 :          1 :   gcc_assert (dispatch_window_list->num_insn <= MAX_INSN);
     300                 :          1 :   if (dispatch_window_list->next)
     301                 :            :     {
     302                 :          0 :       gcc_assert (dispatch_window_list1->num_insn <= MAX_INSN);
     303                 :          0 :       gcc_assert (dispatch_window_list->window_size
     304                 :            :                   + dispatch_window_list1->window_size <= 48);
     305                 :          0 :       init_window (1);
     306                 :            :     }
     307                 :          1 :   init_window (0);
     308                 :          1 : }
     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                 :          1 : allocate_next_window (int window_num)
     317                 :            : {
     318                 :          1 :   if (window_num == 0)
     319                 :            :     {
     320                 :          0 :       if (dispatch_window_list->next)
     321                 :          0 :           init_window (1);
     322                 :          0 :       init_window (0);
     323                 :          0 :       return dispatch_window_list;
     324                 :            :     }
     325                 :            : 
     326                 :          1 :   dispatch_window_list->next = dispatch_window_list1;
     327                 :          1 :   dispatch_window_list1->prev = dispatch_window_list;
     328                 :            : 
     329                 :          1 :   return dispatch_window_list1;
     330                 :            : }
     331                 :            : 
     332                 :            : /* Compute number of immediate operands of an instruction.  */
     333                 :            : 
     334                 :            : static void
     335                 :         52 : find_constant (rtx in_rtx, imm_info *imm_values)
     336                 :            : {
     337                 :         52 :   if (INSN_P (in_rtx))
     338                 :         52 :     in_rtx = PATTERN (in_rtx);
     339                 :         52 :   subrtx_iterator::array_type array;
     340                 :        287 :   FOR_EACH_SUBRTX (iter, array, in_rtx, ALL)
     341                 :        235 :     if (const_rtx x = *iter)
     342                 :        235 :       switch (GET_CODE (x))
     343                 :            :         {
     344                 :         11 :         case CONST:
     345                 :         11 :         case SYMBOL_REF:
     346                 :         11 :         case CONST_INT:
     347                 :         11 :           (imm_values->imm)++;
     348                 :         11 :           if (x86_64_immediate_operand (CONST_CAST_RTX (x), SImode))
     349                 :         11 :             (imm_values->imm32)++;
     350                 :            :           else
     351                 :          0 :             (imm_values->imm64)++;
     352                 :            :           break;
     353                 :            : 
     354                 :          0 :         case CONST_DOUBLE:
     355                 :          0 :         case CONST_WIDE_INT:
     356                 :          0 :           (imm_values->imm)++;
     357                 :          0 :           (imm_values->imm64)++;
     358                 :          0 :           break;
     359                 :            : 
     360                 :          0 :         case CODE_LABEL:
     361                 :          0 :           if (LABEL_KIND (x) == LABEL_NORMAL)
     362                 :            :             {
     363                 :          0 :               (imm_values->imm)++;
     364                 :          0 :               (imm_values->imm32)++;
     365                 :            :             }
     366                 :            :           break;
     367                 :            : 
     368                 :            :         default:
     369                 :            :           break;
     370                 :            :         }
     371                 :         52 : }
     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                 :         52 : get_num_immediates (rtx_insn *insn, int *imm, int *imm32, int *imm64)
     382                 :            : {
     383                 :         52 :   imm_info imm_values = {0, 0, 0};
     384                 :            : 
     385                 :         52 :   find_constant (insn, &imm_values);
     386                 :         52 :   *imm = imm_values.imm;
     387                 :         52 :   *imm32 = imm_values.imm32;
     388                 :         52 :   *imm64 = imm_values.imm64;
     389                 :         52 :   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                 :         38 : has_immediate (rtx_insn *insn)
     397                 :            : {
     398                 :         38 :   int num_imm_operand;
     399                 :         38 :   int num_imm32_operand;
     400                 :         38 :   int num_imm64_operand;
     401                 :            : 
     402                 :          0 :   if (insn)
     403                 :          0 :     return get_num_immediates (insn, &num_imm_operand, &num_imm32_operand,
     404                 :          0 :                                &num_imm64_operand);
     405                 :            :   return false;
     406                 :            : }
     407                 :            : 
     408                 :            : /* Return single or double path for instructions.  */
     409                 :            : 
     410                 :            : static enum insn_path
     411                 :         48 : get_insn_path (rtx_insn *insn)
     412                 :            : {
     413                 :          0 :   enum attr_amdfam10_decode path = get_attr_amdfam10_decode (insn);
     414                 :            : 
     415                 :         48 :   if ((int)path == 0)
     416                 :            :     return path_single;
     417                 :            : 
     418                 :          0 :   if ((int)path == 1)
     419                 :          0 :     return path_double;
     420                 :            : 
     421                 :            :   return path_multi;
     422                 :            : }
     423                 :            : 
     424                 :            : /* Return insn dispatch group.  */
     425                 :            : 
     426                 :            : static enum dispatch_group
     427                 :         54 : get_insn_group (rtx_insn *insn)
     428                 :            : {
     429                 :         54 :   enum dispatch_group group = get_mem_group (insn);
     430                 :         54 :   if (group)
     431                 :            :     return group;
     432                 :            : 
     433                 :         42 :   if (is_branch (insn))
     434                 :            :     return disp_branch;
     435                 :            : 
     436                 :         38 :   if (is_cmp (insn))
     437                 :            :     return disp_cmp;
     438                 :            : 
     439                 :         38 :   if (has_immediate (insn))
     440                 :            :     return disp_imm;
     441                 :            : 
     442                 :         32 :   if (is_prefetch (insn))
     443                 :          0 :     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                 :          6 : count_num_restricted (rtx_insn *insn, dispatch_windows *window_list)
     453                 :            : {
     454                 :          6 :   enum dispatch_group group = get_insn_group (insn);
     455                 :          6 :   int imm_size;
     456                 :          6 :   int num_imm_operand;
     457                 :          6 :   int num_imm32_operand;
     458                 :          6 :   int num_imm64_operand;
     459                 :            : 
     460                 :          6 :   if (group == disp_no_group)
     461                 :            :     return 0;
     462                 :            : 
     463                 :          6 :   if (group == disp_imm)
     464                 :            :     {
     465                 :          2 :       imm_size = get_num_immediates (insn, &num_imm_operand, &num_imm32_operand,
     466                 :            :                               &num_imm64_operand);
     467                 :          2 :       if (window_list->imm_size + imm_size > MAX_IMM_SIZE
     468                 :          2 :           || num_imm_operand + window_list->num_imm > MAX_IMM
     469                 :          2 :           || (num_imm32_operand > 0
     470                 :          2 :               && (window_list->num_imm_32 + num_imm32_operand > MAX_IMM_32
     471                 :          2 :                   || window_list->num_imm_64 * 2 + num_imm32_operand > MAX_IMM_32))
     472                 :          2 :           || (num_imm64_operand > 0
     473                 :          0 :               && (window_list->num_imm_64 + num_imm64_operand > MAX_IMM_64
     474                 :          0 :                   || window_list->num_imm_32 + num_imm64_operand * 2 > MAX_IMM_32))
     475                 :          2 :           || (window_list->imm_size + imm_size == MAX_IMM_SIZE
     476                 :          0 :               && num_imm64_operand > 0
     477                 :          0 :               && ((window_list->num_imm_64 > 0
     478                 :          0 :                    && window_list->num_insn >= 2)
     479                 :          0 :                   || window_list->num_insn >= 3)))
     480                 :            :         return BIG;
     481                 :            : 
     482                 :          2 :       return 1;
     483                 :            :     }
     484                 :            : 
     485                 :          4 :   if ((group == disp_load_store
     486                 :          0 :        && (window_list->num_loads >= MAX_LOAD
     487                 :          0 :            || window_list->num_stores >= MAX_STORE))
     488                 :          4 :       || ((group == disp_load
     489                 :          4 :            || group == disp_prefetch)
     490                 :          2 :           && window_list->num_loads >= MAX_LOAD)
     491                 :          4 :       || (group == disp_store
     492                 :          2 :           && window_list->num_stores >= MAX_STORE))
     493                 :          0 :     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                 :         24 : fits_dispatch_window (rtx_insn *insn)
     503                 :            : {
     504                 :         24 :   dispatch_windows *window_list = dispatch_window_list;
     505                 :         24 :   dispatch_windows *window_list_next = dispatch_window_list->next;
     506                 :         24 :   unsigned int num_restrict;
     507                 :         24 :   enum dispatch_group group = get_insn_group (insn);
     508                 :         24 :   enum insn_path path = get_insn_path (insn);
     509                 :         24 :   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                 :         24 :   if (group == disp_jcc || group == disp_cmp)
     516                 :            :     return false;
     517                 :            : 
     518                 :            :   /* Check nonrestricted.  */
     519                 :         24 :   if (group == disp_no_group || group == disp_branch)
     520                 :            :     return true;
     521                 :            : 
     522                 :            :   /* Get last dispatch window.  */
     523                 :          6 :   if (window_list_next)
     524                 :          0 :     window_list = window_list_next;
     525                 :            : 
     526                 :          6 :   if (window_list->window_num == 1)
     527                 :            :     {
     528                 :          0 :       sum = window_list->prev->window_size + window_list->window_size;
     529                 :            : 
     530                 :          0 :       if (sum == 32
     531                 :          0 :           || (ix86_min_insn_size (insn) + sum) >= 48)
     532                 :            :         /* Window 1 is full.  Go for next window.  */
     533                 :          0 :         return true;
     534                 :            :     }
     535                 :            : 
     536                 :          6 :   num_restrict = count_num_restricted (insn, window_list);
     537                 :            : 
     538                 :          6 :   if (num_restrict > num_allowable_groups[group])
     539                 :            :     return false;
     540                 :            : 
     541                 :            :   /* See if it fits in the first window.  */
     542                 :          6 :   if (window_list->window_num == 0)
     543                 :            :     {
     544                 :            :       /* The first widow should have only single and double path
     545                 :            :          uops.  */
     546                 :          6 :       if (path == path_double
     547                 :          0 :           && (window_list->num_uops + 2) > MAX_INSN)
     548                 :            :         return false;
     549                 :          6 :       else if (path != path_single)
     550                 :          0 :         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                 :         12 : add_insn_window (rtx_insn *insn, dispatch_windows *window_list, int num_uops)
     560                 :            : {
     561                 :         12 :   int byte_len = ix86_min_insn_size (insn);
     562                 :         12 :   int num_insn = window_list->num_insn;
     563                 :         12 :   int imm_size;
     564                 :         12 :   sched_insn_info *window = window_list->window;
     565                 :         12 :   enum dispatch_group group = get_insn_group (insn);
     566                 :         12 :   enum insn_path path = get_insn_path (insn);
     567                 :         12 :   int num_imm_operand;
     568                 :         12 :   int num_imm32_operand;
     569                 :         12 :   int num_imm64_operand;
     570                 :            : 
     571                 :         12 :   if (!window_list->violation && group != disp_cmp
     572                 :         24 :       && !fits_dispatch_window (insn))
     573                 :          0 :     window_list->violation = true;
     574                 :            : 
     575                 :         12 :   imm_size = get_num_immediates (insn, &num_imm_operand, &num_imm32_operand,
     576                 :            :                                  &num_imm64_operand);
     577                 :            : 
     578                 :            :   /* Initialize window with new instruction.  */
     579                 :         12 :   window[num_insn].insn = insn;
     580                 :         12 :   window[num_insn].byte_len = byte_len;
     581                 :         12 :   window[num_insn].group = group;
     582                 :         12 :   window[num_insn].path = path;
     583                 :         12 :   window[num_insn].imm_bytes = imm_size;
     584                 :            : 
     585                 :         12 :   window_list->window_size += byte_len;
     586                 :         12 :   window_list->num_insn = num_insn + 1;
     587                 :         12 :   window_list->num_uops = window_list->num_uops + num_uops;
     588                 :         12 :   window_list->imm_size += imm_size;
     589                 :         12 :   window_list->num_imm += num_imm_operand;
     590                 :         12 :   window_list->num_imm_32 += num_imm32_operand;
     591                 :         12 :   window_list->num_imm_64 += num_imm64_operand;
     592                 :            : 
     593                 :         12 :   if (group == disp_store)
     594                 :          1 :     window_list->num_stores += 1;
     595                 :         11 :   else if (group == disp_load
     596                 :         11 :            || group == disp_prefetch)
     597                 :          1 :     window_list->num_loads += 1;
     598                 :         10 :   else if (group == disp_load_store)
     599                 :            :     {
     600                 :          0 :       window_list->num_stores += 1;
     601                 :          0 :       window_list->num_loads += 1;
     602                 :            :     }
     603                 :         12 : }
     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                 :         15 : add_to_dispatch_window (rtx_insn *insn)
     611                 :            : {
     612                 :         15 :   int byte_len;
     613                 :         15 :   dispatch_windows *window_list;
     614                 :         15 :   dispatch_windows *next_list;
     615                 :         15 :   dispatch_windows *window0_list;
     616                 :         15 :   enum insn_path path;
     617                 :         15 :   enum dispatch_group insn_group;
     618                 :         15 :   bool insn_fits;
     619                 :         15 :   int num_insn;
     620                 :         15 :   int num_uops;
     621                 :         15 :   int window_num;
     622                 :         15 :   int insn_num_uops;
     623                 :         15 :   int sum;
     624                 :            : 
     625                 :         15 :   if (INSN_CODE (insn) < 0)
     626                 :            :     return;
     627                 :            : 
     628                 :         12 :   byte_len = ix86_min_insn_size (insn);
     629                 :         12 :   window_list = dispatch_window_list;
     630                 :         12 :   next_list = window_list->next;
     631                 :         12 :   path = get_insn_path (insn);
     632                 :         12 :   insn_group = get_insn_group (insn);
     633                 :            : 
     634                 :            :   /* Get the last dispatch window.  */
     635                 :         12 :   if (next_list)
     636                 :          0 :       window_list = dispatch_window_list->next;
     637                 :            : 
     638                 :         12 :   if (path == path_single)
     639                 :            :     insn_num_uops = 1;
     640                 :          0 :   else if (path == path_double)
     641                 :            :     insn_num_uops = 2;
     642                 :            :   else
     643                 :          0 :     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                 :         12 :   num_insn = window_list->num_insn;
     652                 :         12 :   num_uops = window_list->num_uops;
     653                 :         12 :   window_num = window_list->window_num;
     654                 :         12 :   insn_fits = fits_dispatch_window (insn);
     655                 :            : 
     656                 :         12 :   if (num_insn >= MAX_INSN
     657                 :         11 :       || num_uops + insn_num_uops > MAX_INSN
     658                 :         11 :       || !(insn_fits))
     659                 :            :     {
     660                 :          1 :       window_num = ~window_num & 1;
     661                 :          1 :       window_list = allocate_next_window (window_num);
     662                 :            :     }
     663                 :            : 
     664                 :         12 :   if (window_num == 0)
     665                 :            :     {
     666                 :         11 :       add_insn_window (insn, window_list, insn_num_uops);
     667                 :         11 :       if (window_list->num_insn >= MAX_INSN
     668                 :          2 :           && insn_group == disp_branch)
     669                 :            :         {
     670                 :          1 :           process_end_window ();
     671                 :          1 :           return;
     672                 :            :         }
     673                 :            :     }
     674                 :          1 :   else if (window_num == 1)
     675                 :            :     {
     676                 :          1 :       window0_list = window_list->prev;
     677                 :          1 :       sum = window0_list->window_size + window_list->window_size;
     678                 :          1 :       if (sum == 32
     679                 :          1 :           || (byte_len + sum) >= 48)
     680                 :            :         {
     681                 :          0 :           process_end_window ();
     682                 :          0 :           window_list = dispatch_window_list;
     683                 :            :         }
     684                 :            : 
     685                 :          1 :       add_insn_window (insn, window_list, insn_num_uops);
     686                 :            :     }
     687                 :            :   else
     688                 :          0 :     gcc_unreachable ();
     689                 :            : 
     690                 :         11 :   if (is_end_basic_block (insn_group))
     691                 :            :     {
     692                 :            :       /* End of basic block is reached do end-basic-block process.  */
     693                 :          0 :       process_end_window ();
     694                 :          0 :       return;
     695                 :            :     }
     696                 :            : }
     697                 :            : 
     698                 :            : /* Print the dispatch window, WINDOW_NUM, to FILE.  */
     699                 :            : 
     700                 :            : DEBUG_FUNCTION static void
     701                 :          0 : debug_dispatch_window_file (FILE *file, int window_num)
     702                 :            : {
     703                 :          0 :   dispatch_windows *list;
     704                 :          0 :   int i;
     705                 :            : 
     706                 :          0 :   if (window_num == 0)
     707                 :          0 :     list = dispatch_window_list;
     708                 :            :   else
     709                 :          0 :     list = dispatch_window_list1;
     710                 :            : 
     711                 :          0 :   fprintf (file, "Window #%d:\n", list->window_num);
     712                 :          0 :   fprintf (file, "  num_insn = %d, num_uops = %d, window_size = %d\n",
     713                 :            :           list->num_insn, list->num_uops, list->window_size);
     714                 :          0 :   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                 :          0 :   fprintf (file, "  num_loads = %d, num_stores = %d\n", list->num_loads,
     718                 :            :           list->num_stores);
     719                 :          0 :   fprintf (file, " insn info:\n");
     720                 :            : 
     721                 :          0 :   for (i = 0; i < MAX_INSN; i++)
     722                 :            :     {
     723                 :          0 :       if (!list->window[i].insn)
     724                 :            :         break;
     725                 :          0 :       fprintf (file, "    group[%d] = %s, insn[%d] = %p, path[%d] = %d byte_len[%d] = %d, imm_bytes[%d] = %d\n",
     726                 :          0 :               i, group_name[list->window[i].group],
     727                 :            :               i, (void *)list->window[i].insn,
     728                 :          0 :               i, list->window[i].path,
     729                 :            :               i, list->window[i].byte_len,
     730                 :            :               i, list->window[i].imm_bytes);
     731                 :            :     }
     732                 :          0 : }
     733                 :            : 
     734                 :            : /* Print to stdout a dispatch window.  */
     735                 :            : 
     736                 :            : DEBUG_FUNCTION void
     737                 :          0 : debug_dispatch_window (int window_num)
     738                 :            : {
     739                 :          0 :   debug_dispatch_window_file (stdout, window_num);
     740                 :          0 : }
     741                 :            : 
     742                 :            : /* Print INSN dispatch information to FILE.  */
     743                 :            : 
     744                 :            : DEBUG_FUNCTION static void
     745                 :          0 : debug_insn_dispatch_info_file (FILE *file, rtx_insn *insn)
     746                 :            : {
     747                 :          0 :   int byte_len;
     748                 :          0 :   enum insn_path path;
     749                 :          0 :   enum dispatch_group group;
     750                 :          0 :   int imm_size;
     751                 :          0 :   int num_imm_operand;
     752                 :          0 :   int num_imm32_operand;
     753                 :          0 :   int num_imm64_operand;
     754                 :            : 
     755                 :          0 :   if (INSN_CODE (insn) < 0)
     756                 :          0 :     return;
     757                 :            : 
     758                 :          0 :   byte_len = ix86_min_insn_size (insn);
     759                 :          0 :   path = get_insn_path (insn);
     760                 :          0 :   group = get_insn_group (insn);
     761                 :          0 :   imm_size = get_num_immediates (insn, &num_imm_operand, &num_imm32_operand,
     762                 :            :                                  &num_imm64_operand);
     763                 :            : 
     764                 :          0 :   fprintf (file, " insn info:\n");
     765                 :          0 :   fprintf (file, "  group = %s, path = %d, byte_len = %d\n",
     766                 :          0 :            group_name[group], path, byte_len);
     767                 :          0 :   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                 :          0 : debug_ready_dispatch (void)
     776                 :            : {
     777                 :          0 :   int i;
     778                 :          0 :   int no_ready = number_in_ready ();
     779                 :            : 
     780                 :          0 :   fprintf (stdout, "Number of ready: %d\n", no_ready);
     781                 :            : 
     782                 :          0 :   for (i = 0; i < no_ready; i++)
     783                 :          0 :     debug_insn_dispatch_info_file (stdout, get_ready_element (i));
     784                 :          0 : }
     785                 :            : 
     786                 :            : /* This routine is the driver of the dispatch scheduler.  */
     787                 :            : 
     788                 :            : void
     789                 :         18 : ix86_bd_do_dispatch (rtx_insn *insn, int mode)
     790                 :            : {
     791                 :         18 :   if (mode == DISPATCH_INIT)
     792                 :          3 :     init_dispatch_sched ();
     793                 :         15 :   else if (mode == ADD_TO_DISPATCH_WINDOW)
     794                 :         15 :     add_to_dispatch_window (insn);
     795                 :         18 : }
     796                 :            : 
     797                 :            : /* Return TRUE if Dispatch Scheduling is supported.  */
     798                 :            : 
     799                 :            : bool
     800                 :   42267900 : ix86_bd_has_dispatch (rtx_insn *insn, int action)
     801                 :            : {
     802                 :            :   /* Current implementation of dispatch scheduler models buldozer only.  */
     803                 :   42267900 :   if ((TARGET_BDVER1 || TARGET_BDVER2 || TARGET_BDVER3
     804                 :   42267900 :       || TARGET_BDVER4) && flag_dispatch_scheduler)
     805                 :         37 :     switch (action)
     806                 :            :       {
     807                 :            :       default:
     808                 :            :         return false;
     809                 :            : 
     810                 :         37 :       case IS_DISPATCH_ON:
     811                 :         37 :         return true;
     812                 :            : 
     813                 :          0 :       case IS_CMP:
     814                 :          0 :         return is_cmp (insn);
     815                 :            : 
     816                 :          0 :       case DISPATCH_VIOLATION:
     817                 :          0 :         return dispatch_violation ();
     818                 :            : 
     819                 :          0 :       case FITS_DISPATCH_WINDOW:
     820                 :          0 :         return fits_dispatch_window (insn);
     821                 :            :       }
     822                 :            : 
     823                 :            :   return false;
     824                 :            : }

Generated by: LCOV version 1.0

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto --enable-host-shared. GCC test suite is run with the built compiler.