Line data Source code
1 : /* Copyright (C) 1988-2026 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-options.h"
94 : #include "i386-builtins.h"
95 : #include "i386-expand.h"
96 : #include "asan.h"
97 : #include "function-abi.h"
98 :
99 : /* Split one or more double-mode RTL references into pairs of half-mode
100 : references. The RTL can be REG, offsettable MEM, integer constant, or
101 : CONST_DOUBLE. "operands" is a pointer to an array of double-mode RTLs to
102 : split and "num" is its length. lo_half and hi_half are output arrays
103 : that parallel "operands". */
104 :
105 : void
106 4195086 : split_double_mode (machine_mode mode, rtx operands[],
107 : int num, rtx lo_half[], rtx hi_half[])
108 : {
109 4195086 : machine_mode half_mode;
110 4195086 : unsigned int byte;
111 4195086 : rtx mem_op = NULL_RTX;
112 4195086 : int mem_num = 0;
113 :
114 4195086 : switch (mode)
115 : {
116 : case E_TImode:
117 : half_mode = DImode;
118 : break;
119 605429 : case E_DImode:
120 605429 : half_mode = SImode;
121 605429 : break;
122 6 : case E_P2HImode:
123 6 : half_mode = HImode;
124 6 : break;
125 30 : case E_P2QImode:
126 30 : half_mode = QImode;
127 30 : break;
128 0 : default:
129 0 : gcc_unreachable ();
130 : }
131 :
132 4195086 : byte = GET_MODE_SIZE (half_mode);
133 :
134 8605251 : while (num--)
135 : {
136 4410165 : rtx op = operands[num];
137 :
138 : /* simplify_subreg refuse to split volatile memory addresses,
139 : but we still have to handle it. */
140 4410165 : if (MEM_P (op))
141 : {
142 1750897 : if (mem_op && rtx_equal_p (op, mem_op))
143 : {
144 2401 : lo_half[num] = lo_half[mem_num];
145 2401 : hi_half[num] = hi_half[mem_num];
146 : }
147 : else
148 : {
149 1748496 : mem_op = op;
150 1748496 : mem_num = num;
151 1748496 : lo_half[num] = adjust_address (op, half_mode, 0);
152 1748496 : hi_half[num] = adjust_address (op, half_mode, byte);
153 : }
154 : }
155 : else
156 : {
157 2659268 : lo_half[num] = simplify_gen_subreg (half_mode, op,
158 2659268 : GET_MODE (op) == VOIDmode
159 : ? mode : GET_MODE (op), 0);
160 :
161 2659268 : rtx tmp = simplify_gen_subreg (half_mode, op,
162 2659268 : GET_MODE (op) == VOIDmode
163 2659268 : ? mode : GET_MODE (op), byte);
164 : /* simplify_gen_subreg will return NULL RTX for the
165 : high half of the paradoxical subreg. */
166 2659268 : hi_half[num] = tmp ? tmp : gen_reg_rtx (half_mode);
167 : }
168 : }
169 4195086 : }
170 :
171 : /* Emit the double word assignment DST = { LO, HI }. */
172 :
173 : void
174 102720 : split_double_concat (machine_mode mode, rtx dst, rtx lo, rtx hi)
175 : {
176 102720 : rtx dlo, dhi;
177 102720 : int deleted_move_count = 0;
178 102720 : split_double_mode (mode, &dst, 1, &dlo, &dhi);
179 : /* Constraints ensure that if both lo and hi are MEMs, then
180 : dst has early-clobber and thus addresses of MEMs don't use
181 : dlo/dhi registers. Otherwise if at least one of li and hi are MEMs,
182 : dlo/dhi are registers. */
183 102720 : if (MEM_P (lo)
184 5580 : && rtx_equal_p (dlo, hi)
185 103690 : && reg_overlap_mentioned_p (dhi, lo))
186 : {
187 : /* If dlo is same as hi and lo's address uses dhi register,
188 : code below would first emit_move_insn (dhi, hi)
189 : and then emit_move_insn (dlo, lo). But the former
190 : would invalidate lo's address. Load into dhi first,
191 : then swap. */
192 193 : emit_move_insn (dhi, lo);
193 193 : lo = dhi;
194 : }
195 102527 : else if (MEM_P (hi)
196 9607 : && !MEM_P (lo)
197 6771 : && !rtx_equal_p (dlo, lo)
198 103885 : && reg_overlap_mentioned_p (dlo, hi))
199 : {
200 : /* In this case, code below would first emit_move_insn (dlo, lo)
201 : and then emit_move_insn (dhi, hi). But the former would
202 : invalidate hi's address. */
203 11 : if (rtx_equal_p (dhi, lo))
204 : {
205 : /* We can't load into dhi first, so load into dlo
206 : first and we'll swap. */
207 5 : emit_move_insn (dlo, hi);
208 5 : hi = dlo;
209 : }
210 : else
211 : {
212 : /* Load into dhi first. */
213 6 : emit_move_insn (dhi, hi);
214 6 : hi = dhi;
215 : }
216 : }
217 102720 : if (!rtx_equal_p (dlo, hi))
218 : {
219 88499 : if (!rtx_equal_p (dlo, lo))
220 38717 : emit_move_insn (dlo, lo);
221 : else
222 : deleted_move_count++;
223 88499 : if (!rtx_equal_p (dhi, hi))
224 82354 : emit_move_insn (dhi, hi);
225 : else
226 6145 : deleted_move_count++;
227 : }
228 14221 : else if (!rtx_equal_p (lo, dhi))
229 : {
230 7221 : if (!rtx_equal_p (dhi, hi))
231 7221 : emit_move_insn (dhi, hi);
232 : else
233 : deleted_move_count++;
234 7221 : if (!rtx_equal_p (dlo, lo))
235 7119 : emit_move_insn (dlo, lo);
236 : else
237 102 : deleted_move_count++;
238 : }
239 7000 : else if (mode == TImode)
240 6980 : emit_insn (gen_swapdi (dlo, dhi));
241 : else
242 20 : emit_insn (gen_swapsi (dlo, dhi));
243 :
244 102720 : if (deleted_move_count == 2)
245 3136 : emit_note (NOTE_INSN_DELETED);
246 102720 : }
247 :
248 :
249 : /* Generate either "mov $0, reg" or "xor reg, reg", as appropriate
250 : for the target. */
251 :
252 : void
253 116601 : ix86_expand_clear (rtx dest)
254 : {
255 116601 : rtx tmp;
256 :
257 : /* We play register width games, which are only valid after reload. */
258 116601 : gcc_assert (reload_completed);
259 :
260 : /* Avoid HImode and its attendant prefix byte. */
261 233202 : if (GET_MODE_SIZE (GET_MODE (dest)) < 4)
262 955 : dest = gen_rtx_REG (SImode, REGNO (dest));
263 116601 : tmp = gen_rtx_SET (dest, const0_rtx);
264 :
265 116601 : if (!TARGET_USE_MOV0 || optimize_insn_for_size_p ())
266 : {
267 116601 : rtx clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
268 116601 : tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, tmp, clob));
269 : }
270 :
271 116601 : emit_insn (tmp);
272 116601 : }
273 :
274 : /* Return true if V can be broadcasted from an integer of WIDTH bits
275 : which is returned in VAL_BROADCAST. Otherwise, return false. */
276 :
277 : static bool
278 4851 : ix86_broadcast (HOST_WIDE_INT v, unsigned int width,
279 : HOST_WIDE_INT &val_broadcast)
280 : {
281 4851 : wide_int val = wi::uhwi (v, HOST_BITS_PER_WIDE_INT);
282 4851 : val_broadcast = wi::extract_uhwi (val, 0, width);
283 6543 : for (unsigned int i = width; i < HOST_BITS_PER_WIDE_INT; i += width)
284 : {
285 5089 : HOST_WIDE_INT each = wi::extract_uhwi (val, i, width);
286 5089 : if (val_broadcast != each)
287 : return false;
288 : }
289 1454 : val_broadcast = sext_hwi (val_broadcast, width);
290 1454 : return true;
291 4851 : }
292 :
293 : /* Convert the CONST_WIDE_INT operand OP to broadcast in MODE. */
294 :
295 : rtx
296 36034 : ix86_convert_const_wide_int_to_broadcast (machine_mode mode, rtx op)
297 : {
298 : /* Don't use integer vector broadcast if we can't move from GPR to SSE
299 : register directly. */
300 36034 : if (!TARGET_INTER_UNIT_MOVES_TO_VEC)
301 : return nullptr;
302 :
303 36034 : unsigned int msize = GET_MODE_SIZE (mode);
304 :
305 : /* Only optimized for vpbroadcast[bwsd]/vbroadcastss with xmm/ymm/zmm. */
306 36034 : if (msize != 16 && msize != 32 && msize != 64)
307 : return nullptr;
308 :
309 : /* Convert CONST_WIDE_INT to a non-standard SSE constant integer
310 : broadcast only if vector broadcast is available. */
311 36034 : if (!TARGET_AVX
312 1662 : || !CONST_WIDE_INT_P (op)
313 1603 : || standard_sse_constant_p (op, mode)
314 37637 : || (CONST_WIDE_INT_NUNITS (op) * HOST_BITS_PER_WIDE_INT
315 1603 : != GET_MODE_BITSIZE (mode)))
316 34439 : return nullptr;
317 :
318 1595 : HOST_WIDE_INT val = CONST_WIDE_INT_ELT (op, 0);
319 1595 : HOST_WIDE_INT val_broadcast;
320 1595 : scalar_int_mode broadcast_mode;
321 : /* vpbroadcastb zmm requires TARGET_AVX512BW. */
322 712 : if ((msize == 64 ? TARGET_AVX512BW : TARGET_AVX2)
323 2089 : && ix86_broadcast (val, GET_MODE_BITSIZE (QImode),
324 : val_broadcast))
325 : broadcast_mode = QImode;
326 654 : else if ((msize == 64 ? TARGET_AVX512BW : TARGET_AVX2)
327 1968 : && ix86_broadcast (val, GET_MODE_BITSIZE (HImode),
328 : val_broadcast))
329 : broadcast_mode = HImode;
330 : /* vbroadcasts[sd] only support memory operand w/o AVX2.
331 : When msize == 16, pshufs is used for vec_duplicate.
332 : when msize == 64, vpbroadcastd is used, and TARGET_AVX512F must be existed. */
333 412 : else if ((msize != 32 || TARGET_AVX2)
334 1768 : && ix86_broadcast (val, GET_MODE_BITSIZE (SImode),
335 : val_broadcast))
336 : broadcast_mode = SImode;
337 1391 : else if (TARGET_64BIT && (msize != 32 || TARGET_AVX2)
338 2641 : && ix86_broadcast (val, GET_MODE_BITSIZE (DImode),
339 : val_broadcast))
340 : broadcast_mode = DImode;
341 : else
342 141 : return nullptr;
343 :
344 : /* Check if OP can be broadcasted from VAL. */
345 1776 : for (int i = 1; i < CONST_WIDE_INT_NUNITS (op); i++)
346 1561 : if (val != CONST_WIDE_INT_ELT (op, i))
347 : return nullptr;
348 :
349 215 : unsigned int nunits = (GET_MODE_SIZE (mode)
350 215 : / GET_MODE_SIZE (broadcast_mode));
351 215 : machine_mode vector_mode;
352 215 : if (!mode_for_vector (broadcast_mode, nunits).exists (&vector_mode))
353 0 : gcc_unreachable ();
354 215 : rtx target = gen_reg_rtx (vector_mode);
355 215 : bool ok = ix86_expand_vector_init_duplicate (false, vector_mode,
356 : target,
357 : GEN_INT (val_broadcast));
358 215 : if (!ok)
359 : return nullptr;
360 215 : target = lowpart_subreg (mode, target, vector_mode);
361 215 : return target;
362 : }
363 :
364 : void
365 74359025 : ix86_expand_move (machine_mode mode, rtx operands[])
366 : {
367 74359025 : rtx op0, op1;
368 74359025 : rtx tmp, addend = NULL_RTX;
369 74359025 : enum tls_model model;
370 :
371 74359025 : op0 = operands[0];
372 74359025 : op1 = operands[1];
373 :
374 : /* Avoid complex sets of likely spilled hard registers before reload. */
375 74359025 : if (!ix86_hardreg_mov_ok (op0, op1))
376 : {
377 140352 : tmp = gen_reg_rtx (mode);
378 140352 : operands[0] = tmp;
379 140352 : ix86_expand_move (mode, operands);
380 140352 : operands[0] = op0;
381 140352 : operands[1] = tmp;
382 140352 : op1 = tmp;
383 : }
384 :
385 74359025 : switch (GET_CODE (op1))
386 : {
387 349677 : case CONST:
388 349677 : tmp = XEXP (op1, 0);
389 :
390 349677 : if (GET_CODE (tmp) != PLUS
391 337942 : || !SYMBOL_REF_P (XEXP (tmp, 0)))
392 : break;
393 :
394 335287 : op1 = XEXP (tmp, 0);
395 335287 : addend = XEXP (tmp, 1);
396 : /* FALLTHRU */
397 :
398 5010924 : case SYMBOL_REF:
399 5010924 : model = SYMBOL_REF_TLS_MODEL (op1);
400 :
401 5010924 : if (model)
402 10166 : op1 = legitimize_tls_address (op1, model, true);
403 5000758 : else if (ix86_force_load_from_GOT_p (op1))
404 : {
405 : /* Load the external function address via GOT slot to avoid PLT. */
406 24 : op1 = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op1),
407 : (TARGET_64BIT
408 : ? UNSPEC_GOTPCREL
409 : : UNSPEC_GOT));
410 24 : op1 = gen_rtx_CONST (Pmode, op1);
411 24 : op1 = gen_const_mem (Pmode, op1);
412 20 : set_mem_alias_set (op1, GOT_ALIAS_SET);
413 : }
414 : else
415 : {
416 : #if TARGET_PECOFF
417 : tmp = legitimize_pe_coff_symbol (op1, addend != NULL_RTX);
418 :
419 : if (tmp)
420 : {
421 : op1 = tmp;
422 : if (!addend)
423 : break;
424 : }
425 : else
426 : #endif
427 5000738 : {
428 5000738 : op1 = operands[1];
429 5000738 : break;
430 : }
431 : }
432 :
433 10186 : if (addend)
434 : {
435 2787 : op1 = force_operand (op1, NULL_RTX);
436 2796 : op1 = expand_simple_binop (Pmode, PLUS, op1, addend,
437 : op0, 1, OPTAB_DIRECT);
438 : }
439 : else
440 7399 : op1 = force_operand (op1, op0);
441 :
442 10186 : if (op1 == op0)
443 : return;
444 :
445 1152 : op1 = convert_to_mode (mode, op1, 1);
446 :
447 : default:
448 : break;
449 :
450 1576113 : case SUBREG:
451 : /* Transform TImode paradoxical SUBREG into zero_extendditi2. */
452 1576113 : if (TARGET_64BIT
453 1348319 : && mode == TImode
454 : && SUBREG_P (op1)
455 74977 : && GET_MODE (SUBREG_REG (op1)) == DImode
456 1622646 : && SUBREG_BYTE (op1) == 0)
457 46533 : op1 = gen_rtx_ZERO_EXTEND (TImode, SUBREG_REG (op1));
458 : /* As not all values in XFmode are representable in real_value,
459 : we might be called with unfoldable SUBREGs of constants. */
460 1576113 : if (mode == XFmode
461 3128 : && CONSTANT_P (SUBREG_REG (op1))
462 0 : && can_create_pseudo_p ())
463 : {
464 0 : machine_mode imode = GET_MODE (SUBREG_REG (op1));
465 0 : rtx r = force_const_mem (imode, SUBREG_REG (op1));
466 0 : if (r)
467 0 : r = validize_mem (r);
468 : else
469 0 : r = force_reg (imode, SUBREG_REG (op1));
470 0 : op1 = simplify_gen_subreg (mode, r, imode, SUBREG_BYTE (op1));
471 : }
472 : break;
473 : }
474 :
475 74349991 : if ((flag_pic || MACHOPIC_INDIRECT)
476 74349991 : && symbolic_operand (op1, mode))
477 : {
478 : #if TARGET_MACHO
479 : if (TARGET_MACHO && !TARGET_64BIT)
480 : {
481 : /* dynamic-no-pic */
482 : if (MACHOPIC_INDIRECT)
483 : {
484 : tmp = (op0 && REG_P (op0) && mode == Pmode)
485 : ? op0 : gen_reg_rtx (Pmode);
486 : op1 = machopic_indirect_data_reference (op1, tmp);
487 : if (MACHOPIC_PURE)
488 : op1 = machopic_legitimize_pic_address (op1, mode,
489 : tmp == op1 ? 0 : tmp);
490 : }
491 : if (op0 != op1 && !MEM_P (op0))
492 : {
493 : rtx insn = gen_rtx_SET (op0, op1);
494 : emit_insn (insn);
495 : return;
496 : }
497 : }
498 : #endif
499 :
500 335093 : if (MEM_P (op0))
501 87578 : op1 = force_reg (mode, op1);
502 247515 : else if (!(TARGET_64BIT && x86_64_movabs_operand (op1, DImode)))
503 : {
504 247458 : rtx reg = can_create_pseudo_p () ? NULL_RTX : op0;
505 247458 : op1 = legitimize_pic_address (op1, reg);
506 247458 : if (op0 == op1)
507 : return;
508 247458 : op1 = convert_to_mode (mode, op1, 1);
509 : }
510 : }
511 : else
512 : {
513 74014898 : if (MEM_P (op0)
514 100945291 : && (PUSH_ROUNDING (GET_MODE_SIZE (mode)) != GET_MODE_SIZE (mode)
515 10867464 : || !push_operand (op0, mode))
516 86467710 : && MEM_P (op1))
517 2147023 : op1 = force_reg (mode, op1);
518 :
519 74014898 : if (push_operand (op0, mode)
520 74014898 : && ! general_no_elim_operand (op1, mode))
521 1004 : op1 = copy_to_mode_reg (mode, op1);
522 :
523 : /* Force large constants in 64bit compilation into register
524 : to get them CSEed. */
525 74014898 : if (can_create_pseudo_p ()
526 68273738 : && (mode == DImode) && TARGET_64BIT
527 35827235 : && immediate_operand (op1, mode)
528 8073695 : && !x86_64_zext_immediate_operand (op1, VOIDmode)
529 728409 : && !register_operand (op0, mode)
530 74192574 : && optimize)
531 125654 : op1 = copy_to_mode_reg (mode, op1);
532 :
533 74014898 : if (can_create_pseudo_p ())
534 : {
535 68273738 : if (CONST_DOUBLE_P (op1))
536 : {
537 : /* If we are loading a floating point constant to a
538 : register, force the value to memory now, since we'll
539 : get better code out the back end. */
540 :
541 905050 : op1 = validize_mem (force_const_mem (mode, op1));
542 905050 : if (!register_operand (op0, mode))
543 : {
544 130648 : tmp = gen_reg_rtx (mode);
545 130648 : emit_insn (gen_rtx_SET (tmp, op1));
546 130648 : emit_move_insn (op0, tmp);
547 130648 : return;
548 : }
549 : }
550 : }
551 : }
552 :
553 : /* Special case inserting 64-bit values into a TImode register. */
554 74219343 : if (TARGET_64BIT
555 : /* Disable for -O0 (see PR110587) unless naked (PR110533). */
556 64496151 : && (optimize || ix86_function_naked (current_function_decl))
557 44244984 : && (mode == DImode || mode == DFmode)
558 30283373 : && SUBREG_P (op0)
559 509922 : && GET_MODE (SUBREG_REG (op0)) == TImode
560 411356 : && REG_P (SUBREG_REG (op0))
561 74630699 : && REG_P (op1))
562 : {
563 : /* Use *insvti_lowpart_1 to set lowpart. */
564 182555 : if (SUBREG_BYTE (op0) == 0)
565 : {
566 54769 : wide_int mask = wi::mask (64, true, 128);
567 54769 : tmp = immed_wide_int_const (mask, TImode);
568 54769 : op0 = SUBREG_REG (op0);
569 54769 : tmp = gen_rtx_AND (TImode, copy_rtx (op0), tmp);
570 54769 : if (mode == DFmode)
571 375 : op1 = gen_lowpart (DImode, op1);
572 54769 : op1 = gen_rtx_ZERO_EXTEND (TImode, op1);
573 54769 : op1 = gen_rtx_IOR (TImode, tmp, op1);
574 54769 : }
575 : /* Use *insvti_highpart_1 to set highpart. */
576 127786 : else if (SUBREG_BYTE (op0) == 8)
577 : {
578 127786 : wide_int mask = wi::mask (64, false, 128);
579 127786 : tmp = immed_wide_int_const (mask, TImode);
580 127786 : op0 = SUBREG_REG (op0);
581 127786 : tmp = gen_rtx_AND (TImode, copy_rtx (op0), tmp);
582 127786 : if (mode == DFmode)
583 226 : op1 = gen_lowpart (DImode, op1);
584 127786 : op1 = gen_rtx_ZERO_EXTEND (TImode, op1);
585 127786 : op1 = gen_rtx_ASHIFT (TImode, op1, GEN_INT (64));
586 127786 : op1 = gen_rtx_IOR (TImode, tmp, op1);
587 127786 : }
588 : }
589 :
590 74219343 : emit_insn (gen_rtx_SET (op0, op1));
591 : }
592 :
593 : /* OP is a memref of CONST_VECTOR, return scalar constant mem
594 : if CONST_VECTOR is a vec_duplicate, else return NULL. */
595 : rtx
596 2544587 : ix86_broadcast_from_constant (machine_mode mode, rtx op)
597 : {
598 2544587 : int nunits = GET_MODE_NUNITS (mode);
599 2544587 : if (nunits < 2)
600 : return nullptr;
601 :
602 : /* Don't use integer vector broadcast if we can't move from GPR to SSE
603 : register directly. */
604 2414244 : if (!TARGET_INTER_UNIT_MOVES_TO_VEC
605 8020 : && INTEGRAL_MODE_P (mode))
606 : return nullptr;
607 :
608 : /* Convert CONST_VECTOR to a non-standard SSE constant integer
609 : broadcast only if vector broadcast is available. */
610 2408834 : if (standard_sse_constant_p (op, mode))
611 : return nullptr;
612 :
613 4817662 : if (GET_MODE_INNER (mode) == TImode)
614 : return nullptr;
615 :
616 2408721 : rtx constant = get_pool_constant (XEXP (op, 0));
617 2408721 : if (!CONST_VECTOR_P (constant))
618 : return nullptr;
619 :
620 : /* There could be some rtx like
621 : (mem/u/c:V16QI (symbol_ref/u:DI ("*.LC1")))
622 : but with "*.LC1" refer to V2DI constant vector. */
623 2408721 : if (GET_MODE (constant) != mode)
624 : {
625 779 : constant = simplify_subreg (mode, constant, GET_MODE (constant),
626 : 0);
627 779 : if (constant == nullptr || !CONST_VECTOR_P (constant))
628 : return nullptr;
629 : }
630 :
631 2408721 : rtx first = XVECEXP (constant, 0, 0);
632 :
633 8289903 : for (int i = 1; i < nunits; ++i)
634 : {
635 7637670 : rtx tmp = XVECEXP (constant, 0, i);
636 : /* Vector duplicate value. */
637 7637670 : if (!rtx_equal_p (tmp, first))
638 : return nullptr;
639 : }
640 :
641 : return first;
642 : }
643 :
644 : void
645 4747092 : ix86_expand_vector_move (machine_mode mode, rtx operands[])
646 : {
647 4747092 : rtx op0 = operands[0], op1 = operands[1];
648 : /* Use GET_MODE_BITSIZE instead of GET_MODE_ALIGNMENT for IA MCU
649 : psABI since the biggest alignment is 4 byte for IA MCU psABI. */
650 4747092 : unsigned int align = (TARGET_IAMCU
651 4747092 : ? GET_MODE_BITSIZE (mode)
652 4747092 : : GET_MODE_ALIGNMENT (mode));
653 :
654 4747092 : if (push_operand (op0, VOIDmode))
655 2918 : op0 = emit_move_resolve_push (mode, op0);
656 :
657 : /* Force constants other than zero into memory. We do not know how
658 : the instructions used to build constants modify the upper 64 bits
659 : of the register, once we have that information we may be able
660 : to handle some of them more efficiently. */
661 4747092 : if (can_create_pseudo_p ()
662 4552020 : && (CONSTANT_P (op1)
663 4221433 : || (SUBREG_P (op1)
664 322783 : && CONSTANT_P (SUBREG_REG (op1))))
665 5077693 : && ((register_operand (op0, mode)
666 272581 : && !standard_sse_constant_p (op1, mode))
667 : /* ix86_expand_vector_move_misalign() does not like constants. */
668 : || (SSE_REG_MODE_P (mode)
669 272880 : && MEM_P (op0)
670 42430 : && MEM_ALIGN (op0) < align)))
671 : {
672 4989 : if (SUBREG_P (op1))
673 : {
674 14 : machine_mode imode = GET_MODE (SUBREG_REG (op1));
675 14 : rtx r = force_const_mem (imode, SUBREG_REG (op1));
676 14 : if (r)
677 14 : r = validize_mem (r);
678 : else
679 0 : r = force_reg (imode, SUBREG_REG (op1));
680 14 : op1 = simplify_gen_subreg (mode, r, imode, SUBREG_BYTE (op1));
681 : }
682 : else
683 : {
684 4975 : machine_mode mode = GET_MODE (op0);
685 4975 : rtx tmp = ix86_convert_const_wide_int_to_broadcast
686 4975 : (mode, op1);
687 4975 : if (tmp == nullptr)
688 4954 : op1 = validize_mem (force_const_mem (mode, op1));
689 : else
690 : op1 = tmp;
691 : }
692 : }
693 :
694 4747092 : if (can_create_pseudo_p ()
695 4552020 : && GET_MODE_SIZE (mode) >= 16
696 3818690 : && VECTOR_MODE_P (mode)
697 8350251 : && (MEM_P (op1)
698 749676 : && SYMBOL_REF_P (XEXP (op1, 0))
699 506531 : && CONSTANT_POOL_ADDRESS_P (XEXP (op1, 0))))
700 : {
701 489932 : rtx first = ix86_broadcast_from_constant (mode, op1);
702 489932 : if (first != nullptr)
703 : {
704 : /* Broadcast to XMM/YMM/ZMM register from an integer
705 : constant or scalar mem. */
706 128924 : rtx tmp = gen_reg_rtx (mode);
707 128924 : if (FLOAT_MODE_P (mode))
708 29496 : first = force_const_mem (GET_MODE_INNER (mode), first);
709 128924 : bool ok = ix86_expand_vector_init_duplicate (false, mode,
710 : tmp, first);
711 128924 : if (!ok && !TARGET_64BIT && GET_MODE_INNER (mode) == DImode)
712 : {
713 0 : first = force_const_mem (GET_MODE_INNER (mode), first);
714 0 : ok = ix86_expand_vector_init_duplicate (false, mode,
715 : tmp, first);
716 : }
717 128924 : if (ok)
718 : {
719 128924 : emit_move_insn (op0, tmp);
720 128924 : return;
721 : }
722 : }
723 : }
724 :
725 : /* We need to check memory alignment for SSE mode since attribute
726 : can make operands unaligned. */
727 4618168 : if (can_create_pseudo_p ()
728 : && SSE_REG_MODE_P (mode)
729 9295951 : && ((MEM_P (op0) && (MEM_ALIGN (op0) < align))
730 4153556 : || (MEM_P (op1) && (MEM_ALIGN (op1) < align))))
731 : {
732 326061 : rtx tmp[2];
733 :
734 : /* ix86_expand_vector_move_misalign() does not like both
735 : arguments in memory. */
736 326061 : if (!register_operand (op0, mode)
737 326061 : && !register_operand (op1, mode))
738 : {
739 96405 : rtx scratch = gen_reg_rtx (mode);
740 96405 : emit_move_insn (scratch, op1);
741 96405 : op1 = scratch;
742 : }
743 :
744 326061 : tmp[0] = op0; tmp[1] = op1;
745 326061 : ix86_expand_vector_move_misalign (mode, tmp);
746 326061 : return;
747 : }
748 :
749 : /* Special case TImode to 128-bit vector conversions via V2DI. */
750 1155396 : if (VECTOR_MODE_P (mode)
751 4240662 : && GET_MODE_SIZE (mode) == 16
752 3014735 : && SUBREG_P (op1)
753 254386 : && GET_MODE (SUBREG_REG (op1)) == TImode
754 3325 : && TARGET_64BIT && TARGET_SSE
755 4294778 : && ix86_pre_reload_split ())
756 : {
757 2557 : rtx tmp = gen_reg_rtx (V2DImode);
758 2557 : rtx lo = gen_reg_rtx (DImode);
759 2557 : rtx hi = gen_reg_rtx (DImode);
760 2557 : emit_move_insn (lo, gen_lowpart (DImode, SUBREG_REG (op1)));
761 2557 : emit_move_insn (hi, gen_highpart (DImode, SUBREG_REG (op1)));
762 2557 : emit_insn (gen_vec_concatv2di (tmp, lo, hi));
763 2557 : emit_move_insn (op0, gen_lowpart (mode, tmp));
764 2557 : return;
765 : }
766 :
767 : /* If operand0 is a hard register, make operand1 a pseudo. */
768 4289550 : if (can_create_pseudo_p ()
769 8384028 : && !ix86_hardreg_mov_ok (op0, op1))
770 : {
771 139 : rtx tmp = gen_reg_rtx (GET_MODE (op0));
772 139 : emit_move_insn (tmp, op1);
773 139 : emit_move_insn (op0, tmp);
774 139 : return;
775 : }
776 :
777 : /* Make operand1 a register if it isn't already. */
778 4289411 : if (can_create_pseudo_p ()
779 4094339 : && !register_operand (op0, mode)
780 5432067 : && !register_operand (op1, mode))
781 : {
782 220038 : rtx tmp = gen_reg_rtx (GET_MODE (op0));
783 220038 : emit_move_insn (tmp, op1);
784 220038 : emit_move_insn (op0, tmp);
785 220038 : return;
786 : }
787 :
788 4069373 : emit_insn (gen_rtx_SET (op0, op1));
789 : }
790 :
791 : /* Split 32-byte AVX unaligned load and store if needed. */
792 :
793 : static void
794 12676 : ix86_avx256_split_vector_move_misalign (rtx op0, rtx op1)
795 : {
796 12676 : rtx m;
797 12676 : rtx (*extract) (rtx, rtx, rtx);
798 12676 : machine_mode mode;
799 :
800 12676 : if ((MEM_P (op1) && !TARGET_AVX256_SPLIT_UNALIGNED_LOAD)
801 4630 : || (MEM_P (op0) && !TARGET_AVX256_SPLIT_UNALIGNED_STORE))
802 : {
803 12650 : emit_insn (gen_rtx_SET (op0, op1));
804 12650 : return;
805 : }
806 :
807 26 : rtx orig_op0 = NULL_RTX;
808 26 : mode = GET_MODE (op0);
809 26 : switch (GET_MODE_CLASS (mode))
810 : {
811 9 : case MODE_VECTOR_INT:
812 9 : case MODE_INT:
813 9 : if (mode != V32QImode)
814 : {
815 7 : if (!MEM_P (op0))
816 : {
817 3 : orig_op0 = op0;
818 3 : op0 = gen_reg_rtx (V32QImode);
819 : }
820 : else
821 4 : op0 = gen_lowpart (V32QImode, op0);
822 7 : op1 = gen_lowpart (V32QImode, op1);
823 7 : mode = V32QImode;
824 : }
825 : break;
826 : case MODE_VECTOR_FLOAT:
827 : break;
828 0 : default:
829 0 : gcc_unreachable ();
830 : }
831 :
832 26 : switch (mode)
833 : {
834 0 : default:
835 0 : gcc_unreachable ();
836 : case E_V32QImode:
837 : extract = gen_avx_vextractf128v32qi;
838 : mode = V16QImode;
839 : break;
840 1 : case E_V16BFmode:
841 1 : extract = gen_avx_vextractf128v16bf;
842 1 : mode = V8BFmode;
843 1 : break;
844 0 : case E_V16HFmode:
845 0 : extract = gen_avx_vextractf128v16hf;
846 0 : mode = V8HFmode;
847 0 : break;
848 8 : case E_V8SFmode:
849 8 : extract = gen_avx_vextractf128v8sf;
850 8 : mode = V4SFmode;
851 8 : break;
852 8 : case E_V4DFmode:
853 8 : extract = gen_avx_vextractf128v4df;
854 8 : mode = V2DFmode;
855 8 : break;
856 : }
857 :
858 26 : if (MEM_P (op1))
859 : {
860 9 : rtx r = gen_reg_rtx (mode);
861 9 : m = adjust_address (op1, mode, 0);
862 9 : emit_move_insn (r, m);
863 9 : m = adjust_address (op1, mode, 16);
864 9 : r = gen_rtx_VEC_CONCAT (GET_MODE (op0), r, m);
865 9 : emit_move_insn (op0, r);
866 : }
867 17 : else if (MEM_P (op0))
868 : {
869 17 : m = adjust_address (op0, mode, 0);
870 17 : emit_insn (extract (m, op1, const0_rtx));
871 17 : m = adjust_address (op0, mode, 16);
872 17 : emit_insn (extract (m, copy_rtx (op1), const1_rtx));
873 : }
874 : else
875 0 : gcc_unreachable ();
876 :
877 26 : if (orig_op0)
878 3 : emit_move_insn (orig_op0, gen_lowpart (GET_MODE (orig_op0), op0));
879 : }
880 :
881 : /* Implement the movmisalign patterns for SSE. Non-SSE modes go
882 : straight to ix86_expand_vector_move. */
883 : /* Code generation for scalar reg-reg moves of single and double precision data:
884 : if (x86_sse_partial_reg_dependency == true | x86_sse_split_regs == true)
885 : movaps reg, reg
886 : else
887 : movss reg, reg
888 : if (x86_sse_partial_reg_dependency == true)
889 : movapd reg, reg
890 : else
891 : movsd reg, reg
892 :
893 : Code generation for scalar loads of double precision data:
894 : if (x86_sse_split_regs == true)
895 : movlpd mem, reg (gas syntax)
896 : else
897 : movsd mem, reg
898 :
899 : Code generation for unaligned packed loads of single precision data
900 : (x86_sse_unaligned_move_optimal overrides x86_sse_partial_reg_dependency):
901 : if (x86_sse_unaligned_move_optimal)
902 : movups mem, reg
903 :
904 : if (x86_sse_partial_reg_dependency == true)
905 : {
906 : xorps reg, reg
907 : movlps mem, reg
908 : movhps mem+8, reg
909 : }
910 : else
911 : {
912 : movlps mem, reg
913 : movhps mem+8, reg
914 : }
915 :
916 : Code generation for unaligned packed loads of double precision data
917 : (x86_sse_unaligned_move_optimal overrides x86_sse_split_regs):
918 : if (x86_sse_unaligned_move_optimal)
919 : movupd mem, reg
920 :
921 : if (x86_sse_split_regs == true)
922 : {
923 : movlpd mem, reg
924 : movhpd mem+8, reg
925 : }
926 : else
927 : {
928 : movsd mem, reg
929 : movhpd mem+8, reg
930 : }
931 : */
932 :
933 : void
934 656888 : ix86_expand_vector_move_misalign (machine_mode mode, rtx operands[])
935 : {
936 656888 : rtx op0, op1, m;
937 :
938 656888 : op0 = operands[0];
939 656888 : op1 = operands[1];
940 :
941 : /* Use unaligned load/store for AVX512 or when optimizing for size. */
942 1313776 : if (GET_MODE_SIZE (mode) == 64 || optimize_insn_for_size_p ())
943 : {
944 25056 : emit_insn (gen_rtx_SET (op0, op1));
945 25056 : return;
946 : }
947 :
948 631832 : if (TARGET_AVX)
949 : {
950 61940 : if (GET_MODE_SIZE (mode) == 32)
951 12676 : ix86_avx256_split_vector_move_misalign (op0, op1);
952 : else
953 : /* Always use 128-bit mov<mode>_internal pattern for AVX. */
954 18294 : emit_insn (gen_rtx_SET (op0, op1));
955 30970 : return;
956 : }
957 :
958 600862 : if (TARGET_SSE_UNALIGNED_LOAD_OPTIMAL
959 95 : || TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL)
960 : {
961 600767 : emit_insn (gen_rtx_SET (op0, op1));
962 600767 : return;
963 : }
964 :
965 : /* ??? If we have typed data, then it would appear that using
966 : movdqu is the only way to get unaligned data loaded with
967 : integer type. */
968 95 : if (TARGET_SSE2 && GET_MODE_CLASS (mode) == MODE_VECTOR_INT)
969 : {
970 81 : emit_insn (gen_rtx_SET (op0, op1));
971 81 : return;
972 : }
973 :
974 14 : if (MEM_P (op1))
975 : {
976 6 : if (TARGET_SSE2 && mode == V2DFmode)
977 : {
978 2 : rtx zero;
979 :
980 : /* When SSE registers are split into halves, we can avoid
981 : writing to the top half twice. */
982 2 : if (TARGET_SSE_SPLIT_REGS)
983 : {
984 2 : emit_clobber (op0);
985 2 : zero = op0;
986 : }
987 : else
988 : {
989 : /* ??? Not sure about the best option for the Intel chips.
990 : The following would seem to satisfy; the register is
991 : entirely cleared, breaking the dependency chain. We
992 : then store to the upper half, with a dependency depth
993 : of one. A rumor has it that Intel recommends two movsd
994 : followed by an unpacklpd, but this is unconfirmed. And
995 : given that the dependency depth of the unpacklpd would
996 : still be one, I'm not sure why this would be better. */
997 0 : zero = CONST0_RTX (V2DFmode);
998 : }
999 :
1000 2 : m = adjust_address (op1, DFmode, 0);
1001 2 : emit_insn (gen_sse2_loadlpd (op0, zero, m));
1002 2 : m = adjust_address (op1, DFmode, 8);
1003 2 : emit_insn (gen_sse2_loadhpd (op0, op0, m));
1004 2 : }
1005 : else
1006 : {
1007 4 : rtx t;
1008 :
1009 4 : if (mode != V4SFmode)
1010 0 : t = gen_reg_rtx (V4SFmode);
1011 : else
1012 : t = op0;
1013 :
1014 4 : if (TARGET_SSE_PARTIAL_REG_DEPENDENCY)
1015 2 : emit_move_insn (t, CONST0_RTX (V4SFmode));
1016 : else
1017 2 : emit_clobber (t);
1018 :
1019 4 : m = adjust_address (op1, V2SFmode, 0);
1020 4 : emit_insn (gen_sse_loadlps (t, t, m));
1021 4 : m = adjust_address (op1, V2SFmode, 8);
1022 4 : emit_insn (gen_sse_loadhps (t, t, m));
1023 4 : if (mode != V4SFmode)
1024 0 : emit_move_insn (op0, gen_lowpart (mode, t));
1025 : }
1026 : }
1027 8 : else if (MEM_P (op0))
1028 : {
1029 8 : if (TARGET_SSE2 && mode == V2DFmode)
1030 : {
1031 2 : m = adjust_address (op0, DFmode, 0);
1032 2 : emit_insn (gen_sse2_storelpd (m, op1));
1033 2 : m = adjust_address (op0, DFmode, 8);
1034 2 : emit_insn (gen_sse2_storehpd (m, op1));
1035 : }
1036 : else
1037 : {
1038 6 : if (mode != V4SFmode)
1039 0 : op1 = gen_lowpart (V4SFmode, op1);
1040 :
1041 6 : m = adjust_address (op0, V2SFmode, 0);
1042 6 : emit_insn (gen_sse_storelps (m, op1));
1043 6 : m = adjust_address (op0, V2SFmode, 8);
1044 6 : emit_insn (gen_sse_storehps (m, copy_rtx (op1)));
1045 : }
1046 : }
1047 : else
1048 0 : gcc_unreachable ();
1049 : }
1050 :
1051 : /* Move bits 64:95 to bits 32:63. */
1052 :
1053 : void
1054 850 : ix86_move_vector_high_sse_to_mmx (rtx op)
1055 : {
1056 850 : rtx mask = gen_rtx_PARALLEL (VOIDmode,
1057 : gen_rtvec (4, GEN_INT (0), GEN_INT (2),
1058 : GEN_INT (0), GEN_INT (0)));
1059 850 : rtx dest = lowpart_subreg (V4SImode, op, GET_MODE (op));
1060 850 : op = gen_rtx_VEC_SELECT (V4SImode, dest, mask);
1061 850 : rtx insn = gen_rtx_SET (dest, op);
1062 850 : emit_insn (insn);
1063 850 : }
1064 :
1065 : /* Split MMX pack with signed/unsigned saturation with SSE/SSE2. */
1066 :
1067 : void
1068 760 : ix86_split_mmx_pack (rtx operands[], enum rtx_code code)
1069 : {
1070 760 : rtx op0 = operands[0];
1071 760 : rtx op1 = operands[1];
1072 760 : rtx op2 = operands[2];
1073 760 : rtx src;
1074 :
1075 760 : machine_mode dmode = GET_MODE (op0);
1076 760 : machine_mode smode = GET_MODE (op1);
1077 760 : machine_mode inner_dmode = GET_MODE_INNER (dmode);
1078 760 : machine_mode inner_smode = GET_MODE_INNER (smode);
1079 :
1080 : /* Get the corresponding SSE mode for destination. */
1081 760 : int nunits = 16 / GET_MODE_SIZE (inner_dmode);
1082 1520 : machine_mode sse_dmode = mode_for_vector (GET_MODE_INNER (dmode),
1083 1520 : nunits).require ();
1084 760 : machine_mode sse_half_dmode = mode_for_vector (GET_MODE_INNER (dmode),
1085 1520 : nunits / 2).require ();
1086 :
1087 : /* Get the corresponding SSE mode for source. */
1088 760 : nunits = 16 / GET_MODE_SIZE (inner_smode);
1089 1520 : machine_mode sse_smode = mode_for_vector (GET_MODE_INNER (smode),
1090 1520 : nunits).require ();
1091 :
1092 : /* Generate SSE pack with signed/unsigned saturation. */
1093 760 : rtx dest = lowpart_subreg (sse_dmode, op0, GET_MODE (op0));
1094 760 : op1 = lowpart_subreg (sse_smode, op1, GET_MODE (op1));
1095 760 : op2 = lowpart_subreg (sse_smode, op2, GET_MODE (op2));
1096 :
1097 : /* paskusdw/packuswb does unsigned saturation of a signed source
1098 : which is different from generic us_truncate RTX. */
1099 760 : if (code == US_TRUNCATE)
1100 658 : src = gen_rtx_UNSPEC (sse_dmode,
1101 : gen_rtvec (2, op1, op2),
1102 : UNSPEC_US_TRUNCATE);
1103 : else
1104 : {
1105 102 : op1 = gen_rtx_fmt_e (code, sse_half_dmode, op1);
1106 102 : op2 = gen_rtx_fmt_e (code, sse_half_dmode, op2);
1107 102 : src = gen_rtx_VEC_CONCAT (sse_dmode, op1, op2);
1108 : }
1109 :
1110 760 : emit_move_insn (dest, src);
1111 :
1112 760 : ix86_move_vector_high_sse_to_mmx (op0);
1113 760 : }
1114 :
1115 : /* Split MMX punpcklXX/punpckhXX with SSE punpcklXX. This is also used
1116 : for a full unpack of OPERANDS[1] and OPERANDS[2] into a wider
1117 : OPERANDS[0]. */
1118 :
1119 : void
1120 6161 : ix86_split_mmx_punpck (rtx operands[], bool high_p)
1121 : {
1122 6161 : rtx op0 = operands[0];
1123 6161 : rtx op1 = operands[1];
1124 6161 : rtx op2 = operands[2];
1125 6161 : machine_mode mode = GET_MODE (op1);
1126 6161 : rtx mask;
1127 : /* The corresponding SSE mode. */
1128 6161 : machine_mode sse_mode, double_sse_mode;
1129 :
1130 6161 : switch (mode)
1131 : {
1132 1611 : case E_V8QImode:
1133 1611 : case E_V4QImode:
1134 1611 : case E_V2QImode:
1135 1611 : sse_mode = V16QImode;
1136 1611 : double_sse_mode = V32QImode;
1137 1611 : mask = gen_rtx_PARALLEL (VOIDmode,
1138 : gen_rtvec (16,
1139 : GEN_INT (0), GEN_INT (16),
1140 : GEN_INT (1), GEN_INT (17),
1141 : GEN_INT (2), GEN_INT (18),
1142 : GEN_INT (3), GEN_INT (19),
1143 : GEN_INT (4), GEN_INT (20),
1144 : GEN_INT (5), GEN_INT (21),
1145 : GEN_INT (6), GEN_INT (22),
1146 : GEN_INT (7), GEN_INT (23)));
1147 1611 : break;
1148 :
1149 3251 : case E_V4HImode:
1150 3251 : case E_V2HImode:
1151 3251 : sse_mode = V8HImode;
1152 3251 : double_sse_mode = V16HImode;
1153 3251 : mask = gen_rtx_PARALLEL (VOIDmode,
1154 : gen_rtvec (8,
1155 : GEN_INT (0), GEN_INT (8),
1156 : GEN_INT (1), GEN_INT (9),
1157 : GEN_INT (2), GEN_INT (10),
1158 : GEN_INT (3), GEN_INT (11)));
1159 3251 : break;
1160 :
1161 917 : case E_V2SImode:
1162 917 : sse_mode = V4SImode;
1163 917 : double_sse_mode = V8SImode;
1164 917 : mask = gen_rtx_PARALLEL (VOIDmode,
1165 : gen_rtvec (4,
1166 : GEN_INT (0), GEN_INT (4),
1167 : GEN_INT (1), GEN_INT (5)));
1168 917 : break;
1169 :
1170 382 : case E_V2SFmode:
1171 382 : sse_mode = V4SFmode;
1172 382 : double_sse_mode = V8SFmode;
1173 382 : mask = gen_rtx_PARALLEL (VOIDmode,
1174 : gen_rtvec (4,
1175 : GEN_INT (0), GEN_INT (4),
1176 : GEN_INT (1), GEN_INT (5)));
1177 382 : break;
1178 :
1179 0 : default:
1180 0 : gcc_unreachable ();
1181 : }
1182 :
1183 : /* Generate SSE punpcklXX. */
1184 6161 : rtx dest = lowpart_subreg (sse_mode, op0, GET_MODE (op0));
1185 6161 : op1 = lowpart_subreg (sse_mode, op1, GET_MODE (op1));
1186 6161 : op2 = lowpart_subreg (sse_mode, op2, GET_MODE (op2));
1187 :
1188 6161 : op1 = gen_rtx_VEC_CONCAT (double_sse_mode, op1, op2);
1189 6161 : op2 = gen_rtx_VEC_SELECT (sse_mode, op1, mask);
1190 6161 : rtx insn = gen_rtx_SET (dest, op2);
1191 6161 : emit_insn (insn);
1192 :
1193 : /* Move high bits to low bits. */
1194 6161 : if (high_p)
1195 : {
1196 2403 : if (sse_mode == V4SFmode)
1197 : {
1198 104 : mask = gen_rtx_PARALLEL (VOIDmode,
1199 : gen_rtvec (4, GEN_INT (2), GEN_INT (3),
1200 : GEN_INT (4), GEN_INT (5)));
1201 104 : op2 = gen_rtx_VEC_CONCAT (V8SFmode, dest, dest);
1202 104 : op1 = gen_rtx_VEC_SELECT (V4SFmode, op2, mask);
1203 : }
1204 : else
1205 : {
1206 2299 : int sz = GET_MODE_SIZE (mode);
1207 :
1208 2299 : if (sz == 4)
1209 239 : mask = gen_rtx_PARALLEL (VOIDmode,
1210 : gen_rtvec (4, GEN_INT (1), GEN_INT (0),
1211 : GEN_INT (0), GEN_INT (1)));
1212 2060 : else if (sz == 8)
1213 2060 : mask = gen_rtx_PARALLEL (VOIDmode,
1214 : gen_rtvec (4, GEN_INT (2), GEN_INT (3),
1215 : GEN_INT (0), GEN_INT (1)));
1216 : else
1217 0 : gcc_unreachable ();
1218 :
1219 2299 : dest = lowpart_subreg (V4SImode, dest, GET_MODE (dest));
1220 2299 : op1 = gen_rtx_VEC_SELECT (V4SImode, dest, mask);
1221 : }
1222 :
1223 2403 : insn = gen_rtx_SET (dest, op1);
1224 2403 : emit_insn (insn);
1225 : }
1226 6161 : }
1227 :
1228 : /* Helper function of ix86_fixup_binary_operands to canonicalize
1229 : operand order. Returns true if the operands should be swapped. */
1230 :
1231 : static bool
1232 177274903 : ix86_swap_binary_operands_p (enum rtx_code code, machine_mode mode,
1233 : rtx operands[])
1234 : {
1235 177274903 : rtx dst = operands[0];
1236 177274903 : rtx src1 = operands[1];
1237 177274903 : rtx src2 = operands[2];
1238 :
1239 : /* If the operation is not commutative, we can't do anything. */
1240 177274903 : if (GET_RTX_CLASS (code) != RTX_COMM_ARITH
1241 28058664 : && GET_RTX_CLASS (code) != RTX_COMM_COMPARE)
1242 : return false;
1243 :
1244 : /* Highest priority is that src1 should match dst. */
1245 149228859 : if (rtx_equal_p (dst, src1))
1246 : return false;
1247 108839604 : if (rtx_equal_p (dst, src2))
1248 : return true;
1249 :
1250 : /* Next highest priority is that immediate constants come second. */
1251 108752770 : if (immediate_operand (src2, mode))
1252 : return false;
1253 26249066 : if (immediate_operand (src1, mode))
1254 : return true;
1255 :
1256 : /* Lowest priority is that memory references should come second. */
1257 26249066 : if (MEM_P (src2))
1258 : return false;
1259 24785977 : if (MEM_P (src1))
1260 : return true;
1261 :
1262 : return false;
1263 : }
1264 :
1265 : /* Fix up OPERANDS to satisfy ix86_binary_operator_ok. Return the
1266 : destination to use for the operation. If different from the true
1267 : destination in operands[0], a copy operation will be required except
1268 : under TARGET_APX_NDD. */
1269 :
1270 : rtx
1271 13648075 : ix86_fixup_binary_operands (enum rtx_code code, machine_mode mode,
1272 : rtx operands[], bool use_ndd)
1273 : {
1274 13648075 : rtx dst = operands[0];
1275 13648075 : rtx src1 = operands[1];
1276 13648075 : rtx src2 = operands[2];
1277 :
1278 : /* Canonicalize operand order. */
1279 13648075 : if (ix86_swap_binary_operands_p (code, mode, operands))
1280 : {
1281 : /* It is invalid to swap operands of different modes. */
1282 89183 : gcc_assert (GET_MODE (src1) == GET_MODE (src2));
1283 :
1284 : std::swap (src1, src2);
1285 : }
1286 :
1287 : /* Both source operands cannot be in memory. */
1288 13648075 : if (MEM_P (src1) && MEM_P (src2))
1289 : {
1290 : /* Optimization: Only read from memory once. */
1291 113640 : if (rtx_equal_p (src1, src2))
1292 : {
1293 17 : src2 = force_reg (mode, src2);
1294 17 : src1 = src2;
1295 : }
1296 113623 : else if (rtx_equal_p (dst, src1))
1297 3464 : src2 = force_reg (mode, src2);
1298 : else
1299 110159 : src1 = force_reg (mode, src1);
1300 : }
1301 :
1302 : /* If the destination is memory, and we do not have matching source
1303 : operands, do things in registers. */
1304 13648075 : if (MEM_P (dst) && !rtx_equal_p (dst, src1))
1305 492162 : dst = gen_reg_rtx (mode);
1306 :
1307 : /* Source 1 cannot be a constant. */
1308 13648075 : if (CONSTANT_P (src1))
1309 716 : src1 = force_reg (mode, src1);
1310 :
1311 : /* Source 1 cannot be a non-matching memory. */
1312 13648075 : if (!use_ndd && MEM_P (src1) && !rtx_equal_p (dst, src1))
1313 449418 : src1 = force_reg (mode, src1);
1314 :
1315 : /* Improve address combine. */
1316 13648075 : if (code == PLUS
1317 10023522 : && GET_MODE_CLASS (mode) == MODE_INT
1318 9911062 : && MEM_P (src2))
1319 179657 : src2 = force_reg (mode, src2);
1320 :
1321 13648075 : operands[1] = src1;
1322 13648075 : operands[2] = src2;
1323 13648075 : return dst;
1324 : }
1325 :
1326 : /* Similarly, but assume that the destination has already been
1327 : set up properly. */
1328 :
1329 : void
1330 298384 : ix86_fixup_binary_operands_no_copy (enum rtx_code code,
1331 : machine_mode mode, rtx operands[],
1332 : bool use_ndd)
1333 : {
1334 298384 : rtx dst = ix86_fixup_binary_operands (code, mode, operands, use_ndd);
1335 298384 : gcc_assert (dst == operands[0]);
1336 298384 : }
1337 :
1338 : /* Attempt to expand a binary operator. Make the expansion closer to the
1339 : actual machine, then just general_operand, which will allow 3 separate
1340 : memory references (one output, two input) in a single insn. */
1341 :
1342 : void
1343 13349562 : ix86_expand_binary_operator (enum rtx_code code, machine_mode mode,
1344 : rtx operands[], bool use_ndd)
1345 : {
1346 13349562 : rtx src1, src2, dst, op, clob;
1347 :
1348 13349562 : dst = ix86_fixup_binary_operands (code, mode, operands, use_ndd);
1349 13349562 : src1 = operands[1];
1350 13349562 : src2 = operands[2];
1351 :
1352 : /* Emit the instruction. */
1353 :
1354 13349562 : op = gen_rtx_SET (dst, gen_rtx_fmt_ee (code, mode, src1, src2));
1355 :
1356 13349562 : if (reload_completed
1357 82340 : && code == PLUS
1358 908 : && !rtx_equal_p (dst, src1)
1359 13349562 : && !use_ndd)
1360 : {
1361 : /* This is going to be an LEA; avoid splitting it later. */
1362 0 : emit_insn (op);
1363 : }
1364 : else
1365 : {
1366 13349562 : clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
1367 13349562 : emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, op, clob)));
1368 : }
1369 :
1370 : /* Fix up the destination if needed. */
1371 13349562 : if (dst != operands[0])
1372 492153 : emit_move_insn (operands[0], dst);
1373 13349562 : }
1374 :
1375 : /* Expand vector logical operation CODE (AND, IOR, XOR) in MODE with
1376 : the given OPERANDS. */
1377 :
1378 : void
1379 85278 : ix86_expand_vector_logical_operator (enum rtx_code code, machine_mode mode,
1380 : rtx operands[])
1381 : {
1382 85278 : rtx op1 = NULL_RTX, op2 = NULL_RTX;
1383 85278 : if (SUBREG_P (operands[1]))
1384 : {
1385 372 : op1 = operands[1];
1386 372 : op2 = operands[2];
1387 : }
1388 84906 : else if (SUBREG_P (operands[2]))
1389 : {
1390 : op1 = operands[2];
1391 : op2 = operands[1];
1392 : }
1393 : /* Optimize (__m128i) d | (__m128i) e and similar code
1394 : when d and e are float vectors into float vector logical
1395 : insn. In C/C++ without using intrinsics there is no other way
1396 : to express vector logical operation on float vectors than
1397 : to cast them temporarily to integer vectors. */
1398 3332 : if (op1
1399 3332 : && !TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL
1400 3332 : && (SUBREG_P (op2) || CONST_VECTOR_P (op2))
1401 358 : && GET_MODE_CLASS (GET_MODE (SUBREG_REG (op1))) == MODE_VECTOR_FLOAT
1402 453 : && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op1))) == GET_MODE_SIZE (mode)
1403 151 : && SUBREG_BYTE (op1) == 0
1404 151 : && (CONST_VECTOR_P (op2)
1405 1 : || (GET_MODE (SUBREG_REG (op1)) == GET_MODE (SUBREG_REG (op2))
1406 1 : && SUBREG_BYTE (op2) == 0))
1407 151 : && can_create_pseudo_p ())
1408 : {
1409 151 : rtx dst;
1410 151 : switch (GET_MODE (SUBREG_REG (op1)))
1411 : {
1412 67 : case E_V4SFmode:
1413 67 : case E_V8SFmode:
1414 67 : case E_V16SFmode:
1415 67 : case E_V2DFmode:
1416 67 : case E_V4DFmode:
1417 67 : case E_V8DFmode:
1418 67 : dst = gen_reg_rtx (GET_MODE (SUBREG_REG (op1)));
1419 67 : if (CONST_VECTOR_P (op2))
1420 : {
1421 66 : op2 = gen_lowpart (GET_MODE (dst), op2);
1422 66 : op2 = force_reg (GET_MODE (dst), op2);
1423 : }
1424 : else
1425 : {
1426 1 : op1 = operands[1];
1427 1 : op2 = SUBREG_REG (operands[2]);
1428 1 : if (!vector_operand (op2, GET_MODE (dst)))
1429 0 : op2 = force_reg (GET_MODE (dst), op2);
1430 : }
1431 67 : op1 = SUBREG_REG (op1);
1432 67 : if (!vector_operand (op1, GET_MODE (dst)))
1433 0 : op1 = force_reg (GET_MODE (dst), op1);
1434 67 : emit_insn (gen_rtx_SET (dst,
1435 : gen_rtx_fmt_ee (code, GET_MODE (dst),
1436 : op1, op2)));
1437 67 : emit_move_insn (operands[0], gen_lowpart (mode, dst));
1438 67 : return;
1439 : default:
1440 : break;
1441 : }
1442 : }
1443 85211 : if (!vector_operand (operands[1], mode))
1444 1 : operands[1] = force_reg (mode, operands[1]);
1445 85211 : if (!vector_operand (operands[2], mode))
1446 12885 : operands[2] = force_reg (mode, operands[2]);
1447 85211 : ix86_fixup_binary_operands_no_copy (code, mode, operands);
1448 85211 : emit_insn (gen_rtx_SET (operands[0],
1449 : gen_rtx_fmt_ee (code, mode, operands[1],
1450 : operands[2])));
1451 : }
1452 :
1453 : /* Return TRUE or FALSE depending on whether the binary operator meets the
1454 : appropriate constraints. */
1455 :
1456 : bool
1457 164676046 : ix86_binary_operator_ok (enum rtx_code code, machine_mode mode,
1458 : rtx operands[3], bool use_ndd)
1459 : {
1460 164676046 : rtx dst = operands[0];
1461 164676046 : rtx src1 = operands[1];
1462 164676046 : rtx src2 = operands[2];
1463 :
1464 : /* Both source operands cannot be in memory. */
1465 157203646 : if ((MEM_P (src1) || bcst_mem_operand (src1, mode))
1466 164676435 : && (MEM_P (src2) || bcst_mem_operand (src2, mode)))
1467 1049218 : return false;
1468 :
1469 : /* Canonicalize operand order for commutative operators. */
1470 163626828 : if (ix86_swap_binary_operands_p (code, mode, operands))
1471 549884 : std::swap (src1, src2);
1472 :
1473 : /* If the destination is memory, we must have a matching source operand. */
1474 163626828 : if (MEM_P (dst) && !rtx_equal_p (dst, src1))
1475 : return false;
1476 :
1477 : /* Source 1 cannot be a constant. */
1478 158490410 : if (CONSTANT_P (src1))
1479 : return false;
1480 :
1481 : /* Source 1 cannot be a non-matching memory. */
1482 158487361 : if (!use_ndd && MEM_P (src1) && !rtx_equal_p (dst, src1))
1483 : /* Support "andhi/andsi/anddi" as a zero-extending move. */
1484 4582654 : return (code == AND
1485 532248 : && (mode == HImode
1486 532248 : || mode == SImode
1487 321201 : || (TARGET_64BIT && mode == DImode))
1488 4890530 : && satisfies_constraint_L (src2));
1489 :
1490 : return true;
1491 : }
1492 :
1493 : /* Attempt to expand a unary operator. Make the expansion closer to the
1494 : actual machine, then just general_operand, which will allow 2 separate
1495 : memory references (one output, one input) in a single insn. */
1496 :
1497 : void
1498 131916 : ix86_expand_unary_operator (enum rtx_code code, machine_mode mode,
1499 : rtx operands[], bool use_ndd)
1500 : {
1501 131916 : bool matching_memory = false;
1502 131916 : rtx src, dst, op, clob;
1503 :
1504 131916 : dst = operands[0];
1505 131916 : src = operands[1];
1506 :
1507 : /* If the destination is memory, and we do not have matching source
1508 : operands, do things in registers. */
1509 131916 : if (MEM_P (dst))
1510 : {
1511 11495 : if (rtx_equal_p (dst, src))
1512 : matching_memory = true;
1513 : else
1514 11179 : dst = gen_reg_rtx (mode);
1515 : }
1516 :
1517 : /* When source operand is memory, destination must match. */
1518 131916 : if (!use_ndd && MEM_P (src) && !matching_memory)
1519 4595 : src = force_reg (mode, src);
1520 :
1521 : /* Emit the instruction. */
1522 :
1523 131916 : op = gen_rtx_SET (dst, gen_rtx_fmt_e (code, mode, src));
1524 :
1525 131916 : if (code == NOT)
1526 71469 : emit_insn (op);
1527 : else
1528 : {
1529 60447 : clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
1530 60447 : emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, op, clob)));
1531 : }
1532 :
1533 : /* Fix up the destination if needed. */
1534 131916 : if (dst != operands[0])
1535 11179 : emit_move_insn (operands[0], dst);
1536 131916 : }
1537 :
1538 : /* Return TRUE or FALSE depending on whether the unary operator meets the
1539 : appropriate constraints. */
1540 :
1541 : bool
1542 2070870 : ix86_unary_operator_ok (enum rtx_code,
1543 : machine_mode,
1544 : rtx operands[2],
1545 : bool use_ndd)
1546 : {
1547 : /* If one of operands is memory, source and destination must match. */
1548 2070870 : if ((MEM_P (operands[0])
1549 1935507 : || (!use_ndd && MEM_P (operands[1])))
1550 2099989 : && ! rtx_equal_p (operands[0], operands[1]))
1551 : return false;
1552 : return true;
1553 : }
1554 :
1555 : /* Predict just emitted jump instruction to be taken with probability PROB. */
1556 :
1557 : static void
1558 13105 : predict_jump (int prob)
1559 : {
1560 13105 : rtx_insn *insn = get_last_insn ();
1561 13105 : gcc_assert (JUMP_P (insn));
1562 13105 : add_reg_br_prob_note (insn, profile_probability::from_reg_br_prob_base (prob));
1563 13105 : }
1564 :
1565 : /* Split 32bit/64bit divmod with 8bit unsigned divmod if dividend and
1566 : divisor are within the range [0-255]. */
1567 :
1568 : void
1569 27 : ix86_split_idivmod (machine_mode mode, rtx operands[],
1570 : bool unsigned_p)
1571 : {
1572 27 : rtx_code_label *end_label, *qimode_label;
1573 27 : rtx div, mod;
1574 27 : rtx_insn *insn;
1575 27 : rtx scratch, tmp0, tmp1, tmp2;
1576 27 : rtx (*gen_divmod4_1) (rtx, rtx, rtx, rtx);
1577 :
1578 27 : operands[2] = force_reg (mode, operands[2]);
1579 27 : operands[3] = force_reg (mode, operands[3]);
1580 :
1581 27 : switch (mode)
1582 : {
1583 20 : case E_SImode:
1584 20 : if (GET_MODE (operands[0]) == SImode)
1585 : {
1586 16 : if (GET_MODE (operands[1]) == SImode)
1587 14 : gen_divmod4_1 = unsigned_p ? gen_udivmodsi4_1 : gen_divmodsi4_1;
1588 : else
1589 2 : gen_divmod4_1
1590 2 : = unsigned_p ? gen_udivmodsi4_zext_2 : gen_divmodsi4_zext_2;
1591 : }
1592 : else
1593 4 : gen_divmod4_1
1594 4 : = unsigned_p ? gen_udivmodsi4_zext_1 : gen_divmodsi4_zext_1;
1595 : break;
1596 :
1597 7 : case E_DImode:
1598 7 : gen_divmod4_1 = unsigned_p ? gen_udivmoddi4_1 : gen_divmoddi4_1;
1599 : break;
1600 :
1601 0 : default:
1602 0 : gcc_unreachable ();
1603 : }
1604 :
1605 27 : end_label = gen_label_rtx ();
1606 27 : qimode_label = gen_label_rtx ();
1607 :
1608 27 : scratch = gen_reg_rtx (mode);
1609 :
1610 : /* Use 8bit unsigned divimod if dividend and divisor are within
1611 : the range [0-255]. */
1612 27 : emit_move_insn (scratch, operands[2]);
1613 27 : scratch = expand_simple_binop (mode, IOR, scratch, operands[3],
1614 : scratch, 1, OPTAB_DIRECT);
1615 27 : emit_insn (gen_test_ccno_1 (mode, scratch, GEN_INT (-0x100)));
1616 27 : tmp0 = gen_rtx_REG (CCNOmode, FLAGS_REG);
1617 27 : tmp0 = gen_rtx_EQ (VOIDmode, tmp0, const0_rtx);
1618 27 : tmp0 = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp0,
1619 : gen_rtx_LABEL_REF (VOIDmode, qimode_label),
1620 : pc_rtx);
1621 27 : insn = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp0));
1622 27 : predict_jump (REG_BR_PROB_BASE * 50 / 100);
1623 27 : JUMP_LABEL (insn) = qimode_label;
1624 :
1625 : /* Generate original signed/unsigned divimod. */
1626 27 : emit_insn (gen_divmod4_1 (operands[0], operands[1],
1627 : operands[2], operands[3]));
1628 :
1629 : /* Branch to the end. */
1630 27 : emit_jump_insn (gen_jump (end_label));
1631 27 : emit_barrier ();
1632 :
1633 : /* Generate 8bit unsigned divide. */
1634 27 : emit_label (qimode_label);
1635 : /* Don't use operands[0] for result of 8bit divide since not all
1636 : registers support QImode ZERO_EXTRACT. */
1637 27 : tmp0 = lowpart_subreg (HImode, scratch, mode);
1638 27 : tmp1 = lowpart_subreg (HImode, operands[2], mode);
1639 27 : tmp2 = lowpart_subreg (QImode, operands[3], mode);
1640 27 : emit_insn (gen_udivmodhiqi3 (tmp0, tmp1, tmp2));
1641 :
1642 27 : if (unsigned_p)
1643 : {
1644 12 : div = gen_rtx_UDIV (mode, operands[2], operands[3]);
1645 12 : mod = gen_rtx_UMOD (mode, operands[2], operands[3]);
1646 : }
1647 : else
1648 : {
1649 15 : div = gen_rtx_DIV (mode, operands[2], operands[3]);
1650 15 : mod = gen_rtx_MOD (mode, operands[2], operands[3]);
1651 : }
1652 27 : if (mode == SImode)
1653 : {
1654 20 : if (GET_MODE (operands[0]) != SImode)
1655 4 : div = gen_rtx_ZERO_EXTEND (DImode, div);
1656 20 : if (GET_MODE (operands[1]) != SImode)
1657 2 : mod = gen_rtx_ZERO_EXTEND (DImode, mod);
1658 : }
1659 :
1660 : /* Extract remainder from AH. */
1661 27 : scratch = gen_lowpart (GET_MODE (operands[1]), scratch);
1662 27 : tmp1 = gen_rtx_ZERO_EXTRACT (GET_MODE (operands[1]), scratch,
1663 : GEN_INT (8), GEN_INT (8));
1664 27 : insn = emit_move_insn (operands[1], tmp1);
1665 27 : set_unique_reg_note (insn, REG_EQUAL, mod);
1666 :
1667 : /* Zero extend quotient from AL. */
1668 27 : tmp1 = gen_lowpart (QImode, tmp0);
1669 27 : insn = emit_insn (gen_extend_insn
1670 27 : (operands[0], tmp1,
1671 27 : GET_MODE (operands[0]), QImode, 1));
1672 27 : set_unique_reg_note (insn, REG_EQUAL, div);
1673 :
1674 27 : emit_label (end_label);
1675 27 : }
1676 :
1677 : /* Emit x86 binary operand CODE in mode MODE, where the first operand
1678 : matches destination. RTX includes clobber of FLAGS_REG. */
1679 :
1680 : void
1681 7768 : ix86_emit_binop (enum rtx_code code, machine_mode mode,
1682 : rtx dst, rtx src)
1683 : {
1684 7768 : rtx op, clob;
1685 :
1686 7768 : op = gen_rtx_SET (dst, gen_rtx_fmt_ee (code, mode, dst, src));
1687 7768 : clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
1688 :
1689 7768 : emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, op, clob)));
1690 7768 : }
1691 :
1692 : /* Return true if regno1 def is nearest to the insn. */
1693 :
1694 : static bool
1695 15 : find_nearest_reg_def (rtx_insn *insn, int regno1, int regno2)
1696 : {
1697 15 : rtx_insn *prev = insn;
1698 15 : rtx_insn *start = BB_HEAD (BLOCK_FOR_INSN (insn));
1699 :
1700 15 : if (insn == start)
1701 : return false;
1702 40 : while (prev && prev != start)
1703 : {
1704 30 : if (!INSN_P (prev) || !NONDEBUG_INSN_P (prev))
1705 : {
1706 10 : prev = PREV_INSN (prev);
1707 10 : continue;
1708 : }
1709 20 : if (insn_defines_reg (regno1, INVALID_REGNUM, prev))
1710 : return true;
1711 15 : else if (insn_defines_reg (regno2, INVALID_REGNUM, prev))
1712 : return false;
1713 15 : prev = PREV_INSN (prev);
1714 : }
1715 :
1716 : /* None of the regs is defined in the bb. */
1717 : return false;
1718 : }
1719 :
1720 : /* INSN_UID of the last insn emitted by zero store peephole2s. */
1721 : int ix86_last_zero_store_uid;
1722 :
1723 : /* Split lea instructions into a sequence of instructions
1724 : which are executed on ALU to avoid AGU stalls.
1725 : It is assumed that it is allowed to clobber flags register
1726 : at lea position. */
1727 :
1728 : void
1729 5944 : ix86_split_lea_for_addr (rtx_insn *insn, rtx operands[], machine_mode mode)
1730 : {
1731 5944 : unsigned int regno0, regno1, regno2;
1732 5944 : struct ix86_address parts;
1733 5944 : rtx target, tmp;
1734 5944 : int ok, adds;
1735 :
1736 5944 : ok = ix86_decompose_address (operands[1], &parts);
1737 5944 : gcc_assert (ok);
1738 :
1739 5944 : target = gen_lowpart (mode, operands[0]);
1740 :
1741 5944 : regno0 = true_regnum (target);
1742 5944 : regno1 = INVALID_REGNUM;
1743 5944 : regno2 = INVALID_REGNUM;
1744 :
1745 5944 : if (parts.base)
1746 : {
1747 5936 : parts.base = gen_lowpart (mode, parts.base);
1748 5936 : regno1 = true_regnum (parts.base);
1749 : }
1750 :
1751 5944 : if (parts.index)
1752 : {
1753 5940 : parts.index = gen_lowpart (mode, parts.index);
1754 5940 : regno2 = true_regnum (parts.index);
1755 : }
1756 :
1757 5944 : if (parts.disp)
1758 217 : parts.disp = gen_lowpart (mode, parts.disp);
1759 :
1760 5944 : if (parts.scale > 1)
1761 : {
1762 : /* Case r1 = r1 + ... */
1763 11 : if (regno1 == regno0)
1764 : {
1765 : /* If we have a case r1 = r1 + C * r2 then we
1766 : should use multiplication which is very
1767 : expensive. Assume cost model is wrong if we
1768 : have such case here. */
1769 0 : gcc_assert (regno2 != regno0);
1770 :
1771 0 : for (adds = parts.scale; adds > 0; adds--)
1772 0 : ix86_emit_binop (PLUS, mode, target, parts.index);
1773 : }
1774 : else
1775 : {
1776 : /* r1 = r2 + r3 * C case. Need to move r3 into r1. */
1777 11 : if (regno0 != regno2)
1778 8 : emit_insn (gen_rtx_SET (target, parts.index));
1779 :
1780 : /* Use shift for scaling, but emit it as MULT instead
1781 : to avoid it being immediately peephole2 optimized back
1782 : into lea. */
1783 11 : ix86_emit_binop (MULT, mode, target, GEN_INT (parts.scale));
1784 :
1785 11 : if (parts.base)
1786 3 : ix86_emit_binop (PLUS, mode, target, parts.base);
1787 :
1788 11 : if (parts.disp && parts.disp != const0_rtx)
1789 2 : ix86_emit_binop (PLUS, mode, target, parts.disp);
1790 : }
1791 : }
1792 5933 : else if (!parts.base && !parts.index)
1793 : {
1794 0 : gcc_assert(parts.disp);
1795 0 : emit_insn (gen_rtx_SET (target, parts.disp));
1796 : }
1797 : else
1798 : {
1799 5933 : if (!parts.base)
1800 : {
1801 0 : if (regno0 != regno2)
1802 0 : emit_insn (gen_rtx_SET (target, parts.index));
1803 : }
1804 5933 : else if (!parts.index)
1805 : {
1806 4 : if (regno0 != regno1)
1807 2 : emit_insn (gen_rtx_SET (target, parts.base));
1808 : }
1809 : else
1810 : {
1811 5929 : if (regno0 == regno1)
1812 : tmp = parts.index;
1813 2900 : else if (regno0 == regno2)
1814 : tmp = parts.base;
1815 : else
1816 : {
1817 15 : rtx tmp1;
1818 :
1819 : /* Find better operand for SET instruction, depending
1820 : on which definition is farther from the insn. */
1821 15 : if (find_nearest_reg_def (insn, regno1, regno2))
1822 5 : tmp = parts.index, tmp1 = parts.base;
1823 : else
1824 10 : tmp = parts.base, tmp1 = parts.index;
1825 :
1826 15 : emit_insn (gen_rtx_SET (target, tmp));
1827 :
1828 15 : if (parts.disp && parts.disp != const0_rtx)
1829 0 : ix86_emit_binop (PLUS, mode, target, parts.disp);
1830 :
1831 15 : ix86_emit_binop (PLUS, mode, target, tmp1);
1832 15 : return;
1833 : }
1834 :
1835 5914 : ix86_emit_binop (PLUS, mode, target, tmp);
1836 : }
1837 :
1838 5918 : if (parts.disp && parts.disp != const0_rtx)
1839 5 : ix86_emit_binop (PLUS, mode, target, parts.disp);
1840 : }
1841 : }
1842 :
1843 : /* Post-reload splitter for converting an SF or DFmode value in an
1844 : SSE register into an unsigned SImode. */
1845 :
1846 : void
1847 0 : ix86_split_convert_uns_si_sse (rtx operands[])
1848 : {
1849 0 : machine_mode vecmode;
1850 0 : rtx value, large, zero_or_two31, input, two31, x;
1851 :
1852 0 : large = operands[1];
1853 0 : zero_or_two31 = operands[2];
1854 0 : input = operands[3];
1855 0 : two31 = operands[4];
1856 0 : vecmode = GET_MODE (large);
1857 0 : value = gen_rtx_REG (vecmode, REGNO (operands[0]));
1858 :
1859 : /* Load up the value into the low element. We must ensure that the other
1860 : elements are valid floats -- zero is the easiest such value. */
1861 0 : if (MEM_P (input))
1862 : {
1863 0 : if (vecmode == V4SFmode)
1864 0 : emit_insn (gen_vec_setv4sf_0 (value, CONST0_RTX (V4SFmode), input));
1865 : else
1866 0 : emit_insn (gen_sse2_loadlpd (value, CONST0_RTX (V2DFmode), input));
1867 : }
1868 : else
1869 : {
1870 0 : input = gen_rtx_REG (vecmode, REGNO (input));
1871 0 : emit_move_insn (value, CONST0_RTX (vecmode));
1872 0 : if (vecmode == V4SFmode)
1873 0 : emit_insn (gen_sse_movss_v4sf (value, value, input));
1874 : else
1875 0 : emit_insn (gen_sse2_movsd_v2df (value, value, input));
1876 : }
1877 :
1878 0 : emit_move_insn (large, two31);
1879 0 : emit_move_insn (zero_or_two31, MEM_P (two31) ? large : two31);
1880 :
1881 0 : x = gen_rtx_fmt_ee (LE, vecmode, large, value);
1882 0 : emit_insn (gen_rtx_SET (large, x));
1883 :
1884 0 : x = gen_rtx_AND (vecmode, zero_or_two31, large);
1885 0 : emit_insn (gen_rtx_SET (zero_or_two31, x));
1886 :
1887 0 : x = gen_rtx_MINUS (vecmode, value, zero_or_two31);
1888 0 : emit_insn (gen_rtx_SET (value, x));
1889 :
1890 0 : large = gen_rtx_REG (V4SImode, REGNO (large));
1891 0 : emit_insn (gen_ashlv4si3 (large, large, GEN_INT (31)));
1892 :
1893 0 : x = gen_rtx_REG (V4SImode, REGNO (value));
1894 0 : if (vecmode == V4SFmode)
1895 0 : emit_insn (gen_fix_truncv4sfv4si2 (x, value));
1896 : else
1897 0 : emit_insn (gen_sse2_cvttpd2dq (x, value));
1898 0 : value = x;
1899 :
1900 0 : emit_insn (gen_xorv4si3 (value, value, large));
1901 0 : }
1902 :
1903 : /* Convert an unsigned DImode value into a DFmode, using only SSE.
1904 : Expects the 64-bit DImode to be supplied in a pair of integral
1905 : registers. Requires SSE2; will use SSE3 if available. For x86_32,
1906 : -mfpmath=sse, !optimize_size only. */
1907 :
1908 : void
1909 0 : ix86_expand_convert_uns_didf_sse (rtx target, rtx input)
1910 : {
1911 0 : REAL_VALUE_TYPE bias_lo_rvt, bias_hi_rvt;
1912 0 : rtx int_xmm, fp_xmm;
1913 0 : rtx biases, exponents;
1914 0 : rtx x;
1915 :
1916 0 : int_xmm = gen_reg_rtx (V4SImode);
1917 0 : if (TARGET_INTER_UNIT_MOVES_TO_VEC)
1918 0 : emit_insn (gen_movdi_to_sse (int_xmm, input));
1919 0 : else if (TARGET_SSE_SPLIT_REGS)
1920 : {
1921 0 : emit_clobber (int_xmm);
1922 0 : emit_move_insn (gen_lowpart (DImode, int_xmm), input);
1923 : }
1924 : else
1925 : {
1926 0 : x = gen_reg_rtx (V2DImode);
1927 0 : ix86_expand_vector_init_one_nonzero (false, V2DImode, x, input, 0);
1928 0 : emit_move_insn (int_xmm, gen_lowpart (V4SImode, x));
1929 : }
1930 :
1931 0 : x = gen_rtx_CONST_VECTOR (V4SImode,
1932 : gen_rtvec (4, GEN_INT (0x43300000UL),
1933 : GEN_INT (0x45300000UL),
1934 : const0_rtx, const0_rtx));
1935 0 : exponents = validize_mem (force_const_mem (V4SImode, x));
1936 :
1937 : /* int_xmm = {0x45300000UL, fp_xmm/hi, 0x43300000, fp_xmm/lo } */
1938 0 : emit_insn (gen_vec_interleave_lowv4si (int_xmm, int_xmm, exponents));
1939 :
1940 : /* Concatenating (juxtaposing) (0x43300000UL ## fp_value_low_xmm)
1941 : yields a valid DF value equal to (0x1.0p52 + double(fp_value_lo_xmm)).
1942 : Similarly (0x45300000UL ## fp_value_hi_xmm) yields
1943 : (0x1.0p84 + double(fp_value_hi_xmm)).
1944 : Note these exponents differ by 32. */
1945 :
1946 0 : fp_xmm = copy_to_mode_reg (V2DFmode, gen_lowpart (V2DFmode, int_xmm));
1947 :
1948 : /* Subtract off those 0x1.0p52 and 0x1.0p84 biases, to produce values
1949 : in [0,2**32-1] and [0]+[2**32,2**64-1] respectively. */
1950 0 : real_ldexp (&bias_lo_rvt, &dconst1, 52);
1951 0 : real_ldexp (&bias_hi_rvt, &dconst1, 84);
1952 0 : biases = const_double_from_real_value (bias_lo_rvt, DFmode);
1953 0 : x = const_double_from_real_value (bias_hi_rvt, DFmode);
1954 0 : biases = gen_rtx_CONST_VECTOR (V2DFmode, gen_rtvec (2, biases, x));
1955 0 : biases = validize_mem (force_const_mem (V2DFmode, biases));
1956 0 : emit_insn (gen_subv2df3 (fp_xmm, fp_xmm, biases));
1957 :
1958 : /* Add the upper and lower DFmode values together. */
1959 0 : if (TARGET_SSE3)
1960 0 : emit_insn (gen_sse3_haddv2df3 (fp_xmm, fp_xmm, fp_xmm));
1961 : else
1962 : {
1963 0 : x = copy_to_mode_reg (V2DFmode, fp_xmm);
1964 0 : emit_insn (gen_vec_interleave_highv2df (fp_xmm, fp_xmm, fp_xmm));
1965 0 : emit_insn (gen_addv2df3 (fp_xmm, fp_xmm, x));
1966 : }
1967 :
1968 0 : ix86_expand_vector_extract (false, target, fp_xmm, 0);
1969 0 : }
1970 :
1971 : /* Not used, but eases macroization of patterns. */
1972 : void
1973 0 : ix86_expand_convert_uns_sixf_sse (rtx, rtx)
1974 : {
1975 0 : gcc_unreachable ();
1976 : }
1977 :
1978 : static rtx ix86_expand_sse_fabs (rtx op0, rtx *smask);
1979 :
1980 : /* Convert an unsigned SImode value into a DFmode. Only currently used
1981 : for SSE, but applicable anywhere. */
1982 :
1983 : void
1984 0 : ix86_expand_convert_uns_sidf_sse (rtx target, rtx input)
1985 : {
1986 0 : REAL_VALUE_TYPE TWO31r;
1987 0 : rtx x, fp;
1988 :
1989 0 : x = expand_simple_binop (SImode, PLUS, input, GEN_INT (-2147483647 - 1),
1990 : NULL, 1, OPTAB_DIRECT);
1991 :
1992 0 : fp = gen_reg_rtx (DFmode);
1993 0 : emit_insn (gen_floatsidf2 (fp, x));
1994 :
1995 0 : real_ldexp (&TWO31r, &dconst1, 31);
1996 0 : x = const_double_from_real_value (TWO31r, DFmode);
1997 :
1998 0 : x = expand_simple_binop (DFmode, PLUS, fp, x, target, 0, OPTAB_DIRECT);
1999 :
2000 : /* Remove the sign with FE_DOWNWARD, where x - x = -0.0. */
2001 0 : if (HONOR_SIGNED_ZEROS (DFmode) && flag_rounding_math)
2002 0 : x = ix86_expand_sse_fabs (x, NULL);
2003 :
2004 0 : if (x != target)
2005 0 : emit_move_insn (target, x);
2006 0 : }
2007 :
2008 : /* Convert a signed DImode value into a DFmode. Only used for SSE in
2009 : 32-bit mode; otherwise we have a direct convert instruction. */
2010 :
2011 : void
2012 0 : ix86_expand_convert_sign_didf_sse (rtx target, rtx input)
2013 : {
2014 0 : REAL_VALUE_TYPE TWO32r;
2015 0 : rtx fp_lo, fp_hi, x;
2016 :
2017 0 : fp_lo = gen_reg_rtx (DFmode);
2018 0 : fp_hi = gen_reg_rtx (DFmode);
2019 :
2020 0 : emit_insn (gen_floatsidf2 (fp_hi, gen_highpart (SImode, input)));
2021 :
2022 0 : real_ldexp (&TWO32r, &dconst1, 32);
2023 0 : x = const_double_from_real_value (TWO32r, DFmode);
2024 0 : fp_hi = expand_simple_binop (DFmode, MULT, fp_hi, x, fp_hi, 0, OPTAB_DIRECT);
2025 :
2026 0 : ix86_expand_convert_uns_sidf_sse (fp_lo, gen_lowpart (SImode, input));
2027 :
2028 0 : x = expand_simple_binop (DFmode, PLUS, fp_hi, fp_lo, target,
2029 : 0, OPTAB_DIRECT);
2030 0 : if (x != target)
2031 0 : emit_move_insn (target, x);
2032 0 : }
2033 :
2034 : /* Convert an unsigned SImode value into a SFmode, using only SSE.
2035 : For x86_32, -mfpmath=sse, !optimize_size only. */
2036 : void
2037 0 : ix86_expand_convert_uns_sisf_sse (rtx target, rtx input)
2038 : {
2039 0 : REAL_VALUE_TYPE ONE16r;
2040 0 : rtx fp_hi, fp_lo, int_hi, int_lo, x;
2041 :
2042 0 : real_ldexp (&ONE16r, &dconst1, 16);
2043 0 : x = const_double_from_real_value (ONE16r, SFmode);
2044 0 : int_lo = expand_simple_binop (SImode, AND, input, GEN_INT(0xffff),
2045 : NULL, 0, OPTAB_DIRECT);
2046 0 : int_hi = expand_simple_binop (SImode, LSHIFTRT, input, GEN_INT(16),
2047 : NULL, 0, OPTAB_DIRECT);
2048 0 : fp_hi = gen_reg_rtx (SFmode);
2049 0 : fp_lo = gen_reg_rtx (SFmode);
2050 0 : emit_insn (gen_floatsisf2 (fp_hi, int_hi));
2051 0 : emit_insn (gen_floatsisf2 (fp_lo, int_lo));
2052 0 : if (TARGET_FMA)
2053 : {
2054 0 : x = validize_mem (force_const_mem (SFmode, x));
2055 0 : fp_hi = gen_rtx_FMA (SFmode, fp_hi, x, fp_lo);
2056 0 : emit_move_insn (target, fp_hi);
2057 : }
2058 : else
2059 : {
2060 0 : fp_hi = expand_simple_binop (SFmode, MULT, fp_hi, x, fp_hi,
2061 : 0, OPTAB_DIRECT);
2062 0 : fp_hi = expand_simple_binop (SFmode, PLUS, fp_hi, fp_lo, target,
2063 : 0, OPTAB_DIRECT);
2064 0 : if (!rtx_equal_p (target, fp_hi))
2065 0 : emit_move_insn (target, fp_hi);
2066 : }
2067 0 : }
2068 :
2069 : /* floatunsv{4,8}siv{4,8}sf2 expander. Expand code to convert
2070 : a vector of unsigned ints VAL to vector of floats TARGET. */
2071 :
2072 : void
2073 54 : ix86_expand_vector_convert_uns_vsivsf (rtx target, rtx val)
2074 : {
2075 54 : rtx tmp[8];
2076 54 : REAL_VALUE_TYPE TWO16r;
2077 54 : machine_mode intmode = GET_MODE (val);
2078 54 : machine_mode fltmode = GET_MODE (target);
2079 54 : rtx (*cvt) (rtx, rtx);
2080 :
2081 54 : if (intmode == V4SImode)
2082 : cvt = gen_floatv4siv4sf2;
2083 : else
2084 2 : cvt = gen_floatv8siv8sf2;
2085 54 : tmp[0] = ix86_build_const_vector (intmode, 1, GEN_INT (0xffff));
2086 54 : tmp[0] = force_reg (intmode, tmp[0]);
2087 54 : tmp[1] = expand_simple_binop (intmode, AND, val, tmp[0], NULL_RTX, 1,
2088 : OPTAB_DIRECT);
2089 54 : tmp[2] = expand_simple_binop (intmode, LSHIFTRT, val, GEN_INT (16),
2090 : NULL_RTX, 1, OPTAB_DIRECT);
2091 54 : tmp[3] = gen_reg_rtx (fltmode);
2092 54 : emit_insn (cvt (tmp[3], tmp[1]));
2093 54 : tmp[4] = gen_reg_rtx (fltmode);
2094 54 : emit_insn (cvt (tmp[4], tmp[2]));
2095 54 : real_ldexp (&TWO16r, &dconst1, 16);
2096 54 : tmp[5] = const_double_from_real_value (TWO16r, SFmode);
2097 54 : tmp[5] = force_reg (fltmode, ix86_build_const_vector (fltmode, 1, tmp[5]));
2098 54 : if (TARGET_FMA)
2099 : {
2100 1 : tmp[6] = gen_rtx_FMA (fltmode, tmp[4], tmp[5], tmp[3]);
2101 1 : emit_move_insn (target, tmp[6]);
2102 : }
2103 : else
2104 : {
2105 53 : tmp[6] = expand_simple_binop (fltmode, MULT, tmp[4], tmp[5],
2106 : NULL_RTX, 1, OPTAB_DIRECT);
2107 53 : tmp[7] = expand_simple_binop (fltmode, PLUS, tmp[3], tmp[6],
2108 : target, 1, OPTAB_DIRECT);
2109 53 : if (tmp[7] != target)
2110 0 : emit_move_insn (target, tmp[7]);
2111 : }
2112 54 : }
2113 :
2114 : /* Adjust a V*SFmode/V*DFmode value VAL so that *sfix_trunc* resp. fix_trunc*
2115 : pattern can be used on it instead of fixuns_trunc*.
2116 : This is done by doing just signed conversion if < 0x1p31, and otherwise by
2117 : subtracting 0x1p31 first and xoring in 0x80000000 from *XORP afterwards. */
2118 :
2119 : rtx
2120 308 : ix86_expand_adjust_ufix_to_sfix_si (rtx val, rtx *xorp)
2121 : {
2122 308 : REAL_VALUE_TYPE TWO31r;
2123 308 : rtx two31r, tmp[4];
2124 308 : machine_mode mode = GET_MODE (val);
2125 308 : machine_mode scalarmode = GET_MODE_INNER (mode);
2126 616 : machine_mode intmode = GET_MODE_SIZE (mode) == 32 ? V8SImode : V4SImode;
2127 308 : rtx (*cmp) (rtx, rtx, rtx, rtx);
2128 308 : int i;
2129 :
2130 1232 : for (i = 0; i < 3; i++)
2131 924 : tmp[i] = gen_reg_rtx (mode);
2132 308 : real_ldexp (&TWO31r, &dconst1, 31);
2133 308 : two31r = const_double_from_real_value (TWO31r, scalarmode);
2134 308 : two31r = ix86_build_const_vector (mode, 1, two31r);
2135 308 : two31r = force_reg (mode, two31r);
2136 308 : switch (mode)
2137 : {
2138 : case E_V8SFmode: cmp = gen_avx_maskcmpv8sf3; break;
2139 10 : case E_V4SFmode: cmp = gen_sse_maskcmpv4sf3; break;
2140 16 : case E_V4DFmode: cmp = gen_avx_maskcmpv4df3; break;
2141 282 : case E_V2DFmode: cmp = gen_sse2_maskcmpv2df3; break;
2142 0 : default: gcc_unreachable ();
2143 : }
2144 308 : tmp[3] = gen_rtx_LE (mode, two31r, val);
2145 308 : emit_insn (cmp (tmp[0], two31r, val, tmp[3]));
2146 308 : tmp[1] = expand_simple_binop (mode, AND, tmp[0], two31r, tmp[1],
2147 : 0, OPTAB_DIRECT);
2148 308 : if (intmode == V4SImode || TARGET_AVX2)
2149 616 : *xorp = expand_simple_binop (intmode, ASHIFT,
2150 308 : gen_lowpart (intmode, tmp[0]),
2151 : GEN_INT (31), NULL_RTX, 0,
2152 : OPTAB_DIRECT);
2153 : else
2154 : {
2155 0 : rtx two31 = gen_int_mode (HOST_WIDE_INT_1U << 31, SImode);
2156 0 : two31 = ix86_build_const_vector (intmode, 1, two31);
2157 0 : *xorp = expand_simple_binop (intmode, AND,
2158 0 : gen_lowpart (intmode, tmp[0]),
2159 : two31, NULL_RTX, 0,
2160 : OPTAB_DIRECT);
2161 : }
2162 308 : return expand_simple_binop (mode, MINUS, val, tmp[1], tmp[2],
2163 308 : 0, OPTAB_DIRECT);
2164 : }
2165 :
2166 : /* Generate code for floating point ABS or NEG. */
2167 :
2168 : void
2169 35085 : ix86_expand_fp_absneg_operator (enum rtx_code code, machine_mode mode,
2170 : rtx operands[])
2171 : {
2172 35085 : rtx set, dst, src;
2173 35085 : bool use_sse = false;
2174 35085 : bool vector_mode = VECTOR_MODE_P (mode);
2175 35085 : machine_mode vmode = mode;
2176 35085 : rtvec par;
2177 :
2178 35085 : switch (mode)
2179 : {
2180 : case E_HFmode:
2181 : use_sse = true;
2182 : vmode = V8HFmode;
2183 : break;
2184 0 : case E_BFmode:
2185 0 : use_sse = true;
2186 0 : vmode = V8BFmode;
2187 0 : break;
2188 9543 : case E_SFmode:
2189 9543 : use_sse = TARGET_SSE_MATH && TARGET_SSE;
2190 : vmode = V4SFmode;
2191 : break;
2192 16147 : case E_DFmode:
2193 16147 : use_sse = TARGET_SSE_MATH && TARGET_SSE2;
2194 : vmode = V2DFmode;
2195 : break;
2196 9196 : default:
2197 9196 : use_sse = vector_mode || mode == TFmode;
2198 9196 : break;
2199 : }
2200 :
2201 35085 : dst = operands[0];
2202 35085 : src = operands[1];
2203 :
2204 35085 : set = gen_rtx_fmt_e (code, mode, src);
2205 35085 : set = gen_rtx_SET (dst, set);
2206 :
2207 35085 : if (use_sse)
2208 : {
2209 29378 : rtx mask, use, clob;
2210 :
2211 : /* NEG and ABS performed with SSE use bitwise mask operations.
2212 : Create the appropriate mask now. */
2213 29378 : mask = ix86_build_signbit_mask (vmode, vector_mode, code == ABS);
2214 29378 : use = gen_rtx_USE (VOIDmode, mask);
2215 29378 : if (vector_mode || mode == TFmode)
2216 4842 : par = gen_rtvec (2, set, use);
2217 : else
2218 : {
2219 24536 : clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
2220 24536 : par = gen_rtvec (3, set, use, clob);
2221 : }
2222 : }
2223 : else
2224 : {
2225 5707 : rtx clob;
2226 :
2227 : /* Changing of sign for FP values is doable using integer unit too. */
2228 5707 : clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
2229 5707 : par = gen_rtvec (2, set, clob);
2230 : }
2231 :
2232 35085 : emit_insn (gen_rtx_PARALLEL (VOIDmode, par));
2233 35085 : }
2234 :
2235 : /* Deconstruct a floating point ABS or NEG operation
2236 : with integer registers into integer operations. */
2237 :
2238 : void
2239 24 : ix86_split_fp_absneg_operator (enum rtx_code code, machine_mode mode,
2240 : rtx operands[])
2241 : {
2242 24 : enum rtx_code absneg_op;
2243 24 : rtx dst, set;
2244 :
2245 24 : gcc_assert (operands_match_p (operands[0], operands[1]));
2246 :
2247 24 : switch (mode)
2248 : {
2249 0 : case E_SFmode:
2250 0 : dst = gen_lowpart (SImode, operands[0]);
2251 :
2252 0 : if (code == ABS)
2253 : {
2254 0 : set = gen_int_mode (0x7fffffff, SImode);
2255 0 : absneg_op = AND;
2256 : }
2257 : else
2258 : {
2259 0 : set = gen_int_mode (0x80000000, SImode);
2260 0 : absneg_op = XOR;
2261 : }
2262 0 : set = gen_rtx_fmt_ee (absneg_op, SImode, dst, set);
2263 0 : break;
2264 :
2265 1 : case E_DFmode:
2266 1 : if (TARGET_64BIT)
2267 : {
2268 1 : dst = gen_lowpart (DImode, operands[0]);
2269 1 : dst = gen_rtx_ZERO_EXTRACT (DImode, dst, const1_rtx, GEN_INT (63));
2270 :
2271 1 : if (code == ABS)
2272 0 : set = const0_rtx;
2273 : else
2274 1 : set = gen_rtx_NOT (DImode, dst);
2275 : }
2276 : else
2277 : {
2278 0 : dst = gen_highpart (SImode, operands[0]);
2279 :
2280 0 : if (code == ABS)
2281 : {
2282 0 : set = gen_int_mode (0x7fffffff, SImode);
2283 0 : absneg_op = AND;
2284 : }
2285 : else
2286 : {
2287 0 : set = gen_int_mode (0x80000000, SImode);
2288 0 : absneg_op = XOR;
2289 : }
2290 0 : set = gen_rtx_fmt_ee (absneg_op, SImode, dst, set);
2291 : }
2292 : break;
2293 :
2294 23 : case E_XFmode:
2295 23 : dst = gen_rtx_REG (SImode,
2296 23 : REGNO (operands[0]) + (TARGET_64BIT ? 1 : 2));
2297 23 : if (code == ABS)
2298 : {
2299 1 : set = GEN_INT (0x7fff);
2300 1 : absneg_op = AND;
2301 : }
2302 : else
2303 : {
2304 22 : set = GEN_INT (0x8000);
2305 22 : absneg_op = XOR;
2306 : }
2307 23 : set = gen_rtx_fmt_ee (absneg_op, SImode, dst, set);
2308 23 : break;
2309 :
2310 0 : default:
2311 0 : gcc_unreachable ();
2312 : }
2313 :
2314 24 : set = gen_rtx_SET (dst, set);
2315 :
2316 24 : rtx clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
2317 24 : rtvec par = gen_rtvec (2, set, clob);
2318 :
2319 24 : emit_insn (gen_rtx_PARALLEL (VOIDmode, par));
2320 24 : }
2321 :
2322 : /* Expand a copysign operation. Special case operand 0 being a constant. */
2323 :
2324 : void
2325 23244 : ix86_expand_copysign (rtx operands[])
2326 : {
2327 23244 : machine_mode mode, vmode;
2328 23244 : rtx dest, vdest, op0, op1, mask, op2, op3;
2329 :
2330 23244 : mode = GET_MODE (operands[0]);
2331 :
2332 23244 : switch (mode)
2333 : {
2334 : case E_HFmode:
2335 : vmode = V8HFmode;
2336 : break;
2337 0 : case E_BFmode:
2338 0 : vmode = V8BFmode;
2339 0 : break;
2340 11565 : case E_SFmode:
2341 11565 : vmode = V4SFmode;
2342 11565 : break;
2343 11540 : case E_DFmode:
2344 11540 : vmode = V2DFmode;
2345 11540 : break;
2346 127 : case E_TFmode:
2347 127 : vmode = mode;
2348 127 : break;
2349 0 : default:
2350 0 : gcc_unreachable();
2351 : }
2352 :
2353 23244 : if (rtx_equal_p (operands[1], operands[2]))
2354 : {
2355 0 : emit_move_insn (operands[0], operands[1]);
2356 0 : return;
2357 : }
2358 :
2359 23244 : dest = operands[0];
2360 23244 : vdest = lowpart_subreg (vmode, dest, mode);
2361 23244 : if (vdest == NULL_RTX)
2362 0 : vdest = gen_reg_rtx (vmode);
2363 : else
2364 : dest = NULL_RTX;
2365 23244 : op1 = lowpart_subreg (vmode, force_reg (mode, operands[1]), mode);
2366 46474 : mask = ix86_build_signbit_mask (vmode, TARGET_AVX512F && mode != HFmode, 0);
2367 :
2368 23244 : if (CONST_DOUBLE_P (operands[2]))
2369 : {
2370 82 : if (real_isneg (CONST_DOUBLE_REAL_VALUE (operands[2])))
2371 : /* Simplify b = copysign (a, negative) to b = mask | a. */
2372 79 : op1 = gen_rtx_IOR (vmode, mask, op1);
2373 : else
2374 : {
2375 : /* Simplify b = copysign (a, positive) to b = invert_mask & a. */
2376 3 : rtx invert_mask
2377 3 : = ix86_build_signbit_mask (vmode,
2378 3 : TARGET_AVX512F && mode != HFmode,
2379 : true);
2380 3 : op1 = gen_rtx_AND (vmode, invert_mask, op1);
2381 : }
2382 82 : emit_move_insn (vdest, op1);
2383 82 : if (dest)
2384 0 : emit_move_insn (dest, lowpart_subreg (mode, vdest, vmode));
2385 82 : return;
2386 : }
2387 : else
2388 23162 : op0 = lowpart_subreg (vmode, force_reg (mode, operands[2]), mode);
2389 :
2390 23162 : op2 = gen_reg_rtx (vmode);
2391 23162 : op3 = gen_reg_rtx (vmode);
2392 23162 : rtx invert_mask;
2393 : /* NB: Generate vmovdqa, vpandn, vpand, vpor for AVX and generate pand,
2394 : pand, por for SSE. */
2395 23162 : if (TARGET_AVX)
2396 31 : invert_mask = gen_rtx_NOT (vmode, mask);
2397 : else
2398 23131 : invert_mask = ix86_build_signbit_mask (vmode,
2399 23131 : TARGET_AVX512F && mode != HFmode,
2400 : true);
2401 23162 : emit_move_insn (op2, gen_rtx_AND (vmode, invert_mask, op1));
2402 23162 : emit_move_insn (op3, gen_rtx_AND (vmode, mask, op0));
2403 23162 : emit_move_insn (vdest, gen_rtx_IOR (vmode, op2, op3));
2404 23162 : if (dest)
2405 0 : emit_move_insn (dest, lowpart_subreg (mode, vdest, vmode));
2406 : }
2407 :
2408 : /* Expand an xorsign operation. */
2409 :
2410 : void
2411 20 : ix86_expand_xorsign (rtx operands[])
2412 : {
2413 20 : machine_mode mode, vmode;
2414 20 : rtx dest, vdest, op0, op1, mask, x, temp;
2415 :
2416 20 : dest = operands[0];
2417 20 : op0 = operands[1];
2418 20 : op1 = operands[2];
2419 :
2420 20 : mode = GET_MODE (dest);
2421 :
2422 20 : switch (mode)
2423 : {
2424 : case E_HFmode:
2425 : vmode = V8HFmode;
2426 : break;
2427 : case E_BFmode:
2428 : vmode = V8BFmode;
2429 : break;
2430 : case E_SFmode:
2431 : vmode = V4SFmode;
2432 : break;
2433 : case E_DFmode:
2434 : vmode = V2DFmode;
2435 : break;
2436 0 : default:
2437 0 : gcc_unreachable ();
2438 20 : break;
2439 : }
2440 :
2441 20 : temp = gen_reg_rtx (vmode);
2442 20 : mask = ix86_build_signbit_mask (vmode, 0, 0);
2443 :
2444 20 : op1 = lowpart_subreg (vmode, force_reg (mode, op1), mode);
2445 20 : x = gen_rtx_AND (vmode, op1, mask);
2446 20 : emit_insn (gen_rtx_SET (temp, x));
2447 :
2448 20 : op0 = lowpart_subreg (vmode, force_reg (mode, op0), mode);
2449 20 : x = gen_rtx_XOR (vmode, temp, op0);
2450 :
2451 20 : vdest = lowpart_subreg (vmode, dest, mode);
2452 20 : if (vdest == NULL_RTX)
2453 0 : vdest = gen_reg_rtx (vmode);
2454 : else
2455 : dest = NULL_RTX;
2456 20 : emit_insn (gen_rtx_SET (vdest, x));
2457 :
2458 20 : if (dest)
2459 0 : emit_move_insn (dest, lowpart_subreg (mode, vdest, vmode));
2460 20 : }
2461 :
2462 : static rtx ix86_expand_compare (enum rtx_code code, rtx op0, rtx op1);
2463 :
2464 : void
2465 6719383 : ix86_expand_branch (enum rtx_code code, rtx op0, rtx op1, rtx label)
2466 : {
2467 6719383 : machine_mode mode = GET_MODE (op0);
2468 6719383 : rtx tmp;
2469 :
2470 : /* Handle special case - vector comparison with boolean result, transform
2471 : it using ptest instruction or vpcmpeq + kortest. */
2472 6719383 : if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT
2473 6700033 : || (mode == TImode && !TARGET_64BIT)
2474 6700033 : || mode == OImode
2475 13419416 : || GET_MODE_SIZE (mode) == 64)
2476 : {
2477 19350 : unsigned msize = GET_MODE_SIZE (mode);
2478 19350 : machine_mode p_mode
2479 19350 : = msize == 64 ? V16SImode : msize == 32 ? V4DImode : V2DImode;
2480 : /* kortest set CF when result is 0xFFFF (op0 == op1). */
2481 19350 : rtx flag = gen_rtx_REG (msize == 64 ? CCCmode : CCZmode, FLAGS_REG);
2482 :
2483 19350 : gcc_assert (code == EQ || code == NE);
2484 :
2485 : /* Using vpcmpeq zmm zmm k + kortest for 512-bit vectors. */
2486 19350 : if (msize == 64)
2487 : {
2488 2431 : if (mode != V16SImode)
2489 : {
2490 2431 : op0 = lowpart_subreg (p_mode, force_reg (mode, op0), mode);
2491 2431 : op1 = lowpart_subreg (p_mode, force_reg (mode, op1), mode);
2492 : }
2493 :
2494 2431 : tmp = gen_reg_rtx (HImode);
2495 2431 : emit_insn (gen_avx512f_cmpv16si3 (tmp, op0, op1, GEN_INT (0)));
2496 2431 : emit_insn (gen_kortesthi_ccc (tmp, tmp));
2497 : }
2498 : /* Using ptest for 128/256-bit vectors. */
2499 : else
2500 : {
2501 16919 : if (GET_MODE_CLASS (mode) != MODE_VECTOR_INT)
2502 : {
2503 0 : op0 = lowpart_subreg (p_mode, force_reg (mode, op0), mode);
2504 0 : op1 = lowpart_subreg (p_mode, force_reg (mode, op1), mode);
2505 0 : mode = p_mode;
2506 : }
2507 :
2508 : /* Generate XOR since we can't check that one operand is zero
2509 : vector. */
2510 16919 : tmp = gen_reg_rtx (mode);
2511 16919 : rtx ops[3] = { tmp, op0, op1 };
2512 16919 : ix86_expand_vector_logical_operator (XOR, mode, ops);
2513 16919 : tmp = gen_lowpart (p_mode, tmp);
2514 16919 : emit_insn (gen_rtx_SET (gen_rtx_REG (CCZmode, FLAGS_REG),
2515 : gen_rtx_UNSPEC (CCZmode,
2516 : gen_rtvec (2, tmp, tmp),
2517 : UNSPEC_PTEST)));
2518 : }
2519 19350 : tmp = gen_rtx_fmt_ee (code, VOIDmode, flag, const0_rtx);
2520 19350 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
2521 : gen_rtx_LABEL_REF (VOIDmode, label),
2522 : pc_rtx);
2523 19350 : emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
2524 19350 : return;
2525 : }
2526 :
2527 6700033 : switch (mode)
2528 : {
2529 6668386 : case E_HFmode:
2530 6668386 : case E_SFmode:
2531 6668386 : case E_DFmode:
2532 6668386 : case E_XFmode:
2533 6668386 : case E_QImode:
2534 6668386 : case E_HImode:
2535 6668386 : case E_SImode:
2536 6668386 : simple:
2537 6668386 : tmp = ix86_expand_compare (code, op0, op1);
2538 6668386 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
2539 : gen_rtx_LABEL_REF (VOIDmode, label),
2540 : pc_rtx);
2541 6668386 : emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
2542 6668386 : return;
2543 :
2544 7 : case E_BFmode:
2545 7 : gcc_assert (TARGET_AVX10_2 && !flag_trapping_math);
2546 7 : goto simple;
2547 :
2548 2712067 : case E_DImode:
2549 2712067 : if (TARGET_64BIT)
2550 2683593 : goto simple;
2551 : /* FALLTHRU */
2552 90221 : case E_TImode:
2553 : /* DI and TI mode equality/inequality comparisons may be performed
2554 : on SSE registers. Avoid splitting them, except when optimizing
2555 : for size. */
2556 90221 : if ((code == EQ || code == NE)
2557 90221 : && !optimize_insn_for_size_p ())
2558 58574 : goto simple;
2559 :
2560 : /* Expand DImode branch into multiple compare+branch. */
2561 31647 : {
2562 31647 : rtx lo[2], hi[2];
2563 31647 : rtx_code_label *label2;
2564 31647 : enum rtx_code code1, code2, code3;
2565 31647 : machine_mode submode;
2566 :
2567 31647 : if (CONSTANT_P (op0) && !CONSTANT_P (op1))
2568 : {
2569 0 : std::swap (op0, op1);
2570 0 : code = swap_condition (code);
2571 : }
2572 :
2573 31647 : split_double_mode (mode, &op0, 1, lo+0, hi+0);
2574 31647 : split_double_mode (mode, &op1, 1, lo+1, hi+1);
2575 :
2576 31647 : submode = mode == DImode ? SImode : DImode;
2577 :
2578 : /* If we are doing less-than or greater-or-equal-than,
2579 : op1 is a constant and the low word is zero, then we can just
2580 : examine the high word. Similarly for low word -1 and
2581 : less-or-equal-than or greater-than. */
2582 :
2583 31647 : if (CONST_INT_P (hi[1]))
2584 20750 : switch (code)
2585 : {
2586 11345 : case LT: case LTU: case GE: case GEU:
2587 11345 : if (lo[1] == const0_rtx)
2588 : {
2589 10921 : ix86_expand_branch (code, hi[0], hi[1], label);
2590 10921 : return;
2591 : }
2592 : break;
2593 7853 : case LE: case LEU: case GT: case GTU:
2594 7853 : if (lo[1] == constm1_rtx)
2595 : {
2596 528 : ix86_expand_branch (code, hi[0], hi[1], label);
2597 528 : return;
2598 : }
2599 : break;
2600 : default:
2601 : break;
2602 : }
2603 :
2604 : /* Emulate comparisons that do not depend on Zero flag with
2605 : double-word subtraction. Note that only Overflow, Sign
2606 : and Carry flags are valid, so swap arguments and condition
2607 : of comparisons that would otherwise test Zero flag. */
2608 :
2609 20198 : switch (code)
2610 : {
2611 12706 : case LE: case LEU: case GT: case GTU:
2612 12706 : std::swap (lo[0], lo[1]);
2613 12706 : std::swap (hi[0], hi[1]);
2614 12706 : code = swap_condition (code);
2615 : /* FALLTHRU */
2616 :
2617 17169 : case LT: case LTU: case GE: case GEU:
2618 17169 : {
2619 17169 : bool uns = (code == LTU || code == GEU);
2620 4053 : rtx (*sbb_insn) (machine_mode, rtx, rtx, rtx)
2621 17169 : = uns ? gen_sub3_carry_ccc : gen_sub3_carry_ccgz;
2622 :
2623 17169 : if (!nonimmediate_operand (lo[0], submode))
2624 7325 : lo[0] = force_reg (submode, lo[0]);
2625 17169 : if (!x86_64_general_operand (lo[1], submode))
2626 0 : lo[1] = force_reg (submode, lo[1]);
2627 :
2628 17169 : if (!register_operand (hi[0], submode))
2629 8108 : hi[0] = force_reg (submode, hi[0]);
2630 13116 : if ((uns && !nonimmediate_operand (hi[1], submode))
2631 17169 : || (!uns && !x86_64_general_operand (hi[1], submode)))
2632 315 : hi[1] = force_reg (submode, hi[1]);
2633 :
2634 17169 : emit_insn (gen_cmp_1 (submode, lo[0], lo[1]));
2635 :
2636 17169 : tmp = gen_rtx_SCRATCH (submode);
2637 17169 : emit_insn (sbb_insn (submode, tmp, hi[0], hi[1]));
2638 :
2639 21222 : tmp = gen_rtx_REG (uns ? CCCmode : CCGZmode, FLAGS_REG);
2640 17169 : ix86_expand_branch (code, tmp, const0_rtx, label);
2641 17169 : return;
2642 : }
2643 :
2644 3029 : default:
2645 3029 : break;
2646 : }
2647 :
2648 : /* Otherwise, we need two or three jumps. */
2649 :
2650 3029 : label2 = gen_label_rtx ();
2651 :
2652 3029 : code1 = code;
2653 3029 : code2 = swap_condition (code);
2654 3029 : code3 = unsigned_condition (code);
2655 :
2656 3029 : switch (code)
2657 : {
2658 : case LT: case GT: case LTU: case GTU:
2659 : break;
2660 :
2661 : case LE: code1 = LT; code2 = GT; break;
2662 : case GE: code1 = GT; code2 = LT; break;
2663 0 : case LEU: code1 = LTU; code2 = GTU; break;
2664 0 : case GEU: code1 = GTU; code2 = LTU; break;
2665 :
2666 : case EQ: code1 = UNKNOWN; code2 = NE; break;
2667 : case NE: code2 = UNKNOWN; break;
2668 :
2669 0 : default:
2670 0 : gcc_unreachable ();
2671 : }
2672 :
2673 : /*
2674 : * a < b =>
2675 : * if (hi(a) < hi(b)) goto true;
2676 : * if (hi(a) > hi(b)) goto false;
2677 : * if (lo(a) < lo(b)) goto true;
2678 : * false:
2679 : */
2680 :
2681 0 : if (code1 != UNKNOWN)
2682 2362 : ix86_expand_branch (code1, hi[0], hi[1], label);
2683 3029 : if (code2 != UNKNOWN)
2684 667 : ix86_expand_branch (code2, hi[0], hi[1], label2);
2685 :
2686 3029 : ix86_expand_branch (code3, lo[0], lo[1], label);
2687 :
2688 3029 : if (code2 != UNKNOWN)
2689 667 : emit_label (label2);
2690 : return;
2691 : }
2692 :
2693 17679 : default:
2694 17679 : gcc_assert (GET_MODE_CLASS (GET_MODE (op0)) == MODE_CC);
2695 17679 : goto simple;
2696 : }
2697 : }
2698 :
2699 : /* Figure out whether to use unordered fp comparisons. */
2700 :
2701 : static bool
2702 1158709 : ix86_unordered_fp_compare (enum rtx_code code)
2703 : {
2704 1158709 : if (!TARGET_IEEE_FP)
2705 : return false;
2706 :
2707 1154297 : switch (code)
2708 : {
2709 : case LT:
2710 : case LE:
2711 : case GT:
2712 : case GE:
2713 : case LTGT:
2714 : return false;
2715 :
2716 : case EQ:
2717 : case NE:
2718 :
2719 : case UNORDERED:
2720 : case ORDERED:
2721 : case UNLT:
2722 : case UNLE:
2723 : case UNGT:
2724 : case UNGE:
2725 : case UNEQ:
2726 : return true;
2727 :
2728 0 : default:
2729 0 : gcc_unreachable ();
2730 : }
2731 : }
2732 :
2733 : /* Return a comparison we can do and that it is equivalent to
2734 : swap_condition (code) apart possibly from orderedness.
2735 : But, never change orderedness if TARGET_IEEE_FP, returning
2736 : UNKNOWN in that case if necessary. */
2737 :
2738 : static enum rtx_code
2739 38042 : ix86_fp_swap_condition (enum rtx_code code)
2740 : {
2741 38042 : switch (code)
2742 : {
2743 1888 : case GT: /* GTU - CF=0 & ZF=0 */
2744 1888 : return TARGET_IEEE_FP ? UNKNOWN : UNLT;
2745 544 : case GE: /* GEU - CF=0 */
2746 544 : return TARGET_IEEE_FP ? UNKNOWN : UNLE;
2747 504 : case UNLT: /* LTU - CF=1 */
2748 504 : return TARGET_IEEE_FP ? UNKNOWN : GT;
2749 6362 : case UNLE: /* LEU - CF=1 | ZF=1 */
2750 6362 : return TARGET_IEEE_FP ? UNKNOWN : GE;
2751 28744 : default:
2752 28744 : return swap_condition (code);
2753 : }
2754 : }
2755 :
2756 : /* Return cost of comparison CODE using the best strategy for performance.
2757 : All following functions do use number of instructions as a cost metrics.
2758 : In future this should be tweaked to compute bytes for optimize_size and
2759 : take into account performance of various instructions on various CPUs. */
2760 :
2761 : static int
2762 1157576 : ix86_fp_comparison_cost (enum rtx_code code)
2763 : {
2764 1157576 : int arith_cost;
2765 :
2766 : /* The cost of code using bit-twiddling on %ah. */
2767 1157576 : switch (code)
2768 : {
2769 : case UNLE:
2770 : case UNLT:
2771 : case LTGT:
2772 : case GT:
2773 : case GE:
2774 : case UNORDERED:
2775 : case ORDERED:
2776 : case UNEQ:
2777 : arith_cost = 4;
2778 : break;
2779 85565 : case LT:
2780 85565 : case NE:
2781 85565 : case EQ:
2782 85565 : case UNGE:
2783 85565 : arith_cost = TARGET_IEEE_FP ? 5 : 4;
2784 : break;
2785 25900 : case LE:
2786 25900 : case UNGT:
2787 1072815 : arith_cost = TARGET_IEEE_FP ? 6 : 4;
2788 : break;
2789 0 : default:
2790 0 : gcc_unreachable ();
2791 : }
2792 :
2793 1157576 : switch (ix86_fp_comparison_strategy (code))
2794 : {
2795 1157576 : case IX86_FPCMP_COMI:
2796 1157576 : return arith_cost > 4 ? 3 : 2;
2797 0 : case IX86_FPCMP_SAHF:
2798 0 : return arith_cost > 4 ? 4 : 3;
2799 : default:
2800 : return arith_cost;
2801 : }
2802 : }
2803 :
2804 : /* Swap, force into registers, or otherwise massage the two operands
2805 : to a fp comparison. The operands are updated in place; the new
2806 : comparison code is returned. */
2807 :
2808 : static enum rtx_code
2809 578788 : ix86_prepare_fp_compare_args (enum rtx_code code, rtx *pop0, rtx *pop1)
2810 : {
2811 578859 : bool unordered_compare = ix86_unordered_fp_compare (code);
2812 578859 : rtx op0 = *pop0, op1 = *pop1;
2813 578859 : machine_mode op_mode = GET_MODE (op0);
2814 578859 : bool is_sse = SSE_FLOAT_MODE_SSEMATH_OR_HFBF_P (op_mode);
2815 :
2816 576470 : if (op_mode == BFmode && (!TARGET_AVX10_2 || flag_trapping_math))
2817 : {
2818 71 : rtx op = gen_lowpart (HImode, op0);
2819 71 : if (CONST_INT_P (op))
2820 0 : op = simplify_const_unary_operation (FLOAT_EXTEND, SFmode,
2821 : op0, BFmode);
2822 : else
2823 : {
2824 71 : rtx t1 = gen_reg_rtx (SImode);
2825 71 : emit_insn (gen_zero_extendhisi2 (t1, op));
2826 71 : emit_insn (gen_ashlsi3 (t1, t1, GEN_INT (16)));
2827 71 : op = gen_lowpart (SFmode, t1);
2828 : }
2829 71 : *pop0 = op;
2830 71 : op = gen_lowpart (HImode, op1);
2831 71 : if (CONST_INT_P (op))
2832 6 : op = simplify_const_unary_operation (FLOAT_EXTEND, SFmode,
2833 : op1, BFmode);
2834 : else
2835 : {
2836 65 : rtx t1 = gen_reg_rtx (SImode);
2837 65 : emit_insn (gen_zero_extendhisi2 (t1, op));
2838 65 : emit_insn (gen_ashlsi3 (t1, t1, GEN_INT (16)));
2839 65 : op = gen_lowpart (SFmode, t1);
2840 : }
2841 71 : *pop1 = op;
2842 71 : return ix86_prepare_fp_compare_args (code, pop0, pop1);
2843 : }
2844 :
2845 : /* All of the unordered compare instructions only work on registers.
2846 : The same is true of the fcomi compare instructions. The XFmode
2847 : compare instructions require registers except when comparing
2848 : against zero or when converting operand 1 from fixed point to
2849 : floating point. */
2850 :
2851 578788 : if (!is_sse
2852 578788 : && (unordered_compare
2853 8135 : || (op_mode == XFmode
2854 10401 : && ! (standard_80387_constant_p (op0) == 1
2855 5197 : || standard_80387_constant_p (op1) == 1)
2856 4763 : && GET_CODE (op1) != FLOAT)
2857 3372 : || ix86_fp_comparison_strategy (code) == IX86_FPCMP_COMI))
2858 : {
2859 148199 : op0 = force_reg (op_mode, op0);
2860 148199 : op1 = force_reg (op_mode, op1);
2861 : }
2862 : else
2863 : {
2864 : /* %%% We only allow op1 in memory; op0 must be st(0). So swap
2865 : things around if they appear profitable, otherwise force op0
2866 : into a register. */
2867 :
2868 430589 : if (standard_80387_constant_p (op0) == 0
2869 430589 : || (MEM_P (op0)
2870 57385 : && ! (standard_80387_constant_p (op1) == 0
2871 41928 : || MEM_P (op1))))
2872 : {
2873 38042 : enum rtx_code new_code = ix86_fp_swap_condition (code);
2874 38042 : if (new_code != UNKNOWN)
2875 : {
2876 : std::swap (op0, op1);
2877 430589 : code = new_code;
2878 : }
2879 : }
2880 :
2881 430589 : if (!REG_P (op0))
2882 53539 : op0 = force_reg (op_mode, op0);
2883 :
2884 430589 : if (CONSTANT_P (op1))
2885 : {
2886 194949 : int tmp = standard_80387_constant_p (op1);
2887 194949 : if (tmp == 0)
2888 75050 : op1 = validize_mem (force_const_mem (op_mode, op1));
2889 119899 : else if (tmp == 1)
2890 : {
2891 65732 : if (TARGET_CMOVE)
2892 65732 : op1 = force_reg (op_mode, op1);
2893 : }
2894 : else
2895 54167 : op1 = force_reg (op_mode, op1);
2896 : }
2897 : }
2898 :
2899 : /* Try to rearrange the comparison to make it cheaper. */
2900 578788 : if (ix86_fp_comparison_cost (code)
2901 578788 : > ix86_fp_comparison_cost (swap_condition (code))
2902 578788 : && (REG_P (op1) || can_create_pseudo_p ()))
2903 : {
2904 0 : std::swap (op0, op1);
2905 0 : code = swap_condition (code);
2906 0 : if (!REG_P (op0))
2907 0 : op0 = force_reg (op_mode, op0);
2908 : }
2909 :
2910 578788 : *pop0 = op0;
2911 578788 : *pop1 = op1;
2912 578788 : return code;
2913 : }
2914 :
2915 : /* Generate insn patterns to do a floating point compare of OPERANDS. */
2916 :
2917 : static rtx
2918 578788 : ix86_expand_fp_compare (enum rtx_code code, rtx op0, rtx op1)
2919 : {
2920 578788 : bool unordered_compare = ix86_unordered_fp_compare (code);
2921 578788 : machine_mode cmp_mode;
2922 578788 : rtx tmp, scratch;
2923 :
2924 578788 : code = ix86_prepare_fp_compare_args (code, &op0, &op1);
2925 :
2926 578788 : tmp = gen_rtx_COMPARE (CCFPmode, op0, op1);
2927 578788 : if (unordered_compare)
2928 503006 : tmp = gen_rtx_UNSPEC (CCFPmode, gen_rtvec (1, tmp), UNSPEC_NOTRAP);
2929 :
2930 : /* Do fcomi/sahf based test when profitable. */
2931 578788 : switch (ix86_fp_comparison_strategy (code))
2932 : {
2933 578788 : case IX86_FPCMP_COMI:
2934 578788 : tmp = gen_rtx_COMPARE (CCFPmode, op0, op1);
2935 : /* We only have vcomisbf16, No vcomubf16 nor vcomxbf16 */
2936 578788 : if (GET_MODE (op0) != E_BFmode)
2937 : {
2938 578760 : if (TARGET_AVX10_2 && (code == EQ || code == NE))
2939 972 : tmp = gen_rtx_UNSPEC (CCFPmode, gen_rtvec (1, tmp), UNSPEC_OPTCOMX);
2940 578760 : if (unordered_compare)
2941 502998 : tmp = gen_rtx_UNSPEC (CCFPmode, gen_rtvec (1, tmp), UNSPEC_NOTRAP);
2942 : }
2943 578788 : cmp_mode = CCFPmode;
2944 578788 : emit_insn (gen_rtx_SET (gen_rtx_REG (CCFPmode, FLAGS_REG), tmp));
2945 578788 : break;
2946 :
2947 0 : case IX86_FPCMP_SAHF:
2948 0 : cmp_mode = CCFPmode;
2949 0 : tmp = gen_rtx_UNSPEC (HImode, gen_rtvec (1, tmp), UNSPEC_FNSTSW);
2950 0 : scratch = gen_reg_rtx (HImode);
2951 0 : emit_insn (gen_rtx_SET (scratch, tmp));
2952 0 : emit_insn (gen_x86_sahf_1 (scratch));
2953 0 : break;
2954 :
2955 0 : case IX86_FPCMP_ARITH:
2956 0 : cmp_mode = CCNOmode;
2957 0 : tmp = gen_rtx_UNSPEC (HImode, gen_rtvec (1, tmp), UNSPEC_FNSTSW);
2958 0 : scratch = gen_reg_rtx (HImode);
2959 0 : emit_insn (gen_rtx_SET (scratch, tmp));
2960 :
2961 : /* In the unordered case, we have to check C2 for NaN's, which
2962 : doesn't happen to work out to anything nice combination-wise.
2963 : So do some bit twiddling on the value we've got in AH to come
2964 : up with an appropriate set of condition codes. */
2965 :
2966 0 : switch (code)
2967 : {
2968 0 : case GT:
2969 0 : case UNGT:
2970 0 : if (code == GT || !TARGET_IEEE_FP)
2971 : {
2972 0 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x45)));
2973 0 : code = EQ;
2974 : }
2975 : else
2976 : {
2977 0 : emit_insn (gen_andqi_ext_1 (scratch, scratch, GEN_INT (0x45)));
2978 0 : emit_insn (gen_addqi_ext_1 (scratch, scratch, constm1_rtx));
2979 0 : emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x44)));
2980 0 : cmp_mode = CCmode;
2981 0 : code = GEU;
2982 : }
2983 : break;
2984 0 : case LT:
2985 0 : case UNLT:
2986 0 : if (code == LT && TARGET_IEEE_FP)
2987 : {
2988 0 : emit_insn (gen_andqi_ext_1 (scratch, scratch, GEN_INT (0x45)));
2989 0 : emit_insn (gen_cmpqi_ext_3 (scratch, const1_rtx));
2990 0 : cmp_mode = CCmode;
2991 0 : code = EQ;
2992 : }
2993 : else
2994 : {
2995 0 : emit_insn (gen_testqi_ext_1_ccno (scratch, const1_rtx));
2996 0 : code = NE;
2997 : }
2998 : break;
2999 0 : case GE:
3000 0 : case UNGE:
3001 0 : if (code == GE || !TARGET_IEEE_FP)
3002 : {
3003 0 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x05)));
3004 0 : code = EQ;
3005 : }
3006 : else
3007 : {
3008 0 : emit_insn (gen_andqi_ext_1 (scratch, scratch, GEN_INT (0x45)));
3009 0 : emit_insn (gen_xorqi_ext_1_cc (scratch, scratch, const1_rtx));
3010 0 : code = NE;
3011 : }
3012 : break;
3013 0 : case LE:
3014 0 : case UNLE:
3015 0 : if (code == LE && TARGET_IEEE_FP)
3016 : {
3017 0 : emit_insn (gen_andqi_ext_1 (scratch, scratch, GEN_INT (0x45)));
3018 0 : emit_insn (gen_addqi_ext_1 (scratch, scratch, constm1_rtx));
3019 0 : emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x40)));
3020 0 : cmp_mode = CCmode;
3021 0 : code = LTU;
3022 : }
3023 : else
3024 : {
3025 0 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x45)));
3026 0 : code = NE;
3027 : }
3028 : break;
3029 0 : case EQ:
3030 0 : case UNEQ:
3031 0 : if (code == EQ && TARGET_IEEE_FP)
3032 : {
3033 0 : emit_insn (gen_andqi_ext_1 (scratch, scratch, GEN_INT (0x45)));
3034 0 : emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x40)));
3035 0 : cmp_mode = CCmode;
3036 0 : code = EQ;
3037 : }
3038 : else
3039 : {
3040 0 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x40)));
3041 0 : code = NE;
3042 : }
3043 : break;
3044 0 : case NE:
3045 0 : case LTGT:
3046 0 : if (code == NE && TARGET_IEEE_FP)
3047 : {
3048 0 : emit_insn (gen_andqi_ext_1 (scratch, scratch, GEN_INT (0x45)));
3049 0 : emit_insn (gen_xorqi_ext_1_cc (scratch, scratch,
3050 : GEN_INT (0x40)));
3051 0 : code = NE;
3052 : }
3053 : else
3054 : {
3055 0 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x40)));
3056 0 : code = EQ;
3057 : }
3058 : break;
3059 :
3060 0 : case UNORDERED:
3061 0 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x04)));
3062 0 : code = NE;
3063 0 : break;
3064 0 : case ORDERED:
3065 0 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x04)));
3066 0 : code = EQ;
3067 0 : break;
3068 :
3069 0 : default:
3070 0 : gcc_unreachable ();
3071 : }
3072 : break;
3073 :
3074 0 : default:
3075 0 : gcc_unreachable();
3076 : }
3077 :
3078 : /* Return the test that should be put into the flags user, i.e.
3079 : the bcc, scc, or cmov instruction. */
3080 578788 : return gen_rtx_fmt_ee (code, VOIDmode,
3081 : gen_rtx_REG (cmp_mode, FLAGS_REG),
3082 : const0_rtx);
3083 : }
3084 :
3085 : /* Generate insn patterns to do an integer compare of OPERANDS. */
3086 :
3087 : static rtx
3088 7060664 : ix86_expand_int_compare (enum rtx_code code, rtx op0, rtx op1)
3089 : {
3090 7060664 : machine_mode cmpmode;
3091 7060664 : rtx tmp, flags;
3092 :
3093 : /* Swap operands to emit carry flag comparison. */
3094 7060664 : if ((code == GTU || code == LEU)
3095 7060664 : && nonimmediate_operand (op1, VOIDmode))
3096 : {
3097 149736 : std::swap (op0, op1);
3098 149736 : code = swap_condition (code);
3099 : }
3100 :
3101 7060664 : cmpmode = SELECT_CC_MODE (code, op0, op1);
3102 7060664 : flags = gen_rtx_REG (cmpmode, FLAGS_REG);
3103 :
3104 : /* Attempt to use PTEST, if available, when testing vector modes for
3105 : equality/inequality against zero. */
3106 7060664 : if (op1 == const0_rtx
3107 2931856 : && SUBREG_P (op0)
3108 24248 : && cmpmode == CCZmode
3109 11268 : && SUBREG_BYTE (op0) == 0
3110 9598 : && REG_P (SUBREG_REG (op0))
3111 9598 : && VECTOR_MODE_P (GET_MODE (SUBREG_REG (op0)))
3112 8 : && TARGET_SSE4_1
3113 2 : && GET_MODE (op0) == TImode
3114 7060668 : && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op0))) == 16)
3115 : {
3116 2 : tmp = SUBREG_REG (op0);
3117 2 : if (GET_MODE (tmp) == V8HFmode || GET_MODE (tmp) == V8BFmode)
3118 1 : tmp = gen_lowpart (V8HImode, tmp);
3119 2 : tmp = gen_rtx_UNSPEC (CCZmode, gen_rtvec (2, tmp, tmp), UNSPEC_PTEST);
3120 : }
3121 : else
3122 7060662 : tmp = gen_rtx_COMPARE (cmpmode, op0, op1);
3123 :
3124 : /* This is very simple, but making the interface the same as in the
3125 : FP case makes the rest of the code easier. */
3126 7060664 : emit_insn (gen_rtx_SET (flags, tmp));
3127 :
3128 : /* Return the test that should be put into the flags user, i.e.
3129 : the bcc, scc, or cmov instruction. */
3130 7060664 : return gen_rtx_fmt_ee (code, VOIDmode, flags, const0_rtx);
3131 : }
3132 :
3133 : static rtx
3134 7768171 : ix86_expand_compare (enum rtx_code code, rtx op0, rtx op1)
3135 : {
3136 7768171 : rtx ret;
3137 :
3138 7768171 : if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_CC)
3139 130789 : ret = gen_rtx_fmt_ee (code, VOIDmode, op0, op1);
3140 :
3141 7637382 : else if (SCALAR_FLOAT_MODE_P (GET_MODE (op0)))
3142 : {
3143 576718 : gcc_assert (!DECIMAL_FLOAT_MODE_P (GET_MODE (op0)));
3144 576718 : ret = ix86_expand_fp_compare (code, op0, op1);
3145 : }
3146 : else
3147 7060664 : ret = ix86_expand_int_compare (code, op0, op1);
3148 :
3149 7768171 : return ret;
3150 : }
3151 :
3152 : void
3153 631819 : ix86_expand_setcc (rtx dest, enum rtx_code code, rtx op0, rtx op1)
3154 : {
3155 631819 : rtx ret;
3156 :
3157 631819 : gcc_assert (GET_MODE (dest) == QImode);
3158 :
3159 631819 : ret = ix86_expand_compare (code, op0, op1);
3160 631819 : PUT_MODE (ret, QImode);
3161 631819 : emit_insn (gen_rtx_SET (dest, ret));
3162 631819 : }
3163 :
3164 : /* Expand floating point op0 <=> op1, i.e.
3165 : dest = op0 == op1 ? 0 : op0 < op1 ? -1 : op0 > op1 ? 1 : -128. */
3166 :
3167 : void
3168 244 : ix86_expand_fp_spaceship (rtx dest, rtx op0, rtx op1, rtx op2)
3169 : {
3170 244 : gcc_checking_assert (ix86_fp_comparison_strategy (GT) != IX86_FPCMP_ARITH);
3171 244 : rtx zero = NULL_RTX;
3172 244 : if (op2 != const0_rtx
3173 52 : && (TARGET_IEEE_FP || TARGET_ZERO_EXTEND_WITH_AND)
3174 34 : && GET_MODE (dest) == SImode)
3175 34 : zero = force_reg (SImode, const0_rtx);
3176 244 : rtx gt = ix86_expand_fp_compare (GT, op0, op1);
3177 244 : rtx l0 = op2 == const0_rtx ? gen_label_rtx () : NULL_RTX;
3178 244 : rtx l1 = op2 == const0_rtx ? gen_label_rtx () : NULL_RTX;
3179 244 : rtx l2 = TARGET_IEEE_FP ? gen_label_rtx () : NULL_RTX;
3180 244 : rtx lend = gen_label_rtx ();
3181 244 : rtx tmp;
3182 244 : rtx_insn *jmp;
3183 244 : if (l2)
3184 : {
3185 207 : rtx un = gen_rtx_fmt_ee (UNORDERED, VOIDmode,
3186 : gen_rtx_REG (CCFPmode, FLAGS_REG), const0_rtx);
3187 207 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, un,
3188 : gen_rtx_LABEL_REF (VOIDmode, l2), pc_rtx);
3189 207 : jmp = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
3190 207 : add_reg_br_prob_note (jmp, profile_probability:: very_unlikely ());
3191 : }
3192 244 : if (op2 == const0_rtx)
3193 : {
3194 192 : rtx eq = gen_rtx_fmt_ee (UNEQ, VOIDmode,
3195 : gen_rtx_REG (CCFPmode, FLAGS_REG), const0_rtx);
3196 192 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, eq,
3197 : gen_rtx_LABEL_REF (VOIDmode, l0), pc_rtx);
3198 192 : jmp = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
3199 192 : add_reg_br_prob_note (jmp, profile_probability::unlikely ());
3200 192 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, gt,
3201 : gen_rtx_LABEL_REF (VOIDmode, l1), pc_rtx);
3202 192 : jmp = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
3203 192 : add_reg_br_prob_note (jmp, profile_probability::even ());
3204 192 : emit_move_insn (dest, constm1_rtx);
3205 192 : emit_jump (lend);
3206 192 : emit_label (l0);
3207 192 : emit_move_insn (dest, const0_rtx);
3208 192 : emit_jump (lend);
3209 192 : emit_label (l1);
3210 192 : emit_move_insn (dest, const1_rtx);
3211 : }
3212 : else
3213 : {
3214 52 : rtx lt_tmp = NULL_RTX;
3215 52 : if (GET_MODE (dest) != SImode || !TARGET_ZERO_EXTEND_WITH_AND)
3216 : {
3217 52 : lt_tmp = gen_reg_rtx (QImode);
3218 52 : ix86_expand_setcc (lt_tmp, UNLT, gen_rtx_REG (CCFPmode, FLAGS_REG),
3219 : const0_rtx);
3220 52 : if (GET_MODE (dest) != QImode)
3221 : {
3222 52 : tmp = gen_reg_rtx (GET_MODE (dest));
3223 52 : emit_insn (gen_rtx_SET (tmp,
3224 : gen_rtx_ZERO_EXTEND (GET_MODE (dest),
3225 : lt_tmp)));
3226 52 : lt_tmp = tmp;
3227 : }
3228 : }
3229 52 : rtx gt_tmp;
3230 52 : if (zero)
3231 : {
3232 : /* If TARGET_IEEE_FP and dest has SImode, emit SImode clear
3233 : before the floating point comparison and use setcc_si_slp
3234 : pattern to hide it from the combiner, so that it doesn't
3235 : undo it. Similarly for TARGET_ZERO_EXTEND_WITH_AND, where
3236 : the ZERO_EXTEND normally emitted would need to be AND
3237 : with flags clobber. */
3238 34 : tmp = ix86_expand_compare (GT, XEXP (gt, 0), const0_rtx);
3239 34 : PUT_MODE (tmp, QImode);
3240 34 : emit_insn (gen_setcc_si_slp (zero, tmp, zero));
3241 34 : gt_tmp = zero;
3242 : }
3243 : else
3244 : {
3245 18 : gt_tmp = gen_reg_rtx (QImode);
3246 18 : ix86_expand_setcc (gt_tmp, GT, XEXP (gt, 0), const0_rtx);
3247 18 : if (GET_MODE (dest) != QImode)
3248 : {
3249 18 : tmp = gen_reg_rtx (GET_MODE (dest));
3250 18 : emit_insn (gen_rtx_SET (tmp,
3251 : gen_rtx_ZERO_EXTEND (GET_MODE (dest),
3252 : gt_tmp)));
3253 18 : gt_tmp = tmp;
3254 : }
3255 : }
3256 52 : if (lt_tmp)
3257 : {
3258 52 : tmp = expand_simple_binop (GET_MODE (dest), MINUS, gt_tmp, lt_tmp,
3259 : dest, 0, OPTAB_DIRECT);
3260 52 : if (!rtx_equal_p (tmp, dest))
3261 0 : emit_move_insn (dest, tmp);
3262 : }
3263 : else
3264 : {
3265 : /* For TARGET_ZERO_EXTEND_WITH_AND emit sbb directly, as we can't
3266 : do ZERO_EXTEND without clobbering flags. */
3267 0 : tmp = ix86_expand_compare (UNLT, XEXP (gt, 0), const0_rtx);
3268 0 : PUT_MODE (tmp, SImode);
3269 0 : emit_insn (gen_subsi3_carry (dest, gt_tmp,
3270 0 : force_reg (GET_MODE (dest), const0_rtx),
3271 : XEXP (gt, 0), tmp));
3272 : }
3273 : }
3274 244 : emit_jump (lend);
3275 244 : if (l2)
3276 : {
3277 207 : emit_label (l2);
3278 207 : emit_move_insn (dest, op2 == const0_rtx ? GEN_INT (-128) : op2);
3279 : }
3280 244 : emit_label (lend);
3281 244 : }
3282 :
3283 : /* Expand integral op0 <=> op1, i.e.
3284 : dest = op0 == op1 ? 0 : op0 < op1 ? -1 : 1. */
3285 :
3286 : void
3287 164 : ix86_expand_int_spaceship (rtx dest, rtx op0, rtx op1, rtx op2)
3288 : {
3289 164 : gcc_assert (INTVAL (op2));
3290 164 : rtx zero1 = NULL_RTX, zero2 = NULL_RTX;
3291 164 : if (TARGET_ZERO_EXTEND_WITH_AND && GET_MODE (dest) == SImode)
3292 : {
3293 0 : zero1 = force_reg (SImode, const0_rtx);
3294 0 : if (INTVAL (op2) != 1)
3295 0 : zero2 = force_reg (SImode, const0_rtx);
3296 : }
3297 :
3298 : /* Not using ix86_expand_int_compare here, so that it doesn't swap
3299 : operands nor optimize CC mode - we need a mode usable for both
3300 : LT and GT resp. LTU and GTU comparisons with the same unswapped
3301 : operands. */
3302 204 : rtx flags = gen_rtx_REG (INTVAL (op2) != 1 ? CCGCmode : CCmode, FLAGS_REG);
3303 164 : rtx tmp = gen_rtx_COMPARE (GET_MODE (flags), op0, op1);
3304 164 : emit_insn (gen_rtx_SET (flags, tmp));
3305 164 : rtx lt_tmp = NULL_RTX;
3306 164 : if (zero2)
3307 : {
3308 : /* For TARGET_ZERO_EXTEND_WITH_AND, emit setcc_si_slp to avoid
3309 : ZERO_EXTEND. */
3310 0 : tmp = ix86_expand_compare (LT, flags, const0_rtx);
3311 0 : PUT_MODE (tmp, QImode);
3312 0 : emit_insn (gen_setcc_si_slp (zero2, tmp, zero2));
3313 0 : lt_tmp = zero2;
3314 : }
3315 164 : else if (!zero1)
3316 : {
3317 164 : lt_tmp = gen_reg_rtx (QImode);
3318 204 : ix86_expand_setcc (lt_tmp, INTVAL (op2) != 1 ? LT : LTU, flags,
3319 : const0_rtx);
3320 164 : if (GET_MODE (dest) != QImode)
3321 : {
3322 164 : tmp = gen_reg_rtx (GET_MODE (dest));
3323 164 : emit_insn (gen_rtx_SET (tmp, gen_rtx_ZERO_EXTEND (GET_MODE (dest),
3324 : lt_tmp)));
3325 164 : lt_tmp = tmp;
3326 : }
3327 : }
3328 164 : rtx gt_tmp;
3329 164 : if (zero1)
3330 : {
3331 : /* For TARGET_ZERO_EXTEND_WITH_AND, emit setcc_si_slp to avoid
3332 : ZERO_EXTEND. */
3333 0 : tmp = ix86_expand_compare (INTVAL (op2) != 1 ? GT : GTU, flags,
3334 : const0_rtx);
3335 0 : PUT_MODE (tmp, QImode);
3336 0 : emit_insn (gen_setcc_si_slp (zero1, tmp, zero1));
3337 0 : gt_tmp = zero1;
3338 : }
3339 : else
3340 : {
3341 164 : gt_tmp = gen_reg_rtx (QImode);
3342 204 : ix86_expand_setcc (gt_tmp, INTVAL (op2) != 1 ? GT : GTU, flags,
3343 : const0_rtx);
3344 164 : if (GET_MODE (dest) != QImode)
3345 : {
3346 164 : tmp = gen_reg_rtx (GET_MODE (dest));
3347 164 : emit_insn (gen_rtx_SET (tmp, gen_rtx_ZERO_EXTEND (GET_MODE (dest),
3348 : gt_tmp)));
3349 164 : gt_tmp = tmp;
3350 : }
3351 : }
3352 164 : if (lt_tmp)
3353 : {
3354 164 : tmp = expand_simple_binop (GET_MODE (dest), MINUS, gt_tmp, lt_tmp, dest,
3355 : 0, OPTAB_DIRECT);
3356 164 : if (!rtx_equal_p (tmp, dest))
3357 0 : emit_move_insn (dest, tmp);
3358 : }
3359 : else
3360 : {
3361 : /* For TARGET_ZERO_EXTEND_WITH_AND emit sbb directly, as we can't
3362 : do ZERO_EXTEND without clobbering flags. */
3363 0 : tmp = ix86_expand_compare (LTU, flags, const0_rtx);
3364 0 : PUT_MODE (tmp, SImode);
3365 0 : emit_insn (gen_subsi3_carry (dest, gt_tmp,
3366 0 : force_reg (GET_MODE (dest), const0_rtx),
3367 : flags, tmp));
3368 : }
3369 164 : }
3370 :
3371 : /* Expand comparison setting or clearing carry flag. Return true when
3372 : successful and set pop for the operation. */
3373 : static bool
3374 25401 : ix86_expand_carry_flag_compare (enum rtx_code code, rtx op0, rtx op1, rtx *pop)
3375 : {
3376 50802 : machine_mode mode
3377 25401 : = GET_MODE (op0) != VOIDmode ? GET_MODE (op0) : GET_MODE (op1);
3378 :
3379 : /* Do not handle double-mode compares that go through special path. */
3380 27366 : if (mode == (TARGET_64BIT ? TImode : DImode))
3381 : return false;
3382 :
3383 25391 : if (SCALAR_FLOAT_MODE_P (mode))
3384 : {
3385 1828 : rtx compare_op;
3386 1828 : rtx_insn *compare_seq;
3387 :
3388 1828 : gcc_assert (!DECIMAL_FLOAT_MODE_P (mode));
3389 :
3390 : /* Shortcut: following common codes never translate
3391 : into carry flag compares. */
3392 1828 : if (code == EQ || code == NE || code == UNEQ || code == LTGT
3393 : || code == ORDERED || code == UNORDERED)
3394 : return false;
3395 :
3396 : /* These comparisons require zero flag; swap operands so they won't. */
3397 : if ((code == GT || code == UNLE || code == LE || code == UNGT)
3398 1759 : && !TARGET_IEEE_FP)
3399 : {
3400 2 : std::swap (op0, op1);
3401 2 : code = swap_condition (code);
3402 : }
3403 :
3404 : /* Try to expand the comparison and verify that we end up with
3405 : carry flag based comparison. This fails to be true only when
3406 : we decide to expand comparison using arithmetic that is not
3407 : too common scenario. */
3408 1826 : start_sequence ();
3409 1826 : compare_op = ix86_expand_fp_compare (code, op0, op1);
3410 1826 : compare_seq = end_sequence ();
3411 :
3412 1826 : if (GET_MODE (XEXP (compare_op, 0)) == CCFPmode)
3413 1826 : code = ix86_fp_compare_code_to_integer (GET_CODE (compare_op));
3414 : else
3415 0 : code = GET_CODE (compare_op);
3416 :
3417 1826 : if (code != LTU && code != GEU)
3418 : return false;
3419 :
3420 67 : emit_insn (compare_seq);
3421 67 : *pop = compare_op;
3422 67 : return true;
3423 : }
3424 :
3425 23563 : if (!INTEGRAL_MODE_P (mode))
3426 : return false;
3427 :
3428 23492 : switch (code)
3429 : {
3430 : case LTU:
3431 : case GEU:
3432 : break;
3433 :
3434 : /* Convert a==0 into (unsigned)a<1. */
3435 19580 : case EQ:
3436 19580 : case NE:
3437 19580 : if (op1 != const0_rtx)
3438 : return false;
3439 10010 : op1 = const1_rtx;
3440 10010 : code = (code == EQ ? LTU : GEU);
3441 : break;
3442 :
3443 : /* Convert a>b into b<a or a>=b-1. */
3444 779 : case GTU:
3445 779 : case LEU:
3446 779 : if (CONST_INT_P (op1))
3447 : {
3448 741 : op1 = gen_int_mode (INTVAL (op1) + 1, GET_MODE (op0));
3449 : /* Bail out on overflow. We still can swap operands but that
3450 : would force loading of the constant into register. */
3451 741 : if (op1 == const0_rtx
3452 741 : || !x86_64_immediate_operand (op1, GET_MODE (op1)))
3453 0 : return false;
3454 741 : code = (code == GTU ? GEU : LTU);
3455 : }
3456 : else
3457 : {
3458 38 : std::swap (op0, op1);
3459 38 : code = (code == GTU ? LTU : GEU);
3460 : }
3461 : break;
3462 :
3463 : /* Convert a>=0 into (unsigned)a<0x80000000. */
3464 1468 : case LT:
3465 1468 : case GE:
3466 1468 : if (mode == DImode || op1 != const0_rtx)
3467 : return false;
3468 204 : op1 = gen_int_mode (1 << (GET_MODE_BITSIZE (mode) - 1), mode);
3469 102 : code = (code == LT ? GEU : LTU);
3470 : break;
3471 965 : case LE:
3472 965 : case GT:
3473 965 : if (mode == DImode || op1 != constm1_rtx)
3474 : return false;
3475 0 : op1 = gen_int_mode (1 << (GET_MODE_BITSIZE (mode) - 1), mode);
3476 0 : code = (code == LE ? GEU : LTU);
3477 : break;
3478 :
3479 : default:
3480 : return false;
3481 : }
3482 : /* Swapping operands may cause constant to appear as first operand. */
3483 11591 : if (!nonimmediate_operand (op0, VOIDmode))
3484 : {
3485 0 : if (!can_create_pseudo_p ())
3486 : return false;
3487 0 : op0 = force_reg (mode, op0);
3488 : }
3489 11591 : *pop = ix86_expand_compare (code, op0, op1);
3490 11591 : gcc_assert (GET_CODE (*pop) == LTU || GET_CODE (*pop) == GEU);
3491 : return true;
3492 : }
3493 :
3494 : /* Expand conditional increment or decrement using adb/sbb instructions.
3495 : The default case using setcc followed by the conditional move can be
3496 : done by generic code. */
3497 : bool
3498 6602 : ix86_expand_int_addcc (rtx operands[])
3499 : {
3500 6602 : enum rtx_code code = GET_CODE (operands[1]);
3501 6602 : rtx flags;
3502 6602 : rtx (*insn) (machine_mode, rtx, rtx, rtx, rtx, rtx);
3503 6602 : rtx compare_op;
3504 6602 : rtx val = const0_rtx;
3505 6602 : bool fpcmp = false;
3506 6602 : machine_mode mode;
3507 6602 : rtx op0 = XEXP (operands[1], 0);
3508 6602 : rtx op1 = XEXP (operands[1], 1);
3509 :
3510 6602 : if (operands[3] != const1_rtx
3511 2912 : && operands[3] != constm1_rtx)
3512 : return false;
3513 4422 : if (!ix86_expand_carry_flag_compare (code, op0, op1, &compare_op))
3514 : return false;
3515 1281 : code = GET_CODE (compare_op);
3516 :
3517 1281 : flags = XEXP (compare_op, 0);
3518 :
3519 1281 : if (GET_MODE (flags) == CCFPmode)
3520 : {
3521 8 : fpcmp = true;
3522 8 : code = ix86_fp_compare_code_to_integer (code);
3523 : }
3524 :
3525 1281 : if (code != LTU)
3526 : {
3527 739 : val = constm1_rtx;
3528 739 : if (fpcmp)
3529 8 : PUT_CODE (compare_op,
3530 : reverse_condition_maybe_unordered
3531 : (GET_CODE (compare_op)));
3532 : else
3533 731 : PUT_CODE (compare_op, reverse_condition (GET_CODE (compare_op)));
3534 : }
3535 :
3536 1281 : mode = GET_MODE (operands[0]);
3537 :
3538 : /* Construct either adc or sbb insn. */
3539 1281 : if ((code == LTU) == (operands[3] == constm1_rtx))
3540 : insn = gen_sub3_carry;
3541 : else
3542 520 : insn = gen_add3_carry;
3543 :
3544 1281 : emit_insn (insn (mode, operands[0], operands[2], val, flags, compare_op));
3545 :
3546 1281 : return true;
3547 : }
3548 :
3549 : bool
3550 425687 : ix86_expand_int_movcc (rtx operands[])
3551 : {
3552 425687 : enum rtx_code code = GET_CODE (operands[1]), compare_code;
3553 425687 : rtx_insn *compare_seq;
3554 425687 : rtx compare_op;
3555 425687 : machine_mode mode = GET_MODE (operands[0]);
3556 425687 : bool sign_bit_compare_p = false;
3557 425687 : bool negate_cc_compare_p = false;
3558 425687 : rtx op0 = XEXP (operands[1], 0);
3559 425687 : rtx op1 = XEXP (operands[1], 1);
3560 425687 : rtx op2 = operands[2];
3561 425687 : rtx op3 = operands[3];
3562 :
3563 425687 : if (GET_MODE (op0) == TImode
3564 410253 : || (GET_MODE (op0) == DImode
3565 105109 : && !TARGET_64BIT))
3566 : return false;
3567 :
3568 409201 : if (GET_MODE (op0) == BFmode
3569 409201 : && !ix86_fp_comparison_operator (operands[1], VOIDmode))
3570 : return false;
3571 :
3572 409201 : start_sequence ();
3573 409201 : compare_op = ix86_expand_compare (code, op0, op1);
3574 409201 : compare_seq = end_sequence ();
3575 :
3576 409201 : compare_code = GET_CODE (compare_op);
3577 :
3578 409201 : if ((op1 == const0_rtx && (code == GE || code == LT))
3579 368352 : || (op1 == constm1_rtx && (code == GT || code == LE)))
3580 : sign_bit_compare_p = true;
3581 :
3582 : /* op0 == op1 ? op0 : op3 is equivalent to op0 == op1 ? op1 : op3,
3583 : but if op1 is a constant, the latter form allows more optimizations,
3584 : either through the last 2 ops being constant handling, or the one
3585 : constant and one variable cases. On the other side, for cmov the
3586 : former might be better as we don't need to load the constant into
3587 : another register. */
3588 368352 : if (code == EQ && CONST_INT_P (op1) && rtx_equal_p (op0, op2))
3589 : op2 = op1;
3590 : /* Similarly for op0 != op1 ? op2 : op0 and op0 != op1 ? op2 : op1. */
3591 408693 : else if (code == NE && CONST_INT_P (op1) && rtx_equal_p (op0, op3))
3592 : op3 = op1;
3593 :
3594 : /* Don't attempt mode expansion here -- if we had to expand 5 or 6
3595 : HImode insns, we'd be swallowed in word prefix ops. */
3596 :
3597 4889 : if ((mode != HImode || TARGET_FAST_PREFIX)
3598 437678 : && (mode != (TARGET_64BIT ? TImode : DImode))
3599 409201 : && CONST_INT_P (op2)
3600 437702 : && CONST_INT_P (op3))
3601 : {
3602 21756 : rtx out = operands[0];
3603 21756 : HOST_WIDE_INT ct = INTVAL (op2);
3604 21756 : HOST_WIDE_INT cf = INTVAL (op3);
3605 21756 : HOST_WIDE_INT diff;
3606 :
3607 21756 : if ((mode == SImode
3608 7828 : || (TARGET_64BIT && mode == DImode))
3609 18379 : && (GET_MODE (op0) == SImode
3610 14292 : || (TARGET_64BIT && GET_MODE (op0) == DImode)))
3611 : {
3612 : /* Special case x != 0 ? -1 : y. */
3613 13725 : if (code == NE && op1 == const0_rtx && ct == -1)
3614 : {
3615 : negate_cc_compare_p = true;
3616 : std::swap (ct, cf);
3617 : code = EQ;
3618 : }
3619 13607 : else if (code == EQ && op1 == const0_rtx && cf == -1)
3620 21756 : negate_cc_compare_p = true;
3621 : }
3622 :
3623 21756 : diff = (unsigned HOST_WIDE_INT) ct - cf;
3624 : /* Make sure we can represent the difference between the two values. */
3625 21756 : if ((diff > 0) != ((cf < 0) != (ct < 0) ? cf < 0 : cf < ct))
3626 425687 : return false;
3627 :
3628 : /* Sign bit compares are better done using shifts than we do by using
3629 : sbb. */
3630 21678 : if (sign_bit_compare_p
3631 21678 : || negate_cc_compare_p
3632 21678 : || ix86_expand_carry_flag_compare (code, op0, op1, &compare_op))
3633 : {
3634 : /* Detect overlap between destination and compare sources. */
3635 11076 : rtx tmp = out;
3636 :
3637 11076 : if (negate_cc_compare_p)
3638 : {
3639 296 : if (GET_MODE (op0) == DImode)
3640 120 : emit_insn (gen_x86_negdi_ccc (gen_reg_rtx (DImode), op0));
3641 : else
3642 176 : emit_insn (gen_x86_negsi_ccc (gen_reg_rtx (SImode),
3643 176 : gen_lowpart (SImode, op0)));
3644 :
3645 296 : tmp = gen_reg_rtx (mode);
3646 296 : if (mode == DImode)
3647 139 : emit_insn (gen_x86_movdicc_0_m1_neg (tmp));
3648 : else
3649 157 : emit_insn (gen_x86_movsicc_0_m1_neg (gen_lowpart (SImode,
3650 : tmp)));
3651 : }
3652 10780 : else if (!sign_bit_compare_p)
3653 : {
3654 10377 : rtx flags;
3655 10377 : bool fpcmp = false;
3656 :
3657 10377 : compare_code = GET_CODE (compare_op);
3658 :
3659 10377 : flags = XEXP (compare_op, 0);
3660 :
3661 10377 : if (GET_MODE (flags) == CCFPmode)
3662 : {
3663 59 : fpcmp = true;
3664 59 : compare_code
3665 59 : = ix86_fp_compare_code_to_integer (compare_code);
3666 : }
3667 :
3668 : /* To simplify rest of code, restrict to the GEU case. */
3669 10377 : if (compare_code == LTU)
3670 : {
3671 6237 : std::swap (ct, cf);
3672 6237 : compare_code = reverse_condition (compare_code);
3673 6237 : code = reverse_condition (code);
3674 : }
3675 : else
3676 : {
3677 4140 : if (fpcmp)
3678 59 : PUT_CODE (compare_op,
3679 : reverse_condition_maybe_unordered
3680 : (GET_CODE (compare_op)));
3681 : else
3682 4081 : PUT_CODE (compare_op,
3683 : reverse_condition (GET_CODE (compare_op)));
3684 : }
3685 :
3686 10377 : diff = (unsigned HOST_WIDE_INT) ct - cf;
3687 : /* Make sure we can represent the difference
3688 : between the two values. */
3689 10377 : if ((diff > 0) != ((cf < 0) != (ct < 0) ? cf < 0 : cf < ct))
3690 : return false;
3691 :
3692 10376 : if (reg_overlap_mentioned_p (out, compare_op))
3693 0 : tmp = gen_reg_rtx (mode);
3694 :
3695 10376 : if (mode == DImode)
3696 1833 : emit_insn (gen_x86_movdicc_0_m1 (tmp, flags, compare_op));
3697 : else
3698 8543 : emit_insn (gen_x86_movsicc_0_m1 (gen_lowpart (SImode, tmp),
3699 : flags, compare_op));
3700 : }
3701 : else
3702 : {
3703 403 : if (code == GT || code == GE)
3704 171 : code = reverse_condition (code);
3705 : else
3706 : {
3707 232 : std::swap (ct, cf);
3708 :
3709 232 : diff = (unsigned HOST_WIDE_INT) ct - cf;
3710 : /* Make sure we can represent the difference
3711 : between the two values. */
3712 232 : if ((diff > 0) != ((cf < 0) != (ct < 0) ? cf < 0 : cf < ct))
3713 : return false;
3714 : }
3715 400 : tmp = emit_store_flag (tmp, code, op0, op1, VOIDmode, 0, -1);
3716 : }
3717 :
3718 11072 : if (diff == 1)
3719 : {
3720 : /*
3721 : * cmpl op0,op1
3722 : * sbbl dest,dest
3723 : * [addl dest, ct]
3724 : *
3725 : * Size 5 - 8.
3726 : */
3727 795 : if (ct)
3728 635 : tmp = expand_simple_binop (mode, PLUS,
3729 : tmp, GEN_INT (ct),
3730 : copy_rtx (tmp), 1, OPTAB_DIRECT);
3731 : }
3732 10277 : else if (cf == -1)
3733 : {
3734 : /*
3735 : * cmpl op0,op1
3736 : * sbbl dest,dest
3737 : * orl $ct, dest
3738 : *
3739 : * Size 8.
3740 : */
3741 684 : tmp = expand_simple_binop (mode, IOR,
3742 : tmp, GEN_INT (ct),
3743 : copy_rtx (tmp), 1, OPTAB_DIRECT);
3744 : }
3745 9593 : else if (diff == -1 && ct)
3746 : {
3747 : /*
3748 : * cmpl op0,op1
3749 : * sbbl dest,dest
3750 : * notl dest
3751 : * [addl dest, cf]
3752 : *
3753 : * Size 8 - 11.
3754 : */
3755 486 : tmp = expand_simple_unop (mode, NOT, tmp, copy_rtx (tmp), 1);
3756 486 : if (cf)
3757 468 : tmp = expand_simple_binop (mode, PLUS,
3758 : copy_rtx (tmp), GEN_INT (cf),
3759 : copy_rtx (tmp), 1, OPTAB_DIRECT);
3760 : }
3761 : else
3762 : {
3763 : /*
3764 : * cmpl op0,op1
3765 : * sbbl dest,dest
3766 : * [notl dest]
3767 : * andl cf - ct, dest
3768 : * [addl dest, ct]
3769 : *
3770 : * Size 8 - 11.
3771 : */
3772 :
3773 9107 : if (cf == 0)
3774 : {
3775 872 : cf = ct;
3776 872 : ct = 0;
3777 872 : tmp = expand_simple_unop (mode, NOT, tmp, copy_rtx (tmp), 1);
3778 : }
3779 :
3780 9107 : HOST_WIDE_INT ival = (unsigned HOST_WIDE_INT) cf - ct;
3781 : /* Make sure we can represent the difference
3782 : between the two values. */
3783 9107 : if ((ival > 0) != ((ct < 0) != (cf < 0) ? ct < 0 : ct < cf))
3784 16568 : return false;
3785 :
3786 9107 : tmp = expand_simple_binop (mode, AND,
3787 : copy_rtx (tmp),
3788 9107 : gen_int_mode (ival, mode),
3789 : copy_rtx (tmp), 1, OPTAB_DIRECT);
3790 9107 : if (ct)
3791 7384 : tmp = expand_simple_binop (mode, PLUS,
3792 : copy_rtx (tmp), GEN_INT (ct),
3793 : copy_rtx (tmp), 1, OPTAB_DIRECT);
3794 : }
3795 :
3796 11072 : if (!rtx_equal_p (tmp, out))
3797 491 : emit_move_insn (copy_rtx (out), copy_rtx (tmp));
3798 :
3799 11072 : return true;
3800 : }
3801 :
3802 10602 : if (diff < 0)
3803 : {
3804 2655 : machine_mode cmp_mode = GET_MODE (op0);
3805 2655 : enum rtx_code new_code;
3806 :
3807 2655 : if (SCALAR_FLOAT_MODE_P (cmp_mode))
3808 : {
3809 55 : gcc_assert (!DECIMAL_FLOAT_MODE_P (cmp_mode));
3810 :
3811 : /* We may be reversing a non-trapping
3812 : comparison to a trapping comparison. */
3813 106 : if (HONOR_NANS (cmp_mode) && flag_trapping_math
3814 48 : && code != EQ && code != NE
3815 103 : && code != ORDERED && code != UNORDERED)
3816 : new_code = UNKNOWN;
3817 : else
3818 7 : new_code = reverse_condition_maybe_unordered (code);
3819 : }
3820 : else
3821 2600 : new_code = ix86_reverse_condition (code, cmp_mode);
3822 2607 : if (new_code != UNKNOWN)
3823 : {
3824 2607 : std::swap (ct, cf);
3825 :
3826 2607 : diff = (unsigned HOST_WIDE_INT) ct - cf;
3827 : /* Make sure we can represent the difference
3828 : between the two values. */
3829 2607 : if ((diff > 0) != ((cf < 0) != (ct < 0) ? cf < 0 : cf < ct))
3830 : return false;
3831 :
3832 : code = new_code;
3833 : }
3834 : }
3835 :
3836 10602 : compare_code = UNKNOWN;
3837 10602 : if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT
3838 8916 : && CONST_INT_P (op1))
3839 : {
3840 2869 : if (op1 == const0_rtx
3841 209 : && (code == LT || code == GE))
3842 : compare_code = code;
3843 2869 : else if (op1 == constm1_rtx)
3844 : {
3845 86 : if (code == LE)
3846 : compare_code = LT;
3847 86 : else if (code == GT)
3848 : compare_code = GE;
3849 : }
3850 : }
3851 :
3852 : /* Optimize dest = (op0 < 0) ? -1 : cf. */
3853 : if (compare_code != UNKNOWN
3854 0 : && GET_MODE (op0) == GET_MODE (out)
3855 0 : && (cf == -1 || ct == -1))
3856 : {
3857 : /* If lea code below could be used, only optimize
3858 : if it results in a 2 insn sequence. */
3859 :
3860 0 : if (! (diff == 1 || diff == 2 || diff == 4 || diff == 8
3861 0 : || diff == 3 || diff == 5 || diff == 9)
3862 0 : || (compare_code == LT && ct == -1)
3863 0 : || (compare_code == GE && cf == -1))
3864 : {
3865 : /*
3866 : * notl op1 (if necessary)
3867 : * sarl $31, op1
3868 : * orl cf, op1
3869 : */
3870 0 : if (ct != -1)
3871 : {
3872 0 : cf = ct;
3873 0 : ct = -1;
3874 0 : code = reverse_condition (code);
3875 : }
3876 :
3877 0 : out = emit_store_flag (out, code, op0, op1, VOIDmode, 0, -1);
3878 :
3879 0 : out = expand_simple_binop (mode, IOR,
3880 : out, GEN_INT (cf),
3881 : out, 1, OPTAB_DIRECT);
3882 0 : if (out != operands[0])
3883 0 : emit_move_insn (operands[0], out);
3884 :
3885 0 : return true;
3886 : }
3887 : }
3888 :
3889 :
3890 13865 : if ((diff == 1 || diff == 2 || diff == 4 || diff == 8
3891 3263 : || diff == 3 || diff == 5 || diff == 9)
3892 7705 : && ((mode != QImode && mode != HImode) || !TARGET_PARTIAL_REG_STALL)
3893 18307 : && (mode != DImode
3894 1828 : || x86_64_immediate_operand (GEN_INT (cf), VOIDmode)))
3895 : {
3896 : /*
3897 : * xorl dest,dest
3898 : * cmpl op1,op2
3899 : * setcc dest
3900 : * lea cf(dest*(ct-cf)),dest
3901 : *
3902 : * Size 14.
3903 : *
3904 : * This also catches the degenerate setcc-only case.
3905 : */
3906 :
3907 7705 : rtx tmp;
3908 7705 : int nops;
3909 :
3910 7705 : out = emit_store_flag (out, code, op0, op1, VOIDmode, 0, 1);
3911 :
3912 7705 : nops = 0;
3913 : /* On x86_64 the lea instruction operates on Pmode, so we need
3914 : to get arithmetics done in proper mode to match. */
3915 7705 : if (diff == 1)
3916 6544 : tmp = copy_rtx (out);
3917 : else
3918 : {
3919 1161 : rtx out1;
3920 1161 : out1 = copy_rtx (out);
3921 1161 : tmp = gen_rtx_MULT (mode, out1, GEN_INT (diff & ~1));
3922 1161 : nops++;
3923 1161 : if (diff & 1)
3924 : {
3925 260 : tmp = gen_rtx_PLUS (mode, tmp, out1);
3926 260 : nops++;
3927 : }
3928 : }
3929 7705 : if (cf != 0)
3930 : {
3931 6972 : tmp = plus_constant (mode, tmp, cf);
3932 6972 : nops++;
3933 : }
3934 7705 : if (!rtx_equal_p (tmp, out))
3935 : {
3936 7210 : if (nops == 1)
3937 6145 : out = force_operand (tmp, copy_rtx (out));
3938 : else
3939 1065 : emit_insn (gen_rtx_SET (copy_rtx (out), copy_rtx (tmp)));
3940 : }
3941 7705 : if (!rtx_equal_p (out, operands[0]))
3942 657 : emit_move_insn (operands[0], copy_rtx (out));
3943 :
3944 7705 : return true;
3945 : }
3946 :
3947 : /*
3948 : * General case: Jumpful:
3949 : * xorl dest,dest cmpl op1, op2
3950 : * cmpl op1, op2 movl ct, dest
3951 : * setcc dest jcc 1f
3952 : * decl dest movl cf, dest
3953 : * andl (cf-ct),dest 1:
3954 : * addl ct,dest
3955 : *
3956 : * Size 20. Size 14.
3957 : *
3958 : * This is reasonably steep, but branch mispredict costs are
3959 : * high on modern cpus, so consider failing only if optimizing
3960 : * for space.
3961 : */
3962 :
3963 2897 : if ((!TARGET_CMOVE || (mode == QImode && TARGET_PARTIAL_REG_STALL))
3964 2897 : && BRANCH_COST (optimize_insn_for_speed_p (),
3965 : false) >= 2)
3966 : {
3967 0 : if (cf == 0)
3968 : {
3969 0 : machine_mode cmp_mode = GET_MODE (op0);
3970 0 : enum rtx_code new_code;
3971 :
3972 0 : if (SCALAR_FLOAT_MODE_P (cmp_mode))
3973 : {
3974 0 : gcc_assert (!DECIMAL_FLOAT_MODE_P (cmp_mode));
3975 :
3976 : /* We may be reversing a non-trapping
3977 : comparison to a trapping comparison. */
3978 0 : if (HONOR_NANS (cmp_mode) && flag_trapping_math
3979 0 : && code != EQ && code != NE
3980 0 : && code != ORDERED && code != UNORDERED)
3981 : new_code = UNKNOWN;
3982 : else
3983 0 : new_code = reverse_condition_maybe_unordered (code);
3984 :
3985 : }
3986 : else
3987 : {
3988 0 : new_code = ix86_reverse_condition (code, cmp_mode);
3989 0 : if (compare_code != UNKNOWN && new_code != UNKNOWN)
3990 0 : compare_code = reverse_condition (compare_code);
3991 : }
3992 :
3993 0 : if (new_code != UNKNOWN)
3994 : {
3995 0 : cf = ct;
3996 0 : ct = 0;
3997 0 : code = new_code;
3998 : }
3999 : }
4000 :
4001 0 : if (compare_code != UNKNOWN)
4002 : {
4003 : /* notl op1 (if needed)
4004 : sarl $31, op1
4005 : andl (cf-ct), op1
4006 : addl ct, op1
4007 :
4008 : For x < 0 (resp. x <= -1) there will be no notl,
4009 : so if possible swap the constants to get rid of the
4010 : complement.
4011 : True/false will be -1/0 while code below (store flag
4012 : followed by decrement) is 0/-1, so the constants need
4013 : to be exchanged once more. */
4014 :
4015 0 : if (compare_code == GE || !cf)
4016 : {
4017 0 : code = reverse_condition (code);
4018 0 : compare_code = LT;
4019 : }
4020 : else
4021 : std::swap (ct, cf);
4022 :
4023 0 : out = emit_store_flag (out, code, op0, op1, VOIDmode, 0, -1);
4024 : }
4025 : else
4026 : {
4027 0 : out = emit_store_flag (out, code, op0, op1, VOIDmode, 0, 1);
4028 :
4029 0 : out = expand_simple_binop (mode, PLUS, copy_rtx (out),
4030 : constm1_rtx,
4031 : copy_rtx (out), 1, OPTAB_DIRECT);
4032 : }
4033 :
4034 0 : HOST_WIDE_INT ival = (unsigned HOST_WIDE_INT) cf - ct;
4035 : /* Make sure we can represent the difference
4036 : between the two values. */
4037 0 : if ((ival > 0) != ((ct < 0) != (cf < 0) ? ct < 0 : ct < cf))
4038 : return false;
4039 :
4040 0 : out = expand_simple_binop (mode, AND, copy_rtx (out),
4041 0 : gen_int_mode (ival, mode),
4042 : copy_rtx (out), 1, OPTAB_DIRECT);
4043 0 : if (ct)
4044 0 : out = expand_simple_binop (mode, PLUS, copy_rtx (out), GEN_INT (ct),
4045 : copy_rtx (out), 1, OPTAB_DIRECT);
4046 0 : if (!rtx_equal_p (out, operands[0]))
4047 0 : emit_move_insn (operands[0], copy_rtx (out));
4048 :
4049 0 : return true;
4050 : }
4051 : }
4052 :
4053 390342 : if (!TARGET_CMOVE || (mode == QImode && TARGET_PARTIAL_REG_STALL))
4054 : {
4055 : /* Try a few things more with specific constants and a variable. */
4056 :
4057 0 : optab op;
4058 0 : rtx var, orig_out, out, tmp;
4059 :
4060 0 : if (BRANCH_COST (optimize_insn_for_speed_p (), false) <= 2)
4061 : return false;
4062 :
4063 0 : operands[2] = op2;
4064 0 : operands[3] = op3;
4065 :
4066 : /* If one of the two operands is an interesting constant, load a
4067 : constant with the above and mask it in with a logical operation. */
4068 :
4069 0 : if (CONST_INT_P (operands[2]))
4070 : {
4071 0 : var = operands[3];
4072 0 : if (INTVAL (operands[2]) == 0 && operands[3] != constm1_rtx)
4073 0 : operands[3] = constm1_rtx, op = and_optab;
4074 0 : else if (INTVAL (operands[2]) == -1 && operands[3] != const0_rtx)
4075 0 : operands[3] = const0_rtx, op = ior_optab;
4076 : else
4077 : return false;
4078 : }
4079 0 : else if (CONST_INT_P (operands[3]))
4080 : {
4081 0 : var = operands[2];
4082 0 : if (INTVAL (operands[3]) == 0 && operands[2] != constm1_rtx)
4083 : {
4084 : /* For smin (x, 0), expand as "x < 0 ? x : 0" instead of
4085 : "x <= 0 ? x : 0" to enable sign_bit_compare_p. */
4086 0 : if (code == LE && op1 == const0_rtx && rtx_equal_p (op0, var))
4087 0 : operands[1] = simplify_gen_relational (LT, VOIDmode,
4088 0 : GET_MODE (op0),
4089 : op0, const0_rtx);
4090 :
4091 0 : operands[2] = constm1_rtx;
4092 0 : op = and_optab;
4093 : }
4094 0 : else if (INTVAL (operands[3]) == -1 && operands[3] != const0_rtx)
4095 0 : operands[2] = const0_rtx, op = ior_optab;
4096 : else
4097 : return false;
4098 : }
4099 : else
4100 : return false;
4101 :
4102 0 : orig_out = operands[0];
4103 0 : tmp = gen_reg_rtx (mode);
4104 0 : operands[0] = tmp;
4105 :
4106 : /* Recurse to get the constant loaded. */
4107 0 : if (!ix86_expand_int_movcc (operands))
4108 : return false;
4109 :
4110 : /* Mask in the interesting variable. */
4111 0 : out = expand_binop (mode, op, var, tmp, orig_out, 0,
4112 : OPTAB_WIDEN);
4113 0 : if (!rtx_equal_p (out, orig_out))
4114 0 : emit_move_insn (copy_rtx (orig_out), copy_rtx (out));
4115 :
4116 0 : return true;
4117 : }
4118 :
4119 : /*
4120 : * For comparison with above,
4121 : *
4122 : * movl cf,dest
4123 : * movl ct,tmp
4124 : * cmpl op1,op2
4125 : * cmovcc tmp,dest
4126 : *
4127 : * Size 15.
4128 : */
4129 :
4130 390342 : if (! nonimmediate_operand (operands[2], mode))
4131 17038 : operands[2] = force_reg (mode, operands[2]);
4132 390342 : if (! nonimmediate_operand (operands[3], mode))
4133 166565 : operands[3] = force_reg (mode, operands[3]);
4134 :
4135 390342 : if (! register_operand (operands[2], VOIDmode)
4136 390342 : && (mode == QImode
4137 1093 : || ! register_operand (operands[3], VOIDmode)))
4138 1564 : operands[2] = force_reg (mode, operands[2]);
4139 :
4140 390342 : if (mode == QImode
4141 390342 : && ! register_operand (operands[3], VOIDmode))
4142 592 : operands[3] = force_reg (mode, operands[3]);
4143 :
4144 390342 : emit_insn (compare_seq);
4145 390342 : emit_insn (gen_rtx_SET (operands[0],
4146 : gen_rtx_IF_THEN_ELSE (mode,
4147 : compare_op, operands[2],
4148 : operands[3])));
4149 390342 : return true;
4150 : }
4151 :
4152 : /* Detect conditional moves that exactly match min/max operational
4153 : semantics. Note that this is IEEE safe, as long as we don't
4154 : interchange the operands.
4155 :
4156 : Returns FALSE if this conditional move doesn't match a MIN/MAX,
4157 : and TRUE if the operation is successful and instructions are emitted. */
4158 :
4159 : static bool
4160 9707 : ix86_expand_sse_fp_minmax (rtx dest, enum rtx_code code, rtx cmp_op0,
4161 : rtx cmp_op1, rtx if_true, rtx if_false)
4162 : {
4163 9707 : machine_mode mode = GET_MODE (dest);
4164 9707 : bool is_min;
4165 9707 : rtx tmp;
4166 :
4167 9707 : if (code == LT)
4168 : ;
4169 3230 : else if (code == LE && !HONOR_NANS (mode))
4170 : {
4171 : /* We can swap LE to GE and then invert to LT. */
4172 : std::swap (cmp_op0, cmp_op1);
4173 : std::swap (if_true, if_false);
4174 : }
4175 3189 : else if (code == UNGE)
4176 : std::swap (if_true, if_false);
4177 : else
4178 : return false;
4179 :
4180 8640 : if (rtx_equal_p (cmp_op0, if_true) && rtx_equal_p (cmp_op1, if_false))
4181 : is_min = true;
4182 4650 : else if (rtx_equal_p (cmp_op1, if_true) && rtx_equal_p (cmp_op0, if_false))
4183 : is_min = false;
4184 : else
4185 1051 : return false;
4186 :
4187 7589 : if (immediate_operand (if_false, mode))
4188 8 : if_false = force_reg (mode, if_false);
4189 7589 : if (immediate_operand (if_true, mode))
4190 0 : if_true = force_reg (mode, if_true);
4191 :
4192 : /* We want to check HONOR_NANS and HONOR_SIGNED_ZEROS here,
4193 : but MODE may be a vector mode and thus not appropriate. */
4194 7589 : if (!flag_finite_math_only || flag_signed_zeros)
4195 : {
4196 7589 : int u = is_min ? UNSPEC_IEEE_MIN : UNSPEC_IEEE_MAX;
4197 7589 : rtvec v;
4198 :
4199 7589 : if_true = force_reg (mode, if_true);
4200 7589 : v = gen_rtvec (2, if_true, if_false);
4201 7589 : tmp = gen_rtx_UNSPEC (mode, v, u);
4202 7589 : }
4203 : else
4204 : {
4205 0 : code = is_min ? SMIN : SMAX;
4206 0 : if (MEM_P (if_true) && MEM_P (if_false))
4207 0 : if_true = force_reg (mode, if_true);
4208 0 : tmp = gen_rtx_fmt_ee (code, mode, if_true, if_false);
4209 : }
4210 :
4211 7589 : emit_insn (gen_rtx_SET (dest, tmp));
4212 7589 : return true;
4213 : }
4214 :
4215 : /* Return true if MODE is valid for vector compare to mask register,
4216 : Same result for conditionl vector move with mask register. */
4217 : static bool
4218 15294 : ix86_valid_mask_cmp_mode (machine_mode mode)
4219 : {
4220 : /* XOP has its own vector conditional movement. */
4221 15294 : if (TARGET_XOP && !TARGET_AVX512F)
4222 : return false;
4223 :
4224 : /* HFmode only supports vcmpsh whose dest is mask register. */
4225 15288 : if (TARGET_AVX512FP16 && mode == HFmode)
4226 : return true;
4227 :
4228 : /* AVX512F is needed for mask operation. */
4229 15196 : if (!(TARGET_AVX512F && VECTOR_MODE_P (mode)))
4230 : return false;
4231 :
4232 : /* AVX512BW is needed for vector QI/HImode,
4233 : AVX512VL is needed for 128/256-bit vector. */
4234 182 : machine_mode inner_mode = GET_MODE_INNER (mode);
4235 182 : int vector_size = GET_MODE_SIZE (mode);
4236 182 : if ((inner_mode == QImode || inner_mode == HImode) && !TARGET_AVX512BW)
4237 : return false;
4238 :
4239 162 : return vector_size == 64 || TARGET_AVX512VL;
4240 : }
4241 :
4242 : /* Return true if integer mask comparison should be used. */
4243 : static bool
4244 56497 : ix86_use_mask_cmp_p (machine_mode mode, machine_mode cmp_mode,
4245 : rtx op_true, rtx op_false)
4246 : {
4247 56497 : int vector_size = GET_MODE_SIZE (mode);
4248 :
4249 56497 : if (cmp_mode == HFmode)
4250 : return true;
4251 56405 : else if (vector_size < 16)
4252 : return false;
4253 49617 : else if (vector_size == 64)
4254 : return true;
4255 99118 : else if (GET_MODE_INNER (cmp_mode) == HFmode)
4256 : return true;
4257 99118 : else if (GET_MODE_INNER (cmp_mode) == BFmode)
4258 : return true;
4259 :
4260 : /* When op_true is NULL, op_false must be NULL, or vice versa. */
4261 49559 : gcc_assert (!op_true == !op_false);
4262 :
4263 : /* When op_true/op_false is NULL or cmp_mode is not valid mask cmp mode,
4264 : vector dest is required. */
4265 49559 : if (!op_true || !ix86_valid_mask_cmp_mode (cmp_mode))
4266 : return false;
4267 :
4268 : /* Exclude those that could be optimized in ix86_expand_sse_movcc. */
4269 48 : if (op_false == CONST0_RTX (mode)
4270 48 : || op_true == CONST0_RTX (mode)
4271 48 : || (INTEGRAL_MODE_P (mode)
4272 40 : && (op_true == CONSTM1_RTX (mode)
4273 40 : || op_false == CONSTM1_RTX (mode))))
4274 0 : return false;
4275 :
4276 : return true;
4277 : }
4278 :
4279 : /* Expand an SSE comparison. Return the register with the result. */
4280 :
4281 : static rtx
4282 38232 : ix86_expand_sse_cmp (rtx dest, enum rtx_code code, rtx cmp_op0, rtx cmp_op1,
4283 : rtx op_true, rtx op_false)
4284 : {
4285 38232 : machine_mode mode = GET_MODE (dest);
4286 38232 : machine_mode cmp_ops_mode = GET_MODE (cmp_op0);
4287 :
4288 : /* In general case result of comparison can differ from operands' type. */
4289 38232 : machine_mode cmp_mode;
4290 :
4291 : /* In AVX512F the result of comparison is an integer mask. */
4292 38232 : bool maskcmp = false;
4293 38232 : rtx x;
4294 :
4295 38232 : if (ix86_use_mask_cmp_p (mode, cmp_ops_mode, op_true, op_false))
4296 : {
4297 145 : unsigned int nbits = GET_MODE_NUNITS (cmp_ops_mode);
4298 145 : maskcmp = true;
4299 145 : cmp_mode = nbits > 8 ? int_mode_for_size (nbits, 0).require () : E_QImode;
4300 : }
4301 : else
4302 : cmp_mode = cmp_ops_mode;
4303 :
4304 38232 : cmp_op0 = force_reg (cmp_ops_mode, cmp_op0);
4305 :
4306 76464 : bool (*op1_predicate)(rtx, machine_mode)
4307 38232 : = VECTOR_MODE_P (cmp_ops_mode) ? vector_operand : nonimmediate_operand;
4308 :
4309 38232 : if (!op1_predicate (cmp_op1, cmp_ops_mode))
4310 0 : cmp_op1 = force_reg (cmp_ops_mode, cmp_op1);
4311 :
4312 38232 : if (optimize
4313 503 : || (maskcmp && cmp_mode != mode)
4314 503 : || (op_true && reg_overlap_mentioned_p (dest, op_true))
4315 38735 : || (op_false && reg_overlap_mentioned_p (dest, op_false)))
4316 75313 : dest = gen_reg_rtx (maskcmp ? cmp_mode : mode);
4317 :
4318 38232 : if (maskcmp)
4319 : {
4320 145 : bool ok = ix86_expand_mask_vec_cmp (dest, code, cmp_op0, cmp_op1);
4321 145 : gcc_assert (ok);
4322 : return dest;
4323 : }
4324 :
4325 38087 : x = gen_rtx_fmt_ee (code, cmp_mode, cmp_op0, cmp_op1);
4326 :
4327 38087 : if (cmp_mode != mode)
4328 : {
4329 7987 : x = force_reg (cmp_ops_mode, x);
4330 7987 : convert_move (dest, x, false);
4331 : }
4332 : else
4333 30100 : emit_insn (gen_rtx_SET (dest, x));
4334 :
4335 : return dest;
4336 : }
4337 :
4338 : /* Emit x86 binary operand CODE in mode MODE for SSE vector
4339 : instructions that can be performed using GP registers. */
4340 :
4341 : static void
4342 6803 : ix86_emit_vec_binop (enum rtx_code code, machine_mode mode,
4343 : rtx dst, rtx src1, rtx src2)
4344 : {
4345 6803 : rtx tmp;
4346 :
4347 6803 : tmp = gen_rtx_SET (dst, gen_rtx_fmt_ee (code, mode, src1, src2));
4348 :
4349 6803 : if (GET_MODE_SIZE (mode) <= GET_MODE_SIZE (SImode)
4350 6803 : && GET_MODE_CLASS (mode) == MODE_VECTOR_INT)
4351 : {
4352 94 : rtx clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
4353 94 : tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, tmp, clob));
4354 : }
4355 :
4356 6803 : emit_insn (tmp);
4357 6803 : }
4358 :
4359 : /* Expand DEST = CMP ? OP_TRUE : OP_FALSE into a sequence of logical
4360 : operations. This is used for both scalar and vector conditional moves. */
4361 :
4362 : void
4363 10458 : ix86_expand_sse_movcc (rtx dest, rtx cmp, rtx op_true, rtx op_false)
4364 : {
4365 10458 : machine_mode mode = GET_MODE (dest);
4366 10458 : machine_mode cmpmode = GET_MODE (cmp);
4367 10458 : rtx x;
4368 :
4369 : /* Simplify trivial VEC_COND_EXPR to avoid ICE in pr97506. */
4370 10458 : if (rtx_equal_p (op_true, op_false))
4371 : {
4372 0 : emit_move_insn (dest, op_true);
4373 0 : return;
4374 : }
4375 :
4376 : /* If we have an integer mask and FP value then we need
4377 : to cast mask to FP mode. */
4378 10458 : if (mode != cmpmode && VECTOR_MODE_P (cmpmode))
4379 : {
4380 1649 : cmp = force_reg (cmpmode, cmp);
4381 1649 : cmp = gen_rtx_SUBREG (mode, cmp, 0);
4382 : }
4383 :
4384 : /* In AVX512F the result of comparison is an integer mask. */
4385 10458 : if (mode != cmpmode
4386 1794 : && GET_MODE_CLASS (cmpmode) == MODE_INT)
4387 : {
4388 145 : gcc_assert (ix86_valid_mask_cmp_mode (mode));
4389 : /* Using scalar/vector move with mask register. */
4390 145 : cmp = force_reg (cmpmode, cmp);
4391 : /* Optimize for mask zero. */
4392 290 : op_true = (op_true != CONST0_RTX (mode)
4393 145 : ? force_reg (mode, op_true) : op_true);
4394 290 : op_false = (op_false != CONST0_RTX (mode)
4395 145 : ? force_reg (mode, op_false) : op_false);
4396 145 : if (op_true == CONST0_RTX (mode))
4397 : {
4398 0 : if (cmpmode == E_DImode && !TARGET_64BIT)
4399 : {
4400 0 : x = gen_reg_rtx (cmpmode);
4401 0 : emit_insn (gen_knotdi (x, cmp));
4402 : }
4403 : else
4404 0 : x = expand_simple_unop (cmpmode, NOT, cmp, NULL, 1);
4405 : cmp = x;
4406 : /* Reverse op_true op_false. */
4407 : std::swap (op_true, op_false);
4408 : }
4409 :
4410 145 : if (mode == HFmode)
4411 92 : emit_insn (gen_movhf_mask (dest, op_true, op_false, cmp));
4412 : else
4413 53 : emit_insn (gen_rtx_SET (dest,
4414 : gen_rtx_VEC_MERGE (mode,
4415 : op_true, op_false, cmp)));
4416 145 : return;
4417 : }
4418 :
4419 10313 : if (vector_all_ones_operand (op_true, mode)
4420 10313 : && op_false == CONST0_RTX (mode))
4421 : {
4422 3 : emit_move_insn (dest, cmp);
4423 3 : return;
4424 : }
4425 10310 : else if (op_false == CONST0_RTX (mode))
4426 : {
4427 982 : x = expand_simple_binop (mode, AND, cmp, op_true,
4428 : dest, 1, OPTAB_DIRECT);
4429 982 : if (x != dest)
4430 0 : emit_move_insn (dest, x);
4431 982 : return;
4432 : }
4433 9328 : else if (op_true == CONST0_RTX (mode))
4434 : {
4435 118 : op_false = force_reg (mode, op_false);
4436 118 : x = gen_rtx_NOT (mode, cmp);
4437 118 : ix86_emit_vec_binop (AND, mode, dest, x, op_false);
4438 118 : return;
4439 : }
4440 9210 : else if (vector_all_ones_operand (op_true, mode))
4441 : {
4442 3 : x = expand_simple_binop (mode, IOR, cmp, op_false,
4443 : dest, 1, OPTAB_DIRECT);
4444 3 : if (x != dest)
4445 0 : emit_move_insn (dest, x);
4446 3 : return;
4447 : }
4448 :
4449 9207 : if (TARGET_XOP)
4450 : {
4451 65 : op_true = force_reg (mode, op_true);
4452 :
4453 65 : if (GET_MODE_SIZE (mode) < 16
4454 65 : || !nonimmediate_operand (op_false, mode))
4455 50 : op_false = force_reg (mode, op_false);
4456 :
4457 65 : emit_insn (gen_rtx_SET (dest,
4458 : gen_rtx_IF_THEN_ELSE (mode, cmp,
4459 : op_true, op_false)));
4460 65 : return;
4461 : }
4462 :
4463 9142 : rtx (*gen) (rtx, rtx, rtx, rtx) = NULL;
4464 9142 : machine_mode blend_mode = mode;
4465 :
4466 9142 : switch (mode)
4467 : {
4468 27 : case E_V2SFmode:
4469 27 : if (TARGET_SSE_MOVCC_USE_BLENDV && TARGET_SSE4_1)
4470 : gen = gen_mmx_blendvps;
4471 : break;
4472 355 : case E_V4SFmode:
4473 355 : if (TARGET_SSE_MOVCC_USE_BLENDV && TARGET_SSE4_1)
4474 : gen = gen_sse4_1_blendvps;
4475 : break;
4476 188 : case E_V2DFmode:
4477 188 : if (TARGET_SSE_MOVCC_USE_BLENDV && TARGET_SSE4_1)
4478 : gen = gen_sse4_1_blendvpd;
4479 : break;
4480 1095 : case E_SFmode:
4481 1095 : if (TARGET_SSE_MOVCC_USE_BLENDV && TARGET_SSE4_1)
4482 : gen = gen_sse4_1_blendvss;
4483 : break;
4484 796 : case E_DFmode:
4485 796 : if (TARGET_SSE_MOVCC_USE_BLENDV && TARGET_SSE4_1)
4486 : gen = gen_sse4_1_blendvsd;
4487 : break;
4488 221 : case E_V8QImode:
4489 221 : case E_V4HImode:
4490 221 : case E_V4HFmode:
4491 221 : case E_V4BFmode:
4492 221 : case E_V2SImode:
4493 221 : if (TARGET_SSE_MOVCC_USE_BLENDV && TARGET_SSE4_1)
4494 : {
4495 : gen = gen_mmx_pblendvb_v8qi;
4496 : blend_mode = V8QImode;
4497 : }
4498 : break;
4499 95 : case E_V4QImode:
4500 95 : case E_V2HImode:
4501 95 : case E_V2HFmode:
4502 95 : case E_V2BFmode:
4503 95 : if (TARGET_SSE_MOVCC_USE_BLENDV && TARGET_SSE4_1)
4504 : {
4505 : gen = gen_mmx_pblendvb_v4qi;
4506 : blend_mode = V4QImode;
4507 : }
4508 : break;
4509 36 : case E_V2QImode:
4510 36 : if (TARGET_SSE_MOVCC_USE_BLENDV && TARGET_SSE4_1)
4511 : gen = gen_mmx_pblendvb_v2qi;
4512 : break;
4513 5660 : case E_V16QImode:
4514 5660 : case E_V8HImode:
4515 5660 : case E_V8HFmode:
4516 5660 : case E_V8BFmode:
4517 5660 : case E_V4SImode:
4518 5660 : case E_V2DImode:
4519 5660 : case E_V1TImode:
4520 5660 : if (TARGET_SSE_MOVCC_USE_BLENDV && TARGET_SSE4_1)
4521 : {
4522 : gen = gen_sse4_1_pblendvb;
4523 : blend_mode = V16QImode;
4524 : }
4525 : break;
4526 99 : case E_V8SFmode:
4527 99 : if (TARGET_AVX && TARGET_SSE_MOVCC_USE_BLENDV)
4528 : gen = gen_avx_blendvps256;
4529 : break;
4530 192 : case E_V4DFmode:
4531 192 : if (TARGET_AVX && TARGET_SSE_MOVCC_USE_BLENDV)
4532 : gen = gen_avx_blendvpd256;
4533 : break;
4534 378 : case E_V32QImode:
4535 378 : case E_V16HImode:
4536 378 : case E_V16HFmode:
4537 378 : case E_V16BFmode:
4538 378 : case E_V8SImode:
4539 378 : case E_V4DImode:
4540 378 : if (TARGET_AVX2 && TARGET_SSE_MOVCC_USE_BLENDV)
4541 : {
4542 : gen = gen_avx2_pblendvb;
4543 : blend_mode = V32QImode;
4544 : }
4545 : break;
4546 :
4547 0 : case E_V64QImode:
4548 0 : gen = gen_avx512bw_blendmv64qi;
4549 0 : break;
4550 0 : case E_V32HImode:
4551 0 : gen = gen_avx512bw_blendmv32hi;
4552 0 : break;
4553 0 : case E_V32HFmode:
4554 0 : gen = gen_avx512bw_blendmv32hf;
4555 0 : break;
4556 0 : case E_V32BFmode:
4557 0 : gen = gen_avx512bw_blendmv32bf;
4558 0 : break;
4559 0 : case E_V16SImode:
4560 0 : gen = gen_avx512f_blendmv16si;
4561 0 : break;
4562 0 : case E_V8DImode:
4563 0 : gen = gen_avx512f_blendmv8di;
4564 0 : break;
4565 0 : case E_V8DFmode:
4566 0 : gen = gen_avx512f_blendmv8df;
4567 0 : break;
4568 : case E_V16SFmode:
4569 : gen = gen_avx512f_blendmv16sf;
4570 : break;
4571 :
4572 : default:
4573 : break;
4574 : }
4575 :
4576 0 : if (gen != NULL)
4577 : {
4578 2086 : if (GET_MODE_SIZE (mode) < 16
4579 2086 : || !vector_operand (op_true, mode))
4580 549 : op_true = force_reg (mode, op_true);
4581 2086 : op_false = force_reg (mode, op_false);
4582 :
4583 2086 : if (blend_mode == mode)
4584 : x = dest;
4585 : else
4586 : {
4587 1036 : x = gen_reg_rtx (blend_mode);
4588 1036 : op_false = gen_lowpart (blend_mode, op_false);
4589 1036 : op_true = gen_lowpart (blend_mode, op_true);
4590 1036 : cmp = gen_lowpart (blend_mode, cmp);
4591 : }
4592 :
4593 2086 : emit_insn (gen (x, op_false, op_true, cmp));
4594 :
4595 2086 : if (x != dest)
4596 1036 : emit_move_insn (dest, gen_lowpart (mode, x));
4597 : }
4598 7056 : else if (CONST_VECTOR_P (op_true) && CONST_VECTOR_P (op_false))
4599 : {
4600 472 : rtx tmp = simplify_const_binary_operation (XOR, mode, op_true, op_false);
4601 472 : tmp = expand_simple_binop (mode, AND, cmp, tmp,
4602 : NULL, 1, OPTAB_DIRECT);
4603 472 : tmp = expand_simple_binop (mode, XOR, tmp, op_false,
4604 : dest, 1, OPTAB_DIRECT);
4605 472 : if (tmp != dest)
4606 0 : emit_move_insn (dest, tmp);
4607 : }
4608 : else
4609 : {
4610 6584 : rtx t2 = expand_simple_binop (mode, AND, cmp, op_true,
4611 : NULL, 1, OPTAB_DIRECT);
4612 :
4613 6584 : rtx t3 = gen_reg_rtx (mode);
4614 6584 : x = gen_rtx_NOT (mode, cmp);
4615 6584 : op_false = force_reg (mode, op_false);
4616 6584 : ix86_emit_vec_binop (AND, mode, t3, x, op_false);
4617 :
4618 6584 : x = expand_simple_binop (mode, IOR, t3, t2,
4619 : dest, 1, OPTAB_DIRECT);
4620 6584 : if (x != dest)
4621 0 : emit_move_insn (dest, x);
4622 : }
4623 : }
4624 :
4625 : /* Swap, force into registers, or otherwise massage the two operands
4626 : to an sse comparison with a mask result. Thus we differ a bit from
4627 : ix86_prepare_fp_compare_args which expects to produce a flags result.
4628 :
4629 : The DEST operand exists to help determine whether to commute commutative
4630 : operators. The POP0/POP1 operands are updated in place. The new
4631 : comparison code is returned, or UNKNOWN if not implementable. */
4632 :
4633 : static enum rtx_code
4634 17694 : ix86_prepare_sse_fp_compare_args (rtx dest, enum rtx_code code,
4635 : rtx *pop0, rtx *pop1)
4636 : {
4637 17694 : switch (code)
4638 : {
4639 67 : case LTGT:
4640 67 : case UNEQ:
4641 : /* AVX supports all the needed comparisons. */
4642 67 : if (TARGET_AVX)
4643 : break;
4644 : /* We have no LTGT as an operator. We could implement it with
4645 : NE & ORDERED, but this requires an extra temporary. It's
4646 : not clear that it's worth it. */
4647 : return UNKNOWN;
4648 :
4649 : case LT:
4650 : case LE:
4651 : case UNGT:
4652 : case UNGE:
4653 : /* These are supported directly. */
4654 : break;
4655 :
4656 6010 : case EQ:
4657 6010 : case NE:
4658 6010 : case UNORDERED:
4659 6010 : case ORDERED:
4660 : /* AVX has 3 operand comparisons, no need to swap anything. */
4661 6010 : if (TARGET_AVX)
4662 : break;
4663 : /* For commutative operators, try to canonicalize the destination
4664 : operand to be first in the comparison - this helps reload to
4665 : avoid extra moves. */
4666 1435 : if (!dest || !rtx_equal_p (dest, *pop1))
4667 : break;
4668 : /* FALLTHRU */
4669 :
4670 10564 : case GE:
4671 10564 : case GT:
4672 10564 : case UNLE:
4673 10564 : case UNLT:
4674 : /* These are not supported directly before AVX, and furthermore
4675 : ix86_expand_sse_fp_minmax only optimizes LT/UNGE. Swap the
4676 : comparison operands to transform into something that is
4677 : supported. */
4678 10564 : std::swap (*pop0, *pop1);
4679 10564 : code = swap_condition (code);
4680 10564 : break;
4681 :
4682 0 : default:
4683 0 : gcc_unreachable ();
4684 : }
4685 :
4686 : return code;
4687 : }
4688 :
4689 : /* Expand a floating-point conditional move. Return true if successful. */
4690 :
4691 : bool
4692 80230 : ix86_expand_fp_movcc (rtx operands[])
4693 : {
4694 80230 : machine_mode mode = GET_MODE (operands[0]);
4695 80230 : enum rtx_code code = GET_CODE (operands[1]);
4696 80230 : rtx tmp, compare_op;
4697 80230 : rtx op0 = XEXP (operands[1], 0);
4698 80230 : rtx op1 = XEXP (operands[1], 1);
4699 :
4700 80230 : if (GET_MODE (op0) == BFmode
4701 80230 : && !ix86_fp_comparison_operator (operands[1], VOIDmode))
4702 : return false;
4703 :
4704 80230 : if (SSE_FLOAT_MODE_SSEMATH_OR_HFBF_P (mode))
4705 : {
4706 65971 : machine_mode cmode;
4707 :
4708 : /* Since we've no cmove for sse registers, don't force bad register
4709 : allocation just to gain access to it. Deny movcc when the
4710 : comparison mode doesn't match the move mode. */
4711 65971 : cmode = GET_MODE (op0);
4712 65971 : if (cmode == VOIDmode)
4713 0 : cmode = GET_MODE (op1);
4714 65971 : if (cmode != mode)
4715 : return false;
4716 :
4717 9727 : code = ix86_prepare_sse_fp_compare_args (operands[0], code, &op0, &op1);
4718 9727 : if (code == UNKNOWN)
4719 : return false;
4720 :
4721 9707 : if (ix86_expand_sse_fp_minmax (operands[0], code, op0, op1,
4722 : operands[2], operands[3]))
4723 : return true;
4724 :
4725 2118 : tmp = ix86_expand_sse_cmp (operands[0], code, op0, op1,
4726 : operands[2], operands[3]);
4727 2118 : ix86_expand_sse_movcc (operands[0], tmp, operands[2], operands[3]);
4728 2118 : return true;
4729 : }
4730 :
4731 14259 : if (GET_MODE (op0) == TImode
4732 14259 : || (GET_MODE (op0) == DImode
4733 72 : && !TARGET_64BIT))
4734 : return false;
4735 :
4736 : /* The floating point conditional move instructions don't directly
4737 : support conditions resulting from a signed integer comparison. */
4738 :
4739 14187 : compare_op = ix86_expand_compare (code, op0, op1);
4740 14187 : if (!fcmov_comparison_operator (compare_op, VOIDmode))
4741 : {
4742 146 : tmp = gen_reg_rtx (QImode);
4743 146 : ix86_expand_setcc (tmp, code, op0, op1);
4744 :
4745 146 : compare_op = ix86_expand_compare (NE, tmp, const0_rtx);
4746 : }
4747 :
4748 14187 : operands[2] = force_reg (mode, operands[2]);
4749 14187 : operands[3] = force_reg (mode, operands[3]);
4750 14187 : emit_insn (gen_rtx_SET (operands[0],
4751 : gen_rtx_IF_THEN_ELSE (mode, compare_op,
4752 : operands[2], operands[3])));
4753 :
4754 14187 : return true;
4755 : }
4756 :
4757 : /* Helper for ix86_cmp_code_to_pcmp_immediate for int modes. */
4758 :
4759 : static int
4760 4940 : ix86_int_cmp_code_to_pcmp_immediate (enum rtx_code code)
4761 : {
4762 4940 : switch (code)
4763 : {
4764 : case EQ:
4765 : return 0;
4766 379 : case LT:
4767 379 : case LTU:
4768 379 : return 1;
4769 220 : case LE:
4770 220 : case LEU:
4771 220 : return 2;
4772 3114 : case NE:
4773 3114 : return 4;
4774 299 : case GE:
4775 299 : case GEU:
4776 299 : return 5;
4777 502 : case GT:
4778 502 : case GTU:
4779 502 : return 6;
4780 0 : default:
4781 0 : gcc_unreachable ();
4782 : }
4783 : }
4784 :
4785 : /* Helper for ix86_cmp_code_to_pcmp_immediate for fp modes. */
4786 :
4787 : static int
4788 1809 : ix86_fp_cmp_code_to_pcmp_immediate (enum rtx_code code)
4789 : {
4790 1809 : switch (code)
4791 : {
4792 : case EQ:
4793 : return 0x00;
4794 378 : case NE:
4795 378 : return 0x04;
4796 514 : case GT:
4797 514 : return 0x0e;
4798 88 : case LE:
4799 88 : return 0x02;
4800 53 : case GE:
4801 53 : return 0x0d;
4802 624 : case LT:
4803 624 : return 0x01;
4804 2 : case UNLE:
4805 2 : return 0x0a;
4806 2 : case UNLT:
4807 2 : return 0x09;
4808 11 : case UNGE:
4809 11 : return 0x05;
4810 44 : case UNGT:
4811 44 : return 0x06;
4812 2 : case UNEQ:
4813 2 : return 0x18;
4814 0 : case LTGT:
4815 0 : return 0x0c;
4816 2 : case ORDERED:
4817 2 : return 0x07;
4818 2 : case UNORDERED:
4819 2 : return 0x03;
4820 0 : default:
4821 0 : gcc_unreachable ();
4822 : }
4823 : }
4824 :
4825 : /* Return immediate value to be used in UNSPEC_PCMP
4826 : for comparison CODE in MODE. */
4827 :
4828 : static int
4829 6749 : ix86_cmp_code_to_pcmp_immediate (enum rtx_code code, machine_mode mode)
4830 : {
4831 6749 : if (FLOAT_MODE_P (mode))
4832 1809 : return ix86_fp_cmp_code_to_pcmp_immediate (code);
4833 4940 : return ix86_int_cmp_code_to_pcmp_immediate (code);
4834 : }
4835 :
4836 : /* Expand AVX-512 vector comparison. */
4837 :
4838 : bool
4839 6749 : ix86_expand_mask_vec_cmp (rtx dest, enum rtx_code code, rtx cmp_op0, rtx cmp_op1)
4840 : {
4841 6749 : machine_mode mask_mode = GET_MODE (dest);
4842 6749 : machine_mode cmp_mode = GET_MODE (cmp_op0);
4843 6749 : rtx imm = GEN_INT (ix86_cmp_code_to_pcmp_immediate (code, cmp_mode));
4844 6749 : int unspec_code;
4845 6749 : rtx unspec;
4846 :
4847 6749 : switch (code)
4848 : {
4849 : case LEU:
4850 : case GTU:
4851 : case GEU:
4852 : case LTU:
4853 : unspec_code = UNSPEC_UNSIGNED_PCMP;
4854 : break;
4855 :
4856 6335 : default:
4857 6335 : unspec_code = UNSPEC_PCMP;
4858 : }
4859 :
4860 6749 : unspec = gen_rtx_UNSPEC (mask_mode, gen_rtvec (3, cmp_op0, cmp_op1, imm),
4861 : unspec_code);
4862 6749 : emit_insn (gen_rtx_SET (dest, unspec));
4863 :
4864 6749 : return true;
4865 : }
4866 :
4867 : /* Expand fp vector comparison. */
4868 :
4869 : bool
4870 7967 : ix86_expand_fp_vec_cmp (rtx operands[])
4871 : {
4872 7967 : enum rtx_code code = GET_CODE (operands[1]);
4873 7967 : rtx cmp;
4874 :
4875 7967 : code = ix86_prepare_sse_fp_compare_args (operands[0], code,
4876 : &operands[2], &operands[3]);
4877 7967 : if (code == UNKNOWN)
4878 : {
4879 20 : rtx temp;
4880 20 : switch (GET_CODE (operands[1]))
4881 : {
4882 2 : case LTGT:
4883 2 : temp = ix86_expand_sse_cmp (operands[0], ORDERED, operands[2],
4884 : operands[3], NULL, NULL);
4885 2 : cmp = ix86_expand_sse_cmp (operands[0], NE, operands[2],
4886 : operands[3], NULL, NULL);
4887 2 : code = AND;
4888 2 : break;
4889 18 : case UNEQ:
4890 18 : temp = ix86_expand_sse_cmp (operands[0], UNORDERED, operands[2],
4891 : operands[3], NULL, NULL);
4892 18 : cmp = ix86_expand_sse_cmp (operands[0], EQ, operands[2],
4893 : operands[3], NULL, NULL);
4894 18 : code = IOR;
4895 18 : break;
4896 0 : default:
4897 0 : gcc_unreachable ();
4898 : }
4899 20 : cmp = expand_simple_binop (GET_MODE (cmp), code, temp, cmp, cmp, 1,
4900 : OPTAB_DIRECT);
4901 : }
4902 : else
4903 7947 : cmp = ix86_expand_sse_cmp (operands[0], code, operands[2], operands[3],
4904 : NULL, NULL);
4905 :
4906 7967 : if (operands[0] != cmp)
4907 7887 : emit_move_insn (operands[0], cmp);
4908 :
4909 7967 : return true;
4910 : }
4911 :
4912 : static rtx
4913 18463 : ix86_expand_int_sse_cmp (rtx dest, enum rtx_code code, rtx cop0, rtx cop1,
4914 : rtx op_true, rtx op_false, bool *negate)
4915 : {
4916 18463 : machine_mode data_mode = GET_MODE (dest);
4917 18463 : machine_mode mode = GET_MODE (cop0);
4918 18463 : rtx x;
4919 :
4920 18463 : *negate = false;
4921 :
4922 : /* XOP supports all of the comparisons on all 128-bit vector int types. */
4923 18463 : if (TARGET_XOP
4924 201 : && GET_MODE_CLASS (mode) == MODE_VECTOR_INT
4925 18664 : && GET_MODE_SIZE (mode) <= 16)
4926 : ;
4927 : /* AVX512F supports all of the comparisons
4928 : on all 128/256/512-bit vector int types. */
4929 18265 : else if (ix86_use_mask_cmp_p (data_mode, mode, op_true, op_false))
4930 : ;
4931 : else
4932 : {
4933 : /* Canonicalize the comparison to EQ, GT, GTU. */
4934 18212 : switch (code)
4935 : {
4936 : case EQ:
4937 : case GT:
4938 : case GTU:
4939 : break;
4940 :
4941 960 : case LE:
4942 960 : case LEU:
4943 : /* x <= cst can be handled as x < cst + 1 unless there is
4944 : wrap around in cst + 1. */
4945 960 : if (CONST_VECTOR_P (cop1)
4946 1637 : && GET_MODE_INNER (mode) != TImode)
4947 : {
4948 677 : unsigned int n_elts = GET_MODE_NUNITS (mode), i;
4949 677 : machine_mode eltmode = GET_MODE_INNER (mode);
4950 4374 : for (i = 0; i < n_elts; ++i)
4951 : {
4952 3698 : rtx elt = CONST_VECTOR_ELT (cop1, i);
4953 3698 : if (!CONST_INT_P (elt))
4954 : break;
4955 3698 : if (code == LE)
4956 : {
4957 : /* For LE punt if some element is signed maximum. */
4958 2522 : if ((INTVAL (elt) & (GET_MODE_MASK (eltmode) >> 1))
4959 : == (GET_MODE_MASK (eltmode) >> 1))
4960 : break;
4961 : }
4962 : /* For LEU punt if some element is unsigned maximum. */
4963 1176 : else if (elt == constm1_rtx)
4964 : break;
4965 : }
4966 677 : if (i == n_elts)
4967 : {
4968 676 : rtvec v = rtvec_alloc (n_elts);
4969 5048 : for (i = 0; i < n_elts; ++i)
4970 3696 : RTVEC_ELT (v, i)
4971 3696 : = gen_int_mode (INTVAL (CONST_VECTOR_ELT (cop1, i)) + 1,
4972 : eltmode);
4973 676 : cop1 = gen_rtx_CONST_VECTOR (mode, v);
4974 676 : std::swap (cop0, cop1);
4975 676 : code = code == LE ? GT : GTU;
4976 : break;
4977 : }
4978 : }
4979 : /* FALLTHRU */
4980 3335 : case NE:
4981 3335 : code = reverse_condition (code);
4982 3335 : *negate = true;
4983 3335 : break;
4984 :
4985 542 : case GE:
4986 542 : case GEU:
4987 : /* x >= cst can be handled as x > cst - 1 unless there is
4988 : wrap around in cst - 1. */
4989 542 : if (CONST_VECTOR_P (cop1)
4990 839 : && GET_MODE_INNER (mode) != TImode)
4991 : {
4992 297 : unsigned int n_elts = GET_MODE_NUNITS (mode), i;
4993 297 : machine_mode eltmode = GET_MODE_INNER (mode);
4994 2221 : for (i = 0; i < n_elts; ++i)
4995 : {
4996 1972 : rtx elt = CONST_VECTOR_ELT (cop1, i);
4997 1972 : if (!CONST_INT_P (elt))
4998 : break;
4999 1972 : if (code == GE)
5000 : {
5001 : /* For GE punt if some element is signed minimum. */
5002 1924 : if (INTVAL (elt) < 0
5003 136 : && ((INTVAL (elt) & (GET_MODE_MASK (eltmode) >> 1))
5004 : == 0))
5005 : break;
5006 : }
5007 : /* For GEU punt if some element is zero. */
5008 48 : else if (elt == const0_rtx)
5009 : break;
5010 : }
5011 297 : if (i == n_elts)
5012 : {
5013 249 : rtvec v = rtvec_alloc (n_elts);
5014 2422 : for (i = 0; i < n_elts; ++i)
5015 1924 : RTVEC_ELT (v, i)
5016 1924 : = gen_int_mode (INTVAL (CONST_VECTOR_ELT (cop1, i)) - 1,
5017 : eltmode);
5018 249 : cop1 = gen_rtx_CONST_VECTOR (mode, v);
5019 249 : code = code == GE ? GT : GTU;
5020 : break;
5021 : }
5022 : }
5023 293 : code = reverse_condition (code);
5024 293 : *negate = true;
5025 : /* FALLTHRU */
5026 :
5027 1662 : case LT:
5028 1662 : case LTU:
5029 1662 : std::swap (cop0, cop1);
5030 1662 : code = swap_condition (code);
5031 1662 : break;
5032 :
5033 0 : default:
5034 0 : gcc_unreachable ();
5035 : }
5036 :
5037 : /* Only SSE4.1/SSE4.2 supports V2DImode. */
5038 18212 : if (mode == V2DImode)
5039 : {
5040 788 : switch (code)
5041 : {
5042 584 : case EQ:
5043 : /* SSE4.1 supports EQ. */
5044 584 : if (!TARGET_SSE4_1)
5045 18463 : return NULL;
5046 : break;
5047 :
5048 204 : case GT:
5049 204 : case GTU:
5050 : /* SSE4.2 supports GT/GTU. */
5051 204 : if (!TARGET_SSE4_2)
5052 : return NULL;
5053 : break;
5054 :
5055 0 : default:
5056 0 : gcc_unreachable ();
5057 : }
5058 : }
5059 :
5060 18212 : if (CONST_VECTOR_P (cop0))
5061 1328 : cop0 = force_reg (mode, cop0);
5062 16884 : else if (CONST_VECTOR_P (cop1))
5063 7661 : cop1 = force_reg (mode, cop1);
5064 :
5065 18212 : rtx optrue = op_true ? op_true : CONSTM1_RTX (data_mode);
5066 18212 : rtx opfalse = op_false ? op_false : CONST0_RTX (data_mode);
5067 18212 : if (*negate)
5068 3628 : std::swap (optrue, opfalse);
5069 :
5070 : /* Transform x > y ? 0 : -1 (i.e. x <= y ? -1 : 0 or x <= y) when
5071 : not using integer masks into min (x, y) == x ? -1 : 0 (i.e.
5072 : min (x, y) == x). While we add one instruction (the minimum),
5073 : we remove the need for two instructions in the negation, as the
5074 : result is done this way.
5075 : When using masks, do it for SI/DImode element types, as it is shorter
5076 : than the two subtractions. */
5077 18212 : if ((code != EQ
5078 7510 : && GET_MODE_SIZE (mode) != 64
5079 7510 : && vector_all_ones_operand (opfalse, data_mode)
5080 577 : && optrue == CONST0_RTX (data_mode))
5081 25145 : || (code == GTU
5082 2082 : && GET_MODE_SIZE (GET_MODE_INNER (mode)) >= 4
5083 : /* Don't do it if not using integer masks and we'd end up with
5084 : the right values in the registers though. */
5085 696 : && (GET_MODE_SIZE (mode) == 64
5086 696 : || !vector_all_ones_operand (optrue, data_mode)
5087 571 : || opfalse != CONST0_RTX (data_mode))))
5088 : {
5089 702 : rtx (*gen) (rtx, rtx, rtx) = NULL;
5090 :
5091 702 : switch (mode)
5092 : {
5093 0 : case E_V16SImode:
5094 0 : gen = (code == GTU) ? gen_uminv16si3 : gen_sminv16si3;
5095 : break;
5096 0 : case E_V8DImode:
5097 0 : gen = (code == GTU) ? gen_uminv8di3 : gen_sminv8di3;
5098 0 : cop0 = force_reg (mode, cop0);
5099 0 : cop1 = force_reg (mode, cop1);
5100 0 : break;
5101 24 : case E_V32QImode:
5102 24 : if (TARGET_AVX2)
5103 24 : gen = (code == GTU) ? gen_uminv32qi3 : gen_sminv32qi3;
5104 : break;
5105 24 : case E_V16HImode:
5106 24 : if (TARGET_AVX2)
5107 24 : gen = (code == GTU) ? gen_uminv16hi3 : gen_sminv16hi3;
5108 : break;
5109 25 : case E_V8SImode:
5110 25 : if (TARGET_AVX2)
5111 25 : gen = (code == GTU) ? gen_uminv8si3 : gen_sminv8si3;
5112 : break;
5113 20 : case E_V4DImode:
5114 20 : if (TARGET_AVX512VL)
5115 : {
5116 0 : gen = (code == GTU) ? gen_uminv4di3 : gen_sminv4di3;
5117 0 : cop0 = force_reg (mode, cop0);
5118 0 : cop1 = force_reg (mode, cop1);
5119 : }
5120 : break;
5121 64 : case E_V16QImode:
5122 64 : if (code == GTU && TARGET_SSE2)
5123 : gen = gen_uminv16qi3;
5124 28 : else if (code == GT && TARGET_SSE4_1)
5125 : gen = gen_sminv16qi3;
5126 : break;
5127 44 : case E_V8QImode:
5128 44 : if (code == GTU && TARGET_SSE2)
5129 : gen = gen_uminv8qi3;
5130 42 : else if (code == GT && TARGET_SSE4_1)
5131 : gen = gen_sminv8qi3;
5132 : break;
5133 13 : case E_V4QImode:
5134 13 : if (code == GTU && TARGET_SSE2)
5135 : gen = gen_uminv4qi3;
5136 2 : else if (code == GT && TARGET_SSE4_1)
5137 : gen = gen_sminv4qi3;
5138 : break;
5139 8 : case E_V2QImode:
5140 8 : if (code == GTU && TARGET_SSE2)
5141 : gen = gen_uminv2qi3;
5142 6 : else if (code == GT && TARGET_SSE4_1)
5143 : gen = gen_sminv2qi3;
5144 : break;
5145 73 : case E_V8HImode:
5146 73 : if (code == GTU && TARGET_SSE4_1)
5147 : gen = gen_uminv8hi3;
5148 63 : else if (code == GT && TARGET_SSE2)
5149 : gen = gen_sminv8hi3;
5150 : break;
5151 4 : case E_V4HImode:
5152 4 : if (code == GTU && TARGET_SSE4_1)
5153 : gen = gen_uminv4hi3;
5154 4 : else if (code == GT && TARGET_SSE2)
5155 : gen = gen_sminv4hi3;
5156 : break;
5157 16 : case E_V2HImode:
5158 16 : if (code == GTU && TARGET_SSE4_1)
5159 : gen = gen_uminv2hi3;
5160 16 : else if (code == GT && TARGET_SSE2)
5161 : gen = gen_sminv2hi3;
5162 : break;
5163 250 : case E_V4SImode:
5164 250 : if (TARGET_SSE4_1)
5165 52 : gen = (code == GTU) ? gen_uminv4si3 : gen_sminv4si3;
5166 : break;
5167 113 : case E_V2SImode:
5168 113 : if (TARGET_SSE4_1)
5169 0 : gen = (code == GTU) ? gen_uminv2si3 : gen_sminv2si3;
5170 : break;
5171 24 : case E_V2DImode:
5172 24 : if (TARGET_AVX512VL)
5173 : {
5174 0 : gen = (code == GTU) ? gen_uminv2di3 : gen_sminv2di3;
5175 0 : cop0 = force_reg (mode, cop0);
5176 0 : cop1 = force_reg (mode, cop1);
5177 : }
5178 : break;
5179 : default:
5180 : break;
5181 : }
5182 :
5183 0 : if (gen)
5184 : {
5185 280 : rtx tem = gen_reg_rtx (mode);
5186 280 : if (!vector_operand (cop0, mode))
5187 0 : cop0 = force_reg (mode, cop0);
5188 280 : if (!vector_operand (cop1, mode))
5189 0 : cop1 = force_reg (mode, cop1);
5190 280 : *negate = !*negate;
5191 280 : emit_insn (gen (tem, cop0, cop1));
5192 280 : cop1 = tem;
5193 280 : code = EQ;
5194 : }
5195 : }
5196 :
5197 : /* Unsigned parallel compare is not supported by the hardware.
5198 : Play some tricks to turn this into a signed comparison
5199 : against 0. */
5200 18212 : if (code == GTU)
5201 : {
5202 1178 : cop0 = force_reg (mode, cop0);
5203 :
5204 1178 : switch (mode)
5205 : {
5206 802 : case E_V16SImode:
5207 802 : case E_V8DImode:
5208 802 : case E_V8SImode:
5209 802 : case E_V4DImode:
5210 802 : case E_V4SImode:
5211 802 : case E_V2SImode:
5212 802 : case E_V2DImode:
5213 802 : {
5214 802 : rtx t1, t2, mask;
5215 :
5216 : /* Subtract (-(INT MAX) - 1) from both operands to make
5217 : them signed. */
5218 802 : mask = ix86_build_signbit_mask (mode, true, false);
5219 802 : t1 = gen_reg_rtx (mode);
5220 802 : emit_insn (gen_sub3_insn (t1, cop0, mask));
5221 :
5222 802 : t2 = gen_reg_rtx (mode);
5223 802 : emit_insn (gen_sub3_insn (t2, cop1, mask));
5224 :
5225 802 : cop0 = t1;
5226 802 : cop1 = t2;
5227 802 : code = GT;
5228 : }
5229 802 : break;
5230 :
5231 376 : case E_V64QImode:
5232 376 : case E_V32HImode:
5233 376 : case E_V32QImode:
5234 376 : case E_V16HImode:
5235 376 : case E_V16QImode:
5236 376 : case E_V8QImode:
5237 376 : case E_V4QImode:
5238 376 : case E_V2QImode:
5239 376 : case E_V8HImode:
5240 376 : case E_V4HImode:
5241 376 : case E_V2HImode:
5242 : /* Perform a parallel unsigned saturating subtraction. */
5243 376 : x = gen_reg_rtx (mode);
5244 376 : emit_insn (gen_rtx_SET
5245 : (x, gen_rtx_US_MINUS (mode, cop0, cop1)));
5246 376 : cop0 = x;
5247 376 : cop1 = CONST0_RTX (mode);
5248 376 : code = EQ;
5249 376 : *negate = !*negate;
5250 376 : break;
5251 :
5252 0 : default:
5253 0 : gcc_unreachable ();
5254 : }
5255 : }
5256 : }
5257 :
5258 18463 : if (*negate)
5259 3662 : std::swap (op_true, op_false);
5260 :
5261 18463 : if (CONST_VECTOR_P (cop1))
5262 445 : cop1 = force_reg (mode, cop1);
5263 :
5264 : /* Allow the comparison to be done in one mode, but the movcc to
5265 : happen in another mode. */
5266 18463 : if (data_mode == mode)
5267 18421 : x = ix86_expand_sse_cmp (dest, code, cop0, cop1, op_true, op_false);
5268 : else
5269 : {
5270 126 : gcc_assert (GET_MODE_SIZE (data_mode) == GET_MODE_SIZE (mode));
5271 42 : x = ix86_expand_sse_cmp (gen_reg_rtx (mode), code, cop0, cop1,
5272 : op_true, op_false);
5273 42 : if (GET_MODE (x) == mode)
5274 24 : x = gen_lowpart (data_mode, x);
5275 : }
5276 :
5277 : return x;
5278 : }
5279 :
5280 : /* Expand integer vector comparison. */
5281 :
5282 : bool
5283 11610 : ix86_expand_int_vec_cmp (rtx operands[])
5284 : {
5285 11610 : rtx_code code = GET_CODE (operands[1]);
5286 11610 : bool negate = false;
5287 11610 : rtx cmp = ix86_expand_int_sse_cmp (operands[0], code, operands[2],
5288 : operands[3], NULL, NULL, &negate);
5289 :
5290 11610 : if (!cmp)
5291 : return false;
5292 :
5293 11610 : if (negate)
5294 : {
5295 3674 : if (TARGET_AVX512F && GET_MODE_SIZE (GET_MODE (cmp)) >= 16)
5296 93 : cmp = gen_rtx_XOR (GET_MODE (cmp), cmp, CONSTM1_RTX (GET_MODE (cmp)));
5297 : else
5298 : {
5299 6906 : cmp = ix86_expand_int_sse_cmp (operands[0], EQ, cmp,
5300 3453 : CONST0_RTX (GET_MODE (cmp)),
5301 : NULL, NULL, &negate);
5302 3453 : gcc_assert (!negate);
5303 : }
5304 : }
5305 :
5306 11610 : if (operands[0] != cmp)
5307 11315 : emit_move_insn (operands[0], cmp);
5308 :
5309 : return true;
5310 : }
5311 :
5312 : /* Expand a floating-point vector conditional move; a vcond operation
5313 : rather than a movcc operation. */
5314 :
5315 : bool
5316 0 : ix86_expand_fp_vcond (rtx operands[])
5317 : {
5318 0 : enum rtx_code code = GET_CODE (operands[3]);
5319 0 : rtx cmp;
5320 :
5321 0 : code = ix86_prepare_sse_fp_compare_args (operands[0], code,
5322 : &operands[4], &operands[5]);
5323 0 : if (code == UNKNOWN)
5324 : {
5325 0 : rtx temp;
5326 0 : switch (GET_CODE (operands[3]))
5327 : {
5328 0 : case LTGT:
5329 0 : temp = ix86_expand_sse_cmp (operands[0], ORDERED, operands[4],
5330 : operands[5], operands[0], operands[0]);
5331 0 : cmp = ix86_expand_sse_cmp (operands[0], NE, operands[4],
5332 : operands[5], operands[1], operands[2]);
5333 0 : code = AND;
5334 0 : break;
5335 0 : case UNEQ:
5336 0 : temp = ix86_expand_sse_cmp (operands[0], UNORDERED, operands[4],
5337 : operands[5], operands[0], operands[0]);
5338 0 : cmp = ix86_expand_sse_cmp (operands[0], EQ, operands[4],
5339 : operands[5], operands[1], operands[2]);
5340 0 : code = IOR;
5341 0 : break;
5342 0 : default:
5343 0 : gcc_unreachable ();
5344 : }
5345 0 : cmp = expand_simple_binop (GET_MODE (cmp), code, temp, cmp, cmp, 1,
5346 : OPTAB_DIRECT);
5347 0 : ix86_expand_sse_movcc (operands[0], cmp, operands[1], operands[2]);
5348 0 : return true;
5349 : }
5350 :
5351 0 : if (ix86_expand_sse_fp_minmax (operands[0], code, operands[4],
5352 : operands[5], operands[1], operands[2]))
5353 : return true;
5354 :
5355 0 : cmp = ix86_expand_sse_cmp (operands[0], code, operands[4], operands[5],
5356 : operands[1], operands[2]);
5357 0 : ix86_expand_sse_movcc (operands[0], cmp, operands[1], operands[2]);
5358 0 : return true;
5359 : }
5360 :
5361 : /* Expand a signed/unsigned integral vector conditional move. */
5362 :
5363 : bool
5364 3400 : ix86_expand_int_vcond (rtx operands[])
5365 : {
5366 3400 : machine_mode data_mode = GET_MODE (operands[0]);
5367 3400 : machine_mode mode = GET_MODE (operands[4]);
5368 3400 : enum rtx_code code = GET_CODE (operands[3]);
5369 3400 : bool negate = false;
5370 3400 : rtx x, cop0, cop1;
5371 :
5372 3400 : cop0 = operands[4];
5373 3400 : cop1 = operands[5];
5374 :
5375 : /* Try to optimize x < 0 ? -1 : 0 into (signed) x >> 31
5376 : and x < 0 ? 1 : 0 into (unsigned) x >> 31. */
5377 3400 : if ((code == LT || code == GE)
5378 0 : && data_mode == mode
5379 0 : && cop1 == CONST0_RTX (mode)
5380 0 : && operands[1 + (code == LT)] == CONST0_RTX (data_mode)
5381 0 : && GET_MODE_UNIT_SIZE (data_mode) > 1
5382 0 : && GET_MODE_UNIT_SIZE (data_mode) <= 8
5383 3400 : && (GET_MODE_SIZE (data_mode) == 16
5384 0 : || (TARGET_AVX2 && GET_MODE_SIZE (data_mode) == 32)))
5385 : {
5386 0 : rtx negop = operands[2 - (code == LT)];
5387 0 : int shift = GET_MODE_UNIT_BITSIZE (data_mode) - 1;
5388 0 : if (negop == CONST1_RTX (data_mode))
5389 : {
5390 0 : rtx res = expand_simple_binop (mode, LSHIFTRT, cop0, GEN_INT (shift),
5391 : operands[0], 1, OPTAB_DIRECT);
5392 0 : if (res != operands[0])
5393 0 : emit_move_insn (operands[0], res);
5394 0 : return true;
5395 : }
5396 0 : else if (GET_MODE_INNER (data_mode) != DImode
5397 0 : && vector_all_ones_operand (negop, data_mode))
5398 : {
5399 0 : rtx res = expand_simple_binop (mode, ASHIFTRT, cop0, GEN_INT (shift),
5400 : operands[0], 0, OPTAB_DIRECT);
5401 0 : if (res != operands[0])
5402 0 : emit_move_insn (operands[0], res);
5403 0 : return true;
5404 : }
5405 : }
5406 :
5407 3400 : if (!nonimmediate_operand (cop1, mode))
5408 126 : cop1 = force_reg (mode, cop1);
5409 3400 : if (!general_operand (operands[1], data_mode))
5410 0 : operands[1] = force_reg (data_mode, operands[1]);
5411 3400 : if (!general_operand (operands[2], data_mode))
5412 0 : operands[2] = force_reg (data_mode, operands[2]);
5413 :
5414 3400 : x = ix86_expand_int_sse_cmp (operands[0], code, cop0, cop1,
5415 : operands[1], operands[2], &negate);
5416 :
5417 3400 : if (!x)
5418 : return false;
5419 :
5420 3400 : ix86_expand_sse_movcc (operands[0], x, operands[1+negate],
5421 3400 : operands[2-negate]);
5422 3400 : return true;
5423 : }
5424 :
5425 : static bool
5426 124698 : ix86_expand_vec_perm_vpermt2 (rtx target, rtx mask, rtx op0, rtx op1,
5427 : struct expand_vec_perm_d *d)
5428 : {
5429 : /* ix86_expand_vec_perm_vpermt2 is called from both const and non-const
5430 : expander, so args are either in d, or in op0, op1 etc. */
5431 124698 : machine_mode mode = GET_MODE (d ? d->op0 : op0);
5432 124698 : machine_mode maskmode = mode;
5433 124698 : rtx (*gen) (rtx, rtx, rtx, rtx) = NULL;
5434 :
5435 124698 : switch (mode)
5436 : {
5437 24001 : case E_V16QImode:
5438 24001 : if (TARGET_AVX512VL && TARGET_AVX512VBMI)
5439 : gen = gen_avx512vl_vpermt2varv16qi3;
5440 : break;
5441 521 : case E_V32QImode:
5442 521 : if (TARGET_AVX512VL && TARGET_AVX512VBMI)
5443 : gen = gen_avx512vl_vpermt2varv32qi3;
5444 : break;
5445 198 : case E_V64QImode:
5446 198 : if (TARGET_AVX512VBMI)
5447 : gen = gen_avx512bw_vpermt2varv64qi3;
5448 : break;
5449 13339 : case E_V8HImode:
5450 13339 : if (TARGET_AVX512VL && TARGET_AVX512BW)
5451 : gen = gen_avx512vl_vpermt2varv8hi3;
5452 : break;
5453 775 : case E_V16HImode:
5454 775 : if (TARGET_AVX512VL && TARGET_AVX512BW)
5455 : gen = gen_avx512vl_vpermt2varv16hi3;
5456 : break;
5457 331 : case E_V32HImode:
5458 331 : if (TARGET_AVX512BW)
5459 : gen = gen_avx512bw_vpermt2varv32hi3;
5460 : break;
5461 33811 : case E_V4SImode:
5462 33811 : if (TARGET_AVX512VL)
5463 : gen = gen_avx512vl_vpermt2varv4si3;
5464 : break;
5465 1138 : case E_V8SImode:
5466 1138 : if (TARGET_AVX512VL)
5467 : gen = gen_avx512vl_vpermt2varv8si3;
5468 : break;
5469 126 : case E_V16SImode:
5470 126 : if (TARGET_AVX512F)
5471 : gen = gen_avx512f_vpermt2varv16si3;
5472 : break;
5473 10387 : case E_V4SFmode:
5474 10387 : if (TARGET_AVX512VL)
5475 : {
5476 : gen = gen_avx512vl_vpermt2varv4sf3;
5477 : maskmode = V4SImode;
5478 : }
5479 : break;
5480 6079 : case E_V8SFmode:
5481 6079 : if (TARGET_AVX512VL)
5482 : {
5483 : gen = gen_avx512vl_vpermt2varv8sf3;
5484 : maskmode = V8SImode;
5485 : }
5486 : break;
5487 239 : case E_V16SFmode:
5488 239 : if (TARGET_AVX512F)
5489 : {
5490 : gen = gen_avx512f_vpermt2varv16sf3;
5491 : maskmode = V16SImode;
5492 : }
5493 : break;
5494 2 : case E_V2DImode:
5495 2 : if (TARGET_AVX512VL)
5496 : gen = gen_avx512vl_vpermt2varv2di3;
5497 : break;
5498 307 : case E_V4DImode:
5499 307 : if (TARGET_AVX512VL)
5500 : gen = gen_avx512vl_vpermt2varv4di3;
5501 : break;
5502 10 : case E_V8DImode:
5503 10 : if (TARGET_AVX512F)
5504 : gen = gen_avx512f_vpermt2varv8di3;
5505 : break;
5506 2 : case E_V2DFmode:
5507 2 : if (TARGET_AVX512VL)
5508 : {
5509 : gen = gen_avx512vl_vpermt2varv2df3;
5510 : maskmode = V2DImode;
5511 : }
5512 : break;
5513 1956 : case E_V4DFmode:
5514 1956 : if (TARGET_AVX512VL)
5515 : {
5516 : gen = gen_avx512vl_vpermt2varv4df3;
5517 : maskmode = V4DImode;
5518 : }
5519 : break;
5520 194 : case E_V8DFmode:
5521 194 : if (TARGET_AVX512F)
5522 : {
5523 : gen = gen_avx512f_vpermt2varv8df3;
5524 : maskmode = V8DImode;
5525 : }
5526 : break;
5527 : default:
5528 : break;
5529 : }
5530 :
5531 : if (gen == NULL)
5532 : return false;
5533 :
5534 918 : if (d && d->testing_p)
5535 : return true;
5536 :
5537 : /* ix86_expand_vec_perm_vpermt2 is called from both const and non-const
5538 : expander, so args are either in d, or in op0, op1 etc. */
5539 907 : if (d)
5540 : {
5541 907 : rtx vec[64];
5542 907 : target = d->target;
5543 907 : op0 = d->op0;
5544 907 : op1 = d->op1;
5545 15703 : for (int i = 0; i < d->nelt; ++i)
5546 14796 : vec[i] = GEN_INT (d->perm[i]);
5547 907 : mask = gen_rtx_CONST_VECTOR (maskmode, gen_rtvec_v (d->nelt, vec));
5548 : }
5549 :
5550 915 : emit_insn (gen (target, force_reg (maskmode, mask), op0, op1));
5551 915 : return true;
5552 : }
5553 :
5554 : /* Expand a variable vector permutation. */
5555 :
5556 : void
5557 18 : ix86_expand_vec_perm (rtx operands[])
5558 : {
5559 18 : rtx target = operands[0];
5560 18 : rtx op0 = operands[1];
5561 18 : rtx op1 = operands[2];
5562 18 : rtx mask = operands[3];
5563 18 : rtx t1, t2, t3, t4, t5, t6, t7, t8, vt, vt2, vec[32];
5564 18 : machine_mode mode = GET_MODE (op0);
5565 18 : machine_mode maskmode = GET_MODE (mask);
5566 18 : int w, e, i;
5567 18 : bool one_operand_shuffle = rtx_equal_p (op0, op1);
5568 :
5569 : /* Number of elements in the vector. */
5570 18 : w = GET_MODE_NUNITS (mode);
5571 18 : e = GET_MODE_UNIT_SIZE (mode);
5572 18 : gcc_assert (w <= 64);
5573 :
5574 : /* For HF mode vector, convert it to HI using subreg. */
5575 36 : if (GET_MODE_INNER (mode) == HFmode)
5576 : {
5577 6 : machine_mode orig_mode = mode;
5578 6 : mode = mode_for_vector (HImode, w).require ();
5579 6 : target = lowpart_subreg (mode, target, orig_mode);
5580 6 : op0 = lowpart_subreg (mode, op0, orig_mode);
5581 6 : op1 = lowpart_subreg (mode, op1, orig_mode);
5582 : }
5583 :
5584 18 : if (TARGET_AVX512F && one_operand_shuffle)
5585 : {
5586 5 : rtx (*gen) (rtx, rtx, rtx) = NULL;
5587 5 : switch (mode)
5588 : {
5589 : case E_V16SImode:
5590 : gen = gen_avx512f_permvarv16si;
5591 : break;
5592 0 : case E_V16SFmode:
5593 0 : gen = gen_avx512f_permvarv16sf;
5594 0 : break;
5595 0 : case E_V8DImode:
5596 0 : gen = gen_avx512f_permvarv8di;
5597 0 : break;
5598 0 : case E_V8DFmode:
5599 0 : gen = gen_avx512f_permvarv8df;
5600 0 : break;
5601 : default:
5602 : break;
5603 : }
5604 0 : if (gen != NULL)
5605 : {
5606 0 : emit_insn (gen (target, op0, mask));
5607 16 : return;
5608 : }
5609 : }
5610 :
5611 18 : if (ix86_expand_vec_perm_vpermt2 (target, mask, op0, op1, NULL))
5612 : return;
5613 :
5614 10 : if (TARGET_AVX2)
5615 : {
5616 5 : if (mode == V4DImode || mode == V4DFmode || mode == V16HImode)
5617 : {
5618 : /* Unfortunately, the VPERMQ and VPERMPD instructions only support
5619 : an constant shuffle operand. With a tiny bit of effort we can
5620 : use VPERMD instead. A re-interpretation stall for V4DFmode is
5621 : unfortunate but there's no avoiding it.
5622 : Similarly for V16HImode we don't have instructions for variable
5623 : shuffling, while for V32QImode we can use after preparing suitable
5624 : masks vpshufb; vpshufb; vpermq; vpor. */
5625 :
5626 : if (mode == V16HImode)
5627 : {
5628 : maskmode = mode = V32QImode;
5629 : w = 32;
5630 : e = 1;
5631 : }
5632 : else
5633 : {
5634 : maskmode = mode = V8SImode;
5635 : w = 8;
5636 : e = 4;
5637 : }
5638 0 : t1 = gen_reg_rtx (maskmode);
5639 :
5640 : /* Replicate the low bits of the V4DImode mask into V8SImode:
5641 : mask = { A B C D }
5642 : t1 = { A A B B C C D D }. */
5643 0 : for (i = 0; i < w / 2; ++i)
5644 0 : vec[i*2 + 1] = vec[i*2] = GEN_INT (i * 2);
5645 0 : vt = gen_rtx_CONST_VECTOR (maskmode, gen_rtvec_v (w, vec));
5646 0 : vt = force_reg (maskmode, vt);
5647 0 : mask = gen_lowpart (maskmode, mask);
5648 0 : if (maskmode == V8SImode)
5649 0 : emit_insn (gen_avx2_permvarv8si (t1, mask, vt));
5650 : else
5651 0 : emit_insn (gen_avx2_pshufbv32qi3 (t1, mask, vt));
5652 :
5653 : /* Multiply the shuffle indices by two. */
5654 0 : t1 = expand_simple_binop (maskmode, PLUS, t1, t1, t1, 1,
5655 : OPTAB_DIRECT);
5656 :
5657 : /* Add one to the odd shuffle indices:
5658 : t1 = { A*2, A*2+1, B*2, B*2+1, ... }. */
5659 0 : for (i = 0; i < w / 2; ++i)
5660 : {
5661 0 : vec[i * 2] = const0_rtx;
5662 0 : vec[i * 2 + 1] = const1_rtx;
5663 : }
5664 0 : vt = gen_rtx_CONST_VECTOR (maskmode, gen_rtvec_v (w, vec));
5665 0 : vt = validize_mem (force_const_mem (maskmode, vt));
5666 0 : t1 = expand_simple_binop (maskmode, PLUS, t1, vt, t1, 1,
5667 : OPTAB_DIRECT);
5668 :
5669 : /* Continue as if V8SImode (resp. V32QImode) was used initially. */
5670 0 : operands[3] = mask = t1;
5671 0 : target = gen_reg_rtx (mode);
5672 0 : op0 = gen_lowpart (mode, op0);
5673 0 : op1 = gen_lowpart (mode, op1);
5674 : }
5675 :
5676 5 : switch (mode)
5677 : {
5678 1 : case E_V8SImode:
5679 : /* The VPERMD and VPERMPS instructions already properly ignore
5680 : the high bits of the shuffle elements. No need for us to
5681 : perform an AND ourselves. */
5682 1 : if (one_operand_shuffle)
5683 : {
5684 0 : emit_insn (gen_avx2_permvarv8si (target, op0, mask));
5685 0 : if (target != operands[0])
5686 0 : emit_move_insn (operands[0],
5687 0 : gen_lowpart (GET_MODE (operands[0]), target));
5688 : }
5689 : else
5690 : {
5691 1 : t1 = gen_reg_rtx (V8SImode);
5692 1 : t2 = gen_reg_rtx (V8SImode);
5693 1 : emit_insn (gen_avx2_permvarv8si (t1, op0, mask));
5694 1 : emit_insn (gen_avx2_permvarv8si (t2, op1, mask));
5695 1 : goto merge_two;
5696 : }
5697 0 : return;
5698 :
5699 0 : case E_V8SFmode:
5700 0 : mask = gen_lowpart (V8SImode, mask);
5701 0 : if (one_operand_shuffle)
5702 0 : emit_insn (gen_avx2_permvarv8sf (target, op0, mask));
5703 : else
5704 : {
5705 0 : t1 = gen_reg_rtx (V8SFmode);
5706 0 : t2 = gen_reg_rtx (V8SFmode);
5707 0 : emit_insn (gen_avx2_permvarv8sf (t1, op0, mask));
5708 0 : emit_insn (gen_avx2_permvarv8sf (t2, op1, mask));
5709 0 : goto merge_two;
5710 : }
5711 0 : return;
5712 :
5713 1 : case E_V4SImode:
5714 1 : if (one_operand_shuffle)
5715 : break; /* Handled below for TARGET_AVX. */
5716 : /* By combining the two 128-bit input vectors into one 256-bit
5717 : input vector, we can use VPERMD and VPERMPS for the full
5718 : two-operand shuffle. */
5719 0 : t1 = gen_reg_rtx (V8SImode);
5720 0 : t2 = gen_reg_rtx (V8SImode);
5721 0 : emit_insn (gen_avx_vec_concatv8si (t1, op0, op1));
5722 0 : emit_insn (gen_avx_vec_concatv8si (t2, mask, mask));
5723 0 : emit_insn (gen_avx2_permvarv8si (t1, t1, t2));
5724 0 : emit_insn (gen_avx_vextractf128v8si (target, t1, const0_rtx));
5725 0 : return;
5726 :
5727 1 : case E_V4SFmode:
5728 1 : if (one_operand_shuffle)
5729 : break; /* Handled below for TARGET_AVX. */
5730 0 : t1 = gen_reg_rtx (V8SFmode);
5731 0 : t2 = gen_reg_rtx (V8SImode);
5732 0 : mask = gen_lowpart (V4SImode, mask);
5733 0 : emit_insn (gen_avx_vec_concatv8sf (t1, op0, op1));
5734 0 : emit_insn (gen_avx_vec_concatv8si (t2, mask, mask));
5735 0 : emit_insn (gen_avx2_permvarv8sf (t1, t1, t2));
5736 0 : emit_insn (gen_avx_vextractf128v8sf (target, t1, const0_rtx));
5737 0 : return;
5738 :
5739 0 : case E_V32QImode:
5740 0 : t1 = gen_reg_rtx (V32QImode);
5741 0 : t2 = gen_reg_rtx (V32QImode);
5742 0 : t3 = gen_reg_rtx (V32QImode);
5743 0 : vt2 = GEN_INT (-128);
5744 0 : vt = gen_const_vec_duplicate (V32QImode, vt2);
5745 0 : vt = force_reg (V32QImode, vt);
5746 0 : for (i = 0; i < 32; i++)
5747 0 : vec[i] = i < 16 ? vt2 : const0_rtx;
5748 0 : vt2 = gen_rtx_CONST_VECTOR (V32QImode, gen_rtvec_v (32, vec));
5749 0 : vt2 = force_reg (V32QImode, vt2);
5750 : /* From mask create two adjusted masks, which contain the same
5751 : bits as mask in the low 7 bits of each vector element.
5752 : The first mask will have the most significant bit clear
5753 : if it requests element from the same 128-bit lane
5754 : and MSB set if it requests element from the other 128-bit lane.
5755 : The second mask will have the opposite values of the MSB,
5756 : and additionally will have its 128-bit lanes swapped.
5757 : E.g. { 07 12 1e 09 ... | 17 19 05 1f ... } mask vector will have
5758 : t1 { 07 92 9e 09 ... | 17 19 85 1f ... } and
5759 : t3 { 97 99 05 9f ... | 87 12 1e 89 ... } where each ...
5760 : stands for other 12 bytes. */
5761 : /* The bit whether element is from the same lane or the other
5762 : lane is bit 4, so shift it up by 3 to the MSB position. */
5763 0 : t5 = gen_reg_rtx (V4DImode);
5764 0 : emit_insn (gen_ashlv4di3 (t5, gen_lowpart (V4DImode, mask),
5765 : GEN_INT (3)));
5766 : /* Clear MSB bits from the mask just in case it had them set. */
5767 0 : emit_insn (gen_avx2_andnotv32qi3 (t2, vt, mask));
5768 : /* After this t1 will have MSB set for elements from other lane. */
5769 0 : emit_insn (gen_xorv32qi3 (t1, gen_lowpart (V32QImode, t5), vt2));
5770 : /* Clear bits other than MSB. */
5771 0 : emit_insn (gen_andv32qi3 (t1, t1, vt));
5772 : /* Or in the lower bits from mask into t3. */
5773 0 : emit_insn (gen_iorv32qi3 (t3, t1, t2));
5774 : /* And invert MSB bits in t1, so MSB is set for elements from the same
5775 : lane. */
5776 0 : emit_insn (gen_xorv32qi3 (t1, t1, vt));
5777 : /* Swap 128-bit lanes in t3. */
5778 0 : t6 = gen_reg_rtx (V4DImode);
5779 0 : emit_insn (gen_avx2_permv4di_1 (t6, gen_lowpart (V4DImode, t3),
5780 : const2_rtx, GEN_INT (3),
5781 : const0_rtx, const1_rtx));
5782 : /* And or in the lower bits from mask into t1. */
5783 0 : emit_insn (gen_iorv32qi3 (t1, t1, t2));
5784 0 : if (one_operand_shuffle)
5785 : {
5786 : /* Each of these shuffles will put 0s in places where
5787 : element from the other 128-bit lane is needed, otherwise
5788 : will shuffle in the requested value. */
5789 0 : emit_insn (gen_avx2_pshufbv32qi3 (t3, op0,
5790 0 : gen_lowpart (V32QImode, t6)));
5791 0 : emit_insn (gen_avx2_pshufbv32qi3 (t1, op0, t1));
5792 : /* For t3 the 128-bit lanes are swapped again. */
5793 0 : t7 = gen_reg_rtx (V4DImode);
5794 0 : emit_insn (gen_avx2_permv4di_1 (t7, gen_lowpart (V4DImode, t3),
5795 : const2_rtx, GEN_INT (3),
5796 : const0_rtx, const1_rtx));
5797 : /* And oring both together leads to the result. */
5798 0 : emit_insn (gen_iorv32qi3 (target, t1,
5799 0 : gen_lowpart (V32QImode, t7)));
5800 0 : if (target != operands[0])
5801 0 : emit_move_insn (operands[0],
5802 0 : gen_lowpart (GET_MODE (operands[0]), target));
5803 0 : return;
5804 : }
5805 :
5806 0 : t4 = gen_reg_rtx (V32QImode);
5807 : /* Similarly to the above one_operand_shuffle code,
5808 : just for repeated twice for each operand. merge_two:
5809 : code will merge the two results together. */
5810 0 : emit_insn (gen_avx2_pshufbv32qi3 (t4, op0,
5811 0 : gen_lowpart (V32QImode, t6)));
5812 0 : emit_insn (gen_avx2_pshufbv32qi3 (t3, op1,
5813 0 : gen_lowpart (V32QImode, t6)));
5814 0 : emit_insn (gen_avx2_pshufbv32qi3 (t2, op0, t1));
5815 0 : emit_insn (gen_avx2_pshufbv32qi3 (t1, op1, t1));
5816 0 : t7 = gen_reg_rtx (V4DImode);
5817 0 : emit_insn (gen_avx2_permv4di_1 (t7, gen_lowpart (V4DImode, t4),
5818 : const2_rtx, GEN_INT (3),
5819 : const0_rtx, const1_rtx));
5820 0 : t8 = gen_reg_rtx (V4DImode);
5821 0 : emit_insn (gen_avx2_permv4di_1 (t8, gen_lowpart (V4DImode, t3),
5822 : const2_rtx, GEN_INT (3),
5823 : const0_rtx, const1_rtx));
5824 0 : emit_insn (gen_iorv32qi3 (t4, t2, gen_lowpart (V32QImode, t7)));
5825 0 : emit_insn (gen_iorv32qi3 (t3, t1, gen_lowpart (V32QImode, t8)));
5826 0 : t1 = t4;
5827 0 : t2 = t3;
5828 0 : goto merge_two;
5829 :
5830 2 : default:
5831 4 : gcc_assert (GET_MODE_SIZE (mode) <= 16);
5832 : break;
5833 : }
5834 : }
5835 :
5836 9 : if (TARGET_AVX && one_operand_shuffle)
5837 8 : switch (mode)
5838 : {
5839 2 : case V4SImode:
5840 2 : op0 = gen_lowpart (V4SFmode, op0);
5841 2 : t1 = gen_reg_rtx (V4SFmode);
5842 2 : emit_insn (gen_avx_vpermilvarv4sf3 (t1, op0, mask));
5843 2 : emit_move_insn (target, gen_lowpart (mode, t1));
5844 2 : return;
5845 2 : case V4SFmode:
5846 2 : emit_insn (gen_avx_vpermilvarv4sf3 (target, op0, mask));
5847 2 : return;
5848 2 : case V2DImode:
5849 2 : op0 = gen_lowpart (V2DFmode, op0);
5850 2 : t1 = gen_reg_rtx (V2DImode);
5851 2 : t2 = gen_reg_rtx (V2DFmode);
5852 2 : emit_insn (gen_addv2di3 (t1, mask, mask));
5853 2 : emit_insn (gen_avx_vpermilvarv2df3 (t2, op0, t1));
5854 2 : emit_move_insn (target, gen_lowpart (mode, t2));
5855 2 : return;
5856 2 : case V2DFmode:
5857 2 : t1 = gen_reg_rtx (V2DImode);
5858 2 : emit_insn (gen_addv2di3 (t1, mask, mask));
5859 2 : emit_insn (gen_avx_vpermilvarv2df3 (target, op0, t1));
5860 2 : return;
5861 : default:
5862 : break;
5863 : }
5864 :
5865 1 : if (TARGET_XOP)
5866 : {
5867 : /* The XOP VPPERM insn supports three inputs. By ignoring the
5868 : one_operand_shuffle special case, we avoid creating another
5869 : set of constant vectors in memory. */
5870 0 : one_operand_shuffle = false;
5871 :
5872 : /* mask = mask & {2*w-1, ...} */
5873 0 : vt = GEN_INT (2*w - 1);
5874 : }
5875 : else
5876 : {
5877 : /* mask = mask & {w-1, ...} */
5878 1 : vt = GEN_INT (w - 1);
5879 : }
5880 :
5881 1 : vt = gen_const_vec_duplicate (maskmode, vt);
5882 1 : mask = expand_simple_binop (maskmode, AND, mask, vt,
5883 : NULL_RTX, 0, OPTAB_DIRECT);
5884 :
5885 : /* For non-QImode operations, convert the word permutation control
5886 : into a byte permutation control. */
5887 1 : if (mode != V16QImode)
5888 : {
5889 1 : mask = expand_simple_binop (maskmode, ASHIFT, mask,
5890 2 : GEN_INT (exact_log2 (e)),
5891 : NULL_RTX, 0, OPTAB_DIRECT);
5892 :
5893 : /* Convert mask to vector of chars. */
5894 1 : mask = force_reg (V16QImode, gen_lowpart (V16QImode, mask));
5895 :
5896 : /* Replicate each of the input bytes into byte positions:
5897 : (v2di) --> {0,0,0,0,0,0,0,0, 8,8,8,8,8,8,8,8}
5898 : (v4si) --> {0,0,0,0, 4,4,4,4, 8,8,8,8, 12,12,12,12}
5899 : (v8hi) --> {0,0, 2,2, 4,4, 6,6, ...}. */
5900 18 : for (i = 0; i < 16; ++i)
5901 16 : vec[i] = GEN_INT (i/e * e);
5902 1 : vt = gen_rtx_CONST_VECTOR (V16QImode, gen_rtvec_v (16, vec));
5903 1 : vt = validize_mem (force_const_mem (V16QImode, vt));
5904 1 : if (TARGET_XOP)
5905 0 : emit_insn (gen_xop_pperm (mask, mask, mask, vt));
5906 : else
5907 1 : emit_insn (gen_ssse3_pshufbv16qi3 (mask, mask, vt));
5908 :
5909 : /* Convert it into the byte positions by doing
5910 : mask = mask + {0,1,..,16/w, 0,1,..,16/w, ...} */
5911 17 : for (i = 0; i < 16; ++i)
5912 16 : vec[i] = GEN_INT (i % e);
5913 1 : vt = gen_rtx_CONST_VECTOR (V16QImode, gen_rtvec_v (16, vec));
5914 1 : vt = validize_mem (force_const_mem (V16QImode, vt));
5915 1 : emit_insn (gen_addv16qi3 (mask, mask, vt));
5916 : }
5917 :
5918 : /* The actual shuffle operations all operate on V16QImode. */
5919 1 : op0 = gen_lowpart (V16QImode, op0);
5920 1 : op1 = gen_lowpart (V16QImode, op1);
5921 :
5922 1 : if (TARGET_XOP)
5923 : {
5924 0 : if (GET_MODE (target) != V16QImode)
5925 0 : target = gen_reg_rtx (V16QImode);
5926 0 : emit_insn (gen_xop_pperm (target, op0, op1, mask));
5927 0 : if (target != operands[0])
5928 0 : emit_move_insn (operands[0],
5929 0 : gen_lowpart (GET_MODE (operands[0]), target));
5930 : }
5931 1 : else if (one_operand_shuffle)
5932 : {
5933 1 : if (GET_MODE (target) != V16QImode)
5934 1 : target = gen_reg_rtx (V16QImode);
5935 1 : emit_insn (gen_ssse3_pshufbv16qi3 (target, op0, mask));
5936 1 : if (target != operands[0])
5937 1 : emit_move_insn (operands[0],
5938 1 : gen_lowpart (GET_MODE (operands[0]), target));
5939 : }
5940 : else
5941 : {
5942 0 : rtx xops[6];
5943 0 : bool ok;
5944 :
5945 : /* Shuffle the two input vectors independently. */
5946 0 : t1 = gen_reg_rtx (V16QImode);
5947 0 : t2 = gen_reg_rtx (V16QImode);
5948 0 : emit_insn (gen_ssse3_pshufbv16qi3 (t1, op0, mask));
5949 0 : emit_insn (gen_ssse3_pshufbv16qi3 (t2, op1, mask));
5950 :
5951 1 : merge_two:
5952 : /* Then merge them together. The key is whether any given control
5953 : element contained a bit set that indicates the second word. */
5954 1 : mask = operands[3];
5955 1 : vt = GEN_INT (w);
5956 1 : if (maskmode == V2DImode && !TARGET_SSE4_1)
5957 : {
5958 : /* Without SSE4.1, we don't have V2DImode EQ. Perform one
5959 : more shuffle to convert the V2DI input mask into a V4SI
5960 : input mask. At which point the masking that expand_int_vcond
5961 : will work as desired. */
5962 0 : rtx t3 = gen_reg_rtx (V4SImode);
5963 0 : emit_insn (gen_sse2_pshufd_1 (t3, gen_lowpart (V4SImode, mask),
5964 : const0_rtx, const0_rtx,
5965 : const2_rtx, const2_rtx));
5966 0 : mask = t3;
5967 0 : maskmode = V4SImode;
5968 0 : e = w = 4;
5969 : }
5970 :
5971 1 : vt = gen_const_vec_duplicate (maskmode, vt);
5972 1 : vt = force_reg (maskmode, vt);
5973 1 : mask = expand_simple_binop (maskmode, AND, mask, vt,
5974 : NULL_RTX, 0, OPTAB_DIRECT);
5975 :
5976 1 : if (GET_MODE (target) != mode)
5977 0 : target = gen_reg_rtx (mode);
5978 1 : xops[0] = target;
5979 1 : xops[1] = gen_lowpart (mode, t2);
5980 1 : xops[2] = gen_lowpart (mode, t1);
5981 1 : xops[3] = gen_rtx_EQ (maskmode, mask, vt);
5982 1 : xops[4] = mask;
5983 1 : xops[5] = vt;
5984 1 : ok = ix86_expand_int_vcond (xops);
5985 1 : gcc_assert (ok);
5986 1 : if (target != operands[0])
5987 0 : emit_move_insn (operands[0],
5988 0 : gen_lowpart (GET_MODE (operands[0]), target));
5989 : }
5990 : }
5991 :
5992 : /* Extend SRC into next wider integer vector type. UNSIGNED_P is
5993 : true if we should do zero extension, else sign extension. */
5994 :
5995 : void
5996 489 : ix86_expand_sse_extend (rtx dest, rtx src, bool unsigned_p)
5997 : {
5998 489 : machine_mode imode = GET_MODE (src);
5999 489 : rtx ops[3];
6000 :
6001 489 : switch (imode)
6002 : {
6003 489 : case E_V8QImode:
6004 489 : case E_V4QImode:
6005 489 : case E_V2QImode:
6006 489 : case E_V4HImode:
6007 489 : case E_V2HImode:
6008 489 : case E_V2SImode:
6009 489 : break;
6010 0 : default:
6011 0 : gcc_unreachable ();
6012 : }
6013 :
6014 489 : ops[0] = dest;
6015 :
6016 489 : ops[1] = force_reg (imode, src);
6017 :
6018 489 : if (unsigned_p)
6019 105 : ops[2] = force_reg (imode, CONST0_RTX (imode));
6020 : else
6021 384 : ops[2] = ix86_expand_sse_cmp (gen_reg_rtx (imode), GT, CONST0_RTX (imode),
6022 : ops[1], pc_rtx, pc_rtx);
6023 :
6024 489 : ix86_split_mmx_punpck (ops, false);
6025 489 : }
6026 :
6027 : /* Unpack SRC into the next wider integer vector type. UNSIGNED_P is
6028 : true if we should do zero extension, else sign extension. HIGH_P is
6029 : true if we want the N/2 high elements, else the low elements. */
6030 :
6031 : void
6032 19278 : ix86_expand_sse_unpack (rtx dest, rtx src, bool unsigned_p, bool high_p)
6033 : {
6034 19278 : machine_mode imode = GET_MODE (src);
6035 19278 : rtx tmp;
6036 :
6037 19278 : if (TARGET_SSE4_1)
6038 : {
6039 6476 : rtx (*unpack)(rtx, rtx);
6040 6476 : rtx (*extract)(rtx, rtx) = NULL;
6041 6476 : machine_mode halfmode = BLKmode;
6042 :
6043 6476 : switch (imode)
6044 : {
6045 198 : case E_V64QImode:
6046 198 : if (unsigned_p)
6047 : unpack = gen_avx512bw_zero_extendv32qiv32hi2;
6048 : else
6049 64 : unpack = gen_avx512bw_sign_extendv32qiv32hi2;
6050 198 : halfmode = V32QImode;
6051 198 : extract
6052 198 : = high_p ? gen_vec_extract_hi_v64qi : gen_vec_extract_lo_v64qi;
6053 : break;
6054 719 : case E_V32QImode:
6055 719 : if (unsigned_p)
6056 : unpack = gen_avx2_zero_extendv16qiv16hi2;
6057 : else
6058 150 : unpack = gen_avx2_sign_extendv16qiv16hi2;
6059 719 : halfmode = V16QImode;
6060 719 : extract
6061 719 : = high_p ? gen_vec_extract_hi_v32qi : gen_vec_extract_lo_v32qi;
6062 : break;
6063 104 : case E_V32HImode:
6064 104 : if (unsigned_p)
6065 : unpack = gen_avx512f_zero_extendv16hiv16si2;
6066 : else
6067 64 : unpack = gen_avx512f_sign_extendv16hiv16si2;
6068 104 : halfmode = V16HImode;
6069 104 : extract
6070 104 : = high_p ? gen_vec_extract_hi_v32hi : gen_vec_extract_lo_v32hi;
6071 : break;
6072 429 : case E_V16HImode:
6073 429 : if (unsigned_p)
6074 : unpack = gen_avx2_zero_extendv8hiv8si2;
6075 : else
6076 314 : unpack = gen_avx2_sign_extendv8hiv8si2;
6077 429 : halfmode = V8HImode;
6078 429 : extract
6079 429 : = high_p ? gen_vec_extract_hi_v16hi : gen_vec_extract_lo_v16hi;
6080 : break;
6081 104 : case E_V16SImode:
6082 104 : if (unsigned_p)
6083 : unpack = gen_avx512f_zero_extendv8siv8di2;
6084 : else
6085 86 : unpack = gen_avx512f_sign_extendv8siv8di2;
6086 104 : halfmode = V8SImode;
6087 104 : extract
6088 104 : = high_p ? gen_vec_extract_hi_v16si : gen_vec_extract_lo_v16si;
6089 : break;
6090 382 : case E_V8SImode:
6091 382 : if (unsigned_p)
6092 : unpack = gen_avx2_zero_extendv4siv4di2;
6093 : else
6094 320 : unpack = gen_avx2_sign_extendv4siv4di2;
6095 382 : halfmode = V4SImode;
6096 382 : extract
6097 382 : = high_p ? gen_vec_extract_hi_v8si : gen_vec_extract_lo_v8si;
6098 : break;
6099 2597 : case E_V16QImode:
6100 2597 : if (unsigned_p)
6101 : unpack = gen_sse4_1_zero_extendv8qiv8hi2;
6102 : else
6103 270 : unpack = gen_sse4_1_sign_extendv8qiv8hi2;
6104 : break;
6105 993 : case E_V8HImode:
6106 993 : if (unsigned_p)
6107 : unpack = gen_sse4_1_zero_extendv4hiv4si2;
6108 : else
6109 776 : unpack = gen_sse4_1_sign_extendv4hiv4si2;
6110 : break;
6111 546 : case E_V4SImode:
6112 546 : if (unsigned_p)
6113 : unpack = gen_sse4_1_zero_extendv2siv2di2;
6114 : else
6115 486 : unpack = gen_sse4_1_sign_extendv2siv2di2;
6116 : break;
6117 119 : case E_V8QImode:
6118 119 : if (unsigned_p)
6119 : unpack = gen_sse4_1_zero_extendv4qiv4hi2;
6120 : else
6121 78 : unpack = gen_sse4_1_sign_extendv4qiv4hi2;
6122 : break;
6123 279 : case E_V4HImode:
6124 279 : if (unsigned_p)
6125 : unpack = gen_sse4_1_zero_extendv2hiv2si2;
6126 : else
6127 220 : unpack = gen_sse4_1_sign_extendv2hiv2si2;
6128 : break;
6129 6 : case E_V4QImode:
6130 6 : if (unsigned_p)
6131 : unpack = gen_sse4_1_zero_extendv2qiv2hi2;
6132 : else
6133 0 : unpack = gen_sse4_1_sign_extendv2qiv2hi2;
6134 : break;
6135 0 : default:
6136 0 : gcc_unreachable ();
6137 : }
6138 :
6139 12952 : if (GET_MODE_SIZE (imode) >= 32)
6140 : {
6141 1936 : tmp = gen_reg_rtx (halfmode);
6142 1936 : emit_insn (extract (tmp, src));
6143 : }
6144 4540 : else if (high_p)
6145 : {
6146 2354 : switch (GET_MODE_SIZE (imode))
6147 : {
6148 972 : case 16:
6149 : /* Shift higher 8 bytes to lower 8 bytes. */
6150 972 : tmp = gen_reg_rtx (V1TImode);
6151 972 : emit_insn (gen_sse2_lshrv1ti3 (tmp, gen_lowpart (V1TImode, src),
6152 : GEN_INT (64)));
6153 972 : break;
6154 202 : case 8:
6155 : /* Shift higher 4 bytes to lower 4 bytes. */
6156 202 : tmp = gen_reg_rtx (V1DImode);
6157 202 : emit_insn (gen_mmx_lshrv1di3 (tmp, gen_lowpart (V1DImode, src),
6158 : GEN_INT (32)));
6159 202 : break;
6160 3 : case 4:
6161 : /* Shift higher 2 bytes to lower 2 bytes. */
6162 3 : tmp = gen_reg_rtx (V1SImode);
6163 3 : emit_insn (gen_mmx_lshrv1si3 (tmp, gen_lowpart (V1SImode, src),
6164 : GEN_INT (16)));
6165 3 : break;
6166 0 : default:
6167 0 : gcc_unreachable ();
6168 : }
6169 :
6170 1177 : tmp = gen_lowpart (imode, tmp);
6171 : }
6172 : else
6173 : tmp = src;
6174 :
6175 6476 : emit_insn (unpack (dest, tmp));
6176 : }
6177 : else
6178 : {
6179 12802 : rtx (*unpack)(rtx, rtx, rtx);
6180 :
6181 12802 : switch (imode)
6182 : {
6183 3532 : case E_V16QImode:
6184 3532 : if (high_p)
6185 : unpack = gen_vec_interleave_highv16qi;
6186 : else
6187 1769 : unpack = gen_vec_interleave_lowv16qi;
6188 : break;
6189 5266 : case E_V8HImode:
6190 5266 : if (high_p)
6191 : unpack = gen_vec_interleave_highv8hi;
6192 : else
6193 2633 : unpack = gen_vec_interleave_lowv8hi;
6194 : break;
6195 2348 : case E_V4SImode:
6196 2348 : if (high_p)
6197 : unpack = gen_vec_interleave_highv4si;
6198 : else
6199 1174 : unpack = gen_vec_interleave_lowv4si;
6200 : break;
6201 564 : case E_V8QImode:
6202 564 : if (high_p)
6203 : unpack = gen_mmx_punpckhbw;
6204 : else
6205 282 : unpack = gen_mmx_punpcklbw;
6206 : break;
6207 1078 : case E_V4HImode:
6208 1078 : if (high_p)
6209 : unpack = gen_mmx_punpckhwd;
6210 : else
6211 539 : unpack = gen_mmx_punpcklwd;
6212 : break;
6213 14 : case E_V4QImode:
6214 14 : if (high_p)
6215 : unpack = gen_mmx_punpckhbw_low;
6216 : else
6217 7 : unpack = gen_mmx_punpcklbw_low;
6218 : break;
6219 0 : default:
6220 0 : gcc_unreachable ();
6221 : }
6222 :
6223 12802 : if (unsigned_p)
6224 4990 : tmp = force_reg (imode, CONST0_RTX (imode));
6225 : else
6226 7812 : tmp = ix86_expand_sse_cmp (gen_reg_rtx (imode), GT, CONST0_RTX (imode),
6227 : src, pc_rtx, pc_rtx);
6228 :
6229 12802 : rtx tmp2 = gen_reg_rtx (imode);
6230 12802 : emit_insn (unpack (tmp2, src, tmp));
6231 12802 : emit_move_insn (dest, gen_lowpart (GET_MODE (dest), tmp2));
6232 : }
6233 19278 : }
6234 :
6235 : /* Return true if mem is pool constant which contains a const_vector
6236 : perm index, assign the index to PERM. */
6237 : bool
6238 35 : ix86_extract_perm_from_pool_constant (int* perm, rtx mem)
6239 : {
6240 35 : machine_mode mode = GET_MODE (mem);
6241 35 : int nelt = GET_MODE_NUNITS (mode);
6242 :
6243 35 : if (!INTEGRAL_MODE_P (mode))
6244 : return false;
6245 :
6246 : /* Needs to be constant pool. */
6247 35 : if (!(MEM_P (mem))
6248 35 : || !SYMBOL_REF_P (XEXP (mem, 0))
6249 70 : || !CONSTANT_POOL_ADDRESS_P (XEXP (mem, 0)))
6250 : return false;
6251 :
6252 35 : rtx constant = get_pool_constant (XEXP (mem, 0));
6253 :
6254 35 : if (!CONST_VECTOR_P (constant))
6255 : return false;
6256 :
6257 : /* There could be some rtx like
6258 : (mem/u/c:V16QI (symbol_ref/u:DI ("*.LC1")))
6259 : but with "*.LC1" refer to V2DI constant vector. */
6260 35 : if (GET_MODE (constant) != mode)
6261 : {
6262 0 : constant = simplify_subreg (mode, constant, GET_MODE (constant), 0);
6263 :
6264 0 : if (constant == nullptr || !CONST_VECTOR_P (constant))
6265 : return false;
6266 : }
6267 :
6268 771 : for (int i = 0; i != nelt; i++)
6269 736 : perm[i] = UINTVAL (XVECEXP (constant, 0, i));
6270 :
6271 : return true;
6272 : }
6273 :
6274 : /* Split operands 0 and 1 into half-mode parts. Similar to split_double_mode,
6275 : but works for floating pointer parameters and nonoffsetable memories.
6276 : For pushes, it returns just stack offsets; the values will be saved
6277 : in the right order. Maximally three parts are generated. */
6278 :
6279 : static int
6280 4150262 : ix86_split_to_parts (rtx operand, rtx *parts, machine_mode mode)
6281 : {
6282 4150262 : int size;
6283 :
6284 4150262 : if (!TARGET_64BIT)
6285 1561714 : size = mode==XFmode ? 3 : GET_MODE_SIZE (mode) / 4;
6286 : else
6287 6737484 : size = (GET_MODE_SIZE (mode) + 4) / 8;
6288 :
6289 4150262 : gcc_assert (!REG_P (operand) || !MMX_REGNO_P (REGNO (operand)));
6290 4150262 : gcc_assert (size >= 2 && size <= 4);
6291 :
6292 : /* Optimize constant pool reference to immediates. This is used by fp
6293 : moves, that force all constants to memory to allow combining. */
6294 4150262 : if (MEM_P (operand) && MEM_READONLY_P (operand))
6295 38113 : operand = avoid_constant_pool_reference (operand);
6296 :
6297 4150262 : if (MEM_P (operand) && !offsettable_memref_p (operand))
6298 : {
6299 : /* The only non-offsetable memories we handle are pushes. */
6300 184109 : int ok = push_operand (operand, VOIDmode);
6301 :
6302 184109 : gcc_assert (ok);
6303 :
6304 184109 : operand = copy_rtx (operand);
6305 184109 : PUT_MODE (operand, word_mode);
6306 184109 : parts[0] = parts[1] = parts[2] = parts[3] = operand;
6307 184109 : return size;
6308 : }
6309 :
6310 3966153 : if (CONST_VECTOR_P (operand))
6311 : {
6312 41976 : scalar_int_mode imode = int_mode_for_mode (mode).require ();
6313 : /* Caution: if we looked through a constant pool memory above,
6314 : the operand may actually have a different mode now. That's
6315 : ok, since we want to pun this all the way back to an integer. */
6316 41976 : operand = simplify_subreg (imode, operand, GET_MODE (operand), 0);
6317 41976 : gcc_assert (operand != NULL);
6318 41976 : mode = imode;
6319 : }
6320 :
6321 3966153 : if (!TARGET_64BIT)
6322 : {
6323 622897 : if (mode == DImode)
6324 493776 : split_double_mode (mode, &operand, 1, &parts[0], &parts[1]);
6325 : else
6326 : {
6327 129121 : int i;
6328 :
6329 129121 : if (REG_P (operand))
6330 : {
6331 66946 : gcc_assert (reload_completed);
6332 200838 : for (i = 0; i < size; i++)
6333 133892 : parts[i] = gen_rtx_REG (SImode, REGNO (operand) + i);
6334 : }
6335 62175 : else if (offsettable_memref_p (operand))
6336 : {
6337 60827 : operand = adjust_address (operand, SImode, 0);
6338 60827 : parts[0] = operand;
6339 122188 : for (i = 1; i < size; i++)
6340 61361 : parts[i] = adjust_address (operand, SImode, 4 * i);
6341 : }
6342 1348 : else if (CONST_DOUBLE_P (operand))
6343 : {
6344 1348 : const REAL_VALUE_TYPE *r;
6345 1348 : long l[4];
6346 :
6347 1348 : r = CONST_DOUBLE_REAL_VALUE (operand);
6348 1348 : switch (mode)
6349 : {
6350 0 : case E_TFmode:
6351 0 : real_to_target (l, r, mode);
6352 0 : parts[3] = gen_int_mode (l[3], SImode);
6353 0 : parts[2] = gen_int_mode (l[2], SImode);
6354 0 : break;
6355 198 : case E_XFmode:
6356 : /* We can't use REAL_VALUE_TO_TARGET_LONG_DOUBLE since
6357 : long double may not be 80-bit. */
6358 198 : real_to_target (l, r, mode);
6359 198 : parts[2] = gen_int_mode (l[2], SImode);
6360 198 : break;
6361 1150 : case E_DFmode:
6362 1150 : REAL_VALUE_TO_TARGET_DOUBLE (*r, l);
6363 1150 : break;
6364 0 : default:
6365 0 : gcc_unreachable ();
6366 : }
6367 1348 : parts[1] = gen_int_mode (l[1], SImode);
6368 1348 : parts[0] = gen_int_mode (l[0], SImode);
6369 : }
6370 : else
6371 0 : gcc_unreachable ();
6372 : }
6373 : }
6374 : else
6375 : {
6376 3343256 : if (mode == TImode)
6377 3323094 : split_double_mode (mode, &operand, 1, &parts[0], &parts[1]);
6378 3343256 : if (mode == XFmode || mode == TFmode)
6379 : {
6380 20162 : machine_mode upper_mode = mode==XFmode ? SImode : DImode;
6381 20162 : if (REG_P (operand))
6382 : {
6383 1494 : gcc_assert (reload_completed);
6384 1494 : parts[0] = gen_rtx_REG (DImode, REGNO (operand) + 0);
6385 1494 : parts[1] = gen_rtx_REG (upper_mode, REGNO (operand) + 1);
6386 : }
6387 18668 : else if (offsettable_memref_p (operand))
6388 : {
6389 14571 : operand = adjust_address (operand, DImode, 0);
6390 14571 : parts[0] = operand;
6391 14571 : parts[1] = adjust_address (operand, upper_mode, 8);
6392 : }
6393 4097 : else if (CONST_DOUBLE_P (operand))
6394 : {
6395 4097 : long l[4];
6396 :
6397 4097 : real_to_target (l, CONST_DOUBLE_REAL_VALUE (operand), mode);
6398 :
6399 : /* real_to_target puts 32-bit pieces in each long. */
6400 8194 : parts[0] = gen_int_mode ((l[0] & HOST_WIDE_INT_C (0xffffffff))
6401 4097 : | ((l[1] & HOST_WIDE_INT_C (0xffffffff))
6402 4097 : << 32), DImode);
6403 :
6404 4097 : if (upper_mode == SImode)
6405 2911 : parts[1] = gen_int_mode (l[2], SImode);
6406 : else
6407 1186 : parts[1]
6408 1186 : = gen_int_mode ((l[2] & HOST_WIDE_INT_C (0xffffffff))
6409 1186 : | ((l[3] & HOST_WIDE_INT_C (0xffffffff))
6410 1186 : << 32), DImode);
6411 : }
6412 : else
6413 0 : gcc_unreachable ();
6414 : }
6415 : }
6416 :
6417 : return size;
6418 : }
6419 :
6420 : /* Emit insns to perform a move or push of DI, DF, XF, and TF values.
6421 : Return false when normal moves are needed; true when all required
6422 : insns have been emitted. Operands 2-4 contain the input values
6423 : int the correct order; operands 5-7 contain the output values. */
6424 :
6425 : void
6426 2088091 : ix86_split_long_move (rtx operands[])
6427 : {
6428 2088091 : rtx part[2][4];
6429 2088091 : int nparts, i, j;
6430 2088091 : int push = 0;
6431 2088091 : int collisions = 0;
6432 2088091 : machine_mode mode = GET_MODE (operands[0]);
6433 2088091 : bool collisionparts[4];
6434 :
6435 : /* The DFmode expanders may ask us to move double.
6436 : For 64bit target this is single move. By hiding the fact
6437 : here we simplify i386.md splitters. */
6438 3785422 : if (TARGET_64BIT && GET_MODE_SIZE (GET_MODE (operands[0])) == 8)
6439 : {
6440 : /* Optimize constant pool reference to immediates. This is used by
6441 : fp moves, that force all constants to memory to allow combining. */
6442 :
6443 12960 : if (MEM_P (operands[1])
6444 12537 : && SYMBOL_REF_P (XEXP (operands[1], 0))
6445 13604 : && CONSTANT_POOL_ADDRESS_P (XEXP (operands[1], 0)))
6446 155 : operands[1] = get_pool_constant (XEXP (operands[1], 0));
6447 12960 : if (push_operand (operands[0], VOIDmode))
6448 : {
6449 12960 : operands[0] = copy_rtx (operands[0]);
6450 12960 : PUT_MODE (operands[0], word_mode);
6451 : }
6452 : else
6453 0 : operands[0] = gen_lowpart (DImode, operands[0]);
6454 12960 : operands[1] = gen_lowpart (DImode, operands[1]);
6455 12960 : emit_move_insn (operands[0], operands[1]);
6456 12960 : return;
6457 : }
6458 :
6459 : /* The only non-offsettable memory we handle is push. */
6460 2075131 : if (push_operand (operands[0], VOIDmode))
6461 : push = 1;
6462 : else
6463 1891022 : gcc_assert (!MEM_P (operands[0])
6464 : || offsettable_memref_p (operands[0]));
6465 :
6466 2075131 : nparts = ix86_split_to_parts (operands[1], part[1], GET_MODE (operands[0]));
6467 2075131 : ix86_split_to_parts (operands[0], part[0], GET_MODE (operands[0]));
6468 :
6469 : /* When emitting push, take care for source operands on the stack. */
6470 184109 : if (push && MEM_P (operands[1])
6471 2172615 : && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
6472 : {
6473 56576 : rtx src_base = XEXP (part[1][nparts - 1], 0);
6474 :
6475 : /* Compensate for the stack decrement by 4. */
6476 56576 : if (!TARGET_64BIT && nparts == 3
6477 51875 : && mode == XFmode && TARGET_128BIT_LONG_DOUBLE)
6478 0 : src_base = plus_constant (Pmode, src_base, 4);
6479 :
6480 : /* src_base refers to the stack pointer and is
6481 : automatically decreased by emitted push. */
6482 170007 : for (i = 0; i < nparts; i++)
6483 113431 : part[1][i] = change_address (part[1][i],
6484 113431 : GET_MODE (part[1][i]), src_base);
6485 : }
6486 :
6487 : /* We need to do copy in the right order in case an address register
6488 : of the source overlaps the destination. */
6489 2075131 : if (REG_P (part[0][0]) && MEM_P (part[1][0]))
6490 : {
6491 : rtx tmp;
6492 :
6493 2373597 : for (i = 0; i < nparts; i++)
6494 : {
6495 1582398 : collisionparts[i]
6496 1582398 : = reg_overlap_mentioned_p (part[0][i], XEXP (part[1][0], 0));
6497 1582398 : if (collisionparts[i])
6498 16890 : collisions++;
6499 : }
6500 :
6501 : /* Collision in the middle part can be handled by reordering. */
6502 791199 : if (collisions == 1 && nparts == 3 && collisionparts [1])
6503 : {
6504 0 : std::swap (part[0][1], part[0][2]);
6505 0 : std::swap (part[1][1], part[1][2]);
6506 : }
6507 791199 : else if (collisions == 1
6508 791199 : && nparts == 4
6509 0 : && (collisionparts [1] || collisionparts [2]))
6510 : {
6511 0 : if (collisionparts [1])
6512 : {
6513 0 : std::swap (part[0][1], part[0][2]);
6514 0 : std::swap (part[1][1], part[1][2]);
6515 : }
6516 : else
6517 : {
6518 0 : std::swap (part[0][2], part[0][3]);
6519 0 : std::swap (part[1][2], part[1][3]);
6520 : }
6521 : }
6522 :
6523 : /* If there are more collisions, we can't handle it by reordering.
6524 : Do an lea to the last part and use only one colliding move. */
6525 791199 : else if (collisions > 1)
6526 : {
6527 76 : rtx base, addr;
6528 :
6529 76 : collisions = 1;
6530 :
6531 76 : base = part[0][nparts - 1];
6532 :
6533 : /* Handle the case when the last part isn't valid for lea.
6534 : Happens in 64-bit mode storing the 12-byte XFmode. */
6535 110 : if (GET_MODE (base) != Pmode)
6536 0 : base = gen_rtx_REG (Pmode, REGNO (base));
6537 :
6538 76 : addr = XEXP (part[1][0], 0);
6539 76 : if (TARGET_TLS_DIRECT_SEG_REFS)
6540 : {
6541 76 : struct ix86_address parts;
6542 76 : int ok = ix86_decompose_address (addr, &parts);
6543 76 : gcc_assert (ok);
6544 : /* It is not valid to use %gs: or %fs: in lea. */
6545 76 : gcc_assert (parts.seg == ADDR_SPACE_GENERIC);
6546 : }
6547 76 : emit_insn (gen_rtx_SET (base, addr));
6548 76 : part[1][0] = replace_equiv_address (part[1][0], base);
6549 152 : for (i = 1; i < nparts; i++)
6550 : {
6551 144 : tmp = plus_constant (Pmode, base, UNITS_PER_WORD * i);
6552 76 : part[1][i] = replace_equiv_address (part[1][i], tmp);
6553 : }
6554 : }
6555 : }
6556 :
6557 2075131 : if (push)
6558 : {
6559 184109 : if (!TARGET_64BIT)
6560 : {
6561 158623 : if (nparts == 3)
6562 : {
6563 594 : if (TARGET_128BIT_LONG_DOUBLE && mode == XFmode)
6564 0 : emit_insn (gen_add2_insn (stack_pointer_rtx, GEN_INT (-4)));
6565 594 : emit_move_insn (part[0][2], part[1][2]);
6566 : }
6567 158029 : else if (nparts == 4)
6568 : {
6569 0 : emit_move_insn (part[0][3], part[1][3]);
6570 0 : emit_move_insn (part[0][2], part[1][2]);
6571 : }
6572 : }
6573 : else
6574 : {
6575 : /* In 64bit mode we don't have 32bit push available. In case this is
6576 : register, it is OK - we will just use larger counterpart. We also
6577 : retype memory - these comes from attempt to avoid REX prefix on
6578 : moving of second half of TFmode value. */
6579 25486 : if (GET_MODE (part[1][1]) == SImode)
6580 : {
6581 11313 : switch (GET_CODE (part[1][1]))
6582 : {
6583 10879 : case MEM:
6584 10879 : part[1][1] = adjust_address (part[1][1], DImode, 0);
6585 10879 : break;
6586 :
6587 434 : case REG:
6588 434 : part[1][1] = gen_rtx_REG (DImode, REGNO (part[1][1]));
6589 434 : break;
6590 :
6591 0 : default:
6592 0 : gcc_unreachable ();
6593 : }
6594 :
6595 11313 : if (GET_MODE (part[1][0]) == SImode)
6596 0 : part[1][0] = part[1][1];
6597 : }
6598 : }
6599 184109 : emit_move_insn (part[0][1], part[1][1]);
6600 184109 : emit_move_insn (part[0][0], part[1][0]);
6601 184109 : return;
6602 : }
6603 :
6604 : /* Choose correct order to not overwrite the source before it is copied. */
6605 1891022 : if ((REG_P (part[0][0])
6606 1032617 : && REG_P (part[1][1])
6607 82667 : && (REGNO (part[0][0]) == REGNO (part[1][1])
6608 67340 : || (nparts == 3
6609 0 : && REGNO (part[0][0]) == REGNO (part[1][2]))
6610 67340 : || (nparts == 4
6611 0 : && REGNO (part[0][0]) == REGNO (part[1][3]))))
6612 2908312 : || (collisions > 0
6613 16814 : && reg_overlap_mentioned_p (part[0][0], XEXP (part[1][0], 0))))
6614 : {
6615 95658 : for (i = 0, j = nparts - 1; i < nparts; i++, j--)
6616 : {
6617 63772 : operands[2 + i] = part[0][j];
6618 63772 : operands[6 + i] = part[1][j];
6619 : }
6620 : }
6621 : else
6622 : {
6623 5577477 : for (i = 0; i < nparts; i++)
6624 : {
6625 3718341 : operands[2 + i] = part[0][i];
6626 3718341 : operands[6 + i] = part[1][i];
6627 : }
6628 : }
6629 :
6630 : /* Attempt to locally unCSE nonzero constants. */
6631 3782113 : for (j = 0; j < nparts - 1; j++)
6632 1891091 : if (CONST_INT_P (operands[6 + j])
6633 226021 : && operands[6 + j] != const0_rtx
6634 63535 : && REG_P (operands[2 + j]))
6635 112936 : for (i = j; i < nparts - 1; i++)
6636 56468 : if (CONST_INT_P (operands[7 + i])
6637 56468 : && INTVAL (operands[7 + i]) == INTVAL (operands[6 + j]))
6638 22607 : operands[7 + i] = operands[2 + j];
6639 :
6640 5673135 : for (i = 0; i < nparts; i++)
6641 3782113 : emit_move_insn (operands[2 + i], operands[6 + i]);
6642 :
6643 : return;
6644 : }
6645 :
6646 : /* Helper function of ix86_split_ashl used to generate an SImode/DImode
6647 : left shift by a constant, either using a single shift or
6648 : a sequence of add instructions. */
6649 :
6650 : static void
6651 4364 : ix86_expand_ashl_const (rtx operand, int count, machine_mode mode)
6652 : {
6653 4364 : if (count == 1
6654 4364 : || (count * ix86_cost->add <= ix86_cost->shift_const
6655 0 : && !optimize_insn_for_size_p ()))
6656 : {
6657 16 : while (count-- > 0)
6658 8 : emit_insn (gen_add2_insn (operand, operand));
6659 : }
6660 : else
6661 : {
6662 4356 : rtx (*insn)(rtx, rtx, rtx);
6663 :
6664 4356 : insn = mode == DImode ? gen_ashlsi3 : gen_ashldi3;
6665 4356 : emit_insn (insn (operand, operand, GEN_INT (count)));
6666 : }
6667 4364 : }
6668 :
6669 : void
6670 10520 : ix86_split_ashl (rtx *operands, rtx scratch, machine_mode mode)
6671 : {
6672 10520 : rtx (*gen_ashl3)(rtx, rtx, rtx);
6673 10520 : rtx (*gen_shld)(rtx, rtx, rtx);
6674 10520 : int half_width = GET_MODE_BITSIZE (mode) >> 1;
6675 10520 : machine_mode half_mode;
6676 :
6677 10520 : rtx low[2], high[2];
6678 10520 : int count;
6679 :
6680 10520 : if (CONST_INT_P (operands[2]))
6681 : {
6682 8812 : split_double_mode (mode, operands, 2, low, high);
6683 8812 : count = INTVAL (operands[2]) & (GET_MODE_BITSIZE (mode) - 1);
6684 :
6685 8812 : if (count >= half_width)
6686 : {
6687 2723 : emit_move_insn (high[0], low[1]);
6688 2723 : ix86_expand_clear (low[0]);
6689 :
6690 2723 : if (count > half_width)
6691 145 : ix86_expand_ashl_const (high[0], count - half_width, mode);
6692 : }
6693 6089 : else if (count == 1)
6694 : {
6695 1870 : if (!rtx_equal_p (operands[0], operands[1]))
6696 0 : emit_move_insn (operands[0], operands[1]);
6697 1870 : rtx x3 = gen_rtx_REG (CCCmode, FLAGS_REG);
6698 1870 : rtx x4 = gen_rtx_LTU (mode, x3, const0_rtx);
6699 1870 : half_mode = mode == DImode ? SImode : DImode;
6700 1870 : emit_insn (gen_add3_cc_overflow_1 (half_mode, low[0],
6701 : low[0], low[0]));
6702 1870 : emit_insn (gen_add3_carry (half_mode, high[0], high[0], high[0],
6703 : x3, x4));
6704 : }
6705 : else
6706 : {
6707 4219 : gen_shld = mode == DImode ? gen_x86_shld : gen_x86_64_shld;
6708 :
6709 4219 : if (!rtx_equal_p (operands[0], operands[1]))
6710 0 : emit_move_insn (operands[0], operands[1]);
6711 :
6712 4219 : emit_insn (gen_shld (high[0], low[0], GEN_INT (count)));
6713 4219 : ix86_expand_ashl_const (low[0], count, mode);
6714 : }
6715 9082 : return;
6716 : }
6717 :
6718 1708 : split_double_mode (mode, operands, 1, low, high);
6719 1708 : half_mode = mode == DImode ? SImode : DImode;
6720 :
6721 1708 : gen_ashl3 = mode == DImode ? gen_ashlsi3 : gen_ashldi3;
6722 :
6723 1708 : if (operands[1] == const1_rtx)
6724 : {
6725 : /* Assuming we've chosen a QImode capable registers, then 1 << N
6726 : can be done with two 32/64-bit shifts, no branches, no cmoves. */
6727 270 : if (ANY_QI_REG_P (low[0]) && ANY_QI_REG_P (high[0]))
6728 : {
6729 163 : rtx s, d, flags = gen_rtx_REG (CCZmode, FLAGS_REG);
6730 :
6731 163 : ix86_expand_clear (low[0]);
6732 163 : ix86_expand_clear (high[0]);
6733 163 : emit_insn (gen_testqi_ccz_1 (operands[2], GEN_INT (half_width)));
6734 :
6735 163 : d = gen_lowpart (QImode, low[0]);
6736 163 : d = gen_rtx_STRICT_LOW_PART (VOIDmode, d);
6737 163 : s = gen_rtx_EQ (QImode, flags, const0_rtx);
6738 163 : emit_insn (gen_rtx_SET (d, s));
6739 :
6740 163 : d = gen_lowpart (QImode, high[0]);
6741 163 : d = gen_rtx_STRICT_LOW_PART (VOIDmode, d);
6742 163 : s = gen_rtx_NE (QImode, flags, const0_rtx);
6743 163 : emit_insn (gen_rtx_SET (d, s));
6744 : }
6745 :
6746 : /* Otherwise, we can get the same results by manually performing
6747 : a bit extract operation on bit 5/6, and then performing the two
6748 : shifts. The two methods of getting 0/1 into low/high are exactly
6749 : the same size. Avoiding the shift in the bit extract case helps
6750 : pentium4 a bit; no one else seems to care much either way. */
6751 : else
6752 : {
6753 107 : rtx (*gen_lshr3)(rtx, rtx, rtx);
6754 107 : rtx (*gen_and3)(rtx, rtx, rtx);
6755 107 : rtx (*gen_xor3)(rtx, rtx, rtx);
6756 107 : HOST_WIDE_INT bits;
6757 107 : rtx x;
6758 :
6759 107 : if (mode == DImode)
6760 : {
6761 : gen_lshr3 = gen_lshrsi3;
6762 : gen_and3 = gen_andsi3;
6763 : gen_xor3 = gen_xorsi3;
6764 : bits = 5;
6765 : }
6766 : else
6767 : {
6768 0 : gen_lshr3 = gen_lshrdi3;
6769 0 : gen_and3 = gen_anddi3;
6770 0 : gen_xor3 = gen_xordi3;
6771 0 : bits = 6;
6772 : }
6773 :
6774 107 : if (TARGET_PARTIAL_REG_STALL && !optimize_insn_for_size_p ())
6775 0 : x = gen_rtx_ZERO_EXTEND (half_mode, operands[2]);
6776 : else
6777 107 : x = gen_lowpart (half_mode, operands[2]);
6778 107 : emit_insn (gen_rtx_SET (high[0], x));
6779 :
6780 107 : emit_insn (gen_lshr3 (high[0], high[0], GEN_INT (bits)));
6781 107 : emit_insn (gen_and3 (high[0], high[0], const1_rtx));
6782 107 : emit_move_insn (low[0], high[0]);
6783 107 : emit_insn (gen_xor3 (low[0], low[0], const1_rtx));
6784 : }
6785 :
6786 270 : emit_insn (gen_ashl3 (low[0], low[0], operands[2]));
6787 270 : emit_insn (gen_ashl3 (high[0], high[0], operands[2]));
6788 270 : return;
6789 : }
6790 :
6791 1438 : if (operands[1] == constm1_rtx)
6792 : {
6793 : /* For -1 << N, we can avoid the shld instruction, because we
6794 : know that we're shifting 0...31/63 ones into a -1. */
6795 115 : emit_move_insn (low[0], constm1_rtx);
6796 115 : if (optimize_insn_for_size_p ())
6797 6 : emit_move_insn (high[0], low[0]);
6798 : else
6799 109 : emit_move_insn (high[0], constm1_rtx);
6800 : }
6801 : else
6802 : {
6803 1323 : gen_shld = mode == DImode ? gen_x86_shld : gen_x86_64_shld;
6804 :
6805 1323 : if (!rtx_equal_p (operands[0], operands[1]))
6806 0 : emit_move_insn (operands[0], operands[1]);
6807 :
6808 1323 : split_double_mode (mode, operands, 1, low, high);
6809 1323 : emit_insn (gen_shld (high[0], low[0], operands[2]));
6810 : }
6811 :
6812 1438 : emit_insn (gen_ashl3 (low[0], low[0], operands[2]));
6813 :
6814 1438 : if (TARGET_CMOVE && scratch)
6815 : {
6816 963 : ix86_expand_clear (scratch);
6817 963 : emit_insn (gen_x86_shift_adj_1
6818 : (half_mode, high[0], low[0], operands[2], scratch));
6819 : }
6820 : else
6821 475 : emit_insn (gen_x86_shift_adj_2 (half_mode, high[0], low[0], operands[2]));
6822 : }
6823 :
6824 : void
6825 6455 : ix86_split_ashr (rtx *operands, rtx scratch, machine_mode mode)
6826 : {
6827 5211 : rtx (*gen_ashr3)(rtx, rtx, rtx)
6828 6455 : = mode == DImode ? gen_ashrsi3 : gen_ashrdi3;
6829 6455 : rtx (*gen_shrd)(rtx, rtx, rtx);
6830 6455 : int half_width = GET_MODE_BITSIZE (mode) >> 1;
6831 :
6832 6455 : rtx low[2], high[2];
6833 6455 : int count;
6834 :
6835 6455 : if (CONST_INT_P (operands[2]))
6836 : {
6837 6282 : split_double_mode (mode, operands, 2, low, high);
6838 6282 : count = INTVAL (operands[2]) & (GET_MODE_BITSIZE (mode) - 1);
6839 :
6840 12564 : if (count == GET_MODE_BITSIZE (mode) - 1)
6841 : {
6842 89 : emit_move_insn (high[0], high[1]);
6843 89 : emit_insn (gen_ashr3 (high[0], high[0],
6844 89 : GEN_INT (half_width - 1)));
6845 89 : emit_move_insn (low[0], high[0]);
6846 :
6847 : }
6848 6193 : else if (count >= half_width)
6849 : {
6850 1995 : emit_move_insn (low[0], high[1]);
6851 1995 : emit_move_insn (high[0], low[0]);
6852 1995 : emit_insn (gen_ashr3 (high[0], high[0],
6853 1995 : GEN_INT (half_width - 1)));
6854 :
6855 1995 : if (count > half_width)
6856 38 : emit_insn (gen_ashr3 (low[0], low[0],
6857 38 : GEN_INT (count - half_width)));
6858 : }
6859 4198 : else if (count == 1
6860 766 : && (TARGET_USE_RCR || optimize_size > 1))
6861 : {
6862 1 : if (!rtx_equal_p (operands[0], operands[1]))
6863 0 : emit_move_insn (operands[0], operands[1]);
6864 1 : if (mode == DImode)
6865 : {
6866 0 : emit_insn (gen_ashrsi3_carry (high[0], high[0]));
6867 0 : emit_insn (gen_rcrsi2 (low[0], low[0]));
6868 : }
6869 : else
6870 : {
6871 1 : emit_insn (gen_ashrdi3_carry (high[0], high[0]));
6872 1 : emit_insn (gen_rcrdi2 (low[0], low[0]));
6873 : }
6874 : }
6875 : else
6876 : {
6877 4197 : gen_shrd = mode == DImode ? gen_x86_shrd : gen_x86_64_shrd;
6878 :
6879 4197 : if (!rtx_equal_p (operands[0], operands[1]))
6880 0 : emit_move_insn (operands[0], operands[1]);
6881 :
6882 4197 : emit_insn (gen_shrd (low[0], high[0], GEN_INT (count)));
6883 4197 : emit_insn (gen_ashr3 (high[0], high[0], GEN_INT (count)));
6884 : }
6885 : }
6886 : else
6887 : {
6888 173 : machine_mode half_mode;
6889 :
6890 173 : gen_shrd = mode == DImode ? gen_x86_shrd : gen_x86_64_shrd;
6891 :
6892 173 : if (!rtx_equal_p (operands[0], operands[1]))
6893 0 : emit_move_insn (operands[0], operands[1]);
6894 :
6895 173 : split_double_mode (mode, operands, 1, low, high);
6896 173 : half_mode = mode == DImode ? SImode : DImode;
6897 :
6898 173 : emit_insn (gen_shrd (low[0], high[0], operands[2]));
6899 173 : emit_insn (gen_ashr3 (high[0], high[0], operands[2]));
6900 :
6901 173 : if (TARGET_CMOVE && scratch)
6902 : {
6903 133 : emit_move_insn (scratch, high[0]);
6904 133 : emit_insn (gen_ashr3 (scratch, scratch,
6905 133 : GEN_INT (half_width - 1)));
6906 133 : emit_insn (gen_x86_shift_adj_1
6907 : (half_mode, low[0], high[0], operands[2], scratch));
6908 : }
6909 : else
6910 40 : emit_insn (gen_x86_shift_adj_3
6911 : (half_mode, low[0], high[0], operands[2]));
6912 : }
6913 6455 : }
6914 :
6915 : void
6916 13864 : ix86_split_lshr (rtx *operands, rtx scratch, machine_mode mode)
6917 : {
6918 6513 : rtx (*gen_lshr3)(rtx, rtx, rtx)
6919 13864 : = mode == DImode ? gen_lshrsi3 : gen_lshrdi3;
6920 13864 : rtx (*gen_shrd)(rtx, rtx, rtx);
6921 13864 : int half_width = GET_MODE_BITSIZE (mode) >> 1;
6922 :
6923 13864 : rtx low[2], high[2];
6924 13864 : int count;
6925 :
6926 13864 : if (CONST_INT_P (operands[2]))
6927 : {
6928 12444 : split_double_mode (mode, operands, 2, low, high);
6929 12444 : count = INTVAL (operands[2]) & (GET_MODE_BITSIZE (mode) - 1);
6930 :
6931 12444 : if (count >= half_width)
6932 : {
6933 9035 : emit_move_insn (low[0], high[1]);
6934 9035 : ix86_expand_clear (high[0]);
6935 :
6936 9035 : if (count > half_width)
6937 655 : emit_insn (gen_lshr3 (low[0], low[0],
6938 655 : GEN_INT (count - half_width)));
6939 : }
6940 3409 : else if (count == 1
6941 653 : && (TARGET_USE_RCR || optimize_size > 1))
6942 : {
6943 1 : if (!rtx_equal_p (operands[0], operands[1]))
6944 0 : emit_move_insn (operands[0], operands[1]);
6945 1 : if (mode == DImode)
6946 : {
6947 0 : emit_insn (gen_lshrsi3_carry (high[0], high[0]));
6948 0 : emit_insn (gen_rcrsi2 (low[0], low[0]));
6949 : }
6950 : else
6951 : {
6952 1 : emit_insn (gen_lshrdi3_carry (high[0], high[0]));
6953 1 : emit_insn (gen_rcrdi2 (low[0], low[0]));
6954 : }
6955 : }
6956 : else
6957 : {
6958 3408 : gen_shrd = mode == DImode ? gen_x86_shrd : gen_x86_64_shrd;
6959 :
6960 3408 : if (!rtx_equal_p (operands[0], operands[1]))
6961 0 : emit_move_insn (operands[0], operands[1]);
6962 :
6963 3408 : emit_insn (gen_shrd (low[0], high[0], GEN_INT (count)));
6964 3408 : emit_insn (gen_lshr3 (high[0], high[0], GEN_INT (count)));
6965 : }
6966 : }
6967 : else
6968 : {
6969 1420 : machine_mode half_mode;
6970 :
6971 1420 : gen_shrd = mode == DImode ? gen_x86_shrd : gen_x86_64_shrd;
6972 :
6973 1420 : if (!rtx_equal_p (operands[0], operands[1]))
6974 0 : emit_move_insn (operands[0], operands[1]);
6975 :
6976 1420 : split_double_mode (mode, operands, 1, low, high);
6977 1420 : half_mode = mode == DImode ? SImode : DImode;
6978 :
6979 1420 : emit_insn (gen_shrd (low[0], high[0], operands[2]));
6980 1420 : emit_insn (gen_lshr3 (high[0], high[0], operands[2]));
6981 :
6982 1420 : if (TARGET_CMOVE && scratch)
6983 : {
6984 1122 : ix86_expand_clear (scratch);
6985 1122 : emit_insn (gen_x86_shift_adj_1
6986 : (half_mode, low[0], high[0], operands[2], scratch));
6987 : }
6988 : else
6989 298 : emit_insn (gen_x86_shift_adj_2
6990 : (half_mode, low[0], high[0], operands[2]));
6991 : }
6992 13864 : }
6993 :
6994 : /* Helper function to split TImode ashl under NDD. */
6995 : void
6996 1 : ix86_split_ashl_ndd (rtx *operands, rtx scratch)
6997 : {
6998 1 : gcc_assert (TARGET_APX_NDD);
6999 1 : int half_width = GET_MODE_BITSIZE (TImode) >> 1;
7000 :
7001 1 : rtx low[2], high[2];
7002 1 : int count;
7003 :
7004 1 : split_double_mode (TImode, operands, 2, low, high);
7005 1 : if (CONST_INT_P (operands[2]))
7006 : {
7007 0 : count = INTVAL (operands[2]) & (GET_MODE_BITSIZE (TImode) - 1);
7008 :
7009 0 : if (count >= half_width)
7010 : {
7011 0 : count = count - half_width;
7012 0 : if (count == 0)
7013 : {
7014 0 : if (!rtx_equal_p (high[0], low[1]))
7015 0 : emit_move_insn (high[0], low[1]);
7016 : }
7017 0 : else if (count == 1)
7018 0 : emit_insn (gen_adddi3 (high[0], low[1], low[1]));
7019 : else
7020 0 : emit_insn (gen_ashldi3 (high[0], low[1], GEN_INT (count)));
7021 :
7022 0 : ix86_expand_clear (low[0]);
7023 : }
7024 0 : else if (count == 1)
7025 : {
7026 0 : rtx x3 = gen_rtx_REG (CCCmode, FLAGS_REG);
7027 0 : rtx x4 = gen_rtx_LTU (TImode, x3, const0_rtx);
7028 0 : emit_insn (gen_add3_cc_overflow_1 (DImode, low[0],
7029 : low[1], low[1]));
7030 0 : emit_insn (gen_add3_carry (DImode, high[0], high[1], high[1],
7031 : x3, x4));
7032 : }
7033 : else
7034 : {
7035 0 : emit_insn (gen_x86_64_shld_ndd (high[0], high[1], low[1],
7036 : GEN_INT (count)));
7037 0 : emit_insn (gen_ashldi3 (low[0], low[1], GEN_INT (count)));
7038 : }
7039 : }
7040 : else
7041 : {
7042 1 : emit_insn (gen_x86_64_shld_ndd (high[0], high[1], low[1],
7043 : operands[2]));
7044 1 : emit_insn (gen_ashldi3 (low[0], low[1], operands[2]));
7045 1 : if (TARGET_CMOVE && scratch)
7046 : {
7047 1 : ix86_expand_clear (scratch);
7048 1 : emit_insn (gen_x86_shift_adj_1
7049 : (DImode, high[0], low[0], operands[2], scratch));
7050 : }
7051 : else
7052 0 : emit_insn (gen_x86_shift_adj_2 (DImode, high[0], low[0], operands[2]));
7053 : }
7054 1 : }
7055 :
7056 : /* Helper function to split TImode l/ashr under NDD. */
7057 : void
7058 2 : ix86_split_rshift_ndd (enum rtx_code code, rtx *operands, rtx scratch)
7059 : {
7060 2 : gcc_assert (TARGET_APX_NDD);
7061 2 : int half_width = GET_MODE_BITSIZE (TImode) >> 1;
7062 2 : bool ashr_p = code == ASHIFTRT;
7063 2 : rtx (*gen_shr)(rtx, rtx, rtx) = ashr_p ? gen_ashrdi3
7064 : : gen_lshrdi3;
7065 :
7066 2 : rtx low[2], high[2];
7067 2 : int count;
7068 :
7069 2 : split_double_mode (TImode, operands, 2, low, high);
7070 2 : if (CONST_INT_P (operands[2]))
7071 : {
7072 0 : count = INTVAL (operands[2]) & (GET_MODE_BITSIZE (TImode) - 1);
7073 :
7074 0 : if (ashr_p && (count == GET_MODE_BITSIZE (TImode) - 1))
7075 : {
7076 0 : emit_insn (gen_shr (high[0], high[1],
7077 : GEN_INT (half_width - 1)));
7078 0 : emit_move_insn (low[0], high[0]);
7079 : }
7080 0 : else if (count >= half_width)
7081 : {
7082 0 : if (ashr_p)
7083 0 : emit_insn (gen_shr (high[0], high[1],
7084 : GEN_INT (half_width - 1)));
7085 : else
7086 0 : ix86_expand_clear (high[0]);
7087 :
7088 0 : if (count > half_width)
7089 0 : emit_insn (gen_shr (low[0], high[1],
7090 0 : GEN_INT (count - half_width)));
7091 : else
7092 0 : emit_move_insn (low[0], high[1]);
7093 : }
7094 : else
7095 : {
7096 0 : emit_insn (gen_x86_64_shrd_ndd (low[0], low[1], high[1],
7097 : GEN_INT (count)));
7098 0 : emit_insn (gen_shr (high[0], high[1], GEN_INT (count)));
7099 : }
7100 : }
7101 : else
7102 : {
7103 2 : emit_insn (gen_x86_64_shrd_ndd (low[0], low[1], high[1],
7104 : operands[2]));
7105 2 : emit_insn (gen_shr (high[0], high[1], operands[2]));
7106 :
7107 2 : if (TARGET_CMOVE && scratch)
7108 : {
7109 2 : if (ashr_p)
7110 : {
7111 1 : emit_move_insn (scratch, high[0]);
7112 1 : emit_insn (gen_shr (scratch, scratch,
7113 : GEN_INT (half_width - 1)));
7114 : }
7115 : else
7116 1 : ix86_expand_clear (scratch);
7117 :
7118 2 : emit_insn (gen_x86_shift_adj_1
7119 : (DImode, low[0], high[0], operands[2], scratch));
7120 : }
7121 0 : else if (ashr_p)
7122 0 : emit_insn (gen_x86_shift_adj_3
7123 : (DImode, low[0], high[0], operands[2]));
7124 : else
7125 0 : emit_insn (gen_x86_shift_adj_2
7126 : (DImode, low[0], high[0], operands[2]));
7127 : }
7128 2 : }
7129 :
7130 : /* Expand move of V1TI mode register X to a new TI mode register. */
7131 : static rtx
7132 17 : ix86_expand_v1ti_to_ti (rtx x)
7133 : {
7134 17 : rtx result = gen_reg_rtx (TImode);
7135 17 : if (TARGET_SSE2)
7136 : {
7137 17 : rtx temp = force_reg (V2DImode, gen_lowpart (V2DImode, x));
7138 17 : rtx lo = gen_lowpart (DImode, result);
7139 17 : emit_insn (gen_vec_extractv2didi (lo, temp, const0_rtx));
7140 17 : rtx hi = gen_highpart (DImode, result);
7141 17 : emit_insn (gen_vec_extractv2didi (hi, temp, const1_rtx));
7142 : }
7143 : else
7144 0 : emit_move_insn (result, gen_lowpart (TImode, x));
7145 17 : return result;
7146 : }
7147 :
7148 : /* Expand move of TI mode register X to a new V1TI mode register. */
7149 : static rtx
7150 17 : ix86_expand_ti_to_v1ti (rtx x)
7151 : {
7152 17 : if (TARGET_SSE2)
7153 : {
7154 17 : rtx lo = gen_lowpart (DImode, x);
7155 17 : rtx hi = gen_highpart (DImode, x);
7156 17 : rtx tmp = gen_reg_rtx (V2DImode);
7157 17 : emit_insn (gen_vec_concatv2di (tmp, lo, hi));
7158 17 : return force_reg (V1TImode, gen_lowpart (V1TImode, tmp));
7159 : }
7160 :
7161 0 : return force_reg (V1TImode, gen_lowpart (V1TImode, x));
7162 : }
7163 :
7164 : /* Expand V1TI mode shift (of rtx_code CODE) by constant. */
7165 : void
7166 42 : ix86_expand_v1ti_shift (enum rtx_code code, rtx operands[])
7167 : {
7168 42 : rtx op1 = force_reg (V1TImode, operands[1]);
7169 :
7170 42 : if (!CONST_INT_P (operands[2]))
7171 : {
7172 6 : rtx tmp1 = ix86_expand_v1ti_to_ti (op1);
7173 6 : rtx tmp2 = gen_reg_rtx (TImode);
7174 3 : rtx (*shift) (rtx, rtx, rtx)
7175 6 : = (code == ASHIFT) ? gen_ashlti3 : gen_lshrti3;
7176 6 : emit_insn (shift (tmp2, tmp1, operands[2]));
7177 6 : rtx tmp3 = ix86_expand_ti_to_v1ti (tmp2);
7178 6 : emit_move_insn (operands[0], tmp3);
7179 6 : return;
7180 : }
7181 :
7182 36 : HOST_WIDE_INT bits = INTVAL (operands[2]) & 127;
7183 :
7184 36 : if (bits == 0)
7185 : {
7186 0 : emit_move_insn (operands[0], op1);
7187 0 : return;
7188 : }
7189 :
7190 36 : if ((bits & 7) == 0)
7191 : {
7192 0 : rtx tmp = gen_reg_rtx (V1TImode);
7193 0 : if (code == ASHIFT)
7194 0 : emit_insn (gen_sse2_ashlv1ti3 (tmp, op1, GEN_INT (bits)));
7195 : else
7196 0 : emit_insn (gen_sse2_lshrv1ti3 (tmp, op1, GEN_INT (bits)));
7197 0 : emit_move_insn (operands[0], tmp);
7198 0 : return;
7199 : }
7200 :
7201 36 : rtx tmp1 = gen_reg_rtx (V1TImode);
7202 36 : if (code == ASHIFT)
7203 18 : emit_insn (gen_sse2_ashlv1ti3 (tmp1, op1, GEN_INT (64)));
7204 : else
7205 18 : emit_insn (gen_sse2_lshrv1ti3 (tmp1, op1, GEN_INT (64)));
7206 :
7207 : /* tmp2 is operands[1] shifted by 64, in V2DImode. */
7208 36 : rtx tmp2 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp1));
7209 :
7210 : /* tmp3 will be the V2DImode result. */
7211 36 : rtx tmp3 = gen_reg_rtx (V2DImode);
7212 :
7213 36 : if (bits > 64)
7214 : {
7215 18 : if (code == ASHIFT)
7216 9 : emit_insn (gen_ashlv2di3 (tmp3, tmp2, GEN_INT (bits - 64)));
7217 : else
7218 9 : emit_insn (gen_lshrv2di3 (tmp3, tmp2, GEN_INT (bits - 64)));
7219 : }
7220 : else
7221 : {
7222 : /* tmp4 is operands[1], in V2DImode. */
7223 18 : rtx tmp4 = force_reg (V2DImode, gen_lowpart (V2DImode, op1));
7224 :
7225 18 : rtx tmp5 = gen_reg_rtx (V2DImode);
7226 18 : if (code == ASHIFT)
7227 9 : emit_insn (gen_ashlv2di3 (tmp5, tmp4, GEN_INT (bits)));
7228 : else
7229 9 : emit_insn (gen_lshrv2di3 (tmp5, tmp4, GEN_INT (bits)));
7230 :
7231 18 : rtx tmp6 = gen_reg_rtx (V2DImode);
7232 18 : if (code == ASHIFT)
7233 9 : emit_insn (gen_lshrv2di3 (tmp6, tmp2, GEN_INT (64 - bits)));
7234 : else
7235 9 : emit_insn (gen_ashlv2di3 (tmp6, tmp2, GEN_INT (64 - bits)));
7236 :
7237 18 : emit_insn (gen_iorv2di3 (tmp3, tmp5, tmp6));
7238 : }
7239 :
7240 : /* Convert the result back to V1TImode and store in operands[0]. */
7241 36 : rtx tmp7 = force_reg (V1TImode, gen_lowpart (V1TImode, tmp3));
7242 36 : emit_move_insn (operands[0], tmp7);
7243 : }
7244 :
7245 : /* Expand V1TI mode rotate (of rtx_code CODE) by constant. */
7246 : void
7247 39 : ix86_expand_v1ti_rotate (enum rtx_code code, rtx operands[])
7248 : {
7249 39 : rtx op1 = force_reg (V1TImode, operands[1]);
7250 :
7251 39 : if (!CONST_INT_P (operands[2]))
7252 : {
7253 8 : rtx tmp1 = ix86_expand_v1ti_to_ti (op1);
7254 8 : rtx tmp2 = gen_reg_rtx (TImode);
7255 4 : rtx (*rotate) (rtx, rtx, rtx)
7256 8 : = (code == ROTATE) ? gen_rotlti3 : gen_rotrti3;
7257 8 : emit_insn (rotate (tmp2, tmp1, operands[2]));
7258 8 : rtx tmp3 = ix86_expand_ti_to_v1ti (tmp2);
7259 8 : emit_move_insn (operands[0], tmp3);
7260 8 : return;
7261 : }
7262 :
7263 31 : HOST_WIDE_INT bits = INTVAL (operands[2]) & 127;
7264 :
7265 31 : if (bits == 0)
7266 : {
7267 0 : emit_move_insn (operands[0], op1);
7268 0 : return;
7269 : }
7270 :
7271 31 : if (code == ROTATERT)
7272 16 : bits = 128 - bits;
7273 :
7274 31 : if ((bits & 31) == 0)
7275 : {
7276 5 : rtx tmp2 = gen_reg_rtx (V4SImode);
7277 5 : rtx tmp1 = force_reg (V4SImode, gen_lowpart (V4SImode, op1));
7278 5 : if (bits == 32)
7279 1 : emit_insn (gen_sse2_pshufd (tmp2, tmp1, GEN_INT (0x93)));
7280 4 : else if (bits == 64)
7281 2 : emit_insn (gen_sse2_pshufd (tmp2, tmp1, GEN_INT (0x4e)));
7282 : else
7283 2 : emit_insn (gen_sse2_pshufd (tmp2, tmp1, GEN_INT (0x39)));
7284 5 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp2));
7285 5 : return;
7286 : }
7287 :
7288 26 : if ((bits & 7) == 0)
7289 : {
7290 6 : rtx tmp1 = gen_reg_rtx (V1TImode);
7291 6 : rtx tmp2 = gen_reg_rtx (V1TImode);
7292 6 : rtx tmp3 = gen_reg_rtx (V1TImode);
7293 :
7294 6 : emit_insn (gen_sse2_ashlv1ti3 (tmp1, op1, GEN_INT (bits)));
7295 6 : emit_insn (gen_sse2_lshrv1ti3 (tmp2, op1, GEN_INT (128 - bits)));
7296 6 : emit_insn (gen_iorv1ti3 (tmp3, tmp1, tmp2));
7297 6 : emit_move_insn (operands[0], tmp3);
7298 6 : return;
7299 : }
7300 :
7301 20 : rtx op1_v4si = force_reg (V4SImode, gen_lowpart (V4SImode, op1));
7302 :
7303 20 : rtx lobits;
7304 20 : rtx hibits;
7305 :
7306 20 : switch (bits >> 5)
7307 : {
7308 7 : case 0:
7309 7 : lobits = op1_v4si;
7310 7 : hibits = gen_reg_rtx (V4SImode);
7311 7 : emit_insn (gen_sse2_pshufd (hibits, op1_v4si, GEN_INT (0x93)));
7312 7 : break;
7313 :
7314 2 : case 1:
7315 2 : lobits = gen_reg_rtx (V4SImode);
7316 2 : hibits = gen_reg_rtx (V4SImode);
7317 2 : emit_insn (gen_sse2_pshufd (lobits, op1_v4si, GEN_INT (0x93)));
7318 2 : emit_insn (gen_sse2_pshufd (hibits, op1_v4si, GEN_INT (0x4e)));
7319 2 : break;
7320 :
7321 2 : case 2:
7322 2 : lobits = gen_reg_rtx (V4SImode);
7323 2 : hibits = gen_reg_rtx (V4SImode);
7324 2 : emit_insn (gen_sse2_pshufd (lobits, op1_v4si, GEN_INT (0x4e)));
7325 2 : emit_insn (gen_sse2_pshufd (hibits, op1_v4si, GEN_INT (0x39)));
7326 2 : break;
7327 :
7328 9 : default:
7329 9 : lobits = gen_reg_rtx (V4SImode);
7330 9 : emit_insn (gen_sse2_pshufd (lobits, op1_v4si, GEN_INT (0x39)));
7331 9 : hibits = op1_v4si;
7332 9 : break;
7333 : }
7334 :
7335 20 : rtx tmp1 = gen_reg_rtx (V4SImode);
7336 20 : rtx tmp2 = gen_reg_rtx (V4SImode);
7337 20 : rtx tmp3 = gen_reg_rtx (V4SImode);
7338 :
7339 20 : emit_insn (gen_ashlv4si3 (tmp1, lobits, GEN_INT (bits & 31)));
7340 20 : emit_insn (gen_lshrv4si3 (tmp2, hibits, GEN_INT (32 - (bits & 31))));
7341 20 : emit_insn (gen_iorv4si3 (tmp3, tmp1, tmp2));
7342 :
7343 20 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp3));
7344 : }
7345 :
7346 : /* Expand V1TI mode ashiftrt by constant. */
7347 : void
7348 109 : ix86_expand_v1ti_ashiftrt (rtx operands[])
7349 : {
7350 109 : rtx op1 = force_reg (V1TImode, operands[1]);
7351 :
7352 109 : if (!CONST_INT_P (operands[2]))
7353 : {
7354 3 : rtx tmp1 = ix86_expand_v1ti_to_ti (op1);
7355 3 : rtx tmp2 = gen_reg_rtx (TImode);
7356 3 : emit_insn (gen_ashrti3 (tmp2, tmp1, operands[2]));
7357 3 : rtx tmp3 = ix86_expand_ti_to_v1ti (tmp2);
7358 3 : emit_move_insn (operands[0], tmp3);
7359 3 : return;
7360 : }
7361 :
7362 106 : HOST_WIDE_INT bits = INTVAL (operands[2]) & 127;
7363 :
7364 106 : if (bits == 0)
7365 : {
7366 0 : emit_move_insn (operands[0], op1);
7367 0 : return;
7368 : }
7369 :
7370 106 : if (bits == 127)
7371 : {
7372 : /* Two operations. */
7373 3 : rtx tmp1 = force_reg(V4SImode, gen_lowpart (V4SImode, op1));
7374 3 : rtx tmp2 = gen_reg_rtx (V4SImode);
7375 3 : emit_insn (gen_sse2_pshufd (tmp2, tmp1, GEN_INT (0xff)));
7376 :
7377 3 : rtx tmp3 = gen_reg_rtx (V4SImode);
7378 3 : emit_insn (gen_ashrv4si3 (tmp3, tmp2, GEN_INT (31)));
7379 :
7380 3 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp3));
7381 3 : return;
7382 : }
7383 :
7384 103 : if (bits == 64)
7385 : {
7386 : /* Three operations. */
7387 3 : rtx tmp1 = force_reg(V4SImode, gen_lowpart (V4SImode, op1));
7388 3 : rtx tmp2 = gen_reg_rtx (V4SImode);
7389 3 : emit_insn (gen_sse2_pshufd (tmp2, tmp1, GEN_INT (0xff)));
7390 :
7391 3 : rtx tmp3 = gen_reg_rtx (V4SImode);
7392 3 : emit_insn (gen_ashrv4si3 (tmp3, tmp2, GEN_INT (31)));
7393 :
7394 3 : rtx tmp4 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp1));
7395 3 : rtx tmp5 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp3));
7396 3 : rtx tmp6 = gen_reg_rtx (V2DImode);
7397 3 : emit_insn (gen_vec_interleave_highv2di (tmp6, tmp4, tmp5));
7398 :
7399 3 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp6));
7400 3 : return;
7401 : }
7402 :
7403 100 : if (bits == 96)
7404 : {
7405 : /* Three operations. */
7406 3 : rtx tmp1 = force_reg(V4SImode, gen_lowpart (V4SImode, op1));
7407 3 : rtx tmp2 = gen_reg_rtx (V4SImode);
7408 3 : emit_insn (gen_ashrv4si3 (tmp2, tmp1, GEN_INT (31)));
7409 :
7410 3 : rtx tmp3 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp1));
7411 3 : rtx tmp4 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp2));
7412 3 : rtx tmp5 = gen_reg_rtx (V2DImode);
7413 3 : emit_insn (gen_vec_interleave_highv2di (tmp5, tmp3, tmp4));
7414 :
7415 3 : rtx tmp6 = force_reg(V4SImode, gen_lowpart (V4SImode, tmp5));
7416 3 : rtx tmp7 = gen_reg_rtx (V4SImode);
7417 3 : emit_insn (gen_sse2_pshufd (tmp7, tmp6, GEN_INT (0xfd)));
7418 :
7419 3 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp7));
7420 3 : return;
7421 : }
7422 :
7423 97 : if (bits >= 111)
7424 : {
7425 : /* Three operations. */
7426 21 : rtx tmp1 = force_reg (V4SImode, gen_lowpart (V4SImode, op1));
7427 21 : rtx tmp2 = gen_reg_rtx (V4SImode);
7428 21 : emit_insn (gen_ashrv4si3 (tmp2, tmp1, GEN_INT (bits - 96)));
7429 :
7430 21 : rtx tmp3 = force_reg (V8HImode, gen_lowpart (V8HImode, tmp2));
7431 21 : rtx tmp4 = gen_reg_rtx (V8HImode);
7432 21 : emit_insn (gen_sse2_pshufhw (tmp4, tmp3, GEN_INT (0xfe)));
7433 :
7434 21 : rtx tmp5 = force_reg (V4SImode, gen_lowpart (V4SImode, tmp4));
7435 21 : rtx tmp6 = gen_reg_rtx (V4SImode);
7436 21 : emit_insn (gen_sse2_pshufd (tmp6, tmp5, GEN_INT (0xfe)));
7437 :
7438 21 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp6));
7439 21 : return;
7440 : }
7441 :
7442 76 : if (TARGET_AVX2 || TARGET_SSE4_1)
7443 : {
7444 : /* Three operations. */
7445 50 : if (bits == 32)
7446 : {
7447 2 : rtx tmp1 = force_reg (V4SImode, gen_lowpart (V4SImode, op1));
7448 2 : rtx tmp2 = gen_reg_rtx (V4SImode);
7449 2 : emit_insn (gen_ashrv4si3 (tmp2, tmp1, GEN_INT (31)));
7450 :
7451 2 : rtx tmp3 = gen_reg_rtx (V1TImode);
7452 2 : emit_insn (gen_sse2_lshrv1ti3 (tmp3, op1, GEN_INT (32)));
7453 :
7454 2 : if (TARGET_AVX2)
7455 : {
7456 1 : rtx tmp4 = force_reg (V4SImode, gen_lowpart (V4SImode, tmp3));
7457 1 : rtx tmp5 = gen_reg_rtx (V4SImode);
7458 1 : emit_insn (gen_avx2_pblenddv4si (tmp5, tmp2, tmp4,
7459 : GEN_INT (7)));
7460 :
7461 1 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp5));
7462 : }
7463 : else
7464 : {
7465 1 : rtx tmp4 = force_reg (V8HImode, gen_lowpart (V8HImode, tmp2));
7466 1 : rtx tmp5 = force_reg (V8HImode, gen_lowpart (V8HImode, tmp3));
7467 1 : rtx tmp6 = gen_reg_rtx (V8HImode);
7468 1 : emit_insn (gen_sse4_1_pblendw (tmp6, tmp4, tmp5,
7469 : GEN_INT (0x3f)));
7470 :
7471 1 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp6));
7472 : }
7473 2 : return;
7474 : }
7475 :
7476 : /* Three operations. */
7477 48 : if (bits == 8 || bits == 16 || bits == 24)
7478 : {
7479 6 : rtx tmp1 = force_reg (V4SImode, gen_lowpart (V4SImode, op1));
7480 6 : rtx tmp2 = gen_reg_rtx (V4SImode);
7481 6 : emit_insn (gen_ashrv4si3 (tmp2, tmp1, GEN_INT (bits)));
7482 :
7483 6 : rtx tmp3 = gen_reg_rtx (V1TImode);
7484 6 : emit_insn (gen_sse2_lshrv1ti3 (tmp3, op1, GEN_INT (bits)));
7485 :
7486 6 : if (TARGET_AVX2)
7487 : {
7488 3 : rtx tmp4 = force_reg (V4SImode, gen_lowpart (V4SImode, tmp3));
7489 3 : rtx tmp5 = gen_reg_rtx (V4SImode);
7490 3 : emit_insn (gen_avx2_pblenddv4si (tmp5, tmp2, tmp4,
7491 : GEN_INT (7)));
7492 :
7493 3 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp5));
7494 : }
7495 : else
7496 : {
7497 3 : rtx tmp4 = force_reg (V8HImode, gen_lowpart (V8HImode, tmp2));
7498 3 : rtx tmp5 = force_reg (V8HImode, gen_lowpart (V8HImode, tmp3));
7499 3 : rtx tmp6 = gen_reg_rtx (V8HImode);
7500 3 : emit_insn (gen_sse4_1_pblendw (tmp6, tmp4, tmp5,
7501 : GEN_INT (0x3f)));
7502 :
7503 3 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp6));
7504 : }
7505 6 : return;
7506 : }
7507 : }
7508 :
7509 68 : if (bits > 96)
7510 : {
7511 : /* Four operations. */
7512 3 : rtx tmp1 = force_reg (V4SImode, gen_lowpart (V4SImode, op1));
7513 3 : rtx tmp2 = gen_reg_rtx (V4SImode);
7514 3 : emit_insn (gen_ashrv4si3 (tmp2, tmp1, GEN_INT (bits - 96)));
7515 :
7516 3 : rtx tmp3 = gen_reg_rtx (V4SImode);
7517 3 : emit_insn (gen_ashrv4si3 (tmp3, tmp1, GEN_INT (31)));
7518 :
7519 3 : rtx tmp4 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp2));
7520 3 : rtx tmp5 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp3));
7521 3 : rtx tmp6 = gen_reg_rtx (V2DImode);
7522 3 : emit_insn (gen_vec_interleave_highv2di (tmp6, tmp4, tmp5));
7523 :
7524 3 : rtx tmp7 = force_reg (V4SImode, gen_lowpart (V4SImode, tmp6));
7525 3 : rtx tmp8 = gen_reg_rtx (V4SImode);
7526 3 : emit_insn (gen_sse2_pshufd (tmp8, tmp7, GEN_INT (0xfd)));
7527 :
7528 3 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp8));
7529 3 : return;
7530 : }
7531 :
7532 65 : if (TARGET_SSE4_1 && (bits == 48 || bits == 80))
7533 : {
7534 : /* Four operations. */
7535 4 : rtx tmp1 = force_reg (V4SImode, gen_lowpart (V4SImode, op1));
7536 4 : rtx tmp2 = gen_reg_rtx (V4SImode);
7537 4 : emit_insn (gen_sse2_pshufd (tmp2, tmp1, GEN_INT (0xff)));
7538 :
7539 4 : rtx tmp3 = gen_reg_rtx (V4SImode);
7540 4 : emit_insn (gen_ashrv4si3 (tmp3, tmp2, GEN_INT (31)));
7541 :
7542 4 : rtx tmp4 = gen_reg_rtx (V1TImode);
7543 4 : emit_insn (gen_sse2_lshrv1ti3 (tmp4, op1, GEN_INT (bits)));
7544 :
7545 4 : rtx tmp5 = force_reg (V8HImode, gen_lowpart (V8HImode, tmp3));
7546 4 : rtx tmp6 = force_reg (V8HImode, gen_lowpart (V8HImode, tmp4));
7547 4 : rtx tmp7 = gen_reg_rtx (V8HImode);
7548 6 : emit_insn (gen_sse4_1_pblendw (tmp7, tmp5, tmp6,
7549 : GEN_INT (bits == 48 ? 0x1f : 0x07)));
7550 :
7551 4 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp7));
7552 4 : return;
7553 : }
7554 :
7555 61 : if ((bits & 7) == 0)
7556 : {
7557 : /* Five operations. */
7558 9 : rtx tmp1 = force_reg (V4SImode, gen_lowpart (V4SImode, op1));
7559 9 : rtx tmp2 = gen_reg_rtx (V4SImode);
7560 9 : emit_insn (gen_sse2_pshufd (tmp2, tmp1, GEN_INT (0xff)));
7561 :
7562 9 : rtx tmp3 = gen_reg_rtx (V4SImode);
7563 9 : emit_insn (gen_ashrv4si3 (tmp3, tmp2, GEN_INT (31)));
7564 :
7565 9 : rtx tmp4 = gen_reg_rtx (V1TImode);
7566 9 : emit_insn (gen_sse2_lshrv1ti3 (tmp4, op1, GEN_INT (bits)));
7567 :
7568 9 : rtx tmp5 = force_reg (V1TImode, gen_lowpart (V1TImode, tmp3));
7569 9 : rtx tmp6 = gen_reg_rtx (V1TImode);
7570 9 : emit_insn (gen_sse2_ashlv1ti3 (tmp6, tmp5, GEN_INT (128 - bits)));
7571 :
7572 9 : rtx tmp7 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp4));
7573 9 : rtx tmp8 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp6));
7574 9 : rtx tmp9 = gen_reg_rtx (V2DImode);
7575 9 : emit_insn (gen_iorv2di3 (tmp9, tmp7, tmp8));
7576 :
7577 9 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp9));
7578 9 : return;
7579 : }
7580 :
7581 52 : if (TARGET_AVX2 && bits < 32)
7582 : {
7583 : /* Six operations. */
7584 9 : rtx tmp1 = force_reg (V4SImode, gen_lowpart (V4SImode, op1));
7585 9 : rtx tmp2 = gen_reg_rtx (V4SImode);
7586 9 : emit_insn (gen_ashrv4si3 (tmp2, tmp1, GEN_INT (bits)));
7587 :
7588 9 : rtx tmp3 = gen_reg_rtx (V1TImode);
7589 9 : emit_insn (gen_sse2_lshrv1ti3 (tmp3, op1, GEN_INT (64)));
7590 :
7591 9 : rtx tmp4 = force_reg (V2DImode, gen_lowpart (V2DImode, op1));
7592 9 : rtx tmp5 = gen_reg_rtx (V2DImode);
7593 9 : emit_insn (gen_lshrv2di3 (tmp5, tmp4, GEN_INT (bits)));
7594 :
7595 9 : rtx tmp6 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp3));
7596 9 : rtx tmp7 = gen_reg_rtx (V2DImode);
7597 9 : emit_insn (gen_ashlv2di3 (tmp7, tmp6, GEN_INT (64 - bits)));
7598 :
7599 9 : rtx tmp8 = gen_reg_rtx (V2DImode);
7600 9 : emit_insn (gen_iorv2di3 (tmp8, tmp5, tmp7));
7601 :
7602 9 : rtx tmp9 = force_reg (V4SImode, gen_lowpart (V4SImode, tmp8));
7603 9 : rtx tmp10 = gen_reg_rtx (V4SImode);
7604 9 : emit_insn (gen_avx2_pblenddv4si (tmp10, tmp2, tmp9, GEN_INT (7)));
7605 :
7606 9 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp10));
7607 9 : return;
7608 : }
7609 :
7610 43 : if (TARGET_SSE4_1 && bits < 15)
7611 : {
7612 : /* Six operations. */
7613 4 : rtx tmp1 = force_reg (V4SImode, gen_lowpart (V4SImode, op1));
7614 4 : rtx tmp2 = gen_reg_rtx (V4SImode);
7615 4 : emit_insn (gen_ashrv4si3 (tmp2, tmp1, GEN_INT (bits)));
7616 :
7617 4 : rtx tmp3 = gen_reg_rtx (V1TImode);
7618 4 : emit_insn (gen_sse2_lshrv1ti3 (tmp3, op1, GEN_INT (64)));
7619 :
7620 4 : rtx tmp4 = force_reg (V2DImode, gen_lowpart (V2DImode, op1));
7621 4 : rtx tmp5 = gen_reg_rtx (V2DImode);
7622 4 : emit_insn (gen_lshrv2di3 (tmp5, tmp4, GEN_INT (bits)));
7623 :
7624 4 : rtx tmp6 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp3));
7625 4 : rtx tmp7 = gen_reg_rtx (V2DImode);
7626 4 : emit_insn (gen_ashlv2di3 (tmp7, tmp6, GEN_INT (64 - bits)));
7627 :
7628 4 : rtx tmp8 = gen_reg_rtx (V2DImode);
7629 4 : emit_insn (gen_iorv2di3 (tmp8, tmp5, tmp7));
7630 :
7631 4 : rtx tmp9 = force_reg (V8HImode, gen_lowpart (V8HImode, tmp2));
7632 4 : rtx tmp10 = force_reg (V8HImode, gen_lowpart (V8HImode, tmp8));
7633 4 : rtx tmp11 = gen_reg_rtx (V8HImode);
7634 4 : emit_insn (gen_sse4_1_pblendw (tmp11, tmp9, tmp10, GEN_INT (0x3f)));
7635 :
7636 4 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp11));
7637 4 : return;
7638 : }
7639 :
7640 18 : if (bits == 1)
7641 : {
7642 : /* Eight operations. */
7643 1 : rtx tmp1 = gen_reg_rtx (V1TImode);
7644 1 : emit_insn (gen_sse2_lshrv1ti3 (tmp1, op1, GEN_INT (64)));
7645 :
7646 1 : rtx tmp2 = force_reg (V2DImode, gen_lowpart (V2DImode, op1));
7647 1 : rtx tmp3 = gen_reg_rtx (V2DImode);
7648 1 : emit_insn (gen_lshrv2di3 (tmp3, tmp2, GEN_INT (1)));
7649 :
7650 1 : rtx tmp4 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp1));
7651 1 : rtx tmp5 = gen_reg_rtx (V2DImode);
7652 1 : emit_insn (gen_ashlv2di3 (tmp5, tmp4, GEN_INT (63)));
7653 :
7654 1 : rtx tmp6 = gen_reg_rtx (V2DImode);
7655 1 : emit_insn (gen_iorv2di3 (tmp6, tmp3, tmp5));
7656 :
7657 1 : rtx tmp7 = gen_reg_rtx (V2DImode);
7658 1 : emit_insn (gen_lshrv2di3 (tmp7, tmp2, GEN_INT (63)));
7659 :
7660 1 : rtx tmp8 = force_reg (V4SImode, gen_lowpart (V4SImode, tmp7));
7661 1 : rtx tmp9 = gen_reg_rtx (V4SImode);
7662 1 : emit_insn (gen_sse2_pshufd (tmp9, tmp8, GEN_INT (0xbf)));
7663 :
7664 1 : rtx tmp10 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp9));
7665 1 : rtx tmp11 = gen_reg_rtx (V2DImode);
7666 1 : emit_insn (gen_ashlv2di3 (tmp11, tmp10, GEN_INT (31)));
7667 :
7668 1 : rtx tmp12 = gen_reg_rtx (V2DImode);
7669 1 : emit_insn (gen_iorv2di3 (tmp12, tmp6, tmp11));
7670 :
7671 1 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp12));
7672 1 : return;
7673 : }
7674 :
7675 38 : if (bits > 64)
7676 : {
7677 : /* Eight operations. */
7678 12 : rtx tmp1 = force_reg (V4SImode, gen_lowpart (V4SImode, op1));
7679 12 : rtx tmp2 = gen_reg_rtx (V4SImode);
7680 12 : emit_insn (gen_sse2_pshufd (tmp2, tmp1, GEN_INT (0xff)));
7681 :
7682 12 : rtx tmp3 = gen_reg_rtx (V4SImode);
7683 12 : emit_insn (gen_ashrv4si3 (tmp3, tmp2, GEN_INT (31)));
7684 :
7685 12 : rtx tmp4 = gen_reg_rtx (V1TImode);
7686 12 : emit_insn (gen_sse2_lshrv1ti3 (tmp4, op1, GEN_INT (64)));
7687 :
7688 12 : rtx tmp5 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp4));
7689 12 : rtx tmp6 = gen_reg_rtx (V2DImode);
7690 12 : emit_insn (gen_lshrv2di3 (tmp6, tmp5, GEN_INT (bits - 64)));
7691 :
7692 12 : rtx tmp7 = force_reg (V1TImode, gen_lowpart (V1TImode, tmp3));
7693 12 : rtx tmp8 = gen_reg_rtx (V1TImode);
7694 12 : emit_insn (gen_sse2_ashlv1ti3 (tmp8, tmp7, GEN_INT (64)));
7695 :
7696 12 : rtx tmp9 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp3));
7697 12 : rtx tmp10 = gen_reg_rtx (V2DImode);
7698 12 : emit_insn (gen_ashlv2di3 (tmp10, tmp9, GEN_INT (128 - bits)));
7699 :
7700 12 : rtx tmp11 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp8));
7701 12 : rtx tmp12 = gen_reg_rtx (V2DImode);
7702 12 : emit_insn (gen_iorv2di3 (tmp12, tmp10, tmp11));
7703 :
7704 12 : rtx tmp13 = gen_reg_rtx (V2DImode);
7705 12 : emit_insn (gen_iorv2di3 (tmp13, tmp6, tmp12));
7706 :
7707 12 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp13));
7708 : }
7709 : else
7710 : {
7711 : /* Nine operations. */
7712 26 : rtx tmp1 = force_reg (V4SImode, gen_lowpart (V4SImode, op1));
7713 26 : rtx tmp2 = gen_reg_rtx (V4SImode);
7714 26 : emit_insn (gen_sse2_pshufd (tmp2, tmp1, GEN_INT (0xff)));
7715 :
7716 26 : rtx tmp3 = gen_reg_rtx (V4SImode);
7717 26 : emit_insn (gen_ashrv4si3 (tmp3, tmp2, GEN_INT (31)));
7718 :
7719 26 : rtx tmp4 = gen_reg_rtx (V1TImode);
7720 26 : emit_insn (gen_sse2_lshrv1ti3 (tmp4, op1, GEN_INT (64)));
7721 :
7722 26 : rtx tmp5 = force_reg (V2DImode, gen_lowpart (V2DImode, op1));
7723 26 : rtx tmp6 = gen_reg_rtx (V2DImode);
7724 26 : emit_insn (gen_lshrv2di3 (tmp6, tmp5, GEN_INT (bits)));
7725 :
7726 26 : rtx tmp7 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp4));
7727 26 : rtx tmp8 = gen_reg_rtx (V2DImode);
7728 26 : emit_insn (gen_ashlv2di3 (tmp8, tmp7, GEN_INT (64 - bits)));
7729 :
7730 26 : rtx tmp9 = gen_reg_rtx (V2DImode);
7731 26 : emit_insn (gen_iorv2di3 (tmp9, tmp6, tmp8));
7732 :
7733 26 : rtx tmp10 = force_reg (V1TImode, gen_lowpart (V1TImode, tmp3));
7734 26 : rtx tmp11 = gen_reg_rtx (V1TImode);
7735 26 : emit_insn (gen_sse2_ashlv1ti3 (tmp11, tmp10, GEN_INT (64)));
7736 :
7737 26 : rtx tmp12 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp11));
7738 26 : rtx tmp13 = gen_reg_rtx (V2DImode);
7739 26 : emit_insn (gen_ashlv2di3 (tmp13, tmp12, GEN_INT (64 - bits)));
7740 :
7741 26 : rtx tmp14 = gen_reg_rtx (V2DImode);
7742 26 : emit_insn (gen_iorv2di3 (tmp14, tmp9, tmp13));
7743 :
7744 26 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp14));
7745 : }
7746 : }
7747 :
7748 : /* Expand V2DI mode ashiftrt. */
7749 : void
7750 439 : ix86_expand_v2di_ashiftrt (rtx operands[])
7751 : {
7752 439 : if (operands[2] == const0_rtx)
7753 : {
7754 0 : emit_move_insn (operands[0], operands[1]);
7755 0 : return;
7756 : }
7757 :
7758 439 : if (TARGET_SSE4_2
7759 135 : && CONST_INT_P (operands[2])
7760 135 : && UINTVAL (operands[2]) >= 63
7761 447 : && !optimize_insn_for_size_p ())
7762 : {
7763 8 : rtx zero = force_reg (V2DImode, CONST0_RTX (V2DImode));
7764 8 : emit_insn (gen_sse4_2_gtv2di3 (operands[0], zero, operands[1]));
7765 8 : return;
7766 : }
7767 :
7768 431 : if (CONST_INT_P (operands[2])
7769 405 : && (!TARGET_XOP || UINTVAL (operands[2]) >= 63))
7770 : {
7771 309 : vec_perm_builder sel (4, 4, 1);
7772 309 : sel.quick_grow (4);
7773 309 : rtx arg0, arg1;
7774 309 : rtx op1 = lowpart_subreg (V4SImode,
7775 : force_reg (V2DImode, operands[1]),
7776 : V2DImode);
7777 309 : rtx target = gen_reg_rtx (V4SImode);
7778 309 : if (UINTVAL (operands[2]) >= 63)
7779 : {
7780 117 : arg0 = arg1 = gen_reg_rtx (V4SImode);
7781 117 : emit_insn (gen_ashrv4si3 (arg0, op1, GEN_INT (31)));
7782 117 : sel[0] = 1;
7783 117 : sel[1] = 1;
7784 117 : sel[2] = 3;
7785 117 : sel[3] = 3;
7786 : }
7787 192 : else if (INTVAL (operands[2]) > 32)
7788 : {
7789 21 : arg0 = gen_reg_rtx (V4SImode);
7790 21 : arg1 = gen_reg_rtx (V4SImode);
7791 21 : emit_insn (gen_ashrv4si3 (arg1, op1, GEN_INT (31)));
7792 21 : emit_insn (gen_ashrv4si3 (arg0, op1,
7793 21 : GEN_INT (INTVAL (operands[2]) - 32)));
7794 21 : sel[0] = 1;
7795 21 : sel[1] = 5;
7796 21 : sel[2] = 3;
7797 21 : sel[3] = 7;
7798 : }
7799 171 : else if (INTVAL (operands[2]) == 32)
7800 : {
7801 5 : arg0 = op1;
7802 5 : arg1 = gen_reg_rtx (V4SImode);
7803 5 : emit_insn (gen_ashrv4si3 (arg1, op1, GEN_INT (31)));
7804 5 : sel[0] = 1;
7805 5 : sel[1] = 5;
7806 5 : sel[2] = 3;
7807 5 : sel[3] = 7;
7808 : }
7809 : else
7810 : {
7811 166 : arg0 = gen_reg_rtx (V2DImode);
7812 166 : arg1 = gen_reg_rtx (V4SImode);
7813 166 : emit_insn (gen_lshrv2di3 (arg0, operands[1], operands[2]));
7814 166 : emit_insn (gen_ashrv4si3 (arg1, op1, operands[2]));
7815 166 : arg0 = lowpart_subreg (V4SImode, arg0, V2DImode);
7816 166 : sel[0] = 0;
7817 166 : sel[1] = 5;
7818 166 : sel[2] = 2;
7819 166 : sel[3] = 7;
7820 : }
7821 426 : vec_perm_indices indices (sel, arg0 != arg1 ? 2 : 1, 4);
7822 309 : rtx op0 = operands[0];
7823 309 : bool ok = targetm.vectorize.vec_perm_const (V4SImode, V4SImode,
7824 : target, arg0, arg1,
7825 : indices);
7826 309 : gcc_assert (ok);
7827 309 : emit_move_insn (op0, lowpart_subreg (V2DImode, target, V4SImode));
7828 309 : return;
7829 309 : }
7830 122 : if (!TARGET_XOP)
7831 : {
7832 26 : rtx zero = force_reg (V2DImode, CONST0_RTX (V2DImode));
7833 26 : rtx zero_or_all_ones;
7834 26 : if (TARGET_SSE4_2)
7835 : {
7836 0 : zero_or_all_ones = gen_reg_rtx (V2DImode);
7837 0 : emit_insn (gen_sse4_2_gtv2di3 (zero_or_all_ones, zero,
7838 : operands[1]));
7839 : }
7840 : else
7841 : {
7842 26 : rtx temp = gen_reg_rtx (V4SImode);
7843 26 : emit_insn (gen_ashrv4si3 (temp,
7844 : lowpart_subreg (V4SImode,
7845 : force_reg (V2DImode,
7846 : operands[1]),
7847 : V2DImode),
7848 : GEN_INT (31)));
7849 26 : zero_or_all_ones = gen_reg_rtx (V4SImode);
7850 26 : emit_insn (gen_sse2_pshufd_1 (zero_or_all_ones, temp,
7851 : const1_rtx, const1_rtx,
7852 : GEN_INT (3), GEN_INT (3)));
7853 26 : zero_or_all_ones = lowpart_subreg (V2DImode, zero_or_all_ones,
7854 : V4SImode);
7855 : }
7856 26 : rtx lshr_res = gen_reg_rtx (V2DImode);
7857 26 : emit_insn (gen_lshrv2di3 (lshr_res, operands[1], operands[2]));
7858 26 : rtx ashl_res = gen_reg_rtx (V2DImode);
7859 26 : rtx amount;
7860 26 : if (TARGET_64BIT)
7861 : {
7862 26 : amount = gen_reg_rtx (DImode);
7863 26 : emit_insn (gen_subdi3 (amount, force_reg (DImode, GEN_INT (64)),
7864 : operands[2]));
7865 : }
7866 : else
7867 : {
7868 0 : rtx temp = gen_reg_rtx (SImode);
7869 0 : emit_insn (gen_subsi3 (temp, force_reg (SImode, GEN_INT (64)),
7870 : lowpart_subreg (SImode, operands[2],
7871 : DImode)));
7872 0 : amount = gen_reg_rtx (V4SImode);
7873 0 : emit_insn (gen_vec_setv4si_0 (amount, CONST0_RTX (V4SImode),
7874 : temp));
7875 : }
7876 26 : amount = lowpart_subreg (DImode, amount, GET_MODE (amount));
7877 26 : emit_insn (gen_ashlv2di3 (ashl_res, zero_or_all_ones, amount));
7878 26 : emit_insn (gen_iorv2di3 (operands[0], lshr_res, ashl_res));
7879 26 : return;
7880 : }
7881 :
7882 96 : rtx reg = gen_reg_rtx (V2DImode);
7883 96 : rtx par;
7884 96 : bool negate = false;
7885 96 : int i;
7886 :
7887 96 : if (CONST_INT_P (operands[2]))
7888 96 : operands[2] = GEN_INT (-INTVAL (operands[2]));
7889 : else
7890 : negate = true;
7891 :
7892 96 : par = gen_rtx_PARALLEL (V2DImode, rtvec_alloc (2));
7893 288 : for (i = 0; i < 2; i++)
7894 192 : XVECEXP (par, 0, i) = operands[2];
7895 :
7896 96 : emit_insn (gen_vec_initv2didi (reg, par));
7897 :
7898 96 : if (negate)
7899 0 : emit_insn (gen_negv2di2 (reg, reg));
7900 :
7901 96 : emit_insn (gen_xop_shav2di3 (operands[0], operands[1], reg));
7902 : }
7903 :
7904 : /* Replace all occurrences of REG FROM with REG TO in X, including
7905 : occurrences with different modes. */
7906 :
7907 : rtx
7908 43025 : ix86_replace_reg_with_reg (rtx x, rtx from, rtx to)
7909 : {
7910 43025 : gcc_checking_assert (REG_P (from)
7911 : && REG_P (to)
7912 : && GET_MODE (from) == GET_MODE (to));
7913 43025 : if (!reg_overlap_mentioned_p (from, x))
7914 : return x;
7915 90 : rtx ret = copy_rtx (x);
7916 90 : subrtx_ptr_iterator::array_type array;
7917 456 : FOR_EACH_SUBRTX_PTR (iter, array, &ret, NONCONST)
7918 : {
7919 366 : rtx *loc = *iter;
7920 366 : x = *loc;
7921 366 : if (REG_P (x) && REGNO (x) == REGNO (from))
7922 : {
7923 90 : if (x == from)
7924 90 : *loc = to;
7925 : else
7926 : {
7927 0 : gcc_checking_assert (REG_NREGS (x) == 1);
7928 0 : *loc = gen_rtx_REG (GET_MODE (x), REGNO (to));
7929 : }
7930 : }
7931 : }
7932 90 : return ret;
7933 90 : }
7934 :
7935 : /* Return mode for the memcpy/memset loop counter. Prefer SImode over
7936 : DImode for constant loop counts. */
7937 :
7938 : static machine_mode
7939 44852 : counter_mode (rtx count_exp)
7940 : {
7941 780 : if (GET_MODE (count_exp) != VOIDmode)
7942 32521 : return GET_MODE (count_exp);
7943 12331 : if (!CONST_INT_P (count_exp))
7944 0 : return Pmode;
7945 : if (TARGET_64BIT && (INTVAL (count_exp) & ~0xffffffff))
7946 : return DImode;
7947 : return SImode;
7948 : }
7949 :
7950 : /* When ISSETMEM is FALSE, output simple loop to move memory pointer to SRCPTR
7951 : to DESTPTR via chunks of MODE unrolled UNROLL times, overall size is COUNT
7952 : specified in bytes. When ISSETMEM is TRUE, output the equivalent loop to set
7953 : memory by VALUE (supposed to be in MODE).
7954 :
7955 : The size is rounded down to whole number of chunk size moved at once.
7956 : SRCMEM and DESTMEM provide MEMrtx to feed proper aliasing info. */
7957 :
7958 :
7959 : static void
7960 8233 : expand_set_or_cpymem_via_loop (rtx destmem, rtx srcmem,
7961 : rtx destptr, rtx srcptr, rtx value,
7962 : rtx count, machine_mode mode, int unroll,
7963 : int expected_size, bool issetmem)
7964 : {
7965 8233 : rtx_code_label *out_label = nullptr;
7966 8233 : rtx_code_label *top_label = nullptr;
7967 8233 : rtx iter, tmp;
7968 8233 : machine_mode iter_mode = counter_mode (count);
7969 8233 : int piece_size_n = GET_MODE_SIZE (mode) * unroll;
7970 8233 : rtx piece_size = GEN_INT (piece_size_n);
7971 16466 : rtx piece_size_mask = GEN_INT (~((GET_MODE_SIZE (mode) * unroll) - 1));
7972 8233 : rtx size;
7973 8233 : int i;
7974 8233 : int loop_count;
7975 :
7976 8233 : if (expected_size != -1 && CONST_INT_P (count))
7977 7225 : loop_count = INTVAL (count) / GET_MODE_SIZE (mode) / unroll;
7978 : else
7979 : loop_count = -1;
7980 :
7981 : /* Don't generate the loop if the loop count is 1. */
7982 7225 : if (loop_count != 1)
7983 : {
7984 8231 : top_label = gen_label_rtx ();
7985 8231 : out_label = gen_label_rtx ();
7986 : }
7987 8233 : iter = gen_reg_rtx (iter_mode);
7988 :
7989 8233 : size = expand_simple_binop (iter_mode, AND, count, piece_size_mask,
7990 : NULL, 1, OPTAB_DIRECT);
7991 : /* Those two should combine. */
7992 8233 : if (piece_size == const1_rtx)
7993 : {
7994 277 : emit_cmp_and_jump_insns (size, const0_rtx, EQ, NULL_RTX, iter_mode,
7995 : true, out_label);
7996 277 : predict_jump (REG_BR_PROB_BASE * 10 / 100);
7997 : }
7998 8233 : emit_move_insn (iter, const0_rtx);
7999 :
8000 8233 : if (loop_count != 1)
8001 8231 : emit_label (top_label);
8002 :
8003 10963 : tmp = convert_modes (Pmode, iter_mode, iter, true);
8004 :
8005 : /* This assert could be relaxed - in this case we'll need to compute
8006 : smallest power of two, containing in PIECE_SIZE_N and pass it to
8007 : offset_address. */
8008 8233 : gcc_assert ((piece_size_n & (piece_size_n - 1)) == 0);
8009 8233 : destmem = offset_address (destmem, tmp, piece_size_n);
8010 8233 : destmem = adjust_address (destmem, mode, 0);
8011 :
8012 8233 : if (!issetmem)
8013 : {
8014 2903 : srcmem = offset_address (srcmem, copy_rtx (tmp), piece_size_n);
8015 2903 : srcmem = adjust_address (srcmem, mode, 0);
8016 :
8017 : /* When unrolling for chips that reorder memory reads and writes,
8018 : we can save registers by using single temporary.
8019 : Also using 4 temporaries is overkill in 32bit mode. */
8020 2903 : if (!TARGET_64BIT && 0)
8021 : {
8022 : for (i = 0; i < unroll; i++)
8023 : {
8024 : if (i)
8025 : {
8026 : destmem = adjust_address (copy_rtx (destmem), mode,
8027 : GET_MODE_SIZE (mode));
8028 : srcmem = adjust_address (copy_rtx (srcmem), mode,
8029 : GET_MODE_SIZE (mode));
8030 : }
8031 : emit_move_insn (destmem, srcmem);
8032 : }
8033 : }
8034 : else
8035 : {
8036 2903 : rtx tmpreg[4];
8037 2903 : gcc_assert (unroll <= 4);
8038 13701 : for (i = 0; i < unroll; i++)
8039 : {
8040 10798 : tmpreg[i] = gen_reg_rtx (mode);
8041 10798 : if (i)
8042 15790 : srcmem = adjust_address (copy_rtx (srcmem), mode,
8043 : GET_MODE_SIZE (mode));
8044 10798 : emit_move_insn (tmpreg[i], srcmem);
8045 : }
8046 13701 : for (i = 0; i < unroll; i++)
8047 : {
8048 10798 : if (i)
8049 15790 : destmem = adjust_address (copy_rtx (destmem), mode,
8050 : GET_MODE_SIZE (mode));
8051 10798 : emit_move_insn (destmem, tmpreg[i]);
8052 : }
8053 : }
8054 : }
8055 : else
8056 26479 : for (i = 0; i < unroll; i++)
8057 : {
8058 21149 : if (i)
8059 31638 : destmem = adjust_address (copy_rtx (destmem), mode,
8060 : GET_MODE_SIZE (mode));
8061 21149 : emit_move_insn (destmem, value);
8062 : }
8063 :
8064 8233 : tmp = expand_simple_binop (iter_mode, PLUS, iter, piece_size, iter,
8065 : true, OPTAB_LIB_WIDEN);
8066 8233 : if (tmp != iter)
8067 0 : emit_move_insn (iter, tmp);
8068 :
8069 8233 : if (loop_count != 1)
8070 : {
8071 8231 : emit_cmp_and_jump_insns (iter, size, LT, NULL_RTX, iter_mode,
8072 : true, top_label);
8073 8231 : if (expected_size != -1)
8074 : {
8075 7339 : expected_size /= GET_MODE_SIZE (mode) * unroll;
8076 7339 : if (expected_size == 0)
8077 0 : predict_jump (0);
8078 7339 : else if (expected_size > REG_BR_PROB_BASE)
8079 2 : predict_jump (REG_BR_PROB_BASE - 1);
8080 : else
8081 7337 : predict_jump (REG_BR_PROB_BASE
8082 7337 : - (REG_BR_PROB_BASE + expected_size / 2)
8083 7337 : / expected_size);
8084 : }
8085 : else
8086 892 : predict_jump (REG_BR_PROB_BASE * 80 / 100);
8087 : }
8088 8233 : iter = ix86_zero_extend_to_Pmode (iter);
8089 10963 : tmp = expand_simple_binop (Pmode, PLUS, destptr, iter, destptr,
8090 : true, OPTAB_LIB_WIDEN);
8091 8233 : if (tmp != destptr)
8092 0 : emit_move_insn (destptr, tmp);
8093 8233 : if (!issetmem)
8094 : {
8095 4234 : tmp = expand_simple_binop (Pmode, PLUS, srcptr, iter, srcptr,
8096 : true, OPTAB_LIB_WIDEN);
8097 2903 : if (tmp != srcptr)
8098 0 : emit_move_insn (srcptr, tmp);
8099 : }
8100 8233 : if (loop_count != 1)
8101 8231 : emit_label (out_label);
8102 8233 : }
8103 :
8104 : /* Divide COUNTREG by SCALE. */
8105 : static rtx
8106 18645 : scale_counter (rtx countreg, int scale)
8107 : {
8108 18645 : rtx sc;
8109 :
8110 18645 : if (scale == 1)
8111 : return countreg;
8112 12876 : if (CONST_INT_P (countreg))
8113 12858 : return GEN_INT (INTVAL (countreg) / scale);
8114 18 : gcc_assert (REG_P (countreg));
8115 :
8116 54 : sc = expand_simple_binop (GET_MODE (countreg), LSHIFTRT, countreg,
8117 36 : GEN_INT (exact_log2 (scale)),
8118 : NULL, 1, OPTAB_DIRECT);
8119 18 : return sc;
8120 : }
8121 :
8122 : /* Output "rep; mov" or "rep; stos" instruction depending on ISSETMEM argument.
8123 : When ISSETMEM is true, arguments SRCMEM and SRCPTR are ignored.
8124 : When ISSETMEM is false, arguments VALUE and ORIG_VALUE are ignored.
8125 : For setmem case, VALUE is a promoted to a wider size ORIG_VALUE.
8126 : ORIG_VALUE is the original value passed to memset to fill the memory with.
8127 : Other arguments have same meaning as for previous function. */
8128 :
8129 : static void
8130 18645 : expand_set_or_cpymem_via_rep (rtx destmem, rtx srcmem,
8131 : rtx destptr, rtx srcptr, rtx value, rtx orig_value,
8132 : rtx count,
8133 : machine_mode mode, bool issetmem)
8134 : {
8135 18645 : rtx destexp;
8136 18645 : rtx srcexp;
8137 18645 : rtx countreg;
8138 18645 : HOST_WIDE_INT rounded_count;
8139 :
8140 : /* If possible, it is shorter to use rep movs.
8141 : TODO: Maybe it is better to move this logic to decide_alg. */
8142 18645 : if (mode == QImode && CONST_INT_P (count) && !(INTVAL (count) & 3)
8143 255 : && !TARGET_PREFER_KNOWN_REP_MOVSB_STOSB
8144 251 : && (!issetmem || orig_value == const0_rtx))
8145 18645 : mode = SImode;
8146 :
8147 18645 : if (destptr != XEXP (destmem, 0) || GET_MODE (destmem) != BLKmode)
8148 18361 : destmem = adjust_automodify_address_nv (destmem, BLKmode, destptr, 0);
8149 :
8150 37290 : countreg = ix86_zero_extend_to_Pmode (scale_counter (count,
8151 18645 : GET_MODE_SIZE (mode)));
8152 18645 : if (mode != QImode)
8153 : {
8154 38888 : destexp = gen_rtx_ASHIFT (Pmode, countreg,
8155 : GEN_INT (exact_log2 (GET_MODE_SIZE (mode))));
8156 13136 : destexp = gen_rtx_PLUS (Pmode, destexp, destptr);
8157 : }
8158 : else
8159 5788 : destexp = gen_rtx_PLUS (Pmode, destptr, countreg);
8160 18645 : if ((!issetmem || orig_value == const0_rtx) && CONST_INT_P (count))
8161 : {
8162 13546 : rounded_count
8163 13546 : = ROUND_DOWN (INTVAL (count), (HOST_WIDE_INT) GET_MODE_SIZE (mode));
8164 13546 : destmem = shallow_copy_rtx (destmem);
8165 13546 : set_mem_size (destmem, rounded_count);
8166 : }
8167 5107 : else if (MEM_SIZE_KNOWN_P (destmem))
8168 346 : clear_mem_size (destmem);
8169 :
8170 18645 : if (issetmem)
8171 : {
8172 7938 : value = force_reg (mode, gen_lowpart (mode, value));
8173 7938 : emit_insn (gen_rep_stos (destptr, countreg, destmem, value, destexp));
8174 : }
8175 : else
8176 : {
8177 10707 : if (srcptr != XEXP (srcmem, 0) || GET_MODE (srcmem) != BLKmode)
8178 10493 : srcmem = adjust_automodify_address_nv (srcmem, BLKmode, srcptr, 0);
8179 10707 : if (mode != QImode)
8180 : {
8181 18988 : srcexp = gen_rtx_ASHIFT (Pmode, countreg,
8182 : GEN_INT (exact_log2 (GET_MODE_SIZE (mode))));
8183 6452 : srcexp = gen_rtx_PLUS (Pmode, srcexp, srcptr);
8184 : }
8185 : else
8186 4454 : srcexp = gen_rtx_PLUS (Pmode, srcptr, countreg);
8187 10707 : if (CONST_INT_P (count))
8188 : {
8189 6763 : rounded_count
8190 6763 : = ROUND_DOWN (INTVAL (count), (HOST_WIDE_INT) GET_MODE_SIZE (mode));
8191 6763 : srcmem = shallow_copy_rtx (srcmem);
8192 6763 : set_mem_size (srcmem, rounded_count);
8193 : }
8194 : else
8195 : {
8196 3959 : if (MEM_SIZE_KNOWN_P (srcmem))
8197 0 : clear_mem_size (srcmem);
8198 : }
8199 10707 : emit_insn (gen_rep_mov (destptr, destmem, srcptr, srcmem, countreg,
8200 : destexp, srcexp));
8201 : }
8202 18645 : }
8203 :
8204 : /* This function emits moves to copy SIZE_TO_MOVE bytes from SRCMEM to
8205 : DESTMEM.
8206 : SRC is passed by pointer to be updated on return.
8207 : Return value is updated DST. */
8208 : static rtx
8209 13 : emit_memmov (rtx destmem, rtx *srcmem, rtx destptr, rtx srcptr,
8210 : HOST_WIDE_INT size_to_move)
8211 : {
8212 13 : rtx dst = destmem, src = *srcmem, tempreg;
8213 13 : enum insn_code code;
8214 13 : machine_mode move_mode;
8215 13 : int piece_size, i;
8216 :
8217 : /* Find the widest mode in which we could perform moves.
8218 : Start with the biggest power of 2 less than SIZE_TO_MOVE and half
8219 : it until move of such size is supported. */
8220 13 : piece_size = 1 << floor_log2 (size_to_move);
8221 26 : while (!int_mode_for_size (piece_size * BITS_PER_UNIT, 0).exists (&move_mode)
8222 26 : || (code = optab_handler (mov_optab, move_mode)) == CODE_FOR_nothing)
8223 : {
8224 0 : gcc_assert (piece_size > 1);
8225 0 : piece_size >>= 1;
8226 : }
8227 :
8228 : /* Find the corresponding vector mode with the same size as MOVE_MODE.
8229 : MOVE_MODE is an integer mode at the moment (SI, DI, TI, etc.). */
8230 39 : if (GET_MODE_SIZE (move_mode) > GET_MODE_SIZE (word_mode))
8231 : {
8232 0 : int nunits = GET_MODE_SIZE (move_mode) / GET_MODE_SIZE (word_mode);
8233 0 : if (!mode_for_vector (word_mode, nunits).exists (&move_mode)
8234 0 : || (code = optab_handler (mov_optab, move_mode)) == CODE_FOR_nothing)
8235 : {
8236 0 : move_mode = word_mode;
8237 0 : piece_size = GET_MODE_SIZE (move_mode);
8238 0 : code = optab_handler (mov_optab, move_mode);
8239 : }
8240 : }
8241 13 : gcc_assert (code != CODE_FOR_nothing);
8242 :
8243 13 : dst = adjust_automodify_address_nv (dst, move_mode, destptr, 0);
8244 13 : src = adjust_automodify_address_nv (src, move_mode, srcptr, 0);
8245 :
8246 : /* Emit moves. We'll need SIZE_TO_MOVE/PIECE_SIZES moves. */
8247 13 : gcc_assert (size_to_move % piece_size == 0);
8248 :
8249 26 : for (i = 0; i < size_to_move; i += piece_size)
8250 : {
8251 : /* We move from memory to memory, so we'll need to do it via
8252 : a temporary register. */
8253 13 : tempreg = gen_reg_rtx (move_mode);
8254 13 : emit_insn (GEN_FCN (code) (tempreg, src));
8255 13 : emit_insn (GEN_FCN (code) (dst, tempreg));
8256 :
8257 26 : emit_move_insn (destptr,
8258 13 : plus_constant (Pmode, copy_rtx (destptr), piece_size));
8259 26 : emit_move_insn (srcptr,
8260 13 : plus_constant (Pmode, copy_rtx (srcptr), piece_size));
8261 :
8262 13 : dst = adjust_automodify_address_nv (dst, move_mode, destptr,
8263 : piece_size);
8264 13 : src = adjust_automodify_address_nv (src, move_mode, srcptr,
8265 : piece_size);
8266 : }
8267 :
8268 : /* Update DST and SRC rtx. */
8269 13 : *srcmem = src;
8270 13 : return dst;
8271 : }
8272 :
8273 : /* Helper function for the string operations below. Dest VARIABLE whether
8274 : it is aligned to VALUE bytes. If true, jump to the label. */
8275 :
8276 : static rtx_code_label *
8277 3341 : ix86_expand_aligntest (rtx variable, int value, bool epilogue)
8278 : {
8279 3341 : rtx_code_label *label = gen_label_rtx ();
8280 3341 : rtx tmpcount = gen_reg_rtx (GET_MODE (variable));
8281 3341 : if (GET_MODE (variable) == DImode)
8282 746 : emit_insn (gen_anddi3 (tmpcount, variable, GEN_INT (value)));
8283 : else
8284 2595 : emit_insn (gen_andsi3 (tmpcount, variable, GEN_INT (value)));
8285 3341 : emit_cmp_and_jump_insns (tmpcount, const0_rtx, EQ, 0, GET_MODE (variable),
8286 : 1, label);
8287 3341 : if (epilogue)
8288 0 : predict_jump (REG_BR_PROB_BASE * 50 / 100);
8289 : else
8290 3341 : predict_jump (REG_BR_PROB_BASE * 90 / 100);
8291 3341 : return label;
8292 : }
8293 :
8294 :
8295 : /* Output code to copy at most count & (max_size - 1) bytes from SRC to DEST. */
8296 :
8297 : static void
8298 6839 : expand_cpymem_epilogue (rtx destmem, rtx srcmem,
8299 : rtx destptr, rtx srcptr, rtx count, int max_size)
8300 : {
8301 6839 : rtx src, dest;
8302 6839 : if (CONST_INT_P (count))
8303 : {
8304 6774 : unsigned HOST_WIDE_INT countval = UINTVAL (count);
8305 6774 : unsigned HOST_WIDE_INT epilogue_size = countval % max_size;
8306 6774 : unsigned int destalign = MEM_ALIGN (destmem);
8307 6774 : cfun->machine->by_pieces_in_use = true;
8308 6774 : move_by_pieces (destmem, srcmem, epilogue_size, destalign,
8309 : RETURN_BEGIN);
8310 6774 : cfun->machine->by_pieces_in_use = false;
8311 6774 : return;
8312 : }
8313 65 : if (max_size > 8)
8314 : {
8315 65 : count = expand_simple_binop (GET_MODE (count), AND, count, GEN_INT (max_size - 1),
8316 : count, 1, OPTAB_DIRECT);
8317 65 : expand_set_or_cpymem_via_loop (destmem, srcmem, destptr, srcptr, NULL,
8318 : count, QImode, 1, 4, false);
8319 65 : return;
8320 : }
8321 :
8322 : /* When there are stringops, we can cheaply increase dest and src pointers.
8323 : Otherwise we save code size by maintaining offset (zero is readily
8324 : available from preceding rep operation) and using x86 addressing modes.
8325 : */
8326 0 : if (TARGET_SINGLE_STRINGOP)
8327 : {
8328 0 : if (max_size > 4)
8329 : {
8330 0 : rtx_code_label *label = ix86_expand_aligntest (count, 4, true);
8331 0 : src = change_address (srcmem, SImode, srcptr);
8332 0 : dest = change_address (destmem, SImode, destptr);
8333 0 : emit_insn (gen_strmov (destptr, dest, srcptr, src));
8334 0 : emit_label (label);
8335 0 : LABEL_NUSES (label) = 1;
8336 : }
8337 0 : if (max_size > 2)
8338 : {
8339 0 : rtx_code_label *label = ix86_expand_aligntest (count, 2, true);
8340 0 : src = change_address (srcmem, HImode, srcptr);
8341 0 : dest = change_address (destmem, HImode, destptr);
8342 0 : emit_insn (gen_strmov (destptr, dest, srcptr, src));
8343 0 : emit_label (label);
8344 0 : LABEL_NUSES (label) = 1;
8345 : }
8346 0 : if (max_size > 1)
8347 : {
8348 0 : rtx_code_label *label = ix86_expand_aligntest (count, 1, true);
8349 0 : src = change_address (srcmem, QImode, srcptr);
8350 0 : dest = change_address (destmem, QImode, destptr);
8351 0 : emit_insn (gen_strmov (destptr, dest, srcptr, src));
8352 0 : emit_label (label);
8353 0 : LABEL_NUSES (label) = 1;
8354 : }
8355 : }
8356 : else
8357 : {
8358 0 : rtx offset = force_reg (Pmode, const0_rtx);
8359 0 : rtx tmp;
8360 :
8361 0 : if (max_size > 4)
8362 : {
8363 0 : rtx_code_label *label = ix86_expand_aligntest (count, 4, true);
8364 0 : src = change_address (srcmem, SImode, srcptr);
8365 0 : dest = change_address (destmem, SImode, destptr);
8366 0 : emit_move_insn (dest, src);
8367 0 : tmp = expand_simple_binop (Pmode, PLUS, offset, GEN_INT (4), NULL,
8368 : true, OPTAB_LIB_WIDEN);
8369 0 : if (tmp != offset)
8370 0 : emit_move_insn (offset, tmp);
8371 0 : emit_label (label);
8372 0 : LABEL_NUSES (label) = 1;
8373 : }
8374 0 : if (max_size > 2)
8375 : {
8376 0 : rtx_code_label *label = ix86_expand_aligntest (count, 2, true);
8377 0 : tmp = gen_rtx_PLUS (Pmode, srcptr, offset);
8378 0 : src = change_address (srcmem, HImode, tmp);
8379 0 : tmp = gen_rtx_PLUS (Pmode, destptr, offset);
8380 0 : dest = change_address (destmem, HImode, tmp);
8381 0 : emit_move_insn (dest, src);
8382 0 : tmp = expand_simple_binop (Pmode, PLUS, offset, GEN_INT (2), tmp,
8383 : true, OPTAB_LIB_WIDEN);
8384 0 : if (tmp != offset)
8385 0 : emit_move_insn (offset, tmp);
8386 0 : emit_label (label);
8387 0 : LABEL_NUSES (label) = 1;
8388 : }
8389 0 : if (max_size > 1)
8390 : {
8391 0 : rtx_code_label *label = ix86_expand_aligntest (count, 1, true);
8392 0 : tmp = gen_rtx_PLUS (Pmode, srcptr, offset);
8393 0 : src = change_address (srcmem, QImode, tmp);
8394 0 : tmp = gen_rtx_PLUS (Pmode, destptr, offset);
8395 0 : dest = change_address (destmem, QImode, tmp);
8396 0 : emit_move_insn (dest, src);
8397 0 : emit_label (label);
8398 0 : LABEL_NUSES (label) = 1;
8399 : }
8400 : }
8401 : }
8402 :
8403 : /* This function emits moves to fill SIZE_TO_MOVE bytes starting from DESTMEM
8404 : with value PROMOTED_VAL.
8405 : SRC is passed by pointer to be updated on return.
8406 : Return value is updated DST. */
8407 : static rtx
8408 6 : emit_memset (rtx destmem, rtx destptr, rtx promoted_val,
8409 : HOST_WIDE_INT size_to_move)
8410 : {
8411 6 : rtx dst = destmem;
8412 6 : enum insn_code code;
8413 6 : machine_mode move_mode;
8414 6 : int piece_size, i;
8415 :
8416 : /* Find the widest mode in which we could perform moves.
8417 : Start with the biggest power of 2 less than SIZE_TO_MOVE and half
8418 : it until move of such size is supported. */
8419 6 : move_mode = GET_MODE (promoted_val);
8420 6 : if (move_mode == VOIDmode)
8421 0 : move_mode = QImode;
8422 12 : if (size_to_move < GET_MODE_SIZE (move_mode))
8423 : {
8424 5 : unsigned int move_bits = size_to_move * BITS_PER_UNIT;
8425 5 : move_mode = int_mode_for_size (move_bits, 0).require ();
8426 5 : promoted_val = gen_lowpart (move_mode, promoted_val);
8427 : }
8428 6 : piece_size = GET_MODE_SIZE (move_mode);
8429 6 : code = optab_handler (mov_optab, move_mode);
8430 6 : gcc_assert (code != CODE_FOR_nothing && promoted_val != NULL_RTX);
8431 :
8432 6 : dst = adjust_automodify_address_nv (dst, move_mode, destptr, 0);
8433 :
8434 : /* Emit moves. We'll need SIZE_TO_MOVE/PIECE_SIZES moves. */
8435 6 : gcc_assert (size_to_move % piece_size == 0);
8436 :
8437 12 : for (i = 0; i < size_to_move; i += piece_size)
8438 : {
8439 12 : if (piece_size <= GET_MODE_SIZE (word_mode))
8440 : {
8441 4 : emit_insn (gen_strset (destptr, dst, promoted_val));
8442 4 : dst = adjust_automodify_address_nv (dst, move_mode, destptr,
8443 : piece_size);
8444 4 : continue;
8445 : }
8446 :
8447 2 : emit_insn (GEN_FCN (code) (dst, promoted_val));
8448 :
8449 4 : emit_move_insn (destptr,
8450 2 : plus_constant (Pmode, copy_rtx (destptr), piece_size));
8451 :
8452 2 : dst = adjust_automodify_address_nv (dst, move_mode, destptr,
8453 : piece_size);
8454 : }
8455 :
8456 : /* Update DST rtx. */
8457 6 : return dst;
8458 : }
8459 : /* Output code to set at most count & (max_size - 1) bytes starting by DEST. */
8460 : static void
8461 39 : expand_setmem_epilogue_via_loop (rtx destmem, rtx destptr, rtx value,
8462 : rtx count, int max_size)
8463 : {
8464 78 : count = expand_simple_binop (counter_mode (count), AND, count,
8465 39 : GEN_INT (max_size - 1), count, 1, OPTAB_DIRECT);
8466 39 : expand_set_or_cpymem_via_loop (destmem, NULL, destptr, NULL,
8467 39 : gen_lowpart (QImode, value), count, QImode,
8468 : 1, max_size / 2, true);
8469 39 : }
8470 :
8471 : /* Callback routine for store_by_pieces. Return the RTL of a register
8472 : containing GET_MODE_SIZE (MODE) bytes in the RTL register op_p which
8473 : is an integer or a word vector register. If PREV_P isn't nullptr,
8474 : it has the RTL info from the previous iteration. */
8475 :
8476 : static rtx
8477 5048 : setmem_epilogue_gen_val (void *op_p, void *prev_p, HOST_WIDE_INT,
8478 : fixed_size_mode mode)
8479 : {
8480 5048 : rtx target;
8481 5048 : by_pieces_prev *prev = (by_pieces_prev *) prev_p;
8482 5048 : if (prev)
8483 : {
8484 5048 : rtx prev_op = prev->data;
8485 5048 : if (prev_op)
8486 : {
8487 2924 : machine_mode prev_mode = GET_MODE (prev_op);
8488 2924 : if (prev_mode == mode)
8489 : return prev_op;
8490 54 : if (VECTOR_MODE_P (prev_mode)
8491 1098 : && VECTOR_MODE_P (mode)
8492 1152 : && GET_MODE_INNER (prev_mode) == GET_MODE_INNER (mode))
8493 : {
8494 0 : target = gen_rtx_SUBREG (mode, prev_op, 0);
8495 0 : return target;
8496 : }
8497 : }
8498 : }
8499 :
8500 3276 : rtx op = (rtx) op_p;
8501 3276 : machine_mode op_mode = GET_MODE (op);
8502 :
8503 3276 : if (VECTOR_MODE_P (mode))
8504 : {
8505 3712 : gcc_assert (GET_MODE_INNER (mode) == QImode);
8506 :
8507 1856 : unsigned int op_size = GET_MODE_SIZE (op_mode);
8508 1856 : unsigned int size = GET_MODE_SIZE (mode);
8509 1856 : unsigned int nunits;
8510 1856 : machine_mode vec_mode;
8511 1856 : if (op_size < size)
8512 : {
8513 : /* If OP size is smaller than MODE size, duplicate it. */
8514 1 : nunits = size / GET_MODE_SIZE (QImode);
8515 1 : vec_mode = mode_for_vector (QImode, nunits).require ();
8516 1 : nunits = size / op_size;
8517 1 : gcc_assert (SCALAR_INT_MODE_P (op_mode));
8518 1 : machine_mode dup_mode
8519 1 : = mode_for_vector (as_a <scalar_mode> (op_mode),
8520 2 : nunits).require ();
8521 1 : target = gen_reg_rtx (vec_mode);
8522 1 : op = gen_vec_duplicate (dup_mode, op);
8523 1 : rtx dup_op = gen_reg_rtx (dup_mode);
8524 1 : emit_move_insn (dup_op, op);
8525 1 : op = gen_rtx_SUBREG (vec_mode, dup_op, 0);
8526 1 : emit_move_insn (target, op);
8527 1 : return target;
8528 : }
8529 1855 : nunits = op_size / GET_MODE_SIZE (QImode);
8530 1855 : vec_mode = mode_for_vector (QImode, nunits).require ();
8531 1855 : target = gen_reg_rtx (vec_mode);
8532 1855 : op = gen_rtx_SUBREG (vec_mode, op, 0);
8533 1855 : emit_move_insn (target, op);
8534 1855 : if (op_size == size)
8535 : return target;
8536 :
8537 0 : rtx tmp = gen_reg_rtx (mode);
8538 0 : target = gen_rtx_SUBREG (mode, target, 0);
8539 0 : emit_move_insn (tmp, target);
8540 0 : return tmp;
8541 : }
8542 :
8543 1420 : if (VECTOR_MODE_P (op_mode))
8544 : {
8545 2830 : gcc_assert (GET_MODE_INNER (op_mode) == word_mode);
8546 1415 : target = gen_reg_rtx (word_mode);
8547 1415 : op = gen_rtx_SUBREG (word_mode, op, 0);
8548 1415 : emit_move_insn (target, op);
8549 : }
8550 : else
8551 : target = op;
8552 :
8553 1420 : if (mode == GET_MODE (target))
8554 : return target;
8555 :
8556 245 : rtx tmp = gen_reg_rtx (mode);
8557 245 : target = gen_rtx_SUBREG (mode, target, 0);
8558 245 : emit_move_insn (tmp, target);
8559 245 : return tmp;
8560 : }
8561 :
8562 : /* Output code to set at most count & (max_size - 1) bytes starting by DEST. */
8563 : static void
8564 9997 : expand_setmem_epilogue (rtx destmem, rtx destptr, rtx value, rtx vec_value,
8565 : rtx count, int max_size)
8566 : {
8567 9997 : rtx dest;
8568 :
8569 9997 : if (CONST_INT_P (count))
8570 : {
8571 9958 : unsigned HOST_WIDE_INT countval = UINTVAL (count);
8572 9958 : unsigned HOST_WIDE_INT epilogue_size = countval % max_size;
8573 9958 : unsigned int destalign = MEM_ALIGN (destmem);
8574 9958 : cfun->machine->by_pieces_in_use = true;
8575 16509 : store_by_pieces (destmem, epilogue_size, setmem_epilogue_gen_val,
8576 : vec_value ? vec_value : value, destalign, true,
8577 : RETURN_BEGIN);
8578 9958 : cfun->machine->by_pieces_in_use = false;
8579 9958 : return;
8580 : }
8581 39 : if (max_size > 32)
8582 : {
8583 39 : expand_setmem_epilogue_via_loop (destmem, destptr, value, count, max_size);
8584 39 : return;
8585 : }
8586 0 : if (max_size > 16)
8587 : {
8588 0 : rtx_code_label *label = ix86_expand_aligntest (count, 16, true);
8589 0 : if (TARGET_64BIT)
8590 : {
8591 0 : dest = change_address (destmem, DImode, destptr);
8592 0 : emit_insn (gen_strset (destptr, dest, value));
8593 0 : dest = adjust_automodify_address_nv (dest, DImode, destptr, 8);
8594 0 : emit_insn (gen_strset (destptr, dest, value));
8595 : }
8596 : else
8597 : {
8598 0 : dest = change_address (destmem, SImode, destptr);
8599 0 : emit_insn (gen_strset (destptr, dest, value));
8600 0 : dest = adjust_automodify_address_nv (dest, SImode, destptr, 4);
8601 0 : emit_insn (gen_strset (destptr, dest, value));
8602 0 : dest = adjust_automodify_address_nv (dest, SImode, destptr, 8);
8603 0 : emit_insn (gen_strset (destptr, dest, value));
8604 0 : dest = adjust_automodify_address_nv (dest, SImode, destptr, 12);
8605 0 : emit_insn (gen_strset (destptr, dest, value));
8606 : }
8607 0 : emit_label (label);
8608 0 : LABEL_NUSES (label) = 1;
8609 : }
8610 0 : if (max_size > 8)
8611 : {
8612 0 : rtx_code_label *label = ix86_expand_aligntest (count, 8, true);
8613 0 : if (TARGET_64BIT)
8614 : {
8615 0 : dest = change_address (destmem, DImode, destptr);
8616 0 : emit_insn (gen_strset (destptr, dest, value));
8617 : }
8618 : else
8619 : {
8620 0 : dest = change_address (destmem, SImode, destptr);
8621 0 : emit_insn (gen_strset (destptr, dest, value));
8622 0 : dest = adjust_automodify_address_nv (dest, SImode, destptr, 4);
8623 0 : emit_insn (gen_strset (destptr, dest, value));
8624 : }
8625 0 : emit_label (label);
8626 0 : LABEL_NUSES (label) = 1;
8627 : }
8628 0 : if (max_size > 4)
8629 : {
8630 0 : rtx_code_label *label = ix86_expand_aligntest (count, 4, true);
8631 0 : dest = change_address (destmem, SImode, destptr);
8632 0 : emit_insn (gen_strset (destptr, dest, gen_lowpart (SImode, value)));
8633 0 : emit_label (label);
8634 0 : LABEL_NUSES (label) = 1;
8635 : }
8636 0 : if (max_size > 2)
8637 : {
8638 0 : rtx_code_label *label = ix86_expand_aligntest (count, 2, true);
8639 0 : dest = change_address (destmem, HImode, destptr);
8640 0 : emit_insn (gen_strset (destptr, dest, gen_lowpart (HImode, value)));
8641 0 : emit_label (label);
8642 0 : LABEL_NUSES (label) = 1;
8643 : }
8644 0 : if (max_size > 1)
8645 : {
8646 0 : rtx_code_label *label = ix86_expand_aligntest (count, 1, true);
8647 0 : dest = change_address (destmem, QImode, destptr);
8648 0 : emit_insn (gen_strset (destptr, dest, gen_lowpart (QImode, value)));
8649 0 : emit_label (label);
8650 0 : LABEL_NUSES (label) = 1;
8651 : }
8652 : }
8653 :
8654 : /* Adjust COUNTER by the VALUE. */
8655 : static void
8656 19 : ix86_adjust_counter (rtx countreg, HOST_WIDE_INT value)
8657 : {
8658 19 : emit_insn (gen_add2_insn (countreg, GEN_INT (-value)));
8659 19 : }
8660 :
8661 : /* Depending on ISSETMEM, copy enough from SRCMEM to DESTMEM or set enough to
8662 : DESTMEM to align it to DESIRED_ALIGNMENT. Original alignment is ALIGN.
8663 : Depending on ISSETMEM, either arguments SRCMEM/SRCPTR or VALUE/VEC_VALUE are
8664 : ignored.
8665 : Return value is updated DESTMEM. */
8666 :
8667 : static rtx
8668 7 : expand_set_or_cpymem_prologue (rtx destmem, rtx srcmem,
8669 : rtx destptr, rtx srcptr, rtx value,
8670 : rtx vec_value, rtx count, int align,
8671 : int desired_alignment, bool issetmem)
8672 : {
8673 7 : int i;
8674 35 : for (i = 1; i < desired_alignment; i <<= 1)
8675 : {
8676 28 : if (align <= i)
8677 : {
8678 19 : rtx_code_label *label = ix86_expand_aligntest (destptr, i, false);
8679 19 : if (issetmem)
8680 : {
8681 12 : if (vec_value && i > GET_MODE_SIZE (GET_MODE (value)))
8682 2 : destmem = emit_memset (destmem, destptr, vec_value, i);
8683 : else
8684 4 : destmem = emit_memset (destmem, destptr, value, i);
8685 : }
8686 : else
8687 13 : destmem = emit_memmov (destmem, &srcmem, destptr, srcptr, i);
8688 19 : ix86_adjust_counter (count, i);
8689 19 : emit_label (label);
8690 19 : LABEL_NUSES (label) = 1;
8691 19 : set_mem_align (destmem, i * 2 * BITS_PER_UNIT);
8692 : }
8693 : }
8694 7 : return destmem;
8695 : }
8696 :
8697 : /* Test if COUNT&SIZE is nonzero and if so, expand movme
8698 : or setmem sequence that is valid for SIZE..2*SIZE-1 bytes
8699 : and jump to DONE_LABEL. */
8700 : static void
8701 2654 : expand_small_cpymem_or_setmem (rtx destmem, rtx srcmem,
8702 : rtx destptr, rtx srcptr,
8703 : rtx value, rtx vec_value,
8704 : rtx count, int size,
8705 : rtx done_label, bool issetmem)
8706 : {
8707 2654 : rtx_code_label *label = ix86_expand_aligntest (count, size, false);
8708 2654 : machine_mode mode = int_mode_for_size (size * BITS_PER_UNIT, 1).else_blk ();
8709 2654 : rtx modesize;
8710 2654 : rtx scalar_value = value;
8711 2654 : int n;
8712 :
8713 : /* If we do not have vector value to copy, we must reduce size. */
8714 2654 : if (issetmem)
8715 : {
8716 881 : if (!vec_value)
8717 : {
8718 4 : if (GET_MODE (value) == VOIDmode && size > 8)
8719 0 : mode = Pmode;
8720 12 : else if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (value)))
8721 0 : mode = GET_MODE (value);
8722 : }
8723 : else
8724 877 : mode = GET_MODE (vec_value), value = vec_value;
8725 : }
8726 : else
8727 : {
8728 : /* Choose appropriate vector mode. */
8729 1773 : if (size >= 32)
8730 442 : switch (MOVE_MAX)
8731 : {
8732 0 : case 64:
8733 0 : if (size >= 64)
8734 : {
8735 : mode = V64QImode;
8736 : break;
8737 : }
8738 : /* FALLTHRU */
8739 0 : case 32:
8740 0 : mode = V32QImode;
8741 0 : break;
8742 : case 16:
8743 : mode = V16QImode;
8744 : break;
8745 : case 8:
8746 : mode = DImode;
8747 : break;
8748 0 : default:
8749 0 : gcc_unreachable ();
8750 : }
8751 1331 : else if (size >= 16)
8752 442 : mode = TARGET_SSE ? V16QImode : DImode;
8753 1773 : srcmem = change_address (srcmem, mode, srcptr);
8754 : }
8755 3531 : if (issetmem && vec_value && GET_MODE_SIZE (mode) > size)
8756 : {
8757 : /* For memset with vector and the size is smaller than the vector
8758 : size, first try the narrower vector, otherwise, use the
8759 : original value. */
8760 443 : machine_mode inner_mode = GET_MODE_INNER (mode);
8761 443 : unsigned int nunits = size / GET_MODE_SIZE (inner_mode);
8762 443 : if (nunits > 1)
8763 : {
8764 320 : mode = mode_for_vector (GET_MODE_INNER (mode),
8765 320 : nunits).require ();
8766 160 : value = gen_rtx_SUBREG (mode, value, 0);
8767 : }
8768 : else
8769 : {
8770 283 : scalar_int_mode smode
8771 283 : = smallest_int_mode_for_size (size * BITS_PER_UNIT).require ();
8772 849 : gcc_assert (GET_MODE_SIZE (GET_MODE (scalar_value))
8773 : >= GET_MODE_SIZE (smode));
8774 283 : mode = smode;
8775 283 : if (GET_MODE (scalar_value) == mode)
8776 : value = scalar_value;
8777 : else
8778 66 : value = gen_rtx_SUBREG (mode, scalar_value, 0);
8779 : }
8780 : }
8781 2654 : destmem = change_address (destmem, mode, destptr);
8782 5308 : modesize = GEN_INT (GET_MODE_SIZE (mode));
8783 5308 : gcc_assert (GET_MODE_SIZE (mode) <= size);
8784 11934 : for (n = 0; n * GET_MODE_SIZE (mode) < size; n++)
8785 : {
8786 3313 : if (issetmem)
8787 1098 : emit_move_insn (destmem, gen_lowpart (mode, value));
8788 : else
8789 : {
8790 2215 : emit_move_insn (destmem, srcmem);
8791 4430 : srcmem = offset_address (srcmem, modesize, GET_MODE_SIZE (mode));
8792 : }
8793 6626 : destmem = offset_address (destmem, modesize, GET_MODE_SIZE (mode));
8794 : }
8795 :
8796 2654 : destmem = offset_address (destmem, count, 1);
8797 5308 : destmem = offset_address (destmem, GEN_INT (-2 * size),
8798 2654 : GET_MODE_SIZE (mode));
8799 2654 : if (!issetmem)
8800 : {
8801 1773 : srcmem = offset_address (srcmem, count, 1);
8802 3546 : srcmem = offset_address (srcmem, GEN_INT (-2 * size),
8803 1773 : GET_MODE_SIZE (mode));
8804 : }
8805 11934 : for (n = 0; n * GET_MODE_SIZE (mode) < size; n++)
8806 : {
8807 3313 : if (issetmem)
8808 1098 : emit_move_insn (destmem, gen_lowpart (mode, value));
8809 : else
8810 : {
8811 2215 : emit_move_insn (destmem, srcmem);
8812 4430 : srcmem = offset_address (srcmem, modesize, GET_MODE_SIZE (mode));
8813 : }
8814 6626 : destmem = offset_address (destmem, modesize, GET_MODE_SIZE (mode));
8815 : }
8816 2654 : emit_jump_insn (gen_jump (done_label));
8817 2654 : emit_barrier ();
8818 :
8819 2654 : emit_label (label);
8820 2654 : LABEL_NUSES (label) = 1;
8821 2654 : }
8822 :
8823 : /* Handle small memcpy (up to SIZE that is supposed to be small power of 2.
8824 : and get ready for the main memcpy loop by copying initial DESIRED_ALIGN-ALIGN
8825 : bytes and last SIZE bytes adjusitng DESTPTR/SRCPTR/COUNT in a way we can
8826 : proceed with an loop copying SIZE bytes at once. Do moves in MODE.
8827 : DONE_LABEL is a label after the whole copying sequence. The label is created
8828 : on demand if *DONE_LABEL is NULL.
8829 : MIN_SIZE is minimal size of block copied. This value gets adjusted for new
8830 : bounds after the initial copies.
8831 :
8832 : DESTMEM/SRCMEM are memory expressions pointing to the copies block,
8833 : DESTPTR/SRCPTR are pointers to the block. DYNAMIC_CHECK indicate whether
8834 : we will dispatch to a library call for large blocks.
8835 :
8836 : In pseudocode we do:
8837 :
8838 : if (COUNT < SIZE)
8839 : {
8840 : Assume that SIZE is 4. Bigger sizes are handled analogously
8841 : if (COUNT & 4)
8842 : {
8843 : copy 4 bytes from SRCPTR to DESTPTR
8844 : copy 4 bytes from SRCPTR + COUNT - 4 to DESTPTR + COUNT - 4
8845 : goto done_label
8846 : }
8847 : if (!COUNT)
8848 : goto done_label;
8849 : copy 1 byte from SRCPTR to DESTPTR
8850 : if (COUNT & 2)
8851 : {
8852 : copy 2 bytes from SRCPTR to DESTPTR
8853 : copy 2 bytes from SRCPTR + COUNT - 2 to DESTPTR + COUNT - 2
8854 : }
8855 : }
8856 : else
8857 : {
8858 : copy at least DESIRED_ALIGN-ALIGN bytes from SRCPTR to DESTPTR
8859 : copy SIZE bytes from SRCPTR + COUNT - SIZE to DESTPTR + COUNT -SIZE
8860 :
8861 : OLD_DESPTR = DESTPTR;
8862 : Align DESTPTR up to DESIRED_ALIGN
8863 : SRCPTR += DESTPTR - OLD_DESTPTR
8864 : COUNT -= DEST_PTR - OLD_DESTPTR
8865 : if (DYNAMIC_CHECK)
8866 : Round COUNT down to multiple of SIZE
8867 : << optional caller supplied zero size guard is here >>
8868 : << optional caller supplied dynamic check is here >>
8869 : << caller supplied main copy loop is here >>
8870 : }
8871 : done_label:
8872 : */
8873 : static void
8874 4040 : expand_set_or_cpymem_prologue_epilogue_by_misaligned_moves (rtx destmem, rtx srcmem,
8875 : rtx *destptr, rtx *srcptr,
8876 : machine_mode mode,
8877 : rtx value, rtx vec_value,
8878 : rtx *count,
8879 : rtx_code_label **done_label,
8880 : int size,
8881 : int desired_align,
8882 : int align,
8883 : unsigned HOST_WIDE_INT *min_size,
8884 : bool dynamic_check,
8885 : bool issetmem)
8886 : {
8887 4040 : rtx_code_label *loop_label = NULL, *label;
8888 4040 : int n;
8889 4040 : rtx modesize;
8890 4040 : int prolog_size = 0;
8891 4040 : rtx mode_value;
8892 :
8893 : /* Chose proper value to copy. */
8894 4040 : if (issetmem && VECTOR_MODE_P (mode))
8895 : mode_value = vec_value;
8896 : else
8897 4040 : mode_value = value;
8898 8080 : gcc_assert (GET_MODE_SIZE (mode) <= size);
8899 :
8900 : /* See if block is big or small, handle small blocks. */
8901 4040 : if (!CONST_INT_P (*count) && *min_size < (unsigned HOST_WIDE_INT)size)
8902 : {
8903 668 : int size2 = size;
8904 668 : loop_label = gen_label_rtx ();
8905 :
8906 668 : if (!*done_label)
8907 668 : *done_label = gen_label_rtx ();
8908 :
8909 668 : emit_cmp_and_jump_insns (*count, GEN_INT (size2), GE, 0, GET_MODE (*count),
8910 : 1, loop_label);
8911 668 : size2 >>= 1;
8912 :
8913 : /* Handle sizes > 3. */
8914 3322 : for (;size2 > 2; size2 >>= 1)
8915 2654 : expand_small_cpymem_or_setmem (destmem, srcmem,
8916 : *destptr, *srcptr,
8917 : value, vec_value,
8918 : *count,
8919 : size2, *done_label, issetmem);
8920 : /* Nothing to copy? Jump to DONE_LABEL if so */
8921 668 : emit_cmp_and_jump_insns (*count, const0_rtx, EQ, 0, GET_MODE (*count),
8922 : 1, *done_label);
8923 :
8924 : /* Do a byte copy. */
8925 668 : destmem = change_address (destmem, QImode, *destptr);
8926 668 : if (issetmem)
8927 221 : emit_move_insn (destmem, gen_lowpart (QImode, value));
8928 : else
8929 : {
8930 447 : srcmem = change_address (srcmem, QImode, *srcptr);
8931 447 : emit_move_insn (destmem, srcmem);
8932 : }
8933 :
8934 : /* Handle sizes 2 and 3. */
8935 668 : label = ix86_expand_aligntest (*count, 2, false);
8936 668 : destmem = change_address (destmem, HImode, *destptr);
8937 668 : destmem = offset_address (destmem, *count, 1);
8938 668 : destmem = offset_address (destmem, GEN_INT (-2), 2);
8939 668 : if (issetmem)
8940 221 : emit_move_insn (destmem, gen_lowpart (HImode, value));
8941 : else
8942 : {
8943 447 : srcmem = change_address (srcmem, HImode, *srcptr);
8944 447 : srcmem = offset_address (srcmem, *count, 1);
8945 447 : srcmem = offset_address (srcmem, GEN_INT (-2), 2);
8946 447 : emit_move_insn (destmem, srcmem);
8947 : }
8948 :
8949 668 : emit_label (label);
8950 668 : LABEL_NUSES (label) = 1;
8951 668 : emit_jump_insn (gen_jump (*done_label));
8952 668 : emit_barrier ();
8953 : }
8954 : else
8955 3372 : gcc_assert (*min_size >= (unsigned HOST_WIDE_INT)size
8956 : || UINTVAL (*count) >= (unsigned HOST_WIDE_INT)size);
8957 :
8958 : /* Start memcpy for COUNT >= SIZE. */
8959 668 : if (loop_label)
8960 : {
8961 668 : emit_label (loop_label);
8962 668 : LABEL_NUSES (loop_label) = 1;
8963 : }
8964 :
8965 : /* Copy first desired_align bytes. */
8966 4040 : if (!issetmem)
8967 2102 : srcmem = change_address (srcmem, mode, *srcptr);
8968 4040 : destmem = change_address (destmem, mode, *destptr);
8969 4040 : modesize = GEN_INT (GET_MODE_SIZE (mode));
8970 8097 : for (n = 0; prolog_size < desired_align - align; n++)
8971 : {
8972 17 : if (issetmem)
8973 1 : emit_move_insn (destmem, mode_value);
8974 : else
8975 : {
8976 16 : emit_move_insn (destmem, srcmem);
8977 32 : srcmem = offset_address (srcmem, modesize, GET_MODE_SIZE (mode));
8978 : }
8979 34 : destmem = offset_address (destmem, modesize, GET_MODE_SIZE (mode));
8980 34 : prolog_size += GET_MODE_SIZE (mode);
8981 : }
8982 :
8983 :
8984 : /* Copy last SIZE bytes. */
8985 4040 : destmem = offset_address (destmem, *count, 1);
8986 4040 : destmem = offset_address (destmem,
8987 4040 : GEN_INT (-size - prolog_size),
8988 : 1);
8989 4040 : if (issetmem)
8990 1938 : emit_move_insn (destmem, mode_value);
8991 : else
8992 : {
8993 2102 : srcmem = offset_address (srcmem, *count, 1);
8994 2102 : srcmem = offset_address (srcmem,
8995 : GEN_INT (-size - prolog_size),
8996 : 1);
8997 2102 : emit_move_insn (destmem, srcmem);
8998 : }
8999 30574 : for (n = 1; n * GET_MODE_SIZE (mode) < size; n++)
9000 : {
9001 11247 : destmem = offset_address (destmem, modesize, 1);
9002 11247 : if (issetmem)
9003 5598 : emit_move_insn (destmem, mode_value);
9004 : else
9005 : {
9006 5649 : srcmem = offset_address (srcmem, modesize, 1);
9007 5649 : emit_move_insn (destmem, srcmem);
9008 : }
9009 : }
9010 :
9011 : /* Align destination. */
9012 4040 : if (desired_align > 1 && desired_align > align)
9013 : {
9014 17 : rtx saveddest = *destptr;
9015 :
9016 17 : gcc_assert (desired_align <= size);
9017 : /* Align destptr up, place it to new register. */
9018 17 : *destptr = expand_simple_binop (GET_MODE (*destptr), PLUS, *destptr,
9019 : GEN_INT (prolog_size),
9020 : NULL_RTX, 1, OPTAB_DIRECT);
9021 17 : if (REG_P (*destptr) && REG_P (saveddest) && REG_POINTER (saveddest))
9022 17 : REG_POINTER (*destptr) = 1;
9023 17 : *destptr = expand_simple_binop (GET_MODE (*destptr), AND, *destptr,
9024 17 : GEN_INT (-desired_align),
9025 : *destptr, 1, OPTAB_DIRECT);
9026 : /* See how many bytes we skipped. */
9027 17 : saveddest = expand_simple_binop (GET_MODE (*destptr), MINUS, saveddest,
9028 : *destptr,
9029 : NULL_RTX, 1, OPTAB_DIRECT);
9030 : /* Adjust srcptr and count. */
9031 17 : if (!issetmem)
9032 16 : *srcptr = expand_simple_binop (GET_MODE (*srcptr), MINUS, *srcptr,
9033 : saveddest, *srcptr, 1, OPTAB_DIRECT);
9034 17 : *count = expand_simple_binop (GET_MODE (*count), PLUS, *count,
9035 : saveddest, *count, 1, OPTAB_DIRECT);
9036 : /* We copied at most size + prolog_size. */
9037 17 : if (*min_size > (unsigned HOST_WIDE_INT)(size + prolog_size))
9038 16 : *min_size
9039 16 : = ROUND_DOWN (*min_size - size, (unsigned HOST_WIDE_INT)size);
9040 : else
9041 1 : *min_size = 0;
9042 :
9043 : /* Our loops always round down the block size, but for dispatch to
9044 : library we need precise value. */
9045 17 : if (dynamic_check)
9046 17 : *count = expand_simple_binop (GET_MODE (*count), AND, *count,
9047 : GEN_INT (-size), *count, 1, OPTAB_DIRECT);
9048 : }
9049 : else
9050 : {
9051 4023 : gcc_assert (prolog_size == 0);
9052 : /* Decrease count, so we won't end up copying last word twice. */
9053 4023 : if (!CONST_INT_P (*count))
9054 667 : *count = expand_simple_binop (GET_MODE (*count), PLUS, *count,
9055 : constm1_rtx, *count, 1, OPTAB_DIRECT);
9056 : else
9057 3356 : *count = GEN_INT (ROUND_DOWN (UINTVAL (*count) - 1,
9058 : (unsigned HOST_WIDE_INT)size));
9059 4023 : if (*min_size)
9060 3797 : *min_size = ROUND_DOWN (*min_size - 1, (unsigned HOST_WIDE_INT)size);
9061 : }
9062 4040 : }
9063 :
9064 :
9065 : /* This function is like the previous one, except here we know how many bytes
9066 : need to be copied. That allows us to update alignment not only of DST, which
9067 : is returned, but also of SRC, which is passed as a pointer for that
9068 : reason. */
9069 : static rtx
9070 0 : expand_set_or_cpymem_constant_prologue (rtx dst, rtx *srcp, rtx destreg,
9071 : rtx srcreg, rtx value, rtx vec_value,
9072 : int desired_align, int align_bytes,
9073 : bool issetmem)
9074 : {
9075 0 : rtx src = NULL;
9076 0 : rtx orig_dst = dst;
9077 0 : rtx orig_src = NULL;
9078 0 : int piece_size = 1;
9079 0 : int copied_bytes = 0;
9080 :
9081 0 : if (!issetmem)
9082 : {
9083 0 : gcc_assert (srcp != NULL);
9084 0 : src = *srcp;
9085 0 : orig_src = src;
9086 : }
9087 :
9088 0 : for (piece_size = 1;
9089 0 : piece_size <= desired_align && copied_bytes < align_bytes;
9090 0 : piece_size <<= 1)
9091 : {
9092 0 : if (align_bytes & piece_size)
9093 : {
9094 0 : if (issetmem)
9095 : {
9096 0 : if (vec_value && piece_size > GET_MODE_SIZE (GET_MODE (value)))
9097 0 : dst = emit_memset (dst, destreg, vec_value, piece_size);
9098 : else
9099 0 : dst = emit_memset (dst, destreg, value, piece_size);
9100 : }
9101 : else
9102 0 : dst = emit_memmov (dst, &src, destreg, srcreg, piece_size);
9103 0 : copied_bytes += piece_size;
9104 : }
9105 : }
9106 0 : if (MEM_ALIGN (dst) < (unsigned int) desired_align * BITS_PER_UNIT)
9107 0 : set_mem_align (dst, desired_align * BITS_PER_UNIT);
9108 0 : if (MEM_SIZE_KNOWN_P (orig_dst))
9109 0 : set_mem_size (dst, MEM_SIZE (orig_dst) - align_bytes);
9110 :
9111 0 : if (!issetmem)
9112 : {
9113 0 : int src_align_bytes = get_mem_align_offset (src, desired_align
9114 : * BITS_PER_UNIT);
9115 0 : if (src_align_bytes >= 0)
9116 0 : src_align_bytes = desired_align - src_align_bytes;
9117 0 : if (src_align_bytes >= 0)
9118 : {
9119 : unsigned int src_align;
9120 0 : for (src_align = desired_align; src_align >= 2; src_align >>= 1)
9121 : {
9122 0 : if ((src_align_bytes & (src_align - 1))
9123 0 : == (align_bytes & (src_align - 1)))
9124 : break;
9125 : }
9126 0 : if (src_align > (unsigned int) desired_align)
9127 : src_align = desired_align;
9128 0 : if (MEM_ALIGN (src) < src_align * BITS_PER_UNIT)
9129 0 : set_mem_align (src, src_align * BITS_PER_UNIT);
9130 : }
9131 0 : if (MEM_SIZE_KNOWN_P (orig_src))
9132 0 : set_mem_size (src, MEM_SIZE (orig_src) - align_bytes);
9133 0 : *srcp = src;
9134 : }
9135 :
9136 0 : return dst;
9137 : }
9138 :
9139 : /* Return true if ALG can be used in current context.
9140 : Assume we expand memset if MEMSET is true. */
9141 : static bool
9142 1440730 : alg_usable_p (enum stringop_alg alg, bool memset,
9143 : addr_space_t dst_as, addr_space_t src_as)
9144 : {
9145 1440730 : if (alg == no_stringop)
9146 : return false;
9147 : /* It is not possible to use a library call if we have non-default
9148 : address space. We can do better than the generic byte-at-a-time
9149 : loop, used as a fallback. */
9150 1440730 : if (alg == libcall &&
9151 826410 : !(ADDR_SPACE_GENERIC_P (dst_as) && ADDR_SPACE_GENERIC_P (src_as)))
9152 : return false;
9153 1440716 : if (alg == vector_loop)
9154 617225 : return TARGET_SSE || TARGET_AVX;
9155 : /* Algorithms using the rep prefix want at least edi and ecx;
9156 : additionally, memset wants eax and memcpy wants esi. Don't
9157 : consider such algorithms if the user has appropriated those
9158 : registers for their own purposes, or if we have the destination
9159 : in the non-default address space, since string insns cannot
9160 : override the destination segment. */
9161 1132063 : if (alg == rep_prefix_1_byte
9162 : || alg == rep_prefix_4_byte
9163 1132063 : || alg == rep_prefix_8_byte)
9164 : {
9165 37709 : if (fixed_regs[CX_REG]
9166 37705 : || fixed_regs[DI_REG]
9167 37701 : || (memset ? fixed_regs[AX_REG] : fixed_regs[SI_REG])
9168 37697 : || !ADDR_SPACE_GENERIC_P (dst_as)
9169 75406 : || !(ADDR_SPACE_GENERIC_P (src_as) || Pmode == word_mode))
9170 12 : return false;
9171 : }
9172 : return true;
9173 : }
9174 :
9175 : /* Given COUNT and EXPECTED_SIZE, decide on codegen of string operation. */
9176 : static enum stringop_alg
9177 286628 : decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size,
9178 : unsigned HOST_WIDE_INT min_size, unsigned HOST_WIDE_INT max_size,
9179 : bool memset, bool zero_memset, addr_space_t dst_as,
9180 : addr_space_t src_as, int *dynamic_check, bool *noalign, bool recur)
9181 : {
9182 286628 : const struct stringop_algs *algs;
9183 286628 : bool optimize_for_speed;
9184 286628 : int max = 0;
9185 286628 : const struct processor_costs *cost;
9186 286628 : int i;
9187 286628 : bool any_alg_usable_p = false;
9188 :
9189 286628 : *noalign = false;
9190 286628 : *dynamic_check = -1;
9191 :
9192 : /* Even if the string operation call is cold, we still might spend a lot
9193 : of time processing large blocks. */
9194 286628 : if (optimize_function_for_size_p (cfun)
9195 286628 : || (optimize_insn_for_size_p ()
9196 12317 : && (max_size < 256
9197 4054 : || (expected_size != -1 && expected_size < 256))))
9198 : optimize_for_speed = false;
9199 : else
9200 267925 : optimize_for_speed = true;
9201 :
9202 267925 : cost = optimize_for_speed ? ix86_cost : &ix86_size_cost;
9203 286628 : if (memset)
9204 87837 : algs = &cost->memset[TARGET_64BIT != 0];
9205 : else
9206 207676 : algs = &cost->memcpy[TARGET_64BIT != 0];
9207 :
9208 : /* See maximal size for user defined algorithm. */
9209 1433140 : for (i = 0; i < MAX_STRINGOP_ALGS; i++)
9210 : {
9211 1146512 : enum stringop_alg candidate = algs->size[i].alg;
9212 1146512 : bool usable = alg_usable_p (candidate, memset, dst_as, src_as);
9213 1146512 : any_alg_usable_p |= usable;
9214 :
9215 1146512 : if (candidate != libcall && candidate && usable)
9216 554440 : max = algs->size[i].max;
9217 : }
9218 :
9219 : /* If expected size is not known but max size is small enough
9220 : so inline version is a win, set expected size into
9221 : the range. */
9222 286628 : if (((max > 1 && (unsigned HOST_WIDE_INT) max >= max_size) || max == -1)
9223 37923 : && expected_size == -1)
9224 15502 : expected_size = min_size / 2 + max_size / 2;
9225 :
9226 : /* If user specified the algorithm, honor it if possible. */
9227 286628 : if (ix86_stringop_alg != no_stringop
9228 286628 : && alg_usable_p (ix86_stringop_alg, memset, dst_as, src_as))
9229 : return ix86_stringop_alg;
9230 : /* rep; movq or rep; movl is the smallest variant. */
9231 286490 : else if (!optimize_for_speed)
9232 : {
9233 18620 : *noalign = true;
9234 18620 : if (!count || (count & 3) || (memset && !zero_memset))
9235 5766 : return alg_usable_p (rep_prefix_1_byte, memset, dst_as, src_as)
9236 5766 : ? rep_prefix_1_byte : loop_1_byte;
9237 : else
9238 12854 : return alg_usable_p (rep_prefix_4_byte, memset, dst_as, src_as)
9239 12854 : ? rep_prefix_4_byte : loop;
9240 : }
9241 : /* Very tiny blocks are best handled via the loop, REP is expensive to
9242 : setup. */
9243 267870 : else if (expected_size != -1 && expected_size < 4)
9244 : return loop_1_byte;
9245 266342 : else if (expected_size != -1)
9246 : {
9247 : enum stringop_alg alg = libcall;
9248 : bool alg_noalign = false;
9249 342272 : for (i = 0; i < MAX_STRINGOP_ALGS; i++)
9250 : {
9251 : /* We get here if the algorithms that were not libcall-based
9252 : were rep-prefix based and we are unable to use rep prefixes
9253 : based on global register usage. Break out of the loop and
9254 : use the heuristic below. */
9255 336535 : if (algs->size[i].max == 0)
9256 : break;
9257 336535 : if (algs->size[i].max >= expected_size || algs->size[i].max == -1)
9258 : {
9259 132562 : enum stringop_alg candidate = algs->size[i].alg;
9260 :
9261 132562 : if (candidate != libcall
9262 132562 : && alg_usable_p (candidate, memset, dst_as, src_as))
9263 : {
9264 24814 : alg = candidate;
9265 24814 : alg_noalign = algs->size[i].noalign;
9266 : }
9267 : /* Honor TARGET_INLINE_ALL_STRINGOPS by picking
9268 : last non-libcall inline algorithm. */
9269 132562 : if (TARGET_INLINE_ALL_STRINGOPS)
9270 : {
9271 : /* When the current size is best to be copied by a libcall,
9272 : but we are still forced to inline, run the heuristic below
9273 : that will pick code for medium sized blocks. */
9274 20038 : if (alg != libcall)
9275 : {
9276 8555 : *noalign = alg_noalign;
9277 8555 : return alg;
9278 : }
9279 11483 : else if (!any_alg_usable_p)
9280 : break;
9281 : }
9282 112524 : else if (alg_usable_p (candidate, memset, dst_as, src_as)
9283 112524 : && !(TARGET_PREFER_KNOWN_REP_MOVSB_STOSB
9284 34 : && candidate == rep_prefix_1_byte
9285 : /* NB: If min_size != max_size, size is
9286 : unknown. */
9287 34 : && min_size != max_size))
9288 : {
9289 112499 : *noalign = algs->size[i].noalign;
9290 112499 : return candidate;
9291 : }
9292 : }
9293 : }
9294 : }
9295 : /* When asked to inline the call anyway, try to pick meaningful choice.
9296 : We look for maximal size of block that is faster to copy by hand and
9297 : take blocks of at most of that size guessing that average size will
9298 : be roughly half of the block.
9299 :
9300 : If this turns out to be bad, we might simply specify the preferred
9301 : choice in ix86_costs. */
9302 138099 : if ((TARGET_INLINE_ALL_STRINGOPS || TARGET_INLINE_STRINGOPS_DYNAMICALLY)
9303 145294 : && (algs->unknown_size == libcall
9304 0 : || !alg_usable_p (algs->unknown_size, memset, dst_as, src_as)))
9305 : {
9306 7195 : enum stringop_alg alg;
9307 7195 : HOST_WIDE_INT new_expected_size = (max > 0 ? max : 4096) / 2;
9308 :
9309 : /* If there aren't any usable algorithms or if recursing already,
9310 : then recursing on smaller sizes or same size isn't going to
9311 : find anything. Just return the simple byte-at-a-time copy loop. */
9312 7195 : if (!any_alg_usable_p || recur)
9313 : {
9314 : /* Pick something reasonable. */
9315 0 : if (TARGET_INLINE_STRINGOPS_DYNAMICALLY && !recur)
9316 0 : *dynamic_check = 128;
9317 0 : return loop_1_byte;
9318 : }
9319 7195 : alg = decide_alg (count, new_expected_size, min_size, max_size,
9320 : memset, zero_memset, dst_as, src_as,
9321 : dynamic_check, noalign, true);
9322 7195 : gcc_assert (*dynamic_check == -1);
9323 7195 : if (TARGET_INLINE_STRINGOPS_DYNAMICALLY)
9324 10 : *dynamic_check = max;
9325 : else
9326 7185 : gcc_assert (alg != libcall);
9327 7195 : return alg;
9328 : }
9329 :
9330 : /* Try to use some reasonable fallback algorithm. Note that for
9331 : non-default address spaces we default to a loop instead of
9332 : a libcall. */
9333 :
9334 138093 : bool have_as = !(ADDR_SPACE_GENERIC_P (dst_as)
9335 : && ADDR_SPACE_GENERIC_P (src_as));
9336 :
9337 138093 : return (alg_usable_p (algs->unknown_size, memset, dst_as, src_as)
9338 138093 : ? algs->unknown_size : have_as ? loop : libcall);
9339 : }
9340 :
9341 : /* Decide on alignment. We know that the operand is already aligned to ALIGN
9342 : (ALIGN can be based on profile feedback and thus it is not 100% guaranteed). */
9343 : static int
9344 26819 : decide_alignment (int align,
9345 : enum stringop_alg alg,
9346 : int expected_size,
9347 : machine_mode move_mode)
9348 : {
9349 26819 : int desired_align = 0;
9350 :
9351 26819 : gcc_assert (alg != no_stringop);
9352 :
9353 26819 : if (alg == libcall)
9354 : return 0;
9355 26819 : if (move_mode == VOIDmode)
9356 : return 0;
9357 :
9358 26819 : desired_align = GET_MODE_SIZE (move_mode);
9359 : /* PentiumPro has special logic triggering for 8 byte aligned blocks.
9360 : copying whole cacheline at once. */
9361 26819 : if (TARGET_CPU_P (PENTIUMPRO)
9362 0 : && (alg == rep_prefix_4_byte || alg == rep_prefix_1_byte))
9363 26819 : desired_align = 8;
9364 :
9365 26819 : if (optimize_size)
9366 9884 : desired_align = 1;
9367 26819 : if (desired_align < align)
9368 : desired_align = align;
9369 26819 : if (expected_size != -1 && expected_size < 4)
9370 1 : desired_align = align;
9371 :
9372 : return desired_align;
9373 : }
9374 :
9375 :
9376 : /* Helper function for memcpy. For QImode value 0xXY produce
9377 : 0xXYXYXYXY of wide specified by MODE. This is essentially
9378 : a * 0x10101010, but we can do slightly better than
9379 : synth_mult by unwinding the sequence by hand on CPUs with
9380 : slow multiply. */
9381 : static rtx
9382 18580 : promote_duplicated_reg (machine_mode mode, rtx val)
9383 : {
9384 18580 : if (val == const0_rtx)
9385 16101 : return copy_to_mode_reg (mode, CONST0_RTX (mode));
9386 :
9387 2479 : machine_mode valmode = GET_MODE (val);
9388 2479 : if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT)
9389 : {
9390 : /* Duplicate the scalar value for integer vector. */
9391 1864 : gcc_assert ((val == const0_rtx || val == constm1_rtx)
9392 : || GET_MODE_INNER (mode) == valmode);
9393 936 : rtx dup = gen_reg_rtx (mode);
9394 936 : bool ok = ix86_expand_vector_init_duplicate (false, mode, dup,
9395 : val);
9396 936 : gcc_assert (ok);
9397 : return dup;
9398 : }
9399 :
9400 1543 : rtx tmp;
9401 1543 : int nops = mode == DImode ? 3 : 2;
9402 :
9403 40 : gcc_assert (mode == SImode || mode == DImode);
9404 1543 : if (CONST_INT_P (val))
9405 : {
9406 1232 : HOST_WIDE_INT v = INTVAL (val) & 255;
9407 :
9408 1232 : v |= v << 8;
9409 1232 : v |= v << 16;
9410 1232 : if (mode == DImode)
9411 1204 : v |= (v << 16) << 16;
9412 1232 : return copy_to_mode_reg (mode, gen_int_mode (v, mode));
9413 : }
9414 :
9415 311 : if (valmode == VOIDmode)
9416 : valmode = QImode;
9417 311 : if (valmode != QImode)
9418 0 : val = gen_lowpart (QImode, val);
9419 311 : if (mode == QImode)
9420 : return val;
9421 311 : if (!TARGET_PARTIAL_REG_STALL)
9422 311 : nops--;
9423 311 : if (ix86_cost->mult_init[mode == DImode ? 3 : 2]
9424 311 : + ix86_cost->mult_bit * (mode == DImode ? 8 : 4)
9425 311 : <= (ix86_cost->shift_const + ix86_cost->add) * nops
9426 311 : + (COSTS_N_INSNS (TARGET_PARTIAL_REG_STALL == 0)))
9427 : {
9428 311 : rtx reg = convert_modes (mode, QImode, val, true);
9429 311 : tmp = promote_duplicated_reg (mode, const1_rtx);
9430 311 : return expand_simple_binop (mode, MULT, reg, tmp, NULL, 1,
9431 311 : OPTAB_DIRECT);
9432 : }
9433 : else
9434 : {
9435 0 : rtx reg = convert_modes (mode, QImode, val, true);
9436 :
9437 0 : if (!TARGET_PARTIAL_REG_STALL)
9438 0 : emit_insn (gen_insv_1 (mode, reg, reg));
9439 : else
9440 : {
9441 0 : tmp = expand_simple_binop (mode, ASHIFT, reg, GEN_INT (8),
9442 : NULL, 1, OPTAB_DIRECT);
9443 0 : reg = expand_simple_binop (mode, IOR, reg, tmp, reg, 1,
9444 : OPTAB_DIRECT);
9445 : }
9446 0 : tmp = expand_simple_binop (mode, ASHIFT, reg, GEN_INT (16),
9447 : NULL, 1, OPTAB_DIRECT);
9448 0 : reg = expand_simple_binop (mode, IOR, reg, tmp, reg, 1, OPTAB_DIRECT);
9449 0 : if (mode == SImode)
9450 : return reg;
9451 0 : tmp = expand_simple_binop (mode, ASHIFT, reg, GEN_INT (32),
9452 : NULL, 1, OPTAB_DIRECT);
9453 0 : reg = expand_simple_binop (mode, IOR, reg, tmp, reg, 1, OPTAB_DIRECT);
9454 0 : return reg;
9455 : }
9456 : }
9457 :
9458 : /* Duplicate value VAL using promote_duplicated_reg into maximal size that will
9459 : be needed by main loop copying SIZE_NEEDED chunks and prologue getting
9460 : alignment from ALIGN to DESIRED_ALIGN. */
9461 : static rtx
9462 13271 : promote_duplicated_reg_to_size (rtx val, int size_needed, int desired_align,
9463 : int align)
9464 : {
9465 13271 : rtx promoted_val;
9466 :
9467 13271 : if (TARGET_64BIT
9468 11794 : && (size_needed > 4 || (desired_align > align && desired_align > 4)))
9469 3940 : promoted_val = promote_duplicated_reg (DImode, val);
9470 9331 : else if (size_needed > 2 || (desired_align > align && desired_align > 2))
9471 7995 : promoted_val = promote_duplicated_reg (SImode, val);
9472 1336 : else if (size_needed > 1 || (desired_align > align && desired_align > 1))
9473 0 : promoted_val = promote_duplicated_reg (HImode, val);
9474 : else
9475 : promoted_val = val;
9476 :
9477 13271 : return promoted_val;
9478 : }
9479 :
9480 : /* Copy the address to a Pmode register. This is used for x32 to
9481 : truncate DImode TLS address to a SImode register. */
9482 :
9483 : static rtx
9484 65010 : ix86_copy_addr_to_reg (rtx addr)
9485 : {
9486 65010 : rtx reg;
9487 69548 : if (GET_MODE (addr) == Pmode || GET_MODE (addr) == VOIDmode)
9488 : {
9489 65010 : reg = copy_addr_to_reg (addr);
9490 65010 : REG_POINTER (reg) = 1;
9491 65010 : return reg;
9492 : }
9493 : else
9494 : {
9495 0 : gcc_assert (GET_MODE (addr) == DImode && Pmode == SImode);
9496 0 : reg = copy_to_mode_reg (DImode, addr);
9497 0 : REG_POINTER (reg) = 1;
9498 0 : return gen_rtx_SUBREG (SImode, reg, 0);
9499 : }
9500 : }
9501 :
9502 : /* Expand string move (memcpy) ot store (memset) operation. Use i386 string
9503 : operations when profitable. The code depends upon architecture, block size
9504 : and alignment, but always has one of the following overall structures:
9505 :
9506 : Aligned move sequence:
9507 :
9508 : 1) Prologue guard: Conditional that jumps up to epilogues for small
9509 : blocks that can be handled by epilogue alone. This is faster
9510 : but also needed for correctness, since prologue assume the block
9511 : is larger than the desired alignment.
9512 :
9513 : Optional dynamic check for size and libcall for large
9514 : blocks is emitted here too, with -minline-stringops-dynamically.
9515 :
9516 : 2) Prologue: copy first few bytes in order to get destination
9517 : aligned to DESIRED_ALIGN. It is emitted only when ALIGN is less
9518 : than DESIRED_ALIGN and up to DESIRED_ALIGN - ALIGN bytes can be
9519 : copied. We emit either a jump tree on power of two sized
9520 : blocks, or a byte loop.
9521 :
9522 : 3) Main body: the copying loop itself, copying in SIZE_NEEDED chunks
9523 : with specified algorithm.
9524 :
9525 : 4) Epilogue: code copying tail of the block that is too small to be
9526 : handled by main body (or up to size guarded by prologue guard).
9527 :
9528 : Misaligned move sequence
9529 :
9530 : 1) missaligned move prologue/epilogue containing:
9531 : a) Prologue handling small memory blocks and jumping to done_label
9532 : (skipped if blocks are known to be large enough)
9533 : b) Single move copying first DESIRED_ALIGN-ALIGN bytes if alignment is
9534 : needed by single possibly misaligned move
9535 : (skipped if alignment is not needed)
9536 : c) Copy of last SIZE_NEEDED bytes by possibly misaligned moves
9537 :
9538 : 2) Zero size guard dispatching to done_label, if needed
9539 :
9540 : 3) dispatch to library call, if needed,
9541 :
9542 : 3) Main body: the copying loop itself, copying in SIZE_NEEDED chunks
9543 : with specified algorithm. */
9544 : bool
9545 152281 : ix86_expand_set_or_cpymem (rtx dst, rtx src, rtx count_exp, rtx val_exp,
9546 : rtx align_exp, rtx expected_align_exp,
9547 : rtx expected_size_exp, rtx min_size_exp,
9548 : rtx max_size_exp, rtx probable_max_size_exp,
9549 : bool issetmem)
9550 : {
9551 152281 : if (TARGET_MISALIGNED_MOVE_STRING_PRO_EPILOGUES)
9552 : {
9553 : /* Expand bounded memset and memcpy as memmove if misaligned moves
9554 : are preferred. Since
9555 :
9556 : commit b41f96465190751561f6909e858604ceab00595b
9557 : Author: H.J. Lu <hjl.tools@gmail.com>
9558 : Date: Mon Oct 20 16:14:34 2025 +0800
9559 :
9560 : x86-64: Inline memmove with overlapping unaligned loads and stores.
9561 :
9562 : inlines memmove with overlapping unaligned and stores, which
9563 : reduces the numbers of branches and memory moves, comparing
9564 : against the regular memset and memcpy inlining. */
9565 152263 : rtx operands[9];
9566 152263 : operands[0] = dst;
9567 152263 : operands[1] = issetmem ? val_exp : src;
9568 152263 : operands[2] = count_exp;
9569 152263 : operands[3] = align_exp;
9570 152263 : operands[4] = expected_align_exp;
9571 152263 : operands[5] = expected_size_exp;
9572 152263 : operands[6] = min_size_exp;
9573 152263 : operands[7] = max_size_exp;
9574 152263 : operands[8] = probable_max_size_exp;
9575 152263 : if (ix86_expand_set_or_movmem (operands, !issetmem, issetmem))
9576 8644 : return true;
9577 : }
9578 :
9579 143637 : rtx destreg;
9580 143637 : rtx srcreg = NULL;
9581 143637 : rtx_code_label *label = NULL;
9582 143637 : rtx tmp;
9583 143637 : rtx_code_label *jump_around_label = NULL;
9584 143637 : HOST_WIDE_INT align = 1;
9585 143637 : unsigned HOST_WIDE_INT count = 0;
9586 143637 : HOST_WIDE_INT expected_size = -1;
9587 143637 : int size_needed = 0, epilogue_size_needed;
9588 143637 : int desired_align = 0, align_bytes = 0;
9589 143637 : enum stringop_alg alg;
9590 143637 : rtx promoted_val = NULL;
9591 143637 : rtx vec_promoted_val = NULL;
9592 143637 : bool force_loopy_epilogue = false;
9593 143637 : int dynamic_check;
9594 143637 : bool need_zero_guard = false;
9595 143637 : bool noalign;
9596 143637 : machine_mode move_mode = VOIDmode;
9597 143637 : int unroll_factor = 1;
9598 : /* TODO: Once value ranges are available, fill in proper data. */
9599 143637 : unsigned HOST_WIDE_INT min_size = HOST_WIDE_INT_0U;
9600 143637 : unsigned HOST_WIDE_INT max_size = HOST_WIDE_INT_M1U;
9601 143637 : unsigned HOST_WIDE_INT probable_max_size = HOST_WIDE_INT_M1U;
9602 143637 : bool misaligned_prologue_used = false;
9603 143637 : addr_space_t dst_as, src_as = ADDR_SPACE_GENERIC;
9604 :
9605 143637 : if (CONST_INT_P (align_exp))
9606 143637 : align = INTVAL (align_exp);
9607 : /* i386 can do misaligned access on reasonably increased cost. */
9608 143637 : if (CONST_INT_P (expected_align_exp)
9609 143637 : && INTVAL (expected_align_exp) > align)
9610 : align = INTVAL (expected_align_exp);
9611 : /* ALIGN is the minimum of destination and source alignment, but we care here
9612 : just about destination alignment. */
9613 137508 : else if (!issetmem
9614 228601 : && MEM_ALIGN (dst) > (unsigned HOST_WIDE_INT) align * BITS_PER_UNIT)
9615 3269 : align = MEM_ALIGN (dst) / BITS_PER_UNIT;
9616 :
9617 143637 : if (CONST_INT_P (count_exp))
9618 : {
9619 70472 : min_size = max_size = probable_max_size = count = expected_size
9620 70472 : = INTVAL (count_exp);
9621 : /* When COUNT is 0, there is nothing to do. */
9622 70472 : if (!count)
9623 : return true;
9624 : }
9625 : else
9626 : {
9627 73165 : if (min_size_exp)
9628 73165 : min_size = INTVAL (min_size_exp);
9629 73165 : if (max_size_exp)
9630 58563 : max_size = INTVAL (max_size_exp);
9631 73165 : if (probable_max_size_exp)
9632 60055 : probable_max_size = INTVAL (probable_max_size_exp);
9633 73165 : if (CONST_INT_P (expected_size_exp))
9634 73165 : expected_size = INTVAL (expected_size_exp);
9635 : }
9636 :
9637 : /* Make sure we don't need to care about overflow later on. */
9638 143637 : if (count > (HOST_WIDE_INT_1U << 30))
9639 : return false;
9640 :
9641 143463 : dst_as = MEM_ADDR_SPACE (dst);
9642 143463 : if (!issetmem)
9643 97109 : src_as = MEM_ADDR_SPACE (src);
9644 :
9645 : /* Step 0: Decide on preferred algorithm, desired alignment and
9646 : size of chunks to be copied by main loop. */
9647 143463 : alg = decide_alg (count, expected_size, min_size, probable_max_size,
9648 46354 : issetmem, issetmem && val_exp == const0_rtx,
9649 : dst_as, src_as, &dynamic_check, &noalign, false);
9650 :
9651 143463 : if (dump_file)
9652 7 : fprintf (dump_file, "Selected stringop expansion strategy: %s\n",
9653 7 : stringop_alg_names[alg]);
9654 :
9655 143463 : if (alg == libcall)
9656 : return false;
9657 26819 : gcc_assert (alg != no_stringop);
9658 :
9659 26819 : if (!count)
9660 5653 : count_exp = copy_to_mode_reg (GET_MODE (count_exp), count_exp);
9661 26819 : destreg = ix86_copy_addr_to_reg (XEXP (dst, 0));
9662 26819 : if (!issetmem)
9663 13548 : srcreg = ix86_copy_addr_to_reg (XEXP (src, 0));
9664 :
9665 26819 : bool aligned_dstmem = false;
9666 26819 : unsigned int nunits = issetmem ? STORE_MAX_PIECES : MOVE_MAX;
9667 26819 : bool single_insn_p = count && count <= nunits;
9668 26819 : if (single_insn_p)
9669 : {
9670 : /* If it can be done with a single instruction, use vector
9671 : instruction and don't align destination. */
9672 7 : alg = vector_loop;
9673 7 : noalign = true;
9674 7 : dynamic_check = -1;
9675 : }
9676 :
9677 26819 : unroll_factor = 1;
9678 26819 : move_mode = word_mode;
9679 26819 : switch (alg)
9680 : {
9681 0 : case libcall:
9682 0 : case no_stringop:
9683 0 : case last_alg:
9684 0 : gcc_unreachable ();
9685 173 : case loop_1_byte:
9686 173 : need_zero_guard = true;
9687 173 : move_mode = QImode;
9688 173 : break;
9689 46 : case loop:
9690 46 : need_zero_guard = true;
9691 46 : break;
9692 19 : case unrolled_loop:
9693 19 : need_zero_guard = true;
9694 19 : unroll_factor = (TARGET_64BIT ? 4 : 2);
9695 : break;
9696 7936 : case vector_loop:
9697 7936 : need_zero_guard = true;
9698 7936 : unroll_factor = 4;
9699 : /* Get the vector mode to move STORE_MAX_PIECES/MOVE_MAX bytes. */
9700 7936 : nunits /= GET_MODE_SIZE (word_mode);
9701 7936 : if (nunits > 1)
9702 : {
9703 7932 : move_mode = mode_for_vector (word_mode, nunits).require ();
9704 7932 : gcc_assert (optab_handler (mov_optab, move_mode)
9705 : != CODE_FOR_nothing);
9706 : }
9707 : break;
9708 25 : case rep_prefix_8_byte:
9709 25 : move_mode = DImode;
9710 25 : break;
9711 12850 : case rep_prefix_4_byte:
9712 12850 : move_mode = SImode;
9713 12850 : break;
9714 5770 : case rep_prefix_1_byte:
9715 5770 : move_mode = QImode;
9716 5770 : break;
9717 : }
9718 26819 : size_needed = GET_MODE_SIZE (move_mode) * unroll_factor;
9719 26819 : epilogue_size_needed = size_needed;
9720 :
9721 : /* If we are going to call any library calls conditionally, make sure any
9722 : pending stack adjustment happen before the first conditional branch,
9723 : otherwise they will be emitted before the library call only and won't
9724 : happen from the other branches. */
9725 26819 : if (dynamic_check != -1)
9726 2 : do_pending_stack_adjust ();
9727 :
9728 26819 : desired_align = decide_alignment (align, alg, expected_size, move_mode);
9729 26819 : if (!TARGET_ALIGN_STRINGOPS || noalign)
9730 26564 : align = desired_align;
9731 :
9732 : /* Step 1: Prologue guard. */
9733 :
9734 : /* Alignment code needs count to be in register. */
9735 26819 : if (CONST_INT_P (count_exp) && desired_align > align)
9736 : {
9737 22 : if (INTVAL (count_exp) > desired_align
9738 22 : && INTVAL (count_exp) > size_needed)
9739 : {
9740 22 : align_bytes
9741 22 : = get_mem_align_offset (dst, desired_align * BITS_PER_UNIT);
9742 22 : if (align_bytes <= 0)
9743 : align_bytes = 0;
9744 : else
9745 0 : align_bytes = desired_align - align_bytes;
9746 : }
9747 0 : if (align_bytes == 0)
9748 44 : count_exp = force_reg (counter_mode (count_exp), count_exp);
9749 : }
9750 26819 : gcc_assert (desired_align >= 1 && align >= 1);
9751 :
9752 26819 : if (!single_insn_p)
9753 : {
9754 : /* Misaligned move sequences handle both prologue and epilogue
9755 : at once. Default code generation results in a smaller code
9756 : for large alignments and also avoids redundant job when sizes
9757 : are known precisely. */
9758 26812 : misaligned_prologue_used
9759 53624 : = (TARGET_MISALIGNED_MOVE_STRING_PRO_EPILOGUES
9760 26806 : && MAX (desired_align, epilogue_size_needed) <= 32
9761 18550 : && desired_align <= epilogue_size_needed
9762 31404 : && ((desired_align > align && !align_bytes)
9763 4575 : || (!count && epilogue_size_needed > 1)));
9764 :
9765 : /* Destination is aligned after the misaligned prologue. */
9766 26812 : aligned_dstmem = misaligned_prologue_used;
9767 :
9768 26812 : if (noalign && !misaligned_prologue_used)
9769 : {
9770 : /* Also use misaligned prologue if alignment isn't needed and
9771 : destination isn't aligned. Since alignment isn't needed,
9772 : the destination after prologue won't be aligned. */
9773 26557 : aligned_dstmem = (GET_MODE_ALIGNMENT (move_mode)
9774 26557 : <= MEM_ALIGN (dst));
9775 26557 : if (!aligned_dstmem)
9776 4023 : misaligned_prologue_used = true;
9777 : }
9778 : }
9779 :
9780 : /* Do the cheap promotion to allow better CSE across the
9781 : main loop and epilogue (ie one load of the big constant in the
9782 : front of all code.
9783 : For now the misaligned move sequences do not have fast path
9784 : without broadcasting. */
9785 26819 : if (issetmem
9786 13271 : && (alg == vector_loop
9787 7962 : || CONST_INT_P (val_exp)
9788 49 : || misaligned_prologue_used))
9789 : {
9790 7914 : if (alg == vector_loop)
9791 : {
9792 5309 : promoted_val = promote_duplicated_reg_to_size (val_exp,
9793 10618 : GET_MODE_SIZE (word_mode),
9794 : desired_align, align);
9795 : /* Duplicate the promoted scalar value if not 0 nor -1. */
9796 5309 : vec_promoted_val
9797 5309 : = promote_duplicated_reg (move_mode,
9798 5309 : (val_exp == const0_rtx
9799 568 : || val_exp == constm1_rtx)
9800 : ? val_exp : promoted_val);
9801 : }
9802 : else
9803 : {
9804 7914 : promoted_val = promote_duplicated_reg_to_size (val_exp, size_needed,
9805 : desired_align, align);
9806 : }
9807 : }
9808 : /* Misaligned move sequences handles both prologues and epilogues at once.
9809 : Default code generation results in smaller code for large alignments and
9810 : also avoids redundant job when sizes are known precisely. */
9811 26771 : if (misaligned_prologue_used)
9812 : {
9813 : /* Misaligned move prologue handled small blocks by itself. */
9814 4040 : expand_set_or_cpymem_prologue_epilogue_by_misaligned_moves
9815 4040 : (dst, src, &destreg, &srcreg,
9816 : move_mode, promoted_val, vec_promoted_val,
9817 : &count_exp,
9818 : &jump_around_label,
9819 4040 : desired_align < align
9820 0 : ? MAX (desired_align, epilogue_size_needed) : epilogue_size_needed,
9821 : desired_align, align, &min_size, dynamic_check, issetmem);
9822 4040 : if (!issetmem)
9823 2102 : src = change_address (src, BLKmode, srcreg);
9824 4040 : dst = change_address (dst, BLKmode, destreg);
9825 4040 : if (aligned_dstmem)
9826 17 : set_mem_align (dst, desired_align * BITS_PER_UNIT);
9827 4040 : epilogue_size_needed = 0;
9828 4040 : if (need_zero_guard
9829 3756 : && min_size < (unsigned HOST_WIDE_INT) size_needed)
9830 : {
9831 : /* It is possible that we copied enough so the main loop will not
9832 : execute. */
9833 715 : gcc_assert (size_needed > 1);
9834 715 : if (jump_around_label == NULL_RTX)
9835 49 : jump_around_label = gen_label_rtx ();
9836 1430 : emit_cmp_and_jump_insns (count_exp,
9837 : GEN_INT (size_needed),
9838 : LTU, 0, counter_mode (count_exp), 1, jump_around_label);
9839 715 : if (expected_size == -1
9840 55 : || expected_size < (desired_align - align) / 2 + size_needed)
9841 660 : predict_jump (REG_BR_PROB_BASE * 20 / 100);
9842 : else
9843 55 : predict_jump (REG_BR_PROB_BASE * 60 / 100);
9844 : }
9845 : }
9846 : /* Ensure that alignment prologue won't copy past end of block. */
9847 22779 : else if (size_needed > 1 || (desired_align > 1 && desired_align > align))
9848 : {
9849 16836 : epilogue_size_needed = MAX (size_needed - 1, desired_align - align);
9850 : /* Epilogue always copies COUNT_EXP & EPILOGUE_SIZE_NEEDED bytes.
9851 : Make sure it is power of 2. */
9852 16836 : epilogue_size_needed = 1 << (floor_log2 (epilogue_size_needed) + 1);
9853 :
9854 : /* To improve performance of small blocks, we jump around the VAL
9855 : promoting mode. This mean that if the promoted VAL is not constant,
9856 : we might not use it in the epilogue and have to use byte
9857 : loop variant. */
9858 16836 : if (issetmem && epilogue_size_needed > 2 && !promoted_val)
9859 16836 : force_loopy_epilogue = true;
9860 16836 : if ((count && count < (unsigned HOST_WIDE_INT) epilogue_size_needed)
9861 16827 : || max_size < (unsigned HOST_WIDE_INT) epilogue_size_needed)
9862 : {
9863 : /* If main algorithm works on QImode, no epilogue is needed.
9864 : For small sizes just don't align anything. */
9865 44 : if (size_needed == 1)
9866 0 : desired_align = align;
9867 : else
9868 44 : goto epilogue;
9869 : }
9870 16792 : else if (!count
9871 63 : && min_size < (unsigned HOST_WIDE_INT) epilogue_size_needed)
9872 : {
9873 63 : label = gen_label_rtx ();
9874 126 : emit_cmp_and_jump_insns (count_exp,
9875 : GEN_INT (epilogue_size_needed),
9876 : LTU, 0, counter_mode (count_exp), 1, label);
9877 63 : if (expected_size == -1 || expected_size < epilogue_size_needed)
9878 63 : predict_jump (REG_BR_PROB_BASE * 60 / 100);
9879 : else
9880 0 : predict_jump (REG_BR_PROB_BASE * 20 / 100);
9881 : }
9882 : }
9883 :
9884 : /* Emit code to decide on runtime whether library call or inline should be
9885 : used. */
9886 26775 : if (dynamic_check != -1)
9887 : {
9888 2 : if (!issetmem && CONST_INT_P (count_exp))
9889 : {
9890 1 : if (UINTVAL (count_exp) >= (unsigned HOST_WIDE_INT)dynamic_check)
9891 : {
9892 1 : emit_block_copy_via_libcall (dst, src, count_exp);
9893 1 : count_exp = const0_rtx;
9894 1 : goto epilogue;
9895 : }
9896 : }
9897 : else
9898 : {
9899 1 : rtx_code_label *hot_label = gen_label_rtx ();
9900 1 : if (jump_around_label == NULL_RTX)
9901 1 : jump_around_label = gen_label_rtx ();
9902 2 : emit_cmp_and_jump_insns (count_exp, GEN_INT (dynamic_check - 1),
9903 : LEU, 0, counter_mode (count_exp),
9904 : 1, hot_label);
9905 1 : predict_jump (REG_BR_PROB_BASE * 90 / 100);
9906 1 : if (issetmem)
9907 1 : set_storage_via_libcall (dst, count_exp, val_exp);
9908 : else
9909 0 : emit_block_copy_via_libcall (dst, src, count_exp);
9910 1 : emit_jump (jump_around_label);
9911 1 : emit_label (hot_label);
9912 : }
9913 : }
9914 :
9915 : /* Step 2: Alignment prologue. */
9916 : /* Do the expensive promotion once we branched off the small blocks. */
9917 26774 : if (issetmem && !promoted_val)
9918 48 : promoted_val = promote_duplicated_reg_to_size (val_exp, size_needed,
9919 : desired_align, align);
9920 :
9921 26774 : if (desired_align > align && !misaligned_prologue_used)
9922 : {
9923 7 : if (align_bytes == 0)
9924 : {
9925 : /* Except for the first move in prologue, we no longer know
9926 : constant offset in aliasing info. It don't seems to worth
9927 : the pain to maintain it for the first move, so throw away
9928 : the info early. */
9929 7 : dst = change_address (dst, BLKmode, destreg);
9930 7 : if (!issetmem)
9931 5 : src = change_address (src, BLKmode, srcreg);
9932 7 : dst = expand_set_or_cpymem_prologue (dst, src, destreg, srcreg,
9933 : promoted_val, vec_promoted_val,
9934 : count_exp, align, desired_align,
9935 : issetmem);
9936 : /* At most desired_align - align bytes are copied. */
9937 7 : if (min_size < (unsigned)(desired_align - align))
9938 0 : min_size = 0;
9939 : else
9940 7 : min_size -= desired_align - align;
9941 : }
9942 : else
9943 : {
9944 : /* If we know how many bytes need to be stored before dst is
9945 : sufficiently aligned, maintain aliasing info accurately. */
9946 0 : dst = expand_set_or_cpymem_constant_prologue (dst, &src, destreg,
9947 : srcreg,
9948 : promoted_val,
9949 : vec_promoted_val,
9950 : desired_align,
9951 : align_bytes,
9952 : issetmem);
9953 :
9954 0 : count_exp = plus_constant (counter_mode (count_exp),
9955 0 : count_exp, -align_bytes);
9956 0 : count -= align_bytes;
9957 0 : min_size -= align_bytes;
9958 0 : max_size -= align_bytes;
9959 : }
9960 7 : if (need_zero_guard
9961 7 : && min_size < (unsigned HOST_WIDE_INT) size_needed
9962 1 : && (count < (unsigned HOST_WIDE_INT) size_needed
9963 0 : || (align_bytes == 0
9964 0 : && count < ((unsigned HOST_WIDE_INT) size_needed
9965 0 : + desired_align - align))))
9966 : {
9967 : /* It is possible that we copied enough so the main loop will not
9968 : execute. */
9969 1 : gcc_assert (size_needed > 1);
9970 1 : if (label == NULL_RTX)
9971 0 : label = gen_label_rtx ();
9972 2 : emit_cmp_and_jump_insns (count_exp,
9973 : GEN_INT (size_needed),
9974 : LTU, 0, counter_mode (count_exp), 1, label);
9975 1 : if (expected_size == -1
9976 0 : || expected_size < (desired_align - align) / 2 + size_needed)
9977 1 : predict_jump (REG_BR_PROB_BASE * 20 / 100);
9978 : else
9979 0 : predict_jump (REG_BR_PROB_BASE * 60 / 100);
9980 : }
9981 : }
9982 26774 : if (label && size_needed == 1)
9983 : {
9984 0 : emit_label (label);
9985 0 : LABEL_NUSES (label) = 1;
9986 0 : label = NULL;
9987 0 : epilogue_size_needed = 1;
9988 0 : if (issetmem)
9989 0 : promoted_val = val_exp;
9990 : }
9991 26774 : else if (label == NULL_RTX && !misaligned_prologue_used)
9992 22672 : epilogue_size_needed = size_needed;
9993 :
9994 : /* Step 3: Main loop. */
9995 :
9996 26774 : switch (alg)
9997 : {
9998 0 : case libcall:
9999 0 : case no_stringop:
10000 0 : case last_alg:
10001 0 : gcc_unreachable ();
10002 238 : case loop_1_byte:
10003 238 : case loop:
10004 238 : case unrolled_loop:
10005 238 : expand_set_or_cpymem_via_loop (dst, src, destreg, srcreg, promoted_val,
10006 : count_exp, move_mode, unroll_factor,
10007 : expected_size, issetmem);
10008 238 : break;
10009 7891 : case vector_loop:
10010 7891 : expand_set_or_cpymem_via_loop (dst, src, destreg, srcreg,
10011 : vec_promoted_val, count_exp, move_mode,
10012 : unroll_factor, expected_size, issetmem);
10013 7891 : break;
10014 18645 : case rep_prefix_8_byte:
10015 18645 : case rep_prefix_4_byte:
10016 18645 : case rep_prefix_1_byte:
10017 18645 : expand_set_or_cpymem_via_rep (dst, src, destreg, srcreg, promoted_val,
10018 : val_exp, count_exp, move_mode, issetmem);
10019 18645 : break;
10020 : }
10021 : /* Adjust properly the offset of src and dest memory for aliasing. */
10022 26774 : if (CONST_INT_P (count_exp))
10023 : {
10024 21134 : if (!issetmem)
10025 8928 : src = adjust_automodify_address_nv (src, BLKmode, srcreg,
10026 : (count / size_needed) * size_needed);
10027 21134 : dst = adjust_automodify_address_nv (dst, BLKmode, destreg,
10028 : (count / size_needed) * size_needed);
10029 : }
10030 : else
10031 : {
10032 5640 : if (!issetmem)
10033 4617 : src = change_address (src, BLKmode, srcreg);
10034 5640 : dst = change_address (dst, BLKmode, destreg);
10035 : }
10036 :
10037 : /* Step 4: Epilogue to copy the remaining bytes. */
10038 26819 : epilogue:
10039 26819 : if (label)
10040 : {
10041 : /* When the main loop is done, COUNT_EXP might hold original count,
10042 : while we want to copy only COUNT_EXP & SIZE_NEEDED bytes.
10043 : Epilogue code will actually copy COUNT_EXP & EPILOGUE_SIZE_NEEDED
10044 : bytes. Compensate if needed. */
10045 :
10046 63 : if (size_needed < epilogue_size_needed)
10047 : {
10048 0 : tmp = expand_simple_binop (counter_mode (count_exp), AND, count_exp,
10049 0 : GEN_INT (size_needed - 1), count_exp, 1,
10050 : OPTAB_DIRECT);
10051 0 : if (tmp != count_exp)
10052 0 : emit_move_insn (count_exp, tmp);
10053 : }
10054 63 : emit_label (label);
10055 63 : LABEL_NUSES (label) = 1;
10056 : }
10057 :
10058 26819 : if (count_exp != const0_rtx && epilogue_size_needed > 1)
10059 : {
10060 16836 : if (force_loopy_epilogue)
10061 0 : expand_setmem_epilogue_via_loop (dst, destreg, val_exp, count_exp,
10062 : epilogue_size_needed);
10063 : else
10064 : {
10065 16836 : if (issetmem)
10066 9997 : expand_setmem_epilogue (dst, destreg, promoted_val,
10067 : vec_promoted_val, count_exp,
10068 : epilogue_size_needed);
10069 : else
10070 6839 : expand_cpymem_epilogue (dst, src, destreg, srcreg, count_exp,
10071 : epilogue_size_needed);
10072 : }
10073 : }
10074 26819 : if (jump_around_label)
10075 718 : emit_label (jump_around_label);
10076 : return true;
10077 : }
10078 :
10079 : /* Fully unroll memmove of known size with up to 8 registers. */
10080 :
10081 : static bool
10082 1882 : ix86_expand_unroll_movmem (rtx dst, rtx src, rtx destreg, rtx srcreg,
10083 : unsigned HOST_WIDE_INT count,
10084 : machine_mode mode)
10085 : {
10086 : /* If 8 registers registers can cover all memory, load them into
10087 : registers and store them together to avoid possible address
10088 : overlap between source and destination. */
10089 1882 : unsigned HOST_WIDE_INT moves = count / GET_MODE_SIZE (mode);
10090 1882 : if (moves == 0)
10091 : {
10092 0 : mode = smallest_int_mode_for_size
10093 0 : (count * BITS_PER_UNIT).require ();
10094 0 : if (count == GET_MODE_SIZE (mode))
10095 : moves = 1;
10096 : else
10097 : {
10098 : /* Reduce the smallest move size by half so that MOVES == 1. */
10099 0 : mode = smallest_int_mode_for_size
10100 0 : (GET_MODE_BITSIZE (mode) / 2).require ();
10101 0 : moves = count / GET_MODE_SIZE (mode);
10102 0 : gcc_assert (moves == 1);
10103 : }
10104 : }
10105 1882 : else if (moves > 8)
10106 : return false;
10107 :
10108 1873 : unsigned int i;
10109 1873 : rtx tmp[9];
10110 :
10111 4314 : for (i = 0; i < moves; i++)
10112 2441 : tmp[i] = gen_reg_rtx (mode);
10113 :
10114 1873 : rtx srcmem = change_address (src, mode, srcreg);
10115 6187 : for (i = 0; i < moves; i++)
10116 : {
10117 2441 : emit_move_insn (tmp[i], srcmem);
10118 4882 : srcmem = offset_address (srcmem,
10119 2441 : GEN_INT (GET_MODE_SIZE (mode)),
10120 2441 : GET_MODE_SIZE (mode));
10121 : }
10122 :
10123 1873 : unsigned int epilogue_size = count & (GET_MODE_SIZE (mode) - 1);
10124 1873 : machine_mode epilogue_mode = VOIDmode;
10125 1873 : if (epilogue_size)
10126 : {
10127 : /* Handle the remaining bytes with overlapping move. */
10128 1700 : epilogue_mode = smallest_int_mode_for_size
10129 1700 : (epilogue_size * BITS_PER_UNIT).require ();
10130 1700 : tmp[8] = gen_reg_rtx (epilogue_mode);
10131 1700 : srcmem = adjust_address (srcmem, epilogue_mode, 0);
10132 1700 : srcmem = offset_address (srcmem, GEN_INT (epilogue_size), 1);
10133 3400 : srcmem = offset_address (srcmem,
10134 1700 : GEN_INT (-GET_MODE_SIZE (epilogue_mode)),
10135 1700 : GET_MODE_SIZE (epilogue_mode));
10136 1700 : emit_move_insn (tmp[8], srcmem);
10137 : }
10138 :
10139 1873 : rtx destmem = change_address (dst, mode, destreg);
10140 6187 : for (i = 0; i < moves; i++)
10141 : {
10142 2441 : emit_move_insn (destmem, tmp[i]);
10143 4882 : destmem = offset_address (destmem,
10144 2441 : GEN_INT (GET_MODE_SIZE (mode)),
10145 2441 : GET_MODE_SIZE (mode));
10146 : }
10147 :
10148 1873 : if (epilogue_size)
10149 : {
10150 : /* Use overlapping move. */
10151 1700 : destmem = adjust_address (destmem, epilogue_mode, 0);
10152 1700 : destmem = offset_address (destmem, GEN_INT (epilogue_size), 1);
10153 3400 : destmem = offset_address (destmem,
10154 1700 : GEN_INT (-GET_MODE_SIZE (epilogue_mode)),
10155 1700 : GET_MODE_SIZE (epilogue_mode));
10156 1700 : emit_move_insn (destmem, tmp[8]);
10157 : }
10158 :
10159 : return true;
10160 : }
10161 :
10162 : /* Value kind in MEMSET_VALS:
10163 :
10164 : memset_val_byte: The value rtx in QImode.
10165 : memset_val_word: The value rtx in word_mode.
10166 : memset_val_vector: The value rtx in QI vector mode.
10167 :
10168 : */
10169 : enum memset_val_kind
10170 : {
10171 : memset_val_byte = 0,
10172 : memset_val_word = 1,
10173 : memset_val_vector = 2,
10174 : memset_val_max = 3
10175 : };
10176 :
10177 : /* Return a value rtx in MODE for memset from MEMSET_VALS. */
10178 :
10179 : static rtx
10180 4281 : ix86_expand_memset_val (rtx *memset_vals, machine_mode mode)
10181 : {
10182 4281 : rtx byte_val = memset_vals[memset_val_byte];
10183 :
10184 4281 : if (mode == QImode)
10185 : return byte_val;
10186 4281 : else if (mode == word_mode)
10187 976 : return memset_vals[memset_val_word];
10188 :
10189 : /* All-zero/all-ones is a property of the original byte value, so
10190 : detect it once here rather than re-deriving it from each slot. */
10191 3305 : if (byte_val == const0_rtx)
10192 1254 : return CONST0_RTX (mode);
10193 2051 : if (byte_val == constm1_rtx)
10194 78 : return CONSTM1_RTX (mode);
10195 :
10196 1973 : if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT)
10197 : {
10198 684 : if (GET_MODE (memset_vals[memset_val_vector]) == mode)
10199 : return memset_vals[memset_val_vector];
10200 7 : return gen_rtx_SUBREG (mode, memset_vals[memset_val_vector], 0);
10201 : }
10202 :
10203 1289 : gcc_assert (mode == HImode || mode == SImode);
10204 1289 : return gen_rtx_SUBREG (mode, memset_vals[memset_val_word], 0);
10205 : }
10206 :
10207 : /* Expand memmove of size with MOVES * mode size and MOVES <= 4. If
10208 : FORWARD is true, copy forward. Otherwise copy backward. */
10209 :
10210 : static void
10211 2433 : ix86_expand_n_move_set_or_movmem (rtx destmem, rtx srcmem,
10212 : rtx *memset_vals, machine_mode mode,
10213 : unsigned int moves, bool forward)
10214 : {
10215 2433 : gcc_assert (moves <= 4);
10216 :
10217 2433 : unsigned int i;
10218 2433 : rtx tmp[8];
10219 :
10220 2433 : rtx step;
10221 2433 : if (forward)
10222 2560 : step = GEN_INT (GET_MODE_SIZE (mode));
10223 : else
10224 2306 : step = GEN_INT (-GET_MODE_SIZE (mode));
10225 :
10226 2433 : if (memset_vals)
10227 : {
10228 : /* Expand memset. */
10229 99 : rtx val = ix86_expand_memset_val (memset_vals, mode);
10230 594 : for (i = 0; i < moves; i++)
10231 396 : tmp[i] = val;
10232 : }
10233 : else
10234 : {
10235 : /* Expand memmove. */
10236 11670 : for (i = 0; i < moves; i++)
10237 9336 : tmp[i] = gen_reg_rtx (mode);
10238 :
10239 : /* Load MOVES. */
10240 9336 : for (i = 0; i < moves - 1; i++)
10241 : {
10242 7002 : emit_move_insn (tmp[i], srcmem);
10243 14004 : srcmem = offset_address (srcmem, step, GET_MODE_SIZE (mode));
10244 : }
10245 2334 : emit_move_insn (tmp[i], srcmem);
10246 : }
10247 :
10248 : /* Store MOVES. */
10249 9732 : for (i = 0; i < moves - 1; i++)
10250 : {
10251 7299 : emit_move_insn (destmem, tmp[i]);
10252 14598 : destmem = offset_address (destmem, step, GET_MODE_SIZE (mode));
10253 : }
10254 2433 : emit_move_insn (destmem, tmp[i]);
10255 2433 : }
10256 :
10257 : /* Load MOVES of mode size into REGS. If LAST is true, load the
10258 : last MOVES. Otherwise, load the first MOVES. */
10259 :
10260 : static void
10261 2334 : ix86_expand_load_movmem (rtx src, rtx srcreg, rtx count_exp,
10262 : machine_mode mode, unsigned int moves,
10263 : rtx regs[], bool last)
10264 : {
10265 2334 : unsigned int i;
10266 :
10267 11670 : for (i = 0; i < moves; i++)
10268 9336 : regs[i] = gen_reg_rtx (mode);
10269 :
10270 2334 : rtx srcmem = change_address (src, mode, srcreg);
10271 2334 : rtx step;
10272 2334 : if (last)
10273 : {
10274 1181 : srcmem = offset_address (srcmem, count_exp, 1);
10275 2362 : step = GEN_INT (-GET_MODE_SIZE (mode));
10276 2362 : srcmem = offset_address (srcmem, step, GET_MODE_SIZE (mode));
10277 : }
10278 : else
10279 2306 : step = GEN_INT (GET_MODE_SIZE (mode));
10280 :
10281 9336 : for (i = 0; i < moves - 1; i++)
10282 : {
10283 7002 : emit_move_insn (regs[i], srcmem);
10284 14004 : srcmem = offset_address (srcmem, step, GET_MODE_SIZE (mode));
10285 : }
10286 2334 : emit_move_insn (regs[i], srcmem);
10287 2334 : }
10288 :
10289 : /* Store MOVES of mode size into REGS. If LAST is true, store the
10290 : last MOVES. Otherwise, store the first MOVES. */
10291 :
10292 : static void
10293 2433 : ix86_expand_store_movmem (rtx dst, rtx destreg, rtx count_exp,
10294 : machine_mode mode, unsigned int moves,
10295 : rtx regs[], bool last)
10296 : {
10297 2433 : unsigned int i;
10298 :
10299 2433 : rtx destmem = change_address (dst, mode, destreg);
10300 2433 : rtx step;
10301 2433 : if (last)
10302 : {
10303 1280 : destmem = offset_address (destmem, count_exp, 1);
10304 2560 : step = GEN_INT (-GET_MODE_SIZE (mode));
10305 2560 : destmem = offset_address (destmem, step, GET_MODE_SIZE (mode));
10306 : }
10307 : else
10308 2306 : step = GEN_INT (GET_MODE_SIZE (mode));
10309 :
10310 9732 : for (i = 0; i < moves - 1; i++)
10311 : {
10312 7299 : emit_move_insn (destmem, regs[i]);
10313 14598 : destmem = offset_address (destmem, step, GET_MODE_SIZE (mode));
10314 : }
10315 2433 : emit_move_insn (destmem, regs[i]);
10316 2433 : }
10317 :
10318 : /* Expand memmove of size between (MOVES / 2) * mode size and
10319 : MOVES * mode size with overlapping load and store. MOVES is even.
10320 : MOVES >= 2 and MOVES <= 8. */
10321 :
10322 : static void
10323 43574 : ix86_expand_n_overlapping_move_set_or_movmem (rtx dst, rtx src,
10324 : rtx *memset_vals,
10325 : rtx destreg, rtx srcreg,
10326 : rtx count_exp,
10327 : machine_mode mode,
10328 : unsigned int moves)
10329 : {
10330 43574 : gcc_assert (moves >= 2 && moves <= 8 && (moves & 1) == 0);
10331 :
10332 43574 : unsigned int half_moves = moves / 2;
10333 43574 : unsigned int i, j;
10334 43574 : rtx tmp[8];
10335 :
10336 43574 : if (memset_vals)
10337 : {
10338 : /* Expand memset. */
10339 4083 : rtx val = ix86_expand_memset_val (memset_vals, mode);
10340 18296 : for (i = 0; i < moves; i++)
10341 10130 : tmp[i] = val;
10342 : }
10343 : else
10344 : {
10345 : /* Expand memmove. */
10346 133139 : for (i = 0; i < moves; i++)
10347 93648 : tmp[i] = gen_reg_rtx (mode);
10348 :
10349 39491 : rtx base_srcmem = change_address (src, mode, srcreg);
10350 :
10351 : /* Load the first half. */
10352 39491 : rtx srcmem = base_srcmem;
10353 86315 : for (i = 0; i < half_moves - 1; i++)
10354 : {
10355 7333 : emit_move_insn (tmp[i], srcmem);
10356 14666 : srcmem = offset_address (srcmem,
10357 7333 : GEN_INT (GET_MODE_SIZE (mode)),
10358 7333 : GET_MODE_SIZE (mode));
10359 : }
10360 39491 : emit_move_insn (tmp[i], srcmem);
10361 :
10362 : /* Load the second half. */
10363 39491 : srcmem = offset_address (base_srcmem, count_exp, 1);
10364 39491 : srcmem = offset_address (srcmem,
10365 39491 : GEN_INT (-GET_MODE_SIZE (mode)),
10366 39491 : GET_MODE_SIZE (mode));
10367 86315 : for (j = half_moves, i = 0; i < half_moves - 1; i++, j++)
10368 : {
10369 7333 : emit_move_insn (tmp[j], srcmem);
10370 14666 : srcmem = offset_address (srcmem,
10371 7333 : GEN_INT (-GET_MODE_SIZE (mode)),
10372 7333 : GET_MODE_SIZE (mode));
10373 : }
10374 39491 : emit_move_insn (tmp[j], srcmem);
10375 : }
10376 :
10377 43574 : rtx base_destmem = change_address (dst, mode, destreg);
10378 :
10379 : /* Store the first half. */
10380 43574 : rtx destmem = base_destmem;
10381 95463 : for (i = 0; i < half_moves - 1; i++)
10382 : {
10383 8315 : emit_move_insn (destmem, tmp[i]);
10384 16630 : destmem = offset_address (destmem,
10385 8315 : GEN_INT (GET_MODE_SIZE (mode)),
10386 8315 : GET_MODE_SIZE (mode));
10387 : }
10388 43574 : emit_move_insn (destmem, tmp[i]);
10389 :
10390 : /* Store the second half. */
10391 43574 : destmem = offset_address (base_destmem, count_exp, 1);
10392 87148 : destmem = offset_address (destmem, GEN_INT (-GET_MODE_SIZE (mode)),
10393 43574 : GET_MODE_SIZE (mode));
10394 95463 : for (j = half_moves, i = 0; i < half_moves - 1; i++, j++)
10395 : {
10396 8315 : emit_move_insn (destmem, tmp[j]);
10397 16630 : destmem = offset_address (destmem, GEN_INT (-GET_MODE_SIZE (mode)),
10398 8315 : GET_MODE_SIZE (mode));
10399 : }
10400 43574 : emit_move_insn (destmem, tmp[j]);
10401 43574 : }
10402 :
10403 : /* Expand memmove of size < mode size which is <= 64. */
10404 :
10405 : static void
10406 10769 : ix86_expand_less_move_set_or_movmem (rtx dst, rtx src, rtx *memset_vals,
10407 : rtx destreg, rtx srcreg,
10408 : rtx count_exp,
10409 : unsigned HOST_WIDE_INT min_size,
10410 : machine_mode mode,
10411 : rtx_code_label *done_label)
10412 : {
10413 10769 : bool skip = false;
10414 10769 : machine_mode count_mode = counter_mode (count_exp);
10415 :
10416 10769 : rtx_code_label *between_32_63_label
10417 10769 : = GET_MODE_SIZE (mode) > 32 ? gen_label_rtx () : nullptr;
10418 : /* Jump to BETWEEN_32_64_LABEL if size >= 32 and size < 64. */
10419 7 : if (between_32_63_label)
10420 : {
10421 7 : if (min_size && min_size >= 32)
10422 : {
10423 1 : emit_jump_insn (gen_jump (between_32_63_label));
10424 1 : emit_barrier ();
10425 1 : skip = true;
10426 : }
10427 : else
10428 6 : emit_cmp_and_jump_insns (count_exp, GEN_INT (32), GEU,
10429 : nullptr, count_mode, 1,
10430 : between_32_63_label);
10431 : }
10432 :
10433 7 : rtx_code_label *between_16_31_label
10434 10768 : = (!skip && GET_MODE_SIZE (mode) > 16) ? gen_label_rtx () : nullptr;
10435 : /* Jump to BETWEEN_16_31_LABEL if size >= 16 and size < 31. */
10436 21 : if (between_16_31_label)
10437 : {
10438 21 : if (min_size && min_size >= 16)
10439 : {
10440 2 : emit_jump_insn (gen_jump (between_16_31_label));
10441 2 : emit_barrier ();
10442 2 : skip = true;
10443 : }
10444 : else
10445 19 : emit_cmp_and_jump_insns (count_exp, GEN_INT (16), GEU,
10446 : nullptr, count_mode, 1,
10447 : between_16_31_label);
10448 : }
10449 :
10450 2 : rtx_code_label *between_8_15_label
10451 21533 : = (!skip && GET_MODE_SIZE (mode) > 8) ? gen_label_rtx () : nullptr;
10452 : /* Jump to BETWEEN_8_15_LABEL if size >= 8 and size < 15. */
10453 8587 : if (between_8_15_label)
10454 : {
10455 8587 : if (min_size && min_size >= 8)
10456 : {
10457 481 : emit_jump_insn (gen_jump (between_8_15_label));
10458 481 : emit_barrier ();
10459 481 : skip = true;
10460 : }
10461 : else
10462 8106 : emit_cmp_and_jump_insns (count_exp, GEN_INT (8), GEU,
10463 : nullptr, count_mode, 1,
10464 : between_8_15_label);
10465 : }
10466 :
10467 481 : rtx_code_label *between_4_7_label
10468 20573 : = (!skip && GET_MODE_SIZE (mode) > 4) ? gen_label_rtx () : nullptr;
10469 : /* Jump to BETWEEN_4_7_LABEL if size >= 4 and size < 7. */
10470 9391 : if (between_4_7_label)
10471 : {
10472 9391 : if (min_size && min_size >= 4)
10473 : {
10474 443 : emit_jump_insn (gen_jump (between_4_7_label));
10475 443 : emit_barrier ();
10476 443 : skip = true;
10477 : }
10478 : else
10479 8948 : emit_cmp_and_jump_insns (count_exp, GEN_INT (4), GEU,
10480 : nullptr, count_mode, 1,
10481 : between_4_7_label);
10482 : }
10483 :
10484 443 : rtx_code_label *between_2_3_label
10485 20168 : = (!skip && GET_MODE_SIZE (mode) > 2) ? gen_label_rtx () : nullptr;
10486 : /* Jump to BETWEEN_2_3_LABEL if size >= 2 and size < 3. */
10487 9624 : if (between_2_3_label)
10488 : {
10489 9624 : if (min_size && min_size >= 2)
10490 : {
10491 1919 : emit_jump_insn (gen_jump (between_2_3_label));
10492 1919 : emit_barrier ();
10493 1919 : skip = true;
10494 : }
10495 : else
10496 7705 : emit_cmp_and_jump_insns (count_exp, GEN_INT (1), GT,
10497 : nullptr, count_mode, 1,
10498 : between_2_3_label);
10499 : }
10500 :
10501 10769 : if (!skip)
10502 : {
10503 7923 : rtx_code_label *zero_label
10504 7923 : = min_size == 0 ? gen_label_rtx () : nullptr;
10505 : /* Skip if size == 0. */
10506 2711 : if (zero_label)
10507 2711 : emit_cmp_and_jump_insns (count_exp, GEN_INT (1), LT,
10508 : nullptr, count_mode, 1,
10509 : zero_label,
10510 : profile_probability::unlikely ());
10511 :
10512 : /* Move 1 byte. */
10513 7923 : rtx tmp0;
10514 : /* Use the value rtx in QImode for memset. */
10515 7923 : if (memset_vals)
10516 904 : tmp0 = memset_vals[memset_val_byte];
10517 : else
10518 : {
10519 7019 : tmp0 = gen_reg_rtx (QImode);
10520 7019 : rtx srcmem = change_address (src, QImode, srcreg);
10521 7019 : emit_move_insn (tmp0, srcmem);
10522 : }
10523 7923 : rtx destmem = change_address (dst, QImode, destreg);
10524 7923 : emit_move_insn (destmem, tmp0);
10525 :
10526 7923 : if (zero_label)
10527 2711 : emit_label (zero_label);
10528 :
10529 7923 : emit_jump_insn (gen_jump (done_label));
10530 7923 : emit_barrier ();
10531 : }
10532 :
10533 : /* For each size band, memset uses a QI-vector mode above a word so it
10534 : can broadcast the fill value, while memmove uses the same-size
10535 : scalar integer mode; at and below a word both use the scalar
10536 : integer mode. */
10537 10769 : struct {
10538 : rtx_code_label *label;
10539 : machine_mode set_mode;
10540 : machine_mode move_mode;
10541 10769 : } bands[] = {
10542 : { between_32_63_label, V32QImode, OImode },
10543 : { between_16_31_label, V16QImode, TImode },
10544 : { between_8_15_label, DImode, DImode },
10545 : { between_4_7_label, SImode, SImode },
10546 : { between_2_3_label, HImode, HImode },
10547 10769 : };
10548 :
10549 64614 : for (auto &band : bands)
10550 53845 : if (band.label)
10551 : {
10552 27630 : emit_label (band.label);
10553 27630 : machine_mode bmode = memset_vals ? band.set_mode : band.move_mode;
10554 27630 : ix86_expand_n_overlapping_move_set_or_movmem (dst, src,
10555 : memset_vals,
10556 : destreg, srcreg,
10557 : count_exp, bmode,
10558 : 2);
10559 27630 : emit_jump_insn (gen_jump (done_label));
10560 27630 : emit_barrier ();
10561 : }
10562 10769 : }
10563 :
10564 : /* Expand movmem with overlapping unaligned loads and stores:
10565 : 1. Load all sources into registers and store them together to avoid
10566 : possible address overlap between source and destination.
10567 : 2. For known size, first try to fully unroll with 8 registers.
10568 : 3. For size <= 2 * MOVE_MAX, load all sources into 2 registers first
10569 : and then store them together.
10570 : 4. For size > 2 * MOVE_MAX and size <= 4 * MOVE_MAX, load all sources
10571 : into 4 registers first and then store them together.
10572 : 5. For size > 4 * MOVE_MAX and size <= 8 * MOVE_MAX, load all sources
10573 : into 8 registers first and then store them together.
10574 : 6. For size > 8 * MOVE_MAX,
10575 : a. If address of destination > address of source, copy backward
10576 : with a 4 * MOVE_MAX loop with unaligned loads and stores. Load
10577 : the first 4 * MOVE_MAX into 4 registers before the loop and
10578 : store them after the loop to support overlapping addresses.
10579 : b. Otherwise, copy forward with a 4 * MOVE_MAX loop with unaligned
10580 : loads and stores. Load the last 4 * MOVE_MAX into 4 registers
10581 : before the loop and store them after the loop to support
10582 : overlapping addresses.
10583 : */
10584 :
10585 : bool
10586 169843 : ix86_expand_set_or_movmem (rtx operands[], bool iscpymem, bool issetmem)
10587 : {
10588 : /* Since there are much less registers available in 32-bit mode, don't
10589 : inline movmem in 32-bit mode. */
10590 169843 : if (!TARGET_64BIT || optimize_insn_for_size_p ())
10591 33683 : return false;
10592 :
10593 136160 : rtx dst = operands[0];
10594 136160 : rtx src, memset_val_exp;
10595 136160 : if (issetmem)
10596 : {
10597 35279 : src = nullptr;
10598 35279 : memset_val_exp = operands[1];
10599 : }
10600 : else
10601 : {
10602 100881 : src = operands[1];
10603 100881 : memset_val_exp = nullptr;
10604 : }
10605 136160 : rtx count_exp = operands[2];
10606 136160 : rtx expected_size_exp = operands[5];
10607 136160 : rtx min_size_exp = operands[6];
10608 136160 : rtx max_size_exp = operands[7];
10609 136160 : rtx probable_max_size_exp = operands[8];
10610 136160 : unsigned HOST_WIDE_INT count = HOST_WIDE_INT_0U;
10611 136160 : HOST_WIDE_INT expected_size = HOST_WIDE_INT_M1U;
10612 136160 : unsigned HOST_WIDE_INT min_size = HOST_WIDE_INT_0U;
10613 136160 : unsigned HOST_WIDE_INT max_size = HOST_WIDE_INT_M1U;
10614 136160 : unsigned HOST_WIDE_INT probable_max_size = HOST_WIDE_INT_M1U;
10615 :
10616 136160 : if (CONST_INT_P (count_exp))
10617 : {
10618 54229 : min_size = max_size = probable_max_size = count = expected_size
10619 54229 : = INTVAL (count_exp);
10620 : /* When COUNT is 0, there is nothing to do. */
10621 54229 : if (!count)
10622 : return true;
10623 : }
10624 : else
10625 : {
10626 81931 : if (min_size_exp)
10627 81931 : min_size = INTVAL (min_size_exp);
10628 81931 : if (max_size_exp)
10629 62874 : max_size = INTVAL (max_size_exp);
10630 81931 : if (probable_max_size_exp)
10631 64860 : probable_max_size = INTVAL (probable_max_size_exp);
10632 81931 : if (CONST_INT_P (expected_size_exp))
10633 81931 : expected_size = INTVAL (expected_size_exp);
10634 :
10635 : /* NB: This assert may fail without the fixes for
10636 : https://gcc.gnu.org/bugzilla/show_bug.cgi?id=125977
10637 : */
10638 81931 : gcc_assert (min_size != max_size);
10639 : }
10640 :
10641 : /* Make sure we don't need to care about overflow later on. */
10642 54227 : if (count > (HOST_WIDE_INT_1U << 30))
10643 : return false;
10644 :
10645 135970 : addr_space_t dst_as = MEM_ADDR_SPACE (dst);
10646 135970 : addr_space_t src_as = (issetmem
10647 : ? ADDR_SPACE_GENERIC
10648 135970 : : MEM_ADDR_SPACE (src));
10649 135970 : int dynamic_check;
10650 135970 : bool noalign;
10651 135970 : enum stringop_alg alg = decide_alg (count, expected_size, min_size,
10652 : probable_max_size, issetmem,
10653 : (issetmem
10654 35216 : && memset_val_exp == const0_rtx),
10655 : dst_as, src_as, &dynamic_check,
10656 : &noalign, false);
10657 135970 : if (alg == libcall)
10658 : return false;
10659 :
10660 : /* Expand memcpy and memset like memmove only for bounded size. */
10661 18240 : if (iscpymem || issetmem)
10662 : {
10663 13995 : unsigned HOST_WIDE_INT unbounded
10664 13995 : = GET_MODE_MASK (counter_mode (count_exp));
10665 13995 : if (count != 0 /* Fixed size. */
10666 13995 : || max_size == 0 /* Unbounded size. */
10667 8970 : || max_size == unbounded) /* Unbounded size. */
10668 : return false;
10669 : }
10670 :
10671 12887 : rtx destreg = ix86_copy_addr_to_reg (XEXP (dst, 0));
10672 12887 : rtx srcreg = (issetmem
10673 12887 : ? nullptr
10674 11756 : : ix86_copy_addr_to_reg (XEXP (src, 0)));
10675 :
10676 12887 : unsigned int move_max = MOVE_MAX;
10677 12887 : machine_mode mode = smallest_int_mode_for_size
10678 12887 : (move_max * BITS_PER_UNIT).require ();
10679 12887 : if (probable_max_size && probable_max_size < move_max)
10680 : {
10681 : /* Get a usable MOVE_MAX. */
10682 3794 : mode = smallest_int_mode_for_size
10683 3794 : (probable_max_size * BITS_PER_UNIT).require ();
10684 : /* Reduce MOVE_MAX by half so that MOVE_MAX can be used. */
10685 7588 : if (GET_MODE_SIZE (mode) > probable_max_size)
10686 3266 : mode = smallest_int_mode_for_size
10687 3266 : (GET_MODE_BITSIZE (mode) / 2).require ();
10688 7588 : move_max = GET_MODE_SIZE (mode);
10689 : }
10690 :
10691 : /* Try to fully unroll memmove of known size first. */
10692 12887 : if (count
10693 12887 : && ix86_expand_unroll_movmem (dst, src, destreg, srcreg, count,
10694 : mode))
10695 : return true;
10696 :
10697 11014 : rtx memset_vals[memset_val_max];
10698 11014 : rtx *memset_vals_p;
10699 11014 : if (issetmem)
10700 : {
10701 : /* Use vector mode if MODE size > word size. */
10702 1131 : unsigned int size = GET_MODE_SIZE (mode);
10703 1131 : poly_uint64 nunits;
10704 1131 : if (size > UNITS_PER_WORD)
10705 : {
10706 628 : nunits = size / GET_MODE_SIZE (QImode);
10707 628 : mode = mode_for_vector (QImode, nunits).require ();
10708 : }
10709 :
10710 : /* Populate MEMSET_VALS to expand memset. */
10711 1131 : rtx val_word;
10712 1131 : memset_vals[memset_val_byte] = memset_val_exp;
10713 1131 : if (memset_val_exp == const0_rtx || memset_val_exp == constm1_rtx)
10714 : val_word = memset_val_exp;
10715 : else
10716 657 : val_word = promote_duplicated_reg (word_mode, memset_val_exp);
10717 1131 : memset_vals[memset_val_word] = val_word;
10718 2262 : if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
10719 : {
10720 628 : if (memset_val_exp == const0_rtx)
10721 242 : memset_vals[memset_val_vector] = CONST0_RTX (mode);
10722 386 : else if (memset_val_exp == constm1_rtx)
10723 18 : memset_vals[memset_val_vector] = CONSTM1_RTX (mode);
10724 : else
10725 : {
10726 : /* Use the vector mode based on WORD_MODE to avoid extra
10727 : GPR moves. */
10728 736 : nunits = size / GET_MODE_SIZE (word_mode);
10729 368 : machine_mode vector_mode
10730 368 : = mode_for_vector (word_mode, nunits).require ();
10731 368 : rtx vector = promote_duplicated_reg (vector_mode,
10732 : val_word);
10733 368 : memset_vals[memset_val_vector]
10734 368 : = convert_to_mode (mode, vector, 1);
10735 : }
10736 : }
10737 : else
10738 503 : memset_vals[memset_val_vector] = nullptr;
10739 1131 : memset_vals_p = memset_vals;
10740 : }
10741 : else
10742 : memset_vals_p = nullptr;
10743 :
10744 11014 : rtx_code_label *done_label = gen_label_rtx ();
10745 :
10746 11014 : rtx_code_label *less_vec_label = nullptr;
10747 11014 : if (min_size == 0 || min_size < move_max)
10748 10769 : less_vec_label = gen_label_rtx ();
10749 :
10750 11014 : machine_mode count_mode = counter_mode (count_exp);
10751 :
10752 : /* Jump to LESS_VEC_LABEL if size < MOVE_MAX. */
10753 11014 : if (less_vec_label)
10754 10769 : emit_cmp_and_jump_insns (count_exp, GEN_INT (move_max), LTU,
10755 : nullptr, count_mode, 1,
10756 : less_vec_label);
10757 :
10758 11014 : rtx_code_label *more_2x_vec_label = nullptr;
10759 11014 : if (probable_max_size == 0 || probable_max_size > 2 * move_max)
10760 3314 : more_2x_vec_label = gen_label_rtx ();
10761 :
10762 : /* Jump to MORE_2X_VEC_LABEL if size > 2 * MOVE_MAX. */
10763 3314 : if (more_2x_vec_label)
10764 3314 : emit_cmp_and_jump_insns (count_exp, GEN_INT (2 * move_max), GTU,
10765 : nullptr, count_mode, 1,
10766 : more_2x_vec_label);
10767 :
10768 11014 : if (max_size != 1 && (min_size == 0 || min_size <= 2 * move_max))
10769 : {
10770 : /* Max size != 1, size >= MOVE_MAX and size <= 2 * MOVE_MAX. */
10771 10971 : ix86_expand_n_overlapping_move_set_or_movmem (dst, src,
10772 : memset_vals_p,
10773 : destreg, srcreg,
10774 : count_exp, mode, 2);
10775 10971 : emit_jump_insn (gen_jump (done_label));
10776 10971 : emit_barrier ();
10777 : }
10778 :
10779 11014 : if (less_vec_label)
10780 : {
10781 : /* Size < MOVE_MAX. */
10782 10769 : emit_label (less_vec_label);
10783 10769 : ix86_expand_less_move_set_or_movmem (dst, src, memset_vals_p,
10784 : destreg, srcreg, count_exp,
10785 : min_size, mode, done_label);
10786 10769 : emit_jump_insn (gen_jump (done_label));
10787 10769 : emit_barrier ();
10788 : }
10789 :
10790 11014 : if (more_2x_vec_label)
10791 : {
10792 : /* Size > 2 * MOVE_MAX and destination may overlap with source. */
10793 3314 : emit_label (more_2x_vec_label);
10794 :
10795 3314 : rtx_code_label *more_8x_vec_label = nullptr;
10796 3314 : if (probable_max_size == 0 || probable_max_size > 8 * move_max)
10797 1280 : more_8x_vec_label = gen_label_rtx ();
10798 :
10799 : /* Jump to MORE_8X_VEC_LABEL if size > 8 * MOVE_MAX. */
10800 1280 : if (more_8x_vec_label)
10801 1280 : emit_cmp_and_jump_insns (count_exp, GEN_INT (8 * move_max), GTU,
10802 : nullptr, count_mode, 1,
10803 : more_8x_vec_label);
10804 :
10805 3314 : rtx_code_label *last_4x_vec_label = nullptr;
10806 3314 : if (min_size == 0 || min_size <= 4 * move_max)
10807 3302 : last_4x_vec_label = gen_label_rtx ();
10808 :
10809 : /* Jump to LAST_4X_VEC_LABEL if size <= 4 * MOVE_MAX. */
10810 3302 : if (last_4x_vec_label)
10811 3302 : emit_cmp_and_jump_insns (count_exp, GEN_INT (4 * move_max), LEU,
10812 : nullptr, count_mode, 1,
10813 : last_4x_vec_label);
10814 :
10815 3314 : if (probable_max_size == 0 || probable_max_size > 4 * move_max)
10816 : {
10817 : /* Size > 4 * MOVE_MAX and size <= 8 * MOVE_MAX. */
10818 1671 : ix86_expand_n_overlapping_move_set_or_movmem (dst, src,
10819 : memset_vals_p,
10820 : destreg, srcreg,
10821 : count_exp, mode,
10822 : 8);
10823 1671 : emit_jump_insn (gen_jump (done_label));
10824 1671 : emit_barrier ();
10825 : }
10826 :
10827 3314 : if (last_4x_vec_label)
10828 : {
10829 : /* Size > 2 * MOVE_MAX and size <= 4 * MOVE_MAX. */
10830 3302 : emit_label (last_4x_vec_label);
10831 3302 : ix86_expand_n_overlapping_move_set_or_movmem (dst, src,
10832 : memset_vals_p,
10833 : destreg, srcreg,
10834 : count_exp, mode,
10835 : 4);
10836 3302 : emit_jump_insn (gen_jump (done_label));
10837 3302 : emit_barrier ();
10838 : }
10839 :
10840 3314 : if (more_8x_vec_label)
10841 : {
10842 : /* Size > 8 * MOVE_MAX. */
10843 1280 : emit_label (more_8x_vec_label);
10844 :
10845 1280 : rtx loop_count = gen_reg_rtx (count_mode);
10846 1280 : emit_move_insn (loop_count, count_exp);
10847 :
10848 1280 : rtx_code_label *more_8x_vec_backward_label;
10849 1280 : rtx base_destreg;
10850 1280 : rtx srcmem;
10851 1280 : rtx regs[4];
10852 1280 : if (iscpymem || issetmem)
10853 : {
10854 : /* Always store forward for memcpy and memset. */
10855 127 : more_8x_vec_backward_label = nullptr;
10856 127 : if (iscpymem)
10857 : {
10858 : /* Load the last 4 * MOVE_MAX for memcpy. */
10859 28 : ix86_expand_load_movmem (src, srcreg, count_exp, mode,
10860 : ARRAY_SIZE (regs), regs,
10861 : true);
10862 28 : srcmem = change_address (src, mode, srcreg);
10863 : }
10864 : else
10865 : {
10866 : /* Fill REGS with MEMSET_VALS for memset. */
10867 99 : rtx val = ix86_expand_memset_val (memset_vals, mode);
10868 495 : for (unsigned int i = 0; i < 4; i++)
10869 396 : regs[i] = val;
10870 : srcmem = nullptr;
10871 : }
10872 127 : base_destreg = gen_reg_rtx (GET_MODE (destreg));
10873 127 : emit_move_insn (base_destreg, destreg);
10874 : }
10875 : else
10876 : {
10877 : /* Jump to MORE_8X_VEC_BACKWARD_LABEL if source address is
10878 : lower than destination address. */
10879 1153 : more_8x_vec_backward_label = gen_label_rtx ();
10880 1153 : emit_cmp_and_jump_insns (srcreg, destreg, LTU, nullptr,
10881 1153 : GET_MODE (destreg), 1,
10882 : more_8x_vec_backward_label);
10883 :
10884 : /* Skip if source == destination which is less common. */
10885 1153 : emit_cmp_and_jump_insns (srcreg, destreg, EQ, nullptr,
10886 1153 : GET_MODE (destreg), 1, done_label,
10887 : profile_probability::unlikely ());
10888 :
10889 1153 : base_destreg = gen_reg_rtx (GET_MODE (destreg));
10890 1153 : emit_move_insn (base_destreg, destreg);
10891 :
10892 : /* Load the last 4 * MOVE_MAX. */
10893 1153 : ix86_expand_load_movmem (src, srcreg, count_exp, mode,
10894 : ARRAY_SIZE (regs), regs, true);
10895 :
10896 1153 : srcmem = change_address (src, mode, srcreg);
10897 : }
10898 :
10899 1280 : rtx destmem = change_address (dst, mode, destreg);
10900 :
10901 : /* Copy forward with a 4 * MOVE_MAX loop. */
10902 1280 : rtx_code_label *loop_4x_vec_forward_label = gen_label_rtx ();
10903 1280 : emit_label (loop_4x_vec_forward_label);
10904 :
10905 1280 : ix86_expand_n_move_set_or_movmem (destmem, srcmem,
10906 : memset_vals_p, mode, 4,
10907 : true);
10908 :
10909 1280 : rtx tmp;
10910 1280 : rtx delta = GEN_INT (4 * MOVE_MAX);
10911 :
10912 : /* Decrement LOOP_COUNT by 4 * MOVE_MAX. */
10913 1280 : tmp = expand_simple_binop (GET_MODE (loop_count), MINUS,
10914 : loop_count, delta, nullptr, 1,
10915 : OPTAB_DIRECT);
10916 1280 : if (tmp != loop_count)
10917 1280 : emit_move_insn (loop_count, tmp);
10918 :
10919 : /* Increment DESTREG and SRCREG by 4 * MOVE_MAX. */
10920 1280 : tmp = expand_simple_binop (GET_MODE (destreg), PLUS,
10921 : destreg, delta, nullptr, 1,
10922 : OPTAB_DIRECT);
10923 1280 : if (tmp != destreg)
10924 1280 : emit_move_insn (destreg, tmp);
10925 1280 : if (!issetmem)
10926 : {
10927 1181 : tmp = expand_simple_binop (GET_MODE (srcreg), PLUS,
10928 : srcreg, delta, nullptr, 1,
10929 : OPTAB_DIRECT);
10930 1181 : if (tmp != srcreg)
10931 1181 : emit_move_insn (srcreg, tmp);
10932 : }
10933 :
10934 : /* Stop if LOOP_EXP <= 4 * MOVE_MAX. */
10935 1280 : emit_cmp_and_jump_insns (loop_count, delta, GTU, nullptr,
10936 1280 : GET_MODE (loop_count), 1,
10937 : loop_4x_vec_forward_label);
10938 :
10939 : /* Store the last 4 * MOVE_MAX. */
10940 1280 : ix86_expand_store_movmem (dst, base_destreg, count_exp, mode,
10941 : ARRAY_SIZE (regs), regs, true);
10942 :
10943 1280 : emit_jump_insn (gen_jump (done_label));
10944 1280 : emit_barrier ();
10945 :
10946 1280 : if (more_8x_vec_backward_label)
10947 : {
10948 : /* Copy backward with a 4 * MOVE_MAX loop. */
10949 1153 : emit_label (more_8x_vec_backward_label);
10950 :
10951 1153 : base_destreg = gen_reg_rtx (GET_MODE (destreg));
10952 1153 : emit_move_insn (base_destreg, destreg);
10953 :
10954 : /* Load the first 4 * MOVE_MAX. */
10955 1153 : ix86_expand_load_movmem (src, srcreg, count_exp, mode,
10956 : ARRAY_SIZE (regs), regs, false);
10957 :
10958 : /* Increment DESTREG and SRCREG by COUNT_EXP. */
10959 1153 : tmp = expand_simple_binop (GET_MODE (destreg), PLUS,
10960 : destreg, count_exp, nullptr, 1,
10961 : OPTAB_DIRECT);
10962 1153 : if (tmp != destreg)
10963 1153 : emit_move_insn (destreg, tmp);
10964 1153 : tmp = expand_simple_binop (GET_MODE (srcreg), PLUS, srcreg,
10965 : count_exp, nullptr, 1,
10966 : OPTAB_DIRECT);
10967 1153 : if (tmp != srcreg)
10968 1153 : emit_move_insn (srcreg, tmp);
10969 :
10970 1153 : srcmem = change_address (src, mode, srcreg);
10971 1153 : destmem = change_address (dst, mode, destreg);
10972 2306 : rtx step = GEN_INT (-GET_MODE_SIZE (mode));
10973 1153 : srcmem = offset_address (srcmem, step,
10974 1153 : GET_MODE_SIZE (mode));
10975 1153 : destmem = offset_address (destmem, step,
10976 1153 : GET_MODE_SIZE (mode));
10977 :
10978 1153 : rtx_code_label *loop_4x_vec_backward_label
10979 1153 : = gen_label_rtx ();
10980 1153 : emit_label (loop_4x_vec_backward_label);
10981 :
10982 1153 : ix86_expand_n_move_set_or_movmem (destmem, srcmem,
10983 : memset_vals_p, mode, 4,
10984 : false);
10985 :
10986 : /* Decrement LOOP_COUNT by 4 * MOVE_MAX. */
10987 1153 : tmp = expand_simple_binop (GET_MODE (loop_count), MINUS,
10988 : loop_count, delta, nullptr, 1,
10989 : OPTAB_DIRECT);
10990 1153 : if (tmp != loop_count)
10991 1153 : emit_move_insn (loop_count, tmp);
10992 :
10993 : /* Decrement DESTREG and SRCREG by 4 * MOVE_MAX. */
10994 1153 : tmp = expand_simple_binop (GET_MODE (destreg), MINUS,
10995 : destreg, delta, nullptr, 1,
10996 : OPTAB_DIRECT);
10997 1153 : if (tmp != destreg)
10998 1153 : emit_move_insn (destreg, tmp);
10999 1153 : tmp = expand_simple_binop (GET_MODE (srcreg), MINUS,
11000 : srcreg, delta, nullptr, 1,
11001 : OPTAB_DIRECT);
11002 1153 : if (tmp != srcreg)
11003 1153 : emit_move_insn (srcreg, tmp);
11004 :
11005 : /* Stop if LOOP_EXP <= 4 * MOVE_MAX. */
11006 1153 : emit_cmp_and_jump_insns (loop_count, delta, GTU, nullptr,
11007 1153 : GET_MODE (loop_count), 1,
11008 : loop_4x_vec_backward_label);
11009 :
11010 : /* Store the first 4 * MOVE_MAX. */
11011 1153 : ix86_expand_store_movmem (dst, base_destreg, count_exp,
11012 : mode, ARRAY_SIZE (regs), regs,
11013 : false);
11014 :
11015 1153 : emit_jump_insn (gen_jump (done_label));
11016 1153 : emit_barrier ();
11017 : }
11018 : }
11019 : }
11020 :
11021 11014 : emit_label (done_label);
11022 :
11023 11014 : return true;
11024 : }
11025 :
11026 : /* Expand cmpstrn or memcmp. */
11027 :
11028 : bool
11029 171425 : ix86_expand_cmpstrn_or_cmpmem (rtx result, rtx src1, rtx src2,
11030 : rtx length, rtx align, bool is_cmpstrn)
11031 : {
11032 : /* Expand strncmp and memcmp only with -minline-all-stringops since
11033 : "repz cmpsb" can be much slower than strncmp and memcmp functions
11034 : implemented with vector instructions, see
11035 :
11036 : https://gcc.gnu.org/bugzilla/show_bug.cgi?id=43052
11037 : */
11038 171425 : if (!TARGET_INLINE_ALL_STRINGOPS)
11039 : return false;
11040 :
11041 : /* Can't use this if the user has appropriated ecx, esi or edi. */
11042 5796 : if (fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG])
11043 : return false;
11044 :
11045 5796 : if (is_cmpstrn)
11046 : {
11047 : /* For strncmp, length is the maximum length, which can be larger
11048 : than actual string lengths. We can expand the cmpstrn pattern
11049 : to "repz cmpsb" only if one of the strings is a constant so
11050 : that expand_builtin_strncmp() can write the length argument to
11051 : be the minimum of the const string length and the actual length
11052 : argument. Otherwise, "repz cmpsb" may pass the 0 byte. */
11053 69 : tree t1 = MEM_EXPR (src1);
11054 69 : tree t2 = MEM_EXPR (src2);
11055 138 : if (!((t1 && TREE_CODE (t1) == MEM_REF
11056 69 : && TREE_CODE (TREE_OPERAND (t1, 0)) == ADDR_EXPR
11057 0 : && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (t1, 0), 0))
11058 : == STRING_CST))
11059 69 : || (t2 && TREE_CODE (t2) == MEM_REF
11060 69 : && TREE_CODE (TREE_OPERAND (t2, 0)) == ADDR_EXPR
11061 69 : && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (t2, 0), 0))
11062 : == STRING_CST))))
11063 : return false;
11064 : }
11065 :
11066 5796 : rtx addr1 = copy_addr_to_reg (XEXP (src1, 0));
11067 5796 : rtx addr2 = copy_addr_to_reg (XEXP (src2, 0));
11068 5796 : if (addr1 != XEXP (src1, 0))
11069 5796 : src1 = replace_equiv_address_nv (src1, addr1);
11070 5796 : if (addr2 != XEXP (src2, 0))
11071 5796 : src2 = replace_equiv_address_nv (src2, addr2);
11072 :
11073 : /* NB: Make a copy of the data length to avoid changing the original
11074 : data length by cmpstrnqi patterns. */
11075 5796 : length = ix86_zero_extend_to_Pmode (length);
11076 8711 : rtx lengthreg = gen_reg_rtx (Pmode);
11077 5796 : emit_move_insn (lengthreg, length);
11078 :
11079 : /* If we are testing strict equality, we can use known alignment to
11080 : good advantage. This may be possible with combine, particularly
11081 : once cc0 is dead. */
11082 5796 : if (CONST_INT_P (length))
11083 : {
11084 0 : if (length == const0_rtx)
11085 : {
11086 0 : emit_move_insn (result, const0_rtx);
11087 0 : return true;
11088 : }
11089 0 : emit_insn (gen_cmpstrnqi_nz_1 (addr1, addr2, lengthreg, align,
11090 : src1, src2));
11091 : }
11092 : else
11093 : {
11094 8711 : emit_insn (gen_cmp_1 (Pmode, lengthreg, lengthreg));
11095 5796 : emit_insn (gen_cmpstrnqi_1 (addr1, addr2, lengthreg, align,
11096 : src1, src2));
11097 : }
11098 :
11099 5796 : rtx out = gen_lowpart (QImode, result);
11100 5796 : emit_insn (gen_cmpintqi (out));
11101 5796 : emit_move_insn (result, gen_rtx_SIGN_EXTEND (SImode, out));
11102 :
11103 5796 : return true;
11104 : }
11105 :
11106 : /* Expand the appropriate insns for doing strlen if not just doing
11107 : repnz; scasb
11108 :
11109 : out = result, initialized with the start address
11110 : align_rtx = alignment of the address.
11111 : scratch = scratch register, initialized with the startaddress when
11112 : not aligned, otherwise undefined
11113 :
11114 : This is just the body. It needs the initializations mentioned above and
11115 : some address computing at the end. These things are done in i386.md. */
11116 :
11117 : static void
11118 11 : ix86_expand_strlensi_unroll_1 (rtx out, rtx src, rtx align_rtx)
11119 : {
11120 11 : int align;
11121 11 : rtx tmp;
11122 11 : rtx_code_label *align_2_label = NULL;
11123 11 : rtx_code_label *align_3_label = NULL;
11124 11 : rtx_code_label *align_4_label = gen_label_rtx ();
11125 11 : rtx_code_label *end_0_label = gen_label_rtx ();
11126 11 : rtx mem;
11127 11 : rtx tmpreg = gen_reg_rtx (SImode);
11128 11 : rtx scratch = gen_reg_rtx (SImode);
11129 11 : rtx cmp;
11130 :
11131 11 : align = 0;
11132 11 : if (CONST_INT_P (align_rtx))
11133 11 : align = INTVAL (align_rtx);
11134 :
11135 : /* Loop to check 1..3 bytes for null to get an aligned pointer. */
11136 :
11137 : /* Is there a known alignment and is it less than 4? */
11138 11 : if (align < 4)
11139 : {
11140 15 : rtx scratch1 = gen_reg_rtx (Pmode);
11141 11 : emit_move_insn (scratch1, out);
11142 : /* Is there a known alignment and is it not 2? */
11143 11 : if (align != 2)
11144 : {
11145 11 : align_3_label = gen_label_rtx (); /* Label when aligned to 3-byte */
11146 11 : align_2_label = gen_label_rtx (); /* Label when aligned to 2-byte */
11147 :
11148 : /* Leave just the 3 lower bits. */
11149 15 : align_rtx = expand_binop (Pmode, and_optab, scratch1, GEN_INT (3),
11150 : NULL_RTX, 0, OPTAB_WIDEN);
11151 :
11152 15 : emit_cmp_and_jump_insns (align_rtx, const0_rtx, EQ, NULL,
11153 11 : Pmode, 1, align_4_label);
11154 15 : emit_cmp_and_jump_insns (align_rtx, const2_rtx, EQ, NULL,
11155 11 : Pmode, 1, align_2_label);
11156 15 : emit_cmp_and_jump_insns (align_rtx, const2_rtx, GTU, NULL,
11157 11 : Pmode, 1, align_3_label);
11158 : }
11159 : else
11160 : {
11161 : /* Since the alignment is 2, we have to check 2 or 0 bytes;
11162 : check if is aligned to 4 - byte. */
11163 :
11164 0 : align_rtx = expand_binop (Pmode, and_optab, scratch1, const2_rtx,
11165 : NULL_RTX, 0, OPTAB_WIDEN);
11166 :
11167 0 : emit_cmp_and_jump_insns (align_rtx, const0_rtx, EQ, NULL,
11168 0 : Pmode, 1, align_4_label);
11169 : }
11170 :
11171 11 : mem = change_address (src, QImode, out);
11172 :
11173 : /* Now compare the bytes. */
11174 :
11175 : /* Compare the first n unaligned byte on a byte per byte basis. */
11176 11 : emit_cmp_and_jump_insns (mem, const0_rtx, EQ, NULL,
11177 : QImode, 1, end_0_label);
11178 :
11179 : /* Increment the address. */
11180 11 : emit_insn (gen_add2_insn (out, const1_rtx));
11181 :
11182 : /* Not needed with an alignment of 2 */
11183 11 : if (align != 2)
11184 : {
11185 11 : emit_label (align_2_label);
11186 :
11187 11 : emit_cmp_and_jump_insns (mem, const0_rtx, EQ, NULL, QImode, 1,
11188 : end_0_label);
11189 :
11190 11 : emit_insn (gen_add2_insn (out, const1_rtx));
11191 :
11192 11 : emit_label (align_3_label);
11193 : }
11194 :
11195 11 : emit_cmp_and_jump_insns (mem, const0_rtx, EQ, NULL, QImode, 1,
11196 : end_0_label);
11197 :
11198 11 : emit_insn (gen_add2_insn (out, const1_rtx));
11199 : }
11200 :
11201 : /* Generate loop to check 4 bytes at a time. It is not a good idea to
11202 : align this loop. It gives only huge programs, but does not help to
11203 : speed up. */
11204 11 : emit_label (align_4_label);
11205 :
11206 11 : mem = change_address (src, SImode, out);
11207 11 : emit_move_insn (scratch, mem);
11208 11 : emit_insn (gen_add2_insn (out, GEN_INT (4)));
11209 :
11210 : /* This formula yields a nonzero result iff one of the bytes is zero.
11211 : This saves three branches inside loop and many cycles. */
11212 :
11213 11 : emit_insn (gen_addsi3 (tmpreg, scratch, GEN_INT (-0x01010101)));
11214 11 : emit_insn (gen_one_cmplsi2 (scratch, scratch));
11215 11 : emit_insn (gen_andsi3 (tmpreg, tmpreg, scratch));
11216 11 : emit_insn (gen_andsi3 (tmpreg, tmpreg,
11217 : gen_int_mode (0x80808080, SImode)));
11218 11 : emit_cmp_and_jump_insns (tmpreg, const0_rtx, EQ, 0, SImode, 1,
11219 : align_4_label);
11220 :
11221 11 : if (TARGET_CMOVE)
11222 : {
11223 11 : rtx reg = gen_reg_rtx (SImode);
11224 15 : rtx reg2 = gen_reg_rtx (Pmode);
11225 11 : emit_move_insn (reg, tmpreg);
11226 11 : emit_insn (gen_lshrsi3 (reg, reg, GEN_INT (16)));
11227 :
11228 : /* If zero is not in the first two bytes, move two bytes forward. */
11229 11 : emit_insn (gen_testsi_ccno_1 (tmpreg, GEN_INT (0x8080)));
11230 11 : tmp = gen_rtx_REG (CCNOmode, FLAGS_REG);
11231 11 : tmp = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
11232 11 : emit_insn (gen_rtx_SET (tmpreg,
11233 : gen_rtx_IF_THEN_ELSE (SImode, tmp,
11234 : reg,
11235 : tmpreg)));
11236 : /* Emit lea manually to avoid clobbering of flags. */
11237 15 : emit_insn (gen_rtx_SET (reg2, plus_constant (Pmode, out, 2)));
11238 :
11239 11 : tmp = gen_rtx_REG (CCNOmode, FLAGS_REG);
11240 11 : tmp = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
11241 15 : emit_insn (gen_rtx_SET (out,
11242 : gen_rtx_IF_THEN_ELSE (Pmode, tmp,
11243 : reg2,
11244 : out)));
11245 11 : }
11246 : else
11247 : {
11248 0 : rtx_code_label *end_2_label = gen_label_rtx ();
11249 : /* Is zero in the first two bytes? */
11250 :
11251 0 : emit_insn (gen_testsi_ccno_1 (tmpreg, GEN_INT (0x8080)));
11252 0 : tmp = gen_rtx_REG (CCNOmode, FLAGS_REG);
11253 0 : tmp = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
11254 0 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
11255 : gen_rtx_LABEL_REF (VOIDmode, end_2_label),
11256 : pc_rtx);
11257 0 : tmp = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
11258 0 : JUMP_LABEL (tmp) = end_2_label;
11259 :
11260 : /* Not in the first two. Move two bytes forward. */
11261 0 : emit_insn (gen_lshrsi3 (tmpreg, tmpreg, GEN_INT (16)));
11262 0 : emit_insn (gen_add2_insn (out, const2_rtx));
11263 :
11264 0 : emit_label (end_2_label);
11265 :
11266 : }
11267 :
11268 : /* Avoid branch in fixing the byte. */
11269 11 : tmpreg = gen_lowpart (QImode, tmpreg);
11270 11 : emit_insn (gen_addqi3_cconly_overflow (tmpreg, tmpreg));
11271 11 : tmp = gen_rtx_REG (CCmode, FLAGS_REG);
11272 11 : cmp = gen_rtx_LTU (VOIDmode, tmp, const0_rtx);
11273 15 : emit_insn (gen_sub3_carry (Pmode, out, out, GEN_INT (3), tmp, cmp));
11274 :
11275 11 : emit_label (end_0_label);
11276 11 : }
11277 :
11278 : /* Expand strlen. */
11279 :
11280 : bool
11281 14609 : ix86_expand_strlen (rtx out, rtx src, rtx eoschar, rtx align)
11282 : {
11283 14609 : if (TARGET_UNROLL_STRLEN
11284 14609 : && TARGET_INLINE_ALL_STRINGOPS
11285 11 : && eoschar == const0_rtx
11286 11 : && optimize > 1)
11287 : {
11288 : /* The generic case of strlen expander is long. Avoid it's
11289 : expanding unless TARGET_INLINE_ALL_STRINGOPS. */
11290 15 : rtx addr = force_reg (Pmode, XEXP (src, 0));
11291 : /* Well it seems that some optimizer does not combine a call like
11292 : foo(strlen(bar), strlen(bar));
11293 : when the move and the subtraction is done here. It does calculate
11294 : the length just once when these instructions are done inside of
11295 : output_strlen_unroll(). But I think since &bar[strlen(bar)] is
11296 : often used and I use one fewer register for the lifetime of
11297 : output_strlen_unroll() this is better. */
11298 :
11299 11 : emit_move_insn (out, addr);
11300 :
11301 11 : ix86_expand_strlensi_unroll_1 (out, src, align);
11302 :
11303 : /* strlensi_unroll_1 returns the address of the zero at the end of
11304 : the string, like memchr(), so compute the length by subtracting
11305 : the start address. */
11306 11 : emit_insn (gen_sub2_insn (out, addr));
11307 11 : return true;
11308 : }
11309 : else
11310 : return false;
11311 : }
11312 :
11313 : /* For given symbol (function) construct code to compute address of it's PLT
11314 : entry in large x86-64 PIC model. */
11315 :
11316 : static rtx
11317 34 : construct_plt_address (rtx symbol)
11318 : {
11319 34 : rtx tmp, unspec;
11320 :
11321 34 : gcc_assert (SYMBOL_REF_P (symbol));
11322 34 : gcc_assert (ix86_cmodel == CM_LARGE_PIC && !TARGET_PECOFF);
11323 34 : gcc_assert (Pmode == DImode);
11324 :
11325 34 : tmp = gen_reg_rtx (Pmode);
11326 34 : unspec = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, symbol), UNSPEC_PLTOFF);
11327 :
11328 34 : emit_move_insn (tmp, gen_rtx_CONST (Pmode, unspec));
11329 34 : emit_insn (gen_add2_insn (tmp, pic_offset_table_rtx));
11330 34 : return tmp;
11331 : }
11332 :
11333 : rtx_insn *
11334 6360428 : ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1,
11335 : rtx callarg2,
11336 : rtx pop, bool sibcall)
11337 : {
11338 6360428 : rtx vec[3];
11339 6360428 : rtx use = NULL, call;
11340 6360428 : unsigned int vec_len = 0;
11341 6360428 : tree fndecl;
11342 :
11343 6360428 : if (SYMBOL_REF_P (XEXP (fnaddr, 0)))
11344 : {
11345 6174329 : fndecl = SYMBOL_REF_DECL (XEXP (fnaddr, 0));
11346 6174329 : if (fndecl)
11347 : {
11348 5914309 : if (lookup_attribute ("interrupt",
11349 5914309 : TYPE_ATTRIBUTES (TREE_TYPE (fndecl))))
11350 1 : error ("interrupt service routine cannot be called directly");
11351 5914309 : if (fndecl == current_function_decl
11352 5914309 : && decl_binds_to_current_def_p (fndecl))
11353 11316 : cfun->machine->recursive_function = true;
11354 : }
11355 : }
11356 : else
11357 : fndecl = NULL_TREE;
11358 :
11359 6360428 : if (pop == const0_rtx)
11360 0 : pop = NULL;
11361 6360428 : gcc_assert (!TARGET_64BIT || !pop);
11362 :
11363 6360428 : rtx addr = XEXP (fnaddr, 0);
11364 6360428 : if (TARGET_MACHO && !TARGET_64BIT)
11365 : {
11366 : #if TARGET_MACHO
11367 : if (flag_pic && SYMBOL_REF_P (XEXP (fnaddr, 0)))
11368 : fnaddr = machopic_indirect_call_target (fnaddr);
11369 : #endif
11370 : }
11371 : else
11372 : {
11373 : /* Static functions and indirect calls don't need the pic register. Also,
11374 : check if PLT was explicitly avoided via no-plt or "noplt" attribute, making
11375 : it an indirect call. */
11376 6360428 : if (flag_pic
11377 530877 : && SYMBOL_REF_P (addr)
11378 6864341 : && ix86_call_use_plt_p (addr))
11379 : {
11380 402541 : if (flag_plt
11381 402541 : && (SYMBOL_REF_DECL (addr) == NULL_TREE
11382 402507 : || !lookup_attribute ("noplt",
11383 402507 : DECL_ATTRIBUTES (SYMBOL_REF_DECL (addr)))))
11384 : {
11385 402506 : if (!TARGET_64BIT
11386 223651 : || (ix86_cmodel == CM_LARGE_PIC
11387 : && DEFAULT_ABI != MS_ABI))
11388 : {
11389 536599 : use_reg (&use, gen_rtx_REG (Pmode,
11390 : REAL_PIC_OFFSET_TABLE_REGNUM));
11391 178889 : if (ix86_use_pseudo_pic_reg ())
11392 357744 : emit_move_insn (gen_rtx_REG (Pmode,
11393 178889 : REAL_PIC_OFFSET_TABLE_REGNUM),
11394 : pic_offset_table_rtx);
11395 : }
11396 : }
11397 35 : else if (!TARGET_PECOFF && !TARGET_MACHO)
11398 : {
11399 35 : if (TARGET_64BIT
11400 35 : && ix86_cmodel == CM_LARGE_PIC
11401 : && DEFAULT_ABI != MS_ABI)
11402 : {
11403 1 : fnaddr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr),
11404 : UNSPEC_GOT);
11405 1 : fnaddr = gen_rtx_CONST (Pmode, fnaddr);
11406 1 : fnaddr = force_reg (Pmode, fnaddr);
11407 1 : fnaddr = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, fnaddr);
11408 : }
11409 34 : else if (TARGET_64BIT)
11410 : {
11411 38 : fnaddr = gen_rtx_UNSPEC (Pmode,
11412 : gen_rtvec (1, addr),
11413 : UNSPEC_GOTPCREL);
11414 38 : fnaddr = gen_rtx_CONST (Pmode, fnaddr);
11415 : }
11416 : else
11417 : {
11418 0 : fnaddr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr),
11419 : UNSPEC_GOT);
11420 0 : fnaddr = gen_rtx_CONST (Pmode, fnaddr);
11421 0 : fnaddr = gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
11422 : fnaddr);
11423 : }
11424 39 : fnaddr = gen_const_mem (Pmode, fnaddr);
11425 : /* Pmode may not be the same as word_mode for x32, which
11426 : doesn't support indirect branch via 32-bit memory slot.
11427 : Since x32 GOT slot is 64 bit with zero upper 32 bits,
11428 : indirect branch via x32 GOT slot is OK. */
11429 35 : if (GET_MODE (fnaddr) != word_mode)
11430 4 : fnaddr = gen_rtx_ZERO_EXTEND (word_mode, fnaddr);
11431 35 : fnaddr = gen_rtx_MEM (QImode, fnaddr);
11432 : }
11433 : }
11434 : }
11435 :
11436 : /* Skip setting up RAX register for -mskip-rax-setup when there are no
11437 : parameters passed in vector registers. */
11438 6360428 : if (TARGET_64BIT
11439 5520120 : && (INTVAL (callarg2) > 0
11440 5458800 : || (INTVAL (callarg2) == 0
11441 326718 : && (TARGET_SSE || !flag_skip_rax_setup))))
11442 : {
11443 388036 : rtx al = gen_rtx_REG (QImode, AX_REG);
11444 388036 : emit_move_insn (al, callarg2);
11445 388036 : use_reg (&use, al);
11446 : }
11447 :
11448 6360428 : if (ix86_cmodel == CM_LARGE_PIC
11449 : && !TARGET_PECOFF
11450 45 : && MEM_P (fnaddr)
11451 45 : && SYMBOL_REF_P (XEXP (fnaddr, 0))
11452 6360465 : && !local_symbolic_operand (XEXP (fnaddr, 0), VOIDmode))
11453 34 : fnaddr = gen_rtx_MEM (QImode, construct_plt_address (XEXP (fnaddr, 0)));
11454 : /* Since x32 GOT slot is 64 bit with zero upper 32 bits, indirect
11455 : branch via x32 GOT slot is OK. */
11456 6360394 : else if (TARGET_X32
11457 74 : && MEM_P (fnaddr)
11458 74 : && GET_CODE (XEXP (fnaddr, 0)) == ZERO_EXTEND
11459 8 : && GOT_memory_operand (XEXP (XEXP (fnaddr, 0), 0), Pmode)
11460 6360398 : && !TARGET_INDIRECT_BRANCH_REGISTER)
11461 : ;
11462 6360394 : else if (sibcall
11463 6360394 : ? !sibcall_insn_operand (XEXP (fnaddr, 0), word_mode)
11464 6229910 : : !call_insn_operand (XEXP (fnaddr, 0), word_mode))
11465 : {
11466 532 : fnaddr = convert_to_mode (word_mode, XEXP (fnaddr, 0), 1);
11467 532 : fnaddr = gen_rtx_MEM (QImode, copy_to_mode_reg (word_mode, fnaddr));
11468 : }
11469 :
11470 : /* PR100665: Hwasan may tag code pointer which is not supported by LAM,
11471 : mask off code pointers here.
11472 : TODO: also need to handle indirect jump. */
11473 6361456 : if (ix86_memtag_can_tag_addresses () && !fndecl
11474 6360452 : && sanitize_flags_p (SANITIZE_HWADDRESS))
11475 : {
11476 24 : rtx untagged_addr = ix86_memtag_untagged_pointer (XEXP (fnaddr, 0),
11477 : NULL_RTX);
11478 24 : fnaddr = gen_rtx_MEM (QImode, untagged_addr);
11479 : }
11480 :
11481 6360428 : call = gen_rtx_CALL (VOIDmode, fnaddr, callarg1);
11482 :
11483 6360428 : if (retval)
11484 2507173 : call = gen_rtx_SET (retval, call);
11485 6360428 : vec[vec_len++] = call;
11486 :
11487 6360428 : if (pop)
11488 : {
11489 450660 : pop = gen_rtx_PLUS (Pmode, stack_pointer_rtx, pop);
11490 225330 : pop = gen_rtx_SET (stack_pointer_rtx, pop);
11491 225330 : vec[vec_len++] = pop;
11492 : }
11493 :
11494 : /* Set here, but it may get cleared later. */
11495 5520120 : if (TARGET_64BIT_MS_ABI
11496 73426 : && (!callarg2 || INTVAL (callarg2) != -2)
11497 6426731 : && TARGET_CALL_MS2SYSV_XLOGUES)
11498 : {
11499 7046 : if (!TARGET_SSE)
11500 : ;
11501 :
11502 : /* Don't break hot-patched functions. */
11503 7046 : else if (ix86_function_ms_hook_prologue (current_function_decl))
11504 : ;
11505 :
11506 : /* TODO: Cases not yet examined. */
11507 7046 : else if (flag_split_stack)
11508 0 : warn_once_call_ms2sysv_xlogues ("-fsplit-stack");
11509 :
11510 : else
11511 : {
11512 7046 : gcc_assert (!reload_completed);
11513 7046 : cfun->machine->call_ms2sysv = true;
11514 : }
11515 : }
11516 :
11517 6360428 : if (TARGET_MACHO && TARGET_64BIT && !sibcall
11518 : && ((SYMBOL_REF_P (addr) && !SYMBOL_REF_LOCAL_P (addr))
11519 : || !fndecl || TREE_PUBLIC (fndecl)))
11520 : {
11521 : /* We allow public functions defined in a TU to bind locally for PIC
11522 : code (the default) on 64bit Mach-O.
11523 : If such functions are not inlined, we cannot tell at compile-time if
11524 : they will be called via the lazy symbol resolver (this can depend on
11525 : options given at link-time). Therefore, we must assume that the lazy
11526 : resolver could be used which clobbers R11 and R10. */
11527 : clobber_reg (&use, gen_rtx_REG (DImode, R11_REG));
11528 : clobber_reg (&use, gen_rtx_REG (DImode, R10_REG));
11529 : }
11530 :
11531 6360428 : if (vec_len > 1)
11532 225330 : call = gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (vec_len, vec));
11533 6360428 : rtx_insn *call_insn = emit_call_insn (call);
11534 6360428 : if (use)
11535 566924 : CALL_INSN_FUNCTION_USAGE (call_insn) = use;
11536 :
11537 6360428 : return call_insn;
11538 : }
11539 :
11540 : /* Split simple return with popping POPC bytes from stack to indirect
11541 : branch with stack adjustment . */
11542 :
11543 : void
11544 0 : ix86_split_simple_return_pop_internal (rtx popc)
11545 : {
11546 0 : struct machine_function *m = cfun->machine;
11547 0 : rtx ecx = gen_rtx_REG (SImode, CX_REG);
11548 0 : rtx_insn *insn;
11549 :
11550 : /* There is no "pascal" calling convention in any 64bit ABI. */
11551 0 : gcc_assert (!TARGET_64BIT);
11552 :
11553 0 : insn = emit_insn (gen_pop (ecx));
11554 0 : m->fs.cfa_offset -= UNITS_PER_WORD;
11555 0 : m->fs.sp_offset -= UNITS_PER_WORD;
11556 :
11557 0 : rtx x = plus_constant (Pmode, stack_pointer_rtx, UNITS_PER_WORD);
11558 0 : x = gen_rtx_SET (stack_pointer_rtx, x);
11559 0 : add_reg_note (insn, REG_CFA_ADJUST_CFA, x);
11560 0 : add_reg_note (insn, REG_CFA_REGISTER, gen_rtx_SET (ecx, pc_rtx));
11561 0 : RTX_FRAME_RELATED_P (insn) = 1;
11562 :
11563 0 : x = gen_rtx_PLUS (Pmode, stack_pointer_rtx, popc);
11564 0 : x = gen_rtx_SET (stack_pointer_rtx, x);
11565 0 : insn = emit_insn (x);
11566 0 : add_reg_note (insn, REG_CFA_ADJUST_CFA, x);
11567 0 : RTX_FRAME_RELATED_P (insn) = 1;
11568 :
11569 : /* Now return address is in ECX. */
11570 0 : emit_jump_insn (gen_simple_return_indirect_internal (ecx));
11571 0 : }
11572 :
11573 : /* Errors in the source file can cause expand_expr to return const0_rtx
11574 : where we expect a vector. To avoid crashing, use one of the vector
11575 : clear instructions. */
11576 :
11577 : static rtx
11578 199734 : safe_vector_operand (rtx x, machine_mode mode)
11579 : {
11580 0 : if (x == const0_rtx)
11581 0 : x = CONST0_RTX (mode);
11582 24 : return x;
11583 : }
11584 :
11585 : /* Subroutine of ix86_expand_builtin to take care of binop insns. */
11586 :
11587 : static rtx
11588 8991 : ix86_expand_binop_builtin (enum insn_code icode, tree exp, rtx target)
11589 : {
11590 8991 : rtx pat;
11591 8991 : tree arg0 = CALL_EXPR_ARG (exp, 0);
11592 8991 : tree arg1 = CALL_EXPR_ARG (exp, 1);
11593 8991 : rtx op0 = expand_normal (arg0);
11594 8991 : rtx op1 = expand_normal (arg1);
11595 8991 : machine_mode tmode = insn_data[icode].operand[0].mode;
11596 8991 : machine_mode mode0 = insn_data[icode].operand[1].mode;
11597 8991 : machine_mode mode1 = insn_data[icode].operand[2].mode;
11598 :
11599 8991 : if (VECTOR_MODE_P (mode0))
11600 8980 : op0 = safe_vector_operand (op0, mode0);
11601 8991 : if (VECTOR_MODE_P (mode1))
11602 8844 : op1 = safe_vector_operand (op1, mode1);
11603 :
11604 2836 : if (optimize || !target
11605 2836 : || GET_MODE (target) != tmode
11606 11827 : || !insn_data[icode].operand[0].predicate (target, tmode))
11607 6208 : target = gen_reg_rtx (tmode);
11608 :
11609 8991 : if (GET_MODE (op1) == SImode && mode1 == TImode)
11610 : {
11611 0 : rtx x = gen_reg_rtx (V4SImode);
11612 0 : emit_insn (gen_sse2_loadd (x, op1));
11613 0 : op1 = gen_lowpart (TImode, x);
11614 : }
11615 :
11616 8991 : if (!insn_data[icode].operand[1].predicate (op0, mode0))
11617 1393 : op0 = copy_to_mode_reg (mode0, op0);
11618 8991 : if (!insn_data[icode].operand[2].predicate (op1, mode1))
11619 818 : op1 = copy_to_mode_reg (mode1, op1);
11620 :
11621 8991 : pat = GEN_FCN (icode) (target, op0, op1);
11622 8991 : if (! pat)
11623 : return 0;
11624 :
11625 8991 : emit_insn (pat);
11626 :
11627 8991 : return target;
11628 : }
11629 :
11630 : /* Subroutine of ix86_expand_builtin to take care of 2-4 argument insns. */
11631 :
11632 : static rtx
11633 1813 : ix86_expand_multi_arg_builtin (enum insn_code icode, tree exp, rtx target,
11634 : enum ix86_builtin_func_type m_type,
11635 : enum rtx_code sub_code)
11636 : {
11637 1813 : rtx pat;
11638 1813 : unsigned int i, nargs;
11639 1813 : bool comparison_p = false;
11640 1813 : bool tf_p = false;
11641 1813 : bool last_arg_constant = false;
11642 1813 : int num_memory = 0;
11643 1813 : rtx xops[4];
11644 :
11645 1813 : machine_mode tmode = insn_data[icode].operand[0].mode;
11646 :
11647 1813 : switch (m_type)
11648 : {
11649 : case MULTI_ARG_4_DF2_DI_I:
11650 : case MULTI_ARG_4_DF2_DI_I1:
11651 : case MULTI_ARG_4_SF2_SI_I:
11652 : case MULTI_ARG_4_SF2_SI_I1:
11653 : nargs = 4;
11654 : last_arg_constant = true;
11655 : break;
11656 :
11657 842 : case MULTI_ARG_3_SF:
11658 842 : case MULTI_ARG_3_DF:
11659 842 : case MULTI_ARG_3_SF2:
11660 842 : case MULTI_ARG_3_DF2:
11661 842 : case MULTI_ARG_3_DI:
11662 842 : case MULTI_ARG_3_SI:
11663 842 : case MULTI_ARG_3_SI_DI:
11664 842 : case MULTI_ARG_3_HI:
11665 842 : case MULTI_ARG_3_HI_SI:
11666 842 : case MULTI_ARG_3_QI:
11667 842 : case MULTI_ARG_3_DI2:
11668 842 : case MULTI_ARG_3_SI2:
11669 842 : case MULTI_ARG_3_HI2:
11670 842 : case MULTI_ARG_3_QI2:
11671 842 : nargs = 3;
11672 842 : break;
11673 :
11674 128 : case MULTI_ARG_2_SF:
11675 128 : case MULTI_ARG_2_DF:
11676 128 : case MULTI_ARG_2_DI:
11677 128 : case MULTI_ARG_2_SI:
11678 128 : case MULTI_ARG_2_HI:
11679 128 : case MULTI_ARG_2_QI:
11680 128 : nargs = 2;
11681 128 : break;
11682 :
11683 64 : case MULTI_ARG_2_DI_IMM:
11684 64 : case MULTI_ARG_2_SI_IMM:
11685 64 : case MULTI_ARG_2_HI_IMM:
11686 64 : case MULTI_ARG_2_QI_IMM:
11687 64 : nargs = 2;
11688 64 : last_arg_constant = true;
11689 64 : break;
11690 :
11691 187 : case MULTI_ARG_1_SF:
11692 187 : case MULTI_ARG_1_DF:
11693 187 : case MULTI_ARG_1_SF2:
11694 187 : case MULTI_ARG_1_DF2:
11695 187 : case MULTI_ARG_1_DI:
11696 187 : case MULTI_ARG_1_SI:
11697 187 : case MULTI_ARG_1_HI:
11698 187 : case MULTI_ARG_1_QI:
11699 187 : case MULTI_ARG_1_SI_DI:
11700 187 : case MULTI_ARG_1_HI_DI:
11701 187 : case MULTI_ARG_1_HI_SI:
11702 187 : case MULTI_ARG_1_QI_DI:
11703 187 : case MULTI_ARG_1_QI_SI:
11704 187 : case MULTI_ARG_1_QI_HI:
11705 187 : nargs = 1;
11706 187 : break;
11707 :
11708 384 : case MULTI_ARG_2_DI_CMP:
11709 384 : case MULTI_ARG_2_SI_CMP:
11710 384 : case MULTI_ARG_2_HI_CMP:
11711 384 : case MULTI_ARG_2_QI_CMP:
11712 384 : nargs = 2;
11713 384 : comparison_p = true;
11714 384 : break;
11715 :
11716 128 : case MULTI_ARG_2_SF_TF:
11717 128 : case MULTI_ARG_2_DF_TF:
11718 128 : case MULTI_ARG_2_DI_TF:
11719 128 : case MULTI_ARG_2_SI_TF:
11720 128 : case MULTI_ARG_2_HI_TF:
11721 128 : case MULTI_ARG_2_QI_TF:
11722 128 : nargs = 2;
11723 128 : tf_p = true;
11724 128 : break;
11725 :
11726 0 : default:
11727 0 : gcc_unreachable ();
11728 : }
11729 :
11730 628 : if (optimize || !target
11731 628 : || GET_MODE (target) != tmode
11732 2417 : || !insn_data[icode].operand[0].predicate (target, tmode))
11733 1209 : target = gen_reg_rtx (tmode);
11734 604 : else if (memory_operand (target, tmode))
11735 0 : num_memory++;
11736 :
11737 1813 : gcc_assert (nargs <= ARRAY_SIZE (xops));
11738 :
11739 6246 : for (i = 0; i < nargs; i++)
11740 : {
11741 4441 : tree arg = CALL_EXPR_ARG (exp, i);
11742 4441 : rtx op = expand_normal (arg);
11743 4441 : int adjust = (comparison_p) ? 1 : 0;
11744 4441 : machine_mode mode = insn_data[icode].operand[i+adjust+1].mode;
11745 :
11746 4441 : if (last_arg_constant && i == nargs - 1)
11747 : {
11748 144 : if (!insn_data[icode].operand[i + 1].predicate (op, mode))
11749 : {
11750 30 : enum insn_code new_icode = icode;
11751 30 : switch (icode)
11752 : {
11753 8 : case CODE_FOR_xop_vpermil2v2df3:
11754 8 : case CODE_FOR_xop_vpermil2v4sf3:
11755 8 : case CODE_FOR_xop_vpermil2v4df3:
11756 8 : case CODE_FOR_xop_vpermil2v8sf3:
11757 8 : error ("the last argument must be a 2-bit immediate");
11758 8 : return gen_reg_rtx (tmode);
11759 5 : case CODE_FOR_xop_rotlv2di3:
11760 5 : new_icode = CODE_FOR_rotlv2di3;
11761 5 : goto xop_rotl;
11762 5 : case CODE_FOR_xop_rotlv4si3:
11763 5 : new_icode = CODE_FOR_rotlv4si3;
11764 5 : goto xop_rotl;
11765 6 : case CODE_FOR_xop_rotlv8hi3:
11766 6 : new_icode = CODE_FOR_rotlv8hi3;
11767 6 : goto xop_rotl;
11768 : case CODE_FOR_xop_rotlv16qi3:
11769 : new_icode = CODE_FOR_rotlv16qi3;
11770 22 : xop_rotl:
11771 22 : if (CONST_INT_P (op))
11772 : {
11773 6 : int mask = GET_MODE_UNIT_BITSIZE (tmode) - 1;
11774 6 : op = GEN_INT (INTVAL (op) & mask);
11775 6 : gcc_checking_assert
11776 : (insn_data[icode].operand[i + 1].predicate (op, mode));
11777 : }
11778 : else
11779 : {
11780 16 : gcc_checking_assert
11781 : (nargs == 2
11782 : && insn_data[new_icode].operand[0].mode == tmode
11783 : && insn_data[new_icode].operand[1].mode == tmode
11784 : && insn_data[new_icode].operand[2].mode == mode
11785 : && insn_data[new_icode].operand[0].predicate
11786 : == insn_data[icode].operand[0].predicate
11787 : && insn_data[new_icode].operand[1].predicate
11788 : == insn_data[icode].operand[1].predicate);
11789 16 : icode = new_icode;
11790 16 : goto non_constant;
11791 : }
11792 : break;
11793 0 : default:
11794 0 : gcc_unreachable ();
11795 : }
11796 : }
11797 : }
11798 : else
11799 : {
11800 4297 : non_constant:
11801 4313 : if (VECTOR_MODE_P (mode))
11802 4297 : op = safe_vector_operand (op, mode);
11803 :
11804 : /* If we aren't optimizing, only allow one memory operand to be
11805 : generated. */
11806 4313 : if (memory_operand (op, mode))
11807 826 : num_memory++;
11808 :
11809 4313 : gcc_assert (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode);
11810 :
11811 4313 : if (optimize
11812 1506 : || !insn_data[icode].operand[i+adjust+1].predicate (op, mode)
11813 5741 : || num_memory > 1)
11814 3392 : op = force_reg (mode, op);
11815 : }
11816 :
11817 4433 : xops[i] = op;
11818 : }
11819 :
11820 1805 : switch (nargs)
11821 : {
11822 187 : case 1:
11823 187 : pat = GEN_FCN (icode) (target, xops[0]);
11824 187 : break;
11825 :
11826 704 : case 2:
11827 704 : if (tf_p)
11828 128 : pat = GEN_FCN (icode) (target, xops[0], xops[1],
11829 128 : GEN_INT ((int)sub_code));
11830 576 : else if (! comparison_p)
11831 192 : pat = GEN_FCN (icode) (target, xops[0], xops[1]);
11832 : else
11833 : {
11834 384 : rtx cmp_op = gen_rtx_fmt_ee (sub_code, GET_MODE (target),
11835 : xops[0], xops[1]);
11836 :
11837 384 : pat = GEN_FCN (icode) (target, cmp_op, xops[0], xops[1]);
11838 : }
11839 : break;
11840 :
11841 842 : case 3:
11842 842 : pat = GEN_FCN (icode) (target, xops[0], xops[1], xops[2]);
11843 842 : break;
11844 :
11845 72 : case 4:
11846 72 : pat = GEN_FCN (icode) (target, xops[0], xops[1], xops[2], xops[3]);
11847 72 : break;
11848 :
11849 : default:
11850 : gcc_unreachable ();
11851 : }
11852 :
11853 1805 : if (! pat)
11854 : return 0;
11855 :
11856 1805 : emit_insn (pat);
11857 1805 : return target;
11858 : }
11859 :
11860 : /* Subroutine of ix86_expand_args_builtin to take care of scalar unop
11861 : insns with vec_merge. */
11862 :
11863 : static rtx
11864 52 : ix86_expand_unop_vec_merge_builtin (enum insn_code icode, tree exp,
11865 : rtx target)
11866 : {
11867 52 : rtx pat;
11868 52 : tree arg0 = CALL_EXPR_ARG (exp, 0);
11869 52 : rtx op1, op0 = expand_normal (arg0);
11870 52 : machine_mode tmode = insn_data[icode].operand[0].mode;
11871 52 : machine_mode mode0 = insn_data[icode].operand[1].mode;
11872 :
11873 16 : if (optimize || !target
11874 16 : || GET_MODE (target) != tmode
11875 68 : || !insn_data[icode].operand[0].predicate (target, tmode))
11876 36 : target = gen_reg_rtx (tmode);
11877 :
11878 52 : if (VECTOR_MODE_P (mode0))
11879 52 : op0 = safe_vector_operand (op0, mode0);
11880 :
11881 36 : if ((optimize && !register_operand (op0, mode0))
11882 88 : || !insn_data[icode].operand[1].predicate (op0, mode0))
11883 0 : op0 = copy_to_mode_reg (mode0, op0);
11884 :
11885 52 : op1 = op0;
11886 52 : if (!insn_data[icode].operand[2].predicate (op1, mode0))
11887 16 : op1 = copy_to_mode_reg (mode0, op1);
11888 :
11889 52 : pat = GEN_FCN (icode) (target, op0, op1);
11890 52 : if (! pat)
11891 : return 0;
11892 52 : emit_insn (pat);
11893 52 : return target;
11894 : }
11895 :
11896 : /* Subroutine of ix86_expand_builtin to take care of comparison insns. */
11897 :
11898 : static rtx
11899 616 : ix86_expand_sse_compare (const struct builtin_description *d,
11900 : tree exp, rtx target, bool swap)
11901 : {
11902 616 : rtx pat;
11903 616 : tree arg0 = CALL_EXPR_ARG (exp, 0);
11904 616 : tree arg1 = CALL_EXPR_ARG (exp, 1);
11905 616 : rtx op0 = expand_normal (arg0);
11906 616 : rtx op1 = expand_normal (arg1);
11907 616 : rtx op2;
11908 616 : machine_mode tmode = insn_data[d->icode].operand[0].mode;
11909 616 : machine_mode mode0 = insn_data[d->icode].operand[1].mode;
11910 616 : machine_mode mode1 = insn_data[d->icode].operand[2].mode;
11911 616 : enum rtx_code comparison = d->comparison;
11912 :
11913 616 : if (VECTOR_MODE_P (mode0))
11914 616 : op0 = safe_vector_operand (op0, mode0);
11915 616 : if (VECTOR_MODE_P (mode1))
11916 616 : op1 = safe_vector_operand (op1, mode1);
11917 :
11918 : /* Swap operands if we have a comparison that isn't available in
11919 : hardware. */
11920 616 : if (swap)
11921 80 : std::swap (op0, op1);
11922 :
11923 202 : if (optimize || !target
11924 202 : || GET_MODE (target) != tmode
11925 818 : || !insn_data[d->icode].operand[0].predicate (target, tmode))
11926 414 : target = gen_reg_rtx (tmode);
11927 :
11928 414 : if ((optimize && !register_operand (op0, mode0))
11929 958 : || !insn_data[d->icode].operand[1].predicate (op0, mode0))
11930 274 : op0 = copy_to_mode_reg (mode0, op0);
11931 414 : if ((optimize && !register_operand (op1, mode1))
11932 974 : || !insn_data[d->icode].operand[2].predicate (op1, mode1))
11933 56 : op1 = copy_to_mode_reg (mode1, op1);
11934 :
11935 616 : op2 = gen_rtx_fmt_ee (comparison, mode0, op0, op1);
11936 616 : pat = GEN_FCN (d->icode) (target, op0, op1, op2);
11937 616 : if (! pat)
11938 : return 0;
11939 616 : emit_insn (pat);
11940 616 : return target;
11941 : }
11942 :
11943 : /* Subroutine of ix86_sse_comi and ix86_sse_comi_round to take care of
11944 : * ordered EQ or unordered NE, generate PF jump. */
11945 :
11946 : static rtx
11947 646 : ix86_ssecom_setcc (const enum rtx_code comparison,
11948 : bool check_unordered, machine_mode mode,
11949 : rtx set_dst, rtx target)
11950 : {
11951 :
11952 646 : rtx_code_label *label = NULL;
11953 :
11954 : /* NB: For ordered EQ or unordered NE, check ZF alone isn't sufficient
11955 : with NAN operands.
11956 : Under TARGET_AVX10_2, VCOMX/VUCOMX are generated instead of
11957 : COMI/UCOMI. VCOMX/VUCOMX will not set ZF for NAN operands. */
11958 646 : if (check_unordered)
11959 : {
11960 122 : gcc_assert (comparison == EQ || comparison == NE);
11961 :
11962 122 : rtx flag = gen_rtx_REG (CCFPmode, FLAGS_REG);
11963 122 : label = gen_label_rtx ();
11964 122 : rtx tmp = gen_rtx_fmt_ee (UNORDERED, VOIDmode, flag, const0_rtx);
11965 122 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
11966 : gen_rtx_LABEL_REF (VOIDmode, label),
11967 : pc_rtx);
11968 122 : emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
11969 : }
11970 :
11971 : /* NB: Set CCFPmode and check a different CCmode which is in subset
11972 : of CCFPmode. */
11973 646 : if (GET_MODE (set_dst) != mode)
11974 : {
11975 200 : gcc_assert (mode == CCAmode || mode == CCCmode
11976 : || mode == CCOmode || mode == CCPmode
11977 : || mode == CCSmode || mode == CCZmode);
11978 200 : set_dst = gen_rtx_REG (mode, FLAGS_REG);
11979 : }
11980 :
11981 646 : emit_insn (gen_rtx_SET (gen_rtx_STRICT_LOW_PART (VOIDmode, target),
11982 : gen_rtx_fmt_ee (comparison, QImode,
11983 : set_dst,
11984 : const0_rtx)));
11985 :
11986 646 : if (label)
11987 122 : emit_label (label);
11988 :
11989 646 : return SUBREG_REG (target);
11990 : }
11991 :
11992 : /* Subroutine of ix86_expand_builtin to take care of comi insns. */
11993 :
11994 : static rtx
11995 547 : ix86_expand_sse_comi (const struct builtin_description *d, tree exp,
11996 : rtx target, bool comx_ok)
11997 : {
11998 547 : rtx pat, set_dst;
11999 547 : tree arg0 = CALL_EXPR_ARG (exp, 0);
12000 547 : tree arg1 = CALL_EXPR_ARG (exp, 1);
12001 547 : rtx op0 = expand_normal (arg0);
12002 547 : rtx op1 = expand_normal (arg1);
12003 547 : enum insn_code icode = d->icode;
12004 547 : const struct insn_data_d *insn_p = &insn_data[icode];
12005 547 : machine_mode mode0 = insn_p->operand[0].mode;
12006 547 : machine_mode mode1 = insn_p->operand[1].mode;
12007 :
12008 547 : if (VECTOR_MODE_P (mode0))
12009 547 : op0 = safe_vector_operand (op0, mode0);
12010 547 : if (VECTOR_MODE_P (mode1))
12011 547 : op1 = safe_vector_operand (op1, mode1);
12012 :
12013 547 : enum rtx_code comparison = d->comparison;
12014 547 : rtx const_val = const0_rtx;
12015 :
12016 547 : bool check_unordered = false;
12017 547 : machine_mode mode = CCFPmode;
12018 547 : switch (comparison)
12019 : {
12020 194 : case LE: /* -> GE */
12021 194 : case LT: /* -> GT */
12022 194 : std::swap (op0, op1);
12023 194 : comparison = swap_condition (comparison);
12024 : /* FALLTHRU */
12025 : case GT:
12026 : case GE:
12027 : break;
12028 73 : case EQ:
12029 73 : if (!TARGET_AVX10_2 || !comx_ok)
12030 45 : check_unordered = true;
12031 : mode = CCZmode;
12032 : break;
12033 96 : case NE:
12034 96 : if (!TARGET_AVX10_2 || !comx_ok)
12035 68 : check_unordered = true;
12036 96 : mode = CCZmode;
12037 96 : const_val = const1_rtx;
12038 96 : break;
12039 0 : default:
12040 0 : gcc_unreachable ();
12041 : }
12042 :
12043 547 : target = gen_reg_rtx (SImode);
12044 547 : emit_move_insn (target, const_val);
12045 547 : target = gen_rtx_SUBREG (QImode, target, 0);
12046 :
12047 426 : if ((optimize && !register_operand (op0, mode0))
12048 925 : || !insn_p->operand[0].predicate (op0, mode0))
12049 169 : op0 = copy_to_mode_reg (mode0, op0);
12050 426 : if ((optimize && !register_operand (op1, mode1))
12051 924 : || !insn_p->operand[1].predicate (op1, mode1))
12052 49 : op1 = copy_to_mode_reg (mode1, op1);
12053 :
12054 547 : if ((comparison == EQ || comparison == NE)
12055 169 : && TARGET_AVX10_2 && comx_ok)
12056 : {
12057 56 : switch (icode)
12058 : {
12059 : case CODE_FOR_sse_comi:
12060 : icode = CODE_FOR_avx10_2_comxsf;
12061 : break;
12062 14 : case CODE_FOR_sse_ucomi:
12063 14 : icode = CODE_FOR_avx10_2_ucomxsf;
12064 14 : break;
12065 14 : case CODE_FOR_sse2_comi:
12066 14 : icode = CODE_FOR_avx10_2_comxdf;
12067 14 : break;
12068 14 : case CODE_FOR_sse2_ucomi:
12069 14 : icode = CODE_FOR_avx10_2_ucomxdf;
12070 14 : break;
12071 :
12072 0 : default:
12073 0 : gcc_unreachable ();
12074 : }
12075 : }
12076 547 : pat = GEN_FCN (icode) (op0, op1);
12077 547 : if (! pat)
12078 : return 0;
12079 :
12080 547 : set_dst = SET_DEST (pat);
12081 547 : emit_insn (pat);
12082 547 : return ix86_ssecom_setcc (comparison, check_unordered, mode,
12083 547 : set_dst, target);
12084 : }
12085 :
12086 : /* Subroutines of ix86_expand_args_builtin to take care of round insns. */
12087 :
12088 : static rtx
12089 0 : ix86_expand_sse_round (const struct builtin_description *d, tree exp,
12090 : rtx target)
12091 : {
12092 0 : rtx pat;
12093 0 : tree arg0 = CALL_EXPR_ARG (exp, 0);
12094 0 : rtx op1, op0 = expand_normal (arg0);
12095 0 : machine_mode tmode = insn_data[d->icode].operand[0].mode;
12096 0 : machine_mode mode0 = insn_data[d->icode].operand[1].mode;
12097 :
12098 0 : if (optimize || target == 0
12099 0 : || GET_MODE (target) != tmode
12100 0 : || !insn_data[d->icode].operand[0].predicate (target, tmode))
12101 0 : target = gen_reg_rtx (tmode);
12102 :
12103 0 : if (VECTOR_MODE_P (mode0))
12104 0 : op0 = safe_vector_operand (op0, mode0);
12105 :
12106 0 : if ((optimize && !register_operand (op0, mode0))
12107 0 : || !insn_data[d->icode].operand[0].predicate (op0, mode0))
12108 0 : op0 = copy_to_mode_reg (mode0, op0);
12109 :
12110 0 : op1 = GEN_INT (d->comparison);
12111 :
12112 0 : pat = GEN_FCN (d->icode) (target, op0, op1);
12113 0 : if (! pat)
12114 : return 0;
12115 0 : emit_insn (pat);
12116 0 : return target;
12117 : }
12118 :
12119 : static rtx
12120 12 : ix86_expand_sse_round_vec_pack_sfix (const struct builtin_description *d,
12121 : tree exp, rtx target)
12122 : {
12123 12 : rtx pat;
12124 12 : tree arg0 = CALL_EXPR_ARG (exp, 0);
12125 12 : tree arg1 = CALL_EXPR_ARG (exp, 1);
12126 12 : rtx op0 = expand_normal (arg0);
12127 12 : rtx op1 = expand_normal (arg1);
12128 12 : rtx op2;
12129 12 : machine_mode tmode = insn_data[d->icode].operand[0].mode;
12130 12 : machine_mode mode0 = insn_data[d->icode].operand[1].mode;
12131 12 : machine_mode mode1 = insn_data[d->icode].operand[2].mode;
12132 :
12133 0 : if (optimize || target == 0
12134 0 : || GET_MODE (target) != tmode
12135 12 : || !insn_data[d->icode].operand[0].predicate (target, tmode))
12136 12 : target = gen_reg_rtx (tmode);
12137 :
12138 12 : op0 = safe_vector_operand (op0, mode0);
12139 12 : op1 = safe_vector_operand (op1, mode1);
12140 :
12141 12 : if ((optimize && !register_operand (op0, mode0))
12142 12 : || !insn_data[d->icode].operand[0].predicate (op0, mode0))
12143 12 : op0 = copy_to_mode_reg (mode0, op0);
12144 12 : if ((optimize && !register_operand (op1, mode1))
12145 12 : || !insn_data[d->icode].operand[1].predicate (op1, mode1))
12146 12 : op1 = copy_to_mode_reg (mode1, op1);
12147 :
12148 12 : op2 = GEN_INT (d->comparison);
12149 :
12150 12 : pat = GEN_FCN (d->icode) (target, op0, op1, op2);
12151 12 : if (! pat)
12152 : return 0;
12153 12 : emit_insn (pat);
12154 12 : return target;
12155 : }
12156 :
12157 : /* Subroutine of ix86_expand_builtin to take care of ptest insns. */
12158 :
12159 : static rtx
12160 239 : ix86_expand_sse_ptest (const struct builtin_description *d, tree exp,
12161 : rtx target)
12162 : {
12163 239 : rtx pat;
12164 239 : tree arg0 = CALL_EXPR_ARG (exp, 0);
12165 239 : tree arg1 = CALL_EXPR_ARG (exp, 1);
12166 239 : rtx op0 = expand_normal (arg0);
12167 239 : rtx op1 = expand_normal (arg1);
12168 239 : machine_mode mode0 = insn_data[d->icode].operand[0].mode;
12169 239 : machine_mode mode1 = insn_data[d->icode].operand[1].mode;
12170 239 : enum rtx_code comparison = d->comparison;
12171 239 : rtx result = NULL_RTX;
12172 :
12173 239 : if (VECTOR_MODE_P (mode0))
12174 239 : op0 = safe_vector_operand (op0, mode0);
12175 239 : if (VECTOR_MODE_P (mode1))
12176 239 : op1 = safe_vector_operand (op1, mode1);
12177 :
12178 239 : switch (d->code)
12179 : {
12180 49 : case IX86_BUILTIN_PTESTZ:
12181 49 : case IX86_BUILTIN_PTESTZ256:
12182 : // Returns (OP0 & OP1) == 0
12183 49 : if (rtx_equal_p (op0, CONST0_RTX (mode0))
12184 49 : || rtx_equal_p (op1, CONST0_RTX (mode1)))
12185 2 : result = const1_rtx;
12186 47 : else if (rtx_equal_p (op0, CONSTM1_RTX (mode0)))
12187 : {
12188 1 : op1 = force_reg (mode1, op1);
12189 1 : op0 = op1;
12190 : }
12191 46 : else if (rtx_equal_p (op1, CONSTM1_RTX (mode1)))
12192 : {
12193 1 : op0 = force_reg (mode0, op0);
12194 1 : op1 = op0;
12195 : }
12196 45 : else if (MEM_P (op0) && !MEM_P (op1))
12197 : std::swap (op0, op1);
12198 : break;
12199 :
12200 31 : case IX86_BUILTIN_PTESTC:
12201 31 : case IX86_BUILTIN_PTESTC256:
12202 : // Returns (~OP0 & OP1) == 0
12203 31 : if (rtx_equal_p (op0, CONSTM1_RTX (mode0))
12204 31 : || rtx_equal_p (op1, CONST0_RTX (mode1))
12205 62 : || rtx_equal_p (op0, op1))
12206 2 : result = const1_rtx;
12207 : break;
12208 :
12209 27 : case IX86_BUILTIN_PTESTNZC:
12210 27 : case IX86_BUILTIN_PTESTNZC256:
12211 : // Returns ((OP0 && OP1) != 0) && ((~OP0 && OP1) != 0)
12212 27 : if (rtx_equal_p (op0, CONST0_RTX (mode0))
12213 26 : || rtx_equal_p (op0, CONSTM1_RTX (mode0))
12214 26 : || rtx_equal_p (op1, CONST0_RTX (mode1))
12215 53 : || rtx_equal_p (op0, op1))
12216 1 : result = const0_rtx;
12217 : break;
12218 :
12219 : default:
12220 : break;
12221 : }
12222 :
12223 167 : if ((optimize && !register_operand (op0, mode0))
12224 210 : || !insn_data[d->icode].operand[0].predicate (op0, mode0)
12225 377 : || result)
12226 104 : op0 = copy_to_mode_reg (mode0, op0);
12227 167 : if ((optimize && !register_operand (op1, mode1))
12228 211 : || !insn_data[d->icode].operand[1].predicate (op1, mode1)
12229 450 : || result)
12230 31 : op1 = copy_to_mode_reg (mode1, op1);
12231 :
12232 239 : if (result)
12233 : {
12234 5 : if (!target)
12235 0 : target = gen_reg_rtx (SImode);
12236 5 : emit_move_insn (target, result);
12237 5 : return target;
12238 : }
12239 :
12240 234 : target = gen_reg_rtx (SImode);
12241 234 : emit_move_insn (target, const0_rtx);
12242 234 : target = gen_rtx_SUBREG (QImode, target, 0);
12243 :
12244 234 : pat = GEN_FCN (d->icode) (op0, op1);
12245 234 : if (! pat)
12246 : return 0;
12247 234 : emit_insn (pat);
12248 234 : emit_insn (gen_rtx_SET (gen_rtx_STRICT_LOW_PART (VOIDmode, target),
12249 : gen_rtx_fmt_ee (comparison, QImode,
12250 : SET_DEST (pat),
12251 : const0_rtx)));
12252 :
12253 234 : return SUBREG_REG (target);
12254 : }
12255 :
12256 : /* Subroutine of ix86_expand_builtin to take care of pcmpestr[im] insns. */
12257 :
12258 : static rtx
12259 216 : ix86_expand_sse_pcmpestr (const struct builtin_description *d,
12260 : tree exp, rtx target)
12261 : {
12262 216 : rtx pat;
12263 216 : tree arg0 = CALL_EXPR_ARG (exp, 0);
12264 216 : tree arg1 = CALL_EXPR_ARG (exp, 1);
12265 216 : tree arg2 = CALL_EXPR_ARG (exp, 2);
12266 216 : tree arg3 = CALL_EXPR_ARG (exp, 3);
12267 216 : tree arg4 = CALL_EXPR_ARG (exp, 4);
12268 216 : rtx scratch0, scratch1;
12269 216 : rtx op0 = expand_normal (arg0);
12270 216 : rtx op1 = expand_normal (arg1);
12271 216 : rtx op2 = expand_normal (arg2);
12272 216 : rtx op3 = expand_normal (arg3);
12273 216 : rtx op4 = expand_normal (arg4);
12274 216 : machine_mode tmode0, tmode1, modev2, modei3, modev4, modei5, modeimm;
12275 :
12276 216 : tmode0 = insn_data[d->icode].operand[0].mode;
12277 216 : tmode1 = insn_data[d->icode].operand[1].mode;
12278 216 : modev2 = insn_data[d->icode].operand[2].mode;
12279 216 : modei3 = insn_data[d->icode].operand[3].mode;
12280 216 : modev4 = insn_data[d->icode].operand[4].mode;
12281 216 : modei5 = insn_data[d->icode].operand[5].mode;
12282 216 : modeimm = insn_data[d->icode].operand[6].mode;
12283 :
12284 216 : if (VECTOR_MODE_P (modev2))
12285 216 : op0 = safe_vector_operand (op0, modev2);
12286 216 : if (VECTOR_MODE_P (modev4))
12287 216 : op2 = safe_vector_operand (op2, modev4);
12288 :
12289 216 : if (!insn_data[d->icode].operand[2].predicate (op0, modev2))
12290 6 : op0 = copy_to_mode_reg (modev2, op0);
12291 216 : if (!insn_data[d->icode].operand[3].predicate (op1, modei3))
12292 34 : op1 = copy_to_mode_reg (modei3, op1);
12293 160 : if ((optimize && !register_operand (op2, modev4))
12294 371 : || !insn_data[d->icode].operand[4].predicate (op2, modev4))
12295 5 : op2 = copy_to_mode_reg (modev4, op2);
12296 216 : if (!insn_data[d->icode].operand[5].predicate (op3, modei5))
12297 34 : op3 = copy_to_mode_reg (modei5, op3);
12298 :
12299 216 : if (!insn_data[d->icode].operand[6].predicate (op4, modeimm))
12300 : {
12301 21 : error ("the fifth argument must be an 8-bit immediate");
12302 21 : return const0_rtx;
12303 : }
12304 :
12305 195 : if (d->code == IX86_BUILTIN_PCMPESTRI128)
12306 : {
12307 5 : if (optimize || !target
12308 5 : || GET_MODE (target) != tmode0
12309 34 : || !insn_data[d->icode].operand[0].predicate (target, tmode0))
12310 24 : target = gen_reg_rtx (tmode0);
12311 :
12312 29 : scratch1 = gen_reg_rtx (tmode1);
12313 :
12314 29 : pat = GEN_FCN (d->icode) (target, scratch1, op0, op1, op2, op3, op4);
12315 : }
12316 166 : else if (d->code == IX86_BUILTIN_PCMPESTRM128)
12317 : {
12318 5 : if (optimize || !target
12319 5 : || GET_MODE (target) != tmode1
12320 36 : || !insn_data[d->icode].operand[1].predicate (target, tmode1))
12321 26 : target = gen_reg_rtx (tmode1);
12322 :
12323 31 : scratch0 = gen_reg_rtx (tmode0);
12324 :
12325 31 : pat = GEN_FCN (d->icode) (scratch0, target, op0, op1, op2, op3, op4);
12326 : }
12327 : else
12328 : {
12329 135 : gcc_assert (d->flag);
12330 :
12331 135 : scratch0 = gen_reg_rtx (tmode0);
12332 135 : scratch1 = gen_reg_rtx (tmode1);
12333 :
12334 135 : pat = GEN_FCN (d->icode) (scratch0, scratch1, op0, op1, op2, op3, op4);
12335 : }
12336 :
12337 195 : if (! pat)
12338 : return 0;
12339 :
12340 195 : emit_insn (pat);
12341 :
12342 195 : if (d->flag)
12343 : {
12344 135 : target = gen_reg_rtx (SImode);
12345 135 : emit_move_insn (target, const0_rtx);
12346 135 : target = gen_rtx_SUBREG (QImode, target, 0);
12347 :
12348 135 : emit_insn
12349 135 : (gen_rtx_SET (gen_rtx_STRICT_LOW_PART (VOIDmode, target),
12350 : gen_rtx_fmt_ee (EQ, QImode,
12351 : gen_rtx_REG ((machine_mode) d->flag,
12352 : FLAGS_REG),
12353 : const0_rtx)));
12354 135 : return SUBREG_REG (target);
12355 : }
12356 : else
12357 : return target;
12358 : }
12359 :
12360 :
12361 : /* Subroutine of ix86_expand_builtin to take care of pcmpistr[im] insns. */
12362 :
12363 : static rtx
12364 275 : ix86_expand_sse_pcmpistr (const struct builtin_description *d,
12365 : tree exp, rtx target)
12366 : {
12367 275 : rtx pat;
12368 275 : tree arg0 = CALL_EXPR_ARG (exp, 0);
12369 275 : tree arg1 = CALL_EXPR_ARG (exp, 1);
12370 275 : tree arg2 = CALL_EXPR_ARG (exp, 2);
12371 275 : rtx scratch0, scratch1;
12372 275 : rtx op0 = expand_normal (arg0);
12373 275 : rtx op1 = expand_normal (arg1);
12374 275 : rtx op2 = expand_normal (arg2);
12375 275 : machine_mode tmode0, tmode1, modev2, modev3, modeimm;
12376 :
12377 275 : tmode0 = insn_data[d->icode].operand[0].mode;
12378 275 : tmode1 = insn_data[d->icode].operand[1].mode;
12379 275 : modev2 = insn_data[d->icode].operand[2].mode;
12380 275 : modev3 = insn_data[d->icode].operand[3].mode;
12381 275 : modeimm = insn_data[d->icode].operand[4].mode;
12382 :
12383 275 : if (VECTOR_MODE_P (modev2))
12384 275 : op0 = safe_vector_operand (op0, modev2);
12385 275 : if (VECTOR_MODE_P (modev3))
12386 275 : op1 = safe_vector_operand (op1, modev3);
12387 :
12388 275 : if (!insn_data[d->icode].operand[2].predicate (op0, modev2))
12389 4 : op0 = copy_to_mode_reg (modev2, op0);
12390 210 : if ((optimize && !register_operand (op1, modev3))
12391 481 : || !insn_data[d->icode].operand[3].predicate (op1, modev3))
12392 4 : op1 = copy_to_mode_reg (modev3, op1);
12393 :
12394 275 : if (!insn_data[d->icode].operand[4].predicate (op2, modeimm))
12395 : {
12396 21 : error ("the third argument must be an 8-bit immediate");
12397 21 : return const0_rtx;
12398 : }
12399 :
12400 254 : if (d->code == IX86_BUILTIN_PCMPISTRI128)
12401 : {
12402 5 : if (optimize || !target
12403 5 : || GET_MODE (target) != tmode0
12404 38 : || !insn_data[d->icode].operand[0].predicate (target, tmode0))
12405 28 : target = gen_reg_rtx (tmode0);
12406 :
12407 33 : scratch1 = gen_reg_rtx (tmode1);
12408 :
12409 33 : pat = GEN_FCN (d->icode) (target, scratch1, op0, op1, op2);
12410 : }
12411 221 : else if (d->code == IX86_BUILTIN_PCMPISTRM128)
12412 : {
12413 8 : if (optimize || !target
12414 8 : || GET_MODE (target) != tmode1
12415 58 : || !insn_data[d->icode].operand[1].predicate (target, tmode1))
12416 42 : target = gen_reg_rtx (tmode1);
12417 :
12418 50 : scratch0 = gen_reg_rtx (tmode0);
12419 :
12420 50 : pat = GEN_FCN (d->icode) (scratch0, target, op0, op1, op2);
12421 : }
12422 : else
12423 : {
12424 171 : gcc_assert (d->flag);
12425 :
12426 171 : scratch0 = gen_reg_rtx (tmode0);
12427 171 : scratch1 = gen_reg_rtx (tmode1);
12428 :
12429 171 : pat = GEN_FCN (d->icode) (scratch0, scratch1, op0, op1, op2);
12430 : }
12431 :
12432 254 : if (! pat)
12433 : return 0;
12434 :
12435 254 : emit_insn (pat);
12436 :
12437 254 : if (d->flag)
12438 : {
12439 171 : target = gen_reg_rtx (SImode);
12440 171 : emit_move_insn (target, const0_rtx);
12441 171 : target = gen_rtx_SUBREG (QImode, target, 0);
12442 :
12443 171 : emit_insn
12444 171 : (gen_rtx_SET (gen_rtx_STRICT_LOW_PART (VOIDmode, target),
12445 : gen_rtx_fmt_ee (EQ, QImode,
12446 : gen_rtx_REG ((machine_mode) d->flag,
12447 : FLAGS_REG),
12448 : const0_rtx)));
12449 171 : return SUBREG_REG (target);
12450 : }
12451 : else
12452 : return target;
12453 : }
12454 :
12455 : /* Fixup modeless constants to fit required mode. */
12456 :
12457 : static rtx
12458 262616 : fixup_modeless_constant (rtx x, machine_mode mode)
12459 : {
12460 262616 : if (GET_MODE (x) == VOIDmode)
12461 41522 : x = convert_to_mode (mode, x, 1);
12462 262616 : return x;
12463 : }
12464 :
12465 : /* Expand the outgoing argument ARG to extract unsigned char and short
12466 : integer constants suitable for the predicates and the instruction
12467 : templates which expect the unsigned expanded value. */
12468 :
12469 : static rtx
12470 283773 : ix86_expand_unsigned_small_int_cst_argument (tree arg)
12471 : {
12472 : /* When passing 0xff as an unsigned char function argument with the
12473 : C frontend promotion, expand_normal gets
12474 :
12475 : <integer_cst 0x7fffe6aa23a8 type <integer_type 0x7fffe98225e8 int> constant 255>
12476 :
12477 : and returns the rtx value using the sign-extended representation:
12478 :
12479 : (const_int 255 [0xff])
12480 :
12481 : Without the C frontend promotion, expand_normal gets
12482 :
12483 : <integer_cst 0x7fffe9824018 type <integer_type 0x7fffe9822348 unsigned char > constant 255>
12484 :
12485 : and returns
12486 :
12487 : (const_int -1 [0xffffffffffffffff])
12488 :
12489 : which doesn't work with the predicates nor the instruction templates
12490 : which expect the unsigned expanded value. Extract the unsigned char
12491 : and short integer constants to return
12492 :
12493 : (const_int 255 [0xff])
12494 :
12495 : so that the expanded value is always unsigned, without the C frontend
12496 : promotion. */
12497 :
12498 283773 : if (TREE_CODE (arg) == INTEGER_CST)
12499 : {
12500 60323 : tree type = TREE_TYPE (arg);
12501 60323 : if (INTEGRAL_TYPE_P (type)
12502 60323 : && TYPE_UNSIGNED (type)
12503 82098 : && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
12504 : {
12505 18294 : HOST_WIDE_INT cst = TREE_INT_CST_LOW (arg);
12506 18294 : return GEN_INT (cst);
12507 : }
12508 : }
12509 :
12510 265479 : return expand_normal (arg);
12511 : }
12512 :
12513 : /* Subroutine of ix86_expand_builtin to take care of insns with
12514 : variable number of operands. */
12515 :
12516 : static rtx
12517 72912 : ix86_expand_args_builtin (const struct builtin_description *d,
12518 : tree exp, rtx target)
12519 : {
12520 72912 : rtx pat, real_target;
12521 72912 : unsigned int i, nargs;
12522 72912 : unsigned int nargs_constant = 0;
12523 72912 : unsigned int mask_pos = 0;
12524 72912 : int num_memory = 0;
12525 72912 : rtx xops[6];
12526 72912 : bool second_arg_count = false;
12527 72912 : enum insn_code icode = d->icode;
12528 72912 : const struct insn_data_d *insn_p = &insn_data[icode];
12529 72912 : machine_mode tmode = insn_p->operand[0].mode;
12530 72912 : machine_mode rmode = VOIDmode;
12531 72912 : bool swap = false;
12532 72912 : enum rtx_code comparison = d->comparison;
12533 :
12534 72912 : switch ((enum ix86_builtin_func_type) d->flag)
12535 : {
12536 0 : case V2DF_FTYPE_V2DF_ROUND:
12537 0 : case V4DF_FTYPE_V4DF_ROUND:
12538 0 : case V8DF_FTYPE_V8DF_ROUND:
12539 0 : case V4SF_FTYPE_V4SF_ROUND:
12540 0 : case V8SF_FTYPE_V8SF_ROUND:
12541 0 : case V16SF_FTYPE_V16SF_ROUND:
12542 0 : case V8HF_FTYPE_V8HF_ROUND:
12543 0 : case V16HF_FTYPE_V16HF_ROUND:
12544 0 : case V32HF_FTYPE_V32HF_ROUND:
12545 0 : case V4SI_FTYPE_V4SF_ROUND:
12546 0 : case V8SI_FTYPE_V8SF_ROUND:
12547 0 : case V16SI_FTYPE_V16SF_ROUND:
12548 0 : return ix86_expand_sse_round (d, exp, target);
12549 12 : case V4SI_FTYPE_V2DF_V2DF_ROUND:
12550 12 : case V8SI_FTYPE_V4DF_V4DF_ROUND:
12551 12 : case V16SI_FTYPE_V8DF_V8DF_ROUND:
12552 12 : return ix86_expand_sse_round_vec_pack_sfix (d, exp, target);
12553 239 : case INT_FTYPE_V8SF_V8SF_PTEST:
12554 239 : case INT_FTYPE_V4DI_V4DI_PTEST:
12555 239 : case INT_FTYPE_V4DF_V4DF_PTEST:
12556 239 : case INT_FTYPE_V4SF_V4SF_PTEST:
12557 239 : case INT_FTYPE_V2DI_V2DI_PTEST:
12558 239 : case INT_FTYPE_V2DF_V2DF_PTEST:
12559 239 : return ix86_expand_sse_ptest (d, exp, target);
12560 : case FLOAT128_FTYPE_FLOAT128:
12561 : case FLOAT_FTYPE_FLOAT:
12562 : case FLOAT_FTYPE_BFLOAT16:
12563 : case INT_FTYPE_INT:
12564 : case UINT_FTYPE_UINT:
12565 : case UINT16_FTYPE_UINT16:
12566 : case UINT64_FTYPE_INT:
12567 : case UINT64_FTYPE_UINT64:
12568 : case INT64_FTYPE_INT64:
12569 : case INT64_FTYPE_V4SF:
12570 : case INT64_FTYPE_V2DF:
12571 : case INT_FTYPE_V16QI:
12572 : case INT_FTYPE_V8QI:
12573 : case INT_FTYPE_V8SF:
12574 : case INT_FTYPE_V4DF:
12575 : case INT_FTYPE_V4SF:
12576 : case INT_FTYPE_V2DF:
12577 : case INT_FTYPE_V32QI:
12578 : case V16QI_FTYPE_V16QI:
12579 : case V8SI_FTYPE_V8SF:
12580 : case V8SI_FTYPE_V4SI:
12581 : case V8HI_FTYPE_V8HI:
12582 : case V8HI_FTYPE_V16QI:
12583 : case V8QI_FTYPE_V8QI:
12584 : case V8SF_FTYPE_V8SF:
12585 : case V8SF_FTYPE_V8SI:
12586 : case V8SF_FTYPE_V4SF:
12587 : case V8SF_FTYPE_V8HI:
12588 : case V4SI_FTYPE_V4SI:
12589 : case V4SI_FTYPE_V16QI:
12590 : case V4SI_FTYPE_V4SF:
12591 : case V4SI_FTYPE_V8SI:
12592 : case V4SI_FTYPE_V8HI:
12593 : case V4SI_FTYPE_V4DF:
12594 : case V4SI_FTYPE_V2DF:
12595 : case V4HI_FTYPE_V4HI:
12596 : case V4DF_FTYPE_V4DF:
12597 : case V4DF_FTYPE_V4SI:
12598 : case V4DF_FTYPE_V4SF:
12599 : case V4DF_FTYPE_V2DF:
12600 : case V4SF_FTYPE_V4SF:
12601 : case V4SF_FTYPE_V4SI:
12602 : case V4SF_FTYPE_V8SF:
12603 : case V4SF_FTYPE_V4DF:
12604 : case V4SF_FTYPE_V8HI:
12605 : case V4SF_FTYPE_V2DF:
12606 : case V2DI_FTYPE_V2DI:
12607 : case V2DI_FTYPE_V16QI:
12608 : case V2DI_FTYPE_V8HI:
12609 : case V2DI_FTYPE_V4SI:
12610 : case V2DF_FTYPE_V2DF:
12611 : case V2DF_FTYPE_V4SI:
12612 : case V2DF_FTYPE_V4DF:
12613 : case V2DF_FTYPE_V4SF:
12614 : case V2DF_FTYPE_V2SI:
12615 : case V2SI_FTYPE_V2SI:
12616 : case V2SI_FTYPE_V4SF:
12617 : case V2SI_FTYPE_V2SF:
12618 : case V2SI_FTYPE_V2DF:
12619 : case V2SF_FTYPE_V2SF:
12620 : case V2SF_FTYPE_V2SI:
12621 : case V32QI_FTYPE_V32QI:
12622 : case V32QI_FTYPE_V16QI:
12623 : case V16HI_FTYPE_V16HI:
12624 : case V16HI_FTYPE_V8HI:
12625 : case V8SI_FTYPE_V8SI:
12626 : case V16HI_FTYPE_V16QI:
12627 : case V8SI_FTYPE_V16QI:
12628 : case V4DI_FTYPE_V16QI:
12629 : case V8SI_FTYPE_V8HI:
12630 : case V4DI_FTYPE_V8HI:
12631 : case V4DI_FTYPE_V4SI:
12632 : case V4DI_FTYPE_V2DI:
12633 : case UQI_FTYPE_UQI:
12634 : case UHI_FTYPE_UHI:
12635 : case USI_FTYPE_USI:
12636 : case USI_FTYPE_UQI:
12637 : case USI_FTYPE_UHI:
12638 : case UDI_FTYPE_UDI:
12639 : case UHI_FTYPE_V16QI:
12640 : case USI_FTYPE_V32QI:
12641 : case UDI_FTYPE_V64QI:
12642 : case V16QI_FTYPE_UHI:
12643 : case V32QI_FTYPE_USI:
12644 : case V64QI_FTYPE_UDI:
12645 : case V8HI_FTYPE_UQI:
12646 : case V16HI_FTYPE_UHI:
12647 : case V32HI_FTYPE_USI:
12648 : case V4SI_FTYPE_UQI:
12649 : case V8SI_FTYPE_UQI:
12650 : case V4SI_FTYPE_UHI:
12651 : case V8SI_FTYPE_UHI:
12652 : case UQI_FTYPE_V8HI:
12653 : case UHI_FTYPE_V16HI:
12654 : case USI_FTYPE_V32HI:
12655 : case UQI_FTYPE_V4SI:
12656 : case UQI_FTYPE_V8SI:
12657 : case UHI_FTYPE_V16SI:
12658 : case UQI_FTYPE_V2DI:
12659 : case UQI_FTYPE_V4DI:
12660 : case UQI_FTYPE_V8DI:
12661 : case V16SI_FTYPE_UHI:
12662 : case V2DI_FTYPE_UQI:
12663 : case V4DI_FTYPE_UQI:
12664 : case V16SI_FTYPE_INT:
12665 : case V16SF_FTYPE_V8SF:
12666 : case V16SI_FTYPE_V8SI:
12667 : case V16SF_FTYPE_V4SF:
12668 : case V16SI_FTYPE_V4SI:
12669 : case V16SI_FTYPE_V16SF:
12670 : case V16SI_FTYPE_V16SI:
12671 : case V64QI_FTYPE_V64QI:
12672 : case V32HI_FTYPE_V32HI:
12673 : case V16SF_FTYPE_V16SF:
12674 : case V8DI_FTYPE_UQI:
12675 : case V8DI_FTYPE_V8DI:
12676 : case V8DF_FTYPE_V4DF:
12677 : case V8DF_FTYPE_V2DF:
12678 : case V8DF_FTYPE_V8DF:
12679 : case V4DI_FTYPE_V4DI:
12680 : case V16BF_FTYPE_V16SF:
12681 : case V8BF_FTYPE_V8SF:
12682 : case V8BF_FTYPE_V4SF:
12683 : nargs = 1;
12684 : break;
12685 52 : case V4SF_FTYPE_V4SF_VEC_MERGE:
12686 52 : case V2DF_FTYPE_V2DF_VEC_MERGE:
12687 52 : return ix86_expand_unop_vec_merge_builtin (icode, exp, target);
12688 9527 : case FLOAT128_FTYPE_FLOAT128_FLOAT128:
12689 9527 : case V16QI_FTYPE_V16QI_V16QI:
12690 9527 : case V16QI_FTYPE_V8HI_V8HI:
12691 9527 : case V16HF_FTYPE_V16HF_V16HF:
12692 9527 : case V16SF_FTYPE_V16SF_V16SF:
12693 9527 : case V16SI_FTYPE_V16SI_V16SI:
12694 9527 : case V8QI_FTYPE_V8QI_V8QI:
12695 9527 : case V8QI_FTYPE_V4HI_V4HI:
12696 9527 : case V8HI_FTYPE_V8HI_V8HI:
12697 9527 : case V8HI_FTYPE_V16QI_V16QI:
12698 9527 : case V8HI_FTYPE_V4SI_V4SI:
12699 9527 : case V8HF_FTYPE_V8HF_V8HF:
12700 9527 : case V8SF_FTYPE_V8SF_V8SF:
12701 9527 : case V8SF_FTYPE_V8SF_V8SI:
12702 9527 : case V8DF_FTYPE_V8DF_V8DF:
12703 9527 : case V4SI_FTYPE_V4SI_V4SI:
12704 9527 : case V4SI_FTYPE_V8HI_V8HI:
12705 9527 : case V4SI_FTYPE_V2DF_V2DF:
12706 9527 : case V4HI_FTYPE_V4HI_V4HI:
12707 9527 : case V4HI_FTYPE_V8QI_V8QI:
12708 9527 : case V4HI_FTYPE_V2SI_V2SI:
12709 9527 : case V4DF_FTYPE_V4DF_V4DF:
12710 9527 : case V4DF_FTYPE_V4DF_V4DI:
12711 9527 : case V4SF_FTYPE_V4SF_V4SF:
12712 9527 : case V4SF_FTYPE_V4SF_V4SI:
12713 9527 : case V4SF_FTYPE_V4SF_V2SI:
12714 9527 : case V4SF_FTYPE_V4SF_V2DF:
12715 9527 : case V4SF_FTYPE_V4SF_UINT:
12716 9527 : case V4SF_FTYPE_V4SF_DI:
12717 9527 : case V4SF_FTYPE_V4SF_SI:
12718 9527 : case V4DI_FTYPE_V4DI_V2DI:
12719 9527 : case V2DI_FTYPE_V2DI_V2DI:
12720 9527 : case V2DI_FTYPE_V16QI_V16QI:
12721 9527 : case V2DI_FTYPE_V4SI_V4SI:
12722 9527 : case V2DI_FTYPE_V2DI_V16QI:
12723 9527 : case V2SI_FTYPE_V2SI_V2SI:
12724 9527 : case V2SI_FTYPE_V4HI_V4HI:
12725 9527 : case V2SI_FTYPE_V2SF_V2SF:
12726 9527 : case V2DF_FTYPE_V2DF_V2DF:
12727 9527 : case V2DF_FTYPE_V2DF_V4SF:
12728 9527 : case V2DF_FTYPE_V2DF_V2DI:
12729 9527 : case V2DF_FTYPE_V2DF_DI:
12730 9527 : case V2DF_FTYPE_V2DF_SI:
12731 9527 : case V2DF_FTYPE_V2DF_UINT:
12732 9527 : case V2SF_FTYPE_V2SF_V2SF:
12733 9527 : case V1DI_FTYPE_V1DI_V1DI:
12734 9527 : case V1DI_FTYPE_V8QI_V8QI:
12735 9527 : case V1DI_FTYPE_V2SI_V2SI:
12736 9527 : case V32QI_FTYPE_V16HI_V16HI:
12737 9527 : case V16HI_FTYPE_V8SI_V8SI:
12738 9527 : case V64QI_FTYPE_V64QI_V64QI:
12739 9527 : case V32QI_FTYPE_V32QI_V32QI:
12740 9527 : case V32BF_FTYPE_V32BF_V32BF:
12741 9527 : case V16BF_FTYPE_V16BF_V16BF:
12742 9527 : case V8BF_FTYPE_V8BF_V8BF:
12743 9527 : case V16HI_FTYPE_V32QI_V32QI:
12744 9527 : case V16HI_FTYPE_V16HI_V16HI:
12745 9527 : case V8SI_FTYPE_V4DF_V4DF:
12746 9527 : case V8SI_FTYPE_V8SI_V8SI:
12747 9527 : case V8SI_FTYPE_V16HI_V16HI:
12748 9527 : case V4DI_FTYPE_V4DI_V4DI:
12749 9527 : case V4DI_FTYPE_V8SI_V8SI:
12750 9527 : case V4DI_FTYPE_V32QI_V32QI:
12751 9527 : case V8DI_FTYPE_V64QI_V64QI:
12752 9527 : if (comparison == UNKNOWN)
12753 8991 : return ix86_expand_binop_builtin (icode, exp, target);
12754 : nargs = 2;
12755 : break;
12756 80 : case V4SF_FTYPE_V4SF_V4SF_SWAP:
12757 80 : case V2DF_FTYPE_V2DF_V2DF_SWAP:
12758 80 : gcc_assert (comparison != UNKNOWN);
12759 : nargs = 2;
12760 : swap = true;
12761 : break;
12762 1481 : case V16HI_FTYPE_V16HI_V8HI_COUNT:
12763 1481 : case V16HI_FTYPE_V16HI_SI_COUNT:
12764 1481 : case V8SI_FTYPE_V8SI_V4SI_COUNT:
12765 1481 : case V8SI_FTYPE_V8SI_SI_COUNT:
12766 1481 : case V4DI_FTYPE_V4DI_V2DI_COUNT:
12767 1481 : case V4DI_FTYPE_V4DI_INT_COUNT:
12768 1481 : case V8HI_FTYPE_V8HI_V8HI_COUNT:
12769 1481 : case V8HI_FTYPE_V8HI_SI_COUNT:
12770 1481 : case V4SI_FTYPE_V4SI_V4SI_COUNT:
12771 1481 : case V4SI_FTYPE_V4SI_SI_COUNT:
12772 1481 : case V4HI_FTYPE_V4HI_V4HI_COUNT:
12773 1481 : case V4HI_FTYPE_V4HI_SI_COUNT:
12774 1481 : case V2DI_FTYPE_V2DI_V2DI_COUNT:
12775 1481 : case V2DI_FTYPE_V2DI_SI_COUNT:
12776 1481 : case V2SI_FTYPE_V2SI_V2SI_COUNT:
12777 1481 : case V2SI_FTYPE_V2SI_SI_COUNT:
12778 1481 : case V1DI_FTYPE_V1DI_V1DI_COUNT:
12779 1481 : case V1DI_FTYPE_V1DI_SI_COUNT:
12780 1481 : nargs = 2;
12781 1481 : second_arg_count = true;
12782 1481 : break;
12783 1408 : case V16HI_FTYPE_V16HI_INT_V16HI_UHI_COUNT:
12784 1408 : case V16HI_FTYPE_V16HI_V8HI_V16HI_UHI_COUNT:
12785 1408 : case V16SI_FTYPE_V16SI_INT_V16SI_UHI_COUNT:
12786 1408 : case V16SI_FTYPE_V16SI_V4SI_V16SI_UHI_COUNT:
12787 1408 : case V2DI_FTYPE_V2DI_INT_V2DI_UQI_COUNT:
12788 1408 : case V2DI_FTYPE_V2DI_V2DI_V2DI_UQI_COUNT:
12789 1408 : case V32HI_FTYPE_V32HI_INT_V32HI_USI_COUNT:
12790 1408 : case V32HI_FTYPE_V32HI_V8HI_V32HI_USI_COUNT:
12791 1408 : case V4DI_FTYPE_V4DI_INT_V4DI_UQI_COUNT:
12792 1408 : case V4DI_FTYPE_V4DI_V2DI_V4DI_UQI_COUNT:
12793 1408 : case V4SI_FTYPE_V4SI_INT_V4SI_UQI_COUNT:
12794 1408 : case V4SI_FTYPE_V4SI_V4SI_V4SI_UQI_COUNT:
12795 1408 : case V8DI_FTYPE_V8DI_INT_V8DI_UQI_COUNT:
12796 1408 : case V8DI_FTYPE_V8DI_V2DI_V8DI_UQI_COUNT:
12797 1408 : case V8HI_FTYPE_V8HI_INT_V8HI_UQI_COUNT:
12798 1408 : case V8HI_FTYPE_V8HI_V8HI_V8HI_UQI_COUNT:
12799 1408 : case V8SI_FTYPE_V8SI_INT_V8SI_UQI_COUNT:
12800 1408 : case V8SI_FTYPE_V8SI_V4SI_V8SI_UQI_COUNT:
12801 1408 : nargs = 4;
12802 1408 : second_arg_count = true;
12803 1408 : break;
12804 966 : case UINT64_FTYPE_UINT64_UINT64:
12805 966 : case UINT_FTYPE_UINT_UINT:
12806 966 : case UINT_FTYPE_UINT_USHORT:
12807 966 : case UINT_FTYPE_UINT_UCHAR:
12808 966 : case UINT16_FTYPE_UINT16_INT:
12809 966 : case UINT8_FTYPE_UINT8_INT:
12810 966 : case UQI_FTYPE_UQI_UQI:
12811 966 : case UHI_FTYPE_UHI_UHI:
12812 966 : case USI_FTYPE_USI_USI:
12813 966 : case UDI_FTYPE_UDI_UDI:
12814 966 : case V16SI_FTYPE_V8DF_V8DF:
12815 966 : case V32BF_FTYPE_V16SF_V16SF:
12816 966 : case V16BF_FTYPE_V8SF_V8SF:
12817 966 : case V8BF_FTYPE_V4SF_V4SF:
12818 966 : case V16BF_FTYPE_V16SF_UHI:
12819 966 : case V8BF_FTYPE_V8SF_UQI:
12820 966 : case V8BF_FTYPE_V4SF_UQI:
12821 966 : case V16QI_FTYPE_V16QI_V8HF:
12822 966 : nargs = 2;
12823 966 : break;
12824 906 : case V2DI_FTYPE_V2DI_INT_CONVERT:
12825 906 : nargs = 2;
12826 906 : rmode = V1TImode;
12827 906 : nargs_constant = 1;
12828 906 : break;
12829 42 : case V4DI_FTYPE_V4DI_INT_CONVERT:
12830 42 : nargs = 2;
12831 42 : rmode = V2TImode;
12832 42 : nargs_constant = 1;
12833 42 : break;
12834 16 : case V8DI_FTYPE_V8DI_INT_CONVERT:
12835 16 : nargs = 2;
12836 16 : rmode = V4TImode;
12837 16 : nargs_constant = 1;
12838 16 : break;
12839 2424 : case V8HI_FTYPE_V8HI_INT:
12840 2424 : case V8HI_FTYPE_V8SF_INT:
12841 2424 : case V16HI_FTYPE_V16SF_INT:
12842 2424 : case V8HI_FTYPE_V4SF_INT:
12843 2424 : case V8SF_FTYPE_V8SF_INT:
12844 2424 : case V4SF_FTYPE_V16SF_INT:
12845 2424 : case V16SF_FTYPE_V16SF_INT:
12846 2424 : case V4SI_FTYPE_V4SI_INT:
12847 2424 : case V4SI_FTYPE_V8SI_INT:
12848 2424 : case V4HI_FTYPE_V4HI_INT:
12849 2424 : case V4DF_FTYPE_V4DF_INT:
12850 2424 : case V4DF_FTYPE_V8DF_INT:
12851 2424 : case V4SF_FTYPE_V4SF_INT:
12852 2424 : case V4SF_FTYPE_V8SF_INT:
12853 2424 : case V2DI_FTYPE_V2DI_INT:
12854 2424 : case V2DF_FTYPE_V2DF_INT:
12855 2424 : case V2DF_FTYPE_V4DF_INT:
12856 2424 : case V16HI_FTYPE_V16HI_INT:
12857 2424 : case V8SI_FTYPE_V8SI_INT:
12858 2424 : case V16SI_FTYPE_V16SI_INT:
12859 2424 : case V4SI_FTYPE_V16SI_INT:
12860 2424 : case V4DI_FTYPE_V4DI_INT:
12861 2424 : case V2DI_FTYPE_V4DI_INT:
12862 2424 : case V4DI_FTYPE_V8DI_INT:
12863 2424 : case UQI_FTYPE_UQI_UQI_CONST:
12864 2424 : case UHI_FTYPE_UHI_UQI:
12865 2424 : case USI_FTYPE_USI_UQI:
12866 2424 : case UDI_FTYPE_UDI_UQI:
12867 2424 : nargs = 2;
12868 2424 : nargs_constant = 1;
12869 2424 : break;
12870 18720 : case V16QI_FTYPE_V16QI_V16QI_V16QI:
12871 18720 : case V8SF_FTYPE_V8SF_V8SF_V8SF:
12872 18720 : case V4DF_FTYPE_V4DF_V4DF_V4DF:
12873 18720 : case V4SF_FTYPE_V4SF_V4SF_V4SF:
12874 18720 : case V2DF_FTYPE_V2DF_V2DF_V2DF:
12875 18720 : case V32QI_FTYPE_V32QI_V32QI_V32QI:
12876 18720 : case UHI_FTYPE_V16SI_V16SI_UHI:
12877 18720 : case UQI_FTYPE_V8DI_V8DI_UQI:
12878 18720 : case V16HI_FTYPE_V16SI_V16HI_UHI:
12879 18720 : case V16QI_FTYPE_V16SI_V16QI_UHI:
12880 18720 : case V16QI_FTYPE_V8DI_V16QI_UQI:
12881 18720 : case V32HF_FTYPE_V32HF_V32HF_USI:
12882 18720 : case V16SF_FTYPE_V16SF_V16SF_UHI:
12883 18720 : case V16SF_FTYPE_V4SF_V16SF_UHI:
12884 18720 : case V16SI_FTYPE_SI_V16SI_UHI:
12885 18720 : case V16SI_FTYPE_V16HI_V16SI_UHI:
12886 18720 : case V16SI_FTYPE_V16QI_V16SI_UHI:
12887 18720 : case V8SF_FTYPE_V4SF_V8SF_UQI:
12888 18720 : case V4DF_FTYPE_V2DF_V4DF_UQI:
12889 18720 : case V8SI_FTYPE_V4SI_V8SI_UQI:
12890 18720 : case V8SI_FTYPE_SI_V8SI_UQI:
12891 18720 : case V4SI_FTYPE_V4SI_V4SI_UQI:
12892 18720 : case V4SI_FTYPE_SI_V4SI_UQI:
12893 18720 : case V4DI_FTYPE_V2DI_V4DI_UQI:
12894 18720 : case V4DI_FTYPE_DI_V4DI_UQI:
12895 18720 : case V2DI_FTYPE_V2DI_V2DI_UQI:
12896 18720 : case V2DI_FTYPE_DI_V2DI_UQI:
12897 18720 : case V64QI_FTYPE_V64QI_V64QI_UDI:
12898 18720 : case V64QI_FTYPE_V16QI_V64QI_UDI:
12899 18720 : case V64QI_FTYPE_QI_V64QI_UDI:
12900 18720 : case V32QI_FTYPE_V32QI_V32QI_USI:
12901 18720 : case V32QI_FTYPE_V16QI_V32QI_USI:
12902 18720 : case V32QI_FTYPE_QI_V32QI_USI:
12903 18720 : case V16QI_FTYPE_V16QI_V16QI_UHI:
12904 18720 : case V16QI_FTYPE_QI_V16QI_UHI:
12905 18720 : case V32HI_FTYPE_V8HI_V32HI_USI:
12906 18720 : case V32HI_FTYPE_V32BF_V32HI_USI:
12907 18720 : case V32HI_FTYPE_HI_V32HI_USI:
12908 18720 : case V16HI_FTYPE_V8HI_V16HI_UHI:
12909 18720 : case V16HI_FTYPE_V16BF_V16HI_UHI:
12910 18720 : case V16HI_FTYPE_HI_V16HI_UHI:
12911 18720 : case V8HI_FTYPE_V8HI_V8HI_UQI:
12912 18720 : case V8HI_FTYPE_V8BF_V8HI_UQI:
12913 18720 : case V8BF_FTYPE_V8BF_V8BF_UQI:
12914 18720 : case V8HI_FTYPE_HI_V8HI_UQI:
12915 18720 : case V16HF_FTYPE_V16HF_V16HF_UHI:
12916 18720 : case V8SF_FTYPE_V8HI_V8SF_UQI:
12917 18720 : case V4SF_FTYPE_V8HI_V4SF_UQI:
12918 18720 : case V8SI_FTYPE_V8HF_V8SI_UQI:
12919 18720 : case V8SF_FTYPE_V8HF_V8SF_UQI:
12920 18720 : case V8SI_FTYPE_V8SF_V8SI_UQI:
12921 18720 : case V4SI_FTYPE_V4SF_V4SI_UQI:
12922 18720 : case V4SI_FTYPE_V8HF_V4SI_UQI:
12923 18720 : case V4SF_FTYPE_V8HF_V4SF_UQI:
12924 18720 : case V4DI_FTYPE_V8HF_V4DI_UQI:
12925 18720 : case V4DI_FTYPE_V4SF_V4DI_UQI:
12926 18720 : case V2DI_FTYPE_V8HF_V2DI_UQI:
12927 18720 : case V2DI_FTYPE_V4SF_V2DI_UQI:
12928 18720 : case V8HF_FTYPE_V8HF_V8HF_UQI:
12929 18720 : case V8HF_FTYPE_V8HF_V8HF_V8HF:
12930 18720 : case V8HF_FTYPE_V8HI_V8HF_UQI:
12931 18720 : case V8HF_FTYPE_V8SI_V8HF_UQI:
12932 18720 : case V8HF_FTYPE_V8SF_V8HF_UQI:
12933 18720 : case V8HF_FTYPE_V4SI_V8HF_UQI:
12934 18720 : case V8HF_FTYPE_V4SF_V8HF_UQI:
12935 18720 : case V8HF_FTYPE_V4DI_V8HF_UQI:
12936 18720 : case V8HF_FTYPE_V4DF_V8HF_UQI:
12937 18720 : case V8HF_FTYPE_V2DI_V8HF_UQI:
12938 18720 : case V8HF_FTYPE_V2DF_V8HF_UQI:
12939 18720 : case V4SF_FTYPE_V4DI_V4SF_UQI:
12940 18720 : case V4SF_FTYPE_V2DI_V4SF_UQI:
12941 18720 : case V4DF_FTYPE_V4DI_V4DF_UQI:
12942 18720 : case V4DF_FTYPE_V8HF_V4DF_UQI:
12943 18720 : case V2DF_FTYPE_V8HF_V2DF_UQI:
12944 18720 : case V2DF_FTYPE_V2DI_V2DF_UQI:
12945 18720 : case V16QI_FTYPE_V8HI_V16QI_UQI:
12946 18720 : case V16QI_FTYPE_V16HI_V16QI_UHI:
12947 18720 : case V16QI_FTYPE_V4SI_V16QI_UQI:
12948 18720 : case V16QI_FTYPE_V8SI_V16QI_UQI:
12949 18720 : case V8HI_FTYPE_V8HF_V8HI_UQI:
12950 18720 : case V8HI_FTYPE_V4SI_V8HI_UQI:
12951 18720 : case V8HI_FTYPE_V8SI_V8HI_UQI:
12952 18720 : case V16QI_FTYPE_V2DI_V16QI_UQI:
12953 18720 : case V16QI_FTYPE_V4DI_V16QI_UQI:
12954 18720 : case V8HI_FTYPE_V2DI_V8HI_UQI:
12955 18720 : case V8HI_FTYPE_V4DI_V8HI_UQI:
12956 18720 : case V4SI_FTYPE_V2DI_V4SI_UQI:
12957 18720 : case V4SI_FTYPE_V4DI_V4SI_UQI:
12958 18720 : case V32QI_FTYPE_V32HI_V32QI_USI:
12959 18720 : case UHI_FTYPE_V16QI_V16QI_UHI:
12960 18720 : case USI_FTYPE_V32QI_V32QI_USI:
12961 18720 : case UDI_FTYPE_V64QI_V64QI_UDI:
12962 18720 : case UQI_FTYPE_V8HI_V8HI_UQI:
12963 18720 : case UHI_FTYPE_V16HI_V16HI_UHI:
12964 18720 : case USI_FTYPE_V32HI_V32HI_USI:
12965 18720 : case UQI_FTYPE_V4SI_V4SI_UQI:
12966 18720 : case UQI_FTYPE_V8SI_V8SI_UQI:
12967 18720 : case UQI_FTYPE_V2DI_V2DI_UQI:
12968 18720 : case UQI_FTYPE_V4DI_V4DI_UQI:
12969 18720 : case V4SF_FTYPE_V2DF_V4SF_UQI:
12970 18720 : case V4SF_FTYPE_V4DF_V4SF_UQI:
12971 18720 : case V16SI_FTYPE_V16SI_V16SI_UHI:
12972 18720 : case V16SI_FTYPE_V4SI_V16SI_UHI:
12973 18720 : case V2DI_FTYPE_V4SI_V2DI_UQI:
12974 18720 : case V2DI_FTYPE_V8HI_V2DI_UQI:
12975 18720 : case V2DI_FTYPE_V16QI_V2DI_UQI:
12976 18720 : case V4DI_FTYPE_V4DI_V4DI_UQI:
12977 18720 : case V4DI_FTYPE_V4SI_V4DI_UQI:
12978 18720 : case V4DI_FTYPE_V8HI_V4DI_UQI:
12979 18720 : case V4DI_FTYPE_V16QI_V4DI_UQI:
12980 18720 : case V4DI_FTYPE_V4DF_V4DI_UQI:
12981 18720 : case V2DI_FTYPE_V2DF_V2DI_UQI:
12982 18720 : case V4SI_FTYPE_V4DF_V4SI_UQI:
12983 18720 : case V4SI_FTYPE_V2DF_V4SI_UQI:
12984 18720 : case V4SI_FTYPE_V8HI_V4SI_UQI:
12985 18720 : case V4SI_FTYPE_V16QI_V4SI_UQI:
12986 18720 : case V4DI_FTYPE_V4DI_V4DI_V4DI:
12987 18720 : case V8DF_FTYPE_V2DF_V8DF_UQI:
12988 18720 : case V8DF_FTYPE_V4DF_V8DF_UQI:
12989 18720 : case V8DF_FTYPE_V8DF_V8DF_UQI:
12990 18720 : case V8SF_FTYPE_V8SF_V8SF_UQI:
12991 18720 : case V8SF_FTYPE_V8SI_V8SF_UQI:
12992 18720 : case V4DF_FTYPE_V4DF_V4DF_UQI:
12993 18720 : case V4SF_FTYPE_V4SF_V4SF_UQI:
12994 18720 : case V2DF_FTYPE_V2DF_V2DF_UQI:
12995 18720 : case V2DF_FTYPE_V4SF_V2DF_UQI:
12996 18720 : case V2DF_FTYPE_V4SI_V2DF_UQI:
12997 18720 : case V4SF_FTYPE_V4SI_V4SF_UQI:
12998 18720 : case V4DF_FTYPE_V4SF_V4DF_UQI:
12999 18720 : case V4DF_FTYPE_V4SI_V4DF_UQI:
13000 18720 : case V8SI_FTYPE_V8SI_V8SI_UQI:
13001 18720 : case V8SI_FTYPE_V8HI_V8SI_UQI:
13002 18720 : case V8SI_FTYPE_V16QI_V8SI_UQI:
13003 18720 : case V8DF_FTYPE_V8SI_V8DF_UQI:
13004 18720 : case V8DI_FTYPE_DI_V8DI_UQI:
13005 18720 : case V16SF_FTYPE_V8SF_V16SF_UHI:
13006 18720 : case V16SI_FTYPE_V8SI_V16SI_UHI:
13007 18720 : case V16HF_FTYPE_V16HI_V16HF_UHI:
13008 18720 : case V16HF_FTYPE_V16HF_V16HF_V16HF:
13009 18720 : case V16HI_FTYPE_V16HF_V16HI_UHI:
13010 18720 : case V16HI_FTYPE_V16HI_V16HI_UHI:
13011 18720 : case V16BF_FTYPE_V16BF_V16BF_UHI:
13012 18720 : case V8HI_FTYPE_V16QI_V8HI_UQI:
13013 18720 : case V16HI_FTYPE_V16QI_V16HI_UHI:
13014 18720 : case V32HI_FTYPE_V32HI_V32HI_USI:
13015 18720 : case V32BF_FTYPE_V32BF_V32BF_USI:
13016 18720 : case V32HI_FTYPE_V32QI_V32HI_USI:
13017 18720 : case V8DI_FTYPE_V16QI_V8DI_UQI:
13018 18720 : case V8DI_FTYPE_V2DI_V8DI_UQI:
13019 18720 : case V8DI_FTYPE_V4DI_V8DI_UQI:
13020 18720 : case V8DI_FTYPE_V8DI_V8DI_UQI:
13021 18720 : case V8DI_FTYPE_V8HI_V8DI_UQI:
13022 18720 : case V8DI_FTYPE_V8SI_V8DI_UQI:
13023 18720 : case V8HI_FTYPE_V8DI_V8HI_UQI:
13024 18720 : case V8SI_FTYPE_V8DI_V8SI_UQI:
13025 18720 : case V4SI_FTYPE_V4SI_V4SI_V4SI:
13026 18720 : case V4DI_FTYPE_V4DI_V4DI_V2DI:
13027 18720 : case V16SI_FTYPE_V16SI_V16SI_V16SI:
13028 18720 : case V8DI_FTYPE_V8DI_V8DI_V8DI:
13029 18720 : case V32HI_FTYPE_V32HI_V32HI_V32HI:
13030 18720 : case V2DI_FTYPE_V2DI_V2DI_V2DI:
13031 18720 : case V16HI_FTYPE_V16HI_V16HI_V16HI:
13032 18720 : case V8SI_FTYPE_V8SI_V8SI_V8SI:
13033 18720 : case V8HI_FTYPE_V8HI_V8HI_V8HI:
13034 18720 : case V32BF_FTYPE_V16SF_V16SF_USI:
13035 18720 : case V16BF_FTYPE_V8SF_V8SF_UHI:
13036 18720 : case V8BF_FTYPE_V4SF_V4SF_UQI:
13037 18720 : case V16BF_FTYPE_V16SF_V16BF_UHI:
13038 18720 : case V8BF_FTYPE_V8SF_V8BF_UQI:
13039 18720 : case V8BF_FTYPE_V4SF_V8BF_UQI:
13040 18720 : case V16SF_FTYPE_V16SF_V32BF_V32BF:
13041 18720 : case V8SF_FTYPE_V8SF_V16BF_V16BF:
13042 18720 : case V4SF_FTYPE_V4SF_V8BF_V8BF:
13043 18720 : case V16QI_FTYPE_V16QI_V8HF_V8HF:
13044 18720 : case V32QI_FTYPE_V32QI_V16HF_V16HF:
13045 18720 : case V64QI_FTYPE_V64QI_V32HF_V32HF:
13046 18720 : case V16QI_FTYPE_V8HF_V16QI_UQI:
13047 18720 : case V16QI_FTYPE_V16HF_V16QI_UHI:
13048 18720 : case V32QI_FTYPE_V32HF_V32QI_USI:
13049 18720 : case V8HF_FTYPE_V16QI_V8HF_UQI:
13050 18720 : case V16HF_FTYPE_V16QI_V16HF_UHI:
13051 18720 : case V32HF_FTYPE_V32QI_V32HF_USI:
13052 18720 : case V16SI_FTYPE_V16SF_V16SI_UHI:
13053 18720 : case V32HI_FTYPE_V32HF_V32HI_USI:
13054 18720 : case V8DI_FTYPE_V8SF_V8DI_UQI:
13055 18720 : case V8DI_FTYPE_V8DF_V8DI_UQI:
13056 18720 : case V8SI_FTYPE_V8DF_V8SI_UQI:
13057 18720 : nargs = 3;
13058 18720 : break;
13059 1480 : case V32QI_FTYPE_V32QI_V32QI_INT:
13060 1480 : case V16HI_FTYPE_V16HI_V16HI_INT:
13061 1480 : case V16QI_FTYPE_V16QI_V16QI_INT:
13062 1480 : case V4DI_FTYPE_V4DI_V4DI_INT:
13063 1480 : case V8HI_FTYPE_V8HI_V8HI_INT:
13064 1480 : case V8SI_FTYPE_V8SI_V8SI_INT:
13065 1480 : case V8SI_FTYPE_V8SI_V4SI_INT:
13066 1480 : case V8SF_FTYPE_V8SF_V8SF_INT:
13067 1480 : case V8SF_FTYPE_V8SF_V4SF_INT:
13068 1480 : case V4SI_FTYPE_V4SI_V4SI_INT:
13069 1480 : case V4DF_FTYPE_V4DF_V4DF_INT:
13070 1480 : case V16SF_FTYPE_V16SF_V16SF_INT:
13071 1480 : case V16SF_FTYPE_V16SF_V4SF_INT:
13072 1480 : case V16SI_FTYPE_V16SI_V4SI_INT:
13073 1480 : case V4DF_FTYPE_V4DF_V2DF_INT:
13074 1480 : case V4SF_FTYPE_V4SF_V4SF_INT:
13075 1480 : case V2DI_FTYPE_V2DI_V2DI_INT:
13076 1480 : case V4DI_FTYPE_V4DI_V2DI_INT:
13077 1480 : case V2DF_FTYPE_V2DF_V2DF_INT:
13078 1480 : case UQI_FTYPE_V8DI_V8UDI_INT:
13079 1480 : case UQI_FTYPE_V8DF_V8DF_INT:
13080 1480 : case UQI_FTYPE_V2DF_V2DF_INT:
13081 1480 : case UQI_FTYPE_V4SF_V4SF_INT:
13082 1480 : case UHI_FTYPE_V16SI_V16SI_INT:
13083 1480 : case UHI_FTYPE_V16SF_V16SF_INT:
13084 1480 : case V64QI_FTYPE_V64QI_V64QI_INT:
13085 1480 : case V32HI_FTYPE_V32HI_V32HI_INT:
13086 1480 : case V16SI_FTYPE_V16SI_V16SI_INT:
13087 1480 : case V8DI_FTYPE_V8DI_V8DI_INT:
13088 1480 : nargs = 3;
13089 1480 : nargs_constant = 1;
13090 1480 : break;
13091 47 : case V4DI_FTYPE_V4DI_V4DI_INT_CONVERT:
13092 47 : nargs = 3;
13093 47 : rmode = V4DImode;
13094 47 : nargs_constant = 1;
13095 47 : break;
13096 80 : case V2DI_FTYPE_V2DI_V2DI_INT_CONVERT:
13097 80 : nargs = 3;
13098 80 : rmode = V2DImode;
13099 80 : nargs_constant = 1;
13100 80 : break;
13101 48 : case V1DI_FTYPE_V1DI_V1DI_INT_CONVERT:
13102 48 : nargs = 3;
13103 48 : rmode = DImode;
13104 48 : nargs_constant = 1;
13105 48 : break;
13106 20 : case V2DI_FTYPE_V2DI_UINT_UINT:
13107 20 : nargs = 3;
13108 20 : nargs_constant = 2;
13109 20 : break;
13110 8 : case V8DI_FTYPE_V8DI_V8DI_INT_CONVERT:
13111 8 : nargs = 3;
13112 8 : rmode = V8DImode;
13113 8 : nargs_constant = 1;
13114 8 : break;
13115 16 : case V8DI_FTYPE_V8DI_V8DI_INT_V8DI_UDI_CONVERT:
13116 16 : nargs = 5;
13117 16 : rmode = V8DImode;
13118 16 : mask_pos = 2;
13119 16 : nargs_constant = 1;
13120 16 : break;
13121 320 : case QI_FTYPE_V8DF_INT_UQI:
13122 320 : case QI_FTYPE_V4DF_INT_UQI:
13123 320 : case QI_FTYPE_V2DF_INT_UQI:
13124 320 : case HI_FTYPE_V16SF_INT_UHI:
13125 320 : case QI_FTYPE_V8SF_INT_UQI:
13126 320 : case QI_FTYPE_V4SF_INT_UQI:
13127 320 : case QI_FTYPE_V8HF_INT_UQI:
13128 320 : case HI_FTYPE_V16HF_INT_UHI:
13129 320 : case SI_FTYPE_V32HF_INT_USI:
13130 320 : case QI_FTYPE_V8BF_INT_UQI:
13131 320 : case HI_FTYPE_V16BF_INT_UHI:
13132 320 : case SI_FTYPE_V32BF_INT_USI:
13133 320 : case V4SI_FTYPE_V4SI_V4SI_UHI:
13134 320 : case V8SI_FTYPE_V8SI_V8SI_UHI:
13135 320 : nargs = 3;
13136 320 : mask_pos = 1;
13137 320 : nargs_constant = 1;
13138 320 : break;
13139 17 : case V4DI_FTYPE_V4DI_V4DI_INT_V4DI_USI_CONVERT:
13140 17 : nargs = 5;
13141 17 : rmode = V4DImode;
13142 17 : mask_pos = 2;
13143 17 : nargs_constant = 1;
13144 17 : break;
13145 17 : case V2DI_FTYPE_V2DI_V2DI_INT_V2DI_UHI_CONVERT:
13146 17 : nargs = 5;
13147 17 : rmode = V2DImode;
13148 17 : mask_pos = 2;
13149 17 : nargs_constant = 1;
13150 17 : break;
13151 17247 : case V32QI_FTYPE_V32QI_V32QI_V32QI_USI:
13152 17247 : case V32HI_FTYPE_V32HI_V32HI_V32HI_USI:
13153 17247 : case V32BF_FTYPE_V32BF_V32BF_V32BF_USI:
13154 17247 : case V32HI_FTYPE_V64QI_V64QI_V32HI_USI:
13155 17247 : case V16SI_FTYPE_V32HI_V32HI_V16SI_UHI:
13156 17247 : case V64QI_FTYPE_V64QI_V64QI_V64QI_UDI:
13157 17247 : case V32HI_FTYPE_V32HI_V8HI_V32HI_USI:
13158 17247 : case V16HI_FTYPE_V16HI_V8HI_V16HI_UHI:
13159 17247 : case V8SI_FTYPE_V8SI_V4SI_V8SI_UQI:
13160 17247 : case V4DI_FTYPE_V4DI_V2DI_V4DI_UQI:
13161 17247 : case V64QI_FTYPE_V32HI_V32HI_V64QI_UDI:
13162 17247 : case V32QI_FTYPE_V16HI_V16HI_V32QI_USI:
13163 17247 : case V16QI_FTYPE_V8HI_V8HI_V16QI_UHI:
13164 17247 : case V32HI_FTYPE_V16SI_V16SI_V32HI_USI:
13165 17247 : case V16HI_FTYPE_V8SI_V8SI_V16HI_UHI:
13166 17247 : case V8HI_FTYPE_V4SI_V4SI_V8HI_UQI:
13167 17247 : case V4DF_FTYPE_V4DF_V4DI_V4DF_UQI:
13168 17247 : case V32HF_FTYPE_V32HF_V32HF_V32HF_USI:
13169 17247 : case V8SF_FTYPE_V8SF_V8SI_V8SF_UQI:
13170 17247 : case V4SF_FTYPE_V4SF_V4SI_V4SF_UQI:
13171 17247 : case V2DF_FTYPE_V2DF_V2DI_V2DF_UQI:
13172 17247 : case V2DI_FTYPE_V4SI_V4SI_V2DI_UQI:
13173 17247 : case V4DI_FTYPE_V8SI_V8SI_V4DI_UQI:
13174 17247 : case V4DF_FTYPE_V4DI_V4DF_V4DF_UQI:
13175 17247 : case V8SF_FTYPE_V8SI_V8SF_V8SF_UQI:
13176 17247 : case V2DF_FTYPE_V2DI_V2DF_V2DF_UQI:
13177 17247 : case V4SF_FTYPE_V4SI_V4SF_V4SF_UQI:
13178 17247 : case V16SF_FTYPE_V16SF_V16SF_V16SF_UHI:
13179 17247 : case V16SF_FTYPE_V16SF_V16SI_V16SF_UHI:
13180 17247 : case V16SF_FTYPE_V16SI_V16SF_V16SF_UHI:
13181 17247 : case V16SI_FTYPE_V16SI_V16SI_V16SI_UHI:
13182 17247 : case V16SI_FTYPE_V16SI_V4SI_V16SI_UHI:
13183 17247 : case V8HI_FTYPE_V8HI_V8HI_V8HI_UQI:
13184 17247 : case V8BF_FTYPE_V8BF_V8BF_V8BF_UQI:
13185 17247 : case V8SI_FTYPE_V8SI_V8SI_V8SI_UQI:
13186 17247 : case V4SI_FTYPE_V4SI_V4SI_V4SI_UQI:
13187 17247 : case V16HF_FTYPE_V16HF_V16HF_V16HF_UQI:
13188 17247 : case V16HF_FTYPE_V16HF_V16HF_V16HF_UHI:
13189 17247 : case V8SF_FTYPE_V8SF_V8SF_V8SF_UQI:
13190 17247 : case V16QI_FTYPE_V16QI_V16QI_V16QI_UHI:
13191 17247 : case V16HI_FTYPE_V16HI_V16HI_V16HI_UHI:
13192 17247 : case V16BF_FTYPE_V16BF_V16BF_V16BF_UHI:
13193 17247 : case V2DI_FTYPE_V2DI_V2DI_V2DI_UQI:
13194 17247 : case V2DF_FTYPE_V2DF_V2DF_V2DF_UQI:
13195 17247 : case V4DI_FTYPE_V4DI_V4DI_V4DI_UQI:
13196 17247 : case V4DF_FTYPE_V4DF_V4DF_V4DF_UQI:
13197 17247 : case V8HF_FTYPE_V8HF_V8HF_V8HF_UQI:
13198 17247 : case V4SF_FTYPE_V4SF_V4SF_V4SF_UQI:
13199 17247 : case V8DF_FTYPE_V8DF_V8DF_V8DF_UQI:
13200 17247 : case V8DF_FTYPE_V8DF_V8DI_V8DF_UQI:
13201 17247 : case V8DF_FTYPE_V8DI_V8DF_V8DF_UQI:
13202 17247 : case V8DI_FTYPE_V16SI_V16SI_V8DI_UQI:
13203 17247 : case V8DI_FTYPE_V8DI_V2DI_V8DI_UQI:
13204 17247 : case V8DI_FTYPE_V8DI_V8DI_V8DI_UQI:
13205 17247 : case V8HI_FTYPE_V16QI_V16QI_V8HI_UQI:
13206 17247 : case V16HI_FTYPE_V32QI_V32QI_V16HI_UHI:
13207 17247 : case V8SI_FTYPE_V16HI_V16HI_V8SI_UQI:
13208 17247 : case V4SI_FTYPE_V8HI_V8HI_V4SI_UQI:
13209 17247 : case V32BF_FTYPE_V16SF_V16SF_V32BF_USI:
13210 17247 : case V16BF_FTYPE_V8SF_V8SF_V16BF_UHI:
13211 17247 : case V8BF_FTYPE_V4SF_V4SF_V8BF_UQI:
13212 17247 : case V32HF_FTYPE_V16SF_V16SF_V32HF_USI:
13213 17247 : case V16HF_FTYPE_V8SF_V8SF_V16HF_UHI:
13214 17247 : case V8HF_FTYPE_V4SF_V4SF_V8HF_UQI:
13215 17247 : case V16QI_FTYPE_V8HF_V8HF_V16QI_UHI:
13216 17247 : case V32QI_FTYPE_V16HF_V16HF_V32QI_USI:
13217 17247 : case V64QI_FTYPE_V32HF_V32HF_V64QI_UDI:
13218 17247 : case V16QI_FTYPE_V16QI_V8HF_V16QI_UHI:
13219 17247 : case V16QI_FTYPE_V32QI_V16HF_V16QI_UHI:
13220 17247 : case V32QI_FTYPE_V64QI_V32HF_V32QI_USI:
13221 17247 : nargs = 4;
13222 17247 : break;
13223 11 : case V2DF_FTYPE_V2DF_V2DF_V2DI_INT:
13224 11 : case V4DF_FTYPE_V4DF_V4DF_V4DI_INT:
13225 11 : case V4SF_FTYPE_V4SF_V4SF_V4SI_INT:
13226 11 : case V8SF_FTYPE_V8SF_V8SF_V8SI_INT:
13227 11 : case V16SF_FTYPE_V16SF_V16SF_V16SI_INT:
13228 11 : case V4SI_FTYPE_V4SI_V4SI_V4SI_INT:
13229 11 : nargs = 4;
13230 11 : nargs_constant = 1;
13231 11 : break;
13232 3718 : case UQI_FTYPE_V4DI_V4DI_INT_UQI:
13233 3718 : case UQI_FTYPE_V8SI_V8SI_INT_UQI:
13234 3718 : case QI_FTYPE_V4DF_V4DF_INT_UQI:
13235 3718 : case QI_FTYPE_V8SF_V8SF_INT_UQI:
13236 3718 : case UHI_FTYPE_V16HF_V16HF_INT_UHI:
13237 3718 : case UQI_FTYPE_V2DI_V2DI_INT_UQI:
13238 3718 : case UQI_FTYPE_V4SI_V4SI_INT_UQI:
13239 3718 : case UQI_FTYPE_V2DF_V2DF_INT_UQI:
13240 3718 : case UQI_FTYPE_V4SF_V4SF_INT_UQI:
13241 3718 : case UQI_FTYPE_V8HF_V8HF_INT_UQI:
13242 3718 : case UDI_FTYPE_V64QI_V64QI_INT_UDI:
13243 3718 : case USI_FTYPE_V32QI_V32QI_INT_USI:
13244 3718 : case UHI_FTYPE_V16QI_V16QI_INT_UHI:
13245 3718 : case USI_FTYPE_V32HI_V32HI_INT_USI:
13246 3718 : case USI_FTYPE_V32BF_V32BF_INT_USI:
13247 3718 : case USI_FTYPE_V32HF_V32HF_INT_USI:
13248 3718 : case UHI_FTYPE_V16HI_V16HI_INT_UHI:
13249 3718 : case UHI_FTYPE_V16BF_V16BF_INT_UHI:
13250 3718 : case UQI_FTYPE_V8HI_V8HI_INT_UQI:
13251 3718 : case UQI_FTYPE_V8BF_V8BF_INT_UQI:
13252 3718 : nargs = 4;
13253 3718 : mask_pos = 1;
13254 3718 : nargs_constant = 1;
13255 3718 : break;
13256 23 : case V2DI_FTYPE_V2DI_V2DI_UINT_UINT:
13257 23 : nargs = 4;
13258 23 : nargs_constant = 2;
13259 23 : break;
13260 67 : case UCHAR_FTYPE_UCHAR_UINT_UINT_PUNSIGNED:
13261 67 : case UCHAR_FTYPE_UCHAR_ULONGLONG_ULONGLONG_PULONGLONG:
13262 67 : case V16SF_FTYPE_V16SF_V32BF_V32BF_UHI:
13263 67 : case V8SF_FTYPE_V8SF_V16BF_V16BF_UQI:
13264 67 : case V4SF_FTYPE_V4SF_V8BF_V8BF_UQI:
13265 67 : nargs = 4;
13266 67 : break;
13267 679 : case UQI_FTYPE_V8DI_V8DI_INT_UQI:
13268 679 : case UHI_FTYPE_V16SI_V16SI_INT_UHI:
13269 679 : mask_pos = 1;
13270 679 : nargs = 4;
13271 679 : nargs_constant = 1;
13272 679 : break;
13273 3948 : case V8SF_FTYPE_V8SF_INT_V8SF_UQI:
13274 3948 : case V4SF_FTYPE_V4SF_INT_V4SF_UQI:
13275 3948 : case V2DF_FTYPE_V4DF_INT_V2DF_UQI:
13276 3948 : case V2DI_FTYPE_V4DI_INT_V2DI_UQI:
13277 3948 : case V8SF_FTYPE_V16SF_INT_V8SF_UQI:
13278 3948 : case V8SI_FTYPE_V16SI_INT_V8SI_UQI:
13279 3948 : case V2DF_FTYPE_V8DF_INT_V2DF_UQI:
13280 3948 : case V2DI_FTYPE_V8DI_INT_V2DI_UQI:
13281 3948 : case V4SF_FTYPE_V8SF_INT_V4SF_UQI:
13282 3948 : case V4SI_FTYPE_V8SI_INT_V4SI_UQI:
13283 3948 : case V8HI_FTYPE_V8SF_INT_V8HI_UQI:
13284 3948 : case V8HI_FTYPE_V4SF_INT_V8HI_UQI:
13285 3948 : case V32HI_FTYPE_V32HI_INT_V32HI_USI:
13286 3948 : case V16HI_FTYPE_V16HI_INT_V16HI_UHI:
13287 3948 : case V8HI_FTYPE_V8HI_INT_V8HI_UQI:
13288 3948 : case V32BF_FTYPE_V32BF_INT_V32BF_USI:
13289 3948 : case V16BF_FTYPE_V16BF_INT_V16BF_UHI:
13290 3948 : case V8BF_FTYPE_V8BF_INT_V8BF_UQI:
13291 3948 : case V4DI_FTYPE_V4DI_INT_V4DI_UQI:
13292 3948 : case V2DI_FTYPE_V2DI_INT_V2DI_UQI:
13293 3948 : case V8SI_FTYPE_V8SI_INT_V8SI_UQI:
13294 3948 : case V4SI_FTYPE_V4SI_INT_V4SI_UQI:
13295 3948 : case V4DF_FTYPE_V4DF_INT_V4DF_UQI:
13296 3948 : case V2DF_FTYPE_V2DF_INT_V2DF_UQI:
13297 3948 : case V8DF_FTYPE_V8DF_INT_V8DF_UQI:
13298 3948 : case V16SF_FTYPE_V16SF_INT_V16SF_UHI:
13299 3948 : case V16HI_FTYPE_V16SF_INT_V16HI_UHI:
13300 3948 : case V16SI_FTYPE_V16SI_INT_V16SI_UHI:
13301 3948 : case V16HF_FTYPE_V16HF_INT_V16HF_UHI:
13302 3948 : case V8HF_FTYPE_V8HF_INT_V8HF_UQI:
13303 3948 : case V4SI_FTYPE_V16SI_INT_V4SI_UQI:
13304 3948 : case V4DI_FTYPE_V8DI_INT_V4DI_UQI:
13305 3948 : case V4DF_FTYPE_V8DF_INT_V4DF_UQI:
13306 3948 : case V4SF_FTYPE_V16SF_INT_V4SF_UQI:
13307 3948 : case V8DI_FTYPE_V8DI_INT_V8DI_UQI:
13308 3948 : nargs = 4;
13309 3948 : mask_pos = 2;
13310 3948 : nargs_constant = 1;
13311 3948 : break;
13312 1726 : case V16SF_FTYPE_V16SF_V4SF_INT_V16SF_UHI:
13313 1726 : case V16SI_FTYPE_V16SI_V4SI_INT_V16SI_UHI:
13314 1726 : case V8DF_FTYPE_V8DF_V8DF_INT_V8DF_UQI:
13315 1726 : case V8DI_FTYPE_V8DI_V8DI_INT_V8DI_UQI:
13316 1726 : case V16SF_FTYPE_V16SF_V16SF_INT_V16SF_UHI:
13317 1726 : case V16SI_FTYPE_V16SI_V16SI_INT_V16SI_UHI:
13318 1726 : case V4SF_FTYPE_V4SF_V4SF_INT_V4SF_UQI:
13319 1726 : case V2DF_FTYPE_V2DF_V2DF_INT_V2DF_UQI:
13320 1726 : case V8DF_FTYPE_V8DF_V4DF_INT_V8DF_UQI:
13321 1726 : case V8DI_FTYPE_V8DI_V4DI_INT_V8DI_UQI:
13322 1726 : case V4DF_FTYPE_V4DF_V4DF_INT_V4DF_UQI:
13323 1726 : case V8SF_FTYPE_V8SF_V8SF_INT_V8SF_UQI:
13324 1726 : case V8DF_FTYPE_V8DF_V2DF_INT_V8DF_UQI:
13325 1726 : case V8DI_FTYPE_V8DI_V2DI_INT_V8DI_UQI:
13326 1726 : case V8SI_FTYPE_V8SI_V8SI_INT_V8SI_UQI:
13327 1726 : case V4DI_FTYPE_V4DI_V4DI_INT_V4DI_UQI:
13328 1726 : case V4SI_FTYPE_V4SI_V4SI_INT_V4SI_UQI:
13329 1726 : case V2DI_FTYPE_V2DI_V2DI_INT_V2DI_UQI:
13330 1726 : case V32HI_FTYPE_V64QI_V64QI_INT_V32HI_USI:
13331 1726 : case V16HI_FTYPE_V32QI_V32QI_INT_V16HI_UHI:
13332 1726 : case V8HI_FTYPE_V16QI_V16QI_INT_V8HI_UQI:
13333 1726 : case V16SF_FTYPE_V16SF_V8SF_INT_V16SF_UHI:
13334 1726 : case V16SI_FTYPE_V16SI_V8SI_INT_V16SI_UHI:
13335 1726 : case V8SF_FTYPE_V8SF_V4SF_INT_V8SF_UQI:
13336 1726 : case V8SI_FTYPE_V8SI_V4SI_INT_V8SI_UQI:
13337 1726 : case V4DI_FTYPE_V4DI_V2DI_INT_V4DI_UQI:
13338 1726 : case V4DF_FTYPE_V4DF_V2DF_INT_V4DF_UQI:
13339 1726 : nargs = 5;
13340 1726 : mask_pos = 2;
13341 1726 : nargs_constant = 1;
13342 1726 : break;
13343 268 : case V8DI_FTYPE_V8DI_V8DI_V8DI_INT_UQI:
13344 268 : case V16SI_FTYPE_V16SI_V16SI_V16SI_INT_UHI:
13345 268 : case V2DF_FTYPE_V2DF_V2DF_V2DI_INT_UQI:
13346 268 : case V4SF_FTYPE_V4SF_V4SF_V4SI_INT_UQI:
13347 268 : case V8SF_FTYPE_V8SF_V8SF_V8SI_INT_UQI:
13348 268 : case V8SI_FTYPE_V8SI_V8SI_V8SI_INT_UQI:
13349 268 : case V4DF_FTYPE_V4DF_V4DF_V4DI_INT_UQI:
13350 268 : case V4DI_FTYPE_V4DI_V4DI_V4DI_INT_UQI:
13351 268 : case V4SI_FTYPE_V4SI_V4SI_V4SI_INT_UQI:
13352 268 : case V2DI_FTYPE_V2DI_V2DI_V2DI_INT_UQI:
13353 268 : nargs = 5;
13354 268 : mask_pos = 1;
13355 268 : nargs_constant = 1;
13356 268 : break;
13357 732 : case V64QI_FTYPE_V64QI_V64QI_INT_V64QI_UDI:
13358 732 : case V32QI_FTYPE_V32QI_V32QI_INT_V32QI_USI:
13359 732 : case V16QI_FTYPE_V16QI_V16QI_INT_V16QI_UHI:
13360 732 : case V32HI_FTYPE_V32HI_V32HI_INT_V32HI_INT:
13361 732 : case V16SI_FTYPE_V16SI_V16SI_INT_V16SI_INT:
13362 732 : case V8DI_FTYPE_V8DI_V8DI_INT_V8DI_INT:
13363 732 : case V16HI_FTYPE_V16HI_V16HI_INT_V16HI_INT:
13364 732 : case V8SI_FTYPE_V8SI_V8SI_INT_V8SI_INT:
13365 732 : case V4DI_FTYPE_V4DI_V4DI_INT_V4DI_INT:
13366 732 : case V8HI_FTYPE_V8HI_V8HI_INT_V8HI_INT:
13367 732 : case V4SI_FTYPE_V4SI_V4SI_INT_V4SI_INT:
13368 732 : case V2DI_FTYPE_V2DI_V2DI_INT_V2DI_INT:
13369 732 : case V8BF_FTYPE_V8BF_V8BF_INT_V8BF_UQI:
13370 732 : case V16BF_FTYPE_V16BF_V16BF_INT_V16BF_UHI:
13371 732 : case V32BF_FTYPE_V32BF_V32BF_INT_V32BF_USI:
13372 732 : case V16HF_FTYPE_V16HF_V16HF_INT_V16HF_UHI:
13373 732 : case V8HF_FTYPE_V8HF_V8HF_INT_V8HF_UQI:
13374 732 : nargs = 5;
13375 732 : mask_pos = 1;
13376 732 : nargs_constant = 2;
13377 732 : break;
13378 :
13379 0 : default:
13380 0 : gcc_unreachable ();
13381 : }
13382 :
13383 56435 : gcc_assert (nargs <= ARRAY_SIZE (xops));
13384 :
13385 63618 : if (comparison != UNKNOWN)
13386 : {
13387 616 : gcc_assert (nargs == 2);
13388 616 : return ix86_expand_sse_compare (d, exp, target, swap);
13389 : }
13390 :
13391 63002 : if (rmode == VOIDmode || rmode == tmode)
13392 : {
13393 62817 : if (optimize
13394 17705 : || target == 0
13395 17705 : || GET_MODE (target) != tmode
13396 80320 : || !insn_p->operand[0].predicate (target, tmode))
13397 45402 : target = gen_reg_rtx (tmode);
13398 17415 : else if (memory_operand (target, tmode))
13399 578 : num_memory++;
13400 : real_target = target;
13401 : }
13402 : else
13403 : {
13404 185 : real_target = gen_reg_rtx (tmode);
13405 185 : target = lowpart_subreg (rmode, real_target, tmode);
13406 : }
13407 :
13408 265291 : for (i = 0; i < nargs; i++)
13409 : {
13410 202522 : tree arg = CALL_EXPR_ARG (exp, i);
13411 202522 : rtx op = ix86_expand_unsigned_small_int_cst_argument (arg);
13412 202522 : machine_mode mode = insn_p->operand[i + 1].mode;
13413 : /* Need to fixup modeless constant before testing predicate. */
13414 202522 : op = fixup_modeless_constant (op, mode);
13415 202522 : bool match = insn_p->operand[i + 1].predicate (op, mode);
13416 :
13417 202522 : if (second_arg_count && i == 1)
13418 : {
13419 : /* SIMD shift insns take either an 8-bit immediate or
13420 : register as count. But builtin functions take int as
13421 : count. If count doesn't match, we put it in register.
13422 : The instructions are using 64-bit count, if op is just
13423 : 32-bit, zero-extend it, as negative shift counts
13424 : are undefined behavior and zero-extension is more
13425 : efficient. */
13426 2889 : if (!match)
13427 : {
13428 1750 : if (SCALAR_INT_MODE_P (GET_MODE (op)))
13429 489 : op = convert_modes (mode, GET_MODE (op), op, 1);
13430 : else
13431 1261 : op = lowpart_subreg (mode, op, GET_MODE (op));
13432 1750 : if (!insn_p->operand[i + 1].predicate (op, mode))
13433 190 : op = copy_to_reg (op);
13434 : }
13435 : }
13436 199633 : else if ((mask_pos && (nargs - i - mask_pos) == nargs_constant) ||
13437 151577 : (!mask_pos && (nargs - i) <= nargs_constant))
13438 : {
13439 16585 : if (!match)
13440 233 : switch (icode)
13441 : {
13442 2 : case CODE_FOR_avx_vinsertf128v4di:
13443 2 : case CODE_FOR_avx_vextractf128v4di:
13444 2 : error ("the last argument must be an 1-bit immediate");
13445 2 : return const0_rtx;
13446 :
13447 8 : case CODE_FOR_avx512f_cmpv8di3_mask:
13448 8 : case CODE_FOR_avx512f_cmpv16si3_mask:
13449 8 : case CODE_FOR_avx512f_ucmpv8di3_mask:
13450 8 : case CODE_FOR_avx512f_ucmpv16si3_mask:
13451 8 : case CODE_FOR_avx512vl_cmpv4di3_mask:
13452 8 : case CODE_FOR_avx512vl_cmpv8si3_mask:
13453 8 : case CODE_FOR_avx512vl_ucmpv4di3_mask:
13454 8 : case CODE_FOR_avx512vl_ucmpv8si3_mask:
13455 8 : case CODE_FOR_avx512vl_cmpv2di3_mask:
13456 8 : case CODE_FOR_avx512vl_cmpv4si3_mask:
13457 8 : case CODE_FOR_avx512vl_ucmpv2di3_mask:
13458 8 : case CODE_FOR_avx512vl_ucmpv4si3_mask:
13459 8 : error ("the last argument must be a 3-bit immediate");
13460 8 : return const0_rtx;
13461 :
13462 24 : case CODE_FOR_sse4_1_roundsd:
13463 24 : case CODE_FOR_sse4_1_roundss:
13464 :
13465 24 : case CODE_FOR_sse4_1_roundpd:
13466 24 : case CODE_FOR_sse4_1_roundps:
13467 24 : case CODE_FOR_avx_roundpd256:
13468 24 : case CODE_FOR_avx_roundps256:
13469 :
13470 24 : case CODE_FOR_sse4_1_roundpd_vec_pack_sfix:
13471 24 : case CODE_FOR_sse4_1_roundps_sfix:
13472 24 : case CODE_FOR_avx_roundpd_vec_pack_sfix256:
13473 24 : case CODE_FOR_avx_roundps_sfix256:
13474 :
13475 24 : case CODE_FOR_sse4_1_blendps:
13476 24 : case CODE_FOR_avx_blendpd256:
13477 24 : case CODE_FOR_avx_vpermilv4df:
13478 24 : case CODE_FOR_avx_vpermilv4df_mask:
13479 24 : case CODE_FOR_avx512f_getmantv8df_mask:
13480 24 : case CODE_FOR_avx512f_getmantv16sf_mask:
13481 24 : case CODE_FOR_avx512vl_getmantv16hf_mask:
13482 24 : case CODE_FOR_avx512vl_getmantv8sf_mask:
13483 24 : case CODE_FOR_avx512vl_getmantv4df_mask:
13484 24 : case CODE_FOR_avx512fp16_getmantv8hf_mask:
13485 24 : case CODE_FOR_avx512vl_getmantv4sf_mask:
13486 24 : case CODE_FOR_avx512vl_getmantv2df_mask:
13487 24 : case CODE_FOR_avx512dq_rangepv8df_mask_round:
13488 24 : case CODE_FOR_avx512dq_rangepv16sf_mask_round:
13489 24 : case CODE_FOR_avx512dq_rangepv4df_mask:
13490 24 : case CODE_FOR_avx512dq_rangepv8sf_mask:
13491 24 : case CODE_FOR_avx512dq_rangepv2df_mask:
13492 24 : case CODE_FOR_avx512dq_rangepv4sf_mask:
13493 24 : case CODE_FOR_avx_shufpd256_mask:
13494 24 : error ("the last argument must be a 4-bit immediate");
13495 24 : return const0_rtx;
13496 :
13497 15 : case CODE_FOR_sha1rnds4:
13498 15 : case CODE_FOR_sse4_1_blendpd:
13499 15 : case CODE_FOR_avx_vpermilv2df:
13500 15 : case CODE_FOR_avx_vpermilv2df_mask:
13501 15 : case CODE_FOR_xop_vpermil2v2df3:
13502 15 : case CODE_FOR_xop_vpermil2v4sf3:
13503 15 : case CODE_FOR_xop_vpermil2v4df3:
13504 15 : case CODE_FOR_xop_vpermil2v8sf3:
13505 15 : case CODE_FOR_avx512f_vinsertf32x4_mask:
13506 15 : case CODE_FOR_avx512f_vinserti32x4_mask:
13507 15 : case CODE_FOR_avx512f_vextractf32x4_mask:
13508 15 : case CODE_FOR_avx512f_vextracti32x4_mask:
13509 15 : case CODE_FOR_sse2_shufpd:
13510 15 : case CODE_FOR_sse2_shufpd_mask:
13511 15 : case CODE_FOR_avx512dq_shuf_f64x2_mask:
13512 15 : case CODE_FOR_avx512dq_shuf_i64x2_mask:
13513 15 : case CODE_FOR_avx512vl_shuf_i32x4_mask:
13514 15 : case CODE_FOR_avx512vl_shuf_f32x4_mask:
13515 15 : error ("the last argument must be a 2-bit immediate");
13516 15 : return const0_rtx;
13517 :
13518 30 : case CODE_FOR_avx_vextractf128v4df:
13519 30 : case CODE_FOR_avx_vextractf128v8sf:
13520 30 : case CODE_FOR_avx_vextractf128v8si:
13521 30 : case CODE_FOR_avx_vinsertf128v4df:
13522 30 : case CODE_FOR_avx_vinsertf128v8sf:
13523 30 : case CODE_FOR_avx_vinsertf128v8si:
13524 30 : case CODE_FOR_avx512f_vinsertf64x4_mask:
13525 30 : case CODE_FOR_avx512f_vinserti64x4_mask:
13526 30 : case CODE_FOR_avx512f_vextractf64x4_mask:
13527 30 : case CODE_FOR_avx512f_vextracti64x4_mask:
13528 30 : case CODE_FOR_avx512dq_vinsertf32x8_mask:
13529 30 : case CODE_FOR_avx512dq_vinserti32x8_mask:
13530 30 : case CODE_FOR_avx512vl_vinsertv4df:
13531 30 : case CODE_FOR_avx512vl_vinsertv4di:
13532 30 : case CODE_FOR_avx512vl_vinsertv8sf:
13533 30 : case CODE_FOR_avx512vl_vinsertv8si:
13534 30 : error ("the last argument must be a 1-bit immediate");
13535 30 : return const0_rtx;
13536 :
13537 16 : case CODE_FOR_avx_vmcmpv2df3:
13538 16 : case CODE_FOR_avx_vmcmpv4sf3:
13539 16 : case CODE_FOR_avx_cmpv2df3:
13540 16 : case CODE_FOR_avx_cmpv4sf3:
13541 16 : if (CONST_INT_P (op) && IN_RANGE (INTVAL (op), 8, 31))
13542 : {
13543 4 : error ("'%s' needs isa option %s", d->name, "-mavx");
13544 4 : return const0_rtx;
13545 : }
13546 : /* FALLTHRU */
13547 18 : case CODE_FOR_avx_cmpv4df3:
13548 18 : case CODE_FOR_avx_cmpv8sf3:
13549 18 : case CODE_FOR_avx512f_cmpv8df3_mask:
13550 18 : case CODE_FOR_avx512f_cmpv16sf3_mask:
13551 18 : case CODE_FOR_avx512f_vmcmpv2df3_mask:
13552 18 : case CODE_FOR_avx512f_vmcmpv4sf3_mask:
13553 18 : case CODE_FOR_avx512bw_cmpv32hf3_mask:
13554 18 : case CODE_FOR_avx512vl_cmpv16hf3_mask:
13555 18 : case CODE_FOR_avx512fp16_cmpv8hf3_mask:
13556 18 : error ("the last argument must be a 5-bit immediate");
13557 18 : return const0_rtx;
13558 :
13559 132 : default:
13560 132 : switch (nargs_constant)
13561 : {
13562 8 : case 2:
13563 8 : if ((mask_pos && (nargs - i - mask_pos) == nargs_constant) ||
13564 8 : (!mask_pos && (nargs - i) == nargs_constant))
13565 : {
13566 4 : error ("the next to last argument must be an 8-bit immediate");
13567 4 : break;
13568 : }
13569 : /* FALLTHRU */
13570 128 : case 1:
13571 128 : error ("the last argument must be an 8-bit immediate");
13572 128 : break;
13573 0 : default:
13574 0 : gcc_unreachable ();
13575 : }
13576 132 : return const0_rtx;
13577 : }
13578 : }
13579 : else
13580 : {
13581 183048 : if (VECTOR_MODE_P (mode))
13582 132445 : op = safe_vector_operand (op, mode);
13583 :
13584 : /* If we aren't optimizing, only allow one memory operand to
13585 : be generated. */
13586 183048 : if (memory_operand (op, mode))
13587 : {
13588 29812 : num_memory++;
13589 29812 : if (!optimize && num_memory > 1)
13590 13571 : op = copy_to_mode_reg (mode, op);
13591 : }
13592 :
13593 183048 : if (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)
13594 : {
13595 180638 : if (!match)
13596 42550 : op = copy_to_mode_reg (mode, op);
13597 : }
13598 : else
13599 : {
13600 2410 : op = copy_to_reg (op);
13601 2410 : op = lowpart_subreg (mode, op, GET_MODE (op));
13602 : }
13603 : }
13604 :
13605 202289 : xops[i] = op;
13606 : }
13607 :
13608 62769 : switch (nargs)
13609 : {
13610 6567 : case 1:
13611 6567 : pat = GEN_FCN (icode) (real_target, xops[0]);
13612 6567 : break;
13613 5782 : case 2:
13614 5782 : pat = GEN_FCN (icode) (real_target, xops[0], xops[1]);
13615 5782 : break;
13616 20633 : case 3:
13617 20633 : pat = GEN_FCN (icode) (real_target, xops[0], xops[1], xops[2]);
13618 20633 : break;
13619 27047 : case 4:
13620 27047 : pat = GEN_FCN (icode) (real_target, xops[0], xops[1],
13621 27047 : xops[2], xops[3]);
13622 27047 : break;
13623 2740 : case 5:
13624 2740 : pat = GEN_FCN (icode) (real_target, xops[0], xops[1],
13625 2740 : xops[2], xops[3], xops[4]);
13626 2740 : break;
13627 : case 6:
13628 : pat = GEN_FCN (icode) (real_target, xops[0], xops[1],
13629 : xops[2], xops[3], xops[4], xops[5]);
13630 : break;
13631 : default:
13632 : gcc_unreachable ();
13633 : }
13634 :
13635 62769 : if (! pat)
13636 : return 0;
13637 :
13638 62769 : emit_insn (pat);
13639 62769 : return target;
13640 : }
13641 :
13642 : /* Transform pattern of following layout:
13643 : (set A
13644 : (unspec [B C] UNSPEC_EMBEDDED_ROUNDING))
13645 : )
13646 : into:
13647 : (set (A B)) */
13648 :
13649 : static rtx
13650 4927 : ix86_erase_embedded_rounding (rtx pat)
13651 : {
13652 4927 : if (NONJUMP_INSN_P (pat))
13653 677 : pat = PATTERN (pat);
13654 :
13655 4927 : gcc_assert (GET_CODE (pat) == SET);
13656 4927 : rtx src = SET_SRC (pat);
13657 4927 : gcc_assert (XVECLEN (src, 0) == 2);
13658 4927 : rtx p0 = XVECEXP (src, 0, 0);
13659 4927 : gcc_assert (GET_CODE (src) == UNSPEC
13660 : && XINT (src, 1) == UNSPEC_EMBEDDED_ROUNDING);
13661 4927 : rtx res = gen_rtx_SET (SET_DEST (pat), p0);
13662 4927 : return res;
13663 : }
13664 :
13665 : /* Subroutine of ix86_expand_round_builtin to take care of comi insns
13666 : with rounding. */
13667 : static rtx
13668 103 : ix86_expand_sse_comi_round (const struct builtin_description *d,
13669 : tree exp, rtx target, bool comx_ok)
13670 : {
13671 103 : rtx pat, set_dst;
13672 103 : tree arg0 = CALL_EXPR_ARG (exp, 0);
13673 103 : tree arg1 = CALL_EXPR_ARG (exp, 1);
13674 103 : tree arg2 = CALL_EXPR_ARG (exp, 2);
13675 103 : tree arg3 = CALL_EXPR_ARG (exp, 3);
13676 103 : rtx op0 = expand_normal (arg0);
13677 103 : rtx op1 = expand_normal (arg1);
13678 103 : rtx op2 = expand_normal (arg2);
13679 103 : rtx op3 = expand_normal (arg3);
13680 103 : enum insn_code icode = d->icode;
13681 103 : const struct insn_data_d *insn_p = &insn_data[icode];
13682 103 : machine_mode mode0 = insn_p->operand[0].mode;
13683 103 : machine_mode mode1 = insn_p->operand[1].mode;
13684 :
13685 : /* See avxintrin.h for values. */
13686 103 : static const enum rtx_code comparisons[32] =
13687 : {
13688 : EQ, LT, LE, UNORDERED, NE, UNGE, UNGT, ORDERED,
13689 : UNEQ, UNLT, UNLE, UNORDERED, LTGT, GE, GT, ORDERED,
13690 : EQ, LT, LE, UNORDERED, NE, UNGE, UNGT, ORDERED,
13691 : UNEQ, UNLT, UNLE, UNORDERED, LTGT, GE, GT, ORDERED
13692 : };
13693 103 : static const bool ordereds[32] =
13694 : {
13695 : true, true, true, false, false, false, false, true,
13696 : false, false, false, true, true, true, true, false,
13697 : true, true, true, false, false, false, false, true,
13698 : false, false, false, true, true, true, true, false
13699 : };
13700 103 : static const bool non_signalings[32] =
13701 : {
13702 : true, false, false, true, true, false, false, true,
13703 : true, false, false, true, true, false, false, true,
13704 : false, true, true, false, false, true, true, false,
13705 : false, true, true, false, false, true, true, false
13706 : };
13707 :
13708 103 : if (!CONST_INT_P (op2))
13709 : {
13710 0 : error ("the third argument must be comparison constant");
13711 0 : return const0_rtx;
13712 : }
13713 103 : if (INTVAL (op2) < 0 || INTVAL (op2) >= 32)
13714 : {
13715 0 : error ("incorrect comparison mode");
13716 0 : return const0_rtx;
13717 : }
13718 :
13719 103 : if (!insn_p->operand[2].predicate (op3, SImode))
13720 : {
13721 4 : error ("incorrect rounding operand");
13722 4 : return const0_rtx;
13723 : }
13724 :
13725 99 : if (VECTOR_MODE_P (mode0))
13726 99 : op0 = safe_vector_operand (op0, mode0);
13727 99 : if (VECTOR_MODE_P (mode1))
13728 99 : op1 = safe_vector_operand (op1, mode1);
13729 :
13730 99 : enum rtx_code comparison = comparisons[INTVAL (op2)];
13731 99 : enum rtx_code orig_comp = comparison;
13732 99 : bool ordered = ordereds[INTVAL (op2)];
13733 99 : bool non_signaling = non_signalings[INTVAL (op2)];
13734 99 : rtx const_val = const0_rtx;
13735 :
13736 99 : bool check_unordered = false;
13737 99 : machine_mode mode = CCFPmode;
13738 99 : switch (comparison)
13739 : {
13740 8 : case ORDERED:
13741 8 : if (!ordered)
13742 : {
13743 4 : if (TARGET_AVX10_2 && comx_ok)
13744 : {
13745 : /* Unlike VCOMI{SH,SS,SD}, VCOMX{SH,SS,SD} will set SF
13746 : differently. So directly return true here. */
13747 0 : target = gen_reg_rtx (SImode);
13748 0 : emit_move_insn (target, const1_rtx);
13749 0 : return target;
13750 : }
13751 : else
13752 : {
13753 : /* NB: Use CCSmode/NE for _CMP_TRUE_UQ/_CMP_TRUE_US. */
13754 : if (!non_signaling)
13755 99 : ordered = true;
13756 99 : mode = CCSmode;
13757 : }
13758 : }
13759 : else
13760 : {
13761 : /* NB: Use CCPmode/NE for _CMP_ORD_Q/_CMP_ORD_S. */
13762 : if (non_signaling)
13763 : ordered = false;
13764 : mode = CCPmode;
13765 : }
13766 : comparison = NE;
13767 : break;
13768 8 : case UNORDERED:
13769 8 : if (ordered)
13770 : {
13771 4 : if (TARGET_AVX10_2 && comx_ok)
13772 : {
13773 : /* Unlike VCOMI{SH,SS,SD}, VCOMX{SH,SS,SD} will set SF
13774 : differently. So directly return false here. */
13775 0 : target = gen_reg_rtx (SImode);
13776 0 : emit_move_insn (target, const0_rtx);
13777 0 : return target;
13778 : }
13779 : else
13780 : {
13781 : /* NB: Use CCSmode/EQ for _CMP_FALSE_OQ/_CMP_FALSE_OS. */
13782 : if (non_signaling)
13783 99 : ordered = false;
13784 : mode = CCSmode;
13785 : }
13786 : }
13787 : else
13788 : {
13789 : /* NB: Use CCPmode/NE for _CMP_UNORD_Q/_CMP_UNORD_S. */
13790 : if (!non_signaling)
13791 99 : ordered = true;
13792 99 : mode = CCPmode;
13793 : }
13794 : comparison = EQ;
13795 : break;
13796 :
13797 40 : case LE: /* -> GE */
13798 40 : case LT: /* -> GT */
13799 40 : case UNGE: /* -> UNLE */
13800 40 : case UNGT: /* -> UNLT */
13801 40 : std::swap (op0, op1);
13802 40 : comparison = swap_condition (comparison);
13803 : /* FALLTHRU */
13804 68 : case GT:
13805 68 : case GE:
13806 68 : case UNEQ:
13807 68 : case UNLT:
13808 68 : case UNLE:
13809 68 : case LTGT:
13810 : /* These are supported by CCFPmode. NB: Use ordered/signaling
13811 : COMI or unordered/non-signaling UCOMI. Both set ZF, PF, CF
13812 : with NAN operands. */
13813 68 : if (ordered == non_signaling)
13814 : ordered = !ordered;
13815 : break;
13816 : /* NB: COMI/UCOMI will set ZF with NAN operands. Use CCZmode for
13817 : _CMP_EQ_OQ/_CMP_EQ_OS.
13818 : Under TARGET_AVX10_2, VCOMX/VUCOMX are always generated instead
13819 : of COMI/UCOMI, VCOMX/VUCOMX will not set ZF with NAN. */
13820 8 : case EQ:
13821 8 : if (!TARGET_AVX10_2 || !comx_ok)
13822 5 : check_unordered = true;
13823 : mode = CCZmode;
13824 : break;
13825 7 : case NE:
13826 : /* NB: COMI/UCOMI will set ZF with NAN operands. Use CCZmode for
13827 : _CMP_NEQ_UQ/_CMP_NEQ_US.
13828 : Under TARGET_AVX10_2, VCOMX/VUCOMX are always generated instead
13829 : of COMI/UCOMI, VCOMX/VUCOMX will not set ZF with NAN. */
13830 7 : gcc_assert (!ordered);
13831 7 : if (!TARGET_AVX10_2 || !comx_ok)
13832 4 : check_unordered = true;
13833 7 : mode = CCZmode;
13834 7 : const_val = const1_rtx;
13835 7 : break;
13836 0 : default:
13837 0 : gcc_unreachable ();
13838 : }
13839 :
13840 99 : target = gen_reg_rtx (SImode);
13841 99 : emit_move_insn (target, const_val);
13842 99 : target = gen_rtx_SUBREG (QImode, target, 0);
13843 :
13844 93 : if ((optimize && !register_operand (op0, mode0))
13845 192 : || !insn_p->operand[0].predicate (op0, mode0))
13846 6 : op0 = copy_to_mode_reg (mode0, op0);
13847 93 : if ((optimize && !register_operand (op1, mode1))
13848 192 : || !insn_p->operand[1].predicate (op1, mode1))
13849 6 : op1 = copy_to_mode_reg (mode1, op1);
13850 :
13851 : /* Generate comx instead of comi when EQ/NE to avoid NAN checks.
13852 : Use orig_comp to exclude ORDERED/UNORDERED cases. */
13853 99 : if ((orig_comp == EQ || orig_comp == NE)
13854 15 : && TARGET_AVX10_2 && comx_ok)
13855 : {
13856 6 : switch (icode)
13857 : {
13858 : case CODE_FOR_avx512fp16_comi_round:
13859 99 : icode = CODE_FOR_avx10_2_comxhf_round;
13860 : break;
13861 4 : case CODE_FOR_sse_comi_round:
13862 4 : icode = CODE_FOR_avx10_2_comxsf_round;
13863 4 : break;
13864 2 : case CODE_FOR_sse2_comi_round:
13865 2 : icode = CODE_FOR_avx10_2_comxdf_round;
13866 2 : break;
13867 :
13868 : default:
13869 : break;
13870 : }
13871 : }
13872 :
13873 : /* Generate comi instead of comx when UNEQ/LTGT to avoid NAN checks. */
13874 99 : if ((comparison == UNEQ || comparison == LTGT)
13875 8 : && TARGET_AVX10_2 && comx_ok)
13876 : {
13877 0 : switch (icode)
13878 : {
13879 : case CODE_FOR_avx10_2_comxhf_round:
13880 99 : icode = CODE_FOR_avx512fp16_comi_round;
13881 : break;
13882 0 : case CODE_FOR_avx10_2_comxsf_round:
13883 0 : icode = CODE_FOR_sse_comi_round;
13884 0 : break;
13885 0 : case CODE_FOR_avx10_2_comxdf_round:
13886 0 : icode = CODE_FOR_sse2_comi_round;
13887 0 : break;
13888 :
13889 : default:
13890 : break;
13891 : }
13892 : }
13893 :
13894 : /*
13895 : 1. COMI/VCOMX: ordered and signaling.
13896 : 2. UCOMI/VUCOMX: unordered and non-signaling.
13897 : */
13898 99 : if (non_signaling)
13899 38 : switch (icode)
13900 : {
13901 : case CODE_FOR_sse_comi_round:
13902 : icode = CODE_FOR_sse_ucomi_round;
13903 : break;
13904 17 : case CODE_FOR_sse2_comi_round:
13905 17 : icode = CODE_FOR_sse2_ucomi_round;
13906 17 : break;
13907 0 : case CODE_FOR_avx512fp16_comi_round:
13908 0 : icode = CODE_FOR_avx512fp16_ucomi_round;
13909 0 : break;
13910 3 : case CODE_FOR_avx10_2_comxsf_round:
13911 3 : icode = CODE_FOR_avx10_2_ucomxsf_round;
13912 3 : break;
13913 0 : case CODE_FOR_avx10_2_comxhf_round:
13914 0 : icode = CODE_FOR_avx10_2_ucomxhf_round;
13915 0 : break;
13916 1 : case CODE_FOR_avx10_2_comxdf_round:
13917 1 : icode = CODE_FOR_avx10_2_ucomxdf_round;
13918 1 : break;
13919 0 : default:
13920 0 : gcc_unreachable ();
13921 : }
13922 :
13923 99 : pat = GEN_FCN (icode) (op0, op1, op3);
13924 99 : if (! pat)
13925 : return 0;
13926 :
13927 : /* Rounding operand can be either NO_ROUND or ROUND_SAE at this point. */
13928 99 : if (INTVAL (op3) == NO_ROUND)
13929 : {
13930 1 : pat = ix86_erase_embedded_rounding (pat);
13931 1 : if (! pat)
13932 : return 0;
13933 :
13934 1 : set_dst = SET_DEST (pat);
13935 : }
13936 : else
13937 : {
13938 98 : gcc_assert (GET_CODE (pat) == SET);
13939 98 : set_dst = SET_DEST (pat);
13940 : }
13941 :
13942 99 : emit_insn (pat);
13943 :
13944 99 : return ix86_ssecom_setcc (comparison, check_unordered, mode,
13945 99 : set_dst, target);
13946 : }
13947 :
13948 : static rtx
13949 15538 : ix86_expand_round_builtin (const struct builtin_description *d,
13950 : tree exp, rtx target)
13951 : {
13952 15538 : rtx pat;
13953 15538 : unsigned int i, nargs;
13954 15538 : rtx xops[6];
13955 15538 : enum insn_code icode = d->icode;
13956 15538 : const struct insn_data_d *insn_p = &insn_data[icode];
13957 15538 : machine_mode tmode = insn_p->operand[0].mode;
13958 15538 : unsigned int nargs_constant = 0;
13959 15538 : unsigned int redundant_embed_rnd = 0;
13960 :
13961 15538 : switch ((enum ix86_builtin_func_type) d->flag)
13962 : {
13963 : case UINT64_FTYPE_V2DF_INT:
13964 : case UINT64_FTYPE_V4SF_INT:
13965 : case UINT64_FTYPE_V8HF_INT:
13966 : case UINT_FTYPE_V2DF_INT:
13967 : case UINT_FTYPE_V4SF_INT:
13968 : case UINT_FTYPE_V8HF_INT:
13969 : case INT64_FTYPE_V2DF_INT:
13970 : case INT64_FTYPE_V4SF_INT:
13971 : case INT64_FTYPE_V8HF_INT:
13972 : case INT_FTYPE_V2DF_INT:
13973 : case INT_FTYPE_V4SF_INT:
13974 : case INT_FTYPE_V8HF_INT:
13975 : nargs = 2;
13976 : break;
13977 634 : case V32HF_FTYPE_V32HF_V32HF_INT:
13978 634 : case V8HF_FTYPE_V8HF_V8HF_INT:
13979 634 : case V8HF_FTYPE_V8HF_INT_INT:
13980 634 : case V8HF_FTYPE_V8HF_UINT_INT:
13981 634 : case V8HF_FTYPE_V8HF_INT64_INT:
13982 634 : case V8HF_FTYPE_V8HF_UINT64_INT:
13983 634 : case V4SF_FTYPE_V4SF_UINT_INT:
13984 634 : case V4SF_FTYPE_V4SF_UINT64_INT:
13985 634 : case V2DF_FTYPE_V2DF_UINT64_INT:
13986 634 : case V4SF_FTYPE_V4SF_INT_INT:
13987 634 : case V4SF_FTYPE_V4SF_INT64_INT:
13988 634 : case V2DF_FTYPE_V2DF_INT64_INT:
13989 634 : case V4SF_FTYPE_V4SF_V4SF_INT:
13990 634 : case V2DF_FTYPE_V2DF_V2DF_INT:
13991 634 : case V4SF_FTYPE_V4SF_V2DF_INT:
13992 634 : case V2DF_FTYPE_V2DF_V4SF_INT:
13993 634 : nargs = 3;
13994 634 : break;
13995 4554 : case V8SF_FTYPE_V8DF_V8SF_QI_INT:
13996 4554 : case V8DF_FTYPE_V8DF_V8DF_QI_INT:
13997 4554 : case V32HI_FTYPE_V32HF_V32HI_USI_INT:
13998 4554 : case V32HI_FTYPE_V32BF_V32HI_USI_INT:
13999 4554 : case V8SI_FTYPE_V8DF_V8SI_QI_INT:
14000 4554 : case V8DI_FTYPE_V8HF_V8DI_UQI_INT:
14001 4554 : case V8DI_FTYPE_V8DF_V8DI_QI_INT:
14002 4554 : case V8SF_FTYPE_V8DI_V8SF_QI_INT:
14003 4554 : case V8DF_FTYPE_V8DI_V8DF_QI_INT:
14004 4554 : case V8DF_FTYPE_V8HF_V8DF_UQI_INT:
14005 4554 : case V16SF_FTYPE_V16HF_V16SF_UHI_INT:
14006 4554 : case V32HF_FTYPE_V32HI_V32HF_USI_INT:
14007 4554 : case V32HF_FTYPE_V32HF_V32HF_USI_INT:
14008 4554 : case V32HF_FTYPE_V32HF_V32HF_V32HF_INT:
14009 4554 : case V16SF_FTYPE_V16SF_V16SF_HI_INT:
14010 4554 : case V8DI_FTYPE_V8SF_V8DI_QI_INT:
14011 4554 : case V16SF_FTYPE_V16SI_V16SF_HI_INT:
14012 4554 : case V16SI_FTYPE_V16SF_V16SI_HI_INT:
14013 4554 : case V16SI_FTYPE_V16SF_V16SI_UHI_INT:
14014 4554 : case V16SI_FTYPE_V16HF_V16SI_UHI_INT:
14015 4554 : case V16HF_FTYPE_V16SI_V16HF_UHI_INT:
14016 4554 : case V8DF_FTYPE_V8SF_V8DF_QI_INT:
14017 4554 : case V16SF_FTYPE_V16HI_V16SF_HI_INT:
14018 4554 : case V2DF_FTYPE_V2DF_V2DF_V2DF_INT:
14019 4554 : case V4SF_FTYPE_V4SF_V4SF_V4SF_INT:
14020 4554 : case V8HF_FTYPE_V8DI_V8HF_UQI_INT:
14021 4554 : case V8HF_FTYPE_V8DF_V8HF_UQI_INT:
14022 4554 : case V16HF_FTYPE_V16SF_V16HF_UHI_INT:
14023 4554 : case V16HI_FTYPE_V16BF_V16HI_UHI_INT:
14024 4554 : case V8HF_FTYPE_V8HF_V8HF_V8HF_INT:
14025 4554 : nargs = 4;
14026 4554 : break;
14027 163 : case V4SF_FTYPE_V4SF_V4SF_INT_INT:
14028 163 : case V2DF_FTYPE_V2DF_V2DF_INT_INT:
14029 163 : nargs_constant = 2;
14030 163 : nargs = 4;
14031 163 : break;
14032 103 : case INT_FTYPE_V4SF_V4SF_INT_INT:
14033 103 : case INT_FTYPE_V2DF_V2DF_INT_INT:
14034 103 : return ix86_expand_sse_comi_round (d, exp, target, true);
14035 6216 : case V8DF_FTYPE_V8DF_V8DF_V8DF_UQI_INT:
14036 6216 : case V2DF_FTYPE_V2DF_V2DF_V2DF_UQI_INT:
14037 6216 : case V4SF_FTYPE_V4SF_V4SF_V4SF_UQI_INT:
14038 6216 : case V4SF_FTYPE_V8HF_V4SF_V4SF_UQI_INT:
14039 6216 : case V16SF_FTYPE_V16SF_V16SF_V16SF_HI_INT:
14040 6216 : case V32HF_FTYPE_V32HF_V32HF_V32HF_UHI_INT:
14041 6216 : case V32HF_FTYPE_V32HF_V32HF_V32HF_USI_INT:
14042 6216 : case V2DF_FTYPE_V8HF_V2DF_V2DF_UQI_INT:
14043 6216 : case V2DF_FTYPE_V2DF_V2DF_V2DF_QI_INT:
14044 6216 : case V2DF_FTYPE_V2DF_V4SF_V2DF_QI_INT:
14045 6216 : case V2DF_FTYPE_V2DF_V4SF_V2DF_UQI_INT:
14046 6216 : case V4SF_FTYPE_V4SF_V4SF_V4SF_QI_INT:
14047 6216 : case V4SF_FTYPE_V4SF_V2DF_V4SF_QI_INT:
14048 6216 : case V4SF_FTYPE_V4SF_V2DF_V4SF_UQI_INT:
14049 6216 : case V8HF_FTYPE_V8HF_V8HF_V8HF_UQI_INT:
14050 6216 : case V8HF_FTYPE_V2DF_V8HF_V8HF_UQI_INT:
14051 6216 : case V8HF_FTYPE_V4SF_V8HF_V8HF_UQI_INT:
14052 6216 : case V32HF_FTYPE_V16SF_V16SF_V32HF_USI_INT:
14053 6216 : nargs = 5;
14054 6216 : break;
14055 635 : case V32HF_FTYPE_V32HF_INT_V32HF_USI_INT:
14056 635 : case V16SF_FTYPE_V16SF_INT_V16SF_HI_INT:
14057 635 : case V8DF_FTYPE_V8DF_INT_V8DF_QI_INT:
14058 635 : case V8DF_FTYPE_V8DF_INT_V8DF_UQI_INT:
14059 635 : case V16SF_FTYPE_V16SF_INT_V16SF_UHI_INT:
14060 635 : nargs_constant = 4;
14061 635 : nargs = 5;
14062 635 : break;
14063 1181 : case UQI_FTYPE_V8DF_V8DF_INT_UQI_INT:
14064 1181 : case UQI_FTYPE_V2DF_V2DF_INT_UQI_INT:
14065 1181 : case UHI_FTYPE_V16SF_V16SF_INT_UHI_INT:
14066 1181 : case UQI_FTYPE_V4SF_V4SF_INT_UQI_INT:
14067 1181 : case USI_FTYPE_V32HF_V32HF_INT_USI_INT:
14068 1181 : case UQI_FTYPE_V8HF_V8HF_INT_UQI_INT:
14069 1181 : nargs_constant = 3;
14070 1181 : nargs = 5;
14071 1181 : break;
14072 1071 : case V16SF_FTYPE_V16SF_V16SF_INT_V16SF_HI_INT:
14073 1071 : case V8DF_FTYPE_V8DF_V8DF_INT_V8DF_QI_INT:
14074 1071 : case V4SF_FTYPE_V4SF_V4SF_INT_V4SF_QI_INT:
14075 1071 : case V2DF_FTYPE_V2DF_V2DF_INT_V2DF_QI_INT:
14076 1071 : case V2DF_FTYPE_V2DF_V2DF_INT_V2DF_UQI_INT:
14077 1071 : case V4SF_FTYPE_V4SF_V4SF_INT_V4SF_UQI_INT:
14078 1071 : case V8HF_FTYPE_V8HF_V8HF_INT_V8HF_UQI_INT:
14079 1071 : case V8DF_FTYPE_V8DF_V8DF_INT_V8DF_UQI_INT:
14080 1071 : case V32HF_FTYPE_V32HF_V32HF_INT_V32HF_USI_INT:
14081 1071 : case V16SF_FTYPE_V16SF_V16SF_INT_V16SF_UHI_INT:
14082 1071 : nargs = 6;
14083 1071 : nargs_constant = 4;
14084 1071 : break;
14085 252 : case V8DF_FTYPE_V8DF_V8DF_V8DI_INT_QI_INT:
14086 252 : case V16SF_FTYPE_V16SF_V16SF_V16SI_INT_HI_INT:
14087 252 : case V2DF_FTYPE_V2DF_V2DF_V2DI_INT_QI_INT:
14088 252 : case V4SF_FTYPE_V4SF_V4SF_V4SI_INT_QI_INT:
14089 252 : nargs = 6;
14090 252 : nargs_constant = 3;
14091 252 : break;
14092 0 : default:
14093 0 : gcc_unreachable ();
14094 : }
14095 14706 : gcc_assert (nargs <= ARRAY_SIZE (xops));
14096 :
14097 15435 : if (optimize
14098 4265 : || target == 0
14099 4265 : || GET_MODE (target) != tmode
14100 19700 : || !insn_p->operand[0].predicate (target, tmode))
14101 11170 : target = gen_reg_rtx (tmode);
14102 :
14103 85110 : for (i = 0; i < nargs; i++)
14104 : {
14105 70230 : tree arg = CALL_EXPR_ARG (exp, i);
14106 70230 : rtx op = ix86_expand_unsigned_small_int_cst_argument (arg);
14107 70230 : machine_mode mode = insn_p->operand[i + 1].mode;
14108 70230 : bool match = insn_p->operand[i + 1].predicate (op, mode);
14109 :
14110 70230 : if (i == nargs - nargs_constant)
14111 : {
14112 3302 : if (!match)
14113 : {
14114 40 : switch (icode)
14115 : {
14116 12 : case CODE_FOR_avx512f_getmantv8df_mask_round:
14117 12 : case CODE_FOR_avx512f_getmantv16sf_mask_round:
14118 12 : case CODE_FOR_avx512bw_getmantv32hf_mask_round:
14119 12 : case CODE_FOR_avx512f_vgetmantv2df_round:
14120 12 : case CODE_FOR_avx512f_vgetmantv2df_mask_round:
14121 12 : case CODE_FOR_avx512f_vgetmantv4sf_round:
14122 12 : case CODE_FOR_avx512f_vgetmantv4sf_mask_round:
14123 12 : case CODE_FOR_avx512f_vgetmantv8hf_mask_round:
14124 12 : error ("the immediate argument must be a 4-bit immediate");
14125 12 : return const0_rtx;
14126 8 : case CODE_FOR_avx512f_cmpv8df3_mask_round:
14127 8 : case CODE_FOR_avx512f_cmpv16sf3_mask_round:
14128 8 : case CODE_FOR_avx512f_vmcmpv2df3_mask_round:
14129 8 : case CODE_FOR_avx512f_vmcmpv4sf3_mask_round:
14130 8 : case CODE_FOR_avx512f_vmcmpv8hf3_mask_round:
14131 8 : case CODE_FOR_avx512bw_cmpv32hf3_mask_round:
14132 8 : error ("the immediate argument must be a 5-bit immediate");
14133 8 : return const0_rtx;
14134 20 : default:
14135 20 : error ("the immediate argument must be an 8-bit immediate");
14136 20 : return const0_rtx;
14137 : }
14138 : }
14139 : }
14140 66928 : else if (i == nargs-1)
14141 : {
14142 15395 : if (!insn_p->operand[nargs].predicate (op, SImode))
14143 : {
14144 515 : error ("incorrect rounding operand");
14145 515 : return const0_rtx;
14146 : }
14147 :
14148 : /* If there is no rounding use normal version of the pattern. */
14149 14880 : if (INTVAL (op) == NO_ROUND)
14150 : {
14151 : /* Skip erasing embedded rounding for below expanders who
14152 : generates multiple insns. In ix86_erase_embedded_rounding
14153 : the pattern will be transformed to a single set, and emit_insn
14154 : appends the set instead of insert it to chain. So the insns
14155 : emitted inside define_expander would be ignored. */
14156 4958 : switch (icode)
14157 : {
14158 : case CODE_FOR_avx512bw_fmaddc_v32hf_mask1_round:
14159 : case CODE_FOR_avx512bw_fcmaddc_v32hf_mask1_round:
14160 : case CODE_FOR_avx512fp16_fmaddcsh_v8hf_mask1_round:
14161 : case CODE_FOR_avx512fp16_fcmaddcsh_v8hf_mask1_round:
14162 : case CODE_FOR_avx512fp16_fmaddcsh_v8hf_mask3_round:
14163 : case CODE_FOR_avx512fp16_fcmaddcsh_v8hf_mask3_round:
14164 : redundant_embed_rnd = 0;
14165 : break;
14166 4926 : default:
14167 4926 : redundant_embed_rnd = 1;
14168 4926 : break;
14169 : }
14170 : }
14171 : }
14172 : else
14173 : {
14174 51533 : if (VECTOR_MODE_P (mode))
14175 37633 : op = safe_vector_operand (op, mode);
14176 :
14177 51533 : op = fixup_modeless_constant (op, mode);
14178 :
14179 51533 : if (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)
14180 : {
14181 51533 : if (optimize || !match)
14182 45205 : op = copy_to_mode_reg (mode, op);
14183 : }
14184 : else
14185 : {
14186 0 : op = copy_to_reg (op);
14187 0 : op = lowpart_subreg (mode, op, GET_MODE (op));
14188 : }
14189 : }
14190 :
14191 69675 : xops[i] = op;
14192 : }
14193 :
14194 14880 : switch (nargs)
14195 : {
14196 : case 1:
14197 : pat = GEN_FCN (icode) (target, xops[0]);
14198 : break;
14199 696 : case 2:
14200 696 : pat = GEN_FCN (icode) (target, xops[0], xops[1]);
14201 696 : break;
14202 590 : case 3:
14203 590 : pat = GEN_FCN (icode) (target, xops[0], xops[1], xops[2]);
14204 590 : break;
14205 4593 : case 4:
14206 4593 : pat = GEN_FCN (icode) (target, xops[0], xops[1],
14207 4593 : xops[2], xops[3]);
14208 4593 : break;
14209 7728 : case 5:
14210 7728 : pat = GEN_FCN (icode) (target, xops[0], xops[1],
14211 7728 : xops[2], xops[3], xops[4]);
14212 7728 : break;
14213 1273 : case 6:
14214 1273 : pat = GEN_FCN (icode) (target, xops[0], xops[1],
14215 1273 : xops[2], xops[3], xops[4], xops[5]);
14216 1273 : break;
14217 : default:
14218 : gcc_unreachable ();
14219 : }
14220 :
14221 14880 : if (!pat)
14222 : return 0;
14223 :
14224 14880 : if (redundant_embed_rnd)
14225 4926 : pat = ix86_erase_embedded_rounding (pat);
14226 :
14227 14880 : emit_insn (pat);
14228 14880 : return target;
14229 : }
14230 :
14231 : /* Subroutine of ix86_expand_builtin to take care of special insns
14232 : with variable number of operands. */
14233 :
14234 : static rtx
14235 27102 : ix86_expand_special_args_builtin (const struct builtin_description *d,
14236 : tree exp, rtx target)
14237 : {
14238 27102 : tree arg;
14239 27102 : rtx pat, op;
14240 27102 : unsigned int i, nargs, arg_adjust, memory;
14241 27102 : unsigned int constant = 100;
14242 27102 : bool aligned_mem = false;
14243 27102 : rtx xops[4];
14244 27102 : enum insn_code icode = d->icode;
14245 27102 : const struct insn_data_d *insn_p = &insn_data[icode];
14246 27102 : machine_mode tmode = insn_p->operand[0].mode;
14247 27102 : enum { load, store } klass;
14248 :
14249 27102 : switch ((enum ix86_builtin_func_type) d->flag)
14250 : {
14251 15360 : case VOID_FTYPE_VOID:
14252 15360 : emit_insn (GEN_FCN (icode) (target));
14253 15360 : return 0;
14254 : case VOID_FTYPE_UINT64:
14255 : case VOID_FTYPE_UNSIGNED:
14256 : nargs = 0;
14257 : klass = store;
14258 : memory = 0;
14259 : break;
14260 :
14261 7508 : case INT_FTYPE_VOID:
14262 7508 : case USHORT_FTYPE_VOID:
14263 7508 : case UINT64_FTYPE_VOID:
14264 7508 : case UINT_FTYPE_VOID:
14265 7508 : case UINT8_FTYPE_VOID:
14266 7508 : case UNSIGNED_FTYPE_VOID:
14267 7508 : nargs = 0;
14268 7508 : klass = load;
14269 7508 : memory = 0;
14270 7508 : break;
14271 360 : case CHAR_FTYPE_PCCHAR:
14272 360 : case SHORT_FTYPE_PCSHORT:
14273 360 : case INT_FTYPE_PCINT:
14274 360 : case INT64_FTYPE_PCINT64:
14275 360 : case UINT64_FTYPE_PUNSIGNED:
14276 360 : case V2DI_FTYPE_PV2DI:
14277 360 : case V4DI_FTYPE_PV4DI:
14278 360 : case V32QI_FTYPE_PCCHAR:
14279 360 : case V16QI_FTYPE_PCCHAR:
14280 360 : case V8SF_FTYPE_PCV4SF:
14281 360 : case V8SF_FTYPE_PCFLOAT:
14282 360 : case V4SF_FTYPE_PCFLOAT:
14283 360 : case V4SF_FTYPE_PCFLOAT16:
14284 360 : case V4SF_FTYPE_PCBFLOAT16:
14285 360 : case V4SF_FTYPE_PCV8BF:
14286 360 : case V4SF_FTYPE_PCV8HF:
14287 360 : case V8SF_FTYPE_PCFLOAT16:
14288 360 : case V8SF_FTYPE_PCBFLOAT16:
14289 360 : case V8SF_FTYPE_PCV16HF:
14290 360 : case V8SF_FTYPE_PCV16BF:
14291 360 : case V4DF_FTYPE_PCV2DF:
14292 360 : case V4DF_FTYPE_PCDOUBLE:
14293 360 : case V2DF_FTYPE_PCDOUBLE:
14294 360 : case VOID_FTYPE_PVOID:
14295 360 : case V8DI_FTYPE_PV8DI:
14296 360 : nargs = 1;
14297 360 : klass = load;
14298 360 : memory = 0;
14299 360 : switch (icode)
14300 : {
14301 : case CODE_FOR_sse4_1_movntdqa:
14302 : case CODE_FOR_avx2_movntdqa:
14303 : case CODE_FOR_avx512f_movntdqa:
14304 : aligned_mem = true;
14305 : break;
14306 : default:
14307 : break;
14308 : }
14309 : break;
14310 372 : case VOID_FTYPE_PV2SF_V4SF:
14311 372 : case VOID_FTYPE_PV8DI_V8DI:
14312 372 : case VOID_FTYPE_PV4DI_V4DI:
14313 372 : case VOID_FTYPE_PV2DI_V2DI:
14314 372 : case VOID_FTYPE_PCHAR_V32QI:
14315 372 : case VOID_FTYPE_PCHAR_V16QI:
14316 372 : case VOID_FTYPE_PFLOAT_V16SF:
14317 372 : case VOID_FTYPE_PFLOAT_V8SF:
14318 372 : case VOID_FTYPE_PFLOAT_V4SF:
14319 372 : case VOID_FTYPE_PDOUBLE_V8DF:
14320 372 : case VOID_FTYPE_PDOUBLE_V4DF:
14321 372 : case VOID_FTYPE_PDOUBLE_V2DF:
14322 372 : case VOID_FTYPE_PLONGLONG_LONGLONG:
14323 372 : case VOID_FTYPE_PULONGLONG_ULONGLONG:
14324 372 : case VOID_FTYPE_PUNSIGNED_UNSIGNED:
14325 372 : case VOID_FTYPE_PINT_INT:
14326 372 : nargs = 1;
14327 372 : klass = store;
14328 : /* Reserve memory operand for target. */
14329 372 : memory = ARRAY_SIZE (xops);
14330 372 : switch (icode)
14331 : {
14332 : /* These builtins and instructions require the memory
14333 : to be properly aligned. */
14334 : case CODE_FOR_avx_movntv4di:
14335 : case CODE_FOR_sse2_movntv2di:
14336 : case CODE_FOR_avx_movntv8sf:
14337 : case CODE_FOR_sse_movntv4sf:
14338 : case CODE_FOR_sse4a_vmmovntv4sf:
14339 : case CODE_FOR_avx_movntv4df:
14340 : case CODE_FOR_sse2_movntv2df:
14341 : case CODE_FOR_sse4a_vmmovntv2df:
14342 : case CODE_FOR_sse2_movntidi:
14343 : case CODE_FOR_sse_movntq:
14344 : case CODE_FOR_sse2_movntisi:
14345 : case CODE_FOR_avx512f_movntv16sf:
14346 : case CODE_FOR_avx512f_movntv8df:
14347 : case CODE_FOR_avx512f_movntv8di:
14348 : aligned_mem = true;
14349 : break;
14350 : default:
14351 : break;
14352 : }
14353 : break;
14354 0 : case VOID_FTYPE_PVOID_PCVOID:
14355 0 : nargs = 1;
14356 0 : klass = store;
14357 0 : memory = 0;
14358 :
14359 0 : break;
14360 26 : case V4SF_FTYPE_V4SF_PCV2SF:
14361 26 : case V2DF_FTYPE_V2DF_PCDOUBLE:
14362 26 : nargs = 2;
14363 26 : klass = load;
14364 26 : memory = 1;
14365 26 : break;
14366 93 : case V8SF_FTYPE_PCV8SF_V8SI:
14367 93 : case V4DF_FTYPE_PCV4DF_V4DI:
14368 93 : case V4SF_FTYPE_PCV4SF_V4SI:
14369 93 : case V2DF_FTYPE_PCV2DF_V2DI:
14370 93 : case V8SI_FTYPE_PCV8SI_V8SI:
14371 93 : case V4DI_FTYPE_PCV4DI_V4DI:
14372 93 : case V4SI_FTYPE_PCV4SI_V4SI:
14373 93 : case V2DI_FTYPE_PCV2DI_V2DI:
14374 93 : case VOID_FTYPE_INT_INT64:
14375 93 : nargs = 2;
14376 93 : klass = load;
14377 93 : memory = 0;
14378 93 : break;
14379 360 : case VOID_FTYPE_PV8DF_V8DF_UQI:
14380 360 : case VOID_FTYPE_PV4DF_V4DF_UQI:
14381 360 : case VOID_FTYPE_PV2DF_V2DF_UQI:
14382 360 : case VOID_FTYPE_PV16SF_V16SF_UHI:
14383 360 : case VOID_FTYPE_PV8SF_V8SF_UQI:
14384 360 : case VOID_FTYPE_PV4SF_V4SF_UQI:
14385 360 : case VOID_FTYPE_PV8DI_V8DI_UQI:
14386 360 : case VOID_FTYPE_PV4DI_V4DI_UQI:
14387 360 : case VOID_FTYPE_PV2DI_V2DI_UQI:
14388 360 : case VOID_FTYPE_PV16SI_V16SI_UHI:
14389 360 : case VOID_FTYPE_PV8SI_V8SI_UQI:
14390 360 : case VOID_FTYPE_PV4SI_V4SI_UQI:
14391 360 : case VOID_FTYPE_PV64QI_V64QI_UDI:
14392 360 : case VOID_FTYPE_PV32HI_V32HI_USI:
14393 360 : case VOID_FTYPE_PV32QI_V32QI_USI:
14394 360 : case VOID_FTYPE_PV16QI_V16QI_UHI:
14395 360 : case VOID_FTYPE_PV16HI_V16HI_UHI:
14396 360 : case VOID_FTYPE_PV8HI_V8HI_UQI:
14397 360 : switch (icode)
14398 : {
14399 : /* These builtins and instructions require the memory
14400 : to be properly aligned. */
14401 : case CODE_FOR_avx512f_storev16sf_mask:
14402 : case CODE_FOR_avx512f_storev16si_mask:
14403 : case CODE_FOR_avx512f_storev8df_mask:
14404 : case CODE_FOR_avx512f_storev8di_mask:
14405 : case CODE_FOR_avx512vl_storev8sf_mask:
14406 : case CODE_FOR_avx512vl_storev8si_mask:
14407 : case CODE_FOR_avx512vl_storev4df_mask:
14408 : case CODE_FOR_avx512vl_storev4di_mask:
14409 : case CODE_FOR_avx512vl_storev4sf_mask:
14410 : case CODE_FOR_avx512vl_storev4si_mask:
14411 : case CODE_FOR_avx512vl_storev2df_mask:
14412 : case CODE_FOR_avx512vl_storev2di_mask:
14413 11742 : aligned_mem = true;
14414 : break;
14415 : default:
14416 : break;
14417 : }
14418 : /* FALLTHRU */
14419 : case VOID_FTYPE_PV8SF_V8SI_V8SF:
14420 : case VOID_FTYPE_PV4DF_V4DI_V4DF:
14421 : case VOID_FTYPE_PV4SF_V4SI_V4SF:
14422 : case VOID_FTYPE_PV2DF_V2DI_V2DF:
14423 : case VOID_FTYPE_PV8SI_V8SI_V8SI:
14424 : case VOID_FTYPE_PV4DI_V4DI_V4DI:
14425 : case VOID_FTYPE_PV4SI_V4SI_V4SI:
14426 : case VOID_FTYPE_PV2DI_V2DI_V2DI:
14427 : case VOID_FTYPE_PV8SI_V8DI_UQI:
14428 : case VOID_FTYPE_PV8HI_V8DI_UQI:
14429 : case VOID_FTYPE_PV16HI_V16SI_UHI:
14430 : case VOID_FTYPE_PUDI_V8DI_UQI:
14431 : case VOID_FTYPE_PV16QI_V16SI_UHI:
14432 : case VOID_FTYPE_PV4SI_V4DI_UQI:
14433 : case VOID_FTYPE_PUDI_V2DI_UQI:
14434 : case VOID_FTYPE_PUDI_V4DI_UQI:
14435 : case VOID_FTYPE_PUSI_V2DI_UQI:
14436 : case VOID_FTYPE_PV8HI_V8SI_UQI:
14437 : case VOID_FTYPE_PUDI_V4SI_UQI:
14438 : case VOID_FTYPE_PUSI_V4DI_UQI:
14439 : case VOID_FTYPE_PUHI_V2DI_UQI:
14440 : case VOID_FTYPE_PUDI_V8SI_UQI:
14441 : case VOID_FTYPE_PUSI_V4SI_UQI:
14442 : case VOID_FTYPE_PCHAR_V64QI_UDI:
14443 : case VOID_FTYPE_PCHAR_V32QI_USI:
14444 : case VOID_FTYPE_PCHAR_V16QI_UHI:
14445 : case VOID_FTYPE_PSHORT_V32HI_USI:
14446 : case VOID_FTYPE_PSHORT_V16HI_UHI:
14447 : case VOID_FTYPE_PSHORT_V8HI_UQI:
14448 : case VOID_FTYPE_PINT_V16SI_UHI:
14449 : case VOID_FTYPE_PINT_V8SI_UQI:
14450 : case VOID_FTYPE_PINT_V4SI_UQI:
14451 : case VOID_FTYPE_PINT64_V8DI_UQI:
14452 : case VOID_FTYPE_PINT64_V4DI_UQI:
14453 : case VOID_FTYPE_PINT64_V2DI_UQI:
14454 : case VOID_FTYPE_PDOUBLE_V8DF_UQI:
14455 : case VOID_FTYPE_PDOUBLE_V4DF_UQI:
14456 : case VOID_FTYPE_PDOUBLE_V2DF_UQI:
14457 : case VOID_FTYPE_PFLOAT_V16SF_UHI:
14458 : case VOID_FTYPE_PFLOAT_V8SF_UQI:
14459 : case VOID_FTYPE_PFLOAT_V4SF_UQI:
14460 : case VOID_FTYPE_PCFLOAT16_V8HF_UQI:
14461 : case VOID_FTYPE_PV32QI_V32HI_USI:
14462 : case VOID_FTYPE_PV16QI_V16HI_UHI:
14463 : case VOID_FTYPE_PUDI_V8HI_UQI:
14464 : nargs = 2;
14465 : klass = store;
14466 : /* Reserve memory operand for target. */
14467 : memory = ARRAY_SIZE (xops);
14468 : break;
14469 1243 : case V4SF_FTYPE_PCV4SF_V4SF_UQI:
14470 1243 : case V8SF_FTYPE_PCV8SF_V8SF_UQI:
14471 1243 : case V16SF_FTYPE_PCV16SF_V16SF_UHI:
14472 1243 : case V4SI_FTYPE_PCV4SI_V4SI_UQI:
14473 1243 : case V8SI_FTYPE_PCV8SI_V8SI_UQI:
14474 1243 : case V16SI_FTYPE_PCV16SI_V16SI_UHI:
14475 1243 : case V2DF_FTYPE_PCV2DF_V2DF_UQI:
14476 1243 : case V4DF_FTYPE_PCV4DF_V4DF_UQI:
14477 1243 : case V8DF_FTYPE_PCV8DF_V8DF_UQI:
14478 1243 : case V2DI_FTYPE_PCV2DI_V2DI_UQI:
14479 1243 : case V4DI_FTYPE_PCV4DI_V4DI_UQI:
14480 1243 : case V8DI_FTYPE_PCV8DI_V8DI_UQI:
14481 1243 : case V64QI_FTYPE_PCV64QI_V64QI_UDI:
14482 1243 : case V32HI_FTYPE_PCV32HI_V32HI_USI:
14483 1243 : case V32QI_FTYPE_PCV32QI_V32QI_USI:
14484 1243 : case V16QI_FTYPE_PCV16QI_V16QI_UHI:
14485 1243 : case V16HI_FTYPE_PCV16HI_V16HI_UHI:
14486 1243 : case V8HI_FTYPE_PCV8HI_V8HI_UQI:
14487 1243 : switch (icode)
14488 : {
14489 : /* These builtins and instructions require the memory
14490 : to be properly aligned. */
14491 : case CODE_FOR_avx512f_loadv16sf_mask:
14492 : case CODE_FOR_avx512f_loadv16si_mask:
14493 : case CODE_FOR_avx512f_loadv8df_mask:
14494 : case CODE_FOR_avx512f_loadv8di_mask:
14495 : case CODE_FOR_avx512vl_loadv8sf_mask:
14496 : case CODE_FOR_avx512vl_loadv8si_mask:
14497 : case CODE_FOR_avx512vl_loadv4df_mask:
14498 : case CODE_FOR_avx512vl_loadv4di_mask:
14499 : case CODE_FOR_avx512vl_loadv4sf_mask:
14500 : case CODE_FOR_avx512vl_loadv4si_mask:
14501 : case CODE_FOR_avx512vl_loadv2df_mask:
14502 : case CODE_FOR_avx512vl_loadv2di_mask:
14503 : case CODE_FOR_avx512bw_loadv64qi_mask:
14504 : case CODE_FOR_avx512vl_loadv32qi_mask:
14505 : case CODE_FOR_avx512vl_loadv16qi_mask:
14506 : case CODE_FOR_avx512bw_loadv32hi_mask:
14507 : case CODE_FOR_avx512vl_loadv16hi_mask:
14508 : case CODE_FOR_avx512vl_loadv8hi_mask:
14509 11742 : aligned_mem = true;
14510 : break;
14511 : default:
14512 : break;
14513 : }
14514 : /* FALLTHRU */
14515 : case V64QI_FTYPE_PCCHAR_V64QI_UDI:
14516 : case V32QI_FTYPE_PCCHAR_V32QI_USI:
14517 : case V16QI_FTYPE_PCCHAR_V16QI_UHI:
14518 : case V32HI_FTYPE_PCSHORT_V32HI_USI:
14519 : case V16HI_FTYPE_PCSHORT_V16HI_UHI:
14520 : case V8HI_FTYPE_PCSHORT_V8HI_UQI:
14521 : case V16SI_FTYPE_PCINT_V16SI_UHI:
14522 : case V8SI_FTYPE_PCINT_V8SI_UQI:
14523 : case V4SI_FTYPE_PCINT_V4SI_UQI:
14524 : case V8DI_FTYPE_PCINT64_V8DI_UQI:
14525 : case V4DI_FTYPE_PCINT64_V4DI_UQI:
14526 : case V2DI_FTYPE_PCINT64_V2DI_UQI:
14527 : case V8DF_FTYPE_PCDOUBLE_V8DF_UQI:
14528 : case V4DF_FTYPE_PCDOUBLE_V4DF_UQI:
14529 : case V2DF_FTYPE_PCDOUBLE_V2DF_UQI:
14530 : case V16SF_FTYPE_PCFLOAT_V16SF_UHI:
14531 : case V8SF_FTYPE_PCFLOAT_V8SF_UQI:
14532 : case V4SF_FTYPE_PCFLOAT_V4SF_UQI:
14533 : case V8HF_FTYPE_PCFLOAT16_V8HF_UQI:
14534 : nargs = 3;
14535 : klass = load;
14536 : memory = 0;
14537 : break;
14538 105 : case INT_FTYPE_PINT_INT_INT_INT:
14539 105 : case LONGLONG_FTYPE_PLONGLONG_LONGLONG_LONGLONG_INT:
14540 105 : nargs = 4;
14541 105 : klass = load;
14542 105 : memory = 0;
14543 105 : constant = 3;
14544 105 : break;
14545 0 : default:
14546 0 : gcc_unreachable ();
14547 : }
14548 :
14549 8268 : gcc_assert (nargs <= ARRAY_SIZE (xops));
14550 :
14551 11742 : if (klass == store)
14552 : {
14553 1879 : arg = CALL_EXPR_ARG (exp, 0);
14554 1879 : op = expand_normal (arg);
14555 1879 : gcc_assert (target == 0);
14556 1879 : if (memory)
14557 : {
14558 1716 : op = ix86_zero_extend_to_Pmode (op);
14559 1716 : target = gen_rtx_MEM (tmode, op);
14560 : /* target at this point has just BITS_PER_UNIT MEM_ALIGN
14561 : on it. Try to improve it using get_pointer_alignment,
14562 : and if the special builtin is one that requires strict
14563 : mode alignment, also from it's GET_MODE_ALIGNMENT.
14564 : Failure to do so could lead to ix86_legitimate_combined_insn
14565 : rejecting all changes to such insns. */
14566 1716 : unsigned int align = get_pointer_alignment (arg);
14567 1716 : if (aligned_mem && align < GET_MODE_ALIGNMENT (tmode))
14568 275 : align = GET_MODE_ALIGNMENT (tmode);
14569 3432 : if (MEM_ALIGN (target) < align)
14570 422 : set_mem_align (target, align);
14571 : }
14572 : else
14573 163 : target = force_reg (tmode, op);
14574 : arg_adjust = 1;
14575 : }
14576 : else
14577 : {
14578 9863 : arg_adjust = 0;
14579 9863 : if (optimize
14580 2919 : || target == 0
14581 2919 : || !register_operand (target, tmode)
14582 12771 : || GET_MODE (target) != tmode)
14583 6955 : target = gen_reg_rtx (tmode);
14584 : }
14585 :
14586 21133 : for (i = 0; i < nargs; i++)
14587 : {
14588 9391 : machine_mode mode = insn_p->operand[i + 1].mode;
14589 :
14590 9391 : arg = CALL_EXPR_ARG (exp, i + arg_adjust);
14591 9391 : op = ix86_expand_unsigned_small_int_cst_argument (arg);
14592 :
14593 9391 : if (i == memory)
14594 : {
14595 : /* This must be the memory operand. */
14596 2355 : op = ix86_zero_extend_to_Pmode (op);
14597 2355 : op = gen_rtx_MEM (mode, op);
14598 : /* op at this point has just BITS_PER_UNIT MEM_ALIGN
14599 : on it. Try to improve it using get_pointer_alignment,
14600 : and if the special builtin is one that requires strict
14601 : mode alignment, also from it's GET_MODE_ALIGNMENT.
14602 : Failure to do so could lead to ix86_legitimate_combined_insn
14603 : rejecting all changes to such insns. */
14604 2355 : unsigned int align = get_pointer_alignment (arg);
14605 2355 : if (aligned_mem && align < GET_MODE_ALIGNMENT (mode))
14606 299 : align = GET_MODE_ALIGNMENT (mode);
14607 4710 : if (MEM_ALIGN (op) < align)
14608 523 : set_mem_align (op, align);
14609 : }
14610 7036 : else if (i == constant)
14611 : {
14612 : /* This must be the constant. */
14613 105 : if (!insn_p->operand[nargs].predicate(op, SImode))
14614 : {
14615 0 : error ("the fourth argument must be one of enum %qs", "_CMPCCX_ENUM");
14616 0 : return const0_rtx;
14617 : }
14618 : }
14619 : else
14620 : {
14621 : /* This must be register. */
14622 6931 : if (VECTOR_MODE_P (mode))
14623 3475 : op = safe_vector_operand (op, mode);
14624 :
14625 6931 : op = fixup_modeless_constant (op, mode);
14626 :
14627 : /* NB: 3-operands load implied it's a mask load or v{p}expand*,
14628 : and that mask operand should be at the end.
14629 : Keep all-ones mask which would be simplified by the expander. */
14630 1771 : if (nargs == 3 && i == 2 && klass == load
14631 1771 : && constm1_operand (op, mode)
14632 7104 : && insn_p->operand[i].predicate (op, mode))
14633 : ;
14634 6931 : else if (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)
14635 6931 : op = copy_to_mode_reg (mode, op);
14636 : else
14637 : {
14638 0 : op = copy_to_reg (op);
14639 0 : op = lowpart_subreg (mode, op, GET_MODE (op));
14640 : }
14641 : }
14642 :
14643 9391 : xops[i]= op;
14644 : }
14645 :
14646 11742 : switch (nargs)
14647 : {
14648 7671 : case 0:
14649 7671 : pat = GEN_FCN (icode) (target);
14650 7671 : break;
14651 732 : case 1:
14652 732 : pat = GEN_FCN (icode) (target, xops[0]);
14653 732 : break;
14654 1463 : case 2:
14655 1463 : pat = GEN_FCN (icode) (target, xops[0], xops[1]);
14656 1463 : break;
14657 1771 : case 3:
14658 1771 : pat = GEN_FCN (icode) (target, xops[0], xops[1], xops[2]);
14659 1771 : break;
14660 105 : case 4:
14661 105 : pat = GEN_FCN (icode) (target, xops[0], xops[1], xops[2], xops[3]);
14662 105 : break;
14663 : default:
14664 : gcc_unreachable ();
14665 : }
14666 :
14667 11742 : if (! pat)
14668 : return 0;
14669 :
14670 11742 : emit_insn (pat);
14671 11742 : return klass == store ? 0 : target;
14672 : }
14673 :
14674 : /* Return the integer constant in ARG. Constrain it to be in the range
14675 : of the subparts of VEC_TYPE; issue an error if not. */
14676 :
14677 : static int
14678 604 : get_element_number (tree vec_type, tree arg)
14679 : {
14680 604 : unsigned HOST_WIDE_INT elt, max = TYPE_VECTOR_SUBPARTS (vec_type) - 1;
14681 :
14682 604 : if (!tree_fits_uhwi_p (arg)
14683 604 : || (elt = tree_to_uhwi (arg), elt > max))
14684 : {
14685 0 : error ("selector must be an integer constant in the range "
14686 : "[0, %wi]", max);
14687 0 : return 0;
14688 : }
14689 :
14690 604 : return elt;
14691 : }
14692 :
14693 : /* A subroutine of ix86_expand_builtin. These builtins are a wrapper around
14694 : ix86_expand_vector_init. We DO have language-level syntax for this, in
14695 : the form of (type){ init-list }. Except that since we can't place emms
14696 : instructions from inside the compiler, we can't allow the use of MMX
14697 : registers unless the user explicitly asks for it. So we do *not* define
14698 : vec_set/vec_extract/vec_init patterns for MMX modes in mmx.md. Instead
14699 : we have builtins invoked by mmintrin.h that gives us license to emit
14700 : these sorts of instructions. */
14701 :
14702 : static rtx
14703 229 : ix86_expand_vec_init_builtin (tree type, tree exp, rtx target)
14704 : {
14705 229 : machine_mode tmode = TYPE_MODE (type);
14706 229 : machine_mode inner_mode = GET_MODE_INNER (tmode);
14707 229 : int i, n_elt = GET_MODE_NUNITS (tmode);
14708 229 : rtvec v = rtvec_alloc (n_elt);
14709 :
14710 229 : gcc_assert (VECTOR_MODE_P (tmode));
14711 229 : gcc_assert (call_expr_nargs (exp) == n_elt);
14712 :
14713 1203 : for (i = 0; i < n_elt; ++i)
14714 : {
14715 974 : rtx x = expand_normal (CALL_EXPR_ARG (exp, i));
14716 974 : RTVEC_ELT (v, i) = gen_lowpart (inner_mode, x);
14717 : }
14718 :
14719 229 : if (!target || !register_operand (target, tmode))
14720 0 : target = gen_reg_rtx (tmode);
14721 :
14722 229 : ix86_expand_vector_init (true, target, gen_rtx_PARALLEL (tmode, v));
14723 229 : return target;
14724 : }
14725 :
14726 : /* A subroutine of ix86_expand_builtin. These builtins are a wrapper around
14727 : ix86_expand_vector_extract. They would be redundant (for non-MMX) if we
14728 : had a language-level syntax for referencing vector elements. */
14729 :
14730 : static rtx
14731 400 : ix86_expand_vec_ext_builtin (tree exp, rtx target)
14732 : {
14733 400 : machine_mode tmode, mode0;
14734 400 : tree arg0, arg1;
14735 400 : int elt;
14736 400 : rtx op0;
14737 :
14738 400 : arg0 = CALL_EXPR_ARG (exp, 0);
14739 400 : arg1 = CALL_EXPR_ARG (exp, 1);
14740 :
14741 400 : op0 = expand_normal (arg0);
14742 400 : elt = get_element_number (TREE_TYPE (arg0), arg1);
14743 :
14744 400 : tmode = TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0)));
14745 400 : mode0 = TYPE_MODE (TREE_TYPE (arg0));
14746 400 : gcc_assert (VECTOR_MODE_P (mode0));
14747 :
14748 400 : op0 = force_reg (mode0, op0);
14749 :
14750 400 : if (optimize || !target || !register_operand (target, tmode))
14751 321 : target = gen_reg_rtx (tmode);
14752 :
14753 400 : ix86_expand_vector_extract (true, target, op0, elt);
14754 :
14755 400 : return target;
14756 : }
14757 :
14758 : /* A subroutine of ix86_expand_builtin. These builtins are a wrapper around
14759 : ix86_expand_vector_set. They would be redundant (for non-MMX) if we had
14760 : a language-level syntax for referencing vector elements. */
14761 :
14762 : static rtx
14763 204 : ix86_expand_vec_set_builtin (tree exp)
14764 : {
14765 204 : machine_mode tmode, mode1;
14766 204 : tree arg0, arg1, arg2;
14767 204 : int elt;
14768 204 : rtx op0, op1, target;
14769 :
14770 204 : arg0 = CALL_EXPR_ARG (exp, 0);
14771 204 : arg1 = CALL_EXPR_ARG (exp, 1);
14772 204 : arg2 = CALL_EXPR_ARG (exp, 2);
14773 :
14774 204 : tmode = TYPE_MODE (TREE_TYPE (arg0));
14775 204 : mode1 = TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0)));
14776 204 : gcc_assert (VECTOR_MODE_P (tmode));
14777 :
14778 204 : op0 = expand_expr (arg0, NULL_RTX, tmode, EXPAND_NORMAL);
14779 204 : op1 = expand_expr (arg1, NULL_RTX, mode1, EXPAND_NORMAL);
14780 204 : elt = get_element_number (TREE_TYPE (arg0), arg2);
14781 :
14782 204 : if (GET_MODE (op1) != mode1)
14783 82 : op1 = convert_modes (mode1, GET_MODE (op1), op1, true);
14784 :
14785 204 : op0 = force_reg (tmode, op0);
14786 204 : op1 = force_reg (mode1, op1);
14787 :
14788 : /* OP0 is the source of these builtin functions and shouldn't be
14789 : modified. Create a copy, use it and return it as target. */
14790 204 : target = gen_reg_rtx (tmode);
14791 204 : emit_move_insn (target, op0);
14792 204 : ix86_expand_vector_set (true, target, op1, elt);
14793 :
14794 204 : return target;
14795 : }
14796 :
14797 : /* Return true if the necessary isa options for this builtin exist,
14798 : else false.
14799 : fcode = DECL_MD_FUNCTION_CODE (fndecl); */
14800 : bool
14801 1328589 : ix86_check_builtin_isa_match (unsigned int fcode,
14802 : HOST_WIDE_INT* pbisa,
14803 : HOST_WIDE_INT* pbisa2)
14804 : {
14805 1328589 : HOST_WIDE_INT isa = ix86_isa_flags;
14806 1328589 : HOST_WIDE_INT isa2 = ix86_isa_flags2;
14807 1328589 : HOST_WIDE_INT bisa = ix86_builtins_isa[fcode].isa;
14808 1328589 : HOST_WIDE_INT bisa2 = ix86_builtins_isa[fcode].isa2;
14809 1328589 : HOST_WIDE_INT tmp_isa = isa, tmp_isa2 = isa2;
14810 : /* The general case is we require all the ISAs specified in bisa{,2}
14811 : to be enabled.
14812 : The exceptions are:
14813 : OPTION_MASK_ISA_SSE | OPTION_MASK_ISA_3DNOW_A
14814 : OPTION_MASK_ISA_SSE4_2 | OPTION_MASK_ISA_CRC32
14815 : OPTION_MASK_ISA_FMA | OPTION_MASK_ISA_FMA4
14816 : (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL) or
14817 : OPTION_MASK_ISA2_AVXVNNI
14818 : (OPTION_MASK_ISA_AVX512IFMA | OPTION_MASK_ISA_AVX512VL) or
14819 : OPTION_MASK_ISA2_AVXIFMA
14820 : (OPTION_MASK_ISA_AVX512VL | OPTION_MASK_ISA2_AVX512BF16) or
14821 : OPTION_MASK_ISA2_AVXNECONVERT
14822 : OPTION_MASK_ISA_AES or (OPTION_MASK_ISA_AVX512VL | OPTION_MASK_ISA2_VAES)
14823 : OPTION_MASK_ISA2_AVX10_2 or OPTION_MASK_ISA2_AVXVNNIINT8
14824 : OPTION_MASK_ISA2_AVX10_2 or OPTION_MASK_ISA2_AVXVNNIINT16
14825 : where for each such pair it is sufficient if either of the ISAs is
14826 : enabled, plus if it is ored with other options also those others.
14827 : OPTION_MASK_ISA_MMX in bisa is satisfied also if TARGET_MMX_WITH_SSE. */
14828 :
14829 : #define SHARE_BUILTIN(A1, A2, B1, B2) \
14830 : if ((((bisa & (A1)) == (A1) && (bisa2 & (A2)) == (A2)) \
14831 : && ((bisa & (B1)) == (B1) && (bisa2 & (B2)) == (B2))) \
14832 : && (((isa & (A1)) == (A1) && (isa2 & (A2)) == (A2)) \
14833 : || ((isa & (B1)) == (B1) && (isa2 & (B2)) == (B2)))) \
14834 : { \
14835 : tmp_isa |= (A1) | (B1); \
14836 : tmp_isa2 |= (A2) | (B2); \
14837 : }
14838 :
14839 1328589 : SHARE_BUILTIN (OPTION_MASK_ISA_SSE, 0, OPTION_MASK_ISA_3DNOW_A, 0);
14840 1328589 : SHARE_BUILTIN (OPTION_MASK_ISA_SSE4_2, 0, OPTION_MASK_ISA_CRC32, 0);
14841 1328589 : SHARE_BUILTIN (OPTION_MASK_ISA_FMA, 0, OPTION_MASK_ISA_FMA4, 0);
14842 1328589 : SHARE_BUILTIN (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, 0,
14843 1328589 : OPTION_MASK_ISA2_AVXVNNI);
14844 1328589 : SHARE_BUILTIN (OPTION_MASK_ISA_AVX512IFMA | OPTION_MASK_ISA_AVX512VL, 0, 0,
14845 1328589 : OPTION_MASK_ISA2_AVXIFMA);
14846 1328589 : SHARE_BUILTIN (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512BF16, 0,
14847 1328589 : OPTION_MASK_ISA2_AVXNECONVERT);
14848 1328589 : SHARE_BUILTIN (OPTION_MASK_ISA_AES, 0, OPTION_MASK_ISA_AVX512VL,
14849 1328589 : OPTION_MASK_ISA2_VAES);
14850 1328589 : SHARE_BUILTIN (0, OPTION_MASK_ISA2_AVXVNNIINT8, 0,
14851 1328589 : OPTION_MASK_ISA2_AVX10_2);
14852 1328589 : SHARE_BUILTIN (0, OPTION_MASK_ISA2_AVXVNNIINT16, 0,
14853 1328589 : OPTION_MASK_ISA2_AVX10_2);
14854 1328589 : isa = tmp_isa;
14855 1328589 : isa2 = tmp_isa2;
14856 :
14857 1328589 : if ((bisa & OPTION_MASK_ISA_MMX) && !TARGET_MMX && TARGET_MMX_WITH_SSE
14858 : /* __builtin_ia32_maskmovq requires MMX registers. */
14859 4563 : && fcode != IX86_BUILTIN_MASKMOVQ)
14860 : {
14861 4554 : bisa &= ~OPTION_MASK_ISA_MMX;
14862 4554 : bisa |= OPTION_MASK_ISA_SSE2;
14863 : }
14864 :
14865 1328589 : if (pbisa)
14866 174830 : *pbisa = bisa;
14867 1328589 : if (pbisa2)
14868 174830 : *pbisa2 = bisa2;
14869 :
14870 1328589 : return (bisa & isa) == bisa && (bisa2 & isa2) == bisa2;
14871 : }
14872 :
14873 : /* Emit instructions to set the carry flag from ARG. */
14874 :
14875 : void
14876 13556 : ix86_expand_carry (rtx arg)
14877 : {
14878 13556 : if (!CONST_INT_P (arg) || arg == const0_rtx)
14879 : {
14880 13550 : arg = convert_to_mode (QImode, arg, 1);
14881 13550 : arg = copy_to_mode_reg (QImode, arg);
14882 13550 : emit_insn (gen_addqi3_cconly_overflow (arg, constm1_rtx));
14883 : }
14884 : else
14885 6 : emit_insn (gen_x86_stc ());
14886 13556 : }
14887 :
14888 : /* Expand an expression EXP that calls a built-in function,
14889 : with result going to TARGET if that's convenient
14890 : (and in mode MODE if that's convenient).
14891 : SUBTARGET may be used as the target for computing one of EXP's operands.
14892 : IGNORE is nonzero if the value is to be ignored. */
14893 :
14894 : rtx
14895 175629 : ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
14896 : machine_mode mode, int ignore)
14897 : {
14898 175629 : size_t i;
14899 175629 : enum insn_code icode, icode2;
14900 175629 : tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
14901 175629 : tree arg0, arg1, arg2, arg3, arg4;
14902 175629 : rtx op0, op1, op2, op3, op4, pat, pat2, insn;
14903 175629 : machine_mode mode0, mode1, mode2, mode3, mode4;
14904 175629 : unsigned int fcode = DECL_MD_FUNCTION_CODE (fndecl);
14905 175629 : HOST_WIDE_INT bisa, bisa2;
14906 :
14907 : /* For CPU builtins that can be folded, fold first and expand the fold. */
14908 175629 : switch (fcode)
14909 : {
14910 197 : case IX86_BUILTIN_CPU_INIT:
14911 197 : {
14912 : /* Make it call __cpu_indicator_init in libgcc. */
14913 197 : tree call_expr, fndecl, type;
14914 197 : type = build_function_type_list (integer_type_node, NULL_TREE);
14915 197 : fndecl = build_fn_decl ("__cpu_indicator_init", type);
14916 197 : call_expr = build_call_expr (fndecl, 0);
14917 197 : return expand_expr (call_expr, target, mode, EXPAND_NORMAL);
14918 : }
14919 602 : case IX86_BUILTIN_CPU_IS:
14920 602 : case IX86_BUILTIN_CPU_SUPPORTS:
14921 602 : {
14922 602 : tree arg0 = CALL_EXPR_ARG (exp, 0);
14923 602 : tree fold_expr = fold_builtin_cpu (fndecl, &arg0);
14924 602 : gcc_assert (fold_expr != NULL_TREE);
14925 602 : return expand_expr (fold_expr, target, mode, EXPAND_NORMAL);
14926 : }
14927 : }
14928 :
14929 174830 : if (!ix86_check_builtin_isa_match (fcode, &bisa, &bisa2))
14930 : {
14931 23 : bool add_abi_p = bisa & OPTION_MASK_ISA_64BIT;
14932 23 : if (TARGET_ABI_X32)
14933 0 : bisa |= OPTION_MASK_ABI_X32;
14934 : else
14935 23 : bisa |= OPTION_MASK_ABI_64;
14936 23 : char *opts = ix86_target_string (bisa, bisa2, 0, 0, NULL, NULL,
14937 : (enum fpmath_unit) 0,
14938 : (enum prefer_vector_width) 0,
14939 : PVW_NONE, false, add_abi_p);
14940 23 : if (!opts)
14941 0 : error ("%qE needs unknown isa option", fndecl);
14942 : else
14943 : {
14944 23 : gcc_assert (opts != NULL);
14945 23 : error ("%qE needs isa option %s", fndecl, opts);
14946 23 : free (opts);
14947 : }
14948 23 : return expand_call (exp, target, ignore);
14949 : }
14950 :
14951 174807 : switch (fcode)
14952 : {
14953 35 : case IX86_BUILTIN_MASKMOVQ:
14954 35 : case IX86_BUILTIN_MASKMOVDQU:
14955 34 : icode = (fcode == IX86_BUILTIN_MASKMOVQ
14956 35 : ? CODE_FOR_mmx_maskmovq
14957 : : CODE_FOR_sse2_maskmovdqu);
14958 : /* Note the arg order is different from the operand order. */
14959 35 : arg1 = CALL_EXPR_ARG (exp, 0);
14960 35 : arg2 = CALL_EXPR_ARG (exp, 1);
14961 35 : arg0 = CALL_EXPR_ARG (exp, 2);
14962 35 : op0 = expand_normal (arg0);
14963 35 : op1 = expand_normal (arg1);
14964 35 : op2 = expand_normal (arg2);
14965 35 : mode0 = insn_data[icode].operand[0].mode;
14966 35 : mode1 = insn_data[icode].operand[1].mode;
14967 35 : mode2 = insn_data[icode].operand[2].mode;
14968 :
14969 35 : op0 = ix86_zero_extend_to_Pmode (op0);
14970 35 : op0 = gen_rtx_MEM (mode1, op0);
14971 :
14972 35 : if (!insn_data[icode].operand[0].predicate (op0, mode0))
14973 0 : op0 = copy_to_mode_reg (mode0, op0);
14974 35 : if (!insn_data[icode].operand[1].predicate (op1, mode1))
14975 2 : op1 = copy_to_mode_reg (mode1, op1);
14976 35 : if (!insn_data[icode].operand[2].predicate (op2, mode2))
14977 2 : op2 = copy_to_mode_reg (mode2, op2);
14978 35 : pat = GEN_FCN (icode) (op0, op1, op2);
14979 35 : if (! pat)
14980 56404 : return 0;
14981 35 : emit_insn (pat);
14982 35 : return 0;
14983 :
14984 21937 : case IX86_BUILTIN_LDMXCSR:
14985 21937 : op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
14986 21937 : target = assign_stack_temp (SImode, GET_MODE_SIZE (SImode));
14987 21937 : emit_move_insn (target, op0);
14988 21937 : emit_insn (gen_sse_ldmxcsr (target));
14989 21937 : return 0;
14990 :
14991 14713 : case IX86_BUILTIN_STMXCSR:
14992 14713 : target = assign_stack_temp (SImode, GET_MODE_SIZE (SImode));
14993 14713 : emit_insn (gen_sse_stmxcsr (target));
14994 14713 : return copy_to_mode_reg (SImode, target);
14995 :
14996 11 : case IX86_BUILTIN_CLFLUSH:
14997 11 : arg0 = CALL_EXPR_ARG (exp, 0);
14998 11 : op0 = expand_normal (arg0);
14999 11 : icode = CODE_FOR_sse2_clflush;
15000 11 : if (!insn_data[icode].operand[0].predicate (op0, Pmode))
15001 5 : op0 = ix86_zero_extend_to_Pmode (op0);
15002 :
15003 11 : emit_insn (gen_sse2_clflush (op0));
15004 11 : return 0;
15005 :
15006 19 : case IX86_BUILTIN_CLWB:
15007 19 : arg0 = CALL_EXPR_ARG (exp, 0);
15008 19 : op0 = expand_normal (arg0);
15009 19 : icode = CODE_FOR_clwb;
15010 19 : if (!insn_data[icode].operand[0].predicate (op0, Pmode))
15011 9 : op0 = ix86_zero_extend_to_Pmode (op0);
15012 :
15013 19 : emit_insn (gen_clwb (op0));
15014 19 : return 0;
15015 :
15016 19 : case IX86_BUILTIN_CLFLUSHOPT:
15017 19 : arg0 = CALL_EXPR_ARG (exp, 0);
15018 19 : op0 = expand_normal (arg0);
15019 19 : icode = CODE_FOR_clflushopt;
15020 19 : if (!insn_data[icode].operand[0].predicate (op0, Pmode))
15021 9 : op0 = ix86_zero_extend_to_Pmode (op0);
15022 :
15023 19 : emit_insn (gen_clflushopt (op0));
15024 19 : return 0;
15025 :
15026 47 : case IX86_BUILTIN_MONITOR:
15027 47 : case IX86_BUILTIN_MONITORX:
15028 47 : arg0 = CALL_EXPR_ARG (exp, 0);
15029 47 : arg1 = CALL_EXPR_ARG (exp, 1);
15030 47 : arg2 = CALL_EXPR_ARG (exp, 2);
15031 47 : op0 = expand_normal (arg0);
15032 47 : op1 = expand_normal (arg1);
15033 47 : op2 = expand_normal (arg2);
15034 47 : if (!REG_P (op0))
15035 19 : op0 = ix86_zero_extend_to_Pmode (op0);
15036 47 : if (!REG_P (op1))
15037 22 : op1 = copy_to_mode_reg (SImode, op1);
15038 47 : if (!REG_P (op2))
15039 25 : op2 = copy_to_mode_reg (SImode, op2);
15040 :
15041 47 : emit_insn (fcode == IX86_BUILTIN_MONITOR
15042 26 : ? gen_sse3_monitor (Pmode, op0, op1, op2)
15043 21 : : gen_monitorx (Pmode, op0, op1, op2));
15044 47 : return 0;
15045 :
15046 25 : case IX86_BUILTIN_MWAIT:
15047 25 : arg0 = CALL_EXPR_ARG (exp, 0);
15048 25 : arg1 = CALL_EXPR_ARG (exp, 1);
15049 25 : op0 = expand_normal (arg0);
15050 25 : op1 = expand_normal (arg1);
15051 25 : if (!REG_P (op0))
15052 13 : op0 = copy_to_mode_reg (SImode, op0);
15053 25 : if (!REG_P (op1))
15054 11 : op1 = copy_to_mode_reg (SImode, op1);
15055 25 : emit_insn (gen_sse3_mwait (op0, op1));
15056 25 : return 0;
15057 :
15058 21 : case IX86_BUILTIN_MWAITX:
15059 21 : arg0 = CALL_EXPR_ARG (exp, 0);
15060 21 : arg1 = CALL_EXPR_ARG (exp, 1);
15061 21 : arg2 = CALL_EXPR_ARG (exp, 2);
15062 21 : op0 = expand_normal (arg0);
15063 21 : op1 = expand_normal (arg1);
15064 21 : op2 = expand_normal (arg2);
15065 21 : if (!REG_P (op0))
15066 11 : op0 = copy_to_mode_reg (SImode, op0);
15067 21 : if (!REG_P (op1))
15068 10 : op1 = copy_to_mode_reg (SImode, op1);
15069 21 : if (!REG_P (op2))
15070 11 : op2 = copy_to_mode_reg (SImode, op2);
15071 21 : emit_insn (gen_mwaitx (op0, op1, op2));
15072 21 : return 0;
15073 :
15074 21 : case IX86_BUILTIN_UMONITOR:
15075 21 : arg0 = CALL_EXPR_ARG (exp, 0);
15076 21 : op0 = expand_normal (arg0);
15077 :
15078 21 : op0 = ix86_zero_extend_to_Pmode (op0);
15079 21 : emit_insn (gen_umonitor (Pmode, op0));
15080 21 : return 0;
15081 :
15082 42 : case IX86_BUILTIN_UMWAIT:
15083 42 : case IX86_BUILTIN_TPAUSE:
15084 42 : arg0 = CALL_EXPR_ARG (exp, 0);
15085 42 : arg1 = CALL_EXPR_ARG (exp, 1);
15086 42 : op0 = expand_normal (arg0);
15087 42 : op1 = expand_normal (arg1);
15088 :
15089 42 : if (!REG_P (op0))
15090 20 : op0 = copy_to_mode_reg (SImode, op0);
15091 :
15092 42 : op1 = force_reg (DImode, op1);
15093 :
15094 42 : if (TARGET_64BIT)
15095 : {
15096 42 : op2 = expand_simple_binop (DImode, LSHIFTRT, op1, GEN_INT (32),
15097 : NULL, 1, OPTAB_DIRECT);
15098 42 : switch (fcode)
15099 : {
15100 : case IX86_BUILTIN_UMWAIT:
15101 : icode = CODE_FOR_umwait_rex64;
15102 : break;
15103 21 : case IX86_BUILTIN_TPAUSE:
15104 21 : icode = CODE_FOR_tpause_rex64;
15105 21 : break;
15106 0 : default:
15107 0 : gcc_unreachable ();
15108 : }
15109 :
15110 42 : op2 = gen_lowpart (SImode, op2);
15111 42 : op1 = gen_lowpart (SImode, op1);
15112 42 : pat = GEN_FCN (icode) (op0, op1, op2);
15113 : }
15114 : else
15115 : {
15116 0 : switch (fcode)
15117 : {
15118 : case IX86_BUILTIN_UMWAIT:
15119 : icode = CODE_FOR_umwait;
15120 : break;
15121 0 : case IX86_BUILTIN_TPAUSE:
15122 0 : icode = CODE_FOR_tpause;
15123 0 : break;
15124 0 : default:
15125 0 : gcc_unreachable ();
15126 : }
15127 0 : pat = GEN_FCN (icode) (op0, op1);
15128 : }
15129 :
15130 42 : if (!pat)
15131 : return 0;
15132 :
15133 42 : emit_insn (pat);
15134 :
15135 42 : if (target == 0
15136 42 : || !register_operand (target, QImode))
15137 0 : target = gen_reg_rtx (QImode);
15138 :
15139 42 : pat = gen_rtx_EQ (QImode, gen_rtx_REG (CCCmode, FLAGS_REG),
15140 : const0_rtx);
15141 42 : emit_insn (gen_rtx_SET (target, pat));
15142 :
15143 42 : return target;
15144 :
15145 20 : case IX86_BUILTIN_TESTUI:
15146 20 : emit_insn (gen_testui ());
15147 :
15148 20 : if (target == 0
15149 20 : || !register_operand (target, QImode))
15150 0 : target = gen_reg_rtx (QImode);
15151 :
15152 20 : pat = gen_rtx_LTU (QImode, gen_rtx_REG (CCCmode, FLAGS_REG),
15153 : const0_rtx);
15154 20 : emit_insn (gen_rtx_SET (target, pat));
15155 :
15156 20 : return target;
15157 :
15158 19 : case IX86_BUILTIN_CLZERO:
15159 19 : arg0 = CALL_EXPR_ARG (exp, 0);
15160 19 : op0 = expand_normal (arg0);
15161 19 : if (!REG_P (op0))
15162 9 : op0 = ix86_zero_extend_to_Pmode (op0);
15163 19 : emit_insn (gen_clzero (Pmode, op0));
15164 19 : return 0;
15165 :
15166 19 : case IX86_BUILTIN_CLDEMOTE:
15167 19 : arg0 = CALL_EXPR_ARG (exp, 0);
15168 19 : op0 = expand_normal (arg0);
15169 19 : icode = CODE_FOR_cldemote;
15170 19 : if (!insn_data[icode].operand[0].predicate (op0, Pmode))
15171 9 : op0 = ix86_zero_extend_to_Pmode (op0);
15172 :
15173 19 : emit_insn (gen_cldemote (op0));
15174 19 : return 0;
15175 :
15176 11 : case IX86_BUILTIN_LOADIWKEY:
15177 11 : {
15178 11 : arg0 = CALL_EXPR_ARG (exp, 0);
15179 11 : arg1 = CALL_EXPR_ARG (exp, 1);
15180 11 : arg2 = CALL_EXPR_ARG (exp, 2);
15181 11 : arg3 = CALL_EXPR_ARG (exp, 3);
15182 :
15183 11 : op0 = expand_normal (arg0);
15184 11 : op1 = expand_normal (arg1);
15185 11 : op2 = expand_normal (arg2);
15186 11 : op3 = expand_normal (arg3);
15187 :
15188 11 : if (!REG_P (op0))
15189 5 : op0 = copy_to_mode_reg (V2DImode, op0);
15190 11 : if (!REG_P (op1))
15191 5 : op1 = copy_to_mode_reg (V2DImode, op1);
15192 11 : if (!REG_P (op2))
15193 5 : op2 = copy_to_mode_reg (V2DImode, op2);
15194 11 : if (!REG_P (op3))
15195 5 : op3 = copy_to_mode_reg (SImode, op3);
15196 :
15197 11 : emit_insn (gen_loadiwkey (op0, op1, op2, op3));
15198 :
15199 11 : return 0;
15200 : }
15201 :
15202 12 : case IX86_BUILTIN_AESDEC128KLU8:
15203 12 : icode = CODE_FOR_aesdec128klu8;
15204 12 : goto aesdecenc_expand;
15205 :
15206 12 : case IX86_BUILTIN_AESDEC256KLU8:
15207 12 : icode = CODE_FOR_aesdec256klu8;
15208 12 : goto aesdecenc_expand;
15209 :
15210 12 : case IX86_BUILTIN_AESENC128KLU8:
15211 12 : icode = CODE_FOR_aesenc128klu8;
15212 12 : goto aesdecenc_expand;
15213 :
15214 : case IX86_BUILTIN_AESENC256KLU8:
15215 : icode = CODE_FOR_aesenc256klu8;
15216 :
15217 48 : aesdecenc_expand:
15218 :
15219 48 : arg0 = CALL_EXPR_ARG (exp, 0); // __m128i *odata
15220 48 : arg1 = CALL_EXPR_ARG (exp, 1); // __m128i idata
15221 48 : arg2 = CALL_EXPR_ARG (exp, 2); // const void *p
15222 :
15223 48 : op0 = expand_normal (arg0);
15224 48 : op1 = expand_normal (arg1);
15225 48 : op2 = expand_normal (arg2);
15226 :
15227 48 : if (!address_operand (op0, V2DImode))
15228 : {
15229 16 : op0 = convert_memory_address (Pmode, op0);
15230 16 : op0 = copy_addr_to_reg (op0);
15231 : }
15232 48 : op0 = gen_rtx_MEM (V2DImode, op0);
15233 :
15234 48 : if (!REG_P (op1))
15235 20 : op1 = copy_to_mode_reg (V2DImode, op1);
15236 :
15237 48 : if (!address_operand (op2, VOIDmode))
15238 : {
15239 16 : op2 = convert_memory_address (Pmode, op2);
15240 16 : op2 = copy_addr_to_reg (op2);
15241 : }
15242 48 : op2 = gen_rtx_MEM (BLKmode, op2);
15243 :
15244 48 : emit_insn (GEN_FCN (icode) (op1, op1, op2));
15245 :
15246 48 : if (target == 0)
15247 4 : target = gen_reg_rtx (QImode);
15248 :
15249 : /* NB: For aesenc/aesdec keylocker insn, ZF will be set when runtime
15250 : error occurs. Then the output should be cleared for safety. */
15251 48 : rtx_code_label *ok_label;
15252 48 : rtx tmp;
15253 :
15254 48 : tmp = gen_rtx_REG (CCZmode, FLAGS_REG);
15255 48 : pat = gen_rtx_EQ (QImode, tmp, const0_rtx);
15256 48 : ok_label = gen_label_rtx ();
15257 48 : emit_cmp_and_jump_insns (tmp, const0_rtx, NE, 0, GET_MODE (tmp),
15258 : true, ok_label);
15259 : /* Usually the runtime error seldom occur, so predict OK path as
15260 : hotspot to optimize it as fallthrough block. */
15261 48 : predict_jump (REG_BR_PROB_BASE * 90 / 100);
15262 :
15263 48 : emit_insn (gen_rtx_SET (op1, const0_rtx));
15264 :
15265 48 : emit_label (ok_label);
15266 48 : emit_insn (gen_rtx_SET (target, pat));
15267 48 : emit_insn (gen_rtx_SET (op0, op1));
15268 :
15269 48 : return target;
15270 :
15271 11 : case IX86_BUILTIN_AESDECWIDE128KLU8:
15272 11 : icode = CODE_FOR_aesdecwide128klu8;
15273 11 : goto wideaesdecenc_expand;
15274 :
15275 11 : case IX86_BUILTIN_AESDECWIDE256KLU8:
15276 11 : icode = CODE_FOR_aesdecwide256klu8;
15277 11 : goto wideaesdecenc_expand;
15278 :
15279 11 : case IX86_BUILTIN_AESENCWIDE128KLU8:
15280 11 : icode = CODE_FOR_aesencwide128klu8;
15281 11 : goto wideaesdecenc_expand;
15282 :
15283 : case IX86_BUILTIN_AESENCWIDE256KLU8:
15284 : icode = CODE_FOR_aesencwide256klu8;
15285 :
15286 44 : wideaesdecenc_expand:
15287 :
15288 44 : rtx xmm_regs[8];
15289 44 : rtx op;
15290 :
15291 44 : arg0 = CALL_EXPR_ARG (exp, 0); // __m128i * odata
15292 44 : arg1 = CALL_EXPR_ARG (exp, 1); // const __m128i * idata
15293 44 : arg2 = CALL_EXPR_ARG (exp, 2); // const void *p
15294 :
15295 44 : op0 = expand_normal (arg0);
15296 44 : op1 = expand_normal (arg1);
15297 44 : op2 = expand_normal (arg2);
15298 :
15299 44 : if (GET_MODE (op1) != Pmode)
15300 0 : op1 = convert_to_mode (Pmode, op1, 1);
15301 :
15302 44 : if (!address_operand (op2, VOIDmode))
15303 : {
15304 16 : op2 = convert_memory_address (Pmode, op2);
15305 16 : op2 = copy_addr_to_reg (op2);
15306 : }
15307 44 : op2 = gen_rtx_MEM (BLKmode, op2);
15308 :
15309 440 : for (i = 0; i < 8; i++)
15310 : {
15311 352 : xmm_regs[i] = gen_rtx_REG (V2DImode, GET_SSE_REGNO (i));
15312 :
15313 352 : op = gen_rtx_MEM (V2DImode,
15314 352 : plus_constant (Pmode, op1, (i * 16)));
15315 :
15316 352 : emit_move_insn (xmm_regs[i], op);
15317 : }
15318 :
15319 44 : emit_insn (GEN_FCN (icode) (op2));
15320 :
15321 44 : if (target == 0)
15322 0 : target = gen_reg_rtx (QImode);
15323 :
15324 44 : tmp = gen_rtx_REG (CCZmode, FLAGS_REG);
15325 44 : pat = gen_rtx_EQ (QImode, tmp, const0_rtx);
15326 44 : ok_label = gen_label_rtx ();
15327 44 : emit_cmp_and_jump_insns (tmp, const0_rtx, NE, 0, GET_MODE (tmp),
15328 : true, ok_label);
15329 44 : predict_jump (REG_BR_PROB_BASE * 90 / 100);
15330 :
15331 440 : for (i = 0; i < 8; i++)
15332 352 : emit_insn (gen_rtx_SET (xmm_regs[i], const0_rtx));
15333 :
15334 44 : emit_label (ok_label);
15335 44 : emit_insn (gen_rtx_SET (target, pat));
15336 :
15337 44 : if (GET_MODE (op0) != Pmode)
15338 0 : op0 = convert_to_mode (Pmode, op0, 1);
15339 :
15340 396 : for (i = 0; i < 8; i++)
15341 : {
15342 352 : op = gen_rtx_MEM (V2DImode,
15343 352 : plus_constant (Pmode, op0, (i * 16)));
15344 352 : emit_move_insn (op, xmm_regs[i]);
15345 : }
15346 :
15347 : return target;
15348 :
15349 13 : case IX86_BUILTIN_ENCODEKEY128U32:
15350 13 : {
15351 13 : rtx op, xmm_regs[7];
15352 :
15353 13 : arg0 = CALL_EXPR_ARG (exp, 0); // unsigned int htype
15354 13 : arg1 = CALL_EXPR_ARG (exp, 1); // __m128i key
15355 13 : arg2 = CALL_EXPR_ARG (exp, 2); // void *h
15356 :
15357 13 : op0 = expand_normal (arg0);
15358 13 : op1 = expand_normal (arg1);
15359 13 : op2 = expand_normal (arg2);
15360 :
15361 13 : if (!REG_P (op0))
15362 7 : op0 = copy_to_mode_reg (SImode, op0);
15363 :
15364 13 : if (GET_MODE (op2) != Pmode)
15365 1 : op2 = convert_to_mode (Pmode, op2, 1);
15366 :
15367 13 : op = gen_rtx_REG (V2DImode, GET_SSE_REGNO (0));
15368 13 : emit_move_insn (op, op1);
15369 :
15370 65 : for (i = 0; i < 3; i++)
15371 39 : xmm_regs[i] = gen_rtx_REG (V2DImode, GET_SSE_REGNO (i));
15372 :
15373 13 : if (target == 0 || !register_operand (target, SImode))
15374 2 : target = gen_reg_rtx (SImode);
15375 :
15376 13 : emit_insn (gen_encodekey128u32 (target, op0));
15377 :
15378 65 : for (i = 0; i < 3; i++)
15379 : {
15380 39 : op = gen_rtx_MEM (V2DImode,
15381 39 : plus_constant (Pmode, op2, (i * 16)));
15382 39 : emit_move_insn (op, xmm_regs[i]);
15383 : }
15384 :
15385 13 : return target;
15386 : }
15387 13 : case IX86_BUILTIN_ENCODEKEY256U32:
15388 13 : {
15389 13 : rtx op, xmm_regs[7];
15390 :
15391 13 : arg0 = CALL_EXPR_ARG (exp, 0); // unsigned int htype
15392 13 : arg1 = CALL_EXPR_ARG (exp, 1); // __m128i keylow
15393 13 : arg2 = CALL_EXPR_ARG (exp, 2); // __m128i keyhi
15394 13 : arg3 = CALL_EXPR_ARG (exp, 3); // void *h
15395 :
15396 13 : op0 = expand_normal (arg0);
15397 13 : op1 = expand_normal (arg1);
15398 13 : op2 = expand_normal (arg2);
15399 13 : op3 = expand_normal (arg3);
15400 :
15401 13 : if (!REG_P (op0))
15402 7 : op0 = copy_to_mode_reg (SImode, op0);
15403 :
15404 13 : if (GET_MODE (op3) != Pmode)
15405 1 : op3 = convert_to_mode (Pmode, op3, 1);
15406 :
15407 : /* Force to use xmm0, xmm1 for keylow, keyhi*/
15408 13 : op = gen_rtx_REG (V2DImode, GET_SSE_REGNO (0));
15409 13 : emit_move_insn (op, op1);
15410 13 : op = gen_rtx_REG (V2DImode, GET_SSE_REGNO (1));
15411 13 : emit_move_insn (op, op2);
15412 :
15413 78 : for (i = 0; i < 4; i++)
15414 52 : xmm_regs[i] = gen_rtx_REG (V2DImode, GET_SSE_REGNO (i));
15415 :
15416 13 : if (target == 0 || !register_operand (target, SImode))
15417 2 : target = gen_reg_rtx (SImode);
15418 :
15419 13 : emit_insn (gen_encodekey256u32 (target, op0));
15420 :
15421 78 : for (i = 0; i < 4; i++)
15422 : {
15423 52 : op = gen_rtx_MEM (V2DImode,
15424 52 : plus_constant (Pmode, op3, (i * 16)));
15425 52 : emit_move_insn (op, xmm_regs[i]);
15426 : }
15427 :
15428 13 : return target;
15429 : }
15430 :
15431 48 : case IX86_BUILTIN_PREFETCH:
15432 48 : {
15433 48 : arg0 = CALL_EXPR_ARG (exp, 0); // const void *
15434 48 : arg1 = CALL_EXPR_ARG (exp, 1); // const int
15435 48 : arg2 = CALL_EXPR_ARG (exp, 2); // const int
15436 48 : arg3 = CALL_EXPR_ARG (exp, 3); // const int
15437 :
15438 48 : op0 = expand_normal (arg0);
15439 48 : op1 = expand_normal (arg1);
15440 48 : op2 = expand_normal (arg2);
15441 48 : op3 = expand_normal (arg3);
15442 :
15443 48 : if (!CONST_INT_P (op1) || !CONST_INT_P (op2) || !CONST_INT_P (op3))
15444 : {
15445 0 : error ("second, third and fourth argument must be a const");
15446 0 : return const0_rtx;
15447 : }
15448 :
15449 48 : if (!IN_RANGE (INTVAL (op1), 0, 2))
15450 : {
15451 1 : warning (0, "invalid second argument to"
15452 : " %<__builtin_ia32_prefetch%>; using zero");
15453 1 : op1 = const0_rtx;
15454 : }
15455 :
15456 48 : if (INTVAL (op3) == 1)
15457 : {
15458 4 : if (!IN_RANGE (INTVAL (op2), 2, 3))
15459 : {
15460 1 : error ("invalid third argument");
15461 1 : return const0_rtx;
15462 : }
15463 :
15464 3 : if (TARGET_64BIT && TARGET_PREFETCHI
15465 6 : && local_func_symbolic_operand (op0, GET_MODE (op0)))
15466 2 : emit_insn (gen_prefetchi (op0, op2));
15467 : else
15468 : {
15469 1 : warning (0, "instruction prefetch applies when in 64-bit mode"
15470 : " with RIP-relative addressing and"
15471 : " option %<-mprefetchi%>;"
15472 : " they stay NOPs otherwise");
15473 1 : emit_insn (gen_nop ());
15474 : }
15475 : }
15476 : else
15477 : {
15478 44 : if (INTVAL (op3) != 0)
15479 1 : warning (0, "invalid fourth argument to"
15480 : " %<__builtin_ia32_prefetch%>; using zero");
15481 :
15482 44 : if (!address_operand (op0, VOIDmode))
15483 : {
15484 10 : op0 = convert_memory_address (Pmode, op0);
15485 10 : op0 = copy_addr_to_reg (op0);
15486 : }
15487 :
15488 44 : if (!IN_RANGE (INTVAL (op2), 0, 3))
15489 : {
15490 1 : warning (0, "invalid third argument to %<__builtin_ia32_prefetch%>; using zero");
15491 1 : op2 = const0_rtx;
15492 : }
15493 :
15494 44 : if (TARGET_3DNOW
15495 26 : || TARGET_PREFETCH_SSE
15496 0 : || TARGET_PRFCHW
15497 0 : || TARGET_MOVRS)
15498 44 : emit_insn (gen_prefetch (op0, op1, op2));
15499 0 : else if (!MEM_P (op0) && side_effects_p (op0))
15500 : /* Don't do anything with direct references to volatile memory,
15501 : but generate code to handle other side effects. */
15502 0 : emit_insn (op0);
15503 : }
15504 :
15505 : return 0;
15506 : }
15507 :
15508 21 : case IX86_BUILTIN_PREFETCHI:
15509 21 : {
15510 21 : arg0 = CALL_EXPR_ARG (exp, 0); // const void *
15511 21 : arg1 = CALL_EXPR_ARG (exp, 1); // const int
15512 :
15513 21 : op0 = expand_normal (arg0);
15514 21 : op1 = expand_normal (arg1);
15515 :
15516 21 : if (!CONST_INT_P (op1))
15517 : {
15518 0 : error ("second argument must be a const");
15519 0 : return const0_rtx;
15520 : }
15521 :
15522 : /* GOT/PLT_PIC should not be available for instruction prefetch.
15523 : It must be real instruction address. */
15524 21 : if (TARGET_64BIT
15525 21 : && local_func_symbolic_operand (op0, GET_MODE (op0)))
15526 4 : emit_insn (gen_prefetchi (op0, op1));
15527 : else
15528 : {
15529 : /* Ignore the hint. */
15530 17 : warning (0, "instruction prefetch applies when in 64-bit mode"
15531 : " with RIP-relative addressing and"
15532 : " option %<-mprefetchi%>;"
15533 : " they stay NOPs otherwise");
15534 17 : emit_insn (gen_nop ());
15535 : }
15536 :
15537 : return 0;
15538 : }
15539 :
15540 53 : case IX86_BUILTIN_URDMSR:
15541 53 : case IX86_BUILTIN_UWRMSR:
15542 53 : {
15543 53 : arg0 = CALL_EXPR_ARG (exp, 0);
15544 53 : op0 = expand_normal (arg0);
15545 :
15546 53 : if (CONST_INT_P (op0))
15547 : {
15548 12 : unsigned HOST_WIDE_INT val = UINTVAL (op0);
15549 12 : if (val > 0xffffffff)
15550 2 : op0 = force_reg (DImode, op0);
15551 : }
15552 : else
15553 41 : op0 = force_reg (DImode, op0);
15554 :
15555 53 : if (fcode == IX86_BUILTIN_UWRMSR)
15556 : {
15557 26 : arg1 = CALL_EXPR_ARG (exp, 1);
15558 26 : op1 = expand_normal (arg1);
15559 26 : op1 = force_reg (DImode, op1);
15560 26 : icode = CODE_FOR_uwrmsr;
15561 26 : target = 0;
15562 : }
15563 : else
15564 : {
15565 27 : if (target == 0 || !register_operand (target, DImode))
15566 1 : target = gen_reg_rtx (DImode);
15567 : icode = CODE_FOR_urdmsr;
15568 : op1 = op0;
15569 : op0 = target;
15570 : }
15571 53 : emit_insn (GEN_FCN (icode) (op0, op1));
15572 53 : return target;
15573 : }
15574 :
15575 229 : case IX86_BUILTIN_VEC_INIT_V2SI:
15576 229 : case IX86_BUILTIN_VEC_INIT_V4HI:
15577 229 : case IX86_BUILTIN_VEC_INIT_V8QI:
15578 229 : return ix86_expand_vec_init_builtin (TREE_TYPE (exp), exp, target);
15579 :
15580 400 : case IX86_BUILTIN_VEC_EXT_V2DF:
15581 400 : case IX86_BUILTIN_VEC_EXT_V2DI:
15582 400 : case IX86_BUILTIN_VEC_EXT_V4SF:
15583 400 : case IX86_BUILTIN_VEC_EXT_V4SI:
15584 400 : case IX86_BUILTIN_VEC_EXT_V8HI:
15585 400 : case IX86_BUILTIN_VEC_EXT_V2SI:
15586 400 : case IX86_BUILTIN_VEC_EXT_V4HI:
15587 400 : case IX86_BUILTIN_VEC_EXT_V16QI:
15588 400 : return ix86_expand_vec_ext_builtin (exp, target);
15589 :
15590 204 : case IX86_BUILTIN_VEC_SET_V2DI:
15591 204 : case IX86_BUILTIN_VEC_SET_V4SF:
15592 204 : case IX86_BUILTIN_VEC_SET_V4SI:
15593 204 : case IX86_BUILTIN_VEC_SET_V8HI:
15594 204 : case IX86_BUILTIN_VEC_SET_V4HI:
15595 204 : case IX86_BUILTIN_VEC_SET_V16QI:
15596 204 : return ix86_expand_vec_set_builtin (exp);
15597 :
15598 0 : case IX86_BUILTIN_NANQ:
15599 0 : case IX86_BUILTIN_NANSQ:
15600 0 : return expand_call (exp, target, ignore);
15601 :
15602 18 : case IX86_BUILTIN_RDPID:
15603 :
15604 18 : op0 = gen_reg_rtx (word_mode);
15605 :
15606 18 : if (TARGET_64BIT)
15607 : {
15608 18 : insn = gen_rdpid_rex64 (op0);
15609 18 : op0 = convert_to_mode (SImode, op0, 1);
15610 : }
15611 : else
15612 0 : insn = gen_rdpid (op0);
15613 :
15614 18 : emit_insn (insn);
15615 :
15616 18 : if (target == 0
15617 18 : || !register_operand (target, SImode))
15618 0 : target = gen_reg_rtx (SImode);
15619 :
15620 18 : emit_move_insn (target, op0);
15621 18 : return target;
15622 :
15623 75 : case IX86_BUILTIN_2INTERSECTD512:
15624 75 : case IX86_BUILTIN_2INTERSECTQ512:
15625 75 : case IX86_BUILTIN_2INTERSECTD256:
15626 75 : case IX86_BUILTIN_2INTERSECTQ256:
15627 75 : case IX86_BUILTIN_2INTERSECTD128:
15628 75 : case IX86_BUILTIN_2INTERSECTQ128:
15629 75 : arg0 = CALL_EXPR_ARG (exp, 0);
15630 75 : arg1 = CALL_EXPR_ARG (exp, 1);
15631 75 : arg2 = CALL_EXPR_ARG (exp, 2);
15632 75 : arg3 = CALL_EXPR_ARG (exp, 3);
15633 75 : op0 = expand_normal (arg0);
15634 75 : op1 = expand_normal (arg1);
15635 75 : op2 = expand_normal (arg2);
15636 75 : op3 = expand_normal (arg3);
15637 :
15638 75 : if (!address_operand (op0, VOIDmode))
15639 : {
15640 25 : op0 = convert_memory_address (Pmode, op0);
15641 25 : op0 = copy_addr_to_reg (op0);
15642 : }
15643 75 : if (!address_operand (op1, VOIDmode))
15644 : {
15645 25 : op1 = convert_memory_address (Pmode, op1);
15646 25 : op1 = copy_addr_to_reg (op1);
15647 : }
15648 :
15649 75 : switch (fcode)
15650 : {
15651 : case IX86_BUILTIN_2INTERSECTD512:
15652 : mode4 = P2HImode;
15653 : icode = CODE_FOR_avx512vp2intersect_2intersectv16si;
15654 : break;
15655 : case IX86_BUILTIN_2INTERSECTQ512:
15656 : mode4 = P2QImode;
15657 : icode = CODE_FOR_avx512vp2intersect_2intersectv8di;
15658 : break;
15659 : case IX86_BUILTIN_2INTERSECTD256:
15660 : mode4 = P2QImode;
15661 : icode = CODE_FOR_avx512vp2intersect_2intersectv8si;
15662 : break;
15663 : case IX86_BUILTIN_2INTERSECTQ256:
15664 : mode4 = P2QImode;
15665 : icode = CODE_FOR_avx512vp2intersect_2intersectv4di;
15666 : break;
15667 : case IX86_BUILTIN_2INTERSECTD128:
15668 : mode4 = P2QImode;
15669 : icode = CODE_FOR_avx512vp2intersect_2intersectv4si;
15670 : break;
15671 : case IX86_BUILTIN_2INTERSECTQ128:
15672 : mode4 = P2QImode;
15673 : icode = CODE_FOR_avx512vp2intersect_2intersectv2di;
15674 : break;
15675 0 : default:
15676 0 : gcc_unreachable ();
15677 : }
15678 :
15679 75 : mode2 = insn_data[icode].operand[1].mode;
15680 75 : mode3 = insn_data[icode].operand[2].mode;
15681 75 : if (!insn_data[icode].operand[1].predicate (op2, mode2))
15682 25 : op2 = copy_to_mode_reg (mode2, op2);
15683 75 : if (!insn_data[icode].operand[2].predicate (op3, mode3))
15684 6 : op3 = copy_to_mode_reg (mode3, op3);
15685 :
15686 75 : op4 = gen_reg_rtx (mode4);
15687 75 : emit_insn (GEN_FCN (icode) (op4, op2, op3));
15688 75 : mode0 = mode4 == P2HImode ? HImode : QImode;
15689 75 : emit_move_insn (gen_rtx_MEM (mode0, op0),
15690 75 : gen_lowpart (mode0, op4));
15691 75 : emit_move_insn (gen_rtx_MEM (mode0, op1),
15692 : gen_highpart (mode0, op4));
15693 :
15694 75 : return 0;
15695 :
15696 102 : case IX86_BUILTIN_RDPMC:
15697 102 : case IX86_BUILTIN_RDTSC:
15698 102 : case IX86_BUILTIN_RDTSCP:
15699 102 : case IX86_BUILTIN_XGETBV:
15700 :
15701 102 : op0 = gen_reg_rtx (DImode);
15702 102 : op1 = gen_reg_rtx (DImode);
15703 :
15704 102 : if (fcode == IX86_BUILTIN_RDPMC)
15705 : {
15706 22 : arg0 = CALL_EXPR_ARG (exp, 0);
15707 22 : op2 = expand_normal (arg0);
15708 22 : if (!register_operand (op2, SImode))
15709 11 : op2 = copy_to_mode_reg (SImode, op2);
15710 :
15711 22 : insn = (TARGET_64BIT
15712 22 : ? gen_rdpmc_rex64 (op0, op1, op2)
15713 0 : : gen_rdpmc (op0, op2));
15714 22 : emit_insn (insn);
15715 : }
15716 80 : else if (fcode == IX86_BUILTIN_XGETBV)
15717 : {
15718 22 : arg0 = CALL_EXPR_ARG (exp, 0);
15719 22 : op2 = expand_normal (arg0);
15720 22 : if (!register_operand (op2, SImode))
15721 1 : op2 = copy_to_mode_reg (SImode, op2);
15722 :
15723 22 : insn = (TARGET_64BIT
15724 22 : ? gen_xgetbv_rex64 (op0, op1, op2)
15725 0 : : gen_xgetbv (op0, op2));
15726 22 : emit_insn (insn);
15727 : }
15728 58 : else if (fcode == IX86_BUILTIN_RDTSC)
15729 : {
15730 36 : insn = (TARGET_64BIT
15731 36 : ? gen_rdtsc_rex64 (op0, op1)
15732 2 : : gen_rdtsc (op0));
15733 36 : emit_insn (insn);
15734 : }
15735 : else
15736 : {
15737 22 : op2 = gen_reg_rtx (SImode);
15738 :
15739 22 : insn = (TARGET_64BIT
15740 22 : ? gen_rdtscp_rex64 (op0, op1, op2)
15741 0 : : gen_rdtscp (op0, op2));
15742 22 : emit_insn (insn);
15743 :
15744 22 : arg0 = CALL_EXPR_ARG (exp, 0);
15745 22 : op4 = expand_normal (arg0);
15746 22 : if (!address_operand (op4, VOIDmode))
15747 : {
15748 10 : op4 = convert_memory_address (Pmode, op4);
15749 10 : op4 = copy_addr_to_reg (op4);
15750 : }
15751 22 : emit_move_insn (gen_rtx_MEM (SImode, op4), op2);
15752 : }
15753 :
15754 102 : if (target == 0
15755 102 : || !register_operand (target, DImode))
15756 10 : target = gen_reg_rtx (DImode);
15757 :
15758 102 : if (TARGET_64BIT)
15759 : {
15760 100 : op1 = expand_simple_binop (DImode, ASHIFT, op1, GEN_INT (32),
15761 : op1, 1, OPTAB_DIRECT);
15762 100 : op0 = expand_simple_binop (DImode, IOR, op0, op1,
15763 : op0, 1, OPTAB_DIRECT);
15764 : }
15765 :
15766 102 : emit_move_insn (target, op0);
15767 102 : return target;
15768 :
15769 62 : case IX86_BUILTIN_ENQCMD:
15770 62 : case IX86_BUILTIN_ENQCMDS:
15771 62 : case IX86_BUILTIN_MOVDIR64B:
15772 :
15773 62 : arg0 = CALL_EXPR_ARG (exp, 0);
15774 62 : arg1 = CALL_EXPR_ARG (exp, 1);
15775 62 : op0 = expand_normal (arg0);
15776 62 : op1 = expand_normal (arg1);
15777 :
15778 62 : op0 = ix86_zero_extend_to_Pmode (op0);
15779 62 : if (!address_operand (op1, VOIDmode))
15780 : {
15781 29 : op1 = convert_memory_address (Pmode, op1);
15782 29 : op1 = copy_addr_to_reg (op1);
15783 : }
15784 62 : op1 = gen_rtx_MEM (XImode, op1);
15785 :
15786 62 : if (fcode == IX86_BUILTIN_MOVDIR64B)
15787 : {
15788 25 : emit_insn (gen_movdir64b (Pmode, op0, op1));
15789 24 : return 0;
15790 : }
15791 : else
15792 : {
15793 38 : if (target == 0
15794 38 : || !register_operand (target, SImode))
15795 0 : target = gen_reg_rtx (SImode);
15796 :
15797 38 : emit_move_insn (target, const0_rtx);
15798 38 : target = gen_rtx_SUBREG (QImode, target, 0);
15799 :
15800 19 : int unspecv = (fcode == IX86_BUILTIN_ENQCMD
15801 38 : ? UNSPECV_ENQCMD
15802 : : UNSPECV_ENQCMDS);
15803 38 : icode = code_for_enqcmd (unspecv, Pmode);
15804 38 : emit_insn (GEN_FCN (icode) (op0, op1));
15805 :
15806 38 : emit_insn
15807 38 : (gen_rtx_SET (gen_rtx_STRICT_LOW_PART (VOIDmode, target),
15808 : gen_rtx_fmt_ee (EQ, QImode,
15809 : gen_rtx_REG (CCZmode, FLAGS_REG),
15810 : const0_rtx)));
15811 38 : return SUBREG_REG (target);
15812 : }
15813 :
15814 14703 : case IX86_BUILTIN_FXSAVE:
15815 14703 : case IX86_BUILTIN_FXRSTOR:
15816 14703 : case IX86_BUILTIN_FXSAVE64:
15817 14703 : case IX86_BUILTIN_FXRSTOR64:
15818 14703 : case IX86_BUILTIN_FNSTENV:
15819 14703 : case IX86_BUILTIN_FLDENV:
15820 14703 : mode0 = BLKmode;
15821 14703 : switch (fcode)
15822 : {
15823 : case IX86_BUILTIN_FXSAVE:
15824 : icode = CODE_FOR_fxsave;
15825 : break;
15826 19 : case IX86_BUILTIN_FXRSTOR:
15827 19 : icode = CODE_FOR_fxrstor;
15828 19 : break;
15829 23 : case IX86_BUILTIN_FXSAVE64:
15830 23 : icode = CODE_FOR_fxsave64;
15831 23 : break;
15832 21 : case IX86_BUILTIN_FXRSTOR64:
15833 21 : icode = CODE_FOR_fxrstor64;
15834 21 : break;
15835 7258 : case IX86_BUILTIN_FNSTENV:
15836 7258 : icode = CODE_FOR_fnstenv;
15837 7258 : break;
15838 7362 : case IX86_BUILTIN_FLDENV:
15839 7362 : icode = CODE_FOR_fldenv;
15840 7362 : break;
15841 0 : default:
15842 0 : gcc_unreachable ();
15843 : }
15844 :
15845 14703 : arg0 = CALL_EXPR_ARG (exp, 0);
15846 14703 : op0 = expand_normal (arg0);
15847 :
15848 14703 : if (!address_operand (op0, VOIDmode))
15849 : {
15850 36 : op0 = convert_memory_address (Pmode, op0);
15851 36 : op0 = copy_addr_to_reg (op0);
15852 : }
15853 14703 : op0 = gen_rtx_MEM (mode0, op0);
15854 :
15855 14703 : pat = GEN_FCN (icode) (op0);
15856 14703 : if (pat)
15857 14703 : emit_insn (pat);
15858 : return 0;
15859 :
15860 21 : case IX86_BUILTIN_XSETBV:
15861 21 : arg0 = CALL_EXPR_ARG (exp, 0);
15862 21 : arg1 = CALL_EXPR_ARG (exp, 1);
15863 21 : op0 = expand_normal (arg0);
15864 21 : op1 = expand_normal (arg1);
15865 :
15866 21 : if (!REG_P (op0))
15867 1 : op0 = copy_to_mode_reg (SImode, op0);
15868 :
15869 21 : op1 = force_reg (DImode, op1);
15870 :
15871 21 : if (TARGET_64BIT)
15872 : {
15873 21 : op2 = expand_simple_binop (DImode, LSHIFTRT, op1, GEN_INT (32),
15874 : NULL, 1, OPTAB_DIRECT);
15875 :
15876 21 : icode = CODE_FOR_xsetbv_rex64;
15877 :
15878 21 : op2 = gen_lowpart (SImode, op2);
15879 21 : op1 = gen_lowpart (SImode, op1);
15880 21 : pat = GEN_FCN (icode) (op0, op1, op2);
15881 : }
15882 : else
15883 : {
15884 0 : icode = CODE_FOR_xsetbv;
15885 :
15886 0 : pat = GEN_FCN (icode) (op0, op1);
15887 : }
15888 21 : if (pat)
15889 21 : emit_insn (pat);
15890 : return 0;
15891 :
15892 232 : case IX86_BUILTIN_XSAVE:
15893 232 : case IX86_BUILTIN_XRSTOR:
15894 232 : case IX86_BUILTIN_XSAVE64:
15895 232 : case IX86_BUILTIN_XRSTOR64:
15896 232 : case IX86_BUILTIN_XSAVEOPT:
15897 232 : case IX86_BUILTIN_XSAVEOPT64:
15898 232 : case IX86_BUILTIN_XSAVES:
15899 232 : case IX86_BUILTIN_XRSTORS:
15900 232 : case IX86_BUILTIN_XSAVES64:
15901 232 : case IX86_BUILTIN_XRSTORS64:
15902 232 : case IX86_BUILTIN_XSAVEC:
15903 232 : case IX86_BUILTIN_XSAVEC64:
15904 232 : arg0 = CALL_EXPR_ARG (exp, 0);
15905 232 : arg1 = CALL_EXPR_ARG (exp, 1);
15906 232 : op0 = expand_normal (arg0);
15907 232 : op1 = expand_normal (arg1);
15908 :
15909 232 : if (!address_operand (op0, VOIDmode))
15910 : {
15911 108 : op0 = convert_memory_address (Pmode, op0);
15912 108 : op0 = copy_addr_to_reg (op0);
15913 : }
15914 232 : op0 = gen_rtx_MEM (BLKmode, op0);
15915 :
15916 232 : op1 = force_reg (DImode, op1);
15917 :
15918 232 : if (TARGET_64BIT)
15919 : {
15920 232 : op2 = expand_simple_binop (DImode, LSHIFTRT, op1, GEN_INT (32),
15921 : NULL, 1, OPTAB_DIRECT);
15922 232 : switch (fcode)
15923 : {
15924 : case IX86_BUILTIN_XSAVE:
15925 : icode = CODE_FOR_xsave_rex64;
15926 : break;
15927 19 : case IX86_BUILTIN_XRSTOR:
15928 19 : icode = CODE_FOR_xrstor_rex64;
15929 19 : break;
15930 21 : case IX86_BUILTIN_XSAVE64:
15931 21 : icode = CODE_FOR_xsave64;
15932 21 : break;
15933 21 : case IX86_BUILTIN_XRSTOR64:
15934 21 : icode = CODE_FOR_xrstor64;
15935 21 : break;
15936 19 : case IX86_BUILTIN_XSAVEOPT:
15937 19 : icode = CODE_FOR_xsaveopt_rex64;
15938 19 : break;
15939 19 : case IX86_BUILTIN_XSAVEOPT64:
15940 19 : icode = CODE_FOR_xsaveopt64;
15941 19 : break;
15942 19 : case IX86_BUILTIN_XSAVES:
15943 19 : icode = CODE_FOR_xsaves_rex64;
15944 19 : break;
15945 19 : case IX86_BUILTIN_XRSTORS:
15946 19 : icode = CODE_FOR_xrstors_rex64;
15947 19 : break;
15948 19 : case IX86_BUILTIN_XSAVES64:
15949 19 : icode = CODE_FOR_xsaves64;
15950 19 : break;
15951 19 : case IX86_BUILTIN_XRSTORS64:
15952 19 : icode = CODE_FOR_xrstors64;
15953 19 : break;
15954 19 : case IX86_BUILTIN_XSAVEC:
15955 19 : icode = CODE_FOR_xsavec_rex64;
15956 19 : break;
15957 19 : case IX86_BUILTIN_XSAVEC64:
15958 19 : icode = CODE_FOR_xsavec64;
15959 19 : break;
15960 0 : default:
15961 0 : gcc_unreachable ();
15962 : }
15963 :
15964 232 : op2 = gen_lowpart (SImode, op2);
15965 232 : op1 = gen_lowpart (SImode, op1);
15966 232 : pat = GEN_FCN (icode) (op0, op1, op2);
15967 : }
15968 : else
15969 : {
15970 0 : switch (fcode)
15971 : {
15972 : case IX86_BUILTIN_XSAVE:
15973 : icode = CODE_FOR_xsave;
15974 : break;
15975 : case IX86_BUILTIN_XRSTOR:
15976 : icode = CODE_FOR_xrstor;
15977 : break;
15978 : case IX86_BUILTIN_XSAVEOPT:
15979 : icode = CODE_FOR_xsaveopt;
15980 : break;
15981 : case IX86_BUILTIN_XSAVES:
15982 : icode = CODE_FOR_xsaves;
15983 : break;
15984 : case IX86_BUILTIN_XRSTORS:
15985 : icode = CODE_FOR_xrstors;
15986 : break;
15987 : case IX86_BUILTIN_XSAVEC:
15988 : icode = CODE_FOR_xsavec;
15989 : break;
15990 0 : default:
15991 0 : gcc_unreachable ();
15992 : }
15993 0 : pat = GEN_FCN (icode) (op0, op1);
15994 : }
15995 :
15996 232 : if (pat)
15997 232 : emit_insn (pat);
15998 : return 0;
15999 :
16000 137 : case IX86_BUILTIN_LDTILECFG:
16001 137 : case IX86_BUILTIN_STTILECFG:
16002 137 : arg0 = CALL_EXPR_ARG (exp, 0);
16003 137 : op0 = expand_normal (arg0);
16004 :
16005 137 : if (!address_operand (op0, VOIDmode))
16006 : {
16007 8 : op0 = convert_memory_address (Pmode, op0);
16008 8 : op0 = copy_addr_to_reg (op0);
16009 : }
16010 137 : op0 = gen_rtx_MEM (BLKmode, op0);
16011 137 : if (fcode == IX86_BUILTIN_LDTILECFG)
16012 : icode = CODE_FOR_ldtilecfg;
16013 : else
16014 88 : icode = CODE_FOR_sttilecfg;
16015 137 : pat = GEN_FCN (icode) (op0);
16016 137 : emit_insn (pat);
16017 137 : return 0;
16018 :
16019 18 : case IX86_BUILTIN_LLWPCB:
16020 18 : arg0 = CALL_EXPR_ARG (exp, 0);
16021 18 : op0 = expand_normal (arg0);
16022 :
16023 18 : if (!register_operand (op0, Pmode))
16024 9 : op0 = ix86_zero_extend_to_Pmode (op0);
16025 18 : emit_insn (gen_lwp_llwpcb (Pmode, op0));
16026 18 : return 0;
16027 :
16028 18 : case IX86_BUILTIN_SLWPCB:
16029 18 : if (!target
16030 18 : || !register_operand (target, Pmode))
16031 0 : target = gen_reg_rtx (Pmode);
16032 18 : emit_insn (gen_lwp_slwpcb (Pmode, target));
16033 18 : return target;
16034 :
16035 51 : case IX86_BUILTIN_LWPVAL32:
16036 51 : case IX86_BUILTIN_LWPVAL64:
16037 51 : case IX86_BUILTIN_LWPINS32:
16038 51 : case IX86_BUILTIN_LWPINS64:
16039 51 : mode = ((fcode == IX86_BUILTIN_LWPVAL32
16040 51 : || fcode == IX86_BUILTIN_LWPINS32)
16041 51 : ? SImode : DImode);
16042 :
16043 51 : if (fcode == IX86_BUILTIN_LWPVAL32
16044 51 : || fcode == IX86_BUILTIN_LWPVAL64)
16045 26 : icode = code_for_lwp_lwpval (mode);
16046 : else
16047 25 : icode = code_for_lwp_lwpins (mode);
16048 :
16049 51 : arg0 = CALL_EXPR_ARG (exp, 0);
16050 51 : arg1 = CALL_EXPR_ARG (exp, 1);
16051 51 : arg2 = CALL_EXPR_ARG (exp, 2);
16052 51 : op0 = expand_normal (arg0);
16053 51 : op1 = expand_normal (arg1);
16054 51 : op2 = expand_normal (arg2);
16055 51 : mode0 = insn_data[icode].operand[0].mode;
16056 :
16057 51 : if (!insn_data[icode].operand[0].predicate (op0, mode0))
16058 13 : op0 = copy_to_mode_reg (mode0, op0);
16059 51 : if (!insn_data[icode].operand[1].predicate (op1, SImode))
16060 0 : op1 = copy_to_mode_reg (SImode, op1);
16061 :
16062 51 : if (!CONST_INT_P (op2))
16063 : {
16064 0 : error ("the last argument must be a 32-bit immediate");
16065 0 : return const0_rtx;
16066 : }
16067 :
16068 51 : emit_insn (GEN_FCN (icode) (op0, op1, op2));
16069 :
16070 51 : if (fcode == IX86_BUILTIN_LWPINS32
16071 51 : || fcode == IX86_BUILTIN_LWPINS64)
16072 : {
16073 25 : if (target == 0
16074 25 : || !nonimmediate_operand (target, QImode))
16075 0 : target = gen_reg_rtx (QImode);
16076 :
16077 25 : pat = gen_rtx_EQ (QImode, gen_rtx_REG (CCCmode, FLAGS_REG),
16078 : const0_rtx);
16079 25 : emit_insn (gen_rtx_SET (target, pat));
16080 :
16081 25 : return target;
16082 : }
16083 : else
16084 : return 0;
16085 :
16086 18 : case IX86_BUILTIN_BEXTRI32:
16087 18 : case IX86_BUILTIN_BEXTRI64:
16088 18 : mode = (fcode == IX86_BUILTIN_BEXTRI32 ? SImode : DImode);
16089 :
16090 18 : arg0 = CALL_EXPR_ARG (exp, 0);
16091 18 : arg1 = CALL_EXPR_ARG (exp, 1);
16092 18 : op0 = expand_normal (arg0);
16093 18 : op1 = expand_normal (arg1);
16094 :
16095 18 : if (!CONST_INT_P (op1))
16096 : {
16097 0 : error ("last argument must be an immediate");
16098 0 : return const0_rtx;
16099 : }
16100 : else
16101 : {
16102 18 : unsigned char lsb_index = UINTVAL (op1);
16103 18 : unsigned char length = UINTVAL (op1) >> 8;
16104 :
16105 18 : unsigned char bitsize = GET_MODE_BITSIZE (mode);
16106 :
16107 18 : icode = code_for_tbm_bextri (mode);
16108 :
16109 18 : mode1 = insn_data[icode].operand[1].mode;
16110 18 : if (!insn_data[icode].operand[1].predicate (op0, mode1))
16111 12 : op0 = copy_to_mode_reg (mode1, op0);
16112 :
16113 18 : mode0 = insn_data[icode].operand[0].mode;
16114 18 : if (target == 0
16115 18 : || !register_operand (target, mode0))
16116 0 : target = gen_reg_rtx (mode0);
16117 :
16118 18 : if (length == 0 || lsb_index >= bitsize)
16119 : {
16120 8 : emit_move_insn (target, const0_rtx);
16121 8 : return target;
16122 : }
16123 :
16124 10 : if (length + lsb_index > bitsize)
16125 5 : length = bitsize - lsb_index;
16126 :
16127 10 : op1 = GEN_INT (length);
16128 10 : op2 = GEN_INT (lsb_index);
16129 :
16130 10 : emit_insn (GEN_FCN (icode) (target, op0, op1, op2));
16131 10 : return target;
16132 : }
16133 :
16134 21 : case IX86_BUILTIN_RDRAND16_STEP:
16135 21 : mode = HImode;
16136 21 : goto rdrand_step;
16137 :
16138 42 : case IX86_BUILTIN_RDRAND32_STEP:
16139 42 : mode = SImode;
16140 42 : goto rdrand_step;
16141 :
16142 : case IX86_BUILTIN_RDRAND64_STEP:
16143 : mode = DImode;
16144 :
16145 83 : rdrand_step:
16146 83 : arg0 = CALL_EXPR_ARG (exp, 0);
16147 83 : op1 = expand_normal (arg0);
16148 83 : if (!address_operand (op1, VOIDmode))
16149 : {
16150 29 : op1 = convert_memory_address (Pmode, op1);
16151 29 : op1 = copy_addr_to_reg (op1);
16152 : }
16153 :
16154 83 : op0 = gen_reg_rtx (mode);
16155 83 : emit_insn (gen_rdrand (mode, op0));
16156 :
16157 83 : emit_move_insn (gen_rtx_MEM (mode, op1), op0);
16158 :
16159 83 : op1 = force_reg (SImode, const1_rtx);
16160 :
16161 : /* Emit SImode conditional move. */
16162 83 : if (mode == HImode)
16163 : {
16164 21 : if (TARGET_ZERO_EXTEND_WITH_AND
16165 21 : && optimize_function_for_speed_p (cfun))
16166 : {
16167 0 : op2 = force_reg (SImode, const0_rtx);
16168 :
16169 0 : emit_insn (gen_movstricthi
16170 0 : (gen_lowpart (HImode, op2), op0));
16171 : }
16172 : else
16173 : {
16174 21 : op2 = gen_reg_rtx (SImode);
16175 :
16176 21 : emit_insn (gen_zero_extendhisi2 (op2, op0));
16177 : }
16178 : }
16179 62 : else if (mode == SImode)
16180 : op2 = op0;
16181 : else
16182 20 : op2 = gen_rtx_SUBREG (SImode, op0, 0);
16183 :
16184 83 : if (target == 0
16185 83 : || !register_operand (target, SImode))
16186 7 : target = gen_reg_rtx (SImode);
16187 :
16188 83 : pat = gen_rtx_GEU (VOIDmode, gen_rtx_REG (CCCmode, FLAGS_REG),
16189 : const0_rtx);
16190 83 : emit_insn (gen_rtx_SET (target,
16191 : gen_rtx_IF_THEN_ELSE (SImode, pat, op2, op1)));
16192 83 : return target;
16193 :
16194 19 : case IX86_BUILTIN_RDSEED16_STEP:
16195 19 : mode = HImode;
16196 19 : goto rdseed_step;
16197 :
16198 28 : case IX86_BUILTIN_RDSEED32_STEP:
16199 28 : mode = SImode;
16200 28 : goto rdseed_step;
16201 :
16202 : case IX86_BUILTIN_RDSEED64_STEP:
16203 : mode = DImode;
16204 :
16205 66 : rdseed_step:
16206 66 : arg0 = CALL_EXPR_ARG (exp, 0);
16207 66 : op1 = expand_normal (arg0);
16208 66 : if (!address_operand (op1, VOIDmode))
16209 : {
16210 28 : op1 = convert_memory_address (Pmode, op1);
16211 28 : op1 = copy_addr_to_reg (op1);
16212 : }
16213 :
16214 66 : op0 = gen_reg_rtx (mode);
16215 66 : emit_insn (gen_rdseed (mode, op0));
16216 :
16217 66 : emit_move_insn (gen_rtx_MEM (mode, op1), op0);
16218 :
16219 66 : op2 = gen_reg_rtx (QImode);
16220 :
16221 66 : pat = gen_rtx_LTU (QImode, gen_rtx_REG (CCCmode, FLAGS_REG),
16222 : const0_rtx);
16223 66 : emit_insn (gen_rtx_SET (op2, pat));
16224 :
16225 66 : if (target == 0
16226 66 : || !register_operand (target, SImode))
16227 1 : target = gen_reg_rtx (SImode);
16228 :
16229 66 : emit_insn (gen_zero_extendqisi2 (target, op2));
16230 66 : return target;
16231 :
16232 38 : case IX86_BUILTIN_SBB32:
16233 38 : icode = CODE_FOR_subborrowsi;
16234 38 : icode2 = CODE_FOR_subborrowsi_0;
16235 38 : mode0 = SImode;
16236 38 : mode1 = DImode;
16237 38 : mode2 = CCmode;
16238 38 : goto handlecarry;
16239 :
16240 44 : case IX86_BUILTIN_SBB64:
16241 44 : icode = CODE_FOR_subborrowdi;
16242 44 : icode2 = CODE_FOR_subborrowdi_0;
16243 44 : mode0 = DImode;
16244 44 : mode1 = TImode;
16245 44 : mode2 = CCmode;
16246 44 : goto handlecarry;
16247 :
16248 68 : case IX86_BUILTIN_ADDCARRYX32:
16249 68 : icode = CODE_FOR_addcarrysi;
16250 68 : icode2 = CODE_FOR_addcarrysi_0;
16251 68 : mode0 = SImode;
16252 68 : mode1 = DImode;
16253 68 : mode2 = CCCmode;
16254 68 : goto handlecarry;
16255 :
16256 : case IX86_BUILTIN_ADDCARRYX64:
16257 : icode = CODE_FOR_addcarrydi;
16258 : icode2 = CODE_FOR_addcarrydi_0;
16259 : mode0 = DImode;
16260 : mode1 = TImode;
16261 : mode2 = CCCmode;
16262 :
16263 212 : handlecarry:
16264 212 : arg0 = CALL_EXPR_ARG (exp, 0); /* unsigned char c_in. */
16265 212 : arg1 = CALL_EXPR_ARG (exp, 1); /* unsigned int src1. */
16266 212 : arg2 = CALL_EXPR_ARG (exp, 2); /* unsigned int src2. */
16267 212 : arg3 = CALL_EXPR_ARG (exp, 3); /* unsigned int *sum_out. */
16268 :
16269 212 : op1 = expand_normal (arg0);
16270 :
16271 212 : op2 = expand_normal (arg1);
16272 212 : if (!register_operand (op2, mode0))
16273 117 : op2 = copy_to_mode_reg (mode0, op2);
16274 :
16275 212 : op3 = expand_normal (arg2);
16276 212 : if (!register_operand (op3, mode0))
16277 120 : op3 = copy_to_mode_reg (mode0, op3);
16278 :
16279 212 : op4 = expand_normal (arg3);
16280 212 : if (!address_operand (op4, VOIDmode))
16281 : {
16282 67 : op4 = convert_memory_address (Pmode, op4);
16283 67 : op4 = copy_addr_to_reg (op4);
16284 : }
16285 :
16286 212 : op0 = gen_reg_rtx (mode0);
16287 212 : if (op1 == const0_rtx)
16288 : {
16289 : /* If arg0 is 0, optimize right away into add or sub
16290 : instruction that sets CCCmode flags. */
16291 21 : op1 = gen_rtx_REG (mode2, FLAGS_REG);
16292 21 : emit_insn (GEN_FCN (icode2) (op0, op2, op3));
16293 : }
16294 : else
16295 : {
16296 : /* Generate CF from input operand. */
16297 191 : ix86_expand_carry (op1);
16298 :
16299 : /* Generate instruction that consumes CF. */
16300 191 : op1 = gen_rtx_REG (CCCmode, FLAGS_REG);
16301 191 : pat = gen_rtx_LTU (mode1, op1, const0_rtx);
16302 191 : pat2 = gen_rtx_LTU (mode0, op1, const0_rtx);
16303 191 : emit_insn (GEN_FCN (icode) (op0, op2, op3, op1, pat, pat2));
16304 : }
16305 :
16306 : /* Return current CF value. */
16307 212 : if (target == 0)
16308 14 : target = gen_reg_rtx (QImode);
16309 :
16310 212 : pat = gen_rtx_LTU (QImode, op1, const0_rtx);
16311 212 : emit_insn (gen_rtx_SET (target, pat));
16312 :
16313 : /* Store the result. */
16314 212 : emit_move_insn (gen_rtx_MEM (mode0, op4), op0);
16315 :
16316 212 : return target;
16317 :
16318 24 : case IX86_BUILTIN_READ_FLAGS:
16319 24 : if (ignore)
16320 3 : return const0_rtx;
16321 :
16322 21 : emit_insn (gen_pushfl ());
16323 :
16324 21 : if (optimize
16325 11 : || target == NULL_RTX
16326 11 : || !nonimmediate_operand (target, word_mode)
16327 32 : || GET_MODE (target) != word_mode)
16328 10 : target = gen_reg_rtx (word_mode);
16329 :
16330 21 : emit_insn (gen_pop (target));
16331 21 : return target;
16332 :
16333 21 : case IX86_BUILTIN_WRITE_FLAGS:
16334 :
16335 21 : arg0 = CALL_EXPR_ARG (exp, 0);
16336 21 : op0 = expand_normal (arg0);
16337 21 : if (!general_no_elim_operand (op0, word_mode))
16338 0 : op0 = copy_to_mode_reg (word_mode, op0);
16339 :
16340 21 : emit_insn (gen_push (op0));
16341 21 : emit_insn (gen_popfl ());
16342 21 : return 0;
16343 :
16344 22 : case IX86_BUILTIN_KTESTC8:
16345 22 : icode = CODE_FOR_ktestqi;
16346 22 : mode3 = CCCmode;
16347 22 : goto kortest;
16348 :
16349 22 : case IX86_BUILTIN_KTESTZ8:
16350 22 : icode = CODE_FOR_ktestqi;
16351 22 : mode3 = CCZmode;
16352 22 : goto kortest;
16353 :
16354 22 : case IX86_BUILTIN_KTESTC16:
16355 22 : icode = CODE_FOR_ktesthi;
16356 22 : mode3 = CCCmode;
16357 22 : goto kortest;
16358 :
16359 22 : case IX86_BUILTIN_KTESTZ16:
16360 22 : icode = CODE_FOR_ktesthi;
16361 22 : mode3 = CCZmode;
16362 22 : goto kortest;
16363 :
16364 22 : case IX86_BUILTIN_KTESTC32:
16365 22 : icode = CODE_FOR_ktestsi;
16366 22 : mode3 = CCCmode;
16367 22 : goto kortest;
16368 :
16369 22 : case IX86_BUILTIN_KTESTZ32:
16370 22 : icode = CODE_FOR_ktestsi;
16371 22 : mode3 = CCZmode;
16372 22 : goto kortest;
16373 :
16374 22 : case IX86_BUILTIN_KTESTC64:
16375 22 : icode = CODE_FOR_ktestdi;
16376 22 : mode3 = CCCmode;
16377 22 : goto kortest;
16378 :
16379 22 : case IX86_BUILTIN_KTESTZ64:
16380 22 : icode = CODE_FOR_ktestdi;
16381 22 : mode3 = CCZmode;
16382 22 : goto kortest;
16383 :
16384 22 : case IX86_BUILTIN_KORTESTC8:
16385 22 : icode = CODE_FOR_kortestqi;
16386 22 : mode3 = CCCmode;
16387 22 : goto kortest;
16388 :
16389 76 : case IX86_BUILTIN_KORTESTZ8:
16390 76 : icode = CODE_FOR_kortestqi;
16391 76 : mode3 = CCZmode;
16392 76 : goto kortest;
16393 :
16394 38 : case IX86_BUILTIN_KORTESTC16:
16395 38 : icode = CODE_FOR_kortesthi;
16396 38 : mode3 = CCCmode;
16397 38 : goto kortest;
16398 :
16399 91 : case IX86_BUILTIN_KORTESTZ16:
16400 91 : icode = CODE_FOR_kortesthi;
16401 91 : mode3 = CCZmode;
16402 91 : goto kortest;
16403 :
16404 22 : case IX86_BUILTIN_KORTESTC32:
16405 22 : icode = CODE_FOR_kortestsi;
16406 22 : mode3 = CCCmode;
16407 22 : goto kortest;
16408 :
16409 79 : case IX86_BUILTIN_KORTESTZ32:
16410 79 : icode = CODE_FOR_kortestsi;
16411 79 : mode3 = CCZmode;
16412 79 : goto kortest;
16413 :
16414 22 : case IX86_BUILTIN_KORTESTC64:
16415 22 : icode = CODE_FOR_kortestdi;
16416 22 : mode3 = CCCmode;
16417 22 : goto kortest;
16418 :
16419 : case IX86_BUILTIN_KORTESTZ64:
16420 : icode = CODE_FOR_kortestdi;
16421 : mode3 = CCZmode;
16422 :
16423 610 : kortest:
16424 610 : arg0 = CALL_EXPR_ARG (exp, 0); /* Mask reg src1. */
16425 610 : arg1 = CALL_EXPR_ARG (exp, 1); /* Mask reg src2. */
16426 610 : op0 = expand_normal (arg0);
16427 610 : op1 = expand_normal (arg1);
16428 :
16429 610 : mode0 = insn_data[icode].operand[0].mode;
16430 610 : mode1 = insn_data[icode].operand[1].mode;
16431 :
16432 610 : if (GET_MODE (op0) != VOIDmode)
16433 610 : op0 = force_reg (GET_MODE (op0), op0);
16434 :
16435 610 : op0 = gen_lowpart (mode0, op0);
16436 :
16437 610 : if (!insn_data[icode].operand[0].predicate (op0, mode0))
16438 0 : op0 = copy_to_mode_reg (mode0, op0);
16439 :
16440 610 : if (GET_MODE (op1) != VOIDmode)
16441 609 : op1 = force_reg (GET_MODE (op1), op1);
16442 :
16443 610 : op1 = gen_lowpart (mode1, op1);
16444 :
16445 610 : if (!insn_data[icode].operand[1].predicate (op1, mode1))
16446 1 : op1 = copy_to_mode_reg (mode1, op1);
16447 :
16448 610 : target = gen_reg_rtx (QImode);
16449 :
16450 : /* Emit kortest. */
16451 610 : emit_insn (GEN_FCN (icode) (op0, op1));
16452 : /* And use setcc to return result from flags. */
16453 610 : ix86_expand_setcc (target, EQ,
16454 : gen_rtx_REG (mode3, FLAGS_REG), const0_rtx);
16455 610 : return target;
16456 :
16457 24 : case IX86_BUILTIN_GATHERSIV2DF:
16458 24 : icode = CODE_FOR_avx2_gathersiv2df;
16459 24 : goto gather_gen;
16460 18 : case IX86_BUILTIN_GATHERSIV4DF:
16461 18 : icode = CODE_FOR_avx2_gathersiv4df;
16462 18 : goto gather_gen;
16463 21 : case IX86_BUILTIN_GATHERDIV2DF:
16464 21 : icode = CODE_FOR_avx2_gatherdiv2df;
16465 21 : goto gather_gen;
16466 32 : case IX86_BUILTIN_GATHERDIV4DF:
16467 32 : icode = CODE_FOR_avx2_gatherdiv4df;
16468 32 : goto gather_gen;
16469 30 : case IX86_BUILTIN_GATHERSIV4SF:
16470 30 : icode = CODE_FOR_avx2_gathersiv4sf;
16471 30 : goto gather_gen;
16472 37 : case IX86_BUILTIN_GATHERSIV8SF:
16473 37 : icode = CODE_FOR_avx2_gathersiv8sf;
16474 37 : goto gather_gen;
16475 24 : case IX86_BUILTIN_GATHERDIV4SF:
16476 24 : icode = CODE_FOR_avx2_gatherdiv4sf;
16477 24 : goto gather_gen;
16478 18 : case IX86_BUILTIN_GATHERDIV8SF:
16479 18 : icode = CODE_FOR_avx2_gatherdiv8sf;
16480 18 : goto gather_gen;
16481 18 : case IX86_BUILTIN_GATHERSIV2DI:
16482 18 : icode = CODE_FOR_avx2_gathersiv2di;
16483 18 : goto gather_gen;
16484 18 : case IX86_BUILTIN_GATHERSIV4DI:
16485 18 : icode = CODE_FOR_avx2_gathersiv4di;
16486 18 : goto gather_gen;
16487 27 : case IX86_BUILTIN_GATHERDIV2DI:
16488 27 : icode = CODE_FOR_avx2_gatherdiv2di;
16489 27 : goto gather_gen;
16490 29 : case IX86_BUILTIN_GATHERDIV4DI:
16491 29 : icode = CODE_FOR_avx2_gatherdiv4di;
16492 29 : goto gather_gen;
16493 20 : case IX86_BUILTIN_GATHERSIV4SI:
16494 20 : icode = CODE_FOR_avx2_gathersiv4si;
16495 20 : goto gather_gen;
16496 22 : case IX86_BUILTIN_GATHERSIV8SI:
16497 22 : icode = CODE_FOR_avx2_gathersiv8si;
16498 22 : goto gather_gen;
16499 28 : case IX86_BUILTIN_GATHERDIV4SI:
16500 28 : icode = CODE_FOR_avx2_gatherdiv4si;
16501 28 : goto gather_gen;
16502 18 : case IX86_BUILTIN_GATHERDIV8SI:
16503 18 : icode = CODE_FOR_avx2_gatherdiv8si;
16504 18 : goto gather_gen;
16505 20 : case IX86_BUILTIN_GATHERALTSIV4DF:
16506 20 : icode = CODE_FOR_avx2_gathersiv4df;
16507 20 : goto gather_gen;
16508 16 : case IX86_BUILTIN_GATHERALTDIV8SF:
16509 16 : icode = CODE_FOR_avx2_gatherdiv8sf;
16510 16 : goto gather_gen;
16511 4 : case IX86_BUILTIN_GATHERALTSIV4DI:
16512 4 : icode = CODE_FOR_avx2_gathersiv4di;
16513 4 : goto gather_gen;
16514 12 : case IX86_BUILTIN_GATHERALTDIV8SI:
16515 12 : icode = CODE_FOR_avx2_gatherdiv8si;
16516 12 : goto gather_gen;
16517 36 : case IX86_BUILTIN_GATHER3SIV16SF:
16518 36 : icode = CODE_FOR_avx512f_gathersiv16sf;
16519 36 : goto gather_gen;
16520 24 : case IX86_BUILTIN_GATHER3SIV8DF:
16521 24 : icode = CODE_FOR_avx512f_gathersiv8df;
16522 24 : goto gather_gen;
16523 24 : case IX86_BUILTIN_GATHER3DIV16SF:
16524 24 : icode = CODE_FOR_avx512f_gatherdiv16sf;
16525 24 : goto gather_gen;
16526 37 : case IX86_BUILTIN_GATHER3DIV8DF:
16527 37 : icode = CODE_FOR_avx512f_gatherdiv8df;
16528 37 : goto gather_gen;
16529 30 : case IX86_BUILTIN_GATHER3SIV16SI:
16530 30 : icode = CODE_FOR_avx512f_gathersiv16si;
16531 30 : goto gather_gen;
16532 24 : case IX86_BUILTIN_GATHER3SIV8DI:
16533 24 : icode = CODE_FOR_avx512f_gathersiv8di;
16534 24 : goto gather_gen;
16535 24 : case IX86_BUILTIN_GATHER3DIV16SI:
16536 24 : icode = CODE_FOR_avx512f_gatherdiv16si;
16537 24 : goto gather_gen;
16538 38 : case IX86_BUILTIN_GATHER3DIV8DI:
16539 38 : icode = CODE_FOR_avx512f_gatherdiv8di;
16540 38 : goto gather_gen;
16541 16 : case IX86_BUILTIN_GATHER3ALTSIV8DF:
16542 16 : icode = CODE_FOR_avx512f_gathersiv8df;
16543 16 : goto gather_gen;
16544 22 : case IX86_BUILTIN_GATHER3ALTDIV16SF:
16545 22 : icode = CODE_FOR_avx512f_gatherdiv16sf;
16546 22 : goto gather_gen;
16547 14 : case IX86_BUILTIN_GATHER3ALTSIV8DI:
16548 14 : icode = CODE_FOR_avx512f_gathersiv8di;
16549 14 : goto gather_gen;
16550 18 : case IX86_BUILTIN_GATHER3ALTDIV16SI:
16551 18 : icode = CODE_FOR_avx512f_gatherdiv16si;
16552 18 : goto gather_gen;
16553 18 : case IX86_BUILTIN_GATHER3SIV2DF:
16554 18 : icode = CODE_FOR_avx512vl_gathersiv2df;
16555 18 : goto gather_gen;
16556 10 : case IX86_BUILTIN_GATHER3SIV4DF:
16557 10 : icode = CODE_FOR_avx512vl_gathersiv4df;
16558 10 : goto gather_gen;
16559 15 : case IX86_BUILTIN_GATHER3DIV2DF:
16560 15 : icode = CODE_FOR_avx512vl_gatherdiv2df;
16561 15 : goto gather_gen;
16562 16 : case IX86_BUILTIN_GATHER3DIV4DF:
16563 16 : icode = CODE_FOR_avx512vl_gatherdiv4df;
16564 16 : goto gather_gen;
16565 14 : case IX86_BUILTIN_GATHER3SIV4SF:
16566 14 : icode = CODE_FOR_avx512vl_gathersiv4sf;
16567 14 : goto gather_gen;
16568 12 : case IX86_BUILTIN_GATHER3SIV8SF:
16569 12 : icode = CODE_FOR_avx512vl_gathersiv8sf;
16570 12 : goto gather_gen;
16571 22 : case IX86_BUILTIN_GATHER3DIV4SF:
16572 22 : icode = CODE_FOR_avx512vl_gatherdiv4sf;
16573 22 : goto gather_gen;
16574 10 : case IX86_BUILTIN_GATHER3DIV8SF:
16575 10 : icode = CODE_FOR_avx512vl_gatherdiv8sf;
16576 10 : goto gather_gen;
16577 20 : case IX86_BUILTIN_GATHER3SIV2DI:
16578 20 : icode = CODE_FOR_avx512vl_gathersiv2di;
16579 20 : goto gather_gen;
16580 10 : case IX86_BUILTIN_GATHER3SIV4DI:
16581 10 : icode = CODE_FOR_avx512vl_gathersiv4di;
16582 10 : goto gather_gen;
16583 15 : case IX86_BUILTIN_GATHER3DIV2DI:
16584 15 : icode = CODE_FOR_avx512vl_gatherdiv2di;
16585 15 : goto gather_gen;
16586 14 : case IX86_BUILTIN_GATHER3DIV4DI:
16587 14 : icode = CODE_FOR_avx512vl_gatherdiv4di;
16588 14 : goto gather_gen;
16589 14 : case IX86_BUILTIN_GATHER3SIV4SI:
16590 14 : icode = CODE_FOR_avx512vl_gathersiv4si;
16591 14 : goto gather_gen;
16592 12 : case IX86_BUILTIN_GATHER3SIV8SI:
16593 12 : icode = CODE_FOR_avx512vl_gathersiv8si;
16594 12 : goto gather_gen;
16595 24 : case IX86_BUILTIN_GATHER3DIV4SI:
16596 24 : icode = CODE_FOR_avx512vl_gatherdiv4si;
16597 24 : goto gather_gen;
16598 10 : case IX86_BUILTIN_GATHER3DIV8SI:
16599 10 : icode = CODE_FOR_avx512vl_gatherdiv8si;
16600 10 : goto gather_gen;
16601 4 : case IX86_BUILTIN_GATHER3ALTSIV4DF:
16602 4 : icode = CODE_FOR_avx512vl_gathersiv4df;
16603 4 : goto gather_gen;
16604 8 : case IX86_BUILTIN_GATHER3ALTDIV8SF:
16605 8 : icode = CODE_FOR_avx512vl_gatherdiv8sf;
16606 8 : goto gather_gen;
16607 6 : case IX86_BUILTIN_GATHER3ALTSIV4DI:
16608 6 : icode = CODE_FOR_avx512vl_gathersiv4di;
16609 6 : goto gather_gen;
16610 10 : case IX86_BUILTIN_GATHER3ALTDIV8SI:
16611 10 : icode = CODE_FOR_avx512vl_gatherdiv8si;
16612 10 : goto gather_gen;
16613 40 : case IX86_BUILTIN_SCATTERSIV16SF:
16614 40 : icode = CODE_FOR_avx512f_scattersiv16sf;
16615 40 : goto scatter_gen;
16616 27 : case IX86_BUILTIN_SCATTERSIV8DF:
16617 27 : icode = CODE_FOR_avx512f_scattersiv8df;
16618 27 : goto scatter_gen;
16619 24 : case IX86_BUILTIN_SCATTERDIV16SF:
16620 24 : icode = CODE_FOR_avx512f_scatterdiv16sf;
16621 24 : goto scatter_gen;
16622 33 : case IX86_BUILTIN_SCATTERDIV8DF:
16623 33 : icode = CODE_FOR_avx512f_scatterdiv8df;
16624 33 : goto scatter_gen;
16625 30 : case IX86_BUILTIN_SCATTERSIV16SI:
16626 30 : icode = CODE_FOR_avx512f_scattersiv16si;
16627 30 : goto scatter_gen;
16628 24 : case IX86_BUILTIN_SCATTERSIV8DI:
16629 24 : icode = CODE_FOR_avx512f_scattersiv8di;
16630 24 : goto scatter_gen;
16631 24 : case IX86_BUILTIN_SCATTERDIV16SI:
16632 24 : icode = CODE_FOR_avx512f_scatterdiv16si;
16633 24 : goto scatter_gen;
16634 29 : case IX86_BUILTIN_SCATTERDIV8DI:
16635 29 : icode = CODE_FOR_avx512f_scatterdiv8di;
16636 29 : goto scatter_gen;
16637 18 : case IX86_BUILTIN_SCATTERSIV8SF:
16638 18 : icode = CODE_FOR_avx512vl_scattersiv8sf;
16639 18 : goto scatter_gen;
16640 20 : case IX86_BUILTIN_SCATTERSIV4SF:
16641 20 : icode = CODE_FOR_avx512vl_scattersiv4sf;
16642 20 : goto scatter_gen;
16643 16 : case IX86_BUILTIN_SCATTERSIV4DF:
16644 16 : icode = CODE_FOR_avx512vl_scattersiv4df;
16645 16 : goto scatter_gen;
16646 16 : case IX86_BUILTIN_SCATTERSIV2DF:
16647 16 : icode = CODE_FOR_avx512vl_scattersiv2df;
16648 16 : goto scatter_gen;
16649 16 : case IX86_BUILTIN_SCATTERDIV8SF:
16650 16 : icode = CODE_FOR_avx512vl_scatterdiv8sf;
16651 16 : goto scatter_gen;
16652 16 : case IX86_BUILTIN_SCATTERDIV4SF:
16653 16 : icode = CODE_FOR_avx512vl_scatterdiv4sf;
16654 16 : goto scatter_gen;
16655 18 : case IX86_BUILTIN_SCATTERDIV4DF:
16656 18 : icode = CODE_FOR_avx512vl_scatterdiv4df;
16657 18 : goto scatter_gen;
16658 18 : case IX86_BUILTIN_SCATTERDIV2DF:
16659 18 : icode = CODE_FOR_avx512vl_scatterdiv2df;
16660 18 : goto scatter_gen;
16661 22 : case IX86_BUILTIN_SCATTERSIV8SI:
16662 22 : icode = CODE_FOR_avx512vl_scattersiv8si;
16663 22 : goto scatter_gen;
16664 24 : case IX86_BUILTIN_SCATTERSIV4SI:
16665 24 : icode = CODE_FOR_avx512vl_scattersiv4si;
16666 24 : goto scatter_gen;
16667 16 : case IX86_BUILTIN_SCATTERSIV4DI:
16668 16 : icode = CODE_FOR_avx512vl_scattersiv4di;
16669 16 : goto scatter_gen;
16670 16 : case IX86_BUILTIN_SCATTERSIV2DI:
16671 16 : icode = CODE_FOR_avx512vl_scattersiv2di;
16672 16 : goto scatter_gen;
16673 16 : case IX86_BUILTIN_SCATTERDIV8SI:
16674 16 : icode = CODE_FOR_avx512vl_scatterdiv8si;
16675 16 : goto scatter_gen;
16676 16 : case IX86_BUILTIN_SCATTERDIV4SI:
16677 16 : icode = CODE_FOR_avx512vl_scatterdiv4si;
16678 16 : goto scatter_gen;
16679 18 : case IX86_BUILTIN_SCATTERDIV4DI:
16680 18 : icode = CODE_FOR_avx512vl_scatterdiv4di;
16681 18 : goto scatter_gen;
16682 18 : case IX86_BUILTIN_SCATTERDIV2DI:
16683 18 : icode = CODE_FOR_avx512vl_scatterdiv2di;
16684 18 : goto scatter_gen;
16685 16 : case IX86_BUILTIN_SCATTERALTSIV8DF:
16686 16 : icode = CODE_FOR_avx512f_scattersiv8df;
16687 16 : goto scatter_gen;
16688 12 : case IX86_BUILTIN_SCATTERALTDIV16SF:
16689 12 : icode = CODE_FOR_avx512f_scatterdiv16sf;
16690 12 : goto scatter_gen;
16691 8 : case IX86_BUILTIN_SCATTERALTSIV8DI:
16692 8 : icode = CODE_FOR_avx512f_scattersiv8di;
16693 8 : goto scatter_gen;
16694 24 : case IX86_BUILTIN_SCATTERALTDIV16SI:
16695 24 : icode = CODE_FOR_avx512f_scatterdiv16si;
16696 24 : goto scatter_gen;
16697 4 : case IX86_BUILTIN_SCATTERALTSIV4DF:
16698 4 : icode = CODE_FOR_avx512vl_scattersiv4df;
16699 4 : goto scatter_gen;
16700 4 : case IX86_BUILTIN_SCATTERALTDIV8SF:
16701 4 : icode = CODE_FOR_avx512vl_scatterdiv8sf;
16702 4 : goto scatter_gen;
16703 4 : case IX86_BUILTIN_SCATTERALTSIV4DI:
16704 4 : icode = CODE_FOR_avx512vl_scattersiv4di;
16705 4 : goto scatter_gen;
16706 4 : case IX86_BUILTIN_SCATTERALTDIV8SI:
16707 4 : icode = CODE_FOR_avx512vl_scatterdiv8si;
16708 4 : goto scatter_gen;
16709 8 : case IX86_BUILTIN_SCATTERALTSIV2DF:
16710 8 : icode = CODE_FOR_avx512vl_scattersiv2df;
16711 8 : goto scatter_gen;
16712 8 : case IX86_BUILTIN_SCATTERALTDIV4SF:
16713 8 : icode = CODE_FOR_avx512vl_scatterdiv4sf;
16714 8 : goto scatter_gen;
16715 8 : case IX86_BUILTIN_SCATTERALTSIV2DI:
16716 8 : icode = CODE_FOR_avx512vl_scattersiv2di;
16717 8 : goto scatter_gen;
16718 8 : case IX86_BUILTIN_SCATTERALTDIV4SI:
16719 8 : icode = CODE_FOR_avx512vl_scatterdiv4si;
16720 8 : goto scatter_gen;
16721 :
16722 1007 : gather_gen:
16723 1007 : rtx half;
16724 1007 : rtx (*gen) (rtx, rtx);
16725 :
16726 1007 : arg0 = CALL_EXPR_ARG (exp, 0);
16727 1007 : arg1 = CALL_EXPR_ARG (exp, 1);
16728 1007 : arg2 = CALL_EXPR_ARG (exp, 2);
16729 1007 : arg3 = CALL_EXPR_ARG (exp, 3);
16730 1007 : arg4 = CALL_EXPR_ARG (exp, 4);
16731 1007 : op0 = expand_normal (arg0);
16732 1007 : op1 = expand_normal (arg1);
16733 1007 : op2 = expand_normal (arg2);
16734 1007 : op3 = ix86_expand_unsigned_small_int_cst_argument (arg3);
16735 1007 : op4 = expand_normal (arg4);
16736 : /* Note the arg order is different from the operand order. */
16737 1007 : mode0 = insn_data[icode].operand[1].mode;
16738 1007 : mode2 = insn_data[icode].operand[3].mode;
16739 1007 : mode3 = insn_data[icode].operand[4].mode;
16740 1007 : mode4 = insn_data[icode].operand[5].mode;
16741 :
16742 1007 : if (target == NULL_RTX
16743 1007 : || GET_MODE (target) != insn_data[icode].operand[0].mode
16744 1910 : || !insn_data[icode].operand[0].predicate (target,
16745 : GET_MODE (target)))
16746 105 : subtarget = gen_reg_rtx (insn_data[icode].operand[0].mode);
16747 : else
16748 : subtarget = target;
16749 :
16750 1007 : switch (fcode)
16751 : {
16752 30 : case IX86_BUILTIN_GATHER3ALTSIV8DF:
16753 30 : case IX86_BUILTIN_GATHER3ALTSIV8DI:
16754 30 : half = gen_reg_rtx (V8SImode);
16755 30 : if (!nonimmediate_operand (op2, V16SImode))
16756 0 : op2 = copy_to_mode_reg (V16SImode, op2);
16757 30 : emit_insn (gen_vec_extract_lo_v16si (half, op2));
16758 30 : op2 = half;
16759 30 : break;
16760 34 : case IX86_BUILTIN_GATHER3ALTSIV4DF:
16761 34 : case IX86_BUILTIN_GATHER3ALTSIV4DI:
16762 34 : case IX86_BUILTIN_GATHERALTSIV4DF:
16763 34 : case IX86_BUILTIN_GATHERALTSIV4DI:
16764 34 : half = gen_reg_rtx (V4SImode);
16765 34 : if (!nonimmediate_operand (op2, V8SImode))
16766 0 : op2 = copy_to_mode_reg (V8SImode, op2);
16767 34 : emit_insn (gen_vec_extract_lo_v8si (half, op2));
16768 34 : op2 = half;
16769 34 : break;
16770 40 : case IX86_BUILTIN_GATHER3ALTDIV16SF:
16771 40 : case IX86_BUILTIN_GATHER3ALTDIV16SI:
16772 40 : half = gen_reg_rtx (mode0);
16773 40 : if (mode0 == V8SFmode)
16774 : gen = gen_vec_extract_lo_v16sf;
16775 : else
16776 18 : gen = gen_vec_extract_lo_v16si;
16777 40 : if (!nonimmediate_operand (op0, GET_MODE (op0)))
16778 40 : op0 = copy_to_mode_reg (GET_MODE (op0), op0);
16779 40 : emit_insn (gen (half, op0));
16780 40 : op0 = half;
16781 40 : op3 = lowpart_subreg (QImode, op3, HImode);
16782 40 : break;
16783 46 : case IX86_BUILTIN_GATHER3ALTDIV8SF:
16784 46 : case IX86_BUILTIN_GATHER3ALTDIV8SI:
16785 46 : case IX86_BUILTIN_GATHERALTDIV8SF:
16786 46 : case IX86_BUILTIN_GATHERALTDIV8SI:
16787 46 : half = gen_reg_rtx (mode0);
16788 46 : if (mode0 == V4SFmode)
16789 : gen = gen_vec_extract_lo_v8sf;
16790 : else
16791 22 : gen = gen_vec_extract_lo_v8si;
16792 46 : if (!nonimmediate_operand (op0, GET_MODE (op0)))
16793 46 : op0 = copy_to_mode_reg (GET_MODE (op0), op0);
16794 46 : emit_insn (gen (half, op0));
16795 46 : op0 = half;
16796 46 : if (VECTOR_MODE_P (GET_MODE (op3)))
16797 : {
16798 28 : half = gen_reg_rtx (mode0);
16799 28 : if (!nonimmediate_operand (op3, GET_MODE (op3)))
16800 12 : op3 = copy_to_mode_reg (GET_MODE (op3), op3);
16801 28 : emit_insn (gen (half, op3));
16802 28 : op3 = half;
16803 : }
16804 : break;
16805 : default:
16806 : break;
16807 : }
16808 :
16809 : /* Force memory operand only with base register here. But we
16810 : don't want to do it on memory operand for other builtin
16811 : functions. */
16812 1007 : op1 = ix86_zero_extend_to_Pmode (op1);
16813 :
16814 1007 : if (!insn_data[icode].operand[1].predicate (op0, mode0))
16815 406 : op0 = copy_to_mode_reg (mode0, op0);
16816 1012 : if (!insn_data[icode].operand[2].predicate (op1, Pmode))
16817 0 : op1 = copy_to_mode_reg (Pmode, op1);
16818 1007 : if (!insn_data[icode].operand[3].predicate (op2, mode2))
16819 224 : op2 = copy_to_mode_reg (mode2, op2);
16820 :
16821 1007 : op3 = fixup_modeless_constant (op3, mode3);
16822 :
16823 1007 : if (GET_MODE (op3) == mode3 || GET_MODE (op3) == VOIDmode)
16824 : {
16825 1007 : if (!insn_data[icode].operand[4].predicate (op3, mode3))
16826 356 : op3 = copy_to_mode_reg (mode3, op3);
16827 : }
16828 : else
16829 : {
16830 0 : op3 = copy_to_reg (op3);
16831 0 : op3 = lowpart_subreg (mode3, op3, GET_MODE (op3));
16832 : }
16833 1007 : if (!insn_data[icode].operand[5].predicate (op4, mode4))
16834 : {
16835 0 : error ("the last argument must be scale 1, 2, 4, 8");
16836 0 : return const0_rtx;
16837 : }
16838 :
16839 : /* Optimize. If mask is known to have all high bits set,
16840 : replace op0 with pc_rtx to signal that the instruction
16841 : overwrites the whole destination and doesn't use its
16842 : previous contents. */
16843 1007 : if (optimize)
16844 : {
16845 917 : if (TREE_CODE (arg3) == INTEGER_CST)
16846 : {
16847 209 : if (integer_all_onesp (arg3))
16848 201 : op0 = pc_rtx;
16849 : }
16850 708 : else if (TREE_CODE (arg3) == VECTOR_CST)
16851 : {
16852 : unsigned int negative = 0;
16853 755 : for (i = 0; i < VECTOR_CST_NELTS (arg3); ++i)
16854 : {
16855 620 : tree cst = VECTOR_CST_ELT (arg3, i);
16856 620 : if (TREE_CODE (cst) == INTEGER_CST
16857 620 : && tree_int_cst_sign_bit (cst))
16858 286 : negative++;
16859 334 : else if (TREE_CODE (cst) == REAL_CST
16860 334 : && REAL_VALUE_NEGATIVE (TREE_REAL_CST (cst)))
16861 306 : negative++;
16862 : }
16863 135 : if (negative == TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg3)))
16864 121 : op0 = pc_rtx;
16865 : }
16866 573 : else if (TREE_CODE (arg3) == SSA_NAME
16867 573 : && VECTOR_TYPE_P (TREE_TYPE (arg3)))
16868 : {
16869 : /* Recognize also when mask is like:
16870 : __v2df src = _mm_setzero_pd ();
16871 : __v2df mask = _mm_cmpeq_pd (src, src);
16872 : or
16873 : __v8sf src = _mm256_setzero_ps ();
16874 : __v8sf mask = _mm256_cmp_ps (src, src, _CMP_EQ_OQ);
16875 : as that is a cheaper way to load all ones into
16876 : a register than having to load a constant from
16877 : memory. */
16878 259 : gimple *def_stmt = SSA_NAME_DEF_STMT (arg3);
16879 259 : if (is_gimple_call (def_stmt))
16880 : {
16881 76 : tree fndecl = gimple_call_fndecl (def_stmt);
16882 76 : if (fndecl
16883 76 : && fndecl_built_in_p (fndecl, BUILT_IN_MD))
16884 67 : switch (DECL_MD_FUNCTION_CODE (fndecl))
16885 : {
16886 24 : case IX86_BUILTIN_CMPPD:
16887 24 : case IX86_BUILTIN_CMPPS:
16888 24 : case IX86_BUILTIN_CMPPD256:
16889 24 : case IX86_BUILTIN_CMPPS256:
16890 24 : if (!integer_zerop (gimple_call_arg (def_stmt, 2)))
16891 : break;
16892 : /* FALLTHRU */
16893 49 : case IX86_BUILTIN_CMPEQPD:
16894 49 : case IX86_BUILTIN_CMPEQPS:
16895 49 : if (initializer_zerop (gimple_call_arg (def_stmt, 0))
16896 49 : && initializer_zerop (gimple_call_arg (def_stmt,
16897 : 1)))
16898 49 : op0 = pc_rtx;
16899 : break;
16900 : default:
16901 : break;
16902 : }
16903 : }
16904 : }
16905 : }
16906 :
16907 1007 : pat = GEN_FCN (icode) (subtarget, op0, op1, op2, op3, op4);
16908 1007 : if (! pat)
16909 0 : return const0_rtx;
16910 1007 : emit_insn (pat);
16911 :
16912 1007 : switch (fcode)
16913 : {
16914 24 : case IX86_BUILTIN_GATHER3DIV16SF:
16915 24 : if (target == NULL_RTX)
16916 0 : target = gen_reg_rtx (V8SFmode);
16917 24 : emit_insn (gen_vec_extract_lo_v16sf (target, subtarget));
16918 24 : break;
16919 24 : case IX86_BUILTIN_GATHER3DIV16SI:
16920 24 : if (target == NULL_RTX)
16921 0 : target = gen_reg_rtx (V8SImode);
16922 24 : emit_insn (gen_vec_extract_lo_v16si (target, subtarget));
16923 24 : break;
16924 28 : case IX86_BUILTIN_GATHER3DIV8SF:
16925 28 : case IX86_BUILTIN_GATHERDIV8SF:
16926 28 : if (target == NULL_RTX)
16927 0 : target = gen_reg_rtx (V4SFmode);
16928 28 : emit_insn (gen_vec_extract_lo_v8sf (target, subtarget));
16929 28 : break;
16930 28 : case IX86_BUILTIN_GATHER3DIV8SI:
16931 28 : case IX86_BUILTIN_GATHERDIV8SI:
16932 28 : if (target == NULL_RTX)
16933 0 : target = gen_reg_rtx (V4SImode);
16934 28 : emit_insn (gen_vec_extract_lo_v8si (target, subtarget));
16935 28 : break;
16936 : default:
16937 : target = subtarget;
16938 : break;
16939 : }
16940 : return target;
16941 :
16942 623 : scatter_gen:
16943 623 : arg0 = CALL_EXPR_ARG (exp, 0);
16944 623 : arg1 = CALL_EXPR_ARG (exp, 1);
16945 623 : arg2 = CALL_EXPR_ARG (exp, 2);
16946 623 : arg3 = CALL_EXPR_ARG (exp, 3);
16947 623 : arg4 = CALL_EXPR_ARG (exp, 4);
16948 623 : op0 = expand_normal (arg0);
16949 623 : op1 = ix86_expand_unsigned_small_int_cst_argument (arg1);
16950 623 : op2 = expand_normal (arg2);
16951 623 : op3 = expand_normal (arg3);
16952 623 : op4 = expand_normal (arg4);
16953 623 : mode1 = insn_data[icode].operand[1].mode;
16954 623 : mode2 = insn_data[icode].operand[2].mode;
16955 623 : mode3 = insn_data[icode].operand[3].mode;
16956 623 : mode4 = insn_data[icode].operand[4].mode;
16957 :
16958 : /* Scatter instruction stores operand op3 to memory with
16959 : indices from op2 and scale from op4 under writemask op1.
16960 : If index operand op2 has more elements then source operand
16961 : op3 one need to use only its low half. And vice versa. */
16962 623 : switch (fcode)
16963 : {
16964 24 : case IX86_BUILTIN_SCATTERALTSIV8DF:
16965 24 : case IX86_BUILTIN_SCATTERALTSIV8DI:
16966 24 : half = gen_reg_rtx (V8SImode);
16967 24 : if (!nonimmediate_operand (op2, V16SImode))
16968 0 : op2 = copy_to_mode_reg (V16SImode, op2);
16969 24 : emit_insn (gen_vec_extract_lo_v16si (half, op2));
16970 24 : op2 = half;
16971 24 : break;
16972 36 : case IX86_BUILTIN_SCATTERALTDIV16SF:
16973 36 : case IX86_BUILTIN_SCATTERALTDIV16SI:
16974 36 : half = gen_reg_rtx (mode3);
16975 36 : if (mode3 == V8SFmode)
16976 : gen = gen_vec_extract_lo_v16sf;
16977 : else
16978 24 : gen = gen_vec_extract_lo_v16si;
16979 36 : if (!nonimmediate_operand (op3, GET_MODE (op3)))
16980 0 : op3 = copy_to_mode_reg (GET_MODE (op3), op3);
16981 36 : emit_insn (gen (half, op3));
16982 36 : op3 = half;
16983 36 : break;
16984 8 : case IX86_BUILTIN_SCATTERALTSIV4DF:
16985 8 : case IX86_BUILTIN_SCATTERALTSIV4DI:
16986 8 : half = gen_reg_rtx (V4SImode);
16987 8 : if (!nonimmediate_operand (op2, V8SImode))
16988 0 : op2 = copy_to_mode_reg (V8SImode, op2);
16989 8 : emit_insn (gen_vec_extract_lo_v8si (half, op2));
16990 8 : op2 = half;
16991 8 : break;
16992 8 : case IX86_BUILTIN_SCATTERALTDIV8SF:
16993 8 : case IX86_BUILTIN_SCATTERALTDIV8SI:
16994 8 : half = gen_reg_rtx (mode3);
16995 8 : if (mode3 == V4SFmode)
16996 : gen = gen_vec_extract_lo_v8sf;
16997 : else
16998 4 : gen = gen_vec_extract_lo_v8si;
16999 8 : if (!nonimmediate_operand (op3, GET_MODE (op3)))
17000 0 : op3 = copy_to_mode_reg (GET_MODE (op3), op3);
17001 8 : emit_insn (gen (half, op3));
17002 8 : op3 = half;
17003 8 : break;
17004 16 : case IX86_BUILTIN_SCATTERALTSIV2DF:
17005 16 : case IX86_BUILTIN_SCATTERALTSIV2DI:
17006 16 : if (!nonimmediate_operand (op2, V4SImode))
17007 0 : op2 = copy_to_mode_reg (V4SImode, op2);
17008 : break;
17009 16 : case IX86_BUILTIN_SCATTERALTDIV4SF:
17010 16 : case IX86_BUILTIN_SCATTERALTDIV4SI:
17011 16 : if (!nonimmediate_operand (op3, GET_MODE (op3)))
17012 0 : op3 = copy_to_mode_reg (GET_MODE (op3), op3);
17013 : break;
17014 : default:
17015 : break;
17016 : }
17017 :
17018 : /* Force memory operand only with base register here. But we
17019 : don't want to do it on memory operand for other builtin
17020 : functions. */
17021 633 : op0 = force_reg (Pmode, convert_to_mode (Pmode, op0, 1));
17022 :
17023 628 : if (!insn_data[icode].operand[0].predicate (op0, Pmode))
17024 0 : op0 = copy_to_mode_reg (Pmode, op0);
17025 :
17026 623 : op1 = fixup_modeless_constant (op1, mode1);
17027 :
17028 623 : if (GET_MODE (op1) == mode1 || GET_MODE (op1) == VOIDmode)
17029 : {
17030 607 : if (!insn_data[icode].operand[1].predicate (op1, mode1))
17031 273 : op1 = copy_to_mode_reg (mode1, op1);
17032 : }
17033 : else
17034 : {
17035 16 : op1 = copy_to_reg (op1);
17036 16 : op1 = lowpart_subreg (mode1, op1, GET_MODE (op1));
17037 : }
17038 :
17039 623 : if (!insn_data[icode].operand[2].predicate (op2, mode2))
17040 57 : op2 = copy_to_mode_reg (mode2, op2);
17041 :
17042 623 : if (!insn_data[icode].operand[3].predicate (op3, mode3))
17043 82 : op3 = copy_to_mode_reg (mode3, op3);
17044 :
17045 623 : if (!insn_data[icode].operand[4].predicate (op4, mode4))
17046 : {
17047 0 : error ("the last argument must be scale 1, 2, 4, 8");
17048 0 : return const0_rtx;
17049 : }
17050 :
17051 623 : pat = GEN_FCN (icode) (op0, op1, op2, op3, op4);
17052 623 : if (! pat)
17053 0 : return const0_rtx;
17054 :
17055 623 : emit_insn (pat);
17056 623 : return 0;
17057 :
17058 23 : case IX86_BUILTIN_XABORT:
17059 23 : icode = CODE_FOR_xabort;
17060 23 : arg0 = CALL_EXPR_ARG (exp, 0);
17061 23 : op0 = expand_normal (arg0);
17062 23 : mode0 = insn_data[icode].operand[0].mode;
17063 23 : if (!insn_data[icode].operand[0].predicate (op0, mode0))
17064 : {
17065 0 : error ("the argument to %<xabort%> intrinsic must "
17066 : "be an 8-bit immediate");
17067 0 : return const0_rtx;
17068 : }
17069 23 : emit_insn (gen_xabort (op0));
17070 23 : return 0;
17071 :
17072 55 : case IX86_BUILTIN_RDSSPD:
17073 55 : case IX86_BUILTIN_RDSSPQ:
17074 55 : mode = (fcode == IX86_BUILTIN_RDSSPD ? SImode : DImode);
17075 :
17076 55 : if (target == 0
17077 55 : || !register_operand (target, mode))
17078 0 : target = gen_reg_rtx (mode);
17079 :
17080 55 : op0 = force_reg (mode, const0_rtx);
17081 :
17082 55 : emit_insn (gen_rdssp (mode, target, op0));
17083 55 : return target;
17084 :
17085 55 : case IX86_BUILTIN_INCSSPD:
17086 55 : case IX86_BUILTIN_INCSSPQ:
17087 55 : mode = (fcode == IX86_BUILTIN_INCSSPD ? SImode : DImode);
17088 :
17089 55 : arg0 = CALL_EXPR_ARG (exp, 0);
17090 55 : op0 = expand_normal (arg0);
17091 :
17092 55 : op0 = force_reg (mode, op0);
17093 :
17094 55 : emit_insn (gen_incssp (mode, op0));
17095 55 : return 0;
17096 :
17097 20 : case IX86_BUILTIN_HRESET:
17098 20 : icode = CODE_FOR_hreset;
17099 20 : arg0 = CALL_EXPR_ARG (exp, 0);
17100 20 : op0 = expand_normal (arg0);
17101 20 : op0 = force_reg (SImode, op0);
17102 20 : emit_insn (gen_hreset (op0));
17103 20 : return 0;
17104 :
17105 38 : case IX86_BUILTIN_RSTORSSP:
17106 38 : case IX86_BUILTIN_CLRSSBSY:
17107 38 : arg0 = CALL_EXPR_ARG (exp, 0);
17108 38 : op0 = expand_normal (arg0);
17109 19 : icode = (fcode == IX86_BUILTIN_RSTORSSP
17110 38 : ? CODE_FOR_rstorssp
17111 : : CODE_FOR_clrssbsy);
17112 :
17113 38 : if (!address_operand (op0, VOIDmode))
17114 : {
17115 18 : op0 = convert_memory_address (Pmode, op0);
17116 18 : op0 = copy_addr_to_reg (op0);
17117 : }
17118 38 : emit_insn (GEN_FCN (icode) (gen_rtx_MEM (DImode, op0)));
17119 38 : return 0;
17120 :
17121 80 : case IX86_BUILTIN_WRSSD:
17122 80 : case IX86_BUILTIN_WRSSQ:
17123 80 : case IX86_BUILTIN_WRUSSD:
17124 80 : case IX86_BUILTIN_WRUSSQ:
17125 80 : mode = ((fcode == IX86_BUILTIN_WRSSD
17126 80 : || fcode == IX86_BUILTIN_WRUSSD)
17127 80 : ? SImode : DImode);
17128 :
17129 80 : arg0 = CALL_EXPR_ARG (exp, 0);
17130 80 : op0 = expand_normal (arg0);
17131 80 : arg1 = CALL_EXPR_ARG (exp, 1);
17132 80 : op1 = expand_normal (arg1);
17133 :
17134 80 : op0 = force_reg (mode, op0);
17135 :
17136 80 : if (!address_operand (op1, VOIDmode))
17137 : {
17138 36 : op1 = convert_memory_address (Pmode, op1);
17139 36 : op1 = copy_addr_to_reg (op1);
17140 : }
17141 80 : op1 = gen_rtx_MEM (mode, op1);
17142 :
17143 80 : icode = ((fcode == IX86_BUILTIN_WRSSD
17144 80 : || fcode == IX86_BUILTIN_WRSSQ)
17145 80 : ? code_for_wrss (mode)
17146 40 : : code_for_wruss (mode));
17147 80 : emit_insn (GEN_FCN (icode) (op0, op1));
17148 :
17149 80 : return 0;
17150 :
17151 118403 : default:
17152 118403 : break;
17153 : }
17154 :
17155 118403 : if (fcode >= IX86_BUILTIN__BDESC_SPECIAL_ARGS_FIRST
17156 118403 : && fcode <= IX86_BUILTIN__BDESC_SPECIAL_ARGS_LAST)
17157 : {
17158 26971 : i = fcode - IX86_BUILTIN__BDESC_SPECIAL_ARGS_FIRST;
17159 26971 : return ix86_expand_special_args_builtin (bdesc_special_args + i, exp,
17160 26971 : target);
17161 : }
17162 :
17163 91432 : if (fcode >= IX86_BUILTIN__BDESC_PURE_ARGS_FIRST
17164 91432 : && fcode <= IX86_BUILTIN__BDESC_PURE_ARGS_LAST)
17165 : {
17166 93 : i = fcode - IX86_BUILTIN__BDESC_PURE_ARGS_FIRST;
17167 93 : return ix86_expand_special_args_builtin (bdesc_pure_args + i, exp,
17168 93 : target);
17169 : }
17170 :
17171 91339 : if (fcode >= IX86_BUILTIN__BDESC_ARGS_FIRST
17172 91339 : && fcode <= IX86_BUILTIN__BDESC_ARGS_LAST)
17173 : {
17174 72986 : i = fcode - IX86_BUILTIN__BDESC_ARGS_FIRST;
17175 :
17176 72986 : switch (fcode)
17177 : {
17178 0 : case IX86_BUILTIN_RDPID:
17179 0 : return ix86_expand_special_args_builtin (bdesc_args + i, exp,
17180 0 : target);
17181 74 : case IX86_BUILTIN_VCOMISBF16EQ:
17182 74 : case IX86_BUILTIN_VCOMISBF16NE:
17183 74 : case IX86_BUILTIN_VCOMISBF16GT:
17184 74 : case IX86_BUILTIN_VCOMISBF16GE:
17185 74 : case IX86_BUILTIN_VCOMISBF16LT:
17186 74 : case IX86_BUILTIN_VCOMISBF16LE:
17187 74 : return ix86_expand_sse_comi (bdesc_args + i, exp, target, false);
17188 15 : case IX86_BUILTIN_FABSQ:
17189 15 : case IX86_BUILTIN_COPYSIGNQ:
17190 15 : if (!TARGET_SSE)
17191 : /* Emit a normal call if SSE isn't available. */
17192 0 : return expand_call (exp, target, ignore);
17193 : /* FALLTHRU */
17194 72912 : default:
17195 72912 : return ix86_expand_args_builtin (bdesc_args + i, exp, target);
17196 : }
17197 : }
17198 :
17199 18353 : if (fcode >= IX86_BUILTIN__BDESC_COMI_FIRST
17200 18353 : && fcode <= IX86_BUILTIN__BDESC_COMI_LAST)
17201 : {
17202 473 : i = fcode - IX86_BUILTIN__BDESC_COMI_FIRST;
17203 473 : return ix86_expand_sse_comi (bdesc_comi + i, exp, target, true);
17204 : }
17205 :
17206 17880 : if (fcode >= IX86_BUILTIN__BDESC_ROUND_ARGS_FIRST
17207 17880 : && fcode <= IX86_BUILTIN__BDESC_ROUND_ARGS_LAST)
17208 : {
17209 15538 : i = fcode - IX86_BUILTIN__BDESC_ROUND_ARGS_FIRST;
17210 15538 : return ix86_expand_round_builtin (bdesc_round_args + i, exp, target);
17211 : }
17212 :
17213 2342 : if (fcode >= IX86_BUILTIN__BDESC_PCMPESTR_FIRST
17214 2342 : && fcode <= IX86_BUILTIN__BDESC_PCMPESTR_LAST)
17215 : {
17216 216 : i = fcode - IX86_BUILTIN__BDESC_PCMPESTR_FIRST;
17217 216 : return ix86_expand_sse_pcmpestr (bdesc_pcmpestr + i, exp, target);
17218 : }
17219 :
17220 2126 : if (fcode >= IX86_BUILTIN__BDESC_PCMPISTR_FIRST
17221 2126 : && fcode <= IX86_BUILTIN__BDESC_PCMPISTR_LAST)
17222 : {
17223 275 : i = fcode - IX86_BUILTIN__BDESC_PCMPISTR_FIRST;
17224 275 : return ix86_expand_sse_pcmpistr (bdesc_pcmpistr + i, exp, target);
17225 : }
17226 :
17227 1851 : if (fcode >= IX86_BUILTIN__BDESC_MULTI_ARG_FIRST
17228 1851 : && fcode <= IX86_BUILTIN__BDESC_MULTI_ARG_LAST)
17229 : {
17230 1813 : i = fcode - IX86_BUILTIN__BDESC_MULTI_ARG_FIRST;
17231 1813 : const struct builtin_description *d = bdesc_multi_arg + i;
17232 1813 : return ix86_expand_multi_arg_builtin (d->icode, exp, target,
17233 : (enum ix86_builtin_func_type)
17234 1813 : d->flag, d->comparison);
17235 : }
17236 :
17237 38 : if (fcode >= IX86_BUILTIN__BDESC_CET_FIRST
17238 38 : && fcode <= IX86_BUILTIN__BDESC_CET_LAST)
17239 : {
17240 38 : i = fcode - IX86_BUILTIN__BDESC_CET_FIRST;
17241 38 : return ix86_expand_special_args_builtin (bdesc_cet + i, exp,
17242 38 : target);
17243 : }
17244 :
17245 0 : gcc_unreachable ();
17246 : }
17247 :
17248 : /* See below where shifts are handled for explanation of this enum. */
17249 : enum ix86_vec_bcast_alg
17250 : {
17251 : VEC_BCAST_PXOR,
17252 : VEC_BCAST_PCMPEQ,
17253 : VEC_BCAST_PABSB,
17254 : VEC_BCAST_PADDB,
17255 : VEC_BCAST_PSRLW,
17256 : VEC_BCAST_PSRLD,
17257 : VEC_BCAST_PSLLW,
17258 : VEC_BCAST_PSLLD
17259 : };
17260 :
17261 : struct ix86_vec_bcast_map_simode_t
17262 : {
17263 : unsigned int key;
17264 : enum ix86_vec_bcast_alg alg;
17265 : unsigned int arg;
17266 : };
17267 :
17268 : /* This table must be kept sorted as values are looked-up using bsearch. */
17269 : static const ix86_vec_bcast_map_simode_t ix86_vec_bcast_map_simode[] = {
17270 : { 0x00000000, VEC_BCAST_PXOR, 0 },
17271 : { 0x00000001, VEC_BCAST_PSRLD, 31 },
17272 : { 0x00000003, VEC_BCAST_PSRLD, 30 },
17273 : { 0x00000007, VEC_BCAST_PSRLD, 29 },
17274 : { 0x0000000f, VEC_BCAST_PSRLD, 28 },
17275 : { 0x0000001f, VEC_BCAST_PSRLD, 27 },
17276 : { 0x0000003f, VEC_BCAST_PSRLD, 26 },
17277 : { 0x0000007f, VEC_BCAST_PSRLD, 25 },
17278 : { 0x000000ff, VEC_BCAST_PSRLD, 24 },
17279 : { 0x000001ff, VEC_BCAST_PSRLD, 23 },
17280 : { 0x000003ff, VEC_BCAST_PSRLD, 22 },
17281 : { 0x000007ff, VEC_BCAST_PSRLD, 21 },
17282 : { 0x00000fff, VEC_BCAST_PSRLD, 20 },
17283 : { 0x00001fff, VEC_BCAST_PSRLD, 19 },
17284 : { 0x00003fff, VEC_BCAST_PSRLD, 18 },
17285 : { 0x00007fff, VEC_BCAST_PSRLD, 17 },
17286 : { 0x0000ffff, VEC_BCAST_PSRLD, 16 },
17287 : { 0x00010001, VEC_BCAST_PSRLW, 15 },
17288 : { 0x0001ffff, VEC_BCAST_PSRLD, 15 },
17289 : { 0x00030003, VEC_BCAST_PSRLW, 14 },
17290 : { 0x0003ffff, VEC_BCAST_PSRLD, 14 },
17291 : { 0x00070007, VEC_BCAST_PSRLW, 13 },
17292 : { 0x0007ffff, VEC_BCAST_PSRLD, 13 },
17293 : { 0x000f000f, VEC_BCAST_PSRLW, 12 },
17294 : { 0x000fffff, VEC_BCAST_PSRLD, 12 },
17295 : { 0x001f001f, VEC_BCAST_PSRLW, 11 },
17296 : { 0x001fffff, VEC_BCAST_PSRLD, 11 },
17297 : { 0x003f003f, VEC_BCAST_PSRLW, 10 },
17298 : { 0x003fffff, VEC_BCAST_PSRLD, 10 },
17299 : { 0x007f007f, VEC_BCAST_PSRLW, 9 },
17300 : { 0x007fffff, VEC_BCAST_PSRLD, 9 },
17301 : { 0x00ff00ff, VEC_BCAST_PSRLW, 8 },
17302 : { 0x00ffffff, VEC_BCAST_PSRLD, 8 },
17303 : { 0x01010101, VEC_BCAST_PABSB, 0 },
17304 : { 0x01ff01ff, VEC_BCAST_PSRLW, 7 },
17305 : { 0x01ffffff, VEC_BCAST_PSRLD, 7 },
17306 : { 0x03ff03ff, VEC_BCAST_PSRLW, 6 },
17307 : { 0x03ffffff, VEC_BCAST_PSRLD, 6 },
17308 : { 0x07ff07ff, VEC_BCAST_PSRLW, 5 },
17309 : { 0x07ffffff, VEC_BCAST_PSRLD, 5 },
17310 : { 0x0fff0fff, VEC_BCAST_PSRLW, 4 },
17311 : { 0x0fffffff, VEC_BCAST_PSRLD, 4 },
17312 : { 0x1fff1fff, VEC_BCAST_PSRLW, 3 },
17313 : { 0x1fffffff, VEC_BCAST_PSRLD, 3 },
17314 : { 0x3fff3fff, VEC_BCAST_PSRLW, 2 },
17315 : { 0x3fffffff, VEC_BCAST_PSRLD, 2 },
17316 : { 0x7fff7fff, VEC_BCAST_PSRLW, 1 },
17317 : { 0x7fffffff, VEC_BCAST_PSRLD, 1 },
17318 : { 0x80000000, VEC_BCAST_PSLLD, 31 },
17319 : { 0x80008000, VEC_BCAST_PSLLW, 15 },
17320 : { 0xc0000000, VEC_BCAST_PSLLD, 30 },
17321 : { 0xc000c000, VEC_BCAST_PSLLW, 14 },
17322 : { 0xe0000000, VEC_BCAST_PSLLD, 29 },
17323 : { 0xe000e000, VEC_BCAST_PSLLW, 13 },
17324 : { 0xf0000000, VEC_BCAST_PSLLD, 28 },
17325 : { 0xf000f000, VEC_BCAST_PSLLW, 12 },
17326 : { 0xf8000000, VEC_BCAST_PSLLD, 27 },
17327 : { 0xf800f800, VEC_BCAST_PSLLW, 11 },
17328 : { 0xfc000000, VEC_BCAST_PSLLD, 26 },
17329 : { 0xfc00fc00, VEC_BCAST_PSLLW, 10 },
17330 : { 0xfe000000, VEC_BCAST_PSLLD, 25 },
17331 : { 0xfe00fe00, VEC_BCAST_PSLLW, 9 },
17332 : { 0xfefefefe, VEC_BCAST_PADDB, 0 },
17333 : { 0xff000000, VEC_BCAST_PSLLD, 24 },
17334 : { 0xff00ff00, VEC_BCAST_PSLLW, 8 },
17335 : { 0xff800000, VEC_BCAST_PSLLD, 23 },
17336 : { 0xff80ff80, VEC_BCAST_PSLLW, 7 },
17337 : { 0xffc00000, VEC_BCAST_PSLLD, 22 },
17338 : { 0xffc0ffc0, VEC_BCAST_PSLLW, 6 },
17339 : { 0xffe00000, VEC_BCAST_PSLLD, 21 },
17340 : { 0xffe0ffe0, VEC_BCAST_PSLLW, 5 },
17341 : { 0xfff00000, VEC_BCAST_PSLLD, 20 },
17342 : { 0xfff0fff0, VEC_BCAST_PSLLW, 4 },
17343 : { 0xfff80000, VEC_BCAST_PSLLD, 19 },
17344 : { 0xfff8fff8, VEC_BCAST_PSLLW, 3 },
17345 : { 0xfffc0000, VEC_BCAST_PSLLD, 18 },
17346 : { 0xfffcfffc, VEC_BCAST_PSLLW, 2 },
17347 : { 0xfffe0000, VEC_BCAST_PSLLD, 17 },
17348 : { 0xfffefffe, VEC_BCAST_PSLLW, 1 },
17349 : { 0xffff0000, VEC_BCAST_PSLLD, 16 },
17350 : { 0xffff8000, VEC_BCAST_PSLLD, 15 },
17351 : { 0xffffc000, VEC_BCAST_PSLLD, 14 },
17352 : { 0xffffe000, VEC_BCAST_PSLLD, 13 },
17353 : { 0xfffff000, VEC_BCAST_PSLLD, 12 },
17354 : { 0xfffff800, VEC_BCAST_PSLLD, 11 },
17355 : { 0xfffffc00, VEC_BCAST_PSLLD, 10 },
17356 : { 0xfffffe00, VEC_BCAST_PSLLD, 9 },
17357 : { 0xffffff00, VEC_BCAST_PSLLD, 8 },
17358 : { 0xffffff80, VEC_BCAST_PSLLD, 7 },
17359 : { 0xffffffc0, VEC_BCAST_PSLLD, 6 },
17360 : { 0xffffffe0, VEC_BCAST_PSLLD, 5 },
17361 : { 0xfffffff0, VEC_BCAST_PSLLD, 4 },
17362 : { 0xfffffff8, VEC_BCAST_PSLLD, 3 },
17363 : { 0xfffffffc, VEC_BCAST_PSLLD, 2 },
17364 : { 0xfffffffe, VEC_BCAST_PSLLD, 1 },
17365 : { 0xffffffff, VEC_BCAST_PCMPEQ, 0 }
17366 : };
17367 :
17368 : /* Comparator for bsearch on ix86_vec_bcast_map. */
17369 : static int
17370 343338 : ix86_vec_bcast_map_simode_cmp (const void *key, const void *entry)
17371 : {
17372 343338 : return (*(const unsigned int*)key)
17373 343338 : - ((const ix86_vec_bcast_map_simode_t*)entry)->key;
17374 : }
17375 :
17376 : /* A subroutine of ix86_vector_duplicate_value. Tries to efficiently
17377 : materialize V4SImode, V8SImode and V16SImode vectors from SImode
17378 : integer constants. */
17379 : static bool
17380 51973 : ix86_vector_duplicate_simode_const (machine_mode mode, rtx target,
17381 : unsigned int val)
17382 : {
17383 51973 : const ix86_vec_bcast_map_simode_t *entry;
17384 51973 : rtx tmp1, tmp2;
17385 :
17386 51973 : entry = (const ix86_vec_bcast_map_simode_t*)
17387 51973 : bsearch(&val, ix86_vec_bcast_map_simode,
17388 : ARRAY_SIZE (ix86_vec_bcast_map_simode),
17389 : sizeof (ix86_vec_bcast_map_simode_t),
17390 : ix86_vec_bcast_map_simode_cmp);
17391 51973 : if (!entry)
17392 : return false;
17393 :
17394 19531 : switch (entry->alg)
17395 : {
17396 2584 : case VEC_BCAST_PXOR:
17397 2584 : if ((mode == V8SImode && !TARGET_AVX2)
17398 2584 : || (mode == V16SImode && !TARGET_AVX512F))
17399 : return false;
17400 2584 : emit_move_insn (target, CONST0_RTX (mode));
17401 2584 : return true;
17402 :
17403 299 : case VEC_BCAST_PCMPEQ:
17404 299 : if ((mode == V4SImode && !TARGET_SSE2)
17405 298 : || (mode == V8SImode && !TARGET_AVX2)
17406 271 : || (mode == V16SImode && !TARGET_AVX512F))
17407 : return false;
17408 271 : emit_move_insn (target, CONSTM1_RTX (mode));
17409 271 : return true;
17410 :
17411 616 : case VEC_BCAST_PABSB:
17412 616 : if (mode == V4SImode && TARGET_SSE2)
17413 : {
17414 491 : tmp1 = gen_reg_rtx (V16QImode);
17415 491 : emit_move_insn (tmp1, CONSTM1_RTX (V16QImode));
17416 491 : tmp2 = gen_reg_rtx (V16QImode);
17417 491 : emit_insn (gen_absv16qi2 (tmp2, tmp1));
17418 : }
17419 125 : else if (mode == V8SImode && TARGET_AVX2)
17420 : {
17421 68 : tmp1 = gen_reg_rtx (V32QImode);
17422 68 : emit_move_insn (tmp1, CONSTM1_RTX (V32QImode));
17423 68 : tmp2 = gen_reg_rtx (V32QImode);
17424 68 : emit_insn (gen_absv32qi2 (tmp2, tmp1));
17425 : }
17426 57 : else if (mode == V16SImode && TARGET_AVX512BW)
17427 : {
17428 49 : tmp1 = gen_reg_rtx (V64QImode);
17429 49 : emit_move_insn (tmp1, CONSTM1_RTX (V64QImode));
17430 49 : tmp2 = gen_reg_rtx (V64QImode);
17431 49 : emit_insn (gen_absv64qi2 (tmp2, tmp1));
17432 : }
17433 : else
17434 : return false;
17435 : break;
17436 :
17437 103 : case VEC_BCAST_PADDB:
17438 103 : if (mode == V4SImode && TARGET_SSE2)
17439 : {
17440 99 : tmp1 = gen_reg_rtx (V16QImode);
17441 99 : emit_move_insn (tmp1, CONSTM1_RTX (V16QImode));
17442 99 : tmp2 = gen_reg_rtx (V16QImode);
17443 99 : emit_insn (gen_addv16qi3 (tmp2, tmp1, tmp1));
17444 : }
17445 4 : else if (mode == V8SImode && TARGET_AVX2)
17446 : {
17447 1 : tmp1 = gen_reg_rtx (V32QImode);
17448 1 : emit_move_insn (tmp1, CONSTM1_RTX (V32QImode));
17449 1 : tmp2 = gen_reg_rtx (V32QImode);
17450 1 : emit_insn (gen_addv32qi3 (tmp2, tmp1, tmp1));
17451 : }
17452 3 : else if (mode == V16SImode && TARGET_AVX512BW)
17453 : {
17454 3 : tmp1 = gen_reg_rtx (V64QImode);
17455 3 : emit_move_insn (tmp1, CONSTM1_RTX (V64QImode));
17456 3 : tmp2 = gen_reg_rtx (V64QImode);
17457 3 : emit_insn (gen_addv64qi3 (tmp2, tmp1, tmp1));
17458 : }
17459 : else
17460 : return false;
17461 : break;
17462 :
17463 3764 : case VEC_BCAST_PSRLW:
17464 3764 : if (mode == V4SImode && TARGET_SSE2)
17465 : {
17466 3540 : tmp1 = gen_reg_rtx (V8HImode);
17467 3540 : emit_move_insn (tmp1, CONSTM1_RTX (V8HImode));
17468 3540 : tmp2 = gen_reg_rtx (V8HImode);
17469 3540 : emit_insn (gen_lshrv8hi3 (tmp2, tmp1, GEN_INT (entry->arg)));
17470 : }
17471 224 : else if (mode == V8SImode && TARGET_AVX2)
17472 : {
17473 131 : tmp1 = gen_reg_rtx (V16HImode);
17474 131 : emit_move_insn (tmp1, CONSTM1_RTX (V16HImode));
17475 131 : tmp2 = gen_reg_rtx (V16HImode);
17476 131 : emit_insn (gen_lshrv16hi3 (tmp2, tmp1, GEN_INT (entry->arg)));
17477 : }
17478 93 : else if (mode == V16SImode && TARGET_AVX512BW)
17479 : {
17480 90 : tmp1 = gen_reg_rtx (V32HImode);
17481 90 : emit_move_insn (tmp1, CONSTM1_RTX (V32HImode));
17482 90 : tmp2 = gen_reg_rtx (V32HImode);
17483 90 : emit_insn (gen_lshrv32hi3 (tmp2, tmp1, GEN_INT (entry->arg)));
17484 : }
17485 : else
17486 : return false;
17487 : break;
17488 :
17489 10287 : case VEC_BCAST_PSRLD:
17490 10287 : if (mode == V4SImode && TARGET_SSE2)
17491 : {
17492 7441 : tmp1 = gen_reg_rtx (V4SImode);
17493 7441 : emit_move_insn (tmp1, CONSTM1_RTX (V4SImode));
17494 7441 : emit_insn (gen_lshrv4si3 (target, tmp1, GEN_INT (entry->arg)));
17495 7441 : return true;
17496 : }
17497 2846 : else if (mode == V8SImode && TARGET_AVX2)
17498 : {
17499 1055 : tmp1 = gen_reg_rtx (V8SImode);
17500 1055 : emit_move_insn (tmp1, CONSTM1_RTX (V8SImode));
17501 1055 : emit_insn (gen_lshrv8si3 (target, tmp1, GEN_INT (entry->arg)));
17502 1055 : return true;
17503 : }
17504 1791 : else if (mode == V16SImode && TARGET_AVX512F)
17505 : {
17506 952 : tmp1 = gen_reg_rtx (V16SImode);
17507 952 : emit_move_insn (tmp1, CONSTM1_RTX (V16SImode));
17508 952 : emit_insn (gen_lshrv16si3 (target, tmp1, GEN_INT (entry->arg)));
17509 952 : return true;
17510 : }
17511 : else
17512 : return false;
17513 134 : break;
17514 :
17515 134 : case VEC_BCAST_PSLLW:
17516 134 : if (mode == V4SImode && TARGET_SSE2)
17517 : {
17518 104 : tmp1 = gen_reg_rtx (V8HImode);
17519 104 : emit_move_insn (tmp1, CONSTM1_RTX (V8HImode));
17520 104 : tmp2 = gen_reg_rtx (V8HImode);
17521 104 : emit_insn (gen_ashlv8hi3 (tmp2, tmp1, GEN_INT (entry->arg)));
17522 : }
17523 30 : else if (mode == V8SImode && TARGET_AVX2)
17524 : {
17525 21 : tmp1 = gen_reg_rtx (V16HImode);
17526 21 : emit_move_insn (tmp1, CONSTM1_RTX (V16HImode));
17527 21 : tmp2 = gen_reg_rtx (V16HImode);
17528 21 : emit_insn (gen_ashlv16hi3 (tmp2, tmp1, GEN_INT (entry->arg)));
17529 : }
17530 9 : else if (mode == V16SImode && TARGET_AVX512BW)
17531 : {
17532 9 : tmp1 = gen_reg_rtx (V32HImode);
17533 9 : emit_move_insn (tmp1, CONSTM1_RTX (V32HImode));
17534 9 : tmp2 = gen_reg_rtx (V32HImode);
17535 9 : emit_insn (gen_ashlv32hi3 (tmp2, tmp1, GEN_INT (entry->arg)));
17536 : }
17537 : else
17538 : return false;
17539 : break;
17540 :
17541 1744 : case VEC_BCAST_PSLLD:
17542 1744 : if (mode == V4SImode && TARGET_SSE2)
17543 : {
17544 1708 : tmp1 = gen_reg_rtx (V4SImode);
17545 1708 : emit_move_insn (tmp1, CONSTM1_RTX (V4SImode));
17546 1708 : emit_insn (gen_ashlv4si3 (target, tmp1, GEN_INT (entry->arg)));
17547 1708 : return true;
17548 : }
17549 36 : else if (mode == V8SImode && TARGET_AVX2)
17550 : {
17551 18 : tmp1 = gen_reg_rtx (V8SImode);
17552 18 : emit_move_insn (tmp1, CONSTM1_RTX (V8SImode));
17553 18 : emit_insn (gen_ashlv8si3 (target, tmp1, GEN_INT (entry->arg)));
17554 18 : return true;
17555 : }
17556 18 : else if (mode == V16SImode && TARGET_AVX512F)
17557 : {
17558 18 : tmp1 = gen_reg_rtx (V16SImode);
17559 18 : emit_move_insn (tmp1, CONSTM1_RTX (V16SImode));
17560 18 : emit_insn (gen_ashlv16si3 (target, tmp1, GEN_INT (entry->arg)));
17561 18 : return true;
17562 : }
17563 : else
17564 : return false;
17565 :
17566 : default:
17567 : return false;
17568 : }
17569 :
17570 4606 : emit_move_insn (target, gen_lowpart (mode, tmp2));
17571 4606 : return true;
17572 : }
17573 :
17574 : /* A subroutine of ix86_expand_vector_init_duplicate. Tries to
17575 : fill target with val via vec_duplicate. */
17576 :
17577 : static bool
17578 152696 : ix86_vector_duplicate_value (machine_mode mode, rtx target, rtx val)
17579 : {
17580 152696 : bool ok;
17581 152696 : rtx_insn *insn;
17582 152696 : rtx dup;
17583 :
17584 152696 : if ((mode == V4SImode || mode == V8SImode || mode == V16SImode)
17585 59915 : && CONST_INT_P (val)
17586 51973 : && ix86_vector_duplicate_simode_const (mode, target, INTVAL (val)))
17587 : return true;
17588 :
17589 : /* Save/restore recog_data in case this is called from splitters
17590 : or other routines where recog_data needs to stay valid across
17591 : force_reg. See PR106577. */
17592 134043 : recog_data_d recog_data_save = recog_data;
17593 :
17594 : /* First attempt to recognize VAL as-is. */
17595 134043 : dup = gen_vec_duplicate (mode, val);
17596 134043 : insn = emit_insn (gen_rtx_SET (target, dup));
17597 134043 : if (recog_memoized (insn) < 0)
17598 : {
17599 95887 : rtx_insn *seq;
17600 95887 : machine_mode innermode = GET_MODE_INNER (mode);
17601 95887 : rtx reg;
17602 :
17603 : /* If that fails, force VAL into a register or mem. */
17604 :
17605 95887 : start_sequence ();
17606 :
17607 0 : if (!TARGET_PREFER_BCST_FROM_INTEGER && CONST_INT_P (val)
17608 0 : && GET_MODE_BITSIZE (innermode) <= HOST_BITS_PER_WIDE_INT
17609 95887 : && GET_MODE_BITSIZE(mode) >= 128)
17610 0 : reg = validize_mem (force_const_mem (innermode, val));
17611 : else
17612 : {
17613 95887 : reg = force_reg (innermode, val);
17614 95887 : if (GET_MODE (reg) != innermode)
17615 0 : reg = gen_lowpart (innermode, reg);
17616 : }
17617 :
17618 95887 : SET_SRC (PATTERN (insn)) = gen_vec_duplicate (mode, reg);
17619 95887 : seq = end_sequence ();
17620 95887 : if (seq)
17621 95887 : emit_insn_before (seq, insn);
17622 :
17623 95887 : ok = recog_memoized (insn) >= 0;
17624 95887 : gcc_assert (ok);
17625 : }
17626 134043 : recog_data = recog_data_save;
17627 134043 : return true;
17628 : }
17629 :
17630 : /* Get a vector mode of the same size as the original but with elements
17631 : twice as wide. This is only guaranteed to apply to integral vectors. */
17632 :
17633 : static machine_mode
17634 25949 : get_mode_wider_vector (machine_mode o)
17635 : {
17636 : /* ??? Rely on the ordering that genmodes.cc gives to vectors. */
17637 25949 : machine_mode n = GET_MODE_NEXT_MODE (o).require ();
17638 77847 : gcc_assert (GET_MODE_NUNITS (o) == GET_MODE_NUNITS (n) * 2);
17639 77847 : gcc_assert (GET_MODE_SIZE (o) == GET_MODE_SIZE (n));
17640 25949 : return n;
17641 : }
17642 :
17643 : static bool expand_vec_perm_broadcast_1 (struct expand_vec_perm_d *d);
17644 : static bool expand_vec_perm_1 (struct expand_vec_perm_d *d);
17645 :
17646 : /* A subroutine of ix86_expand_vector_init. Store into TARGET a vector
17647 : with all elements equal to VAR. Return true if successful. */
17648 :
17649 : bool
17650 179922 : ix86_expand_vector_init_duplicate (bool mmx_ok, machine_mode mode,
17651 : rtx target, rtx val)
17652 : {
17653 179922 : bool ok;
17654 :
17655 179922 : switch (mode)
17656 : {
17657 70922 : case E_V2DImode:
17658 70922 : if (CONST_INT_P (val))
17659 : {
17660 61711 : int tmp = (int)INTVAL (val);
17661 61711 : if (tmp == (int)(INTVAL (val) >> 32))
17662 : {
17663 93 : rtx reg = gen_reg_rtx (V4SImode);
17664 93 : ok = ix86_vector_duplicate_value (V4SImode, reg,
17665 : GEN_INT (tmp));
17666 93 : if (ok)
17667 : {
17668 93 : emit_move_insn (target, gen_lowpart (V2DImode, reg));
17669 93 : return true;
17670 : }
17671 : }
17672 : }
17673 70829 : return ix86_vector_duplicate_value (mode, target, val);
17674 :
17675 1007 : case E_V4DImode:
17676 1007 : if (CONST_INT_P (val))
17677 : {
17678 718 : int tmp = (int)INTVAL (val);
17679 718 : if (tmp == (int)(INTVAL (val) >> 32))
17680 : {
17681 54 : rtx reg = gen_reg_rtx (V8SImode);
17682 54 : ok = ix86_vector_duplicate_value (V8SImode, reg,
17683 : GEN_INT (tmp));
17684 54 : if (ok)
17685 : {
17686 54 : emit_move_insn (target, gen_lowpart (V4DImode, reg));
17687 54 : return true;
17688 : }
17689 : }
17690 : }
17691 953 : return ix86_vector_duplicate_value (mode, target, val);
17692 :
17693 464 : case E_V8DImode:
17694 464 : if (CONST_INT_P (val))
17695 : {
17696 264 : int tmp = (int)INTVAL (val);
17697 264 : if (tmp == (int)(INTVAL (val) >> 32))
17698 : {
17699 24 : rtx reg = gen_reg_rtx (V16SImode);
17700 24 : ok = ix86_vector_duplicate_value (V16SImode, reg,
17701 : GEN_INT (tmp));
17702 24 : if (ok)
17703 : {
17704 24 : emit_move_insn (target, gen_lowpart (V8DImode, reg));
17705 24 : return true;
17706 : }
17707 : }
17708 : }
17709 440 : return ix86_vector_duplicate_value (mode, target, val);
17710 :
17711 2684 : case E_V2SImode:
17712 2684 : case E_V2SFmode:
17713 2684 : if (!mmx_ok)
17714 : return false;
17715 : /* FALLTHRU */
17716 :
17717 79317 : case E_V4DFmode:
17718 79317 : case E_V8SFmode:
17719 79317 : case E_V8SImode:
17720 79317 : case E_V2DFmode:
17721 79317 : case E_V4SFmode:
17722 79317 : case E_V4SImode:
17723 79317 : case E_V16SImode:
17724 79317 : case E_V16SFmode:
17725 79317 : case E_V8DFmode:
17726 79317 : return ix86_vector_duplicate_value (mode, target, val);
17727 :
17728 387 : case E_V4HImode:
17729 387 : if (!mmx_ok)
17730 : return false;
17731 384 : if (TARGET_SSE || TARGET_3DNOW_A)
17732 : {
17733 384 : rtx x;
17734 :
17735 384 : val = gen_lowpart (SImode, val);
17736 384 : if (CONST_INT_P (val))
17737 : return false;
17738 382 : x = gen_rtx_TRUNCATE (HImode, val);
17739 382 : x = gen_rtx_VEC_DUPLICATE (mode, x);
17740 382 : emit_insn (gen_rtx_SET (target, x));
17741 382 : return true;
17742 : }
17743 0 : goto widen;
17744 :
17745 5 : case E_V4HFmode:
17746 5 : case E_V4BFmode:
17747 5 : if (TARGET_MMX_WITH_SSE)
17748 : {
17749 10 : val = force_reg (GET_MODE_INNER (mode), val);
17750 5 : rtx x = gen_rtx_VEC_DUPLICATE (mode, val);
17751 5 : emit_insn (gen_rtx_SET (target, x));
17752 5 : return true;
17753 : }
17754 : return false;
17755 :
17756 125 : case E_V2HImode:
17757 125 : if (TARGET_SSE2)
17758 : {
17759 125 : rtx x;
17760 :
17761 125 : val = gen_lowpart (SImode, val);
17762 125 : if (CONST_INT_P (val))
17763 : return false;
17764 125 : x = gen_rtx_TRUNCATE (HImode, val);
17765 125 : x = gen_rtx_VEC_DUPLICATE (mode, x);
17766 125 : emit_insn (gen_rtx_SET (target, x));
17767 125 : return true;
17768 : }
17769 : return false;
17770 :
17771 5 : case E_V2HFmode:
17772 5 : case E_V2BFmode:
17773 5 : if (TARGET_SSE2)
17774 : {
17775 10 : val = force_reg (GET_MODE_INNER (mode), val);
17776 5 : rtx x = gen_rtx_VEC_DUPLICATE (mode, val);
17777 5 : emit_insn (gen_rtx_SET (target, x));
17778 5 : return true;
17779 : }
17780 : return false;
17781 :
17782 297 : case E_V8QImode:
17783 297 : case E_V4QImode:
17784 297 : if (!mmx_ok)
17785 : return false;
17786 296 : goto widen;
17787 :
17788 13668 : case E_V8HImode:
17789 13668 : if (CONST_INT_P (val))
17790 13124 : goto widen;
17791 : /* FALLTHRU */
17792 :
17793 858 : case E_V8HFmode:
17794 858 : case E_V8BFmode:
17795 858 : if (TARGET_AVX2)
17796 392 : return ix86_vector_duplicate_value (mode, target, val);
17797 :
17798 466 : if (TARGET_SSE2)
17799 : {
17800 1182 : struct expand_vec_perm_d dperm;
17801 1182 : rtx tmp1, tmp2;
17802 :
17803 466 : permute:
17804 1182 : memset (&dperm, 0, sizeof (dperm));
17805 1182 : dperm.target = target;
17806 1182 : dperm.vmode = mode;
17807 1182 : dperm.nelt = GET_MODE_NUNITS (mode);
17808 1182 : dperm.op0 = dperm.op1 = gen_reg_rtx (mode);
17809 1182 : dperm.one_operand_p = true;
17810 :
17811 1182 : if (mode == V8HFmode || mode == V8BFmode)
17812 : {
17813 3 : tmp1 = force_reg (GET_MODE_INNER (mode), val);
17814 3 : tmp2 = gen_reg_rtx (mode);
17815 3 : emit_insn (gen_vec_set_0 (mode, tmp2, CONST0_RTX (mode), tmp1));
17816 3 : tmp1 = gen_lowpart (mode, tmp2);
17817 : }
17818 : else
17819 : {
17820 : /* Extend to SImode using a paradoxical SUBREG. */
17821 1179 : tmp1 = gen_reg_rtx (SImode);
17822 1179 : emit_move_insn (tmp1, gen_lowpart (SImode, val));
17823 :
17824 : /* Insert the SImode value as
17825 : low element of a V4SImode vector. */
17826 1179 : tmp2 = gen_reg_rtx (V4SImode);
17827 1179 : emit_insn (gen_vec_setv4si_0 (tmp2, CONST0_RTX (V4SImode), tmp1));
17828 1179 : tmp1 = gen_lowpart (mode, tmp2);
17829 : }
17830 :
17831 1182 : emit_move_insn (dperm.op0, tmp1);
17832 1182 : ok = (expand_vec_perm_1 (&dperm)
17833 1182 : || expand_vec_perm_broadcast_1 (&dperm));
17834 0 : gcc_assert (ok);
17835 1182 : return ok;
17836 : }
17837 0 : goto widen;
17838 :
17839 9262 : case E_V16QImode:
17840 9262 : if (CONST_INT_P (val))
17841 8486 : goto widen;
17842 776 : if (TARGET_AVX2)
17843 60 : return ix86_vector_duplicate_value (mode, target, val);
17844 :
17845 716 : if (TARGET_SSE2)
17846 716 : goto permute;
17847 0 : goto widen;
17848 :
17849 24325 : widen:
17850 : /* Replicate the value once into the next wider mode and recurse. */
17851 24325 : {
17852 24325 : machine_mode smode, wsmode, wvmode;
17853 24325 : rtx x;
17854 :
17855 24325 : smode = GET_MODE_INNER (mode);
17856 24325 : wvmode = get_mode_wider_vector (mode);
17857 24325 : wsmode = GET_MODE_INNER (wvmode);
17858 :
17859 24325 : val = convert_modes (wsmode, smode, val, true);
17860 :
17861 24325 : if (CONST_INT_P (val))
17862 : {
17863 48060 : x = simplify_binary_operation (ASHIFT, wsmode, val,
17864 24030 : GEN_INT (GET_MODE_BITSIZE (smode)));
17865 24030 : val = simplify_binary_operation (IOR, wsmode, val, x);
17866 : }
17867 295 : else if (smode == QImode && !TARGET_PARTIAL_REG_STALL)
17868 295 : emit_insn (gen_insv_1 (wsmode, val, val));
17869 : else
17870 : {
17871 0 : x = expand_simple_binop (wsmode, ASHIFT, val,
17872 0 : GEN_INT (GET_MODE_BITSIZE (smode)),
17873 : NULL_RTX, 1, OPTAB_LIB_WIDEN);
17874 0 : val = expand_simple_binop (wsmode, IOR, val, x, x, 1,
17875 : OPTAB_LIB_WIDEN);
17876 : }
17877 :
17878 24325 : x = gen_reg_rtx (wvmode);
17879 24325 : ok = ix86_expand_vector_init_duplicate (mmx_ok, wvmode, x, val);
17880 24325 : if (!ok)
17881 : return false;
17882 24324 : emit_move_insn (target, gen_lowpart (GET_MODE (target), x));
17883 24324 : return true;
17884 : }
17885 :
17886 1538 : case E_V16HImode:
17887 1538 : case E_V32QImode:
17888 1538 : if (CONST_INT_P (val))
17889 1246 : goto widen;
17890 : /* FALLTHRU */
17891 :
17892 375 : case E_V16HFmode:
17893 375 : case E_V16BFmode:
17894 375 : if (TARGET_AVX2)
17895 347 : return ix86_vector_duplicate_value (mode, target, val);
17896 : else
17897 : {
17898 28 : machine_mode hvmode;
17899 28 : switch (mode)
17900 : {
17901 : case V16HImode:
17902 : hvmode = V8HImode;
17903 : break;
17904 0 : case V16HFmode:
17905 0 : hvmode = V8HFmode;
17906 0 : break;
17907 1 : case V16BFmode:
17908 1 : hvmode = V8BFmode;
17909 1 : break;
17910 14 : case V32QImode:
17911 14 : hvmode = V16QImode;
17912 14 : break;
17913 0 : default:
17914 0 : gcc_unreachable ();
17915 : }
17916 28 : rtx x = gen_reg_rtx (hvmode);
17917 :
17918 28 : ok = ix86_expand_vector_init_duplicate (false, hvmode, x, val);
17919 28 : if (!ok)
17920 : return false;
17921 :
17922 28 : x = gen_rtx_VEC_CONCAT (mode, x, x);
17923 28 : emit_insn (gen_rtx_SET (target, x));
17924 : }
17925 28 : return true;
17926 :
17927 1301 : case E_V32HImode:
17928 1301 : case E_V64QImode:
17929 1301 : if (CONST_INT_P (val))
17930 1173 : goto widen;
17931 : /* FALLTHRU */
17932 :
17933 207 : case E_V32HFmode:
17934 207 : case E_V32BFmode:
17935 207 : if (TARGET_AVX512BW)
17936 187 : return ix86_vector_duplicate_value (mode, target, val);
17937 : else
17938 : {
17939 20 : machine_mode hvmode;
17940 20 : switch (mode)
17941 : {
17942 : case V32HImode:
17943 : hvmode = V16HImode;
17944 : break;
17945 0 : case V32HFmode:
17946 0 : hvmode = V16HFmode;
17947 0 : break;
17948 1 : case V32BFmode:
17949 1 : hvmode = V16BFmode;
17950 1 : break;
17951 10 : case V64QImode:
17952 10 : hvmode = V32QImode;
17953 10 : break;
17954 0 : default:
17955 0 : gcc_unreachable ();
17956 : }
17957 20 : rtx x = gen_reg_rtx (hvmode);
17958 :
17959 20 : ok = ix86_expand_vector_init_duplicate (false, hvmode, x, val);
17960 20 : if (!ok)
17961 : return false;
17962 :
17963 20 : x = gen_rtx_VEC_CONCAT (mode, x, x);
17964 20 : emit_insn (gen_rtx_SET (target, x));
17965 : }
17966 20 : return true;
17967 :
17968 : default:
17969 : return false;
17970 : }
17971 : }
17972 :
17973 : /* A subroutine of ix86_expand_vector_init. Store into TARGET a vector
17974 : whose ONE_VAR element is VAR, and other elements are zero. Return true
17975 : if successful. */
17976 :
17977 : bool
17978 10861 : ix86_expand_vector_init_one_nonzero (bool mmx_ok, machine_mode mode,
17979 : rtx target, rtx var, int one_var)
17980 : {
17981 10861 : machine_mode vsimode;
17982 10861 : rtx new_target;
17983 10861 : rtx x, tmp;
17984 10861 : bool use_vector_set = false;
17985 10861 : rtx (*gen_vec_set_0) (rtx, rtx, rtx) = NULL;
17986 :
17987 10861 : switch (mode)
17988 : {
17989 8375 : case E_V2DImode:
17990 : /* For SSE4.1, we normally use vector set. But if the second
17991 : element is zero and inter-unit moves are OK, we use movq
17992 : instead. */
17993 8366 : use_vector_set = (TARGET_64BIT && TARGET_SSE4_1
17994 8498 : && !(TARGET_INTER_UNIT_MOVES_TO_VEC
17995 : && one_var == 0));
17996 : break;
17997 871 : case E_V16QImode:
17998 871 : case E_V4SImode:
17999 871 : case E_V4SFmode:
18000 871 : use_vector_set = TARGET_SSE4_1;
18001 871 : break;
18002 86 : case E_V8HImode:
18003 86 : use_vector_set = TARGET_SSE2;
18004 86 : gen_vec_set_0 = TARGET_AVX512FP16 && one_var == 0
18005 86 : ? gen_vec_setv8hi_0 : NULL;
18006 : break;
18007 4 : case E_V8QImode:
18008 4 : use_vector_set = TARGET_MMX_WITH_SSE && TARGET_SSE4_1;
18009 : break;
18010 14 : case E_V4HImode:
18011 14 : case E_V4HFmode:
18012 14 : case E_V4BFmode:
18013 14 : use_vector_set = TARGET_SSE || TARGET_3DNOW_A;
18014 : break;
18015 32 : case E_V4QImode:
18016 32 : use_vector_set = TARGET_SSE4_1;
18017 32 : break;
18018 0 : case E_V32QImode:
18019 0 : use_vector_set = TARGET_AVX;
18020 0 : break;
18021 5 : case E_V16HImode:
18022 5 : use_vector_set = TARGET_AVX;
18023 5 : gen_vec_set_0 = TARGET_AVX512FP16 && one_var == 0
18024 5 : ? gen_vec_setv16hi_0 : NULL;
18025 : break;
18026 5 : case E_V8SImode:
18027 5 : use_vector_set = TARGET_AVX;
18028 5 : gen_vec_set_0 = gen_vec_setv8si_0;
18029 5 : break;
18030 22 : case E_V8SFmode:
18031 22 : use_vector_set = TARGET_AVX;
18032 22 : gen_vec_set_0 = gen_vec_setv8sf_0;
18033 22 : break;
18034 13 : case E_V4DFmode:
18035 13 : use_vector_set = TARGET_AVX;
18036 13 : gen_vec_set_0 = gen_vec_setv4df_0;
18037 13 : break;
18038 7 : case E_V4DImode:
18039 : /* Use ix86_expand_vector_set in 64bit mode only. */
18040 7 : use_vector_set = TARGET_AVX && TARGET_64BIT;
18041 : gen_vec_set_0 = gen_vec_setv4di_0;
18042 : break;
18043 17 : case E_V16SImode:
18044 17 : use_vector_set = TARGET_AVX512F && one_var == 0;
18045 : gen_vec_set_0 = gen_vec_setv16si_0;
18046 : break;
18047 22 : case E_V16SFmode:
18048 22 : use_vector_set = TARGET_AVX512F && one_var == 0;
18049 : gen_vec_set_0 = gen_vec_setv16sf_0;
18050 : break;
18051 0 : case E_V8DFmode:
18052 0 : use_vector_set = TARGET_AVX512F && one_var == 0;
18053 : gen_vec_set_0 = gen_vec_setv8df_0;
18054 : break;
18055 2 : case E_V8DImode:
18056 : /* Use ix86_expand_vector_set in 64bit mode only. */
18057 2 : use_vector_set = TARGET_AVX512F && TARGET_64BIT && one_var == 0;
18058 : gen_vec_set_0 = gen_vec_setv8di_0;
18059 : break;
18060 39 : case E_V8HFmode:
18061 39 : use_vector_set = TARGET_AVX512FP16 && one_var == 0;
18062 : gen_vec_set_0 = gen_vec_setv8hf_0;
18063 : break;
18064 9 : case E_V16HFmode:
18065 9 : use_vector_set = TARGET_AVX512FP16 && one_var == 0;
18066 : gen_vec_set_0 = gen_vec_setv16hf_0;
18067 : break;
18068 6 : case E_V32HFmode:
18069 6 : use_vector_set = TARGET_AVX512FP16 && one_var == 0;
18070 : gen_vec_set_0 = gen_vec_setv32hf_0;
18071 : break;
18072 2 : case E_V8BFmode:
18073 2 : use_vector_set = TARGET_AVX512FP16 && one_var == 0;
18074 : gen_vec_set_0 = gen_vec_setv8bf_0;
18075 : break;
18076 0 : case E_V16BFmode:
18077 0 : use_vector_set = TARGET_AVX512FP16 && one_var == 0;
18078 : gen_vec_set_0 = gen_vec_setv16bf_0;
18079 : break;
18080 0 : case E_V32BFmode:
18081 0 : use_vector_set = TARGET_AVX512FP16 && one_var == 0;
18082 : gen_vec_set_0 = gen_vec_setv32bf_0;
18083 : break;
18084 4 : case E_V32HImode:
18085 4 : use_vector_set = TARGET_AVX512FP16 && one_var == 0;
18086 : gen_vec_set_0 = gen_vec_setv32hi_0;
18087 : default:
18088 : break;
18089 : }
18090 :
18091 9423 : if (use_vector_set)
18092 : {
18093 858 : if (gen_vec_set_0 && one_var == 0)
18094 : {
18095 354 : var = force_reg (GET_MODE_INNER (mode), var);
18096 177 : emit_insn (gen_vec_set_0 (target, CONST0_RTX (mode), var));
18097 177 : return true;
18098 : }
18099 681 : emit_insn (gen_rtx_SET (target, CONST0_RTX (mode)));
18100 1362 : var = force_reg (GET_MODE_INNER (mode), var);
18101 681 : ix86_expand_vector_set (mmx_ok, target, var, one_var);
18102 681 : return true;
18103 : }
18104 :
18105 10003 : switch (mode)
18106 : {
18107 1216 : case E_V2SFmode:
18108 1216 : case E_V2SImode:
18109 1216 : if (!mmx_ok)
18110 : return false;
18111 : /* FALLTHRU */
18112 :
18113 8633 : case E_V2DFmode:
18114 8633 : case E_V2DImode:
18115 8633 : if (one_var != 0)
18116 : return false;
18117 5268 : var = force_reg (GET_MODE_INNER (mode), var);
18118 5268 : x = gen_rtx_VEC_CONCAT (mode, var, CONST0_RTX (GET_MODE_INNER (mode)));
18119 2634 : emit_insn (gen_rtx_SET (target, x));
18120 2634 : return true;
18121 :
18122 306 : case E_V4SFmode:
18123 306 : case E_V4SImode:
18124 306 : if (!REG_P (target) || REGNO (target) < FIRST_PSEUDO_REGISTER)
18125 0 : new_target = gen_reg_rtx (mode);
18126 : else
18127 : new_target = target;
18128 612 : var = force_reg (GET_MODE_INNER (mode), var);
18129 306 : x = gen_rtx_VEC_DUPLICATE (mode, var);
18130 306 : x = gen_rtx_VEC_MERGE (mode, x, CONST0_RTX (mode), const1_rtx);
18131 306 : emit_insn (gen_rtx_SET (new_target, x));
18132 306 : if (one_var != 0)
18133 : {
18134 : /* We need to shuffle the value to the correct position, so
18135 : create a new pseudo to store the intermediate result. */
18136 :
18137 : /* With SSE2, we can use the integer shuffle insns. */
18138 44 : if (mode != V4SFmode && TARGET_SSE2)
18139 : {
18140 31 : emit_insn (gen_sse2_pshufd_1 (new_target, new_target,
18141 : const1_rtx,
18142 31 : GEN_INT (one_var == 1 ? 0 : 1),
18143 31 : GEN_INT (one_var == 2 ? 0 : 1),
18144 31 : GEN_INT (one_var == 3 ? 0 : 1)));
18145 31 : if (target != new_target)
18146 0 : emit_move_insn (target, new_target);
18147 31 : return true;
18148 : }
18149 :
18150 : /* Otherwise convert the intermediate result to V4SFmode and
18151 : use the SSE1 shuffle instructions. */
18152 0 : if (mode != V4SFmode)
18153 : {
18154 0 : tmp = gen_reg_rtx (V4SFmode);
18155 0 : emit_move_insn (tmp, gen_lowpart (V4SFmode, new_target));
18156 : }
18157 : else
18158 : tmp = new_target;
18159 :
18160 43 : emit_insn (gen_sse_shufps_v4sf (tmp, tmp, tmp,
18161 : const1_rtx,
18162 13 : GEN_INT (one_var == 1 ? 0 : 1),
18163 : GEN_INT (one_var == 2 ? 0+4 : 1+4),
18164 : GEN_INT (one_var == 3 ? 0+4 : 1+4)));
18165 :
18166 13 : if (mode != V4SFmode)
18167 0 : emit_move_insn (target, gen_lowpart (V4SImode, tmp));
18168 13 : else if (tmp != target)
18169 0 : emit_move_insn (target, tmp);
18170 : }
18171 262 : else if (target != new_target)
18172 0 : emit_move_insn (target, new_target);
18173 : return true;
18174 :
18175 14 : case E_V8HImode:
18176 14 : case E_V16QImode:
18177 14 : vsimode = V4SImode;
18178 14 : goto widen;
18179 3 : case E_V4HImode:
18180 3 : case E_V8QImode:
18181 3 : if (!mmx_ok)
18182 : return false;
18183 3 : vsimode = V2SImode;
18184 3 : goto widen;
18185 17 : widen:
18186 17 : if (one_var != 0)
18187 : return false;
18188 :
18189 : /* Zero extend the variable element to SImode and recurse. */
18190 18 : var = convert_modes (SImode, GET_MODE_INNER (mode), var, true);
18191 :
18192 9 : x = gen_reg_rtx (vsimode);
18193 9 : if (!ix86_expand_vector_init_one_nonzero (mmx_ok, vsimode, x,
18194 : var, one_var))
18195 0 : gcc_unreachable ();
18196 :
18197 9 : emit_move_insn (target, gen_lowpart (mode, x));
18198 9 : return true;
18199 :
18200 : default:
18201 : return false;
18202 : }
18203 : }
18204 :
18205 : /* A subroutine of ix86_expand_vector_init. Store into TARGET a vector
18206 : consisting of the values in VALS. It is known that all elements
18207 : except ONE_VAR are constants. Return true if successful. */
18208 :
18209 : static bool
18210 8367 : ix86_expand_vector_init_one_var (bool mmx_ok, machine_mode mode,
18211 : rtx target, rtx vals, int one_var)
18212 : {
18213 8367 : rtx var = XVECEXP (vals, 0, one_var);
18214 8367 : machine_mode wmode;
18215 8367 : rtx const_vec, x;
18216 :
18217 8367 : const_vec = copy_rtx (vals);
18218 8367 : XVECEXP (const_vec, 0, one_var) = CONST0_RTX (GET_MODE_INNER (mode));
18219 8367 : const_vec = gen_rtx_CONST_VECTOR (mode, XVEC (const_vec, 0));
18220 :
18221 8367 : switch (mode)
18222 : {
18223 : case E_V2DFmode:
18224 : case E_V2DImode:
18225 : case E_V2SFmode:
18226 : case E_V2SImode:
18227 : /* For the two element vectors, it's just as easy to use
18228 : the general case. */
18229 : return false;
18230 :
18231 3 : case E_V4DImode:
18232 : /* Use ix86_expand_vector_set in 64bit mode only. */
18233 3 : if (!TARGET_64BIT)
18234 : return false;
18235 : /* FALLTHRU */
18236 : case E_V8HFmode:
18237 : case E_V16HFmode:
18238 : case E_V8BFmode:
18239 : case E_V16BFmode:
18240 : case E_V4DFmode:
18241 : case E_V8SFmode:
18242 : case E_V8SImode:
18243 : case E_V16HImode:
18244 : case E_V32QImode:
18245 : case E_V4SFmode:
18246 : case E_V4SImode:
18247 : case E_V8HImode:
18248 : case E_V4HImode:
18249 : case E_V4HFmode:
18250 : case E_V4BFmode:
18251 : break;
18252 :
18253 8 : case E_V16QImode:
18254 8 : if (TARGET_SSE4_1)
18255 : break;
18256 8 : wmode = V8HImode;
18257 8 : goto widen;
18258 1 : case E_V8QImode:
18259 1 : if (TARGET_MMX_WITH_SSE && TARGET_SSE4_1)
18260 : break;
18261 1 : wmode = V4HImode;
18262 1 : goto widen;
18263 38 : case E_V4QImode:
18264 38 : if (TARGET_SSE4_1)
18265 : break;
18266 : wmode = V2HImode;
18267 47 : widen:
18268 : /* There's no way to set one QImode entry easily. Combine
18269 : the variable value with its adjacent constant value, and
18270 : promote to an HImode set. */
18271 47 : x = XVECEXP (vals, 0, one_var ^ 1);
18272 47 : if (one_var & 1)
18273 : {
18274 13 : var = convert_modes (HImode, QImode, var, true);
18275 13 : var = expand_simple_binop (HImode, ASHIFT, var, GEN_INT (8),
18276 : NULL_RTX, 1, OPTAB_LIB_WIDEN);
18277 13 : x = GEN_INT (INTVAL (x) & 0xff);
18278 : }
18279 : else
18280 : {
18281 34 : var = convert_modes (HImode, QImode, var, true);
18282 34 : x = gen_int_mode (UINTVAL (x) << 8, HImode);
18283 : }
18284 47 : if (x != const0_rtx)
18285 7 : var = expand_simple_binop (HImode, IOR, var, x, var,
18286 : 1, OPTAB_LIB_WIDEN);
18287 :
18288 47 : x = gen_reg_rtx (wmode);
18289 47 : emit_move_insn (x, gen_lowpart (wmode, const_vec));
18290 47 : ix86_expand_vector_set (mmx_ok, x, var, one_var >> 1);
18291 :
18292 47 : emit_move_insn (target, gen_lowpart (mode, x));
18293 47 : return true;
18294 :
18295 : default:
18296 : return false;
18297 : }
18298 :
18299 199 : emit_move_insn (target, const_vec);
18300 199 : ix86_expand_vector_set (mmx_ok, target, var, one_var);
18301 199 : return true;
18302 : }
18303 :
18304 : /* A subroutine of ix86_expand_vector_init_general. Use vector
18305 : concatenate to handle the most general case: all values variable,
18306 : and none identical. */
18307 :
18308 : static void
18309 121010 : ix86_expand_vector_init_concat (machine_mode mode,
18310 : rtx target, rtx *ops, int n)
18311 : {
18312 121010 : machine_mode half_mode = VOIDmode;
18313 121010 : rtx half[2];
18314 121010 : rtvec v;
18315 121010 : int i, j;
18316 :
18317 121010 : switch (n)
18318 : {
18319 112622 : case 2:
18320 112622 : switch (mode)
18321 : {
18322 : case E_V32HFmode:
18323 : half_mode = V16HFmode;
18324 : break;
18325 0 : case E_V32BFmode:
18326 0 : half_mode = V16BFmode;
18327 0 : break;
18328 59 : case E_V16SImode:
18329 59 : half_mode = V8SImode;
18330 59 : break;
18331 33 : case E_V16SFmode:
18332 33 : half_mode = V8SFmode;
18333 33 : break;
18334 84 : case E_V8DImode:
18335 84 : half_mode = V4DImode;
18336 84 : break;
18337 59 : case E_V8DFmode:
18338 59 : half_mode = V4DFmode;
18339 59 : break;
18340 0 : case E_V16HFmode:
18341 0 : half_mode = V8HFmode;
18342 0 : break;
18343 0 : case E_V16BFmode:
18344 0 : half_mode = V8BFmode;
18345 0 : break;
18346 170 : case E_V8SImode:
18347 170 : half_mode = V4SImode;
18348 170 : break;
18349 258 : case E_V8SFmode:
18350 258 : half_mode = V4SFmode;
18351 258 : break;
18352 272 : case E_V4DImode:
18353 272 : half_mode = V2DImode;
18354 272 : break;
18355 551 : case E_V4DFmode:
18356 551 : half_mode = V2DFmode;
18357 551 : break;
18358 6198 : case E_V4SImode:
18359 6198 : half_mode = V2SImode;
18360 6198 : break;
18361 2227 : case E_V4SFmode:
18362 2227 : half_mode = V2SFmode;
18363 2227 : break;
18364 66071 : case E_V2DImode:
18365 66071 : half_mode = DImode;
18366 66071 : break;
18367 27714 : case E_V2SImode:
18368 27714 : half_mode = SImode;
18369 27714 : break;
18370 3565 : case E_V2DFmode:
18371 3565 : half_mode = DFmode;
18372 3565 : break;
18373 5361 : case E_V2SFmode:
18374 5361 : half_mode = SFmode;
18375 5361 : break;
18376 0 : default:
18377 0 : gcc_unreachable ();
18378 : }
18379 :
18380 112622 : if (!register_operand (ops[1], half_mode))
18381 47829 : ops[1] = force_reg (half_mode, ops[1]);
18382 112622 : if (!register_operand (ops[0], half_mode))
18383 36355 : ops[0] = force_reg (half_mode, ops[0]);
18384 112622 : emit_insn (gen_rtx_SET (target, gen_rtx_VEC_CONCAT (mode, ops[0],
18385 : ops[1])));
18386 112622 : break;
18387 :
18388 7830 : case 4:
18389 7830 : switch (mode)
18390 : {
18391 : case E_V4DImode:
18392 : half_mode = V2DImode;
18393 : break;
18394 494 : case E_V4DFmode:
18395 494 : half_mode = V2DFmode;
18396 494 : break;
18397 5242 : case E_V4SImode:
18398 5242 : half_mode = V2SImode;
18399 5242 : break;
18400 1948 : case E_V4SFmode:
18401 1948 : half_mode = V2SFmode;
18402 1948 : break;
18403 0 : default:
18404 0 : gcc_unreachable ();
18405 : }
18406 7830 : goto half;
18407 :
18408 487 : case 8:
18409 487 : switch (mode)
18410 : {
18411 : case E_V8DImode:
18412 : half_mode = V4DImode;
18413 : break;
18414 59 : case E_V8DFmode:
18415 59 : half_mode = V4DFmode;
18416 59 : break;
18417 133 : case E_V8SImode:
18418 133 : half_mode = V4SImode;
18419 133 : break;
18420 252 : case E_V8SFmode:
18421 252 : half_mode = V4SFmode;
18422 252 : break;
18423 0 : default:
18424 0 : gcc_unreachable ();
18425 : }
18426 487 : goto half;
18427 :
18428 71 : case 16:
18429 71 : switch (mode)
18430 : {
18431 : case E_V16SImode:
18432 : half_mode = V8SImode;
18433 : break;
18434 33 : case E_V16SFmode:
18435 33 : half_mode = V8SFmode;
18436 33 : break;
18437 0 : default:
18438 0 : gcc_unreachable ();
18439 : }
18440 71 : goto half;
18441 :
18442 8388 : half:
18443 : /* FIXME: We process inputs backward to help RA. PR 36222. */
18444 8388 : i = n - 1;
18445 25164 : for (j = 1; j != -1; j--)
18446 : {
18447 16776 : half[j] = gen_reg_rtx (half_mode);
18448 16776 : switch (n >> 1)
18449 : {
18450 15660 : case 2:
18451 15660 : v = gen_rtvec (2, ops[i-1], ops[i]);
18452 15660 : i -= 2;
18453 15660 : break;
18454 974 : case 4:
18455 974 : v = gen_rtvec (4, ops[i-3], ops[i-2], ops[i-1], ops[i]);
18456 974 : i -= 4;
18457 974 : break;
18458 142 : case 8:
18459 284 : v = gen_rtvec (8, ops[i-7], ops[i-6], ops[i-5], ops[i-4],
18460 142 : ops[i-3], ops[i-2], ops[i-1], ops[i]);
18461 142 : i -= 8;
18462 142 : break;
18463 0 : default:
18464 0 : gcc_unreachable ();
18465 : }
18466 16776 : ix86_expand_vector_init (false, half[j],
18467 : gen_rtx_PARALLEL (half_mode, v));
18468 : }
18469 :
18470 8388 : ix86_expand_vector_init_concat (mode, target, half, 2);
18471 8388 : break;
18472 :
18473 0 : default:
18474 0 : gcc_unreachable ();
18475 : }
18476 121010 : }
18477 :
18478 : /* A subroutine of ix86_expand_vector_init_general. Use vector
18479 : interleave to handle the most general case: all values variable,
18480 : and none identical. */
18481 :
18482 : static void
18483 3939 : ix86_expand_vector_init_interleave (machine_mode mode,
18484 : rtx target, rtx *ops, int n)
18485 : {
18486 3939 : machine_mode first_imode, second_imode, third_imode, inner_mode;
18487 3939 : int i, j;
18488 3939 : rtx op, op0, op1;
18489 3939 : rtx (*gen_load_even) (rtx, rtx, rtx);
18490 3939 : rtx (*gen_interleave_first_low) (rtx, rtx, rtx);
18491 3939 : rtx (*gen_interleave_second_low) (rtx, rtx, rtx);
18492 :
18493 3939 : switch (mode)
18494 : {
18495 : case E_V8HFmode:
18496 : gen_load_even = gen_vec_interleave_lowv8hf;
18497 : gen_interleave_first_low = gen_vec_interleave_lowv4si;
18498 : gen_interleave_second_low = gen_vec_interleave_lowv2di;
18499 : inner_mode = HFmode;
18500 : first_imode = V4SImode;
18501 : second_imode = V2DImode;
18502 : third_imode = VOIDmode;
18503 : break;
18504 487 : case E_V8BFmode:
18505 487 : gen_load_even = gen_vec_interleave_lowv8bf;
18506 487 : gen_interleave_first_low = gen_vec_interleave_lowv4si;
18507 487 : gen_interleave_second_low = gen_vec_interleave_lowv2di;
18508 487 : inner_mode = BFmode;
18509 487 : first_imode = V4SImode;
18510 487 : second_imode = V2DImode;
18511 487 : third_imode = VOIDmode;
18512 487 : break;
18513 851 : case E_V8HImode:
18514 851 : gen_load_even = gen_vec_setv8hi;
18515 851 : gen_interleave_first_low = gen_vec_interleave_lowv4si;
18516 851 : gen_interleave_second_low = gen_vec_interleave_lowv2di;
18517 851 : inner_mode = HImode;
18518 851 : first_imode = V4SImode;
18519 851 : second_imode = V2DImode;
18520 851 : third_imode = VOIDmode;
18521 851 : break;
18522 374 : case E_V16QImode:
18523 374 : gen_load_even = gen_vec_setv16qi;
18524 374 : gen_interleave_first_low = gen_vec_interleave_lowv8hi;
18525 374 : gen_interleave_second_low = gen_vec_interleave_lowv4si;
18526 374 : inner_mode = QImode;
18527 374 : first_imode = V8HImode;
18528 374 : second_imode = V4SImode;
18529 374 : third_imode = V2DImode;
18530 374 : break;
18531 0 : default:
18532 0 : gcc_unreachable ();
18533 : }
18534 :
18535 21191 : for (i = 0; i < n; i++)
18536 : {
18537 17252 : op = ops [i + i];
18538 17252 : if (inner_mode == HFmode || inner_mode == BFmode)
18539 : {
18540 10856 : rtx even, odd;
18541 : /* Use vpuncklwd to pack 2 HFmode or BFmode. */
18542 1948 : machine_mode vec_mode =
18543 10856 : (inner_mode == HFmode) ? V8HFmode : V8BFmode;
18544 10856 : op0 = gen_reg_rtx (vec_mode);
18545 10856 : even = lowpart_subreg (vec_mode,
18546 : force_reg (inner_mode, op), inner_mode);
18547 10856 : odd = lowpart_subreg (vec_mode,
18548 10856 : force_reg (inner_mode, ops[i + i + 1]),
18549 : inner_mode);
18550 10856 : emit_insn (gen_load_even (op0, even, odd));
18551 : }
18552 : else
18553 : {
18554 : /* Extend the odd element to SImode using a paradoxical SUBREG. */
18555 6396 : op0 = gen_reg_rtx (SImode);
18556 6396 : emit_move_insn (op0, gen_lowpart (SImode, op));
18557 :
18558 : /* Insert the SImode value as low element of V4SImode vector. */
18559 6396 : op1 = gen_reg_rtx (V4SImode);
18560 6396 : op0 = gen_rtx_VEC_MERGE (V4SImode,
18561 : gen_rtx_VEC_DUPLICATE (V4SImode,
18562 : op0),
18563 : CONST0_RTX (V4SImode),
18564 : const1_rtx);
18565 6396 : emit_insn (gen_rtx_SET (op1, op0));
18566 :
18567 : /* Cast the V4SImode vector back to a vector in original mode. */
18568 6396 : op0 = gen_reg_rtx (mode);
18569 6396 : emit_move_insn (op0, gen_lowpart (mode, op1));
18570 :
18571 : /* Load even elements into the second position. */
18572 6396 : emit_insn (gen_load_even (op0,
18573 : force_reg (inner_mode,
18574 6396 : ops[i + i + 1]),
18575 : const1_rtx));
18576 : }
18577 :
18578 : /* Cast vector to FIRST_IMODE vector. */
18579 17252 : ops[i] = gen_reg_rtx (first_imode);
18580 17252 : emit_move_insn (ops[i], gen_lowpart (first_imode, op0));
18581 : }
18582 :
18583 : /* Interleave low FIRST_IMODE vectors. */
18584 12565 : for (i = j = 0; i < n; i += 2, j++)
18585 : {
18586 8626 : op0 = gen_reg_rtx (first_imode);
18587 8626 : emit_insn (gen_interleave_first_low (op0, ops[i], ops[i + 1]));
18588 :
18589 : /* Cast FIRST_IMODE vector to SECOND_IMODE vector. */
18590 8626 : ops[j] = gen_reg_rtx (second_imode);
18591 8626 : emit_move_insn (ops[j], gen_lowpart (second_imode, op0));
18592 : }
18593 :
18594 : /* Interleave low SECOND_IMODE vectors. */
18595 3939 : switch (second_imode)
18596 : {
18597 : case E_V4SImode:
18598 1122 : for (i = j = 0; i < n / 2; i += 2, j++)
18599 : {
18600 748 : op0 = gen_reg_rtx (second_imode);
18601 748 : emit_insn (gen_interleave_second_low (op0, ops[i],
18602 748 : ops[i + 1]));
18603 :
18604 : /* Cast the SECOND_IMODE vector to the THIRD_IMODE
18605 : vector. */
18606 748 : ops[j] = gen_reg_rtx (third_imode);
18607 748 : emit_move_insn (ops[j], gen_lowpart (third_imode, op0));
18608 : }
18609 : second_imode = V2DImode;
18610 : gen_interleave_second_low = gen_vec_interleave_lowv2di;
18611 : /* FALLTHRU */
18612 :
18613 3939 : case E_V2DImode:
18614 3939 : op0 = gen_reg_rtx (second_imode);
18615 3939 : emit_insn (gen_interleave_second_low (op0, ops[0],
18616 : ops[1]));
18617 :
18618 : /* Cast the SECOND_IMODE vector back to a vector on original
18619 : mode. */
18620 3939 : emit_insn (gen_rtx_SET (target, gen_lowpart (mode, op0)));
18621 3939 : break;
18622 :
18623 : default:
18624 : gcc_unreachable ();
18625 : }
18626 3939 : }
18627 :
18628 : /* A subroutine of ix86_expand_vector_init. Handle the most general case:
18629 : all values variable, and none identical. */
18630 :
18631 : static void
18632 121830 : ix86_expand_vector_init_general (bool mmx_ok, machine_mode mode,
18633 : rtx target, rtx vals)
18634 : {
18635 121830 : rtx ops[64], op0, op1, op2, op3, op4, op5;
18636 121830 : machine_mode half_mode = VOIDmode;
18637 121830 : machine_mode quarter_mode = VOIDmode;
18638 121830 : machine_mode int_inner_mode = VOIDmode;
18639 121830 : int n, i;
18640 :
18641 121830 : switch (mode)
18642 : {
18643 33075 : case E_V2SFmode:
18644 33075 : case E_V2SImode:
18645 33075 : if (!mmx_ok && !TARGET_SSE)
18646 : break;
18647 : /* FALLTHRU */
18648 :
18649 111099 : case E_V16SImode:
18650 111099 : case E_V16SFmode:
18651 111099 : case E_V8DFmode:
18652 111099 : case E_V8DImode:
18653 111099 : case E_V8SFmode:
18654 111099 : case E_V8SImode:
18655 111099 : case E_V4DFmode:
18656 111099 : case E_V4DImode:
18657 111099 : case E_V4SFmode:
18658 111099 : case E_V4SImode:
18659 111099 : case E_V2DFmode:
18660 111099 : case E_V2DImode:
18661 111099 : n = GET_MODE_NUNITS (mode);
18662 352873 : for (i = 0; i < n; i++)
18663 241774 : ops[i] = XVECEXP (vals, 0, i);
18664 111099 : ix86_expand_vector_init_concat (mode, target, ops, n);
18665 224361 : return;
18666 :
18667 : case E_V2TImode:
18668 135 : for (i = 0; i < 2; i++)
18669 90 : ops[i] = gen_lowpart (V2DImode, XVECEXP (vals, 0, i));
18670 45 : op0 = gen_reg_rtx (V4DImode);
18671 45 : ix86_expand_vector_init_concat (V4DImode, op0, ops, 2);
18672 45 : emit_move_insn (target, gen_lowpart (GET_MODE (target), op0));
18673 45 : return;
18674 :
18675 : case E_V4TImode:
18676 195 : for (i = 0; i < 4; i++)
18677 156 : ops[i] = gen_lowpart (V2DImode, XVECEXP (vals, 0, i));
18678 39 : ops[4] = gen_reg_rtx (V4DImode);
18679 39 : ix86_expand_vector_init_concat (V4DImode, ops[4], ops, 2);
18680 39 : ops[5] = gen_reg_rtx (V4DImode);
18681 39 : ix86_expand_vector_init_concat (V4DImode, ops[5], ops + 2, 2);
18682 39 : op0 = gen_reg_rtx (V8DImode);
18683 39 : ix86_expand_vector_init_concat (V8DImode, op0, ops + 4, 2);
18684 39 : emit_move_insn (target, gen_lowpart (GET_MODE (target), op0));
18685 39 : return;
18686 :
18687 69 : case E_V32QImode:
18688 69 : half_mode = V16QImode;
18689 69 : goto half;
18690 :
18691 64 : case E_V16HImode:
18692 64 : half_mode = V8HImode;
18693 64 : goto half;
18694 :
18695 237 : case E_V16HFmode:
18696 237 : half_mode = V8HFmode;
18697 237 : goto half;
18698 :
18699 95 : case E_V16BFmode:
18700 95 : half_mode = V8BFmode;
18701 95 : goto half;
18702 :
18703 465 : half:
18704 465 : n = GET_MODE_NUNITS (mode);
18705 9009 : for (i = 0; i < n; i++)
18706 8544 : ops[i] = XVECEXP (vals, 0, i);
18707 465 : op0 = gen_reg_rtx (half_mode);
18708 465 : op1 = gen_reg_rtx (half_mode);
18709 465 : ix86_expand_vector_init_interleave (half_mode, op0, ops,
18710 : n >> 2);
18711 465 : ix86_expand_vector_init_interleave (half_mode, op1,
18712 465 : &ops [n >> 1], n >> 2);
18713 465 : emit_insn (gen_rtx_SET (target, gen_rtx_VEC_CONCAT (mode, op0, op1)));
18714 465 : return;
18715 :
18716 56 : case E_V64QImode:
18717 56 : quarter_mode = V16QImode;
18718 56 : half_mode = V32QImode;
18719 56 : goto quarter;
18720 :
18721 71 : case E_V32HImode:
18722 71 : quarter_mode = V8HImode;
18723 71 : half_mode = V16HImode;
18724 71 : goto quarter;
18725 :
18726 287 : case E_V32HFmode:
18727 287 : quarter_mode = V8HFmode;
18728 287 : half_mode = V16HFmode;
18729 287 : goto quarter;
18730 :
18731 51 : case E_V32BFmode:
18732 51 : quarter_mode = V8BFmode;
18733 51 : half_mode = V16BFmode;
18734 51 : goto quarter;
18735 :
18736 465 : quarter:
18737 465 : n = GET_MODE_NUNITS (mode);
18738 17137 : for (i = 0; i < n; i++)
18739 16672 : ops[i] = XVECEXP (vals, 0, i);
18740 465 : op0 = gen_reg_rtx (quarter_mode);
18741 465 : op1 = gen_reg_rtx (quarter_mode);
18742 465 : op2 = gen_reg_rtx (quarter_mode);
18743 465 : op3 = gen_reg_rtx (quarter_mode);
18744 465 : op4 = gen_reg_rtx (half_mode);
18745 465 : op5 = gen_reg_rtx (half_mode);
18746 465 : ix86_expand_vector_init_interleave (quarter_mode, op0, ops,
18747 : n >> 3);
18748 465 : ix86_expand_vector_init_interleave (quarter_mode, op1,
18749 465 : &ops [n >> 2], n >> 3);
18750 465 : ix86_expand_vector_init_interleave (quarter_mode, op2,
18751 465 : &ops [n >> 1], n >> 3);
18752 465 : ix86_expand_vector_init_interleave (quarter_mode, op3,
18753 465 : &ops [(n >> 1) | (n >> 2)], n >> 3);
18754 465 : emit_insn (gen_rtx_SET (op4, gen_rtx_VEC_CONCAT (half_mode, op0, op1)));
18755 465 : emit_insn (gen_rtx_SET (op5, gen_rtx_VEC_CONCAT (half_mode, op2, op3)));
18756 465 : emit_insn (gen_rtx_SET (target, gen_rtx_VEC_CONCAT (mode, op4, op5)));
18757 465 : return;
18758 :
18759 389 : case E_V16QImode:
18760 389 : if (!TARGET_SSE4_1)
18761 : break;
18762 : /* FALLTHRU */
18763 :
18764 575 : case E_V8HImode:
18765 575 : if (!TARGET_SSE2)
18766 : break;
18767 :
18768 : /* Don't use ix86_expand_vector_init_interleave if we can't
18769 : move from GPR to SSE register directly. */
18770 575 : if (!TARGET_INTER_UNIT_MOVES_TO_VEC)
18771 : break;
18772 : /* FALLTHRU */
18773 :
18774 1149 : case E_V8HFmode:
18775 1149 : case E_V8BFmode:
18776 :
18777 1149 : n = GET_MODE_NUNITS (mode);
18778 10437 : for (i = 0; i < n; i++)
18779 9288 : ops[i] = XVECEXP (vals, 0, i);
18780 1149 : ix86_expand_vector_init_interleave (mode, target, ops, n >> 1);
18781 1149 : return;
18782 :
18783 : case E_V4HFmode:
18784 : case E_V4BFmode:
18785 : case E_V2HFmode:
18786 : case E_V2BFmode:
18787 8568 : int_inner_mode = HImode;
18788 : break;
18789 :
18790 : case E_V4HImode:
18791 : case E_V8QImode:
18792 :
18793 : case E_V2HImode:
18794 : case E_V4QImode:
18795 : break;
18796 :
18797 0 : default:
18798 0 : gcc_unreachable ();
18799 : }
18800 :
18801 8568 : {
18802 8568 : int i, j, n_elts, n_words, n_elt_per_word;
18803 8568 : machine_mode tmp_mode, inner_mode;
18804 8568 : rtx words[4], shift;
18805 :
18806 17210 : tmp_mode = (GET_MODE_SIZE (mode) < UNITS_PER_WORD) ? SImode : word_mode;
18807 :
18808 8568 : inner_mode = GET_MODE_INNER (mode);
18809 8568 : n_elts = GET_MODE_NUNITS (mode);
18810 17136 : n_words = GET_MODE_SIZE (mode) / GET_MODE_SIZE (tmp_mode);
18811 8568 : n_elt_per_word = n_elts / n_words;
18812 8568 : shift = GEN_INT (GET_MODE_BITSIZE (inner_mode));
18813 :
18814 17591 : for (i = 0; i < n_words; ++i)
18815 : {
18816 : rtx word = NULL_RTX;
18817 :
18818 48129 : for (j = 0; j < n_elt_per_word; ++j)
18819 : {
18820 39106 : rtx elt = XVECEXP (vals, 0, (i+1)*n_elt_per_word - j - 1);
18821 39106 : if (int_inner_mode != E_VOIDmode)
18822 : {
18823 310 : gcc_assert (TARGET_SSE2 && int_inner_mode == HImode);
18824 310 : rtx tmp = gen_reg_rtx (int_inner_mode);
18825 310 : elt = lowpart_subreg (int_inner_mode,
18826 : force_reg (inner_mode, elt),
18827 : inner_mode);
18828 310 : emit_move_insn (tmp, elt);
18829 310 : elt = tmp;
18830 : }
18831 39106 : elt = convert_modes (tmp_mode, inner_mode, elt, true);
18832 :
18833 39106 : if (j == 0)
18834 : word = elt;
18835 : else
18836 : {
18837 30083 : word = expand_simple_binop (tmp_mode, ASHIFT, word, shift,
18838 : NULL_RTX, 1, OPTAB_LIB_WIDEN);
18839 30083 : word = expand_simple_binop (tmp_mode, IOR, word, elt,
18840 : NULL_RTX, 1, OPTAB_LIB_WIDEN);
18841 : }
18842 : }
18843 :
18844 9023 : words[i] = word;
18845 : }
18846 :
18847 8568 : if (n_words == 1)
18848 8113 : emit_move_insn (target, gen_lowpart (mode, words[0]));
18849 455 : else if (n_words == 2)
18850 : {
18851 455 : gcc_assert (tmp_mode == DImode || tmp_mode == SImode);
18852 455 : machine_mode concat_mode = tmp_mode == DImode ? V2DImode : V2SImode;
18853 455 : rtx tmp = gen_reg_rtx (concat_mode);
18854 455 : vals = gen_rtx_PARALLEL (concat_mode, gen_rtvec_v (2, words));
18855 455 : ix86_expand_vector_init_general (mmx_ok, concat_mode, tmp, vals);
18856 455 : emit_move_insn (target, gen_lowpart (mode, tmp));
18857 : }
18858 0 : else if (n_words == 4)
18859 : {
18860 0 : rtx tmp = gen_reg_rtx (V4SImode);
18861 0 : gcc_assert (tmp_mode == SImode);
18862 0 : vals = gen_rtx_PARALLEL (V4SImode, gen_rtvec_v (4, words));
18863 0 : ix86_expand_vector_init_general (false, V4SImode, tmp, vals);
18864 0 : emit_move_insn (target, gen_lowpart (mode, tmp));
18865 : }
18866 : else
18867 0 : gcc_unreachable ();
18868 : }
18869 : }
18870 :
18871 : /* Initialize vector TARGET via VALS. Suppress the use of MMX
18872 : instructions unless MMX_OK is true. */
18873 :
18874 : void
18875 133332 : ix86_expand_vector_init (bool mmx_ok, rtx target, rtx vals)
18876 : {
18877 133332 : machine_mode mode = GET_MODE (target);
18878 133332 : machine_mode inner_mode = GET_MODE_INNER (mode);
18879 133332 : int n_elts = GET_MODE_NUNITS (mode);
18880 133332 : int n_var = 0, one_var = -1;
18881 133332 : bool all_same = true, all_const_zero = true;
18882 133332 : int i;
18883 133332 : rtx x;
18884 :
18885 : /* Handle first initialization from vector elts. */
18886 133332 : if (n_elts != XVECLEN (vals, 0))
18887 : {
18888 1361 : rtx subtarget = target;
18889 1361 : x = XVECEXP (vals, 0, 0);
18890 2722 : gcc_assert (GET_MODE_INNER (GET_MODE (x)) == inner_mode);
18891 2722 : if (GET_MODE_NUNITS (GET_MODE (x)) * 2 == n_elts)
18892 : {
18893 1361 : rtx ops[2] = { XVECEXP (vals, 0, 0), XVECEXP (vals, 0, 1) };
18894 1361 : if (inner_mode == QImode
18895 1361 : || inner_mode == HImode
18896 1361 : || inner_mode == TImode
18897 : || inner_mode == HFmode
18898 : || inner_mode == BFmode)
18899 : {
18900 168 : unsigned int n_bits = n_elts * GET_MODE_SIZE (inner_mode);
18901 168 : scalar_mode elt_mode = inner_mode == TImode ? DImode : SImode;
18902 168 : n_bits /= GET_MODE_SIZE (elt_mode);
18903 168 : mode = mode_for_vector (elt_mode, n_bits).require ();
18904 168 : inner_mode = mode_for_vector (elt_mode, n_bits / 2).require ();
18905 168 : ops[0] = gen_lowpart (inner_mode, ops[0]);
18906 168 : ops[1] = gen_lowpart (inner_mode, ops[1]);
18907 168 : subtarget = gen_reg_rtx (mode);
18908 : }
18909 1361 : ix86_expand_vector_init_concat (mode, subtarget, ops, 2);
18910 1361 : if (subtarget != target)
18911 168 : emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
18912 1361 : return;
18913 : }
18914 0 : gcc_unreachable ();
18915 : }
18916 :
18917 484459 : for (i = 0; i < n_elts; ++i)
18918 : {
18919 352488 : x = XVECEXP (vals, 0, i);
18920 683924 : if (!(CONST_SCALAR_INT_P (x)
18921 335418 : || CONST_DOUBLE_P (x)
18922 : || CONST_FIXED_P (x)))
18923 331436 : n_var++, one_var = i;
18924 21052 : else if (x != CONST0_RTX (inner_mode))
18925 3404 : all_const_zero = false;
18926 352488 : if (i > 0 && !rtx_equal_p (x, XVECEXP (vals, 0, 0)))
18927 : all_same = false;
18928 : }
18929 :
18930 : /* Handle the zero vector as special case. */
18931 131971 : if (n_var == 0 && all_const_zero)
18932 : {
18933 310 : emit_move_insn (target, CONST0_RTX (mode));
18934 310 : return;
18935 : }
18936 :
18937 : /* If all values are identical, broadcast the value. */
18938 131661 : if (all_same
18939 139014 : && ix86_expand_vector_init_duplicate (mmx_ok, mode, target,
18940 7353 : XVECEXP (vals, 0, 0)))
18941 : return;
18942 :
18943 : /* Constants are best loaded from the constant pool. */
18944 125462 : if (n_var == 0)
18945 : {
18946 43 : emit_move_insn (target, gen_rtx_CONST_VECTOR (mode, XVEC (vals, 0)));
18947 43 : return;
18948 : }
18949 :
18950 : /* Values where only one field is non-constant are best loaded from
18951 : the pool and overwritten via move later. */
18952 125419 : if (n_var == 1)
18953 : {
18954 12165 : if (all_const_zero
18955 23017 : && ix86_expand_vector_init_one_nonzero (mmx_ok, mode, target,
18956 10852 : XVECEXP (vals, 0, one_var),
18957 : one_var))
18958 : return;
18959 :
18960 8367 : if (ix86_expand_vector_init_one_var (mmx_ok, mode, target, vals, one_var))
18961 : return;
18962 : }
18963 :
18964 121375 : ix86_expand_vector_init_general (mmx_ok, mode, target, vals);
18965 : }
18966 :
18967 : /* Implemented as
18968 : V setg (V v, int idx, T val)
18969 : {
18970 : V idxv = (V){idx, idx, idx, idx, idx, idx, idx, idx};
18971 : V valv = (V){val, val, val, val, val, val, val, val};
18972 : V mask = ((V){0, 1, 2, 3, 4, 5, 6, 7} == idxv);
18973 : v = (v & ~mask) | (valv & mask);
18974 : return v;
18975 : }. */
18976 : void
18977 129 : ix86_expand_vector_set_var (rtx target, rtx val, rtx idx)
18978 : {
18979 129 : rtx vec[64];
18980 129 : machine_mode mode = GET_MODE (target);
18981 129 : machine_mode cmp_mode = mode;
18982 129 : int n_elts = GET_MODE_NUNITS (mode);
18983 129 : rtx valv,idxv,constv,idx_tmp;
18984 129 : bool ok = false;
18985 :
18986 : /* 512-bits vector byte/word broadcast and comparison only available
18987 : under TARGET_AVX512BW, break 512-bits vector into two 256-bits vector
18988 : when without TARGET_AVX512BW. */
18989 129 : if ((mode == V32HImode || mode == V32HFmode || mode == V32BFmode
18990 123 : || mode == V64QImode)
18991 10 : && !TARGET_AVX512BW)
18992 : {
18993 3 : gcc_assert (TARGET_AVX512F);
18994 3 : rtx vhi, vlo, idx_hi;
18995 3 : machine_mode half_mode;
18996 3 : rtx (*extract_hi)(rtx, rtx);
18997 3 : rtx (*extract_lo)(rtx, rtx);
18998 :
18999 3 : if (mode == V32HImode)
19000 : {
19001 : half_mode = V16HImode;
19002 : extract_hi = gen_vec_extract_hi_v32hi;
19003 : extract_lo = gen_vec_extract_lo_v32hi;
19004 : }
19005 : else if (mode == V32HFmode)
19006 : {
19007 : half_mode = V16HFmode;
19008 : extract_hi = gen_vec_extract_hi_v32hf;
19009 : extract_lo = gen_vec_extract_lo_v32hf;
19010 : }
19011 : else if (mode == V32BFmode)
19012 : {
19013 : half_mode = V16BFmode;
19014 : extract_hi = gen_vec_extract_hi_v32bf;
19015 : extract_lo = gen_vec_extract_lo_v32bf;
19016 : }
19017 : else
19018 : {
19019 3 : half_mode = V32QImode;
19020 3 : extract_hi = gen_vec_extract_hi_v64qi;
19021 3 : extract_lo = gen_vec_extract_lo_v64qi;
19022 : }
19023 :
19024 3 : vhi = gen_reg_rtx (half_mode);
19025 3 : vlo = gen_reg_rtx (half_mode);
19026 3 : idx_hi = gen_reg_rtx (GET_MODE (idx));
19027 3 : emit_insn (extract_hi (vhi, target));
19028 3 : emit_insn (extract_lo (vlo, target));
19029 3 : vec[0] = idx_hi;
19030 3 : vec[1] = idx;
19031 3 : vec[2] = GEN_INT (n_elts/2);
19032 3 : ix86_expand_binary_operator (MINUS, GET_MODE (idx), vec);
19033 3 : ix86_expand_vector_set_var (vhi, val, idx_hi);
19034 3 : ix86_expand_vector_set_var (vlo, val, idx);
19035 3 : emit_insn (gen_rtx_SET (target, gen_rtx_VEC_CONCAT (mode, vlo, vhi)));
19036 3 : return;
19037 : }
19038 :
19039 504 : if (FLOAT_MODE_P (GET_MODE_INNER (mode)))
19040 : {
19041 42 : switch (mode)
19042 : {
19043 : case E_V2DFmode:
19044 : cmp_mode = V2DImode;
19045 : break;
19046 6 : case E_V4DFmode:
19047 6 : cmp_mode = V4DImode;
19048 6 : break;
19049 4 : case E_V8DFmode:
19050 4 : cmp_mode = V8DImode;
19051 4 : break;
19052 2 : case E_V2SFmode:
19053 2 : cmp_mode = V2SImode;
19054 2 : break;
19055 6 : case E_V4SFmode:
19056 6 : cmp_mode = V4SImode;
19057 6 : break;
19058 6 : case E_V8SFmode:
19059 6 : cmp_mode = V8SImode;
19060 6 : break;
19061 5 : case E_V16SFmode:
19062 5 : cmp_mode = V16SImode;
19063 5 : break;
19064 1 : case E_V2HFmode:
19065 1 : case E_V2BFmode:
19066 1 : cmp_mode = V2HImode;
19067 1 : break;
19068 1 : case E_V4HFmode:
19069 1 : case E_V4BFmode:
19070 1 : cmp_mode = V4HImode;
19071 1 : break;
19072 : case E_V8HFmode:
19073 2 : cmp_mode = V8HImode;
19074 : break;
19075 : case E_V16HFmode:
19076 2 : cmp_mode = V16HImode;
19077 : break;
19078 : case E_V32HFmode:
19079 1 : cmp_mode = V32HImode;
19080 : break;
19081 : case E_V8BFmode:
19082 2 : cmp_mode = V8HImode;
19083 : break;
19084 : case E_V16BFmode:
19085 2 : cmp_mode = V16HImode;
19086 : break;
19087 : case E_V32BFmode:
19088 1 : cmp_mode = V32HImode;
19089 : break;
19090 0 : default:
19091 0 : gcc_unreachable ();
19092 : }
19093 : }
19094 :
19095 1604 : for (int i = 0; i != n_elts; i++)
19096 1478 : vec[i] = GEN_INT (i);
19097 126 : constv = gen_rtx_CONST_VECTOR (cmp_mode, gen_rtvec_v (n_elts, vec));
19098 126 : valv = gen_reg_rtx (mode);
19099 126 : idxv = gen_reg_rtx (cmp_mode);
19100 252 : idx_tmp = convert_to_mode (GET_MODE_INNER (cmp_mode), idx, 1);
19101 :
19102 126 : ok = ix86_expand_vector_init_duplicate (TARGET_MMX_WITH_SSE,
19103 : mode, valv, val);
19104 126 : gcc_assert (ok);
19105 126 : ok = ix86_expand_vector_init_duplicate (TARGET_MMX_WITH_SSE,
19106 : cmp_mode, idxv, idx_tmp);
19107 126 : gcc_assert (ok);
19108 126 : vec[0] = target;
19109 126 : vec[1] = valv;
19110 126 : vec[2] = target;
19111 126 : vec[3] = gen_rtx_EQ (mode, idxv, constv);
19112 126 : vec[4] = idxv;
19113 126 : vec[5] = constv;
19114 126 : ok = ix86_expand_int_vcond (vec);
19115 126 : gcc_assert (ok);
19116 : }
19117 :
19118 : void
19119 8606 : ix86_expand_vector_set (bool mmx_ok, rtx target, rtx val, int elt)
19120 : {
19121 8606 : machine_mode mode = GET_MODE (target);
19122 8606 : machine_mode inner_mode = GET_MODE_INNER (mode);
19123 8606 : machine_mode half_mode;
19124 8606 : bool use_vec_merge = false;
19125 8606 : bool blendm_const = false;
19126 8606 : rtx tmp;
19127 8606 : static rtx (*gen_extract[8][2]) (rtx, rtx)
19128 : = {
19129 : { gen_vec_extract_lo_v32qi, gen_vec_extract_hi_v32qi },
19130 : { gen_vec_extract_lo_v16hi, gen_vec_extract_hi_v16hi },
19131 : { gen_vec_extract_lo_v8si, gen_vec_extract_hi_v8si },
19132 : { gen_vec_extract_lo_v4di, gen_vec_extract_hi_v4di },
19133 : { gen_vec_extract_lo_v8sf, gen_vec_extract_hi_v8sf },
19134 : { gen_vec_extract_lo_v4df, gen_vec_extract_hi_v4df },
19135 : { gen_vec_extract_lo_v16hf, gen_vec_extract_hi_v16hf },
19136 : { gen_vec_extract_lo_v16bf, gen_vec_extract_hi_v16bf }
19137 : };
19138 8606 : static rtx (*gen_insert[8][2]) (rtx, rtx, rtx)
19139 : = {
19140 : { gen_vec_set_lo_v32qi, gen_vec_set_hi_v32qi },
19141 : { gen_vec_set_lo_v16hi, gen_vec_set_hi_v16hi },
19142 : { gen_vec_set_lo_v8si, gen_vec_set_hi_v8si },
19143 : { gen_vec_set_lo_v4di, gen_vec_set_hi_v4di },
19144 : { gen_vec_set_lo_v8sf, gen_vec_set_hi_v8sf },
19145 : { gen_vec_set_lo_v4df, gen_vec_set_hi_v4df },
19146 : { gen_vec_set_lo_v16hf, gen_vec_set_hi_v16hf },
19147 : { gen_vec_set_lo_v16bf, gen_vec_set_hi_v16bf },
19148 : };
19149 8606 : int i, j, n;
19150 8606 : machine_mode mmode = VOIDmode;
19151 8606 : rtx (*gen_blendm) (rtx, rtx, rtx, rtx);
19152 :
19153 8606 : switch (mode)
19154 : {
19155 187 : case E_V2SImode:
19156 187 : use_vec_merge = TARGET_MMX_WITH_SSE && TARGET_SSE4_1;
19157 : if (use_vec_merge)
19158 : break;
19159 : /* FALLTHRU */
19160 :
19161 170 : case E_V2SFmode:
19162 170 : if (mmx_ok)
19163 : {
19164 168 : tmp = gen_reg_rtx (GET_MODE_INNER (mode));
19165 168 : ix86_expand_vector_extract (true, tmp, target, 1 - elt);
19166 168 : if (elt == 0)
19167 0 : tmp = gen_rtx_VEC_CONCAT (mode, val, tmp);
19168 : else
19169 168 : tmp = gen_rtx_VEC_CONCAT (mode, tmp, val);
19170 168 : emit_insn (gen_rtx_SET (target, tmp));
19171 168 : return;
19172 : }
19173 : break;
19174 :
19175 234 : case E_V2DImode:
19176 234 : use_vec_merge = TARGET_SSE4_1 && TARGET_64BIT;
19177 88 : if (use_vec_merge)
19178 : break;
19179 :
19180 88 : tmp = gen_reg_rtx (GET_MODE_INNER (mode));
19181 88 : ix86_expand_vector_extract (false, tmp, target, 1 - elt);
19182 88 : if (elt == 0)
19183 53 : tmp = gen_rtx_VEC_CONCAT (mode, val, tmp);
19184 : else
19185 35 : tmp = gen_rtx_VEC_CONCAT (mode, tmp, val);
19186 88 : emit_insn (gen_rtx_SET (target, tmp));
19187 88 : return;
19188 :
19189 126 : case E_V2DFmode:
19190 : /* NB: For ELT == 0, use standard scalar operation patterns which
19191 : preserve the rest of the vector for combiner:
19192 :
19193 : (vec_merge:V2DF
19194 : (vec_duplicate:V2DF (reg:DF))
19195 : (reg:V2DF)
19196 : (const_int 1))
19197 : */
19198 126 : if (elt == 0)
19199 64 : goto do_vec_merge;
19200 :
19201 62 : {
19202 62 : rtx op0, op1;
19203 :
19204 : /* For the two element vectors, we implement a VEC_CONCAT with
19205 : the extraction of the other element. */
19206 :
19207 62 : tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (1, GEN_INT (1 - elt)));
19208 62 : tmp = gen_rtx_VEC_SELECT (inner_mode, target, tmp);
19209 :
19210 62 : if (elt == 0)
19211 : op0 = val, op1 = tmp;
19212 : else
19213 62 : op0 = tmp, op1 = val;
19214 :
19215 62 : tmp = gen_rtx_VEC_CONCAT (mode, op0, op1);
19216 62 : emit_insn (gen_rtx_SET (target, tmp));
19217 : }
19218 62 : return;
19219 :
19220 574 : case E_V4SFmode:
19221 574 : use_vec_merge = TARGET_SSE4_1;
19222 574 : if (use_vec_merge)
19223 : break;
19224 :
19225 62 : switch (elt)
19226 : {
19227 : case 0:
19228 : use_vec_merge = true;
19229 : break;
19230 :
19231 1 : case 1:
19232 : /* tmp = target = A B C D */
19233 1 : tmp = copy_to_reg (target);
19234 : /* target = A A B B */
19235 1 : emit_insn (gen_vec_interleave_lowv4sf (target, target, target));
19236 : /* target = X A B B */
19237 1 : ix86_expand_vector_set (false, target, val, 0);
19238 : /* target = A X C D */
19239 1 : emit_insn (gen_sse_shufps_v4sf (target, target, tmp,
19240 : const1_rtx, const0_rtx,
19241 : GEN_INT (2+4), GEN_INT (3+4)));
19242 1 : return;
19243 :
19244 0 : case 2:
19245 : /* tmp = target = A B C D */
19246 0 : tmp = copy_to_reg (target);
19247 : /* tmp = X B C D */
19248 0 : ix86_expand_vector_set (false, tmp, val, 0);
19249 : /* target = A B X D */
19250 0 : emit_insn (gen_sse_shufps_v4sf (target, target, tmp,
19251 : const0_rtx, const1_rtx,
19252 : GEN_INT (0+4), GEN_INT (3+4)));
19253 0 : return;
19254 :
19255 4 : case 3:
19256 : /* tmp = target = A B C D */
19257 4 : tmp = copy_to_reg (target);
19258 : /* tmp = X B C D */
19259 4 : ix86_expand_vector_set (false, tmp, val, 0);
19260 : /* target = A B X D */
19261 4 : emit_insn (gen_sse_shufps_v4sf (target, target, tmp,
19262 : const0_rtx, const1_rtx,
19263 : GEN_INT (2+4), GEN_INT (0+4)));
19264 4 : return;
19265 :
19266 0 : default:
19267 0 : gcc_unreachable ();
19268 : }
19269 : break;
19270 :
19271 455 : case E_V4SImode:
19272 455 : use_vec_merge = TARGET_SSE4_1;
19273 455 : if (use_vec_merge)
19274 : break;
19275 :
19276 : /* Element 0 handled by vec_merge below. */
19277 289 : if (elt == 0)
19278 : {
19279 : use_vec_merge = true;
19280 : break;
19281 : }
19282 :
19283 92 : if (TARGET_SSE2)
19284 : {
19285 : /* With SSE2, use integer shuffles to swap element 0 and ELT,
19286 : store into element 0, then shuffle them back. */
19287 :
19288 92 : rtx order[4];
19289 :
19290 92 : order[0] = GEN_INT (elt);
19291 92 : order[1] = const1_rtx;
19292 92 : order[2] = const2_rtx;
19293 92 : order[3] = GEN_INT (3);
19294 92 : order[elt] = const0_rtx;
19295 :
19296 92 : emit_insn (gen_sse2_pshufd_1 (target, target, order[0],
19297 : order[1], order[2], order[3]));
19298 :
19299 92 : ix86_expand_vector_set (false, target, val, 0);
19300 :
19301 92 : emit_insn (gen_sse2_pshufd_1 (target, target, order[0],
19302 : order[1], order[2], order[3]));
19303 : }
19304 : else
19305 : {
19306 : /* For SSE1, we have to reuse the V4SF code. */
19307 0 : rtx t = gen_reg_rtx (V4SFmode);
19308 0 : emit_move_insn (t, gen_lowpart (V4SFmode, target));
19309 0 : ix86_expand_vector_set (false, t, gen_lowpart (SFmode, val), elt);
19310 0 : emit_move_insn (target, gen_lowpart (mode, t));
19311 : }
19312 : return;
19313 :
19314 3767 : case E_V8HImode:
19315 3767 : case E_V8HFmode:
19316 3767 : case E_V8BFmode:
19317 3767 : case E_V2HImode:
19318 3767 : case E_V2HFmode:
19319 3767 : case E_V2BFmode:
19320 3767 : use_vec_merge = TARGET_SSE2;
19321 3767 : break;
19322 52 : case E_V4HImode:
19323 52 : case E_V4HFmode:
19324 52 : case E_V4BFmode:
19325 52 : use_vec_merge = mmx_ok && (TARGET_SSE || TARGET_3DNOW_A);
19326 : break;
19327 :
19328 3067 : case E_V16QImode:
19329 3067 : case E_V4QImode:
19330 3067 : use_vec_merge = TARGET_SSE4_1;
19331 3067 : break;
19332 :
19333 1 : case E_V8QImode:
19334 1 : use_vec_merge = TARGET_MMX_WITH_SSE && TARGET_SSE4_1;
19335 : break;
19336 :
19337 3 : case E_V32QImode:
19338 3 : half_mode = V16QImode;
19339 3 : j = 0;
19340 3 : n = 16;
19341 3 : goto half;
19342 :
19343 17 : case E_V16HFmode:
19344 17 : case E_V16BFmode:
19345 : /* For ELT == 0, vec_setv8hf_0 can save 1 vpbroadcastw. */
19346 17 : if (TARGET_AVX2 && elt != 0)
19347 : {
19348 12 : mmode = SImode;
19349 12 : gen_blendm = ((mode == E_V16HFmode) ? gen_avx2_pblendph_1
19350 : : gen_avx2_pblendbf_1);
19351 : blendm_const = true;
19352 : break;
19353 : }
19354 : else
19355 : {
19356 5 : half_mode = ((mode == E_V16HFmode) ? V8HFmode : V8BFmode);
19357 3 : j = ((mode == E_V16HFmode) ? 6 : 7);
19358 5 : n = 8;
19359 5 : goto half;
19360 : }
19361 :
19362 5 : case E_V16HImode:
19363 5 : half_mode = V8HImode;
19364 5 : j = 1;
19365 5 : n = 8;
19366 5 : goto half;
19367 :
19368 15 : case E_V8SImode:
19369 15 : half_mode = V4SImode;
19370 15 : j = 2;
19371 15 : n = 4;
19372 15 : goto half;
19373 :
19374 15 : case E_V4DImode:
19375 15 : half_mode = V2DImode;
19376 15 : j = 3;
19377 15 : n = 2;
19378 15 : goto half;
19379 :
19380 4 : case E_V8SFmode:
19381 4 : half_mode = V4SFmode;
19382 4 : j = 4;
19383 4 : n = 4;
19384 4 : goto half;
19385 :
19386 6 : case E_V4DFmode:
19387 6 : half_mode = V2DFmode;
19388 6 : j = 5;
19389 6 : n = 2;
19390 6 : goto half;
19391 :
19392 53 : half:
19393 : /* Compute offset. */
19394 53 : i = elt / n;
19395 53 : elt %= n;
19396 :
19397 53 : gcc_assert (i <= 1);
19398 :
19399 : /* Extract the half. */
19400 53 : tmp = gen_reg_rtx (half_mode);
19401 53 : emit_insn (gen_extract[j][i] (tmp, target));
19402 :
19403 : /* Put val in tmp at elt. */
19404 53 : ix86_expand_vector_set (false, tmp, val, elt);
19405 :
19406 : /* Put it back. */
19407 53 : emit_insn (gen_insert[j][i] (target, target, tmp));
19408 53 : return;
19409 :
19410 8 : case E_V8DFmode:
19411 8 : if (TARGET_AVX512F)
19412 : {
19413 : mmode = QImode;
19414 : gen_blendm = gen_avx512f_blendmv8df;
19415 : }
19416 : break;
19417 :
19418 6 : case E_V8DImode:
19419 6 : if (TARGET_AVX512F)
19420 : {
19421 : mmode = QImode;
19422 : gen_blendm = gen_avx512f_blendmv8di;
19423 : }
19424 : break;
19425 :
19426 0 : case E_V16SFmode:
19427 0 : if (TARGET_AVX512F)
19428 : {
19429 : mmode = HImode;
19430 : gen_blendm = gen_avx512f_blendmv16sf;
19431 : }
19432 : break;
19433 :
19434 0 : case E_V16SImode:
19435 0 : if (TARGET_AVX512F)
19436 : {
19437 : mmode = HImode;
19438 : gen_blendm = gen_avx512f_blendmv16si;
19439 : }
19440 : break;
19441 :
19442 12 : case E_V32HFmode:
19443 12 : if (TARGET_AVX512BW)
19444 : {
19445 : mmode = SImode;
19446 : gen_blendm = gen_avx512bw_blendmv32hf;
19447 : }
19448 : break;
19449 12 : case E_V32BFmode:
19450 12 : if (TARGET_AVX512BW)
19451 : {
19452 : mmode = SImode;
19453 : gen_blendm = gen_avx512bw_blendmv32bf;
19454 : }
19455 : break;
19456 11 : case E_V32HImode:
19457 11 : if (TARGET_AVX512BW)
19458 : {
19459 : mmode = SImode;
19460 : gen_blendm = gen_avx512bw_blendmv32hi;
19461 : }
19462 7 : else if (TARGET_AVX512F)
19463 : {
19464 7 : half_mode = E_V8HImode;
19465 7 : n = 8;
19466 7 : goto quarter;
19467 : }
19468 : break;
19469 :
19470 12 : case E_V64QImode:
19471 12 : if (TARGET_AVX512BW)
19472 : {
19473 : mmode = DImode;
19474 : gen_blendm = gen_avx512bw_blendmv64qi;
19475 : }
19476 6 : else if (TARGET_AVX512F)
19477 : {
19478 6 : half_mode = E_V16QImode;
19479 6 : n = 16;
19480 6 : goto quarter;
19481 : }
19482 : break;
19483 :
19484 13 : quarter:
19485 : /* Compute offset. */
19486 13 : i = elt / n;
19487 13 : elt %= n;
19488 :
19489 13 : gcc_assert (i <= 3);
19490 :
19491 13 : {
19492 : /* Extract the quarter. */
19493 13 : tmp = gen_reg_rtx (V4SImode);
19494 13 : rtx tmp2 = gen_lowpart (V16SImode, target);
19495 13 : rtx mask = gen_reg_rtx (QImode);
19496 :
19497 13 : emit_move_insn (mask, constm1_rtx);
19498 13 : emit_insn (gen_avx512f_vextracti32x4_mask (tmp, tmp2, GEN_INT (i),
19499 : tmp, mask));
19500 :
19501 13 : tmp2 = gen_reg_rtx (half_mode);
19502 13 : emit_move_insn (tmp2, gen_lowpart (half_mode, tmp));
19503 13 : tmp = tmp2;
19504 :
19505 : /* Put val in tmp at elt. */
19506 13 : ix86_expand_vector_set (false, tmp, val, elt);
19507 :
19508 : /* Put it back. */
19509 13 : tmp2 = gen_reg_rtx (V16SImode);
19510 13 : rtx tmp3 = gen_lowpart (V16SImode, target);
19511 13 : mask = gen_reg_rtx (HImode);
19512 13 : emit_move_insn (mask, constm1_rtx);
19513 13 : tmp = gen_lowpart (V4SImode, tmp);
19514 13 : emit_insn (gen_avx512f_vinserti32x4_mask (tmp2, tmp3, tmp, GEN_INT (i),
19515 : tmp3, mask));
19516 13 : emit_move_insn (target, gen_lowpart (mode, tmp2));
19517 : }
19518 13 : return;
19519 :
19520 : default:
19521 : break;
19522 : }
19523 :
19524 6834 : if (mmode != VOIDmode)
19525 : {
19526 54 : tmp = gen_reg_rtx (mode);
19527 54 : emit_insn (gen_rtx_SET (tmp, gen_rtx_VEC_DUPLICATE (mode, val)));
19528 54 : rtx merge_mask = gen_int_mode (HOST_WIDE_INT_1U << elt, mmode);
19529 : /* The avx512*_blendm<mode> expanders have different operand order
19530 : from VEC_MERGE. In VEC_MERGE, the first input operand is used for
19531 : elements where the mask is set and second input operand otherwise,
19532 : in {sse,avx}*_*blend* the first input operand is used for elements
19533 : where the mask is clear and second input operand otherwise. */
19534 54 : if (!blendm_const)
19535 42 : merge_mask = force_reg (mmode, merge_mask);
19536 54 : emit_insn (gen_blendm (target, target, tmp, merge_mask));
19537 : }
19538 8007 : else if (use_vec_merge)
19539 : {
19540 7995 : do_vec_merge:
19541 8059 : if (!nonimmediate_operand (val, inner_mode))
19542 1 : val = force_reg (inner_mode, val);
19543 8059 : tmp = gen_rtx_VEC_DUPLICATE (mode, val);
19544 8059 : tmp = gen_rtx_VEC_MERGE (mode, tmp, target,
19545 : GEN_INT (HOST_WIDE_INT_1U << elt));
19546 8059 : emit_insn (gen_rtx_SET (target, tmp));
19547 : }
19548 : else
19549 : {
19550 24 : rtx mem = assign_stack_temp (mode, GET_MODE_SIZE (mode));
19551 :
19552 12 : emit_move_insn (mem, target);
19553 :
19554 24 : tmp = adjust_address (mem, inner_mode, elt * GET_MODE_SIZE (inner_mode));
19555 12 : emit_move_insn (tmp, val);
19556 :
19557 12 : emit_move_insn (target, mem);
19558 : }
19559 : }
19560 :
19561 : void
19562 112541 : ix86_expand_vector_extract (bool mmx_ok, rtx target, rtx vec, int elt)
19563 : {
19564 112541 : machine_mode mode = GET_MODE (vec);
19565 112541 : machine_mode inner_mode = GET_MODE_INNER (mode);
19566 112541 : bool use_vec_extr = false;
19567 112541 : rtx tmp;
19568 :
19569 112541 : switch (mode)
19570 : {
19571 8577 : case E_V2SImode:
19572 8577 : use_vec_extr = TARGET_MMX_WITH_SSE && TARGET_SSE4_1;
19573 : if (use_vec_extr)
19574 : break;
19575 : /* FALLTHRU */
19576 :
19577 9790 : case E_V2SFmode:
19578 9790 : if (!mmx_ok)
19579 : break;
19580 : /* FALLTHRU */
19581 :
19582 : case E_V2DFmode:
19583 : case E_V2DImode:
19584 : case E_V2TImode:
19585 : case E_V4TImode:
19586 : use_vec_extr = true;
19587 : break;
19588 :
19589 7931 : case E_V4SFmode:
19590 7931 : use_vec_extr = TARGET_SSE4_1;
19591 7931 : if (use_vec_extr)
19592 : break;
19593 :
19594 3925 : switch (elt)
19595 : {
19596 : case 0:
19597 : tmp = vec;
19598 : break;
19599 :
19600 1709 : case 1:
19601 1709 : case 3:
19602 1709 : tmp = gen_reg_rtx (mode);
19603 1709 : emit_insn (gen_sse_shufps_v4sf (tmp, vec, vec,
19604 : GEN_INT (elt), GEN_INT (elt),
19605 1709 : GEN_INT (elt+4), GEN_INT (elt+4)));
19606 1709 : break;
19607 :
19608 845 : case 2:
19609 845 : tmp = gen_reg_rtx (mode);
19610 845 : emit_insn (gen_vec_interleave_highv4sf (tmp, vec, vec));
19611 845 : break;
19612 :
19613 0 : default:
19614 0 : gcc_unreachable ();
19615 : }
19616 : vec = tmp;
19617 : use_vec_extr = true;
19618 : elt = 0;
19619 : break;
19620 :
19621 25246 : case E_V4SImode:
19622 25246 : use_vec_extr = TARGET_SSE4_1;
19623 25246 : if (use_vec_extr)
19624 : break;
19625 :
19626 19340 : if (TARGET_SSE2)
19627 : {
19628 19336 : switch (elt)
19629 : {
19630 : case 0:
19631 : tmp = vec;
19632 : break;
19633 :
19634 6479 : case 1:
19635 6479 : case 3:
19636 6479 : tmp = gen_reg_rtx (mode);
19637 6479 : emit_insn (gen_sse2_pshufd_1 (tmp, vec,
19638 : GEN_INT (elt), GEN_INT (elt),
19639 : GEN_INT (elt), GEN_INT (elt)));
19640 6479 : break;
19641 :
19642 3257 : case 2:
19643 3257 : tmp = gen_reg_rtx (mode);
19644 3257 : emit_insn (gen_vec_interleave_highv4si (tmp, vec, vec));
19645 3257 : break;
19646 :
19647 0 : default:
19648 0 : gcc_unreachable ();
19649 : }
19650 : vec = tmp;
19651 : use_vec_extr = true;
19652 : elt = 0;
19653 : }
19654 : else
19655 : {
19656 : /* For SSE1, we have to reuse the V4SF code. */
19657 4 : ix86_expand_vector_extract (false, gen_lowpart (SFmode, target),
19658 4 : gen_lowpart (V4SFmode, vec), elt);
19659 4 : return;
19660 : }
19661 : break;
19662 :
19663 6890 : case E_V8HImode:
19664 6890 : case E_V8HFmode:
19665 6890 : case E_V8BFmode:
19666 6890 : case E_V2HImode:
19667 6890 : case E_V2HFmode:
19668 6890 : case E_V2BFmode:
19669 6890 : use_vec_extr = TARGET_SSE2;
19670 6890 : break;
19671 868 : case E_V4HImode:
19672 868 : case E_V4HFmode:
19673 868 : case E_V4BFmode:
19674 868 : use_vec_extr = mmx_ok && (TARGET_SSE || TARGET_3DNOW_A);
19675 : break;
19676 :
19677 8414 : case E_V16QImode:
19678 8414 : use_vec_extr = TARGET_SSE4_1;
19679 8414 : if (!use_vec_extr
19680 6828 : && TARGET_SSE2
19681 6828 : && elt == 0
19682 12338 : && (optimize_insn_for_size_p () || TARGET_INTER_UNIT_MOVES_FROM_VEC))
19683 : {
19684 3923 : tmp = gen_reg_rtx (SImode);
19685 3923 : ix86_expand_vector_extract (false, tmp, gen_lowpart (V4SImode, vec),
19686 : 0);
19687 3923 : emit_insn (gen_rtx_SET (target, gen_lowpart (QImode, tmp)));
19688 3923 : return;
19689 : }
19690 : break;
19691 78 : case E_V4QImode:
19692 78 : use_vec_extr = TARGET_SSE4_1;
19693 78 : break;
19694 :
19695 663 : case E_V8SFmode:
19696 663 : if (TARGET_AVX)
19697 : {
19698 663 : tmp = gen_reg_rtx (V4SFmode);
19699 663 : if (elt < 4)
19700 326 : emit_insn (gen_vec_extract_lo_v8sf (tmp, vec));
19701 : else
19702 337 : emit_insn (gen_vec_extract_hi_v8sf (tmp, vec));
19703 663 : ix86_expand_vector_extract (false, target, tmp, elt & 3);
19704 663 : return;
19705 : }
19706 : break;
19707 :
19708 538 : case E_V4DFmode:
19709 538 : if (TARGET_AVX)
19710 : {
19711 538 : tmp = gen_reg_rtx (V2DFmode);
19712 538 : if (elt < 2)
19713 283 : emit_insn (gen_vec_extract_lo_v4df (tmp, vec));
19714 : else
19715 255 : emit_insn (gen_vec_extract_hi_v4df (tmp, vec));
19716 538 : ix86_expand_vector_extract (false, target, tmp, elt & 1);
19717 538 : return;
19718 : }
19719 : break;
19720 :
19721 253 : case E_V32QImode:
19722 253 : if (TARGET_AVX)
19723 : {
19724 253 : tmp = gen_reg_rtx (V16QImode);
19725 253 : if (elt < 16)
19726 130 : emit_insn (gen_vec_extract_lo_v32qi (tmp, vec));
19727 : else
19728 123 : emit_insn (gen_vec_extract_hi_v32qi (tmp, vec));
19729 253 : ix86_expand_vector_extract (false, target, tmp, elt & 15);
19730 253 : return;
19731 : }
19732 : break;
19733 :
19734 616 : case E_V16HImode:
19735 616 : if (TARGET_AVX)
19736 : {
19737 616 : tmp = gen_reg_rtx (V8HImode);
19738 616 : if (elt < 8)
19739 304 : emit_insn (gen_vec_extract_lo_v16hi (tmp, vec));
19740 : else
19741 312 : emit_insn (gen_vec_extract_hi_v16hi (tmp, vec));
19742 616 : ix86_expand_vector_extract (false, target, tmp, elt & 7);
19743 616 : return;
19744 : }
19745 : break;
19746 :
19747 1105 : case E_V8SImode:
19748 1105 : if (TARGET_AVX)
19749 : {
19750 1105 : tmp = gen_reg_rtx (V4SImode);
19751 1105 : if (elt < 4)
19752 535 : emit_insn (gen_vec_extract_lo_v8si (tmp, vec));
19753 : else
19754 570 : emit_insn (gen_vec_extract_hi_v8si (tmp, vec));
19755 1105 : ix86_expand_vector_extract (false, target, tmp, elt & 3);
19756 1105 : return;
19757 : }
19758 : break;
19759 :
19760 1350 : case E_V4DImode:
19761 1350 : if (TARGET_AVX)
19762 : {
19763 1350 : tmp = gen_reg_rtx (V2DImode);
19764 1350 : if (elt < 2)
19765 713 : emit_insn (gen_vec_extract_lo_v4di (tmp, vec));
19766 : else
19767 637 : emit_insn (gen_vec_extract_hi_v4di (tmp, vec));
19768 1350 : ix86_expand_vector_extract (false, target, tmp, elt & 1);
19769 1350 : return;
19770 : }
19771 : break;
19772 :
19773 8 : case E_V32HImode:
19774 8 : if (TARGET_AVX512BW)
19775 : {
19776 8 : tmp = gen_reg_rtx (V16HImode);
19777 8 : if (elt < 16)
19778 3 : emit_insn (gen_vec_extract_lo_v32hi (tmp, vec));
19779 : else
19780 5 : emit_insn (gen_vec_extract_hi_v32hi (tmp, vec));
19781 8 : ix86_expand_vector_extract (false, target, tmp, elt & 15);
19782 8 : return;
19783 : }
19784 : break;
19785 :
19786 10 : case E_V64QImode:
19787 10 : if (TARGET_AVX512BW)
19788 : {
19789 10 : tmp = gen_reg_rtx (V32QImode);
19790 10 : if (elt < 32)
19791 5 : emit_insn (gen_vec_extract_lo_v64qi (tmp, vec));
19792 : else
19793 5 : emit_insn (gen_vec_extract_hi_v64qi (tmp, vec));
19794 10 : ix86_expand_vector_extract (false, target, tmp, elt & 31);
19795 10 : return;
19796 : }
19797 : break;
19798 :
19799 311 : case E_V16SFmode:
19800 311 : tmp = gen_reg_rtx (V8SFmode);
19801 311 : if (elt < 8)
19802 157 : emit_insn (gen_vec_extract_lo_v16sf (tmp, vec));
19803 : else
19804 154 : emit_insn (gen_vec_extract_hi_v16sf (tmp, vec));
19805 311 : ix86_expand_vector_extract (false, target, tmp, elt & 7);
19806 311 : return;
19807 :
19808 296 : case E_V8DFmode:
19809 296 : tmp = gen_reg_rtx (V4DFmode);
19810 296 : if (elt < 4)
19811 160 : emit_insn (gen_vec_extract_lo_v8df (tmp, vec));
19812 : else
19813 136 : emit_insn (gen_vec_extract_hi_v8df (tmp, vec));
19814 296 : ix86_expand_vector_extract (false, target, tmp, elt & 3);
19815 296 : return;
19816 :
19817 236 : case E_V16SImode:
19818 236 : tmp = gen_reg_rtx (V8SImode);
19819 236 : if (elt < 8)
19820 125 : emit_insn (gen_vec_extract_lo_v16si (tmp, vec));
19821 : else
19822 111 : emit_insn (gen_vec_extract_hi_v16si (tmp, vec));
19823 236 : ix86_expand_vector_extract (false, target, tmp, elt & 7);
19824 236 : return;
19825 :
19826 674 : case E_V8DImode:
19827 674 : tmp = gen_reg_rtx (V4DImode);
19828 674 : if (elt < 4)
19829 387 : emit_insn (gen_vec_extract_lo_v8di (tmp, vec));
19830 : else
19831 287 : emit_insn (gen_vec_extract_hi_v8di (tmp, vec));
19832 674 : ix86_expand_vector_extract (false, target, tmp, elt & 3);
19833 674 : return;
19834 :
19835 45 : case E_V32HFmode:
19836 45 : case E_V32BFmode:
19837 45 : if (TARGET_AVX512BW)
19838 : {
19839 45 : tmp = (mode == E_V32HFmode
19840 45 : ? gen_reg_rtx (V16HFmode)
19841 7 : : gen_reg_rtx (V16BFmode));
19842 45 : if (elt < 16)
19843 31 : emit_insn (gen_vec_extract_lo (mode, tmp, vec));
19844 : else
19845 14 : emit_insn (gen_vec_extract_hi (mode, tmp, vec));
19846 45 : ix86_expand_vector_extract (false, target, tmp, elt & 15);
19847 45 : return;
19848 : }
19849 : break;
19850 :
19851 474 : case E_V16HFmode:
19852 474 : case E_V16BFmode:
19853 474 : if (TARGET_AVX)
19854 : {
19855 474 : tmp = (mode == E_V16HFmode
19856 474 : ? gen_reg_rtx (V8HFmode)
19857 339 : : gen_reg_rtx (V8BFmode));
19858 474 : if (elt < 8)
19859 249 : emit_insn (gen_vec_extract_lo (mode, tmp, vec));
19860 : else
19861 225 : emit_insn (gen_vec_extract_hi (mode, tmp, vec));
19862 474 : ix86_expand_vector_extract (false, target, tmp, elt & 7);
19863 474 : return;
19864 : }
19865 : break;
19866 :
19867 630 : case E_V8QImode:
19868 630 : use_vec_extr = TARGET_MMX_WITH_SSE && TARGET_SSE4_1;
19869 : /* ??? Could extract the appropriate HImode element and shift. */
19870 : break;
19871 :
19872 : default:
19873 : break;
19874 : }
19875 :
19876 27749 : if (use_vec_extr)
19877 : {
19878 93945 : tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (1, GEN_INT (elt)));
19879 93945 : tmp = gen_rtx_VEC_SELECT (inner_mode, vec, tmp);
19880 :
19881 : /* Let the rtl optimizers know about the zero extension performed. */
19882 93945 : if (inner_mode == QImode || inner_mode == HImode)
19883 : {
19884 8818 : rtx reg = gen_reg_rtx (SImode);
19885 8818 : tmp = gen_rtx_ZERO_EXTEND (SImode, tmp);
19886 8818 : emit_move_insn (reg, tmp);
19887 8818 : tmp = gen_lowpart (inner_mode, reg);
19888 8818 : SUBREG_PROMOTED_VAR_P (tmp) = 1;
19889 8818 : SUBREG_PROMOTED_SET (tmp, 1);
19890 : }
19891 :
19892 93945 : emit_move_insn (target, tmp);
19893 : }
19894 : else
19895 : {
19896 16180 : rtx mem = assign_stack_temp (mode, GET_MODE_SIZE (mode));
19897 :
19898 8090 : emit_move_insn (mem, vec);
19899 :
19900 16180 : tmp = adjust_address (mem, inner_mode, elt*GET_MODE_SIZE (inner_mode));
19901 8090 : emit_move_insn (target, tmp);
19902 : }
19903 : }
19904 :
19905 : /* Generate code to copy vector bits i / 2 ... i - 1 from vector SRC
19906 : to bits 0 ... i / 2 - 1 of vector DEST, which has the same mode.
19907 : The upper bits of DEST are undefined, though they shouldn't cause
19908 : exceptions (some bits from src or all zeros are ok). */
19909 :
19910 : static void
19911 41828 : emit_reduc_half (rtx dest, rtx src, int i)
19912 : {
19913 41828 : rtx tem, d = dest;
19914 41828 : switch (GET_MODE (src))
19915 : {
19916 6214 : case E_V4SFmode:
19917 6214 : if (i == 128)
19918 3107 : tem = gen_sse_movhlps (dest, src, src);
19919 : else
19920 3107 : tem = gen_sse_shufps_v4sf (dest, src, src, const1_rtx, const1_rtx,
19921 : GEN_INT (1 + 4), GEN_INT (1 + 4));
19922 : break;
19923 3355 : case E_V2DFmode:
19924 3355 : tem = gen_vec_interleave_highv2df (dest, src, src);
19925 3355 : break;
19926 76 : case E_V4QImode:
19927 76 : d = gen_reg_rtx (V1SImode);
19928 76 : tem = gen_mmx_lshrv1si3 (d, gen_lowpart (V1SImode, src),
19929 76 : GEN_INT (i / 2));
19930 76 : break;
19931 600 : case E_V8QImode:
19932 600 : case E_V4HImode:
19933 600 : d = gen_reg_rtx (V1DImode);
19934 600 : tem = gen_mmx_lshrv1di3 (d, gen_lowpart (V1DImode, src),
19935 600 : GEN_INT (i / 2));
19936 600 : break;
19937 31583 : case E_V16QImode:
19938 31583 : case E_V8HImode:
19939 31583 : case E_V8HFmode:
19940 31583 : case E_V4SImode:
19941 31583 : case E_V2DImode:
19942 31583 : if (TARGET_SSE_REDUCTION_PREFER_PSHUF)
19943 : {
19944 15 : if (i == 128)
19945 : {
19946 9 : d = gen_reg_rtx (V4SImode);
19947 18 : tem = gen_sse2_pshufd_1 (
19948 9 : d, force_reg (V4SImode, gen_lowpart (V4SImode, src)),
19949 : GEN_INT (2), GEN_INT (3), GEN_INT (2), GEN_INT (3));
19950 9 : break;
19951 : }
19952 6 : else if (i == 64)
19953 : {
19954 5 : d = gen_reg_rtx (V4SImode);
19955 10 : tem = gen_sse2_pshufd_1 (
19956 5 : d, force_reg (V4SImode, gen_lowpart (V4SImode, src)),
19957 : GEN_INT (1), GEN_INT (1), GEN_INT (1), GEN_INT (1));
19958 5 : break;
19959 : }
19960 1 : else if (i == 32)
19961 : {
19962 1 : d = gen_reg_rtx (V8HImode);
19963 2 : tem = gen_sse2_pshuflw_1 (
19964 1 : d, force_reg (V8HImode, gen_lowpart (V8HImode, src)),
19965 : GEN_INT (1), GEN_INT (1), GEN_INT (1), GEN_INT (1));
19966 1 : break;
19967 : }
19968 : }
19969 31568 : d = gen_reg_rtx (V1TImode);
19970 31568 : tem = gen_sse2_lshrv1ti3 (d, gen_lowpart (V1TImode, src),
19971 31568 : GEN_INT (i / 2));
19972 31568 : break;
19973 0 : case E_V8SFmode:
19974 0 : if (i == 256)
19975 0 : tem = gen_avx_vperm2f128v8sf3 (dest, src, src, const1_rtx);
19976 : else
19977 0 : tem = gen_avx_shufps256 (dest, src, src,
19978 : GEN_INT (i == 128 ? 2 + (3 << 2) : 1));
19979 : break;
19980 0 : case E_V4DFmode:
19981 0 : if (i == 256)
19982 0 : tem = gen_avx_vperm2f128v4df3 (dest, src, src, const1_rtx);
19983 : else
19984 0 : tem = gen_avx_shufpd256 (dest, src, src, const1_rtx);
19985 : break;
19986 0 : case E_V32QImode:
19987 0 : case E_V16HImode:
19988 0 : case E_V16HFmode:
19989 0 : case E_V8SImode:
19990 0 : case E_V4DImode:
19991 0 : if (i == 256)
19992 : {
19993 0 : if (GET_MODE (dest) != V4DImode)
19994 0 : d = gen_reg_rtx (V4DImode);
19995 0 : tem = gen_avx2_permv2ti (d, gen_lowpart (V4DImode, src),
19996 0 : gen_lowpart (V4DImode, src),
19997 : const1_rtx);
19998 : }
19999 : else
20000 : {
20001 0 : d = gen_reg_rtx (V2TImode);
20002 0 : tem = gen_avx2_lshrv2ti3 (d, gen_lowpart (V2TImode, src),
20003 0 : GEN_INT (i / 2));
20004 : }
20005 : break;
20006 0 : case E_V64QImode:
20007 0 : case E_V32HImode:
20008 0 : case E_V32HFmode:
20009 0 : if (i < 64)
20010 : {
20011 0 : d = gen_reg_rtx (V4TImode);
20012 0 : tem = gen_avx512bw_lshrv4ti3 (d, gen_lowpart (V4TImode, src),
20013 0 : GEN_INT (i / 2));
20014 0 : break;
20015 : }
20016 : /* FALLTHRU */
20017 0 : case E_V16SImode:
20018 0 : case E_V16SFmode:
20019 0 : case E_V8DImode:
20020 0 : case E_V8DFmode:
20021 0 : if (i > 128)
20022 0 : tem = gen_avx512f_shuf_i32x4_1 (gen_lowpart (V16SImode, dest),
20023 0 : gen_lowpart (V16SImode, src),
20024 0 : gen_lowpart (V16SImode, src),
20025 : GEN_INT (0x4 + (i == 512 ? 4 : 0)),
20026 : GEN_INT (0x5 + (i == 512 ? 4 : 0)),
20027 : GEN_INT (0x6 + (i == 512 ? 4 : 0)),
20028 : GEN_INT (0x7 + (i == 512 ? 4 : 0)),
20029 : GEN_INT (0xC), GEN_INT (0xD),
20030 : GEN_INT (0xE), GEN_INT (0xF),
20031 : GEN_INT (0x10), GEN_INT (0x11),
20032 : GEN_INT (0x12), GEN_INT (0x13),
20033 : GEN_INT (0x14), GEN_INT (0x15),
20034 : GEN_INT (0x16), GEN_INT (0x17));
20035 : else
20036 0 : tem = gen_avx512f_pshufd_1 (gen_lowpart (V16SImode, dest),
20037 0 : gen_lowpart (V16SImode, src),
20038 : GEN_INT (i == 128 ? 0x2 : 0x1),
20039 : GEN_INT (0x3),
20040 : GEN_INT (0x3),
20041 : GEN_INT (0x3),
20042 : GEN_INT (i == 128 ? 0x6 : 0x5),
20043 : GEN_INT (0x7),
20044 : GEN_INT (0x7),
20045 : GEN_INT (0x7),
20046 : GEN_INT (i == 128 ? 0xA : 0x9),
20047 : GEN_INT (0xB),
20048 : GEN_INT (0xB),
20049 : GEN_INT (0xB),
20050 : GEN_INT (i == 128 ? 0xE : 0xD),
20051 : GEN_INT (0xF),
20052 : GEN_INT (0xF),
20053 : GEN_INT (0xF));
20054 : break;
20055 0 : default:
20056 0 : gcc_unreachable ();
20057 : }
20058 41828 : emit_insn (tem);
20059 41828 : if (d != dest)
20060 32259 : emit_move_insn (dest, gen_lowpart (GET_MODE (dest), d));
20061 41828 : }
20062 :
20063 : /* Expand a vector reduction. FN is the binary pattern to reduce;
20064 : DEST is the destination; IN is the input vector. */
20065 :
20066 : void
20067 20760 : ix86_expand_reduc (rtx (*fn) (rtx, rtx, rtx), rtx dest, rtx in)
20068 : {
20069 20760 : rtx half, dst, vec = in;
20070 20760 : machine_mode mode = GET_MODE (in);
20071 20760 : int i;
20072 :
20073 : /* SSE4 has a special instruction for V8HImode UMIN reduction. */
20074 20760 : if (TARGET_SSE4_1
20075 10026 : && mode == V8HImode
20076 780 : && fn == gen_uminv8hi3)
20077 : {
20078 4 : emit_insn (gen_sse4_1_phminposuw (dest, in));
20079 4 : return;
20080 : }
20081 :
20082 41512 : for (i = GET_MODE_BITSIZE (mode);
20083 125168 : i > GET_MODE_UNIT_BITSIZE (mode);
20084 41828 : i >>= 1)
20085 : {
20086 41828 : half = gen_reg_rtx (mode);
20087 41828 : emit_reduc_half (half, vec, i);
20088 83656 : if (i == GET_MODE_UNIT_BITSIZE (mode) * 2)
20089 : dst = dest;
20090 : else
20091 21072 : dst = gen_reg_rtx (mode);
20092 41828 : emit_insn (fn (dst, half, vec));
20093 41828 : vec = dst;
20094 : }
20095 : }
20096 :
20097 : /* Output code to perform a conditional jump to LABEL, if C2 flag in
20098 : FP status register is set. */
20099 :
20100 : void
20101 285 : ix86_emit_fp_unordered_jump (rtx label)
20102 : {
20103 285 : rtx reg = gen_reg_rtx (HImode);
20104 285 : rtx_insn *insn;
20105 285 : rtx temp;
20106 :
20107 285 : emit_insn (gen_x86_fnstsw_1 (reg));
20108 :
20109 285 : if (TARGET_SAHF && (TARGET_USE_SAHF || optimize_insn_for_size_p ()))
20110 : {
20111 37 : emit_insn (gen_x86_sahf_1 (reg));
20112 :
20113 37 : temp = gen_rtx_REG (CCmode, FLAGS_REG);
20114 37 : temp = gen_rtx_UNORDERED (VOIDmode, temp, const0_rtx);
20115 : }
20116 : else
20117 : {
20118 248 : emit_insn (gen_testqi_ext_1_ccno (reg, GEN_INT (0x04)));
20119 :
20120 248 : temp = gen_rtx_REG (CCNOmode, FLAGS_REG);
20121 248 : temp = gen_rtx_NE (VOIDmode, temp, const0_rtx);
20122 : }
20123 :
20124 285 : temp = gen_rtx_IF_THEN_ELSE (VOIDmode, temp,
20125 : gen_rtx_LABEL_REF (VOIDmode, label),
20126 : pc_rtx);
20127 285 : insn = emit_jump_insn (gen_rtx_SET (pc_rtx, temp));
20128 285 : predict_jump (REG_BR_PROB_BASE * 10 / 100);
20129 285 : JUMP_LABEL (insn) = label;
20130 285 : }
20131 :
20132 : /* Output code to perform an sinh XFmode calculation. */
20133 :
20134 : void
20135 2 : ix86_emit_i387_sinh (rtx op0, rtx op1)
20136 : {
20137 2 : rtx e1 = gen_reg_rtx (XFmode);
20138 2 : rtx e2 = gen_reg_rtx (XFmode);
20139 2 : rtx scratch = gen_reg_rtx (HImode);
20140 2 : rtx flags = gen_rtx_REG (CCNOmode, FLAGS_REG);
20141 2 : rtx half = const_double_from_real_value (dconsthalf, XFmode);
20142 2 : rtx cst1, tmp;
20143 2 : rtx_code_label *jump_label = gen_label_rtx ();
20144 2 : rtx_insn *insn;
20145 :
20146 : /* scratch = fxam (op1) */
20147 2 : emit_insn (gen_fxamxf2_i387 (scratch, op1));
20148 :
20149 : /* e1 = expm1 (|op1|) */
20150 2 : emit_insn (gen_absxf2 (e2, op1));
20151 2 : emit_insn (gen_expm1xf2 (e1, e2));
20152 :
20153 : /* e2 = e1 / (e1 + 1.0) + e1 */
20154 2 : cst1 = force_reg (XFmode, CONST1_RTX (XFmode));
20155 2 : emit_insn (gen_addxf3 (e2, e1, cst1));
20156 2 : emit_insn (gen_divxf3 (e2, e1, e2));
20157 2 : emit_insn (gen_addxf3 (e2, e2, e1));
20158 :
20159 : /* flags = signbit (op1) */
20160 2 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x02)));
20161 :
20162 : /* if (flags) then e2 = -e2 */
20163 2 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode,
20164 : gen_rtx_EQ (VOIDmode, flags, const0_rtx),
20165 : gen_rtx_LABEL_REF (VOIDmode, jump_label),
20166 : pc_rtx);
20167 2 : insn = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
20168 2 : predict_jump (REG_BR_PROB_BASE * 50 / 100);
20169 2 : JUMP_LABEL (insn) = jump_label;
20170 :
20171 2 : emit_insn (gen_negxf2 (e2, e2));
20172 :
20173 2 : emit_label (jump_label);
20174 2 : LABEL_NUSES (jump_label) = 1;
20175 :
20176 : /* op0 = 0.5 * e2 */
20177 2 : half = force_reg (XFmode, half);
20178 2 : emit_insn (gen_mulxf3 (op0, e2, half));
20179 2 : }
20180 :
20181 : /* Output code to perform an cosh XFmode calculation. */
20182 :
20183 : void
20184 3 : ix86_emit_i387_cosh (rtx op0, rtx op1)
20185 : {
20186 3 : rtx e1 = gen_reg_rtx (XFmode);
20187 3 : rtx e2 = gen_reg_rtx (XFmode);
20188 3 : rtx half = const_double_from_real_value (dconsthalf, XFmode);
20189 3 : rtx cst1;
20190 :
20191 : /* e1 = exp (op1) */
20192 3 : emit_insn (gen_expxf2 (e1, op1));
20193 :
20194 : /* e2 = e1 + 1.0 / e1 */
20195 3 : cst1 = force_reg (XFmode, CONST1_RTX (XFmode));
20196 3 : emit_insn (gen_divxf3 (e2, cst1, e1));
20197 3 : emit_insn (gen_addxf3 (e2, e1, e2));
20198 :
20199 : /* op0 = 0.5 * e2 */
20200 3 : half = force_reg (XFmode, half);
20201 3 : emit_insn (gen_mulxf3 (op0, e2, half));
20202 3 : }
20203 :
20204 : /* Output code to perform an tanh XFmode calculation. */
20205 :
20206 : void
20207 1 : ix86_emit_i387_tanh (rtx op0, rtx op1)
20208 : {
20209 1 : rtx e1 = gen_reg_rtx (XFmode);
20210 1 : rtx e2 = gen_reg_rtx (XFmode);
20211 1 : rtx scratch = gen_reg_rtx (HImode);
20212 1 : rtx flags = gen_rtx_REG (CCNOmode, FLAGS_REG);
20213 1 : rtx cst2, tmp;
20214 1 : rtx_code_label *jump_label = gen_label_rtx ();
20215 1 : rtx_insn *insn;
20216 :
20217 : /* scratch = fxam (op1) */
20218 1 : emit_insn (gen_fxamxf2_i387 (scratch, op1));
20219 :
20220 : /* e1 = expm1 (-|2 * op1|) */
20221 1 : emit_insn (gen_addxf3 (e2, op1, op1));
20222 1 : emit_insn (gen_absxf2 (e2, e2));
20223 1 : emit_insn (gen_negxf2 (e2, e2));
20224 1 : emit_insn (gen_expm1xf2 (e1, e2));
20225 :
20226 : /* e2 = e1 / (e1 + 2.0) */
20227 1 : cst2 = force_reg (XFmode, CONST2_RTX (XFmode));
20228 1 : emit_insn (gen_addxf3 (e2, e1, cst2));
20229 1 : emit_insn (gen_divxf3 (e2, e1, e2));
20230 :
20231 : /* flags = signbit (op1) */
20232 1 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x02)));
20233 :
20234 : /* if (!flags) then e2 = -e2 */
20235 1 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode,
20236 : gen_rtx_NE (VOIDmode, flags, const0_rtx),
20237 : gen_rtx_LABEL_REF (VOIDmode, jump_label),
20238 : pc_rtx);
20239 1 : insn = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
20240 1 : predict_jump (REG_BR_PROB_BASE * 50 / 100);
20241 1 : JUMP_LABEL (insn) = jump_label;
20242 :
20243 1 : emit_insn (gen_negxf2 (e2, e2));
20244 :
20245 1 : emit_label (jump_label);
20246 1 : LABEL_NUSES (jump_label) = 1;
20247 :
20248 1 : emit_move_insn (op0, e2);
20249 1 : }
20250 :
20251 : /* Output code to perform an asinh XFmode calculation. */
20252 :
20253 : void
20254 0 : ix86_emit_i387_asinh (rtx op0, rtx op1)
20255 : {
20256 0 : rtx e1 = gen_reg_rtx (XFmode);
20257 0 : rtx e2 = gen_reg_rtx (XFmode);
20258 0 : rtx scratch = gen_reg_rtx (HImode);
20259 0 : rtx flags = gen_rtx_REG (CCNOmode, FLAGS_REG);
20260 0 : rtx cst1, tmp;
20261 0 : rtx_code_label *jump_label = gen_label_rtx ();
20262 0 : rtx_insn *insn;
20263 :
20264 : /* e2 = sqrt (op1^2 + 1.0) + 1.0 */
20265 0 : emit_insn (gen_mulxf3 (e1, op1, op1));
20266 0 : cst1 = force_reg (XFmode, CONST1_RTX (XFmode));
20267 0 : emit_insn (gen_addxf3 (e2, e1, cst1));
20268 0 : emit_insn (gen_sqrtxf2 (e2, e2));
20269 0 : emit_insn (gen_addxf3 (e2, e2, cst1));
20270 :
20271 : /* e1 = e1 / e2 */
20272 0 : emit_insn (gen_divxf3 (e1, e1, e2));
20273 :
20274 : /* scratch = fxam (op1) */
20275 0 : emit_insn (gen_fxamxf2_i387 (scratch, op1));
20276 :
20277 : /* e1 = e1 + |op1| */
20278 0 : emit_insn (gen_absxf2 (e2, op1));
20279 0 : emit_insn (gen_addxf3 (e1, e1, e2));
20280 :
20281 : /* e2 = log1p (e1) */
20282 0 : ix86_emit_i387_log1p (e2, e1);
20283 :
20284 : /* flags = signbit (op1) */
20285 0 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x02)));
20286 :
20287 : /* if (flags) then e2 = -e2 */
20288 0 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode,
20289 : gen_rtx_EQ (VOIDmode, flags, const0_rtx),
20290 : gen_rtx_LABEL_REF (VOIDmode, jump_label),
20291 : pc_rtx);
20292 0 : insn = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
20293 0 : predict_jump (REG_BR_PROB_BASE * 50 / 100);
20294 0 : JUMP_LABEL (insn) = jump_label;
20295 :
20296 0 : emit_insn (gen_negxf2 (e2, e2));
20297 :
20298 0 : emit_label (jump_label);
20299 0 : LABEL_NUSES (jump_label) = 1;
20300 :
20301 0 : emit_move_insn (op0, e2);
20302 0 : }
20303 :
20304 : /* Output code to perform an acosh XFmode calculation. */
20305 :
20306 : void
20307 0 : ix86_emit_i387_acosh (rtx op0, rtx op1)
20308 : {
20309 0 : rtx e1 = gen_reg_rtx (XFmode);
20310 0 : rtx e2 = gen_reg_rtx (XFmode);
20311 0 : rtx cst1 = force_reg (XFmode, CONST1_RTX (XFmode));
20312 :
20313 : /* e2 = sqrt (op1 + 1.0) */
20314 0 : emit_insn (gen_addxf3 (e2, op1, cst1));
20315 0 : emit_insn (gen_sqrtxf2 (e2, e2));
20316 :
20317 : /* e1 = sqrt (op1 - 1.0) */
20318 0 : emit_insn (gen_subxf3 (e1, op1, cst1));
20319 0 : emit_insn (gen_sqrtxf2 (e1, e1));
20320 :
20321 : /* e1 = e1 * e2 */
20322 0 : emit_insn (gen_mulxf3 (e1, e1, e2));
20323 :
20324 : /* e1 = e1 + op1 */
20325 0 : emit_insn (gen_addxf3 (e1, e1, op1));
20326 :
20327 : /* op0 = log (e1) */
20328 0 : emit_insn (gen_logxf2 (op0, e1));
20329 0 : }
20330 :
20331 : /* Output code to perform an atanh XFmode calculation. */
20332 :
20333 : void
20334 4 : ix86_emit_i387_atanh (rtx op0, rtx op1)
20335 : {
20336 4 : rtx e1 = gen_reg_rtx (XFmode);
20337 4 : rtx e2 = gen_reg_rtx (XFmode);
20338 4 : rtx scratch = gen_reg_rtx (HImode);
20339 4 : rtx flags = gen_rtx_REG (CCNOmode, FLAGS_REG);
20340 4 : rtx half = const_double_from_real_value (dconsthalf, XFmode);
20341 4 : rtx cst1, tmp;
20342 4 : rtx_code_label *jump_label = gen_label_rtx ();
20343 4 : rtx_insn *insn;
20344 :
20345 : /* scratch = fxam (op1) */
20346 4 : emit_insn (gen_fxamxf2_i387 (scratch, op1));
20347 :
20348 : /* e2 = |op1| */
20349 4 : emit_insn (gen_absxf2 (e2, op1));
20350 :
20351 : /* e1 = -(e2 + e2) / (e2 + 1.0) */
20352 4 : cst1 = force_reg (XFmode, CONST1_RTX (XFmode));
20353 4 : emit_insn (gen_addxf3 (e1, e2, cst1));
20354 4 : emit_insn (gen_addxf3 (e2, e2, e2));
20355 4 : emit_insn (gen_negxf2 (e2, e2));
20356 4 : emit_insn (gen_divxf3 (e1, e2, e1));
20357 :
20358 : /* e2 = log1p (e1) */
20359 4 : ix86_emit_i387_log1p (e2, e1);
20360 :
20361 : /* flags = signbit (op1) */
20362 4 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x02)));
20363 :
20364 : /* if (!flags) then e2 = -e2 */
20365 4 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode,
20366 : gen_rtx_NE (VOIDmode, flags, const0_rtx),
20367 : gen_rtx_LABEL_REF (VOIDmode, jump_label),
20368 : pc_rtx);
20369 4 : insn = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
20370 4 : predict_jump (REG_BR_PROB_BASE * 50 / 100);
20371 4 : JUMP_LABEL (insn) = jump_label;
20372 :
20373 4 : emit_insn (gen_negxf2 (e2, e2));
20374 :
20375 4 : emit_label (jump_label);
20376 4 : LABEL_NUSES (jump_label) = 1;
20377 :
20378 : /* op0 = 0.5 * e2 */
20379 4 : half = force_reg (XFmode, half);
20380 4 : emit_insn (gen_mulxf3 (op0, e2, half));
20381 4 : }
20382 :
20383 : /* Output code to perform a log1p XFmode calculation. */
20384 :
20385 : void
20386 5 : ix86_emit_i387_log1p (rtx op0, rtx op1)
20387 : {
20388 5 : rtx_code_label *label1 = gen_label_rtx ();
20389 5 : rtx_code_label *label2 = gen_label_rtx ();
20390 :
20391 5 : rtx tmp = gen_reg_rtx (XFmode);
20392 5 : rtx res = gen_reg_rtx (XFmode);
20393 5 : rtx cst, cstln2, cst1;
20394 5 : rtx_insn *insn;
20395 :
20396 : /* The emit_jump call emits pending stack adjust, make sure it is emitted
20397 : before the conditional jump, otherwise the stack adjustment will be
20398 : only conditional. */
20399 5 : do_pending_stack_adjust ();
20400 :
20401 5 : cst = const_double_from_real_value
20402 5 : (REAL_VALUE_ATOF ("0.29289321881345247561810596348408353", XFmode), XFmode);
20403 5 : cstln2 = force_reg (XFmode, standard_80387_constant_rtx (4)); /* fldln2 */
20404 :
20405 5 : emit_insn (gen_absxf2 (tmp, op1));
20406 :
20407 5 : cst = force_reg (XFmode, cst);
20408 5 : ix86_expand_branch (GE, tmp, cst, label1);
20409 5 : predict_jump (REG_BR_PROB_BASE * 10 / 100);
20410 5 : insn = get_last_insn ();
20411 5 : JUMP_LABEL (insn) = label1;
20412 :
20413 5 : emit_insn (gen_fyl2xp1xf3_i387 (res, op1, cstln2));
20414 5 : emit_jump (label2);
20415 :
20416 5 : emit_label (label1);
20417 5 : LABEL_NUSES (label1) = 1;
20418 :
20419 5 : cst1 = force_reg (XFmode, CONST1_RTX (XFmode));
20420 5 : emit_insn (gen_rtx_SET (tmp, gen_rtx_PLUS (XFmode, op1, cst1)));
20421 5 : emit_insn (gen_fyl2xxf3_i387 (res, tmp, cstln2));
20422 :
20423 5 : emit_label (label2);
20424 5 : LABEL_NUSES (label2) = 1;
20425 :
20426 5 : emit_move_insn (op0, res);
20427 5 : }
20428 :
20429 : /* Emit code for round calculation. */
20430 : void
20431 60 : ix86_emit_i387_round (rtx op0, rtx op1)
20432 : {
20433 60 : machine_mode inmode = GET_MODE (op1);
20434 60 : machine_mode outmode = GET_MODE (op0);
20435 60 : rtx e1 = gen_reg_rtx (XFmode);
20436 60 : rtx e2 = gen_reg_rtx (XFmode);
20437 60 : rtx scratch = gen_reg_rtx (HImode);
20438 60 : rtx flags = gen_rtx_REG (CCNOmode, FLAGS_REG);
20439 60 : rtx half = const_double_from_real_value (dconsthalf, XFmode);
20440 60 : rtx res = gen_reg_rtx (outmode);
20441 60 : rtx_code_label *jump_label = gen_label_rtx ();
20442 60 : rtx (*floor_insn) (rtx, rtx);
20443 60 : rtx (*neg_insn) (rtx, rtx);
20444 60 : rtx_insn *insn;
20445 60 : rtx tmp;
20446 :
20447 60 : switch (inmode)
20448 : {
20449 29 : case E_SFmode:
20450 29 : case E_DFmode:
20451 29 : tmp = gen_reg_rtx (XFmode);
20452 :
20453 29 : emit_insn (gen_rtx_SET (tmp, gen_rtx_FLOAT_EXTEND (XFmode, op1)));
20454 29 : op1 = tmp;
20455 29 : break;
20456 : case E_XFmode:
20457 : break;
20458 0 : default:
20459 0 : gcc_unreachable ();
20460 : }
20461 :
20462 60 : switch (outmode)
20463 : {
20464 : case E_SFmode:
20465 : floor_insn = gen_frndintxf2_floor;
20466 : neg_insn = gen_negsf2;
20467 : break;
20468 6 : case E_DFmode:
20469 6 : floor_insn = gen_frndintxf2_floor;
20470 6 : neg_insn = gen_negdf2;
20471 6 : break;
20472 10 : case E_XFmode:
20473 10 : floor_insn = gen_frndintxf2_floor;
20474 10 : neg_insn = gen_negxf2;
20475 10 : break;
20476 0 : case E_HImode:
20477 0 : floor_insn = gen_lfloorxfhi2;
20478 0 : neg_insn = gen_neghi2;
20479 0 : break;
20480 6 : case E_SImode:
20481 6 : floor_insn = gen_lfloorxfsi2;
20482 6 : neg_insn = gen_negsi2;
20483 6 : break;
20484 36 : case E_DImode:
20485 36 : floor_insn = gen_lfloorxfdi2;
20486 36 : neg_insn = gen_negdi2;
20487 36 : break;
20488 0 : default:
20489 0 : gcc_unreachable ();
20490 : }
20491 :
20492 : /* round(a) = sgn(a) * floor(fabs(a) + 0.5) */
20493 :
20494 : /* scratch = fxam(op1) */
20495 60 : emit_insn (gen_fxamxf2_i387 (scratch, op1));
20496 :
20497 : /* e1 = fabs(op1) */
20498 60 : emit_insn (gen_absxf2 (e1, op1));
20499 :
20500 : /* e2 = e1 + 0.5 */
20501 60 : half = force_reg (XFmode, half);
20502 60 : emit_insn (gen_rtx_SET (e2, gen_rtx_PLUS (XFmode, e1, half)));
20503 :
20504 : /* res = floor(e2) */
20505 60 : switch (outmode)
20506 : {
20507 8 : case E_SFmode:
20508 8 : case E_DFmode:
20509 8 : {
20510 8 : tmp = gen_reg_rtx (XFmode);
20511 :
20512 8 : emit_insn (floor_insn (tmp, e2));
20513 8 : emit_insn (gen_rtx_SET (res,
20514 : gen_rtx_UNSPEC (outmode, gen_rtvec (1, tmp),
20515 : UNSPEC_TRUNC_NOOP)));
20516 : }
20517 8 : break;
20518 52 : default:
20519 52 : emit_insn (floor_insn (res, e2));
20520 : }
20521 :
20522 : /* flags = signbit(a) */
20523 60 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x02)));
20524 :
20525 : /* if (flags) then res = -res */
20526 60 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode,
20527 : gen_rtx_EQ (VOIDmode, flags, const0_rtx),
20528 : gen_rtx_LABEL_REF (VOIDmode, jump_label),
20529 : pc_rtx);
20530 60 : insn = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
20531 60 : predict_jump (REG_BR_PROB_BASE * 50 / 100);
20532 60 : JUMP_LABEL (insn) = jump_label;
20533 :
20534 60 : emit_insn (neg_insn (res, res));
20535 :
20536 60 : emit_label (jump_label);
20537 60 : LABEL_NUSES (jump_label) = 1;
20538 :
20539 60 : emit_move_insn (op0, res);
20540 60 : }
20541 :
20542 : /* Output code to perform a Newton-Rhapson approximation of a single precision
20543 : floating point divide [http://en.wikipedia.org/wiki/N-th_root_algorithm]. */
20544 :
20545 : void
20546 56 : ix86_emit_swdivsf (rtx res, rtx a, rtx b, machine_mode mode)
20547 : {
20548 56 : rtx x0, x1, e0, e1;
20549 :
20550 56 : x0 = gen_reg_rtx (mode);
20551 56 : e0 = gen_reg_rtx (mode);
20552 56 : e1 = gen_reg_rtx (mode);
20553 56 : x1 = gen_reg_rtx (mode);
20554 :
20555 56 : b = force_reg (mode, b);
20556 :
20557 : /* x0 = rcp(b) estimate */
20558 56 : if (mode == V16SFmode || mode == V8DFmode)
20559 : {
20560 0 : emit_insn (gen_rtx_SET (x0, gen_rtx_UNSPEC (mode, gen_rtvec (1, b),
20561 : UNSPEC_RCP14)));
20562 : }
20563 : else
20564 56 : emit_insn (gen_rtx_SET (x0, gen_rtx_UNSPEC (mode, gen_rtvec (1, b),
20565 : UNSPEC_RCP)));
20566 :
20567 56 : unsigned vector_size = GET_MODE_SIZE (mode);
20568 :
20569 : /* (a - (rcp(b) * a * b)) * rcp(b) + rcp(b) * a
20570 : N-R step with 2 fma implementation. */
20571 56 : if (TARGET_FMA
20572 55 : || (TARGET_AVX512F && vector_size == 64)
20573 55 : || (TARGET_AVX512VL && (vector_size == 32 || vector_size == 16)))
20574 : {
20575 : /* e0 = x0 * a */
20576 1 : emit_insn (gen_rtx_SET (e0, gen_rtx_MULT (mode, x0, a)));
20577 : /* e1 = e0 * b - a */
20578 1 : emit_insn (gen_rtx_SET (e1, gen_rtx_FMA (mode, e0, b,
20579 : gen_rtx_NEG (mode, a))));
20580 : /* res = - e1 * x0 + e0 */
20581 1 : emit_insn (gen_rtx_SET (res, gen_rtx_FMA (mode,
20582 : gen_rtx_NEG (mode, e1),
20583 : x0, e0)));
20584 : }
20585 : else
20586 : /* a / b = a * ((rcp(b) + rcp(b)) - (b * rcp(b) * rcp (b))) */
20587 : {
20588 : /* e0 = x0 * b */
20589 55 : emit_insn (gen_rtx_SET (e0, gen_rtx_MULT (mode, x0, b)));
20590 :
20591 : /* e1 = x0 + x0 */
20592 55 : emit_insn (gen_rtx_SET (e1, gen_rtx_PLUS (mode, x0, x0)));
20593 :
20594 : /* e0 = x0 * e0 */
20595 55 : emit_insn (gen_rtx_SET (e0, gen_rtx_MULT (mode, x0, e0)));
20596 :
20597 : /* x1 = e1 - e0 */
20598 55 : emit_insn (gen_rtx_SET (x1, gen_rtx_MINUS (mode, e1, e0)));
20599 :
20600 : /* res = a * x1 */
20601 55 : emit_insn (gen_rtx_SET (res, gen_rtx_MULT (mode, a, x1)));
20602 : }
20603 56 : }
20604 :
20605 : /* Output code to perform a Newton-Rhapson approximation of a
20606 : single precision floating point [reciprocal] square root. */
20607 :
20608 : void
20609 85 : ix86_emit_swsqrtsf (rtx res, rtx a, machine_mode mode, bool recip)
20610 : {
20611 85 : rtx x0, e0, e1, e2, e3, mthree, mhalf;
20612 85 : REAL_VALUE_TYPE r;
20613 85 : int unspec;
20614 :
20615 85 : x0 = gen_reg_rtx (mode);
20616 85 : e0 = gen_reg_rtx (mode);
20617 85 : e1 = gen_reg_rtx (mode);
20618 85 : e2 = gen_reg_rtx (mode);
20619 85 : e3 = gen_reg_rtx (mode);
20620 :
20621 85 : real_from_integer (&r, VOIDmode, -3, SIGNED);
20622 85 : mthree = const_double_from_real_value (r, SFmode);
20623 :
20624 85 : real_arithmetic (&r, NEGATE_EXPR, &dconsthalf, NULL);
20625 85 : mhalf = const_double_from_real_value (r, SFmode);
20626 85 : unspec = UNSPEC_RSQRT;
20627 :
20628 85 : if (VECTOR_MODE_P (mode))
20629 : {
20630 66 : mthree = ix86_build_const_vector (mode, true, mthree);
20631 66 : mhalf = ix86_build_const_vector (mode, true, mhalf);
20632 : /* There is no 512-bit rsqrt. There is however rsqrt14. */
20633 132 : if (GET_MODE_SIZE (mode) == 64)
20634 0 : unspec = UNSPEC_RSQRT14;
20635 : }
20636 :
20637 : /* sqrt(a) = -0.5 * a * rsqrtss(a) * (a * rsqrtss(a) * rsqrtss(a) - 3.0)
20638 : rsqrt(a) = -0.5 * rsqrtss(a) * (a * rsqrtss(a) * rsqrtss(a) - 3.0) */
20639 :
20640 85 : a = force_reg (mode, a);
20641 :
20642 : /* x0 = rsqrt(a) estimate */
20643 85 : emit_insn (gen_rtx_SET (x0, gen_rtx_UNSPEC (mode, gen_rtvec (1, a),
20644 : unspec)));
20645 :
20646 : /* If (a == 0.0) Filter out infinity to prevent NaN for sqrt(0.0). */
20647 85 : if (!recip)
20648 : {
20649 57 : rtx zero = force_reg (mode, CONST0_RTX(mode));
20650 57 : rtx mask;
20651 :
20652 : /* Handle masked compare. */
20653 110 : if (VECTOR_MODE_P (mode) && GET_MODE_SIZE (mode) == 64)
20654 : {
20655 0 : mask = gen_reg_rtx (HImode);
20656 : /* Imm value 0x4 corresponds to not-equal comparison. */
20657 0 : emit_insn (gen_avx512f_cmpv16sf3 (mask, zero, a, GEN_INT (0x4)));
20658 0 : emit_insn (gen_avx512f_blendmv16sf (x0, zero, x0, mask));
20659 : }
20660 : else
20661 : {
20662 57 : mask = gen_reg_rtx (mode);
20663 57 : emit_insn (gen_rtx_SET (mask, gen_rtx_NE (mode, zero, a)));
20664 57 : emit_insn (gen_rtx_SET (x0, gen_rtx_AND (mode, x0, mask)));
20665 : }
20666 : }
20667 :
20668 85 : mthree = force_reg (mode, mthree);
20669 :
20670 : /* e0 = x0 * a */
20671 85 : emit_insn (gen_rtx_SET (e0, gen_rtx_MULT (mode, x0, a)));
20672 :
20673 85 : unsigned vector_size = GET_MODE_SIZE (mode);
20674 85 : if (TARGET_FMA
20675 77 : || (TARGET_AVX512F && vector_size == 64)
20676 77 : || (TARGET_AVX512VL && (vector_size == 32 || vector_size == 16)))
20677 16 : emit_insn (gen_rtx_SET (e2,
20678 : gen_rtx_FMA (mode, e0, x0, mthree)));
20679 : else
20680 : {
20681 : /* e1 = e0 * x0 */
20682 69 : emit_insn (gen_rtx_SET (e1, gen_rtx_MULT (mode, e0, x0)));
20683 :
20684 : /* e2 = e1 - 3. */
20685 69 : emit_insn (gen_rtx_SET (e2, gen_rtx_PLUS (mode, e1, mthree)));
20686 : }
20687 :
20688 85 : mhalf = force_reg (mode, mhalf);
20689 85 : if (recip)
20690 : /* e3 = -.5 * x0 */
20691 28 : emit_insn (gen_rtx_SET (e3, gen_rtx_MULT (mode, x0, mhalf)));
20692 : else
20693 : /* e3 = -.5 * e0 */
20694 57 : emit_insn (gen_rtx_SET (e3, gen_rtx_MULT (mode, e0, mhalf)));
20695 : /* ret = e2 * e3 */
20696 85 : emit_insn (gen_rtx_SET (res, gen_rtx_MULT (mode, e2, e3)));
20697 85 : }
20698 :
20699 : /* Expand fabs (OP0) and return a new rtx that holds the result. The
20700 : mask for masking out the sign-bit is stored in *SMASK, if that is
20701 : non-null. */
20702 :
20703 : static rtx
20704 1047 : ix86_expand_sse_fabs (rtx op0, rtx *smask)
20705 : {
20706 1047 : machine_mode vmode, mode = GET_MODE (op0);
20707 1047 : rtx xa, mask;
20708 :
20709 1047 : xa = gen_reg_rtx (mode);
20710 1047 : if (mode == SFmode)
20711 : vmode = V4SFmode;
20712 465 : else if (mode == DFmode)
20713 : vmode = V2DFmode;
20714 : else
20715 0 : vmode = mode;
20716 1047 : mask = ix86_build_signbit_mask (vmode, VECTOR_MODE_P (mode), true);
20717 1047 : if (!VECTOR_MODE_P (mode))
20718 : {
20719 : /* We need to generate a scalar mode mask in this case. */
20720 1047 : rtx tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (1, const0_rtx));
20721 1047 : tmp = gen_rtx_VEC_SELECT (mode, mask, tmp);
20722 1047 : mask = gen_reg_rtx (mode);
20723 1047 : emit_insn (gen_rtx_SET (mask, tmp));
20724 : }
20725 1047 : emit_insn (gen_rtx_SET (xa, gen_rtx_AND (mode, op0, mask)));
20726 :
20727 1047 : if (smask)
20728 994 : *smask = mask;
20729 :
20730 1047 : return xa;
20731 : }
20732 :
20733 : /* Expands a comparison of OP0 with OP1 using comparison code CODE,
20734 : swapping the operands if SWAP_OPERANDS is true. The expanded
20735 : code is a forward jump to a newly created label in case the
20736 : comparison is true. The generated label rtx is returned. */
20737 : static rtx_code_label *
20738 1062 : ix86_expand_sse_compare_and_jump (enum rtx_code code, rtx op0, rtx op1,
20739 : bool swap_operands)
20740 : {
20741 1062 : bool unordered_compare = ix86_unordered_fp_compare (code);
20742 1062 : rtx_code_label *label;
20743 1062 : rtx tmp, reg;
20744 :
20745 1062 : if (swap_operands)
20746 34 : std::swap (op0, op1);
20747 :
20748 1062 : label = gen_label_rtx ();
20749 1062 : tmp = gen_rtx_COMPARE (CCFPmode, op0, op1);
20750 1062 : if (unordered_compare)
20751 906 : tmp = gen_rtx_UNSPEC (CCFPmode, gen_rtvec (1, tmp), UNSPEC_NOTRAP);
20752 1062 : reg = gen_rtx_REG (CCFPmode, FLAGS_REG);
20753 1062 : emit_insn (gen_rtx_SET (reg, tmp));
20754 1062 : tmp = gen_rtx_fmt_ee (code, VOIDmode, reg, const0_rtx);
20755 1062 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
20756 : gen_rtx_LABEL_REF (VOIDmode, label), pc_rtx);
20757 1062 : tmp = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
20758 1062 : JUMP_LABEL (tmp) = label;
20759 :
20760 1062 : return label;
20761 : }
20762 :
20763 : /* Expand a mask generating SSE comparison instruction comparing OP0 with OP1
20764 : using comparison code CODE. Operands are swapped for the comparison if
20765 : SWAP_OPERANDS is true. Returns a rtx for the generated mask. */
20766 : static rtx
20767 538 : ix86_expand_sse_compare_mask (enum rtx_code code, rtx op0, rtx op1,
20768 : bool swap_operands)
20769 : {
20770 538 : rtx (*insn)(rtx, rtx, rtx, rtx);
20771 538 : machine_mode mode = GET_MODE (op0);
20772 538 : rtx mask = gen_reg_rtx (mode);
20773 :
20774 538 : if (swap_operands)
20775 361 : std::swap (op0, op1);
20776 :
20777 538 : insn = mode == DFmode ? gen_setcc_df_sse : gen_setcc_sf_sse;
20778 :
20779 538 : emit_insn (insn (mask, op0, op1,
20780 : gen_rtx_fmt_ee (code, mode, op0, op1)));
20781 538 : return mask;
20782 : }
20783 :
20784 : /* Expand copysign from SIGN to the positive value ABS_VALUE
20785 : storing in RESULT. If MASK is non-null, it shall be a mask to mask out
20786 : the sign-bit. */
20787 :
20788 : static void
20789 1014 : ix86_sse_copysign_to_positive (rtx result, rtx abs_value, rtx sign, rtx mask)
20790 : {
20791 1014 : machine_mode mode = GET_MODE (sign);
20792 1014 : rtx sgn = gen_reg_rtx (mode);
20793 1014 : if (mask == NULL_RTX)
20794 : {
20795 28 : machine_mode vmode;
20796 :
20797 28 : if (mode == SFmode)
20798 : vmode = V4SFmode;
20799 : else if (mode == DFmode)
20800 : vmode = V2DFmode;
20801 : else if (mode == HFmode)
20802 : vmode = V8HFmode;
20803 : else
20804 28 : vmode = mode;
20805 :
20806 28 : mask = ix86_build_signbit_mask (vmode, VECTOR_MODE_P (mode), false);
20807 28 : if (!VECTOR_MODE_P (mode))
20808 : {
20809 : /* We need to generate a scalar mode mask in this case. */
20810 28 : rtx tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (1, const0_rtx));
20811 28 : tmp = gen_rtx_VEC_SELECT (mode, mask, tmp);
20812 28 : mask = gen_reg_rtx (mode);
20813 28 : emit_insn (gen_rtx_SET (mask, tmp));
20814 : }
20815 : }
20816 : else
20817 986 : mask = gen_rtx_NOT (mode, mask);
20818 1014 : emit_insn (gen_rtx_SET (sgn, gen_rtx_AND (mode, mask, sign)));
20819 1014 : emit_insn (gen_rtx_SET (result, gen_rtx_IOR (mode, abs_value, sgn)));
20820 1014 : }
20821 :
20822 : /* Expand SSE sequence for computing lround from OP1 storing
20823 : into OP0. */
20824 :
20825 : void
20826 28 : ix86_expand_lround (rtx op0, rtx op1)
20827 : {
20828 : /* C code for the stuff we're doing below:
20829 : tmp = op1 + copysign (nextafter (0.5, 0.0), op1)
20830 : return (long)tmp;
20831 : */
20832 28 : machine_mode mode = GET_MODE (op1);
20833 28 : const struct real_format *fmt;
20834 28 : REAL_VALUE_TYPE pred_half, half_minus_pred_half;
20835 28 : rtx adj;
20836 :
20837 : /* load nextafter (0.5, 0.0) */
20838 28 : fmt = REAL_MODE_FORMAT (mode);
20839 28 : real_2expN (&half_minus_pred_half, -(fmt->p) - 1, mode);
20840 28 : real_arithmetic (&pred_half, MINUS_EXPR, &dconsthalf, &half_minus_pred_half);
20841 :
20842 : /* adj = copysign (0.5, op1) */
20843 28 : adj = force_reg (mode, const_double_from_real_value (pred_half, mode));
20844 28 : ix86_sse_copysign_to_positive (adj, adj, force_reg (mode, op1), NULL_RTX);
20845 :
20846 : /* adj = op1 + adj */
20847 28 : adj = expand_simple_binop (mode, PLUS, adj, op1, NULL_RTX, 0, OPTAB_DIRECT);
20848 :
20849 : /* op0 = (imode)adj */
20850 28 : expand_fix (op0, adj, 0);
20851 28 : }
20852 :
20853 : /* Expand SSE2 sequence for computing lround from OPERAND1 storing
20854 : into OPERAND0. */
20855 :
20856 : void
20857 68 : ix86_expand_lfloorceil (rtx op0, rtx op1, bool do_floor)
20858 : {
20859 : /* C code for the stuff we're doing below (for do_floor):
20860 : xi = (long)op1;
20861 : xi -= (double)xi > op1 ? 1 : 0;
20862 : return xi;
20863 : */
20864 68 : machine_mode fmode = GET_MODE (op1);
20865 68 : machine_mode imode = GET_MODE (op0);
20866 68 : rtx ireg, freg, tmp;
20867 68 : rtx_code_label *label;
20868 :
20869 : /* reg = (long)op1 */
20870 68 : ireg = gen_reg_rtx (imode);
20871 68 : expand_fix (ireg, op1, 0);
20872 :
20873 : /* freg = (double)reg */
20874 68 : freg = gen_reg_rtx (fmode);
20875 68 : expand_float (freg, ireg, 0);
20876 :
20877 : /* ireg = (freg > op1) ? ireg - 1 : ireg */
20878 136 : label = ix86_expand_sse_compare_and_jump (UNLE,
20879 68 : freg, op1, !do_floor);
20880 102 : tmp = expand_simple_binop (imode, do_floor ? MINUS : PLUS,
20881 : ireg, const1_rtx, NULL_RTX, 0, OPTAB_DIRECT);
20882 68 : emit_move_insn (ireg, tmp);
20883 :
20884 68 : emit_label (label);
20885 68 : LABEL_NUSES (label) = 1;
20886 :
20887 68 : emit_move_insn (op0, ireg);
20888 68 : }
20889 :
20890 : /* Generate and return a rtx of mode MODE for 2**n where n is the number
20891 : of bits of the mantissa of MODE, which must be one of DFmode or SFmode. */
20892 :
20893 : static rtx
20894 994 : ix86_gen_TWO52 (machine_mode mode)
20895 : {
20896 994 : const struct real_format *fmt;
20897 994 : REAL_VALUE_TYPE TWO52r;
20898 994 : rtx TWO52;
20899 :
20900 994 : fmt = REAL_MODE_FORMAT (mode);
20901 994 : real_2expN (&TWO52r, fmt->p - 1, mode);
20902 994 : TWO52 = const_double_from_real_value (TWO52r, mode);
20903 994 : TWO52 = force_reg (mode, TWO52);
20904 :
20905 994 : return TWO52;
20906 : }
20907 :
20908 : /* Expand rint rounding OPERAND1 and storing the result in OPERAND0. */
20909 :
20910 : void
20911 121 : ix86_expand_rint (rtx operand0, rtx operand1)
20912 : {
20913 : /* C code for the stuff we're doing below:
20914 : xa = fabs (operand1);
20915 : if (!isless (xa, 2**52))
20916 : return operand1;
20917 : two52 = 2**52;
20918 : if (flag_rounding_math)
20919 : {
20920 : two52 = copysign (two52, operand1);
20921 : xa = operand1;
20922 : }
20923 : xa = xa + two52 - two52;
20924 : return copysign (xa, operand1);
20925 : */
20926 121 : machine_mode mode = GET_MODE (operand0);
20927 121 : rtx res, xa, TWO52, mask;
20928 121 : rtx_code_label *label;
20929 :
20930 121 : TWO52 = ix86_gen_TWO52 (mode);
20931 :
20932 : /* Temporary for holding the result, initialized to the input
20933 : operand to ease control flow. */
20934 121 : res = copy_to_reg (operand1);
20935 :
20936 : /* xa = abs (operand1) */
20937 121 : xa = ix86_expand_sse_fabs (res, &mask);
20938 :
20939 : /* if (!isless (xa, TWO52)) goto label; */
20940 121 : label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
20941 :
20942 121 : if (flag_rounding_math)
20943 : {
20944 53 : ix86_sse_copysign_to_positive (TWO52, TWO52, res, mask);
20945 53 : xa = res;
20946 : }
20947 :
20948 121 : xa = expand_simple_binop (mode, PLUS, xa, TWO52, NULL_RTX, 0, OPTAB_DIRECT);
20949 121 : xa = expand_simple_binop (mode, MINUS, xa, TWO52, xa, 0, OPTAB_DIRECT);
20950 :
20951 : /* Remove the sign with FE_DOWNWARD, where x - x = -0.0. */
20952 121 : if (HONOR_SIGNED_ZEROS (mode) && flag_rounding_math)
20953 53 : xa = ix86_expand_sse_fabs (xa, NULL);
20954 :
20955 121 : ix86_sse_copysign_to_positive (res, xa, res, mask);
20956 :
20957 121 : emit_label (label);
20958 121 : LABEL_NUSES (label) = 1;
20959 :
20960 121 : emit_move_insn (operand0, res);
20961 121 : }
20962 :
20963 : /* Expand SSE2 sequence for computing floor or ceil
20964 : from OPERAND1 storing into OPERAND0. */
20965 : void
20966 538 : ix86_expand_floorceil (rtx operand0, rtx operand1, bool do_floor)
20967 : {
20968 : /* C code for the stuff we expand below.
20969 : double xa = fabs (x), x2;
20970 : if (!isless (xa, TWO52))
20971 : return x;
20972 : x2 = (double)(long)x;
20973 :
20974 : Compensate. Floor:
20975 : if (x2 > x)
20976 : x2 -= 1;
20977 : Compensate. Ceil:
20978 : if (x2 < x)
20979 : x2 += 1;
20980 :
20981 : if (HONOR_SIGNED_ZEROS (mode))
20982 : return copysign (x2, x);
20983 : return x2;
20984 : */
20985 538 : machine_mode mode = GET_MODE (operand0);
20986 538 : rtx xa, xi, TWO52, tmp, one, res, mask;
20987 538 : rtx_code_label *label;
20988 :
20989 538 : TWO52 = ix86_gen_TWO52 (mode);
20990 :
20991 : /* Temporary for holding the result, initialized to the input
20992 : operand to ease control flow. */
20993 538 : res = copy_to_reg (operand1);
20994 :
20995 : /* xa = abs (operand1) */
20996 538 : xa = ix86_expand_sse_fabs (res, &mask);
20997 :
20998 : /* if (!isless (xa, TWO52)) goto label; */
20999 538 : label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
21000 :
21001 : /* xa = (double)(long)x */
21002 538 : xi = gen_reg_rtx (int_mode_for_mode (mode).require ());
21003 538 : expand_fix (xi, res, 0);
21004 538 : expand_float (xa, xi, 0);
21005 :
21006 : /* generate 1.0 */
21007 538 : one = force_reg (mode, const_double_from_real_value (dconst1, mode));
21008 :
21009 : /* Compensate: xa = xa - (xa > operand1 ? 1 : 0) */
21010 538 : tmp = ix86_expand_sse_compare_mask (UNGT, xa, res, !do_floor);
21011 538 : emit_insn (gen_rtx_SET (tmp, gen_rtx_AND (mode, one, tmp)));
21012 899 : tmp = expand_simple_binop (mode, do_floor ? MINUS : PLUS,
21013 : xa, tmp, NULL_RTX, 0, OPTAB_DIRECT);
21014 538 : if (HONOR_SIGNED_ZEROS (mode))
21015 : {
21016 : /* Remove the sign with FE_DOWNWARD, where x - x = -0.0. */
21017 491 : if (do_floor && flag_rounding_math)
21018 0 : tmp = ix86_expand_sse_fabs (tmp, NULL);
21019 :
21020 491 : ix86_sse_copysign_to_positive (tmp, tmp, res, mask);
21021 : }
21022 538 : emit_move_insn (res, tmp);
21023 :
21024 538 : emit_label (label);
21025 538 : LABEL_NUSES (label) = 1;
21026 :
21027 538 : emit_move_insn (operand0, res);
21028 538 : }
21029 :
21030 : /* Expand SSE2 sequence for computing floor or ceil from OPERAND1 storing
21031 : into OPERAND0 without relying on DImode truncation via cvttsd2siq
21032 : that is only available on 64bit targets. */
21033 : void
21034 0 : ix86_expand_floorceildf_32 (rtx operand0, rtx operand1, bool do_floor)
21035 : {
21036 : /* C code for the stuff we expand below.
21037 : double xa = fabs (x), x2;
21038 : if (!isless (xa, TWO52))
21039 : return x;
21040 : xa = xa + TWO52 - TWO52;
21041 : x2 = copysign (xa, x);
21042 :
21043 : Compensate. Floor:
21044 : if (x2 > x)
21045 : x2 -= 1;
21046 : Compensate. Ceil:
21047 : if (x2 < x)
21048 : x2 += 1;
21049 :
21050 : if (HONOR_SIGNED_ZEROS (mode))
21051 : x2 = copysign (x2, x);
21052 : return x2;
21053 : */
21054 0 : machine_mode mode = GET_MODE (operand0);
21055 0 : rtx xa, TWO52, tmp, one, res, mask;
21056 0 : rtx_code_label *label;
21057 :
21058 0 : TWO52 = ix86_gen_TWO52 (mode);
21059 :
21060 : /* Temporary for holding the result, initialized to the input
21061 : operand to ease control flow. */
21062 0 : res = copy_to_reg (operand1);
21063 :
21064 : /* xa = abs (operand1) */
21065 0 : xa = ix86_expand_sse_fabs (res, &mask);
21066 :
21067 : /* if (!isless (xa, TWO52)) goto label; */
21068 0 : label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
21069 :
21070 : /* xa = xa + TWO52 - TWO52; */
21071 0 : xa = expand_simple_binop (mode, PLUS, xa, TWO52, NULL_RTX, 0, OPTAB_DIRECT);
21072 0 : xa = expand_simple_binop (mode, MINUS, xa, TWO52, xa, 0, OPTAB_DIRECT);
21073 :
21074 : /* xa = copysign (xa, operand1) */
21075 0 : ix86_sse_copysign_to_positive (xa, xa, res, mask);
21076 :
21077 : /* generate 1.0 */
21078 0 : one = force_reg (mode, const_double_from_real_value (dconst1, mode));
21079 :
21080 : /* Compensate: xa = xa - (xa > operand1 ? 1 : 0) */
21081 0 : tmp = ix86_expand_sse_compare_mask (UNGT, xa, res, !do_floor);
21082 0 : emit_insn (gen_rtx_SET (tmp, gen_rtx_AND (mode, one, tmp)));
21083 0 : tmp = expand_simple_binop (mode, do_floor ? MINUS : PLUS,
21084 : xa, tmp, NULL_RTX, 0, OPTAB_DIRECT);
21085 0 : if (HONOR_SIGNED_ZEROS (mode))
21086 : {
21087 : /* Remove the sign with FE_DOWNWARD, where x - x = -0.0. */
21088 0 : if (do_floor && flag_rounding_math)
21089 0 : tmp = ix86_expand_sse_fabs (tmp, NULL);
21090 :
21091 0 : ix86_sse_copysign_to_positive (tmp, tmp, res, mask);
21092 : }
21093 0 : emit_move_insn (res, tmp);
21094 :
21095 0 : emit_label (label);
21096 0 : LABEL_NUSES (label) = 1;
21097 :
21098 0 : emit_move_insn (operand0, res);
21099 0 : }
21100 :
21101 : /* Expand SSE sequence for computing trunc
21102 : from OPERAND1 storing into OPERAND0. */
21103 : void
21104 321 : ix86_expand_trunc (rtx operand0, rtx operand1)
21105 : {
21106 : /* C code for SSE variant we expand below.
21107 : double xa = fabs (x), x2;
21108 : if (!isless (xa, TWO52))
21109 : return x;
21110 : x2 = (double)(long)x;
21111 : if (HONOR_SIGNED_ZEROS (mode))
21112 : return copysign (x2, x);
21113 : return x2;
21114 : */
21115 321 : machine_mode mode = GET_MODE (operand0);
21116 321 : rtx xa, xi, TWO52, res, mask;
21117 321 : rtx_code_label *label;
21118 :
21119 321 : TWO52 = ix86_gen_TWO52 (mode);
21120 :
21121 : /* Temporary for holding the result, initialized to the input
21122 : operand to ease control flow. */
21123 321 : res = copy_to_reg (operand1);
21124 :
21125 : /* xa = abs (operand1) */
21126 321 : xa = ix86_expand_sse_fabs (res, &mask);
21127 :
21128 : /* if (!isless (xa, TWO52)) goto label; */
21129 321 : label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
21130 :
21131 : /* xa = (double)(long)x */
21132 321 : xi = gen_reg_rtx (int_mode_for_mode (mode).require ());
21133 321 : expand_fix (xi, res, 0);
21134 321 : expand_float (xa, xi, 0);
21135 :
21136 321 : if (HONOR_SIGNED_ZEROS (mode))
21137 307 : ix86_sse_copysign_to_positive (xa, xa, res, mask);
21138 :
21139 321 : emit_move_insn (res, xa);
21140 :
21141 321 : emit_label (label);
21142 321 : LABEL_NUSES (label) = 1;
21143 :
21144 321 : emit_move_insn (operand0, res);
21145 321 : }
21146 :
21147 : /* Expand SSE sequence for computing trunc from OPERAND1 storing
21148 : into OPERAND0 without relying on DImode truncation via cvttsd2siq
21149 : that is only available on 64bit targets. */
21150 : void
21151 0 : ix86_expand_truncdf_32 (rtx operand0, rtx operand1)
21152 : {
21153 0 : machine_mode mode = GET_MODE (operand0);
21154 0 : rtx xa, xa2, TWO52, tmp, one, res, mask;
21155 0 : rtx_code_label *label;
21156 :
21157 : /* C code for SSE variant we expand below.
21158 : double xa = fabs (x), x2;
21159 : if (!isless (xa, TWO52))
21160 : return x;
21161 : xa2 = xa + TWO52 - TWO52;
21162 : Compensate:
21163 : if (xa2 > xa)
21164 : xa2 -= 1.0;
21165 : x2 = copysign (xa2, x);
21166 : return x2;
21167 : */
21168 :
21169 0 : TWO52 = ix86_gen_TWO52 (mode);
21170 :
21171 : /* Temporary for holding the result, initialized to the input
21172 : operand to ease control flow. */
21173 0 : res =copy_to_reg (operand1);
21174 :
21175 : /* xa = abs (operand1) */
21176 0 : xa = ix86_expand_sse_fabs (res, &mask);
21177 :
21178 : /* if (!isless (xa, TWO52)) goto label; */
21179 0 : label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
21180 :
21181 : /* xa2 = xa + TWO52 - TWO52; */
21182 0 : xa2 = expand_simple_binop (mode, PLUS, xa, TWO52, NULL_RTX, 0, OPTAB_DIRECT);
21183 0 : xa2 = expand_simple_binop (mode, MINUS, xa2, TWO52, xa2, 0, OPTAB_DIRECT);
21184 :
21185 : /* generate 1.0 */
21186 0 : one = force_reg (mode, const_double_from_real_value (dconst1, mode));
21187 :
21188 : /* Compensate: xa2 = xa2 - (xa2 > xa ? 1 : 0) */
21189 0 : tmp = ix86_expand_sse_compare_mask (UNGT, xa2, xa, false);
21190 0 : emit_insn (gen_rtx_SET (tmp, gen_rtx_AND (mode, one, tmp)));
21191 0 : tmp = expand_simple_binop (mode, MINUS,
21192 : xa2, tmp, NULL_RTX, 0, OPTAB_DIRECT);
21193 : /* Remove the sign with FE_DOWNWARD, where x - x = -0.0. */
21194 0 : if (HONOR_SIGNED_ZEROS (mode) && flag_rounding_math)
21195 0 : tmp = ix86_expand_sse_fabs (tmp, NULL);
21196 :
21197 : /* res = copysign (xa2, operand1) */
21198 0 : ix86_sse_copysign_to_positive (res, tmp, res, mask);
21199 :
21200 0 : emit_label (label);
21201 0 : LABEL_NUSES (label) = 1;
21202 :
21203 0 : emit_move_insn (operand0, res);
21204 0 : }
21205 :
21206 : /* Expand SSE sequence for computing round
21207 : from OPERAND1 storing into OPERAND0. */
21208 : void
21209 14 : ix86_expand_round (rtx operand0, rtx operand1)
21210 : {
21211 : /* C code for the stuff we're doing below:
21212 : double xa = fabs (x);
21213 : if (!isless (xa, TWO52))
21214 : return x;
21215 : xa = (double)(long)(xa + nextafter (0.5, 0.0));
21216 : return copysign (xa, x);
21217 : */
21218 14 : machine_mode mode = GET_MODE (operand0);
21219 14 : rtx res, TWO52, xa, xi, half, mask;
21220 14 : rtx_code_label *label;
21221 14 : const struct real_format *fmt;
21222 14 : REAL_VALUE_TYPE pred_half, half_minus_pred_half;
21223 :
21224 : /* Temporary for holding the result, initialized to the input
21225 : operand to ease control flow. */
21226 14 : res = copy_to_reg (operand1);
21227 :
21228 14 : TWO52 = ix86_gen_TWO52 (mode);
21229 14 : xa = ix86_expand_sse_fabs (res, &mask);
21230 14 : label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
21231 :
21232 : /* load nextafter (0.5, 0.0) */
21233 14 : fmt = REAL_MODE_FORMAT (mode);
21234 14 : real_2expN (&half_minus_pred_half, -(fmt->p) - 1, mode);
21235 14 : real_arithmetic (&pred_half, MINUS_EXPR, &dconsthalf, &half_minus_pred_half);
21236 :
21237 : /* xa = xa + 0.5 */
21238 14 : half = force_reg (mode, const_double_from_real_value (pred_half, mode));
21239 14 : xa = expand_simple_binop (mode, PLUS, xa, half, NULL_RTX, 0, OPTAB_DIRECT);
21240 :
21241 : /* xa = (double)(int64_t)xa */
21242 14 : xi = gen_reg_rtx (int_mode_for_mode (mode).require ());
21243 14 : expand_fix (xi, xa, 0);
21244 14 : expand_float (xa, xi, 0);
21245 :
21246 : /* res = copysign (xa, operand1) */
21247 14 : ix86_sse_copysign_to_positive (res, xa, res, mask);
21248 :
21249 14 : emit_label (label);
21250 14 : LABEL_NUSES (label) = 1;
21251 :
21252 14 : emit_move_insn (operand0, res);
21253 14 : }
21254 :
21255 : /* Expand SSE sequence for computing round from OPERAND1 storing
21256 : into OPERAND0 without relying on DImode truncation via cvttsd2siq
21257 : that is only available on 64bit targets. */
21258 : void
21259 0 : ix86_expand_rounddf_32 (rtx operand0, rtx operand1)
21260 : {
21261 : /* C code for the stuff we expand below.
21262 : double xa = fabs (x), xa2, x2;
21263 : if (!isless (xa, TWO52))
21264 : return x;
21265 : Using the absolute value and copying back sign makes
21266 : -0.0 -> -0.0 correct.
21267 : xa2 = xa + TWO52 - TWO52;
21268 : Compensate.
21269 : dxa = xa2 - xa;
21270 : if (dxa <= -0.5)
21271 : xa2 += 1;
21272 : else if (dxa > 0.5)
21273 : xa2 -= 1;
21274 : x2 = copysign (xa2, x);
21275 : return x2;
21276 : */
21277 0 : machine_mode mode = GET_MODE (operand0);
21278 0 : rtx xa, xa2, dxa, TWO52, tmp, half, mhalf, one, res, mask;
21279 0 : rtx_code_label *label;
21280 :
21281 0 : TWO52 = ix86_gen_TWO52 (mode);
21282 :
21283 : /* Temporary for holding the result, initialized to the input
21284 : operand to ease control flow. */
21285 0 : res = copy_to_reg (operand1);
21286 :
21287 : /* xa = abs (operand1) */
21288 0 : xa = ix86_expand_sse_fabs (res, &mask);
21289 :
21290 : /* if (!isless (xa, TWO52)) goto label; */
21291 0 : label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
21292 :
21293 : /* xa2 = xa + TWO52 - TWO52; */
21294 0 : xa2 = expand_simple_binop (mode, PLUS, xa, TWO52, NULL_RTX, 0, OPTAB_DIRECT);
21295 0 : xa2 = expand_simple_binop (mode, MINUS, xa2, TWO52, xa2, 0, OPTAB_DIRECT);
21296 :
21297 : /* dxa = xa2 - xa; */
21298 0 : dxa = expand_simple_binop (mode, MINUS, xa2, xa, NULL_RTX, 0, OPTAB_DIRECT);
21299 :
21300 : /* generate 0.5, 1.0 and -0.5 */
21301 0 : half = force_reg (mode, const_double_from_real_value (dconsthalf, mode));
21302 0 : one = expand_simple_binop (mode, PLUS, half, half, NULL_RTX, 0, OPTAB_DIRECT);
21303 0 : mhalf = expand_simple_binop (mode, MINUS, half, one, NULL_RTX,
21304 : 0, OPTAB_DIRECT);
21305 :
21306 : /* Compensate. */
21307 : /* xa2 = xa2 - (dxa > 0.5 ? 1 : 0) */
21308 0 : tmp = ix86_expand_sse_compare_mask (UNGT, dxa, half, false);
21309 0 : emit_insn (gen_rtx_SET (tmp, gen_rtx_AND (mode, tmp, one)));
21310 0 : xa2 = expand_simple_binop (mode, MINUS, xa2, tmp, NULL_RTX, 0, OPTAB_DIRECT);
21311 : /* xa2 = xa2 + (dxa <= -0.5 ? 1 : 0) */
21312 0 : tmp = ix86_expand_sse_compare_mask (UNGE, mhalf, dxa, false);
21313 0 : emit_insn (gen_rtx_SET (tmp, gen_rtx_AND (mode, tmp, one)));
21314 0 : xa2 = expand_simple_binop (mode, PLUS, xa2, tmp, NULL_RTX, 0, OPTAB_DIRECT);
21315 :
21316 : /* res = copysign (xa2, operand1) */
21317 0 : ix86_sse_copysign_to_positive (res, xa2, res, mask);
21318 :
21319 0 : emit_label (label);
21320 0 : LABEL_NUSES (label) = 1;
21321 :
21322 0 : emit_move_insn (operand0, res);
21323 0 : }
21324 :
21325 : /* Expand SSE sequence for computing round
21326 : from OP1 storing into OP0 using sse4 round insn. */
21327 : void
21328 9 : ix86_expand_round_sse4 (rtx op0, rtx op1)
21329 : {
21330 9 : machine_mode mode = GET_MODE (op0);
21331 9 : rtx e1, e2, res, half;
21332 9 : const struct real_format *fmt;
21333 9 : REAL_VALUE_TYPE pred_half, half_minus_pred_half;
21334 9 : rtx (*gen_copysign) (rtx, rtx, rtx);
21335 9 : rtx (*gen_round) (rtx, rtx, rtx);
21336 :
21337 9 : switch (mode)
21338 : {
21339 : case E_HFmode:
21340 : gen_copysign = gen_copysignhf3;
21341 : gen_round = gen_sse4_1_roundhf2;
21342 : break;
21343 4 : case E_SFmode:
21344 4 : gen_copysign = gen_copysignsf3;
21345 4 : gen_round = gen_sse4_1_roundsf2;
21346 4 : break;
21347 4 : case E_DFmode:
21348 4 : gen_copysign = gen_copysigndf3;
21349 4 : gen_round = gen_sse4_1_rounddf2;
21350 4 : break;
21351 0 : default:
21352 0 : gcc_unreachable ();
21353 : }
21354 :
21355 : /* round (a) = trunc (a + copysign (0.5, a)) */
21356 :
21357 : /* load nextafter (0.5, 0.0) */
21358 9 : fmt = REAL_MODE_FORMAT (mode);
21359 9 : real_2expN (&half_minus_pred_half, -(fmt->p) - 1, mode);
21360 9 : real_arithmetic (&pred_half, MINUS_EXPR, &dconsthalf, &half_minus_pred_half);
21361 9 : half = const_double_from_real_value (pred_half, mode);
21362 :
21363 : /* e1 = copysign (0.5, op1) */
21364 9 : e1 = gen_reg_rtx (mode);
21365 9 : emit_insn (gen_copysign (e1, half, op1));
21366 :
21367 : /* e2 = op1 + e1 */
21368 9 : e2 = expand_simple_binop (mode, PLUS, op1, e1, NULL_RTX, 0, OPTAB_DIRECT);
21369 :
21370 : /* res = trunc (e2) */
21371 9 : res = gen_reg_rtx (mode);
21372 9 : emit_insn (gen_round (res, e2, GEN_INT (ROUND_TRUNC)));
21373 :
21374 9 : emit_move_insn (op0, res);
21375 9 : }
21376 :
21377 : /* A cached (set (nil) (vselect (vconcat (nil) (nil)) (parallel [])))
21378 : insn, so that expand_vselect{,_vconcat} doesn't have to create a fresh
21379 : insn every time. */
21380 :
21381 : static GTY(()) rtx_insn *vselect_insn;
21382 :
21383 : /* Initialize vselect_insn. */
21384 :
21385 : static void
21386 7698 : init_vselect_insn (void)
21387 : {
21388 7698 : unsigned i;
21389 7698 : rtx x;
21390 :
21391 7698 : x = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (MAX_VECT_LEN));
21392 500370 : for (i = 0; i < MAX_VECT_LEN; ++i)
21393 492672 : XVECEXP (x, 0, i) = const0_rtx;
21394 7698 : x = gen_rtx_VEC_SELECT (V2DFmode, gen_rtx_VEC_CONCAT (V4DFmode, const0_rtx,
21395 : const0_rtx), x);
21396 7698 : x = gen_rtx_SET (const0_rtx, x);
21397 7698 : start_sequence ();
21398 7698 : vselect_insn = emit_insn (x);
21399 7698 : end_sequence ();
21400 7698 : }
21401 :
21402 : /* Construct (set target (vec_select op0 (parallel perm))) and
21403 : return true if that's a valid instruction in the active ISA. */
21404 :
21405 : static bool
21406 541847 : expand_vselect (rtx target, rtx op0, const unsigned char *perm,
21407 : unsigned nelt, bool testing_p)
21408 : {
21409 541847 : unsigned int i;
21410 541847 : rtx x, save_vconcat;
21411 541847 : int icode;
21412 :
21413 541847 : if (vselect_insn == NULL_RTX)
21414 1701 : init_vselect_insn ();
21415 :
21416 541847 : x = XEXP (SET_SRC (PATTERN (vselect_insn)), 1);
21417 541847 : PUT_NUM_ELEM (XVEC (x, 0), nelt);
21418 4157737 : for (i = 0; i < nelt; ++i)
21419 3615890 : XVECEXP (x, 0, i) = GEN_INT (perm[i]);
21420 541847 : save_vconcat = XEXP (SET_SRC (PATTERN (vselect_insn)), 0);
21421 541847 : XEXP (SET_SRC (PATTERN (vselect_insn)), 0) = op0;
21422 541847 : PUT_MODE (SET_SRC (PATTERN (vselect_insn)), GET_MODE (target));
21423 541847 : SET_DEST (PATTERN (vselect_insn)) = target;
21424 541847 : icode = recog_memoized (vselect_insn);
21425 :
21426 541847 : if (icode >= 0 && !testing_p)
21427 72941 : emit_insn (copy_rtx (PATTERN (vselect_insn)));
21428 :
21429 541847 : SET_DEST (PATTERN (vselect_insn)) = const0_rtx;
21430 541847 : XEXP (SET_SRC (PATTERN (vselect_insn)), 0) = save_vconcat;
21431 541847 : INSN_CODE (vselect_insn) = -1;
21432 :
21433 541847 : return icode >= 0;
21434 : }
21435 :
21436 : /* Similar, but generate a vec_concat from op0 and op1 as well. */
21437 :
21438 : static bool
21439 476373 : expand_vselect_vconcat (rtx target, rtx op0, rtx op1,
21440 : const unsigned char *perm, unsigned nelt,
21441 : bool testing_p)
21442 : {
21443 476373 : machine_mode v2mode;
21444 476373 : rtx x;
21445 476373 : bool ok;
21446 :
21447 476373 : if (vselect_insn == NULL_RTX)
21448 5997 : init_vselect_insn ();
21449 :
21450 476373 : if (!GET_MODE_2XWIDER_MODE (GET_MODE (op0)).exists (&v2mode))
21451 : return false;
21452 476373 : x = XEXP (SET_SRC (PATTERN (vselect_insn)), 0);
21453 476373 : PUT_MODE (x, v2mode);
21454 476373 : XEXP (x, 0) = op0;
21455 476373 : XEXP (x, 1) = op1;
21456 476373 : ok = expand_vselect (target, x, perm, nelt, testing_p);
21457 476373 : XEXP (x, 0) = const0_rtx;
21458 476373 : XEXP (x, 1) = const0_rtx;
21459 476373 : return ok;
21460 : }
21461 :
21462 : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement D
21463 : using movss or movsd. */
21464 : static bool
21465 342494 : expand_vec_perm_movs (struct expand_vec_perm_d *d)
21466 : {
21467 342494 : machine_mode vmode = d->vmode;
21468 342494 : unsigned i, nelt = d->nelt;
21469 342494 : rtx x;
21470 :
21471 342494 : if (d->one_operand_p)
21472 : return false;
21473 :
21474 316772 : if (!(TARGET_SSE && (vmode == V4SFmode || vmode == V4SImode))
21475 166504 : && !(TARGET_MMX_WITH_SSE && (vmode == V2SFmode || vmode == V2SImode))
21476 86057 : && !(TARGET_SSE2 && (vmode == V2DFmode || vmode == V2DImode)))
21477 : return false;
21478 :
21479 : /* Only the first element is changed. */
21480 239942 : if (d->perm[0] != nelt && d->perm[0] != 0)
21481 : return false;
21482 203028 : for (i = 1; i < nelt; ++i)
21483 148055 : if (d->perm[i] != i + nelt - d->perm[0])
21484 : return false;
21485 :
21486 54973 : if (d->testing_p)
21487 : return true;
21488 :
21489 6668 : if (d->perm[0] == nelt)
21490 0 : x = gen_rtx_VEC_MERGE (vmode, d->op1, d->op0, GEN_INT (1));
21491 : else
21492 6668 : x = gen_rtx_VEC_MERGE (vmode, d->op0, d->op1, GEN_INT (1));
21493 :
21494 6668 : emit_insn (gen_rtx_SET (d->target, x));
21495 :
21496 6668 : return true;
21497 : }
21498 :
21499 : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement D
21500 : using insertps. */
21501 : static bool
21502 287521 : expand_vec_perm_insertps (struct expand_vec_perm_d *d)
21503 : {
21504 287521 : machine_mode vmode = d->vmode;
21505 287521 : unsigned i, cnt_s, nelt = d->nelt;
21506 287521 : int cnt_d = -1;
21507 287521 : rtx src, dst;
21508 :
21509 287521 : if (d->one_operand_p)
21510 : return false;
21511 :
21512 261799 : if (!(TARGET_SSE4_1
21513 37901 : && (vmode == V4SFmode || vmode == V4SImode
21514 27663 : || (TARGET_MMX_WITH_SSE
21515 21283 : && (vmode == V2SFmode || vmode == V2SImode)))))
21516 : return false;
21517 :
21518 56282 : for (i = 0; i < nelt; ++i)
21519 : {
21520 53031 : if (d->perm[i] == i)
21521 10744 : continue;
21522 42287 : if (cnt_d != -1)
21523 : {
21524 : cnt_d = -1;
21525 : break;
21526 : }
21527 22769 : cnt_d = i;
21528 : }
21529 :
21530 22769 : if (cnt_d == -1)
21531 : {
21532 44098 : for (i = 0; i < nelt; ++i)
21533 : {
21534 41279 : if (d->perm[i] == i + nelt)
21535 5062 : continue;
21536 36217 : if (cnt_d != -1)
21537 : return false;
21538 19518 : cnt_d = i;
21539 : }
21540 :
21541 2819 : if (cnt_d == -1)
21542 : return false;
21543 : }
21544 :
21545 6070 : if (d->testing_p)
21546 : return true;
21547 :
21548 544 : gcc_assert (cnt_d != -1);
21549 :
21550 544 : cnt_s = d->perm[cnt_d];
21551 544 : if (cnt_s < nelt)
21552 : {
21553 233 : src = d->op0;
21554 233 : dst = d->op1;
21555 : }
21556 : else
21557 : {
21558 311 : cnt_s -= nelt;
21559 311 : src = d->op1;
21560 311 : dst = d->op0;
21561 : }
21562 544 : gcc_assert (cnt_s < nelt);
21563 :
21564 544 : rtx x = gen_sse4_1_insertps (vmode, d->target, dst, src,
21565 544 : GEN_INT (cnt_s << 6 | cnt_d << 4));
21566 544 : emit_insn (x);
21567 :
21568 544 : return true;
21569 : }
21570 :
21571 : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement D
21572 : in terms of blendp[sd] / pblendw / pblendvb / vpblendd. */
21573 :
21574 : static bool
21575 347126 : expand_vec_perm_blend (struct expand_vec_perm_d *d)
21576 : {
21577 347126 : machine_mode mmode, vmode = d->vmode;
21578 347126 : unsigned i, nelt = d->nelt;
21579 347126 : unsigned HOST_WIDE_INT mask;
21580 347126 : rtx target, op0, op1, maskop, x;
21581 347126 : rtx rperm[32], vperm;
21582 :
21583 347126 : if (d->one_operand_p)
21584 : return false;
21585 6628 : if (TARGET_AVX512F && GET_MODE_SIZE (vmode) == 64
21586 322424 : && (TARGET_AVX512BW
21587 655 : || GET_MODE_UNIT_SIZE (vmode) >= 4))
21588 : ;
21589 333329 : else if (TARGET_AVX2 && GET_MODE_SIZE (vmode) == 32)
21590 : ;
21591 314914 : else if (TARGET_AVX && (vmode == V4DFmode || vmode == V8SFmode))
21592 : ;
21593 309699 : else if (TARGET_SSE4_1
21594 345787 : && (GET_MODE_SIZE (vmode) == 16
21595 29508 : || (TARGET_MMX_WITH_SSE && GET_MODE_SIZE (vmode) == 8)
21596 3636 : || GET_MODE_SIZE (vmode) == 4))
21597 : ;
21598 : else
21599 : return false;
21600 :
21601 : /* This is a blend, not a permute. Elements must stay in their
21602 : respective lanes. */
21603 97619 : for (i = 0; i < nelt; ++i)
21604 : {
21605 92987 : unsigned e = d->perm[i];
21606 92987 : if (!(e == i || e == i + nelt))
21607 : return false;
21608 : }
21609 :
21610 4632 : if (d->testing_p)
21611 : return true;
21612 :
21613 : /* ??? Without SSE4.1, we could implement this with and/andn/or. This
21614 : decision should be extracted elsewhere, so that we only try that
21615 : sequence once all budget==3 options have been tried. */
21616 2773 : target = d->target;
21617 2773 : op0 = d->op0;
21618 2773 : op1 = d->op1;
21619 2773 : mask = 0;
21620 :
21621 2773 : switch (vmode)
21622 : {
21623 : case E_V8DFmode:
21624 : case E_V16SFmode:
21625 : case E_V4DFmode:
21626 : case E_V8SFmode:
21627 : case E_V2DFmode:
21628 : case E_V4SFmode:
21629 : case E_V2SFmode:
21630 : case E_V2HImode:
21631 : case E_V4HImode:
21632 : case E_V8HImode:
21633 : case E_V8SImode:
21634 : case E_V32HImode:
21635 : case E_V64QImode:
21636 : case E_V16SImode:
21637 : case E_V8DImode:
21638 10860 : for (i = 0; i < nelt; ++i)
21639 9378 : mask |= ((unsigned HOST_WIDE_INT) (d->perm[i] >= nelt)) << i;
21640 : break;
21641 :
21642 : case E_V2DImode:
21643 18 : for (i = 0; i < 2; ++i)
21644 18 : mask |= (d->perm[i] >= 2 ? 15 : 0) << (i * 4);
21645 6 : vmode = V8HImode;
21646 6 : goto do_subreg;
21647 :
21648 : case E_V2SImode:
21649 24 : for (i = 0; i < 2; ++i)
21650 24 : mask |= (d->perm[i] >= 2 ? 3 : 0) << (i * 2);
21651 8 : vmode = V4HImode;
21652 8 : goto do_subreg;
21653 :
21654 872 : case E_V4SImode:
21655 872 : if (TARGET_AVX2)
21656 : {
21657 : /* Use vpblendd instead of vpblendw. */
21658 190 : for (i = 0; i < nelt; ++i)
21659 152 : mask |= ((unsigned HOST_WIDE_INT) (d->perm[i] >= nelt)) << i;
21660 : break;
21661 : }
21662 : else
21663 : {
21664 4170 : for (i = 0; i < 4; ++i)
21665 5200 : mask |= (d->perm[i] >= 4 ? 3 : 0) << (i * 2);
21666 834 : vmode = V8HImode;
21667 834 : goto do_subreg;
21668 : }
21669 :
21670 : case E_V16QImode:
21671 : /* See if bytes move in pairs so we can use pblendw with
21672 : an immediate argument, rather than pblendvb with a vector
21673 : argument. */
21674 102 : for (i = 0; i < 16; i += 2)
21675 100 : if (d->perm[i] + 1 != d->perm[i + 1])
21676 : {
21677 83 : use_pblendvb:
21678 3502 : for (i = 0; i < nelt; ++i)
21679 3212 : rperm[i] = (d->perm[i] < nelt ? const0_rtx : constm1_rtx);
21680 :
21681 290 : finish_pblendvb:
21682 291 : vperm = gen_rtx_CONST_VECTOR (vmode, gen_rtvec_v (nelt, rperm));
21683 291 : vperm = force_reg (vmode, vperm);
21684 :
21685 582 : if (GET_MODE_SIZE (vmode) == 4)
21686 135 : emit_insn (gen_mmx_pblendvb_v4qi (target, op0, op1, vperm));
21687 312 : else if (GET_MODE_SIZE (vmode) == 8)
21688 40 : emit_insn (gen_mmx_pblendvb_v8qi (target, op0, op1, vperm));
21689 232 : else if (GET_MODE_SIZE (vmode) == 16)
21690 83 : emit_insn (gen_sse4_1_pblendvb (target, op0, op1, vperm));
21691 : else
21692 33 : emit_insn (gen_avx2_pblendvb (target, op0, op1, vperm));
21693 291 : if (target != d->target)
21694 1 : emit_move_insn (d->target, gen_lowpart (d->vmode, target));
21695 291 : return true;
21696 : }
21697 :
21698 18 : for (i = 0; i < 8; ++i)
21699 16 : mask |= (d->perm[i * 2] >= 16) << i;
21700 : vmode = V8HImode;
21701 : /* FALLTHRU */
21702 :
21703 930 : do_subreg:
21704 930 : target = gen_reg_rtx (vmode);
21705 930 : op0 = gen_lowpart (vmode, op0);
21706 930 : op1 = gen_lowpart (vmode, op1);
21707 930 : break;
21708 :
21709 : case E_V8QImode:
21710 40 : for (i = 0; i < 8; i += 2)
21711 40 : if (d->perm[i] + 1 != d->perm[i + 1])
21712 40 : goto use_pblendvb;
21713 :
21714 0 : for (i = 0; i < 4; ++i)
21715 0 : mask |= (d->perm[i * 2] >= 8) << i;
21716 0 : vmode = V4HImode;
21717 0 : goto do_subreg;
21718 :
21719 : case E_V4QImode:
21720 153 : for (i = 0; i < 4; i += 2)
21721 150 : if (d->perm[i] + 1 != d->perm[i + 1])
21722 135 : goto use_pblendvb;
21723 :
21724 9 : for (i = 0; i < 2; ++i)
21725 6 : mask |= (d->perm[i * 2] >= 4) << i;
21726 3 : vmode = V2HImode;
21727 3 : goto do_subreg;
21728 :
21729 : case E_V32QImode:
21730 : /* See if bytes move in pairs. If not, vpblendvb must be used. */
21731 916 : for (i = 0; i < 32; i += 2)
21732 864 : if (d->perm[i] + 1 != d->perm[i + 1])
21733 32 : goto use_pblendvb;
21734 : /* See if bytes move in quadruplets. If yes, vpblendd
21735 : with immediate can be used. */
21736 468 : for (i = 0; i < 32; i += 4)
21737 416 : if (d->perm[i] + 2 != d->perm[i + 2])
21738 : break;
21739 52 : if (i < 32)
21740 : {
21741 : /* See if bytes move the same in both lanes. If yes,
21742 : vpblendw with immediate can be used. */
21743 0 : for (i = 0; i < 16; i += 2)
21744 0 : if (d->perm[i] + 16 != d->perm[i + 16])
21745 0 : goto use_pblendvb;
21746 :
21747 : /* Use vpblendw. */
21748 0 : for (i = 0; i < 16; ++i)
21749 0 : mask |= (d->perm[i * 2] >= 32) << i;
21750 0 : vmode = V16HImode;
21751 0 : goto do_subreg;
21752 : }
21753 :
21754 : /* Use vpblendd. */
21755 468 : for (i = 0; i < 8; ++i)
21756 416 : mask |= (d->perm[i * 4] >= 32) << i;
21757 52 : vmode = V8SImode;
21758 52 : goto do_subreg;
21759 :
21760 : case E_V16HImode:
21761 : /* See if words move in pairs. If yes, vpblendd can be used. */
21762 186 : for (i = 0; i < 16; i += 2)
21763 169 : if (d->perm[i] + 1 != d->perm[i + 1])
21764 : break;
21765 50 : if (i < 16)
21766 : {
21767 : /* See if words move the same in both lanes. If not,
21768 : vpblendvb must be used. */
21769 290 : for (i = 0; i < 8; i++)
21770 258 : if (d->perm[i] + 8 != d->perm[i + 8])
21771 : {
21772 : /* Use vpblendvb. */
21773 33 : for (i = 0; i < 32; ++i)
21774 32 : rperm[i] = (d->perm[i / 2] < 16 ? const0_rtx : constm1_rtx);
21775 :
21776 1 : vmode = V32QImode;
21777 1 : nelt = 32;
21778 1 : target = gen_reg_rtx (vmode);
21779 1 : op0 = gen_lowpart (vmode, op0);
21780 1 : op1 = gen_lowpart (vmode, op1);
21781 1 : goto finish_pblendvb;
21782 : }
21783 :
21784 : /* Use vpblendw. */
21785 544 : for (i = 0; i < 16; ++i)
21786 512 : mask |= (d->perm[i] >= 16) << i;
21787 : break;
21788 : }
21789 :
21790 : /* Use vpblendd. */
21791 153 : for (i = 0; i < 8; ++i)
21792 136 : mask |= (d->perm[i * 2] >= 16) << i;
21793 17 : vmode = V8SImode;
21794 17 : goto do_subreg;
21795 :
21796 : case E_V4DImode:
21797 : /* Use vpblendd. */
21798 40 : for (i = 0; i < 4; ++i)
21799 47 : mask |= (d->perm[i] >= 4 ? 3 : 0) << (i * 2);
21800 8 : vmode = V8SImode;
21801 8 : goto do_subreg;
21802 :
21803 0 : default:
21804 0 : gcc_unreachable ();
21805 : }
21806 :
21807 2482 : switch (vmode)
21808 : {
21809 : case E_V8DFmode:
21810 : case E_V8DImode:
21811 : mmode = QImode;
21812 : break;
21813 1 : case E_V16SFmode:
21814 1 : case E_V16SImode:
21815 1 : mmode = HImode;
21816 1 : break;
21817 6 : case E_V32HImode:
21818 6 : mmode = SImode;
21819 6 : break;
21820 1 : case E_V64QImode:
21821 1 : mmode = DImode;
21822 1 : break;
21823 : default:
21824 : mmode = VOIDmode;
21825 : }
21826 :
21827 : /* Canonicalize vec_merge. */
21828 2482 : if (swap_commutative_operands_p (op1, op0)
21829 : /* Two operands have same precedence, then
21830 : first bit of mask select first operand. */
21831 2482 : || (!swap_commutative_operands_p (op0, op1)
21832 2482 : && !(mask & 1)))
21833 : {
21834 2475 : unsigned n_elts = GET_MODE_NUNITS (vmode);
21835 2475 : std::swap (op0, op1);
21836 2475 : unsigned HOST_WIDE_INT mask_all = HOST_WIDE_INT_1U;
21837 2475 : if (n_elts == HOST_BITS_PER_WIDE_INT)
21838 : mask_all = -1;
21839 : else
21840 2474 : mask_all = (HOST_WIDE_INT_1U << n_elts) - 1;
21841 2475 : mask = ~mask & mask_all;
21842 : }
21843 :
21844 2482 : if (mmode != VOIDmode)
21845 14 : maskop = force_reg (mmode, gen_int_mode (mask, mmode));
21846 : else
21847 2468 : maskop = GEN_INT (mask);
21848 :
21849 : /* This matches five different patterns with the different modes. */
21850 2482 : x = gen_rtx_VEC_MERGE (vmode, op1, op0, maskop);
21851 2482 : x = gen_rtx_SET (target, x);
21852 2482 : emit_insn (x);
21853 2482 : if (target != d->target)
21854 930 : emit_move_insn (d->target, gen_lowpart (d->vmode, target));
21855 :
21856 : return true;
21857 : }
21858 :
21859 : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement D
21860 : in terms of the variable form of vpermilps.
21861 :
21862 : Note that we will have already failed the immediate input vpermilps,
21863 : which requires that the high and low part shuffle be identical; the
21864 : variable form doesn't require that. */
21865 :
21866 : static bool
21867 137406 : expand_vec_perm_vpermil (struct expand_vec_perm_d *d)
21868 : {
21869 137406 : rtx rperm[8], vperm;
21870 137406 : unsigned i;
21871 :
21872 137406 : if (!TARGET_AVX || !d->one_operand_p
21873 11091 : || (d->vmode != V8SImode && d->vmode != V8SFmode))
21874 : return false;
21875 :
21876 : /* We can only permute within the 128-bit lane. */
21877 16076 : for (i = 0; i < 8; ++i)
21878 : {
21879 15440 : unsigned e = d->perm[i];
21880 15440 : if (i < 4 ? e >= 4 : e < 4)
21881 : return false;
21882 : }
21883 :
21884 636 : if (d->testing_p)
21885 : return true;
21886 :
21887 531 : for (i = 0; i < 8; ++i)
21888 : {
21889 472 : unsigned e = d->perm[i];
21890 :
21891 : /* Within each 128-bit lane, the elements of op0 are numbered
21892 : from 0 and the elements of op1 are numbered from 4. */
21893 472 : if (e >= 8 + 4)
21894 0 : e -= 8;
21895 472 : else if (e >= 4)
21896 236 : e -= 4;
21897 :
21898 472 : rperm[i] = GEN_INT (e);
21899 : }
21900 :
21901 59 : vperm = gen_rtx_CONST_VECTOR (V8SImode, gen_rtvec_v (8, rperm));
21902 59 : vperm = force_reg (V8SImode, vperm);
21903 59 : rtx target = d->target;
21904 59 : rtx op0 = d->op0;
21905 59 : if (d->vmode == V8SImode)
21906 : {
21907 7 : target = lowpart_subreg (V8SFmode, target, V8SImode);
21908 7 : op0 = lowpart_subreg (V8SFmode, op0, V8SImode);
21909 : }
21910 :
21911 59 : emit_insn (gen_avx_vpermilvarv8sf3 (target, op0, vperm));
21912 :
21913 59 : return true;
21914 : }
21915 :
21916 : /* For V*[QHS]Imode permutations, check if the same permutation
21917 : can't be performed in a 2x, 4x or 8x wider inner mode. */
21918 :
21919 : static bool
21920 161748 : canonicalize_vector_int_perm (const struct expand_vec_perm_d *d,
21921 : struct expand_vec_perm_d *nd)
21922 : {
21923 161748 : int i;
21924 161748 : machine_mode mode = VOIDmode;
21925 :
21926 161748 : switch (d->vmode)
21927 : {
21928 : case E_V8QImode: mode = V4HImode; break;
21929 30188 : case E_V16QImode: mode = V8HImode; break;
21930 715 : case E_V32QImode: mode = V16HImode; break;
21931 275 : case E_V64QImode: mode = V32HImode; break;
21932 12270 : case E_V4HImode: mode = V2SImode; break;
21933 20804 : case E_V8HImode: mode = V4SImode; break;
21934 1006 : case E_V16HImode: mode = V8SImode; break;
21935 397 : case E_V32HImode: mode = V16SImode; break;
21936 41007 : case E_V4SImode: mode = V2DImode; break;
21937 1429 : case E_V8SImode: mode = V4DImode; break;
21938 65 : case E_V16SImode: mode = V8DImode; break;
21939 : default: return false;
21940 : }
21941 206458 : for (i = 0; i < d->nelt; i += 2)
21942 191688 : if ((d->perm[i] & 1) || d->perm[i + 1] != d->perm[i] + 1)
21943 : return false;
21944 14770 : nd->vmode = mode;
21945 14770 : nd->nelt = d->nelt / 2;
21946 96188 : for (i = 0; i < nd->nelt; i++)
21947 81418 : nd->perm[i] = d->perm[2 * i] / 2;
21948 29540 : if (GET_MODE_INNER (mode) != DImode)
21949 13001 : canonicalize_vector_int_perm (nd, nd);
21950 14770 : if (nd != d)
21951 : {
21952 9420 : nd->one_operand_p = d->one_operand_p;
21953 9420 : nd->testing_p = d->testing_p;
21954 9420 : if (d->op0 == d->op1)
21955 2781 : nd->op0 = nd->op1 = gen_lowpart (nd->vmode, d->op0);
21956 : else
21957 : {
21958 6639 : nd->op0 = gen_lowpart (nd->vmode, d->op0);
21959 6639 : nd->op1 = gen_lowpart (nd->vmode, d->op1);
21960 : }
21961 9420 : if (d->testing_p)
21962 6120 : nd->target = gen_raw_REG (nd->vmode, LAST_VIRTUAL_REGISTER + 1);
21963 : else
21964 3300 : nd->target = gen_reg_rtx (nd->vmode);
21965 : }
21966 : return true;
21967 : }
21968 :
21969 : /* Return true if permutation D can be performed as VMODE permutation
21970 : instead. */
21971 :
21972 : static bool
21973 5970 : valid_perm_using_mode_p (machine_mode vmode, struct expand_vec_perm_d *d)
21974 : {
21975 5970 : unsigned int i, j, chunk;
21976 :
21977 5970 : if (GET_MODE_CLASS (vmode) != MODE_VECTOR_INT
21978 5970 : || GET_MODE_CLASS (d->vmode) != MODE_VECTOR_INT
21979 14558 : || GET_MODE_SIZE (vmode) != GET_MODE_SIZE (d->vmode))
21980 : return false;
21981 :
21982 8588 : if (GET_MODE_NUNITS (vmode) >= d->nelt)
21983 : return true;
21984 :
21985 4030 : chunk = d->nelt / GET_MODE_NUNITS (vmode);
21986 5272 : for (i = 0; i < d->nelt; i += chunk)
21987 5025 : if (d->perm[i] & (chunk - 1))
21988 : return false;
21989 : else
21990 7759 : for (j = 1; j < chunk; ++j)
21991 6517 : if (d->perm[i] + j != d->perm[i + j])
21992 : return false;
21993 :
21994 : return true;
21995 : }
21996 :
21997 : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement D
21998 : in terms of pshufb, vpperm, vpermq, vpermd, vpermps or vperm2i128. */
21999 :
22000 : static bool
22001 136770 : expand_vec_perm_pshufb (struct expand_vec_perm_d *d)
22002 : {
22003 136770 : unsigned i, nelt, eltsz, mask;
22004 136770 : unsigned char perm[64];
22005 136770 : machine_mode vmode;
22006 136770 : struct expand_vec_perm_d nd;
22007 136770 : rtx rperm[64], vperm, target, op0, op1;
22008 :
22009 136770 : nelt = d->nelt;
22010 :
22011 136770 : if (!d->one_operand_p)
22012 223576 : switch (GET_MODE_SIZE (d->vmode))
22013 : {
22014 8327 : case 4:
22015 8327 : if (!TARGET_XOP)
22016 : return false;
22017 : vmode = V4QImode;
22018 : break;
22019 :
22020 19732 : case 8:
22021 19732 : if (!TARGET_XOP)
22022 : return false;
22023 : vmode = V8QImode;
22024 : break;
22025 :
22026 74711 : case 16:
22027 74711 : if (!TARGET_XOP)
22028 : return false;
22029 : vmode = V16QImode;
22030 : break;
22031 :
22032 8100 : case 32:
22033 8100 : if (!TARGET_AVX2)
22034 : return false;
22035 :
22036 4038 : if (valid_perm_using_mode_p (V2TImode, d))
22037 : {
22038 56 : if (d->testing_p)
22039 : return true;
22040 :
22041 : /* Use vperm2i128 insn. The pattern uses
22042 : V4DImode instead of V2TImode. */
22043 52 : target = d->target;
22044 52 : if (d->vmode != V4DImode)
22045 12 : target = gen_reg_rtx (V4DImode);
22046 52 : op0 = gen_lowpart (V4DImode, d->op0);
22047 52 : op1 = gen_lowpart (V4DImode, d->op1);
22048 52 : rperm[0]
22049 52 : = GEN_INT ((d->perm[0] / (nelt / 2))
22050 : | ((d->perm[nelt / 2] / (nelt / 2)) * 16));
22051 52 : emit_insn (gen_avx2_permv2ti (target, op0, op1, rperm[0]));
22052 52 : if (target != d->target)
22053 12 : emit_move_insn (d->target, gen_lowpart (d->vmode, target));
22054 52 : return true;
22055 : }
22056 : /* FALLTHRU */
22057 :
22058 : default:
22059 : return false;
22060 : }
22061 : else
22062 49964 : switch (GET_MODE_SIZE (d->vmode))
22063 : {
22064 3630 : case 4:
22065 3630 : if (!TARGET_SSSE3)
22066 : return false;
22067 : vmode = V4QImode;
22068 : break;
22069 :
22070 2229 : case 8:
22071 2229 : if (!TARGET_SSSE3)
22072 : return false;
22073 : vmode = V8QImode;
22074 : break;
22075 :
22076 14160 : case 16:
22077 14160 : if (!TARGET_SSSE3)
22078 : return false;
22079 : vmode = V16QImode;
22080 : break;
22081 :
22082 4564 : case 32:
22083 4564 : if (!TARGET_AVX2)
22084 : return false;
22085 :
22086 : /* V4DImode should be already handled through
22087 : expand_vselect by vpermq instruction. */
22088 1987 : gcc_assert (d->vmode != V4DImode);
22089 :
22090 1987 : vmode = V32QImode;
22091 1987 : if (d->vmode == V8SImode
22092 1622 : || d->vmode == V16HImode
22093 1406 : || d->vmode == V32QImode)
22094 : {
22095 : /* First see if vpermq can be used for
22096 : V8SImode/V16HImode/V32QImode. */
22097 879 : if (valid_perm_using_mode_p (V4DImode, d))
22098 : {
22099 770 : for (i = 0; i < 4; i++)
22100 616 : perm[i] = (d->perm[i * nelt / 4] * 4 / nelt) & 3;
22101 154 : if (d->testing_p)
22102 : return true;
22103 58 : target = gen_reg_rtx (V4DImode);
22104 58 : if (expand_vselect (target, gen_lowpart (V4DImode, d->op0),
22105 : perm, 4, false))
22106 : {
22107 116 : emit_move_insn (d->target,
22108 58 : gen_lowpart (d->vmode, target));
22109 58 : return true;
22110 : }
22111 : return false;
22112 : }
22113 :
22114 : /* Next see if vpermd can be used. */
22115 725 : if (valid_perm_using_mode_p (V8SImode, d))
22116 : vmode = V8SImode;
22117 : }
22118 : /* Or if vpermps can be used. */
22119 1108 : else if (d->vmode == V8SFmode)
22120 : vmode = V8SImode;
22121 :
22122 : if (vmode == V32QImode)
22123 : {
22124 : /* vpshufb only works intra lanes, it is not
22125 : possible to shuffle bytes in between the lanes. */
22126 6473 : for (i = 0; i < nelt; ++i)
22127 6291 : if ((d->perm[i] ^ i) & (nelt / 2))
22128 : return false;
22129 : }
22130 : break;
22131 :
22132 399 : case 64:
22133 399 : if (!TARGET_AVX512BW)
22134 : return false;
22135 :
22136 : /* If vpermq didn't work, vpshufb won't work either. */
22137 204 : if (d->vmode == V8DFmode || d->vmode == V8DImode)
22138 : return false;
22139 :
22140 175 : vmode = V64QImode;
22141 175 : if (d->vmode == V16SImode
22142 150 : || d->vmode == V32HImode
22143 50 : || d->vmode == V64QImode)
22144 : {
22145 : /* First see if vpermq can be used for
22146 : V16SImode/V32HImode/V64QImode. */
22147 164 : if (valid_perm_using_mode_p (V8DImode, d))
22148 : {
22149 0 : for (i = 0; i < 8; i++)
22150 0 : perm[i] = (d->perm[i * nelt / 8] * 8 / nelt) & 7;
22151 0 : if (d->testing_p)
22152 : return true;
22153 0 : target = gen_reg_rtx (V8DImode);
22154 0 : if (expand_vselect (target, gen_lowpart (V8DImode, d->op0),
22155 : perm, 8, false))
22156 : {
22157 0 : emit_move_insn (d->target,
22158 0 : gen_lowpart (d->vmode, target));
22159 0 : return true;
22160 : }
22161 : return false;
22162 : }
22163 :
22164 : /* Next see if vpermd can be used. */
22165 164 : if (valid_perm_using_mode_p (V16SImode, d))
22166 : vmode = V16SImode;
22167 : }
22168 : /* Or if vpermps can be used. */
22169 11 : else if (d->vmode == V16SFmode)
22170 : vmode = V16SImode;
22171 :
22172 : if (vmode == V64QImode)
22173 : {
22174 : /* vpshufb only works intra lanes, it is not
22175 : possible to shuffle bytes in between the lanes. */
22176 578 : for (i = 0; i < nelt; ++i)
22177 578 : if ((d->perm[i] ^ i) & (3 * nelt / 4))
22178 : return false;
22179 : }
22180 : break;
22181 :
22182 : default:
22183 : return false;
22184 : }
22185 :
22186 11547 : if (d->testing_p)
22187 : return true;
22188 :
22189 : /* Try to avoid variable permutation instruction. */
22190 8846 : if (canonicalize_vector_int_perm (d, &nd) && expand_vec_perm_1 (&nd))
22191 : {
22192 1839 : emit_move_insn (d->target, gen_lowpart (d->vmode, nd.target));
22193 1839 : return true;
22194 : }
22195 :
22196 7007 : if (vmode == V8SImode)
22197 9531 : for (i = 0; i < 8; ++i)
22198 8472 : rperm[i] = GEN_INT ((d->perm[i * nelt / 8] * 8 / nelt) & 7);
22199 5948 : else if (vmode == V16SImode)
22200 612 : for (i = 0; i < 16; ++i)
22201 576 : rperm[i] = GEN_INT ((d->perm[i * nelt / 16] * 16 / nelt) & 15);
22202 : else
22203 : {
22204 5912 : eltsz = GET_MODE_UNIT_SIZE (d->vmode);
22205 5912 : if (!d->one_operand_p)
22206 3212 : mask = 2 * nelt - 1;
22207 2700 : else if (vmode == V64QImode)
22208 0 : mask = nelt / 4 - 1;
22209 2700 : else if (vmode == V32QImode)
22210 176 : mask = nelt / 2 - 1;
22211 : else
22212 2524 : mask = nelt - 1;
22213 :
22214 59020 : for (i = 0; i < nelt; ++i)
22215 : {
22216 53108 : unsigned j, e = d->perm[i] & mask;
22217 148168 : for (j = 0; j < eltsz; ++j)
22218 95060 : rperm[i * eltsz + j] = GEN_INT (e * eltsz + j);
22219 : }
22220 : }
22221 :
22222 7007 : machine_mode vpmode = vmode;
22223 :
22224 7007 : nelt = GET_MODE_SIZE (vmode);
22225 :
22226 : /* Emulate narrow modes with V16QI instructions. */
22227 7007 : if (nelt < 16)
22228 : {
22229 222 : rtx m128 = GEN_INT (-128);
22230 :
22231 : /* Remap elements from the second operand, as we have to
22232 : account for inactive top elements from the first operand. */
22233 222 : if (!d->one_operand_p)
22234 : {
22235 243 : for (i = 0; i < nelt; ++i)
22236 : {
22237 216 : unsigned ival = UINTVAL (rperm[i]);
22238 216 : if (ival >= nelt)
22239 108 : rperm[i] = GEN_INT (ival + 16 - nelt);
22240 : }
22241 : }
22242 :
22243 : /* Fill inactive elements in the top positions with zeros. */
22244 2570 : for (i = nelt; i < 16; ++i)
22245 2348 : rperm[i] = m128;
22246 :
22247 : vpmode = V16QImode;
22248 : }
22249 :
22250 14014 : vperm = gen_rtx_CONST_VECTOR (vpmode,
22251 7007 : gen_rtvec_v (GET_MODE_NUNITS (vpmode), rperm));
22252 7007 : vperm = force_reg (vpmode, vperm);
22253 :
22254 7007 : if (vmode == d->vmode)
22255 2398 : target = d->target;
22256 : else
22257 4609 : target = gen_reg_rtx (vmode);
22258 :
22259 7007 : op0 = gen_lowpart (vmode, d->op0);
22260 :
22261 7007 : if (d->one_operand_p)
22262 : {
22263 3795 : rtx (*gen) (rtx, rtx, rtx);
22264 :
22265 3795 : if (vmode == V4QImode)
22266 : gen = gen_mmx_pshufbv4qi3;
22267 : else if (vmode == V8QImode)
22268 : gen = gen_mmx_pshufbv8qi3;
22269 : else if (vmode == V16QImode)
22270 : gen = gen_ssse3_pshufbv16qi3;
22271 : else if (vmode == V32QImode)
22272 : gen = gen_avx2_pshufbv32qi3;
22273 : else if (vmode == V64QImode)
22274 : gen = gen_avx512bw_pshufbv64qi3;
22275 : else if (vmode == V8SFmode)
22276 : gen = gen_avx2_permvarv8sf;
22277 : else if (vmode == V8SImode)
22278 : gen = gen_avx2_permvarv8si;
22279 : else if (vmode == V16SFmode)
22280 : gen = gen_avx512f_permvarv16sf;
22281 : else if (vmode == V16SImode)
22282 : gen = gen_avx512f_permvarv16si;
22283 : else
22284 : gcc_unreachable ();
22285 :
22286 3795 : emit_insn (gen (target, op0, vperm));
22287 : }
22288 : else
22289 : {
22290 3212 : rtx (*gen) (rtx, rtx, rtx, rtx);
22291 :
22292 3212 : op1 = gen_lowpart (vmode, d->op1);
22293 :
22294 3212 : if (vmode == V4QImode)
22295 : gen = gen_mmx_ppermv32;
22296 : else if (vmode == V8QImode)
22297 : gen = gen_mmx_ppermv64;
22298 : else if (vmode == V16QImode)
22299 : gen = gen_xop_pperm;
22300 : else
22301 0 : gcc_unreachable ();
22302 :
22303 3212 : emit_insn (gen (target, op0, op1, vperm));
22304 : }
22305 :
22306 7007 : if (target != d->target)
22307 4609 : emit_move_insn (d->target, gen_lowpart (d->vmode, target));
22308 :
22309 : return true;
22310 : }
22311 :
22312 : /* Try to expand one-operand permutation with constant mask. */
22313 :
22314 : static bool
22315 124889 : ix86_expand_vec_one_operand_perm_avx512 (struct expand_vec_perm_d *d)
22316 : {
22317 124889 : machine_mode mode = GET_MODE (d->op0);
22318 124889 : machine_mode maskmode = mode;
22319 249778 : unsigned inner_size = GET_MODE_SIZE (GET_MODE_INNER (mode));
22320 124889 : rtx (*gen) (rtx, rtx, rtx) = NULL;
22321 124889 : rtx target, op0, mask;
22322 124889 : rtx vec[64];
22323 :
22324 124889 : if (!rtx_equal_p (d->op0, d->op1))
22325 : return false;
22326 :
22327 17616 : if (!TARGET_AVX512F)
22328 : return false;
22329 :
22330 : /* Accept VNxHImode and VNxQImode now. */
22331 739 : if (!TARGET_AVX512VL && GET_MODE_SIZE (mode) < 64)
22332 : return false;
22333 :
22334 : /* vpermw. */
22335 463 : if (!TARGET_AVX512BW && inner_size == 2)
22336 : return false;
22337 :
22338 : /* vpermb. */
22339 329 : if (!TARGET_AVX512VBMI && inner_size == 1)
22340 : return false;
22341 :
22342 210 : switch (mode)
22343 : {
22344 : case E_V16SImode:
22345 : gen = gen_avx512f_permvarv16si;
22346 : break;
22347 4 : case E_V16SFmode:
22348 4 : gen = gen_avx512f_permvarv16sf;
22349 4 : maskmode = V16SImode;
22350 4 : break;
22351 1 : case E_V8DImode:
22352 1 : gen = gen_avx512f_permvarv8di;
22353 1 : break;
22354 30 : case E_V8DFmode:
22355 30 : gen = gen_avx512f_permvarv8df;
22356 30 : maskmode = V8DImode;
22357 30 : break;
22358 106 : case E_V32HImode:
22359 106 : gen = gen_avx512bw_permvarv32hi;
22360 106 : break;
22361 14 : case E_V16HImode:
22362 14 : gen = gen_avx512vl_permvarv16hi;
22363 14 : break;
22364 6 : case E_V8HImode:
22365 6 : gen = gen_avx512vl_permvarv8hi;
22366 6 : break;
22367 4 : case E_V64QImode:
22368 4 : gen = gen_avx512bw_permvarv64qi;
22369 4 : break;
22370 2 : case E_V32QImode:
22371 2 : gen = gen_avx512vl_permvarv32qi;
22372 2 : break;
22373 0 : case E_V16QImode:
22374 0 : gen = gen_avx512vl_permvarv16qi;
22375 0 : break;
22376 :
22377 : default:
22378 : return false;
22379 : }
22380 :
22381 209 : if (d->testing_p)
22382 : return true;
22383 :
22384 200 : target = d->target;
22385 200 : op0 = d->op0;
22386 5024 : for (int i = 0; i < d->nelt; ++i)
22387 4824 : vec[i] = GEN_INT (d->perm[i]);
22388 200 : mask = gen_rtx_CONST_VECTOR (maskmode, gen_rtvec_v (d->nelt, vec));
22389 200 : emit_insn (gen (target, op0, force_reg (maskmode, mask)));
22390 200 : return true;
22391 : }
22392 :
22393 : static bool expand_vec_perm_palignr (struct expand_vec_perm_d *d, bool);
22394 :
22395 : /* A subroutine of ix86_expand_vec_perm_const_1. Try to instantiate D
22396 : in a single instruction. */
22397 :
22398 : static bool
22399 380993 : expand_vec_perm_1 (struct expand_vec_perm_d *d)
22400 : {
22401 380993 : unsigned i, nelt = d->nelt;
22402 380993 : struct expand_vec_perm_d nd;
22403 :
22404 : /* Check plain VEC_SELECT first, because AVX has instructions that could
22405 : match both SEL and SEL+CONCAT, but the plain SEL will allow a memory
22406 : input where SEL+CONCAT may not. */
22407 380993 : if (d->one_operand_p)
22408 : {
22409 : int mask = nelt - 1;
22410 : bool identity_perm = true;
22411 : bool broadcast_perm = true;
22412 :
22413 506969 : for (i = 0; i < nelt; i++)
22414 : {
22415 444876 : nd.perm[i] = d->perm[i] & mask;
22416 444876 : if (nd.perm[i] != i)
22417 339698 : identity_perm = false;
22418 444876 : if (nd.perm[i])
22419 366672 : broadcast_perm = false;
22420 : }
22421 :
22422 62093 : if (identity_perm)
22423 : {
22424 11 : if (!d->testing_p)
22425 5 : emit_move_insn (d->target, d->op0);
22426 11 : return true;
22427 : }
22428 62082 : else if (broadcast_perm && TARGET_AVX2)
22429 : {
22430 : /* Use vpbroadcast{b,w,d}. */
22431 381 : rtx (*gen) (rtx, rtx) = NULL;
22432 381 : switch (d->vmode)
22433 : {
22434 1 : case E_V64QImode:
22435 1 : if (TARGET_AVX512BW)
22436 : gen = gen_avx512bw_vec_dupv64qi_1;
22437 : break;
22438 4 : case E_V32QImode:
22439 4 : gen = gen_avx2_pbroadcastv32qi_1;
22440 4 : break;
22441 1 : case E_V32HImode:
22442 1 : if (TARGET_AVX512BW)
22443 : gen = gen_avx512bw_vec_dupv32hi_1;
22444 : break;
22445 4 : case E_V16HImode:
22446 4 : gen = gen_avx2_pbroadcastv16hi_1;
22447 4 : break;
22448 1 : case E_V16SImode:
22449 1 : if (TARGET_AVX512F)
22450 : gen = gen_avx512f_vec_dupv16si_1;
22451 : break;
22452 4 : case E_V8SImode:
22453 4 : gen = gen_avx2_pbroadcastv8si_1;
22454 4 : break;
22455 4 : case E_V16QImode:
22456 4 : gen = gen_avx2_pbroadcastv16qi;
22457 4 : break;
22458 5 : case E_V8HImode:
22459 5 : gen = gen_avx2_pbroadcastv8hi;
22460 5 : break;
22461 0 : case E_V16SFmode:
22462 0 : if (TARGET_AVX512F)
22463 : gen = gen_avx512f_vec_dupv16sf_1;
22464 : break;
22465 : case E_V8SFmode:
22466 : gen = gen_avx2_vec_dupv8sf_1;
22467 : break;
22468 0 : case E_V8DFmode:
22469 0 : if (TARGET_AVX512F)
22470 : gen = gen_avx512f_vec_dupv8df_1;
22471 : break;
22472 0 : case E_V8DImode:
22473 0 : if (TARGET_AVX512F)
22474 : gen = gen_avx512f_vec_dupv8di_1;
22475 : break;
22476 : /* For other modes prefer other shuffles this function creates. */
22477 : default: break;
22478 : }
22479 21 : if (gen != NULL)
22480 : {
22481 24 : if (!d->testing_p)
22482 24 : emit_insn (gen (d->target, d->op0));
22483 24 : return true;
22484 : }
22485 : }
22486 :
22487 62058 : if (expand_vselect (d->target, d->op0, nd.perm, nelt, d->testing_p))
22488 : return true;
22489 :
22490 : /* There are plenty of patterns in sse.md that are written for
22491 : SEL+CONCAT and are not replicated for a single op. Perhaps
22492 : that should be changed, to avoid the nastiness here. */
22493 :
22494 : /* Recognize interleave style patterns, which means incrementing
22495 : every other permutation operand. */
22496 200655 : for (i = 0; i < nelt; i += 2)
22497 : {
22498 164142 : nd.perm[i] = d->perm[i] & mask;
22499 164142 : nd.perm[i + 1] = (d->perm[i + 1] & mask) + nelt;
22500 : }
22501 36513 : if (expand_vselect_vconcat (d->target, d->op0, d->op0, nd.perm, nelt,
22502 36513 : d->testing_p))
22503 : return true;
22504 :
22505 : /* Recognize shufps, which means adding {0, 0, nelt, nelt}. */
22506 31489 : if (nelt >= 4)
22507 : {
22508 107492 : for (i = 0; i < nelt; i += 4)
22509 : {
22510 76003 : nd.perm[i + 0] = d->perm[i + 0] & mask;
22511 76003 : nd.perm[i + 1] = d->perm[i + 1] & mask;
22512 76003 : nd.perm[i + 2] = (d->perm[i + 2] & mask) + nelt;
22513 76003 : nd.perm[i + 3] = (d->perm[i + 3] & mask) + nelt;
22514 : }
22515 :
22516 31489 : if (expand_vselect_vconcat (d->target, d->op0, d->op0, nd.perm, nelt,
22517 31489 : d->testing_p))
22518 : return true;
22519 : }
22520 : }
22521 :
22522 : /* Try the SSE4.1 blend variable merge instructions. */
22523 344622 : if (expand_vec_perm_blend (d))
22524 : return true;
22525 :
22526 : /* Try movss/movsd instructions. */
22527 342494 : if (expand_vec_perm_movs (d))
22528 : return true;
22529 :
22530 : /* Try the SSE4.1 insertps instruction. */
22531 287521 : if (expand_vec_perm_insertps (d))
22532 : return true;
22533 :
22534 : /* Try the fully general two operand permute. */
22535 281451 : if (expand_vselect_vconcat (d->target, d->op0, d->op1, d->perm, nelt,
22536 281451 : d->testing_p))
22537 : return true;
22538 :
22539 : /* Recognize interleave style patterns with reversed operands. */
22540 137538 : if (!d->one_operand_p)
22541 : {
22542 897154 : for (i = 0; i < nelt; ++i)
22543 : {
22544 785234 : unsigned e = d->perm[i];
22545 785234 : if (e >= nelt)
22546 385203 : e -= nelt;
22547 : else
22548 400031 : e += nelt;
22549 785234 : nd.perm[i] = e;
22550 : }
22551 :
22552 111920 : if (expand_vselect_vconcat (d->target, d->op1, d->op0, nd.perm, nelt,
22553 111920 : d->testing_p))
22554 : return true;
22555 : }
22556 :
22557 : /* Try one of the AVX vpermil variable permutations. */
22558 137406 : if (expand_vec_perm_vpermil (d))
22559 : return true;
22560 :
22561 : /* Try the SSSE3 pshufb or XOP vpperm or AVX2 vperm2i128,
22562 : vpshufb, vpermd, vpermps or vpermq variable permutation. */
22563 136770 : if (expand_vec_perm_pshufb (d))
22564 : return true;
22565 :
22566 : /* Try the AVX2 vpalignr instruction. */
22567 125013 : if (expand_vec_perm_palignr (d, true))
22568 : return true;
22569 :
22570 : /* Try the AVX512F vperm{w,b,s,d} instructions */
22571 124889 : if (ix86_expand_vec_one_operand_perm_avx512 (d))
22572 : return true;
22573 :
22574 : /* Try the AVX512F vpermt2/vpermi2 instructions. */
22575 124680 : if (ix86_expand_vec_perm_vpermt2 (NULL_RTX, NULL_RTX, NULL_RTX, NULL_RTX, d))
22576 : return true;
22577 :
22578 : /* See if we can get the same permutation in different vector integer
22579 : mode. */
22580 123770 : if (canonicalize_vector_int_perm (d, &nd) && expand_vec_perm_1 (&nd))
22581 : {
22582 6805 : if (!d->testing_p)
22583 1234 : emit_move_insn (d->target, gen_lowpart (d->vmode, nd.target));
22584 6805 : return true;
22585 : }
22586 : return false;
22587 : }
22588 :
22589 : /* Canonicalize vec_perm index to make the first index
22590 : always comes from the first vector. */
22591 : static void
22592 8168 : ix86_vec_perm_index_canon (struct expand_vec_perm_d *d)
22593 : {
22594 8168 : unsigned nelt = d->nelt;
22595 8168 : if (d->perm[0] < nelt)
22596 : return;
22597 :
22598 5 : for (unsigned i = 0; i != nelt; i++)
22599 4 : d->perm[i] = (d->perm[i] + nelt) % (2 * nelt);
22600 :
22601 1 : std::swap (d->op0, d->op1);
22602 1 : return;
22603 : }
22604 :
22605 : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement D
22606 : in terms of a pair of shufps+ shufps/pshufd instructions. */
22607 : static bool
22608 85707 : expand_vec_perm_shufps_shufps (struct expand_vec_perm_d *d)
22609 : {
22610 85707 : unsigned char perm1[4];
22611 85707 : machine_mode vmode = d->vmode;
22612 85707 : bool ok;
22613 85707 : unsigned i, j, k, count = 0;
22614 :
22615 85707 : if (d->one_operand_p
22616 80236 : || (vmode != V4SImode && vmode != V4SFmode))
22617 : return false;
22618 :
22619 35204 : if (d->testing_p)
22620 : return true;
22621 :
22622 8168 : ix86_vec_perm_index_canon (d);
22623 49008 : for (i = 0; i < 4; ++i)
22624 51107 : count += d->perm[i] > 3 ? 1 : 0;
22625 :
22626 8168 : gcc_assert (count & 3);
22627 :
22628 8168 : rtx tmp = gen_reg_rtx (vmode);
22629 : /* 2 from op0 and 2 from op1. */
22630 8168 : if (count == 2)
22631 : {
22632 : unsigned char perm2[4];
22633 18285 : for (i = 0, j = 0, k = 2; i < 4; ++i)
22634 14628 : if (d->perm[i] & 4)
22635 : {
22636 7314 : perm1[k++] = d->perm[i];
22637 7314 : perm2[i] = k - 1;
22638 : }
22639 : else
22640 : {
22641 7314 : perm1[j++] = d->perm[i];
22642 7314 : perm2[i] = j - 1;
22643 : }
22644 :
22645 : /* shufps. */
22646 7314 : ok = expand_vselect_vconcat (tmp, d->op0, d->op1,
22647 3657 : perm1, d->nelt, false);
22648 3657 : gcc_assert (ok);
22649 3657 : if (vmode == V4SImode && TARGET_SSE2)
22650 : /* pshufd. */
22651 2092 : ok = expand_vselect (d->target, tmp,
22652 2092 : perm2, d->nelt, false);
22653 : else
22654 : {
22655 : /* shufps. */
22656 1565 : perm2[2] += 4;
22657 1565 : perm2[3] += 4;
22658 1565 : ok = expand_vselect_vconcat (d->target, tmp, tmp,
22659 1565 : perm2, d->nelt, false);
22660 : }
22661 3657 : gcc_assert (ok);
22662 : }
22663 : /* 3 from one op and 1 from another. */
22664 : else
22665 : {
22666 22555 : unsigned pair_idx = 8, lone_idx = 8, shift;
22667 :
22668 : /* Find the lone index. */
22669 22555 : for (i = 0; i < 4; ++i)
22670 18044 : if ((d->perm[i] > 3 && count == 1)
22671 14739 : || (d->perm[i] < 4 && count == 3))
22672 18044 : lone_idx = i;
22673 :
22674 : /* When lone_idx is not 0, it must from second op(count == 1). */
22675 5717 : gcc_assert (count == (lone_idx ? 1 : 3));
22676 :
22677 : /* Find the pair index that sits in the same half as the lone index. */
22678 4511 : shift = lone_idx & 2;
22679 4511 : pair_idx = 1 - lone_idx + 2 * shift;
22680 :
22681 : /* First permutate lone index and pair index into the same vector as
22682 : [ lone, lone, pair, pair ]. */
22683 9022 : perm1[1] = perm1[0]
22684 4511 : = (count == 3) ? d->perm[lone_idx] : d->perm[lone_idx] - 4;
22685 9022 : perm1[3] = perm1[2]
22686 4511 : = (count == 3) ? d->perm[pair_idx] : d->perm[pair_idx] + 4;
22687 :
22688 : /* Always put the vector contains lone indx at the first. */
22689 4511 : if (count == 1)
22690 3305 : std::swap (d->op0, d->op1);
22691 :
22692 : /* shufps. */
22693 9022 : ok = expand_vselect_vconcat (tmp, d->op0, d->op1,
22694 4511 : perm1, d->nelt, false);
22695 4511 : gcc_assert (ok);
22696 :
22697 : /* Refine lone and pair index to original order. */
22698 4511 : perm1[shift] = lone_idx << 1;
22699 4511 : perm1[shift + 1] = pair_idx << 1;
22700 :
22701 : /* Select the remaining 2 elements in another vector. */
22702 13533 : for (i = 2 - shift; i < 4 - shift; ++i)
22703 9022 : perm1[i] = lone_idx == 1 ? d->perm[i] + 4 : d->perm[i];
22704 :
22705 : /* Adjust to original selector. */
22706 4511 : if (lone_idx > 1)
22707 2233 : std::swap (tmp, d->op1);
22708 :
22709 : /* shufps. */
22710 9022 : ok = expand_vselect_vconcat (d->target, tmp, d->op1,
22711 4511 : perm1, d->nelt, false);
22712 :
22713 4511 : gcc_assert (ok);
22714 : }
22715 :
22716 : return true;
22717 : }
22718 :
22719 : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement D
22720 : in terms of a pair of pshuflw + pshufhw instructions. */
22721 :
22722 : static bool
22723 102322 : expand_vec_perm_pshuflw_pshufhw (struct expand_vec_perm_d *d)
22724 : {
22725 102322 : unsigned char perm2[MAX_VECT_LEN];
22726 102322 : unsigned i;
22727 102322 : bool ok;
22728 :
22729 102322 : if (d->vmode != V8HImode || !d->one_operand_p)
22730 : return false;
22731 :
22732 : /* The two permutations only operate in 64-bit lanes. */
22733 12841 : for (i = 0; i < 4; ++i)
22734 10364 : if (d->perm[i] >= 4)
22735 : return false;
22736 12329 : for (i = 4; i < 8; ++i)
22737 9866 : if (d->perm[i] < 4)
22738 : return false;
22739 :
22740 2463 : if (d->testing_p)
22741 : return true;
22742 :
22743 : /* Emit the pshuflw. */
22744 134 : memcpy (perm2, d->perm, 4);
22745 670 : for (i = 4; i < 8; ++i)
22746 536 : perm2[i] = i;
22747 134 : ok = expand_vselect (d->target, d->op0, perm2, 8, d->testing_p);
22748 134 : gcc_assert (ok);
22749 :
22750 : /* Emit the pshufhw. */
22751 134 : memcpy (perm2 + 4, d->perm + 4, 4);
22752 670 : for (i = 0; i < 4; ++i)
22753 536 : perm2[i] = i;
22754 134 : ok = expand_vselect (d->target, d->target, perm2, 8, d->testing_p);
22755 134 : gcc_assert (ok);
22756 :
22757 : return true;
22758 : }
22759 :
22760 : /* Try to permute 2 64-bit vectors by punpckldq + 128-bit vector shuffle. */
22761 : static bool
22762 50503 : expand_vec_perm_punpckldq_pshuf (struct expand_vec_perm_d *d)
22763 : {
22764 50503 : if (GET_MODE_BITSIZE (d->vmode) != 64
22765 16210 : || !TARGET_MMX_WITH_SSE
22766 66713 : || d->one_operand_p)
22767 : return false;
22768 :
22769 14772 : machine_mode widen_vmode;
22770 14772 : switch (d->vmode)
22771 : {
22772 : /* pshufd. */
22773 : case E_V2SImode:
22774 : widen_vmode = V4SImode;
22775 : break;
22776 :
22777 : /* pshufd. */
22778 1173 : case E_V2SFmode:
22779 1173 : widen_vmode = V4SFmode;
22780 1173 : break;
22781 :
22782 5136 : case E_V4HImode:
22783 5136 : widen_vmode = V8HImode;
22784 : /* pshufb. */
22785 5136 : if (!TARGET_SSSE3)
22786 : return false;
22787 : break;
22788 :
22789 5969 : case E_V8QImode:
22790 : /* pshufb. */
22791 5969 : widen_vmode = V16QImode;
22792 5969 : if (!TARGET_SSSE3)
22793 : return false;
22794 : break;
22795 :
22796 : default:
22797 : return false;
22798 : }
22799 :
22800 5736 : if (d->testing_p)
22801 : return true;
22802 :
22803 368 : struct expand_vec_perm_d dperm;
22804 368 : dperm.target = gen_reg_rtx (widen_vmode);
22805 368 : rtx op0 = gen_reg_rtx (widen_vmode);
22806 368 : emit_move_insn (op0, gen_rtx_VEC_CONCAT (widen_vmode, d->op0, d->op1));
22807 368 : dperm.op0 = op0;
22808 368 : dperm.op1 = op0;
22809 368 : dperm.vmode = widen_vmode;
22810 368 : unsigned nelt = GET_MODE_NUNITS (widen_vmode);
22811 368 : dperm.nelt = nelt;
22812 368 : dperm.one_operand_p = true;
22813 368 : dperm.testing_p = false;
22814 :
22815 1990 : for (unsigned i = 0; i != nelt / 2; i++)
22816 : {
22817 1622 : dperm.perm[i] = d->perm[i];
22818 1622 : dperm.perm[i + nelt / 2] = d->perm[i];
22819 : }
22820 :
22821 368 : gcc_assert (expand_vec_perm_1 (&dperm));
22822 368 : emit_move_insn (d->target, lowpart_subreg (d->vmode,
22823 : dperm.target,
22824 : dperm.vmode));
22825 368 : return true;
22826 : }
22827 :
22828 : /* A subroutine of ix86_expand_vec_perm_const_1. Try to simplify
22829 : the permutation using the SSSE3 palignr instruction. This succeeds
22830 : when all of the elements in PERM fit within one vector and we merely
22831 : need to shift them down so that a single vector permutation has a
22832 : chance to succeed. If SINGLE_INSN_ONLY_P, succeed if only
22833 : the vpalignr instruction itself can perform the requested permutation. */
22834 :
22835 : static bool
22836 224872 : expand_vec_perm_palignr (struct expand_vec_perm_d *d, bool single_insn_only_p)
22837 : {
22838 224872 : unsigned i, nelt = d->nelt;
22839 224872 : unsigned min, max, minswap, maxswap;
22840 224872 : bool in_order, ok, swap = false;
22841 224872 : rtx shift, target;
22842 224872 : struct expand_vec_perm_d dcopy;
22843 :
22844 : /* Even with AVX, palignr only operates on 128-bit vectors,
22845 : in AVX2 palignr operates on both 128-bit lanes. */
22846 117914 : if ((!TARGET_SSSE3 || GET_MODE_SIZE (d->vmode) != 16)
22847 267492 : && (!TARGET_AVX2 || GET_MODE_SIZE (d->vmode) != 32))
22848 : return false;
22849 :
22850 34521 : min = 2 * nelt;
22851 34521 : max = 0;
22852 34521 : minswap = 2 * nelt;
22853 34521 : maxswap = 0;
22854 239317 : for (i = 0; i < nelt; ++i)
22855 : {
22856 204796 : unsigned e = d->perm[i];
22857 204796 : unsigned eswap = d->perm[i] ^ nelt;
22858 409592 : if (GET_MODE_SIZE (d->vmode) == 32)
22859 : {
22860 70192 : e = (e & ((nelt / 2) - 1)) | ((e & nelt) >> 1);
22861 70192 : eswap = e ^ (nelt / 2);
22862 : }
22863 204796 : if (e < min)
22864 : min = e;
22865 204796 : if (e > max)
22866 : max = e;
22867 204796 : if (eswap < minswap)
22868 : minswap = eswap;
22869 204796 : if (eswap > maxswap)
22870 : maxswap = eswap;
22871 : }
22872 34521 : if (min == 0
22873 50464 : || max - min >= (GET_MODE_SIZE (d->vmode) == 32 ? nelt / 2 : nelt))
22874 : {
22875 31321 : if (d->one_operand_p
22876 31052 : || minswap == 0
22877 67085 : || maxswap - minswap >= (GET_MODE_SIZE (d->vmode) == 32
22878 17882 : ? nelt / 2 : nelt))
22879 : return false;
22880 : swap = true;
22881 : min = minswap;
22882 6420 : max = maxswap;
22883 : }
22884 :
22885 : /* Given that we have SSSE3, we know we'll be able to implement the
22886 : single operand permutation after the palignr with pshufb for
22887 : 128-bit vectors. If SINGLE_INSN_ONLY_P, in_order has to be computed
22888 : first. */
22889 6474 : if (d->testing_p && GET_MODE_SIZE (d->vmode) == 16 && !single_insn_only_p)
22890 : return true;
22891 :
22892 6420 : dcopy = *d;
22893 6420 : if (swap)
22894 : {
22895 3220 : dcopy.op0 = d->op1;
22896 3220 : dcopy.op1 = d->op0;
22897 16172 : for (i = 0; i < nelt; ++i)
22898 12952 : dcopy.perm[i] ^= nelt;
22899 : }
22900 :
22901 : in_order = true;
22902 32668 : for (i = 0; i < nelt; ++i)
22903 : {
22904 26248 : unsigned e = dcopy.perm[i];
22905 26248 : if (GET_MODE_SIZE (d->vmode) == 32
22906 1152 : && e >= nelt
22907 26510 : && (e & (nelt / 2 - 1)) < min)
22908 262 : e = e - min - (nelt / 2);
22909 : else
22910 25986 : e = e - min;
22911 26248 : if (e != i)
22912 19394 : in_order = false;
22913 26248 : dcopy.perm[i] = e;
22914 : }
22915 6420 : dcopy.one_operand_p = true;
22916 :
22917 6420 : if (single_insn_only_p && !in_order)
22918 : return false;
22919 :
22920 : /* For AVX2, test whether we can permute the result in one instruction. */
22921 3271 : if (d->testing_p)
22922 : {
22923 54 : if (in_order)
22924 : return true;
22925 0 : dcopy.op1 = dcopy.op0;
22926 0 : return expand_vec_perm_1 (&dcopy);
22927 : }
22928 :
22929 6434 : shift = GEN_INT (min * GET_MODE_UNIT_BITSIZE (d->vmode));
22930 6434 : if (GET_MODE_SIZE (d->vmode) == 16)
22931 : {
22932 3145 : target = gen_reg_rtx (V1TImode);
22933 3145 : emit_insn (gen_ssse3_palignrv1ti (target,
22934 3145 : gen_lowpart (V1TImode, dcopy.op1),
22935 3145 : gen_lowpart (V1TImode, dcopy.op0),
22936 : shift));
22937 : }
22938 : else
22939 : {
22940 72 : target = gen_reg_rtx (V2TImode);
22941 72 : emit_insn (gen_avx2_palignrv2ti (target,
22942 72 : gen_lowpart (V2TImode, dcopy.op1),
22943 72 : gen_lowpart (V2TImode, dcopy.op0),
22944 : shift));
22945 : }
22946 :
22947 3217 : dcopy.op0 = dcopy.op1 = gen_lowpart (d->vmode, target);
22948 :
22949 : /* Test for the degenerate case where the alignment by itself
22950 : produces the desired permutation. */
22951 3217 : if (in_order)
22952 : {
22953 70 : emit_move_insn (d->target, dcopy.op0);
22954 70 : return true;
22955 : }
22956 :
22957 3147 : ok = expand_vec_perm_1 (&dcopy);
22958 3159 : gcc_assert (ok || GET_MODE_SIZE (d->vmode) == 32);
22959 :
22960 : return ok;
22961 : }
22962 :
22963 : /* A subroutine of ix86_expand_vec_perm_const_1. Try to simplify
22964 : the permutation using the SSE4_1 pblendv instruction. Potentially
22965 : reduces permutation from 2 pshufb and or to 1 pshufb and pblendv. */
22966 :
22967 : static bool
22968 90617 : expand_vec_perm_pblendv (struct expand_vec_perm_d *d)
22969 : {
22970 90617 : unsigned i, which, nelt = d->nelt;
22971 90617 : struct expand_vec_perm_d dcopy, dcopy1;
22972 90617 : machine_mode vmode = d->vmode;
22973 90617 : bool ok;
22974 :
22975 : /* Use the same checks as in expand_vec_perm_blend. */
22976 90617 : if (d->one_operand_p)
22977 : return false;
22978 88951 : if (TARGET_AVX2 && GET_MODE_SIZE (vmode) == 32)
22979 : ;
22980 83399 : else if (TARGET_AVX && (vmode == V4DFmode || vmode == V8SFmode))
22981 : ;
22982 80052 : else if (TARGET_SSE4_1
22983 90596 : && (GET_MODE_SIZE (vmode) == 16
22984 9154 : || (TARGET_MMX_WITH_SSE && GET_MODE_SIZE (vmode) == 8)
22985 2733 : || GET_MODE_SIZE (vmode) == 4))
22986 : ;
22987 : else
22988 : return false;
22989 :
22990 : /* Figure out where permutation elements stay not in their
22991 : respective lanes. */
22992 108472 : for (i = 0, which = 0; i < nelt; ++i)
22993 : {
22994 93178 : unsigned e = d->perm[i];
22995 93178 : if (e != i)
22996 128205 : which |= (e < nelt ? 1 : 2);
22997 : }
22998 : /* We can pblend the part where elements stay not in their
22999 : respective lanes only when these elements are all in one
23000 : half of a permutation.
23001 : {0 1 8 3 4 5 9 7} is ok as 8, 9 are at not at their respective
23002 : lanes, but both 8 and 9 >= 8
23003 : {0 1 8 3 4 5 2 7} is not ok as 2 and 8 are not at their
23004 : respective lanes and 8 >= 8, but 2 not. */
23005 15294 : if (which != 1 && which != 2)
23006 : return false;
23007 3175 : if (d->testing_p && GET_MODE_SIZE (vmode) == 16)
23008 : return true;
23009 :
23010 : /* First we apply one operand permutation to the part where
23011 : elements stay not in their respective lanes. */
23012 1958 : dcopy = *d;
23013 1958 : if (which == 2)
23014 1958 : dcopy.op0 = dcopy.op1 = d->op1;
23015 : else
23016 0 : dcopy.op0 = dcopy.op1 = d->op0;
23017 1958 : if (!d->testing_p)
23018 741 : dcopy.target = gen_reg_rtx (vmode);
23019 1958 : dcopy.one_operand_p = true;
23020 :
23021 15762 : for (i = 0; i < nelt; ++i)
23022 13804 : dcopy.perm[i] = d->perm[i] & (nelt - 1);
23023 :
23024 1958 : ok = expand_vec_perm_1 (&dcopy);
23025 3916 : if (GET_MODE_SIZE (vmode) != 16 && !ok)
23026 : return false;
23027 : else
23028 1663 : gcc_assert (ok);
23029 1663 : if (d->testing_p)
23030 : return true;
23031 :
23032 : /* Next we put permuted elements into their positions. */
23033 679 : dcopy1 = *d;
23034 679 : if (which == 2)
23035 679 : dcopy1.op1 = dcopy.target;
23036 : else
23037 0 : dcopy1.op0 = dcopy.target;
23038 :
23039 5751 : for (i = 0; i < nelt; ++i)
23040 5072 : dcopy1.perm[i] = ((d->perm[i] >= nelt) ? (nelt + i) : i);
23041 :
23042 679 : ok = expand_vec_perm_blend (&dcopy1);
23043 679 : gcc_assert (ok);
23044 :
23045 : return true;
23046 : }
23047 :
23048 : static bool expand_vec_perm_interleave3 (struct expand_vec_perm_d *d);
23049 :
23050 : /* A subroutine of ix86_expand_vec_perm_const_1. Try to simplify
23051 : a two vector permutation into a single vector permutation by using
23052 : an interleave operation to merge the vectors. */
23053 :
23054 : static bool
23055 96724 : expand_vec_perm_interleave2 (struct expand_vec_perm_d *d)
23056 : {
23057 96724 : struct expand_vec_perm_d dremap, dfinal;
23058 96724 : unsigned i, nelt = d->nelt, nelt2 = nelt / 2;
23059 96724 : unsigned HOST_WIDE_INT contents;
23060 96724 : unsigned char remap[2 * MAX_VECT_LEN];
23061 96724 : rtx_insn *seq;
23062 96724 : bool ok, same_halves = false;
23063 :
23064 96724 : if (GET_MODE_SIZE (d->vmode) == 4
23065 173314 : || GET_MODE_SIZE (d->vmode) == 8
23066 234324 : || GET_MODE_SIZE (d->vmode) == 16)
23067 : {
23068 90196 : if (d->one_operand_p)
23069 : return false;
23070 : }
23071 13056 : else if (GET_MODE_SIZE (d->vmode) == 32)
23072 : {
23073 6203 : if (!TARGET_AVX)
23074 : return false;
23075 : /* For 32-byte modes allow even d->one_operand_p.
23076 : The lack of cross-lane shuffling in some instructions
23077 : might prevent a single insn shuffle. */
23078 6203 : dfinal = *d;
23079 6203 : dfinal.testing_p = true;
23080 : /* If expand_vec_perm_interleave3 can expand this into
23081 : a 3 insn sequence, give up and let it be expanded as
23082 : 3 insn sequence. While that is one insn longer,
23083 : it doesn't need a memory operand and in the common
23084 : case that both interleave low and high permutations
23085 : with the same operands are adjacent needs 4 insns
23086 : for both after CSE. */
23087 6203 : if (expand_vec_perm_interleave3 (&dfinal))
23088 : return false;
23089 : }
23090 : else
23091 : return false;
23092 :
23093 : /* Examine from whence the elements come. */
23094 90782 : contents = 0;
23095 680328 : for (i = 0; i < nelt; ++i)
23096 589546 : contents |= HOST_WIDE_INT_1U << d->perm[i];
23097 :
23098 90782 : memset (remap, 0xff, sizeof (remap));
23099 90782 : dremap = *d;
23100 :
23101 90782 : if (GET_MODE_SIZE (d->vmode) == 4
23102 173273 : || GET_MODE_SIZE (d->vmode) == 8)
23103 : {
23104 24706 : unsigned HOST_WIDE_INT h1, h2, h3, h4;
23105 :
23106 : /* Split the two input vectors into 4 halves. */
23107 24706 : h1 = (HOST_WIDE_INT_1U << nelt2) - 1;
23108 24706 : h2 = h1 << nelt2;
23109 24706 : h3 = h2 << nelt2;
23110 24706 : h4 = h3 << nelt2;
23111 :
23112 : /* If the elements from the low halves use interleave low,
23113 : and similarly for interleave high. */
23114 24706 : if ((contents & (h1 | h3)) == contents)
23115 : {
23116 : /* punpckl* */
23117 2796 : for (i = 0; i < nelt2; ++i)
23118 : {
23119 1912 : remap[i] = i * 2;
23120 1912 : remap[i + nelt] = i * 2 + 1;
23121 1912 : dremap.perm[i * 2] = i;
23122 1912 : dremap.perm[i * 2 + 1] = i + nelt;
23123 : }
23124 : }
23125 23822 : else if ((contents & (h2 | h4)) == contents)
23126 : {
23127 : /* punpckh* */
23128 2277 : for (i = 0; i < nelt2; ++i)
23129 : {
23130 1548 : remap[i + nelt2] = i * 2;
23131 1548 : remap[i + nelt + nelt2] = i * 2 + 1;
23132 1548 : dremap.perm[i * 2] = i + nelt2;
23133 1548 : dremap.perm[i * 2 + 1] = i + nelt + nelt2;
23134 : }
23135 : }
23136 : else
23137 : return false;
23138 : }
23139 132152 : else if (GET_MODE_SIZE (d->vmode) == 16)
23140 : {
23141 60099 : unsigned HOST_WIDE_INT h1, h2, h3, h4;
23142 :
23143 : /* Split the two input vectors into 4 halves. */
23144 60099 : h1 = (HOST_WIDE_INT_1U << nelt2) - 1;
23145 60099 : h2 = h1 << nelt2;
23146 60099 : h3 = h2 << nelt2;
23147 60099 : h4 = h3 << nelt2;
23148 :
23149 : /* If the elements from the low halves use interleave low, and similarly
23150 : for interleave high. If the elements are from mis-matched halves, we
23151 : can use shufps for V4SF/V4SI or do a DImode shuffle. */
23152 60099 : if ((contents & (h1 | h3)) == contents)
23153 : {
23154 : /* punpckl* */
23155 5368 : for (i = 0; i < nelt2; ++i)
23156 : {
23157 3906 : remap[i] = i * 2;
23158 3906 : remap[i + nelt] = i * 2 + 1;
23159 3906 : dremap.perm[i * 2] = i;
23160 3906 : dremap.perm[i * 2 + 1] = i + nelt;
23161 : }
23162 1462 : if (!TARGET_SSE2 && d->vmode == V4SImode)
23163 0 : dremap.vmode = V4SFmode;
23164 : }
23165 58637 : else if ((contents & (h2 | h4)) == contents)
23166 : {
23167 : /* punpckh* */
23168 4563 : for (i = 0; i < nelt2; ++i)
23169 : {
23170 3278 : remap[i + nelt2] = i * 2;
23171 3278 : remap[i + nelt + nelt2] = i * 2 + 1;
23172 3278 : dremap.perm[i * 2] = i + nelt2;
23173 3278 : dremap.perm[i * 2 + 1] = i + nelt + nelt2;
23174 : }
23175 1285 : if (!TARGET_SSE2 && d->vmode == V4SImode)
23176 0 : dremap.vmode = V4SFmode;
23177 : }
23178 57352 : else if ((contents & (h1 | h4)) == contents)
23179 : {
23180 : /* shufps */
23181 2990 : for (i = 0; i < nelt2; ++i)
23182 : {
23183 2232 : remap[i] = i;
23184 2232 : remap[i + nelt + nelt2] = i + nelt2;
23185 2232 : dremap.perm[i] = i;
23186 2232 : dremap.perm[i + nelt2] = i + nelt + nelt2;
23187 : }
23188 758 : if (nelt != 4)
23189 : {
23190 : /* shufpd */
23191 120 : dremap.vmode = V2DImode;
23192 120 : dremap.nelt = 2;
23193 120 : dremap.perm[0] = 0;
23194 120 : dremap.perm[1] = 3;
23195 : }
23196 : }
23197 56594 : else if ((contents & (h2 | h3)) == contents)
23198 : {
23199 : /* shufps */
23200 4002 : for (i = 0; i < nelt2; ++i)
23201 : {
23202 2914 : remap[i + nelt2] = i;
23203 2914 : remap[i + nelt] = i + nelt2;
23204 2914 : dremap.perm[i] = i + nelt2;
23205 2914 : dremap.perm[i + nelt2] = i + nelt;
23206 : }
23207 1088 : if (nelt != 4)
23208 : {
23209 : /* shufpd */
23210 139 : dremap.vmode = V2DImode;
23211 139 : dremap.nelt = 2;
23212 139 : dremap.perm[0] = 1;
23213 139 : dremap.perm[1] = 2;
23214 : }
23215 : }
23216 : else
23217 : return false;
23218 : }
23219 : else
23220 : {
23221 5977 : unsigned int nelt4 = nelt / 4, nzcnt = 0;
23222 5977 : unsigned HOST_WIDE_INT q[8];
23223 5977 : unsigned int nonzero_halves[4];
23224 :
23225 : /* Split the two input vectors into 8 quarters. */
23226 5977 : q[0] = (HOST_WIDE_INT_1U << nelt4) - 1;
23227 47816 : for (i = 1; i < 8; ++i)
23228 41839 : q[i] = q[0] << (nelt4 * i);
23229 29885 : for (i = 0; i < 4; ++i)
23230 23908 : if (((q[2 * i] | q[2 * i + 1]) & contents) != 0)
23231 : {
23232 21650 : nonzero_halves[nzcnt] = i;
23233 21650 : ++nzcnt;
23234 : }
23235 :
23236 5977 : if (nzcnt == 1)
23237 : {
23238 211 : gcc_assert (d->one_operand_p);
23239 211 : nonzero_halves[1] = nonzero_halves[0];
23240 211 : same_halves = true;
23241 : }
23242 5766 : else if (d->one_operand_p)
23243 : {
23244 39 : gcc_assert (nonzero_halves[0] == 0);
23245 39 : gcc_assert (nonzero_halves[1] == 1);
23246 : }
23247 :
23248 5977 : if (nzcnt <= 2)
23249 : {
23250 502 : if (d->perm[0] / nelt2 == nonzero_halves[1])
23251 : {
23252 : /* Attempt to increase the likelihood that dfinal
23253 : shuffle will be intra-lane. */
23254 235 : std::swap (nonzero_halves[0], nonzero_halves[1]);
23255 : }
23256 :
23257 : /* vperm2f128 or vperm2i128. */
23258 3292 : for (i = 0; i < nelt2; ++i)
23259 : {
23260 2790 : remap[i + nonzero_halves[1] * nelt2] = i + nelt2;
23261 2790 : remap[i + nonzero_halves[0] * nelt2] = i;
23262 2790 : dremap.perm[i + nelt2] = i + nonzero_halves[1] * nelt2;
23263 2790 : dremap.perm[i] = i + nonzero_halves[0] * nelt2;
23264 : }
23265 :
23266 502 : if (d->vmode != V8SFmode
23267 : && d->vmode != V4DFmode
23268 : && d->vmode != V8SImode)
23269 : {
23270 148 : dremap.vmode = V8SImode;
23271 148 : dremap.nelt = 8;
23272 740 : for (i = 0; i < 4; ++i)
23273 : {
23274 592 : dremap.perm[i] = i + nonzero_halves[0] * 4;
23275 592 : dremap.perm[i + 4] = i + nonzero_halves[1] * 4;
23276 : }
23277 : }
23278 : }
23279 5475 : else if (d->one_operand_p)
23280 5010 : return false;
23281 5475 : else if (TARGET_AVX2
23282 2172 : && (contents & (q[0] | q[2] | q[4] | q[6])) == contents)
23283 : {
23284 : /* vpunpckl* */
23285 491 : for (i = 0; i < nelt4; ++i)
23286 : {
23287 247 : remap[i] = i * 2;
23288 247 : remap[i + nelt] = i * 2 + 1;
23289 247 : remap[i + nelt2] = i * 2 + nelt2;
23290 247 : remap[i + nelt + nelt2] = i * 2 + nelt2 + 1;
23291 247 : dremap.perm[i * 2] = i;
23292 247 : dremap.perm[i * 2 + 1] = i + nelt;
23293 247 : dremap.perm[i * 2 + nelt2] = i + nelt2;
23294 247 : dremap.perm[i * 2 + nelt2 + 1] = i + nelt + nelt2;
23295 : }
23296 : }
23297 5231 : else if (TARGET_AVX2
23298 1928 : && (contents & (q[1] | q[3] | q[5] | q[7])) == contents)
23299 : {
23300 : /* vpunpckh* */
23301 445 : for (i = 0; i < nelt4; ++i)
23302 : {
23303 224 : remap[i + nelt4] = i * 2;
23304 224 : remap[i + nelt + nelt4] = i * 2 + 1;
23305 224 : remap[i + nelt2 + nelt4] = i * 2 + nelt2;
23306 224 : remap[i + nelt + nelt2 + nelt4] = i * 2 + nelt2 + 1;
23307 224 : dremap.perm[i * 2] = i + nelt4;
23308 224 : dremap.perm[i * 2 + 1] = i + nelt + nelt4;
23309 224 : dremap.perm[i * 2 + nelt2] = i + nelt2 + nelt4;
23310 224 : dremap.perm[i * 2 + nelt2 + 1] = i + nelt + nelt2 + nelt4;
23311 : }
23312 : }
23313 : else
23314 : return false;
23315 : }
23316 :
23317 : /* Use the remapping array set up above to move the elements from their
23318 : swizzled locations into their final destinations. */
23319 7173 : dfinal = *d;
23320 46217 : for (i = 0; i < nelt; ++i)
23321 : {
23322 39044 : unsigned e = remap[d->perm[i]];
23323 39044 : gcc_assert (e < nelt);
23324 : /* If same_halves is true, both halves of the remapped vector are the
23325 : same. Avoid cross-lane accesses if possible. */
23326 39044 : if (same_halves && i >= nelt2)
23327 : {
23328 784 : gcc_assert (e < nelt2);
23329 784 : dfinal.perm[i] = e + nelt2;
23330 : }
23331 : else
23332 38260 : dfinal.perm[i] = e;
23333 : }
23334 7173 : if (!d->testing_p)
23335 : {
23336 2737 : dremap.target = gen_reg_rtx (dremap.vmode);
23337 2737 : dfinal.op0 = gen_lowpart (dfinal.vmode, dremap.target);
23338 : }
23339 7173 : dfinal.op1 = dfinal.op0;
23340 7173 : dfinal.one_operand_p = true;
23341 :
23342 : /* Test if the final remap can be done with a single insn. For V4SFmode or
23343 : V4SImode this *will* succeed. For V8HImode or V16QImode it may not. */
23344 7173 : start_sequence ();
23345 7173 : ok = expand_vec_perm_1 (&dfinal);
23346 7173 : seq = end_sequence ();
23347 :
23348 7173 : if (!ok)
23349 : return false;
23350 :
23351 5939 : if (d->testing_p)
23352 : return true;
23353 :
23354 2698 : if (dremap.vmode != dfinal.vmode)
23355 : {
23356 57 : dremap.op0 = gen_lowpart (dremap.vmode, dremap.op0);
23357 57 : dremap.op1 = gen_lowpart (dremap.vmode, dremap.op1);
23358 : }
23359 :
23360 2698 : ok = expand_vec_perm_1 (&dremap);
23361 2698 : gcc_assert (ok);
23362 :
23363 2698 : emit_insn (seq);
23364 2698 : return true;
23365 : }
23366 :
23367 : /* A subroutine of ix86_expand_vec_perm_const_1. Try to simplify
23368 : a single vector cross-lane permutation into vpermq followed
23369 : by any of the single insn permutations. */
23370 :
23371 : static bool
23372 90685 : expand_vec_perm_vpermq_perm_1 (struct expand_vec_perm_d *d)
23373 : {
23374 90685 : struct expand_vec_perm_d dremap, dfinal;
23375 90685 : unsigned i, j, nelt = d->nelt, nelt2 = nelt / 2, nelt4 = nelt / 4;
23376 90685 : unsigned contents[2];
23377 90685 : bool ok;
23378 :
23379 90685 : if (!(TARGET_AVX2
23380 4035 : && (d->vmode == V32QImode || d->vmode == V16HImode)
23381 256 : && d->one_operand_p))
23382 : return false;
23383 :
23384 7 : contents[0] = 0;
23385 7 : contents[1] = 0;
23386 103 : for (i = 0; i < nelt2; ++i)
23387 : {
23388 96 : contents[0] |= 1u << (d->perm[i] / nelt4);
23389 96 : contents[1] |= 1u << (d->perm[i + nelt2] / nelt4);
23390 : }
23391 :
23392 7 : for (i = 0; i < 2; ++i)
23393 : {
23394 : unsigned int cnt = 0;
23395 21 : for (j = 0; j < 4; ++j)
23396 21 : if ((contents[i] & (1u << j)) != 0 && ++cnt > 2)
23397 : return false;
23398 : }
23399 :
23400 0 : if (d->testing_p)
23401 : return true;
23402 :
23403 0 : dremap = *d;
23404 0 : dremap.vmode = V4DImode;
23405 0 : dremap.nelt = 4;
23406 0 : dremap.target = gen_reg_rtx (V4DImode);
23407 0 : dremap.op0 = gen_lowpart (V4DImode, d->op0);
23408 0 : dremap.op1 = dremap.op0;
23409 0 : dremap.one_operand_p = true;
23410 0 : for (i = 0; i < 2; ++i)
23411 : {
23412 : unsigned int cnt = 0;
23413 0 : for (j = 0; j < 4; ++j)
23414 0 : if ((contents[i] & (1u << j)) != 0)
23415 0 : dremap.perm[2 * i + cnt++] = j;
23416 0 : for (; cnt < 2; ++cnt)
23417 0 : dremap.perm[2 * i + cnt] = 0;
23418 : }
23419 :
23420 0 : dfinal = *d;
23421 0 : dfinal.op0 = gen_lowpart (dfinal.vmode, dremap.target);
23422 0 : dfinal.op1 = dfinal.op0;
23423 0 : dfinal.one_operand_p = true;
23424 0 : for (i = 0, j = 0; i < nelt; ++i)
23425 : {
23426 0 : if (i == nelt2)
23427 0 : j = 2;
23428 0 : dfinal.perm[i] = (d->perm[i] & (nelt4 - 1)) | (j ? nelt2 : 0);
23429 0 : if ((d->perm[i] / nelt4) == dremap.perm[j])
23430 : ;
23431 0 : else if ((d->perm[i] / nelt4) == dremap.perm[j + 1])
23432 0 : dfinal.perm[i] |= nelt4;
23433 : else
23434 0 : gcc_unreachable ();
23435 : }
23436 :
23437 0 : ok = expand_vec_perm_1 (&dremap);
23438 0 : gcc_assert (ok);
23439 :
23440 0 : ok = expand_vec_perm_1 (&dfinal);
23441 0 : gcc_assert (ok);
23442 :
23443 : return true;
23444 : }
23445 :
23446 : static bool canonicalize_perm (struct expand_vec_perm_d *d);
23447 :
23448 : /* A subroutine of ix86_expand_vec_perm_const_1. Try to expand
23449 : a vector permutation using two instructions, vperm2f128 resp.
23450 : vperm2i128 followed by any single in-lane permutation. */
23451 :
23452 : static bool
23453 90685 : expand_vec_perm_vperm2f128 (struct expand_vec_perm_d *d)
23454 : {
23455 90685 : struct expand_vec_perm_d dfirst, dsecond;
23456 90685 : unsigned i, j, nelt = d->nelt, nelt2 = nelt / 2, perm;
23457 90685 : bool ok;
23458 :
23459 90685 : if (!TARGET_AVX
23460 22186 : || GET_MODE_SIZE (d->vmode) != 32
23461 96046 : || (d->vmode != V8SFmode && d->vmode != V4DFmode && !TARGET_AVX2))
23462 : return false;
23463 :
23464 5177 : dsecond = *d;
23465 5177 : dsecond.one_operand_p = false;
23466 5177 : dsecond.testing_p = true;
23467 :
23468 : /* ((perm << 2)|perm) & 0x33 is the vperm2[fi]128
23469 : immediate. For perm < 16 the second permutation uses
23470 : d->op0 as first operand, for perm >= 16 it uses d->op1
23471 : as first operand. The second operand is the result of
23472 : vperm2[fi]128. */
23473 169527 : for (perm = 0; perm < 32; perm++)
23474 : {
23475 : /* Ignore permutations which do not move anything cross-lane. */
23476 164433 : if (perm < 16)
23477 : {
23478 : /* The second shuffle for e.g. V4DFmode has
23479 : 0123 and ABCD operands.
23480 : Ignore AB23, as 23 is already in the second lane
23481 : of the first operand. */
23482 82470 : if ((perm & 0xc) == (1 << 2)) continue;
23483 : /* And 01CD, as 01 is in the first lane of the first
23484 : operand. */
23485 61838 : if ((perm & 3) == 0) continue;
23486 : /* And 4567, as then the vperm2[fi]128 doesn't change
23487 : anything on the original 4567 second operand. */
23488 46361 : if ((perm & 0xf) == ((3 << 2) | 2)) continue;
23489 : }
23490 : else
23491 : {
23492 : /* The second shuffle for e.g. V4DFmode has
23493 : 4567 and ABCD operands.
23494 : Ignore AB67, as 67 is already in the second lane
23495 : of the first operand. */
23496 81963 : if ((perm & 0xc) == (3 << 2)) continue;
23497 : /* And 45CD, as 45 is in the first lane of the first
23498 : operand. */
23499 61587 : if ((perm & 3) == 2) continue;
23500 : /* And 0123, as then the vperm2[fi]128 doesn't change
23501 : anything on the original 0123 first operand. */
23502 46214 : if ((perm & 0xf) == (1 << 2)) continue;
23503 : }
23504 :
23505 212352 : for (i = 0; i < nelt; i++)
23506 : {
23507 211225 : j = d->perm[i] / nelt2;
23508 392886 : if (j == ((perm >> (2 * (i >= nelt2))) & 3))
23509 52316 : dsecond.perm[i] = nelt + (i & nelt2) + (d->perm[i] & (nelt2 - 1));
23510 263771 : else if (j == (unsigned) (i >= nelt2) + 2 * (perm >= 16))
23511 77743 : dsecond.perm[i] = d->perm[i] & (nelt - 1);
23512 : else
23513 : break;
23514 : }
23515 :
23516 82293 : if (i == nelt)
23517 : {
23518 1127 : start_sequence ();
23519 1127 : ok = expand_vec_perm_1 (&dsecond);
23520 1127 : end_sequence ();
23521 : }
23522 : else
23523 : ok = false;
23524 :
23525 1127 : if (ok)
23526 : {
23527 68 : if (d->testing_p)
23528 : return true;
23529 :
23530 : /* Found a usable second shuffle. dfirst will be
23531 : vperm2f128 on d->op0 and d->op1. */
23532 46 : dsecond.testing_p = false;
23533 46 : dfirst = *d;
23534 46 : dfirst.target = gen_reg_rtx (d->vmode);
23535 270 : for (i = 0; i < nelt; i++)
23536 448 : dfirst.perm[i] = (i & (nelt2 - 1))
23537 336 : + ((perm >> (2 * (i >= nelt2))) & 3) * nelt2;
23538 :
23539 46 : canonicalize_perm (&dfirst);
23540 46 : ok = expand_vec_perm_1 (&dfirst);
23541 46 : gcc_assert (ok);
23542 :
23543 : /* And dsecond is some single insn shuffle, taking
23544 : d->op0 and result of vperm2f128 (if perm < 16) or
23545 : d->op1 and result of vperm2f128 (otherwise). */
23546 46 : if (perm >= 16)
23547 46 : dsecond.op0 = dsecond.op1;
23548 46 : dsecond.op1 = dfirst.target;
23549 :
23550 46 : ok = expand_vec_perm_1 (&dsecond);
23551 46 : gcc_assert (ok);
23552 :
23553 : return true;
23554 : }
23555 :
23556 : /* For one operand, the only useful vperm2f128 permutation is 0x01
23557 : aka lanes swap. */
23558 82225 : if (d->one_operand_p)
23559 : return false;
23560 : }
23561 :
23562 : return false;
23563 : }
23564 :
23565 : /* A subroutine of ix86_expand_vec_perm_const_1. Try to simplify
23566 : a two vector permutation using 2 intra-lane interleave insns
23567 : and cross-lane shuffle for 32-byte vectors. */
23568 :
23569 : static bool
23570 34163 : expand_vec_perm_interleave3 (struct expand_vec_perm_d *d)
23571 : {
23572 34163 : unsigned i, nelt;
23573 34163 : rtx (*gen) (rtx, rtx, rtx);
23574 :
23575 34163 : if (d->one_operand_p)
23576 : return false;
23577 31895 : if (TARGET_AVX2 && GET_MODE_SIZE (d->vmode) == 32)
23578 : ;
23579 25235 : else if (TARGET_AVX && (d->vmode == V8SFmode || d->vmode == V4DFmode))
23580 : ;
23581 : else
23582 : return false;
23583 :
23584 8325 : nelt = d->nelt;
23585 8325 : if (d->perm[0] != 0 && d->perm[0] != nelt / 2)
23586 : return false;
23587 8698 : for (i = 0; i < nelt; i += 2)
23588 8326 : if (d->perm[i] != d->perm[0] + i / 2
23589 7453 : || d->perm[i + 1] != d->perm[0] + i / 2 + nelt)
23590 : return false;
23591 :
23592 372 : if (d->testing_p)
23593 : return true;
23594 :
23595 56 : switch (d->vmode)
23596 : {
23597 32 : case E_V32QImode:
23598 32 : if (d->perm[0])
23599 : gen = gen_vec_interleave_highv32qi;
23600 : else
23601 16 : gen = gen_vec_interleave_lowv32qi;
23602 : break;
23603 18 : case E_V16HImode:
23604 18 : if (d->perm[0])
23605 : gen = gen_vec_interleave_highv16hi;
23606 : else
23607 9 : gen = gen_vec_interleave_lowv16hi;
23608 : break;
23609 0 : case E_V8SImode:
23610 0 : if (d->perm[0])
23611 : gen = gen_vec_interleave_highv8si;
23612 : else
23613 0 : gen = gen_vec_interleave_lowv8si;
23614 : break;
23615 4 : case E_V4DImode:
23616 4 : if (d->perm[0])
23617 : gen = gen_vec_interleave_highv4di;
23618 : else
23619 2 : gen = gen_vec_interleave_lowv4di;
23620 : break;
23621 2 : case E_V8SFmode:
23622 2 : if (d->perm[0])
23623 : gen = gen_vec_interleave_highv8sf;
23624 : else
23625 1 : gen = gen_vec_interleave_lowv8sf;
23626 : break;
23627 0 : case E_V4DFmode:
23628 0 : if (d->perm[0])
23629 : gen = gen_vec_interleave_highv4df;
23630 : else
23631 0 : gen = gen_vec_interleave_lowv4df;
23632 : break;
23633 0 : default:
23634 0 : gcc_unreachable ();
23635 : }
23636 :
23637 56 : emit_insn (gen (d->target, d->op0, d->op1));
23638 56 : return true;
23639 : }
23640 :
23641 : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement
23642 : a single vector permutation using a single intra-lane vector
23643 : permutation, vperm2f128 swapping the lanes and vblend* insn blending
23644 : the non-swapped and swapped vectors together. */
23645 :
23646 : static bool
23647 27814 : expand_vec_perm_vperm2f128_vblend (struct expand_vec_perm_d *d)
23648 : {
23649 27814 : struct expand_vec_perm_d dfirst, dsecond;
23650 27814 : unsigned i, j, msk, nelt = d->nelt, nelt2 = nelt / 2;
23651 27814 : rtx_insn *seq;
23652 27814 : bool ok;
23653 27814 : rtx (*blend) (rtx, rtx, rtx, rtx) = NULL;
23654 :
23655 27814 : if (!TARGET_AVX
23656 2933 : || TARGET_AVX2
23657 1814 : || (d->vmode != V8SFmode && d->vmode != V4DFmode)
23658 1630 : || !d->one_operand_p)
23659 : return false;
23660 :
23661 0 : dfirst = *d;
23662 0 : for (i = 0; i < nelt; i++)
23663 0 : dfirst.perm[i] = 0xff;
23664 0 : for (i = 0, msk = 0; i < nelt; i++)
23665 : {
23666 0 : j = (d->perm[i] & nelt2) ? i | nelt2 : i & ~nelt2;
23667 0 : if (dfirst.perm[j] != 0xff && dfirst.perm[j] != d->perm[i])
23668 : return false;
23669 0 : dfirst.perm[j] = d->perm[i];
23670 0 : if (j != i)
23671 0 : msk |= (1 << i);
23672 : }
23673 0 : for (i = 0; i < nelt; i++)
23674 0 : if (dfirst.perm[i] == 0xff)
23675 0 : dfirst.perm[i] = i;
23676 :
23677 0 : if (!d->testing_p)
23678 0 : dfirst.target = gen_reg_rtx (dfirst.vmode);
23679 :
23680 0 : start_sequence ();
23681 0 : ok = expand_vec_perm_1 (&dfirst);
23682 0 : seq = end_sequence ();
23683 :
23684 0 : if (!ok)
23685 : return false;
23686 :
23687 0 : if (d->testing_p)
23688 : return true;
23689 :
23690 0 : emit_insn (seq);
23691 :
23692 0 : dsecond = *d;
23693 0 : dsecond.op0 = dfirst.target;
23694 0 : dsecond.op1 = dfirst.target;
23695 0 : dsecond.one_operand_p = true;
23696 0 : dsecond.target = gen_reg_rtx (dsecond.vmode);
23697 0 : for (i = 0; i < nelt; i++)
23698 0 : dsecond.perm[i] = i ^ nelt2;
23699 :
23700 0 : ok = expand_vec_perm_1 (&dsecond);
23701 0 : gcc_assert (ok);
23702 :
23703 0 : blend = d->vmode == V8SFmode ? gen_avx_blendps256 : gen_avx_blendpd256;
23704 0 : emit_insn (blend (d->target, dfirst.target, dsecond.target, GEN_INT (msk)));
23705 0 : return true;
23706 : }
23707 :
23708 : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement
23709 : a two vector permutation using two single vector permutations and
23710 : {,v}{,p}unpckl{ps,pd,bw,wd,dq}. If two_insn, succeed only if one
23711 : of dfirst or dsecond is identity permutation. */
23712 :
23713 : static bool
23714 116768 : expand_vec_perm_2perm_interleave (struct expand_vec_perm_d *d, bool two_insn)
23715 : {
23716 116768 : unsigned i, nelt = d->nelt, nelt2 = nelt / 2, lane = nelt;
23717 116768 : struct expand_vec_perm_d dfirst, dsecond, dfinal;
23718 116768 : bool ident1 = true, ident2 = true;
23719 :
23720 116768 : if (d->one_operand_p)
23721 : return false;
23722 :
23723 211738 : if (GET_MODE_SIZE (d->vmode) == 16)
23724 : {
23725 63700 : if (!TARGET_SSE)
23726 : return false;
23727 63700 : if (d->vmode != V4SFmode && d->vmode != V2DFmode && !TARGET_SSE2)
23728 : return false;
23729 : }
23730 84338 : else if (GET_MODE_SIZE (d->vmode) == 32)
23731 : {
23732 7291 : if (!TARGET_AVX)
23733 : return false;
23734 7291 : if (d->vmode != V8SFmode && d->vmode != V4DFmode && !TARGET_AVX2)
23735 : return false;
23736 : lane = nelt2;
23737 : }
23738 : else
23739 : return false;
23740 :
23741 231856 : for (i = 1; i < nelt; i++)
23742 198459 : if ((d->perm[i] >= nelt) != ((d->perm[0] >= nelt) ^ (i & 1)))
23743 : return false;
23744 :
23745 33397 : dfirst = *d;
23746 33397 : dsecond = *d;
23747 33397 : dfinal = *d;
23748 33397 : dfirst.op1 = dfirst.op0;
23749 33397 : dfirst.one_operand_p = true;
23750 33397 : dsecond.op0 = dsecond.op1;
23751 33397 : dsecond.one_operand_p = true;
23752 :
23753 218505 : for (i = 0; i < nelt; i++)
23754 185108 : if (d->perm[i] >= nelt)
23755 : {
23756 92554 : dsecond.perm[i / 2 + (i >= lane ? lane / 2 : 0)] = d->perm[i] - nelt;
23757 92554 : if (d->perm[i] - nelt != i / 2 + (i >= lane ? lane / 2 : 0))
23758 84218 : ident2 = false;
23759 92554 : dsecond.perm[i / 2 + (i >= lane ? lane : lane / 2)]
23760 92554 : = d->perm[i] - nelt;
23761 : }
23762 : else
23763 : {
23764 92554 : dfirst.perm[i / 2 + (i >= lane ? lane / 2 : 0)] = d->perm[i];
23765 92554 : if (d->perm[i] != i / 2 + (i >= lane ? lane / 2 : 0))
23766 75819 : ident1 = false;
23767 92554 : dfirst.perm[i / 2 + (i >= lane ? lane : lane / 2)] = d->perm[i];
23768 : }
23769 :
23770 33397 : if (two_insn && !ident1 && !ident2)
23771 : return false;
23772 :
23773 3899 : if (!d->testing_p)
23774 : {
23775 216 : if (!ident1)
23776 146 : dfinal.op0 = dfirst.target = gen_reg_rtx (d->vmode);
23777 216 : if (!ident2)
23778 148 : dfinal.op1 = dsecond.target = gen_reg_rtx (d->vmode);
23779 216 : if (d->perm[0] >= nelt)
23780 0 : std::swap (dfinal.op0, dfinal.op1);
23781 : }
23782 :
23783 3899 : bool ok;
23784 3899 : rtx_insn *seq1 = NULL, *seq2 = NULL;
23785 :
23786 3899 : if (!ident1)
23787 : {
23788 2587 : start_sequence ();
23789 2587 : ok = expand_vec_perm_1 (&dfirst);
23790 2587 : seq1 = end_sequence ();
23791 :
23792 2587 : if (!ok)
23793 : return false;
23794 : }
23795 :
23796 2174 : if (!ident2)
23797 : {
23798 2074 : start_sequence ();
23799 2074 : ok = expand_vec_perm_1 (&dsecond);
23800 2074 : seq2 = end_sequence ();
23801 :
23802 2074 : if (!ok)
23803 : return false;
23804 : }
23805 :
23806 608 : if (d->testing_p)
23807 : return true;
23808 :
23809 690 : for (i = 0; i < nelt; i++)
23810 : {
23811 552 : dfinal.perm[i] = i / 2;
23812 552 : if (i >= lane)
23813 4 : dfinal.perm[i] += lane / 2;
23814 552 : if ((i & 1) != 0)
23815 276 : dfinal.perm[i] += nelt;
23816 : }
23817 138 : emit_insn (seq1);
23818 138 : emit_insn (seq2);
23819 138 : ok = expand_vselect_vconcat (dfinal.target, dfinal.op0, dfinal.op1,
23820 : dfinal.perm, dfinal.nelt, false);
23821 138 : gcc_assert (ok);
23822 : return true;
23823 : }
23824 :
23825 : /* A subroutine of ix86_expand_vec_perm_const_1. Try to simplify
23826 : the permutation using two single vector permutations and the SSE4_1 pblendv
23827 : instruction. If two_insn, succeed only if one of dfirst or dsecond is
23828 : identity permutation. */
23829 :
23830 : static bool
23831 116160 : expand_vec_perm_2perm_pblendv (struct expand_vec_perm_d *d, bool two_insn)
23832 : {
23833 116160 : unsigned i, nelt = d->nelt;
23834 116160 : struct expand_vec_perm_d dfirst, dsecond, dfinal;
23835 116160 : machine_mode vmode = d->vmode;
23836 116160 : bool ident1 = true, ident2 = true;
23837 :
23838 : /* Use the same checks as in expand_vec_perm_blend. */
23839 116160 : if (d->one_operand_p)
23840 : return false;
23841 109185 : if (TARGET_AVX2 && GET_MODE_SIZE (vmode) == 32)
23842 : ;
23843 103283 : else if (TARGET_AVX && (vmode == V4DFmode || vmode == V8SFmode))
23844 : ;
23845 98586 : else if (TARGET_SSE4_1
23846 108335 : && (GET_MODE_SIZE (vmode) == 16
23847 8804 : || (TARGET_MMX_WITH_SSE && GET_MODE_SIZE (vmode) == 8)
23848 2629 : || GET_MODE_SIZE (vmode) == 4))
23849 : ;
23850 : else
23851 : return false;
23852 :
23853 15736 : dfirst = *d;
23854 15736 : dsecond = *d;
23855 15736 : dfinal = *d;
23856 15736 : dfirst.op1 = dfirst.op0;
23857 15736 : dfirst.one_operand_p = true;
23858 15736 : dsecond.op0 = dsecond.op1;
23859 15736 : dsecond.one_operand_p = true;
23860 :
23861 116958 : for (i = 0; i < nelt; ++i)
23862 101222 : if (d->perm[i] >= nelt)
23863 : {
23864 51081 : dfirst.perm[i] = 0xff;
23865 51081 : dsecond.perm[i] = d->perm[i] - nelt;
23866 51081 : if (d->perm[i] != i + nelt)
23867 101222 : ident2 = false;
23868 : }
23869 : else
23870 : {
23871 50141 : dsecond.perm[i] = 0xff;
23872 50141 : dfirst.perm[i] = d->perm[i];
23873 50141 : if (d->perm[i] != i)
23874 101222 : ident1 = false;
23875 : }
23876 :
23877 15736 : if (two_insn && !ident1 && !ident2)
23878 : return false;
23879 :
23880 : /* For now. Ideally treat 0xff as a wildcard. */
23881 44279 : for (i = 0; i < nelt; ++i)
23882 38880 : if (dfirst.perm[i] == 0xff)
23883 : {
23884 20709 : if (GET_MODE_SIZE (vmode) == 32
23885 20709 : && dfirst.perm[i ^ (nelt / 2)] != 0xff)
23886 11731 : dfirst.perm[i] = dfirst.perm[i ^ (nelt / 2)] ^ (nelt / 2);
23887 : else
23888 8978 : dfirst.perm[i] = i;
23889 : }
23890 : else
23891 : {
23892 18171 : if (GET_MODE_SIZE (vmode) == 32
23893 18171 : && dsecond.perm[i ^ (nelt / 2)] != 0xff)
23894 9986 : dsecond.perm[i] = dsecond.perm[i ^ (nelt / 2)] ^ (nelt / 2);
23895 : else
23896 8185 : dsecond.perm[i] = i;
23897 : }
23898 :
23899 5399 : if (!d->testing_p)
23900 : {
23901 2167 : if (!ident1)
23902 2043 : dfinal.op0 = dfirst.target = gen_reg_rtx (d->vmode);
23903 2167 : if (!ident2)
23904 855 : dfinal.op1 = dsecond.target = gen_reg_rtx (d->vmode);
23905 : }
23906 :
23907 5399 : bool ok;
23908 5399 : rtx_insn *seq1 = NULL, *seq2 = NULL;
23909 :
23910 5399 : if (!ident1)
23911 : {
23912 4810 : start_sequence ();
23913 4810 : ok = expand_vec_perm_1 (&dfirst);
23914 4810 : seq1 = end_sequence ();
23915 :
23916 4810 : if (!ok)
23917 : return false;
23918 : }
23919 :
23920 4012 : if (!ident2)
23921 : {
23922 1133 : start_sequence ();
23923 1133 : ok = expand_vec_perm_1 (&dsecond);
23924 1133 : seq2 = end_sequence ();
23925 :
23926 1133 : if (!ok)
23927 : return false;
23928 : }
23929 :
23930 3423 : if (d->testing_p)
23931 : return true;
23932 :
23933 14037 : for (i = 0; i < nelt; ++i)
23934 12212 : dfinal.perm[i] = (d->perm[i] >= nelt ? i + nelt : i);
23935 :
23936 1825 : emit_insn (seq1);
23937 1825 : emit_insn (seq2);
23938 1825 : ok = expand_vec_perm_blend (&dfinal);
23939 1825 : gcc_assert (ok);
23940 : return true;
23941 : }
23942 :
23943 : /* A subroutine of ix86_expand_vec_perm_const_1.
23944 : Implement a permutation with psrlw, psllw and por.
23945 : It handles case:
23946 : __builtin_shufflevector (v,v,1,0,3,2,5,4,7,6,9,8,11,10,13,12,15,14);
23947 : __builtin_shufflevector (v,v,1,0,3,2,5,4,7,6); */
23948 :
23949 : static bool
23950 27030 : expand_vec_perm_psrlw_psllw_por (struct expand_vec_perm_d *d)
23951 : {
23952 27030 : unsigned i;
23953 27030 : rtx (*gen_shr) (rtx, rtx, rtx);
23954 27030 : rtx (*gen_shl) (rtx, rtx, rtx);
23955 27030 : rtx (*gen_or) (rtx, rtx, rtx);
23956 27030 : machine_mode mode = VOIDmode;
23957 :
23958 27030 : if (!TARGET_SSE2 || !d->one_operand_p)
23959 : return false;
23960 :
23961 5428 : switch (d->vmode)
23962 : {
23963 1438 : case E_V8QImode:
23964 1438 : if (!TARGET_MMX_WITH_SSE)
23965 : return false;
23966 : mode = V4HImode;
23967 : gen_shr = gen_lshrv4hi3;
23968 : gen_shl = gen_ashlv4hi3;
23969 : gen_or = gen_iorv4hi3;
23970 : break;
23971 : case E_V16QImode:
23972 : mode = V8HImode;
23973 : gen_shr = gen_lshrv8hi3;
23974 : gen_shl = gen_ashlv8hi3;
23975 : gen_or = gen_iorv8hi3;
23976 : break;
23977 : default: return false;
23978 : }
23979 :
23980 3212 : if (!rtx_equal_p (d->op0, d->op1))
23981 : return false;
23982 :
23983 12380 : for (i = 0; i < d->nelt; i += 2)
23984 10926 : if (d->perm[i] != i + 1 || d->perm[i + 1] != i)
23985 : return false;
23986 :
23987 1454 : if (d->testing_p)
23988 : return true;
23989 :
23990 30 : rtx tmp1 = gen_reg_rtx (mode);
23991 30 : rtx tmp2 = gen_reg_rtx (mode);
23992 30 : rtx op0 = force_reg (d->vmode, d->op0);
23993 :
23994 30 : emit_move_insn (tmp1, lowpart_subreg (mode, op0, d->vmode));
23995 30 : emit_move_insn (tmp2, lowpart_subreg (mode, op0, d->vmode));
23996 30 : emit_insn (gen_shr (tmp1, tmp1, GEN_INT (8)));
23997 30 : emit_insn (gen_shl (tmp2, tmp2, GEN_INT (8)));
23998 30 : emit_insn (gen_or (tmp1, tmp1, tmp2));
23999 30 : emit_move_insn (d->target, lowpart_subreg (d->vmode, tmp1, mode));
24000 :
24001 30 : return true;
24002 : }
24003 :
24004 : /* A subroutine of ix86_expand_vec_perm_const_1. Implement a V4DF
24005 : permutation using two vperm2f128, followed by a vshufpd insn blending
24006 : the two vectors together. */
24007 :
24008 : static bool
24009 30880 : expand_vec_perm_2vperm2f128_vshuf (struct expand_vec_perm_d *d)
24010 : {
24011 30880 : struct expand_vec_perm_d dfirst, dsecond, dthird;
24012 30880 : bool ok;
24013 :
24014 30880 : if (!TARGET_AVX || (d->vmode != V4DFmode))
24015 : return false;
24016 :
24017 1277 : if (d->testing_p)
24018 : return true;
24019 :
24020 206 : dfirst = *d;
24021 206 : dsecond = *d;
24022 206 : dthird = *d;
24023 :
24024 206 : dfirst.perm[0] = (d->perm[0] & ~1);
24025 206 : dfirst.perm[1] = (d->perm[0] & ~1) + 1;
24026 206 : dfirst.perm[2] = (d->perm[2] & ~1);
24027 206 : dfirst.perm[3] = (d->perm[2] & ~1) + 1;
24028 206 : dsecond.perm[0] = (d->perm[1] & ~1);
24029 206 : dsecond.perm[1] = (d->perm[1] & ~1) + 1;
24030 206 : dsecond.perm[2] = (d->perm[3] & ~1);
24031 206 : dsecond.perm[3] = (d->perm[3] & ~1) + 1;
24032 206 : dthird.perm[0] = (d->perm[0] % 2);
24033 206 : dthird.perm[1] = (d->perm[1] % 2) + 4;
24034 206 : dthird.perm[2] = (d->perm[2] % 2) + 2;
24035 206 : dthird.perm[3] = (d->perm[3] % 2) + 6;
24036 :
24037 206 : dfirst.target = gen_reg_rtx (dfirst.vmode);
24038 206 : dsecond.target = gen_reg_rtx (dsecond.vmode);
24039 206 : dthird.op0 = dfirst.target;
24040 206 : dthird.op1 = dsecond.target;
24041 206 : dthird.one_operand_p = false;
24042 :
24043 206 : canonicalize_perm (&dfirst);
24044 206 : canonicalize_perm (&dsecond);
24045 :
24046 206 : ok = expand_vec_perm_1 (&dfirst)
24047 206 : && expand_vec_perm_1 (&dsecond)
24048 412 : && expand_vec_perm_1 (&dthird);
24049 :
24050 0 : gcc_assert (ok);
24051 :
24052 : return true;
24053 : }
24054 :
24055 : static bool ix86_expand_vec_perm_const_1 (struct expand_vec_perm_d *);
24056 :
24057 : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement
24058 : a two vector permutation using two intra-lane vector
24059 : permutations, vperm2f128 swapping the lanes and vblend* insn blending
24060 : the non-swapped and swapped vectors together. */
24061 :
24062 : static bool
24063 16131 : expand_vec_perm2_vperm2f128_vblend (struct expand_vec_perm_d *d)
24064 : {
24065 16131 : struct expand_vec_perm_d dfirst, dsecond, dthird;
24066 16131 : unsigned i, j, msk, nelt = d->nelt, nelt2 = nelt / 2, which1 = 0, which2 = 0;
24067 16131 : rtx_insn *seq1, *seq2;
24068 16131 : bool ok;
24069 16131 : rtx (*blend) (rtx, rtx, rtx, rtx) = NULL;
24070 :
24071 16131 : if (!TARGET_AVX
24072 794 : || TARGET_AVX2
24073 530 : || (d->vmode != V8SFmode && d->vmode != V4DFmode)
24074 403 : || d->one_operand_p)
24075 : return false;
24076 :
24077 403 : dfirst = *d;
24078 403 : dsecond = *d;
24079 3627 : for (i = 0; i < nelt; i++)
24080 : {
24081 3224 : dfirst.perm[i] = 0xff;
24082 3224 : dsecond.perm[i] = 0xff;
24083 : }
24084 3627 : for (i = 0, msk = 0; i < nelt; i++)
24085 : {
24086 3224 : j = (d->perm[i] & nelt2) ? i | nelt2 : i & ~nelt2;
24087 3224 : if (j == i)
24088 : {
24089 2498 : dfirst.perm[j] = d->perm[i];
24090 4322 : which1 |= (d->perm[i] < nelt ? 1 : 2);
24091 : }
24092 : else
24093 : {
24094 726 : dsecond.perm[j] = d->perm[i];
24095 726 : which2 |= (d->perm[i] < nelt ? 1 : 2);
24096 726 : msk |= (1U << i);
24097 : }
24098 : }
24099 403 : if (msk == 0 || msk == (1U << nelt) - 1)
24100 : return false;
24101 :
24102 403 : if (!d->testing_p)
24103 : {
24104 40 : dfirst.target = gen_reg_rtx (dfirst.vmode);
24105 40 : dsecond.target = gen_reg_rtx (dsecond.vmode);
24106 : }
24107 :
24108 3627 : for (i = 0; i < nelt; i++)
24109 : {
24110 3224 : if (dfirst.perm[i] == 0xff)
24111 726 : dfirst.perm[i] = (which1 == 2 ? i + nelt : i);
24112 3224 : if (dsecond.perm[i] == 0xff)
24113 2498 : dsecond.perm[i] = (which2 == 2 ? i + nelt : i);
24114 : }
24115 403 : canonicalize_perm (&dfirst);
24116 403 : start_sequence ();
24117 403 : ok = ix86_expand_vec_perm_const_1 (&dfirst);
24118 403 : seq1 = end_sequence ();
24119 :
24120 403 : if (!ok)
24121 : return false;
24122 :
24123 403 : canonicalize_perm (&dsecond);
24124 403 : start_sequence ();
24125 403 : ok = ix86_expand_vec_perm_const_1 (&dsecond);
24126 403 : seq2 = end_sequence ();
24127 :
24128 403 : if (!ok)
24129 : return false;
24130 :
24131 403 : if (d->testing_p)
24132 : return true;
24133 :
24134 40 : emit_insn (seq1);
24135 40 : emit_insn (seq2);
24136 :
24137 40 : dthird = *d;
24138 40 : dthird.op0 = dsecond.target;
24139 40 : dthird.op1 = dsecond.target;
24140 40 : dthird.one_operand_p = true;
24141 40 : dthird.target = gen_reg_rtx (dthird.vmode);
24142 360 : for (i = 0; i < nelt; i++)
24143 320 : dthird.perm[i] = i ^ nelt2;
24144 :
24145 40 : ok = expand_vec_perm_1 (&dthird);
24146 40 : gcc_assert (ok);
24147 :
24148 40 : blend = d->vmode == V8SFmode ? gen_avx_blendps256 : gen_avx_blendpd256;
24149 40 : emit_insn (blend (d->target, dfirst.target, dthird.target, GEN_INT (msk)));
24150 40 : return true;
24151 : }
24152 :
24153 : /* A subroutine of expand_vec_perm_even_odd_1. Implement the double-word
24154 : permutation with two pshufb insns and an ior. We should have already
24155 : failed all two instruction sequences. */
24156 :
24157 : static bool
24158 29624 : expand_vec_perm_pshufb2 (struct expand_vec_perm_d *d)
24159 : {
24160 29624 : rtx rperm[2][16], vperm, l, h, op, m128;
24161 29624 : unsigned int i, nelt, eltsz;
24162 29624 : machine_mode mode;
24163 29624 : rtx (*gen) (rtx, rtx, rtx);
24164 :
24165 34112 : if (!TARGET_SSSE3 || (GET_MODE_SIZE (d->vmode) != 16
24166 8886 : && GET_MODE_SIZE (d->vmode) != 8
24167 8846 : && GET_MODE_SIZE (d->vmode) != 4))
24168 : return false;
24169 1409 : gcc_assert (!d->one_operand_p);
24170 :
24171 1409 : if (d->testing_p)
24172 : return true;
24173 :
24174 202 : switch (GET_MODE_SIZE (d->vmode))
24175 : {
24176 : case 4:
24177 : mode = V4QImode;
24178 : gen = gen_mmx_pshufbv4qi3;
24179 : break;
24180 20 : case 8:
24181 20 : mode = V8QImode;
24182 20 : gen = gen_mmx_pshufbv8qi3;
24183 20 : break;
24184 45 : case 16:
24185 45 : mode = V16QImode;
24186 45 : gen = gen_ssse3_pshufbv16qi3;
24187 45 : break;
24188 0 : default:
24189 0 : gcc_unreachable ();
24190 : }
24191 :
24192 101 : nelt = d->nelt;
24193 101 : eltsz = GET_MODE_UNIT_SIZE (d->vmode);
24194 :
24195 : /* Generate two permutation masks. If the required element is within
24196 : the given vector it is shuffled into the proper lane. If the required
24197 : element is in the other vector, force a zero into the lane by setting
24198 : bit 7 in the permutation mask. */
24199 101 : m128 = GEN_INT (-128);
24200 1029 : for (i = 0; i < nelt; ++i)
24201 : {
24202 928 : unsigned j, k, e = d->perm[i];
24203 928 : unsigned which = (e >= nelt);
24204 928 : if (e >= nelt)
24205 480 : e -= nelt;
24206 :
24207 1952 : for (j = 0; j < eltsz; ++j)
24208 : {
24209 1024 : rperm[which][i*eltsz + j] = GEN_INT (e*eltsz + j);
24210 1024 : rperm[1-which][i*eltsz + j] = m128;
24211 : }
24212 :
24213 9024 : for (k = i*eltsz + j; k < 16; ++k)
24214 8096 : rperm[0][k] = rperm[1][k] = m128;
24215 : }
24216 :
24217 101 : vperm = gen_rtx_CONST_VECTOR (V16QImode, gen_rtvec_v (16, rperm[0]));
24218 101 : vperm = force_reg (V16QImode, vperm);
24219 :
24220 101 : l = gen_reg_rtx (mode);
24221 101 : op = gen_lowpart (mode, d->op0);
24222 101 : emit_insn (gen (l, op, vperm));
24223 :
24224 101 : vperm = gen_rtx_CONST_VECTOR (V16QImode, gen_rtvec_v (16, rperm[1]));
24225 101 : vperm = force_reg (V16QImode, vperm);
24226 :
24227 101 : h = gen_reg_rtx (mode);
24228 101 : op = gen_lowpart (mode, d->op1);
24229 101 : emit_insn (gen (h, op, vperm));
24230 :
24231 101 : op = d->target;
24232 101 : if (d->vmode != mode)
24233 22 : op = gen_reg_rtx (mode);
24234 101 : ix86_emit_vec_binop (IOR, mode, op, l, h);
24235 101 : if (op != d->target)
24236 22 : emit_move_insn (d->target, gen_lowpart (d->vmode, op));
24237 :
24238 : return true;
24239 : }
24240 :
24241 : /* Implement arbitrary permutation of one V32QImode and V16QImode operand
24242 : with two vpshufb insns, vpermq and vpor. We should have already failed
24243 : all two or three instruction sequences. */
24244 :
24245 : static bool
24246 24441 : expand_vec_perm_vpshufb2_vpermq (struct expand_vec_perm_d *d)
24247 : {
24248 24441 : rtx rperm[2][32], vperm, l, h, hp, op, m128;
24249 24441 : unsigned int i, nelt, eltsz;
24250 :
24251 24441 : if (!TARGET_AVX2
24252 374 : || !d->one_operand_p
24253 172 : || (d->vmode != V32QImode && d->vmode != V16HImode))
24254 : return false;
24255 :
24256 7 : if (d->testing_p)
24257 : return true;
24258 :
24259 7 : nelt = d->nelt;
24260 7 : eltsz = GET_MODE_UNIT_SIZE (d->vmode);
24261 :
24262 : /* Generate two permutation masks. If the required element is within
24263 : the same lane, it is shuffled in. If the required element from the
24264 : other lane, force a zero by setting bit 7 in the permutation mask.
24265 : In the other mask the mask has non-negative elements if element
24266 : is requested from the other lane, but also moved to the other lane,
24267 : so that the result of vpshufb can have the two V2TImode halves
24268 : swapped. */
24269 7 : m128 = GEN_INT (-128);
24270 199 : for (i = 0; i < nelt; ++i)
24271 : {
24272 192 : unsigned j, e = d->perm[i] & (nelt / 2 - 1);
24273 192 : unsigned which = ((d->perm[i] ^ i) & (nelt / 2)) * eltsz;
24274 :
24275 416 : for (j = 0; j < eltsz; ++j)
24276 : {
24277 224 : rperm[!!which][(i * eltsz + j) ^ which] = GEN_INT (e * eltsz + j);
24278 224 : rperm[!which][(i * eltsz + j) ^ (which ^ 16)] = m128;
24279 : }
24280 : }
24281 :
24282 7 : vperm = gen_rtx_CONST_VECTOR (V32QImode, gen_rtvec_v (32, rperm[1]));
24283 7 : vperm = force_reg (V32QImode, vperm);
24284 :
24285 7 : h = gen_reg_rtx (V32QImode);
24286 7 : op = gen_lowpart (V32QImode, d->op0);
24287 7 : emit_insn (gen_avx2_pshufbv32qi3 (h, op, vperm));
24288 :
24289 : /* Swap the 128-byte lanes of h into hp. */
24290 7 : hp = gen_reg_rtx (V4DImode);
24291 7 : op = gen_lowpart (V4DImode, h);
24292 7 : emit_insn (gen_avx2_permv4di_1 (hp, op, const2_rtx, GEN_INT (3), const0_rtx,
24293 : const1_rtx));
24294 :
24295 7 : vperm = gen_rtx_CONST_VECTOR (V32QImode, gen_rtvec_v (32, rperm[0]));
24296 7 : vperm = force_reg (V32QImode, vperm);
24297 :
24298 7 : l = gen_reg_rtx (V32QImode);
24299 7 : op = gen_lowpart (V32QImode, d->op0);
24300 7 : emit_insn (gen_avx2_pshufbv32qi3 (l, op, vperm));
24301 :
24302 7 : op = d->target;
24303 7 : if (d->vmode != V32QImode)
24304 2 : op = gen_reg_rtx (V32QImode);
24305 7 : emit_insn (gen_iorv32qi3 (op, l, gen_lowpart (V32QImode, hp)));
24306 7 : if (op != d->target)
24307 2 : emit_move_insn (d->target, gen_lowpart (d->vmode, op));
24308 :
24309 : return true;
24310 : }
24311 :
24312 : /* A subroutine of expand_vec_perm_even_odd_1. Implement extract-even
24313 : and extract-odd permutations of two V32QImode and V16QImode operand
24314 : with two vpshufb insns, vpor and vpermq. We should have already
24315 : failed all two or three instruction sequences. */
24316 :
24317 : static bool
24318 24434 : expand_vec_perm_vpshufb2_vpermq_even_odd (struct expand_vec_perm_d *d)
24319 : {
24320 24434 : rtx rperm[2][32], vperm, l, h, ior, op, m128;
24321 24434 : unsigned int i, nelt, eltsz;
24322 :
24323 24434 : if (!TARGET_AVX2
24324 367 : || d->one_operand_p
24325 202 : || (d->vmode != V32QImode && d->vmode != V16HImode))
24326 : return false;
24327 :
24328 112 : for (i = 0; i < d->nelt; ++i)
24329 112 : if ((d->perm[i] ^ (i * 2)) & (3 * d->nelt / 2))
24330 : return false;
24331 :
24332 0 : if (d->testing_p)
24333 : return true;
24334 :
24335 0 : nelt = d->nelt;
24336 0 : eltsz = GET_MODE_UNIT_SIZE (d->vmode);
24337 :
24338 : /* Generate two permutation masks. In the first permutation mask
24339 : the first quarter will contain indexes for the first half
24340 : of the op0, the second quarter will contain bit 7 set, third quarter
24341 : will contain indexes for the second half of the op0 and the
24342 : last quarter bit 7 set. In the second permutation mask
24343 : the first quarter will contain bit 7 set, the second quarter
24344 : indexes for the first half of the op1, the third quarter bit 7 set
24345 : and last quarter indexes for the second half of the op1.
24346 : I.e. the first mask e.g. for V32QImode extract even will be:
24347 : 0, 2, ..., 0xe, -128, ..., -128, 0, 2, ..., 0xe, -128, ..., -128
24348 : (all values masked with 0xf except for -128) and second mask
24349 : for extract even will be
24350 : -128, ..., -128, 0, 2, ..., 0xe, -128, ..., -128, 0, 2, ..., 0xe. */
24351 0 : m128 = GEN_INT (-128);
24352 0 : for (i = 0; i < nelt; ++i)
24353 : {
24354 0 : unsigned j, e = d->perm[i] & (nelt / 2 - 1);
24355 0 : unsigned which = d->perm[i] >= nelt;
24356 0 : unsigned xorv = (i >= nelt / 4 && i < 3 * nelt / 4) ? 24 : 0;
24357 :
24358 0 : for (j = 0; j < eltsz; ++j)
24359 : {
24360 0 : rperm[which][(i * eltsz + j) ^ xorv] = GEN_INT (e * eltsz + j);
24361 0 : rperm[1 - which][(i * eltsz + j) ^ xorv] = m128;
24362 : }
24363 : }
24364 :
24365 0 : vperm = gen_rtx_CONST_VECTOR (V32QImode, gen_rtvec_v (32, rperm[0]));
24366 0 : vperm = force_reg (V32QImode, vperm);
24367 :
24368 0 : l = gen_reg_rtx (V32QImode);
24369 0 : op = gen_lowpart (V32QImode, d->op0);
24370 0 : emit_insn (gen_avx2_pshufbv32qi3 (l, op, vperm));
24371 :
24372 0 : vperm = gen_rtx_CONST_VECTOR (V32QImode, gen_rtvec_v (32, rperm[1]));
24373 0 : vperm = force_reg (V32QImode, vperm);
24374 :
24375 0 : h = gen_reg_rtx (V32QImode);
24376 0 : op = gen_lowpart (V32QImode, d->op1);
24377 0 : emit_insn (gen_avx2_pshufbv32qi3 (h, op, vperm));
24378 :
24379 0 : ior = gen_reg_rtx (V32QImode);
24380 0 : emit_insn (gen_iorv32qi3 (ior, l, h));
24381 :
24382 : /* Permute the V4DImode quarters using { 0, 2, 1, 3 } permutation. */
24383 0 : op = gen_reg_rtx (V4DImode);
24384 0 : ior = gen_lowpart (V4DImode, ior);
24385 0 : emit_insn (gen_avx2_permv4di_1 (op, ior, const0_rtx, const2_rtx,
24386 : const1_rtx, GEN_INT (3)));
24387 0 : emit_move_insn (d->target, gen_lowpart (d->vmode, op));
24388 :
24389 0 : return true;
24390 : }
24391 :
24392 : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement a
24393 : permutation (which is a bland) with and, andnot and or when pshufb is not available.
24394 :
24395 : It handles case:
24396 : __builtin_shufflevector (v1, v2, 0, 9, 2, 11, 4, 13, 6, 15);
24397 : __builtin_shufflevector (v1, v2, 8, 1, 2, 11, 4, 13, 6, 15);
24398 :
24399 : An element[i] must be chosen between op0[i] and op1[i] to satisfy the
24400 : requirement.
24401 : */
24402 :
24403 : static bool
24404 25576 : expand_vec_perm_pand_pandn_por (struct expand_vec_perm_d *d)
24405 : {
24406 25576 : rtx rperm[16], vperm;
24407 25576 : unsigned int i, nelt = d->nelt;
24408 :
24409 25576 : if (!TARGET_SSE2
24410 25576 : || d->one_operand_p
24411 21602 : || (d->vmode != V16QImode && d->vmode != V8HImode))
24412 : return false;
24413 :
24414 8040 : if (d->perm[0] != 0)
24415 : return false;
24416 :
24417 : /* The dest[i] must select an element between op0[i] and op1[i]. */
24418 17326 : for (i = 1; i < nelt; i++)
24419 16203 : if ((d->perm[i] % nelt) != i)
24420 : return false;
24421 :
24422 1123 : if (d->testing_p)
24423 : return true;
24424 :
24425 : /* Generates a blend mask for the operators AND and ANDNOT. */
24426 134 : machine_mode inner_mode = GET_MODE_INNER (d->vmode);
24427 1526 : for (i = 0; i < nelt; i++)
24428 1999 : rperm[i] = (d->perm[i] < nelt) ? CONSTM1_RTX (inner_mode)
24429 607 : : CONST0_RTX (inner_mode);
24430 :
24431 134 : vperm = gen_rtx_CONST_VECTOR (d->vmode, gen_rtvec_v (nelt, rperm));
24432 134 : vperm = force_reg (d->vmode, vperm);
24433 :
24434 134 : ix86_expand_sse_movcc (d->target, vperm, d->op0, d->op1);
24435 :
24436 134 : return true;
24437 : }
24438 :
24439 : /* Implement permutation with pslldq + psrldq + por when pshufb is not
24440 : available. */
24441 : static bool
24442 44736 : expand_vec_perm_pslldq_psrldq_por (struct expand_vec_perm_d *d, bool pandn)
24443 : {
24444 44736 : unsigned i, nelt = d->nelt;
24445 44736 : unsigned start1, end1 = -1;
24446 44736 : machine_mode vmode = d->vmode, imode;
24447 44736 : int start2 = -1;
24448 44736 : bool clear_op0, clear_op1;
24449 44736 : unsigned inner_size;
24450 44736 : rtx op0, op1, dop1;
24451 44736 : rtx (*gen_vec_shr) (rtx, rtx, rtx);
24452 44736 : rtx (*gen_vec_shl) (rtx, rtx, rtx);
24453 :
24454 : /* pshufd can be used for V4SI/V2DI under TARGET_SSE2. */
24455 44736 : if (!TARGET_SSE2 || (vmode != E_V16QImode && vmode != E_V8HImode))
24456 : return false;
24457 :
24458 14411 : start1 = d->perm[0];
24459 43298 : for (i = 1; i < nelt; i++)
24460 : {
24461 42353 : if (d->perm[i] != d->perm[i-1] + 1
24462 14766 : || d->perm[i] == nelt)
24463 : {
24464 27877 : if (start2 == -1)
24465 : {
24466 14411 : start2 = d->perm[i];
24467 14411 : end1 = d->perm[i-1];
24468 : }
24469 : else
24470 : return false;
24471 : }
24472 : }
24473 :
24474 945 : clear_op0 = end1 != nelt - 1;
24475 945 : clear_op1 = start2 % nelt != 0;
24476 : /* pandn/pand is needed to clear upper/lower bits of op0/op1. */
24477 945 : if (!pandn && (clear_op0 || clear_op1))
24478 : return false;
24479 :
24480 591 : if (d->testing_p)
24481 : return true;
24482 :
24483 89 : gen_vec_shr = vmode == E_V16QImode ? gen_vec_shr_v16qi : gen_vec_shr_v8hi;
24484 28 : gen_vec_shl = vmode == E_V16QImode ? gen_vec_shl_v16qi : gen_vec_shl_v8hi;
24485 89 : imode = GET_MODE_INNER (vmode);
24486 89 : inner_size = GET_MODE_BITSIZE (imode);
24487 89 : op0 = gen_reg_rtx (vmode);
24488 89 : op1 = gen_reg_rtx (vmode);
24489 :
24490 89 : if (start1)
24491 84 : emit_insn (gen_vec_shr (op0, d->op0, GEN_INT (start1 * inner_size)));
24492 : else
24493 5 : emit_move_insn (op0, d->op0);
24494 :
24495 89 : dop1 = d->op1;
24496 89 : if (d->one_operand_p)
24497 64 : dop1 = d->op0;
24498 :
24499 89 : int shl_offset = end1 - start1 + 1 - start2 % nelt;
24500 89 : if (shl_offset)
24501 49 : emit_insn (gen_vec_shl (op1, dop1, GEN_INT (shl_offset * inner_size)));
24502 : else
24503 40 : emit_move_insn (op1, dop1);
24504 :
24505 : /* Clear lower/upper bits for op0/op1. */
24506 89 : if (clear_op0 || clear_op1)
24507 : {
24508 : rtx vec[16];
24509 : rtx const_vec;
24510 : rtx clear;
24511 989 : for (i = 0; i != nelt; i++)
24512 : {
24513 920 : if (i < (end1 - start1 + 1))
24514 346 : vec[i] = gen_int_mode ((HOST_WIDE_INT_1U << inner_size) - 1, imode);
24515 : else
24516 574 : vec[i] = CONST0_RTX (imode);
24517 : }
24518 69 : const_vec = gen_rtx_CONST_VECTOR (vmode, gen_rtvec_v (nelt, vec));
24519 69 : const_vec = validize_mem (force_const_mem (vmode, const_vec));
24520 69 : clear = force_reg (vmode, const_vec);
24521 :
24522 69 : if (clear_op0)
24523 61 : emit_move_insn (op0, gen_rtx_AND (vmode, op0, clear));
24524 69 : if (clear_op1)
24525 56 : emit_move_insn (op1, gen_rtx_AND (vmode,
24526 : gen_rtx_NOT (vmode, clear),
24527 : op1));
24528 : }
24529 :
24530 89 : emit_move_insn (d->target, gen_rtx_IOR (vmode, op0, op1));
24531 89 : return true;
24532 : }
24533 :
24534 : /* A subroutine of expand_vec_perm_even_odd_1. Implement extract-even
24535 : and extract-odd permutations of two V8QI, V8HI, V16QI, V16HI or V32QI
24536 : operands with two "and" and "pack" or two "shift" and "pack" insns.
24537 : We should have already failed all two instruction sequences. */
24538 :
24539 : static bool
24540 47109 : expand_vec_perm_even_odd_pack (struct expand_vec_perm_d *d)
24541 : {
24542 47109 : rtx op, dop0, dop1, t;
24543 47109 : unsigned i, odd, c, s, nelt = d->nelt;
24544 47109 : int pblendw_i = 0;
24545 47109 : bool end_perm = false;
24546 47109 : machine_mode half_mode;
24547 47109 : rtx (*gen_and) (rtx, rtx, rtx);
24548 47109 : rtx (*gen_pack) (rtx, rtx, rtx);
24549 47109 : rtx (*gen_shift) (rtx, rtx, rtx);
24550 :
24551 47109 : if (d->one_operand_p)
24552 : return false;
24553 :
24554 41638 : switch (d->vmode)
24555 : {
24556 4628 : case E_V4HImode:
24557 : /* Required for "pack". */
24558 4628 : if (!TARGET_SSE4_1)
24559 : return false;
24560 : c = 0xffff;
24561 : s = 16;
24562 : half_mode = V2SImode;
24563 : gen_and = gen_andv2si3;
24564 : gen_pack = gen_mmx_packusdw;
24565 : gen_shift = gen_lshrv2si3;
24566 : pblendw_i = 0x5;
24567 : break;
24568 5953 : case E_V8HImode:
24569 : /* Required for "pack". */
24570 5953 : if (!TARGET_SSE4_1)
24571 : return false;
24572 : c = 0xffff;
24573 : s = 16;
24574 : half_mode = V4SImode;
24575 : gen_and = gen_andv4si3;
24576 : gen_pack = gen_sse4_1_packusdw;
24577 : gen_shift = gen_lshrv4si3;
24578 : pblendw_i = 0x55;
24579 : break;
24580 : case E_V8QImode:
24581 : /* No check as all instructions are SSE2. */
24582 : c = 0xff;
24583 : s = 8;
24584 : half_mode = V4HImode;
24585 : gen_and = gen_andv4hi3;
24586 : gen_pack = gen_mmx_packuswb;
24587 : gen_shift = gen_lshrv4hi3;
24588 : break;
24589 14630 : case E_V16QImode:
24590 : /* No check as all instructions are SSE2. */
24591 14630 : c = 0xff;
24592 14630 : s = 8;
24593 14630 : half_mode = V8HImode;
24594 14630 : gen_and = gen_andv8hi3;
24595 14630 : gen_pack = gen_sse2_packuswb;
24596 14630 : gen_shift = gen_lshrv8hi3;
24597 14630 : break;
24598 440 : case E_V16HImode:
24599 440 : if (!TARGET_AVX2)
24600 : return false;
24601 : c = 0xffff;
24602 : s = 16;
24603 : half_mode = V8SImode;
24604 : gen_and = gen_andv8si3;
24605 : gen_pack = gen_avx2_packusdw;
24606 : gen_shift = gen_lshrv8si3;
24607 : pblendw_i = 0x5555;
24608 : end_perm = true;
24609 : break;
24610 276 : case E_V32QImode:
24611 276 : if (!TARGET_AVX2)
24612 : return false;
24613 : c = 0xff;
24614 : s = 8;
24615 : half_mode = V16HImode;
24616 : gen_and = gen_andv16hi3;
24617 : gen_pack = gen_avx2_packuswb;
24618 : gen_shift = gen_lshrv16hi3;
24619 : end_perm = true;
24620 : break;
24621 : default:
24622 : /* Only V4HI, V8QI, V8HI, V16QI, V16HI and V32QI modes
24623 : are more profitable than general shuffles. */
24624 : return false;
24625 : }
24626 :
24627 : /* Check that permutation is even or odd. */
24628 20461 : odd = d->perm[0];
24629 20461 : if (odd > 1)
24630 : return false;
24631 :
24632 231488 : for (i = 1; i < nelt; ++i)
24633 215319 : if (d->perm[i] != 2 * i + odd)
24634 : return false;
24635 :
24636 16169 : if (d->testing_p)
24637 : return true;
24638 :
24639 5553 : dop0 = gen_reg_rtx (half_mode);
24640 5553 : dop1 = gen_reg_rtx (half_mode);
24641 5553 : if (odd == 0)
24642 : {
24643 : /* Use pblendw since const_vector 0 should be cheaper than
24644 : const_vector 0xffff. */
24645 4832 : if (d->vmode == V4HImode
24646 : || d->vmode == E_V8HImode
24647 : || d->vmode == E_V16HImode)
24648 : {
24649 872 : rtx dop0_t = gen_reg_rtx (d->vmode);
24650 872 : rtx dop1_t = gen_reg_rtx (d->vmode);
24651 872 : t = gen_reg_rtx (d->vmode);
24652 872 : emit_move_insn (t, CONST0_RTX (d->vmode));
24653 :
24654 872 : emit_move_insn (dop0_t, gen_rtx_VEC_MERGE (d->vmode, d->op0, t,
24655 : GEN_INT (pblendw_i)));
24656 872 : emit_move_insn (dop1_t, gen_rtx_VEC_MERGE (d->vmode, d->op1, t,
24657 : GEN_INT (pblendw_i)));
24658 :
24659 872 : emit_move_insn (dop0, gen_lowpart (half_mode, dop0_t));
24660 872 : emit_move_insn (dop1, gen_lowpart (half_mode, dop1_t));
24661 872 : }
24662 : else
24663 : {
24664 3960 : t = gen_const_vec_duplicate (half_mode, GEN_INT (c));
24665 3960 : t = force_reg (half_mode, t);
24666 3960 : emit_insn (gen_and (dop0, t, gen_lowpart (half_mode, d->op0)));
24667 3960 : emit_insn (gen_and (dop1, t, gen_lowpart (half_mode, d->op1)));
24668 : }
24669 : }
24670 : else
24671 : {
24672 1442 : emit_insn (gen_shift (dop0,
24673 721 : gen_lowpart (half_mode, d->op0),
24674 : GEN_INT (s)));
24675 1442 : emit_insn (gen_shift (dop1,
24676 721 : gen_lowpart (half_mode, d->op1),
24677 : GEN_INT (s)));
24678 : }
24679 : /* In AVX2 for 256 bit case we need to permute pack result. */
24680 5553 : if (TARGET_AVX2 && end_perm)
24681 : {
24682 419 : op = gen_reg_rtx (d->vmode);
24683 419 : t = gen_reg_rtx (V4DImode);
24684 419 : emit_insn (gen_pack (op, dop0, dop1));
24685 838 : emit_insn (gen_avx2_permv4di_1 (t,
24686 419 : gen_lowpart (V4DImode, op),
24687 : const0_rtx,
24688 : const2_rtx,
24689 : const1_rtx,
24690 : GEN_INT (3)));
24691 419 : emit_move_insn (d->target, gen_lowpart (d->vmode, t));
24692 : }
24693 : else
24694 5134 : emit_insn (gen_pack (d->target, dop0, dop1));
24695 :
24696 : return true;
24697 : }
24698 :
24699 : /* A subroutine of expand_vec_perm_even_odd_1. Implement extract-even
24700 : and extract-odd permutations of two V64QI operands
24701 : with two "shifts", two "truncs" and one "concat" insns for "odd"
24702 : and two "truncs" and one concat insn for "even."
24703 : Have already failed all two instruction sequences. */
24704 :
24705 : static bool
24706 24478 : expand_vec_perm_even_odd_trunc (struct expand_vec_perm_d *d)
24707 : {
24708 24478 : rtx t1, t2, t3, t4;
24709 24478 : unsigned i, odd, nelt = d->nelt;
24710 :
24711 24478 : if (!TARGET_AVX512BW
24712 74 : || d->one_operand_p
24713 38 : || d->vmode != V64QImode)
24714 : return false;
24715 :
24716 : /* Check that permutation is even or odd. */
24717 38 : odd = d->perm[0];
24718 38 : if (odd > 1)
24719 : return false;
24720 :
24721 1662 : for (i = 1; i < nelt; ++i)
24722 1637 : if (d->perm[i] != 2 * i + odd)
24723 : return false;
24724 :
24725 25 : if (d->testing_p)
24726 : return true;
24727 :
24728 :
24729 25 : if (odd)
24730 : {
24731 5 : t1 = gen_reg_rtx (V32HImode);
24732 5 : t2 = gen_reg_rtx (V32HImode);
24733 10 : emit_insn (gen_lshrv32hi3 (t1,
24734 5 : gen_lowpart (V32HImode, d->op0),
24735 : GEN_INT (8)));
24736 10 : emit_insn (gen_lshrv32hi3 (t2,
24737 5 : gen_lowpart (V32HImode, d->op1),
24738 : GEN_INT (8)));
24739 : }
24740 : else
24741 : {
24742 20 : t1 = gen_lowpart (V32HImode, d->op0);
24743 20 : t2 = gen_lowpart (V32HImode, d->op1);
24744 : }
24745 :
24746 25 : t3 = gen_reg_rtx (V32QImode);
24747 25 : t4 = gen_reg_rtx (V32QImode);
24748 25 : emit_insn (gen_avx512bw_truncatev32hiv32qi2 (t3, t1));
24749 25 : emit_insn (gen_avx512bw_truncatev32hiv32qi2 (t4, t2));
24750 25 : emit_insn (gen_avx_vec_concatv64qi (d->target, t3, t4));
24751 :
24752 25 : return true;
24753 : }
24754 :
24755 : /* A subroutine of ix86_expand_vec_perm_const_1. Implement extract-even
24756 : and extract-odd permutations. */
24757 :
24758 : static bool
24759 13021 : expand_vec_perm_even_odd_1 (struct expand_vec_perm_d *d, unsigned odd)
24760 : {
24761 13021 : rtx t1, t2, t3, t4, t5;
24762 :
24763 13021 : switch (d->vmode)
24764 : {
24765 19 : case E_V4DFmode:
24766 19 : if (d->testing_p)
24767 : break;
24768 1 : t1 = gen_reg_rtx (V4DFmode);
24769 1 : t2 = gen_reg_rtx (V4DFmode);
24770 :
24771 : /* Shuffle the lanes around into { 0 1 4 5 } and { 2 3 6 7 }. */
24772 1 : emit_insn (gen_avx_vperm2f128v4df3 (t1, d->op0, d->op1, GEN_INT (0x20)));
24773 1 : emit_insn (gen_avx_vperm2f128v4df3 (t2, d->op0, d->op1, GEN_INT (0x31)));
24774 :
24775 : /* Now an unpck[lh]pd will produce the result required. */
24776 1 : if (odd)
24777 0 : t3 = gen_avx_unpckhpd256 (d->target, t1, t2);
24778 : else
24779 1 : t3 = gen_avx_unpcklpd256 (d->target, t1, t2);
24780 1 : emit_insn (t3);
24781 1 : break;
24782 :
24783 1214 : case E_V8SFmode:
24784 1214 : {
24785 1214 : int mask = odd ? 0xdd : 0x88;
24786 :
24787 1214 : if (d->testing_p)
24788 : break;
24789 186 : t1 = gen_reg_rtx (V8SFmode);
24790 186 : t2 = gen_reg_rtx (V8SFmode);
24791 186 : t3 = gen_reg_rtx (V8SFmode);
24792 :
24793 : /* Shuffle within the 128-bit lanes to produce:
24794 : { 0 2 8 a 4 6 c e } | { 1 3 9 b 5 7 d f }. */
24795 186 : emit_insn (gen_avx_shufps256 (t1, d->op0, d->op1,
24796 : GEN_INT (mask)));
24797 :
24798 : /* Shuffle the lanes around to produce:
24799 : { 4 6 c e 0 2 8 a } and { 5 7 d f 1 3 9 b }. */
24800 186 : emit_insn (gen_avx_vperm2f128v8sf3 (t2, t1, t1,
24801 : GEN_INT (0x3)));
24802 :
24803 : /* Shuffle within the 128-bit lanes to produce:
24804 : { 0 2 4 6 4 6 0 2 } | { 1 3 5 7 5 7 1 3 }. */
24805 186 : emit_insn (gen_avx_shufps256 (t3, t1, t2, GEN_INT (0x44)));
24806 :
24807 : /* Shuffle within the 128-bit lanes to produce:
24808 : { 8 a c e c e 8 a } | { 9 b d f d f 9 b }. */
24809 186 : emit_insn (gen_avx_shufps256 (t2, t1, t2, GEN_INT (0xee)));
24810 :
24811 : /* Shuffle the lanes around to produce:
24812 : { 0 2 4 6 8 a c e } | { 1 3 5 7 9 b d f }. */
24813 186 : emit_insn (gen_avx_vperm2f128v8sf3 (d->target, t3, t2,
24814 : GEN_INT (0x20)));
24815 : }
24816 186 : break;
24817 :
24818 0 : case E_V2DFmode:
24819 0 : case E_V4SFmode:
24820 0 : case E_V2DImode:
24821 0 : case E_V2SImode:
24822 0 : case E_V4SImode:
24823 0 : case E_V2HImode:
24824 : /* These are always directly implementable by expand_vec_perm_1. */
24825 0 : gcc_unreachable ();
24826 :
24827 0 : case E_V2SFmode:
24828 0 : gcc_assert (TARGET_MMX_WITH_SSE);
24829 : /* We have no suitable instructions. */
24830 0 : if (d->testing_p)
24831 : return false;
24832 : break;
24833 :
24834 1548 : case E_V4QImode:
24835 1548 : if (TARGET_SSSE3 && !TARGET_SLOW_PSHUFB)
24836 0 : return expand_vec_perm_pshufb2 (d);
24837 : else
24838 : {
24839 1548 : if (d->testing_p)
24840 : break;
24841 : /* We need 2*log2(N)-1 operations to achieve odd/even
24842 : with interleave. */
24843 178 : t1 = gen_reg_rtx (V4QImode);
24844 178 : emit_insn (gen_mmx_punpckhbw_low (t1, d->op0, d->op1));
24845 178 : emit_insn (gen_mmx_punpcklbw_low (d->target, d->op0, d->op1));
24846 178 : if (odd)
24847 41 : t2 = gen_mmx_punpckhbw_low (d->target, d->target, t1);
24848 : else
24849 137 : t2 = gen_mmx_punpcklbw_low (d->target, d->target, t1);
24850 178 : emit_insn (t2);
24851 : }
24852 178 : break;
24853 :
24854 1526 : case E_V4HImode:
24855 1526 : if (TARGET_SSE4_1)
24856 92 : return expand_vec_perm_even_odd_pack (d);
24857 1434 : else if (TARGET_SSSE3 && !TARGET_SLOW_PSHUFB)
24858 20 : return expand_vec_perm_pshufb2 (d);
24859 : else
24860 : {
24861 1414 : if (d->testing_p)
24862 : break;
24863 : /* We need 2*log2(N)-1 operations to achieve odd/even
24864 : with interleave. */
24865 453 : t1 = gen_reg_rtx (V4HImode);
24866 453 : emit_insn (gen_mmx_punpckhwd (t1, d->op0, d->op1));
24867 453 : emit_insn (gen_mmx_punpcklwd (d->target, d->op0, d->op1));
24868 453 : if (odd)
24869 8 : t2 = gen_mmx_punpckhwd (d->target, d->target, t1);
24870 : else
24871 445 : t2 = gen_mmx_punpcklwd (d->target, d->target, t1);
24872 453 : emit_insn (t2);
24873 : }
24874 453 : break;
24875 :
24876 6684 : case E_V8HImode:
24877 6684 : if (TARGET_SSE4_1)
24878 440 : return expand_vec_perm_even_odd_pack (d);
24879 6244 : else if (TARGET_SSSE3 && !TARGET_SLOW_PSHUFB)
24880 1 : return expand_vec_perm_pshufb2 (d);
24881 : else
24882 : {
24883 6243 : if (d->testing_p)
24884 : break;
24885 : /* We need 2*log2(N)-1 operations to achieve odd/even
24886 : with interleave. */
24887 2747 : t1 = gen_reg_rtx (V8HImode);
24888 2747 : t2 = gen_reg_rtx (V8HImode);
24889 2747 : emit_insn (gen_vec_interleave_highv8hi (t1, d->op0, d->op1));
24890 2747 : emit_insn (gen_vec_interleave_lowv8hi (d->target, d->op0, d->op1));
24891 2747 : emit_insn (gen_vec_interleave_highv8hi (t2, d->target, t1));
24892 2747 : emit_insn (gen_vec_interleave_lowv8hi (d->target, d->target, t1));
24893 2747 : if (odd)
24894 91 : t3 = gen_vec_interleave_highv8hi (d->target, d->target, t2);
24895 : else
24896 2656 : t3 = gen_vec_interleave_lowv8hi (d->target, d->target, t2);
24897 2747 : emit_insn (t3);
24898 : }
24899 2747 : break;
24900 :
24901 1343 : case E_V8QImode:
24902 1343 : case E_V16QImode:
24903 1343 : return expand_vec_perm_even_odd_pack (d);
24904 :
24905 467 : case E_V16HImode:
24906 467 : case E_V32QImode:
24907 467 : return expand_vec_perm_even_odd_pack (d);
24908 :
24909 25 : case E_V64QImode:
24910 25 : return expand_vec_perm_even_odd_trunc (d);
24911 :
24912 19 : case E_V4DImode:
24913 19 : if (!TARGET_AVX2)
24914 : {
24915 19 : struct expand_vec_perm_d d_copy = *d;
24916 19 : d_copy.vmode = V4DFmode;
24917 19 : if (d->testing_p)
24918 18 : d_copy.target = gen_raw_REG (V4DFmode, LAST_VIRTUAL_REGISTER + 1);
24919 : else
24920 1 : d_copy.target = gen_reg_rtx (V4DFmode);
24921 19 : d_copy.op0 = gen_lowpart (V4DFmode, d->op0);
24922 19 : d_copy.op1 = gen_lowpart (V4DFmode, d->op1);
24923 19 : if (expand_vec_perm_even_odd_1 (&d_copy, odd))
24924 : {
24925 19 : if (!d->testing_p)
24926 1 : emit_move_insn (d->target,
24927 1 : gen_lowpart (V4DImode, d_copy.target));
24928 19 : return true;
24929 : }
24930 : return false;
24931 : }
24932 :
24933 0 : if (d->testing_p)
24934 : break;
24935 :
24936 0 : t1 = gen_reg_rtx (V4DImode);
24937 0 : t2 = gen_reg_rtx (V4DImode);
24938 :
24939 : /* Shuffle the lanes around into { 0 1 4 5 } and { 2 3 6 7 }. */
24940 0 : emit_insn (gen_avx2_permv2ti (t1, d->op0, d->op1, GEN_INT (0x20)));
24941 0 : emit_insn (gen_avx2_permv2ti (t2, d->op0, d->op1, GEN_INT (0x31)));
24942 :
24943 : /* Now an vpunpck[lh]qdq will produce the result required. */
24944 0 : if (odd)
24945 0 : t3 = gen_avx2_interleave_highv4di (d->target, t1, t2);
24946 : else
24947 0 : t3 = gen_avx2_interleave_lowv4di (d->target, t1, t2);
24948 0 : emit_insn (t3);
24949 0 : break;
24950 :
24951 176 : case E_V8SImode:
24952 176 : if (!TARGET_AVX2)
24953 : {
24954 38 : struct expand_vec_perm_d d_copy = *d;
24955 38 : d_copy.vmode = V8SFmode;
24956 38 : if (d->testing_p)
24957 38 : d_copy.target = gen_raw_REG (V8SFmode, LAST_VIRTUAL_REGISTER + 1);
24958 : else
24959 0 : d_copy.target = gen_reg_rtx (V8SFmode);
24960 38 : d_copy.op0 = gen_lowpart (V8SFmode, d->op0);
24961 38 : d_copy.op1 = gen_lowpart (V8SFmode, d->op1);
24962 38 : if (expand_vec_perm_even_odd_1 (&d_copy, odd))
24963 : {
24964 38 : if (!d->testing_p)
24965 0 : emit_move_insn (d->target,
24966 0 : gen_lowpart (V8SImode, d_copy.target));
24967 38 : return true;
24968 : }
24969 : return false;
24970 : }
24971 :
24972 138 : if (d->testing_p)
24973 : break;
24974 :
24975 138 : t1 = gen_reg_rtx (V8SImode);
24976 138 : t2 = gen_reg_rtx (V8SImode);
24977 138 : t3 = gen_reg_rtx (V4DImode);
24978 138 : t4 = gen_reg_rtx (V4DImode);
24979 138 : t5 = gen_reg_rtx (V4DImode);
24980 :
24981 : /* Shuffle the lanes around into
24982 : { 0 1 2 3 8 9 a b } and { 4 5 6 7 c d e f }. */
24983 276 : emit_insn (gen_avx2_permv2ti (t3, gen_lowpart (V4DImode, d->op0),
24984 138 : gen_lowpart (V4DImode, d->op1),
24985 : GEN_INT (0x20)));
24986 276 : emit_insn (gen_avx2_permv2ti (t4, gen_lowpart (V4DImode, d->op0),
24987 138 : gen_lowpart (V4DImode, d->op1),
24988 : GEN_INT (0x31)));
24989 :
24990 : /* Swap the 2nd and 3rd position in each lane into
24991 : { 0 2 1 3 8 a 9 b } and { 4 6 5 7 c e d f }. */
24992 138 : emit_insn (gen_avx2_pshufdv3 (t1, gen_lowpart (V8SImode, t3),
24993 : GEN_INT (2 * 4 + 1 * 16 + 3 * 64)));
24994 138 : emit_insn (gen_avx2_pshufdv3 (t2, gen_lowpart (V8SImode, t4),
24995 : GEN_INT (2 * 4 + 1 * 16 + 3 * 64)));
24996 :
24997 : /* Now an vpunpck[lh]qdq will produce
24998 : { 0 2 4 6 8 a c e } resp. { 1 3 5 7 9 b d f }. */
24999 138 : if (odd)
25000 0 : t3 = gen_avx2_interleave_highv4di (t5, gen_lowpart (V4DImode, t1),
25001 0 : gen_lowpart (V4DImode, t2));
25002 : else
25003 138 : t3 = gen_avx2_interleave_lowv4di (t5, gen_lowpart (V4DImode, t1),
25004 138 : gen_lowpart (V4DImode, t2));
25005 138 : emit_insn (t3);
25006 138 : emit_move_insn (d->target, gen_lowpart (V8SImode, t5));
25007 138 : break;
25008 :
25009 0 : default:
25010 0 : gcc_unreachable ();
25011 : }
25012 :
25013 : return true;
25014 : }
25015 :
25016 : /* A subroutine of ix86_expand_vec_perm_const_1. Pattern match
25017 : extract-even and extract-odd permutations. */
25018 :
25019 : static bool
25020 24385 : expand_vec_perm_even_odd (struct expand_vec_perm_d *d)
25021 : {
25022 24385 : unsigned i, odd, nelt = d->nelt;
25023 :
25024 24385 : odd = d->perm[0];
25025 24385 : if (odd != 0 && odd != 1)
25026 : return false;
25027 :
25028 65549 : for (i = 1; i < nelt; ++i)
25029 57601 : if (d->perm[i] != 2 * i + odd)
25030 : return false;
25031 :
25032 7948 : if (d->vmode == E_V32HImode
25033 12 : && d->testing_p
25034 12 : && !TARGET_AVX512BW)
25035 : return false;
25036 :
25037 7936 : return expand_vec_perm_even_odd_1 (d, odd);
25038 : }
25039 :
25040 : /* A subroutine of ix86_expand_vec_perm_const_1. Implement broadcast
25041 : permutations. We assume that expand_vec_perm_1 has already failed. */
25042 :
25043 : static bool
25044 1080 : expand_vec_perm_broadcast_1 (struct expand_vec_perm_d *d)
25045 : {
25046 1080 : unsigned elt = d->perm[0], nelt2 = d->nelt / 2;
25047 1080 : machine_mode vmode = d->vmode;
25048 1080 : rtx (*gen) (rtx, rtx, rtx);
25049 1080 : unsigned char perm2[4];
25050 1080 : rtx op0 = d->op0, dest;
25051 1080 : bool ok;
25052 :
25053 1080 : switch (vmode)
25054 : {
25055 0 : case E_V4DFmode:
25056 0 : case E_V8SFmode:
25057 : /* These are special-cased in sse.md so that we can optionally
25058 : use the vbroadcast instruction. They expand to two insns
25059 : if the input happens to be in a register. */
25060 0 : gcc_unreachable ();
25061 :
25062 0 : case E_V2DFmode:
25063 0 : case E_V2SFmode:
25064 0 : case E_V4SFmode:
25065 0 : case E_V2DImode:
25066 0 : case E_V2SImode:
25067 0 : case E_V4SImode:
25068 0 : case E_V2HImode:
25069 0 : case E_V4HImode:
25070 : /* These are always implementable using standard shuffle patterns. */
25071 0 : gcc_unreachable ();
25072 :
25073 16 : case E_V4QImode:
25074 : /* This can be implemented via interleave and pshuflw. */
25075 16 : if (d->testing_p)
25076 : return true;
25077 :
25078 8 : if (elt >= nelt2)
25079 : {
25080 4 : gen = gen_mmx_punpckhbw_low;
25081 4 : elt -= nelt2;
25082 : }
25083 : else
25084 : gen = gen_mmx_punpcklbw_low;
25085 :
25086 8 : dest = gen_reg_rtx (vmode);
25087 8 : emit_insn (gen (dest, op0, op0));
25088 8 : vmode = get_mode_wider_vector (vmode);
25089 8 : op0 = gen_lowpart (vmode, dest);
25090 :
25091 8 : memset (perm2, elt, 2);
25092 8 : dest = gen_reg_rtx (vmode);
25093 8 : ok = expand_vselect (dest, op0, perm2, 2, d->testing_p);
25094 8 : gcc_assert (ok);
25095 :
25096 8 : emit_move_insn (d->target, gen_lowpart (d->vmode, dest));
25097 8 : return true;
25098 :
25099 4 : case E_V8QImode:
25100 : /* This can be implemented via interleave. We save one insn by
25101 : stopping once we have promoted to V2SImode and then use pshufd. */
25102 4 : if (d->testing_p)
25103 : return true;
25104 4 : do
25105 : {
25106 4 : if (elt >= nelt2)
25107 : {
25108 1 : gen = vmode == V8QImode ? gen_mmx_punpckhbw
25109 : : gen_mmx_punpckhwd;
25110 1 : elt -= nelt2;
25111 : }
25112 : else
25113 3 : gen = vmode == V8QImode ? gen_mmx_punpcklbw
25114 : : gen_mmx_punpcklwd;
25115 4 : nelt2 /= 2;
25116 :
25117 4 : dest = gen_reg_rtx (vmode);
25118 4 : emit_insn (gen (dest, op0, op0));
25119 4 : vmode = get_mode_wider_vector (vmode);
25120 4 : op0 = gen_lowpart (vmode, dest);
25121 : }
25122 4 : while (vmode != V2SImode);
25123 :
25124 2 : memset (perm2, elt, 2);
25125 2 : dest = gen_reg_rtx (vmode);
25126 2 : ok = expand_vselect (dest, op0, perm2, 2, d->testing_p);
25127 2 : gcc_assert (ok);
25128 :
25129 2 : emit_move_insn (d->target, gen_lowpart (d->vmode, dest));
25130 2 : return true;
25131 :
25132 1051 : case E_V8HImode:
25133 1051 : case E_V16QImode:
25134 : /* These can be implemented via interleave. We save one insn by
25135 : stopping once we have promoted to V4SImode and then use pshufd. */
25136 1051 : if (d->testing_p)
25137 : return true;
25138 1612 : do
25139 : {
25140 1612 : if (elt >= nelt2)
25141 : {
25142 16 : gen = vmode == V16QImode ? gen_vec_interleave_highv16qi
25143 : : gen_vec_interleave_highv8hi;
25144 16 : elt -= nelt2;
25145 : }
25146 : else
25147 1596 : gen = vmode == V16QImode ? gen_vec_interleave_lowv16qi
25148 : : gen_vec_interleave_lowv8hi;
25149 1612 : nelt2 /= 2;
25150 :
25151 1612 : dest = gen_reg_rtx (vmode);
25152 1612 : emit_insn (gen (dest, op0, op0));
25153 1612 : vmode = get_mode_wider_vector (vmode);
25154 1612 : op0 = gen_lowpart (vmode, dest);
25155 : }
25156 1612 : while (vmode != V4SImode);
25157 :
25158 987 : memset (perm2, elt, 4);
25159 987 : dest = gen_reg_rtx (vmode);
25160 987 : ok = expand_vselect (dest, op0, perm2, 4, d->testing_p);
25161 987 : gcc_assert (ok);
25162 :
25163 987 : emit_move_insn (d->target, gen_lowpart (d->vmode, dest));
25164 987 : return true;
25165 :
25166 1 : case E_V8HFmode:
25167 1 : case E_V8BFmode:
25168 : /* This can be implemented via interleave and pshufd. */
25169 1 : if (d->testing_p)
25170 : return true;
25171 :
25172 1 : rtx (*gen_interleave) (machine_mode, rtx, rtx, rtx);
25173 1 : if (elt >= nelt2)
25174 : {
25175 0 : gen_interleave = gen_vec_interleave_high;
25176 0 : elt -= nelt2;
25177 : }
25178 : else
25179 : gen_interleave = gen_vec_interleave_low;
25180 1 : nelt2 /= 2;
25181 :
25182 1 : dest = gen_reg_rtx (vmode);
25183 1 : emit_insn (gen_interleave (vmode, dest, op0, op0));
25184 :
25185 1 : vmode = V4SImode;
25186 1 : op0 = gen_lowpart (vmode, dest);
25187 :
25188 1 : memset (perm2, elt, 4);
25189 1 : dest = gen_reg_rtx (vmode);
25190 1 : ok = expand_vselect (dest, op0, perm2, 4, d->testing_p);
25191 1 : gcc_assert (ok);
25192 :
25193 1 : emit_move_insn (d->target, gen_lowpart (d->vmode, dest));
25194 1 : return true;
25195 :
25196 0 : case E_V32QImode:
25197 0 : case E_V16HImode:
25198 0 : case E_V8SImode:
25199 0 : case E_V4DImode:
25200 : /* For AVX2 broadcasts of the first element vpbroadcast* or
25201 : vpermq should be used by expand_vec_perm_1. */
25202 0 : gcc_assert (!TARGET_AVX2 || d->perm[0]);
25203 : return false;
25204 :
25205 6 : case E_V64QImode:
25206 6 : gcc_assert (!TARGET_AVX512BW || d->perm[0]);
25207 : return false;
25208 :
25209 2 : case E_V32HImode:
25210 2 : gcc_assert (!TARGET_AVX512BW);
25211 : return false;
25212 :
25213 0 : default:
25214 0 : gcc_unreachable ();
25215 : }
25216 : }
25217 :
25218 : /* A subroutine of ix86_expand_vec_perm_const_1. Pattern match
25219 : broadcast permutations. */
25220 :
25221 : static bool
25222 90785 : expand_vec_perm_broadcast (struct expand_vec_perm_d *d)
25223 : {
25224 90785 : unsigned i, elt, nelt = d->nelt;
25225 :
25226 90785 : if (!d->one_operand_p)
25227 : return false;
25228 :
25229 5575 : elt = d->perm[0];
25230 8146 : for (i = 1; i < nelt; ++i)
25231 8038 : if (d->perm[i] != elt)
25232 : return false;
25233 :
25234 108 : return expand_vec_perm_broadcast_1 (d);
25235 : }
25236 :
25237 : /* Implement arbitrary permutations of two V64QImode operands
25238 : with 2 vperm[it]2w, 2 vpshufb and one vpor instruction. */
25239 : static bool
25240 24434 : expand_vec_perm_vpermt2_vpshub2 (struct expand_vec_perm_d *d)
25241 : {
25242 24434 : if (!TARGET_AVX512BW || !(d->vmode == V64QImode))
25243 : return false;
25244 :
25245 49 : if (d->testing_p)
25246 : return true;
25247 :
25248 49 : struct expand_vec_perm_d ds[2];
25249 49 : rtx rperm[128], vperm, target0, target1;
25250 49 : unsigned int i, nelt;
25251 49 : machine_mode vmode;
25252 :
25253 49 : nelt = d->nelt;
25254 49 : vmode = V64QImode;
25255 :
25256 147 : for (i = 0; i < 2; i++)
25257 : {
25258 98 : ds[i] = *d;
25259 98 : ds[i].vmode = V32HImode;
25260 98 : ds[i].nelt = 32;
25261 98 : ds[i].target = gen_reg_rtx (V32HImode);
25262 98 : ds[i].op0 = gen_lowpart (V32HImode, d->op0);
25263 98 : ds[i].op1 = gen_lowpart (V32HImode, d->op1);
25264 : }
25265 :
25266 : /* Prepare permutations such that the first one takes care of
25267 : putting the even bytes into the right positions or one higher
25268 : positions (ds[0]) and the second one takes care of
25269 : putting the odd bytes into the right positions or one below
25270 : (ds[1]). */
25271 :
25272 3185 : for (i = 0; i < nelt; i++)
25273 : {
25274 3136 : ds[i & 1].perm[i / 2] = d->perm[i] / 2;
25275 3136 : if (i & 1)
25276 : {
25277 1568 : rperm[i] = constm1_rtx;
25278 1568 : rperm[i + 64] = GEN_INT ((i & 14) + (d->perm[i] & 1));
25279 : }
25280 : else
25281 : {
25282 1568 : rperm[i] = GEN_INT ((i & 14) + (d->perm[i] & 1));
25283 1568 : rperm[i + 64] = constm1_rtx;
25284 : }
25285 : }
25286 :
25287 49 : bool ok = expand_vec_perm_1 (&ds[0]);
25288 49 : gcc_assert (ok);
25289 49 : ds[0].target = gen_lowpart (V64QImode, ds[0].target);
25290 :
25291 49 : ok = expand_vec_perm_1 (&ds[1]);
25292 49 : gcc_assert (ok);
25293 49 : ds[1].target = gen_lowpart (V64QImode, ds[1].target);
25294 :
25295 49 : vperm = gen_rtx_CONST_VECTOR (V64QImode, gen_rtvec_v (64, rperm));
25296 49 : vperm = force_reg (vmode, vperm);
25297 49 : target0 = gen_reg_rtx (V64QImode);
25298 49 : emit_insn (gen_avx512bw_pshufbv64qi3 (target0, ds[0].target, vperm));
25299 :
25300 49 : vperm = gen_rtx_CONST_VECTOR (V64QImode, gen_rtvec_v (64, rperm + 64));
25301 49 : vperm = force_reg (vmode, vperm);
25302 49 : target1 = gen_reg_rtx (V64QImode);
25303 49 : emit_insn (gen_avx512bw_pshufbv64qi3 (target1, ds[1].target, vperm));
25304 :
25305 49 : emit_insn (gen_iorv64qi3 (d->target, target0, target1));
25306 49 : return true;
25307 : }
25308 :
25309 : /* Implement arbitrary permutation of two V32QImode and V16QImode operands
25310 : with 4 vpshufb insns, 2 vpermq and 3 vpor. We should have already failed
25311 : all the shorter instruction sequences. */
25312 :
25313 : static bool
25314 16185 : expand_vec_perm_vpshufb4_vpermq2 (struct expand_vec_perm_d *d)
25315 : {
25316 16185 : rtx rperm[4][32], vperm, l[2], h[2], op, m128;
25317 16185 : unsigned int i, nelt, eltsz;
25318 16185 : bool used[4];
25319 :
25320 16185 : if (!TARGET_AVX2
25321 318 : || d->one_operand_p
25322 189 : || (d->vmode != V32QImode && d->vmode != V16HImode))
25323 : return false;
25324 :
25325 54 : if (d->testing_p)
25326 : return true;
25327 :
25328 54 : nelt = d->nelt;
25329 54 : eltsz = GET_MODE_UNIT_SIZE (d->vmode);
25330 :
25331 : /* Generate 4 permutation masks. If the required element is within
25332 : the same lane, it is shuffled in. If the required element from the
25333 : other lane, force a zero by setting bit 7 in the permutation mask.
25334 : In the other mask the mask has non-negative elements if element
25335 : is requested from the other lane, but also moved to the other lane,
25336 : so that the result of vpshufb can have the two V2TImode halves
25337 : swapped. */
25338 54 : m128 = GEN_INT (-128);
25339 1836 : for (i = 0; i < 32; ++i)
25340 : {
25341 1728 : rperm[0][i] = m128;
25342 1728 : rperm[1][i] = m128;
25343 1728 : rperm[2][i] = m128;
25344 1728 : rperm[3][i] = m128;
25345 : }
25346 54 : used[0] = false;
25347 54 : used[1] = false;
25348 54 : used[2] = false;
25349 54 : used[3] = false;
25350 1590 : for (i = 0; i < nelt; ++i)
25351 : {
25352 1536 : unsigned j, e = d->perm[i] & (nelt / 2 - 1);
25353 1536 : unsigned xlane = ((d->perm[i] ^ i) & (nelt / 2)) * eltsz;
25354 2074 : unsigned int which = ((d->perm[i] & nelt) ? 2 : 0) + (xlane ? 1 : 0);
25355 :
25356 3264 : for (j = 0; j < eltsz; ++j)
25357 1728 : rperm[which][(i * eltsz + j) ^ xlane] = GEN_INT (e * eltsz + j);
25358 1536 : used[which] = true;
25359 : }
25360 :
25361 162 : for (i = 0; i < 2; ++i)
25362 : {
25363 108 : if (!used[2 * i + 1])
25364 : {
25365 22 : h[i] = NULL_RTX;
25366 22 : continue;
25367 : }
25368 86 : vperm = gen_rtx_CONST_VECTOR (V32QImode,
25369 86 : gen_rtvec_v (32, rperm[2 * i + 1]));
25370 86 : vperm = force_reg (V32QImode, vperm);
25371 86 : h[i] = gen_reg_rtx (V32QImode);
25372 86 : op = gen_lowpart (V32QImode, i ? d->op1 : d->op0);
25373 86 : emit_insn (gen_avx2_pshufbv32qi3 (h[i], op, vperm));
25374 : }
25375 :
25376 : /* Swap the 128-byte lanes of h[X]. */
25377 162 : for (i = 0; i < 2; ++i)
25378 : {
25379 108 : if (h[i] == NULL_RTX)
25380 22 : continue;
25381 86 : op = gen_reg_rtx (V4DImode);
25382 86 : emit_insn (gen_avx2_permv4di_1 (op, gen_lowpart (V4DImode, h[i]),
25383 : const2_rtx, GEN_INT (3), const0_rtx,
25384 : const1_rtx));
25385 86 : h[i] = gen_lowpart (V32QImode, op);
25386 : }
25387 :
25388 162 : for (i = 0; i < 2; ++i)
25389 : {
25390 108 : if (!used[2 * i])
25391 : {
25392 0 : l[i] = NULL_RTX;
25393 0 : continue;
25394 : }
25395 108 : vperm = gen_rtx_CONST_VECTOR (V32QImode, gen_rtvec_v (32, rperm[2 * i]));
25396 108 : vperm = force_reg (V32QImode, vperm);
25397 108 : l[i] = gen_reg_rtx (V32QImode);
25398 108 : op = gen_lowpart (V32QImode, i ? d->op1 : d->op0);
25399 108 : emit_insn (gen_avx2_pshufbv32qi3 (l[i], op, vperm));
25400 : }
25401 :
25402 162 : for (i = 0; i < 2; ++i)
25403 : {
25404 108 : if (h[i] && l[i])
25405 : {
25406 86 : op = gen_reg_rtx (V32QImode);
25407 86 : emit_insn (gen_iorv32qi3 (op, l[i], h[i]));
25408 86 : l[i] = op;
25409 : }
25410 22 : else if (h[i])
25411 0 : l[i] = h[i];
25412 : }
25413 :
25414 54 : gcc_assert (l[0] && l[1]);
25415 54 : op = d->target;
25416 54 : if (d->vmode != V32QImode)
25417 12 : op = gen_reg_rtx (V32QImode);
25418 54 : emit_insn (gen_iorv32qi3 (op, l[0], l[1]));
25419 54 : if (op != d->target)
25420 12 : emit_move_insn (d->target, gen_lowpart (d->vmode, op));
25421 : return true;
25422 : }
25423 :
25424 : /* The guts of ix86_vectorize_vec_perm_const. With all of the interface bits
25425 : taken care of, perform the expansion in D and return true on success. */
25426 :
25427 : static bool
25428 334231 : ix86_expand_vec_perm_const_1 (struct expand_vec_perm_d *d)
25429 : {
25430 : /* Try a single instruction expansion. */
25431 334231 : if (expand_vec_perm_1 (d))
25432 : return true;
25433 :
25434 : /* Try sequences of two instructions. */
25435 :
25436 102322 : if (expand_vec_perm_pshuflw_pshufhw (d))
25437 : return true;
25438 :
25439 99859 : if (expand_vec_perm_palignr (d, false))
25440 : return true;
25441 :
25442 96724 : if (expand_vec_perm_interleave2 (d))
25443 : return true;
25444 :
25445 90785 : if (expand_vec_perm_broadcast (d))
25446 : return true;
25447 :
25448 90685 : if (expand_vec_perm_vpermq_perm_1 (d))
25449 : return true;
25450 :
25451 90685 : if (expand_vec_perm_vperm2f128 (d))
25452 : return true;
25453 :
25454 90617 : if (expand_vec_perm_pblendv (d))
25455 : return true;
25456 :
25457 88954 : if (expand_vec_perm_2perm_interleave (d, true))
25458 : return true;
25459 :
25460 88586 : if (expand_vec_perm_2perm_pblendv (d, true))
25461 : return true;
25462 :
25463 85707 : if (expand_vec_perm_shufps_shufps (d))
25464 : return true;
25465 :
25466 50503 : if (expand_vec_perm_punpckldq_pshuf (d))
25467 : return true;
25468 :
25469 : /* Try sequences of three instructions. */
25470 :
25471 44767 : if (expand_vec_perm_even_odd_pack (d))
25472 : return true;
25473 :
25474 30880 : if (expand_vec_perm_2vperm2f128_vshuf (d))
25475 : return true;
25476 :
25477 29603 : if (expand_vec_perm_pshufb2 (d))
25478 : return true;
25479 :
25480 28215 : if (expand_vec_perm_pslldq_psrldq_por (d, false))
25481 : return true;
25482 :
25483 27960 : if (expand_vec_perm_interleave3 (d))
25484 : return true;
25485 :
25486 27814 : if (expand_vec_perm_vperm2f128_vblend (d))
25487 : return true;
25488 :
25489 27814 : if (expand_vec_perm_2perm_interleave (d, false))
25490 : return true;
25491 :
25492 27574 : if (expand_vec_perm_2perm_pblendv (d, false))
25493 : return true;
25494 :
25495 27030 : if (expand_vec_perm_psrlw_psllw_por (d))
25496 : return true;
25497 :
25498 25576 : if (expand_vec_perm_pand_pandn_por (d))
25499 : return true;
25500 :
25501 : /* Try sequences of four instructions. */
25502 :
25503 24453 : if (expand_vec_perm_even_odd_trunc (d))
25504 : return true;
25505 24441 : if (expand_vec_perm_vpshufb2_vpermq (d))
25506 : return true;
25507 :
25508 24434 : if (expand_vec_perm_vpshufb2_vpermq_even_odd (d))
25509 : return true;
25510 :
25511 24434 : if (expand_vec_perm_vpermt2_vpshub2 (d))
25512 : return true;
25513 :
25514 : /* ??? Look for narrow permutations whose element orderings would
25515 : allow the promotion to a wider mode. */
25516 :
25517 : /* ??? Look for sequences of interleave or a wider permute that place
25518 : the data into the correct lanes for a half-vector shuffle like
25519 : pshuf[lh]w or vpermilps. */
25520 :
25521 : /* ??? Look for sequences of interleave that produce the desired results.
25522 : The combinatorics of punpck[lh] get pretty ugly... */
25523 :
25524 24385 : if (expand_vec_perm_even_odd (d))
25525 : return true;
25526 :
25527 : /* Generate four or five instructions. */
25528 16521 : if (expand_vec_perm_pslldq_psrldq_por (d, true))
25529 : return true;
25530 :
25531 : /* Even longer sequences. */
25532 16185 : if (expand_vec_perm_vpshufb4_vpermq2 (d))
25533 : return true;
25534 :
25535 : /* See if we can get the same permutation in different vector integer
25536 : mode. */
25537 16131 : struct expand_vec_perm_d nd;
25538 16131 : if (canonicalize_vector_int_perm (d, &nd) && expand_vec_perm_1 (&nd))
25539 : {
25540 0 : if (!d->testing_p)
25541 0 : emit_move_insn (d->target, gen_lowpart (d->vmode, nd.target));
25542 0 : return true;
25543 : }
25544 :
25545 : /* Even longer, including recursion to ix86_expand_vec_perm_const_1. */
25546 16131 : if (expand_vec_perm2_vperm2f128_vblend (d))
25547 : return true;
25548 :
25549 : return false;
25550 : }
25551 :
25552 : /* If a permutation only uses one operand, make it clear. Returns true
25553 : if the permutation references both operands. */
25554 :
25555 : static bool
25556 74931 : canonicalize_perm (struct expand_vec_perm_d *d)
25557 : {
25558 74931 : int i, which, nelt = d->nelt;
25559 :
25560 449593 : for (i = which = 0; i < nelt; ++i)
25561 509229 : which |= (d->perm[i] < nelt ? 1 : 2);
25562 :
25563 74931 : d->one_operand_p = true;
25564 74931 : switch (which)
25565 : {
25566 0 : default:
25567 0 : gcc_unreachable();
25568 :
25569 55784 : case 3:
25570 55784 : if (!rtx_equal_p (d->op0, d->op1))
25571 : {
25572 55755 : d->one_operand_p = false;
25573 55755 : break;
25574 : }
25575 : /* The elements of PERM do not suggest that only the first operand
25576 : is used, but both operands are identical. Allow easier matching
25577 : of the permutation by folding the permutation into the single
25578 : input vector. */
25579 : /* FALLTHRU */
25580 :
25581 : case 2:
25582 2635 : for (i = 0; i < nelt; ++i)
25583 2320 : d->perm[i] &= nelt - 1;
25584 315 : d->op0 = d->op1;
25585 315 : break;
25586 :
25587 18861 : case 1:
25588 18861 : d->op1 = d->op0;
25589 18861 : break;
25590 : }
25591 :
25592 74931 : return (which == 3);
25593 : }
25594 :
25595 : /* Implement TARGET_VECTORIZE_VEC_PERM_CONST. */
25596 :
25597 : bool
25598 818142 : ix86_vectorize_vec_perm_const (machine_mode vmode, machine_mode op_mode,
25599 : rtx target, rtx op0, rtx op1,
25600 : const vec_perm_indices &sel)
25601 : {
25602 818142 : if (vmode != op_mode)
25603 : return false;
25604 :
25605 816283 : struct expand_vec_perm_d d;
25606 816283 : unsigned char perm[MAX_VECT_LEN];
25607 816283 : unsigned int i, nelt, which;
25608 816283 : bool two_args;
25609 :
25610 : /* For HF and BF mode vector, convert it to HI using subreg. */
25611 2446363 : if (GET_MODE_INNER (vmode) == HFmode || GET_MODE_INNER (vmode) == BFmode)
25612 : {
25613 2512 : machine_mode orig_mode = vmode;
25614 5024 : vmode = mode_for_vector (HImode,
25615 2512 : GET_MODE_NUNITS (vmode)).require ();
25616 2512 : if (target)
25617 437 : target = lowpart_subreg (vmode, target, orig_mode);
25618 2512 : if (op0)
25619 437 : op0 = lowpart_subreg (vmode, op0, orig_mode);
25620 2512 : if (op1)
25621 437 : op1 = lowpart_subreg (vmode, op1, orig_mode);
25622 : }
25623 :
25624 816283 : d.target = target;
25625 816283 : d.op0 = op0;
25626 816283 : d.op1 = op1;
25627 :
25628 816283 : d.vmode = vmode;
25629 816283 : gcc_assert (VECTOR_MODE_P (d.vmode));
25630 816283 : d.nelt = nelt = GET_MODE_NUNITS (d.vmode);
25631 816283 : d.testing_p = !target;
25632 :
25633 816283 : gcc_assert (sel.length () == nelt);
25634 816283 : gcc_checking_assert (sizeof (d.perm) == sizeof (perm));
25635 :
25636 : /* Given sufficient ISA support we can just return true here
25637 : for selected vector modes. */
25638 816283 : switch (d.vmode)
25639 : {
25640 1636 : case E_V16SFmode:
25641 1636 : case E_V16SImode:
25642 1636 : case E_V8DImode:
25643 1636 : case E_V8DFmode:
25644 1636 : if (!TARGET_AVX512F)
25645 : return false;
25646 : /* All implementable with a single vperm[it]2 insn. */
25647 1636 : if (d.testing_p)
25648 : return true;
25649 : break;
25650 323 : case E_V32HImode:
25651 323 : if (!TARGET_AVX512F)
25652 : return false;
25653 323 : if (d.testing_p && TARGET_AVX512BW)
25654 : /* All implementable with a single vperm[it]2 insn. */
25655 : return true;
25656 : break;
25657 747 : case E_V64QImode:
25658 747 : if (!TARGET_AVX512F)
25659 : return false;
25660 747 : if (d.testing_p && TARGET_AVX512BW)
25661 : /* Implementable with 2 vperm[it]2, 2 vpshufb and 1 or insn. */
25662 : return true;
25663 : break;
25664 11410 : case E_V8SImode:
25665 11410 : case E_V8SFmode:
25666 11410 : case E_V4DFmode:
25667 11410 : case E_V4DImode:
25668 11410 : if (!TARGET_AVX)
25669 : return false;
25670 11410 : if (d.testing_p && TARGET_AVX512VL)
25671 : /* All implementable with a single vperm[it]2 insn. */
25672 : return true;
25673 : break;
25674 614 : case E_V16HImode:
25675 614 : if (!TARGET_SSE2)
25676 : return false;
25677 614 : if (d.testing_p && TARGET_AVX2)
25678 : /* Implementable with 4 vpshufb insns, 2 vpermq and 3 vpor insns. */
25679 : return true;
25680 : break;
25681 693 : case E_V32QImode:
25682 693 : if (!TARGET_SSE2)
25683 : return false;
25684 693 : if (d.testing_p && TARGET_AVX2)
25685 : /* Implementable with 4 vpshufb insns, 2 vpermq and 3 vpor insns. */
25686 : return true;
25687 : break;
25688 38754 : case E_V8HImode:
25689 38754 : case E_V16QImode:
25690 38754 : if (!TARGET_SSE2)
25691 : return false;
25692 : /* Fall through. */
25693 238738 : case E_V4SImode:
25694 238738 : case E_V4SFmode:
25695 238738 : if (!TARGET_SSE)
25696 : return false;
25697 : /* All implementable with a single vpperm insn. */
25698 238738 : if (d.testing_p && TARGET_XOP)
25699 : return true;
25700 : /* All implementable with 2 pshufb + 1 ior. */
25701 238632 : if (d.testing_p && TARGET_SSSE3)
25702 : return true;
25703 : break;
25704 178499 : case E_V2SFmode:
25705 178499 : case E_V2SImode:
25706 178499 : case E_V4HImode:
25707 178499 : case E_V8QImode:
25708 178499 : if (!TARGET_MMX_WITH_SSE)
25709 : return false;
25710 : break;
25711 23016 : case E_V2HImode:
25712 23016 : if (!TARGET_SSE2)
25713 : return false;
25714 : /* All implementable with *punpckwd. */
25715 23016 : if (d.testing_p)
25716 : return true;
25717 : break;
25718 11958 : case E_V4QImode:
25719 11958 : if (!TARGET_SSE2)
25720 : return false;
25721 : break;
25722 346403 : case E_V2DImode:
25723 346403 : case E_V2DFmode:
25724 346403 : if (!TARGET_SSE)
25725 : return false;
25726 : /* All implementable with shufpd or unpck[lh]pd. */
25727 346403 : if (d.testing_p)
25728 : return true;
25729 : break;
25730 : default:
25731 : return false;
25732 : }
25733 :
25734 2365509 : for (i = which = 0; i < nelt; ++i)
25735 : {
25736 1918976 : unsigned char e = sel[i];
25737 1918976 : gcc_assert (e < 2 * nelt);
25738 1918976 : d.perm[i] = e;
25739 1918976 : perm[i] = e;
25740 2596380 : which |= (e < nelt ? 1 : 2);
25741 : }
25742 :
25743 446533 : if (d.testing_p)
25744 : {
25745 : /* For all elements from second vector, fold the elements to first. */
25746 372866 : if (which == 2)
25747 1060 : for (i = 0; i < nelt; ++i)
25748 958 : d.perm[i] -= nelt;
25749 :
25750 : /* Check whether the mask can be applied to the vector type. */
25751 372866 : d.one_operand_p = (which != 3);
25752 :
25753 : /* Implementable with shufps, pshufd or pshuflw. */
25754 372866 : if (d.one_operand_p
25755 : && (d.vmode == V4SFmode || d.vmode == V2SFmode
25756 : || d.vmode == V4SImode || d.vmode == V2SImode
25757 : || d.vmode == V4HImode || d.vmode == V2HImode))
25758 : return true;
25759 :
25760 : /* Otherwise we have to go through the motions and see if we can
25761 : figure out how to generate the requested permutation. */
25762 256712 : d.target = gen_raw_REG (d.vmode, LAST_VIRTUAL_REGISTER + 1);
25763 256712 : d.op1 = d.op0 = gen_raw_REG (d.vmode, LAST_VIRTUAL_REGISTER + 2);
25764 256712 : if (!d.one_operand_p)
25765 242303 : d.op1 = gen_raw_REG (d.vmode, LAST_VIRTUAL_REGISTER + 3);
25766 :
25767 256712 : start_sequence ();
25768 256712 : bool ret = ix86_expand_vec_perm_const_1 (&d);
25769 256712 : end_sequence ();
25770 :
25771 256712 : return ret;
25772 : }
25773 :
25774 73667 : two_args = canonicalize_perm (&d);
25775 :
25776 : /* If one of the operands is a zero vector, try to match pmovzx. */
25777 73667 : if (two_args && (d.op0 == CONST0_RTX (vmode) || d.op1 == CONST0_RTX (vmode)))
25778 : {
25779 618 : struct expand_vec_perm_d dzero = d;
25780 618 : if (d.op0 == CONST0_RTX (vmode))
25781 : {
25782 387 : d.op1 = dzero.op1 = force_reg (vmode, d.op1);
25783 387 : std::swap (dzero.op0, dzero.op1);
25784 7527 : for (i = 0; i < nelt; ++i)
25785 7140 : dzero.perm[i] ^= nelt;
25786 : }
25787 : else
25788 231 : d.op0 = dzero.op0 = force_reg (vmode, d.op0);
25789 :
25790 618 : if (expand_vselect_vconcat (dzero.target, dzero.op0, dzero.op1,
25791 618 : dzero.perm, nelt, dzero.testing_p))
25792 128 : return true;
25793 : }
25794 :
25795 : /* Force operands into registers. */
25796 73539 : rtx nop0 = force_reg (vmode, d.op0);
25797 73539 : if (d.op0 == d.op1)
25798 18775 : d.op1 = nop0;
25799 73539 : d.op0 = nop0;
25800 73539 : d.op1 = force_reg (vmode, d.op1);
25801 :
25802 73539 : if (ix86_expand_vec_perm_const_1 (&d))
25803 : return true;
25804 :
25805 : /* If the selector says both arguments are needed, but the operands are the
25806 : same, the above tried to expand with one_operand_p and flattened selector.
25807 : If that didn't work, retry without one_operand_p; we succeeded with that
25808 : during testing. */
25809 0 : if (two_args && d.one_operand_p)
25810 : {
25811 0 : d.one_operand_p = false;
25812 0 : memcpy (d.perm, perm, sizeof (perm));
25813 0 : return ix86_expand_vec_perm_const_1 (&d);
25814 : }
25815 :
25816 : return false;
25817 : }
25818 :
25819 : void
25820 8237 : ix86_expand_vec_extract_even_odd (rtx targ, rtx op0, rtx op1, unsigned odd)
25821 : {
25822 8237 : struct expand_vec_perm_d d;
25823 8237 : unsigned i, nelt;
25824 :
25825 8237 : d.target = targ;
25826 8237 : d.op0 = op0;
25827 8237 : d.op1 = op1;
25828 8237 : d.vmode = GET_MODE (targ);
25829 8237 : d.nelt = nelt = GET_MODE_NUNITS (d.vmode);
25830 8237 : d.one_operand_p = false;
25831 8237 : d.testing_p = false;
25832 :
25833 78061 : for (i = 0; i < nelt; ++i)
25834 69824 : d.perm[i] = i * 2 + odd;
25835 :
25836 : /* We'll either be able to implement the permutation directly... */
25837 8237 : if (expand_vec_perm_1 (&d))
25838 3209 : return;
25839 :
25840 : /* ... or we use the special-case patterns. */
25841 5028 : expand_vec_perm_even_odd_1 (&d, odd);
25842 : }
25843 :
25844 : static void
25845 922 : ix86_expand_vec_interleave (rtx targ, rtx op0, rtx op1, bool high_p)
25846 : {
25847 922 : struct expand_vec_perm_d d;
25848 922 : unsigned i, nelt, base;
25849 922 : bool ok;
25850 :
25851 922 : d.target = targ;
25852 922 : d.op0 = op0;
25853 922 : d.op1 = op1;
25854 922 : d.vmode = GET_MODE (targ);
25855 922 : d.nelt = nelt = GET_MODE_NUNITS (d.vmode);
25856 922 : d.one_operand_p = false;
25857 922 : d.testing_p = false;
25858 :
25859 922 : base = high_p ? nelt / 2 : 0;
25860 3642 : for (i = 0; i < nelt / 2; ++i)
25861 : {
25862 2720 : d.perm[i * 2] = i + base;
25863 2720 : d.perm[i * 2 + 1] = i + base + nelt;
25864 : }
25865 :
25866 : /* Note that for AVX this isn't one instruction. */
25867 922 : ok = ix86_expand_vec_perm_const_1 (&d);
25868 922 : gcc_assert (ok);
25869 922 : }
25870 :
25871 : /* Expand a vector operation shift by constant for a V*QImode in terms of the
25872 : same operation on V*HImode. Return true if success. */
25873 : static bool
25874 395 : ix86_expand_vec_shift_qihi_constant (enum rtx_code code,
25875 : rtx dest, rtx op1, rtx op2)
25876 : {
25877 395 : machine_mode qimode, himode;
25878 395 : HOST_WIDE_INT and_constant, xor_constant;
25879 395 : HOST_WIDE_INT shift_amount;
25880 395 : rtx vec_const_and, vec_const_xor;
25881 395 : rtx tmp, op1_subreg;
25882 395 : rtx (*gen_shift) (rtx, rtx, rtx);
25883 395 : rtx (*gen_and) (rtx, rtx, rtx);
25884 395 : rtx (*gen_xor) (rtx, rtx, rtx);
25885 395 : rtx (*gen_sub) (rtx, rtx, rtx);
25886 :
25887 : /* Only optimize shift by constant. */
25888 395 : if (!CONST_INT_P (op2))
25889 : return false;
25890 :
25891 395 : qimode = GET_MODE (dest);
25892 395 : shift_amount = INTVAL (op2);
25893 : /* Do nothing when shift amount greater equal 8. */
25894 395 : if (shift_amount > 7)
25895 : return false;
25896 :
25897 395 : gcc_assert (code == ASHIFT || code == ASHIFTRT || code == LSHIFTRT);
25898 :
25899 :
25900 395 : if (shift_amount == 7
25901 395 : && code == ASHIFTRT)
25902 : {
25903 47 : if (qimode == V16QImode
25904 8 : || qimode == V32QImode)
25905 : {
25906 46 : rtx zero = gen_reg_rtx (qimode);
25907 46 : emit_move_insn (zero, CONST0_RTX (qimode));
25908 46 : emit_move_insn (dest, gen_rtx_fmt_ee (GT, qimode, zero, op1));
25909 46 : }
25910 : else
25911 : {
25912 1 : gcc_assert (qimode == V64QImode);
25913 1 : rtx kmask = gen_reg_rtx (DImode);
25914 1 : emit_insn (gen_avx512bw_cvtb2maskv64qi (kmask, op1));
25915 1 : emit_insn (gen_avx512bw_cvtmask2bv64qi (dest, kmask));
25916 : }
25917 47 : return true;
25918 : }
25919 :
25920 : /* Record sign bit. */
25921 348 : xor_constant = 1 << (8 - shift_amount - 1);
25922 :
25923 : /* Zero upper/lower bits shift from left/right element. */
25924 348 : and_constant
25925 348 : = (code == ASHIFT ? 256 - (1 << shift_amount)
25926 317 : : (1 << (8 - shift_amount)) - 1);
25927 :
25928 348 : switch (qimode)
25929 : {
25930 335 : case V16QImode:
25931 335 : himode = V8HImode;
25932 281 : gen_shift =
25933 : ((code == ASHIFT)
25934 335 : ? gen_ashlv8hi3
25935 313 : : (code == ASHIFTRT) ? gen_ashrv8hi3 : gen_lshrv8hi3);
25936 : gen_and = gen_andv16qi3;
25937 : gen_xor = gen_xorv16qi3;
25938 : gen_sub = gen_subv16qi3;
25939 : break;
25940 6 : case V32QImode:
25941 6 : himode = V16HImode;
25942 1 : gen_shift =
25943 : ((code == ASHIFT)
25944 6 : ? gen_ashlv16hi3
25945 2 : : (code == ASHIFTRT) ? gen_ashrv16hi3 : gen_lshrv16hi3);
25946 : gen_and = gen_andv32qi3;
25947 : gen_xor = gen_xorv32qi3;
25948 : gen_sub = gen_subv32qi3;
25949 : break;
25950 7 : case V64QImode:
25951 7 : himode = V32HImode;
25952 1 : gen_shift =
25953 : ((code == ASHIFT)
25954 7 : ? gen_ashlv32hi3
25955 2 : : (code == ASHIFTRT) ? gen_ashrv32hi3 : gen_lshrv32hi3);
25956 : gen_and = gen_andv64qi3;
25957 : gen_xor = gen_xorv64qi3;
25958 : gen_sub = gen_subv64qi3;
25959 : break;
25960 0 : default:
25961 0 : gcc_unreachable ();
25962 : }
25963 :
25964 348 : tmp = gen_reg_rtx (himode);
25965 348 : vec_const_and = gen_reg_rtx (qimode);
25966 348 : op1_subreg = lowpart_subreg (himode, op1, qimode);
25967 :
25968 : /* For ASHIFT and LSHIFTRT, perform operation like
25969 : vpsllw/vpsrlw $shift_amount, %op1, %dest.
25970 : vpand %vec_const_and, %dest. */
25971 348 : emit_insn (gen_shift (tmp, op1_subreg, op2));
25972 348 : emit_move_insn (dest, simplify_gen_subreg (qimode, tmp, himode, 0));
25973 348 : emit_move_insn (vec_const_and,
25974 : ix86_build_const_vector (qimode, true,
25975 348 : gen_int_mode (and_constant, QImode)));
25976 348 : emit_insn (gen_and (dest, dest, vec_const_and));
25977 :
25978 : /* For ASHIFTRT, perform extra operation like
25979 : vpxor %vec_const_xor, %dest, %dest
25980 : vpsubb %vec_const_xor, %dest, %dest */
25981 348 : if (code == ASHIFTRT)
25982 : {
25983 34 : vec_const_xor = gen_reg_rtx (qimode);
25984 34 : emit_move_insn (vec_const_xor,
25985 : ix86_build_const_vector (qimode, true,
25986 34 : gen_int_mode (xor_constant, QImode)));
25987 34 : emit_insn (gen_xor (dest, dest, vec_const_xor));
25988 34 : emit_insn (gen_sub (dest, dest, vec_const_xor));
25989 : }
25990 : return true;
25991 : }
25992 :
25993 : void
25994 1440 : ix86_expand_vecop_qihi_partial (enum rtx_code code, rtx dest, rtx op1, rtx op2)
25995 : {
25996 1440 : machine_mode qimode = GET_MODE (dest);
25997 1440 : rtx qop1, qop2, hop1, hop2, qdest, hdest;
25998 1440 : bool op2vec = GET_MODE_CLASS (GET_MODE (op2)) == MODE_VECTOR_INT;
25999 1440 : bool uns_p = code != ASHIFTRT;
26000 :
26001 1440 : switch (qimode)
26002 : {
26003 1440 : case E_V4QImode:
26004 1440 : case E_V8QImode:
26005 1440 : break;
26006 0 : default:
26007 0 : gcc_unreachable ();
26008 : }
26009 :
26010 1440 : qop1 = lowpart_subreg (V16QImode, force_reg (qimode, op1), qimode);
26011 :
26012 1440 : if (op2vec)
26013 1310 : qop2 = lowpart_subreg (V16QImode, force_reg (qimode, op2), qimode);
26014 : else
26015 : qop2 = op2;
26016 :
26017 1440 : qdest = gen_reg_rtx (V16QImode);
26018 :
26019 1440 : if (CONST_INT_P (op2)
26020 118 : && (code == ASHIFT || code == LSHIFTRT || code == ASHIFTRT)
26021 : /* With AVX512 it's cheaper to do vpmovsxbw/op/vpmovwb.
26022 : Even with SSE4.1 the alternative is better. */
26023 118 : && !TARGET_SSE4_1
26024 1494 : && ix86_expand_vec_shift_qihi_constant (code, qdest, qop1, qop2))
26025 : {
26026 54 : emit_move_insn (dest, gen_lowpart (qimode, qdest));
26027 54 : return;
26028 : }
26029 :
26030 1386 : if (CONST_INT_P (op2)
26031 64 : && code == ASHIFTRT
26032 14 : && INTVAL (op2) == 7)
26033 : {
26034 4 : rtx zero = gen_reg_rtx (qimode);
26035 4 : emit_move_insn (zero, CONST0_RTX (qimode));
26036 4 : emit_move_insn (dest, gen_rtx_fmt_ee (GT, qimode, zero, op1));
26037 4 : return;
26038 : }
26039 :
26040 1382 : switch (code)
26041 : {
26042 1297 : case MULT:
26043 1297 : gcc_assert (op2vec);
26044 1297 : if (!TARGET_SSE4_1)
26045 : {
26046 : /* Unpack data such that we've got a source byte in each low byte
26047 : of each word. We don't care what goes into the high byte of
26048 : each word. Rather than trying to get zero in there, most
26049 : convenient is to let it be a copy of the low byte. */
26050 244 : hop1 = copy_to_reg (qop1);
26051 244 : hop2 = copy_to_reg (qop2);
26052 244 : emit_insn (gen_vec_interleave_lowv16qi (hop1, hop1, hop1));
26053 244 : emit_insn (gen_vec_interleave_lowv16qi (hop2, hop2, hop2));
26054 244 : break;
26055 : }
26056 : /* FALLTHRU */
26057 1138 : case ASHIFT:
26058 1138 : case ASHIFTRT:
26059 1138 : case LSHIFTRT:
26060 1138 : hop1 = gen_reg_rtx (V8HImode);
26061 1138 : ix86_expand_sse_unpack (hop1, qop1, uns_p, false);
26062 : /* mult/vashr/vlshr/vashl */
26063 1138 : if (op2vec)
26064 : {
26065 1066 : hop2 = gen_reg_rtx (V8HImode);
26066 1066 : ix86_expand_sse_unpack (hop2, qop2, uns_p, false);
26067 : }
26068 : else
26069 : hop2 = qop2;
26070 :
26071 : break;
26072 0 : default:
26073 0 : gcc_unreachable ();
26074 : }
26075 :
26076 1382 : if (code != MULT && op2vec)
26077 : {
26078 : /* Expand vashr/vlshr/vashl. */
26079 13 : hdest = gen_reg_rtx (V8HImode);
26080 13 : emit_insn (gen_rtx_SET (hdest,
26081 : simplify_gen_binary (code, V8HImode,
26082 : hop1, hop2)));
26083 : }
26084 : else
26085 : /* Expand mult/ashr/lshr/ashl. */
26086 1369 : hdest = expand_simple_binop (V8HImode, code, hop1, hop2,
26087 : NULL_RTX, 1, OPTAB_DIRECT);
26088 :
26089 1382 : if (TARGET_AVX512BW && TARGET_AVX512VL)
26090 : {
26091 57 : if (qimode == V8QImode)
26092 : qdest = dest;
26093 : else
26094 10 : qdest = gen_reg_rtx (V8QImode);
26095 :
26096 57 : emit_insn (gen_truncv8hiv8qi2 (qdest, hdest));
26097 : }
26098 : else
26099 : {
26100 1325 : struct expand_vec_perm_d d;
26101 1325 : rtx qres = gen_lowpart (V16QImode, hdest);
26102 1325 : bool ok;
26103 1325 : int i;
26104 :
26105 : /* Merge the data back into the right place. */
26106 1325 : d.target = qdest;
26107 1325 : d.op0 = d.op1 = qres;
26108 1325 : d.vmode = V16QImode;
26109 1325 : d.nelt = 16;
26110 1325 : d.one_operand_p = TARGET_SSSE3;
26111 1325 : d.testing_p = false;
26112 :
26113 22525 : for (i = 0; i < d.nelt; ++i)
26114 21200 : d.perm[i] = i * 2;
26115 :
26116 1325 : ok = ix86_expand_vec_perm_const_1 (&d);
26117 1325 : gcc_assert (ok);
26118 : }
26119 :
26120 1382 : if (qdest != dest)
26121 1335 : emit_move_insn (dest, gen_lowpart (qimode, qdest));
26122 : }
26123 :
26124 : /* Emit instruction in 2x wider mode. For example, optimize
26125 : vector MUL generation like
26126 :
26127 : vpmovzxbw ymm2, xmm0
26128 : vpmovzxbw ymm3, xmm1
26129 : vpmullw ymm4, ymm2, ymm3
26130 : vpmovwb xmm0, ymm4
26131 :
26132 : it would take less instructions than ix86_expand_vecop_qihi.
26133 : Return true if success. */
26134 :
26135 : static bool
26136 1177 : ix86_expand_vecop_qihi2 (enum rtx_code code, rtx dest, rtx op1, rtx op2)
26137 : {
26138 1177 : machine_mode himode, qimode = GET_MODE (dest);
26139 1177 : machine_mode wqimode;
26140 1177 : rtx qop1, qop2, hop1, hop2, hdest;
26141 1177 : rtx (*gen_truncate)(rtx, rtx) = NULL;
26142 1177 : bool op2vec = GET_MODE_CLASS (GET_MODE (op2)) == MODE_VECTOR_INT;
26143 1177 : bool uns_p = code != ASHIFTRT;
26144 :
26145 : /* Without VPMOVWB (provided by AVX512BW ISA), the expansion uses the
26146 : generic permutation to merge the data back into the right place. This
26147 : permutation results in VPERMQ, which is slow, so better fall back to
26148 : ix86_expand_vecop_qihi. */
26149 1177 : if (!TARGET_AVX512BW
26150 327 : || (qimode == V16QImode && !TARGET_AVX512VL)
26151 : /* There are no V64HImode instructions. */
26152 327 : || qimode == V64QImode)
26153 : return false;
26154 :
26155 : /* Do not generate ymm/zmm instructions when
26156 : target prefers 128/256 bit vector width. */
26157 317 : if ((qimode == V16QImode && TARGET_PREFER_AVX128)
26158 317 : || (qimode == V32QImode && TARGET_PREFER_AVX256))
26159 : return false;
26160 :
26161 312 : switch (qimode)
26162 : {
26163 : case E_V16QImode:
26164 : himode = V16HImode;
26165 : gen_truncate = gen_truncv16hiv16qi2;
26166 : break;
26167 57 : case E_V32QImode:
26168 57 : himode = V32HImode;
26169 57 : gen_truncate = gen_truncv32hiv32qi2;
26170 57 : break;
26171 0 : default:
26172 0 : gcc_unreachable ();
26173 : }
26174 :
26175 312 : wqimode = GET_MODE_2XWIDER_MODE (qimode).require ();
26176 312 : qop1 = lowpart_subreg (wqimode, force_reg (qimode, op1), qimode);
26177 :
26178 312 : if (op2vec)
26179 312 : qop2 = lowpart_subreg (wqimode, force_reg (qimode, op2), qimode);
26180 : else
26181 : qop2 = op2;
26182 :
26183 312 : hop1 = gen_reg_rtx (himode);
26184 312 : ix86_expand_sse_unpack (hop1, qop1, uns_p, false);
26185 :
26186 312 : if (op2vec)
26187 : {
26188 312 : hop2 = gen_reg_rtx (himode);
26189 312 : ix86_expand_sse_unpack (hop2, qop2, uns_p, false);
26190 : }
26191 : else
26192 : hop2 = qop2;
26193 :
26194 312 : if (code != MULT && op2vec)
26195 : {
26196 : /* Expand vashr/vlshr/vashl. */
26197 14 : hdest = gen_reg_rtx (himode);
26198 14 : emit_insn (gen_rtx_SET (hdest,
26199 : simplify_gen_binary (code, himode,
26200 : hop1, hop2)));
26201 : }
26202 : else
26203 : /* Expand mult/ashr/lshr/ashl. */
26204 298 : hdest = expand_simple_binop (himode, code, hop1, hop2,
26205 : NULL_RTX, 1, OPTAB_DIRECT);
26206 :
26207 312 : emit_insn (gen_truncate (dest, hdest));
26208 312 : return true;
26209 : }
26210 :
26211 : /* Expand a vector operation CODE for a V*QImode in terms of the
26212 : same operation on V*HImode. */
26213 :
26214 : void
26215 1518 : ix86_expand_vecop_qihi (enum rtx_code code, rtx dest, rtx op1, rtx op2)
26216 : {
26217 1518 : machine_mode qimode = GET_MODE (dest);
26218 1518 : machine_mode himode;
26219 1518 : rtx (*gen_il) (rtx, rtx, rtx);
26220 1518 : rtx (*gen_ih) (rtx, rtx, rtx);
26221 1518 : rtx op1_l, op1_h, op2_l, op2_h, res_l, res_h;
26222 1518 : bool op2vec = GET_MODE_CLASS (GET_MODE (op2)) == MODE_VECTOR_INT;
26223 1518 : struct expand_vec_perm_d d;
26224 1518 : bool full_interleave = true;
26225 1518 : bool uns_p = code != ASHIFTRT;
26226 1518 : bool ok;
26227 1518 : int i;
26228 :
26229 1518 : if (CONST_INT_P (op2)
26230 341 : && (code == ASHIFT || code == LSHIFTRT || code == ASHIFTRT)
26231 1859 : && ix86_expand_vec_shift_qihi_constant (code, dest, op1, op2))
26232 653 : return;
26233 :
26234 1177 : if (ix86_expand_vecop_qihi2 (code, dest, op1, op2))
26235 : return;
26236 :
26237 865 : switch (qimode)
26238 : {
26239 : case E_V16QImode:
26240 : himode = V8HImode;
26241 : break;
26242 44 : case E_V32QImode:
26243 44 : himode = V16HImode;
26244 44 : break;
26245 10 : case E_V64QImode:
26246 10 : himode = V32HImode;
26247 10 : break;
26248 0 : default:
26249 0 : gcc_unreachable ();
26250 : }
26251 :
26252 865 : switch (code)
26253 : {
26254 819 : case MULT:
26255 819 : gcc_assert (op2vec);
26256 : /* Unpack data such that we've got a source byte in each low byte of
26257 : each word. We don't care what goes into the high byte of each word.
26258 : Rather than trying to get zero in there, most convenient is to let
26259 : it be a copy of the low byte. */
26260 819 : switch (qimode)
26261 : {
26262 : case E_V16QImode:
26263 : gen_il = gen_vec_interleave_lowv16qi;
26264 : gen_ih = gen_vec_interleave_highv16qi;
26265 : break;
26266 44 : case E_V32QImode:
26267 44 : gen_il = gen_avx2_interleave_lowv32qi;
26268 44 : gen_ih = gen_avx2_interleave_highv32qi;
26269 44 : full_interleave = false;
26270 44 : break;
26271 8 : case E_V64QImode:
26272 8 : gen_il = gen_avx512bw_interleave_lowv64qi;
26273 8 : gen_ih = gen_avx512bw_interleave_highv64qi;
26274 8 : full_interleave = false;
26275 8 : break;
26276 0 : default:
26277 0 : gcc_unreachable ();
26278 : }
26279 :
26280 819 : op2_l = gen_reg_rtx (qimode);
26281 819 : op2_h = gen_reg_rtx (qimode);
26282 819 : emit_insn (gen_il (op2_l, op2, op2));
26283 819 : emit_insn (gen_ih (op2_h, op2, op2));
26284 :
26285 819 : op1_l = gen_reg_rtx (qimode);
26286 819 : op1_h = gen_reg_rtx (qimode);
26287 819 : emit_insn (gen_il (op1_l, op1, op1));
26288 819 : emit_insn (gen_ih (op1_h, op1, op1));
26289 819 : break;
26290 :
26291 46 : case ASHIFT:
26292 46 : case ASHIFTRT:
26293 46 : case LSHIFTRT:
26294 46 : op1_l = gen_reg_rtx (himode);
26295 46 : op1_h = gen_reg_rtx (himode);
26296 46 : ix86_expand_sse_unpack (op1_l, op1, uns_p, false);
26297 46 : ix86_expand_sse_unpack (op1_h, op1, uns_p, true);
26298 : /* vashr/vlshr/vashl */
26299 46 : if (op2vec)
26300 : {
26301 2 : rtx tmp = force_reg (qimode, op2);
26302 2 : op2_l = gen_reg_rtx (himode);
26303 2 : op2_h = gen_reg_rtx (himode);
26304 2 : ix86_expand_sse_unpack (op2_l, tmp, uns_p, false);
26305 2 : ix86_expand_sse_unpack (op2_h, tmp, uns_p, true);
26306 : }
26307 : else
26308 : op2_l = op2_h = op2;
26309 :
26310 : break;
26311 0 : default:
26312 0 : gcc_unreachable ();
26313 : }
26314 :
26315 865 : if (code != MULT && op2vec)
26316 : {
26317 : /* Expand vashr/vlshr/vashl. */
26318 2 : res_l = gen_reg_rtx (himode);
26319 2 : res_h = gen_reg_rtx (himode);
26320 2 : emit_insn (gen_rtx_SET (res_l,
26321 : simplify_gen_binary (code, himode,
26322 : op1_l, op2_l)));
26323 2 : emit_insn (gen_rtx_SET (res_h,
26324 : simplify_gen_binary (code, himode,
26325 : op1_h, op2_h)));
26326 : }
26327 : else
26328 : {
26329 : /* Expand mult/ashr/lshr/ashl. */
26330 863 : res_l = expand_simple_binop (himode, code, op1_l, op2_l, NULL_RTX,
26331 : 1, OPTAB_DIRECT);
26332 863 : res_h = expand_simple_binop (himode, code, op1_h, op2_h, NULL_RTX,
26333 : 1, OPTAB_DIRECT);
26334 : }
26335 :
26336 865 : gcc_assert (res_l && res_h);
26337 :
26338 : /* Merge the data back into the right place. */
26339 865 : d.target = dest;
26340 865 : d.op0 = gen_lowpart (qimode, res_l);
26341 865 : d.op1 = gen_lowpart (qimode, res_h);
26342 865 : d.vmode = qimode;
26343 865 : d.nelt = GET_MODE_NUNITS (qimode);
26344 865 : d.one_operand_p = false;
26345 865 : d.testing_p = false;
26346 :
26347 865 : if (full_interleave)
26348 : {
26349 : /* We used the full interleave, the desired
26350 : results are in the even elements. */
26351 13917 : for (i = 0; i < d.nelt; ++i)
26352 13104 : d.perm[i] = i * 2;
26353 : }
26354 : else
26355 : {
26356 : /* For AVX, the interleave used above was not cross-lane. So the
26357 : extraction is evens but with the second and third quarter swapped.
26358 : Happily, that is even one insn shorter than even extraction.
26359 : For AVX512BW we have 4 lanes. We extract evens from within a lane,
26360 : always first from the first and then from the second source operand,
26361 : the index bits above the low 4 bits remains the same.
26362 : Thus, for d.nelt == 32 we want permutation
26363 : 0,2,4,..14, 32,34,36,..46, 16,18,20,..30, 48,50,52,..62
26364 : and for d.nelt == 64 we want permutation
26365 : 0,2,4,..14, 64,66,68,..78, 16,18,20,..30, 80,82,84,..94,
26366 : 32,34,36,..46, 96,98,100,..110, 48,50,52,..62, 112,114,116,..126. */
26367 1972 : for (i = 0; i < d.nelt; ++i)
26368 2880 : d.perm[i] = ((i * 2) & 14) + ((i & 8) ? d.nelt : 0) + (i & ~15);
26369 : }
26370 :
26371 865 : ok = ix86_expand_vec_perm_const_1 (&d);
26372 865 : gcc_assert (ok);
26373 : }
26374 :
26375 : /* Helper function of ix86_expand_mul_widen_evenodd. Return true
26376 : if op is CONST_VECTOR with all odd elements equal to their
26377 : preceding element. */
26378 :
26379 : static bool
26380 8842 : const_vector_equal_evenodd_p (rtx op)
26381 : {
26382 8842 : machine_mode mode = GET_MODE (op);
26383 8842 : int i, nunits = GET_MODE_NUNITS (mode);
26384 8842 : if (!CONST_VECTOR_P (op)
26385 8842 : || nunits != CONST_VECTOR_NUNITS (op))
26386 : return false;
26387 3639 : for (i = 0; i < nunits; i += 2)
26388 2924 : if (CONST_VECTOR_ELT (op, i) != CONST_VECTOR_ELT (op, i + 1))
26389 : return false;
26390 : return true;
26391 : }
26392 :
26393 : void
26394 8953 : ix86_expand_mul_widen_evenodd (rtx dest, rtx op1, rtx op2,
26395 : bool uns_p, bool odd_p)
26396 : {
26397 8953 : machine_mode mode = GET_MODE (op1);
26398 8953 : machine_mode wmode = GET_MODE (dest);
26399 8953 : rtx x;
26400 8953 : rtx orig_op1 = op1, orig_op2 = op2;
26401 :
26402 8953 : if (!nonimmediate_operand (op1, mode))
26403 0 : op1 = force_reg (mode, op1);
26404 8953 : if (!nonimmediate_operand (op2, mode))
26405 3354 : op2 = force_reg (mode, op2);
26406 :
26407 : /* We only play even/odd games with vectors of SImode. */
26408 8953 : gcc_assert (mode == V4SImode || mode == V8SImode || mode == V16SImode);
26409 :
26410 : /* If we're looking for the odd results, shift those members down to
26411 : the even slots. For some cpus this is faster than a PSHUFD. */
26412 8953 : if (odd_p)
26413 : {
26414 : /* For XOP use vpmacsdqh, but only for smult, as it is only
26415 : signed. */
26416 4439 : if (TARGET_XOP && mode == V4SImode && !uns_p)
26417 : {
26418 18 : x = force_reg (wmode, CONST0_RTX (wmode));
26419 18 : emit_insn (gen_xop_pmacsdqh (dest, op1, op2, x));
26420 18 : return;
26421 : }
26422 :
26423 8842 : x = GEN_INT (GET_MODE_UNIT_BITSIZE (mode));
26424 4421 : if (!const_vector_equal_evenodd_p (orig_op1))
26425 4421 : op1 = expand_binop (wmode, lshr_optab, gen_lowpart (wmode, op1),
26426 : x, NULL, 1, OPTAB_DIRECT);
26427 4421 : if (!const_vector_equal_evenodd_p (orig_op2))
26428 3706 : op2 = expand_binop (wmode, lshr_optab, gen_lowpart (wmode, op2),
26429 : x, NULL, 1, OPTAB_DIRECT);
26430 4421 : op1 = gen_lowpart (mode, op1);
26431 4421 : op2 = gen_lowpart (mode, op2);
26432 : }
26433 :
26434 8935 : if (mode == V16SImode)
26435 : {
26436 6 : if (uns_p)
26437 0 : x = gen_vec_widen_umult_even_v16si (dest, op1, op2);
26438 : else
26439 6 : x = gen_vec_widen_smult_even_v16si (dest, op1, op2);
26440 : }
26441 8929 : else if (mode == V8SImode)
26442 : {
26443 139 : if (uns_p)
26444 59 : x = gen_vec_widen_umult_even_v8si (dest, op1, op2);
26445 : else
26446 80 : x = gen_vec_widen_smult_even_v8si (dest, op1, op2);
26447 : }
26448 8790 : else if (uns_p)
26449 7689 : x = gen_vec_widen_umult_even_v4si (dest, op1, op2);
26450 1101 : else if (TARGET_SSE4_1)
26451 367 : x = gen_sse4_1_mulv2siv2di3 (dest, op1, op2);
26452 : else
26453 : {
26454 734 : rtx s1, s2, t0, t1, t2;
26455 :
26456 : /* The easiest way to implement this without PMULDQ is to go through
26457 : the motions as if we are performing a full 64-bit multiply. With
26458 : the exception that we need to do less shuffling of the elements. */
26459 :
26460 : /* Compute the sign-extension, aka highparts, of the two operands. */
26461 734 : s1 = ix86_expand_sse_cmp (gen_reg_rtx (mode), GT, CONST0_RTX (mode),
26462 : op1, pc_rtx, pc_rtx);
26463 734 : s2 = ix86_expand_sse_cmp (gen_reg_rtx (mode), GT, CONST0_RTX (mode),
26464 : op2, pc_rtx, pc_rtx);
26465 :
26466 : /* Multiply LO(A) * HI(B), and vice-versa. */
26467 734 : t1 = gen_reg_rtx (wmode);
26468 734 : t2 = gen_reg_rtx (wmode);
26469 734 : emit_insn (gen_vec_widen_umult_even_v4si (t1, s1, op2));
26470 734 : emit_insn (gen_vec_widen_umult_even_v4si (t2, s2, op1));
26471 :
26472 : /* Multiply LO(A) * LO(B). */
26473 734 : t0 = gen_reg_rtx (wmode);
26474 734 : emit_insn (gen_vec_widen_umult_even_v4si (t0, op1, op2));
26475 :
26476 : /* Combine and shift the highparts into place. */
26477 734 : t1 = expand_binop (wmode, add_optab, t1, t2, t1, 1, OPTAB_DIRECT);
26478 734 : t1 = expand_binop (wmode, ashl_optab, t1, GEN_INT (32), t1,
26479 : 1, OPTAB_DIRECT);
26480 :
26481 : /* Combine high and low parts. */
26482 734 : force_expand_binop (wmode, add_optab, t0, t1, dest, 1, OPTAB_DIRECT);
26483 734 : return;
26484 : }
26485 8201 : emit_insn (x);
26486 : }
26487 :
26488 : void
26489 977 : ix86_expand_mul_widen_hilo (rtx dest, rtx op1, rtx op2,
26490 : bool uns_p, bool high_p)
26491 : {
26492 977 : machine_mode wmode = GET_MODE (dest);
26493 977 : machine_mode mode = GET_MODE (op1);
26494 977 : rtx t1, t2, t3, t4, mask;
26495 :
26496 977 : switch (mode)
26497 : {
26498 297 : case E_V4SImode:
26499 297 : t1 = gen_reg_rtx (mode);
26500 297 : t2 = gen_reg_rtx (mode);
26501 297 : if (TARGET_XOP && !uns_p)
26502 : {
26503 : /* With XOP, we have pmacsdqh, aka mul_widen_odd. In this case,
26504 : shuffle the elements once so that all elements are in the right
26505 : place for immediate use: { A C B D }. */
26506 33 : emit_insn (gen_sse2_pshufd_1 (t1, op1, const0_rtx, const2_rtx,
26507 : const1_rtx, GEN_INT (3)));
26508 33 : emit_insn (gen_sse2_pshufd_1 (t2, op2, const0_rtx, const2_rtx,
26509 : const1_rtx, GEN_INT (3)));
26510 : }
26511 : else
26512 : {
26513 : /* Put the elements into place for the multiply. */
26514 264 : ix86_expand_vec_interleave (t1, op1, op1, high_p);
26515 264 : ix86_expand_vec_interleave (t2, op2, op2, high_p);
26516 264 : high_p = false;
26517 : }
26518 297 : ix86_expand_mul_widen_evenodd (dest, t1, t2, uns_p, high_p);
26519 297 : break;
26520 :
26521 70 : case E_V8SImode:
26522 : /* Shuffle the elements between the lanes. After this we
26523 : have { A B E F | C D G H } for each operand. */
26524 70 : t1 = gen_reg_rtx (V4DImode);
26525 70 : t2 = gen_reg_rtx (V4DImode);
26526 70 : emit_insn (gen_avx2_permv4di_1 (t1, gen_lowpart (V4DImode, op1),
26527 : const0_rtx, const2_rtx,
26528 : const1_rtx, GEN_INT (3)));
26529 70 : emit_insn (gen_avx2_permv4di_1 (t2, gen_lowpart (V4DImode, op2),
26530 : const0_rtx, const2_rtx,
26531 : const1_rtx, GEN_INT (3)));
26532 :
26533 : /* Shuffle the elements within the lanes. After this we
26534 : have { A A B B | C C D D } or { E E F F | G G H H }. */
26535 70 : t3 = gen_reg_rtx (V8SImode);
26536 70 : t4 = gen_reg_rtx (V8SImode);
26537 105 : mask = GEN_INT (high_p
26538 : ? 2 + (2 << 2) + (3 << 4) + (3 << 6)
26539 : : 0 + (0 << 2) + (1 << 4) + (1 << 6));
26540 70 : emit_insn (gen_avx2_pshufdv3 (t3, gen_lowpart (V8SImode, t1), mask));
26541 70 : emit_insn (gen_avx2_pshufdv3 (t4, gen_lowpart (V8SImode, t2), mask));
26542 :
26543 70 : ix86_expand_mul_widen_evenodd (dest, t3, t4, uns_p, false);
26544 70 : break;
26545 :
26546 394 : case E_V8HImode:
26547 394 : case E_V16HImode:
26548 394 : t1 = expand_binop (mode, smul_optab, op1, op2, NULL_RTX,
26549 : uns_p, OPTAB_DIRECT);
26550 626 : t2 = expand_binop (mode,
26551 : uns_p ? umul_highpart_optab : smul_highpart_optab,
26552 : op1, op2, NULL_RTX, uns_p, OPTAB_DIRECT);
26553 394 : gcc_assert (t1 && t2);
26554 :
26555 394 : t3 = gen_reg_rtx (mode);
26556 394 : ix86_expand_vec_interleave (t3, t1, t2, high_p);
26557 394 : emit_move_insn (dest, gen_lowpart (wmode, t3));
26558 394 : break;
26559 :
26560 216 : case E_V16QImode:
26561 216 : case E_V32QImode:
26562 216 : case E_V32HImode:
26563 216 : case E_V16SImode:
26564 216 : case E_V64QImode:
26565 216 : t1 = gen_reg_rtx (wmode);
26566 216 : t2 = gen_reg_rtx (wmode);
26567 216 : ix86_expand_sse_unpack (t1, op1, uns_p, high_p);
26568 216 : ix86_expand_sse_unpack (t2, op2, uns_p, high_p);
26569 :
26570 216 : emit_insn (gen_rtx_SET (dest, gen_rtx_MULT (wmode, t1, t2)));
26571 216 : break;
26572 :
26573 0 : default:
26574 0 : gcc_unreachable ();
26575 : }
26576 977 : }
26577 :
26578 : void
26579 3676 : ix86_expand_sse2_mulv4si3 (rtx op0, rtx op1, rtx op2)
26580 : {
26581 3676 : rtx res_1, res_2, res_3, res_4;
26582 :
26583 3676 : res_1 = gen_reg_rtx (V4SImode);
26584 3676 : res_2 = gen_reg_rtx (V4SImode);
26585 3676 : res_3 = gen_reg_rtx (V2DImode);
26586 3676 : res_4 = gen_reg_rtx (V2DImode);
26587 3676 : ix86_expand_mul_widen_evenodd (res_3, op1, op2, true, false);
26588 3676 : ix86_expand_mul_widen_evenodd (res_4, op1, op2, true, true);
26589 :
26590 : /* Move the results in element 2 down to element 1; we don't care
26591 : what goes in elements 2 and 3. Then we can merge the parts
26592 : back together with an interleave.
26593 :
26594 : Note that two other sequences were tried:
26595 : (1) Use interleaves at the start instead of psrldq, which allows
26596 : us to use a single shufps to merge things back at the end.
26597 : (2) Use shufps here to combine the two vectors, then pshufd to
26598 : put the elements in the correct order.
26599 : In both cases the cost of the reformatting stall was too high
26600 : and the overall sequence slower. */
26601 :
26602 3676 : emit_insn (gen_sse2_pshufd_1 (res_1, gen_lowpart (V4SImode, res_3),
26603 : const0_rtx, const2_rtx,
26604 : const0_rtx, const0_rtx));
26605 3676 : emit_insn (gen_sse2_pshufd_1 (res_2, gen_lowpart (V4SImode, res_4),
26606 : const0_rtx, const2_rtx,
26607 : const0_rtx, const0_rtx));
26608 3676 : res_1 = emit_insn (gen_vec_interleave_lowv4si (op0, res_1, res_2));
26609 :
26610 3676 : set_unique_reg_note (res_1, REG_EQUAL, gen_rtx_MULT (V4SImode, op1, op2));
26611 3676 : }
26612 :
26613 : void
26614 540 : ix86_expand_sse2_mulvxdi3 (rtx op0, rtx op1, rtx op2)
26615 : {
26616 540 : machine_mode mode = GET_MODE (op0);
26617 540 : rtx t1, t2, t3, t4, t5, t6;
26618 :
26619 540 : if (TARGET_AVX512DQ && mode == V8DImode)
26620 32 : emit_insn (gen_avx512dq_mulv8di3 (op0, op1, op2));
26621 508 : else if (TARGET_AVX512DQ && TARGET_AVX512VL && mode == V4DImode)
26622 32 : emit_insn (gen_avx512dq_mulv4di3 (op0, op1, op2));
26623 476 : else if (TARGET_AVX512DQ && TARGET_AVX512VL && mode == V2DImode)
26624 36 : emit_insn (gen_avx512dq_mulv2di3 (op0, op1, op2));
26625 440 : else if (TARGET_XOP && mode == V2DImode)
26626 : {
26627 : /* op1: A,B,C,D, op2: E,F,G,H */
26628 2 : op1 = gen_lowpart (V4SImode, op1);
26629 2 : op2 = gen_lowpart (V4SImode, op2);
26630 :
26631 2 : t1 = gen_reg_rtx (V4SImode);
26632 2 : t2 = gen_reg_rtx (V4SImode);
26633 2 : t3 = gen_reg_rtx (V2DImode);
26634 2 : t4 = gen_reg_rtx (V2DImode);
26635 :
26636 : /* t1: B,A,D,C */
26637 2 : emit_insn (gen_sse2_pshufd_1 (t1, op1,
26638 : GEN_INT (1),
26639 : GEN_INT (0),
26640 : GEN_INT (3),
26641 : GEN_INT (2)));
26642 :
26643 : /* t2: (B*E),(A*F),(D*G),(C*H) */
26644 2 : emit_insn (gen_mulv4si3 (t2, t1, op2));
26645 :
26646 : /* t3: (B*E)+(A*F), (D*G)+(C*H) */
26647 2 : emit_insn (gen_xop_phadddq (t3, t2));
26648 :
26649 : /* t4: ((B*E)+(A*F))<<32, ((D*G)+(C*H))<<32 */
26650 2 : emit_insn (gen_ashlv2di3 (t4, t3, GEN_INT (32)));
26651 :
26652 : /* Multiply lower parts and add all */
26653 2 : t5 = gen_reg_rtx (V2DImode);
26654 2 : emit_insn (gen_vec_widen_umult_even_v4si (t5,
26655 2 : gen_lowpart (V4SImode, op1),
26656 2 : gen_lowpart (V4SImode, op2)));
26657 2 : force_expand_binop (mode, add_optab, t5, t4, op0, 1, OPTAB_DIRECT);
26658 : }
26659 : else
26660 : {
26661 438 : machine_mode nmode;
26662 438 : rtx (*umul) (rtx, rtx, rtx);
26663 :
26664 438 : if (mode == V2DImode)
26665 : {
26666 : umul = gen_vec_widen_umult_even_v4si;
26667 : nmode = V4SImode;
26668 : }
26669 295 : else if (mode == V4DImode)
26670 : {
26671 : umul = gen_vec_widen_umult_even_v8si;
26672 : nmode = V8SImode;
26673 : }
26674 116 : else if (mode == V8DImode)
26675 : {
26676 : umul = gen_vec_widen_umult_even_v16si;
26677 : nmode = V16SImode;
26678 : }
26679 : else
26680 0 : gcc_unreachable ();
26681 :
26682 :
26683 : /* Multiply low parts. */
26684 438 : t1 = gen_reg_rtx (mode);
26685 438 : emit_insn (umul (t1, gen_lowpart (nmode, op1), gen_lowpart (nmode, op2)));
26686 :
26687 : /* Shift input vectors right 32 bits so we can multiply high parts. */
26688 438 : t6 = GEN_INT (32);
26689 438 : t2 = expand_binop (mode, lshr_optab, op1, t6, NULL, 1, OPTAB_DIRECT);
26690 438 : t3 = expand_binop (mode, lshr_optab, op2, t6, NULL, 1, OPTAB_DIRECT);
26691 :
26692 : /* Multiply high parts by low parts. */
26693 438 : t4 = gen_reg_rtx (mode);
26694 438 : t5 = gen_reg_rtx (mode);
26695 438 : emit_insn (umul (t4, gen_lowpart (nmode, t2), gen_lowpart (nmode, op2)));
26696 438 : emit_insn (umul (t5, gen_lowpart (nmode, t3), gen_lowpart (nmode, op1)));
26697 :
26698 : /* Combine and shift the highparts back. */
26699 438 : t4 = expand_binop (mode, add_optab, t4, t5, t4, 1, OPTAB_DIRECT);
26700 438 : t4 = expand_binop (mode, ashl_optab, t4, t6, t4, 1, OPTAB_DIRECT);
26701 :
26702 : /* Combine high and low parts. */
26703 438 : force_expand_binop (mode, add_optab, t1, t4, op0, 1, OPTAB_DIRECT);
26704 : }
26705 :
26706 540 : set_unique_reg_note (get_last_insn (), REG_EQUAL,
26707 : gen_rtx_MULT (mode, op1, op2));
26708 540 : }
26709 :
26710 : /* Return 1 if control transfer instruction INSN
26711 : should be encoded with notrack prefix. */
26712 :
26713 : bool
26714 15110200 : ix86_notrack_prefixed_insn_p (rtx_insn *insn)
26715 : {
26716 15110200 : if (!insn || !((flag_cf_protection & CF_BRANCH)))
26717 : return false;
26718 :
26719 4090399 : if (CALL_P (insn))
26720 : {
26721 1474511 : rtx call = get_call_rtx_from (insn);
26722 1474511 : gcc_assert (call != NULL_RTX);
26723 1474511 : rtx addr = XEXP (call, 0);
26724 :
26725 : /* Do not emit 'notrack' if it's not an indirect call. */
26726 1474511 : if (MEM_P (addr)
26727 1474511 : && SYMBOL_REF_P (XEXP (addr, 0)))
26728 : return false;
26729 : else
26730 67035 : return find_reg_note (insn, REG_CALL_NOCF_CHECK, 0);
26731 : }
26732 :
26733 2615888 : if (JUMP_P (insn) && !flag_cet_switch)
26734 : {
26735 2602276 : rtx target = JUMP_LABEL (insn);
26736 2602276 : if (target == NULL_RTX || ANY_RETURN_P (target))
26737 : return false;
26738 :
26739 : /* Check the jump is a switch table. */
26740 2602238 : rtx_insn *label = as_a<rtx_insn *> (target);
26741 2602238 : rtx_insn *table = next_insn (label);
26742 2602238 : if (table == NULL_RTX || !JUMP_TABLE_DATA_P (table))
26743 : return false;
26744 : else
26745 : return true;
26746 : }
26747 : return false;
26748 : }
26749 :
26750 : /* Calculate integer abs() using only SSE2 instructions. */
26751 :
26752 : void
26753 625 : ix86_expand_sse2_abs (rtx target, rtx input)
26754 : {
26755 625 : machine_mode mode = GET_MODE (target);
26756 625 : rtx tmp0, tmp1, x;
26757 :
26758 625 : switch (mode)
26759 : {
26760 48 : case E_V2DImode:
26761 48 : case E_V4DImode:
26762 : /* For 64-bit signed integer X, with SSE4.2 use
26763 : pxor t0, t0; pcmpgtq X, t0; pxor t0, X; psubq t0, X.
26764 : Otherwise handle it similarly to V4SImode, except use 64 as W instead of
26765 : 32 and use logical instead of arithmetic right shift (which is
26766 : unimplemented) and subtract. */
26767 48 : if (TARGET_SSE4_2)
26768 : {
26769 9 : tmp0 = gen_reg_rtx (mode);
26770 9 : tmp1 = gen_reg_rtx (mode);
26771 9 : emit_move_insn (tmp1, CONST0_RTX (mode));
26772 9 : if (mode == E_V2DImode)
26773 6 : emit_insn (gen_sse4_2_gtv2di3 (tmp0, tmp1, input));
26774 : else
26775 3 : emit_insn (gen_avx2_gtv4di3 (tmp0, tmp1, input));
26776 : }
26777 : else
26778 : {
26779 78 : tmp0 = expand_simple_binop (mode, LSHIFTRT, input,
26780 39 : GEN_INT (GET_MODE_UNIT_BITSIZE (mode)
26781 : - 1), NULL, 0, OPTAB_DIRECT);
26782 39 : tmp0 = expand_simple_unop (mode, NEG, tmp0, NULL, false);
26783 : }
26784 :
26785 48 : tmp1 = expand_simple_binop (mode, XOR, tmp0, input,
26786 : NULL, 0, OPTAB_DIRECT);
26787 48 : x = expand_simple_binop (mode, MINUS, tmp1, tmp0,
26788 : target, 0, OPTAB_DIRECT);
26789 48 : break;
26790 :
26791 76 : case E_V4SImode:
26792 : /* For 32-bit signed integer X, the best way to calculate the absolute
26793 : value of X is (((signed) X >> (W-1)) ^ X) - ((signed) X >> (W-1)). */
26794 76 : tmp0 = expand_simple_binop (mode, ASHIFTRT, input,
26795 76 : GEN_INT (GET_MODE_UNIT_BITSIZE (mode) - 1),
26796 : NULL, 0, OPTAB_DIRECT);
26797 76 : tmp1 = expand_simple_binop (mode, XOR, tmp0, input,
26798 : NULL, 0, OPTAB_DIRECT);
26799 76 : x = expand_simple_binop (mode, MINUS, tmp1, tmp0,
26800 : target, 0, OPTAB_DIRECT);
26801 76 : break;
26802 :
26803 97 : case E_V8HImode:
26804 : /* For 16-bit signed integer X, the best way to calculate the absolute
26805 : value of X is max (X, -X), as SSE2 provides the PMAXSW insn. */
26806 97 : tmp0 = expand_unop (mode, neg_optab, input, NULL_RTX, 0);
26807 :
26808 97 : x = expand_simple_binop (mode, SMAX, tmp0, input,
26809 : target, 0, OPTAB_DIRECT);
26810 97 : break;
26811 :
26812 404 : case E_V16QImode:
26813 : /* For 8-bit signed integer X, the best way to calculate the absolute
26814 : value of X is min ((unsigned char) X, (unsigned char) (-X)),
26815 : as SSE2 provides the PMINUB insn. */
26816 404 : tmp0 = expand_unop (mode, neg_optab, input, NULL_RTX, 0);
26817 :
26818 404 : x = expand_simple_binop (V16QImode, UMIN, tmp0, input,
26819 : target, 0, OPTAB_DIRECT);
26820 404 : break;
26821 :
26822 0 : default:
26823 0 : gcc_unreachable ();
26824 : }
26825 :
26826 625 : if (x != target)
26827 0 : emit_move_insn (target, x);
26828 625 : }
26829 :
26830 : /* Expand an extract from a vector register through pextr insn.
26831 : Return true if successful. */
26832 :
26833 : bool
26834 119378 : ix86_expand_pextr (rtx *operands)
26835 : {
26836 119378 : rtx dst = operands[0];
26837 119378 : rtx src = operands[1];
26838 :
26839 119378 : unsigned int size = INTVAL (operands[2]);
26840 119378 : unsigned int pos = INTVAL (operands[3]);
26841 :
26842 119378 : if (SUBREG_P (dst))
26843 : {
26844 : /* Reject non-lowpart subregs. */
26845 76150 : if (SUBREG_BYTE (dst) > 0)
26846 : return false;
26847 76021 : dst = SUBREG_REG (dst);
26848 : }
26849 :
26850 119249 : if (SUBREG_P (src))
26851 : {
26852 34025 : pos += SUBREG_BYTE (src) * BITS_PER_UNIT;
26853 34025 : src = SUBREG_REG (src);
26854 : }
26855 :
26856 119249 : switch (GET_MODE (src))
26857 : {
26858 0 : case E_V16QImode:
26859 0 : case E_V8HImode:
26860 0 : case E_V4SImode:
26861 0 : case E_V2DImode:
26862 0 : case E_V1TImode:
26863 0 : {
26864 0 : machine_mode srcmode, dstmode;
26865 0 : rtx d, pat;
26866 :
26867 0 : if (!int_mode_for_size (size, 0).exists (&dstmode))
26868 0 : return false;
26869 :
26870 0 : switch (dstmode)
26871 : {
26872 0 : case E_QImode:
26873 0 : if (!TARGET_SSE4_1)
26874 : return false;
26875 : srcmode = V16QImode;
26876 : break;
26877 :
26878 0 : case E_HImode:
26879 0 : if (!TARGET_SSE2)
26880 : return false;
26881 : srcmode = V8HImode;
26882 : break;
26883 :
26884 0 : case E_SImode:
26885 0 : if (!TARGET_SSE4_1)
26886 : return false;
26887 : srcmode = V4SImode;
26888 : break;
26889 :
26890 0 : case E_DImode:
26891 0 : gcc_assert (TARGET_64BIT);
26892 0 : if (!TARGET_SSE4_1)
26893 : return false;
26894 : srcmode = V2DImode;
26895 : break;
26896 :
26897 : default:
26898 : return false;
26899 : }
26900 :
26901 : /* Reject extractions from misaligned positions. */
26902 0 : if (pos & (size-1))
26903 : return false;
26904 :
26905 0 : if (GET_MODE (dst) == dstmode)
26906 : d = dst;
26907 : else
26908 0 : d = gen_reg_rtx (dstmode);
26909 :
26910 : /* Construct insn pattern. */
26911 0 : pat = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (1, GEN_INT (pos / size)));
26912 0 : pat = gen_rtx_VEC_SELECT (dstmode, gen_lowpart (srcmode, src), pat);
26913 :
26914 : /* Let the rtl optimizers know about the zero extension performed. */
26915 0 : if (dstmode == QImode || dstmode == HImode)
26916 : {
26917 0 : pat = gen_rtx_ZERO_EXTEND (SImode, pat);
26918 0 : d = gen_lowpart (SImode, d);
26919 : }
26920 :
26921 0 : emit_insn (gen_rtx_SET (d, pat));
26922 :
26923 0 : if (d != dst)
26924 0 : emit_move_insn (dst, gen_lowpart (GET_MODE (dst), d));
26925 : return true;
26926 : }
26927 :
26928 : default:
26929 : return false;
26930 : }
26931 : }
26932 :
26933 : /* Expand an insert into a vector register through pinsr insn.
26934 : Return true if successful. */
26935 :
26936 : bool
26937 112545 : ix86_expand_pinsr (rtx *operands)
26938 : {
26939 112545 : rtx dst = operands[0];
26940 112545 : rtx src = operands[3];
26941 :
26942 112545 : unsigned int size = INTVAL (operands[1]);
26943 112545 : unsigned int pos = INTVAL (operands[2]);
26944 :
26945 112545 : if (SUBREG_P (dst))
26946 : {
26947 63957 : pos += SUBREG_BYTE (dst) * BITS_PER_UNIT;
26948 63957 : dst = SUBREG_REG (dst);
26949 : }
26950 :
26951 112545 : switch (GET_MODE (dst))
26952 : {
26953 20 : case E_V16QImode:
26954 20 : case E_V8HImode:
26955 20 : case E_V4SImode:
26956 20 : case E_V2DImode:
26957 20 : case E_V1TImode:
26958 20 : {
26959 20 : machine_mode srcmode, dstmode;
26960 20 : rtx (*pinsr)(rtx, rtx, rtx, rtx);
26961 20 : rtx d;
26962 :
26963 20 : if (!int_mode_for_size (size, 0).exists (&srcmode))
26964 0 : return false;
26965 :
26966 20 : switch (srcmode)
26967 : {
26968 1 : case E_QImode:
26969 1 : if (!TARGET_SSE4_1)
26970 : return false;
26971 : dstmode = V16QImode;
26972 : pinsr = gen_sse4_1_pinsrb;
26973 : break;
26974 :
26975 5 : case E_HImode:
26976 5 : if (!TARGET_SSE2)
26977 : return false;
26978 : dstmode = V8HImode;
26979 : pinsr = gen_sse2_pinsrw;
26980 : break;
26981 :
26982 14 : case E_SImode:
26983 14 : if (!TARGET_SSE4_1)
26984 : return false;
26985 : dstmode = V4SImode;
26986 : pinsr = gen_sse4_1_pinsrd;
26987 : break;
26988 :
26989 0 : case E_DImode:
26990 0 : gcc_assert (TARGET_64BIT);
26991 0 : if (!TARGET_SSE4_1)
26992 : return false;
26993 : dstmode = V2DImode;
26994 : pinsr = gen_sse4_1_pinsrq;
26995 : break;
26996 :
26997 : default:
26998 : return false;
26999 : }
27000 :
27001 : /* Reject insertions to misaligned positions. */
27002 7 : if (pos & (size-1))
27003 : return false;
27004 :
27005 7 : if (SUBREG_P (src))
27006 : {
27007 7 : unsigned int srcpos = SUBREG_BYTE (src);
27008 :
27009 7 : if (srcpos > 0)
27010 : {
27011 0 : rtx extr_ops[4];
27012 :
27013 0 : extr_ops[0] = gen_reg_rtx (srcmode);
27014 0 : extr_ops[1] = gen_lowpart (srcmode, SUBREG_REG (src));
27015 0 : extr_ops[2] = GEN_INT (size);
27016 0 : extr_ops[3] = GEN_INT (srcpos * BITS_PER_UNIT);
27017 :
27018 0 : if (!ix86_expand_pextr (extr_ops))
27019 0 : return false;
27020 :
27021 0 : src = extr_ops[0];
27022 : }
27023 : else
27024 7 : src = gen_lowpart (srcmode, SUBREG_REG (src));
27025 : }
27026 :
27027 7 : if (GET_MODE (dst) == dstmode)
27028 : d = dst;
27029 : else
27030 7 : d = gen_reg_rtx (dstmode);
27031 :
27032 7 : emit_insn (pinsr (d, gen_lowpart (dstmode, dst),
27033 7 : gen_lowpart (srcmode, src),
27034 7 : GEN_INT (1 << (pos / size))));
27035 7 : if (d != dst)
27036 7 : emit_move_insn (dst, gen_lowpart (GET_MODE (dst), d));
27037 : return true;
27038 : }
27039 :
27040 : default:
27041 : return false;
27042 : }
27043 : }
27044 :
27045 : /* All CPUs prefer to avoid cross-lane operations so perform reductions
27046 : upper against lower halves up to SSE reg size. */
27047 :
27048 : machine_mode
27049 1997 : ix86_split_reduction (machine_mode mode)
27050 : {
27051 : /* Reduce lowpart against highpart until we reach SSE reg width to
27052 : avoid cross-lane operations. */
27053 1997 : switch (mode)
27054 : {
27055 : case E_V8DImode:
27056 : case E_V4DImode:
27057 : return V2DImode;
27058 9 : case E_V16SImode:
27059 9 : case E_V8SImode:
27060 9 : return V4SImode;
27061 8 : case E_V32HImode:
27062 8 : case E_V16HImode:
27063 8 : return V8HImode;
27064 4 : case E_V64QImode:
27065 4 : case E_V32QImode:
27066 4 : return V16QImode;
27067 5 : case E_V16SFmode:
27068 5 : case E_V8SFmode:
27069 5 : return V4SFmode;
27070 16 : case E_V8DFmode:
27071 16 : case E_V4DFmode:
27072 16 : return V2DFmode;
27073 1950 : default:
27074 1950 : return mode;
27075 : }
27076 : }
27077 :
27078 : /* Generate call to __divmoddi4. */
27079 :
27080 : void
27081 896 : ix86_expand_divmod_libfunc (rtx libfunc, machine_mode mode,
27082 : rtx op0, rtx op1,
27083 : rtx *quot_p, rtx *rem_p)
27084 : {
27085 1792 : rtx rem = assign_stack_temp (mode, GET_MODE_SIZE (mode));
27086 :
27087 896 : rtx quot = emit_library_call_value (libfunc, NULL_RTX, LCT_NORMAL,
27088 : mode, op0, mode, op1, mode,
27089 896 : XEXP (rem, 0), Pmode);
27090 896 : *quot_p = quot;
27091 896 : *rem_p = rem;
27092 896 : }
27093 :
27094 : void
27095 64 : ix86_expand_atomic_fetch_op_loop (rtx target, rtx mem, rtx val,
27096 : enum rtx_code code, bool after,
27097 : bool doubleword)
27098 : {
27099 64 : rtx old_reg, new_reg, old_mem, success;
27100 64 : machine_mode mode = GET_MODE (target);
27101 64 : rtx_code_label *loop_label = NULL;
27102 :
27103 64 : old_reg = gen_reg_rtx (mode);
27104 64 : new_reg = old_reg;
27105 64 : old_mem = copy_to_reg (mem);
27106 64 : loop_label = gen_label_rtx ();
27107 64 : emit_label (loop_label);
27108 64 : emit_move_insn (old_reg, old_mem);
27109 :
27110 : /* return value for atomic_fetch_op. */
27111 64 : if (!after)
27112 32 : emit_move_insn (target, old_reg);
27113 :
27114 64 : if (code == NOT)
27115 : {
27116 16 : new_reg = expand_simple_binop (mode, AND, new_reg, val, NULL_RTX,
27117 : true, OPTAB_LIB_WIDEN);
27118 16 : new_reg = expand_simple_unop (mode, code, new_reg, NULL_RTX, true);
27119 : }
27120 : else
27121 48 : new_reg = expand_simple_binop (mode, code, new_reg, val, NULL_RTX,
27122 : true, OPTAB_LIB_WIDEN);
27123 :
27124 : /* return value for atomic_op_fetch. */
27125 64 : if (after)
27126 32 : emit_move_insn (target, new_reg);
27127 :
27128 64 : success = NULL_RTX;
27129 :
27130 64 : ix86_expand_cmpxchg_loop (&success, old_mem, mem, old_reg, new_reg,
27131 : gen_int_mode (MEMMODEL_SYNC_SEQ_CST,
27132 : SImode),
27133 : doubleword, loop_label);
27134 64 : }
27135 :
27136 : /* Relax cmpxchg instruction, param loop_label indicates whether
27137 : the instruction should be relaxed with a pause loop. If not,
27138 : it will be relaxed to an atomic load + compare, and skip
27139 : cmpxchg instruction if mem != exp_input. */
27140 :
27141 : void
27142 72 : ix86_expand_cmpxchg_loop (rtx *ptarget_bool, rtx target_val,
27143 : rtx mem, rtx exp_input, rtx new_input,
27144 : rtx mem_model, bool doubleword,
27145 : rtx_code_label *loop_label)
27146 : {
27147 72 : rtx_code_label *cmp_label = NULL;
27148 72 : rtx_code_label *done_label = NULL;
27149 72 : rtx target_bool = NULL_RTX, new_mem = NULL_RTX;
27150 72 : rtx (*gen) (rtx, rtx, rtx, rtx, rtx) = NULL;
27151 72 : rtx (*gendw) (rtx, rtx, rtx, rtx, rtx, rtx) = NULL;
27152 72 : machine_mode mode = GET_MODE (target_val), hmode = mode;
27153 :
27154 72 : if (*ptarget_bool == NULL)
27155 64 : target_bool = gen_reg_rtx (QImode);
27156 : else
27157 : target_bool = *ptarget_bool;
27158 :
27159 72 : cmp_label = gen_label_rtx ();
27160 72 : done_label = gen_label_rtx ();
27161 :
27162 72 : new_mem = gen_reg_rtx (mode);
27163 : /* Load memory first. */
27164 72 : expand_atomic_load (new_mem, mem, MEMMODEL_SEQ_CST);
27165 :
27166 72 : switch (mode)
27167 : {
27168 : case E_TImode:
27169 : gendw = gen_atomic_compare_and_swapti_doubleword;
27170 : hmode = DImode;
27171 : break;
27172 18 : case E_DImode:
27173 18 : if (doubleword)
27174 : {
27175 : gendw = gen_atomic_compare_and_swapdi_doubleword;
27176 : hmode = SImode;
27177 : }
27178 : else
27179 : gen = gen_atomic_compare_and_swapdi_1;
27180 : break;
27181 18 : case E_SImode:
27182 18 : gen = gen_atomic_compare_and_swapsi_1;
27183 18 : break;
27184 18 : case E_HImode:
27185 18 : gen = gen_atomic_compare_and_swaphi_1;
27186 18 : break;
27187 18 : case E_QImode:
27188 18 : gen = gen_atomic_compare_and_swapqi_1;
27189 18 : break;
27190 0 : default:
27191 0 : gcc_unreachable ();
27192 : }
27193 :
27194 : /* Compare mem value with expected value. */
27195 54 : if (doubleword)
27196 : {
27197 0 : rtx low_new_mem = gen_lowpart (hmode, new_mem);
27198 0 : rtx low_exp_input = gen_lowpart (hmode, exp_input);
27199 0 : rtx high_new_mem = gen_highpart (hmode, new_mem);
27200 0 : rtx high_exp_input = gen_highpart (hmode, exp_input);
27201 0 : emit_cmp_and_jump_insns (low_new_mem, low_exp_input, NE, NULL_RTX,
27202 : hmode, 1, cmp_label,
27203 : profile_probability::guessed_never ());
27204 0 : emit_cmp_and_jump_insns (high_new_mem, high_exp_input, NE, NULL_RTX,
27205 : hmode, 1, cmp_label,
27206 : profile_probability::guessed_never ());
27207 : }
27208 : else
27209 72 : emit_cmp_and_jump_insns (new_mem, exp_input, NE, NULL_RTX,
27210 72 : GET_MODE (exp_input), 1, cmp_label,
27211 : profile_probability::guessed_never ());
27212 :
27213 : /* Directly emits cmpxchg here. */
27214 72 : if (doubleword)
27215 0 : emit_insn (gendw (target_val, mem, exp_input,
27216 0 : gen_lowpart (hmode, new_input),
27217 : gen_highpart (hmode, new_input),
27218 : mem_model));
27219 : else
27220 72 : emit_insn (gen (target_val, mem, exp_input, new_input, mem_model));
27221 :
27222 72 : if (!loop_label)
27223 : {
27224 8 : emit_jump_insn (gen_jump (done_label));
27225 8 : emit_barrier ();
27226 8 : emit_label (cmp_label);
27227 8 : emit_move_insn (target_val, new_mem);
27228 8 : emit_label (done_label);
27229 8 : ix86_expand_setcc (target_bool, EQ, gen_rtx_REG (CCZmode, FLAGS_REG),
27230 : const0_rtx);
27231 : }
27232 : else
27233 : {
27234 64 : ix86_expand_setcc (target_bool, EQ, gen_rtx_REG (CCZmode, FLAGS_REG),
27235 : const0_rtx);
27236 64 : emit_cmp_and_jump_insns (target_bool, const0_rtx, EQ, const0_rtx,
27237 64 : GET_MODE (target_bool), 1, loop_label,
27238 : profile_probability::guessed_never ());
27239 64 : emit_jump_insn (gen_jump (done_label));
27240 64 : emit_barrier ();
27241 :
27242 : /* If mem is not expected, pause and loop back. */
27243 64 : emit_label (cmp_label);
27244 64 : emit_move_insn (target_val, new_mem);
27245 64 : emit_insn (gen_pause ());
27246 64 : emit_jump_insn (gen_jump (loop_label));
27247 64 : emit_barrier ();
27248 64 : emit_label (done_label);
27249 : }
27250 :
27251 72 : *ptarget_bool = target_bool;
27252 72 : }
27253 :
27254 : /* Convert a BFmode VAL to SFmode without signaling sNaNs.
27255 : This is done by returning SF SUBREG of ((HI SUBREG) (VAL)) << 16. */
27256 :
27257 : rtx
27258 2978 : ix86_expand_fast_convert_bf_to_sf (rtx val)
27259 : {
27260 2978 : rtx op = gen_lowpart (HImode, val), ret;
27261 2978 : if (CONST_INT_P (op))
27262 : {
27263 587 : ret = simplify_const_unary_operation (FLOAT_EXTEND, SFmode,
27264 : val, BFmode);
27265 587 : if (ret)
27266 : return ret;
27267 : /* FLOAT_EXTEND simplification will fail if VAL is a sNaN. */
27268 1 : ret = gen_reg_rtx (SImode);
27269 1 : emit_move_insn (ret, GEN_INT (INTVAL (op) & 0xffff));
27270 1 : emit_insn (gen_ashlsi3 (ret, ret, GEN_INT (16)));
27271 1 : return gen_lowpart (SFmode, ret);
27272 : }
27273 :
27274 2391 : ret = gen_reg_rtx (SFmode);
27275 2391 : emit_insn (gen_extendbfsf2_1 (ret, force_reg (BFmode, val)));
27276 2391 : return ret;
27277 : }
27278 :
27279 : rtx
27280 65578 : ix86_gen_ccmp_first (rtx_insn **prep_seq, rtx_insn **gen_seq,
27281 : rtx_code code, tree treeop0, tree treeop1)
27282 : {
27283 65578 : if (!TARGET_APX_CCMP)
27284 : return NULL_RTX;
27285 :
27286 65578 : rtx op0, op1, res;
27287 65578 : machine_mode op_mode;
27288 :
27289 65578 : start_sequence ();
27290 65578 : expand_operands (treeop0, treeop1, NULL_RTX, &op0, &op1, EXPAND_NORMAL);
27291 :
27292 65578 : op_mode = GET_MODE (op0);
27293 65578 : if (op_mode == VOIDmode)
27294 0 : op_mode = GET_MODE (op1);
27295 :
27296 : /* We only supports following scalar comparisons that use just 1
27297 : instruction: DI/SI/HI/QI/XF/DF/SF/HF.
27298 : Unordered/Ordered compare cannot be correctly identified by
27299 : ccmp so they are not supported. */
27300 32771 : if (!(op_mode == DImode || op_mode == SImode
27301 65578 : || op_mode == HImode || op_mode == QImode
27302 32778 : || ((op_mode == XFmode || op_mode == DFmode || op_mode == SFmode)
27303 8 : && (TARGET_80387
27304 1 : || (SSE_FLOAT_MODE_P (op_mode) && TARGET_SSE_MATH)))
27305 0 : || (op_mode == HFmode && TARGET_AVX512FP16))
27306 32807 : || code == ORDERED
27307 32807 : || code == UNORDERED)
27308 : {
27309 32771 : end_sequence ();
27310 32771 : return NULL_RTX;
27311 : }
27312 :
27313 : /* Canonicalize the operands according to mode. */
27314 32807 : if (SCALAR_INT_MODE_P (op_mode))
27315 : {
27316 32800 : if (!nonimmediate_operand (op0, op_mode))
27317 0 : op0 = force_reg (op_mode, op0);
27318 32800 : if (!x86_64_general_operand (op1, op_mode))
27319 0 : op1 = force_reg (op_mode, op1);
27320 : }
27321 : else
27322 : {
27323 : /* op0/op1 can be canonicallized from expand_fp_compare, so
27324 : just adjust the code to make it generate supported fp
27325 : condition. */
27326 7 : if (ix86_fp_compare_code_to_integer (code) == UNKNOWN)
27327 : {
27328 : /* First try to split condition if we don't need to honor
27329 : NaNs, as the ORDERED/UNORDERED check always fall
27330 : through. */
27331 6 : if (!HONOR_NANS (op_mode))
27332 : {
27333 6 : rtx_code first_code;
27334 6 : split_comparison (code, op_mode, &first_code, &code);
27335 : }
27336 : /* Otherwise try to swap the operand order and check if
27337 : the comparison is supported. */
27338 : else
27339 : {
27340 0 : code = swap_condition (code);
27341 0 : std::swap (op0, op1);
27342 : }
27343 :
27344 6 : if (ix86_fp_compare_code_to_integer (code) == UNKNOWN)
27345 : {
27346 0 : end_sequence ();
27347 0 : return NULL_RTX;
27348 : }
27349 : }
27350 : }
27351 :
27352 32807 : *prep_seq = end_sequence ();
27353 :
27354 32807 : start_sequence ();
27355 :
27356 32807 : res = ix86_expand_compare (code, op0, op1);
27357 :
27358 32807 : if (!res)
27359 : {
27360 : end_sequence ();
27361 : return NULL_RTX;
27362 : }
27363 32807 : *gen_seq = end_sequence ();
27364 :
27365 32807 : return res;
27366 : }
27367 :
27368 : rtx
27369 32810 : ix86_gen_ccmp_next (rtx_insn **prep_seq, rtx_insn **gen_seq, rtx prev,
27370 : rtx_code cmp_code, tree treeop0, tree treeop1,
27371 : rtx_code bit_code)
27372 : {
27373 32810 : if (!TARGET_APX_CCMP)
27374 : return NULL_RTX;
27375 :
27376 32810 : rtx op0, op1, target;
27377 32810 : machine_mode op_mode, cmp_mode, cc_mode = CCmode;
27378 32810 : int unsignedp = TYPE_UNSIGNED (TREE_TYPE (treeop0));
27379 32810 : insn_code icode;
27380 32810 : rtx_code prev_code;
27381 32810 : struct expand_operand ops[5];
27382 32810 : int dfv;
27383 :
27384 : /* Exit early for non integer modes to avoid O(n^2) part of expand_operands. */
27385 32810 : cmp_mode = op_mode = TYPE_MODE (TREE_TYPE (treeop0));
27386 :
27387 32810 : if (!(op_mode == DImode || op_mode == SImode || op_mode == HImode
27388 : || op_mode == QImode))
27389 : return NULL_RTX;
27390 :
27391 32 : push_to_sequence (*prep_seq);
27392 32 : expand_operands (treeop0, treeop1, NULL_RTX, &op0, &op1, EXPAND_NORMAL);
27393 :
27394 32 : icode = code_for_ccmp (op_mode);
27395 :
27396 32 : op0 = prepare_operand (icode, op0, 2, op_mode, cmp_mode, unsignedp);
27397 32 : op1 = prepare_operand (icode, op1, 3, op_mode, cmp_mode, unsignedp);
27398 32 : if (!op0 || !op1)
27399 : {
27400 0 : end_sequence ();
27401 0 : return NULL_RTX;
27402 : }
27403 :
27404 32 : *prep_seq = end_sequence ();
27405 :
27406 32 : target = gen_rtx_REG (cc_mode, FLAGS_REG);
27407 32 : dfv = ix86_get_flags_cc ((rtx_code) cmp_code);
27408 :
27409 32 : prev_code = GET_CODE (prev);
27410 : /* Fixup FP compare code here. */
27411 32 : if (GET_MODE (XEXP (prev, 0)) == CCFPmode)
27412 7 : prev_code = ix86_fp_compare_code_to_integer (prev_code);
27413 :
27414 32 : if (bit_code != AND)
27415 17 : prev_code = reverse_condition (prev_code);
27416 : else
27417 15 : dfv = (int)(dfv ^ 1);
27418 :
27419 32 : prev = gen_rtx_fmt_ee (prev_code, VOIDmode, XEXP (prev, 0),
27420 : const0_rtx);
27421 :
27422 32 : create_fixed_operand (&ops[0], target);
27423 32 : create_fixed_operand (&ops[1], prev);
27424 32 : create_fixed_operand (&ops[2], op0);
27425 32 : create_fixed_operand (&ops[3], op1);
27426 32 : create_fixed_operand (&ops[4], GEN_INT (dfv));
27427 :
27428 32 : push_to_sequence (*gen_seq);
27429 32 : if (!maybe_expand_insn (icode, 5, ops))
27430 : {
27431 0 : end_sequence ();
27432 0 : return NULL_RTX;
27433 : }
27434 :
27435 32 : *gen_seq = end_sequence ();
27436 :
27437 32 : return gen_rtx_fmt_ee ((rtx_code) cmp_code, VOIDmode, target, const0_rtx);
27438 : }
27439 :
27440 : /* Attempt to convert a CONST_VECTOR into a bcst_mem_operand.
27441 : Returns NULL_RTX if X is cannot be expressed as a suitable
27442 : VEC_DUPLICATE in mode MODE. */
27443 :
27444 : static rtx
27445 48 : ix86_gen_bcst_mem (machine_mode mode, rtx x)
27446 : {
27447 48 : if (!TARGET_AVX512F
27448 48 : || !CONST_VECTOR_P (x)
27449 64 : || (!TARGET_AVX512VL && GET_MODE_SIZE (mode) != 64)
27450 147 : || !VALID_BCST_MODE_P (GET_MODE_INNER (mode))
27451 : /* Disallow HFmode broadcast. */
27452 126 : || GET_MODE_SIZE (GET_MODE_INNER (mode)) < 4)
27453 : return NULL_RTX;
27454 :
27455 21 : rtx cst = CONST_VECTOR_ELT (x, 0);
27456 21 : if (!CONST_SCALAR_INT_P (cst)
27457 15 : && !CONST_DOUBLE_P (cst)
27458 0 : && !CONST_FIXED_P (cst))
27459 : return NULL_RTX;
27460 :
27461 21 : int n_elts = GET_MODE_NUNITS (mode);
27462 42 : if (CONST_VECTOR_NUNITS (x) != n_elts)
27463 : return NULL_RTX;
27464 :
27465 150 : for (int i = 1; i < n_elts; i++)
27466 129 : if (!rtx_equal_p (cst, CONST_VECTOR_ELT (x, i)))
27467 : return NULL_RTX;
27468 :
27469 42 : rtx mem = force_const_mem (GET_MODE_INNER (mode), cst);
27470 21 : return gen_rtx_VEC_DUPLICATE (mode, validize_mem (mem));
27471 : }
27472 :
27473 : /* Determine the ternlog immediate index that implements 3-operand
27474 : ternary logic expression OP. This uses and modifies the 3 element
27475 : array ARGS to record and check the leaves, either 3 REGs, or 2 REGs
27476 : and MEM. Returns an index between 0 and 255 for a valid ternlog,
27477 : or -1 if the expression isn't suitable. */
27478 :
27479 : int
27480 7507051 : ix86_ternlog_idx (rtx op, rtx *args)
27481 : {
27482 7507051 : int idx0, idx1;
27483 :
27484 7507051 : if (!op)
27485 : return -1;
27486 :
27487 7507051 : switch (GET_CODE (op))
27488 : {
27489 765654 : case SUBREG:
27490 765654 : if (!register_operand (op, GET_MODE (op)))
27491 : return -1;
27492 : /* FALLTHRU */
27493 :
27494 3706319 : case REG:
27495 3706319 : if (!args[0])
27496 : {
27497 1909971 : args[0] = op;
27498 1909971 : return 0xf0;
27499 : }
27500 1796348 : if (rtx_equal_p (op, args[0]))
27501 : return 0xf0;
27502 1770040 : if (!args[1])
27503 : {
27504 1498302 : args[1] = op;
27505 1498302 : return 0xcc;
27506 : }
27507 271738 : if (rtx_equal_p (op, args[1]))
27508 : return 0xcc;
27509 255160 : if (!args[2])
27510 : {
27511 232215 : args[2] = op;
27512 232215 : return 0xaa;
27513 : }
27514 22945 : if (rtx_equal_p (op, args[2]))
27515 : return 0xaa;
27516 : return -1;
27517 :
27518 18502 : case VEC_DUPLICATE:
27519 18502 : if (!bcst_mem_operand (op, GET_MODE (op)))
27520 : return -1;
27521 302 : goto do_mem_operand;
27522 :
27523 349753 : case MEM:
27524 349753 : if (!memory_operand (op, GET_MODE (op)))
27525 : return -1;
27526 349588 : if (MEM_P (op)
27527 349588 : && MEM_VOLATILE_P (op)
27528 349682 : && !volatile_ok)
27529 : return -1;
27530 : /* FALLTHRU */
27531 :
27532 462175 : case CONST_VECTOR:
27533 462175 : do_mem_operand:
27534 462175 : if (!args[2])
27535 : {
27536 414713 : args[2] = op;
27537 414713 : return 0xaa;
27538 : }
27539 : /* Maximum of one volatile memory reference per expression. */
27540 47462 : if (side_effects_p (op))
27541 : return -1;
27542 47462 : if (rtx_equal_p (op, args[2]))
27543 : return 0xaa;
27544 : /* Check if CONST_VECTOR is the ones-complement of args[2]. */
27545 47411 : if (CONST_VECTOR_P (op)
27546 3550 : && CONST_VECTOR_P (args[2])
27547 47656 : && rtx_equal_p (simplify_const_unary_operation (NOT, GET_MODE (op),
27548 245 : op, GET_MODE (op)),
27549 : args[2]))
27550 : return 0x55;
27551 47224 : if (!args[0])
27552 : {
27553 45414 : args[0] = op;
27554 45414 : return 0xf0;
27555 : }
27556 1810 : if (rtx_equal_p (op, args[0]))
27557 : return 0xf0;
27558 : /* Check if CONST_VECTOR is the ones-complement of args[0]. */
27559 1810 : if (CONST_VECTOR_P (op)
27560 105 : && CONST_VECTOR_P (args[0])
27561 1852 : && rtx_equal_p (simplify_const_unary_operation (NOT, GET_MODE (op),
27562 42 : op, GET_MODE (op)),
27563 : args[0]))
27564 : return 0x0f;
27565 1768 : if (!args[1])
27566 : {
27567 1756 : args[1] = op;
27568 1756 : return 0xcc;
27569 : }
27570 12 : if (rtx_equal_p (op, args[1]))
27571 : return 0xcc;
27572 : /* Check if CONST_VECTOR is the ones-complement of args[1]. */
27573 12 : if (CONST_VECTOR_P (op)
27574 0 : && CONST_VECTOR_P (args[1])
27575 12 : && rtx_equal_p (simplify_const_unary_operation (NOT, GET_MODE (op),
27576 0 : op, GET_MODE (op)),
27577 : args[1]))
27578 : return 0x33;
27579 : return -1;
27580 :
27581 184081 : case NOT:
27582 184081 : idx0 = ix86_ternlog_idx (XEXP (op, 0), args);
27583 184081 : return (idx0 >= 0) ? idx0 ^ 0xff : -1;
27584 :
27585 1348365 : case AND:
27586 1348365 : idx0 = ix86_ternlog_idx (XEXP (op, 0), args);
27587 1348365 : if (idx0 < 0)
27588 : return -1;
27589 1108214 : idx1 = ix86_ternlog_idx (XEXP (op, 1), args);
27590 1108214 : return (idx1 >= 0) ? idx0 & idx1 : -1;
27591 :
27592 959190 : case IOR:
27593 959190 : idx0 = ix86_ternlog_idx (XEXP (op, 0), args);
27594 959190 : if (idx0 < 0)
27595 : return -1;
27596 711803 : idx1 = ix86_ternlog_idx (XEXP (op, 1), args);
27597 711803 : return (idx1 >= 0) ? idx0 | idx1 : -1;
27598 :
27599 434096 : case XOR:
27600 434096 : idx0 = ix86_ternlog_idx (XEXP (op, 0), args);
27601 434096 : if (idx0 < 0)
27602 : return -1;
27603 411802 : if (vector_all_ones_operand (XEXP (op, 1), GET_MODE (op)))
27604 6724 : return idx0 ^ 0xff;
27605 405078 : idx1 = ix86_ternlog_idx (XEXP (op, 1), args);
27606 405078 : return (idx1 >= 0) ? idx0 ^ idx1 : -1;
27607 :
27608 7348 : case UNSPEC:
27609 7348 : if (XINT (op, 1) != UNSPEC_VTERNLOG
27610 0 : || XVECLEN (op, 0) != 4
27611 0 : || !CONST_INT_P (XVECEXP (op, 0, 3)))
27612 : return -1;
27613 :
27614 : /* TODO: Handle permuted operands. */
27615 0 : if (ix86_ternlog_idx (XVECEXP (op, 0, 0), args) != 0xf0
27616 0 : || ix86_ternlog_idx (XVECEXP (op, 0, 1), args) != 0xcc
27617 0 : || ix86_ternlog_idx (XVECEXP (op, 0, 2), args) != 0xaa)
27618 0 : return -1;
27619 0 : return INTVAL (XVECEXP (op, 0, 3));
27620 :
27621 : default:
27622 : return -1;
27623 : }
27624 : }
27625 :
27626 : /* Return TRUE if OP (in mode MODE) is the leaf of a ternary logic
27627 : expression, such as a register or a memory reference. */
27628 :
27629 : bool
27630 3486845 : ix86_ternlog_leaf_p (rtx op, machine_mode mode)
27631 : {
27632 : /* We can't use memory_operand here, as it may return a different
27633 : value before and after reload (for volatile MEMs) which creates
27634 : problems splitting instructions. */
27635 3486845 : return register_operand (op, mode)
27636 730423 : || MEM_P (op)
27637 395078 : || CONST_VECTOR_P (op)
27638 3776894 : || bcst_mem_operand (op, mode);
27639 : }
27640 :
27641 : /* Test whether OP is a 3-operand ternary logic expression suitable
27642 : for use in a ternlog instruction. */
27643 :
27644 : bool
27645 2320220 : ix86_ternlog_operand_p (rtx op)
27646 : {
27647 2320220 : rtx op0, op1;
27648 2320220 : rtx args[3];
27649 :
27650 2320220 : args[0] = NULL_RTX;
27651 2320220 : args[1] = NULL_RTX;
27652 2320220 : args[2] = NULL_RTX;
27653 2320220 : int idx = ix86_ternlog_idx (op, args);
27654 2320220 : if (idx < 0)
27655 : return false;
27656 :
27657 : /* Don't match simple (binary or unary) expressions. */
27658 1885899 : machine_mode mode = GET_MODE (op);
27659 1885899 : switch (GET_CODE (op))
27660 : {
27661 874400 : case AND:
27662 874400 : op0 = XEXP (op, 0);
27663 874400 : op1 = XEXP (op, 1);
27664 :
27665 : /* Prefer pand. */
27666 874400 : if (ix86_ternlog_leaf_p (op0, mode)
27667 874400 : && ix86_ternlog_leaf_p (op1, mode))
27668 : return false;
27669 : /* Prefer pandn. */
27670 113251 : if (GET_CODE (op0) == NOT
27671 77860 : && register_operand (XEXP (op0, 0), mode)
27672 187484 : && ix86_ternlog_leaf_p (op1, mode))
27673 : return false;
27674 : break;
27675 :
27676 624633 : case IOR:
27677 : /* Prefer por. */
27678 624633 : if (ix86_ternlog_leaf_p (XEXP (op, 0), mode)
27679 624633 : && ix86_ternlog_leaf_p (XEXP (op, 1), mode))
27680 : return false;
27681 : break;
27682 :
27683 351468 : case XOR:
27684 351468 : op1 = XEXP (op, 1);
27685 : /* Prefer pxor, or one_cmpl<vmode>2. */
27686 351468 : if (ix86_ternlog_leaf_p (XEXP (op, 0), mode)
27687 351468 : && ix86_ternlog_leaf_p (XEXP (op, 1), mode))
27688 : return false;
27689 : break;
27690 :
27691 : default:
27692 : break;
27693 : }
27694 : return true;
27695 : }
27696 :
27697 : /* Helper function for ix86_expand_ternlog. */
27698 : static rtx
27699 0 : ix86_expand_ternlog_binop (enum rtx_code code, machine_mode mode,
27700 : rtx op0, rtx op1, rtx target)
27701 : {
27702 0 : if (GET_MODE (op0) != mode)
27703 0 : op0 = gen_lowpart (mode, op0);
27704 0 : if (GET_MODE (op1) != mode)
27705 0 : op1 = gen_lowpart (mode, op1);
27706 :
27707 0 : if (CONST_VECTOR_P (op0))
27708 0 : op0 = validize_mem (force_const_mem (mode, op0));
27709 0 : if (CONST_VECTOR_P (op1))
27710 0 : op1 = validize_mem (force_const_mem (mode, op1));
27711 :
27712 0 : if (!register_operand (op0, mode))
27713 : {
27714 0 : if (!register_operand (op1, mode))
27715 : {
27716 : /* We can't use force_reg (op0, mode). */
27717 0 : rtx reg = gen_reg_rtx (mode);
27718 0 : emit_move_insn (reg, op0);
27719 0 : op0 = reg;
27720 : }
27721 : else
27722 : std::swap (op0, op1);
27723 : }
27724 0 : rtx ops[3] = { target, op0, op1 };
27725 0 : ix86_expand_vector_logical_operator (code, mode, ops);
27726 0 : return target;
27727 : }
27728 :
27729 :
27730 : /* Helper function for ix86_expand_ternlog. */
27731 : static rtx
27732 0 : ix86_expand_ternlog_andnot (machine_mode mode, rtx op0, rtx op1, rtx target)
27733 : {
27734 0 : if (GET_MODE (op0) != mode)
27735 0 : op0 = gen_lowpart (mode, op0);
27736 0 : op0 = gen_rtx_NOT (mode, op0);
27737 0 : if (GET_MODE (op1) != mode)
27738 0 : op1 = gen_lowpart (mode, op1);
27739 0 : if (CONST_VECTOR_P (op1))
27740 0 : op1 = validize_mem (force_const_mem (mode, op1));
27741 0 : emit_move_insn (target, gen_rtx_AND (mode, op0, op1));
27742 0 : return target;
27743 : }
27744 :
27745 : /* Expand a 3-operand ternary logic expression. Return TARGET. */
27746 : rtx
27747 2422 : ix86_expand_ternlog (machine_mode mode, rtx op0, rtx op1, rtx op2, int idx,
27748 : rtx target)
27749 : {
27750 2422 : rtx tmp0, tmp1, tmp2;
27751 :
27752 2422 : if (!target)
27753 3 : target = gen_reg_rtx (mode);
27754 :
27755 : /* Canonicalize ternlog index for degenerate (duplicated) operands. */
27756 2422 : if (rtx_equal_p (op0, op1) && rtx_equal_p (op0, op2))
27757 0 : switch (idx & 0x81)
27758 : {
27759 : case 0x00:
27760 : idx = 0x00;
27761 : break;
27762 : case 0x01:
27763 : idx = 0x0f;
27764 : break;
27765 : case 0x80:
27766 : idx = 0xf0;
27767 : break;
27768 : case 0x81:
27769 : idx = 0xff;
27770 : break;
27771 : }
27772 :
27773 2422 : switch (idx & 0xff)
27774 : {
27775 0 : case 0x00:
27776 0 : if ((!op0 || !side_effects_p (op0))
27777 0 : && (!op1 || !side_effects_p (op1))
27778 0 : && (!op2 || !side_effects_p (op2)))
27779 : {
27780 0 : emit_move_insn (target, CONST0_RTX (mode));
27781 0 : return target;
27782 : }
27783 : break;
27784 :
27785 0 : case 0x0a: /* ~a&c */
27786 0 : if ((!op1 || !side_effects_p (op1))
27787 0 : && op0 && register_operand (op0, mode)
27788 0 : && op2 && ix86_ternlog_leaf_p (op2, mode))
27789 0 : return ix86_expand_ternlog_andnot (mode, op0, op2, target);
27790 : break;
27791 :
27792 0 : case 0x0c: /* ~a&b */
27793 0 : if ((!op2 || !side_effects_p (op2))
27794 0 : && op0 && register_operand (op0, mode)
27795 0 : && op1 && ix86_ternlog_leaf_p (op1, mode))
27796 0 : return ix86_expand_ternlog_andnot (mode, op0, op1, target);
27797 : break;
27798 :
27799 80 : case 0x0f: /* ~a */
27800 0 : if ((!op1 || !side_effects_p (op1))
27801 80 : && (!op2 || !side_effects_p (op2))
27802 160 : && op0)
27803 : {
27804 80 : emit_move_insn (target, gen_rtx_XOR (mode, op0, CONSTM1_RTX (mode)));
27805 80 : return target;
27806 : }
27807 : break;
27808 :
27809 0 : case 0x22: /* ~b&c */
27810 0 : if ((!op0 || !side_effects_p (op0))
27811 0 : && op1 && register_operand (op1, mode)
27812 0 : && op2 && ix86_ternlog_leaf_p (op2, mode))
27813 0 : return ix86_expand_ternlog_andnot (mode, op1, op2, target);
27814 : break;
27815 :
27816 0 : case 0x30: /* ~b&a */
27817 0 : if ((!op2 || !side_effects_p (op2))
27818 0 : && op0 && ix86_ternlog_leaf_p (op0, mode)
27819 0 : && op1 && register_operand (op1, mode))
27820 0 : return ix86_expand_ternlog_andnot (mode, op1, op0, target);
27821 : break;
27822 :
27823 0 : case 0x33: /* ~b */
27824 0 : if ((!op0 || !side_effects_p (op0))
27825 0 : && (!op2 || !side_effects_p (op2))
27826 0 : && op1)
27827 : {
27828 0 : emit_move_insn (target, gen_rtx_XOR (mode, op1, CONSTM1_RTX (mode)));
27829 0 : return target;
27830 : }
27831 : break;
27832 :
27833 0 : case 0x3c: /* a^b */
27834 0 : if (op0 && ix86_ternlog_leaf_p (op0, mode)
27835 0 : && op1 && ix86_ternlog_leaf_p (op1, mode)
27836 0 : && (!op2 || !side_effects_p (op2)))
27837 0 : return ix86_expand_ternlog_binop (XOR, mode, op0, op1, target);
27838 : break;
27839 :
27840 0 : case 0x44: /* ~c&b */
27841 0 : if ((!op0 || !side_effects_p (op0))
27842 0 : && op1 && ix86_ternlog_leaf_p (op1, mode)
27843 0 : && op2 && register_operand (op2, mode))
27844 0 : return ix86_expand_ternlog_andnot (mode, op2, op1, target);
27845 : break;
27846 :
27847 2 : case 0x50: /* ~c&a */
27848 0 : if ((!op1 || !side_effects_p (op1))
27849 2 : && op0 && ix86_ternlog_leaf_p (op0, mode)
27850 4 : && op2 && register_operand (op2, mode))
27851 0 : return ix86_expand_ternlog_andnot (mode, op2, op0, target);
27852 : break;
27853 :
27854 4 : case 0x55: /* ~c */
27855 1 : if ((!op0 || !side_effects_p (op0))
27856 4 : && (!op1 || !side_effects_p (op1))
27857 8 : && op2)
27858 : {
27859 4 : emit_move_insn (target, gen_rtx_XOR (mode, op2, CONSTM1_RTX (mode)));
27860 4 : return target;
27861 : }
27862 : break;
27863 :
27864 0 : case 0x5a: /* a^c */
27865 0 : if (op0 && ix86_ternlog_leaf_p (op0, mode)
27866 0 : && op2 && ix86_ternlog_leaf_p (op2, mode)
27867 0 : && (!op1 || !side_effects_p (op1)))
27868 0 : return ix86_expand_ternlog_binop (XOR, mode, op0, op2, target);
27869 : break;
27870 :
27871 0 : case 0x66: /* b^c */
27872 0 : if ((!op0 || !side_effects_p (op0))
27873 0 : && op1 && ix86_ternlog_leaf_p (op1, mode)
27874 0 : && op2 && ix86_ternlog_leaf_p (op2, mode))
27875 0 : return ix86_expand_ternlog_binop (XOR, mode, op1, op2, target);
27876 : break;
27877 :
27878 0 : case 0x88: /* b&c */
27879 0 : if ((!op0 || !side_effects_p (op0))
27880 0 : && op1 && ix86_ternlog_leaf_p (op1, mode)
27881 0 : && op2 && ix86_ternlog_leaf_p (op2, mode))
27882 0 : return ix86_expand_ternlog_binop (AND, mode, op1, op2, target);
27883 : break;
27884 :
27885 0 : case 0xa0: /* a&c */
27886 0 : if ((!op1 || !side_effects_p (op1))
27887 0 : && op0 && ix86_ternlog_leaf_p (op0, mode)
27888 0 : && op2 && ix86_ternlog_leaf_p (op2, mode))
27889 0 : return ix86_expand_ternlog_binop (AND, mode, op0, op2, target);
27890 : break;
27891 :
27892 0 : case 0xaa: /* c */
27893 0 : if ((!op0 || !side_effects_p (op0))
27894 0 : && (!op1 || !side_effects_p (op1))
27895 0 : && op2)
27896 : {
27897 0 : if (GET_MODE (op2) != mode)
27898 0 : op2 = gen_lowpart (mode, op2);
27899 0 : emit_move_insn (target, op2);
27900 0 : return target;
27901 : }
27902 : break;
27903 :
27904 0 : case 0xc0: /* a&b */
27905 0 : if (op0 && ix86_ternlog_leaf_p (op0, mode)
27906 0 : && op1 && ix86_ternlog_leaf_p (op1, mode)
27907 0 : && (!op2 || !side_effects_p (op2)))
27908 0 : return ix86_expand_ternlog_binop (AND, mode, op0, op1, target);
27909 : break;
27910 :
27911 0 : case 0xcc: /* b */
27912 0 : if ((!op0 || !side_effects_p (op0))
27913 0 : && op1
27914 0 : && (!op2 || !side_effects_p (op2)))
27915 : {
27916 0 : if (GET_MODE (op1) != mode)
27917 0 : op1 = gen_lowpart (mode, op1);
27918 0 : emit_move_insn (target, op1);
27919 0 : return target;
27920 : }
27921 : break;
27922 :
27923 0 : case 0xee: /* b|c */
27924 0 : if ((!op0 || !side_effects_p (op0))
27925 0 : && op1 && ix86_ternlog_leaf_p (op1, mode)
27926 0 : && op2 && ix86_ternlog_leaf_p (op2, mode))
27927 0 : return ix86_expand_ternlog_binop (IOR, mode, op1, op2, target);
27928 : break;
27929 :
27930 6 : case 0xf0: /* a */
27931 6 : if (op0
27932 6 : && (!op1 || !side_effects_p (op1))
27933 12 : && (!op2 || !side_effects_p (op2)))
27934 : {
27935 6 : if (GET_MODE (op0) != mode)
27936 0 : op0 = gen_lowpart (mode, op0);
27937 6 : emit_move_insn (target, op0);
27938 6 : return target;
27939 : }
27940 : break;
27941 :
27942 0 : case 0xfa: /* a|c */
27943 0 : if (op0 && ix86_ternlog_leaf_p (op0, mode)
27944 0 : && op2 && ix86_ternlog_leaf_p (op2, mode)
27945 0 : && (!op1 || !side_effects_p (op1)))
27946 0 : return ix86_expand_ternlog_binop (IOR, mode, op0, op2, target);
27947 : break;
27948 :
27949 0 : case 0xfc: /* a|b */
27950 0 : if (op0 && ix86_ternlog_leaf_p (op0, mode)
27951 0 : && op1 && ix86_ternlog_leaf_p (op1, mode)
27952 0 : && (!op2 || !side_effects_p (op2)))
27953 0 : return ix86_expand_ternlog_binop (IOR, mode, op0, op1, target);
27954 : break;
27955 :
27956 0 : case 0xff:
27957 0 : if ((!op0 || !side_effects_p (op0))
27958 0 : && (!op1 || !side_effects_p (op1))
27959 0 : && (!op2 || !side_effects_p (op2)))
27960 : {
27961 0 : emit_move_insn (target, CONSTM1_RTX (mode));
27962 0 : return target;
27963 : }
27964 : break;
27965 : }
27966 :
27967 2332 : if (!register_operand (op0, mode))
27968 : {
27969 : /* We can't use force_reg (mode, op0). */
27970 12 : tmp0 = gen_reg_rtx (GET_MODE (op0));
27971 12 : emit_move_insn (tmp0,op0);
27972 : }
27973 : else
27974 : tmp0 = op0;
27975 2332 : if (GET_MODE (tmp0) != mode)
27976 0 : tmp0 = gen_lowpart (mode, tmp0);
27977 :
27978 2332 : if (!op1 || rtx_equal_p (op0, op1))
27979 6 : tmp1 = copy_rtx (tmp0);
27980 2326 : else if (!register_operand (op1, mode))
27981 : {
27982 : /* We can't use force_reg (mode, op1). */
27983 28 : tmp1 = gen_reg_rtx (GET_MODE (op1));
27984 28 : emit_move_insn (tmp1, op1);
27985 : }
27986 : else
27987 : tmp1 = op1;
27988 2332 : if (GET_MODE (tmp1) != mode)
27989 0 : tmp1 = gen_lowpart (mode, tmp1);
27990 :
27991 2332 : if (!op2 || rtx_equal_p (op0, op2))
27992 75 : tmp2 = copy_rtx (tmp0);
27993 2257 : else if (rtx_equal_p (op1, op2))
27994 0 : tmp2 = copy_rtx (tmp1);
27995 2257 : else if (CONST_VECTOR_P (op2))
27996 : {
27997 43 : if (GET_MODE (op2) != mode)
27998 0 : op2 = gen_lowpart (mode, op2);
27999 43 : tmp2 = ix86_gen_bcst_mem (mode, op2);
28000 43 : if (!tmp2)
28001 : {
28002 25 : machine_mode bcst32_mode = mode;
28003 25 : machine_mode bcst64_mode = mode;
28004 25 : switch (mode)
28005 : {
28006 1 : case V1TImode:
28007 1 : case V4SImode:
28008 1 : case V4SFmode:
28009 1 : case V8HImode:
28010 1 : case V16QImode:
28011 1 : bcst32_mode = V4SImode;
28012 1 : bcst64_mode = V2DImode;
28013 1 : break;
28014 :
28015 0 : case V2TImode:
28016 0 : case V8SImode:
28017 0 : case V8SFmode:
28018 0 : case V16HImode:
28019 0 : case V32QImode:
28020 0 : bcst32_mode = V8SImode;
28021 0 : bcst64_mode = V4DImode;
28022 0 : break;
28023 :
28024 3 : case V4TImode:
28025 3 : case V16SImode:
28026 3 : case V16SFmode:
28027 3 : case V32HImode:
28028 3 : case V64QImode:
28029 3 : bcst32_mode = V16SImode;
28030 3 : bcst64_mode = V8DImode;
28031 3 : break;
28032 :
28033 : default:
28034 : break;
28035 : }
28036 :
28037 25 : if (bcst32_mode != mode)
28038 : {
28039 4 : tmp2 = gen_lowpart (bcst32_mode, op2);
28040 4 : if (ix86_gen_bcst_mem (bcst32_mode, tmp2))
28041 : {
28042 3 : tmp2 = ix86_expand_ternlog (bcst32_mode,
28043 3 : gen_lowpart (bcst32_mode, tmp0),
28044 3 : gen_lowpart (bcst32_mode, tmp1),
28045 : tmp2, idx, NULL_RTX);
28046 3 : emit_move_insn (target, gen_lowpart (mode, tmp2));
28047 3 : return target;
28048 : }
28049 : }
28050 :
28051 22 : if (bcst64_mode != mode)
28052 : {
28053 1 : tmp2 = gen_lowpart (bcst64_mode, op2);
28054 1 : if (ix86_gen_bcst_mem (bcst64_mode, tmp2))
28055 : {
28056 0 : tmp2 = ix86_expand_ternlog (bcst64_mode,
28057 0 : gen_lowpart (bcst64_mode, tmp0),
28058 0 : gen_lowpart (bcst64_mode, tmp1),
28059 : tmp2, idx, NULL_RTX);
28060 0 : emit_move_insn (target, gen_lowpart (mode, tmp2));
28061 0 : return target;
28062 : }
28063 : }
28064 :
28065 22 : tmp2 = force_const_mem (mode, op2);
28066 22 : rtx bcast = ix86_broadcast_from_constant (mode, tmp2);
28067 22 : tmp2 = validize_mem (tmp2);
28068 22 : if (bcast)
28069 : {
28070 12 : rtx reg2 = gen_reg_rtx (mode);
28071 12 : bool ok = ix86_expand_vector_init_duplicate (false, mode,
28072 : reg2, bcast);
28073 12 : if (ok)
28074 2329 : tmp2 = reg2;
28075 : }
28076 : }
28077 : }
28078 : else
28079 : tmp2 = op2;
28080 2329 : if (GET_MODE (tmp2) != mode)
28081 0 : tmp2 = gen_lowpart (mode, tmp2);
28082 : /* Some memory_operands are not vector_memory_operands. */
28083 2329 : if (!bcst_vector_operand (tmp2, mode))
28084 0 : tmp2 = force_reg (mode, tmp2);
28085 :
28086 2329 : rtvec vec = gen_rtvec (4, tmp0, tmp1, tmp2, GEN_INT (idx));
28087 2329 : emit_move_insn (target, gen_rtx_UNSPEC (mode, vec, UNSPEC_VTERNLOG));
28088 2329 : return target;
28089 : }
28090 :
28091 : /* GF2P8AFFINEQB matrixes to implement shift and rotate. */
28092 :
28093 : static const uint64_t matrix_ashift[8] =
28094 : {
28095 : 0,
28096 : 0x0001020408102040, /* 1 l */
28097 : 0x0000010204081020, /* 2 l */
28098 : 0x0000000102040810, /* 3 l */
28099 : 0x0000000001020408, /* 4 l */
28100 : 0x0000000000010204, /* 5 l */
28101 : 0x0000000000000102, /* 6 l */
28102 : 0x0000000000000001 /* 7 l */
28103 : };
28104 :
28105 : static const uint64_t matrix_lshiftrt[8] =
28106 : {
28107 : 0,
28108 : 0x0204081020408000, /* 1 r */
28109 : 0x0408102040800000, /* 2 r */
28110 : 0x0810204080000000, /* 3 r */
28111 : 0x1020408000000000, /* 4 r */
28112 : 0x2040800000000000, /* 5 r */
28113 : 0x4080000000000000, /* 6 r */
28114 : 0x8000000000000000 /* 7 r */
28115 : };
28116 :
28117 : static const uint64_t matrix_ashiftrt[8] =
28118 : {
28119 : 0,
28120 : 0x0204081020408080, /* 1 r */
28121 : 0x0408102040808080, /* 2 r */
28122 : 0x0810204080808080, /* 3 r */
28123 : 0x1020408080808080, /* 4 r */
28124 : 0x2040808080808080, /* 5 r */
28125 : 0x4080808080808080, /* 6 r */
28126 : 0x8080808080808080 /* 7 r */
28127 : };
28128 :
28129 : static const uint64_t matrix_rotate[8] =
28130 : {
28131 : 0,
28132 : 0x8001020408102040, /* 1 rol8 */
28133 : 0x4080010204081020, /* 2 rol8 */
28134 : 0x2040800102040810, /* 3 rol8 */
28135 : 0x1020408001020408, /* 4 rol8 */
28136 : 0x0810204080010204, /* 5 rol8 */
28137 : 0x0408102040800102, /* 6 rol8 */
28138 : 0x0204081020408001 /* 7 rol8 */
28139 : };
28140 :
28141 : static const uint64_t matrix_rotatert[8] =
28142 : {
28143 : 0,
28144 : 0x0204081020408001, /* 1 ror8 */
28145 : 0x0408102040800102, /* 2 ror8 */
28146 : 0x0810204080010204, /* 3 ror8 */
28147 : 0x1020408001020408, /* 4 ror8 */
28148 : 0x2040800102040810, /* 5 ror8 */
28149 : 0x4080010204081020, /* 6 ror8 */
28150 : 0x8001020408102040 /* 7 ror8 */
28151 : };
28152 :
28153 : /* Return rtx to load a 64bit GF2P8AFFINE GP(2) matrix implementing a shift
28154 : for CODE and shift count COUNT into register with vector of size of SRC. */
28155 :
28156 : rtx
28157 202 : ix86_vgf2p8affine_shift_matrix (rtx src, rtx count, enum rtx_code code)
28158 : {
28159 202 : machine_mode mode = GET_MODE (src);
28160 202 : const uint64_t *matrix;
28161 202 : unsigned shift = INTVAL (count) & 7;
28162 202 : gcc_assert (shift > 0 && shift < 8);
28163 :
28164 202 : switch (code)
28165 : {
28166 : case ASHIFT:
28167 : matrix = matrix_ashift;
28168 : break;
28169 27 : case ASHIFTRT:
28170 27 : matrix = matrix_ashiftrt;
28171 27 : break;
28172 30 : case LSHIFTRT:
28173 30 : matrix = matrix_lshiftrt;
28174 30 : break;
28175 34 : case ROTATE:
28176 34 : matrix = matrix_rotate;
28177 34 : break;
28178 35 : case ROTATERT:
28179 35 : matrix = matrix_rotatert;
28180 35 : break;
28181 0 : default:
28182 0 : gcc_unreachable ();
28183 : }
28184 :
28185 202 : int nelts = GET_MODE_NUNITS (mode);
28186 202 : rtvec vec = rtvec_alloc (nelts);
28187 202 : uint64_t ma = matrix[shift];
28188 6922 : for (int i = 0; i < nelts; i++)
28189 6720 : RTVEC_ELT (vec, i) = gen_int_mode ((ma >> ((i % 8) * 8)) & 0xff, QImode);
28190 :
28191 202 : return force_reg (mode, gen_rtx_CONST_VECTOR (mode, vec));
28192 : }
28193 :
28194 : /* Trunc a vector to a narrow vector, like v4di -> v4si. */
28195 :
28196 : void
28197 62 : ix86_expand_trunc_with_avx2_noavx512f (rtx output, rtx input, machine_mode cvt_mode)
28198 : {
28199 62 : machine_mode out_mode = GET_MODE (output);
28200 62 : machine_mode in_mode = GET_MODE (input);
28201 62 : int len = GET_MODE_SIZE (in_mode);
28202 248 : gcc_assert (len == GET_MODE_SIZE (cvt_mode)
28203 : && GET_MODE_INNER (out_mode) == GET_MODE_INNER (cvt_mode)
28204 : && (REG_P (input) || SUBREG_P (input)));
28205 62 : scalar_mode inner_out_mode = GET_MODE_INNER (out_mode);
28206 124 : int in_innersize = GET_MODE_SIZE (GET_MODE_INNER (in_mode));
28207 62 : int out_innersize = GET_MODE_SIZE (inner_out_mode);
28208 :
28209 62 : struct expand_vec_perm_d d;
28210 62 : d.target = gen_reg_rtx (cvt_mode);
28211 62 : d.op0 = lowpart_subreg (cvt_mode, force_reg(in_mode, input), in_mode);
28212 62 : d.op1 = d.op0;
28213 62 : d.vmode = cvt_mode;
28214 62 : d.nelt = GET_MODE_NUNITS (cvt_mode);
28215 62 : d.testing_p = false;
28216 62 : d.one_operand_p = true;
28217 :
28218 : /* Init perm. Put the needed bits of input in order and
28219 : fill the rest of bits by default. */
28220 678 : for (int i = 0; i < d.nelt; ++i)
28221 : {
28222 616 : d.perm[i] = i;
28223 1232 : if (i < GET_MODE_NUNITS (out_mode))
28224 242 : d.perm[i] = i * (in_innersize / out_innersize);
28225 : }
28226 :
28227 62 : bool ok = ix86_expand_vec_perm_const_1(&d);
28228 62 : gcc_assert (ok);
28229 62 : emit_move_insn (output, gen_lowpart (out_mode, d.target));
28230 62 : }
28231 :
28232 : /* Implement truncv8sfv8bf2 with vector permutation. */
28233 : void
28234 8 : ix86_expand_vector_sf2bf_with_vec_perm (rtx dest, rtx src)
28235 : {
28236 8 : machine_mode vperm_mode, src_mode = GET_MODE (src);
28237 8 : switch (src_mode)
28238 : {
28239 : case V16SFmode:
28240 : vperm_mode = V32BFmode;
28241 : break;
28242 2 : case V8SFmode:
28243 2 : vperm_mode = V16BFmode;
28244 2 : break;
28245 4 : case V4SFmode:
28246 4 : vperm_mode = V8BFmode;
28247 4 : break;
28248 0 : default:
28249 0 : gcc_unreachable ();
28250 : }
28251 :
28252 8 : int nelt = GET_MODE_NUNITS (vperm_mode);
28253 8 : vec_perm_builder sel (nelt, nelt, 1);
28254 8 : sel.quick_grow (nelt);
28255 136 : for (int i = 0; i != nelt; i++)
28256 128 : sel[i] = (2 * i + 1) % nelt;
28257 16 : vec_perm_indices indices (sel, 1, nelt);
28258 :
28259 8 : rtx target = gen_reg_rtx (vperm_mode);
28260 8 : rtx op0 = lowpart_subreg (vperm_mode,
28261 : force_reg (src_mode, src),
28262 : src_mode);
28263 8 : bool ok = targetm.vectorize.vec_perm_const (vperm_mode, vperm_mode,
28264 : target, op0, op0, indices);
28265 8 : gcc_assert (ok);
28266 8 : emit_move_insn (dest, lowpart_subreg (GET_MODE (dest), target, vperm_mode));
28267 8 : }
28268 :
28269 : /* Implement extendv8bf2v8sf2 with vector permutation. */
28270 : void
28271 8 : ix86_expand_vector_bf2sf_with_vec_perm (rtx dest, rtx src)
28272 : {
28273 8 : machine_mode vperm_mode, src_mode = GET_MODE (src);
28274 8 : switch (src_mode)
28275 : {
28276 : case V16BFmode:
28277 : vperm_mode = V32BFmode;
28278 : break;
28279 2 : case V8BFmode:
28280 2 : vperm_mode = V16BFmode;
28281 2 : break;
28282 4 : case V4BFmode:
28283 4 : vperm_mode = V8BFmode;
28284 4 : break;
28285 0 : default:
28286 0 : gcc_unreachable ();
28287 : }
28288 :
28289 8 : int nelt = GET_MODE_NUNITS (vperm_mode);
28290 8 : vec_perm_builder sel (nelt, nelt, 1);
28291 8 : sel.quick_grow (nelt);
28292 136 : for (int i = 0, k = 0, j = nelt; i != nelt; i++)
28293 128 : sel[i] = i & 1 ? j++ : k++;
28294 :
28295 16 : vec_perm_indices indices (sel, 2, nelt);
28296 :
28297 8 : rtx target = gen_reg_rtx (vperm_mode);
28298 8 : rtx op1 = lowpart_subreg (vperm_mode,
28299 : force_reg (src_mode, src),
28300 : src_mode);
28301 8 : rtx op0 = CONST0_RTX (vperm_mode);
28302 8 : bool ok = targetm.vectorize.vec_perm_const (vperm_mode, vperm_mode,
28303 : target, op0, op1, indices);
28304 8 : gcc_assert (ok);
28305 8 : emit_move_insn (dest, lowpart_subreg (GET_MODE (dest), target, vperm_mode));
28306 8 : }
28307 :
28308 : /* Implement bitreverse<mode>2 using gf2p8affineqb. */
28309 :
28310 : void
28311 5 : ix86_expand_gfni_bitreverse (rtx dest, rtx src)
28312 : {
28313 5 : machine_mode mode = GET_MODE (dest);
28314 5 : rtx temp;
28315 10 : if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
28316 : {
28317 1 : rtx temp1 = gen_reg_rtx (mode == TImode ? V2DImode : V4SImode);
28318 1 : rtx temp2 = gen_reg_rtx (mode == TImode ? V2DImode : V4SImode);
28319 1 : if (mode == TImode)
28320 : {
28321 1 : temp = lowpart_subreg (DImode, src, TImode);
28322 1 : emit_insn (gen_rtx_SET (temp1, gen_rtx_VEC_CONCAT (V2DImode, temp,
28323 : const0_rtx)));
28324 1 : temp = gen_highpart (DImode, src);
28325 1 : emit_insn (gen_rtx_SET (temp2, gen_rtx_VEC_CONCAT (V2DImode, temp,
28326 : const0_rtx)));
28327 : }
28328 : else
28329 : {
28330 0 : temp = lowpart_subreg (SImode, src, DImode);
28331 0 : emit_insn (gen_vec_setv4si_0 (temp1, CONST0_RTX (V4SImode), temp));
28332 0 : temp = gen_highpart (SImode, src);
28333 0 : emit_insn (gen_vec_setv4si_0 (temp2, CONST0_RTX (V4SImode), temp));
28334 0 : temp1 = lowpart_subreg (V2DImode, temp1, V4SImode);
28335 0 : temp2 = lowpart_subreg (V2DImode, temp2, V4SImode);
28336 : }
28337 1 : temp = gen_reg_rtx (V2DImode);
28338 1 : emit_insn (gen_vec_interleave_lowv2di (temp, temp1, temp2));
28339 : }
28340 4 : else if (mode != DImode)
28341 : {
28342 3 : if (mode != SImode)
28343 : {
28344 2 : src = force_reg (mode, src);
28345 2 : src = lowpart_subreg (SImode, src, mode);
28346 : }
28347 3 : temp = gen_reg_rtx (V4SImode);
28348 3 : emit_insn (gen_vec_setv4si_0 (temp, CONST0_RTX (V4SImode), src));
28349 : }
28350 : else
28351 : {
28352 1 : temp = gen_reg_rtx (V2DImode);
28353 1 : emit_insn (gen_rtx_SET (temp, gen_rtx_VEC_CONCAT (V2DImode, src,
28354 : const0_rtx)));
28355 : }
28356 5 : src = temp;
28357 5 : temp = gen_reg_rtx (V16QImode);
28358 5 : rtx src2 = gen_rtx_CONST_VECTOR (V16QImode,
28359 : gen_rtvec (16, GEN_INT (1), GEN_INT (2),
28360 : GEN_INT (4), GEN_INT (8),
28361 : GEN_INT (16), GEN_INT (32),
28362 : GEN_INT (64), GEN_INT (-128),
28363 : GEN_INT (1), GEN_INT (2),
28364 : GEN_INT (4), GEN_INT (8),
28365 : GEN_INT (16), GEN_INT (32),
28366 : GEN_INT (64), GEN_INT (-128)));
28367 5 : src2 = validize_mem (force_const_mem (V16QImode, src2));
28368 5 : src = lowpart_subreg (V16QImode, src, GET_MODE (src));
28369 5 : emit_insn (gen_vgf2p8affineqb_v16qi (temp, src, src2, const0_rtx));
28370 5 : if (mode == QImode)
28371 : {
28372 1 : rtx temp1 = gen_reg_rtx (SImode);
28373 1 : rtx temp2 = lowpart_subreg (V4SImode, temp, V16QImode);
28374 1 : rtx temp3 = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (1, const0_rtx));
28375 1 : emit_insn (gen_rtx_SET (temp1,
28376 : gen_rtx_VEC_SELECT (SImode, temp2, temp3)));
28377 1 : emit_move_insn (dest, lowpart_subreg (QImode, temp1, SImode));
28378 1 : return;
28379 : }
28380 11 : rtx target = gen_reg_rtx ((GET_MODE_SIZE (mode) < 4 || !TARGET_64BIT)
28381 3 : ? SImode : mode == TImode ? DImode : mode);
28382 4 : emit_move_insn (target, lowpart_subreg (GET_MODE (target), temp, V16QImode));
28383 8 : if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
28384 : {
28385 1 : rtx temp1 = gen_reg_rtx (GET_MODE (target));
28386 1 : if (mode == TImode || TARGET_SSE4_1)
28387 : {
28388 1 : rtx temp2 = lowpart_subreg (mode == TImode ? V2DImode : V4SImode,
28389 : temp, V16QImode);
28390 1 : rtx temp3 = gen_rtx_PARALLEL (VOIDmode,
28391 : gen_rtvec (1, GEN_INT (mode == TImode
28392 : ? 1 : 2)));
28393 1 : emit_insn (gen_rtx_SET (temp1,
28394 : gen_rtx_VEC_SELECT (GET_MODE (target), temp2,
28395 : temp3)));
28396 1 : }
28397 : else
28398 : {
28399 0 : rtx temp2 = gen_reg_rtx (V4SImode);
28400 0 : rtx temp3 = lowpart_subreg (V4SImode, temp, V16QImode);
28401 0 : emit_insn (gen_sse2_pshufd (temp2, temp3, GEN_INT (0xaa)));
28402 0 : emit_move_insn (temp1, lowpart_subreg (GET_MODE (target), temp2,
28403 : V4SImode));
28404 : }
28405 1 : rtx temp4 = gen_reg_rtx (GET_MODE (target));
28406 1 : rtx temp5 = gen_reg_rtx (GET_MODE (target));
28407 0 : rtx (*gen_bswap) (rtx, rtx)
28408 1 : = mode == TImode ? gen_bswapdi2 : gen_bswapsi2;
28409 1 : emit_insn (gen_bswap (temp4, target));
28410 1 : emit_insn (gen_bswap (temp5, temp1));
28411 1 : temp4 = gen_rtx_ZERO_EXTEND (mode, temp4);
28412 1 : temp5 = gen_rtx_ZERO_EXTEND (mode, temp5);
28413 1 : rtx shift = GEN_INT (GET_MODE_PRECISION (GET_MODE (target)));
28414 1 : temp4 = gen_rtx_ASHIFT (mode, temp4, shift);
28415 1 : emit_insn (gen_rtx_SET (dest, gen_rtx_IOR (mode, temp4, temp5)));
28416 1 : return;
28417 : }
28418 3 : if (mode == HImode)
28419 1 : target = lowpart_subreg (mode, target, SImode);
28420 3 : if (mode == SImode)
28421 1 : emit_insn (gen_bswapsi2 (dest, target));
28422 : else
28423 2 : emit_insn (gen_rtx_SET (dest, gen_rtx_BSWAP (mode, target)));
28424 : }
28425 :
28426 : /* Expand LCP stall or long immediate peephole for INSN. Use the
28427 : previous scratch register if possible. If USE_XOR is true,
28428 : generate "*movsi_xor". */
28429 :
28430 : void
28431 31347 : ix86_expand_lcp_stall_peephole (rtx_insn *insn, rtx *operands,
28432 : bool use_xor)
28433 : {
28434 31347 : rtx imm, scratch;
28435 31347 : machine_mode mode = GET_MODE (operands[0]);
28436 :
28437 : /* Get the immediate operand and the allocated scratch register. */
28438 31347 : if (use_xor)
28439 : {
28440 10493 : imm = const0_rtx;
28441 10493 : scratch = operands[1];
28442 : }
28443 : else
28444 : {
28445 20854 : imm = operands[1];
28446 20854 : scratch = operands[2];
28447 : }
28448 :
28449 31347 : df_ref def;
28450 31347 : rtx_insn *prev, *prev_insn = nullptr;
28451 31347 : rtx set, prev_scratch = nullptr;
28452 :
28453 : /* Scan backward for the previous scratch register def with IMM in
28454 : the same basic block. */
28455 31347 : basic_block bb = BLOCK_FOR_INSN (insn);
28456 955497 : for (prev = PREV_INSN (insn);
28457 955497 : prev != BB_HEAD (bb);
28458 924150 : prev = PREV_INSN (prev))
28459 : {
28460 928937 : if (NONDEBUG_INSN_P (prev))
28461 2072688 : FOR_EACH_INSN_DEF (def, prev)
28462 1745806 : if (!DF_REF_IS_ARTIFICIAL (def)
28463 1745806 : && !DF_REF_FLAGS_IS_SET (def, DF_REF_MAY_CLOBBER)
28464 174862 : && !DF_REF_FLAGS_IS_SET (def, DF_REF_MUST_CLOBBER))
28465 : {
28466 154272 : rtx reg = DF_REF_REG (def);
28467 154272 : if (HARD_REGISTER_P (reg) && REGNO (reg) != FLAGS_REG)
28468 : {
28469 153049 : set = single_set (prev);
28470 153049 : if (!set)
28471 479 : continue;
28472 :
28473 152570 : rtx dest = SET_DEST (set);
28474 :
28475 : /* Reject DEST if a register is not wide enough to
28476 : supply MODE or invalid for QImode. */
28477 133333 : if (!GENERAL_REG_P (dest)
28478 229682 : || (GET_MODE_SIZE (GET_MODE (dest))
28479 114841 : < GET_MODE_SIZE (mode))
28480 266277 : || (mode == QImode
28481 0 : && !ANY_QI_REGNO_P (REGNO (dest))))
28482 38863 : continue;
28483 :
28484 113707 : rtx src = SET_SRC (set);
28485 113707 : if (rtx_equal_p (src, imm))
28486 : {
28487 : /* A previous scratch register is found. */
28488 : prev_scratch = dest;
28489 : prev_insn = prev;
28490 : break;
28491 : }
28492 : }
28493 : }
28494 :
28495 928937 : if (prev_scratch)
28496 : break;
28497 : }
28498 :
28499 31347 : if (prev_scratch)
28500 : {
28501 : /* The previous scratch register is unusable if it is set between
28502 : PREV_INSN and INSN. */
28503 4787 : unsigned int regno = REGNO (prev_scratch);
28504 :
28505 : /* Scan backward for the previous scratch register def. */
28506 4787 : for (prev = PREV_INSN (insn);
28507 131544 : prev != prev_insn;
28508 126757 : prev = PREV_INSN (prev))
28509 : {
28510 128217 : if (NONDEBUG_INSN_P (prev))
28511 265425 : FOR_EACH_INSN_DEF (def, prev)
28512 187424 : if (HARD_REGISTER_P (DF_REF_REAL_REG (def))
28513 187424 : && DF_REF_REGNO (def) == regno)
28514 : {
28515 : /* Since the previous scratch register is set, it is
28516 : unusable. */
28517 1460 : if (dump_file)
28518 : {
28519 0 : fprintf (dump_file,
28520 : "\nThe previous scratch register:\n\n");
28521 0 : print_rtl_single (dump_file, prev_scratch);
28522 0 : fprintf (dump_file, "\nset in:\n\n");
28523 0 : print_rtl_single (dump_file, prev_insn);
28524 0 : fprintf (dump_file,
28525 : "\nis unusable by:\n\n");
28526 0 : print_rtl_single (dump_file, insn);
28527 0 : fprintf (dump_file,
28528 : "\nsince it is overridden by:\n\n");
28529 0 : print_rtl_single (dump_file, prev);
28530 0 : fprintf (dump_file, "\n");
28531 : }
28532 : prev_scratch = nullptr;
28533 : break;
28534 : }
28535 :
28536 126757 : if (!prev_scratch)
28537 : break;
28538 : }
28539 :
28540 4787 : if (prev_scratch)
28541 : {
28542 : /* Ignore the allocated scratch register and use the previous
28543 : scratch register. */
28544 3327 : if (dump_file)
28545 : {
28546 0 : fprintf (dump_file,
28547 : "\nIgnore the allocated scratch register:\n\n");
28548 0 : print_rtl_single (dump_file, scratch);
28549 0 : fprintf (dump_file,
28550 : "\nand use the previous scratch register:\n\n");
28551 0 : print_rtl_single (dump_file, prev_scratch);
28552 0 : fprintf (dump_file, "\nset in:\n\n");
28553 0 : print_rtl_single (dump_file, prev_insn);
28554 0 : fprintf (dump_file, "\nfor:\n\n");
28555 0 : print_rtl_single (dump_file, insn);
28556 0 : fprintf (dump_file, "\n");
28557 : }
28558 3327 : scratch = gen_lowpart (mode, prev_scratch);
28559 3327 : set = gen_rtx_SET (operands[0], scratch);
28560 3327 : emit_insn (set);
28561 3327 : return;
28562 : }
28563 : }
28564 :
28565 : /* If there is no usable previous scratch register, use the allocated
28566 : scratch register. */
28567 28020 : if (use_xor)
28568 : {
28569 : /* Generate "*movsi_xor". */
28570 8976 : rtx x = gen_lowpart (SImode, scratch);
28571 8976 : rtvec p = rtvec_alloc (2);
28572 8976 : set = gen_rtx_SET (x, const0_rtx);
28573 8976 : RTVEC_ELT (p, 0) = set;
28574 8976 : rtx clobber = gen_rtx_REG (CCmode, FLAGS_REG);
28575 8976 : RTVEC_ELT (p, 1) = gen_rtx_CLOBBER (VOIDmode, clobber);
28576 8976 : set = gen_rtx_PARALLEL (VOIDmode, p);
28577 : }
28578 : else
28579 19044 : set = gen_rtx_SET (scratch, imm);
28580 28020 : emit_insn (set);
28581 28020 : set = gen_rtx_SET (operands[0], scratch);
28582 28020 : emit_insn (set);
28583 : }
28584 :
28585 : #include "gt-i386-expand.h"
|