Branch data Line data Source code
1 : : /* Scheduler hooks for IA-32 which implement CPU specific logic.
2 : : Copyright (C) 1988-2024 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 : :
36 : : /* Return the maximum number of instructions a cpu can issue. */
37 : :
38 : : int
39 : 34127808 : ix86_issue_rate (void)
40 : : {
41 : 34127808 : switch (ix86_tune)
42 : : {
43 : : case PROCESSOR_PENTIUM:
44 : : case PROCESSOR_LAKEMONT:
45 : : case PROCESSOR_BONNELL:
46 : : case PROCESSOR_SILVERMONT:
47 : : case PROCESSOR_KNL:
48 : : case PROCESSOR_KNM:
49 : : case PROCESSOR_INTEL:
50 : : case PROCESSOR_K6:
51 : : case PROCESSOR_BTVER2:
52 : : case PROCESSOR_PENTIUM4:
53 : : case PROCESSOR_NOCONA:
54 : : return 2;
55 : :
56 : : case PROCESSOR_PENTIUMPRO:
57 : : case PROCESSOR_ATHLON:
58 : : case PROCESSOR_K8:
59 : : case PROCESSOR_AMDFAM10:
60 : : case PROCESSOR_BTVER1:
61 : : case PROCESSOR_LUJIAZUI:
62 : : return 3;
63 : :
64 : : case PROCESSOR_BDVER1:
65 : : case PROCESSOR_BDVER2:
66 : : case PROCESSOR_BDVER3:
67 : : case PROCESSOR_BDVER4:
68 : : case PROCESSOR_ZNVER1:
69 : : case PROCESSOR_ZNVER2:
70 : : case PROCESSOR_ZNVER3:
71 : : case PROCESSOR_ZNVER4:
72 : : case PROCESSOR_ZNVER5:
73 : : case PROCESSOR_CORE2:
74 : : case PROCESSOR_NEHALEM:
75 : : case PROCESSOR_SANDYBRIDGE:
76 : : case PROCESSOR_HASWELL:
77 : : case PROCESSOR_TREMONT:
78 : : case PROCESSOR_SKYLAKE:
79 : : case PROCESSOR_SKYLAKE_AVX512:
80 : : case PROCESSOR_CASCADELAKE:
81 : : case PROCESSOR_CANNONLAKE:
82 : : case PROCESSOR_ALDERLAKE:
83 : : case PROCESSOR_YONGFENG:
84 : : case PROCESSOR_GENERIC:
85 : : return 4;
86 : :
87 : : case PROCESSOR_ICELAKE_CLIENT:
88 : : case PROCESSOR_ICELAKE_SERVER:
89 : : case PROCESSOR_TIGERLAKE:
90 : : case PROCESSOR_COOPERLAKE:
91 : : case PROCESSOR_ROCKETLAKE:
92 : : return 5;
93 : :
94 : : case PROCESSOR_SAPPHIRERAPIDS:
95 : : return 6;
96 : :
97 : : default:
98 : : return 1;
99 : : }
100 : : }
101 : :
102 : : /* Return true iff USE_INSN has a memory address with operands set by
103 : : SET_INSN. */
104 : :
105 : : bool
106 : 9704304 : ix86_agi_dependent (rtx_insn *set_insn, rtx_insn *use_insn)
107 : : {
108 : 9704304 : int i;
109 : 9704304 : extract_insn_cached (use_insn);
110 : 11907416 : for (i = recog_data.n_operands - 1; i >= 0; --i)
111 : 11554828 : if (MEM_P (recog_data.operand[i]))
112 : : {
113 : 9351716 : rtx addr = XEXP (recog_data.operand[i], 0);
114 : 9351716 : if (modified_in_p (addr, set_insn) != 0)
115 : : {
116 : : /* No AGI stall if SET_INSN is a push or pop and USE_INSN
117 : : has SP based memory (unless index reg is modified in a pop). */
118 : 4359757 : rtx set = single_set (set_insn);
119 : 4359757 : if (set
120 : 4359757 : && (push_operand (SET_DEST (set), GET_MODE (SET_DEST (set)))
121 : 3610415 : || pop_operand (SET_SRC (set), GET_MODE (SET_SRC (set)))))
122 : : {
123 : 545623 : struct ix86_address parts;
124 : 545623 : if (ix86_decompose_address (addr, &parts)
125 : 545623 : && parts.base == stack_pointer_rtx
126 : 1090997 : && (parts.index == NULL_RTX
127 : 642 : || MEM_P (SET_DEST (set))
128 : 14 : || !modified_in_p (parts.index, set_insn)))
129 : 545371 : return false;
130 : : }
131 : 3814386 : return true;
132 : : }
133 : : return false;
134 : : }
135 : : return false;
136 : : }
137 : :
138 : : /* A subroutine of ix86_adjust_cost -- return TRUE iff INSN reads flags set
139 : : by DEP_INSN and nothing set by DEP_INSN. */
140 : :
141 : : static bool
142 : 0 : ix86_flags_dependent (rtx_insn *insn, rtx_insn *dep_insn, enum attr_type insn_type)
143 : : {
144 : 0 : rtx set, set2;
145 : :
146 : : /* Simplify the test for uninteresting insns. */
147 : 0 : if (insn_type != TYPE_SETCC
148 : 0 : && insn_type != TYPE_ICMOV
149 : 0 : && insn_type != TYPE_FCMOV
150 : 0 : && insn_type != TYPE_IBR)
151 : : return false;
152 : :
153 : 0 : if ((set = single_set (dep_insn)) != 0)
154 : : {
155 : 0 : set = SET_DEST (set);
156 : 0 : set2 = NULL_RTX;
157 : : }
158 : 0 : else if (GET_CODE (PATTERN (dep_insn)) == PARALLEL
159 : 0 : && XVECLEN (PATTERN (dep_insn), 0) == 2
160 : 0 : && GET_CODE (XVECEXP (PATTERN (dep_insn), 0, 0)) == SET
161 : 0 : && GET_CODE (XVECEXP (PATTERN (dep_insn), 0, 1)) == SET)
162 : : {
163 : 0 : set = SET_DEST (XVECEXP (PATTERN (dep_insn), 0, 0));
164 : 0 : set2 = SET_DEST (XVECEXP (PATTERN (dep_insn), 0, 0));
165 : : }
166 : : else
167 : : return false;
168 : :
169 : 0 : if (!REG_P (set) || REGNO (set) != FLAGS_REG)
170 : : return false;
171 : :
172 : : /* This test is true if the dependent insn reads the flags but
173 : : not any other potentially set register. */
174 : 0 : if (!reg_overlap_mentioned_p (set, PATTERN (insn)))
175 : : return false;
176 : :
177 : 0 : if (set2 && reg_overlap_mentioned_p (set2, PATTERN (insn)))
178 : : return false;
179 : :
180 : : return true;
181 : : }
182 : :
183 : : /* Helper function for exact_store_load_dependency.
184 : : Return true if addr is found in insn. */
185 : : static bool
186 : 0 : exact_dependency_1 (rtx addr, rtx insn)
187 : : {
188 : 0 : enum rtx_code code;
189 : 0 : const char *format_ptr;
190 : 0 : int i, j;
191 : :
192 : 0 : code = GET_CODE (insn);
193 : 0 : switch (code)
194 : : {
195 : 0 : case MEM:
196 : 0 : if (rtx_equal_p (addr, insn))
197 : : return true;
198 : : break;
199 : : case REG:
200 : : CASE_CONST_ANY:
201 : : case SYMBOL_REF:
202 : : case CODE_LABEL:
203 : : case PC:
204 : : case EXPR_LIST:
205 : : return false;
206 : : default:
207 : : break;
208 : : }
209 : :
210 : 0 : format_ptr = GET_RTX_FORMAT (code);
211 : 0 : for (i = 0; i < GET_RTX_LENGTH (code); i++)
212 : : {
213 : 0 : switch (*format_ptr++)
214 : : {
215 : 0 : case 'e':
216 : 0 : if (exact_dependency_1 (addr, XEXP (insn, i)))
217 : : return true;
218 : : break;
219 : : case 'E':
220 : 0 : for (j = 0; j < XVECLEN (insn, i); j++)
221 : 0 : if (exact_dependency_1 (addr, XVECEXP (insn, i, j)))
222 : : return true;
223 : : break;
224 : : }
225 : : }
226 : : return false;
227 : : }
228 : :
229 : : /* Return true if there exists exact dependency for store & load, i.e.
230 : : the same memory address is used in them. */
231 : : static bool
232 : 0 : exact_store_load_dependency (rtx_insn *store, rtx_insn *load)
233 : : {
234 : 0 : rtx set1, set2;
235 : :
236 : 0 : set1 = single_set (store);
237 : 0 : if (!set1)
238 : : return false;
239 : 0 : if (!MEM_P (SET_DEST (set1)))
240 : : return false;
241 : 0 : set2 = single_set (load);
242 : 0 : if (!set2)
243 : : return false;
244 : 0 : if (exact_dependency_1 (SET_DEST (set1), SET_SRC (set2)))
245 : : return true;
246 : : return false;
247 : : }
248 : :
249 : :
250 : : /* This function corrects the value of COST (latency) based on the relationship
251 : : between INSN and DEP_INSN through a dependence of type DEP_TYPE, and strength
252 : : DW. It should return the new value.
253 : :
254 : : On x86 CPUs this is most commonly used to model the fact that valus of
255 : : registers used to compute address of memory operand needs to be ready
256 : : earlier than values of registers used in the actual operation. */
257 : :
258 : : int
259 : 143949201 : ix86_adjust_cost (rtx_insn *insn, int dep_type, rtx_insn *dep_insn, int cost,
260 : : unsigned int)
261 : : {
262 : 143949201 : enum attr_type insn_type, dep_insn_type;
263 : 143949201 : enum attr_memory memory;
264 : 143949201 : rtx set, set2;
265 : 143949201 : int dep_insn_code_number;
266 : :
267 : : /* Anti and output dependencies have zero cost on all CPUs. */
268 : 143949201 : if (dep_type != 0)
269 : : return 0;
270 : :
271 : 51874173 : dep_insn_code_number = recog_memoized (dep_insn);
272 : :
273 : : /* If we can't recognize the insns, we can't really do anything. */
274 : 51874173 : if (dep_insn_code_number < 0 || recog_memoized (insn) < 0)
275 : 343548 : return cost;
276 : :
277 : 51530625 : insn_type = get_attr_type (insn);
278 : 51530625 : dep_insn_type = get_attr_type (dep_insn);
279 : :
280 : 51530625 : switch (ix86_tune)
281 : : {
282 : 0 : case PROCESSOR_PENTIUM:
283 : 0 : case PROCESSOR_LAKEMONT:
284 : : /* Address Generation Interlock adds a cycle of latency. */
285 : 0 : if (insn_type == TYPE_LEA)
286 : : {
287 : 0 : rtx addr = PATTERN (insn);
288 : :
289 : 0 : if (GET_CODE (addr) == PARALLEL)
290 : 0 : addr = XVECEXP (addr, 0, 0);
291 : :
292 : 0 : gcc_assert (GET_CODE (addr) == SET);
293 : :
294 : 0 : addr = SET_SRC (addr);
295 : 0 : if (modified_in_p (addr, dep_insn))
296 : 0 : cost += 1;
297 : : }
298 : 0 : else if (ix86_agi_dependent (dep_insn, insn))
299 : 0 : cost += 1;
300 : :
301 : : /* ??? Compares pair with jump/setcc. */
302 : 0 : if (ix86_flags_dependent (insn, dep_insn, insn_type))
303 : 0 : cost = 0;
304 : :
305 : : /* Floating point stores require value to be ready one cycle earlier. */
306 : 0 : if (insn_type == TYPE_FMOV
307 : 0 : && get_attr_memory (insn) == MEMORY_STORE
308 : 0 : && !ix86_agi_dependent (dep_insn, insn))
309 : 0 : cost += 1;
310 : : break;
311 : :
312 : 0 : case PROCESSOR_PENTIUMPRO:
313 : : /* INT->FP conversion is expensive. */
314 : 0 : if (get_attr_fp_int_src (dep_insn))
315 : 0 : cost += 5;
316 : :
317 : : /* There is one cycle extra latency between an FP op and a store. */
318 : 0 : if (insn_type == TYPE_FMOV
319 : 0 : && (set = single_set (dep_insn)) != NULL_RTX
320 : 0 : && (set2 = single_set (insn)) != NULL_RTX
321 : 0 : && rtx_equal_p (SET_DEST (set), SET_SRC (set2))
322 : 0 : && MEM_P (SET_DEST (set2)))
323 : 0 : cost += 1;
324 : :
325 : 0 : memory = get_attr_memory (insn);
326 : :
327 : : /* Show ability of reorder buffer to hide latency of load by executing
328 : : in parallel with previous instruction in case
329 : : previous instruction is not needed to compute the address. */
330 : 0 : if ((memory == MEMORY_LOAD || memory == MEMORY_BOTH)
331 : 0 : && !ix86_agi_dependent (dep_insn, insn))
332 : : {
333 : : /* Claim moves to take one cycle, as core can issue one load
334 : : at time and the next load can start cycle later. */
335 : 0 : if (dep_insn_type == TYPE_IMOV
336 : 0 : || dep_insn_type == TYPE_FMOV)
337 : : cost = 1;
338 : 0 : else if (cost > 1)
339 : 0 : cost--;
340 : : }
341 : : break;
342 : :
343 : 0 : case PROCESSOR_K6:
344 : : /* The esp dependency is resolved before
345 : : the instruction is really finished. */
346 : 0 : if ((insn_type == TYPE_PUSH || insn_type == TYPE_POP)
347 : 0 : && (dep_insn_type == TYPE_PUSH || dep_insn_type == TYPE_POP))
348 : : return 1;
349 : :
350 : : /* INT->FP conversion is expensive. */
351 : 0 : if (get_attr_fp_int_src (dep_insn))
352 : 0 : cost += 5;
353 : :
354 : 0 : memory = get_attr_memory (insn);
355 : :
356 : : /* Show ability of reorder buffer to hide latency of load by executing
357 : : in parallel with previous instruction in case
358 : : previous instruction is not needed to compute the address. */
359 : 0 : if ((memory == MEMORY_LOAD || memory == MEMORY_BOTH)
360 : 0 : && !ix86_agi_dependent (dep_insn, insn))
361 : : {
362 : : /* Claim moves to take one cycle, as core can issue one load
363 : : at time and the next load can start cycle later. */
364 : 0 : if (dep_insn_type == TYPE_IMOV
365 : 0 : || dep_insn_type == TYPE_FMOV)
366 : : cost = 1;
367 : 0 : else if (cost > 2)
368 : 0 : cost -= 2;
369 : : else
370 : : cost = 1;
371 : : }
372 : : break;
373 : :
374 : 10682 : case PROCESSOR_AMDFAM10:
375 : 10682 : case PROCESSOR_BDVER1:
376 : 10682 : case PROCESSOR_BDVER2:
377 : 10682 : case PROCESSOR_BDVER3:
378 : 10682 : case PROCESSOR_BDVER4:
379 : 10682 : case PROCESSOR_BTVER1:
380 : 10682 : case PROCESSOR_BTVER2:
381 : : /* Stack engine allows to execute push&pop instructions in parall. */
382 : 10682 : if ((insn_type == TYPE_PUSH || insn_type == TYPE_POP)
383 : 325 : && (dep_insn_type == TYPE_PUSH || dep_insn_type == TYPE_POP))
384 : : return 0;
385 : : /* FALLTHRU */
386 : :
387 : 72108 : case PROCESSOR_ATHLON:
388 : 72108 : case PROCESSOR_K8:
389 : 72108 : memory = get_attr_memory (insn);
390 : :
391 : : /* Show ability of reorder buffer to hide latency of load by executing
392 : : in parallel with previous instruction in case
393 : : previous instruction is not needed to compute the address. */
394 : 72108 : if ((memory == MEMORY_LOAD || memory == MEMORY_BOTH)
395 : 72108 : && !ix86_agi_dependent (dep_insn, insn))
396 : : {
397 : 11181 : enum attr_unit unit = get_attr_unit (insn);
398 : 11181 : int loadcost = 3;
399 : :
400 : : /* Because of the difference between the length of integer and
401 : : floating unit pipeline preparation stages, the memory operands
402 : : for floating point are cheaper.
403 : :
404 : : ??? For Athlon it the difference is most probably 2. */
405 : 11181 : if (unit == UNIT_INTEGER || unit == UNIT_UNKNOWN)
406 : : loadcost = 3;
407 : : else
408 : 6317 : loadcost = TARGET_CPU_P (ATHLON) ? 2 : 0;
409 : :
410 : 11181 : if (cost >= loadcost)
411 : 7070 : cost -= loadcost;
412 : : else
413 : : cost = 0;
414 : : }
415 : : break;
416 : :
417 : 604 : case PROCESSOR_ZNVER1:
418 : 604 : case PROCESSOR_ZNVER2:
419 : 604 : case PROCESSOR_ZNVER3:
420 : 604 : case PROCESSOR_ZNVER4:
421 : 604 : case PROCESSOR_ZNVER5:
422 : : /* Stack engine allows to execute push&pop instructions in parall. */
423 : 604 : if ((insn_type == TYPE_PUSH || insn_type == TYPE_POP)
424 : 83 : && (dep_insn_type == TYPE_PUSH || dep_insn_type == TYPE_POP))
425 : : return 0;
426 : :
427 : 556 : memory = get_attr_memory (insn);
428 : :
429 : : /* Show ability of reorder buffer to hide latency of load by executing
430 : : in parallel with previous instruction in case
431 : : previous instruction is not needed to compute the address. */
432 : 556 : if ((memory == MEMORY_LOAD || memory == MEMORY_BOTH)
433 : 556 : && !ix86_agi_dependent (dep_insn, insn))
434 : : {
435 : 37 : enum attr_unit unit = get_attr_unit (insn);
436 : 37 : int loadcost;
437 : :
438 : 37 : if (unit == UNIT_INTEGER || unit == UNIT_UNKNOWN)
439 : : loadcost = 4;
440 : : else
441 : 29 : loadcost = 7;
442 : :
443 : 37 : if (cost >= loadcost)
444 : 12 : cost -= loadcost;
445 : : else
446 : : cost = 0;
447 : : }
448 : : break;
449 : :
450 : 0 : case PROCESSOR_YONGFENG:
451 : : /* Stack engine allows to execute push&pop instructions in parallel. */
452 : 0 : if ((insn_type == TYPE_PUSH || insn_type == TYPE_POP)
453 : 0 : && (dep_insn_type == TYPE_PUSH || dep_insn_type == TYPE_POP))
454 : : return 0;
455 : : /* FALLTHRU */
456 : :
457 : 0 : case PROCESSOR_LUJIAZUI:
458 : 0 : memory = get_attr_memory (insn);
459 : :
460 : : /* Show ability of reorder buffer to hide latency of load by executing
461 : : in parallel with previous instruction in case
462 : : previous instruction is not needed to compute the address. */
463 : 0 : if ((memory == MEMORY_LOAD || memory == MEMORY_BOTH)
464 : 0 : && !ix86_agi_dependent (dep_insn, insn))
465 : : {
466 : 0 : int loadcost = 4;
467 : :
468 : 0 : if (cost >= loadcost)
469 : 0 : cost -= loadcost;
470 : : else
471 : : cost = 0;
472 : : }
473 : : break;
474 : :
475 : 51420136 : case PROCESSOR_CORE2:
476 : 51420136 : case PROCESSOR_NEHALEM:
477 : 51420136 : case PROCESSOR_SANDYBRIDGE:
478 : 51420136 : case PROCESSOR_HASWELL:
479 : 51420136 : case PROCESSOR_TREMONT:
480 : 51420136 : case PROCESSOR_ALDERLAKE:
481 : 51420136 : case PROCESSOR_GENERIC:
482 : : /* Stack engine allows to execute push&pop instructions in parall. */
483 : 51420136 : if ((insn_type == TYPE_PUSH || insn_type == TYPE_POP)
484 : 10282888 : && (dep_insn_type == TYPE_PUSH || dep_insn_type == TYPE_POP))
485 : : return 0;
486 : :
487 : 44640630 : memory = get_attr_memory (insn);
488 : :
489 : : /* Show ability of reorder buffer to hide latency of load by executing
490 : : in parallel with previous instruction in case
491 : : previous instruction is not needed to compute the address. */
492 : 44640630 : if ((memory == MEMORY_LOAD || memory == MEMORY_BOTH)
493 : 44640630 : && !ix86_agi_dependent (dep_insn, insn))
494 : : {
495 : 5878637 : if (cost >= 4)
496 : 222466 : cost -= 4;
497 : : else
498 : : cost = 0;
499 : : }
500 : : break;
501 : :
502 : 4521 : case PROCESSOR_SILVERMONT:
503 : 4521 : case PROCESSOR_KNL:
504 : 4521 : case PROCESSOR_KNM:
505 : 4521 : case PROCESSOR_INTEL:
506 : 4521 : if (!reload_completed)
507 : : return cost;
508 : :
509 : : /* Increase cost of integer loads. */
510 : 4521 : memory = get_attr_memory (dep_insn);
511 : 4521 : if (memory == MEMORY_LOAD || memory == MEMORY_BOTH)
512 : : {
513 : 868 : enum attr_unit unit = get_attr_unit (dep_insn);
514 : 868 : if (unit == UNIT_INTEGER && cost == 1)
515 : : {
516 : 629 : if (memory == MEMORY_LOAD)
517 : : cost = 3;
518 : : else
519 : : {
520 : : /* Increase cost of ld/st for short int types only
521 : : because of store forwarding issue. */
522 : 0 : rtx set = single_set (dep_insn);
523 : 0 : if (set && (GET_MODE (SET_DEST (set)) == QImode
524 : 0 : || GET_MODE (SET_DEST (set)) == HImode))
525 : : {
526 : : /* Increase cost of store/load insn if exact
527 : : dependence exists and it is load insn. */
528 : 0 : enum attr_memory insn_memory = get_attr_memory (insn);
529 : 0 : if (insn_memory == MEMORY_LOAD
530 : 0 : && exact_store_load_dependency (dep_insn, insn))
531 : : cost = 3;
532 : : }
533 : : }
534 : : }
535 : : }
536 : :
537 : : default:
538 : : break;
539 : : }
540 : :
541 : : return cost;
542 : : }
543 : :
544 : : /* How many alternative schedules to try. This should be as wide as the
545 : : scheduling freedom in the DFA, but no wider. Making this value too
546 : : large results extra work for the scheduler. */
547 : :
548 : : int
549 : 901287 : ia32_multipass_dfa_lookahead (void)
550 : : {
551 : : /* Generally, we want haifa-sched:max_issue() to look ahead as far
552 : : as many instructions can be executed on a cycle, i.e.,
553 : : issue_rate. */
554 : 901287 : if (reload_completed)
555 : 901066 : return ix86_issue_rate ();
556 : : /* Don't use lookahead for pre-reload schedule to save compile time. */
557 : : return 0;
558 : : }
559 : :
560 : : /* Return true if target platform supports macro-fusion. */
561 : :
562 : : bool
563 : 90078871 : ix86_macro_fusion_p ()
564 : : {
565 : 90078871 : return TARGET_FUSE_CMP_AND_BRANCH;
566 : : }
567 : :
568 : : /* Check whether current microarchitecture support macro fusion
569 : : for insn pair "CONDGEN + CONDJMP". Refer to
570 : : "Intel Architectures Optimization Reference Manual". */
571 : :
572 : : bool
573 : 38763644 : ix86_macro_fusion_pair_p (rtx_insn *condgen, rtx_insn *condjmp)
574 : : {
575 : 38763644 : rtx src, dest;
576 : 38763644 : enum rtx_code ccode;
577 : 38763644 : rtx compare_set = NULL_RTX, test_if, cond;
578 : 38763644 : rtx alu_set = NULL_RTX, addr = NULL_RTX;
579 : 38763644 : enum attr_type condgen_type;
580 : :
581 : 38763644 : if (!any_condjump_p (condjmp))
582 : : return false;
583 : :
584 : 4126136 : unsigned int condreg1, condreg2;
585 : 4126136 : rtx cc_reg_1;
586 : 4126136 : targetm.fixed_condition_code_regs (&condreg1, &condreg2);
587 : 4126136 : cc_reg_1 = gen_rtx_REG (CCmode, condreg1);
588 : 4126136 : if (!reg_referenced_p (cc_reg_1, PATTERN (condjmp))
589 : 4126136 : || !condgen
590 : 8252272 : || !modified_in_p (cc_reg_1, condgen))
591 : 77814 : return false;
592 : :
593 : 4048322 : condgen_type = get_attr_type (condgen);
594 : 4048322 : if (condgen_type == TYPE_MULTI
595 : 147 : && INSN_CODE (condgen) == code_for_stack_protect_test_1 (ptr_mode)
596 : 4048469 : && TARGET_FUSE_ALU_AND_BRANCH)
597 : : {
598 : : /* stack_protect_test_<mode> ends with a sub, which subtracts
599 : : a non-rip special memory operand from a GPR. */
600 : 147 : src = NULL_RTX;
601 : 147 : alu_set = XVECEXP (PATTERN (condgen), 0, 1);
602 : 147 : goto handle_stack_protect_test;
603 : : }
604 : 4048175 : else if (condgen_type != TYPE_TEST
605 : 4048175 : && condgen_type != TYPE_ICMP
606 : 4048175 : && condgen_type != TYPE_INCDEC
607 : 359771 : && condgen_type != TYPE_ALU)
608 : : return false;
609 : :
610 : 3853459 : compare_set = single_set (condgen);
611 : 3853459 : if (compare_set == NULL_RTX && !TARGET_FUSE_ALU_AND_BRANCH)
612 : : return false;
613 : :
614 : 68101 : if (compare_set == NULL_RTX)
615 : : {
616 : 68101 : int i;
617 : 68101 : rtx pat = PATTERN (condgen);
618 : 204303 : for (i = 0; i < XVECLEN (pat, 0); i++)
619 : 136202 : if (GET_CODE (XVECEXP (pat, 0, i)) == SET)
620 : : {
621 : 136202 : rtx set_src = SET_SRC (XVECEXP (pat, 0, i));
622 : 136202 : if (GET_CODE (set_src) == COMPARE)
623 : : compare_set = XVECEXP (pat, 0, i);
624 : : else
625 : 72495 : alu_set = XVECEXP (pat, 0, i);
626 : : }
627 : : }
628 : 68101 : if (compare_set == NULL_RTX)
629 : : return false;
630 : 3849041 : src = SET_SRC (compare_set);
631 : 3849041 : if (GET_CODE (src) != COMPARE)
632 : : return false;
633 : :
634 : : /* Macro-fusion for cmp/test MEM-IMM + conditional jmp is not
635 : : supported. */
636 : 3843132 : if ((MEM_P (XEXP (src, 0)) && CONST_INT_P (XEXP (src, 1)))
637 : 3521212 : || (MEM_P (XEXP (src, 1)) && CONST_INT_P (XEXP (src, 0))))
638 : : return false;
639 : :
640 : : /* No fusion for RIP-relative address. */
641 : 3521212 : if (MEM_P (XEXP (src, 0)))
642 : 167833 : addr = XEXP (XEXP (src, 0), 0);
643 : 3353379 : else if (MEM_P (XEXP (src, 1)))
644 : 312736 : addr = XEXP (XEXP (src, 1), 0);
645 : :
646 : 480569 : if (addr)
647 : : {
648 : 480569 : ix86_address parts;
649 : 480569 : int ok = ix86_decompose_address (addr, &parts);
650 : 480569 : gcc_assert (ok);
651 : :
652 : 480569 : if (ix86_rip_relative_addr_p (&parts))
653 : 17559 : return false;
654 : : }
655 : :
656 : 0 : handle_stack_protect_test:
657 : 3503800 : test_if = SET_SRC (pc_set (condjmp));
658 : 3503800 : cond = XEXP (test_if, 0);
659 : 3503800 : ccode = GET_CODE (cond);
660 : : /* Check whether conditional jump use Sign or Overflow Flags. */
661 : 3503800 : if (!TARGET_FUSE_CMP_AND_BRANCH_SOFLAGS
662 : 0 : && (ccode == GE || ccode == GT || ccode == LE || ccode == LT))
663 : : return false;
664 : :
665 : : /* Return true for TYPE_TEST and TYPE_ICMP. */
666 : 3503800 : if (condgen_type == TYPE_TEST || condgen_type == TYPE_ICMP)
667 : : return true;
668 : :
669 : : /* The following is the case that macro-fusion for alu + jmp. */
670 : 159763 : if (!TARGET_FUSE_ALU_AND_BRANCH || !alu_set)
671 : : return false;
672 : :
673 : : /* No fusion for alu op with memory destination operand. */
674 : 63854 : dest = SET_DEST (alu_set);
675 : 63854 : if (MEM_P (dest))
676 : : return false;
677 : :
678 : : /* Macro-fusion for inc/dec + unsigned conditional jump is not
679 : : supported. */
680 : 62399 : if (condgen_type == TYPE_INCDEC
681 : 1190 : && (ccode == GEU || ccode == GTU || ccode == LEU || ccode == LTU))
682 : : return false;
683 : :
684 : : return true;
685 : : }
686 : :
|