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