Home | History | Annotate | Line # | Download | only in i386
      1 /* Scheduler hooks for IA-32 which implement atom+ specific logic.
      2    Copyright (C) 1988-2022 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 /* Try to reorder ready list to take advantage of Atom pipelined IMUL
     39    execution. It is applied if
     40    (1) IMUL instruction is on the top of list;
     41    (2) There exists the only producer of independent IMUL instruction in
     42        ready list.
     43    Return index of IMUL producer if it was found and -1 otherwise.  */
     44 static int
     45 do_reorder_for_imul (rtx_insn **ready, int n_ready)
     46 {
     47   rtx_insn *insn;
     48   rtx set, insn1, insn2;
     49   sd_iterator_def sd_it;
     50   dep_t dep;
     51   int index = -1;
     52   int i;
     53 
     54   if (!TARGET_CPU_P (BONNELL))
     55     return index;
     56 
     57   /* Check that IMUL instruction is on the top of ready list.  */
     58   insn = ready[n_ready - 1];
     59   set = single_set (insn);
     60   if (!set)
     61     return index;
     62   if (!(GET_CODE (SET_SRC (set)) == MULT
     63       && GET_MODE (SET_SRC (set)) == SImode))
     64     return index;
     65 
     66   /* Search for producer of independent IMUL instruction.  */
     67   for (i = n_ready - 2; i >= 0; i--)
     68     {
     69       insn = ready[i];
     70       if (!NONDEBUG_INSN_P (insn))
     71 	continue;
     72       /* Skip IMUL instruction.  */
     73       insn2 = PATTERN (insn);
     74       if (GET_CODE (insn2) == PARALLEL)
     75 	insn2 = XVECEXP (insn2, 0, 0);
     76       if (GET_CODE (insn2) == SET
     77 	  && GET_CODE (SET_SRC (insn2)) == MULT
     78 	  && GET_MODE (SET_SRC (insn2)) == SImode)
     79 	continue;
     80 
     81       FOR_EACH_DEP (insn, SD_LIST_FORW, sd_it, dep)
     82 	{
     83 	  rtx con;
     84 	  con = DEP_CON (dep);
     85 	  if (!NONDEBUG_INSN_P (con))
     86 	    continue;
     87 	  insn1 = PATTERN (con);
     88 	  if (GET_CODE (insn1) == PARALLEL)
     89 	    insn1 = XVECEXP (insn1, 0, 0);
     90 
     91 	  if (GET_CODE (insn1) == SET
     92 	      && GET_CODE (SET_SRC (insn1)) == MULT
     93 	      && GET_MODE (SET_SRC (insn1)) == SImode)
     94 	    {
     95 	      sd_iterator_def sd_it1;
     96 	      dep_t dep1;
     97 	      /* Check if there is no other dependee for IMUL.  */
     98 	      index = i;
     99 	      FOR_EACH_DEP (con, SD_LIST_BACK, sd_it1, dep1)
    100 		{
    101 		  rtx pro;
    102 		  pro = DEP_PRO (dep1);
    103 		  if (!NONDEBUG_INSN_P (pro))
    104 		    continue;
    105 		  if (pro != insn)
    106 		    index = -1;
    107 		}
    108 	      if (index >= 0)
    109 		break;
    110 	    }
    111 	}
    112       if (index >= 0)
    113 	break;
    114     }
    115   return index;
    116 }
    117 
    118 /* Try to find the best candidate on the top of ready list if two insns
    119    have the same priority - candidate is best if its dependees were
    120    scheduled earlier. Applied for Silvermont only.
    121    Return true if top 2 insns must be interchanged.  */
    122 static bool
    123 swap_top_of_ready_list (rtx_insn **ready, int n_ready)
    124 {
    125   rtx_insn *top = ready[n_ready - 1];
    126   rtx_insn *next = ready[n_ready - 2];
    127   rtx set;
    128   sd_iterator_def sd_it;
    129   dep_t dep;
    130   int clock1 = -1;
    131   int clock2 = -1;
    132   #define INSN_TICK(INSN) (HID (INSN)->tick)
    133 
    134   if (!TARGET_CPU_P (SILVERMONT) && !TARGET_CPU_P (INTEL))
    135     return false;
    136 
    137   if (!NONDEBUG_INSN_P (top))
    138     return false;
    139   if (!NONJUMP_INSN_P (top))
    140     return false;
    141   if (!NONDEBUG_INSN_P (next))
    142     return false;
    143   if (!NONJUMP_INSN_P (next))
    144     return false;
    145   set = single_set (top);
    146   if (!set)
    147     return false;
    148   set = single_set (next);
    149   if (!set)
    150     return false;
    151 
    152   if (INSN_PRIORITY_KNOWN (top) && INSN_PRIORITY_KNOWN (next))
    153     {
    154       if (INSN_PRIORITY (top) != INSN_PRIORITY (next))
    155 	return false;
    156       /* Determine winner more precise.  */
    157       FOR_EACH_DEP (top, SD_LIST_RES_BACK, sd_it, dep)
    158 	{
    159 	  rtx pro;
    160 	  pro = DEP_PRO (dep);
    161 	  if (!NONDEBUG_INSN_P (pro))
    162 	    continue;
    163 	  if (INSN_TICK (pro) > clock1)
    164 	    clock1 = INSN_TICK (pro);
    165 	}
    166       FOR_EACH_DEP (next, SD_LIST_RES_BACK, sd_it, dep)
    167 	{
    168 	  rtx pro;
    169 	  pro = DEP_PRO (dep);
    170 	  if (!NONDEBUG_INSN_P (pro))
    171 	    continue;
    172 	  if (INSN_TICK (pro) > clock2)
    173 	    clock2 = INSN_TICK (pro);
    174 	}
    175 
    176       if (clock1 == clock2)
    177 	{
    178 	  /* Determine winner - load must win. */
    179 	  enum attr_memory memory1, memory2;
    180 	  memory1 = get_attr_memory (top);
    181 	  memory2 = get_attr_memory (next);
    182 	  if (memory2 == MEMORY_LOAD && memory1 != MEMORY_LOAD)
    183 	    return true;
    184 	}
    185 	return (bool) (clock2 < clock1);
    186     }
    187   return false;
    188   #undef INSN_TICK
    189 }
    190 
    191 /* Perform possible reodering of ready list for Atom/Silvermont only.
    192    Return issue rate.  */
    193 int
    194 ix86_atom_sched_reorder (FILE *dump, int sched_verbose, rtx_insn **ready,
    195 		         int *pn_ready, int clock_var)
    196 {
    197   int issue_rate = -1;
    198   int n_ready = *pn_ready;
    199   int i;
    200   rtx_insn *insn;
    201   int index = -1;
    202 
    203   /* Set up issue rate.  */
    204   issue_rate = ix86_issue_rate ();
    205 
    206   /* Do reodering for BONNELL/SILVERMONT only.  */
    207   if (!TARGET_CPU_P (BONNELL) && !TARGET_CPU_P (SILVERMONT)
    208       && !TARGET_CPU_P (INTEL))
    209     return issue_rate;
    210 
    211   /* Nothing to do if ready list contains only 1 instruction.  */
    212   if (n_ready <= 1)
    213     return issue_rate;
    214 
    215   /* Do reodering for post-reload scheduler only.  */
    216   if (!reload_completed)
    217     return issue_rate;
    218 
    219   if ((index = do_reorder_for_imul (ready, n_ready)) >= 0)
    220     {
    221       if (sched_verbose > 1)
    222 	fprintf (dump, ";;\tatom sched_reorder: put %d insn on top\n",
    223 		 INSN_UID (ready[index]));
    224 
    225       /* Put IMUL producer (ready[index]) at the top of ready list.  */
    226       insn = ready[index];
    227       for (i = index; i < n_ready - 1; i++)
    228 	ready[i] = ready[i + 1];
    229       ready[n_ready - 1] = insn;
    230       return issue_rate;
    231     }
    232 
    233   /* Skip selective scheduling since HID is not populated in it.  */
    234   if (clock_var != 0
    235       && !sel_sched_p ()
    236       && swap_top_of_ready_list (ready, n_ready))
    237     {
    238       if (sched_verbose > 1)
    239 	fprintf (dump, ";;\tslm sched_reorder: swap %d and %d insns\n",
    240 		 INSN_UID (ready[n_ready - 1]), INSN_UID (ready[n_ready - 2]));
    241       /* Swap 2 top elements of ready list.  */
    242       insn = ready[n_ready - 1];
    243       ready[n_ready - 1] = ready[n_ready - 2];
    244       ready[n_ready - 2] = insn;
    245     }
    246   return issue_rate;
    247 }
    248