x86-tune-sched-atom.cc revision 1.1 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