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