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