Branch data Line data Source code
1 : : /* Copyright (C) 1988-2025 Free Software Foundation, Inc.
2 : :
3 : : This file is part of GCC.
4 : :
5 : : GCC is free software; you can redistribute it and/or modify
6 : : it under the terms of the GNU General Public License as published by
7 : : the Free Software Foundation; either version 3, or (at your option)
8 : : any later version.
9 : :
10 : : GCC is distributed in the hope that it will be useful,
11 : : but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 : : GNU General Public License for more details.
14 : :
15 : : You should have received a copy of the GNU General Public License
16 : : along with GCC; see the file COPYING3. If not see
17 : : <http://www.gnu.org/licenses/>. */
18 : :
19 : : #define IN_TARGET_CODE 1
20 : :
21 : : #include "config.h"
22 : : #include "system.h"
23 : : #include "coretypes.h"
24 : : #include "backend.h"
25 : : #include "rtl.h"
26 : : #include "tree.h"
27 : : #include "memmodel.h"
28 : : #include "gimple.h"
29 : : #include "cfghooks.h"
30 : : #include "cfgloop.h"
31 : : #include "df.h"
32 : : #include "tm_p.h"
33 : : #include "stringpool.h"
34 : : #include "expmed.h"
35 : : #include "optabs.h"
36 : : #include "regs.h"
37 : : #include "emit-rtl.h"
38 : : #include "recog.h"
39 : : #include "cgraph.h"
40 : : #include "diagnostic.h"
41 : : #include "cfgbuild.h"
42 : : #include "alias.h"
43 : : #include "fold-const.h"
44 : : #include "attribs.h"
45 : : #include "calls.h"
46 : : #include "stor-layout.h"
47 : : #include "varasm.h"
48 : : #include "output.h"
49 : : #include "insn-attr.h"
50 : : #include "flags.h"
51 : : #include "except.h"
52 : : #include "explow.h"
53 : : #include "expr.h"
54 : : #include "cfgrtl.h"
55 : : #include "common/common-target.h"
56 : : #include "langhooks.h"
57 : : #include "reload.h"
58 : : #include "gimplify.h"
59 : : #include "dwarf2.h"
60 : : #include "tm-constrs.h"
61 : : #include "cselib.h"
62 : : #include "sched-int.h"
63 : : #include "opts.h"
64 : : #include "tree-pass.h"
65 : : #include "context.h"
66 : : #include "pass_manager.h"
67 : : #include "target-globals.h"
68 : : #include "gimple-iterator.h"
69 : : #include "shrink-wrap.h"
70 : : #include "builtins.h"
71 : : #include "rtl-iter.h"
72 : : #include "tree-iterator.h"
73 : : #include "dbgcnt.h"
74 : : #include "case-cfn-macros.h"
75 : : #include "dojump.h"
76 : : #include "fold-const-call.h"
77 : : #include "tree-vrp.h"
78 : : #include "tree-ssanames.h"
79 : : #include "selftest.h"
80 : : #include "selftest-rtl.h"
81 : : #include "print-rtl.h"
82 : : #include "intl.h"
83 : : #include "ifcvt.h"
84 : : #include "symbol-summary.h"
85 : : #include "sreal.h"
86 : : #include "ipa-cp.h"
87 : : #include "ipa-prop.h"
88 : : #include "ipa-fnsummary.h"
89 : : #include "wide-int-bitmask.h"
90 : : #include "tree-vector-builder.h"
91 : : #include "debug.h"
92 : : #include "dwarf2out.h"
93 : : #include "i386-builtins.h"
94 : : #include "i386-features.h"
95 : : #include "i386-expand.h"
96 : :
97 : : const char * const xlogue_layout::STUB_BASE_NAMES[XLOGUE_STUB_COUNT] = {
98 : : "savms64",
99 : : "resms64",
100 : : "resms64x",
101 : : "savms64f",
102 : : "resms64f",
103 : : "resms64fx"
104 : : };
105 : :
106 : : const unsigned xlogue_layout::REG_ORDER[xlogue_layout::MAX_REGS] = {
107 : : /* The below offset values are where each register is stored for the layout
108 : : relative to incoming stack pointer. The value of each m_regs[].offset will
109 : : be relative to the incoming base pointer (rax or rsi) used by the stub.
110 : :
111 : : s_instances: 0 1 2 3
112 : : Offset: realigned or aligned + 8
113 : : Register aligned aligned + 8 aligned w/HFP w/HFP */
114 : : XMM15_REG, /* 0x10 0x18 0x10 0x18 */
115 : : XMM14_REG, /* 0x20 0x28 0x20 0x28 */
116 : : XMM13_REG, /* 0x30 0x38 0x30 0x38 */
117 : : XMM12_REG, /* 0x40 0x48 0x40 0x48 */
118 : : XMM11_REG, /* 0x50 0x58 0x50 0x58 */
119 : : XMM10_REG, /* 0x60 0x68 0x60 0x68 */
120 : : XMM9_REG, /* 0x70 0x78 0x70 0x78 */
121 : : XMM8_REG, /* 0x80 0x88 0x80 0x88 */
122 : : XMM7_REG, /* 0x90 0x98 0x90 0x98 */
123 : : XMM6_REG, /* 0xa0 0xa8 0xa0 0xa8 */
124 : : SI_REG, /* 0xa8 0xb0 0xa8 0xb0 */
125 : : DI_REG, /* 0xb0 0xb8 0xb0 0xb8 */
126 : : BX_REG, /* 0xb8 0xc0 0xb8 0xc0 */
127 : : BP_REG, /* 0xc0 0xc8 N/A N/A */
128 : : R12_REG, /* 0xc8 0xd0 0xc0 0xc8 */
129 : : R13_REG, /* 0xd0 0xd8 0xc8 0xd0 */
130 : : R14_REG, /* 0xd8 0xe0 0xd0 0xd8 */
131 : : R15_REG, /* 0xe0 0xe8 0xd8 0xe0 */
132 : : };
133 : :
134 : : /* Instantiate static const values. */
135 : : const HOST_WIDE_INT xlogue_layout::STUB_INDEX_OFFSET;
136 : : const unsigned xlogue_layout::MIN_REGS;
137 : : const unsigned xlogue_layout::MAX_REGS;
138 : : const unsigned xlogue_layout::MAX_EXTRA_REGS;
139 : : const unsigned xlogue_layout::VARIANT_COUNT;
140 : : const unsigned xlogue_layout::STUB_NAME_MAX_LEN;
141 : :
142 : : /* Initialize xlogue_layout::s_stub_names to zero. */
143 : : char xlogue_layout::s_stub_names[2][XLOGUE_STUB_COUNT][VARIANT_COUNT]
144 : : [STUB_NAME_MAX_LEN];
145 : :
146 : : /* Instantiates all xlogue_layout instances. */
147 : : const xlogue_layout xlogue_layout::s_instances[XLOGUE_SET_COUNT] = {
148 : : xlogue_layout (0, false),
149 : : xlogue_layout (8, false),
150 : : xlogue_layout (0, true),
151 : : xlogue_layout (8, true)
152 : : };
153 : :
154 : : /* Return an appropriate const instance of xlogue_layout based upon values
155 : : in cfun->machine and crtl. */
156 : : const class xlogue_layout &
157 : 49891 : xlogue_layout::get_instance ()
158 : : {
159 : 49891 : enum xlogue_stub_sets stub_set;
160 : 49891 : bool aligned_plus_8 = cfun->machine->call_ms2sysv_pad_in;
161 : :
162 : 49891 : if (stack_realign_fp)
163 : : stub_set = XLOGUE_SET_HFP_ALIGNED_OR_REALIGN;
164 : 40910 : else if (frame_pointer_needed)
165 : 31552 : stub_set = aligned_plus_8
166 : 31552 : ? XLOGUE_SET_HFP_ALIGNED_PLUS_8
167 : : : XLOGUE_SET_HFP_ALIGNED_OR_REALIGN;
168 : : else
169 : 9358 : stub_set = aligned_plus_8 ? XLOGUE_SET_ALIGNED_PLUS_8 : XLOGUE_SET_ALIGNED;
170 : :
171 : 49891 : return s_instances[stub_set];
172 : : }
173 : :
174 : : /* Determine how many clobbered registers can be saved by the stub.
175 : : Returns the count of registers the stub will save and restore. */
176 : : unsigned
177 : 35225 : xlogue_layout::count_stub_managed_regs ()
178 : : {
179 : 35225 : bool hfp = frame_pointer_needed || stack_realign_fp;
180 : 35225 : unsigned i, count;
181 : 35225 : unsigned regno;
182 : :
183 : 94890 : for (count = i = MIN_REGS; i < MAX_REGS; ++i)
184 : : {
185 : 93670 : regno = REG_ORDER[i];
186 : 93670 : if (regno == BP_REG && hfp)
187 : 18200 : continue;
188 : 75470 : if (!ix86_save_reg (regno, false, false))
189 : : break;
190 : 41465 : ++count;
191 : : }
192 : 35225 : return count;
193 : : }
194 : :
195 : : /* Determine if register REGNO is a stub managed register given the
196 : : total COUNT of stub managed registers. */
197 : : bool
198 : 2650688 : xlogue_layout::is_stub_managed_reg (unsigned regno, unsigned count)
199 : : {
200 : 2650688 : bool hfp = frame_pointer_needed || stack_realign_fp;
201 : 2650688 : unsigned i;
202 : :
203 : 34587805 : for (i = 0; i < count; ++i)
204 : : {
205 : 32436986 : gcc_assert (i < MAX_REGS);
206 : 32436986 : if (REG_ORDER[i] == BP_REG && hfp)
207 : 522627 : ++count;
208 : 31914359 : else if (REG_ORDER[i] == regno)
209 : : return true;
210 : : }
211 : : return false;
212 : : }
213 : :
214 : : /* Constructor for xlogue_layout. */
215 : 1107424 : xlogue_layout::xlogue_layout (HOST_WIDE_INT stack_align_off_in, bool hfp)
216 : 1107424 : : m_hfp (hfp) , m_nregs (hfp ? 17 : 18),
217 : 1107424 : m_stack_align_off_in (stack_align_off_in)
218 : : {
219 : 1107424 : HOST_WIDE_INT offset = stack_align_off_in;
220 : 1107424 : unsigned i, j;
221 : :
222 : 21041056 : for (i = j = 0; i < MAX_REGS; ++i)
223 : : {
224 : 19933632 : unsigned regno = REG_ORDER[i];
225 : :
226 : 19933632 : if (regno == BP_REG && hfp)
227 : 553712 : continue;
228 : 19379920 : if (SSE_REGNO_P (regno))
229 : : {
230 : 11074240 : offset += 16;
231 : : /* Verify that SSE regs are always aligned. */
232 : 11074240 : gcc_assert (!((stack_align_off_in + offset) & 15));
233 : : }
234 : : else
235 : 8305680 : offset += 8;
236 : :
237 : 19379920 : m_regs[j].regno = regno;
238 : 19379920 : m_regs[j++].offset = offset - STUB_INDEX_OFFSET;
239 : : }
240 : 1107424 : gcc_assert (j == m_nregs);
241 : 1107424 : }
242 : :
243 : : const char *
244 : 14666 : xlogue_layout::get_stub_name (enum xlogue_stub stub,
245 : : unsigned n_extra_regs)
246 : : {
247 : 14666 : const int have_avx = TARGET_AVX;
248 : 14666 : char *name = s_stub_names[!!have_avx][stub][n_extra_regs];
249 : :
250 : : /* Lazy init */
251 : 14666 : if (!*name)
252 : : {
253 : 362 : int res = snprintf (name, STUB_NAME_MAX_LEN, "__%s_%s_%u",
254 : : (have_avx ? "avx" : "sse"),
255 : 181 : STUB_BASE_NAMES[stub],
256 : : MIN_REGS + n_extra_regs);
257 : 181 : gcc_checking_assert (res < (int)STUB_NAME_MAX_LEN);
258 : : }
259 : :
260 : 14666 : return name;
261 : : }
262 : :
263 : : /* Return rtx of a symbol ref for the entry point (based upon
264 : : cfun->machine->call_ms2sysv_extra_regs) of the specified stub. */
265 : : rtx
266 : 14666 : xlogue_layout::get_stub_rtx (enum xlogue_stub stub)
267 : : {
268 : 14666 : const unsigned n_extra_regs = cfun->machine->call_ms2sysv_extra_regs;
269 : 14666 : gcc_checking_assert (n_extra_regs <= MAX_EXTRA_REGS);
270 : 14666 : gcc_assert (stub < XLOGUE_STUB_COUNT);
271 : 14666 : gcc_assert (crtl->stack_realign_finalized);
272 : :
273 : 14666 : return gen_rtx_SYMBOL_REF (Pmode, get_stub_name (stub, n_extra_regs));
274 : : }
275 : :
276 : : unsigned scalar_chain::max_id = 0;
277 : :
278 : : namespace {
279 : :
280 : : /* Initialize new chain. */
281 : :
282 : 6372916 : scalar_chain::scalar_chain (enum machine_mode smode_, enum machine_mode vmode_)
283 : : {
284 : 6372916 : smode = smode_;
285 : 6372916 : vmode = vmode_;
286 : :
287 : 6372916 : chain_id = ++max_id;
288 : :
289 : 6372916 : if (dump_file)
290 : 138 : fprintf (dump_file, "Created a new instruction chain #%d\n", chain_id);
291 : :
292 : 6372916 : bitmap_obstack_initialize (NULL);
293 : 6372916 : insns = BITMAP_ALLOC (NULL);
294 : 6372916 : defs = BITMAP_ALLOC (NULL);
295 : 6372916 : defs_conv = BITMAP_ALLOC (NULL);
296 : 6372916 : insns_conv = BITMAP_ALLOC (NULL);
297 : 6372916 : queue = NULL;
298 : :
299 : 6372916 : n_sse_to_integer = 0;
300 : 6372916 : n_integer_to_sse = 0;
301 : :
302 : 6372916 : max_visits = x86_stv_max_visits;
303 : 6372916 : }
304 : :
305 : : /* Free chain's data. */
306 : :
307 : 6372916 : scalar_chain::~scalar_chain ()
308 : : {
309 : 6372916 : BITMAP_FREE (insns);
310 : 6372916 : BITMAP_FREE (defs);
311 : 6372916 : BITMAP_FREE (defs_conv);
312 : 6372916 : BITMAP_FREE (insns_conv);
313 : 6372916 : bitmap_obstack_release (NULL);
314 : 6372916 : }
315 : :
316 : : /* Add instruction into chains' queue. */
317 : :
318 : : void
319 : 7780435 : scalar_chain::add_to_queue (unsigned insn_uid)
320 : : {
321 : 7780435 : if (!bitmap_set_bit (queue, insn_uid))
322 : : return;
323 : :
324 : 5990052 : if (dump_file)
325 : 141 : fprintf (dump_file, " Adding insn %d into chain's #%d queue\n",
326 : : insn_uid, chain_id);
327 : : }
328 : :
329 : : /* For DImode conversion, mark register defined by DEF as requiring
330 : : conversion. */
331 : :
332 : : void
333 : 9237809 : scalar_chain::mark_dual_mode_def (df_ref def)
334 : : {
335 : 9237809 : gcc_assert (DF_REF_REG_DEF_P (def));
336 : :
337 : : /* Record the def/insn pair so we can later efficiently iterate over
338 : : the defs to convert on insns not in the chain. */
339 : 9237809 : bool reg_new = bitmap_set_bit (defs_conv, DF_REF_REGNO (def));
340 : 9237809 : if (!bitmap_bit_p (insns, DF_REF_INSN_UID (def)))
341 : : {
342 : 2657078 : if (!bitmap_set_bit (insns_conv, DF_REF_INSN_UID (def))
343 : 2657078 : && !reg_new)
344 : : return;
345 : 2416452 : n_integer_to_sse++;
346 : : }
347 : : else
348 : : {
349 : 6580731 : if (!reg_new)
350 : : return;
351 : 5467688 : n_sse_to_integer++;
352 : : }
353 : :
354 : 7884140 : if (dump_file)
355 : 240 : fprintf (dump_file,
356 : : " Mark r%d def in insn %d as requiring both modes in chain #%d\n",
357 : 240 : DF_REF_REGNO (def), DF_REF_INSN_UID (def), chain_id);
358 : : }
359 : :
360 : : /* Check REF's chain to add new insns into a queue
361 : : and find registers requiring conversion. Return true if OK, false
362 : : if the analysis was aborted. */
363 : :
364 : : bool
365 : 17347080 : scalar_chain::analyze_register_chain (bitmap candidates, df_ref ref,
366 : : bitmap disallowed)
367 : : {
368 : 17347080 : df_link *chain;
369 : 17347080 : bool mark_def = false;
370 : :
371 : 17347080 : gcc_checking_assert (bitmap_bit_p (insns, DF_REF_INSN_UID (ref)));
372 : :
373 : 58632573 : for (chain = DF_REF_CHAIN (ref); chain; chain = chain->next)
374 : : {
375 : 41286028 : unsigned uid = DF_REF_INSN_UID (chain->ref);
376 : :
377 : 41286028 : if (!NONDEBUG_INSN_P (DF_REF_INSN (chain->ref)))
378 : 7145558 : continue;
379 : :
380 : 34140470 : if (--max_visits == 0)
381 : : return false;
382 : :
383 : 34139950 : if (!DF_REF_REG_MEM_P (chain->ref))
384 : : {
385 : 28865868 : if (bitmap_bit_p (insns, uid))
386 : 9086124 : continue;
387 : :
388 : 19779744 : if (bitmap_bit_p (candidates, uid))
389 : : {
390 : 7780435 : add_to_queue (uid);
391 : 7780435 : continue;
392 : : }
393 : :
394 : : /* If we run into parts of an aborted chain discovery abort. */
395 : 11999309 : if (bitmap_bit_p (disallowed, uid))
396 : : return false;
397 : : }
398 : :
399 : 17273376 : if (DF_REF_REG_DEF_P (chain->ref))
400 : : {
401 : 2657078 : if (dump_file)
402 : 127 : fprintf (dump_file, " r%d def in insn %d isn't convertible\n",
403 : : DF_REF_REGNO (chain->ref), uid);
404 : 2657078 : mark_dual_mode_def (chain->ref);
405 : : }
406 : : else
407 : : {
408 : 14616298 : if (dump_file)
409 : 538 : fprintf (dump_file, " r%d use in insn %d isn't convertible\n",
410 : : DF_REF_REGNO (chain->ref), uid);
411 : : mark_def = true;
412 : : }
413 : : }
414 : :
415 : 17346545 : if (mark_def)
416 : 6580731 : mark_dual_mode_def (ref);
417 : :
418 : : return true;
419 : : }
420 : :
421 : : /* Add instruction into a chain. Return true if OK, false if the search
422 : : was aborted. */
423 : :
424 : : bool
425 : 12362947 : scalar_chain::add_insn (bitmap candidates, unsigned int insn_uid,
426 : : bitmap disallowed)
427 : : {
428 : 12362947 : if (!bitmap_set_bit (insns, insn_uid))
429 : : return true;
430 : :
431 : 12362947 : if (dump_file)
432 : 279 : fprintf (dump_file, " Adding insn %d to chain #%d\n", insn_uid, chain_id);
433 : :
434 : 12362947 : rtx_insn *insn = DF_INSN_UID_GET (insn_uid)->insn;
435 : 12362947 : rtx def_set = single_set (insn);
436 : 12362947 : if (def_set && REG_P (SET_DEST (def_set))
437 : 21962289 : && !HARD_REGISTER_P (SET_DEST (def_set)))
438 : 9599336 : bitmap_set_bit (defs, REGNO (SET_DEST (def_set)));
439 : :
440 : : /* ??? The following is quadratic since analyze_register_chain
441 : : iterates over all refs to look for dual-mode regs. Instead this
442 : : should be done separately for all regs mentioned in the chain once. */
443 : 12362947 : df_ref ref;
444 : 25280677 : for (ref = DF_INSN_UID_DEFS (insn_uid); ref; ref = DF_REF_NEXT_LOC (ref))
445 : 12918191 : if (!HARD_REGISTER_P (DF_REF_REG (ref)))
446 : 9599336 : if (!analyze_register_chain (candidates, ref, disallowed))
447 : : return false;
448 : :
449 : : /* The operand(s) of VEC_SELECT don't need to be converted/convertible. */
450 : 12362486 : if (def_set && GET_CODE (SET_SRC (def_set)) == VEC_SELECT)
451 : : return true;
452 : :
453 : 26908524 : for (ref = DF_INSN_UID_USES (insn_uid); ref; ref = DF_REF_NEXT_LOC (ref))
454 : 14580629 : if (!DF_REF_REG_MEM_P (ref))
455 : 7747744 : if (!analyze_register_chain (candidates, ref, disallowed))
456 : : return false;
457 : :
458 : : return true;
459 : : }
460 : :
461 : : /* Build new chain starting from insn INSN_UID recursively
462 : : adding all dependent uses and definitions. Return true if OK, false
463 : : if the chain discovery was aborted. */
464 : :
465 : : bool
466 : 6372916 : scalar_chain::build (bitmap candidates, unsigned insn_uid, bitmap disallowed)
467 : : {
468 : 6372916 : queue = BITMAP_ALLOC (NULL);
469 : 6372916 : bitmap_set_bit (queue, insn_uid);
470 : :
471 : 6372916 : if (dump_file)
472 : 138 : fprintf (dump_file, "Building chain #%d...\n", chain_id);
473 : :
474 : 18735328 : while (!bitmap_empty_p (queue))
475 : : {
476 : 12362947 : insn_uid = bitmap_first_set_bit (queue);
477 : 12362947 : bitmap_clear_bit (queue, insn_uid);
478 : 12362947 : bitmap_clear_bit (candidates, insn_uid);
479 : 12362947 : if (!add_insn (candidates, insn_uid, disallowed))
480 : : {
481 : : /* If we aborted the search put sofar found insn on the set of
482 : : disallowed insns so that further searches reaching them also
483 : : abort and thus we abort the whole but yet undiscovered chain. */
484 : 535 : bitmap_ior_into (disallowed, insns);
485 : 535 : if (dump_file)
486 : 0 : fprintf (dump_file, "Aborted chain #%d discovery\n", chain_id);
487 : 535 : BITMAP_FREE (queue);
488 : 535 : return false;
489 : : }
490 : : }
491 : :
492 : 6372381 : if (dump_file)
493 : : {
494 : 138 : fprintf (dump_file, "Collected chain #%d...\n", chain_id);
495 : 138 : fprintf (dump_file, " insns: ");
496 : 138 : dump_bitmap (dump_file, insns);
497 : 138 : if (!bitmap_empty_p (defs_conv))
498 : : {
499 : 138 : bitmap_iterator bi;
500 : 138 : unsigned id;
501 : 138 : const char *comma = "";
502 : 138 : fprintf (dump_file, " defs to convert: ");
503 : 368 : EXECUTE_IF_SET_IN_BITMAP (defs_conv, 0, id, bi)
504 : : {
505 : 230 : fprintf (dump_file, "%sr%d", comma, id);
506 : 230 : comma = ", ";
507 : : }
508 : 138 : fprintf (dump_file, "\n");
509 : : }
510 : : }
511 : :
512 : 6372381 : BITMAP_FREE (queue);
513 : :
514 : 6372381 : return true;
515 : : }
516 : :
517 : : /* Return a cost of building a vector costant
518 : : instead of using a scalar one. */
519 : :
520 : : int
521 : 2846874 : general_scalar_chain::vector_const_cost (rtx exp)
522 : : {
523 : 2846874 : gcc_assert (CONST_INT_P (exp));
524 : :
525 : 2846874 : if (standard_sse_constant_p (exp, vmode))
526 : 738191 : return ix86_cost->sse_op;
527 : : /* We have separate costs for SImode and DImode, use SImode costs
528 : : for smaller modes. */
529 : 2770118 : return ix86_cost->sse_load[smode == DImode ? 1 : 0];
530 : : }
531 : :
532 : : /* Compute a gain for chain conversion. */
533 : :
534 : : int
535 : 5932139 : general_scalar_chain::compute_convert_gain ()
536 : : {
537 : 5932139 : bitmap_iterator bi;
538 : 5932139 : unsigned insn_uid;
539 : 5932139 : int gain = 0;
540 : 5932139 : int cost = 0;
541 : :
542 : 5932139 : if (dump_file)
543 : 138 : fprintf (dump_file, "Computing gain for chain #%d...\n", chain_id);
544 : :
545 : : /* SSE costs distinguish between SImode and DImode loads/stores, for
546 : : int costs factor in the number of GPRs involved. When supporting
547 : : smaller modes than SImode the int load/store costs need to be
548 : : adjusted as well. */
549 : 5932139 : unsigned sse_cost_idx = smode == DImode ? 1 : 0;
550 : 5932139 : unsigned m = smode == DImode ? (TARGET_64BIT ? 1 : 2) : 1;
551 : :
552 : 17427225 : EXECUTE_IF_SET_IN_BITMAP (insns, 0, insn_uid, bi)
553 : : {
554 : 11495086 : rtx_insn *insn = DF_INSN_UID_GET (insn_uid)->insn;
555 : 11495086 : rtx def_set = single_set (insn);
556 : 11495086 : rtx src = SET_SRC (def_set);
557 : 11495086 : rtx dst = SET_DEST (def_set);
558 : 11495086 : int igain = 0;
559 : :
560 : 11495086 : if (REG_P (src) && REG_P (dst))
561 : 860052 : igain += 2 * m - ix86_cost->xmm_move;
562 : 10635034 : else if (REG_P (src) && MEM_P (dst))
563 : 2232143 : igain
564 : 2232143 : += m * ix86_cost->int_store[2] - ix86_cost->sse_store[sse_cost_idx];
565 : 8402891 : else if (MEM_P (src) && REG_P (dst))
566 : 3850691 : igain += m * ix86_cost->int_load[2] - ix86_cost->sse_load[sse_cost_idx];
567 : : else
568 : : {
569 : : /* For operations on memory operands, include the overhead
570 : : of explicit load and store instructions. */
571 : 4552200 : if (MEM_P (dst))
572 : 119778 : igain += optimize_insn_for_size_p ()
573 : 59889 : ? -COSTS_N_BYTES (8)
574 : 56856 : : (m * (ix86_cost->int_load[2]
575 : 56856 : + ix86_cost->int_store[2])
576 : 56856 : - (ix86_cost->sse_load[sse_cost_idx] +
577 : 56856 : ix86_cost->sse_store[sse_cost_idx]));
578 : :
579 : 4552200 : switch (GET_CODE (src))
580 : : {
581 : 450196 : case ASHIFT:
582 : 450196 : case ASHIFTRT:
583 : 450196 : case LSHIFTRT:
584 : 450196 : if (m == 2)
585 : : {
586 : 17082 : if (INTVAL (XEXP (src, 1)) >= 32)
587 : 11545 : igain += ix86_cost->add;
588 : : /* Gain for extend highpart case. */
589 : 5537 : else if (GET_CODE (XEXP (src, 0)) == ASHIFT)
590 : 0 : igain += ix86_cost->shift_const - ix86_cost->sse_op;
591 : : else
592 : 5537 : igain += ix86_cost->shift_const;
593 : : }
594 : :
595 : 450196 : igain += ix86_cost->shift_const - ix86_cost->sse_op;
596 : :
597 : 450196 : if (CONST_INT_P (XEXP (src, 0)))
598 : 0 : igain -= vector_const_cost (XEXP (src, 0));
599 : : break;
600 : :
601 : 3710 : case ROTATE:
602 : 3710 : case ROTATERT:
603 : 3710 : igain += m * ix86_cost->shift_const;
604 : 3710 : if (TARGET_AVX512VL)
605 : 192 : igain -= ix86_cost->sse_op;
606 : 3518 : else if (smode == DImode)
607 : : {
608 : 554 : int bits = INTVAL (XEXP (src, 1));
609 : 554 : if ((bits & 0x0f) == 0)
610 : 104 : igain -= ix86_cost->sse_op;
611 : 450 : else if ((bits & 0x07) == 0)
612 : 27 : igain -= 2 * ix86_cost->sse_op;
613 : : else
614 : 423 : igain -= 3 * ix86_cost->sse_op;
615 : : }
616 : 2964 : else if (INTVAL (XEXP (src, 1)) == 16)
617 : 218 : igain -= ix86_cost->sse_op;
618 : : else
619 : 2746 : igain -= 2 * ix86_cost->sse_op;
620 : : break;
621 : :
622 : 2786849 : case AND:
623 : 2786849 : case IOR:
624 : 2786849 : case XOR:
625 : 2786849 : case PLUS:
626 : 2786849 : case MINUS:
627 : 2786849 : igain += m * ix86_cost->add - ix86_cost->sse_op;
628 : : /* Additional gain for andnot for targets without BMI. */
629 : 2786849 : if (GET_CODE (XEXP (src, 0)) == NOT
630 : 3599 : && !TARGET_BMI)
631 : 3590 : igain += m * ix86_cost->add;
632 : :
633 : 2786849 : if (CONST_INT_P (XEXP (src, 0)))
634 : 0 : igain -= vector_const_cost (XEXP (src, 0));
635 : 2786849 : if (CONST_INT_P (XEXP (src, 1)))
636 : 1665668 : igain -= vector_const_cost (XEXP (src, 1));
637 : 2786849 : if (MEM_P (XEXP (src, 1)))
638 : : {
639 : 97047 : if (optimize_insn_for_size_p ())
640 : 12176 : igain -= COSTS_N_BYTES (m == 2 ? 3 : 5);
641 : : else
642 : 90959 : igain += m * ix86_cost->int_load[2]
643 : 90959 : - ix86_cost->sse_load[sse_cost_idx];
644 : : }
645 : : break;
646 : :
647 : 50232 : case NEG:
648 : 50232 : case NOT:
649 : 50232 : igain -= ix86_cost->sse_op + COSTS_N_INSNS (1);
650 : :
651 : 50232 : if (GET_CODE (XEXP (src, 0)) != ABS)
652 : : {
653 : 50232 : igain += m * ix86_cost->add;
654 : 50232 : break;
655 : : }
656 : : /* FALLTHRU */
657 : :
658 : 1119 : case ABS:
659 : 1119 : case SMAX:
660 : 1119 : case SMIN:
661 : 1119 : case UMAX:
662 : 1119 : case UMIN:
663 : : /* We do not have any conditional move cost, estimate it as a
664 : : reg-reg move. Comparisons are costed as adds. */
665 : 1119 : igain += m * (COSTS_N_INSNS (2) + ix86_cost->add);
666 : : /* Integer SSE ops are all costed the same. */
667 : 1119 : igain -= ix86_cost->sse_op;
668 : 1119 : break;
669 : :
670 : 0 : case COMPARE:
671 : 0 : if (XEXP (src, 1) != const0_rtx)
672 : : {
673 : : /* cmp vs. pxor;pshufd;ptest. */
674 : 0 : igain += COSTS_N_INSNS (m - 3);
675 : : }
676 : 0 : else if (GET_CODE (XEXP (src, 0)) != AND)
677 : : {
678 : : /* test vs. pshufd;ptest. */
679 : 0 : igain += COSTS_N_INSNS (m - 2);
680 : : }
681 : 0 : else if (GET_CODE (XEXP (XEXP (src, 0), 0)) != NOT)
682 : : {
683 : : /* and;test vs. pshufd;ptest. */
684 : 0 : igain += COSTS_N_INSNS (2 * m - 2);
685 : : }
686 : 0 : else if (TARGET_BMI)
687 : : {
688 : : /* andn;test vs. pandn;pshufd;ptest. */
689 : 0 : igain += COSTS_N_INSNS (2 * m - 3);
690 : : }
691 : : else
692 : : {
693 : : /* not;and;test vs. pandn;pshufd;ptest. */
694 : 0 : igain += COSTS_N_INSNS (3 * m - 3);
695 : : }
696 : : break;
697 : :
698 : 1225577 : case CONST_INT:
699 : 1225577 : if (REG_P (dst))
700 : : {
701 : 1225577 : if (optimize_insn_for_size_p ())
702 : : {
703 : : /* xor (2 bytes) vs. xorps (3 bytes). */
704 : 44371 : if (src == const0_rtx)
705 : 18578 : igain -= COSTS_N_BYTES (1);
706 : : /* movdi_internal vs. movv2di_internal. */
707 : : /* => mov (5 bytes) vs. movaps (7 bytes). */
708 : 25793 : else if (x86_64_immediate_operand (src, SImode))
709 : 20948 : igain -= COSTS_N_BYTES (2);
710 : : else
711 : : /* ??? Larger immediate constants are placed in the
712 : : constant pool, where the size benefit/impact of
713 : : STV conversion is affected by whether and how
714 : : often each constant pool entry is shared/reused.
715 : : The value below is empirically derived from the
716 : : CSiBE benchmark (and the optimal value may drift
717 : : over time). */
718 : : igain += COSTS_N_BYTES (0);
719 : : }
720 : : else
721 : : {
722 : : /* DImode can be immediate for TARGET_64BIT
723 : : and SImode always. */
724 : 1181206 : igain += m * COSTS_N_INSNS (1);
725 : 1181206 : igain -= vector_const_cost (src);
726 : : }
727 : : }
728 : 0 : else if (MEM_P (dst))
729 : : {
730 : 0 : igain += (m * ix86_cost->int_store[2]
731 : 0 : - ix86_cost->sse_store[sse_cost_idx]);
732 : 0 : igain -= vector_const_cost (src);
733 : : }
734 : : break;
735 : :
736 : 34517 : case VEC_SELECT:
737 : 34517 : if (XVECEXP (XEXP (src, 1), 0, 0) == const0_rtx)
738 : : {
739 : : // movd (4 bytes) replaced with movdqa (4 bytes).
740 : 26175 : if (!optimize_insn_for_size_p ())
741 : 25670 : igain += ix86_cost->sse_to_integer - ix86_cost->xmm_move;
742 : : }
743 : : else
744 : : {
745 : : // pshufd; movd replaced with pshufd.
746 : 8342 : if (optimize_insn_for_size_p ())
747 : 88 : igain += COSTS_N_BYTES (4);
748 : : else
749 : 8254 : igain += ix86_cost->sse_to_integer;
750 : : }
751 : : break;
752 : :
753 : 0 : default:
754 : 0 : gcc_unreachable ();
755 : : }
756 : : }
757 : :
758 : 11495086 : if (igain != 0 && dump_file)
759 : : {
760 : 103 : fprintf (dump_file, " Instruction gain %d for ", igain);
761 : 103 : dump_insn_slim (dump_file, insn);
762 : : }
763 : 11495086 : gain += igain;
764 : : }
765 : :
766 : 5932139 : if (dump_file)
767 : 138 : fprintf (dump_file, " Instruction conversion gain: %d\n", gain);
768 : :
769 : : /* Cost the integer to sse and sse to integer moves. */
770 : 5932139 : if (!optimize_function_for_size_p (cfun))
771 : : {
772 : 5732806 : cost += n_sse_to_integer * ix86_cost->sse_to_integer;
773 : : /* ??? integer_to_sse but we only have that in the RA cost table.
774 : : Assume sse_to_integer/integer_to_sse are the same which they
775 : : are at the moment. */
776 : 5732806 : cost += n_integer_to_sse * ix86_cost->sse_to_integer;
777 : : }
778 : 199333 : else if (TARGET_64BIT || smode == SImode)
779 : : {
780 : 198454 : cost += n_sse_to_integer * COSTS_N_BYTES (4);
781 : 198454 : cost += n_integer_to_sse * COSTS_N_BYTES (4);
782 : : }
783 : 879 : else if (TARGET_SSE4_1)
784 : : {
785 : : /* vmovd (4 bytes) + vpextrd (6 bytes). */
786 : 0 : cost += n_sse_to_integer * COSTS_N_BYTES (10);
787 : : /* vmovd (4 bytes) + vpinsrd (6 bytes). */
788 : 0 : cost += n_integer_to_sse * COSTS_N_BYTES (10);
789 : : }
790 : : else
791 : : {
792 : : /* movd (4 bytes) + psrlq (5 bytes) + movd (4 bytes). */
793 : 879 : cost += n_sse_to_integer * COSTS_N_BYTES (13);
794 : : /* movd (4 bytes) + movd (4 bytes) + unpckldq (4 bytes). */
795 : 879 : cost += n_integer_to_sse * COSTS_N_BYTES (12);
796 : : }
797 : :
798 : 5932139 : if (dump_file)
799 : 138 : fprintf (dump_file, " Registers conversion cost: %d\n", cost);
800 : :
801 : 5932139 : gain -= cost;
802 : :
803 : 5932139 : if (dump_file)
804 : 138 : fprintf (dump_file, " Total gain: %d\n", gain);
805 : :
806 : 5932139 : return gain;
807 : : }
808 : :
809 : : /* Insert generated conversion instruction sequence INSNS
810 : : after instruction AFTER. New BB may be required in case
811 : : instruction has EH region attached. */
812 : :
813 : : void
814 : 33534 : scalar_chain::emit_conversion_insns (rtx insns, rtx_insn *after)
815 : : {
816 : 33534 : if (!control_flow_insn_p (after))
817 : : {
818 : 33353 : emit_insn_after (insns, after);
819 : 33353 : return;
820 : : }
821 : :
822 : 181 : basic_block bb = BLOCK_FOR_INSN (after);
823 : 181 : edge e = find_fallthru_edge (bb->succs);
824 : 181 : gcc_assert (e);
825 : :
826 : 181 : basic_block new_bb = split_edge (e);
827 : 181 : emit_insn_after (insns, BB_HEAD (new_bb));
828 : : }
829 : :
830 : : } // anon namespace
831 : :
832 : : /* Generate the canonical SET_SRC to move GPR to a VMODE vector register,
833 : : zeroing the upper parts. */
834 : :
835 : : static rtx
836 : 173220 : gen_gpr_to_xmm_move_src (enum machine_mode vmode, rtx gpr)
837 : : {
838 : 346440 : switch (GET_MODE_NUNITS (vmode))
839 : : {
840 : 12 : case 1:
841 : 12 : return gen_rtx_SUBREG (vmode, gpr, 0);
842 : 172693 : case 2:
843 : 345386 : return gen_rtx_VEC_CONCAT (vmode, gpr,
844 : : CONST0_RTX (GET_MODE_INNER (vmode)));
845 : 515 : default:
846 : 515 : return gen_rtx_VEC_MERGE (vmode, gen_rtx_VEC_DUPLICATE (vmode, gpr),
847 : : CONST0_RTX (vmode), GEN_INT (HOST_WIDE_INT_1U));
848 : : }
849 : : }
850 : :
851 : : /* Make vector copies for all register REGNO definitions
852 : : and replace its uses in a chain. */
853 : :
854 : : void
855 : 9117 : scalar_chain::make_vector_copies (rtx_insn *insn, rtx reg)
856 : : {
857 : 9117 : rtx vreg = *defs_map.get (reg);
858 : :
859 : 9117 : start_sequence ();
860 : 9117 : if (!TARGET_INTER_UNIT_MOVES_TO_VEC)
861 : : {
862 : 0 : rtx tmp = assign_386_stack_local (smode, SLOT_STV_TEMP);
863 : 0 : if (smode == DImode && !TARGET_64BIT)
864 : : {
865 : 0 : emit_move_insn (adjust_address (tmp, SImode, 0),
866 : 0 : gen_rtx_SUBREG (SImode, reg, 0));
867 : 0 : emit_move_insn (adjust_address (tmp, SImode, 4),
868 : 0 : gen_rtx_SUBREG (SImode, reg, 4));
869 : : }
870 : : else
871 : 0 : emit_move_insn (copy_rtx (tmp), reg);
872 : 0 : emit_insn (gen_rtx_SET (gen_rtx_SUBREG (vmode, vreg, 0),
873 : : gen_gpr_to_xmm_move_src (vmode, tmp)));
874 : : }
875 : 9117 : else if (!TARGET_64BIT && smode == DImode)
876 : : {
877 : 9039 : if (TARGET_SSE4_1)
878 : : {
879 : 664 : emit_insn (gen_sse2_loadld (gen_rtx_SUBREG (V4SImode, vreg, 0),
880 : : CONST0_RTX (V4SImode),
881 : 664 : gen_rtx_SUBREG (SImode, reg, 0)));
882 : 664 : emit_insn (gen_sse4_1_pinsrd (gen_rtx_SUBREG (V4SImode, vreg, 0),
883 : 664 : gen_rtx_SUBREG (V4SImode, vreg, 0),
884 : 664 : gen_rtx_SUBREG (SImode, reg, 4),
885 : : GEN_INT (2)));
886 : : }
887 : : else
888 : : {
889 : 8375 : rtx tmp = gen_reg_rtx (DImode);
890 : 8375 : emit_insn (gen_sse2_loadld (gen_rtx_SUBREG (V4SImode, vreg, 0),
891 : : CONST0_RTX (V4SImode),
892 : 8375 : gen_rtx_SUBREG (SImode, reg, 0)));
893 : 8375 : emit_insn (gen_sse2_loadld (gen_rtx_SUBREG (V4SImode, tmp, 0),
894 : : CONST0_RTX (V4SImode),
895 : 8375 : gen_rtx_SUBREG (SImode, reg, 4)));
896 : 8375 : emit_insn (gen_vec_interleave_lowv4si
897 : 8375 : (gen_rtx_SUBREG (V4SImode, vreg, 0),
898 : 8375 : gen_rtx_SUBREG (V4SImode, vreg, 0),
899 : 8375 : gen_rtx_SUBREG (V4SImode, tmp, 0)));
900 : : }
901 : : }
902 : : else
903 : 78 : emit_insn (gen_rtx_SET (gen_rtx_SUBREG (vmode, vreg, 0),
904 : : gen_gpr_to_xmm_move_src (vmode, reg)));
905 : 9117 : rtx_insn *seq = get_insns ();
906 : 9117 : end_sequence ();
907 : 9117 : emit_conversion_insns (seq, insn);
908 : :
909 : 9117 : if (dump_file)
910 : 0 : fprintf (dump_file,
911 : : " Copied r%d to a vector register r%d for insn %d\n",
912 : 0 : REGNO (reg), REGNO (vreg), INSN_UID (insn));
913 : 9117 : }
914 : :
915 : : /* Copy the definition SRC of INSN inside the chain to DST for
916 : : scalar uses outside of the chain. */
917 : :
918 : : void
919 : 23657 : scalar_chain::convert_reg (rtx_insn *insn, rtx dst, rtx src)
920 : : {
921 : 23657 : start_sequence ();
922 : 23657 : if (!TARGET_INTER_UNIT_MOVES_FROM_VEC)
923 : : {
924 : 0 : rtx tmp = assign_386_stack_local (smode, SLOT_STV_TEMP);
925 : 0 : emit_move_insn (tmp, src);
926 : 0 : if (!TARGET_64BIT && smode == DImode)
927 : : {
928 : 0 : emit_move_insn (gen_rtx_SUBREG (SImode, dst, 0),
929 : 0 : adjust_address (tmp, SImode, 0));
930 : 0 : emit_move_insn (gen_rtx_SUBREG (SImode, dst, 4),
931 : 0 : adjust_address (tmp, SImode, 4));
932 : : }
933 : : else
934 : 0 : emit_move_insn (dst, copy_rtx (tmp));
935 : : }
936 : 23657 : else if (!TARGET_64BIT && smode == DImode)
937 : : {
938 : 23407 : if (TARGET_SSE4_1)
939 : : {
940 : 0 : rtx tmp = gen_rtx_PARALLEL (VOIDmode,
941 : : gen_rtvec (1, const0_rtx));
942 : 0 : emit_insn
943 : 0 : (gen_rtx_SET
944 : : (gen_rtx_SUBREG (SImode, dst, 0),
945 : : gen_rtx_VEC_SELECT (SImode,
946 : : gen_rtx_SUBREG (V4SImode, src, 0),
947 : : tmp)));
948 : :
949 : 0 : tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (1, const1_rtx));
950 : 0 : emit_insn
951 : 0 : (gen_rtx_SET
952 : : (gen_rtx_SUBREG (SImode, dst, 4),
953 : : gen_rtx_VEC_SELECT (SImode,
954 : : gen_rtx_SUBREG (V4SImode, src, 0),
955 : : tmp)));
956 : : }
957 : : else
958 : : {
959 : 23407 : rtx vcopy = gen_reg_rtx (V2DImode);
960 : 23407 : emit_move_insn (vcopy, gen_rtx_SUBREG (V2DImode, src, 0));
961 : 23407 : emit_move_insn (gen_rtx_SUBREG (SImode, dst, 0),
962 : 23407 : gen_rtx_SUBREG (SImode, vcopy, 0));
963 : 23407 : emit_move_insn (vcopy,
964 : : gen_rtx_LSHIFTRT (V2DImode,
965 : : vcopy, GEN_INT (32)));
966 : 23407 : emit_move_insn (gen_rtx_SUBREG (SImode, dst, 4),
967 : 23407 : gen_rtx_SUBREG (SImode, vcopy, 0));
968 : : }
969 : : }
970 : : else
971 : 250 : emit_move_insn (dst, src);
972 : :
973 : 23657 : rtx_insn *seq = get_insns ();
974 : 23657 : end_sequence ();
975 : 23657 : emit_conversion_insns (seq, insn);
976 : :
977 : 23657 : if (dump_file)
978 : 0 : fprintf (dump_file,
979 : : " Copied r%d to a scalar register r%d for insn %d\n",
980 : 0 : REGNO (src), REGNO (dst), INSN_UID (insn));
981 : 23657 : }
982 : :
983 : : /* Helper function to convert immediate constant X to vmode. */
984 : : static rtx
985 : 44516 : smode_convert_cst (rtx x, enum machine_mode vmode)
986 : : {
987 : : /* Prefer all ones vector in case of -1. */
988 : 44516 : if (constm1_operand (x, GET_MODE (x)))
989 : 775 : return CONSTM1_RTX (vmode);
990 : :
991 : 43741 : unsigned n = GET_MODE_NUNITS (vmode);
992 : 43741 : rtx *v = XALLOCAVEC (rtx, n);
993 : 43741 : v[0] = x;
994 : 52172 : for (unsigned i = 1; i < n; ++i)
995 : 8431 : v[i] = const0_rtx;
996 : 43741 : return gen_rtx_CONST_VECTOR (vmode, gen_rtvec_v (n, v));
997 : : }
998 : :
999 : : /* Convert operand OP in INSN. We should handle
1000 : : memory operands and uninitialized registers.
1001 : : All other register uses are converted during
1002 : : registers conversion. */
1003 : :
1004 : : void
1005 : 259023 : scalar_chain::convert_op (rtx *op, rtx_insn *insn)
1006 : : {
1007 : 259023 : rtx tmp;
1008 : :
1009 : 259023 : if (GET_MODE (*op) == V1TImode)
1010 : : return;
1011 : :
1012 : 258996 : *op = copy_rtx_if_shared (*op);
1013 : :
1014 : 258996 : if (GET_CODE (*op) == NOT
1015 : 258996 : || GET_CODE (*op) == ASHIFT)
1016 : : {
1017 : 3547 : convert_op (&XEXP (*op, 0), insn);
1018 : 3547 : PUT_MODE (*op, vmode);
1019 : : }
1020 : : else if (MEM_P (*op))
1021 : : {
1022 : 173142 : rtx_insn *movabs = NULL;
1023 : :
1024 : : /* Emit MOVABS to load from a 64-bit absolute address to a GPR. */
1025 : 173142 : if (!memory_operand (*op, GET_MODE (*op)))
1026 : : {
1027 : 0 : tmp = gen_reg_rtx (GET_MODE (*op));
1028 : 0 : movabs = emit_insn_before (gen_rtx_SET (tmp, *op), insn);
1029 : :
1030 : 0 : *op = tmp;
1031 : : }
1032 : :
1033 : 173142 : tmp = gen_rtx_SUBREG (vmode, gen_reg_rtx (GET_MODE (*op)), 0);
1034 : :
1035 : 173142 : rtx_insn *eh_insn
1036 : 173142 : = emit_insn_before (gen_rtx_SET (copy_rtx (tmp),
1037 : : gen_gpr_to_xmm_move_src (vmode, *op)),
1038 : 173142 : insn);
1039 : :
1040 : 173142 : if (cfun->can_throw_non_call_exceptions)
1041 : : {
1042 : : /* Handle REG_EH_REGION note. */
1043 : 169176 : rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
1044 : 169176 : if (note)
1045 : : {
1046 : 3592 : if (movabs)
1047 : 0 : eh_insn = movabs;
1048 : 3592 : control_flow_insns.safe_push (eh_insn);
1049 : 3592 : add_reg_note (eh_insn, REG_EH_REGION, XEXP (note, 0));
1050 : : }
1051 : : }
1052 : :
1053 : 173142 : *op = tmp;
1054 : :
1055 : 173142 : if (dump_file)
1056 : 0 : fprintf (dump_file, " Preloading operand for insn %d into r%d\n",
1057 : 0 : INSN_UID (insn), reg_or_subregno (tmp));
1058 : : }
1059 : : else if (REG_P (*op))
1060 : 73278 : *op = gen_rtx_SUBREG (vmode, *op, 0);
1061 : : else if (CONST_SCALAR_INT_P (*op))
1062 : : {
1063 : 9029 : rtx vec_cst = smode_convert_cst (*op, vmode);
1064 : :
1065 : 9029 : if (!standard_sse_constant_p (vec_cst, vmode))
1066 : : {
1067 : 5004 : start_sequence ();
1068 : 5004 : vec_cst = validize_mem (force_const_mem (vmode, vec_cst));
1069 : 5004 : rtx_insn *seq = get_insns ();
1070 : 5004 : end_sequence ();
1071 : 5004 : emit_insn_before (seq, insn);
1072 : : }
1073 : :
1074 : 9029 : tmp = gen_rtx_SUBREG (vmode, gen_reg_rtx (smode), 0);
1075 : :
1076 : 9029 : emit_insn_before (gen_move_insn (copy_rtx (tmp), vec_cst), insn);
1077 : 9029 : *op = tmp;
1078 : : }
1079 : : else
1080 : : {
1081 : 0 : gcc_assert (SUBREG_P (*op));
1082 : 0 : gcc_assert (GET_MODE (*op) == vmode);
1083 : : }
1084 : : }
1085 : :
1086 : : /* Convert CCZmode COMPARE to vector mode. */
1087 : :
1088 : : rtx
1089 : 6 : scalar_chain::convert_compare (rtx op1, rtx op2, rtx_insn *insn)
1090 : : {
1091 : 6 : rtx src, tmp;
1092 : :
1093 : : /* Handle any REG_EQUAL notes. */
1094 : 6 : tmp = find_reg_equal_equiv_note (insn);
1095 : 6 : if (tmp)
1096 : : {
1097 : 1 : if (GET_CODE (XEXP (tmp, 0)) == COMPARE
1098 : 1 : && GET_MODE (XEXP (tmp, 0)) == CCZmode
1099 : 1 : && REG_P (XEXP (XEXP (tmp, 0), 0)))
1100 : : {
1101 : 1 : rtx *op = &XEXP (XEXP (tmp, 0), 1);
1102 : 1 : if (CONST_SCALAR_INT_P (*op))
1103 : : {
1104 : 1 : if (constm1_operand (*op, GET_MODE (*op)))
1105 : 0 : *op = CONSTM1_RTX (vmode);
1106 : : else
1107 : : {
1108 : 1 : unsigned n = GET_MODE_NUNITS (vmode);
1109 : 1 : rtx *v = XALLOCAVEC (rtx, n);
1110 : 1 : v[0] = *op;
1111 : 1 : for (unsigned i = 1; i < n; ++i)
1112 : 0 : v[i] = const0_rtx;
1113 : 1 : *op = gen_rtx_CONST_VECTOR (vmode, gen_rtvec_v (n, v));
1114 : : }
1115 : : tmp = NULL_RTX;
1116 : : }
1117 : 0 : else if (REG_P (*op))
1118 : : tmp = NULL_RTX;
1119 : : }
1120 : :
1121 : : if (tmp)
1122 : 0 : remove_note (insn, tmp);
1123 : : }
1124 : :
1125 : : /* Comparison against anything other than zero, requires an XOR. */
1126 : 6 : if (op2 != const0_rtx)
1127 : : {
1128 : 4 : convert_op (&op1, insn);
1129 : 4 : convert_op (&op2, insn);
1130 : : /* If both operands are MEMs, explicitly load the OP1 into TMP. */
1131 : 4 : if (MEM_P (op1) && MEM_P (op2))
1132 : : {
1133 : 0 : tmp = gen_reg_rtx (vmode);
1134 : 0 : emit_insn_before (gen_rtx_SET (tmp, op1), insn);
1135 : 0 : src = tmp;
1136 : : }
1137 : : else
1138 : : src = op1;
1139 : 4 : src = gen_rtx_XOR (vmode, src, op2);
1140 : : }
1141 : 2 : else if (GET_CODE (op1) == AND
1142 : 0 : && GET_CODE (XEXP (op1, 0)) == NOT)
1143 : : {
1144 : 0 : rtx op11 = XEXP (XEXP (op1, 0), 0);
1145 : 0 : rtx op12 = XEXP (op1, 1);
1146 : 0 : convert_op (&op11, insn);
1147 : 0 : convert_op (&op12, insn);
1148 : 0 : if (!REG_P (op11))
1149 : : {
1150 : 0 : tmp = gen_reg_rtx (vmode);
1151 : 0 : emit_insn_before (gen_rtx_SET (tmp, op11), insn);
1152 : 0 : op11 = tmp;
1153 : : }
1154 : 0 : src = gen_rtx_AND (vmode, gen_rtx_NOT (vmode, op11), op12);
1155 : 0 : }
1156 : 2 : else if (GET_CODE (op1) == AND)
1157 : : {
1158 : 0 : rtx op11 = XEXP (op1, 0);
1159 : 0 : rtx op12 = XEXP (op1, 1);
1160 : 0 : convert_op (&op11, insn);
1161 : 0 : convert_op (&op12, insn);
1162 : 0 : if (!REG_P (op11))
1163 : : {
1164 : 0 : tmp = gen_reg_rtx (vmode);
1165 : 0 : emit_insn_before (gen_rtx_SET (tmp, op11), insn);
1166 : 0 : op11 = tmp;
1167 : : }
1168 : 0 : return gen_rtx_UNSPEC (CCZmode, gen_rtvec (2, op11, op12),
1169 : : UNSPEC_PTEST);
1170 : : }
1171 : : else
1172 : : {
1173 : 2 : convert_op (&op1, insn);
1174 : 2 : src = op1;
1175 : : }
1176 : :
1177 : 6 : if (!REG_P (src))
1178 : : {
1179 : 4 : tmp = gen_reg_rtx (vmode);
1180 : 4 : emit_insn_before (gen_rtx_SET (tmp, src), insn);
1181 : 4 : src = tmp;
1182 : : }
1183 : :
1184 : 6 : if (vmode == V2DImode)
1185 : : {
1186 : 0 : tmp = gen_reg_rtx (vmode);
1187 : 0 : emit_insn_before (gen_vec_interleave_lowv2di (tmp, src, src), insn);
1188 : 0 : src = tmp;
1189 : : }
1190 : 6 : else if (vmode == V4SImode)
1191 : : {
1192 : 0 : tmp = gen_reg_rtx (vmode);
1193 : 0 : emit_insn_before (gen_sse2_pshufd (tmp, src, const0_rtx), insn);
1194 : 0 : src = tmp;
1195 : : }
1196 : :
1197 : 6 : return gen_rtx_UNSPEC (CCZmode, gen_rtvec (2, src, src), UNSPEC_PTEST);
1198 : : }
1199 : :
1200 : : /* Helper function for converting INSN to vector mode. */
1201 : :
1202 : : void
1203 : 1283393 : scalar_chain::convert_insn_common (rtx_insn *insn)
1204 : : {
1205 : : /* Generate copies for out-of-chain uses of defs and adjust debug uses. */
1206 : 1968396 : for (df_ref ref = DF_INSN_DEFS (insn); ref; ref = DF_REF_NEXT_LOC (ref))
1207 : 685003 : if (bitmap_bit_p (defs_conv, DF_REF_REGNO (ref)))
1208 : : {
1209 : 25979 : df_link *use;
1210 : 50410 : for (use = DF_REF_CHAIN (ref); use; use = use->next)
1211 : 48088 : if (NONDEBUG_INSN_P (DF_REF_INSN (use->ref))
1212 : 48088 : && (DF_REF_REG_MEM_P (use->ref)
1213 : 41732 : || !bitmap_bit_p (insns, DF_REF_INSN_UID (use->ref))))
1214 : : break;
1215 : 25979 : if (use)
1216 : 23657 : convert_reg (insn, DF_REF_REG (ref),
1217 : 23657 : *defs_map.get (regno_reg_rtx [DF_REF_REGNO (ref)]));
1218 : 2322 : else if (MAY_HAVE_DEBUG_BIND_INSNS)
1219 : : {
1220 : : /* If we generated a scalar copy we can leave debug-insns
1221 : : as-is, if not, we have to adjust them. */
1222 : 2282 : auto_vec<rtx_insn *, 5> to_reset_debug_insns;
1223 : 7660 : for (use = DF_REF_CHAIN (ref); use; use = use->next)
1224 : 5378 : if (DEBUG_INSN_P (DF_REF_INSN (use->ref)))
1225 : : {
1226 : 1898 : rtx_insn *debug_insn = DF_REF_INSN (use->ref);
1227 : : /* If there's a reaching definition outside of the
1228 : : chain we have to reset. */
1229 : 1898 : df_link *def;
1230 : 8094 : for (def = DF_REF_CHAIN (use->ref); def; def = def->next)
1231 : 6571 : if (!bitmap_bit_p (insns, DF_REF_INSN_UID (def->ref)))
1232 : : break;
1233 : 1898 : if (def)
1234 : 375 : to_reset_debug_insns.safe_push (debug_insn);
1235 : : else
1236 : : {
1237 : 1523 : *DF_REF_REAL_LOC (use->ref)
1238 : 1523 : = *defs_map.get (regno_reg_rtx [DF_REF_REGNO (ref)]);
1239 : 1523 : df_insn_rescan (debug_insn);
1240 : : }
1241 : : }
1242 : : /* Have to do the reset outside of the DF_CHAIN walk to not
1243 : : disrupt it. */
1244 : 4939 : while (!to_reset_debug_insns.is_empty ())
1245 : : {
1246 : 375 : rtx_insn *debug_insn = to_reset_debug_insns.pop ();
1247 : 375 : INSN_VAR_LOCATION_LOC (debug_insn) = gen_rtx_UNKNOWN_VAR_LOC ();
1248 : 375 : df_insn_rescan_debug_internal (debug_insn);
1249 : : }
1250 : 2282 : }
1251 : : }
1252 : :
1253 : : /* Replace uses in this insn with the defs we use in the chain. */
1254 : 3183499 : for (df_ref ref = DF_INSN_USES (insn); ref; ref = DF_REF_NEXT_LOC (ref))
1255 : 1900106 : if (!DF_REF_REG_MEM_P (ref))
1256 : 695088 : if (rtx *vreg = defs_map.get (regno_reg_rtx[DF_REF_REGNO (ref)]))
1257 : : {
1258 : : /* Also update a corresponding REG_DEAD note. */
1259 : 38681 : rtx note = find_reg_note (insn, REG_DEAD, DF_REF_REG (ref));
1260 : 38681 : if (note)
1261 : 25124 : XEXP (note, 0) = *vreg;
1262 : 38681 : *DF_REF_REAL_LOC (ref) = *vreg;
1263 : : }
1264 : 1283393 : }
1265 : :
1266 : : /* Convert INSN which is an SImode or DImode rotation by a constant
1267 : : to vector mode. CODE is either ROTATE or ROTATERT with operands
1268 : : OP0 and OP1. Returns the SET_SRC of the last instruction in the
1269 : : resulting sequence, which is emitted before INSN. */
1270 : :
1271 : : rtx
1272 : 100 : general_scalar_chain::convert_rotate (enum rtx_code code, rtx op0, rtx op1,
1273 : : rtx_insn *insn)
1274 : : {
1275 : 100 : int bits = INTVAL (op1);
1276 : 100 : rtx pat, result;
1277 : :
1278 : 100 : convert_op (&op0, insn);
1279 : 100 : if (bits == 0)
1280 : 0 : return op0;
1281 : :
1282 : 100 : if (smode == DImode)
1283 : : {
1284 : 100 : if (code == ROTATE)
1285 : 53 : bits = 64 - bits;
1286 : 100 : if (bits == 32)
1287 : : {
1288 : 8 : rtx tmp1 = gen_reg_rtx (V4SImode);
1289 : 8 : pat = gen_sse2_pshufd (tmp1, gen_lowpart (V4SImode, op0),
1290 : : GEN_INT (225));
1291 : 8 : emit_insn_before (pat, insn);
1292 : 8 : result = gen_lowpart (V2DImode, tmp1);
1293 : : }
1294 : 92 : else if (TARGET_AVX512VL)
1295 : 0 : result = simplify_gen_binary (code, V2DImode, op0, op1);
1296 : 92 : else if (bits == 16 || bits == 48)
1297 : : {
1298 : 0 : rtx tmp1 = gen_reg_rtx (V8HImode);
1299 : 0 : pat = gen_sse2_pshuflw (tmp1, gen_lowpart (V8HImode, op0),
1300 : : GEN_INT (bits == 16 ? 57 : 147));
1301 : 0 : emit_insn_before (pat, insn);
1302 : 0 : result = gen_lowpart (V2DImode, tmp1);
1303 : : }
1304 : 92 : else if ((bits & 0x07) == 0)
1305 : : {
1306 : 0 : rtx tmp1 = gen_reg_rtx (V4SImode);
1307 : 0 : pat = gen_sse2_pshufd (tmp1, gen_lowpart (V4SImode, op0),
1308 : : GEN_INT (68));
1309 : 0 : emit_insn_before (pat, insn);
1310 : 0 : rtx tmp2 = gen_reg_rtx (V1TImode);
1311 : 0 : pat = gen_sse2_lshrv1ti3 (tmp2, gen_lowpart (V1TImode, tmp1),
1312 : : GEN_INT (bits));
1313 : 0 : emit_insn_before (pat, insn);
1314 : 0 : result = gen_lowpart (V2DImode, tmp2);
1315 : : }
1316 : : else
1317 : : {
1318 : 92 : rtx tmp1 = gen_reg_rtx (V4SImode);
1319 : 92 : pat = gen_sse2_pshufd (tmp1, gen_lowpart (V4SImode, op0),
1320 : : GEN_INT (20));
1321 : 92 : emit_insn_before (pat, insn);
1322 : 92 : rtx tmp2 = gen_reg_rtx (V2DImode);
1323 : 92 : pat = gen_lshrv2di3 (tmp2, gen_lowpart (V2DImode, tmp1),
1324 : : GEN_INT (bits & 31));
1325 : 92 : emit_insn_before (pat, insn);
1326 : 92 : rtx tmp3 = gen_reg_rtx (V4SImode);
1327 : 139 : pat = gen_sse2_pshufd (tmp3, gen_lowpart (V4SImode, tmp2),
1328 : : GEN_INT (bits > 32 ? 34 : 136));
1329 : 92 : emit_insn_before (pat, insn);
1330 : 92 : result = gen_lowpart (V2DImode, tmp3);
1331 : : }
1332 : : }
1333 : 0 : else if (bits == 16)
1334 : : {
1335 : 0 : rtx tmp1 = gen_reg_rtx (V8HImode);
1336 : 0 : pat = gen_sse2_pshuflw (tmp1, gen_lowpart (V8HImode, op0), GEN_INT (225));
1337 : 0 : emit_insn_before (pat, insn);
1338 : 0 : result = gen_lowpart (V4SImode, tmp1);
1339 : : }
1340 : 0 : else if (TARGET_AVX512VL)
1341 : 0 : result = simplify_gen_binary (code, V4SImode, op0, op1);
1342 : : else
1343 : : {
1344 : 0 : if (code == ROTATE)
1345 : 0 : bits = 32 - bits;
1346 : :
1347 : 0 : rtx tmp1 = gen_reg_rtx (V4SImode);
1348 : 0 : emit_insn_before (gen_sse2_pshufd (tmp1, op0, GEN_INT (224)), insn);
1349 : 0 : rtx tmp2 = gen_reg_rtx (V2DImode);
1350 : 0 : pat = gen_lshrv2di3 (tmp2, gen_lowpart (V2DImode, tmp1),
1351 : : GEN_INT (bits));
1352 : 0 : emit_insn_before (pat, insn);
1353 : 0 : result = gen_lowpart (V4SImode, tmp2);
1354 : : }
1355 : :
1356 : : return result;
1357 : : }
1358 : :
1359 : : /* Convert INSN to vector mode. */
1360 : :
1361 : : void
1362 : 416588 : general_scalar_chain::convert_insn (rtx_insn *insn)
1363 : : {
1364 : 416588 : rtx def_set = single_set (insn);
1365 : 416588 : rtx src = SET_SRC (def_set);
1366 : 416588 : rtx dst = SET_DEST (def_set);
1367 : 416588 : rtx subreg;
1368 : :
1369 : 416588 : if (MEM_P (dst) && !REG_P (src))
1370 : : {
1371 : : /* There are no scalar integer instructions and therefore
1372 : : temporary register usage is required. */
1373 : 760 : rtx tmp = gen_reg_rtx (smode);
1374 : 760 : emit_conversion_insns (gen_move_insn (dst, tmp), insn);
1375 : 760 : dst = gen_rtx_SUBREG (vmode, tmp, 0);
1376 : 760 : }
1377 : 415828 : else if (REG_P (dst) && GET_MODE (dst) == smode)
1378 : : {
1379 : : /* Replace the definition with a SUBREG to the definition we
1380 : : use inside the chain. */
1381 : 222304 : rtx *vdef = defs_map.get (dst);
1382 : 222304 : if (vdef)
1383 : 25979 : dst = *vdef;
1384 : 222304 : dst = gen_rtx_SUBREG (vmode, dst, 0);
1385 : : /* IRA doesn't like to have REG_EQUAL/EQUIV notes when the SET_DEST
1386 : : is a non-REG_P. So kill those off. */
1387 : 222304 : rtx note = find_reg_equal_equiv_note (insn);
1388 : 222304 : if (note)
1389 : 9015 : remove_note (insn, note);
1390 : : }
1391 : :
1392 : 416588 : switch (GET_CODE (src))
1393 : : {
1394 : 34027 : case PLUS:
1395 : 34027 : case MINUS:
1396 : 34027 : case IOR:
1397 : 34027 : case XOR:
1398 : 34027 : case AND:
1399 : 34027 : case SMAX:
1400 : 34027 : case SMIN:
1401 : 34027 : case UMAX:
1402 : 34027 : case UMIN:
1403 : 34027 : convert_op (&XEXP (src, 1), insn);
1404 : : /* FALLTHRU */
1405 : :
1406 : 43384 : case ABS:
1407 : 43384 : case ASHIFT:
1408 : 43384 : case ASHIFTRT:
1409 : 43384 : case LSHIFTRT:
1410 : 43384 : convert_op (&XEXP (src, 0), insn);
1411 : 43384 : PUT_MODE (src, vmode);
1412 : 43384 : break;
1413 : :
1414 : 100 : case ROTATE:
1415 : 100 : case ROTATERT:
1416 : 100 : src = convert_rotate (GET_CODE (src), XEXP (src, 0), XEXP (src, 1),
1417 : : insn);
1418 : 100 : break;
1419 : :
1420 : 435 : case NEG:
1421 : 435 : src = XEXP (src, 0);
1422 : :
1423 : 435 : if (GET_CODE (src) == ABS)
1424 : : {
1425 : 0 : src = XEXP (src, 0);
1426 : 0 : convert_op (&src, insn);
1427 : 0 : subreg = gen_reg_rtx (vmode);
1428 : 0 : emit_insn_before (gen_rtx_SET (subreg,
1429 : : gen_rtx_ABS (vmode, src)), insn);
1430 : 0 : src = subreg;
1431 : : }
1432 : : else
1433 : 435 : convert_op (&src, insn);
1434 : :
1435 : 435 : subreg = gen_reg_rtx (vmode);
1436 : 435 : emit_insn_before (gen_move_insn (subreg, CONST0_RTX (vmode)), insn);
1437 : 435 : src = gen_rtx_MINUS (vmode, subreg, src);
1438 : 435 : break;
1439 : :
1440 : 302 : case NOT:
1441 : 302 : src = XEXP (src, 0);
1442 : 302 : convert_op (&src, insn);
1443 : 302 : subreg = gen_reg_rtx (vmode);
1444 : 302 : emit_insn_before (gen_move_insn (subreg, CONSTM1_RTX (vmode)), insn);
1445 : 302 : src = gen_rtx_XOR (vmode, src, subreg);
1446 : 302 : break;
1447 : :
1448 : 171046 : case MEM:
1449 : 171046 : if (!REG_P (dst))
1450 : 171046 : convert_op (&src, insn);
1451 : : break;
1452 : :
1453 : 195149 : case REG:
1454 : 195149 : if (!MEM_P (dst))
1455 : 1625 : convert_op (&src, insn);
1456 : : break;
1457 : :
1458 : 0 : case SUBREG:
1459 : 0 : gcc_assert (GET_MODE (src) == vmode);
1460 : : break;
1461 : :
1462 : 0 : case COMPARE:
1463 : 0 : dst = gen_rtx_REG (CCZmode, FLAGS_REG);
1464 : 0 : src = convert_compare (XEXP (src, 0), XEXP (src, 1), insn);
1465 : 0 : break;
1466 : :
1467 : 4513 : case CONST_INT:
1468 : 4513 : convert_op (&src, insn);
1469 : 4513 : break;
1470 : :
1471 : 1659 : case VEC_SELECT:
1472 : 1659 : if (XVECEXP (XEXP (src, 1), 0, 0) == const0_rtx)
1473 : 1280 : src = XEXP (src, 0);
1474 : 379 : else if (smode == DImode)
1475 : : {
1476 : 227 : rtx tmp = gen_lowpart (V1TImode, XEXP (src, 0));
1477 : 227 : dst = gen_lowpart (V1TImode, dst);
1478 : 227 : src = gen_rtx_LSHIFTRT (V1TImode, tmp, GEN_INT (64));
1479 : : }
1480 : : else
1481 : : {
1482 : 152 : rtx tmp = XVECEXP (XEXP (src, 1), 0, 0);
1483 : 152 : rtvec vec = gen_rtvec (4, tmp, tmp, tmp, tmp);
1484 : 152 : rtx par = gen_rtx_PARALLEL (VOIDmode, vec);
1485 : 152 : src = gen_rtx_VEC_SELECT (vmode, XEXP (src, 0), par);
1486 : : }
1487 : : break;
1488 : :
1489 : 0 : default:
1490 : 0 : gcc_unreachable ();
1491 : : }
1492 : :
1493 : 416588 : SET_SRC (def_set) = src;
1494 : 416588 : SET_DEST (def_set) = dst;
1495 : :
1496 : : /* Drop possible dead definitions. */
1497 : 416588 : PATTERN (insn) = def_set;
1498 : :
1499 : 416588 : INSN_CODE (insn) = -1;
1500 : 416588 : int patt = recog_memoized (insn);
1501 : 416588 : if (patt == -1)
1502 : 0 : fatal_insn_not_found (insn);
1503 : 416588 : df_insn_rescan (insn);
1504 : 416588 : }
1505 : :
1506 : : /* Helper function to compute gain for loading an immediate constant.
1507 : : Typically, two movabsq for TImode vs. vmovdqa for V1TImode, but
1508 : : with numerous special cases. */
1509 : :
1510 : : static int
1511 : 5 : timode_immed_const_gain (rtx cst)
1512 : : {
1513 : : /* movabsq vs. movabsq+vmovq+vunpacklqdq. */
1514 : 5 : if (CONST_WIDE_INT_P (cst)
1515 : 4 : && CONST_WIDE_INT_NUNITS (cst) == 2
1516 : 9 : && CONST_WIDE_INT_ELT (cst, 0) == CONST_WIDE_INT_ELT (cst, 1))
1517 : 0 : return optimize_insn_for_size_p () ? -COSTS_N_BYTES (9)
1518 : : : -COSTS_N_INSNS (2);
1519 : : /* 2x movabsq ~ vmovdqa. */
1520 : : return 0;
1521 : : }
1522 : :
1523 : : /* Compute a gain for chain conversion. */
1524 : :
1525 : : int
1526 : 440242 : timode_scalar_chain::compute_convert_gain ()
1527 : : {
1528 : : /* Assume that if we have to move TImode values between units,
1529 : : then transforming this chain isn't worth it. */
1530 : 440242 : if (n_sse_to_integer || n_integer_to_sse)
1531 : : return -1;
1532 : :
1533 : 440242 : bitmap_iterator bi;
1534 : 440242 : unsigned insn_uid;
1535 : :
1536 : : /* Split ties to prefer V1TImode when not optimizing for size. */
1537 : 440242 : int gain = optimize_size ? 0 : 1;
1538 : :
1539 : 440242 : if (dump_file)
1540 : 0 : fprintf (dump_file, "Computing gain for chain #%d...\n", chain_id);
1541 : :
1542 : 1307379 : EXECUTE_IF_SET_IN_BITMAP (insns, 0, insn_uid, bi)
1543 : : {
1544 : 867137 : rtx_insn *insn = DF_INSN_UID_GET (insn_uid)->insn;
1545 : 867137 : rtx def_set = single_set (insn);
1546 : 867137 : rtx src = SET_SRC (def_set);
1547 : 867137 : rtx dst = SET_DEST (def_set);
1548 : 867137 : HOST_WIDE_INT op1val;
1549 : 867137 : int scost, vcost;
1550 : 867137 : int igain = 0;
1551 : :
1552 : 867137 : switch (GET_CODE (src))
1553 : : {
1554 : 426646 : case REG:
1555 : 426646 : if (optimize_insn_for_size_p ())
1556 : 2470 : igain = MEM_P (dst) ? COSTS_N_BYTES (6) : COSTS_N_BYTES (3);
1557 : : else
1558 : : igain = COSTS_N_INSNS (1);
1559 : : break;
1560 : :
1561 : 394618 : case MEM:
1562 : 394618 : igain = optimize_insn_for_size_p () ? COSTS_N_BYTES (7)
1563 : : : COSTS_N_INSNS (1);
1564 : : break;
1565 : :
1566 : 9924 : case CONST_INT:
1567 : 9924 : if (MEM_P (dst)
1568 : 9924 : && standard_sse_constant_p (src, V1TImode))
1569 : 9418 : igain = optimize_insn_for_size_p () ? COSTS_N_BYTES (11) : 1;
1570 : : break;
1571 : :
1572 : 35682 : case CONST_WIDE_INT:
1573 : : /* 2 x mov vs. vmovdqa. */
1574 : 35682 : if (MEM_P (dst))
1575 : 35501 : igain = optimize_insn_for_size_p () ? COSTS_N_BYTES (3)
1576 : : : COSTS_N_INSNS (1);
1577 : : break;
1578 : :
1579 : 17 : case NOT:
1580 : 17 : if (MEM_P (dst))
1581 : : igain = -COSTS_N_INSNS (1);
1582 : : break;
1583 : :
1584 : 12 : case AND:
1585 : 12 : case XOR:
1586 : 12 : case IOR:
1587 : 12 : if (!MEM_P (dst))
1588 : 6 : igain = COSTS_N_INSNS (1);
1589 : 12 : if (CONST_SCALAR_INT_P (XEXP (src, 1)))
1590 : 5 : igain += timode_immed_const_gain (XEXP (src, 1));
1591 : : break;
1592 : :
1593 : 124 : case ASHIFT:
1594 : 124 : case LSHIFTRT:
1595 : : /* See ix86_expand_v1ti_shift. */
1596 : 124 : op1val = INTVAL (XEXP (src, 1));
1597 : 124 : if (optimize_insn_for_size_p ())
1598 : : {
1599 : 9 : if (op1val == 64 || op1val == 65)
1600 : : scost = COSTS_N_BYTES (5);
1601 : 9 : else if (op1val >= 66)
1602 : : scost = COSTS_N_BYTES (6);
1603 : 9 : else if (op1val == 1)
1604 : : scost = COSTS_N_BYTES (8);
1605 : : else
1606 : : scost = COSTS_N_BYTES (9);
1607 : :
1608 : 8 : if ((op1val & 7) == 0)
1609 : : vcost = COSTS_N_BYTES (5);
1610 : 9 : else if (op1val > 64)
1611 : : vcost = COSTS_N_BYTES (10);
1612 : : else
1613 : 9 : vcost = TARGET_AVX ? COSTS_N_BYTES (19) : COSTS_N_BYTES (23);
1614 : : }
1615 : : else
1616 : : {
1617 : 115 : scost = COSTS_N_INSNS (2);
1618 : 115 : if ((op1val & 7) == 0)
1619 : : vcost = COSTS_N_INSNS (1);
1620 : 113 : else if (op1val > 64)
1621 : : vcost = COSTS_N_INSNS (2);
1622 : : else
1623 : 109 : vcost = TARGET_AVX ? COSTS_N_INSNS (4) : COSTS_N_INSNS (5);
1624 : : }
1625 : 124 : igain = scost - vcost;
1626 : 124 : break;
1627 : :
1628 : 103 : case ASHIFTRT:
1629 : : /* See ix86_expand_v1ti_ashiftrt. */
1630 : 103 : op1val = INTVAL (XEXP (src, 1));
1631 : 103 : if (optimize_insn_for_size_p ())
1632 : : {
1633 : 6 : if (op1val == 64 || op1val == 127)
1634 : : scost = COSTS_N_BYTES (7);
1635 : 6 : else if (op1val == 1)
1636 : : scost = COSTS_N_BYTES (8);
1637 : 6 : else if (op1val == 65)
1638 : : scost = COSTS_N_BYTES (10);
1639 : 6 : else if (op1val >= 66)
1640 : : scost = COSTS_N_BYTES (11);
1641 : : else
1642 : : scost = COSTS_N_BYTES (9);
1643 : :
1644 : 0 : if (op1val == 127)
1645 : : vcost = COSTS_N_BYTES (10);
1646 : 6 : else if (op1val == 64)
1647 : : vcost = COSTS_N_BYTES (14);
1648 : 6 : else if (op1val == 96)
1649 : : vcost = COSTS_N_BYTES (18);
1650 : 6 : else if (op1val >= 111)
1651 : : vcost = COSTS_N_BYTES (15);
1652 : 6 : else if (TARGET_AVX2 && op1val == 32)
1653 : : vcost = COSTS_N_BYTES (16);
1654 : 6 : else if (TARGET_SSE4_1 && op1val == 32)
1655 : : vcost = COSTS_N_BYTES (20);
1656 : 6 : else if (op1val >= 96)
1657 : : vcost = COSTS_N_BYTES (23);
1658 : 6 : else if ((op1val & 7) == 0)
1659 : : vcost = COSTS_N_BYTES (28);
1660 : 6 : else if (TARGET_AVX2 && op1val < 32)
1661 : : vcost = COSTS_N_BYTES (30);
1662 : 6 : else if (op1val == 1 || op1val >= 64)
1663 : : vcost = COSTS_N_BYTES (42);
1664 : : else
1665 : 6 : vcost = COSTS_N_BYTES (47);
1666 : : }
1667 : : else
1668 : : {
1669 : 97 : if (op1val >= 65 && op1val <= 126)
1670 : : scost = COSTS_N_INSNS (3);
1671 : : else
1672 : 97 : scost = COSTS_N_INSNS (2);
1673 : :
1674 : 97 : if (op1val == 127)
1675 : : vcost = COSTS_N_INSNS (2);
1676 : 97 : else if (op1val == 64)
1677 : : vcost = COSTS_N_INSNS (3);
1678 : 97 : else if (op1val == 96)
1679 : : vcost = COSTS_N_INSNS (3);
1680 : 97 : else if (op1val >= 111)
1681 : : vcost = COSTS_N_INSNS (3);
1682 : 97 : else if (TARGET_SSE4_1 && op1val == 32)
1683 : : vcost = COSTS_N_INSNS (3);
1684 : 97 : else if (TARGET_SSE4_1
1685 : 0 : && (op1val == 8 || op1val == 16 || op1val == 24))
1686 : : vcost = COSTS_N_INSNS (3);
1687 : 97 : else if (op1val >= 96)
1688 : : vcost = COSTS_N_INSNS (4);
1689 : 97 : else if (TARGET_SSE4_1 && (op1val == 28 || op1val == 80))
1690 : : vcost = COSTS_N_INSNS (4);
1691 : 97 : else if ((op1val & 7) == 0)
1692 : : vcost = COSTS_N_INSNS (5);
1693 : 97 : else if (TARGET_AVX2 && op1val < 32)
1694 : : vcost = COSTS_N_INSNS (6);
1695 : 97 : else if (TARGET_SSE4_1 && op1val < 15)
1696 : : vcost = COSTS_N_INSNS (6);
1697 : 97 : else if (op1val == 1 || op1val >= 64)
1698 : : vcost = COSTS_N_INSNS (8);
1699 : : else
1700 : 1 : vcost = COSTS_N_INSNS (9);
1701 : : }
1702 : 103 : igain = scost - vcost;
1703 : 103 : break;
1704 : :
1705 : 5 : case ROTATE:
1706 : 5 : case ROTATERT:
1707 : : /* See ix86_expand_v1ti_rotate. */
1708 : 5 : op1val = INTVAL (XEXP (src, 1));
1709 : 5 : if (optimize_insn_for_size_p ())
1710 : : {
1711 : 0 : scost = COSTS_N_BYTES (13);
1712 : 0 : if ((op1val & 31) == 0)
1713 : : vcost = COSTS_N_BYTES (5);
1714 : 0 : else if ((op1val & 7) == 0)
1715 : 0 : vcost = TARGET_AVX ? COSTS_N_BYTES (13) : COSTS_N_BYTES (18);
1716 : 0 : else if (op1val > 32 && op1val < 96)
1717 : : vcost = COSTS_N_BYTES (24);
1718 : : else
1719 : 0 : vcost = COSTS_N_BYTES (19);
1720 : : }
1721 : : else
1722 : : {
1723 : 5 : scost = COSTS_N_INSNS (3);
1724 : 5 : if ((op1val & 31) == 0)
1725 : : vcost = COSTS_N_INSNS (1);
1726 : 3 : else if ((op1val & 7) == 0)
1727 : 1 : vcost = TARGET_AVX ? COSTS_N_INSNS (3) : COSTS_N_INSNS (4);
1728 : 2 : else if (op1val > 32 && op1val < 96)
1729 : : vcost = COSTS_N_INSNS (5);
1730 : : else
1731 : 2 : vcost = COSTS_N_INSNS (1);
1732 : : }
1733 : 5 : igain = scost - vcost;
1734 : 5 : break;
1735 : :
1736 : 6 : case COMPARE:
1737 : 6 : if (XEXP (src, 1) == const0_rtx)
1738 : : {
1739 : 2 : if (GET_CODE (XEXP (src, 0)) == AND)
1740 : : /* and;and;or (9 bytes) vs. ptest (5 bytes). */
1741 : 0 : igain = optimize_insn_for_size_p() ? COSTS_N_BYTES (4)
1742 : : : COSTS_N_INSNS (2);
1743 : : /* or (3 bytes) vs. ptest (5 bytes). */
1744 : 2 : else if (optimize_insn_for_size_p ())
1745 : : igain = -COSTS_N_BYTES (2);
1746 : : }
1747 : 4 : else if (XEXP (src, 1) == const1_rtx)
1748 : : /* and;cmp -1 (7 bytes) vs. pcmpeqd;pxor;ptest (13 bytes). */
1749 : 0 : igain = optimize_insn_for_size_p() ? -COSTS_N_BYTES (6)
1750 : : : -COSTS_N_INSNS (1);
1751 : : break;
1752 : :
1753 : : default:
1754 : : break;
1755 : : }
1756 : :
1757 : 866443 : if (igain != 0 && dump_file)
1758 : : {
1759 : 0 : fprintf (dump_file, " Instruction gain %d for ", igain);
1760 : 0 : dump_insn_slim (dump_file, insn);
1761 : : }
1762 : 867137 : gain += igain;
1763 : : }
1764 : :
1765 : 440242 : if (dump_file)
1766 : 0 : fprintf (dump_file, " Total gain: %d\n", gain);
1767 : :
1768 : : return gain;
1769 : : }
1770 : :
1771 : : /* Fix uses of converted REG in debug insns. */
1772 : :
1773 : : void
1774 : 395411 : timode_scalar_chain::fix_debug_reg_uses (rtx reg)
1775 : : {
1776 : 395411 : if (!flag_var_tracking)
1777 : : return;
1778 : :
1779 : 349537 : df_ref ref, next;
1780 : 721594 : for (ref = DF_REG_USE_CHAIN (REGNO (reg)); ref; ref = next)
1781 : : {
1782 : 372057 : rtx_insn *insn = DF_REF_INSN (ref);
1783 : : /* Make sure the next ref is for a different instruction,
1784 : : so that we're not affected by the rescan. */
1785 : 372057 : next = DF_REF_NEXT_REG (ref);
1786 : 372057 : while (next && DF_REF_INSN (next) == insn)
1787 : 0 : next = DF_REF_NEXT_REG (next);
1788 : :
1789 : 372057 : if (DEBUG_INSN_P (insn))
1790 : : {
1791 : : /* It may be a debug insn with a TImode variable in
1792 : : register. */
1793 : : bool changed = false;
1794 : 708 : for (; ref != next; ref = DF_REF_NEXT_REG (ref))
1795 : : {
1796 : 354 : rtx *loc = DF_REF_LOC (ref);
1797 : 354 : if (REG_P (*loc) && GET_MODE (*loc) == V1TImode)
1798 : : {
1799 : 12 : *loc = gen_rtx_SUBREG (TImode, *loc, 0);
1800 : 12 : changed = true;
1801 : : }
1802 : : }
1803 : 354 : if (changed)
1804 : 12 : df_insn_rescan (insn);
1805 : : }
1806 : : }
1807 : : }
1808 : :
1809 : : /* Convert INSN from TImode to V1T1mode. */
1810 : :
1811 : : void
1812 : 866805 : timode_scalar_chain::convert_insn (rtx_insn *insn)
1813 : : {
1814 : 866805 : rtx def_set = single_set (insn);
1815 : 866805 : rtx src = SET_SRC (def_set);
1816 : 866805 : rtx dst = SET_DEST (def_set);
1817 : 866805 : rtx tmp;
1818 : :
1819 : 866805 : switch (GET_CODE (dst))
1820 : : {
1821 : 395417 : case REG:
1822 : 395417 : if (GET_MODE (dst) == TImode)
1823 : : {
1824 : 394836 : PUT_MODE (dst, V1TImode);
1825 : 394836 : fix_debug_reg_uses (dst);
1826 : : }
1827 : 395417 : if (GET_MODE (dst) == V1TImode)
1828 : : {
1829 : : /* It might potentially be helpful to convert REG_EQUAL notes,
1830 : : but for now we just remove them. */
1831 : 395411 : rtx note = find_reg_equal_equiv_note (insn);
1832 : 395411 : if (note)
1833 : 449 : remove_note (insn, note);
1834 : : }
1835 : : break;
1836 : 471388 : case MEM:
1837 : 471388 : PUT_MODE (dst, V1TImode);
1838 : 471388 : break;
1839 : :
1840 : 0 : default:
1841 : 0 : gcc_unreachable ();
1842 : : }
1843 : :
1844 : 866805 : switch (GET_CODE (src))
1845 : : {
1846 : 426600 : case REG:
1847 : 426600 : if (GET_MODE (src) == TImode)
1848 : : {
1849 : 575 : PUT_MODE (src, V1TImode);
1850 : 575 : fix_debug_reg_uses (src);
1851 : : }
1852 : : break;
1853 : :
1854 : 394572 : case MEM:
1855 : 394572 : PUT_MODE (src, V1TImode);
1856 : 394572 : break;
1857 : :
1858 : 35681 : case CONST_WIDE_INT:
1859 : 35681 : if (NONDEBUG_INSN_P (insn))
1860 : : {
1861 : : /* Since there are no instructions to store 128-bit constant,
1862 : : temporary register usage is required. */
1863 : 35681 : bool use_move;
1864 : 35681 : start_sequence ();
1865 : 35681 : tmp = ix86_convert_const_wide_int_to_broadcast (TImode, src);
1866 : 35681 : if (tmp)
1867 : : {
1868 : 194 : src = lowpart_subreg (V1TImode, tmp, TImode);
1869 : 194 : use_move = true;
1870 : : }
1871 : : else
1872 : : {
1873 : 35487 : src = smode_convert_cst (src, V1TImode);
1874 : 35487 : src = validize_mem (force_const_mem (V1TImode, src));
1875 : 35487 : use_move = MEM_P (dst);
1876 : : }
1877 : 35681 : rtx_insn *seq = get_insns ();
1878 : 35681 : end_sequence ();
1879 : 35681 : if (seq)
1880 : 195 : emit_insn_before (seq, insn);
1881 : 35681 : if (use_move)
1882 : : {
1883 : 35502 : tmp = gen_reg_rtx (V1TImode);
1884 : 35502 : emit_insn_before (gen_rtx_SET (tmp, src), insn);
1885 : 35502 : src = tmp;
1886 : : }
1887 : : }
1888 : : break;
1889 : :
1890 : 9923 : case CONST_INT:
1891 : 9923 : switch (standard_sse_constant_p (src, TImode))
1892 : : {
1893 : 9701 : case 1:
1894 : 9701 : src = CONST0_RTX (GET_MODE (dst));
1895 : 9701 : break;
1896 : 222 : case 2:
1897 : 222 : src = CONSTM1_RTX (GET_MODE (dst));
1898 : 222 : break;
1899 : 0 : default:
1900 : 0 : gcc_unreachable ();
1901 : : }
1902 : 9923 : if (MEM_P (dst))
1903 : : {
1904 : 9418 : tmp = gen_reg_rtx (V1TImode);
1905 : 9418 : emit_insn_before (gen_rtx_SET (tmp, src), insn);
1906 : 9418 : src = tmp;
1907 : : }
1908 : : break;
1909 : :
1910 : 8 : case AND:
1911 : 8 : if (GET_CODE (XEXP (src, 0)) == NOT)
1912 : : {
1913 : 0 : convert_op (&XEXP (XEXP (src, 0), 0), insn);
1914 : 0 : convert_op (&XEXP (src, 1), insn);
1915 : 0 : PUT_MODE (XEXP (src, 0), V1TImode);
1916 : 0 : PUT_MODE (src, V1TImode);
1917 : 0 : break;
1918 : : }
1919 : : /* FALLTHRU */
1920 : :
1921 : 11 : case XOR:
1922 : 11 : case IOR:
1923 : 11 : convert_op (&XEXP (src, 0), insn);
1924 : 11 : convert_op (&XEXP (src, 1), insn);
1925 : 11 : PUT_MODE (src, V1TImode);
1926 : 11 : if (MEM_P (dst))
1927 : : {
1928 : 5 : tmp = gen_reg_rtx (V1TImode);
1929 : 5 : emit_insn_before (gen_rtx_SET (tmp, src), insn);
1930 : 5 : src = tmp;
1931 : : }
1932 : : break;
1933 : :
1934 : 1 : case NOT:
1935 : 1 : src = XEXP (src, 0);
1936 : 1 : convert_op (&src, insn);
1937 : 1 : tmp = gen_reg_rtx (V1TImode);
1938 : 1 : emit_insn_before (gen_move_insn (tmp, CONSTM1_RTX (V1TImode)), insn);
1939 : 1 : src = gen_rtx_XOR (V1TImode, src, tmp);
1940 : 1 : if (MEM_P (dst))
1941 : : {
1942 : 0 : tmp = gen_reg_rtx (V1TImode);
1943 : 0 : emit_insn_before (gen_rtx_SET (tmp, src), insn);
1944 : 0 : src = tmp;
1945 : : }
1946 : : break;
1947 : :
1948 : 6 : case COMPARE:
1949 : 6 : dst = gen_rtx_REG (CCZmode, FLAGS_REG);
1950 : 6 : src = convert_compare (XEXP (src, 0), XEXP (src, 1), insn);
1951 : 6 : break;
1952 : :
1953 : 11 : case ASHIFT:
1954 : 11 : case LSHIFTRT:
1955 : 11 : case ASHIFTRT:
1956 : 11 : case ROTATERT:
1957 : 11 : case ROTATE:
1958 : 11 : convert_op (&XEXP (src, 0), insn);
1959 : 11 : PUT_MODE (src, V1TImode);
1960 : 11 : break;
1961 : :
1962 : 0 : default:
1963 : 0 : gcc_unreachable ();
1964 : : }
1965 : :
1966 : 866805 : SET_SRC (def_set) = src;
1967 : 866805 : SET_DEST (def_set) = dst;
1968 : :
1969 : : /* Drop possible dead definitions. */
1970 : 866805 : PATTERN (insn) = def_set;
1971 : :
1972 : 866805 : INSN_CODE (insn) = -1;
1973 : 866805 : recog_memoized (insn);
1974 : 866805 : df_insn_rescan (insn);
1975 : 866805 : }
1976 : :
1977 : : /* Generate copies from defs used by the chain but not defined therein.
1978 : : Also populates defs_map which is used later by convert_insn. */
1979 : :
1980 : : void
1981 : 612219 : scalar_chain::convert_registers ()
1982 : : {
1983 : 612219 : bitmap_iterator bi;
1984 : 612219 : unsigned id;
1985 : 639861 : EXECUTE_IF_SET_IN_BITMAP (defs_conv, 0, id, bi)
1986 : : {
1987 : 27642 : rtx chain_reg = gen_reg_rtx (smode);
1988 : 27642 : defs_map.put (regno_reg_rtx[id], chain_reg);
1989 : : }
1990 : 621336 : EXECUTE_IF_SET_IN_BITMAP (insns_conv, 0, id, bi)
1991 : 24317 : for (df_ref ref = DF_INSN_UID_DEFS (id); ref; ref = DF_REF_NEXT_LOC (ref))
1992 : 15200 : if (bitmap_bit_p (defs_conv, DF_REF_REGNO (ref)))
1993 : 9117 : make_vector_copies (DF_REF_INSN (ref), DF_REF_REAL_REG (ref));
1994 : 612219 : }
1995 : :
1996 : : /* Convert whole chain creating required register
1997 : : conversions and copies. */
1998 : :
1999 : : int
2000 : 612219 : scalar_chain::convert ()
2001 : : {
2002 : 612219 : bitmap_iterator bi;
2003 : 612219 : unsigned id;
2004 : 612219 : int converted_insns = 0;
2005 : :
2006 : 612219 : if (!dbg_cnt (stv_conversion))
2007 : : return 0;
2008 : :
2009 : 612219 : if (dump_file)
2010 : 0 : fprintf (dump_file, "Converting chain #%d...\n", chain_id);
2011 : :
2012 : 612219 : convert_registers ();
2013 : :
2014 : 1895612 : EXECUTE_IF_SET_IN_BITMAP (insns, 0, id, bi)
2015 : : {
2016 : 1283393 : rtx_insn *insn = DF_INSN_UID_GET (id)->insn;
2017 : 1283393 : convert_insn_common (insn);
2018 : 1283393 : convert_insn (insn);
2019 : 1283393 : converted_insns++;
2020 : : }
2021 : :
2022 : : return converted_insns;
2023 : : }
2024 : :
2025 : : /* Return the SET expression if INSN doesn't reference hard register.
2026 : : Return NULL if INSN uses or defines a hard register, excluding
2027 : : pseudo register pushes, hard register uses in a memory address,
2028 : : clobbers and flags definitions. */
2029 : :
2030 : : static rtx
2031 : 328160393 : pseudo_reg_set (rtx_insn *insn)
2032 : : {
2033 : 328160393 : rtx set = single_set (insn);
2034 : 328160393 : if (!set)
2035 : : return NULL;
2036 : :
2037 : : /* Check pseudo register push first. */
2038 : 133139851 : machine_mode mode = TARGET_64BIT ? TImode : DImode;
2039 : 133139851 : if (REG_P (SET_SRC (set))
2040 : 37524949 : && !HARD_REGISTER_P (SET_SRC (set))
2041 : 162203055 : && push_operand (SET_DEST (set), mode))
2042 : : return set;
2043 : :
2044 : 132889122 : df_ref ref;
2045 : 215650421 : FOR_EACH_INSN_DEF (ref, insn)
2046 : 119784984 : if (HARD_REGISTER_P (DF_REF_REAL_REG (ref))
2047 : 64291906 : && !DF_REF_FLAGS_IS_SET (ref, DF_REF_MUST_CLOBBER)
2048 : 169840533 : && DF_REF_REGNO (ref) != FLAGS_REG)
2049 : : return NULL;
2050 : :
2051 : 182404859 : FOR_EACH_INSN_USE (ref, insn)
2052 : 111612087 : if (!DF_REF_REG_MEM_P (ref) && HARD_REGISTER_P (DF_REF_REAL_REG (ref)))
2053 : : return NULL;
2054 : :
2055 : : return set;
2056 : : }
2057 : :
2058 : : /* Return true if the register REG is defined in a single DEF chain.
2059 : : If it is defined in more than one DEF chains, we may not be able
2060 : : to convert it in all chains. */
2061 : :
2062 : : static bool
2063 : 1122740 : single_def_chain_p (rtx reg)
2064 : : {
2065 : 1122740 : df_ref ref = DF_REG_DEF_CHAIN (REGNO (reg));
2066 : 1122740 : if (!ref)
2067 : : return false;
2068 : 1122725 : return DF_REF_NEXT_REG (ref) == nullptr;
2069 : : }
2070 : :
2071 : : /* Check if comparison INSN may be transformed into vector comparison.
2072 : : Currently we transform equality/inequality checks which look like:
2073 : : (set (reg:CCZ 17 flags) (compare:CCZ (reg:TI x) (reg:TI y))) */
2074 : :
2075 : : static bool
2076 : 12397042 : convertible_comparison_p (rtx_insn *insn, enum machine_mode mode)
2077 : : {
2078 : 12397042 : if (mode != (TARGET_64BIT ? TImode : DImode))
2079 : : return false;
2080 : :
2081 : 4538455 : if (!TARGET_SSE4_1)
2082 : : return false;
2083 : :
2084 : 154049 : rtx def_set = single_set (insn);
2085 : :
2086 : 154049 : gcc_assert (def_set);
2087 : :
2088 : 154049 : rtx src = SET_SRC (def_set);
2089 : 154049 : rtx dst = SET_DEST (def_set);
2090 : :
2091 : 154049 : gcc_assert (GET_CODE (src) == COMPARE);
2092 : :
2093 : 154049 : if (GET_CODE (dst) != REG
2094 : 154049 : || REGNO (dst) != FLAGS_REG
2095 : 308098 : || GET_MODE (dst) != CCZmode)
2096 : : return false;
2097 : :
2098 : 107392 : rtx op1 = XEXP (src, 0);
2099 : 107392 : rtx op2 = XEXP (src, 1);
2100 : :
2101 : : /* *cmp<dwi>_doubleword. */
2102 : 107392 : if ((CONST_SCALAR_INT_P (op1)
2103 : 107392 : || ((REG_P (op1) || MEM_P (op1))
2104 : 105027 : && GET_MODE (op1) == mode))
2105 : 49 : && (CONST_SCALAR_INT_P (op2)
2106 : 6 : || ((REG_P (op2) || MEM_P (op2))
2107 : 4 : && GET_MODE (op2) == mode)))
2108 : : return true;
2109 : :
2110 : : /* *testti_doubleword. */
2111 : 107345 : if (op2 == const0_rtx
2112 : 37844 : && GET_CODE (op1) == AND
2113 : 152 : && REG_P (XEXP (op1, 0)))
2114 : : {
2115 : 152 : rtx op12 = XEXP (op1, 1);
2116 : 152 : return GET_MODE (XEXP (op1, 0)) == TImode
2117 : 152 : && (CONST_SCALAR_INT_P (op12)
2118 : 0 : || ((REG_P (op12) || MEM_P (op12))
2119 : 0 : && GET_MODE (op12) == TImode));
2120 : : }
2121 : :
2122 : : /* *test<dwi>_not_doubleword. */
2123 : 107193 : if (op2 == const0_rtx
2124 : 37692 : && GET_CODE (op1) == AND
2125 : 0 : && GET_CODE (XEXP (op1, 0)) == NOT)
2126 : : {
2127 : 0 : rtx op11 = XEXP (XEXP (op1, 0), 0);
2128 : 0 : rtx op12 = XEXP (op1, 1);
2129 : 0 : return (REG_P (op11) || MEM_P (op11))
2130 : 0 : && (REG_P (op12) || MEM_P (op12))
2131 : 0 : && GET_MODE (op11) == mode
2132 : 0 : && GET_MODE (op12) == mode;
2133 : : }
2134 : :
2135 : : return false;
2136 : : }
2137 : :
2138 : : /* The general version of scalar_to_vector_candidate_p. */
2139 : :
2140 : : static bool
2141 : 229665528 : general_scalar_to_vector_candidate_p (rtx_insn *insn, enum machine_mode mode)
2142 : : {
2143 : 229665528 : rtx def_set = pseudo_reg_set (insn);
2144 : :
2145 : 229665528 : if (!def_set)
2146 : : return false;
2147 : :
2148 : 48084926 : rtx src = SET_SRC (def_set);
2149 : 48084926 : rtx dst = SET_DEST (def_set);
2150 : :
2151 : 48084926 : if (GET_CODE (src) == COMPARE)
2152 : 8548186 : return convertible_comparison_p (insn, mode);
2153 : :
2154 : : /* We are interested in "mode" only. */
2155 : 39536740 : if ((GET_MODE (src) != mode
2156 : 26928303 : && !CONST_INT_P (src))
2157 : 17694483 : || GET_MODE (dst) != mode)
2158 : : return false;
2159 : :
2160 : 14829778 : if (!REG_P (dst) && !MEM_P (dst))
2161 : : return false;
2162 : :
2163 : 14587388 : switch (GET_CODE (src))
2164 : : {
2165 : 499532 : case ASHIFT:
2166 : 499532 : case LSHIFTRT:
2167 : 499532 : case ASHIFTRT:
2168 : 499532 : case ROTATE:
2169 : 499532 : case ROTATERT:
2170 : 499532 : if (!CONST_INT_P (XEXP (src, 1))
2171 : 964044 : || !IN_RANGE (INTVAL (XEXP (src, 1)), 0, GET_MODE_BITSIZE (mode)-1))
2172 : : return false;
2173 : :
2174 : : /* Check for extend highpart case. */
2175 : 464508 : if (mode != DImode
2176 : 339858 : || GET_CODE (src) != ASHIFTRT
2177 : 78231 : || GET_CODE (XEXP (src, 0)) != ASHIFT)
2178 : : break;
2179 : :
2180 : 3576620 : src = XEXP (src, 0);
2181 : : break;
2182 : :
2183 : 67133 : case SMAX:
2184 : 67133 : case SMIN:
2185 : 67133 : case UMAX:
2186 : 67133 : case UMIN:
2187 : 67133 : if ((mode == DImode && !TARGET_AVX512VL)
2188 : 17379 : || (mode == SImode && !TARGET_SSE4_1))
2189 : : return false;
2190 : : /* Fallthru. */
2191 : :
2192 : 3165229 : case AND:
2193 : 3165229 : case IOR:
2194 : 3165229 : case XOR:
2195 : 3165229 : case PLUS:
2196 : 3165229 : case MINUS:
2197 : 3165229 : if (!REG_P (XEXP (src, 1))
2198 : : && !MEM_P (XEXP (src, 1))
2199 : : && !CONST_INT_P (XEXP (src, 1)))
2200 : : return false;
2201 : :
2202 : 3060186 : if (GET_MODE (XEXP (src, 1)) != mode
2203 : 1788604 : && !CONST_INT_P (XEXP (src, 1)))
2204 : : return false;
2205 : :
2206 : : /* Check for andnot case. */
2207 : 3060186 : if (GET_CODE (src) != AND
2208 : 201326 : || GET_CODE (XEXP (src, 0)) != NOT)
2209 : : break;
2210 : :
2211 : 3576620 : src = XEXP (src, 0);
2212 : : /* FALLTHRU */
2213 : :
2214 : : case NOT:
2215 : : break;
2216 : :
2217 : 25592 : case NEG:
2218 : : /* Check for nabs case. */
2219 : 25592 : if (GET_CODE (XEXP (src, 0)) != ABS)
2220 : : break;
2221 : :
2222 : : src = XEXP (src, 0);
2223 : : /* FALLTHRU */
2224 : :
2225 : 2897 : case ABS:
2226 : 2897 : if ((mode == DImode && !TARGET_AVX512VL)
2227 : 1119 : || (mode == SImode && !TARGET_SSSE3))
2228 : : return false;
2229 : : break;
2230 : :
2231 : : case REG:
2232 : : return true;
2233 : :
2234 : 6023023 : case MEM:
2235 : 6023023 : case CONST_INT:
2236 : 6023023 : return REG_P (dst);
2237 : :
2238 : 54197 : case VEC_SELECT:
2239 : : /* Excluding MEM_P (dst) avoids intefering with vpextr[dq]. */
2240 : 54197 : return REG_P (dst)
2241 : 43676 : && REG_P (XEXP (src, 0))
2242 : 50571 : && GET_MODE (XEXP (src, 0)) == (mode == DImode ? V2DImode
2243 : : : V4SImode)
2244 : 34517 : && GET_CODE (XEXP (src, 1)) == PARALLEL
2245 : 34517 : && XVECLEN (XEXP (src, 1), 0) == 1
2246 : 88714 : && CONST_INT_P (XVECEXP (XEXP (src, 1), 0, 0));
2247 : :
2248 : : default:
2249 : : return false;
2250 : : }
2251 : :
2252 : 3576620 : if (!REG_P (XEXP (src, 0))
2253 : : && !MEM_P (XEXP (src, 0))
2254 : : && !CONST_INT_P (XEXP (src, 0)))
2255 : : return false;
2256 : :
2257 : 3292358 : if (GET_MODE (XEXP (src, 0)) != mode
2258 : 0 : && !CONST_INT_P (XEXP (src, 0)))
2259 : : return false;
2260 : :
2261 : : return true;
2262 : : }
2263 : :
2264 : : /* Check for a suitable TImode memory operand. */
2265 : :
2266 : : static bool
2267 : 12855 : timode_mem_p (rtx x)
2268 : : {
2269 : 12855 : return MEM_P (x)
2270 : 12855 : && (TARGET_SSE_UNALIGNED_LOAD_OPTIMAL
2271 : 0 : || !misaligned_operand (x, TImode));
2272 : : }
2273 : :
2274 : : /* The TImode version of scalar_to_vector_candidate_p. */
2275 : :
2276 : : static bool
2277 : 98494865 : timode_scalar_to_vector_candidate_p (rtx_insn *insn)
2278 : : {
2279 : 98494865 : rtx def_set = pseudo_reg_set (insn);
2280 : :
2281 : 98494865 : if (!def_set)
2282 : : return false;
2283 : :
2284 : 22958575 : rtx src = SET_SRC (def_set);
2285 : 22958575 : rtx dst = SET_DEST (def_set);
2286 : :
2287 : 22958575 : if (GET_CODE (src) == COMPARE)
2288 : 3848856 : return convertible_comparison_p (insn, TImode);
2289 : :
2290 : 19109719 : if (GET_MODE (dst) != TImode
2291 : 1170442 : || (GET_MODE (src) != TImode
2292 : 62070 : && !CONST_SCALAR_INT_P (src)))
2293 : : return false;
2294 : :
2295 : 1170442 : if (!REG_P (dst) && !MEM_P (dst))
2296 : : return false;
2297 : :
2298 : 1168994 : if (MEM_P (dst)
2299 : 508788 : && misaligned_operand (dst, TImode)
2300 : 1451755 : && !TARGET_SSE_UNALIGNED_STORE_OPTIMAL)
2301 : : return false;
2302 : :
2303 : 1168989 : if (REG_P (dst) && !single_def_chain_p (dst))
2304 : : return false;
2305 : :
2306 : 991989 : switch (GET_CODE (src))
2307 : : {
2308 : 462534 : case REG:
2309 : 462534 : return single_def_chain_p (src);
2310 : :
2311 : : case CONST_WIDE_INT:
2312 : : return true;
2313 : :
2314 : 11563 : case CONST_INT:
2315 : : /* ??? Verify performance impact before enabling CONST_INT for
2316 : : __int128 store. */
2317 : 11563 : return standard_sse_constant_p (src, TImode);
2318 : :
2319 : 415462 : case MEM:
2320 : : /* Memory must be aligned or unaligned load is optimal. */
2321 : 415462 : return (REG_P (dst)
2322 : 415462 : && (!misaligned_operand (src, TImode)
2323 : 102834 : || TARGET_SSE_UNALIGNED_LOAD_OPTIMAL));
2324 : :
2325 : 4180 : case AND:
2326 : 4180 : if (!MEM_P (dst)
2327 : 4144 : && GET_CODE (XEXP (src, 0)) == NOT
2328 : 0 : && REG_P (XEXP (XEXP (src, 0), 0))
2329 : 4180 : && (REG_P (XEXP (src, 1))
2330 : 0 : || CONST_SCALAR_INT_P (XEXP (src, 1))
2331 : 0 : || timode_mem_p (XEXP (src, 1))))
2332 : 0 : return true;
2333 : 4180 : return (REG_P (XEXP (src, 0))
2334 : 41 : || timode_mem_p (XEXP (src, 0)))
2335 : 4221 : && (REG_P (XEXP (src, 1))
2336 : 2351 : || CONST_SCALAR_INT_P (XEXP (src, 1))
2337 : 35 : || timode_mem_p (XEXP (src, 1)));
2338 : :
2339 : 13987 : case IOR:
2340 : 13987 : case XOR:
2341 : 13987 : return (REG_P (XEXP (src, 0))
2342 : 12719 : || timode_mem_p (XEXP (src, 0)))
2343 : 13995 : && (REG_P (XEXP (src, 1))
2344 : 280 : || CONST_SCALAR_INT_P (XEXP (src, 1))
2345 : 44 : || timode_mem_p (XEXP (src, 1)));
2346 : :
2347 : 361 : case NOT:
2348 : 361 : return REG_P (XEXP (src, 0)) || timode_mem_p (XEXP (src, 0));
2349 : :
2350 : 12613 : case ASHIFT:
2351 : 12613 : case LSHIFTRT:
2352 : 12613 : case ASHIFTRT:
2353 : 12613 : case ROTATERT:
2354 : 12613 : case ROTATE:
2355 : : /* Handle shifts/rotates by integer constants between 0 and 127. */
2356 : 12613 : return REG_P (XEXP (src, 0))
2357 : 12577 : && CONST_INT_P (XEXP (src, 1))
2358 : 24846 : && (INTVAL (XEXP (src, 1)) & ~0x7f) == 0;
2359 : :
2360 : : default:
2361 : : return false;
2362 : : }
2363 : : }
2364 : :
2365 : : /* For a register REGNO, scan instructions for its defs and uses.
2366 : : Put REGNO in REGS if a def or use isn't in CANDIDATES. */
2367 : :
2368 : : static void
2369 : 1207729 : timode_check_non_convertible_regs (bitmap candidates, bitmap regs,
2370 : : unsigned int regno)
2371 : : {
2372 : : /* Do nothing if REGNO is already in REGS or is a hard reg. */
2373 : 1207729 : if (bitmap_bit_p (regs, regno)
2374 : 1207729 : || HARD_REGISTER_NUM_P (regno))
2375 : : return;
2376 : :
2377 : 1195590 : for (df_ref def = DF_REG_DEF_CHAIN (regno);
2378 : 2360253 : def;
2379 : 1164663 : def = DF_REF_NEXT_REG (def))
2380 : : {
2381 : 1195570 : if (!bitmap_bit_p (candidates, DF_REF_INSN_UID (def)))
2382 : : {
2383 : 30907 : if (dump_file)
2384 : 0 : fprintf (dump_file,
2385 : : "r%d has non convertible def in insn %d\n",
2386 : 0 : regno, DF_REF_INSN_UID (def));
2387 : :
2388 : 30907 : bitmap_set_bit (regs, regno);
2389 : 30907 : break;
2390 : : }
2391 : : }
2392 : :
2393 : 1195590 : for (df_ref ref = DF_REG_USE_CHAIN (regno);
2394 : 2678408 : ref;
2395 : 1482818 : ref = DF_REF_NEXT_REG (ref))
2396 : : {
2397 : : /* Debug instructions are skipped. */
2398 : 1536248 : if (NONDEBUG_INSN_P (DF_REF_INSN (ref))
2399 : 1536248 : && !bitmap_bit_p (candidates, DF_REF_INSN_UID (ref)))
2400 : : {
2401 : 53430 : if (dump_file)
2402 : 0 : fprintf (dump_file,
2403 : : "r%d has non convertible use in insn %d\n",
2404 : 0 : regno, DF_REF_INSN_UID (ref));
2405 : :
2406 : 53430 : bitmap_set_bit (regs, regno);
2407 : 53430 : break;
2408 : : }
2409 : : }
2410 : : }
2411 : :
2412 : : /* For a given bitmap of insn UIDs scans all instructions and
2413 : : remove insn from CANDIDATES in case it has both convertible
2414 : : and not convertible definitions.
2415 : :
2416 : : All insns in a bitmap are conversion candidates according to
2417 : : scalar_to_vector_candidate_p. Currently it implies all insns
2418 : : are single_set. */
2419 : :
2420 : : static void
2421 : 815811 : timode_remove_non_convertible_regs (bitmap candidates)
2422 : : {
2423 : 815811 : bitmap_iterator bi;
2424 : 815811 : unsigned id;
2425 : 815811 : bitmap regs = BITMAP_ALLOC (NULL);
2426 : 839121 : bool changed;
2427 : :
2428 : 839121 : do {
2429 : 839121 : changed = false;
2430 : 2077144 : EXECUTE_IF_SET_IN_BITMAP (candidates, 0, id, bi)
2431 : : {
2432 : 1238023 : rtx_insn *insn = DF_INSN_UID_GET (id)->insn;
2433 : 1238023 : df_ref ref;
2434 : :
2435 : 1845259 : FOR_EACH_INSN_DEF (ref, insn)
2436 : 607236 : if (!DF_REF_REG_MEM_P (ref)
2437 : 607236 : && GET_MODE (DF_REF_REG (ref)) == TImode)
2438 : 584676 : timode_check_non_convertible_regs (candidates, regs,
2439 : : DF_REF_REGNO (ref));
2440 : :
2441 : 3021320 : FOR_EACH_INSN_USE (ref, insn)
2442 : 1783297 : if (!DF_REF_REG_MEM_P (ref)
2443 : 623053 : && GET_MODE (DF_REF_REG (ref)) == TImode)
2444 : 623053 : timode_check_non_convertible_regs (candidates, regs,
2445 : : DF_REF_REGNO (ref));
2446 : : }
2447 : :
2448 : 1007733 : EXECUTE_IF_SET_IN_BITMAP (regs, 0, id, bi)
2449 : : {
2450 : 168612 : for (df_ref def = DF_REG_DEF_CHAIN (id);
2451 : 343418 : def;
2452 : 174806 : def = DF_REF_NEXT_REG (def))
2453 : 174806 : if (bitmap_bit_p (candidates, DF_REF_INSN_UID (def)))
2454 : : {
2455 : 35522 : if (dump_file)
2456 : 0 : fprintf (dump_file, "Removing insn %d from candidates list\n",
2457 : 0 : DF_REF_INSN_UID (def));
2458 : :
2459 : 35522 : bitmap_clear_bit (candidates, DF_REF_INSN_UID (def));
2460 : 35522 : changed = true;
2461 : : }
2462 : :
2463 : 168612 : for (df_ref ref = DF_REG_USE_CHAIN (id);
2464 : 452378 : ref;
2465 : 283766 : ref = DF_REF_NEXT_REG (ref))
2466 : 283766 : if (bitmap_bit_p (candidates, DF_REF_INSN_UID (ref)))
2467 : : {
2468 : 40937 : if (dump_file)
2469 : 0 : fprintf (dump_file, "Removing insn %d from candidates list\n",
2470 : 0 : DF_REF_INSN_UID (ref));
2471 : :
2472 : 40937 : bitmap_clear_bit (candidates, DF_REF_INSN_UID (ref));
2473 : 40937 : changed = true;
2474 : : }
2475 : : }
2476 : : } while (changed);
2477 : :
2478 : 815811 : BITMAP_FREE (regs);
2479 : 815811 : }
2480 : :
2481 : : /* Main STV pass function. Find and convert scalar
2482 : : instructions into vector mode when profitable. */
2483 : :
2484 : : static unsigned int
2485 : 1756645 : convert_scalars_to_vector (bool timode_p)
2486 : : {
2487 : 1756645 : basic_block bb;
2488 : 1756645 : int converted_insns = 0;
2489 : 1756645 : auto_vec<rtx_insn *> control_flow_insns;
2490 : :
2491 : 1756645 : bitmap_obstack_initialize (NULL);
2492 : 1756645 : const machine_mode cand_mode[3] = { SImode, DImode, TImode };
2493 : 1756645 : const machine_mode cand_vmode[3] = { V4SImode, V2DImode, V1TImode };
2494 : 5269935 : bitmap_head candidates[3]; /* { SImode, DImode, TImode } */
2495 : 7026580 : for (unsigned i = 0; i < 3; ++i)
2496 : 5269935 : bitmap_initialize (&candidates[i], &bitmap_default_obstack);
2497 : :
2498 : 1756645 : calculate_dominance_info (CDI_DOMINATORS);
2499 : 1756645 : df_set_flags (DF_DEFER_INSN_RESCAN | DF_RD_PRUNE_DEAD_DEFS);
2500 : 1756645 : df_chain_add_problem (DF_DU_CHAIN | DF_UD_CHAIN);
2501 : 1756645 : df_analyze ();
2502 : :
2503 : : /* Find all instructions we want to convert into vector mode. */
2504 : 1756645 : if (dump_file)
2505 : 44 : fprintf (dump_file, "Searching for mode conversion candidates...\n");
2506 : :
2507 : 19381196 : FOR_EACH_BB_FN (bb, cfun)
2508 : : {
2509 : 17624551 : rtx_insn *insn;
2510 : 232673416 : FOR_BB_INSNS (bb, insn)
2511 : 215048865 : if (timode_p
2512 : 215048865 : && timode_scalar_to_vector_candidate_p (insn))
2513 : : {
2514 : 943596 : if (dump_file)
2515 : 0 : fprintf (dump_file, " insn %d is marked as a TImode candidate\n",
2516 : 0 : INSN_UID (insn));
2517 : :
2518 : 943596 : bitmap_set_bit (&candidates[2], INSN_UID (insn));
2519 : : }
2520 : 214105269 : else if (!timode_p)
2521 : : {
2522 : : /* Check {SI,DI}mode. */
2523 : 334723718 : for (unsigned i = 0; i <= 1; ++i)
2524 : 229665528 : if (general_scalar_to_vector_candidate_p (insn, cand_mode[i]))
2525 : : {
2526 : 11495810 : if (dump_file)
2527 : 558 : fprintf (dump_file, " insn %d is marked as a %s candidate\n",
2528 : 279 : INSN_UID (insn), i == 0 ? "SImode" : "DImode");
2529 : :
2530 : 11495810 : bitmap_set_bit (&candidates[i], INSN_UID (insn));
2531 : 11495810 : break;
2532 : : }
2533 : : }
2534 : : }
2535 : :
2536 : 1756645 : if (timode_p)
2537 : 815811 : timode_remove_non_convertible_regs (&candidates[2]);
2538 : :
2539 : 5553874 : for (unsigned i = 0; i <= 2; ++i)
2540 : 4423697 : if (!bitmap_empty_p (&candidates[i]))
2541 : : break;
2542 : 3797229 : else if (i == 2 && dump_file)
2543 : 23 : fprintf (dump_file, "There are no candidates for optimization.\n");
2544 : :
2545 : 7026580 : for (unsigned i = 0; i <= 2; ++i)
2546 : : {
2547 : 5269935 : auto_bitmap disallowed;
2548 : 5269935 : bitmap_tree_view (&candidates[i]);
2549 : 16912786 : while (!bitmap_empty_p (&candidates[i]))
2550 : : {
2551 : 6372916 : unsigned uid = bitmap_first_set_bit (&candidates[i]);
2552 : 6372916 : scalar_chain *chain;
2553 : :
2554 : 6372916 : if (cand_mode[i] == TImode)
2555 : 440242 : chain = new timode_scalar_chain;
2556 : : else
2557 : 5932674 : chain = new general_scalar_chain (cand_mode[i], cand_vmode[i]);
2558 : :
2559 : : /* Find instructions chain we want to convert to vector mode.
2560 : : Check all uses and definitions to estimate all required
2561 : : conversions. */
2562 : 6372916 : if (chain->build (&candidates[i], uid, disallowed))
2563 : : {
2564 : 6372381 : if (chain->compute_convert_gain () > 0)
2565 : 612219 : converted_insns += chain->convert ();
2566 : 5760162 : else if (dump_file)
2567 : 138 : fprintf (dump_file, "Chain #%d conversion is not profitable\n",
2568 : : chain->chain_id);
2569 : : }
2570 : :
2571 : 6372916 : rtx_insn* iter_insn;
2572 : 6372916 : unsigned int ii;
2573 : 6376508 : FOR_EACH_VEC_ELT (chain->control_flow_insns, ii, iter_insn)
2574 : 3592 : control_flow_insns.safe_push (iter_insn);
2575 : :
2576 : 6372916 : delete chain;
2577 : : }
2578 : 5269935 : }
2579 : :
2580 : 1756645 : if (dump_file)
2581 : 44 : fprintf (dump_file, "Total insns converted: %d\n", converted_insns);
2582 : :
2583 : 7026580 : for (unsigned i = 0; i <= 2; ++i)
2584 : 5269935 : bitmap_release (&candidates[i]);
2585 : 1756645 : bitmap_obstack_release (NULL);
2586 : 1756645 : df_process_deferred_rescans ();
2587 : :
2588 : : /* Conversion means we may have 128bit register spills/fills
2589 : : which require aligned stack. */
2590 : 1756645 : if (converted_insns)
2591 : : {
2592 : 103059 : if (crtl->stack_alignment_needed < 128)
2593 : 2070 : crtl->stack_alignment_needed = 128;
2594 : 103059 : if (crtl->stack_alignment_estimated < 128)
2595 : 201 : crtl->stack_alignment_estimated = 128;
2596 : :
2597 : 103059 : crtl->stack_realign_needed
2598 : 103059 : = INCOMING_STACK_BOUNDARY < crtl->stack_alignment_estimated;
2599 : 103059 : crtl->stack_realign_tried = crtl->stack_realign_needed;
2600 : :
2601 : 103059 : crtl->stack_realign_processed = true;
2602 : :
2603 : 103059 : if (!crtl->drap_reg)
2604 : : {
2605 : 102899 : rtx drap_rtx = targetm.calls.get_drap_rtx ();
2606 : :
2607 : : /* stack_realign_drap and drap_rtx must match. */
2608 : 102899 : gcc_assert ((stack_realign_drap != 0) == (drap_rtx != NULL));
2609 : :
2610 : : /* Do nothing if NULL is returned,
2611 : : which means DRAP is not needed. */
2612 : 102899 : if (drap_rtx != NULL)
2613 : : {
2614 : 0 : crtl->args.internal_arg_pointer = drap_rtx;
2615 : :
2616 : : /* Call fixup_tail_calls to clean up
2617 : : REG_EQUIV note if DRAP is needed. */
2618 : 0 : fixup_tail_calls ();
2619 : : }
2620 : : }
2621 : :
2622 : : /* Fix up DECL_RTL/DECL_INCOMING_RTL of arguments. */
2623 : 103059 : if (TARGET_64BIT)
2624 : 65466 : for (tree parm = DECL_ARGUMENTS (current_function_decl);
2625 : 180355 : parm; parm = DECL_CHAIN (parm))
2626 : : {
2627 : 114889 : if (TYPE_MODE (TREE_TYPE (parm)) != TImode)
2628 : 98566 : continue;
2629 : 16323 : if (DECL_RTL_SET_P (parm)
2630 : 32646 : && GET_MODE (DECL_RTL (parm)) == V1TImode)
2631 : : {
2632 : 414 : rtx r = DECL_RTL (parm);
2633 : 414 : if (REG_P (r))
2634 : 414 : SET_DECL_RTL (parm, gen_rtx_SUBREG (TImode, r, 0));
2635 : : }
2636 : 16323 : if (DECL_INCOMING_RTL (parm)
2637 : 16323 : && GET_MODE (DECL_INCOMING_RTL (parm)) == V1TImode)
2638 : : {
2639 : 0 : rtx r = DECL_INCOMING_RTL (parm);
2640 : 0 : if (REG_P (r))
2641 : 0 : DECL_INCOMING_RTL (parm) = gen_rtx_SUBREG (TImode, r, 0);
2642 : : }
2643 : : }
2644 : :
2645 : 103059 : if (!control_flow_insns.is_empty ())
2646 : : {
2647 : 1130 : free_dominance_info (CDI_DOMINATORS);
2648 : :
2649 : 1130 : unsigned int i;
2650 : 1130 : rtx_insn* insn;
2651 : 5852 : FOR_EACH_VEC_ELT (control_flow_insns, i, insn)
2652 : 3592 : if (control_flow_insn_p (insn))
2653 : : {
2654 : : /* Split the block after insn. There will be a fallthru
2655 : : edge, which is OK so we keep it. We have to create
2656 : : the exception edges ourselves. */
2657 : 3592 : bb = BLOCK_FOR_INSN (insn);
2658 : 3592 : split_block (bb, insn);
2659 : 3592 : rtl_make_eh_edge (NULL, bb, BB_END (bb));
2660 : : }
2661 : : }
2662 : : }
2663 : :
2664 : 1756645 : return 0;
2665 : 1756645 : }
2666 : :
2667 : : static unsigned int
2668 : 72254 : rest_of_handle_insert_vzeroupper (void)
2669 : : {
2670 : : /* vzeroupper instructions are inserted immediately after reload and
2671 : : postreload_cse to clean up after it a little bit to account for possible
2672 : : spills from 256bit or 512bit registers. The pass reuses mode switching
2673 : : infrastructure by re-running mode insertion pass, so disable entities
2674 : : that have already been processed. */
2675 : 505778 : for (int i = 0; i < MAX_386_ENTITIES; i++)
2676 : 433524 : ix86_optimize_mode_switching[i] = 0;
2677 : :
2678 : 72254 : ix86_optimize_mode_switching[AVX_U128] = 1;
2679 : :
2680 : : /* Call optimize_mode_switching. */
2681 : 72254 : g->get_passes ()->execute_pass_mode_switching ();
2682 : :
2683 : : /* LRA removes all REG_DEAD/REG_UNUSED notes and normally they
2684 : : reappear in the IL only at the start of pass_rtl_dse2, which does
2685 : : df_note_add_problem (); df_analyze ();
2686 : : The vzeroupper is scheduled after postreload_cse pass and mode
2687 : : switching computes the notes as well, the problem is that e.g.
2688 : : pass_gcse2 doesn't maintain the notes, see PR113059 and
2689 : : PR112760. Remove the notes now to restore status quo ante
2690 : : until we figure out how to maintain the notes or what else
2691 : : to do. */
2692 : 72254 : basic_block bb;
2693 : 72254 : rtx_insn *insn;
2694 : 386967 : FOR_EACH_BB_FN (bb, cfun)
2695 : 4122678 : FOR_BB_INSNS (bb, insn)
2696 : 3807965 : if (NONDEBUG_INSN_P (insn))
2697 : : {
2698 : 2000884 : rtx *pnote = ®_NOTES (insn);
2699 : 3704835 : while (*pnote != 0)
2700 : : {
2701 : 1703951 : if (REG_NOTE_KIND (*pnote) == REG_DEAD
2702 : 779575 : || REG_NOTE_KIND (*pnote) == REG_UNUSED)
2703 : 1226117 : *pnote = XEXP (*pnote, 1);
2704 : : else
2705 : 477834 : pnote = &XEXP (*pnote, 1);
2706 : : }
2707 : : }
2708 : :
2709 : 72254 : df_remove_problem (df_note);
2710 : 72254 : df_analyze ();
2711 : 72254 : return 0;
2712 : : }
2713 : :
2714 : : namespace {
2715 : :
2716 : : const pass_data pass_data_insert_vzeroupper =
2717 : : {
2718 : : RTL_PASS, /* type */
2719 : : "vzeroupper", /* name */
2720 : : OPTGROUP_NONE, /* optinfo_flags */
2721 : : TV_MACH_DEP, /* tv_id */
2722 : : 0, /* properties_required */
2723 : : 0, /* properties_provided */
2724 : : 0, /* properties_destroyed */
2725 : : 0, /* todo_flags_start */
2726 : : TODO_df_finish, /* todo_flags_finish */
2727 : : };
2728 : :
2729 : : class pass_insert_vzeroupper : public rtl_opt_pass
2730 : : {
2731 : : public:
2732 : 277917 : pass_insert_vzeroupper(gcc::context *ctxt)
2733 : 555834 : : rtl_opt_pass(pass_data_insert_vzeroupper, ctxt)
2734 : : {}
2735 : :
2736 : : /* opt_pass methods: */
2737 : 1443154 : bool gate (function *) final override
2738 : : {
2739 : 1443154 : return TARGET_AVX && TARGET_VZEROUPPER;
2740 : : }
2741 : :
2742 : 72254 : unsigned int execute (function *) final override
2743 : : {
2744 : 72254 : return rest_of_handle_insert_vzeroupper ();
2745 : : }
2746 : :
2747 : : }; // class pass_insert_vzeroupper
2748 : :
2749 : : const pass_data pass_data_stv =
2750 : : {
2751 : : RTL_PASS, /* type */
2752 : : "stv", /* name */
2753 : : OPTGROUP_NONE, /* optinfo_flags */
2754 : : TV_MACH_DEP, /* tv_id */
2755 : : 0, /* properties_required */
2756 : : 0, /* properties_provided */
2757 : : 0, /* properties_destroyed */
2758 : : 0, /* todo_flags_start */
2759 : : TODO_df_finish, /* todo_flags_finish */
2760 : : };
2761 : :
2762 : : class pass_stv : public rtl_opt_pass
2763 : : {
2764 : : public:
2765 : 555834 : pass_stv (gcc::context *ctxt)
2766 : 555834 : : rtl_opt_pass (pass_data_stv, ctxt),
2767 : 1111668 : timode_p (false)
2768 : : {}
2769 : :
2770 : : /* opt_pass methods: */
2771 : 2886308 : bool gate (function *) final override
2772 : : {
2773 : 1443154 : return ((!timode_p || TARGET_64BIT)
2774 : 4204133 : && TARGET_STV && TARGET_SSE2 && optimize > 1);
2775 : : }
2776 : :
2777 : 1756645 : unsigned int execute (function *) final override
2778 : : {
2779 : 1756645 : return convert_scalars_to_vector (timode_p);
2780 : : }
2781 : :
2782 : 277917 : opt_pass *clone () final override
2783 : : {
2784 : 277917 : return new pass_stv (m_ctxt);
2785 : : }
2786 : :
2787 : 555834 : void set_pass_param (unsigned int n, bool param) final override
2788 : : {
2789 : 555834 : gcc_assert (n == 0);
2790 : 555834 : timode_p = param;
2791 : 555834 : }
2792 : :
2793 : : private:
2794 : : bool timode_p;
2795 : : }; // class pass_stv
2796 : :
2797 : : } // anon namespace
2798 : :
2799 : : rtl_opt_pass *
2800 : 277917 : make_pass_insert_vzeroupper (gcc::context *ctxt)
2801 : : {
2802 : 277917 : return new pass_insert_vzeroupper (ctxt);
2803 : : }
2804 : :
2805 : : rtl_opt_pass *
2806 : 277917 : make_pass_stv (gcc::context *ctxt)
2807 : : {
2808 : 277917 : return new pass_stv (ctxt);
2809 : : }
2810 : :
2811 : : /* Inserting ENDBR and pseudo patchable-area instructions. */
2812 : :
2813 : : static void
2814 : 200604 : rest_of_insert_endbr_and_patchable_area (bool need_endbr,
2815 : : unsigned int patchable_area_size)
2816 : : {
2817 : 200604 : rtx endbr;
2818 : 200604 : rtx_insn *insn;
2819 : 200604 : rtx_insn *endbr_insn = NULL;
2820 : 200604 : basic_block bb;
2821 : :
2822 : 200604 : if (need_endbr)
2823 : : {
2824 : : /* Currently emit EB if it's a tracking function, i.e. 'nocf_check'
2825 : : is absent among function attributes. Later an optimization will
2826 : : be introduced to make analysis if an address of a static function
2827 : : is taken. A static function whose address is not taken will get
2828 : : a nocf_check attribute. This will allow to reduce the number of
2829 : : EB. */
2830 : 200559 : if (!lookup_attribute ("nocf_check",
2831 : 200559 : TYPE_ATTRIBUTES (TREE_TYPE (cfun->decl)))
2832 : 200549 : && (!flag_manual_endbr
2833 : 8 : || lookup_attribute ("cf_check",
2834 : 8 : DECL_ATTRIBUTES (cfun->decl)))
2835 : 401107 : && (!cgraph_node::get (cfun->decl)->only_called_directly_p ()
2836 : 26311 : || ix86_cmodel == CM_LARGE
2837 : 26310 : || ix86_cmodel == CM_LARGE_PIC
2838 : 26309 : || flag_force_indirect_call
2839 : 26309 : || (TARGET_DLLIMPORT_DECL_ATTRIBUTES
2840 : : && DECL_DLLIMPORT_P (cfun->decl))))
2841 : : {
2842 : 174240 : if (crtl->profile && flag_fentry)
2843 : : {
2844 : : /* Queue ENDBR insertion to x86_function_profiler.
2845 : : NB: Any patchable-area insn will be inserted after
2846 : : ENDBR. */
2847 : 4 : cfun->machine->insn_queued_at_entrance = TYPE_ENDBR;
2848 : : }
2849 : : else
2850 : : {
2851 : 174236 : endbr = gen_nop_endbr ();
2852 : 174236 : bb = ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb;
2853 : 174236 : rtx_insn *insn = BB_HEAD (bb);
2854 : 174236 : endbr_insn = emit_insn_before (endbr, insn);
2855 : : }
2856 : : }
2857 : : }
2858 : :
2859 : 200604 : if (patchable_area_size)
2860 : : {
2861 : 51 : if (crtl->profile && flag_fentry)
2862 : : {
2863 : : /* Queue patchable-area insertion to x86_function_profiler.
2864 : : NB: If there is a queued ENDBR, x86_function_profiler
2865 : : will also handle patchable-area. */
2866 : 2 : if (!cfun->machine->insn_queued_at_entrance)
2867 : 1 : cfun->machine->insn_queued_at_entrance = TYPE_PATCHABLE_AREA;
2868 : : }
2869 : : else
2870 : : {
2871 : 49 : rtx patchable_area
2872 : 49 : = gen_patchable_area (GEN_INT (patchable_area_size),
2873 : 49 : GEN_INT (crtl->patch_area_entry == 0));
2874 : 49 : if (endbr_insn)
2875 : 3 : emit_insn_after (patchable_area, endbr_insn);
2876 : : else
2877 : : {
2878 : 46 : bb = ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb;
2879 : 46 : insn = BB_HEAD (bb);
2880 : 46 : emit_insn_before (patchable_area, insn);
2881 : : }
2882 : : }
2883 : : }
2884 : :
2885 : 200604 : if (!need_endbr)
2886 : : return;
2887 : :
2888 : 200559 : bb = 0;
2889 : 4055687 : FOR_EACH_BB_FN (bb, cfun)
2890 : : {
2891 : 71819552 : for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
2892 : 67964424 : insn = NEXT_INSN (insn))
2893 : : {
2894 : 67964424 : if (CALL_P (insn))
2895 : : {
2896 : 1418712 : need_endbr = find_reg_note (insn, REG_SETJMP, NULL) != NULL;
2897 : 1418712 : if (!need_endbr && !SIBLING_CALL_P (insn))
2898 : : {
2899 : 1369479 : rtx call = get_call_rtx_from (insn);
2900 : 1369479 : rtx fnaddr = XEXP (call, 0);
2901 : 1369479 : tree fndecl = NULL_TREE;
2902 : :
2903 : : /* Also generate ENDBRANCH for non-tail call which
2904 : : may return via indirect branch. */
2905 : 1369479 : if (GET_CODE (XEXP (fnaddr, 0)) == SYMBOL_REF)
2906 : 1307629 : fndecl = SYMBOL_REF_DECL (XEXP (fnaddr, 0));
2907 : 1307629 : if (fndecl == NULL_TREE)
2908 : 62882 : fndecl = MEM_EXPR (fnaddr);
2909 : 62882 : if (fndecl
2910 : 1366013 : && TREE_CODE (TREE_TYPE (fndecl)) != FUNCTION_TYPE
2911 : 638264 : && TREE_CODE (TREE_TYPE (fndecl)) != METHOD_TYPE)
2912 : : fndecl = NULL_TREE;
2913 : 1369479 : if (fndecl && TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
2914 : : {
2915 : 1325792 : tree fntype = TREE_TYPE (fndecl);
2916 : 1325792 : if (lookup_attribute ("indirect_return",
2917 : 1325792 : TYPE_ATTRIBUTES (fntype)))
2918 : : need_endbr = true;
2919 : : }
2920 : : }
2921 : 1418700 : if (!need_endbr)
2922 : 1418694 : continue;
2923 : : /* Generate ENDBRANCH after CALL, which can return more than
2924 : : twice, setjmp-like functions. */
2925 : :
2926 : 18 : endbr = gen_nop_endbr ();
2927 : 18 : emit_insn_after_setloc (endbr, insn, INSN_LOCATION (insn));
2928 : 18 : continue;
2929 : 18 : }
2930 : :
2931 : 66545712 : if (JUMP_P (insn) && flag_cet_switch)
2932 : : {
2933 : 9 : rtx target = JUMP_LABEL (insn);
2934 : 9 : if (target == NULL_RTX || ANY_RETURN_P (target))
2935 : 5 : continue;
2936 : :
2937 : : /* Check the jump is a switch table. */
2938 : 4 : rtx_insn *label = as_a<rtx_insn *> (target);
2939 : 4 : rtx_insn *table = next_insn (label);
2940 : 4 : if (table == NULL_RTX || !JUMP_TABLE_DATA_P (table))
2941 : 2 : continue;
2942 : :
2943 : : /* For the indirect jump find out all places it jumps and insert
2944 : : ENDBRANCH there. It should be done under a special flag to
2945 : : control ENDBRANCH generation for switch stmts. */
2946 : 2 : edge_iterator ei;
2947 : 2 : edge e;
2948 : 2 : basic_block dest_blk;
2949 : :
2950 : 24 : FOR_EACH_EDGE (e, ei, bb->succs)
2951 : : {
2952 : 22 : rtx_insn *insn;
2953 : :
2954 : 22 : dest_blk = e->dest;
2955 : 22 : insn = BB_HEAD (dest_blk);
2956 : 22 : gcc_assert (LABEL_P (insn));
2957 : 22 : endbr = gen_nop_endbr ();
2958 : 22 : emit_insn_after (endbr, insn);
2959 : : }
2960 : 2 : continue;
2961 : 2 : }
2962 : :
2963 : 66545703 : if (LABEL_P (insn) && LABEL_PRESERVE_P (insn))
2964 : : {
2965 : 151879 : endbr = gen_nop_endbr ();
2966 : 151879 : emit_insn_after (endbr, insn);
2967 : 151879 : continue;
2968 : : }
2969 : : }
2970 : : }
2971 : :
2972 : : return;
2973 : : }
2974 : :
2975 : : namespace {
2976 : :
2977 : : const pass_data pass_data_insert_endbr_and_patchable_area =
2978 : : {
2979 : : RTL_PASS, /* type. */
2980 : : "endbr_and_patchable_area", /* name. */
2981 : : OPTGROUP_NONE, /* optinfo_flags. */
2982 : : TV_MACH_DEP, /* tv_id. */
2983 : : 0, /* properties_required. */
2984 : : 0, /* properties_provided. */
2985 : : 0, /* properties_destroyed. */
2986 : : 0, /* todo_flags_start. */
2987 : : 0, /* todo_flags_finish. */
2988 : : };
2989 : :
2990 : : class pass_insert_endbr_and_patchable_area : public rtl_opt_pass
2991 : : {
2992 : : public:
2993 : 277917 : pass_insert_endbr_and_patchable_area (gcc::context *ctxt)
2994 : 555834 : : rtl_opt_pass (pass_data_insert_endbr_and_patchable_area, ctxt)
2995 : : {}
2996 : :
2997 : : /* opt_pass methods: */
2998 : 1443154 : bool gate (function *) final override
2999 : : {
3000 : 1443154 : need_endbr = (flag_cf_protection & CF_BRANCH) != 0;
3001 : 1443154 : patchable_area_size = crtl->patch_area_size - crtl->patch_area_entry;
3002 : 1443154 : return need_endbr || patchable_area_size;
3003 : : }
3004 : :
3005 : 200604 : unsigned int execute (function *) final override
3006 : : {
3007 : 200604 : timevar_push (TV_MACH_DEP);
3008 : 200604 : rest_of_insert_endbr_and_patchable_area (need_endbr,
3009 : : patchable_area_size);
3010 : 200604 : timevar_pop (TV_MACH_DEP);
3011 : 200604 : return 0;
3012 : : }
3013 : :
3014 : : private:
3015 : : bool need_endbr;
3016 : : unsigned int patchable_area_size;
3017 : : }; // class pass_insert_endbr_and_patchable_area
3018 : :
3019 : : } // anon namespace
3020 : :
3021 : : rtl_opt_pass *
3022 : 277917 : make_pass_insert_endbr_and_patchable_area (gcc::context *ctxt)
3023 : : {
3024 : 277917 : return new pass_insert_endbr_and_patchable_area (ctxt);
3025 : : }
3026 : :
3027 : : bool
3028 : 5802526 : ix86_rpad_gate ()
3029 : : {
3030 : 5802526 : return (TARGET_AVX
3031 : 393718 : && TARGET_SSE_PARTIAL_REG_DEPENDENCY
3032 : 299482 : && TARGET_SSE_MATH
3033 : 299260 : && optimize
3034 : 6096780 : && optimize_function_for_speed_p (cfun));
3035 : : }
3036 : :
3037 : : /* At entry of the nearest common dominator for basic blocks with
3038 : : conversions/rcp/sqrt/rsqrt/round, generate a single
3039 : : vxorps %xmmN, %xmmN, %xmmN
3040 : : for all
3041 : : vcvtss2sd op, %xmmN, %xmmX
3042 : : vcvtsd2ss op, %xmmN, %xmmX
3043 : : vcvtsi2ss op, %xmmN, %xmmX
3044 : : vcvtsi2sd op, %xmmN, %xmmX
3045 : :
3046 : : NB: We want to generate only a single vxorps to cover the whole
3047 : : function. The LCM algorithm isn't appropriate here since it may
3048 : : place a vxorps inside the loop. */
3049 : :
3050 : : static unsigned int
3051 : 31160 : remove_partial_avx_dependency (void)
3052 : : {
3053 : 31160 : timevar_push (TV_MACH_DEP);
3054 : :
3055 : 31160 : bitmap_obstack_initialize (NULL);
3056 : 31160 : bitmap convert_bbs = BITMAP_ALLOC (NULL);
3057 : :
3058 : 31160 : basic_block bb;
3059 : 31160 : rtx_insn *insn, *set_insn;
3060 : 31160 : rtx set;
3061 : 31160 : rtx v4sf_const0 = NULL_RTX;
3062 : :
3063 : 31160 : auto_vec<rtx_insn *> control_flow_insns;
3064 : :
3065 : : /* We create invalid RTL initially so defer rescans. */
3066 : 31160 : df_set_flags (DF_DEFER_INSN_RESCAN);
3067 : :
3068 : 288355 : FOR_EACH_BB_FN (bb, cfun)
3069 : : {
3070 : 3349073 : FOR_BB_INSNS (bb, insn)
3071 : : {
3072 : 3091878 : if (!NONDEBUG_INSN_P (insn))
3073 : 1381169 : continue;
3074 : :
3075 : 1710709 : set = single_set (insn);
3076 : 1710709 : if (!set)
3077 : 65374 : continue;
3078 : :
3079 : 1645335 : if (get_attr_avx_partial_xmm_update (insn)
3080 : : != AVX_PARTIAL_XMM_UPDATE_TRUE)
3081 : 1642379 : continue;
3082 : :
3083 : : /* Convert PARTIAL_XMM_UPDATE_TRUE insns, DF -> SF, SF -> DF,
3084 : : SI -> SF, SI -> DF, DI -> SF, DI -> DF, sqrt, rsqrt, rcp,
3085 : : round, to vec_dup and vec_merge with subreg. */
3086 : 2956 : rtx src = SET_SRC (set);
3087 : 2956 : rtx dest = SET_DEST (set);
3088 : 2956 : machine_mode dest_mode = GET_MODE (dest);
3089 : 2956 : bool convert_p = false;
3090 : 2956 : switch (GET_CODE (src))
3091 : : {
3092 : 2852 : case FLOAT:
3093 : 2852 : case FLOAT_EXTEND:
3094 : 2852 : case FLOAT_TRUNCATE:
3095 : 2852 : case UNSIGNED_FLOAT:
3096 : 2852 : convert_p = true;
3097 : 2852 : break;
3098 : : default:
3099 : : break;
3100 : : }
3101 : :
3102 : : /* Only hanlde conversion here. */
3103 : 2956 : machine_mode src_mode
3104 : 2852 : = convert_p ? GET_MODE (XEXP (src, 0)) : VOIDmode;
3105 : 2852 : switch (src_mode)
3106 : : {
3107 : 180 : case E_SFmode:
3108 : 180 : case E_DFmode:
3109 : 180 : if (TARGET_USE_VECTOR_FP_CONVERTS
3110 : 174 : || !TARGET_SSE_PARTIAL_REG_FP_CONVERTS_DEPENDENCY)
3111 : 8 : continue;
3112 : : break;
3113 : 2672 : case E_SImode:
3114 : 2672 : case E_DImode:
3115 : 2672 : if (TARGET_USE_VECTOR_CONVERTS
3116 : 2660 : || !TARGET_SSE_PARTIAL_REG_CONVERTS_DEPENDENCY)
3117 : 14 : continue;
3118 : : break;
3119 : 104 : case E_VOIDmode:
3120 : 104 : gcc_assert (!convert_p);
3121 : : break;
3122 : 0 : default:
3123 : 0 : gcc_unreachable ();
3124 : : }
3125 : :
3126 : 2934 : if (!v4sf_const0)
3127 : 942 : v4sf_const0 = gen_reg_rtx (V4SFmode);
3128 : :
3129 : 2934 : rtx zero;
3130 : 2934 : machine_mode dest_vecmode;
3131 : 2934 : switch (dest_mode)
3132 : : {
3133 : 90 : case E_HFmode:
3134 : 90 : dest_vecmode = V8HFmode;
3135 : 90 : zero = gen_rtx_SUBREG (V8HFmode, v4sf_const0, 0);
3136 : 90 : break;
3137 : : case E_SFmode:
3138 : : dest_vecmode = V4SFmode;
3139 : : zero = v4sf_const0;
3140 : : break;
3141 : 976 : case E_DFmode:
3142 : 976 : dest_vecmode = V2DFmode;
3143 : 976 : zero = gen_rtx_SUBREG (V2DFmode, v4sf_const0, 0);
3144 : 976 : break;
3145 : 0 : default:
3146 : 0 : gcc_unreachable ();
3147 : : }
3148 : :
3149 : : /* Change source to vector mode. */
3150 : 2934 : src = gen_rtx_VEC_DUPLICATE (dest_vecmode, src);
3151 : 2934 : src = gen_rtx_VEC_MERGE (dest_vecmode, src, zero,
3152 : : GEN_INT (HOST_WIDE_INT_1U));
3153 : : /* Change destination to vector mode. */
3154 : 2934 : rtx vec = gen_reg_rtx (dest_vecmode);
3155 : : /* Generate an XMM vector SET. */
3156 : 2934 : set = gen_rtx_SET (vec, src);
3157 : 2934 : set_insn = emit_insn_before (set, insn);
3158 : 2934 : df_insn_rescan (set_insn);
3159 : :
3160 : 2934 : if (cfun->can_throw_non_call_exceptions)
3161 : : {
3162 : : /* Handle REG_EH_REGION note. */
3163 : 0 : rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
3164 : 0 : if (note)
3165 : : {
3166 : 0 : control_flow_insns.safe_push (set_insn);
3167 : 0 : add_reg_note (set_insn, REG_EH_REGION, XEXP (note, 0));
3168 : : }
3169 : : }
3170 : :
3171 : 2934 : src = gen_rtx_SUBREG (dest_mode, vec, 0);
3172 : 2934 : set = gen_rtx_SET (dest, src);
3173 : :
3174 : : /* Drop possible dead definitions. */
3175 : 2934 : PATTERN (insn) = set;
3176 : :
3177 : 2934 : INSN_CODE (insn) = -1;
3178 : 2934 : recog_memoized (insn);
3179 : 2934 : df_insn_rescan (insn);
3180 : 2934 : bitmap_set_bit (convert_bbs, bb->index);
3181 : : }
3182 : : }
3183 : :
3184 : 31160 : if (v4sf_const0)
3185 : : {
3186 : : /* (Re-)discover loops so that bb->loop_father can be used in the
3187 : : analysis below. */
3188 : 942 : calculate_dominance_info (CDI_DOMINATORS);
3189 : 942 : loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
3190 : :
3191 : : /* Generate a vxorps at entry of the nearest dominator for basic
3192 : : blocks with conversions, which is in the fake loop that
3193 : : contains the whole function, so that there is only a single
3194 : : vxorps in the whole function. */
3195 : 942 : bb = nearest_common_dominator_for_set (CDI_DOMINATORS,
3196 : : convert_bbs);
3197 : 942 : while (bb->loop_father->latch
3198 : 1402 : != EXIT_BLOCK_PTR_FOR_FN (cfun))
3199 : 460 : bb = get_immediate_dominator (CDI_DOMINATORS,
3200 : : bb->loop_father->header);
3201 : :
3202 : 942 : set = gen_rtx_SET (v4sf_const0, CONST0_RTX (V4SFmode));
3203 : :
3204 : 942 : insn = BB_HEAD (bb);
3205 : 2580 : while (insn && !NONDEBUG_INSN_P (insn))
3206 : : {
3207 : 1639 : if (insn == BB_END (bb))
3208 : : {
3209 : : insn = NULL;
3210 : : break;
3211 : : }
3212 : 1638 : insn = NEXT_INSN (insn);
3213 : : }
3214 : 942 : if (insn == BB_HEAD (bb))
3215 : 0 : set_insn = emit_insn_before (set, insn);
3216 : : else
3217 : 1884 : set_insn = emit_insn_after (set,
3218 : 942 : insn ? PREV_INSN (insn) : BB_END (bb));
3219 : 942 : df_insn_rescan (set_insn);
3220 : 942 : loop_optimizer_finalize ();
3221 : :
3222 : 942 : if (!control_flow_insns.is_empty ())
3223 : : {
3224 : 0 : free_dominance_info (CDI_DOMINATORS);
3225 : :
3226 : 0 : unsigned int i;
3227 : 0 : FOR_EACH_VEC_ELT (control_flow_insns, i, insn)
3228 : 0 : if (control_flow_insn_p (insn))
3229 : : {
3230 : : /* Split the block after insn. There will be a fallthru
3231 : : edge, which is OK so we keep it. We have to create
3232 : : the exception edges ourselves. */
3233 : 0 : bb = BLOCK_FOR_INSN (insn);
3234 : 0 : split_block (bb, insn);
3235 : 0 : rtl_make_eh_edge (NULL, bb, BB_END (bb));
3236 : : }
3237 : : }
3238 : : }
3239 : :
3240 : 31160 : df_process_deferred_rescans ();
3241 : 31160 : df_clear_flags (DF_DEFER_INSN_RESCAN);
3242 : 31160 : bitmap_obstack_release (NULL);
3243 : 31160 : BITMAP_FREE (convert_bbs);
3244 : :
3245 : 31160 : timevar_pop (TV_MACH_DEP);
3246 : 31160 : return 0;
3247 : 31160 : }
3248 : :
3249 : : namespace {
3250 : :
3251 : : const pass_data pass_data_remove_partial_avx_dependency =
3252 : : {
3253 : : RTL_PASS, /* type */
3254 : : "rpad", /* name */
3255 : : OPTGROUP_NONE, /* optinfo_flags */
3256 : : TV_MACH_DEP, /* tv_id */
3257 : : 0, /* properties_required */
3258 : : 0, /* properties_provided */
3259 : : 0, /* properties_destroyed */
3260 : : 0, /* todo_flags_start */
3261 : : 0, /* todo_flags_finish */
3262 : : };
3263 : :
3264 : : class pass_remove_partial_avx_dependency : public rtl_opt_pass
3265 : : {
3266 : : public:
3267 : 277917 : pass_remove_partial_avx_dependency (gcc::context *ctxt)
3268 : 555834 : : rtl_opt_pass (pass_data_remove_partial_avx_dependency, ctxt)
3269 : : {}
3270 : :
3271 : : /* opt_pass methods: */
3272 : 1443154 : bool gate (function *) final override
3273 : : {
3274 : 1443154 : return ix86_rpad_gate ();
3275 : : }
3276 : :
3277 : 31160 : unsigned int execute (function *) final override
3278 : : {
3279 : 31160 : return remove_partial_avx_dependency ();
3280 : : }
3281 : : }; // class pass_rpad
3282 : :
3283 : : } // anon namespace
3284 : :
3285 : : rtl_opt_pass *
3286 : 277917 : make_pass_remove_partial_avx_dependency (gcc::context *ctxt)
3287 : : {
3288 : 277917 : return new pass_remove_partial_avx_dependency (ctxt);
3289 : : }
3290 : :
3291 : : /* Convert legacy instructions that clobbers EFLAGS to APX_NF
3292 : : instructions when there are no flag set between a flag
3293 : : producer and user. */
3294 : :
3295 : : static unsigned int
3296 : 338 : ix86_apx_nf_convert (void)
3297 : : {
3298 : 338 : timevar_push (TV_MACH_DEP);
3299 : :
3300 : 338 : basic_block bb;
3301 : 338 : rtx_insn *insn;
3302 : 338 : hash_map <rtx_insn *, rtx> converting_map;
3303 : 338 : auto_vec <rtx_insn *> current_convert_list;
3304 : :
3305 : 338 : bool converting_seq = false;
3306 : 338 : rtx cc = gen_rtx_REG (CCmode, FLAGS_REG);
3307 : :
3308 : 717 : FOR_EACH_BB_FN (bb, cfun)
3309 : : {
3310 : : /* Reset conversion for each bb. */
3311 : 379 : converting_seq = false;
3312 : 4160 : FOR_BB_INSNS (bb, insn)
3313 : : {
3314 : 3781 : if (!NONDEBUG_INSN_P (insn))
3315 : 4246 : continue;
3316 : :
3317 : 3037 : if (recog_memoized (insn) < 0)
3318 : 320 : continue;
3319 : :
3320 : : /* Convert candidate insns after cstore, which should
3321 : : satisify the two conditions:
3322 : : 1. Is not flag user or producer, only clobbers
3323 : : FLAGS_REG.
3324 : : 2. Have corresponding nf pattern. */
3325 : :
3326 : 2717 : rtx pat = PATTERN (insn);
3327 : :
3328 : : /* Starting convertion at first cstorecc. */
3329 : 2717 : rtx set = NULL_RTX;
3330 : 2717 : if (!converting_seq
3331 : 2449 : && (set = single_set (insn))
3332 : 2433 : && ix86_comparison_operator (SET_SRC (set), VOIDmode)
3333 : 28 : && reg_overlap_mentioned_p (cc, SET_SRC (set))
3334 : 2742 : && !reg_overlap_mentioned_p (cc, SET_DEST (set)))
3335 : : {
3336 : 25 : converting_seq = true;
3337 : 25 : current_convert_list.truncate (0);
3338 : : }
3339 : : /* Terminate at the next explicit flag set. */
3340 : 2692 : else if (reg_set_p (cc, pat)
3341 : 2692 : && GET_CODE (set_of (cc, pat)) != CLOBBER)
3342 : : converting_seq = false;
3343 : :
3344 : 2636 : if (!converting_seq)
3345 : 2438 : continue;
3346 : :
3347 : 279 : if (get_attr_has_nf (insn)
3348 : 279 : && GET_CODE (pat) == PARALLEL)
3349 : : {
3350 : : /* Record the insn to candidate map. */
3351 : 15 : current_convert_list.safe_push (insn);
3352 : 15 : converting_map.put (insn, pat);
3353 : : }
3354 : : /* If the insn clobbers flags but has no nf_attr,
3355 : : revoke all previous candidates. */
3356 : 264 : else if (!get_attr_has_nf (insn)
3357 : 263 : && reg_set_p (cc, pat)
3358 : 264 : && GET_CODE (set_of (cc, pat)) == CLOBBER)
3359 : : {
3360 : 0 : for (auto item : current_convert_list)
3361 : 0 : converting_map.remove (item);
3362 : 0 : converting_seq = false;
3363 : : }
3364 : : }
3365 : : }
3366 : :
3367 : 338 : if (!converting_map.is_empty ())
3368 : : {
3369 : 21 : for (auto iter = converting_map.begin ();
3370 : 42 : iter != converting_map.end (); ++iter)
3371 : : {
3372 : 15 : rtx_insn *replace = (*iter).first;
3373 : 15 : rtx pat = (*iter).second;
3374 : 15 : int i, n = 0, len = XVECLEN (pat, 0);
3375 : 15 : rtx *new_elems = XALLOCAVEC (rtx, len);
3376 : 15 : rtx new_pat;
3377 : 45 : for (i = 0; i < len; i++)
3378 : : {
3379 : 30 : rtx temp = XVECEXP (pat, 0, i);
3380 : 45 : if (! (GET_CODE (temp) == CLOBBER
3381 : 15 : && reg_overlap_mentioned_p (cc,
3382 : 15 : XEXP (temp, 0))))
3383 : : {
3384 : 15 : new_elems[n] = temp;
3385 : 15 : n++;
3386 : : }
3387 : : }
3388 : :
3389 : 15 : if (n == 1)
3390 : 15 : new_pat = new_elems[0];
3391 : : else
3392 : 0 : new_pat =
3393 : 0 : gen_rtx_PARALLEL (VOIDmode,
3394 : : gen_rtvec_v (n,
3395 : : new_elems));
3396 : :
3397 : 15 : PATTERN (replace) = new_pat;
3398 : 15 : INSN_CODE (replace) = -1;
3399 : 15 : recog_memoized (replace);
3400 : 15 : df_insn_rescan (replace);
3401 : : }
3402 : : }
3403 : :
3404 : 338 : timevar_pop (TV_MACH_DEP);
3405 : 338 : return 0;
3406 : 338 : }
3407 : :
3408 : :
3409 : : namespace {
3410 : :
3411 : : const pass_data pass_data_apx_nf_convert =
3412 : : {
3413 : : RTL_PASS, /* type */
3414 : : "apx_nfcvt", /* name */
3415 : : OPTGROUP_NONE, /* optinfo_flags */
3416 : : TV_MACH_DEP, /* tv_id */
3417 : : 0, /* properties_required */
3418 : : 0, /* properties_provided */
3419 : : 0, /* properties_destroyed */
3420 : : 0, /* todo_flags_start */
3421 : : 0, /* todo_flags_finish */
3422 : : };
3423 : :
3424 : : class pass_apx_nf_convert : public rtl_opt_pass
3425 : : {
3426 : : public:
3427 : 277917 : pass_apx_nf_convert (gcc::context *ctxt)
3428 : 555834 : : rtl_opt_pass (pass_data_apx_nf_convert, ctxt)
3429 : : {}
3430 : :
3431 : : /* opt_pass methods: */
3432 : 1443154 : bool gate (function *) final override
3433 : : {
3434 : 1443154 : return (TARGET_APX_NF
3435 : 346 : && optimize
3436 : 1443493 : && optimize_function_for_speed_p (cfun));
3437 : : }
3438 : :
3439 : 338 : unsigned int execute (function *) final override
3440 : : {
3441 : 338 : return ix86_apx_nf_convert ();
3442 : : }
3443 : : }; // class pass_apx_nf_convert
3444 : :
3445 : : } // anon namespace
3446 : :
3447 : : rtl_opt_pass *
3448 : 277917 : make_pass_apx_nf_convert (gcc::context *ctxt)
3449 : : {
3450 : 277917 : return new pass_apx_nf_convert (ctxt);
3451 : : }
3452 : :
3453 : : /* When a hot loop can be fit into one cacheline,
3454 : : force align the loop without considering the max skip. */
3455 : : static void
3456 : 959632 : ix86_align_loops ()
3457 : : {
3458 : 959632 : basic_block bb;
3459 : :
3460 : : /* Don't do this when we don't know cache line size. */
3461 : 959632 : if (ix86_cost->prefetch_block == 0)
3462 : 9 : return;
3463 : :
3464 : 959623 : loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
3465 : 959623 : profile_count count_threshold = cfun->cfg->count_max / param_align_threshold;
3466 : 11148720 : FOR_EACH_BB_FN (bb, cfun)
3467 : : {
3468 : 10189097 : rtx_insn *label = BB_HEAD (bb);
3469 : 10189097 : bool has_fallthru = 0;
3470 : 10189097 : edge e;
3471 : 10189097 : edge_iterator ei;
3472 : :
3473 : 10189097 : if (!LABEL_P (label))
3474 : 5179687 : continue;
3475 : :
3476 : 5014702 : profile_count fallthru_count = profile_count::zero ();
3477 : 5014702 : profile_count branch_count = profile_count::zero ();
3478 : :
3479 : 14577602 : FOR_EACH_EDGE (e, ei, bb->preds)
3480 : : {
3481 : 9562900 : if (e->flags & EDGE_FALLTHRU)
3482 : 2431883 : has_fallthru = 1, fallthru_count += e->count ();
3483 : : else
3484 : 7131017 : branch_count += e->count ();
3485 : : }
3486 : :
3487 : 5014702 : if (!fallthru_count.initialized_p () || !branch_count.initialized_p ())
3488 : 5292 : continue;
3489 : :
3490 : 5009410 : if (bb->loop_father
3491 : 5009410 : && bb->loop_father->latch != EXIT_BLOCK_PTR_FOR_FN (cfun)
3492 : 6293155 : && (has_fallthru
3493 : 1283745 : ? (!(single_succ_p (bb)
3494 : 137125 : && single_succ (bb) == EXIT_BLOCK_PTR_FOR_FN (cfun))
3495 : 894483 : && optimize_bb_for_speed_p (bb)
3496 : 811481 : && branch_count + fallthru_count > count_threshold
3497 : 707371 : && (branch_count > fallthru_count * param_align_loop_iterations))
3498 : : /* In case there'no fallthru for the loop.
3499 : : Nops inserted won't be executed. */
3500 : 389262 : : (branch_count > count_threshold
3501 : 119270 : || (bb->count > bb->prev_bb->count * 10
3502 : 10866 : && (bb->prev_bb->count
3503 : 4485065 : <= ENTRY_BLOCK_PTR_FOR_FN (cfun)->count / 2)))))
3504 : : {
3505 : 535211 : rtx_insn* insn, *end_insn;
3506 : 535211 : HOST_WIDE_INT size = 0;
3507 : 535211 : bool padding_p = true;
3508 : 535211 : basic_block tbb = bb;
3509 : 535211 : unsigned cond_branch_num = 0;
3510 : 535211 : bool detect_tight_loop_p = false;
3511 : :
3512 : 843145 : for (unsigned int i = 0; i != bb->loop_father->num_nodes;
3513 : 307934 : i++, tbb = tbb->next_bb)
3514 : : {
3515 : : /* Only handle continuous cfg layout. */
3516 : 843145 : if (bb->loop_father != tbb->loop_father)
3517 : : {
3518 : : padding_p = false;
3519 : : break;
3520 : : }
3521 : :
3522 : 9996515 : FOR_BB_INSNS (tbb, insn)
3523 : : {
3524 : 9359957 : if (!NONDEBUG_INSN_P (insn))
3525 : 5365311 : continue;
3526 : 3994646 : size += ix86_min_insn_size (insn);
3527 : :
3528 : : /* We don't know size of inline asm.
3529 : : Don't align loop for call. */
3530 : 3994646 : if (asm_noperands (PATTERN (insn)) >= 0
3531 : 3994646 : || CALL_P (insn))
3532 : : {
3533 : : size = -1;
3534 : : break;
3535 : : }
3536 : : }
3537 : :
3538 : 802256 : if (size == -1 || size > ix86_cost->prefetch_block)
3539 : : {
3540 : : padding_p = false;
3541 : : break;
3542 : : }
3543 : :
3544 : 1415533 : FOR_EACH_EDGE (e, ei, tbb->succs)
3545 : : {
3546 : : /* It could be part of the loop. */
3547 : 975590 : if (e->dest == bb)
3548 : : {
3549 : : detect_tight_loop_p = true;
3550 : : break;
3551 : : }
3552 : : }
3553 : :
3554 : 610981 : if (detect_tight_loop_p)
3555 : : break;
3556 : :
3557 : 439943 : end_insn = BB_END (tbb);
3558 : 439943 : if (JUMP_P (end_insn))
3559 : : {
3560 : : /* For decoded icache:
3561 : : 1. Up to two branches are allowed per Way.
3562 : : 2. A non-conditional branch is the last micro-op in a Way.
3563 : : */
3564 : 353957 : if (onlyjump_p (end_insn)
3565 : 353957 : && (any_uncondjump_p (end_insn)
3566 : 301218 : || single_succ_p (tbb)))
3567 : : {
3568 : : padding_p = false;
3569 : : break;
3570 : : }
3571 : 301218 : else if (++cond_branch_num >= 2)
3572 : : {
3573 : : padding_p = false;
3574 : : break;
3575 : : }
3576 : : }
3577 : :
3578 : : }
3579 : :
3580 : 535211 : if (padding_p && detect_tight_loop_p)
3581 : : {
3582 : 342076 : emit_insn_before (gen_max_skip_align (GEN_INT (ceil_log2 (size)),
3583 : : GEN_INT (0)), label);
3584 : : /* End of function. */
3585 : 171038 : if (!tbb || tbb == EXIT_BLOCK_PTR_FOR_FN (cfun))
3586 : : break;
3587 : : /* Skip bb which already fits into one cacheline. */
3588 : : bb = tbb;
3589 : : }
3590 : : }
3591 : : }
3592 : :
3593 : 959623 : loop_optimizer_finalize ();
3594 : 959623 : free_dominance_info (CDI_DOMINATORS);
3595 : : }
3596 : :
3597 : : namespace {
3598 : :
3599 : : const pass_data pass_data_align_tight_loops =
3600 : : {
3601 : : RTL_PASS, /* type */
3602 : : "align_tight_loops", /* name */
3603 : : OPTGROUP_NONE, /* optinfo_flags */
3604 : : TV_MACH_DEP, /* tv_id */
3605 : : 0, /* properties_required */
3606 : : 0, /* properties_provided */
3607 : : 0, /* properties_destroyed */
3608 : : 0, /* todo_flags_start */
3609 : : 0, /* todo_flags_finish */
3610 : : };
3611 : :
3612 : : class pass_align_tight_loops : public rtl_opt_pass
3613 : : {
3614 : : public:
3615 : 277917 : pass_align_tight_loops (gcc::context *ctxt)
3616 : 555834 : : rtl_opt_pass (pass_data_align_tight_loops, ctxt)
3617 : : {}
3618 : :
3619 : : /* opt_pass methods: */
3620 : 1443154 : bool gate (function *) final override
3621 : : {
3622 : 1443154 : return TARGET_ALIGN_TIGHT_LOOPS
3623 : 1442687 : && optimize
3624 : 2464775 : && optimize_function_for_speed_p (cfun);
3625 : : }
3626 : :
3627 : 959632 : unsigned int execute (function *) final override
3628 : : {
3629 : 959632 : timevar_push (TV_MACH_DEP);
3630 : : #ifdef ASM_OUTPUT_MAX_SKIP_ALIGN
3631 : 959632 : ix86_align_loops ();
3632 : : #endif
3633 : 959632 : timevar_pop (TV_MACH_DEP);
3634 : 959632 : return 0;
3635 : : }
3636 : : }; // class pass_align_tight_loops
3637 : :
3638 : : } // anon namespace
3639 : :
3640 : : rtl_opt_pass *
3641 : 277917 : make_pass_align_tight_loops (gcc::context *ctxt)
3642 : : {
3643 : 277917 : return new pass_align_tight_loops (ctxt);
3644 : : }
3645 : :
3646 : : /* This compares the priority of target features in function DECL1
3647 : : and DECL2. It returns positive value if DECL1 is higher priority,
3648 : : negative value if DECL2 is higher priority and 0 if they are the
3649 : : same. */
3650 : :
3651 : : int
3652 : 860 : ix86_compare_version_priority (tree decl1, tree decl2)
3653 : : {
3654 : 860 : unsigned int priority1 = get_builtin_code_for_version (decl1, NULL);
3655 : 860 : unsigned int priority2 = get_builtin_code_for_version (decl2, NULL);
3656 : :
3657 : 860 : return (int)priority1 - (int)priority2;
3658 : : }
3659 : :
3660 : : /* V1 and V2 point to function versions with different priorities
3661 : : based on the target ISA. This function compares their priorities. */
3662 : :
3663 : : static int
3664 : 6578 : feature_compare (const void *v1, const void *v2)
3665 : : {
3666 : 6578 : typedef struct _function_version_info
3667 : : {
3668 : : tree version_decl;
3669 : : tree predicate_chain;
3670 : : unsigned int dispatch_priority;
3671 : : } function_version_info;
3672 : :
3673 : 6578 : const function_version_info c1 = *(const function_version_info *)v1;
3674 : 6578 : const function_version_info c2 = *(const function_version_info *)v2;
3675 : 6578 : return (c2.dispatch_priority - c1.dispatch_priority);
3676 : : }
3677 : :
3678 : : /* This adds a condition to the basic_block NEW_BB in function FUNCTION_DECL
3679 : : to return a pointer to VERSION_DECL if the outcome of the expression
3680 : : formed by PREDICATE_CHAIN is true. This function will be called during
3681 : : version dispatch to decide which function version to execute. It returns
3682 : : the basic block at the end, to which more conditions can be added. */
3683 : :
3684 : : static basic_block
3685 : 713 : add_condition_to_bb (tree function_decl, tree version_decl,
3686 : : tree predicate_chain, basic_block new_bb)
3687 : : {
3688 : 713 : gimple *return_stmt;
3689 : 713 : tree convert_expr, result_var;
3690 : 713 : gimple *convert_stmt;
3691 : 713 : gimple *call_cond_stmt;
3692 : 713 : gimple *if_else_stmt;
3693 : :
3694 : 713 : basic_block bb1, bb2, bb3;
3695 : 713 : edge e12, e23;
3696 : :
3697 : 713 : tree cond_var, and_expr_var = NULL_TREE;
3698 : 713 : gimple_seq gseq;
3699 : :
3700 : 713 : tree predicate_decl, predicate_arg;
3701 : :
3702 : 713 : push_cfun (DECL_STRUCT_FUNCTION (function_decl));
3703 : :
3704 : 713 : gcc_assert (new_bb != NULL);
3705 : 713 : gseq = bb_seq (new_bb);
3706 : :
3707 : :
3708 : 713 : convert_expr = build1 (CONVERT_EXPR, ptr_type_node,
3709 : : build_fold_addr_expr (version_decl));
3710 : 713 : result_var = create_tmp_var (ptr_type_node);
3711 : 713 : convert_stmt = gimple_build_assign (result_var, convert_expr);
3712 : 713 : return_stmt = gimple_build_return (result_var);
3713 : :
3714 : 713 : if (predicate_chain == NULL_TREE)
3715 : : {
3716 : 162 : gimple_seq_add_stmt (&gseq, convert_stmt);
3717 : 162 : gimple_seq_add_stmt (&gseq, return_stmt);
3718 : 162 : set_bb_seq (new_bb, gseq);
3719 : 162 : gimple_set_bb (convert_stmt, new_bb);
3720 : 162 : gimple_set_bb (return_stmt, new_bb);
3721 : 162 : pop_cfun ();
3722 : 162 : return new_bb;
3723 : : }
3724 : :
3725 : 1141 : while (predicate_chain != NULL)
3726 : : {
3727 : 590 : cond_var = create_tmp_var (integer_type_node);
3728 : 590 : predicate_decl = TREE_PURPOSE (predicate_chain);
3729 : 590 : predicate_arg = TREE_VALUE (predicate_chain);
3730 : 590 : call_cond_stmt = gimple_build_call (predicate_decl, 1, predicate_arg);
3731 : 590 : gimple_call_set_lhs (call_cond_stmt, cond_var);
3732 : :
3733 : 590 : gimple_set_block (call_cond_stmt, DECL_INITIAL (function_decl));
3734 : 590 : gimple_set_bb (call_cond_stmt, new_bb);
3735 : 590 : gimple_seq_add_stmt (&gseq, call_cond_stmt);
3736 : :
3737 : 590 : predicate_chain = TREE_CHAIN (predicate_chain);
3738 : :
3739 : 590 : if (and_expr_var == NULL)
3740 : : and_expr_var = cond_var;
3741 : : else
3742 : : {
3743 : 39 : gimple *assign_stmt;
3744 : : /* Use MIN_EXPR to check if any integer is zero?.
3745 : : and_expr_var = min_expr <cond_var, and_expr_var> */
3746 : 39 : assign_stmt = gimple_build_assign (and_expr_var,
3747 : : build2 (MIN_EXPR, integer_type_node,
3748 : : cond_var, and_expr_var));
3749 : :
3750 : 39 : gimple_set_block (assign_stmt, DECL_INITIAL (function_decl));
3751 : 39 : gimple_set_bb (assign_stmt, new_bb);
3752 : 39 : gimple_seq_add_stmt (&gseq, assign_stmt);
3753 : : }
3754 : : }
3755 : :
3756 : 551 : if_else_stmt = gimple_build_cond (GT_EXPR, and_expr_var,
3757 : : integer_zero_node,
3758 : : NULL_TREE, NULL_TREE);
3759 : 551 : gimple_set_block (if_else_stmt, DECL_INITIAL (function_decl));
3760 : 551 : gimple_set_bb (if_else_stmt, new_bb);
3761 : 551 : gimple_seq_add_stmt (&gseq, if_else_stmt);
3762 : :
3763 : 551 : gimple_seq_add_stmt (&gseq, convert_stmt);
3764 : 551 : gimple_seq_add_stmt (&gseq, return_stmt);
3765 : 551 : set_bb_seq (new_bb, gseq);
3766 : :
3767 : 551 : bb1 = new_bb;
3768 : 551 : e12 = split_block (bb1, if_else_stmt);
3769 : 551 : bb2 = e12->dest;
3770 : 551 : e12->flags &= ~EDGE_FALLTHRU;
3771 : 551 : e12->flags |= EDGE_TRUE_VALUE;
3772 : :
3773 : 551 : e23 = split_block (bb2, return_stmt);
3774 : :
3775 : 551 : gimple_set_bb (convert_stmt, bb2);
3776 : 551 : gimple_set_bb (return_stmt, bb2);
3777 : :
3778 : 551 : bb3 = e23->dest;
3779 : 551 : make_edge (bb1, bb3, EDGE_FALSE_VALUE);
3780 : :
3781 : 551 : remove_edge (e23);
3782 : 551 : make_edge (bb2, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
3783 : :
3784 : 551 : pop_cfun ();
3785 : :
3786 : 551 : return bb3;
3787 : : }
3788 : :
3789 : : /* This function generates the dispatch function for
3790 : : multi-versioned functions. DISPATCH_DECL is the function which will
3791 : : contain the dispatch logic. FNDECLS are the function choices for
3792 : : dispatch, and is a tree chain. EMPTY_BB is the basic block pointer
3793 : : in DISPATCH_DECL in which the dispatch code is generated. */
3794 : :
3795 : : static int
3796 : 162 : dispatch_function_versions (tree dispatch_decl,
3797 : : void *fndecls_p,
3798 : : basic_block *empty_bb)
3799 : : {
3800 : 162 : tree default_decl;
3801 : 162 : gimple *ifunc_cpu_init_stmt;
3802 : 162 : gimple_seq gseq;
3803 : 162 : int ix;
3804 : 162 : tree ele;
3805 : 162 : vec<tree> *fndecls;
3806 : 162 : unsigned int num_versions = 0;
3807 : 162 : unsigned int actual_versions = 0;
3808 : 162 : unsigned int i;
3809 : :
3810 : 162 : struct _function_version_info
3811 : : {
3812 : : tree version_decl;
3813 : : tree predicate_chain;
3814 : : unsigned int dispatch_priority;
3815 : : }*function_version_info;
3816 : :
3817 : 162 : gcc_assert (dispatch_decl != NULL
3818 : : && fndecls_p != NULL
3819 : : && empty_bb != NULL);
3820 : :
3821 : : /*fndecls_p is actually a vector. */
3822 : 162 : fndecls = static_cast<vec<tree> *> (fndecls_p);
3823 : :
3824 : : /* At least one more version other than the default. */
3825 : 162 : num_versions = fndecls->length ();
3826 : 162 : gcc_assert (num_versions >= 2);
3827 : :
3828 : 162 : function_version_info = (struct _function_version_info *)
3829 : 162 : XNEWVEC (struct _function_version_info, (num_versions - 1));
3830 : :
3831 : : /* The first version in the vector is the default decl. */
3832 : 162 : default_decl = (*fndecls)[0];
3833 : :
3834 : 162 : push_cfun (DECL_STRUCT_FUNCTION (dispatch_decl));
3835 : :
3836 : 162 : gseq = bb_seq (*empty_bb);
3837 : : /* Function version dispatch is via IFUNC. IFUNC resolvers fire before
3838 : : constructors, so explicity call __builtin_cpu_init here. */
3839 : 162 : ifunc_cpu_init_stmt
3840 : 162 : = gimple_build_call_vec (get_ix86_builtin (IX86_BUILTIN_CPU_INIT), vNULL);
3841 : 162 : gimple_seq_add_stmt (&gseq, ifunc_cpu_init_stmt);
3842 : 162 : gimple_set_bb (ifunc_cpu_init_stmt, *empty_bb);
3843 : 162 : set_bb_seq (*empty_bb, gseq);
3844 : :
3845 : 162 : pop_cfun ();
3846 : :
3847 : :
3848 : 867 : for (ix = 1; fndecls->iterate (ix, &ele); ++ix)
3849 : : {
3850 : 705 : tree version_decl = ele;
3851 : 705 : tree predicate_chain = NULL_TREE;
3852 : 705 : unsigned int priority;
3853 : : /* Get attribute string, parse it and find the right predicate decl.
3854 : : The predicate function could be a lengthy combination of many
3855 : : features, like arch-type and various isa-variants. */
3856 : 705 : priority = get_builtin_code_for_version (version_decl,
3857 : : &predicate_chain);
3858 : :
3859 : 705 : if (predicate_chain == NULL_TREE)
3860 : 154 : continue;
3861 : :
3862 : 551 : function_version_info [actual_versions].version_decl = version_decl;
3863 : 551 : function_version_info [actual_versions].predicate_chain
3864 : 551 : = predicate_chain;
3865 : 551 : function_version_info [actual_versions].dispatch_priority = priority;
3866 : 551 : actual_versions++;
3867 : : }
3868 : :
3869 : : /* Sort the versions according to descending order of dispatch priority. The
3870 : : priority is based on the ISA. This is not a perfect solution. There
3871 : : could still be ambiguity. If more than one function version is suitable
3872 : : to execute, which one should be dispatched? In future, allow the user
3873 : : to specify a dispatch priority next to the version. */
3874 : 162 : qsort (function_version_info, actual_versions,
3875 : : sizeof (struct _function_version_info), feature_compare);
3876 : :
3877 : 875 : for (i = 0; i < actual_versions; ++i)
3878 : 551 : *empty_bb = add_condition_to_bb (dispatch_decl,
3879 : : function_version_info[i].version_decl,
3880 : 551 : function_version_info[i].predicate_chain,
3881 : : *empty_bb);
3882 : :
3883 : : /* dispatch default version at the end. */
3884 : 162 : *empty_bb = add_condition_to_bb (dispatch_decl, default_decl,
3885 : : NULL, *empty_bb);
3886 : :
3887 : 162 : free (function_version_info);
3888 : 162 : return 0;
3889 : : }
3890 : :
3891 : : /* This function changes the assembler name for functions that are
3892 : : versions. If DECL is a function version and has a "target"
3893 : : attribute, it appends the attribute string to its assembler name. */
3894 : :
3895 : : static tree
3896 : 753 : ix86_mangle_function_version_assembler_name (tree decl, tree id)
3897 : : {
3898 : 753 : tree version_attr;
3899 : 753 : const char *orig_name, *version_string;
3900 : 753 : char *attr_str, *assembler_name;
3901 : :
3902 : 753 : if (DECL_DECLARED_INLINE_P (decl)
3903 : 807 : && lookup_attribute ("gnu_inline",
3904 : 54 : DECL_ATTRIBUTES (decl)))
3905 : 0 : error_at (DECL_SOURCE_LOCATION (decl),
3906 : : "function versions cannot be marked as %<gnu_inline%>,"
3907 : : " bodies have to be generated");
3908 : :
3909 : 753 : if (DECL_VIRTUAL_P (decl)
3910 : 1506 : || DECL_VINDEX (decl))
3911 : 0 : sorry ("virtual function multiversioning not supported");
3912 : :
3913 : 753 : version_attr = lookup_attribute ("target", DECL_ATTRIBUTES (decl));
3914 : :
3915 : : /* target attribute string cannot be NULL. */
3916 : 753 : gcc_assert (version_attr != NULL_TREE);
3917 : :
3918 : 753 : orig_name = IDENTIFIER_POINTER (id);
3919 : 753 : version_string
3920 : 753 : = TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (version_attr)));
3921 : :
3922 : 753 : if (strcmp (version_string, "default") == 0)
3923 : : return id;
3924 : :
3925 : 630 : attr_str = sorted_attr_string (TREE_VALUE (version_attr));
3926 : 630 : assembler_name = XNEWVEC (char, strlen (orig_name) + strlen (attr_str) + 2);
3927 : :
3928 : 630 : sprintf (assembler_name, "%s.%s", orig_name, attr_str);
3929 : :
3930 : : /* Allow assembler name to be modified if already set. */
3931 : 630 : if (DECL_ASSEMBLER_NAME_SET_P (decl))
3932 : 12 : SET_DECL_RTL (decl, NULL);
3933 : :
3934 : 630 : tree ret = get_identifier (assembler_name);
3935 : 630 : XDELETEVEC (attr_str);
3936 : 630 : XDELETEVEC (assembler_name);
3937 : 630 : return ret;
3938 : : }
3939 : :
3940 : : tree
3941 : 371321635 : ix86_mangle_decl_assembler_name (tree decl, tree id)
3942 : : {
3943 : : /* For function version, add the target suffix to the assembler name. */
3944 : 371321635 : if (TREE_CODE (decl) == FUNCTION_DECL
3945 : 371321635 : && DECL_FUNCTION_VERSIONED (decl))
3946 : 753 : id = ix86_mangle_function_version_assembler_name (decl, id);
3947 : : #ifdef SUBTARGET_MANGLE_DECL_ASSEMBLER_NAME
3948 : : id = SUBTARGET_MANGLE_DECL_ASSEMBLER_NAME (decl, id);
3949 : : #endif
3950 : :
3951 : 371321635 : return id;
3952 : : }
3953 : :
3954 : : /* Make a dispatcher declaration for the multi-versioned function DECL.
3955 : : Calls to DECL function will be replaced with calls to the dispatcher
3956 : : by the front-end. Returns the decl of the dispatcher function. */
3957 : :
3958 : : tree
3959 : 288 : ix86_get_function_versions_dispatcher (void *decl)
3960 : : {
3961 : 288 : tree fn = (tree) decl;
3962 : 288 : struct cgraph_node *node = NULL;
3963 : 288 : struct cgraph_node *default_node = NULL;
3964 : 288 : struct cgraph_function_version_info *node_v = NULL;
3965 : 288 : struct cgraph_function_version_info *first_v = NULL;
3966 : :
3967 : 288 : tree dispatch_decl = NULL;
3968 : :
3969 : 288 : struct cgraph_function_version_info *default_version_info = NULL;
3970 : :
3971 : 576 : gcc_assert (fn != NULL && DECL_FUNCTION_VERSIONED (fn));
3972 : :
3973 : 288 : node = cgraph_node::get (fn);
3974 : 288 : gcc_assert (node != NULL);
3975 : :
3976 : 288 : node_v = node->function_version ();
3977 : 288 : gcc_assert (node_v != NULL);
3978 : :
3979 : 288 : if (node_v->dispatcher_resolver != NULL)
3980 : : return node_v->dispatcher_resolver;
3981 : :
3982 : : /* Find the default version and make it the first node. */
3983 : : first_v = node_v;
3984 : : /* Go to the beginning of the chain. */
3985 : 429 : while (first_v->prev != NULL)
3986 : : first_v = first_v->prev;
3987 : : default_version_info = first_v;
3988 : 240 : while (default_version_info != NULL)
3989 : : {
3990 : 231 : if (is_function_default_version
3991 : 231 : (default_version_info->this_node->decl))
3992 : : break;
3993 : 66 : default_version_info = default_version_info->next;
3994 : : }
3995 : :
3996 : : /* If there is no default node, just return NULL. */
3997 : 174 : if (default_version_info == NULL)
3998 : : return NULL;
3999 : :
4000 : : /* Make default info the first node. */
4001 : 165 : if (first_v != default_version_info)
4002 : : {
4003 : 15 : default_version_info->prev->next = default_version_info->next;
4004 : 15 : if (default_version_info->next)
4005 : 0 : default_version_info->next->prev = default_version_info->prev;
4006 : 15 : first_v->prev = default_version_info;
4007 : 15 : default_version_info->next = first_v;
4008 : 15 : default_version_info->prev = NULL;
4009 : : }
4010 : :
4011 : 165 : default_node = default_version_info->this_node;
4012 : :
4013 : : #if defined (ASM_OUTPUT_TYPE_DIRECTIVE)
4014 : 165 : if (targetm.has_ifunc_p ())
4015 : : {
4016 : 165 : struct cgraph_function_version_info *it_v = NULL;
4017 : 165 : struct cgraph_node *dispatcher_node = NULL;
4018 : 165 : struct cgraph_function_version_info *dispatcher_version_info = NULL;
4019 : :
4020 : : /* Right now, the dispatching is done via ifunc. */
4021 : 165 : dispatch_decl = make_dispatcher_decl (default_node->decl);
4022 : 165 : TREE_NOTHROW (dispatch_decl) = TREE_NOTHROW (fn);
4023 : :
4024 : 165 : dispatcher_node = cgraph_node::get_create (dispatch_decl);
4025 : 165 : gcc_assert (dispatcher_node != NULL);
4026 : 165 : dispatcher_node->dispatcher_function = 1;
4027 : 165 : dispatcher_version_info
4028 : 165 : = dispatcher_node->insert_new_function_version ();
4029 : 165 : dispatcher_version_info->next = default_version_info;
4030 : 165 : dispatcher_node->definition = 1;
4031 : :
4032 : : /* Set the dispatcher for all the versions. */
4033 : 165 : it_v = default_version_info;
4034 : 1038 : while (it_v != NULL)
4035 : : {
4036 : 873 : it_v->dispatcher_resolver = dispatch_decl;
4037 : 873 : it_v = it_v->next;
4038 : : }
4039 : : }
4040 : : else
4041 : : #endif
4042 : : {
4043 : 0 : error_at (DECL_SOURCE_LOCATION (default_node->decl),
4044 : : "multiversioning needs %<ifunc%> which is not supported "
4045 : : "on this target");
4046 : : }
4047 : :
4048 : : return dispatch_decl;
4049 : : }
4050 : :
4051 : : /* Make the resolver function decl to dispatch the versions of
4052 : : a multi-versioned function, DEFAULT_DECL. IFUNC_ALIAS_DECL is
4053 : : ifunc alias that will point to the created resolver. Create an
4054 : : empty basic block in the resolver and store the pointer in
4055 : : EMPTY_BB. Return the decl of the resolver function. */
4056 : :
4057 : : static tree
4058 : 162 : make_resolver_func (const tree default_decl,
4059 : : const tree ifunc_alias_decl,
4060 : : basic_block *empty_bb)
4061 : : {
4062 : 162 : tree decl, type, t;
4063 : :
4064 : : /* Create resolver function name based on default_decl. */
4065 : 162 : tree decl_name = clone_function_name (default_decl, "resolver");
4066 : 162 : const char *resolver_name = IDENTIFIER_POINTER (decl_name);
4067 : :
4068 : : /* The resolver function should return a (void *). */
4069 : 162 : type = build_function_type_list (ptr_type_node, NULL_TREE);
4070 : :
4071 : 162 : decl = build_fn_decl (resolver_name, type);
4072 : 162 : SET_DECL_ASSEMBLER_NAME (decl, decl_name);
4073 : :
4074 : 162 : DECL_NAME (decl) = decl_name;
4075 : 162 : TREE_USED (decl) = 1;
4076 : 162 : DECL_ARTIFICIAL (decl) = 1;
4077 : 162 : DECL_IGNORED_P (decl) = 1;
4078 : 162 : TREE_PUBLIC (decl) = 0;
4079 : 162 : DECL_UNINLINABLE (decl) = 1;
4080 : :
4081 : : /* Resolver is not external, body is generated. */
4082 : 162 : DECL_EXTERNAL (decl) = 0;
4083 : 162 : DECL_EXTERNAL (ifunc_alias_decl) = 0;
4084 : :
4085 : 162 : DECL_CONTEXT (decl) = NULL_TREE;
4086 : 162 : DECL_INITIAL (decl) = make_node (BLOCK);
4087 : 162 : DECL_STATIC_CONSTRUCTOR (decl) = 0;
4088 : :
4089 : 162 : if (DECL_COMDAT_GROUP (default_decl)
4090 : 162 : || TREE_PUBLIC (default_decl))
4091 : : {
4092 : : /* In this case, each translation unit with a call to this
4093 : : versioned function will put out a resolver. Ensure it
4094 : : is comdat to keep just one copy. */
4095 : 138 : DECL_COMDAT (decl) = 1;
4096 : 138 : make_decl_one_only (decl, DECL_ASSEMBLER_NAME (decl));
4097 : : }
4098 : : else
4099 : 24 : TREE_PUBLIC (ifunc_alias_decl) = 0;
4100 : :
4101 : : /* Build result decl and add to function_decl. */
4102 : 162 : t = build_decl (UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE, ptr_type_node);
4103 : 162 : DECL_CONTEXT (t) = decl;
4104 : 162 : DECL_ARTIFICIAL (t) = 1;
4105 : 162 : DECL_IGNORED_P (t) = 1;
4106 : 162 : DECL_RESULT (decl) = t;
4107 : :
4108 : 162 : gimplify_function_tree (decl);
4109 : 162 : push_cfun (DECL_STRUCT_FUNCTION (decl));
4110 : 162 : *empty_bb = init_lowered_empty_function (decl, false,
4111 : : profile_count::uninitialized ());
4112 : :
4113 : 162 : cgraph_node::add_new_function (decl, true);
4114 : 162 : symtab->call_cgraph_insertion_hooks (cgraph_node::get_create (decl));
4115 : :
4116 : 162 : pop_cfun ();
4117 : :
4118 : 162 : gcc_assert (ifunc_alias_decl != NULL);
4119 : : /* Mark ifunc_alias_decl as "ifunc" with resolver as resolver_name. */
4120 : 162 : DECL_ATTRIBUTES (ifunc_alias_decl)
4121 : 162 : = make_attribute ("ifunc", resolver_name,
4122 : 162 : DECL_ATTRIBUTES (ifunc_alias_decl));
4123 : :
4124 : : /* Create the alias for dispatch to resolver here. */
4125 : 162 : cgraph_node::create_same_body_alias (ifunc_alias_decl, decl);
4126 : 162 : return decl;
4127 : : }
4128 : :
4129 : : /* Generate the dispatching code body to dispatch multi-versioned function
4130 : : DECL. The target hook is called to process the "target" attributes and
4131 : : provide the code to dispatch the right function at run-time. NODE points
4132 : : to the dispatcher decl whose body will be created. */
4133 : :
4134 : : tree
4135 : 162 : ix86_generate_version_dispatcher_body (void *node_p)
4136 : : {
4137 : 162 : tree resolver_decl;
4138 : 162 : basic_block empty_bb;
4139 : 162 : tree default_ver_decl;
4140 : 162 : struct cgraph_node *versn;
4141 : 162 : struct cgraph_node *node;
4142 : :
4143 : 162 : struct cgraph_function_version_info *node_version_info = NULL;
4144 : 162 : struct cgraph_function_version_info *versn_info = NULL;
4145 : :
4146 : 162 : node = (cgraph_node *)node_p;
4147 : :
4148 : 162 : node_version_info = node->function_version ();
4149 : 162 : gcc_assert (node->dispatcher_function
4150 : : && node_version_info != NULL);
4151 : :
4152 : 162 : if (node_version_info->dispatcher_resolver)
4153 : : return node_version_info->dispatcher_resolver;
4154 : :
4155 : : /* The first version in the chain corresponds to the default version. */
4156 : 162 : default_ver_decl = node_version_info->next->this_node->decl;
4157 : :
4158 : : /* node is going to be an alias, so remove the finalized bit. */
4159 : 162 : node->definition = false;
4160 : :
4161 : 162 : resolver_decl = make_resolver_func (default_ver_decl,
4162 : : node->decl, &empty_bb);
4163 : :
4164 : 162 : node_version_info->dispatcher_resolver = resolver_decl;
4165 : :
4166 : 162 : push_cfun (DECL_STRUCT_FUNCTION (resolver_decl));
4167 : :
4168 : 162 : auto_vec<tree, 2> fn_ver_vec;
4169 : :
4170 : 1029 : for (versn_info = node_version_info->next; versn_info;
4171 : 867 : versn_info = versn_info->next)
4172 : : {
4173 : 867 : versn = versn_info->this_node;
4174 : : /* Check for virtual functions here again, as by this time it should
4175 : : have been determined if this function needs a vtable index or
4176 : : not. This happens for methods in derived classes that override
4177 : : virtual methods in base classes but are not explicitly marked as
4178 : : virtual. */
4179 : 867 : if (DECL_VINDEX (versn->decl))
4180 : 0 : sorry ("virtual function multiversioning not supported");
4181 : :
4182 : 867 : fn_ver_vec.safe_push (versn->decl);
4183 : : }
4184 : :
4185 : 162 : dispatch_function_versions (resolver_decl, &fn_ver_vec, &empty_bb);
4186 : 162 : cgraph_edge::rebuild_edges ();
4187 : 162 : pop_cfun ();
4188 : 162 : return resolver_decl;
4189 : 162 : }
4190 : :
4191 : :
|