Branch data Line data Source code
1 : : /* Scheduler hooks for IA-32 which implement CPU 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 "target.h"
31 : : #include "insn-config.h"
32 : : #include "insn-attr.h"
33 : : #include "insn-opinit.h"
34 : : #include "recog.h"
35 : : #include "tm-constrs.h"
36 : :
37 : : /* Return the maximum number of instructions a cpu can issue. */
38 : :
39 : : int
40 : 36324215 : ix86_issue_rate (void)
41 : : {
42 : 36324215 : switch (ix86_tune)
43 : : {
44 : : case PROCESSOR_PENTIUM:
45 : : case PROCESSOR_LAKEMONT:
46 : : case PROCESSOR_BONNELL:
47 : : case PROCESSOR_SILVERMONT:
48 : : case PROCESSOR_K6:
49 : : case PROCESSOR_BTVER2:
50 : : case PROCESSOR_PENTIUM4:
51 : : case PROCESSOR_NOCONA:
52 : : return 2;
53 : :
54 : : case PROCESSOR_PENTIUMPRO:
55 : : case PROCESSOR_ATHLON:
56 : : case PROCESSOR_K8:
57 : : case PROCESSOR_AMDFAM10:
58 : : case PROCESSOR_BTVER1:
59 : : case PROCESSOR_LUJIAZUI:
60 : : return 3;
61 : :
62 : : case PROCESSOR_BDVER1:
63 : : case PROCESSOR_BDVER2:
64 : : case PROCESSOR_BDVER3:
65 : : case PROCESSOR_BDVER4:
66 : : case PROCESSOR_ZNVER1:
67 : : case PROCESSOR_ZNVER2:
68 : : case PROCESSOR_ZNVER3:
69 : : case PROCESSOR_ZNVER4:
70 : : case PROCESSOR_CORE2:
71 : : case PROCESSOR_NEHALEM:
72 : : case PROCESSOR_SANDYBRIDGE:
73 : : case PROCESSOR_HASWELL:
74 : : case PROCESSOR_TREMONT:
75 : : case PROCESSOR_SKYLAKE:
76 : : case PROCESSOR_SKYLAKE_AVX512:
77 : : case PROCESSOR_CASCADELAKE:
78 : : case PROCESSOR_CANNONLAKE:
79 : : case PROCESSOR_ALDERLAKE:
80 : : case PROCESSOR_YONGFENG:
81 : : case PROCESSOR_SHIJIDADAO:
82 : : case PROCESSOR_SIERRAFOREST:
83 : : case PROCESSOR_INTEL:
84 : : case PROCESSOR_GENERIC:
85 : : /* For znver5 decoder can handle 4 or 8 instructions per cycle,
86 : : op cache 12 instruction/cycle, dispatch 8 instructions
87 : : integer rename 8 instructions and Fp 6 instructions.
88 : :
89 : : The scheduler, without understanding out of order nature of the CPU
90 : : is not going to be able to use more than 4 instructions since that
91 : : is limits of the decoders. */
92 : : case PROCESSOR_ZNVER5:
93 : : return 4;
94 : :
95 : : case PROCESSOR_ICELAKE_CLIENT:
96 : : case PROCESSOR_ICELAKE_SERVER:
97 : : case PROCESSOR_TIGERLAKE:
98 : : case PROCESSOR_COOPERLAKE:
99 : : case PROCESSOR_ROCKETLAKE:
100 : : return 5;
101 : :
102 : : case PROCESSOR_SAPPHIRERAPIDS:
103 : : case PROCESSOR_GRANITERAPIDS:
104 : : case PROCESSOR_GRANITERAPIDS_D:
105 : : case PROCESSOR_DIAMONDRAPIDS:
106 : : case PROCESSOR_GRANDRIDGE:
107 : : case PROCESSOR_CLEARWATERFOREST:
108 : : case PROCESSOR_ARROWLAKE:
109 : : case PROCESSOR_ARROWLAKE_S:
110 : : case PROCESSOR_PANTHERLAKE:
111 : : return 6;
112 : :
113 : : default:
114 : : return 1;
115 : : }
116 : : }
117 : :
118 : : /* Return true iff USE_INSN has a memory address with operands set by
119 : : SET_INSN. */
120 : :
121 : : bool
122 : 9814425 : ix86_agi_dependent (rtx_insn *set_insn, rtx_insn *use_insn)
123 : : {
124 : 9814425 : int i;
125 : 9814425 : extract_insn_cached (use_insn);
126 : 11988139 : for (i = recog_data.n_operands - 1; i >= 0; --i)
127 : 11649840 : if (MEM_P (recog_data.operand[i]))
128 : : {
129 : 9476126 : rtx addr = XEXP (recog_data.operand[i], 0);
130 : 9476126 : if (modified_in_p (addr, set_insn) != 0)
131 : : {
132 : : /* No AGI stall if SET_INSN is a push or pop and USE_INSN
133 : : has SP based memory (unless index reg is modified in a pop). */
134 : 4260677 : rtx set = single_set (set_insn);
135 : 4260677 : if (set
136 : 4260677 : && (push_operand (SET_DEST (set), GET_MODE (SET_DEST (set)))
137 : 3482774 : || pop_operand (SET_SRC (set), GET_MODE (SET_SRC (set)))))
138 : : {
139 : 591525 : struct ix86_address parts;
140 : 591525 : if (ix86_decompose_address (addr, &parts)
141 : 591525 : && parts.base == stack_pointer_rtx
142 : 1182824 : && (parts.index == NULL_RTX
143 : 504 : || MEM_P (SET_DEST (set))
144 : 2 : || !modified_in_p (parts.index, set_insn)))
145 : 591298 : return false;
146 : : }
147 : 3669379 : return true;
148 : : }
149 : : return false;
150 : : }
151 : : return false;
152 : : }
153 : :
154 : : /* A subroutine of ix86_adjust_cost -- return TRUE iff INSN reads flags set
155 : : by DEP_INSN and nothing set by DEP_INSN. */
156 : :
157 : : static bool
158 : 0 : ix86_flags_dependent (rtx_insn *insn, rtx_insn *dep_insn, enum attr_type insn_type)
159 : : {
160 : 0 : rtx set, set2;
161 : :
162 : : /* Simplify the test for uninteresting insns. */
163 : 0 : if (insn_type != TYPE_SETCC
164 : 0 : && insn_type != TYPE_ICMOV
165 : 0 : && insn_type != TYPE_FCMOV
166 : 0 : && insn_type != TYPE_IBR)
167 : : return false;
168 : :
169 : 0 : if ((set = single_set (dep_insn)) != 0)
170 : : {
171 : 0 : set = SET_DEST (set);
172 : 0 : set2 = NULL_RTX;
173 : : }
174 : 0 : else if (GET_CODE (PATTERN (dep_insn)) == PARALLEL
175 : 0 : && XVECLEN (PATTERN (dep_insn), 0) == 2
176 : 0 : && GET_CODE (XVECEXP (PATTERN (dep_insn), 0, 0)) == SET
177 : 0 : && GET_CODE (XVECEXP (PATTERN (dep_insn), 0, 1)) == SET)
178 : : {
179 : 0 : set = SET_DEST (XVECEXP (PATTERN (dep_insn), 0, 0));
180 : 0 : set2 = SET_DEST (XVECEXP (PATTERN (dep_insn), 0, 0));
181 : : }
182 : : else
183 : : return false;
184 : :
185 : 0 : if (!REG_P (set) || REGNO (set) != FLAGS_REG)
186 : : return false;
187 : :
188 : : /* This test is true if the dependent insn reads the flags but
189 : : not any other potentially set register. */
190 : 0 : if (!reg_overlap_mentioned_p (set, PATTERN (insn)))
191 : : return false;
192 : :
193 : 0 : if (set2 && reg_overlap_mentioned_p (set2, PATTERN (insn)))
194 : : return false;
195 : :
196 : : return true;
197 : : }
198 : :
199 : : /* Helper function for exact_store_load_dependency.
200 : : Return true if addr is found in insn. */
201 : : static bool
202 : 0 : exact_dependency_1 (rtx addr, rtx insn)
203 : : {
204 : 0 : enum rtx_code code;
205 : 0 : const char *format_ptr;
206 : 0 : int i, j;
207 : :
208 : 0 : code = GET_CODE (insn);
209 : 0 : switch (code)
210 : : {
211 : 0 : case MEM:
212 : 0 : if (rtx_equal_p (addr, insn))
213 : : return true;
214 : : break;
215 : : case REG:
216 : : CASE_CONST_ANY:
217 : : case SYMBOL_REF:
218 : : case CODE_LABEL:
219 : : case PC:
220 : : case EXPR_LIST:
221 : : return false;
222 : : default:
223 : : break;
224 : : }
225 : :
226 : 0 : format_ptr = GET_RTX_FORMAT (code);
227 : 0 : for (i = 0; i < GET_RTX_LENGTH (code); i++)
228 : : {
229 : 0 : switch (*format_ptr++)
230 : : {
231 : 0 : case 'e':
232 : 0 : if (exact_dependency_1 (addr, XEXP (insn, i)))
233 : : return true;
234 : : break;
235 : : case 'E':
236 : 0 : for (j = 0; j < XVECLEN (insn, i); j++)
237 : 0 : if (exact_dependency_1 (addr, XVECEXP (insn, i, j)))
238 : : return true;
239 : : break;
240 : : }
241 : : }
242 : : return false;
243 : : }
244 : :
245 : : /* Return true if there exists exact dependency for store & load, i.e.
246 : : the same memory address is used in them. */
247 : : static bool
248 : 0 : exact_store_load_dependency (rtx_insn *store, rtx_insn *load)
249 : : {
250 : 0 : rtx set1, set2;
251 : :
252 : 0 : set1 = single_set (store);
253 : 0 : if (!set1)
254 : : return false;
255 : 0 : if (!MEM_P (SET_DEST (set1)))
256 : : return false;
257 : 0 : set2 = single_set (load);
258 : 0 : if (!set2)
259 : : return false;
260 : 0 : if (exact_dependency_1 (SET_DEST (set1), SET_SRC (set2)))
261 : : return true;
262 : : return false;
263 : : }
264 : :
265 : :
266 : : /* This function corrects the value of COST (latency) based on the relationship
267 : : between INSN and DEP_INSN through a dependence of type DEP_TYPE, and strength
268 : : DW. It should return the new value.
269 : :
270 : : On x86 CPUs this is most commonly used to model the fact that valus of
271 : : registers used to compute address of memory operand needs to be ready
272 : : earlier than values of registers used in the actual operation. */
273 : :
274 : : int
275 : 149794652 : ix86_adjust_cost (rtx_insn *insn, int dep_type, rtx_insn *dep_insn, int cost,
276 : : unsigned int)
277 : : {
278 : 149794652 : enum attr_type insn_type, dep_insn_type;
279 : 149794652 : enum attr_memory memory;
280 : 149794652 : rtx set, set2;
281 : 149794652 : int dep_insn_code_number;
282 : :
283 : : /* Anti and output dependencies have zero cost on all CPUs. */
284 : 149794652 : if (dep_type != 0)
285 : : return 0;
286 : :
287 : 52209013 : dep_insn_code_number = recog_memoized (dep_insn);
288 : :
289 : : /* If we can't recognize the insns, we can't really do anything. */
290 : 52209013 : if (dep_insn_code_number < 0 || recog_memoized (insn) < 0)
291 : 350630 : return cost;
292 : :
293 : 51858383 : insn_type = get_attr_type (insn);
294 : 51858383 : dep_insn_type = get_attr_type (dep_insn);
295 : :
296 : 51858383 : switch (ix86_tune)
297 : : {
298 : 0 : case PROCESSOR_PENTIUM:
299 : 0 : case PROCESSOR_LAKEMONT:
300 : : /* Address Generation Interlock adds a cycle of latency. */
301 : 0 : if (insn_type == TYPE_LEA)
302 : : {
303 : 0 : rtx addr = PATTERN (insn);
304 : :
305 : 0 : if (GET_CODE (addr) == PARALLEL)
306 : 0 : addr = XVECEXP (addr, 0, 0);
307 : :
308 : 0 : gcc_assert (GET_CODE (addr) == SET);
309 : :
310 : 0 : addr = SET_SRC (addr);
311 : 0 : if (modified_in_p (addr, dep_insn))
312 : 0 : cost += 1;
313 : : }
314 : 0 : else if (ix86_agi_dependent (dep_insn, insn))
315 : 0 : cost += 1;
316 : :
317 : : /* ??? Compares pair with jump/setcc. */
318 : 0 : if (ix86_flags_dependent (insn, dep_insn, insn_type))
319 : 0 : cost = 0;
320 : :
321 : : /* Floating point stores require value to be ready one cycle earlier. */
322 : 0 : if (insn_type == TYPE_FMOV
323 : 0 : && get_attr_memory (insn) == MEMORY_STORE
324 : 0 : && !ix86_agi_dependent (dep_insn, insn))
325 : 0 : cost += 1;
326 : : break;
327 : :
328 : 0 : case PROCESSOR_PENTIUMPRO:
329 : : /* INT->FP conversion is expensive. */
330 : 0 : if (get_attr_fp_int_src (dep_insn))
331 : 0 : cost += 5;
332 : :
333 : : /* There is one cycle extra latency between an FP op and a store. */
334 : 0 : if (insn_type == TYPE_FMOV
335 : 0 : && (set = single_set (dep_insn)) != NULL_RTX
336 : 0 : && (set2 = single_set (insn)) != NULL_RTX
337 : 0 : && rtx_equal_p (SET_DEST (set), SET_SRC (set2))
338 : 0 : && MEM_P (SET_DEST (set2)))
339 : 0 : cost += 1;
340 : :
341 : 0 : memory = get_attr_memory (insn);
342 : :
343 : : /* Show ability of reorder buffer to hide latency of load by executing
344 : : in parallel with previous instruction in case
345 : : previous instruction is not needed to compute the address. */
346 : 0 : if ((memory == MEMORY_LOAD || memory == MEMORY_BOTH)
347 : 0 : && !ix86_agi_dependent (dep_insn, insn))
348 : : {
349 : : /* Claim moves to take one cycle, as core can issue one load
350 : : at time and the next load can start cycle later. */
351 : 0 : if (dep_insn_type == TYPE_IMOV
352 : 0 : || dep_insn_type == TYPE_FMOV)
353 : : cost = 1;
354 : 0 : else if (cost > 1)
355 : 0 : cost--;
356 : : }
357 : : break;
358 : :
359 : 0 : case PROCESSOR_K6:
360 : : /* The esp dependency is resolved before
361 : : the instruction is really finished. */
362 : 0 : if ((insn_type == TYPE_PUSH || insn_type == TYPE_POP)
363 : 0 : && (dep_insn_type == TYPE_PUSH || dep_insn_type == TYPE_POP))
364 : : return 1;
365 : :
366 : : /* INT->FP conversion is expensive. */
367 : 0 : if (get_attr_fp_int_src (dep_insn))
368 : 0 : cost += 5;
369 : :
370 : 0 : memory = get_attr_memory (insn);
371 : :
372 : : /* Show ability of reorder buffer to hide latency of load by executing
373 : : in parallel with previous instruction in case
374 : : previous instruction is not needed to compute the address. */
375 : 0 : if ((memory == MEMORY_LOAD || memory == MEMORY_BOTH)
376 : 0 : && !ix86_agi_dependent (dep_insn, insn))
377 : : {
378 : : /* Claim moves to take one cycle, as core can issue one load
379 : : at time and the next load can start cycle later. */
380 : 0 : if (dep_insn_type == TYPE_IMOV
381 : 0 : || dep_insn_type == TYPE_FMOV)
382 : : cost = 1;
383 : 0 : else if (cost > 2)
384 : 0 : cost -= 2;
385 : : else
386 : : cost = 1;
387 : : }
388 : : break;
389 : :
390 : 9897 : case PROCESSOR_AMDFAM10:
391 : 9897 : case PROCESSOR_BDVER1:
392 : 9897 : case PROCESSOR_BDVER2:
393 : 9897 : case PROCESSOR_BDVER3:
394 : 9897 : case PROCESSOR_BDVER4:
395 : 9897 : case PROCESSOR_BTVER1:
396 : 9897 : case PROCESSOR_BTVER2:
397 : : /* Stack engine allows to execute push&pop instructions in parall. */
398 : 9897 : if ((insn_type == TYPE_PUSH || insn_type == TYPE_POP)
399 : 292 : && (dep_insn_type == TYPE_PUSH || dep_insn_type == TYPE_POP))
400 : : return 0;
401 : : /* FALLTHRU */
402 : :
403 : 75385 : case PROCESSOR_ATHLON:
404 : 75385 : case PROCESSOR_K8:
405 : 75385 : memory = get_attr_memory (insn);
406 : :
407 : : /* Show ability of reorder buffer to hide latency of load by executing
408 : : in parallel with previous instruction in case
409 : : previous instruction is not needed to compute the address. */
410 : 75385 : if ((memory == MEMORY_LOAD || memory == MEMORY_BOTH)
411 : 75385 : && !ix86_agi_dependent (dep_insn, insn))
412 : : {
413 : 11645 : enum attr_unit unit = get_attr_unit (insn);
414 : 11645 : int loadcost = 3;
415 : :
416 : : /* Because of the difference between the length of integer and
417 : : floating unit pipeline preparation stages, the memory operands
418 : : for floating point are cheaper.
419 : :
420 : : ??? For Athlon it the difference is most probably 2. */
421 : 11645 : if (unit == UNIT_INTEGER || unit == UNIT_UNKNOWN)
422 : : loadcost = 3;
423 : : else
424 : 6312 : loadcost = TARGET_CPU_P (ATHLON) ? 2 : 0;
425 : :
426 : 11645 : if (cost >= loadcost)
427 : 7084 : cost -= loadcost;
428 : : else
429 : : cost = 0;
430 : : }
431 : : break;
432 : :
433 : 3444 : case PROCESSOR_ZNVER1:
434 : 3444 : case PROCESSOR_ZNVER2:
435 : 3444 : case PROCESSOR_ZNVER3:
436 : 3444 : case PROCESSOR_ZNVER4:
437 : 3444 : case PROCESSOR_ZNVER5:
438 : : /* Stack engine allows to execute push&pop instructions in parall. */
439 : 3444 : if ((insn_type == TYPE_PUSH || insn_type == TYPE_POP)
440 : 469 : && (dep_insn_type == TYPE_PUSH || dep_insn_type == TYPE_POP))
441 : : return 0;
442 : :
443 : 3250 : memory = get_attr_memory (insn);
444 : :
445 : : /* Show ability of reorder buffer to hide latency of load by executing
446 : : in parallel with previous instruction in case
447 : : previous instruction is not needed to compute the address. */
448 : 3250 : if ((memory == MEMORY_LOAD || memory == MEMORY_BOTH)
449 : 3250 : && !ix86_agi_dependent (dep_insn, insn))
450 : : {
451 : 514 : enum attr_unit unit = get_attr_unit (insn);
452 : 514 : int loadcost;
453 : :
454 : : /* TODO: On znver5 complex addressing modes have
455 : : greater latency. */
456 : 514 : if (unit == UNIT_INTEGER || unit == UNIT_UNKNOWN)
457 : : loadcost = 4;
458 : : else
459 : 361 : loadcost = 7;
460 : :
461 : 514 : if (cost >= loadcost)
462 : 52 : cost -= loadcost;
463 : : else
464 : : cost = 0;
465 : : }
466 : : break;
467 : :
468 : 0 : case PROCESSOR_YONGFENG:
469 : 0 : case PROCESSOR_SHIJIDADAO:
470 : : /* Stack engine allows to execute push&pop instructions in parallel. */
471 : 0 : if ((insn_type == TYPE_PUSH || insn_type == TYPE_POP)
472 : 0 : && (dep_insn_type == TYPE_PUSH || dep_insn_type == TYPE_POP))
473 : : return 0;
474 : : /* FALLTHRU */
475 : :
476 : 0 : case PROCESSOR_LUJIAZUI:
477 : 0 : memory = get_attr_memory (insn);
478 : :
479 : : /* Show ability of reorder buffer to hide latency of load by executing
480 : : in parallel with previous instruction in case
481 : : previous instruction is not needed to compute the address. */
482 : 0 : if ((memory == MEMORY_LOAD || memory == MEMORY_BOTH)
483 : 0 : && !ix86_agi_dependent (dep_insn, insn))
484 : : {
485 : 0 : int loadcost = 4;
486 : :
487 : 0 : if (cost >= loadcost)
488 : 0 : cost -= loadcost;
489 : : else
490 : : cost = 0;
491 : : }
492 : : break;
493 : :
494 : 51748182 : case PROCESSOR_CORE2:
495 : 51748182 : case PROCESSOR_NEHALEM:
496 : 51748182 : case PROCESSOR_SANDYBRIDGE:
497 : 51748182 : case PROCESSOR_HASWELL:
498 : 51748182 : case PROCESSOR_TREMONT:
499 : 51748182 : case PROCESSOR_ALDERLAKE:
500 : 51748182 : case PROCESSOR_INTEL:
501 : 51748182 : case PROCESSOR_GENERIC:
502 : : /* Stack engine allows to execute push&pop instructions in parall. */
503 : 51748182 : if ((insn_type == TYPE_PUSH || insn_type == TYPE_POP)
504 : 8768813 : && (dep_insn_type == TYPE_PUSH || dep_insn_type == TYPE_POP))
505 : : return 0;
506 : :
507 : 46154928 : memory = get_attr_memory (insn);
508 : :
509 : : /* Show ability of reorder buffer to hide latency of load by executing
510 : : in parallel with previous instruction in case
511 : : previous instruction is not needed to compute the address. */
512 : 46154928 : if ((memory == MEMORY_LOAD || memory == MEMORY_BOTH)
513 : 46154928 : && !ix86_agi_dependent (dep_insn, insn))
514 : : {
515 : 6132816 : if (cost >= 4)
516 : 205505 : cost -= 4;
517 : : else
518 : : cost = 0;
519 : : }
520 : : break;
521 : :
522 : 937 : case PROCESSOR_SILVERMONT:
523 : 937 : if (!reload_completed)
524 : : return cost;
525 : :
526 : : /* Increase cost of integer loads. */
527 : 937 : memory = get_attr_memory (dep_insn);
528 : 937 : if (memory == MEMORY_LOAD || memory == MEMORY_BOTH)
529 : : {
530 : 214 : enum attr_unit unit = get_attr_unit (dep_insn);
531 : 214 : if (unit == UNIT_INTEGER && cost == 1)
532 : : {
533 : 165 : if (memory == MEMORY_LOAD)
534 : : cost = 3;
535 : : else
536 : : {
537 : : /* Increase cost of ld/st for short int types only
538 : : because of store forwarding issue. */
539 : 0 : rtx set = single_set (dep_insn);
540 : 0 : if (set && (GET_MODE (SET_DEST (set)) == QImode
541 : 0 : || GET_MODE (SET_DEST (set)) == HImode))
542 : : {
543 : : /* Increase cost of store/load insn if exact
544 : : dependence exists and it is load insn. */
545 : 0 : enum attr_memory insn_memory = get_attr_memory (insn);
546 : 0 : if (insn_memory == MEMORY_LOAD
547 : 0 : && exact_store_load_dependency (dep_insn, insn))
548 : : cost = 3;
549 : : }
550 : : }
551 : : }
552 : : }
553 : :
554 : : default:
555 : : break;
556 : : }
557 : :
558 : : return cost;
559 : : }
560 : :
561 : : /* How many alternative schedules to try. This should be as wide as the
562 : : scheduling freedom in the DFA, but no wider. Making this value too
563 : : large results extra work for the scheduler. */
564 : :
565 : : int
566 : 948147 : ia32_multipass_dfa_lookahead (void)
567 : : {
568 : : /* Generally, we want haifa-sched:max_issue() to look ahead as far
569 : : as many instructions can be executed on a cycle, i.e.,
570 : : issue_rate. */
571 : 948147 : if (reload_completed)
572 : 947895 : return ix86_issue_rate ();
573 : : /* Don't use lookahead for pre-reload schedule to save compile time. */
574 : : return 0;
575 : : }
576 : :
577 : : /* Return true if target platform supports macro-fusion. */
578 : :
579 : : bool
580 : 105587646 : ix86_macro_fusion_p ()
581 : : {
582 : 105587646 : return TARGET_FUSE_CMP_AND_BRANCH;
583 : : }
584 : :
585 : : /* Check whether MOV is a reg-reg move and ALU is an
586 : : ALU operation that allows macro-op fusion. */
587 : :
588 : : static bool
589 : 768 : ix86_fuse_mov_alu_p (rtx_insn *mov, rtx_insn *alu)
590 : : {
591 : : /* Validate mov:
592 : : - It should be reg-reg move with opcode 0x89 or 0x8B. */
593 : 768 : rtx set1 = PATTERN (mov);
594 : 768 : if (GET_CODE (set1) != SET
595 : 625 : || !GENERAL_REG_P (SET_SRC (set1))
596 : 915 : || !GENERAL_REG_P (SET_DEST (set1)))
597 : : return false;
598 : 48 : rtx reg = SET_DEST (set1);
599 : : /* - it should have 0x89 or 0x8B opcode. */
600 : 48 : if (!INTEGRAL_MODE_P (GET_MODE (reg))
601 : 96 : || GET_MODE_SIZE (GET_MODE (reg)) < 2
602 : 96 : || GET_MODE_SIZE (GET_MODE (reg)) > 8)
603 : : return false;
604 : : /* Validate ALU. */
605 : 48 : if (GET_CODE (PATTERN (alu)) != PARALLEL)
606 : : return false;
607 : 1 : rtx set2 = XVECEXP (PATTERN (alu), 0, 0);
608 : 1 : if (GET_CODE (set2) != SET)
609 : : return false;
610 : : /* If this is instruction setting both compare and normal
611 : : register, the first set always sets flags, while
612 : : second set writes to the output operan. Pick
613 : : the second set. */
614 : 1 : if (GET_CODE (SET_SRC (set2)) == COMPARE)
615 : : {
616 : 0 : set2 = XVECEXP (PATTERN (alu), 0, 1);
617 : 0 : if (GET_CODE (set2) != SET)
618 : : return false;
619 : : }
620 : : /* Match one of:
621 : : ADD ADC AND XOR OR SUB SBB INC DEC NOT SAL SHL SHR SAR
622 : : We also may add insn attribute to handle some of sporadic
623 : : case we output those with different RTX expressions. */
624 : :
625 : 1 : if (GET_CODE (SET_SRC (set2)) != PLUS
626 : 1 : && GET_CODE (SET_SRC (set2)) != MINUS
627 : : && GET_CODE (SET_SRC (set2)) != XOR
628 : : && GET_CODE (SET_SRC (set2)) != AND
629 : : && GET_CODE (SET_SRC (set2)) != IOR
630 : : && GET_CODE (SET_SRC (set2)) != NOT
631 : : && GET_CODE (SET_SRC (set2)) != ASHIFT
632 : : && GET_CODE (SET_SRC (set2)) != ASHIFTRT
633 : : && GET_CODE (SET_SRC (set2)) != LSHIFTRT)
634 : : return false;
635 : 1 : rtx op0 = XEXP (SET_SRC (set2), 0);
636 : 1 : rtx op1 = GET_CODE (SET_SRC (set2)) != NOT ? XEXP (SET_SRC (set2), 1) : NULL;
637 : : /* One of operands should be register. */
638 : 1 : if (op1 && (!REG_P (op0) || REGNO (op0) != REGNO (reg)))
639 : : std::swap (op0, op1);
640 : 1 : if (!REG_P (op0) || REGNO (op0) != REGNO (reg))
641 : : return false;
642 : 0 : if (op1
643 : 0 : && !REG_P (op1)
644 : 0 : && !x86_64_immediate_operand (op1, VOIDmode))
645 : : return false;
646 : : /* Only one of two parameters must be move destination. */
647 : 0 : if (op1 && REG_P (op1) && REGNO (op1) == REGNO (reg))
648 : : return false;
649 : : return true;
650 : : }
651 : :
652 : : /* Check whether current microarchitecture support macro fusion
653 : : for insn pair "CONDGEN + CONDJMP". Refer to
654 : : "Intel Architectures Optimization Reference Manual". */
655 : :
656 : : bool
657 : 41939083 : ix86_macro_fusion_pair_p (rtx_insn *condgen, rtx_insn *condjmp)
658 : : {
659 : 41939083 : if (TARGET_FUSE_MOV_AND_ALU
660 : 41939083 : && ix86_fuse_mov_alu_p (condgen, condjmp))
661 : : return true;
662 : 41939083 : rtx src, imm = NULL_RTX;
663 : 41939083 : enum rtx_code ccode;
664 : 41939083 : rtx compare_set = NULL_RTX, test_if, cond;
665 : 41939083 : rtx alu_set = NULL_RTX, addr = NULL_RTX;
666 : 41939083 : rtx alu_clobber = NULL_RTX;
667 : 41939083 : enum attr_type condgen_type;
668 : :
669 : 41939083 : if (!any_condjump_p (condjmp))
670 : : return false;
671 : :
672 : 4587583 : unsigned int condreg1, condreg2;
673 : 4587583 : rtx cc_reg_1;
674 : 4587583 : targetm.fixed_condition_code_regs (&condreg1, &condreg2);
675 : 4587583 : cc_reg_1 = gen_rtx_REG (CCmode, condreg1);
676 : 4587583 : if (!reg_referenced_p (cc_reg_1, PATTERN (condjmp))
677 : 4587583 : || !condgen
678 : 9175166 : || !modified_in_p (cc_reg_1, condgen))
679 : 120124 : return false;
680 : :
681 : 4467459 : condgen_type = get_attr_type (condgen);
682 : 4467459 : if (condgen_type == TYPE_MULTI
683 : 165 : && INSN_CODE (condgen) == code_for_stack_protect_test_1 (ptr_mode)
684 : 4467624 : && TARGET_FUSE_ALU_AND_BRANCH)
685 : : {
686 : : /* stack_protect_test_<mode> ends with a sub, which subtracts
687 : : a non-rip special memory operand from a GPR. */
688 : 165 : src = NULL_RTX;
689 : 165 : alu_set = XVECEXP (PATTERN (condgen), 0, 1);
690 : 165 : goto handle_stack_protect_test;
691 : : }
692 : : /* ??? zen5 can fuse cmp, test, sub, add, inc, dec, or, and xor.
693 : : Cores can not fuse or and xor which will pass the test below
694 : : since type is ALU. */
695 : 4467294 : else if (condgen_type != TYPE_TEST
696 : 4467294 : && condgen_type != TYPE_ICMP
697 : 4467294 : && condgen_type != TYPE_INCDEC
698 : 394917 : && condgen_type != TYPE_ALU)
699 : : return false;
700 : :
701 : 4254369 : compare_set = single_set (condgen);
702 : 4254369 : if (compare_set == NULL_RTX && !TARGET_FUSE_ALU_AND_BRANCH)
703 : : return false;
704 : :
705 : 77946 : if (compare_set == NULL_RTX)
706 : : {
707 : 77946 : int i;
708 : 77946 : rtx pat = PATTERN (condgen);
709 : 233838 : for (i = 0; i < XVECLEN (pat, 0); i++)
710 : 155892 : if (GET_CODE (XVECEXP (pat, 0, i)) == SET)
711 : : {
712 : 155892 : rtx set_src = SET_SRC (XVECEXP (pat, 0, i));
713 : 155892 : if (GET_CODE (set_src) == COMPARE)
714 : : compare_set = XVECEXP (pat, 0, i);
715 : : else
716 : 82350 : alu_set = XVECEXP (pat, 0, i);
717 : : }
718 : : /* We also possibly generated ALU instruction only to set
719 : : flags. In this case there will be clobber. */
720 : 0 : else if (GET_CODE (XVECEXP (pat, 0, i)) == CLOBBER
721 : 0 : && GENERAL_REG_P (XEXP (XVECEXP (pat, 0, i), 0)))
722 : : alu_clobber = XVECEXP (pat, 0, i);
723 : : }
724 : 77946 : if (compare_set == NULL_RTX)
725 : : return false;
726 : 4249950 : src = SET_SRC (compare_set);
727 : 4249950 : if (GET_CODE (src) != COMPARE)
728 : : return false;
729 : :
730 : : /* Check for memory operand. */
731 : 4244108 : if (MEM_P (XEXP (src, 0)))
732 : 557001 : addr = XEXP (XEXP (src, 0), 0);
733 : 3687107 : else if (MEM_P (XEXP (src, 1)))
734 : 360517 : addr = XEXP (XEXP (src, 1), 0);
735 : : /* Some CPUs, i.e. tigerlake and cooperlake does not fuse
736 : : ALU with memory operand. */
737 : 917518 : if (addr && !TARGET_FUSE_ALU_AND_BRANCH_MEM)
738 : : return false;
739 : 4244099 : if (CONST_INT_P (XEXP (src, 0)))
740 : : imm = XEXP (src, 0);
741 : 4244099 : else if (CONST_INT_P (XEXP (src, 1)))
742 : : imm = XEXP (src, 1);
743 : : /* Check that the instruction really has immediate.
744 : : In particular compare with 0 is done using test with no immediate. */
745 : 2753904 : if (imm && !get_attr_length_immediate (condgen))
746 : : imm = NULL;
747 : : /* Macro-fusion for cmp/test MEM-IMM + conditional jmp is not
748 : : supported. */
749 : 4244099 : if (addr && imm && !TARGET_FUSE_ALU_AND_BRANCH_MEM_IMM)
750 : : return false;
751 : :
752 : : /* No fusion for RIP-relative address. */
753 : 4243983 : if (addr && !TARGET_FUSE_ALU_AND_BRANCH_RIP_RELATIVE)
754 : : {
755 : 917393 : ix86_address parts;
756 : 917393 : int ok = ix86_decompose_address (addr, &parts);
757 : 917393 : gcc_assert (ok);
758 : :
759 : 917393 : if (ix86_rip_relative_addr_p (&parts))
760 : 68075 : return false;
761 : : }
762 : : /* Znver5 supports fussion fusion with their reg/reg, reg/imm and
763 : : reg/mem forms. They are also supported when the instruction has an
764 : : immediate and displacement that meets the criteria of 4 byte displacement
765 : : and 2 byte immediate or the case of 2 byte displacement and 4 byte
766 : : immediate. We do not know the displacement size, so we ignore this
767 : : limitation. */
768 : :
769 : 3326590 : handle_stack_protect_test:
770 : 4176073 : test_if = SET_SRC (pc_set (condjmp));
771 : 4176073 : cond = XEXP (test_if, 0);
772 : 4176073 : ccode = GET_CODE (cond);
773 : : /* Check whether conditional jump use Sign or Overflow Flags. */
774 : 4176073 : if (!TARGET_FUSE_CMP_AND_BRANCH_SOFLAGS
775 : 0 : && (ccode == GE || ccode == GT || ccode == LE || ccode == LT))
776 : : return false;
777 : :
778 : : /* Return true for TYPE_TEST and TYPE_ICMP. */
779 : 4176073 : if (condgen_type == TYPE_TEST || condgen_type == TYPE_ICMP)
780 : : return true;
781 : :
782 : : /* The following is the case that macro-fusion for alu + jmp. */
783 : 177906 : if (!TARGET_FUSE_ALU_AND_BRANCH || (!alu_set && !alu_clobber))
784 : : return false;
785 : :
786 : : /* No fusion for alu op with memory destination operand. */
787 : 73707 : if (alu_set && MEM_P (SET_DEST (alu_set)))
788 : : return false;
789 : :
790 : :
791 : : /* Macro-fusion for inc/dec + unsigned conditional jump is not
792 : : supported on some CPUs while supported on others (znver5 and core_avx512).
793 : : We however never generate it, so we do not need a specific tune for it. */
794 : 70718 : gcc_checking_assert (!(condgen_type == TYPE_INCDEC
795 : : && (ccode == GEU || ccode == GTU || ccode == LEU || ccode == LTU)));
796 : :
797 : : return true;
798 : : }
|