1/* Scheduler hooks for IA-32 which implement bdver1-4 specific logic.
2 Copyright (C) 1988-2023 Free Software Foundation, Inc.
3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 3, or (at your option)
9any later version.
10
11GCC is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along 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. */
46static 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. */
50static int core2i7_ifetch_block_size;
51
52/* Maximum number of instructions decoder can handle per cycle.
53 '6' for Core 2/i7. */
54static int core2i7_ifetch_block_max_insns;
55
56typedef struct ix86_first_cycle_multipass_data_ *
57 ix86_first_cycle_multipass_data_t;
58typedef 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. */
63static 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. */
67static void
68core2i7_first_cycle_multipass_init (void *_data)
69{
70 ix86_first_cycle_multipass_data_t data
71 = (ix86_first_cycle_multipass_data_t) _data;
72
73 data->ifetch_block_len = 0;
74 data->ifetch_block_n_insns = 0;
75 data->ready_try_change = NULL;
76 data->ready_try_change_size = 0;
77}
78
79/* Advancing the cycle; reset ifetch block counts. */
80static void
81core2i7_dfa_post_advance_cycle (void)
82{
83 ix86_first_cycle_multipass_data_t data = ix86_first_cycle_multipass_data;
84
85 gcc_assert (data->ifetch_block_n_insns <= core2i7_ifetch_block_max_insns);
86
87 data->ifetch_block_len = 0;
88 data->ifetch_block_n_insns = 0;
89}
90
91/* Filter out insns from ready_try that the core will not be able to issue
92 on current cycle due to decoder. */
93static void
94core2i7_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 while (n_ready--)
99 {
100 rtx_insn *insn;
101 int insn_size;
102
103 if (ready_try[n_ready])
104 continue;
105
106 insn = get_ready_element (n_ready);
107 insn_size = ix86_min_insn_size (insn);
108
109 if (/* If this is a too long an insn for a secondary decoder ... */
110 (!first_cycle_insn_p
111 && insn_size > core2i7_secondary_decoder_max_insn_size)
112 /* ... or it would not fit into the ifetch block ... */
113 || data->ifetch_block_len + insn_size > core2i7_ifetch_block_size
114 /* ... or the decoder is full already ... */
115 || data->ifetch_block_n_insns + 1 > core2i7_ifetch_block_max_insns)
116 /* ... mask the insn out. */
117 {
118 ready_try[n_ready] = 1;
119
120 if (data->ready_try_change)
121 bitmap_set_bit (map: data->ready_try_change, bitno: n_ready);
122 }
123 }
124}
125
126/* Prepare for a new round of multipass lookahead scheduling. */
127static void
128core2i7_first_cycle_multipass_begin (void *_data,
129 signed char *ready_try, int n_ready,
130 bool first_cycle_insn_p)
131{
132 ix86_first_cycle_multipass_data_t data
133 = (ix86_first_cycle_multipass_data_t) _data;
134 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 data->ifetch_block_len = prev_data->ifetch_block_len;
139 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 core2i7_first_cycle_multipass_filter_ready_try (data, ready_try, n_ready,
144 first_cycle_insn_p);
145}
146
147/* INSN is being issued in current solution. Account for its impact on
148 the decoder model. */
149static void
150core2i7_first_cycle_multipass_issue (void *_data,
151 signed char *ready_try, int n_ready,
152 rtx_insn *insn, const void *_prev_data)
153{
154 ix86_first_cycle_multipass_data_t data
155 = (ix86_first_cycle_multipass_data_t) _data;
156 const_ix86_first_cycle_multipass_data_t prev_data
157 = (const_ix86_first_cycle_multipass_data_t) _prev_data;
158
159 int insn_size = ix86_min_insn_size (insn);
160
161 data->ifetch_block_len = prev_data->ifetch_block_len + insn_size;
162 data->ifetch_block_n_insns = prev_data->ifetch_block_n_insns + 1;
163 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 if (!data->ready_try_change)
168 {
169 data->ready_try_change = sbitmap_alloc (n_ready);
170 data->ready_try_change_size = n_ready;
171 }
172 else if (data->ready_try_change_size < n_ready)
173 {
174 data->ready_try_change = sbitmap_resize (data->ready_try_change,
175 n_ready, 0);
176 data->ready_try_change_size = n_ready;
177 }
178 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 core2i7_first_cycle_multipass_filter_ready_try (data, ready_try, n_ready,
183 first_cycle_insn_p: false);
184}
185
186/* Revert the effect on ready_try. */
187static void
188core2i7_first_cycle_multipass_backtrack (const void *_data,
189 signed char *ready_try,
190 int n_ready ATTRIBUTE_UNUSED)
191{
192 const_ix86_first_cycle_multipass_data_t data
193 = (const_ix86_first_cycle_multipass_data_t) _data;
194 unsigned int i = 0;
195 sbitmap_iterator sbi;
196
197 gcc_assert (bitmap_last_set_bit (data->ready_try_change) < n_ready);
198 EXECUTE_IF_SET_IN_BITMAP (data->ready_try_change, 0, i, sbi)
199 {
200 ready_try[i] = 0;
201 }
202}
203
204/* Save the result of multipass lookahead scheduling for the next round. */
205static void
206core2i7_first_cycle_multipass_end (const void *_data)
207{
208 const_ix86_first_cycle_multipass_data_t data
209 = (const_ix86_first_cycle_multipass_data_t) _data;
210 ix86_first_cycle_multipass_data_t next_data
211 = ix86_first_cycle_multipass_data;
212
213 if (data != NULL)
214 {
215 next_data->ifetch_block_len = data->ifetch_block_len;
216 next_data->ifetch_block_n_insns = data->ifetch_block_n_insns;
217 }
218}
219
220/* Deallocate target data. */
221static void
222core2i7_first_cycle_multipass_fini (void *_data)
223{
224 ix86_first_cycle_multipass_data_t data
225 = (ix86_first_cycle_multipass_data_t) _data;
226
227 if (data->ready_try_change)
228 {
229 sbitmap_free (map: data->ready_try_change);
230 data->ready_try_change = NULL;
231 data->ready_try_change_size = 0;
232 }
233}
234
235void
236ix86_core2i7_init_hooks (void)
237{
238 targetm.sched.dfa_post_advance_cycle
239 = core2i7_dfa_post_advance_cycle;
240 targetm.sched.first_cycle_multipass_init
241 = core2i7_first_cycle_multipass_init;
242 targetm.sched.first_cycle_multipass_begin
243 = core2i7_first_cycle_multipass_begin;
244 targetm.sched.first_cycle_multipass_issue
245 = core2i7_first_cycle_multipass_issue;
246 targetm.sched.first_cycle_multipass_backtrack
247 = core2i7_first_cycle_multipass_backtrack;
248 targetm.sched.first_cycle_multipass_end
249 = core2i7_first_cycle_multipass_end;
250 targetm.sched.first_cycle_multipass_fini
251 = core2i7_first_cycle_multipass_fini;
252
253 /* Set decoder parameters. */
254 core2i7_secondary_decoder_max_insn_size = 8;
255 core2i7_ifetch_block_size = 16;
256 core2i7_ifetch_block_max_insns = 6;
257}
258

source code of gcc/config/i386/x86-tune-sched-core.cc