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