Home | History | Annotate | Line # | Download | only in i386
      1  1.1  mrg /* Scheduler hooks for IA-32 which implement atom+ specific logic.
      2  1.1  mrg    Copyright (C) 1988-2022 Free Software Foundation, Inc.
      3  1.1  mrg 
      4  1.1  mrg This file is part of GCC.
      5  1.1  mrg 
      6  1.1  mrg GCC is free software; you can redistribute it and/or modify
      7  1.1  mrg it under the terms of the GNU General Public License as published by
      8  1.1  mrg the Free Software Foundation; either version 3, or (at your option)
      9  1.1  mrg any later version.
     10  1.1  mrg 
     11  1.1  mrg GCC is distributed in the hope that it will be useful,
     12  1.1  mrg but WITHOUT ANY WARRANTY; without even the implied warranty of
     13  1.1  mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14  1.1  mrg GNU General Public License for more details.
     15  1.1  mrg 
     16  1.1  mrg You should have received a copy of the GNU General Public License
     17  1.1  mrg along with GCC; see the file COPYING3.  If not see
     18  1.1  mrg <http://www.gnu.org/licenses/>.  */
     19  1.1  mrg 
     20  1.1  mrg #define IN_TARGET_CODE 1
     21  1.1  mrg 
     22  1.1  mrg #include "config.h"
     23  1.1  mrg #include "system.h"
     24  1.1  mrg #include "coretypes.h"
     25  1.1  mrg #include "backend.h"
     26  1.1  mrg #include "rtl.h"
     27  1.1  mrg #include "tree.h"
     28  1.1  mrg #include "cfghooks.h"
     29  1.1  mrg #include "tm_p.h"
     30  1.1  mrg #include "insn-config.h"
     31  1.1  mrg #include "insn-attr.h"
     32  1.1  mrg #include "recog.h"
     33  1.1  mrg #include "target.h"
     34  1.1  mrg #include "rtl-iter.h"
     35  1.1  mrg #include "regset.h"
     36  1.1  mrg #include "sched-int.h"
     37  1.1  mrg 
     38  1.1  mrg /* Try to reorder ready list to take advantage of Atom pipelined IMUL
     39  1.1  mrg    execution. It is applied if
     40  1.1  mrg    (1) IMUL instruction is on the top of list;
     41  1.1  mrg    (2) There exists the only producer of independent IMUL instruction in
     42  1.1  mrg        ready list.
     43  1.1  mrg    Return index of IMUL producer if it was found and -1 otherwise.  */
     44  1.1  mrg static int
     45  1.1  mrg do_reorder_for_imul (rtx_insn **ready, int n_ready)
     46  1.1  mrg {
     47  1.1  mrg   rtx_insn *insn;
     48  1.1  mrg   rtx set, insn1, insn2;
     49  1.1  mrg   sd_iterator_def sd_it;
     50  1.1  mrg   dep_t dep;
     51  1.1  mrg   int index = -1;
     52  1.1  mrg   int i;
     53  1.1  mrg 
     54  1.1  mrg   if (!TARGET_CPU_P (BONNELL))
     55  1.1  mrg     return index;
     56  1.1  mrg 
     57  1.1  mrg   /* Check that IMUL instruction is on the top of ready list.  */
     58  1.1  mrg   insn = ready[n_ready - 1];
     59  1.1  mrg   set = single_set (insn);
     60  1.1  mrg   if (!set)
     61  1.1  mrg     return index;
     62  1.1  mrg   if (!(GET_CODE (SET_SRC (set)) == MULT
     63  1.1  mrg       && GET_MODE (SET_SRC (set)) == SImode))
     64  1.1  mrg     return index;
     65  1.1  mrg 
     66  1.1  mrg   /* Search for producer of independent IMUL instruction.  */
     67  1.1  mrg   for (i = n_ready - 2; i >= 0; i--)
     68  1.1  mrg     {
     69  1.1  mrg       insn = ready[i];
     70  1.1  mrg       if (!NONDEBUG_INSN_P (insn))
     71  1.1  mrg 	continue;
     72  1.1  mrg       /* Skip IMUL instruction.  */
     73  1.1  mrg       insn2 = PATTERN (insn);
     74  1.1  mrg       if (GET_CODE (insn2) == PARALLEL)
     75  1.1  mrg 	insn2 = XVECEXP (insn2, 0, 0);
     76  1.1  mrg       if (GET_CODE (insn2) == SET
     77  1.1  mrg 	  && GET_CODE (SET_SRC (insn2)) == MULT
     78  1.1  mrg 	  && GET_MODE (SET_SRC (insn2)) == SImode)
     79  1.1  mrg 	continue;
     80  1.1  mrg 
     81  1.1  mrg       FOR_EACH_DEP (insn, SD_LIST_FORW, sd_it, dep)
     82  1.1  mrg 	{
     83  1.1  mrg 	  rtx con;
     84  1.1  mrg 	  con = DEP_CON (dep);
     85  1.1  mrg 	  if (!NONDEBUG_INSN_P (con))
     86  1.1  mrg 	    continue;
     87  1.1  mrg 	  insn1 = PATTERN (con);
     88  1.1  mrg 	  if (GET_CODE (insn1) == PARALLEL)
     89  1.1  mrg 	    insn1 = XVECEXP (insn1, 0, 0);
     90  1.1  mrg 
     91  1.1  mrg 	  if (GET_CODE (insn1) == SET
     92  1.1  mrg 	      && GET_CODE (SET_SRC (insn1)) == MULT
     93  1.1  mrg 	      && GET_MODE (SET_SRC (insn1)) == SImode)
     94  1.1  mrg 	    {
     95  1.1  mrg 	      sd_iterator_def sd_it1;
     96  1.1  mrg 	      dep_t dep1;
     97  1.1  mrg 	      /* Check if there is no other dependee for IMUL.  */
     98  1.1  mrg 	      index = i;
     99  1.1  mrg 	      FOR_EACH_DEP (con, SD_LIST_BACK, sd_it1, dep1)
    100  1.1  mrg 		{
    101  1.1  mrg 		  rtx pro;
    102  1.1  mrg 		  pro = DEP_PRO (dep1);
    103  1.1  mrg 		  if (!NONDEBUG_INSN_P (pro))
    104  1.1  mrg 		    continue;
    105  1.1  mrg 		  if (pro != insn)
    106  1.1  mrg 		    index = -1;
    107  1.1  mrg 		}
    108  1.1  mrg 	      if (index >= 0)
    109  1.1  mrg 		break;
    110  1.1  mrg 	    }
    111  1.1  mrg 	}
    112  1.1  mrg       if (index >= 0)
    113  1.1  mrg 	break;
    114  1.1  mrg     }
    115  1.1  mrg   return index;
    116  1.1  mrg }
    117  1.1  mrg 
    118  1.1  mrg /* Try to find the best candidate on the top of ready list if two insns
    119  1.1  mrg    have the same priority - candidate is best if its dependees were
    120  1.1  mrg    scheduled earlier. Applied for Silvermont only.
    121  1.1  mrg    Return true if top 2 insns must be interchanged.  */
    122  1.1  mrg static bool
    123  1.1  mrg swap_top_of_ready_list (rtx_insn **ready, int n_ready)
    124  1.1  mrg {
    125  1.1  mrg   rtx_insn *top = ready[n_ready - 1];
    126  1.1  mrg   rtx_insn *next = ready[n_ready - 2];
    127  1.1  mrg   rtx set;
    128  1.1  mrg   sd_iterator_def sd_it;
    129  1.1  mrg   dep_t dep;
    130  1.1  mrg   int clock1 = -1;
    131  1.1  mrg   int clock2 = -1;
    132  1.1  mrg   #define INSN_TICK(INSN) (HID (INSN)->tick)
    133  1.1  mrg 
    134  1.1  mrg   if (!TARGET_CPU_P (SILVERMONT) && !TARGET_CPU_P (INTEL))
    135  1.1  mrg     return false;
    136  1.1  mrg 
    137  1.1  mrg   if (!NONDEBUG_INSN_P (top))
    138  1.1  mrg     return false;
    139  1.1  mrg   if (!NONJUMP_INSN_P (top))
    140  1.1  mrg     return false;
    141  1.1  mrg   if (!NONDEBUG_INSN_P (next))
    142  1.1  mrg     return false;
    143  1.1  mrg   if (!NONJUMP_INSN_P (next))
    144  1.1  mrg     return false;
    145  1.1  mrg   set = single_set (top);
    146  1.1  mrg   if (!set)
    147  1.1  mrg     return false;
    148  1.1  mrg   set = single_set (next);
    149  1.1  mrg   if (!set)
    150  1.1  mrg     return false;
    151  1.1  mrg 
    152  1.1  mrg   if (INSN_PRIORITY_KNOWN (top) && INSN_PRIORITY_KNOWN (next))
    153  1.1  mrg     {
    154  1.1  mrg       if (INSN_PRIORITY (top) != INSN_PRIORITY (next))
    155  1.1  mrg 	return false;
    156  1.1  mrg       /* Determine winner more precise.  */
    157  1.1  mrg       FOR_EACH_DEP (top, SD_LIST_RES_BACK, sd_it, dep)
    158  1.1  mrg 	{
    159  1.1  mrg 	  rtx pro;
    160  1.1  mrg 	  pro = DEP_PRO (dep);
    161  1.1  mrg 	  if (!NONDEBUG_INSN_P (pro))
    162  1.1  mrg 	    continue;
    163  1.1  mrg 	  if (INSN_TICK (pro) > clock1)
    164  1.1  mrg 	    clock1 = INSN_TICK (pro);
    165  1.1  mrg 	}
    166  1.1  mrg       FOR_EACH_DEP (next, SD_LIST_RES_BACK, sd_it, dep)
    167  1.1  mrg 	{
    168  1.1  mrg 	  rtx pro;
    169  1.1  mrg 	  pro = DEP_PRO (dep);
    170  1.1  mrg 	  if (!NONDEBUG_INSN_P (pro))
    171  1.1  mrg 	    continue;
    172  1.1  mrg 	  if (INSN_TICK (pro) > clock2)
    173  1.1  mrg 	    clock2 = INSN_TICK (pro);
    174  1.1  mrg 	}
    175  1.1  mrg 
    176  1.1  mrg       if (clock1 == clock2)
    177  1.1  mrg 	{
    178  1.1  mrg 	  /* Determine winner - load must win. */
    179  1.1  mrg 	  enum attr_memory memory1, memory2;
    180  1.1  mrg 	  memory1 = get_attr_memory (top);
    181  1.1  mrg 	  memory2 = get_attr_memory (next);
    182  1.1  mrg 	  if (memory2 == MEMORY_LOAD && memory1 != MEMORY_LOAD)
    183  1.1  mrg 	    return true;
    184  1.1  mrg 	}
    185  1.1  mrg 	return (bool) (clock2 < clock1);
    186  1.1  mrg     }
    187  1.1  mrg   return false;
    188  1.1  mrg   #undef INSN_TICK
    189  1.1  mrg }
    190  1.1  mrg 
    191  1.1  mrg /* Perform possible reodering of ready list for Atom/Silvermont only.
    192  1.1  mrg    Return issue rate.  */
    193  1.1  mrg int
    194  1.1  mrg ix86_atom_sched_reorder (FILE *dump, int sched_verbose, rtx_insn **ready,
    195  1.1  mrg 		         int *pn_ready, int clock_var)
    196  1.1  mrg {
    197  1.1  mrg   int issue_rate = -1;
    198  1.1  mrg   int n_ready = *pn_ready;
    199  1.1  mrg   int i;
    200  1.1  mrg   rtx_insn *insn;
    201  1.1  mrg   int index = -1;
    202  1.1  mrg 
    203  1.1  mrg   /* Set up issue rate.  */
    204  1.1  mrg   issue_rate = ix86_issue_rate ();
    205  1.1  mrg 
    206  1.1  mrg   /* Do reodering for BONNELL/SILVERMONT only.  */
    207  1.1  mrg   if (!TARGET_CPU_P (BONNELL) && !TARGET_CPU_P (SILVERMONT)
    208  1.1  mrg       && !TARGET_CPU_P (INTEL))
    209  1.1  mrg     return issue_rate;
    210  1.1  mrg 
    211  1.1  mrg   /* Nothing to do if ready list contains only 1 instruction.  */
    212  1.1  mrg   if (n_ready <= 1)
    213  1.1  mrg     return issue_rate;
    214  1.1  mrg 
    215  1.1  mrg   /* Do reodering for post-reload scheduler only.  */
    216  1.1  mrg   if (!reload_completed)
    217  1.1  mrg     return issue_rate;
    218  1.1  mrg 
    219  1.1  mrg   if ((index = do_reorder_for_imul (ready, n_ready)) >= 0)
    220  1.1  mrg     {
    221  1.1  mrg       if (sched_verbose > 1)
    222  1.1  mrg 	fprintf (dump, ";;\tatom sched_reorder: put %d insn on top\n",
    223  1.1  mrg 		 INSN_UID (ready[index]));
    224  1.1  mrg 
    225  1.1  mrg       /* Put IMUL producer (ready[index]) at the top of ready list.  */
    226  1.1  mrg       insn = ready[index];
    227  1.1  mrg       for (i = index; i < n_ready - 1; i++)
    228  1.1  mrg 	ready[i] = ready[i + 1];
    229  1.1  mrg       ready[n_ready - 1] = insn;
    230  1.1  mrg       return issue_rate;
    231  1.1  mrg     }
    232  1.1  mrg 
    233  1.1  mrg   /* Skip selective scheduling since HID is not populated in it.  */
    234  1.1  mrg   if (clock_var != 0
    235  1.1  mrg       && !sel_sched_p ()
    236  1.1  mrg       && swap_top_of_ready_list (ready, n_ready))
    237  1.1  mrg     {
    238  1.1  mrg       if (sched_verbose > 1)
    239  1.1  mrg 	fprintf (dump, ";;\tslm sched_reorder: swap %d and %d insns\n",
    240  1.1  mrg 		 INSN_UID (ready[n_ready - 1]), INSN_UID (ready[n_ready - 2]));
    241  1.1  mrg       /* Swap 2 top elements of ready list.  */
    242  1.1  mrg       insn = ready[n_ready - 1];
    243  1.1  mrg       ready[n_ready - 1] = ready[n_ready - 2];
    244  1.1  mrg       ready[n_ready - 2] = insn;
    245  1.1  mrg     }
    246  1.1  mrg   return issue_rate;
    247  1.1  mrg }
    248