LCOV - code coverage report
Current view: top level - gcc/config/i386 - x86-tune-sched-atom.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 69.6 % 115 80
Test Date: 2026-02-28 14:20:25 Functions: 100.0 % 3 3
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Scheduler hooks for IA-32 which implement atom+ specific logic.
       2              :    Copyright (C) 1988-2026 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         1108 : do_reorder_for_imul (rtx_insn **ready, int n_ready)
      46              : {
      47         1108 :   rtx_insn *insn;
      48         1108 :   rtx set, insn1, insn2;
      49         1108 :   sd_iterator_def sd_it;
      50         1108 :   dep_t dep;
      51         1108 :   int index = -1;
      52         1108 :   int i;
      53              : 
      54         1108 :   if (!TARGET_CPU_P (BONNELL))
      55              :     return index;
      56              : 
      57              :   /* Check that IMUL instruction is on the top of ready list.  */
      58          243 :   insn = ready[n_ready - 1];
      59          243 :   set = single_set (insn);
      60          243 :   if (!set)
      61              :     return index;
      62          242 :   if (!(GET_CODE (SET_SRC (set)) == MULT
      63            6 :       && GET_MODE (SET_SRC (set)) == SImode))
      64              :     return index;
      65              : 
      66              :   /* Search for producer of independent IMUL instruction.  */
      67            2 :   for (i = n_ready - 2; i >= 0; i--)
      68              :     {
      69            1 :       insn = ready[i];
      70            1 :       if (!NONDEBUG_INSN_P (insn))
      71            0 :         continue;
      72              :       /* Skip IMUL instruction.  */
      73            1 :       insn2 = PATTERN (insn);
      74            1 :       if (GET_CODE (insn2) == PARALLEL)
      75            1 :         insn2 = XVECEXP (insn2, 0, 0);
      76            1 :       if (GET_CODE (insn2) == SET
      77            1 :           && GET_CODE (SET_SRC (insn2)) == MULT
      78            0 :           && GET_MODE (SET_SRC (insn2)) == SImode)
      79            0 :         continue;
      80              : 
      81            1 :       FOR_EACH_DEP (insn, SD_LIST_FORW, sd_it, dep)
      82              :         {
      83            0 :           rtx con;
      84            0 :           con = DEP_CON (dep);
      85            0 :           if (!NONDEBUG_INSN_P (con))
      86            0 :             continue;
      87            0 :           insn1 = PATTERN (con);
      88            0 :           if (GET_CODE (insn1) == PARALLEL)
      89            0 :             insn1 = XVECEXP (insn1, 0, 0);
      90              : 
      91            0 :           if (GET_CODE (insn1) == SET
      92            0 :               && GET_CODE (SET_SRC (insn1)) == MULT
      93            0 :               && GET_MODE (SET_SRC (insn1)) == SImode)
      94              :             {
      95            0 :               sd_iterator_def sd_it1;
      96            0 :               dep_t dep1;
      97              :               /* Check if there is no other dependee for IMUL.  */
      98            0 :               index = i;
      99            0 :               FOR_EACH_DEP (con, SD_LIST_BACK, sd_it1, dep1)
     100              :                 {
     101            0 :                   rtx pro;
     102            0 :                   pro = DEP_PRO (dep1);
     103            0 :                   if (!NONDEBUG_INSN_P (pro))
     104            0 :                     continue;
     105            0 :                   if (pro != insn)
     106            0 :                     index = -1;
     107              :                 }
     108            0 :               if (index >= 0)
     109              :                 break;
     110              :             }
     111              :         }
     112            1 :       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          686 : swap_top_of_ready_list (rtx_insn **ready, int n_ready)
     124              : {
     125          686 :   rtx_insn *top = ready[n_ready - 1];
     126          686 :   rtx_insn *next = ready[n_ready - 2];
     127          686 :   rtx set;
     128          686 :   sd_iterator_def sd_it;
     129          686 :   dep_t dep;
     130          686 :   int clock1 = -1;
     131          686 :   int clock2 = -1;
     132              :   #define INSN_TICK(INSN) (HID (INSN)->tick)
     133              : 
     134          686 :   if (!TARGET_CPU_P (SILVERMONT) && !TARGET_CPU_P (INTEL))
     135              :     return false;
     136              : 
     137          568 :   if (!NONDEBUG_INSN_P (top))
     138              :     return false;
     139          568 :   if (!NONJUMP_INSN_P (top))
     140              :     return false;
     141          568 :   if (!NONDEBUG_INSN_P (next))
     142              :     return false;
     143          568 :   if (!NONJUMP_INSN_P (next))
     144              :     return false;
     145          568 :   set = single_set (top);
     146          568 :   if (!set)
     147              :     return false;
     148          567 :   set = single_set (next);
     149          567 :   if (!set)
     150              :     return false;
     151              : 
     152          559 :   if (INSN_PRIORITY_KNOWN (top) && INSN_PRIORITY_KNOWN (next))
     153              :     {
     154          559 :       if (INSN_PRIORITY (top) != INSN_PRIORITY (next))
     155              :         return false;
     156              :       /* Determine winner more precise.  */
     157          674 :       FOR_EACH_DEP (top, SD_LIST_RES_BACK, sd_it, dep)
     158              :         {
     159          329 :           rtx pro;
     160          329 :           pro = DEP_PRO (dep);
     161          329 :           if (!NONDEBUG_INSN_P (pro))
     162            1 :             continue;
     163          328 :           if (INSN_TICK (pro) > clock1)
     164          329 :             clock1 = INSN_TICK (pro);
     165              :         }
     166          733 :       FOR_EACH_DEP (next, SD_LIST_RES_BACK, sd_it, dep)
     167              :         {
     168          388 :           rtx pro;
     169          388 :           pro = DEP_PRO (dep);
     170          388 :           if (!NONDEBUG_INSN_P (pro))
     171            0 :             continue;
     172          388 :           if (INSN_TICK (pro) > clock2)
     173          388 :             clock2 = INSN_TICK (pro);
     174              :         }
     175              : 
     176          345 :       if (clock1 == clock2)
     177              :         {
     178              :           /* Determine winner - load must win. */
     179          271 :           enum attr_memory memory1, memory2;
     180          271 :           memory1 = get_attr_memory (top);
     181          271 :           memory2 = get_attr_memory (next);
     182          271 :           if (memory2 == MEMORY_LOAD && memory1 != MEMORY_LOAD)
     183              :             return true;
     184              :         }
     185          345 :         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     34932974 : ix86_atom_sched_reorder (FILE *dump, int sched_verbose, rtx_insn **ready,
     195              :                          int *pn_ready, int clock_var)
     196              : {
     197     34932974 :   int issue_rate = -1;
     198     34932974 :   int n_ready = *pn_ready;
     199     34932974 :   int i;
     200     34932974 :   rtx_insn *insn;
     201     34932974 :   int index = -1;
     202              : 
     203              :   /* Set up issue rate.  */
     204     34932974 :   issue_rate = ix86_issue_rate ();
     205              : 
     206              :   /* Do reodering for BONNELL/SILVERMONT only.  */
     207     34932974 :   if (!TARGET_CPU_P (BONNELL) && !TARGET_CPU_P (SILVERMONT)
     208     34930972 :       && !TARGET_CPU_P (INTEL))
     209              :     return issue_rate;
     210              : 
     211              :   /* Nothing to do if ready list contains only 1 instruction.  */
     212         3908 :   if (n_ready <= 1)
     213              :     return issue_rate;
     214              : 
     215              :   /* Do reodering for post-reload scheduler only.  */
     216         1111 :   if (!reload_completed)
     217              :     return issue_rate;
     218              : 
     219         1108 :   if ((index = do_reorder_for_imul (ready, n_ready)) >= 0)
     220              :     {
     221            0 :       if (sched_verbose > 1)
     222            0 :         fprintf (dump, ";;\tatom sched_reorder: put %d insn on top\n",
     223            0 :                  INSN_UID (ready[index]));
     224              : 
     225              :       /* Put IMUL producer (ready[index]) at the top of ready list.  */
     226            0 :       insn = ready[index];
     227            0 :       for (i = index; i < n_ready - 1; i++)
     228            0 :         ready[i] = ready[i + 1];
     229            0 :       ready[n_ready - 1] = insn;
     230            0 :       return issue_rate;
     231              :     }
     232              : 
     233              :   /* Skip selective scheduling since HID is not populated in it.  */
     234         1108 :   if (clock_var != 0
     235          708 :       && !sel_sched_p ()
     236         1794 :       && swap_top_of_ready_list (ready, n_ready))
     237              :     {
     238           43 :       if (sched_verbose > 1)
     239            0 :         fprintf (dump, ";;\tslm sched_reorder: swap %d and %d insns\n",
     240            0 :                  INSN_UID (ready[n_ready - 1]), INSN_UID (ready[n_ready - 2]));
     241              :       /* Swap 2 top elements of ready list.  */
     242           43 :       insn = ready[n_ready - 1];
     243           43 :       ready[n_ready - 1] = ready[n_ready - 2];
     244           43 :       ready[n_ready - 2] = insn;
     245              :     }
     246              :   return issue_rate;
     247              : }
        

Generated by: LCOV version 2.4-beta

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,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.