annotate gcc/config/i386/x86-tune-sched.c @ 111:04ced10e8804

gcc 7
author kono
date Fri, 27 Oct 2017 22:46:09 +0900
parents
children 84e7813d76e9
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 /* Scheduler hooks for IA-32 which implement CPU specific logic.
kono
parents:
diff changeset
2 Copyright (C) 1988-2017 Free Software Foundation, Inc.
kono
parents:
diff changeset
3
kono
parents:
diff changeset
4 This file is part of GCC.
kono
parents:
diff changeset
5
kono
parents:
diff changeset
6 GCC is free software; you can redistribute it and/or modify
kono
parents:
diff changeset
7 it under the terms of the GNU General Public License as published by
kono
parents:
diff changeset
8 the Free Software Foundation; either version 3, or (at your option)
kono
parents:
diff changeset
9 any later version.
kono
parents:
diff changeset
10
kono
parents:
diff changeset
11 GCC is distributed in the hope that it will be useful,
kono
parents:
diff changeset
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
kono
parents:
diff changeset
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
kono
parents:
diff changeset
14 GNU General Public License for more details.
kono
parents:
diff changeset
15
kono
parents:
diff changeset
16 You should have received a copy of the GNU General Public License
kono
parents:
diff changeset
17 along with GCC; see the file COPYING3. If not see
kono
parents:
diff changeset
18 <http://www.gnu.org/licenses/>. */
kono
parents:
diff changeset
19
kono
parents:
diff changeset
20 #include "config.h"
kono
parents:
diff changeset
21 #include "system.h"
kono
parents:
diff changeset
22 #include "coretypes.h"
kono
parents:
diff changeset
23 #include "backend.h"
kono
parents:
diff changeset
24 #include "rtl.h"
kono
parents:
diff changeset
25 #include "tree.h"
kono
parents:
diff changeset
26 #include "cfghooks.h"
kono
parents:
diff changeset
27 #include "tm_p.h"
kono
parents:
diff changeset
28 #include "insn-config.h"
kono
parents:
diff changeset
29 #include "insn-attr.h"
kono
parents:
diff changeset
30 #include "recog.h"
kono
parents:
diff changeset
31 #include "target.h"
kono
parents:
diff changeset
32
kono
parents:
diff changeset
33 /* Return the maximum number of instructions a cpu can issue. */
kono
parents:
diff changeset
34
kono
parents:
diff changeset
35 int
kono
parents:
diff changeset
36 ix86_issue_rate (void)
kono
parents:
diff changeset
37 {
kono
parents:
diff changeset
38 switch (ix86_tune)
kono
parents:
diff changeset
39 {
kono
parents:
diff changeset
40 case PROCESSOR_PENTIUM:
kono
parents:
diff changeset
41 case PROCESSOR_LAKEMONT:
kono
parents:
diff changeset
42 case PROCESSOR_BONNELL:
kono
parents:
diff changeset
43 case PROCESSOR_SILVERMONT:
kono
parents:
diff changeset
44 case PROCESSOR_KNL:
kono
parents:
diff changeset
45 case PROCESSOR_KNM:
kono
parents:
diff changeset
46 case PROCESSOR_INTEL:
kono
parents:
diff changeset
47 case PROCESSOR_K6:
kono
parents:
diff changeset
48 case PROCESSOR_BTVER2:
kono
parents:
diff changeset
49 case PROCESSOR_PENTIUM4:
kono
parents:
diff changeset
50 case PROCESSOR_NOCONA:
kono
parents:
diff changeset
51 return 2;
kono
parents:
diff changeset
52
kono
parents:
diff changeset
53 case PROCESSOR_PENTIUMPRO:
kono
parents:
diff changeset
54 case PROCESSOR_ATHLON:
kono
parents:
diff changeset
55 case PROCESSOR_K8:
kono
parents:
diff changeset
56 case PROCESSOR_AMDFAM10:
kono
parents:
diff changeset
57 case PROCESSOR_GENERIC:
kono
parents:
diff changeset
58 case PROCESSOR_BTVER1:
kono
parents:
diff changeset
59 return 3;
kono
parents:
diff changeset
60
kono
parents:
diff changeset
61 case PROCESSOR_BDVER1:
kono
parents:
diff changeset
62 case PROCESSOR_BDVER2:
kono
parents:
diff changeset
63 case PROCESSOR_BDVER3:
kono
parents:
diff changeset
64 case PROCESSOR_BDVER4:
kono
parents:
diff changeset
65 case PROCESSOR_ZNVER1:
kono
parents:
diff changeset
66 case PROCESSOR_CORE2:
kono
parents:
diff changeset
67 case PROCESSOR_NEHALEM:
kono
parents:
diff changeset
68 case PROCESSOR_SANDYBRIDGE:
kono
parents:
diff changeset
69 case PROCESSOR_HASWELL:
kono
parents:
diff changeset
70 return 4;
kono
parents:
diff changeset
71
kono
parents:
diff changeset
72 default:
kono
parents:
diff changeset
73 return 1;
kono
parents:
diff changeset
74 }
kono
parents:
diff changeset
75 }
kono
parents:
diff changeset
76
kono
parents:
diff changeset
77 /* Return true iff USE_INSN has a memory address with operands set by
kono
parents:
diff changeset
78 SET_INSN. */
kono
parents:
diff changeset
79
kono
parents:
diff changeset
80 bool
kono
parents:
diff changeset
81 ix86_agi_dependent (rtx_insn *set_insn, rtx_insn *use_insn)
kono
parents:
diff changeset
82 {
kono
parents:
diff changeset
83 int i;
kono
parents:
diff changeset
84 extract_insn_cached (use_insn);
kono
parents:
diff changeset
85 for (i = recog_data.n_operands - 1; i >= 0; --i)
kono
parents:
diff changeset
86 if (MEM_P (recog_data.operand[i]))
kono
parents:
diff changeset
87 {
kono
parents:
diff changeset
88 rtx addr = XEXP (recog_data.operand[i], 0);
kono
parents:
diff changeset
89 if (modified_in_p (addr, set_insn) != 0)
kono
parents:
diff changeset
90 {
kono
parents:
diff changeset
91 /* No AGI stall if SET_INSN is a push or pop and USE_INSN
kono
parents:
diff changeset
92 has SP based memory (unless index reg is modified in a pop). */
kono
parents:
diff changeset
93 rtx set = single_set (set_insn);
kono
parents:
diff changeset
94 if (set
kono
parents:
diff changeset
95 && (push_operand (SET_DEST (set), GET_MODE (SET_DEST (set)))
kono
parents:
diff changeset
96 || pop_operand (SET_SRC (set), GET_MODE (SET_SRC (set)))))
kono
parents:
diff changeset
97 {
kono
parents:
diff changeset
98 struct ix86_address parts;
kono
parents:
diff changeset
99 if (ix86_decompose_address (addr, &parts)
kono
parents:
diff changeset
100 && parts.base == stack_pointer_rtx
kono
parents:
diff changeset
101 && (parts.index == NULL_RTX
kono
parents:
diff changeset
102 || MEM_P (SET_DEST (set))
kono
parents:
diff changeset
103 || !modified_in_p (parts.index, set_insn)))
kono
parents:
diff changeset
104 return false;
kono
parents:
diff changeset
105 }
kono
parents:
diff changeset
106 return true;
kono
parents:
diff changeset
107 }
kono
parents:
diff changeset
108 return false;
kono
parents:
diff changeset
109 }
kono
parents:
diff changeset
110 return false;
kono
parents:
diff changeset
111 }
kono
parents:
diff changeset
112
kono
parents:
diff changeset
113 /* A subroutine of ix86_adjust_cost -- return TRUE iff INSN reads flags set
kono
parents:
diff changeset
114 by DEP_INSN and nothing set by DEP_INSN. */
kono
parents:
diff changeset
115
kono
parents:
diff changeset
116 static bool
kono
parents:
diff changeset
117 ix86_flags_dependent (rtx_insn *insn, rtx_insn *dep_insn, enum attr_type insn_type)
kono
parents:
diff changeset
118 {
kono
parents:
diff changeset
119 rtx set, set2;
kono
parents:
diff changeset
120
kono
parents:
diff changeset
121 /* Simplify the test for uninteresting insns. */
kono
parents:
diff changeset
122 if (insn_type != TYPE_SETCC
kono
parents:
diff changeset
123 && insn_type != TYPE_ICMOV
kono
parents:
diff changeset
124 && insn_type != TYPE_FCMOV
kono
parents:
diff changeset
125 && insn_type != TYPE_IBR)
kono
parents:
diff changeset
126 return false;
kono
parents:
diff changeset
127
kono
parents:
diff changeset
128 if ((set = single_set (dep_insn)) != 0)
kono
parents:
diff changeset
129 {
kono
parents:
diff changeset
130 set = SET_DEST (set);
kono
parents:
diff changeset
131 set2 = NULL_RTX;
kono
parents:
diff changeset
132 }
kono
parents:
diff changeset
133 else if (GET_CODE (PATTERN (dep_insn)) == PARALLEL
kono
parents:
diff changeset
134 && XVECLEN (PATTERN (dep_insn), 0) == 2
kono
parents:
diff changeset
135 && GET_CODE (XVECEXP (PATTERN (dep_insn), 0, 0)) == SET
kono
parents:
diff changeset
136 && GET_CODE (XVECEXP (PATTERN (dep_insn), 0, 1)) == SET)
kono
parents:
diff changeset
137 {
kono
parents:
diff changeset
138 set = SET_DEST (XVECEXP (PATTERN (dep_insn), 0, 0));
kono
parents:
diff changeset
139 set2 = SET_DEST (XVECEXP (PATTERN (dep_insn), 0, 0));
kono
parents:
diff changeset
140 }
kono
parents:
diff changeset
141 else
kono
parents:
diff changeset
142 return false;
kono
parents:
diff changeset
143
kono
parents:
diff changeset
144 if (!REG_P (set) || REGNO (set) != FLAGS_REG)
kono
parents:
diff changeset
145 return false;
kono
parents:
diff changeset
146
kono
parents:
diff changeset
147 /* This test is true if the dependent insn reads the flags but
kono
parents:
diff changeset
148 not any other potentially set register. */
kono
parents:
diff changeset
149 if (!reg_overlap_mentioned_p (set, PATTERN (insn)))
kono
parents:
diff changeset
150 return false;
kono
parents:
diff changeset
151
kono
parents:
diff changeset
152 if (set2 && reg_overlap_mentioned_p (set2, PATTERN (insn)))
kono
parents:
diff changeset
153 return false;
kono
parents:
diff changeset
154
kono
parents:
diff changeset
155 return true;
kono
parents:
diff changeset
156 }
kono
parents:
diff changeset
157
kono
parents:
diff changeset
158 /* Helper function for exact_store_load_dependency.
kono
parents:
diff changeset
159 Return true if addr is found in insn. */
kono
parents:
diff changeset
160 static bool
kono
parents:
diff changeset
161 exact_dependency_1 (rtx addr, rtx insn)
kono
parents:
diff changeset
162 {
kono
parents:
diff changeset
163 enum rtx_code code;
kono
parents:
diff changeset
164 const char *format_ptr;
kono
parents:
diff changeset
165 int i, j;
kono
parents:
diff changeset
166
kono
parents:
diff changeset
167 code = GET_CODE (insn);
kono
parents:
diff changeset
168 switch (code)
kono
parents:
diff changeset
169 {
kono
parents:
diff changeset
170 case MEM:
kono
parents:
diff changeset
171 if (rtx_equal_p (addr, insn))
kono
parents:
diff changeset
172 return true;
kono
parents:
diff changeset
173 break;
kono
parents:
diff changeset
174 case REG:
kono
parents:
diff changeset
175 CASE_CONST_ANY:
kono
parents:
diff changeset
176 case SYMBOL_REF:
kono
parents:
diff changeset
177 case CODE_LABEL:
kono
parents:
diff changeset
178 case PC:
kono
parents:
diff changeset
179 case CC0:
kono
parents:
diff changeset
180 case EXPR_LIST:
kono
parents:
diff changeset
181 return false;
kono
parents:
diff changeset
182 default:
kono
parents:
diff changeset
183 break;
kono
parents:
diff changeset
184 }
kono
parents:
diff changeset
185
kono
parents:
diff changeset
186 format_ptr = GET_RTX_FORMAT (code);
kono
parents:
diff changeset
187 for (i = 0; i < GET_RTX_LENGTH (code); i++)
kono
parents:
diff changeset
188 {
kono
parents:
diff changeset
189 switch (*format_ptr++)
kono
parents:
diff changeset
190 {
kono
parents:
diff changeset
191 case 'e':
kono
parents:
diff changeset
192 if (exact_dependency_1 (addr, XEXP (insn, i)))
kono
parents:
diff changeset
193 return true;
kono
parents:
diff changeset
194 break;
kono
parents:
diff changeset
195 case 'E':
kono
parents:
diff changeset
196 for (j = 0; j < XVECLEN (insn, i); j++)
kono
parents:
diff changeset
197 if (exact_dependency_1 (addr, XVECEXP (insn, i, j)))
kono
parents:
diff changeset
198 return true;
kono
parents:
diff changeset
199 break;
kono
parents:
diff changeset
200 }
kono
parents:
diff changeset
201 }
kono
parents:
diff changeset
202 return false;
kono
parents:
diff changeset
203 }
kono
parents:
diff changeset
204
kono
parents:
diff changeset
205 /* Return true if there exists exact dependency for store & load, i.e.
kono
parents:
diff changeset
206 the same memory address is used in them. */
kono
parents:
diff changeset
207 static bool
kono
parents:
diff changeset
208 exact_store_load_dependency (rtx_insn *store, rtx_insn *load)
kono
parents:
diff changeset
209 {
kono
parents:
diff changeset
210 rtx set1, set2;
kono
parents:
diff changeset
211
kono
parents:
diff changeset
212 set1 = single_set (store);
kono
parents:
diff changeset
213 if (!set1)
kono
parents:
diff changeset
214 return false;
kono
parents:
diff changeset
215 if (!MEM_P (SET_DEST (set1)))
kono
parents:
diff changeset
216 return false;
kono
parents:
diff changeset
217 set2 = single_set (load);
kono
parents:
diff changeset
218 if (!set2)
kono
parents:
diff changeset
219 return false;
kono
parents:
diff changeset
220 if (exact_dependency_1 (SET_DEST (set1), SET_SRC (set2)))
kono
parents:
diff changeset
221 return true;
kono
parents:
diff changeset
222 return false;
kono
parents:
diff changeset
223 }
kono
parents:
diff changeset
224
kono
parents:
diff changeset
225
kono
parents:
diff changeset
226 /* This function corrects the value of COST (latency) based on the relationship
kono
parents:
diff changeset
227 between INSN and DEP_INSN through a dependence of type DEP_TYPE, and strength
kono
parents:
diff changeset
228 DW. It should return the new value.
kono
parents:
diff changeset
229
kono
parents:
diff changeset
230 On x86 CPUs this is most commonly used to model the fact that valus of
kono
parents:
diff changeset
231 registers used to compute address of memory operand needs to be ready
kono
parents:
diff changeset
232 earlier than values of registers used in the actual operation. */
kono
parents:
diff changeset
233
kono
parents:
diff changeset
234 int
kono
parents:
diff changeset
235 ix86_adjust_cost (rtx_insn *insn, int dep_type, rtx_insn *dep_insn, int cost,
kono
parents:
diff changeset
236 unsigned int)
kono
parents:
diff changeset
237 {
kono
parents:
diff changeset
238 enum attr_type insn_type, dep_insn_type;
kono
parents:
diff changeset
239 enum attr_memory memory;
kono
parents:
diff changeset
240 rtx set, set2;
kono
parents:
diff changeset
241 int dep_insn_code_number;
kono
parents:
diff changeset
242
kono
parents:
diff changeset
243 /* Anti and output dependencies have zero cost on all CPUs. */
kono
parents:
diff changeset
244 if (dep_type != 0)
kono
parents:
diff changeset
245 return 0;
kono
parents:
diff changeset
246
kono
parents:
diff changeset
247 dep_insn_code_number = recog_memoized (dep_insn);
kono
parents:
diff changeset
248
kono
parents:
diff changeset
249 /* If we can't recognize the insns, we can't really do anything. */
kono
parents:
diff changeset
250 if (dep_insn_code_number < 0 || recog_memoized (insn) < 0)
kono
parents:
diff changeset
251 return cost;
kono
parents:
diff changeset
252
kono
parents:
diff changeset
253 insn_type = get_attr_type (insn);
kono
parents:
diff changeset
254 dep_insn_type = get_attr_type (dep_insn);
kono
parents:
diff changeset
255
kono
parents:
diff changeset
256 switch (ix86_tune)
kono
parents:
diff changeset
257 {
kono
parents:
diff changeset
258 case PROCESSOR_PENTIUM:
kono
parents:
diff changeset
259 case PROCESSOR_LAKEMONT:
kono
parents:
diff changeset
260 /* Address Generation Interlock adds a cycle of latency. */
kono
parents:
diff changeset
261 if (insn_type == TYPE_LEA)
kono
parents:
diff changeset
262 {
kono
parents:
diff changeset
263 rtx addr = PATTERN (insn);
kono
parents:
diff changeset
264
kono
parents:
diff changeset
265 if (GET_CODE (addr) == PARALLEL)
kono
parents:
diff changeset
266 addr = XVECEXP (addr, 0, 0);
kono
parents:
diff changeset
267
kono
parents:
diff changeset
268 gcc_assert (GET_CODE (addr) == SET);
kono
parents:
diff changeset
269
kono
parents:
diff changeset
270 addr = SET_SRC (addr);
kono
parents:
diff changeset
271 if (modified_in_p (addr, dep_insn))
kono
parents:
diff changeset
272 cost += 1;
kono
parents:
diff changeset
273 }
kono
parents:
diff changeset
274 else if (ix86_agi_dependent (dep_insn, insn))
kono
parents:
diff changeset
275 cost += 1;
kono
parents:
diff changeset
276
kono
parents:
diff changeset
277 /* ??? Compares pair with jump/setcc. */
kono
parents:
diff changeset
278 if (ix86_flags_dependent (insn, dep_insn, insn_type))
kono
parents:
diff changeset
279 cost = 0;
kono
parents:
diff changeset
280
kono
parents:
diff changeset
281 /* Floating point stores require value to be ready one cycle earlier. */
kono
parents:
diff changeset
282 if (insn_type == TYPE_FMOV
kono
parents:
diff changeset
283 && get_attr_memory (insn) == MEMORY_STORE
kono
parents:
diff changeset
284 && !ix86_agi_dependent (dep_insn, insn))
kono
parents:
diff changeset
285 cost += 1;
kono
parents:
diff changeset
286 break;
kono
parents:
diff changeset
287
kono
parents:
diff changeset
288 case PROCESSOR_PENTIUMPRO:
kono
parents:
diff changeset
289 /* INT->FP conversion is expensive. */
kono
parents:
diff changeset
290 if (get_attr_fp_int_src (dep_insn))
kono
parents:
diff changeset
291 cost += 5;
kono
parents:
diff changeset
292
kono
parents:
diff changeset
293 /* There is one cycle extra latency between an FP op and a store. */
kono
parents:
diff changeset
294 if (insn_type == TYPE_FMOV
kono
parents:
diff changeset
295 && (set = single_set (dep_insn)) != NULL_RTX
kono
parents:
diff changeset
296 && (set2 = single_set (insn)) != NULL_RTX
kono
parents:
diff changeset
297 && rtx_equal_p (SET_DEST (set), SET_SRC (set2))
kono
parents:
diff changeset
298 && MEM_P (SET_DEST (set2)))
kono
parents:
diff changeset
299 cost += 1;
kono
parents:
diff changeset
300
kono
parents:
diff changeset
301 memory = get_attr_memory (insn);
kono
parents:
diff changeset
302
kono
parents:
diff changeset
303 /* Show ability of reorder buffer to hide latency of load by executing
kono
parents:
diff changeset
304 in parallel with previous instruction in case
kono
parents:
diff changeset
305 previous instruction is not needed to compute the address. */
kono
parents:
diff changeset
306 if ((memory == MEMORY_LOAD || memory == MEMORY_BOTH)
kono
parents:
diff changeset
307 && !ix86_agi_dependent (dep_insn, insn))
kono
parents:
diff changeset
308 {
kono
parents:
diff changeset
309 /* Claim moves to take one cycle, as core can issue one load
kono
parents:
diff changeset
310 at time and the next load can start cycle later. */
kono
parents:
diff changeset
311 if (dep_insn_type == TYPE_IMOV
kono
parents:
diff changeset
312 || dep_insn_type == TYPE_FMOV)
kono
parents:
diff changeset
313 cost = 1;
kono
parents:
diff changeset
314 else if (cost > 1)
kono
parents:
diff changeset
315 cost--;
kono
parents:
diff changeset
316 }
kono
parents:
diff changeset
317 break;
kono
parents:
diff changeset
318
kono
parents:
diff changeset
319 case PROCESSOR_K6:
kono
parents:
diff changeset
320 /* The esp dependency is resolved before
kono
parents:
diff changeset
321 the instruction is really finished. */
kono
parents:
diff changeset
322 if ((insn_type == TYPE_PUSH || insn_type == TYPE_POP)
kono
parents:
diff changeset
323 && (dep_insn_type == TYPE_PUSH || dep_insn_type == TYPE_POP))
kono
parents:
diff changeset
324 return 1;
kono
parents:
diff changeset
325
kono
parents:
diff changeset
326 /* INT->FP conversion is expensive. */
kono
parents:
diff changeset
327 if (get_attr_fp_int_src (dep_insn))
kono
parents:
diff changeset
328 cost += 5;
kono
parents:
diff changeset
329
kono
parents:
diff changeset
330 memory = get_attr_memory (insn);
kono
parents:
diff changeset
331
kono
parents:
diff changeset
332 /* Show ability of reorder buffer to hide latency of load by executing
kono
parents:
diff changeset
333 in parallel with previous instruction in case
kono
parents:
diff changeset
334 previous instruction is not needed to compute the address. */
kono
parents:
diff changeset
335 if ((memory == MEMORY_LOAD || memory == MEMORY_BOTH)
kono
parents:
diff changeset
336 && !ix86_agi_dependent (dep_insn, insn))
kono
parents:
diff changeset
337 {
kono
parents:
diff changeset
338 /* Claim moves to take one cycle, as core can issue one load
kono
parents:
diff changeset
339 at time and the next load can start cycle later. */
kono
parents:
diff changeset
340 if (dep_insn_type == TYPE_IMOV
kono
parents:
diff changeset
341 || dep_insn_type == TYPE_FMOV)
kono
parents:
diff changeset
342 cost = 1;
kono
parents:
diff changeset
343 else if (cost > 2)
kono
parents:
diff changeset
344 cost -= 2;
kono
parents:
diff changeset
345 else
kono
parents:
diff changeset
346 cost = 1;
kono
parents:
diff changeset
347 }
kono
parents:
diff changeset
348 break;
kono
parents:
diff changeset
349
kono
parents:
diff changeset
350 case PROCESSOR_AMDFAM10:
kono
parents:
diff changeset
351 case PROCESSOR_BDVER1:
kono
parents:
diff changeset
352 case PROCESSOR_BDVER2:
kono
parents:
diff changeset
353 case PROCESSOR_BDVER3:
kono
parents:
diff changeset
354 case PROCESSOR_BDVER4:
kono
parents:
diff changeset
355 case PROCESSOR_BTVER1:
kono
parents:
diff changeset
356 case PROCESSOR_BTVER2:
kono
parents:
diff changeset
357 case PROCESSOR_GENERIC:
kono
parents:
diff changeset
358 /* Stack engine allows to execute push&pop instructions in parall. */
kono
parents:
diff changeset
359 if ((insn_type == TYPE_PUSH || insn_type == TYPE_POP)
kono
parents:
diff changeset
360 && (dep_insn_type == TYPE_PUSH || dep_insn_type == TYPE_POP))
kono
parents:
diff changeset
361 return 0;
kono
parents:
diff changeset
362 /* FALLTHRU */
kono
parents:
diff changeset
363
kono
parents:
diff changeset
364 case PROCESSOR_ATHLON:
kono
parents:
diff changeset
365 case PROCESSOR_K8:
kono
parents:
diff changeset
366 memory = get_attr_memory (insn);
kono
parents:
diff changeset
367
kono
parents:
diff changeset
368 /* Show ability of reorder buffer to hide latency of load by executing
kono
parents:
diff changeset
369 in parallel with previous instruction in case
kono
parents:
diff changeset
370 previous instruction is not needed to compute the address. */
kono
parents:
diff changeset
371 if ((memory == MEMORY_LOAD || memory == MEMORY_BOTH)
kono
parents:
diff changeset
372 && !ix86_agi_dependent (dep_insn, insn))
kono
parents:
diff changeset
373 {
kono
parents:
diff changeset
374 enum attr_unit unit = get_attr_unit (insn);
kono
parents:
diff changeset
375 int loadcost = 3;
kono
parents:
diff changeset
376
kono
parents:
diff changeset
377 /* Because of the difference between the length of integer and
kono
parents:
diff changeset
378 floating unit pipeline preparation stages, the memory operands
kono
parents:
diff changeset
379 for floating point are cheaper.
kono
parents:
diff changeset
380
kono
parents:
diff changeset
381 ??? For Athlon it the difference is most probably 2. */
kono
parents:
diff changeset
382 if (unit == UNIT_INTEGER || unit == UNIT_UNKNOWN)
kono
parents:
diff changeset
383 loadcost = 3;
kono
parents:
diff changeset
384 else
kono
parents:
diff changeset
385 loadcost = TARGET_ATHLON ? 2 : 0;
kono
parents:
diff changeset
386
kono
parents:
diff changeset
387 if (cost >= loadcost)
kono
parents:
diff changeset
388 cost -= loadcost;
kono
parents:
diff changeset
389 else
kono
parents:
diff changeset
390 cost = 0;
kono
parents:
diff changeset
391 }
kono
parents:
diff changeset
392 break;
kono
parents:
diff changeset
393
kono
parents:
diff changeset
394 case PROCESSOR_ZNVER1:
kono
parents:
diff changeset
395 /* Stack engine allows to execute push&pop instructions in parall. */
kono
parents:
diff changeset
396 if ((insn_type == TYPE_PUSH || insn_type == TYPE_POP)
kono
parents:
diff changeset
397 && (dep_insn_type == TYPE_PUSH || dep_insn_type == TYPE_POP))
kono
parents:
diff changeset
398 return 0;
kono
parents:
diff changeset
399
kono
parents:
diff changeset
400 memory = get_attr_memory (insn);
kono
parents:
diff changeset
401
kono
parents:
diff changeset
402 /* Show ability of reorder buffer to hide latency of load by executing
kono
parents:
diff changeset
403 in parallel with previous instruction in case
kono
parents:
diff changeset
404 previous instruction is not needed to compute the address. */
kono
parents:
diff changeset
405 if ((memory == MEMORY_LOAD || memory == MEMORY_BOTH)
kono
parents:
diff changeset
406 && !ix86_agi_dependent (dep_insn, insn))
kono
parents:
diff changeset
407 {
kono
parents:
diff changeset
408 enum attr_unit unit = get_attr_unit (insn);
kono
parents:
diff changeset
409 int loadcost;
kono
parents:
diff changeset
410
kono
parents:
diff changeset
411 if (unit == UNIT_INTEGER || unit == UNIT_UNKNOWN)
kono
parents:
diff changeset
412 loadcost = 4;
kono
parents:
diff changeset
413 else
kono
parents:
diff changeset
414 loadcost = 7;
kono
parents:
diff changeset
415
kono
parents:
diff changeset
416 if (cost >= loadcost)
kono
parents:
diff changeset
417 cost -= loadcost;
kono
parents:
diff changeset
418 else
kono
parents:
diff changeset
419 cost = 0;
kono
parents:
diff changeset
420 }
kono
parents:
diff changeset
421 break;
kono
parents:
diff changeset
422
kono
parents:
diff changeset
423 case PROCESSOR_CORE2:
kono
parents:
diff changeset
424 case PROCESSOR_NEHALEM:
kono
parents:
diff changeset
425 case PROCESSOR_SANDYBRIDGE:
kono
parents:
diff changeset
426 case PROCESSOR_HASWELL:
kono
parents:
diff changeset
427 /* Stack engine allows to execute push&pop instructions in parall. */
kono
parents:
diff changeset
428 if ((insn_type == TYPE_PUSH || insn_type == TYPE_POP)
kono
parents:
diff changeset
429 && (dep_insn_type == TYPE_PUSH || dep_insn_type == TYPE_POP))
kono
parents:
diff changeset
430 return 0;
kono
parents:
diff changeset
431
kono
parents:
diff changeset
432 memory = get_attr_memory (insn);
kono
parents:
diff changeset
433
kono
parents:
diff changeset
434 /* Show ability of reorder buffer to hide latency of load by executing
kono
parents:
diff changeset
435 in parallel with previous instruction in case
kono
parents:
diff changeset
436 previous instruction is not needed to compute the address. */
kono
parents:
diff changeset
437 if ((memory == MEMORY_LOAD || memory == MEMORY_BOTH)
kono
parents:
diff changeset
438 && !ix86_agi_dependent (dep_insn, insn))
kono
parents:
diff changeset
439 {
kono
parents:
diff changeset
440 if (cost >= 4)
kono
parents:
diff changeset
441 cost -= 4;
kono
parents:
diff changeset
442 else
kono
parents:
diff changeset
443 cost = 0;
kono
parents:
diff changeset
444 }
kono
parents:
diff changeset
445 break;
kono
parents:
diff changeset
446
kono
parents:
diff changeset
447 case PROCESSOR_SILVERMONT:
kono
parents:
diff changeset
448 case PROCESSOR_KNL:
kono
parents:
diff changeset
449 case PROCESSOR_KNM:
kono
parents:
diff changeset
450 case PROCESSOR_INTEL:
kono
parents:
diff changeset
451 if (!reload_completed)
kono
parents:
diff changeset
452 return cost;
kono
parents:
diff changeset
453
kono
parents:
diff changeset
454 /* Increase cost of integer loads. */
kono
parents:
diff changeset
455 memory = get_attr_memory (dep_insn);
kono
parents:
diff changeset
456 if (memory == MEMORY_LOAD || memory == MEMORY_BOTH)
kono
parents:
diff changeset
457 {
kono
parents:
diff changeset
458 enum attr_unit unit = get_attr_unit (dep_insn);
kono
parents:
diff changeset
459 if (unit == UNIT_INTEGER && cost == 1)
kono
parents:
diff changeset
460 {
kono
parents:
diff changeset
461 if (memory == MEMORY_LOAD)
kono
parents:
diff changeset
462 cost = 3;
kono
parents:
diff changeset
463 else
kono
parents:
diff changeset
464 {
kono
parents:
diff changeset
465 /* Increase cost of ld/st for short int types only
kono
parents:
diff changeset
466 because of store forwarding issue. */
kono
parents:
diff changeset
467 rtx set = single_set (dep_insn);
kono
parents:
diff changeset
468 if (set && (GET_MODE (SET_DEST (set)) == QImode
kono
parents:
diff changeset
469 || GET_MODE (SET_DEST (set)) == HImode))
kono
parents:
diff changeset
470 {
kono
parents:
diff changeset
471 /* Increase cost of store/load insn if exact
kono
parents:
diff changeset
472 dependence exists and it is load insn. */
kono
parents:
diff changeset
473 enum attr_memory insn_memory = get_attr_memory (insn);
kono
parents:
diff changeset
474 if (insn_memory == MEMORY_LOAD
kono
parents:
diff changeset
475 && exact_store_load_dependency (dep_insn, insn))
kono
parents:
diff changeset
476 cost = 3;
kono
parents:
diff changeset
477 }
kono
parents:
diff changeset
478 }
kono
parents:
diff changeset
479 }
kono
parents:
diff changeset
480 }
kono
parents:
diff changeset
481
kono
parents:
diff changeset
482 default:
kono
parents:
diff changeset
483 break;
kono
parents:
diff changeset
484 }
kono
parents:
diff changeset
485
kono
parents:
diff changeset
486 return cost;
kono
parents:
diff changeset
487 }
kono
parents:
diff changeset
488
kono
parents:
diff changeset
489 /* How many alternative schedules to try. This should be as wide as the
kono
parents:
diff changeset
490 scheduling freedom in the DFA, but no wider. Making this value too
kono
parents:
diff changeset
491 large results extra work for the scheduler. */
kono
parents:
diff changeset
492
kono
parents:
diff changeset
493 int
kono
parents:
diff changeset
494 ia32_multipass_dfa_lookahead (void)
kono
parents:
diff changeset
495 {
kono
parents:
diff changeset
496 /* Generally, we want haifa-sched:max_issue() to look ahead as far
kono
parents:
diff changeset
497 as many instructions can be executed on a cycle, i.e.,
kono
parents:
diff changeset
498 issue_rate. */
kono
parents:
diff changeset
499 if (reload_completed)
kono
parents:
diff changeset
500 return ix86_issue_rate ();
kono
parents:
diff changeset
501 /* Don't use lookahead for pre-reload schedule to save compile time. */
kono
parents:
diff changeset
502 return 0;
kono
parents:
diff changeset
503 }
kono
parents:
diff changeset
504
kono
parents:
diff changeset
505 /* Return true if target platform supports macro-fusion. */
kono
parents:
diff changeset
506
kono
parents:
diff changeset
507 bool
kono
parents:
diff changeset
508 ix86_macro_fusion_p ()
kono
parents:
diff changeset
509 {
kono
parents:
diff changeset
510 return TARGET_FUSE_CMP_AND_BRANCH;
kono
parents:
diff changeset
511 }
kono
parents:
diff changeset
512
kono
parents:
diff changeset
513 /* Check whether current microarchitecture support macro fusion
kono
parents:
diff changeset
514 for insn pair "CONDGEN + CONDJMP". Refer to
kono
parents:
diff changeset
515 "Intel Architectures Optimization Reference Manual". */
kono
parents:
diff changeset
516
kono
parents:
diff changeset
517 bool
kono
parents:
diff changeset
518 ix86_macro_fusion_pair_p (rtx_insn *condgen, rtx_insn *condjmp)
kono
parents:
diff changeset
519 {
kono
parents:
diff changeset
520 rtx src, dest;
kono
parents:
diff changeset
521 enum rtx_code ccode;
kono
parents:
diff changeset
522 rtx compare_set = NULL_RTX, test_if, cond;
kono
parents:
diff changeset
523 rtx alu_set = NULL_RTX, addr = NULL_RTX;
kono
parents:
diff changeset
524
kono
parents:
diff changeset
525 if (!any_condjump_p (condjmp))
kono
parents:
diff changeset
526 return false;
kono
parents:
diff changeset
527
kono
parents:
diff changeset
528 unsigned int condreg1, condreg2;
kono
parents:
diff changeset
529 rtx cc_reg_1;
kono
parents:
diff changeset
530 targetm.fixed_condition_code_regs (&condreg1, &condreg2);
kono
parents:
diff changeset
531 cc_reg_1 = gen_rtx_REG (CCmode, condreg1);
kono
parents:
diff changeset
532 if (!reg_referenced_p (cc_reg_1, PATTERN (condjmp))
kono
parents:
diff changeset
533 || !condgen
kono
parents:
diff changeset
534 || !modified_in_p (cc_reg_1, condgen))
kono
parents:
diff changeset
535 return false;
kono
parents:
diff changeset
536
kono
parents:
diff changeset
537 if (get_attr_type (condgen) != TYPE_TEST
kono
parents:
diff changeset
538 && get_attr_type (condgen) != TYPE_ICMP
kono
parents:
diff changeset
539 && get_attr_type (condgen) != TYPE_INCDEC
kono
parents:
diff changeset
540 && get_attr_type (condgen) != TYPE_ALU)
kono
parents:
diff changeset
541 return false;
kono
parents:
diff changeset
542
kono
parents:
diff changeset
543 compare_set = single_set (condgen);
kono
parents:
diff changeset
544 if (compare_set == NULL_RTX
kono
parents:
diff changeset
545 && !TARGET_FUSE_ALU_AND_BRANCH)
kono
parents:
diff changeset
546 return false;
kono
parents:
diff changeset
547
kono
parents:
diff changeset
548 if (compare_set == NULL_RTX)
kono
parents:
diff changeset
549 {
kono
parents:
diff changeset
550 int i;
kono
parents:
diff changeset
551 rtx pat = PATTERN (condgen);
kono
parents:
diff changeset
552 for (i = 0; i < XVECLEN (pat, 0); i++)
kono
parents:
diff changeset
553 if (GET_CODE (XVECEXP (pat, 0, i)) == SET)
kono
parents:
diff changeset
554 {
kono
parents:
diff changeset
555 rtx set_src = SET_SRC (XVECEXP (pat, 0, i));
kono
parents:
diff changeset
556 if (GET_CODE (set_src) == COMPARE)
kono
parents:
diff changeset
557 compare_set = XVECEXP (pat, 0, i);
kono
parents:
diff changeset
558 else
kono
parents:
diff changeset
559 alu_set = XVECEXP (pat, 0, i);
kono
parents:
diff changeset
560 }
kono
parents:
diff changeset
561 }
kono
parents:
diff changeset
562 if (compare_set == NULL_RTX)
kono
parents:
diff changeset
563 return false;
kono
parents:
diff changeset
564 src = SET_SRC (compare_set);
kono
parents:
diff changeset
565 if (GET_CODE (src) != COMPARE)
kono
parents:
diff changeset
566 return false;
kono
parents:
diff changeset
567
kono
parents:
diff changeset
568 /* Macro-fusion for cmp/test MEM-IMM + conditional jmp is not
kono
parents:
diff changeset
569 supported. */
kono
parents:
diff changeset
570 if ((MEM_P (XEXP (src, 0))
kono
parents:
diff changeset
571 && CONST_INT_P (XEXP (src, 1)))
kono
parents:
diff changeset
572 || (MEM_P (XEXP (src, 1))
kono
parents:
diff changeset
573 && CONST_INT_P (XEXP (src, 0))))
kono
parents:
diff changeset
574 return false;
kono
parents:
diff changeset
575
kono
parents:
diff changeset
576 /* No fusion for RIP-relative address. */
kono
parents:
diff changeset
577 if (MEM_P (XEXP (src, 0)))
kono
parents:
diff changeset
578 addr = XEXP (XEXP (src, 0), 0);
kono
parents:
diff changeset
579 else if (MEM_P (XEXP (src, 1)))
kono
parents:
diff changeset
580 addr = XEXP (XEXP (src, 1), 0);
kono
parents:
diff changeset
581
kono
parents:
diff changeset
582 if (addr) {
kono
parents:
diff changeset
583 ix86_address parts;
kono
parents:
diff changeset
584 int ok = ix86_decompose_address (addr, &parts);
kono
parents:
diff changeset
585 gcc_assert (ok);
kono
parents:
diff changeset
586
kono
parents:
diff changeset
587 if (ix86_rip_relative_addr_p (&parts))
kono
parents:
diff changeset
588 return false;
kono
parents:
diff changeset
589 }
kono
parents:
diff changeset
590
kono
parents:
diff changeset
591 test_if = SET_SRC (pc_set (condjmp));
kono
parents:
diff changeset
592 cond = XEXP (test_if, 0);
kono
parents:
diff changeset
593 ccode = GET_CODE (cond);
kono
parents:
diff changeset
594 /* Check whether conditional jump use Sign or Overflow Flags. */
kono
parents:
diff changeset
595 if (!TARGET_FUSE_CMP_AND_BRANCH_SOFLAGS
kono
parents:
diff changeset
596 && (ccode == GE
kono
parents:
diff changeset
597 || ccode == GT
kono
parents:
diff changeset
598 || ccode == LE
kono
parents:
diff changeset
599 || ccode == LT))
kono
parents:
diff changeset
600 return false;
kono
parents:
diff changeset
601
kono
parents:
diff changeset
602 /* Return true for TYPE_TEST and TYPE_ICMP. */
kono
parents:
diff changeset
603 if (get_attr_type (condgen) == TYPE_TEST
kono
parents:
diff changeset
604 || get_attr_type (condgen) == TYPE_ICMP)
kono
parents:
diff changeset
605 return true;
kono
parents:
diff changeset
606
kono
parents:
diff changeset
607 /* The following is the case that macro-fusion for alu + jmp. */
kono
parents:
diff changeset
608 if (!TARGET_FUSE_ALU_AND_BRANCH || !alu_set)
kono
parents:
diff changeset
609 return false;
kono
parents:
diff changeset
610
kono
parents:
diff changeset
611 /* No fusion for alu op with memory destination operand. */
kono
parents:
diff changeset
612 dest = SET_DEST (alu_set);
kono
parents:
diff changeset
613 if (MEM_P (dest))
kono
parents:
diff changeset
614 return false;
kono
parents:
diff changeset
615
kono
parents:
diff changeset
616 /* Macro-fusion for inc/dec + unsigned conditional jump is not
kono
parents:
diff changeset
617 supported. */
kono
parents:
diff changeset
618 if (get_attr_type (condgen) == TYPE_INCDEC
kono
parents:
diff changeset
619 && (ccode == GEU
kono
parents:
diff changeset
620 || ccode == GTU
kono
parents:
diff changeset
621 || ccode == LEU
kono
parents:
diff changeset
622 || ccode == LTU))
kono
parents:
diff changeset
623 return false;
kono
parents:
diff changeset
624
kono
parents:
diff changeset
625 return true;
kono
parents:
diff changeset
626 }
kono
parents:
diff changeset
627