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 : 25246 : 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 : 1157144 : xlogue_layout::xlogue_layout (HOST_WIDE_INT stack_align_off_in, bool hfp)
216 : 1157144 : : m_hfp (hfp) , m_nregs (hfp ? 17 : 18),
217 : 1157144 : m_stack_align_off_in (stack_align_off_in)
218 : : {
219 : 1157144 : HOST_WIDE_INT offset = stack_align_off_in;
220 : 1157144 : unsigned i, j;
221 : :
222 : 21985736 : for (i = j = 0; i < MAX_REGS; ++i)
223 : : {
224 : 20828592 : unsigned regno = REG_ORDER[i];
225 : :
226 : 20828592 : if (regno == BP_REG && hfp)
227 : 578572 : continue;
228 : 20250020 : if (SSE_REGNO_P (regno))
229 : : {
230 : 11571440 : offset += 16;
231 : : /* Verify that SSE regs are always aligned. */
232 : 11571440 : gcc_assert (!((stack_align_off_in + offset) & 15));
233 : : }
234 : : else
235 : 8678580 : offset += 8;
236 : :
237 : 20250020 : m_regs[j].regno = regno;
238 : 20250020 : m_regs[j++].offset = offset - STUB_INDEX_OFFSET;
239 : : }
240 : 1157144 : gcc_assert (j == m_nregs);
241 : 1157144 : }
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 : 6491135 : scalar_chain::scalar_chain (enum machine_mode smode_, enum machine_mode vmode_)
283 : : {
284 : 6491135 : smode = smode_;
285 : 6491135 : vmode = vmode_;
286 : :
287 : 6491135 : chain_id = ++max_id;
288 : :
289 : 6491135 : if (dump_file)
290 : 136 : fprintf (dump_file, "Created a new instruction chain #%d\n", chain_id);
291 : :
292 : 6491135 : bitmap_obstack_initialize (NULL);
293 : 6491135 : insns = BITMAP_ALLOC (NULL);
294 : 6491135 : defs = BITMAP_ALLOC (NULL);
295 : 6491135 : defs_conv = BITMAP_ALLOC (NULL);
296 : 6491135 : insns_conv = BITMAP_ALLOC (NULL);
297 : 6491135 : queue = NULL;
298 : :
299 : 6491135 : cost_sse_integer = 0;
300 : 6491135 : weighted_cost_sse_integer = 0 ;
301 : 6491135 : max_visits = x86_stv_max_visits;
302 : 6491135 : }
303 : :
304 : : /* Free chain's data. */
305 : :
306 : 6491135 : scalar_chain::~scalar_chain ()
307 : : {
308 : 6491135 : BITMAP_FREE (insns);
309 : 6491135 : BITMAP_FREE (defs);
310 : 6491135 : BITMAP_FREE (defs_conv);
311 : 6491135 : BITMAP_FREE (insns_conv);
312 : 6491135 : bitmap_obstack_release (NULL);
313 : 6491135 : }
314 : :
315 : : /* Add instruction into chains' queue. */
316 : :
317 : : void
318 : 8221892 : scalar_chain::add_to_queue (unsigned insn_uid)
319 : : {
320 : 8221892 : if (!bitmap_set_bit (queue, insn_uid))
321 : : return;
322 : :
323 : 6332724 : if (dump_file)
324 : 141 : fprintf (dump_file, " Adding insn %d into chain's #%d queue\n",
325 : : insn_uid, chain_id);
326 : : }
327 : :
328 : : /* For DImode conversion, mark register defined by DEF as requiring
329 : : conversion. */
330 : :
331 : : void
332 : 9588392 : scalar_chain::mark_dual_mode_def (df_ref def)
333 : : {
334 : 9588392 : gcc_assert (DF_REF_REG_DEF_P (def));
335 : :
336 : : /* Record the def/insn pair so we can later efficiently iterate over
337 : : the defs to convert on insns not in the chain. */
338 : 9588392 : bool reg_new = bitmap_set_bit (defs_conv, DF_REF_REGNO (def));
339 : 9588392 : basic_block bb = BLOCK_FOR_INSN (DF_REF_INSN (def));
340 : 9588392 : profile_count entry_count = ENTRY_BLOCK_PTR_FOR_FN (cfun)->count;
341 : 9588392 : bool speed_p = optimize_bb_for_speed_p (bb);
342 : 9588392 : int cost = 0;
343 : :
344 : 9588392 : if (!bitmap_bit_p (insns, DF_REF_INSN_UID (def)))
345 : : {
346 : 2779331 : if (!bitmap_set_bit (insns_conv, DF_REF_INSN_UID (def))
347 : 2779331 : && !reg_new)
348 : 1463540 : return;
349 : :
350 : : /* Cost integer to sse moves. */
351 : 2516970 : if (speed_p)
352 : 2235943 : cost = COSTS_N_INSNS (ix86_cost->integer_to_sse) / 2;
353 : 281027 : else if (TARGET_64BIT || smode == SImode)
354 : : cost = COSTS_N_BYTES (4);
355 : : /* vmovd (4 bytes) + vpinsrd (6 bytes). */
356 : 18635 : else if (TARGET_SSE4_1)
357 : : cost = COSTS_N_BYTES (10);
358 : : /* movd (4 bytes) + movd (4 bytes) + unpckldq (4 bytes). */
359 : : else
360 : 8124852 : cost = COSTS_N_BYTES (12);
361 : : }
362 : : else
363 : : {
364 : 6809061 : if (!reg_new)
365 : : return;
366 : :
367 : : /* Cost sse to integer moves. */
368 : 5607882 : if (speed_p)
369 : 5049258 : cost = COSTS_N_INSNS (ix86_cost->sse_to_integer) / 2;
370 : 558624 : else if (TARGET_64BIT || smode == SImode)
371 : : cost = COSTS_N_BYTES (4);
372 : : /* vmovd (4 bytes) + vpextrd (6 bytes). */
373 : 3017 : else if (TARGET_SSE4_1)
374 : : cost = COSTS_N_BYTES (10);
375 : : /* movd (4 bytes) + psrlq (5 bytes) + movd (4 bytes). */
376 : : else
377 : 8124852 : cost = COSTS_N_BYTES (13);
378 : : }
379 : :
380 : 8124852 : if (speed_p)
381 : 7285201 : weighted_cost_sse_integer += bb->count.to_sreal_scale (entry_count) * cost;
382 : :
383 : 8124852 : cost_sse_integer += cost;
384 : :
385 : 8124852 : if (dump_file)
386 : 240 : fprintf (dump_file,
387 : : " Mark r%d def in insn %d as requiring both modes in chain #%d\n",
388 : 240 : DF_REF_REGNO (def), DF_REF_INSN_UID (def), chain_id);
389 : : }
390 : :
391 : : /* Check REF's chain to add new insns into a queue
392 : : and find registers requiring conversion. Return true if OK, false
393 : : if the analysis was aborted. */
394 : :
395 : : bool
396 : 18102871 : scalar_chain::analyze_register_chain (bitmap candidates, df_ref ref,
397 : : bitmap disallowed)
398 : : {
399 : 18102871 : df_link *chain;
400 : 18102871 : bool mark_def = false;
401 : :
402 : 18102871 : gcc_checking_assert (bitmap_bit_p (insns, DF_REF_INSN_UID (ref)));
403 : :
404 : 62275223 : for (chain = DF_REF_CHAIN (ref); chain; chain = chain->next)
405 : : {
406 : 44172861 : unsigned uid = DF_REF_INSN_UID (chain->ref);
407 : :
408 : 44172861 : if (!NONDEBUG_INSN_P (DF_REF_INSN (chain->ref)))
409 : 7690796 : continue;
410 : :
411 : 36482065 : if (--max_visits == 0)
412 : : return false;
413 : :
414 : 36481556 : if (!DF_REF_REG_MEM_P (chain->ref))
415 : : {
416 : 30472138 : if (bitmap_bit_p (insns, uid))
417 : 9633856 : continue;
418 : :
419 : 20838282 : if (bitmap_bit_p (candidates, uid))
420 : : {
421 : 8221892 : add_to_queue (uid);
422 : 8221892 : continue;
423 : : }
424 : :
425 : : /* If we run into parts of an aborted chain discovery abort. */
426 : 12616390 : if (bitmap_bit_p (disallowed, uid))
427 : : return false;
428 : : }
429 : :
430 : 18625808 : if (DF_REF_REG_DEF_P (chain->ref))
431 : : {
432 : 2779331 : if (dump_file)
433 : 125 : fprintf (dump_file, " r%d def in insn %d isn't convertible\n",
434 : : DF_REF_REGNO (chain->ref), uid);
435 : 2779331 : mark_dual_mode_def (chain->ref);
436 : : }
437 : : else
438 : : {
439 : 15846477 : if (dump_file)
440 : 524 : fprintf (dump_file, " r%d use in insn %d isn't convertible\n",
441 : : DF_REF_REGNO (chain->ref), uid);
442 : : mark_def = true;
443 : : }
444 : : }
445 : :
446 : 18102362 : if (mark_def)
447 : 6809061 : mark_dual_mode_def (ref);
448 : :
449 : : return true;
450 : : }
451 : :
452 : : /* Check whether X is a convertible *concatditi_? variant. X is known
453 : : to be any_or_plus:TI, i.e. PLUS:TI, IOR:TI or XOR:TI. */
454 : :
455 : : static bool
456 : 27953 : timode_concatdi_p (rtx x)
457 : : {
458 : 27953 : rtx op0 = XEXP (x, 0);
459 : 27953 : rtx op1 = XEXP (x, 1);
460 : :
461 : 27953 : if (GET_CODE (op1) == ASHIFT)
462 : 961 : std::swap (op0, op1);
463 : :
464 : 27953 : return GET_CODE (op0) == ASHIFT
465 : 18653 : && GET_CODE (XEXP (op0, 0)) == ZERO_EXTEND
466 : 18653 : && GET_MODE (XEXP (XEXP (op0, 0), 0)) == DImode
467 : 18653 : && REG_P (XEXP (XEXP (op0, 0), 0))
468 : 18522 : && CONST_INT_P (XEXP (op0, 1))
469 : 18522 : && INTVAL (XEXP (op0, 1)) == 64
470 : 18522 : && GET_CODE (op1) == ZERO_EXTEND
471 : 17561 : && GET_MODE (XEXP (op1, 0)) == DImode
472 : 45514 : && REG_P (XEXP (op1, 0));
473 : : }
474 : :
475 : :
476 : : /* Add instruction into a chain. Return true if OK, false if the search
477 : : was aborted. */
478 : :
479 : : bool
480 : 12823859 : scalar_chain::add_insn (bitmap candidates, unsigned int insn_uid,
481 : : bitmap disallowed)
482 : : {
483 : 12823859 : if (!bitmap_set_bit (insns, insn_uid))
484 : : return true;
485 : :
486 : 12823859 : if (dump_file)
487 : 277 : fprintf (dump_file, " Adding insn %d to chain #%d\n", insn_uid, chain_id);
488 : :
489 : 12823859 : rtx_insn *insn = DF_INSN_UID_GET (insn_uid)->insn;
490 : 12823859 : rtx def_set = single_set (insn);
491 : 12823859 : if (def_set && REG_P (SET_DEST (def_set))
492 : 22741874 : && !HARD_REGISTER_P (SET_DEST (def_set)))
493 : 9918007 : bitmap_set_bit (defs, REGNO (SET_DEST (def_set)));
494 : :
495 : : /* ??? The following is quadratic since analyze_register_chain
496 : : iterates over all refs to look for dual-mode regs. Instead this
497 : : should be done separately for all regs mentioned in the chain once. */
498 : 12823859 : df_ref ref;
499 : 26215761 : for (ref = DF_INSN_UID_DEFS (insn_uid); ref; ref = DF_REF_NEXT_LOC (ref))
500 : 13392344 : if (!HARD_REGISTER_P (DF_REF_REG (ref)))
501 : 9918007 : if (!analyze_register_chain (candidates, ref, disallowed))
502 : : return false;
503 : :
504 : : /* The operand(s) of VEC_SELECT, ZERO_EXTEND and similar ops don't need
505 : : to be converted/convertible. */
506 : 12823417 : if (def_set)
507 : 12823417 : switch (GET_CODE (SET_SRC (def_set)))
508 : : {
509 : : case VEC_SELECT:
510 : : return true;
511 : 121 : case ZERO_EXTEND:
512 : 121 : if (GET_MODE (XEXP (SET_SRC (def_set), 0)) == DImode)
513 : : return true;
514 : : break;
515 : 2396428 : case PLUS:
516 : 2396428 : case IOR:
517 : 2396428 : case XOR:
518 : 2396428 : if (smode == TImode && timode_concatdi_p (SET_SRC (def_set)))
519 : : return true;
520 : : break;
521 : : default:
522 : : break;
523 : : }
524 : :
525 : 28076849 : for (ref = DF_INSN_UID_USES (insn_uid); ref; ref = DF_REF_NEXT_LOC (ref))
526 : 15290029 : if (!DF_REF_REG_MEM_P (ref))
527 : 8184864 : if (!analyze_register_chain (candidates, ref, disallowed))
528 : : return false;
529 : :
530 : : return true;
531 : : }
532 : :
533 : : /* Build new chain starting from insn INSN_UID recursively
534 : : adding all dependent uses and definitions. Return true if OK, false
535 : : if the chain discovery was aborted. */
536 : :
537 : : bool
538 : 6491135 : scalar_chain::build (bitmap candidates, unsigned insn_uid, bitmap disallowed)
539 : : {
540 : 6491135 : queue = BITMAP_ALLOC (NULL);
541 : 6491135 : bitmap_set_bit (queue, insn_uid);
542 : :
543 : 6491135 : if (dump_file)
544 : 136 : fprintf (dump_file, "Building chain #%d...\n", chain_id);
545 : :
546 : 19314485 : while (!bitmap_empty_p (queue))
547 : : {
548 : 12823859 : insn_uid = bitmap_first_set_bit (queue);
549 : 12823859 : bitmap_clear_bit (queue, insn_uid);
550 : 12823859 : bitmap_clear_bit (candidates, insn_uid);
551 : 12823859 : if (!add_insn (candidates, insn_uid, disallowed))
552 : : {
553 : : /* If we aborted the search put sofar found insn on the set of
554 : : disallowed insns so that further searches reaching them also
555 : : abort and thus we abort the whole but yet undiscovered chain. */
556 : 509 : bitmap_ior_into (disallowed, insns);
557 : 509 : if (dump_file)
558 : 0 : fprintf (dump_file, "Aborted chain #%d discovery\n", chain_id);
559 : 509 : BITMAP_FREE (queue);
560 : 509 : return false;
561 : : }
562 : : }
563 : :
564 : 6490626 : if (dump_file)
565 : : {
566 : 136 : fprintf (dump_file, "Collected chain #%d...\n", chain_id);
567 : 136 : fprintf (dump_file, " insns: ");
568 : 136 : dump_bitmap (dump_file, insns);
569 : 136 : if (!bitmap_empty_p (defs_conv))
570 : : {
571 : 136 : bitmap_iterator bi;
572 : 136 : unsigned id;
573 : 136 : const char *comma = "";
574 : 136 : fprintf (dump_file, " defs to convert: ");
575 : 366 : EXECUTE_IF_SET_IN_BITMAP (defs_conv, 0, id, bi)
576 : : {
577 : 230 : fprintf (dump_file, "%sr%d", comma, id);
578 : 230 : comma = ", ";
579 : : }
580 : 136 : fprintf (dump_file, "\n");
581 : : }
582 : : }
583 : :
584 : 6490626 : BITMAP_FREE (queue);
585 : :
586 : 6490626 : return true;
587 : : }
588 : :
589 : : /* Return a cost of building a vector constant
590 : : instead of using a scalar one. */
591 : :
592 : : int
593 : 2725276 : general_scalar_chain::vector_const_cost (rtx exp, basic_block bb)
594 : : {
595 : 2725276 : gcc_assert (CONST_INT_P (exp));
596 : :
597 : 2725276 : if (standard_sse_constant_p (exp, vmode))
598 : 632690 : return ix86_cost->sse_op;
599 : 2092586 : if (optimize_bb_for_size_p (bb))
600 : : return COSTS_N_BYTES (8);
601 : : /* We have separate costs for SImode and DImode, use SImode costs
602 : : for smaller modes. */
603 : 2512284 : return COSTS_N_INSNS (ix86_cost->sse_load[smode == DImode ? 1 : 0]) / 2;
604 : : }
605 : :
606 : : /* Return true if it's cost profitable for chain conversion. */
607 : :
608 : : bool
609 : 6001209 : general_scalar_chain::compute_convert_gain ()
610 : : {
611 : 6001209 : bitmap_iterator bi;
612 : 6001209 : unsigned insn_uid;
613 : 6001209 : int gain = 0;
614 : 6001209 : sreal weighted_gain = 0;
615 : :
616 : 6001209 : if (dump_file)
617 : 136 : fprintf (dump_file, "Computing gain for chain #%d...\n", chain_id);
618 : :
619 : : /* SSE costs distinguish between SImode and DImode loads/stores, for
620 : : int costs factor in the number of GPRs involved. When supporting
621 : : smaller modes than SImode the int load/store costs need to be
622 : : adjusted as well. */
623 : 6001209 : unsigned sse_cost_idx = smode == DImode ? 1 : 0;
624 : 6001209 : int m = smode == DImode ? (TARGET_64BIT ? 1 : 2) : 1;
625 : :
626 : 17864154 : EXECUTE_IF_SET_IN_BITMAP (insns, 0, insn_uid, bi)
627 : : {
628 : 11862945 : rtx_insn *insn = DF_INSN_UID_GET (insn_uid)->insn;
629 : 11862945 : rtx def_set = single_set (insn);
630 : 11862945 : rtx src = SET_SRC (def_set);
631 : 11862945 : rtx dst = SET_DEST (def_set);
632 : 11862945 : basic_block bb = BLOCK_FOR_INSN (insn);
633 : 11862945 : int igain = 0;
634 : 11862945 : profile_count entry_count = ENTRY_BLOCK_PTR_FOR_FN (cfun)->count;
635 : 11862945 : bool speed_p = optimize_bb_for_speed_p (bb);
636 : 11862945 : sreal bb_freq = bb->count.to_sreal_scale (entry_count);
637 : :
638 : 11862945 : if (REG_P (src) && REG_P (dst))
639 : : {
640 : 963728 : if (!speed_p)
641 : : /* reg-reg move is 2 bytes, while SSE 3. */
642 : 197128 : igain += COSTS_N_BYTES (2 * m - 3);
643 : : else
644 : : /* Move costs are normalized to reg-reg move having cost 2. */
645 : 766600 : igain += COSTS_N_INSNS (2 * m - ix86_cost->xmm_move) / 2;
646 : : }
647 : 10899217 : else if (REG_P (src) && MEM_P (dst))
648 : : {
649 : 2315736 : if (!speed_p)
650 : : /* Integer load/store is 3+ bytes and SSE 4+. */
651 : 188318 : igain += COSTS_N_BYTES (3 * m - 4);
652 : : else
653 : 2127418 : igain
654 : 2127418 : += COSTS_N_INSNS (m * ix86_cost->int_store[2]
655 : : - ix86_cost->sse_store[sse_cost_idx]) / 2;
656 : : }
657 : 8583481 : else if (MEM_P (src) && REG_P (dst))
658 : : {
659 : 3870334 : if (!speed_p)
660 : 360880 : igain += COSTS_N_BYTES (3 * m - 4);
661 : : else
662 : 3509454 : igain += COSTS_N_INSNS (m * ix86_cost->int_load[2]
663 : : - ix86_cost->sse_load[sse_cost_idx]) / 2;
664 : : }
665 : : else
666 : : {
667 : : /* For operations on memory operands, include the overhead
668 : : of explicit load and store instructions. */
669 : 4713147 : if (MEM_P (dst))
670 : : {
671 : 70956 : if (!speed_p)
672 : : /* ??? This probably should account size difference
673 : : of SSE and integer load rather than full SSE load. */
674 : : igain -= COSTS_N_BYTES (8);
675 : : else
676 : : {
677 : 60980 : int cost = (m * (ix86_cost->int_load[2]
678 : 60980 : + ix86_cost->int_store[2])
679 : 60980 : - (ix86_cost->sse_load[sse_cost_idx] +
680 : 60980 : ix86_cost->sse_store[sse_cost_idx]));
681 : 60980 : igain += COSTS_N_INSNS (cost) / 2;
682 : : }
683 : : }
684 : :
685 : 4713147 : switch (GET_CODE (src))
686 : : {
687 : 488394 : case ASHIFT:
688 : 488394 : case ASHIFTRT:
689 : 488394 : case LSHIFTRT:
690 : 488394 : if (m == 2)
691 : : {
692 : 16960 : if (INTVAL (XEXP (src, 1)) >= 32)
693 : 11542 : igain += ix86_cost->add;
694 : : /* Gain for extend highpart case. */
695 : 5418 : else if (GET_CODE (XEXP (src, 0)) == ASHIFT)
696 : 0 : igain += ix86_cost->shift_const - ix86_cost->sse_op;
697 : : else
698 : 5418 : igain += ix86_cost->shift_const;
699 : : }
700 : :
701 : 488394 : igain += ix86_cost->shift_const - ix86_cost->sse_op;
702 : :
703 : 488394 : if (CONST_INT_P (XEXP (src, 0)))
704 : 0 : igain -= vector_const_cost (XEXP (src, 0), bb);
705 : : break;
706 : :
707 : 3814 : case ROTATE:
708 : 3814 : case ROTATERT:
709 : 3814 : igain += m * ix86_cost->shift_const;
710 : 3814 : if (TARGET_AVX512VL)
711 : 204 : igain -= ix86_cost->sse_op;
712 : 3610 : else if (smode == DImode)
713 : : {
714 : 606 : int bits = INTVAL (XEXP (src, 1));
715 : 606 : if ((bits & 0x0f) == 0)
716 : 122 : igain -= ix86_cost->sse_op;
717 : 484 : else if ((bits & 0x07) == 0)
718 : 27 : igain -= 2 * ix86_cost->sse_op;
719 : : else
720 : 457 : igain -= 3 * ix86_cost->sse_op;
721 : : }
722 : 3004 : else if (INTVAL (XEXP (src, 1)) == 16)
723 : 241 : igain -= ix86_cost->sse_op;
724 : : else
725 : 2763 : igain -= 2 * ix86_cost->sse_op;
726 : : break;
727 : :
728 : 2903466 : case AND:
729 : 2903466 : case IOR:
730 : 2903466 : case XOR:
731 : 2903466 : case PLUS:
732 : 2903466 : case MINUS:
733 : 2903466 : igain += m * ix86_cost->add - ix86_cost->sse_op;
734 : : /* Additional gain for andnot for targets without BMI. */
735 : 2903466 : if (GET_CODE (XEXP (src, 0)) == NOT
736 : 3599 : && !TARGET_BMI)
737 : 3590 : igain += m * ix86_cost->add;
738 : :
739 : 2903466 : if (CONST_INT_P (XEXP (src, 0)))
740 : 0 : igain -= vector_const_cost (XEXP (src, 0), bb);
741 : 2903466 : if (CONST_INT_P (XEXP (src, 1)))
742 : 1720262 : igain -= vector_const_cost (XEXP (src, 1), bb);
743 : 2903466 : if (MEM_P (XEXP (src, 1)))
744 : : {
745 : 96628 : if (!speed_p)
746 : 19979 : igain -= COSTS_N_BYTES (m == 2 ? 3 : 5);
747 : : else
748 : 86634 : igain += COSTS_N_INSNS
749 : : (m * ix86_cost->int_load[2]
750 : : - ix86_cost->sse_load[sse_cost_idx]) / 2;
751 : : }
752 : : break;
753 : :
754 : 51078 : case NEG:
755 : 51078 : case NOT:
756 : 51078 : igain -= ix86_cost->sse_op + COSTS_N_INSNS (1);
757 : :
758 : 51078 : if (GET_CODE (XEXP (src, 0)) != ABS)
759 : : {
760 : 51078 : igain += m * ix86_cost->add;
761 : 51078 : break;
762 : : }
763 : : /* FALLTHRU */
764 : :
765 : 1010 : case ABS:
766 : 1010 : case SMAX:
767 : 1010 : case SMIN:
768 : 1010 : case UMAX:
769 : 1010 : case UMIN:
770 : : /* We do not have any conditional move cost, estimate it as a
771 : : reg-reg move. Comparisons are costed as adds. */
772 : 1010 : igain += m * (COSTS_N_INSNS (2) + ix86_cost->add);
773 : : /* Integer SSE ops are all costed the same. */
774 : 1010 : igain -= ix86_cost->sse_op;
775 : 1010 : break;
776 : :
777 : 0 : case COMPARE:
778 : 0 : if (XEXP (src, 1) != const0_rtx)
779 : : {
780 : : /* cmp vs. pxor;pshufd;ptest. */
781 : 0 : igain += COSTS_N_INSNS (m - 3);
782 : : }
783 : 0 : else if (GET_CODE (XEXP (src, 0)) != AND)
784 : : {
785 : : /* test vs. pshufd;ptest. */
786 : 0 : igain += COSTS_N_INSNS (m - 2);
787 : : }
788 : 0 : else if (GET_CODE (XEXP (XEXP (src, 0), 0)) != NOT)
789 : : {
790 : : /* and;test vs. pshufd;ptest. */
791 : 0 : igain += COSTS_N_INSNS (2 * m - 2);
792 : : }
793 : 0 : else if (TARGET_BMI)
794 : : {
795 : : /* andn;test vs. pandn;pshufd;ptest. */
796 : 0 : igain += COSTS_N_INSNS (2 * m - 3);
797 : : }
798 : : else
799 : : {
800 : : /* not;and;test vs. pandn;pshufd;ptest. */
801 : 0 : igain += COSTS_N_INSNS (3 * m - 3);
802 : : }
803 : : break;
804 : :
805 : 1231793 : case CONST_INT:
806 : 1231793 : if (REG_P (dst))
807 : : {
808 : 1231793 : if (!speed_p)
809 : : {
810 : : /* xor (2 bytes) vs. xorps (3 bytes). */
811 : 226779 : if (src == const0_rtx)
812 : 122491 : igain -= COSTS_N_BYTES (1);
813 : : /* movdi_internal vs. movv2di_internal. */
814 : : /* => mov (5 bytes) vs. movaps (7 bytes). */
815 : 104288 : else if (x86_64_immediate_operand (src, SImode))
816 : 93138 : igain -= COSTS_N_BYTES (2);
817 : : else
818 : : /* ??? Larger immediate constants are placed in the
819 : : constant pool, where the size benefit/impact of
820 : : STV conversion is affected by whether and how
821 : : often each constant pool entry is shared/reused.
822 : : The value below is empirically derived from the
823 : : CSiBE benchmark (and the optimal value may drift
824 : : over time). */
825 : : igain += COSTS_N_BYTES (0);
826 : : }
827 : : else
828 : : {
829 : : /* DImode can be immediate for TARGET_64BIT
830 : : and SImode always. */
831 : 1005014 : igain += m * COSTS_N_INSNS (1);
832 : 1005014 : igain -= vector_const_cost (src, bb);
833 : : }
834 : : }
835 : 0 : else if (MEM_P (dst))
836 : : {
837 : 0 : igain += (m * ix86_cost->int_store[2]
838 : 0 : - ix86_cost->sse_store[sse_cost_idx]);
839 : 0 : igain -= vector_const_cost (src, bb);
840 : : }
841 : : break;
842 : :
843 : 33592 : case VEC_SELECT:
844 : 33592 : if (XVECEXP (XEXP (src, 1), 0, 0) == const0_rtx)
845 : : {
846 : : // movd (4 bytes) replaced with movdqa (4 bytes).
847 : 25422 : if (!!speed_p)
848 : 23660 : igain += COSTS_N_INSNS (ix86_cost->sse_to_integer
849 : : - ix86_cost->xmm_move) / 2;
850 : : }
851 : : else
852 : : {
853 : : // pshufd; movd replaced with pshufd.
854 : 8170 : if (!speed_p)
855 : 637 : igain += COSTS_N_BYTES (4);
856 : : else
857 : 7533 : igain += ix86_cost->sse_to_integer;
858 : : }
859 : : break;
860 : :
861 : 0 : default:
862 : 0 : gcc_unreachable ();
863 : : }
864 : : }
865 : :
866 : 11861183 : if (speed_p)
867 : 10592163 : weighted_gain += bb_freq * igain;
868 : 11862945 : gain += igain;
869 : :
870 : 11862945 : if (igain != 0 && dump_file)
871 : : {
872 : 93 : fprintf (dump_file, " Instruction gain %d with bb_freq %.2f for",
873 : : igain, bb_freq.to_double ());
874 : 93 : dump_insn_slim (dump_file, insn);
875 : : }
876 : : }
877 : :
878 : 6001209 : if (dump_file)
879 : : {
880 : 136 : fprintf (dump_file, " Instruction conversion gain: %d, \n",
881 : : gain);
882 : 136 : fprintf (dump_file, " Registers conversion cost: %d\n",
883 : : cost_sse_integer);
884 : 136 : fprintf (dump_file, " Weighted instruction conversion gain: %.2f, \n",
885 : : weighted_gain.to_double ());
886 : 136 : fprintf (dump_file, " Weighted registers conversion cost: %.2f\n",
887 : : weighted_cost_sse_integer.to_double ());
888 : : }
889 : :
890 : 6001209 : if (weighted_gain != weighted_cost_sse_integer)
891 : 4874637 : return weighted_gain > weighted_cost_sse_integer;
892 : : else
893 : 1126572 : return gain > cost_sse_integer;;
894 : : }
895 : :
896 : : /* Insert generated conversion instruction sequence INSNS
897 : : after instruction AFTER. New BB may be required in case
898 : : instruction has EH region attached. */
899 : :
900 : : void
901 : 30489 : scalar_chain::emit_conversion_insns (rtx insns, rtx_insn *after)
902 : : {
903 : 30489 : if (!control_flow_insn_p (after))
904 : : {
905 : 30265 : emit_insn_after (insns, after);
906 : 30265 : return;
907 : : }
908 : :
909 : 224 : basic_block bb = BLOCK_FOR_INSN (after);
910 : 224 : edge e = find_fallthru_edge (bb->succs);
911 : 224 : gcc_assert (e);
912 : :
913 : 224 : basic_block new_bb = split_edge (e);
914 : 224 : emit_insn_after (insns, BB_HEAD (new_bb));
915 : : }
916 : :
917 : : } // anon namespace
918 : :
919 : : /* Generate the canonical SET_SRC to move GPR to a VMODE vector register,
920 : : zeroing the upper parts. */
921 : :
922 : : static rtx
923 : 173254 : gen_gpr_to_xmm_move_src (enum machine_mode vmode, rtx gpr)
924 : : {
925 : 346508 : switch (GET_MODE_NUNITS (vmode))
926 : : {
927 : 13 : case 1:
928 : 13 : return gen_rtx_SUBREG (vmode, gpr, 0);
929 : 172663 : case 2:
930 : 345326 : return gen_rtx_VEC_CONCAT (vmode, gpr,
931 : : CONST0_RTX (GET_MODE_INNER (vmode)));
932 : 578 : default:
933 : 578 : return gen_rtx_VEC_MERGE (vmode, gen_rtx_VEC_DUPLICATE (vmode, gpr),
934 : : CONST0_RTX (vmode), GEN_INT (HOST_WIDE_INT_1U));
935 : : }
936 : : }
937 : :
938 : : /* Make vector copies for all register REGNO definitions
939 : : and replace its uses in a chain. */
940 : :
941 : : void
942 : 8051 : scalar_chain::make_vector_copies (rtx_insn *insn, rtx reg)
943 : : {
944 : 8051 : rtx vreg = *defs_map.get (reg);
945 : :
946 : 8051 : start_sequence ();
947 : 8051 : if (!TARGET_INTER_UNIT_MOVES_TO_VEC)
948 : : {
949 : 0 : rtx tmp = assign_386_stack_local (smode, SLOT_STV_TEMP);
950 : 0 : if (smode == DImode && !TARGET_64BIT)
951 : : {
952 : 0 : emit_move_insn (adjust_address (tmp, SImode, 0),
953 : : gen_rtx_SUBREG (SImode, reg, 0));
954 : 0 : emit_move_insn (adjust_address (tmp, SImode, 4),
955 : : gen_rtx_SUBREG (SImode, reg, 4));
956 : : }
957 : : else
958 : 0 : emit_move_insn (copy_rtx (tmp), reg);
959 : 0 : emit_insn (gen_rtx_SET (gen_rtx_SUBREG (vmode, vreg, 0),
960 : : gen_gpr_to_xmm_move_src (vmode, tmp)));
961 : : }
962 : 8051 : else if (!TARGET_64BIT && smode == DImode)
963 : : {
964 : 7947 : if (TARGET_SSE4_1)
965 : : {
966 : 356 : emit_insn (gen_sse2_loadld (gen_rtx_SUBREG (V4SImode, vreg, 0),
967 : : CONST0_RTX (V4SImode),
968 : : gen_rtx_SUBREG (SImode, reg, 0)));
969 : 356 : emit_insn (gen_sse4_1_pinsrd (gen_rtx_SUBREG (V4SImode, vreg, 0),
970 : : gen_rtx_SUBREG (V4SImode, vreg, 0),
971 : : gen_rtx_SUBREG (SImode, reg, 4),
972 : : GEN_INT (2)));
973 : : }
974 : : else
975 : : {
976 : 7591 : rtx tmp = gen_reg_rtx (DImode);
977 : 7591 : emit_insn (gen_sse2_loadld (gen_rtx_SUBREG (V4SImode, vreg, 0),
978 : : CONST0_RTX (V4SImode),
979 : : gen_rtx_SUBREG (SImode, reg, 0)));
980 : 7591 : emit_insn (gen_sse2_loadld (gen_rtx_SUBREG (V4SImode, tmp, 0),
981 : : CONST0_RTX (V4SImode),
982 : : gen_rtx_SUBREG (SImode, reg, 4)));
983 : 7591 : emit_insn (gen_vec_interleave_lowv4si
984 : : (gen_rtx_SUBREG (V4SImode, vreg, 0),
985 : : gen_rtx_SUBREG (V4SImode, vreg, 0),
986 : : gen_rtx_SUBREG (V4SImode, tmp, 0)));
987 : : }
988 : : }
989 : : else
990 : 104 : emit_insn (gen_rtx_SET (gen_rtx_SUBREG (vmode, vreg, 0),
991 : : gen_gpr_to_xmm_move_src (vmode, reg)));
992 : 8051 : rtx_insn *seq = end_sequence ();
993 : 8051 : emit_conversion_insns (seq, insn);
994 : :
995 : 8051 : if (dump_file)
996 : 0 : fprintf (dump_file,
997 : : " Copied r%d to a vector register r%d for insn %d\n",
998 : 0 : REGNO (reg), REGNO (vreg), INSN_UID (insn));
999 : 8051 : }
1000 : :
1001 : : /* Copy the definition SRC of INSN inside the chain to DST for
1002 : : scalar uses outside of the chain. */
1003 : :
1004 : : void
1005 : 21676 : scalar_chain::convert_reg (rtx_insn *insn, rtx dst, rtx src)
1006 : : {
1007 : 21676 : start_sequence ();
1008 : 21676 : if (!TARGET_INTER_UNIT_MOVES_FROM_VEC)
1009 : : {
1010 : 0 : rtx tmp = assign_386_stack_local (smode, SLOT_STV_TEMP);
1011 : 0 : emit_move_insn (tmp, src);
1012 : 0 : if (!TARGET_64BIT && smode == DImode)
1013 : : {
1014 : 0 : emit_move_insn (gen_rtx_SUBREG (SImode, dst, 0),
1015 : : adjust_address (tmp, SImode, 0));
1016 : 0 : emit_move_insn (gen_rtx_SUBREG (SImode, dst, 4),
1017 : : adjust_address (tmp, SImode, 4));
1018 : : }
1019 : : else
1020 : 0 : emit_move_insn (dst, copy_rtx (tmp));
1021 : : }
1022 : 21676 : else if (!TARGET_64BIT && smode == DImode)
1023 : : {
1024 : 21285 : if (TARGET_SSE4_1)
1025 : : {
1026 : 0 : rtx tmp = gen_rtx_PARALLEL (VOIDmode,
1027 : : gen_rtvec (1, const0_rtx));
1028 : 0 : emit_insn
1029 : 0 : (gen_rtx_SET
1030 : : (gen_rtx_SUBREG (SImode, dst, 0),
1031 : : gen_rtx_VEC_SELECT (SImode,
1032 : : gen_rtx_SUBREG (V4SImode, src, 0),
1033 : : tmp)));
1034 : :
1035 : 0 : tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (1, const1_rtx));
1036 : 0 : emit_insn
1037 : 0 : (gen_rtx_SET
1038 : : (gen_rtx_SUBREG (SImode, dst, 4),
1039 : : gen_rtx_VEC_SELECT (SImode,
1040 : : gen_rtx_SUBREG (V4SImode, src, 0),
1041 : : tmp)));
1042 : : }
1043 : : else
1044 : : {
1045 : 21285 : rtx vcopy = gen_reg_rtx (V2DImode);
1046 : 21285 : emit_move_insn (vcopy, gen_rtx_SUBREG (V2DImode, src, 0));
1047 : 21285 : emit_move_insn (gen_rtx_SUBREG (SImode, dst, 0),
1048 : : gen_rtx_SUBREG (SImode, vcopy, 0));
1049 : 21285 : emit_move_insn (vcopy,
1050 : : gen_rtx_LSHIFTRT (V2DImode,
1051 : : vcopy, GEN_INT (32)));
1052 : 21285 : emit_move_insn (gen_rtx_SUBREG (SImode, dst, 4),
1053 : : gen_rtx_SUBREG (SImode, vcopy, 0));
1054 : : }
1055 : : }
1056 : : else
1057 : 391 : emit_move_insn (dst, src);
1058 : :
1059 : 21676 : rtx_insn *seq = end_sequence ();
1060 : 21676 : emit_conversion_insns (seq, insn);
1061 : :
1062 : 21676 : if (dump_file)
1063 : 0 : fprintf (dump_file,
1064 : : " Copied r%d to a scalar register r%d for insn %d\n",
1065 : 0 : REGNO (src), REGNO (dst), INSN_UID (insn));
1066 : 21676 : }
1067 : :
1068 : : /* Helper function to convert immediate constant X to vmode. */
1069 : : static rtx
1070 : 44266 : smode_convert_cst (rtx x, enum machine_mode vmode)
1071 : : {
1072 : : /* Prefer all ones vector in case of -1. */
1073 : 44266 : if (constm1_operand (x, GET_MODE (x)))
1074 : 905 : return CONSTM1_RTX (vmode);
1075 : :
1076 : 43361 : unsigned n = GET_MODE_NUNITS (vmode);
1077 : 43361 : rtx *v = XALLOCAVEC (rtx, n);
1078 : 43361 : v[0] = x;
1079 : 49156 : for (unsigned i = 1; i < n; ++i)
1080 : 5795 : v[i] = const0_rtx;
1081 : 43361 : return gen_rtx_CONST_VECTOR (vmode, gen_rtvec_v (n, v));
1082 : : }
1083 : :
1084 : : /* Convert operand OP in INSN. We should handle
1085 : : memory operands and uninitialized registers.
1086 : : All other register uses are converted during
1087 : : registers conversion. */
1088 : :
1089 : : void
1090 : 246704 : scalar_chain::convert_op (rtx *op, rtx_insn *insn)
1091 : : {
1092 : 246704 : rtx tmp;
1093 : :
1094 : 246704 : if (GET_MODE (*op) == V1TImode)
1095 : : return;
1096 : :
1097 : 246569 : *op = copy_rtx_if_shared (*op);
1098 : :
1099 : 246569 : if (GET_CODE (*op) == NOT
1100 : 246569 : || GET_CODE (*op) == ASHIFT)
1101 : : {
1102 : 3490 : convert_op (&XEXP (*op, 0), insn);
1103 : 3490 : PUT_MODE (*op, vmode);
1104 : : }
1105 : : else if (MEM_P (*op))
1106 : : {
1107 : 173150 : rtx_insn *movabs = NULL;
1108 : :
1109 : : /* Emit MOVABS to load from a 64-bit absolute address to a GPR. */
1110 : 173150 : if (!memory_operand (*op, GET_MODE (*op)))
1111 : : {
1112 : 0 : tmp = gen_reg_rtx (GET_MODE (*op));
1113 : 0 : movabs = emit_insn_before (gen_rtx_SET (tmp, *op), insn);
1114 : :
1115 : 0 : *op = tmp;
1116 : : }
1117 : :
1118 : 173150 : tmp = gen_rtx_SUBREG (vmode, gen_reg_rtx (GET_MODE (*op)), 0);
1119 : :
1120 : 173150 : rtx_insn *eh_insn
1121 : 173150 : = emit_insn_before (gen_rtx_SET (copy_rtx (tmp),
1122 : : gen_gpr_to_xmm_move_src (vmode, *op)),
1123 : 173150 : insn);
1124 : :
1125 : 173150 : if (cfun->can_throw_non_call_exceptions)
1126 : : {
1127 : : /* Handle REG_EH_REGION note. */
1128 : 169097 : rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
1129 : 169097 : if (note)
1130 : : {
1131 : 3753 : if (movabs)
1132 : 0 : eh_insn = movabs;
1133 : 3753 : control_flow_insns.safe_push (eh_insn);
1134 : 3753 : add_reg_note (eh_insn, REG_EH_REGION, XEXP (note, 0));
1135 : : }
1136 : : }
1137 : :
1138 : 173150 : *op = tmp;
1139 : :
1140 : 173150 : if (dump_file)
1141 : 0 : fprintf (dump_file, " Preloading operand for insn %d into r%d\n",
1142 : 0 : INSN_UID (insn), reg_or_subregno (tmp));
1143 : : }
1144 : : else if (REG_P (*op))
1145 : 63513 : *op = gen_rtx_SUBREG (vmode, *op, 0);
1146 : : else if (CONST_SCALAR_INT_P (*op))
1147 : : {
1148 : 6416 : rtx vec_cst = smode_convert_cst (*op, vmode);
1149 : :
1150 : 6416 : if (!standard_sse_constant_p (vec_cst, vmode))
1151 : : {
1152 : 2694 : start_sequence ();
1153 : 2694 : vec_cst = validize_mem (force_const_mem (vmode, vec_cst));
1154 : 2694 : rtx_insn *seq = end_sequence ();
1155 : 2694 : emit_insn_before (seq, insn);
1156 : : }
1157 : :
1158 : 6416 : tmp = gen_rtx_SUBREG (vmode, gen_reg_rtx (smode), 0);
1159 : :
1160 : 6416 : emit_insn_before (gen_move_insn (copy_rtx (tmp), vec_cst), insn);
1161 : 6416 : *op = tmp;
1162 : : }
1163 : : else
1164 : : {
1165 : 0 : gcc_assert (SUBREG_P (*op));
1166 : 0 : gcc_assert (GET_MODE (*op) == vmode);
1167 : : }
1168 : : }
1169 : :
1170 : : /* Convert CCZmode COMPARE to vector mode. */
1171 : :
1172 : : rtx
1173 : 6 : scalar_chain::convert_compare (rtx op1, rtx op2, rtx_insn *insn)
1174 : : {
1175 : 6 : rtx src, tmp;
1176 : :
1177 : : /* Handle any REG_EQUAL notes. */
1178 : 6 : tmp = find_reg_equal_equiv_note (insn);
1179 : 6 : if (tmp)
1180 : : {
1181 : 1 : if (GET_CODE (XEXP (tmp, 0)) == COMPARE
1182 : 1 : && GET_MODE (XEXP (tmp, 0)) == CCZmode
1183 : 1 : && REG_P (XEXP (XEXP (tmp, 0), 0)))
1184 : : {
1185 : 1 : rtx *op = &XEXP (XEXP (tmp, 0), 1);
1186 : 1 : if (CONST_SCALAR_INT_P (*op))
1187 : : {
1188 : 1 : if (constm1_operand (*op, GET_MODE (*op)))
1189 : 0 : *op = CONSTM1_RTX (vmode);
1190 : : else
1191 : : {
1192 : 1 : unsigned n = GET_MODE_NUNITS (vmode);
1193 : 1 : rtx *v = XALLOCAVEC (rtx, n);
1194 : 1 : v[0] = *op;
1195 : 1 : for (unsigned i = 1; i < n; ++i)
1196 : 0 : v[i] = const0_rtx;
1197 : 1 : *op = gen_rtx_CONST_VECTOR (vmode, gen_rtvec_v (n, v));
1198 : : }
1199 : : tmp = NULL_RTX;
1200 : : }
1201 : 0 : else if (REG_P (*op))
1202 : : tmp = NULL_RTX;
1203 : : }
1204 : :
1205 : : if (tmp)
1206 : 0 : remove_note (insn, tmp);
1207 : : }
1208 : :
1209 : : /* Comparison against anything other than zero, requires an XOR. */
1210 : 6 : if (op2 != const0_rtx)
1211 : : {
1212 : 4 : convert_op (&op1, insn);
1213 : 4 : convert_op (&op2, insn);
1214 : : /* If both operands are MEMs, explicitly load the OP1 into TMP. */
1215 : 4 : if (MEM_P (op1) && MEM_P (op2))
1216 : : {
1217 : 0 : tmp = gen_reg_rtx (vmode);
1218 : 0 : emit_insn_before (gen_rtx_SET (tmp, op1), insn);
1219 : 0 : src = tmp;
1220 : : }
1221 : : else
1222 : : src = op1;
1223 : 4 : src = gen_rtx_XOR (vmode, src, op2);
1224 : : }
1225 : 2 : else if (GET_CODE (op1) == AND
1226 : 0 : && GET_CODE (XEXP (op1, 0)) == NOT)
1227 : : {
1228 : 0 : rtx op11 = XEXP (XEXP (op1, 0), 0);
1229 : 0 : rtx op12 = XEXP (op1, 1);
1230 : 0 : convert_op (&op11, insn);
1231 : 0 : convert_op (&op12, insn);
1232 : 0 : if (!REG_P (op11))
1233 : : {
1234 : 0 : tmp = gen_reg_rtx (vmode);
1235 : 0 : emit_insn_before (gen_rtx_SET (tmp, op11), insn);
1236 : 0 : op11 = tmp;
1237 : : }
1238 : 0 : src = gen_rtx_AND (vmode, gen_rtx_NOT (vmode, op11), op12);
1239 : 0 : }
1240 : 2 : else if (GET_CODE (op1) == AND)
1241 : : {
1242 : 0 : rtx op11 = XEXP (op1, 0);
1243 : 0 : rtx op12 = XEXP (op1, 1);
1244 : 0 : convert_op (&op11, insn);
1245 : 0 : convert_op (&op12, insn);
1246 : 0 : if (!REG_P (op11))
1247 : : {
1248 : 0 : tmp = gen_reg_rtx (vmode);
1249 : 0 : emit_insn_before (gen_rtx_SET (tmp, op11), insn);
1250 : 0 : op11 = tmp;
1251 : : }
1252 : 0 : return gen_rtx_UNSPEC (CCZmode, gen_rtvec (2, op11, op12),
1253 : : UNSPEC_PTEST);
1254 : : }
1255 : : else
1256 : : {
1257 : 2 : convert_op (&op1, insn);
1258 : 2 : src = op1;
1259 : : }
1260 : :
1261 : 6 : if (!REG_P (src))
1262 : : {
1263 : 4 : tmp = gen_reg_rtx (vmode);
1264 : 4 : emit_insn_before (gen_rtx_SET (tmp, src), insn);
1265 : 4 : src = tmp;
1266 : : }
1267 : :
1268 : 6 : if (vmode == V2DImode)
1269 : : {
1270 : 0 : tmp = gen_reg_rtx (vmode);
1271 : 0 : emit_insn_before (gen_vec_interleave_lowv2di (tmp, src, src), insn);
1272 : 0 : src = tmp;
1273 : : }
1274 : 6 : else if (vmode == V4SImode)
1275 : : {
1276 : 0 : tmp = gen_reg_rtx (vmode);
1277 : 0 : emit_insn_before (gen_sse2_pshufd (tmp, src, const0_rtx), insn);
1278 : 0 : src = tmp;
1279 : : }
1280 : :
1281 : 6 : return gen_rtx_UNSPEC (CCZmode, gen_rtvec (2, src, src), UNSPEC_PTEST);
1282 : : }
1283 : :
1284 : : /* Helper function for converting INSN to vector mode. */
1285 : :
1286 : : void
1287 : 1364966 : scalar_chain::convert_insn_common (rtx_insn *insn)
1288 : : {
1289 : : /* Generate copies for out-of-chain uses of defs and adjust debug uses. */
1290 : 2082655 : for (df_ref ref = DF_INSN_DEFS (insn); ref; ref = DF_REF_NEXT_LOC (ref))
1291 : 717689 : if (bitmap_bit_p (defs_conv, DF_REF_REGNO (ref)))
1292 : : {
1293 : 23105 : df_link *use;
1294 : 44441 : for (use = DF_REF_CHAIN (ref); use; use = use->next)
1295 : 43012 : if (NONDEBUG_INSN_P (DF_REF_INSN (use->ref))
1296 : 43012 : && (DF_REF_REG_MEM_P (use->ref)
1297 : 38489 : || !bitmap_bit_p (insns, DF_REF_INSN_UID (use->ref))))
1298 : : break;
1299 : 23105 : if (use)
1300 : 21676 : convert_reg (insn, DF_REF_REG (ref),
1301 : 21676 : *defs_map.get (regno_reg_rtx [DF_REF_REGNO (ref)]));
1302 : 1429 : else if (MAY_HAVE_DEBUG_BIND_INSNS)
1303 : : {
1304 : : /* If we generated a scalar copy we can leave debug-insns
1305 : : as-is, if not, we have to adjust them. */
1306 : 1311 : auto_vec<rtx_insn *, 5> to_reset_debug_insns;
1307 : 3918 : for (use = DF_REF_CHAIN (ref); use; use = use->next)
1308 : 2607 : if (DEBUG_INSN_P (DF_REF_INSN (use->ref)))
1309 : : {
1310 : 845 : rtx_insn *debug_insn = DF_REF_INSN (use->ref);
1311 : : /* If there's a reaching definition outside of the
1312 : : chain we have to reset. */
1313 : 845 : df_link *def;
1314 : 2953 : for (def = DF_REF_CHAIN (use->ref); def; def = def->next)
1315 : 2292 : if (!bitmap_bit_p (insns, DF_REF_INSN_UID (def->ref)))
1316 : : break;
1317 : 845 : if (def)
1318 : 184 : to_reset_debug_insns.safe_push (debug_insn);
1319 : : else
1320 : : {
1321 : 661 : *DF_REF_REAL_LOC (use->ref)
1322 : 661 : = *defs_map.get (regno_reg_rtx [DF_REF_REGNO (ref)]);
1323 : 661 : df_insn_rescan (debug_insn);
1324 : : }
1325 : : }
1326 : : /* Have to do the reset outside of the DF_CHAIN walk to not
1327 : : disrupt it. */
1328 : 2806 : while (!to_reset_debug_insns.is_empty ())
1329 : : {
1330 : 184 : rtx_insn *debug_insn = to_reset_debug_insns.pop ();
1331 : 184 : INSN_VAR_LOCATION_LOC (debug_insn) = gen_rtx_UNKNOWN_VAR_LOC ();
1332 : 184 : df_insn_rescan_debug_internal (debug_insn);
1333 : : }
1334 : 1311 : }
1335 : : }
1336 : :
1337 : : /* Replace uses in this insn with the defs we use in the chain. */
1338 : 3413779 : for (df_ref ref = DF_INSN_USES (insn); ref; ref = DF_REF_NEXT_LOC (ref))
1339 : 2048813 : if (!DF_REF_REG_MEM_P (ref))
1340 : 728872 : if (rtx *vreg = defs_map.get (regno_reg_rtx[DF_REF_REGNO (ref)]))
1341 : : {
1342 : : /* Also update a corresponding REG_DEAD note. */
1343 : 35343 : rtx note = find_reg_note (insn, REG_DEAD, DF_REF_REG (ref));
1344 : 35343 : if (note)
1345 : 23432 : XEXP (note, 0) = *vreg;
1346 : 35343 : *DF_REF_REAL_LOC (ref) = *vreg;
1347 : : }
1348 : 1364966 : }
1349 : :
1350 : : /* Convert INSN which is an SImode or DImode rotation by a constant
1351 : : to vector mode. CODE is either ROTATE or ROTATERT with operands
1352 : : OP0 and OP1. Returns the SET_SRC of the last instruction in the
1353 : : resulting sequence, which is emitted before INSN. */
1354 : :
1355 : : rtx
1356 : 92 : general_scalar_chain::convert_rotate (enum rtx_code code, rtx op0, rtx op1,
1357 : : rtx_insn *insn)
1358 : : {
1359 : 92 : int bits = INTVAL (op1);
1360 : 92 : rtx pat, result;
1361 : :
1362 : 92 : convert_op (&op0, insn);
1363 : 92 : if (bits == 0)
1364 : 0 : return op0;
1365 : :
1366 : 92 : if (smode == DImode)
1367 : : {
1368 : 92 : if (code == ROTATE)
1369 : 45 : bits = 64 - bits;
1370 : 92 : if (bits == 32)
1371 : : {
1372 : 0 : rtx tmp1 = gen_reg_rtx (V4SImode);
1373 : 0 : pat = gen_sse2_pshufd (tmp1, gen_lowpart (V4SImode, op0),
1374 : : GEN_INT (225));
1375 : 0 : emit_insn_before (pat, insn);
1376 : 0 : result = gen_lowpart (V2DImode, tmp1);
1377 : : }
1378 : 92 : else if (TARGET_AVX512VL)
1379 : 0 : result = simplify_gen_binary (code, V2DImode, op0, op1);
1380 : 92 : else if (bits == 16 || bits == 48)
1381 : : {
1382 : 0 : rtx tmp1 = gen_reg_rtx (V8HImode);
1383 : 0 : pat = gen_sse2_pshuflw (tmp1, gen_lowpart (V8HImode, op0),
1384 : : GEN_INT (bits == 16 ? 57 : 147));
1385 : 0 : emit_insn_before (pat, insn);
1386 : 0 : result = gen_lowpart (V2DImode, tmp1);
1387 : : }
1388 : 92 : else if ((bits & 0x07) == 0)
1389 : : {
1390 : 0 : rtx tmp1 = gen_reg_rtx (V4SImode);
1391 : 0 : pat = gen_sse2_pshufd (tmp1, gen_lowpart (V4SImode, op0),
1392 : : GEN_INT (68));
1393 : 0 : emit_insn_before (pat, insn);
1394 : 0 : rtx tmp2 = gen_reg_rtx (V1TImode);
1395 : 0 : pat = gen_sse2_lshrv1ti3 (tmp2, gen_lowpart (V1TImode, tmp1),
1396 : : GEN_INT (bits));
1397 : 0 : emit_insn_before (pat, insn);
1398 : 0 : result = gen_lowpart (V2DImode, tmp2);
1399 : : }
1400 : : else
1401 : : {
1402 : 92 : rtx tmp1 = gen_reg_rtx (V4SImode);
1403 : 92 : pat = gen_sse2_pshufd (tmp1, gen_lowpart (V4SImode, op0),
1404 : : GEN_INT (20));
1405 : 92 : emit_insn_before (pat, insn);
1406 : 92 : rtx tmp2 = gen_reg_rtx (V2DImode);
1407 : 92 : pat = gen_lshrv2di3 (tmp2, gen_lowpart (V2DImode, tmp1),
1408 : : GEN_INT (bits & 31));
1409 : 92 : emit_insn_before (pat, insn);
1410 : 92 : rtx tmp3 = gen_reg_rtx (V4SImode);
1411 : 139 : pat = gen_sse2_pshufd (tmp3, gen_lowpart (V4SImode, tmp2),
1412 : : GEN_INT (bits > 32 ? 34 : 136));
1413 : 92 : emit_insn_before (pat, insn);
1414 : 92 : result = gen_lowpart (V2DImode, tmp3);
1415 : : }
1416 : : }
1417 : 0 : else if (bits == 16)
1418 : : {
1419 : 0 : rtx tmp1 = gen_reg_rtx (V8HImode);
1420 : 0 : pat = gen_sse2_pshuflw (tmp1, gen_lowpart (V8HImode, op0), GEN_INT (225));
1421 : 0 : emit_insn_before (pat, insn);
1422 : 0 : result = gen_lowpart (V4SImode, tmp1);
1423 : : }
1424 : 0 : else if (TARGET_AVX512VL)
1425 : 0 : result = simplify_gen_binary (code, V4SImode, op0, op1);
1426 : : else
1427 : : {
1428 : 0 : if (code == ROTATE)
1429 : 0 : bits = 32 - bits;
1430 : :
1431 : 0 : rtx tmp1 = gen_reg_rtx (V4SImode);
1432 : 0 : emit_insn_before (gen_sse2_pshufd (tmp1, op0, GEN_INT (224)), insn);
1433 : 0 : rtx tmp2 = gen_reg_rtx (V2DImode);
1434 : 0 : pat = gen_lshrv2di3 (tmp2, gen_lowpart (V2DImode, tmp1),
1435 : : GEN_INT (bits));
1436 : 0 : emit_insn_before (pat, insn);
1437 : 0 : result = gen_lowpart (V4SImode, tmp2);
1438 : : }
1439 : :
1440 : : return result;
1441 : : }
1442 : :
1443 : : /* Convert INSN to vector mode. */
1444 : :
1445 : : void
1446 : 411098 : general_scalar_chain::convert_insn (rtx_insn *insn)
1447 : : {
1448 : 411098 : rtx def_set = single_set (insn);
1449 : 411098 : rtx src = SET_SRC (def_set);
1450 : 411098 : rtx dst = SET_DEST (def_set);
1451 : 411098 : rtx subreg;
1452 : :
1453 : 411098 : if (MEM_P (dst) && !REG_P (src))
1454 : : {
1455 : : /* There are no scalar integer instructions and therefore
1456 : : temporary register usage is required. */
1457 : 762 : rtx tmp = gen_reg_rtx (smode);
1458 : 762 : emit_conversion_insns (gen_move_insn (dst, tmp), insn);
1459 : 762 : dst = gen_rtx_SUBREG (vmode, tmp, 0);
1460 : 762 : }
1461 : 410336 : else if (REG_P (dst) && GET_MODE (dst) == smode)
1462 : : {
1463 : : /* Replace the definition with a SUBREG to the definition we
1464 : : use inside the chain. */
1465 : 214482 : rtx *vdef = defs_map.get (dst);
1466 : 214482 : if (vdef)
1467 : 23105 : dst = *vdef;
1468 : 214482 : dst = gen_rtx_SUBREG (vmode, dst, 0);
1469 : : /* IRA doesn't like to have REG_EQUAL/EQUIV notes when the SET_DEST
1470 : : is a non-REG_P. So kill those off. */
1471 : 214482 : rtx note = find_reg_equal_equiv_note (insn);
1472 : 214482 : if (note)
1473 : 9537 : remove_note (insn, note);
1474 : : }
1475 : :
1476 : 411098 : switch (GET_CODE (src))
1477 : : {
1478 : 29613 : case PLUS:
1479 : 29613 : case MINUS:
1480 : 29613 : case IOR:
1481 : 29613 : case XOR:
1482 : 29613 : case AND:
1483 : 29613 : case SMAX:
1484 : 29613 : case SMIN:
1485 : 29613 : case UMAX:
1486 : 29613 : case UMIN:
1487 : 29613 : convert_op (&XEXP (src, 1), insn);
1488 : : /* FALLTHRU */
1489 : :
1490 : 36901 : case ABS:
1491 : 36901 : case ASHIFT:
1492 : 36901 : case ASHIFTRT:
1493 : 36901 : case LSHIFTRT:
1494 : 36901 : convert_op (&XEXP (src, 0), insn);
1495 : 36901 : PUT_MODE (src, vmode);
1496 : 36901 : break;
1497 : :
1498 : 92 : case ROTATE:
1499 : 92 : case ROTATERT:
1500 : 92 : src = convert_rotate (GET_CODE (src), XEXP (src, 0), XEXP (src, 1),
1501 : : insn);
1502 : 92 : break;
1503 : :
1504 : 400 : case NEG:
1505 : 400 : src = XEXP (src, 0);
1506 : :
1507 : 400 : if (GET_CODE (src) == ABS)
1508 : : {
1509 : 0 : src = XEXP (src, 0);
1510 : 0 : convert_op (&src, insn);
1511 : 0 : subreg = gen_reg_rtx (vmode);
1512 : 0 : emit_insn_before (gen_rtx_SET (subreg,
1513 : : gen_rtx_ABS (vmode, src)), insn);
1514 : 0 : src = subreg;
1515 : : }
1516 : : else
1517 : 400 : convert_op (&src, insn);
1518 : :
1519 : 400 : subreg = gen_reg_rtx (vmode);
1520 : 400 : emit_insn_before (gen_move_insn (subreg, CONST0_RTX (vmode)), insn);
1521 : 400 : src = gen_rtx_MINUS (vmode, subreg, src);
1522 : 400 : break;
1523 : :
1524 : 250 : case NOT:
1525 : 250 : src = XEXP (src, 0);
1526 : 250 : convert_op (&src, insn);
1527 : 250 : subreg = gen_reg_rtx (vmode);
1528 : 250 : emit_insn_before (gen_move_insn (subreg, CONSTM1_RTX (vmode)), insn);
1529 : 250 : src = gen_rtx_XOR (vmode, src, subreg);
1530 : 250 : break;
1531 : :
1532 : 171011 : case MEM:
1533 : 171011 : if (!REG_P (dst))
1534 : 171011 : convert_op (&src, insn);
1535 : : break;
1536 : :
1537 : 197243 : case REG:
1538 : 197243 : if (!MEM_P (dst))
1539 : 1389 : convert_op (&src, insn);
1540 : : break;
1541 : :
1542 : 0 : case SUBREG:
1543 : 0 : gcc_assert (GET_MODE (src) == vmode);
1544 : : break;
1545 : :
1546 : 0 : case COMPARE:
1547 : 0 : dst = gen_rtx_REG (CCZmode, FLAGS_REG);
1548 : 0 : src = convert_compare (XEXP (src, 0), XEXP (src, 1), insn);
1549 : 0 : break;
1550 : :
1551 : 3404 : case CONST_INT:
1552 : 3404 : convert_op (&src, insn);
1553 : 3404 : break;
1554 : :
1555 : 1797 : case VEC_SELECT:
1556 : 1797 : if (XVECEXP (XEXP (src, 1), 0, 0) == const0_rtx)
1557 : 1398 : src = XEXP (src, 0);
1558 : 399 : else if (smode == DImode)
1559 : : {
1560 : 156 : rtx tmp = gen_lowpart (V1TImode, XEXP (src, 0));
1561 : 156 : dst = gen_lowpart (V1TImode, dst);
1562 : 156 : src = gen_rtx_LSHIFTRT (V1TImode, tmp, GEN_INT (64));
1563 : : }
1564 : : else
1565 : : {
1566 : 243 : rtx tmp = XVECEXP (XEXP (src, 1), 0, 0);
1567 : 243 : rtvec vec = gen_rtvec (4, tmp, tmp, tmp, tmp);
1568 : 243 : rtx par = gen_rtx_PARALLEL (VOIDmode, vec);
1569 : 243 : src = gen_rtx_VEC_SELECT (vmode, XEXP (src, 0), par);
1570 : : }
1571 : : break;
1572 : :
1573 : 0 : default:
1574 : 0 : gcc_unreachable ();
1575 : : }
1576 : :
1577 : 411098 : SET_SRC (def_set) = src;
1578 : 411098 : SET_DEST (def_set) = dst;
1579 : :
1580 : : /* Drop possible dead definitions. */
1581 : 411098 : PATTERN (insn) = def_set;
1582 : :
1583 : 411098 : INSN_CODE (insn) = -1;
1584 : 411098 : int patt = recog_memoized (insn);
1585 : 411098 : if (patt == -1)
1586 : 0 : fatal_insn_not_found (insn);
1587 : 411098 : df_insn_rescan (insn);
1588 : 411098 : }
1589 : :
1590 : : /* Helper function to compute gain for loading an immediate constant.
1591 : : Typically, two movabsq for TImode vs. vmovdqa for V1TImode, but
1592 : : with numerous special cases. */
1593 : :
1594 : : static int
1595 : 6 : timode_immed_const_gain (rtx cst, basic_block bb)
1596 : : {
1597 : : /* movabsq vs. movabsq+vmovq+vunpacklqdq. */
1598 : 6 : if (CONST_WIDE_INT_P (cst)
1599 : 5 : && CONST_WIDE_INT_NUNITS (cst) == 2
1600 : 11 : && CONST_WIDE_INT_ELT (cst, 0) == CONST_WIDE_INT_ELT (cst, 1))
1601 : 0 : return optimize_bb_for_size_p (bb) ? -COSTS_N_BYTES (9)
1602 : : : -COSTS_N_INSNS (2);
1603 : : /* 2x movabsq ~ vmovdqa. */
1604 : : return 0;
1605 : : }
1606 : :
1607 : : /* Return true it's cost profitable for for chain conversion. */
1608 : :
1609 : : bool
1610 : 489417 : timode_scalar_chain::compute_convert_gain ()
1611 : : {
1612 : : /* Assume that if we have to move TImode values between units,
1613 : : then transforming this chain isn't worth it. */
1614 : 489417 : if (cost_sse_integer)
1615 : : return false;
1616 : :
1617 : 489417 : bitmap_iterator bi;
1618 : 489417 : unsigned insn_uid;
1619 : :
1620 : : /* Split ties to prefer V1TImode when not optimizing for size. */
1621 : 489417 : int gain = optimize_size ? 0 : 1;
1622 : 489417 : sreal weighted_gain = 0;
1623 : :
1624 : 489417 : if (dump_file)
1625 : 0 : fprintf (dump_file, "Computing gain for chain #%d...\n", chain_id);
1626 : :
1627 : 1449822 : EXECUTE_IF_SET_IN_BITMAP (insns, 0, insn_uid, bi)
1628 : : {
1629 : 960405 : rtx_insn *insn = DF_INSN_UID_GET (insn_uid)->insn;
1630 : 960405 : rtx def_set = single_set (insn);
1631 : 960405 : rtx src = SET_SRC (def_set);
1632 : 960405 : rtx dst = SET_DEST (def_set);
1633 : 960405 : HOST_WIDE_INT op1val;
1634 : 960405 : basic_block bb = BLOCK_FOR_INSN (insn);
1635 : 960405 : int scost, vcost;
1636 : 960405 : int igain = 0;
1637 : 960405 : profile_count entry_count = ENTRY_BLOCK_PTR_FOR_FN (cfun)->count;
1638 : 960405 : bool speed_p = optimize_bb_for_speed_p (bb);
1639 : 960405 : sreal bb_freq = bb->count.to_sreal_scale (entry_count);
1640 : :
1641 : 960405 : switch (GET_CODE (src))
1642 : : {
1643 : 470627 : case REG:
1644 : 470627 : if (!speed_p)
1645 : 20922 : igain = MEM_P (dst) ? COSTS_N_BYTES (6) : COSTS_N_BYTES (3);
1646 : : else
1647 : : igain = COSTS_N_INSNS (1);
1648 : : break;
1649 : :
1650 : 437226 : case MEM:
1651 : 437226 : igain = !speed_p ? COSTS_N_BYTES (7) : COSTS_N_INSNS (1);
1652 : : break;
1653 : :
1654 : 11227 : case CONST_INT:
1655 : 11227 : if (MEM_P (dst)
1656 : 11227 : && standard_sse_constant_p (src, V1TImode))
1657 : 10678 : igain = !speed_p ? COSTS_N_BYTES (11) : 1;
1658 : : break;
1659 : :
1660 : 38045 : case CONST_WIDE_INT:
1661 : : /* 2 x mov vs. vmovdqa. */
1662 : 38045 : if (MEM_P (dst))
1663 : 37861 : igain = !speed_p ? COSTS_N_BYTES (3) : COSTS_N_INSNS (1);
1664 : : break;
1665 : :
1666 : 17 : case NOT:
1667 : 17 : if (MEM_P (dst))
1668 : 24910 : igain = -COSTS_N_INSNS (1);
1669 : : break;
1670 : :
1671 : 10 : case AND:
1672 : 10 : if (!MEM_P (dst))
1673 : 3 : igain = COSTS_N_INSNS (1);
1674 : 10 : if (CONST_SCALAR_INT_P (XEXP (src, 1)))
1675 : 5 : igain += timode_immed_const_gain (XEXP (src, 1), bb);
1676 : : break;
1677 : :
1678 : 2858 : case XOR:
1679 : 2858 : case IOR:
1680 : 2858 : if (timode_concatdi_p (src))
1681 : : {
1682 : : /* vmovq;vpinsrq (11 bytes). */
1683 : 2817 : igain = speed_p ? -2 * ix86_cost->sse_to_integer
1684 : : : -COSTS_N_BYTES (11);
1685 : : break;
1686 : : }
1687 : 41 : if (!MEM_P (dst))
1688 : 41 : igain = COSTS_N_INSNS (1);
1689 : 41 : if (CONST_SCALAR_INT_P (XEXP (src, 1)))
1690 : 1 : igain += timode_immed_const_gain (XEXP (src, 1), bb);
1691 : : break;
1692 : :
1693 : 0 : case PLUS:
1694 : 0 : if (timode_concatdi_p (src))
1695 : : /* vmovq;vpinsrq (11 bytes). */
1696 : 0 : igain = speed_p ? -2 * ix86_cost->sse_to_integer
1697 : : : -COSTS_N_BYTES (11);
1698 : : break;
1699 : :
1700 : 158 : case ASHIFT:
1701 : 158 : case LSHIFTRT:
1702 : : /* See ix86_expand_v1ti_shift. */
1703 : 158 : op1val = INTVAL (XEXP (src, 1));
1704 : 158 : if (!speed_p)
1705 : : {
1706 : 15 : if (op1val == 64 || op1val == 65)
1707 : : scost = COSTS_N_BYTES (5);
1708 : 10 : else if (op1val >= 66)
1709 : : scost = COSTS_N_BYTES (6);
1710 : 10 : else if (op1val == 1)
1711 : : scost = COSTS_N_BYTES (8);
1712 : : else
1713 : : scost = COSTS_N_BYTES (9);
1714 : :
1715 : 14 : if ((op1val & 7) == 0)
1716 : : vcost = COSTS_N_BYTES (5);
1717 : 10 : else if (op1val > 64)
1718 : : vcost = COSTS_N_BYTES (10);
1719 : : else
1720 : 10 : vcost = TARGET_AVX ? COSTS_N_BYTES (19) : COSTS_N_BYTES (23);
1721 : : }
1722 : : else
1723 : : {
1724 : 143 : scost = COSTS_N_INSNS (2);
1725 : 143 : if ((op1val & 7) == 0)
1726 : : vcost = COSTS_N_INSNS (1);
1727 : 110 : else if (op1val > 64)
1728 : : vcost = COSTS_N_INSNS (2);
1729 : : else
1730 : 110 : vcost = TARGET_AVX ? COSTS_N_INSNS (4) : COSTS_N_INSNS (5);
1731 : : }
1732 : 158 : igain = scost - vcost;
1733 : 158 : break;
1734 : :
1735 : 103 : case ASHIFTRT:
1736 : : /* See ix86_expand_v1ti_ashiftrt. */
1737 : 103 : op1val = INTVAL (XEXP (src, 1));
1738 : 103 : if (!speed_p)
1739 : : {
1740 : 7 : if (op1val == 64 || op1val == 127)
1741 : : scost = COSTS_N_BYTES (7);
1742 : 7 : else if (op1val == 1)
1743 : : scost = COSTS_N_BYTES (8);
1744 : 7 : else if (op1val == 65)
1745 : : scost = COSTS_N_BYTES (10);
1746 : 7 : else if (op1val >= 66)
1747 : : scost = COSTS_N_BYTES (11);
1748 : : else
1749 : : scost = COSTS_N_BYTES (9);
1750 : :
1751 : 0 : if (op1val == 127)
1752 : : vcost = COSTS_N_BYTES (10);
1753 : 7 : else if (op1val == 64)
1754 : : vcost = COSTS_N_BYTES (14);
1755 : 7 : else if (op1val == 96)
1756 : : vcost = COSTS_N_BYTES (18);
1757 : 7 : else if (op1val >= 111)
1758 : : vcost = COSTS_N_BYTES (15);
1759 : 7 : else if (TARGET_AVX2 && op1val == 32)
1760 : : vcost = COSTS_N_BYTES (16);
1761 : 7 : else if (TARGET_SSE4_1 && op1val == 32)
1762 : : vcost = COSTS_N_BYTES (20);
1763 : 7 : else if (op1val >= 96)
1764 : : vcost = COSTS_N_BYTES (23);
1765 : 7 : else if ((op1val & 7) == 0)
1766 : : vcost = COSTS_N_BYTES (28);
1767 : 7 : else if (TARGET_AVX2 && op1val < 32)
1768 : : vcost = COSTS_N_BYTES (30);
1769 : 7 : else if (op1val == 1 || op1val >= 64)
1770 : : vcost = COSTS_N_BYTES (42);
1771 : : else
1772 : 7 : vcost = COSTS_N_BYTES (47);
1773 : : }
1774 : : else
1775 : : {
1776 : 96 : if (op1val >= 65 && op1val <= 126)
1777 : : scost = COSTS_N_INSNS (3);
1778 : : else
1779 : 96 : scost = COSTS_N_INSNS (2);
1780 : :
1781 : 96 : if (op1val == 127)
1782 : : vcost = COSTS_N_INSNS (2);
1783 : 96 : else if (op1val == 64)
1784 : : vcost = COSTS_N_INSNS (3);
1785 : 96 : else if (op1val == 96)
1786 : : vcost = COSTS_N_INSNS (3);
1787 : 96 : else if (op1val >= 111)
1788 : : vcost = COSTS_N_INSNS (3);
1789 : 96 : else if (TARGET_SSE4_1 && op1val == 32)
1790 : : vcost = COSTS_N_INSNS (3);
1791 : 96 : else if (TARGET_SSE4_1
1792 : 0 : && (op1val == 8 || op1val == 16 || op1val == 24))
1793 : : vcost = COSTS_N_INSNS (3);
1794 : 96 : else if (op1val >= 96)
1795 : : vcost = COSTS_N_INSNS (4);
1796 : 96 : else if (TARGET_SSE4_1 && (op1val == 28 || op1val == 80))
1797 : : vcost = COSTS_N_INSNS (4);
1798 : 96 : else if ((op1val & 7) == 0)
1799 : : vcost = COSTS_N_INSNS (5);
1800 : 96 : else if (TARGET_AVX2 && op1val < 32)
1801 : : vcost = COSTS_N_INSNS (6);
1802 : 96 : else if (TARGET_SSE4_1 && op1val < 15)
1803 : : vcost = COSTS_N_INSNS (6);
1804 : 96 : else if (op1val == 1 || op1val >= 64)
1805 : : vcost = COSTS_N_INSNS (8);
1806 : : else
1807 : 0 : vcost = COSTS_N_INSNS (9);
1808 : : }
1809 : 103 : igain = scost - vcost;
1810 : 103 : break;
1811 : :
1812 : 5 : case ROTATE:
1813 : 5 : case ROTATERT:
1814 : : /* See ix86_expand_v1ti_rotate. */
1815 : 5 : op1val = INTVAL (XEXP (src, 1));
1816 : 5 : if (!speed_p)
1817 : : {
1818 : 0 : scost = COSTS_N_BYTES (13);
1819 : 0 : if ((op1val & 31) == 0)
1820 : : vcost = COSTS_N_BYTES (5);
1821 : 0 : else if ((op1val & 7) == 0)
1822 : 0 : vcost = TARGET_AVX ? COSTS_N_BYTES (13) : COSTS_N_BYTES (18);
1823 : 0 : else if (op1val > 32 && op1val < 96)
1824 : : vcost = COSTS_N_BYTES (24);
1825 : : else
1826 : 0 : vcost = COSTS_N_BYTES (19);
1827 : : }
1828 : : else
1829 : : {
1830 : 5 : scost = COSTS_N_INSNS (3);
1831 : 5 : if ((op1val & 31) == 0)
1832 : : vcost = COSTS_N_INSNS (1);
1833 : 3 : else if ((op1val & 7) == 0)
1834 : 1 : vcost = TARGET_AVX ? COSTS_N_INSNS (3) : COSTS_N_INSNS (4);
1835 : 2 : else if (op1val > 32 && op1val < 96)
1836 : : vcost = COSTS_N_INSNS (5);
1837 : : else
1838 : 2 : vcost = COSTS_N_INSNS (1);
1839 : : }
1840 : 5 : igain = scost - vcost;
1841 : 5 : break;
1842 : :
1843 : 8 : case COMPARE:
1844 : 8 : if (XEXP (src, 1) == const0_rtx)
1845 : : {
1846 : 4 : if (GET_CODE (XEXP (src, 0)) == AND)
1847 : : /* and;and;or (9 bytes) vs. ptest (5 bytes). */
1848 : : igain = !speed_p ? COSTS_N_BYTES (4) : COSTS_N_INSNS (2);
1849 : : /* or (3 bytes) vs. ptest (5 bytes). */
1850 : 4 : else if (!speed_p)
1851 : 0 : igain = -COSTS_N_BYTES (2);
1852 : : }
1853 : 4 : else if (XEXP (src, 1) == const1_rtx)
1854 : : /* and;cmp -1 (7 bytes) vs. pcmpeqd;pxor;ptest (13 bytes). */
1855 : 0 : igain = !speed_p ? -COSTS_N_BYTES (6) : -COSTS_N_INSNS (1);
1856 : : break;
1857 : :
1858 : 121 : case ZERO_EXTEND:
1859 : 121 : if (GET_MODE (XEXP (src, 0)) == DImode)
1860 : : /* xor (2 bytes) vs. vmovq (5 bytes). */
1861 : 121 : igain = speed_p ? COSTS_N_INSNS (1) - ix86_cost->sse_to_integer
1862 : : : -COSTS_N_BYTES (3);
1863 : : break;
1864 : :
1865 : : default:
1866 : : break;
1867 : : }
1868 : :
1869 : 1878696 : gain += igain;
1870 : 960401 : if (speed_p)
1871 : 918295 : weighted_gain += bb_freq * igain;
1872 : :
1873 : 960405 : if (igain != 0 && dump_file)
1874 : : {
1875 : 0 : fprintf (dump_file, " Instruction gain %d with bb_freq %.2f for ",
1876 : : igain, bb_freq.to_double ());
1877 : 0 : dump_insn_slim (dump_file, insn);
1878 : : }
1879 : : }
1880 : :
1881 : 489417 : if (dump_file)
1882 : 0 : fprintf (dump_file, " Total gain: %d, weighted gain %.2f\n",
1883 : : gain, weighted_gain.to_double ());
1884 : :
1885 : 489417 : if (weighted_gain > (sreal) 0)
1886 : : return true;
1887 : : else
1888 : 24532 : return gain > 0;
1889 : : }
1890 : :
1891 : : /* Fix uses of converted REG in debug insns. */
1892 : :
1893 : : void
1894 : 438475 : timode_scalar_chain::fix_debug_reg_uses (rtx reg)
1895 : : {
1896 : 438475 : if (!flag_var_tracking)
1897 : : return;
1898 : :
1899 : 387827 : df_ref ref, next;
1900 : 794857 : for (ref = DF_REG_USE_CHAIN (REGNO (reg)); ref; ref = next)
1901 : : {
1902 : 407030 : rtx_insn *insn = DF_REF_INSN (ref);
1903 : : /* Make sure the next ref is for a different instruction,
1904 : : so that we're not affected by the rescan. */
1905 : 407030 : next = DF_REF_NEXT_REG (ref);
1906 : 407030 : while (next && DF_REF_INSN (next) == insn)
1907 : 0 : next = DF_REF_NEXT_REG (next);
1908 : :
1909 : 407030 : if (DEBUG_INSN_P (insn))
1910 : : {
1911 : : /* It may be a debug insn with a TImode variable in
1912 : : register. */
1913 : : bool changed = false;
1914 : 126 : for (; ref != next; ref = DF_REF_NEXT_REG (ref))
1915 : : {
1916 : 63 : rtx *loc = DF_REF_LOC (ref);
1917 : 63 : if (REG_P (*loc) && GET_MODE (*loc) == V1TImode)
1918 : : {
1919 : 59 : *loc = gen_rtx_SUBREG (TImode, *loc, 0);
1920 : 59 : changed = true;
1921 : : }
1922 : : }
1923 : 63 : if (changed)
1924 : 59 : df_insn_rescan (insn);
1925 : : }
1926 : : }
1927 : : }
1928 : :
1929 : : /* Convert SRC, a *concatditi3 pattern, into a vec_concatv2di instruction.
1930 : : Insert this before INSN, and return the result as a V1TImode subreg. */
1931 : :
1932 : : static rtx
1933 : 253 : timode_convert_concatdi (rtx src, rtx_insn *insn)
1934 : : {
1935 : 253 : rtx hi, lo;
1936 : 253 : rtx tmp = gen_reg_rtx (V2DImode);
1937 : 253 : if (GET_CODE (XEXP (src, 0)) == ASHIFT)
1938 : : {
1939 : 253 : hi = XEXP (XEXP (XEXP (src, 0), 0), 0);
1940 : 253 : lo = XEXP (XEXP (src, 1), 0);
1941 : : }
1942 : : else
1943 : : {
1944 : 0 : hi = XEXP (XEXP (XEXP (src, 1), 0), 0);
1945 : 0 : lo = XEXP (XEXP (src, 0), 0);
1946 : : }
1947 : 253 : emit_insn_before (gen_vec_concatv2di (tmp, lo, hi), insn);
1948 : 253 : return gen_rtx_SUBREG (V1TImode, tmp, 0);
1949 : : }
1950 : :
1951 : : /* Convert INSN from TImode to V1T1mode. */
1952 : :
1953 : : void
1954 : 953868 : timode_scalar_chain::convert_insn (rtx_insn *insn)
1955 : : {
1956 : 953868 : rtx def_set = single_set (insn);
1957 : 953868 : rtx src = SET_SRC (def_set);
1958 : 953868 : rtx dst = SET_DEST (def_set);
1959 : 953868 : rtx tmp;
1960 : :
1961 : 953868 : switch (GET_CODE (dst))
1962 : : {
1963 : 438481 : case REG:
1964 : 438481 : if (GET_MODE (dst) == TImode)
1965 : : {
1966 : 436719 : PUT_MODE (dst, V1TImode);
1967 : 436719 : fix_debug_reg_uses (dst);
1968 : : }
1969 : 438481 : if (GET_MODE (dst) == V1TImode)
1970 : : {
1971 : : /* It might potentially be helpful to convert REG_EQUAL notes,
1972 : : but for now we just remove them. */
1973 : 438475 : rtx note = find_reg_equal_equiv_note (insn);
1974 : 438475 : if (note)
1975 : 444 : remove_note (insn, note);
1976 : : }
1977 : : break;
1978 : 515387 : case MEM:
1979 : 515387 : PUT_MODE (dst, V1TImode);
1980 : 515387 : break;
1981 : :
1982 : 0 : default:
1983 : 0 : gcc_unreachable ();
1984 : : }
1985 : :
1986 : 953868 : switch (GET_CODE (src))
1987 : : {
1988 : 466968 : case REG:
1989 : 466968 : if (GET_MODE (src) == TImode)
1990 : : {
1991 : 1756 : PUT_MODE (src, V1TImode);
1992 : 1756 : fix_debug_reg_uses (src);
1993 : : }
1994 : : break;
1995 : :
1996 : 437178 : case MEM:
1997 : 437178 : PUT_MODE (src, V1TImode);
1998 : 437178 : break;
1999 : :
2000 : 38044 : case CONST_WIDE_INT:
2001 : 38044 : if (NONDEBUG_INSN_P (insn))
2002 : : {
2003 : : /* Since there are no instructions to store 128-bit constant,
2004 : : temporary register usage is required. */
2005 : 38044 : bool use_move;
2006 : 38044 : start_sequence ();
2007 : 38044 : tmp = ix86_convert_const_wide_int_to_broadcast (TImode, src);
2008 : 38044 : if (tmp)
2009 : : {
2010 : 194 : src = lowpart_subreg (V1TImode, tmp, TImode);
2011 : 194 : use_move = true;
2012 : : }
2013 : : else
2014 : : {
2015 : 37850 : src = smode_convert_cst (src, V1TImode);
2016 : 37850 : src = validize_mem (force_const_mem (V1TImode, src));
2017 : 37850 : use_move = MEM_P (dst);
2018 : : }
2019 : 38044 : rtx_insn *seq = end_sequence ();
2020 : 38044 : if (seq)
2021 : 195 : emit_insn_before (seq, insn);
2022 : 38044 : if (use_move)
2023 : : {
2024 : 37862 : tmp = gen_reg_rtx (V1TImode);
2025 : 37862 : emit_insn_before (gen_rtx_SET (tmp, src), insn);
2026 : 37862 : src = tmp;
2027 : : }
2028 : : }
2029 : : break;
2030 : :
2031 : 11226 : case CONST_INT:
2032 : 11226 : switch (standard_sse_constant_p (src, TImode))
2033 : : {
2034 : 10997 : case 1:
2035 : 10997 : src = CONST0_RTX (GET_MODE (dst));
2036 : 10997 : break;
2037 : 229 : case 2:
2038 : 229 : src = CONSTM1_RTX (GET_MODE (dst));
2039 : 229 : break;
2040 : 0 : default:
2041 : 0 : gcc_unreachable ();
2042 : : }
2043 : 11226 : if (MEM_P (dst))
2044 : : {
2045 : 10678 : tmp = gen_reg_rtx (V1TImode);
2046 : 10678 : emit_insn_before (gen_rtx_SET (tmp, src), insn);
2047 : 10678 : src = tmp;
2048 : : }
2049 : : break;
2050 : :
2051 : 9 : case AND:
2052 : 9 : if (GET_CODE (XEXP (src, 0)) == NOT)
2053 : : {
2054 : 0 : convert_op (&XEXP (XEXP (src, 0), 0), insn);
2055 : 0 : convert_op (&XEXP (src, 1), insn);
2056 : 0 : PUT_MODE (XEXP (src, 0), V1TImode);
2057 : 0 : PUT_MODE (src, V1TImode);
2058 : 0 : break;
2059 : : }
2060 : 9 : convert_op (&XEXP (src, 0), insn);
2061 : 9 : convert_op (&XEXP (src, 1), insn);
2062 : 9 : PUT_MODE (src, V1TImode);
2063 : 9 : if (MEM_P (dst))
2064 : : {
2065 : 6 : tmp = gen_reg_rtx (V1TImode);
2066 : 6 : emit_insn_before (gen_rtx_SET (tmp, src), insn);
2067 : 6 : src = tmp;
2068 : : }
2069 : : break;
2070 : :
2071 : 294 : case XOR:
2072 : 294 : case IOR:
2073 : 294 : if (timode_concatdi_p (src))
2074 : : {
2075 : 253 : src = timode_convert_concatdi (src, insn);
2076 : 253 : break;
2077 : : }
2078 : 41 : convert_op (&XEXP (src, 0), insn);
2079 : 41 : convert_op (&XEXP (src, 1), insn);
2080 : 41 : PUT_MODE (src, V1TImode);
2081 : 41 : if (MEM_P (dst))
2082 : : {
2083 : 0 : tmp = gen_reg_rtx (V1TImode);
2084 : 0 : emit_insn_before (gen_rtx_SET (tmp, src), insn);
2085 : 0 : src = tmp;
2086 : : }
2087 : : break;
2088 : :
2089 : 1 : case NOT:
2090 : 1 : src = XEXP (src, 0);
2091 : 1 : convert_op (&src, insn);
2092 : 1 : tmp = gen_reg_rtx (V1TImode);
2093 : 1 : emit_insn_before (gen_move_insn (tmp, CONSTM1_RTX (V1TImode)), insn);
2094 : 1 : src = gen_rtx_XOR (V1TImode, src, tmp);
2095 : 1 : if (MEM_P (dst))
2096 : : {
2097 : 0 : tmp = gen_reg_rtx (V1TImode);
2098 : 0 : emit_insn_before (gen_rtx_SET (tmp, src), insn);
2099 : 0 : src = tmp;
2100 : : }
2101 : : break;
2102 : :
2103 : 6 : case COMPARE:
2104 : 6 : dst = gen_rtx_REG (CCZmode, FLAGS_REG);
2105 : 6 : src = convert_compare (XEXP (src, 0), XEXP (src, 1), insn);
2106 : 6 : break;
2107 : :
2108 : 43 : case ASHIFT:
2109 : 43 : case LSHIFTRT:
2110 : 43 : case ASHIFTRT:
2111 : 43 : case ROTATERT:
2112 : 43 : case ROTATE:
2113 : 43 : convert_op (&XEXP (src, 0), insn);
2114 : 43 : PUT_MODE (src, V1TImode);
2115 : 43 : break;
2116 : :
2117 : 99 : case ZERO_EXTEND:
2118 : 99 : if (GET_MODE (XEXP (src, 0)) == DImode)
2119 : : {
2120 : : /* Convert to *vec_concatv2di_0. */
2121 : 99 : rtx tmp = gen_reg_rtx (V2DImode);
2122 : 99 : rtx pat = gen_rtx_VEC_CONCAT (V2DImode, XEXP (src, 0), const0_rtx);
2123 : 99 : emit_insn_before (gen_move_insn (tmp, pat), insn);
2124 : 99 : src = gen_rtx_SUBREG (vmode, tmp, 0);
2125 : : }
2126 : : else
2127 : 0 : gcc_unreachable ();
2128 : 99 : break;
2129 : :
2130 : 0 : case PLUS:
2131 : 0 : if (timode_concatdi_p (src))
2132 : 0 : src = timode_convert_concatdi (src, insn);
2133 : : else
2134 : 0 : gcc_unreachable ();
2135 : 0 : break;
2136 : :
2137 : 0 : default:
2138 : 0 : gcc_unreachable ();
2139 : : }
2140 : :
2141 : 953868 : SET_SRC (def_set) = src;
2142 : 953868 : SET_DEST (def_set) = dst;
2143 : :
2144 : : /* Drop possible dead definitions. */
2145 : 953868 : PATTERN (insn) = def_set;
2146 : :
2147 : 953868 : INSN_CODE (insn) = -1;
2148 : 953868 : recog_memoized (insn);
2149 : 953868 : df_insn_rescan (insn);
2150 : 953868 : }
2151 : :
2152 : : /* Generate copies from defs used by the chain but not defined therein.
2153 : : Also populates defs_map which is used later by convert_insn. */
2154 : :
2155 : : void
2156 : 659608 : scalar_chain::convert_registers ()
2157 : : {
2158 : 659608 : bitmap_iterator bi;
2159 : 659608 : unsigned id;
2160 : 685287 : EXECUTE_IF_SET_IN_BITMAP (defs_conv, 0, id, bi)
2161 : : {
2162 : 25679 : rtx chain_reg = gen_reg_rtx (smode);
2163 : 25679 : defs_map.put (regno_reg_rtx[id], chain_reg);
2164 : : }
2165 : 667659 : EXECUTE_IF_SET_IN_BITMAP (insns_conv, 0, id, bi)
2166 : 20352 : for (df_ref ref = DF_INSN_UID_DEFS (id); ref; ref = DF_REF_NEXT_LOC (ref))
2167 : 12301 : if (bitmap_bit_p (defs_conv, DF_REF_REGNO (ref)))
2168 : 8051 : make_vector_copies (DF_REF_INSN (ref), DF_REF_REAL_REG (ref));
2169 : 659608 : }
2170 : :
2171 : : /* Convert whole chain creating required register
2172 : : conversions and copies. */
2173 : :
2174 : : int
2175 : 659608 : scalar_chain::convert ()
2176 : : {
2177 : 659608 : bitmap_iterator bi;
2178 : 659608 : unsigned id;
2179 : 659608 : int converted_insns = 0;
2180 : :
2181 : 659608 : if (!dbg_cnt (stv_conversion))
2182 : : return 0;
2183 : :
2184 : 659608 : if (dump_file)
2185 : 0 : fprintf (dump_file, "Converting chain #%d...\n", chain_id);
2186 : :
2187 : 659608 : convert_registers ();
2188 : :
2189 : 2024574 : EXECUTE_IF_SET_IN_BITMAP (insns, 0, id, bi)
2190 : : {
2191 : 1364966 : rtx_insn *insn = DF_INSN_UID_GET (id)->insn;
2192 : 1364966 : convert_insn_common (insn);
2193 : 1364966 : convert_insn (insn);
2194 : 1364966 : converted_insns++;
2195 : : }
2196 : :
2197 : : return converted_insns;
2198 : : }
2199 : :
2200 : : /* Return the SET expression if INSN doesn't reference hard register.
2201 : : Return NULL if INSN uses or defines a hard register, excluding
2202 : : pseudo register pushes, hard register uses in a memory address,
2203 : : clobbers and flags definitions. */
2204 : :
2205 : : static rtx
2206 : 345579233 : pseudo_reg_set (rtx_insn *insn)
2207 : : {
2208 : 345579233 : rtx set = single_set (insn);
2209 : 345579233 : if (!set)
2210 : : return NULL;
2211 : :
2212 : : /* Check pseudo register push first. */
2213 : 138349363 : machine_mode mode = TARGET_64BIT ? TImode : DImode;
2214 : 138349363 : if (REG_P (SET_SRC (set))
2215 : 38960803 : && !HARD_REGISTER_P (SET_SRC (set))
2216 : 168792772 : && push_operand (SET_DEST (set), mode))
2217 : : return set;
2218 : :
2219 : 138097132 : df_ref ref;
2220 : 223954006 : FOR_EACH_INSN_DEF (ref, insn)
2221 : 123334810 : if (HARD_REGISTER_P (DF_REF_REAL_REG (ref))
2222 : 66129791 : && !DF_REF_FLAGS_IS_SET (ref, DF_REF_MUST_CLOBBER)
2223 : 174611133 : && DF_REF_REGNO (ref) != FLAGS_REG)
2224 : : return NULL;
2225 : :
2226 : 192476632 : FOR_EACH_INSN_USE (ref, insn)
2227 : 117840253 : if (!DF_REF_REG_MEM_P (ref) && HARD_REGISTER_P (DF_REF_REAL_REG (ref)))
2228 : : return NULL;
2229 : :
2230 : : return set;
2231 : : }
2232 : :
2233 : : /* Return true if the register REG is defined in a single DEF chain.
2234 : : If it is defined in more than one DEF chains, we may not be able
2235 : : to convert it in all chains. */
2236 : :
2237 : : static bool
2238 : 1202485 : single_def_chain_p (rtx reg)
2239 : : {
2240 : 1202485 : df_ref ref = DF_REG_DEF_CHAIN (REGNO (reg));
2241 : 1202485 : if (!ref)
2242 : : return false;
2243 : 1202469 : return DF_REF_NEXT_REG (ref) == nullptr;
2244 : : }
2245 : :
2246 : : /* Check if comparison INSN may be transformed into vector comparison.
2247 : : Currently we transform equality/inequality checks which look like:
2248 : : (set (reg:CCZ 17 flags) (compare:CCZ (reg:TI x) (reg:TI y))) */
2249 : :
2250 : : static bool
2251 : 13170030 : convertible_comparison_p (rtx_insn *insn, enum machine_mode mode)
2252 : : {
2253 : 14572778 : if (mode != (TARGET_64BIT ? TImode : DImode))
2254 : : return false;
2255 : :
2256 : 4810912 : if (!TARGET_SSE4_1)
2257 : : return false;
2258 : :
2259 : 164679 : rtx def_set = single_set (insn);
2260 : :
2261 : 164679 : gcc_assert (def_set);
2262 : :
2263 : 164679 : rtx src = SET_SRC (def_set);
2264 : 164679 : rtx dst = SET_DEST (def_set);
2265 : :
2266 : 164679 : gcc_assert (GET_CODE (src) == COMPARE);
2267 : :
2268 : 164679 : if (!REG_P (dst)
2269 : 164679 : || REGNO (dst) != FLAGS_REG
2270 : 329358 : || GET_MODE (dst) != CCZmode)
2271 : : return false;
2272 : :
2273 : 119742 : rtx op1 = XEXP (src, 0);
2274 : 119742 : rtx op2 = XEXP (src, 1);
2275 : :
2276 : : /* *cmp<dwi>_doubleword. */
2277 : 119742 : if ((CONST_SCALAR_INT_P (op1)
2278 : 119742 : || ((REG_P (op1) || MEM_P (op1))
2279 : 117866 : && GET_MODE (op1) == mode))
2280 : 52 : && (CONST_SCALAR_INT_P (op2)
2281 : 6 : || ((REG_P (op2) || MEM_P (op2))
2282 : 4 : && GET_MODE (op2) == mode)))
2283 : : return true;
2284 : :
2285 : : /* *testti_doubleword. */
2286 : 119692 : if (op2 == const0_rtx
2287 : 38070 : && GET_CODE (op1) == AND
2288 : 150 : && REG_P (XEXP (op1, 0)))
2289 : : {
2290 : 150 : rtx op12 = XEXP (op1, 1);
2291 : 150 : return GET_MODE (XEXP (op1, 0)) == TImode
2292 : 150 : && (CONST_SCALAR_INT_P (op12)
2293 : 0 : || ((REG_P (op12) || MEM_P (op12))
2294 : 0 : && GET_MODE (op12) == TImode));
2295 : : }
2296 : :
2297 : : /* *test<dwi>_not_doubleword. */
2298 : 119542 : if (op2 == const0_rtx
2299 : 37920 : && GET_CODE (op1) == AND
2300 : 0 : && GET_CODE (XEXP (op1, 0)) == NOT)
2301 : : {
2302 : 0 : rtx op11 = XEXP (XEXP (op1, 0), 0);
2303 : 0 : rtx op12 = XEXP (op1, 1);
2304 : 0 : return (REG_P (op11) || MEM_P (op11))
2305 : 0 : && (REG_P (op12) || MEM_P (op12))
2306 : 0 : && GET_MODE (op11) == mode
2307 : 0 : && GET_MODE (op12) == mode;
2308 : : }
2309 : :
2310 : : return false;
2311 : : }
2312 : :
2313 : : /* The general version of scalar_to_vector_candidate_p. */
2314 : :
2315 : : static bool
2316 : 241372671 : general_scalar_to_vector_candidate_p (rtx_insn *insn, enum machine_mode mode)
2317 : : {
2318 : 241372671 : rtx def_set = pseudo_reg_set (insn);
2319 : :
2320 : 241372671 : if (!def_set)
2321 : : return false;
2322 : :
2323 : 50539881 : rtx src = SET_SRC (def_set);
2324 : 50539881 : rtx dst = SET_DEST (def_set);
2325 : :
2326 : 50539881 : if (GET_CODE (src) == COMPARE)
2327 : 9060492 : return convertible_comparison_p (insn, mode);
2328 : :
2329 : : /* We are interested in "mode" only. */
2330 : 41479389 : if ((GET_MODE (src) != mode
2331 : 28386928 : && !CONST_INT_P (src))
2332 : 18420158 : || GET_MODE (dst) != mode)
2333 : : return false;
2334 : :
2335 : 15379049 : if (!REG_P (dst) && !MEM_P (dst))
2336 : : return false;
2337 : :
2338 : 15146683 : switch (GET_CODE (src))
2339 : : {
2340 : 537426 : case ASHIFT:
2341 : 537426 : case LSHIFTRT:
2342 : 537426 : case ASHIFTRT:
2343 : 537426 : case ROTATE:
2344 : 537426 : case ROTATERT:
2345 : 537426 : if (!CONST_INT_P (XEXP (src, 1))
2346 : 1039336 : || !IN_RANGE (INTVAL (XEXP (src, 1)), 0, GET_MODE_BITSIZE (mode)-1))
2347 : : return false;
2348 : :
2349 : : /* Check for extend highpart case. */
2350 : 501906 : if (mode != DImode
2351 : 356129 : || GET_CODE (src) != ASHIFTRT
2352 : 80498 : || GET_CODE (XEXP (src, 0)) != ASHIFT)
2353 : : break;
2354 : :
2355 : 3753159 : src = XEXP (src, 0);
2356 : : break;
2357 : :
2358 : 70586 : case SMAX:
2359 : 70586 : case SMIN:
2360 : 70586 : case UMAX:
2361 : 70586 : case UMIN:
2362 : 70586 : if ((mode == DImode && !TARGET_AVX512VL)
2363 : 17442 : || (mode == SImode && !TARGET_SSE4_1))
2364 : : return false;
2365 : : /* Fallthru. */
2366 : :
2367 : 3295357 : case AND:
2368 : 3295357 : case IOR:
2369 : 3295357 : case XOR:
2370 : 3295357 : case PLUS:
2371 : 3295357 : case MINUS:
2372 : 3295357 : if (!REG_P (XEXP (src, 1))
2373 : : && !MEM_P (XEXP (src, 1))
2374 : : && !CONST_INT_P (XEXP (src, 1)))
2375 : : return false;
2376 : :
2377 : 3198410 : if (GET_MODE (XEXP (src, 1)) != mode
2378 : 1861088 : && !CONST_INT_P (XEXP (src, 1)))
2379 : : return false;
2380 : :
2381 : : /* Check for andnot case. */
2382 : 3198410 : if (GET_CODE (src) != AND
2383 : 188127 : || GET_CODE (XEXP (src, 0)) != NOT)
2384 : : break;
2385 : :
2386 : 3753159 : src = XEXP (src, 0);
2387 : : /* FALLTHRU */
2388 : :
2389 : : case NOT:
2390 : : break;
2391 : :
2392 : 25486 : case NEG:
2393 : : /* Check for nabs case. */
2394 : 25486 : if (GET_CODE (XEXP (src, 0)) != ABS)
2395 : : break;
2396 : :
2397 : : src = XEXP (src, 0);
2398 : : /* FALLTHRU */
2399 : :
2400 : 3138 : case ABS:
2401 : 3138 : if ((mode == DImode && !TARGET_AVX512VL)
2402 : 1475 : || (mode == SImode && !TARGET_SSSE3))
2403 : : return false;
2404 : : break;
2405 : :
2406 : : case REG:
2407 : : return true;
2408 : :
2409 : 6110040 : case MEM:
2410 : 6110040 : case CONST_INT:
2411 : 6110040 : return REG_P (dst);
2412 : :
2413 : 52909 : case VEC_SELECT:
2414 : : /* Excluding MEM_P (dst) avoids intefering with vpextr[dq]. */
2415 : 52909 : return REG_P (dst)
2416 : 42582 : && REG_P (XEXP (src, 0))
2417 : 48657 : && GET_MODE (XEXP (src, 0)) == (mode == DImode ? V2DImode
2418 : : : V4SImode)
2419 : 33592 : && GET_CODE (XEXP (src, 1)) == PARALLEL
2420 : 33592 : && XVECLEN (XEXP (src, 1), 0) == 1
2421 : 86501 : && CONST_INT_P (XVECEXP (XEXP (src, 1), 0, 0));
2422 : :
2423 : : default:
2424 : : return false;
2425 : : }
2426 : :
2427 : 3753159 : if (!REG_P (XEXP (src, 0))
2428 : : && !MEM_P (XEXP (src, 0))
2429 : : && !CONST_INT_P (XEXP (src, 0)))
2430 : : return false;
2431 : :
2432 : 3448009 : if (GET_MODE (XEXP (src, 0)) != mode
2433 : 0 : && !CONST_INT_P (XEXP (src, 0)))
2434 : : return false;
2435 : :
2436 : : return true;
2437 : : }
2438 : :
2439 : : /* Check for a suitable TImode memory operand. */
2440 : :
2441 : : static bool
2442 : 1549 : timode_mem_p (rtx x)
2443 : : {
2444 : 1549 : return MEM_P (x)
2445 : 1549 : && (TARGET_SSE_UNALIGNED_LOAD_OPTIMAL
2446 : 0 : || !misaligned_operand (x, TImode));
2447 : : }
2448 : :
2449 : : /* The TImode version of scalar_to_vector_candidate_p. */
2450 : :
2451 : : static bool
2452 : 104206562 : timode_scalar_to_vector_candidate_p (rtx_insn *insn)
2453 : : {
2454 : 104206562 : rtx def_set = pseudo_reg_set (insn);
2455 : :
2456 : 104206562 : if (!def_set)
2457 : : return false;
2458 : :
2459 : 24348729 : rtx src = SET_SRC (def_set);
2460 : 24348729 : rtx dst = SET_DEST (def_set);
2461 : :
2462 : 24348729 : if (GET_CODE (src) == COMPARE)
2463 : 4109538 : return convertible_comparison_p (insn, TImode);
2464 : :
2465 : 20239191 : if (GET_MODE (dst) != TImode
2466 : 1254143 : || (GET_MODE (src) != TImode
2467 : 69213 : && !CONST_SCALAR_INT_P (src)))
2468 : : return false;
2469 : :
2470 : 1254143 : if (!REG_P (dst) && !MEM_P (dst))
2471 : : return false;
2472 : :
2473 : 1252692 : if (MEM_P (dst)
2474 : 554435 : && misaligned_operand (dst, TImode)
2475 : 1571311 : && !TARGET_SSE_UNALIGNED_STORE_OPTIMAL)
2476 : : return false;
2477 : :
2478 : 1252687 : if (REG_P (dst) && !single_def_chain_p (dst))
2479 : : return false;
2480 : :
2481 : 1085430 : switch (GET_CODE (src))
2482 : : {
2483 : 504228 : case REG:
2484 : 504228 : return single_def_chain_p (src);
2485 : :
2486 : : case CONST_WIDE_INT:
2487 : : return true;
2488 : :
2489 : 13263 : case CONST_INT:
2490 : : /* ??? Verify performance impact before enabling CONST_INT for
2491 : : __int128 store. */
2492 : 13263 : return standard_sse_constant_p (src, TImode);
2493 : :
2494 : 459995 : case MEM:
2495 : : /* Memory must be aligned or unaligned load is optimal. */
2496 : 459995 : return (REG_P (dst)
2497 : 459995 : && (!misaligned_operand (src, TImode)
2498 : 151583 : || TARGET_SSE_UNALIGNED_LOAD_OPTIMAL));
2499 : :
2500 : 4841 : case AND:
2501 : 4841 : if (!MEM_P (dst)
2502 : 4804 : && GET_CODE (XEXP (src, 0)) == NOT
2503 : 0 : && REG_P (XEXP (XEXP (src, 0), 0))
2504 : 4841 : && (REG_P (XEXP (src, 1))
2505 : 0 : || CONST_SCALAR_INT_P (XEXP (src, 1))
2506 : 0 : || timode_mem_p (XEXP (src, 1))))
2507 : 0 : return true;
2508 : 4841 : return (REG_P (XEXP (src, 0))
2509 : 42 : || timode_mem_p (XEXP (src, 0)))
2510 : 4883 : && (REG_P (XEXP (src, 1))
2511 : 3002 : || CONST_SCALAR_INT_P (XEXP (src, 1))
2512 : 35 : || timode_mem_p (XEXP (src, 1)));
2513 : :
2514 : 14246 : case IOR:
2515 : 14246 : case XOR:
2516 : 14246 : if (timode_concatdi_p (src))
2517 : : return true;
2518 : 2679 : return (REG_P (XEXP (src, 0))
2519 : 1425 : || timode_mem_p (XEXP (src, 0)))
2520 : 2687 : && (REG_P (XEXP (src, 1))
2521 : 271 : || CONST_SCALAR_INT_P (XEXP (src, 1))
2522 : 31 : || timode_mem_p (XEXP (src, 1)));
2523 : :
2524 : 635 : case NOT:
2525 : 635 : return REG_P (XEXP (src, 0)) || timode_mem_p (XEXP (src, 0));
2526 : :
2527 : 13209 : case ASHIFT:
2528 : 13209 : case LSHIFTRT:
2529 : 13209 : case ASHIFTRT:
2530 : 13209 : case ROTATERT:
2531 : 13209 : case ROTATE:
2532 : : /* Handle shifts/rotates by integer constants between 0 and 127. */
2533 : 13209 : return REG_P (XEXP (src, 0))
2534 : 13172 : && CONST_INT_P (XEXP (src, 1))
2535 : 26033 : && (INTVAL (XEXP (src, 1)) & ~0x7f) == 0;
2536 : :
2537 : 7697 : case PLUS:
2538 : 7697 : return timode_concatdi_p (src);
2539 : :
2540 : 4074 : case ZERO_EXTEND:
2541 : 4074 : return REG_P (XEXP (src, 0))
2542 : 4074 : && GET_MODE (XEXP (src, 0)) == DImode;
2543 : :
2544 : : default:
2545 : : return false;
2546 : : }
2547 : : }
2548 : :
2549 : : /* For a register REGNO, scan instructions for its defs and uses.
2550 : : Put REGNO in REGS if a def or use isn't in CANDIDATES. */
2551 : :
2552 : : static void
2553 : 1318841 : timode_check_non_convertible_regs (bitmap candidates, bitmap regs,
2554 : : unsigned int regno)
2555 : : {
2556 : : /* Do nothing if REGNO is already in REGS or is a hard reg. */
2557 : 1318841 : if (bitmap_bit_p (regs, regno)
2558 : 1318841 : || HARD_REGISTER_NUM_P (regno))
2559 : : return;
2560 : :
2561 : 1304634 : for (df_ref def = DF_REG_DEF_CHAIN (regno);
2562 : 2584105 : def;
2563 : 1279471 : def = DF_REF_NEXT_REG (def))
2564 : : {
2565 : 1304614 : if (!bitmap_bit_p (candidates, DF_REF_INSN_UID (def)))
2566 : : {
2567 : 25143 : if (dump_file)
2568 : 0 : fprintf (dump_file,
2569 : : "r%d has non convertible def in insn %d\n",
2570 : 0 : regno, DF_REF_INSN_UID (def));
2571 : :
2572 : 25143 : bitmap_set_bit (regs, regno);
2573 : 25143 : break;
2574 : : }
2575 : : }
2576 : :
2577 : 1304634 : for (df_ref ref = DF_REG_USE_CHAIN (regno);
2578 : 2863379 : ref;
2579 : 1558745 : ref = DF_REF_NEXT_REG (ref))
2580 : : {
2581 : : /* Debug instructions are skipped. */
2582 : 1625882 : if (NONDEBUG_INSN_P (DF_REF_INSN (ref))
2583 : 1625882 : && !bitmap_bit_p (candidates, DF_REF_INSN_UID (ref)))
2584 : : {
2585 : 67137 : if (dump_file)
2586 : 0 : fprintf (dump_file,
2587 : : "r%d has non convertible use in insn %d\n",
2588 : 0 : regno, DF_REF_INSN_UID (ref));
2589 : :
2590 : 67137 : bitmap_set_bit (regs, regno);
2591 : 67137 : break;
2592 : : }
2593 : : }
2594 : : }
2595 : :
2596 : : /* For a given bitmap of insn UIDs scans all instructions and
2597 : : remove insn from CANDIDATES in case it has both convertible
2598 : : and not convertible definitions.
2599 : :
2600 : : All insns in a bitmap are conversion candidates according to
2601 : : scalar_to_vector_candidate_p. Currently it implies all insns
2602 : : are single_set. */
2603 : :
2604 : : static void
2605 : 838408 : timode_remove_non_convertible_regs (bitmap candidates)
2606 : : {
2607 : 838408 : bitmap_iterator bi;
2608 : 838408 : unsigned id;
2609 : 838408 : bitmap regs = BITMAP_ALLOC (NULL);
2610 : 866086 : bool changed;
2611 : :
2612 : 866086 : do {
2613 : 866086 : changed = false;
2614 : 2219794 : EXECUTE_IF_SET_IN_BITMAP (candidates, 0, id, bi)
2615 : : {
2616 : 1353708 : rtx_insn *insn = DF_INSN_UID_GET (id)->insn;
2617 : 1353708 : df_ref ref;
2618 : :
2619 : 2029511 : FOR_EACH_INSN_DEF (ref, insn)
2620 : 675803 : if (!DF_REF_REG_MEM_P (ref)
2621 : 675803 : && GET_MODE (DF_REF_REG (ref)) == TImode)
2622 : 651217 : timode_check_non_convertible_regs (candidates, regs,
2623 : : DF_REF_REGNO (ref));
2624 : :
2625 : 3338231 : FOR_EACH_INSN_USE (ref, insn)
2626 : 1984523 : if (!DF_REF_REG_MEM_P (ref)
2627 : 698710 : && GET_MODE (DF_REF_REG (ref)) == TImode)
2628 : 667624 : timode_check_non_convertible_regs (candidates, regs,
2629 : : DF_REF_REGNO (ref));
2630 : : }
2631 : :
2632 : 1063991 : EXECUTE_IF_SET_IN_BITMAP (regs, 0, id, bi)
2633 : : {
2634 : 197905 : for (df_ref def = DF_REG_DEF_CHAIN (id);
2635 : 404412 : def;
2636 : 206507 : def = DF_REF_NEXT_REG (def))
2637 : 206507 : if (bitmap_bit_p (candidates, DF_REF_INSN_UID (def)))
2638 : : {
2639 : 50361 : if (dump_file)
2640 : 0 : fprintf (dump_file, "Removing insn %d from candidates list\n",
2641 : 0 : DF_REF_INSN_UID (def));
2642 : :
2643 : 50361 : bitmap_clear_bit (candidates, DF_REF_INSN_UID (def));
2644 : 50361 : changed = true;
2645 : : }
2646 : :
2647 : 197905 : for (df_ref ref = DF_REG_USE_CHAIN (id);
2648 : 560928 : ref;
2649 : 363023 : ref = DF_REF_NEXT_REG (ref))
2650 : 363023 : if (bitmap_bit_p (candidates, DF_REF_INSN_UID (ref)))
2651 : : {
2652 : 37464 : if (dump_file)
2653 : 0 : fprintf (dump_file, "Removing insn %d from candidates list\n",
2654 : 0 : DF_REF_INSN_UID (ref));
2655 : :
2656 : 37464 : bitmap_clear_bit (candidates, DF_REF_INSN_UID (ref));
2657 : 37464 : changed = true;
2658 : : }
2659 : : }
2660 : : } while (changed);
2661 : :
2662 : 838408 : BITMAP_FREE (regs);
2663 : 838408 : }
2664 : :
2665 : : /* Main STV pass function. Find and convert scalar
2666 : : instructions into vector mode when profitable. */
2667 : :
2668 : : static unsigned int
2669 : 1802458 : convert_scalars_to_vector (bool timode_p)
2670 : : {
2671 : 1802458 : basic_block bb;
2672 : 1802458 : int converted_insns = 0;
2673 : 1802458 : auto_vec<rtx_insn *> control_flow_insns;
2674 : :
2675 : 1802458 : bitmap_obstack_initialize (NULL);
2676 : 1802458 : const machine_mode cand_mode[3] = { SImode, DImode, TImode };
2677 : 1802458 : const machine_mode cand_vmode[3] = { V4SImode, V2DImode, V1TImode };
2678 : 5407374 : bitmap_head candidates[3]; /* { SImode, DImode, TImode } */
2679 : 7209832 : for (unsigned i = 0; i < 3; ++i)
2680 : 5407374 : bitmap_initialize (&candidates[i], &bitmap_default_obstack);
2681 : :
2682 : 1802458 : calculate_dominance_info (CDI_DOMINATORS);
2683 : 1802458 : df_set_flags (DF_DEFER_INSN_RESCAN | DF_RD_PRUNE_DEAD_DEFS);
2684 : 1802458 : df_chain_add_problem (DF_DU_CHAIN | DF_UD_CHAIN);
2685 : 1802458 : df_analyze ();
2686 : :
2687 : : /* Find all instructions we want to convert into vector mode. */
2688 : 1802458 : if (dump_file)
2689 : 44 : fprintf (dump_file, "Searching for mode conversion candidates...\n");
2690 : :
2691 : 20231648 : FOR_EACH_BB_FN (bb, cfun)
2692 : : {
2693 : 18429190 : rtx_insn *insn;
2694 : 245122329 : FOR_BB_INSNS (bb, insn)
2695 : 226693139 : if (timode_p
2696 : 226693139 : && timode_scalar_to_vector_candidate_p (insn))
2697 : : {
2698 : 1048230 : if (dump_file)
2699 : 0 : fprintf (dump_file, " insn %d is marked as a TImode candidate\n",
2700 : 0 : INSN_UID (insn));
2701 : :
2702 : 1048230 : bitmap_set_bit (&candidates[2], INSN_UID (insn));
2703 : : }
2704 : 225644909 : else if (!timode_p)
2705 : : {
2706 : : /* Check {SI,DI}mode. */
2707 : 351995794 : for (unsigned i = 0; i <= 1; ++i)
2708 : 241372671 : if (general_scalar_to_vector_candidate_p (insn, cand_mode[i]))
2709 : : {
2710 : 11863454 : if (dump_file)
2711 : 554 : fprintf (dump_file, " insn %d is marked as a %s candidate\n",
2712 : 277 : INSN_UID (insn), i == 0 ? "SImode" : "DImode");
2713 : :
2714 : 11863454 : bitmap_set_bit (&candidates[i], INSN_UID (insn));
2715 : 11863454 : break;
2716 : : }
2717 : : }
2718 : : }
2719 : :
2720 : 1802458 : if (timode_p)
2721 : 838408 : timode_remove_non_convertible_regs (&candidates[2]);
2722 : :
2723 : 5710802 : for (unsigned i = 0; i <= 2; ++i)
2724 : 4547332 : if (!bitmap_empty_p (&candidates[i]))
2725 : : break;
2726 : 3908344 : else if (i == 2 && dump_file)
2727 : 23 : fprintf (dump_file, "There are no candidates for optimization.\n");
2728 : :
2729 : 7209832 : for (unsigned i = 0; i <= 2; ++i)
2730 : : {
2731 : 5407374 : auto_bitmap disallowed;
2732 : 5407374 : bitmap_tree_view (&candidates[i]);
2733 : 17305883 : while (!bitmap_empty_p (&candidates[i]))
2734 : : {
2735 : 6491135 : unsigned uid = bitmap_first_set_bit (&candidates[i]);
2736 : 6491135 : scalar_chain *chain;
2737 : :
2738 : 6491135 : if (cand_mode[i] == TImode)
2739 : 489417 : chain = new timode_scalar_chain;
2740 : : else
2741 : 6001718 : chain = new general_scalar_chain (cand_mode[i], cand_vmode[i]);
2742 : :
2743 : : /* Find instructions chain we want to convert to vector mode.
2744 : : Check all uses and definitions to estimate all required
2745 : : conversions. */
2746 : 6491135 : if (chain->build (&candidates[i], uid, disallowed))
2747 : : {
2748 : 6490626 : if (chain->compute_convert_gain ())
2749 : 659608 : converted_insns += chain->convert ();
2750 : 5831018 : else if (dump_file)
2751 : 136 : fprintf (dump_file, "Chain #%d conversion is not profitable\n",
2752 : : chain->chain_id);
2753 : : }
2754 : :
2755 : 6491135 : rtx_insn* iter_insn;
2756 : 6491135 : unsigned int ii;
2757 : 6494888 : FOR_EACH_VEC_ELT (chain->control_flow_insns, ii, iter_insn)
2758 : 3753 : control_flow_insns.safe_push (iter_insn);
2759 : :
2760 : 6491135 : delete chain;
2761 : : }
2762 : 5407374 : }
2763 : :
2764 : 1802458 : if (dump_file)
2765 : 44 : fprintf (dump_file, "Total insns converted: %d\n", converted_insns);
2766 : :
2767 : 7209832 : for (unsigned i = 0; i <= 2; ++i)
2768 : 5407374 : bitmap_release (&candidates[i]);
2769 : 1802458 : bitmap_obstack_release (NULL);
2770 : 1802458 : df_process_deferred_rescans ();
2771 : :
2772 : : /* Conversion means we may have 128bit register spills/fills
2773 : : which require aligned stack. */
2774 : 1802458 : if (converted_insns)
2775 : : {
2776 : 107000 : if (crtl->stack_alignment_needed < 128)
2777 : 2345 : crtl->stack_alignment_needed = 128;
2778 : 107000 : if (crtl->stack_alignment_estimated < 128)
2779 : 194 : crtl->stack_alignment_estimated = 128;
2780 : :
2781 : 107000 : crtl->stack_realign_needed
2782 : 107000 : = INCOMING_STACK_BOUNDARY < crtl->stack_alignment_estimated;
2783 : 107000 : crtl->stack_realign_tried = crtl->stack_realign_needed;
2784 : :
2785 : 107000 : crtl->stack_realign_processed = true;
2786 : :
2787 : 107000 : if (!crtl->drap_reg)
2788 : : {
2789 : 106835 : rtx drap_rtx = targetm.calls.get_drap_rtx ();
2790 : :
2791 : : /* stack_realign_drap and drap_rtx must match. */
2792 : 106835 : gcc_assert ((stack_realign_drap != 0) == (drap_rtx != NULL));
2793 : :
2794 : : /* Do nothing if NULL is returned,
2795 : : which means DRAP is not needed. */
2796 : 106835 : if (drap_rtx != NULL)
2797 : : {
2798 : 0 : crtl->args.internal_arg_pointer = drap_rtx;
2799 : :
2800 : : /* Call fixup_tail_calls to clean up
2801 : : REG_EQUIV note if DRAP is needed. */
2802 : 0 : fixup_tail_calls ();
2803 : : }
2804 : : }
2805 : :
2806 : : /* Fix up DECL_RTL/DECL_INCOMING_RTL of arguments. */
2807 : 107000 : if (TARGET_64BIT)
2808 : 68597 : for (tree parm = DECL_ARGUMENTS (current_function_decl);
2809 : 191423 : parm; parm = DECL_CHAIN (parm))
2810 : : {
2811 : 122826 : if (TYPE_MODE (TREE_TYPE (parm)) != TImode)
2812 : 106408 : continue;
2813 : 16418 : if (DECL_RTL_SET_P (parm)
2814 : 32836 : && GET_MODE (DECL_RTL (parm)) == V1TImode)
2815 : : {
2816 : 522 : rtx r = DECL_RTL (parm);
2817 : 522 : if (REG_P (r))
2818 : 522 : SET_DECL_RTL (parm, gen_rtx_SUBREG (TImode, r, 0));
2819 : : }
2820 : 16418 : if (DECL_INCOMING_RTL (parm)
2821 : 16418 : && GET_MODE (DECL_INCOMING_RTL (parm)) == V1TImode)
2822 : : {
2823 : 0 : rtx r = DECL_INCOMING_RTL (parm);
2824 : 0 : if (REG_P (r))
2825 : 0 : DECL_INCOMING_RTL (parm) = gen_rtx_SUBREG (TImode, r, 0);
2826 : : }
2827 : : }
2828 : :
2829 : 107000 : if (!control_flow_insns.is_empty ())
2830 : : {
2831 : 1170 : free_dominance_info (CDI_DOMINATORS);
2832 : :
2833 : 1170 : unsigned int i;
2834 : 1170 : rtx_insn* insn;
2835 : 6093 : FOR_EACH_VEC_ELT (control_flow_insns, i, insn)
2836 : 3753 : if (control_flow_insn_p (insn))
2837 : : {
2838 : : /* Split the block after insn. There will be a fallthru
2839 : : edge, which is OK so we keep it. We have to create
2840 : : the exception edges ourselves. */
2841 : 3753 : bb = BLOCK_FOR_INSN (insn);
2842 : 3753 : split_block (bb, insn);
2843 : 3753 : rtl_make_eh_edge (NULL, bb, BB_END (bb));
2844 : : }
2845 : : }
2846 : : }
2847 : :
2848 : 1802458 : return 0;
2849 : 1802458 : }
2850 : :
2851 : : static unsigned int
2852 : 74690 : rest_of_handle_insert_vzeroupper (void)
2853 : : {
2854 : : /* vzeroupper instructions are inserted immediately after reload and
2855 : : postreload_cse to clean up after it a little bit to account for possible
2856 : : spills from 256bit or 512bit registers. The pass reuses mode switching
2857 : : infrastructure by re-running mode insertion pass, so disable entities
2858 : : that have already been processed. */
2859 : 522830 : for (int i = 0; i < MAX_386_ENTITIES; i++)
2860 : 448140 : ix86_optimize_mode_switching[i] = 0;
2861 : :
2862 : 74690 : ix86_optimize_mode_switching[AVX_U128] = 1;
2863 : :
2864 : : /* Call optimize_mode_switching. */
2865 : 74690 : g->get_passes ()->execute_pass_mode_switching ();
2866 : :
2867 : : /* LRA removes all REG_DEAD/REG_UNUSED notes and normally they
2868 : : reappear in the IL only at the start of pass_rtl_dse2, which does
2869 : : df_note_add_problem (); df_analyze ();
2870 : : The vzeroupper is scheduled after postreload_cse pass and mode
2871 : : switching computes the notes as well, the problem is that e.g.
2872 : : pass_gcse2 doesn't maintain the notes, see PR113059 and
2873 : : PR112760. Remove the notes now to restore status quo ante
2874 : : until we figure out how to maintain the notes or what else
2875 : : to do. */
2876 : 74690 : basic_block bb;
2877 : 74690 : rtx_insn *insn;
2878 : 410499 : FOR_EACH_BB_FN (bb, cfun)
2879 : 4321730 : FOR_BB_INSNS (bb, insn)
2880 : 3985921 : if (NONDEBUG_INSN_P (insn))
2881 : : {
2882 : 2121416 : rtx *pnote = ®_NOTES (insn);
2883 : 3934960 : while (*pnote != 0)
2884 : : {
2885 : 1813544 : if (REG_NOTE_KIND (*pnote) == REG_DEAD
2886 : 831705 : || REG_NOTE_KIND (*pnote) == REG_UNUSED)
2887 : 1300323 : *pnote = XEXP (*pnote, 1);
2888 : : else
2889 : 513221 : pnote = &XEXP (*pnote, 1);
2890 : : }
2891 : : }
2892 : :
2893 : 74690 : df_remove_problem (df_note);
2894 : 74690 : df_analyze ();
2895 : 74690 : return 0;
2896 : : }
2897 : :
2898 : : namespace {
2899 : :
2900 : : const pass_data pass_data_insert_vzeroupper =
2901 : : {
2902 : : RTL_PASS, /* type */
2903 : : "vzeroupper", /* name */
2904 : : OPTGROUP_NONE, /* optinfo_flags */
2905 : : TV_MACH_DEP, /* tv_id */
2906 : : 0, /* properties_required */
2907 : : 0, /* properties_provided */
2908 : : 0, /* properties_destroyed */
2909 : : 0, /* todo_flags_start */
2910 : : TODO_df_finish, /* todo_flags_finish */
2911 : : };
2912 : :
2913 : : class pass_insert_vzeroupper : public rtl_opt_pass
2914 : : {
2915 : : public:
2916 : 290417 : pass_insert_vzeroupper(gcc::context *ctxt)
2917 : 580834 : : rtl_opt_pass(pass_data_insert_vzeroupper, ctxt)
2918 : : {}
2919 : :
2920 : : /* opt_pass methods: */
2921 : 1478637 : bool gate (function *) final override
2922 : : {
2923 : 1478637 : return TARGET_AVX && TARGET_VZEROUPPER;
2924 : : }
2925 : :
2926 : 74690 : unsigned int execute (function *) final override
2927 : : {
2928 : 74690 : return rest_of_handle_insert_vzeroupper ();
2929 : : }
2930 : :
2931 : : }; // class pass_insert_vzeroupper
2932 : :
2933 : : const pass_data pass_data_stv =
2934 : : {
2935 : : RTL_PASS, /* type */
2936 : : "stv", /* name */
2937 : : OPTGROUP_NONE, /* optinfo_flags */
2938 : : TV_MACH_DEP, /* tv_id */
2939 : : 0, /* properties_required */
2940 : : 0, /* properties_provided */
2941 : : 0, /* properties_destroyed */
2942 : : 0, /* todo_flags_start */
2943 : : TODO_df_finish, /* todo_flags_finish */
2944 : : };
2945 : :
2946 : : class pass_stv : public rtl_opt_pass
2947 : : {
2948 : : public:
2949 : 580834 : pass_stv (gcc::context *ctxt)
2950 : 580834 : : rtl_opt_pass (pass_data_stv, ctxt),
2951 : 1161668 : timode_p (false)
2952 : : {}
2953 : :
2954 : : /* opt_pass methods: */
2955 : 2957274 : bool gate (function *) final override
2956 : : {
2957 : 1478637 : return ((!timode_p || TARGET_64BIT)
2958 : 4309948 : && TARGET_STV && TARGET_SSE2 && optimize > 1);
2959 : : }
2960 : :
2961 : 1802458 : unsigned int execute (function *) final override
2962 : : {
2963 : 1802458 : return convert_scalars_to_vector (timode_p);
2964 : : }
2965 : :
2966 : 290417 : opt_pass *clone () final override
2967 : : {
2968 : 290417 : return new pass_stv (m_ctxt);
2969 : : }
2970 : :
2971 : 580834 : void set_pass_param (unsigned int n, bool param) final override
2972 : : {
2973 : 580834 : gcc_assert (n == 0);
2974 : 580834 : timode_p = param;
2975 : 580834 : }
2976 : :
2977 : : private:
2978 : : bool timode_p;
2979 : : }; // class pass_stv
2980 : :
2981 : : } // anon namespace
2982 : :
2983 : : rtl_opt_pass *
2984 : 290417 : make_pass_insert_vzeroupper (gcc::context *ctxt)
2985 : : {
2986 : 290417 : return new pass_insert_vzeroupper (ctxt);
2987 : : }
2988 : :
2989 : : rtl_opt_pass *
2990 : 290417 : make_pass_stv (gcc::context *ctxt)
2991 : : {
2992 : 290417 : return new pass_stv (ctxt);
2993 : : }
2994 : :
2995 : : /* Inserting ENDBR and pseudo patchable-area instructions. */
2996 : :
2997 : : static void
2998 : 208882 : rest_of_insert_endbr_and_patchable_area (bool need_endbr,
2999 : : unsigned int patchable_area_size)
3000 : : {
3001 : 208882 : rtx endbr;
3002 : 208882 : rtx_insn *insn;
3003 : 208882 : rtx_insn *endbr_insn = NULL;
3004 : 208882 : basic_block bb;
3005 : :
3006 : 208882 : if (need_endbr)
3007 : : {
3008 : : /* Currently emit EB if it's a tracking function, i.e. 'nocf_check'
3009 : : is absent among function attributes. Later an optimization will
3010 : : be introduced to make analysis if an address of a static function
3011 : : is taken. A static function whose address is not taken will get
3012 : : a nocf_check attribute. This will allow to reduce the number of
3013 : : EB. */
3014 : 208837 : if (!lookup_attribute ("nocf_check",
3015 : 208837 : TYPE_ATTRIBUTES (TREE_TYPE (cfun->decl)))
3016 : 208819 : && (!flag_manual_endbr
3017 : 8 : || lookup_attribute ("cf_check",
3018 : 8 : DECL_ATTRIBUTES (cfun->decl)))
3019 : 417655 : && (!cgraph_node::get (cfun->decl)->only_called_directly_p ()
3020 : 28803 : || ix86_cmodel == CM_LARGE
3021 : 28802 : || ix86_cmodel == CM_LARGE_PIC
3022 : 28801 : || flag_force_indirect_call
3023 : 28801 : || (TARGET_DLLIMPORT_DECL_ATTRIBUTES
3024 : : && DECL_DLLIMPORT_P (cfun->decl))))
3025 : : {
3026 : 180018 : if (crtl->profile && flag_fentry)
3027 : : {
3028 : : /* Queue ENDBR insertion to x86_function_profiler.
3029 : : NB: Any patchable-area insn will be inserted after
3030 : : ENDBR. */
3031 : 6 : cfun->machine->insn_queued_at_entrance = TYPE_ENDBR;
3032 : : }
3033 : : else
3034 : : {
3035 : 180012 : endbr = gen_nop_endbr ();
3036 : 180012 : bb = ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb;
3037 : 180012 : rtx_insn *insn = BB_HEAD (bb);
3038 : 180012 : endbr_insn = emit_insn_before (endbr, insn);
3039 : : }
3040 : : }
3041 : : }
3042 : :
3043 : 208882 : if (patchable_area_size)
3044 : : {
3045 : 51 : if (crtl->profile && flag_fentry)
3046 : : {
3047 : : /* Queue patchable-area insertion to x86_function_profiler.
3048 : : NB: If there is a queued ENDBR, x86_function_profiler
3049 : : will also handle patchable-area. */
3050 : 2 : if (!cfun->machine->insn_queued_at_entrance)
3051 : 1 : cfun->machine->insn_queued_at_entrance = TYPE_PATCHABLE_AREA;
3052 : : }
3053 : : else
3054 : : {
3055 : 49 : rtx patchable_area
3056 : 49 : = gen_patchable_area (GEN_INT (patchable_area_size),
3057 : 49 : GEN_INT (crtl->patch_area_entry == 0));
3058 : 49 : if (endbr_insn)
3059 : 3 : emit_insn_after (patchable_area, endbr_insn);
3060 : : else
3061 : : {
3062 : 46 : bb = ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb;
3063 : 46 : insn = BB_HEAD (bb);
3064 : 46 : emit_insn_before (patchable_area, insn);
3065 : : }
3066 : : }
3067 : : }
3068 : :
3069 : 208882 : if (!need_endbr)
3070 : : return;
3071 : :
3072 : 208837 : bb = 0;
3073 : 4342151 : FOR_EACH_BB_FN (bb, cfun)
3074 : : {
3075 : 76486285 : for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
3076 : 72352971 : insn = NEXT_INSN (insn))
3077 : : {
3078 : 72352971 : if (CALL_P (insn))
3079 : : {
3080 : 1443162 : need_endbr = find_reg_note (insn, REG_SETJMP, NULL) != NULL;
3081 : 1443162 : if (!need_endbr && !SIBLING_CALL_P (insn))
3082 : : {
3083 : 1389675 : rtx call = get_call_rtx_from (insn);
3084 : 1389675 : rtx fnaddr = XEXP (call, 0);
3085 : 1389675 : tree fndecl = NULL_TREE;
3086 : :
3087 : : /* Also generate ENDBRANCH for non-tail call which
3088 : : may return via indirect branch. */
3089 : 1389675 : if (SYMBOL_REF_P (XEXP (fnaddr, 0)))
3090 : 1320336 : fndecl = SYMBOL_REF_DECL (XEXP (fnaddr, 0));
3091 : 1320336 : if (fndecl == NULL_TREE)
3092 : 69707 : fndecl = MEM_EXPR (fnaddr);
3093 : 69707 : if (fndecl
3094 : 1386775 : && TREE_CODE (TREE_TYPE (fndecl)) != FUNCTION_TYPE
3095 : 627350 : && TREE_CODE (TREE_TYPE (fndecl)) != METHOD_TYPE)
3096 : : fndecl = NULL_TREE;
3097 : 1389675 : if (fndecl && TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
3098 : : {
3099 : 1346070 : tree fntype = TREE_TYPE (fndecl);
3100 : 1346070 : if (lookup_attribute ("indirect_return",
3101 : 1346070 : TYPE_ATTRIBUTES (fntype)))
3102 : : need_endbr = true;
3103 : : }
3104 : : }
3105 : 1443150 : if (!need_endbr)
3106 : 1443144 : continue;
3107 : : /* Generate ENDBRANCH after CALL, which can return more than
3108 : : twice, setjmp-like functions. */
3109 : :
3110 : 18 : endbr = gen_nop_endbr ();
3111 : 18 : emit_insn_after_setloc (endbr, insn, INSN_LOCATION (insn));
3112 : 18 : continue;
3113 : 18 : }
3114 : :
3115 : 70909809 : if (JUMP_P (insn) && flag_cet_switch)
3116 : : {
3117 : 9 : rtx target = JUMP_LABEL (insn);
3118 : 9 : if (target == NULL_RTX || ANY_RETURN_P (target))
3119 : 5 : continue;
3120 : :
3121 : : /* Check the jump is a switch table. */
3122 : 4 : rtx_insn *label = as_a<rtx_insn *> (target);
3123 : 4 : rtx_insn *table = next_insn (label);
3124 : 4 : if (table == NULL_RTX || !JUMP_TABLE_DATA_P (table))
3125 : 2 : continue;
3126 : :
3127 : : /* For the indirect jump find out all places it jumps and insert
3128 : : ENDBRANCH there. It should be done under a special flag to
3129 : : control ENDBRANCH generation for switch stmts. */
3130 : 2 : edge_iterator ei;
3131 : 2 : edge e;
3132 : 2 : basic_block dest_blk;
3133 : :
3134 : 24 : FOR_EACH_EDGE (e, ei, bb->succs)
3135 : : {
3136 : 22 : rtx_insn *insn;
3137 : :
3138 : 22 : dest_blk = e->dest;
3139 : 22 : insn = BB_HEAD (dest_blk);
3140 : 22 : gcc_assert (LABEL_P (insn));
3141 : 22 : endbr = gen_nop_endbr ();
3142 : 22 : emit_insn_after (endbr, insn);
3143 : : }
3144 : 2 : continue;
3145 : 2 : }
3146 : :
3147 : 70909800 : if (LABEL_P (insn) && LABEL_PRESERVE_P (insn))
3148 : : {
3149 : 145807 : endbr = gen_nop_endbr ();
3150 : 145807 : emit_insn_after (endbr, insn);
3151 : 145807 : continue;
3152 : : }
3153 : : }
3154 : : }
3155 : :
3156 : : return;
3157 : : }
3158 : :
3159 : : namespace {
3160 : :
3161 : : const pass_data pass_data_insert_endbr_and_patchable_area =
3162 : : {
3163 : : RTL_PASS, /* type. */
3164 : : "endbr_and_patchable_area", /* name. */
3165 : : OPTGROUP_NONE, /* optinfo_flags. */
3166 : : TV_MACH_DEP, /* tv_id. */
3167 : : 0, /* properties_required. */
3168 : : 0, /* properties_provided. */
3169 : : 0, /* properties_destroyed. */
3170 : : 0, /* todo_flags_start. */
3171 : : 0, /* todo_flags_finish. */
3172 : : };
3173 : :
3174 : : class pass_insert_endbr_and_patchable_area : public rtl_opt_pass
3175 : : {
3176 : : public:
3177 : 290417 : pass_insert_endbr_and_patchable_area (gcc::context *ctxt)
3178 : 580834 : : rtl_opt_pass (pass_data_insert_endbr_and_patchable_area, ctxt)
3179 : : {}
3180 : :
3181 : : /* opt_pass methods: */
3182 : 1478637 : bool gate (function *) final override
3183 : : {
3184 : 1478637 : need_endbr = (flag_cf_protection & CF_BRANCH) != 0;
3185 : 1478637 : patchable_area_size = crtl->patch_area_size - crtl->patch_area_entry;
3186 : 1478637 : return need_endbr || patchable_area_size;
3187 : : }
3188 : :
3189 : 208882 : unsigned int execute (function *) final override
3190 : : {
3191 : 208882 : timevar_push (TV_MACH_DEP);
3192 : 208882 : rest_of_insert_endbr_and_patchable_area (need_endbr,
3193 : : patchable_area_size);
3194 : 208882 : timevar_pop (TV_MACH_DEP);
3195 : 208882 : return 0;
3196 : : }
3197 : :
3198 : : private:
3199 : : bool need_endbr;
3200 : : unsigned int patchable_area_size;
3201 : : }; // class pass_insert_endbr_and_patchable_area
3202 : :
3203 : : } // anon namespace
3204 : :
3205 : : rtl_opt_pass *
3206 : 290417 : make_pass_insert_endbr_and_patchable_area (gcc::context *ctxt)
3207 : : {
3208 : 290417 : return new pass_insert_endbr_and_patchable_area (ctxt);
3209 : : }
3210 : :
3211 : : bool
3212 : 6115533 : ix86_rpad_gate ()
3213 : : {
3214 : 6115533 : return (TARGET_AVX
3215 : 406168 : && TARGET_SSE_PARTIAL_REG_DEPENDENCY
3216 : 311511 : && TARGET_SSE_MATH
3217 : 311281 : && optimize
3218 : 6421659 : && optimize_function_for_speed_p (cfun));
3219 : : }
3220 : :
3221 : : enum x86_cse_kind
3222 : : {
3223 : : X86_CSE_CONST0_VECTOR,
3224 : : X86_CSE_CONSTM1_VECTOR,
3225 : : X86_CSE_VEC_DUP,
3226 : : X86_CSE_TLS_GD,
3227 : : X86_CSE_TLS_LD_BASE,
3228 : : X86_CSE_TLSDESC
3229 : : };
3230 : :
3231 : 124444 : struct redundant_pattern
3232 : : {
3233 : : /* Bitmap of basic blocks with broadcast instructions. */
3234 : : auto_bitmap bbs;
3235 : : /* Bitmap of broadcast instructions. */
3236 : : auto_bitmap insns;
3237 : : /* The broadcast inner scalar. */
3238 : : rtx val;
3239 : : /* The actual redundant source value for UNSPEC_TLSDESC. */
3240 : : rtx tlsdesc_val;
3241 : : /* The inner scalar mode. */
3242 : : machine_mode mode;
3243 : : /* The instruction which sets the inner scalar. Nullptr if the inner
3244 : : scalar is applied to the whole function, instead of within the same
3245 : : block. */
3246 : : rtx_insn *def_insn;
3247 : : /* The widest broadcast source. */
3248 : : rtx broadcast_source;
3249 : : /* The widest broadcast register. */
3250 : : rtx broadcast_reg;
3251 : : /* The basic block of the broadcast instruction. */
3252 : : basic_block bb;
3253 : : /* The number of broadcast instructions with the same inner scalar. */
3254 : : unsigned HOST_WIDE_INT count;
3255 : : /* The threshold of broadcast instructions with the same inner
3256 : : scalar. */
3257 : : unsigned int threshold;
3258 : : /* The widest broadcast size in bytes. */
3259 : : unsigned int size;
3260 : : /* Load kind. */
3261 : : x86_cse_kind kind;
3262 : : };
3263 : :
3264 : : /* Generate a vector set, DEST = SRC, at entry of the nearest dominator
3265 : : for basic block map BBS, which is in the fake loop that contains the
3266 : : whole function, so that there is only a single vector set in the
3267 : : whole function. If not nullptr, LOAD is a pointer to the load. */
3268 : :
3269 : : static void
3270 : 33616 : ix86_place_single_vector_set (rtx dest, rtx src, bitmap bbs,
3271 : : redundant_pattern *load = nullptr)
3272 : : {
3273 : 33616 : basic_block bb = nearest_common_dominator_for_set (CDI_DOMINATORS, bbs);
3274 : : /* For X86_CSE_VEC_DUP, don't place the vector set outside of the loop
3275 : : to avoid extra spills. */
3276 : 33616 : if (!load || load->kind != X86_CSE_VEC_DUP)
3277 : : {
3278 : 24779 : while (bb->loop_father->latch
3279 : 24779 : != EXIT_BLOCK_PTR_FOR_FN (cfun))
3280 : 1358 : bb = get_immediate_dominator (CDI_DOMINATORS,
3281 : : bb->loop_father->header);
3282 : : }
3283 : :
3284 : 33616 : rtx set = gen_rtx_SET (dest, src);
3285 : :
3286 : 33616 : rtx_insn *insn = BB_HEAD (bb);
3287 : 141683 : while (insn && !NONDEBUG_INSN_P (insn))
3288 : : {
3289 : 108071 : if (insn == BB_END (bb))
3290 : : {
3291 : : insn = NULL;
3292 : : break;
3293 : : }
3294 : 108067 : insn = NEXT_INSN (insn);
3295 : : }
3296 : :
3297 : 33616 : rtx_insn *set_insn;
3298 : 33616 : if (insn == BB_HEAD (bb))
3299 : : {
3300 : 0 : set_insn = emit_insn_before (set, insn);
3301 : 0 : if (dump_file)
3302 : : {
3303 : 0 : fprintf (dump_file, "\nPlace:\n\n");
3304 : 0 : print_rtl_single (dump_file, set_insn);
3305 : 0 : fprintf (dump_file, "\nbefore:\n\n");
3306 : 0 : print_rtl_single (dump_file, insn);
3307 : 0 : fprintf (dump_file, "\n");
3308 : : }
3309 : : }
3310 : : else
3311 : : {
3312 : 33616 : rtx_insn *after = insn ? PREV_INSN (insn) : BB_END (bb);
3313 : 33616 : set_insn = emit_insn_after (set, after);
3314 : 33616 : if (dump_file)
3315 : : {
3316 : 0 : fprintf (dump_file, "\nPlace:\n\n");
3317 : 0 : print_rtl_single (dump_file, set_insn);
3318 : 0 : fprintf (dump_file, "\nafter:\n\n");
3319 : 0 : print_rtl_single (dump_file, after);
3320 : 0 : fprintf (dump_file, "\n");
3321 : : }
3322 : : }
3323 : :
3324 : 33616 : if (load && load->kind == X86_CSE_VEC_DUP)
3325 : : {
3326 : : /* Get the source from LOAD as (reg:SI 99) in
3327 : :
3328 : : (vec_duplicate:V4SI (reg:SI 99))
3329 : :
3330 : : */
3331 : 10195 : rtx inner_scalar = load->val;
3332 : : /* Set the source in (vec_duplicate:V4SI (reg:SI 99)). */
3333 : 10195 : rtx reg = XEXP (src, 0);
3334 : 10195 : if ((REG_P (inner_scalar) || MEM_P (inner_scalar))
3335 : 262 : && GET_MODE (reg) != GET_MODE (inner_scalar))
3336 : 0 : inner_scalar = gen_rtx_SUBREG (GET_MODE (reg), inner_scalar, 0);
3337 : 10195 : rtx set = gen_rtx_SET (reg, inner_scalar);
3338 : 10195 : insn = emit_insn_before (set, set_insn);
3339 : 10195 : if (dump_file)
3340 : : {
3341 : 0 : fprintf (dump_file, "\nAdd:\n\n");
3342 : 0 : print_rtl_single (dump_file, insn);
3343 : 0 : fprintf (dump_file, "\nbefore:\n\n");
3344 : 0 : print_rtl_single (dump_file, set_insn);
3345 : 0 : fprintf (dump_file, "\n");
3346 : : }
3347 : : }
3348 : 33616 : }
3349 : :
3350 : : /* At entry of the nearest common dominator for basic blocks with
3351 : : conversions/rcp/sqrt/rsqrt/round, generate a single
3352 : : vxorps %xmmN, %xmmN, %xmmN
3353 : : for all
3354 : : vcvtss2sd op, %xmmN, %xmmX
3355 : : vcvtsd2ss op, %xmmN, %xmmX
3356 : : vcvtsi2ss op, %xmmN, %xmmX
3357 : : vcvtsi2sd op, %xmmN, %xmmX
3358 : :
3359 : : NB: We want to generate only a single vxorps to cover the whole
3360 : : function. The LCM algorithm isn't appropriate here since it may
3361 : : place a vxorps inside the loop. */
3362 : :
3363 : : static unsigned int
3364 : 33599 : remove_partial_avx_dependency (void)
3365 : : {
3366 : 33599 : timevar_push (TV_MACH_DEP);
3367 : :
3368 : 33599 : bitmap_obstack_initialize (NULL);
3369 : 33599 : bitmap convert_bbs = BITMAP_ALLOC (NULL);
3370 : :
3371 : 33599 : basic_block bb;
3372 : 33599 : rtx_insn *insn, *set_insn;
3373 : 33599 : rtx set;
3374 : 33599 : rtx v4sf_const0 = NULL_RTX;
3375 : :
3376 : 33599 : auto_vec<rtx_insn *> control_flow_insns;
3377 : :
3378 : : /* We create invalid RTL initially so defer rescans. */
3379 : 33599 : df_set_flags (DF_DEFER_INSN_RESCAN);
3380 : :
3381 : 313514 : FOR_EACH_BB_FN (bb, cfun)
3382 : : {
3383 : 3554254 : FOR_BB_INSNS (bb, insn)
3384 : : {
3385 : 3274339 : if (!NONDEBUG_INSN_P (insn))
3386 : 1465890 : continue;
3387 : :
3388 : 1808449 : set = single_set (insn);
3389 : 1808449 : if (!set)
3390 : 70726 : continue;
3391 : :
3392 : 1737723 : if (get_attr_avx_partial_xmm_update (insn)
3393 : : != AVX_PARTIAL_XMM_UPDATE_TRUE)
3394 : 1734356 : continue;
3395 : :
3396 : : /* Convert PARTIAL_XMM_UPDATE_TRUE insns, DF -> SF, SF -> DF,
3397 : : SI -> SF, SI -> DF, DI -> SF, DI -> DF, sqrt, rsqrt, rcp,
3398 : : round, to vec_dup and vec_merge with subreg. */
3399 : 3367 : rtx src = SET_SRC (set);
3400 : 3367 : rtx dest = SET_DEST (set);
3401 : 3367 : machine_mode dest_mode = GET_MODE (dest);
3402 : 3367 : bool convert_p = false;
3403 : 3367 : switch (GET_CODE (src))
3404 : : {
3405 : 3262 : case FLOAT:
3406 : 3262 : case FLOAT_EXTEND:
3407 : 3262 : case FLOAT_TRUNCATE:
3408 : 3262 : case UNSIGNED_FLOAT:
3409 : 3262 : convert_p = true;
3410 : 3262 : break;
3411 : : default:
3412 : : break;
3413 : : }
3414 : :
3415 : : /* Only handle conversion here. */
3416 : 3262 : machine_mode src_mode
3417 : 3262 : = convert_p ? GET_MODE (XEXP (src, 0)) : VOIDmode;
3418 : 3262 : switch (src_mode)
3419 : : {
3420 : 172 : case E_SFmode:
3421 : 172 : case E_DFmode:
3422 : 172 : if (TARGET_USE_VECTOR_FP_CONVERTS
3423 : 166 : || !TARGET_SSE_PARTIAL_REG_FP_CONVERTS_DEPENDENCY)
3424 : 8 : continue;
3425 : : break;
3426 : 3090 : case E_SImode:
3427 : 3090 : case E_DImode:
3428 : 3090 : if (TARGET_USE_VECTOR_CONVERTS
3429 : 3078 : || !TARGET_SSE_PARTIAL_REG_CONVERTS_DEPENDENCY)
3430 : 14 : continue;
3431 : : break;
3432 : 105 : case E_VOIDmode:
3433 : 105 : gcc_assert (!convert_p);
3434 : : break;
3435 : 0 : default:
3436 : 0 : gcc_unreachable ();
3437 : : }
3438 : :
3439 : 3345 : if (!v4sf_const0)
3440 : 1015 : v4sf_const0 = gen_reg_rtx (V4SFmode);
3441 : :
3442 : 3345 : rtx zero;
3443 : 3345 : machine_mode dest_vecmode;
3444 : 3345 : switch (dest_mode)
3445 : : {
3446 : 90 : case E_HFmode:
3447 : 90 : dest_vecmode = V8HFmode;
3448 : 90 : zero = gen_rtx_SUBREG (V8HFmode, v4sf_const0, 0);
3449 : 90 : break;
3450 : : case E_SFmode:
3451 : : dest_vecmode = V4SFmode;
3452 : : zero = v4sf_const0;
3453 : : break;
3454 : 1326 : case E_DFmode:
3455 : 1326 : dest_vecmode = V2DFmode;
3456 : 1326 : zero = gen_rtx_SUBREG (V2DFmode, v4sf_const0, 0);
3457 : 1326 : break;
3458 : 0 : default:
3459 : 0 : gcc_unreachable ();
3460 : : }
3461 : :
3462 : : /* Change source to vector mode. */
3463 : 3345 : src = gen_rtx_VEC_DUPLICATE (dest_vecmode, src);
3464 : 3345 : src = gen_rtx_VEC_MERGE (dest_vecmode, src, zero,
3465 : : GEN_INT (HOST_WIDE_INT_1U));
3466 : : /* Change destination to vector mode. */
3467 : 3345 : rtx vec = gen_reg_rtx (dest_vecmode);
3468 : : /* Generate an XMM vector SET. */
3469 : 3345 : set = gen_rtx_SET (vec, src);
3470 : 3345 : set_insn = emit_insn_before (set, insn);
3471 : :
3472 : 3345 : if (cfun->can_throw_non_call_exceptions)
3473 : : {
3474 : : /* Handle REG_EH_REGION note. */
3475 : 0 : rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
3476 : 0 : if (note)
3477 : : {
3478 : 0 : control_flow_insns.safe_push (set_insn);
3479 : 0 : add_reg_note (set_insn, REG_EH_REGION, XEXP (note, 0));
3480 : : }
3481 : : }
3482 : :
3483 : 3345 : src = gen_rtx_SUBREG (dest_mode, vec, 0);
3484 : 3345 : set = gen_rtx_SET (dest, src);
3485 : :
3486 : : /* Drop possible dead definitions. */
3487 : 3345 : PATTERN (insn) = set;
3488 : :
3489 : 3345 : INSN_CODE (insn) = -1;
3490 : 3345 : recog_memoized (insn);
3491 : 3345 : df_insn_rescan (insn);
3492 : 3345 : bitmap_set_bit (convert_bbs, bb->index);
3493 : : }
3494 : : }
3495 : :
3496 : 33599 : if (v4sf_const0)
3497 : : {
3498 : : /* (Re-)discover loops so that bb->loop_father can be used in the
3499 : : analysis below. */
3500 : 1015 : calculate_dominance_info (CDI_DOMINATORS);
3501 : 1015 : loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
3502 : :
3503 : 1015 : ix86_place_single_vector_set (v4sf_const0,
3504 : : CONST0_RTX (V4SFmode),
3505 : : convert_bbs);
3506 : :
3507 : 1015 : loop_optimizer_finalize ();
3508 : :
3509 : 1015 : if (!control_flow_insns.is_empty ())
3510 : : {
3511 : 0 : free_dominance_info (CDI_DOMINATORS);
3512 : :
3513 : 0 : unsigned int i;
3514 : 0 : FOR_EACH_VEC_ELT (control_flow_insns, i, insn)
3515 : 0 : if (control_flow_insn_p (insn))
3516 : : {
3517 : : /* Split the block after insn. There will be a fallthru
3518 : : edge, which is OK so we keep it. We have to create
3519 : : the exception edges ourselves. */
3520 : 0 : bb = BLOCK_FOR_INSN (insn);
3521 : 0 : split_block (bb, insn);
3522 : 0 : rtl_make_eh_edge (NULL, bb, BB_END (bb));
3523 : : }
3524 : : }
3525 : : }
3526 : :
3527 : 33599 : df_process_deferred_rescans ();
3528 : 33599 : df_clear_flags (DF_DEFER_INSN_RESCAN);
3529 : 33599 : bitmap_obstack_release (NULL);
3530 : 33599 : BITMAP_FREE (convert_bbs);
3531 : :
3532 : 33599 : timevar_pop (TV_MACH_DEP);
3533 : 33599 : return 0;
3534 : 33599 : }
3535 : :
3536 : : namespace {
3537 : :
3538 : : const pass_data pass_data_remove_partial_avx_dependency =
3539 : : {
3540 : : RTL_PASS, /* type */
3541 : : "rpad", /* name */
3542 : : OPTGROUP_NONE, /* optinfo_flags */
3543 : : TV_MACH_DEP, /* tv_id */
3544 : : 0, /* properties_required */
3545 : : 0, /* properties_provided */
3546 : : 0, /* properties_destroyed */
3547 : : 0, /* todo_flags_start */
3548 : : 0, /* todo_flags_finish */
3549 : : };
3550 : :
3551 : : class pass_remove_partial_avx_dependency : public rtl_opt_pass
3552 : : {
3553 : : public:
3554 : 290417 : pass_remove_partial_avx_dependency (gcc::context *ctxt)
3555 : 580834 : : rtl_opt_pass (pass_data_remove_partial_avx_dependency, ctxt)
3556 : : {}
3557 : :
3558 : : /* opt_pass methods: */
3559 : 1478637 : bool gate (function *) final override
3560 : : {
3561 : 1478637 : return ix86_rpad_gate ();
3562 : : }
3563 : :
3564 : 33599 : unsigned int execute (function *) final override
3565 : : {
3566 : 33599 : return remove_partial_avx_dependency ();
3567 : : }
3568 : : }; // class pass_rpad
3569 : :
3570 : : } // anon namespace
3571 : :
3572 : : rtl_opt_pass *
3573 : 290417 : make_pass_remove_partial_avx_dependency (gcc::context *ctxt)
3574 : : {
3575 : 290417 : return new pass_remove_partial_avx_dependency (ctxt);
3576 : : }
3577 : :
3578 : : /* Return a machine mode suitable for vector SIZE with SMODE inner
3579 : : mode. */
3580 : :
3581 : : static machine_mode
3582 : 33842 : ix86_get_vector_cse_mode (unsigned int size, machine_mode smode)
3583 : : {
3584 : : /* Use the inner scalar mode of vector broadcast source in:
3585 : :
3586 : : (set (reg:V8DF 394)
3587 : : (vec_duplicate:V8DF (reg:V2DF 190 [ alpha ])))
3588 : :
3589 : : to compute the vector mode for broadcast from vector source.
3590 : : */
3591 : 33842 : if (VECTOR_MODE_P (smode))
3592 : 1 : smode = GET_MODE_INNER (smode);
3593 : 33842 : scalar_mode s_mode = as_a <scalar_mode> (smode);
3594 : 67684 : poly_uint64 nunits = size / GET_MODE_SIZE (smode);
3595 : 33842 : machine_mode mode = mode_for_vector (s_mode, nunits).require ();
3596 : 33842 : return mode;
3597 : : }
3598 : :
3599 : : /* Replace the source operand of instructions in VECTOR_INSNS with
3600 : : VECTOR_CONST in VECTOR_MODE. */
3601 : :
3602 : : static void
3603 : 33419 : replace_vector_const (machine_mode vector_mode, rtx vector_const,
3604 : : auto_bitmap &vector_insns,
3605 : : machine_mode scalar_mode)
3606 : : {
3607 : 33419 : bitmap_iterator bi;
3608 : 33419 : unsigned int id;
3609 : :
3610 : 161959 : EXECUTE_IF_SET_IN_BITMAP (vector_insns, 0, id, bi)
3611 : : {
3612 : 128540 : rtx_insn *insn = DF_INSN_UID_GET (id)->insn;
3613 : :
3614 : : /* Get the single SET instruction. */
3615 : 128540 : rtx set = single_set (insn);
3616 : 128540 : rtx src = SET_SRC (set);
3617 : 128540 : rtx dest = SET_DEST (set);
3618 : 128540 : machine_mode mode = GET_MODE (dest);
3619 : :
3620 : 128540 : rtx replace;
3621 : : /* Replace the source operand with VECTOR_CONST. */
3622 : 128540 : if (SUBREG_P (src) || mode == vector_mode)
3623 : : replace = vector_const;
3624 : : else
3625 : : {
3626 : 60379 : unsigned int size = GET_MODE_SIZE (mode);
3627 : 60379 : if (size < ix86_regmode_natural_size (mode))
3628 : : {
3629 : : /* If the mode size is smaller than its natural size,
3630 : : first insert an extra move with a QI vector SUBREG
3631 : : of the same size to avoid validate_subreg failure. */
3632 : 423 : machine_mode vmode
3633 : 423 : = ix86_get_vector_cse_mode (size, scalar_mode);
3634 : 423 : rtx vreg;
3635 : 423 : if (mode == vmode)
3636 : : vreg = vector_const;
3637 : : else
3638 : : {
3639 : 40 : vreg = gen_reg_rtx (vmode);
3640 : 40 : rtx vsubreg = gen_rtx_SUBREG (vmode, vector_const, 0);
3641 : 40 : rtx pat = gen_rtx_SET (vreg, vsubreg);
3642 : 40 : rtx_insn *vinsn = emit_insn_before (pat, insn);
3643 : 40 : if (dump_file)
3644 : : {
3645 : 0 : fprintf (dump_file, "\nInsert an extra move:\n\n");
3646 : 0 : print_rtl_single (dump_file, vinsn);
3647 : 0 : fprintf (dump_file, "\nbefore:\n\n");
3648 : 0 : print_rtl_single (dump_file, insn);
3649 : 0 : fprintf (dump_file, "\n");
3650 : : }
3651 : : }
3652 : 423 : replace = gen_rtx_SUBREG (mode, vreg, 0);
3653 : : }
3654 : : else
3655 : 59956 : replace = gen_rtx_SUBREG (mode, vector_const, 0);
3656 : : }
3657 : :
3658 : 128540 : if (dump_file)
3659 : : {
3660 : 0 : fprintf (dump_file, "\nReplace:\n\n");
3661 : 0 : print_rtl_single (dump_file, insn);
3662 : : }
3663 : 128540 : SET_SRC (set) = replace;
3664 : : /* Drop possible dead definitions. */
3665 : 128540 : PATTERN (insn) = set;
3666 : 128540 : INSN_CODE (insn) = -1;
3667 : 128540 : recog_memoized (insn);
3668 : 128540 : if (dump_file)
3669 : : {
3670 : 0 : fprintf (dump_file, "\nwith:\n\n");
3671 : 0 : print_rtl_single (dump_file, insn);
3672 : 0 : fprintf (dump_file, "\n");
3673 : : }
3674 : 128540 : df_insn_rescan (insn);
3675 : : }
3676 : 33419 : }
3677 : :
3678 : : /* Return the inner scalar if OP is a broadcast, else return nullptr. */
3679 : :
3680 : : static rtx
3681 : 2195247 : ix86_broadcast_inner (rtx op, machine_mode mode,
3682 : : machine_mode *scalar_mode_p,
3683 : : x86_cse_kind *kind_p, rtx_insn **insn_p)
3684 : : {
3685 : 2195247 : switch (standard_sse_constant_p (op, mode))
3686 : : {
3687 : 121047 : case 1:
3688 : 121047 : *scalar_mode_p = QImode;
3689 : 121047 : *kind_p = X86_CSE_CONST0_VECTOR;
3690 : 121047 : *insn_p = nullptr;
3691 : 121047 : return const0_rtx;
3692 : 10676 : case 2:
3693 : 10676 : *scalar_mode_p = QImode;
3694 : 10676 : *kind_p = X86_CSE_CONSTM1_VECTOR;
3695 : 10676 : *insn_p = nullptr;
3696 : 10676 : return constm1_rtx;
3697 : 2063524 : default:
3698 : 2063524 : break;
3699 : : }
3700 : :
3701 : 2063524 : mode = GET_MODE (op);
3702 : 2063524 : int nunits = GET_MODE_NUNITS (mode);
3703 : 2063524 : if (nunits < 2)
3704 : : return nullptr;
3705 : :
3706 : 1570164 : *kind_p = X86_CSE_VEC_DUP;
3707 : :
3708 : 1570164 : rtx reg;
3709 : 1570164 : if (GET_CODE (op) == VEC_DUPLICATE)
3710 : : {
3711 : : /* Only
3712 : : (vec_duplicate:V4SI (reg:SI 99))
3713 : : (vec_duplicate:V2DF (mem/u/c:DF (symbol_ref/u:DI ("*.LC1") [flags 0x2]) [0 S8 A64]))
3714 : : are supported. Set OP to the broadcast source by default. */
3715 : 94701 : op = XEXP (op, 0);
3716 : 94701 : reg = op;
3717 : 94701 : if (SUBREG_P (op)
3718 : 394 : && SUBREG_BYTE (op) == 0
3719 : 95095 : && !paradoxical_subreg_p (op))
3720 : 394 : reg = SUBREG_REG (op);
3721 : 94701 : if (!REG_P (reg))
3722 : : {
3723 : 7751 : if (MEM_P (op)
3724 : 7485 : && SYMBOL_REF_P (XEXP (op, 0))
3725 : 13455 : && CONSTANT_POOL_ADDRESS_P (XEXP (op, 0)))
3726 : : {
3727 : : /* Handle constant broadcast from memory. */
3728 : 5483 : *scalar_mode_p = GET_MODE_INNER (mode);
3729 : 5483 : *insn_p = nullptr;
3730 : 5483 : return op;
3731 : : }
3732 : : return nullptr;
3733 : : }
3734 : : }
3735 : 1475463 : else if (CONST_VECTOR_P (op))
3736 : : {
3737 : 20 : rtx first = XVECEXP (op, 0, 0);
3738 : 48 : for (int i = 1; i < nunits; ++i)
3739 : : {
3740 : 48 : rtx tmp = XVECEXP (op, 0, i);
3741 : : /* Vector duplicate value. */
3742 : 48 : if (!rtx_equal_p (tmp, first))
3743 : : return nullptr;
3744 : : }
3745 : 0 : *scalar_mode_p = GET_MODE (first);
3746 : 0 : *insn_p = nullptr;
3747 : 0 : return first;
3748 : : }
3749 : : else
3750 : : return nullptr;
3751 : :
3752 : 86950 : mode = GET_MODE (op);
3753 : :
3754 : : /* Only single def chain is supported. */
3755 : 86950 : df_ref ref = DF_REG_DEF_CHAIN (REGNO (reg));
3756 : 86950 : if (!ref
3757 : 86949 : || DF_REF_IS_ARTIFICIAL (ref)
3758 : 86949 : || DF_REF_NEXT_REG (ref) != nullptr)
3759 : : return nullptr;
3760 : :
3761 : 81450 : rtx_insn *insn = DF_REF_INSN (ref);
3762 : 81450 : rtx set = single_set (insn);
3763 : 81450 : if (!set)
3764 : : return nullptr;
3765 : :
3766 : 81406 : rtx src = SET_SRC (set);
3767 : :
3768 : 81406 : if (CONST_INT_P (src))
3769 : : {
3770 : : /* Handle sequences like
3771 : :
3772 : : (set (reg:SI 99)
3773 : : (const_int 34 [0x22]))
3774 : : (set (reg:V4SI 98)
3775 : : (vec_duplicate:V4SI (reg:SI 99)))
3776 : :
3777 : : Set *INSN_P to nullptr and return SET_SRC if SET_SRC is an
3778 : : integer constant. */
3779 : 66655 : op = src;
3780 : 66655 : if (mode != GET_MODE (reg))
3781 : 0 : op = gen_int_mode (INTVAL (src), mode);
3782 : 66655 : *insn_p = nullptr;
3783 : : }
3784 : : else
3785 : : {
3786 : : /* Handle sequences like
3787 : :
3788 : : (set (reg:QI 105 [ c ])
3789 : : (reg:QI 5 di [ c ]))
3790 : : (set (reg:V64QI 102 [ _1 ])
3791 : : (vec_duplicate:V64QI (reg:QI 105 [ c ])))
3792 : :
3793 : : (set (reg/v:SI 116 [ argc ])
3794 : : (mem/c:SI (reg:SI 135) [2 argc+0 S4 A32]))
3795 : : (set (reg:V4SI 119 [ _45 ])
3796 : : (vec_duplicate:V4SI (reg/v:SI 116 [ argc ])))
3797 : :
3798 : : (set (reg:SI 98 [ _1 ])
3799 : : (sign_extend:SI (reg:QI 106 [ c ])))
3800 : : (set (reg:V16SI 103 [ _2 ])
3801 : : (vec_duplicate:V16SI (reg:SI 98 [ _1 ])))
3802 : :
3803 : : (set (reg:SI 102 [ cost ])
3804 : : (mem/c:SI (symbol_ref:DI ("cost") [flags 0x40])))
3805 : : (set (reg:V4HI 103 [ _16 ])
3806 : : (vec_duplicate:V4HI (subreg:HI (reg:SI 102 [ cost ]) 0)))
3807 : :
3808 : : (set (subreg:SI (reg/v:HI 107 [ cr_val ]) 0)
3809 : : (ashift:SI (reg:SI 158)
3810 : : (subreg:QI (reg:SI 156 [ _2 ]) 0)))
3811 : : (set (reg:V16HI 183 [ _61 ])
3812 : : (vec_duplicate:V16HI (reg/v:HI 107 [ cr_val ])))
3813 : :
3814 : : Set *INSN_P to INSN and return the broadcast source otherwise. */
3815 : 14751 : *insn_p = insn;
3816 : : }
3817 : :
3818 : 81406 : *scalar_mode_p = mode;
3819 : 81406 : return op;
3820 : : }
3821 : :
3822 : : /* Replace CALL instruction in TLS_CALL_INSNS with SET from SRC and
3823 : : put the updated instruction in UPDATED_TLS_INSNS. */
3824 : :
3825 : : static void
3826 : 304 : replace_tls_call (rtx src, auto_bitmap &tls_call_insns,
3827 : : auto_bitmap &updated_tls_insns)
3828 : : {
3829 : 304 : bitmap_iterator bi;
3830 : 304 : unsigned int id;
3831 : :
3832 : 1713 : EXECUTE_IF_SET_IN_BITMAP (tls_call_insns, 0, id, bi)
3833 : : {
3834 : 1409 : rtx_insn *insn = DF_INSN_UID_GET (id)->insn;
3835 : :
3836 : : /* If this isn't a CALL, only GNU2 TLS implicit CALL patterns are
3837 : : allowed. */
3838 : 1409 : if (!CALL_P (insn))
3839 : : {
3840 : 41 : attr_tls64 tls64 = get_attr_tls64 (insn);
3841 : 41 : if (tls64 != TLS64_CALL && tls64 != TLS64_COMBINE)
3842 : 0 : gcc_unreachable ();
3843 : : }
3844 : :
3845 : 1409 : rtx pat = PATTERN (insn);
3846 : 1409 : gcc_assert (GET_CODE (pat) == PARALLEL);
3847 : 1409 : rtx set = XVECEXP (pat, 0, 0);
3848 : 1409 : gcc_assert (GET_CODE (set) == SET);
3849 : 1409 : rtx dest = SET_DEST (set);
3850 : :
3851 : 1409 : set = gen_rtx_SET (dest, src);
3852 : 1409 : rtx_insn *set_insn = emit_insn_after (set, insn);
3853 : 1409 : if (recog_memoized (set_insn) < 0)
3854 : 0 : gcc_unreachable ();
3855 : :
3856 : : /* Put SET_INSN in UPDATED_TLS_INSNS. */
3857 : 1409 : bitmap_set_bit (updated_tls_insns, INSN_UID (set_insn));
3858 : :
3859 : 1409 : if (dump_file)
3860 : : {
3861 : 0 : fprintf (dump_file, "\nReplace:\n\n");
3862 : 0 : print_rtl_single (dump_file, insn);
3863 : 0 : fprintf (dump_file, "\nwith:\n\n");
3864 : 0 : print_rtl_single (dump_file, set_insn);
3865 : 0 : fprintf (dump_file, "\n");
3866 : : }
3867 : :
3868 : : /* Delete the CALL insn. */
3869 : 1409 : delete_insn (insn);
3870 : :
3871 : 1409 : df_insn_rescan (set_insn);
3872 : : }
3873 : 304 : }
3874 : :
3875 : : /* Return the basic block which dominates all basic blocks which set
3876 : : hard register REGNO used in basic block BB. */
3877 : :
3878 : : static basic_block
3879 : 2 : ix86_get_dominator_for_reg (unsigned int regno, basic_block bb)
3880 : : {
3881 : 2 : basic_block set_bb;
3882 : 2 : auto_bitmap set_bbs;
3883 : :
3884 : : /* Get all BBs which set REGNO and dominate the current BB from all
3885 : : DEFs of REGNO. */
3886 : 2 : for (df_ref def = DF_REG_DEF_CHAIN (regno);
3887 : 18 : def;
3888 : 16 : def = DF_REF_NEXT_REG (def))
3889 : 16 : if (!DF_REF_IS_ARTIFICIAL (def)
3890 : 16 : && !DF_REF_FLAGS_IS_SET (def, DF_REF_MAY_CLOBBER)
3891 : 6 : && !DF_REF_FLAGS_IS_SET (def, DF_REF_MUST_CLOBBER))
3892 : : {
3893 : 4 : set_bb = DF_REF_BB (def);
3894 : 4 : if (dominated_by_p (CDI_DOMINATORS, bb, set_bb))
3895 : 2 : bitmap_set_bit (set_bbs, set_bb->index);
3896 : : }
3897 : :
3898 : 2 : bb = nearest_common_dominator_for_set (CDI_DOMINATORS, set_bbs);
3899 : 2 : return bb;
3900 : 2 : }
3901 : :
3902 : : /* Mark FLAGS register as live in DATA, a bitmap of live caller-saved
3903 : : registers, if DEST is FLAGS register. */
3904 : :
3905 : : static void
3906 : 353 : ix86_check_flags_reg (rtx dest, const_rtx, void *data)
3907 : : {
3908 : 353 : auto_bitmap *live_caller_saved_regs = (auto_bitmap *) data;
3909 : 353 : if (REG_P (dest) && REGNO (dest) == FLAGS_REG)
3910 : 0 : bitmap_set_bit (*live_caller_saved_regs, FLAGS_REG);
3911 : 353 : }
3912 : :
3913 : : /* Emit a TLS_SET instruction of KIND in basic block BB. Store the
3914 : : insertion point in *BEFORE_P for emit_insn_before or in *AFTER_P
3915 : : for emit_insn_after. UPDATED_GNU_TLS_INSNS contains instructions
3916 : : which replace the GNU TLS instructions. UPDATED_GNU2_TLS_INSNS
3917 : : contains instructions which replace the GNU2 TLS instructions. */
3918 : :
3919 : : static rtx_insn *
3920 : 304 : ix86_emit_tls_call (rtx tls_set, x86_cse_kind kind, basic_block bb,
3921 : : rtx_insn **before_p, rtx_insn **after_p,
3922 : : auto_bitmap &updated_gnu_tls_insns,
3923 : : auto_bitmap &updated_gnu2_tls_insns)
3924 : : {
3925 : 306 : rtx_insn *tls_insn;
3926 : :
3927 : 306 : do
3928 : : {
3929 : 306 : rtx_insn *insn = BB_HEAD (bb);
3930 : 1277 : while (insn && !NONDEBUG_INSN_P (insn))
3931 : : {
3932 : 976 : if (insn == BB_END (bb))
3933 : : {
3934 : : /* This must be the beginning basic block:
3935 : :
3936 : : (note 4 0 2 2 [bb 2] NOTE_INSN_BASIC_BLOCK)
3937 : : (note 2 4 26 2 NOTE_INSN_FUNCTION_BEG)
3938 : :
3939 : : or a basic block with only a label:
3940 : :
3941 : : (code_label 78 11 77 3 14 (nil) [1 uses])
3942 : : (note 77 78 54 3 [bb 3] NOTE_INSN_BASIC_BLOCK)
3943 : :
3944 : : or a basic block with only a debug marker:
3945 : :
3946 : : (note 3 0 2 2 [bb 2] NOTE_INSN_BASIC_BLOCK)
3947 : : (note 2 3 5 2 NOTE_INSN_FUNCTION_BEG)
3948 : : (debug_insn 5 2 16 2 (debug_marker) "x.c":6:3 -1 (nil))
3949 : :
3950 : : or a basic block with only deleted instructions:
3951 : :
3952 : : (code_label 348 23 349 45 3 (nil) [0 uses])
3953 : : (note 349 348 436 45 [bb 45] NOTE_INSN_BASIC_BLOCK)
3954 : : (note 436 349 362 45 NOTE_INSN_DELETED)
3955 : :
3956 : : */
3957 : 5 : gcc_assert (DEBUG_INSN_P (insn)
3958 : : || (NOTE_P (insn)
3959 : : && ((NOTE_KIND (insn)
3960 : : == NOTE_INSN_FUNCTION_BEG)
3961 : : || (NOTE_KIND (insn)
3962 : : == NOTE_INSN_DELETED)
3963 : : || (NOTE_KIND (insn)
3964 : : == NOTE_INSN_BASIC_BLOCK))));
3965 : : insn = NULL;
3966 : : break;
3967 : : }
3968 : 971 : insn = NEXT_INSN (insn);
3969 : : }
3970 : :
3971 : : /* TLS_GD and TLS_LD_BASE instructions are normal functions which
3972 : : clobber caller-saved registers. TLSDESC instructions only
3973 : : clobber FLAGS. If any registers clobbered by TLS instructions
3974 : : are live in this basic block, we must insert TLS instructions
3975 : : after all live registers clobbered are dead. */
3976 : :
3977 : 306 : auto_bitmap live_caller_saved_regs;
3978 : 612 : bitmap in = df_live ? DF_LIVE_IN (bb) : DF_LR_IN (bb);
3979 : :
3980 : 306 : if (bitmap_bit_p (in, FLAGS_REG))
3981 : 4 : bitmap_set_bit (live_caller_saved_regs, FLAGS_REG);
3982 : :
3983 : 306 : unsigned int i;
3984 : :
3985 : : /* Get all live caller-saved registers for TLS_GD and TLS_LD_BASE
3986 : : instructions. */
3987 : 306 : if (kind != X86_CSE_TLSDESC)
3988 : 26691 : for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3989 : 26404 : if (call_used_regs[i]
3990 : 24682 : && !fixed_regs[i]
3991 : 38195 : && bitmap_bit_p (in, i))
3992 : 337 : bitmap_set_bit (live_caller_saved_regs, i);
3993 : :
3994 : 306 : if (bitmap_empty_p (live_caller_saved_regs))
3995 : : {
3996 : 80 : if (insn == BB_HEAD (bb))
3997 : : {
3998 : 0 : *before_p = insn;
3999 : 0 : tls_insn = emit_insn_before (tls_set, insn);
4000 : : }
4001 : : else
4002 : : {
4003 : : /* Emit the TLS call after NOTE_INSN_FUNCTION_BEG in the
4004 : : beginning basic block:
4005 : :
4006 : : (note 4 0 2 2 [bb 2] NOTE_INSN_BASIC_BLOCK)
4007 : : (note 2 4 26 2 NOTE_INSN_FUNCTION_BEG)
4008 : :
4009 : : or after NOTE_INSN_BASIC_BLOCK in a basic block with
4010 : : only a label:
4011 : :
4012 : : (code_label 78 11 77 3 14 (nil) [1 uses])
4013 : : (note 77 78 54 3 [bb 3] NOTE_INSN_BASIC_BLOCK)
4014 : :
4015 : : or after debug marker in a basic block with only a
4016 : : debug marker:
4017 : :
4018 : : (note 3 0 2 2 [bb 2] NOTE_INSN_BASIC_BLOCK)
4019 : : (note 2 3 5 2 NOTE_INSN_FUNCTION_BEG)
4020 : : (debug_insn 5 2 16 2 (debug_marker) "x.c":6:3 -1 (nil))
4021 : :
4022 : : */
4023 : 80 : insn = insn ? PREV_INSN (insn) : BB_END (bb);
4024 : 80 : *after_p = insn;
4025 : 80 : tls_insn = emit_insn_after (tls_set, insn);
4026 : : }
4027 : 80 : return tls_insn;
4028 : : }
4029 : :
4030 : 226 : bool repeat = false;
4031 : :
4032 : : /* Search for REG_DEAD notes in this basic block. */
4033 : 619 : FOR_BB_INSNS (bb, insn)
4034 : : {
4035 : 619 : if (!NONDEBUG_INSN_P (insn))
4036 : 262 : continue;
4037 : :
4038 : : /* NB: Conditional jump is the only instruction which reads
4039 : : flags register and changes control flow. We can never
4040 : : place the TLS call after unconditional jump. */
4041 : 357 : if (JUMP_P (insn))
4042 : : {
4043 : : /* This must be a conditional jump. */
4044 : 2 : rtx label = JUMP_LABEL (insn);
4045 : 2 : if (label == nullptr
4046 : 2 : || ANY_RETURN_P (label)
4047 : 2 : || !(LABEL_P (label) || SYMBOL_REF_P (label)))
4048 : 0 : gcc_unreachable ();
4049 : :
4050 : : /* Place the call before all FLAGS_REG setting BBs since
4051 : : we can't place a call before nor after a conditional
4052 : : jump. */
4053 : 2 : bb = ix86_get_dominator_for_reg (FLAGS_REG, bb);
4054 : :
4055 : : /* Start over again. */
4056 : 2 : repeat = true;
4057 : 2 : break;
4058 : : }
4059 : :
4060 : 355 : if (bitmap_bit_p (updated_gnu_tls_insns, INSN_UID (insn)))
4061 : : {
4062 : : /* Insert the __tls_get_addr call before INSN which
4063 : : replaces a __tls_get_addr call. */
4064 : 1 : *before_p = insn;
4065 : 1 : tls_insn = emit_insn_before (tls_set, insn);
4066 : 1 : return tls_insn;
4067 : : }
4068 : :
4069 : 354 : if (bitmap_bit_p (updated_gnu2_tls_insns, INSN_UID (insn)))
4070 : : {
4071 : : /* Mark FLAGS register as dead since FLAGS register
4072 : : would be clobbered by the GNU2 TLS instruction. */
4073 : 1 : bitmap_clear_bit (live_caller_saved_regs, FLAGS_REG);
4074 : 1 : continue;
4075 : : }
4076 : :
4077 : : /* Check if FLAGS register is live. */
4078 : 353 : note_stores (insn, ix86_check_flags_reg,
4079 : : &live_caller_saved_regs);
4080 : :
4081 : 353 : rtx link;
4082 : 480 : for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
4083 : 350 : if (REG_NOTE_KIND (link) == REG_DEAD
4084 : 348 : && REG_P (XEXP (link, 0)))
4085 : : {
4086 : : /* Mark the live caller-saved register as dead. */
4087 : 701 : for (i = REGNO (XEXP (link, 0));
4088 : 701 : i < END_REGNO (XEXP (link, 0));
4089 : : i++)
4090 : 353 : if (i < FIRST_PSEUDO_REGISTER)
4091 : 337 : bitmap_clear_bit (live_caller_saved_regs, i);
4092 : :
4093 : 348 : if (bitmap_empty_p (live_caller_saved_regs))
4094 : : {
4095 : 223 : *after_p = insn;
4096 : 223 : tls_insn = emit_insn_after (tls_set, insn);
4097 : 223 : return tls_insn;
4098 : : }
4099 : : }
4100 : : }
4101 : :
4102 : : /* NB: Start over again for conditional jump. */
4103 : 2 : if (repeat)
4104 : 2 : continue;
4105 : :
4106 : 0 : gcc_assert (!bitmap_empty_p (live_caller_saved_regs));
4107 : :
4108 : : /* If any live caller-saved registers aren't dead at the end of
4109 : : this basic block, get the basic block which dominates all
4110 : : basic blocks which set the remaining live registers. */
4111 : 0 : auto_bitmap set_bbs;
4112 : 0 : bitmap_iterator bi;
4113 : 0 : unsigned int id;
4114 : 0 : EXECUTE_IF_SET_IN_BITMAP (live_caller_saved_regs, 0, id, bi)
4115 : : {
4116 : 0 : basic_block set_bb = ix86_get_dominator_for_reg (id, bb);
4117 : 0 : bitmap_set_bit (set_bbs, set_bb->index);
4118 : : }
4119 : 0 : bb = nearest_common_dominator_for_set (CDI_DOMINATORS, set_bbs);
4120 : 2 : }
4121 : : while (true);
4122 : : }
4123 : :
4124 : : /* Generate a TLS call of KIND with VAL and copy the call result to DEST,
4125 : : at entry of the nearest dominator for basic block map BBS, which is in
4126 : : the fake loop that contains the whole function, so that there is only
4127 : : a single TLS CALL of KIND with VAL in the whole function.
4128 : : UPDATED_GNU_TLS_INSNS contains instructions which replace the GNU TLS
4129 : : instructions. UPDATED_GNU2_TLS_INSNS contains instructions which
4130 : : replace the GNU2 TLS instructions. If TLSDESC_SET isn't nullptr,
4131 : : insert it before the TLS call. */
4132 : :
4133 : : static void
4134 : 304 : ix86_place_single_tls_call (rtx dest, rtx val, x86_cse_kind kind,
4135 : : auto_bitmap &bbs,
4136 : : auto_bitmap &updated_gnu_tls_insns,
4137 : : auto_bitmap &updated_gnu2_tls_insns,
4138 : : rtx tlsdesc_set = nullptr)
4139 : : {
4140 : 304 : basic_block bb = nearest_common_dominator_for_set (CDI_DOMINATORS, bbs);
4141 : 304 : while (bb->loop_father->latch
4142 : 311 : != EXIT_BLOCK_PTR_FOR_FN (cfun))
4143 : 7 : bb = get_immediate_dominator (CDI_DOMINATORS,
4144 : : bb->loop_father->header);
4145 : :
4146 : 304 : rtx rax = nullptr, rdi;
4147 : 304 : rtx eqv = nullptr;
4148 : 304 : rtx caddr;
4149 : 304 : rtx set;
4150 : 304 : rtx clob;
4151 : 304 : rtx symbol;
4152 : 304 : rtx tls;
4153 : :
4154 : 304 : switch (kind)
4155 : : {
4156 : 259 : case X86_CSE_TLS_GD:
4157 : 259 : rax = gen_rtx_REG (Pmode, AX_REG);
4158 : 259 : rdi = gen_rtx_REG (Pmode, DI_REG);
4159 : 259 : caddr = ix86_tls_get_addr ();
4160 : :
4161 : 259 : symbol = XVECEXP (val, 0, 0);
4162 : 259 : tls = gen_tls_global_dynamic_64 (Pmode, rax, symbol, caddr, rdi);
4163 : :
4164 : 259 : if (GET_MODE (symbol) != Pmode)
4165 : 0 : symbol = gen_rtx_ZERO_EXTEND (Pmode, symbol);
4166 : : eqv = symbol;
4167 : : break;
4168 : :
4169 : 27 : case X86_CSE_TLS_LD_BASE:
4170 : 27 : rax = gen_rtx_REG (Pmode, AX_REG);
4171 : 27 : rdi = gen_rtx_REG (Pmode, DI_REG);
4172 : 27 : caddr = ix86_tls_get_addr ();
4173 : :
4174 : 27 : tls = gen_tls_local_dynamic_base_64 (Pmode, rax, caddr, rdi);
4175 : :
4176 : : /* Attach a unique REG_EQUAL to DEST, to allow the RTL optimizers
4177 : : to share the LD_BASE result with other LD model accesses. */
4178 : 27 : eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
4179 : : UNSPEC_TLS_LD_BASE);
4180 : :
4181 : 27 : break;
4182 : :
4183 : 18 : case X86_CSE_TLSDESC:
4184 : 18 : set = gen_rtx_SET (dest, val);
4185 : 18 : clob = gen_rtx_CLOBBER (VOIDmode,
4186 : : gen_rtx_REG (CCmode, FLAGS_REG));
4187 : 18 : tls = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, set, clob));
4188 : 18 : break;
4189 : :
4190 : 0 : default:
4191 : 0 : gcc_unreachable ();
4192 : : }
4193 : :
4194 : : /* Emit the TLS CALL insn. */
4195 : 304 : rtx_insn *before = nullptr;
4196 : 304 : rtx_insn *after = nullptr;
4197 : 304 : rtx_insn *tls_insn = ix86_emit_tls_call (tls, kind, bb, &before,
4198 : : &after,
4199 : : updated_gnu_tls_insns,
4200 : : updated_gnu2_tls_insns);
4201 : :
4202 : 304 : rtx_insn *tlsdesc_insn = nullptr;
4203 : 304 : if (tlsdesc_set)
4204 : : {
4205 : 14 : rtx dest = copy_rtx (SET_DEST (tlsdesc_set));
4206 : 14 : rtx src = copy_rtx (SET_SRC (tlsdesc_set));
4207 : 14 : tlsdesc_set = gen_rtx_SET (dest, src);
4208 : 14 : tlsdesc_insn = emit_insn_before (tlsdesc_set, tls_insn);
4209 : : }
4210 : :
4211 : 304 : if (kind != X86_CSE_TLSDESC)
4212 : : {
4213 : 286 : RTL_CONST_CALL_P (tls_insn) = 1;
4214 : :
4215 : : /* Indicate that this function can't jump to non-local gotos. */
4216 : 286 : make_reg_eh_region_note_nothrow_nononlocal (tls_insn);
4217 : : }
4218 : :
4219 : 304 : if (recog_memoized (tls_insn) < 0)
4220 : 0 : gcc_unreachable ();
4221 : :
4222 : 304 : if (dump_file)
4223 : : {
4224 : 0 : if (after)
4225 : : {
4226 : 0 : fprintf (dump_file, "\nPlace:\n\n");
4227 : 0 : if (tlsdesc_insn)
4228 : 0 : print_rtl_single (dump_file, tlsdesc_insn);
4229 : 0 : print_rtl_single (dump_file, tls_insn);
4230 : 0 : fprintf (dump_file, "\nafter:\n\n");
4231 : 0 : print_rtl_single (dump_file, after);
4232 : 0 : fprintf (dump_file, "\n");
4233 : : }
4234 : : else
4235 : : {
4236 : 0 : fprintf (dump_file, "\nPlace:\n\n");
4237 : 0 : if (tlsdesc_insn)
4238 : 0 : print_rtl_single (dump_file, tlsdesc_insn);
4239 : 0 : print_rtl_single (dump_file, tls_insn);
4240 : 0 : fprintf (dump_file, "\nbefore:\n\n");
4241 : 0 : print_rtl_single (dump_file, before);
4242 : 0 : fprintf (dump_file, "\n");
4243 : : }
4244 : : }
4245 : :
4246 : 304 : if (kind != X86_CSE_TLSDESC)
4247 : : {
4248 : : /* Copy RAX to DEST. */
4249 : 286 : set = gen_rtx_SET (dest, rax);
4250 : 286 : rtx_insn *set_insn = emit_insn_after (set, tls_insn);
4251 : 286 : set_dst_reg_note (set_insn, REG_EQUAL, copy_rtx (eqv), dest);
4252 : 286 : if (dump_file)
4253 : : {
4254 : 0 : fprintf (dump_file, "\nPlace:\n\n");
4255 : 0 : print_rtl_single (dump_file, set_insn);
4256 : 0 : fprintf (dump_file, "\nafter:\n\n");
4257 : 0 : print_rtl_single (dump_file, tls_insn);
4258 : 0 : fprintf (dump_file, "\n");
4259 : : }
4260 : : }
4261 : 304 : }
4262 : :
4263 : : namespace {
4264 : :
4265 : : const pass_data pass_data_x86_cse =
4266 : : {
4267 : : RTL_PASS, /* type */
4268 : : "x86_cse", /* name */
4269 : : OPTGROUP_NONE, /* optinfo_flags */
4270 : : TV_MACH_DEP, /* tv_id */
4271 : : 0, /* properties_required */
4272 : : 0, /* properties_provided */
4273 : : 0, /* properties_destroyed */
4274 : : 0, /* todo_flags_start */
4275 : : 0, /* todo_flags_finish */
4276 : : };
4277 : :
4278 : : class pass_x86_cse : public rtl_opt_pass
4279 : : {
4280 : : public:
4281 : 290417 : pass_x86_cse (gcc::context *ctxt)
4282 : 580834 : : rtl_opt_pass (pass_data_x86_cse, ctxt)
4283 : : {}
4284 : :
4285 : : /* opt_pass methods: */
4286 : 1478637 : bool gate (function *fun) final override
4287 : : {
4288 : 1478637 : return (TARGET_SSE2
4289 : 1474416 : && optimize
4290 : 2525359 : && optimize_function_for_speed_p (fun));
4291 : : }
4292 : :
4293 : 982649 : unsigned int execute (function *) final override
4294 : : {
4295 : 982649 : return x86_cse ();
4296 : : }
4297 : :
4298 : : private:
4299 : : /* The redundant source value. */
4300 : : rtx val;
4301 : : /* The actual redundant source value for UNSPEC_TLSDESC. */
4302 : : rtx tlsdesc_val;
4303 : : /* The instruction which defines the redundant value. */
4304 : : rtx_insn *def_insn;
4305 : : /* Mode of the destination of the candidate redundant instruction. */
4306 : : machine_mode mode;
4307 : : /* Mode of the source of the candidate redundant instruction. */
4308 : : machine_mode scalar_mode;
4309 : : /* The classification of the candidate redundant instruction. */
4310 : : x86_cse_kind kind;
4311 : :
4312 : : unsigned int x86_cse (void);
4313 : : bool candidate_gnu_tls_p (rtx_insn *, attr_tls64);
4314 : : bool candidate_gnu2_tls_p (rtx, attr_tls64);
4315 : : bool candidate_vector_p (rtx);
4316 : : rtx_insn *tls_set_insn_from_symbol (const_rtx, const_rtx);
4317 : : }; // class pass_x86_cse
4318 : :
4319 : : /* Return the instruction which sets REG from TLS_SYMBOL. */
4320 : :
4321 : : rtx_insn *
4322 : 38 : pass_x86_cse::tls_set_insn_from_symbol (const_rtx reg,
4323 : : const_rtx tls_symbol)
4324 : : {
4325 : 38 : rtx_insn *set_insn = nullptr;
4326 : 38 : for (df_ref ref = DF_REG_DEF_CHAIN (REGNO (reg));
4327 : 103 : ref;
4328 : 65 : ref = DF_REF_NEXT_REG (ref))
4329 : : {
4330 : 65 : if (DF_REF_IS_ARTIFICIAL (ref))
4331 : : return nullptr;
4332 : :
4333 : 65 : set_insn = DF_REF_INSN (ref);
4334 : 65 : if (get_attr_tls64 (set_insn) != TLS64_LEA)
4335 : : return nullptr;
4336 : :
4337 : 65 : rtx tls_set = PATTERN (set_insn);
4338 : 65 : rtx tls_src = XVECEXP (SET_SRC (tls_set), 0, 0);
4339 : 65 : if (!rtx_equal_p (tls_symbol, tls_src))
4340 : : return nullptr;
4341 : : }
4342 : :
4343 : : return set_insn;
4344 : : }
4345 : :
4346 : : /* Return true and output def_insn, val, mode, scalar_mode and kind if
4347 : : INSN is UNSPEC_TLS_GD or UNSPEC_TLS_LD_BASE. */
4348 : :
4349 : : bool
4350 : 2173 : pass_x86_cse::candidate_gnu_tls_p (rtx_insn *insn, attr_tls64 tls64)
4351 : : {
4352 : 2173 : if (!TARGET_64BIT || !cfun->machine->tls_descriptor_call_multiple_p)
4353 : : return false;
4354 : :
4355 : : /* Record the redundant TLS CALLs for 64-bit:
4356 : :
4357 : : (parallel [
4358 : : (set (reg:DI 0 ax)
4359 : : (call:DI (mem:QI (symbol_ref:DI ("__tls_get_addr")))
4360 : : (const_int 0 [0])))
4361 : : (unspec:DI [(symbol_ref:DI ("foo") [flags 0x50])
4362 : : (reg/f:DI 7 sp)] UNSPEC_TLS_GD)
4363 : : (clobber (reg:DI 5 di))])
4364 : :
4365 : :
4366 : : and
4367 : :
4368 : : (parallel [
4369 : : (set (reg:DI 0 ax)
4370 : : (call:DI (mem:QI (symbol_ref:DI ("__tls_get_addr")))
4371 : : (const_int 0 [0])))
4372 : : (unspec:DI [(reg/f:DI 7 sp)] UNSPEC_TLS_LD_BASE)])
4373 : :
4374 : : */
4375 : :
4376 : 2010 : rtx pat = PATTERN (insn);
4377 : 2010 : rtx set = XVECEXP (pat, 0, 0);
4378 : 2010 : gcc_assert (GET_CODE (set) == SET);
4379 : 2010 : rtx dest = SET_DEST (set);
4380 : 2010 : scalar_mode = mode = GET_MODE (dest);
4381 : 2010 : val = XVECEXP (pat, 0, 1);
4382 : 2010 : gcc_assert (GET_CODE (val) == UNSPEC);
4383 : :
4384 : 2010 : if (tls64 == TLS64_GD)
4385 : 1915 : kind = X86_CSE_TLS_GD;
4386 : : else
4387 : 95 : kind = X86_CSE_TLS_LD_BASE;
4388 : :
4389 : 2010 : def_insn = nullptr;
4390 : 2010 : return true;
4391 : : }
4392 : :
4393 : : /* Return true and output def_insn, val, mode, scalar_mode and kind if
4394 : : SET is UNSPEC_TLSDESC. */
4395 : :
4396 : : bool
4397 : 50 : pass_x86_cse::candidate_gnu2_tls_p (rtx set, attr_tls64 tls64)
4398 : : {
4399 : 50 : if (!TARGET_64BIT || !cfun->machine->tls_descriptor_call_multiple_p)
4400 : : return false;
4401 : :
4402 : 48 : rtx tls_symbol;
4403 : 48 : rtx_insn *set_insn;
4404 : 48 : rtx src = SET_SRC (set);
4405 : 48 : val = src;
4406 : 48 : tlsdesc_val = src;
4407 : 48 : kind = X86_CSE_TLSDESC;
4408 : :
4409 : 48 : if (tls64 == TLS64_COMBINE)
4410 : : {
4411 : : /* Record 64-bit TLS64_COMBINE:
4412 : :
4413 : : (set (reg/f:DI 104)
4414 : : (plus:DI (unspec:DI [
4415 : : (symbol_ref:DI ("_TLS_MODULE_BASE_") [flags 0x10])
4416 : : (reg:DI 114)
4417 : : (reg/f:DI 7 sp)] UNSPEC_TLSDESC)
4418 : : (const:DI (unspec:DI [
4419 : : (symbol_ref:DI ("e") [flags 0x1a])
4420 : : ] UNSPEC_DTPOFF))))
4421 : :
4422 : : (set (reg/f:DI 104)
4423 : : (plus:DI (unspec:DI [
4424 : : (symbol_ref:DI ("_TLS_MODULE_BASE_") [flags 0x10])
4425 : : (unspec:DI [
4426 : : (symbol_ref:DI ("_TLS_MODULE_BASE_") [flags 0x10])
4427 : : ] UNSPEC_TLSDESC)
4428 : : (reg/f:DI 7 sp)] UNSPEC_TLSDESC)
4429 : : (const:DI (unspec:DI [
4430 : : (symbol_ref:DI ("e") [flags 0x1a])
4431 : : ] UNSPEC_DTPOFF))))
4432 : : */
4433 : :
4434 : 10 : scalar_mode = mode = GET_MODE (src);
4435 : :
4436 : : /* Since the first operand of PLUS in the source TLS_COMBINE
4437 : : pattern is unused, use the second operand of PLUS:
4438 : :
4439 : : (const:DI (unspec:DI [
4440 : : (symbol_ref:DI ("e") [flags 0x1a])
4441 : : ] UNSPEC_DTPOFF))
4442 : :
4443 : : as VAL to check if 2 TLS_COMBINE patterns have the same
4444 : : source. */
4445 : 10 : val = XEXP (src, 1);
4446 : 10 : gcc_assert (GET_CODE (val) == CONST
4447 : : && GET_CODE (XEXP (val, 0)) == UNSPEC
4448 : : && XINT (XEXP (val, 0), 1) == UNSPEC_DTPOFF
4449 : : && SYMBOL_REF_P (XVECEXP (XEXP (val, 0), 0, 0)));
4450 : 10 : def_insn = nullptr;
4451 : 10 : return true;
4452 : : }
4453 : :
4454 : : /* Record 64-bit TLS_CALL:
4455 : :
4456 : : (set (reg:DI 101)
4457 : : (unspec:DI [(symbol_ref:DI ("foo") [flags 0x50])
4458 : : (reg:DI 112)
4459 : : (reg/f:DI 7 sp)] UNSPEC_TLSDESC))
4460 : :
4461 : : */
4462 : :
4463 : 38 : gcc_assert (GET_CODE (src) == UNSPEC);
4464 : 38 : tls_symbol = XVECEXP (src, 0, 0);
4465 : 38 : src = XVECEXP (src, 0, 1);
4466 : 38 : scalar_mode = mode = GET_MODE (src);
4467 : 38 : gcc_assert (REG_P (src));
4468 : :
4469 : : /* All definitions of reg:DI 129 in
4470 : :
4471 : : (set (reg:DI 110)
4472 : : (unspec:DI [(symbol_ref:DI ("foo"))
4473 : : (reg:DI 129)
4474 : : (reg/f:DI 7 sp)] UNSPEC_TLSDESC))
4475 : :
4476 : : should have the same source as in
4477 : :
4478 : : (set (reg:DI 129)
4479 : : (unspec:DI [(symbol_ref:DI ("foo"))] UNSPEC_TLSDESC))
4480 : :
4481 : : */
4482 : :
4483 : 38 : set_insn = tls_set_insn_from_symbol (src, tls_symbol);
4484 : 38 : if (!set_insn)
4485 : : return false;
4486 : :
4487 : : /* Use TLS_SYMBOL as VAL to check if 2 patterns have the same source. */
4488 : 38 : val = tls_symbol;
4489 : 38 : def_insn = set_insn;
4490 : 38 : return true;
4491 : : }
4492 : :
4493 : : /* Return true and output def_insn, val, mode, scalar_mode and kind if
4494 : : INSN is a vector broadcast instruction. */
4495 : :
4496 : : bool
4497 : 51086844 : pass_x86_cse::candidate_vector_p (rtx set)
4498 : : {
4499 : 51086844 : rtx src = SET_SRC (set);
4500 : 51086844 : rtx dest = SET_DEST (set);
4501 : 51086844 : mode = GET_MODE (dest);
4502 : : /* Skip non-vector instruction. */
4503 : 51086844 : if (!VECTOR_MODE_P (mode))
4504 : : return false;
4505 : :
4506 : : /* Skip non-vector load instruction. */
4507 : 3727842 : if (!REG_P (dest) && !SUBREG_P (dest))
4508 : : return false;
4509 : :
4510 : 2195247 : val = ix86_broadcast_inner (src, mode, &scalar_mode, &kind,
4511 : : &def_insn);
4512 : 2195247 : return val ? true : false;
4513 : : }
4514 : :
4515 : : /* At entry of the nearest common dominator for basic blocks with
4516 : :
4517 : : 1. Vector CONST0_RTX patterns.
4518 : : 2. Vector CONSTM1_RTX patterns.
4519 : : 3. Vector broadcast patterns.
4520 : : 4. UNSPEC_TLS_GD patterns.
4521 : : 5. UNSPEC_TLS_LD_BASE patterns.
4522 : : 6. UNSPEC_TLSDESC patterns.
4523 : :
4524 : : generate a single pattern whose destination is used to replace the
4525 : : source in all identical patterns.
4526 : :
4527 : : NB: We want to generate a pattern, which is executed only once, to
4528 : : cover the whole function. The LCM algorithm isn't appropriate here
4529 : : since it may place a pattern inside the loop. */
4530 : :
4531 : : unsigned int
4532 : 982649 : pass_x86_cse::x86_cse (void)
4533 : : {
4534 : 982649 : timevar_push (TV_MACH_DEP);
4535 : :
4536 : 982649 : auto_vec<redundant_pattern *> loads;
4537 : 982649 : redundant_pattern *load;
4538 : 982649 : basic_block bb;
4539 : 982649 : rtx_insn *insn;
4540 : 982649 : unsigned int i;
4541 : 982649 : auto_bitmap updated_gnu_tls_insns;
4542 : 982649 : auto_bitmap updated_gnu2_tls_insns;
4543 : :
4544 : 982649 : df_set_flags (DF_DEFER_INSN_RESCAN);
4545 : :
4546 : 982649 : bool recursive_call_p = cfun->machine->recursive_function;
4547 : :
4548 : 11192767 : FOR_EACH_BB_FN (bb, cfun)
4549 : : {
4550 : 134713192 : FOR_BB_INSNS (bb, insn)
4551 : : {
4552 : 124503074 : if (!NONDEBUG_INSN_P (insn))
4553 : 69714778 : continue;
4554 : :
4555 : 54788296 : bool matched = false;
4556 : : /* Remove redundant pattens if there are more than 2 of
4557 : : them. */
4558 : 54788296 : unsigned int threshold = 2;
4559 : :
4560 : 54788296 : rtx set = single_set (insn);
4561 : 54788296 : if (!set && !CALL_P (insn))
4562 : 1113006 : continue;
4563 : :
4564 : 53675290 : tlsdesc_val = nullptr;
4565 : :
4566 : 53675290 : attr_tls64 tls64 = get_attr_tls64 (insn);
4567 : 53675290 : switch (tls64)
4568 : : {
4569 : 2173 : case TLS64_GD:
4570 : 2173 : case TLS64_LD_BASE:
4571 : : /* Verify UNSPEC_TLS_GD and UNSPEC_TLS_LD_BASE. */
4572 : 2173 : if (candidate_gnu_tls_p (insn, tls64))
4573 : : break;
4574 : 163 : continue;
4575 : :
4576 : 50 : case TLS64_CALL:
4577 : 50 : case TLS64_COMBINE:
4578 : : /* Verify UNSPEC_TLSDESC. */
4579 : 50 : if (candidate_gnu2_tls_p (set, tls64))
4580 : : break;
4581 : 2 : continue;
4582 : :
4583 : 35 : case TLS64_LEA:
4584 : : /* Skip TLS64_LEA. */
4585 : 35 : continue;
4586 : :
4587 : 53673032 : case TLS64_NONE:
4588 : 53673032 : if (!set)
4589 : 2586188 : continue;
4590 : :
4591 : : /* Check for vector broadcast. */
4592 : 51086844 : if (candidate_vector_p (set))
4593 : : break;
4594 : 50868232 : continue;
4595 : : }
4596 : :
4597 : : /* Check if there is a matching redundant load. */
4598 : 387351 : FOR_EACH_VEC_ELT (loads, i, load)
4599 : 262907 : if (load->val
4600 : 262907 : && load->kind == kind
4601 : 205871 : && load->mode == scalar_mode
4602 : 196707 : && (load->bb == bb
4603 : 160778 : || kind != X86_CSE_VEC_DUP
4604 : : /* Non all 0s/1s vector load must be in the same
4605 : : basic block if it is in a recursive call. */
4606 : 97131 : || !recursive_call_p)
4607 : 457659 : && rtx_equal_p (load->val, val))
4608 : : {
4609 : : /* Record instruction. */
4610 : 96226 : bitmap_set_bit (load->insns, INSN_UID (insn));
4611 : :
4612 : : /* Record the maximum vector size. */
4613 : 96226 : if (kind <= X86_CSE_VEC_DUP
4614 : 191347 : && load->size < GET_MODE_SIZE (mode))
4615 : 944 : load->size = GET_MODE_SIZE (mode);
4616 : :
4617 : : /* Record the basic block. */
4618 : 96226 : bitmap_set_bit (load->bbs, bb->index);
4619 : :
4620 : : /* Increment the count. */
4621 : 96226 : load->count++;
4622 : :
4623 : 96226 : matched = true;
4624 : 96226 : break;
4625 : : }
4626 : :
4627 : 220670 : if (matched)
4628 : 96226 : continue;
4629 : :
4630 : : /* We see this instruction the first time. Record the
4631 : : redundant source value, its mode, the destination size,
4632 : : instruction which defines the redundant source value,
4633 : : instruction basic block and the instruction kind. */
4634 : 124444 : load = new redundant_pattern;
4635 : :
4636 : 124444 : load->val = copy_rtx (val);
4637 : 124444 : if (tlsdesc_val)
4638 : 25 : load->tlsdesc_val = copy_rtx (tlsdesc_val);
4639 : : else
4640 : 124419 : load->tlsdesc_val = nullptr;
4641 : 124444 : load->mode = scalar_mode;
4642 : 124444 : load->size = GET_MODE_SIZE (mode);
4643 : 124444 : load->def_insn = def_insn;
4644 : 124444 : load->count = 1;
4645 : 124444 : load->threshold = threshold;
4646 : 124444 : load->bb = BLOCK_FOR_INSN (insn);
4647 : 124444 : load->kind = kind;
4648 : :
4649 : 124444 : bitmap_set_bit (load->insns, INSN_UID (insn));
4650 : 124444 : bitmap_set_bit (load->bbs, bb->index);
4651 : :
4652 : 124444 : loads.safe_push (load);
4653 : : }
4654 : : }
4655 : :
4656 : : bool replaced = false;
4657 : 1107093 : FOR_EACH_VEC_ELT (loads, i, load)
4658 : 124444 : if (load->count >= load->threshold)
4659 : : {
4660 : 33723 : machine_mode mode;
4661 : 33723 : rtx reg, broadcast_source, broadcast_reg;
4662 : 33723 : replaced = true;
4663 : 33723 : switch (load->kind)
4664 : : {
4665 : 304 : case X86_CSE_TLS_GD:
4666 : 304 : case X86_CSE_TLS_LD_BASE:
4667 : 304 : case X86_CSE_TLSDESC:
4668 : 304 : broadcast_reg = gen_reg_rtx (load->mode);
4669 : 304 : replace_tls_call (broadcast_reg, load->insns,
4670 : 304 : (load->kind == X86_CSE_TLSDESC
4671 : : ? updated_gnu2_tls_insns
4672 : : : updated_gnu_tls_insns));
4673 : 304 : load->broadcast_reg = broadcast_reg;
4674 : 304 : break;
4675 : :
4676 : 33419 : case X86_CSE_CONST0_VECTOR:
4677 : 33419 : case X86_CSE_CONSTM1_VECTOR:
4678 : 33419 : case X86_CSE_VEC_DUP:
4679 : 33419 : mode = ix86_get_vector_cse_mode (load->size, load->mode);
4680 : 33419 : broadcast_reg = gen_reg_rtx (mode);
4681 : 33419 : if (load->def_insn)
4682 : : {
4683 : : /* Replace redundant vector loads with a single vector
4684 : : load in the same basic block. */
4685 : 818 : reg = load->val;
4686 : 818 : if (load->mode != GET_MODE (reg))
4687 : 0 : reg = gen_rtx_SUBREG (load->mode, reg, 0);
4688 : 818 : broadcast_source = gen_rtx_VEC_DUPLICATE (mode, reg);
4689 : : }
4690 : : else
4691 : : /* This is a constant integer/double vector. If the
4692 : : inner scalar is 0 or -1, set vector to CONST0_RTX
4693 : : or CONSTM1_RTX directly. */
4694 : 32601 : switch (load->kind)
4695 : : {
4696 : 21260 : case X86_CSE_CONST0_VECTOR:
4697 : 21260 : broadcast_source = CONST0_RTX (mode);
4698 : 21260 : break;
4699 : 1146 : case X86_CSE_CONSTM1_VECTOR:
4700 : 1146 : broadcast_source = CONSTM1_RTX (mode);
4701 : 1146 : break;
4702 : 10195 : case X86_CSE_VEC_DUP:
4703 : 10195 : reg = gen_reg_rtx (load->mode);
4704 : 10195 : broadcast_source = gen_rtx_VEC_DUPLICATE (mode, reg);
4705 : 10195 : break;
4706 : 0 : default:
4707 : 0 : gcc_unreachable ();
4708 : : }
4709 : 33419 : replace_vector_const (mode, broadcast_reg, load->insns,
4710 : : load->mode);
4711 : 33419 : load->broadcast_source = broadcast_source;
4712 : 33419 : load->broadcast_reg = broadcast_reg;
4713 : 33419 : break;
4714 : : }
4715 : : }
4716 : :
4717 : 982649 : if (replaced)
4718 : : {
4719 : 27727 : auto_vec<rtx_insn *> control_flow_insns;
4720 : :
4721 : : /* (Re-)discover loops so that bb->loop_father can be used in the
4722 : : analysis below. */
4723 : 27727 : calculate_dominance_info (CDI_DOMINATORS);
4724 : 27727 : loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
4725 : :
4726 : 75001 : FOR_EACH_VEC_ELT (loads, i, load)
4727 : 47274 : if (load->count >= load->threshold)
4728 : : {
4729 : 33723 : rtx set;
4730 : 33723 : if (load->def_insn)
4731 : 832 : switch (load->kind)
4732 : : {
4733 : 14 : case X86_CSE_TLSDESC:
4734 : 14 : ix86_place_single_tls_call (load->broadcast_reg,
4735 : : load->tlsdesc_val,
4736 : : load->kind,
4737 : 14 : load->bbs,
4738 : : updated_gnu_tls_insns,
4739 : : updated_gnu2_tls_insns,
4740 : 14 : PATTERN (load->def_insn));
4741 : 14 : break;
4742 : 818 : case X86_CSE_VEC_DUP:
4743 : : /* Insert a broadcast after the original scalar
4744 : : definition. */
4745 : 818 : set = gen_rtx_SET (load->broadcast_reg,
4746 : : load->broadcast_source);
4747 : 818 : insn = emit_insn_after (set, load->def_insn);
4748 : :
4749 : 818 : if (cfun->can_throw_non_call_exceptions)
4750 : : {
4751 : : /* Handle REG_EH_REGION note in DEF_INSN. */
4752 : 6 : rtx note = find_reg_note (load->def_insn,
4753 : : REG_EH_REGION, nullptr);
4754 : 6 : if (note)
4755 : : {
4756 : 1 : control_flow_insns.safe_push (load->def_insn);
4757 : 1 : add_reg_note (insn, REG_EH_REGION,
4758 : : XEXP (note, 0));
4759 : : }
4760 : : }
4761 : :
4762 : 818 : if (dump_file)
4763 : : {
4764 : 0 : fprintf (dump_file, "\nAdd:\n\n");
4765 : 0 : print_rtl_single (dump_file, insn);
4766 : 0 : fprintf (dump_file, "\nafter:\n\n");
4767 : 0 : print_rtl_single (dump_file, load->def_insn);
4768 : 0 : fprintf (dump_file, "\n");
4769 : : }
4770 : : break;
4771 : 0 : default:
4772 : 0 : gcc_unreachable ();
4773 : : }
4774 : : else
4775 : 32891 : switch (load->kind)
4776 : : {
4777 : 290 : case X86_CSE_TLS_GD:
4778 : 290 : case X86_CSE_TLS_LD_BASE:
4779 : 290 : case X86_CSE_TLSDESC:
4780 : 290 : ix86_place_single_tls_call (load->broadcast_reg,
4781 : : (load->kind == X86_CSE_TLSDESC
4782 : : ? load->tlsdesc_val
4783 : : : load->val),
4784 : : load->kind,
4785 : 290 : load->bbs,
4786 : : updated_gnu_tls_insns,
4787 : : updated_gnu2_tls_insns);
4788 : 290 : break;
4789 : 32601 : case X86_CSE_CONST0_VECTOR:
4790 : 32601 : case X86_CSE_CONSTM1_VECTOR:
4791 : 32601 : case X86_CSE_VEC_DUP:
4792 : 32601 : ix86_place_single_vector_set (load->broadcast_reg,
4793 : : load->broadcast_source,
4794 : : load->bbs,
4795 : : load);
4796 : 32601 : break;
4797 : : }
4798 : : }
4799 : :
4800 : 27727 : loop_optimizer_finalize ();
4801 : :
4802 : 27727 : if (!control_flow_insns.is_empty ())
4803 : : {
4804 : 1 : free_dominance_info (CDI_DOMINATORS);
4805 : :
4806 : 3 : FOR_EACH_VEC_ELT (control_flow_insns, i, insn)
4807 : 1 : if (control_flow_insn_p (insn))
4808 : : {
4809 : : /* Split the block after insn. There will be a fallthru
4810 : : edge, which is OK so we keep it. We have to create
4811 : : the exception edges ourselves. */
4812 : 1 : bb = BLOCK_FOR_INSN (insn);
4813 : 1 : split_block (bb, insn);
4814 : 1 : rtl_make_eh_edge (NULL, bb, BB_END (bb));
4815 : : }
4816 : : }
4817 : :
4818 : 27727 : df_process_deferred_rescans ();
4819 : 27727 : }
4820 : :
4821 : 1107093 : FOR_EACH_VEC_ELT (loads, i, load)
4822 : 248888 : delete load;
4823 : :
4824 : 982649 : df_clear_flags (DF_DEFER_INSN_RESCAN);
4825 : :
4826 : 982649 : timevar_pop (TV_MACH_DEP);
4827 : 982649 : return 0;
4828 : 982649 : }
4829 : :
4830 : : } // anon namespace
4831 : :
4832 : : rtl_opt_pass *
4833 : 290417 : make_pass_x86_cse (gcc::context *ctxt)
4834 : : {
4835 : 290417 : return new pass_x86_cse (ctxt);
4836 : : }
4837 : :
4838 : : /* Convert legacy instructions that clobbers EFLAGS to APX_NF
4839 : : instructions when there are no flag set between a flag
4840 : : producer and user. */
4841 : :
4842 : : static unsigned int
4843 : 365 : ix86_apx_nf_convert (void)
4844 : : {
4845 : 365 : timevar_push (TV_MACH_DEP);
4846 : :
4847 : 365 : basic_block bb;
4848 : 365 : rtx_insn *insn;
4849 : 365 : hash_map <rtx_insn *, rtx> converting_map;
4850 : 365 : auto_vec <rtx_insn *> current_convert_list;
4851 : :
4852 : 365 : bool converting_seq = false;
4853 : 365 : rtx cc = gen_rtx_REG (CCmode, FLAGS_REG);
4854 : :
4855 : 780 : FOR_EACH_BB_FN (bb, cfun)
4856 : : {
4857 : : /* Reset conversion for each bb. */
4858 : 415 : converting_seq = false;
4859 : 4960 : FOR_BB_INSNS (bb, insn)
4860 : : {
4861 : 4545 : if (!NONDEBUG_INSN_P (insn))
4862 : 4869 : continue;
4863 : :
4864 : 3620 : if (recog_memoized (insn) < 0)
4865 : 333 : continue;
4866 : :
4867 : : /* Convert candidate insns after cstore, which should
4868 : : satisify the two conditions:
4869 : : 1. Is not flag user or producer, only clobbers
4870 : : FLAGS_REG.
4871 : : 2. Have corresponding nf pattern. */
4872 : :
4873 : 3287 : rtx pat = PATTERN (insn);
4874 : :
4875 : : /* Starting convertion at first cstorecc. */
4876 : 3287 : rtx set = NULL_RTX;
4877 : 3287 : if (!converting_seq
4878 : 2707 : && (set = single_set (insn))
4879 : 2633 : && ix86_comparison_operator (SET_SRC (set), VOIDmode)
4880 : 125 : && reg_overlap_mentioned_p (cc, SET_SRC (set))
4881 : 3409 : && !reg_overlap_mentioned_p (cc, SET_DEST (set)))
4882 : : {
4883 : 122 : converting_seq = true;
4884 : 122 : current_convert_list.truncate (0);
4885 : : }
4886 : : /* Terminate at the next explicit flag set. */
4887 : 3165 : else if (reg_set_p (cc, pat)
4888 : 3165 : && GET_CODE (set_of (cc, pat)) != CLOBBER)
4889 : : converting_seq = false;
4890 : :
4891 : 3070 : if (!converting_seq)
4892 : 2686 : continue;
4893 : :
4894 : 601 : if (get_attr_has_nf (insn)
4895 : 601 : && GET_CODE (pat) == PARALLEL)
4896 : : {
4897 : : /* Record the insn to candidate map. */
4898 : 72 : current_convert_list.safe_push (insn);
4899 : 72 : converting_map.put (insn, pat);
4900 : : }
4901 : : /* If the insn clobbers flags but has no nf_attr,
4902 : : revoke all previous candidates. */
4903 : 529 : else if (!get_attr_has_nf (insn)
4904 : 528 : && reg_set_p (cc, pat)
4905 : 532 : && GET_CODE (set_of (cc, pat)) == CLOBBER)
4906 : : {
4907 : 3 : for (auto item : current_convert_list)
4908 : 0 : converting_map.remove (item);
4909 : 3 : converting_seq = false;
4910 : : }
4911 : : }
4912 : : }
4913 : :
4914 : 365 : if (!converting_map.is_empty ())
4915 : : {
4916 : 85 : for (auto iter = converting_map.begin ();
4917 : 170 : iter != converting_map.end (); ++iter)
4918 : : {
4919 : 72 : rtx_insn *replace = (*iter).first;
4920 : 72 : rtx pat = (*iter).second;
4921 : 72 : int i, n = 0, len = XVECLEN (pat, 0);
4922 : 72 : rtx *new_elems = XALLOCAVEC (rtx, len);
4923 : 72 : rtx new_pat;
4924 : 216 : for (i = 0; i < len; i++)
4925 : : {
4926 : 144 : rtx temp = XVECEXP (pat, 0, i);
4927 : 216 : if (! (GET_CODE (temp) == CLOBBER
4928 : 72 : && reg_overlap_mentioned_p (cc,
4929 : 72 : XEXP (temp, 0))))
4930 : : {
4931 : 72 : new_elems[n] = temp;
4932 : 72 : n++;
4933 : : }
4934 : : }
4935 : :
4936 : 72 : if (n == 1)
4937 : 72 : new_pat = new_elems[0];
4938 : : else
4939 : 0 : new_pat =
4940 : 0 : gen_rtx_PARALLEL (VOIDmode,
4941 : : gen_rtvec_v (n,
4942 : : new_elems));
4943 : :
4944 : 72 : PATTERN (replace) = new_pat;
4945 : 72 : INSN_CODE (replace) = -1;
4946 : 72 : recog_memoized (replace);
4947 : 72 : df_insn_rescan (replace);
4948 : : }
4949 : : }
4950 : :
4951 : 365 : timevar_pop (TV_MACH_DEP);
4952 : 365 : return 0;
4953 : 365 : }
4954 : :
4955 : :
4956 : : namespace {
4957 : :
4958 : : const pass_data pass_data_apx_nf_convert =
4959 : : {
4960 : : RTL_PASS, /* type */
4961 : : "apx_nfcvt", /* name */
4962 : : OPTGROUP_NONE, /* optinfo_flags */
4963 : : TV_MACH_DEP, /* tv_id */
4964 : : 0, /* properties_required */
4965 : : 0, /* properties_provided */
4966 : : 0, /* properties_destroyed */
4967 : : 0, /* todo_flags_start */
4968 : : 0, /* todo_flags_finish */
4969 : : };
4970 : :
4971 : : class pass_apx_nf_convert : public rtl_opt_pass
4972 : : {
4973 : : public:
4974 : 290417 : pass_apx_nf_convert (gcc::context *ctxt)
4975 : 580834 : : rtl_opt_pass (pass_data_apx_nf_convert, ctxt)
4976 : : {}
4977 : :
4978 : : /* opt_pass methods: */
4979 : 1478637 : bool gate (function *) final override
4980 : : {
4981 : 1478637 : return (TARGET_APX_NF
4982 : 458 : && optimize
4983 : 1479086 : && optimize_function_for_speed_p (cfun));
4984 : : }
4985 : :
4986 : 365 : unsigned int execute (function *) final override
4987 : : {
4988 : 365 : return ix86_apx_nf_convert ();
4989 : : }
4990 : : }; // class pass_apx_nf_convert
4991 : :
4992 : : } // anon namespace
4993 : :
4994 : : rtl_opt_pass *
4995 : 290417 : make_pass_apx_nf_convert (gcc::context *ctxt)
4996 : : {
4997 : 290417 : return new pass_apx_nf_convert (ctxt);
4998 : : }
4999 : :
5000 : : /* When a hot loop can be fit into one cacheline,
5001 : : force align the loop without considering the max skip. */
5002 : : static void
5003 : 984486 : ix86_align_loops ()
5004 : : {
5005 : 984486 : basic_block bb;
5006 : :
5007 : : /* Don't do this when we don't know cache line size. */
5008 : 984486 : if (ix86_cost->prefetch_block == 0)
5009 : 9 : return;
5010 : :
5011 : 984477 : loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
5012 : 984477 : profile_count count_threshold = cfun->cfg->count_max / param_align_threshold;
5013 : 11664818 : FOR_EACH_BB_FN (bb, cfun)
5014 : : {
5015 : 10680341 : rtx_insn *label = BB_HEAD (bb);
5016 : 10680341 : bool has_fallthru = 0;
5017 : 10680341 : edge e;
5018 : 10680341 : edge_iterator ei;
5019 : :
5020 : 10680341 : if (!LABEL_P (label))
5021 : 5409524 : continue;
5022 : :
5023 : 5275745 : profile_count fallthru_count = profile_count::zero ();
5024 : 5275745 : profile_count branch_count = profile_count::zero ();
5025 : :
5026 : 15354290 : FOR_EACH_EDGE (e, ei, bb->preds)
5027 : : {
5028 : 10078545 : if (e->flags & EDGE_FALLTHRU)
5029 : 2568977 : has_fallthru = 1, fallthru_count += e->count ();
5030 : : else
5031 : 7509568 : branch_count += e->count ();
5032 : : }
5033 : :
5034 : 5275745 : if (!fallthru_count.initialized_p () || !branch_count.initialized_p ())
5035 : 4928 : continue;
5036 : :
5037 : 5270817 : if (bb->loop_father
5038 : 5270817 : && bb->loop_father->latch != EXIT_BLOCK_PTR_FOR_FN (cfun)
5039 : 6633752 : && (has_fallthru
5040 : 1362935 : ? (!(single_succ_p (bb)
5041 : 145318 : && single_succ (bb) == EXIT_BLOCK_PTR_FOR_FN (cfun))
5042 : 948365 : && optimize_bb_for_speed_p (bb)
5043 : 864452 : && branch_count + fallthru_count > count_threshold
5044 : 743940 : && (branch_count > fallthru_count * param_align_loop_iterations))
5045 : : /* In case there'no fallthru for the loop.
5046 : : Nops inserted won't be executed. */
5047 : 414570 : : (branch_count > count_threshold
5048 : 142071 : || (bb->count > bb->prev_bb->count * 10
5049 : 12997 : && (bb->prev_bb->count
5050 : 4728697 : <= ENTRY_BLOCK_PTR_FOR_FN (cfun)->count / 2)))))
5051 : : {
5052 : 555117 : rtx_insn* insn, *end_insn;
5053 : 555117 : HOST_WIDE_INT size = 0;
5054 : 555117 : bool padding_p = true;
5055 : 555117 : basic_block tbb = bb;
5056 : 555117 : unsigned cond_branch_num = 0;
5057 : 555117 : bool detect_tight_loop_p = false;
5058 : :
5059 : 872369 : for (unsigned int i = 0; i != bb->loop_father->num_nodes;
5060 : 317252 : i++, tbb = tbb->next_bb)
5061 : : {
5062 : : /* Only handle continuous cfg layout. */
5063 : 872369 : if (bb->loop_father != tbb->loop_father)
5064 : : {
5065 : : padding_p = false;
5066 : : break;
5067 : : }
5068 : :
5069 : 10133691 : FOR_BB_INSNS (tbb, insn)
5070 : : {
5071 : 9466311 : if (!NONDEBUG_INSN_P (insn))
5072 : 5369849 : continue;
5073 : 4096462 : size += ix86_min_insn_size (insn);
5074 : :
5075 : : /* We don't know size of inline asm.
5076 : : Don't align loop for call. */
5077 : 4096462 : if (asm_noperands (PATTERN (insn)) >= 0
5078 : 4096462 : || CALL_P (insn))
5079 : : {
5080 : : size = -1;
5081 : : break;
5082 : : }
5083 : : }
5084 : :
5085 : 828174 : if (size == -1 || size > ix86_cost->prefetch_block)
5086 : : {
5087 : : padding_p = false;
5088 : : break;
5089 : : }
5090 : :
5091 : 1478442 : FOR_EACH_EDGE (e, ei, tbb->succs)
5092 : : {
5093 : : /* It could be part of the loop. */
5094 : 1018740 : if (e->dest == bb)
5095 : : {
5096 : : detect_tight_loop_p = true;
5097 : : break;
5098 : : }
5099 : : }
5100 : :
5101 : 641810 : if (detect_tight_loop_p)
5102 : : break;
5103 : :
5104 : 459702 : end_insn = BB_END (tbb);
5105 : 459702 : if (JUMP_P (end_insn))
5106 : : {
5107 : : /* For decoded icache:
5108 : : 1. Up to two branches are allowed per Way.
5109 : : 2. A non-conditional branch is the last micro-op in a Way.
5110 : : */
5111 : 374778 : if (onlyjump_p (end_insn)
5112 : 374778 : && (any_uncondjump_p (end_insn)
5113 : 315554 : || single_succ_p (tbb)))
5114 : : {
5115 : : padding_p = false;
5116 : : break;
5117 : : }
5118 : 315554 : else if (++cond_branch_num >= 2)
5119 : : {
5120 : : padding_p = false;
5121 : : break;
5122 : : }
5123 : : }
5124 : :
5125 : : }
5126 : :
5127 : 555117 : if (padding_p && detect_tight_loop_p)
5128 : : {
5129 : 364216 : emit_insn_before (gen_max_skip_align (GEN_INT (ceil_log2 (size)),
5130 : : GEN_INT (0)), label);
5131 : : /* End of function. */
5132 : 182108 : if (!tbb || tbb == EXIT_BLOCK_PTR_FOR_FN (cfun))
5133 : : break;
5134 : : /* Skip bb which already fits into one cacheline. */
5135 : : bb = tbb;
5136 : : }
5137 : : }
5138 : : }
5139 : :
5140 : 984477 : loop_optimizer_finalize ();
5141 : 984477 : free_dominance_info (CDI_DOMINATORS);
5142 : : }
5143 : :
5144 : : namespace {
5145 : :
5146 : : const pass_data pass_data_align_tight_loops =
5147 : : {
5148 : : RTL_PASS, /* type */
5149 : : "align_tight_loops", /* name */
5150 : : OPTGROUP_NONE, /* optinfo_flags */
5151 : : TV_MACH_DEP, /* tv_id */
5152 : : 0, /* properties_required */
5153 : : 0, /* properties_provided */
5154 : : 0, /* properties_destroyed */
5155 : : 0, /* todo_flags_start */
5156 : : 0, /* todo_flags_finish */
5157 : : };
5158 : :
5159 : : class pass_align_tight_loops : public rtl_opt_pass
5160 : : {
5161 : : public:
5162 : 290417 : pass_align_tight_loops (gcc::context *ctxt)
5163 : 580834 : : rtl_opt_pass (pass_data_align_tight_loops, ctxt)
5164 : : {}
5165 : :
5166 : : /* opt_pass methods: */
5167 : 1478637 : bool gate (function *) final override
5168 : : {
5169 : 1478637 : return TARGET_ALIGN_TIGHT_LOOPS
5170 : 1478168 : && optimize
5171 : 2527242 : && optimize_function_for_speed_p (cfun);
5172 : : }
5173 : :
5174 : 984486 : unsigned int execute (function *) final override
5175 : : {
5176 : 984486 : timevar_push (TV_MACH_DEP);
5177 : : #ifdef ASM_OUTPUT_MAX_SKIP_ALIGN
5178 : 984486 : ix86_align_loops ();
5179 : : #endif
5180 : 984486 : timevar_pop (TV_MACH_DEP);
5181 : 984486 : return 0;
5182 : : }
5183 : : }; // class pass_align_tight_loops
5184 : :
5185 : : } // anon namespace
5186 : :
5187 : : rtl_opt_pass *
5188 : 290417 : make_pass_align_tight_loops (gcc::context *ctxt)
5189 : : {
5190 : 290417 : return new pass_align_tight_loops (ctxt);
5191 : : }
5192 : :
5193 : : /* This compares the priority of target features in function DECL1
5194 : : and DECL2. It returns positive value if DECL1 is higher priority,
5195 : : negative value if DECL2 is higher priority and 0 if they are the
5196 : : same. */
5197 : :
5198 : : int
5199 : 5701 : ix86_compare_version_priority (tree decl1, tree decl2)
5200 : : {
5201 : 5701 : unsigned int priority1 = get_builtin_code_for_version (decl1, NULL);
5202 : 5701 : unsigned int priority2 = get_builtin_code_for_version (decl2, NULL);
5203 : :
5204 : 5701 : return (int)priority1 - (int)priority2;
5205 : : }
5206 : :
5207 : : /* V1 and V2 point to function versions with different priorities
5208 : : based on the target ISA. This function compares their priorities. */
5209 : :
5210 : : static int
5211 : 6770 : feature_compare (const void *v1, const void *v2)
5212 : : {
5213 : 6770 : typedef struct _function_version_info
5214 : : {
5215 : : tree version_decl;
5216 : : tree predicate_chain;
5217 : : unsigned int dispatch_priority;
5218 : : } function_version_info;
5219 : :
5220 : 6770 : const function_version_info c1 = *(const function_version_info *)v1;
5221 : 6770 : const function_version_info c2 = *(const function_version_info *)v2;
5222 : 6770 : return (c2.dispatch_priority - c1.dispatch_priority);
5223 : : }
5224 : :
5225 : : /* This adds a condition to the basic_block NEW_BB in function FUNCTION_DECL
5226 : : to return a pointer to VERSION_DECL if the outcome of the expression
5227 : : formed by PREDICATE_CHAIN is true. This function will be called during
5228 : : version dispatch to decide which function version to execute. It returns
5229 : : the basic block at the end, to which more conditions can be added. */
5230 : :
5231 : : static basic_block
5232 : 815 : add_condition_to_bb (tree function_decl, tree version_decl,
5233 : : tree predicate_chain, basic_block new_bb)
5234 : : {
5235 : 815 : gimple *return_stmt;
5236 : 815 : tree convert_expr, result_var;
5237 : 815 : gimple *convert_stmt;
5238 : 815 : gimple *call_cond_stmt;
5239 : 815 : gimple *if_else_stmt;
5240 : :
5241 : 815 : basic_block bb1, bb2, bb3;
5242 : 815 : edge e12, e23;
5243 : :
5244 : 815 : tree cond_var, and_expr_var = NULL_TREE;
5245 : 815 : gimple_seq gseq;
5246 : :
5247 : 815 : tree predicate_decl, predicate_arg;
5248 : :
5249 : 815 : push_cfun (DECL_STRUCT_FUNCTION (function_decl));
5250 : :
5251 : 815 : gcc_assert (new_bb != NULL);
5252 : 815 : gseq = bb_seq (new_bb);
5253 : :
5254 : :
5255 : 815 : convert_expr = build1 (CONVERT_EXPR, ptr_type_node,
5256 : : build_fold_addr_expr (version_decl));
5257 : 815 : result_var = create_tmp_var (ptr_type_node);
5258 : 815 : convert_stmt = gimple_build_assign (result_var, convert_expr);
5259 : 815 : return_stmt = gimple_build_return (result_var);
5260 : :
5261 : 815 : if (predicate_chain == NULL_TREE)
5262 : : {
5263 : 195 : gimple_seq_add_stmt (&gseq, convert_stmt);
5264 : 195 : gimple_seq_add_stmt (&gseq, return_stmt);
5265 : 195 : set_bb_seq (new_bb, gseq);
5266 : 195 : gimple_set_bb (convert_stmt, new_bb);
5267 : 195 : gimple_set_bb (return_stmt, new_bb);
5268 : 195 : pop_cfun ();
5269 : 195 : return new_bb;
5270 : : }
5271 : :
5272 : 1279 : while (predicate_chain != NULL)
5273 : : {
5274 : 659 : cond_var = create_tmp_var (integer_type_node);
5275 : 659 : predicate_decl = TREE_PURPOSE (predicate_chain);
5276 : 659 : predicate_arg = TREE_VALUE (predicate_chain);
5277 : 659 : call_cond_stmt = gimple_build_call (predicate_decl, 1, predicate_arg);
5278 : 659 : gimple_call_set_lhs (call_cond_stmt, cond_var);
5279 : :
5280 : 659 : gimple_set_block (call_cond_stmt, DECL_INITIAL (function_decl));
5281 : 659 : gimple_set_bb (call_cond_stmt, new_bb);
5282 : 659 : gimple_seq_add_stmt (&gseq, call_cond_stmt);
5283 : :
5284 : 659 : predicate_chain = TREE_CHAIN (predicate_chain);
5285 : :
5286 : 659 : if (and_expr_var == NULL)
5287 : : and_expr_var = cond_var;
5288 : : else
5289 : : {
5290 : 39 : gimple *assign_stmt;
5291 : : /* Use MIN_EXPR to check if any integer is zero?.
5292 : : and_expr_var = min_expr <cond_var, and_expr_var> */
5293 : 39 : assign_stmt = gimple_build_assign (and_expr_var,
5294 : : build2 (MIN_EXPR, integer_type_node,
5295 : : cond_var, and_expr_var));
5296 : :
5297 : 39 : gimple_set_block (assign_stmt, DECL_INITIAL (function_decl));
5298 : 39 : gimple_set_bb (assign_stmt, new_bb);
5299 : 39 : gimple_seq_add_stmt (&gseq, assign_stmt);
5300 : : }
5301 : : }
5302 : :
5303 : 620 : if_else_stmt = gimple_build_cond (GT_EXPR, and_expr_var,
5304 : : integer_zero_node,
5305 : : NULL_TREE, NULL_TREE);
5306 : 620 : gimple_set_block (if_else_stmt, DECL_INITIAL (function_decl));
5307 : 620 : gimple_set_bb (if_else_stmt, new_bb);
5308 : 620 : gimple_seq_add_stmt (&gseq, if_else_stmt);
5309 : :
5310 : 620 : gimple_seq_add_stmt (&gseq, convert_stmt);
5311 : 620 : gimple_seq_add_stmt (&gseq, return_stmt);
5312 : 620 : set_bb_seq (new_bb, gseq);
5313 : :
5314 : 620 : bb1 = new_bb;
5315 : 620 : e12 = split_block (bb1, if_else_stmt);
5316 : 620 : bb2 = e12->dest;
5317 : 620 : e12->flags &= ~EDGE_FALLTHRU;
5318 : 620 : e12->flags |= EDGE_TRUE_VALUE;
5319 : :
5320 : 620 : e23 = split_block (bb2, return_stmt);
5321 : :
5322 : 620 : gimple_set_bb (convert_stmt, bb2);
5323 : 620 : gimple_set_bb (return_stmt, bb2);
5324 : :
5325 : 620 : bb3 = e23->dest;
5326 : 620 : make_edge (bb1, bb3, EDGE_FALSE_VALUE);
5327 : :
5328 : 620 : remove_edge (e23);
5329 : 620 : make_edge (bb2, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
5330 : :
5331 : 620 : pop_cfun ();
5332 : :
5333 : 620 : return bb3;
5334 : : }
5335 : :
5336 : : /* This function generates the dispatch function for
5337 : : multi-versioned functions. DISPATCH_DECL is the function which will
5338 : : contain the dispatch logic. FNDECLS are the function choices for
5339 : : dispatch, and is a tree chain. EMPTY_BB is the basic block pointer
5340 : : in DISPATCH_DECL in which the dispatch code is generated. */
5341 : :
5342 : : static int
5343 : 195 : dispatch_function_versions (tree dispatch_decl,
5344 : : void *fndecls_p,
5345 : : basic_block *empty_bb)
5346 : : {
5347 : 195 : tree default_decl;
5348 : 195 : gimple *ifunc_cpu_init_stmt;
5349 : 195 : gimple_seq gseq;
5350 : 195 : int ix;
5351 : 195 : tree ele;
5352 : 195 : vec<tree> *fndecls;
5353 : 195 : unsigned int num_versions = 0;
5354 : 195 : unsigned int actual_versions = 0;
5355 : 195 : unsigned int i;
5356 : :
5357 : 195 : struct _function_version_info
5358 : : {
5359 : : tree version_decl;
5360 : : tree predicate_chain;
5361 : : unsigned int dispatch_priority;
5362 : : }*function_version_info;
5363 : :
5364 : 195 : gcc_assert (dispatch_decl != NULL
5365 : : && fndecls_p != NULL
5366 : : && empty_bb != NULL);
5367 : :
5368 : : /*fndecls_p is actually a vector. */
5369 : 195 : fndecls = static_cast<vec<tree> *> (fndecls_p);
5370 : :
5371 : : /* At least one more version other than the default. */
5372 : 195 : num_versions = fndecls->length ();
5373 : 195 : gcc_assert (num_versions >= 2);
5374 : :
5375 : 195 : function_version_info = (struct _function_version_info *)
5376 : 195 : XNEWVEC (struct _function_version_info, (num_versions - 1));
5377 : :
5378 : : /* The first version in the vector is the default decl. */
5379 : 195 : default_decl = (*fndecls)[0];
5380 : :
5381 : 195 : push_cfun (DECL_STRUCT_FUNCTION (dispatch_decl));
5382 : :
5383 : 195 : gseq = bb_seq (*empty_bb);
5384 : : /* Function version dispatch is via IFUNC. IFUNC resolvers fire before
5385 : : constructors, so explicity call __builtin_cpu_init here. */
5386 : 195 : ifunc_cpu_init_stmt
5387 : 195 : = gimple_build_call_vec (get_ix86_builtin (IX86_BUILTIN_CPU_INIT), vNULL);
5388 : 195 : gimple_seq_add_stmt (&gseq, ifunc_cpu_init_stmt);
5389 : 195 : gimple_set_bb (ifunc_cpu_init_stmt, *empty_bb);
5390 : 195 : set_bb_seq (*empty_bb, gseq);
5391 : :
5392 : 195 : pop_cfun ();
5393 : :
5394 : :
5395 : 972 : for (ix = 1; fndecls->iterate (ix, &ele); ++ix)
5396 : : {
5397 : 777 : tree version_decl = ele;
5398 : 777 : tree predicate_chain = NULL_TREE;
5399 : 777 : unsigned int priority;
5400 : : /* Get attribute string, parse it and find the right predicate decl.
5401 : : The predicate function could be a lengthy combination of many
5402 : : features, like arch-type and various isa-variants. */
5403 : 777 : priority = get_builtin_code_for_version (version_decl,
5404 : : &predicate_chain);
5405 : :
5406 : 777 : if (predicate_chain == NULL_TREE)
5407 : 157 : continue;
5408 : :
5409 : 620 : function_version_info [actual_versions].version_decl = version_decl;
5410 : 620 : function_version_info [actual_versions].predicate_chain
5411 : 620 : = predicate_chain;
5412 : 620 : function_version_info [actual_versions].dispatch_priority = priority;
5413 : 620 : actual_versions++;
5414 : : }
5415 : :
5416 : : /* Sort the versions according to descending order of dispatch priority. The
5417 : : priority is based on the ISA. This is not a perfect solution. There
5418 : : could still be ambiguity. If more than one function version is suitable
5419 : : to execute, which one should be dispatched? In future, allow the user
5420 : : to specify a dispatch priority next to the version. */
5421 : 195 : qsort (function_version_info, actual_versions,
5422 : : sizeof (struct _function_version_info), feature_compare);
5423 : :
5424 : 1010 : for (i = 0; i < actual_versions; ++i)
5425 : 620 : *empty_bb = add_condition_to_bb (dispatch_decl,
5426 : : function_version_info[i].version_decl,
5427 : 620 : function_version_info[i].predicate_chain,
5428 : : *empty_bb);
5429 : :
5430 : : /* dispatch default version at the end. */
5431 : 195 : *empty_bb = add_condition_to_bb (dispatch_decl, default_decl,
5432 : : NULL, *empty_bb);
5433 : :
5434 : 195 : free (function_version_info);
5435 : 195 : return 0;
5436 : : }
5437 : :
5438 : : /* This function changes the assembler name for functions that are
5439 : : versions. If DECL is a function version and has a "target"
5440 : : attribute, it appends the attribute string to its assembler name. */
5441 : :
5442 : : static tree
5443 : 1097 : ix86_mangle_function_version_assembler_name (tree decl, tree id)
5444 : : {
5445 : 1097 : tree version_attr;
5446 : 1097 : char *attr_str;
5447 : :
5448 : 1097 : if (DECL_DECLARED_INLINE_P (decl)
5449 : 1144 : && lookup_attribute ("gnu_inline",
5450 : 47 : DECL_ATTRIBUTES (decl)))
5451 : 0 : error_at (DECL_SOURCE_LOCATION (decl),
5452 : : "function versions cannot be marked as %<gnu_inline%>,"
5453 : : " bodies have to be generated");
5454 : :
5455 : 1097 : if (DECL_VIRTUAL_P (decl)
5456 : 2194 : || DECL_VINDEX (decl))
5457 : 0 : sorry ("virtual function multiversioning not supported");
5458 : :
5459 : 1097 : version_attr = lookup_attribute ("target", DECL_ATTRIBUTES (decl));
5460 : :
5461 : : /* target attribute string cannot be NULL. */
5462 : 1097 : gcc_assert (version_attr != NULL_TREE);
5463 : :
5464 : 1097 : attr_str = sorted_attr_string (TREE_VALUE (version_attr));
5465 : :
5466 : : /* Allow assembler name to be modified if already set. */
5467 : 1097 : if (DECL_ASSEMBLER_NAME_SET_P (decl))
5468 : 1082 : SET_DECL_RTL (decl, NULL);
5469 : :
5470 : 1097 : tree ret = clone_identifier (id, attr_str, true);
5471 : :
5472 : 1097 : XDELETEVEC (attr_str);
5473 : :
5474 : 1097 : return ret;
5475 : : }
5476 : :
5477 : : tree
5478 : 458787973 : ix86_mangle_decl_assembler_name (tree decl, tree id)
5479 : : {
5480 : : /* For function version, add the target suffix to the assembler name. */
5481 : 458787973 : if (TREE_CODE (decl) == FUNCTION_DECL)
5482 : : {
5483 : 433669194 : cgraph_node *node = cgraph_node::get (decl);
5484 : : /* Mangle all versions when annotated with target_clones, but only
5485 : : non-default versions when annotated with target attributes. */
5486 : 433669194 : if (DECL_FUNCTION_VERSIONED (decl)
5487 : 433669194 : && (node->is_target_clone
5488 : 1074 : || !is_function_default_version (node->decl)))
5489 : 1097 : id = ix86_mangle_function_version_assembler_name (decl, id);
5490 : : /* Mangle the dispatched symbol but only in the case of target clones. */
5491 : 433668097 : else if (node && node->dispatcher_function && !node->is_target_clone)
5492 : 114 : id = clone_identifier (id, "ifunc");
5493 : 58519745 : else if (node && node->dispatcher_resolver_function)
5494 : 195 : id = clone_identifier (id, "resolver");
5495 : : }
5496 : : #ifdef SUBTARGET_MANGLE_DECL_ASSEMBLER_NAME
5497 : : id = SUBTARGET_MANGLE_DECL_ASSEMBLER_NAME (decl, id);
5498 : : #endif
5499 : :
5500 : 458787973 : return id;
5501 : : }
5502 : :
5503 : : /* Make a dispatcher declaration for the multi-versioned function DECL.
5504 : : Calls to DECL function will be replaced with calls to the dispatcher
5505 : : by the front-end. Returns the decl of the dispatcher function. */
5506 : :
5507 : : tree
5508 : 321 : ix86_get_function_versions_dispatcher (void *decl)
5509 : : {
5510 : 321 : tree fn = (tree) decl;
5511 : 321 : struct cgraph_node *node = NULL;
5512 : 321 : struct cgraph_node *default_node = NULL;
5513 : 321 : struct cgraph_function_version_info *node_v = NULL;
5514 : :
5515 : 321 : tree dispatch_decl = NULL;
5516 : :
5517 : 321 : struct cgraph_function_version_info *default_version_info = NULL;
5518 : :
5519 : 642 : gcc_assert (fn != NULL && DECL_FUNCTION_VERSIONED (fn));
5520 : :
5521 : 321 : node = cgraph_node::get (fn);
5522 : 321 : gcc_assert (node != NULL);
5523 : :
5524 : 321 : node_v = node->function_version ();
5525 : 321 : gcc_assert (node_v != NULL);
5526 : :
5527 : 321 : if (node_v->dispatcher_resolver != NULL)
5528 : : return node_v->dispatcher_resolver;
5529 : :
5530 : : /* The default node is always the beginning of the chain. */
5531 : : default_version_info = node_v;
5532 : 657 : while (default_version_info->prev != NULL)
5533 : : default_version_info = default_version_info->prev;
5534 : 207 : default_node = default_version_info->this_node;
5535 : :
5536 : : /* If there is no default node, just return NULL. */
5537 : 207 : if (!is_function_default_version (default_node->decl))
5538 : : return NULL;
5539 : :
5540 : : #if defined (ASM_OUTPUT_TYPE_DIRECTIVE)
5541 : 198 : if (targetm.has_ifunc_p ())
5542 : : {
5543 : 198 : struct cgraph_function_version_info *it_v = NULL;
5544 : :
5545 : : /* Right now, the dispatching is done via ifunc. */
5546 : 198 : dispatch_decl = make_dispatcher_decl (default_node->decl);
5547 : :
5548 : : /* Set the dispatcher for all the versions. */
5549 : 198 : it_v = default_version_info;
5550 : 1374 : while (it_v != NULL)
5551 : : {
5552 : 978 : it_v->dispatcher_resolver = dispatch_decl;
5553 : 978 : it_v = it_v->next;
5554 : : }
5555 : : }
5556 : : else
5557 : : #endif
5558 : : {
5559 : 0 : error_at (DECL_SOURCE_LOCATION (default_node->decl),
5560 : : "multiversioning needs %<ifunc%> which is not supported "
5561 : : "on this target");
5562 : : }
5563 : :
5564 : : return dispatch_decl;
5565 : : }
5566 : :
5567 : : /* Make the resolver function decl to dispatch the versions of
5568 : : a multi-versioned function, DEFAULT_DECL. IFUNC_ALIAS_DECL is
5569 : : ifunc alias that will point to the created resolver. Create an
5570 : : empty basic block in the resolver and store the pointer in
5571 : : EMPTY_BB. Return the decl of the resolver function. */
5572 : :
5573 : : static tree
5574 : 195 : make_resolver_func (const tree default_decl,
5575 : : const tree ifunc_alias_decl,
5576 : : basic_block *empty_bb)
5577 : : {
5578 : 195 : tree decl, type, t;
5579 : :
5580 : : /* The resolver function should return a (void *). */
5581 : 195 : type = build_function_type_list (ptr_type_node, NULL_TREE);
5582 : :
5583 : 195 : cgraph_node *node = cgraph_node::get (default_decl);
5584 : 195 : gcc_assert (node && node->function_version ());
5585 : :
5586 : 195 : decl = build_fn_decl (IDENTIFIER_POINTER (DECL_NAME (default_decl)), type);
5587 : :
5588 : : /* Set the assembler name to prevent cgraph_node attempting to mangle. */
5589 : 195 : SET_DECL_ASSEMBLER_NAME (decl, DECL_ASSEMBLER_NAME (default_decl));
5590 : :
5591 : 195 : cgraph_node *resolver_node = cgraph_node::get_create (decl);
5592 : 195 : resolver_node->dispatcher_resolver_function = true;
5593 : :
5594 : 195 : if (node->is_target_clone)
5595 : 84 : resolver_node->is_target_clone = true;
5596 : :
5597 : 195 : tree id = ix86_mangle_decl_assembler_name
5598 : 195 : (decl, node->function_version ()->assembler_name);
5599 : 195 : SET_DECL_ASSEMBLER_NAME (decl, id);
5600 : :
5601 : 195 : DECL_NAME (decl) = DECL_NAME (default_decl);
5602 : 195 : TREE_USED (decl) = 1;
5603 : 195 : DECL_ARTIFICIAL (decl) = 1;
5604 : 195 : DECL_IGNORED_P (decl) = 1;
5605 : 195 : TREE_PUBLIC (decl) = 0;
5606 : 195 : DECL_UNINLINABLE (decl) = 1;
5607 : :
5608 : : /* Resolver is not external, body is generated. */
5609 : 195 : DECL_EXTERNAL (decl) = 0;
5610 : 195 : DECL_EXTERNAL (ifunc_alias_decl) = 0;
5611 : :
5612 : 195 : DECL_CONTEXT (decl) = NULL_TREE;
5613 : 195 : DECL_INITIAL (decl) = make_node (BLOCK);
5614 : 195 : DECL_STATIC_CONSTRUCTOR (decl) = 0;
5615 : :
5616 : 195 : if (DECL_COMDAT_GROUP (default_decl)
5617 : 195 : || TREE_PUBLIC (default_decl))
5618 : : {
5619 : : /* In this case, each translation unit with a call to this
5620 : : versioned function will put out a resolver. Ensure it
5621 : : is comdat to keep just one copy. */
5622 : 171 : DECL_COMDAT (decl) = 1;
5623 : 171 : make_decl_one_only (decl, DECL_ASSEMBLER_NAME (decl));
5624 : : }
5625 : : else
5626 : 24 : TREE_PUBLIC (ifunc_alias_decl) = 0;
5627 : :
5628 : : /* Build result decl and add to function_decl. */
5629 : 195 : t = build_decl (UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE, ptr_type_node);
5630 : 195 : DECL_CONTEXT (t) = decl;
5631 : 195 : DECL_ARTIFICIAL (t) = 1;
5632 : 195 : DECL_IGNORED_P (t) = 1;
5633 : 195 : DECL_RESULT (decl) = t;
5634 : :
5635 : 195 : gimplify_function_tree (decl);
5636 : 195 : push_cfun (DECL_STRUCT_FUNCTION (decl));
5637 : 195 : *empty_bb = init_lowered_empty_function (decl, false,
5638 : : profile_count::uninitialized ());
5639 : :
5640 : 195 : cgraph_node::add_new_function (decl, true);
5641 : 195 : symtab->call_cgraph_insertion_hooks (cgraph_node::get_create (decl));
5642 : :
5643 : 195 : pop_cfun ();
5644 : :
5645 : 195 : gcc_assert (ifunc_alias_decl != NULL);
5646 : : /* Mark ifunc_alias_decl as "ifunc" with resolver as resolver_name. */
5647 : 195 : DECL_ATTRIBUTES (ifunc_alias_decl)
5648 : 195 : = make_attribute ("ifunc", IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)),
5649 : 195 : DECL_ATTRIBUTES (ifunc_alias_decl));
5650 : :
5651 : : /* Create the alias for dispatch to resolver here. */
5652 : 195 : cgraph_node::create_same_body_alias (ifunc_alias_decl, decl);
5653 : 195 : return decl;
5654 : : }
5655 : :
5656 : : /* Generate the dispatching code body to dispatch multi-versioned function
5657 : : DECL. The target hook is called to process the "target" attributes and
5658 : : provide the code to dispatch the right function at run-time. NODE points
5659 : : to the dispatcher decl whose body will be created. */
5660 : :
5661 : : tree
5662 : 195 : ix86_generate_version_dispatcher_body (void *node_p)
5663 : : {
5664 : 195 : tree resolver_decl;
5665 : 195 : basic_block empty_bb;
5666 : 195 : tree default_ver_decl;
5667 : 195 : struct cgraph_node *versn;
5668 : 195 : struct cgraph_node *node;
5669 : :
5670 : 195 : struct cgraph_function_version_info *node_version_info = NULL;
5671 : 195 : struct cgraph_function_version_info *versn_info = NULL;
5672 : :
5673 : 195 : node = (cgraph_node *)node_p;
5674 : :
5675 : 195 : node_version_info = node->function_version ();
5676 : 195 : gcc_assert (node->dispatcher_function
5677 : : && node_version_info != NULL);
5678 : :
5679 : 195 : if (node_version_info->dispatcher_resolver)
5680 : : return node_version_info->dispatcher_resolver;
5681 : :
5682 : : /* The first version in the chain corresponds to the default version. */
5683 : 195 : default_ver_decl = node_version_info->next->this_node->decl;
5684 : :
5685 : : /* node is going to be an alias, so remove the finalized bit. */
5686 : 195 : node->definition = false;
5687 : :
5688 : 195 : resolver_decl = make_resolver_func (default_ver_decl,
5689 : : node->decl, &empty_bb);
5690 : :
5691 : 195 : node_version_info->dispatcher_resolver = resolver_decl;
5692 : :
5693 : 195 : push_cfun (DECL_STRUCT_FUNCTION (resolver_decl));
5694 : :
5695 : 195 : auto_vec<tree, 2> fn_ver_vec;
5696 : :
5697 : 1167 : for (versn_info = node_version_info->next; versn_info;
5698 : 972 : versn_info = versn_info->next)
5699 : : {
5700 : 972 : versn = versn_info->this_node;
5701 : : /* Check for virtual functions here again, as by this time it should
5702 : : have been determined if this function needs a vtable index or
5703 : : not. This happens for methods in derived classes that override
5704 : : virtual methods in base classes but are not explicitly marked as
5705 : : virtual. */
5706 : 972 : if (DECL_VINDEX (versn->decl))
5707 : 0 : sorry ("virtual function multiversioning not supported");
5708 : :
5709 : 972 : fn_ver_vec.safe_push (versn->decl);
5710 : : }
5711 : :
5712 : 195 : dispatch_function_versions (resolver_decl, &fn_ver_vec, &empty_bb);
5713 : 195 : cgraph_edge::rebuild_edges ();
5714 : 195 : pop_cfun ();
5715 : 195 : return resolver_decl;
5716 : 195 : }
5717 : :
5718 : :
|