Branch data Line data Source code
1 : : /* Scheduler hooks for IA-32 which implement Core 2 specific logic.
2 : : Copyright (C) 1988-2025 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 : :
39 : : /* Model decoder of Core 2/i7.
40 : : Below hooks for multipass scheduling (see haifa-sched.cc:max_issue)
41 : : track the instruction fetch block boundaries and make sure that long
42 : : (9+ bytes) instructions are assigned to D0. */
43 : :
44 : : /* Maximum length of an insn that can be handled by
45 : : a secondary decoder unit. '8' for Core 2/i7. */
46 : : static int core2i7_secondary_decoder_max_insn_size;
47 : :
48 : : /* Ifetch block size, i.e., number of bytes decoder reads per cycle.
49 : : '16' for Core 2/i7. */
50 : : static int core2i7_ifetch_block_size;
51 : :
52 : : /* Maximum number of instructions decoder can handle per cycle.
53 : : '6' for Core 2/i7. */
54 : : static int core2i7_ifetch_block_max_insns;
55 : :
56 : : typedef struct ix86_first_cycle_multipass_data_ *
57 : : ix86_first_cycle_multipass_data_t;
58 : : typedef const struct ix86_first_cycle_multipass_data_ *
59 : : const_ix86_first_cycle_multipass_data_t;
60 : :
61 : : /* A variable to store target state across calls to max_issue within
62 : : one cycle. */
63 : : static struct ix86_first_cycle_multipass_data_ _ix86_first_cycle_multipass_data,
64 : : *ix86_first_cycle_multipass_data = &_ix86_first_cycle_multipass_data;
65 : :
66 : : /* Initialize DATA. */
67 : : static void
68 : 105729762 : core2i7_first_cycle_multipass_init (void *_data)
69 : : {
70 : 105729762 : ix86_first_cycle_multipass_data_t data
71 : : = (ix86_first_cycle_multipass_data_t) _data;
72 : :
73 : 105729762 : data->ifetch_block_len = 0;
74 : 105729762 : data->ifetch_block_n_insns = 0;
75 : 105729762 : data->ready_try_change = NULL;
76 : 105729762 : data->ready_try_change_size = 0;
77 : 105729762 : }
78 : :
79 : : /* Advancing the cycle; reset ifetch block counts. */
80 : : static void
81 : 43499931 : core2i7_dfa_post_advance_cycle (void)
82 : : {
83 : 43499931 : ix86_first_cycle_multipass_data_t data = ix86_first_cycle_multipass_data;
84 : :
85 : 43499931 : gcc_assert (data->ifetch_block_n_insns <= core2i7_ifetch_block_max_insns);
86 : :
87 : 43499931 : data->ifetch_block_len = 0;
88 : 43499931 : data->ifetch_block_n_insns = 0;
89 : 43499931 : }
90 : :
91 : : /* Filter out insns from ready_try that the core will not be able to issue
92 : : on current cycle due to decoder. */
93 : : static void
94 : 152392724 : core2i7_first_cycle_multipass_filter_ready_try
95 : : (const_ix86_first_cycle_multipass_data_t data,
96 : : signed char *ready_try, int n_ready, bool first_cycle_insn_p)
97 : : {
98 : 575467466 : while (n_ready--)
99 : : {
100 : 423074742 : rtx_insn *insn;
101 : 423074742 : int insn_size;
102 : :
103 : 423074742 : if (ready_try[n_ready])
104 : 187298213 : continue;
105 : :
106 : 235776529 : insn = get_ready_element (n_ready);
107 : 235776529 : insn_size = ix86_min_insn_size (insn);
108 : :
109 : 235776529 : if (/* If this is a too long an insn for a secondary decoder ... */
110 : : (!first_cycle_insn_p
111 : 183737061 : && insn_size > core2i7_secondary_decoder_max_insn_size)
112 : : /* ... or it would not fit into the ifetch block ... */
113 : 213277580 : || data->ifetch_block_len + insn_size > core2i7_ifetch_block_size
114 : : /* ... or the decoder is full already ... */
115 : 146418589 : || data->ifetch_block_n_insns + 1 > core2i7_ifetch_block_max_insns)
116 : : /* ... mask the insn out. */
117 : : {
118 : 89358012 : ready_try[n_ready] = 1;
119 : :
120 : 89358012 : if (data->ready_try_change)
121 : 82332828 : bitmap_set_bit (data->ready_try_change, n_ready);
122 : : }
123 : : }
124 : 152392724 : }
125 : :
126 : : /* Prepare for a new round of multipass lookahead scheduling. */
127 : : static void
128 : 51767194 : core2i7_first_cycle_multipass_begin (void *_data,
129 : : signed char *ready_try, int n_ready,
130 : : bool first_cycle_insn_p)
131 : : {
132 : 51767194 : ix86_first_cycle_multipass_data_t data
133 : : = (ix86_first_cycle_multipass_data_t) _data;
134 : 51767194 : const_ix86_first_cycle_multipass_data_t prev_data
135 : : = ix86_first_cycle_multipass_data;
136 : :
137 : : /* Restore the state from the end of the previous round. */
138 : 51767194 : data->ifetch_block_len = prev_data->ifetch_block_len;
139 : 51767194 : data->ifetch_block_n_insns = prev_data->ifetch_block_n_insns;
140 : :
141 : : /* Filter instructions that cannot be issued on current cycle due to
142 : : decoder restrictions. */
143 : 51767194 : core2i7_first_cycle_multipass_filter_ready_try (data, ready_try, n_ready,
144 : : first_cycle_insn_p);
145 : 51767194 : }
146 : :
147 : : /* INSN is being issued in current solution. Account for its impact on
148 : : the decoder model. */
149 : : static void
150 : 100625530 : core2i7_first_cycle_multipass_issue (void *_data,
151 : : signed char *ready_try, int n_ready,
152 : : rtx_insn *insn, const void *_prev_data)
153 : : {
154 : 100625530 : ix86_first_cycle_multipass_data_t data
155 : : = (ix86_first_cycle_multipass_data_t) _data;
156 : 100625530 : const_ix86_first_cycle_multipass_data_t prev_data
157 : : = (const_ix86_first_cycle_multipass_data_t) _prev_data;
158 : :
159 : 100625530 : int insn_size = ix86_min_insn_size (insn);
160 : :
161 : 100625530 : data->ifetch_block_len = prev_data->ifetch_block_len + insn_size;
162 : 100625530 : data->ifetch_block_n_insns = prev_data->ifetch_block_n_insns + 1;
163 : 100625530 : gcc_assert (data->ifetch_block_len <= core2i7_ifetch_block_size
164 : : && data->ifetch_block_n_insns <= core2i7_ifetch_block_max_insns);
165 : :
166 : : /* Allocate or resize the bitmap for storing INSN's effect on ready_try. */
167 : 100625530 : if (!data->ready_try_change)
168 : : {
169 : 14931172 : data->ready_try_change = sbitmap_alloc (n_ready);
170 : 14931172 : data->ready_try_change_size = n_ready;
171 : : }
172 : 85694358 : else if (data->ready_try_change_size < n_ready)
173 : : {
174 : 976709 : data->ready_try_change = sbitmap_resize (data->ready_try_change,
175 : : n_ready, 0);
176 : 976709 : data->ready_try_change_size = n_ready;
177 : : }
178 : 100625530 : bitmap_clear (data->ready_try_change);
179 : :
180 : : /* Filter out insns from ready_try that the core will not be able to issue
181 : : on current cycle due to decoder. */
182 : 100625530 : core2i7_first_cycle_multipass_filter_ready_try (data, ready_try, n_ready,
183 : : false);
184 : 100625530 : }
185 : :
186 : : /* Revert the effect on ready_try. */
187 : : static void
188 : 48310453 : core2i7_first_cycle_multipass_backtrack (const void *_data,
189 : : signed char *ready_try,
190 : : int n_ready ATTRIBUTE_UNUSED)
191 : : {
192 : 48310453 : const_ix86_first_cycle_multipass_data_t data
193 : : = (const_ix86_first_cycle_multipass_data_t) _data;
194 : 48310453 : unsigned int i = 0;
195 : 48310453 : sbitmap_iterator sbi;
196 : :
197 : 48310453 : gcc_assert (bitmap_last_set_bit (data->ready_try_change) < n_ready);
198 : 177556623 : EXECUTE_IF_SET_IN_BITMAP (data->ready_try_change, 0, i, sbi)
199 : : {
200 : 80935717 : ready_try[i] = 0;
201 : : }
202 : 48310453 : }
203 : :
204 : : /* Save the result of multipass lookahead scheduling for the next round. */
205 : : static void
206 : 51767194 : core2i7_first_cycle_multipass_end (const void *_data)
207 : : {
208 : 51767194 : const_ix86_first_cycle_multipass_data_t data
209 : : = (const_ix86_first_cycle_multipass_data_t) _data;
210 : 51767194 : ix86_first_cycle_multipass_data_t next_data
211 : : = ix86_first_cycle_multipass_data;
212 : :
213 : 51767194 : if (data != NULL)
214 : : {
215 : 49753493 : next_data->ifetch_block_len = data->ifetch_block_len;
216 : 49753493 : next_data->ifetch_block_n_insns = data->ifetch_block_n_insns;
217 : : }
218 : 51767194 : }
219 : :
220 : : /* Deallocate target data. */
221 : : static void
222 : 105729762 : core2i7_first_cycle_multipass_fini (void *_data)
223 : : {
224 : 105729762 : ix86_first_cycle_multipass_data_t data
225 : : = (ix86_first_cycle_multipass_data_t) _data;
226 : :
227 : 105729762 : if (data->ready_try_change)
228 : : {
229 : 14931172 : sbitmap_free (data->ready_try_change);
230 : 14931172 : data->ready_try_change = NULL;
231 : 14931172 : data->ready_try_change_size = 0;
232 : : }
233 : 105729762 : }
234 : :
235 : : void
236 : 881361 : ix86_core2i7_init_hooks (void)
237 : : {
238 : 881361 : targetm.sched.dfa_post_advance_cycle
239 : 881361 : = core2i7_dfa_post_advance_cycle;
240 : 881361 : targetm.sched.first_cycle_multipass_init
241 : 881361 : = core2i7_first_cycle_multipass_init;
242 : 881361 : targetm.sched.first_cycle_multipass_begin
243 : 881361 : = core2i7_first_cycle_multipass_begin;
244 : 881361 : targetm.sched.first_cycle_multipass_issue
245 : 881361 : = core2i7_first_cycle_multipass_issue;
246 : 881361 : targetm.sched.first_cycle_multipass_backtrack
247 : 881361 : = core2i7_first_cycle_multipass_backtrack;
248 : 881361 : targetm.sched.first_cycle_multipass_end
249 : 881361 : = core2i7_first_cycle_multipass_end;
250 : 881361 : targetm.sched.first_cycle_multipass_fini
251 : 881361 : = core2i7_first_cycle_multipass_fini;
252 : :
253 : : /* Set decoder parameters. */
254 : 881361 : core2i7_secondary_decoder_max_insn_size = 8;
255 : 881361 : core2i7_ifetch_block_size = 16;
256 : 881361 : core2i7_ifetch_block_max_insns = 6;
257 : 881361 : }
|