Branch data Line data Source code
1 : : /* Copyright (C) 1988-2025 Free Software Foundation, Inc.
2 : :
3 : : This file is part of GCC.
4 : :
5 : : GCC is free software; you can redistribute it and/or modify
6 : : it under the terms of the GNU General Public License as published by
7 : : the Free Software Foundation; either version 3, or (at your option)
8 : : any later version.
9 : :
10 : : GCC is distributed in the hope that it will be useful,
11 : : but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 : : GNU General Public License for more details.
14 : :
15 : : You should have received a copy of the GNU General Public License
16 : : along with GCC; see the file COPYING3. If not see
17 : : <http://www.gnu.org/licenses/>. */
18 : :
19 : : #define IN_TARGET_CODE 1
20 : :
21 : : #include "config.h"
22 : : #include "system.h"
23 : : #include "coretypes.h"
24 : : #include "backend.h"
25 : : #include "rtl.h"
26 : : #include "tree.h"
27 : : #include "memmodel.h"
28 : : #include "gimple.h"
29 : : #include "cfghooks.h"
30 : : #include "cfgloop.h"
31 : : #include "df.h"
32 : : #include "tm_p.h"
33 : : #include "stringpool.h"
34 : : #include "expmed.h"
35 : : #include "optabs.h"
36 : : #include "regs.h"
37 : : #include "emit-rtl.h"
38 : : #include "recog.h"
39 : : #include "cgraph.h"
40 : : #include "diagnostic.h"
41 : : #include "cfgbuild.h"
42 : : #include "alias.h"
43 : : #include "fold-const.h"
44 : : #include "attribs.h"
45 : : #include "calls.h"
46 : : #include "stor-layout.h"
47 : : #include "varasm.h"
48 : : #include "output.h"
49 : : #include "insn-attr.h"
50 : : #include "flags.h"
51 : : #include "except.h"
52 : : #include "explow.h"
53 : : #include "expr.h"
54 : : #include "cfgrtl.h"
55 : : #include "common/common-target.h"
56 : : #include "langhooks.h"
57 : : #include "reload.h"
58 : : #include "gimplify.h"
59 : : #include "dwarf2.h"
60 : : #include "tm-constrs.h"
61 : : #include "cselib.h"
62 : : #include "sched-int.h"
63 : : #include "opts.h"
64 : : #include "tree-pass.h"
65 : : #include "context.h"
66 : : #include "pass_manager.h"
67 : : #include "target-globals.h"
68 : : #include "gimple-iterator.h"
69 : : #include "shrink-wrap.h"
70 : : #include "builtins.h"
71 : : #include "rtl-iter.h"
72 : : #include "tree-iterator.h"
73 : : #include "dbgcnt.h"
74 : : #include "case-cfn-macros.h"
75 : : #include "dojump.h"
76 : : #include "fold-const-call.h"
77 : : #include "tree-vrp.h"
78 : : #include "tree-ssanames.h"
79 : : #include "selftest.h"
80 : : #include "selftest-rtl.h"
81 : : #include "print-rtl.h"
82 : : #include "intl.h"
83 : : #include "ifcvt.h"
84 : : #include "symbol-summary.h"
85 : : #include "sreal.h"
86 : : #include "ipa-cp.h"
87 : : #include "ipa-prop.h"
88 : : #include "ipa-fnsummary.h"
89 : : #include "wide-int-bitmask.h"
90 : : #include "tree-vector-builder.h"
91 : : #include "debug.h"
92 : : #include "dwarf2out.h"
93 : : #include "i386-options.h"
94 : : #include "i386-builtins.h"
95 : : #include "i386-expand.h"
96 : : #include "asan.h"
97 : :
98 : : /* Split one or more double-mode RTL references into pairs of half-mode
99 : : references. The RTL can be REG, offsettable MEM, integer constant, or
100 : : CONST_DOUBLE. "operands" is a pointer to an array of double-mode RTLs to
101 : : split and "num" is its length. lo_half and hi_half are output arrays
102 : : that parallel "operands". */
103 : :
104 : : void
105 : 4182599 : split_double_mode (machine_mode mode, rtx operands[],
106 : : int num, rtx lo_half[], rtx hi_half[])
107 : : {
108 : 4182599 : machine_mode half_mode;
109 : 4182599 : unsigned int byte;
110 : 4182599 : rtx mem_op = NULL_RTX;
111 : 4182599 : int mem_num = 0;
112 : :
113 : 4182599 : switch (mode)
114 : : {
115 : : case E_TImode:
116 : : half_mode = DImode;
117 : : break;
118 : 605205 : case E_DImode:
119 : 605205 : half_mode = SImode;
120 : 605205 : break;
121 : 6 : case E_P2HImode:
122 : 6 : half_mode = HImode;
123 : 6 : break;
124 : 30 : case E_P2QImode:
125 : 30 : half_mode = QImode;
126 : 30 : break;
127 : 0 : default:
128 : 0 : gcc_unreachable ();
129 : : }
130 : :
131 : 4182599 : byte = GET_MODE_SIZE (half_mode);
132 : :
133 : 8585545 : while (num--)
134 : : {
135 : 4402946 : rtx op = operands[num];
136 : :
137 : : /* simplify_subreg refuse to split volatile memory addresses,
138 : : but we still have to handle it. */
139 : 4402946 : if (MEM_P (op))
140 : : {
141 : 1731889 : if (mem_op && rtx_equal_p (op, mem_op))
142 : : {
143 : 2444 : lo_half[num] = lo_half[mem_num];
144 : 2444 : hi_half[num] = hi_half[mem_num];
145 : : }
146 : : else
147 : : {
148 : 1729445 : mem_op = op;
149 : 1729445 : mem_num = num;
150 : 1729445 : lo_half[num] = adjust_address (op, half_mode, 0);
151 : 1729445 : hi_half[num] = adjust_address (op, half_mode, byte);
152 : : }
153 : : }
154 : : else
155 : : {
156 : 2671057 : lo_half[num] = simplify_gen_subreg (half_mode, op,
157 : 2671057 : GET_MODE (op) == VOIDmode
158 : : ? mode : GET_MODE (op), 0);
159 : :
160 : 2671057 : rtx tmp = simplify_gen_subreg (half_mode, op,
161 : 2671057 : GET_MODE (op) == VOIDmode
162 : 2671057 : ? mode : GET_MODE (op), byte);
163 : : /* simplify_gen_subreg will return NULL RTX for the
164 : : high half of the paradoxical subreg. */
165 : 2671057 : hi_half[num] = tmp ? tmp : gen_reg_rtx (half_mode);
166 : : }
167 : : }
168 : 4182599 : }
169 : :
170 : : /* Emit the double word assignment DST = { LO, HI }. */
171 : :
172 : : void
173 : 109192 : split_double_concat (machine_mode mode, rtx dst, rtx lo, rtx hi)
174 : : {
175 : 109192 : rtx dlo, dhi;
176 : 109192 : int deleted_move_count = 0;
177 : 109192 : split_double_mode (mode, &dst, 1, &dlo, &dhi);
178 : : /* Constraints ensure that if both lo and hi are MEMs, then
179 : : dst has early-clobber and thus addresses of MEMs don't use
180 : : dlo/dhi registers. Otherwise if at least one of li and hi are MEMs,
181 : : dlo/dhi are registers. */
182 : 109192 : if (MEM_P (lo)
183 : 5651 : && rtx_equal_p (dlo, hi)
184 : 110267 : && reg_overlap_mentioned_p (dhi, lo))
185 : : {
186 : : /* If dlo is same as hi and lo's address uses dhi register,
187 : : code below would first emit_move_insn (dhi, hi)
188 : : and then emit_move_insn (dlo, lo). But the former
189 : : would invalidate lo's address. Load into dhi first,
190 : : then swap. */
191 : 194 : emit_move_insn (dhi, lo);
192 : 194 : lo = dhi;
193 : : }
194 : 108998 : else if (MEM_P (hi)
195 : 9706 : && !MEM_P (lo)
196 : 6959 : && !rtx_equal_p (dlo, lo)
197 : 110580 : && reg_overlap_mentioned_p (dlo, hi))
198 : : {
199 : : /* In this case, code below would first emit_move_insn (dlo, lo)
200 : : and then emit_move_insn (dhi, hi). But the former would
201 : : invalidate hi's address. */
202 : 18 : if (rtx_equal_p (dhi, lo))
203 : : {
204 : : /* We can't load into dhi first, so load into dlo
205 : : first and we'll swap. */
206 : 9 : emit_move_insn (dlo, hi);
207 : 9 : hi = dlo;
208 : : }
209 : : else
210 : : {
211 : : /* Load into dhi first. */
212 : 9 : emit_move_insn (dhi, hi);
213 : 9 : hi = dhi;
214 : : }
215 : : }
216 : 109192 : if (!rtx_equal_p (dlo, hi))
217 : : {
218 : 94426 : if (!rtx_equal_p (dlo, lo))
219 : 42007 : emit_move_insn (dlo, lo);
220 : : else
221 : : deleted_move_count++;
222 : 94426 : if (!rtx_equal_p (dhi, hi))
223 : 87550 : emit_move_insn (dhi, hi);
224 : : else
225 : 6876 : deleted_move_count++;
226 : : }
227 : 14766 : else if (!rtx_equal_p (lo, dhi))
228 : : {
229 : 7434 : if (!rtx_equal_p (dhi, hi))
230 : 7434 : emit_move_insn (dhi, hi);
231 : : else
232 : : deleted_move_count++;
233 : 7434 : if (!rtx_equal_p (dlo, lo))
234 : 7327 : emit_move_insn (dlo, lo);
235 : : else
236 : 107 : deleted_move_count++;
237 : : }
238 : 7332 : else if (mode == TImode)
239 : 7314 : emit_insn (gen_swapdi (dlo, dhi));
240 : : else
241 : 18 : emit_insn (gen_swapsi (dlo, dhi));
242 : :
243 : 109192 : if (deleted_move_count == 2)
244 : 3565 : emit_note (NOTE_INSN_DELETED);
245 : 109192 : }
246 : :
247 : :
248 : : /* Generate either "mov $0, reg" or "xor reg, reg", as appropriate
249 : : for the target. */
250 : :
251 : : void
252 : 110234 : ix86_expand_clear (rtx dest)
253 : : {
254 : 110234 : rtx tmp;
255 : :
256 : : /* We play register width games, which are only valid after reload. */
257 : 110234 : gcc_assert (reload_completed);
258 : :
259 : : /* Avoid HImode and its attendant prefix byte. */
260 : 220468 : if (GET_MODE_SIZE (GET_MODE (dest)) < 4)
261 : 992 : dest = gen_rtx_REG (SImode, REGNO (dest));
262 : 110234 : tmp = gen_rtx_SET (dest, const0_rtx);
263 : :
264 : 110234 : if (!TARGET_USE_MOV0 || optimize_insn_for_size_p ())
265 : : {
266 : 110234 : rtx clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
267 : 110234 : tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, tmp, clob));
268 : : }
269 : :
270 : 110234 : emit_insn (tmp);
271 : 110234 : }
272 : :
273 : : /* Return true if V can be broadcasted from an integer of WIDTH bits
274 : : which is returned in VAL_BROADCAST. Otherwise, return false. */
275 : :
276 : : static bool
277 : 4851 : ix86_broadcast (HOST_WIDE_INT v, unsigned int width,
278 : : HOST_WIDE_INT &val_broadcast)
279 : : {
280 : 4851 : wide_int val = wi::uhwi (v, HOST_BITS_PER_WIDE_INT);
281 : 4851 : val_broadcast = wi::extract_uhwi (val, 0, width);
282 : 6543 : for (unsigned int i = width; i < HOST_BITS_PER_WIDE_INT; i += width)
283 : : {
284 : 5089 : HOST_WIDE_INT each = wi::extract_uhwi (val, i, width);
285 : 5089 : if (val_broadcast != each)
286 : : return false;
287 : : }
288 : 1454 : val_broadcast = sext_hwi (val_broadcast, width);
289 : 1454 : return true;
290 : 4851 : }
291 : :
292 : : /* Convert the CONST_WIDE_INT operand OP to broadcast in MODE. */
293 : :
294 : : rtx
295 : 40061 : ix86_convert_const_wide_int_to_broadcast (machine_mode mode, rtx op)
296 : : {
297 : : /* Don't use integer vector broadcast if we can't move from GPR to SSE
298 : : register directly. */
299 : 40061 : if (!TARGET_INTER_UNIT_MOVES_TO_VEC)
300 : : return nullptr;
301 : :
302 : 40061 : unsigned int msize = GET_MODE_SIZE (mode);
303 : :
304 : : /* Only optimized for vpbroadcast[bwsd]/vbroadcastss with xmm/ymm/zmm. */
305 : 40061 : if (msize != 16 && msize != 32 && msize != 64)
306 : : return nullptr;
307 : :
308 : : /* Convert CONST_WIDE_INT to a non-standard SSE constant integer
309 : : broadcast only if vector broadcast is available. */
310 : 40061 : if (!TARGET_AVX
311 : 1610 : || !CONST_WIDE_INT_P (op)
312 : 1603 : || standard_sse_constant_p (op, mode)
313 : 41664 : || (CONST_WIDE_INT_NUNITS (op) * HOST_BITS_PER_WIDE_INT
314 : 1603 : != GET_MODE_BITSIZE (mode)))
315 : 38466 : return nullptr;
316 : :
317 : 1595 : HOST_WIDE_INT val = CONST_WIDE_INT_ELT (op, 0);
318 : 1595 : HOST_WIDE_INT val_broadcast;
319 : 1595 : scalar_int_mode broadcast_mode;
320 : : /* vpbroadcastb zmm requires TARGET_AVX512BW. */
321 : 712 : if ((msize == 64 ? TARGET_AVX512BW : TARGET_AVX2)
322 : 2089 : && ix86_broadcast (val, GET_MODE_BITSIZE (QImode),
323 : : val_broadcast))
324 : : broadcast_mode = QImode;
325 : 654 : else if ((msize == 64 ? TARGET_AVX512BW : TARGET_AVX2)
326 : 1968 : && ix86_broadcast (val, GET_MODE_BITSIZE (HImode),
327 : : val_broadcast))
328 : : broadcast_mode = HImode;
329 : : /* vbroadcasts[sd] only support memory operand w/o AVX2.
330 : : When msize == 16, pshufs is used for vec_duplicate.
331 : : when msize == 64, vpbroadcastd is used, and TARGET_AVX512F must be existed. */
332 : 412 : else if ((msize != 32 || TARGET_AVX2)
333 : 1768 : && ix86_broadcast (val, GET_MODE_BITSIZE (SImode),
334 : : val_broadcast))
335 : : broadcast_mode = SImode;
336 : 1391 : else if (TARGET_64BIT && (msize != 32 || TARGET_AVX2)
337 : 2641 : && ix86_broadcast (val, GET_MODE_BITSIZE (DImode),
338 : : val_broadcast))
339 : : broadcast_mode = DImode;
340 : : else
341 : 141 : return nullptr;
342 : :
343 : : /* Check if OP can be broadcasted from VAL. */
344 : 1776 : for (int i = 1; i < CONST_WIDE_INT_NUNITS (op); i++)
345 : 1561 : if (val != CONST_WIDE_INT_ELT (op, i))
346 : : return nullptr;
347 : :
348 : 215 : unsigned int nunits = (GET_MODE_SIZE (mode)
349 : 215 : / GET_MODE_SIZE (broadcast_mode));
350 : 215 : machine_mode vector_mode;
351 : 215 : if (!mode_for_vector (broadcast_mode, nunits).exists (&vector_mode))
352 : 0 : gcc_unreachable ();
353 : 215 : rtx target = gen_reg_rtx (vector_mode);
354 : 215 : bool ok = ix86_expand_vector_init_duplicate (false, vector_mode,
355 : : target,
356 : : GEN_INT (val_broadcast));
357 : 215 : if (!ok)
358 : : return nullptr;
359 : 215 : target = lowpart_subreg (mode, target, vector_mode);
360 : 215 : return target;
361 : : }
362 : :
363 : : void
364 : 73944275 : ix86_expand_move (machine_mode mode, rtx operands[])
365 : : {
366 : 73944275 : rtx op0, op1;
367 : 73944275 : rtx tmp, addend = NULL_RTX;
368 : 73944275 : enum tls_model model;
369 : :
370 : 73944275 : op0 = operands[0];
371 : 73944275 : op1 = operands[1];
372 : :
373 : : /* Avoid complex sets of likely spilled hard registers before reload. */
374 : 73944275 : if (!ix86_hardreg_mov_ok (op0, op1))
375 : : {
376 : 141091 : tmp = gen_reg_rtx (mode);
377 : 141091 : operands[0] = tmp;
378 : 141091 : ix86_expand_move (mode, operands);
379 : 141091 : operands[0] = op0;
380 : 141091 : operands[1] = tmp;
381 : 141091 : op1 = tmp;
382 : : }
383 : :
384 : 73944275 : switch (GET_CODE (op1))
385 : : {
386 : 355508 : case CONST:
387 : 355508 : tmp = XEXP (op1, 0);
388 : :
389 : 355508 : if (GET_CODE (tmp) != PLUS
390 : 343847 : || !SYMBOL_REF_P (XEXP (tmp, 0)))
391 : : break;
392 : :
393 : 341188 : op1 = XEXP (tmp, 0);
394 : 341188 : addend = XEXP (tmp, 1);
395 : : /* FALLTHRU */
396 : :
397 : 4923768 : case SYMBOL_REF:
398 : 4923768 : model = SYMBOL_REF_TLS_MODEL (op1);
399 : :
400 : 4923768 : if (model)
401 : 10113 : op1 = legitimize_tls_address (op1, model, true);
402 : 4913655 : else if (ix86_force_load_from_GOT_p (op1))
403 : : {
404 : : /* Load the external function address via GOT slot to avoid PLT. */
405 : 24 : op1 = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op1),
406 : : (TARGET_64BIT
407 : : ? UNSPEC_GOTPCREL
408 : : : UNSPEC_GOT));
409 : 24 : op1 = gen_rtx_CONST (Pmode, op1);
410 : 24 : op1 = gen_const_mem (Pmode, op1);
411 : 20 : set_mem_alias_set (op1, GOT_ALIAS_SET);
412 : : }
413 : : else
414 : : {
415 : : #if TARGET_PECOFF
416 : : tmp = legitimize_pe_coff_symbol (op1, addend != NULL_RTX);
417 : :
418 : : if (tmp)
419 : : {
420 : : op1 = tmp;
421 : : if (!addend)
422 : : break;
423 : : }
424 : : else
425 : : #endif
426 : 4913635 : {
427 : 4913635 : op1 = operands[1];
428 : 4913635 : break;
429 : : }
430 : : }
431 : :
432 : 10133 : if (addend)
433 : : {
434 : 2786 : op1 = force_operand (op1, NULL_RTX);
435 : 2795 : op1 = expand_simple_binop (Pmode, PLUS, op1, addend,
436 : : op0, 1, OPTAB_DIRECT);
437 : : }
438 : : else
439 : 7347 : op1 = force_operand (op1, op0);
440 : :
441 : 10133 : if (op1 == op0)
442 : : return;
443 : :
444 : 1146 : op1 = convert_to_mode (mode, op1, 1);
445 : :
446 : : default:
447 : : break;
448 : :
449 : 1548071 : case SUBREG:
450 : : /* Transform TImode paradoxical SUBREG into zero_extendditi2. */
451 : 1548071 : if (TARGET_64BIT
452 : 1318579 : && mode == TImode
453 : : && SUBREG_P (op1)
454 : 75727 : && GET_MODE (SUBREG_REG (op1)) == DImode
455 : 1595358 : && SUBREG_BYTE (op1) == 0)
456 : 47287 : op1 = gen_rtx_ZERO_EXTEND (TImode, SUBREG_REG (op1));
457 : : /* As not all values in XFmode are representable in real_value,
458 : : we might be called with unfoldable SUBREGs of constants. */
459 : 1548071 : if (mode == XFmode
460 : 3130 : && CONSTANT_P (SUBREG_REG (op1))
461 : 0 : && can_create_pseudo_p ())
462 : : {
463 : 0 : machine_mode imode = GET_MODE (SUBREG_REG (op1));
464 : 0 : rtx r = force_const_mem (imode, SUBREG_REG (op1));
465 : 0 : if (r)
466 : 0 : r = validize_mem (r);
467 : : else
468 : 0 : r = force_reg (imode, SUBREG_REG (op1));
469 : 0 : op1 = simplify_gen_subreg (mode, r, imode, SUBREG_BYTE (op1));
470 : : }
471 : : break;
472 : : }
473 : :
474 : 73935288 : if ((flag_pic || MACHOPIC_INDIRECT)
475 : 73935288 : && symbolic_operand (op1, mode))
476 : : {
477 : : #if TARGET_MACHO
478 : : if (TARGET_MACHO && !TARGET_64BIT)
479 : : {
480 : : /* dynamic-no-pic */
481 : : if (MACHOPIC_INDIRECT)
482 : : {
483 : : tmp = (op0 && REG_P (op0) && mode == Pmode)
484 : : ? op0 : gen_reg_rtx (Pmode);
485 : : op1 = machopic_indirect_data_reference (op1, tmp);
486 : : if (MACHOPIC_PURE)
487 : : op1 = machopic_legitimize_pic_address (op1, mode,
488 : : tmp == op1 ? 0 : tmp);
489 : : }
490 : : if (op0 != op1 && !MEM_P (op0))
491 : : {
492 : : rtx insn = gen_rtx_SET (op0, op1);
493 : : emit_insn (insn);
494 : : return;
495 : : }
496 : : }
497 : : #endif
498 : :
499 : 331866 : if (MEM_P (op0))
500 : 87058 : op1 = force_reg (mode, op1);
501 : 244808 : else if (!(TARGET_64BIT && x86_64_movabs_operand (op1, DImode)))
502 : : {
503 : 244768 : rtx reg = can_create_pseudo_p () ? NULL_RTX : op0;
504 : 244768 : op1 = legitimize_pic_address (op1, reg);
505 : 244768 : if (op0 == op1)
506 : : return;
507 : 244768 : op1 = convert_to_mode (mode, op1, 1);
508 : : }
509 : : }
510 : : else
511 : : {
512 : 73603422 : if (MEM_P (op0)
513 : 100137081 : && (PUSH_ROUNDING (GET_MODE_SIZE (mode)) != GET_MODE_SIZE (mode)
514 : 10708010 : || !push_operand (op0, mode))
515 : 85877335 : && MEM_P (op1))
516 : 2167291 : op1 = force_reg (mode, op1);
517 : :
518 : 73603422 : if (push_operand (op0, mode)
519 : 73603422 : && ! general_no_elim_operand (op1, mode))
520 : 1004 : op1 = copy_to_mode_reg (mode, op1);
521 : :
522 : : /* Force large constants in 64bit compilation into register
523 : : to get them CSEed. */
524 : 73603422 : if (can_create_pseudo_p ()
525 : 67872449 : && (mode == DImode) && TARGET_64BIT
526 : 35273494 : && immediate_operand (op1, mode)
527 : 7926362 : && !x86_64_zext_immediate_operand (op1, VOIDmode)
528 : 703611 : && !register_operand (op0, mode)
529 : 73774234 : && optimize)
530 : 119272 : op1 = copy_to_mode_reg (mode, op1);
531 : :
532 : 73603422 : if (can_create_pseudo_p ())
533 : : {
534 : 67872449 : if (CONST_DOUBLE_P (op1))
535 : : {
536 : : /* If we are loading a floating point constant to a
537 : : register, force the value to memory now, since we'll
538 : : get better code out the back end. */
539 : :
540 : 897894 : op1 = validize_mem (force_const_mem (mode, op1));
541 : 897894 : if (!register_operand (op0, mode))
542 : : {
543 : 129315 : tmp = gen_reg_rtx (mode);
544 : 129315 : emit_insn (gen_rtx_SET (tmp, op1));
545 : 129315 : emit_move_insn (op0, tmp);
546 : 129315 : return;
547 : : }
548 : : }
549 : : }
550 : : }
551 : :
552 : : /* Special case inserting 64-bit values into a TImode register. */
553 : 73805973 : if (TARGET_64BIT
554 : : /* Disable for -O0 (see PR110587) unless naked (PR110533). */
555 : 64114009 : && (optimize || ix86_function_naked (current_function_decl))
556 : 44347425 : && (mode == DImode || mode == DFmode)
557 : 30052891 : && SUBREG_P (op0)
558 : 507193 : && GET_MODE (SUBREG_REG (op0)) == TImode
559 : 419535 : && REG_P (SUBREG_REG (op0))
560 : 74225508 : && REG_P (op1))
561 : : {
562 : : /* Use *insvti_lowpart_1 to set lowpart. */
563 : 194043 : if (SUBREG_BYTE (op0) == 0)
564 : : {
565 : 58866 : wide_int mask = wi::mask (64, true, 128);
566 : 58866 : tmp = immed_wide_int_const (mask, TImode);
567 : 58866 : op0 = SUBREG_REG (op0);
568 : 58866 : tmp = gen_rtx_AND (TImode, copy_rtx (op0), tmp);
569 : 58866 : if (mode == DFmode)
570 : 350 : op1 = gen_lowpart (DImode, op1);
571 : 58866 : op1 = gen_rtx_ZERO_EXTEND (TImode, op1);
572 : 58866 : op1 = gen_rtx_IOR (TImode, tmp, op1);
573 : 58866 : }
574 : : /* Use *insvti_highpart_1 to set highpart. */
575 : 135177 : else if (SUBREG_BYTE (op0) == 8)
576 : : {
577 : 135177 : wide_int mask = wi::mask (64, false, 128);
578 : 135177 : tmp = immed_wide_int_const (mask, TImode);
579 : 135177 : op0 = SUBREG_REG (op0);
580 : 135177 : tmp = gen_rtx_AND (TImode, copy_rtx (op0), tmp);
581 : 135177 : if (mode == DFmode)
582 : 201 : op1 = gen_lowpart (DImode, op1);
583 : 135177 : op1 = gen_rtx_ZERO_EXTEND (TImode, op1);
584 : 135177 : op1 = gen_rtx_ASHIFT (TImode, op1, GEN_INT (64));
585 : 135177 : op1 = gen_rtx_IOR (TImode, tmp, op1);
586 : 135177 : }
587 : : }
588 : :
589 : 73805973 : emit_insn (gen_rtx_SET (op0, op1));
590 : : }
591 : :
592 : : /* OP is a memref of CONST_VECTOR, return scalar constant mem
593 : : if CONST_VECTOR is a vec_duplicate, else return NULL. */
594 : : rtx
595 : 2526343 : ix86_broadcast_from_constant (machine_mode mode, rtx op)
596 : : {
597 : 2526343 : int nunits = GET_MODE_NUNITS (mode);
598 : 2526343 : if (nunits < 2)
599 : : return nullptr;
600 : :
601 : : /* Don't use integer vector broadcast if we can't move from GPR to SSE
602 : : register directly. */
603 : 2368963 : if (!TARGET_INTER_UNIT_MOVES_TO_VEC
604 : 8177 : && INTEGRAL_MODE_P (mode))
605 : : return nullptr;
606 : :
607 : : /* Convert CONST_VECTOR to a non-standard SSE constant integer
608 : : broadcast only if vector broadcast is available. */
609 : 2363401 : if (standard_sse_constant_p (op, mode))
610 : : return nullptr;
611 : :
612 : 4726796 : if (GET_MODE_INNER (mode) == TImode)
613 : : return nullptr;
614 : :
615 : 2363288 : rtx constant = get_pool_constant (XEXP (op, 0));
616 : 2363288 : if (!CONST_VECTOR_P (constant))
617 : : return nullptr;
618 : :
619 : : /* There could be some rtx like
620 : : (mem/u/c:V16QI (symbol_ref/u:DI ("*.LC1")))
621 : : but with "*.LC1" refer to V2DI constant vector. */
622 : 2363288 : if (GET_MODE (constant) != mode)
623 : : {
624 : 605 : constant = simplify_subreg (mode, constant, GET_MODE (constant),
625 : : 0);
626 : 605 : if (constant == nullptr || !CONST_VECTOR_P (constant))
627 : : return nullptr;
628 : : }
629 : :
630 : 2363288 : rtx first = XVECEXP (constant, 0, 0);
631 : :
632 : 8403165 : for (int i = 1; i < nunits; ++i)
633 : : {
634 : 7758339 : rtx tmp = XVECEXP (constant, 0, i);
635 : : /* Vector duplicate value. */
636 : 7758339 : if (!rtx_equal_p (tmp, first))
637 : : return nullptr;
638 : : }
639 : :
640 : : return first;
641 : : }
642 : :
643 : : void
644 : 4751453 : ix86_expand_vector_move (machine_mode mode, rtx operands[])
645 : : {
646 : 4751453 : rtx op0 = operands[0], op1 = operands[1];
647 : : /* Use GET_MODE_BITSIZE instead of GET_MODE_ALIGNMENT for IA MCU
648 : : psABI since the biggest alignment is 4 byte for IA MCU psABI. */
649 : 4751453 : unsigned int align = (TARGET_IAMCU
650 : 4751453 : ? GET_MODE_BITSIZE (mode)
651 : 4751453 : : GET_MODE_ALIGNMENT (mode));
652 : :
653 : 4751453 : if (push_operand (op0, VOIDmode))
654 : 2875 : op0 = emit_move_resolve_push (mode, op0);
655 : :
656 : : /* Force constants other than zero into memory. We do not know how
657 : : the instructions used to build constants modify the upper 64 bits
658 : : of the register, once we have that information we may be able
659 : : to handle some of them more efficiently. */
660 : 4751453 : if (can_create_pseudo_p ()
661 : 4556551 : && (CONSTANT_P (op1)
662 : 4232520 : || (SUBREG_P (op1)
663 : 305919 : && CONSTANT_P (SUBREG_REG (op1))))
664 : 5075498 : && ((register_operand (op0, mode)
665 : 268053 : && !standard_sse_constant_p (op1, mode))
666 : : /* ix86_expand_vector_move_misalign() does not like constants. */
667 : : || (SSE_REG_MODE_P (mode)
668 : 266410 : && MEM_P (op0)
669 : 40083 : && MEM_ALIGN (op0) < align)))
670 : : {
671 : 2031 : if (SUBREG_P (op1))
672 : : {
673 : 14 : machine_mode imode = GET_MODE (SUBREG_REG (op1));
674 : 14 : rtx r = force_const_mem (imode, SUBREG_REG (op1));
675 : 14 : if (r)
676 : 14 : r = validize_mem (r);
677 : : else
678 : 0 : r = force_reg (imode, SUBREG_REG (op1));
679 : 14 : op1 = simplify_gen_subreg (mode, r, imode, SUBREG_BYTE (op1));
680 : : }
681 : : else
682 : : {
683 : 2017 : machine_mode mode = GET_MODE (op0);
684 : 2017 : rtx tmp = ix86_convert_const_wide_int_to_broadcast
685 : 2017 : (mode, op1);
686 : 2017 : if (tmp == nullptr)
687 : 1996 : op1 = validize_mem (force_const_mem (mode, op1));
688 : : else
689 : : op1 = tmp;
690 : : }
691 : : }
692 : :
693 : 4751453 : if (can_create_pseudo_p ()
694 : 4556551 : && GET_MODE_SIZE (mode) >= 16
695 : 3858256 : && VECTOR_MODE_P (mode)
696 : 8394845 : && (MEM_P (op1)
697 : 850624 : && SYMBOL_REF_P (XEXP (op1, 0))
698 : 488387 : && CONSTANT_POOL_ADDRESS_P (XEXP (op1, 0))))
699 : : {
700 : 471857 : rtx first = ix86_broadcast_from_constant (mode, op1);
701 : 471857 : if (first != nullptr)
702 : : {
703 : : /* Broadcast to XMM/YMM/ZMM register from an integer
704 : : constant or scalar mem. */
705 : 119789 : rtx tmp = gen_reg_rtx (mode);
706 : 119789 : if (FLOAT_MODE_P (mode))
707 : 30012 : first = force_const_mem (GET_MODE_INNER (mode), first);
708 : 119789 : bool ok = ix86_expand_vector_init_duplicate (false, mode,
709 : : tmp, first);
710 : 119789 : if (!ok && !TARGET_64BIT && GET_MODE_INNER (mode) == DImode)
711 : : {
712 : 0 : first = force_const_mem (GET_MODE_INNER (mode), first);
713 : 0 : ok = ix86_expand_vector_init_duplicate (false, mode,
714 : : tmp, first);
715 : : }
716 : 119789 : if (ok)
717 : : {
718 : 119789 : emit_move_insn (op0, tmp);
719 : 119789 : return;
720 : : }
721 : : }
722 : : }
723 : :
724 : : /* We need to check memory alignment for SSE mode since attribute
725 : : can make operands unaligned. */
726 : 4631664 : if (can_create_pseudo_p ()
727 : : && SSE_REG_MODE_P (mode)
728 : 9424974 : && ((MEM_P (op0) && (MEM_ALIGN (op0) < align))
729 : 4188216 : || (MEM_P (op1) && (MEM_ALIGN (op1) < align))))
730 : : {
731 : 469687 : rtx tmp[2];
732 : :
733 : : /* ix86_expand_vector_move_misalign() does not like both
734 : : arguments in memory. */
735 : 469687 : if (!register_operand (op0, mode)
736 : 469687 : && !register_operand (op1, mode))
737 : : {
738 : 147301 : rtx scratch = gen_reg_rtx (mode);
739 : 147301 : emit_move_insn (scratch, op1);
740 : 147301 : op1 = scratch;
741 : : }
742 : :
743 : 469687 : tmp[0] = op0; tmp[1] = op1;
744 : 469687 : ix86_expand_vector_move_misalign (mode, tmp);
745 : 469687 : return;
746 : : }
747 : :
748 : : /* Special case TImode to 128-bit vector conversions via V2DI. */
749 : 1135678 : if (VECTOR_MODE_P (mode)
750 : 4110934 : && GET_MODE_SIZE (mode) == 16
751 : 2912723 : && SUBREG_P (op1)
752 : 237406 : && GET_MODE (SUBREG_REG (op1)) == TImode
753 : 3128 : && TARGET_64BIT && TARGET_SSE
754 : 4164450 : && ix86_pre_reload_split ())
755 : : {
756 : 2374 : rtx tmp = gen_reg_rtx (V2DImode);
757 : 2374 : rtx lo = gen_reg_rtx (DImode);
758 : 2374 : rtx hi = gen_reg_rtx (DImode);
759 : 2374 : emit_move_insn (lo, gen_lowpart (DImode, SUBREG_REG (op1)));
760 : 2374 : emit_move_insn (hi, gen_highpart (DImode, SUBREG_REG (op1)));
761 : 2374 : emit_insn (gen_vec_concatv2di (tmp, lo, hi));
762 : 2374 : emit_move_insn (op0, gen_lowpart (mode, tmp));
763 : 2374 : return;
764 : : }
765 : :
766 : : /* If operand0 is a hard register, make operand1 a pseudo. */
767 : 4159603 : if (can_create_pseudo_p ()
768 : 8124304 : && !ix86_hardreg_mov_ok (op0, op1))
769 : : {
770 : 125 : rtx tmp = gen_reg_rtx (GET_MODE (op0));
771 : 125 : emit_move_insn (tmp, op1);
772 : 125 : emit_move_insn (op0, tmp);
773 : 125 : return;
774 : : }
775 : :
776 : : /* Make operand1 a register if it isn't already. */
777 : 4159478 : if (can_create_pseudo_p ()
778 : 3964576 : && !register_operand (op0, mode)
779 : 5288513 : && !register_operand (op1, mode))
780 : : {
781 : 214143 : rtx tmp = gen_reg_rtx (GET_MODE (op0));
782 : 214143 : emit_move_insn (tmp, op1);
783 : 214143 : emit_move_insn (op0, tmp);
784 : 214143 : return;
785 : : }
786 : :
787 : 3945335 : emit_insn (gen_rtx_SET (op0, op1));
788 : : }
789 : :
790 : : /* Split 32-byte AVX unaligned load and store if needed. */
791 : :
792 : : static void
793 : 13352 : ix86_avx256_split_vector_move_misalign (rtx op0, rtx op1)
794 : : {
795 : 13352 : rtx m;
796 : 13352 : rtx (*extract) (rtx, rtx, rtx);
797 : 13352 : machine_mode mode;
798 : :
799 : 13352 : if ((MEM_P (op1) && !TARGET_AVX256_SPLIT_UNALIGNED_LOAD)
800 : 4749 : || (MEM_P (op0) && !TARGET_AVX256_SPLIT_UNALIGNED_STORE))
801 : : {
802 : 13300 : emit_insn (gen_rtx_SET (op0, op1));
803 : 13300 : return;
804 : : }
805 : :
806 : 52 : rtx orig_op0 = NULL_RTX;
807 : 52 : mode = GET_MODE (op0);
808 : 52 : switch (GET_MODE_CLASS (mode))
809 : : {
810 : 35 : case MODE_VECTOR_INT:
811 : 35 : case MODE_INT:
812 : 35 : if (mode != V32QImode)
813 : : {
814 : 7 : if (!MEM_P (op0))
815 : : {
816 : 3 : orig_op0 = op0;
817 : 3 : op0 = gen_reg_rtx (V32QImode);
818 : : }
819 : : else
820 : 4 : op0 = gen_lowpart (V32QImode, op0);
821 : 7 : op1 = gen_lowpart (V32QImode, op1);
822 : 7 : mode = V32QImode;
823 : : }
824 : : break;
825 : : case MODE_VECTOR_FLOAT:
826 : : break;
827 : 0 : default:
828 : 0 : gcc_unreachable ();
829 : : }
830 : :
831 : 52 : switch (mode)
832 : : {
833 : 0 : default:
834 : 0 : gcc_unreachable ();
835 : : case E_V32QImode:
836 : : extract = gen_avx_vextractf128v32qi;
837 : : mode = V16QImode;
838 : : break;
839 : 1 : case E_V16BFmode:
840 : 1 : extract = gen_avx_vextractf128v16bf;
841 : 1 : mode = V8BFmode;
842 : 1 : break;
843 : 0 : case E_V16HFmode:
844 : 0 : extract = gen_avx_vextractf128v16hf;
845 : 0 : mode = V8HFmode;
846 : 0 : break;
847 : 8 : case E_V8SFmode:
848 : 8 : extract = gen_avx_vextractf128v8sf;
849 : 8 : mode = V4SFmode;
850 : 8 : break;
851 : 8 : case E_V4DFmode:
852 : 8 : extract = gen_avx_vextractf128v4df;
853 : 8 : mode = V2DFmode;
854 : 8 : break;
855 : : }
856 : :
857 : 52 : if (MEM_P (op1))
858 : : {
859 : 9 : rtx r = gen_reg_rtx (mode);
860 : 9 : m = adjust_address (op1, mode, 0);
861 : 9 : emit_move_insn (r, m);
862 : 9 : m = adjust_address (op1, mode, 16);
863 : 9 : r = gen_rtx_VEC_CONCAT (GET_MODE (op0), r, m);
864 : 9 : emit_move_insn (op0, r);
865 : : }
866 : 43 : else if (MEM_P (op0))
867 : : {
868 : 43 : m = adjust_address (op0, mode, 0);
869 : 43 : emit_insn (extract (m, op1, const0_rtx));
870 : 43 : m = adjust_address (op0, mode, 16);
871 : 43 : emit_insn (extract (m, copy_rtx (op1), const1_rtx));
872 : : }
873 : : else
874 : 0 : gcc_unreachable ();
875 : :
876 : 52 : if (orig_op0)
877 : 3 : emit_move_insn (orig_op0, gen_lowpart (GET_MODE (orig_op0), op0));
878 : : }
879 : :
880 : : /* Implement the movmisalign patterns for SSE. Non-SSE modes go
881 : : straight to ix86_expand_vector_move. */
882 : : /* Code generation for scalar reg-reg moves of single and double precision data:
883 : : if (x86_sse_partial_reg_dependency == true | x86_sse_split_regs == true)
884 : : movaps reg, reg
885 : : else
886 : : movss reg, reg
887 : : if (x86_sse_partial_reg_dependency == true)
888 : : movapd reg, reg
889 : : else
890 : : movsd reg, reg
891 : :
892 : : Code generation for scalar loads of double precision data:
893 : : if (x86_sse_split_regs == true)
894 : : movlpd mem, reg (gas syntax)
895 : : else
896 : : movsd mem, reg
897 : :
898 : : Code generation for unaligned packed loads of single precision data
899 : : (x86_sse_unaligned_move_optimal overrides x86_sse_partial_reg_dependency):
900 : : if (x86_sse_unaligned_move_optimal)
901 : : movups mem, reg
902 : :
903 : : if (x86_sse_partial_reg_dependency == true)
904 : : {
905 : : xorps reg, reg
906 : : movlps mem, reg
907 : : movhps mem+8, reg
908 : : }
909 : : else
910 : : {
911 : : movlps mem, reg
912 : : movhps mem+8, reg
913 : : }
914 : :
915 : : Code generation for unaligned packed loads of double precision data
916 : : (x86_sse_unaligned_move_optimal overrides x86_sse_split_regs):
917 : : if (x86_sse_unaligned_move_optimal)
918 : : movupd mem, reg
919 : :
920 : : if (x86_sse_split_regs == true)
921 : : {
922 : : movlpd mem, reg
923 : : movhpd mem+8, reg
924 : : }
925 : : else
926 : : {
927 : : movsd mem, reg
928 : : movhpd mem+8, reg
929 : : }
930 : : */
931 : :
932 : : void
933 : 793079 : ix86_expand_vector_move_misalign (machine_mode mode, rtx operands[])
934 : : {
935 : 793079 : rtx op0, op1, m;
936 : :
937 : 793079 : op0 = operands[0];
938 : 793079 : op1 = operands[1];
939 : :
940 : : /* Use unaligned load/store for AVX512 or when optimizing for size. */
941 : 1586158 : if (GET_MODE_SIZE (mode) == 64 || optimize_insn_for_size_p ())
942 : : {
943 : 23216 : emit_insn (gen_rtx_SET (op0, op1));
944 : 23216 : return;
945 : : }
946 : :
947 : 769863 : if (TARGET_AVX)
948 : : {
949 : 62270 : if (GET_MODE_SIZE (mode) == 32)
950 : 13352 : ix86_avx256_split_vector_move_misalign (op0, op1);
951 : : else
952 : : /* Always use 128-bit mov<mode>_internal pattern for AVX. */
953 : 17783 : emit_insn (gen_rtx_SET (op0, op1));
954 : 31135 : return;
955 : : }
956 : :
957 : 738728 : if (TARGET_SSE_UNALIGNED_LOAD_OPTIMAL
958 : 95 : || TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL)
959 : : {
960 : 738633 : emit_insn (gen_rtx_SET (op0, op1));
961 : 738633 : return;
962 : : }
963 : :
964 : : /* ??? If we have typed data, then it would appear that using
965 : : movdqu is the only way to get unaligned data loaded with
966 : : integer type. */
967 : 95 : if (TARGET_SSE2 && GET_MODE_CLASS (mode) == MODE_VECTOR_INT)
968 : : {
969 : 81 : emit_insn (gen_rtx_SET (op0, op1));
970 : 81 : return;
971 : : }
972 : :
973 : 14 : if (MEM_P (op1))
974 : : {
975 : 6 : if (TARGET_SSE2 && mode == V2DFmode)
976 : : {
977 : 2 : rtx zero;
978 : :
979 : : /* When SSE registers are split into halves, we can avoid
980 : : writing to the top half twice. */
981 : 2 : if (TARGET_SSE_SPLIT_REGS)
982 : : {
983 : 2 : emit_clobber (op0);
984 : 2 : zero = op0;
985 : : }
986 : : else
987 : : {
988 : : /* ??? Not sure about the best option for the Intel chips.
989 : : The following would seem to satisfy; the register is
990 : : entirely cleared, breaking the dependency chain. We
991 : : then store to the upper half, with a dependency depth
992 : : of one. A rumor has it that Intel recommends two movsd
993 : : followed by an unpacklpd, but this is unconfirmed. And
994 : : given that the dependency depth of the unpacklpd would
995 : : still be one, I'm not sure why this would be better. */
996 : 0 : zero = CONST0_RTX (V2DFmode);
997 : : }
998 : :
999 : 2 : m = adjust_address (op1, DFmode, 0);
1000 : 2 : emit_insn (gen_sse2_loadlpd (op0, zero, m));
1001 : 2 : m = adjust_address (op1, DFmode, 8);
1002 : 2 : emit_insn (gen_sse2_loadhpd (op0, op0, m));
1003 : 2 : }
1004 : : else
1005 : : {
1006 : 4 : rtx t;
1007 : :
1008 : 4 : if (mode != V4SFmode)
1009 : 0 : t = gen_reg_rtx (V4SFmode);
1010 : : else
1011 : : t = op0;
1012 : :
1013 : 4 : if (TARGET_SSE_PARTIAL_REG_DEPENDENCY)
1014 : 2 : emit_move_insn (t, CONST0_RTX (V4SFmode));
1015 : : else
1016 : 2 : emit_clobber (t);
1017 : :
1018 : 4 : m = adjust_address (op1, V2SFmode, 0);
1019 : 4 : emit_insn (gen_sse_loadlps (t, t, m));
1020 : 4 : m = adjust_address (op1, V2SFmode, 8);
1021 : 4 : emit_insn (gen_sse_loadhps (t, t, m));
1022 : 4 : if (mode != V4SFmode)
1023 : 0 : emit_move_insn (op0, gen_lowpart (mode, t));
1024 : : }
1025 : : }
1026 : 8 : else if (MEM_P (op0))
1027 : : {
1028 : 8 : if (TARGET_SSE2 && mode == V2DFmode)
1029 : : {
1030 : 2 : m = adjust_address (op0, DFmode, 0);
1031 : 2 : emit_insn (gen_sse2_storelpd (m, op1));
1032 : 2 : m = adjust_address (op0, DFmode, 8);
1033 : 2 : emit_insn (gen_sse2_storehpd (m, op1));
1034 : : }
1035 : : else
1036 : : {
1037 : 6 : if (mode != V4SFmode)
1038 : 0 : op1 = gen_lowpart (V4SFmode, op1);
1039 : :
1040 : 6 : m = adjust_address (op0, V2SFmode, 0);
1041 : 6 : emit_insn (gen_sse_storelps (m, op1));
1042 : 6 : m = adjust_address (op0, V2SFmode, 8);
1043 : 6 : emit_insn (gen_sse_storehps (m, copy_rtx (op1)));
1044 : : }
1045 : : }
1046 : : else
1047 : 0 : gcc_unreachable ();
1048 : : }
1049 : :
1050 : : /* Move bits 64:95 to bits 32:63. */
1051 : :
1052 : : void
1053 : 868 : ix86_move_vector_high_sse_to_mmx (rtx op)
1054 : : {
1055 : 868 : rtx mask = gen_rtx_PARALLEL (VOIDmode,
1056 : : gen_rtvec (4, GEN_INT (0), GEN_INT (2),
1057 : : GEN_INT (0), GEN_INT (0)));
1058 : 868 : rtx dest = lowpart_subreg (V4SImode, op, GET_MODE (op));
1059 : 868 : op = gen_rtx_VEC_SELECT (V4SImode, dest, mask);
1060 : 868 : rtx insn = gen_rtx_SET (dest, op);
1061 : 868 : emit_insn (insn);
1062 : 868 : }
1063 : :
1064 : : /* Split MMX pack with signed/unsigned saturation with SSE/SSE2. */
1065 : :
1066 : : void
1067 : 778 : ix86_split_mmx_pack (rtx operands[], enum rtx_code code)
1068 : : {
1069 : 778 : rtx op0 = operands[0];
1070 : 778 : rtx op1 = operands[1];
1071 : 778 : rtx op2 = operands[2];
1072 : 778 : rtx src;
1073 : :
1074 : 778 : machine_mode dmode = GET_MODE (op0);
1075 : 778 : machine_mode smode = GET_MODE (op1);
1076 : 778 : machine_mode inner_dmode = GET_MODE_INNER (dmode);
1077 : 778 : machine_mode inner_smode = GET_MODE_INNER (smode);
1078 : :
1079 : : /* Get the corresponding SSE mode for destination. */
1080 : 778 : int nunits = 16 / GET_MODE_SIZE (inner_dmode);
1081 : 1556 : machine_mode sse_dmode = mode_for_vector (GET_MODE_INNER (dmode),
1082 : 1556 : nunits).require ();
1083 : 778 : machine_mode sse_half_dmode = mode_for_vector (GET_MODE_INNER (dmode),
1084 : 1556 : nunits / 2).require ();
1085 : :
1086 : : /* Get the corresponding SSE mode for source. */
1087 : 778 : nunits = 16 / GET_MODE_SIZE (inner_smode);
1088 : 1556 : machine_mode sse_smode = mode_for_vector (GET_MODE_INNER (smode),
1089 : 1556 : nunits).require ();
1090 : :
1091 : : /* Generate SSE pack with signed/unsigned saturation. */
1092 : 778 : rtx dest = lowpart_subreg (sse_dmode, op0, GET_MODE (op0));
1093 : 778 : op1 = lowpart_subreg (sse_smode, op1, GET_MODE (op1));
1094 : 778 : op2 = lowpart_subreg (sse_smode, op2, GET_MODE (op2));
1095 : :
1096 : : /* paskusdw/packuswb does unsigned saturation of a signed source
1097 : : which is different from generic us_truncate RTX. */
1098 : 778 : if (code == US_TRUNCATE)
1099 : 676 : src = gen_rtx_UNSPEC (sse_dmode,
1100 : : gen_rtvec (2, op1, op2),
1101 : : UNSPEC_US_TRUNCATE);
1102 : : else
1103 : : {
1104 : 102 : op1 = gen_rtx_fmt_e (code, sse_half_dmode, op1);
1105 : 102 : op2 = gen_rtx_fmt_e (code, sse_half_dmode, op2);
1106 : 102 : src = gen_rtx_VEC_CONCAT (sse_dmode, op1, op2);
1107 : : }
1108 : :
1109 : 778 : emit_move_insn (dest, src);
1110 : :
1111 : 778 : ix86_move_vector_high_sse_to_mmx (op0);
1112 : 778 : }
1113 : :
1114 : : /* Split MMX punpcklXX/punpckhXX with SSE punpcklXX. This is also used
1115 : : for a full unpack of OPERANDS[1] and OPERANDS[2] into a wider
1116 : : OPERANDS[0]. */
1117 : :
1118 : : void
1119 : 6036 : ix86_split_mmx_punpck (rtx operands[], bool high_p)
1120 : : {
1121 : 6036 : rtx op0 = operands[0];
1122 : 6036 : rtx op1 = operands[1];
1123 : 6036 : rtx op2 = operands[2];
1124 : 6036 : machine_mode mode = GET_MODE (op1);
1125 : 6036 : rtx mask;
1126 : : /* The corresponding SSE mode. */
1127 : 6036 : machine_mode sse_mode, double_sse_mode;
1128 : :
1129 : 6036 : switch (mode)
1130 : : {
1131 : 1686 : case E_V8QImode:
1132 : 1686 : case E_V4QImode:
1133 : 1686 : case E_V2QImode:
1134 : 1686 : sse_mode = V16QImode;
1135 : 1686 : double_sse_mode = V32QImode;
1136 : 1686 : mask = gen_rtx_PARALLEL (VOIDmode,
1137 : : gen_rtvec (16,
1138 : : GEN_INT (0), GEN_INT (16),
1139 : : GEN_INT (1), GEN_INT (17),
1140 : : GEN_INT (2), GEN_INT (18),
1141 : : GEN_INT (3), GEN_INT (19),
1142 : : GEN_INT (4), GEN_INT (20),
1143 : : GEN_INT (5), GEN_INT (21),
1144 : : GEN_INT (6), GEN_INT (22),
1145 : : GEN_INT (7), GEN_INT (23)));
1146 : 1686 : break;
1147 : :
1148 : 3424 : case E_V4HImode:
1149 : 3424 : case E_V2HImode:
1150 : 3424 : sse_mode = V8HImode;
1151 : 3424 : double_sse_mode = V16HImode;
1152 : 3424 : mask = gen_rtx_PARALLEL (VOIDmode,
1153 : : gen_rtvec (8,
1154 : : GEN_INT (0), GEN_INT (8),
1155 : : GEN_INT (1), GEN_INT (9),
1156 : : GEN_INT (2), GEN_INT (10),
1157 : : GEN_INT (3), GEN_INT (11)));
1158 : 3424 : break;
1159 : :
1160 : 646 : case E_V2SImode:
1161 : 646 : sse_mode = V4SImode;
1162 : 646 : double_sse_mode = V8SImode;
1163 : 646 : mask = gen_rtx_PARALLEL (VOIDmode,
1164 : : gen_rtvec (4,
1165 : : GEN_INT (0), GEN_INT (4),
1166 : : GEN_INT (1), GEN_INT (5)));
1167 : 646 : break;
1168 : :
1169 : 280 : case E_V2SFmode:
1170 : 280 : sse_mode = V4SFmode;
1171 : 280 : double_sse_mode = V8SFmode;
1172 : 280 : mask = gen_rtx_PARALLEL (VOIDmode,
1173 : : gen_rtvec (4,
1174 : : GEN_INT (0), GEN_INT (4),
1175 : : GEN_INT (1), GEN_INT (5)));
1176 : 280 : break;
1177 : :
1178 : 0 : default:
1179 : 0 : gcc_unreachable ();
1180 : : }
1181 : :
1182 : : /* Generate SSE punpcklXX. */
1183 : 6036 : rtx dest = lowpart_subreg (sse_mode, op0, GET_MODE (op0));
1184 : 6036 : op1 = lowpart_subreg (sse_mode, op1, GET_MODE (op1));
1185 : 6036 : op2 = lowpart_subreg (sse_mode, op2, GET_MODE (op2));
1186 : :
1187 : 6036 : op1 = gen_rtx_VEC_CONCAT (double_sse_mode, op1, op2);
1188 : 6036 : op2 = gen_rtx_VEC_SELECT (sse_mode, op1, mask);
1189 : 6036 : rtx insn = gen_rtx_SET (dest, op2);
1190 : 6036 : emit_insn (insn);
1191 : :
1192 : : /* Move high bits to low bits. */
1193 : 6036 : if (high_p)
1194 : : {
1195 : 2516 : if (sse_mode == V4SFmode)
1196 : : {
1197 : 121 : mask = gen_rtx_PARALLEL (VOIDmode,
1198 : : gen_rtvec (4, GEN_INT (2), GEN_INT (3),
1199 : : GEN_INT (4), GEN_INT (5)));
1200 : 121 : op2 = gen_rtx_VEC_CONCAT (V8SFmode, dest, dest);
1201 : 121 : op1 = gen_rtx_VEC_SELECT (V4SFmode, op2, mask);
1202 : : }
1203 : : else
1204 : : {
1205 : 2395 : int sz = GET_MODE_SIZE (mode);
1206 : :
1207 : 2395 : if (sz == 4)
1208 : 256 : mask = gen_rtx_PARALLEL (VOIDmode,
1209 : : gen_rtvec (4, GEN_INT (1), GEN_INT (0),
1210 : : GEN_INT (0), GEN_INT (1)));
1211 : 2139 : else if (sz == 8)
1212 : 2139 : mask = gen_rtx_PARALLEL (VOIDmode,
1213 : : gen_rtvec (4, GEN_INT (2), GEN_INT (3),
1214 : : GEN_INT (0), GEN_INT (1)));
1215 : : else
1216 : 0 : gcc_unreachable ();
1217 : :
1218 : 2395 : dest = lowpart_subreg (V4SImode, dest, GET_MODE (dest));
1219 : 2395 : op1 = gen_rtx_VEC_SELECT (V4SImode, dest, mask);
1220 : : }
1221 : :
1222 : 2516 : insn = gen_rtx_SET (dest, op1);
1223 : 2516 : emit_insn (insn);
1224 : : }
1225 : 6036 : }
1226 : :
1227 : : /* Helper function of ix86_fixup_binary_operands to canonicalize
1228 : : operand order. Returns true if the operands should be swapped. */
1229 : :
1230 : : static bool
1231 : 177920912 : ix86_swap_binary_operands_p (enum rtx_code code, machine_mode mode,
1232 : : rtx operands[])
1233 : : {
1234 : 177920912 : rtx dst = operands[0];
1235 : 177920912 : rtx src1 = operands[1];
1236 : 177920912 : rtx src2 = operands[2];
1237 : :
1238 : : /* If the operation is not commutative, we can't do anything. */
1239 : 177920912 : if (GET_RTX_CLASS (code) != RTX_COMM_ARITH
1240 : 27737513 : && GET_RTX_CLASS (code) != RTX_COMM_COMPARE)
1241 : : return false;
1242 : :
1243 : : /* Highest priority is that src1 should match dst. */
1244 : 150194754 : if (rtx_equal_p (dst, src1))
1245 : : return false;
1246 : 109677655 : if (rtx_equal_p (dst, src2))
1247 : : return true;
1248 : :
1249 : : /* Next highest priority is that immediate constants come second. */
1250 : 109592513 : if (immediate_operand (src2, mode))
1251 : : return false;
1252 : 25772673 : if (immediate_operand (src1, mode))
1253 : : return true;
1254 : :
1255 : : /* Lowest priority is that memory references should come second. */
1256 : 25772673 : if (MEM_P (src2))
1257 : : return false;
1258 : 24348411 : if (MEM_P (src1))
1259 : : return true;
1260 : :
1261 : : return false;
1262 : : }
1263 : :
1264 : : /* Fix up OPERANDS to satisfy ix86_binary_operator_ok. Return the
1265 : : destination to use for the operation. If different from the true
1266 : : destination in operands[0], a copy operation will be required except
1267 : : under TARGET_APX_NDD. */
1268 : :
1269 : : rtx
1270 : 13727773 : ix86_fixup_binary_operands (enum rtx_code code, machine_mode mode,
1271 : : rtx operands[], bool use_ndd)
1272 : : {
1273 : 13727773 : rtx dst = operands[0];
1274 : 13727773 : rtx src1 = operands[1];
1275 : 13727773 : rtx src2 = operands[2];
1276 : :
1277 : : /* Canonicalize operand order. */
1278 : 13727773 : if (ix86_swap_binary_operands_p (code, mode, operands))
1279 : : {
1280 : : /* It is invalid to swap operands of different modes. */
1281 : 88903 : gcc_assert (GET_MODE (src1) == GET_MODE (src2));
1282 : :
1283 : : std::swap (src1, src2);
1284 : : }
1285 : :
1286 : : /* Both source operands cannot be in memory. */
1287 : 13727773 : if (MEM_P (src1) && MEM_P (src2))
1288 : : {
1289 : : /* Optimization: Only read from memory once. */
1290 : 111371 : if (rtx_equal_p (src1, src2))
1291 : : {
1292 : 17 : src2 = force_reg (mode, src2);
1293 : 17 : src1 = src2;
1294 : : }
1295 : 111354 : else if (rtx_equal_p (dst, src1))
1296 : 3277 : src2 = force_reg (mode, src2);
1297 : : else
1298 : 108077 : src1 = force_reg (mode, src1);
1299 : : }
1300 : :
1301 : : /* If the destination is memory, and we do not have matching source
1302 : : operands, do things in registers. */
1303 : 13727773 : if (MEM_P (dst) && !rtx_equal_p (dst, src1))
1304 : 499205 : dst = gen_reg_rtx (mode);
1305 : :
1306 : : /* Source 1 cannot be a constant. */
1307 : 13727773 : if (CONSTANT_P (src1))
1308 : 721 : src1 = force_reg (mode, src1);
1309 : :
1310 : : /* Source 1 cannot be a non-matching memory. */
1311 : 13727773 : if (!use_ndd && MEM_P (src1) && !rtx_equal_p (dst, src1))
1312 : 470345 : src1 = force_reg (mode, src1);
1313 : :
1314 : : /* Improve address combine. */
1315 : 13727773 : if (code == PLUS
1316 : 10022597 : && GET_MODE_CLASS (mode) == MODE_INT
1317 : 9913877 : && MEM_P (src2))
1318 : 177826 : src2 = force_reg (mode, src2);
1319 : :
1320 : 13727773 : operands[1] = src1;
1321 : 13727773 : operands[2] = src2;
1322 : 13727773 : return dst;
1323 : : }
1324 : :
1325 : : /* Similarly, but assume that the destination has already been
1326 : : set up properly. */
1327 : :
1328 : : void
1329 : 287160 : ix86_fixup_binary_operands_no_copy (enum rtx_code code,
1330 : : machine_mode mode, rtx operands[],
1331 : : bool use_ndd)
1332 : : {
1333 : 287160 : rtx dst = ix86_fixup_binary_operands (code, mode, operands, use_ndd);
1334 : 287160 : gcc_assert (dst == operands[0]);
1335 : 287160 : }
1336 : :
1337 : : /* Attempt to expand a binary operator. Make the expansion closer to the
1338 : : actual machine, then just general_operand, which will allow 3 separate
1339 : : memory references (one output, two input) in a single insn. */
1340 : :
1341 : : void
1342 : 13440484 : ix86_expand_binary_operator (enum rtx_code code, machine_mode mode,
1343 : : rtx operands[], bool use_ndd)
1344 : : {
1345 : 13440484 : rtx src1, src2, dst, op, clob;
1346 : :
1347 : 13440484 : dst = ix86_fixup_binary_operands (code, mode, operands, use_ndd);
1348 : 13440484 : src1 = operands[1];
1349 : 13440484 : src2 = operands[2];
1350 : :
1351 : : /* Emit the instruction. */
1352 : :
1353 : 13440484 : op = gen_rtx_SET (dst, gen_rtx_fmt_ee (code, mode, src1, src2));
1354 : :
1355 : 13440484 : if (reload_completed
1356 : 84636 : && code == PLUS
1357 : 904 : && !rtx_equal_p (dst, src1)
1358 : 13440484 : && !use_ndd)
1359 : : {
1360 : : /* This is going to be an LEA; avoid splitting it later. */
1361 : 0 : emit_insn (op);
1362 : : }
1363 : : else
1364 : : {
1365 : 13440484 : clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
1366 : 13440484 : emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, op, clob)));
1367 : : }
1368 : :
1369 : : /* Fix up the destination if needed. */
1370 : 13440484 : if (dst != operands[0])
1371 : 499196 : emit_move_insn (operands[0], dst);
1372 : 13440484 : }
1373 : :
1374 : : /* Expand vector logical operation CODE (AND, IOR, XOR) in MODE with
1375 : : the given OPERANDS. */
1376 : :
1377 : : void
1378 : 82351 : ix86_expand_vector_logical_operator (enum rtx_code code, machine_mode mode,
1379 : : rtx operands[])
1380 : : {
1381 : 82351 : rtx op1 = NULL_RTX, op2 = NULL_RTX;
1382 : 82351 : if (SUBREG_P (operands[1]))
1383 : : {
1384 : 312 : op1 = operands[1];
1385 : 312 : op2 = operands[2];
1386 : : }
1387 : 82039 : else if (SUBREG_P (operands[2]))
1388 : : {
1389 : : op1 = operands[2];
1390 : : op2 = operands[1];
1391 : : }
1392 : : /* Optimize (__m128i) d | (__m128i) e and similar code
1393 : : when d and e are float vectors into float vector logical
1394 : : insn. In C/C++ without using intrinsics there is no other way
1395 : : to express vector logical operation on float vectors than
1396 : : to cast them temporarily to integer vectors. */
1397 : 3069 : if (op1
1398 : 3069 : && !TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL
1399 : 3069 : && (SUBREG_P (op2) || CONST_VECTOR_P (op2))
1400 : 298 : && GET_MODE_CLASS (GET_MODE (SUBREG_REG (op1))) == MODE_VECTOR_FLOAT
1401 : 303 : && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op1))) == GET_MODE_SIZE (mode)
1402 : 101 : && SUBREG_BYTE (op1) == 0
1403 : 101 : && (CONST_VECTOR_P (op2)
1404 : 1 : || (GET_MODE (SUBREG_REG (op1)) == GET_MODE (SUBREG_REG (op2))
1405 : 1 : && SUBREG_BYTE (op2) == 0))
1406 : 101 : && can_create_pseudo_p ())
1407 : : {
1408 : 101 : rtx dst;
1409 : 101 : switch (GET_MODE (SUBREG_REG (op1)))
1410 : : {
1411 : 17 : case E_V4SFmode:
1412 : 17 : case E_V8SFmode:
1413 : 17 : case E_V16SFmode:
1414 : 17 : case E_V2DFmode:
1415 : 17 : case E_V4DFmode:
1416 : 17 : case E_V8DFmode:
1417 : 17 : dst = gen_reg_rtx (GET_MODE (SUBREG_REG (op1)));
1418 : 17 : if (CONST_VECTOR_P (op2))
1419 : : {
1420 : 16 : op2 = gen_lowpart (GET_MODE (dst), op2);
1421 : 16 : op2 = force_reg (GET_MODE (dst), op2);
1422 : : }
1423 : : else
1424 : : {
1425 : 1 : op1 = operands[1];
1426 : 1 : op2 = SUBREG_REG (operands[2]);
1427 : 1 : if (!vector_operand (op2, GET_MODE (dst)))
1428 : 0 : op2 = force_reg (GET_MODE (dst), op2);
1429 : : }
1430 : 17 : op1 = SUBREG_REG (op1);
1431 : 17 : if (!vector_operand (op1, GET_MODE (dst)))
1432 : 0 : op1 = force_reg (GET_MODE (dst), op1);
1433 : 17 : emit_insn (gen_rtx_SET (dst,
1434 : : gen_rtx_fmt_ee (code, GET_MODE (dst),
1435 : : op1, op2)));
1436 : 17 : emit_move_insn (operands[0], gen_lowpart (mode, dst));
1437 : 17 : return;
1438 : : default:
1439 : : break;
1440 : : }
1441 : : }
1442 : 82334 : if (!vector_operand (operands[1], mode))
1443 : 0 : operands[1] = force_reg (mode, operands[1]);
1444 : 82334 : if (!vector_operand (operands[2], mode))
1445 : 11068 : operands[2] = force_reg (mode, operands[2]);
1446 : 82334 : ix86_fixup_binary_operands_no_copy (code, mode, operands);
1447 : 82334 : emit_insn (gen_rtx_SET (operands[0],
1448 : : gen_rtx_fmt_ee (code, mode, operands[1],
1449 : : operands[2])));
1450 : : }
1451 : :
1452 : : /* Return TRUE or FALSE depending on whether the binary operator meets the
1453 : : appropriate constraints. */
1454 : :
1455 : : bool
1456 : 165214692 : ix86_binary_operator_ok (enum rtx_code code, machine_mode mode,
1457 : : rtx operands[3], bool use_ndd)
1458 : : {
1459 : 165214692 : rtx dst = operands[0];
1460 : 165214692 : rtx src1 = operands[1];
1461 : 165214692 : rtx src2 = operands[2];
1462 : :
1463 : : /* Both source operands cannot be in memory. */
1464 : 157307134 : if ((MEM_P (src1) || bcst_mem_operand (src1, mode))
1465 : 165215089 : && (MEM_P (src2) || bcst_mem_operand (src2, mode)))
1466 : 1021553 : return false;
1467 : :
1468 : : /* Canonicalize operand order for commutative operators. */
1469 : 164193139 : if (ix86_swap_binary_operands_p (code, mode, operands))
1470 : 544885 : std::swap (src1, src2);
1471 : :
1472 : : /* If the destination is memory, we must have a matching source operand. */
1473 : 164193139 : if (MEM_P (dst) && !rtx_equal_p (dst, src1))
1474 : : return false;
1475 : :
1476 : : /* Source 1 cannot be a constant. */
1477 : 158909043 : if (CONSTANT_P (src1))
1478 : : return false;
1479 : :
1480 : : /* Source 1 cannot be a non-matching memory. */
1481 : 158905994 : if (!use_ndd && MEM_P (src1) && !rtx_equal_p (dst, src1))
1482 : : /* Support "andhi/andsi/anddi" as a zero-extending move. */
1483 : 4819121 : return (code == AND
1484 : 712727 : && (mode == HImode
1485 : 712727 : || mode == SImode
1486 : 452606 : || (TARGET_64BIT && mode == DImode))
1487 : 5172972 : && satisfies_constraint_L (src2));
1488 : :
1489 : : return true;
1490 : : }
1491 : :
1492 : : /* Attempt to expand a unary operator. Make the expansion closer to the
1493 : : actual machine, then just general_operand, which will allow 2 separate
1494 : : memory references (one output, one input) in a single insn. */
1495 : :
1496 : : void
1497 : 119379 : ix86_expand_unary_operator (enum rtx_code code, machine_mode mode,
1498 : : rtx operands[], bool use_ndd)
1499 : : {
1500 : 119379 : bool matching_memory = false;
1501 : 119379 : rtx src, dst, op, clob;
1502 : :
1503 : 119379 : dst = operands[0];
1504 : 119379 : src = operands[1];
1505 : :
1506 : : /* If the destination is memory, and we do not have matching source
1507 : : operands, do things in registers. */
1508 : 119379 : if (MEM_P (dst))
1509 : : {
1510 : 3236 : if (rtx_equal_p (dst, src))
1511 : : matching_memory = true;
1512 : : else
1513 : 2919 : dst = gen_reg_rtx (mode);
1514 : : }
1515 : :
1516 : : /* When source operand is memory, destination must match. */
1517 : 119379 : if (!use_ndd && MEM_P (src) && !matching_memory)
1518 : 5037 : src = force_reg (mode, src);
1519 : :
1520 : : /* Emit the instruction. */
1521 : :
1522 : 119379 : op = gen_rtx_SET (dst, gen_rtx_fmt_e (code, mode, src));
1523 : :
1524 : 119379 : if (code == NOT)
1525 : 68165 : emit_insn (op);
1526 : : else
1527 : : {
1528 : 51214 : clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
1529 : 51214 : emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, op, clob)));
1530 : : }
1531 : :
1532 : : /* Fix up the destination if needed. */
1533 : 119379 : if (dst != operands[0])
1534 : 2919 : emit_move_insn (operands[0], dst);
1535 : 119379 : }
1536 : :
1537 : : /* Return TRUE or FALSE depending on whether the unary operator meets the
1538 : : appropriate constraints. */
1539 : :
1540 : : bool
1541 : 1746409 : ix86_unary_operator_ok (enum rtx_code,
1542 : : machine_mode,
1543 : : rtx operands[2],
1544 : : bool use_ndd)
1545 : : {
1546 : : /* If one of operands is memory, source and destination must match. */
1547 : 1746409 : if ((MEM_P (operands[0])
1548 : 1703000 : || (!use_ndd && MEM_P (operands[1])))
1549 : 1776497 : && ! rtx_equal_p (operands[0], operands[1]))
1550 : : return false;
1551 : : return true;
1552 : : }
1553 : :
1554 : : /* Predict just emitted jump instruction to be taken with probability PROB. */
1555 : :
1556 : : static void
1557 : 63442 : predict_jump (int prob)
1558 : : {
1559 : 63442 : rtx_insn *insn = get_last_insn ();
1560 : 63442 : gcc_assert (JUMP_P (insn));
1561 : 63442 : add_reg_br_prob_note (insn, profile_probability::from_reg_br_prob_base (prob));
1562 : 63442 : }
1563 : :
1564 : : /* Split 32bit/64bit divmod with 8bit unsigned divmod if dividend and
1565 : : divisor are within the range [0-255]. */
1566 : :
1567 : : void
1568 : 27 : ix86_split_idivmod (machine_mode mode, rtx operands[],
1569 : : bool unsigned_p)
1570 : : {
1571 : 27 : rtx_code_label *end_label, *qimode_label;
1572 : 27 : rtx div, mod;
1573 : 27 : rtx_insn *insn;
1574 : 27 : rtx scratch, tmp0, tmp1, tmp2;
1575 : 27 : rtx (*gen_divmod4_1) (rtx, rtx, rtx, rtx);
1576 : :
1577 : 27 : operands[2] = force_reg (mode, operands[2]);
1578 : 27 : operands[3] = force_reg (mode, operands[3]);
1579 : :
1580 : 27 : switch (mode)
1581 : : {
1582 : 20 : case E_SImode:
1583 : 20 : if (GET_MODE (operands[0]) == SImode)
1584 : : {
1585 : 16 : if (GET_MODE (operands[1]) == SImode)
1586 : 14 : gen_divmod4_1 = unsigned_p ? gen_udivmodsi4_1 : gen_divmodsi4_1;
1587 : : else
1588 : 2 : gen_divmod4_1
1589 : 2 : = unsigned_p ? gen_udivmodsi4_zext_2 : gen_divmodsi4_zext_2;
1590 : : }
1591 : : else
1592 : 4 : gen_divmod4_1
1593 : 4 : = unsigned_p ? gen_udivmodsi4_zext_1 : gen_divmodsi4_zext_1;
1594 : : break;
1595 : :
1596 : 7 : case E_DImode:
1597 : 7 : gen_divmod4_1 = unsigned_p ? gen_udivmoddi4_1 : gen_divmoddi4_1;
1598 : : break;
1599 : :
1600 : 0 : default:
1601 : 0 : gcc_unreachable ();
1602 : : }
1603 : :
1604 : 27 : end_label = gen_label_rtx ();
1605 : 27 : qimode_label = gen_label_rtx ();
1606 : :
1607 : 27 : scratch = gen_reg_rtx (mode);
1608 : :
1609 : : /* Use 8bit unsigned divimod if dividend and divisor are within
1610 : : the range [0-255]. */
1611 : 27 : emit_move_insn (scratch, operands[2]);
1612 : 27 : scratch = expand_simple_binop (mode, IOR, scratch, operands[3],
1613 : : scratch, 1, OPTAB_DIRECT);
1614 : 27 : emit_insn (gen_test_ccno_1 (mode, scratch, GEN_INT (-0x100)));
1615 : 27 : tmp0 = gen_rtx_REG (CCNOmode, FLAGS_REG);
1616 : 27 : tmp0 = gen_rtx_EQ (VOIDmode, tmp0, const0_rtx);
1617 : 27 : tmp0 = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp0,
1618 : : gen_rtx_LABEL_REF (VOIDmode, qimode_label),
1619 : : pc_rtx);
1620 : 27 : insn = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp0));
1621 : 27 : predict_jump (REG_BR_PROB_BASE * 50 / 100);
1622 : 27 : JUMP_LABEL (insn) = qimode_label;
1623 : :
1624 : : /* Generate original signed/unsigned divimod. */
1625 : 27 : emit_insn (gen_divmod4_1 (operands[0], operands[1],
1626 : : operands[2], operands[3]));
1627 : :
1628 : : /* Branch to the end. */
1629 : 27 : emit_jump_insn (gen_jump (end_label));
1630 : 27 : emit_barrier ();
1631 : :
1632 : : /* Generate 8bit unsigned divide. */
1633 : 27 : emit_label (qimode_label);
1634 : : /* Don't use operands[0] for result of 8bit divide since not all
1635 : : registers support QImode ZERO_EXTRACT. */
1636 : 27 : tmp0 = lowpart_subreg (HImode, scratch, mode);
1637 : 27 : tmp1 = lowpart_subreg (HImode, operands[2], mode);
1638 : 27 : tmp2 = lowpart_subreg (QImode, operands[3], mode);
1639 : 27 : emit_insn (gen_udivmodhiqi3 (tmp0, tmp1, tmp2));
1640 : :
1641 : 27 : if (unsigned_p)
1642 : : {
1643 : 12 : div = gen_rtx_UDIV (mode, operands[2], operands[3]);
1644 : 12 : mod = gen_rtx_UMOD (mode, operands[2], operands[3]);
1645 : : }
1646 : : else
1647 : : {
1648 : 15 : div = gen_rtx_DIV (mode, operands[2], operands[3]);
1649 : 15 : mod = gen_rtx_MOD (mode, operands[2], operands[3]);
1650 : : }
1651 : 27 : if (mode == SImode)
1652 : : {
1653 : 20 : if (GET_MODE (operands[0]) != SImode)
1654 : 4 : div = gen_rtx_ZERO_EXTEND (DImode, div);
1655 : 20 : if (GET_MODE (operands[1]) != SImode)
1656 : 2 : mod = gen_rtx_ZERO_EXTEND (DImode, mod);
1657 : : }
1658 : :
1659 : : /* Extract remainder from AH. */
1660 : 27 : scratch = gen_lowpart (GET_MODE (operands[1]), scratch);
1661 : 27 : tmp1 = gen_rtx_ZERO_EXTRACT (GET_MODE (operands[1]), scratch,
1662 : : GEN_INT (8), GEN_INT (8));
1663 : 27 : insn = emit_move_insn (operands[1], tmp1);
1664 : 27 : set_unique_reg_note (insn, REG_EQUAL, mod);
1665 : :
1666 : : /* Zero extend quotient from AL. */
1667 : 27 : tmp1 = gen_lowpart (QImode, tmp0);
1668 : 27 : insn = emit_insn (gen_extend_insn
1669 : 27 : (operands[0], tmp1,
1670 : 27 : GET_MODE (operands[0]), QImode, 1));
1671 : 27 : set_unique_reg_note (insn, REG_EQUAL, div);
1672 : :
1673 : 27 : emit_label (end_label);
1674 : 27 : }
1675 : :
1676 : : /* Emit x86 binary operand CODE in mode MODE, where the first operand
1677 : : matches destination. RTX includes clobber of FLAGS_REG. */
1678 : :
1679 : : void
1680 : 8761 : ix86_emit_binop (enum rtx_code code, machine_mode mode,
1681 : : rtx dst, rtx src)
1682 : : {
1683 : 8761 : rtx op, clob;
1684 : :
1685 : 8761 : op = gen_rtx_SET (dst, gen_rtx_fmt_ee (code, mode, dst, src));
1686 : 8761 : clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
1687 : :
1688 : 8761 : emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, op, clob)));
1689 : 8761 : }
1690 : :
1691 : : /* Return true if regno1 def is nearest to the insn. */
1692 : :
1693 : : static bool
1694 : 15 : find_nearest_reg_def (rtx_insn *insn, int regno1, int regno2)
1695 : : {
1696 : 15 : rtx_insn *prev = insn;
1697 : 15 : rtx_insn *start = BB_HEAD (BLOCK_FOR_INSN (insn));
1698 : :
1699 : 15 : if (insn == start)
1700 : : return false;
1701 : 40 : while (prev && prev != start)
1702 : : {
1703 : 30 : if (!INSN_P (prev) || !NONDEBUG_INSN_P (prev))
1704 : : {
1705 : 10 : prev = PREV_INSN (prev);
1706 : 10 : continue;
1707 : : }
1708 : 20 : if (insn_defines_reg (regno1, INVALID_REGNUM, prev))
1709 : : return true;
1710 : 15 : else if (insn_defines_reg (regno2, INVALID_REGNUM, prev))
1711 : : return false;
1712 : 15 : prev = PREV_INSN (prev);
1713 : : }
1714 : :
1715 : : /* None of the regs is defined in the bb. */
1716 : : return false;
1717 : : }
1718 : :
1719 : : /* INSN_UID of the last insn emitted by zero store peephole2s. */
1720 : : int ix86_last_zero_store_uid;
1721 : :
1722 : : /* Split lea instructions into a sequence of instructions
1723 : : which are executed on ALU to avoid AGU stalls.
1724 : : It is assumed that it is allowed to clobber flags register
1725 : : at lea position. */
1726 : :
1727 : : void
1728 : 6942 : ix86_split_lea_for_addr (rtx_insn *insn, rtx operands[], machine_mode mode)
1729 : : {
1730 : 6942 : unsigned int regno0, regno1, regno2;
1731 : 6942 : struct ix86_address parts;
1732 : 6942 : rtx target, tmp;
1733 : 6942 : int ok, adds;
1734 : :
1735 : 6942 : ok = ix86_decompose_address (operands[1], &parts);
1736 : 6942 : gcc_assert (ok);
1737 : :
1738 : 6942 : target = gen_lowpart (mode, operands[0]);
1739 : :
1740 : 6942 : regno0 = true_regnum (target);
1741 : 6942 : regno1 = INVALID_REGNUM;
1742 : 6942 : regno2 = INVALID_REGNUM;
1743 : :
1744 : 6942 : if (parts.base)
1745 : : {
1746 : 6934 : parts.base = gen_lowpart (mode, parts.base);
1747 : 6934 : regno1 = true_regnum (parts.base);
1748 : : }
1749 : :
1750 : 6942 : if (parts.index)
1751 : : {
1752 : 6939 : parts.index = gen_lowpart (mode, parts.index);
1753 : 6939 : regno2 = true_regnum (parts.index);
1754 : : }
1755 : :
1756 : 6942 : if (parts.disp)
1757 : 234 : parts.disp = gen_lowpart (mode, parts.disp);
1758 : :
1759 : 6942 : if (parts.scale > 1)
1760 : : {
1761 : : /* Case r1 = r1 + ... */
1762 : 11 : if (regno1 == regno0)
1763 : : {
1764 : : /* If we have a case r1 = r1 + C * r2 then we
1765 : : should use multiplication which is very
1766 : : expensive. Assume cost model is wrong if we
1767 : : have such case here. */
1768 : 0 : gcc_assert (regno2 != regno0);
1769 : :
1770 : 0 : for (adds = parts.scale; adds > 0; adds--)
1771 : 0 : ix86_emit_binop (PLUS, mode, target, parts.index);
1772 : : }
1773 : : else
1774 : : {
1775 : : /* r1 = r2 + r3 * C case. Need to move r3 into r1. */
1776 : 11 : if (regno0 != regno2)
1777 : 8 : emit_insn (gen_rtx_SET (target, parts.index));
1778 : :
1779 : : /* Use shift for scaling, but emit it as MULT instead
1780 : : to avoid it being immediately peephole2 optimized back
1781 : : into lea. */
1782 : 11 : ix86_emit_binop (MULT, mode, target, GEN_INT (parts.scale));
1783 : :
1784 : 11 : if (parts.base)
1785 : 3 : ix86_emit_binop (PLUS, mode, target, parts.base);
1786 : :
1787 : 11 : if (parts.disp && parts.disp != const0_rtx)
1788 : 3 : ix86_emit_binop (PLUS, mode, target, parts.disp);
1789 : : }
1790 : : }
1791 : 6931 : else if (!parts.base && !parts.index)
1792 : : {
1793 : 0 : gcc_assert(parts.disp);
1794 : 0 : emit_insn (gen_rtx_SET (target, parts.disp));
1795 : : }
1796 : : else
1797 : : {
1798 : 6931 : if (!parts.base)
1799 : : {
1800 : 0 : if (regno0 != regno2)
1801 : 0 : emit_insn (gen_rtx_SET (target, parts.index));
1802 : : }
1803 : 6931 : else if (!parts.index)
1804 : : {
1805 : 3 : if (regno0 != regno1)
1806 : 1 : emit_insn (gen_rtx_SET (target, parts.base));
1807 : : }
1808 : : else
1809 : : {
1810 : 6928 : if (regno0 == regno1)
1811 : : tmp = parts.index;
1812 : 3333 : else if (regno0 == regno2)
1813 : : tmp = parts.base;
1814 : : else
1815 : : {
1816 : 15 : rtx tmp1;
1817 : :
1818 : : /* Find better operand for SET instruction, depending
1819 : : on which definition is farther from the insn. */
1820 : 15 : if (find_nearest_reg_def (insn, regno1, regno2))
1821 : 5 : tmp = parts.index, tmp1 = parts.base;
1822 : : else
1823 : 10 : tmp = parts.base, tmp1 = parts.index;
1824 : :
1825 : 15 : emit_insn (gen_rtx_SET (target, tmp));
1826 : :
1827 : 15 : if (parts.disp && parts.disp != const0_rtx)
1828 : 0 : ix86_emit_binop (PLUS, mode, target, parts.disp);
1829 : :
1830 : 15 : ix86_emit_binop (PLUS, mode, target, tmp1);
1831 : 15 : return;
1832 : : }
1833 : :
1834 : 6913 : ix86_emit_binop (PLUS, mode, target, tmp);
1835 : : }
1836 : :
1837 : 6916 : if (parts.disp && parts.disp != const0_rtx)
1838 : 4 : ix86_emit_binop (PLUS, mode, target, parts.disp);
1839 : : }
1840 : : }
1841 : :
1842 : : /* Post-reload splitter for converting an SF or DFmode value in an
1843 : : SSE register into an unsigned SImode. */
1844 : :
1845 : : void
1846 : 0 : ix86_split_convert_uns_si_sse (rtx operands[])
1847 : : {
1848 : 0 : machine_mode vecmode;
1849 : 0 : rtx value, large, zero_or_two31, input, two31, x;
1850 : :
1851 : 0 : large = operands[1];
1852 : 0 : zero_or_two31 = operands[2];
1853 : 0 : input = operands[3];
1854 : 0 : two31 = operands[4];
1855 : 0 : vecmode = GET_MODE (large);
1856 : 0 : value = gen_rtx_REG (vecmode, REGNO (operands[0]));
1857 : :
1858 : : /* Load up the value into the low element. We must ensure that the other
1859 : : elements are valid floats -- zero is the easiest such value. */
1860 : 0 : if (MEM_P (input))
1861 : : {
1862 : 0 : if (vecmode == V4SFmode)
1863 : 0 : emit_insn (gen_vec_setv4sf_0 (value, CONST0_RTX (V4SFmode), input));
1864 : : else
1865 : 0 : emit_insn (gen_sse2_loadlpd (value, CONST0_RTX (V2DFmode), input));
1866 : : }
1867 : : else
1868 : : {
1869 : 0 : input = gen_rtx_REG (vecmode, REGNO (input));
1870 : 0 : emit_move_insn (value, CONST0_RTX (vecmode));
1871 : 0 : if (vecmode == V4SFmode)
1872 : 0 : emit_insn (gen_sse_movss_v4sf (value, value, input));
1873 : : else
1874 : 0 : emit_insn (gen_sse2_movsd_v2df (value, value, input));
1875 : : }
1876 : :
1877 : 0 : emit_move_insn (large, two31);
1878 : 0 : emit_move_insn (zero_or_two31, MEM_P (two31) ? large : two31);
1879 : :
1880 : 0 : x = gen_rtx_fmt_ee (LE, vecmode, large, value);
1881 : 0 : emit_insn (gen_rtx_SET (large, x));
1882 : :
1883 : 0 : x = gen_rtx_AND (vecmode, zero_or_two31, large);
1884 : 0 : emit_insn (gen_rtx_SET (zero_or_two31, x));
1885 : :
1886 : 0 : x = gen_rtx_MINUS (vecmode, value, zero_or_two31);
1887 : 0 : emit_insn (gen_rtx_SET (value, x));
1888 : :
1889 : 0 : large = gen_rtx_REG (V4SImode, REGNO (large));
1890 : 0 : emit_insn (gen_ashlv4si3 (large, large, GEN_INT (31)));
1891 : :
1892 : 0 : x = gen_rtx_REG (V4SImode, REGNO (value));
1893 : 0 : if (vecmode == V4SFmode)
1894 : 0 : emit_insn (gen_fix_truncv4sfv4si2 (x, value));
1895 : : else
1896 : 0 : emit_insn (gen_sse2_cvttpd2dq (x, value));
1897 : 0 : value = x;
1898 : :
1899 : 0 : emit_insn (gen_xorv4si3 (value, value, large));
1900 : 0 : }
1901 : :
1902 : : /* Convert an unsigned DImode value into a DFmode, using only SSE.
1903 : : Expects the 64-bit DImode to be supplied in a pair of integral
1904 : : registers. Requires SSE2; will use SSE3 if available. For x86_32,
1905 : : -mfpmath=sse, !optimize_size only. */
1906 : :
1907 : : void
1908 : 0 : ix86_expand_convert_uns_didf_sse (rtx target, rtx input)
1909 : : {
1910 : 0 : REAL_VALUE_TYPE bias_lo_rvt, bias_hi_rvt;
1911 : 0 : rtx int_xmm, fp_xmm;
1912 : 0 : rtx biases, exponents;
1913 : 0 : rtx x;
1914 : :
1915 : 0 : int_xmm = gen_reg_rtx (V4SImode);
1916 : 0 : if (TARGET_INTER_UNIT_MOVES_TO_VEC)
1917 : 0 : emit_insn (gen_movdi_to_sse (int_xmm, input));
1918 : 0 : else if (TARGET_SSE_SPLIT_REGS)
1919 : : {
1920 : 0 : emit_clobber (int_xmm);
1921 : 0 : emit_move_insn (gen_lowpart (DImode, int_xmm), input);
1922 : : }
1923 : : else
1924 : : {
1925 : 0 : x = gen_reg_rtx (V2DImode);
1926 : 0 : ix86_expand_vector_init_one_nonzero (false, V2DImode, x, input, 0);
1927 : 0 : emit_move_insn (int_xmm, gen_lowpart (V4SImode, x));
1928 : : }
1929 : :
1930 : 0 : x = gen_rtx_CONST_VECTOR (V4SImode,
1931 : : gen_rtvec (4, GEN_INT (0x43300000UL),
1932 : : GEN_INT (0x45300000UL),
1933 : : const0_rtx, const0_rtx));
1934 : 0 : exponents = validize_mem (force_const_mem (V4SImode, x));
1935 : :
1936 : : /* int_xmm = {0x45300000UL, fp_xmm/hi, 0x43300000, fp_xmm/lo } */
1937 : 0 : emit_insn (gen_vec_interleave_lowv4si (int_xmm, int_xmm, exponents));
1938 : :
1939 : : /* Concatenating (juxtaposing) (0x43300000UL ## fp_value_low_xmm)
1940 : : yields a valid DF value equal to (0x1.0p52 + double(fp_value_lo_xmm)).
1941 : : Similarly (0x45300000UL ## fp_value_hi_xmm) yields
1942 : : (0x1.0p84 + double(fp_value_hi_xmm)).
1943 : : Note these exponents differ by 32. */
1944 : :
1945 : 0 : fp_xmm = copy_to_mode_reg (V2DFmode, gen_lowpart (V2DFmode, int_xmm));
1946 : :
1947 : : /* Subtract off those 0x1.0p52 and 0x1.0p84 biases, to produce values
1948 : : in [0,2**32-1] and [0]+[2**32,2**64-1] respectively. */
1949 : 0 : real_ldexp (&bias_lo_rvt, &dconst1, 52);
1950 : 0 : real_ldexp (&bias_hi_rvt, &dconst1, 84);
1951 : 0 : biases = const_double_from_real_value (bias_lo_rvt, DFmode);
1952 : 0 : x = const_double_from_real_value (bias_hi_rvt, DFmode);
1953 : 0 : biases = gen_rtx_CONST_VECTOR (V2DFmode, gen_rtvec (2, biases, x));
1954 : 0 : biases = validize_mem (force_const_mem (V2DFmode, biases));
1955 : 0 : emit_insn (gen_subv2df3 (fp_xmm, fp_xmm, biases));
1956 : :
1957 : : /* Add the upper and lower DFmode values together. */
1958 : 0 : if (TARGET_SSE3)
1959 : 0 : emit_insn (gen_sse3_haddv2df3 (fp_xmm, fp_xmm, fp_xmm));
1960 : : else
1961 : : {
1962 : 0 : x = copy_to_mode_reg (V2DFmode, fp_xmm);
1963 : 0 : emit_insn (gen_vec_interleave_highv2df (fp_xmm, fp_xmm, fp_xmm));
1964 : 0 : emit_insn (gen_addv2df3 (fp_xmm, fp_xmm, x));
1965 : : }
1966 : :
1967 : 0 : ix86_expand_vector_extract (false, target, fp_xmm, 0);
1968 : 0 : }
1969 : :
1970 : : /* Not used, but eases macroization of patterns. */
1971 : : void
1972 : 0 : ix86_expand_convert_uns_sixf_sse (rtx, rtx)
1973 : : {
1974 : 0 : gcc_unreachable ();
1975 : : }
1976 : :
1977 : : static rtx ix86_expand_sse_fabs (rtx op0, rtx *smask);
1978 : :
1979 : : /* Convert an unsigned SImode value into a DFmode. Only currently used
1980 : : for SSE, but applicable anywhere. */
1981 : :
1982 : : void
1983 : 0 : ix86_expand_convert_uns_sidf_sse (rtx target, rtx input)
1984 : : {
1985 : 0 : REAL_VALUE_TYPE TWO31r;
1986 : 0 : rtx x, fp;
1987 : :
1988 : 0 : x = expand_simple_binop (SImode, PLUS, input, GEN_INT (-2147483647 - 1),
1989 : : NULL, 1, OPTAB_DIRECT);
1990 : :
1991 : 0 : fp = gen_reg_rtx (DFmode);
1992 : 0 : emit_insn (gen_floatsidf2 (fp, x));
1993 : :
1994 : 0 : real_ldexp (&TWO31r, &dconst1, 31);
1995 : 0 : x = const_double_from_real_value (TWO31r, DFmode);
1996 : :
1997 : 0 : x = expand_simple_binop (DFmode, PLUS, fp, x, target, 0, OPTAB_DIRECT);
1998 : :
1999 : : /* Remove the sign with FE_DOWNWARD, where x - x = -0.0. */
2000 : 0 : if (HONOR_SIGNED_ZEROS (DFmode) && flag_rounding_math)
2001 : 0 : x = ix86_expand_sse_fabs (x, NULL);
2002 : :
2003 : 0 : if (x != target)
2004 : 0 : emit_move_insn (target, x);
2005 : 0 : }
2006 : :
2007 : : /* Convert a signed DImode value into a DFmode. Only used for SSE in
2008 : : 32-bit mode; otherwise we have a direct convert instruction. */
2009 : :
2010 : : void
2011 : 0 : ix86_expand_convert_sign_didf_sse (rtx target, rtx input)
2012 : : {
2013 : 0 : REAL_VALUE_TYPE TWO32r;
2014 : 0 : rtx fp_lo, fp_hi, x;
2015 : :
2016 : 0 : fp_lo = gen_reg_rtx (DFmode);
2017 : 0 : fp_hi = gen_reg_rtx (DFmode);
2018 : :
2019 : 0 : emit_insn (gen_floatsidf2 (fp_hi, gen_highpart (SImode, input)));
2020 : :
2021 : 0 : real_ldexp (&TWO32r, &dconst1, 32);
2022 : 0 : x = const_double_from_real_value (TWO32r, DFmode);
2023 : 0 : fp_hi = expand_simple_binop (DFmode, MULT, fp_hi, x, fp_hi, 0, OPTAB_DIRECT);
2024 : :
2025 : 0 : ix86_expand_convert_uns_sidf_sse (fp_lo, gen_lowpart (SImode, input));
2026 : :
2027 : 0 : x = expand_simple_binop (DFmode, PLUS, fp_hi, fp_lo, target,
2028 : : 0, OPTAB_DIRECT);
2029 : 0 : if (x != target)
2030 : 0 : emit_move_insn (target, x);
2031 : 0 : }
2032 : :
2033 : : /* Convert an unsigned SImode value into a SFmode, using only SSE.
2034 : : For x86_32, -mfpmath=sse, !optimize_size only. */
2035 : : void
2036 : 0 : ix86_expand_convert_uns_sisf_sse (rtx target, rtx input)
2037 : : {
2038 : 0 : REAL_VALUE_TYPE ONE16r;
2039 : 0 : rtx fp_hi, fp_lo, int_hi, int_lo, x;
2040 : :
2041 : 0 : real_ldexp (&ONE16r, &dconst1, 16);
2042 : 0 : x = const_double_from_real_value (ONE16r, SFmode);
2043 : 0 : int_lo = expand_simple_binop (SImode, AND, input, GEN_INT(0xffff),
2044 : : NULL, 0, OPTAB_DIRECT);
2045 : 0 : int_hi = expand_simple_binop (SImode, LSHIFTRT, input, GEN_INT(16),
2046 : : NULL, 0, OPTAB_DIRECT);
2047 : 0 : fp_hi = gen_reg_rtx (SFmode);
2048 : 0 : fp_lo = gen_reg_rtx (SFmode);
2049 : 0 : emit_insn (gen_floatsisf2 (fp_hi, int_hi));
2050 : 0 : emit_insn (gen_floatsisf2 (fp_lo, int_lo));
2051 : 0 : if (TARGET_FMA)
2052 : : {
2053 : 0 : x = validize_mem (force_const_mem (SFmode, x));
2054 : 0 : fp_hi = gen_rtx_FMA (SFmode, fp_hi, x, fp_lo);
2055 : 0 : emit_move_insn (target, fp_hi);
2056 : : }
2057 : : else
2058 : : {
2059 : 0 : fp_hi = expand_simple_binop (SFmode, MULT, fp_hi, x, fp_hi,
2060 : : 0, OPTAB_DIRECT);
2061 : 0 : fp_hi = expand_simple_binop (SFmode, PLUS, fp_hi, fp_lo, target,
2062 : : 0, OPTAB_DIRECT);
2063 : 0 : if (!rtx_equal_p (target, fp_hi))
2064 : 0 : emit_move_insn (target, fp_hi);
2065 : : }
2066 : 0 : }
2067 : :
2068 : : /* floatunsv{4,8}siv{4,8}sf2 expander. Expand code to convert
2069 : : a vector of unsigned ints VAL to vector of floats TARGET. */
2070 : :
2071 : : void
2072 : 54 : ix86_expand_vector_convert_uns_vsivsf (rtx target, rtx val)
2073 : : {
2074 : 54 : rtx tmp[8];
2075 : 54 : REAL_VALUE_TYPE TWO16r;
2076 : 54 : machine_mode intmode = GET_MODE (val);
2077 : 54 : machine_mode fltmode = GET_MODE (target);
2078 : 54 : rtx (*cvt) (rtx, rtx);
2079 : :
2080 : 54 : if (intmode == V4SImode)
2081 : : cvt = gen_floatv4siv4sf2;
2082 : : else
2083 : 2 : cvt = gen_floatv8siv8sf2;
2084 : 54 : tmp[0] = ix86_build_const_vector (intmode, 1, GEN_INT (0xffff));
2085 : 54 : tmp[0] = force_reg (intmode, tmp[0]);
2086 : 54 : tmp[1] = expand_simple_binop (intmode, AND, val, tmp[0], NULL_RTX, 1,
2087 : : OPTAB_DIRECT);
2088 : 54 : tmp[2] = expand_simple_binop (intmode, LSHIFTRT, val, GEN_INT (16),
2089 : : NULL_RTX, 1, OPTAB_DIRECT);
2090 : 54 : tmp[3] = gen_reg_rtx (fltmode);
2091 : 54 : emit_insn (cvt (tmp[3], tmp[1]));
2092 : 54 : tmp[4] = gen_reg_rtx (fltmode);
2093 : 54 : emit_insn (cvt (tmp[4], tmp[2]));
2094 : 54 : real_ldexp (&TWO16r, &dconst1, 16);
2095 : 54 : tmp[5] = const_double_from_real_value (TWO16r, SFmode);
2096 : 54 : tmp[5] = force_reg (fltmode, ix86_build_const_vector (fltmode, 1, tmp[5]));
2097 : 54 : if (TARGET_FMA)
2098 : : {
2099 : 1 : tmp[6] = gen_rtx_FMA (fltmode, tmp[4], tmp[5], tmp[3]);
2100 : 1 : emit_move_insn (target, tmp[6]);
2101 : : }
2102 : : else
2103 : : {
2104 : 53 : tmp[6] = expand_simple_binop (fltmode, MULT, tmp[4], tmp[5],
2105 : : NULL_RTX, 1, OPTAB_DIRECT);
2106 : 53 : tmp[7] = expand_simple_binop (fltmode, PLUS, tmp[3], tmp[6],
2107 : : target, 1, OPTAB_DIRECT);
2108 : 53 : if (tmp[7] != target)
2109 : 0 : emit_move_insn (target, tmp[7]);
2110 : : }
2111 : 54 : }
2112 : :
2113 : : /* Adjust a V*SFmode/V*DFmode value VAL so that *sfix_trunc* resp. fix_trunc*
2114 : : pattern can be used on it instead of fixuns_trunc*.
2115 : : This is done by doing just signed conversion if < 0x1p31, and otherwise by
2116 : : subtracting 0x1p31 first and xoring in 0x80000000 from *XORP afterwards. */
2117 : :
2118 : : rtx
2119 : 264 : ix86_expand_adjust_ufix_to_sfix_si (rtx val, rtx *xorp)
2120 : : {
2121 : 264 : REAL_VALUE_TYPE TWO31r;
2122 : 264 : rtx two31r, tmp[4];
2123 : 264 : machine_mode mode = GET_MODE (val);
2124 : 264 : machine_mode scalarmode = GET_MODE_INNER (mode);
2125 : 528 : machine_mode intmode = GET_MODE_SIZE (mode) == 32 ? V8SImode : V4SImode;
2126 : 264 : rtx (*cmp) (rtx, rtx, rtx, rtx);
2127 : 264 : int i;
2128 : :
2129 : 1056 : for (i = 0; i < 3; i++)
2130 : 792 : tmp[i] = gen_reg_rtx (mode);
2131 : 264 : real_ldexp (&TWO31r, &dconst1, 31);
2132 : 264 : two31r = const_double_from_real_value (TWO31r, scalarmode);
2133 : 264 : two31r = ix86_build_const_vector (mode, 1, two31r);
2134 : 264 : two31r = force_reg (mode, two31r);
2135 : 264 : switch (mode)
2136 : : {
2137 : : case E_V8SFmode: cmp = gen_avx_maskcmpv8sf3; break;
2138 : 10 : case E_V4SFmode: cmp = gen_sse_maskcmpv4sf3; break;
2139 : 16 : case E_V4DFmode: cmp = gen_avx_maskcmpv4df3; break;
2140 : 238 : case E_V2DFmode: cmp = gen_sse2_maskcmpv2df3; break;
2141 : 0 : default: gcc_unreachable ();
2142 : : }
2143 : 264 : tmp[3] = gen_rtx_LE (mode, two31r, val);
2144 : 264 : emit_insn (cmp (tmp[0], two31r, val, tmp[3]));
2145 : 264 : tmp[1] = expand_simple_binop (mode, AND, tmp[0], two31r, tmp[1],
2146 : : 0, OPTAB_DIRECT);
2147 : 264 : if (intmode == V4SImode || TARGET_AVX2)
2148 : 528 : *xorp = expand_simple_binop (intmode, ASHIFT,
2149 : 264 : gen_lowpart (intmode, tmp[0]),
2150 : : GEN_INT (31), NULL_RTX, 0,
2151 : : OPTAB_DIRECT);
2152 : : else
2153 : : {
2154 : 0 : rtx two31 = gen_int_mode (HOST_WIDE_INT_1U << 31, SImode);
2155 : 0 : two31 = ix86_build_const_vector (intmode, 1, two31);
2156 : 0 : *xorp = expand_simple_binop (intmode, AND,
2157 : 0 : gen_lowpart (intmode, tmp[0]),
2158 : : two31, NULL_RTX, 0,
2159 : : OPTAB_DIRECT);
2160 : : }
2161 : 264 : return expand_simple_binop (mode, MINUS, val, tmp[1], tmp[2],
2162 : 264 : 0, OPTAB_DIRECT);
2163 : : }
2164 : :
2165 : : /* Generate code for floating point ABS or NEG. */
2166 : :
2167 : : void
2168 : 34817 : ix86_expand_fp_absneg_operator (enum rtx_code code, machine_mode mode,
2169 : : rtx operands[])
2170 : : {
2171 : 34817 : rtx set, dst, src;
2172 : 34817 : bool use_sse = false;
2173 : 34817 : bool vector_mode = VECTOR_MODE_P (mode);
2174 : 34817 : machine_mode vmode = mode;
2175 : 34817 : rtvec par;
2176 : :
2177 : 34817 : switch (mode)
2178 : : {
2179 : : case E_HFmode:
2180 : : use_sse = true;
2181 : : vmode = V8HFmode;
2182 : : break;
2183 : 0 : case E_BFmode:
2184 : 0 : use_sse = true;
2185 : 0 : vmode = V8BFmode;
2186 : 0 : break;
2187 : 9968 : case E_SFmode:
2188 : 9968 : use_sse = TARGET_SSE_MATH && TARGET_SSE;
2189 : : vmode = V4SFmode;
2190 : : break;
2191 : 15579 : case E_DFmode:
2192 : 15579 : use_sse = TARGET_SSE_MATH && TARGET_SSE2;
2193 : : vmode = V2DFmode;
2194 : : break;
2195 : 9071 : default:
2196 : 9071 : use_sse = vector_mode || mode == TFmode;
2197 : 9071 : break;
2198 : : }
2199 : :
2200 : 34817 : dst = operands[0];
2201 : 34817 : src = operands[1];
2202 : :
2203 : 34817 : set = gen_rtx_fmt_e (code, mode, src);
2204 : 34817 : set = gen_rtx_SET (dst, set);
2205 : :
2206 : 34817 : if (use_sse)
2207 : : {
2208 : 29198 : rtx mask, use, clob;
2209 : :
2210 : : /* NEG and ABS performed with SSE use bitwise mask operations.
2211 : : Create the appropriate mask now. */
2212 : 29198 : mask = ix86_build_signbit_mask (vmode, vector_mode, code == ABS);
2213 : 29198 : use = gen_rtx_USE (VOIDmode, mask);
2214 : 29198 : if (vector_mode || mode == TFmode)
2215 : 4801 : par = gen_rtvec (2, set, use);
2216 : : else
2217 : : {
2218 : 24397 : clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
2219 : 24397 : par = gen_rtvec (3, set, use, clob);
2220 : : }
2221 : : }
2222 : : else
2223 : : {
2224 : 5619 : rtx clob;
2225 : :
2226 : : /* Changing of sign for FP values is doable using integer unit too. */
2227 : 5619 : clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
2228 : 5619 : par = gen_rtvec (2, set, clob);
2229 : : }
2230 : :
2231 : 34817 : emit_insn (gen_rtx_PARALLEL (VOIDmode, par));
2232 : 34817 : }
2233 : :
2234 : : /* Deconstruct a floating point ABS or NEG operation
2235 : : with integer registers into integer operations. */
2236 : :
2237 : : void
2238 : 24 : ix86_split_fp_absneg_operator (enum rtx_code code, machine_mode mode,
2239 : : rtx operands[])
2240 : : {
2241 : 24 : enum rtx_code absneg_op;
2242 : 24 : rtx dst, set;
2243 : :
2244 : 24 : gcc_assert (operands_match_p (operands[0], operands[1]));
2245 : :
2246 : 24 : switch (mode)
2247 : : {
2248 : 0 : case E_SFmode:
2249 : 0 : dst = gen_lowpart (SImode, operands[0]);
2250 : :
2251 : 0 : if (code == ABS)
2252 : : {
2253 : 0 : set = gen_int_mode (0x7fffffff, SImode);
2254 : 0 : absneg_op = AND;
2255 : : }
2256 : : else
2257 : : {
2258 : 0 : set = gen_int_mode (0x80000000, SImode);
2259 : 0 : absneg_op = XOR;
2260 : : }
2261 : 0 : set = gen_rtx_fmt_ee (absneg_op, SImode, dst, set);
2262 : 0 : break;
2263 : :
2264 : 1 : case E_DFmode:
2265 : 1 : if (TARGET_64BIT)
2266 : : {
2267 : 1 : dst = gen_lowpart (DImode, operands[0]);
2268 : 1 : dst = gen_rtx_ZERO_EXTRACT (DImode, dst, const1_rtx, GEN_INT (63));
2269 : :
2270 : 1 : if (code == ABS)
2271 : 0 : set = const0_rtx;
2272 : : else
2273 : 1 : set = gen_rtx_NOT (DImode, dst);
2274 : : }
2275 : : else
2276 : : {
2277 : 0 : dst = gen_highpart (SImode, operands[0]);
2278 : :
2279 : 0 : if (code == ABS)
2280 : : {
2281 : 0 : set = gen_int_mode (0x7fffffff, SImode);
2282 : 0 : absneg_op = AND;
2283 : : }
2284 : : else
2285 : : {
2286 : 0 : set = gen_int_mode (0x80000000, SImode);
2287 : 0 : absneg_op = XOR;
2288 : : }
2289 : 0 : set = gen_rtx_fmt_ee (absneg_op, SImode, dst, set);
2290 : : }
2291 : : break;
2292 : :
2293 : 23 : case E_XFmode:
2294 : 23 : dst = gen_rtx_REG (SImode,
2295 : 23 : REGNO (operands[0]) + (TARGET_64BIT ? 1 : 2));
2296 : 23 : if (code == ABS)
2297 : : {
2298 : 1 : set = GEN_INT (0x7fff);
2299 : 1 : absneg_op = AND;
2300 : : }
2301 : : else
2302 : : {
2303 : 22 : set = GEN_INT (0x8000);
2304 : 22 : absneg_op = XOR;
2305 : : }
2306 : 23 : set = gen_rtx_fmt_ee (absneg_op, SImode, dst, set);
2307 : 23 : break;
2308 : :
2309 : 0 : default:
2310 : 0 : gcc_unreachable ();
2311 : : }
2312 : :
2313 : 24 : set = gen_rtx_SET (dst, set);
2314 : :
2315 : 24 : rtx clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
2316 : 24 : rtvec par = gen_rtvec (2, set, clob);
2317 : :
2318 : 24 : emit_insn (gen_rtx_PARALLEL (VOIDmode, par));
2319 : 24 : }
2320 : :
2321 : : /* Expand a copysign operation. Special case operand 0 being a constant. */
2322 : :
2323 : : void
2324 : 23248 : ix86_expand_copysign (rtx operands[])
2325 : : {
2326 : 23248 : machine_mode mode, vmode;
2327 : 23248 : rtx dest, vdest, op0, op1, mask, op2, op3;
2328 : :
2329 : 23248 : mode = GET_MODE (operands[0]);
2330 : :
2331 : 23248 : switch (mode)
2332 : : {
2333 : : case E_HFmode:
2334 : : vmode = V8HFmode;
2335 : : break;
2336 : 0 : case E_BFmode:
2337 : 0 : vmode = V8BFmode;
2338 : 0 : break;
2339 : 11566 : case E_SFmode:
2340 : 11566 : vmode = V4SFmode;
2341 : 11566 : break;
2342 : 11544 : case E_DFmode:
2343 : 11544 : vmode = V2DFmode;
2344 : 11544 : break;
2345 : 127 : case E_TFmode:
2346 : 127 : vmode = mode;
2347 : 127 : break;
2348 : 0 : default:
2349 : 0 : gcc_unreachable();
2350 : : }
2351 : :
2352 : 23248 : if (rtx_equal_p (operands[1], operands[2]))
2353 : : {
2354 : 0 : emit_move_insn (operands[0], operands[1]);
2355 : 0 : return;
2356 : : }
2357 : :
2358 : 23248 : dest = operands[0];
2359 : 23248 : vdest = lowpart_subreg (vmode, dest, mode);
2360 : 23248 : if (vdest == NULL_RTX)
2361 : 0 : vdest = gen_reg_rtx (vmode);
2362 : : else
2363 : : dest = NULL_RTX;
2364 : 23248 : op1 = lowpart_subreg (vmode, force_reg (mode, operands[1]), mode);
2365 : 46482 : mask = ix86_build_signbit_mask (vmode, TARGET_AVX512F && mode != HFmode, 0);
2366 : :
2367 : 23248 : if (CONST_DOUBLE_P (operands[2]))
2368 : : {
2369 : 79 : if (real_isneg (CONST_DOUBLE_REAL_VALUE (operands[2])))
2370 : : /* Simplify b = copysign (a, negative) to b = mask | a. */
2371 : 76 : op1 = gen_rtx_IOR (vmode, mask, op1);
2372 : : else
2373 : : {
2374 : : /* Simplify b = copysign (a, positive) to b = invert_mask & a. */
2375 : 3 : rtx invert_mask
2376 : 3 : = ix86_build_signbit_mask (vmode,
2377 : 3 : TARGET_AVX512F && mode != HFmode,
2378 : : true);
2379 : 3 : op1 = gen_rtx_AND (vmode, invert_mask, op1);
2380 : : }
2381 : 79 : emit_move_insn (vdest, op1);
2382 : 79 : if (dest)
2383 : 0 : emit_move_insn (dest, lowpart_subreg (mode, vdest, vmode));
2384 : 79 : return;
2385 : : }
2386 : : else
2387 : 23169 : op0 = lowpart_subreg (vmode, force_reg (mode, operands[2]), mode);
2388 : :
2389 : 23169 : op2 = gen_reg_rtx (vmode);
2390 : 23169 : op3 = gen_reg_rtx (vmode);
2391 : 23169 : rtx invert_mask;
2392 : : /* NB: Generate vmovdqa, vpandn, vpand, vpor for AVX and generate pand,
2393 : : pand, por for SSE. */
2394 : 23169 : if (TARGET_AVX)
2395 : 32 : invert_mask = gen_rtx_NOT (vmode, mask);
2396 : : else
2397 : 23137 : invert_mask = ix86_build_signbit_mask (vmode,
2398 : 23137 : TARGET_AVX512F && mode != HFmode,
2399 : : true);
2400 : 23169 : emit_move_insn (op2, gen_rtx_AND (vmode, invert_mask, op1));
2401 : 23169 : emit_move_insn (op3, gen_rtx_AND (vmode, mask, op0));
2402 : 23169 : emit_move_insn (vdest, gen_rtx_IOR (vmode, op2, op3));
2403 : 23169 : if (dest)
2404 : 0 : emit_move_insn (dest, lowpart_subreg (mode, vdest, vmode));
2405 : : }
2406 : :
2407 : : /* Expand an xorsign operation. */
2408 : :
2409 : : void
2410 : 20 : ix86_expand_xorsign (rtx operands[])
2411 : : {
2412 : 20 : machine_mode mode, vmode;
2413 : 20 : rtx dest, vdest, op0, op1, mask, x, temp;
2414 : :
2415 : 20 : dest = operands[0];
2416 : 20 : op0 = operands[1];
2417 : 20 : op1 = operands[2];
2418 : :
2419 : 20 : mode = GET_MODE (dest);
2420 : :
2421 : 20 : switch (mode)
2422 : : {
2423 : : case E_HFmode:
2424 : : vmode = V8HFmode;
2425 : : break;
2426 : : case E_BFmode:
2427 : : vmode = V8BFmode;
2428 : : break;
2429 : : case E_SFmode:
2430 : : vmode = V4SFmode;
2431 : : break;
2432 : : case E_DFmode:
2433 : : vmode = V2DFmode;
2434 : : break;
2435 : 0 : default:
2436 : 0 : gcc_unreachable ();
2437 : 20 : break;
2438 : : }
2439 : :
2440 : 20 : temp = gen_reg_rtx (vmode);
2441 : 20 : mask = ix86_build_signbit_mask (vmode, 0, 0);
2442 : :
2443 : 20 : op1 = lowpart_subreg (vmode, force_reg (mode, op1), mode);
2444 : 20 : x = gen_rtx_AND (vmode, op1, mask);
2445 : 20 : emit_insn (gen_rtx_SET (temp, x));
2446 : :
2447 : 20 : op0 = lowpart_subreg (vmode, force_reg (mode, op0), mode);
2448 : 20 : x = gen_rtx_XOR (vmode, temp, op0);
2449 : :
2450 : 20 : vdest = lowpart_subreg (vmode, dest, mode);
2451 : 20 : if (vdest == NULL_RTX)
2452 : 0 : vdest = gen_reg_rtx (vmode);
2453 : : else
2454 : : dest = NULL_RTX;
2455 : 20 : emit_insn (gen_rtx_SET (vdest, x));
2456 : :
2457 : 20 : if (dest)
2458 : 0 : emit_move_insn (dest, lowpart_subreg (mode, vdest, vmode));
2459 : 20 : }
2460 : :
2461 : : static rtx ix86_expand_compare (enum rtx_code code, rtx op0, rtx op1);
2462 : :
2463 : : void
2464 : 6741220 : ix86_expand_branch (enum rtx_code code, rtx op0, rtx op1, rtx label)
2465 : : {
2466 : 6741220 : machine_mode mode = GET_MODE (op0);
2467 : 6741220 : rtx tmp;
2468 : :
2469 : : /* Handle special case - vector comparsion with boolean result, transform
2470 : : it using ptest instruction or vpcmpeq + kortest. */
2471 : 6741220 : if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT
2472 : 6721821 : || (mode == TImode && !TARGET_64BIT)
2473 : 6721821 : || mode == OImode
2474 : 13463041 : || GET_MODE_SIZE (mode) == 64)
2475 : : {
2476 : 19399 : unsigned msize = GET_MODE_SIZE (mode);
2477 : 19399 : machine_mode p_mode
2478 : 19399 : = msize == 64 ? V16SImode : msize == 32 ? V4DImode : V2DImode;
2479 : : /* kortest set CF when result is 0xFFFF (op0 == op1). */
2480 : 19399 : rtx flag = gen_rtx_REG (msize == 64 ? CCCmode : CCZmode, FLAGS_REG);
2481 : :
2482 : 19399 : gcc_assert (code == EQ || code == NE);
2483 : :
2484 : : /* Using vpcmpeq zmm zmm k + kortest for 512-bit vectors. */
2485 : 19399 : if (msize == 64)
2486 : : {
2487 : 2195 : if (mode != V16SImode)
2488 : : {
2489 : 2195 : op0 = lowpart_subreg (p_mode, force_reg (mode, op0), mode);
2490 : 2195 : op1 = lowpart_subreg (p_mode, force_reg (mode, op1), mode);
2491 : : }
2492 : :
2493 : 2195 : tmp = gen_reg_rtx (HImode);
2494 : 2195 : emit_insn (gen_avx512f_cmpv16si3 (tmp, op0, op1, GEN_INT (0)));
2495 : 2195 : emit_insn (gen_kortesthi_ccc (tmp, tmp));
2496 : : }
2497 : : /* Using ptest for 128/256-bit vectors. */
2498 : : else
2499 : : {
2500 : 17204 : if (GET_MODE_CLASS (mode) != MODE_VECTOR_INT)
2501 : : {
2502 : 0 : op0 = lowpart_subreg (p_mode, force_reg (mode, op0), mode);
2503 : 0 : op1 = lowpart_subreg (p_mode, force_reg (mode, op1), mode);
2504 : 0 : mode = p_mode;
2505 : : }
2506 : :
2507 : : /* Generate XOR since we can't check that one operand is zero
2508 : : vector. */
2509 : 17204 : tmp = gen_reg_rtx (mode);
2510 : 17204 : rtx ops[3] = { tmp, op0, op1 };
2511 : 17204 : ix86_expand_vector_logical_operator (XOR, mode, ops);
2512 : 17204 : tmp = gen_lowpart (p_mode, tmp);
2513 : 17204 : emit_insn (gen_rtx_SET (gen_rtx_REG (CCZmode, FLAGS_REG),
2514 : : gen_rtx_UNSPEC (CCZmode,
2515 : : gen_rtvec (2, tmp, tmp),
2516 : : UNSPEC_PTEST)));
2517 : : }
2518 : 19399 : tmp = gen_rtx_fmt_ee (code, VOIDmode, flag, const0_rtx);
2519 : 19399 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
2520 : : gen_rtx_LABEL_REF (VOIDmode, label),
2521 : : pc_rtx);
2522 : 19399 : emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
2523 : 19399 : return;
2524 : : }
2525 : :
2526 : 6721821 : switch (mode)
2527 : : {
2528 : 6686019 : case E_HFmode:
2529 : 6686019 : case E_SFmode:
2530 : 6686019 : case E_DFmode:
2531 : 6686019 : case E_XFmode:
2532 : 6686019 : case E_QImode:
2533 : 6686019 : case E_HImode:
2534 : 6686019 : case E_SImode:
2535 : 6686019 : simple:
2536 : 6686019 : tmp = ix86_expand_compare (code, op0, op1);
2537 : 6686019 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
2538 : : gen_rtx_LABEL_REF (VOIDmode, label),
2539 : : pc_rtx);
2540 : 6686019 : emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
2541 : 6686019 : return;
2542 : :
2543 : 7 : case E_BFmode:
2544 : 7 : gcc_assert (TARGET_AVX10_2 && !flag_trapping_math);
2545 : 7 : goto simple;
2546 : :
2547 : 2679257 : case E_DImode:
2548 : 2679257 : if (TARGET_64BIT)
2549 : 2651665 : goto simple;
2550 : : /* FALLTHRU */
2551 : 94334 : case E_TImode:
2552 : : /* DI and TI mode equality/inequality comparisons may be performed
2553 : : on SSE registers. Avoid splitting them, except when optimizing
2554 : : for size. */
2555 : 94334 : if ((code == EQ || code == NE)
2556 : 94334 : && !optimize_insn_for_size_p ())
2557 : 58532 : goto simple;
2558 : :
2559 : : /* Expand DImode branch into multiple compare+branch. */
2560 : 35802 : {
2561 : 35802 : rtx lo[2], hi[2];
2562 : 35802 : rtx_code_label *label2;
2563 : 35802 : enum rtx_code code1, code2, code3;
2564 : 35802 : machine_mode submode;
2565 : :
2566 : 35802 : if (CONSTANT_P (op0) && !CONSTANT_P (op1))
2567 : : {
2568 : 0 : std::swap (op0, op1);
2569 : 0 : code = swap_condition (code);
2570 : : }
2571 : :
2572 : 35802 : split_double_mode (mode, &op0, 1, lo+0, hi+0);
2573 : 35802 : split_double_mode (mode, &op1, 1, lo+1, hi+1);
2574 : :
2575 : 35802 : submode = mode == DImode ? SImode : DImode;
2576 : :
2577 : : /* If we are doing less-than or greater-or-equal-than,
2578 : : op1 is a constant and the low word is zero, then we can just
2579 : : examine the high word. Similarly for low word -1 and
2580 : : less-or-equal-than or greater-than. */
2581 : :
2582 : 35802 : if (CONST_INT_P (hi[1]))
2583 : 24445 : switch (code)
2584 : : {
2585 : 10812 : case LT: case LTU: case GE: case GEU:
2586 : 10812 : if (lo[1] == const0_rtx)
2587 : : {
2588 : 10404 : ix86_expand_branch (code, hi[0], hi[1], label);
2589 : 10404 : return;
2590 : : }
2591 : : break;
2592 : 12058 : case LE: case LEU: case GT: case GTU:
2593 : 12058 : if (lo[1] == constm1_rtx)
2594 : : {
2595 : 529 : ix86_expand_branch (code, hi[0], hi[1], label);
2596 : 529 : return;
2597 : : }
2598 : : break;
2599 : : default:
2600 : : break;
2601 : : }
2602 : :
2603 : : /* Emulate comparisons that do not depend on Zero flag with
2604 : : double-word subtraction. Note that only Overflow, Sign
2605 : : and Carry flags are valid, so swap arguments and condition
2606 : : of comparisons that would otherwise test Zero flag. */
2607 : :
2608 : 24869 : switch (code)
2609 : : {
2610 : 17356 : case LE: case LEU: case GT: case GTU:
2611 : 17356 : std::swap (lo[0], lo[1]);
2612 : 17356 : std::swap (hi[0], hi[1]);
2613 : 17356 : code = swap_condition (code);
2614 : : /* FALLTHRU */
2615 : :
2616 : 21802 : case LT: case LTU: case GE: case GEU:
2617 : 21802 : {
2618 : 21802 : bool uns = (code == LTU || code == GEU);
2619 : 3995 : rtx (*sbb_insn) (machine_mode, rtx, rtx, rtx)
2620 : 21802 : = uns ? gen_sub3_carry_ccc : gen_sub3_carry_ccgz;
2621 : :
2622 : 21802 : if (!nonimmediate_operand (lo[0], submode))
2623 : 11529 : lo[0] = force_reg (submode, lo[0]);
2624 : 21802 : if (!x86_64_general_operand (lo[1], submode))
2625 : 0 : lo[1] = force_reg (submode, lo[1]);
2626 : :
2627 : 21802 : if (!register_operand (hi[0], submode))
2628 : 12345 : hi[0] = force_reg (submode, hi[0]);
2629 : 17807 : if ((uns && !nonimmediate_operand (hi[1], submode))
2630 : 21802 : || (!uns && !x86_64_general_operand (hi[1], submode)))
2631 : 315 : hi[1] = force_reg (submode, hi[1]);
2632 : :
2633 : 21802 : emit_insn (gen_cmp_1 (submode, lo[0], lo[1]));
2634 : :
2635 : 21802 : tmp = gen_rtx_SCRATCH (submode);
2636 : 21802 : emit_insn (sbb_insn (submode, tmp, hi[0], hi[1]));
2637 : :
2638 : 25797 : tmp = gen_rtx_REG (uns ? CCCmode : CCGZmode, FLAGS_REG);
2639 : 21802 : ix86_expand_branch (code, tmp, const0_rtx, label);
2640 : 21802 : return;
2641 : : }
2642 : :
2643 : 3067 : default:
2644 : 3067 : break;
2645 : : }
2646 : :
2647 : : /* Otherwise, we need two or three jumps. */
2648 : :
2649 : 3067 : label2 = gen_label_rtx ();
2650 : :
2651 : 3067 : code1 = code;
2652 : 3067 : code2 = swap_condition (code);
2653 : 3067 : code3 = unsigned_condition (code);
2654 : :
2655 : 3067 : switch (code)
2656 : : {
2657 : : case LT: case GT: case LTU: case GTU:
2658 : : break;
2659 : :
2660 : : case LE: code1 = LT; code2 = GT; break;
2661 : : case GE: code1 = GT; code2 = LT; break;
2662 : 0 : case LEU: code1 = LTU; code2 = GTU; break;
2663 : 0 : case GEU: code1 = GTU; code2 = LTU; break;
2664 : :
2665 : : case EQ: code1 = UNKNOWN; code2 = NE; break;
2666 : : case NE: code2 = UNKNOWN; break;
2667 : :
2668 : 0 : default:
2669 : 0 : gcc_unreachable ();
2670 : : }
2671 : :
2672 : : /*
2673 : : * a < b =>
2674 : : * if (hi(a) < hi(b)) goto true;
2675 : : * if (hi(a) > hi(b)) goto false;
2676 : : * if (lo(a) < lo(b)) goto true;
2677 : : * false:
2678 : : */
2679 : :
2680 : 0 : if (code1 != UNKNOWN)
2681 : 2335 : ix86_expand_branch (code1, hi[0], hi[1], label);
2682 : 3067 : if (code2 != UNKNOWN)
2683 : 732 : ix86_expand_branch (code2, hi[0], hi[1], label2);
2684 : :
2685 : 3067 : ix86_expand_branch (code3, lo[0], lo[1], label);
2686 : :
2687 : 3067 : if (code2 != UNKNOWN)
2688 : 732 : emit_label (label2);
2689 : : return;
2690 : : }
2691 : :
2692 : 22239 : default:
2693 : 22239 : gcc_assert (GET_MODE_CLASS (GET_MODE (op0)) == MODE_CC);
2694 : 22239 : goto simple;
2695 : : }
2696 : : }
2697 : :
2698 : : /* Figure out whether to use unordered fp comparisons. */
2699 : :
2700 : : static bool
2701 : 1124632 : ix86_unordered_fp_compare (enum rtx_code code)
2702 : : {
2703 : 1124632 : if (!TARGET_IEEE_FP)
2704 : : return false;
2705 : :
2706 : 1120256 : switch (code)
2707 : : {
2708 : : case LT:
2709 : : case LE:
2710 : : case GT:
2711 : : case GE:
2712 : : case LTGT:
2713 : : return false;
2714 : :
2715 : : case EQ:
2716 : : case NE:
2717 : :
2718 : : case UNORDERED:
2719 : : case ORDERED:
2720 : : case UNLT:
2721 : : case UNLE:
2722 : : case UNGT:
2723 : : case UNGE:
2724 : : case UNEQ:
2725 : : return true;
2726 : :
2727 : 0 : default:
2728 : 0 : gcc_unreachable ();
2729 : : }
2730 : : }
2731 : :
2732 : : /* Return a comparison we can do and that it is equivalent to
2733 : : swap_condition (code) apart possibly from orderedness.
2734 : : But, never change orderedness if TARGET_IEEE_FP, returning
2735 : : UNKNOWN in that case if necessary. */
2736 : :
2737 : : static enum rtx_code
2738 : 37069 : ix86_fp_swap_condition (enum rtx_code code)
2739 : : {
2740 : 37069 : switch (code)
2741 : : {
2742 : 1866 : case GT: /* GTU - CF=0 & ZF=0 */
2743 : 1866 : return TARGET_IEEE_FP ? UNKNOWN : UNLT;
2744 : 525 : case GE: /* GEU - CF=0 */
2745 : 525 : return TARGET_IEEE_FP ? UNKNOWN : UNLE;
2746 : 440 : case UNLT: /* LTU - CF=1 */
2747 : 440 : return TARGET_IEEE_FP ? UNKNOWN : GT;
2748 : 6315 : case UNLE: /* LEU - CF=1 | ZF=1 */
2749 : 6315 : return TARGET_IEEE_FP ? UNKNOWN : GE;
2750 : 27923 : default:
2751 : 27923 : return swap_condition (code);
2752 : : }
2753 : : }
2754 : :
2755 : : /* Return cost of comparison CODE using the best strategy for performance.
2756 : : All following functions do use number of instructions as a cost metrics.
2757 : : In future this should be tweaked to compute bytes for optimize_size and
2758 : : take into account performance of various instructions on various CPUs. */
2759 : :
2760 : : static int
2761 : 1123478 : ix86_fp_comparison_cost (enum rtx_code code)
2762 : : {
2763 : 1123478 : int arith_cost;
2764 : :
2765 : : /* The cost of code using bit-twiddling on %ah. */
2766 : 1123478 : switch (code)
2767 : : {
2768 : : case UNLE:
2769 : : case UNLT:
2770 : : case LTGT:
2771 : : case GT:
2772 : : case GE:
2773 : : case UNORDERED:
2774 : : case ORDERED:
2775 : : case UNEQ:
2776 : : arith_cost = 4;
2777 : : break;
2778 : 73052 : case LT:
2779 : 73052 : case NE:
2780 : 73052 : case EQ:
2781 : 73052 : case UNGE:
2782 : 73052 : arith_cost = TARGET_IEEE_FP ? 5 : 4;
2783 : : break;
2784 : 25996 : case LE:
2785 : 25996 : case UNGT:
2786 : 1051234 : arith_cost = TARGET_IEEE_FP ? 6 : 4;
2787 : : break;
2788 : 0 : default:
2789 : 0 : gcc_unreachable ();
2790 : : }
2791 : :
2792 : 1123478 : switch (ix86_fp_comparison_strategy (code))
2793 : : {
2794 : 1123478 : case IX86_FPCMP_COMI:
2795 : 1123478 : return arith_cost > 4 ? 3 : 2;
2796 : 0 : case IX86_FPCMP_SAHF:
2797 : 0 : return arith_cost > 4 ? 4 : 3;
2798 : : default:
2799 : : return arith_cost;
2800 : : }
2801 : : }
2802 : :
2803 : : /* Swap, force into registers, or otherwise massage the two operands
2804 : : to a fp comparison. The operands are updated in place; the new
2805 : : comparison code is returned. */
2806 : :
2807 : : static enum rtx_code
2808 : 561739 : ix86_prepare_fp_compare_args (enum rtx_code code, rtx *pop0, rtx *pop1)
2809 : : {
2810 : 561810 : bool unordered_compare = ix86_unordered_fp_compare (code);
2811 : 561810 : rtx op0 = *pop0, op1 = *pop1;
2812 : 561810 : machine_mode op_mode = GET_MODE (op0);
2813 : 561810 : bool is_sse = SSE_FLOAT_MODE_SSEMATH_OR_HFBF_P (op_mode);
2814 : :
2815 : 559422 : if (op_mode == BFmode && (!TARGET_AVX10_2 || flag_trapping_math))
2816 : : {
2817 : 71 : rtx op = gen_lowpart (HImode, op0);
2818 : 71 : if (CONST_INT_P (op))
2819 : 0 : op = simplify_const_unary_operation (FLOAT_EXTEND, SFmode,
2820 : : op0, BFmode);
2821 : : else
2822 : : {
2823 : 71 : rtx t1 = gen_reg_rtx (SImode);
2824 : 71 : emit_insn (gen_zero_extendhisi2 (t1, op));
2825 : 71 : emit_insn (gen_ashlsi3 (t1, t1, GEN_INT (16)));
2826 : 71 : op = gen_lowpart (SFmode, t1);
2827 : : }
2828 : 71 : *pop0 = op;
2829 : 71 : op = gen_lowpart (HImode, op1);
2830 : 71 : if (CONST_INT_P (op))
2831 : 6 : op = simplify_const_unary_operation (FLOAT_EXTEND, SFmode,
2832 : : op1, BFmode);
2833 : : else
2834 : : {
2835 : 65 : rtx t1 = gen_reg_rtx (SImode);
2836 : 65 : emit_insn (gen_zero_extendhisi2 (t1, op));
2837 : 65 : emit_insn (gen_ashlsi3 (t1, t1, GEN_INT (16)));
2838 : 65 : op = gen_lowpart (SFmode, t1);
2839 : : }
2840 : 71 : *pop1 = op;
2841 : 71 : return ix86_prepare_fp_compare_args (code, pop0, pop1);
2842 : : }
2843 : :
2844 : : /* All of the unordered compare instructions only work on registers.
2845 : : The same is true of the fcomi compare instructions. The XFmode
2846 : : compare instructions require registers except when comparing
2847 : : against zero or when converting operand 1 from fixed point to
2848 : : floating point. */
2849 : :
2850 : 561739 : if (!is_sse
2851 : 561739 : && (unordered_compare
2852 : 8241 : || (op_mode == XFmode
2853 : 10587 : && ! (standard_80387_constant_p (op0) == 1
2854 : 5291 : || standard_80387_constant_p (op1) == 1)
2855 : 4945 : && GET_CODE (op1) != FLOAT)
2856 : 3296 : || ix86_fp_comparison_strategy (code) == IX86_FPCMP_COMI))
2857 : : {
2858 : 147887 : op0 = force_reg (op_mode, op0);
2859 : 147887 : op1 = force_reg (op_mode, op1);
2860 : : }
2861 : : else
2862 : : {
2863 : : /* %%% We only allow op1 in memory; op0 must be st(0). So swap
2864 : : things around if they appear profitable, otherwise force op0
2865 : : into a register. */
2866 : :
2867 : 413852 : if (standard_80387_constant_p (op0) == 0
2868 : 413852 : || (MEM_P (op0)
2869 : 55362 : && ! (standard_80387_constant_p (op1) == 0
2870 : 40661 : || MEM_P (op1))))
2871 : : {
2872 : 37069 : enum rtx_code new_code = ix86_fp_swap_condition (code);
2873 : 37069 : if (new_code != UNKNOWN)
2874 : : {
2875 : : std::swap (op0, op1);
2876 : 413852 : code = new_code;
2877 : : }
2878 : : }
2879 : :
2880 : 413852 : if (!REG_P (op0))
2881 : 52346 : op0 = force_reg (op_mode, op0);
2882 : :
2883 : 413852 : if (CONSTANT_P (op1))
2884 : : {
2885 : 192223 : int tmp = standard_80387_constant_p (op1);
2886 : 192223 : if (tmp == 0)
2887 : 73077 : op1 = validize_mem (force_const_mem (op_mode, op1));
2888 : 119146 : else if (tmp == 1)
2889 : : {
2890 : 65081 : if (TARGET_CMOVE)
2891 : 65081 : op1 = force_reg (op_mode, op1);
2892 : : }
2893 : : else
2894 : 54065 : op1 = force_reg (op_mode, op1);
2895 : : }
2896 : : }
2897 : :
2898 : : /* Try to rearrange the comparison to make it cheaper. */
2899 : 561739 : if (ix86_fp_comparison_cost (code)
2900 : 561739 : > ix86_fp_comparison_cost (swap_condition (code))
2901 : 561739 : && (REG_P (op1) || can_create_pseudo_p ()))
2902 : : {
2903 : 0 : std::swap (op0, op1);
2904 : 0 : code = swap_condition (code);
2905 : 0 : if (!REG_P (op0))
2906 : 0 : op0 = force_reg (op_mode, op0);
2907 : : }
2908 : :
2909 : 561739 : *pop0 = op0;
2910 : 561739 : *pop1 = op1;
2911 : 561739 : return code;
2912 : : }
2913 : :
2914 : : /* Generate insn patterns to do a floating point compare of OPERANDS. */
2915 : :
2916 : : static rtx
2917 : 561739 : ix86_expand_fp_compare (enum rtx_code code, rtx op0, rtx op1)
2918 : : {
2919 : 561739 : bool unordered_compare = ix86_unordered_fp_compare (code);
2920 : 561739 : machine_mode cmp_mode;
2921 : 561739 : rtx tmp, scratch;
2922 : :
2923 : 561739 : code = ix86_prepare_fp_compare_args (code, &op0, &op1);
2924 : :
2925 : 561739 : tmp = gen_rtx_COMPARE (CCFPmode, op0, op1);
2926 : 561739 : if (unordered_compare)
2927 : 494437 : tmp = gen_rtx_UNSPEC (CCFPmode, gen_rtvec (1, tmp), UNSPEC_NOTRAP);
2928 : :
2929 : : /* Do fcomi/sahf based test when profitable. */
2930 : 561739 : switch (ix86_fp_comparison_strategy (code))
2931 : : {
2932 : 561739 : case IX86_FPCMP_COMI:
2933 : 561739 : tmp = gen_rtx_COMPARE (CCFPmode, op0, op1);
2934 : : /* We only have vcomisbf16, No vcomubf16 nor vcomxbf16 */
2935 : 561739 : if (GET_MODE (op0) != E_BFmode)
2936 : : {
2937 : 561711 : if (TARGET_AVX10_2 && (code == EQ || code == NE))
2938 : 972 : tmp = gen_rtx_UNSPEC (CCFPmode, gen_rtvec (1, tmp), UNSPEC_OPTCOMX);
2939 : 561711 : if (unordered_compare)
2940 : 494429 : tmp = gen_rtx_UNSPEC (CCFPmode, gen_rtvec (1, tmp), UNSPEC_NOTRAP);
2941 : : }
2942 : 561739 : cmp_mode = CCFPmode;
2943 : 561739 : emit_insn (gen_rtx_SET (gen_rtx_REG (CCFPmode, FLAGS_REG), tmp));
2944 : 561739 : break;
2945 : :
2946 : 0 : case IX86_FPCMP_SAHF:
2947 : 0 : cmp_mode = CCFPmode;
2948 : 0 : tmp = gen_rtx_UNSPEC (HImode, gen_rtvec (1, tmp), UNSPEC_FNSTSW);
2949 : 0 : scratch = gen_reg_rtx (HImode);
2950 : 0 : emit_insn (gen_rtx_SET (scratch, tmp));
2951 : 0 : emit_insn (gen_x86_sahf_1 (scratch));
2952 : 0 : break;
2953 : :
2954 : 0 : case IX86_FPCMP_ARITH:
2955 : 0 : cmp_mode = CCNOmode;
2956 : 0 : tmp = gen_rtx_UNSPEC (HImode, gen_rtvec (1, tmp), UNSPEC_FNSTSW);
2957 : 0 : scratch = gen_reg_rtx (HImode);
2958 : 0 : emit_insn (gen_rtx_SET (scratch, tmp));
2959 : :
2960 : : /* In the unordered case, we have to check C2 for NaN's, which
2961 : : doesn't happen to work out to anything nice combination-wise.
2962 : : So do some bit twiddling on the value we've got in AH to come
2963 : : up with an appropriate set of condition codes. */
2964 : :
2965 : 0 : switch (code)
2966 : : {
2967 : 0 : case GT:
2968 : 0 : case UNGT:
2969 : 0 : if (code == GT || !TARGET_IEEE_FP)
2970 : : {
2971 : 0 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x45)));
2972 : 0 : code = EQ;
2973 : : }
2974 : : else
2975 : : {
2976 : 0 : emit_insn (gen_andqi_ext_1 (scratch, scratch, GEN_INT (0x45)));
2977 : 0 : emit_insn (gen_addqi_ext_1 (scratch, scratch, constm1_rtx));
2978 : 0 : emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x44)));
2979 : 0 : cmp_mode = CCmode;
2980 : 0 : code = GEU;
2981 : : }
2982 : : break;
2983 : 0 : case LT:
2984 : 0 : case UNLT:
2985 : 0 : if (code == LT && TARGET_IEEE_FP)
2986 : : {
2987 : 0 : emit_insn (gen_andqi_ext_1 (scratch, scratch, GEN_INT (0x45)));
2988 : 0 : emit_insn (gen_cmpqi_ext_3 (scratch, const1_rtx));
2989 : 0 : cmp_mode = CCmode;
2990 : 0 : code = EQ;
2991 : : }
2992 : : else
2993 : : {
2994 : 0 : emit_insn (gen_testqi_ext_1_ccno (scratch, const1_rtx));
2995 : 0 : code = NE;
2996 : : }
2997 : : break;
2998 : 0 : case GE:
2999 : 0 : case UNGE:
3000 : 0 : if (code == GE || !TARGET_IEEE_FP)
3001 : : {
3002 : 0 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x05)));
3003 : 0 : code = EQ;
3004 : : }
3005 : : else
3006 : : {
3007 : 0 : emit_insn (gen_andqi_ext_1 (scratch, scratch, GEN_INT (0x45)));
3008 : 0 : emit_insn (gen_xorqi_ext_1_cc (scratch, scratch, const1_rtx));
3009 : 0 : code = NE;
3010 : : }
3011 : : break;
3012 : 0 : case LE:
3013 : 0 : case UNLE:
3014 : 0 : if (code == LE && TARGET_IEEE_FP)
3015 : : {
3016 : 0 : emit_insn (gen_andqi_ext_1 (scratch, scratch, GEN_INT (0x45)));
3017 : 0 : emit_insn (gen_addqi_ext_1 (scratch, scratch, constm1_rtx));
3018 : 0 : emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x40)));
3019 : 0 : cmp_mode = CCmode;
3020 : 0 : code = LTU;
3021 : : }
3022 : : else
3023 : : {
3024 : 0 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x45)));
3025 : 0 : code = NE;
3026 : : }
3027 : : break;
3028 : 0 : case EQ:
3029 : 0 : case UNEQ:
3030 : 0 : if (code == EQ && TARGET_IEEE_FP)
3031 : : {
3032 : 0 : emit_insn (gen_andqi_ext_1 (scratch, scratch, GEN_INT (0x45)));
3033 : 0 : emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x40)));
3034 : 0 : cmp_mode = CCmode;
3035 : 0 : code = EQ;
3036 : : }
3037 : : else
3038 : : {
3039 : 0 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x40)));
3040 : 0 : code = NE;
3041 : : }
3042 : : break;
3043 : 0 : case NE:
3044 : 0 : case LTGT:
3045 : 0 : if (code == NE && TARGET_IEEE_FP)
3046 : : {
3047 : 0 : emit_insn (gen_andqi_ext_1 (scratch, scratch, GEN_INT (0x45)));
3048 : 0 : emit_insn (gen_xorqi_ext_1_cc (scratch, scratch,
3049 : : GEN_INT (0x40)));
3050 : 0 : code = NE;
3051 : : }
3052 : : else
3053 : : {
3054 : 0 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x40)));
3055 : 0 : code = EQ;
3056 : : }
3057 : : break;
3058 : :
3059 : 0 : case UNORDERED:
3060 : 0 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x04)));
3061 : 0 : code = NE;
3062 : 0 : break;
3063 : 0 : case ORDERED:
3064 : 0 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x04)));
3065 : 0 : code = EQ;
3066 : 0 : break;
3067 : :
3068 : 0 : default:
3069 : 0 : gcc_unreachable ();
3070 : : }
3071 : : break;
3072 : :
3073 : 0 : default:
3074 : 0 : gcc_unreachable();
3075 : : }
3076 : :
3077 : : /* Return the test that should be put into the flags user, i.e.
3078 : : the bcc, scc, or cmov instruction. */
3079 : 561739 : return gen_rtx_fmt_ee (code, VOIDmode,
3080 : : gen_rtx_REG (cmp_mode, FLAGS_REG),
3081 : : const0_rtx);
3082 : : }
3083 : :
3084 : : /* Generate insn patterns to do an integer compare of OPERANDS. */
3085 : :
3086 : : static rtx
3087 : 7069410 : ix86_expand_int_compare (enum rtx_code code, rtx op0, rtx op1)
3088 : : {
3089 : 7069410 : machine_mode cmpmode;
3090 : 7069410 : rtx tmp, flags;
3091 : :
3092 : : /* Swap operands to emit carry flag comparison. */
3093 : 7069410 : if ((code == GTU || code == LEU)
3094 : 7069410 : && nonimmediate_operand (op1, VOIDmode))
3095 : : {
3096 : 144018 : std::swap (op0, op1);
3097 : 144018 : code = swap_condition (code);
3098 : : }
3099 : :
3100 : 7069410 : cmpmode = SELECT_CC_MODE (code, op0, op1);
3101 : 7069410 : flags = gen_rtx_REG (cmpmode, FLAGS_REG);
3102 : :
3103 : : /* Attempt to use PTEST, if available, when testing vector modes for
3104 : : equality/inequality against zero. */
3105 : 7069410 : if (op1 == const0_rtx
3106 : 2952927 : && SUBREG_P (op0)
3107 : 23047 : && cmpmode == CCZmode
3108 : 10363 : && SUBREG_BYTE (op0) == 0
3109 : 8718 : && REG_P (SUBREG_REG (op0))
3110 : 8718 : && VECTOR_MODE_P (GET_MODE (SUBREG_REG (op0)))
3111 : 7 : && TARGET_SSE4_1
3112 : 1 : && GET_MODE (op0) == TImode
3113 : 7069412 : && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op0))) == 16)
3114 : : {
3115 : 1 : tmp = SUBREG_REG (op0);
3116 : 1 : if (GET_MODE (tmp) == V8HFmode || GET_MODE (tmp) == V8BFmode)
3117 : 1 : tmp = gen_lowpart (V8HImode, tmp);
3118 : 1 : tmp = gen_rtx_UNSPEC (CCZmode, gen_rtvec (2, tmp, tmp), UNSPEC_PTEST);
3119 : : }
3120 : : else
3121 : 7069409 : tmp = gen_rtx_COMPARE (cmpmode, op0, op1);
3122 : :
3123 : : /* This is very simple, but making the interface the same as in the
3124 : : FP case makes the rest of the code easier. */
3125 : 7069410 : emit_insn (gen_rtx_SET (flags, tmp));
3126 : :
3127 : : /* Return the test that should be put into the flags user, i.e.
3128 : : the bcc, scc, or cmov instruction. */
3129 : 7069410 : return gen_rtx_fmt_ee (code, VOIDmode, flags, const0_rtx);
3130 : : }
3131 : :
3132 : : static rtx
3133 : 7762487 : ix86_expand_compare (enum rtx_code code, rtx op0, rtx op1)
3134 : : {
3135 : 7762487 : rtx ret;
3136 : :
3137 : 7762487 : if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_CC)
3138 : 131875 : ret = gen_rtx_fmt_ee (code, VOIDmode, op0, op1);
3139 : :
3140 : 7630612 : else if (SCALAR_FLOAT_MODE_P (GET_MODE (op0)))
3141 : : {
3142 : 561202 : gcc_assert (!DECIMAL_FLOAT_MODE_P (GET_MODE (op0)));
3143 : 561202 : ret = ix86_expand_fp_compare (code, op0, op1);
3144 : : }
3145 : : else
3146 : 7069410 : ret = ix86_expand_int_compare (code, op0, op1);
3147 : :
3148 : 7762487 : return ret;
3149 : : }
3150 : :
3151 : : void
3152 : 606211 : ix86_expand_setcc (rtx dest, enum rtx_code code, rtx op0, rtx op1)
3153 : : {
3154 : 606211 : rtx ret;
3155 : :
3156 : 606211 : gcc_assert (GET_MODE (dest) == QImode);
3157 : :
3158 : 606211 : ret = ix86_expand_compare (code, op0, op1);
3159 : 606211 : PUT_MODE (ret, QImode);
3160 : 606211 : emit_insn (gen_rtx_SET (dest, ret));
3161 : 606211 : }
3162 : :
3163 : : /* Expand floating point op0 <=> op1, i.e.
3164 : : dest = op0 == op1 ? 0 : op0 < op1 ? -1 : op0 > op1 ? 1 : -128. */
3165 : :
3166 : : void
3167 : 298 : ix86_expand_fp_spaceship (rtx dest, rtx op0, rtx op1, rtx op2)
3168 : : {
3169 : 298 : gcc_checking_assert (ix86_fp_comparison_strategy (GT) != IX86_FPCMP_ARITH);
3170 : 298 : rtx zero = NULL_RTX;
3171 : 298 : if (op2 != const0_rtx
3172 : 52 : && (TARGET_IEEE_FP || TARGET_ZERO_EXTEND_WITH_AND)
3173 : 34 : && GET_MODE (dest) == SImode)
3174 : 34 : zero = force_reg (SImode, const0_rtx);
3175 : 298 : rtx gt = ix86_expand_fp_compare (GT, op0, op1);
3176 : 298 : rtx l0 = op2 == const0_rtx ? gen_label_rtx () : NULL_RTX;
3177 : 298 : rtx l1 = op2 == const0_rtx ? gen_label_rtx () : NULL_RTX;
3178 : 298 : rtx l2 = TARGET_IEEE_FP ? gen_label_rtx () : NULL_RTX;
3179 : 298 : rtx lend = gen_label_rtx ();
3180 : 298 : rtx tmp;
3181 : 298 : rtx_insn *jmp;
3182 : 298 : if (l2)
3183 : : {
3184 : 261 : rtx un = gen_rtx_fmt_ee (UNORDERED, VOIDmode,
3185 : : gen_rtx_REG (CCFPmode, FLAGS_REG), const0_rtx);
3186 : 261 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, un,
3187 : : gen_rtx_LABEL_REF (VOIDmode, l2), pc_rtx);
3188 : 261 : jmp = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
3189 : 261 : add_reg_br_prob_note (jmp, profile_probability:: very_unlikely ());
3190 : : }
3191 : 298 : if (op2 == const0_rtx)
3192 : : {
3193 : 246 : rtx eq = gen_rtx_fmt_ee (UNEQ, VOIDmode,
3194 : : gen_rtx_REG (CCFPmode, FLAGS_REG), const0_rtx);
3195 : 246 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, eq,
3196 : : gen_rtx_LABEL_REF (VOIDmode, l0), pc_rtx);
3197 : 246 : jmp = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
3198 : 246 : add_reg_br_prob_note (jmp, profile_probability::unlikely ());
3199 : 246 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, gt,
3200 : : gen_rtx_LABEL_REF (VOIDmode, l1), pc_rtx);
3201 : 246 : jmp = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
3202 : 246 : add_reg_br_prob_note (jmp, profile_probability::even ());
3203 : 246 : emit_move_insn (dest, constm1_rtx);
3204 : 246 : emit_jump (lend);
3205 : 246 : emit_label (l0);
3206 : 246 : emit_move_insn (dest, const0_rtx);
3207 : 246 : emit_jump (lend);
3208 : 246 : emit_label (l1);
3209 : 246 : emit_move_insn (dest, const1_rtx);
3210 : : }
3211 : : else
3212 : : {
3213 : 52 : rtx lt_tmp = NULL_RTX;
3214 : 52 : if (GET_MODE (dest) != SImode || !TARGET_ZERO_EXTEND_WITH_AND)
3215 : : {
3216 : 52 : lt_tmp = gen_reg_rtx (QImode);
3217 : 52 : ix86_expand_setcc (lt_tmp, UNLT, gen_rtx_REG (CCFPmode, FLAGS_REG),
3218 : : const0_rtx);
3219 : 52 : if (GET_MODE (dest) != QImode)
3220 : : {
3221 : 52 : tmp = gen_reg_rtx (GET_MODE (dest));
3222 : 52 : emit_insn (gen_rtx_SET (tmp,
3223 : : gen_rtx_ZERO_EXTEND (GET_MODE (dest),
3224 : : lt_tmp)));
3225 : 52 : lt_tmp = tmp;
3226 : : }
3227 : : }
3228 : 52 : rtx gt_tmp;
3229 : 52 : if (zero)
3230 : : {
3231 : : /* If TARGET_IEEE_FP and dest has SImode, emit SImode clear
3232 : : before the floating point comparison and use setcc_si_slp
3233 : : pattern to hide it from the combiner, so that it doesn't
3234 : : undo it. Similarly for TARGET_ZERO_EXTEND_WITH_AND, where
3235 : : the ZERO_EXTEND normally emitted would need to be AND
3236 : : with flags clobber. */
3237 : 34 : tmp = ix86_expand_compare (GT, XEXP (gt, 0), const0_rtx);
3238 : 34 : PUT_MODE (tmp, QImode);
3239 : 34 : emit_insn (gen_setcc_si_slp (zero, tmp, zero));
3240 : 34 : gt_tmp = zero;
3241 : : }
3242 : : else
3243 : : {
3244 : 18 : gt_tmp = gen_reg_rtx (QImode);
3245 : 18 : ix86_expand_setcc (gt_tmp, GT, XEXP (gt, 0), const0_rtx);
3246 : 18 : if (GET_MODE (dest) != QImode)
3247 : : {
3248 : 18 : tmp = gen_reg_rtx (GET_MODE (dest));
3249 : 18 : emit_insn (gen_rtx_SET (tmp,
3250 : : gen_rtx_ZERO_EXTEND (GET_MODE (dest),
3251 : : gt_tmp)));
3252 : 18 : gt_tmp = tmp;
3253 : : }
3254 : : }
3255 : 52 : if (lt_tmp)
3256 : : {
3257 : 52 : tmp = expand_simple_binop (GET_MODE (dest), MINUS, gt_tmp, lt_tmp,
3258 : : dest, 0, OPTAB_DIRECT);
3259 : 52 : if (!rtx_equal_p (tmp, dest))
3260 : 0 : emit_move_insn (dest, tmp);
3261 : : }
3262 : : else
3263 : : {
3264 : : /* For TARGET_ZERO_EXTEND_WITH_AND emit sbb directly, as we can't
3265 : : do ZERO_EXTEND without clobbering flags. */
3266 : 0 : tmp = ix86_expand_compare (UNLT, XEXP (gt, 0), const0_rtx);
3267 : 0 : PUT_MODE (tmp, SImode);
3268 : 0 : emit_insn (gen_subsi3_carry (dest, gt_tmp,
3269 : 0 : force_reg (GET_MODE (dest), const0_rtx),
3270 : : XEXP (gt, 0), tmp));
3271 : : }
3272 : : }
3273 : 298 : emit_jump (lend);
3274 : 298 : if (l2)
3275 : : {
3276 : 261 : emit_label (l2);
3277 : 261 : emit_move_insn (dest, op2 == const0_rtx ? GEN_INT (-128) : op2);
3278 : : }
3279 : 298 : emit_label (lend);
3280 : 298 : }
3281 : :
3282 : : /* Expand integral op0 <=> op1, i.e.
3283 : : dest = op0 == op1 ? 0 : op0 < op1 ? -1 : 1. */
3284 : :
3285 : : void
3286 : 29 : ix86_expand_int_spaceship (rtx dest, rtx op0, rtx op1, rtx op2)
3287 : : {
3288 : 29 : gcc_assert (INTVAL (op2));
3289 : 29 : rtx zero1 = NULL_RTX, zero2 = NULL_RTX;
3290 : 29 : if (TARGET_ZERO_EXTEND_WITH_AND && GET_MODE (dest) == SImode)
3291 : : {
3292 : 0 : zero1 = force_reg (SImode, const0_rtx);
3293 : 0 : if (INTVAL (op2) != 1)
3294 : 0 : zero2 = force_reg (SImode, const0_rtx);
3295 : : }
3296 : :
3297 : : /* Not using ix86_expand_int_compare here, so that it doesn't swap
3298 : : operands nor optimize CC mode - we need a mode usable for both
3299 : : LT and GT resp. LTU and GTU comparisons with the same unswapped
3300 : : operands. */
3301 : 41 : rtx flags = gen_rtx_REG (INTVAL (op2) != 1 ? CCGCmode : CCmode, FLAGS_REG);
3302 : 29 : rtx tmp = gen_rtx_COMPARE (GET_MODE (flags), op0, op1);
3303 : 29 : emit_insn (gen_rtx_SET (flags, tmp));
3304 : 29 : rtx lt_tmp = NULL_RTX;
3305 : 29 : if (zero2)
3306 : : {
3307 : : /* For TARGET_ZERO_EXTEND_WITH_AND, emit setcc_si_slp to avoid
3308 : : ZERO_EXTEND. */
3309 : 0 : tmp = ix86_expand_compare (LT, flags, const0_rtx);
3310 : 0 : PUT_MODE (tmp, QImode);
3311 : 0 : emit_insn (gen_setcc_si_slp (zero2, tmp, zero2));
3312 : 0 : lt_tmp = zero2;
3313 : : }
3314 : 29 : else if (!zero1)
3315 : : {
3316 : 29 : lt_tmp = gen_reg_rtx (QImode);
3317 : 41 : ix86_expand_setcc (lt_tmp, INTVAL (op2) != 1 ? LT : LTU, flags,
3318 : : const0_rtx);
3319 : 29 : if (GET_MODE (dest) != QImode)
3320 : : {
3321 : 29 : tmp = gen_reg_rtx (GET_MODE (dest));
3322 : 29 : emit_insn (gen_rtx_SET (tmp, gen_rtx_ZERO_EXTEND (GET_MODE (dest),
3323 : : lt_tmp)));
3324 : 29 : lt_tmp = tmp;
3325 : : }
3326 : : }
3327 : 29 : rtx gt_tmp;
3328 : 29 : if (zero1)
3329 : : {
3330 : : /* For TARGET_ZERO_EXTEND_WITH_AND, emit setcc_si_slp to avoid
3331 : : ZERO_EXTEND. */
3332 : 0 : tmp = ix86_expand_compare (INTVAL (op2) != 1 ? GT : GTU, flags,
3333 : : const0_rtx);
3334 : 0 : PUT_MODE (tmp, QImode);
3335 : 0 : emit_insn (gen_setcc_si_slp (zero1, tmp, zero1));
3336 : 0 : gt_tmp = zero1;
3337 : : }
3338 : : else
3339 : : {
3340 : 29 : gt_tmp = gen_reg_rtx (QImode);
3341 : 41 : ix86_expand_setcc (gt_tmp, INTVAL (op2) != 1 ? GT : GTU, flags,
3342 : : const0_rtx);
3343 : 29 : if (GET_MODE (dest) != QImode)
3344 : : {
3345 : 29 : tmp = gen_reg_rtx (GET_MODE (dest));
3346 : 29 : emit_insn (gen_rtx_SET (tmp, gen_rtx_ZERO_EXTEND (GET_MODE (dest),
3347 : : gt_tmp)));
3348 : 29 : gt_tmp = tmp;
3349 : : }
3350 : : }
3351 : 29 : if (lt_tmp)
3352 : : {
3353 : 29 : tmp = expand_simple_binop (GET_MODE (dest), MINUS, gt_tmp, lt_tmp, dest,
3354 : : 0, OPTAB_DIRECT);
3355 : 29 : if (!rtx_equal_p (tmp, dest))
3356 : 0 : emit_move_insn (dest, tmp);
3357 : : }
3358 : : else
3359 : : {
3360 : : /* For TARGET_ZERO_EXTEND_WITH_AND emit sbb directly, as we can't
3361 : : do ZERO_EXTEND without clobbering flags. */
3362 : 0 : tmp = ix86_expand_compare (LTU, flags, const0_rtx);
3363 : 0 : PUT_MODE (tmp, SImode);
3364 : 0 : emit_insn (gen_subsi3_carry (dest, gt_tmp,
3365 : 0 : force_reg (GET_MODE (dest), const0_rtx),
3366 : : flags, tmp));
3367 : : }
3368 : 29 : }
3369 : :
3370 : : /* Expand comparison setting or clearing carry flag. Return true when
3371 : : successful and set pop for the operation. */
3372 : : static bool
3373 : 29996 : ix86_expand_carry_flag_compare (enum rtx_code code, rtx op0, rtx op1, rtx *pop)
3374 : : {
3375 : 59992 : machine_mode mode
3376 : 29996 : = GET_MODE (op0) != VOIDmode ? GET_MODE (op0) : GET_MODE (op1);
3377 : :
3378 : : /* Do not handle double-mode compares that go through special path. */
3379 : 31706 : if (mode == (TARGET_64BIT ? TImode : DImode))
3380 : : return false;
3381 : :
3382 : 29988 : if (SCALAR_FLOAT_MODE_P (mode))
3383 : : {
3384 : 241 : rtx compare_op;
3385 : 241 : rtx_insn *compare_seq;
3386 : :
3387 : 241 : gcc_assert (!DECIMAL_FLOAT_MODE_P (mode));
3388 : :
3389 : : /* Shortcut: following common codes never translate
3390 : : into carry flag compares. */
3391 : 241 : if (code == EQ || code == NE || code == UNEQ || code == LTGT
3392 : : || code == ORDERED || code == UNORDERED)
3393 : : return false;
3394 : :
3395 : : /* These comparisons require zero flag; swap operands so they won't. */
3396 : : if ((code == GT || code == UNLE || code == LE || code == UNGT)
3397 : 200 : && !TARGET_IEEE_FP)
3398 : : {
3399 : 2 : std::swap (op0, op1);
3400 : 2 : code = swap_condition (code);
3401 : : }
3402 : :
3403 : : /* Try to expand the comparison and verify that we end up with
3404 : : carry flag based comparison. This fails to be true only when
3405 : : we decide to expand comparison using arithmetic that is not
3406 : : too common scenario. */
3407 : 239 : start_sequence ();
3408 : 239 : compare_op = ix86_expand_fp_compare (code, op0, op1);
3409 : 239 : compare_seq = end_sequence ();
3410 : :
3411 : 239 : if (GET_MODE (XEXP (compare_op, 0)) == CCFPmode)
3412 : 239 : code = ix86_fp_compare_code_to_integer (GET_CODE (compare_op));
3413 : : else
3414 : 0 : code = GET_CODE (compare_op);
3415 : :
3416 : 239 : if (code != LTU && code != GEU)
3417 : : return false;
3418 : :
3419 : 39 : emit_insn (compare_seq);
3420 : 39 : *pop = compare_op;
3421 : 39 : return true;
3422 : : }
3423 : :
3424 : 29747 : if (!INTEGRAL_MODE_P (mode))
3425 : : return false;
3426 : :
3427 : 29641 : switch (code)
3428 : : {
3429 : : case LTU:
3430 : : case GEU:
3431 : : break;
3432 : :
3433 : : /* Convert a==0 into (unsigned)a<1. */
3434 : 25919 : case EQ:
3435 : 25919 : case NE:
3436 : 25919 : if (op1 != const0_rtx)
3437 : : return false;
3438 : 6892 : op1 = const1_rtx;
3439 : 6892 : code = (code == EQ ? LTU : GEU);
3440 : : break;
3441 : :
3442 : : /* Convert a>b into b<a or a>=b-1. */
3443 : 1093 : case GTU:
3444 : 1093 : case LEU:
3445 : 1093 : if (CONST_INT_P (op1))
3446 : : {
3447 : 1051 : op1 = gen_int_mode (INTVAL (op1) + 1, GET_MODE (op0));
3448 : : /* Bail out on overflow. We still can swap operands but that
3449 : : would force loading of the constant into register. */
3450 : 1051 : if (op1 == const0_rtx
3451 : 1051 : || !x86_64_immediate_operand (op1, GET_MODE (op1)))
3452 : 0 : return false;
3453 : 1051 : code = (code == GTU ? GEU : LTU);
3454 : : }
3455 : : else
3456 : : {
3457 : 42 : std::swap (op0, op1);
3458 : 42 : code = (code == GTU ? LTU : GEU);
3459 : : }
3460 : : break;
3461 : :
3462 : : /* Convert a>=0 into (unsigned)a<0x80000000. */
3463 : 1296 : case LT:
3464 : 1296 : case GE:
3465 : 1296 : if (mode == DImode || op1 != const0_rtx)
3466 : : return false;
3467 : 210 : op1 = gen_int_mode (1 << (GET_MODE_BITSIZE (mode) - 1), mode);
3468 : 105 : code = (code == LT ? GEU : LTU);
3469 : : break;
3470 : 738 : case LE:
3471 : 738 : case GT:
3472 : 738 : if (mode == DImode || op1 != constm1_rtx)
3473 : : return false;
3474 : 0 : op1 = gen_int_mode (1 << (GET_MODE_BITSIZE (mode) - 1), mode);
3475 : 0 : code = (code == LE ? GEU : LTU);
3476 : : break;
3477 : :
3478 : : default:
3479 : : return false;
3480 : : }
3481 : : /* Swapping operands may cause constant to appear as first operand. */
3482 : 8685 : if (!nonimmediate_operand (op0, VOIDmode))
3483 : : {
3484 : 0 : if (!can_create_pseudo_p ())
3485 : : return false;
3486 : 0 : op0 = force_reg (mode, op0);
3487 : : }
3488 : 8685 : *pop = ix86_expand_compare (code, op0, op1);
3489 : 8685 : gcc_assert (GET_CODE (*pop) == LTU || GET_CODE (*pop) == GEU);
3490 : : return true;
3491 : : }
3492 : :
3493 : : /* Expand conditional increment or decrement using adb/sbb instructions.
3494 : : The default case using setcc followed by the conditional move can be
3495 : : done by generic code. */
3496 : : bool
3497 : 7433 : ix86_expand_int_addcc (rtx operands[])
3498 : : {
3499 : 7433 : enum rtx_code code = GET_CODE (operands[1]);
3500 : 7433 : rtx flags;
3501 : 7433 : rtx (*insn) (machine_mode, rtx, rtx, rtx, rtx, rtx);
3502 : 7433 : rtx compare_op;
3503 : 7433 : rtx val = const0_rtx;
3504 : 7433 : bool fpcmp = false;
3505 : 7433 : machine_mode mode;
3506 : 7433 : rtx op0 = XEXP (operands[1], 0);
3507 : 7433 : rtx op1 = XEXP (operands[1], 1);
3508 : :
3509 : 7433 : if (operands[3] != const1_rtx
3510 : 3120 : && operands[3] != constm1_rtx)
3511 : : return false;
3512 : 5172 : if (!ix86_expand_carry_flag_compare (code, op0, op1, &compare_op))
3513 : : return false;
3514 : 1214 : code = GET_CODE (compare_op);
3515 : :
3516 : 1214 : flags = XEXP (compare_op, 0);
3517 : :
3518 : 1214 : if (GET_MODE (flags) == CCFPmode)
3519 : : {
3520 : 4 : fpcmp = true;
3521 : 4 : code = ix86_fp_compare_code_to_integer (code);
3522 : : }
3523 : :
3524 : 1214 : if (code != LTU)
3525 : : {
3526 : 660 : val = constm1_rtx;
3527 : 660 : if (fpcmp)
3528 : 4 : PUT_CODE (compare_op,
3529 : : reverse_condition_maybe_unordered
3530 : : (GET_CODE (compare_op)));
3531 : : else
3532 : 656 : PUT_CODE (compare_op, reverse_condition (GET_CODE (compare_op)));
3533 : : }
3534 : :
3535 : 1214 : mode = GET_MODE (operands[0]);
3536 : :
3537 : : /* Construct either adc or sbb insn. */
3538 : 1214 : if ((code == LTU) == (operands[3] == constm1_rtx))
3539 : : insn = gen_sub3_carry;
3540 : : else
3541 : 533 : insn = gen_add3_carry;
3542 : :
3543 : 1214 : emit_insn (insn (mode, operands[0], operands[2], val, flags, compare_op));
3544 : :
3545 : 1214 : return true;
3546 : : }
3547 : :
3548 : : bool
3549 : 414387 : ix86_expand_int_movcc (rtx operands[])
3550 : : {
3551 : 414387 : enum rtx_code code = GET_CODE (operands[1]), compare_code;
3552 : 414387 : rtx_insn *compare_seq;
3553 : 414387 : rtx compare_op;
3554 : 414387 : machine_mode mode = GET_MODE (operands[0]);
3555 : 414387 : bool sign_bit_compare_p = false;
3556 : 414387 : bool negate_cc_compare_p = false;
3557 : 414387 : rtx op0 = XEXP (operands[1], 0);
3558 : 414387 : rtx op1 = XEXP (operands[1], 1);
3559 : 414387 : rtx op2 = operands[2];
3560 : 414387 : rtx op3 = operands[3];
3561 : :
3562 : 414387 : if (GET_MODE (op0) == TImode
3563 : 398943 : || (GET_MODE (op0) == DImode
3564 : 94005 : && !TARGET_64BIT))
3565 : : return false;
3566 : :
3567 : 398195 : if (GET_MODE (op0) == BFmode
3568 : 398195 : && !ix86_fp_comparison_operator (operands[1], VOIDmode))
3569 : : return false;
3570 : :
3571 : 398195 : start_sequence ();
3572 : 398195 : compare_op = ix86_expand_compare (code, op0, op1);
3573 : 398195 : compare_seq = end_sequence ();
3574 : :
3575 : 398195 : compare_code = GET_CODE (compare_op);
3576 : :
3577 : 398195 : if ((op1 == const0_rtx && (code == GE || code == LT))
3578 : 358603 : || (op1 == constm1_rtx && (code == GT || code == LE)))
3579 : : sign_bit_compare_p = true;
3580 : :
3581 : : /* op0 == op1 ? op0 : op3 is equivalent to op0 == op1 ? op1 : op3,
3582 : : but if op1 is a constant, the latter form allows more optimizations,
3583 : : either through the last 2 ops being constant handling, or the one
3584 : : constant and one variable cases. On the other side, for cmov the
3585 : : former might be better as we don't need to load the constant into
3586 : : another register. */
3587 : 358603 : if (code == EQ && CONST_INT_P (op1) && rtx_equal_p (op0, op2))
3588 : : op2 = op1;
3589 : : /* Similarly for op0 != op1 ? op2 : op0 and op0 != op1 ? op2 : op1. */
3590 : 397744 : else if (code == NE && CONST_INT_P (op1) && rtx_equal_p (op0, op3))
3591 : : op3 = op1;
3592 : :
3593 : : /* Don't attempt mode expansion here -- if we had to expand 5 or 6
3594 : : HImode insns, we'd be swallowed in word prefix ops. */
3595 : :
3596 : 4763 : if ((mode != HImode || TARGET_FAST_PREFIX)
3597 : 424540 : && (mode != (TARGET_64BIT ? TImode : DImode))
3598 : 398195 : && CONST_INT_P (op2)
3599 : 429349 : && CONST_INT_P (op3))
3600 : : {
3601 : 25372 : rtx out = operands[0];
3602 : 25372 : HOST_WIDE_INT ct = INTVAL (op2);
3603 : 25372 : HOST_WIDE_INT cf = INTVAL (op3);
3604 : 25372 : HOST_WIDE_INT diff;
3605 : :
3606 : 25372 : if ((mode == SImode
3607 : 16725 : || (TARGET_64BIT && mode == DImode))
3608 : 11509 : && (GET_MODE (op0) == SImode
3609 : 8420 : || (TARGET_64BIT && GET_MODE (op0) == DImode)))
3610 : : {
3611 : : /* Special case x != 0 ? -1 : y. */
3612 : 7606 : if (code == NE && op1 == const0_rtx && ct == -1)
3613 : : {
3614 : : negate_cc_compare_p = true;
3615 : : std::swap (ct, cf);
3616 : : code = EQ;
3617 : : }
3618 : 7571 : else if (code == EQ && op1 == const0_rtx && cf == -1)
3619 : 25372 : negate_cc_compare_p = true;
3620 : : }
3621 : :
3622 : 25372 : diff = (unsigned HOST_WIDE_INT) ct - cf;
3623 : : /* Make sure we can represent the difference between the two values. */
3624 : 25372 : if ((diff > 0) != ((cf < 0) != (ct < 0) ? cf < 0 : cf < ct))
3625 : 414387 : return false;
3626 : :
3627 : : /* Sign bit compares are better done using shifts than we do by using
3628 : : sbb. */
3629 : 25276 : if (sign_bit_compare_p
3630 : 25276 : || negate_cc_compare_p
3631 : 25276 : || ix86_expand_carry_flag_compare (code, op0, op1, &compare_op))
3632 : : {
3633 : : /* Detect overlap between destination and compare sources. */
3634 : 7962 : rtx tmp = out;
3635 : :
3636 : 7962 : if (negate_cc_compare_p)
3637 : : {
3638 : 132 : if (GET_MODE (op0) == DImode)
3639 : 50 : emit_insn (gen_x86_negdi_ccc (gen_reg_rtx (DImode), op0));
3640 : : else
3641 : 82 : emit_insn (gen_x86_negsi_ccc (gen_reg_rtx (SImode),
3642 : 82 : gen_lowpart (SImode, op0)));
3643 : :
3644 : 132 : tmp = gen_reg_rtx (mode);
3645 : 132 : if (mode == DImode)
3646 : 49 : emit_insn (gen_x86_movdicc_0_m1_neg (tmp));
3647 : : else
3648 : 83 : emit_insn (gen_x86_movsicc_0_m1_neg (gen_lowpart (SImode,
3649 : : tmp)));
3650 : : }
3651 : 7830 : else if (!sign_bit_compare_p)
3652 : : {
3653 : 7510 : rtx flags;
3654 : 7510 : bool fpcmp = false;
3655 : :
3656 : 7510 : compare_code = GET_CODE (compare_op);
3657 : :
3658 : 7510 : flags = XEXP (compare_op, 0);
3659 : :
3660 : 7510 : if (GET_MODE (flags) == CCFPmode)
3661 : : {
3662 : 35 : fpcmp = true;
3663 : 35 : compare_code
3664 : 35 : = ix86_fp_compare_code_to_integer (compare_code);
3665 : : }
3666 : :
3667 : : /* To simplify rest of code, restrict to the GEU case. */
3668 : 7510 : if (compare_code == LTU)
3669 : : {
3670 : 3248 : std::swap (ct, cf);
3671 : 3248 : compare_code = reverse_condition (compare_code);
3672 : 3248 : code = reverse_condition (code);
3673 : : }
3674 : : else
3675 : : {
3676 : 4262 : if (fpcmp)
3677 : 35 : PUT_CODE (compare_op,
3678 : : reverse_condition_maybe_unordered
3679 : : (GET_CODE (compare_op)));
3680 : : else
3681 : 4227 : PUT_CODE (compare_op,
3682 : : reverse_condition (GET_CODE (compare_op)));
3683 : : }
3684 : :
3685 : 7510 : diff = (unsigned HOST_WIDE_INT) ct - cf;
3686 : : /* Make sure we can represent the difference
3687 : : between the two values. */
3688 : 7510 : if ((diff > 0) != ((cf < 0) != (ct < 0) ? cf < 0 : cf < ct))
3689 : : return false;
3690 : :
3691 : 7509 : if (reg_overlap_mentioned_p (out, compare_op))
3692 : 0 : tmp = gen_reg_rtx (mode);
3693 : :
3694 : 7509 : if (mode == DImode)
3695 : 2107 : emit_insn (gen_x86_movdicc_0_m1 (tmp, flags, compare_op));
3696 : : else
3697 : 5402 : emit_insn (gen_x86_movsicc_0_m1 (gen_lowpart (SImode, tmp),
3698 : : flags, compare_op));
3699 : : }
3700 : : else
3701 : : {
3702 : 320 : if (code == GT || code == GE)
3703 : 121 : code = reverse_condition (code);
3704 : : else
3705 : : {
3706 : 199 : std::swap (ct, cf);
3707 : :
3708 : 199 : diff = (unsigned HOST_WIDE_INT) ct - cf;
3709 : : /* Make sure we can represent the difference
3710 : : between the two values. */
3711 : 199 : if ((diff > 0) != ((cf < 0) != (ct < 0) ? cf < 0 : cf < ct))
3712 : : return false;
3713 : : }
3714 : 317 : tmp = emit_store_flag (tmp, code, op0, op1, VOIDmode, 0, -1);
3715 : : }
3716 : :
3717 : 7958 : if (diff == 1)
3718 : : {
3719 : : /*
3720 : : * cmpl op0,op1
3721 : : * sbbl dest,dest
3722 : : * [addl dest, ct]
3723 : : *
3724 : : * Size 5 - 8.
3725 : : */
3726 : 1120 : if (ct)
3727 : 1092 : tmp = expand_simple_binop (mode, PLUS,
3728 : : tmp, GEN_INT (ct),
3729 : : copy_rtx (tmp), 1, OPTAB_DIRECT);
3730 : : }
3731 : 6838 : else if (cf == -1)
3732 : : {
3733 : : /*
3734 : : * cmpl op0,op1
3735 : : * sbbl dest,dest
3736 : : * orl $ct, dest
3737 : : *
3738 : : * Size 8.
3739 : : */
3740 : 428 : tmp = expand_simple_binop (mode, IOR,
3741 : : tmp, GEN_INT (ct),
3742 : : copy_rtx (tmp), 1, OPTAB_DIRECT);
3743 : : }
3744 : 6410 : else if (diff == -1 && ct)
3745 : : {
3746 : : /*
3747 : : * cmpl op0,op1
3748 : : * sbbl dest,dest
3749 : : * notl dest
3750 : : * [addl dest, cf]
3751 : : *
3752 : : * Size 8 - 11.
3753 : : */
3754 : 655 : tmp = expand_simple_unop (mode, NOT, tmp, copy_rtx (tmp), 1);
3755 : 655 : if (cf)
3756 : 655 : tmp = expand_simple_binop (mode, PLUS,
3757 : : copy_rtx (tmp), GEN_INT (cf),
3758 : : copy_rtx (tmp), 1, OPTAB_DIRECT);
3759 : : }
3760 : : else
3761 : : {
3762 : : /*
3763 : : * cmpl op0,op1
3764 : : * sbbl dest,dest
3765 : : * [notl dest]
3766 : : * andl cf - ct, dest
3767 : : * [addl dest, ct]
3768 : : *
3769 : : * Size 8 - 11.
3770 : : */
3771 : :
3772 : 5755 : if (cf == 0)
3773 : : {
3774 : 676 : cf = ct;
3775 : 676 : ct = 0;
3776 : 676 : tmp = expand_simple_unop (mode, NOT, tmp, copy_rtx (tmp), 1);
3777 : : }
3778 : :
3779 : 5755 : HOST_WIDE_INT ival = (unsigned HOST_WIDE_INT) cf - ct;
3780 : : /* Make sure we can represent the difference
3781 : : between the two values. */
3782 : 5755 : if ((ival > 0) != ((ct < 0) != (cf < 0) ? ct < 0 : ct < cf))
3783 : 16292 : return false;
3784 : :
3785 : 5755 : tmp = expand_simple_binop (mode, AND,
3786 : : copy_rtx (tmp),
3787 : 5755 : gen_int_mode (ival, mode),
3788 : : copy_rtx (tmp), 1, OPTAB_DIRECT);
3789 : 5755 : if (ct)
3790 : 4402 : tmp = expand_simple_binop (mode, PLUS,
3791 : : copy_rtx (tmp), GEN_INT (ct),
3792 : : copy_rtx (tmp), 1, OPTAB_DIRECT);
3793 : : }
3794 : :
3795 : 7958 : if (!rtx_equal_p (tmp, out))
3796 : 265 : emit_move_insn (copy_rtx (out), copy_rtx (tmp));
3797 : :
3798 : 7958 : return true;
3799 : : }
3800 : :
3801 : 17314 : if (diff < 0)
3802 : : {
3803 : 8356 : machine_mode cmp_mode = GET_MODE (op0);
3804 : 8356 : enum rtx_code new_code;
3805 : :
3806 : 8356 : if (SCALAR_FLOAT_MODE_P (cmp_mode))
3807 : : {
3808 : 42 : gcc_assert (!DECIMAL_FLOAT_MODE_P (cmp_mode));
3809 : :
3810 : : /* We may be reversing a non-trapping
3811 : : comparison to a trapping comparison. */
3812 : 80 : if (HONOR_NANS (cmp_mode) && flag_trapping_math
3813 : 29 : && code != EQ && code != NE
3814 : 71 : && code != ORDERED && code != UNORDERED)
3815 : : new_code = UNKNOWN;
3816 : : else
3817 : 13 : new_code = reverse_condition_maybe_unordered (code);
3818 : : }
3819 : : else
3820 : 8314 : new_code = ix86_reverse_condition (code, cmp_mode);
3821 : 8327 : if (new_code != UNKNOWN)
3822 : : {
3823 : 8327 : std::swap (ct, cf);
3824 : :
3825 : 8327 : diff = (unsigned HOST_WIDE_INT) ct - cf;
3826 : : /* Make sure we can represent the difference
3827 : : between the two values. */
3828 : 8327 : if ((diff > 0) != ((cf < 0) != (ct < 0) ? cf < 0 : cf < ct))
3829 : : return false;
3830 : :
3831 : : code = new_code;
3832 : : }
3833 : : }
3834 : :
3835 : 17314 : compare_code = UNKNOWN;
3836 : 17314 : if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT
3837 : 17155 : && CONST_INT_P (op1))
3838 : : {
3839 : 13135 : if (op1 == const0_rtx
3840 : 86 : && (code == LT || code == GE))
3841 : : compare_code = code;
3842 : 13135 : else if (op1 == constm1_rtx)
3843 : : {
3844 : 206 : if (code == LE)
3845 : : compare_code = LT;
3846 : 206 : else if (code == GT)
3847 : : compare_code = GE;
3848 : : }
3849 : : }
3850 : :
3851 : : /* Optimize dest = (op0 < 0) ? -1 : cf. */
3852 : : if (compare_code != UNKNOWN
3853 : 0 : && GET_MODE (op0) == GET_MODE (out)
3854 : 0 : && (cf == -1 || ct == -1))
3855 : : {
3856 : : /* If lea code below could be used, only optimize
3857 : : if it results in a 2 insn sequence. */
3858 : :
3859 : 0 : if (! (diff == 1 || diff == 2 || diff == 4 || diff == 8
3860 : 0 : || diff == 3 || diff == 5 || diff == 9)
3861 : 0 : || (compare_code == LT && ct == -1)
3862 : 0 : || (compare_code == GE && cf == -1))
3863 : : {
3864 : : /*
3865 : : * notl op1 (if necessary)
3866 : : * sarl $31, op1
3867 : : * orl cf, op1
3868 : : */
3869 : 0 : if (ct != -1)
3870 : : {
3871 : 0 : cf = ct;
3872 : 0 : ct = -1;
3873 : 0 : code = reverse_condition (code);
3874 : : }
3875 : :
3876 : 0 : out = emit_store_flag (out, code, op0, op1, VOIDmode, 0, -1);
3877 : :
3878 : 0 : out = expand_simple_binop (mode, IOR,
3879 : : out, GEN_INT (cf),
3880 : : out, 1, OPTAB_DIRECT);
3881 : 0 : if (out != operands[0])
3882 : 0 : emit_move_insn (operands[0], out);
3883 : :
3884 : 0 : return true;
3885 : : }
3886 : : }
3887 : :
3888 : :
3889 : 29763 : if ((diff == 1 || diff == 2 || diff == 4 || diff == 8
3890 : 12449 : || diff == 3 || diff == 5 || diff == 9)
3891 : 5084 : && ((mode != QImode && mode != HImode) || !TARGET_PARTIAL_REG_STALL)
3892 : 22398 : && (mode != DImode
3893 : 243 : || x86_64_immediate_operand (GEN_INT (cf), VOIDmode)))
3894 : : {
3895 : : /*
3896 : : * xorl dest,dest
3897 : : * cmpl op1,op2
3898 : : * setcc dest
3899 : : * lea cf(dest*(ct-cf)),dest
3900 : : *
3901 : : * Size 14.
3902 : : *
3903 : : * This also catches the degenerate setcc-only case.
3904 : : */
3905 : :
3906 : 5084 : rtx tmp;
3907 : 5084 : int nops;
3908 : :
3909 : 5084 : out = emit_store_flag (out, code, op0, op1, VOIDmode, 0, 1);
3910 : :
3911 : 5084 : nops = 0;
3912 : : /* On x86_64 the lea instruction operates on Pmode, so we need
3913 : : to get arithmetics done in proper mode to match. */
3914 : 5084 : if (diff == 1)
3915 : 4260 : tmp = copy_rtx (out);
3916 : : else
3917 : : {
3918 : 824 : rtx out1;
3919 : 824 : out1 = copy_rtx (out);
3920 : 824 : tmp = gen_rtx_MULT (mode, out1, GEN_INT (diff & ~1));
3921 : 824 : nops++;
3922 : 824 : if (diff & 1)
3923 : : {
3924 : 179 : tmp = gen_rtx_PLUS (mode, tmp, out1);
3925 : 179 : nops++;
3926 : : }
3927 : : }
3928 : 5084 : if (cf != 0)
3929 : : {
3930 : 4306 : tmp = plus_constant (mode, tmp, cf);
3931 : 4306 : nops++;
3932 : : }
3933 : 5084 : if (!rtx_equal_p (tmp, out))
3934 : : {
3935 : 4427 : if (nops == 1)
3936 : 3607 : out = force_operand (tmp, copy_rtx (out));
3937 : : else
3938 : 820 : emit_insn (gen_rtx_SET (copy_rtx (out), copy_rtx (tmp)));
3939 : : }
3940 : 5084 : if (!rtx_equal_p (out, operands[0]))
3941 : 750 : emit_move_insn (operands[0], copy_rtx (out));
3942 : :
3943 : 5084 : return true;
3944 : : }
3945 : :
3946 : : /*
3947 : : * General case: Jumpful:
3948 : : * xorl dest,dest cmpl op1, op2
3949 : : * cmpl op1, op2 movl ct, dest
3950 : : * setcc dest jcc 1f
3951 : : * decl dest movl cf, dest
3952 : : * andl (cf-ct),dest 1:
3953 : : * addl ct,dest
3954 : : *
3955 : : * Size 20. Size 14.
3956 : : *
3957 : : * This is reasonably steep, but branch mispredict costs are
3958 : : * high on modern cpus, so consider failing only if optimizing
3959 : : * for space.
3960 : : */
3961 : :
3962 : 12230 : if ((!TARGET_CMOVE || (mode == QImode && TARGET_PARTIAL_REG_STALL))
3963 : 12230 : && BRANCH_COST (optimize_insn_for_speed_p (),
3964 : : false) >= 2)
3965 : : {
3966 : 0 : if (cf == 0)
3967 : : {
3968 : 0 : machine_mode cmp_mode = GET_MODE (op0);
3969 : 0 : enum rtx_code new_code;
3970 : :
3971 : 0 : if (SCALAR_FLOAT_MODE_P (cmp_mode))
3972 : : {
3973 : 0 : gcc_assert (!DECIMAL_FLOAT_MODE_P (cmp_mode));
3974 : :
3975 : : /* We may be reversing a non-trapping
3976 : : comparison to a trapping comparison. */
3977 : 0 : if (HONOR_NANS (cmp_mode) && flag_trapping_math
3978 : 0 : && code != EQ && code != NE
3979 : 0 : && code != ORDERED && code != UNORDERED)
3980 : : new_code = UNKNOWN;
3981 : : else
3982 : 0 : new_code = reverse_condition_maybe_unordered (code);
3983 : :
3984 : : }
3985 : : else
3986 : : {
3987 : 0 : new_code = ix86_reverse_condition (code, cmp_mode);
3988 : 0 : if (compare_code != UNKNOWN && new_code != UNKNOWN)
3989 : 0 : compare_code = reverse_condition (compare_code);
3990 : : }
3991 : :
3992 : 0 : if (new_code != UNKNOWN)
3993 : : {
3994 : 0 : cf = ct;
3995 : 0 : ct = 0;
3996 : 0 : code = new_code;
3997 : : }
3998 : : }
3999 : :
4000 : 0 : if (compare_code != UNKNOWN)
4001 : : {
4002 : : /* notl op1 (if needed)
4003 : : sarl $31, op1
4004 : : andl (cf-ct), op1
4005 : : addl ct, op1
4006 : :
4007 : : For x < 0 (resp. x <= -1) there will be no notl,
4008 : : so if possible swap the constants to get rid of the
4009 : : complement.
4010 : : True/false will be -1/0 while code below (store flag
4011 : : followed by decrement) is 0/-1, so the constants need
4012 : : to be exchanged once more. */
4013 : :
4014 : 0 : if (compare_code == GE || !cf)
4015 : : {
4016 : 0 : code = reverse_condition (code);
4017 : 0 : compare_code = LT;
4018 : : }
4019 : : else
4020 : : std::swap (ct, cf);
4021 : :
4022 : 0 : out = emit_store_flag (out, code, op0, op1, VOIDmode, 0, -1);
4023 : : }
4024 : : else
4025 : : {
4026 : 0 : out = emit_store_flag (out, code, op0, op1, VOIDmode, 0, 1);
4027 : :
4028 : 0 : out = expand_simple_binop (mode, PLUS, copy_rtx (out),
4029 : : constm1_rtx,
4030 : : copy_rtx (out), 1, OPTAB_DIRECT);
4031 : : }
4032 : :
4033 : 0 : HOST_WIDE_INT ival = (unsigned HOST_WIDE_INT) cf - ct;
4034 : : /* Make sure we can represent the difference
4035 : : between the two values. */
4036 : 0 : if ((ival > 0) != ((ct < 0) != (cf < 0) ? ct < 0 : ct < cf))
4037 : : return false;
4038 : :
4039 : 0 : out = expand_simple_binop (mode, AND, copy_rtx (out),
4040 : 0 : gen_int_mode (ival, mode),
4041 : : copy_rtx (out), 1, OPTAB_DIRECT);
4042 : 0 : if (ct)
4043 : 0 : out = expand_simple_binop (mode, PLUS, copy_rtx (out), GEN_INT (ct),
4044 : : copy_rtx (out), 1, OPTAB_DIRECT);
4045 : 0 : if (!rtx_equal_p (out, operands[0]))
4046 : 0 : emit_move_insn (operands[0], copy_rtx (out));
4047 : :
4048 : 0 : return true;
4049 : : }
4050 : : }
4051 : :
4052 : 385053 : if (!TARGET_CMOVE || (mode == QImode && TARGET_PARTIAL_REG_STALL))
4053 : : {
4054 : : /* Try a few things more with specific constants and a variable. */
4055 : :
4056 : 0 : optab op;
4057 : 0 : rtx var, orig_out, out, tmp;
4058 : :
4059 : 0 : if (BRANCH_COST (optimize_insn_for_speed_p (), false) <= 2)
4060 : : return false;
4061 : :
4062 : 0 : operands[2] = op2;
4063 : 0 : operands[3] = op3;
4064 : :
4065 : : /* If one of the two operands is an interesting constant, load a
4066 : : constant with the above and mask it in with a logical operation. */
4067 : :
4068 : 0 : if (CONST_INT_P (operands[2]))
4069 : : {
4070 : 0 : var = operands[3];
4071 : 0 : if (INTVAL (operands[2]) == 0 && operands[3] != constm1_rtx)
4072 : 0 : operands[3] = constm1_rtx, op = and_optab;
4073 : 0 : else if (INTVAL (operands[2]) == -1 && operands[3] != const0_rtx)
4074 : 0 : operands[3] = const0_rtx, op = ior_optab;
4075 : : else
4076 : : return false;
4077 : : }
4078 : 0 : else if (CONST_INT_P (operands[3]))
4079 : : {
4080 : 0 : var = operands[2];
4081 : 0 : if (INTVAL (operands[3]) == 0 && operands[2] != constm1_rtx)
4082 : : {
4083 : : /* For smin (x, 0), expand as "x < 0 ? x : 0" instead of
4084 : : "x <= 0 ? x : 0" to enable sign_bit_compare_p. */
4085 : 0 : if (code == LE && op1 == const0_rtx && rtx_equal_p (op0, var))
4086 : 0 : operands[1] = simplify_gen_relational (LT, VOIDmode,
4087 : 0 : GET_MODE (op0),
4088 : : op0, const0_rtx);
4089 : :
4090 : 0 : operands[2] = constm1_rtx;
4091 : 0 : op = and_optab;
4092 : : }
4093 : 0 : else if (INTVAL (operands[3]) == -1 && operands[3] != const0_rtx)
4094 : 0 : operands[2] = const0_rtx, op = ior_optab;
4095 : : else
4096 : : return false;
4097 : : }
4098 : : else
4099 : : return false;
4100 : :
4101 : 0 : orig_out = operands[0];
4102 : 0 : tmp = gen_reg_rtx (mode);
4103 : 0 : operands[0] = tmp;
4104 : :
4105 : : /* Recurse to get the constant loaded. */
4106 : 0 : if (!ix86_expand_int_movcc (operands))
4107 : : return false;
4108 : :
4109 : : /* Mask in the interesting variable. */
4110 : 0 : out = expand_binop (mode, op, var, tmp, orig_out, 0,
4111 : : OPTAB_WIDEN);
4112 : 0 : if (!rtx_equal_p (out, orig_out))
4113 : 0 : emit_move_insn (copy_rtx (orig_out), copy_rtx (out));
4114 : :
4115 : 0 : return true;
4116 : : }
4117 : :
4118 : : /*
4119 : : * For comparison with above,
4120 : : *
4121 : : * movl cf,dest
4122 : : * movl ct,tmp
4123 : : * cmpl op1,op2
4124 : : * cmovcc tmp,dest
4125 : : *
4126 : : * Size 15.
4127 : : */
4128 : :
4129 : 385053 : if (! nonimmediate_operand (operands[2], mode))
4130 : 27965 : operands[2] = force_reg (mode, operands[2]);
4131 : 385053 : if (! nonimmediate_operand (operands[3], mode))
4132 : 161331 : operands[3] = force_reg (mode, operands[3]);
4133 : :
4134 : 385053 : if (! register_operand (operands[2], VOIDmode)
4135 : 385053 : && (mode == QImode
4136 : 1093 : || ! register_operand (operands[3], VOIDmode)))
4137 : 1564 : operands[2] = force_reg (mode, operands[2]);
4138 : :
4139 : 385053 : if (mode == QImode
4140 : 385053 : && ! register_operand (operands[3], VOIDmode))
4141 : 592 : operands[3] = force_reg (mode, operands[3]);
4142 : :
4143 : 385053 : emit_insn (compare_seq);
4144 : 385053 : emit_insn (gen_rtx_SET (operands[0],
4145 : : gen_rtx_IF_THEN_ELSE (mode,
4146 : : compare_op, operands[2],
4147 : : operands[3])));
4148 : 385053 : return true;
4149 : : }
4150 : :
4151 : : /* Detect conditional moves that exactly match min/max operational
4152 : : semantics. Note that this is IEEE safe, as long as we don't
4153 : : interchange the operands.
4154 : :
4155 : : Returns FALSE if this conditional move doesn't match a MIN/MAX,
4156 : : and TRUE if the operation is successful and instructions are emitted. */
4157 : :
4158 : : static bool
4159 : 9283 : ix86_expand_sse_fp_minmax (rtx dest, enum rtx_code code, rtx cmp_op0,
4160 : : rtx cmp_op1, rtx if_true, rtx if_false)
4161 : : {
4162 : 9283 : machine_mode mode = GET_MODE (dest);
4163 : 9283 : bool is_min;
4164 : 9283 : rtx tmp;
4165 : :
4166 : 9283 : if (code == LT)
4167 : : ;
4168 : 3263 : else if (code == LE && !HONOR_NANS (mode))
4169 : : {
4170 : : /* We can swap LE to GE and then invert to LT. */
4171 : : std::swap (cmp_op0, cmp_op1);
4172 : : std::swap (if_true, if_false);
4173 : : }
4174 : 3222 : else if (code == UNGE)
4175 : : std::swap (if_true, if_false);
4176 : : else
4177 : : return false;
4178 : :
4179 : 8205 : if (rtx_equal_p (cmp_op0, if_true) && rtx_equal_p (cmp_op1, if_false))
4180 : : is_min = true;
4181 : 4396 : else if (rtx_equal_p (cmp_op1, if_true) && rtx_equal_p (cmp_op0, if_false))
4182 : : is_min = false;
4183 : : else
4184 : 998 : return false;
4185 : :
4186 : 7207 : if (immediate_operand (if_false, mode))
4187 : 8 : if_false = force_reg (mode, if_false);
4188 : 7207 : if (immediate_operand (if_true, mode))
4189 : 0 : if_true = force_reg (mode, if_true);
4190 : :
4191 : : /* We want to check HONOR_NANS and HONOR_SIGNED_ZEROS here,
4192 : : but MODE may be a vector mode and thus not appropriate. */
4193 : 7207 : if (!flag_finite_math_only || flag_signed_zeros)
4194 : : {
4195 : 7207 : int u = is_min ? UNSPEC_IEEE_MIN : UNSPEC_IEEE_MAX;
4196 : 7207 : rtvec v;
4197 : :
4198 : 7207 : if_true = force_reg (mode, if_true);
4199 : 7207 : v = gen_rtvec (2, if_true, if_false);
4200 : 7207 : tmp = gen_rtx_UNSPEC (mode, v, u);
4201 : 7207 : }
4202 : : else
4203 : : {
4204 : 0 : code = is_min ? SMIN : SMAX;
4205 : 0 : if (MEM_P (if_true) && MEM_P (if_false))
4206 : 0 : if_true = force_reg (mode, if_true);
4207 : 0 : tmp = gen_rtx_fmt_ee (code, mode, if_true, if_false);
4208 : : }
4209 : :
4210 : 7207 : emit_insn (gen_rtx_SET (dest, tmp));
4211 : 7207 : return true;
4212 : : }
4213 : :
4214 : : /* Return true if MODE is valid for vector compare to mask register,
4215 : : Same result for conditionl vector move with mask register. */
4216 : : static bool
4217 : 14425 : ix86_valid_mask_cmp_mode (machine_mode mode)
4218 : : {
4219 : : /* XOP has its own vector conditional movement. */
4220 : 14425 : if (TARGET_XOP && !TARGET_AVX512F)
4221 : : return false;
4222 : :
4223 : : /* HFmode only supports vcmpsh whose dest is mask register. */
4224 : 14419 : if (TARGET_AVX512FP16 && mode == HFmode)
4225 : : return true;
4226 : :
4227 : : /* AVX512F is needed for mask operation. */
4228 : 14328 : if (!(TARGET_AVX512F && VECTOR_MODE_P (mode)))
4229 : : return false;
4230 : :
4231 : : /* AVX512BW is needed for vector QI/HImode,
4232 : : AVX512VL is needed for 128/256-bit vector. */
4233 : 182 : machine_mode inner_mode = GET_MODE_INNER (mode);
4234 : 182 : int vector_size = GET_MODE_SIZE (mode);
4235 : 182 : if ((inner_mode == QImode || inner_mode == HImode) && !TARGET_AVX512BW)
4236 : : return false;
4237 : :
4238 : 162 : return vector_size == 64 || TARGET_AVX512VL;
4239 : : }
4240 : :
4241 : : /* Return true if integer mask comparison should be used. */
4242 : : static bool
4243 : 50592 : ix86_use_mask_cmp_p (machine_mode mode, machine_mode cmp_mode,
4244 : : rtx op_true, rtx op_false)
4245 : : {
4246 : 50592 : int vector_size = GET_MODE_SIZE (mode);
4247 : :
4248 : 50592 : if (cmp_mode == HFmode)
4249 : : return true;
4250 : 50501 : else if (vector_size < 16)
4251 : : return false;
4252 : 44102 : else if (vector_size == 64)
4253 : : return true;
4254 : 88088 : else if (GET_MODE_INNER (cmp_mode) == HFmode)
4255 : : return true;
4256 : 88088 : else if (GET_MODE_INNER (cmp_mode) == BFmode)
4257 : : return true;
4258 : :
4259 : : /* When op_true is NULL, op_false must be NULL, or vice versa. */
4260 : 44044 : gcc_assert (!op_true == !op_false);
4261 : :
4262 : : /* When op_true/op_false is NULL or cmp_mode is not valid mask cmp mode,
4263 : : vector dest is required. */
4264 : 44044 : if (!op_true || !ix86_valid_mask_cmp_mode (cmp_mode))
4265 : : return false;
4266 : :
4267 : : /* Exclude those that could be optimized in ix86_expand_sse_movcc. */
4268 : 48 : if (op_false == CONST0_RTX (mode)
4269 : 48 : || op_true == CONST0_RTX (mode)
4270 : 48 : || (INTEGRAL_MODE_P (mode)
4271 : 40 : && (op_true == CONSTM1_RTX (mode)
4272 : 40 : || op_false == CONSTM1_RTX (mode))))
4273 : 0 : return false;
4274 : :
4275 : : return true;
4276 : : }
4277 : :
4278 : : /* Expand an SSE comparison. Return the register with the result. */
4279 : :
4280 : : static rtx
4281 : 34470 : ix86_expand_sse_cmp (rtx dest, enum rtx_code code, rtx cmp_op0, rtx cmp_op1,
4282 : : rtx op_true, rtx op_false)
4283 : : {
4284 : 34470 : machine_mode mode = GET_MODE (dest);
4285 : 34470 : machine_mode cmp_ops_mode = GET_MODE (cmp_op0);
4286 : :
4287 : : /* In general case result of comparison can differ from operands' type. */
4288 : 34470 : machine_mode cmp_mode;
4289 : :
4290 : : /* In AVX512F the result of comparison is an integer mask. */
4291 : 34470 : bool maskcmp = false;
4292 : 34470 : rtx x;
4293 : :
4294 : 34470 : if (ix86_use_mask_cmp_p (mode, cmp_ops_mode, op_true, op_false))
4295 : : {
4296 : 144 : unsigned int nbits = GET_MODE_NUNITS (cmp_ops_mode);
4297 : 144 : maskcmp = true;
4298 : 144 : cmp_mode = nbits > 8 ? int_mode_for_size (nbits, 0).require () : E_QImode;
4299 : : }
4300 : : else
4301 : : cmp_mode = cmp_ops_mode;
4302 : :
4303 : 34470 : cmp_op0 = force_reg (cmp_ops_mode, cmp_op0);
4304 : :
4305 : 68940 : bool (*op1_predicate)(rtx, machine_mode)
4306 : 34470 : = VECTOR_MODE_P (cmp_ops_mode) ? vector_operand : nonimmediate_operand;
4307 : :
4308 : 34470 : if (!op1_predicate (cmp_op1, cmp_ops_mode))
4309 : 0 : cmp_op1 = force_reg (cmp_ops_mode, cmp_op1);
4310 : :
4311 : 34470 : if (optimize
4312 : 503 : || (maskcmp && cmp_mode != mode)
4313 : 503 : || (op_true && reg_overlap_mentioned_p (dest, op_true))
4314 : 34973 : || (op_false && reg_overlap_mentioned_p (dest, op_false)))
4315 : 67790 : dest = gen_reg_rtx (maskcmp ? cmp_mode : mode);
4316 : :
4317 : 34470 : if (maskcmp)
4318 : : {
4319 : 144 : bool ok = ix86_expand_mask_vec_cmp (dest, code, cmp_op0, cmp_op1);
4320 : 144 : gcc_assert (ok);
4321 : : return dest;
4322 : : }
4323 : :
4324 : 34326 : x = gen_rtx_fmt_ee (code, cmp_mode, cmp_op0, cmp_op1);
4325 : :
4326 : 34326 : if (cmp_mode != mode)
4327 : : {
4328 : 7122 : x = force_reg (cmp_ops_mode, x);
4329 : 7122 : convert_move (dest, x, false);
4330 : : }
4331 : : else
4332 : 27204 : emit_insn (gen_rtx_SET (dest, x));
4333 : :
4334 : : return dest;
4335 : : }
4336 : :
4337 : : /* Emit x86 binary operand CODE in mode MODE for SSE vector
4338 : : instructions that can be performed using GP registers. */
4339 : :
4340 : : static void
4341 : 6899 : ix86_emit_vec_binop (enum rtx_code code, machine_mode mode,
4342 : : rtx dst, rtx src1, rtx src2)
4343 : : {
4344 : 6899 : rtx tmp;
4345 : :
4346 : 6899 : tmp = gen_rtx_SET (dst, gen_rtx_fmt_ee (code, mode, src1, src2));
4347 : :
4348 : 6899 : if (GET_MODE_SIZE (mode) <= GET_MODE_SIZE (SImode)
4349 : 6899 : && GET_MODE_CLASS (mode) == MODE_VECTOR_INT)
4350 : : {
4351 : 52 : rtx clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
4352 : 52 : tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, tmp, clob));
4353 : : }
4354 : :
4355 : 6899 : emit_insn (tmp);
4356 : 6899 : }
4357 : :
4358 : : /* Expand DEST = CMP ? OP_TRUE : OP_FALSE into a sequence of logical
4359 : : operations. This is used for both scalar and vector conditional moves. */
4360 : :
4361 : : void
4362 : 9988 : ix86_expand_sse_movcc (rtx dest, rtx cmp, rtx op_true, rtx op_false)
4363 : : {
4364 : 9988 : machine_mode mode = GET_MODE (dest);
4365 : 9988 : machine_mode cmpmode = GET_MODE (cmp);
4366 : 9988 : rtx x;
4367 : :
4368 : : /* Simplify trivial VEC_COND_EXPR to avoid ICE in pr97506. */
4369 : 9988 : if (rtx_equal_p (op_true, op_false))
4370 : : {
4371 : 0 : emit_move_insn (dest, op_true);
4372 : 0 : return;
4373 : : }
4374 : :
4375 : : /* If we have an integer mask and FP value then we need
4376 : : to cast mask to FP mode. */
4377 : 9988 : if (mode != cmpmode && VECTOR_MODE_P (cmpmode))
4378 : : {
4379 : 1451 : cmp = force_reg (cmpmode, cmp);
4380 : 1451 : cmp = gen_rtx_SUBREG (mode, cmp, 0);
4381 : : }
4382 : :
4383 : : /* In AVX512F the result of comparison is an integer mask. */
4384 : 9988 : if (mode != cmpmode
4385 : 1595 : && GET_MODE_CLASS (cmpmode) == MODE_INT)
4386 : : {
4387 : 144 : gcc_assert (ix86_valid_mask_cmp_mode (mode));
4388 : : /* Using scalar/vector move with mask register. */
4389 : 144 : cmp = force_reg (cmpmode, cmp);
4390 : : /* Optimize for mask zero. */
4391 : 288 : op_true = (op_true != CONST0_RTX (mode)
4392 : 144 : ? force_reg (mode, op_true) : op_true);
4393 : 288 : op_false = (op_false != CONST0_RTX (mode)
4394 : 144 : ? force_reg (mode, op_false) : op_false);
4395 : 144 : if (op_true == CONST0_RTX (mode))
4396 : : {
4397 : 0 : if (cmpmode == E_DImode && !TARGET_64BIT)
4398 : : {
4399 : 0 : x = gen_reg_rtx (cmpmode);
4400 : 0 : emit_insn (gen_knotdi (x, cmp));
4401 : : }
4402 : : else
4403 : 0 : x = expand_simple_unop (cmpmode, NOT, cmp, NULL, 1);
4404 : : cmp = x;
4405 : : /* Reverse op_true op_false. */
4406 : : std::swap (op_true, op_false);
4407 : : }
4408 : :
4409 : 144 : if (mode == HFmode)
4410 : 91 : emit_insn (gen_movhf_mask (dest, op_true, op_false, cmp));
4411 : : else
4412 : 53 : emit_insn (gen_rtx_SET (dest,
4413 : : gen_rtx_VEC_MERGE (mode,
4414 : : op_true, op_false, cmp)));
4415 : 144 : return;
4416 : : }
4417 : :
4418 : 9844 : if (vector_all_ones_operand (op_true, mode)
4419 : 9844 : && op_false == CONST0_RTX (mode))
4420 : : {
4421 : 2 : emit_move_insn (dest, cmp);
4422 : 2 : return;
4423 : : }
4424 : 9842 : else if (op_false == CONST0_RTX (mode))
4425 : : {
4426 : 892 : x = expand_simple_binop (mode, AND, cmp, op_true,
4427 : : dest, 1, OPTAB_DIRECT);
4428 : 892 : if (x != dest)
4429 : 0 : emit_move_insn (dest, x);
4430 : 892 : return;
4431 : : }
4432 : 8950 : else if (op_true == CONST0_RTX (mode))
4433 : : {
4434 : 94 : op_false = force_reg (mode, op_false);
4435 : 94 : x = gen_rtx_NOT (mode, cmp);
4436 : 94 : ix86_emit_vec_binop (AND, mode, dest, x, op_false);
4437 : 94 : return;
4438 : : }
4439 : 8856 : else if (vector_all_ones_operand (op_true, mode))
4440 : : {
4441 : 0 : x = expand_simple_binop (mode, IOR, cmp, op_false,
4442 : : dest, 1, OPTAB_DIRECT);
4443 : 0 : if (x != dest)
4444 : 0 : emit_move_insn (dest, x);
4445 : 0 : return;
4446 : : }
4447 : :
4448 : 8856 : if (TARGET_XOP)
4449 : : {
4450 : 65 : op_true = force_reg (mode, op_true);
4451 : :
4452 : 65 : if (GET_MODE_SIZE (mode) < 16
4453 : 65 : || !nonimmediate_operand (op_false, mode))
4454 : 49 : op_false = force_reg (mode, op_false);
4455 : :
4456 : 65 : emit_insn (gen_rtx_SET (dest,
4457 : : gen_rtx_IF_THEN_ELSE (mode, cmp,
4458 : : op_true, op_false)));
4459 : 65 : return;
4460 : : }
4461 : :
4462 : 8791 : rtx (*gen) (rtx, rtx, rtx, rtx) = NULL;
4463 : 8791 : machine_mode blend_mode = mode;
4464 : :
4465 : 8791 : if (GET_MODE_SIZE (mode) < 16
4466 : 8791 : || !vector_operand (op_true, mode))
4467 : 2336 : op_true = force_reg (mode, op_true);
4468 : :
4469 : 8791 : op_false = force_reg (mode, op_false);
4470 : :
4471 : 8791 : switch (mode)
4472 : : {
4473 : 29 : case E_V2SFmode:
4474 : 29 : if (TARGET_SSE_MOVCC_USE_BLENDV && TARGET_SSE4_1)
4475 : : gen = gen_mmx_blendvps;
4476 : : break;
4477 : 288 : case E_V4SFmode:
4478 : 288 : if (TARGET_SSE_MOVCC_USE_BLENDV && TARGET_SSE4_1)
4479 : : gen = gen_sse4_1_blendvps;
4480 : : break;
4481 : 132 : case E_V2DFmode:
4482 : 132 : if (TARGET_SSE_MOVCC_USE_BLENDV && TARGET_SSE4_1)
4483 : : gen = gen_sse4_1_blendvpd;
4484 : : break;
4485 : 983 : case E_SFmode:
4486 : 983 : if (TARGET_SSE_MOVCC_USE_BLENDV && TARGET_SSE4_1)
4487 : : gen = gen_sse4_1_blendvss;
4488 : : break;
4489 : 859 : case E_DFmode:
4490 : 859 : if (TARGET_SSE_MOVCC_USE_BLENDV && TARGET_SSE4_1)
4491 : : gen = gen_sse4_1_blendvsd;
4492 : : break;
4493 : 348 : case E_V8QImode:
4494 : 348 : case E_V4HImode:
4495 : 348 : case E_V4HFmode:
4496 : 348 : case E_V4BFmode:
4497 : 348 : case E_V2SImode:
4498 : 348 : if (TARGET_SSE_MOVCC_USE_BLENDV && TARGET_SSE4_1)
4499 : : {
4500 : : gen = gen_mmx_pblendvb_v8qi;
4501 : : blend_mode = V8QImode;
4502 : : }
4503 : : break;
4504 : 81 : case E_V4QImode:
4505 : 81 : case E_V2HImode:
4506 : 81 : case E_V2HFmode:
4507 : 81 : case E_V2BFmode:
4508 : 81 : if (TARGET_SSE_MOVCC_USE_BLENDV && TARGET_SSE4_1)
4509 : : {
4510 : : gen = gen_mmx_pblendvb_v4qi;
4511 : : blend_mode = V4QImode;
4512 : : }
4513 : : break;
4514 : 36 : case E_V2QImode:
4515 : 36 : if (TARGET_SSE_MOVCC_USE_BLENDV && TARGET_SSE4_1)
4516 : : gen = gen_mmx_pblendvb_v2qi;
4517 : : break;
4518 : 5388 : case E_V16QImode:
4519 : 5388 : case E_V8HImode:
4520 : 5388 : case E_V8HFmode:
4521 : 5388 : case E_V8BFmode:
4522 : 5388 : case E_V4SImode:
4523 : 5388 : case E_V2DImode:
4524 : 5388 : case E_V1TImode:
4525 : 5388 : if (TARGET_SSE_MOVCC_USE_BLENDV && TARGET_SSE4_1)
4526 : : {
4527 : : gen = gen_sse4_1_pblendvb;
4528 : : blend_mode = V16QImode;
4529 : : }
4530 : : break;
4531 : 75 : case E_V8SFmode:
4532 : 75 : if (TARGET_AVX && TARGET_SSE_MOVCC_USE_BLENDV)
4533 : : gen = gen_avx_blendvps256;
4534 : : break;
4535 : 192 : case E_V4DFmode:
4536 : 192 : if (TARGET_AVX && TARGET_SSE_MOVCC_USE_BLENDV)
4537 : : gen = gen_avx_blendvpd256;
4538 : : break;
4539 : 380 : case E_V32QImode:
4540 : 380 : case E_V16HImode:
4541 : 380 : case E_V16HFmode:
4542 : 380 : case E_V16BFmode:
4543 : 380 : case E_V8SImode:
4544 : 380 : case E_V4DImode:
4545 : 380 : if (TARGET_AVX2 && TARGET_SSE_MOVCC_USE_BLENDV)
4546 : : {
4547 : : gen = gen_avx2_pblendvb;
4548 : : blend_mode = V32QImode;
4549 : : }
4550 : : break;
4551 : :
4552 : 0 : case E_V64QImode:
4553 : 0 : gen = gen_avx512bw_blendmv64qi;
4554 : 0 : break;
4555 : 0 : case E_V32HImode:
4556 : 0 : gen = gen_avx512bw_blendmv32hi;
4557 : 0 : break;
4558 : 0 : case E_V32HFmode:
4559 : 0 : gen = gen_avx512bw_blendmv32hf;
4560 : 0 : break;
4561 : 0 : case E_V32BFmode:
4562 : 0 : gen = gen_avx512bw_blendmv32bf;
4563 : 0 : break;
4564 : 0 : case E_V16SImode:
4565 : 0 : gen = gen_avx512f_blendmv16si;
4566 : 0 : break;
4567 : 0 : case E_V8DImode:
4568 : 0 : gen = gen_avx512f_blendmv8di;
4569 : 0 : break;
4570 : 0 : case E_V8DFmode:
4571 : 0 : gen = gen_avx512f_blendmv8df;
4572 : 0 : break;
4573 : : case E_V16SFmode:
4574 : : gen = gen_avx512f_blendmv16sf;
4575 : : break;
4576 : :
4577 : : default:
4578 : : break;
4579 : : }
4580 : :
4581 : 0 : if (gen != NULL)
4582 : : {
4583 : 2051 : if (blend_mode == mode)
4584 : : x = dest;
4585 : : else
4586 : : {
4587 : 1004 : x = gen_reg_rtx (blend_mode);
4588 : 1004 : op_false = gen_lowpart (blend_mode, op_false);
4589 : 1004 : op_true = gen_lowpart (blend_mode, op_true);
4590 : 1004 : cmp = gen_lowpart (blend_mode, cmp);
4591 : : }
4592 : :
4593 : 2051 : emit_insn (gen (x, op_false, op_true, cmp));
4594 : :
4595 : 2051 : if (x != dest)
4596 : 1004 : emit_move_insn (dest, gen_lowpart (mode, x));
4597 : : }
4598 : : else
4599 : : {
4600 : 6740 : rtx t2, t3;
4601 : :
4602 : 6740 : t2 = expand_simple_binop (mode, AND, op_true, cmp,
4603 : : NULL, 1, OPTAB_DIRECT);
4604 : :
4605 : 6740 : t3 = gen_reg_rtx (mode);
4606 : 6740 : x = gen_rtx_NOT (mode, cmp);
4607 : 6740 : ix86_emit_vec_binop (AND, mode, t3, x, op_false);
4608 : :
4609 : 6740 : x = expand_simple_binop (mode, IOR, t3, t2,
4610 : : dest, 1, OPTAB_DIRECT);
4611 : 6740 : if (x != dest)
4612 : 0 : emit_move_insn (dest, x);
4613 : : }
4614 : : }
4615 : :
4616 : : /* Swap, force into registers, or otherwise massage the two operands
4617 : : to an sse comparison with a mask result. Thus we differ a bit from
4618 : : ix86_prepare_fp_compare_args which expects to produce a flags result.
4619 : :
4620 : : The DEST operand exists to help determine whether to commute commutative
4621 : : operators. The POP0/POP1 operands are updated in place. The new
4622 : : comparison code is returned, or UNKNOWN if not implementable. */
4623 : :
4624 : : static enum rtx_code
4625 : 16405 : ix86_prepare_sse_fp_compare_args (rtx dest, enum rtx_code code,
4626 : : rtx *pop0, rtx *pop1)
4627 : : {
4628 : 16405 : switch (code)
4629 : : {
4630 : 67 : case LTGT:
4631 : 67 : case UNEQ:
4632 : : /* AVX supports all the needed comparisons. */
4633 : 67 : if (TARGET_AVX)
4634 : : break;
4635 : : /* We have no LTGT as an operator. We could implement it with
4636 : : NE & ORDERED, but this requires an extra temporary. It's
4637 : : not clear that it's worth it. */
4638 : : return UNKNOWN;
4639 : :
4640 : : case LT:
4641 : : case LE:
4642 : : case UNGT:
4643 : : case UNGE:
4644 : : /* These are supported directly. */
4645 : : break;
4646 : :
4647 : 5127 : case EQ:
4648 : 5127 : case NE:
4649 : 5127 : case UNORDERED:
4650 : 5127 : case ORDERED:
4651 : : /* AVX has 3 operand comparisons, no need to swap anything. */
4652 : 5127 : if (TARGET_AVX)
4653 : : break;
4654 : : /* For commutative operators, try to canonicalize the destination
4655 : : operand to be first in the comparison - this helps reload to
4656 : : avoid extra moves. */
4657 : 348 : if (!dest || !rtx_equal_p (dest, *pop1))
4658 : : break;
4659 : : /* FALLTHRU */
4660 : :
4661 : 10178 : case GE:
4662 : 10178 : case GT:
4663 : 10178 : case UNLE:
4664 : 10178 : case UNLT:
4665 : : /* These are not supported directly before AVX, and furthermore
4666 : : ix86_expand_sse_fp_minmax only optimizes LT/UNGE. Swap the
4667 : : comparison operands to transform into something that is
4668 : : supported. */
4669 : 10178 : std::swap (*pop0, *pop1);
4670 : 10178 : code = swap_condition (code);
4671 : 10178 : break;
4672 : :
4673 : 0 : default:
4674 : 0 : gcc_unreachable ();
4675 : : }
4676 : :
4677 : : return code;
4678 : : }
4679 : :
4680 : : /* Expand a floating-point conditional move. Return true if successful. */
4681 : :
4682 : : bool
4683 : 92320 : ix86_expand_fp_movcc (rtx operands[])
4684 : : {
4685 : 92320 : machine_mode mode = GET_MODE (operands[0]);
4686 : 92320 : enum rtx_code code = GET_CODE (operands[1]);
4687 : 92320 : rtx tmp, compare_op;
4688 : 92320 : rtx op0 = XEXP (operands[1], 0);
4689 : 92320 : rtx op1 = XEXP (operands[1], 1);
4690 : :
4691 : 92320 : if (GET_MODE (op0) == BFmode
4692 : 92320 : && !ix86_fp_comparison_operator (operands[1], VOIDmode))
4693 : : return false;
4694 : :
4695 : 92320 : if (SSE_FLOAT_MODE_SSEMATH_OR_HFBF_P (mode))
4696 : : {
4697 : 61853 : machine_mode cmode;
4698 : :
4699 : : /* Since we've no cmove for sse registers, don't force bad register
4700 : : allocation just to gain access to it. Deny movcc when the
4701 : : comparison mode doesn't match the move mode. */
4702 : 61853 : cmode = GET_MODE (op0);
4703 : 61853 : if (cmode == VOIDmode)
4704 : 0 : cmode = GET_MODE (op1);
4705 : 61853 : if (cmode != mode)
4706 : : return false;
4707 : :
4708 : 9303 : code = ix86_prepare_sse_fp_compare_args (operands[0], code, &op0, &op1);
4709 : 9303 : if (code == UNKNOWN)
4710 : : return false;
4711 : :
4712 : 9283 : if (ix86_expand_sse_fp_minmax (operands[0], code, op0, op1,
4713 : : operands[2], operands[3]))
4714 : : return true;
4715 : :
4716 : 2076 : tmp = ix86_expand_sse_cmp (operands[0], code, op0, op1,
4717 : : operands[2], operands[3]);
4718 : 2076 : ix86_expand_sse_movcc (operands[0], tmp, operands[2], operands[3]);
4719 : 2076 : return true;
4720 : : }
4721 : :
4722 : 30467 : if (GET_MODE (op0) == TImode
4723 : 30467 : || (GET_MODE (op0) == DImode
4724 : 72 : && !TARGET_64BIT))
4725 : : return false;
4726 : :
4727 : : /* The floating point conditional move instructions don't directly
4728 : : support conditions resulting from a signed integer comparison. */
4729 : :
4730 : 30395 : compare_op = ix86_expand_compare (code, op0, op1);
4731 : 30395 : if (!fcmov_comparison_operator (compare_op, VOIDmode))
4732 : : {
4733 : 142 : tmp = gen_reg_rtx (QImode);
4734 : 142 : ix86_expand_setcc (tmp, code, op0, op1);
4735 : :
4736 : 142 : compare_op = ix86_expand_compare (NE, tmp, const0_rtx);
4737 : : }
4738 : :
4739 : 30395 : operands[2] = force_reg (mode, operands[2]);
4740 : 30395 : operands[3] = force_reg (mode, operands[3]);
4741 : 30395 : emit_insn (gen_rtx_SET (operands[0],
4742 : : gen_rtx_IF_THEN_ELSE (mode, compare_op,
4743 : : operands[2], operands[3])));
4744 : :
4745 : 30395 : return true;
4746 : : }
4747 : :
4748 : : /* Helper for ix86_cmp_code_to_pcmp_immediate for int modes. */
4749 : :
4750 : : static int
4751 : 4857 : ix86_int_cmp_code_to_pcmp_immediate (enum rtx_code code)
4752 : : {
4753 : 4857 : switch (code)
4754 : : {
4755 : : case EQ:
4756 : : return 0;
4757 : 360 : case LT:
4758 : 360 : case LTU:
4759 : 360 : return 1;
4760 : 209 : case LE:
4761 : 209 : case LEU:
4762 : 209 : return 2;
4763 : 3081 : case NE:
4764 : 3081 : return 4;
4765 : 307 : case GE:
4766 : 307 : case GEU:
4767 : 307 : return 5;
4768 : 497 : case GT:
4769 : 497 : case GTU:
4770 : 497 : return 6;
4771 : 0 : default:
4772 : 0 : gcc_unreachable ();
4773 : : }
4774 : : }
4775 : :
4776 : : /* Helper for ix86_cmp_code_to_pcmp_immediate for fp modes. */
4777 : :
4778 : : static int
4779 : 1833 : ix86_fp_cmp_code_to_pcmp_immediate (enum rtx_code code)
4780 : : {
4781 : 1833 : switch (code)
4782 : : {
4783 : : case EQ:
4784 : : return 0x00;
4785 : 407 : case NE:
4786 : 407 : return 0x04;
4787 : 514 : case GT:
4788 : 514 : return 0x0e;
4789 : 88 : case LE:
4790 : 88 : return 0x02;
4791 : 53 : case GE:
4792 : 53 : return 0x0d;
4793 : 619 : case LT:
4794 : 619 : return 0x01;
4795 : 2 : case UNLE:
4796 : 2 : return 0x0a;
4797 : 2 : case UNLT:
4798 : 2 : return 0x09;
4799 : 11 : case UNGE:
4800 : 11 : return 0x05;
4801 : 44 : case UNGT:
4802 : 44 : return 0x06;
4803 : 2 : case UNEQ:
4804 : 2 : return 0x18;
4805 : 0 : case LTGT:
4806 : 0 : return 0x0c;
4807 : 2 : case ORDERED:
4808 : 2 : return 0x07;
4809 : 2 : case UNORDERED:
4810 : 2 : return 0x03;
4811 : 0 : default:
4812 : 0 : gcc_unreachable ();
4813 : : }
4814 : : }
4815 : :
4816 : : /* Return immediate value to be used in UNSPEC_PCMP
4817 : : for comparison CODE in MODE. */
4818 : :
4819 : : static int
4820 : 6690 : ix86_cmp_code_to_pcmp_immediate (enum rtx_code code, machine_mode mode)
4821 : : {
4822 : 6690 : if (FLOAT_MODE_P (mode))
4823 : 1833 : return ix86_fp_cmp_code_to_pcmp_immediate (code);
4824 : 4857 : return ix86_int_cmp_code_to_pcmp_immediate (code);
4825 : : }
4826 : :
4827 : : /* Expand AVX-512 vector comparison. */
4828 : :
4829 : : bool
4830 : 6690 : ix86_expand_mask_vec_cmp (rtx dest, enum rtx_code code, rtx cmp_op0, rtx cmp_op1)
4831 : : {
4832 : 6690 : machine_mode mask_mode = GET_MODE (dest);
4833 : 6690 : machine_mode cmp_mode = GET_MODE (cmp_op0);
4834 : 6690 : rtx imm = GEN_INT (ix86_cmp_code_to_pcmp_immediate (code, cmp_mode));
4835 : 6690 : int unspec_code;
4836 : 6690 : rtx unspec;
4837 : :
4838 : 6690 : switch (code)
4839 : : {
4840 : : case LEU:
4841 : : case GTU:
4842 : : case GEU:
4843 : : case LTU:
4844 : : unspec_code = UNSPEC_UNSIGNED_PCMP;
4845 : : break;
4846 : :
4847 : 6279 : default:
4848 : 6279 : unspec_code = UNSPEC_PCMP;
4849 : : }
4850 : :
4851 : 6690 : unspec = gen_rtx_UNSPEC (mask_mode, gen_rtvec (3, cmp_op0, cmp_op1, imm),
4852 : : unspec_code);
4853 : 6690 : emit_insn (gen_rtx_SET (dest, unspec));
4854 : :
4855 : 6690 : return true;
4856 : : }
4857 : :
4858 : : /* Expand fp vector comparison. */
4859 : :
4860 : : bool
4861 : 7102 : ix86_expand_fp_vec_cmp (rtx operands[])
4862 : : {
4863 : 7102 : enum rtx_code code = GET_CODE (operands[1]);
4864 : 7102 : rtx cmp;
4865 : :
4866 : 7102 : code = ix86_prepare_sse_fp_compare_args (operands[0], code,
4867 : : &operands[2], &operands[3]);
4868 : 7102 : if (code == UNKNOWN)
4869 : : {
4870 : 20 : rtx temp;
4871 : 20 : switch (GET_CODE (operands[1]))
4872 : : {
4873 : 2 : case LTGT:
4874 : 2 : temp = ix86_expand_sse_cmp (operands[0], ORDERED, operands[2],
4875 : : operands[3], NULL, NULL);
4876 : 2 : cmp = ix86_expand_sse_cmp (operands[0], NE, operands[2],
4877 : : operands[3], NULL, NULL);
4878 : 2 : code = AND;
4879 : 2 : break;
4880 : 18 : case UNEQ:
4881 : 18 : temp = ix86_expand_sse_cmp (operands[0], UNORDERED, operands[2],
4882 : : operands[3], NULL, NULL);
4883 : 18 : cmp = ix86_expand_sse_cmp (operands[0], EQ, operands[2],
4884 : : operands[3], NULL, NULL);
4885 : 18 : code = IOR;
4886 : 18 : break;
4887 : 0 : default:
4888 : 0 : gcc_unreachable ();
4889 : : }
4890 : 20 : cmp = expand_simple_binop (GET_MODE (cmp), code, temp, cmp, cmp, 1,
4891 : : OPTAB_DIRECT);
4892 : : }
4893 : : else
4894 : 7082 : cmp = ix86_expand_sse_cmp (operands[0], code, operands[2], operands[3],
4895 : : NULL, NULL);
4896 : :
4897 : 7102 : if (operands[0] != cmp)
4898 : 7019 : emit_move_insn (operands[0], cmp);
4899 : :
4900 : 7102 : return true;
4901 : : }
4902 : :
4903 : : static rtx
4904 : 16320 : ix86_expand_int_sse_cmp (rtx dest, enum rtx_code code, rtx cop0, rtx cop1,
4905 : : rtx op_true, rtx op_false, bool *negate)
4906 : : {
4907 : 16320 : machine_mode data_mode = GET_MODE (dest);
4908 : 16320 : machine_mode mode = GET_MODE (cop0);
4909 : 16320 : rtx x;
4910 : :
4911 : 16320 : *negate = false;
4912 : :
4913 : : /* XOP supports all of the comparisons on all 128-bit vector int types. */
4914 : 16320 : if (TARGET_XOP
4915 : 201 : && GET_MODE_CLASS (mode) == MODE_VECTOR_INT
4916 : 16521 : && GET_MODE_SIZE (mode) <= 16)
4917 : : ;
4918 : : /* AVX512F supports all of the comparsions
4919 : : on all 128/256/512-bit vector int types. */
4920 : 16122 : else if (ix86_use_mask_cmp_p (data_mode, mode, op_true, op_false))
4921 : : ;
4922 : : else
4923 : : {
4924 : : /* Canonicalize the comparison to EQ, GT, GTU. */
4925 : 16069 : switch (code)
4926 : : {
4927 : : case EQ:
4928 : : case GT:
4929 : : case GTU:
4930 : : break;
4931 : :
4932 : 826 : case LE:
4933 : 826 : case LEU:
4934 : : /* x <= cst can be handled as x < cst + 1 unless there is
4935 : : wrap around in cst + 1. */
4936 : 826 : if (CONST_VECTOR_P (cop1)
4937 : 1386 : && GET_MODE_INNER (mode) != TImode)
4938 : : {
4939 : 560 : unsigned int n_elts = GET_MODE_NUNITS (mode), i;
4940 : 560 : machine_mode eltmode = GET_MODE_INNER (mode);
4941 : 3505 : for (i = 0; i < n_elts; ++i)
4942 : : {
4943 : 2946 : rtx elt = CONST_VECTOR_ELT (cop1, i);
4944 : 2946 : if (!CONST_INT_P (elt))
4945 : : break;
4946 : 2946 : if (code == LE)
4947 : : {
4948 : : /* For LE punt if some element is signed maximum. */
4949 : 1866 : if ((INTVAL (elt) & (GET_MODE_MASK (eltmode) >> 1))
4950 : : == (GET_MODE_MASK (eltmode) >> 1))
4951 : : break;
4952 : : }
4953 : : /* For LEU punt if some element is unsigned maximum. */
4954 : 1080 : else if (elt == constm1_rtx)
4955 : : break;
4956 : : }
4957 : 560 : if (i == n_elts)
4958 : : {
4959 : 559 : rtvec v = rtvec_alloc (n_elts);
4960 : 4062 : for (i = 0; i < n_elts; ++i)
4961 : 2944 : RTVEC_ELT (v, i)
4962 : 2944 : = gen_int_mode (INTVAL (CONST_VECTOR_ELT (cop1, i)) + 1,
4963 : : eltmode);
4964 : 559 : cop1 = gen_rtx_CONST_VECTOR (mode, v);
4965 : 559 : std::swap (cop0, cop1);
4966 : 559 : code = code == LE ? GT : GTU;
4967 : : break;
4968 : : }
4969 : : }
4970 : : /* FALLTHRU */
4971 : 3407 : case NE:
4972 : 3407 : code = reverse_condition (code);
4973 : 3407 : *negate = true;
4974 : 3407 : break;
4975 : :
4976 : 403 : case GE:
4977 : 403 : case GEU:
4978 : : /* x >= cst can be handled as x > cst - 1 unless there is
4979 : : wrap around in cst - 1. */
4980 : 403 : if (CONST_VECTOR_P (cop1)
4981 : 572 : && GET_MODE_INNER (mode) != TImode)
4982 : : {
4983 : 169 : unsigned int n_elts = GET_MODE_NUNITS (mode), i;
4984 : 169 : machine_mode eltmode = GET_MODE_INNER (mode);
4985 : 1135 : for (i = 0; i < n_elts; ++i)
4986 : : {
4987 : 1014 : rtx elt = CONST_VECTOR_ELT (cop1, i);
4988 : 1014 : if (!CONST_INT_P (elt))
4989 : : break;
4990 : 1014 : if (code == GE)
4991 : : {
4992 : : /* For GE punt if some element is signed minimum. */
4993 : 966 : if (INTVAL (elt) < 0
4994 : 136 : && ((INTVAL (elt) & (GET_MODE_MASK (eltmode) >> 1))
4995 : : == 0))
4996 : : break;
4997 : : }
4998 : : /* For GEU punt if some element is zero. */
4999 : 48 : else if (elt == const0_rtx)
5000 : : break;
5001 : : }
5002 : 169 : if (i == n_elts)
5003 : : {
5004 : 121 : rtvec v = rtvec_alloc (n_elts);
5005 : 1208 : for (i = 0; i < n_elts; ++i)
5006 : 966 : RTVEC_ELT (v, i)
5007 : 966 : = gen_int_mode (INTVAL (CONST_VECTOR_ELT (cop1, i)) - 1,
5008 : : eltmode);
5009 : 121 : cop1 = gen_rtx_CONST_VECTOR (mode, v);
5010 : 121 : code = code == GE ? GT : GTU;
5011 : : break;
5012 : : }
5013 : : }
5014 : 282 : code = reverse_condition (code);
5015 : 282 : *negate = true;
5016 : : /* FALLTHRU */
5017 : :
5018 : 1564 : case LT:
5019 : 1564 : case LTU:
5020 : 1564 : std::swap (cop0, cop1);
5021 : 1564 : code = swap_condition (code);
5022 : 1564 : break;
5023 : :
5024 : 0 : default:
5025 : 0 : gcc_unreachable ();
5026 : : }
5027 : :
5028 : : /* Only SSE4.1/SSE4.2 supports V2DImode. */
5029 : 16069 : if (mode == V2DImode)
5030 : : {
5031 : 723 : switch (code)
5032 : : {
5033 : 519 : case EQ:
5034 : : /* SSE4.1 supports EQ. */
5035 : 519 : if (!TARGET_SSE4_1)
5036 : 16320 : return NULL;
5037 : : break;
5038 : :
5039 : 204 : case GT:
5040 : 204 : case GTU:
5041 : : /* SSE4.2 supports GT/GTU. */
5042 : 204 : if (!TARGET_SSE4_2)
5043 : : return NULL;
5044 : : break;
5045 : :
5046 : 0 : default:
5047 : 0 : gcc_unreachable ();
5048 : : }
5049 : : }
5050 : :
5051 : 16069 : if (CONST_VECTOR_P (cop0))
5052 : 1166 : cop0 = force_reg (mode, cop0);
5053 : 14903 : else if (CONST_VECTOR_P (cop1))
5054 : 7046 : cop1 = force_reg (mode, cop1);
5055 : :
5056 : 16069 : rtx optrue = op_true ? op_true : CONSTM1_RTX (data_mode);
5057 : 16069 : rtx opfalse = op_false ? op_false : CONST0_RTX (data_mode);
5058 : 16069 : if (*negate)
5059 : 3689 : std::swap (optrue, opfalse);
5060 : :
5061 : : /* Transform x > y ? 0 : -1 (i.e. x <= y ? -1 : 0 or x <= y) when
5062 : : not using integer masks into min (x, y) == x ? -1 : 0 (i.e.
5063 : : min (x, y) == x). While we add one instruction (the minimum),
5064 : : we remove the need for two instructions in the negation, as the
5065 : : result is done this way.
5066 : : When using masks, do it for SI/DImode element types, as it is shorter
5067 : : than the two subtractions. */
5068 : 16069 : if ((code != EQ
5069 : 6926 : && GET_MODE_SIZE (mode) != 64
5070 : 6926 : && vector_all_ones_operand (opfalse, data_mode)
5071 : 549 : && optrue == CONST0_RTX (data_mode))
5072 : 22446 : || (code == GTU
5073 : 1878 : && GET_MODE_SIZE (GET_MODE_INNER (mode)) >= 4
5074 : : /* Don't do it if not using integer masks and we'd end up with
5075 : : the right values in the registers though. */
5076 : 623 : && (GET_MODE_SIZE (mode) == 64
5077 : 623 : || !vector_all_ones_operand (optrue, data_mode)
5078 : 518 : || opfalse != CONST0_RTX (data_mode))))
5079 : : {
5080 : 654 : rtx (*gen) (rtx, rtx, rtx) = NULL;
5081 : :
5082 : 654 : switch (mode)
5083 : : {
5084 : 0 : case E_V16SImode:
5085 : 0 : gen = (code == GTU) ? gen_uminv16si3 : gen_sminv16si3;
5086 : : break;
5087 : 0 : case E_V8DImode:
5088 : 0 : gen = (code == GTU) ? gen_uminv8di3 : gen_sminv8di3;
5089 : 0 : cop0 = force_reg (mode, cop0);
5090 : 0 : cop1 = force_reg (mode, cop1);
5091 : 0 : break;
5092 : 24 : case E_V32QImode:
5093 : 24 : if (TARGET_AVX2)
5094 : 24 : gen = (code == GTU) ? gen_uminv32qi3 : gen_sminv32qi3;
5095 : : break;
5096 : 24 : case E_V16HImode:
5097 : 24 : if (TARGET_AVX2)
5098 : 24 : gen = (code == GTU) ? gen_uminv16hi3 : gen_sminv16hi3;
5099 : : break;
5100 : 26 : case E_V8SImode:
5101 : 26 : if (TARGET_AVX2)
5102 : 26 : gen = (code == GTU) ? gen_uminv8si3 : gen_sminv8si3;
5103 : : break;
5104 : 20 : case E_V4DImode:
5105 : 20 : if (TARGET_AVX512VL)
5106 : : {
5107 : 0 : gen = (code == GTU) ? gen_uminv4di3 : gen_sminv4di3;
5108 : 0 : cop0 = force_reg (mode, cop0);
5109 : 0 : cop1 = force_reg (mode, cop1);
5110 : : }
5111 : : break;
5112 : 59 : case E_V16QImode:
5113 : 59 : if (code == GTU && TARGET_SSE2)
5114 : : gen = gen_uminv16qi3;
5115 : 20 : else if (code == GT && TARGET_SSE4_1)
5116 : : gen = gen_sminv16qi3;
5117 : : break;
5118 : 40 : case E_V8QImode:
5119 : 40 : if (code == GTU && TARGET_SSE2)
5120 : : gen = gen_uminv8qi3;
5121 : 38 : else if (code == GT && TARGET_SSE4_1)
5122 : : gen = gen_sminv8qi3;
5123 : : break;
5124 : 13 : case E_V4QImode:
5125 : 13 : if (code == GTU && TARGET_SSE2)
5126 : : gen = gen_uminv4qi3;
5127 : 2 : else if (code == GT && TARGET_SSE4_1)
5128 : : gen = gen_sminv4qi3;
5129 : : break;
5130 : 8 : case E_V2QImode:
5131 : 8 : if (code == GTU && TARGET_SSE2)
5132 : : gen = gen_uminv2qi3;
5133 : 6 : else if (code == GT && TARGET_SSE4_1)
5134 : : gen = gen_sminv2qi3;
5135 : : break;
5136 : 65 : case E_V8HImode:
5137 : 65 : if (code == GTU && TARGET_SSE4_1)
5138 : : gen = gen_uminv8hi3;
5139 : 55 : else if (code == GT && TARGET_SSE2)
5140 : : gen = gen_sminv8hi3;
5141 : : break;
5142 : 4 : case E_V4HImode:
5143 : 4 : if (code == GTU && TARGET_SSE4_1)
5144 : : gen = gen_uminv4hi3;
5145 : 4 : else if (code == GT && TARGET_SSE2)
5146 : : gen = gen_sminv4hi3;
5147 : : break;
5148 : 13 : case E_V2HImode:
5149 : 13 : if (code == GTU && TARGET_SSE4_1)
5150 : : gen = gen_uminv2hi3;
5151 : 13 : else if (code == GT && TARGET_SSE2)
5152 : : gen = gen_sminv2hi3;
5153 : : break;
5154 : 233 : case E_V4SImode:
5155 : 233 : if (TARGET_SSE4_1)
5156 : 55 : gen = (code == GTU) ? gen_uminv4si3 : gen_sminv4si3;
5157 : : break;
5158 : 101 : case E_V2SImode:
5159 : 101 : if (TARGET_SSE4_1)
5160 : 0 : gen = (code == GTU) ? gen_uminv2si3 : gen_sminv2si3;
5161 : : break;
5162 : 24 : case E_V2DImode:
5163 : 24 : if (TARGET_AVX512VL)
5164 : : {
5165 : 0 : gen = (code == GTU) ? gen_uminv2di3 : gen_sminv2di3;
5166 : 0 : cop0 = force_reg (mode, cop0);
5167 : 0 : cop1 = force_reg (mode, cop1);
5168 : : }
5169 : : break;
5170 : : default:
5171 : : break;
5172 : : }
5173 : :
5174 : 0 : if (gen)
5175 : : {
5176 : 276 : rtx tem = gen_reg_rtx (mode);
5177 : 276 : if (!vector_operand (cop0, mode))
5178 : 0 : cop0 = force_reg (mode, cop0);
5179 : 276 : if (!vector_operand (cop1, mode))
5180 : 0 : cop1 = force_reg (mode, cop1);
5181 : 276 : *negate = !*negate;
5182 : 276 : emit_insn (gen (tem, cop0, cop1));
5183 : 276 : cop1 = tem;
5184 : 276 : code = EQ;
5185 : : }
5186 : : }
5187 : :
5188 : : /* Unsigned parallel compare is not supported by the hardware.
5189 : : Play some tricks to turn this into a signed comparison
5190 : : against 0. */
5191 : 16069 : if (code == GTU)
5192 : : {
5193 : 1069 : cop0 = force_reg (mode, cop0);
5194 : :
5195 : 1069 : switch (mode)
5196 : : {
5197 : 722 : case E_V16SImode:
5198 : 722 : case E_V8DImode:
5199 : 722 : case E_V8SImode:
5200 : 722 : case E_V4DImode:
5201 : 722 : case E_V4SImode:
5202 : 722 : case E_V2SImode:
5203 : 722 : case E_V2DImode:
5204 : 722 : {
5205 : 722 : rtx t1, t2, mask;
5206 : :
5207 : : /* Subtract (-(INT MAX) - 1) from both operands to make
5208 : : them signed. */
5209 : 722 : mask = ix86_build_signbit_mask (mode, true, false);
5210 : 722 : t1 = gen_reg_rtx (mode);
5211 : 722 : emit_insn (gen_sub3_insn (t1, cop0, mask));
5212 : :
5213 : 722 : t2 = gen_reg_rtx (mode);
5214 : 722 : emit_insn (gen_sub3_insn (t2, cop1, mask));
5215 : :
5216 : 722 : cop0 = t1;
5217 : 722 : cop1 = t2;
5218 : 722 : code = GT;
5219 : : }
5220 : 722 : break;
5221 : :
5222 : 347 : case E_V64QImode:
5223 : 347 : case E_V32HImode:
5224 : 347 : case E_V32QImode:
5225 : 347 : case E_V16HImode:
5226 : 347 : case E_V16QImode:
5227 : 347 : case E_V8QImode:
5228 : 347 : case E_V4QImode:
5229 : 347 : case E_V2QImode:
5230 : 347 : case E_V8HImode:
5231 : 347 : case E_V4HImode:
5232 : 347 : case E_V2HImode:
5233 : : /* Perform a parallel unsigned saturating subtraction. */
5234 : 347 : x = gen_reg_rtx (mode);
5235 : 347 : emit_insn (gen_rtx_SET
5236 : : (x, gen_rtx_US_MINUS (mode, cop0, cop1)));
5237 : 347 : cop0 = x;
5238 : 347 : cop1 = CONST0_RTX (mode);
5239 : 347 : code = EQ;
5240 : 347 : *negate = !*negate;
5241 : 347 : break;
5242 : :
5243 : 0 : default:
5244 : 0 : gcc_unreachable ();
5245 : : }
5246 : : }
5247 : : }
5248 : :
5249 : 16320 : if (*negate)
5250 : 3698 : std::swap (op_true, op_false);
5251 : :
5252 : 16320 : if (CONST_VECTOR_P (cop1))
5253 : 416 : cop1 = force_reg (mode, cop1);
5254 : :
5255 : : /* Allow the comparison to be done in one mode, but the movcc to
5256 : : happen in another mode. */
5257 : 16320 : if (data_mode == mode)
5258 : 16278 : x = ix86_expand_sse_cmp (dest, code, cop0, cop1, op_true, op_false);
5259 : : else
5260 : : {
5261 : 126 : gcc_assert (GET_MODE_SIZE (data_mode) == GET_MODE_SIZE (mode));
5262 : 42 : x = ix86_expand_sse_cmp (gen_reg_rtx (mode), code, cop0, cop1,
5263 : : op_true, op_false);
5264 : 42 : if (GET_MODE (x) == mode)
5265 : 24 : x = gen_lowpart (data_mode, x);
5266 : : }
5267 : :
5268 : : return x;
5269 : : }
5270 : :
5271 : : /* Expand integer vector comparison. */
5272 : :
5273 : : bool
5274 : 9397 : ix86_expand_int_vec_cmp (rtx operands[])
5275 : : {
5276 : 9397 : rtx_code code = GET_CODE (operands[1]);
5277 : 9397 : bool negate = false;
5278 : 9397 : rtx cmp = ix86_expand_int_sse_cmp (operands[0], code, operands[2],
5279 : : operands[3], NULL, NULL, &negate);
5280 : :
5281 : 9397 : if (!cmp)
5282 : : return false;
5283 : :
5284 : 9397 : if (negate)
5285 : 3602 : cmp = ix86_expand_int_sse_cmp (operands[0], EQ, cmp,
5286 : 3602 : CONST0_RTX (GET_MODE (cmp)),
5287 : : NULL, NULL, &negate);
5288 : :
5289 : 9397 : gcc_assert (!negate);
5290 : :
5291 : 9397 : if (operands[0] != cmp)
5292 : 9104 : emit_move_insn (operands[0], cmp);
5293 : :
5294 : : return true;
5295 : : }
5296 : :
5297 : : /* Expand a floating-point vector conditional move; a vcond operation
5298 : : rather than a movcc operation. */
5299 : :
5300 : : bool
5301 : 0 : ix86_expand_fp_vcond (rtx operands[])
5302 : : {
5303 : 0 : enum rtx_code code = GET_CODE (operands[3]);
5304 : 0 : rtx cmp;
5305 : :
5306 : 0 : code = ix86_prepare_sse_fp_compare_args (operands[0], code,
5307 : : &operands[4], &operands[5]);
5308 : 0 : if (code == UNKNOWN)
5309 : : {
5310 : 0 : rtx temp;
5311 : 0 : switch (GET_CODE (operands[3]))
5312 : : {
5313 : 0 : case LTGT:
5314 : 0 : temp = ix86_expand_sse_cmp (operands[0], ORDERED, operands[4],
5315 : : operands[5], operands[0], operands[0]);
5316 : 0 : cmp = ix86_expand_sse_cmp (operands[0], NE, operands[4],
5317 : : operands[5], operands[1], operands[2]);
5318 : 0 : code = AND;
5319 : 0 : break;
5320 : 0 : case UNEQ:
5321 : 0 : temp = ix86_expand_sse_cmp (operands[0], UNORDERED, operands[4],
5322 : : operands[5], operands[0], operands[0]);
5323 : 0 : cmp = ix86_expand_sse_cmp (operands[0], EQ, operands[4],
5324 : : operands[5], operands[1], operands[2]);
5325 : 0 : code = IOR;
5326 : 0 : break;
5327 : 0 : default:
5328 : 0 : gcc_unreachable ();
5329 : : }
5330 : 0 : cmp = expand_simple_binop (GET_MODE (cmp), code, temp, cmp, cmp, 1,
5331 : : OPTAB_DIRECT);
5332 : 0 : ix86_expand_sse_movcc (operands[0], cmp, operands[1], operands[2]);
5333 : 0 : return true;
5334 : : }
5335 : :
5336 : 0 : if (ix86_expand_sse_fp_minmax (operands[0], code, operands[4],
5337 : : operands[5], operands[1], operands[2]))
5338 : : return true;
5339 : :
5340 : 0 : cmp = ix86_expand_sse_cmp (operands[0], code, operands[4], operands[5],
5341 : : operands[1], operands[2]);
5342 : 0 : ix86_expand_sse_movcc (operands[0], cmp, operands[1], operands[2]);
5343 : 0 : return true;
5344 : : }
5345 : :
5346 : : /* Expand a signed/unsigned integral vector conditional move. */
5347 : :
5348 : : bool
5349 : 3321 : ix86_expand_int_vcond (rtx operands[])
5350 : : {
5351 : 3321 : machine_mode data_mode = GET_MODE (operands[0]);
5352 : 3321 : machine_mode mode = GET_MODE (operands[4]);
5353 : 3321 : enum rtx_code code = GET_CODE (operands[3]);
5354 : 3321 : bool negate = false;
5355 : 3321 : rtx x, cop0, cop1;
5356 : :
5357 : 3321 : cop0 = operands[4];
5358 : 3321 : cop1 = operands[5];
5359 : :
5360 : : /* Try to optimize x < 0 ? -1 : 0 into (signed) x >> 31
5361 : : and x < 0 ? 1 : 0 into (unsigned) x >> 31. */
5362 : 3321 : if ((code == LT || code == GE)
5363 : 0 : && data_mode == mode
5364 : 0 : && cop1 == CONST0_RTX (mode)
5365 : 0 : && operands[1 + (code == LT)] == CONST0_RTX (data_mode)
5366 : 0 : && GET_MODE_UNIT_SIZE (data_mode) > 1
5367 : 0 : && GET_MODE_UNIT_SIZE (data_mode) <= 8
5368 : 3321 : && (GET_MODE_SIZE (data_mode) == 16
5369 : 0 : || (TARGET_AVX2 && GET_MODE_SIZE (data_mode) == 32)))
5370 : : {
5371 : 0 : rtx negop = operands[2 - (code == LT)];
5372 : 0 : int shift = GET_MODE_UNIT_BITSIZE (data_mode) - 1;
5373 : 0 : if (negop == CONST1_RTX (data_mode))
5374 : : {
5375 : 0 : rtx res = expand_simple_binop (mode, LSHIFTRT, cop0, GEN_INT (shift),
5376 : : operands[0], 1, OPTAB_DIRECT);
5377 : 0 : if (res != operands[0])
5378 : 0 : emit_move_insn (operands[0], res);
5379 : 0 : return true;
5380 : : }
5381 : 0 : else if (GET_MODE_INNER (data_mode) != DImode
5382 : 0 : && vector_all_ones_operand (negop, data_mode))
5383 : : {
5384 : 0 : rtx res = expand_simple_binop (mode, ASHIFTRT, cop0, GEN_INT (shift),
5385 : : operands[0], 0, OPTAB_DIRECT);
5386 : 0 : if (res != operands[0])
5387 : 0 : emit_move_insn (operands[0], res);
5388 : 0 : return true;
5389 : : }
5390 : : }
5391 : :
5392 : 3321 : if (!nonimmediate_operand (cop1, mode))
5393 : 125 : cop1 = force_reg (mode, cop1);
5394 : 3321 : if (!general_operand (operands[1], data_mode))
5395 : 0 : operands[1] = force_reg (data_mode, operands[1]);
5396 : 3321 : if (!general_operand (operands[2], data_mode))
5397 : 0 : operands[2] = force_reg (data_mode, operands[2]);
5398 : :
5399 : 3321 : x = ix86_expand_int_sse_cmp (operands[0], code, cop0, cop1,
5400 : : operands[1], operands[2], &negate);
5401 : :
5402 : 3321 : if (!x)
5403 : : return false;
5404 : :
5405 : 3321 : ix86_expand_sse_movcc (operands[0], x, operands[1+negate],
5406 : 3321 : operands[2-negate]);
5407 : 3321 : return true;
5408 : : }
5409 : :
5410 : : static bool
5411 : 125011 : ix86_expand_vec_perm_vpermt2 (rtx target, rtx mask, rtx op0, rtx op1,
5412 : : struct expand_vec_perm_d *d)
5413 : : {
5414 : : /* ix86_expand_vec_perm_vpermt2 is called from both const and non-const
5415 : : expander, so args are either in d, or in op0, op1 etc. */
5416 : 125011 : machine_mode mode = GET_MODE (d ? d->op0 : op0);
5417 : 125011 : machine_mode maskmode = mode;
5418 : 125011 : rtx (*gen) (rtx, rtx, rtx, rtx) = NULL;
5419 : :
5420 : 125011 : switch (mode)
5421 : : {
5422 : 23292 : case E_V16QImode:
5423 : 23292 : if (TARGET_AVX512VL && TARGET_AVX512VBMI)
5424 : : gen = gen_avx512vl_vpermt2varv16qi3;
5425 : : break;
5426 : 738 : case E_V32QImode:
5427 : 738 : if (TARGET_AVX512VL && TARGET_AVX512VBMI)
5428 : : gen = gen_avx512vl_vpermt2varv32qi3;
5429 : : break;
5430 : 227 : case E_V64QImode:
5431 : 227 : if (TARGET_AVX512VBMI)
5432 : : gen = gen_avx512bw_vpermt2varv64qi3;
5433 : : break;
5434 : 12878 : case E_V8HImode:
5435 : 12878 : if (TARGET_AVX512VL && TARGET_AVX512BW)
5436 : : gen = gen_avx512vl_vpermt2varv8hi3;
5437 : : break;
5438 : 751 : case E_V16HImode:
5439 : 751 : if (TARGET_AVX512VL && TARGET_AVX512BW)
5440 : : gen = gen_avx512vl_vpermt2varv16hi3;
5441 : : break;
5442 : 391 : case E_V32HImode:
5443 : 391 : if (TARGET_AVX512BW)
5444 : : gen = gen_avx512bw_vpermt2varv32hi3;
5445 : : break;
5446 : 36328 : case E_V4SImode:
5447 : 36328 : if (TARGET_AVX512VL)
5448 : : gen = gen_avx512vl_vpermt2varv4si3;
5449 : : break;
5450 : 1167 : case E_V8SImode:
5451 : 1167 : if (TARGET_AVX512VL)
5452 : : gen = gen_avx512vl_vpermt2varv8si3;
5453 : : break;
5454 : 126 : case E_V16SImode:
5455 : 126 : if (TARGET_AVX512F)
5456 : : gen = gen_avx512f_vpermt2varv16si3;
5457 : : break;
5458 : 10342 : case E_V4SFmode:
5459 : 10342 : if (TARGET_AVX512VL)
5460 : : {
5461 : : gen = gen_avx512vl_vpermt2varv4sf3;
5462 : : maskmode = V4SImode;
5463 : : }
5464 : : break;
5465 : 7623 : case E_V8SFmode:
5466 : 7623 : if (TARGET_AVX512VL)
5467 : : {
5468 : : gen = gen_avx512vl_vpermt2varv8sf3;
5469 : : maskmode = V8SImode;
5470 : : }
5471 : : break;
5472 : 207 : case E_V16SFmode:
5473 : 207 : if (TARGET_AVX512F)
5474 : : {
5475 : : gen = gen_avx512f_vpermt2varv16sf3;
5476 : : maskmode = V16SImode;
5477 : : }
5478 : : break;
5479 : 0 : case E_V2DImode:
5480 : 0 : if (TARGET_AVX512VL)
5481 : : gen = gen_avx512vl_vpermt2varv2di3;
5482 : : break;
5483 : 290 : case E_V4DImode:
5484 : 290 : if (TARGET_AVX512VL)
5485 : : gen = gen_avx512vl_vpermt2varv4di3;
5486 : : break;
5487 : 10 : case E_V8DImode:
5488 : 10 : if (TARGET_AVX512F)
5489 : : gen = gen_avx512f_vpermt2varv8di3;
5490 : : break;
5491 : 0 : case E_V2DFmode:
5492 : 0 : if (TARGET_AVX512VL)
5493 : : {
5494 : : gen = gen_avx512vl_vpermt2varv2df3;
5495 : : maskmode = V2DImode;
5496 : : }
5497 : : break;
5498 : 1877 : case E_V4DFmode:
5499 : 1877 : if (TARGET_AVX512VL)
5500 : : {
5501 : : gen = gen_avx512vl_vpermt2varv4df3;
5502 : : maskmode = V4DImode;
5503 : : }
5504 : : break;
5505 : 202 : case E_V8DFmode:
5506 : 202 : if (TARGET_AVX512F)
5507 : : {
5508 : : gen = gen_avx512f_vpermt2varv8df3;
5509 : : maskmode = V8DImode;
5510 : : }
5511 : : break;
5512 : : default:
5513 : : break;
5514 : : }
5515 : :
5516 : : if (gen == NULL)
5517 : : return false;
5518 : :
5519 : 932 : if (d && d->testing_p)
5520 : : return true;
5521 : :
5522 : : /* ix86_expand_vec_perm_vpermt2 is called from both const and non-const
5523 : : expander, so args are either in d, or in op0, op1 etc. */
5524 : 921 : if (d)
5525 : : {
5526 : 921 : rtx vec[64];
5527 : 921 : target = d->target;
5528 : 921 : op0 = d->op0;
5529 : 921 : op1 = d->op1;
5530 : 16877 : for (int i = 0; i < d->nelt; ++i)
5531 : 15956 : vec[i] = GEN_INT (d->perm[i]);
5532 : 921 : mask = gen_rtx_CONST_VECTOR (maskmode, gen_rtvec_v (d->nelt, vec));
5533 : : }
5534 : :
5535 : 929 : emit_insn (gen (target, force_reg (maskmode, mask), op0, op1));
5536 : 929 : return true;
5537 : : }
5538 : :
5539 : : /* Expand a variable vector permutation. */
5540 : :
5541 : : void
5542 : 10 : ix86_expand_vec_perm (rtx operands[])
5543 : : {
5544 : 10 : rtx target = operands[0];
5545 : 10 : rtx op0 = operands[1];
5546 : 10 : rtx op1 = operands[2];
5547 : 10 : rtx mask = operands[3];
5548 : 10 : rtx t1, t2, t3, t4, t5, t6, t7, t8, vt, vt2, vec[32];
5549 : 10 : machine_mode mode = GET_MODE (op0);
5550 : 10 : machine_mode maskmode = GET_MODE (mask);
5551 : 10 : int w, e, i;
5552 : 10 : bool one_operand_shuffle = rtx_equal_p (op0, op1);
5553 : :
5554 : : /* Number of elements in the vector. */
5555 : 10 : w = GET_MODE_NUNITS (mode);
5556 : 10 : e = GET_MODE_UNIT_SIZE (mode);
5557 : 10 : gcc_assert (w <= 64);
5558 : :
5559 : : /* For HF mode vector, convert it to HI using subreg. */
5560 : 20 : if (GET_MODE_INNER (mode) == HFmode)
5561 : : {
5562 : 6 : machine_mode orig_mode = mode;
5563 : 6 : mode = mode_for_vector (HImode, w).require ();
5564 : 6 : target = lowpart_subreg (mode, target, orig_mode);
5565 : 6 : op0 = lowpart_subreg (mode, op0, orig_mode);
5566 : 6 : op1 = lowpart_subreg (mode, op1, orig_mode);
5567 : : }
5568 : :
5569 : 10 : if (TARGET_AVX512F && one_operand_shuffle)
5570 : : {
5571 : 5 : rtx (*gen) (rtx, rtx, rtx) = NULL;
5572 : 5 : switch (mode)
5573 : : {
5574 : : case E_V16SImode:
5575 : : gen =gen_avx512f_permvarv16si;
5576 : : break;
5577 : 0 : case E_V16SFmode:
5578 : 0 : gen = gen_avx512f_permvarv16sf;
5579 : 0 : break;
5580 : 0 : case E_V8DImode:
5581 : 0 : gen = gen_avx512f_permvarv8di;
5582 : 0 : break;
5583 : 0 : case E_V8DFmode:
5584 : 0 : gen = gen_avx512f_permvarv8df;
5585 : 0 : break;
5586 : : default:
5587 : : break;
5588 : : }
5589 : 0 : if (gen != NULL)
5590 : : {
5591 : 0 : emit_insn (gen (target, op0, mask));
5592 : 8 : return;
5593 : : }
5594 : : }
5595 : :
5596 : 10 : if (ix86_expand_vec_perm_vpermt2 (target, mask, op0, op1, NULL))
5597 : : return;
5598 : :
5599 : 2 : if (TARGET_AVX2)
5600 : : {
5601 : 1 : if (mode == V4DImode || mode == V4DFmode || mode == V16HImode)
5602 : : {
5603 : : /* Unfortunately, the VPERMQ and VPERMPD instructions only support
5604 : : an constant shuffle operand. With a tiny bit of effort we can
5605 : : use VPERMD instead. A re-interpretation stall for V4DFmode is
5606 : : unfortunate but there's no avoiding it.
5607 : : Similarly for V16HImode we don't have instructions for variable
5608 : : shuffling, while for V32QImode we can use after preparing suitable
5609 : : masks vpshufb; vpshufb; vpermq; vpor. */
5610 : :
5611 : : if (mode == V16HImode)
5612 : : {
5613 : : maskmode = mode = V32QImode;
5614 : : w = 32;
5615 : : e = 1;
5616 : : }
5617 : : else
5618 : : {
5619 : : maskmode = mode = V8SImode;
5620 : : w = 8;
5621 : : e = 4;
5622 : : }
5623 : 0 : t1 = gen_reg_rtx (maskmode);
5624 : :
5625 : : /* Replicate the low bits of the V4DImode mask into V8SImode:
5626 : : mask = { A B C D }
5627 : : t1 = { A A B B C C D D }. */
5628 : 0 : for (i = 0; i < w / 2; ++i)
5629 : 0 : vec[i*2 + 1] = vec[i*2] = GEN_INT (i * 2);
5630 : 0 : vt = gen_rtx_CONST_VECTOR (maskmode, gen_rtvec_v (w, vec));
5631 : 0 : vt = force_reg (maskmode, vt);
5632 : 0 : mask = gen_lowpart (maskmode, mask);
5633 : 0 : if (maskmode == V8SImode)
5634 : 0 : emit_insn (gen_avx2_permvarv8si (t1, mask, vt));
5635 : : else
5636 : 0 : emit_insn (gen_avx2_pshufbv32qi3 (t1, mask, vt));
5637 : :
5638 : : /* Multiply the shuffle indicies by two. */
5639 : 0 : t1 = expand_simple_binop (maskmode, PLUS, t1, t1, t1, 1,
5640 : : OPTAB_DIRECT);
5641 : :
5642 : : /* Add one to the odd shuffle indicies:
5643 : : t1 = { A*2, A*2+1, B*2, B*2+1, ... }. */
5644 : 0 : for (i = 0; i < w / 2; ++i)
5645 : : {
5646 : 0 : vec[i * 2] = const0_rtx;
5647 : 0 : vec[i * 2 + 1] = const1_rtx;
5648 : : }
5649 : 0 : vt = gen_rtx_CONST_VECTOR (maskmode, gen_rtvec_v (w, vec));
5650 : 0 : vt = validize_mem (force_const_mem (maskmode, vt));
5651 : 0 : t1 = expand_simple_binop (maskmode, PLUS, t1, vt, t1, 1,
5652 : : OPTAB_DIRECT);
5653 : :
5654 : : /* Continue as if V8SImode (resp. V32QImode) was used initially. */
5655 : 0 : operands[3] = mask = t1;
5656 : 0 : target = gen_reg_rtx (mode);
5657 : 0 : op0 = gen_lowpart (mode, op0);
5658 : 0 : op1 = gen_lowpart (mode, op1);
5659 : : }
5660 : :
5661 : 1 : switch (mode)
5662 : : {
5663 : 1 : case E_V8SImode:
5664 : : /* The VPERMD and VPERMPS instructions already properly ignore
5665 : : the high bits of the shuffle elements. No need for us to
5666 : : perform an AND ourselves. */
5667 : 1 : if (one_operand_shuffle)
5668 : : {
5669 : 0 : emit_insn (gen_avx2_permvarv8si (target, op0, mask));
5670 : 0 : if (target != operands[0])
5671 : 0 : emit_move_insn (operands[0],
5672 : 0 : gen_lowpart (GET_MODE (operands[0]), target));
5673 : : }
5674 : : else
5675 : : {
5676 : 1 : t1 = gen_reg_rtx (V8SImode);
5677 : 1 : t2 = gen_reg_rtx (V8SImode);
5678 : 1 : emit_insn (gen_avx2_permvarv8si (t1, op0, mask));
5679 : 1 : emit_insn (gen_avx2_permvarv8si (t2, op1, mask));
5680 : 1 : goto merge_two;
5681 : : }
5682 : 0 : return;
5683 : :
5684 : 0 : case E_V8SFmode:
5685 : 0 : mask = gen_lowpart (V8SImode, mask);
5686 : 0 : if (one_operand_shuffle)
5687 : 0 : emit_insn (gen_avx2_permvarv8sf (target, op0, mask));
5688 : : else
5689 : : {
5690 : 0 : t1 = gen_reg_rtx (V8SFmode);
5691 : 0 : t2 = gen_reg_rtx (V8SFmode);
5692 : 0 : emit_insn (gen_avx2_permvarv8sf (t1, op0, mask));
5693 : 0 : emit_insn (gen_avx2_permvarv8sf (t2, op1, mask));
5694 : 0 : goto merge_two;
5695 : : }
5696 : 0 : return;
5697 : :
5698 : 0 : case E_V4SImode:
5699 : : /* By combining the two 128-bit input vectors into one 256-bit
5700 : : input vector, we can use VPERMD and VPERMPS for the full
5701 : : two-operand shuffle. */
5702 : 0 : t1 = gen_reg_rtx (V8SImode);
5703 : 0 : t2 = gen_reg_rtx (V8SImode);
5704 : 0 : emit_insn (gen_avx_vec_concatv8si (t1, op0, op1));
5705 : 0 : emit_insn (gen_avx_vec_concatv8si (t2, mask, mask));
5706 : 0 : emit_insn (gen_avx2_permvarv8si (t1, t1, t2));
5707 : 0 : emit_insn (gen_avx_vextractf128v8si (target, t1, const0_rtx));
5708 : 0 : return;
5709 : :
5710 : 0 : case E_V4SFmode:
5711 : 0 : t1 = gen_reg_rtx (V8SFmode);
5712 : 0 : t2 = gen_reg_rtx (V8SImode);
5713 : 0 : mask = gen_lowpart (V4SImode, mask);
5714 : 0 : emit_insn (gen_avx_vec_concatv8sf (t1, op0, op1));
5715 : 0 : emit_insn (gen_avx_vec_concatv8si (t2, mask, mask));
5716 : 0 : emit_insn (gen_avx2_permvarv8sf (t1, t1, t2));
5717 : 0 : emit_insn (gen_avx_vextractf128v8sf (target, t1, const0_rtx));
5718 : 0 : return;
5719 : :
5720 : 0 : case E_V32QImode:
5721 : 0 : t1 = gen_reg_rtx (V32QImode);
5722 : 0 : t2 = gen_reg_rtx (V32QImode);
5723 : 0 : t3 = gen_reg_rtx (V32QImode);
5724 : 0 : vt2 = GEN_INT (-128);
5725 : 0 : vt = gen_const_vec_duplicate (V32QImode, vt2);
5726 : 0 : vt = force_reg (V32QImode, vt);
5727 : 0 : for (i = 0; i < 32; i++)
5728 : 0 : vec[i] = i < 16 ? vt2 : const0_rtx;
5729 : 0 : vt2 = gen_rtx_CONST_VECTOR (V32QImode, gen_rtvec_v (32, vec));
5730 : 0 : vt2 = force_reg (V32QImode, vt2);
5731 : : /* From mask create two adjusted masks, which contain the same
5732 : : bits as mask in the low 7 bits of each vector element.
5733 : : The first mask will have the most significant bit clear
5734 : : if it requests element from the same 128-bit lane
5735 : : and MSB set if it requests element from the other 128-bit lane.
5736 : : The second mask will have the opposite values of the MSB,
5737 : : and additionally will have its 128-bit lanes swapped.
5738 : : E.g. { 07 12 1e 09 ... | 17 19 05 1f ... } mask vector will have
5739 : : t1 { 07 92 9e 09 ... | 17 19 85 1f ... } and
5740 : : t3 { 97 99 05 9f ... | 87 12 1e 89 ... } where each ...
5741 : : stands for other 12 bytes. */
5742 : : /* The bit whether element is from the same lane or the other
5743 : : lane is bit 4, so shift it up by 3 to the MSB position. */
5744 : 0 : t5 = gen_reg_rtx (V4DImode);
5745 : 0 : emit_insn (gen_ashlv4di3 (t5, gen_lowpart (V4DImode, mask),
5746 : : GEN_INT (3)));
5747 : : /* Clear MSB bits from the mask just in case it had them set. */
5748 : 0 : emit_insn (gen_avx2_andnotv32qi3 (t2, vt, mask));
5749 : : /* After this t1 will have MSB set for elements from other lane. */
5750 : 0 : emit_insn (gen_xorv32qi3 (t1, gen_lowpart (V32QImode, t5), vt2));
5751 : : /* Clear bits other than MSB. */
5752 : 0 : emit_insn (gen_andv32qi3 (t1, t1, vt));
5753 : : /* Or in the lower bits from mask into t3. */
5754 : 0 : emit_insn (gen_iorv32qi3 (t3, t1, t2));
5755 : : /* And invert MSB bits in t1, so MSB is set for elements from the same
5756 : : lane. */
5757 : 0 : emit_insn (gen_xorv32qi3 (t1, t1, vt));
5758 : : /* Swap 128-bit lanes in t3. */
5759 : 0 : t6 = gen_reg_rtx (V4DImode);
5760 : 0 : emit_insn (gen_avx2_permv4di_1 (t6, gen_lowpart (V4DImode, t3),
5761 : : const2_rtx, GEN_INT (3),
5762 : : const0_rtx, const1_rtx));
5763 : : /* And or in the lower bits from mask into t1. */
5764 : 0 : emit_insn (gen_iorv32qi3 (t1, t1, t2));
5765 : 0 : if (one_operand_shuffle)
5766 : : {
5767 : : /* Each of these shuffles will put 0s in places where
5768 : : element from the other 128-bit lane is needed, otherwise
5769 : : will shuffle in the requested value. */
5770 : 0 : emit_insn (gen_avx2_pshufbv32qi3 (t3, op0,
5771 : 0 : gen_lowpart (V32QImode, t6)));
5772 : 0 : emit_insn (gen_avx2_pshufbv32qi3 (t1, op0, t1));
5773 : : /* For t3 the 128-bit lanes are swapped again. */
5774 : 0 : t7 = gen_reg_rtx (V4DImode);
5775 : 0 : emit_insn (gen_avx2_permv4di_1 (t7, gen_lowpart (V4DImode, t3),
5776 : : const2_rtx, GEN_INT (3),
5777 : : const0_rtx, const1_rtx));
5778 : : /* And oring both together leads to the result. */
5779 : 0 : emit_insn (gen_iorv32qi3 (target, t1,
5780 : 0 : gen_lowpart (V32QImode, t7)));
5781 : 0 : if (target != operands[0])
5782 : 0 : emit_move_insn (operands[0],
5783 : 0 : gen_lowpart (GET_MODE (operands[0]), target));
5784 : 0 : return;
5785 : : }
5786 : :
5787 : 0 : t4 = gen_reg_rtx (V32QImode);
5788 : : /* Similarly to the above one_operand_shuffle code,
5789 : : just for repeated twice for each operand. merge_two:
5790 : : code will merge the two results together. */
5791 : 0 : emit_insn (gen_avx2_pshufbv32qi3 (t4, op0,
5792 : 0 : gen_lowpart (V32QImode, t6)));
5793 : 0 : emit_insn (gen_avx2_pshufbv32qi3 (t3, op1,
5794 : 0 : gen_lowpart (V32QImode, t6)));
5795 : 0 : emit_insn (gen_avx2_pshufbv32qi3 (t2, op0, t1));
5796 : 0 : emit_insn (gen_avx2_pshufbv32qi3 (t1, op1, t1));
5797 : 0 : t7 = gen_reg_rtx (V4DImode);
5798 : 0 : emit_insn (gen_avx2_permv4di_1 (t7, gen_lowpart (V4DImode, t4),
5799 : : const2_rtx, GEN_INT (3),
5800 : : const0_rtx, const1_rtx));
5801 : 0 : t8 = gen_reg_rtx (V4DImode);
5802 : 0 : emit_insn (gen_avx2_permv4di_1 (t8, gen_lowpart (V4DImode, t3),
5803 : : const2_rtx, GEN_INT (3),
5804 : : const0_rtx, const1_rtx));
5805 : 0 : emit_insn (gen_iorv32qi3 (t4, t2, gen_lowpart (V32QImode, t7)));
5806 : 0 : emit_insn (gen_iorv32qi3 (t3, t1, gen_lowpart (V32QImode, t8)));
5807 : 0 : t1 = t4;
5808 : 0 : t2 = t3;
5809 : 0 : goto merge_two;
5810 : :
5811 : 0 : default:
5812 : 0 : gcc_assert (GET_MODE_SIZE (mode) <= 16);
5813 : : break;
5814 : : }
5815 : : }
5816 : :
5817 : 1 : if (TARGET_XOP)
5818 : : {
5819 : : /* The XOP VPPERM insn supports three inputs. By ignoring the
5820 : : one_operand_shuffle special case, we avoid creating another
5821 : : set of constant vectors in memory. */
5822 : 0 : one_operand_shuffle = false;
5823 : :
5824 : : /* mask = mask & {2*w-1, ...} */
5825 : 0 : vt = GEN_INT (2*w - 1);
5826 : : }
5827 : : else
5828 : : {
5829 : : /* mask = mask & {w-1, ...} */
5830 : 1 : vt = GEN_INT (w - 1);
5831 : : }
5832 : :
5833 : 1 : vt = gen_const_vec_duplicate (maskmode, vt);
5834 : 1 : mask = expand_simple_binop (maskmode, AND, mask, vt,
5835 : : NULL_RTX, 0, OPTAB_DIRECT);
5836 : :
5837 : : /* For non-QImode operations, convert the word permutation control
5838 : : into a byte permutation control. */
5839 : 1 : if (mode != V16QImode)
5840 : : {
5841 : 1 : mask = expand_simple_binop (maskmode, ASHIFT, mask,
5842 : 2 : GEN_INT (exact_log2 (e)),
5843 : : NULL_RTX, 0, OPTAB_DIRECT);
5844 : :
5845 : : /* Convert mask to vector of chars. */
5846 : 1 : mask = force_reg (V16QImode, gen_lowpart (V16QImode, mask));
5847 : :
5848 : : /* Replicate each of the input bytes into byte positions:
5849 : : (v2di) --> {0,0,0,0,0,0,0,0, 8,8,8,8,8,8,8,8}
5850 : : (v4si) --> {0,0,0,0, 4,4,4,4, 8,8,8,8, 12,12,12,12}
5851 : : (v8hi) --> {0,0, 2,2, 4,4, 6,6, ...}. */
5852 : 18 : for (i = 0; i < 16; ++i)
5853 : 16 : vec[i] = GEN_INT (i/e * e);
5854 : 1 : vt = gen_rtx_CONST_VECTOR (V16QImode, gen_rtvec_v (16, vec));
5855 : 1 : vt = validize_mem (force_const_mem (V16QImode, vt));
5856 : 1 : if (TARGET_XOP)
5857 : 0 : emit_insn (gen_xop_pperm (mask, mask, mask, vt));
5858 : : else
5859 : 1 : emit_insn (gen_ssse3_pshufbv16qi3 (mask, mask, vt));
5860 : :
5861 : : /* Convert it into the byte positions by doing
5862 : : mask = mask + {0,1,..,16/w, 0,1,..,16/w, ...} */
5863 : 17 : for (i = 0; i < 16; ++i)
5864 : 16 : vec[i] = GEN_INT (i % e);
5865 : 1 : vt = gen_rtx_CONST_VECTOR (V16QImode, gen_rtvec_v (16, vec));
5866 : 1 : vt = validize_mem (force_const_mem (V16QImode, vt));
5867 : 1 : emit_insn (gen_addv16qi3 (mask, mask, vt));
5868 : : }
5869 : :
5870 : : /* The actual shuffle operations all operate on V16QImode. */
5871 : 1 : op0 = gen_lowpart (V16QImode, op0);
5872 : 1 : op1 = gen_lowpart (V16QImode, op1);
5873 : :
5874 : 1 : if (TARGET_XOP)
5875 : : {
5876 : 0 : if (GET_MODE (target) != V16QImode)
5877 : 0 : target = gen_reg_rtx (V16QImode);
5878 : 0 : emit_insn (gen_xop_pperm (target, op0, op1, mask));
5879 : 0 : if (target != operands[0])
5880 : 0 : emit_move_insn (operands[0],
5881 : 0 : gen_lowpart (GET_MODE (operands[0]), target));
5882 : : }
5883 : 1 : else if (one_operand_shuffle)
5884 : : {
5885 : 1 : if (GET_MODE (target) != V16QImode)
5886 : 1 : target = gen_reg_rtx (V16QImode);
5887 : 1 : emit_insn (gen_ssse3_pshufbv16qi3 (target, op0, mask));
5888 : 1 : if (target != operands[0])
5889 : 1 : emit_move_insn (operands[0],
5890 : 1 : gen_lowpart (GET_MODE (operands[0]), target));
5891 : : }
5892 : : else
5893 : : {
5894 : 0 : rtx xops[6];
5895 : 0 : bool ok;
5896 : :
5897 : : /* Shuffle the two input vectors independently. */
5898 : 0 : t1 = gen_reg_rtx (V16QImode);
5899 : 0 : t2 = gen_reg_rtx (V16QImode);
5900 : 0 : emit_insn (gen_ssse3_pshufbv16qi3 (t1, op0, mask));
5901 : 0 : emit_insn (gen_ssse3_pshufbv16qi3 (t2, op1, mask));
5902 : :
5903 : 1 : merge_two:
5904 : : /* Then merge them together. The key is whether any given control
5905 : : element contained a bit set that indicates the second word. */
5906 : 1 : mask = operands[3];
5907 : 1 : vt = GEN_INT (w);
5908 : 1 : if (maskmode == V2DImode && !TARGET_SSE4_1)
5909 : : {
5910 : : /* Without SSE4.1, we don't have V2DImode EQ. Perform one
5911 : : more shuffle to convert the V2DI input mask into a V4SI
5912 : : input mask. At which point the masking that expand_int_vcond
5913 : : will work as desired. */
5914 : 0 : rtx t3 = gen_reg_rtx (V4SImode);
5915 : 0 : emit_insn (gen_sse2_pshufd_1 (t3, gen_lowpart (V4SImode, mask),
5916 : : const0_rtx, const0_rtx,
5917 : : const2_rtx, const2_rtx));
5918 : 0 : mask = t3;
5919 : 0 : maskmode = V4SImode;
5920 : 0 : e = w = 4;
5921 : : }
5922 : :
5923 : 1 : vt = gen_const_vec_duplicate (maskmode, vt);
5924 : 1 : vt = force_reg (maskmode, vt);
5925 : 1 : mask = expand_simple_binop (maskmode, AND, mask, vt,
5926 : : NULL_RTX, 0, OPTAB_DIRECT);
5927 : :
5928 : 1 : if (GET_MODE (target) != mode)
5929 : 0 : target = gen_reg_rtx (mode);
5930 : 1 : xops[0] = target;
5931 : 1 : xops[1] = gen_lowpart (mode, t2);
5932 : 1 : xops[2] = gen_lowpart (mode, t1);
5933 : 1 : xops[3] = gen_rtx_EQ (maskmode, mask, vt);
5934 : 1 : xops[4] = mask;
5935 : 1 : xops[5] = vt;
5936 : 1 : ok = ix86_expand_int_vcond (xops);
5937 : 1 : gcc_assert (ok);
5938 : 1 : if (target != operands[0])
5939 : 0 : emit_move_insn (operands[0],
5940 : 0 : gen_lowpart (GET_MODE (operands[0]), target));
5941 : : }
5942 : : }
5943 : :
5944 : : /* Extend SRC into next wider integer vector type. UNSIGNED_P is
5945 : : true if we should do zero extension, else sign extension. */
5946 : :
5947 : : void
5948 : 253 : ix86_expand_sse_extend (rtx dest, rtx src, bool unsigned_p)
5949 : : {
5950 : 253 : machine_mode imode = GET_MODE (src);
5951 : 253 : rtx ops[3];
5952 : :
5953 : 253 : switch (imode)
5954 : : {
5955 : 253 : case E_V8QImode:
5956 : 253 : case E_V4QImode:
5957 : 253 : case E_V2QImode:
5958 : 253 : case E_V4HImode:
5959 : 253 : case E_V2HImode:
5960 : 253 : case E_V2SImode:
5961 : 253 : break;
5962 : 0 : default:
5963 : 0 : gcc_unreachable ();
5964 : : }
5965 : :
5966 : 253 : ops[0] = dest;
5967 : :
5968 : 253 : ops[1] = force_reg (imode, src);
5969 : :
5970 : 253 : if (unsigned_p)
5971 : 71 : ops[2] = force_reg (imode, CONST0_RTX (imode));
5972 : : else
5973 : 182 : ops[2] = ix86_expand_sse_cmp (gen_reg_rtx (imode), GT, CONST0_RTX (imode),
5974 : : ops[1], pc_rtx, pc_rtx);
5975 : :
5976 : 253 : ix86_split_mmx_punpck (ops, false);
5977 : 253 : }
5978 : :
5979 : : /* Unpack SRC into the next wider integer vector type. UNSIGNED_P is
5980 : : true if we should do zero extension, else sign extension. HIGH_P is
5981 : : true if we want the N/2 high elements, else the low elements. */
5982 : :
5983 : : void
5984 : 18559 : ix86_expand_sse_unpack (rtx dest, rtx src, bool unsigned_p, bool high_p)
5985 : : {
5986 : 18559 : machine_mode imode = GET_MODE (src);
5987 : 18559 : rtx tmp;
5988 : :
5989 : 18559 : if (TARGET_SSE4_1)
5990 : : {
5991 : 6305 : rtx (*unpack)(rtx, rtx);
5992 : 6305 : rtx (*extract)(rtx, rtx) = NULL;
5993 : 6305 : machine_mode halfmode = BLKmode;
5994 : :
5995 : 6305 : switch (imode)
5996 : : {
5997 : 116 : case E_V64QImode:
5998 : 116 : if (unsigned_p)
5999 : : unpack = gen_avx512bw_zero_extendv32qiv32hi2;
6000 : : else
6001 : 62 : unpack = gen_avx512bw_sign_extendv32qiv32hi2;
6002 : 116 : halfmode = V32QImode;
6003 : 116 : extract
6004 : 116 : = high_p ? gen_vec_extract_hi_v64qi : gen_vec_extract_lo_v64qi;
6005 : : break;
6006 : 687 : case E_V32QImode:
6007 : 687 : if (unsigned_p)
6008 : : unpack = gen_avx2_zero_extendv16qiv16hi2;
6009 : : else
6010 : 142 : unpack = gen_avx2_sign_extendv16qiv16hi2;
6011 : 687 : halfmode = V16QImode;
6012 : 687 : extract
6013 : 687 : = high_p ? gen_vec_extract_hi_v32qi : gen_vec_extract_lo_v32qi;
6014 : : break;
6015 : 102 : case E_V32HImode:
6016 : 102 : if (unsigned_p)
6017 : : unpack = gen_avx512f_zero_extendv16hiv16si2;
6018 : : else
6019 : 60 : unpack = gen_avx512f_sign_extendv16hiv16si2;
6020 : 102 : halfmode = V16HImode;
6021 : 102 : extract
6022 : 102 : = high_p ? gen_vec_extract_hi_v32hi : gen_vec_extract_lo_v32hi;
6023 : : break;
6024 : 467 : case E_V16HImode:
6025 : 467 : if (unsigned_p)
6026 : : unpack = gen_avx2_zero_extendv8hiv8si2;
6027 : : else
6028 : 348 : unpack = gen_avx2_sign_extendv8hiv8si2;
6029 : 467 : halfmode = V8HImode;
6030 : 467 : extract
6031 : 467 : = high_p ? gen_vec_extract_hi_v16hi : gen_vec_extract_lo_v16hi;
6032 : : break;
6033 : 124 : case E_V16SImode:
6034 : 124 : if (unsigned_p)
6035 : : unpack = gen_avx512f_zero_extendv8siv8di2;
6036 : : else
6037 : 106 : unpack = gen_avx512f_sign_extendv8siv8di2;
6038 : 124 : halfmode = V8SImode;
6039 : 124 : extract
6040 : 124 : = high_p ? gen_vec_extract_hi_v16si : gen_vec_extract_lo_v16si;
6041 : : break;
6042 : 388 : case E_V8SImode:
6043 : 388 : if (unsigned_p)
6044 : : unpack = gen_avx2_zero_extendv4siv4di2;
6045 : : else
6046 : 334 : unpack = gen_avx2_sign_extendv4siv4di2;
6047 : 388 : halfmode = V4SImode;
6048 : 388 : extract
6049 : 388 : = high_p ? gen_vec_extract_hi_v8si : gen_vec_extract_lo_v8si;
6050 : : break;
6051 : 2556 : case E_V16QImode:
6052 : 2556 : if (unsigned_p)
6053 : : unpack = gen_sse4_1_zero_extendv8qiv8hi2;
6054 : : else
6055 : 257 : unpack = gen_sse4_1_sign_extendv8qiv8hi2;
6056 : : break;
6057 : 955 : case E_V8HImode:
6058 : 955 : if (unsigned_p)
6059 : : unpack = gen_sse4_1_zero_extendv4hiv4si2;
6060 : : else
6061 : 746 : unpack = gen_sse4_1_sign_extendv4hiv4si2;
6062 : : break;
6063 : 530 : case E_V4SImode:
6064 : 530 : if (unsigned_p)
6065 : : unpack = gen_sse4_1_zero_extendv2siv2di2;
6066 : : else
6067 : 478 : unpack = gen_sse4_1_sign_extendv2siv2di2;
6068 : : break;
6069 : 111 : case E_V8QImode:
6070 : 111 : if (unsigned_p)
6071 : : unpack = gen_sse4_1_zero_extendv4qiv4hi2;
6072 : : else
6073 : 72 : unpack = gen_sse4_1_sign_extendv4qiv4hi2;
6074 : : break;
6075 : 263 : case E_V4HImode:
6076 : 263 : if (unsigned_p)
6077 : : unpack = gen_sse4_1_zero_extendv2hiv2si2;
6078 : : else
6079 : 208 : unpack = gen_sse4_1_sign_extendv2hiv2si2;
6080 : : break;
6081 : 6 : case E_V4QImode:
6082 : 6 : if (unsigned_p)
6083 : : unpack = gen_sse4_1_zero_extendv2qiv2hi2;
6084 : : else
6085 : 0 : unpack = gen_sse4_1_sign_extendv2qiv2hi2;
6086 : : break;
6087 : 0 : default:
6088 : 0 : gcc_unreachable ();
6089 : : }
6090 : :
6091 : 12610 : if (GET_MODE_SIZE (imode) >= 32)
6092 : : {
6093 : 1884 : tmp = gen_reg_rtx (halfmode);
6094 : 1884 : emit_insn (extract (tmp, src));
6095 : : }
6096 : 4421 : else if (high_p)
6097 : : {
6098 : 2262 : switch (GET_MODE_SIZE (imode))
6099 : : {
6100 : 938 : case 16:
6101 : : /* Shift higher 8 bytes to lower 8 bytes. */
6102 : 938 : tmp = gen_reg_rtx (V1TImode);
6103 : 938 : emit_insn (gen_sse2_lshrv1ti3 (tmp, gen_lowpart (V1TImode, src),
6104 : : GEN_INT (64)));
6105 : 938 : break;
6106 : 190 : case 8:
6107 : : /* Shift higher 4 bytes to lower 4 bytes. */
6108 : 190 : tmp = gen_reg_rtx (V1DImode);
6109 : 190 : emit_insn (gen_mmx_lshrv1di3 (tmp, gen_lowpart (V1DImode, src),
6110 : : GEN_INT (32)));
6111 : 190 : break;
6112 : 3 : case 4:
6113 : : /* Shift higher 2 bytes to lower 2 bytes. */
6114 : 3 : tmp = gen_reg_rtx (V1SImode);
6115 : 3 : emit_insn (gen_mmx_lshrv1si3 (tmp, gen_lowpart (V1SImode, src),
6116 : : GEN_INT (16)));
6117 : 3 : break;
6118 : 0 : default:
6119 : 0 : gcc_unreachable ();
6120 : : }
6121 : :
6122 : 1131 : tmp = gen_lowpart (imode, tmp);
6123 : : }
6124 : : else
6125 : : tmp = src;
6126 : :
6127 : 6305 : emit_insn (unpack (dest, tmp));
6128 : : }
6129 : : else
6130 : : {
6131 : 12254 : rtx (*unpack)(rtx, rtx, rtx);
6132 : :
6133 : 12254 : switch (imode)
6134 : : {
6135 : 3190 : case E_V16QImode:
6136 : 3190 : if (high_p)
6137 : : unpack = gen_vec_interleave_highv16qi;
6138 : : else
6139 : 1598 : unpack = gen_vec_interleave_lowv16qi;
6140 : : break;
6141 : 4856 : case E_V8HImode:
6142 : 4856 : if (high_p)
6143 : : unpack = gen_vec_interleave_highv8hi;
6144 : : else
6145 : 2428 : unpack = gen_vec_interleave_lowv8hi;
6146 : : break;
6147 : 2352 : case E_V4SImode:
6148 : 2352 : if (high_p)
6149 : : unpack = gen_vec_interleave_highv4si;
6150 : : else
6151 : 1176 : unpack = gen_vec_interleave_lowv4si;
6152 : : break;
6153 : 632 : case E_V8QImode:
6154 : 632 : if (high_p)
6155 : : unpack = gen_mmx_punpckhbw;
6156 : : else
6157 : 316 : unpack = gen_mmx_punpcklbw;
6158 : : break;
6159 : 1210 : case E_V4HImode:
6160 : 1210 : if (high_p)
6161 : : unpack = gen_mmx_punpckhwd;
6162 : : else
6163 : 605 : unpack = gen_mmx_punpcklwd;
6164 : : break;
6165 : 14 : case E_V4QImode:
6166 : 14 : if (high_p)
6167 : : unpack = gen_mmx_punpckhbw_low;
6168 : : else
6169 : 7 : unpack = gen_mmx_punpcklbw_low;
6170 : : break;
6171 : 0 : default:
6172 : 0 : gcc_unreachable ();
6173 : : }
6174 : :
6175 : 12254 : if (unsigned_p)
6176 : 4856 : tmp = force_reg (imode, CONST0_RTX (imode));
6177 : : else
6178 : 7398 : tmp = ix86_expand_sse_cmp (gen_reg_rtx (imode), GT, CONST0_RTX (imode),
6179 : : src, pc_rtx, pc_rtx);
6180 : :
6181 : 12254 : rtx tmp2 = gen_reg_rtx (imode);
6182 : 12254 : emit_insn (unpack (tmp2, src, tmp));
6183 : 12254 : emit_move_insn (dest, gen_lowpart (GET_MODE (dest), tmp2));
6184 : : }
6185 : 18559 : }
6186 : :
6187 : : /* Return true if mem is pool constant which contains a const_vector
6188 : : perm index, assign the index to PERM. */
6189 : : bool
6190 : 35 : ix86_extract_perm_from_pool_constant (int* perm, rtx mem)
6191 : : {
6192 : 35 : machine_mode mode = GET_MODE (mem);
6193 : 35 : int nelt = GET_MODE_NUNITS (mode);
6194 : :
6195 : 35 : if (!INTEGRAL_MODE_P (mode))
6196 : : return false;
6197 : :
6198 : : /* Needs to be constant pool. */
6199 : 35 : if (!(MEM_P (mem))
6200 : 35 : || !SYMBOL_REF_P (XEXP (mem, 0))
6201 : 70 : || !CONSTANT_POOL_ADDRESS_P (XEXP (mem, 0)))
6202 : : return false;
6203 : :
6204 : 35 : rtx constant = get_pool_constant (XEXP (mem, 0));
6205 : :
6206 : 35 : if (!CONST_VECTOR_P (constant))
6207 : : return false;
6208 : :
6209 : : /* There could be some rtx like
6210 : : (mem/u/c:V16QI (symbol_ref/u:DI ("*.LC1")))
6211 : : but with "*.LC1" refer to V2DI constant vector. */
6212 : 35 : if (GET_MODE (constant) != mode)
6213 : : {
6214 : 0 : constant = simplify_subreg (mode, constant, GET_MODE (constant), 0);
6215 : :
6216 : 0 : if (constant == nullptr || !CONST_VECTOR_P (constant))
6217 : : return false;
6218 : : }
6219 : :
6220 : 771 : for (int i = 0; i != nelt; i++)
6221 : 736 : perm[i] = UINTVAL (XVECEXP (constant, 0, i));
6222 : :
6223 : : return true;
6224 : : }
6225 : :
6226 : : /* Split operands 0 and 1 into half-mode parts. Similar to split_double_mode,
6227 : : but works for floating pointer parameters and nonoffsetable memories.
6228 : : For pushes, it returns just stack offsets; the values will be saved
6229 : : in the right order. Maximally three parts are generated. */
6230 : :
6231 : : static int
6232 : 4119238 : ix86_split_to_parts (rtx operand, rtx *parts, machine_mode mode)
6233 : : {
6234 : 4119238 : int size;
6235 : :
6236 : 4119238 : if (!TARGET_64BIT)
6237 : 1559038 : size = mode==XFmode ? 3 : GET_MODE_SIZE (mode) / 4;
6238 : : else
6239 : 6678164 : size = (GET_MODE_SIZE (mode) + 4) / 8;
6240 : :
6241 : 4119238 : gcc_assert (!REG_P (operand) || !MMX_REGNO_P (REGNO (operand)));
6242 : 4119238 : gcc_assert (size >= 2 && size <= 4);
6243 : :
6244 : : /* Optimize constant pool reference to immediates. This is used by fp
6245 : : moves, that force all constants to memory to allow combining. */
6246 : 4119238 : if (MEM_P (operand) && MEM_READONLY_P (operand))
6247 : 36206 : operand = avoid_constant_pool_reference (operand);
6248 : :
6249 : 4119238 : if (MEM_P (operand) && !offsettable_memref_p (operand))
6250 : : {
6251 : : /* The only non-offsetable memories we handle are pushes. */
6252 : 184671 : int ok = push_operand (operand, VOIDmode);
6253 : :
6254 : 184671 : gcc_assert (ok);
6255 : :
6256 : 184671 : operand = copy_rtx (operand);
6257 : 184671 : PUT_MODE (operand, word_mode);
6258 : 184671 : parts[0] = parts[1] = parts[2] = parts[3] = operand;
6259 : 184671 : return size;
6260 : : }
6261 : :
6262 : 3934567 : if (CONST_VECTOR_P (operand))
6263 : : {
6264 : 41860 : scalar_int_mode imode = int_mode_for_mode (mode).require ();
6265 : : /* Caution: if we looked through a constant pool memory above,
6266 : : the operand may actually have a different mode now. That's
6267 : : ok, since we want to pun this all the way back to an integer. */
6268 : 41860 : operand = simplify_subreg (imode, operand, GET_MODE (operand), 0);
6269 : 41860 : gcc_assert (operand != NULL);
6270 : 41860 : mode = imode;
6271 : : }
6272 : :
6273 : 3934567 : if (!TARGET_64BIT)
6274 : : {
6275 : 621916 : if (mode == DImode)
6276 : 493831 : split_double_mode (mode, &operand, 1, &parts[0], &parts[1]);
6277 : : else
6278 : : {
6279 : 128085 : int i;
6280 : :
6281 : 128085 : if (REG_P (operand))
6282 : : {
6283 : 66539 : gcc_assert (reload_completed);
6284 : 199617 : for (i = 0; i < size; i++)
6285 : 133078 : parts[i] = gen_rtx_REG (SImode, REGNO (operand) + i);
6286 : : }
6287 : 61546 : else if (offsettable_memref_p (operand))
6288 : : {
6289 : 60260 : operand = adjust_address (operand, SImode, 0);
6290 : 60260 : parts[0] = operand;
6291 : 121028 : for (i = 1; i < size; i++)
6292 : 60768 : parts[i] = adjust_address (operand, SImode, 4 * i);
6293 : : }
6294 : 1286 : else if (CONST_DOUBLE_P (operand))
6295 : : {
6296 : 1286 : const REAL_VALUE_TYPE *r;
6297 : 1286 : long l[4];
6298 : :
6299 : 1286 : r = CONST_DOUBLE_REAL_VALUE (operand);
6300 : 1286 : switch (mode)
6301 : : {
6302 : 0 : case E_TFmode:
6303 : 0 : real_to_target (l, r, mode);
6304 : 0 : parts[3] = gen_int_mode (l[3], SImode);
6305 : 0 : parts[2] = gen_int_mode (l[2], SImode);
6306 : 0 : break;
6307 : 212 : case E_XFmode:
6308 : : /* We can't use REAL_VALUE_TO_TARGET_LONG_DOUBLE since
6309 : : long double may not be 80-bit. */
6310 : 212 : real_to_target (l, r, mode);
6311 : 212 : parts[2] = gen_int_mode (l[2], SImode);
6312 : 212 : break;
6313 : 1074 : case E_DFmode:
6314 : 1074 : REAL_VALUE_TO_TARGET_DOUBLE (*r, l);
6315 : 1074 : break;
6316 : 0 : default:
6317 : 0 : gcc_unreachable ();
6318 : : }
6319 : 1286 : parts[1] = gen_int_mode (l[1], SImode);
6320 : 1286 : parts[0] = gen_int_mode (l[0], SImode);
6321 : : }
6322 : : else
6323 : 0 : gcc_unreachable ();
6324 : : }
6325 : : }
6326 : : else
6327 : : {
6328 : 3312651 : if (mode == TImode)
6329 : 3292111 : split_double_mode (mode, &operand, 1, &parts[0], &parts[1]);
6330 : 3312651 : if (mode == XFmode || mode == TFmode)
6331 : : {
6332 : 20540 : machine_mode upper_mode = mode==XFmode ? SImode : DImode;
6333 : 20540 : if (REG_P (operand))
6334 : : {
6335 : 1595 : gcc_assert (reload_completed);
6336 : 1595 : parts[0] = gen_rtx_REG (DImode, REGNO (operand) + 0);
6337 : 1595 : parts[1] = gen_rtx_REG (upper_mode, REGNO (operand) + 1);
6338 : : }
6339 : 18945 : else if (offsettable_memref_p (operand))
6340 : : {
6341 : 15237 : operand = adjust_address (operand, DImode, 0);
6342 : 15237 : parts[0] = operand;
6343 : 15237 : parts[1] = adjust_address (operand, upper_mode, 8);
6344 : : }
6345 : 3708 : else if (CONST_DOUBLE_P (operand))
6346 : : {
6347 : 3708 : long l[4];
6348 : :
6349 : 3708 : real_to_target (l, CONST_DOUBLE_REAL_VALUE (operand), mode);
6350 : :
6351 : : /* real_to_target puts 32-bit pieces in each long. */
6352 : 7416 : parts[0] = gen_int_mode ((l[0] & HOST_WIDE_INT_C (0xffffffff))
6353 : 3708 : | ((l[1] & HOST_WIDE_INT_C (0xffffffff))
6354 : 3708 : << 32), DImode);
6355 : :
6356 : 3708 : if (upper_mode == SImode)
6357 : 2769 : parts[1] = gen_int_mode (l[2], SImode);
6358 : : else
6359 : 939 : parts[1]
6360 : 939 : = gen_int_mode ((l[2] & HOST_WIDE_INT_C (0xffffffff))
6361 : 939 : | ((l[3] & HOST_WIDE_INT_C (0xffffffff))
6362 : 939 : << 32), DImode);
6363 : : }
6364 : : else
6365 : 0 : gcc_unreachable ();
6366 : : }
6367 : : }
6368 : :
6369 : : return size;
6370 : : }
6371 : :
6372 : : /* Emit insns to perform a move or push of DI, DF, XF, and TF values.
6373 : : Return false when normal moves are needed; true when all required
6374 : : insns have been emitted. Operands 2-4 contain the input values
6375 : : int the correct order; operands 5-7 contain the output values. */
6376 : :
6377 : : void
6378 : 2072549 : ix86_split_long_move (rtx operands[])
6379 : : {
6380 : 2072549 : rtx part[2][4];
6381 : 2072549 : int nparts, i, j;
6382 : 2072549 : int push = 0;
6383 : 2072549 : int collisions = 0;
6384 : 2072549 : machine_mode mode = GET_MODE (operands[0]);
6385 : 2072549 : bool collisionparts[4];
6386 : :
6387 : : /* The DFmode expanders may ask us to move double.
6388 : : For 64bit target this is single move. By hiding the fact
6389 : : here we simplify i386.md splitters. */
6390 : 3755020 : if (TARGET_64BIT && GET_MODE_SIZE (GET_MODE (operands[0])) == 8)
6391 : : {
6392 : : /* Optimize constant pool reference to immediates. This is used by
6393 : : fp moves, that force all constants to memory to allow combining. */
6394 : :
6395 : 12930 : if (MEM_P (operands[1])
6396 : 12516 : && SYMBOL_REF_P (XEXP (operands[1], 0))
6397 : 13536 : && CONSTANT_POOL_ADDRESS_P (XEXP (operands[1], 0)))
6398 : 117 : operands[1] = get_pool_constant (XEXP (operands[1], 0));
6399 : 12930 : if (push_operand (operands[0], VOIDmode))
6400 : : {
6401 : 12930 : operands[0] = copy_rtx (operands[0]);
6402 : 12930 : PUT_MODE (operands[0], word_mode);
6403 : : }
6404 : : else
6405 : 0 : operands[0] = gen_lowpart (DImode, operands[0]);
6406 : 12930 : operands[1] = gen_lowpart (DImode, operands[1]);
6407 : 12930 : emit_move_insn (operands[0], operands[1]);
6408 : 12930 : return;
6409 : : }
6410 : :
6411 : : /* The only non-offsettable memory we handle is push. */
6412 : 2059619 : if (push_operand (operands[0], VOIDmode))
6413 : : push = 1;
6414 : : else
6415 : 1874948 : gcc_assert (!MEM_P (operands[0])
6416 : : || offsettable_memref_p (operands[0]));
6417 : :
6418 : 2059619 : nparts = ix86_split_to_parts (operands[1], part[1], GET_MODE (operands[0]));
6419 : 2059619 : ix86_split_to_parts (operands[0], part[0], GET_MODE (operands[0]));
6420 : :
6421 : : /* When emitting push, take care for source operands on the stack. */
6422 : 184671 : if (push && MEM_P (operands[1])
6423 : 2157716 : && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
6424 : : {
6425 : 56488 : rtx src_base = XEXP (part[1][nparts - 1], 0);
6426 : :
6427 : : /* Compensate for the stack decrement by 4. */
6428 : 56488 : if (!TARGET_64BIT && nparts == 3
6429 : 50853 : && mode == XFmode && TARGET_128BIT_LONG_DOUBLE)
6430 : 0 : src_base = plus_constant (Pmode, src_base, 4);
6431 : :
6432 : : /* src_base refers to the stack pointer and is
6433 : : automatically decreased by emitted push. */
6434 : 169743 : for (i = 0; i < nparts; i++)
6435 : 113255 : part[1][i] = change_address (part[1][i],
6436 : 113255 : GET_MODE (part[1][i]), src_base);
6437 : : }
6438 : :
6439 : : /* We need to do copy in the right order in case an address register
6440 : : of the source overlaps the destination. */
6441 : 2059619 : if (REG_P (part[0][0]) && MEM_P (part[1][0]))
6442 : : {
6443 : : rtx tmp;
6444 : :
6445 : 2345220 : for (i = 0; i < nparts; i++)
6446 : : {
6447 : 1563480 : collisionparts[i]
6448 : 1563480 : = reg_overlap_mentioned_p (part[0][i], XEXP (part[1][0], 0));
6449 : 1563480 : if (collisionparts[i])
6450 : 16638 : collisions++;
6451 : : }
6452 : :
6453 : : /* Collision in the middle part can be handled by reordering. */
6454 : 781740 : if (collisions == 1 && nparts == 3 && collisionparts [1])
6455 : : {
6456 : 0 : std::swap (part[0][1], part[0][2]);
6457 : 0 : std::swap (part[1][1], part[1][2]);
6458 : : }
6459 : 781740 : else if (collisions == 1
6460 : 781740 : && nparts == 4
6461 : 0 : && (collisionparts [1] || collisionparts [2]))
6462 : : {
6463 : 0 : if (collisionparts [1])
6464 : : {
6465 : 0 : std::swap (part[0][1], part[0][2]);
6466 : 0 : std::swap (part[1][1], part[1][2]);
6467 : : }
6468 : : else
6469 : : {
6470 : 0 : std::swap (part[0][2], part[0][3]);
6471 : 0 : std::swap (part[1][2], part[1][3]);
6472 : : }
6473 : : }
6474 : :
6475 : : /* If there are more collisions, we can't handle it by reordering.
6476 : : Do an lea to the last part and use only one colliding move. */
6477 : 781740 : else if (collisions > 1)
6478 : : {
6479 : 82 : rtx base, addr;
6480 : :
6481 : 82 : collisions = 1;
6482 : :
6483 : 82 : base = part[0][nparts - 1];
6484 : :
6485 : : /* Handle the case when the last part isn't valid for lea.
6486 : : Happens in 64-bit mode storing the 12-byte XFmode. */
6487 : 124 : if (GET_MODE (base) != Pmode)
6488 : 0 : base = gen_rtx_REG (Pmode, REGNO (base));
6489 : :
6490 : 82 : addr = XEXP (part[1][0], 0);
6491 : 82 : if (TARGET_TLS_DIRECT_SEG_REFS)
6492 : : {
6493 : 82 : struct ix86_address parts;
6494 : 82 : int ok = ix86_decompose_address (addr, &parts);
6495 : 82 : gcc_assert (ok);
6496 : : /* It is not valid to use %gs: or %fs: in lea. */
6497 : 82 : gcc_assert (parts.seg == ADDR_SPACE_GENERIC);
6498 : : }
6499 : 82 : emit_insn (gen_rtx_SET (base, addr));
6500 : 82 : part[1][0] = replace_equiv_address (part[1][0], base);
6501 : 164 : for (i = 1; i < nparts; i++)
6502 : : {
6503 : 166 : tmp = plus_constant (Pmode, base, UNITS_PER_WORD * i);
6504 : 82 : part[1][i] = replace_equiv_address (part[1][i], tmp);
6505 : : }
6506 : : }
6507 : : }
6508 : :
6509 : 2059619 : if (push)
6510 : : {
6511 : 184671 : if (!TARGET_64BIT)
6512 : : {
6513 : 158240 : if (nparts == 3)
6514 : : {
6515 : 554 : if (TARGET_128BIT_LONG_DOUBLE && mode == XFmode)
6516 : 0 : emit_insn (gen_add2_insn (stack_pointer_rtx, GEN_INT (-4)));
6517 : 554 : emit_move_insn (part[0][2], part[1][2]);
6518 : : }
6519 : 157686 : else if (nparts == 4)
6520 : : {
6521 : 0 : emit_move_insn (part[0][3], part[1][3]);
6522 : 0 : emit_move_insn (part[0][2], part[1][2]);
6523 : : }
6524 : : }
6525 : : else
6526 : : {
6527 : : /* In 64bit mode we don't have 32bit push available. In case this is
6528 : : register, it is OK - we will just use larger counterpart. We also
6529 : : retype memory - these comes from attempt to avoid REX prefix on
6530 : : moving of second half of TFmode value. */
6531 : 26431 : if (GET_MODE (part[1][1]) == SImode)
6532 : : {
6533 : 12383 : switch (GET_CODE (part[1][1]))
6534 : : {
6535 : 11915 : case MEM:
6536 : 11915 : part[1][1] = adjust_address (part[1][1], DImode, 0);
6537 : 11915 : break;
6538 : :
6539 : 468 : case REG:
6540 : 468 : part[1][1] = gen_rtx_REG (DImode, REGNO (part[1][1]));
6541 : 468 : break;
6542 : :
6543 : 0 : default:
6544 : 0 : gcc_unreachable ();
6545 : : }
6546 : :
6547 : 12383 : if (GET_MODE (part[1][0]) == SImode)
6548 : 0 : part[1][0] = part[1][1];
6549 : : }
6550 : : }
6551 : 184671 : emit_move_insn (part[0][1], part[1][1]);
6552 : 184671 : emit_move_insn (part[0][0], part[1][0]);
6553 : 184671 : return;
6554 : : }
6555 : :
6556 : : /* Choose correct order to not overwrite the source before it is copied. */
6557 : 1874948 : if ((REG_P (part[0][0])
6558 : 1026236 : && REG_P (part[1][1])
6559 : 84438 : && (REGNO (part[0][0]) == REGNO (part[1][1])
6560 : 69103 : || (nparts == 3
6561 : 0 : && REGNO (part[0][0]) == REGNO (part[1][2]))
6562 : 69103 : || (nparts == 4
6563 : 0 : && REGNO (part[0][0]) == REGNO (part[1][3]))))
6564 : 2885849 : || (collisions > 0
6565 : 16556 : && reg_overlap_mentioned_p (part[0][0], XEXP (part[1][0], 0))))
6566 : : {
6567 : 94878 : for (i = 0, j = nparts - 1; i < nparts; i++, j--)
6568 : : {
6569 : 63252 : operands[2 + i] = part[0][j];
6570 : 63252 : operands[6 + i] = part[1][j];
6571 : : }
6572 : : }
6573 : : else
6574 : : {
6575 : 5530049 : for (i = 0; i < nparts; i++)
6576 : : {
6577 : 3686727 : operands[2 + i] = part[0][i];
6578 : 3686727 : operands[6 + i] = part[1][i];
6579 : : }
6580 : : }
6581 : :
6582 : : /* Attempt to locally unCSE nonzero constants. */
6583 : 3749979 : for (j = 0; j < nparts - 1; j++)
6584 : 1875031 : if (CONST_INT_P (operands[6 + j])
6585 : 226283 : && operands[6 + j] != const0_rtx
6586 : 65045 : && REG_P (operands[2 + j]))
6587 : 116046 : for (i = j; i < nparts - 1; i++)
6588 : 58023 : if (CONST_INT_P (operands[7 + i])
6589 : 58023 : && INTVAL (operands[7 + i]) == INTVAL (operands[6 + j]))
6590 : 22586 : operands[7 + i] = operands[2 + j];
6591 : :
6592 : 5624927 : for (i = 0; i < nparts; i++)
6593 : 3749979 : emit_move_insn (operands[2 + i], operands[6 + i]);
6594 : :
6595 : : return;
6596 : : }
6597 : :
6598 : : /* Helper function of ix86_split_ashl used to generate an SImode/DImode
6599 : : left shift by a constant, either using a single shift or
6600 : : a sequence of add instructions. */
6601 : :
6602 : : static void
6603 : 4342 : ix86_expand_ashl_const (rtx operand, int count, machine_mode mode)
6604 : : {
6605 : 4342 : if (count == 1
6606 : 4342 : || (count * ix86_cost->add <= ix86_cost->shift_const
6607 : 0 : && !optimize_insn_for_size_p ()))
6608 : : {
6609 : 16 : while (count-- > 0)
6610 : 8 : emit_insn (gen_add2_insn (operand, operand));
6611 : : }
6612 : : else
6613 : : {
6614 : 4334 : rtx (*insn)(rtx, rtx, rtx);
6615 : :
6616 : 4334 : insn = mode == DImode ? gen_ashlsi3 : gen_ashldi3;
6617 : 4334 : emit_insn (insn (operand, operand, GEN_INT (count)));
6618 : : }
6619 : 4342 : }
6620 : :
6621 : : void
6622 : 10504 : ix86_split_ashl (rtx *operands, rtx scratch, machine_mode mode)
6623 : : {
6624 : 10504 : rtx (*gen_ashl3)(rtx, rtx, rtx);
6625 : 10504 : rtx (*gen_shld)(rtx, rtx, rtx);
6626 : 10504 : int half_width = GET_MODE_BITSIZE (mode) >> 1;
6627 : 10504 : machine_mode half_mode;
6628 : :
6629 : 10504 : rtx low[2], high[2];
6630 : 10504 : int count;
6631 : :
6632 : 10504 : if (CONST_INT_P (operands[2]))
6633 : : {
6634 : 8797 : split_double_mode (mode, operands, 2, low, high);
6635 : 8797 : count = INTVAL (operands[2]) & (GET_MODE_BITSIZE (mode) - 1);
6636 : :
6637 : 8797 : if (count >= half_width)
6638 : : {
6639 : 2463 : emit_move_insn (high[0], low[1]);
6640 : 2463 : ix86_expand_clear (low[0]);
6641 : :
6642 : 2463 : if (count > half_width)
6643 : 141 : ix86_expand_ashl_const (high[0], count - half_width, mode);
6644 : : }
6645 : 6334 : else if (count == 1)
6646 : : {
6647 : 2133 : if (!rtx_equal_p (operands[0], operands[1]))
6648 : 0 : emit_move_insn (operands[0], operands[1]);
6649 : 2133 : rtx x3 = gen_rtx_REG (CCCmode, FLAGS_REG);
6650 : 2133 : rtx x4 = gen_rtx_LTU (mode, x3, const0_rtx);
6651 : 2133 : half_mode = mode == DImode ? SImode : DImode;
6652 : 2133 : emit_insn (gen_add3_cc_overflow_1 (half_mode, low[0],
6653 : : low[0], low[0]));
6654 : 2133 : emit_insn (gen_add3_carry (half_mode, high[0], high[0], high[0],
6655 : : x3, x4));
6656 : : }
6657 : : else
6658 : : {
6659 : 4201 : gen_shld = mode == DImode ? gen_x86_shld : gen_x86_64_shld;
6660 : :
6661 : 4201 : if (!rtx_equal_p (operands[0], operands[1]))
6662 : 0 : emit_move_insn (operands[0], operands[1]);
6663 : :
6664 : 4201 : emit_insn (gen_shld (high[0], low[0], GEN_INT (count)));
6665 : 4201 : ix86_expand_ashl_const (low[0], count, mode);
6666 : : }
6667 : 9068 : return;
6668 : : }
6669 : :
6670 : 1707 : split_double_mode (mode, operands, 1, low, high);
6671 : 1707 : half_mode = mode == DImode ? SImode : DImode;
6672 : :
6673 : 1707 : gen_ashl3 = mode == DImode ? gen_ashlsi3 : gen_ashldi3;
6674 : :
6675 : 1707 : if (operands[1] == const1_rtx)
6676 : : {
6677 : : /* Assuming we've chosen a QImode capable registers, then 1 << N
6678 : : can be done with two 32/64-bit shifts, no branches, no cmoves. */
6679 : 271 : if (ANY_QI_REG_P (low[0]) && ANY_QI_REG_P (high[0]))
6680 : : {
6681 : 163 : rtx s, d, flags = gen_rtx_REG (CCZmode, FLAGS_REG);
6682 : :
6683 : 163 : ix86_expand_clear (low[0]);
6684 : 163 : ix86_expand_clear (high[0]);
6685 : 163 : emit_insn (gen_testqi_ccz_1 (operands[2], GEN_INT (half_width)));
6686 : :
6687 : 163 : d = gen_lowpart (QImode, low[0]);
6688 : 163 : d = gen_rtx_STRICT_LOW_PART (VOIDmode, d);
6689 : 163 : s = gen_rtx_EQ (QImode, flags, const0_rtx);
6690 : 163 : emit_insn (gen_rtx_SET (d, s));
6691 : :
6692 : 163 : d = gen_lowpart (QImode, high[0]);
6693 : 163 : d = gen_rtx_STRICT_LOW_PART (VOIDmode, d);
6694 : 163 : s = gen_rtx_NE (QImode, flags, const0_rtx);
6695 : 163 : emit_insn (gen_rtx_SET (d, s));
6696 : : }
6697 : :
6698 : : /* Otherwise, we can get the same results by manually performing
6699 : : a bit extract operation on bit 5/6, and then performing the two
6700 : : shifts. The two methods of getting 0/1 into low/high are exactly
6701 : : the same size. Avoiding the shift in the bit extract case helps
6702 : : pentium4 a bit; no one else seems to care much either way. */
6703 : : else
6704 : : {
6705 : 108 : rtx (*gen_lshr3)(rtx, rtx, rtx);
6706 : 108 : rtx (*gen_and3)(rtx, rtx, rtx);
6707 : 108 : rtx (*gen_xor3)(rtx, rtx, rtx);
6708 : 108 : HOST_WIDE_INT bits;
6709 : 108 : rtx x;
6710 : :
6711 : 108 : if (mode == DImode)
6712 : : {
6713 : : gen_lshr3 = gen_lshrsi3;
6714 : : gen_and3 = gen_andsi3;
6715 : : gen_xor3 = gen_xorsi3;
6716 : : bits = 5;
6717 : : }
6718 : : else
6719 : : {
6720 : 0 : gen_lshr3 = gen_lshrdi3;
6721 : 0 : gen_and3 = gen_anddi3;
6722 : 0 : gen_xor3 = gen_xordi3;
6723 : 0 : bits = 6;
6724 : : }
6725 : :
6726 : 108 : if (TARGET_PARTIAL_REG_STALL && !optimize_insn_for_size_p ())
6727 : 0 : x = gen_rtx_ZERO_EXTEND (half_mode, operands[2]);
6728 : : else
6729 : 108 : x = gen_lowpart (half_mode, operands[2]);
6730 : 108 : emit_insn (gen_rtx_SET (high[0], x));
6731 : :
6732 : 108 : emit_insn (gen_lshr3 (high[0], high[0], GEN_INT (bits)));
6733 : 108 : emit_insn (gen_and3 (high[0], high[0], const1_rtx));
6734 : 108 : emit_move_insn (low[0], high[0]);
6735 : 108 : emit_insn (gen_xor3 (low[0], low[0], const1_rtx));
6736 : : }
6737 : :
6738 : 271 : emit_insn (gen_ashl3 (low[0], low[0], operands[2]));
6739 : 271 : emit_insn (gen_ashl3 (high[0], high[0], operands[2]));
6740 : 271 : return;
6741 : : }
6742 : :
6743 : 1436 : if (operands[1] == constm1_rtx)
6744 : : {
6745 : : /* For -1 << N, we can avoid the shld instruction, because we
6746 : : know that we're shifting 0...31/63 ones into a -1. */
6747 : 118 : emit_move_insn (low[0], constm1_rtx);
6748 : 118 : if (optimize_insn_for_size_p ())
6749 : 6 : emit_move_insn (high[0], low[0]);
6750 : : else
6751 : 112 : emit_move_insn (high[0], constm1_rtx);
6752 : : }
6753 : : else
6754 : : {
6755 : 1318 : gen_shld = mode == DImode ? gen_x86_shld : gen_x86_64_shld;
6756 : :
6757 : 1318 : if (!rtx_equal_p (operands[0], operands[1]))
6758 : 0 : emit_move_insn (operands[0], operands[1]);
6759 : :
6760 : 1318 : split_double_mode (mode, operands, 1, low, high);
6761 : 1318 : emit_insn (gen_shld (high[0], low[0], operands[2]));
6762 : : }
6763 : :
6764 : 1436 : emit_insn (gen_ashl3 (low[0], low[0], operands[2]));
6765 : :
6766 : 1436 : if (TARGET_CMOVE && scratch)
6767 : : {
6768 : 960 : ix86_expand_clear (scratch);
6769 : 960 : emit_insn (gen_x86_shift_adj_1
6770 : : (half_mode, high[0], low[0], operands[2], scratch));
6771 : : }
6772 : : else
6773 : 476 : emit_insn (gen_x86_shift_adj_2 (half_mode, high[0], low[0], operands[2]));
6774 : : }
6775 : :
6776 : : void
6777 : 6077 : ix86_split_ashr (rtx *operands, rtx scratch, machine_mode mode)
6778 : : {
6779 : 4834 : rtx (*gen_ashr3)(rtx, rtx, rtx)
6780 : 6077 : = mode == DImode ? gen_ashrsi3 : gen_ashrdi3;
6781 : 6077 : rtx (*gen_shrd)(rtx, rtx, rtx);
6782 : 6077 : int half_width = GET_MODE_BITSIZE (mode) >> 1;
6783 : :
6784 : 6077 : rtx low[2], high[2];
6785 : 6077 : int count;
6786 : :
6787 : 6077 : if (CONST_INT_P (operands[2]))
6788 : : {
6789 : 5896 : split_double_mode (mode, operands, 2, low, high);
6790 : 5896 : count = INTVAL (operands[2]) & (GET_MODE_BITSIZE (mode) - 1);
6791 : :
6792 : 11792 : if (count == GET_MODE_BITSIZE (mode) - 1)
6793 : : {
6794 : 90 : emit_move_insn (high[0], high[1]);
6795 : 90 : emit_insn (gen_ashr3 (high[0], high[0],
6796 : 90 : GEN_INT (half_width - 1)));
6797 : 90 : emit_move_insn (low[0], high[0]);
6798 : :
6799 : : }
6800 : 5806 : else if (count >= half_width)
6801 : : {
6802 : 1617 : emit_move_insn (low[0], high[1]);
6803 : 1617 : emit_move_insn (high[0], low[0]);
6804 : 1617 : emit_insn (gen_ashr3 (high[0], high[0],
6805 : 1617 : GEN_INT (half_width - 1)));
6806 : :
6807 : 1617 : if (count > half_width)
6808 : 38 : emit_insn (gen_ashr3 (low[0], low[0],
6809 : 38 : GEN_INT (count - half_width)));
6810 : : }
6811 : 4189 : else if (count == 1
6812 : 799 : && (TARGET_USE_RCR || optimize_size > 1))
6813 : : {
6814 : 1 : if (!rtx_equal_p (operands[0], operands[1]))
6815 : 0 : emit_move_insn (operands[0], operands[1]);
6816 : 1 : if (mode == DImode)
6817 : : {
6818 : 0 : emit_insn (gen_ashrsi3_carry (high[0], high[0]));
6819 : 0 : emit_insn (gen_rcrsi2 (low[0], low[0]));
6820 : : }
6821 : : else
6822 : : {
6823 : 1 : emit_insn (gen_ashrdi3_carry (high[0], high[0]));
6824 : 1 : emit_insn (gen_rcrdi2 (low[0], low[0]));
6825 : : }
6826 : : }
6827 : : else
6828 : : {
6829 : 4188 : gen_shrd = mode == DImode ? gen_x86_shrd : gen_x86_64_shrd;
6830 : :
6831 : 4188 : if (!rtx_equal_p (operands[0], operands[1]))
6832 : 0 : emit_move_insn (operands[0], operands[1]);
6833 : :
6834 : 4188 : emit_insn (gen_shrd (low[0], high[0], GEN_INT (count)));
6835 : 4188 : emit_insn (gen_ashr3 (high[0], high[0], GEN_INT (count)));
6836 : : }
6837 : : }
6838 : : else
6839 : : {
6840 : 181 : machine_mode half_mode;
6841 : :
6842 : 181 : gen_shrd = mode == DImode ? gen_x86_shrd : gen_x86_64_shrd;
6843 : :
6844 : 181 : if (!rtx_equal_p (operands[0], operands[1]))
6845 : 0 : emit_move_insn (operands[0], operands[1]);
6846 : :
6847 : 181 : split_double_mode (mode, operands, 1, low, high);
6848 : 181 : half_mode = mode == DImode ? SImode : DImode;
6849 : :
6850 : 181 : emit_insn (gen_shrd (low[0], high[0], operands[2]));
6851 : 181 : emit_insn (gen_ashr3 (high[0], high[0], operands[2]));
6852 : :
6853 : 181 : if (TARGET_CMOVE && scratch)
6854 : : {
6855 : 144 : emit_move_insn (scratch, high[0]);
6856 : 144 : emit_insn (gen_ashr3 (scratch, scratch,
6857 : 144 : GEN_INT (half_width - 1)));
6858 : 144 : emit_insn (gen_x86_shift_adj_1
6859 : : (half_mode, low[0], high[0], operands[2], scratch));
6860 : : }
6861 : : else
6862 : 37 : emit_insn (gen_x86_shift_adj_3
6863 : : (half_mode, low[0], high[0], operands[2]));
6864 : : }
6865 : 6077 : }
6866 : :
6867 : : void
6868 : 15098 : ix86_split_lshr (rtx *operands, rtx scratch, machine_mode mode)
6869 : : {
6870 : 7750 : rtx (*gen_lshr3)(rtx, rtx, rtx)
6871 : 15098 : = mode == DImode ? gen_lshrsi3 : gen_lshrdi3;
6872 : 15098 : rtx (*gen_shrd)(rtx, rtx, rtx);
6873 : 15098 : int half_width = GET_MODE_BITSIZE (mode) >> 1;
6874 : :
6875 : 15098 : rtx low[2], high[2];
6876 : 15098 : int count;
6877 : :
6878 : 15098 : if (CONST_INT_P (operands[2]))
6879 : : {
6880 : 13707 : split_double_mode (mode, operands, 2, low, high);
6881 : 13707 : count = INTVAL (operands[2]) & (GET_MODE_BITSIZE (mode) - 1);
6882 : :
6883 : 13707 : if (count >= half_width)
6884 : : {
6885 : 8466 : emit_move_insn (low[0], high[1]);
6886 : 8466 : ix86_expand_clear (high[0]);
6887 : :
6888 : 8466 : if (count > half_width)
6889 : 656 : emit_insn (gen_lshr3 (low[0], low[0],
6890 : 656 : GEN_INT (count - half_width)));
6891 : : }
6892 : 5241 : else if (count == 1
6893 : 993 : && (TARGET_USE_RCR || optimize_size > 1))
6894 : : {
6895 : 1 : if (!rtx_equal_p (operands[0], operands[1]))
6896 : 0 : emit_move_insn (operands[0], operands[1]);
6897 : 1 : if (mode == DImode)
6898 : : {
6899 : 0 : emit_insn (gen_lshrsi3_carry (high[0], high[0]));
6900 : 0 : emit_insn (gen_rcrsi2 (low[0], low[0]));
6901 : : }
6902 : : else
6903 : : {
6904 : 1 : emit_insn (gen_lshrdi3_carry (high[0], high[0]));
6905 : 1 : emit_insn (gen_rcrdi2 (low[0], low[0]));
6906 : : }
6907 : : }
6908 : : else
6909 : : {
6910 : 5240 : gen_shrd = mode == DImode ? gen_x86_shrd : gen_x86_64_shrd;
6911 : :
6912 : 5240 : if (!rtx_equal_p (operands[0], operands[1]))
6913 : 0 : emit_move_insn (operands[0], operands[1]);
6914 : :
6915 : 5240 : emit_insn (gen_shrd (low[0], high[0], GEN_INT (count)));
6916 : 5240 : emit_insn (gen_lshr3 (high[0], high[0], GEN_INT (count)));
6917 : : }
6918 : : }
6919 : : else
6920 : : {
6921 : 1391 : machine_mode half_mode;
6922 : :
6923 : 1391 : gen_shrd = mode == DImode ? gen_x86_shrd : gen_x86_64_shrd;
6924 : :
6925 : 1391 : if (!rtx_equal_p (operands[0], operands[1]))
6926 : 0 : emit_move_insn (operands[0], operands[1]);
6927 : :
6928 : 1391 : split_double_mode (mode, operands, 1, low, high);
6929 : 1391 : half_mode = mode == DImode ? SImode : DImode;
6930 : :
6931 : 1391 : emit_insn (gen_shrd (low[0], high[0], operands[2]));
6932 : 1391 : emit_insn (gen_lshr3 (high[0], high[0], operands[2]));
6933 : :
6934 : 1391 : if (TARGET_CMOVE && scratch)
6935 : : {
6936 : 1120 : ix86_expand_clear (scratch);
6937 : 1120 : emit_insn (gen_x86_shift_adj_1
6938 : : (half_mode, low[0], high[0], operands[2], scratch));
6939 : : }
6940 : : else
6941 : 271 : emit_insn (gen_x86_shift_adj_2
6942 : : (half_mode, low[0], high[0], operands[2]));
6943 : : }
6944 : 15098 : }
6945 : :
6946 : : /* Helper function to split TImode ashl under NDD. */
6947 : : void
6948 : 1 : ix86_split_ashl_ndd (rtx *operands, rtx scratch)
6949 : : {
6950 : 1 : gcc_assert (TARGET_APX_NDD);
6951 : 1 : int half_width = GET_MODE_BITSIZE (TImode) >> 1;
6952 : :
6953 : 1 : rtx low[2], high[2];
6954 : 1 : int count;
6955 : :
6956 : 1 : split_double_mode (TImode, operands, 2, low, high);
6957 : 1 : if (CONST_INT_P (operands[2]))
6958 : : {
6959 : 0 : count = INTVAL (operands[2]) & (GET_MODE_BITSIZE (TImode) - 1);
6960 : :
6961 : 0 : if (count >= half_width)
6962 : : {
6963 : 0 : count = count - half_width;
6964 : 0 : if (count == 0)
6965 : : {
6966 : 0 : if (!rtx_equal_p (high[0], low[1]))
6967 : 0 : emit_move_insn (high[0], low[1]);
6968 : : }
6969 : 0 : else if (count == 1)
6970 : 0 : emit_insn (gen_adddi3 (high[0], low[1], low[1]));
6971 : : else
6972 : 0 : emit_insn (gen_ashldi3 (high[0], low[1], GEN_INT (count)));
6973 : :
6974 : 0 : ix86_expand_clear (low[0]);
6975 : : }
6976 : 0 : else if (count == 1)
6977 : : {
6978 : 0 : rtx x3 = gen_rtx_REG (CCCmode, FLAGS_REG);
6979 : 0 : rtx x4 = gen_rtx_LTU (TImode, x3, const0_rtx);
6980 : 0 : emit_insn (gen_add3_cc_overflow_1 (DImode, low[0],
6981 : : low[1], low[1]));
6982 : 0 : emit_insn (gen_add3_carry (DImode, high[0], high[1], high[1],
6983 : : x3, x4));
6984 : : }
6985 : : else
6986 : : {
6987 : 0 : emit_insn (gen_x86_64_shld_ndd (high[0], high[1], low[1],
6988 : : GEN_INT (count)));
6989 : 0 : emit_insn (gen_ashldi3 (low[0], low[1], GEN_INT (count)));
6990 : : }
6991 : : }
6992 : : else
6993 : : {
6994 : 1 : emit_insn (gen_x86_64_shld_ndd (high[0], high[1], low[1],
6995 : : operands[2]));
6996 : 1 : emit_insn (gen_ashldi3 (low[0], low[1], operands[2]));
6997 : 1 : if (TARGET_CMOVE && scratch)
6998 : : {
6999 : 1 : ix86_expand_clear (scratch);
7000 : 1 : emit_insn (gen_x86_shift_adj_1
7001 : : (DImode, high[0], low[0], operands[2], scratch));
7002 : : }
7003 : : else
7004 : 0 : emit_insn (gen_x86_shift_adj_2 (DImode, high[0], low[0], operands[2]));
7005 : : }
7006 : 1 : }
7007 : :
7008 : : /* Helper function to split TImode l/ashr under NDD. */
7009 : : void
7010 : 2 : ix86_split_rshift_ndd (enum rtx_code code, rtx *operands, rtx scratch)
7011 : : {
7012 : 2 : gcc_assert (TARGET_APX_NDD);
7013 : 2 : int half_width = GET_MODE_BITSIZE (TImode) >> 1;
7014 : 2 : bool ashr_p = code == ASHIFTRT;
7015 : 2 : rtx (*gen_shr)(rtx, rtx, rtx) = ashr_p ? gen_ashrdi3
7016 : : : gen_lshrdi3;
7017 : :
7018 : 2 : rtx low[2], high[2];
7019 : 2 : int count;
7020 : :
7021 : 2 : split_double_mode (TImode, operands, 2, low, high);
7022 : 2 : if (CONST_INT_P (operands[2]))
7023 : : {
7024 : 0 : count = INTVAL (operands[2]) & (GET_MODE_BITSIZE (TImode) - 1);
7025 : :
7026 : 0 : if (ashr_p && (count == GET_MODE_BITSIZE (TImode) - 1))
7027 : : {
7028 : 0 : emit_insn (gen_shr (high[0], high[1],
7029 : : GEN_INT (half_width - 1)));
7030 : 0 : emit_move_insn (low[0], high[0]);
7031 : : }
7032 : 0 : else if (count >= half_width)
7033 : : {
7034 : 0 : if (ashr_p)
7035 : 0 : emit_insn (gen_shr (high[0], high[1],
7036 : : GEN_INT (half_width - 1)));
7037 : : else
7038 : 0 : ix86_expand_clear (high[0]);
7039 : :
7040 : 0 : if (count > half_width)
7041 : 0 : emit_insn (gen_shr (low[0], high[1],
7042 : 0 : GEN_INT (count - half_width)));
7043 : : else
7044 : 0 : emit_move_insn (low[0], high[1]);
7045 : : }
7046 : : else
7047 : : {
7048 : 0 : emit_insn (gen_x86_64_shrd_ndd (low[0], low[1], high[1],
7049 : : GEN_INT (count)));
7050 : 0 : emit_insn (gen_shr (high[0], high[1], GEN_INT (count)));
7051 : : }
7052 : : }
7053 : : else
7054 : : {
7055 : 2 : emit_insn (gen_x86_64_shrd_ndd (low[0], low[1], high[1],
7056 : : operands[2]));
7057 : 2 : emit_insn (gen_shr (high[0], high[1], operands[2]));
7058 : :
7059 : 2 : if (TARGET_CMOVE && scratch)
7060 : : {
7061 : 2 : if (ashr_p)
7062 : : {
7063 : 1 : emit_move_insn (scratch, high[0]);
7064 : 1 : emit_insn (gen_shr (scratch, scratch,
7065 : : GEN_INT (half_width - 1)));
7066 : : }
7067 : : else
7068 : 1 : ix86_expand_clear (scratch);
7069 : :
7070 : 2 : emit_insn (gen_x86_shift_adj_1
7071 : : (DImode, low[0], high[0], operands[2], scratch));
7072 : : }
7073 : 0 : else if (ashr_p)
7074 : 0 : emit_insn (gen_x86_shift_adj_3
7075 : : (DImode, low[0], high[0], operands[2]));
7076 : : else
7077 : 0 : emit_insn (gen_x86_shift_adj_2
7078 : : (DImode, low[0], high[0], operands[2]));
7079 : : }
7080 : 2 : }
7081 : :
7082 : : /* Expand move of V1TI mode register X to a new TI mode register. */
7083 : : static rtx
7084 : 17 : ix86_expand_v1ti_to_ti (rtx x)
7085 : : {
7086 : 17 : rtx result = gen_reg_rtx (TImode);
7087 : 17 : if (TARGET_SSE2)
7088 : : {
7089 : 17 : rtx temp = force_reg (V2DImode, gen_lowpart (V2DImode, x));
7090 : 17 : rtx lo = gen_lowpart (DImode, result);
7091 : 17 : emit_insn (gen_vec_extractv2didi (lo, temp, const0_rtx));
7092 : 17 : rtx hi = gen_highpart (DImode, result);
7093 : 17 : emit_insn (gen_vec_extractv2didi (hi, temp, const1_rtx));
7094 : : }
7095 : : else
7096 : 0 : emit_move_insn (result, gen_lowpart (TImode, x));
7097 : 17 : return result;
7098 : : }
7099 : :
7100 : : /* Expand move of TI mode register X to a new V1TI mode register. */
7101 : : static rtx
7102 : 17 : ix86_expand_ti_to_v1ti (rtx x)
7103 : : {
7104 : 17 : if (TARGET_SSE2)
7105 : : {
7106 : 17 : rtx lo = gen_lowpart (DImode, x);
7107 : 17 : rtx hi = gen_highpart (DImode, x);
7108 : 17 : rtx tmp = gen_reg_rtx (V2DImode);
7109 : 17 : emit_insn (gen_vec_concatv2di (tmp, lo, hi));
7110 : 17 : return force_reg (V1TImode, gen_lowpart (V1TImode, tmp));
7111 : : }
7112 : :
7113 : 0 : return force_reg (V1TImode, gen_lowpart (V1TImode, x));
7114 : : }
7115 : :
7116 : : /* Expand V1TI mode shift (of rtx_code CODE) by constant. */
7117 : : void
7118 : 42 : ix86_expand_v1ti_shift (enum rtx_code code, rtx operands[])
7119 : : {
7120 : 42 : rtx op1 = force_reg (V1TImode, operands[1]);
7121 : :
7122 : 42 : if (!CONST_INT_P (operands[2]))
7123 : : {
7124 : 6 : rtx tmp1 = ix86_expand_v1ti_to_ti (op1);
7125 : 6 : rtx tmp2 = gen_reg_rtx (TImode);
7126 : 3 : rtx (*shift) (rtx, rtx, rtx)
7127 : 6 : = (code == ASHIFT) ? gen_ashlti3 : gen_lshrti3;
7128 : 6 : emit_insn (shift (tmp2, tmp1, operands[2]));
7129 : 6 : rtx tmp3 = ix86_expand_ti_to_v1ti (tmp2);
7130 : 6 : emit_move_insn (operands[0], tmp3);
7131 : 6 : return;
7132 : : }
7133 : :
7134 : 36 : HOST_WIDE_INT bits = INTVAL (operands[2]) & 127;
7135 : :
7136 : 36 : if (bits == 0)
7137 : : {
7138 : 0 : emit_move_insn (operands[0], op1);
7139 : 0 : return;
7140 : : }
7141 : :
7142 : 36 : if ((bits & 7) == 0)
7143 : : {
7144 : 0 : rtx tmp = gen_reg_rtx (V1TImode);
7145 : 0 : if (code == ASHIFT)
7146 : 0 : emit_insn (gen_sse2_ashlv1ti3 (tmp, op1, GEN_INT (bits)));
7147 : : else
7148 : 0 : emit_insn (gen_sse2_lshrv1ti3 (tmp, op1, GEN_INT (bits)));
7149 : 0 : emit_move_insn (operands[0], tmp);
7150 : 0 : return;
7151 : : }
7152 : :
7153 : 36 : rtx tmp1 = gen_reg_rtx (V1TImode);
7154 : 36 : if (code == ASHIFT)
7155 : 18 : emit_insn (gen_sse2_ashlv1ti3 (tmp1, op1, GEN_INT (64)));
7156 : : else
7157 : 18 : emit_insn (gen_sse2_lshrv1ti3 (tmp1, op1, GEN_INT (64)));
7158 : :
7159 : : /* tmp2 is operands[1] shifted by 64, in V2DImode. */
7160 : 36 : rtx tmp2 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp1));
7161 : :
7162 : : /* tmp3 will be the V2DImode result. */
7163 : 36 : rtx tmp3 = gen_reg_rtx (V2DImode);
7164 : :
7165 : 36 : if (bits > 64)
7166 : : {
7167 : 18 : if (code == ASHIFT)
7168 : 9 : emit_insn (gen_ashlv2di3 (tmp3, tmp2, GEN_INT (bits - 64)));
7169 : : else
7170 : 9 : emit_insn (gen_lshrv2di3 (tmp3, tmp2, GEN_INT (bits - 64)));
7171 : : }
7172 : : else
7173 : : {
7174 : : /* tmp4 is operands[1], in V2DImode. */
7175 : 18 : rtx tmp4 = force_reg (V2DImode, gen_lowpart (V2DImode, op1));
7176 : :
7177 : 18 : rtx tmp5 = gen_reg_rtx (V2DImode);
7178 : 18 : if (code == ASHIFT)
7179 : 9 : emit_insn (gen_ashlv2di3 (tmp5, tmp4, GEN_INT (bits)));
7180 : : else
7181 : 9 : emit_insn (gen_lshrv2di3 (tmp5, tmp4, GEN_INT (bits)));
7182 : :
7183 : 18 : rtx tmp6 = gen_reg_rtx (V2DImode);
7184 : 18 : if (code == ASHIFT)
7185 : 9 : emit_insn (gen_lshrv2di3 (tmp6, tmp2, GEN_INT (64 - bits)));
7186 : : else
7187 : 9 : emit_insn (gen_ashlv2di3 (tmp6, tmp2, GEN_INT (64 - bits)));
7188 : :
7189 : 18 : emit_insn (gen_iorv2di3 (tmp3, tmp5, tmp6));
7190 : : }
7191 : :
7192 : : /* Convert the result back to V1TImode and store in operands[0]. */
7193 : 36 : rtx tmp7 = force_reg (V1TImode, gen_lowpart (V1TImode, tmp3));
7194 : 36 : emit_move_insn (operands[0], tmp7);
7195 : : }
7196 : :
7197 : : /* Expand V1TI mode rotate (of rtx_code CODE) by constant. */
7198 : : void
7199 : 39 : ix86_expand_v1ti_rotate (enum rtx_code code, rtx operands[])
7200 : : {
7201 : 39 : rtx op1 = force_reg (V1TImode, operands[1]);
7202 : :
7203 : 39 : if (!CONST_INT_P (operands[2]))
7204 : : {
7205 : 8 : rtx tmp1 = ix86_expand_v1ti_to_ti (op1);
7206 : 8 : rtx tmp2 = gen_reg_rtx (TImode);
7207 : 4 : rtx (*rotate) (rtx, rtx, rtx)
7208 : 8 : = (code == ROTATE) ? gen_rotlti3 : gen_rotrti3;
7209 : 8 : emit_insn (rotate (tmp2, tmp1, operands[2]));
7210 : 8 : rtx tmp3 = ix86_expand_ti_to_v1ti (tmp2);
7211 : 8 : emit_move_insn (operands[0], tmp3);
7212 : 8 : return;
7213 : : }
7214 : :
7215 : 31 : HOST_WIDE_INT bits = INTVAL (operands[2]) & 127;
7216 : :
7217 : 31 : if (bits == 0)
7218 : : {
7219 : 0 : emit_move_insn (operands[0], op1);
7220 : 0 : return;
7221 : : }
7222 : :
7223 : 31 : if (code == ROTATERT)
7224 : 16 : bits = 128 - bits;
7225 : :
7226 : 31 : if ((bits & 31) == 0)
7227 : : {
7228 : 5 : rtx tmp2 = gen_reg_rtx (V4SImode);
7229 : 5 : rtx tmp1 = force_reg (V4SImode, gen_lowpart (V4SImode, op1));
7230 : 5 : if (bits == 32)
7231 : 1 : emit_insn (gen_sse2_pshufd (tmp2, tmp1, GEN_INT (0x93)));
7232 : 4 : else if (bits == 64)
7233 : 2 : emit_insn (gen_sse2_pshufd (tmp2, tmp1, GEN_INT (0x4e)));
7234 : : else
7235 : 2 : emit_insn (gen_sse2_pshufd (tmp2, tmp1, GEN_INT (0x39)));
7236 : 5 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp2));
7237 : 5 : return;
7238 : : }
7239 : :
7240 : 26 : if ((bits & 7) == 0)
7241 : : {
7242 : 6 : rtx tmp1 = gen_reg_rtx (V1TImode);
7243 : 6 : rtx tmp2 = gen_reg_rtx (V1TImode);
7244 : 6 : rtx tmp3 = gen_reg_rtx (V1TImode);
7245 : :
7246 : 6 : emit_insn (gen_sse2_ashlv1ti3 (tmp1, op1, GEN_INT (bits)));
7247 : 6 : emit_insn (gen_sse2_lshrv1ti3 (tmp2, op1, GEN_INT (128 - bits)));
7248 : 6 : emit_insn (gen_iorv1ti3 (tmp3, tmp1, tmp2));
7249 : 6 : emit_move_insn (operands[0], tmp3);
7250 : 6 : return;
7251 : : }
7252 : :
7253 : 20 : rtx op1_v4si = force_reg (V4SImode, gen_lowpart (V4SImode, op1));
7254 : :
7255 : 20 : rtx lobits;
7256 : 20 : rtx hibits;
7257 : :
7258 : 20 : switch (bits >> 5)
7259 : : {
7260 : 7 : case 0:
7261 : 7 : lobits = op1_v4si;
7262 : 7 : hibits = gen_reg_rtx (V4SImode);
7263 : 7 : emit_insn (gen_sse2_pshufd (hibits, op1_v4si, GEN_INT (0x93)));
7264 : 7 : break;
7265 : :
7266 : 2 : case 1:
7267 : 2 : lobits = gen_reg_rtx (V4SImode);
7268 : 2 : hibits = gen_reg_rtx (V4SImode);
7269 : 2 : emit_insn (gen_sse2_pshufd (lobits, op1_v4si, GEN_INT (0x93)));
7270 : 2 : emit_insn (gen_sse2_pshufd (hibits, op1_v4si, GEN_INT (0x4e)));
7271 : 2 : break;
7272 : :
7273 : 2 : case 2:
7274 : 2 : lobits = gen_reg_rtx (V4SImode);
7275 : 2 : hibits = gen_reg_rtx (V4SImode);
7276 : 2 : emit_insn (gen_sse2_pshufd (lobits, op1_v4si, GEN_INT (0x4e)));
7277 : 2 : emit_insn (gen_sse2_pshufd (hibits, op1_v4si, GEN_INT (0x39)));
7278 : 2 : break;
7279 : :
7280 : 9 : default:
7281 : 9 : lobits = gen_reg_rtx (V4SImode);
7282 : 9 : emit_insn (gen_sse2_pshufd (lobits, op1_v4si, GEN_INT (0x39)));
7283 : 9 : hibits = op1_v4si;
7284 : 9 : break;
7285 : : }
7286 : :
7287 : 20 : rtx tmp1 = gen_reg_rtx (V4SImode);
7288 : 20 : rtx tmp2 = gen_reg_rtx (V4SImode);
7289 : 20 : rtx tmp3 = gen_reg_rtx (V4SImode);
7290 : :
7291 : 20 : emit_insn (gen_ashlv4si3 (tmp1, lobits, GEN_INT (bits & 31)));
7292 : 20 : emit_insn (gen_lshrv4si3 (tmp2, hibits, GEN_INT (32 - (bits & 31))));
7293 : 20 : emit_insn (gen_iorv4si3 (tmp3, tmp1, tmp2));
7294 : :
7295 : 20 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp3));
7296 : : }
7297 : :
7298 : : /* Expand V1TI mode ashiftrt by constant. */
7299 : : void
7300 : 109 : ix86_expand_v1ti_ashiftrt (rtx operands[])
7301 : : {
7302 : 109 : rtx op1 = force_reg (V1TImode, operands[1]);
7303 : :
7304 : 109 : if (!CONST_INT_P (operands[2]))
7305 : : {
7306 : 3 : rtx tmp1 = ix86_expand_v1ti_to_ti (op1);
7307 : 3 : rtx tmp2 = gen_reg_rtx (TImode);
7308 : 3 : emit_insn (gen_ashrti3 (tmp2, tmp1, operands[2]));
7309 : 3 : rtx tmp3 = ix86_expand_ti_to_v1ti (tmp2);
7310 : 3 : emit_move_insn (operands[0], tmp3);
7311 : 3 : return;
7312 : : }
7313 : :
7314 : 106 : HOST_WIDE_INT bits = INTVAL (operands[2]) & 127;
7315 : :
7316 : 106 : if (bits == 0)
7317 : : {
7318 : 0 : emit_move_insn (operands[0], op1);
7319 : 0 : return;
7320 : : }
7321 : :
7322 : 106 : if (bits == 127)
7323 : : {
7324 : : /* Two operations. */
7325 : 3 : rtx tmp1 = force_reg(V4SImode, gen_lowpart (V4SImode, op1));
7326 : 3 : rtx tmp2 = gen_reg_rtx (V4SImode);
7327 : 3 : emit_insn (gen_sse2_pshufd (tmp2, tmp1, GEN_INT (0xff)));
7328 : :
7329 : 3 : rtx tmp3 = gen_reg_rtx (V4SImode);
7330 : 3 : emit_insn (gen_ashrv4si3 (tmp3, tmp2, GEN_INT (31)));
7331 : :
7332 : 3 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp3));
7333 : 3 : return;
7334 : : }
7335 : :
7336 : 103 : if (bits == 64)
7337 : : {
7338 : : /* Three operations. */
7339 : 3 : rtx tmp1 = force_reg(V4SImode, gen_lowpart (V4SImode, op1));
7340 : 3 : rtx tmp2 = gen_reg_rtx (V4SImode);
7341 : 3 : emit_insn (gen_sse2_pshufd (tmp2, tmp1, GEN_INT (0xff)));
7342 : :
7343 : 3 : rtx tmp3 = gen_reg_rtx (V4SImode);
7344 : 3 : emit_insn (gen_ashrv4si3 (tmp3, tmp2, GEN_INT (31)));
7345 : :
7346 : 3 : rtx tmp4 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp1));
7347 : 3 : rtx tmp5 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp3));
7348 : 3 : rtx tmp6 = gen_reg_rtx (V2DImode);
7349 : 3 : emit_insn (gen_vec_interleave_highv2di (tmp6, tmp4, tmp5));
7350 : :
7351 : 3 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp6));
7352 : 3 : return;
7353 : : }
7354 : :
7355 : 100 : if (bits == 96)
7356 : : {
7357 : : /* Three operations. */
7358 : 3 : rtx tmp1 = force_reg(V4SImode, gen_lowpart (V4SImode, op1));
7359 : 3 : rtx tmp2 = gen_reg_rtx (V4SImode);
7360 : 3 : emit_insn (gen_ashrv4si3 (tmp2, tmp1, GEN_INT (31)));
7361 : :
7362 : 3 : rtx tmp3 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp1));
7363 : 3 : rtx tmp4 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp2));
7364 : 3 : rtx tmp5 = gen_reg_rtx (V2DImode);
7365 : 3 : emit_insn (gen_vec_interleave_highv2di (tmp5, tmp3, tmp4));
7366 : :
7367 : 3 : rtx tmp6 = force_reg(V4SImode, gen_lowpart (V4SImode, tmp5));
7368 : 3 : rtx tmp7 = gen_reg_rtx (V4SImode);
7369 : 3 : emit_insn (gen_sse2_pshufd (tmp7, tmp6, GEN_INT (0xfd)));
7370 : :
7371 : 3 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp7));
7372 : 3 : return;
7373 : : }
7374 : :
7375 : 97 : if (bits >= 111)
7376 : : {
7377 : : /* Three operations. */
7378 : 21 : rtx tmp1 = force_reg (V4SImode, gen_lowpart (V4SImode, op1));
7379 : 21 : rtx tmp2 = gen_reg_rtx (V4SImode);
7380 : 21 : emit_insn (gen_ashrv4si3 (tmp2, tmp1, GEN_INT (bits - 96)));
7381 : :
7382 : 21 : rtx tmp3 = force_reg (V8HImode, gen_lowpart (V8HImode, tmp2));
7383 : 21 : rtx tmp4 = gen_reg_rtx (V8HImode);
7384 : 21 : emit_insn (gen_sse2_pshufhw (tmp4, tmp3, GEN_INT (0xfe)));
7385 : :
7386 : 21 : rtx tmp5 = force_reg (V4SImode, gen_lowpart (V4SImode, tmp4));
7387 : 21 : rtx tmp6 = gen_reg_rtx (V4SImode);
7388 : 21 : emit_insn (gen_sse2_pshufd (tmp6, tmp5, GEN_INT (0xfe)));
7389 : :
7390 : 21 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp6));
7391 : 21 : return;
7392 : : }
7393 : :
7394 : 76 : if (TARGET_AVX2 || TARGET_SSE4_1)
7395 : : {
7396 : : /* Three operations. */
7397 : 50 : if (bits == 32)
7398 : : {
7399 : 2 : rtx tmp1 = force_reg (V4SImode, gen_lowpart (V4SImode, op1));
7400 : 2 : rtx tmp2 = gen_reg_rtx (V4SImode);
7401 : 2 : emit_insn (gen_ashrv4si3 (tmp2, tmp1, GEN_INT (31)));
7402 : :
7403 : 2 : rtx tmp3 = gen_reg_rtx (V1TImode);
7404 : 2 : emit_insn (gen_sse2_lshrv1ti3 (tmp3, op1, GEN_INT (32)));
7405 : :
7406 : 2 : if (TARGET_AVX2)
7407 : : {
7408 : 1 : rtx tmp4 = force_reg (V4SImode, gen_lowpart (V4SImode, tmp3));
7409 : 1 : rtx tmp5 = gen_reg_rtx (V4SImode);
7410 : 1 : emit_insn (gen_avx2_pblenddv4si (tmp5, tmp2, tmp4,
7411 : : GEN_INT (7)));
7412 : :
7413 : 1 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp5));
7414 : : }
7415 : : else
7416 : : {
7417 : 1 : rtx tmp4 = force_reg (V8HImode, gen_lowpart (V8HImode, tmp2));
7418 : 1 : rtx tmp5 = force_reg (V8HImode, gen_lowpart (V8HImode, tmp3));
7419 : 1 : rtx tmp6 = gen_reg_rtx (V8HImode);
7420 : 1 : emit_insn (gen_sse4_1_pblendw (tmp6, tmp4, tmp5,
7421 : : GEN_INT (0x3f)));
7422 : :
7423 : 1 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp6));
7424 : : }
7425 : 2 : return;
7426 : : }
7427 : :
7428 : : /* Three operations. */
7429 : 48 : if (bits == 8 || bits == 16 || bits == 24)
7430 : : {
7431 : 6 : rtx tmp1 = force_reg (V4SImode, gen_lowpart (V4SImode, op1));
7432 : 6 : rtx tmp2 = gen_reg_rtx (V4SImode);
7433 : 6 : emit_insn (gen_ashrv4si3 (tmp2, tmp1, GEN_INT (bits)));
7434 : :
7435 : 6 : rtx tmp3 = gen_reg_rtx (V1TImode);
7436 : 6 : emit_insn (gen_sse2_lshrv1ti3 (tmp3, op1, GEN_INT (bits)));
7437 : :
7438 : 6 : if (TARGET_AVX2)
7439 : : {
7440 : 3 : rtx tmp4 = force_reg (V4SImode, gen_lowpart (V4SImode, tmp3));
7441 : 3 : rtx tmp5 = gen_reg_rtx (V4SImode);
7442 : 3 : emit_insn (gen_avx2_pblenddv4si (tmp5, tmp2, tmp4,
7443 : : GEN_INT (7)));
7444 : :
7445 : 3 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp5));
7446 : : }
7447 : : else
7448 : : {
7449 : 3 : rtx tmp4 = force_reg (V8HImode, gen_lowpart (V8HImode, tmp2));
7450 : 3 : rtx tmp5 = force_reg (V8HImode, gen_lowpart (V8HImode, tmp3));
7451 : 3 : rtx tmp6 = gen_reg_rtx (V8HImode);
7452 : 3 : emit_insn (gen_sse4_1_pblendw (tmp6, tmp4, tmp5,
7453 : : GEN_INT (0x3f)));
7454 : :
7455 : 3 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp6));
7456 : : }
7457 : 6 : return;
7458 : : }
7459 : : }
7460 : :
7461 : 68 : if (bits > 96)
7462 : : {
7463 : : /* Four operations. */
7464 : 3 : rtx tmp1 = force_reg (V4SImode, gen_lowpart (V4SImode, op1));
7465 : 3 : rtx tmp2 = gen_reg_rtx (V4SImode);
7466 : 3 : emit_insn (gen_ashrv4si3 (tmp2, tmp1, GEN_INT (bits - 96)));
7467 : :
7468 : 3 : rtx tmp3 = gen_reg_rtx (V4SImode);
7469 : 3 : emit_insn (gen_ashrv4si3 (tmp3, tmp1, GEN_INT (31)));
7470 : :
7471 : 3 : rtx tmp4 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp2));
7472 : 3 : rtx tmp5 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp3));
7473 : 3 : rtx tmp6 = gen_reg_rtx (V2DImode);
7474 : 3 : emit_insn (gen_vec_interleave_highv2di (tmp6, tmp4, tmp5));
7475 : :
7476 : 3 : rtx tmp7 = force_reg (V4SImode, gen_lowpart (V4SImode, tmp6));
7477 : 3 : rtx tmp8 = gen_reg_rtx (V4SImode);
7478 : 3 : emit_insn (gen_sse2_pshufd (tmp8, tmp7, GEN_INT (0xfd)));
7479 : :
7480 : 3 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp8));
7481 : 3 : return;
7482 : : }
7483 : :
7484 : 65 : if (TARGET_SSE4_1 && (bits == 48 || bits == 80))
7485 : : {
7486 : : /* Four operations. */
7487 : 4 : rtx tmp1 = force_reg (V4SImode, gen_lowpart (V4SImode, op1));
7488 : 4 : rtx tmp2 = gen_reg_rtx (V4SImode);
7489 : 4 : emit_insn (gen_sse2_pshufd (tmp2, tmp1, GEN_INT (0xff)));
7490 : :
7491 : 4 : rtx tmp3 = gen_reg_rtx (V4SImode);
7492 : 4 : emit_insn (gen_ashrv4si3 (tmp3, tmp2, GEN_INT (31)));
7493 : :
7494 : 4 : rtx tmp4 = gen_reg_rtx (V1TImode);
7495 : 4 : emit_insn (gen_sse2_lshrv1ti3 (tmp4, op1, GEN_INT (bits)));
7496 : :
7497 : 4 : rtx tmp5 = force_reg (V8HImode, gen_lowpart (V8HImode, tmp3));
7498 : 4 : rtx tmp6 = force_reg (V8HImode, gen_lowpart (V8HImode, tmp4));
7499 : 4 : rtx tmp7 = gen_reg_rtx (V8HImode);
7500 : 6 : emit_insn (gen_sse4_1_pblendw (tmp7, tmp5, tmp6,
7501 : : GEN_INT (bits == 48 ? 0x1f : 0x07)));
7502 : :
7503 : 4 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp7));
7504 : 4 : return;
7505 : : }
7506 : :
7507 : 61 : if ((bits & 7) == 0)
7508 : : {
7509 : : /* Five operations. */
7510 : 9 : rtx tmp1 = force_reg (V4SImode, gen_lowpart (V4SImode, op1));
7511 : 9 : rtx tmp2 = gen_reg_rtx (V4SImode);
7512 : 9 : emit_insn (gen_sse2_pshufd (tmp2, tmp1, GEN_INT (0xff)));
7513 : :
7514 : 9 : rtx tmp3 = gen_reg_rtx (V4SImode);
7515 : 9 : emit_insn (gen_ashrv4si3 (tmp3, tmp2, GEN_INT (31)));
7516 : :
7517 : 9 : rtx tmp4 = gen_reg_rtx (V1TImode);
7518 : 9 : emit_insn (gen_sse2_lshrv1ti3 (tmp4, op1, GEN_INT (bits)));
7519 : :
7520 : 9 : rtx tmp5 = force_reg (V1TImode, gen_lowpart (V1TImode, tmp3));
7521 : 9 : rtx tmp6 = gen_reg_rtx (V1TImode);
7522 : 9 : emit_insn (gen_sse2_ashlv1ti3 (tmp6, tmp5, GEN_INT (128 - bits)));
7523 : :
7524 : 9 : rtx tmp7 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp4));
7525 : 9 : rtx tmp8 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp6));
7526 : 9 : rtx tmp9 = gen_reg_rtx (V2DImode);
7527 : 9 : emit_insn (gen_iorv2di3 (tmp9, tmp7, tmp8));
7528 : :
7529 : 9 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp9));
7530 : 9 : return;
7531 : : }
7532 : :
7533 : 52 : if (TARGET_AVX2 && bits < 32)
7534 : : {
7535 : : /* Six operations. */
7536 : 9 : rtx tmp1 = force_reg (V4SImode, gen_lowpart (V4SImode, op1));
7537 : 9 : rtx tmp2 = gen_reg_rtx (V4SImode);
7538 : 9 : emit_insn (gen_ashrv4si3 (tmp2, tmp1, GEN_INT (bits)));
7539 : :
7540 : 9 : rtx tmp3 = gen_reg_rtx (V1TImode);
7541 : 9 : emit_insn (gen_sse2_lshrv1ti3 (tmp3, op1, GEN_INT (64)));
7542 : :
7543 : 9 : rtx tmp4 = force_reg (V2DImode, gen_lowpart (V2DImode, op1));
7544 : 9 : rtx tmp5 = gen_reg_rtx (V2DImode);
7545 : 9 : emit_insn (gen_lshrv2di3 (tmp5, tmp4, GEN_INT (bits)));
7546 : :
7547 : 9 : rtx tmp6 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp3));
7548 : 9 : rtx tmp7 = gen_reg_rtx (V2DImode);
7549 : 9 : emit_insn (gen_ashlv2di3 (tmp7, tmp6, GEN_INT (64 - bits)));
7550 : :
7551 : 9 : rtx tmp8 = gen_reg_rtx (V2DImode);
7552 : 9 : emit_insn (gen_iorv2di3 (tmp8, tmp5, tmp7));
7553 : :
7554 : 9 : rtx tmp9 = force_reg (V4SImode, gen_lowpart (V4SImode, tmp8));
7555 : 9 : rtx tmp10 = gen_reg_rtx (V4SImode);
7556 : 9 : emit_insn (gen_avx2_pblenddv4si (tmp10, tmp2, tmp9, GEN_INT (7)));
7557 : :
7558 : 9 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp10));
7559 : 9 : return;
7560 : : }
7561 : :
7562 : 43 : if (TARGET_SSE4_1 && bits < 15)
7563 : : {
7564 : : /* Six operations. */
7565 : 4 : rtx tmp1 = force_reg (V4SImode, gen_lowpart (V4SImode, op1));
7566 : 4 : rtx tmp2 = gen_reg_rtx (V4SImode);
7567 : 4 : emit_insn (gen_ashrv4si3 (tmp2, tmp1, GEN_INT (bits)));
7568 : :
7569 : 4 : rtx tmp3 = gen_reg_rtx (V1TImode);
7570 : 4 : emit_insn (gen_sse2_lshrv1ti3 (tmp3, op1, GEN_INT (64)));
7571 : :
7572 : 4 : rtx tmp4 = force_reg (V2DImode, gen_lowpart (V2DImode, op1));
7573 : 4 : rtx tmp5 = gen_reg_rtx (V2DImode);
7574 : 4 : emit_insn (gen_lshrv2di3 (tmp5, tmp4, GEN_INT (bits)));
7575 : :
7576 : 4 : rtx tmp6 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp3));
7577 : 4 : rtx tmp7 = gen_reg_rtx (V2DImode);
7578 : 4 : emit_insn (gen_ashlv2di3 (tmp7, tmp6, GEN_INT (64 - bits)));
7579 : :
7580 : 4 : rtx tmp8 = gen_reg_rtx (V2DImode);
7581 : 4 : emit_insn (gen_iorv2di3 (tmp8, tmp5, tmp7));
7582 : :
7583 : 4 : rtx tmp9 = force_reg (V8HImode, gen_lowpart (V8HImode, tmp2));
7584 : 4 : rtx tmp10 = force_reg (V8HImode, gen_lowpart (V8HImode, tmp8));
7585 : 4 : rtx tmp11 = gen_reg_rtx (V8HImode);
7586 : 4 : emit_insn (gen_sse4_1_pblendw (tmp11, tmp9, tmp10, GEN_INT (0x3f)));
7587 : :
7588 : 4 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp11));
7589 : 4 : return;
7590 : : }
7591 : :
7592 : 18 : if (bits == 1)
7593 : : {
7594 : : /* Eight operations. */
7595 : 1 : rtx tmp1 = gen_reg_rtx (V1TImode);
7596 : 1 : emit_insn (gen_sse2_lshrv1ti3 (tmp1, op1, GEN_INT (64)));
7597 : :
7598 : 1 : rtx tmp2 = force_reg (V2DImode, gen_lowpart (V2DImode, op1));
7599 : 1 : rtx tmp3 = gen_reg_rtx (V2DImode);
7600 : 1 : emit_insn (gen_lshrv2di3 (tmp3, tmp2, GEN_INT (1)));
7601 : :
7602 : 1 : rtx tmp4 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp1));
7603 : 1 : rtx tmp5 = gen_reg_rtx (V2DImode);
7604 : 1 : emit_insn (gen_ashlv2di3 (tmp5, tmp4, GEN_INT (63)));
7605 : :
7606 : 1 : rtx tmp6 = gen_reg_rtx (V2DImode);
7607 : 1 : emit_insn (gen_iorv2di3 (tmp6, tmp3, tmp5));
7608 : :
7609 : 1 : rtx tmp7 = gen_reg_rtx (V2DImode);
7610 : 1 : emit_insn (gen_lshrv2di3 (tmp7, tmp2, GEN_INT (63)));
7611 : :
7612 : 1 : rtx tmp8 = force_reg (V4SImode, gen_lowpart (V4SImode, tmp7));
7613 : 1 : rtx tmp9 = gen_reg_rtx (V4SImode);
7614 : 1 : emit_insn (gen_sse2_pshufd (tmp9, tmp8, GEN_INT (0xbf)));
7615 : :
7616 : 1 : rtx tmp10 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp9));
7617 : 1 : rtx tmp11 = gen_reg_rtx (V2DImode);
7618 : 1 : emit_insn (gen_ashlv2di3 (tmp11, tmp10, GEN_INT (31)));
7619 : :
7620 : 1 : rtx tmp12 = gen_reg_rtx (V2DImode);
7621 : 1 : emit_insn (gen_iorv2di3 (tmp12, tmp6, tmp11));
7622 : :
7623 : 1 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp12));
7624 : 1 : return;
7625 : : }
7626 : :
7627 : 38 : if (bits > 64)
7628 : : {
7629 : : /* Eight operations. */
7630 : 12 : rtx tmp1 = force_reg (V4SImode, gen_lowpart (V4SImode, op1));
7631 : 12 : rtx tmp2 = gen_reg_rtx (V4SImode);
7632 : 12 : emit_insn (gen_sse2_pshufd (tmp2, tmp1, GEN_INT (0xff)));
7633 : :
7634 : 12 : rtx tmp3 = gen_reg_rtx (V4SImode);
7635 : 12 : emit_insn (gen_ashrv4si3 (tmp3, tmp2, GEN_INT (31)));
7636 : :
7637 : 12 : rtx tmp4 = gen_reg_rtx (V1TImode);
7638 : 12 : emit_insn (gen_sse2_lshrv1ti3 (tmp4, op1, GEN_INT (64)));
7639 : :
7640 : 12 : rtx tmp5 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp4));
7641 : 12 : rtx tmp6 = gen_reg_rtx (V2DImode);
7642 : 12 : emit_insn (gen_lshrv2di3 (tmp6, tmp5, GEN_INT (bits - 64)));
7643 : :
7644 : 12 : rtx tmp7 = force_reg (V1TImode, gen_lowpart (V1TImode, tmp3));
7645 : 12 : rtx tmp8 = gen_reg_rtx (V1TImode);
7646 : 12 : emit_insn (gen_sse2_ashlv1ti3 (tmp8, tmp7, GEN_INT (64)));
7647 : :
7648 : 12 : rtx tmp9 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp3));
7649 : 12 : rtx tmp10 = gen_reg_rtx (V2DImode);
7650 : 12 : emit_insn (gen_ashlv2di3 (tmp10, tmp9, GEN_INT (128 - bits)));
7651 : :
7652 : 12 : rtx tmp11 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp8));
7653 : 12 : rtx tmp12 = gen_reg_rtx (V2DImode);
7654 : 12 : emit_insn (gen_iorv2di3 (tmp12, tmp10, tmp11));
7655 : :
7656 : 12 : rtx tmp13 = gen_reg_rtx (V2DImode);
7657 : 12 : emit_insn (gen_iorv2di3 (tmp13, tmp6, tmp12));
7658 : :
7659 : 12 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp13));
7660 : : }
7661 : : else
7662 : : {
7663 : : /* Nine operations. */
7664 : 26 : rtx tmp1 = force_reg (V4SImode, gen_lowpart (V4SImode, op1));
7665 : 26 : rtx tmp2 = gen_reg_rtx (V4SImode);
7666 : 26 : emit_insn (gen_sse2_pshufd (tmp2, tmp1, GEN_INT (0xff)));
7667 : :
7668 : 26 : rtx tmp3 = gen_reg_rtx (V4SImode);
7669 : 26 : emit_insn (gen_ashrv4si3 (tmp3, tmp2, GEN_INT (31)));
7670 : :
7671 : 26 : rtx tmp4 = gen_reg_rtx (V1TImode);
7672 : 26 : emit_insn (gen_sse2_lshrv1ti3 (tmp4, op1, GEN_INT (64)));
7673 : :
7674 : 26 : rtx tmp5 = force_reg (V2DImode, gen_lowpart (V2DImode, op1));
7675 : 26 : rtx tmp6 = gen_reg_rtx (V2DImode);
7676 : 26 : emit_insn (gen_lshrv2di3 (tmp6, tmp5, GEN_INT (bits)));
7677 : :
7678 : 26 : rtx tmp7 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp4));
7679 : 26 : rtx tmp8 = gen_reg_rtx (V2DImode);
7680 : 26 : emit_insn (gen_ashlv2di3 (tmp8, tmp7, GEN_INT (64 - bits)));
7681 : :
7682 : 26 : rtx tmp9 = gen_reg_rtx (V2DImode);
7683 : 26 : emit_insn (gen_iorv2di3 (tmp9, tmp6, tmp8));
7684 : :
7685 : 26 : rtx tmp10 = force_reg (V1TImode, gen_lowpart (V1TImode, tmp3));
7686 : 26 : rtx tmp11 = gen_reg_rtx (V1TImode);
7687 : 26 : emit_insn (gen_sse2_ashlv1ti3 (tmp11, tmp10, GEN_INT (64)));
7688 : :
7689 : 26 : rtx tmp12 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp11));
7690 : 26 : rtx tmp13 = gen_reg_rtx (V2DImode);
7691 : 26 : emit_insn (gen_ashlv2di3 (tmp13, tmp12, GEN_INT (64 - bits)));
7692 : :
7693 : 26 : rtx tmp14 = gen_reg_rtx (V2DImode);
7694 : 26 : emit_insn (gen_iorv2di3 (tmp14, tmp9, tmp13));
7695 : :
7696 : 26 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp14));
7697 : : }
7698 : : }
7699 : :
7700 : : /* Expand V2DI mode ashiftrt. */
7701 : : void
7702 : 362 : ix86_expand_v2di_ashiftrt (rtx operands[])
7703 : : {
7704 : 362 : if (operands[2] == const0_rtx)
7705 : : {
7706 : 0 : emit_move_insn (operands[0], operands[1]);
7707 : 0 : return;
7708 : : }
7709 : :
7710 : 362 : if (TARGET_SSE4_2
7711 : 133 : && CONST_INT_P (operands[2])
7712 : 133 : && UINTVAL (operands[2]) >= 63
7713 : 370 : && !optimize_insn_for_size_p ())
7714 : : {
7715 : 8 : rtx zero = force_reg (V2DImode, CONST0_RTX (V2DImode));
7716 : 8 : emit_insn (gen_sse4_2_gtv2di3 (operands[0], zero, operands[1]));
7717 : 8 : return;
7718 : : }
7719 : :
7720 : 354 : if (CONST_INT_P (operands[2])
7721 : 346 : && (!TARGET_XOP || UINTVAL (operands[2]) >= 63))
7722 : : {
7723 : 250 : vec_perm_builder sel (4, 4, 1);
7724 : 250 : sel.quick_grow (4);
7725 : 250 : rtx arg0, arg1;
7726 : 250 : rtx op1 = lowpart_subreg (V4SImode,
7727 : : force_reg (V2DImode, operands[1]),
7728 : : V2DImode);
7729 : 250 : rtx target = gen_reg_rtx (V4SImode);
7730 : 250 : if (UINTVAL (operands[2]) >= 63)
7731 : : {
7732 : 84 : arg0 = arg1 = gen_reg_rtx (V4SImode);
7733 : 84 : emit_insn (gen_ashrv4si3 (arg0, op1, GEN_INT (31)));
7734 : 84 : sel[0] = 1;
7735 : 84 : sel[1] = 1;
7736 : 84 : sel[2] = 3;
7737 : 84 : sel[3] = 3;
7738 : : }
7739 : 166 : else if (INTVAL (operands[2]) > 32)
7740 : : {
7741 : 15 : arg0 = gen_reg_rtx (V4SImode);
7742 : 15 : arg1 = gen_reg_rtx (V4SImode);
7743 : 15 : emit_insn (gen_ashrv4si3 (arg1, op1, GEN_INT (31)));
7744 : 15 : emit_insn (gen_ashrv4si3 (arg0, op1,
7745 : 15 : GEN_INT (INTVAL (operands[2]) - 32)));
7746 : 15 : sel[0] = 1;
7747 : 15 : sel[1] = 5;
7748 : 15 : sel[2] = 3;
7749 : 15 : sel[3] = 7;
7750 : : }
7751 : 151 : else if (INTVAL (operands[2]) == 32)
7752 : : {
7753 : 3 : arg0 = op1;
7754 : 3 : arg1 = gen_reg_rtx (V4SImode);
7755 : 3 : emit_insn (gen_ashrv4si3 (arg1, op1, GEN_INT (31)));
7756 : 3 : sel[0] = 1;
7757 : 3 : sel[1] = 5;
7758 : 3 : sel[2] = 3;
7759 : 3 : sel[3] = 7;
7760 : : }
7761 : : else
7762 : : {
7763 : 148 : arg0 = gen_reg_rtx (V2DImode);
7764 : 148 : arg1 = gen_reg_rtx (V4SImode);
7765 : 148 : emit_insn (gen_lshrv2di3 (arg0, operands[1], operands[2]));
7766 : 148 : emit_insn (gen_ashrv4si3 (arg1, op1, operands[2]));
7767 : 148 : arg0 = lowpart_subreg (V4SImode, arg0, V2DImode);
7768 : 148 : sel[0] = 0;
7769 : 148 : sel[1] = 5;
7770 : 148 : sel[2] = 2;
7771 : 148 : sel[3] = 7;
7772 : : }
7773 : 334 : vec_perm_indices indices (sel, arg0 != arg1 ? 2 : 1, 4);
7774 : 250 : rtx op0 = operands[0];
7775 : 250 : bool ok = targetm.vectorize.vec_perm_const (V4SImode, V4SImode,
7776 : : target, arg0, arg1,
7777 : : indices);
7778 : 250 : gcc_assert (ok);
7779 : 250 : emit_move_insn (op0, lowpart_subreg (V2DImode, target, V4SImode));
7780 : 250 : return;
7781 : 250 : }
7782 : 104 : if (!TARGET_XOP)
7783 : : {
7784 : 8 : rtx zero = force_reg (V2DImode, CONST0_RTX (V2DImode));
7785 : 8 : rtx zero_or_all_ones;
7786 : 8 : if (TARGET_SSE4_2)
7787 : : {
7788 : 0 : zero_or_all_ones = gen_reg_rtx (V2DImode);
7789 : 0 : emit_insn (gen_sse4_2_gtv2di3 (zero_or_all_ones, zero,
7790 : : operands[1]));
7791 : : }
7792 : : else
7793 : : {
7794 : 8 : rtx temp = gen_reg_rtx (V4SImode);
7795 : 8 : emit_insn (gen_ashrv4si3 (temp,
7796 : : lowpart_subreg (V4SImode,
7797 : : force_reg (V2DImode,
7798 : : operands[1]),
7799 : : V2DImode),
7800 : : GEN_INT (31)));
7801 : 8 : zero_or_all_ones = gen_reg_rtx (V4SImode);
7802 : 8 : emit_insn (gen_sse2_pshufd_1 (zero_or_all_ones, temp,
7803 : : const1_rtx, const1_rtx,
7804 : : GEN_INT (3), GEN_INT (3)));
7805 : 8 : zero_or_all_ones = lowpart_subreg (V2DImode, zero_or_all_ones,
7806 : : V4SImode);
7807 : : }
7808 : 8 : rtx lshr_res = gen_reg_rtx (V2DImode);
7809 : 8 : emit_insn (gen_lshrv2di3 (lshr_res, operands[1], operands[2]));
7810 : 8 : rtx ashl_res = gen_reg_rtx (V2DImode);
7811 : 8 : rtx amount;
7812 : 8 : if (TARGET_64BIT)
7813 : : {
7814 : 8 : amount = gen_reg_rtx (DImode);
7815 : 8 : emit_insn (gen_subdi3 (amount, force_reg (DImode, GEN_INT (64)),
7816 : : operands[2]));
7817 : : }
7818 : : else
7819 : : {
7820 : 0 : rtx temp = gen_reg_rtx (SImode);
7821 : 0 : emit_insn (gen_subsi3 (temp, force_reg (SImode, GEN_INT (64)),
7822 : : lowpart_subreg (SImode, operands[2],
7823 : : DImode)));
7824 : 0 : amount = gen_reg_rtx (V4SImode);
7825 : 0 : emit_insn (gen_vec_setv4si_0 (amount, CONST0_RTX (V4SImode),
7826 : : temp));
7827 : : }
7828 : 8 : amount = lowpart_subreg (DImode, amount, GET_MODE (amount));
7829 : 8 : emit_insn (gen_ashlv2di3 (ashl_res, zero_or_all_ones, amount));
7830 : 8 : emit_insn (gen_iorv2di3 (operands[0], lshr_res, ashl_res));
7831 : 8 : return;
7832 : : }
7833 : :
7834 : 96 : rtx reg = gen_reg_rtx (V2DImode);
7835 : 96 : rtx par;
7836 : 96 : bool negate = false;
7837 : 96 : int i;
7838 : :
7839 : 96 : if (CONST_INT_P (operands[2]))
7840 : 96 : operands[2] = GEN_INT (-INTVAL (operands[2]));
7841 : : else
7842 : : negate = true;
7843 : :
7844 : 96 : par = gen_rtx_PARALLEL (V2DImode, rtvec_alloc (2));
7845 : 288 : for (i = 0; i < 2; i++)
7846 : 192 : XVECEXP (par, 0, i) = operands[2];
7847 : :
7848 : 96 : emit_insn (gen_vec_initv2didi (reg, par));
7849 : :
7850 : 96 : if (negate)
7851 : 0 : emit_insn (gen_negv2di2 (reg, reg));
7852 : :
7853 : 96 : emit_insn (gen_xop_shav2di3 (operands[0], operands[1], reg));
7854 : : }
7855 : :
7856 : : /* Replace all occurrences of REG FROM with REG TO in X, including
7857 : : occurrences with different modes. */
7858 : :
7859 : : rtx
7860 : 40408 : ix86_replace_reg_with_reg (rtx x, rtx from, rtx to)
7861 : : {
7862 : 40408 : gcc_checking_assert (REG_P (from)
7863 : : && REG_P (to)
7864 : : && GET_MODE (from) == GET_MODE (to));
7865 : 40408 : if (!reg_overlap_mentioned_p (from, x))
7866 : : return x;
7867 : 102 : rtx ret = copy_rtx (x);
7868 : 102 : subrtx_ptr_iterator::array_type array;
7869 : 498 : FOR_EACH_SUBRTX_PTR (iter, array, &ret, NONCONST)
7870 : : {
7871 : 396 : rtx *loc = *iter;
7872 : 396 : x = *loc;
7873 : 396 : if (REG_P (x) && REGNO (x) == REGNO (from))
7874 : : {
7875 : 102 : if (x == from)
7876 : 102 : *loc = to;
7877 : : else
7878 : : {
7879 : 0 : gcc_checking_assert (REG_NREGS (x) == 1);
7880 : 0 : *loc = gen_rtx_REG (GET_MODE (x), REGNO (to));
7881 : : }
7882 : : }
7883 : : }
7884 : 102 : return ret;
7885 : 102 : }
7886 : :
7887 : : /* Return mode for the memcpy/memset loop counter. Prefer SImode over
7888 : : DImode for constant loop counts. */
7889 : :
7890 : : static machine_mode
7891 : 32913 : counter_mode (rtx count_exp)
7892 : : {
7893 : 6781 : if (GET_MODE (count_exp) != VOIDmode)
7894 : 26056 : return GET_MODE (count_exp);
7895 : 6857 : if (!CONST_INT_P (count_exp))
7896 : 0 : return Pmode;
7897 : : if (TARGET_64BIT && (INTVAL (count_exp) & ~0xffffffff))
7898 : : return DImode;
7899 : : return SImode;
7900 : : }
7901 : :
7902 : : /* When ISSETMEM is FALSE, output simple loop to move memory pointer to SRCPTR
7903 : : to DESTPTR via chunks of MODE unrolled UNROLL times, overall size is COUNT
7904 : : specified in bytes. When ISSETMEM is TRUE, output the equivalent loop to set
7905 : : memory by VALUE (supposed to be in MODE).
7906 : :
7907 : : The size is rounded down to whole number of chunk size moved at once.
7908 : : SRCMEM and DESTMEM provide MEMrtx to feed proper aliasing info. */
7909 : :
7910 : :
7911 : : static void
7912 : 18693 : expand_set_or_cpymem_via_loop (rtx destmem, rtx srcmem,
7913 : : rtx destptr, rtx srcptr, rtx value,
7914 : : rtx count, machine_mode mode, int unroll,
7915 : : int expected_size, bool issetmem)
7916 : : {
7917 : 18693 : rtx_code_label *out_label = nullptr;
7918 : 18693 : rtx_code_label *top_label = nullptr;
7919 : 18693 : rtx iter, tmp;
7920 : 18693 : machine_mode iter_mode = counter_mode (count);
7921 : 18693 : int piece_size_n = GET_MODE_SIZE (mode) * unroll;
7922 : 18693 : rtx piece_size = GEN_INT (piece_size_n);
7923 : 37386 : rtx piece_size_mask = GEN_INT (~((GET_MODE_SIZE (mode) * unroll) - 1));
7924 : 18693 : rtx size;
7925 : 18693 : int i;
7926 : 18693 : int loop_count;
7927 : :
7928 : 18693 : if (expected_size != -1 && CONST_INT_P (count))
7929 : 6774 : loop_count = INTVAL (count) / GET_MODE_SIZE (mode) / unroll;
7930 : : else
7931 : : loop_count = -1;
7932 : :
7933 : : /* Don't generate the loop if the loop count is 1. */
7934 : 6774 : if (loop_count != 1)
7935 : : {
7936 : 18621 : top_label = gen_label_rtx ();
7937 : 18621 : out_label = gen_label_rtx ();
7938 : : }
7939 : 18693 : iter = gen_reg_rtx (iter_mode);
7940 : :
7941 : 18693 : size = expand_simple_binop (iter_mode, AND, count, piece_size_mask,
7942 : : NULL, 1, OPTAB_DIRECT);
7943 : : /* Those two should combine. */
7944 : 18693 : if (piece_size == const1_rtx)
7945 : : {
7946 : 5187 : emit_cmp_and_jump_insns (size, const0_rtx, EQ, NULL_RTX, iter_mode,
7947 : : true, out_label);
7948 : 5187 : predict_jump (REG_BR_PROB_BASE * 10 / 100);
7949 : : }
7950 : 18693 : emit_move_insn (iter, const0_rtx);
7951 : :
7952 : 18693 : if (loop_count != 1)
7953 : 18621 : emit_label (top_label);
7954 : :
7955 : 21449 : tmp = convert_modes (Pmode, iter_mode, iter, true);
7956 : :
7957 : : /* This assert could be relaxed - in this case we'll need to compute
7958 : : smallest power of two, containing in PIECE_SIZE_N and pass it to
7959 : : offset_address. */
7960 : 18693 : gcc_assert ((piece_size_n & (piece_size_n - 1)) == 0);
7961 : 18693 : destmem = offset_address (destmem, tmp, piece_size_n);
7962 : 18693 : destmem = adjust_address (destmem, mode, 0);
7963 : :
7964 : 18693 : if (!issetmem)
7965 : : {
7966 : 12122 : srcmem = offset_address (srcmem, copy_rtx (tmp), piece_size_n);
7967 : 12122 : srcmem = adjust_address (srcmem, mode, 0);
7968 : :
7969 : : /* When unrolling for chips that reorder memory reads and writes,
7970 : : we can save registers by using single temporary.
7971 : : Also using 4 temporaries is overkill in 32bit mode. */
7972 : 12122 : if (!TARGET_64BIT && 0)
7973 : : {
7974 : : for (i = 0; i < unroll; i++)
7975 : : {
7976 : : if (i)
7977 : : {
7978 : : destmem = adjust_address (copy_rtx (destmem), mode,
7979 : : GET_MODE_SIZE (mode));
7980 : : srcmem = adjust_address (copy_rtx (srcmem), mode,
7981 : : GET_MODE_SIZE (mode));
7982 : : }
7983 : : emit_move_insn (destmem, srcmem);
7984 : : }
7985 : : }
7986 : : else
7987 : : {
7988 : 12122 : rtx tmpreg[4];
7989 : 12122 : gcc_assert (unroll <= 4);
7990 : 47628 : for (i = 0; i < unroll; i++)
7991 : : {
7992 : 35506 : tmpreg[i] = gen_reg_rtx (mode);
7993 : 35506 : if (i)
7994 : 46768 : srcmem = adjust_address (copy_rtx (srcmem), mode,
7995 : : GET_MODE_SIZE (mode));
7996 : 35506 : emit_move_insn (tmpreg[i], srcmem);
7997 : : }
7998 : 47628 : for (i = 0; i < unroll; i++)
7999 : : {
8000 : 35506 : if (i)
8001 : 46768 : destmem = adjust_address (copy_rtx (destmem), mode,
8002 : : GET_MODE_SIZE (mode));
8003 : 35506 : emit_move_insn (destmem, tmpreg[i]);
8004 : : }
8005 : : }
8006 : : }
8007 : : else
8008 : 30125 : for (i = 0; i < unroll; i++)
8009 : : {
8010 : 23554 : if (i)
8011 : 33966 : destmem = adjust_address (copy_rtx (destmem), mode,
8012 : : GET_MODE_SIZE (mode));
8013 : 23554 : emit_move_insn (destmem, value);
8014 : : }
8015 : :
8016 : 18693 : tmp = expand_simple_binop (iter_mode, PLUS, iter, piece_size, iter,
8017 : : true, OPTAB_LIB_WIDEN);
8018 : 18693 : if (tmp != iter)
8019 : 0 : emit_move_insn (iter, tmp);
8020 : :
8021 : 18693 : if (loop_count != 1)
8022 : : {
8023 : 18621 : emit_cmp_and_jump_insns (iter, size, LT, NULL_RTX, iter_mode,
8024 : : true, top_label);
8025 : 18621 : if (expected_size != -1)
8026 : : {
8027 : 9370 : expected_size /= GET_MODE_SIZE (mode) * unroll;
8028 : 9370 : if (expected_size == 0)
8029 : 1 : predict_jump (0);
8030 : 9369 : else if (expected_size > REG_BR_PROB_BASE)
8031 : 2 : predict_jump (REG_BR_PROB_BASE - 1);
8032 : : else
8033 : 9367 : predict_jump (REG_BR_PROB_BASE
8034 : 9367 : - (REG_BR_PROB_BASE + expected_size / 2)
8035 : 9367 : / expected_size);
8036 : : }
8037 : : else
8038 : 9251 : predict_jump (REG_BR_PROB_BASE * 80 / 100);
8039 : : }
8040 : 18693 : iter = ix86_zero_extend_to_Pmode (iter);
8041 : 21449 : tmp = expand_simple_binop (Pmode, PLUS, destptr, iter, destptr,
8042 : : true, OPTAB_LIB_WIDEN);
8043 : 18693 : if (tmp != destptr)
8044 : 0 : emit_move_insn (destptr, tmp);
8045 : 18693 : if (!issetmem)
8046 : : {
8047 : 13456 : tmp = expand_simple_binop (Pmode, PLUS, srcptr, iter, srcptr,
8048 : : true, OPTAB_LIB_WIDEN);
8049 : 12122 : if (tmp != srcptr)
8050 : 0 : emit_move_insn (srcptr, tmp);
8051 : : }
8052 : 18693 : if (loop_count != 1)
8053 : 18621 : emit_label (out_label);
8054 : 18693 : }
8055 : :
8056 : : /* Divide COUNTREG by SCALE. */
8057 : : static rtx
8058 : 14806 : scale_counter (rtx countreg, int scale)
8059 : : {
8060 : 14806 : rtx sc;
8061 : :
8062 : 14806 : if (scale == 1)
8063 : : return countreg;
8064 : 9962 : if (CONST_INT_P (countreg))
8065 : 9946 : return GEN_INT (INTVAL (countreg) / scale);
8066 : 16 : gcc_assert (REG_P (countreg));
8067 : :
8068 : 48 : sc = expand_simple_binop (GET_MODE (countreg), LSHIFTRT, countreg,
8069 : 32 : GEN_INT (exact_log2 (scale)),
8070 : : NULL, 1, OPTAB_DIRECT);
8071 : 16 : return sc;
8072 : : }
8073 : :
8074 : : /* Output "rep; mov" or "rep; stos" instruction depending on ISSETMEM argument.
8075 : : When ISSETMEM is true, arguments SRCMEM and SRCPTR are ignored.
8076 : : When ISSETMEM is false, arguments VALUE and ORIG_VALUE are ignored.
8077 : : For setmem case, VALUE is a promoted to a wider size ORIG_VALUE.
8078 : : ORIG_VALUE is the original value passed to memset to fill the memory with.
8079 : : Other arguments have same meaning as for previous function. */
8080 : :
8081 : : static void
8082 : 14806 : expand_set_or_cpymem_via_rep (rtx destmem, rtx srcmem,
8083 : : rtx destptr, rtx srcptr, rtx value, rtx orig_value,
8084 : : rtx count,
8085 : : machine_mode mode, bool issetmem)
8086 : : {
8087 : 14806 : rtx destexp;
8088 : 14806 : rtx srcexp;
8089 : 14806 : rtx countreg;
8090 : 14806 : HOST_WIDE_INT rounded_count;
8091 : :
8092 : : /* If possible, it is shorter to use rep movs.
8093 : : TODO: Maybe it is better to move this logic to decide_alg. */
8094 : 14806 : if (mode == QImode && CONST_INT_P (count) && !(INTVAL (count) & 3)
8095 : 241 : && !TARGET_PREFER_KNOWN_REP_MOVSB_STOSB
8096 : 237 : && (!issetmem || orig_value == const0_rtx))
8097 : 14806 : mode = SImode;
8098 : :
8099 : 14806 : if (destptr != XEXP (destmem, 0) || GET_MODE (destmem) != BLKmode)
8100 : 14544 : destmem = adjust_automodify_address_nv (destmem, BLKmode, destptr, 0);
8101 : :
8102 : 29612 : countreg = ix86_zero_extend_to_Pmode (scale_counter (count,
8103 : 14806 : GET_MODE_SIZE (mode)));
8104 : 14806 : if (mode != QImode)
8105 : : {
8106 : 30143 : destexp = gen_rtx_ASHIFT (Pmode, countreg,
8107 : : GEN_INT (exact_log2 (GET_MODE_SIZE (mode))));
8108 : 10219 : destexp = gen_rtx_PLUS (Pmode, destexp, destptr);
8109 : : }
8110 : : else
8111 : 4865 : destexp = gen_rtx_PLUS (Pmode, destptr, countreg);
8112 : 14806 : if ((!issetmem || orig_value == const0_rtx) && CONST_INT_P (count))
8113 : : {
8114 : 10620 : rounded_count
8115 : 10620 : = ROUND_DOWN (INTVAL (count), (HOST_WIDE_INT) GET_MODE_SIZE (mode));
8116 : 10620 : destmem = shallow_copy_rtx (destmem);
8117 : 10620 : set_mem_size (destmem, rounded_count);
8118 : : }
8119 : 4193 : else if (MEM_SIZE_KNOWN_P (destmem))
8120 : 332 : clear_mem_size (destmem);
8121 : :
8122 : 14806 : if (issetmem)
8123 : : {
8124 : 6029 : value = force_reg (mode, gen_lowpart (mode, value));
8125 : 6029 : emit_insn (gen_rep_stos (destptr, countreg, destmem, value, destexp));
8126 : : }
8127 : : else
8128 : : {
8129 : 8777 : if (srcptr != XEXP (srcmem, 0) || GET_MODE (srcmem) != BLKmode)
8130 : 8574 : srcmem = adjust_automodify_address_nv (srcmem, BLKmode, srcptr, 0);
8131 : 8777 : if (mode != QImode)
8132 : : {
8133 : 15914 : srcexp = gen_rtx_ASHIFT (Pmode, countreg,
8134 : : GEN_INT (exact_log2 (GET_MODE_SIZE (mode))));
8135 : 5426 : srcexp = gen_rtx_PLUS (Pmode, srcexp, srcptr);
8136 : : }
8137 : : else
8138 : 3550 : srcexp = gen_rtx_PLUS (Pmode, srcptr, countreg);
8139 : 8777 : if (CONST_INT_P (count))
8140 : : {
8141 : 5726 : rounded_count
8142 : 5726 : = ROUND_DOWN (INTVAL (count), (HOST_WIDE_INT) GET_MODE_SIZE (mode));
8143 : 5726 : srcmem = shallow_copy_rtx (srcmem);
8144 : 5726 : set_mem_size (srcmem, rounded_count);
8145 : : }
8146 : : else
8147 : : {
8148 : 3065 : if (MEM_SIZE_KNOWN_P (srcmem))
8149 : 0 : clear_mem_size (srcmem);
8150 : : }
8151 : 8777 : emit_insn (gen_rep_mov (destptr, destmem, srcptr, srcmem, countreg,
8152 : : destexp, srcexp));
8153 : : }
8154 : 14806 : }
8155 : :
8156 : : /* This function emits moves to copy SIZE_TO_MOVE bytes from SRCMEM to
8157 : : DESTMEM.
8158 : : SRC is passed by pointer to be updated on return.
8159 : : Return value is updated DST. */
8160 : : static rtx
8161 : 13 : emit_memmov (rtx destmem, rtx *srcmem, rtx destptr, rtx srcptr,
8162 : : HOST_WIDE_INT size_to_move)
8163 : : {
8164 : 13 : rtx dst = destmem, src = *srcmem, tempreg;
8165 : 13 : enum insn_code code;
8166 : 13 : machine_mode move_mode;
8167 : 13 : int piece_size, i;
8168 : :
8169 : : /* Find the widest mode in which we could perform moves.
8170 : : Start with the biggest power of 2 less than SIZE_TO_MOVE and half
8171 : : it until move of such size is supported. */
8172 : 13 : piece_size = 1 << floor_log2 (size_to_move);
8173 : 26 : while (!int_mode_for_size (piece_size * BITS_PER_UNIT, 0).exists (&move_mode)
8174 : 26 : || (code = optab_handler (mov_optab, move_mode)) == CODE_FOR_nothing)
8175 : : {
8176 : 0 : gcc_assert (piece_size > 1);
8177 : 0 : piece_size >>= 1;
8178 : : }
8179 : :
8180 : : /* Find the corresponding vector mode with the same size as MOVE_MODE.
8181 : : MOVE_MODE is an integer mode at the moment (SI, DI, TI, etc.). */
8182 : 39 : if (GET_MODE_SIZE (move_mode) > GET_MODE_SIZE (word_mode))
8183 : : {
8184 : 0 : int nunits = GET_MODE_SIZE (move_mode) / GET_MODE_SIZE (word_mode);
8185 : 0 : if (!mode_for_vector (word_mode, nunits).exists (&move_mode)
8186 : 0 : || (code = optab_handler (mov_optab, move_mode)) == CODE_FOR_nothing)
8187 : : {
8188 : 0 : move_mode = word_mode;
8189 : 0 : piece_size = GET_MODE_SIZE (move_mode);
8190 : 0 : code = optab_handler (mov_optab, move_mode);
8191 : : }
8192 : : }
8193 : 13 : gcc_assert (code != CODE_FOR_nothing);
8194 : :
8195 : 13 : dst = adjust_automodify_address_nv (dst, move_mode, destptr, 0);
8196 : 13 : src = adjust_automodify_address_nv (src, move_mode, srcptr, 0);
8197 : :
8198 : : /* Emit moves. We'll need SIZE_TO_MOVE/PIECE_SIZES moves. */
8199 : 13 : gcc_assert (size_to_move % piece_size == 0);
8200 : :
8201 : 26 : for (i = 0; i < size_to_move; i += piece_size)
8202 : : {
8203 : : /* We move from memory to memory, so we'll need to do it via
8204 : : a temporary register. */
8205 : 13 : tempreg = gen_reg_rtx (move_mode);
8206 : 13 : emit_insn (GEN_FCN (code) (tempreg, src));
8207 : 13 : emit_insn (GEN_FCN (code) (dst, tempreg));
8208 : :
8209 : 26 : emit_move_insn (destptr,
8210 : 13 : plus_constant (Pmode, copy_rtx (destptr), piece_size));
8211 : 26 : emit_move_insn (srcptr,
8212 : 13 : plus_constant (Pmode, copy_rtx (srcptr), piece_size));
8213 : :
8214 : 13 : dst = adjust_automodify_address_nv (dst, move_mode, destptr,
8215 : : piece_size);
8216 : 13 : src = adjust_automodify_address_nv (src, move_mode, srcptr,
8217 : : piece_size);
8218 : : }
8219 : :
8220 : : /* Update DST and SRC rtx. */
8221 : 13 : *srcmem = src;
8222 : 13 : return dst;
8223 : : }
8224 : :
8225 : : /* Helper function for the string operations below. Dest VARIABLE whether
8226 : : it is aligned to VALUE bytes. If true, jump to the label. */
8227 : :
8228 : : static rtx_code_label *
8229 : 32370 : ix86_expand_aligntest (rtx variable, int value, bool epilogue)
8230 : : {
8231 : 32370 : rtx_code_label *label = gen_label_rtx ();
8232 : 32370 : rtx tmpcount = gen_reg_rtx (GET_MODE (variable));
8233 : 32370 : if (GET_MODE (variable) == DImode)
8234 : 897 : emit_insn (gen_anddi3 (tmpcount, variable, GEN_INT (value)));
8235 : : else
8236 : 31473 : emit_insn (gen_andsi3 (tmpcount, variable, GEN_INT (value)));
8237 : 32370 : emit_cmp_and_jump_insns (tmpcount, const0_rtx, EQ, 0, GET_MODE (variable),
8238 : : 1, label);
8239 : 32370 : if (epilogue)
8240 : 3 : predict_jump (REG_BR_PROB_BASE * 50 / 100);
8241 : : else
8242 : 32367 : predict_jump (REG_BR_PROB_BASE * 90 / 100);
8243 : 32370 : return label;
8244 : : }
8245 : :
8246 : :
8247 : : /* Output code to copy at most count & (max_size - 1) bytes from SRC to DEST. */
8248 : :
8249 : : static void
8250 : 7916 : expand_cpymem_epilogue (rtx destmem, rtx srcmem,
8251 : : rtx destptr, rtx srcptr, rtx count, int max_size)
8252 : : {
8253 : 7916 : rtx src, dest;
8254 : 7916 : if (CONST_INT_P (count))
8255 : : {
8256 : 5676 : unsigned HOST_WIDE_INT countval = UINTVAL (count);
8257 : 5676 : unsigned HOST_WIDE_INT epilogue_size = countval % max_size;
8258 : 5676 : unsigned int destalign = MEM_ALIGN (destmem);
8259 : 5676 : cfun->machine->by_pieces_in_use = true;
8260 : 5676 : move_by_pieces (destmem, srcmem, epilogue_size, destalign,
8261 : : RETURN_BEGIN);
8262 : 5676 : cfun->machine->by_pieces_in_use = false;
8263 : 5676 : return;
8264 : : }
8265 : 2240 : if (max_size > 8)
8266 : : {
8267 : 2240 : count = expand_simple_binop (GET_MODE (count), AND, count, GEN_INT (max_size - 1),
8268 : : count, 1, OPTAB_DIRECT);
8269 : 2240 : expand_set_or_cpymem_via_loop (destmem, srcmem, destptr, srcptr, NULL,
8270 : : count, QImode, 1, 4, false);
8271 : 2240 : return;
8272 : : }
8273 : :
8274 : : /* When there are stringops, we can cheaply increase dest and src pointers.
8275 : : Otherwise we save code size by maintaining offset (zero is readily
8276 : : available from preceding rep operation) and using x86 addressing modes.
8277 : : */
8278 : 0 : if (TARGET_SINGLE_STRINGOP)
8279 : : {
8280 : 0 : if (max_size > 4)
8281 : : {
8282 : 0 : rtx_code_label *label = ix86_expand_aligntest (count, 4, true);
8283 : 0 : src = change_address (srcmem, SImode, srcptr);
8284 : 0 : dest = change_address (destmem, SImode, destptr);
8285 : 0 : emit_insn (gen_strmov (destptr, dest, srcptr, src));
8286 : 0 : emit_label (label);
8287 : 0 : LABEL_NUSES (label) = 1;
8288 : : }
8289 : 0 : if (max_size > 2)
8290 : : {
8291 : 0 : rtx_code_label *label = ix86_expand_aligntest (count, 2, true);
8292 : 0 : src = change_address (srcmem, HImode, srcptr);
8293 : 0 : dest = change_address (destmem, HImode, destptr);
8294 : 0 : emit_insn (gen_strmov (destptr, dest, srcptr, src));
8295 : 0 : emit_label (label);
8296 : 0 : LABEL_NUSES (label) = 1;
8297 : : }
8298 : 0 : if (max_size > 1)
8299 : : {
8300 : 0 : rtx_code_label *label = ix86_expand_aligntest (count, 1, true);
8301 : 0 : src = change_address (srcmem, QImode, srcptr);
8302 : 0 : dest = change_address (destmem, QImode, destptr);
8303 : 0 : emit_insn (gen_strmov (destptr, dest, srcptr, src));
8304 : 0 : emit_label (label);
8305 : 0 : LABEL_NUSES (label) = 1;
8306 : : }
8307 : : }
8308 : : else
8309 : : {
8310 : 0 : rtx offset = force_reg (Pmode, const0_rtx);
8311 : 0 : rtx tmp;
8312 : :
8313 : 0 : if (max_size > 4)
8314 : : {
8315 : 0 : rtx_code_label *label = ix86_expand_aligntest (count, 4, true);
8316 : 0 : src = change_address (srcmem, SImode, srcptr);
8317 : 0 : dest = change_address (destmem, SImode, destptr);
8318 : 0 : emit_move_insn (dest, src);
8319 : 0 : tmp = expand_simple_binop (Pmode, PLUS, offset, GEN_INT (4), NULL,
8320 : : true, OPTAB_LIB_WIDEN);
8321 : 0 : if (tmp != offset)
8322 : 0 : emit_move_insn (offset, tmp);
8323 : 0 : emit_label (label);
8324 : 0 : LABEL_NUSES (label) = 1;
8325 : : }
8326 : 0 : if (max_size > 2)
8327 : : {
8328 : 0 : rtx_code_label *label = ix86_expand_aligntest (count, 2, true);
8329 : 0 : tmp = gen_rtx_PLUS (Pmode, srcptr, offset);
8330 : 0 : src = change_address (srcmem, HImode, tmp);
8331 : 0 : tmp = gen_rtx_PLUS (Pmode, destptr, offset);
8332 : 0 : dest = change_address (destmem, HImode, tmp);
8333 : 0 : emit_move_insn (dest, src);
8334 : 0 : tmp = expand_simple_binop (Pmode, PLUS, offset, GEN_INT (2), tmp,
8335 : : true, OPTAB_LIB_WIDEN);
8336 : 0 : if (tmp != offset)
8337 : 0 : emit_move_insn (offset, tmp);
8338 : 0 : emit_label (label);
8339 : 0 : LABEL_NUSES (label) = 1;
8340 : : }
8341 : 0 : if (max_size > 1)
8342 : : {
8343 : 0 : rtx_code_label *label = ix86_expand_aligntest (count, 1, true);
8344 : 0 : tmp = gen_rtx_PLUS (Pmode, srcptr, offset);
8345 : 0 : src = change_address (srcmem, QImode, tmp);
8346 : 0 : tmp = gen_rtx_PLUS (Pmode, destptr, offset);
8347 : 0 : dest = change_address (destmem, QImode, tmp);
8348 : 0 : emit_move_insn (dest, src);
8349 : 0 : emit_label (label);
8350 : 0 : LABEL_NUSES (label) = 1;
8351 : : }
8352 : : }
8353 : : }
8354 : :
8355 : : /* This function emits moves to fill SIZE_TO_MOVE bytes starting from DESTMEM
8356 : : with value PROMOTED_VAL.
8357 : : SRC is passed by pointer to be updated on return.
8358 : : Return value is updated DST. */
8359 : : static rtx
8360 : 6 : emit_memset (rtx destmem, rtx destptr, rtx promoted_val,
8361 : : HOST_WIDE_INT size_to_move)
8362 : : {
8363 : 6 : rtx dst = destmem;
8364 : 6 : enum insn_code code;
8365 : 6 : machine_mode move_mode;
8366 : 6 : int piece_size, i;
8367 : :
8368 : : /* Find the widest mode in which we could perform moves.
8369 : : Start with the biggest power of 2 less than SIZE_TO_MOVE and half
8370 : : it until move of such size is supported. */
8371 : 6 : move_mode = GET_MODE (promoted_val);
8372 : 6 : if (move_mode == VOIDmode)
8373 : 0 : move_mode = QImode;
8374 : 12 : if (size_to_move < GET_MODE_SIZE (move_mode))
8375 : : {
8376 : 5 : unsigned int move_bits = size_to_move * BITS_PER_UNIT;
8377 : 5 : move_mode = int_mode_for_size (move_bits, 0).require ();
8378 : 5 : promoted_val = gen_lowpart (move_mode, promoted_val);
8379 : : }
8380 : 6 : piece_size = GET_MODE_SIZE (move_mode);
8381 : 6 : code = optab_handler (mov_optab, move_mode);
8382 : 6 : gcc_assert (code != CODE_FOR_nothing && promoted_val != NULL_RTX);
8383 : :
8384 : 6 : dst = adjust_automodify_address_nv (dst, move_mode, destptr, 0);
8385 : :
8386 : : /* Emit moves. We'll need SIZE_TO_MOVE/PIECE_SIZES moves. */
8387 : 6 : gcc_assert (size_to_move % piece_size == 0);
8388 : :
8389 : 12 : for (i = 0; i < size_to_move; i += piece_size)
8390 : : {
8391 : 12 : if (piece_size <= GET_MODE_SIZE (word_mode))
8392 : : {
8393 : 4 : emit_insn (gen_strset (destptr, dst, promoted_val));
8394 : 4 : dst = adjust_automodify_address_nv (dst, move_mode, destptr,
8395 : : piece_size);
8396 : 4 : continue;
8397 : : }
8398 : :
8399 : 2 : emit_insn (GEN_FCN (code) (dst, promoted_val));
8400 : :
8401 : 4 : emit_move_insn (destptr,
8402 : 2 : plus_constant (Pmode, copy_rtx (destptr), piece_size));
8403 : :
8404 : 2 : dst = adjust_automodify_address_nv (dst, move_mode, destptr,
8405 : : piece_size);
8406 : : }
8407 : :
8408 : : /* Update DST rtx. */
8409 : 6 : return dst;
8410 : : }
8411 : : /* Output code to set at most count & (max_size - 1) bytes starting by DEST. */
8412 : : static void
8413 : 418 : expand_setmem_epilogue_via_loop (rtx destmem, rtx destptr, rtx value,
8414 : : rtx count, int max_size)
8415 : : {
8416 : 836 : count = expand_simple_binop (counter_mode (count), AND, count,
8417 : 418 : GEN_INT (max_size - 1), count, 1, OPTAB_DIRECT);
8418 : 418 : expand_set_or_cpymem_via_loop (destmem, NULL, destptr, NULL,
8419 : 418 : gen_lowpart (QImode, value), count, QImode,
8420 : : 1, max_size / 2, true);
8421 : 418 : }
8422 : :
8423 : : /* Callback routine for store_by_pieces. Return the RTL of a register
8424 : : containing GET_MODE_SIZE (MODE) bytes in the RTL register op_p which
8425 : : is an integer or a word vector register. If PREV_P isn't nullptr,
8426 : : it has the RTL info from the previous iteration. */
8427 : :
8428 : : static rtx
8429 : 5067 : setmem_epilogue_gen_val (void *op_p, void *prev_p, HOST_WIDE_INT,
8430 : : fixed_size_mode mode)
8431 : : {
8432 : 5067 : rtx target;
8433 : 5067 : by_pieces_prev *prev = (by_pieces_prev *) prev_p;
8434 : 5067 : if (prev)
8435 : : {
8436 : 5067 : rtx prev_op = prev->data;
8437 : 5067 : if (prev_op)
8438 : : {
8439 : 2919 : machine_mode prev_mode = GET_MODE (prev_op);
8440 : 2919 : if (prev_mode == mode)
8441 : : return prev_op;
8442 : 52 : if (VECTOR_MODE_P (prev_mode)
8443 : 1103 : && VECTOR_MODE_P (mode)
8444 : 1155 : && GET_MODE_INNER (prev_mode) == GET_MODE_INNER (mode))
8445 : : {
8446 : 0 : target = gen_rtx_SUBREG (mode, prev_op, 0);
8447 : 0 : return target;
8448 : : }
8449 : : }
8450 : : }
8451 : :
8452 : 3303 : rtx op = (rtx) op_p;
8453 : 3303 : machine_mode op_mode = GET_MODE (op);
8454 : :
8455 : 3303 : if (VECTOR_MODE_P (mode))
8456 : : {
8457 : 3746 : gcc_assert (GET_MODE_INNER (mode) == QImode);
8458 : :
8459 : 1873 : unsigned int op_size = GET_MODE_SIZE (op_mode);
8460 : 1873 : unsigned int size = GET_MODE_SIZE (mode);
8461 : 1873 : unsigned int nunits;
8462 : 1873 : machine_mode vec_mode;
8463 : 1873 : if (op_size < size)
8464 : : {
8465 : : /* If OP size is smaller than MODE size, duplicate it. */
8466 : 1 : nunits = size / GET_MODE_SIZE (QImode);
8467 : 1 : vec_mode = mode_for_vector (QImode, nunits).require ();
8468 : 1 : nunits = size / op_size;
8469 : 1 : gcc_assert (SCALAR_INT_MODE_P (op_mode));
8470 : 1 : machine_mode dup_mode
8471 : 1 : = mode_for_vector (as_a <scalar_mode> (op_mode),
8472 : 2 : nunits).require ();
8473 : 1 : target = gen_reg_rtx (vec_mode);
8474 : 1 : op = gen_vec_duplicate (dup_mode, op);
8475 : 1 : rtx dup_op = gen_reg_rtx (dup_mode);
8476 : 1 : emit_move_insn (dup_op, op);
8477 : 1 : op = gen_rtx_SUBREG (vec_mode, dup_op, 0);
8478 : 1 : emit_move_insn (target, op);
8479 : 1 : return target;
8480 : : }
8481 : 1872 : nunits = op_size / GET_MODE_SIZE (QImode);
8482 : 1872 : vec_mode = mode_for_vector (QImode, nunits).require ();
8483 : 1872 : target = gen_reg_rtx (vec_mode);
8484 : 1872 : op = gen_rtx_SUBREG (vec_mode, op, 0);
8485 : 1872 : emit_move_insn (target, op);
8486 : 1872 : if (op_size == size)
8487 : : return target;
8488 : :
8489 : 0 : rtx tmp = gen_reg_rtx (mode);
8490 : 0 : target = gen_rtx_SUBREG (mode, target, 0);
8491 : 0 : emit_move_insn (tmp, target);
8492 : 0 : return tmp;
8493 : : }
8494 : :
8495 : 1430 : if (VECTOR_MODE_P (op_mode))
8496 : : {
8497 : 2850 : gcc_assert (GET_MODE_INNER (op_mode) == word_mode);
8498 : 1425 : target = gen_reg_rtx (word_mode);
8499 : 1425 : op = gen_rtx_SUBREG (word_mode, op, 0);
8500 : 1425 : emit_move_insn (target, op);
8501 : : }
8502 : : else
8503 : : target = op;
8504 : :
8505 : 1430 : if (mode == GET_MODE (target))
8506 : : return target;
8507 : :
8508 : 240 : rtx tmp = gen_reg_rtx (mode);
8509 : 240 : target = gen_rtx_SUBREG (mode, target, 0);
8510 : 240 : emit_move_insn (tmp, target);
8511 : 240 : return tmp;
8512 : : }
8513 : :
8514 : : /* Output code to set at most count & (max_size - 1) bytes starting by DEST. */
8515 : : static void
8516 : 8176 : expand_setmem_epilogue (rtx destmem, rtx destptr, rtx value, rtx vec_value,
8517 : : rtx count, int max_size)
8518 : : {
8519 : 8176 : rtx dest;
8520 : :
8521 : 8176 : if (CONST_INT_P (count))
8522 : : {
8523 : 7757 : unsigned HOST_WIDE_INT countval = UINTVAL (count);
8524 : 7757 : unsigned HOST_WIDE_INT epilogue_size = countval % max_size;
8525 : 7757 : unsigned int destalign = MEM_ALIGN (destmem);
8526 : 7757 : cfun->machine->by_pieces_in_use = true;
8527 : 12427 : store_by_pieces (destmem, epilogue_size, setmem_epilogue_gen_val,
8528 : : vec_value ? vec_value : value, destalign, true,
8529 : : RETURN_BEGIN);
8530 : 7757 : cfun->machine->by_pieces_in_use = false;
8531 : 7757 : return;
8532 : : }
8533 : 419 : if (max_size > 32)
8534 : : {
8535 : 418 : expand_setmem_epilogue_via_loop (destmem, destptr, value, count, max_size);
8536 : 418 : return;
8537 : : }
8538 : 1 : if (max_size > 16)
8539 : : {
8540 : 0 : rtx_code_label *label = ix86_expand_aligntest (count, 16, true);
8541 : 0 : if (TARGET_64BIT)
8542 : : {
8543 : 0 : dest = change_address (destmem, DImode, destptr);
8544 : 0 : emit_insn (gen_strset (destptr, dest, value));
8545 : 0 : dest = adjust_automodify_address_nv (dest, DImode, destptr, 8);
8546 : 0 : emit_insn (gen_strset (destptr, dest, value));
8547 : : }
8548 : : else
8549 : : {
8550 : 0 : dest = change_address (destmem, SImode, destptr);
8551 : 0 : emit_insn (gen_strset (destptr, dest, value));
8552 : 0 : dest = adjust_automodify_address_nv (dest, SImode, destptr, 4);
8553 : 0 : emit_insn (gen_strset (destptr, dest, value));
8554 : 0 : dest = adjust_automodify_address_nv (dest, SImode, destptr, 8);
8555 : 0 : emit_insn (gen_strset (destptr, dest, value));
8556 : 0 : dest = adjust_automodify_address_nv (dest, SImode, destptr, 12);
8557 : 0 : emit_insn (gen_strset (destptr, dest, value));
8558 : : }
8559 : 0 : emit_label (label);
8560 : 0 : LABEL_NUSES (label) = 1;
8561 : : }
8562 : 1 : if (max_size > 8)
8563 : : {
8564 : 0 : rtx_code_label *label = ix86_expand_aligntest (count, 8, true);
8565 : 0 : if (TARGET_64BIT)
8566 : : {
8567 : 0 : dest = change_address (destmem, DImode, destptr);
8568 : 0 : emit_insn (gen_strset (destptr, dest, value));
8569 : : }
8570 : : else
8571 : : {
8572 : 0 : dest = change_address (destmem, SImode, destptr);
8573 : 0 : emit_insn (gen_strset (destptr, dest, value));
8574 : 0 : dest = adjust_automodify_address_nv (dest, SImode, destptr, 4);
8575 : 0 : emit_insn (gen_strset (destptr, dest, value));
8576 : : }
8577 : 0 : emit_label (label);
8578 : 0 : LABEL_NUSES (label) = 1;
8579 : : }
8580 : 1 : if (max_size > 4)
8581 : : {
8582 : 1 : rtx_code_label *label = ix86_expand_aligntest (count, 4, true);
8583 : 1 : dest = change_address (destmem, SImode, destptr);
8584 : 1 : emit_insn (gen_strset (destptr, dest, gen_lowpart (SImode, value)));
8585 : 1 : emit_label (label);
8586 : 1 : LABEL_NUSES (label) = 1;
8587 : : }
8588 : 1 : if (max_size > 2)
8589 : : {
8590 : 1 : rtx_code_label *label = ix86_expand_aligntest (count, 2, true);
8591 : 1 : dest = change_address (destmem, HImode, destptr);
8592 : 1 : emit_insn (gen_strset (destptr, dest, gen_lowpart (HImode, value)));
8593 : 1 : emit_label (label);
8594 : 1 : LABEL_NUSES (label) = 1;
8595 : : }
8596 : 1 : if (max_size > 1)
8597 : : {
8598 : 1 : rtx_code_label *label = ix86_expand_aligntest (count, 1, true);
8599 : 1 : dest = change_address (destmem, QImode, destptr);
8600 : 1 : emit_insn (gen_strset (destptr, dest, gen_lowpart (QImode, value)));
8601 : 1 : emit_label (label);
8602 : 1 : LABEL_NUSES (label) = 1;
8603 : : }
8604 : : }
8605 : :
8606 : : /* Adjust COUNTER by the VALUE. */
8607 : : static void
8608 : 19 : ix86_adjust_counter (rtx countreg, HOST_WIDE_INT value)
8609 : : {
8610 : 19 : emit_insn (gen_add2_insn (countreg, GEN_INT (-value)));
8611 : 19 : }
8612 : :
8613 : : /* Depending on ISSETMEM, copy enough from SRCMEM to DESTMEM or set enough to
8614 : : DESTMEM to align it to DESIRED_ALIGNMENT. Original alignment is ALIGN.
8615 : : Depending on ISSETMEM, either arguments SRCMEM/SRCPTR or VALUE/VEC_VALUE are
8616 : : ignored.
8617 : : Return value is updated DESTMEM. */
8618 : :
8619 : : static rtx
8620 : 7 : expand_set_or_cpymem_prologue (rtx destmem, rtx srcmem,
8621 : : rtx destptr, rtx srcptr, rtx value,
8622 : : rtx vec_value, rtx count, int align,
8623 : : int desired_alignment, bool issetmem)
8624 : : {
8625 : 7 : int i;
8626 : 35 : for (i = 1; i < desired_alignment; i <<= 1)
8627 : : {
8628 : 28 : if (align <= i)
8629 : : {
8630 : 19 : rtx_code_label *label = ix86_expand_aligntest (destptr, i, false);
8631 : 19 : if (issetmem)
8632 : : {
8633 : 12 : if (vec_value && i > GET_MODE_SIZE (GET_MODE (value)))
8634 : 2 : destmem = emit_memset (destmem, destptr, vec_value, i);
8635 : : else
8636 : 4 : destmem = emit_memset (destmem, destptr, value, i);
8637 : : }
8638 : : else
8639 : 13 : destmem = emit_memmov (destmem, &srcmem, destptr, srcptr, i);
8640 : 19 : ix86_adjust_counter (count, i);
8641 : 19 : emit_label (label);
8642 : 19 : LABEL_NUSES (label) = 1;
8643 : 19 : set_mem_align (destmem, i * 2 * BITS_PER_UNIT);
8644 : : }
8645 : : }
8646 : 7 : return destmem;
8647 : : }
8648 : :
8649 : : /* Test if COUNT&SIZE is nonzero and if so, expand movme
8650 : : or setmem sequence that is valid for SIZE..2*SIZE-1 bytes
8651 : : and jump to DONE_LABEL. */
8652 : : static void
8653 : 25874 : expand_small_cpymem_or_setmem (rtx destmem, rtx srcmem,
8654 : : rtx destptr, rtx srcptr,
8655 : : rtx value, rtx vec_value,
8656 : : rtx count, int size,
8657 : : rtx done_label, bool issetmem)
8658 : : {
8659 : 25874 : rtx_code_label *label = ix86_expand_aligntest (count, size, false);
8660 : 25874 : machine_mode mode = int_mode_for_size (size * BITS_PER_UNIT, 1).else_blk ();
8661 : 25874 : rtx modesize;
8662 : 25874 : rtx scalar_value = value;
8663 : 25874 : int n;
8664 : :
8665 : : /* If we do not have vector value to copy, we must reduce size. */
8666 : 25874 : if (issetmem)
8667 : : {
8668 : 3684 : if (!vec_value)
8669 : : {
8670 : 7 : if (GET_MODE (value) == VOIDmode && size > 8)
8671 : 0 : mode = Pmode;
8672 : 21 : else if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (value)))
8673 : 1 : mode = GET_MODE (value);
8674 : : }
8675 : : else
8676 : 3677 : mode = GET_MODE (vec_value), value = vec_value;
8677 : : }
8678 : : else
8679 : : {
8680 : : /* Choose appropriate vector mode. */
8681 : 22190 : if (size >= 32)
8682 : 5546 : switch (MOVE_MAX)
8683 : : {
8684 : 0 : case 64:
8685 : 0 : if (size >= 64)
8686 : : {
8687 : : mode = V64QImode;
8688 : : break;
8689 : : }
8690 : : /* FALLTHRU */
8691 : 0 : case 32:
8692 : 0 : mode = V32QImode;
8693 : 0 : break;
8694 : : case 16:
8695 : : mode = V16QImode;
8696 : : break;
8697 : : case 8:
8698 : : mode = DImode;
8699 : : break;
8700 : 0 : default:
8701 : 0 : gcc_unreachable ();
8702 : : }
8703 : 16644 : else if (size >= 16)
8704 : 5546 : mode = TARGET_SSE ? V16QImode : DImode;
8705 : 22190 : srcmem = change_address (srcmem, mode, srcptr);
8706 : : }
8707 : 29551 : if (issetmem && vec_value && GET_MODE_SIZE (mode) > size)
8708 : : {
8709 : : /* For memset with vector and the size is smaller than the vector
8710 : : size, first try the narrower vector, otherwise, use the
8711 : : original value. */
8712 : 1843 : machine_mode inner_mode = GET_MODE_INNER (mode);
8713 : 1843 : unsigned int nunits = size / GET_MODE_SIZE (inner_mode);
8714 : 1843 : if (nunits > 1)
8715 : : {
8716 : 364 : mode = mode_for_vector (GET_MODE_INNER (mode),
8717 : 364 : nunits).require ();
8718 : 182 : value = gen_rtx_SUBREG (mode, value, 0);
8719 : : }
8720 : : else
8721 : : {
8722 : 1661 : scalar_int_mode smode
8723 : 1661 : = smallest_int_mode_for_size (size * BITS_PER_UNIT).require ();
8724 : 4983 : gcc_assert (GET_MODE_SIZE (GET_MODE (scalar_value))
8725 : : >= GET_MODE_SIZE (smode));
8726 : 1661 : mode = smode;
8727 : 1661 : if (GET_MODE (scalar_value) == mode)
8728 : : value = scalar_value;
8729 : : else
8730 : 744 : value = gen_rtx_SUBREG (mode, scalar_value, 0);
8731 : : }
8732 : : }
8733 : 25874 : destmem = change_address (destmem, mode, destptr);
8734 : 51748 : modesize = GEN_INT (GET_MODE_SIZE (mode));
8735 : 51748 : gcc_assert (GET_MODE_SIZE (mode) <= size);
8736 : 116424 : for (n = 0; n * GET_MODE_SIZE (mode) < size; n++)
8737 : : {
8738 : 32338 : if (issetmem)
8739 : 4602 : emit_move_insn (destmem, gen_lowpart (mode, value));
8740 : : else
8741 : : {
8742 : 27736 : emit_move_insn (destmem, srcmem);
8743 : 55472 : srcmem = offset_address (srcmem, modesize, GET_MODE_SIZE (mode));
8744 : : }
8745 : 64676 : destmem = offset_address (destmem, modesize, GET_MODE_SIZE (mode));
8746 : : }
8747 : :
8748 : 25874 : destmem = offset_address (destmem, count, 1);
8749 : 51748 : destmem = offset_address (destmem, GEN_INT (-2 * size),
8750 : 25874 : GET_MODE_SIZE (mode));
8751 : 25874 : if (!issetmem)
8752 : : {
8753 : 22190 : srcmem = offset_address (srcmem, count, 1);
8754 : 44380 : srcmem = offset_address (srcmem, GEN_INT (-2 * size),
8755 : 22190 : GET_MODE_SIZE (mode));
8756 : : }
8757 : 116424 : for (n = 0; n * GET_MODE_SIZE (mode) < size; n++)
8758 : : {
8759 : 32338 : if (issetmem)
8760 : 4602 : emit_move_insn (destmem, gen_lowpart (mode, value));
8761 : : else
8762 : : {
8763 : 27736 : emit_move_insn (destmem, srcmem);
8764 : 55472 : srcmem = offset_address (srcmem, modesize, GET_MODE_SIZE (mode));
8765 : : }
8766 : 64676 : destmem = offset_address (destmem, modesize, GET_MODE_SIZE (mode));
8767 : : }
8768 : 25874 : emit_jump_insn (gen_jump (done_label));
8769 : 25874 : emit_barrier ();
8770 : :
8771 : 25874 : emit_label (label);
8772 : 25874 : LABEL_NUSES (label) = 1;
8773 : 25874 : }
8774 : :
8775 : : /* Handle small memcpy (up to SIZE that is supposed to be small power of 2.
8776 : : and get ready for the main memcpy loop by copying iniital DESIRED_ALIGN-ALIGN
8777 : : bytes and last SIZE bytes adjusitng DESTPTR/SRCPTR/COUNT in a way we can
8778 : : proceed with an loop copying SIZE bytes at once. Do moves in MODE.
8779 : : DONE_LABEL is a label after the whole copying sequence. The label is created
8780 : : on demand if *DONE_LABEL is NULL.
8781 : : MIN_SIZE is minimal size of block copied. This value gets adjusted for new
8782 : : bounds after the initial copies.
8783 : :
8784 : : DESTMEM/SRCMEM are memory expressions pointing to the copies block,
8785 : : DESTPTR/SRCPTR are pointers to the block. DYNAMIC_CHECK indicate whether
8786 : : we will dispatch to a library call for large blocks.
8787 : :
8788 : : In pseudocode we do:
8789 : :
8790 : : if (COUNT < SIZE)
8791 : : {
8792 : : Assume that SIZE is 4. Bigger sizes are handled analogously
8793 : : if (COUNT & 4)
8794 : : {
8795 : : copy 4 bytes from SRCPTR to DESTPTR
8796 : : copy 4 bytes from SRCPTR + COUNT - 4 to DESTPTR + COUNT - 4
8797 : : goto done_label
8798 : : }
8799 : : if (!COUNT)
8800 : : goto done_label;
8801 : : copy 1 byte from SRCPTR to DESTPTR
8802 : : if (COUNT & 2)
8803 : : {
8804 : : copy 2 bytes from SRCPTR to DESTPTR
8805 : : copy 2 bytes from SRCPTR + COUNT - 2 to DESTPTR + COUNT - 2
8806 : : }
8807 : : }
8808 : : else
8809 : : {
8810 : : copy at least DESIRED_ALIGN-ALIGN bytes from SRCPTR to DESTPTR
8811 : : copy SIZE bytes from SRCPTR + COUNT - SIZE to DESTPTR + COUNT -SIZE
8812 : :
8813 : : OLD_DESPTR = DESTPTR;
8814 : : Align DESTPTR up to DESIRED_ALIGN
8815 : : SRCPTR += DESTPTR - OLD_DESTPTR
8816 : : COUNT -= DEST_PTR - OLD_DESTPTR
8817 : : if (DYNAMIC_CHECK)
8818 : : Round COUNT down to multiple of SIZE
8819 : : << optional caller supplied zero size guard is here >>
8820 : : << optional caller supplied dynamic check is here >>
8821 : : << caller supplied main copy loop is here >>
8822 : : }
8823 : : done_label:
8824 : : */
8825 : : static void
8826 : 9786 : expand_set_or_cpymem_prologue_epilogue_by_misaligned_moves (rtx destmem, rtx srcmem,
8827 : : rtx *destptr, rtx *srcptr,
8828 : : machine_mode mode,
8829 : : rtx value, rtx vec_value,
8830 : : rtx *count,
8831 : : rtx_code_label **done_label,
8832 : : int size,
8833 : : int desired_align,
8834 : : int align,
8835 : : unsigned HOST_WIDE_INT *min_size,
8836 : : bool dynamic_check,
8837 : : bool issetmem)
8838 : : {
8839 : 9786 : rtx_code_label *loop_label = NULL, *label;
8840 : 9786 : int n;
8841 : 9786 : rtx modesize;
8842 : 9786 : int prolog_size = 0;
8843 : 9786 : rtx mode_value;
8844 : :
8845 : : /* Chose proper value to copy. */
8846 : 9786 : if (issetmem && VECTOR_MODE_P (mode))
8847 : : mode_value = vec_value;
8848 : : else
8849 : 9786 : mode_value = value;
8850 : 19572 : gcc_assert (GET_MODE_SIZE (mode) <= size);
8851 : :
8852 : : /* See if block is big or small, handle small blocks. */
8853 : 9786 : if (!CONST_INT_P (*count) && *min_size < (unsigned HOST_WIDE_INT)size)
8854 : : {
8855 : 6474 : int size2 = size;
8856 : 6474 : loop_label = gen_label_rtx ();
8857 : :
8858 : 6474 : if (!*done_label)
8859 : 6474 : *done_label = gen_label_rtx ();
8860 : :
8861 : 6474 : emit_cmp_and_jump_insns (*count, GEN_INT (size2), GE, 0, GET_MODE (*count),
8862 : : 1, loop_label);
8863 : 6474 : size2 >>= 1;
8864 : :
8865 : : /* Handle sizes > 3. */
8866 : 32348 : for (;size2 > 2; size2 >>= 1)
8867 : 25874 : expand_small_cpymem_or_setmem (destmem, srcmem,
8868 : : *destptr, *srcptr,
8869 : : value, vec_value,
8870 : : *count,
8871 : : size2, *done_label, issetmem);
8872 : : /* Nothing to copy? Jump to DONE_LABEL if so */
8873 : 6474 : emit_cmp_and_jump_insns (*count, const0_rtx, EQ, 0, GET_MODE (*count),
8874 : : 1, *done_label);
8875 : :
8876 : : /* Do a byte copy. */
8877 : 6474 : destmem = change_address (destmem, QImode, *destptr);
8878 : 6474 : if (issetmem)
8879 : 922 : emit_move_insn (destmem, gen_lowpart (QImode, value));
8880 : : else
8881 : : {
8882 : 5552 : srcmem = change_address (srcmem, QImode, *srcptr);
8883 : 5552 : emit_move_insn (destmem, srcmem);
8884 : : }
8885 : :
8886 : : /* Handle sizes 2 and 3. */
8887 : 6474 : label = ix86_expand_aligntest (*count, 2, false);
8888 : 6474 : destmem = change_address (destmem, HImode, *destptr);
8889 : 6474 : destmem = offset_address (destmem, *count, 1);
8890 : 6474 : destmem = offset_address (destmem, GEN_INT (-2), 2);
8891 : 6474 : if (issetmem)
8892 : 922 : emit_move_insn (destmem, gen_lowpart (HImode, value));
8893 : : else
8894 : : {
8895 : 5552 : srcmem = change_address (srcmem, HImode, *srcptr);
8896 : 5552 : srcmem = offset_address (srcmem, *count, 1);
8897 : 5552 : srcmem = offset_address (srcmem, GEN_INT (-2), 2);
8898 : 5552 : emit_move_insn (destmem, srcmem);
8899 : : }
8900 : :
8901 : 6474 : emit_label (label);
8902 : 6474 : LABEL_NUSES (label) = 1;
8903 : 6474 : emit_jump_insn (gen_jump (*done_label));
8904 : 6474 : emit_barrier ();
8905 : : }
8906 : : else
8907 : 3312 : gcc_assert (*min_size >= (unsigned HOST_WIDE_INT)size
8908 : : || UINTVAL (*count) >= (unsigned HOST_WIDE_INT)size);
8909 : :
8910 : : /* Start memcpy for COUNT >= SIZE. */
8911 : 6474 : if (loop_label)
8912 : : {
8913 : 6474 : emit_label (loop_label);
8914 : 6474 : LABEL_NUSES (loop_label) = 1;
8915 : : }
8916 : :
8917 : : /* Copy first desired_align bytes. */
8918 : 9786 : if (!issetmem)
8919 : 7184 : srcmem = change_address (srcmem, mode, *srcptr);
8920 : 9786 : destmem = change_address (destmem, mode, *destptr);
8921 : 9786 : modesize = GEN_INT (GET_MODE_SIZE (mode));
8922 : 19593 : for (n = 0; prolog_size < desired_align - align; n++)
8923 : : {
8924 : 21 : if (issetmem)
8925 : 3 : emit_move_insn (destmem, mode_value);
8926 : : else
8927 : : {
8928 : 18 : emit_move_insn (destmem, srcmem);
8929 : 36 : srcmem = offset_address (srcmem, modesize, GET_MODE_SIZE (mode));
8930 : : }
8931 : 42 : destmem = offset_address (destmem, modesize, GET_MODE_SIZE (mode));
8932 : 42 : prolog_size += GET_MODE_SIZE (mode);
8933 : : }
8934 : :
8935 : :
8936 : : /* Copy last SIZE bytes. */
8937 : 9786 : destmem = offset_address (destmem, *count, 1);
8938 : 9786 : destmem = offset_address (destmem,
8939 : 9786 : GEN_INT (-size - prolog_size),
8940 : : 1);
8941 : 9786 : if (issetmem)
8942 : 2602 : emit_move_insn (destmem, mode_value);
8943 : : else
8944 : : {
8945 : 7184 : srcmem = offset_address (srcmem, *count, 1);
8946 : 7184 : srcmem = offset_address (srcmem,
8947 : : GEN_INT (-size - prolog_size),
8948 : : 1);
8949 : 7184 : emit_move_insn (destmem, srcmem);
8950 : : }
8951 : 76662 : for (n = 1; n * GET_MODE_SIZE (mode) < size; n++)
8952 : : {
8953 : 28545 : destmem = offset_address (destmem, modesize, 1);
8954 : 28545 : if (issetmem)
8955 : 7620 : emit_move_insn (destmem, mode_value);
8956 : : else
8957 : : {
8958 : 20925 : srcmem = offset_address (srcmem, modesize, 1);
8959 : 20925 : emit_move_insn (destmem, srcmem);
8960 : : }
8961 : : }
8962 : :
8963 : : /* Align destination. */
8964 : 9786 : if (desired_align > 1 && desired_align > align)
8965 : : {
8966 : 21 : rtx saveddest = *destptr;
8967 : :
8968 : 21 : gcc_assert (desired_align <= size);
8969 : : /* Align destptr up, place it to new register. */
8970 : 21 : *destptr = expand_simple_binop (GET_MODE (*destptr), PLUS, *destptr,
8971 : : GEN_INT (prolog_size),
8972 : : NULL_RTX, 1, OPTAB_DIRECT);
8973 : 21 : if (REG_P (*destptr) && REG_P (saveddest) && REG_POINTER (saveddest))
8974 : 21 : REG_POINTER (*destptr) = 1;
8975 : 21 : *destptr = expand_simple_binop (GET_MODE (*destptr), AND, *destptr,
8976 : 21 : GEN_INT (-desired_align),
8977 : : *destptr, 1, OPTAB_DIRECT);
8978 : : /* See how many bytes we skipped. */
8979 : 21 : saveddest = expand_simple_binop (GET_MODE (*destptr), MINUS, saveddest,
8980 : : *destptr,
8981 : : NULL_RTX, 1, OPTAB_DIRECT);
8982 : : /* Adjust srcptr and count. */
8983 : 21 : if (!issetmem)
8984 : 18 : *srcptr = expand_simple_binop (GET_MODE (*srcptr), MINUS, *srcptr,
8985 : : saveddest, *srcptr, 1, OPTAB_DIRECT);
8986 : 21 : *count = expand_simple_binop (GET_MODE (*count), PLUS, *count,
8987 : : saveddest, *count, 1, OPTAB_DIRECT);
8988 : : /* We copied at most size + prolog_size. */
8989 : 21 : if (*min_size > (unsigned HOST_WIDE_INT)(size + prolog_size))
8990 : 14 : *min_size
8991 : 14 : = ROUND_DOWN (*min_size - size, (unsigned HOST_WIDE_INT)size);
8992 : : else
8993 : 7 : *min_size = 0;
8994 : :
8995 : : /* Our loops always round down the block size, but for dispatch to
8996 : : library we need precise value. */
8997 : 21 : if (dynamic_check)
8998 : 21 : *count = expand_simple_binop (GET_MODE (*count), AND, *count,
8999 : : GEN_INT (-size), *count, 1, OPTAB_DIRECT);
9000 : : }
9001 : : else
9002 : : {
9003 : 9765 : gcc_assert (prolog_size == 0);
9004 : : /* Decrease count, so we won't end up copying last word twice. */
9005 : 9765 : if (!CONST_INT_P (*count))
9006 : 6474 : *count = expand_simple_binop (GET_MODE (*count), PLUS, *count,
9007 : : constm1_rtx, *count, 1, OPTAB_DIRECT);
9008 : : else
9009 : 3291 : *count = GEN_INT (ROUND_DOWN (UINTVAL (*count) - 1,
9010 : : (unsigned HOST_WIDE_INT)size));
9011 : 9765 : if (*min_size)
9012 : 9157 : *min_size = ROUND_DOWN (*min_size - 1, (unsigned HOST_WIDE_INT)size);
9013 : : }
9014 : 9786 : }
9015 : :
9016 : :
9017 : : /* This function is like the previous one, except here we know how many bytes
9018 : : need to be copied. That allows us to update alignment not only of DST, which
9019 : : is returned, but also of SRC, which is passed as a pointer for that
9020 : : reason. */
9021 : : static rtx
9022 : 0 : expand_set_or_cpymem_constant_prologue (rtx dst, rtx *srcp, rtx destreg,
9023 : : rtx srcreg, rtx value, rtx vec_value,
9024 : : int desired_align, int align_bytes,
9025 : : bool issetmem)
9026 : : {
9027 : 0 : rtx src = NULL;
9028 : 0 : rtx orig_dst = dst;
9029 : 0 : rtx orig_src = NULL;
9030 : 0 : int piece_size = 1;
9031 : 0 : int copied_bytes = 0;
9032 : :
9033 : 0 : if (!issetmem)
9034 : : {
9035 : 0 : gcc_assert (srcp != NULL);
9036 : 0 : src = *srcp;
9037 : 0 : orig_src = src;
9038 : : }
9039 : :
9040 : 0 : for (piece_size = 1;
9041 : 0 : piece_size <= desired_align && copied_bytes < align_bytes;
9042 : 0 : piece_size <<= 1)
9043 : : {
9044 : 0 : if (align_bytes & piece_size)
9045 : : {
9046 : 0 : if (issetmem)
9047 : : {
9048 : 0 : if (vec_value && piece_size > GET_MODE_SIZE (GET_MODE (value)))
9049 : 0 : dst = emit_memset (dst, destreg, vec_value, piece_size);
9050 : : else
9051 : 0 : dst = emit_memset (dst, destreg, value, piece_size);
9052 : : }
9053 : : else
9054 : 0 : dst = emit_memmov (dst, &src, destreg, srcreg, piece_size);
9055 : 0 : copied_bytes += piece_size;
9056 : : }
9057 : : }
9058 : 0 : if (MEM_ALIGN (dst) < (unsigned int) desired_align * BITS_PER_UNIT)
9059 : 0 : set_mem_align (dst, desired_align * BITS_PER_UNIT);
9060 : 0 : if (MEM_SIZE_KNOWN_P (orig_dst))
9061 : 0 : set_mem_size (dst, MEM_SIZE (orig_dst) - align_bytes);
9062 : :
9063 : 0 : if (!issetmem)
9064 : : {
9065 : 0 : int src_align_bytes = get_mem_align_offset (src, desired_align
9066 : : * BITS_PER_UNIT);
9067 : 0 : if (src_align_bytes >= 0)
9068 : 0 : src_align_bytes = desired_align - src_align_bytes;
9069 : 0 : if (src_align_bytes >= 0)
9070 : : {
9071 : : unsigned int src_align;
9072 : 0 : for (src_align = desired_align; src_align >= 2; src_align >>= 1)
9073 : : {
9074 : 0 : if ((src_align_bytes & (src_align - 1))
9075 : 0 : == (align_bytes & (src_align - 1)))
9076 : : break;
9077 : : }
9078 : 0 : if (src_align > (unsigned int) desired_align)
9079 : : src_align = desired_align;
9080 : 0 : if (MEM_ALIGN (src) < src_align * BITS_PER_UNIT)
9081 : 0 : set_mem_align (src, src_align * BITS_PER_UNIT);
9082 : : }
9083 : 0 : if (MEM_SIZE_KNOWN_P (orig_src))
9084 : 0 : set_mem_size (src, MEM_SIZE (orig_src) - align_bytes);
9085 : 0 : *srcp = src;
9086 : : }
9087 : :
9088 : 0 : return dst;
9089 : : }
9090 : :
9091 : : /* Return true if ALG can be used in current context.
9092 : : Assume we expand memset if MEMSET is true. */
9093 : : static bool
9094 : 817417 : alg_usable_p (enum stringop_alg alg, bool memset,
9095 : : addr_space_t dst_as, addr_space_t src_as)
9096 : : {
9097 : 817417 : if (alg == no_stringop)
9098 : : return false;
9099 : : /* It is not possible to use a library call if we have non-default
9100 : : address space. We can do better than the generic byte-at-a-time
9101 : : loop, used as a fallback. */
9102 : 817417 : if (alg == libcall &&
9103 : 458687 : !(ADDR_SPACE_GENERIC_P (dst_as) && ADDR_SPACE_GENERIC_P (src_as)))
9104 : : return false;
9105 : 817410 : if (alg == vector_loop)
9106 : 361499 : return TARGET_SSE || TARGET_AVX;
9107 : : /* Algorithms using the rep prefix want at least edi and ecx;
9108 : : additionally, memset wants eax and memcpy wants esi. Don't
9109 : : consider such algorithms if the user has appropriated those
9110 : : registers for their own purposes, or if we have the destination
9111 : : in the non-default address space, since string insns cannot
9112 : : override the destination segment. */
9113 : 636629 : if (alg == rep_prefix_1_byte
9114 : : || alg == rep_prefix_4_byte
9115 : 636629 : || alg == rep_prefix_8_byte)
9116 : : {
9117 : 31450 : if (fixed_regs[CX_REG]
9118 : 31446 : || fixed_regs[DI_REG]
9119 : 31442 : || (memset ? fixed_regs[AX_REG] : fixed_regs[SI_REG])
9120 : 31438 : || !ADDR_SPACE_GENERIC_P (dst_as)
9121 : 62888 : || !(ADDR_SPACE_GENERIC_P (src_as) || Pmode == word_mode))
9122 : 12 : return false;
9123 : : }
9124 : : return true;
9125 : : }
9126 : :
9127 : : /* Given COUNT and EXPECTED_SIZE, decide on codegen of string operation. */
9128 : : static enum stringop_alg
9129 : 162124 : decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size,
9130 : : unsigned HOST_WIDE_INT min_size, unsigned HOST_WIDE_INT max_size,
9131 : : bool memset, bool zero_memset, addr_space_t dst_as,
9132 : : addr_space_t src_as, int *dynamic_check, bool *noalign, bool recur)
9133 : : {
9134 : 162124 : const struct stringop_algs *algs;
9135 : 162124 : bool optimize_for_speed;
9136 : 162124 : int max = 0;
9137 : 162124 : const struct processor_costs *cost;
9138 : 162124 : int i;
9139 : 162124 : bool any_alg_usable_p = false;
9140 : :
9141 : 162124 : *noalign = false;
9142 : 162124 : *dynamic_check = -1;
9143 : :
9144 : : /* Even if the string operation call is cold, we still might spend a lot
9145 : : of time processing large blocks. */
9146 : 162124 : if (optimize_function_for_size_p (cfun)
9147 : 162124 : || (optimize_insn_for_size_p ()
9148 : 8325 : && (max_size < 256
9149 : 2827 : || (expected_size != -1 && expected_size < 256))))
9150 : : optimize_for_speed = false;
9151 : : else
9152 : 146456 : optimize_for_speed = true;
9153 : :
9154 : 146456 : cost = optimize_for_speed ? ix86_cost : &ix86_size_cost;
9155 : 162124 : if (memset)
9156 : 52720 : algs = &cost->memset[TARGET_64BIT != 0];
9157 : : else
9158 : 118071 : algs = &cost->memcpy[TARGET_64BIT != 0];
9159 : :
9160 : : /* See maximal size for user defined algorithm. */
9161 : 810620 : for (i = 0; i < MAX_STRINGOP_ALGS; i++)
9162 : : {
9163 : 648496 : enum stringop_alg candidate = algs->size[i].alg;
9164 : 648496 : bool usable = alg_usable_p (candidate, memset, dst_as, src_as);
9165 : 648496 : any_alg_usable_p |= usable;
9166 : :
9167 : 648496 : if (candidate != libcall && candidate && usable)
9168 : 308513 : max = algs->size[i].max;
9169 : : }
9170 : :
9171 : : /* If expected size is not known but max size is small enough
9172 : : so inline version is a win, set expected size into
9173 : : the range. */
9174 : 162124 : if (((max > 1 && (unsigned HOST_WIDE_INT) max >= max_size) || max == -1)
9175 : 35012 : && expected_size == -1)
9176 : 17972 : expected_size = min_size / 2 + max_size / 2;
9177 : :
9178 : : /* If user specified the algorithm, honor it if possible. */
9179 : 162124 : if (ix86_stringop_alg != no_stringop
9180 : 162124 : && alg_usable_p (ix86_stringop_alg, memset, dst_as, src_as))
9181 : : return ix86_stringop_alg;
9182 : : /* rep; movq or rep; movl is the smallest variant. */
9183 : 162015 : else if (!optimize_for_speed)
9184 : : {
9185 : 15588 : *noalign = true;
9186 : 15588 : if (!count || (count & 3) || (memset && !zero_memset))
9187 : 5552 : return alg_usable_p (rep_prefix_1_byte, memset, dst_as, src_as)
9188 : 5552 : ? rep_prefix_1_byte : loop_1_byte;
9189 : : else
9190 : 10036 : return alg_usable_p (rep_prefix_4_byte, memset, dst_as, src_as)
9191 : 10036 : ? rep_prefix_4_byte : loop;
9192 : : }
9193 : : /* Very tiny blocks are best handled via the loop, REP is expensive to
9194 : : setup. */
9195 : 146427 : else if (expected_size != -1 && expected_size < 4)
9196 : : return loop_1_byte;
9197 : 142731 : else if (expected_size != -1)
9198 : : {
9199 : : enum stringop_alg alg = libcall;
9200 : : bool alg_noalign = false;
9201 : 186589 : for (i = 0; i < MAX_STRINGOP_ALGS; i++)
9202 : : {
9203 : : /* We get here if the algorithms that were not libcall-based
9204 : : were rep-prefix based and we are unable to use rep prefixes
9205 : : based on global register usage. Break out of the loop and
9206 : : use the heuristic below. */
9207 : 183656 : if (algs->size[i].max == 0)
9208 : : break;
9209 : 183656 : if (algs->size[i].max >= expected_size || algs->size[i].max == -1)
9210 : : {
9211 : 76392 : enum stringop_alg candidate = algs->size[i].alg;
9212 : :
9213 : 76392 : if (candidate != libcall
9214 : 76392 : && alg_usable_p (candidate, memset, dst_as, src_as))
9215 : : {
9216 : 19803 : alg = candidate;
9217 : 19803 : alg_noalign = algs->size[i].noalign;
9218 : : }
9219 : : /* Honor TARGET_INLINE_ALL_STRINGOPS by picking
9220 : : last non-libcall inline algorithm. */
9221 : 76392 : if (TARGET_INLINE_ALL_STRINGOPS)
9222 : : {
9223 : : /* When the current size is best to be copied by a libcall,
9224 : : but we are still forced to inline, run the heuristic below
9225 : : that will pick code for medium sized blocks. */
9226 : 10992 : if (alg != libcall)
9227 : : {
9228 : 5117 : *noalign = alg_noalign;
9229 : 5117 : return alg;
9230 : : }
9231 : 5875 : else if (!any_alg_usable_p)
9232 : : break;
9233 : : }
9234 : 65400 : else if (alg_usable_p (candidate, memset, dst_as, src_as)
9235 : 65400 : && !(TARGET_PREFER_KNOWN_REP_MOVSB_STOSB
9236 : 22 : && candidate == rep_prefix_1_byte
9237 : : /* NB: If min_size != max_size, size is
9238 : : unknown. */
9239 : 22 : && min_size != max_size))
9240 : : {
9241 : 65381 : *noalign = algs->size[i].noalign;
9242 : 65381 : return candidate;
9243 : : }
9244 : : }
9245 : : }
9246 : : }
9247 : : /* When asked to inline the call anyway, try to pick meaningful choice.
9248 : : We look for maximal size of block that is faster to copy by hand and
9249 : : take blocks of at most of that size guessing that average size will
9250 : : be roughly half of the block.
9251 : :
9252 : : If this turns out to be bad, we might simply specify the preferred
9253 : : choice in ix86_costs. */
9254 : 68004 : if ((TARGET_INLINE_ALL_STRINGOPS || TARGET_INLINE_STRINGOPS_DYNAMICALLY)
9255 : 72239 : && (algs->unknown_size == libcall
9256 : 0 : || !alg_usable_p (algs->unknown_size, memset, dst_as, src_as)))
9257 : : {
9258 : 4235 : enum stringop_alg alg;
9259 : 4235 : HOST_WIDE_INT new_expected_size = (max > 0 ? max : 4096) / 2;
9260 : :
9261 : : /* If there aren't any usable algorithms or if recursing already,
9262 : : then recursing on smaller sizes or same size isn't going to
9263 : : find anything. Just return the simple byte-at-a-time copy loop. */
9264 : 4235 : if (!any_alg_usable_p || recur)
9265 : : {
9266 : : /* Pick something reasonable. */
9267 : 0 : if (TARGET_INLINE_STRINGOPS_DYNAMICALLY && !recur)
9268 : 0 : *dynamic_check = 128;
9269 : 0 : return loop_1_byte;
9270 : : }
9271 : 4235 : alg = decide_alg (count, new_expected_size, min_size, max_size,
9272 : : memset, zero_memset, dst_as, src_as,
9273 : : dynamic_check, noalign, true);
9274 : 4235 : gcc_assert (*dynamic_check == -1);
9275 : 4235 : if (TARGET_INLINE_STRINGOPS_DYNAMICALLY)
9276 : 8 : *dynamic_check = max;
9277 : : else
9278 : 4227 : gcc_assert (alg != libcall);
9279 : 4235 : return alg;
9280 : : }
9281 : :
9282 : : /* Try to use some reasonable fallback algorithm. Note that for
9283 : : non-default address spaces we default to a loop instead of
9284 : : a libcall. */
9285 : :
9286 : 67998 : bool have_as = !(ADDR_SPACE_GENERIC_P (dst_as)
9287 : : && ADDR_SPACE_GENERIC_P (src_as));
9288 : :
9289 : 67998 : return (alg_usable_p (algs->unknown_size, memset, dst_as, src_as)
9290 : 67998 : ? algs->unknown_size : have_as ? loop : libcall);
9291 : : }
9292 : :
9293 : : /* Decide on alignment. We know that the operand is already aligned to ALIGN
9294 : : (ALIGN can be based on profile feedback and thus it is not 100% guaranteed). */
9295 : : static int
9296 : 33252 : decide_alignment (int align,
9297 : : enum stringop_alg alg,
9298 : : int expected_size,
9299 : : machine_mode move_mode)
9300 : : {
9301 : 33252 : int desired_align = 0;
9302 : :
9303 : 33252 : gcc_assert (alg != no_stringop);
9304 : :
9305 : 33252 : if (alg == libcall)
9306 : : return 0;
9307 : 33252 : if (move_mode == VOIDmode)
9308 : : return 0;
9309 : :
9310 : 33252 : desired_align = GET_MODE_SIZE (move_mode);
9311 : : /* PentiumPro has special logic triggering for 8 byte aligned blocks.
9312 : : copying whole cacheline at once. */
9313 : 33252 : if (TARGET_CPU_P (PENTIUMPRO)
9314 : 0 : && (alg == rep_prefix_4_byte || alg == rep_prefix_1_byte))
9315 : 33252 : desired_align = 8;
9316 : :
9317 : 33252 : if (optimize_size)
9318 : 9096 : desired_align = 1;
9319 : 33252 : if (desired_align < align)
9320 : : desired_align = align;
9321 : 33252 : if (expected_size != -1 && expected_size < 4)
9322 : 0 : desired_align = align;
9323 : :
9324 : : return desired_align;
9325 : : }
9326 : :
9327 : :
9328 : : /* Helper function for memcpy. For QImode value 0xXY produce
9329 : : 0xXYXYXYXY of wide specified by MODE. This is essentially
9330 : : a * 0x10101010, but we can do slightly better than
9331 : : synth_mult by unwinding the sequence by hand on CPUs with
9332 : : slow multiply. */
9333 : : static rtx
9334 : 17206 : promote_duplicated_reg (machine_mode mode, rtx val)
9335 : : {
9336 : 17206 : if (val == const0_rtx)
9337 : 15112 : return copy_to_mode_reg (mode, CONST0_RTX (mode));
9338 : :
9339 : 2094 : machine_mode valmode = GET_MODE (val);
9340 : 2094 : if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT)
9341 : : {
9342 : : /* Duplicate the scalar value for integer vector. */
9343 : 1677 : gcc_assert ((val == const0_rtx || val == constm1_rtx)
9344 : : || GET_MODE_INNER (mode) == valmode);
9345 : 850 : rtx dup = gen_reg_rtx (mode);
9346 : 850 : bool ok = ix86_expand_vector_init_duplicate (false, mode, dup,
9347 : : val);
9348 : 850 : gcc_assert (ok);
9349 : : return dup;
9350 : : }
9351 : :
9352 : 1244 : rtx tmp;
9353 : 1244 : int nops = mode == DImode ? 3 : 2;
9354 : :
9355 : 30 : gcc_assert (mode == SImode || mode == DImode);
9356 : 1244 : if (CONST_INT_P (val))
9357 : : {
9358 : 857 : HOST_WIDE_INT v = INTVAL (val) & 255;
9359 : :
9360 : 857 : v |= v << 8;
9361 : 857 : v |= v << 16;
9362 : 857 : if (mode == DImode)
9363 : 835 : v |= (v << 16) << 16;
9364 : 857 : return copy_to_mode_reg (mode, gen_int_mode (v, mode));
9365 : : }
9366 : :
9367 : 387 : if (valmode == VOIDmode)
9368 : : valmode = QImode;
9369 : 387 : if (valmode != QImode)
9370 : 0 : val = gen_lowpart (QImode, val);
9371 : 387 : if (mode == QImode)
9372 : : return val;
9373 : 387 : if (!TARGET_PARTIAL_REG_STALL)
9374 : 387 : nops--;
9375 : 387 : if (ix86_cost->mult_init[mode == DImode ? 3 : 2]
9376 : 387 : + ix86_cost->mult_bit * (mode == DImode ? 8 : 4)
9377 : 387 : <= (ix86_cost->shift_const + ix86_cost->add) * nops
9378 : 387 : + (COSTS_N_INSNS (TARGET_PARTIAL_REG_STALL == 0)))
9379 : : {
9380 : 387 : rtx reg = convert_modes (mode, QImode, val, true);
9381 : 387 : tmp = promote_duplicated_reg (mode, const1_rtx);
9382 : 387 : return expand_simple_binop (mode, MULT, reg, tmp, NULL, 1,
9383 : 387 : OPTAB_DIRECT);
9384 : : }
9385 : : else
9386 : : {
9387 : 0 : rtx reg = convert_modes (mode, QImode, val, true);
9388 : :
9389 : 0 : if (!TARGET_PARTIAL_REG_STALL)
9390 : 0 : emit_insn (gen_insv_1 (mode, reg, reg));
9391 : : else
9392 : : {
9393 : 0 : tmp = expand_simple_binop (mode, ASHIFT, reg, GEN_INT (8),
9394 : : NULL, 1, OPTAB_DIRECT);
9395 : 0 : reg = expand_simple_binop (mode, IOR, reg, tmp, reg, 1,
9396 : : OPTAB_DIRECT);
9397 : : }
9398 : 0 : tmp = expand_simple_binop (mode, ASHIFT, reg, GEN_INT (16),
9399 : : NULL, 1, OPTAB_DIRECT);
9400 : 0 : reg = expand_simple_binop (mode, IOR, reg, tmp, reg, 1, OPTAB_DIRECT);
9401 : 0 : if (mode == SImode)
9402 : : return reg;
9403 : 0 : tmp = expand_simple_binop (mode, ASHIFT, reg, GEN_INT (32),
9404 : : NULL, 1, OPTAB_DIRECT);
9405 : 0 : reg = expand_simple_binop (mode, IOR, reg, tmp, reg, 1, OPTAB_DIRECT);
9406 : 0 : return reg;
9407 : : }
9408 : : }
9409 : :
9410 : : /* Duplicate value VAL using promote_duplicated_reg into maximal size that will
9411 : : be needed by main loop copying SIZE_NEEDED chunks and prologue getting
9412 : : alignment from ALIGN to DESIRED_ALIGN. */
9413 : : static rtx
9414 : 12569 : promote_duplicated_reg_to_size (rtx val, int size_needed, int desired_align,
9415 : : int align)
9416 : : {
9417 : 12569 : rtx promoted_val;
9418 : :
9419 : 12569 : if (TARGET_64BIT
9420 : 11069 : && (size_needed > 4 || (desired_align > align && desired_align > 4)))
9421 : 4648 : promoted_val = promote_duplicated_reg (DImode, val);
9422 : 7921 : else if (size_needed > 2 || (desired_align > align && desired_align > 2))
9423 : 6130 : promoted_val = promote_duplicated_reg (SImode, val);
9424 : 1791 : else if (size_needed > 1 || (desired_align > align && desired_align > 1))
9425 : 0 : promoted_val = promote_duplicated_reg (HImode, val);
9426 : : else
9427 : : promoted_val = val;
9428 : :
9429 : 12569 : return promoted_val;
9430 : : }
9431 : :
9432 : : /* Copy the address to a Pmode register. This is used for x32 to
9433 : : truncate DImode TLS address to a SImode register. */
9434 : :
9435 : : static rtx
9436 : 65739 : ix86_copy_addr_to_reg (rtx addr)
9437 : : {
9438 : 65739 : rtx reg;
9439 : 70305 : if (GET_MODE (addr) == Pmode || GET_MODE (addr) == VOIDmode)
9440 : : {
9441 : 65739 : reg = copy_addr_to_reg (addr);
9442 : 65739 : REG_POINTER (reg) = 1;
9443 : 65739 : return reg;
9444 : : }
9445 : : else
9446 : : {
9447 : 0 : gcc_assert (GET_MODE (addr) == DImode && Pmode == SImode);
9448 : 0 : reg = copy_to_mode_reg (DImode, addr);
9449 : 0 : REG_POINTER (reg) = 1;
9450 : 0 : return gen_rtx_SUBREG (SImode, reg, 0);
9451 : : }
9452 : : }
9453 : :
9454 : : /* Expand string move (memcpy) ot store (memset) operation. Use i386 string
9455 : : operations when profitable. The code depends upon architecture, block size
9456 : : and alignment, but always has one of the following overall structures:
9457 : :
9458 : : Aligned move sequence:
9459 : :
9460 : : 1) Prologue guard: Conditional that jumps up to epilogues for small
9461 : : blocks that can be handled by epilogue alone. This is faster
9462 : : but also needed for correctness, since prologue assume the block
9463 : : is larger than the desired alignment.
9464 : :
9465 : : Optional dynamic check for size and libcall for large
9466 : : blocks is emitted here too, with -minline-stringops-dynamically.
9467 : :
9468 : : 2) Prologue: copy first few bytes in order to get destination
9469 : : aligned to DESIRED_ALIGN. It is emitted only when ALIGN is less
9470 : : than DESIRED_ALIGN and up to DESIRED_ALIGN - ALIGN bytes can be
9471 : : copied. We emit either a jump tree on power of two sized
9472 : : blocks, or a byte loop.
9473 : :
9474 : : 3) Main body: the copying loop itself, copying in SIZE_NEEDED chunks
9475 : : with specified algorithm.
9476 : :
9477 : : 4) Epilogue: code copying tail of the block that is too small to be
9478 : : handled by main body (or up to size guarded by prologue guard).
9479 : :
9480 : : Misaligned move sequence
9481 : :
9482 : : 1) missaligned move prologue/epilogue containing:
9483 : : a) Prologue handling small memory blocks and jumping to done_label
9484 : : (skipped if blocks are known to be large enough)
9485 : : b) Signle move copying first DESIRED_ALIGN-ALIGN bytes if alignment is
9486 : : needed by single possibly misaligned move
9487 : : (skipped if alignment is not needed)
9488 : : c) Copy of last SIZE_NEEDED bytes by possibly misaligned moves
9489 : :
9490 : : 2) Zero size guard dispatching to done_label, if needed
9491 : :
9492 : : 3) dispatch to library call, if needed,
9493 : :
9494 : : 3) Main body: the copying loop itself, copying in SIZE_NEEDED chunks
9495 : : with specified algorithm. */
9496 : : bool
9497 : 143843 : ix86_expand_set_or_cpymem (rtx dst, rtx src, rtx count_exp, rtx val_exp,
9498 : : rtx align_exp, rtx expected_align_exp,
9499 : : rtx expected_size_exp, rtx min_size_exp,
9500 : : rtx max_size_exp, rtx probable_max_size_exp,
9501 : : bool issetmem)
9502 : : {
9503 : 143843 : rtx destreg;
9504 : 143843 : rtx srcreg = NULL;
9505 : 143843 : rtx_code_label *label = NULL;
9506 : 143843 : rtx tmp;
9507 : 143843 : rtx_code_label *jump_around_label = NULL;
9508 : 143843 : HOST_WIDE_INT align = 1;
9509 : 143843 : unsigned HOST_WIDE_INT count = 0;
9510 : 143843 : HOST_WIDE_INT expected_size = -1;
9511 : 143843 : int size_needed = 0, epilogue_size_needed;
9512 : 143843 : int desired_align = 0, align_bytes = 0;
9513 : 143843 : enum stringop_alg alg;
9514 : 143843 : rtx promoted_val = NULL;
9515 : 143843 : rtx vec_promoted_val = NULL;
9516 : 143843 : bool force_loopy_epilogue = false;
9517 : 143843 : int dynamic_check;
9518 : 143843 : bool need_zero_guard = false;
9519 : 143843 : bool noalign;
9520 : 143843 : machine_mode move_mode = VOIDmode;
9521 : 143843 : int unroll_factor = 1;
9522 : : /* TODO: Once value ranges are available, fill in proper data. */
9523 : 143843 : unsigned HOST_WIDE_INT min_size = HOST_WIDE_INT_0U;
9524 : 143843 : unsigned HOST_WIDE_INT max_size = HOST_WIDE_INT_M1U;
9525 : 143843 : unsigned HOST_WIDE_INT probable_max_size = HOST_WIDE_INT_M1U;
9526 : 143843 : bool misaligned_prologue_used = false;
9527 : 143843 : addr_space_t dst_as, src_as = ADDR_SPACE_GENERIC;
9528 : :
9529 : 143843 : if (CONST_INT_P (align_exp))
9530 : 143843 : align = INTVAL (align_exp);
9531 : : /* i386 can do misaligned access on reasonably increased cost. */
9532 : 143843 : if (CONST_INT_P (expected_align_exp)
9533 : 143843 : && INTVAL (expected_align_exp) > align)
9534 : : align = INTVAL (expected_align_exp);
9535 : : /* ALIGN is the minimum of destination and source alignment, but we care here
9536 : : just about destination alignment. */
9537 : 137563 : else if (!issetmem
9538 : 226974 : && MEM_ALIGN (dst) > (unsigned HOST_WIDE_INT) align * BITS_PER_UNIT)
9539 : 2978 : align = MEM_ALIGN (dst) / BITS_PER_UNIT;
9540 : :
9541 : 143843 : if (CONST_INT_P (count_exp))
9542 : : {
9543 : 68571 : min_size = max_size = probable_max_size = count = expected_size
9544 : 68571 : = INTVAL (count_exp);
9545 : : /* When COUNT is 0, there is nothing to do. */
9546 : 68571 : if (!count)
9547 : : return true;
9548 : : }
9549 : : else
9550 : : {
9551 : 75272 : if (min_size_exp)
9552 : 75272 : min_size = INTVAL (min_size_exp);
9553 : 75272 : if (max_size_exp)
9554 : 60061 : max_size = INTVAL (max_size_exp);
9555 : 75272 : if (probable_max_size_exp)
9556 : 61947 : probable_max_size = INTVAL (probable_max_size_exp);
9557 : 75272 : if (CONST_INT_P (expected_size_exp))
9558 : 75272 : expected_size = INTVAL (expected_size_exp);
9559 : : }
9560 : :
9561 : : /* Make sure we don't need to care about overflow later on. */
9562 : 143841 : if (count > (HOST_WIDE_INT_1U << 30))
9563 : : return false;
9564 : :
9565 : 143667 : dst_as = MEM_ADDR_SPACE (dst);
9566 : 143667 : if (!issetmem)
9567 : 95580 : src_as = MEM_ADDR_SPACE (src);
9568 : :
9569 : : /* Step 0: Decide on preferred algorithm, desired alignment and
9570 : : size of chunks to be copied by main loop. */
9571 : 143667 : alg = decide_alg (count, expected_size, min_size, probable_max_size,
9572 : 48087 : issetmem, issetmem && val_exp == const0_rtx,
9573 : : dst_as, src_as, &dynamic_check, &noalign, false);
9574 : :
9575 : 143667 : if (dump_file)
9576 : 7 : fprintf (dump_file, "Selected stringop expansion strategy: %s\n",
9577 : 7 : stringop_alg_names[alg]);
9578 : :
9579 : 143667 : if (alg == libcall)
9580 : : return false;
9581 : 33252 : gcc_assert (alg != no_stringop);
9582 : :
9583 : 33252 : if (!count)
9584 : 15483 : count_exp = copy_to_mode_reg (GET_MODE (count_exp), count_exp);
9585 : 33252 : destreg = ix86_copy_addr_to_reg (XEXP (dst, 0));
9586 : 33252 : if (!issetmem)
9587 : 20683 : srcreg = ix86_copy_addr_to_reg (XEXP (src, 0));
9588 : :
9589 : 33252 : bool aligned_dstmem = false;
9590 : 33252 : unsigned int nunits = issetmem ? STORE_MAX_PIECES : MOVE_MAX;
9591 : 33252 : bool single_insn_p = count && count <= nunits;
9592 : 33252 : if (single_insn_p)
9593 : : {
9594 : : /* If it can be done with a single instruction, use vector
9595 : : instruction and don't align destination. */
9596 : 6 : alg = vector_loop;
9597 : 6 : noalign = true;
9598 : 6 : dynamic_check = -1;
9599 : : }
9600 : :
9601 : 33252 : unroll_factor = 1;
9602 : 33252 : move_mode = word_mode;
9603 : 33252 : switch (alg)
9604 : : {
9605 : 0 : case libcall:
9606 : 0 : case no_stringop:
9607 : 0 : case last_alg:
9608 : 0 : gcc_unreachable ();
9609 : 2529 : case loop_1_byte:
9610 : 2529 : need_zero_guard = true;
9611 : 2529 : move_mode = QImode;
9612 : 2529 : break;
9613 : 45 : case loop:
9614 : 45 : need_zero_guard = true;
9615 : 45 : break;
9616 : 20 : case unrolled_loop:
9617 : 20 : need_zero_guard = true;
9618 : 20 : unroll_factor = (TARGET_64BIT ? 4 : 2);
9619 : : break;
9620 : 15852 : case vector_loop:
9621 : 15852 : need_zero_guard = true;
9622 : 15852 : unroll_factor = 4;
9623 : : /* Get the vector mode to move STORE_MAX_PIECES/MOVE_MAX bytes. */
9624 : 15852 : nunits /= GET_MODE_SIZE (word_mode);
9625 : 15852 : if (nunits > 1)
9626 : : {
9627 : 15848 : move_mode = mode_for_vector (word_mode, nunits).require ();
9628 : 15848 : gcc_assert (optab_handler (mov_optab, move_mode)
9629 : : != CODE_FOR_nothing);
9630 : : }
9631 : : break;
9632 : 24 : case rep_prefix_8_byte:
9633 : 24 : move_mode = DImode;
9634 : 24 : break;
9635 : 9937 : case rep_prefix_4_byte:
9636 : 9937 : move_mode = SImode;
9637 : 9937 : break;
9638 : 4845 : case rep_prefix_1_byte:
9639 : 4845 : move_mode = QImode;
9640 : 4845 : break;
9641 : : }
9642 : 33252 : size_needed = GET_MODE_SIZE (move_mode) * unroll_factor;
9643 : 33252 : epilogue_size_needed = size_needed;
9644 : :
9645 : : /* If we are going to call any library calls conditionally, make sure any
9646 : : pending stack adjustment happen before the first conditional branch,
9647 : : otherwise they will be emitted before the library call only and won't
9648 : : happen from the other branches. */
9649 : 33252 : if (dynamic_check != -1)
9650 : 7 : do_pending_stack_adjust ();
9651 : :
9652 : 33252 : desired_align = decide_alignment (align, alg, expected_size, move_mode);
9653 : 33252 : if (!TARGET_ALIGN_STRINGOPS || noalign)
9654 : 30639 : align = desired_align;
9655 : :
9656 : : /* Step 1: Prologue guard. */
9657 : :
9658 : : /* Alignment code needs count to be in register. */
9659 : 33252 : if (CONST_INT_P (count_exp) && desired_align > align)
9660 : : {
9661 : 20 : if (INTVAL (count_exp) > desired_align
9662 : 20 : && INTVAL (count_exp) > size_needed)
9663 : : {
9664 : 20 : align_bytes
9665 : 20 : = get_mem_align_offset (dst, desired_align * BITS_PER_UNIT);
9666 : 20 : if (align_bytes <= 0)
9667 : : align_bytes = 0;
9668 : : else
9669 : 0 : align_bytes = desired_align - align_bytes;
9670 : : }
9671 : 0 : if (align_bytes == 0)
9672 : 40 : count_exp = force_reg (counter_mode (count_exp), count_exp);
9673 : : }
9674 : 33252 : gcc_assert (desired_align >= 1 && align >= 1);
9675 : :
9676 : 33252 : if (!single_insn_p)
9677 : : {
9678 : : /* Misaligned move sequences handle both prologue and epilogue
9679 : : at once. Default code generation results in a smaller code
9680 : : for large alignments and also avoids redundant job when sizes
9681 : : are known precisely. */
9682 : 33246 : misaligned_prologue_used
9683 : 66492 : = (TARGET_MISALIGNED_MOVE_STRING_PRO_EPILOGUES
9684 : 33240 : && MAX (desired_align, epilogue_size_needed) <= 32
9685 : 17132 : && desired_align <= epilogue_size_needed
9686 : 39653 : && ((desired_align > align && !align_bytes)
9687 : 6386 : || (!count && epilogue_size_needed > 1)));
9688 : :
9689 : : /* Destination is aligned after the misaligned prologue. */
9690 : 33246 : aligned_dstmem = misaligned_prologue_used;
9691 : :
9692 : 33246 : if (noalign && !misaligned_prologue_used)
9693 : : {
9694 : : /* Also use misaligned prologue if alignment isn't needed and
9695 : : destination isn't aligned. Since alignment isn't needed,
9696 : : the destination after prologue won't be aligned. */
9697 : 30633 : aligned_dstmem = (GET_MODE_ALIGNMENT (move_mode)
9698 : 30633 : <= MEM_ALIGN (dst));
9699 : 30633 : if (!aligned_dstmem)
9700 : 9765 : misaligned_prologue_used = true;
9701 : : }
9702 : : }
9703 : :
9704 : : /* Do the cheap promotion to allow better CSE across the
9705 : : main loop and epilogue (ie one load of the big constant in the
9706 : : front of all code.
9707 : : For now the misaligned move sequences do not have fast path
9708 : : without broadcasting. */
9709 : 33252 : if (issetmem
9710 : 12569 : && (alg == vector_loop
9711 : 6528 : || CONST_INT_P (val_exp)
9712 : 46 : || misaligned_prologue_used))
9713 : : {
9714 : 6482 : if (alg == vector_loop)
9715 : : {
9716 : 6041 : promoted_val = promote_duplicated_reg_to_size (val_exp,
9717 : 12082 : GET_MODE_SIZE (word_mode),
9718 : : desired_align, align);
9719 : : /* Duplicate the promoted scalar value if not 0 nor -1. */
9720 : 6041 : vec_promoted_val
9721 : 6041 : = promote_duplicated_reg (move_mode,
9722 : 6041 : (val_exp == const0_rtx
9723 : 850 : || val_exp == constm1_rtx)
9724 : : ? val_exp : promoted_val);
9725 : : }
9726 : : else
9727 : : {
9728 : 6482 : promoted_val = promote_duplicated_reg_to_size (val_exp, size_needed,
9729 : : desired_align, align);
9730 : : }
9731 : : }
9732 : : /* Misaligned move sequences handles both prologues and epilogues at once.
9733 : : Default code generation results in smaller code for large alignments and
9734 : : also avoids redundant job when sizes are known precisely. */
9735 : 33206 : if (misaligned_prologue_used)
9736 : : {
9737 : : /* Misaligned move prologue handled small blocks by itself. */
9738 : 9786 : expand_set_or_cpymem_prologue_epilogue_by_misaligned_moves
9739 : 9786 : (dst, src, &destreg, &srcreg,
9740 : : move_mode, promoted_val, vec_promoted_val,
9741 : : &count_exp,
9742 : : &jump_around_label,
9743 : 9786 : desired_align < align
9744 : 0 : ? MAX (desired_align, epilogue_size_needed) : epilogue_size_needed,
9745 : : desired_align, align, &min_size, dynamic_check, issetmem);
9746 : 9786 : if (!issetmem)
9747 : 7184 : src = change_address (src, BLKmode, srcreg);
9748 : 9786 : dst = change_address (dst, BLKmode, destreg);
9749 : 9786 : if (aligned_dstmem)
9750 : 21 : set_mem_align (dst, desired_align * BITS_PER_UNIT);
9751 : 9786 : epilogue_size_needed = 0;
9752 : 9786 : if (need_zero_guard
9753 : 9524 : && min_size < (unsigned HOST_WIDE_INT) size_needed)
9754 : : {
9755 : : /* It is possible that we copied enough so the main loop will not
9756 : : execute. */
9757 : 6523 : gcc_assert (size_needed > 1);
9758 : 6523 : if (jump_around_label == NULL_RTX)
9759 : 50 : jump_around_label = gen_label_rtx ();
9760 : 13046 : emit_cmp_and_jump_insns (count_exp,
9761 : : GEN_INT (size_needed),
9762 : : LTU, 0, counter_mode (count_exp), 1, jump_around_label);
9763 : 6523 : if (expected_size == -1
9764 : 53 : || expected_size < (desired_align - align) / 2 + size_needed)
9765 : 6471 : predict_jump (REG_BR_PROB_BASE * 20 / 100);
9766 : : else
9767 : 52 : predict_jump (REG_BR_PROB_BASE * 60 / 100);
9768 : : }
9769 : : }
9770 : : /* Ensure that alignment prologue won't copy past end of block. */
9771 : 23466 : else if (size_needed > 1 || (desired_align > 1 && desired_align > align))
9772 : : {
9773 : 16092 : epilogue_size_needed = MAX (size_needed - 1, desired_align - align);
9774 : : /* Epilogue always copies COUNT_EXP & EPILOGUE_SIZE_NEEDED bytes.
9775 : : Make sure it is power of 2. */
9776 : 16092 : epilogue_size_needed = 1 << (floor_log2 (epilogue_size_needed) + 1);
9777 : :
9778 : : /* To improve performance of small blocks, we jump around the VAL
9779 : : promoting mode. This mean that if the promoted VAL is not constant,
9780 : : we might not use it in the epilogue and have to use byte
9781 : : loop variant. */
9782 : 16092 : if (issetmem && epilogue_size_needed > 2 && !promoted_val)
9783 : 16092 : force_loopy_epilogue = true;
9784 : 16092 : if ((count && count < (unsigned HOST_WIDE_INT) epilogue_size_needed)
9785 : 16084 : || max_size < (unsigned HOST_WIDE_INT) epilogue_size_needed)
9786 : : {
9787 : : /* If main algorithm works on QImode, no epilogue is needed.
9788 : : For small sizes just don't align anything. */
9789 : 2410 : if (size_needed == 1)
9790 : 0 : desired_align = align;
9791 : : else
9792 : 2410 : goto epilogue;
9793 : : }
9794 : 13682 : else if (!count
9795 : 251 : && min_size < (unsigned HOST_WIDE_INT) epilogue_size_needed)
9796 : : {
9797 : 251 : label = gen_label_rtx ();
9798 : 502 : emit_cmp_and_jump_insns (count_exp,
9799 : : GEN_INT (epilogue_size_needed),
9800 : : LTU, 0, counter_mode (count_exp), 1, label);
9801 : 251 : if (expected_size == -1 || expected_size < epilogue_size_needed)
9802 : 251 : predict_jump (REG_BR_PROB_BASE * 60 / 100);
9803 : : else
9804 : 0 : predict_jump (REG_BR_PROB_BASE * 20 / 100);
9805 : : }
9806 : : }
9807 : :
9808 : : /* Emit code to decide on runtime whether library call or inline should be
9809 : : used. */
9810 : 30842 : if (dynamic_check != -1)
9811 : : {
9812 : 7 : if (!issetmem && CONST_INT_P (count_exp))
9813 : : {
9814 : 1 : if (UINTVAL (count_exp) >= (unsigned HOST_WIDE_INT)dynamic_check)
9815 : : {
9816 : 1 : emit_block_copy_via_libcall (dst, src, count_exp);
9817 : 1 : count_exp = const0_rtx;
9818 : 1 : goto epilogue;
9819 : : }
9820 : : }
9821 : : else
9822 : : {
9823 : 6 : rtx_code_label *hot_label = gen_label_rtx ();
9824 : 6 : if (jump_around_label == NULL_RTX)
9825 : 1 : jump_around_label = gen_label_rtx ();
9826 : 12 : emit_cmp_and_jump_insns (count_exp, GEN_INT (dynamic_check - 1),
9827 : : LEU, 0, counter_mode (count_exp),
9828 : : 1, hot_label);
9829 : 6 : predict_jump (REG_BR_PROB_BASE * 90 / 100);
9830 : 6 : if (issetmem)
9831 : 4 : set_storage_via_libcall (dst, count_exp, val_exp);
9832 : : else
9833 : 2 : emit_block_copy_via_libcall (dst, src, count_exp);
9834 : 6 : emit_jump (jump_around_label);
9835 : 6 : emit_label (hot_label);
9836 : : }
9837 : : }
9838 : :
9839 : : /* Step 2: Alignment prologue. */
9840 : : /* Do the expensive promotion once we branched off the small blocks. */
9841 : 30841 : if (issetmem && !promoted_val)
9842 : 46 : promoted_val = promote_duplicated_reg_to_size (val_exp, size_needed,
9843 : : desired_align, align);
9844 : :
9845 : 30841 : if (desired_align > align && !misaligned_prologue_used)
9846 : : {
9847 : 7 : if (align_bytes == 0)
9848 : : {
9849 : : /* Except for the first move in prologue, we no longer know
9850 : : constant offset in aliasing info. It don't seems to worth
9851 : : the pain to maintain it for the first move, so throw away
9852 : : the info early. */
9853 : 7 : dst = change_address (dst, BLKmode, destreg);
9854 : 7 : if (!issetmem)
9855 : 5 : src = change_address (src, BLKmode, srcreg);
9856 : 7 : dst = expand_set_or_cpymem_prologue (dst, src, destreg, srcreg,
9857 : : promoted_val, vec_promoted_val,
9858 : : count_exp, align, desired_align,
9859 : : issetmem);
9860 : : /* At most desired_align - align bytes are copied. */
9861 : 7 : if (min_size < (unsigned)(desired_align - align))
9862 : 0 : min_size = 0;
9863 : : else
9864 : 7 : min_size -= desired_align - align;
9865 : : }
9866 : : else
9867 : : {
9868 : : /* If we know how many bytes need to be stored before dst is
9869 : : sufficiently aligned, maintain aliasing info accurately. */
9870 : 0 : dst = expand_set_or_cpymem_constant_prologue (dst, &src, destreg,
9871 : : srcreg,
9872 : : promoted_val,
9873 : : vec_promoted_val,
9874 : : desired_align,
9875 : : align_bytes,
9876 : : issetmem);
9877 : :
9878 : 0 : count_exp = plus_constant (counter_mode (count_exp),
9879 : 0 : count_exp, -align_bytes);
9880 : 0 : count -= align_bytes;
9881 : 0 : min_size -= align_bytes;
9882 : 0 : max_size -= align_bytes;
9883 : : }
9884 : 7 : if (need_zero_guard
9885 : 7 : && min_size < (unsigned HOST_WIDE_INT) size_needed
9886 : 1 : && (count < (unsigned HOST_WIDE_INT) size_needed
9887 : 0 : || (align_bytes == 0
9888 : 0 : && count < ((unsigned HOST_WIDE_INT) size_needed
9889 : 0 : + desired_align - align))))
9890 : : {
9891 : : /* It is possible that we copied enough so the main loop will not
9892 : : execute. */
9893 : 1 : gcc_assert (size_needed > 1);
9894 : 1 : if (label == NULL_RTX)
9895 : 0 : label = gen_label_rtx ();
9896 : 2 : emit_cmp_and_jump_insns (count_exp,
9897 : : GEN_INT (size_needed),
9898 : : LTU, 0, counter_mode (count_exp), 1, label);
9899 : 1 : if (expected_size == -1
9900 : 0 : || expected_size < (desired_align - align) / 2 + size_needed)
9901 : 1 : predict_jump (REG_BR_PROB_BASE * 20 / 100);
9902 : : else
9903 : 0 : predict_jump (REG_BR_PROB_BASE * 60 / 100);
9904 : : }
9905 : : }
9906 : 30841 : if (label && size_needed == 1)
9907 : : {
9908 : 0 : emit_label (label);
9909 : 0 : LABEL_NUSES (label) = 1;
9910 : 0 : label = NULL;
9911 : 0 : epilogue_size_needed = 1;
9912 : 0 : if (issetmem)
9913 : 0 : promoted_val = val_exp;
9914 : : }
9915 : 30841 : else if (label == NULL_RTX && !misaligned_prologue_used)
9916 : 20805 : epilogue_size_needed = size_needed;
9917 : :
9918 : : /* Step 3: Main loop. */
9919 : :
9920 : 30841 : switch (alg)
9921 : : {
9922 : 0 : case libcall:
9923 : 0 : case no_stringop:
9924 : 0 : case last_alg:
9925 : 0 : gcc_unreachable ();
9926 : 2594 : case loop_1_byte:
9927 : 2594 : case loop:
9928 : 2594 : case unrolled_loop:
9929 : 2594 : expand_set_or_cpymem_via_loop (dst, src, destreg, srcreg, promoted_val,
9930 : : count_exp, move_mode, unroll_factor,
9931 : : expected_size, issetmem);
9932 : 2594 : break;
9933 : 13441 : case vector_loop:
9934 : 13441 : expand_set_or_cpymem_via_loop (dst, src, destreg, srcreg,
9935 : : vec_promoted_val, count_exp, move_mode,
9936 : : unroll_factor, expected_size, issetmem);
9937 : 13441 : break;
9938 : 14806 : case rep_prefix_8_byte:
9939 : 14806 : case rep_prefix_4_byte:
9940 : 14806 : case rep_prefix_1_byte:
9941 : 14806 : expand_set_or_cpymem_via_rep (dst, src, destreg, srcreg, promoted_val,
9942 : : val_exp, count_exp, move_mode, issetmem);
9943 : 14806 : break;
9944 : : }
9945 : : /* Adjust properly the offset of src and dest memory for aliasing. */
9946 : 30841 : if (CONST_INT_P (count_exp))
9947 : : {
9948 : 17740 : if (!issetmem)
9949 : 7794 : src = adjust_automodify_address_nv (src, BLKmode, srcreg,
9950 : : (count / size_needed) * size_needed);
9951 : 17740 : dst = adjust_automodify_address_nv (dst, BLKmode, destreg,
9952 : : (count / size_needed) * size_needed);
9953 : : }
9954 : : else
9955 : : {
9956 : 13101 : if (!issetmem)
9957 : 10865 : src = change_address (src, BLKmode, srcreg);
9958 : 13101 : dst = change_address (dst, BLKmode, destreg);
9959 : : }
9960 : :
9961 : : /* Step 4: Epilogue to copy the remaining bytes. */
9962 : 33252 : epilogue:
9963 : 33252 : if (label)
9964 : : {
9965 : : /* When the main loop is done, COUNT_EXP might hold original count,
9966 : : while we want to copy only COUNT_EXP & SIZE_NEEDED bytes.
9967 : : Epilogue code will actually copy COUNT_EXP & EPILOGUE_SIZE_NEEDED
9968 : : bytes. Compensate if needed. */
9969 : :
9970 : 251 : if (size_needed < epilogue_size_needed)
9971 : : {
9972 : 0 : tmp = expand_simple_binop (counter_mode (count_exp), AND, count_exp,
9973 : 0 : GEN_INT (size_needed - 1), count_exp, 1,
9974 : : OPTAB_DIRECT);
9975 : 0 : if (tmp != count_exp)
9976 : 0 : emit_move_insn (count_exp, tmp);
9977 : : }
9978 : 251 : emit_label (label);
9979 : 251 : LABEL_NUSES (label) = 1;
9980 : : }
9981 : :
9982 : 33252 : if (count_exp != const0_rtx && epilogue_size_needed > 1)
9983 : : {
9984 : 16092 : if (force_loopy_epilogue)
9985 : 0 : expand_setmem_epilogue_via_loop (dst, destreg, val_exp, count_exp,
9986 : : epilogue_size_needed);
9987 : : else
9988 : : {
9989 : 16092 : if (issetmem)
9990 : 8176 : expand_setmem_epilogue (dst, destreg, promoted_val,
9991 : : vec_promoted_val, count_exp,
9992 : : epilogue_size_needed);
9993 : : else
9994 : 7916 : expand_cpymem_epilogue (dst, src, destreg, srcreg, count_exp,
9995 : : epilogue_size_needed);
9996 : : }
9997 : : }
9998 : 33252 : if (jump_around_label)
9999 : 6525 : emit_label (jump_around_label);
10000 : : return true;
10001 : : }
10002 : :
10003 : : /* Fully unroll memmove of known size with up to 8 registers. */
10004 : :
10005 : : static bool
10006 : 2099 : ix86_expand_unroll_movmem (rtx dst, rtx src, rtx destreg, rtx srcreg,
10007 : : unsigned HOST_WIDE_INT count,
10008 : : machine_mode mode)
10009 : : {
10010 : : /* If 8 registers registers can cover all memory, load them into
10011 : : registers and store them together to avoid possible address
10012 : : overlap between source and destination. */
10013 : 2099 : unsigned HOST_WIDE_INT moves = count / GET_MODE_SIZE (mode);
10014 : 2099 : if (moves == 0)
10015 : : {
10016 : 0 : mode = smallest_int_mode_for_size
10017 : 0 : (count * BITS_PER_UNIT).require ();
10018 : 0 : if (count == GET_MODE_SIZE (mode))
10019 : : moves = 1;
10020 : : else
10021 : : {
10022 : : /* Reduce the smallest move size by half so that MOVES == 1. */
10023 : 0 : mode = smallest_int_mode_for_size
10024 : 0 : (GET_MODE_BITSIZE (mode) / 2).require ();
10025 : 0 : moves = count / GET_MODE_SIZE (mode);
10026 : 0 : gcc_assert (moves == 1);
10027 : : }
10028 : : }
10029 : 2099 : else if (moves > 8)
10030 : : return false;
10031 : :
10032 : 2086 : unsigned int i;
10033 : 2086 : rtx tmp[9];
10034 : :
10035 : 4749 : for (i = 0; i < moves; i++)
10036 : 2663 : tmp[i] = gen_reg_rtx (mode);
10037 : :
10038 : 2086 : rtx srcmem = change_address (src, mode, srcreg);
10039 : 6835 : for (i = 0; i < moves; i++)
10040 : : {
10041 : 2663 : emit_move_insn (tmp[i], srcmem);
10042 : 5326 : srcmem = offset_address (srcmem,
10043 : 2663 : GEN_INT (GET_MODE_SIZE (mode)),
10044 : 2663 : GET_MODE_SIZE (mode));
10045 : : }
10046 : :
10047 : 2086 : unsigned int epilogue_size = count & (GET_MODE_SIZE (mode) - 1);
10048 : 2086 : machine_mode epilogue_mode = VOIDmode;
10049 : 2086 : if (epilogue_size)
10050 : : {
10051 : : /* Handle the remaining bytes with overlapping move. */
10052 : 1911 : epilogue_mode = smallest_int_mode_for_size
10053 : 1911 : (epilogue_size * BITS_PER_UNIT).require ();
10054 : 1911 : tmp[8] = gen_reg_rtx (epilogue_mode);
10055 : 1911 : srcmem = adjust_address (srcmem, epilogue_mode, 0);
10056 : 1911 : srcmem = offset_address (srcmem, GEN_INT (epilogue_size), 1);
10057 : 3822 : srcmem = offset_address (srcmem,
10058 : 1911 : GEN_INT (-GET_MODE_SIZE (epilogue_mode)),
10059 : 1911 : GET_MODE_SIZE (epilogue_mode));
10060 : 1911 : emit_move_insn (tmp[8], srcmem);
10061 : : }
10062 : :
10063 : 2086 : rtx destmem = change_address (dst, mode, destreg);
10064 : 6835 : for (i = 0; i < moves; i++)
10065 : : {
10066 : 2663 : emit_move_insn (destmem, tmp[i]);
10067 : 5326 : destmem = offset_address (destmem,
10068 : 2663 : GEN_INT (GET_MODE_SIZE (mode)),
10069 : 2663 : GET_MODE_SIZE (mode));
10070 : : }
10071 : :
10072 : 2086 : if (epilogue_size)
10073 : : {
10074 : : /* Use overlapping move. */
10075 : 1911 : destmem = adjust_address (destmem, epilogue_mode, 0);
10076 : 1911 : destmem = offset_address (destmem, GEN_INT (epilogue_size), 1);
10077 : 3822 : destmem = offset_address (destmem,
10078 : 1911 : GEN_INT (-GET_MODE_SIZE (epilogue_mode)),
10079 : 1911 : GET_MODE_SIZE (epilogue_mode));
10080 : 1911 : emit_move_insn (destmem, tmp[8]);
10081 : : }
10082 : :
10083 : : return true;
10084 : : }
10085 : :
10086 : : /* Expand memmove of size with MOVES * mode size and MOVES <= 4. If
10087 : : FORWARD is true, copy forward. Otherwise copy backward. */
10088 : :
10089 : : static void
10090 : 2970 : ix86_expand_n_move_movmem (rtx destmem, rtx srcmem, machine_mode mode,
10091 : : unsigned int moves, bool forward)
10092 : : {
10093 : 2970 : gcc_assert (moves <= 4);
10094 : :
10095 : : unsigned int i;
10096 : : rtx tmp[8];
10097 : :
10098 : 14850 : for (i = 0; i < moves; i++)
10099 : 11880 : tmp[i] = gen_reg_rtx (mode);
10100 : :
10101 : 2970 : rtx step;
10102 : 2970 : if (forward)
10103 : 2970 : step = GEN_INT (GET_MODE_SIZE (mode));
10104 : : else
10105 : 2970 : step = GEN_INT (-GET_MODE_SIZE (mode));
10106 : :
10107 : : /* Load MOVES. */
10108 : 11880 : for (i = 0; i < moves - 1; i++)
10109 : : {
10110 : 8910 : emit_move_insn (tmp[i], srcmem);
10111 : 17820 : srcmem = offset_address (srcmem, step, GET_MODE_SIZE (mode));
10112 : : }
10113 : 2970 : emit_move_insn (tmp[i], srcmem);
10114 : :
10115 : : /* Store MOVES. */
10116 : 14850 : for (i = 0; i < moves - 1; i++)
10117 : : {
10118 : 8910 : emit_move_insn (destmem, tmp[i]);
10119 : 17820 : destmem = offset_address (destmem, step, GET_MODE_SIZE (mode));
10120 : : }
10121 : 2970 : emit_move_insn (destmem, tmp[i]);
10122 : 2970 : }
10123 : :
10124 : : /* Load MOVES of mode size into REGS. If LAST is true, load the
10125 : : last MOVES. Otherwise, load the first MOVES. */
10126 : :
10127 : : static void
10128 : 2970 : ix86_expand_load_movmem (rtx src, rtx srcreg, rtx count_exp,
10129 : : machine_mode mode, unsigned int moves,
10130 : : rtx regs[], bool last)
10131 : : {
10132 : 2970 : unsigned int i;
10133 : :
10134 : 14850 : for (i = 0; i < moves; i++)
10135 : 11880 : regs[i] = gen_reg_rtx (mode);
10136 : :
10137 : 2970 : rtx srcmem = change_address (src, mode, srcreg);
10138 : 2970 : rtx step;
10139 : 2970 : if (last)
10140 : : {
10141 : 1485 : srcmem = offset_address (srcmem, count_exp, 1);
10142 : 2970 : step = GEN_INT (-GET_MODE_SIZE (mode));
10143 : 2970 : srcmem = offset_address (srcmem, step, GET_MODE_SIZE (mode));
10144 : : }
10145 : : else
10146 : 2970 : step = GEN_INT (GET_MODE_SIZE (mode));
10147 : :
10148 : 11880 : for (i = 0; i < moves - 1; i++)
10149 : : {
10150 : 8910 : emit_move_insn (regs[i], srcmem);
10151 : 17820 : srcmem = offset_address (srcmem, step, GET_MODE_SIZE (mode));
10152 : : }
10153 : 2970 : emit_move_insn (regs[i], srcmem);
10154 : 2970 : }
10155 : :
10156 : : /* Store MOVES of mode size into REGS. If LAST is true, store the
10157 : : last MOVES. Otherwise, store the first MOVES. */
10158 : :
10159 : : static void
10160 : 2970 : ix86_expand_store_movmem (rtx dst, rtx destreg, rtx count_exp,
10161 : : machine_mode mode, unsigned int moves,
10162 : : rtx regs[], bool last)
10163 : : {
10164 : 2970 : unsigned int i;
10165 : :
10166 : 2970 : rtx destmem = change_address (dst, mode, destreg);
10167 : 2970 : rtx step;
10168 : 2970 : if (last)
10169 : : {
10170 : 1485 : destmem = offset_address (destmem, count_exp, 1);
10171 : 2970 : step = GEN_INT (-GET_MODE_SIZE (mode));
10172 : 2970 : destmem = offset_address (destmem, step, GET_MODE_SIZE (mode));
10173 : : }
10174 : : else
10175 : 2970 : step = GEN_INT (GET_MODE_SIZE (mode));
10176 : :
10177 : 11880 : for (i = 0; i < moves - 1; i++)
10178 : : {
10179 : 8910 : emit_move_insn (destmem, regs[i]);
10180 : 17820 : destmem = offset_address (destmem, step, GET_MODE_SIZE (mode));
10181 : : }
10182 : 2970 : emit_move_insn (destmem, regs[i]);
10183 : 2970 : }
10184 : :
10185 : : /* Expand memmove of size between (MOVES / 2) * mode size and
10186 : : MOVES * mode size with overlapping load and store. MOVES is even.
10187 : : MOVES >= 2 and MOVES <= 8. */
10188 : :
10189 : : static void
10190 : 14515 : ix86_expand_n_overlapping_move_movmem (rtx dst, rtx src, rtx destreg,
10191 : : rtx srcreg, rtx count_exp,
10192 : : machine_mode mode,
10193 : : unsigned int moves)
10194 : : {
10195 : 14515 : gcc_assert (moves >= 2 && moves <= 8 && (moves & 1) == 0);
10196 : :
10197 : 14515 : unsigned int half_moves = moves / 2;
10198 : 14515 : unsigned int i, j;
10199 : 14515 : rtx tmp[8];
10200 : :
10201 : 56453 : for (i = 0; i < moves; i++)
10202 : 41938 : tmp[i] = gen_reg_rtx (mode);
10203 : :
10204 : 14515 : rtx base_srcmem = change_address (src, mode, srcreg);
10205 : :
10206 : : /* Load the first half. */
10207 : 14515 : rtx srcmem = base_srcmem;
10208 : 35484 : for (i = 0; i < half_moves - 1; i++)
10209 : : {
10210 : 6454 : emit_move_insn (tmp[i], srcmem);
10211 : 12908 : srcmem = offset_address (srcmem,
10212 : 6454 : GEN_INT (GET_MODE_SIZE (mode)),
10213 : 6454 : GET_MODE_SIZE (mode));
10214 : : }
10215 : 14515 : emit_move_insn (tmp[i], srcmem);
10216 : :
10217 : : /* Load the second half. */
10218 : 14515 : srcmem = offset_address (base_srcmem, count_exp, 1);
10219 : 14515 : srcmem = offset_address (srcmem,
10220 : 14515 : GEN_INT (-GET_MODE_SIZE (mode)),
10221 : 14515 : GET_MODE_SIZE (mode));
10222 : 35484 : for (j = half_moves, i = 0; i < half_moves - 1; i++, j++)
10223 : : {
10224 : 6454 : emit_move_insn (tmp[j], srcmem);
10225 : 12908 : srcmem = offset_address (srcmem,
10226 : 6454 : GEN_INT (-GET_MODE_SIZE (mode)),
10227 : 6454 : GET_MODE_SIZE (mode));
10228 : : }
10229 : 14515 : emit_move_insn (tmp[j], srcmem);
10230 : :
10231 : 14515 : rtx base_destmem = change_address (dst, mode, destreg);
10232 : :
10233 : : /* Store the first half. */
10234 : 14515 : rtx destmem = base_destmem;
10235 : 35484 : for (i = 0; i < half_moves - 1; i++)
10236 : : {
10237 : 6454 : emit_move_insn (destmem, tmp[i]);
10238 : 12908 : destmem = offset_address (destmem,
10239 : 6454 : GEN_INT (GET_MODE_SIZE (mode)),
10240 : 6454 : GET_MODE_SIZE (mode));
10241 : : }
10242 : 14515 : emit_move_insn (destmem, tmp[i]);
10243 : :
10244 : : /* Store the second half. */
10245 : 14515 : destmem = offset_address (base_destmem, count_exp, 1);
10246 : 29030 : destmem = offset_address (destmem, GEN_INT (-GET_MODE_SIZE (mode)),
10247 : 14515 : GET_MODE_SIZE (mode));
10248 : 35484 : for (j = half_moves, i = 0; i < half_moves - 1; i++, j++)
10249 : : {
10250 : 6454 : emit_move_insn (destmem, tmp[j]);
10251 : 12908 : destmem = offset_address (destmem, GEN_INT (-GET_MODE_SIZE (mode)),
10252 : 6454 : GET_MODE_SIZE (mode));
10253 : : }
10254 : 14515 : emit_move_insn (destmem, tmp[j]);
10255 : 14515 : }
10256 : :
10257 : : /* Expand memmove of size < mode size which is <= 64. */
10258 : :
10259 : : static void
10260 : 3185 : ix86_expand_less_move_movmem (rtx dst, rtx src, rtx destreg,
10261 : : rtx srcreg, rtx count_exp,
10262 : : unsigned HOST_WIDE_INT min_size,
10263 : : machine_mode mode,
10264 : : rtx_code_label *done_label)
10265 : : {
10266 : 3185 : bool skip = false;
10267 : 3185 : machine_mode count_mode = counter_mode (count_exp);
10268 : :
10269 : 3185 : rtx_code_label *between_32_63_label
10270 : 3185 : = GET_MODE_SIZE (mode) > 32 ? gen_label_rtx () : nullptr;
10271 : : /* Jump to BETWEEN_32_64_LABEL if size >= 32 and size < 64. */
10272 : 3 : if (between_32_63_label)
10273 : : {
10274 : 3 : if (min_size && min_size >= 32)
10275 : : {
10276 : 1 : emit_jump_insn (gen_jump (between_32_63_label));
10277 : 1 : emit_barrier ();
10278 : 1 : skip = true;
10279 : : }
10280 : : else
10281 : 2 : emit_cmp_and_jump_insns (count_exp, GEN_INT (32), GEU,
10282 : : nullptr, count_mode, 1,
10283 : : between_32_63_label);
10284 : : }
10285 : :
10286 : 3 : rtx_code_label *between_16_31_label
10287 : 3184 : = (!skip && GET_MODE_SIZE (mode) > 16) ? gen_label_rtx () : nullptr;
10288 : : /* Jump to BETWEEN_16_31_LABEL if size >= 16 and size < 31. */
10289 : 4 : if (between_16_31_label)
10290 : : {
10291 : 4 : if (min_size && min_size >= 16)
10292 : : {
10293 : 2 : emit_jump_insn (gen_jump (between_16_31_label));
10294 : 2 : emit_barrier ();
10295 : 2 : skip = true;
10296 : : }
10297 : : else
10298 : 2 : emit_cmp_and_jump_insns (count_exp, GEN_INT (16), GEU,
10299 : : nullptr, count_mode, 1,
10300 : : between_16_31_label);
10301 : : }
10302 : :
10303 : 2 : rtx_code_label *between_8_15_label
10304 : 6365 : = (!skip && GET_MODE_SIZE (mode) > 8) ? gen_label_rtx () : nullptr;
10305 : : /* Jump to BETWEEN_8_15_LABEL if size >= 8 and size < 15. */
10306 : 2193 : if (between_8_15_label)
10307 : : {
10308 : 2193 : if (min_size && min_size >= 8)
10309 : : {
10310 : 108 : emit_jump_insn (gen_jump (between_8_15_label));
10311 : 108 : emit_barrier ();
10312 : 108 : skip = true;
10313 : : }
10314 : : else
10315 : 2085 : emit_cmp_and_jump_insns (count_exp, GEN_INT (8), GEU,
10316 : : nullptr, count_mode, 1,
10317 : : between_8_15_label);
10318 : : }
10319 : :
10320 : 108 : rtx_code_label *between_4_7_label
10321 : 6151 : = (!skip && GET_MODE_SIZE (mode) > 4) ? gen_label_rtx () : nullptr;
10322 : : /* Jump to BETWEEN_4_7_LABEL if size >= 4 and size < 7. */
10323 : 2418 : if (between_4_7_label)
10324 : : {
10325 : 2418 : if (min_size && min_size >= 4)
10326 : : {
10327 : 174 : emit_jump_insn (gen_jump (between_4_7_label));
10328 : 174 : emit_barrier ();
10329 : 174 : skip = true;
10330 : : }
10331 : : else
10332 : 2244 : emit_cmp_and_jump_insns (count_exp, GEN_INT (4), GEU,
10333 : : nullptr, count_mode, 1,
10334 : : between_4_7_label);
10335 : : }
10336 : :
10337 : 174 : rtx_code_label *between_2_3_label
10338 : 5911 : = (!skip && GET_MODE_SIZE (mode) > 2) ? gen_label_rtx () : nullptr;
10339 : : /* Jump to BETWEEN_2_3_LABEL if size >= 2 and size < 3. */
10340 : 2756 : if (between_2_3_label)
10341 : : {
10342 : 2756 : if (min_size && min_size >= 2)
10343 : : {
10344 : 196 : emit_jump_insn (gen_jump (between_2_3_label));
10345 : 196 : emit_barrier ();
10346 : 196 : skip = true;
10347 : : }
10348 : : else
10349 : 2560 : emit_cmp_and_jump_insns (count_exp, GEN_INT (1), GT,
10350 : : nullptr, count_mode, 1,
10351 : : between_2_3_label);
10352 : : }
10353 : :
10354 : 3185 : if (!skip)
10355 : : {
10356 : 2704 : rtx_code_label *zero_label
10357 : 2704 : = min_size == 0 ? gen_label_rtx () : nullptr;
10358 : : /* Skip if size == 0. */
10359 : 1661 : if (zero_label)
10360 : 1661 : emit_cmp_and_jump_insns (count_exp, GEN_INT (1), LT,
10361 : : nullptr, count_mode, 1,
10362 : : zero_label,
10363 : : profile_probability::unlikely ());
10364 : :
10365 : : /* Move 1 byte. */
10366 : 2704 : rtx tmp0 = gen_reg_rtx (QImode);
10367 : 2704 : rtx srcmem = change_address (src, QImode, srcreg);
10368 : 2704 : emit_move_insn (tmp0, srcmem);
10369 : 2704 : rtx destmem = change_address (dst, QImode, destreg);
10370 : 2704 : emit_move_insn (destmem, tmp0);
10371 : :
10372 : 2704 : if (zero_label)
10373 : 1661 : emit_label (zero_label);
10374 : :
10375 : 2704 : emit_jump_insn (gen_jump (done_label));
10376 : 2704 : emit_barrier ();
10377 : : }
10378 : :
10379 : 3185 : if (between_32_63_label)
10380 : : {
10381 : 3 : emit_label (between_32_63_label);
10382 : 3 : ix86_expand_n_overlapping_move_movmem (dst, src, destreg, srcreg,
10383 : : count_exp, OImode, 2);
10384 : 3 : emit_jump_insn (gen_jump (done_label));
10385 : 3 : emit_barrier ();
10386 : : }
10387 : :
10388 : 3185 : if (between_16_31_label)
10389 : : {
10390 : 4 : emit_label (between_16_31_label);
10391 : 4 : ix86_expand_n_overlapping_move_movmem (dst, src, destreg, srcreg,
10392 : : count_exp, TImode, 2);
10393 : 4 : emit_jump_insn (gen_jump (done_label));
10394 : 4 : emit_barrier ();
10395 : : }
10396 : :
10397 : 3185 : if (between_8_15_label)
10398 : : {
10399 : 2193 : emit_label (between_8_15_label);
10400 : 2193 : ix86_expand_n_overlapping_move_movmem (dst, src, destreg, srcreg,
10401 : : count_exp, DImode, 2);
10402 : 2193 : emit_jump_insn (gen_jump (done_label));
10403 : 2193 : emit_barrier ();
10404 : : }
10405 : :
10406 : 3185 : if (between_4_7_label)
10407 : : {
10408 : 2418 : emit_label (between_4_7_label);
10409 : 2418 : ix86_expand_n_overlapping_move_movmem (dst, src, destreg, srcreg,
10410 : : count_exp, SImode, 2);
10411 : 2418 : emit_jump_insn (gen_jump (done_label));
10412 : 2418 : emit_barrier ();
10413 : : }
10414 : :
10415 : 3185 : if (between_2_3_label)
10416 : : {
10417 : 2756 : emit_label (between_2_3_label);
10418 : 2756 : ix86_expand_n_overlapping_move_movmem (dst, src, destreg, srcreg,
10419 : : count_exp, HImode, 2);
10420 : 2756 : emit_jump_insn (gen_jump (done_label));
10421 : 2756 : emit_barrier ();
10422 : : }
10423 : 3185 : }
10424 : :
10425 : : /* Expand movmem with overlapping unaligned loads and stores:
10426 : : 1. Load all sources into registers and store them together to avoid
10427 : : possible address overlap between source and destination.
10428 : : 2. For known size, first try to fully unroll with 8 registers.
10429 : : 3. For size <= 2 * MOVE_MAX, load all sources into 2 registers first
10430 : : and then store them together.
10431 : : 4. For size > 2 * MOVE_MAX and size <= 4 * MOVE_MAX, load all sources
10432 : : into 4 registers first and then store them together.
10433 : : 5. For size > 4 * MOVE_MAX and size <= 8 * MOVE_MAX, load all sources
10434 : : into 8 registers first and then store them together.
10435 : : 6. For size > 8 * MOVE_MAX,
10436 : : a. If address of destination > address of source, copy backward
10437 : : with a 4 * MOVE_MAX loop with unaligned loads and stores. Load
10438 : : the first 4 * MOVE_MAX into 4 registers before the loop and
10439 : : store them after the loop to support overlapping addresses.
10440 : : b. Otherwise, copy forward with a 4 * MOVE_MAX loop with unaligned
10441 : : loads and stores. Load the last 4 * MOVE_MAX into 4 registers
10442 : : before the loop and store them after the loop to support
10443 : : overlapping addresses.
10444 : : */
10445 : :
10446 : : bool
10447 : 16635 : ix86_expand_movmem (rtx operands[])
10448 : : {
10449 : : /* Since there are much less registers available in 32-bit mode, don't
10450 : : inline movmem in 32-bit mode. */
10451 : 16635 : if (!TARGET_64BIT)
10452 : : return false;
10453 : :
10454 : 14258 : rtx dst = operands[0];
10455 : 14258 : rtx src = operands[1];
10456 : 14258 : rtx count_exp = operands[2];
10457 : 14258 : rtx expected_size_exp = operands[5];
10458 : 14258 : rtx min_size_exp = operands[6];
10459 : 14258 : rtx probable_max_size_exp = operands[8];
10460 : 14258 : unsigned HOST_WIDE_INT count = HOST_WIDE_INT_0U;
10461 : 14258 : HOST_WIDE_INT expected_size = HOST_WIDE_INT_M1U;
10462 : 14258 : unsigned HOST_WIDE_INT min_size = HOST_WIDE_INT_0U;
10463 : 14258 : unsigned HOST_WIDE_INT probable_max_size = HOST_WIDE_INT_M1U;
10464 : :
10465 : 14258 : if (CONST_INT_P (count_exp))
10466 : : {
10467 : 2239 : min_size = probable_max_size = count = expected_size
10468 : 2239 : = INTVAL (count_exp);
10469 : : /* When COUNT is 0, there is nothing to do. */
10470 : 2239 : if (!count)
10471 : : return true;
10472 : : }
10473 : : else
10474 : : {
10475 : 12019 : if (min_size_exp)
10476 : 12019 : min_size = INTVAL (min_size_exp);
10477 : 12019 : if (probable_max_size_exp)
10478 : 8627 : probable_max_size = INTVAL (probable_max_size_exp);
10479 : 12019 : if (CONST_INT_P (expected_size_exp))
10480 : 12019 : expected_size = INTVAL (expected_size_exp);
10481 : : }
10482 : :
10483 : : /* Make sure we don't need to care about overflow later on. */
10484 : 14258 : if (count > (HOST_WIDE_INT_1U << 30))
10485 : : return false;
10486 : :
10487 : 14222 : addr_space_t dst_as = MEM_ADDR_SPACE (dst);
10488 : 14222 : addr_space_t src_as = MEM_ADDR_SPACE (src);
10489 : 14222 : int dynamic_check;
10490 : 14222 : bool noalign;
10491 : 14222 : enum stringop_alg alg = decide_alg (count, expected_size, min_size,
10492 : : probable_max_size, false, false,
10493 : : dst_as, src_as, &dynamic_check,
10494 : : &noalign, false);
10495 : 14222 : if (alg == libcall)
10496 : : return false;
10497 : :
10498 : 5902 : rtx destreg = ix86_copy_addr_to_reg (XEXP (dst, 0));
10499 : 5902 : rtx srcreg = ix86_copy_addr_to_reg (XEXP (src, 0));
10500 : :
10501 : 5902 : unsigned int move_max = MOVE_MAX;
10502 : 5902 : machine_mode mode = smallest_int_mode_for_size
10503 : 5902 : (move_max * BITS_PER_UNIT).require ();
10504 : 5902 : if (probable_max_size && probable_max_size < move_max)
10505 : : {
10506 : : /* Get a usable MOVE_MAX. */
10507 : 3124 : mode = smallest_int_mode_for_size
10508 : 3124 : (probable_max_size * BITS_PER_UNIT).require ();
10509 : : /* Reduce MOVE_MAX by half so that MOVE_MAX can be used. */
10510 : 6248 : if (GET_MODE_SIZE (mode) > probable_max_size)
10511 : 2646 : mode = smallest_int_mode_for_size
10512 : 2646 : (GET_MODE_BITSIZE (mode) / 2).require ();
10513 : 6248 : move_max = GET_MODE_SIZE (mode);
10514 : : }
10515 : :
10516 : : /* Try to fully unroll memmove of known size first. */
10517 : 5902 : if (count
10518 : 5902 : && ix86_expand_unroll_movmem (dst, src, destreg, srcreg, count,
10519 : : mode))
10520 : : return true;
10521 : :
10522 : 3816 : rtx_code_label *done_label = gen_label_rtx ();
10523 : :
10524 : 3816 : rtx_code_label *less_vec_label = nullptr;
10525 : 3816 : if (min_size == 0 || min_size < move_max)
10526 : 3185 : less_vec_label = gen_label_rtx ();
10527 : :
10528 : 3816 : machine_mode count_mode = counter_mode (count_exp);
10529 : :
10530 : : /* Jump to LESS_VEC_LABEL if size < MOVE_MAX. */
10531 : 3816 : if (less_vec_label)
10532 : 3185 : emit_cmp_and_jump_insns (count_exp, GEN_INT (move_max), LTU,
10533 : : nullptr, count_mode, 1,
10534 : : less_vec_label);
10535 : :
10536 : 3816 : rtx_code_label *more_2x_vec_label = nullptr;
10537 : 3816 : if (probable_max_size == 0 || probable_max_size > 2 * move_max)
10538 : 1812 : more_2x_vec_label = gen_label_rtx ();
10539 : :
10540 : : /* Jump to MORE_2X_VEC_LABEL if size > 2 * MOVE_MAX. */
10541 : 1812 : if (more_2x_vec_label)
10542 : 1812 : emit_cmp_and_jump_insns (count_exp, GEN_INT (2 * move_max), GTU,
10543 : : nullptr, count_mode, 1,
10544 : : more_2x_vec_label);
10545 : :
10546 : 3816 : if (min_size == 0 || min_size <= 2 * move_max)
10547 : : {
10548 : : /* Size >= MOVE_MAX and size <= 2 * MOVE_MAX. */
10549 : 3793 : ix86_expand_n_overlapping_move_movmem (dst, src, destreg, srcreg,
10550 : : count_exp, mode, 2);
10551 : 3793 : emit_jump_insn (gen_jump (done_label));
10552 : 3793 : emit_barrier ();
10553 : : }
10554 : :
10555 : 3816 : if (less_vec_label)
10556 : : {
10557 : : /* Size < MOVE_MAX. */
10558 : 3185 : emit_label (less_vec_label);
10559 : 3185 : ix86_expand_less_move_movmem (dst, src, destreg, srcreg,
10560 : : count_exp, min_size, mode,
10561 : : done_label);
10562 : 3185 : emit_jump_insn (gen_jump (done_label));
10563 : 3185 : emit_barrier ();
10564 : : }
10565 : :
10566 : 3816 : if (more_2x_vec_label)
10567 : : {
10568 : : /* Size > 2 * MOVE_MAX and destination may overlap with source. */
10569 : 1812 : emit_label (more_2x_vec_label);
10570 : :
10571 : 1812 : rtx_code_label *more_8x_vec_label = nullptr;
10572 : 1812 : if (probable_max_size == 0 || probable_max_size > 8 * move_max)
10573 : 1485 : more_8x_vec_label = gen_label_rtx ();
10574 : :
10575 : : /* Jump to MORE_8X_VEC_LABEL if size > 8 * MOVE_MAX. */
10576 : 1485 : if (more_8x_vec_label)
10577 : 1485 : emit_cmp_and_jump_insns (count_exp, GEN_INT (8 * move_max), GTU,
10578 : : nullptr, count_mode, 1,
10579 : : more_8x_vec_label);
10580 : :
10581 : 1812 : rtx_code_label *last_4x_vec_label = nullptr;
10582 : 1812 : if (min_size == 0 || min_size < 4 * move_max)
10583 : 1795 : last_4x_vec_label = gen_label_rtx ();
10584 : :
10585 : : /* Jump to LAST_4X_VEC_LABEL if size < 4 * MOVE_MAX. */
10586 : 1795 : if (last_4x_vec_label)
10587 : 1795 : emit_cmp_and_jump_insns (count_exp, GEN_INT (4 * move_max), LTU,
10588 : : nullptr, count_mode, 1,
10589 : : last_4x_vec_label);
10590 : :
10591 : 1812 : if (probable_max_size == 0 || probable_max_size > 4 * move_max)
10592 : : {
10593 : : /* Size > 4 * MOVE_MAX and size <= 8 * MOVE_MAX. */
10594 : 1553 : ix86_expand_n_overlapping_move_movmem (dst, src, destreg,
10595 : : srcreg, count_exp,
10596 : : mode, 8);
10597 : 1553 : emit_jump_insn (gen_jump (done_label));
10598 : 1553 : emit_barrier ();
10599 : : }
10600 : :
10601 : 1812 : if (last_4x_vec_label)
10602 : : {
10603 : : /* Size > 2 * MOVE_MAX and size <= 4 * MOVE_MAX. */
10604 : 1795 : emit_label (last_4x_vec_label);
10605 : 1795 : ix86_expand_n_overlapping_move_movmem (dst, src, destreg,
10606 : : srcreg, count_exp,
10607 : : mode, 4);
10608 : 1795 : emit_jump_insn (gen_jump (done_label));
10609 : 1795 : emit_barrier ();
10610 : : }
10611 : :
10612 : 1812 : if (more_8x_vec_label)
10613 : : {
10614 : : /* Size > 8 * MOVE_MAX. */
10615 : 1485 : emit_label (more_8x_vec_label);
10616 : :
10617 : 1485 : rtx loop_count = gen_reg_rtx (count_mode);
10618 : 1485 : emit_move_insn (loop_count, count_exp);
10619 : :
10620 : : /* Jump to MORE_8X_VEC_BACKWARD_LABEL if source address is
10621 : : lower than destination address. */
10622 : 1485 : rtx_code_label *more_8x_vec_backward_label = gen_label_rtx ();
10623 : 1485 : emit_cmp_and_jump_insns (srcreg, destreg, LTU, nullptr,
10624 : 1485 : GET_MODE (destreg), 1,
10625 : : more_8x_vec_backward_label);
10626 : :
10627 : : /* Skip if source == destination which is less common. */
10628 : 1485 : emit_cmp_and_jump_insns (srcreg, destreg, EQ, nullptr,
10629 : 1485 : GET_MODE (destreg), 1, done_label,
10630 : : profile_probability::unlikely ());
10631 : :
10632 : 1485 : rtx base_destreg = gen_reg_rtx (GET_MODE (destreg));
10633 : 1485 : emit_move_insn (base_destreg, destreg);
10634 : :
10635 : : /* Load the last 4 * MOVE_MAX. */
10636 : 1485 : rtx regs[4];
10637 : 1485 : ix86_expand_load_movmem (src, srcreg, count_exp, mode,
10638 : : ARRAY_SIZE (regs), regs, true);
10639 : :
10640 : 1485 : rtx srcmem = change_address (src, mode, srcreg);
10641 : 1485 : rtx destmem = change_address (dst, mode, destreg);
10642 : :
10643 : : /* Copy forward with a 4 * MOVE_MAX loop. */
10644 : 1485 : rtx_code_label *loop_4x_vec_forward_label = gen_label_rtx ();
10645 : 1485 : emit_label (loop_4x_vec_forward_label);
10646 : :
10647 : 1485 : ix86_expand_n_move_movmem (destmem, srcmem, mode, 4, true);
10648 : :
10649 : 1485 : rtx tmp;
10650 : 1485 : rtx delta = GEN_INT (4 * MOVE_MAX);
10651 : :
10652 : : /* Decrement LOOP_COUNT by 4 * MOVE_MAX. */
10653 : 1485 : tmp = expand_simple_binop (GET_MODE (loop_count), MINUS,
10654 : : loop_count, delta, nullptr, 1,
10655 : : OPTAB_DIRECT);
10656 : 1485 : if (tmp != loop_count)
10657 : 1485 : emit_move_insn (loop_count, tmp);
10658 : :
10659 : : /* Increment DESTREG and SRCREG by 4 * MOVE_MAX. */
10660 : 1485 : tmp = expand_simple_binop (GET_MODE (destreg), PLUS,
10661 : : destreg, delta, nullptr, 1,
10662 : : OPTAB_DIRECT);
10663 : 1485 : if (tmp != destreg)
10664 : 1485 : emit_move_insn (destreg, tmp);
10665 : 1485 : tmp = expand_simple_binop (GET_MODE (srcreg), PLUS, srcreg,
10666 : : delta, nullptr, 1, OPTAB_DIRECT);
10667 : 1485 : if (tmp != srcreg)
10668 : 1485 : emit_move_insn (srcreg, tmp);
10669 : :
10670 : : /* Stop if LOOP_EXP <= 4 * MOVE_MAX. */
10671 : 1485 : emit_cmp_and_jump_insns (loop_count, delta, GTU, nullptr,
10672 : 1485 : GET_MODE (loop_count), 1,
10673 : : loop_4x_vec_forward_label);
10674 : :
10675 : : /* Store the last 4 * MOVE_MAX. */
10676 : 1485 : ix86_expand_store_movmem (dst, base_destreg, count_exp, mode,
10677 : : ARRAY_SIZE (regs), regs, true);
10678 : :
10679 : 1485 : emit_jump_insn (gen_jump (done_label));
10680 : 1485 : emit_barrier ();
10681 : :
10682 : : /* Copy backward with a 4 * MOVE_MAX loop. */
10683 : 1485 : emit_label (more_8x_vec_backward_label);
10684 : :
10685 : 1485 : base_destreg = gen_reg_rtx (GET_MODE (destreg));
10686 : 1485 : emit_move_insn (base_destreg, destreg);
10687 : :
10688 : : /* Load the first 4 * MOVE_MAX. */
10689 : 1485 : ix86_expand_load_movmem (src, srcreg, count_exp, mode,
10690 : : ARRAY_SIZE (regs), regs, false);
10691 : :
10692 : : /* Increment DESTREG and SRCREG by COUNT_EXP. */
10693 : 1485 : tmp = expand_simple_binop (GET_MODE (destreg), PLUS,
10694 : : destreg, count_exp, nullptr, 1,
10695 : : OPTAB_DIRECT);
10696 : 1485 : if (tmp != destreg)
10697 : 1485 : emit_move_insn (destreg, tmp);
10698 : 1485 : tmp = expand_simple_binop (GET_MODE (srcreg), PLUS, srcreg,
10699 : : count_exp, nullptr, 1, OPTAB_DIRECT);
10700 : 1485 : if (tmp != srcreg)
10701 : 1485 : emit_move_insn (srcreg, tmp);
10702 : :
10703 : 1485 : srcmem = change_address (src, mode, srcreg);
10704 : 1485 : destmem = change_address (dst, mode, destreg);
10705 : 2970 : rtx step = GEN_INT (-GET_MODE_SIZE (mode));
10706 : 2970 : srcmem = offset_address (srcmem, step, GET_MODE_SIZE (mode));
10707 : 2970 : destmem = offset_address (destmem, step, GET_MODE_SIZE (mode));
10708 : :
10709 : 1485 : rtx_code_label *loop_4x_vec_backward_label = gen_label_rtx ();
10710 : 1485 : emit_label (loop_4x_vec_backward_label);
10711 : :
10712 : 1485 : ix86_expand_n_move_movmem (destmem, srcmem, mode, 4, false);
10713 : :
10714 : : /* Decrement LOOP_COUNT by 4 * MOVE_MAX. */
10715 : 1485 : tmp = expand_simple_binop (GET_MODE (loop_count), MINUS,
10716 : : loop_count, delta, nullptr, 1,
10717 : : OPTAB_DIRECT);
10718 : 1485 : if (tmp != loop_count)
10719 : 1485 : emit_move_insn (loop_count, tmp);
10720 : :
10721 : : /* Decrement DESTREG and SRCREG by 4 * MOVE_MAX. */
10722 : 1485 : tmp = expand_simple_binop (GET_MODE (destreg), MINUS,
10723 : : destreg, delta, nullptr, 1,
10724 : : OPTAB_DIRECT);
10725 : 1485 : if (tmp != destreg)
10726 : 1485 : emit_move_insn (destreg, tmp);
10727 : 1485 : tmp = expand_simple_binop (GET_MODE (srcreg), MINUS, srcreg,
10728 : : delta, nullptr, 1, OPTAB_DIRECT);
10729 : 1485 : if (tmp != srcreg)
10730 : 1485 : emit_move_insn (srcreg, tmp);
10731 : :
10732 : : /* Stop if LOOP_EXP <= 4 * MOVE_MAX. */
10733 : 1485 : emit_cmp_and_jump_insns (loop_count, delta, GTU, nullptr,
10734 : 1485 : GET_MODE (loop_count), 1,
10735 : : loop_4x_vec_backward_label);
10736 : :
10737 : : /* Store the first 4 * MOVE_MAX. */
10738 : 1485 : ix86_expand_store_movmem (dst, base_destreg, count_exp, mode,
10739 : : ARRAY_SIZE (regs), regs, false);
10740 : :
10741 : 1485 : emit_jump_insn (gen_jump (done_label));
10742 : 1485 : emit_barrier ();
10743 : : }
10744 : : }
10745 : :
10746 : 3816 : emit_label (done_label);
10747 : :
10748 : 3816 : return true;
10749 : : }
10750 : :
10751 : : /* Expand cmpstrn or memcmp. */
10752 : :
10753 : : bool
10754 : 170410 : ix86_expand_cmpstrn_or_cmpmem (rtx result, rtx src1, rtx src2,
10755 : : rtx length, rtx align, bool is_cmpstrn)
10756 : : {
10757 : : /* Expand strncmp and memcmp only with -minline-all-stringops since
10758 : : "repz cmpsb" can be much slower than strncmp and memcmp functions
10759 : : implemented with vector instructions, see
10760 : :
10761 : : https://gcc.gnu.org/bugzilla/show_bug.cgi?id=43052
10762 : : */
10763 : 170410 : if (!TARGET_INLINE_ALL_STRINGOPS)
10764 : : return false;
10765 : :
10766 : : /* Can't use this if the user has appropriated ecx, esi or edi. */
10767 : 5771 : if (fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG])
10768 : : return false;
10769 : :
10770 : 5771 : if (is_cmpstrn)
10771 : : {
10772 : : /* For strncmp, length is the maximum length, which can be larger
10773 : : than actual string lengths. We can expand the cmpstrn pattern
10774 : : to "repz cmpsb" only if one of the strings is a constant so
10775 : : that expand_builtin_strncmp() can write the length argument to
10776 : : be the minimum of the const string length and the actual length
10777 : : argument. Otherwise, "repz cmpsb" may pass the 0 byte. */
10778 : 69 : tree t1 = MEM_EXPR (src1);
10779 : 69 : tree t2 = MEM_EXPR (src2);
10780 : 138 : if (!((t1 && TREE_CODE (t1) == MEM_REF
10781 : 69 : && TREE_CODE (TREE_OPERAND (t1, 0)) == ADDR_EXPR
10782 : 0 : && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (t1, 0), 0))
10783 : : == STRING_CST))
10784 : 69 : || (t2 && TREE_CODE (t2) == MEM_REF
10785 : 69 : && TREE_CODE (TREE_OPERAND (t2, 0)) == ADDR_EXPR
10786 : 69 : && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (t2, 0), 0))
10787 : : == STRING_CST))))
10788 : : return false;
10789 : : }
10790 : :
10791 : 5771 : rtx addr1 = copy_addr_to_reg (XEXP (src1, 0));
10792 : 5771 : rtx addr2 = copy_addr_to_reg (XEXP (src2, 0));
10793 : 5771 : if (addr1 != XEXP (src1, 0))
10794 : 5771 : src1 = replace_equiv_address_nv (src1, addr1);
10795 : 5771 : if (addr2 != XEXP (src2, 0))
10796 : 5771 : src2 = replace_equiv_address_nv (src2, addr2);
10797 : :
10798 : : /* NB: Make a copy of the data length to avoid changing the original
10799 : : data length by cmpstrnqi patterns. */
10800 : 5771 : length = ix86_zero_extend_to_Pmode (length);
10801 : 8659 : rtx lengthreg = gen_reg_rtx (Pmode);
10802 : 5771 : emit_move_insn (lengthreg, length);
10803 : :
10804 : : /* If we are testing strict equality, we can use known alignment to
10805 : : good advantage. This may be possible with combine, particularly
10806 : : once cc0 is dead. */
10807 : 5771 : if (CONST_INT_P (length))
10808 : : {
10809 : 0 : if (length == const0_rtx)
10810 : : {
10811 : 0 : emit_move_insn (result, const0_rtx);
10812 : 0 : return true;
10813 : : }
10814 : 0 : emit_insn (gen_cmpstrnqi_nz_1 (addr1, addr2, lengthreg, align,
10815 : : src1, src2));
10816 : : }
10817 : : else
10818 : : {
10819 : 8659 : emit_insn (gen_cmp_1 (Pmode, lengthreg, lengthreg));
10820 : 5771 : emit_insn (gen_cmpstrnqi_1 (addr1, addr2, lengthreg, align,
10821 : : src1, src2));
10822 : : }
10823 : :
10824 : 5771 : rtx out = gen_lowpart (QImode, result);
10825 : 5771 : emit_insn (gen_cmpintqi (out));
10826 : 5771 : emit_move_insn (result, gen_rtx_SIGN_EXTEND (SImode, out));
10827 : :
10828 : 5771 : return true;
10829 : : }
10830 : :
10831 : : /* Expand the appropriate insns for doing strlen if not just doing
10832 : : repnz; scasb
10833 : :
10834 : : out = result, initialized with the start address
10835 : : align_rtx = alignment of the address.
10836 : : scratch = scratch register, initialized with the startaddress when
10837 : : not aligned, otherwise undefined
10838 : :
10839 : : This is just the body. It needs the initializations mentioned above and
10840 : : some address computing at the end. These things are done in i386.md. */
10841 : :
10842 : : static void
10843 : 11 : ix86_expand_strlensi_unroll_1 (rtx out, rtx src, rtx align_rtx)
10844 : : {
10845 : 11 : int align;
10846 : 11 : rtx tmp;
10847 : 11 : rtx_code_label *align_2_label = NULL;
10848 : 11 : rtx_code_label *align_3_label = NULL;
10849 : 11 : rtx_code_label *align_4_label = gen_label_rtx ();
10850 : 11 : rtx_code_label *end_0_label = gen_label_rtx ();
10851 : 11 : rtx mem;
10852 : 11 : rtx tmpreg = gen_reg_rtx (SImode);
10853 : 11 : rtx scratch = gen_reg_rtx (SImode);
10854 : 11 : rtx cmp;
10855 : :
10856 : 11 : align = 0;
10857 : 11 : if (CONST_INT_P (align_rtx))
10858 : 11 : align = INTVAL (align_rtx);
10859 : :
10860 : : /* Loop to check 1..3 bytes for null to get an aligned pointer. */
10861 : :
10862 : : /* Is there a known alignment and is it less than 4? */
10863 : 11 : if (align < 4)
10864 : : {
10865 : 15 : rtx scratch1 = gen_reg_rtx (Pmode);
10866 : 11 : emit_move_insn (scratch1, out);
10867 : : /* Is there a known alignment and is it not 2? */
10868 : 11 : if (align != 2)
10869 : : {
10870 : 11 : align_3_label = gen_label_rtx (); /* Label when aligned to 3-byte */
10871 : 11 : align_2_label = gen_label_rtx (); /* Label when aligned to 2-byte */
10872 : :
10873 : : /* Leave just the 3 lower bits. */
10874 : 15 : align_rtx = expand_binop (Pmode, and_optab, scratch1, GEN_INT (3),
10875 : : NULL_RTX, 0, OPTAB_WIDEN);
10876 : :
10877 : 15 : emit_cmp_and_jump_insns (align_rtx, const0_rtx, EQ, NULL,
10878 : 11 : Pmode, 1, align_4_label);
10879 : 15 : emit_cmp_and_jump_insns (align_rtx, const2_rtx, EQ, NULL,
10880 : 11 : Pmode, 1, align_2_label);
10881 : 15 : emit_cmp_and_jump_insns (align_rtx, const2_rtx, GTU, NULL,
10882 : 11 : Pmode, 1, align_3_label);
10883 : : }
10884 : : else
10885 : : {
10886 : : /* Since the alignment is 2, we have to check 2 or 0 bytes;
10887 : : check if is aligned to 4 - byte. */
10888 : :
10889 : 0 : align_rtx = expand_binop (Pmode, and_optab, scratch1, const2_rtx,
10890 : : NULL_RTX, 0, OPTAB_WIDEN);
10891 : :
10892 : 0 : emit_cmp_and_jump_insns (align_rtx, const0_rtx, EQ, NULL,
10893 : 0 : Pmode, 1, align_4_label);
10894 : : }
10895 : :
10896 : 11 : mem = change_address (src, QImode, out);
10897 : :
10898 : : /* Now compare the bytes. */
10899 : :
10900 : : /* Compare the first n unaligned byte on a byte per byte basis. */
10901 : 11 : emit_cmp_and_jump_insns (mem, const0_rtx, EQ, NULL,
10902 : : QImode, 1, end_0_label);
10903 : :
10904 : : /* Increment the address. */
10905 : 11 : emit_insn (gen_add2_insn (out, const1_rtx));
10906 : :
10907 : : /* Not needed with an alignment of 2 */
10908 : 11 : if (align != 2)
10909 : : {
10910 : 11 : emit_label (align_2_label);
10911 : :
10912 : 11 : emit_cmp_and_jump_insns (mem, const0_rtx, EQ, NULL, QImode, 1,
10913 : : end_0_label);
10914 : :
10915 : 11 : emit_insn (gen_add2_insn (out, const1_rtx));
10916 : :
10917 : 11 : emit_label (align_3_label);
10918 : : }
10919 : :
10920 : 11 : emit_cmp_and_jump_insns (mem, const0_rtx, EQ, NULL, QImode, 1,
10921 : : end_0_label);
10922 : :
10923 : 11 : emit_insn (gen_add2_insn (out, const1_rtx));
10924 : : }
10925 : :
10926 : : /* Generate loop to check 4 bytes at a time. It is not a good idea to
10927 : : align this loop. It gives only huge programs, but does not help to
10928 : : speed up. */
10929 : 11 : emit_label (align_4_label);
10930 : :
10931 : 11 : mem = change_address (src, SImode, out);
10932 : 11 : emit_move_insn (scratch, mem);
10933 : 11 : emit_insn (gen_add2_insn (out, GEN_INT (4)));
10934 : :
10935 : : /* This formula yields a nonzero result iff one of the bytes is zero.
10936 : : This saves three branches inside loop and many cycles. */
10937 : :
10938 : 11 : emit_insn (gen_addsi3 (tmpreg, scratch, GEN_INT (-0x01010101)));
10939 : 11 : emit_insn (gen_one_cmplsi2 (scratch, scratch));
10940 : 11 : emit_insn (gen_andsi3 (tmpreg, tmpreg, scratch));
10941 : 11 : emit_insn (gen_andsi3 (tmpreg, tmpreg,
10942 : : gen_int_mode (0x80808080, SImode)));
10943 : 11 : emit_cmp_and_jump_insns (tmpreg, const0_rtx, EQ, 0, SImode, 1,
10944 : : align_4_label);
10945 : :
10946 : 11 : if (TARGET_CMOVE)
10947 : : {
10948 : 11 : rtx reg = gen_reg_rtx (SImode);
10949 : 15 : rtx reg2 = gen_reg_rtx (Pmode);
10950 : 11 : emit_move_insn (reg, tmpreg);
10951 : 11 : emit_insn (gen_lshrsi3 (reg, reg, GEN_INT (16)));
10952 : :
10953 : : /* If zero is not in the first two bytes, move two bytes forward. */
10954 : 11 : emit_insn (gen_testsi_ccno_1 (tmpreg, GEN_INT (0x8080)));
10955 : 11 : tmp = gen_rtx_REG (CCNOmode, FLAGS_REG);
10956 : 11 : tmp = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
10957 : 11 : emit_insn (gen_rtx_SET (tmpreg,
10958 : : gen_rtx_IF_THEN_ELSE (SImode, tmp,
10959 : : reg,
10960 : : tmpreg)));
10961 : : /* Emit lea manually to avoid clobbering of flags. */
10962 : 15 : emit_insn (gen_rtx_SET (reg2, plus_constant (Pmode, out, 2)));
10963 : :
10964 : 11 : tmp = gen_rtx_REG (CCNOmode, FLAGS_REG);
10965 : 11 : tmp = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
10966 : 15 : emit_insn (gen_rtx_SET (out,
10967 : : gen_rtx_IF_THEN_ELSE (Pmode, tmp,
10968 : : reg2,
10969 : : out)));
10970 : 11 : }
10971 : : else
10972 : : {
10973 : 0 : rtx_code_label *end_2_label = gen_label_rtx ();
10974 : : /* Is zero in the first two bytes? */
10975 : :
10976 : 0 : emit_insn (gen_testsi_ccno_1 (tmpreg, GEN_INT (0x8080)));
10977 : 0 : tmp = gen_rtx_REG (CCNOmode, FLAGS_REG);
10978 : 0 : tmp = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
10979 : 0 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
10980 : : gen_rtx_LABEL_REF (VOIDmode, end_2_label),
10981 : : pc_rtx);
10982 : 0 : tmp = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
10983 : 0 : JUMP_LABEL (tmp) = end_2_label;
10984 : :
10985 : : /* Not in the first two. Move two bytes forward. */
10986 : 0 : emit_insn (gen_lshrsi3 (tmpreg, tmpreg, GEN_INT (16)));
10987 : 0 : emit_insn (gen_add2_insn (out, const2_rtx));
10988 : :
10989 : 0 : emit_label (end_2_label);
10990 : :
10991 : : }
10992 : :
10993 : : /* Avoid branch in fixing the byte. */
10994 : 11 : tmpreg = gen_lowpart (QImode, tmpreg);
10995 : 11 : emit_insn (gen_addqi3_cconly_overflow (tmpreg, tmpreg));
10996 : 11 : tmp = gen_rtx_REG (CCmode, FLAGS_REG);
10997 : 11 : cmp = gen_rtx_LTU (VOIDmode, tmp, const0_rtx);
10998 : 15 : emit_insn (gen_sub3_carry (Pmode, out, out, GEN_INT (3), tmp, cmp));
10999 : :
11000 : 11 : emit_label (end_0_label);
11001 : 11 : }
11002 : :
11003 : : /* Expand strlen. */
11004 : :
11005 : : bool
11006 : 13718 : ix86_expand_strlen (rtx out, rtx src, rtx eoschar, rtx align)
11007 : : {
11008 : 13718 : if (TARGET_UNROLL_STRLEN
11009 : 13718 : && TARGET_INLINE_ALL_STRINGOPS
11010 : 11 : && eoschar == const0_rtx
11011 : 11 : && optimize > 1)
11012 : : {
11013 : : /* The generic case of strlen expander is long. Avoid it's
11014 : : expanding unless TARGET_INLINE_ALL_STRINGOPS. */
11015 : 15 : rtx addr = force_reg (Pmode, XEXP (src, 0));
11016 : : /* Well it seems that some optimizer does not combine a call like
11017 : : foo(strlen(bar), strlen(bar));
11018 : : when the move and the subtraction is done here. It does calculate
11019 : : the length just once when these instructions are done inside of
11020 : : output_strlen_unroll(). But I think since &bar[strlen(bar)] is
11021 : : often used and I use one fewer register for the lifetime of
11022 : : output_strlen_unroll() this is better. */
11023 : :
11024 : 11 : emit_move_insn (out, addr);
11025 : :
11026 : 11 : ix86_expand_strlensi_unroll_1 (out, src, align);
11027 : :
11028 : : /* strlensi_unroll_1 returns the address of the zero at the end of
11029 : : the string, like memchr(), so compute the length by subtracting
11030 : : the start address. */
11031 : 11 : emit_insn (gen_sub2_insn (out, addr));
11032 : 11 : return true;
11033 : : }
11034 : : else
11035 : : return false;
11036 : : }
11037 : :
11038 : : /* For given symbol (function) construct code to compute address of it's PLT
11039 : : entry in large x86-64 PIC model. */
11040 : :
11041 : : static rtx
11042 : 31 : construct_plt_address (rtx symbol)
11043 : : {
11044 : 31 : rtx tmp, unspec;
11045 : :
11046 : 31 : gcc_assert (SYMBOL_REF_P (symbol));
11047 : 31 : gcc_assert (ix86_cmodel == CM_LARGE_PIC && !TARGET_PECOFF);
11048 : 31 : gcc_assert (Pmode == DImode);
11049 : :
11050 : 31 : tmp = gen_reg_rtx (Pmode);
11051 : 31 : unspec = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, symbol), UNSPEC_PLTOFF);
11052 : :
11053 : 31 : emit_move_insn (tmp, gen_rtx_CONST (Pmode, unspec));
11054 : 31 : emit_insn (gen_add2_insn (tmp, pic_offset_table_rtx));
11055 : 31 : return tmp;
11056 : : }
11057 : :
11058 : : /* Additional registers that are clobbered by SYSV calls. */
11059 : :
11060 : : static int const x86_64_ms_sysv_extra_clobbered_registers
11061 : : [NUM_X86_64_MS_CLOBBERED_REGS] =
11062 : : {
11063 : : SI_REG, DI_REG,
11064 : : XMM6_REG, XMM7_REG,
11065 : : XMM8_REG, XMM9_REG, XMM10_REG, XMM11_REG,
11066 : : XMM12_REG, XMM13_REG, XMM14_REG, XMM15_REG
11067 : : };
11068 : :
11069 : : rtx_insn *
11070 : 6250335 : ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1,
11071 : : rtx callarg2,
11072 : : rtx pop, bool sibcall)
11073 : : {
11074 : 6250335 : rtx vec[3];
11075 : 6250335 : rtx use = NULL, call;
11076 : 6250335 : unsigned int vec_len = 0;
11077 : 6250335 : tree fndecl;
11078 : 6250335 : bool call_no_callee_saved_registers = false;
11079 : :
11080 : 6250335 : if (SYMBOL_REF_P (XEXP (fnaddr, 0)))
11081 : : {
11082 : 6054783 : fndecl = SYMBOL_REF_DECL (XEXP (fnaddr, 0));
11083 : 6054783 : if (fndecl)
11084 : : {
11085 : 5794855 : if (lookup_attribute ("interrupt",
11086 : 5794855 : TYPE_ATTRIBUTES (TREE_TYPE (fndecl))))
11087 : 1 : error ("interrupt service routine cannot be called directly");
11088 : 5794854 : else if (ix86_type_no_callee_saved_registers_p (TREE_TYPE (fndecl)))
11089 : 5794855 : call_no_callee_saved_registers = true;
11090 : 5794855 : if (fndecl == current_function_decl
11091 : 5794855 : && decl_binds_to_current_def_p (fndecl))
11092 : 11061 : cfun->machine->recursive_function = true;
11093 : : }
11094 : : }
11095 : : else
11096 : : {
11097 : 195552 : if (MEM_P (fnaddr))
11098 : : {
11099 : 195552 : tree mem_expr = MEM_EXPR (fnaddr);
11100 : 195552 : if (mem_expr != nullptr
11101 : 195507 : && TREE_CODE (mem_expr) == MEM_REF
11102 : 391059 : && ix86_type_no_callee_saved_registers_p (TREE_TYPE (mem_expr)))
11103 : : call_no_callee_saved_registers = true;
11104 : : }
11105 : :
11106 : : fndecl = NULL_TREE;
11107 : : }
11108 : :
11109 : 6250335 : if (pop == const0_rtx)
11110 : 0 : pop = NULL;
11111 : 6250335 : gcc_assert (!TARGET_64BIT || !pop);
11112 : :
11113 : 6250335 : rtx addr = XEXP (fnaddr, 0);
11114 : 6250335 : if (TARGET_MACHO && !TARGET_64BIT)
11115 : : {
11116 : : #if TARGET_MACHO
11117 : : if (flag_pic && SYMBOL_REF_P (XEXP (fnaddr, 0)))
11118 : : fnaddr = machopic_indirect_call_target (fnaddr);
11119 : : #endif
11120 : : }
11121 : : else
11122 : : {
11123 : : /* Static functions and indirect calls don't need the pic register. Also,
11124 : : check if PLT was explicitly avoided via no-plt or "noplt" attribute, making
11125 : : it an indirect call. */
11126 : 6250335 : if (flag_pic
11127 : 516882 : && SYMBOL_REF_P (addr)
11128 : 6740978 : && ix86_call_use_plt_p (addr))
11129 : : {
11130 : 392456 : if (flag_plt
11131 : 392456 : && (SYMBOL_REF_DECL (addr) == NULL_TREE
11132 : 392422 : || !lookup_attribute ("noplt",
11133 : 392422 : DECL_ATTRIBUTES (SYMBOL_REF_DECL (addr)))))
11134 : : {
11135 : 392421 : if (!TARGET_64BIT
11136 : 215552 : || (ix86_cmodel == CM_LARGE_PIC
11137 : : && DEFAULT_ABI != MS_ABI))
11138 : : {
11139 : 530638 : use_reg (&use, gen_rtx_REG (Pmode,
11140 : : REAL_PIC_OFFSET_TABLE_REGNUM));
11141 : 176900 : if (ix86_use_pseudo_pic_reg ())
11142 : 353769 : emit_move_insn (gen_rtx_REG (Pmode,
11143 : 176900 : REAL_PIC_OFFSET_TABLE_REGNUM),
11144 : : pic_offset_table_rtx);
11145 : : }
11146 : : }
11147 : 35 : else if (!TARGET_PECOFF && !TARGET_MACHO)
11148 : : {
11149 : 35 : if (TARGET_64BIT
11150 : 35 : && ix86_cmodel == CM_LARGE_PIC
11151 : : && DEFAULT_ABI != MS_ABI)
11152 : : {
11153 : 1 : fnaddr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr),
11154 : : UNSPEC_GOT);
11155 : 1 : fnaddr = gen_rtx_CONST (Pmode, fnaddr);
11156 : 1 : fnaddr = force_reg (Pmode, fnaddr);
11157 : 1 : fnaddr = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, fnaddr);
11158 : : }
11159 : 34 : else if (TARGET_64BIT)
11160 : : {
11161 : 38 : fnaddr = gen_rtx_UNSPEC (Pmode,
11162 : : gen_rtvec (1, addr),
11163 : : UNSPEC_GOTPCREL);
11164 : 38 : fnaddr = gen_rtx_CONST (Pmode, fnaddr);
11165 : : }
11166 : : else
11167 : : {
11168 : 0 : fnaddr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr),
11169 : : UNSPEC_GOT);
11170 : 0 : fnaddr = gen_rtx_CONST (Pmode, fnaddr);
11171 : 0 : fnaddr = gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
11172 : : fnaddr);
11173 : : }
11174 : 39 : fnaddr = gen_const_mem (Pmode, fnaddr);
11175 : : /* Pmode may not be the same as word_mode for x32, which
11176 : : doesn't support indirect branch via 32-bit memory slot.
11177 : : Since x32 GOT slot is 64 bit with zero upper 32 bits,
11178 : : indirect branch via x32 GOT slot is OK. */
11179 : 35 : if (GET_MODE (fnaddr) != word_mode)
11180 : 4 : fnaddr = gen_rtx_ZERO_EXTEND (word_mode, fnaddr);
11181 : 35 : fnaddr = gen_rtx_MEM (QImode, fnaddr);
11182 : : }
11183 : : }
11184 : : }
11185 : :
11186 : : /* Skip setting up RAX register for -mskip-rax-setup when there are no
11187 : : parameters passed in vector registers. */
11188 : 6250335 : if (TARGET_64BIT
11189 : 5413367 : && (INTVAL (callarg2) > 0
11190 : 5352186 : || (INTVAL (callarg2) == 0
11191 : 323327 : && (TARGET_SSE || !flag_skip_rax_setup))))
11192 : : {
11193 : 384506 : rtx al = gen_rtx_REG (QImode, AX_REG);
11194 : 384506 : emit_move_insn (al, callarg2);
11195 : 384506 : use_reg (&use, al);
11196 : : }
11197 : :
11198 : 6250335 : if (ix86_cmodel == CM_LARGE_PIC
11199 : : && !TARGET_PECOFF
11200 : 41 : && MEM_P (fnaddr)
11201 : 41 : && SYMBOL_REF_P (XEXP (fnaddr, 0))
11202 : 6250368 : && !local_symbolic_operand (XEXP (fnaddr, 0), VOIDmode))
11203 : 31 : fnaddr = gen_rtx_MEM (QImode, construct_plt_address (XEXP (fnaddr, 0)));
11204 : : /* Since x32 GOT slot is 64 bit with zero upper 32 bits, indirect
11205 : : branch via x32 GOT slot is OK. */
11206 : 6250304 : else if (TARGET_X32
11207 : 75 : && MEM_P (fnaddr)
11208 : 75 : && GET_CODE (XEXP (fnaddr, 0)) == ZERO_EXTEND
11209 : 8 : && GOT_memory_operand (XEXP (XEXP (fnaddr, 0), 0), Pmode)
11210 : 6250308 : && !TARGET_INDIRECT_BRANCH_REGISTER)
11211 : : ;
11212 : 6250304 : else if (sibcall
11213 : 6250304 : ? !sibcall_insn_operand (XEXP (fnaddr, 0), word_mode)
11214 : 6119818 : : !call_insn_operand (XEXP (fnaddr, 0), word_mode))
11215 : : {
11216 : 531 : fnaddr = convert_to_mode (word_mode, XEXP (fnaddr, 0), 1);
11217 : 531 : fnaddr = gen_rtx_MEM (QImode, copy_to_mode_reg (word_mode, fnaddr));
11218 : : }
11219 : :
11220 : : /* PR100665: Hwasan may tag code pointer which is not supported by LAM,
11221 : : mask off code pointers here.
11222 : : TODO: also need to handle indirect jump. */
11223 : 6251421 : if (ix86_memtag_can_tag_addresses () && !fndecl
11224 : 6250359 : && sanitize_flags_p (SANITIZE_HWADDRESS))
11225 : : {
11226 : 24 : rtx untagged_addr = ix86_memtag_untagged_pointer (XEXP (fnaddr, 0),
11227 : : NULL_RTX);
11228 : 24 : fnaddr = gen_rtx_MEM (QImode, untagged_addr);
11229 : : }
11230 : :
11231 : 6250335 : call = gen_rtx_CALL (VOIDmode, fnaddr, callarg1);
11232 : :
11233 : 6250335 : if (retval)
11234 : 2472264 : call = gen_rtx_SET (retval, call);
11235 : 6250335 : vec[vec_len++] = call;
11236 : :
11237 : 6250335 : if (pop)
11238 : : {
11239 : 449604 : pop = gen_rtx_PLUS (Pmode, stack_pointer_rtx, pop);
11240 : 224802 : pop = gen_rtx_SET (stack_pointer_rtx, pop);
11241 : 224802 : vec[vec_len++] = pop;
11242 : : }
11243 : :
11244 : 6250335 : static const char ix86_call_used_regs[] = CALL_USED_REGISTERS;
11245 : :
11246 : 6250335 : if ((cfun->machine->call_saved_registers
11247 : 6250335 : == TYPE_NO_CALLER_SAVED_REGISTERS)
11248 : 6250335 : && (!fndecl
11249 : 468 : || (!TREE_THIS_VOLATILE (fndecl)
11250 : 186 : && !lookup_attribute ("no_caller_saved_registers",
11251 : 186 : TYPE_ATTRIBUTES (TREE_TYPE (fndecl))))))
11252 : : {
11253 : 182 : bool is_64bit_ms_abi = (TARGET_64BIT
11254 : 182 : && ix86_function_abi (fndecl) == MS_ABI);
11255 : 182 : char c_mask = CALL_USED_REGISTERS_MASK (is_64bit_ms_abi);
11256 : :
11257 : : /* If there are no caller-saved registers, add all registers
11258 : : that are clobbered by the call which returns. */
11259 : 16926 : for (int i = 0; i < FIRST_PSEUDO_REGISTER; i++)
11260 : 16744 : if (!fixed_regs[i]
11261 : 3242 : && (ix86_call_used_regs[i] == 1
11262 : 1506 : || (ix86_call_used_regs[i] & c_mask))
11263 : 2150 : && !STACK_REGNO_P (i)
11264 : 2150 : && !MMX_REGNO_P (i))
11265 : 2150 : clobber_reg (&use,
11266 : 2150 : gen_rtx_REG (GET_MODE (regno_reg_rtx[i]), i));
11267 : : }
11268 : 5413185 : else if (TARGET_64BIT_MS_ABI
11269 : 6323556 : && (!callarg2 || INTVAL (callarg2) != -2))
11270 : : {
11271 : : unsigned i;
11272 : :
11273 : 861718 : for (i = 0; i < NUM_X86_64_MS_CLOBBERED_REGS; i++)
11274 : : {
11275 : 795432 : int regno = x86_64_ms_sysv_extra_clobbered_registers[i];
11276 : 795432 : machine_mode mode = SSE_REGNO_P (regno) ? TImode : DImode;
11277 : :
11278 : 795432 : clobber_reg (&use, gen_rtx_REG (mode, regno));
11279 : : }
11280 : :
11281 : : /* Set here, but it may get cleared later. */
11282 : 66286 : if (TARGET_CALL_MS2SYSV_XLOGUES)
11283 : : {
11284 : 7046 : if (!TARGET_SSE)
11285 : : ;
11286 : :
11287 : : /* Don't break hot-patched functions. */
11288 : 7046 : else if (ix86_function_ms_hook_prologue (current_function_decl))
11289 : : ;
11290 : :
11291 : : /* TODO: Cases not yet examined. */
11292 : 7046 : else if (flag_split_stack)
11293 : 0 : warn_once_call_ms2sysv_xlogues ("-fsplit-stack");
11294 : :
11295 : : else
11296 : : {
11297 : 7046 : gcc_assert (!reload_completed);
11298 : 7046 : cfun->machine->call_ms2sysv = true;
11299 : : }
11300 : : }
11301 : : }
11302 : :
11303 : 6250335 : if (TARGET_MACHO && TARGET_64BIT && !sibcall
11304 : : && ((SYMBOL_REF_P (addr) && !SYMBOL_REF_LOCAL_P (addr))
11305 : : || !fndecl || TREE_PUBLIC (fndecl)))
11306 : : {
11307 : : /* We allow public functions defined in a TU to bind locally for PIC
11308 : : code (the default) on 64bit Mach-O.
11309 : : If such functions are not inlined, we cannot tell at compile-time if
11310 : : they will be called via the lazy symbol resolver (this can depend on
11311 : : options given at link-time). Therefore, we must assume that the lazy
11312 : : resolver could be used which clobbers R11 and R10. */
11313 : : clobber_reg (&use, gen_rtx_REG (DImode, R11_REG));
11314 : : clobber_reg (&use, gen_rtx_REG (DImode, R10_REG));
11315 : : }
11316 : :
11317 : 6250335 : if (call_no_callee_saved_registers)
11318 : : {
11319 : : /* After calling a no_callee_saved_registers function, all
11320 : : registers may be clobbered. Clobber all registers that are
11321 : : not used by the callee. */
11322 : 59 : bool is_64bit_ms_abi = (TARGET_64BIT
11323 : 59 : && ix86_function_abi (fndecl) == MS_ABI);
11324 : 59 : char c_mask = CALL_USED_REGISTERS_MASK (is_64bit_ms_abi);
11325 : 5487 : for (int i = 0; i < FIRST_PSEUDO_REGISTER; i++)
11326 : 5428 : if (!fixed_regs[i]
11327 : 2597 : && i != HARD_FRAME_POINTER_REGNUM
11328 : 2538 : && !(ix86_call_used_regs[i] == 1
11329 : 973 : || (ix86_call_used_regs[i] & c_mask))
11330 : 295 : && !STACK_REGNO_P (i)
11331 : 295 : && !MMX_REGNO_P (i))
11332 : 295 : clobber_reg (&use,
11333 : 295 : gen_rtx_REG (GET_MODE (regno_reg_rtx[i]), i));
11334 : : }
11335 : :
11336 : 6250335 : if (vec_len > 1)
11337 : 224802 : call = gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (vec_len, vec));
11338 : 6250335 : rtx_insn *call_insn = emit_call_insn (call);
11339 : 6250335 : if (use)
11340 : 601834 : CALL_INSN_FUNCTION_USAGE (call_insn) = use;
11341 : :
11342 : 6250335 : return call_insn;
11343 : : }
11344 : :
11345 : : /* Split simple return with popping POPC bytes from stack to indirect
11346 : : branch with stack adjustment . */
11347 : :
11348 : : void
11349 : 0 : ix86_split_simple_return_pop_internal (rtx popc)
11350 : : {
11351 : 0 : struct machine_function *m = cfun->machine;
11352 : 0 : rtx ecx = gen_rtx_REG (SImode, CX_REG);
11353 : 0 : rtx_insn *insn;
11354 : :
11355 : : /* There is no "pascal" calling convention in any 64bit ABI. */
11356 : 0 : gcc_assert (!TARGET_64BIT);
11357 : :
11358 : 0 : insn = emit_insn (gen_pop (ecx));
11359 : 0 : m->fs.cfa_offset -= UNITS_PER_WORD;
11360 : 0 : m->fs.sp_offset -= UNITS_PER_WORD;
11361 : :
11362 : 0 : rtx x = plus_constant (Pmode, stack_pointer_rtx, UNITS_PER_WORD);
11363 : 0 : x = gen_rtx_SET (stack_pointer_rtx, x);
11364 : 0 : add_reg_note (insn, REG_CFA_ADJUST_CFA, x);
11365 : 0 : add_reg_note (insn, REG_CFA_REGISTER, gen_rtx_SET (ecx, pc_rtx));
11366 : 0 : RTX_FRAME_RELATED_P (insn) = 1;
11367 : :
11368 : 0 : x = gen_rtx_PLUS (Pmode, stack_pointer_rtx, popc);
11369 : 0 : x = gen_rtx_SET (stack_pointer_rtx, x);
11370 : 0 : insn = emit_insn (x);
11371 : 0 : add_reg_note (insn, REG_CFA_ADJUST_CFA, x);
11372 : 0 : RTX_FRAME_RELATED_P (insn) = 1;
11373 : :
11374 : : /* Now return address is in ECX. */
11375 : 0 : emit_jump_insn (gen_simple_return_indirect_internal (ecx));
11376 : 0 : }
11377 : :
11378 : : /* Errors in the source file can cause expand_expr to return const0_rtx
11379 : : where we expect a vector. To avoid crashing, use one of the vector
11380 : : clear instructions. */
11381 : :
11382 : : static rtx
11383 : 196917 : safe_vector_operand (rtx x, machine_mode mode)
11384 : : {
11385 : 0 : if (x == const0_rtx)
11386 : 0 : x = CONST0_RTX (mode);
11387 : 24 : return x;
11388 : : }
11389 : :
11390 : : /* Subroutine of ix86_expand_builtin to take care of binop insns. */
11391 : :
11392 : : static rtx
11393 : 9035 : ix86_expand_binop_builtin (enum insn_code icode, tree exp, rtx target)
11394 : : {
11395 : 9035 : rtx pat;
11396 : 9035 : tree arg0 = CALL_EXPR_ARG (exp, 0);
11397 : 9035 : tree arg1 = CALL_EXPR_ARG (exp, 1);
11398 : 9035 : rtx op0 = expand_normal (arg0);
11399 : 9035 : rtx op1 = expand_normal (arg1);
11400 : 9035 : machine_mode tmode = insn_data[icode].operand[0].mode;
11401 : 9035 : machine_mode mode0 = insn_data[icode].operand[1].mode;
11402 : 9035 : machine_mode mode1 = insn_data[icode].operand[2].mode;
11403 : :
11404 : 9035 : if (VECTOR_MODE_P (mode0))
11405 : 9024 : op0 = safe_vector_operand (op0, mode0);
11406 : 9035 : if (VECTOR_MODE_P (mode1))
11407 : 8888 : op1 = safe_vector_operand (op1, mode1);
11408 : :
11409 : 2900 : if (optimize || !target
11410 : 2900 : || GET_MODE (target) != tmode
11411 : 11935 : || !insn_data[icode].operand[0].predicate (target, tmode))
11412 : 6188 : target = gen_reg_rtx (tmode);
11413 : :
11414 : 9035 : if (GET_MODE (op1) == SImode && mode1 == TImode)
11415 : : {
11416 : 0 : rtx x = gen_reg_rtx (V4SImode);
11417 : 0 : emit_insn (gen_sse2_loadd (x, op1));
11418 : 0 : op1 = gen_lowpart (TImode, x);
11419 : : }
11420 : :
11421 : 9035 : if (!insn_data[icode].operand[1].predicate (op0, mode0))
11422 : 1452 : op0 = copy_to_mode_reg (mode0, op0);
11423 : 9035 : if (!insn_data[icode].operand[2].predicate (op1, mode1))
11424 : 816 : op1 = copy_to_mode_reg (mode1, op1);
11425 : :
11426 : 9035 : pat = GEN_FCN (icode) (target, op0, op1);
11427 : 9035 : if (! pat)
11428 : : return 0;
11429 : :
11430 : 9035 : emit_insn (pat);
11431 : :
11432 : 9035 : return target;
11433 : : }
11434 : :
11435 : : /* Subroutine of ix86_expand_builtin to take care of 2-4 argument insns. */
11436 : :
11437 : : static rtx
11438 : 1792 : ix86_expand_multi_arg_builtin (enum insn_code icode, tree exp, rtx target,
11439 : : enum ix86_builtin_func_type m_type,
11440 : : enum rtx_code sub_code)
11441 : : {
11442 : 1792 : rtx pat;
11443 : 1792 : unsigned int i, nargs;
11444 : 1792 : bool comparison_p = false;
11445 : 1792 : bool tf_p = false;
11446 : 1792 : bool last_arg_constant = false;
11447 : 1792 : int num_memory = 0;
11448 : 1792 : rtx xops[4];
11449 : :
11450 : 1792 : machine_mode tmode = insn_data[icode].operand[0].mode;
11451 : :
11452 : 1792 : switch (m_type)
11453 : : {
11454 : : case MULTI_ARG_4_DF2_DI_I:
11455 : : case MULTI_ARG_4_DF2_DI_I1:
11456 : : case MULTI_ARG_4_SF2_SI_I:
11457 : : case MULTI_ARG_4_SF2_SI_I1:
11458 : : nargs = 4;
11459 : : last_arg_constant = true;
11460 : : break;
11461 : :
11462 : 821 : case MULTI_ARG_3_SF:
11463 : 821 : case MULTI_ARG_3_DF:
11464 : 821 : case MULTI_ARG_3_SF2:
11465 : 821 : case MULTI_ARG_3_DF2:
11466 : 821 : case MULTI_ARG_3_DI:
11467 : 821 : case MULTI_ARG_3_SI:
11468 : 821 : case MULTI_ARG_3_SI_DI:
11469 : 821 : case MULTI_ARG_3_HI:
11470 : 821 : case MULTI_ARG_3_HI_SI:
11471 : 821 : case MULTI_ARG_3_QI:
11472 : 821 : case MULTI_ARG_3_DI2:
11473 : 821 : case MULTI_ARG_3_SI2:
11474 : 821 : case MULTI_ARG_3_HI2:
11475 : 821 : case MULTI_ARG_3_QI2:
11476 : 821 : nargs = 3;
11477 : 821 : break;
11478 : :
11479 : 128 : case MULTI_ARG_2_SF:
11480 : 128 : case MULTI_ARG_2_DF:
11481 : 128 : case MULTI_ARG_2_DI:
11482 : 128 : case MULTI_ARG_2_SI:
11483 : 128 : case MULTI_ARG_2_HI:
11484 : 128 : case MULTI_ARG_2_QI:
11485 : 128 : nargs = 2;
11486 : 128 : break;
11487 : :
11488 : 64 : case MULTI_ARG_2_DI_IMM:
11489 : 64 : case MULTI_ARG_2_SI_IMM:
11490 : 64 : case MULTI_ARG_2_HI_IMM:
11491 : 64 : case MULTI_ARG_2_QI_IMM:
11492 : 64 : nargs = 2;
11493 : 64 : last_arg_constant = true;
11494 : 64 : break;
11495 : :
11496 : 187 : case MULTI_ARG_1_SF:
11497 : 187 : case MULTI_ARG_1_DF:
11498 : 187 : case MULTI_ARG_1_SF2:
11499 : 187 : case MULTI_ARG_1_DF2:
11500 : 187 : case MULTI_ARG_1_DI:
11501 : 187 : case MULTI_ARG_1_SI:
11502 : 187 : case MULTI_ARG_1_HI:
11503 : 187 : case MULTI_ARG_1_QI:
11504 : 187 : case MULTI_ARG_1_SI_DI:
11505 : 187 : case MULTI_ARG_1_HI_DI:
11506 : 187 : case MULTI_ARG_1_HI_SI:
11507 : 187 : case MULTI_ARG_1_QI_DI:
11508 : 187 : case MULTI_ARG_1_QI_SI:
11509 : 187 : case MULTI_ARG_1_QI_HI:
11510 : 187 : nargs = 1;
11511 : 187 : break;
11512 : :
11513 : 384 : case MULTI_ARG_2_DI_CMP:
11514 : 384 : case MULTI_ARG_2_SI_CMP:
11515 : 384 : case MULTI_ARG_2_HI_CMP:
11516 : 384 : case MULTI_ARG_2_QI_CMP:
11517 : 384 : nargs = 2;
11518 : 384 : comparison_p = true;
11519 : 384 : break;
11520 : :
11521 : 128 : case MULTI_ARG_2_SF_TF:
11522 : 128 : case MULTI_ARG_2_DF_TF:
11523 : 128 : case MULTI_ARG_2_DI_TF:
11524 : 128 : case MULTI_ARG_2_SI_TF:
11525 : 128 : case MULTI_ARG_2_HI_TF:
11526 : 128 : case MULTI_ARG_2_QI_TF:
11527 : 128 : nargs = 2;
11528 : 128 : tf_p = true;
11529 : 128 : break;
11530 : :
11531 : 0 : default:
11532 : 0 : gcc_unreachable ();
11533 : : }
11534 : :
11535 : 628 : if (optimize || !target
11536 : 628 : || GET_MODE (target) != tmode
11537 : 2396 : || !insn_data[icode].operand[0].predicate (target, tmode))
11538 : 1188 : target = gen_reg_rtx (tmode);
11539 : 604 : else if (memory_operand (target, tmode))
11540 : 0 : num_memory++;
11541 : :
11542 : 1792 : gcc_assert (nargs <= ARRAY_SIZE (xops));
11543 : :
11544 : 6162 : for (i = 0; i < nargs; i++)
11545 : : {
11546 : 4378 : tree arg = CALL_EXPR_ARG (exp, i);
11547 : 4378 : rtx op = expand_normal (arg);
11548 : 4378 : int adjust = (comparison_p) ? 1 : 0;
11549 : 4378 : machine_mode mode = insn_data[icode].operand[i+adjust+1].mode;
11550 : :
11551 : 4378 : if (last_arg_constant && i == nargs - 1)
11552 : : {
11553 : 144 : if (!insn_data[icode].operand[i + 1].predicate (op, mode))
11554 : : {
11555 : 30 : enum insn_code new_icode = icode;
11556 : 30 : switch (icode)
11557 : : {
11558 : 8 : case CODE_FOR_xop_vpermil2v2df3:
11559 : 8 : case CODE_FOR_xop_vpermil2v4sf3:
11560 : 8 : case CODE_FOR_xop_vpermil2v4df3:
11561 : 8 : case CODE_FOR_xop_vpermil2v8sf3:
11562 : 8 : error ("the last argument must be a 2-bit immediate");
11563 : 8 : return gen_reg_rtx (tmode);
11564 : 5 : case CODE_FOR_xop_rotlv2di3:
11565 : 5 : new_icode = CODE_FOR_rotlv2di3;
11566 : 5 : goto xop_rotl;
11567 : 5 : case CODE_FOR_xop_rotlv4si3:
11568 : 5 : new_icode = CODE_FOR_rotlv4si3;
11569 : 5 : goto xop_rotl;
11570 : 6 : case CODE_FOR_xop_rotlv8hi3:
11571 : 6 : new_icode = CODE_FOR_rotlv8hi3;
11572 : 6 : goto xop_rotl;
11573 : : case CODE_FOR_xop_rotlv16qi3:
11574 : : new_icode = CODE_FOR_rotlv16qi3;
11575 : 22 : xop_rotl:
11576 : 22 : if (CONST_INT_P (op))
11577 : : {
11578 : 6 : int mask = GET_MODE_UNIT_BITSIZE (tmode) - 1;
11579 : 6 : op = GEN_INT (INTVAL (op) & mask);
11580 : 6 : gcc_checking_assert
11581 : : (insn_data[icode].operand[i + 1].predicate (op, mode));
11582 : : }
11583 : : else
11584 : : {
11585 : 16 : gcc_checking_assert
11586 : : (nargs == 2
11587 : : && insn_data[new_icode].operand[0].mode == tmode
11588 : : && insn_data[new_icode].operand[1].mode == tmode
11589 : : && insn_data[new_icode].operand[2].mode == mode
11590 : : && insn_data[new_icode].operand[0].predicate
11591 : : == insn_data[icode].operand[0].predicate
11592 : : && insn_data[new_icode].operand[1].predicate
11593 : : == insn_data[icode].operand[1].predicate);
11594 : 16 : icode = new_icode;
11595 : 16 : goto non_constant;
11596 : : }
11597 : : break;
11598 : 0 : default:
11599 : 0 : gcc_unreachable ();
11600 : : }
11601 : : }
11602 : : }
11603 : : else
11604 : : {
11605 : 4234 : non_constant:
11606 : 4250 : if (VECTOR_MODE_P (mode))
11607 : 4234 : op = safe_vector_operand (op, mode);
11608 : :
11609 : : /* If we aren't optimizing, only allow one memory operand to be
11610 : : generated. */
11611 : 4250 : if (memory_operand (op, mode))
11612 : 826 : num_memory++;
11613 : :
11614 : 4250 : gcc_assert (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode);
11615 : :
11616 : 4250 : if (optimize
11617 : 1506 : || !insn_data[icode].operand[i+adjust+1].predicate (op, mode)
11618 : 5678 : || num_memory > 1)
11619 : 3329 : op = force_reg (mode, op);
11620 : : }
11621 : :
11622 : 4370 : xops[i] = op;
11623 : : }
11624 : :
11625 : 1784 : switch (nargs)
11626 : : {
11627 : 187 : case 1:
11628 : 187 : pat = GEN_FCN (icode) (target, xops[0]);
11629 : 187 : break;
11630 : :
11631 : 704 : case 2:
11632 : 704 : if (tf_p)
11633 : 128 : pat = GEN_FCN (icode) (target, xops[0], xops[1],
11634 : 128 : GEN_INT ((int)sub_code));
11635 : 576 : else if (! comparison_p)
11636 : 192 : pat = GEN_FCN (icode) (target, xops[0], xops[1]);
11637 : : else
11638 : : {
11639 : 384 : rtx cmp_op = gen_rtx_fmt_ee (sub_code, GET_MODE (target),
11640 : : xops[0], xops[1]);
11641 : :
11642 : 384 : pat = GEN_FCN (icode) (target, cmp_op, xops[0], xops[1]);
11643 : : }
11644 : : break;
11645 : :
11646 : 821 : case 3:
11647 : 821 : pat = GEN_FCN (icode) (target, xops[0], xops[1], xops[2]);
11648 : 821 : break;
11649 : :
11650 : 72 : case 4:
11651 : 72 : pat = GEN_FCN (icode) (target, xops[0], xops[1], xops[2], xops[3]);
11652 : 72 : break;
11653 : :
11654 : : default:
11655 : : gcc_unreachable ();
11656 : : }
11657 : :
11658 : 1784 : if (! pat)
11659 : : return 0;
11660 : :
11661 : 1784 : emit_insn (pat);
11662 : 1784 : return target;
11663 : : }
11664 : :
11665 : : /* Subroutine of ix86_expand_args_builtin to take care of scalar unop
11666 : : insns with vec_merge. */
11667 : :
11668 : : static rtx
11669 : 52 : ix86_expand_unop_vec_merge_builtin (enum insn_code icode, tree exp,
11670 : : rtx target)
11671 : : {
11672 : 52 : rtx pat;
11673 : 52 : tree arg0 = CALL_EXPR_ARG (exp, 0);
11674 : 52 : rtx op1, op0 = expand_normal (arg0);
11675 : 52 : machine_mode tmode = insn_data[icode].operand[0].mode;
11676 : 52 : machine_mode mode0 = insn_data[icode].operand[1].mode;
11677 : :
11678 : 16 : if (optimize || !target
11679 : 16 : || GET_MODE (target) != tmode
11680 : 68 : || !insn_data[icode].operand[0].predicate (target, tmode))
11681 : 36 : target = gen_reg_rtx (tmode);
11682 : :
11683 : 52 : if (VECTOR_MODE_P (mode0))
11684 : 52 : op0 = safe_vector_operand (op0, mode0);
11685 : :
11686 : 36 : if ((optimize && !register_operand (op0, mode0))
11687 : 88 : || !insn_data[icode].operand[1].predicate (op0, mode0))
11688 : 0 : op0 = copy_to_mode_reg (mode0, op0);
11689 : :
11690 : 52 : op1 = op0;
11691 : 52 : if (!insn_data[icode].operand[2].predicate (op1, mode0))
11692 : 16 : op1 = copy_to_mode_reg (mode0, op1);
11693 : :
11694 : 52 : pat = GEN_FCN (icode) (target, op0, op1);
11695 : 52 : if (! pat)
11696 : : return 0;
11697 : 52 : emit_insn (pat);
11698 : 52 : return target;
11699 : : }
11700 : :
11701 : : /* Subroutine of ix86_expand_builtin to take care of comparison insns. */
11702 : :
11703 : : static rtx
11704 : 614 : ix86_expand_sse_compare (const struct builtin_description *d,
11705 : : tree exp, rtx target, bool swap)
11706 : : {
11707 : 614 : rtx pat;
11708 : 614 : tree arg0 = CALL_EXPR_ARG (exp, 0);
11709 : 614 : tree arg1 = CALL_EXPR_ARG (exp, 1);
11710 : 614 : rtx op0 = expand_normal (arg0);
11711 : 614 : rtx op1 = expand_normal (arg1);
11712 : 614 : rtx op2;
11713 : 614 : machine_mode tmode = insn_data[d->icode].operand[0].mode;
11714 : 614 : machine_mode mode0 = insn_data[d->icode].operand[1].mode;
11715 : 614 : machine_mode mode1 = insn_data[d->icode].operand[2].mode;
11716 : 614 : enum rtx_code comparison = d->comparison;
11717 : :
11718 : 614 : if (VECTOR_MODE_P (mode0))
11719 : 614 : op0 = safe_vector_operand (op0, mode0);
11720 : 614 : if (VECTOR_MODE_P (mode1))
11721 : 614 : op1 = safe_vector_operand (op1, mode1);
11722 : :
11723 : : /* Swap operands if we have a comparison that isn't available in
11724 : : hardware. */
11725 : 614 : if (swap)
11726 : 80 : std::swap (op0, op1);
11727 : :
11728 : 202 : if (optimize || !target
11729 : 202 : || GET_MODE (target) != tmode
11730 : 816 : || !insn_data[d->icode].operand[0].predicate (target, tmode))
11731 : 412 : target = gen_reg_rtx (tmode);
11732 : :
11733 : 412 : if ((optimize && !register_operand (op0, mode0))
11734 : 956 : || !insn_data[d->icode].operand[1].predicate (op0, mode0))
11735 : 272 : op0 = copy_to_mode_reg (mode0, op0);
11736 : 412 : if ((optimize && !register_operand (op1, mode1))
11737 : 972 : || !insn_data[d->icode].operand[2].predicate (op1, mode1))
11738 : 54 : op1 = copy_to_mode_reg (mode1, op1);
11739 : :
11740 : 614 : op2 = gen_rtx_fmt_ee (comparison, mode0, op0, op1);
11741 : 614 : pat = GEN_FCN (d->icode) (target, op0, op1, op2);
11742 : 614 : if (! pat)
11743 : : return 0;
11744 : 614 : emit_insn (pat);
11745 : 614 : return target;
11746 : : }
11747 : :
11748 : : /* Subroutine of ix86_sse_comi and ix86_sse_comi_round to take care of
11749 : : * ordered EQ or unordered NE, generate PF jump. */
11750 : :
11751 : : static rtx
11752 : 644 : ix86_ssecom_setcc (const enum rtx_code comparison,
11753 : : bool check_unordered, machine_mode mode,
11754 : : rtx set_dst, rtx target)
11755 : : {
11756 : :
11757 : 644 : rtx_code_label *label = NULL;
11758 : :
11759 : : /* NB: For ordered EQ or unordered NE, check ZF alone isn't sufficient
11760 : : with NAN operands.
11761 : : Under TARGET_AVX10_2, VCOMX/VUCOMX are generated instead of
11762 : : COMI/UCOMI. VCOMX/VUCOMX will not set ZF for NAN operands. */
11763 : 644 : if (check_unordered)
11764 : : {
11765 : 122 : gcc_assert (comparison == EQ || comparison == NE);
11766 : :
11767 : 122 : rtx flag = gen_rtx_REG (CCFPmode, FLAGS_REG);
11768 : 122 : label = gen_label_rtx ();
11769 : 122 : rtx tmp = gen_rtx_fmt_ee (UNORDERED, VOIDmode, flag, const0_rtx);
11770 : 122 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
11771 : : gen_rtx_LABEL_REF (VOIDmode, label),
11772 : : pc_rtx);
11773 : 122 : emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
11774 : : }
11775 : :
11776 : : /* NB: Set CCFPmode and check a different CCmode which is in subset
11777 : : of CCFPmode. */
11778 : 644 : if (GET_MODE (set_dst) != mode)
11779 : : {
11780 : 200 : gcc_assert (mode == CCAmode || mode == CCCmode
11781 : : || mode == CCOmode || mode == CCPmode
11782 : : || mode == CCSmode || mode == CCZmode);
11783 : 200 : set_dst = gen_rtx_REG (mode, FLAGS_REG);
11784 : : }
11785 : :
11786 : 644 : emit_insn (gen_rtx_SET (gen_rtx_STRICT_LOW_PART (VOIDmode, target),
11787 : : gen_rtx_fmt_ee (comparison, QImode,
11788 : : set_dst,
11789 : : const0_rtx)));
11790 : :
11791 : 644 : if (label)
11792 : 122 : emit_label (label);
11793 : :
11794 : 644 : return SUBREG_REG (target);
11795 : : }
11796 : :
11797 : : /* Subroutine of ix86_expand_builtin to take care of comi insns. */
11798 : :
11799 : : static rtx
11800 : 545 : ix86_expand_sse_comi (const struct builtin_description *d, tree exp,
11801 : : rtx target, bool comx_ok)
11802 : : {
11803 : 545 : rtx pat, set_dst;
11804 : 545 : tree arg0 = CALL_EXPR_ARG (exp, 0);
11805 : 545 : tree arg1 = CALL_EXPR_ARG (exp, 1);
11806 : 545 : rtx op0 = expand_normal (arg0);
11807 : 545 : rtx op1 = expand_normal (arg1);
11808 : 545 : enum insn_code icode = d->icode;
11809 : 545 : const struct insn_data_d *insn_p = &insn_data[icode];
11810 : 545 : machine_mode mode0 = insn_p->operand[0].mode;
11811 : 545 : machine_mode mode1 = insn_p->operand[1].mode;
11812 : :
11813 : 545 : if (VECTOR_MODE_P (mode0))
11814 : 545 : op0 = safe_vector_operand (op0, mode0);
11815 : 545 : if (VECTOR_MODE_P (mode1))
11816 : 545 : op1 = safe_vector_operand (op1, mode1);
11817 : :
11818 : 545 : enum rtx_code comparison = d->comparison;
11819 : 545 : rtx const_val = const0_rtx;
11820 : :
11821 : 545 : bool check_unordered = false;
11822 : 545 : machine_mode mode = CCFPmode;
11823 : 545 : switch (comparison)
11824 : : {
11825 : 192 : case LE: /* -> GE */
11826 : 192 : case LT: /* -> GT */
11827 : 192 : std::swap (op0, op1);
11828 : 192 : comparison = swap_condition (comparison);
11829 : : /* FALLTHRU */
11830 : : case GT:
11831 : : case GE:
11832 : : break;
11833 : 73 : case EQ:
11834 : 73 : if (!TARGET_AVX10_2 || !comx_ok)
11835 : 45 : check_unordered = true;
11836 : : mode = CCZmode;
11837 : : break;
11838 : 96 : case NE:
11839 : 96 : if (!TARGET_AVX10_2 || !comx_ok)
11840 : 68 : check_unordered = true;
11841 : 96 : mode = CCZmode;
11842 : 96 : const_val = const1_rtx;
11843 : 96 : break;
11844 : 0 : default:
11845 : 0 : gcc_unreachable ();
11846 : : }
11847 : :
11848 : 545 : target = gen_reg_rtx (SImode);
11849 : 545 : emit_move_insn (target, const_val);
11850 : 545 : target = gen_rtx_SUBREG (QImode, target, 0);
11851 : :
11852 : 424 : if ((optimize && !register_operand (op0, mode0))
11853 : 921 : || !insn_p->operand[0].predicate (op0, mode0))
11854 : 169 : op0 = copy_to_mode_reg (mode0, op0);
11855 : 424 : if ((optimize && !register_operand (op1, mode1))
11856 : 921 : || !insn_p->operand[1].predicate (op1, mode1))
11857 : 48 : op1 = copy_to_mode_reg (mode1, op1);
11858 : :
11859 : 545 : if ((comparison == EQ || comparison == NE)
11860 : 169 : && TARGET_AVX10_2 && comx_ok)
11861 : : {
11862 : 56 : switch (icode)
11863 : : {
11864 : : case CODE_FOR_sse_comi:
11865 : : icode = CODE_FOR_avx10_2_comxsf;
11866 : : break;
11867 : 14 : case CODE_FOR_sse_ucomi:
11868 : 14 : icode = CODE_FOR_avx10_2_ucomxsf;
11869 : 14 : break;
11870 : 14 : case CODE_FOR_sse2_comi:
11871 : 14 : icode = CODE_FOR_avx10_2_comxdf;
11872 : 14 : break;
11873 : 14 : case CODE_FOR_sse2_ucomi:
11874 : 14 : icode = CODE_FOR_avx10_2_ucomxdf;
11875 : 14 : break;
11876 : :
11877 : 0 : default:
11878 : 0 : gcc_unreachable ();
11879 : : }
11880 : : }
11881 : 545 : pat = GEN_FCN (icode) (op0, op1);
11882 : 545 : if (! pat)
11883 : : return 0;
11884 : :
11885 : 545 : set_dst = SET_DEST (pat);
11886 : 545 : emit_insn (pat);
11887 : 545 : return ix86_ssecom_setcc (comparison, check_unordered, mode,
11888 : 545 : set_dst, target);
11889 : : }
11890 : :
11891 : : /* Subroutines of ix86_expand_args_builtin to take care of round insns. */
11892 : :
11893 : : static rtx
11894 : 0 : ix86_expand_sse_round (const struct builtin_description *d, tree exp,
11895 : : rtx target)
11896 : : {
11897 : 0 : rtx pat;
11898 : 0 : tree arg0 = CALL_EXPR_ARG (exp, 0);
11899 : 0 : rtx op1, op0 = expand_normal (arg0);
11900 : 0 : machine_mode tmode = insn_data[d->icode].operand[0].mode;
11901 : 0 : machine_mode mode0 = insn_data[d->icode].operand[1].mode;
11902 : :
11903 : 0 : if (optimize || target == 0
11904 : 0 : || GET_MODE (target) != tmode
11905 : 0 : || !insn_data[d->icode].operand[0].predicate (target, tmode))
11906 : 0 : target = gen_reg_rtx (tmode);
11907 : :
11908 : 0 : if (VECTOR_MODE_P (mode0))
11909 : 0 : op0 = safe_vector_operand (op0, mode0);
11910 : :
11911 : 0 : if ((optimize && !register_operand (op0, mode0))
11912 : 0 : || !insn_data[d->icode].operand[0].predicate (op0, mode0))
11913 : 0 : op0 = copy_to_mode_reg (mode0, op0);
11914 : :
11915 : 0 : op1 = GEN_INT (d->comparison);
11916 : :
11917 : 0 : pat = GEN_FCN (d->icode) (target, op0, op1);
11918 : 0 : if (! pat)
11919 : : return 0;
11920 : 0 : emit_insn (pat);
11921 : 0 : return target;
11922 : : }
11923 : :
11924 : : static rtx
11925 : 12 : ix86_expand_sse_round_vec_pack_sfix (const struct builtin_description *d,
11926 : : tree exp, rtx target)
11927 : : {
11928 : 12 : rtx pat;
11929 : 12 : tree arg0 = CALL_EXPR_ARG (exp, 0);
11930 : 12 : tree arg1 = CALL_EXPR_ARG (exp, 1);
11931 : 12 : rtx op0 = expand_normal (arg0);
11932 : 12 : rtx op1 = expand_normal (arg1);
11933 : 12 : rtx op2;
11934 : 12 : machine_mode tmode = insn_data[d->icode].operand[0].mode;
11935 : 12 : machine_mode mode0 = insn_data[d->icode].operand[1].mode;
11936 : 12 : machine_mode mode1 = insn_data[d->icode].operand[2].mode;
11937 : :
11938 : 0 : if (optimize || target == 0
11939 : 0 : || GET_MODE (target) != tmode
11940 : 12 : || !insn_data[d->icode].operand[0].predicate (target, tmode))
11941 : 12 : target = gen_reg_rtx (tmode);
11942 : :
11943 : 12 : op0 = safe_vector_operand (op0, mode0);
11944 : 12 : op1 = safe_vector_operand (op1, mode1);
11945 : :
11946 : 12 : if ((optimize && !register_operand (op0, mode0))
11947 : 12 : || !insn_data[d->icode].operand[0].predicate (op0, mode0))
11948 : 12 : op0 = copy_to_mode_reg (mode0, op0);
11949 : 12 : if ((optimize && !register_operand (op1, mode1))
11950 : 12 : || !insn_data[d->icode].operand[1].predicate (op1, mode1))
11951 : 12 : op1 = copy_to_mode_reg (mode1, op1);
11952 : :
11953 : 12 : op2 = GEN_INT (d->comparison);
11954 : :
11955 : 12 : pat = GEN_FCN (d->icode) (target, op0, op1, op2);
11956 : 12 : if (! pat)
11957 : : return 0;
11958 : 12 : emit_insn (pat);
11959 : 12 : return target;
11960 : : }
11961 : :
11962 : : /* Subroutine of ix86_expand_builtin to take care of ptest insns. */
11963 : :
11964 : : static rtx
11965 : 235 : ix86_expand_sse_ptest (const struct builtin_description *d, tree exp,
11966 : : rtx target)
11967 : : {
11968 : 235 : rtx pat;
11969 : 235 : tree arg0 = CALL_EXPR_ARG (exp, 0);
11970 : 235 : tree arg1 = CALL_EXPR_ARG (exp, 1);
11971 : 235 : rtx op0 = expand_normal (arg0);
11972 : 235 : rtx op1 = expand_normal (arg1);
11973 : 235 : machine_mode mode0 = insn_data[d->icode].operand[0].mode;
11974 : 235 : machine_mode mode1 = insn_data[d->icode].operand[1].mode;
11975 : 235 : enum rtx_code comparison = d->comparison;
11976 : :
11977 : : /* ptest reg, reg sets the carry flag. */
11978 : 235 : if (comparison == LTU
11979 : 75 : && (d->code == IX86_BUILTIN_PTESTC
11980 : 57 : || d->code == IX86_BUILTIN_PTESTC256)
11981 : 266 : && rtx_equal_p (op0, op1))
11982 : : {
11983 : 2 : if (!target)
11984 : 0 : target = gen_reg_rtx (SImode);
11985 : 2 : emit_move_insn (target, const1_rtx);
11986 : 2 : return target;
11987 : : }
11988 : :
11989 : 233 : if (VECTOR_MODE_P (mode0))
11990 : 233 : op0 = safe_vector_operand (op0, mode0);
11991 : 233 : if (VECTOR_MODE_P (mode1))
11992 : 233 : op1 = safe_vector_operand (op1, mode1);
11993 : :
11994 : 233 : target = gen_reg_rtx (SImode);
11995 : 233 : emit_move_insn (target, const0_rtx);
11996 : 233 : target = gen_rtx_SUBREG (QImode, target, 0);
11997 : :
11998 : 161 : if ((optimize && !register_operand (op0, mode0))
11999 : 366 : || !insn_data[d->icode].operand[0].predicate (op0, mode0))
12000 : 100 : op0 = copy_to_mode_reg (mode0, op0);
12001 : 161 : if ((optimize && !register_operand (op1, mode1))
12002 : 367 : || !insn_data[d->icode].operand[1].predicate (op1, mode1))
12003 : 27 : op1 = copy_to_mode_reg (mode1, op1);
12004 : :
12005 : 233 : pat = GEN_FCN (d->icode) (op0, op1);
12006 : 233 : if (! pat)
12007 : : return 0;
12008 : 233 : emit_insn (pat);
12009 : 233 : emit_insn (gen_rtx_SET (gen_rtx_STRICT_LOW_PART (VOIDmode, target),
12010 : : gen_rtx_fmt_ee (comparison, QImode,
12011 : : SET_DEST (pat),
12012 : : const0_rtx)));
12013 : :
12014 : 233 : return SUBREG_REG (target);
12015 : : }
12016 : :
12017 : : /* Subroutine of ix86_expand_builtin to take care of pcmpestr[im] insns. */
12018 : :
12019 : : static rtx
12020 : 216 : ix86_expand_sse_pcmpestr (const struct builtin_description *d,
12021 : : tree exp, rtx target)
12022 : : {
12023 : 216 : rtx pat;
12024 : 216 : tree arg0 = CALL_EXPR_ARG (exp, 0);
12025 : 216 : tree arg1 = CALL_EXPR_ARG (exp, 1);
12026 : 216 : tree arg2 = CALL_EXPR_ARG (exp, 2);
12027 : 216 : tree arg3 = CALL_EXPR_ARG (exp, 3);
12028 : 216 : tree arg4 = CALL_EXPR_ARG (exp, 4);
12029 : 216 : rtx scratch0, scratch1;
12030 : 216 : rtx op0 = expand_normal (arg0);
12031 : 216 : rtx op1 = expand_normal (arg1);
12032 : 216 : rtx op2 = expand_normal (arg2);
12033 : 216 : rtx op3 = expand_normal (arg3);
12034 : 216 : rtx op4 = expand_normal (arg4);
12035 : 216 : machine_mode tmode0, tmode1, modev2, modei3, modev4, modei5, modeimm;
12036 : :
12037 : 216 : tmode0 = insn_data[d->icode].operand[0].mode;
12038 : 216 : tmode1 = insn_data[d->icode].operand[1].mode;
12039 : 216 : modev2 = insn_data[d->icode].operand[2].mode;
12040 : 216 : modei3 = insn_data[d->icode].operand[3].mode;
12041 : 216 : modev4 = insn_data[d->icode].operand[4].mode;
12042 : 216 : modei5 = insn_data[d->icode].operand[5].mode;
12043 : 216 : modeimm = insn_data[d->icode].operand[6].mode;
12044 : :
12045 : 216 : if (VECTOR_MODE_P (modev2))
12046 : 216 : op0 = safe_vector_operand (op0, modev2);
12047 : 216 : if (VECTOR_MODE_P (modev4))
12048 : 216 : op2 = safe_vector_operand (op2, modev4);
12049 : :
12050 : 216 : if (!insn_data[d->icode].operand[2].predicate (op0, modev2))
12051 : 6 : op0 = copy_to_mode_reg (modev2, op0);
12052 : 216 : if (!insn_data[d->icode].operand[3].predicate (op1, modei3))
12053 : 34 : op1 = copy_to_mode_reg (modei3, op1);
12054 : 160 : if ((optimize && !register_operand (op2, modev4))
12055 : 371 : || !insn_data[d->icode].operand[4].predicate (op2, modev4))
12056 : 5 : op2 = copy_to_mode_reg (modev4, op2);
12057 : 216 : if (!insn_data[d->icode].operand[5].predicate (op3, modei5))
12058 : 34 : op3 = copy_to_mode_reg (modei5, op3);
12059 : :
12060 : 216 : if (!insn_data[d->icode].operand[6].predicate (op4, modeimm))
12061 : : {
12062 : 21 : error ("the fifth argument must be an 8-bit immediate");
12063 : 21 : return const0_rtx;
12064 : : }
12065 : :
12066 : 195 : if (d->code == IX86_BUILTIN_PCMPESTRI128)
12067 : : {
12068 : 5 : if (optimize || !target
12069 : 5 : || GET_MODE (target) != tmode0
12070 : 34 : || !insn_data[d->icode].operand[0].predicate (target, tmode0))
12071 : 24 : target = gen_reg_rtx (tmode0);
12072 : :
12073 : 29 : scratch1 = gen_reg_rtx (tmode1);
12074 : :
12075 : 29 : pat = GEN_FCN (d->icode) (target, scratch1, op0, op1, op2, op3, op4);
12076 : : }
12077 : 166 : else if (d->code == IX86_BUILTIN_PCMPESTRM128)
12078 : : {
12079 : 5 : if (optimize || !target
12080 : 5 : || GET_MODE (target) != tmode1
12081 : 36 : || !insn_data[d->icode].operand[1].predicate (target, tmode1))
12082 : 26 : target = gen_reg_rtx (tmode1);
12083 : :
12084 : 31 : scratch0 = gen_reg_rtx (tmode0);
12085 : :
12086 : 31 : pat = GEN_FCN (d->icode) (scratch0, target, op0, op1, op2, op3, op4);
12087 : : }
12088 : : else
12089 : : {
12090 : 135 : gcc_assert (d->flag);
12091 : :
12092 : 135 : scratch0 = gen_reg_rtx (tmode0);
12093 : 135 : scratch1 = gen_reg_rtx (tmode1);
12094 : :
12095 : 135 : pat = GEN_FCN (d->icode) (scratch0, scratch1, op0, op1, op2, op3, op4);
12096 : : }
12097 : :
12098 : 195 : if (! pat)
12099 : : return 0;
12100 : :
12101 : 195 : emit_insn (pat);
12102 : :
12103 : 195 : if (d->flag)
12104 : : {
12105 : 135 : target = gen_reg_rtx (SImode);
12106 : 135 : emit_move_insn (target, const0_rtx);
12107 : 135 : target = gen_rtx_SUBREG (QImode, target, 0);
12108 : :
12109 : 135 : emit_insn
12110 : 135 : (gen_rtx_SET (gen_rtx_STRICT_LOW_PART (VOIDmode, target),
12111 : : gen_rtx_fmt_ee (EQ, QImode,
12112 : : gen_rtx_REG ((machine_mode) d->flag,
12113 : : FLAGS_REG),
12114 : : const0_rtx)));
12115 : 135 : return SUBREG_REG (target);
12116 : : }
12117 : : else
12118 : : return target;
12119 : : }
12120 : :
12121 : :
12122 : : /* Subroutine of ix86_expand_builtin to take care of pcmpistr[im] insns. */
12123 : :
12124 : : static rtx
12125 : 275 : ix86_expand_sse_pcmpistr (const struct builtin_description *d,
12126 : : tree exp, rtx target)
12127 : : {
12128 : 275 : rtx pat;
12129 : 275 : tree arg0 = CALL_EXPR_ARG (exp, 0);
12130 : 275 : tree arg1 = CALL_EXPR_ARG (exp, 1);
12131 : 275 : tree arg2 = CALL_EXPR_ARG (exp, 2);
12132 : 275 : rtx scratch0, scratch1;
12133 : 275 : rtx op0 = expand_normal (arg0);
12134 : 275 : rtx op1 = expand_normal (arg1);
12135 : 275 : rtx op2 = expand_normal (arg2);
12136 : 275 : machine_mode tmode0, tmode1, modev2, modev3, modeimm;
12137 : :
12138 : 275 : tmode0 = insn_data[d->icode].operand[0].mode;
12139 : 275 : tmode1 = insn_data[d->icode].operand[1].mode;
12140 : 275 : modev2 = insn_data[d->icode].operand[2].mode;
12141 : 275 : modev3 = insn_data[d->icode].operand[3].mode;
12142 : 275 : modeimm = insn_data[d->icode].operand[4].mode;
12143 : :
12144 : 275 : if (VECTOR_MODE_P (modev2))
12145 : 275 : op0 = safe_vector_operand (op0, modev2);
12146 : 275 : if (VECTOR_MODE_P (modev3))
12147 : 275 : op1 = safe_vector_operand (op1, modev3);
12148 : :
12149 : 275 : if (!insn_data[d->icode].operand[2].predicate (op0, modev2))
12150 : 4 : op0 = copy_to_mode_reg (modev2, op0);
12151 : 210 : if ((optimize && !register_operand (op1, modev3))
12152 : 481 : || !insn_data[d->icode].operand[3].predicate (op1, modev3))
12153 : 4 : op1 = copy_to_mode_reg (modev3, op1);
12154 : :
12155 : 275 : if (!insn_data[d->icode].operand[4].predicate (op2, modeimm))
12156 : : {
12157 : 21 : error ("the third argument must be an 8-bit immediate");
12158 : 21 : return const0_rtx;
12159 : : }
12160 : :
12161 : 254 : if (d->code == IX86_BUILTIN_PCMPISTRI128)
12162 : : {
12163 : 5 : if (optimize || !target
12164 : 5 : || GET_MODE (target) != tmode0
12165 : 38 : || !insn_data[d->icode].operand[0].predicate (target, tmode0))
12166 : 28 : target = gen_reg_rtx (tmode0);
12167 : :
12168 : 33 : scratch1 = gen_reg_rtx (tmode1);
12169 : :
12170 : 33 : pat = GEN_FCN (d->icode) (target, scratch1, op0, op1, op2);
12171 : : }
12172 : 221 : else if (d->code == IX86_BUILTIN_PCMPISTRM128)
12173 : : {
12174 : 8 : if (optimize || !target
12175 : 8 : || GET_MODE (target) != tmode1
12176 : 58 : || !insn_data[d->icode].operand[1].predicate (target, tmode1))
12177 : 42 : target = gen_reg_rtx (tmode1);
12178 : :
12179 : 50 : scratch0 = gen_reg_rtx (tmode0);
12180 : :
12181 : 50 : pat = GEN_FCN (d->icode) (scratch0, target, op0, op1, op2);
12182 : : }
12183 : : else
12184 : : {
12185 : 171 : gcc_assert (d->flag);
12186 : :
12187 : 171 : scratch0 = gen_reg_rtx (tmode0);
12188 : 171 : scratch1 = gen_reg_rtx (tmode1);
12189 : :
12190 : 171 : pat = GEN_FCN (d->icode) (scratch0, scratch1, op0, op1, op2);
12191 : : }
12192 : :
12193 : 254 : if (! pat)
12194 : : return 0;
12195 : :
12196 : 254 : emit_insn (pat);
12197 : :
12198 : 254 : if (d->flag)
12199 : : {
12200 : 171 : target = gen_reg_rtx (SImode);
12201 : 171 : emit_move_insn (target, const0_rtx);
12202 : 171 : target = gen_rtx_SUBREG (QImode, target, 0);
12203 : :
12204 : 171 : emit_insn
12205 : 171 : (gen_rtx_SET (gen_rtx_STRICT_LOW_PART (VOIDmode, target),
12206 : : gen_rtx_fmt_ee (EQ, QImode,
12207 : : gen_rtx_REG ((machine_mode) d->flag,
12208 : : FLAGS_REG),
12209 : : const0_rtx)));
12210 : 171 : return SUBREG_REG (target);
12211 : : }
12212 : : else
12213 : : return target;
12214 : : }
12215 : :
12216 : : /* Fixup modeless constants to fit required mode. */
12217 : :
12218 : : static rtx
12219 : 259683 : fixup_modeless_constant (rtx x, machine_mode mode)
12220 : : {
12221 : 259683 : if (GET_MODE (x) == VOIDmode)
12222 : 41525 : x = convert_to_mode (mode, x, 1);
12223 : 259683 : return x;
12224 : : }
12225 : :
12226 : : /* Expand the outgoing argument ARG to extract unsigned char and short
12227 : : integer constants suitable for the predicates and the instruction
12228 : : templates which expect the unsigned expanded value. */
12229 : :
12230 : : static rtx
12231 : 281233 : ix86_expand_unsigned_small_int_cst_argument (tree arg)
12232 : : {
12233 : : /* When passing 0xff as an unsigned char function argument with the
12234 : : C frontend promotion, expand_normal gets
12235 : :
12236 : : <integer_cst 0x7fffe6aa23a8 type <integer_type 0x7fffe98225e8 int> constant 255>
12237 : :
12238 : : and returns the rtx value using the sign-extended representation:
12239 : :
12240 : : (const_int 255 [0xff])
12241 : :
12242 : : Without the C frontend promotion, expand_normal gets
12243 : :
12244 : : <integer_cst 0x7fffe9824018 type <integer_type 0x7fffe9822348 unsigned char > constant 255>
12245 : :
12246 : : and returns
12247 : :
12248 : : (const_int -1 [0xffffffffffffffff])
12249 : :
12250 : : which doesn't work with the predicates nor the instruction templates
12251 : : which expect the unsigned expanded value. Extract the unsigned char
12252 : : and short integer constants to return
12253 : :
12254 : : (const_int 255 [0xff])
12255 : :
12256 : : so that the expanded value is always unsigned, without the C frontend
12257 : : promotion. */
12258 : :
12259 : 281233 : if (TREE_CODE (arg) == INTEGER_CST)
12260 : : {
12261 : 60722 : tree type = TREE_TYPE (arg);
12262 : 60722 : if (INTEGRAL_TYPE_P (type)
12263 : 60722 : && TYPE_UNSIGNED (type)
12264 : 82627 : && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
12265 : : {
12266 : 18418 : HOST_WIDE_INT cst = TREE_INT_CST_LOW (arg);
12267 : 18418 : return GEN_INT (cst);
12268 : : }
12269 : : }
12270 : :
12271 : 262815 : return expand_normal (arg);
12272 : : }
12273 : :
12274 : : /* Subroutine of ix86_expand_builtin to take care of insns with
12275 : : variable number of operands. */
12276 : :
12277 : : static rtx
12278 : 69515 : ix86_expand_args_builtin (const struct builtin_description *d,
12279 : : tree exp, rtx target)
12280 : : {
12281 : 69515 : rtx pat, real_target;
12282 : 69515 : unsigned int i, nargs;
12283 : 69515 : unsigned int nargs_constant = 0;
12284 : 69515 : unsigned int mask_pos = 0;
12285 : 69515 : int num_memory = 0;
12286 : 69515 : rtx xops[6];
12287 : 69515 : bool second_arg_count = false;
12288 : 69515 : enum insn_code icode = d->icode;
12289 : 69515 : const struct insn_data_d *insn_p = &insn_data[icode];
12290 : 69515 : machine_mode tmode = insn_p->operand[0].mode;
12291 : 69515 : machine_mode rmode = VOIDmode;
12292 : 69515 : bool swap = false;
12293 : 69515 : enum rtx_code comparison = d->comparison;
12294 : :
12295 : 69515 : switch ((enum ix86_builtin_func_type) d->flag)
12296 : : {
12297 : 0 : case V2DF_FTYPE_V2DF_ROUND:
12298 : 0 : case V4DF_FTYPE_V4DF_ROUND:
12299 : 0 : case V8DF_FTYPE_V8DF_ROUND:
12300 : 0 : case V4SF_FTYPE_V4SF_ROUND:
12301 : 0 : case V8SF_FTYPE_V8SF_ROUND:
12302 : 0 : case V16SF_FTYPE_V16SF_ROUND:
12303 : 0 : case V8HF_FTYPE_V8HF_ROUND:
12304 : 0 : case V16HF_FTYPE_V16HF_ROUND:
12305 : 0 : case V32HF_FTYPE_V32HF_ROUND:
12306 : 0 : case V4SI_FTYPE_V4SF_ROUND:
12307 : 0 : case V8SI_FTYPE_V8SF_ROUND:
12308 : 0 : case V16SI_FTYPE_V16SF_ROUND:
12309 : 0 : return ix86_expand_sse_round (d, exp, target);
12310 : 12 : case V4SI_FTYPE_V2DF_V2DF_ROUND:
12311 : 12 : case V8SI_FTYPE_V4DF_V4DF_ROUND:
12312 : 12 : case V16SI_FTYPE_V8DF_V8DF_ROUND:
12313 : 12 : return ix86_expand_sse_round_vec_pack_sfix (d, exp, target);
12314 : 235 : case INT_FTYPE_V8SF_V8SF_PTEST:
12315 : 235 : case INT_FTYPE_V4DI_V4DI_PTEST:
12316 : 235 : case INT_FTYPE_V4DF_V4DF_PTEST:
12317 : 235 : case INT_FTYPE_V4SF_V4SF_PTEST:
12318 : 235 : case INT_FTYPE_V2DI_V2DI_PTEST:
12319 : 235 : case INT_FTYPE_V2DF_V2DF_PTEST:
12320 : 235 : return ix86_expand_sse_ptest (d, exp, target);
12321 : : case FLOAT128_FTYPE_FLOAT128:
12322 : : case FLOAT_FTYPE_FLOAT:
12323 : : case FLOAT_FTYPE_BFLOAT16:
12324 : : case INT_FTYPE_INT:
12325 : : case UINT_FTYPE_UINT:
12326 : : case UINT16_FTYPE_UINT16:
12327 : : case UINT64_FTYPE_INT:
12328 : : case UINT64_FTYPE_UINT64:
12329 : : case INT64_FTYPE_INT64:
12330 : : case INT64_FTYPE_V4SF:
12331 : : case INT64_FTYPE_V2DF:
12332 : : case INT_FTYPE_V16QI:
12333 : : case INT_FTYPE_V8QI:
12334 : : case INT_FTYPE_V8SF:
12335 : : case INT_FTYPE_V4DF:
12336 : : case INT_FTYPE_V4SF:
12337 : : case INT_FTYPE_V2DF:
12338 : : case INT_FTYPE_V32QI:
12339 : : case V16QI_FTYPE_V16QI:
12340 : : case V8SI_FTYPE_V8SF:
12341 : : case V8SI_FTYPE_V4SI:
12342 : : case V8HI_FTYPE_V8HI:
12343 : : case V8HI_FTYPE_V16QI:
12344 : : case V8QI_FTYPE_V8QI:
12345 : : case V8SF_FTYPE_V8SF:
12346 : : case V8SF_FTYPE_V8SI:
12347 : : case V8SF_FTYPE_V4SF:
12348 : : case V8SF_FTYPE_V8HI:
12349 : : case V4SI_FTYPE_V4SI:
12350 : : case V4SI_FTYPE_V16QI:
12351 : : case V4SI_FTYPE_V4SF:
12352 : : case V4SI_FTYPE_V8SI:
12353 : : case V4SI_FTYPE_V8HI:
12354 : : case V4SI_FTYPE_V4DF:
12355 : : case V4SI_FTYPE_V2DF:
12356 : : case V4HI_FTYPE_V4HI:
12357 : : case V4DF_FTYPE_V4DF:
12358 : : case V4DF_FTYPE_V4SI:
12359 : : case V4DF_FTYPE_V4SF:
12360 : : case V4DF_FTYPE_V2DF:
12361 : : case V4SF_FTYPE_V4SF:
12362 : : case V4SF_FTYPE_V4SI:
12363 : : case V4SF_FTYPE_V8SF:
12364 : : case V4SF_FTYPE_V4DF:
12365 : : case V4SF_FTYPE_V8HI:
12366 : : case V4SF_FTYPE_V2DF:
12367 : : case V2DI_FTYPE_V2DI:
12368 : : case V2DI_FTYPE_V16QI:
12369 : : case V2DI_FTYPE_V8HI:
12370 : : case V2DI_FTYPE_V4SI:
12371 : : case V2DF_FTYPE_V2DF:
12372 : : case V2DF_FTYPE_V4SI:
12373 : : case V2DF_FTYPE_V4DF:
12374 : : case V2DF_FTYPE_V4SF:
12375 : : case V2DF_FTYPE_V2SI:
12376 : : case V2SI_FTYPE_V2SI:
12377 : : case V2SI_FTYPE_V4SF:
12378 : : case V2SI_FTYPE_V2SF:
12379 : : case V2SI_FTYPE_V2DF:
12380 : : case V2SF_FTYPE_V2SF:
12381 : : case V2SF_FTYPE_V2SI:
12382 : : case V32QI_FTYPE_V32QI:
12383 : : case V32QI_FTYPE_V16QI:
12384 : : case V16HI_FTYPE_V16HI:
12385 : : case V16HI_FTYPE_V8HI:
12386 : : case V8SI_FTYPE_V8SI:
12387 : : case V16HI_FTYPE_V16QI:
12388 : : case V8SI_FTYPE_V16QI:
12389 : : case V4DI_FTYPE_V16QI:
12390 : : case V8SI_FTYPE_V8HI:
12391 : : case V4DI_FTYPE_V8HI:
12392 : : case V4DI_FTYPE_V4SI:
12393 : : case V4DI_FTYPE_V2DI:
12394 : : case UQI_FTYPE_UQI:
12395 : : case UHI_FTYPE_UHI:
12396 : : case USI_FTYPE_USI:
12397 : : case USI_FTYPE_UQI:
12398 : : case USI_FTYPE_UHI:
12399 : : case UDI_FTYPE_UDI:
12400 : : case UHI_FTYPE_V16QI:
12401 : : case USI_FTYPE_V32QI:
12402 : : case UDI_FTYPE_V64QI:
12403 : : case V16QI_FTYPE_UHI:
12404 : : case V32QI_FTYPE_USI:
12405 : : case V64QI_FTYPE_UDI:
12406 : : case V8HI_FTYPE_UQI:
12407 : : case V16HI_FTYPE_UHI:
12408 : : case V32HI_FTYPE_USI:
12409 : : case V4SI_FTYPE_UQI:
12410 : : case V8SI_FTYPE_UQI:
12411 : : case V4SI_FTYPE_UHI:
12412 : : case V8SI_FTYPE_UHI:
12413 : : case UQI_FTYPE_V8HI:
12414 : : case UHI_FTYPE_V16HI:
12415 : : case USI_FTYPE_V32HI:
12416 : : case UQI_FTYPE_V4SI:
12417 : : case UQI_FTYPE_V8SI:
12418 : : case UHI_FTYPE_V16SI:
12419 : : case UQI_FTYPE_V2DI:
12420 : : case UQI_FTYPE_V4DI:
12421 : : case UQI_FTYPE_V8DI:
12422 : : case V16SI_FTYPE_UHI:
12423 : : case V2DI_FTYPE_UQI:
12424 : : case V4DI_FTYPE_UQI:
12425 : : case V16SI_FTYPE_INT:
12426 : : case V16SF_FTYPE_V8SF:
12427 : : case V16SI_FTYPE_V8SI:
12428 : : case V16SF_FTYPE_V4SF:
12429 : : case V16SI_FTYPE_V4SI:
12430 : : case V16SI_FTYPE_V16SF:
12431 : : case V16SI_FTYPE_V16SI:
12432 : : case V64QI_FTYPE_V64QI:
12433 : : case V32HI_FTYPE_V32HI:
12434 : : case V16SF_FTYPE_V16SF:
12435 : : case V8DI_FTYPE_UQI:
12436 : : case V8DI_FTYPE_V8DI:
12437 : : case V8DF_FTYPE_V4DF:
12438 : : case V8DF_FTYPE_V2DF:
12439 : : case V8DF_FTYPE_V8DF:
12440 : : case V4DI_FTYPE_V4DI:
12441 : : case V16BF_FTYPE_V16SF:
12442 : : case V8BF_FTYPE_V8SF:
12443 : : case V8BF_FTYPE_V4SF:
12444 : : nargs = 1;
12445 : : break;
12446 : 52 : case V4SF_FTYPE_V4SF_VEC_MERGE:
12447 : 52 : case V2DF_FTYPE_V2DF_VEC_MERGE:
12448 : 52 : return ix86_expand_unop_vec_merge_builtin (icode, exp, target);
12449 : 9569 : case FLOAT128_FTYPE_FLOAT128_FLOAT128:
12450 : 9569 : case V16QI_FTYPE_V16QI_V16QI:
12451 : 9569 : case V16QI_FTYPE_V8HI_V8HI:
12452 : 9569 : case V16HF_FTYPE_V16HF_V16HF:
12453 : 9569 : case V16SF_FTYPE_V16SF_V16SF:
12454 : 9569 : case V16SI_FTYPE_V16SI_V16SI:
12455 : 9569 : case V8QI_FTYPE_V8QI_V8QI:
12456 : 9569 : case V8QI_FTYPE_V4HI_V4HI:
12457 : 9569 : case V8HI_FTYPE_V8HI_V8HI:
12458 : 9569 : case V8HI_FTYPE_V16QI_V16QI:
12459 : 9569 : case V8HI_FTYPE_V4SI_V4SI:
12460 : 9569 : case V8HF_FTYPE_V8HF_V8HF:
12461 : 9569 : case V8SF_FTYPE_V8SF_V8SF:
12462 : 9569 : case V8SF_FTYPE_V8SF_V8SI:
12463 : 9569 : case V8DF_FTYPE_V8DF_V8DF:
12464 : 9569 : case V4SI_FTYPE_V4SI_V4SI:
12465 : 9569 : case V4SI_FTYPE_V8HI_V8HI:
12466 : 9569 : case V4SI_FTYPE_V2DF_V2DF:
12467 : 9569 : case V4HI_FTYPE_V4HI_V4HI:
12468 : 9569 : case V4HI_FTYPE_V8QI_V8QI:
12469 : 9569 : case V4HI_FTYPE_V2SI_V2SI:
12470 : 9569 : case V4DF_FTYPE_V4DF_V4DF:
12471 : 9569 : case V4DF_FTYPE_V4DF_V4DI:
12472 : 9569 : case V4SF_FTYPE_V4SF_V4SF:
12473 : 9569 : case V4SF_FTYPE_V4SF_V4SI:
12474 : 9569 : case V4SF_FTYPE_V4SF_V2SI:
12475 : 9569 : case V4SF_FTYPE_V4SF_V2DF:
12476 : 9569 : case V4SF_FTYPE_V4SF_UINT:
12477 : 9569 : case V4SF_FTYPE_V4SF_DI:
12478 : 9569 : case V4SF_FTYPE_V4SF_SI:
12479 : 9569 : case V4DI_FTYPE_V4DI_V2DI:
12480 : 9569 : case V2DI_FTYPE_V2DI_V2DI:
12481 : 9569 : case V2DI_FTYPE_V16QI_V16QI:
12482 : 9569 : case V2DI_FTYPE_V4SI_V4SI:
12483 : 9569 : case V2DI_FTYPE_V2DI_V16QI:
12484 : 9569 : case V2SI_FTYPE_V2SI_V2SI:
12485 : 9569 : case V2SI_FTYPE_V4HI_V4HI:
12486 : 9569 : case V2SI_FTYPE_V2SF_V2SF:
12487 : 9569 : case V2DF_FTYPE_V2DF_V2DF:
12488 : 9569 : case V2DF_FTYPE_V2DF_V4SF:
12489 : 9569 : case V2DF_FTYPE_V2DF_V2DI:
12490 : 9569 : case V2DF_FTYPE_V2DF_DI:
12491 : 9569 : case V2DF_FTYPE_V2DF_SI:
12492 : 9569 : case V2DF_FTYPE_V2DF_UINT:
12493 : 9569 : case V2SF_FTYPE_V2SF_V2SF:
12494 : 9569 : case V1DI_FTYPE_V1DI_V1DI:
12495 : 9569 : case V1DI_FTYPE_V8QI_V8QI:
12496 : 9569 : case V1DI_FTYPE_V2SI_V2SI:
12497 : 9569 : case V32QI_FTYPE_V16HI_V16HI:
12498 : 9569 : case V16HI_FTYPE_V8SI_V8SI:
12499 : 9569 : case V64QI_FTYPE_V64QI_V64QI:
12500 : 9569 : case V32QI_FTYPE_V32QI_V32QI:
12501 : 9569 : case V32BF_FTYPE_V32BF_V32BF:
12502 : 9569 : case V16BF_FTYPE_V16BF_V16BF:
12503 : 9569 : case V8BF_FTYPE_V8BF_V8BF:
12504 : 9569 : case V16HI_FTYPE_V32QI_V32QI:
12505 : 9569 : case V16HI_FTYPE_V16HI_V16HI:
12506 : 9569 : case V8SI_FTYPE_V4DF_V4DF:
12507 : 9569 : case V8SI_FTYPE_V8SI_V8SI:
12508 : 9569 : case V8SI_FTYPE_V16HI_V16HI:
12509 : 9569 : case V4DI_FTYPE_V4DI_V4DI:
12510 : 9569 : case V4DI_FTYPE_V8SI_V8SI:
12511 : 9569 : case V4DI_FTYPE_V32QI_V32QI:
12512 : 9569 : case V8DI_FTYPE_V64QI_V64QI:
12513 : 9569 : if (comparison == UNKNOWN)
12514 : 9035 : return ix86_expand_binop_builtin (icode, exp, target);
12515 : : nargs = 2;
12516 : : break;
12517 : 80 : case V4SF_FTYPE_V4SF_V4SF_SWAP:
12518 : 80 : case V2DF_FTYPE_V2DF_V2DF_SWAP:
12519 : 80 : gcc_assert (comparison != UNKNOWN);
12520 : : nargs = 2;
12521 : : swap = true;
12522 : : break;
12523 : 1481 : case V16HI_FTYPE_V16HI_V8HI_COUNT:
12524 : 1481 : case V16HI_FTYPE_V16HI_SI_COUNT:
12525 : 1481 : case V8SI_FTYPE_V8SI_V4SI_COUNT:
12526 : 1481 : case V8SI_FTYPE_V8SI_SI_COUNT:
12527 : 1481 : case V4DI_FTYPE_V4DI_V2DI_COUNT:
12528 : 1481 : case V4DI_FTYPE_V4DI_INT_COUNT:
12529 : 1481 : case V8HI_FTYPE_V8HI_V8HI_COUNT:
12530 : 1481 : case V8HI_FTYPE_V8HI_SI_COUNT:
12531 : 1481 : case V4SI_FTYPE_V4SI_V4SI_COUNT:
12532 : 1481 : case V4SI_FTYPE_V4SI_SI_COUNT:
12533 : 1481 : case V4HI_FTYPE_V4HI_V4HI_COUNT:
12534 : 1481 : case V4HI_FTYPE_V4HI_SI_COUNT:
12535 : 1481 : case V2DI_FTYPE_V2DI_V2DI_COUNT:
12536 : 1481 : case V2DI_FTYPE_V2DI_SI_COUNT:
12537 : 1481 : case V2SI_FTYPE_V2SI_V2SI_COUNT:
12538 : 1481 : case V2SI_FTYPE_V2SI_SI_COUNT:
12539 : 1481 : case V1DI_FTYPE_V1DI_V1DI_COUNT:
12540 : 1481 : case V1DI_FTYPE_V1DI_SI_COUNT:
12541 : 1481 : nargs = 2;
12542 : 1481 : second_arg_count = true;
12543 : 1481 : break;
12544 : 1406 : case V16HI_FTYPE_V16HI_INT_V16HI_UHI_COUNT:
12545 : 1406 : case V16HI_FTYPE_V16HI_V8HI_V16HI_UHI_COUNT:
12546 : 1406 : case V16SI_FTYPE_V16SI_INT_V16SI_UHI_COUNT:
12547 : 1406 : case V16SI_FTYPE_V16SI_V4SI_V16SI_UHI_COUNT:
12548 : 1406 : case V2DI_FTYPE_V2DI_INT_V2DI_UQI_COUNT:
12549 : 1406 : case V2DI_FTYPE_V2DI_V2DI_V2DI_UQI_COUNT:
12550 : 1406 : case V32HI_FTYPE_V32HI_INT_V32HI_USI_COUNT:
12551 : 1406 : case V32HI_FTYPE_V32HI_V8HI_V32HI_USI_COUNT:
12552 : 1406 : case V4DI_FTYPE_V4DI_INT_V4DI_UQI_COUNT:
12553 : 1406 : case V4DI_FTYPE_V4DI_V2DI_V4DI_UQI_COUNT:
12554 : 1406 : case V4SI_FTYPE_V4SI_INT_V4SI_UQI_COUNT:
12555 : 1406 : case V4SI_FTYPE_V4SI_V4SI_V4SI_UQI_COUNT:
12556 : 1406 : case V8DI_FTYPE_V8DI_INT_V8DI_UQI_COUNT:
12557 : 1406 : case V8DI_FTYPE_V8DI_V2DI_V8DI_UQI_COUNT:
12558 : 1406 : case V8HI_FTYPE_V8HI_INT_V8HI_UQI_COUNT:
12559 : 1406 : case V8HI_FTYPE_V8HI_V8HI_V8HI_UQI_COUNT:
12560 : 1406 : case V8SI_FTYPE_V8SI_INT_V8SI_UQI_COUNT:
12561 : 1406 : case V8SI_FTYPE_V8SI_V4SI_V8SI_UQI_COUNT:
12562 : 1406 : nargs = 4;
12563 : 1406 : second_arg_count = true;
12564 : 1406 : break;
12565 : 962 : case UINT64_FTYPE_UINT64_UINT64:
12566 : 962 : case UINT_FTYPE_UINT_UINT:
12567 : 962 : case UINT_FTYPE_UINT_USHORT:
12568 : 962 : case UINT_FTYPE_UINT_UCHAR:
12569 : 962 : case UINT16_FTYPE_UINT16_INT:
12570 : 962 : case UINT8_FTYPE_UINT8_INT:
12571 : 962 : case UQI_FTYPE_UQI_UQI:
12572 : 962 : case UHI_FTYPE_UHI_UHI:
12573 : 962 : case USI_FTYPE_USI_USI:
12574 : 962 : case UDI_FTYPE_UDI_UDI:
12575 : 962 : case V16SI_FTYPE_V8DF_V8DF:
12576 : 962 : case V32BF_FTYPE_V16SF_V16SF:
12577 : 962 : case V16BF_FTYPE_V8SF_V8SF:
12578 : 962 : case V8BF_FTYPE_V4SF_V4SF:
12579 : 962 : case V16BF_FTYPE_V16SF_UHI:
12580 : 962 : case V8BF_FTYPE_V8SF_UQI:
12581 : 962 : case V8BF_FTYPE_V4SF_UQI:
12582 : 962 : case V16QI_FTYPE_V16QI_V8HF:
12583 : 962 : nargs = 2;
12584 : 962 : break;
12585 : 830 : case V2DI_FTYPE_V2DI_INT_CONVERT:
12586 : 830 : nargs = 2;
12587 : 830 : rmode = V1TImode;
12588 : 830 : nargs_constant = 1;
12589 : 830 : break;
12590 : 42 : case V4DI_FTYPE_V4DI_INT_CONVERT:
12591 : 42 : nargs = 2;
12592 : 42 : rmode = V2TImode;
12593 : 42 : nargs_constant = 1;
12594 : 42 : break;
12595 : 16 : case V8DI_FTYPE_V8DI_INT_CONVERT:
12596 : 16 : nargs = 2;
12597 : 16 : rmode = V4TImode;
12598 : 16 : nargs_constant = 1;
12599 : 16 : break;
12600 : 2376 : case V8HI_FTYPE_V8HI_INT:
12601 : 2376 : case V8HI_FTYPE_V8SF_INT:
12602 : 2376 : case V16HI_FTYPE_V16SF_INT:
12603 : 2376 : case V8HI_FTYPE_V4SF_INT:
12604 : 2376 : case V8SF_FTYPE_V8SF_INT:
12605 : 2376 : case V4SF_FTYPE_V16SF_INT:
12606 : 2376 : case V16SF_FTYPE_V16SF_INT:
12607 : 2376 : case V4SI_FTYPE_V4SI_INT:
12608 : 2376 : case V4SI_FTYPE_V8SI_INT:
12609 : 2376 : case V4HI_FTYPE_V4HI_INT:
12610 : 2376 : case V4DF_FTYPE_V4DF_INT:
12611 : 2376 : case V4DF_FTYPE_V8DF_INT:
12612 : 2376 : case V4SF_FTYPE_V4SF_INT:
12613 : 2376 : case V4SF_FTYPE_V8SF_INT:
12614 : 2376 : case V2DI_FTYPE_V2DI_INT:
12615 : 2376 : case V2DF_FTYPE_V2DF_INT:
12616 : 2376 : case V2DF_FTYPE_V4DF_INT:
12617 : 2376 : case V16HI_FTYPE_V16HI_INT:
12618 : 2376 : case V8SI_FTYPE_V8SI_INT:
12619 : 2376 : case V16SI_FTYPE_V16SI_INT:
12620 : 2376 : case V4SI_FTYPE_V16SI_INT:
12621 : 2376 : case V4DI_FTYPE_V4DI_INT:
12622 : 2376 : case V2DI_FTYPE_V4DI_INT:
12623 : 2376 : case V4DI_FTYPE_V8DI_INT:
12624 : 2376 : case UQI_FTYPE_UQI_UQI_CONST:
12625 : 2376 : case UHI_FTYPE_UHI_UQI:
12626 : 2376 : case USI_FTYPE_USI_UQI:
12627 : 2376 : case UDI_FTYPE_UDI_UQI:
12628 : 2376 : nargs = 2;
12629 : 2376 : nargs_constant = 1;
12630 : 2376 : break;
12631 : 18550 : case V16QI_FTYPE_V16QI_V16QI_V16QI:
12632 : 18550 : case V8SF_FTYPE_V8SF_V8SF_V8SF:
12633 : 18550 : case V4DF_FTYPE_V4DF_V4DF_V4DF:
12634 : 18550 : case V4SF_FTYPE_V4SF_V4SF_V4SF:
12635 : 18550 : case V2DF_FTYPE_V2DF_V2DF_V2DF:
12636 : 18550 : case V32QI_FTYPE_V32QI_V32QI_V32QI:
12637 : 18550 : case UHI_FTYPE_V16SI_V16SI_UHI:
12638 : 18550 : case UQI_FTYPE_V8DI_V8DI_UQI:
12639 : 18550 : case V16HI_FTYPE_V16SI_V16HI_UHI:
12640 : 18550 : case V16QI_FTYPE_V16SI_V16QI_UHI:
12641 : 18550 : case V16QI_FTYPE_V8DI_V16QI_UQI:
12642 : 18550 : case V32HF_FTYPE_V32HF_V32HF_USI:
12643 : 18550 : case V16SF_FTYPE_V16SF_V16SF_UHI:
12644 : 18550 : case V16SF_FTYPE_V4SF_V16SF_UHI:
12645 : 18550 : case V16SI_FTYPE_SI_V16SI_UHI:
12646 : 18550 : case V16SI_FTYPE_V16HI_V16SI_UHI:
12647 : 18550 : case V16SI_FTYPE_V16QI_V16SI_UHI:
12648 : 18550 : case V8SF_FTYPE_V4SF_V8SF_UQI:
12649 : 18550 : case V4DF_FTYPE_V2DF_V4DF_UQI:
12650 : 18550 : case V8SI_FTYPE_V4SI_V8SI_UQI:
12651 : 18550 : case V8SI_FTYPE_SI_V8SI_UQI:
12652 : 18550 : case V4SI_FTYPE_V4SI_V4SI_UQI:
12653 : 18550 : case V4SI_FTYPE_SI_V4SI_UQI:
12654 : 18550 : case V4DI_FTYPE_V2DI_V4DI_UQI:
12655 : 18550 : case V4DI_FTYPE_DI_V4DI_UQI:
12656 : 18550 : case V2DI_FTYPE_V2DI_V2DI_UQI:
12657 : 18550 : case V2DI_FTYPE_DI_V2DI_UQI:
12658 : 18550 : case V64QI_FTYPE_V64QI_V64QI_UDI:
12659 : 18550 : case V64QI_FTYPE_V16QI_V64QI_UDI:
12660 : 18550 : case V64QI_FTYPE_QI_V64QI_UDI:
12661 : 18550 : case V32QI_FTYPE_V32QI_V32QI_USI:
12662 : 18550 : case V32QI_FTYPE_V16QI_V32QI_USI:
12663 : 18550 : case V32QI_FTYPE_QI_V32QI_USI:
12664 : 18550 : case V16QI_FTYPE_V16QI_V16QI_UHI:
12665 : 18550 : case V16QI_FTYPE_QI_V16QI_UHI:
12666 : 18550 : case V32HI_FTYPE_V8HI_V32HI_USI:
12667 : 18550 : case V32HI_FTYPE_V32BF_V32HI_USI:
12668 : 18550 : case V32HI_FTYPE_HI_V32HI_USI:
12669 : 18550 : case V16HI_FTYPE_V8HI_V16HI_UHI:
12670 : 18550 : case V16HI_FTYPE_V16BF_V16HI_UHI:
12671 : 18550 : case V16HI_FTYPE_HI_V16HI_UHI:
12672 : 18550 : case V8HI_FTYPE_V8HI_V8HI_UQI:
12673 : 18550 : case V8HI_FTYPE_V8BF_V8HI_UQI:
12674 : 18550 : case V8BF_FTYPE_V8BF_V8BF_UQI:
12675 : 18550 : case V8HI_FTYPE_HI_V8HI_UQI:
12676 : 18550 : case V16HF_FTYPE_V16HF_V16HF_UHI:
12677 : 18550 : case V8SF_FTYPE_V8HI_V8SF_UQI:
12678 : 18550 : case V4SF_FTYPE_V8HI_V4SF_UQI:
12679 : 18550 : case V8SI_FTYPE_V8HF_V8SI_UQI:
12680 : 18550 : case V8SF_FTYPE_V8HF_V8SF_UQI:
12681 : 18550 : case V8SI_FTYPE_V8SF_V8SI_UQI:
12682 : 18550 : case V4SI_FTYPE_V4SF_V4SI_UQI:
12683 : 18550 : case V4SI_FTYPE_V8HF_V4SI_UQI:
12684 : 18550 : case V4SF_FTYPE_V8HF_V4SF_UQI:
12685 : 18550 : case V4DI_FTYPE_V8HF_V4DI_UQI:
12686 : 18550 : case V4DI_FTYPE_V4SF_V4DI_UQI:
12687 : 18550 : case V2DI_FTYPE_V8HF_V2DI_UQI:
12688 : 18550 : case V2DI_FTYPE_V4SF_V2DI_UQI:
12689 : 18550 : case V8HF_FTYPE_V8HF_V8HF_UQI:
12690 : 18550 : case V8HF_FTYPE_V8HF_V8HF_V8HF:
12691 : 18550 : case V8HF_FTYPE_V8HI_V8HF_UQI:
12692 : 18550 : case V8HF_FTYPE_V8SI_V8HF_UQI:
12693 : 18550 : case V8HF_FTYPE_V8SF_V8HF_UQI:
12694 : 18550 : case V8HF_FTYPE_V4SI_V8HF_UQI:
12695 : 18550 : case V8HF_FTYPE_V4SF_V8HF_UQI:
12696 : 18550 : case V8HF_FTYPE_V4DI_V8HF_UQI:
12697 : 18550 : case V8HF_FTYPE_V4DF_V8HF_UQI:
12698 : 18550 : case V8HF_FTYPE_V2DI_V8HF_UQI:
12699 : 18550 : case V8HF_FTYPE_V2DF_V8HF_UQI:
12700 : 18550 : case V4SF_FTYPE_V4DI_V4SF_UQI:
12701 : 18550 : case V4SF_FTYPE_V2DI_V4SF_UQI:
12702 : 18550 : case V4DF_FTYPE_V4DI_V4DF_UQI:
12703 : 18550 : case V4DF_FTYPE_V8HF_V4DF_UQI:
12704 : 18550 : case V2DF_FTYPE_V8HF_V2DF_UQI:
12705 : 18550 : case V2DF_FTYPE_V2DI_V2DF_UQI:
12706 : 18550 : case V16QI_FTYPE_V8HI_V16QI_UQI:
12707 : 18550 : case V16QI_FTYPE_V16HI_V16QI_UHI:
12708 : 18550 : case V16QI_FTYPE_V4SI_V16QI_UQI:
12709 : 18550 : case V16QI_FTYPE_V8SI_V16QI_UQI:
12710 : 18550 : case V8HI_FTYPE_V8HF_V8HI_UQI:
12711 : 18550 : case V8HI_FTYPE_V4SI_V8HI_UQI:
12712 : 18550 : case V8HI_FTYPE_V8SI_V8HI_UQI:
12713 : 18550 : case V16QI_FTYPE_V2DI_V16QI_UQI:
12714 : 18550 : case V16QI_FTYPE_V4DI_V16QI_UQI:
12715 : 18550 : case V8HI_FTYPE_V2DI_V8HI_UQI:
12716 : 18550 : case V8HI_FTYPE_V4DI_V8HI_UQI:
12717 : 18550 : case V4SI_FTYPE_V2DI_V4SI_UQI:
12718 : 18550 : case V4SI_FTYPE_V4DI_V4SI_UQI:
12719 : 18550 : case V32QI_FTYPE_V32HI_V32QI_USI:
12720 : 18550 : case UHI_FTYPE_V16QI_V16QI_UHI:
12721 : 18550 : case USI_FTYPE_V32QI_V32QI_USI:
12722 : 18550 : case UDI_FTYPE_V64QI_V64QI_UDI:
12723 : 18550 : case UQI_FTYPE_V8HI_V8HI_UQI:
12724 : 18550 : case UHI_FTYPE_V16HI_V16HI_UHI:
12725 : 18550 : case USI_FTYPE_V32HI_V32HI_USI:
12726 : 18550 : case UQI_FTYPE_V4SI_V4SI_UQI:
12727 : 18550 : case UQI_FTYPE_V8SI_V8SI_UQI:
12728 : 18550 : case UQI_FTYPE_V2DI_V2DI_UQI:
12729 : 18550 : case UQI_FTYPE_V4DI_V4DI_UQI:
12730 : 18550 : case V4SF_FTYPE_V2DF_V4SF_UQI:
12731 : 18550 : case V4SF_FTYPE_V4DF_V4SF_UQI:
12732 : 18550 : case V16SI_FTYPE_V16SI_V16SI_UHI:
12733 : 18550 : case V16SI_FTYPE_V4SI_V16SI_UHI:
12734 : 18550 : case V2DI_FTYPE_V4SI_V2DI_UQI:
12735 : 18550 : case V2DI_FTYPE_V8HI_V2DI_UQI:
12736 : 18550 : case V2DI_FTYPE_V16QI_V2DI_UQI:
12737 : 18550 : case V4DI_FTYPE_V4DI_V4DI_UQI:
12738 : 18550 : case V4DI_FTYPE_V4SI_V4DI_UQI:
12739 : 18550 : case V4DI_FTYPE_V8HI_V4DI_UQI:
12740 : 18550 : case V4DI_FTYPE_V16QI_V4DI_UQI:
12741 : 18550 : case V4DI_FTYPE_V4DF_V4DI_UQI:
12742 : 18550 : case V2DI_FTYPE_V2DF_V2DI_UQI:
12743 : 18550 : case V4SI_FTYPE_V4DF_V4SI_UQI:
12744 : 18550 : case V4SI_FTYPE_V2DF_V4SI_UQI:
12745 : 18550 : case V4SI_FTYPE_V8HI_V4SI_UQI:
12746 : 18550 : case V4SI_FTYPE_V16QI_V4SI_UQI:
12747 : 18550 : case V4DI_FTYPE_V4DI_V4DI_V4DI:
12748 : 18550 : case V8DF_FTYPE_V2DF_V8DF_UQI:
12749 : 18550 : case V8DF_FTYPE_V4DF_V8DF_UQI:
12750 : 18550 : case V8DF_FTYPE_V8DF_V8DF_UQI:
12751 : 18550 : case V8SF_FTYPE_V8SF_V8SF_UQI:
12752 : 18550 : case V8SF_FTYPE_V8SI_V8SF_UQI:
12753 : 18550 : case V4DF_FTYPE_V4DF_V4DF_UQI:
12754 : 18550 : case V4SF_FTYPE_V4SF_V4SF_UQI:
12755 : 18550 : case V2DF_FTYPE_V2DF_V2DF_UQI:
12756 : 18550 : case V2DF_FTYPE_V4SF_V2DF_UQI:
12757 : 18550 : case V2DF_FTYPE_V4SI_V2DF_UQI:
12758 : 18550 : case V4SF_FTYPE_V4SI_V4SF_UQI:
12759 : 18550 : case V4DF_FTYPE_V4SF_V4DF_UQI:
12760 : 18550 : case V4DF_FTYPE_V4SI_V4DF_UQI:
12761 : 18550 : case V8SI_FTYPE_V8SI_V8SI_UQI:
12762 : 18550 : case V8SI_FTYPE_V8HI_V8SI_UQI:
12763 : 18550 : case V8SI_FTYPE_V16QI_V8SI_UQI:
12764 : 18550 : case V8DF_FTYPE_V8SI_V8DF_UQI:
12765 : 18550 : case V8DI_FTYPE_DI_V8DI_UQI:
12766 : 18550 : case V16SF_FTYPE_V8SF_V16SF_UHI:
12767 : 18550 : case V16SI_FTYPE_V8SI_V16SI_UHI:
12768 : 18550 : case V16HF_FTYPE_V16HI_V16HF_UHI:
12769 : 18550 : case V16HF_FTYPE_V16HF_V16HF_V16HF:
12770 : 18550 : case V16HI_FTYPE_V16HF_V16HI_UHI:
12771 : 18550 : case V16HI_FTYPE_V16HI_V16HI_UHI:
12772 : 18550 : case V16BF_FTYPE_V16BF_V16BF_UHI:
12773 : 18550 : case V8HI_FTYPE_V16QI_V8HI_UQI:
12774 : 18550 : case V16HI_FTYPE_V16QI_V16HI_UHI:
12775 : 18550 : case V32HI_FTYPE_V32HI_V32HI_USI:
12776 : 18550 : case V32BF_FTYPE_V32BF_V32BF_USI:
12777 : 18550 : case V32HI_FTYPE_V32QI_V32HI_USI:
12778 : 18550 : case V8DI_FTYPE_V16QI_V8DI_UQI:
12779 : 18550 : case V8DI_FTYPE_V2DI_V8DI_UQI:
12780 : 18550 : case V8DI_FTYPE_V4DI_V8DI_UQI:
12781 : 18550 : case V8DI_FTYPE_V8DI_V8DI_UQI:
12782 : 18550 : case V8DI_FTYPE_V8HI_V8DI_UQI:
12783 : 18550 : case V8DI_FTYPE_V8SI_V8DI_UQI:
12784 : 18550 : case V8HI_FTYPE_V8DI_V8HI_UQI:
12785 : 18550 : case V8SI_FTYPE_V8DI_V8SI_UQI:
12786 : 18550 : case V4SI_FTYPE_V4SI_V4SI_V4SI:
12787 : 18550 : case V4DI_FTYPE_V4DI_V4DI_V2DI:
12788 : 18550 : case V16SI_FTYPE_V16SI_V16SI_V16SI:
12789 : 18550 : case V8DI_FTYPE_V8DI_V8DI_V8DI:
12790 : 18550 : case V32HI_FTYPE_V32HI_V32HI_V32HI:
12791 : 18550 : case V2DI_FTYPE_V2DI_V2DI_V2DI:
12792 : 18550 : case V16HI_FTYPE_V16HI_V16HI_V16HI:
12793 : 18550 : case V8SI_FTYPE_V8SI_V8SI_V8SI:
12794 : 18550 : case V8HI_FTYPE_V8HI_V8HI_V8HI:
12795 : 18550 : case V32BF_FTYPE_V16SF_V16SF_USI:
12796 : 18550 : case V16BF_FTYPE_V8SF_V8SF_UHI:
12797 : 18550 : case V8BF_FTYPE_V4SF_V4SF_UQI:
12798 : 18550 : case V16BF_FTYPE_V16SF_V16BF_UHI:
12799 : 18550 : case V8BF_FTYPE_V8SF_V8BF_UQI:
12800 : 18550 : case V8BF_FTYPE_V4SF_V8BF_UQI:
12801 : 18550 : case V16SF_FTYPE_V16SF_V32BF_V32BF:
12802 : 18550 : case V8SF_FTYPE_V8SF_V16BF_V16BF:
12803 : 18550 : case V4SF_FTYPE_V4SF_V8BF_V8BF:
12804 : 18550 : case V16QI_FTYPE_V16QI_V8HF_V8HF:
12805 : 18550 : case V32QI_FTYPE_V32QI_V16HF_V16HF:
12806 : 18550 : case V64QI_FTYPE_V64QI_V32HF_V32HF:
12807 : 18550 : case V16QI_FTYPE_V8HF_V16QI_UQI:
12808 : 18550 : case V16QI_FTYPE_V16HF_V16QI_UHI:
12809 : 18550 : case V32QI_FTYPE_V32HF_V32QI_USI:
12810 : 18550 : case V8HF_FTYPE_V16QI_V8HF_UQI:
12811 : 18550 : case V16HF_FTYPE_V16QI_V16HF_UHI:
12812 : 18550 : case V32HF_FTYPE_V32QI_V32HF_USI:
12813 : 18550 : case V16SI_FTYPE_V16SF_V16SI_UHI:
12814 : 18550 : case V32HI_FTYPE_V32HF_V32HI_USI:
12815 : 18550 : case V8DI_FTYPE_V8SF_V8DI_UQI:
12816 : 18550 : case V8DI_FTYPE_V8DF_V8DI_UQI:
12817 : 18550 : case V8SI_FTYPE_V8DF_V8SI_UQI:
12818 : 18550 : nargs = 3;
12819 : 18550 : break;
12820 : 1478 : case V32QI_FTYPE_V32QI_V32QI_INT:
12821 : 1478 : case V16HI_FTYPE_V16HI_V16HI_INT:
12822 : 1478 : case V16QI_FTYPE_V16QI_V16QI_INT:
12823 : 1478 : case V4DI_FTYPE_V4DI_V4DI_INT:
12824 : 1478 : case V8HI_FTYPE_V8HI_V8HI_INT:
12825 : 1478 : case V8SI_FTYPE_V8SI_V8SI_INT:
12826 : 1478 : case V8SI_FTYPE_V8SI_V4SI_INT:
12827 : 1478 : case V8SF_FTYPE_V8SF_V8SF_INT:
12828 : 1478 : case V8SF_FTYPE_V8SF_V4SF_INT:
12829 : 1478 : case V4SI_FTYPE_V4SI_V4SI_INT:
12830 : 1478 : case V4DF_FTYPE_V4DF_V4DF_INT:
12831 : 1478 : case V16SF_FTYPE_V16SF_V16SF_INT:
12832 : 1478 : case V16SF_FTYPE_V16SF_V4SF_INT:
12833 : 1478 : case V16SI_FTYPE_V16SI_V4SI_INT:
12834 : 1478 : case V4DF_FTYPE_V4DF_V2DF_INT:
12835 : 1478 : case V4SF_FTYPE_V4SF_V4SF_INT:
12836 : 1478 : case V2DI_FTYPE_V2DI_V2DI_INT:
12837 : 1478 : case V4DI_FTYPE_V4DI_V2DI_INT:
12838 : 1478 : case V2DF_FTYPE_V2DF_V2DF_INT:
12839 : 1478 : case UQI_FTYPE_V8DI_V8UDI_INT:
12840 : 1478 : case UQI_FTYPE_V8DF_V8DF_INT:
12841 : 1478 : case UQI_FTYPE_V2DF_V2DF_INT:
12842 : 1478 : case UQI_FTYPE_V4SF_V4SF_INT:
12843 : 1478 : case UHI_FTYPE_V16SI_V16SI_INT:
12844 : 1478 : case UHI_FTYPE_V16SF_V16SF_INT:
12845 : 1478 : case V64QI_FTYPE_V64QI_V64QI_INT:
12846 : 1478 : case V32HI_FTYPE_V32HI_V32HI_INT:
12847 : 1478 : case V16SI_FTYPE_V16SI_V16SI_INT:
12848 : 1478 : case V8DI_FTYPE_V8DI_V8DI_INT:
12849 : 1478 : nargs = 3;
12850 : 1478 : nargs_constant = 1;
12851 : 1478 : break;
12852 : 47 : case V4DI_FTYPE_V4DI_V4DI_INT_CONVERT:
12853 : 47 : nargs = 3;
12854 : 47 : rmode = V4DImode;
12855 : 47 : nargs_constant = 1;
12856 : 47 : break;
12857 : 80 : case V2DI_FTYPE_V2DI_V2DI_INT_CONVERT:
12858 : 80 : nargs = 3;
12859 : 80 : rmode = V2DImode;
12860 : 80 : nargs_constant = 1;
12861 : 80 : break;
12862 : 48 : case V1DI_FTYPE_V1DI_V1DI_INT_CONVERT:
12863 : 48 : nargs = 3;
12864 : 48 : rmode = DImode;
12865 : 48 : nargs_constant = 1;
12866 : 48 : break;
12867 : 20 : case V2DI_FTYPE_V2DI_UINT_UINT:
12868 : 20 : nargs = 3;
12869 : 20 : nargs_constant = 2;
12870 : 20 : break;
12871 : 8 : case V8DI_FTYPE_V8DI_V8DI_INT_CONVERT:
12872 : 8 : nargs = 3;
12873 : 8 : rmode = V8DImode;
12874 : 8 : nargs_constant = 1;
12875 : 8 : break;
12876 : 16 : case V8DI_FTYPE_V8DI_V8DI_INT_V8DI_UDI_CONVERT:
12877 : 16 : nargs = 5;
12878 : 16 : rmode = V8DImode;
12879 : 16 : mask_pos = 2;
12880 : 16 : nargs_constant = 1;
12881 : 16 : break;
12882 : 320 : case QI_FTYPE_V8DF_INT_UQI:
12883 : 320 : case QI_FTYPE_V4DF_INT_UQI:
12884 : 320 : case QI_FTYPE_V2DF_INT_UQI:
12885 : 320 : case HI_FTYPE_V16SF_INT_UHI:
12886 : 320 : case QI_FTYPE_V8SF_INT_UQI:
12887 : 320 : case QI_FTYPE_V4SF_INT_UQI:
12888 : 320 : case QI_FTYPE_V8HF_INT_UQI:
12889 : 320 : case HI_FTYPE_V16HF_INT_UHI:
12890 : 320 : case SI_FTYPE_V32HF_INT_USI:
12891 : 320 : case QI_FTYPE_V8BF_INT_UQI:
12892 : 320 : case HI_FTYPE_V16BF_INT_UHI:
12893 : 320 : case SI_FTYPE_V32BF_INT_USI:
12894 : 320 : case V4SI_FTYPE_V4SI_V4SI_UHI:
12895 : 320 : case V8SI_FTYPE_V8SI_V8SI_UHI:
12896 : 320 : nargs = 3;
12897 : 320 : mask_pos = 1;
12898 : 320 : nargs_constant = 1;
12899 : 320 : break;
12900 : 17 : case V4DI_FTYPE_V4DI_V4DI_INT_V4DI_USI_CONVERT:
12901 : 17 : nargs = 5;
12902 : 17 : rmode = V4DImode;
12903 : 17 : mask_pos = 2;
12904 : 17 : nargs_constant = 1;
12905 : 17 : break;
12906 : 17 : case V2DI_FTYPE_V2DI_V2DI_INT_V2DI_UHI_CONVERT:
12907 : 17 : nargs = 5;
12908 : 17 : rmode = V2DImode;
12909 : 17 : mask_pos = 2;
12910 : 17 : nargs_constant = 1;
12911 : 17 : break;
12912 : 17312 : case V32QI_FTYPE_V32QI_V32QI_V32QI_USI:
12913 : 17312 : case V32HI_FTYPE_V32HI_V32HI_V32HI_USI:
12914 : 17312 : case V32BF_FTYPE_V32BF_V32BF_V32BF_USI:
12915 : 17312 : case V32HI_FTYPE_V64QI_V64QI_V32HI_USI:
12916 : 17312 : case V16SI_FTYPE_V32HI_V32HI_V16SI_UHI:
12917 : 17312 : case V64QI_FTYPE_V64QI_V64QI_V64QI_UDI:
12918 : 17312 : case V32HI_FTYPE_V32HI_V8HI_V32HI_USI:
12919 : 17312 : case V16HI_FTYPE_V16HI_V8HI_V16HI_UHI:
12920 : 17312 : case V8SI_FTYPE_V8SI_V4SI_V8SI_UQI:
12921 : 17312 : case V4DI_FTYPE_V4DI_V2DI_V4DI_UQI:
12922 : 17312 : case V64QI_FTYPE_V32HI_V32HI_V64QI_UDI:
12923 : 17312 : case V32QI_FTYPE_V16HI_V16HI_V32QI_USI:
12924 : 17312 : case V16QI_FTYPE_V8HI_V8HI_V16QI_UHI:
12925 : 17312 : case V32HI_FTYPE_V16SI_V16SI_V32HI_USI:
12926 : 17312 : case V16HI_FTYPE_V8SI_V8SI_V16HI_UHI:
12927 : 17312 : case V8HI_FTYPE_V4SI_V4SI_V8HI_UQI:
12928 : 17312 : case V4DF_FTYPE_V4DF_V4DI_V4DF_UQI:
12929 : 17312 : case V32HF_FTYPE_V32HF_V32HF_V32HF_USI:
12930 : 17312 : case V8SF_FTYPE_V8SF_V8SI_V8SF_UQI:
12931 : 17312 : case V4SF_FTYPE_V4SF_V4SI_V4SF_UQI:
12932 : 17312 : case V2DF_FTYPE_V2DF_V2DI_V2DF_UQI:
12933 : 17312 : case V2DI_FTYPE_V4SI_V4SI_V2DI_UQI:
12934 : 17312 : case V4DI_FTYPE_V8SI_V8SI_V4DI_UQI:
12935 : 17312 : case V4DF_FTYPE_V4DI_V4DF_V4DF_UQI:
12936 : 17312 : case V8SF_FTYPE_V8SI_V8SF_V8SF_UQI:
12937 : 17312 : case V2DF_FTYPE_V2DI_V2DF_V2DF_UQI:
12938 : 17312 : case V4SF_FTYPE_V4SI_V4SF_V4SF_UQI:
12939 : 17312 : case V16SF_FTYPE_V16SF_V16SF_V16SF_UHI:
12940 : 17312 : case V16SF_FTYPE_V16SF_V16SI_V16SF_UHI:
12941 : 17312 : case V16SF_FTYPE_V16SI_V16SF_V16SF_UHI:
12942 : 17312 : case V16SI_FTYPE_V16SI_V16SI_V16SI_UHI:
12943 : 17312 : case V16SI_FTYPE_V16SI_V4SI_V16SI_UHI:
12944 : 17312 : case V8HI_FTYPE_V8HI_V8HI_V8HI_UQI:
12945 : 17312 : case V8BF_FTYPE_V8BF_V8BF_V8BF_UQI:
12946 : 17312 : case V8SI_FTYPE_V8SI_V8SI_V8SI_UQI:
12947 : 17312 : case V4SI_FTYPE_V4SI_V4SI_V4SI_UQI:
12948 : 17312 : case V16HF_FTYPE_V16HF_V16HF_V16HF_UQI:
12949 : 17312 : case V16HF_FTYPE_V16HF_V16HF_V16HF_UHI:
12950 : 17312 : case V8SF_FTYPE_V8SF_V8SF_V8SF_UQI:
12951 : 17312 : case V16QI_FTYPE_V16QI_V16QI_V16QI_UHI:
12952 : 17312 : case V16HI_FTYPE_V16HI_V16HI_V16HI_UHI:
12953 : 17312 : case V16BF_FTYPE_V16BF_V16BF_V16BF_UHI:
12954 : 17312 : case V2DI_FTYPE_V2DI_V2DI_V2DI_UQI:
12955 : 17312 : case V2DF_FTYPE_V2DF_V2DF_V2DF_UQI:
12956 : 17312 : case V4DI_FTYPE_V4DI_V4DI_V4DI_UQI:
12957 : 17312 : case V4DF_FTYPE_V4DF_V4DF_V4DF_UQI:
12958 : 17312 : case V8HF_FTYPE_V8HF_V8HF_V8HF_UQI:
12959 : 17312 : case V4SF_FTYPE_V4SF_V4SF_V4SF_UQI:
12960 : 17312 : case V8DF_FTYPE_V8DF_V8DF_V8DF_UQI:
12961 : 17312 : case V8DF_FTYPE_V8DF_V8DI_V8DF_UQI:
12962 : 17312 : case V8DF_FTYPE_V8DI_V8DF_V8DF_UQI:
12963 : 17312 : case V8DI_FTYPE_V16SI_V16SI_V8DI_UQI:
12964 : 17312 : case V8DI_FTYPE_V8DI_V2DI_V8DI_UQI:
12965 : 17312 : case V8DI_FTYPE_V8DI_V8DI_V8DI_UQI:
12966 : 17312 : case V8HI_FTYPE_V16QI_V16QI_V8HI_UQI:
12967 : 17312 : case V16HI_FTYPE_V32QI_V32QI_V16HI_UHI:
12968 : 17312 : case V8SI_FTYPE_V16HI_V16HI_V8SI_UQI:
12969 : 17312 : case V4SI_FTYPE_V8HI_V8HI_V4SI_UQI:
12970 : 17312 : case V32BF_FTYPE_V16SF_V16SF_V32BF_USI:
12971 : 17312 : case V16BF_FTYPE_V8SF_V8SF_V16BF_UHI:
12972 : 17312 : case V8BF_FTYPE_V4SF_V4SF_V8BF_UQI:
12973 : 17312 : case V32HF_FTYPE_V16SF_V16SF_V32HF_USI:
12974 : 17312 : case V16HF_FTYPE_V8SF_V8SF_V16HF_UHI:
12975 : 17312 : case V8HF_FTYPE_V4SF_V4SF_V8HF_UQI:
12976 : 17312 : case V16QI_FTYPE_V8HF_V8HF_V16QI_UHI:
12977 : 17312 : case V32QI_FTYPE_V16HF_V16HF_V32QI_USI:
12978 : 17312 : case V64QI_FTYPE_V32HF_V32HF_V64QI_UDI:
12979 : 17312 : case V16QI_FTYPE_V16QI_V8HF_V16QI_UHI:
12980 : 17312 : case V16QI_FTYPE_V32QI_V16HF_V16QI_UHI:
12981 : 17312 : case V32QI_FTYPE_V64QI_V32HF_V32QI_USI:
12982 : 17312 : nargs = 4;
12983 : 17312 : break;
12984 : 11 : case V2DF_FTYPE_V2DF_V2DF_V2DI_INT:
12985 : 11 : case V4DF_FTYPE_V4DF_V4DF_V4DI_INT:
12986 : 11 : case V4SF_FTYPE_V4SF_V4SF_V4SI_INT:
12987 : 11 : case V8SF_FTYPE_V8SF_V8SF_V8SI_INT:
12988 : 11 : case V16SF_FTYPE_V16SF_V16SF_V16SI_INT:
12989 : 11 : case V4SI_FTYPE_V4SI_V4SI_V4SI_INT:
12990 : 11 : nargs = 4;
12991 : 11 : nargs_constant = 1;
12992 : 11 : break;
12993 : 3717 : case UQI_FTYPE_V4DI_V4DI_INT_UQI:
12994 : 3717 : case UQI_FTYPE_V8SI_V8SI_INT_UQI:
12995 : 3717 : case QI_FTYPE_V4DF_V4DF_INT_UQI:
12996 : 3717 : case QI_FTYPE_V8SF_V8SF_INT_UQI:
12997 : 3717 : case UHI_FTYPE_V16HF_V16HF_INT_UHI:
12998 : 3717 : case UQI_FTYPE_V2DI_V2DI_INT_UQI:
12999 : 3717 : case UQI_FTYPE_V4SI_V4SI_INT_UQI:
13000 : 3717 : case UQI_FTYPE_V2DF_V2DF_INT_UQI:
13001 : 3717 : case UQI_FTYPE_V4SF_V4SF_INT_UQI:
13002 : 3717 : case UQI_FTYPE_V8HF_V8HF_INT_UQI:
13003 : 3717 : case UDI_FTYPE_V64QI_V64QI_INT_UDI:
13004 : 3717 : case USI_FTYPE_V32QI_V32QI_INT_USI:
13005 : 3717 : case UHI_FTYPE_V16QI_V16QI_INT_UHI:
13006 : 3717 : case USI_FTYPE_V32HI_V32HI_INT_USI:
13007 : 3717 : case USI_FTYPE_V32BF_V32BF_INT_USI:
13008 : 3717 : case USI_FTYPE_V32HF_V32HF_INT_USI:
13009 : 3717 : case UHI_FTYPE_V16HI_V16HI_INT_UHI:
13010 : 3717 : case UHI_FTYPE_V16BF_V16BF_INT_UHI:
13011 : 3717 : case UQI_FTYPE_V8HI_V8HI_INT_UQI:
13012 : 3717 : case UQI_FTYPE_V8BF_V8BF_INT_UQI:
13013 : 3717 : nargs = 4;
13014 : 3717 : mask_pos = 1;
13015 : 3717 : nargs_constant = 1;
13016 : 3717 : break;
13017 : 23 : case V2DI_FTYPE_V2DI_V2DI_UINT_UINT:
13018 : 23 : nargs = 4;
13019 : 23 : nargs_constant = 2;
13020 : 23 : break;
13021 : 67 : case UCHAR_FTYPE_UCHAR_UINT_UINT_PUNSIGNED:
13022 : 67 : case UCHAR_FTYPE_UCHAR_ULONGLONG_ULONGLONG_PULONGLONG:
13023 : 67 : case V16SF_FTYPE_V16SF_V32BF_V32BF_UHI:
13024 : 67 : case V8SF_FTYPE_V8SF_V16BF_V16BF_UQI:
13025 : 67 : case V4SF_FTYPE_V4SF_V8BF_V8BF_UQI:
13026 : 67 : nargs = 4;
13027 : 67 : break;
13028 : 679 : case UQI_FTYPE_V8DI_V8DI_INT_UQI:
13029 : 679 : case UHI_FTYPE_V16SI_V16SI_INT_UHI:
13030 : 679 : mask_pos = 1;
13031 : 679 : nargs = 4;
13032 : 679 : nargs_constant = 1;
13033 : 679 : break;
13034 : 3948 : case V8SF_FTYPE_V8SF_INT_V8SF_UQI:
13035 : 3948 : case V4SF_FTYPE_V4SF_INT_V4SF_UQI:
13036 : 3948 : case V2DF_FTYPE_V4DF_INT_V2DF_UQI:
13037 : 3948 : case V2DI_FTYPE_V4DI_INT_V2DI_UQI:
13038 : 3948 : case V8SF_FTYPE_V16SF_INT_V8SF_UQI:
13039 : 3948 : case V8SI_FTYPE_V16SI_INT_V8SI_UQI:
13040 : 3948 : case V2DF_FTYPE_V8DF_INT_V2DF_UQI:
13041 : 3948 : case V2DI_FTYPE_V8DI_INT_V2DI_UQI:
13042 : 3948 : case V4SF_FTYPE_V8SF_INT_V4SF_UQI:
13043 : 3948 : case V4SI_FTYPE_V8SI_INT_V4SI_UQI:
13044 : 3948 : case V8HI_FTYPE_V8SF_INT_V8HI_UQI:
13045 : 3948 : case V8HI_FTYPE_V4SF_INT_V8HI_UQI:
13046 : 3948 : case V32HI_FTYPE_V32HI_INT_V32HI_USI:
13047 : 3948 : case V16HI_FTYPE_V16HI_INT_V16HI_UHI:
13048 : 3948 : case V8HI_FTYPE_V8HI_INT_V8HI_UQI:
13049 : 3948 : case V32BF_FTYPE_V32BF_INT_V32BF_USI:
13050 : 3948 : case V16BF_FTYPE_V16BF_INT_V16BF_UHI:
13051 : 3948 : case V8BF_FTYPE_V8BF_INT_V8BF_UQI:
13052 : 3948 : case V4DI_FTYPE_V4DI_INT_V4DI_UQI:
13053 : 3948 : case V2DI_FTYPE_V2DI_INT_V2DI_UQI:
13054 : 3948 : case V8SI_FTYPE_V8SI_INT_V8SI_UQI:
13055 : 3948 : case V4SI_FTYPE_V4SI_INT_V4SI_UQI:
13056 : 3948 : case V4DF_FTYPE_V4DF_INT_V4DF_UQI:
13057 : 3948 : case V2DF_FTYPE_V2DF_INT_V2DF_UQI:
13058 : 3948 : case V8DF_FTYPE_V8DF_INT_V8DF_UQI:
13059 : 3948 : case V16SF_FTYPE_V16SF_INT_V16SF_UHI:
13060 : 3948 : case V16HI_FTYPE_V16SF_INT_V16HI_UHI:
13061 : 3948 : case V16SI_FTYPE_V16SI_INT_V16SI_UHI:
13062 : 3948 : case V16HF_FTYPE_V16HF_INT_V16HF_UHI:
13063 : 3948 : case V8HF_FTYPE_V8HF_INT_V8HF_UQI:
13064 : 3948 : case V4SI_FTYPE_V16SI_INT_V4SI_UQI:
13065 : 3948 : case V4DI_FTYPE_V8DI_INT_V4DI_UQI:
13066 : 3948 : case V4DF_FTYPE_V8DF_INT_V4DF_UQI:
13067 : 3948 : case V4SF_FTYPE_V16SF_INT_V4SF_UQI:
13068 : 3948 : case V8DI_FTYPE_V8DI_INT_V8DI_UQI:
13069 : 3948 : nargs = 4;
13070 : 3948 : mask_pos = 2;
13071 : 3948 : nargs_constant = 1;
13072 : 3948 : break;
13073 : 1726 : case V16SF_FTYPE_V16SF_V4SF_INT_V16SF_UHI:
13074 : 1726 : case V16SI_FTYPE_V16SI_V4SI_INT_V16SI_UHI:
13075 : 1726 : case V8DF_FTYPE_V8DF_V8DF_INT_V8DF_UQI:
13076 : 1726 : case V8DI_FTYPE_V8DI_V8DI_INT_V8DI_UQI:
13077 : 1726 : case V16SF_FTYPE_V16SF_V16SF_INT_V16SF_UHI:
13078 : 1726 : case V16SI_FTYPE_V16SI_V16SI_INT_V16SI_UHI:
13079 : 1726 : case V4SF_FTYPE_V4SF_V4SF_INT_V4SF_UQI:
13080 : 1726 : case V2DF_FTYPE_V2DF_V2DF_INT_V2DF_UQI:
13081 : 1726 : case V8DF_FTYPE_V8DF_V4DF_INT_V8DF_UQI:
13082 : 1726 : case V8DI_FTYPE_V8DI_V4DI_INT_V8DI_UQI:
13083 : 1726 : case V4DF_FTYPE_V4DF_V4DF_INT_V4DF_UQI:
13084 : 1726 : case V8SF_FTYPE_V8SF_V8SF_INT_V8SF_UQI:
13085 : 1726 : case V8DF_FTYPE_V8DF_V2DF_INT_V8DF_UQI:
13086 : 1726 : case V8DI_FTYPE_V8DI_V2DI_INT_V8DI_UQI:
13087 : 1726 : case V8SI_FTYPE_V8SI_V8SI_INT_V8SI_UQI:
13088 : 1726 : case V4DI_FTYPE_V4DI_V4DI_INT_V4DI_UQI:
13089 : 1726 : case V4SI_FTYPE_V4SI_V4SI_INT_V4SI_UQI:
13090 : 1726 : case V2DI_FTYPE_V2DI_V2DI_INT_V2DI_UQI:
13091 : 1726 : case V32HI_FTYPE_V64QI_V64QI_INT_V32HI_USI:
13092 : 1726 : case V16HI_FTYPE_V32QI_V32QI_INT_V16HI_UHI:
13093 : 1726 : case V8HI_FTYPE_V16QI_V16QI_INT_V8HI_UQI:
13094 : 1726 : case V16SF_FTYPE_V16SF_V8SF_INT_V16SF_UHI:
13095 : 1726 : case V16SI_FTYPE_V16SI_V8SI_INT_V16SI_UHI:
13096 : 1726 : case V8SF_FTYPE_V8SF_V4SF_INT_V8SF_UQI:
13097 : 1726 : case V8SI_FTYPE_V8SI_V4SI_INT_V8SI_UQI:
13098 : 1726 : case V4DI_FTYPE_V4DI_V2DI_INT_V4DI_UQI:
13099 : 1726 : case V4DF_FTYPE_V4DF_V2DF_INT_V4DF_UQI:
13100 : 1726 : nargs = 5;
13101 : 1726 : mask_pos = 2;
13102 : 1726 : nargs_constant = 1;
13103 : 1726 : break;
13104 : 268 : case V8DI_FTYPE_V8DI_V8DI_V8DI_INT_UQI:
13105 : 268 : case V16SI_FTYPE_V16SI_V16SI_V16SI_INT_UHI:
13106 : 268 : case V2DF_FTYPE_V2DF_V2DF_V2DI_INT_UQI:
13107 : 268 : case V4SF_FTYPE_V4SF_V4SF_V4SI_INT_UQI:
13108 : 268 : case V8SF_FTYPE_V8SF_V8SF_V8SI_INT_UQI:
13109 : 268 : case V8SI_FTYPE_V8SI_V8SI_V8SI_INT_UQI:
13110 : 268 : case V4DF_FTYPE_V4DF_V4DF_V4DI_INT_UQI:
13111 : 268 : case V4DI_FTYPE_V4DI_V4DI_V4DI_INT_UQI:
13112 : 268 : case V4SI_FTYPE_V4SI_V4SI_V4SI_INT_UQI:
13113 : 268 : case V2DI_FTYPE_V2DI_V2DI_V2DI_INT_UQI:
13114 : 268 : nargs = 5;
13115 : 268 : mask_pos = 1;
13116 : 268 : nargs_constant = 1;
13117 : 268 : break;
13118 : 732 : case V64QI_FTYPE_V64QI_V64QI_INT_V64QI_UDI:
13119 : 732 : case V32QI_FTYPE_V32QI_V32QI_INT_V32QI_USI:
13120 : 732 : case V16QI_FTYPE_V16QI_V16QI_INT_V16QI_UHI:
13121 : 732 : case V32HI_FTYPE_V32HI_V32HI_INT_V32HI_INT:
13122 : 732 : case V16SI_FTYPE_V16SI_V16SI_INT_V16SI_INT:
13123 : 732 : case V8DI_FTYPE_V8DI_V8DI_INT_V8DI_INT:
13124 : 732 : case V16HI_FTYPE_V16HI_V16HI_INT_V16HI_INT:
13125 : 732 : case V8SI_FTYPE_V8SI_V8SI_INT_V8SI_INT:
13126 : 732 : case V4DI_FTYPE_V4DI_V4DI_INT_V4DI_INT:
13127 : 732 : case V8HI_FTYPE_V8HI_V8HI_INT_V8HI_INT:
13128 : 732 : case V4SI_FTYPE_V4SI_V4SI_INT_V4SI_INT:
13129 : 732 : case V2DI_FTYPE_V2DI_V2DI_INT_V2DI_INT:
13130 : 732 : case V8BF_FTYPE_V8BF_V8BF_INT_V8BF_UQI:
13131 : 732 : case V16BF_FTYPE_V16BF_V16BF_INT_V16BF_UHI:
13132 : 732 : case V32BF_FTYPE_V32BF_V32BF_INT_V32BF_USI:
13133 : 732 : case V16HF_FTYPE_V16HF_V16HF_INT_V16HF_UHI:
13134 : 732 : case V8HF_FTYPE_V8HF_V8HF_INT_V8HF_UQI:
13135 : 732 : nargs = 5;
13136 : 732 : mask_pos = 1;
13137 : 732 : nargs_constant = 2;
13138 : 732 : break;
13139 : :
13140 : 0 : default:
13141 : 0 : gcc_unreachable ();
13142 : : }
13143 : :
13144 : 56197 : gcc_assert (nargs <= ARRAY_SIZE (xops));
13145 : :
13146 : 60181 : if (comparison != UNKNOWN)
13147 : : {
13148 : 614 : gcc_assert (nargs == 2);
13149 : 614 : return ix86_expand_sse_compare (d, exp, target, swap);
13150 : : }
13151 : :
13152 : 59567 : if (rmode == VOIDmode || rmode == tmode)
13153 : : {
13154 : 59382 : if (optimize
13155 : 17718 : || target == 0
13156 : 17718 : || GET_MODE (target) != tmode
13157 : 76898 : || !insn_p->operand[0].predicate (target, tmode))
13158 : 41954 : target = gen_reg_rtx (tmode);
13159 : 17428 : else if (memory_operand (target, tmode))
13160 : 578 : num_memory++;
13161 : : real_target = target;
13162 : : }
13163 : : else
13164 : : {
13165 : 185 : real_target = gen_reg_rtx (tmode);
13166 : 185 : target = lowpart_subreg (rmode, real_target, tmode);
13167 : : }
13168 : :
13169 : 258135 : for (i = 0; i < nargs; i++)
13170 : : {
13171 : 198801 : tree arg = CALL_EXPR_ARG (exp, i);
13172 : 198801 : rtx op = ix86_expand_unsigned_small_int_cst_argument (arg);
13173 : 198801 : machine_mode mode = insn_p->operand[i + 1].mode;
13174 : : /* Need to fixup modeless constant before testing predicate. */
13175 : 198801 : op = fixup_modeless_constant (op, mode);
13176 : 198801 : bool match = insn_p->operand[i + 1].predicate (op, mode);
13177 : :
13178 : 198801 : if (second_arg_count && i == 1)
13179 : : {
13180 : : /* SIMD shift insns take either an 8-bit immediate or
13181 : : register as count. But builtin functions take int as
13182 : : count. If count doesn't match, we put it in register.
13183 : : The instructions are using 64-bit count, if op is just
13184 : : 32-bit, zero-extend it, as negative shift counts
13185 : : are undefined behavior and zero-extension is more
13186 : : efficient. */
13187 : 2887 : if (!match)
13188 : : {
13189 : 1748 : if (SCALAR_INT_MODE_P (GET_MODE (op)))
13190 : 489 : op = convert_modes (mode, GET_MODE (op), op, 1);
13191 : : else
13192 : 1259 : op = lowpart_subreg (mode, op, GET_MODE (op));
13193 : 1748 : if (!insn_p->operand[i + 1].predicate (op, mode))
13194 : 190 : op = copy_to_reg (op);
13195 : : }
13196 : : }
13197 : 195914 : else if ((mask_pos && (nargs - i - mask_pos) == nargs_constant) ||
13198 : 147862 : (!mask_pos && (nargs - i) <= nargs_constant))
13199 : : {
13200 : 16458 : if (!match)
13201 : 233 : switch (icode)
13202 : : {
13203 : 2 : case CODE_FOR_avx_vinsertf128v4di:
13204 : 2 : case CODE_FOR_avx_vextractf128v4di:
13205 : 2 : error ("the last argument must be an 1-bit immediate");
13206 : 2 : return const0_rtx;
13207 : :
13208 : 8 : case CODE_FOR_avx512f_cmpv8di3_mask:
13209 : 8 : case CODE_FOR_avx512f_cmpv16si3_mask:
13210 : 8 : case CODE_FOR_avx512f_ucmpv8di3_mask:
13211 : 8 : case CODE_FOR_avx512f_ucmpv16si3_mask:
13212 : 8 : case CODE_FOR_avx512vl_cmpv4di3_mask:
13213 : 8 : case CODE_FOR_avx512vl_cmpv8si3_mask:
13214 : 8 : case CODE_FOR_avx512vl_ucmpv4di3_mask:
13215 : 8 : case CODE_FOR_avx512vl_ucmpv8si3_mask:
13216 : 8 : case CODE_FOR_avx512vl_cmpv2di3_mask:
13217 : 8 : case CODE_FOR_avx512vl_cmpv4si3_mask:
13218 : 8 : case CODE_FOR_avx512vl_ucmpv2di3_mask:
13219 : 8 : case CODE_FOR_avx512vl_ucmpv4si3_mask:
13220 : 8 : error ("the last argument must be a 3-bit immediate");
13221 : 8 : return const0_rtx;
13222 : :
13223 : 24 : case CODE_FOR_sse4_1_roundsd:
13224 : 24 : case CODE_FOR_sse4_1_roundss:
13225 : :
13226 : 24 : case CODE_FOR_sse4_1_roundpd:
13227 : 24 : case CODE_FOR_sse4_1_roundps:
13228 : 24 : case CODE_FOR_avx_roundpd256:
13229 : 24 : case CODE_FOR_avx_roundps256:
13230 : :
13231 : 24 : case CODE_FOR_sse4_1_roundpd_vec_pack_sfix:
13232 : 24 : case CODE_FOR_sse4_1_roundps_sfix:
13233 : 24 : case CODE_FOR_avx_roundpd_vec_pack_sfix256:
13234 : 24 : case CODE_FOR_avx_roundps_sfix256:
13235 : :
13236 : 24 : case CODE_FOR_sse4_1_blendps:
13237 : 24 : case CODE_FOR_avx_blendpd256:
13238 : 24 : case CODE_FOR_avx_vpermilv4df:
13239 : 24 : case CODE_FOR_avx_vpermilv4df_mask:
13240 : 24 : case CODE_FOR_avx512f_getmantv8df_mask:
13241 : 24 : case CODE_FOR_avx512f_getmantv16sf_mask:
13242 : 24 : case CODE_FOR_avx512vl_getmantv16hf_mask:
13243 : 24 : case CODE_FOR_avx512vl_getmantv8sf_mask:
13244 : 24 : case CODE_FOR_avx512vl_getmantv4df_mask:
13245 : 24 : case CODE_FOR_avx512fp16_getmantv8hf_mask:
13246 : 24 : case CODE_FOR_avx512vl_getmantv4sf_mask:
13247 : 24 : case CODE_FOR_avx512vl_getmantv2df_mask:
13248 : 24 : case CODE_FOR_avx512dq_rangepv8df_mask_round:
13249 : 24 : case CODE_FOR_avx512dq_rangepv16sf_mask_round:
13250 : 24 : case CODE_FOR_avx512dq_rangepv4df_mask:
13251 : 24 : case CODE_FOR_avx512dq_rangepv8sf_mask:
13252 : 24 : case CODE_FOR_avx512dq_rangepv2df_mask:
13253 : 24 : case CODE_FOR_avx512dq_rangepv4sf_mask:
13254 : 24 : case CODE_FOR_avx_shufpd256_mask:
13255 : 24 : error ("the last argument must be a 4-bit immediate");
13256 : 24 : return const0_rtx;
13257 : :
13258 : 15 : case CODE_FOR_sha1rnds4:
13259 : 15 : case CODE_FOR_sse4_1_blendpd:
13260 : 15 : case CODE_FOR_avx_vpermilv2df:
13261 : 15 : case CODE_FOR_avx_vpermilv2df_mask:
13262 : 15 : case CODE_FOR_xop_vpermil2v2df3:
13263 : 15 : case CODE_FOR_xop_vpermil2v4sf3:
13264 : 15 : case CODE_FOR_xop_vpermil2v4df3:
13265 : 15 : case CODE_FOR_xop_vpermil2v8sf3:
13266 : 15 : case CODE_FOR_avx512f_vinsertf32x4_mask:
13267 : 15 : case CODE_FOR_avx512f_vinserti32x4_mask:
13268 : 15 : case CODE_FOR_avx512f_vextractf32x4_mask:
13269 : 15 : case CODE_FOR_avx512f_vextracti32x4_mask:
13270 : 15 : case CODE_FOR_sse2_shufpd:
13271 : 15 : case CODE_FOR_sse2_shufpd_mask:
13272 : 15 : case CODE_FOR_avx512dq_shuf_f64x2_mask:
13273 : 15 : case CODE_FOR_avx512dq_shuf_i64x2_mask:
13274 : 15 : case CODE_FOR_avx512vl_shuf_i32x4_mask:
13275 : 15 : case CODE_FOR_avx512vl_shuf_f32x4_mask:
13276 : 15 : error ("the last argument must be a 2-bit immediate");
13277 : 15 : return const0_rtx;
13278 : :
13279 : 30 : case CODE_FOR_avx_vextractf128v4df:
13280 : 30 : case CODE_FOR_avx_vextractf128v8sf:
13281 : 30 : case CODE_FOR_avx_vextractf128v8si:
13282 : 30 : case CODE_FOR_avx_vinsertf128v4df:
13283 : 30 : case CODE_FOR_avx_vinsertf128v8sf:
13284 : 30 : case CODE_FOR_avx_vinsertf128v8si:
13285 : 30 : case CODE_FOR_avx512f_vinsertf64x4_mask:
13286 : 30 : case CODE_FOR_avx512f_vinserti64x4_mask:
13287 : 30 : case CODE_FOR_avx512f_vextractf64x4_mask:
13288 : 30 : case CODE_FOR_avx512f_vextracti64x4_mask:
13289 : 30 : case CODE_FOR_avx512dq_vinsertf32x8_mask:
13290 : 30 : case CODE_FOR_avx512dq_vinserti32x8_mask:
13291 : 30 : case CODE_FOR_avx512vl_vinsertv4df:
13292 : 30 : case CODE_FOR_avx512vl_vinsertv4di:
13293 : 30 : case CODE_FOR_avx512vl_vinsertv8sf:
13294 : 30 : case CODE_FOR_avx512vl_vinsertv8si:
13295 : 30 : error ("the last argument must be a 1-bit immediate");
13296 : 30 : return const0_rtx;
13297 : :
13298 : 16 : case CODE_FOR_avx_vmcmpv2df3:
13299 : 16 : case CODE_FOR_avx_vmcmpv4sf3:
13300 : 16 : case CODE_FOR_avx_cmpv2df3:
13301 : 16 : case CODE_FOR_avx_cmpv4sf3:
13302 : 16 : if (CONST_INT_P (op) && IN_RANGE (INTVAL (op), 8, 31))
13303 : : {
13304 : 4 : error ("'%s' needs isa option %s", d->name, "-mavx");
13305 : 4 : return const0_rtx;
13306 : : }
13307 : : /* FALLTHRU */
13308 : 18 : case CODE_FOR_avx_cmpv4df3:
13309 : 18 : case CODE_FOR_avx_cmpv8sf3:
13310 : 18 : case CODE_FOR_avx512f_cmpv8df3_mask:
13311 : 18 : case CODE_FOR_avx512f_cmpv16sf3_mask:
13312 : 18 : case CODE_FOR_avx512f_vmcmpv2df3_mask:
13313 : 18 : case CODE_FOR_avx512f_vmcmpv4sf3_mask:
13314 : 18 : case CODE_FOR_avx512bw_cmpv32hf3_mask:
13315 : 18 : case CODE_FOR_avx512vl_cmpv16hf3_mask:
13316 : 18 : case CODE_FOR_avx512fp16_cmpv8hf3_mask:
13317 : 18 : error ("the last argument must be a 5-bit immediate");
13318 : 18 : return const0_rtx;
13319 : :
13320 : 132 : default:
13321 : 132 : switch (nargs_constant)
13322 : : {
13323 : 8 : case 2:
13324 : 8 : if ((mask_pos && (nargs - i - mask_pos) == nargs_constant) ||
13325 : 8 : (!mask_pos && (nargs - i) == nargs_constant))
13326 : : {
13327 : 4 : error ("the next to last argument must be an 8-bit immediate");
13328 : 4 : break;
13329 : : }
13330 : : /* FALLTHRU */
13331 : 128 : case 1:
13332 : 128 : error ("the last argument must be an 8-bit immediate");
13333 : 128 : break;
13334 : 0 : default:
13335 : 0 : gcc_unreachable ();
13336 : : }
13337 : 132 : return const0_rtx;
13338 : : }
13339 : : }
13340 : : else
13341 : : {
13342 : 179456 : if (VECTOR_MODE_P (mode))
13343 : 128930 : op = safe_vector_operand (op, mode);
13344 : :
13345 : : /* If we aren't optimizing, only allow one memory operand to
13346 : : be generated. */
13347 : 179456 : if (memory_operand (op, mode))
13348 : : {
13349 : 29958 : num_memory++;
13350 : 29958 : if (!optimize && num_memory > 1)
13351 : 13719 : op = copy_to_mode_reg (mode, op);
13352 : : }
13353 : :
13354 : 179456 : if (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)
13355 : : {
13356 : 177122 : if (!match)
13357 : 42557 : op = copy_to_mode_reg (mode, op);
13358 : : }
13359 : : else
13360 : : {
13361 : 2334 : op = copy_to_reg (op);
13362 : 2334 : op = lowpart_subreg (mode, op, GET_MODE (op));
13363 : : }
13364 : : }
13365 : :
13366 : 198568 : xops[i] = op;
13367 : : }
13368 : :
13369 : 59334 : switch (nargs)
13370 : : {
13371 : 3370 : case 1:
13372 : 3370 : pat = GEN_FCN (icode) (real_target, xops[0]);
13373 : 3370 : break;
13374 : 5654 : case 2:
13375 : 5654 : pat = GEN_FCN (icode) (real_target, xops[0], xops[1]);
13376 : 5654 : break;
13377 : 20461 : case 3:
13378 : 20461 : pat = GEN_FCN (icode) (real_target, xops[0], xops[1], xops[2]);
13379 : 20461 : break;
13380 : 27109 : case 4:
13381 : 27109 : pat = GEN_FCN (icode) (real_target, xops[0], xops[1],
13382 : 27109 : xops[2], xops[3]);
13383 : 27109 : break;
13384 : 2740 : case 5:
13385 : 2740 : pat = GEN_FCN (icode) (real_target, xops[0], xops[1],
13386 : 2740 : xops[2], xops[3], xops[4]);
13387 : 2740 : break;
13388 : : case 6:
13389 : : pat = GEN_FCN (icode) (real_target, xops[0], xops[1],
13390 : : xops[2], xops[3], xops[4], xops[5]);
13391 : : break;
13392 : : default:
13393 : : gcc_unreachable ();
13394 : : }
13395 : :
13396 : 59334 : if (! pat)
13397 : : return 0;
13398 : :
13399 : 59334 : emit_insn (pat);
13400 : 59334 : return target;
13401 : : }
13402 : :
13403 : : /* Transform pattern of following layout:
13404 : : (set A
13405 : : (unspec [B C] UNSPEC_EMBEDDED_ROUNDING))
13406 : : )
13407 : : into:
13408 : : (set (A B)) */
13409 : :
13410 : : static rtx
13411 : 5025 : ix86_erase_embedded_rounding (rtx pat)
13412 : : {
13413 : 5025 : if (NONJUMP_INSN_P (pat))
13414 : 779 : pat = PATTERN (pat);
13415 : :
13416 : 5025 : gcc_assert (GET_CODE (pat) == SET);
13417 : 5025 : rtx src = SET_SRC (pat);
13418 : 5025 : gcc_assert (XVECLEN (src, 0) == 2);
13419 : 5025 : rtx p0 = XVECEXP (src, 0, 0);
13420 : 5025 : gcc_assert (GET_CODE (src) == UNSPEC
13421 : : && XINT (src, 1) == UNSPEC_EMBEDDED_ROUNDING);
13422 : 5025 : rtx res = gen_rtx_SET (SET_DEST (pat), p0);
13423 : 5025 : return res;
13424 : : }
13425 : :
13426 : : /* Subroutine of ix86_expand_round_builtin to take care of comi insns
13427 : : with rounding. */
13428 : : static rtx
13429 : 103 : ix86_expand_sse_comi_round (const struct builtin_description *d,
13430 : : tree exp, rtx target, bool comx_ok)
13431 : : {
13432 : 103 : rtx pat, set_dst;
13433 : 103 : tree arg0 = CALL_EXPR_ARG (exp, 0);
13434 : 103 : tree arg1 = CALL_EXPR_ARG (exp, 1);
13435 : 103 : tree arg2 = CALL_EXPR_ARG (exp, 2);
13436 : 103 : tree arg3 = CALL_EXPR_ARG (exp, 3);
13437 : 103 : rtx op0 = expand_normal (arg0);
13438 : 103 : rtx op1 = expand_normal (arg1);
13439 : 103 : rtx op2 = expand_normal (arg2);
13440 : 103 : rtx op3 = expand_normal (arg3);
13441 : 103 : enum insn_code icode = d->icode;
13442 : 103 : const struct insn_data_d *insn_p = &insn_data[icode];
13443 : 103 : machine_mode mode0 = insn_p->operand[0].mode;
13444 : 103 : machine_mode mode1 = insn_p->operand[1].mode;
13445 : :
13446 : : /* See avxintrin.h for values. */
13447 : 103 : static const enum rtx_code comparisons[32] =
13448 : : {
13449 : : EQ, LT, LE, UNORDERED, NE, UNGE, UNGT, ORDERED,
13450 : : UNEQ, UNLT, UNLE, UNORDERED, LTGT, GE, GT, ORDERED,
13451 : : EQ, LT, LE, UNORDERED, NE, UNGE, UNGT, ORDERED,
13452 : : UNEQ, UNLT, UNLE, UNORDERED, LTGT, GE, GT, ORDERED
13453 : : };
13454 : 103 : static const bool ordereds[32] =
13455 : : {
13456 : : true, true, true, false, false, false, false, true,
13457 : : false, false, false, true, true, true, true, false,
13458 : : true, true, true, false, false, false, false, true,
13459 : : false, false, false, true, true, true, true, false
13460 : : };
13461 : 103 : static const bool non_signalings[32] =
13462 : : {
13463 : : true, false, false, true, true, false, false, true,
13464 : : true, false, false, true, true, false, false, true,
13465 : : false, true, true, false, false, true, true, false,
13466 : : false, true, true, false, false, true, true, false
13467 : : };
13468 : :
13469 : 103 : if (!CONST_INT_P (op2))
13470 : : {
13471 : 0 : error ("the third argument must be comparison constant");
13472 : 0 : return const0_rtx;
13473 : : }
13474 : 103 : if (INTVAL (op2) < 0 || INTVAL (op2) >= 32)
13475 : : {
13476 : 0 : error ("incorrect comparison mode");
13477 : 0 : return const0_rtx;
13478 : : }
13479 : :
13480 : 103 : if (!insn_p->operand[2].predicate (op3, SImode))
13481 : : {
13482 : 4 : error ("incorrect rounding operand");
13483 : 4 : return const0_rtx;
13484 : : }
13485 : :
13486 : 99 : if (VECTOR_MODE_P (mode0))
13487 : 99 : op0 = safe_vector_operand (op0, mode0);
13488 : 99 : if (VECTOR_MODE_P (mode1))
13489 : 99 : op1 = safe_vector_operand (op1, mode1);
13490 : :
13491 : 99 : enum rtx_code comparison = comparisons[INTVAL (op2)];
13492 : 99 : enum rtx_code orig_comp = comparison;
13493 : 99 : bool ordered = ordereds[INTVAL (op2)];
13494 : 99 : bool non_signaling = non_signalings[INTVAL (op2)];
13495 : 99 : rtx const_val = const0_rtx;
13496 : :
13497 : 99 : bool check_unordered = false;
13498 : 99 : machine_mode mode = CCFPmode;
13499 : 99 : switch (comparison)
13500 : : {
13501 : 8 : case ORDERED:
13502 : 8 : if (!ordered)
13503 : : {
13504 : 4 : if (TARGET_AVX10_2 && comx_ok)
13505 : : {
13506 : : /* Unlike VCOMI{SH,SS,SD}, VCOMX{SH,SS,SD} will set SF
13507 : : differently. So directly return true here. */
13508 : 0 : target = gen_reg_rtx (SImode);
13509 : 0 : emit_move_insn (target, const1_rtx);
13510 : 0 : return target;
13511 : : }
13512 : : else
13513 : : {
13514 : : /* NB: Use CCSmode/NE for _CMP_TRUE_UQ/_CMP_TRUE_US. */
13515 : : if (!non_signaling)
13516 : 99 : ordered = true;
13517 : 99 : mode = CCSmode;
13518 : : }
13519 : : }
13520 : : else
13521 : : {
13522 : : /* NB: Use CCPmode/NE for _CMP_ORD_Q/_CMP_ORD_S. */
13523 : : if (non_signaling)
13524 : : ordered = false;
13525 : : mode = CCPmode;
13526 : : }
13527 : : comparison = NE;
13528 : : break;
13529 : 8 : case UNORDERED:
13530 : 8 : if (ordered)
13531 : : {
13532 : 4 : if (TARGET_AVX10_2 && comx_ok)
13533 : : {
13534 : : /* Unlike VCOMI{SH,SS,SD}, VCOMX{SH,SS,SD} will set SF
13535 : : differently. So directly return false here. */
13536 : 0 : target = gen_reg_rtx (SImode);
13537 : 0 : emit_move_insn (target, const0_rtx);
13538 : 0 : return target;
13539 : : }
13540 : : else
13541 : : {
13542 : : /* NB: Use CCSmode/EQ for _CMP_FALSE_OQ/_CMP_FALSE_OS. */
13543 : : if (non_signaling)
13544 : 99 : ordered = false;
13545 : : mode = CCSmode;
13546 : : }
13547 : : }
13548 : : else
13549 : : {
13550 : : /* NB: Use CCPmode/NE for _CMP_UNORD_Q/_CMP_UNORD_S. */
13551 : : if (!non_signaling)
13552 : 99 : ordered = true;
13553 : 99 : mode = CCPmode;
13554 : : }
13555 : : comparison = EQ;
13556 : : break;
13557 : :
13558 : 40 : case LE: /* -> GE */
13559 : 40 : case LT: /* -> GT */
13560 : 40 : case UNGE: /* -> UNLE */
13561 : 40 : case UNGT: /* -> UNLT */
13562 : 40 : std::swap (op0, op1);
13563 : 40 : comparison = swap_condition (comparison);
13564 : : /* FALLTHRU */
13565 : 68 : case GT:
13566 : 68 : case GE:
13567 : 68 : case UNEQ:
13568 : 68 : case UNLT:
13569 : 68 : case UNLE:
13570 : 68 : case LTGT:
13571 : : /* These are supported by CCFPmode. NB: Use ordered/signaling
13572 : : COMI or unordered/non-signaling UCOMI. Both set ZF, PF, CF
13573 : : with NAN operands. */
13574 : 68 : if (ordered == non_signaling)
13575 : : ordered = !ordered;
13576 : : break;
13577 : : /* NB: COMI/UCOMI will set ZF with NAN operands. Use CCZmode for
13578 : : _CMP_EQ_OQ/_CMP_EQ_OS.
13579 : : Under TARGET_AVX10_2, VCOMX/VUCOMX are always generated instead
13580 : : of COMI/UCOMI, VCOMX/VUCOMX will not set ZF with NAN. */
13581 : 8 : case EQ:
13582 : 8 : if (!TARGET_AVX10_2 || !comx_ok)
13583 : 5 : check_unordered = true;
13584 : : mode = CCZmode;
13585 : : break;
13586 : 7 : case NE:
13587 : : /* NB: COMI/UCOMI will set ZF with NAN operands. Use CCZmode for
13588 : : _CMP_NEQ_UQ/_CMP_NEQ_US.
13589 : : Under TARGET_AVX10_2, VCOMX/VUCOMX are always generated instead
13590 : : of COMI/UCOMI, VCOMX/VUCOMX will not set ZF with NAN. */
13591 : 7 : gcc_assert (!ordered);
13592 : 7 : if (!TARGET_AVX10_2 || !comx_ok)
13593 : 4 : check_unordered = true;
13594 : 7 : mode = CCZmode;
13595 : 7 : const_val = const1_rtx;
13596 : 7 : break;
13597 : 0 : default:
13598 : 0 : gcc_unreachable ();
13599 : : }
13600 : :
13601 : 99 : target = gen_reg_rtx (SImode);
13602 : 99 : emit_move_insn (target, const_val);
13603 : 99 : target = gen_rtx_SUBREG (QImode, target, 0);
13604 : :
13605 : 93 : if ((optimize && !register_operand (op0, mode0))
13606 : 192 : || !insn_p->operand[0].predicate (op0, mode0))
13607 : 6 : op0 = copy_to_mode_reg (mode0, op0);
13608 : 93 : if ((optimize && !register_operand (op1, mode1))
13609 : 192 : || !insn_p->operand[1].predicate (op1, mode1))
13610 : 6 : op1 = copy_to_mode_reg (mode1, op1);
13611 : :
13612 : : /* Generate comx instead of comi when EQ/NE to avoid NAN checks.
13613 : : Use orig_comp to exclude ORDERED/UNORDERED cases. */
13614 : 99 : if ((orig_comp == EQ || orig_comp == NE)
13615 : 15 : && TARGET_AVX10_2 && comx_ok)
13616 : : {
13617 : 6 : switch (icode)
13618 : : {
13619 : : case CODE_FOR_avx512fp16_comi_round:
13620 : 99 : icode = CODE_FOR_avx10_2_comxhf_round;
13621 : : break;
13622 : 4 : case CODE_FOR_sse_comi_round:
13623 : 4 : icode = CODE_FOR_avx10_2_comxsf_round;
13624 : 4 : break;
13625 : 2 : case CODE_FOR_sse2_comi_round:
13626 : 2 : icode = CODE_FOR_avx10_2_comxdf_round;
13627 : 2 : break;
13628 : :
13629 : : default:
13630 : : break;
13631 : : }
13632 : : }
13633 : :
13634 : : /* Generate comi instead of comx when UNEQ/LTGT to avoid NAN checks. */
13635 : 99 : if ((comparison == UNEQ || comparison == LTGT)
13636 : 8 : && TARGET_AVX10_2 && comx_ok)
13637 : : {
13638 : 0 : switch (icode)
13639 : : {
13640 : : case CODE_FOR_avx10_2_comxhf_round:
13641 : 99 : icode = CODE_FOR_avx512fp16_comi_round;
13642 : : break;
13643 : 0 : case CODE_FOR_avx10_2_comxsf_round:
13644 : 0 : icode = CODE_FOR_sse_comi_round;
13645 : 0 : break;
13646 : 0 : case CODE_FOR_avx10_2_comxdf_round:
13647 : 0 : icode = CODE_FOR_sse2_comi_round;
13648 : 0 : break;
13649 : :
13650 : : default:
13651 : : break;
13652 : : }
13653 : : }
13654 : :
13655 : : /*
13656 : : 1. COMI/VCOMX: ordered and signaling.
13657 : : 2. UCOMI/VUCOMX: unordered and non-signaling.
13658 : : */
13659 : 99 : if (non_signaling)
13660 : 38 : switch (icode)
13661 : : {
13662 : : case CODE_FOR_sse_comi_round:
13663 : : icode = CODE_FOR_sse_ucomi_round;
13664 : : break;
13665 : 17 : case CODE_FOR_sse2_comi_round:
13666 : 17 : icode = CODE_FOR_sse2_ucomi_round;
13667 : 17 : break;
13668 : 0 : case CODE_FOR_avx512fp16_comi_round:
13669 : 0 : icode = CODE_FOR_avx512fp16_ucomi_round;
13670 : 0 : break;
13671 : 3 : case CODE_FOR_avx10_2_comxsf_round:
13672 : 3 : icode = CODE_FOR_avx10_2_ucomxsf_round;
13673 : 3 : break;
13674 : 0 : case CODE_FOR_avx10_2_comxhf_round:
13675 : 0 : icode = CODE_FOR_avx10_2_ucomxhf_round;
13676 : 0 : break;
13677 : 1 : case CODE_FOR_avx10_2_comxdf_round:
13678 : 1 : icode = CODE_FOR_avx10_2_ucomxdf_round;
13679 : 1 : break;
13680 : 0 : default:
13681 : 0 : gcc_unreachable ();
13682 : : }
13683 : :
13684 : 99 : pat = GEN_FCN (icode) (op0, op1, op3);
13685 : 99 : if (! pat)
13686 : : return 0;
13687 : :
13688 : : /* Rounding operand can be either NO_ROUND or ROUND_SAE at this point. */
13689 : 99 : if (INTVAL (op3) == NO_ROUND)
13690 : : {
13691 : 1 : pat = ix86_erase_embedded_rounding (pat);
13692 : 1 : if (! pat)
13693 : : return 0;
13694 : :
13695 : 1 : set_dst = SET_DEST (pat);
13696 : : }
13697 : : else
13698 : : {
13699 : 98 : gcc_assert (GET_CODE (pat) == SET);
13700 : 98 : set_dst = SET_DEST (pat);
13701 : : }
13702 : :
13703 : 99 : emit_insn (pat);
13704 : :
13705 : 99 : return ix86_ssecom_setcc (comparison, check_unordered, mode,
13706 : 99 : set_dst, target);
13707 : : }
13708 : :
13709 : : static rtx
13710 : 15832 : ix86_expand_round_builtin (const struct builtin_description *d,
13711 : : tree exp, rtx target)
13712 : : {
13713 : 15832 : rtx pat;
13714 : 15832 : unsigned int i, nargs;
13715 : 15832 : rtx xops[6];
13716 : 15832 : enum insn_code icode = d->icode;
13717 : 15832 : const struct insn_data_d *insn_p = &insn_data[icode];
13718 : 15832 : machine_mode tmode = insn_p->operand[0].mode;
13719 : 15832 : unsigned int nargs_constant = 0;
13720 : 15832 : unsigned int redundant_embed_rnd = 0;
13721 : :
13722 : 15832 : switch ((enum ix86_builtin_func_type) d->flag)
13723 : : {
13724 : : case UINT64_FTYPE_V2DF_INT:
13725 : : case UINT64_FTYPE_V4SF_INT:
13726 : : case UINT64_FTYPE_V8HF_INT:
13727 : : case UINT_FTYPE_V2DF_INT:
13728 : : case UINT_FTYPE_V4SF_INT:
13729 : : case UINT_FTYPE_V8HF_INT:
13730 : : case INT64_FTYPE_V2DF_INT:
13731 : : case INT64_FTYPE_V4SF_INT:
13732 : : case INT64_FTYPE_V8HF_INT:
13733 : : case INT_FTYPE_V2DF_INT:
13734 : : case INT_FTYPE_V4SF_INT:
13735 : : case INT_FTYPE_V8HF_INT:
13736 : : nargs = 2;
13737 : : break;
13738 : 736 : case V32HF_FTYPE_V32HF_V32HF_INT:
13739 : 736 : case V8HF_FTYPE_V8HF_V8HF_INT:
13740 : 736 : case V8HF_FTYPE_V8HF_INT_INT:
13741 : 736 : case V8HF_FTYPE_V8HF_UINT_INT:
13742 : 736 : case V8HF_FTYPE_V8HF_INT64_INT:
13743 : 736 : case V8HF_FTYPE_V8HF_UINT64_INT:
13744 : 736 : case V4SF_FTYPE_V4SF_UINT_INT:
13745 : 736 : case V4SF_FTYPE_V4SF_UINT64_INT:
13746 : 736 : case V2DF_FTYPE_V2DF_UINT64_INT:
13747 : 736 : case V4SF_FTYPE_V4SF_INT_INT:
13748 : 736 : case V4SF_FTYPE_V4SF_INT64_INT:
13749 : 736 : case V2DF_FTYPE_V2DF_INT64_INT:
13750 : 736 : case V4SF_FTYPE_V4SF_V4SF_INT:
13751 : 736 : case V2DF_FTYPE_V2DF_V2DF_INT:
13752 : 736 : case V4SF_FTYPE_V4SF_V2DF_INT:
13753 : 736 : case V2DF_FTYPE_V2DF_V4SF_INT:
13754 : 736 : nargs = 3;
13755 : 736 : break;
13756 : 4554 : case V8SF_FTYPE_V8DF_V8SF_QI_INT:
13757 : 4554 : case V8DF_FTYPE_V8DF_V8DF_QI_INT:
13758 : 4554 : case V32HI_FTYPE_V32HF_V32HI_USI_INT:
13759 : 4554 : case V32HI_FTYPE_V32BF_V32HI_USI_INT:
13760 : 4554 : case V8SI_FTYPE_V8DF_V8SI_QI_INT:
13761 : 4554 : case V8DI_FTYPE_V8HF_V8DI_UQI_INT:
13762 : 4554 : case V8DI_FTYPE_V8DF_V8DI_QI_INT:
13763 : 4554 : case V8SF_FTYPE_V8DI_V8SF_QI_INT:
13764 : 4554 : case V8DF_FTYPE_V8DI_V8DF_QI_INT:
13765 : 4554 : case V8DF_FTYPE_V8HF_V8DF_UQI_INT:
13766 : 4554 : case V16SF_FTYPE_V16HF_V16SF_UHI_INT:
13767 : 4554 : case V32HF_FTYPE_V32HI_V32HF_USI_INT:
13768 : 4554 : case V32HF_FTYPE_V32HF_V32HF_USI_INT:
13769 : 4554 : case V32HF_FTYPE_V32HF_V32HF_V32HF_INT:
13770 : 4554 : case V16SF_FTYPE_V16SF_V16SF_HI_INT:
13771 : 4554 : case V8DI_FTYPE_V8SF_V8DI_QI_INT:
13772 : 4554 : case V16SF_FTYPE_V16SI_V16SF_HI_INT:
13773 : 4554 : case V16SI_FTYPE_V16SF_V16SI_HI_INT:
13774 : 4554 : case V16SI_FTYPE_V16SF_V16SI_UHI_INT:
13775 : 4554 : case V16SI_FTYPE_V16HF_V16SI_UHI_INT:
13776 : 4554 : case V16HF_FTYPE_V16SI_V16HF_UHI_INT:
13777 : 4554 : case V8DF_FTYPE_V8SF_V8DF_QI_INT:
13778 : 4554 : case V16SF_FTYPE_V16HI_V16SF_HI_INT:
13779 : 4554 : case V2DF_FTYPE_V2DF_V2DF_V2DF_INT:
13780 : 4554 : case V4SF_FTYPE_V4SF_V4SF_V4SF_INT:
13781 : 4554 : case V8HF_FTYPE_V8DI_V8HF_UQI_INT:
13782 : 4554 : case V8HF_FTYPE_V8DF_V8HF_UQI_INT:
13783 : 4554 : case V16HF_FTYPE_V16SF_V16HF_UHI_INT:
13784 : 4554 : case V16HI_FTYPE_V16BF_V16HI_UHI_INT:
13785 : 4554 : case V8HF_FTYPE_V8HF_V8HF_V8HF_INT:
13786 : 4554 : nargs = 4;
13787 : 4554 : break;
13788 : 265 : case V4SF_FTYPE_V4SF_V4SF_INT_INT:
13789 : 265 : case V2DF_FTYPE_V2DF_V2DF_INT_INT:
13790 : 265 : nargs_constant = 2;
13791 : 265 : nargs = 4;
13792 : 265 : break;
13793 : 103 : case INT_FTYPE_V4SF_V4SF_INT_INT:
13794 : 103 : case INT_FTYPE_V2DF_V2DF_INT_INT:
13795 : 103 : return ix86_expand_sse_comi_round (d, exp, target, true);
13796 : 6314 : case V8DF_FTYPE_V8DF_V8DF_V8DF_UQI_INT:
13797 : 6314 : case V2DF_FTYPE_V2DF_V2DF_V2DF_UQI_INT:
13798 : 6314 : case V4SF_FTYPE_V4SF_V4SF_V4SF_UQI_INT:
13799 : 6314 : case V4SF_FTYPE_V8HF_V4SF_V4SF_UQI_INT:
13800 : 6314 : case V16SF_FTYPE_V16SF_V16SF_V16SF_HI_INT:
13801 : 6314 : case V32HF_FTYPE_V32HF_V32HF_V32HF_UHI_INT:
13802 : 6314 : case V32HF_FTYPE_V32HF_V32HF_V32HF_USI_INT:
13803 : 6314 : case V2DF_FTYPE_V8HF_V2DF_V2DF_UQI_INT:
13804 : 6314 : case V2DF_FTYPE_V2DF_V2DF_V2DF_QI_INT:
13805 : 6314 : case V2DF_FTYPE_V2DF_V4SF_V2DF_QI_INT:
13806 : 6314 : case V2DF_FTYPE_V2DF_V4SF_V2DF_UQI_INT:
13807 : 6314 : case V4SF_FTYPE_V4SF_V4SF_V4SF_QI_INT:
13808 : 6314 : case V4SF_FTYPE_V4SF_V2DF_V4SF_QI_INT:
13809 : 6314 : case V4SF_FTYPE_V4SF_V2DF_V4SF_UQI_INT:
13810 : 6314 : case V8HF_FTYPE_V8HF_V8HF_V8HF_UQI_INT:
13811 : 6314 : case V8HF_FTYPE_V2DF_V8HF_V8HF_UQI_INT:
13812 : 6314 : case V8HF_FTYPE_V4SF_V8HF_V8HF_UQI_INT:
13813 : 6314 : case V32HF_FTYPE_V16SF_V16SF_V32HF_USI_INT:
13814 : 6314 : nargs = 5;
13815 : 6314 : break;
13816 : 635 : case V32HF_FTYPE_V32HF_INT_V32HF_USI_INT:
13817 : 635 : case V16SF_FTYPE_V16SF_INT_V16SF_HI_INT:
13818 : 635 : case V8DF_FTYPE_V8DF_INT_V8DF_QI_INT:
13819 : 635 : case V8DF_FTYPE_V8DF_INT_V8DF_UQI_INT:
13820 : 635 : case V16SF_FTYPE_V16SF_INT_V16SF_UHI_INT:
13821 : 635 : nargs_constant = 4;
13822 : 635 : nargs = 5;
13823 : 635 : break;
13824 : 1181 : case UQI_FTYPE_V8DF_V8DF_INT_UQI_INT:
13825 : 1181 : case UQI_FTYPE_V2DF_V2DF_INT_UQI_INT:
13826 : 1181 : case UHI_FTYPE_V16SF_V16SF_INT_UHI_INT:
13827 : 1181 : case UQI_FTYPE_V4SF_V4SF_INT_UQI_INT:
13828 : 1181 : case USI_FTYPE_V32HF_V32HF_INT_USI_INT:
13829 : 1181 : case UQI_FTYPE_V8HF_V8HF_INT_UQI_INT:
13830 : 1181 : nargs_constant = 3;
13831 : 1181 : nargs = 5;
13832 : 1181 : break;
13833 : 1071 : case V16SF_FTYPE_V16SF_V16SF_INT_V16SF_HI_INT:
13834 : 1071 : case V8DF_FTYPE_V8DF_V8DF_INT_V8DF_QI_INT:
13835 : 1071 : case V4SF_FTYPE_V4SF_V4SF_INT_V4SF_QI_INT:
13836 : 1071 : case V2DF_FTYPE_V2DF_V2DF_INT_V2DF_QI_INT:
13837 : 1071 : case V2DF_FTYPE_V2DF_V2DF_INT_V2DF_UQI_INT:
13838 : 1071 : case V4SF_FTYPE_V4SF_V4SF_INT_V4SF_UQI_INT:
13839 : 1071 : case V8HF_FTYPE_V8HF_V8HF_INT_V8HF_UQI_INT:
13840 : 1071 : case V8DF_FTYPE_V8DF_V8DF_INT_V8DF_UQI_INT:
13841 : 1071 : case V32HF_FTYPE_V32HF_V32HF_INT_V32HF_USI_INT:
13842 : 1071 : case V16SF_FTYPE_V16SF_V16SF_INT_V16SF_UHI_INT:
13843 : 1071 : nargs = 6;
13844 : 1071 : nargs_constant = 4;
13845 : 1071 : break;
13846 : 252 : case V8DF_FTYPE_V8DF_V8DF_V8DI_INT_QI_INT:
13847 : 252 : case V16SF_FTYPE_V16SF_V16SF_V16SI_INT_HI_INT:
13848 : 252 : case V2DF_FTYPE_V2DF_V2DF_V2DI_INT_QI_INT:
13849 : 252 : case V4SF_FTYPE_V4SF_V4SF_V4SI_INT_QI_INT:
13850 : 252 : nargs = 6;
13851 : 252 : nargs_constant = 3;
13852 : 252 : break;
13853 : 0 : default:
13854 : 0 : gcc_unreachable ();
13855 : : }
13856 : 15008 : gcc_assert (nargs <= ARRAY_SIZE (xops));
13857 : :
13858 : 15729 : if (optimize
13859 : 4261 : || target == 0
13860 : 4261 : || GET_MODE (target) != tmode
13861 : 19990 : || !insn_p->operand[0].predicate (target, tmode))
13862 : 11468 : target = gen_reg_rtx (tmode);
13863 : :
13864 : 86592 : for (i = 0; i < nargs; i++)
13865 : : {
13866 : 71418 : tree arg = CALL_EXPR_ARG (exp, i);
13867 : 71418 : rtx op = ix86_expand_unsigned_small_int_cst_argument (arg);
13868 : 71418 : machine_mode mode = insn_p->operand[i + 1].mode;
13869 : 71418 : bool match = insn_p->operand[i + 1].predicate (op, mode);
13870 : :
13871 : 71418 : if (i == nargs - nargs_constant)
13872 : : {
13873 : 3404 : if (!match)
13874 : : {
13875 : 40 : switch (icode)
13876 : : {
13877 : 12 : case CODE_FOR_avx512f_getmantv8df_mask_round:
13878 : 12 : case CODE_FOR_avx512f_getmantv16sf_mask_round:
13879 : 12 : case CODE_FOR_avx512bw_getmantv32hf_mask_round:
13880 : 12 : case CODE_FOR_avx512f_vgetmantv2df_round:
13881 : 12 : case CODE_FOR_avx512f_vgetmantv2df_mask_round:
13882 : 12 : case CODE_FOR_avx512f_vgetmantv4sf_round:
13883 : 12 : case CODE_FOR_avx512f_vgetmantv4sf_mask_round:
13884 : 12 : case CODE_FOR_avx512f_vgetmantv8hf_mask_round:
13885 : 12 : error ("the immediate argument must be a 4-bit immediate");
13886 : 12 : return const0_rtx;
13887 : 8 : case CODE_FOR_avx512f_cmpv8df3_mask_round:
13888 : 8 : case CODE_FOR_avx512f_cmpv16sf3_mask_round:
13889 : 8 : case CODE_FOR_avx512f_vmcmpv2df3_mask_round:
13890 : 8 : case CODE_FOR_avx512f_vmcmpv4sf3_mask_round:
13891 : 8 : case CODE_FOR_avx512f_vmcmpv8hf3_mask_round:
13892 : 8 : case CODE_FOR_avx512bw_cmpv32hf3_mask_round:
13893 : 8 : error ("the immediate argument must be a 5-bit immediate");
13894 : 8 : return const0_rtx;
13895 : 20 : default:
13896 : 20 : error ("the immediate argument must be an 8-bit immediate");
13897 : 20 : return const0_rtx;
13898 : : }
13899 : : }
13900 : : }
13901 : 68014 : else if (i == nargs-1)
13902 : : {
13903 : 15689 : if (!insn_p->operand[nargs].predicate (op, SImode))
13904 : : {
13905 : 515 : error ("incorrect rounding operand");
13906 : 515 : return const0_rtx;
13907 : : }
13908 : :
13909 : : /* If there is no rounding use normal version of the pattern. */
13910 : 15174 : if (INTVAL (op) == NO_ROUND)
13911 : : {
13912 : : /* Skip erasing embedded rounding for below expanders who
13913 : : generates multiple insns. In ix86_erase_embedded_rounding
13914 : : the pattern will be transformed to a single set, and emit_insn
13915 : : appends the set instead of insert it to chain. So the insns
13916 : : emitted inside define_expander would be ignored. */
13917 : 5056 : switch (icode)
13918 : : {
13919 : : case CODE_FOR_avx512bw_fmaddc_v32hf_mask1_round:
13920 : : case CODE_FOR_avx512bw_fcmaddc_v32hf_mask1_round:
13921 : : case CODE_FOR_avx512fp16_fmaddcsh_v8hf_mask1_round:
13922 : : case CODE_FOR_avx512fp16_fcmaddcsh_v8hf_mask1_round:
13923 : : case CODE_FOR_avx512fp16_fmaddcsh_v8hf_mask3_round:
13924 : : case CODE_FOR_avx512fp16_fcmaddcsh_v8hf_mask3_round:
13925 : : redundant_embed_rnd = 0;
13926 : : break;
13927 : 5024 : default:
13928 : 5024 : redundant_embed_rnd = 1;
13929 : 5024 : break;
13930 : : }
13931 : : }
13932 : : }
13933 : : else
13934 : : {
13935 : 52325 : if (VECTOR_MODE_P (mode))
13936 : 38327 : op = safe_vector_operand (op, mode);
13937 : :
13938 : 52325 : op = fixup_modeless_constant (op, mode);
13939 : :
13940 : 52325 : if (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)
13941 : : {
13942 : 52325 : if (optimize || !match)
13943 : 45997 : op = copy_to_mode_reg (mode, op);
13944 : : }
13945 : : else
13946 : : {
13947 : 0 : op = copy_to_reg (op);
13948 : 0 : op = lowpart_subreg (mode, op, GET_MODE (op));
13949 : : }
13950 : : }
13951 : :
13952 : 70863 : xops[i] = op;
13953 : : }
13954 : :
13955 : 15174 : switch (nargs)
13956 : : {
13957 : : case 1:
13958 : : pat = GEN_FCN (icode) (target, xops[0]);
13959 : : break;
13960 : 688 : case 2:
13961 : 688 : pat = GEN_FCN (icode) (target, xops[0], xops[1]);
13962 : 688 : break;
13963 : 692 : case 3:
13964 : 692 : pat = GEN_FCN (icode) (target, xops[0], xops[1], xops[2]);
13965 : 692 : break;
13966 : 4695 : case 4:
13967 : 4695 : pat = GEN_FCN (icode) (target, xops[0], xops[1],
13968 : 4695 : xops[2], xops[3]);
13969 : 4695 : break;
13970 : 7826 : case 5:
13971 : 7826 : pat = GEN_FCN (icode) (target, xops[0], xops[1],
13972 : 7826 : xops[2], xops[3], xops[4]);
13973 : 7826 : break;
13974 : 1273 : case 6:
13975 : 1273 : pat = GEN_FCN (icode) (target, xops[0], xops[1],
13976 : 1273 : xops[2], xops[3], xops[4], xops[5]);
13977 : 1273 : break;
13978 : : default:
13979 : : gcc_unreachable ();
13980 : : }
13981 : :
13982 : 15174 : if (!pat)
13983 : : return 0;
13984 : :
13985 : 15174 : if (redundant_embed_rnd)
13986 : 5024 : pat = ix86_erase_embedded_rounding (pat);
13987 : :
13988 : 15174 : emit_insn (pat);
13989 : 15174 : return target;
13990 : : }
13991 : :
13992 : : /* Subroutine of ix86_expand_builtin to take care of special insns
13993 : : with variable number of operands. */
13994 : :
13995 : : static rtx
13996 : 27397 : ix86_expand_special_args_builtin (const struct builtin_description *d,
13997 : : tree exp, rtx target)
13998 : : {
13999 : 27397 : tree arg;
14000 : 27397 : rtx pat, op;
14001 : 27397 : unsigned int i, nargs, arg_adjust, memory;
14002 : 27397 : unsigned int constant = 100;
14003 : 27397 : bool aligned_mem = false;
14004 : 27397 : rtx xops[4];
14005 : 27397 : enum insn_code icode = d->icode;
14006 : 27397 : const struct insn_data_d *insn_p = &insn_data[icode];
14007 : 27397 : machine_mode tmode = insn_p->operand[0].mode;
14008 : 27397 : enum { load, store } klass;
14009 : :
14010 : 27397 : switch ((enum ix86_builtin_func_type) d->flag)
14011 : : {
14012 : 15588 : case VOID_FTYPE_VOID:
14013 : 15588 : emit_insn (GEN_FCN (icode) (target));
14014 : 15588 : return 0;
14015 : : case VOID_FTYPE_UINT64:
14016 : : case VOID_FTYPE_UNSIGNED:
14017 : : nargs = 0;
14018 : : klass = store;
14019 : : memory = 0;
14020 : : break;
14021 : :
14022 : 7581 : case INT_FTYPE_VOID:
14023 : 7581 : case USHORT_FTYPE_VOID:
14024 : 7581 : case UINT64_FTYPE_VOID:
14025 : 7581 : case UINT_FTYPE_VOID:
14026 : 7581 : case UINT8_FTYPE_VOID:
14027 : 7581 : case UNSIGNED_FTYPE_VOID:
14028 : 7581 : nargs = 0;
14029 : 7581 : klass = load;
14030 : 7581 : memory = 0;
14031 : 7581 : break;
14032 : 358 : case CHAR_FTYPE_PCCHAR:
14033 : 358 : case SHORT_FTYPE_PCSHORT:
14034 : 358 : case INT_FTYPE_PCINT:
14035 : 358 : case INT64_FTYPE_PCINT64:
14036 : 358 : case UINT64_FTYPE_PUNSIGNED:
14037 : 358 : case V2DI_FTYPE_PV2DI:
14038 : 358 : case V4DI_FTYPE_PV4DI:
14039 : 358 : case V32QI_FTYPE_PCCHAR:
14040 : 358 : case V16QI_FTYPE_PCCHAR:
14041 : 358 : case V8SF_FTYPE_PCV4SF:
14042 : 358 : case V8SF_FTYPE_PCFLOAT:
14043 : 358 : case V4SF_FTYPE_PCFLOAT:
14044 : 358 : case V4SF_FTYPE_PCFLOAT16:
14045 : 358 : case V4SF_FTYPE_PCBFLOAT16:
14046 : 358 : case V4SF_FTYPE_PCV8BF:
14047 : 358 : case V4SF_FTYPE_PCV8HF:
14048 : 358 : case V8SF_FTYPE_PCFLOAT16:
14049 : 358 : case V8SF_FTYPE_PCBFLOAT16:
14050 : 358 : case V8SF_FTYPE_PCV16HF:
14051 : 358 : case V8SF_FTYPE_PCV16BF:
14052 : 358 : case V4DF_FTYPE_PCV2DF:
14053 : 358 : case V4DF_FTYPE_PCDOUBLE:
14054 : 358 : case V2DF_FTYPE_PCDOUBLE:
14055 : 358 : case VOID_FTYPE_PVOID:
14056 : 358 : case V8DI_FTYPE_PV8DI:
14057 : 358 : nargs = 1;
14058 : 358 : klass = load;
14059 : 358 : memory = 0;
14060 : 358 : switch (icode)
14061 : : {
14062 : : case CODE_FOR_sse4_1_movntdqa:
14063 : : case CODE_FOR_avx2_movntdqa:
14064 : : case CODE_FOR_avx512f_movntdqa:
14065 : : aligned_mem = true;
14066 : : break;
14067 : : default:
14068 : : break;
14069 : : }
14070 : : break;
14071 : 373 : case VOID_FTYPE_PV2SF_V4SF:
14072 : 373 : case VOID_FTYPE_PV8DI_V8DI:
14073 : 373 : case VOID_FTYPE_PV4DI_V4DI:
14074 : 373 : case VOID_FTYPE_PV2DI_V2DI:
14075 : 373 : case VOID_FTYPE_PCHAR_V32QI:
14076 : 373 : case VOID_FTYPE_PCHAR_V16QI:
14077 : 373 : case VOID_FTYPE_PFLOAT_V16SF:
14078 : 373 : case VOID_FTYPE_PFLOAT_V8SF:
14079 : 373 : case VOID_FTYPE_PFLOAT_V4SF:
14080 : 373 : case VOID_FTYPE_PDOUBLE_V8DF:
14081 : 373 : case VOID_FTYPE_PDOUBLE_V4DF:
14082 : 373 : case VOID_FTYPE_PDOUBLE_V2DF:
14083 : 373 : case VOID_FTYPE_PLONGLONG_LONGLONG:
14084 : 373 : case VOID_FTYPE_PULONGLONG_ULONGLONG:
14085 : 373 : case VOID_FTYPE_PUNSIGNED_UNSIGNED:
14086 : 373 : case VOID_FTYPE_PINT_INT:
14087 : 373 : nargs = 1;
14088 : 373 : klass = store;
14089 : : /* Reserve memory operand for target. */
14090 : 373 : memory = ARRAY_SIZE (xops);
14091 : 373 : switch (icode)
14092 : : {
14093 : : /* These builtins and instructions require the memory
14094 : : to be properly aligned. */
14095 : : case CODE_FOR_avx_movntv4di:
14096 : : case CODE_FOR_sse2_movntv2di:
14097 : : case CODE_FOR_avx_movntv8sf:
14098 : : case CODE_FOR_sse_movntv4sf:
14099 : : case CODE_FOR_sse4a_vmmovntv4sf:
14100 : : case CODE_FOR_avx_movntv4df:
14101 : : case CODE_FOR_sse2_movntv2df:
14102 : : case CODE_FOR_sse4a_vmmovntv2df:
14103 : : case CODE_FOR_sse2_movntidi:
14104 : : case CODE_FOR_sse_movntq:
14105 : : case CODE_FOR_sse2_movntisi:
14106 : : case CODE_FOR_avx512f_movntv16sf:
14107 : : case CODE_FOR_avx512f_movntv8df:
14108 : : case CODE_FOR_avx512f_movntv8di:
14109 : : aligned_mem = true;
14110 : : break;
14111 : : default:
14112 : : break;
14113 : : }
14114 : : break;
14115 : 0 : case VOID_FTYPE_PVOID_PCVOID:
14116 : 0 : nargs = 1;
14117 : 0 : klass = store;
14118 : 0 : memory = 0;
14119 : :
14120 : 0 : break;
14121 : 26 : case V4SF_FTYPE_V4SF_PCV2SF:
14122 : 26 : case V2DF_FTYPE_V2DF_PCDOUBLE:
14123 : 26 : nargs = 2;
14124 : 26 : klass = load;
14125 : 26 : memory = 1;
14126 : 26 : break;
14127 : 93 : case V8SF_FTYPE_PCV8SF_V8SI:
14128 : 93 : case V4DF_FTYPE_PCV4DF_V4DI:
14129 : 93 : case V4SF_FTYPE_PCV4SF_V4SI:
14130 : 93 : case V2DF_FTYPE_PCV2DF_V2DI:
14131 : 93 : case V8SI_FTYPE_PCV8SI_V8SI:
14132 : 93 : case V4DI_FTYPE_PCV4DI_V4DI:
14133 : 93 : case V4SI_FTYPE_PCV4SI_V4SI:
14134 : 93 : case V2DI_FTYPE_PCV2DI_V2DI:
14135 : 93 : case VOID_FTYPE_INT_INT64:
14136 : 93 : nargs = 2;
14137 : 93 : klass = load;
14138 : 93 : memory = 0;
14139 : 93 : break;
14140 : 360 : case VOID_FTYPE_PV8DF_V8DF_UQI:
14141 : 360 : case VOID_FTYPE_PV4DF_V4DF_UQI:
14142 : 360 : case VOID_FTYPE_PV2DF_V2DF_UQI:
14143 : 360 : case VOID_FTYPE_PV16SF_V16SF_UHI:
14144 : 360 : case VOID_FTYPE_PV8SF_V8SF_UQI:
14145 : 360 : case VOID_FTYPE_PV4SF_V4SF_UQI:
14146 : 360 : case VOID_FTYPE_PV8DI_V8DI_UQI:
14147 : 360 : case VOID_FTYPE_PV4DI_V4DI_UQI:
14148 : 360 : case VOID_FTYPE_PV2DI_V2DI_UQI:
14149 : 360 : case VOID_FTYPE_PV16SI_V16SI_UHI:
14150 : 360 : case VOID_FTYPE_PV8SI_V8SI_UQI:
14151 : 360 : case VOID_FTYPE_PV4SI_V4SI_UQI:
14152 : 360 : case VOID_FTYPE_PV64QI_V64QI_UDI:
14153 : 360 : case VOID_FTYPE_PV32HI_V32HI_USI:
14154 : 360 : case VOID_FTYPE_PV32QI_V32QI_USI:
14155 : 360 : case VOID_FTYPE_PV16QI_V16QI_UHI:
14156 : 360 : case VOID_FTYPE_PV16HI_V16HI_UHI:
14157 : 360 : case VOID_FTYPE_PV8HI_V8HI_UQI:
14158 : 360 : switch (icode)
14159 : : {
14160 : : /* These builtins and instructions require the memory
14161 : : to be properly aligned. */
14162 : : case CODE_FOR_avx512f_storev16sf_mask:
14163 : : case CODE_FOR_avx512f_storev16si_mask:
14164 : : case CODE_FOR_avx512f_storev8df_mask:
14165 : : case CODE_FOR_avx512f_storev8di_mask:
14166 : : case CODE_FOR_avx512vl_storev8sf_mask:
14167 : : case CODE_FOR_avx512vl_storev8si_mask:
14168 : : case CODE_FOR_avx512vl_storev4df_mask:
14169 : : case CODE_FOR_avx512vl_storev4di_mask:
14170 : : case CODE_FOR_avx512vl_storev4sf_mask:
14171 : : case CODE_FOR_avx512vl_storev4si_mask:
14172 : : case CODE_FOR_avx512vl_storev2df_mask:
14173 : : case CODE_FOR_avx512vl_storev2di_mask:
14174 : 11809 : aligned_mem = true;
14175 : : break;
14176 : : default:
14177 : : break;
14178 : : }
14179 : : /* FALLTHRU */
14180 : : case VOID_FTYPE_PV8SF_V8SI_V8SF:
14181 : : case VOID_FTYPE_PV4DF_V4DI_V4DF:
14182 : : case VOID_FTYPE_PV4SF_V4SI_V4SF:
14183 : : case VOID_FTYPE_PV2DF_V2DI_V2DF:
14184 : : case VOID_FTYPE_PV8SI_V8SI_V8SI:
14185 : : case VOID_FTYPE_PV4DI_V4DI_V4DI:
14186 : : case VOID_FTYPE_PV4SI_V4SI_V4SI:
14187 : : case VOID_FTYPE_PV2DI_V2DI_V2DI:
14188 : : case VOID_FTYPE_PV8SI_V8DI_UQI:
14189 : : case VOID_FTYPE_PV8HI_V8DI_UQI:
14190 : : case VOID_FTYPE_PV16HI_V16SI_UHI:
14191 : : case VOID_FTYPE_PUDI_V8DI_UQI:
14192 : : case VOID_FTYPE_PV16QI_V16SI_UHI:
14193 : : case VOID_FTYPE_PV4SI_V4DI_UQI:
14194 : : case VOID_FTYPE_PUDI_V2DI_UQI:
14195 : : case VOID_FTYPE_PUDI_V4DI_UQI:
14196 : : case VOID_FTYPE_PUSI_V2DI_UQI:
14197 : : case VOID_FTYPE_PV8HI_V8SI_UQI:
14198 : : case VOID_FTYPE_PUDI_V4SI_UQI:
14199 : : case VOID_FTYPE_PUSI_V4DI_UQI:
14200 : : case VOID_FTYPE_PUHI_V2DI_UQI:
14201 : : case VOID_FTYPE_PUDI_V8SI_UQI:
14202 : : case VOID_FTYPE_PUSI_V4SI_UQI:
14203 : : case VOID_FTYPE_PCHAR_V64QI_UDI:
14204 : : case VOID_FTYPE_PCHAR_V32QI_USI:
14205 : : case VOID_FTYPE_PCHAR_V16QI_UHI:
14206 : : case VOID_FTYPE_PSHORT_V32HI_USI:
14207 : : case VOID_FTYPE_PSHORT_V16HI_UHI:
14208 : : case VOID_FTYPE_PSHORT_V8HI_UQI:
14209 : : case VOID_FTYPE_PINT_V16SI_UHI:
14210 : : case VOID_FTYPE_PINT_V8SI_UQI:
14211 : : case VOID_FTYPE_PINT_V4SI_UQI:
14212 : : case VOID_FTYPE_PINT64_V8DI_UQI:
14213 : : case VOID_FTYPE_PINT64_V4DI_UQI:
14214 : : case VOID_FTYPE_PINT64_V2DI_UQI:
14215 : : case VOID_FTYPE_PDOUBLE_V8DF_UQI:
14216 : : case VOID_FTYPE_PDOUBLE_V4DF_UQI:
14217 : : case VOID_FTYPE_PDOUBLE_V2DF_UQI:
14218 : : case VOID_FTYPE_PFLOAT_V16SF_UHI:
14219 : : case VOID_FTYPE_PFLOAT_V8SF_UQI:
14220 : : case VOID_FTYPE_PFLOAT_V4SF_UQI:
14221 : : case VOID_FTYPE_PCFLOAT16_V8HF_UQI:
14222 : : case VOID_FTYPE_PV32QI_V32HI_USI:
14223 : : case VOID_FTYPE_PV16QI_V16HI_UHI:
14224 : : case VOID_FTYPE_PUDI_V8HI_UQI:
14225 : : nargs = 2;
14226 : : klass = store;
14227 : : /* Reserve memory operand for target. */
14228 : : memory = ARRAY_SIZE (xops);
14229 : : break;
14230 : 1243 : case V4SF_FTYPE_PCV4SF_V4SF_UQI:
14231 : 1243 : case V8SF_FTYPE_PCV8SF_V8SF_UQI:
14232 : 1243 : case V16SF_FTYPE_PCV16SF_V16SF_UHI:
14233 : 1243 : case V4SI_FTYPE_PCV4SI_V4SI_UQI:
14234 : 1243 : case V8SI_FTYPE_PCV8SI_V8SI_UQI:
14235 : 1243 : case V16SI_FTYPE_PCV16SI_V16SI_UHI:
14236 : 1243 : case V2DF_FTYPE_PCV2DF_V2DF_UQI:
14237 : 1243 : case V4DF_FTYPE_PCV4DF_V4DF_UQI:
14238 : 1243 : case V8DF_FTYPE_PCV8DF_V8DF_UQI:
14239 : 1243 : case V2DI_FTYPE_PCV2DI_V2DI_UQI:
14240 : 1243 : case V4DI_FTYPE_PCV4DI_V4DI_UQI:
14241 : 1243 : case V8DI_FTYPE_PCV8DI_V8DI_UQI:
14242 : 1243 : case V64QI_FTYPE_PCV64QI_V64QI_UDI:
14243 : 1243 : case V32HI_FTYPE_PCV32HI_V32HI_USI:
14244 : 1243 : case V32QI_FTYPE_PCV32QI_V32QI_USI:
14245 : 1243 : case V16QI_FTYPE_PCV16QI_V16QI_UHI:
14246 : 1243 : case V16HI_FTYPE_PCV16HI_V16HI_UHI:
14247 : 1243 : case V8HI_FTYPE_PCV8HI_V8HI_UQI:
14248 : 1243 : switch (icode)
14249 : : {
14250 : : /* These builtins and instructions require the memory
14251 : : to be properly aligned. */
14252 : : case CODE_FOR_avx512f_loadv16sf_mask:
14253 : : case CODE_FOR_avx512f_loadv16si_mask:
14254 : : case CODE_FOR_avx512f_loadv8df_mask:
14255 : : case CODE_FOR_avx512f_loadv8di_mask:
14256 : : case CODE_FOR_avx512vl_loadv8sf_mask:
14257 : : case CODE_FOR_avx512vl_loadv8si_mask:
14258 : : case CODE_FOR_avx512vl_loadv4df_mask:
14259 : : case CODE_FOR_avx512vl_loadv4di_mask:
14260 : : case CODE_FOR_avx512vl_loadv4sf_mask:
14261 : : case CODE_FOR_avx512vl_loadv4si_mask:
14262 : : case CODE_FOR_avx512vl_loadv2df_mask:
14263 : : case CODE_FOR_avx512vl_loadv2di_mask:
14264 : : case CODE_FOR_avx512bw_loadv64qi_mask:
14265 : : case CODE_FOR_avx512vl_loadv32qi_mask:
14266 : : case CODE_FOR_avx512vl_loadv16qi_mask:
14267 : : case CODE_FOR_avx512bw_loadv32hi_mask:
14268 : : case CODE_FOR_avx512vl_loadv16hi_mask:
14269 : : case CODE_FOR_avx512vl_loadv8hi_mask:
14270 : 11809 : aligned_mem = true;
14271 : : break;
14272 : : default:
14273 : : break;
14274 : : }
14275 : : /* FALLTHRU */
14276 : : case V64QI_FTYPE_PCCHAR_V64QI_UDI:
14277 : : case V32QI_FTYPE_PCCHAR_V32QI_USI:
14278 : : case V16QI_FTYPE_PCCHAR_V16QI_UHI:
14279 : : case V32HI_FTYPE_PCSHORT_V32HI_USI:
14280 : : case V16HI_FTYPE_PCSHORT_V16HI_UHI:
14281 : : case V8HI_FTYPE_PCSHORT_V8HI_UQI:
14282 : : case V16SI_FTYPE_PCINT_V16SI_UHI:
14283 : : case V8SI_FTYPE_PCINT_V8SI_UQI:
14284 : : case V4SI_FTYPE_PCINT_V4SI_UQI:
14285 : : case V8DI_FTYPE_PCINT64_V8DI_UQI:
14286 : : case V4DI_FTYPE_PCINT64_V4DI_UQI:
14287 : : case V2DI_FTYPE_PCINT64_V2DI_UQI:
14288 : : case V8DF_FTYPE_PCDOUBLE_V8DF_UQI:
14289 : : case V4DF_FTYPE_PCDOUBLE_V4DF_UQI:
14290 : : case V2DF_FTYPE_PCDOUBLE_V2DF_UQI:
14291 : : case V16SF_FTYPE_PCFLOAT_V16SF_UHI:
14292 : : case V8SF_FTYPE_PCFLOAT_V8SF_UQI:
14293 : : case V4SF_FTYPE_PCFLOAT_V4SF_UQI:
14294 : : case V8HF_FTYPE_PCFLOAT16_V8HF_UQI:
14295 : : nargs = 3;
14296 : : klass = load;
14297 : : memory = 0;
14298 : : break;
14299 : 105 : case INT_FTYPE_PINT_INT_INT_INT:
14300 : 105 : case LONGLONG_FTYPE_PLONGLONG_LONGLONG_LONGLONG_INT:
14301 : 105 : nargs = 4;
14302 : 105 : klass = load;
14303 : 105 : memory = 0;
14304 : 105 : constant = 3;
14305 : 105 : break;
14306 : 0 : default:
14307 : 0 : gcc_unreachable ();
14308 : : }
14309 : :
14310 : 8340 : gcc_assert (nargs <= ARRAY_SIZE (xops));
14311 : :
14312 : 11809 : if (klass == store)
14313 : : {
14314 : 1876 : arg = CALL_EXPR_ARG (exp, 0);
14315 : 1876 : op = expand_normal (arg);
14316 : 1876 : gcc_assert (target == 0);
14317 : 1876 : if (memory)
14318 : : {
14319 : 1717 : op = ix86_zero_extend_to_Pmode (op);
14320 : 1717 : target = gen_rtx_MEM (tmode, op);
14321 : : /* target at this point has just BITS_PER_UNIT MEM_ALIGN
14322 : : on it. Try to improve it using get_pointer_alignment,
14323 : : and if the special builtin is one that requires strict
14324 : : mode alignment, also from it's GET_MODE_ALIGNMENT.
14325 : : Failure to do so could lead to ix86_legitimate_combined_insn
14326 : : rejecting all changes to such insns. */
14327 : 1717 : unsigned int align = get_pointer_alignment (arg);
14328 : 1717 : if (aligned_mem && align < GET_MODE_ALIGNMENT (tmode))
14329 : 275 : align = GET_MODE_ALIGNMENT (tmode);
14330 : 3434 : if (MEM_ALIGN (target) < align)
14331 : 422 : set_mem_align (target, align);
14332 : : }
14333 : : else
14334 : 159 : target = force_reg (tmode, op);
14335 : : arg_adjust = 1;
14336 : : }
14337 : : else
14338 : : {
14339 : 9933 : arg_adjust = 0;
14340 : 9933 : if (optimize
14341 : 2918 : || target == 0
14342 : 2918 : || !register_operand (target, tmode)
14343 : 12840 : || GET_MODE (target) != tmode)
14344 : 7026 : target = gen_reg_rtx (tmode);
14345 : : }
14346 : :
14347 : 21196 : for (i = 0; i < nargs; i++)
14348 : : {
14349 : 9387 : machine_mode mode = insn_p->operand[i + 1].mode;
14350 : :
14351 : 9387 : arg = CALL_EXPR_ARG (exp, i + arg_adjust);
14352 : 9387 : op = ix86_expand_unsigned_small_int_cst_argument (arg);
14353 : :
14354 : 9387 : if (i == memory)
14355 : : {
14356 : : /* This must be the memory operand. */
14357 : 2352 : op = ix86_zero_extend_to_Pmode (op);
14358 : 2352 : op = gen_rtx_MEM (mode, op);
14359 : : /* op at this point has just BITS_PER_UNIT MEM_ALIGN
14360 : : on it. Try to improve it using get_pointer_alignment,
14361 : : and if the special builtin is one that requires strict
14362 : : mode alignment, also from it's GET_MODE_ALIGNMENT.
14363 : : Failure to do so could lead to ix86_legitimate_combined_insn
14364 : : rejecting all changes to such insns. */
14365 : 2352 : unsigned int align = get_pointer_alignment (arg);
14366 : 2352 : if (aligned_mem && align < GET_MODE_ALIGNMENT (mode))
14367 : 299 : align = GET_MODE_ALIGNMENT (mode);
14368 : 4704 : if (MEM_ALIGN (op) < align)
14369 : 523 : set_mem_align (op, align);
14370 : : }
14371 : 7035 : else if (i == constant)
14372 : : {
14373 : : /* This must be the constant. */
14374 : 105 : if (!insn_p->operand[nargs].predicate(op, SImode))
14375 : : {
14376 : 0 : error ("the fourth argument must be one of enum %qs", "_CMPCCX_ENUM");
14377 : 0 : return const0_rtx;
14378 : : }
14379 : : }
14380 : : else
14381 : : {
14382 : : /* This must be register. */
14383 : 6930 : if (VECTOR_MODE_P (mode))
14384 : 3474 : op = safe_vector_operand (op, mode);
14385 : :
14386 : 6930 : op = fixup_modeless_constant (op, mode);
14387 : :
14388 : : /* NB: 3-operands load implied it's a mask load or v{p}expand*,
14389 : : and that mask operand shoud be at the end.
14390 : : Keep all-ones mask which would be simplified by the expander. */
14391 : 1770 : if (nargs == 3 && i == 2 && klass == load
14392 : 1770 : && constm1_operand (op, mode)
14393 : 7103 : && insn_p->operand[i].predicate (op, mode))
14394 : : ;
14395 : 6930 : else if (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)
14396 : 6930 : op = copy_to_mode_reg (mode, op);
14397 : : else
14398 : : {
14399 : 0 : op = copy_to_reg (op);
14400 : 0 : op = lowpart_subreg (mode, op, GET_MODE (op));
14401 : : }
14402 : : }
14403 : :
14404 : 9387 : xops[i]= op;
14405 : : }
14406 : :
14407 : 11809 : switch (nargs)
14408 : : {
14409 : 7740 : case 0:
14410 : 7740 : pat = GEN_FCN (icode) (target);
14411 : 7740 : break;
14412 : 731 : case 1:
14413 : 731 : pat = GEN_FCN (icode) (target, xops[0]);
14414 : 731 : break;
14415 : 1463 : case 2:
14416 : 1463 : pat = GEN_FCN (icode) (target, xops[0], xops[1]);
14417 : 1463 : break;
14418 : 1770 : case 3:
14419 : 1770 : pat = GEN_FCN (icode) (target, xops[0], xops[1], xops[2]);
14420 : 1770 : break;
14421 : 105 : case 4:
14422 : 105 : pat = GEN_FCN (icode) (target, xops[0], xops[1], xops[2], xops[3]);
14423 : 105 : break;
14424 : : default:
14425 : : gcc_unreachable ();
14426 : : }
14427 : :
14428 : 11809 : if (! pat)
14429 : : return 0;
14430 : :
14431 : 11809 : emit_insn (pat);
14432 : 11809 : return klass == store ? 0 : target;
14433 : : }
14434 : :
14435 : : /* Return the integer constant in ARG. Constrain it to be in the range
14436 : : of the subparts of VEC_TYPE; issue an error if not. */
14437 : :
14438 : : static int
14439 : 595 : get_element_number (tree vec_type, tree arg)
14440 : : {
14441 : 595 : unsigned HOST_WIDE_INT elt, max = TYPE_VECTOR_SUBPARTS (vec_type) - 1;
14442 : :
14443 : 595 : if (!tree_fits_uhwi_p (arg)
14444 : 595 : || (elt = tree_to_uhwi (arg), elt > max))
14445 : : {
14446 : 0 : error ("selector must be an integer constant in the range "
14447 : : "[0, %wi]", max);
14448 : 0 : return 0;
14449 : : }
14450 : :
14451 : 595 : return elt;
14452 : : }
14453 : :
14454 : : /* A subroutine of ix86_expand_builtin. These builtins are a wrapper around
14455 : : ix86_expand_vector_init. We DO have language-level syntax for this, in
14456 : : the form of (type){ init-list }. Except that since we can't place emms
14457 : : instructions from inside the compiler, we can't allow the use of MMX
14458 : : registers unless the user explicitly asks for it. So we do *not* define
14459 : : vec_set/vec_extract/vec_init patterns for MMX modes in mmx.md. Instead
14460 : : we have builtins invoked by mmintrin.h that gives us license to emit
14461 : : these sorts of instructions. */
14462 : :
14463 : : static rtx
14464 : 229 : ix86_expand_vec_init_builtin (tree type, tree exp, rtx target)
14465 : : {
14466 : 229 : machine_mode tmode = TYPE_MODE (type);
14467 : 229 : machine_mode inner_mode = GET_MODE_INNER (tmode);
14468 : 229 : int i, n_elt = GET_MODE_NUNITS (tmode);
14469 : 229 : rtvec v = rtvec_alloc (n_elt);
14470 : :
14471 : 229 : gcc_assert (VECTOR_MODE_P (tmode));
14472 : 229 : gcc_assert (call_expr_nargs (exp) == n_elt);
14473 : :
14474 : 1203 : for (i = 0; i < n_elt; ++i)
14475 : : {
14476 : 974 : rtx x = expand_normal (CALL_EXPR_ARG (exp, i));
14477 : 974 : RTVEC_ELT (v, i) = gen_lowpart (inner_mode, x);
14478 : : }
14479 : :
14480 : 229 : if (!target || !register_operand (target, tmode))
14481 : 0 : target = gen_reg_rtx (tmode);
14482 : :
14483 : 229 : ix86_expand_vector_init (true, target, gen_rtx_PARALLEL (tmode, v));
14484 : 229 : return target;
14485 : : }
14486 : :
14487 : : /* A subroutine of ix86_expand_builtin. These builtins are a wrapper around
14488 : : ix86_expand_vector_extract. They would be redundant (for non-MMX) if we
14489 : : had a language-level syntax for referencing vector elements. */
14490 : :
14491 : : static rtx
14492 : 391 : ix86_expand_vec_ext_builtin (tree exp, rtx target)
14493 : : {
14494 : 391 : machine_mode tmode, mode0;
14495 : 391 : tree arg0, arg1;
14496 : 391 : int elt;
14497 : 391 : rtx op0;
14498 : :
14499 : 391 : arg0 = CALL_EXPR_ARG (exp, 0);
14500 : 391 : arg1 = CALL_EXPR_ARG (exp, 1);
14501 : :
14502 : 391 : op0 = expand_normal (arg0);
14503 : 391 : elt = get_element_number (TREE_TYPE (arg0), arg1);
14504 : :
14505 : 391 : tmode = TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0)));
14506 : 391 : mode0 = TYPE_MODE (TREE_TYPE (arg0));
14507 : 391 : gcc_assert (VECTOR_MODE_P (mode0));
14508 : :
14509 : 391 : op0 = force_reg (mode0, op0);
14510 : :
14511 : 391 : if (optimize || !target || !register_operand (target, tmode))
14512 : 312 : target = gen_reg_rtx (tmode);
14513 : :
14514 : 391 : ix86_expand_vector_extract (true, target, op0, elt);
14515 : :
14516 : 391 : return target;
14517 : : }
14518 : :
14519 : : /* A subroutine of ix86_expand_builtin. These builtins are a wrapper around
14520 : : ix86_expand_vector_set. They would be redundant (for non-MMX) if we had
14521 : : a language-level syntax for referencing vector elements. */
14522 : :
14523 : : static rtx
14524 : 204 : ix86_expand_vec_set_builtin (tree exp)
14525 : : {
14526 : 204 : machine_mode tmode, mode1;
14527 : 204 : tree arg0, arg1, arg2;
14528 : 204 : int elt;
14529 : 204 : rtx op0, op1, target;
14530 : :
14531 : 204 : arg0 = CALL_EXPR_ARG (exp, 0);
14532 : 204 : arg1 = CALL_EXPR_ARG (exp, 1);
14533 : 204 : arg2 = CALL_EXPR_ARG (exp, 2);
14534 : :
14535 : 204 : tmode = TYPE_MODE (TREE_TYPE (arg0));
14536 : 204 : mode1 = TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0)));
14537 : 204 : gcc_assert (VECTOR_MODE_P (tmode));
14538 : :
14539 : 204 : op0 = expand_expr (arg0, NULL_RTX, tmode, EXPAND_NORMAL);
14540 : 204 : op1 = expand_expr (arg1, NULL_RTX, mode1, EXPAND_NORMAL);
14541 : 204 : elt = get_element_number (TREE_TYPE (arg0), arg2);
14542 : :
14543 : 204 : if (GET_MODE (op1) != mode1)
14544 : 82 : op1 = convert_modes (mode1, GET_MODE (op1), op1, true);
14545 : :
14546 : 204 : op0 = force_reg (tmode, op0);
14547 : 204 : op1 = force_reg (mode1, op1);
14548 : :
14549 : : /* OP0 is the source of these builtin functions and shouldn't be
14550 : : modified. Create a copy, use it and return it as target. */
14551 : 204 : target = gen_reg_rtx (tmode);
14552 : 204 : emit_move_insn (target, op0);
14553 : 204 : ix86_expand_vector_set (true, target, op1, elt);
14554 : :
14555 : 204 : return target;
14556 : : }
14557 : :
14558 : : /* Return true if the necessary isa options for this builtin exist,
14559 : : else false.
14560 : : fcode = DECL_MD_FUNCTION_CODE (fndecl); */
14561 : : bool
14562 : 1271589 : ix86_check_builtin_isa_match (unsigned int fcode,
14563 : : HOST_WIDE_INT* pbisa,
14564 : : HOST_WIDE_INT* pbisa2)
14565 : : {
14566 : 1271589 : HOST_WIDE_INT isa = ix86_isa_flags;
14567 : 1271589 : HOST_WIDE_INT isa2 = ix86_isa_flags2;
14568 : 1271589 : HOST_WIDE_INT bisa = ix86_builtins_isa[fcode].isa;
14569 : 1271589 : HOST_WIDE_INT bisa2 = ix86_builtins_isa[fcode].isa2;
14570 : 1271589 : HOST_WIDE_INT tmp_isa = isa, tmp_isa2 = isa2;
14571 : : /* The general case is we require all the ISAs specified in bisa{,2}
14572 : : to be enabled.
14573 : : The exceptions are:
14574 : : OPTION_MASK_ISA_SSE | OPTION_MASK_ISA_3DNOW_A
14575 : : OPTION_MASK_ISA_SSE4_2 | OPTION_MASK_ISA_CRC32
14576 : : OPTION_MASK_ISA_FMA | OPTION_MASK_ISA_FMA4
14577 : : (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL) or
14578 : : OPTION_MASK_ISA2_AVXVNNI
14579 : : (OPTION_MASK_ISA_AVX512IFMA | OPTION_MASK_ISA_AVX512VL) or
14580 : : OPTION_MASK_ISA2_AVXIFMA
14581 : : (OPTION_MASK_ISA_AVX512VL | OPTION_MASK_ISA2_AVX512BF16) or
14582 : : OPTION_MASK_ISA2_AVXNECONVERT
14583 : : OPTION_MASK_ISA_AES or (OPTION_MASK_ISA_AVX512VL | OPTION_MASK_ISA2_VAES)
14584 : : OPTION_MASK_ISA2_AVX10_2 or OPTION_MASK_ISA2_AVXVNNIINT8
14585 : : OPTION_MASK_ISA2_AVX10_2 or OPTION_MASK_ISA2_AVXVNNIINT16
14586 : : where for each such pair it is sufficient if either of the ISAs is
14587 : : enabled, plus if it is ored with other options also those others.
14588 : : OPTION_MASK_ISA_MMX in bisa is satisfied also if TARGET_MMX_WITH_SSE. */
14589 : :
14590 : : #define SHARE_BUILTIN(A1, A2, B1, B2) \
14591 : : if ((((bisa & (A1)) == (A1) && (bisa2 & (A2)) == (A2)) \
14592 : : && ((bisa & (B1)) == (B1) && (bisa2 & (B2)) == (B2))) \
14593 : : && (((isa & (A1)) == (A1) && (isa2 & (A2)) == (A2)) \
14594 : : || ((isa & (B1)) == (B1) && (isa2 & (B2)) == (B2)))) \
14595 : : { \
14596 : : tmp_isa |= (A1) | (B1); \
14597 : : tmp_isa2 |= (A2) | (B2); \
14598 : : }
14599 : :
14600 : 1271589 : SHARE_BUILTIN (OPTION_MASK_ISA_SSE, 0, OPTION_MASK_ISA_3DNOW_A, 0);
14601 : 1271589 : SHARE_BUILTIN (OPTION_MASK_ISA_SSE4_2, 0, OPTION_MASK_ISA_CRC32, 0);
14602 : 1271589 : SHARE_BUILTIN (OPTION_MASK_ISA_FMA, 0, OPTION_MASK_ISA_FMA4, 0);
14603 : 1271589 : SHARE_BUILTIN (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, 0,
14604 : 1271589 : OPTION_MASK_ISA2_AVXVNNI);
14605 : 1271589 : SHARE_BUILTIN (OPTION_MASK_ISA_AVX512IFMA | OPTION_MASK_ISA_AVX512VL, 0, 0,
14606 : 1271589 : OPTION_MASK_ISA2_AVXIFMA);
14607 : 1271589 : SHARE_BUILTIN (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512BF16, 0,
14608 : 1271589 : OPTION_MASK_ISA2_AVXNECONVERT);
14609 : 1271589 : SHARE_BUILTIN (OPTION_MASK_ISA_AES, 0, OPTION_MASK_ISA_AVX512VL,
14610 : 1271589 : OPTION_MASK_ISA2_VAES);
14611 : 1271589 : SHARE_BUILTIN (0, OPTION_MASK_ISA2_AVXVNNIINT8, 0,
14612 : 1271589 : OPTION_MASK_ISA2_AVX10_2);
14613 : 1271589 : SHARE_BUILTIN (0, OPTION_MASK_ISA2_AVXVNNIINT16, 0,
14614 : 1271589 : OPTION_MASK_ISA2_AVX10_2);
14615 : 1271589 : isa = tmp_isa;
14616 : 1271589 : isa2 = tmp_isa2;
14617 : :
14618 : 1271589 : if ((bisa & OPTION_MASK_ISA_MMX) && !TARGET_MMX && TARGET_MMX_WITH_SSE
14619 : : /* __builtin_ia32_maskmovq requires MMX registers. */
14620 : 4563 : && fcode != IX86_BUILTIN_MASKMOVQ)
14621 : : {
14622 : 4554 : bisa &= ~OPTION_MASK_ISA_MMX;
14623 : 4554 : bisa |= OPTION_MASK_ISA_SSE2;
14624 : : }
14625 : :
14626 : 1271589 : if (pbisa)
14627 : 172202 : *pbisa = bisa;
14628 : 1271589 : if (pbisa2)
14629 : 172202 : *pbisa2 = bisa2;
14630 : :
14631 : 1271589 : return (bisa & isa) == bisa && (bisa2 & isa2) == bisa2;
14632 : : }
14633 : :
14634 : : /* Emit instructions to set the carry flag from ARG. */
14635 : :
14636 : : void
14637 : 13074 : ix86_expand_carry (rtx arg)
14638 : : {
14639 : 13074 : if (!CONST_INT_P (arg) || arg == const0_rtx)
14640 : : {
14641 : 13068 : arg = convert_to_mode (QImode, arg, 1);
14642 : 13068 : arg = copy_to_mode_reg (QImode, arg);
14643 : 13068 : emit_insn (gen_addqi3_cconly_overflow (arg, constm1_rtx));
14644 : : }
14645 : : else
14646 : 6 : emit_insn (gen_x86_stc ());
14647 : 13074 : }
14648 : :
14649 : : /* Expand an expression EXP that calls a built-in function,
14650 : : with result going to TARGET if that's convenient
14651 : : (and in mode MODE if that's convenient).
14652 : : SUBTARGET may be used as the target for computing one of EXP's operands.
14653 : : IGNORE is nonzero if the value is to be ignored. */
14654 : :
14655 : : rtx
14656 : 172978 : ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
14657 : : machine_mode mode, int ignore)
14658 : : {
14659 : 172978 : size_t i;
14660 : 172978 : enum insn_code icode, icode2;
14661 : 172978 : tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
14662 : 172978 : tree arg0, arg1, arg2, arg3, arg4;
14663 : 172978 : rtx op0, op1, op2, op3, op4, pat, pat2, insn;
14664 : 172978 : machine_mode mode0, mode1, mode2, mode3, mode4;
14665 : 172978 : unsigned int fcode = DECL_MD_FUNCTION_CODE (fndecl);
14666 : 172978 : HOST_WIDE_INT bisa, bisa2;
14667 : :
14668 : : /* For CPU builtins that can be folded, fold first and expand the fold. */
14669 : 172978 : switch (fcode)
14670 : : {
14671 : 195 : case IX86_BUILTIN_CPU_INIT:
14672 : 195 : {
14673 : : /* Make it call __cpu_indicator_init in libgcc. */
14674 : 195 : tree call_expr, fndecl, type;
14675 : 195 : type = build_function_type_list (integer_type_node, NULL_TREE);
14676 : 195 : fndecl = build_fn_decl ("__cpu_indicator_init", type);
14677 : 195 : call_expr = build_call_expr (fndecl, 0);
14678 : 195 : return expand_expr (call_expr, target, mode, EXPAND_NORMAL);
14679 : : }
14680 : 581 : case IX86_BUILTIN_CPU_IS:
14681 : 581 : case IX86_BUILTIN_CPU_SUPPORTS:
14682 : 581 : {
14683 : 581 : tree arg0 = CALL_EXPR_ARG (exp, 0);
14684 : 581 : tree fold_expr = fold_builtin_cpu (fndecl, &arg0);
14685 : 581 : gcc_assert (fold_expr != NULL_TREE);
14686 : 581 : return expand_expr (fold_expr, target, mode, EXPAND_NORMAL);
14687 : : }
14688 : : }
14689 : :
14690 : 172202 : if (!ix86_check_builtin_isa_match (fcode, &bisa, &bisa2))
14691 : : {
14692 : 23 : bool add_abi_p = bisa & OPTION_MASK_ISA_64BIT;
14693 : 23 : if (TARGET_ABI_X32)
14694 : 0 : bisa |= OPTION_MASK_ABI_X32;
14695 : : else
14696 : 23 : bisa |= OPTION_MASK_ABI_64;
14697 : 23 : char *opts = ix86_target_string (bisa, bisa2, 0, 0, NULL, NULL,
14698 : : (enum fpmath_unit) 0,
14699 : : (enum prefer_vector_width) 0,
14700 : : PVW_NONE, false, add_abi_p);
14701 : 23 : if (!opts)
14702 : 0 : error ("%qE needs unknown isa option", fndecl);
14703 : : else
14704 : : {
14705 : 23 : gcc_assert (opts != NULL);
14706 : 23 : error ("%qE needs isa option %s", fndecl, opts);
14707 : 23 : free (opts);
14708 : : }
14709 : 23 : return expand_call (exp, target, ignore);
14710 : : }
14711 : :
14712 : 172179 : switch (fcode)
14713 : : {
14714 : 35 : case IX86_BUILTIN_MASKMOVQ:
14715 : 35 : case IX86_BUILTIN_MASKMOVDQU:
14716 : 34 : icode = (fcode == IX86_BUILTIN_MASKMOVQ
14717 : 35 : ? CODE_FOR_mmx_maskmovq
14718 : : : CODE_FOR_sse2_maskmovdqu);
14719 : : /* Note the arg order is different from the operand order. */
14720 : 35 : arg1 = CALL_EXPR_ARG (exp, 0);
14721 : 35 : arg2 = CALL_EXPR_ARG (exp, 1);
14722 : 35 : arg0 = CALL_EXPR_ARG (exp, 2);
14723 : 35 : op0 = expand_normal (arg0);
14724 : 35 : op1 = expand_normal (arg1);
14725 : 35 : op2 = expand_normal (arg2);
14726 : 35 : mode0 = insn_data[icode].operand[0].mode;
14727 : 35 : mode1 = insn_data[icode].operand[1].mode;
14728 : 35 : mode2 = insn_data[icode].operand[2].mode;
14729 : :
14730 : 35 : op0 = ix86_zero_extend_to_Pmode (op0);
14731 : 35 : op0 = gen_rtx_MEM (mode1, op0);
14732 : :
14733 : 35 : if (!insn_data[icode].operand[0].predicate (op0, mode0))
14734 : 0 : op0 = copy_to_mode_reg (mode0, op0);
14735 : 35 : if (!insn_data[icode].operand[1].predicate (op1, mode1))
14736 : 2 : op1 = copy_to_mode_reg (mode1, op1);
14737 : 35 : if (!insn_data[icode].operand[2].predicate (op2, mode2))
14738 : 2 : op2 = copy_to_mode_reg (mode2, op2);
14739 : 35 : pat = GEN_FCN (icode) (op0, op1, op2);
14740 : 35 : if (! pat)
14741 : 56607 : return 0;
14742 : 35 : emit_insn (pat);
14743 : 35 : return 0;
14744 : :
14745 : 22008 : case IX86_BUILTIN_LDMXCSR:
14746 : 22008 : op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
14747 : 22008 : target = assign_stack_temp (SImode, GET_MODE_SIZE (SImode));
14748 : 22008 : emit_move_insn (target, op0);
14749 : 22008 : emit_insn (gen_sse_ldmxcsr (target));
14750 : 22008 : return 0;
14751 : :
14752 : 14785 : case IX86_BUILTIN_STMXCSR:
14753 : 14785 : target = assign_stack_temp (SImode, GET_MODE_SIZE (SImode));
14754 : 14785 : emit_insn (gen_sse_stmxcsr (target));
14755 : 14785 : return copy_to_mode_reg (SImode, target);
14756 : :
14757 : 11 : case IX86_BUILTIN_CLFLUSH:
14758 : 11 : arg0 = CALL_EXPR_ARG (exp, 0);
14759 : 11 : op0 = expand_normal (arg0);
14760 : 11 : icode = CODE_FOR_sse2_clflush;
14761 : 11 : if (!insn_data[icode].operand[0].predicate (op0, Pmode))
14762 : 5 : op0 = ix86_zero_extend_to_Pmode (op0);
14763 : :
14764 : 11 : emit_insn (gen_sse2_clflush (op0));
14765 : 11 : return 0;
14766 : :
14767 : 19 : case IX86_BUILTIN_CLWB:
14768 : 19 : arg0 = CALL_EXPR_ARG (exp, 0);
14769 : 19 : op0 = expand_normal (arg0);
14770 : 19 : icode = CODE_FOR_clwb;
14771 : 19 : if (!insn_data[icode].operand[0].predicate (op0, Pmode))
14772 : 9 : op0 = ix86_zero_extend_to_Pmode (op0);
14773 : :
14774 : 19 : emit_insn (gen_clwb (op0));
14775 : 19 : return 0;
14776 : :
14777 : 19 : case IX86_BUILTIN_CLFLUSHOPT:
14778 : 19 : arg0 = CALL_EXPR_ARG (exp, 0);
14779 : 19 : op0 = expand_normal (arg0);
14780 : 19 : icode = CODE_FOR_clflushopt;
14781 : 19 : if (!insn_data[icode].operand[0].predicate (op0, Pmode))
14782 : 9 : op0 = ix86_zero_extend_to_Pmode (op0);
14783 : :
14784 : 19 : emit_insn (gen_clflushopt (op0));
14785 : 19 : return 0;
14786 : :
14787 : 47 : case IX86_BUILTIN_MONITOR:
14788 : 47 : case IX86_BUILTIN_MONITORX:
14789 : 47 : arg0 = CALL_EXPR_ARG (exp, 0);
14790 : 47 : arg1 = CALL_EXPR_ARG (exp, 1);
14791 : 47 : arg2 = CALL_EXPR_ARG (exp, 2);
14792 : 47 : op0 = expand_normal (arg0);
14793 : 47 : op1 = expand_normal (arg1);
14794 : 47 : op2 = expand_normal (arg2);
14795 : 47 : if (!REG_P (op0))
14796 : 19 : op0 = ix86_zero_extend_to_Pmode (op0);
14797 : 47 : if (!REG_P (op1))
14798 : 22 : op1 = copy_to_mode_reg (SImode, op1);
14799 : 47 : if (!REG_P (op2))
14800 : 25 : op2 = copy_to_mode_reg (SImode, op2);
14801 : :
14802 : 47 : emit_insn (fcode == IX86_BUILTIN_MONITOR
14803 : 26 : ? gen_sse3_monitor (Pmode, op0, op1, op2)
14804 : 21 : : gen_monitorx (Pmode, op0, op1, op2));
14805 : 47 : return 0;
14806 : :
14807 : 25 : case IX86_BUILTIN_MWAIT:
14808 : 25 : arg0 = CALL_EXPR_ARG (exp, 0);
14809 : 25 : arg1 = CALL_EXPR_ARG (exp, 1);
14810 : 25 : op0 = expand_normal (arg0);
14811 : 25 : op1 = expand_normal (arg1);
14812 : 25 : if (!REG_P (op0))
14813 : 13 : op0 = copy_to_mode_reg (SImode, op0);
14814 : 25 : if (!REG_P (op1))
14815 : 11 : op1 = copy_to_mode_reg (SImode, op1);
14816 : 25 : emit_insn (gen_sse3_mwait (op0, op1));
14817 : 25 : return 0;
14818 : :
14819 : 21 : case IX86_BUILTIN_MWAITX:
14820 : 21 : arg0 = CALL_EXPR_ARG (exp, 0);
14821 : 21 : arg1 = CALL_EXPR_ARG (exp, 1);
14822 : 21 : arg2 = CALL_EXPR_ARG (exp, 2);
14823 : 21 : op0 = expand_normal (arg0);
14824 : 21 : op1 = expand_normal (arg1);
14825 : 21 : op2 = expand_normal (arg2);
14826 : 21 : if (!REG_P (op0))
14827 : 11 : op0 = copy_to_mode_reg (SImode, op0);
14828 : 21 : if (!REG_P (op1))
14829 : 10 : op1 = copy_to_mode_reg (SImode, op1);
14830 : 21 : if (!REG_P (op2))
14831 : 11 : op2 = copy_to_mode_reg (SImode, op2);
14832 : 21 : emit_insn (gen_mwaitx (op0, op1, op2));
14833 : 21 : return 0;
14834 : :
14835 : 21 : case IX86_BUILTIN_UMONITOR:
14836 : 21 : arg0 = CALL_EXPR_ARG (exp, 0);
14837 : 21 : op0 = expand_normal (arg0);
14838 : :
14839 : 21 : op0 = ix86_zero_extend_to_Pmode (op0);
14840 : 21 : emit_insn (gen_umonitor (Pmode, op0));
14841 : 21 : return 0;
14842 : :
14843 : 42 : case IX86_BUILTIN_UMWAIT:
14844 : 42 : case IX86_BUILTIN_TPAUSE:
14845 : 42 : arg0 = CALL_EXPR_ARG (exp, 0);
14846 : 42 : arg1 = CALL_EXPR_ARG (exp, 1);
14847 : 42 : op0 = expand_normal (arg0);
14848 : 42 : op1 = expand_normal (arg1);
14849 : :
14850 : 42 : if (!REG_P (op0))
14851 : 20 : op0 = copy_to_mode_reg (SImode, op0);
14852 : :
14853 : 42 : op1 = force_reg (DImode, op1);
14854 : :
14855 : 42 : if (TARGET_64BIT)
14856 : : {
14857 : 42 : op2 = expand_simple_binop (DImode, LSHIFTRT, op1, GEN_INT (32),
14858 : : NULL, 1, OPTAB_DIRECT);
14859 : 42 : switch (fcode)
14860 : : {
14861 : : case IX86_BUILTIN_UMWAIT:
14862 : : icode = CODE_FOR_umwait_rex64;
14863 : : break;
14864 : 21 : case IX86_BUILTIN_TPAUSE:
14865 : 21 : icode = CODE_FOR_tpause_rex64;
14866 : 21 : break;
14867 : 0 : default:
14868 : 0 : gcc_unreachable ();
14869 : : }
14870 : :
14871 : 42 : op2 = gen_lowpart (SImode, op2);
14872 : 42 : op1 = gen_lowpart (SImode, op1);
14873 : 42 : pat = GEN_FCN (icode) (op0, op1, op2);
14874 : : }
14875 : : else
14876 : : {
14877 : 0 : switch (fcode)
14878 : : {
14879 : : case IX86_BUILTIN_UMWAIT:
14880 : : icode = CODE_FOR_umwait;
14881 : : break;
14882 : 0 : case IX86_BUILTIN_TPAUSE:
14883 : 0 : icode = CODE_FOR_tpause;
14884 : 0 : break;
14885 : 0 : default:
14886 : 0 : gcc_unreachable ();
14887 : : }
14888 : 0 : pat = GEN_FCN (icode) (op0, op1);
14889 : : }
14890 : :
14891 : 42 : if (!pat)
14892 : : return 0;
14893 : :
14894 : 42 : emit_insn (pat);
14895 : :
14896 : 42 : if (target == 0
14897 : 42 : || !register_operand (target, QImode))
14898 : 0 : target = gen_reg_rtx (QImode);
14899 : :
14900 : 42 : pat = gen_rtx_EQ (QImode, gen_rtx_REG (CCCmode, FLAGS_REG),
14901 : : const0_rtx);
14902 : 42 : emit_insn (gen_rtx_SET (target, pat));
14903 : :
14904 : 42 : return target;
14905 : :
14906 : 20 : case IX86_BUILTIN_TESTUI:
14907 : 20 : emit_insn (gen_testui ());
14908 : :
14909 : 20 : if (target == 0
14910 : 20 : || !register_operand (target, QImode))
14911 : 0 : target = gen_reg_rtx (QImode);
14912 : :
14913 : 20 : pat = gen_rtx_LTU (QImode, gen_rtx_REG (CCCmode, FLAGS_REG),
14914 : : const0_rtx);
14915 : 20 : emit_insn (gen_rtx_SET (target, pat));
14916 : :
14917 : 20 : return target;
14918 : :
14919 : 19 : case IX86_BUILTIN_CLZERO:
14920 : 19 : arg0 = CALL_EXPR_ARG (exp, 0);
14921 : 19 : op0 = expand_normal (arg0);
14922 : 19 : if (!REG_P (op0))
14923 : 9 : op0 = ix86_zero_extend_to_Pmode (op0);
14924 : 19 : emit_insn (gen_clzero (Pmode, op0));
14925 : 19 : return 0;
14926 : :
14927 : 19 : case IX86_BUILTIN_CLDEMOTE:
14928 : 19 : arg0 = CALL_EXPR_ARG (exp, 0);
14929 : 19 : op0 = expand_normal (arg0);
14930 : 19 : icode = CODE_FOR_cldemote;
14931 : 19 : if (!insn_data[icode].operand[0].predicate (op0, Pmode))
14932 : 9 : op0 = ix86_zero_extend_to_Pmode (op0);
14933 : :
14934 : 19 : emit_insn (gen_cldemote (op0));
14935 : 19 : return 0;
14936 : :
14937 : 11 : case IX86_BUILTIN_LOADIWKEY:
14938 : 11 : {
14939 : 11 : arg0 = CALL_EXPR_ARG (exp, 0);
14940 : 11 : arg1 = CALL_EXPR_ARG (exp, 1);
14941 : 11 : arg2 = CALL_EXPR_ARG (exp, 2);
14942 : 11 : arg3 = CALL_EXPR_ARG (exp, 3);
14943 : :
14944 : 11 : op0 = expand_normal (arg0);
14945 : 11 : op1 = expand_normal (arg1);
14946 : 11 : op2 = expand_normal (arg2);
14947 : 11 : op3 = expand_normal (arg3);
14948 : :
14949 : 11 : if (!REG_P (op0))
14950 : 5 : op0 = copy_to_mode_reg (V2DImode, op0);
14951 : 11 : if (!REG_P (op1))
14952 : 5 : op1 = copy_to_mode_reg (V2DImode, op1);
14953 : 11 : if (!REG_P (op2))
14954 : 5 : op2 = copy_to_mode_reg (V2DImode, op2);
14955 : 11 : if (!REG_P (op3))
14956 : 5 : op3 = copy_to_mode_reg (SImode, op3);
14957 : :
14958 : 11 : emit_insn (gen_loadiwkey (op0, op1, op2, op3));
14959 : :
14960 : 11 : return 0;
14961 : : }
14962 : :
14963 : 12 : case IX86_BUILTIN_AESDEC128KLU8:
14964 : 12 : icode = CODE_FOR_aesdec128klu8;
14965 : 12 : goto aesdecenc_expand;
14966 : :
14967 : 12 : case IX86_BUILTIN_AESDEC256KLU8:
14968 : 12 : icode = CODE_FOR_aesdec256klu8;
14969 : 12 : goto aesdecenc_expand;
14970 : :
14971 : 12 : case IX86_BUILTIN_AESENC128KLU8:
14972 : 12 : icode = CODE_FOR_aesenc128klu8;
14973 : 12 : goto aesdecenc_expand;
14974 : :
14975 : : case IX86_BUILTIN_AESENC256KLU8:
14976 : : icode = CODE_FOR_aesenc256klu8;
14977 : :
14978 : 48 : aesdecenc_expand:
14979 : :
14980 : 48 : arg0 = CALL_EXPR_ARG (exp, 0); // __m128i *odata
14981 : 48 : arg1 = CALL_EXPR_ARG (exp, 1); // __m128i idata
14982 : 48 : arg2 = CALL_EXPR_ARG (exp, 2); // const void *p
14983 : :
14984 : 48 : op0 = expand_normal (arg0);
14985 : 48 : op1 = expand_normal (arg1);
14986 : 48 : op2 = expand_normal (arg2);
14987 : :
14988 : 48 : if (!address_operand (op0, V2DImode))
14989 : : {
14990 : 16 : op0 = convert_memory_address (Pmode, op0);
14991 : 16 : op0 = copy_addr_to_reg (op0);
14992 : : }
14993 : 48 : op0 = gen_rtx_MEM (V2DImode, op0);
14994 : :
14995 : 48 : if (!REG_P (op1))
14996 : 20 : op1 = copy_to_mode_reg (V2DImode, op1);
14997 : :
14998 : 48 : if (!address_operand (op2, VOIDmode))
14999 : : {
15000 : 16 : op2 = convert_memory_address (Pmode, op2);
15001 : 16 : op2 = copy_addr_to_reg (op2);
15002 : : }
15003 : 48 : op2 = gen_rtx_MEM (BLKmode, op2);
15004 : :
15005 : 48 : emit_insn (GEN_FCN (icode) (op1, op1, op2));
15006 : :
15007 : 48 : if (target == 0)
15008 : 4 : target = gen_reg_rtx (QImode);
15009 : :
15010 : : /* NB: For aesenc/aesdec keylocker insn, ZF will be set when runtime
15011 : : error occurs. Then the output should be cleared for safety. */
15012 : 48 : rtx_code_label *ok_label;
15013 : 48 : rtx tmp;
15014 : :
15015 : 48 : tmp = gen_rtx_REG (CCZmode, FLAGS_REG);
15016 : 48 : pat = gen_rtx_EQ (QImode, tmp, const0_rtx);
15017 : 48 : ok_label = gen_label_rtx ();
15018 : 48 : emit_cmp_and_jump_insns (tmp, const0_rtx, NE, 0, GET_MODE (tmp),
15019 : : true, ok_label);
15020 : : /* Usually the runtime error seldom occur, so predict OK path as
15021 : : hotspot to optimize it as fallthrough block. */
15022 : 48 : predict_jump (REG_BR_PROB_BASE * 90 / 100);
15023 : :
15024 : 48 : emit_insn (gen_rtx_SET (op1, const0_rtx));
15025 : :
15026 : 48 : emit_label (ok_label);
15027 : 48 : emit_insn (gen_rtx_SET (target, pat));
15028 : 48 : emit_insn (gen_rtx_SET (op0, op1));
15029 : :
15030 : 48 : return target;
15031 : :
15032 : 11 : case IX86_BUILTIN_AESDECWIDE128KLU8:
15033 : 11 : icode = CODE_FOR_aesdecwide128klu8;
15034 : 11 : goto wideaesdecenc_expand;
15035 : :
15036 : 11 : case IX86_BUILTIN_AESDECWIDE256KLU8:
15037 : 11 : icode = CODE_FOR_aesdecwide256klu8;
15038 : 11 : goto wideaesdecenc_expand;
15039 : :
15040 : 11 : case IX86_BUILTIN_AESENCWIDE128KLU8:
15041 : 11 : icode = CODE_FOR_aesencwide128klu8;
15042 : 11 : goto wideaesdecenc_expand;
15043 : :
15044 : : case IX86_BUILTIN_AESENCWIDE256KLU8:
15045 : : icode = CODE_FOR_aesencwide256klu8;
15046 : :
15047 : 44 : wideaesdecenc_expand:
15048 : :
15049 : 44 : rtx xmm_regs[8];
15050 : 44 : rtx op;
15051 : :
15052 : 44 : arg0 = CALL_EXPR_ARG (exp, 0); // __m128i * odata
15053 : 44 : arg1 = CALL_EXPR_ARG (exp, 1); // const __m128i * idata
15054 : 44 : arg2 = CALL_EXPR_ARG (exp, 2); // const void *p
15055 : :
15056 : 44 : op0 = expand_normal (arg0);
15057 : 44 : op1 = expand_normal (arg1);
15058 : 44 : op2 = expand_normal (arg2);
15059 : :
15060 : 44 : if (GET_MODE (op1) != Pmode)
15061 : 0 : op1 = convert_to_mode (Pmode, op1, 1);
15062 : :
15063 : 44 : if (!address_operand (op2, VOIDmode))
15064 : : {
15065 : 16 : op2 = convert_memory_address (Pmode, op2);
15066 : 16 : op2 = copy_addr_to_reg (op2);
15067 : : }
15068 : 44 : op2 = gen_rtx_MEM (BLKmode, op2);
15069 : :
15070 : 440 : for (i = 0; i < 8; i++)
15071 : : {
15072 : 352 : xmm_regs[i] = gen_rtx_REG (V2DImode, GET_SSE_REGNO (i));
15073 : :
15074 : 352 : op = gen_rtx_MEM (V2DImode,
15075 : 352 : plus_constant (Pmode, op1, (i * 16)));
15076 : :
15077 : 352 : emit_move_insn (xmm_regs[i], op);
15078 : : }
15079 : :
15080 : 44 : emit_insn (GEN_FCN (icode) (op2));
15081 : :
15082 : 44 : if (target == 0)
15083 : 0 : target = gen_reg_rtx (QImode);
15084 : :
15085 : 44 : tmp = gen_rtx_REG (CCZmode, FLAGS_REG);
15086 : 44 : pat = gen_rtx_EQ (QImode, tmp, const0_rtx);
15087 : 44 : ok_label = gen_label_rtx ();
15088 : 44 : emit_cmp_and_jump_insns (tmp, const0_rtx, NE, 0, GET_MODE (tmp),
15089 : : true, ok_label);
15090 : 44 : predict_jump (REG_BR_PROB_BASE * 90 / 100);
15091 : :
15092 : 440 : for (i = 0; i < 8; i++)
15093 : 352 : emit_insn (gen_rtx_SET (xmm_regs[i], const0_rtx));
15094 : :
15095 : 44 : emit_label (ok_label);
15096 : 44 : emit_insn (gen_rtx_SET (target, pat));
15097 : :
15098 : 44 : if (GET_MODE (op0) != Pmode)
15099 : 0 : op0 = convert_to_mode (Pmode, op0, 1);
15100 : :
15101 : 396 : for (i = 0; i < 8; i++)
15102 : : {
15103 : 352 : op = gen_rtx_MEM (V2DImode,
15104 : 352 : plus_constant (Pmode, op0, (i * 16)));
15105 : 352 : emit_move_insn (op, xmm_regs[i]);
15106 : : }
15107 : :
15108 : : return target;
15109 : :
15110 : 12 : case IX86_BUILTIN_ENCODEKEY128U32:
15111 : 12 : {
15112 : 12 : rtx op, xmm_regs[7];
15113 : :
15114 : 12 : arg0 = CALL_EXPR_ARG (exp, 0); // unsigned int htype
15115 : 12 : arg1 = CALL_EXPR_ARG (exp, 1); // __m128i key
15116 : 12 : arg2 = CALL_EXPR_ARG (exp, 2); // void *h
15117 : :
15118 : 12 : op0 = expand_normal (arg0);
15119 : 12 : op1 = expand_normal (arg1);
15120 : 12 : op2 = expand_normal (arg2);
15121 : :
15122 : 12 : if (!REG_P (op0))
15123 : 6 : op0 = copy_to_mode_reg (SImode, op0);
15124 : :
15125 : 12 : if (GET_MODE (op2) != Pmode)
15126 : 1 : op2 = convert_to_mode (Pmode, op2, 1);
15127 : :
15128 : 12 : op = gen_rtx_REG (V2DImode, GET_SSE_REGNO (0));
15129 : 12 : emit_move_insn (op, op1);
15130 : :
15131 : 60 : for (i = 0; i < 3; i++)
15132 : 36 : xmm_regs[i] = gen_rtx_REG (V2DImode, GET_SSE_REGNO (i));
15133 : :
15134 : 12 : if (target == 0)
15135 : 1 : target = gen_reg_rtx (SImode);
15136 : :
15137 : 12 : emit_insn (gen_encodekey128u32 (target, op0));
15138 : :
15139 : 60 : for (i = 0; i < 3; i++)
15140 : : {
15141 : 36 : op = gen_rtx_MEM (V2DImode,
15142 : 36 : plus_constant (Pmode, op2, (i * 16)));
15143 : 36 : emit_move_insn (op, xmm_regs[i]);
15144 : : }
15145 : :
15146 : 12 : return target;
15147 : : }
15148 : 12 : case IX86_BUILTIN_ENCODEKEY256U32:
15149 : 12 : {
15150 : 12 : rtx op, xmm_regs[7];
15151 : :
15152 : 12 : arg0 = CALL_EXPR_ARG (exp, 0); // unsigned int htype
15153 : 12 : arg1 = CALL_EXPR_ARG (exp, 1); // __m128i keylow
15154 : 12 : arg2 = CALL_EXPR_ARG (exp, 2); // __m128i keyhi
15155 : 12 : arg3 = CALL_EXPR_ARG (exp, 3); // void *h
15156 : :
15157 : 12 : op0 = expand_normal (arg0);
15158 : 12 : op1 = expand_normal (arg1);
15159 : 12 : op2 = expand_normal (arg2);
15160 : 12 : op3 = expand_normal (arg3);
15161 : :
15162 : 12 : if (!REG_P (op0))
15163 : 6 : op0 = copy_to_mode_reg (SImode, op0);
15164 : :
15165 : 12 : if (GET_MODE (op3) != Pmode)
15166 : 1 : op3 = convert_to_mode (Pmode, op3, 1);
15167 : :
15168 : : /* Force to use xmm0, xmm1 for keylow, keyhi*/
15169 : 12 : op = gen_rtx_REG (V2DImode, GET_SSE_REGNO (0));
15170 : 12 : emit_move_insn (op, op1);
15171 : 12 : op = gen_rtx_REG (V2DImode, GET_SSE_REGNO (1));
15172 : 12 : emit_move_insn (op, op2);
15173 : :
15174 : 72 : for (i = 0; i < 4; i++)
15175 : 48 : xmm_regs[i] = gen_rtx_REG (V2DImode, GET_SSE_REGNO (i));
15176 : :
15177 : 12 : if (target == 0)
15178 : 1 : target = gen_reg_rtx (SImode);
15179 : :
15180 : 12 : emit_insn (gen_encodekey256u32 (target, op0));
15181 : :
15182 : 72 : for (i = 0; i < 4; i++)
15183 : : {
15184 : 48 : op = gen_rtx_MEM (V2DImode,
15185 : 48 : plus_constant (Pmode, op3, (i * 16)));
15186 : 48 : emit_move_insn (op, xmm_regs[i]);
15187 : : }
15188 : :
15189 : 12 : return target;
15190 : : }
15191 : :
15192 : 48 : case IX86_BUILTIN_PREFETCH:
15193 : 48 : {
15194 : 48 : arg0 = CALL_EXPR_ARG (exp, 0); // const void *
15195 : 48 : arg1 = CALL_EXPR_ARG (exp, 1); // const int
15196 : 48 : arg2 = CALL_EXPR_ARG (exp, 2); // const int
15197 : 48 : arg3 = CALL_EXPR_ARG (exp, 3); // const int
15198 : :
15199 : 48 : op0 = expand_normal (arg0);
15200 : 48 : op1 = expand_normal (arg1);
15201 : 48 : op2 = expand_normal (arg2);
15202 : 48 : op3 = expand_normal (arg3);
15203 : :
15204 : 48 : if (!CONST_INT_P (op1) || !CONST_INT_P (op2) || !CONST_INT_P (op3))
15205 : : {
15206 : 0 : error ("second, third and fourth argument must be a const");
15207 : 0 : return const0_rtx;
15208 : : }
15209 : :
15210 : 48 : if (!IN_RANGE (INTVAL (op1), 0, 2))
15211 : : {
15212 : 1 : warning (0, "invalid second argument to"
15213 : : " %<__builtin_ia32_prefetch%>; using zero");
15214 : 1 : op1 = const0_rtx;
15215 : : }
15216 : :
15217 : 48 : if (INTVAL (op3) == 1)
15218 : : {
15219 : 4 : if (!IN_RANGE (INTVAL (op2), 2, 3))
15220 : : {
15221 : 1 : error ("invalid third argument");
15222 : 1 : return const0_rtx;
15223 : : }
15224 : :
15225 : 3 : if (TARGET_64BIT && TARGET_PREFETCHI
15226 : 6 : && local_func_symbolic_operand (op0, GET_MODE (op0)))
15227 : 2 : emit_insn (gen_prefetchi (op0, op2));
15228 : : else
15229 : : {
15230 : 1 : warning (0, "instruction prefetch applies when in 64-bit mode"
15231 : : " with RIP-relative addressing and"
15232 : : " option %<-mprefetchi%>;"
15233 : : " they stay NOPs otherwise");
15234 : 1 : emit_insn (gen_nop ());
15235 : : }
15236 : : }
15237 : : else
15238 : : {
15239 : 44 : if (INTVAL (op3) != 0)
15240 : 1 : warning (0, "invalid forth argument to"
15241 : : " %<__builtin_ia32_prefetch%>; using zero");
15242 : :
15243 : 44 : if (!address_operand (op0, VOIDmode))
15244 : : {
15245 : 10 : op0 = convert_memory_address (Pmode, op0);
15246 : 10 : op0 = copy_addr_to_reg (op0);
15247 : : }
15248 : :
15249 : 44 : if (!IN_RANGE (INTVAL (op2), 0, 3))
15250 : : {
15251 : 1 : warning (0, "invalid third argument to %<__builtin_ia32_prefetch%>; using zero");
15252 : 1 : op2 = const0_rtx;
15253 : : }
15254 : :
15255 : 44 : if (TARGET_3DNOW
15256 : 26 : || TARGET_PREFETCH_SSE
15257 : 0 : || TARGET_PRFCHW
15258 : 0 : || TARGET_MOVRS)
15259 : 44 : emit_insn (gen_prefetch (op0, op1, op2));
15260 : 0 : else if (!MEM_P (op0) && side_effects_p (op0))
15261 : : /* Don't do anything with direct references to volatile memory,
15262 : : but generate code to handle other side effects. */
15263 : 0 : emit_insn (op0);
15264 : : }
15265 : :
15266 : : return 0;
15267 : : }
15268 : :
15269 : 21 : case IX86_BUILTIN_PREFETCHI:
15270 : 21 : {
15271 : 21 : arg0 = CALL_EXPR_ARG (exp, 0); // const void *
15272 : 21 : arg1 = CALL_EXPR_ARG (exp, 1); // const int
15273 : :
15274 : 21 : op0 = expand_normal (arg0);
15275 : 21 : op1 = expand_normal (arg1);
15276 : :
15277 : 21 : if (!CONST_INT_P (op1))
15278 : : {
15279 : 0 : error ("second argument must be a const");
15280 : 0 : return const0_rtx;
15281 : : }
15282 : :
15283 : : /* GOT/PLT_PIC should not be available for instruction prefetch.
15284 : : It must be real instruction address. */
15285 : 21 : if (TARGET_64BIT
15286 : 21 : && local_func_symbolic_operand (op0, GET_MODE (op0)))
15287 : 4 : emit_insn (gen_prefetchi (op0, op1));
15288 : : else
15289 : : {
15290 : : /* Ignore the hint. */
15291 : 17 : warning (0, "instruction prefetch applies when in 64-bit mode"
15292 : : " with RIP-relative addressing and"
15293 : : " option %<-mprefetchi%>;"
15294 : : " they stay NOPs otherwise");
15295 : 17 : emit_insn (gen_nop ());
15296 : : }
15297 : :
15298 : : return 0;
15299 : : }
15300 : :
15301 : 52 : case IX86_BUILTIN_URDMSR:
15302 : 52 : case IX86_BUILTIN_UWRMSR:
15303 : 52 : {
15304 : 52 : arg0 = CALL_EXPR_ARG (exp, 0);
15305 : 52 : op0 = expand_normal (arg0);
15306 : :
15307 : 52 : if (CONST_INT_P (op0))
15308 : : {
15309 : 12 : unsigned HOST_WIDE_INT val = UINTVAL (op0);
15310 : 12 : if (val > 0xffffffff)
15311 : 2 : op0 = force_reg (DImode, op0);
15312 : : }
15313 : : else
15314 : 40 : op0 = force_reg (DImode, op0);
15315 : :
15316 : 52 : if (fcode == IX86_BUILTIN_UWRMSR)
15317 : : {
15318 : 26 : arg1 = CALL_EXPR_ARG (exp, 1);
15319 : 26 : op1 = expand_normal (arg1);
15320 : 26 : op1 = force_reg (DImode, op1);
15321 : 26 : icode = CODE_FOR_uwrmsr;
15322 : 26 : target = 0;
15323 : : }
15324 : : else
15325 : : {
15326 : 26 : if (target == 0)
15327 : 0 : target = gen_reg_rtx (DImode);
15328 : : icode = CODE_FOR_urdmsr;
15329 : : op1 = op0;
15330 : : op0 = target;
15331 : : }
15332 : 52 : emit_insn (GEN_FCN (icode) (op0, op1));
15333 : 52 : return target;
15334 : : }
15335 : :
15336 : 229 : case IX86_BUILTIN_VEC_INIT_V2SI:
15337 : 229 : case IX86_BUILTIN_VEC_INIT_V4HI:
15338 : 229 : case IX86_BUILTIN_VEC_INIT_V8QI:
15339 : 229 : return ix86_expand_vec_init_builtin (TREE_TYPE (exp), exp, target);
15340 : :
15341 : 391 : case IX86_BUILTIN_VEC_EXT_V2DF:
15342 : 391 : case IX86_BUILTIN_VEC_EXT_V2DI:
15343 : 391 : case IX86_BUILTIN_VEC_EXT_V4SF:
15344 : 391 : case IX86_BUILTIN_VEC_EXT_V4SI:
15345 : 391 : case IX86_BUILTIN_VEC_EXT_V8HI:
15346 : 391 : case IX86_BUILTIN_VEC_EXT_V2SI:
15347 : 391 : case IX86_BUILTIN_VEC_EXT_V4HI:
15348 : 391 : case IX86_BUILTIN_VEC_EXT_V16QI:
15349 : 391 : return ix86_expand_vec_ext_builtin (exp, target);
15350 : :
15351 : 204 : case IX86_BUILTIN_VEC_SET_V2DI:
15352 : 204 : case IX86_BUILTIN_VEC_SET_V4SF:
15353 : 204 : case IX86_BUILTIN_VEC_SET_V4SI:
15354 : 204 : case IX86_BUILTIN_VEC_SET_V8HI:
15355 : 204 : case IX86_BUILTIN_VEC_SET_V4HI:
15356 : 204 : case IX86_BUILTIN_VEC_SET_V16QI:
15357 : 204 : return ix86_expand_vec_set_builtin (exp);
15358 : :
15359 : 0 : case IX86_BUILTIN_NANQ:
15360 : 0 : case IX86_BUILTIN_NANSQ:
15361 : 0 : return expand_call (exp, target, ignore);
15362 : :
15363 : 18 : case IX86_BUILTIN_RDPID:
15364 : :
15365 : 18 : op0 = gen_reg_rtx (word_mode);
15366 : :
15367 : 18 : if (TARGET_64BIT)
15368 : : {
15369 : 18 : insn = gen_rdpid_rex64 (op0);
15370 : 18 : op0 = convert_to_mode (SImode, op0, 1);
15371 : : }
15372 : : else
15373 : 0 : insn = gen_rdpid (op0);
15374 : :
15375 : 18 : emit_insn (insn);
15376 : :
15377 : 18 : if (target == 0
15378 : 18 : || !register_operand (target, SImode))
15379 : 0 : target = gen_reg_rtx (SImode);
15380 : :
15381 : 18 : emit_move_insn (target, op0);
15382 : 18 : return target;
15383 : :
15384 : 75 : case IX86_BUILTIN_2INTERSECTD512:
15385 : 75 : case IX86_BUILTIN_2INTERSECTQ512:
15386 : 75 : case IX86_BUILTIN_2INTERSECTD256:
15387 : 75 : case IX86_BUILTIN_2INTERSECTQ256:
15388 : 75 : case IX86_BUILTIN_2INTERSECTD128:
15389 : 75 : case IX86_BUILTIN_2INTERSECTQ128:
15390 : 75 : arg0 = CALL_EXPR_ARG (exp, 0);
15391 : 75 : arg1 = CALL_EXPR_ARG (exp, 1);
15392 : 75 : arg2 = CALL_EXPR_ARG (exp, 2);
15393 : 75 : arg3 = CALL_EXPR_ARG (exp, 3);
15394 : 75 : op0 = expand_normal (arg0);
15395 : 75 : op1 = expand_normal (arg1);
15396 : 75 : op2 = expand_normal (arg2);
15397 : 75 : op3 = expand_normal (arg3);
15398 : :
15399 : 75 : if (!address_operand (op0, VOIDmode))
15400 : : {
15401 : 25 : op0 = convert_memory_address (Pmode, op0);
15402 : 25 : op0 = copy_addr_to_reg (op0);
15403 : : }
15404 : 75 : if (!address_operand (op1, VOIDmode))
15405 : : {
15406 : 25 : op1 = convert_memory_address (Pmode, op1);
15407 : 25 : op1 = copy_addr_to_reg (op1);
15408 : : }
15409 : :
15410 : 75 : switch (fcode)
15411 : : {
15412 : : case IX86_BUILTIN_2INTERSECTD512:
15413 : : mode4 = P2HImode;
15414 : : icode = CODE_FOR_avx512vp2intersect_2intersectv16si;
15415 : : break;
15416 : : case IX86_BUILTIN_2INTERSECTQ512:
15417 : : mode4 = P2QImode;
15418 : : icode = CODE_FOR_avx512vp2intersect_2intersectv8di;
15419 : : break;
15420 : : case IX86_BUILTIN_2INTERSECTD256:
15421 : : mode4 = P2QImode;
15422 : : icode = CODE_FOR_avx512vp2intersect_2intersectv8si;
15423 : : break;
15424 : : case IX86_BUILTIN_2INTERSECTQ256:
15425 : : mode4 = P2QImode;
15426 : : icode = CODE_FOR_avx512vp2intersect_2intersectv4di;
15427 : : break;
15428 : : case IX86_BUILTIN_2INTERSECTD128:
15429 : : mode4 = P2QImode;
15430 : : icode = CODE_FOR_avx512vp2intersect_2intersectv4si;
15431 : : break;
15432 : : case IX86_BUILTIN_2INTERSECTQ128:
15433 : : mode4 = P2QImode;
15434 : : icode = CODE_FOR_avx512vp2intersect_2intersectv2di;
15435 : : break;
15436 : 0 : default:
15437 : 0 : gcc_unreachable ();
15438 : : }
15439 : :
15440 : 75 : mode2 = insn_data[icode].operand[1].mode;
15441 : 75 : mode3 = insn_data[icode].operand[2].mode;
15442 : 75 : if (!insn_data[icode].operand[1].predicate (op2, mode2))
15443 : 25 : op2 = copy_to_mode_reg (mode2, op2);
15444 : 75 : if (!insn_data[icode].operand[2].predicate (op3, mode3))
15445 : 6 : op3 = copy_to_mode_reg (mode3, op3);
15446 : :
15447 : 75 : op4 = gen_reg_rtx (mode4);
15448 : 75 : emit_insn (GEN_FCN (icode) (op4, op2, op3));
15449 : 75 : mode0 = mode4 == P2HImode ? HImode : QImode;
15450 : 75 : emit_move_insn (gen_rtx_MEM (mode0, op0),
15451 : 75 : gen_lowpart (mode0, op4));
15452 : 75 : emit_move_insn (gen_rtx_MEM (mode0, op1),
15453 : : gen_highpart (mode0, op4));
15454 : :
15455 : 75 : return 0;
15456 : :
15457 : 102 : case IX86_BUILTIN_RDPMC:
15458 : 102 : case IX86_BUILTIN_RDTSC:
15459 : 102 : case IX86_BUILTIN_RDTSCP:
15460 : 102 : case IX86_BUILTIN_XGETBV:
15461 : :
15462 : 102 : op0 = gen_reg_rtx (DImode);
15463 : 102 : op1 = gen_reg_rtx (DImode);
15464 : :
15465 : 102 : if (fcode == IX86_BUILTIN_RDPMC)
15466 : : {
15467 : 22 : arg0 = CALL_EXPR_ARG (exp, 0);
15468 : 22 : op2 = expand_normal (arg0);
15469 : 22 : if (!register_operand (op2, SImode))
15470 : 11 : op2 = copy_to_mode_reg (SImode, op2);
15471 : :
15472 : 22 : insn = (TARGET_64BIT
15473 : 22 : ? gen_rdpmc_rex64 (op0, op1, op2)
15474 : 0 : : gen_rdpmc (op0, op2));
15475 : 22 : emit_insn (insn);
15476 : : }
15477 : 80 : else if (fcode == IX86_BUILTIN_XGETBV)
15478 : : {
15479 : 22 : arg0 = CALL_EXPR_ARG (exp, 0);
15480 : 22 : op2 = expand_normal (arg0);
15481 : 22 : if (!register_operand (op2, SImode))
15482 : 1 : op2 = copy_to_mode_reg (SImode, op2);
15483 : :
15484 : 22 : insn = (TARGET_64BIT
15485 : 22 : ? gen_xgetbv_rex64 (op0, op1, op2)
15486 : 0 : : gen_xgetbv (op0, op2));
15487 : 22 : emit_insn (insn);
15488 : : }
15489 : 58 : else if (fcode == IX86_BUILTIN_RDTSC)
15490 : : {
15491 : 36 : insn = (TARGET_64BIT
15492 : 36 : ? gen_rdtsc_rex64 (op0, op1)
15493 : 2 : : gen_rdtsc (op0));
15494 : 36 : emit_insn (insn);
15495 : : }
15496 : : else
15497 : : {
15498 : 22 : op2 = gen_reg_rtx (SImode);
15499 : :
15500 : 22 : insn = (TARGET_64BIT
15501 : 22 : ? gen_rdtscp_rex64 (op0, op1, op2)
15502 : 0 : : gen_rdtscp (op0, op2));
15503 : 22 : emit_insn (insn);
15504 : :
15505 : 22 : arg0 = CALL_EXPR_ARG (exp, 0);
15506 : 22 : op4 = expand_normal (arg0);
15507 : 22 : if (!address_operand (op4, VOIDmode))
15508 : : {
15509 : 10 : op4 = convert_memory_address (Pmode, op4);
15510 : 10 : op4 = copy_addr_to_reg (op4);
15511 : : }
15512 : 22 : emit_move_insn (gen_rtx_MEM (SImode, op4), op2);
15513 : : }
15514 : :
15515 : 102 : if (target == 0
15516 : 102 : || !register_operand (target, DImode))
15517 : 10 : target = gen_reg_rtx (DImode);
15518 : :
15519 : 102 : if (TARGET_64BIT)
15520 : : {
15521 : 100 : op1 = expand_simple_binop (DImode, ASHIFT, op1, GEN_INT (32),
15522 : : op1, 1, OPTAB_DIRECT);
15523 : 100 : op0 = expand_simple_binop (DImode, IOR, op0, op1,
15524 : : op0, 1, OPTAB_DIRECT);
15525 : : }
15526 : :
15527 : 102 : emit_move_insn (target, op0);
15528 : 102 : return target;
15529 : :
15530 : 62 : case IX86_BUILTIN_ENQCMD:
15531 : 62 : case IX86_BUILTIN_ENQCMDS:
15532 : 62 : case IX86_BUILTIN_MOVDIR64B:
15533 : :
15534 : 62 : arg0 = CALL_EXPR_ARG (exp, 0);
15535 : 62 : arg1 = CALL_EXPR_ARG (exp, 1);
15536 : 62 : op0 = expand_normal (arg0);
15537 : 62 : op1 = expand_normal (arg1);
15538 : :
15539 : 62 : op0 = ix86_zero_extend_to_Pmode (op0);
15540 : 62 : if (!address_operand (op1, VOIDmode))
15541 : : {
15542 : 29 : op1 = convert_memory_address (Pmode, op1);
15543 : 29 : op1 = copy_addr_to_reg (op1);
15544 : : }
15545 : 62 : op1 = gen_rtx_MEM (XImode, op1);
15546 : :
15547 : 62 : if (fcode == IX86_BUILTIN_MOVDIR64B)
15548 : : {
15549 : 25 : emit_insn (gen_movdir64b (Pmode, op0, op1));
15550 : 24 : return 0;
15551 : : }
15552 : : else
15553 : : {
15554 : 38 : if (target == 0
15555 : 38 : || !register_operand (target, SImode))
15556 : 0 : target = gen_reg_rtx (SImode);
15557 : :
15558 : 38 : emit_move_insn (target, const0_rtx);
15559 : 38 : target = gen_rtx_SUBREG (QImode, target, 0);
15560 : :
15561 : 19 : int unspecv = (fcode == IX86_BUILTIN_ENQCMD
15562 : 38 : ? UNSPECV_ENQCMD
15563 : : : UNSPECV_ENQCMDS);
15564 : 38 : icode = code_for_enqcmd (unspecv, Pmode);
15565 : 38 : emit_insn (GEN_FCN (icode) (op0, op1));
15566 : :
15567 : 38 : emit_insn
15568 : 38 : (gen_rtx_SET (gen_rtx_STRICT_LOW_PART (VOIDmode, target),
15569 : : gen_rtx_fmt_ee (EQ, QImode,
15570 : : gen_rtx_REG (CCZmode, FLAGS_REG),
15571 : : const0_rtx)));
15572 : 38 : return SUBREG_REG (target);
15573 : : }
15574 : :
15575 : 14775 : case IX86_BUILTIN_FXSAVE:
15576 : 14775 : case IX86_BUILTIN_FXRSTOR:
15577 : 14775 : case IX86_BUILTIN_FXSAVE64:
15578 : 14775 : case IX86_BUILTIN_FXRSTOR64:
15579 : 14775 : case IX86_BUILTIN_FNSTENV:
15580 : 14775 : case IX86_BUILTIN_FLDENV:
15581 : 14775 : mode0 = BLKmode;
15582 : 14775 : switch (fcode)
15583 : : {
15584 : : case IX86_BUILTIN_FXSAVE:
15585 : : icode = CODE_FOR_fxsave;
15586 : : break;
15587 : 19 : case IX86_BUILTIN_FXRSTOR:
15588 : 19 : icode = CODE_FOR_fxrstor;
15589 : 19 : break;
15590 : 23 : case IX86_BUILTIN_FXSAVE64:
15591 : 23 : icode = CODE_FOR_fxsave64;
15592 : 23 : break;
15593 : 21 : case IX86_BUILTIN_FXRSTOR64:
15594 : 21 : icode = CODE_FOR_fxrstor64;
15595 : 21 : break;
15596 : 7257 : case IX86_BUILTIN_FNSTENV:
15597 : 7257 : icode = CODE_FOR_fnstenv;
15598 : 7257 : break;
15599 : 7435 : case IX86_BUILTIN_FLDENV:
15600 : 7435 : icode = CODE_FOR_fldenv;
15601 : 7435 : break;
15602 : 0 : default:
15603 : 0 : gcc_unreachable ();
15604 : : }
15605 : :
15606 : 14775 : arg0 = CALL_EXPR_ARG (exp, 0);
15607 : 14775 : op0 = expand_normal (arg0);
15608 : :
15609 : 14775 : if (!address_operand (op0, VOIDmode))
15610 : : {
15611 : 36 : op0 = convert_memory_address (Pmode, op0);
15612 : 36 : op0 = copy_addr_to_reg (op0);
15613 : : }
15614 : 14775 : op0 = gen_rtx_MEM (mode0, op0);
15615 : :
15616 : 14775 : pat = GEN_FCN (icode) (op0);
15617 : 14775 : if (pat)
15618 : 14775 : emit_insn (pat);
15619 : : return 0;
15620 : :
15621 : 21 : case IX86_BUILTIN_XSETBV:
15622 : 21 : arg0 = CALL_EXPR_ARG (exp, 0);
15623 : 21 : arg1 = CALL_EXPR_ARG (exp, 1);
15624 : 21 : op0 = expand_normal (arg0);
15625 : 21 : op1 = expand_normal (arg1);
15626 : :
15627 : 21 : if (!REG_P (op0))
15628 : 1 : op0 = copy_to_mode_reg (SImode, op0);
15629 : :
15630 : 21 : op1 = force_reg (DImode, op1);
15631 : :
15632 : 21 : if (TARGET_64BIT)
15633 : : {
15634 : 21 : op2 = expand_simple_binop (DImode, LSHIFTRT, op1, GEN_INT (32),
15635 : : NULL, 1, OPTAB_DIRECT);
15636 : :
15637 : 21 : icode = CODE_FOR_xsetbv_rex64;
15638 : :
15639 : 21 : op2 = gen_lowpart (SImode, op2);
15640 : 21 : op1 = gen_lowpart (SImode, op1);
15641 : 21 : pat = GEN_FCN (icode) (op0, op1, op2);
15642 : : }
15643 : : else
15644 : : {
15645 : 0 : icode = CODE_FOR_xsetbv;
15646 : :
15647 : 0 : pat = GEN_FCN (icode) (op0, op1);
15648 : : }
15649 : 21 : if (pat)
15650 : 21 : emit_insn (pat);
15651 : : return 0;
15652 : :
15653 : 232 : case IX86_BUILTIN_XSAVE:
15654 : 232 : case IX86_BUILTIN_XRSTOR:
15655 : 232 : case IX86_BUILTIN_XSAVE64:
15656 : 232 : case IX86_BUILTIN_XRSTOR64:
15657 : 232 : case IX86_BUILTIN_XSAVEOPT:
15658 : 232 : case IX86_BUILTIN_XSAVEOPT64:
15659 : 232 : case IX86_BUILTIN_XSAVES:
15660 : 232 : case IX86_BUILTIN_XRSTORS:
15661 : 232 : case IX86_BUILTIN_XSAVES64:
15662 : 232 : case IX86_BUILTIN_XRSTORS64:
15663 : 232 : case IX86_BUILTIN_XSAVEC:
15664 : 232 : case IX86_BUILTIN_XSAVEC64:
15665 : 232 : arg0 = CALL_EXPR_ARG (exp, 0);
15666 : 232 : arg1 = CALL_EXPR_ARG (exp, 1);
15667 : 232 : op0 = expand_normal (arg0);
15668 : 232 : op1 = expand_normal (arg1);
15669 : :
15670 : 232 : if (!address_operand (op0, VOIDmode))
15671 : : {
15672 : 108 : op0 = convert_memory_address (Pmode, op0);
15673 : 108 : op0 = copy_addr_to_reg (op0);
15674 : : }
15675 : 232 : op0 = gen_rtx_MEM (BLKmode, op0);
15676 : :
15677 : 232 : op1 = force_reg (DImode, op1);
15678 : :
15679 : 232 : if (TARGET_64BIT)
15680 : : {
15681 : 232 : op2 = expand_simple_binop (DImode, LSHIFTRT, op1, GEN_INT (32),
15682 : : NULL, 1, OPTAB_DIRECT);
15683 : 232 : switch (fcode)
15684 : : {
15685 : : case IX86_BUILTIN_XSAVE:
15686 : : icode = CODE_FOR_xsave_rex64;
15687 : : break;
15688 : 19 : case IX86_BUILTIN_XRSTOR:
15689 : 19 : icode = CODE_FOR_xrstor_rex64;
15690 : 19 : break;
15691 : 21 : case IX86_BUILTIN_XSAVE64:
15692 : 21 : icode = CODE_FOR_xsave64;
15693 : 21 : break;
15694 : 21 : case IX86_BUILTIN_XRSTOR64:
15695 : 21 : icode = CODE_FOR_xrstor64;
15696 : 21 : break;
15697 : 19 : case IX86_BUILTIN_XSAVEOPT:
15698 : 19 : icode = CODE_FOR_xsaveopt_rex64;
15699 : 19 : break;
15700 : 19 : case IX86_BUILTIN_XSAVEOPT64:
15701 : 19 : icode = CODE_FOR_xsaveopt64;
15702 : 19 : break;
15703 : 19 : case IX86_BUILTIN_XSAVES:
15704 : 19 : icode = CODE_FOR_xsaves_rex64;
15705 : 19 : break;
15706 : 19 : case IX86_BUILTIN_XRSTORS:
15707 : 19 : icode = CODE_FOR_xrstors_rex64;
15708 : 19 : break;
15709 : 19 : case IX86_BUILTIN_XSAVES64:
15710 : 19 : icode = CODE_FOR_xsaves64;
15711 : 19 : break;
15712 : 19 : case IX86_BUILTIN_XRSTORS64:
15713 : 19 : icode = CODE_FOR_xrstors64;
15714 : 19 : break;
15715 : 19 : case IX86_BUILTIN_XSAVEC:
15716 : 19 : icode = CODE_FOR_xsavec_rex64;
15717 : 19 : break;
15718 : 19 : case IX86_BUILTIN_XSAVEC64:
15719 : 19 : icode = CODE_FOR_xsavec64;
15720 : 19 : break;
15721 : 0 : default:
15722 : 0 : gcc_unreachable ();
15723 : : }
15724 : :
15725 : 232 : op2 = gen_lowpart (SImode, op2);
15726 : 232 : op1 = gen_lowpart (SImode, op1);
15727 : 232 : pat = GEN_FCN (icode) (op0, op1, op2);
15728 : : }
15729 : : else
15730 : : {
15731 : 0 : switch (fcode)
15732 : : {
15733 : : case IX86_BUILTIN_XSAVE:
15734 : : icode = CODE_FOR_xsave;
15735 : : break;
15736 : : case IX86_BUILTIN_XRSTOR:
15737 : : icode = CODE_FOR_xrstor;
15738 : : break;
15739 : : case IX86_BUILTIN_XSAVEOPT:
15740 : : icode = CODE_FOR_xsaveopt;
15741 : : break;
15742 : : case IX86_BUILTIN_XSAVES:
15743 : : icode = CODE_FOR_xsaves;
15744 : : break;
15745 : : case IX86_BUILTIN_XRSTORS:
15746 : : icode = CODE_FOR_xrstors;
15747 : : break;
15748 : : case IX86_BUILTIN_XSAVEC:
15749 : : icode = CODE_FOR_xsavec;
15750 : : break;
15751 : 0 : default:
15752 : 0 : gcc_unreachable ();
15753 : : }
15754 : 0 : pat = GEN_FCN (icode) (op0, op1);
15755 : : }
15756 : :
15757 : 232 : if (pat)
15758 : 232 : emit_insn (pat);
15759 : : return 0;
15760 : :
15761 : 144 : case IX86_BUILTIN_LDTILECFG:
15762 : 144 : case IX86_BUILTIN_STTILECFG:
15763 : 144 : arg0 = CALL_EXPR_ARG (exp, 0);
15764 : 144 : op0 = expand_normal (arg0);
15765 : :
15766 : 144 : if (!address_operand (op0, VOIDmode))
15767 : : {
15768 : 8 : op0 = convert_memory_address (Pmode, op0);
15769 : 8 : op0 = copy_addr_to_reg (op0);
15770 : : }
15771 : 144 : op0 = gen_rtx_MEM (BLKmode, op0);
15772 : 144 : if (fcode == IX86_BUILTIN_LDTILECFG)
15773 : : icode = CODE_FOR_ldtilecfg;
15774 : : else
15775 : 93 : icode = CODE_FOR_sttilecfg;
15776 : 144 : pat = GEN_FCN (icode) (op0);
15777 : 144 : emit_insn (pat);
15778 : 144 : return 0;
15779 : :
15780 : 18 : case IX86_BUILTIN_LLWPCB:
15781 : 18 : arg0 = CALL_EXPR_ARG (exp, 0);
15782 : 18 : op0 = expand_normal (arg0);
15783 : :
15784 : 18 : if (!register_operand (op0, Pmode))
15785 : 9 : op0 = ix86_zero_extend_to_Pmode (op0);
15786 : 18 : emit_insn (gen_lwp_llwpcb (Pmode, op0));
15787 : 18 : return 0;
15788 : :
15789 : 18 : case IX86_BUILTIN_SLWPCB:
15790 : 18 : if (!target
15791 : 18 : || !register_operand (target, Pmode))
15792 : 0 : target = gen_reg_rtx (Pmode);
15793 : 18 : emit_insn (gen_lwp_slwpcb (Pmode, target));
15794 : 18 : return target;
15795 : :
15796 : 51 : case IX86_BUILTIN_LWPVAL32:
15797 : 51 : case IX86_BUILTIN_LWPVAL64:
15798 : 51 : case IX86_BUILTIN_LWPINS32:
15799 : 51 : case IX86_BUILTIN_LWPINS64:
15800 : 51 : mode = ((fcode == IX86_BUILTIN_LWPVAL32
15801 : 51 : || fcode == IX86_BUILTIN_LWPINS32)
15802 : 51 : ? SImode : DImode);
15803 : :
15804 : 51 : if (fcode == IX86_BUILTIN_LWPVAL32
15805 : 51 : || fcode == IX86_BUILTIN_LWPVAL64)
15806 : 26 : icode = code_for_lwp_lwpval (mode);
15807 : : else
15808 : 25 : icode = code_for_lwp_lwpins (mode);
15809 : :
15810 : 51 : arg0 = CALL_EXPR_ARG (exp, 0);
15811 : 51 : arg1 = CALL_EXPR_ARG (exp, 1);
15812 : 51 : arg2 = CALL_EXPR_ARG (exp, 2);
15813 : 51 : op0 = expand_normal (arg0);
15814 : 51 : op1 = expand_normal (arg1);
15815 : 51 : op2 = expand_normal (arg2);
15816 : 51 : mode0 = insn_data[icode].operand[0].mode;
15817 : :
15818 : 51 : if (!insn_data[icode].operand[0].predicate (op0, mode0))
15819 : 13 : op0 = copy_to_mode_reg (mode0, op0);
15820 : 51 : if (!insn_data[icode].operand[1].predicate (op1, SImode))
15821 : 0 : op1 = copy_to_mode_reg (SImode, op1);
15822 : :
15823 : 51 : if (!CONST_INT_P (op2))
15824 : : {
15825 : 0 : error ("the last argument must be a 32-bit immediate");
15826 : 0 : return const0_rtx;
15827 : : }
15828 : :
15829 : 51 : emit_insn (GEN_FCN (icode) (op0, op1, op2));
15830 : :
15831 : 51 : if (fcode == IX86_BUILTIN_LWPINS32
15832 : 51 : || fcode == IX86_BUILTIN_LWPINS64)
15833 : : {
15834 : 25 : if (target == 0
15835 : 25 : || !nonimmediate_operand (target, QImode))
15836 : 0 : target = gen_reg_rtx (QImode);
15837 : :
15838 : 25 : pat = gen_rtx_EQ (QImode, gen_rtx_REG (CCCmode, FLAGS_REG),
15839 : : const0_rtx);
15840 : 25 : emit_insn (gen_rtx_SET (target, pat));
15841 : :
15842 : 25 : return target;
15843 : : }
15844 : : else
15845 : : return 0;
15846 : :
15847 : 18 : case IX86_BUILTIN_BEXTRI32:
15848 : 18 : case IX86_BUILTIN_BEXTRI64:
15849 : 18 : mode = (fcode == IX86_BUILTIN_BEXTRI32 ? SImode : DImode);
15850 : :
15851 : 18 : arg0 = CALL_EXPR_ARG (exp, 0);
15852 : 18 : arg1 = CALL_EXPR_ARG (exp, 1);
15853 : 18 : op0 = expand_normal (arg0);
15854 : 18 : op1 = expand_normal (arg1);
15855 : :
15856 : 18 : if (!CONST_INT_P (op1))
15857 : : {
15858 : 0 : error ("last argument must be an immediate");
15859 : 0 : return const0_rtx;
15860 : : }
15861 : : else
15862 : : {
15863 : 18 : unsigned char lsb_index = UINTVAL (op1);
15864 : 18 : unsigned char length = UINTVAL (op1) >> 8;
15865 : :
15866 : 18 : unsigned char bitsize = GET_MODE_BITSIZE (mode);
15867 : :
15868 : 18 : icode = code_for_tbm_bextri (mode);
15869 : :
15870 : 18 : mode1 = insn_data[icode].operand[1].mode;
15871 : 18 : if (!insn_data[icode].operand[1].predicate (op0, mode1))
15872 : 12 : op0 = copy_to_mode_reg (mode1, op0);
15873 : :
15874 : 18 : mode0 = insn_data[icode].operand[0].mode;
15875 : 18 : if (target == 0
15876 : 18 : || !register_operand (target, mode0))
15877 : 0 : target = gen_reg_rtx (mode0);
15878 : :
15879 : 18 : if (length == 0 || lsb_index >= bitsize)
15880 : : {
15881 : 8 : emit_move_insn (target, const0_rtx);
15882 : 8 : return target;
15883 : : }
15884 : :
15885 : 10 : if (length + lsb_index > bitsize)
15886 : 5 : length = bitsize - lsb_index;
15887 : :
15888 : 10 : op1 = GEN_INT (length);
15889 : 10 : op2 = GEN_INT (lsb_index);
15890 : :
15891 : 10 : emit_insn (GEN_FCN (icode) (target, op0, op1, op2));
15892 : 10 : return target;
15893 : : }
15894 : :
15895 : 21 : case IX86_BUILTIN_RDRAND16_STEP:
15896 : 21 : mode = HImode;
15897 : 21 : goto rdrand_step;
15898 : :
15899 : 42 : case IX86_BUILTIN_RDRAND32_STEP:
15900 : 42 : mode = SImode;
15901 : 42 : goto rdrand_step;
15902 : :
15903 : : case IX86_BUILTIN_RDRAND64_STEP:
15904 : : mode = DImode;
15905 : :
15906 : 83 : rdrand_step:
15907 : 83 : arg0 = CALL_EXPR_ARG (exp, 0);
15908 : 83 : op1 = expand_normal (arg0);
15909 : 83 : if (!address_operand (op1, VOIDmode))
15910 : : {
15911 : 29 : op1 = convert_memory_address (Pmode, op1);
15912 : 29 : op1 = copy_addr_to_reg (op1);
15913 : : }
15914 : :
15915 : 83 : op0 = gen_reg_rtx (mode);
15916 : 83 : emit_insn (gen_rdrand (mode, op0));
15917 : :
15918 : 83 : emit_move_insn (gen_rtx_MEM (mode, op1), op0);
15919 : :
15920 : 83 : op1 = force_reg (SImode, const1_rtx);
15921 : :
15922 : : /* Emit SImode conditional move. */
15923 : 83 : if (mode == HImode)
15924 : : {
15925 : 21 : if (TARGET_ZERO_EXTEND_WITH_AND
15926 : 21 : && optimize_function_for_speed_p (cfun))
15927 : : {
15928 : 0 : op2 = force_reg (SImode, const0_rtx);
15929 : :
15930 : 0 : emit_insn (gen_movstricthi
15931 : 0 : (gen_lowpart (HImode, op2), op0));
15932 : : }
15933 : : else
15934 : : {
15935 : 21 : op2 = gen_reg_rtx (SImode);
15936 : :
15937 : 21 : emit_insn (gen_zero_extendhisi2 (op2, op0));
15938 : : }
15939 : : }
15940 : 62 : else if (mode == SImode)
15941 : : op2 = op0;
15942 : : else
15943 : 20 : op2 = gen_rtx_SUBREG (SImode, op0, 0);
15944 : :
15945 : 83 : if (target == 0
15946 : 83 : || !register_operand (target, SImode))
15947 : 7 : target = gen_reg_rtx (SImode);
15948 : :
15949 : 83 : pat = gen_rtx_GEU (VOIDmode, gen_rtx_REG (CCCmode, FLAGS_REG),
15950 : : const0_rtx);
15951 : 83 : emit_insn (gen_rtx_SET (target,
15952 : : gen_rtx_IF_THEN_ELSE (SImode, pat, op2, op1)));
15953 : 83 : return target;
15954 : :
15955 : 19 : case IX86_BUILTIN_RDSEED16_STEP:
15956 : 19 : mode = HImode;
15957 : 19 : goto rdseed_step;
15958 : :
15959 : 28 : case IX86_BUILTIN_RDSEED32_STEP:
15960 : 28 : mode = SImode;
15961 : 28 : goto rdseed_step;
15962 : :
15963 : : case IX86_BUILTIN_RDSEED64_STEP:
15964 : : mode = DImode;
15965 : :
15966 : 66 : rdseed_step:
15967 : 66 : arg0 = CALL_EXPR_ARG (exp, 0);
15968 : 66 : op1 = expand_normal (arg0);
15969 : 66 : if (!address_operand (op1, VOIDmode))
15970 : : {
15971 : 28 : op1 = convert_memory_address (Pmode, op1);
15972 : 28 : op1 = copy_addr_to_reg (op1);
15973 : : }
15974 : :
15975 : 66 : op0 = gen_reg_rtx (mode);
15976 : 66 : emit_insn (gen_rdseed (mode, op0));
15977 : :
15978 : 66 : emit_move_insn (gen_rtx_MEM (mode, op1), op0);
15979 : :
15980 : 66 : op2 = gen_reg_rtx (QImode);
15981 : :
15982 : 66 : pat = gen_rtx_LTU (QImode, gen_rtx_REG (CCCmode, FLAGS_REG),
15983 : : const0_rtx);
15984 : 66 : emit_insn (gen_rtx_SET (op2, pat));
15985 : :
15986 : 66 : if (target == 0
15987 : 66 : || !register_operand (target, SImode))
15988 : 1 : target = gen_reg_rtx (SImode);
15989 : :
15990 : 66 : emit_insn (gen_zero_extendqisi2 (target, op2));
15991 : 66 : return target;
15992 : :
15993 : 38 : case IX86_BUILTIN_SBB32:
15994 : 38 : icode = CODE_FOR_subborrowsi;
15995 : 38 : icode2 = CODE_FOR_subborrowsi_0;
15996 : 38 : mode0 = SImode;
15997 : 38 : mode1 = DImode;
15998 : 38 : mode2 = CCmode;
15999 : 38 : goto handlecarry;
16000 : :
16001 : 44 : case IX86_BUILTIN_SBB64:
16002 : 44 : icode = CODE_FOR_subborrowdi;
16003 : 44 : icode2 = CODE_FOR_subborrowdi_0;
16004 : 44 : mode0 = DImode;
16005 : 44 : mode1 = TImode;
16006 : 44 : mode2 = CCmode;
16007 : 44 : goto handlecarry;
16008 : :
16009 : 68 : case IX86_BUILTIN_ADDCARRYX32:
16010 : 68 : icode = CODE_FOR_addcarrysi;
16011 : 68 : icode2 = CODE_FOR_addcarrysi_0;
16012 : 68 : mode0 = SImode;
16013 : 68 : mode1 = DImode;
16014 : 68 : mode2 = CCCmode;
16015 : 68 : goto handlecarry;
16016 : :
16017 : : case IX86_BUILTIN_ADDCARRYX64:
16018 : : icode = CODE_FOR_addcarrydi;
16019 : : icode2 = CODE_FOR_addcarrydi_0;
16020 : : mode0 = DImode;
16021 : : mode1 = TImode;
16022 : : mode2 = CCCmode;
16023 : :
16024 : 212 : handlecarry:
16025 : 212 : arg0 = CALL_EXPR_ARG (exp, 0); /* unsigned char c_in. */
16026 : 212 : arg1 = CALL_EXPR_ARG (exp, 1); /* unsigned int src1. */
16027 : 212 : arg2 = CALL_EXPR_ARG (exp, 2); /* unsigned int src2. */
16028 : 212 : arg3 = CALL_EXPR_ARG (exp, 3); /* unsigned int *sum_out. */
16029 : :
16030 : 212 : op1 = expand_normal (arg0);
16031 : :
16032 : 212 : op2 = expand_normal (arg1);
16033 : 212 : if (!register_operand (op2, mode0))
16034 : 117 : op2 = copy_to_mode_reg (mode0, op2);
16035 : :
16036 : 212 : op3 = expand_normal (arg2);
16037 : 212 : if (!register_operand (op3, mode0))
16038 : 120 : op3 = copy_to_mode_reg (mode0, op3);
16039 : :
16040 : 212 : op4 = expand_normal (arg3);
16041 : 212 : if (!address_operand (op4, VOIDmode))
16042 : : {
16043 : 67 : op4 = convert_memory_address (Pmode, op4);
16044 : 67 : op4 = copy_addr_to_reg (op4);
16045 : : }
16046 : :
16047 : 212 : op0 = gen_reg_rtx (mode0);
16048 : 212 : if (op1 == const0_rtx)
16049 : : {
16050 : : /* If arg0 is 0, optimize right away into add or sub
16051 : : instruction that sets CCCmode flags. */
16052 : 21 : op1 = gen_rtx_REG (mode2, FLAGS_REG);
16053 : 21 : emit_insn (GEN_FCN (icode2) (op0, op2, op3));
16054 : : }
16055 : : else
16056 : : {
16057 : : /* Generate CF from input operand. */
16058 : 191 : ix86_expand_carry (op1);
16059 : :
16060 : : /* Generate instruction that consumes CF. */
16061 : 191 : op1 = gen_rtx_REG (CCCmode, FLAGS_REG);
16062 : 191 : pat = gen_rtx_LTU (mode1, op1, const0_rtx);
16063 : 191 : pat2 = gen_rtx_LTU (mode0, op1, const0_rtx);
16064 : 191 : emit_insn (GEN_FCN (icode) (op0, op2, op3, op1, pat, pat2));
16065 : : }
16066 : :
16067 : : /* Return current CF value. */
16068 : 212 : if (target == 0)
16069 : 14 : target = gen_reg_rtx (QImode);
16070 : :
16071 : 212 : pat = gen_rtx_LTU (QImode, op1, const0_rtx);
16072 : 212 : emit_insn (gen_rtx_SET (target, pat));
16073 : :
16074 : : /* Store the result. */
16075 : 212 : emit_move_insn (gen_rtx_MEM (mode0, op4), op0);
16076 : :
16077 : 212 : return target;
16078 : :
16079 : 24 : case IX86_BUILTIN_READ_FLAGS:
16080 : 24 : if (ignore)
16081 : 1 : return const0_rtx;
16082 : :
16083 : 23 : emit_insn (gen_pushfl ());
16084 : :
16085 : 23 : if (optimize
16086 : 11 : || target == NULL_RTX
16087 : 11 : || !nonimmediate_operand (target, word_mode)
16088 : 34 : || GET_MODE (target) != word_mode)
16089 : 12 : target = gen_reg_rtx (word_mode);
16090 : :
16091 : 23 : emit_insn (gen_pop (target));
16092 : 23 : return target;
16093 : :
16094 : 21 : case IX86_BUILTIN_WRITE_FLAGS:
16095 : :
16096 : 21 : arg0 = CALL_EXPR_ARG (exp, 0);
16097 : 21 : op0 = expand_normal (arg0);
16098 : 21 : if (!general_no_elim_operand (op0, word_mode))
16099 : 0 : op0 = copy_to_mode_reg (word_mode, op0);
16100 : :
16101 : 21 : emit_insn (gen_push (op0));
16102 : 21 : emit_insn (gen_popfl ());
16103 : 21 : return 0;
16104 : :
16105 : 22 : case IX86_BUILTIN_KTESTC8:
16106 : 22 : icode = CODE_FOR_ktestqi;
16107 : 22 : mode3 = CCCmode;
16108 : 22 : goto kortest;
16109 : :
16110 : 22 : case IX86_BUILTIN_KTESTZ8:
16111 : 22 : icode = CODE_FOR_ktestqi;
16112 : 22 : mode3 = CCZmode;
16113 : 22 : goto kortest;
16114 : :
16115 : 22 : case IX86_BUILTIN_KTESTC16:
16116 : 22 : icode = CODE_FOR_ktesthi;
16117 : 22 : mode3 = CCCmode;
16118 : 22 : goto kortest;
16119 : :
16120 : 22 : case IX86_BUILTIN_KTESTZ16:
16121 : 22 : icode = CODE_FOR_ktesthi;
16122 : 22 : mode3 = CCZmode;
16123 : 22 : goto kortest;
16124 : :
16125 : 22 : case IX86_BUILTIN_KTESTC32:
16126 : 22 : icode = CODE_FOR_ktestsi;
16127 : 22 : mode3 = CCCmode;
16128 : 22 : goto kortest;
16129 : :
16130 : 22 : case IX86_BUILTIN_KTESTZ32:
16131 : 22 : icode = CODE_FOR_ktestsi;
16132 : 22 : mode3 = CCZmode;
16133 : 22 : goto kortest;
16134 : :
16135 : 22 : case IX86_BUILTIN_KTESTC64:
16136 : 22 : icode = CODE_FOR_ktestdi;
16137 : 22 : mode3 = CCCmode;
16138 : 22 : goto kortest;
16139 : :
16140 : 22 : case IX86_BUILTIN_KTESTZ64:
16141 : 22 : icode = CODE_FOR_ktestdi;
16142 : 22 : mode3 = CCZmode;
16143 : 22 : goto kortest;
16144 : :
16145 : 22 : case IX86_BUILTIN_KORTESTC8:
16146 : 22 : icode = CODE_FOR_kortestqi;
16147 : 22 : mode3 = CCCmode;
16148 : 22 : goto kortest;
16149 : :
16150 : 76 : case IX86_BUILTIN_KORTESTZ8:
16151 : 76 : icode = CODE_FOR_kortestqi;
16152 : 76 : mode3 = CCZmode;
16153 : 76 : goto kortest;
16154 : :
16155 : 38 : case IX86_BUILTIN_KORTESTC16:
16156 : 38 : icode = CODE_FOR_kortesthi;
16157 : 38 : mode3 = CCCmode;
16158 : 38 : goto kortest;
16159 : :
16160 : 91 : case IX86_BUILTIN_KORTESTZ16:
16161 : 91 : icode = CODE_FOR_kortesthi;
16162 : 91 : mode3 = CCZmode;
16163 : 91 : goto kortest;
16164 : :
16165 : 22 : case IX86_BUILTIN_KORTESTC32:
16166 : 22 : icode = CODE_FOR_kortestsi;
16167 : 22 : mode3 = CCCmode;
16168 : 22 : goto kortest;
16169 : :
16170 : 79 : case IX86_BUILTIN_KORTESTZ32:
16171 : 79 : icode = CODE_FOR_kortestsi;
16172 : 79 : mode3 = CCZmode;
16173 : 79 : goto kortest;
16174 : :
16175 : 22 : case IX86_BUILTIN_KORTESTC64:
16176 : 22 : icode = CODE_FOR_kortestdi;
16177 : 22 : mode3 = CCCmode;
16178 : 22 : goto kortest;
16179 : :
16180 : : case IX86_BUILTIN_KORTESTZ64:
16181 : : icode = CODE_FOR_kortestdi;
16182 : : mode3 = CCZmode;
16183 : :
16184 : 610 : kortest:
16185 : 610 : arg0 = CALL_EXPR_ARG (exp, 0); /* Mask reg src1. */
16186 : 610 : arg1 = CALL_EXPR_ARG (exp, 1); /* Mask reg src2. */
16187 : 610 : op0 = expand_normal (arg0);
16188 : 610 : op1 = expand_normal (arg1);
16189 : :
16190 : 610 : mode0 = insn_data[icode].operand[0].mode;
16191 : 610 : mode1 = insn_data[icode].operand[1].mode;
16192 : :
16193 : 610 : if (GET_MODE (op0) != VOIDmode)
16194 : 610 : op0 = force_reg (GET_MODE (op0), op0);
16195 : :
16196 : 610 : op0 = gen_lowpart (mode0, op0);
16197 : :
16198 : 610 : if (!insn_data[icode].operand[0].predicate (op0, mode0))
16199 : 0 : op0 = copy_to_mode_reg (mode0, op0);
16200 : :
16201 : 610 : if (GET_MODE (op1) != VOIDmode)
16202 : 609 : op1 = force_reg (GET_MODE (op1), op1);
16203 : :
16204 : 610 : op1 = gen_lowpart (mode1, op1);
16205 : :
16206 : 610 : if (!insn_data[icode].operand[1].predicate (op1, mode1))
16207 : 1 : op1 = copy_to_mode_reg (mode1, op1);
16208 : :
16209 : 610 : target = gen_reg_rtx (QImode);
16210 : :
16211 : : /* Emit kortest. */
16212 : 610 : emit_insn (GEN_FCN (icode) (op0, op1));
16213 : : /* And use setcc to return result from flags. */
16214 : 610 : ix86_expand_setcc (target, EQ,
16215 : : gen_rtx_REG (mode3, FLAGS_REG), const0_rtx);
16216 : 610 : return target;
16217 : :
16218 : 24 : case IX86_BUILTIN_GATHERSIV2DF:
16219 : 24 : icode = CODE_FOR_avx2_gathersiv2df;
16220 : 24 : goto gather_gen;
16221 : 18 : case IX86_BUILTIN_GATHERSIV4DF:
16222 : 18 : icode = CODE_FOR_avx2_gathersiv4df;
16223 : 18 : goto gather_gen;
16224 : 21 : case IX86_BUILTIN_GATHERDIV2DF:
16225 : 21 : icode = CODE_FOR_avx2_gatherdiv2df;
16226 : 21 : goto gather_gen;
16227 : 32 : case IX86_BUILTIN_GATHERDIV4DF:
16228 : 32 : icode = CODE_FOR_avx2_gatherdiv4df;
16229 : 32 : goto gather_gen;
16230 : 30 : case IX86_BUILTIN_GATHERSIV4SF:
16231 : 30 : icode = CODE_FOR_avx2_gathersiv4sf;
16232 : 30 : goto gather_gen;
16233 : 37 : case IX86_BUILTIN_GATHERSIV8SF:
16234 : 37 : icode = CODE_FOR_avx2_gathersiv8sf;
16235 : 37 : goto gather_gen;
16236 : 24 : case IX86_BUILTIN_GATHERDIV4SF:
16237 : 24 : icode = CODE_FOR_avx2_gatherdiv4sf;
16238 : 24 : goto gather_gen;
16239 : 18 : case IX86_BUILTIN_GATHERDIV8SF:
16240 : 18 : icode = CODE_FOR_avx2_gatherdiv8sf;
16241 : 18 : goto gather_gen;
16242 : 18 : case IX86_BUILTIN_GATHERSIV2DI:
16243 : 18 : icode = CODE_FOR_avx2_gathersiv2di;
16244 : 18 : goto gather_gen;
16245 : 18 : case IX86_BUILTIN_GATHERSIV4DI:
16246 : 18 : icode = CODE_FOR_avx2_gathersiv4di;
16247 : 18 : goto gather_gen;
16248 : 27 : case IX86_BUILTIN_GATHERDIV2DI:
16249 : 27 : icode = CODE_FOR_avx2_gatherdiv2di;
16250 : 27 : goto gather_gen;
16251 : 29 : case IX86_BUILTIN_GATHERDIV4DI:
16252 : 29 : icode = CODE_FOR_avx2_gatherdiv4di;
16253 : 29 : goto gather_gen;
16254 : 20 : case IX86_BUILTIN_GATHERSIV4SI:
16255 : 20 : icode = CODE_FOR_avx2_gathersiv4si;
16256 : 20 : goto gather_gen;
16257 : 22 : case IX86_BUILTIN_GATHERSIV8SI:
16258 : 22 : icode = CODE_FOR_avx2_gathersiv8si;
16259 : 22 : goto gather_gen;
16260 : 28 : case IX86_BUILTIN_GATHERDIV4SI:
16261 : 28 : icode = CODE_FOR_avx2_gatherdiv4si;
16262 : 28 : goto gather_gen;
16263 : 18 : case IX86_BUILTIN_GATHERDIV8SI:
16264 : 18 : icode = CODE_FOR_avx2_gatherdiv8si;
16265 : 18 : goto gather_gen;
16266 : 20 : case IX86_BUILTIN_GATHERALTSIV4DF:
16267 : 20 : icode = CODE_FOR_avx2_gathersiv4df;
16268 : 20 : goto gather_gen;
16269 : 16 : case IX86_BUILTIN_GATHERALTDIV8SF:
16270 : 16 : icode = CODE_FOR_avx2_gatherdiv8sf;
16271 : 16 : goto gather_gen;
16272 : 4 : case IX86_BUILTIN_GATHERALTSIV4DI:
16273 : 4 : icode = CODE_FOR_avx2_gathersiv4di;
16274 : 4 : goto gather_gen;
16275 : 12 : case IX86_BUILTIN_GATHERALTDIV8SI:
16276 : 12 : icode = CODE_FOR_avx2_gatherdiv8si;
16277 : 12 : goto gather_gen;
16278 : 36 : case IX86_BUILTIN_GATHER3SIV16SF:
16279 : 36 : icode = CODE_FOR_avx512f_gathersiv16sf;
16280 : 36 : goto gather_gen;
16281 : 24 : case IX86_BUILTIN_GATHER3SIV8DF:
16282 : 24 : icode = CODE_FOR_avx512f_gathersiv8df;
16283 : 24 : goto gather_gen;
16284 : 24 : case IX86_BUILTIN_GATHER3DIV16SF:
16285 : 24 : icode = CODE_FOR_avx512f_gatherdiv16sf;
16286 : 24 : goto gather_gen;
16287 : 37 : case IX86_BUILTIN_GATHER3DIV8DF:
16288 : 37 : icode = CODE_FOR_avx512f_gatherdiv8df;
16289 : 37 : goto gather_gen;
16290 : 30 : case IX86_BUILTIN_GATHER3SIV16SI:
16291 : 30 : icode = CODE_FOR_avx512f_gathersiv16si;
16292 : 30 : goto gather_gen;
16293 : 24 : case IX86_BUILTIN_GATHER3SIV8DI:
16294 : 24 : icode = CODE_FOR_avx512f_gathersiv8di;
16295 : 24 : goto gather_gen;
16296 : 24 : case IX86_BUILTIN_GATHER3DIV16SI:
16297 : 24 : icode = CODE_FOR_avx512f_gatherdiv16si;
16298 : 24 : goto gather_gen;
16299 : 37 : case IX86_BUILTIN_GATHER3DIV8DI:
16300 : 37 : icode = CODE_FOR_avx512f_gatherdiv8di;
16301 : 37 : goto gather_gen;
16302 : 16 : case IX86_BUILTIN_GATHER3ALTSIV8DF:
16303 : 16 : icode = CODE_FOR_avx512f_gathersiv8df;
16304 : 16 : goto gather_gen;
16305 : 22 : case IX86_BUILTIN_GATHER3ALTDIV16SF:
16306 : 22 : icode = CODE_FOR_avx512f_gatherdiv16sf;
16307 : 22 : goto gather_gen;
16308 : 14 : case IX86_BUILTIN_GATHER3ALTSIV8DI:
16309 : 14 : icode = CODE_FOR_avx512f_gathersiv8di;
16310 : 14 : goto gather_gen;
16311 : 18 : case IX86_BUILTIN_GATHER3ALTDIV16SI:
16312 : 18 : icode = CODE_FOR_avx512f_gatherdiv16si;
16313 : 18 : goto gather_gen;
16314 : 18 : case IX86_BUILTIN_GATHER3SIV2DF:
16315 : 18 : icode = CODE_FOR_avx512vl_gathersiv2df;
16316 : 18 : goto gather_gen;
16317 : 10 : case IX86_BUILTIN_GATHER3SIV4DF:
16318 : 10 : icode = CODE_FOR_avx512vl_gathersiv4df;
16319 : 10 : goto gather_gen;
16320 : 15 : case IX86_BUILTIN_GATHER3DIV2DF:
16321 : 15 : icode = CODE_FOR_avx512vl_gatherdiv2df;
16322 : 15 : goto gather_gen;
16323 : 16 : case IX86_BUILTIN_GATHER3DIV4DF:
16324 : 16 : icode = CODE_FOR_avx512vl_gatherdiv4df;
16325 : 16 : goto gather_gen;
16326 : 14 : case IX86_BUILTIN_GATHER3SIV4SF:
16327 : 14 : icode = CODE_FOR_avx512vl_gathersiv4sf;
16328 : 14 : goto gather_gen;
16329 : 12 : case IX86_BUILTIN_GATHER3SIV8SF:
16330 : 12 : icode = CODE_FOR_avx512vl_gathersiv8sf;
16331 : 12 : goto gather_gen;
16332 : 22 : case IX86_BUILTIN_GATHER3DIV4SF:
16333 : 22 : icode = CODE_FOR_avx512vl_gatherdiv4sf;
16334 : 22 : goto gather_gen;
16335 : 10 : case IX86_BUILTIN_GATHER3DIV8SF:
16336 : 10 : icode = CODE_FOR_avx512vl_gatherdiv8sf;
16337 : 10 : goto gather_gen;
16338 : 20 : case IX86_BUILTIN_GATHER3SIV2DI:
16339 : 20 : icode = CODE_FOR_avx512vl_gathersiv2di;
16340 : 20 : goto gather_gen;
16341 : 10 : case IX86_BUILTIN_GATHER3SIV4DI:
16342 : 10 : icode = CODE_FOR_avx512vl_gathersiv4di;
16343 : 10 : goto gather_gen;
16344 : 14 : case IX86_BUILTIN_GATHER3DIV2DI:
16345 : 14 : icode = CODE_FOR_avx512vl_gatherdiv2di;
16346 : 14 : goto gather_gen;
16347 : 13 : case IX86_BUILTIN_GATHER3DIV4DI:
16348 : 13 : icode = CODE_FOR_avx512vl_gatherdiv4di;
16349 : 13 : goto gather_gen;
16350 : 14 : case IX86_BUILTIN_GATHER3SIV4SI:
16351 : 14 : icode = CODE_FOR_avx512vl_gathersiv4si;
16352 : 14 : goto gather_gen;
16353 : 12 : case IX86_BUILTIN_GATHER3SIV8SI:
16354 : 12 : icode = CODE_FOR_avx512vl_gathersiv8si;
16355 : 12 : goto gather_gen;
16356 : 24 : case IX86_BUILTIN_GATHER3DIV4SI:
16357 : 24 : icode = CODE_FOR_avx512vl_gatherdiv4si;
16358 : 24 : goto gather_gen;
16359 : 10 : case IX86_BUILTIN_GATHER3DIV8SI:
16360 : 10 : icode = CODE_FOR_avx512vl_gatherdiv8si;
16361 : 10 : goto gather_gen;
16362 : 4 : case IX86_BUILTIN_GATHER3ALTSIV4DF:
16363 : 4 : icode = CODE_FOR_avx512vl_gathersiv4df;
16364 : 4 : goto gather_gen;
16365 : 8 : case IX86_BUILTIN_GATHER3ALTDIV8SF:
16366 : 8 : icode = CODE_FOR_avx512vl_gatherdiv8sf;
16367 : 8 : goto gather_gen;
16368 : 6 : case IX86_BUILTIN_GATHER3ALTSIV4DI:
16369 : 6 : icode = CODE_FOR_avx512vl_gathersiv4di;
16370 : 6 : goto gather_gen;
16371 : 10 : case IX86_BUILTIN_GATHER3ALTDIV8SI:
16372 : 10 : icode = CODE_FOR_avx512vl_gatherdiv8si;
16373 : 10 : goto gather_gen;
16374 : 40 : case IX86_BUILTIN_SCATTERSIV16SF:
16375 : 40 : icode = CODE_FOR_avx512f_scattersiv16sf;
16376 : 40 : goto scatter_gen;
16377 : 27 : case IX86_BUILTIN_SCATTERSIV8DF:
16378 : 27 : icode = CODE_FOR_avx512f_scattersiv8df;
16379 : 27 : goto scatter_gen;
16380 : 24 : case IX86_BUILTIN_SCATTERDIV16SF:
16381 : 24 : icode = CODE_FOR_avx512f_scatterdiv16sf;
16382 : 24 : goto scatter_gen;
16383 : 33 : case IX86_BUILTIN_SCATTERDIV8DF:
16384 : 33 : icode = CODE_FOR_avx512f_scatterdiv8df;
16385 : 33 : goto scatter_gen;
16386 : 30 : case IX86_BUILTIN_SCATTERSIV16SI:
16387 : 30 : icode = CODE_FOR_avx512f_scattersiv16si;
16388 : 30 : goto scatter_gen;
16389 : 24 : case IX86_BUILTIN_SCATTERSIV8DI:
16390 : 24 : icode = CODE_FOR_avx512f_scattersiv8di;
16391 : 24 : goto scatter_gen;
16392 : 24 : case IX86_BUILTIN_SCATTERDIV16SI:
16393 : 24 : icode = CODE_FOR_avx512f_scatterdiv16si;
16394 : 24 : goto scatter_gen;
16395 : 29 : case IX86_BUILTIN_SCATTERDIV8DI:
16396 : 29 : icode = CODE_FOR_avx512f_scatterdiv8di;
16397 : 29 : goto scatter_gen;
16398 : 18 : case IX86_BUILTIN_SCATTERSIV8SF:
16399 : 18 : icode = CODE_FOR_avx512vl_scattersiv8sf;
16400 : 18 : goto scatter_gen;
16401 : 20 : case IX86_BUILTIN_SCATTERSIV4SF:
16402 : 20 : icode = CODE_FOR_avx512vl_scattersiv4sf;
16403 : 20 : goto scatter_gen;
16404 : 16 : case IX86_BUILTIN_SCATTERSIV4DF:
16405 : 16 : icode = CODE_FOR_avx512vl_scattersiv4df;
16406 : 16 : goto scatter_gen;
16407 : 16 : case IX86_BUILTIN_SCATTERSIV2DF:
16408 : 16 : icode = CODE_FOR_avx512vl_scattersiv2df;
16409 : 16 : goto scatter_gen;
16410 : 16 : case IX86_BUILTIN_SCATTERDIV8SF:
16411 : 16 : icode = CODE_FOR_avx512vl_scatterdiv8sf;
16412 : 16 : goto scatter_gen;
16413 : 16 : case IX86_BUILTIN_SCATTERDIV4SF:
16414 : 16 : icode = CODE_FOR_avx512vl_scatterdiv4sf;
16415 : 16 : goto scatter_gen;
16416 : 18 : case IX86_BUILTIN_SCATTERDIV4DF:
16417 : 18 : icode = CODE_FOR_avx512vl_scatterdiv4df;
16418 : 18 : goto scatter_gen;
16419 : 18 : case IX86_BUILTIN_SCATTERDIV2DF:
16420 : 18 : icode = CODE_FOR_avx512vl_scatterdiv2df;
16421 : 18 : goto scatter_gen;
16422 : 22 : case IX86_BUILTIN_SCATTERSIV8SI:
16423 : 22 : icode = CODE_FOR_avx512vl_scattersiv8si;
16424 : 22 : goto scatter_gen;
16425 : 24 : case IX86_BUILTIN_SCATTERSIV4SI:
16426 : 24 : icode = CODE_FOR_avx512vl_scattersiv4si;
16427 : 24 : goto scatter_gen;
16428 : 16 : case IX86_BUILTIN_SCATTERSIV4DI:
16429 : 16 : icode = CODE_FOR_avx512vl_scattersiv4di;
16430 : 16 : goto scatter_gen;
16431 : 16 : case IX86_BUILTIN_SCATTERSIV2DI:
16432 : 16 : icode = CODE_FOR_avx512vl_scattersiv2di;
16433 : 16 : goto scatter_gen;
16434 : 16 : case IX86_BUILTIN_SCATTERDIV8SI:
16435 : 16 : icode = CODE_FOR_avx512vl_scatterdiv8si;
16436 : 16 : goto scatter_gen;
16437 : 16 : case IX86_BUILTIN_SCATTERDIV4SI:
16438 : 16 : icode = CODE_FOR_avx512vl_scatterdiv4si;
16439 : 16 : goto scatter_gen;
16440 : 18 : case IX86_BUILTIN_SCATTERDIV4DI:
16441 : 18 : icode = CODE_FOR_avx512vl_scatterdiv4di;
16442 : 18 : goto scatter_gen;
16443 : 18 : case IX86_BUILTIN_SCATTERDIV2DI:
16444 : 18 : icode = CODE_FOR_avx512vl_scatterdiv2di;
16445 : 18 : goto scatter_gen;
16446 : 16 : case IX86_BUILTIN_SCATTERALTSIV8DF:
16447 : 16 : icode = CODE_FOR_avx512f_scattersiv8df;
16448 : 16 : goto scatter_gen;
16449 : 12 : case IX86_BUILTIN_SCATTERALTDIV16SF:
16450 : 12 : icode = CODE_FOR_avx512f_scatterdiv16sf;
16451 : 12 : goto scatter_gen;
16452 : 8 : case IX86_BUILTIN_SCATTERALTSIV8DI:
16453 : 8 : icode = CODE_FOR_avx512f_scattersiv8di;
16454 : 8 : goto scatter_gen;
16455 : 24 : case IX86_BUILTIN_SCATTERALTDIV16SI:
16456 : 24 : icode = CODE_FOR_avx512f_scatterdiv16si;
16457 : 24 : goto scatter_gen;
16458 : 4 : case IX86_BUILTIN_SCATTERALTSIV4DF:
16459 : 4 : icode = CODE_FOR_avx512vl_scattersiv4df;
16460 : 4 : goto scatter_gen;
16461 : 4 : case IX86_BUILTIN_SCATTERALTDIV8SF:
16462 : 4 : icode = CODE_FOR_avx512vl_scatterdiv8sf;
16463 : 4 : goto scatter_gen;
16464 : 4 : case IX86_BUILTIN_SCATTERALTSIV4DI:
16465 : 4 : icode = CODE_FOR_avx512vl_scattersiv4di;
16466 : 4 : goto scatter_gen;
16467 : 4 : case IX86_BUILTIN_SCATTERALTDIV8SI:
16468 : 4 : icode = CODE_FOR_avx512vl_scatterdiv8si;
16469 : 4 : goto scatter_gen;
16470 : 8 : case IX86_BUILTIN_SCATTERALTSIV2DF:
16471 : 8 : icode = CODE_FOR_avx512vl_scattersiv2df;
16472 : 8 : goto scatter_gen;
16473 : 8 : case IX86_BUILTIN_SCATTERALTDIV4SF:
16474 : 8 : icode = CODE_FOR_avx512vl_scatterdiv4sf;
16475 : 8 : goto scatter_gen;
16476 : 8 : case IX86_BUILTIN_SCATTERALTSIV2DI:
16477 : 8 : icode = CODE_FOR_avx512vl_scattersiv2di;
16478 : 8 : goto scatter_gen;
16479 : 8 : case IX86_BUILTIN_SCATTERALTDIV4SI:
16480 : 8 : icode = CODE_FOR_avx512vl_scatterdiv4si;
16481 : 8 : goto scatter_gen;
16482 : :
16483 : 1004 : gather_gen:
16484 : 1004 : rtx half;
16485 : 1004 : rtx (*gen) (rtx, rtx);
16486 : :
16487 : 1004 : arg0 = CALL_EXPR_ARG (exp, 0);
16488 : 1004 : arg1 = CALL_EXPR_ARG (exp, 1);
16489 : 1004 : arg2 = CALL_EXPR_ARG (exp, 2);
16490 : 1004 : arg3 = CALL_EXPR_ARG (exp, 3);
16491 : 1004 : arg4 = CALL_EXPR_ARG (exp, 4);
16492 : 1004 : op0 = expand_normal (arg0);
16493 : 1004 : op1 = expand_normal (arg1);
16494 : 1004 : op2 = expand_normal (arg2);
16495 : 1004 : op3 = ix86_expand_unsigned_small_int_cst_argument (arg3);
16496 : 1004 : op4 = expand_normal (arg4);
16497 : : /* Note the arg order is different from the operand order. */
16498 : 1004 : mode0 = insn_data[icode].operand[1].mode;
16499 : 1004 : mode2 = insn_data[icode].operand[3].mode;
16500 : 1004 : mode3 = insn_data[icode].operand[4].mode;
16501 : 1004 : mode4 = insn_data[icode].operand[5].mode;
16502 : :
16503 : 1004 : if (target == NULL_RTX
16504 : 1004 : || GET_MODE (target) != insn_data[icode].operand[0].mode
16505 : 1904 : || !insn_data[icode].operand[0].predicate (target,
16506 : : GET_MODE (target)))
16507 : 105 : subtarget = gen_reg_rtx (insn_data[icode].operand[0].mode);
16508 : : else
16509 : : subtarget = target;
16510 : :
16511 : 1004 : switch (fcode)
16512 : : {
16513 : 30 : case IX86_BUILTIN_GATHER3ALTSIV8DF:
16514 : 30 : case IX86_BUILTIN_GATHER3ALTSIV8DI:
16515 : 30 : half = gen_reg_rtx (V8SImode);
16516 : 30 : if (!nonimmediate_operand (op2, V16SImode))
16517 : 0 : op2 = copy_to_mode_reg (V16SImode, op2);
16518 : 30 : emit_insn (gen_vec_extract_lo_v16si (half, op2));
16519 : 30 : op2 = half;
16520 : 30 : break;
16521 : 34 : case IX86_BUILTIN_GATHER3ALTSIV4DF:
16522 : 34 : case IX86_BUILTIN_GATHER3ALTSIV4DI:
16523 : 34 : case IX86_BUILTIN_GATHERALTSIV4DF:
16524 : 34 : case IX86_BUILTIN_GATHERALTSIV4DI:
16525 : 34 : half = gen_reg_rtx (V4SImode);
16526 : 34 : if (!nonimmediate_operand (op2, V8SImode))
16527 : 0 : op2 = copy_to_mode_reg (V8SImode, op2);
16528 : 34 : emit_insn (gen_vec_extract_lo_v8si (half, op2));
16529 : 34 : op2 = half;
16530 : 34 : break;
16531 : 40 : case IX86_BUILTIN_GATHER3ALTDIV16SF:
16532 : 40 : case IX86_BUILTIN_GATHER3ALTDIV16SI:
16533 : 40 : half = gen_reg_rtx (mode0);
16534 : 40 : if (mode0 == V8SFmode)
16535 : : gen = gen_vec_extract_lo_v16sf;
16536 : : else
16537 : 18 : gen = gen_vec_extract_lo_v16si;
16538 : 40 : if (!nonimmediate_operand (op0, GET_MODE (op0)))
16539 : 40 : op0 = copy_to_mode_reg (GET_MODE (op0), op0);
16540 : 40 : emit_insn (gen (half, op0));
16541 : 40 : op0 = half;
16542 : 40 : op3 = lowpart_subreg (QImode, op3, HImode);
16543 : 40 : break;
16544 : 46 : case IX86_BUILTIN_GATHER3ALTDIV8SF:
16545 : 46 : case IX86_BUILTIN_GATHER3ALTDIV8SI:
16546 : 46 : case IX86_BUILTIN_GATHERALTDIV8SF:
16547 : 46 : case IX86_BUILTIN_GATHERALTDIV8SI:
16548 : 46 : half = gen_reg_rtx (mode0);
16549 : 46 : if (mode0 == V4SFmode)
16550 : : gen = gen_vec_extract_lo_v8sf;
16551 : : else
16552 : 22 : gen = gen_vec_extract_lo_v8si;
16553 : 46 : if (!nonimmediate_operand (op0, GET_MODE (op0)))
16554 : 46 : op0 = copy_to_mode_reg (GET_MODE (op0), op0);
16555 : 46 : emit_insn (gen (half, op0));
16556 : 46 : op0 = half;
16557 : 46 : if (VECTOR_MODE_P (GET_MODE (op3)))
16558 : : {
16559 : 28 : half = gen_reg_rtx (mode0);
16560 : 28 : if (!nonimmediate_operand (op3, GET_MODE (op3)))
16561 : 12 : op3 = copy_to_mode_reg (GET_MODE (op3), op3);
16562 : 28 : emit_insn (gen (half, op3));
16563 : 28 : op3 = half;
16564 : : }
16565 : : break;
16566 : : default:
16567 : : break;
16568 : : }
16569 : :
16570 : : /* Force memory operand only with base register here. But we
16571 : : don't want to do it on memory operand for other builtin
16572 : : functions. */
16573 : 1004 : op1 = ix86_zero_extend_to_Pmode (op1);
16574 : :
16575 : 1004 : if (!insn_data[icode].operand[1].predicate (op0, mode0))
16576 : 403 : op0 = copy_to_mode_reg (mode0, op0);
16577 : 1009 : if (!insn_data[icode].operand[2].predicate (op1, Pmode))
16578 : 0 : op1 = copy_to_mode_reg (Pmode, op1);
16579 : 1004 : if (!insn_data[icode].operand[3].predicate (op2, mode2))
16580 : 221 : op2 = copy_to_mode_reg (mode2, op2);
16581 : :
16582 : 1004 : op3 = fixup_modeless_constant (op3, mode3);
16583 : :
16584 : 1004 : if (GET_MODE (op3) == mode3 || GET_MODE (op3) == VOIDmode)
16585 : : {
16586 : 1004 : if (!insn_data[icode].operand[4].predicate (op3, mode3))
16587 : 356 : op3 = copy_to_mode_reg (mode3, op3);
16588 : : }
16589 : : else
16590 : : {
16591 : 0 : op3 = copy_to_reg (op3);
16592 : 0 : op3 = lowpart_subreg (mode3, op3, GET_MODE (op3));
16593 : : }
16594 : 1004 : if (!insn_data[icode].operand[5].predicate (op4, mode4))
16595 : : {
16596 : 0 : error ("the last argument must be scale 1, 2, 4, 8");
16597 : 0 : return const0_rtx;
16598 : : }
16599 : :
16600 : : /* Optimize. If mask is known to have all high bits set,
16601 : : replace op0 with pc_rtx to signal that the instruction
16602 : : overwrites the whole destination and doesn't use its
16603 : : previous contents. */
16604 : 1004 : if (optimize)
16605 : : {
16606 : 914 : if (TREE_CODE (arg3) == INTEGER_CST)
16607 : : {
16608 : 209 : if (integer_all_onesp (arg3))
16609 : 201 : op0 = pc_rtx;
16610 : : }
16611 : 705 : else if (TREE_CODE (arg3) == VECTOR_CST)
16612 : : {
16613 : : unsigned int negative = 0;
16614 : 755 : for (i = 0; i < VECTOR_CST_NELTS (arg3); ++i)
16615 : : {
16616 : 620 : tree cst = VECTOR_CST_ELT (arg3, i);
16617 : 620 : if (TREE_CODE (cst) == INTEGER_CST
16618 : 620 : && tree_int_cst_sign_bit (cst))
16619 : 286 : negative++;
16620 : 334 : else if (TREE_CODE (cst) == REAL_CST
16621 : 334 : && REAL_VALUE_NEGATIVE (TREE_REAL_CST (cst)))
16622 : 306 : negative++;
16623 : : }
16624 : 135 : if (negative == TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg3)))
16625 : 121 : op0 = pc_rtx;
16626 : : }
16627 : 570 : else if (TREE_CODE (arg3) == SSA_NAME
16628 : 570 : && VECTOR_TYPE_P (TREE_TYPE (arg3)))
16629 : : {
16630 : : /* Recognize also when mask is like:
16631 : : __v2df src = _mm_setzero_pd ();
16632 : : __v2df mask = _mm_cmpeq_pd (src, src);
16633 : : or
16634 : : __v8sf src = _mm256_setzero_ps ();
16635 : : __v8sf mask = _mm256_cmp_ps (src, src, _CMP_EQ_OQ);
16636 : : as that is a cheaper way to load all ones into
16637 : : a register than having to load a constant from
16638 : : memory. */
16639 : 259 : gimple *def_stmt = SSA_NAME_DEF_STMT (arg3);
16640 : 259 : if (is_gimple_call (def_stmt))
16641 : : {
16642 : 76 : tree fndecl = gimple_call_fndecl (def_stmt);
16643 : 76 : if (fndecl
16644 : 76 : && fndecl_built_in_p (fndecl, BUILT_IN_MD))
16645 : 67 : switch (DECL_MD_FUNCTION_CODE (fndecl))
16646 : : {
16647 : 24 : case IX86_BUILTIN_CMPPD:
16648 : 24 : case IX86_BUILTIN_CMPPS:
16649 : 24 : case IX86_BUILTIN_CMPPD256:
16650 : 24 : case IX86_BUILTIN_CMPPS256:
16651 : 24 : if (!integer_zerop (gimple_call_arg (def_stmt, 2)))
16652 : : break;
16653 : : /* FALLTHRU */
16654 : 49 : case IX86_BUILTIN_CMPEQPD:
16655 : 49 : case IX86_BUILTIN_CMPEQPS:
16656 : 49 : if (initializer_zerop (gimple_call_arg (def_stmt, 0))
16657 : 49 : && initializer_zerop (gimple_call_arg (def_stmt,
16658 : : 1)))
16659 : 49 : op0 = pc_rtx;
16660 : : break;
16661 : : default:
16662 : : break;
16663 : : }
16664 : : }
16665 : : }
16666 : : }
16667 : :
16668 : 1004 : pat = GEN_FCN (icode) (subtarget, op0, op1, op2, op3, op4);
16669 : 1004 : if (! pat)
16670 : 0 : return const0_rtx;
16671 : 1004 : emit_insn (pat);
16672 : :
16673 : 1004 : switch (fcode)
16674 : : {
16675 : 24 : case IX86_BUILTIN_GATHER3DIV16SF:
16676 : 24 : if (target == NULL_RTX)
16677 : 0 : target = gen_reg_rtx (V8SFmode);
16678 : 24 : emit_insn (gen_vec_extract_lo_v16sf (target, subtarget));
16679 : 24 : break;
16680 : 24 : case IX86_BUILTIN_GATHER3DIV16SI:
16681 : 24 : if (target == NULL_RTX)
16682 : 0 : target = gen_reg_rtx (V8SImode);
16683 : 24 : emit_insn (gen_vec_extract_lo_v16si (target, subtarget));
16684 : 24 : break;
16685 : 28 : case IX86_BUILTIN_GATHER3DIV8SF:
16686 : 28 : case IX86_BUILTIN_GATHERDIV8SF:
16687 : 28 : if (target == NULL_RTX)
16688 : 0 : target = gen_reg_rtx (V4SFmode);
16689 : 28 : emit_insn (gen_vec_extract_lo_v8sf (target, subtarget));
16690 : 28 : break;
16691 : 28 : case IX86_BUILTIN_GATHER3DIV8SI:
16692 : 28 : case IX86_BUILTIN_GATHERDIV8SI:
16693 : 28 : if (target == NULL_RTX)
16694 : 0 : target = gen_reg_rtx (V4SImode);
16695 : 28 : emit_insn (gen_vec_extract_lo_v8si (target, subtarget));
16696 : 28 : break;
16697 : : default:
16698 : : target = subtarget;
16699 : : break;
16700 : : }
16701 : : return target;
16702 : :
16703 : 623 : scatter_gen:
16704 : 623 : arg0 = CALL_EXPR_ARG (exp, 0);
16705 : 623 : arg1 = CALL_EXPR_ARG (exp, 1);
16706 : 623 : arg2 = CALL_EXPR_ARG (exp, 2);
16707 : 623 : arg3 = CALL_EXPR_ARG (exp, 3);
16708 : 623 : arg4 = CALL_EXPR_ARG (exp, 4);
16709 : 623 : op0 = expand_normal (arg0);
16710 : 623 : op1 = ix86_expand_unsigned_small_int_cst_argument (arg1);
16711 : 623 : op2 = expand_normal (arg2);
16712 : 623 : op3 = expand_normal (arg3);
16713 : 623 : op4 = expand_normal (arg4);
16714 : 623 : mode1 = insn_data[icode].operand[1].mode;
16715 : 623 : mode2 = insn_data[icode].operand[2].mode;
16716 : 623 : mode3 = insn_data[icode].operand[3].mode;
16717 : 623 : mode4 = insn_data[icode].operand[4].mode;
16718 : :
16719 : : /* Scatter instruction stores operand op3 to memory with
16720 : : indices from op2 and scale from op4 under writemask op1.
16721 : : If index operand op2 has more elements then source operand
16722 : : op3 one need to use only its low half. And vice versa. */
16723 : 623 : switch (fcode)
16724 : : {
16725 : 24 : case IX86_BUILTIN_SCATTERALTSIV8DF:
16726 : 24 : case IX86_BUILTIN_SCATTERALTSIV8DI:
16727 : 24 : half = gen_reg_rtx (V8SImode);
16728 : 24 : if (!nonimmediate_operand (op2, V16SImode))
16729 : 0 : op2 = copy_to_mode_reg (V16SImode, op2);
16730 : 24 : emit_insn (gen_vec_extract_lo_v16si (half, op2));
16731 : 24 : op2 = half;
16732 : 24 : break;
16733 : 36 : case IX86_BUILTIN_SCATTERALTDIV16SF:
16734 : 36 : case IX86_BUILTIN_SCATTERALTDIV16SI:
16735 : 36 : half = gen_reg_rtx (mode3);
16736 : 36 : if (mode3 == V8SFmode)
16737 : : gen = gen_vec_extract_lo_v16sf;
16738 : : else
16739 : 24 : gen = gen_vec_extract_lo_v16si;
16740 : 36 : if (!nonimmediate_operand (op3, GET_MODE (op3)))
16741 : 0 : op3 = copy_to_mode_reg (GET_MODE (op3), op3);
16742 : 36 : emit_insn (gen (half, op3));
16743 : 36 : op3 = half;
16744 : 36 : break;
16745 : 8 : case IX86_BUILTIN_SCATTERALTSIV4DF:
16746 : 8 : case IX86_BUILTIN_SCATTERALTSIV4DI:
16747 : 8 : half = gen_reg_rtx (V4SImode);
16748 : 8 : if (!nonimmediate_operand (op2, V8SImode))
16749 : 0 : op2 = copy_to_mode_reg (V8SImode, op2);
16750 : 8 : emit_insn (gen_vec_extract_lo_v8si (half, op2));
16751 : 8 : op2 = half;
16752 : 8 : break;
16753 : 8 : case IX86_BUILTIN_SCATTERALTDIV8SF:
16754 : 8 : case IX86_BUILTIN_SCATTERALTDIV8SI:
16755 : 8 : half = gen_reg_rtx (mode3);
16756 : 8 : if (mode3 == V4SFmode)
16757 : : gen = gen_vec_extract_lo_v8sf;
16758 : : else
16759 : 4 : gen = gen_vec_extract_lo_v8si;
16760 : 8 : if (!nonimmediate_operand (op3, GET_MODE (op3)))
16761 : 0 : op3 = copy_to_mode_reg (GET_MODE (op3), op3);
16762 : 8 : emit_insn (gen (half, op3));
16763 : 8 : op3 = half;
16764 : 8 : break;
16765 : 16 : case IX86_BUILTIN_SCATTERALTSIV2DF:
16766 : 16 : case IX86_BUILTIN_SCATTERALTSIV2DI:
16767 : 16 : if (!nonimmediate_operand (op2, V4SImode))
16768 : 0 : op2 = copy_to_mode_reg (V4SImode, op2);
16769 : : break;
16770 : 16 : case IX86_BUILTIN_SCATTERALTDIV4SF:
16771 : 16 : case IX86_BUILTIN_SCATTERALTDIV4SI:
16772 : 16 : if (!nonimmediate_operand (op3, GET_MODE (op3)))
16773 : 0 : op3 = copy_to_mode_reg (GET_MODE (op3), op3);
16774 : : break;
16775 : : default:
16776 : : break;
16777 : : }
16778 : :
16779 : : /* Force memory operand only with base register here. But we
16780 : : don't want to do it on memory operand for other builtin
16781 : : functions. */
16782 : 633 : op0 = force_reg (Pmode, convert_to_mode (Pmode, op0, 1));
16783 : :
16784 : 628 : if (!insn_data[icode].operand[0].predicate (op0, Pmode))
16785 : 0 : op0 = copy_to_mode_reg (Pmode, op0);
16786 : :
16787 : 623 : op1 = fixup_modeless_constant (op1, mode1);
16788 : :
16789 : 623 : if (GET_MODE (op1) == mode1 || GET_MODE (op1) == VOIDmode)
16790 : : {
16791 : 607 : if (!insn_data[icode].operand[1].predicate (op1, mode1))
16792 : 273 : op1 = copy_to_mode_reg (mode1, op1);
16793 : : }
16794 : : else
16795 : : {
16796 : 16 : op1 = copy_to_reg (op1);
16797 : 16 : op1 = lowpart_subreg (mode1, op1, GET_MODE (op1));
16798 : : }
16799 : :
16800 : 623 : if (!insn_data[icode].operand[2].predicate (op2, mode2))
16801 : 57 : op2 = copy_to_mode_reg (mode2, op2);
16802 : :
16803 : 623 : if (!insn_data[icode].operand[3].predicate (op3, mode3))
16804 : 82 : op3 = copy_to_mode_reg (mode3, op3);
16805 : :
16806 : 623 : if (!insn_data[icode].operand[4].predicate (op4, mode4))
16807 : : {
16808 : 0 : error ("the last argument must be scale 1, 2, 4, 8");
16809 : 0 : return const0_rtx;
16810 : : }
16811 : :
16812 : 623 : pat = GEN_FCN (icode) (op0, op1, op2, op3, op4);
16813 : 623 : if (! pat)
16814 : 0 : return const0_rtx;
16815 : :
16816 : 623 : emit_insn (pat);
16817 : 623 : return 0;
16818 : :
16819 : 23 : case IX86_BUILTIN_XABORT:
16820 : 23 : icode = CODE_FOR_xabort;
16821 : 23 : arg0 = CALL_EXPR_ARG (exp, 0);
16822 : 23 : op0 = expand_normal (arg0);
16823 : 23 : mode0 = insn_data[icode].operand[0].mode;
16824 : 23 : if (!insn_data[icode].operand[0].predicate (op0, mode0))
16825 : : {
16826 : 0 : error ("the argument to %<xabort%> intrinsic must "
16827 : : "be an 8-bit immediate");
16828 : 0 : return const0_rtx;
16829 : : }
16830 : 23 : emit_insn (gen_xabort (op0));
16831 : 23 : return 0;
16832 : :
16833 : 55 : case IX86_BUILTIN_RDSSPD:
16834 : 55 : case IX86_BUILTIN_RDSSPQ:
16835 : 55 : mode = (fcode == IX86_BUILTIN_RDSSPD ? SImode : DImode);
16836 : :
16837 : 55 : if (target == 0
16838 : 55 : || !register_operand (target, mode))
16839 : 0 : target = gen_reg_rtx (mode);
16840 : :
16841 : 55 : op0 = force_reg (mode, const0_rtx);
16842 : :
16843 : 55 : emit_insn (gen_rdssp (mode, target, op0));
16844 : 55 : return target;
16845 : :
16846 : 55 : case IX86_BUILTIN_INCSSPD:
16847 : 55 : case IX86_BUILTIN_INCSSPQ:
16848 : 55 : mode = (fcode == IX86_BUILTIN_INCSSPD ? SImode : DImode);
16849 : :
16850 : 55 : arg0 = CALL_EXPR_ARG (exp, 0);
16851 : 55 : op0 = expand_normal (arg0);
16852 : :
16853 : 55 : op0 = force_reg (mode, op0);
16854 : :
16855 : 55 : emit_insn (gen_incssp (mode, op0));
16856 : 55 : return 0;
16857 : :
16858 : 20 : case IX86_BUILTIN_HRESET:
16859 : 20 : icode = CODE_FOR_hreset;
16860 : 20 : arg0 = CALL_EXPR_ARG (exp, 0);
16861 : 20 : op0 = expand_normal (arg0);
16862 : 20 : op0 = force_reg (SImode, op0);
16863 : 20 : emit_insn (gen_hreset (op0));
16864 : 20 : return 0;
16865 : :
16866 : 38 : case IX86_BUILTIN_RSTORSSP:
16867 : 38 : case IX86_BUILTIN_CLRSSBSY:
16868 : 38 : arg0 = CALL_EXPR_ARG (exp, 0);
16869 : 38 : op0 = expand_normal (arg0);
16870 : 19 : icode = (fcode == IX86_BUILTIN_RSTORSSP
16871 : 38 : ? CODE_FOR_rstorssp
16872 : : : CODE_FOR_clrssbsy);
16873 : :
16874 : 38 : if (!address_operand (op0, VOIDmode))
16875 : : {
16876 : 18 : op0 = convert_memory_address (Pmode, op0);
16877 : 18 : op0 = copy_addr_to_reg (op0);
16878 : : }
16879 : 38 : emit_insn (GEN_FCN (icode) (gen_rtx_MEM (DImode, op0)));
16880 : 38 : return 0;
16881 : :
16882 : 76 : case IX86_BUILTIN_WRSSD:
16883 : 76 : case IX86_BUILTIN_WRSSQ:
16884 : 76 : case IX86_BUILTIN_WRUSSD:
16885 : 76 : case IX86_BUILTIN_WRUSSQ:
16886 : 76 : mode = ((fcode == IX86_BUILTIN_WRSSD
16887 : 76 : || fcode == IX86_BUILTIN_WRUSSD)
16888 : 76 : ? SImode : DImode);
16889 : :
16890 : 76 : arg0 = CALL_EXPR_ARG (exp, 0);
16891 : 76 : op0 = expand_normal (arg0);
16892 : 76 : arg1 = CALL_EXPR_ARG (exp, 1);
16893 : 76 : op1 = expand_normal (arg1);
16894 : :
16895 : 76 : op0 = force_reg (mode, op0);
16896 : :
16897 : 76 : if (!address_operand (op1, VOIDmode))
16898 : : {
16899 : 36 : op1 = convert_memory_address (Pmode, op1);
16900 : 36 : op1 = copy_addr_to_reg (op1);
16901 : : }
16902 : 76 : op1 = gen_rtx_MEM (mode, op1);
16903 : :
16904 : 76 : icode = ((fcode == IX86_BUILTIN_WRSSD
16905 : 76 : || fcode == IX86_BUILTIN_WRSSQ)
16906 : 76 : ? code_for_wrss (mode)
16907 : 38 : : code_for_wruss (mode));
16908 : 76 : emit_insn (GEN_FCN (icode) (op0, op1));
16909 : :
16910 : 76 : return 0;
16911 : :
16912 : 115572 : default:
16913 : 115572 : break;
16914 : : }
16915 : :
16916 : 115572 : if (fcode >= IX86_BUILTIN__BDESC_SPECIAL_ARGS_FIRST
16917 : 115572 : && fcode <= IX86_BUILTIN__BDESC_SPECIAL_ARGS_LAST)
16918 : : {
16919 : 27266 : i = fcode - IX86_BUILTIN__BDESC_SPECIAL_ARGS_FIRST;
16920 : 27266 : return ix86_expand_special_args_builtin (bdesc_special_args + i, exp,
16921 : 27266 : target);
16922 : : }
16923 : :
16924 : 88306 : if (fcode >= IX86_BUILTIN__BDESC_PURE_ARGS_FIRST
16925 : 88306 : && fcode <= IX86_BUILTIN__BDESC_PURE_ARGS_LAST)
16926 : : {
16927 : 93 : i = fcode - IX86_BUILTIN__BDESC_PURE_ARGS_FIRST;
16928 : 93 : return ix86_expand_special_args_builtin (bdesc_pure_args + i, exp,
16929 : 93 : target);
16930 : : }
16931 : :
16932 : 88213 : if (fcode >= IX86_BUILTIN__BDESC_ARGS_FIRST
16933 : 88213 : && fcode <= IX86_BUILTIN__BDESC_ARGS_LAST)
16934 : : {
16935 : 69587 : i = fcode - IX86_BUILTIN__BDESC_ARGS_FIRST;
16936 : :
16937 : 69587 : switch (fcode)
16938 : : {
16939 : 0 : case IX86_BUILTIN_RDPID:
16940 : 0 : return ix86_expand_special_args_builtin (bdesc_args + i, exp,
16941 : 0 : target);
16942 : 72 : case IX86_BUILTIN_VCOMISBF16EQ:
16943 : 72 : case IX86_BUILTIN_VCOMISBF16NE:
16944 : 72 : case IX86_BUILTIN_VCOMISBF16GT:
16945 : 72 : case IX86_BUILTIN_VCOMISBF16GE:
16946 : 72 : case IX86_BUILTIN_VCOMISBF16LT:
16947 : 72 : case IX86_BUILTIN_VCOMISBF16LE:
16948 : 72 : return ix86_expand_sse_comi (bdesc_args + i, exp, target, false);
16949 : 15 : case IX86_BUILTIN_FABSQ:
16950 : 15 : case IX86_BUILTIN_COPYSIGNQ:
16951 : 15 : if (!TARGET_SSE)
16952 : : /* Emit a normal call if SSE isn't available. */
16953 : 0 : return expand_call (exp, target, ignore);
16954 : : /* FALLTHRU */
16955 : 69515 : default:
16956 : 69515 : return ix86_expand_args_builtin (bdesc_args + i, exp, target);
16957 : : }
16958 : : }
16959 : :
16960 : 18626 : if (fcode >= IX86_BUILTIN__BDESC_COMI_FIRST
16961 : 18626 : && fcode <= IX86_BUILTIN__BDESC_COMI_LAST)
16962 : : {
16963 : 473 : i = fcode - IX86_BUILTIN__BDESC_COMI_FIRST;
16964 : 473 : return ix86_expand_sse_comi (bdesc_comi + i, exp, target, true);
16965 : : }
16966 : :
16967 : 18153 : if (fcode >= IX86_BUILTIN__BDESC_ROUND_ARGS_FIRST
16968 : 18153 : && fcode <= IX86_BUILTIN__BDESC_ROUND_ARGS_LAST)
16969 : : {
16970 : 15832 : i = fcode - IX86_BUILTIN__BDESC_ROUND_ARGS_FIRST;
16971 : 15832 : return ix86_expand_round_builtin (bdesc_round_args + i, exp, target);
16972 : : }
16973 : :
16974 : 2321 : if (fcode >= IX86_BUILTIN__BDESC_PCMPESTR_FIRST
16975 : 2321 : && fcode <= IX86_BUILTIN__BDESC_PCMPESTR_LAST)
16976 : : {
16977 : 216 : i = fcode - IX86_BUILTIN__BDESC_PCMPESTR_FIRST;
16978 : 216 : return ix86_expand_sse_pcmpestr (bdesc_pcmpestr + i, exp, target);
16979 : : }
16980 : :
16981 : 2105 : if (fcode >= IX86_BUILTIN__BDESC_PCMPISTR_FIRST
16982 : 2105 : && fcode <= IX86_BUILTIN__BDESC_PCMPISTR_LAST)
16983 : : {
16984 : 275 : i = fcode - IX86_BUILTIN__BDESC_PCMPISTR_FIRST;
16985 : 275 : return ix86_expand_sse_pcmpistr (bdesc_pcmpistr + i, exp, target);
16986 : : }
16987 : :
16988 : 1830 : if (fcode >= IX86_BUILTIN__BDESC_MULTI_ARG_FIRST
16989 : 1830 : && fcode <= IX86_BUILTIN__BDESC_MULTI_ARG_LAST)
16990 : : {
16991 : 1792 : i = fcode - IX86_BUILTIN__BDESC_MULTI_ARG_FIRST;
16992 : 1792 : const struct builtin_description *d = bdesc_multi_arg + i;
16993 : 1792 : return ix86_expand_multi_arg_builtin (d->icode, exp, target,
16994 : : (enum ix86_builtin_func_type)
16995 : 1792 : d->flag, d->comparison);
16996 : : }
16997 : :
16998 : 38 : if (fcode >= IX86_BUILTIN__BDESC_CET_FIRST
16999 : 38 : && fcode <= IX86_BUILTIN__BDESC_CET_LAST)
17000 : : {
17001 : 38 : i = fcode - IX86_BUILTIN__BDESC_CET_FIRST;
17002 : 38 : return ix86_expand_special_args_builtin (bdesc_cet + i, exp,
17003 : 38 : target);
17004 : : }
17005 : :
17006 : 0 : gcc_unreachable ();
17007 : : }
17008 : :
17009 : : /* See below where shifts are handled for explanation of this enum. */
17010 : : enum ix86_vec_bcast_alg
17011 : : {
17012 : : VEC_BCAST_PXOR,
17013 : : VEC_BCAST_PCMPEQ,
17014 : : VEC_BCAST_PABSB,
17015 : : VEC_BCAST_PADDB,
17016 : : VEC_BCAST_PSRLW,
17017 : : VEC_BCAST_PSRLD,
17018 : : VEC_BCAST_PSLLW,
17019 : : VEC_BCAST_PSLLD
17020 : : };
17021 : :
17022 : : struct ix86_vec_bcast_map_simode_t
17023 : : {
17024 : : unsigned int key;
17025 : : enum ix86_vec_bcast_alg alg;
17026 : : unsigned int arg;
17027 : : };
17028 : :
17029 : : /* This table must be kept sorted as values are looked-up using bsearch. */
17030 : : static const ix86_vec_bcast_map_simode_t ix86_vec_bcast_map_simode[] = {
17031 : : { 0x00000000, VEC_BCAST_PXOR, 0 },
17032 : : { 0x00000001, VEC_BCAST_PSRLD, 31 },
17033 : : { 0x00000003, VEC_BCAST_PSRLD, 30 },
17034 : : { 0x00000007, VEC_BCAST_PSRLD, 29 },
17035 : : { 0x0000000f, VEC_BCAST_PSRLD, 28 },
17036 : : { 0x0000001f, VEC_BCAST_PSRLD, 27 },
17037 : : { 0x0000003f, VEC_BCAST_PSRLD, 26 },
17038 : : { 0x0000007f, VEC_BCAST_PSRLD, 25 },
17039 : : { 0x000000ff, VEC_BCAST_PSRLD, 24 },
17040 : : { 0x000001ff, VEC_BCAST_PSRLD, 23 },
17041 : : { 0x000003ff, VEC_BCAST_PSRLD, 22 },
17042 : : { 0x000007ff, VEC_BCAST_PSRLD, 21 },
17043 : : { 0x00000fff, VEC_BCAST_PSRLD, 20 },
17044 : : { 0x00001fff, VEC_BCAST_PSRLD, 19 },
17045 : : { 0x00003fff, VEC_BCAST_PSRLD, 18 },
17046 : : { 0x00007fff, VEC_BCAST_PSRLD, 17 },
17047 : : { 0x0000ffff, VEC_BCAST_PSRLD, 16 },
17048 : : { 0x00010001, VEC_BCAST_PSRLW, 15 },
17049 : : { 0x0001ffff, VEC_BCAST_PSRLD, 15 },
17050 : : { 0x00030003, VEC_BCAST_PSRLW, 14 },
17051 : : { 0x0003ffff, VEC_BCAST_PSRLD, 14 },
17052 : : { 0x00070007, VEC_BCAST_PSRLW, 13 },
17053 : : { 0x0007ffff, VEC_BCAST_PSRLD, 13 },
17054 : : { 0x000f000f, VEC_BCAST_PSRLW, 12 },
17055 : : { 0x000fffff, VEC_BCAST_PSRLD, 12 },
17056 : : { 0x001f001f, VEC_BCAST_PSRLW, 11 },
17057 : : { 0x001fffff, VEC_BCAST_PSRLD, 11 },
17058 : : { 0x003f003f, VEC_BCAST_PSRLW, 10 },
17059 : : { 0x003fffff, VEC_BCAST_PSRLD, 10 },
17060 : : { 0x007f007f, VEC_BCAST_PSRLW, 9 },
17061 : : { 0x007fffff, VEC_BCAST_PSRLD, 9 },
17062 : : { 0x00ff00ff, VEC_BCAST_PSRLW, 8 },
17063 : : { 0x00ffffff, VEC_BCAST_PSRLD, 8 },
17064 : : { 0x01010101, VEC_BCAST_PABSB, 0 },
17065 : : { 0x01ff01ff, VEC_BCAST_PSRLW, 7 },
17066 : : { 0x01ffffff, VEC_BCAST_PSRLD, 7 },
17067 : : { 0x03ff03ff, VEC_BCAST_PSRLW, 6 },
17068 : : { 0x03ffffff, VEC_BCAST_PSRLD, 6 },
17069 : : { 0x07ff07ff, VEC_BCAST_PSRLW, 5 },
17070 : : { 0x07ffffff, VEC_BCAST_PSRLD, 5 },
17071 : : { 0x0fff0fff, VEC_BCAST_PSRLW, 4 },
17072 : : { 0x0fffffff, VEC_BCAST_PSRLD, 4 },
17073 : : { 0x1fff1fff, VEC_BCAST_PSRLW, 3 },
17074 : : { 0x1fffffff, VEC_BCAST_PSRLD, 3 },
17075 : : { 0x3fff3fff, VEC_BCAST_PSRLW, 2 },
17076 : : { 0x3fffffff, VEC_BCAST_PSRLD, 2 },
17077 : : { 0x7fff7fff, VEC_BCAST_PSRLW, 1 },
17078 : : { 0x7fffffff, VEC_BCAST_PSRLD, 1 },
17079 : : { 0x80000000, VEC_BCAST_PSLLD, 31 },
17080 : : { 0x80008000, VEC_BCAST_PSLLW, 15 },
17081 : : { 0xc0000000, VEC_BCAST_PSLLD, 30 },
17082 : : { 0xc000c000, VEC_BCAST_PSLLW, 14 },
17083 : : { 0xe0000000, VEC_BCAST_PSLLD, 29 },
17084 : : { 0xe000e000, VEC_BCAST_PSLLW, 13 },
17085 : : { 0xf0000000, VEC_BCAST_PSLLD, 28 },
17086 : : { 0xf000f000, VEC_BCAST_PSLLW, 12 },
17087 : : { 0xf8000000, VEC_BCAST_PSLLD, 27 },
17088 : : { 0xf800f800, VEC_BCAST_PSLLW, 11 },
17089 : : { 0xfc000000, VEC_BCAST_PSLLD, 26 },
17090 : : { 0xfc00fc00, VEC_BCAST_PSLLW, 10 },
17091 : : { 0xfe000000, VEC_BCAST_PSLLD, 25 },
17092 : : { 0xfe00fe00, VEC_BCAST_PSLLW, 9 },
17093 : : { 0xfefefefe, VEC_BCAST_PADDB, 0 },
17094 : : { 0xff000000, VEC_BCAST_PSLLD, 24 },
17095 : : { 0xff00ff00, VEC_BCAST_PSLLW, 8 },
17096 : : { 0xff800000, VEC_BCAST_PSLLD, 23 },
17097 : : { 0xff80ff80, VEC_BCAST_PSLLW, 7 },
17098 : : { 0xffc00000, VEC_BCAST_PSLLD, 22 },
17099 : : { 0xffc0ffc0, VEC_BCAST_PSLLW, 6 },
17100 : : { 0xffe00000, VEC_BCAST_PSLLD, 21 },
17101 : : { 0xffe0ffe0, VEC_BCAST_PSLLW, 5 },
17102 : : { 0xfff00000, VEC_BCAST_PSLLD, 20 },
17103 : : { 0xfff0fff0, VEC_BCAST_PSLLW, 4 },
17104 : : { 0xfff80000, VEC_BCAST_PSLLD, 19 },
17105 : : { 0xfff8fff8, VEC_BCAST_PSLLW, 3 },
17106 : : { 0xfffc0000, VEC_BCAST_PSLLD, 18 },
17107 : : { 0xfffcfffc, VEC_BCAST_PSLLW, 2 },
17108 : : { 0xfffe0000, VEC_BCAST_PSLLD, 17 },
17109 : : { 0xfffefffe, VEC_BCAST_PSLLW, 1 },
17110 : : { 0xffff0000, VEC_BCAST_PSLLD, 16 },
17111 : : { 0xffff8000, VEC_BCAST_PSLLD, 15 },
17112 : : { 0xffffc000, VEC_BCAST_PSLLD, 14 },
17113 : : { 0xffffe000, VEC_BCAST_PSLLD, 13 },
17114 : : { 0xfffff000, VEC_BCAST_PSLLD, 12 },
17115 : : { 0xfffff800, VEC_BCAST_PSLLD, 11 },
17116 : : { 0xfffffc00, VEC_BCAST_PSLLD, 10 },
17117 : : { 0xfffffe00, VEC_BCAST_PSLLD, 9 },
17118 : : { 0xffffff00, VEC_BCAST_PSLLD, 8 },
17119 : : { 0xffffff80, VEC_BCAST_PSLLD, 7 },
17120 : : { 0xffffffc0, VEC_BCAST_PSLLD, 6 },
17121 : : { 0xffffffe0, VEC_BCAST_PSLLD, 5 },
17122 : : { 0xfffffff0, VEC_BCAST_PSLLD, 4 },
17123 : : { 0xfffffff8, VEC_BCAST_PSLLD, 3 },
17124 : : { 0xfffffffc, VEC_BCAST_PSLLD, 2 },
17125 : : { 0xfffffffe, VEC_BCAST_PSLLD, 1 },
17126 : : { 0xffffffff, VEC_BCAST_PCMPEQ, 0 }
17127 : : };
17128 : :
17129 : : /* Comparator for bsearch on ix86_vec_bcast_map. */
17130 : : static int
17131 : 283307 : ix86_vec_bcast_map_simode_cmp (const void *key, const void *entry)
17132 : : {
17133 : 283307 : return (*(const unsigned int*)key)
17134 : 283307 : - ((const ix86_vec_bcast_map_simode_t*)entry)->key;
17135 : : }
17136 : :
17137 : : /* A subroutine of ix86_vector_duplicate_value. Tries to efficiently
17138 : : materialize V4SImode, V8SImode and V16SImode vectors from SImode
17139 : : integer constants. */
17140 : : static bool
17141 : 43542 : ix86_vector_duplicate_simode_const (machine_mode mode, rtx target,
17142 : : unsigned int val)
17143 : : {
17144 : 43542 : const ix86_vec_bcast_map_simode_t *entry;
17145 : 43542 : rtx tmp1, tmp2;
17146 : :
17147 : 43542 : entry = (const ix86_vec_bcast_map_simode_t*)
17148 : 43542 : bsearch(&val, ix86_vec_bcast_map_simode,
17149 : : ARRAY_SIZE (ix86_vec_bcast_map_simode),
17150 : : sizeof (ix86_vec_bcast_map_simode_t),
17151 : : ix86_vec_bcast_map_simode_cmp);
17152 : 43542 : if (!entry)
17153 : : return false;
17154 : :
17155 : 18553 : switch (entry->alg)
17156 : : {
17157 : 0 : case VEC_BCAST_PXOR:
17158 : 0 : if ((mode == V8SImode && !TARGET_AVX2)
17159 : 0 : || (mode == V16SImode && !TARGET_AVX512F))
17160 : : return false;
17161 : 0 : emit_move_insn (target, CONST0_RTX (mode));
17162 : 0 : return true;
17163 : :
17164 : 142 : case VEC_BCAST_PCMPEQ:
17165 : 142 : if ((mode == V4SImode && !TARGET_SSE2)
17166 : 141 : || (mode == V8SImode && !TARGET_AVX2)
17167 : 114 : || (mode == V16SImode && !TARGET_AVX512F))
17168 : : return false;
17169 : 114 : emit_move_insn (target, CONSTM1_RTX (mode));
17170 : 114 : return true;
17171 : :
17172 : 645 : case VEC_BCAST_PABSB:
17173 : 645 : if (mode == V4SImode && TARGET_SSE2)
17174 : : {
17175 : 508 : tmp1 = gen_reg_rtx (V16QImode);
17176 : 508 : emit_move_insn (tmp1, CONSTM1_RTX (V16QImode));
17177 : 508 : tmp2 = gen_reg_rtx (V16QImode);
17178 : 508 : emit_insn (gen_absv16qi2 (tmp2, tmp1));
17179 : : }
17180 : 137 : else if (mode == V8SImode && TARGET_AVX2)
17181 : : {
17182 : 79 : tmp1 = gen_reg_rtx (V32QImode);
17183 : 79 : emit_move_insn (tmp1, CONSTM1_RTX (V32QImode));
17184 : 79 : tmp2 = gen_reg_rtx (V32QImode);
17185 : 79 : emit_insn (gen_absv32qi2 (tmp2, tmp1));
17186 : : }
17187 : 58 : else if (mode == V16SImode && TARGET_AVX512BW)
17188 : : {
17189 : 50 : tmp1 = gen_reg_rtx (V64QImode);
17190 : 50 : emit_move_insn (tmp1, CONSTM1_RTX (V64QImode));
17191 : 50 : tmp2 = gen_reg_rtx (V64QImode);
17192 : 50 : emit_insn (gen_absv64qi2 (tmp2, tmp1));
17193 : : }
17194 : : else
17195 : : return false;
17196 : : break;
17197 : :
17198 : 102 : case VEC_BCAST_PADDB:
17199 : 102 : if (mode == V4SImode && TARGET_SSE2)
17200 : : {
17201 : 95 : tmp1 = gen_reg_rtx (V16QImode);
17202 : 95 : emit_move_insn (tmp1, CONSTM1_RTX (V16QImode));
17203 : 95 : tmp2 = gen_reg_rtx (V16QImode);
17204 : 95 : emit_insn (gen_addv16qi3 (tmp2, tmp1, tmp1));
17205 : : }
17206 : 7 : else if (mode == V8SImode && TARGET_AVX2)
17207 : : {
17208 : 1 : tmp1 = gen_reg_rtx (V32QImode);
17209 : 1 : emit_move_insn (tmp1, CONSTM1_RTX (V32QImode));
17210 : 1 : tmp2 = gen_reg_rtx (V32QImode);
17211 : 1 : emit_insn (gen_addv32qi3 (tmp2, tmp1, tmp1));
17212 : : }
17213 : 6 : else if (mode == V16SImode && TARGET_AVX512BW)
17214 : : {
17215 : 6 : tmp1 = gen_reg_rtx (V64QImode);
17216 : 6 : emit_move_insn (tmp1, CONSTM1_RTX (V64QImode));
17217 : 6 : tmp2 = gen_reg_rtx (V64QImode);
17218 : 6 : emit_insn (gen_addv64qi3 (tmp2, tmp1, tmp1));
17219 : : }
17220 : : else
17221 : : return false;
17222 : : break;
17223 : :
17224 : 3632 : case VEC_BCAST_PSRLW:
17225 : 3632 : if (mode == V4SImode && TARGET_SSE2)
17226 : : {
17227 : 3411 : tmp1 = gen_reg_rtx (V8HImode);
17228 : 3411 : emit_move_insn (tmp1, CONSTM1_RTX (V8HImode));
17229 : 3411 : tmp2 = gen_reg_rtx (V8HImode);
17230 : 3411 : emit_insn (gen_lshrv8hi3 (tmp2, tmp1, GEN_INT (entry->arg)));
17231 : : }
17232 : 221 : else if (mode == V8SImode && TARGET_AVX2)
17233 : : {
17234 : 128 : tmp1 = gen_reg_rtx (V16HImode);
17235 : 128 : emit_move_insn (tmp1, CONSTM1_RTX (V16HImode));
17236 : 128 : tmp2 = gen_reg_rtx (V16HImode);
17237 : 128 : emit_insn (gen_lshrv16hi3 (tmp2, tmp1, GEN_INT (entry->arg)));
17238 : : }
17239 : 93 : else if (mode == V16SImode && TARGET_AVX512BW)
17240 : : {
17241 : 91 : tmp1 = gen_reg_rtx (V32HImode);
17242 : 91 : emit_move_insn (tmp1, CONSTM1_RTX (V32HImode));
17243 : 91 : tmp2 = gen_reg_rtx (V32HImode);
17244 : 91 : emit_insn (gen_lshrv32hi3 (tmp2, tmp1, GEN_INT (entry->arg)));
17245 : : }
17246 : : else
17247 : : return false;
17248 : : break;
17249 : :
17250 : 12377 : case VEC_BCAST_PSRLD:
17251 : 12377 : if (mode == V4SImode && TARGET_SSE2)
17252 : : {
17253 : 9414 : tmp1 = gen_reg_rtx (V4SImode);
17254 : 9414 : emit_move_insn (tmp1, CONSTM1_RTX (V4SImode));
17255 : 9414 : emit_insn (gen_lshrv4si3 (target, tmp1, GEN_INT (entry->arg)));
17256 : 9414 : return true;
17257 : : }
17258 : 2963 : else if (mode == V8SImode && TARGET_AVX2)
17259 : : {
17260 : 1119 : tmp1 = gen_reg_rtx (V8SImode);
17261 : 1119 : emit_move_insn (tmp1, CONSTM1_RTX (V8SImode));
17262 : 1119 : emit_insn (gen_lshrv8si3 (target, tmp1, GEN_INT (entry->arg)));
17263 : 1119 : return true;
17264 : : }
17265 : 1844 : else if (mode == V16SImode && TARGET_AVX512F)
17266 : : {
17267 : 1005 : tmp1 = gen_reg_rtx (V16SImode);
17268 : 1005 : emit_move_insn (tmp1, CONSTM1_RTX (V16SImode));
17269 : 1005 : emit_insn (gen_lshrv16si3 (target, tmp1, GEN_INT (entry->arg)));
17270 : 1005 : return true;
17271 : : }
17272 : : else
17273 : : return false;
17274 : 121 : break;
17275 : :
17276 : 121 : case VEC_BCAST_PSLLW:
17277 : 121 : if (mode == V4SImode && TARGET_SSE2)
17278 : : {
17279 : 91 : tmp1 = gen_reg_rtx (V8HImode);
17280 : 91 : emit_move_insn (tmp1, CONSTM1_RTX (V8HImode));
17281 : 91 : tmp2 = gen_reg_rtx (V8HImode);
17282 : 91 : emit_insn (gen_ashlv8hi3 (tmp2, tmp1, GEN_INT (entry->arg)));
17283 : : }
17284 : 30 : else if (mode == V8SImode && TARGET_AVX2)
17285 : : {
17286 : 21 : tmp1 = gen_reg_rtx (V16HImode);
17287 : 21 : emit_move_insn (tmp1, CONSTM1_RTX (V16HImode));
17288 : 21 : tmp2 = gen_reg_rtx (V16HImode);
17289 : 21 : emit_insn (gen_ashlv16hi3 (tmp2, tmp1, GEN_INT (entry->arg)));
17290 : : }
17291 : 9 : else if (mode == V16SImode && TARGET_AVX512BW)
17292 : : {
17293 : 9 : tmp1 = gen_reg_rtx (V32HImode);
17294 : 9 : emit_move_insn (tmp1, CONSTM1_RTX (V32HImode));
17295 : 9 : tmp2 = gen_reg_rtx (V32HImode);
17296 : 9 : emit_insn (gen_ashlv32hi3 (tmp2, tmp1, GEN_INT (entry->arg)));
17297 : : }
17298 : : else
17299 : : return false;
17300 : : break;
17301 : :
17302 : 1534 : case VEC_BCAST_PSLLD:
17303 : 1534 : if (mode == V4SImode && TARGET_SSE2)
17304 : : {
17305 : 1502 : tmp1 = gen_reg_rtx (V4SImode);
17306 : 1502 : emit_move_insn (tmp1, CONSTM1_RTX (V4SImode));
17307 : 1502 : emit_insn (gen_ashlv4si3 (target, tmp1, GEN_INT (entry->arg)));
17308 : 1502 : return true;
17309 : : }
17310 : 32 : else if (mode == V8SImode && TARGET_AVX2)
17311 : : {
17312 : 15 : tmp1 = gen_reg_rtx (V8SImode);
17313 : 15 : emit_move_insn (tmp1, CONSTM1_RTX (V8SImode));
17314 : 15 : emit_insn (gen_ashlv8si3 (target, tmp1, GEN_INT (entry->arg)));
17315 : 15 : return true;
17316 : : }
17317 : 17 : else if (mode == V16SImode && TARGET_AVX512F)
17318 : : {
17319 : 17 : tmp1 = gen_reg_rtx (V16SImode);
17320 : 17 : emit_move_insn (tmp1, CONSTM1_RTX (V16SImode));
17321 : 17 : emit_insn (gen_ashlv16si3 (target, tmp1, GEN_INT (entry->arg)));
17322 : 17 : return true;
17323 : : }
17324 : : else
17325 : : return false;
17326 : :
17327 : : default:
17328 : : return false;
17329 : : }
17330 : :
17331 : 4490 : emit_move_insn (target, gen_lowpart (mode, tmp2));
17332 : 4490 : return true;
17333 : : }
17334 : :
17335 : : /* A subroutine of ix86_expand_vector_init_duplicate. Tries to
17336 : : fill target with val via vec_duplicate. */
17337 : :
17338 : : static bool
17339 : 143017 : ix86_vector_duplicate_value (machine_mode mode, rtx target, rtx val)
17340 : : {
17341 : 143017 : bool ok;
17342 : 143017 : rtx_insn *insn;
17343 : 143017 : rtx dup;
17344 : :
17345 : 143017 : if ((mode == V4SImode || mode == V8SImode || mode == V16SImode)
17346 : 51348 : && CONST_INT_P (val)
17347 : 43542 : && ix86_vector_duplicate_simode_const (mode, target, INTVAL (val)))
17348 : : return true;
17349 : :
17350 : : /* Save/restore recog_data in case this is called from splitters
17351 : : or other routines where recog_data needs to stay valid across
17352 : : force_reg. See PR106577. */
17353 : 125341 : recog_data_d recog_data_save = recog_data;
17354 : :
17355 : : /* First attempt to recognize VAL as-is. */
17356 : 125341 : dup = gen_vec_duplicate (mode, val);
17357 : 125341 : insn = emit_insn (gen_rtx_SET (target, dup));
17358 : 125341 : if (recog_memoized (insn) < 0)
17359 : : {
17360 : 87477 : rtx_insn *seq;
17361 : 87477 : machine_mode innermode = GET_MODE_INNER (mode);
17362 : 87477 : rtx reg;
17363 : :
17364 : : /* If that fails, force VAL into a register. */
17365 : :
17366 : 87477 : start_sequence ();
17367 : 87477 : reg = force_reg (innermode, val);
17368 : 87477 : if (GET_MODE (reg) != innermode)
17369 : 0 : reg = gen_lowpart (innermode, reg);
17370 : 87477 : SET_SRC (PATTERN (insn)) = gen_vec_duplicate (mode, reg);
17371 : 87477 : seq = end_sequence ();
17372 : 87477 : if (seq)
17373 : 87477 : emit_insn_before (seq, insn);
17374 : :
17375 : 87477 : ok = recog_memoized (insn) >= 0;
17376 : 87477 : gcc_assert (ok);
17377 : : }
17378 : 125341 : recog_data = recog_data_save;
17379 : 125341 : return true;
17380 : : }
17381 : :
17382 : : /* Get a vector mode of the same size as the original but with elements
17383 : : twice as wide. This is only guaranteed to apply to integral vectors. */
17384 : :
17385 : : static machine_mode
17386 : 17959 : get_mode_wider_vector (machine_mode o)
17387 : : {
17388 : : /* ??? Rely on the ordering that genmodes.cc gives to vectors. */
17389 : 17959 : machine_mode n = GET_MODE_NEXT_MODE (o).require ();
17390 : 53877 : gcc_assert (GET_MODE_NUNITS (o) == GET_MODE_NUNITS (n) * 2);
17391 : 53877 : gcc_assert (GET_MODE_SIZE (o) == GET_MODE_SIZE (n));
17392 : 17959 : return n;
17393 : : }
17394 : :
17395 : : static bool expand_vec_perm_broadcast_1 (struct expand_vec_perm_d *d);
17396 : : static bool expand_vec_perm_1 (struct expand_vec_perm_d *d);
17397 : :
17398 : : /* A subroutine of ix86_expand_vector_init. Store into TARGET a vector
17399 : : with all elements equal to VAR. Return true if successful. */
17400 : :
17401 : : bool
17402 : 162231 : ix86_expand_vector_init_duplicate (bool mmx_ok, machine_mode mode,
17403 : : rtx target, rtx val)
17404 : : {
17405 : 162231 : bool ok;
17406 : :
17407 : 162231 : switch (mode)
17408 : : {
17409 : 69798 : case E_V2DImode:
17410 : 69798 : if (CONST_INT_P (val))
17411 : : {
17412 : 60769 : int tmp = (int)INTVAL (val);
17413 : 60769 : if (tmp == (int)(INTVAL (val) >> 32))
17414 : : {
17415 : 165 : rtx reg = gen_reg_rtx (V4SImode);
17416 : 165 : ok = ix86_vector_duplicate_value (V4SImode, reg,
17417 : : GEN_INT (tmp));
17418 : 165 : if (ok)
17419 : : {
17420 : 165 : emit_move_insn (target, gen_lowpart (V2DImode, reg));
17421 : 165 : return true;
17422 : : }
17423 : : }
17424 : : }
17425 : 69633 : return ix86_vector_duplicate_value (mode, target, val);
17426 : :
17427 : 1082 : case E_V4DImode:
17428 : 1082 : if (CONST_INT_P (val))
17429 : : {
17430 : 781 : int tmp = (int)INTVAL (val);
17431 : 781 : if (tmp == (int)(INTVAL (val) >> 32))
17432 : : {
17433 : 54 : rtx reg = gen_reg_rtx (V8SImode);
17434 : 54 : ok = ix86_vector_duplicate_value (V8SImode, reg,
17435 : : GEN_INT (tmp));
17436 : 54 : if (ok)
17437 : : {
17438 : 54 : emit_move_insn (target, gen_lowpart (V4DImode, reg));
17439 : 54 : return true;
17440 : : }
17441 : : }
17442 : : }
17443 : 1028 : return ix86_vector_duplicate_value (mode, target, val);
17444 : :
17445 : 517 : case E_V8DImode:
17446 : 517 : if (CONST_INT_P (val))
17447 : : {
17448 : 268 : int tmp = (int)INTVAL (val);
17449 : 268 : if (tmp == (int)(INTVAL (val) >> 32))
17450 : : {
17451 : 24 : rtx reg = gen_reg_rtx (V16SImode);
17452 : 24 : ok = ix86_vector_duplicate_value (V16SImode, reg,
17453 : : GEN_INT (tmp));
17454 : 24 : if (ok)
17455 : : {
17456 : 24 : emit_move_insn (target, gen_lowpart (V8DImode, reg));
17457 : 24 : return true;
17458 : : }
17459 : : }
17460 : : }
17461 : 493 : return ix86_vector_duplicate_value (mode, target, val);
17462 : :
17463 : 2550 : case E_V2SImode:
17464 : 2550 : case E_V2SFmode:
17465 : 2550 : if (!mmx_ok)
17466 : : return false;
17467 : : /* FALLTHRU */
17468 : :
17469 : 70628 : case E_V4DFmode:
17470 : 70628 : case E_V8SFmode:
17471 : 70628 : case E_V8SImode:
17472 : 70628 : case E_V2DFmode:
17473 : 70628 : case E_V4SFmode:
17474 : 70628 : case E_V4SImode:
17475 : 70628 : case E_V16SImode:
17476 : 70628 : case E_V16SFmode:
17477 : 70628 : case E_V8DFmode:
17478 : 70628 : return ix86_vector_duplicate_value (mode, target, val);
17479 : :
17480 : 374 : case E_V4HImode:
17481 : 374 : if (!mmx_ok)
17482 : : return false;
17483 : 371 : if (TARGET_SSE || TARGET_3DNOW_A)
17484 : : {
17485 : 371 : rtx x;
17486 : :
17487 : 371 : val = gen_lowpart (SImode, val);
17488 : 371 : if (CONST_INT_P (val))
17489 : : return false;
17490 : 369 : x = gen_rtx_TRUNCATE (HImode, val);
17491 : 369 : x = gen_rtx_VEC_DUPLICATE (mode, x);
17492 : 369 : emit_insn (gen_rtx_SET (target, x));
17493 : 369 : return true;
17494 : : }
17495 : 0 : goto widen;
17496 : :
17497 : 5 : case E_V4HFmode:
17498 : 5 : case E_V4BFmode:
17499 : 5 : if (TARGET_MMX_WITH_SSE)
17500 : : {
17501 : 10 : val = force_reg (GET_MODE_INNER (mode), val);
17502 : 5 : rtx x = gen_rtx_VEC_DUPLICATE (mode, val);
17503 : 5 : emit_insn (gen_rtx_SET (target, x));
17504 : 5 : return true;
17505 : : }
17506 : : return false;
17507 : :
17508 : 110 : case E_V2HImode:
17509 : 110 : if (TARGET_SSE2)
17510 : : {
17511 : 110 : rtx x;
17512 : :
17513 : 110 : val = gen_lowpart (SImode, val);
17514 : 110 : if (CONST_INT_P (val))
17515 : : return false;
17516 : 110 : x = gen_rtx_TRUNCATE (HImode, val);
17517 : 110 : x = gen_rtx_VEC_DUPLICATE (mode, x);
17518 : 110 : emit_insn (gen_rtx_SET (target, x));
17519 : 110 : return true;
17520 : : }
17521 : : return false;
17522 : :
17523 : 3 : case E_V2HFmode:
17524 : 3 : case E_V2BFmode:
17525 : 3 : if (TARGET_SSE2)
17526 : : {
17527 : 6 : val = force_reg (GET_MODE_INNER (mode), val);
17528 : 3 : rtx x = gen_rtx_VEC_DUPLICATE (mode, val);
17529 : 3 : emit_insn (gen_rtx_SET (target, x));
17530 : 3 : return true;
17531 : : }
17532 : : return false;
17533 : :
17534 : 283 : case E_V8QImode:
17535 : 283 : case E_V4QImode:
17536 : 283 : if (!mmx_ok)
17537 : : return false;
17538 : 279 : goto widen;
17539 : :
17540 : 9643 : case E_V8HImode:
17541 : 9643 : if (CONST_INT_P (val))
17542 : 9161 : goto widen;
17543 : : /* FALLTHRU */
17544 : :
17545 : 796 : case E_V8HFmode:
17546 : 796 : case E_V8BFmode:
17547 : 796 : if (TARGET_AVX2)
17548 : 392 : return ix86_vector_duplicate_value (mode, target, val);
17549 : :
17550 : 404 : if (TARGET_SSE2)
17551 : : {
17552 : 1107 : struct expand_vec_perm_d dperm;
17553 : 1107 : rtx tmp1, tmp2;
17554 : :
17555 : 404 : permute:
17556 : 1107 : memset (&dperm, 0, sizeof (dperm));
17557 : 1107 : dperm.target = target;
17558 : 1107 : dperm.vmode = mode;
17559 : 1107 : dperm.nelt = GET_MODE_NUNITS (mode);
17560 : 1107 : dperm.op0 = dperm.op1 = gen_reg_rtx (mode);
17561 : 1107 : dperm.one_operand_p = true;
17562 : :
17563 : 1107 : if (mode == V8HFmode || mode == V8BFmode)
17564 : : {
17565 : 3 : tmp1 = force_reg (GET_MODE_INNER (mode), val);
17566 : 3 : tmp2 = gen_reg_rtx (mode);
17567 : 3 : emit_insn (gen_vec_set_0 (mode, tmp2, CONST0_RTX (mode), tmp1));
17568 : 3 : tmp1 = gen_lowpart (mode, tmp2);
17569 : : }
17570 : : else
17571 : : {
17572 : : /* Extend to SImode using a paradoxical SUBREG. */
17573 : 1104 : tmp1 = gen_reg_rtx (SImode);
17574 : 1104 : emit_move_insn (tmp1, gen_lowpart (SImode, val));
17575 : :
17576 : : /* Insert the SImode value as
17577 : : low element of a V4SImode vector. */
17578 : 1104 : tmp2 = gen_reg_rtx (V4SImode);
17579 : 1104 : emit_insn (gen_vec_setv4si_0 (tmp2, CONST0_RTX (V4SImode), tmp1));
17580 : 1104 : tmp1 = gen_lowpart (mode, tmp2);
17581 : : }
17582 : :
17583 : 1107 : emit_move_insn (dperm.op0, tmp1);
17584 : 1107 : ok = (expand_vec_perm_1 (&dperm)
17585 : 1107 : || expand_vec_perm_broadcast_1 (&dperm));
17586 : 0 : gcc_assert (ok);
17587 : 1107 : return ok;
17588 : : }
17589 : 0 : goto widen;
17590 : :
17591 : 5536 : case E_V16QImode:
17592 : 5536 : if (CONST_INT_P (val))
17593 : 4776 : goto widen;
17594 : 760 : if (TARGET_AVX2)
17595 : 57 : return ix86_vector_duplicate_value (mode, target, val);
17596 : :
17597 : 703 : if (TARGET_SSE2)
17598 : 703 : goto permute;
17599 : 0 : goto widen;
17600 : :
17601 : 16411 : widen:
17602 : : /* Replicate the value once into the next wider mode and recurse. */
17603 : 16411 : {
17604 : 16411 : machine_mode smode, wsmode, wvmode;
17605 : 16411 : rtx x;
17606 : :
17607 : 16411 : smode = GET_MODE_INNER (mode);
17608 : 16411 : wvmode = get_mode_wider_vector (mode);
17609 : 16411 : wsmode = GET_MODE_INNER (wvmode);
17610 : :
17611 : 16411 : val = convert_modes (wsmode, smode, val, true);
17612 : :
17613 : 16411 : if (CONST_INT_P (val))
17614 : : {
17615 : 32266 : x = simplify_binary_operation (ASHIFT, wsmode, val,
17616 : 16133 : GEN_INT (GET_MODE_BITSIZE (smode)));
17617 : 16133 : val = simplify_binary_operation (IOR, wsmode, val, x);
17618 : : }
17619 : 278 : else if (smode == QImode && !TARGET_PARTIAL_REG_STALL)
17620 : 278 : emit_insn (gen_insv_1 (wsmode, val, val));
17621 : : else
17622 : : {
17623 : 0 : x = expand_simple_binop (wsmode, ASHIFT, val,
17624 : 0 : GEN_INT (GET_MODE_BITSIZE (smode)),
17625 : : NULL_RTX, 1, OPTAB_LIB_WIDEN);
17626 : 0 : val = expand_simple_binop (wsmode, IOR, val, x, x, 1,
17627 : : OPTAB_LIB_WIDEN);
17628 : : }
17629 : :
17630 : 16411 : x = gen_reg_rtx (wvmode);
17631 : 16411 : ok = ix86_expand_vector_init_duplicate (mmx_ok, wvmode, x, val);
17632 : 16411 : if (!ok)
17633 : : return false;
17634 : 16410 : emit_move_insn (target, gen_lowpart (GET_MODE (target), x));
17635 : 16410 : return true;
17636 : : }
17637 : :
17638 : 1428 : case E_V16HImode:
17639 : 1428 : case E_V32QImode:
17640 : 1428 : if (CONST_INT_P (val))
17641 : 1131 : goto widen;
17642 : : /* FALLTHRU */
17643 : :
17644 : 380 : case E_V16HFmode:
17645 : 380 : case E_V16BFmode:
17646 : 380 : if (TARGET_AVX2)
17647 : 352 : return ix86_vector_duplicate_value (mode, target, val);
17648 : : else
17649 : : {
17650 : 28 : machine_mode hvmode;
17651 : 28 : switch (mode)
17652 : : {
17653 : : case V16HImode:
17654 : : hvmode = V8HImode;
17655 : : break;
17656 : 0 : case V16HFmode:
17657 : 0 : hvmode = V8HFmode;
17658 : 0 : break;
17659 : 1 : case V16BFmode:
17660 : 1 : hvmode = V8BFmode;
17661 : 1 : break;
17662 : 14 : case V32QImode:
17663 : 14 : hvmode = V16QImode;
17664 : 14 : break;
17665 : 0 : default:
17666 : 0 : gcc_unreachable ();
17667 : : }
17668 : 28 : rtx x = gen_reg_rtx (hvmode);
17669 : :
17670 : 28 : ok = ix86_expand_vector_init_duplicate (false, hvmode, x, val);
17671 : 28 : if (!ok)
17672 : : return false;
17673 : :
17674 : 28 : x = gen_rtx_VEC_CONCAT (mode, x, x);
17675 : 28 : emit_insn (gen_rtx_SET (target, x));
17676 : : }
17677 : 28 : return true;
17678 : :
17679 : 1196 : case E_V32HImode:
17680 : 1196 : case E_V64QImode:
17681 : 1196 : if (CONST_INT_P (val))
17682 : 1064 : goto widen;
17683 : : /* FALLTHRU */
17684 : :
17685 : 211 : case E_V32HFmode:
17686 : 211 : case E_V32BFmode:
17687 : 211 : if (TARGET_AVX512BW)
17688 : 191 : return ix86_vector_duplicate_value (mode, target, val);
17689 : : else
17690 : : {
17691 : 20 : machine_mode hvmode;
17692 : 20 : switch (mode)
17693 : : {
17694 : : case V32HImode:
17695 : : hvmode = V16HImode;
17696 : : break;
17697 : 0 : case V32HFmode:
17698 : 0 : hvmode = V16HFmode;
17699 : 0 : break;
17700 : 1 : case V32BFmode:
17701 : 1 : hvmode = V16BFmode;
17702 : 1 : break;
17703 : 10 : case V64QImode:
17704 : 10 : hvmode = V32QImode;
17705 : 10 : break;
17706 : 0 : default:
17707 : 0 : gcc_unreachable ();
17708 : : }
17709 : 20 : rtx x = gen_reg_rtx (hvmode);
17710 : :
17711 : 20 : ok = ix86_expand_vector_init_duplicate (false, hvmode, x, val);
17712 : 20 : if (!ok)
17713 : : return false;
17714 : :
17715 : 20 : x = gen_rtx_VEC_CONCAT (mode, x, x);
17716 : 20 : emit_insn (gen_rtx_SET (target, x));
17717 : : }
17718 : 20 : return true;
17719 : :
17720 : : default:
17721 : : return false;
17722 : : }
17723 : : }
17724 : :
17725 : : /* A subroutine of ix86_expand_vector_init. Store into TARGET a vector
17726 : : whose ONE_VAR element is VAR, and other elements are zero. Return true
17727 : : if successful. */
17728 : :
17729 : : bool
17730 : 11154 : ix86_expand_vector_init_one_nonzero (bool mmx_ok, machine_mode mode,
17731 : : rtx target, rtx var, int one_var)
17732 : : {
17733 : 11154 : machine_mode vsimode;
17734 : 11154 : rtx new_target;
17735 : 11154 : rtx x, tmp;
17736 : 11154 : bool use_vector_set = false;
17737 : 11154 : rtx (*gen_vec_set_0) (rtx, rtx, rtx) = NULL;
17738 : :
17739 : 11154 : switch (mode)
17740 : : {
17741 : 8693 : case E_V2DImode:
17742 : : /* For SSE4.1, we normally use vector set. But if the second
17743 : : element is zero and inter-unit moves are OK, we use movq
17744 : : instead. */
17745 : 8684 : use_vector_set = (TARGET_64BIT && TARGET_SSE4_1
17746 : 8798 : && !(TARGET_INTER_UNIT_MOVES_TO_VEC
17747 : : && one_var == 0));
17748 : : break;
17749 : 862 : case E_V16QImode:
17750 : 862 : case E_V4SImode:
17751 : 862 : case E_V4SFmode:
17752 : 862 : use_vector_set = TARGET_SSE4_1;
17753 : 862 : break;
17754 : 85 : case E_V8HImode:
17755 : 85 : use_vector_set = TARGET_SSE2;
17756 : 85 : gen_vec_set_0 = TARGET_AVX512FP16 && one_var == 0
17757 : 85 : ? gen_vec_setv8hi_0 : NULL;
17758 : : break;
17759 : 7 : case E_V8QImode:
17760 : 7 : use_vector_set = TARGET_MMX_WITH_SSE && TARGET_SSE4_1;
17761 : : break;
17762 : 13 : case E_V4HImode:
17763 : 13 : case E_V4HFmode:
17764 : 13 : case E_V4BFmode:
17765 : 13 : use_vector_set = TARGET_SSE || TARGET_3DNOW_A;
17766 : : break;
17767 : 23 : case E_V4QImode:
17768 : 23 : use_vector_set = TARGET_SSE4_1;
17769 : 23 : break;
17770 : 0 : case E_V32QImode:
17771 : 0 : use_vector_set = TARGET_AVX;
17772 : 0 : break;
17773 : 5 : case E_V16HImode:
17774 : 5 : use_vector_set = TARGET_AVX;
17775 : 5 : gen_vec_set_0 = TARGET_AVX512FP16 && one_var == 0
17776 : 5 : ? gen_vec_setv16hi_0 : NULL;
17777 : : break;
17778 : 5 : case E_V8SImode:
17779 : 5 : use_vector_set = TARGET_AVX;
17780 : 5 : gen_vec_set_0 = gen_vec_setv8si_0;
17781 : 5 : break;
17782 : 22 : case E_V8SFmode:
17783 : 22 : use_vector_set = TARGET_AVX;
17784 : 22 : gen_vec_set_0 = gen_vec_setv8sf_0;
17785 : 22 : break;
17786 : 13 : case E_V4DFmode:
17787 : 13 : use_vector_set = TARGET_AVX;
17788 : 13 : gen_vec_set_0 = gen_vec_setv4df_0;
17789 : 13 : break;
17790 : 7 : case E_V4DImode:
17791 : : /* Use ix86_expand_vector_set in 64bit mode only. */
17792 : 7 : use_vector_set = TARGET_AVX && TARGET_64BIT;
17793 : : gen_vec_set_0 = gen_vec_setv4di_0;
17794 : : break;
17795 : 17 : case E_V16SImode:
17796 : 17 : use_vector_set = TARGET_AVX512F && one_var == 0;
17797 : : gen_vec_set_0 = gen_vec_setv16si_0;
17798 : : break;
17799 : 22 : case E_V16SFmode:
17800 : 22 : use_vector_set = TARGET_AVX512F && one_var == 0;
17801 : : gen_vec_set_0 = gen_vec_setv16sf_0;
17802 : : break;
17803 : 0 : case E_V8DFmode:
17804 : 0 : use_vector_set = TARGET_AVX512F && one_var == 0;
17805 : : gen_vec_set_0 = gen_vec_setv8df_0;
17806 : : break;
17807 : 2 : case E_V8DImode:
17808 : : /* Use ix86_expand_vector_set in 64bit mode only. */
17809 : 2 : use_vector_set = TARGET_AVX512F && TARGET_64BIT && one_var == 0;
17810 : : gen_vec_set_0 = gen_vec_setv8di_0;
17811 : : break;
17812 : 39 : case E_V8HFmode:
17813 : 39 : use_vector_set = TARGET_AVX512FP16 && one_var == 0;
17814 : : gen_vec_set_0 = gen_vec_setv8hf_0;
17815 : : break;
17816 : 9 : case E_V16HFmode:
17817 : 9 : use_vector_set = TARGET_AVX512FP16 && one_var == 0;
17818 : : gen_vec_set_0 = gen_vec_setv16hf_0;
17819 : : break;
17820 : 6 : case E_V32HFmode:
17821 : 6 : use_vector_set = TARGET_AVX512FP16 && one_var == 0;
17822 : : gen_vec_set_0 = gen_vec_setv32hf_0;
17823 : : break;
17824 : 2 : case E_V8BFmode:
17825 : 2 : use_vector_set = TARGET_AVX512FP16 && one_var == 0;
17826 : : gen_vec_set_0 = gen_vec_setv8bf_0;
17827 : : break;
17828 : 0 : case E_V16BFmode:
17829 : 0 : use_vector_set = TARGET_AVX512FP16 && one_var == 0;
17830 : : gen_vec_set_0 = gen_vec_setv16bf_0;
17831 : : break;
17832 : 0 : case E_V32BFmode:
17833 : 0 : use_vector_set = TARGET_AVX512FP16 && one_var == 0;
17834 : : gen_vec_set_0 = gen_vec_setv32bf_0;
17835 : : break;
17836 : 4 : case E_V32HImode:
17837 : 4 : use_vector_set = TARGET_AVX512FP16 && one_var == 0;
17838 : : gen_vec_set_0 = gen_vec_setv32hi_0;
17839 : : default:
17840 : : break;
17841 : : }
17842 : :
17843 : 9721 : if (use_vector_set)
17844 : : {
17845 : 851 : if (gen_vec_set_0 && one_var == 0)
17846 : : {
17847 : 354 : var = force_reg (GET_MODE_INNER (mode), var);
17848 : 177 : emit_insn (gen_vec_set_0 (target, CONST0_RTX (mode), var));
17849 : 177 : return true;
17850 : : }
17851 : 674 : emit_insn (gen_rtx_SET (target, CONST0_RTX (mode)));
17852 : 1348 : var = force_reg (GET_MODE_INNER (mode), var);
17853 : 674 : ix86_expand_vector_set (mmx_ok, target, var, one_var);
17854 : 674 : return true;
17855 : : }
17856 : :
17857 : 10303 : switch (mode)
17858 : : {
17859 : 1234 : case E_V2SFmode:
17860 : 1234 : case E_V2SImode:
17861 : 1234 : if (!mmx_ok)
17862 : : return false;
17863 : : /* FALLTHRU */
17864 : :
17865 : 8906 : case E_V2DFmode:
17866 : 8906 : case E_V2DImode:
17867 : 8906 : if (one_var != 0)
17868 : : return false;
17869 : 5450 : var = force_reg (GET_MODE_INNER (mode), var);
17870 : 5450 : x = gen_rtx_VEC_CONCAT (mode, var, CONST0_RTX (GET_MODE_INNER (mode)));
17871 : 2725 : emit_insn (gen_rtx_SET (target, x));
17872 : 2725 : return true;
17873 : :
17874 : 308 : case E_V4SFmode:
17875 : 308 : case E_V4SImode:
17876 : 308 : if (!REG_P (target) || REGNO (target) < FIRST_PSEUDO_REGISTER)
17877 : 0 : new_target = gen_reg_rtx (mode);
17878 : : else
17879 : : new_target = target;
17880 : 616 : var = force_reg (GET_MODE_INNER (mode), var);
17881 : 308 : x = gen_rtx_VEC_DUPLICATE (mode, var);
17882 : 308 : x = gen_rtx_VEC_MERGE (mode, x, CONST0_RTX (mode), const1_rtx);
17883 : 308 : emit_insn (gen_rtx_SET (new_target, x));
17884 : 308 : if (one_var != 0)
17885 : : {
17886 : : /* We need to shuffle the value to the correct position, so
17887 : : create a new pseudo to store the intermediate result. */
17888 : :
17889 : : /* With SSE2, we can use the integer shuffle insns. */
17890 : 40 : if (mode != V4SFmode && TARGET_SSE2)
17891 : : {
17892 : 27 : emit_insn (gen_sse2_pshufd_1 (new_target, new_target,
17893 : : const1_rtx,
17894 : 27 : GEN_INT (one_var == 1 ? 0 : 1),
17895 : 27 : GEN_INT (one_var == 2 ? 0 : 1),
17896 : 27 : GEN_INT (one_var == 3 ? 0 : 1)));
17897 : 27 : if (target != new_target)
17898 : 0 : emit_move_insn (target, new_target);
17899 : 27 : return true;
17900 : : }
17901 : :
17902 : : /* Otherwise convert the intermediate result to V4SFmode and
17903 : : use the SSE1 shuffle instructions. */
17904 : 0 : if (mode != V4SFmode)
17905 : : {
17906 : 0 : tmp = gen_reg_rtx (V4SFmode);
17907 : 0 : emit_move_insn (tmp, gen_lowpart (V4SFmode, new_target));
17908 : : }
17909 : : else
17910 : : tmp = new_target;
17911 : :
17912 : 43 : emit_insn (gen_sse_shufps_v4sf (tmp, tmp, tmp,
17913 : : const1_rtx,
17914 : 13 : GEN_INT (one_var == 1 ? 0 : 1),
17915 : : GEN_INT (one_var == 2 ? 0+4 : 1+4),
17916 : : GEN_INT (one_var == 3 ? 0+4 : 1+4)));
17917 : :
17918 : 13 : if (mode != V4SFmode)
17919 : 0 : emit_move_insn (target, gen_lowpart (V4SImode, tmp));
17920 : 13 : else if (tmp != target)
17921 : 0 : emit_move_insn (target, tmp);
17922 : : }
17923 : 268 : else if (target != new_target)
17924 : 0 : emit_move_insn (target, new_target);
17925 : : return true;
17926 : :
17927 : 12 : case E_V8HImode:
17928 : 12 : case E_V16QImode:
17929 : 12 : vsimode = V4SImode;
17930 : 12 : goto widen;
17931 : 2 : case E_V4HImode:
17932 : 2 : case E_V8QImode:
17933 : 2 : if (!mmx_ok)
17934 : : return false;
17935 : 2 : vsimode = V2SImode;
17936 : 2 : goto widen;
17937 : 14 : widen:
17938 : 14 : if (one_var != 0)
17939 : : return false;
17940 : :
17941 : : /* Zero extend the variable element to SImode and recurse. */
17942 : 14 : var = convert_modes (SImode, GET_MODE_INNER (mode), var, true);
17943 : :
17944 : 7 : x = gen_reg_rtx (vsimode);
17945 : 7 : if (!ix86_expand_vector_init_one_nonzero (mmx_ok, vsimode, x,
17946 : : var, one_var))
17947 : 0 : gcc_unreachable ();
17948 : :
17949 : 7 : emit_move_insn (target, gen_lowpart (mode, x));
17950 : 7 : return true;
17951 : :
17952 : : default:
17953 : : return false;
17954 : : }
17955 : : }
17956 : :
17957 : : /* A subroutine of ix86_expand_vector_init. Store into TARGET a vector
17958 : : consisting of the values in VALS. It is known that all elements
17959 : : except ONE_VAR are constants. Return true if successful. */
17960 : :
17961 : : static bool
17962 : 8421 : ix86_expand_vector_init_one_var (bool mmx_ok, machine_mode mode,
17963 : : rtx target, rtx vals, int one_var)
17964 : : {
17965 : 8421 : rtx var = XVECEXP (vals, 0, one_var);
17966 : 8421 : machine_mode wmode;
17967 : 8421 : rtx const_vec, x;
17968 : :
17969 : 8421 : const_vec = copy_rtx (vals);
17970 : 8421 : XVECEXP (const_vec, 0, one_var) = CONST0_RTX (GET_MODE_INNER (mode));
17971 : 8421 : const_vec = gen_rtx_CONST_VECTOR (mode, XVEC (const_vec, 0));
17972 : :
17973 : 8421 : switch (mode)
17974 : : {
17975 : : case E_V2DFmode:
17976 : : case E_V2DImode:
17977 : : case E_V2SFmode:
17978 : : case E_V2SImode:
17979 : : /* For the two element vectors, it's just as easy to use
17980 : : the general case. */
17981 : : return false;
17982 : :
17983 : 3 : case E_V4DImode:
17984 : : /* Use ix86_expand_vector_set in 64bit mode only. */
17985 : 3 : if (!TARGET_64BIT)
17986 : : return false;
17987 : : /* FALLTHRU */
17988 : : case E_V8HFmode:
17989 : : case E_V16HFmode:
17990 : : case E_V8BFmode:
17991 : : case E_V16BFmode:
17992 : : case E_V4DFmode:
17993 : : case E_V8SFmode:
17994 : : case E_V8SImode:
17995 : : case E_V16HImode:
17996 : : case E_V32QImode:
17997 : : case E_V4SFmode:
17998 : : case E_V4SImode:
17999 : : case E_V8HImode:
18000 : : case E_V4HImode:
18001 : : case E_V4HFmode:
18002 : : case E_V4BFmode:
18003 : : break;
18004 : :
18005 : 8 : case E_V16QImode:
18006 : 8 : if (TARGET_SSE4_1)
18007 : : break;
18008 : 8 : wmode = V8HImode;
18009 : 8 : goto widen;
18010 : 0 : case E_V8QImode:
18011 : 0 : if (TARGET_MMX_WITH_SSE && TARGET_SSE4_1)
18012 : : break;
18013 : 0 : wmode = V4HImode;
18014 : 0 : goto widen;
18015 : 29 : case E_V4QImode:
18016 : 29 : if (TARGET_SSE4_1)
18017 : : break;
18018 : : wmode = V2HImode;
18019 : 37 : widen:
18020 : : /* There's no way to set one QImode entry easily. Combine
18021 : : the variable value with its adjacent constant value, and
18022 : : promote to an HImode set. */
18023 : 37 : x = XVECEXP (vals, 0, one_var ^ 1);
18024 : 37 : if (one_var & 1)
18025 : : {
18026 : 12 : var = convert_modes (HImode, QImode, var, true);
18027 : 12 : var = expand_simple_binop (HImode, ASHIFT, var, GEN_INT (8),
18028 : : NULL_RTX, 1, OPTAB_LIB_WIDEN);
18029 : 12 : x = GEN_INT (INTVAL (x) & 0xff);
18030 : : }
18031 : : else
18032 : : {
18033 : 25 : var = convert_modes (HImode, QImode, var, true);
18034 : 25 : x = gen_int_mode (UINTVAL (x) << 8, HImode);
18035 : : }
18036 : 37 : if (x != const0_rtx)
18037 : 7 : var = expand_simple_binop (HImode, IOR, var, x, var,
18038 : : 1, OPTAB_LIB_WIDEN);
18039 : :
18040 : 37 : x = gen_reg_rtx (wmode);
18041 : 37 : emit_move_insn (x, gen_lowpart (wmode, const_vec));
18042 : 37 : ix86_expand_vector_set (mmx_ok, x, var, one_var >> 1);
18043 : :
18044 : 37 : emit_move_insn (target, gen_lowpart (mode, x));
18045 : 37 : return true;
18046 : :
18047 : : default:
18048 : : return false;
18049 : : }
18050 : :
18051 : 191 : emit_move_insn (target, const_vec);
18052 : 191 : ix86_expand_vector_set (mmx_ok, target, var, one_var);
18053 : 191 : return true;
18054 : : }
18055 : :
18056 : : /* A subroutine of ix86_expand_vector_init_general. Use vector
18057 : : concatenate to handle the most general case: all values variable,
18058 : : and none identical. */
18059 : :
18060 : : static void
18061 : 123329 : ix86_expand_vector_init_concat (machine_mode mode,
18062 : : rtx target, rtx *ops, int n)
18063 : : {
18064 : 123329 : machine_mode half_mode = VOIDmode;
18065 : 123329 : rtx half[2];
18066 : 123329 : rtvec v;
18067 : 123329 : int i, j;
18068 : :
18069 : 123329 : switch (n)
18070 : : {
18071 : 114821 : case 2:
18072 : 114821 : switch (mode)
18073 : : {
18074 : : case E_V32HFmode:
18075 : : half_mode = V16HFmode;
18076 : : break;
18077 : 0 : case E_V32BFmode:
18078 : 0 : half_mode = V16BFmode;
18079 : 0 : break;
18080 : 80 : case E_V16SImode:
18081 : 80 : half_mode = V8SImode;
18082 : 80 : break;
18083 : 33 : case E_V16SFmode:
18084 : 33 : half_mode = V8SFmode;
18085 : 33 : break;
18086 : 86 : case E_V8DImode:
18087 : 86 : half_mode = V4DImode;
18088 : 86 : break;
18089 : 73 : case E_V8DFmode:
18090 : 73 : half_mode = V4DFmode;
18091 : 73 : break;
18092 : 0 : case E_V16HFmode:
18093 : 0 : half_mode = V8HFmode;
18094 : 0 : break;
18095 : 0 : case E_V16BFmode:
18096 : 0 : half_mode = V8BFmode;
18097 : 0 : break;
18098 : 197 : case E_V8SImode:
18099 : 197 : half_mode = V4SImode;
18100 : 197 : break;
18101 : 271 : case E_V8SFmode:
18102 : 271 : half_mode = V4SFmode;
18103 : 271 : break;
18104 : 296 : case E_V4DImode:
18105 : 296 : half_mode = V2DImode;
18106 : 296 : break;
18107 : 613 : case E_V4DFmode:
18108 : 613 : half_mode = V2DFmode;
18109 : 613 : break;
18110 : 5808 : case E_V4SImode:
18111 : 5808 : half_mode = V2SImode;
18112 : 5808 : break;
18113 : 2290 : case E_V4SFmode:
18114 : 2290 : half_mode = V2SFmode;
18115 : 2290 : break;
18116 : 68874 : case E_V2DImode:
18117 : 68874 : half_mode = DImode;
18118 : 68874 : break;
18119 : 27149 : case E_V2SImode:
18120 : 27149 : half_mode = SImode;
18121 : 27149 : break;
18122 : 3480 : case E_V2DFmode:
18123 : 3480 : half_mode = DFmode;
18124 : 3480 : break;
18125 : 5571 : case E_V2SFmode:
18126 : 5571 : half_mode = SFmode;
18127 : 5571 : break;
18128 : 0 : default:
18129 : 0 : gcc_unreachable ();
18130 : : }
18131 : :
18132 : 114821 : if (!register_operand (ops[1], half_mode))
18133 : 50773 : ops[1] = force_reg (half_mode, ops[1]);
18134 : 114821 : if (!register_operand (ops[0], half_mode))
18135 : 39685 : ops[0] = force_reg (half_mode, ops[0]);
18136 : 114821 : emit_insn (gen_rtx_SET (target, gen_rtx_VEC_CONCAT (mode, ops[0],
18137 : : ops[1])));
18138 : 114821 : break;
18139 : :
18140 : 7877 : case 4:
18141 : 7877 : switch (mode)
18142 : : {
18143 : : case E_V4DImode:
18144 : : half_mode = V2DImode;
18145 : : break;
18146 : 531 : case E_V4DFmode:
18147 : 531 : half_mode = V2DFmode;
18148 : 531 : break;
18149 : 5029 : case E_V4SImode:
18150 : 5029 : half_mode = V2SImode;
18151 : 5029 : break;
18152 : 2147 : case E_V4SFmode:
18153 : 2147 : half_mode = V2SFmode;
18154 : 2147 : break;
18155 : 0 : default:
18156 : 0 : gcc_unreachable ();
18157 : : }
18158 : 7877 : goto half;
18159 : :
18160 : 539 : case 8:
18161 : 539 : switch (mode)
18162 : : {
18163 : : case E_V8DImode:
18164 : : half_mode = V4DImode;
18165 : : break;
18166 : 73 : case E_V8DFmode:
18167 : 73 : half_mode = V4DFmode;
18168 : 73 : break;
18169 : 156 : case E_V8SImode:
18170 : 156 : half_mode = V4SImode;
18171 : 156 : break;
18172 : 265 : case E_V8SFmode:
18173 : 265 : half_mode = V4SFmode;
18174 : 265 : break;
18175 : 0 : default:
18176 : 0 : gcc_unreachable ();
18177 : : }
18178 : 539 : goto half;
18179 : :
18180 : 92 : case 16:
18181 : 92 : switch (mode)
18182 : : {
18183 : : case E_V16SImode:
18184 : : half_mode = V8SImode;
18185 : : break;
18186 : 33 : case E_V16SFmode:
18187 : 33 : half_mode = V8SFmode;
18188 : 33 : break;
18189 : 0 : default:
18190 : 0 : gcc_unreachable ();
18191 : : }
18192 : 92 : goto half;
18193 : :
18194 : 8508 : half:
18195 : : /* FIXME: We process inputs backward to help RA. PR 36222. */
18196 : 8508 : i = n - 1;
18197 : 25524 : for (j = 1; j != -1; j--)
18198 : : {
18199 : 17016 : half[j] = gen_reg_rtx (half_mode);
18200 : 17016 : switch (n >> 1)
18201 : : {
18202 : 15754 : case 2:
18203 : 15754 : v = gen_rtvec (2, ops[i-1], ops[i]);
18204 : 15754 : i -= 2;
18205 : 15754 : break;
18206 : 1078 : case 4:
18207 : 1078 : v = gen_rtvec (4, ops[i-3], ops[i-2], ops[i-1], ops[i]);
18208 : 1078 : i -= 4;
18209 : 1078 : break;
18210 : 184 : case 8:
18211 : 368 : v = gen_rtvec (8, ops[i-7], ops[i-6], ops[i-5], ops[i-4],
18212 : 184 : ops[i-3], ops[i-2], ops[i-1], ops[i]);
18213 : 184 : i -= 8;
18214 : 184 : break;
18215 : 0 : default:
18216 : 0 : gcc_unreachable ();
18217 : : }
18218 : 17016 : ix86_expand_vector_init (false, half[j],
18219 : : gen_rtx_PARALLEL (half_mode, v));
18220 : : }
18221 : :
18222 : 8508 : ix86_expand_vector_init_concat (mode, target, half, 2);
18223 : 8508 : break;
18224 : :
18225 : 0 : default:
18226 : 0 : gcc_unreachable ();
18227 : : }
18228 : 123329 : }
18229 : :
18230 : : /* A subroutine of ix86_expand_vector_init_general. Use vector
18231 : : interleave to handle the most general case: all values variable,
18232 : : and none identical. */
18233 : :
18234 : : static void
18235 : 3823 : ix86_expand_vector_init_interleave (machine_mode mode,
18236 : : rtx target, rtx *ops, int n)
18237 : : {
18238 : 3823 : machine_mode first_imode, second_imode, third_imode, inner_mode;
18239 : 3823 : int i, j;
18240 : 3823 : rtx op, op0, op1;
18241 : 3823 : rtx (*gen_load_even) (rtx, rtx, rtx);
18242 : 3823 : rtx (*gen_interleave_first_low) (rtx, rtx, rtx);
18243 : 3823 : rtx (*gen_interleave_second_low) (rtx, rtx, rtx);
18244 : :
18245 : 3823 : switch (mode)
18246 : : {
18247 : : case E_V8HFmode:
18248 : : gen_load_even = gen_vec_interleave_lowv8hf;
18249 : : gen_interleave_first_low = gen_vec_interleave_lowv4si;
18250 : : gen_interleave_second_low = gen_vec_interleave_lowv2di;
18251 : : inner_mode = HFmode;
18252 : : first_imode = V4SImode;
18253 : : second_imode = V2DImode;
18254 : : third_imode = VOIDmode;
18255 : : break;
18256 : 487 : case E_V8BFmode:
18257 : 487 : gen_load_even = gen_vec_interleave_lowv8bf;
18258 : 487 : gen_interleave_first_low = gen_vec_interleave_lowv4si;
18259 : 487 : gen_interleave_second_low = gen_vec_interleave_lowv2di;
18260 : 487 : inner_mode = BFmode;
18261 : 487 : first_imode = V4SImode;
18262 : 487 : second_imode = V2DImode;
18263 : 487 : third_imode = VOIDmode;
18264 : 487 : break;
18265 : 738 : case E_V8HImode:
18266 : 738 : gen_load_even = gen_vec_setv8hi;
18267 : 738 : gen_interleave_first_low = gen_vec_interleave_lowv4si;
18268 : 738 : gen_interleave_second_low = gen_vec_interleave_lowv2di;
18269 : 738 : inner_mode = HImode;
18270 : 738 : first_imode = V4SImode;
18271 : 738 : second_imode = V2DImode;
18272 : 738 : third_imode = VOIDmode;
18273 : 738 : break;
18274 : 372 : case E_V16QImode:
18275 : 372 : gen_load_even = gen_vec_setv16qi;
18276 : 372 : gen_interleave_first_low = gen_vec_interleave_lowv8hi;
18277 : 372 : gen_interleave_second_low = gen_vec_interleave_lowv4si;
18278 : 372 : inner_mode = QImode;
18279 : 372 : first_imode = V8HImode;
18280 : 372 : second_imode = V4SImode;
18281 : 372 : third_imode = V2DImode;
18282 : 372 : break;
18283 : 0 : default:
18284 : 0 : gcc_unreachable ();
18285 : : }
18286 : :
18287 : 20603 : for (i = 0; i < n; i++)
18288 : : {
18289 : 16780 : op = ops [i + i];
18290 : 16780 : if (inner_mode == HFmode || inner_mode == BFmode)
18291 : : {
18292 : 10852 : rtx even, odd;
18293 : : /* Use vpuncklwd to pack 2 HFmode or BFmode. */
18294 : 1948 : machine_mode vec_mode =
18295 : 10852 : (inner_mode == HFmode) ? V8HFmode : V8BFmode;
18296 : 10852 : op0 = gen_reg_rtx (vec_mode);
18297 : 10852 : even = lowpart_subreg (vec_mode,
18298 : : force_reg (inner_mode, op), inner_mode);
18299 : 10852 : odd = lowpart_subreg (vec_mode,
18300 : 10852 : force_reg (inner_mode, ops[i + i + 1]),
18301 : : inner_mode);
18302 : 10852 : emit_insn (gen_load_even (op0, even, odd));
18303 : : }
18304 : : else
18305 : : {
18306 : : /* Extend the odd elment to SImode using a paradoxical SUBREG. */
18307 : 5928 : op0 = gen_reg_rtx (SImode);
18308 : 5928 : emit_move_insn (op0, gen_lowpart (SImode, op));
18309 : :
18310 : : /* Insert the SImode value as low element of V4SImode vector. */
18311 : 5928 : op1 = gen_reg_rtx (V4SImode);
18312 : 5928 : op0 = gen_rtx_VEC_MERGE (V4SImode,
18313 : : gen_rtx_VEC_DUPLICATE (V4SImode,
18314 : : op0),
18315 : : CONST0_RTX (V4SImode),
18316 : : const1_rtx);
18317 : 5928 : emit_insn (gen_rtx_SET (op1, op0));
18318 : :
18319 : : /* Cast the V4SImode vector back to a vector in orignal mode. */
18320 : 5928 : op0 = gen_reg_rtx (mode);
18321 : 5928 : emit_move_insn (op0, gen_lowpart (mode, op1));
18322 : :
18323 : : /* Load even elements into the second position. */
18324 : 5928 : emit_insn (gen_load_even (op0,
18325 : : force_reg (inner_mode,
18326 : 5928 : ops[i + i + 1]),
18327 : : const1_rtx));
18328 : : }
18329 : :
18330 : : /* Cast vector to FIRST_IMODE vector. */
18331 : 16780 : ops[i] = gen_reg_rtx (first_imode);
18332 : 16780 : emit_move_insn (ops[i], gen_lowpart (first_imode, op0));
18333 : : }
18334 : :
18335 : : /* Interleave low FIRST_IMODE vectors. */
18336 : 12213 : for (i = j = 0; i < n; i += 2, j++)
18337 : : {
18338 : 8390 : op0 = gen_reg_rtx (first_imode);
18339 : 8390 : emit_insn (gen_interleave_first_low (op0, ops[i], ops[i + 1]));
18340 : :
18341 : : /* Cast FIRST_IMODE vector to SECOND_IMODE vector. */
18342 : 8390 : ops[j] = gen_reg_rtx (second_imode);
18343 : 8390 : emit_move_insn (ops[j], gen_lowpart (second_imode, op0));
18344 : : }
18345 : :
18346 : : /* Interleave low SECOND_IMODE vectors. */
18347 : 3823 : switch (second_imode)
18348 : : {
18349 : : case E_V4SImode:
18350 : 1116 : for (i = j = 0; i < n / 2; i += 2, j++)
18351 : : {
18352 : 744 : op0 = gen_reg_rtx (second_imode);
18353 : 744 : emit_insn (gen_interleave_second_low (op0, ops[i],
18354 : 744 : ops[i + 1]));
18355 : :
18356 : : /* Cast the SECOND_IMODE vector to the THIRD_IMODE
18357 : : vector. */
18358 : 744 : ops[j] = gen_reg_rtx (third_imode);
18359 : 744 : emit_move_insn (ops[j], gen_lowpart (third_imode, op0));
18360 : : }
18361 : : second_imode = V2DImode;
18362 : : gen_interleave_second_low = gen_vec_interleave_lowv2di;
18363 : : /* FALLTHRU */
18364 : :
18365 : 3823 : case E_V2DImode:
18366 : 3823 : op0 = gen_reg_rtx (second_imode);
18367 : 3823 : emit_insn (gen_interleave_second_low (op0, ops[0],
18368 : : ops[1]));
18369 : :
18370 : : /* Cast the SECOND_IMODE vector back to a vector on original
18371 : : mode. */
18372 : 3823 : emit_insn (gen_rtx_SET (target, gen_lowpart (mode, op0)));
18373 : 3823 : break;
18374 : :
18375 : : default:
18376 : : gcc_unreachable ();
18377 : : }
18378 : 3823 : }
18379 : :
18380 : : /* A subroutine of ix86_expand_vector_init. Handle the most general case:
18381 : : all values variable, and none identical. */
18382 : :
18383 : : static void
18384 : 123915 : ix86_expand_vector_init_general (bool mmx_ok, machine_mode mode,
18385 : : rtx target, rtx vals)
18386 : : {
18387 : 123915 : rtx ops[64], op0, op1, op2, op3, op4, op5;
18388 : 123915 : machine_mode half_mode = VOIDmode;
18389 : 123915 : machine_mode quarter_mode = VOIDmode;
18390 : 123915 : machine_mode int_inner_mode = VOIDmode;
18391 : 123915 : int n, i;
18392 : :
18393 : 123915 : switch (mode)
18394 : : {
18395 : 32720 : case E_V2SFmode:
18396 : 32720 : case E_V2SImode:
18397 : 32720 : if (!mmx_ok && !TARGET_SSE)
18398 : : break;
18399 : : /* FALLTHRU */
18400 : :
18401 : 113582 : case E_V16SImode:
18402 : 113582 : case E_V16SFmode:
18403 : 113582 : case E_V8DFmode:
18404 : 113582 : case E_V8DImode:
18405 : 113582 : case E_V8SFmode:
18406 : 113582 : case E_V8SImode:
18407 : 113582 : case E_V4DFmode:
18408 : 113582 : case E_V4DImode:
18409 : 113582 : case E_V4SFmode:
18410 : 113582 : case E_V4SImode:
18411 : 113582 : case E_V2DFmode:
18412 : 113582 : case E_V2DImode:
18413 : 113582 : n = GET_MODE_NUNITS (mode);
18414 : 361022 : for (i = 0; i < n; i++)
18415 : 247440 : ops[i] = XVECEXP (vals, 0, i);
18416 : 113582 : ix86_expand_vector_init_concat (mode, target, ops, n);
18417 : 229212 : return;
18418 : :
18419 : : case E_V2TImode:
18420 : 135 : for (i = 0; i < 2; i++)
18421 : 90 : ops[i] = gen_lowpart (V2DImode, XVECEXP (vals, 0, i));
18422 : 45 : op0 = gen_reg_rtx (V4DImode);
18423 : 45 : ix86_expand_vector_init_concat (V4DImode, op0, ops, 2);
18424 : 45 : emit_move_insn (target, gen_lowpart (GET_MODE (target), op0));
18425 : 45 : return;
18426 : :
18427 : : case E_V4TImode:
18428 : 195 : for (i = 0; i < 4; i++)
18429 : 156 : ops[i] = gen_lowpart (V2DImode, XVECEXP (vals, 0, i));
18430 : 39 : ops[4] = gen_reg_rtx (V4DImode);
18431 : 39 : ix86_expand_vector_init_concat (V4DImode, ops[4], ops, 2);
18432 : 39 : ops[5] = gen_reg_rtx (V4DImode);
18433 : 39 : ix86_expand_vector_init_concat (V4DImode, ops[5], ops + 2, 2);
18434 : 39 : op0 = gen_reg_rtx (V8DImode);
18435 : 39 : ix86_expand_vector_init_concat (V8DImode, op0, ops + 4, 2);
18436 : 39 : emit_move_insn (target, gen_lowpart (GET_MODE (target), op0));
18437 : 39 : return;
18438 : :
18439 : 68 : case E_V32QImode:
18440 : 68 : half_mode = V16QImode;
18441 : 68 : goto half;
18442 : :
18443 : 64 : case E_V16HImode:
18444 : 64 : half_mode = V8HImode;
18445 : 64 : goto half;
18446 : :
18447 : 237 : case E_V16HFmode:
18448 : 237 : half_mode = V8HFmode;
18449 : 237 : goto half;
18450 : :
18451 : 95 : case E_V16BFmode:
18452 : 95 : half_mode = V8BFmode;
18453 : 95 : goto half;
18454 : :
18455 : 464 : half:
18456 : 464 : n = GET_MODE_NUNITS (mode);
18457 : 8976 : for (i = 0; i < n; i++)
18458 : 8512 : ops[i] = XVECEXP (vals, 0, i);
18459 : 464 : op0 = gen_reg_rtx (half_mode);
18460 : 464 : op1 = gen_reg_rtx (half_mode);
18461 : 464 : ix86_expand_vector_init_interleave (half_mode, op0, ops,
18462 : : n >> 2);
18463 : 464 : ix86_expand_vector_init_interleave (half_mode, op1,
18464 : 464 : &ops [n >> 1], n >> 2);
18465 : 464 : emit_insn (gen_rtx_SET (target, gen_rtx_VEC_CONCAT (mode, op0, op1)));
18466 : 464 : return;
18467 : :
18468 : 56 : case E_V64QImode:
18469 : 56 : quarter_mode = V16QImode;
18470 : 56 : half_mode = V32QImode;
18471 : 56 : goto quarter;
18472 : :
18473 : 71 : case E_V32HImode:
18474 : 71 : quarter_mode = V8HImode;
18475 : 71 : half_mode = V16HImode;
18476 : 71 : goto quarter;
18477 : :
18478 : 287 : case E_V32HFmode:
18479 : 287 : quarter_mode = V8HFmode;
18480 : 287 : half_mode = V16HFmode;
18481 : 287 : goto quarter;
18482 : :
18483 : 51 : case E_V32BFmode:
18484 : 51 : quarter_mode = V8BFmode;
18485 : 51 : half_mode = V16BFmode;
18486 : 51 : goto quarter;
18487 : :
18488 : 465 : quarter:
18489 : 465 : n = GET_MODE_NUNITS (mode);
18490 : 17137 : for (i = 0; i < n; i++)
18491 : 16672 : ops[i] = XVECEXP (vals, 0, i);
18492 : 465 : op0 = gen_reg_rtx (quarter_mode);
18493 : 465 : op1 = gen_reg_rtx (quarter_mode);
18494 : 465 : op2 = gen_reg_rtx (quarter_mode);
18495 : 465 : op3 = gen_reg_rtx (quarter_mode);
18496 : 465 : op4 = gen_reg_rtx (half_mode);
18497 : 465 : op5 = gen_reg_rtx (half_mode);
18498 : 465 : ix86_expand_vector_init_interleave (quarter_mode, op0, ops,
18499 : : n >> 3);
18500 : 465 : ix86_expand_vector_init_interleave (quarter_mode, op1,
18501 : 465 : &ops [n >> 2], n >> 3);
18502 : 465 : ix86_expand_vector_init_interleave (quarter_mode, op2,
18503 : 465 : &ops [n >> 1], n >> 3);
18504 : 465 : ix86_expand_vector_init_interleave (quarter_mode, op3,
18505 : 465 : &ops [(n >> 1) | (n >> 2)], n >> 3);
18506 : 465 : emit_insn (gen_rtx_SET (op4, gen_rtx_VEC_CONCAT (half_mode, op0, op1)));
18507 : 465 : emit_insn (gen_rtx_SET (op5, gen_rtx_VEC_CONCAT (half_mode, op2, op3)));
18508 : 465 : emit_insn (gen_rtx_SET (target, gen_rtx_VEC_CONCAT (mode, op4, op5)));
18509 : 465 : return;
18510 : :
18511 : 264 : case E_V16QImode:
18512 : 264 : if (!TARGET_SSE4_1)
18513 : : break;
18514 : : /* FALLTHRU */
18515 : :
18516 : 462 : case E_V8HImode:
18517 : 462 : if (!TARGET_SSE2)
18518 : : break;
18519 : :
18520 : : /* Don't use ix86_expand_vector_init_interleave if we can't
18521 : : move from GPR to SSE register directly. */
18522 : 462 : if (!TARGET_INTER_UNIT_MOVES_TO_VEC)
18523 : : break;
18524 : : /* FALLTHRU */
18525 : :
18526 : 1035 : case E_V8HFmode:
18527 : 1035 : case E_V8BFmode:
18528 : :
18529 : 1035 : n = GET_MODE_NUNITS (mode);
18530 : 9411 : for (i = 0; i < n; i++)
18531 : 8376 : ops[i] = XVECEXP (vals, 0, i);
18532 : 1035 : ix86_expand_vector_init_interleave (mode, target, ops, n >> 1);
18533 : 1035 : return;
18534 : :
18535 : : case E_V4HFmode:
18536 : : case E_V4BFmode:
18537 : : case E_V2HFmode:
18538 : : case E_V2BFmode:
18539 : 8285 : int_inner_mode = HImode;
18540 : : break;
18541 : :
18542 : : case E_V4HImode:
18543 : : case E_V8QImode:
18544 : :
18545 : : case E_V2HImode:
18546 : : case E_V4QImode:
18547 : : break;
18548 : :
18549 : 0 : default:
18550 : 0 : gcc_unreachable ();
18551 : : }
18552 : :
18553 : 8285 : {
18554 : 8285 : int i, j, n_elts, n_words, n_elt_per_word;
18555 : 8285 : machine_mode tmp_mode, inner_mode;
18556 : 8285 : rtx words[4], shift;
18557 : :
18558 : 16692 : tmp_mode = (GET_MODE_SIZE (mode) < UNITS_PER_WORD) ? SImode : word_mode;
18559 : :
18560 : 8285 : inner_mode = GET_MODE_INNER (mode);
18561 : 8285 : n_elts = GET_MODE_NUNITS (mode);
18562 : 16570 : n_words = GET_MODE_SIZE (mode) / GET_MODE_SIZE (tmp_mode);
18563 : 8285 : n_elt_per_word = n_elts / n_words;
18564 : 8285 : shift = GEN_INT (GET_MODE_BITSIZE (inner_mode));
18565 : :
18566 : 16897 : for (i = 0; i < n_words; ++i)
18567 : : {
18568 : : rtx word = NULL_RTX;
18569 : :
18570 : 45098 : for (j = 0; j < n_elt_per_word; ++j)
18571 : : {
18572 : 36486 : rtx elt = XVECEXP (vals, 0, (i+1)*n_elt_per_word - j - 1);
18573 : 36486 : if (int_inner_mode != E_VOIDmode)
18574 : : {
18575 : 134 : gcc_assert (TARGET_SSE2 && int_inner_mode == HImode);
18576 : 134 : rtx tmp = gen_reg_rtx (int_inner_mode);
18577 : 134 : elt = lowpart_subreg (int_inner_mode,
18578 : : force_reg (inner_mode, elt),
18579 : : inner_mode);
18580 : 134 : emit_move_insn (tmp, elt);
18581 : 134 : elt = tmp;
18582 : : }
18583 : 36486 : elt = convert_modes (tmp_mode, inner_mode, elt, true);
18584 : :
18585 : 36486 : if (j == 0)
18586 : : word = elt;
18587 : : else
18588 : : {
18589 : 27874 : word = expand_simple_binop (tmp_mode, ASHIFT, word, shift,
18590 : : NULL_RTX, 1, OPTAB_LIB_WIDEN);
18591 : 27874 : word = expand_simple_binop (tmp_mode, IOR, word, elt,
18592 : : NULL_RTX, 1, OPTAB_LIB_WIDEN);
18593 : : }
18594 : : }
18595 : :
18596 : 8612 : words[i] = word;
18597 : : }
18598 : :
18599 : 8285 : if (n_words == 1)
18600 : 7958 : emit_move_insn (target, gen_lowpart (mode, words[0]));
18601 : 327 : else if (n_words == 2)
18602 : : {
18603 : 327 : gcc_assert (tmp_mode == DImode || tmp_mode == SImode);
18604 : 327 : machine_mode concat_mode = tmp_mode == DImode ? V2DImode : V2SImode;
18605 : 327 : rtx tmp = gen_reg_rtx (concat_mode);
18606 : 327 : vals = gen_rtx_PARALLEL (concat_mode, gen_rtvec_v (2, words));
18607 : 327 : ix86_expand_vector_init_general (mmx_ok, concat_mode, tmp, vals);
18608 : 327 : emit_move_insn (target, gen_lowpart (mode, tmp));
18609 : : }
18610 : 0 : else if (n_words == 4)
18611 : : {
18612 : 0 : rtx tmp = gen_reg_rtx (V4SImode);
18613 : 0 : gcc_assert (tmp_mode == SImode);
18614 : 0 : vals = gen_rtx_PARALLEL (V4SImode, gen_rtvec_v (4, words));
18615 : 0 : ix86_expand_vector_init_general (false, V4SImode, tmp, vals);
18616 : 0 : emit_move_insn (target, gen_lowpart (mode, tmp));
18617 : : }
18618 : : else
18619 : 0 : gcc_unreachable ();
18620 : : }
18621 : : }
18622 : :
18623 : : /* Initialize vector TARGET via VALS. Suppress the use of MMX
18624 : : instructions unless MMX_OK is true. */
18625 : :
18626 : : void
18627 : 135021 : ix86_expand_vector_init (bool mmx_ok, rtx target, rtx vals)
18628 : : {
18629 : 135021 : machine_mode mode = GET_MODE (target);
18630 : 135021 : machine_mode inner_mode = GET_MODE_INNER (mode);
18631 : 135021 : int n_elts = GET_MODE_NUNITS (mode);
18632 : 135021 : int n_var = 0, one_var = -1;
18633 : 135021 : bool all_same = true, all_const_zero = true;
18634 : 135021 : int i;
18635 : 135021 : rtx x;
18636 : :
18637 : : /* Handle first initialization from vector elts. */
18638 : 135021 : if (n_elts != XVECLEN (vals, 0))
18639 : : {
18640 : 1077 : rtx subtarget = target;
18641 : 1077 : x = XVECEXP (vals, 0, 0);
18642 : 2154 : gcc_assert (GET_MODE_INNER (GET_MODE (x)) == inner_mode);
18643 : 2154 : if (GET_MODE_NUNITS (GET_MODE (x)) * 2 == n_elts)
18644 : : {
18645 : 1077 : rtx ops[2] = { XVECEXP (vals, 0, 0), XVECEXP (vals, 0, 1) };
18646 : 1077 : if (inner_mode == QImode
18647 : 1077 : || inner_mode == HImode
18648 : 1077 : || inner_mode == TImode
18649 : : || inner_mode == HFmode
18650 : : || inner_mode == BFmode)
18651 : : {
18652 : 134 : unsigned int n_bits = n_elts * GET_MODE_SIZE (inner_mode);
18653 : 134 : scalar_mode elt_mode = inner_mode == TImode ? DImode : SImode;
18654 : 134 : n_bits /= GET_MODE_SIZE (elt_mode);
18655 : 134 : mode = mode_for_vector (elt_mode, n_bits).require ();
18656 : 134 : inner_mode = mode_for_vector (elt_mode, n_bits / 2).require ();
18657 : 134 : ops[0] = gen_lowpart (inner_mode, ops[0]);
18658 : 134 : ops[1] = gen_lowpart (inner_mode, ops[1]);
18659 : 134 : subtarget = gen_reg_rtx (mode);
18660 : : }
18661 : 1077 : ix86_expand_vector_init_concat (mode, subtarget, ops, 2);
18662 : 1077 : if (subtarget != target)
18663 : 134 : emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
18664 : 1077 : return;
18665 : : }
18666 : 0 : gcc_unreachable ();
18667 : : }
18668 : :
18669 : 488482 : for (i = 0; i < n_elts; ++i)
18670 : : {
18671 : 354538 : x = XVECEXP (vals, 0, i);
18672 : 687913 : if (!(CONST_SCALAR_INT_P (x)
18673 : 337368 : || CONST_DOUBLE_P (x)
18674 : : || CONST_FIXED_P (x)))
18675 : 333375 : n_var++, one_var = i;
18676 : 21163 : else if (x != CONST0_RTX (inner_mode))
18677 : 3250 : all_const_zero = false;
18678 : 354538 : if (i > 0 && !rtx_equal_p (x, XVECEXP (vals, 0, 0)))
18679 : : all_same = false;
18680 : : }
18681 : :
18682 : : /* Handle the zero vector as special case. */
18683 : 133944 : if (n_var == 0 && all_const_zero)
18684 : : {
18685 : 346 : emit_move_insn (target, CONST0_RTX (mode));
18686 : 346 : return;
18687 : : }
18688 : :
18689 : : /* If all values are identical, broadcast the value. */
18690 : 133598 : if (all_same
18691 : 140616 : && ix86_expand_vector_init_duplicate (mmx_ok, mode, target,
18692 : 7018 : XVECEXP (vals, 0, 0)))
18693 : : return;
18694 : :
18695 : : /* Constants are best loaded from the constant pool. */
18696 : 127741 : if (n_var == 0)
18697 : : {
18698 : 41 : emit_move_insn (target, gen_rtx_CONST_VECTOR (mode, XVEC (vals, 0)));
18699 : 41 : return;
18700 : : }
18701 : :
18702 : : /* Values where only one field is non-constant are best loaded from
18703 : : the pool and overwritten via move later. */
18704 : 127700 : if (n_var == 1)
18705 : : {
18706 : 12305 : if (all_const_zero
18707 : 23452 : && ix86_expand_vector_init_one_nonzero (mmx_ok, mode, target,
18708 : 11147 : XVECEXP (vals, 0, one_var),
18709 : : one_var))
18710 : : return;
18711 : :
18712 : 8421 : if (ix86_expand_vector_init_one_var (mmx_ok, mode, target, vals, one_var))
18713 : : return;
18714 : : }
18715 : :
18716 : 123588 : ix86_expand_vector_init_general (mmx_ok, mode, target, vals);
18717 : : }
18718 : :
18719 : : /* Implemented as
18720 : : V setg (V v, int idx, T val)
18721 : : {
18722 : : V idxv = (V){idx, idx, idx, idx, idx, idx, idx, idx};
18723 : : V valv = (V){val, val, val, val, val, val, val, val};
18724 : : V mask = ((V){0, 1, 2, 3, 4, 5, 6, 7} == idxv);
18725 : : v = (v & ~mask) | (valv & mask);
18726 : : return v;
18727 : : }. */
18728 : : void
18729 : 128 : ix86_expand_vector_set_var (rtx target, rtx val, rtx idx)
18730 : : {
18731 : 128 : rtx vec[64];
18732 : 128 : machine_mode mode = GET_MODE (target);
18733 : 128 : machine_mode cmp_mode = mode;
18734 : 128 : int n_elts = GET_MODE_NUNITS (mode);
18735 : 128 : rtx valv,idxv,constv,idx_tmp;
18736 : 128 : bool ok = false;
18737 : :
18738 : : /* 512-bits vector byte/word broadcast and comparison only available
18739 : : under TARGET_AVX512BW, break 512-bits vector into two 256-bits vector
18740 : : when without TARGET_AVX512BW. */
18741 : 128 : if ((mode == V32HImode || mode == V32HFmode || mode == V32BFmode
18742 : 122 : || mode == V64QImode)
18743 : 10 : && !TARGET_AVX512BW)
18744 : : {
18745 : 3 : gcc_assert (TARGET_AVX512F);
18746 : 3 : rtx vhi, vlo, idx_hi;
18747 : 3 : machine_mode half_mode;
18748 : 3 : rtx (*extract_hi)(rtx, rtx);
18749 : 3 : rtx (*extract_lo)(rtx, rtx);
18750 : :
18751 : 3 : if (mode == V32HImode)
18752 : : {
18753 : : half_mode = V16HImode;
18754 : : extract_hi = gen_vec_extract_hi_v32hi;
18755 : : extract_lo = gen_vec_extract_lo_v32hi;
18756 : : }
18757 : : else if (mode == V32HFmode)
18758 : : {
18759 : : half_mode = V16HFmode;
18760 : : extract_hi = gen_vec_extract_hi_v32hf;
18761 : : extract_lo = gen_vec_extract_lo_v32hf;
18762 : : }
18763 : : else if (mode == V32BFmode)
18764 : : {
18765 : : half_mode = V16BFmode;
18766 : : extract_hi = gen_vec_extract_hi_v32bf;
18767 : : extract_lo = gen_vec_extract_lo_v32bf;
18768 : : }
18769 : : else
18770 : : {
18771 : 3 : half_mode = V32QImode;
18772 : 3 : extract_hi = gen_vec_extract_hi_v64qi;
18773 : 3 : extract_lo = gen_vec_extract_lo_v64qi;
18774 : : }
18775 : :
18776 : 3 : vhi = gen_reg_rtx (half_mode);
18777 : 3 : vlo = gen_reg_rtx (half_mode);
18778 : 3 : idx_hi = gen_reg_rtx (GET_MODE (idx));
18779 : 3 : emit_insn (extract_hi (vhi, target));
18780 : 3 : emit_insn (extract_lo (vlo, target));
18781 : 3 : vec[0] = idx_hi;
18782 : 3 : vec[1] = idx;
18783 : 3 : vec[2] = GEN_INT (n_elts/2);
18784 : 3 : ix86_expand_binary_operator (MINUS, GET_MODE (idx), vec);
18785 : 3 : ix86_expand_vector_set_var (vhi, val, idx_hi);
18786 : 3 : ix86_expand_vector_set_var (vlo, val, idx);
18787 : 3 : emit_insn (gen_rtx_SET (target, gen_rtx_VEC_CONCAT (mode, vlo, vhi)));
18788 : 3 : return;
18789 : : }
18790 : :
18791 : 499 : if (FLOAT_MODE_P (GET_MODE_INNER (mode)))
18792 : : {
18793 : 42 : switch (mode)
18794 : : {
18795 : : case E_V2DFmode:
18796 : : cmp_mode = V2DImode;
18797 : : break;
18798 : 6 : case E_V4DFmode:
18799 : 6 : cmp_mode = V4DImode;
18800 : 6 : break;
18801 : 4 : case E_V8DFmode:
18802 : 4 : cmp_mode = V8DImode;
18803 : 4 : break;
18804 : 2 : case E_V2SFmode:
18805 : 2 : cmp_mode = V2SImode;
18806 : 2 : break;
18807 : 6 : case E_V4SFmode:
18808 : 6 : cmp_mode = V4SImode;
18809 : 6 : break;
18810 : 6 : case E_V8SFmode:
18811 : 6 : cmp_mode = V8SImode;
18812 : 6 : break;
18813 : 5 : case E_V16SFmode:
18814 : 5 : cmp_mode = V16SImode;
18815 : 5 : break;
18816 : 1 : case E_V2HFmode:
18817 : 1 : case E_V2BFmode:
18818 : 1 : cmp_mode = V2HImode;
18819 : 1 : break;
18820 : 1 : case E_V4HFmode:
18821 : 1 : case E_V4BFmode:
18822 : 1 : cmp_mode = V4HImode;
18823 : 1 : break;
18824 : : case E_V8HFmode:
18825 : 2 : cmp_mode = V8HImode;
18826 : : break;
18827 : : case E_V16HFmode:
18828 : 2 : cmp_mode = V16HImode;
18829 : : break;
18830 : : case E_V32HFmode:
18831 : 1 : cmp_mode = V32HImode;
18832 : : break;
18833 : : case E_V8BFmode:
18834 : 2 : cmp_mode = V8HImode;
18835 : : break;
18836 : : case E_V16BFmode:
18837 : 2 : cmp_mode = V16HImode;
18838 : : break;
18839 : : case E_V32BFmode:
18840 : 1 : cmp_mode = V32HImode;
18841 : : break;
18842 : 0 : default:
18843 : 0 : gcc_unreachable ();
18844 : : }
18845 : : }
18846 : :
18847 : 1599 : for (int i = 0; i != n_elts; i++)
18848 : 1474 : vec[i] = GEN_INT (i);
18849 : 125 : constv = gen_rtx_CONST_VECTOR (cmp_mode, gen_rtvec_v (n_elts, vec));
18850 : 125 : valv = gen_reg_rtx (mode);
18851 : 125 : idxv = gen_reg_rtx (cmp_mode);
18852 : 250 : idx_tmp = convert_to_mode (GET_MODE_INNER (cmp_mode), idx, 1);
18853 : :
18854 : 125 : ok = ix86_expand_vector_init_duplicate (TARGET_MMX_WITH_SSE,
18855 : : mode, valv, val);
18856 : 125 : gcc_assert (ok);
18857 : 125 : ok = ix86_expand_vector_init_duplicate (TARGET_MMX_WITH_SSE,
18858 : : cmp_mode, idxv, idx_tmp);
18859 : 125 : gcc_assert (ok);
18860 : 125 : vec[0] = target;
18861 : 125 : vec[1] = valv;
18862 : 125 : vec[2] = target;
18863 : 125 : vec[3] = gen_rtx_EQ (mode, idxv, constv);
18864 : 125 : vec[4] = idxv;
18865 : 125 : vec[5] = constv;
18866 : 125 : ok = ix86_expand_int_vcond (vec);
18867 : 125 : gcc_assert (ok);
18868 : : }
18869 : :
18870 : : void
18871 : 8063 : ix86_expand_vector_set (bool mmx_ok, rtx target, rtx val, int elt)
18872 : : {
18873 : 8063 : machine_mode mode = GET_MODE (target);
18874 : 8063 : machine_mode inner_mode = GET_MODE_INNER (mode);
18875 : 8063 : machine_mode half_mode;
18876 : 8063 : bool use_vec_merge = false;
18877 : 8063 : bool blendm_const = false;
18878 : 8063 : rtx tmp;
18879 : 8063 : static rtx (*gen_extract[8][2]) (rtx, rtx)
18880 : : = {
18881 : : { gen_vec_extract_lo_v32qi, gen_vec_extract_hi_v32qi },
18882 : : { gen_vec_extract_lo_v16hi, gen_vec_extract_hi_v16hi },
18883 : : { gen_vec_extract_lo_v8si, gen_vec_extract_hi_v8si },
18884 : : { gen_vec_extract_lo_v4di, gen_vec_extract_hi_v4di },
18885 : : { gen_vec_extract_lo_v8sf, gen_vec_extract_hi_v8sf },
18886 : : { gen_vec_extract_lo_v4df, gen_vec_extract_hi_v4df },
18887 : : { gen_vec_extract_lo_v16hf, gen_vec_extract_hi_v16hf },
18888 : : { gen_vec_extract_lo_v16bf, gen_vec_extract_hi_v16bf }
18889 : : };
18890 : 8063 : static rtx (*gen_insert[8][2]) (rtx, rtx, rtx)
18891 : : = {
18892 : : { gen_vec_set_lo_v32qi, gen_vec_set_hi_v32qi },
18893 : : { gen_vec_set_lo_v16hi, gen_vec_set_hi_v16hi },
18894 : : { gen_vec_set_lo_v8si, gen_vec_set_hi_v8si },
18895 : : { gen_vec_set_lo_v4di, gen_vec_set_hi_v4di },
18896 : : { gen_vec_set_lo_v8sf, gen_vec_set_hi_v8sf },
18897 : : { gen_vec_set_lo_v4df, gen_vec_set_hi_v4df },
18898 : : { gen_vec_set_lo_v16hf, gen_vec_set_hi_v16hf },
18899 : : { gen_vec_set_lo_v16bf, gen_vec_set_hi_v16bf },
18900 : : };
18901 : 8063 : int i, j, n;
18902 : 8063 : machine_mode mmode = VOIDmode;
18903 : 8063 : rtx (*gen_blendm) (rtx, rtx, rtx, rtx);
18904 : :
18905 : 8063 : switch (mode)
18906 : : {
18907 : 167 : case E_V2SImode:
18908 : 167 : use_vec_merge = TARGET_MMX_WITH_SSE && TARGET_SSE4_1;
18909 : : if (use_vec_merge)
18910 : : break;
18911 : : /* FALLTHRU */
18912 : :
18913 : 148 : case E_V2SFmode:
18914 : 148 : if (mmx_ok)
18915 : : {
18916 : 148 : tmp = gen_reg_rtx (GET_MODE_INNER (mode));
18917 : 148 : ix86_expand_vector_extract (true, tmp, target, 1 - elt);
18918 : 148 : if (elt == 0)
18919 : 1 : tmp = gen_rtx_VEC_CONCAT (mode, val, tmp);
18920 : : else
18921 : 147 : tmp = gen_rtx_VEC_CONCAT (mode, tmp, val);
18922 : 148 : emit_insn (gen_rtx_SET (target, tmp));
18923 : 148 : return;
18924 : : }
18925 : : break;
18926 : :
18927 : 230 : case E_V2DImode:
18928 : 230 : use_vec_merge = TARGET_SSE4_1 && TARGET_64BIT;
18929 : 88 : if (use_vec_merge)
18930 : : break;
18931 : :
18932 : 88 : tmp = gen_reg_rtx (GET_MODE_INNER (mode));
18933 : 88 : ix86_expand_vector_extract (false, tmp, target, 1 - elt);
18934 : 88 : if (elt == 0)
18935 : 72 : tmp = gen_rtx_VEC_CONCAT (mode, val, tmp);
18936 : : else
18937 : 16 : tmp = gen_rtx_VEC_CONCAT (mode, tmp, val);
18938 : 88 : emit_insn (gen_rtx_SET (target, tmp));
18939 : 88 : return;
18940 : :
18941 : 148 : case E_V2DFmode:
18942 : : /* NB: For ELT == 0, use standard scalar operation patterns which
18943 : : preserve the rest of the vector for combiner:
18944 : :
18945 : : (vec_merge:V2DF
18946 : : (vec_duplicate:V2DF (reg:DF))
18947 : : (reg:V2DF)
18948 : : (const_int 1))
18949 : : */
18950 : 148 : if (elt == 0)
18951 : 63 : goto do_vec_merge;
18952 : :
18953 : 85 : {
18954 : 85 : rtx op0, op1;
18955 : :
18956 : : /* For the two element vectors, we implement a VEC_CONCAT with
18957 : : the extraction of the other element. */
18958 : :
18959 : 85 : tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (1, GEN_INT (1 - elt)));
18960 : 85 : tmp = gen_rtx_VEC_SELECT (inner_mode, target, tmp);
18961 : :
18962 : 85 : if (elt == 0)
18963 : : op0 = val, op1 = tmp;
18964 : : else
18965 : 85 : op0 = tmp, op1 = val;
18966 : :
18967 : 85 : tmp = gen_rtx_VEC_CONCAT (mode, op0, op1);
18968 : 85 : emit_insn (gen_rtx_SET (target, tmp));
18969 : : }
18970 : 85 : return;
18971 : :
18972 : 574 : case E_V4SFmode:
18973 : 574 : use_vec_merge = TARGET_SSE4_1;
18974 : 574 : if (use_vec_merge)
18975 : : break;
18976 : :
18977 : 62 : switch (elt)
18978 : : {
18979 : : case 0:
18980 : : use_vec_merge = true;
18981 : : break;
18982 : :
18983 : 1 : case 1:
18984 : : /* tmp = target = A B C D */
18985 : 1 : tmp = copy_to_reg (target);
18986 : : /* target = A A B B */
18987 : 1 : emit_insn (gen_vec_interleave_lowv4sf (target, target, target));
18988 : : /* target = X A B B */
18989 : 1 : ix86_expand_vector_set (false, target, val, 0);
18990 : : /* target = A X C D */
18991 : 1 : emit_insn (gen_sse_shufps_v4sf (target, target, tmp,
18992 : : const1_rtx, const0_rtx,
18993 : : GEN_INT (2+4), GEN_INT (3+4)));
18994 : 1 : return;
18995 : :
18996 : 0 : case 2:
18997 : : /* tmp = target = A B C D */
18998 : 0 : tmp = copy_to_reg (target);
18999 : : /* tmp = X B C D */
19000 : 0 : ix86_expand_vector_set (false, tmp, val, 0);
19001 : : /* target = A B X D */
19002 : 0 : emit_insn (gen_sse_shufps_v4sf (target, target, tmp,
19003 : : const0_rtx, const1_rtx,
19004 : : GEN_INT (0+4), GEN_INT (3+4)));
19005 : 0 : return;
19006 : :
19007 : 4 : case 3:
19008 : : /* tmp = target = A B C D */
19009 : 4 : tmp = copy_to_reg (target);
19010 : : /* tmp = X B C D */
19011 : 4 : ix86_expand_vector_set (false, tmp, val, 0);
19012 : : /* target = A B X D */
19013 : 4 : emit_insn (gen_sse_shufps_v4sf (target, target, tmp,
19014 : : const0_rtx, const1_rtx,
19015 : : GEN_INT (2+4), GEN_INT (0+4)));
19016 : 4 : return;
19017 : :
19018 : 0 : default:
19019 : 0 : gcc_unreachable ();
19020 : : }
19021 : : break;
19022 : :
19023 : 413 : case E_V4SImode:
19024 : 413 : use_vec_merge = TARGET_SSE4_1;
19025 : 413 : if (use_vec_merge)
19026 : : break;
19027 : :
19028 : : /* Element 0 handled by vec_merge below. */
19029 : 263 : if (elt == 0)
19030 : : {
19031 : : use_vec_merge = true;
19032 : : break;
19033 : : }
19034 : :
19035 : 80 : if (TARGET_SSE2)
19036 : : {
19037 : : /* With SSE2, use integer shuffles to swap element 0 and ELT,
19038 : : store into element 0, then shuffle them back. */
19039 : :
19040 : 80 : rtx order[4];
19041 : :
19042 : 80 : order[0] = GEN_INT (elt);
19043 : 80 : order[1] = const1_rtx;
19044 : 80 : order[2] = const2_rtx;
19045 : 80 : order[3] = GEN_INT (3);
19046 : 80 : order[elt] = const0_rtx;
19047 : :
19048 : 80 : emit_insn (gen_sse2_pshufd_1 (target, target, order[0],
19049 : : order[1], order[2], order[3]));
19050 : :
19051 : 80 : ix86_expand_vector_set (false, target, val, 0);
19052 : :
19053 : 80 : emit_insn (gen_sse2_pshufd_1 (target, target, order[0],
19054 : : order[1], order[2], order[3]));
19055 : : }
19056 : : else
19057 : : {
19058 : : /* For SSE1, we have to reuse the V4SF code. */
19059 : 0 : rtx t = gen_reg_rtx (V4SFmode);
19060 : 0 : emit_move_insn (t, gen_lowpart (V4SFmode, target));
19061 : 0 : ix86_expand_vector_set (false, t, gen_lowpart (SFmode, val), elt);
19062 : 0 : emit_move_insn (target, gen_lowpart (mode, t));
19063 : : }
19064 : : return;
19065 : :
19066 : 3286 : case E_V8HImode:
19067 : 3286 : case E_V8HFmode:
19068 : 3286 : case E_V8BFmode:
19069 : 3286 : case E_V2HImode:
19070 : 3286 : case E_V2HFmode:
19071 : 3286 : case E_V2BFmode:
19072 : 3286 : use_vec_merge = TARGET_SSE2;
19073 : 3286 : break;
19074 : 48 : case E_V4HImode:
19075 : 48 : case E_V4HFmode:
19076 : 48 : case E_V4BFmode:
19077 : 48 : use_vec_merge = mmx_ok && (TARGET_SSE || TARGET_3DNOW_A);
19078 : : break;
19079 : :
19080 : 3051 : case E_V16QImode:
19081 : 3051 : case E_V4QImode:
19082 : 3051 : use_vec_merge = TARGET_SSE4_1;
19083 : 3051 : break;
19084 : :
19085 : 5 : case E_V8QImode:
19086 : 5 : use_vec_merge = TARGET_MMX_WITH_SSE && TARGET_SSE4_1;
19087 : : break;
19088 : :
19089 : 3 : case E_V32QImode:
19090 : 3 : half_mode = V16QImode;
19091 : 3 : j = 0;
19092 : 3 : n = 16;
19093 : 3 : goto half;
19094 : :
19095 : 17 : case E_V16HFmode:
19096 : 17 : case E_V16BFmode:
19097 : : /* For ELT == 0, vec_setv8hf_0 can save 1 vpbroadcastw. */
19098 : 17 : if (TARGET_AVX2 && elt != 0)
19099 : : {
19100 : 12 : mmode = SImode;
19101 : 12 : gen_blendm = ((mode == E_V16HFmode) ? gen_avx2_pblendph_1
19102 : : : gen_avx2_pblendbf_1);
19103 : : blendm_const = true;
19104 : : break;
19105 : : }
19106 : : else
19107 : : {
19108 : 5 : half_mode = ((mode == E_V16HFmode) ? V8HFmode : V8BFmode);
19109 : 3 : j = ((mode == E_V16HFmode) ? 6 : 7);
19110 : 5 : n = 8;
19111 : 5 : goto half;
19112 : : }
19113 : :
19114 : 5 : case E_V16HImode:
19115 : 5 : half_mode = V8HImode;
19116 : 5 : j = 1;
19117 : 5 : n = 8;
19118 : 5 : goto half;
19119 : :
19120 : 15 : case E_V8SImode:
19121 : 15 : half_mode = V4SImode;
19122 : 15 : j = 2;
19123 : 15 : n = 4;
19124 : 15 : goto half;
19125 : :
19126 : 15 : case E_V4DImode:
19127 : 15 : half_mode = V2DImode;
19128 : 15 : j = 3;
19129 : 15 : n = 2;
19130 : 15 : goto half;
19131 : :
19132 : 4 : case E_V8SFmode:
19133 : 4 : half_mode = V4SFmode;
19134 : 4 : j = 4;
19135 : 4 : n = 4;
19136 : 4 : goto half;
19137 : :
19138 : 6 : case E_V4DFmode:
19139 : 6 : half_mode = V2DFmode;
19140 : 6 : j = 5;
19141 : 6 : n = 2;
19142 : 6 : goto half;
19143 : :
19144 : 53 : half:
19145 : : /* Compute offset. */
19146 : 53 : i = elt / n;
19147 : 53 : elt %= n;
19148 : :
19149 : 53 : gcc_assert (i <= 1);
19150 : :
19151 : : /* Extract the half. */
19152 : 53 : tmp = gen_reg_rtx (half_mode);
19153 : 53 : emit_insn (gen_extract[j][i] (tmp, target));
19154 : :
19155 : : /* Put val in tmp at elt. */
19156 : 53 : ix86_expand_vector_set (false, tmp, val, elt);
19157 : :
19158 : : /* Put it back. */
19159 : 53 : emit_insn (gen_insert[j][i] (target, target, tmp));
19160 : 53 : return;
19161 : :
19162 : 8 : case E_V8DFmode:
19163 : 8 : if (TARGET_AVX512F)
19164 : : {
19165 : : mmode = QImode;
19166 : : gen_blendm = gen_avx512f_blendmv8df;
19167 : : }
19168 : : break;
19169 : :
19170 : 6 : case E_V8DImode:
19171 : 6 : if (TARGET_AVX512F)
19172 : : {
19173 : : mmode = QImode;
19174 : : gen_blendm = gen_avx512f_blendmv8di;
19175 : : }
19176 : : break;
19177 : :
19178 : 0 : case E_V16SFmode:
19179 : 0 : if (TARGET_AVX512F)
19180 : : {
19181 : : mmode = HImode;
19182 : : gen_blendm = gen_avx512f_blendmv16sf;
19183 : : }
19184 : : break;
19185 : :
19186 : 0 : case E_V16SImode:
19187 : 0 : if (TARGET_AVX512F)
19188 : : {
19189 : : mmode = HImode;
19190 : : gen_blendm = gen_avx512f_blendmv16si;
19191 : : }
19192 : : break;
19193 : :
19194 : 12 : case E_V32HFmode:
19195 : 12 : if (TARGET_AVX512BW)
19196 : : {
19197 : : mmode = SImode;
19198 : : gen_blendm = gen_avx512bw_blendmv32hf;
19199 : : }
19200 : : break;
19201 : 12 : case E_V32BFmode:
19202 : 12 : if (TARGET_AVX512BW)
19203 : : {
19204 : : mmode = SImode;
19205 : : gen_blendm = gen_avx512bw_blendmv32bf;
19206 : : }
19207 : : break;
19208 : 11 : case E_V32HImode:
19209 : 11 : if (TARGET_AVX512BW)
19210 : : {
19211 : : mmode = SImode;
19212 : : gen_blendm = gen_avx512bw_blendmv32hi;
19213 : : }
19214 : 7 : else if (TARGET_AVX512F)
19215 : : {
19216 : 7 : half_mode = E_V8HImode;
19217 : 7 : n = 8;
19218 : 7 : goto quarter;
19219 : : }
19220 : : break;
19221 : :
19222 : 12 : case E_V64QImode:
19223 : 12 : if (TARGET_AVX512BW)
19224 : : {
19225 : : mmode = DImode;
19226 : : gen_blendm = gen_avx512bw_blendmv64qi;
19227 : : }
19228 : 6 : else if (TARGET_AVX512F)
19229 : : {
19230 : 6 : half_mode = E_V16QImode;
19231 : 6 : n = 16;
19232 : 6 : goto quarter;
19233 : : }
19234 : : break;
19235 : :
19236 : 13 : quarter:
19237 : : /* Compute offset. */
19238 : 13 : i = elt / n;
19239 : 13 : elt %= n;
19240 : :
19241 : 13 : gcc_assert (i <= 3);
19242 : :
19243 : 13 : {
19244 : : /* Extract the quarter. */
19245 : 13 : tmp = gen_reg_rtx (V4SImode);
19246 : 13 : rtx tmp2 = gen_lowpart (V16SImode, target);
19247 : 13 : rtx mask = gen_reg_rtx (QImode);
19248 : :
19249 : 13 : emit_move_insn (mask, constm1_rtx);
19250 : 13 : emit_insn (gen_avx512f_vextracti32x4_mask (tmp, tmp2, GEN_INT (i),
19251 : : tmp, mask));
19252 : :
19253 : 13 : tmp2 = gen_reg_rtx (half_mode);
19254 : 13 : emit_move_insn (tmp2, gen_lowpart (half_mode, tmp));
19255 : 13 : tmp = tmp2;
19256 : :
19257 : : /* Put val in tmp at elt. */
19258 : 13 : ix86_expand_vector_set (false, tmp, val, elt);
19259 : :
19260 : : /* Put it back. */
19261 : 13 : tmp2 = gen_reg_rtx (V16SImode);
19262 : 13 : rtx tmp3 = gen_lowpart (V16SImode, target);
19263 : 13 : mask = gen_reg_rtx (HImode);
19264 : 13 : emit_move_insn (mask, constm1_rtx);
19265 : 13 : tmp = gen_lowpart (V4SImode, tmp);
19266 : 13 : emit_insn (gen_avx512f_vinserti32x4_mask (tmp2, tmp3, tmp, GEN_INT (i),
19267 : : tmp3, mask));
19268 : 13 : emit_move_insn (target, gen_lowpart (mode, tmp2));
19269 : : }
19270 : 13 : return;
19271 : :
19272 : : default:
19273 : : break;
19274 : : }
19275 : :
19276 : 6337 : if (mmode != VOIDmode)
19277 : : {
19278 : 54 : tmp = gen_reg_rtx (mode);
19279 : 54 : emit_insn (gen_rtx_SET (tmp, gen_rtx_VEC_DUPLICATE (mode, val)));
19280 : 54 : rtx merge_mask = gen_int_mode (HOST_WIDE_INT_1U << elt, mmode);
19281 : : /* The avx512*_blendm<mode> expanders have different operand order
19282 : : from VEC_MERGE. In VEC_MERGE, the first input operand is used for
19283 : : elements where the mask is set and second input operand otherwise,
19284 : : in {sse,avx}*_*blend* the first input operand is used for elements
19285 : : where the mask is clear and second input operand otherwise. */
19286 : 54 : if (!blendm_const)
19287 : 42 : merge_mask = force_reg (mmode, merge_mask);
19288 : 54 : emit_insn (gen_blendm (target, target, tmp, merge_mask));
19289 : : }
19290 : 7474 : else if (use_vec_merge)
19291 : : {
19292 : 7464 : do_vec_merge:
19293 : 7527 : if (!nonimmediate_operand (val, inner_mode))
19294 : 1 : val = force_reg (inner_mode, val);
19295 : 7527 : tmp = gen_rtx_VEC_DUPLICATE (mode, val);
19296 : 7527 : tmp = gen_rtx_VEC_MERGE (mode, tmp, target,
19297 : : GEN_INT (HOST_WIDE_INT_1U << elt));
19298 : 7527 : emit_insn (gen_rtx_SET (target, tmp));
19299 : : }
19300 : : else
19301 : : {
19302 : 20 : rtx mem = assign_stack_temp (mode, GET_MODE_SIZE (mode));
19303 : :
19304 : 10 : emit_move_insn (mem, target);
19305 : :
19306 : 20 : tmp = adjust_address (mem, inner_mode, elt * GET_MODE_SIZE (inner_mode));
19307 : 10 : emit_move_insn (tmp, val);
19308 : :
19309 : 10 : emit_move_insn (target, mem);
19310 : : }
19311 : : }
19312 : :
19313 : : void
19314 : 101899 : ix86_expand_vector_extract (bool mmx_ok, rtx target, rtx vec, int elt)
19315 : : {
19316 : 101899 : machine_mode mode = GET_MODE (vec);
19317 : 101899 : machine_mode inner_mode = GET_MODE_INNER (mode);
19318 : 101899 : bool use_vec_extr = false;
19319 : 101899 : rtx tmp;
19320 : :
19321 : 101899 : switch (mode)
19322 : : {
19323 : 8078 : case E_V2SImode:
19324 : 8078 : use_vec_extr = TARGET_MMX_WITH_SSE && TARGET_SSE4_1;
19325 : : if (use_vec_extr)
19326 : : break;
19327 : : /* FALLTHRU */
19328 : :
19329 : 8907 : case E_V2SFmode:
19330 : 8907 : if (!mmx_ok)
19331 : : break;
19332 : : /* FALLTHRU */
19333 : :
19334 : : case E_V2DFmode:
19335 : : case E_V2DImode:
19336 : : case E_V2TImode:
19337 : : case E_V4TImode:
19338 : : use_vec_extr = true;
19339 : : break;
19340 : :
19341 : 7479 : case E_V4SFmode:
19342 : 7479 : use_vec_extr = TARGET_SSE4_1;
19343 : 7479 : if (use_vec_extr)
19344 : : break;
19345 : :
19346 : 4023 : switch (elt)
19347 : : {
19348 : : case 0:
19349 : : tmp = vec;
19350 : : break;
19351 : :
19352 : 1668 : case 1:
19353 : 1668 : case 3:
19354 : 1668 : tmp = gen_reg_rtx (mode);
19355 : 1668 : emit_insn (gen_sse_shufps_v4sf (tmp, vec, vec,
19356 : : GEN_INT (elt), GEN_INT (elt),
19357 : 1668 : GEN_INT (elt+4), GEN_INT (elt+4)));
19358 : 1668 : break;
19359 : :
19360 : 927 : case 2:
19361 : 927 : tmp = gen_reg_rtx (mode);
19362 : 927 : emit_insn (gen_vec_interleave_highv4sf (tmp, vec, vec));
19363 : 927 : break;
19364 : :
19365 : 0 : default:
19366 : 0 : gcc_unreachable ();
19367 : : }
19368 : : vec = tmp;
19369 : : use_vec_extr = true;
19370 : : elt = 0;
19371 : : break;
19372 : :
19373 : 22426 : case E_V4SImode:
19374 : 22426 : use_vec_extr = TARGET_SSE4_1;
19375 : 22426 : if (use_vec_extr)
19376 : : break;
19377 : :
19378 : 16685 : if (TARGET_SSE2)
19379 : : {
19380 : 16681 : switch (elt)
19381 : : {
19382 : : case 0:
19383 : : tmp = vec;
19384 : : break;
19385 : :
19386 : 5321 : case 1:
19387 : 5321 : case 3:
19388 : 5321 : tmp = gen_reg_rtx (mode);
19389 : 5321 : emit_insn (gen_sse2_pshufd_1 (tmp, vec,
19390 : : GEN_INT (elt), GEN_INT (elt),
19391 : : GEN_INT (elt), GEN_INT (elt)));
19392 : 5321 : break;
19393 : :
19394 : 2652 : case 2:
19395 : 2652 : tmp = gen_reg_rtx (mode);
19396 : 2652 : emit_insn (gen_vec_interleave_highv4si (tmp, vec, vec));
19397 : 2652 : break;
19398 : :
19399 : 0 : default:
19400 : 0 : gcc_unreachable ();
19401 : : }
19402 : : vec = tmp;
19403 : : use_vec_extr = true;
19404 : : elt = 0;
19405 : : }
19406 : : else
19407 : : {
19408 : : /* For SSE1, we have to reuse the V4SF code. */
19409 : 4 : ix86_expand_vector_extract (false, gen_lowpart (SFmode, target),
19410 : 4 : gen_lowpart (V4SFmode, vec), elt);
19411 : 4 : return;
19412 : : }
19413 : : break;
19414 : :
19415 : 6160 : case E_V8HImode:
19416 : 6160 : case E_V8HFmode:
19417 : 6160 : case E_V8BFmode:
19418 : 6160 : case E_V2HImode:
19419 : 6160 : case E_V2HFmode:
19420 : 6160 : case E_V2BFmode:
19421 : 6160 : use_vec_extr = TARGET_SSE2;
19422 : 6160 : break;
19423 : 789 : case E_V4HImode:
19424 : 789 : case E_V4HFmode:
19425 : 789 : case E_V4BFmode:
19426 : 789 : use_vec_extr = mmx_ok && (TARGET_SSE || TARGET_3DNOW_A);
19427 : : break;
19428 : :
19429 : 7396 : case E_V16QImode:
19430 : 7396 : use_vec_extr = TARGET_SSE4_1;
19431 : 7396 : if (!use_vec_extr
19432 : 5590 : && TARGET_SSE2
19433 : 5590 : && elt == 0
19434 : 11209 : && (optimize_insn_for_size_p () || TARGET_INTER_UNIT_MOVES_FROM_VEC))
19435 : : {
19436 : 3812 : tmp = gen_reg_rtx (SImode);
19437 : 3812 : ix86_expand_vector_extract (false, tmp, gen_lowpart (V4SImode, vec),
19438 : : 0);
19439 : 3812 : emit_insn (gen_rtx_SET (target, gen_lowpart (QImode, tmp)));
19440 : 3812 : return;
19441 : : }
19442 : : break;
19443 : 54 : case E_V4QImode:
19444 : 54 : use_vec_extr = TARGET_SSE4_1;
19445 : 54 : break;
19446 : :
19447 : 220 : case E_V8SFmode:
19448 : 220 : if (TARGET_AVX)
19449 : : {
19450 : 220 : tmp = gen_reg_rtx (V4SFmode);
19451 : 220 : if (elt < 4)
19452 : 106 : emit_insn (gen_vec_extract_lo_v8sf (tmp, vec));
19453 : : else
19454 : 114 : emit_insn (gen_vec_extract_hi_v8sf (tmp, vec));
19455 : 220 : ix86_expand_vector_extract (false, target, tmp, elt & 3);
19456 : 220 : return;
19457 : : }
19458 : : break;
19459 : :
19460 : 565 : case E_V4DFmode:
19461 : 565 : if (TARGET_AVX)
19462 : : {
19463 : 565 : tmp = gen_reg_rtx (V2DFmode);
19464 : 565 : if (elt < 2)
19465 : 297 : emit_insn (gen_vec_extract_lo_v4df (tmp, vec));
19466 : : else
19467 : 268 : emit_insn (gen_vec_extract_hi_v4df (tmp, vec));
19468 : 565 : ix86_expand_vector_extract (false, target, tmp, elt & 1);
19469 : 565 : return;
19470 : : }
19471 : : break;
19472 : :
19473 : 253 : case E_V32QImode:
19474 : 253 : if (TARGET_AVX)
19475 : : {
19476 : 253 : tmp = gen_reg_rtx (V16QImode);
19477 : 253 : if (elt < 16)
19478 : 130 : emit_insn (gen_vec_extract_lo_v32qi (tmp, vec));
19479 : : else
19480 : 123 : emit_insn (gen_vec_extract_hi_v32qi (tmp, vec));
19481 : 253 : ix86_expand_vector_extract (false, target, tmp, elt & 15);
19482 : 253 : return;
19483 : : }
19484 : : break;
19485 : :
19486 : 584 : case E_V16HImode:
19487 : 584 : if (TARGET_AVX)
19488 : : {
19489 : 584 : tmp = gen_reg_rtx (V8HImode);
19490 : 584 : if (elt < 8)
19491 : 288 : emit_insn (gen_vec_extract_lo_v16hi (tmp, vec));
19492 : : else
19493 : 296 : emit_insn (gen_vec_extract_hi_v16hi (tmp, vec));
19494 : 584 : ix86_expand_vector_extract (false, target, tmp, elt & 7);
19495 : 584 : return;
19496 : : }
19497 : : break;
19498 : :
19499 : 1095 : case E_V8SImode:
19500 : 1095 : if (TARGET_AVX)
19501 : : {
19502 : 1095 : tmp = gen_reg_rtx (V4SImode);
19503 : 1095 : if (elt < 4)
19504 : 531 : emit_insn (gen_vec_extract_lo_v8si (tmp, vec));
19505 : : else
19506 : 564 : emit_insn (gen_vec_extract_hi_v8si (tmp, vec));
19507 : 1095 : ix86_expand_vector_extract (false, target, tmp, elt & 3);
19508 : 1095 : return;
19509 : : }
19510 : : break;
19511 : :
19512 : 1552 : case E_V4DImode:
19513 : 1552 : if (TARGET_AVX)
19514 : : {
19515 : 1552 : tmp = gen_reg_rtx (V2DImode);
19516 : 1552 : if (elt < 2)
19517 : 829 : emit_insn (gen_vec_extract_lo_v4di (tmp, vec));
19518 : : else
19519 : 723 : emit_insn (gen_vec_extract_hi_v4di (tmp, vec));
19520 : 1552 : ix86_expand_vector_extract (false, target, tmp, elt & 1);
19521 : 1552 : return;
19522 : : }
19523 : : break;
19524 : :
19525 : 8 : case E_V32HImode:
19526 : 8 : if (TARGET_AVX512BW)
19527 : : {
19528 : 8 : tmp = gen_reg_rtx (V16HImode);
19529 : 8 : if (elt < 16)
19530 : 3 : emit_insn (gen_vec_extract_lo_v32hi (tmp, vec));
19531 : : else
19532 : 5 : emit_insn (gen_vec_extract_hi_v32hi (tmp, vec));
19533 : 8 : ix86_expand_vector_extract (false, target, tmp, elt & 15);
19534 : 8 : return;
19535 : : }
19536 : : break;
19537 : :
19538 : 11 : case E_V64QImode:
19539 : 11 : if (TARGET_AVX512BW)
19540 : : {
19541 : 11 : tmp = gen_reg_rtx (V32QImode);
19542 : 11 : if (elt < 32)
19543 : 5 : emit_insn (gen_vec_extract_lo_v64qi (tmp, vec));
19544 : : else
19545 : 6 : emit_insn (gen_vec_extract_hi_v64qi (tmp, vec));
19546 : 11 : ix86_expand_vector_extract (false, target, tmp, elt & 31);
19547 : 11 : return;
19548 : : }
19549 : : break;
19550 : :
19551 : 55 : case E_V16SFmode:
19552 : 55 : tmp = gen_reg_rtx (V8SFmode);
19553 : 55 : if (elt < 8)
19554 : 29 : emit_insn (gen_vec_extract_lo_v16sf (tmp, vec));
19555 : : else
19556 : 26 : emit_insn (gen_vec_extract_hi_v16sf (tmp, vec));
19557 : 55 : ix86_expand_vector_extract (false, target, tmp, elt & 7);
19558 : 55 : return;
19559 : :
19560 : 296 : case E_V8DFmode:
19561 : 296 : tmp = gen_reg_rtx (V4DFmode);
19562 : 296 : if (elt < 4)
19563 : 160 : emit_insn (gen_vec_extract_lo_v8df (tmp, vec));
19564 : : else
19565 : 136 : emit_insn (gen_vec_extract_hi_v8df (tmp, vec));
19566 : 296 : ix86_expand_vector_extract (false, target, tmp, elt & 3);
19567 : 296 : return;
19568 : :
19569 : 334 : case E_V16SImode:
19570 : 334 : tmp = gen_reg_rtx (V8SImode);
19571 : 334 : if (elt < 8)
19572 : 165 : emit_insn (gen_vec_extract_lo_v16si (tmp, vec));
19573 : : else
19574 : 169 : emit_insn (gen_vec_extract_hi_v16si (tmp, vec));
19575 : 334 : ix86_expand_vector_extract (false, target, tmp, elt & 7);
19576 : 334 : return;
19577 : :
19578 : 734 : case E_V8DImode:
19579 : 734 : tmp = gen_reg_rtx (V4DImode);
19580 : 734 : if (elt < 4)
19581 : 415 : emit_insn (gen_vec_extract_lo_v8di (tmp, vec));
19582 : : else
19583 : 319 : emit_insn (gen_vec_extract_hi_v8di (tmp, vec));
19584 : 734 : ix86_expand_vector_extract (false, target, tmp, elt & 3);
19585 : 734 : return;
19586 : :
19587 : 45 : case E_V32HFmode:
19588 : 45 : case E_V32BFmode:
19589 : 45 : if (TARGET_AVX512BW)
19590 : : {
19591 : 45 : tmp = (mode == E_V32HFmode
19592 : 45 : ? gen_reg_rtx (V16HFmode)
19593 : 7 : : gen_reg_rtx (V16BFmode));
19594 : 45 : if (elt < 16)
19595 : 31 : emit_insn (gen_vec_extract_lo (mode, tmp, vec));
19596 : : else
19597 : 14 : emit_insn (gen_vec_extract_hi (mode, tmp, vec));
19598 : 45 : ix86_expand_vector_extract (false, target, tmp, elt & 15);
19599 : 45 : return;
19600 : : }
19601 : : break;
19602 : :
19603 : 474 : case E_V16HFmode:
19604 : 474 : case E_V16BFmode:
19605 : 474 : if (TARGET_AVX)
19606 : : {
19607 : 474 : tmp = (mode == E_V16HFmode
19608 : 474 : ? gen_reg_rtx (V8HFmode)
19609 : 339 : : gen_reg_rtx (V8BFmode));
19610 : 474 : if (elt < 8)
19611 : 249 : emit_insn (gen_vec_extract_lo (mode, tmp, vec));
19612 : : else
19613 : 225 : emit_insn (gen_vec_extract_hi (mode, tmp, vec));
19614 : 474 : ix86_expand_vector_extract (false, target, tmp, elt & 7);
19615 : 474 : return;
19616 : : }
19617 : : break;
19618 : :
19619 : 627 : case E_V8QImode:
19620 : 627 : use_vec_extr = TARGET_MMX_WITH_SSE && TARGET_SSE4_1;
19621 : : /* ??? Could extract the appropriate HImode element and shift. */
19622 : : break;
19623 : :
19624 : : default:
19625 : : break;
19626 : : }
19627 : :
19628 : 25210 : if (use_vec_extr)
19629 : : {
19630 : 84927 : tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (1, GEN_INT (elt)));
19631 : 84927 : tmp = gen_rtx_VEC_SELECT (inner_mode, vec, tmp);
19632 : :
19633 : : /* Let the rtl optimizers know about the zero extension performed. */
19634 : 84927 : if (inner_mode == QImode || inner_mode == HImode)
19635 : : {
19636 : 8260 : rtx reg = gen_reg_rtx (SImode);
19637 : 8260 : tmp = gen_rtx_ZERO_EXTEND (SImode, tmp);
19638 : 8260 : emit_move_insn (reg, tmp);
19639 : 8260 : tmp = gen_lowpart (inner_mode, reg);
19640 : 8260 : SUBREG_PROMOTED_VAR_P (tmp) = 1;
19641 : 8260 : SUBREG_PROMOTED_SET (tmp, 1);
19642 : : }
19643 : :
19644 : 84927 : emit_move_insn (target, tmp);
19645 : : }
19646 : : else
19647 : : {
19648 : 13860 : rtx mem = assign_stack_temp (mode, GET_MODE_SIZE (mode));
19649 : :
19650 : 6930 : emit_move_insn (mem, vec);
19651 : :
19652 : 13860 : tmp = adjust_address (mem, inner_mode, elt*GET_MODE_SIZE (inner_mode));
19653 : 6930 : emit_move_insn (target, tmp);
19654 : : }
19655 : : }
19656 : :
19657 : : /* Generate code to copy vector bits i / 2 ... i - 1 from vector SRC
19658 : : to bits 0 ... i / 2 - 1 of vector DEST, which has the same mode.
19659 : : The upper bits of DEST are undefined, though they shouldn't cause
19660 : : exceptions (some bits from src or all zeros are ok). */
19661 : :
19662 : : static void
19663 : 41623 : emit_reduc_half (rtx dest, rtx src, int i)
19664 : : {
19665 : 41623 : rtx tem, d = dest;
19666 : 41623 : switch (GET_MODE (src))
19667 : : {
19668 : 6042 : case E_V4SFmode:
19669 : 6042 : if (i == 128)
19670 : 3021 : tem = gen_sse_movhlps (dest, src, src);
19671 : : else
19672 : 3021 : tem = gen_sse_shufps_v4sf (dest, src, src, const1_rtx, const1_rtx,
19673 : : GEN_INT (1 + 4), GEN_INT (1 + 4));
19674 : : break;
19675 : 3360 : case E_V2DFmode:
19676 : 3360 : tem = gen_vec_interleave_highv2df (dest, src, src);
19677 : 3360 : break;
19678 : 76 : case E_V4QImode:
19679 : 76 : d = gen_reg_rtx (V1SImode);
19680 : 76 : tem = gen_mmx_lshrv1si3 (d, gen_lowpart (V1SImode, src),
19681 : 76 : GEN_INT (i / 2));
19682 : 76 : break;
19683 : 615 : case E_V8QImode:
19684 : 615 : case E_V4HImode:
19685 : 615 : d = gen_reg_rtx (V1DImode);
19686 : 615 : tem = gen_mmx_lshrv1di3 (d, gen_lowpart (V1DImode, src),
19687 : 615 : GEN_INT (i / 2));
19688 : 615 : break;
19689 : 31530 : case E_V16QImode:
19690 : 31530 : case E_V8HImode:
19691 : 31530 : case E_V8HFmode:
19692 : 31530 : case E_V4SImode:
19693 : 31530 : case E_V2DImode:
19694 : 31530 : if (TARGET_SSE_REDUCTION_PREFER_PSHUF)
19695 : : {
19696 : 19 : if (i == 128)
19697 : : {
19698 : 13 : d = gen_reg_rtx (V4SImode);
19699 : 26 : tem = gen_sse2_pshufd_1 (
19700 : 13 : d, force_reg (V4SImode, gen_lowpart (V4SImode, src)),
19701 : : GEN_INT (2), GEN_INT (3), GEN_INT (2), GEN_INT (3));
19702 : 13 : break;
19703 : : }
19704 : 6 : else if (i == 64)
19705 : : {
19706 : 5 : d = gen_reg_rtx (V4SImode);
19707 : 10 : tem = gen_sse2_pshufd_1 (
19708 : 5 : d, force_reg (V4SImode, gen_lowpart (V4SImode, src)),
19709 : : GEN_INT (1), GEN_INT (1), GEN_INT (1), GEN_INT (1));
19710 : 5 : break;
19711 : : }
19712 : 1 : else if (i == 32)
19713 : : {
19714 : 1 : d = gen_reg_rtx (V8HImode);
19715 : 2 : tem = gen_sse2_pshuflw_1 (
19716 : 1 : d, force_reg (V8HImode, gen_lowpart (V8HImode, src)),
19717 : : GEN_INT (1), GEN_INT (1), GEN_INT (1), GEN_INT (1));
19718 : 1 : break;
19719 : : }
19720 : : }
19721 : 31511 : d = gen_reg_rtx (V1TImode);
19722 : 31511 : tem = gen_sse2_lshrv1ti3 (d, gen_lowpart (V1TImode, src),
19723 : 31511 : GEN_INT (i / 2));
19724 : 31511 : break;
19725 : 0 : case E_V8SFmode:
19726 : 0 : if (i == 256)
19727 : 0 : tem = gen_avx_vperm2f128v8sf3 (dest, src, src, const1_rtx);
19728 : : else
19729 : 0 : tem = gen_avx_shufps256 (dest, src, src,
19730 : : GEN_INT (i == 128 ? 2 + (3 << 2) : 1));
19731 : : break;
19732 : 0 : case E_V4DFmode:
19733 : 0 : if (i == 256)
19734 : 0 : tem = gen_avx_vperm2f128v4df3 (dest, src, src, const1_rtx);
19735 : : else
19736 : 0 : tem = gen_avx_shufpd256 (dest, src, src, const1_rtx);
19737 : : break;
19738 : 0 : case E_V32QImode:
19739 : 0 : case E_V16HImode:
19740 : 0 : case E_V16HFmode:
19741 : 0 : case E_V8SImode:
19742 : 0 : case E_V4DImode:
19743 : 0 : if (i == 256)
19744 : : {
19745 : 0 : if (GET_MODE (dest) != V4DImode)
19746 : 0 : d = gen_reg_rtx (V4DImode);
19747 : 0 : tem = gen_avx2_permv2ti (d, gen_lowpart (V4DImode, src),
19748 : 0 : gen_lowpart (V4DImode, src),
19749 : : const1_rtx);
19750 : : }
19751 : : else
19752 : : {
19753 : 0 : d = gen_reg_rtx (V2TImode);
19754 : 0 : tem = gen_avx2_lshrv2ti3 (d, gen_lowpart (V2TImode, src),
19755 : 0 : GEN_INT (i / 2));
19756 : : }
19757 : : break;
19758 : 0 : case E_V64QImode:
19759 : 0 : case E_V32HImode:
19760 : 0 : case E_V32HFmode:
19761 : 0 : if (i < 64)
19762 : : {
19763 : 0 : d = gen_reg_rtx (V4TImode);
19764 : 0 : tem = gen_avx512bw_lshrv4ti3 (d, gen_lowpart (V4TImode, src),
19765 : 0 : GEN_INT (i / 2));
19766 : 0 : break;
19767 : : }
19768 : : /* FALLTHRU */
19769 : 0 : case E_V16SImode:
19770 : 0 : case E_V16SFmode:
19771 : 0 : case E_V8DImode:
19772 : 0 : case E_V8DFmode:
19773 : 0 : if (i > 128)
19774 : 0 : tem = gen_avx512f_shuf_i32x4_1 (gen_lowpart (V16SImode, dest),
19775 : 0 : gen_lowpart (V16SImode, src),
19776 : 0 : gen_lowpart (V16SImode, src),
19777 : : GEN_INT (0x4 + (i == 512 ? 4 : 0)),
19778 : : GEN_INT (0x5 + (i == 512 ? 4 : 0)),
19779 : : GEN_INT (0x6 + (i == 512 ? 4 : 0)),
19780 : : GEN_INT (0x7 + (i == 512 ? 4 : 0)),
19781 : : GEN_INT (0xC), GEN_INT (0xD),
19782 : : GEN_INT (0xE), GEN_INT (0xF),
19783 : : GEN_INT (0x10), GEN_INT (0x11),
19784 : : GEN_INT (0x12), GEN_INT (0x13),
19785 : : GEN_INT (0x14), GEN_INT (0x15),
19786 : : GEN_INT (0x16), GEN_INT (0x17));
19787 : : else
19788 : 0 : tem = gen_avx512f_pshufd_1 (gen_lowpart (V16SImode, dest),
19789 : 0 : gen_lowpart (V16SImode, src),
19790 : : GEN_INT (i == 128 ? 0x2 : 0x1),
19791 : : GEN_INT (0x3),
19792 : : GEN_INT (0x3),
19793 : : GEN_INT (0x3),
19794 : : GEN_INT (i == 128 ? 0x6 : 0x5),
19795 : : GEN_INT (0x7),
19796 : : GEN_INT (0x7),
19797 : : GEN_INT (0x7),
19798 : : GEN_INT (i == 128 ? 0xA : 0x9),
19799 : : GEN_INT (0xB),
19800 : : GEN_INT (0xB),
19801 : : GEN_INT (0xB),
19802 : : GEN_INT (i == 128 ? 0xE : 0xD),
19803 : : GEN_INT (0xF),
19804 : : GEN_INT (0xF),
19805 : : GEN_INT (0xF));
19806 : : break;
19807 : 0 : default:
19808 : 0 : gcc_unreachable ();
19809 : : }
19810 : 41623 : emit_insn (tem);
19811 : 41623 : if (d != dest)
19812 : 32221 : emit_move_insn (dest, gen_lowpart (GET_MODE (dest), d));
19813 : 41623 : }
19814 : :
19815 : : /* Expand a vector reduction. FN is the binary pattern to reduce;
19816 : : DEST is the destination; IN is the input vector. */
19817 : :
19818 : : void
19819 : 20769 : ix86_expand_reduc (rtx (*fn) (rtx, rtx, rtx), rtx dest, rtx in)
19820 : : {
19821 : 20769 : rtx half, dst, vec = in;
19822 : 20769 : machine_mode mode = GET_MODE (in);
19823 : 20769 : int i;
19824 : :
19825 : : /* SSE4 has a special instruction for V8HImode UMIN reduction. */
19826 : 20769 : if (TARGET_SSE4_1
19827 : 9927 : && mode == V8HImode
19828 : 777 : && fn == gen_uminv8hi3)
19829 : : {
19830 : 4 : emit_insn (gen_sse4_1_phminposuw (dest, in));
19831 : 4 : return;
19832 : : }
19833 : :
19834 : 41530 : for (i = GET_MODE_BITSIZE (mode);
19835 : 124776 : i > GET_MODE_UNIT_BITSIZE (mode);
19836 : 41623 : i >>= 1)
19837 : : {
19838 : 41623 : half = gen_reg_rtx (mode);
19839 : 41623 : emit_reduc_half (half, vec, i);
19840 : 83246 : if (i == GET_MODE_UNIT_BITSIZE (mode) * 2)
19841 : : dst = dest;
19842 : : else
19843 : 20858 : dst = gen_reg_rtx (mode);
19844 : 41623 : emit_insn (fn (dst, half, vec));
19845 : 41623 : vec = dst;
19846 : : }
19847 : : }
19848 : :
19849 : : /* Output code to perform a conditional jump to LABEL, if C2 flag in
19850 : : FP status register is set. */
19851 : :
19852 : : void
19853 : 284 : ix86_emit_fp_unordered_jump (rtx label)
19854 : : {
19855 : 284 : rtx reg = gen_reg_rtx (HImode);
19856 : 284 : rtx_insn *insn;
19857 : 284 : rtx temp;
19858 : :
19859 : 284 : emit_insn (gen_x86_fnstsw_1 (reg));
19860 : :
19861 : 284 : if (TARGET_SAHF && (TARGET_USE_SAHF || optimize_insn_for_size_p ()))
19862 : : {
19863 : 37 : emit_insn (gen_x86_sahf_1 (reg));
19864 : :
19865 : 37 : temp = gen_rtx_REG (CCmode, FLAGS_REG);
19866 : 37 : temp = gen_rtx_UNORDERED (VOIDmode, temp, const0_rtx);
19867 : : }
19868 : : else
19869 : : {
19870 : 247 : emit_insn (gen_testqi_ext_1_ccno (reg, GEN_INT (0x04)));
19871 : :
19872 : 247 : temp = gen_rtx_REG (CCNOmode, FLAGS_REG);
19873 : 247 : temp = gen_rtx_NE (VOIDmode, temp, const0_rtx);
19874 : : }
19875 : :
19876 : 284 : temp = gen_rtx_IF_THEN_ELSE (VOIDmode, temp,
19877 : : gen_rtx_LABEL_REF (VOIDmode, label),
19878 : : pc_rtx);
19879 : 284 : insn = emit_jump_insn (gen_rtx_SET (pc_rtx, temp));
19880 : 284 : predict_jump (REG_BR_PROB_BASE * 10 / 100);
19881 : 284 : JUMP_LABEL (insn) = label;
19882 : 284 : }
19883 : :
19884 : : /* Output code to perform an sinh XFmode calculation. */
19885 : :
19886 : : void
19887 : 2 : ix86_emit_i387_sinh (rtx op0, rtx op1)
19888 : : {
19889 : 2 : rtx e1 = gen_reg_rtx (XFmode);
19890 : 2 : rtx e2 = gen_reg_rtx (XFmode);
19891 : 2 : rtx scratch = gen_reg_rtx (HImode);
19892 : 2 : rtx flags = gen_rtx_REG (CCNOmode, FLAGS_REG);
19893 : 2 : rtx half = const_double_from_real_value (dconsthalf, XFmode);
19894 : 2 : rtx cst1, tmp;
19895 : 2 : rtx_code_label *jump_label = gen_label_rtx ();
19896 : 2 : rtx_insn *insn;
19897 : :
19898 : : /* scratch = fxam (op1) */
19899 : 2 : emit_insn (gen_fxamxf2_i387 (scratch, op1));
19900 : :
19901 : : /* e1 = expm1 (|op1|) */
19902 : 2 : emit_insn (gen_absxf2 (e2, op1));
19903 : 2 : emit_insn (gen_expm1xf2 (e1, e2));
19904 : :
19905 : : /* e2 = e1 / (e1 + 1.0) + e1 */
19906 : 2 : cst1 = force_reg (XFmode, CONST1_RTX (XFmode));
19907 : 2 : emit_insn (gen_addxf3 (e2, e1, cst1));
19908 : 2 : emit_insn (gen_divxf3 (e2, e1, e2));
19909 : 2 : emit_insn (gen_addxf3 (e2, e2, e1));
19910 : :
19911 : : /* flags = signbit (op1) */
19912 : 2 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x02)));
19913 : :
19914 : : /* if (flags) then e2 = -e2 */
19915 : 2 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode,
19916 : : gen_rtx_EQ (VOIDmode, flags, const0_rtx),
19917 : : gen_rtx_LABEL_REF (VOIDmode, jump_label),
19918 : : pc_rtx);
19919 : 2 : insn = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
19920 : 2 : predict_jump (REG_BR_PROB_BASE * 50 / 100);
19921 : 2 : JUMP_LABEL (insn) = jump_label;
19922 : :
19923 : 2 : emit_insn (gen_negxf2 (e2, e2));
19924 : :
19925 : 2 : emit_label (jump_label);
19926 : 2 : LABEL_NUSES (jump_label) = 1;
19927 : :
19928 : : /* op0 = 0.5 * e2 */
19929 : 2 : half = force_reg (XFmode, half);
19930 : 2 : emit_insn (gen_mulxf3 (op0, e2, half));
19931 : 2 : }
19932 : :
19933 : : /* Output code to perform an cosh XFmode calculation. */
19934 : :
19935 : : void
19936 : 3 : ix86_emit_i387_cosh (rtx op0, rtx op1)
19937 : : {
19938 : 3 : rtx e1 = gen_reg_rtx (XFmode);
19939 : 3 : rtx e2 = gen_reg_rtx (XFmode);
19940 : 3 : rtx half = const_double_from_real_value (dconsthalf, XFmode);
19941 : 3 : rtx cst1;
19942 : :
19943 : : /* e1 = exp (op1) */
19944 : 3 : emit_insn (gen_expxf2 (e1, op1));
19945 : :
19946 : : /* e2 = e1 + 1.0 / e1 */
19947 : 3 : cst1 = force_reg (XFmode, CONST1_RTX (XFmode));
19948 : 3 : emit_insn (gen_divxf3 (e2, cst1, e1));
19949 : 3 : emit_insn (gen_addxf3 (e2, e1, e2));
19950 : :
19951 : : /* op0 = 0.5 * e2 */
19952 : 3 : half = force_reg (XFmode, half);
19953 : 3 : emit_insn (gen_mulxf3 (op0, e2, half));
19954 : 3 : }
19955 : :
19956 : : /* Output code to perform an tanh XFmode calculation. */
19957 : :
19958 : : void
19959 : 1 : ix86_emit_i387_tanh (rtx op0, rtx op1)
19960 : : {
19961 : 1 : rtx e1 = gen_reg_rtx (XFmode);
19962 : 1 : rtx e2 = gen_reg_rtx (XFmode);
19963 : 1 : rtx scratch = gen_reg_rtx (HImode);
19964 : 1 : rtx flags = gen_rtx_REG (CCNOmode, FLAGS_REG);
19965 : 1 : rtx cst2, tmp;
19966 : 1 : rtx_code_label *jump_label = gen_label_rtx ();
19967 : 1 : rtx_insn *insn;
19968 : :
19969 : : /* scratch = fxam (op1) */
19970 : 1 : emit_insn (gen_fxamxf2_i387 (scratch, op1));
19971 : :
19972 : : /* e1 = expm1 (-|2 * op1|) */
19973 : 1 : emit_insn (gen_addxf3 (e2, op1, op1));
19974 : 1 : emit_insn (gen_absxf2 (e2, e2));
19975 : 1 : emit_insn (gen_negxf2 (e2, e2));
19976 : 1 : emit_insn (gen_expm1xf2 (e1, e2));
19977 : :
19978 : : /* e2 = e1 / (e1 + 2.0) */
19979 : 1 : cst2 = force_reg (XFmode, CONST2_RTX (XFmode));
19980 : 1 : emit_insn (gen_addxf3 (e2, e1, cst2));
19981 : 1 : emit_insn (gen_divxf3 (e2, e1, e2));
19982 : :
19983 : : /* flags = signbit (op1) */
19984 : 1 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x02)));
19985 : :
19986 : : /* if (!flags) then e2 = -e2 */
19987 : 1 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode,
19988 : : gen_rtx_NE (VOIDmode, flags, const0_rtx),
19989 : : gen_rtx_LABEL_REF (VOIDmode, jump_label),
19990 : : pc_rtx);
19991 : 1 : insn = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
19992 : 1 : predict_jump (REG_BR_PROB_BASE * 50 / 100);
19993 : 1 : JUMP_LABEL (insn) = jump_label;
19994 : :
19995 : 1 : emit_insn (gen_negxf2 (e2, e2));
19996 : :
19997 : 1 : emit_label (jump_label);
19998 : 1 : LABEL_NUSES (jump_label) = 1;
19999 : :
20000 : 1 : emit_move_insn (op0, e2);
20001 : 1 : }
20002 : :
20003 : : /* Output code to perform an asinh XFmode calculation. */
20004 : :
20005 : : void
20006 : 0 : ix86_emit_i387_asinh (rtx op0, rtx op1)
20007 : : {
20008 : 0 : rtx e1 = gen_reg_rtx (XFmode);
20009 : 0 : rtx e2 = gen_reg_rtx (XFmode);
20010 : 0 : rtx scratch = gen_reg_rtx (HImode);
20011 : 0 : rtx flags = gen_rtx_REG (CCNOmode, FLAGS_REG);
20012 : 0 : rtx cst1, tmp;
20013 : 0 : rtx_code_label *jump_label = gen_label_rtx ();
20014 : 0 : rtx_insn *insn;
20015 : :
20016 : : /* e2 = sqrt (op1^2 + 1.0) + 1.0 */
20017 : 0 : emit_insn (gen_mulxf3 (e1, op1, op1));
20018 : 0 : cst1 = force_reg (XFmode, CONST1_RTX (XFmode));
20019 : 0 : emit_insn (gen_addxf3 (e2, e1, cst1));
20020 : 0 : emit_insn (gen_sqrtxf2 (e2, e2));
20021 : 0 : emit_insn (gen_addxf3 (e2, e2, cst1));
20022 : :
20023 : : /* e1 = e1 / e2 */
20024 : 0 : emit_insn (gen_divxf3 (e1, e1, e2));
20025 : :
20026 : : /* scratch = fxam (op1) */
20027 : 0 : emit_insn (gen_fxamxf2_i387 (scratch, op1));
20028 : :
20029 : : /* e1 = e1 + |op1| */
20030 : 0 : emit_insn (gen_absxf2 (e2, op1));
20031 : 0 : emit_insn (gen_addxf3 (e1, e1, e2));
20032 : :
20033 : : /* e2 = log1p (e1) */
20034 : 0 : ix86_emit_i387_log1p (e2, e1);
20035 : :
20036 : : /* flags = signbit (op1) */
20037 : 0 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x02)));
20038 : :
20039 : : /* if (flags) then e2 = -e2 */
20040 : 0 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode,
20041 : : gen_rtx_EQ (VOIDmode, flags, const0_rtx),
20042 : : gen_rtx_LABEL_REF (VOIDmode, jump_label),
20043 : : pc_rtx);
20044 : 0 : insn = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
20045 : 0 : predict_jump (REG_BR_PROB_BASE * 50 / 100);
20046 : 0 : JUMP_LABEL (insn) = jump_label;
20047 : :
20048 : 0 : emit_insn (gen_negxf2 (e2, e2));
20049 : :
20050 : 0 : emit_label (jump_label);
20051 : 0 : LABEL_NUSES (jump_label) = 1;
20052 : :
20053 : 0 : emit_move_insn (op0, e2);
20054 : 0 : }
20055 : :
20056 : : /* Output code to perform an acosh XFmode calculation. */
20057 : :
20058 : : void
20059 : 0 : ix86_emit_i387_acosh (rtx op0, rtx op1)
20060 : : {
20061 : 0 : rtx e1 = gen_reg_rtx (XFmode);
20062 : 0 : rtx e2 = gen_reg_rtx (XFmode);
20063 : 0 : rtx cst1 = force_reg (XFmode, CONST1_RTX (XFmode));
20064 : :
20065 : : /* e2 = sqrt (op1 + 1.0) */
20066 : 0 : emit_insn (gen_addxf3 (e2, op1, cst1));
20067 : 0 : emit_insn (gen_sqrtxf2 (e2, e2));
20068 : :
20069 : : /* e1 = sqrt (op1 - 1.0) */
20070 : 0 : emit_insn (gen_subxf3 (e1, op1, cst1));
20071 : 0 : emit_insn (gen_sqrtxf2 (e1, e1));
20072 : :
20073 : : /* e1 = e1 * e2 */
20074 : 0 : emit_insn (gen_mulxf3 (e1, e1, e2));
20075 : :
20076 : : /* e1 = e1 + op1 */
20077 : 0 : emit_insn (gen_addxf3 (e1, e1, op1));
20078 : :
20079 : : /* op0 = log (e1) */
20080 : 0 : emit_insn (gen_logxf2 (op0, e1));
20081 : 0 : }
20082 : :
20083 : : /* Output code to perform an atanh XFmode calculation. */
20084 : :
20085 : : void
20086 : 4 : ix86_emit_i387_atanh (rtx op0, rtx op1)
20087 : : {
20088 : 4 : rtx e1 = gen_reg_rtx (XFmode);
20089 : 4 : rtx e2 = gen_reg_rtx (XFmode);
20090 : 4 : rtx scratch = gen_reg_rtx (HImode);
20091 : 4 : rtx flags = gen_rtx_REG (CCNOmode, FLAGS_REG);
20092 : 4 : rtx half = const_double_from_real_value (dconsthalf, XFmode);
20093 : 4 : rtx cst1, tmp;
20094 : 4 : rtx_code_label *jump_label = gen_label_rtx ();
20095 : 4 : rtx_insn *insn;
20096 : :
20097 : : /* scratch = fxam (op1) */
20098 : 4 : emit_insn (gen_fxamxf2_i387 (scratch, op1));
20099 : :
20100 : : /* e2 = |op1| */
20101 : 4 : emit_insn (gen_absxf2 (e2, op1));
20102 : :
20103 : : /* e1 = -(e2 + e2) / (e2 + 1.0) */
20104 : 4 : cst1 = force_reg (XFmode, CONST1_RTX (XFmode));
20105 : 4 : emit_insn (gen_addxf3 (e1, e2, cst1));
20106 : 4 : emit_insn (gen_addxf3 (e2, e2, e2));
20107 : 4 : emit_insn (gen_negxf2 (e2, e2));
20108 : 4 : emit_insn (gen_divxf3 (e1, e2, e1));
20109 : :
20110 : : /* e2 = log1p (e1) */
20111 : 4 : ix86_emit_i387_log1p (e2, e1);
20112 : :
20113 : : /* flags = signbit (op1) */
20114 : 4 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x02)));
20115 : :
20116 : : /* if (!flags) then e2 = -e2 */
20117 : 4 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode,
20118 : : gen_rtx_NE (VOIDmode, flags, const0_rtx),
20119 : : gen_rtx_LABEL_REF (VOIDmode, jump_label),
20120 : : pc_rtx);
20121 : 4 : insn = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
20122 : 4 : predict_jump (REG_BR_PROB_BASE * 50 / 100);
20123 : 4 : JUMP_LABEL (insn) = jump_label;
20124 : :
20125 : 4 : emit_insn (gen_negxf2 (e2, e2));
20126 : :
20127 : 4 : emit_label (jump_label);
20128 : 4 : LABEL_NUSES (jump_label) = 1;
20129 : :
20130 : : /* op0 = 0.5 * e2 */
20131 : 4 : half = force_reg (XFmode, half);
20132 : 4 : emit_insn (gen_mulxf3 (op0, e2, half));
20133 : 4 : }
20134 : :
20135 : : /* Output code to perform a log1p XFmode calculation. */
20136 : :
20137 : : void
20138 : 5 : ix86_emit_i387_log1p (rtx op0, rtx op1)
20139 : : {
20140 : 5 : rtx_code_label *label1 = gen_label_rtx ();
20141 : 5 : rtx_code_label *label2 = gen_label_rtx ();
20142 : :
20143 : 5 : rtx tmp = gen_reg_rtx (XFmode);
20144 : 5 : rtx res = gen_reg_rtx (XFmode);
20145 : 5 : rtx cst, cstln2, cst1;
20146 : 5 : rtx_insn *insn;
20147 : :
20148 : : /* The emit_jump call emits pending stack adjust, make sure it is emitted
20149 : : before the conditional jump, otherwise the stack adjustment will be
20150 : : only conditional. */
20151 : 5 : do_pending_stack_adjust ();
20152 : :
20153 : 5 : cst = const_double_from_real_value
20154 : 5 : (REAL_VALUE_ATOF ("0.29289321881345247561810596348408353", XFmode), XFmode);
20155 : 5 : cstln2 = force_reg (XFmode, standard_80387_constant_rtx (4)); /* fldln2 */
20156 : :
20157 : 5 : emit_insn (gen_absxf2 (tmp, op1));
20158 : :
20159 : 5 : cst = force_reg (XFmode, cst);
20160 : 5 : ix86_expand_branch (GE, tmp, cst, label1);
20161 : 5 : predict_jump (REG_BR_PROB_BASE * 10 / 100);
20162 : 5 : insn = get_last_insn ();
20163 : 5 : JUMP_LABEL (insn) = label1;
20164 : :
20165 : 5 : emit_insn (gen_fyl2xp1xf3_i387 (res, op1, cstln2));
20166 : 5 : emit_jump (label2);
20167 : :
20168 : 5 : emit_label (label1);
20169 : 5 : LABEL_NUSES (label1) = 1;
20170 : :
20171 : 5 : cst1 = force_reg (XFmode, CONST1_RTX (XFmode));
20172 : 5 : emit_insn (gen_rtx_SET (tmp, gen_rtx_PLUS (XFmode, op1, cst1)));
20173 : 5 : emit_insn (gen_fyl2xxf3_i387 (res, tmp, cstln2));
20174 : :
20175 : 5 : emit_label (label2);
20176 : 5 : LABEL_NUSES (label2) = 1;
20177 : :
20178 : 5 : emit_move_insn (op0, res);
20179 : 5 : }
20180 : :
20181 : : /* Emit code for round calculation. */
20182 : : void
20183 : 68 : ix86_emit_i387_round (rtx op0, rtx op1)
20184 : : {
20185 : 68 : machine_mode inmode = GET_MODE (op1);
20186 : 68 : machine_mode outmode = GET_MODE (op0);
20187 : 68 : rtx e1 = gen_reg_rtx (XFmode);
20188 : 68 : rtx e2 = gen_reg_rtx (XFmode);
20189 : 68 : rtx scratch = gen_reg_rtx (HImode);
20190 : 68 : rtx flags = gen_rtx_REG (CCNOmode, FLAGS_REG);
20191 : 68 : rtx half = const_double_from_real_value (dconsthalf, XFmode);
20192 : 68 : rtx res = gen_reg_rtx (outmode);
20193 : 68 : rtx_code_label *jump_label = gen_label_rtx ();
20194 : 68 : rtx (*floor_insn) (rtx, rtx);
20195 : 68 : rtx (*neg_insn) (rtx, rtx);
20196 : 68 : rtx_insn *insn;
20197 : 68 : rtx tmp;
20198 : :
20199 : 68 : switch (inmode)
20200 : : {
20201 : 37 : case E_SFmode:
20202 : 37 : case E_DFmode:
20203 : 37 : tmp = gen_reg_rtx (XFmode);
20204 : :
20205 : 37 : emit_insn (gen_rtx_SET (tmp, gen_rtx_FLOAT_EXTEND (XFmode, op1)));
20206 : 37 : op1 = tmp;
20207 : 37 : break;
20208 : : case E_XFmode:
20209 : : break;
20210 : 0 : default:
20211 : 0 : gcc_unreachable ();
20212 : : }
20213 : :
20214 : 68 : switch (outmode)
20215 : : {
20216 : : case E_SFmode:
20217 : : floor_insn = gen_frndintxf2_floor;
20218 : : neg_insn = gen_negsf2;
20219 : : break;
20220 : 8 : case E_DFmode:
20221 : 8 : floor_insn = gen_frndintxf2_floor;
20222 : 8 : neg_insn = gen_negdf2;
20223 : 8 : break;
20224 : 10 : case E_XFmode:
20225 : 10 : floor_insn = gen_frndintxf2_floor;
20226 : 10 : neg_insn = gen_negxf2;
20227 : 10 : break;
20228 : 0 : case E_HImode:
20229 : 0 : floor_insn = gen_lfloorxfhi2;
20230 : 0 : neg_insn = gen_neghi2;
20231 : 0 : break;
20232 : 10 : case E_SImode:
20233 : 10 : floor_insn = gen_lfloorxfsi2;
20234 : 10 : neg_insn = gen_negsi2;
20235 : 10 : break;
20236 : 36 : case E_DImode:
20237 : 36 : floor_insn = gen_lfloorxfdi2;
20238 : 36 : neg_insn = gen_negdi2;
20239 : 36 : break;
20240 : 0 : default:
20241 : 0 : gcc_unreachable ();
20242 : : }
20243 : :
20244 : : /* round(a) = sgn(a) * floor(fabs(a) + 0.5) */
20245 : :
20246 : : /* scratch = fxam(op1) */
20247 : 68 : emit_insn (gen_fxamxf2_i387 (scratch, op1));
20248 : :
20249 : : /* e1 = fabs(op1) */
20250 : 68 : emit_insn (gen_absxf2 (e1, op1));
20251 : :
20252 : : /* e2 = e1 + 0.5 */
20253 : 68 : half = force_reg (XFmode, half);
20254 : 68 : emit_insn (gen_rtx_SET (e2, gen_rtx_PLUS (XFmode, e1, half)));
20255 : :
20256 : : /* res = floor(e2) */
20257 : 68 : switch (outmode)
20258 : : {
20259 : 12 : case E_SFmode:
20260 : 12 : case E_DFmode:
20261 : 12 : {
20262 : 12 : tmp = gen_reg_rtx (XFmode);
20263 : :
20264 : 12 : emit_insn (floor_insn (tmp, e2));
20265 : 12 : emit_insn (gen_rtx_SET (res,
20266 : : gen_rtx_UNSPEC (outmode, gen_rtvec (1, tmp),
20267 : : UNSPEC_TRUNC_NOOP)));
20268 : : }
20269 : 12 : break;
20270 : 56 : default:
20271 : 56 : emit_insn (floor_insn (res, e2));
20272 : : }
20273 : :
20274 : : /* flags = signbit(a) */
20275 : 68 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x02)));
20276 : :
20277 : : /* if (flags) then res = -res */
20278 : 68 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode,
20279 : : gen_rtx_EQ (VOIDmode, flags, const0_rtx),
20280 : : gen_rtx_LABEL_REF (VOIDmode, jump_label),
20281 : : pc_rtx);
20282 : 68 : insn = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
20283 : 68 : predict_jump (REG_BR_PROB_BASE * 50 / 100);
20284 : 68 : JUMP_LABEL (insn) = jump_label;
20285 : :
20286 : 68 : emit_insn (neg_insn (res, res));
20287 : :
20288 : 68 : emit_label (jump_label);
20289 : 68 : LABEL_NUSES (jump_label) = 1;
20290 : :
20291 : 68 : emit_move_insn (op0, res);
20292 : 68 : }
20293 : :
20294 : : /* Output code to perform a Newton-Rhapson approximation of a single precision
20295 : : floating point divide [http://en.wikipedia.org/wiki/N-th_root_algorithm]. */
20296 : :
20297 : : void
20298 : 49 : ix86_emit_swdivsf (rtx res, rtx a, rtx b, machine_mode mode)
20299 : : {
20300 : 49 : rtx x0, x1, e0, e1;
20301 : :
20302 : 49 : x0 = gen_reg_rtx (mode);
20303 : 49 : e0 = gen_reg_rtx (mode);
20304 : 49 : e1 = gen_reg_rtx (mode);
20305 : 49 : x1 = gen_reg_rtx (mode);
20306 : :
20307 : 49 : b = force_reg (mode, b);
20308 : :
20309 : : /* x0 = rcp(b) estimate */
20310 : 49 : if (mode == V16SFmode || mode == V8DFmode)
20311 : : {
20312 : 0 : emit_insn (gen_rtx_SET (x0, gen_rtx_UNSPEC (mode, gen_rtvec (1, b),
20313 : : UNSPEC_RCP14)));
20314 : : }
20315 : : else
20316 : 49 : emit_insn (gen_rtx_SET (x0, gen_rtx_UNSPEC (mode, gen_rtvec (1, b),
20317 : : UNSPEC_RCP)));
20318 : :
20319 : 49 : unsigned vector_size = GET_MODE_SIZE (mode);
20320 : :
20321 : : /* (a - (rcp(b) * a * b)) * rcp(b) + rcp(b) * a
20322 : : N-R step with 2 fma implementation. */
20323 : 49 : if (TARGET_FMA
20324 : 48 : || (TARGET_AVX512F && vector_size == 64)
20325 : 48 : || (TARGET_AVX512VL && (vector_size == 32 || vector_size == 16)))
20326 : : {
20327 : : /* e0 = x0 * a */
20328 : 1 : emit_insn (gen_rtx_SET (e0, gen_rtx_MULT (mode, x0, a)));
20329 : : /* e1 = e0 * b - a */
20330 : 1 : emit_insn (gen_rtx_SET (e1, gen_rtx_FMA (mode, e0, b,
20331 : : gen_rtx_NEG (mode, a))));
20332 : : /* res = - e1 * x0 + e0 */
20333 : 1 : emit_insn (gen_rtx_SET (res, gen_rtx_FMA (mode,
20334 : : gen_rtx_NEG (mode, e1),
20335 : : x0, e0)));
20336 : : }
20337 : : else
20338 : : /* a / b = a * ((rcp(b) + rcp(b)) - (b * rcp(b) * rcp (b))) */
20339 : : {
20340 : : /* e0 = x0 * b */
20341 : 48 : emit_insn (gen_rtx_SET (e0, gen_rtx_MULT (mode, x0, b)));
20342 : :
20343 : : /* e1 = x0 + x0 */
20344 : 48 : emit_insn (gen_rtx_SET (e1, gen_rtx_PLUS (mode, x0, x0)));
20345 : :
20346 : : /* e0 = x0 * e0 */
20347 : 48 : emit_insn (gen_rtx_SET (e0, gen_rtx_MULT (mode, x0, e0)));
20348 : :
20349 : : /* x1 = e1 - e0 */
20350 : 48 : emit_insn (gen_rtx_SET (x1, gen_rtx_MINUS (mode, e1, e0)));
20351 : :
20352 : : /* res = a * x1 */
20353 : 48 : emit_insn (gen_rtx_SET (res, gen_rtx_MULT (mode, a, x1)));
20354 : : }
20355 : 49 : }
20356 : :
20357 : : /* Output code to perform a Newton-Rhapson approximation of a
20358 : : single precision floating point [reciprocal] square root. */
20359 : :
20360 : : void
20361 : 85 : ix86_emit_swsqrtsf (rtx res, rtx a, machine_mode mode, bool recip)
20362 : : {
20363 : 85 : rtx x0, e0, e1, e2, e3, mthree, mhalf;
20364 : 85 : REAL_VALUE_TYPE r;
20365 : 85 : int unspec;
20366 : :
20367 : 85 : x0 = gen_reg_rtx (mode);
20368 : 85 : e0 = gen_reg_rtx (mode);
20369 : 85 : e1 = gen_reg_rtx (mode);
20370 : 85 : e2 = gen_reg_rtx (mode);
20371 : 85 : e3 = gen_reg_rtx (mode);
20372 : :
20373 : 85 : real_from_integer (&r, VOIDmode, -3, SIGNED);
20374 : 85 : mthree = const_double_from_real_value (r, SFmode);
20375 : :
20376 : 85 : real_arithmetic (&r, NEGATE_EXPR, &dconsthalf, NULL);
20377 : 85 : mhalf = const_double_from_real_value (r, SFmode);
20378 : 85 : unspec = UNSPEC_RSQRT;
20379 : :
20380 : 85 : if (VECTOR_MODE_P (mode))
20381 : : {
20382 : 66 : mthree = ix86_build_const_vector (mode, true, mthree);
20383 : 66 : mhalf = ix86_build_const_vector (mode, true, mhalf);
20384 : : /* There is no 512-bit rsqrt. There is however rsqrt14. */
20385 : 132 : if (GET_MODE_SIZE (mode) == 64)
20386 : 0 : unspec = UNSPEC_RSQRT14;
20387 : : }
20388 : :
20389 : : /* sqrt(a) = -0.5 * a * rsqrtss(a) * (a * rsqrtss(a) * rsqrtss(a) - 3.0)
20390 : : rsqrt(a) = -0.5 * rsqrtss(a) * (a * rsqrtss(a) * rsqrtss(a) - 3.0) */
20391 : :
20392 : 85 : a = force_reg (mode, a);
20393 : :
20394 : : /* x0 = rsqrt(a) estimate */
20395 : 85 : emit_insn (gen_rtx_SET (x0, gen_rtx_UNSPEC (mode, gen_rtvec (1, a),
20396 : : unspec)));
20397 : :
20398 : : /* If (a == 0.0) Filter out infinity to prevent NaN for sqrt(0.0). */
20399 : 85 : if (!recip)
20400 : : {
20401 : 57 : rtx zero = force_reg (mode, CONST0_RTX(mode));
20402 : 57 : rtx mask;
20403 : :
20404 : : /* Handle masked compare. */
20405 : 110 : if (VECTOR_MODE_P (mode) && GET_MODE_SIZE (mode) == 64)
20406 : : {
20407 : 0 : mask = gen_reg_rtx (HImode);
20408 : : /* Imm value 0x4 corresponds to not-equal comparison. */
20409 : 0 : emit_insn (gen_avx512f_cmpv16sf3 (mask, zero, a, GEN_INT (0x4)));
20410 : 0 : emit_insn (gen_avx512f_blendmv16sf (x0, zero, x0, mask));
20411 : : }
20412 : : else
20413 : : {
20414 : 57 : mask = gen_reg_rtx (mode);
20415 : 57 : emit_insn (gen_rtx_SET (mask, gen_rtx_NE (mode, zero, a)));
20416 : 57 : emit_insn (gen_rtx_SET (x0, gen_rtx_AND (mode, x0, mask)));
20417 : : }
20418 : : }
20419 : :
20420 : 85 : mthree = force_reg (mode, mthree);
20421 : :
20422 : : /* e0 = x0 * a */
20423 : 85 : emit_insn (gen_rtx_SET (e0, gen_rtx_MULT (mode, x0, a)));
20424 : :
20425 : 85 : unsigned vector_size = GET_MODE_SIZE (mode);
20426 : 85 : if (TARGET_FMA
20427 : 77 : || (TARGET_AVX512F && vector_size == 64)
20428 : 77 : || (TARGET_AVX512VL && (vector_size == 32 || vector_size == 16)))
20429 : 16 : emit_insn (gen_rtx_SET (e2,
20430 : : gen_rtx_FMA (mode, e0, x0, mthree)));
20431 : : else
20432 : : {
20433 : : /* e1 = e0 * x0 */
20434 : 69 : emit_insn (gen_rtx_SET (e1, gen_rtx_MULT (mode, e0, x0)));
20435 : :
20436 : : /* e2 = e1 - 3. */
20437 : 69 : emit_insn (gen_rtx_SET (e2, gen_rtx_PLUS (mode, e1, mthree)));
20438 : : }
20439 : :
20440 : 85 : mhalf = force_reg (mode, mhalf);
20441 : 85 : if (recip)
20442 : : /* e3 = -.5 * x0 */
20443 : 28 : emit_insn (gen_rtx_SET (e3, gen_rtx_MULT (mode, x0, mhalf)));
20444 : : else
20445 : : /* e3 = -.5 * e0 */
20446 : 57 : emit_insn (gen_rtx_SET (e3, gen_rtx_MULT (mode, e0, mhalf)));
20447 : : /* ret = e2 * e3 */
20448 : 85 : emit_insn (gen_rtx_SET (res, gen_rtx_MULT (mode, e2, e3)));
20449 : 85 : }
20450 : :
20451 : : /* Expand fabs (OP0) and return a new rtx that holds the result. The
20452 : : mask for masking out the sign-bit is stored in *SMASK, if that is
20453 : : non-null. */
20454 : :
20455 : : static rtx
20456 : 1068 : ix86_expand_sse_fabs (rtx op0, rtx *smask)
20457 : : {
20458 : 1068 : machine_mode vmode, mode = GET_MODE (op0);
20459 : 1068 : rtx xa, mask;
20460 : :
20461 : 1068 : xa = gen_reg_rtx (mode);
20462 : 1068 : if (mode == SFmode)
20463 : : vmode = V4SFmode;
20464 : 488 : else if (mode == DFmode)
20465 : : vmode = V2DFmode;
20466 : : else
20467 : 0 : vmode = mode;
20468 : 1068 : mask = ix86_build_signbit_mask (vmode, VECTOR_MODE_P (mode), true);
20469 : 1068 : if (!VECTOR_MODE_P (mode))
20470 : : {
20471 : : /* We need to generate a scalar mode mask in this case. */
20472 : 1068 : rtx tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (1, const0_rtx));
20473 : 1068 : tmp = gen_rtx_VEC_SELECT (mode, mask, tmp);
20474 : 1068 : mask = gen_reg_rtx (mode);
20475 : 1068 : emit_insn (gen_rtx_SET (mask, tmp));
20476 : : }
20477 : 1068 : emit_insn (gen_rtx_SET (xa, gen_rtx_AND (mode, op0, mask)));
20478 : :
20479 : 1068 : if (smask)
20480 : 1015 : *smask = mask;
20481 : :
20482 : 1068 : return xa;
20483 : : }
20484 : :
20485 : : /* Expands a comparison of OP0 with OP1 using comparison code CODE,
20486 : : swapping the operands if SWAP_OPERANDS is true. The expanded
20487 : : code is a forward jump to a newly created label in case the
20488 : : comparison is true. The generated label rtx is returned. */
20489 : : static rtx_code_label *
20490 : 1083 : ix86_expand_sse_compare_and_jump (enum rtx_code code, rtx op0, rtx op1,
20491 : : bool swap_operands)
20492 : : {
20493 : 1083 : bool unordered_compare = ix86_unordered_fp_compare (code);
20494 : 1083 : rtx_code_label *label;
20495 : 1083 : rtx tmp, reg;
20496 : :
20497 : 1083 : if (swap_operands)
20498 : 34 : std::swap (op0, op1);
20499 : :
20500 : 1083 : label = gen_label_rtx ();
20501 : 1083 : tmp = gen_rtx_COMPARE (CCFPmode, op0, op1);
20502 : 1083 : if (unordered_compare)
20503 : 927 : tmp = gen_rtx_UNSPEC (CCFPmode, gen_rtvec (1, tmp), UNSPEC_NOTRAP);
20504 : 1083 : reg = gen_rtx_REG (CCFPmode, FLAGS_REG);
20505 : 1083 : emit_insn (gen_rtx_SET (reg, tmp));
20506 : 1083 : tmp = gen_rtx_fmt_ee (code, VOIDmode, reg, const0_rtx);
20507 : 1083 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
20508 : : gen_rtx_LABEL_REF (VOIDmode, label), pc_rtx);
20509 : 1083 : tmp = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
20510 : 1083 : JUMP_LABEL (tmp) = label;
20511 : :
20512 : 1083 : return label;
20513 : : }
20514 : :
20515 : : /* Expand a mask generating SSE comparison instruction comparing OP0 with OP1
20516 : : using comparison code CODE. Operands are swapped for the comparison if
20517 : : SWAP_OPERANDS is true. Returns a rtx for the generated mask. */
20518 : : static rtx
20519 : 564 : ix86_expand_sse_compare_mask (enum rtx_code code, rtx op0, rtx op1,
20520 : : bool swap_operands)
20521 : : {
20522 : 564 : rtx (*insn)(rtx, rtx, rtx, rtx);
20523 : 564 : machine_mode mode = GET_MODE (op0);
20524 : 564 : rtx mask = gen_reg_rtx (mode);
20525 : :
20526 : 564 : if (swap_operands)
20527 : 385 : std::swap (op0, op1);
20528 : :
20529 : 564 : insn = mode == DFmode ? gen_setcc_df_sse : gen_setcc_sf_sse;
20530 : :
20531 : 564 : emit_insn (insn (mask, op0, op1,
20532 : : gen_rtx_fmt_ee (code, mode, op0, op1)));
20533 : 564 : return mask;
20534 : : }
20535 : :
20536 : : /* Expand copysign from SIGN to the positive value ABS_VALUE
20537 : : storing in RESULT. If MASK is non-null, it shall be a mask to mask out
20538 : : the sign-bit. */
20539 : :
20540 : : static void
20541 : 1035 : ix86_sse_copysign_to_positive (rtx result, rtx abs_value, rtx sign, rtx mask)
20542 : : {
20543 : 1035 : machine_mode mode = GET_MODE (sign);
20544 : 1035 : rtx sgn = gen_reg_rtx (mode);
20545 : 1035 : if (mask == NULL_RTX)
20546 : : {
20547 : 28 : machine_mode vmode;
20548 : :
20549 : 28 : if (mode == SFmode)
20550 : : vmode = V4SFmode;
20551 : : else if (mode == DFmode)
20552 : : vmode = V2DFmode;
20553 : : else if (mode == HFmode)
20554 : : vmode = V8HFmode;
20555 : : else
20556 : 28 : vmode = mode;
20557 : :
20558 : 28 : mask = ix86_build_signbit_mask (vmode, VECTOR_MODE_P (mode), false);
20559 : 28 : if (!VECTOR_MODE_P (mode))
20560 : : {
20561 : : /* We need to generate a scalar mode mask in this case. */
20562 : 28 : rtx tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (1, const0_rtx));
20563 : 28 : tmp = gen_rtx_VEC_SELECT (mode, mask, tmp);
20564 : 28 : mask = gen_reg_rtx (mode);
20565 : 28 : emit_insn (gen_rtx_SET (mask, tmp));
20566 : : }
20567 : : }
20568 : : else
20569 : 1007 : mask = gen_rtx_NOT (mode, mask);
20570 : 1035 : emit_insn (gen_rtx_SET (sgn, gen_rtx_AND (mode, mask, sign)));
20571 : 1035 : emit_insn (gen_rtx_SET (result, gen_rtx_IOR (mode, abs_value, sgn)));
20572 : 1035 : }
20573 : :
20574 : : /* Expand SSE sequence for computing lround from OP1 storing
20575 : : into OP0. */
20576 : :
20577 : : void
20578 : 28 : ix86_expand_lround (rtx op0, rtx op1)
20579 : : {
20580 : : /* C code for the stuff we're doing below:
20581 : : tmp = op1 + copysign (nextafter (0.5, 0.0), op1)
20582 : : return (long)tmp;
20583 : : */
20584 : 28 : machine_mode mode = GET_MODE (op1);
20585 : 28 : const struct real_format *fmt;
20586 : 28 : REAL_VALUE_TYPE pred_half, half_minus_pred_half;
20587 : 28 : rtx adj;
20588 : :
20589 : : /* load nextafter (0.5, 0.0) */
20590 : 28 : fmt = REAL_MODE_FORMAT (mode);
20591 : 28 : real_2expN (&half_minus_pred_half, -(fmt->p) - 1, mode);
20592 : 28 : real_arithmetic (&pred_half, MINUS_EXPR, &dconsthalf, &half_minus_pred_half);
20593 : :
20594 : : /* adj = copysign (0.5, op1) */
20595 : 28 : adj = force_reg (mode, const_double_from_real_value (pred_half, mode));
20596 : 28 : ix86_sse_copysign_to_positive (adj, adj, force_reg (mode, op1), NULL_RTX);
20597 : :
20598 : : /* adj = op1 + adj */
20599 : 28 : adj = expand_simple_binop (mode, PLUS, adj, op1, NULL_RTX, 0, OPTAB_DIRECT);
20600 : :
20601 : : /* op0 = (imode)adj */
20602 : 28 : expand_fix (op0, adj, 0);
20603 : 28 : }
20604 : :
20605 : : /* Expand SSE2 sequence for computing lround from OPERAND1 storing
20606 : : into OPERAND0. */
20607 : :
20608 : : void
20609 : 68 : ix86_expand_lfloorceil (rtx op0, rtx op1, bool do_floor)
20610 : : {
20611 : : /* C code for the stuff we're doing below (for do_floor):
20612 : : xi = (long)op1;
20613 : : xi -= (double)xi > op1 ? 1 : 0;
20614 : : return xi;
20615 : : */
20616 : 68 : machine_mode fmode = GET_MODE (op1);
20617 : 68 : machine_mode imode = GET_MODE (op0);
20618 : 68 : rtx ireg, freg, tmp;
20619 : 68 : rtx_code_label *label;
20620 : :
20621 : : /* reg = (long)op1 */
20622 : 68 : ireg = gen_reg_rtx (imode);
20623 : 68 : expand_fix (ireg, op1, 0);
20624 : :
20625 : : /* freg = (double)reg */
20626 : 68 : freg = gen_reg_rtx (fmode);
20627 : 68 : expand_float (freg, ireg, 0);
20628 : :
20629 : : /* ireg = (freg > op1) ? ireg - 1 : ireg */
20630 : 136 : label = ix86_expand_sse_compare_and_jump (UNLE,
20631 : 68 : freg, op1, !do_floor);
20632 : 102 : tmp = expand_simple_binop (imode, do_floor ? MINUS : PLUS,
20633 : : ireg, const1_rtx, NULL_RTX, 0, OPTAB_DIRECT);
20634 : 68 : emit_move_insn (ireg, tmp);
20635 : :
20636 : 68 : emit_label (label);
20637 : 68 : LABEL_NUSES (label) = 1;
20638 : :
20639 : 68 : emit_move_insn (op0, ireg);
20640 : 68 : }
20641 : :
20642 : : /* Generate and return a rtx of mode MODE for 2**n where n is the number
20643 : : of bits of the mantissa of MODE, which must be one of DFmode or SFmode. */
20644 : :
20645 : : static rtx
20646 : 1015 : ix86_gen_TWO52 (machine_mode mode)
20647 : : {
20648 : 1015 : const struct real_format *fmt;
20649 : 1015 : REAL_VALUE_TYPE TWO52r;
20650 : 1015 : rtx TWO52;
20651 : :
20652 : 1015 : fmt = REAL_MODE_FORMAT (mode);
20653 : 1015 : real_2expN (&TWO52r, fmt->p - 1, mode);
20654 : 1015 : TWO52 = const_double_from_real_value (TWO52r, mode);
20655 : 1015 : TWO52 = force_reg (mode, TWO52);
20656 : :
20657 : 1015 : return TWO52;
20658 : : }
20659 : :
20660 : : /* Expand rint rounding OPERAND1 and storing the result in OPERAND0. */
20661 : :
20662 : : void
20663 : 122 : ix86_expand_rint (rtx operand0, rtx operand1)
20664 : : {
20665 : : /* C code for the stuff we're doing below:
20666 : : xa = fabs (operand1);
20667 : : if (!isless (xa, 2**52))
20668 : : return operand1;
20669 : : two52 = 2**52;
20670 : : if (flag_rounding_math)
20671 : : {
20672 : : two52 = copysign (two52, operand1);
20673 : : xa = operand1;
20674 : : }
20675 : : xa = xa + two52 - two52;
20676 : : return copysign (xa, operand1);
20677 : : */
20678 : 122 : machine_mode mode = GET_MODE (operand0);
20679 : 122 : rtx res, xa, TWO52, mask;
20680 : 122 : rtx_code_label *label;
20681 : :
20682 : 122 : TWO52 = ix86_gen_TWO52 (mode);
20683 : :
20684 : : /* Temporary for holding the result, initialized to the input
20685 : : operand to ease control flow. */
20686 : 122 : res = copy_to_reg (operand1);
20687 : :
20688 : : /* xa = abs (operand1) */
20689 : 122 : xa = ix86_expand_sse_fabs (res, &mask);
20690 : :
20691 : : /* if (!isless (xa, TWO52)) goto label; */
20692 : 122 : label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
20693 : :
20694 : 122 : if (flag_rounding_math)
20695 : : {
20696 : 53 : ix86_sse_copysign_to_positive (TWO52, TWO52, res, mask);
20697 : 53 : xa = res;
20698 : : }
20699 : :
20700 : 122 : xa = expand_simple_binop (mode, PLUS, xa, TWO52, NULL_RTX, 0, OPTAB_DIRECT);
20701 : 122 : xa = expand_simple_binop (mode, MINUS, xa, TWO52, xa, 0, OPTAB_DIRECT);
20702 : :
20703 : : /* Remove the sign with FE_DOWNWARD, where x - x = -0.0. */
20704 : 122 : if (HONOR_SIGNED_ZEROS (mode) && flag_rounding_math)
20705 : 53 : xa = ix86_expand_sse_fabs (xa, NULL);
20706 : :
20707 : 122 : ix86_sse_copysign_to_positive (res, xa, res, mask);
20708 : :
20709 : 122 : emit_label (label);
20710 : 122 : LABEL_NUSES (label) = 1;
20711 : :
20712 : 122 : emit_move_insn (operand0, res);
20713 : 122 : }
20714 : :
20715 : : /* Expand SSE2 sequence for computing floor or ceil
20716 : : from OPERAND1 storing into OPERAND0. */
20717 : : void
20718 : 564 : ix86_expand_floorceil (rtx operand0, rtx operand1, bool do_floor)
20719 : : {
20720 : : /* C code for the stuff we expand below.
20721 : : double xa = fabs (x), x2;
20722 : : if (!isless (xa, TWO52))
20723 : : return x;
20724 : : x2 = (double)(long)x;
20725 : :
20726 : : Compensate. Floor:
20727 : : if (x2 > x)
20728 : : x2 -= 1;
20729 : : Compensate. Ceil:
20730 : : if (x2 < x)
20731 : : x2 += 1;
20732 : :
20733 : : if (HONOR_SIGNED_ZEROS (mode))
20734 : : return copysign (x2, x);
20735 : : return x2;
20736 : : */
20737 : 564 : machine_mode mode = GET_MODE (operand0);
20738 : 564 : rtx xa, xi, TWO52, tmp, one, res, mask;
20739 : 564 : rtx_code_label *label;
20740 : :
20741 : 564 : TWO52 = ix86_gen_TWO52 (mode);
20742 : :
20743 : : /* Temporary for holding the result, initialized to the input
20744 : : operand to ease control flow. */
20745 : 564 : res = copy_to_reg (operand1);
20746 : :
20747 : : /* xa = abs (operand1) */
20748 : 564 : xa = ix86_expand_sse_fabs (res, &mask);
20749 : :
20750 : : /* if (!isless (xa, TWO52)) goto label; */
20751 : 564 : label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
20752 : :
20753 : : /* xa = (double)(long)x */
20754 : 564 : xi = gen_reg_rtx (int_mode_for_mode (mode).require ());
20755 : 564 : expand_fix (xi, res, 0);
20756 : 564 : expand_float (xa, xi, 0);
20757 : :
20758 : : /* generate 1.0 */
20759 : 564 : one = force_reg (mode, const_double_from_real_value (dconst1, mode));
20760 : :
20761 : : /* Compensate: xa = xa - (xa > operand1 ? 1 : 0) */
20762 : 564 : tmp = ix86_expand_sse_compare_mask (UNGT, xa, res, !do_floor);
20763 : 564 : emit_insn (gen_rtx_SET (tmp, gen_rtx_AND (mode, one, tmp)));
20764 : 949 : tmp = expand_simple_binop (mode, do_floor ? MINUS : PLUS,
20765 : : xa, tmp, NULL_RTX, 0, OPTAB_DIRECT);
20766 : 564 : if (HONOR_SIGNED_ZEROS (mode))
20767 : : {
20768 : : /* Remove the sign with FE_DOWNWARD, where x - x = -0.0. */
20769 : 517 : if (do_floor && flag_rounding_math)
20770 : 0 : tmp = ix86_expand_sse_fabs (tmp, NULL);
20771 : :
20772 : 517 : ix86_sse_copysign_to_positive (tmp, tmp, res, mask);
20773 : : }
20774 : 564 : emit_move_insn (res, tmp);
20775 : :
20776 : 564 : emit_label (label);
20777 : 564 : LABEL_NUSES (label) = 1;
20778 : :
20779 : 564 : emit_move_insn (operand0, res);
20780 : 564 : }
20781 : :
20782 : : /* Expand SSE2 sequence for computing floor or ceil from OPERAND1 storing
20783 : : into OPERAND0 without relying on DImode truncation via cvttsd2siq
20784 : : that is only available on 64bit targets. */
20785 : : void
20786 : 0 : ix86_expand_floorceildf_32 (rtx operand0, rtx operand1, bool do_floor)
20787 : : {
20788 : : /* C code for the stuff we expand below.
20789 : : double xa = fabs (x), x2;
20790 : : if (!isless (xa, TWO52))
20791 : : return x;
20792 : : xa = xa + TWO52 - TWO52;
20793 : : x2 = copysign (xa, x);
20794 : :
20795 : : Compensate. Floor:
20796 : : if (x2 > x)
20797 : : x2 -= 1;
20798 : : Compensate. Ceil:
20799 : : if (x2 < x)
20800 : : x2 += 1;
20801 : :
20802 : : if (HONOR_SIGNED_ZEROS (mode))
20803 : : x2 = copysign (x2, x);
20804 : : return x2;
20805 : : */
20806 : 0 : machine_mode mode = GET_MODE (operand0);
20807 : 0 : rtx xa, TWO52, tmp, one, res, mask;
20808 : 0 : rtx_code_label *label;
20809 : :
20810 : 0 : TWO52 = ix86_gen_TWO52 (mode);
20811 : :
20812 : : /* Temporary for holding the result, initialized to the input
20813 : : operand to ease control flow. */
20814 : 0 : res = copy_to_reg (operand1);
20815 : :
20816 : : /* xa = abs (operand1) */
20817 : 0 : xa = ix86_expand_sse_fabs (res, &mask);
20818 : :
20819 : : /* if (!isless (xa, TWO52)) goto label; */
20820 : 0 : label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
20821 : :
20822 : : /* xa = xa + TWO52 - TWO52; */
20823 : 0 : xa = expand_simple_binop (mode, PLUS, xa, TWO52, NULL_RTX, 0, OPTAB_DIRECT);
20824 : 0 : xa = expand_simple_binop (mode, MINUS, xa, TWO52, xa, 0, OPTAB_DIRECT);
20825 : :
20826 : : /* xa = copysign (xa, operand1) */
20827 : 0 : ix86_sse_copysign_to_positive (xa, xa, res, mask);
20828 : :
20829 : : /* generate 1.0 */
20830 : 0 : one = force_reg (mode, const_double_from_real_value (dconst1, mode));
20831 : :
20832 : : /* Compensate: xa = xa - (xa > operand1 ? 1 : 0) */
20833 : 0 : tmp = ix86_expand_sse_compare_mask (UNGT, xa, res, !do_floor);
20834 : 0 : emit_insn (gen_rtx_SET (tmp, gen_rtx_AND (mode, one, tmp)));
20835 : 0 : tmp = expand_simple_binop (mode, do_floor ? MINUS : PLUS,
20836 : : xa, tmp, NULL_RTX, 0, OPTAB_DIRECT);
20837 : 0 : if (HONOR_SIGNED_ZEROS (mode))
20838 : : {
20839 : : /* Remove the sign with FE_DOWNWARD, where x - x = -0.0. */
20840 : 0 : if (do_floor && flag_rounding_math)
20841 : 0 : tmp = ix86_expand_sse_fabs (tmp, NULL);
20842 : :
20843 : 0 : ix86_sse_copysign_to_positive (tmp, tmp, res, mask);
20844 : : }
20845 : 0 : emit_move_insn (res, tmp);
20846 : :
20847 : 0 : emit_label (label);
20848 : 0 : LABEL_NUSES (label) = 1;
20849 : :
20850 : 0 : emit_move_insn (operand0, res);
20851 : 0 : }
20852 : :
20853 : : /* Expand SSE sequence for computing trunc
20854 : : from OPERAND1 storing into OPERAND0. */
20855 : : void
20856 : 315 : ix86_expand_trunc (rtx operand0, rtx operand1)
20857 : : {
20858 : : /* C code for SSE variant we expand below.
20859 : : double xa = fabs (x), x2;
20860 : : if (!isless (xa, TWO52))
20861 : : return x;
20862 : : x2 = (double)(long)x;
20863 : : if (HONOR_SIGNED_ZEROS (mode))
20864 : : return copysign (x2, x);
20865 : : return x2;
20866 : : */
20867 : 315 : machine_mode mode = GET_MODE (operand0);
20868 : 315 : rtx xa, xi, TWO52, res, mask;
20869 : 315 : rtx_code_label *label;
20870 : :
20871 : 315 : TWO52 = ix86_gen_TWO52 (mode);
20872 : :
20873 : : /* Temporary for holding the result, initialized to the input
20874 : : operand to ease control flow. */
20875 : 315 : res = copy_to_reg (operand1);
20876 : :
20877 : : /* xa = abs (operand1) */
20878 : 315 : xa = ix86_expand_sse_fabs (res, &mask);
20879 : :
20880 : : /* if (!isless (xa, TWO52)) goto label; */
20881 : 315 : label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
20882 : :
20883 : : /* xa = (double)(long)x */
20884 : 315 : xi = gen_reg_rtx (int_mode_for_mode (mode).require ());
20885 : 315 : expand_fix (xi, res, 0);
20886 : 315 : expand_float (xa, xi, 0);
20887 : :
20888 : 315 : if (HONOR_SIGNED_ZEROS (mode))
20889 : 301 : ix86_sse_copysign_to_positive (xa, xa, res, mask);
20890 : :
20891 : 315 : emit_move_insn (res, xa);
20892 : :
20893 : 315 : emit_label (label);
20894 : 315 : LABEL_NUSES (label) = 1;
20895 : :
20896 : 315 : emit_move_insn (operand0, res);
20897 : 315 : }
20898 : :
20899 : : /* Expand SSE sequence for computing trunc from OPERAND1 storing
20900 : : into OPERAND0 without relying on DImode truncation via cvttsd2siq
20901 : : that is only available on 64bit targets. */
20902 : : void
20903 : 0 : ix86_expand_truncdf_32 (rtx operand0, rtx operand1)
20904 : : {
20905 : 0 : machine_mode mode = GET_MODE (operand0);
20906 : 0 : rtx xa, xa2, TWO52, tmp, one, res, mask;
20907 : 0 : rtx_code_label *label;
20908 : :
20909 : : /* C code for SSE variant we expand below.
20910 : : double xa = fabs (x), x2;
20911 : : if (!isless (xa, TWO52))
20912 : : return x;
20913 : : xa2 = xa + TWO52 - TWO52;
20914 : : Compensate:
20915 : : if (xa2 > xa)
20916 : : xa2 -= 1.0;
20917 : : x2 = copysign (xa2, x);
20918 : : return x2;
20919 : : */
20920 : :
20921 : 0 : TWO52 = ix86_gen_TWO52 (mode);
20922 : :
20923 : : /* Temporary for holding the result, initialized to the input
20924 : : operand to ease control flow. */
20925 : 0 : res =copy_to_reg (operand1);
20926 : :
20927 : : /* xa = abs (operand1) */
20928 : 0 : xa = ix86_expand_sse_fabs (res, &mask);
20929 : :
20930 : : /* if (!isless (xa, TWO52)) goto label; */
20931 : 0 : label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
20932 : :
20933 : : /* xa2 = xa + TWO52 - TWO52; */
20934 : 0 : xa2 = expand_simple_binop (mode, PLUS, xa, TWO52, NULL_RTX, 0, OPTAB_DIRECT);
20935 : 0 : xa2 = expand_simple_binop (mode, MINUS, xa2, TWO52, xa2, 0, OPTAB_DIRECT);
20936 : :
20937 : : /* generate 1.0 */
20938 : 0 : one = force_reg (mode, const_double_from_real_value (dconst1, mode));
20939 : :
20940 : : /* Compensate: xa2 = xa2 - (xa2 > xa ? 1 : 0) */
20941 : 0 : tmp = ix86_expand_sse_compare_mask (UNGT, xa2, xa, false);
20942 : 0 : emit_insn (gen_rtx_SET (tmp, gen_rtx_AND (mode, one, tmp)));
20943 : 0 : tmp = expand_simple_binop (mode, MINUS,
20944 : : xa2, tmp, NULL_RTX, 0, OPTAB_DIRECT);
20945 : : /* Remove the sign with FE_DOWNWARD, where x - x = -0.0. */
20946 : 0 : if (HONOR_SIGNED_ZEROS (mode) && flag_rounding_math)
20947 : 0 : tmp = ix86_expand_sse_fabs (tmp, NULL);
20948 : :
20949 : : /* res = copysign (xa2, operand1) */
20950 : 0 : ix86_sse_copysign_to_positive (res, tmp, res, mask);
20951 : :
20952 : 0 : emit_label (label);
20953 : 0 : LABEL_NUSES (label) = 1;
20954 : :
20955 : 0 : emit_move_insn (operand0, res);
20956 : 0 : }
20957 : :
20958 : : /* Expand SSE sequence for computing round
20959 : : from OPERAND1 storing into OPERAND0. */
20960 : : void
20961 : 14 : ix86_expand_round (rtx operand0, rtx operand1)
20962 : : {
20963 : : /* C code for the stuff we're doing below:
20964 : : double xa = fabs (x);
20965 : : if (!isless (xa, TWO52))
20966 : : return x;
20967 : : xa = (double)(long)(xa + nextafter (0.5, 0.0));
20968 : : return copysign (xa, x);
20969 : : */
20970 : 14 : machine_mode mode = GET_MODE (operand0);
20971 : 14 : rtx res, TWO52, xa, xi, half, mask;
20972 : 14 : rtx_code_label *label;
20973 : 14 : const struct real_format *fmt;
20974 : 14 : REAL_VALUE_TYPE pred_half, half_minus_pred_half;
20975 : :
20976 : : /* Temporary for holding the result, initialized to the input
20977 : : operand to ease control flow. */
20978 : 14 : res = copy_to_reg (operand1);
20979 : :
20980 : 14 : TWO52 = ix86_gen_TWO52 (mode);
20981 : 14 : xa = ix86_expand_sse_fabs (res, &mask);
20982 : 14 : label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
20983 : :
20984 : : /* load nextafter (0.5, 0.0) */
20985 : 14 : fmt = REAL_MODE_FORMAT (mode);
20986 : 14 : real_2expN (&half_minus_pred_half, -(fmt->p) - 1, mode);
20987 : 14 : real_arithmetic (&pred_half, MINUS_EXPR, &dconsthalf, &half_minus_pred_half);
20988 : :
20989 : : /* xa = xa + 0.5 */
20990 : 14 : half = force_reg (mode, const_double_from_real_value (pred_half, mode));
20991 : 14 : xa = expand_simple_binop (mode, PLUS, xa, half, NULL_RTX, 0, OPTAB_DIRECT);
20992 : :
20993 : : /* xa = (double)(int64_t)xa */
20994 : 14 : xi = gen_reg_rtx (int_mode_for_mode (mode).require ());
20995 : 14 : expand_fix (xi, xa, 0);
20996 : 14 : expand_float (xa, xi, 0);
20997 : :
20998 : : /* res = copysign (xa, operand1) */
20999 : 14 : ix86_sse_copysign_to_positive (res, xa, res, mask);
21000 : :
21001 : 14 : emit_label (label);
21002 : 14 : LABEL_NUSES (label) = 1;
21003 : :
21004 : 14 : emit_move_insn (operand0, res);
21005 : 14 : }
21006 : :
21007 : : /* Expand SSE sequence for computing round from OPERAND1 storing
21008 : : into OPERAND0 without relying on DImode truncation via cvttsd2siq
21009 : : that is only available on 64bit targets. */
21010 : : void
21011 : 0 : ix86_expand_rounddf_32 (rtx operand0, rtx operand1)
21012 : : {
21013 : : /* C code for the stuff we expand below.
21014 : : double xa = fabs (x), xa2, x2;
21015 : : if (!isless (xa, TWO52))
21016 : : return x;
21017 : : Using the absolute value and copying back sign makes
21018 : : -0.0 -> -0.0 correct.
21019 : : xa2 = xa + TWO52 - TWO52;
21020 : : Compensate.
21021 : : dxa = xa2 - xa;
21022 : : if (dxa <= -0.5)
21023 : : xa2 += 1;
21024 : : else if (dxa > 0.5)
21025 : : xa2 -= 1;
21026 : : x2 = copysign (xa2, x);
21027 : : return x2;
21028 : : */
21029 : 0 : machine_mode mode = GET_MODE (operand0);
21030 : 0 : rtx xa, xa2, dxa, TWO52, tmp, half, mhalf, one, res, mask;
21031 : 0 : rtx_code_label *label;
21032 : :
21033 : 0 : TWO52 = ix86_gen_TWO52 (mode);
21034 : :
21035 : : /* Temporary for holding the result, initialized to the input
21036 : : operand to ease control flow. */
21037 : 0 : res = copy_to_reg (operand1);
21038 : :
21039 : : /* xa = abs (operand1) */
21040 : 0 : xa = ix86_expand_sse_fabs (res, &mask);
21041 : :
21042 : : /* if (!isless (xa, TWO52)) goto label; */
21043 : 0 : label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
21044 : :
21045 : : /* xa2 = xa + TWO52 - TWO52; */
21046 : 0 : xa2 = expand_simple_binop (mode, PLUS, xa, TWO52, NULL_RTX, 0, OPTAB_DIRECT);
21047 : 0 : xa2 = expand_simple_binop (mode, MINUS, xa2, TWO52, xa2, 0, OPTAB_DIRECT);
21048 : :
21049 : : /* dxa = xa2 - xa; */
21050 : 0 : dxa = expand_simple_binop (mode, MINUS, xa2, xa, NULL_RTX, 0, OPTAB_DIRECT);
21051 : :
21052 : : /* generate 0.5, 1.0 and -0.5 */
21053 : 0 : half = force_reg (mode, const_double_from_real_value (dconsthalf, mode));
21054 : 0 : one = expand_simple_binop (mode, PLUS, half, half, NULL_RTX, 0, OPTAB_DIRECT);
21055 : 0 : mhalf = expand_simple_binop (mode, MINUS, half, one, NULL_RTX,
21056 : : 0, OPTAB_DIRECT);
21057 : :
21058 : : /* Compensate. */
21059 : : /* xa2 = xa2 - (dxa > 0.5 ? 1 : 0) */
21060 : 0 : tmp = ix86_expand_sse_compare_mask (UNGT, dxa, half, false);
21061 : 0 : emit_insn (gen_rtx_SET (tmp, gen_rtx_AND (mode, tmp, one)));
21062 : 0 : xa2 = expand_simple_binop (mode, MINUS, xa2, tmp, NULL_RTX, 0, OPTAB_DIRECT);
21063 : : /* xa2 = xa2 + (dxa <= -0.5 ? 1 : 0) */
21064 : 0 : tmp = ix86_expand_sse_compare_mask (UNGE, mhalf, dxa, false);
21065 : 0 : emit_insn (gen_rtx_SET (tmp, gen_rtx_AND (mode, tmp, one)));
21066 : 0 : xa2 = expand_simple_binop (mode, PLUS, xa2, tmp, NULL_RTX, 0, OPTAB_DIRECT);
21067 : :
21068 : : /* res = copysign (xa2, operand1) */
21069 : 0 : ix86_sse_copysign_to_positive (res, xa2, res, mask);
21070 : :
21071 : 0 : emit_label (label);
21072 : 0 : LABEL_NUSES (label) = 1;
21073 : :
21074 : 0 : emit_move_insn (operand0, res);
21075 : 0 : }
21076 : :
21077 : : /* Expand SSE sequence for computing round
21078 : : from OP1 storing into OP0 using sse4 round insn. */
21079 : : void
21080 : 9 : ix86_expand_round_sse4 (rtx op0, rtx op1)
21081 : : {
21082 : 9 : machine_mode mode = GET_MODE (op0);
21083 : 9 : rtx e1, e2, res, half;
21084 : 9 : const struct real_format *fmt;
21085 : 9 : REAL_VALUE_TYPE pred_half, half_minus_pred_half;
21086 : 9 : rtx (*gen_copysign) (rtx, rtx, rtx);
21087 : 9 : rtx (*gen_round) (rtx, rtx, rtx);
21088 : :
21089 : 9 : switch (mode)
21090 : : {
21091 : : case E_HFmode:
21092 : : gen_copysign = gen_copysignhf3;
21093 : : gen_round = gen_sse4_1_roundhf2;
21094 : : break;
21095 : 4 : case E_SFmode:
21096 : 4 : gen_copysign = gen_copysignsf3;
21097 : 4 : gen_round = gen_sse4_1_roundsf2;
21098 : 4 : break;
21099 : 4 : case E_DFmode:
21100 : 4 : gen_copysign = gen_copysigndf3;
21101 : 4 : gen_round = gen_sse4_1_rounddf2;
21102 : 4 : break;
21103 : 0 : default:
21104 : 0 : gcc_unreachable ();
21105 : : }
21106 : :
21107 : : /* round (a) = trunc (a + copysign (0.5, a)) */
21108 : :
21109 : : /* load nextafter (0.5, 0.0) */
21110 : 9 : fmt = REAL_MODE_FORMAT (mode);
21111 : 9 : real_2expN (&half_minus_pred_half, -(fmt->p) - 1, mode);
21112 : 9 : real_arithmetic (&pred_half, MINUS_EXPR, &dconsthalf, &half_minus_pred_half);
21113 : 9 : half = const_double_from_real_value (pred_half, mode);
21114 : :
21115 : : /* e1 = copysign (0.5, op1) */
21116 : 9 : e1 = gen_reg_rtx (mode);
21117 : 9 : emit_insn (gen_copysign (e1, half, op1));
21118 : :
21119 : : /* e2 = op1 + e1 */
21120 : 9 : e2 = expand_simple_binop (mode, PLUS, op1, e1, NULL_RTX, 0, OPTAB_DIRECT);
21121 : :
21122 : : /* res = trunc (e2) */
21123 : 9 : res = gen_reg_rtx (mode);
21124 : 9 : emit_insn (gen_round (res, e2, GEN_INT (ROUND_TRUNC)));
21125 : :
21126 : 9 : emit_move_insn (op0, res);
21127 : 9 : }
21128 : :
21129 : : /* A cached (set (nil) (vselect (vconcat (nil) (nil)) (parallel [])))
21130 : : insn, so that expand_vselect{,_vconcat} doesn't have to create a fresh
21131 : : insn every time. */
21132 : :
21133 : : static GTY(()) rtx_insn *vselect_insn;
21134 : :
21135 : : /* Initialize vselect_insn. */
21136 : :
21137 : : static void
21138 : 7256 : init_vselect_insn (void)
21139 : : {
21140 : 7256 : unsigned i;
21141 : 7256 : rtx x;
21142 : :
21143 : 7256 : x = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (MAX_VECT_LEN));
21144 : 471640 : for (i = 0; i < MAX_VECT_LEN; ++i)
21145 : 464384 : XVECEXP (x, 0, i) = const0_rtx;
21146 : 7256 : x = gen_rtx_VEC_SELECT (V2DFmode, gen_rtx_VEC_CONCAT (V4DFmode, const0_rtx,
21147 : : const0_rtx), x);
21148 : 7256 : x = gen_rtx_SET (const0_rtx, x);
21149 : 7256 : start_sequence ();
21150 : 7256 : vselect_insn = emit_insn (x);
21151 : 7256 : end_sequence ();
21152 : 7256 : }
21153 : :
21154 : : /* Construct (set target (vec_select op0 (parallel perm))) and
21155 : : return true if that's a valid instruction in the active ISA. */
21156 : :
21157 : : static bool
21158 : 537282 : expand_vselect (rtx target, rtx op0, const unsigned char *perm,
21159 : : unsigned nelt, bool testing_p)
21160 : : {
21161 : 537282 : unsigned int i;
21162 : 537282 : rtx x, save_vconcat;
21163 : 537282 : int icode;
21164 : :
21165 : 537282 : if (vselect_insn == NULL_RTX)
21166 : 1542 : init_vselect_insn ();
21167 : :
21168 : 537282 : x = XEXP (SET_SRC (PATTERN (vselect_insn)), 1);
21169 : 537282 : PUT_NUM_ELEM (XVEC (x, 0), nelt);
21170 : 4213210 : for (i = 0; i < nelt; ++i)
21171 : 3675928 : XVECEXP (x, 0, i) = GEN_INT (perm[i]);
21172 : 537282 : save_vconcat = XEXP (SET_SRC (PATTERN (vselect_insn)), 0);
21173 : 537282 : XEXP (SET_SRC (PATTERN (vselect_insn)), 0) = op0;
21174 : 537282 : PUT_MODE (SET_SRC (PATTERN (vselect_insn)), GET_MODE (target));
21175 : 537282 : SET_DEST (PATTERN (vselect_insn)) = target;
21176 : 537282 : icode = recog_memoized (vselect_insn);
21177 : :
21178 : 537282 : if (icode >= 0 && !testing_p)
21179 : 70806 : emit_insn (copy_rtx (PATTERN (vselect_insn)));
21180 : :
21181 : 537282 : SET_DEST (PATTERN (vselect_insn)) = const0_rtx;
21182 : 537282 : XEXP (SET_SRC (PATTERN (vselect_insn)), 0) = save_vconcat;
21183 : 537282 : INSN_CODE (vselect_insn) = -1;
21184 : :
21185 : 537282 : return icode >= 0;
21186 : : }
21187 : :
21188 : : /* Similar, but generate a vec_concat from op0 and op1 as well. */
21189 : :
21190 : : static bool
21191 : 471801 : expand_vselect_vconcat (rtx target, rtx op0, rtx op1,
21192 : : const unsigned char *perm, unsigned nelt,
21193 : : bool testing_p)
21194 : : {
21195 : 471801 : machine_mode v2mode;
21196 : 471801 : rtx x;
21197 : 471801 : bool ok;
21198 : :
21199 : 471801 : if (vselect_insn == NULL_RTX)
21200 : 5714 : init_vselect_insn ();
21201 : :
21202 : 471801 : if (!GET_MODE_2XWIDER_MODE (GET_MODE (op0)).exists (&v2mode))
21203 : : return false;
21204 : 471801 : x = XEXP (SET_SRC (PATTERN (vselect_insn)), 0);
21205 : 471801 : PUT_MODE (x, v2mode);
21206 : 471801 : XEXP (x, 0) = op0;
21207 : 471801 : XEXP (x, 1) = op1;
21208 : 471801 : ok = expand_vselect (target, x, perm, nelt, testing_p);
21209 : 471801 : XEXP (x, 0) = const0_rtx;
21210 : 471801 : XEXP (x, 1) = const0_rtx;
21211 : 471801 : return ok;
21212 : : }
21213 : :
21214 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement D
21215 : : using movss or movsd. */
21216 : : static bool
21217 : 313786 : expand_vec_perm_movs (struct expand_vec_perm_d *d)
21218 : : {
21219 : 313786 : machine_mode vmode = d->vmode;
21220 : 313786 : unsigned i, nelt = d->nelt;
21221 : 313786 : rtx x;
21222 : :
21223 : 313786 : if (d->one_operand_p)
21224 : : return false;
21225 : :
21226 : 287306 : if (!(TARGET_SSE && (vmode == V4SFmode || vmode == V4SImode))
21227 : 136553 : && !(TARGET_MMX_WITH_SSE && (vmode == V2SFmode || vmode == V2SImode))
21228 : 83242 : && !(TARGET_SSE2 && (vmode == V2DFmode || vmode == V2DImode)))
21229 : : return false;
21230 : :
21231 : : /* Only the first element is changed. */
21232 : 212369 : if (d->perm[0] != nelt && d->perm[0] != 0)
21233 : : return false;
21234 : 156524 : for (i = 1; i < nelt; ++i)
21235 : 122489 : if (d->perm[i] != i + nelt - d->perm[0])
21236 : : return false;
21237 : :
21238 : 34035 : if (d->testing_p)
21239 : : return true;
21240 : :
21241 : 5589 : if (d->perm[0] == nelt)
21242 : 0 : x = gen_rtx_VEC_MERGE (vmode, d->op1, d->op0, GEN_INT (1));
21243 : : else
21244 : 5589 : x = gen_rtx_VEC_MERGE (vmode, d->op0, d->op1, GEN_INT (1));
21245 : :
21246 : 5589 : emit_insn (gen_rtx_SET (d->target, x));
21247 : :
21248 : 5589 : return true;
21249 : : }
21250 : :
21251 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement D
21252 : : using insertps. */
21253 : : static bool
21254 : 279751 : expand_vec_perm_insertps (struct expand_vec_perm_d *d)
21255 : : {
21256 : 279751 : machine_mode vmode = d->vmode;
21257 : 279751 : unsigned i, cnt_s, nelt = d->nelt;
21258 : 279751 : int cnt_d = -1;
21259 : 279751 : rtx src, dst;
21260 : :
21261 : 279751 : if (d->one_operand_p)
21262 : : return false;
21263 : :
21264 : 253271 : if (!(TARGET_SSE4_1
21265 : 36699 : && (vmode == V4SFmode || vmode == V4SImode
21266 : 26464 : || (TARGET_MMX_WITH_SSE
21267 : 18924 : && (vmode == V2SFmode || vmode == V2SImode)))))
21268 : : return false;
21269 : :
21270 : 51003 : for (i = 0; i < nelt; ++i)
21271 : : {
21272 : 48749 : if (d->perm[i] == i)
21273 : 9637 : continue;
21274 : 39112 : if (cnt_d != -1)
21275 : : {
21276 : : cnt_d = -1;
21277 : : break;
21278 : : }
21279 : 20683 : cnt_d = i;
21280 : : }
21281 : :
21282 : 20683 : if (cnt_d == -1)
21283 : : {
21284 : 41023 : for (i = 0; i < nelt; ++i)
21285 : : {
21286 : 39091 : if (d->perm[i] == i + nelt)
21287 : 4165 : continue;
21288 : 34926 : if (cnt_d != -1)
21289 : : return false;
21290 : 18429 : cnt_d = i;
21291 : : }
21292 : :
21293 : 1932 : if (cnt_d == -1)
21294 : : return false;
21295 : : }
21296 : :
21297 : 4186 : if (d->testing_p)
21298 : : return true;
21299 : :
21300 : 550 : gcc_assert (cnt_d != -1);
21301 : :
21302 : 550 : cnt_s = d->perm[cnt_d];
21303 : 550 : if (cnt_s < nelt)
21304 : : {
21305 : 241 : src = d->op0;
21306 : 241 : dst = d->op1;
21307 : : }
21308 : : else
21309 : : {
21310 : 309 : cnt_s -= nelt;
21311 : 309 : src = d->op1;
21312 : 309 : dst = d->op0;
21313 : : }
21314 : 550 : gcc_assert (cnt_s < nelt);
21315 : :
21316 : 550 : rtx x = gen_sse4_1_insertps (vmode, d->target, dst, src,
21317 : 550 : GEN_INT (cnt_s << 6 | cnt_d << 4));
21318 : 550 : emit_insn (x);
21319 : :
21320 : 550 : return true;
21321 : : }
21322 : :
21323 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement D
21324 : : in terms of blendp[sd] / pblendw / pblendvb / vpblendd. */
21325 : :
21326 : : static bool
21327 : 317983 : expand_vec_perm_blend (struct expand_vec_perm_d *d)
21328 : : {
21329 : 317983 : machine_mode mmode, vmode = d->vmode;
21330 : 317983 : unsigned i, nelt = d->nelt;
21331 : 317983 : unsigned HOST_WIDE_INT mask;
21332 : 317983 : rtx target, op0, op1, maskop, x;
21333 : 317983 : rtx rperm[32], vperm;
21334 : :
21335 : 317983 : if (d->one_operand_p)
21336 : : return false;
21337 : 5959 : if (TARGET_AVX512F && GET_MODE_SIZE (vmode) == 64
21338 : 292614 : && (TARGET_AVX512BW
21339 : 691 : || GET_MODE_UNIT_SIZE (vmode) >= 4))
21340 : : ;
21341 : 302269 : else if (TARGET_AVX2 && GET_MODE_SIZE (vmode) == 32)
21342 : : ;
21343 : 283735 : else if (TARGET_AVX && (vmode == V4DFmode || vmode == V8SFmode))
21344 : : ;
21345 : 277148 : else if (TARGET_SSE4_1
21346 : 308743 : && (GET_MODE_SIZE (vmode) == 16
21347 : 21224 : || (TARGET_MMX_WITH_SSE && GET_MODE_SIZE (vmode) == 8)
21348 : 2569 : || GET_MODE_SIZE (vmode) == 4))
21349 : : ;
21350 : : else
21351 : : return false;
21352 : :
21353 : : /* This is a blend, not a permute. Elements must stay in their
21354 : : respective lanes. */
21355 : 104221 : for (i = 0; i < nelt; ++i)
21356 : : {
21357 : 100024 : unsigned e = d->perm[i];
21358 : 100024 : if (!(e == i || e == i + nelt))
21359 : : return false;
21360 : : }
21361 : :
21362 : 4197 : if (d->testing_p)
21363 : : return true;
21364 : :
21365 : : /* ??? Without SSE4.1, we could implement this with and/andn/or. This
21366 : : decision should be extracted elsewhere, so that we only try that
21367 : : sequence once all budget==3 options have been tried. */
21368 : 2894 : target = d->target;
21369 : 2894 : op0 = d->op0;
21370 : 2894 : op1 = d->op1;
21371 : 2894 : mask = 0;
21372 : :
21373 : 2894 : switch (vmode)
21374 : : {
21375 : : case E_V8DFmode:
21376 : : case E_V16SFmode:
21377 : : case E_V4DFmode:
21378 : : case E_V8SFmode:
21379 : : case E_V2DFmode:
21380 : : case E_V4SFmode:
21381 : : case E_V2SFmode:
21382 : : case E_V2HImode:
21383 : : case E_V4HImode:
21384 : : case E_V8HImode:
21385 : : case E_V8SImode:
21386 : : case E_V32HImode:
21387 : : case E_V64QImode:
21388 : : case E_V16SImode:
21389 : : case E_V8DImode:
21390 : 10396 : for (i = 0; i < nelt; ++i)
21391 : 9000 : mask |= ((unsigned HOST_WIDE_INT) (d->perm[i] >= nelt)) << i;
21392 : : break;
21393 : :
21394 : : case E_V2DImode:
21395 : 18 : for (i = 0; i < 2; ++i)
21396 : 18 : mask |= (d->perm[i] >= 2 ? 15 : 0) << (i * 4);
21397 : 6 : vmode = V8HImode;
21398 : 6 : goto do_subreg;
21399 : :
21400 : : case E_V2SImode:
21401 : 24 : for (i = 0; i < 2; ++i)
21402 : 24 : mask |= (d->perm[i] >= 2 ? 3 : 0) << (i * 2);
21403 : 8 : vmode = V4HImode;
21404 : 8 : goto do_subreg;
21405 : :
21406 : 861 : case E_V4SImode:
21407 : 861 : if (TARGET_AVX2)
21408 : : {
21409 : : /* Use vpblendd instead of vpblendw. */
21410 : 135 : for (i = 0; i < nelt; ++i)
21411 : 108 : mask |= ((unsigned HOST_WIDE_INT) (d->perm[i] >= nelt)) << i;
21412 : : break;
21413 : : }
21414 : : else
21415 : : {
21416 : 4170 : for (i = 0; i < 4; ++i)
21417 : 5200 : mask |= (d->perm[i] >= 4 ? 3 : 0) << (i * 2);
21418 : 834 : vmode = V8HImode;
21419 : 834 : goto do_subreg;
21420 : : }
21421 : :
21422 : : case E_V16QImode:
21423 : : /* See if bytes move in pairs so we can use pblendw with
21424 : : an immediate argument, rather than pblendvb with a vector
21425 : : argument. */
21426 : 93 : for (i = 0; i < 16; i += 2)
21427 : 92 : if (d->perm[i] + 1 != d->perm[i + 1])
21428 : : {
21429 : 83 : use_pblendvb:
21430 : 3427 : for (i = 0; i < nelt; ++i)
21431 : 3152 : rperm[i] = (d->perm[i] < nelt ? const0_rtx : constm1_rtx);
21432 : :
21433 : 275 : finish_pblendvb:
21434 : 276 : vperm = gen_rtx_CONST_VECTOR (vmode, gen_rtvec_v (nelt, rperm));
21435 : 276 : vperm = force_reg (vmode, vperm);
21436 : :
21437 : 552 : if (GET_MODE_SIZE (vmode) == 4)
21438 : 120 : emit_insn (gen_mmx_pblendvb_v4qi (target, op0, op1, vperm));
21439 : 312 : else if (GET_MODE_SIZE (vmode) == 8)
21440 : 40 : emit_insn (gen_mmx_pblendvb_v8qi (target, op0, op1, vperm));
21441 : 232 : else if (GET_MODE_SIZE (vmode) == 16)
21442 : 83 : emit_insn (gen_sse4_1_pblendvb (target, op0, op1, vperm));
21443 : : else
21444 : 33 : emit_insn (gen_avx2_pblendvb (target, op0, op1, vperm));
21445 : 276 : if (target != d->target)
21446 : 1 : emit_move_insn (d->target, gen_lowpart (d->vmode, target));
21447 : 276 : return true;
21448 : : }
21449 : :
21450 : 9 : for (i = 0; i < 8; ++i)
21451 : 8 : mask |= (d->perm[i * 2] >= 16) << i;
21452 : : vmode = V8HImode;
21453 : : /* FALLTHRU */
21454 : :
21455 : 1163 : do_subreg:
21456 : 1163 : target = gen_reg_rtx (vmode);
21457 : 1163 : op0 = gen_lowpart (vmode, op0);
21458 : 1163 : op1 = gen_lowpart (vmode, op1);
21459 : 1163 : break;
21460 : :
21461 : : case E_V8QImode:
21462 : 40 : for (i = 0; i < 8; i += 2)
21463 : 40 : if (d->perm[i] + 1 != d->perm[i + 1])
21464 : 40 : goto use_pblendvb;
21465 : :
21466 : 0 : for (i = 0; i < 4; ++i)
21467 : 0 : mask |= (d->perm[i * 2] >= 8) << i;
21468 : 0 : vmode = V4HImode;
21469 : 0 : goto do_subreg;
21470 : :
21471 : : case E_V4QImode:
21472 : 120 : for (i = 0; i < 4; i += 2)
21473 : 120 : if (d->perm[i] + 1 != d->perm[i + 1])
21474 : 120 : goto use_pblendvb;
21475 : :
21476 : 0 : for (i = 0; i < 2; ++i)
21477 : 0 : mask |= (d->perm[i * 2] >= 4) << i;
21478 : 0 : vmode = V2HImode;
21479 : 0 : goto do_subreg;
21480 : :
21481 : : case E_V32QImode:
21482 : : /* See if bytes move in pairs. If not, vpblendvb must be used. */
21483 : 4928 : for (i = 0; i < 32; i += 2)
21484 : 4640 : if (d->perm[i] + 1 != d->perm[i + 1])
21485 : 32 : goto use_pblendvb;
21486 : : /* See if bytes move in quadruplets. If yes, vpblendd
21487 : : with immediate can be used. */
21488 : 2592 : for (i = 0; i < 32; i += 4)
21489 : 2304 : if (d->perm[i] + 2 != d->perm[i + 2])
21490 : : break;
21491 : 288 : if (i < 32)
21492 : : {
21493 : : /* See if bytes move the same in both lanes. If yes,
21494 : : vpblendw with immediate can be used. */
21495 : 0 : for (i = 0; i < 16; i += 2)
21496 : 0 : if (d->perm[i] + 16 != d->perm[i + 16])
21497 : 0 : goto use_pblendvb;
21498 : :
21499 : : /* Use vpblendw. */
21500 : 0 : for (i = 0; i < 16; ++i)
21501 : 0 : mask |= (d->perm[i * 2] >= 32) << i;
21502 : 0 : vmode = V16HImode;
21503 : 0 : goto do_subreg;
21504 : : }
21505 : :
21506 : : /* Use vpblendd. */
21507 : 2592 : for (i = 0; i < 8; ++i)
21508 : 2304 : mask |= (d->perm[i * 4] >= 32) << i;
21509 : 288 : vmode = V8SImode;
21510 : 288 : goto do_subreg;
21511 : :
21512 : : case E_V16HImode:
21513 : : /* See if words move in pairs. If yes, vpblendd can be used. */
21514 : 186 : for (i = 0; i < 16; i += 2)
21515 : 169 : if (d->perm[i] + 1 != d->perm[i + 1])
21516 : : break;
21517 : 50 : if (i < 16)
21518 : : {
21519 : : /* See if words move the same in both lanes. If not,
21520 : : vpblendvb must be used. */
21521 : 290 : for (i = 0; i < 8; i++)
21522 : 258 : if (d->perm[i] + 8 != d->perm[i + 8])
21523 : : {
21524 : : /* Use vpblendvb. */
21525 : 33 : for (i = 0; i < 32; ++i)
21526 : 32 : rperm[i] = (d->perm[i / 2] < 16 ? const0_rtx : constm1_rtx);
21527 : :
21528 : 1 : vmode = V32QImode;
21529 : 1 : nelt = 32;
21530 : 1 : target = gen_reg_rtx (vmode);
21531 : 1 : op0 = gen_lowpart (vmode, op0);
21532 : 1 : op1 = gen_lowpart (vmode, op1);
21533 : 1 : goto finish_pblendvb;
21534 : : }
21535 : :
21536 : : /* Use vpblendw. */
21537 : 544 : for (i = 0; i < 16; ++i)
21538 : 512 : mask |= (d->perm[i] >= 16) << i;
21539 : : break;
21540 : : }
21541 : :
21542 : : /* Use vpblendd. */
21543 : 153 : for (i = 0; i < 8; ++i)
21544 : 136 : mask |= (d->perm[i * 2] >= 16) << i;
21545 : 17 : vmode = V8SImode;
21546 : 17 : goto do_subreg;
21547 : :
21548 : : case E_V4DImode:
21549 : : /* Use vpblendd. */
21550 : 45 : for (i = 0; i < 4; ++i)
21551 : 54 : mask |= (d->perm[i] >= 4 ? 3 : 0) << (i * 2);
21552 : 9 : vmode = V8SImode;
21553 : 9 : goto do_subreg;
21554 : :
21555 : 0 : default:
21556 : 0 : gcc_unreachable ();
21557 : : }
21558 : :
21559 : 2618 : switch (vmode)
21560 : : {
21561 : : case E_V8DFmode:
21562 : : case E_V8DImode:
21563 : : mmode = QImode;
21564 : : break;
21565 : 5 : case E_V16SFmode:
21566 : 5 : case E_V16SImode:
21567 : 5 : mmode = HImode;
21568 : 5 : break;
21569 : 6 : case E_V32HImode:
21570 : 6 : mmode = SImode;
21571 : 6 : break;
21572 : 1 : case E_V64QImode:
21573 : 1 : mmode = DImode;
21574 : 1 : break;
21575 : : default:
21576 : : mmode = VOIDmode;
21577 : : }
21578 : :
21579 : : /* Canonicalize vec_merge. */
21580 : 2618 : if (swap_commutative_operands_p (op1, op0)
21581 : : /* Two operands have same precedence, then
21582 : : first bit of mask select first operand. */
21583 : 2618 : || (!swap_commutative_operands_p (op0, op1)
21584 : 2618 : && !(mask & 1)))
21585 : : {
21586 : 2611 : unsigned n_elts = GET_MODE_NUNITS (vmode);
21587 : 2611 : std::swap (op0, op1);
21588 : 2611 : unsigned HOST_WIDE_INT mask_all = HOST_WIDE_INT_1U;
21589 : 2611 : if (n_elts == HOST_BITS_PER_WIDE_INT)
21590 : : mask_all = -1;
21591 : : else
21592 : 2610 : mask_all = (HOST_WIDE_INT_1U << n_elts) - 1;
21593 : 2611 : mask = ~mask & mask_all;
21594 : : }
21595 : :
21596 : 2618 : if (mmode != VOIDmode)
21597 : 22 : maskop = force_reg (mmode, gen_int_mode (mask, mmode));
21598 : : else
21599 : 2596 : maskop = GEN_INT (mask);
21600 : :
21601 : : /* This matches five different patterns with the different modes. */
21602 : 2618 : x = gen_rtx_VEC_MERGE (vmode, op1, op0, maskop);
21603 : 2618 : x = gen_rtx_SET (target, x);
21604 : 2618 : emit_insn (x);
21605 : 2618 : if (target != d->target)
21606 : 1163 : emit_move_insn (d->target, gen_lowpart (d->vmode, target));
21607 : :
21608 : : return true;
21609 : : }
21610 : :
21611 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement D
21612 : : in terms of the variable form of vpermilps.
21613 : :
21614 : : Note that we will have already failed the immediate input vpermilps,
21615 : : which requires that the high and low part shuffle be identical; the
21616 : : variable form doesn't require that. */
21617 : :
21618 : : static bool
21619 : 138449 : expand_vec_perm_vpermil (struct expand_vec_perm_d *d)
21620 : : {
21621 : 138449 : rtx rperm[8], vperm;
21622 : 138449 : unsigned i;
21623 : :
21624 : 138449 : if (!TARGET_AVX || !d->one_operand_p
21625 : 12354 : || (d->vmode != V8SImode && d->vmode != V8SFmode))
21626 : : return false;
21627 : :
21628 : : /* We can only permute within the 128-bit lane. */
21629 : 20167 : for (i = 0; i < 8; ++i)
21630 : : {
21631 : 19229 : unsigned e = d->perm[i];
21632 : 19229 : if (i < 4 ? e >= 4 : e < 4)
21633 : : return false;
21634 : : }
21635 : :
21636 : 938 : if (d->testing_p)
21637 : : return true;
21638 : :
21639 : 657 : for (i = 0; i < 8; ++i)
21640 : : {
21641 : 584 : unsigned e = d->perm[i];
21642 : :
21643 : : /* Within each 128-bit lane, the elements of op0 are numbered
21644 : : from 0 and the elements of op1 are numbered from 4. */
21645 : 584 : if (e >= 8 + 4)
21646 : 0 : e -= 8;
21647 : 584 : else if (e >= 4)
21648 : 292 : e -= 4;
21649 : :
21650 : 584 : rperm[i] = GEN_INT (e);
21651 : : }
21652 : :
21653 : 73 : vperm = gen_rtx_CONST_VECTOR (V8SImode, gen_rtvec_v (8, rperm));
21654 : 73 : vperm = force_reg (V8SImode, vperm);
21655 : 73 : rtx target = d->target;
21656 : 73 : rtx op0 = d->op0;
21657 : 73 : if (d->vmode == V8SImode)
21658 : : {
21659 : 21 : target = lowpart_subreg (V8SFmode, target, V8SImode);
21660 : 21 : op0 = lowpart_subreg (V8SFmode, op0, V8SImode);
21661 : : }
21662 : :
21663 : 73 : emit_insn (gen_avx_vpermilvarv8sf3 (target, op0, vperm));
21664 : :
21665 : 73 : return true;
21666 : : }
21667 : :
21668 : : /* For V*[QHS]Imode permutations, check if the same permutation
21669 : : can't be performed in a 2x, 4x or 8x wider inner mode. */
21670 : :
21671 : : static bool
21672 : 161385 : canonicalize_vector_int_perm (const struct expand_vec_perm_d *d,
21673 : : struct expand_vec_perm_d *nd)
21674 : : {
21675 : 161385 : int i;
21676 : 161385 : machine_mode mode = VOIDmode;
21677 : :
21678 : 161385 : switch (d->vmode)
21679 : : {
21680 : : case E_V8QImode: mode = V4HImode; break;
21681 : 29230 : case E_V16QImode: mode = V8HImode; break;
21682 : 1408 : case E_V32QImode: mode = V16HImode; break;
21683 : 307 : case E_V64QImode: mode = V32HImode; break;
21684 : 11625 : case E_V4HImode: mode = V2SImode; break;
21685 : 20093 : case E_V8HImode: mode = V4SImode; break;
21686 : 994 : case E_V16HImode: mode = V8SImode; break;
21687 : 397 : case E_V32HImode: mode = V16SImode; break;
21688 : 43380 : case E_V4SImode: mode = V2DImode; break;
21689 : 1487 : case E_V8SImode: mode = V4DImode; break;
21690 : 61 : case E_V16SImode: mode = V8DImode; break;
21691 : : default: return false;
21692 : : }
21693 : 202568 : for (i = 0; i < d->nelt; i += 2)
21694 : 188572 : if ((d->perm[i] & 1) || d->perm[i + 1] != d->perm[i] + 1)
21695 : : return false;
21696 : 13996 : nd->vmode = mode;
21697 : 13996 : nd->nelt = d->nelt / 2;
21698 : 91914 : for (i = 0; i < nd->nelt; i++)
21699 : 77918 : nd->perm[i] = d->perm[2 * i] / 2;
21700 : 27992 : if (GET_MODE_INNER (mode) != DImode)
21701 : 12305 : canonicalize_vector_int_perm (nd, nd);
21702 : 13996 : if (nd != d)
21703 : : {
21704 : 8886 : nd->one_operand_p = d->one_operand_p;
21705 : 8886 : nd->testing_p = d->testing_p;
21706 : 8886 : if (d->op0 == d->op1)
21707 : 3001 : nd->op0 = nd->op1 = gen_lowpart (nd->vmode, d->op0);
21708 : : else
21709 : : {
21710 : 5885 : nd->op0 = gen_lowpart (nd->vmode, d->op0);
21711 : 5885 : nd->op1 = gen_lowpart (nd->vmode, d->op1);
21712 : : }
21713 : 8886 : if (d->testing_p)
21714 : 5660 : nd->target = gen_raw_REG (nd->vmode, LAST_VIRTUAL_REGISTER + 1);
21715 : : else
21716 : 3226 : nd->target = gen_reg_rtx (nd->vmode);
21717 : : }
21718 : : return true;
21719 : : }
21720 : :
21721 : : /* Return true if permutation D can be performed as VMODE permutation
21722 : : instead. */
21723 : :
21724 : : static bool
21725 : 7424 : valid_perm_using_mode_p (machine_mode vmode, struct expand_vec_perm_d *d)
21726 : : {
21727 : 7424 : unsigned int i, j, chunk;
21728 : :
21729 : 7424 : if (GET_MODE_CLASS (vmode) != MODE_VECTOR_INT
21730 : 7424 : || GET_MODE_CLASS (d->vmode) != MODE_VECTOR_INT
21731 : 18406 : || GET_MODE_SIZE (vmode) != GET_MODE_SIZE (d->vmode))
21732 : : return false;
21733 : :
21734 : 10982 : if (GET_MODE_NUNITS (vmode) >= d->nelt)
21735 : : return true;
21736 : :
21737 : 5203 : chunk = d->nelt / GET_MODE_NUNITS (vmode);
21738 : 7153 : for (i = 0; i < d->nelt; i += chunk)
21739 : 6906 : if (d->perm[i] & (chunk - 1))
21740 : : return false;
21741 : : else
21742 : 12677 : for (j = 1; j < chunk; ++j)
21743 : 10727 : if (d->perm[i] + j != d->perm[i + j])
21744 : : return false;
21745 : :
21746 : : return true;
21747 : : }
21748 : :
21749 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement D
21750 : : in terms of pshufb, vpperm, vpermq, vpermd, vpermps or vperm2i128. */
21751 : :
21752 : : static bool
21753 : 137511 : expand_vec_perm_pshufb (struct expand_vec_perm_d *d)
21754 : : {
21755 : 137511 : unsigned i, nelt, eltsz, mask;
21756 : 137511 : unsigned char perm[64];
21757 : 137511 : machine_mode vmode;
21758 : 137511 : struct expand_vec_perm_d nd;
21759 : 137511 : rtx rperm[64], vperm, target, op0, op1;
21760 : :
21761 : 137511 : nelt = d->nelt;
21762 : :
21763 : 137511 : if (!d->one_operand_p)
21764 : 224154 : switch (GET_MODE_SIZE (d->vmode))
21765 : : {
21766 : 7307 : case 4:
21767 : 7307 : if (!TARGET_XOP)
21768 : : return false;
21769 : : vmode = V4QImode;
21770 : : break;
21771 : :
21772 : 18072 : case 8:
21773 : 18072 : if (!TARGET_XOP)
21774 : : return false;
21775 : : vmode = V8QImode;
21776 : : break;
21777 : :
21778 : 76235 : case 16:
21779 : 76235 : if (!TARGET_XOP)
21780 : : return false;
21781 : : vmode = V16QImode;
21782 : : break;
21783 : :
21784 : 9478 : case 32:
21785 : 9478 : if (!TARGET_AVX2)
21786 : : return false;
21787 : :
21788 : 4504 : if (valid_perm_using_mode_p (V2TImode, d))
21789 : : {
21790 : 56 : if (d->testing_p)
21791 : : return true;
21792 : :
21793 : : /* Use vperm2i128 insn. The pattern uses
21794 : : V4DImode instead of V2TImode. */
21795 : 52 : target = d->target;
21796 : 52 : if (d->vmode != V4DImode)
21797 : 12 : target = gen_reg_rtx (V4DImode);
21798 : 52 : op0 = gen_lowpart (V4DImode, d->op0);
21799 : 52 : op1 = gen_lowpart (V4DImode, d->op1);
21800 : 52 : rperm[0]
21801 : 52 : = GEN_INT ((d->perm[0] / (nelt / 2))
21802 : : | ((d->perm[nelt / 2] / (nelt / 2)) * 16));
21803 : 52 : emit_insn (gen_avx2_permv2ti (target, op0, op1, rperm[0]));
21804 : 52 : if (target != d->target)
21805 : 12 : emit_move_insn (d->target, gen_lowpart (d->vmode, target));
21806 : 52 : return true;
21807 : : }
21808 : : /* FALLTHRU */
21809 : :
21810 : : default:
21811 : : return false;
21812 : : }
21813 : : else
21814 : 50868 : switch (GET_MODE_SIZE (d->vmode))
21815 : : {
21816 : 3253 : case 4:
21817 : 3253 : if (!TARGET_SSSE3)
21818 : : return false;
21819 : : vmode = V4QImode;
21820 : : break;
21821 : :
21822 : 2404 : case 8:
21823 : 2404 : if (!TARGET_SSSE3)
21824 : : return false;
21825 : : vmode = V8QImode;
21826 : : break;
21827 : :
21828 : 13932 : case 16:
21829 : 13932 : if (!TARGET_SSSE3)
21830 : : return false;
21831 : : vmode = V16QImode;
21832 : : break;
21833 : :
21834 : 5464 : case 32:
21835 : 5464 : if (!TARGET_AVX2)
21836 : : return false;
21837 : :
21838 : : /* V4DImode should be already handled through
21839 : : expand_vselect by vpermq instruction. */
21840 : 2597 : gcc_assert (d->vmode != V4DImode);
21841 : :
21842 : 2597 : vmode = V32QImode;
21843 : 2597 : if (d->vmode == V8SImode
21844 : 2204 : || d->vmode == V16HImode
21845 : 1988 : || d->vmode == V32QImode)
21846 : : {
21847 : : /* First see if vpermq can be used for
21848 : : V8SImode/V16HImode/V32QImode. */
21849 : 1377 : if (valid_perm_using_mode_p (V4DImode, d))
21850 : : {
21851 : 770 : for (i = 0; i < 4; i++)
21852 : 616 : perm[i] = (d->perm[i * nelt / 4] * 4 / nelt) & 3;
21853 : 154 : if (d->testing_p)
21854 : : return true;
21855 : 58 : target = gen_reg_rtx (V4DImode);
21856 : 58 : if (expand_vselect (target, gen_lowpart (V4DImode, d->op0),
21857 : : perm, 4, false))
21858 : : {
21859 : 116 : emit_move_insn (d->target,
21860 : 58 : gen_lowpart (d->vmode, target));
21861 : 58 : return true;
21862 : : }
21863 : : return false;
21864 : : }
21865 : :
21866 : : /* Next see if vpermd can be used. */
21867 : 1223 : if (valid_perm_using_mode_p (V8SImode, d))
21868 : : vmode = V8SImode;
21869 : : }
21870 : : /* Or if vpermps can be used. */
21871 : 1220 : else if (d->vmode == V8SFmode)
21872 : : vmode = V8SImode;
21873 : :
21874 : : if (vmode == V32QImode)
21875 : : {
21876 : : /* vpshufb only works intra lanes, it is not
21877 : : possible to shuffle bytes in between the lanes. */
21878 : 22039 : for (i = 0; i < nelt; ++i)
21879 : 21385 : if ((d->perm[i] ^ i) & (nelt / 2))
21880 : : return false;
21881 : : }
21882 : : break;
21883 : :
21884 : 381 : case 64:
21885 : 381 : if (!TARGET_AVX512BW)
21886 : : return false;
21887 : :
21888 : : /* If vpermq didn't work, vpshufb won't work either. */
21889 : 200 : if (d->vmode == V8DFmode || d->vmode == V8DImode)
21890 : : return false;
21891 : :
21892 : 171 : vmode = V64QImode;
21893 : 171 : if (d->vmode == V16SImode
21894 : 150 : || d->vmode == V32HImode
21895 : 50 : || d->vmode == V64QImode)
21896 : : {
21897 : : /* First see if vpermq can be used for
21898 : : V16SImode/V32HImode/V64QImode. */
21899 : 160 : if (valid_perm_using_mode_p (V8DImode, d))
21900 : : {
21901 : 0 : for (i = 0; i < 8; i++)
21902 : 0 : perm[i] = (d->perm[i * nelt / 8] * 8 / nelt) & 7;
21903 : 0 : if (d->testing_p)
21904 : : return true;
21905 : 0 : target = gen_reg_rtx (V8DImode);
21906 : 0 : if (expand_vselect (target, gen_lowpart (V8DImode, d->op0),
21907 : : perm, 8, false))
21908 : : {
21909 : 0 : emit_move_insn (d->target,
21910 : 0 : gen_lowpart (d->vmode, target));
21911 : 0 : return true;
21912 : : }
21913 : : return false;
21914 : : }
21915 : :
21916 : : /* Next see if vpermd can be used. */
21917 : 160 : if (valid_perm_using_mode_p (V16SImode, d))
21918 : : vmode = V16SImode;
21919 : : }
21920 : : /* Or if vpermps can be used. */
21921 : 11 : else if (d->vmode == V16SFmode)
21922 : : vmode = V16SImode;
21923 : :
21924 : : if (vmode == V64QImode)
21925 : : {
21926 : : /* vpshufb only works intra lanes, it is not
21927 : : possible to shuffle bytes in between the lanes. */
21928 : 578 : for (i = 0; i < nelt; ++i)
21929 : 578 : if ((d->perm[i] ^ i) & (3 * nelt / 4))
21930 : : return false;
21931 : : }
21932 : : break;
21933 : :
21934 : : default:
21935 : : return false;
21936 : : }
21937 : :
21938 : 11983 : if (d->testing_p)
21939 : : return true;
21940 : :
21941 : : /* Try to avoid variable permutation instruction. */
21942 : 9231 : if (canonicalize_vector_int_perm (d, &nd) && expand_vec_perm_1 (&nd))
21943 : : {
21944 : 1839 : emit_move_insn (d->target, gen_lowpart (d->vmode, nd.target));
21945 : 1839 : return true;
21946 : : }
21947 : :
21948 : 7392 : if (vmode == V8SImode)
21949 : 9063 : for (i = 0; i < 8; ++i)
21950 : 8056 : rperm[i] = GEN_INT ((d->perm[i * nelt / 8] * 8 / nelt) & 7);
21951 : 6385 : else if (vmode == V16SImode)
21952 : 544 : for (i = 0; i < 16; ++i)
21953 : 512 : rperm[i] = GEN_INT ((d->perm[i * nelt / 16] * 16 / nelt) & 15);
21954 : : else
21955 : : {
21956 : 6353 : eltsz = GET_MODE_UNIT_SIZE (d->vmode);
21957 : 6353 : if (!d->one_operand_p)
21958 : 3210 : mask = 2 * nelt - 1;
21959 : 3143 : else if (vmode == V64QImode)
21960 : 0 : mask = nelt / 4 - 1;
21961 : 3143 : else if (vmode == V32QImode)
21962 : 648 : mask = nelt / 2 - 1;
21963 : : else
21964 : 2495 : mask = nelt - 1;
21965 : :
21966 : 74305 : for (i = 0; i < nelt; ++i)
21967 : : {
21968 : 67952 : unsigned j, e = d->perm[i] & mask;
21969 : 177872 : for (j = 0; j < eltsz; ++j)
21970 : 109920 : rperm[i * eltsz + j] = GEN_INT (e * eltsz + j);
21971 : : }
21972 : : }
21973 : :
21974 : 7392 : machine_mode vpmode = vmode;
21975 : :
21976 : 7392 : nelt = GET_MODE_SIZE (vmode);
21977 : :
21978 : : /* Emulate narrow modes with V16QI instructions. */
21979 : 7392 : if (nelt < 16)
21980 : : {
21981 : 201 : rtx m128 = GEN_INT (-128);
21982 : :
21983 : : /* Remap elements from the second operand, as we have to
21984 : : account for inactive top elements from the first operand. */
21985 : 201 : if (!d->one_operand_p)
21986 : : {
21987 : 243 : for (i = 0; i < nelt; ++i)
21988 : : {
21989 : 216 : unsigned ival = UINTVAL (rperm[i]);
21990 : 216 : if (ival >= nelt)
21991 : 108 : rperm[i] = GEN_INT (ival + 16 - nelt);
21992 : : }
21993 : : }
21994 : :
21995 : : /* Fill inactive elements in the top positions with zeros. */
21996 : 2297 : for (i = nelt; i < 16; ++i)
21997 : 2096 : rperm[i] = m128;
21998 : :
21999 : : vpmode = V16QImode;
22000 : : }
22001 : :
22002 : 14784 : vperm = gen_rtx_CONST_VECTOR (vpmode,
22003 : 7392 : gen_rtvec_v (GET_MODE_NUNITS (vpmode), rperm));
22004 : 7392 : vperm = force_reg (vpmode, vperm);
22005 : :
22006 : 7392 : if (vmode == d->vmode)
22007 : 2861 : target = d->target;
22008 : : else
22009 : 4531 : target = gen_reg_rtx (vmode);
22010 : :
22011 : 7392 : op0 = gen_lowpart (vmode, d->op0);
22012 : :
22013 : 7392 : if (d->one_operand_p)
22014 : : {
22015 : 4182 : rtx (*gen) (rtx, rtx, rtx);
22016 : :
22017 : 4182 : if (vmode == V4QImode)
22018 : : gen = gen_mmx_pshufbv4qi3;
22019 : : else if (vmode == V8QImode)
22020 : : gen = gen_mmx_pshufbv8qi3;
22021 : : else if (vmode == V16QImode)
22022 : : gen = gen_ssse3_pshufbv16qi3;
22023 : : else if (vmode == V32QImode)
22024 : : gen = gen_avx2_pshufbv32qi3;
22025 : : else if (vmode == V64QImode)
22026 : : gen = gen_avx512bw_pshufbv64qi3;
22027 : : else if (vmode == V8SFmode)
22028 : : gen = gen_avx2_permvarv8sf;
22029 : : else if (vmode == V8SImode)
22030 : : gen = gen_avx2_permvarv8si;
22031 : : else if (vmode == V16SFmode)
22032 : : gen = gen_avx512f_permvarv16sf;
22033 : : else if (vmode == V16SImode)
22034 : : gen = gen_avx512f_permvarv16si;
22035 : : else
22036 : : gcc_unreachable ();
22037 : :
22038 : 4182 : emit_insn (gen (target, op0, vperm));
22039 : : }
22040 : : else
22041 : : {
22042 : 3210 : rtx (*gen) (rtx, rtx, rtx, rtx);
22043 : :
22044 : 3210 : op1 = gen_lowpart (vmode, d->op1);
22045 : :
22046 : 3210 : if (vmode == V4QImode)
22047 : : gen = gen_mmx_ppermv32;
22048 : : else if (vmode == V8QImode)
22049 : : gen = gen_mmx_ppermv64;
22050 : : else if (vmode == V16QImode)
22051 : : gen = gen_xop_pperm;
22052 : : else
22053 : 0 : gcc_unreachable ();
22054 : :
22055 : 3210 : emit_insn (gen (target, op0, op1, vperm));
22056 : : }
22057 : :
22058 : 7392 : if (target != d->target)
22059 : 4531 : emit_move_insn (d->target, gen_lowpart (d->vmode, target));
22060 : :
22061 : : return true;
22062 : : }
22063 : :
22064 : : /* Try to expand one-operand permutation with constant mask. */
22065 : :
22066 : : static bool
22067 : 125198 : ix86_expand_vec_one_operand_perm_avx512 (struct expand_vec_perm_d *d)
22068 : : {
22069 : 125198 : machine_mode mode = GET_MODE (d->op0);
22070 : 125198 : machine_mode maskmode = mode;
22071 : 250396 : unsigned inner_size = GET_MODE_SIZE (GET_MODE_INNER (mode));
22072 : 125198 : rtx (*gen) (rtx, rtx, rtx) = NULL;
22073 : 125198 : rtx target, op0, mask;
22074 : 125198 : rtx vec[64];
22075 : :
22076 : 125198 : if (!rtx_equal_p (d->op0, d->op1))
22077 : : return false;
22078 : :
22079 : 17611 : if (!TARGET_AVX512F)
22080 : : return false;
22081 : :
22082 : : /* Accept VNxHImode and VNxQImode now. */
22083 : 711 : if (!TARGET_AVX512VL && GET_MODE_SIZE (mode) < 64)
22084 : : return false;
22085 : :
22086 : : /* vpermw. */
22087 : 453 : if (!TARGET_AVX512BW && inner_size == 2)
22088 : : return false;
22089 : :
22090 : : /* vpermb. */
22091 : 319 : if (!TARGET_AVX512VBMI && inner_size == 1)
22092 : : return false;
22093 : :
22094 : 198 : switch (mode)
22095 : : {
22096 : : case E_V16SImode:
22097 : : gen = gen_avx512f_permvarv16si;
22098 : : break;
22099 : 4 : case E_V16SFmode:
22100 : 4 : gen = gen_avx512f_permvarv16sf;
22101 : 4 : maskmode = V16SImode;
22102 : 4 : break;
22103 : 0 : case E_V8DImode:
22104 : 0 : gen = gen_avx512f_permvarv8di;
22105 : 0 : break;
22106 : 29 : case E_V8DFmode:
22107 : 29 : gen = gen_avx512f_permvarv8df;
22108 : 29 : maskmode = V8DImode;
22109 : 29 : break;
22110 : 108 : case E_V32HImode:
22111 : 108 : gen = gen_avx512bw_permvarv32hi;
22112 : 108 : break;
22113 : 14 : case E_V16HImode:
22114 : 14 : gen = gen_avx512vl_permvarv16hi;
22115 : 14 : break;
22116 : 6 : case E_V8HImode:
22117 : 6 : gen = gen_avx512vl_permvarv8hi;
22118 : 6 : break;
22119 : 4 : case E_V64QImode:
22120 : 4 : gen = gen_avx512bw_permvarv64qi;
22121 : 4 : break;
22122 : 2 : case E_V32QImode:
22123 : 2 : gen = gen_avx512vl_permvarv32qi;
22124 : 2 : break;
22125 : 0 : case E_V16QImode:
22126 : 0 : gen = gen_avx512vl_permvarv16qi;
22127 : 0 : break;
22128 : :
22129 : : default:
22130 : : return false;
22131 : : }
22132 : :
22133 : 197 : if (d->testing_p)
22134 : : return true;
22135 : :
22136 : 188 : target = d->target;
22137 : 188 : op0 = d->op0;
22138 : 4868 : for (int i = 0; i < d->nelt; ++i)
22139 : 4680 : vec[i] = GEN_INT (d->perm[i]);
22140 : 188 : mask = gen_rtx_CONST_VECTOR (maskmode, gen_rtvec_v (d->nelt, vec));
22141 : 188 : emit_insn (gen (target, op0, force_reg (maskmode, mask)));
22142 : 188 : return true;
22143 : : }
22144 : :
22145 : : static bool expand_vec_perm_palignr (struct expand_vec_perm_d *d, bool);
22146 : :
22147 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to instantiate D
22148 : : in a single instruction. */
22149 : :
22150 : : static bool
22151 : 351071 : expand_vec_perm_1 (struct expand_vec_perm_d *d)
22152 : : {
22153 : 351071 : unsigned i, nelt = d->nelt;
22154 : 351071 : struct expand_vec_perm_d nd;
22155 : :
22156 : : /* Check plain VEC_SELECT first, because AVX has instructions that could
22157 : : match both SEL and SEL+CONCAT, but the plain SEL will allow a memory
22158 : : input where SEL+CONCAT may not. */
22159 : 351071 : if (d->one_operand_p)
22160 : : {
22161 : : int mask = nelt - 1;
22162 : : bool identity_perm = true;
22163 : : bool broadcast_perm = true;
22164 : :
22165 : 523183 : for (i = 0; i < nelt; i++)
22166 : : {
22167 : 460940 : nd.perm[i] = d->perm[i] & mask;
22168 : 460940 : if (nd.perm[i] != i)
22169 : 346349 : identity_perm = false;
22170 : 460940 : if (nd.perm[i])
22171 : 382717 : broadcast_perm = false;
22172 : : }
22173 : :
22174 : 62243 : if (identity_perm)
22175 : : {
22176 : 59 : if (!d->testing_p)
22177 : 5 : emit_move_insn (d->target, d->op0);
22178 : 59 : return true;
22179 : : }
22180 : 62184 : else if (broadcast_perm && TARGET_AVX2)
22181 : : {
22182 : : /* Use vpbroadcast{b,w,d}. */
22183 : 335 : rtx (*gen) (rtx, rtx) = NULL;
22184 : 335 : switch (d->vmode)
22185 : : {
22186 : 1 : case E_V64QImode:
22187 : 1 : if (TARGET_AVX512BW)
22188 : : gen = gen_avx512bw_vec_dupv64qi_1;
22189 : : break;
22190 : 4 : case E_V32QImode:
22191 : 4 : gen = gen_avx2_pbroadcastv32qi_1;
22192 : 4 : break;
22193 : 1 : case E_V32HImode:
22194 : 1 : if (TARGET_AVX512BW)
22195 : : gen = gen_avx512bw_vec_dupv32hi_1;
22196 : : break;
22197 : 4 : case E_V16HImode:
22198 : 4 : gen = gen_avx2_pbroadcastv16hi_1;
22199 : 4 : break;
22200 : 1 : case E_V16SImode:
22201 : 1 : if (TARGET_AVX512F)
22202 : : gen = gen_avx512f_vec_dupv16si_1;
22203 : : break;
22204 : 4 : case E_V8SImode:
22205 : 4 : gen = gen_avx2_pbroadcastv8si_1;
22206 : 4 : break;
22207 : 4 : case E_V16QImode:
22208 : 4 : gen = gen_avx2_pbroadcastv16qi;
22209 : 4 : break;
22210 : 5 : case E_V8HImode:
22211 : 5 : gen = gen_avx2_pbroadcastv8hi;
22212 : 5 : break;
22213 : 0 : case E_V16SFmode:
22214 : 0 : if (TARGET_AVX512F)
22215 : : gen = gen_avx512f_vec_dupv16sf_1;
22216 : : break;
22217 : : case E_V8SFmode:
22218 : : gen = gen_avx2_vec_dupv8sf_1;
22219 : : break;
22220 : 0 : case E_V8DFmode:
22221 : 0 : if (TARGET_AVX512F)
22222 : : gen = gen_avx512f_vec_dupv8df_1;
22223 : : break;
22224 : 0 : case E_V8DImode:
22225 : 0 : if (TARGET_AVX512F)
22226 : : gen = gen_avx512f_vec_dupv8di_1;
22227 : : break;
22228 : : /* For other modes prefer other shuffles this function creates. */
22229 : : default: break;
22230 : : }
22231 : 21 : if (gen != NULL)
22232 : : {
22233 : 24 : if (!d->testing_p)
22234 : 24 : emit_insn (gen (d->target, d->op0));
22235 : 24 : return true;
22236 : : }
22237 : : }
22238 : :
22239 : 62160 : if (expand_vselect (d->target, d->op0, nd.perm, nelt, d->testing_p))
22240 : : return true;
22241 : :
22242 : : /* There are plenty of patterns in sse.md that are written for
22243 : : SEL+CONCAT and are not replicated for a single op. Perhaps
22244 : : that should be changed, to avoid the nastiness here. */
22245 : :
22246 : : /* Recognize interleave style patterns, which means incrementing
22247 : : every other permutation operand. */
22248 : 209346 : for (i = 0; i < nelt; i += 2)
22249 : : {
22250 : 172297 : nd.perm[i] = d->perm[i] & mask;
22251 : 172297 : nd.perm[i + 1] = (d->perm[i + 1] & mask) + nelt;
22252 : : }
22253 : 37049 : if (expand_vselect_vconcat (d->target, d->op0, d->op0, nd.perm, nelt,
22254 : 37049 : d->testing_p))
22255 : : return true;
22256 : :
22257 : : /* Recognize shufps, which means adding {0, 0, nelt, nelt}. */
22258 : 32138 : if (nelt >= 4)
22259 : : {
22260 : 112485 : for (i = 0; i < nelt; i += 4)
22261 : : {
22262 : 80347 : nd.perm[i + 0] = d->perm[i + 0] & mask;
22263 : 80347 : nd.perm[i + 1] = d->perm[i + 1] & mask;
22264 : 80347 : nd.perm[i + 2] = (d->perm[i + 2] & mask) + nelt;
22265 : 80347 : nd.perm[i + 3] = (d->perm[i + 3] & mask) + nelt;
22266 : : }
22267 : :
22268 : 32138 : if (expand_vselect_vconcat (d->target, d->op0, d->op0, nd.perm, nelt,
22269 : 32138 : d->testing_p))
22270 : : return true;
22271 : : }
22272 : : }
22273 : :
22274 : : /* Try the SSE4.1 blend variable merge instructions. */
22275 : 315308 : if (expand_vec_perm_blend (d))
22276 : : return true;
22277 : :
22278 : : /* Try movss/movsd instructions. */
22279 : 313786 : if (expand_vec_perm_movs (d))
22280 : : return true;
22281 : :
22282 : : /* Try the SSE4.1 insertps instruction. */
22283 : 279751 : if (expand_vec_perm_insertps (d))
22284 : : return true;
22285 : :
22286 : : /* Try the fully general two operand permute. */
22287 : 275565 : if (expand_vselect_vconcat (d->target, d->op0, d->op1, d->perm, nelt,
22288 : 275565 : d->testing_p))
22289 : : return true;
22290 : :
22291 : : /* Recognize interleave style patterns with reversed operands. */
22292 : 138462 : if (!d->one_operand_p)
22293 : : {
22294 : 903754 : for (i = 0; i < nelt; ++i)
22295 : : {
22296 : 791664 : unsigned e = d->perm[i];
22297 : 791664 : if (e >= nelt)
22298 : 387926 : e -= nelt;
22299 : : else
22300 : 403738 : e += nelt;
22301 : 791664 : nd.perm[i] = e;
22302 : : }
22303 : :
22304 : 112090 : if (expand_vselect_vconcat (d->target, d->op1, d->op0, nd.perm, nelt,
22305 : 112090 : d->testing_p))
22306 : : return true;
22307 : : }
22308 : :
22309 : : /* Try one of the AVX vpermil variable permutations. */
22310 : 138449 : if (expand_vec_perm_vpermil (d))
22311 : : return true;
22312 : :
22313 : : /* Try the SSSE3 pshufb or XOP vpperm or AVX2 vperm2i128,
22314 : : vpshufb, vpermd, vpermps or vpermq variable permutation. */
22315 : 137511 : if (expand_vec_perm_pshufb (d))
22316 : : return true;
22317 : :
22318 : : /* Try the AVX2 vpalignr instruction. */
22319 : 125318 : if (expand_vec_perm_palignr (d, true))
22320 : : return true;
22321 : :
22322 : : /* Try the AVX512F vperm{w,b,s,d} instructions */
22323 : 125198 : if (ix86_expand_vec_one_operand_perm_avx512 (d))
22324 : : return true;
22325 : :
22326 : : /* Try the AVX512F vpermt2/vpermi2 instructions. */
22327 : 125001 : if (ix86_expand_vec_perm_vpermt2 (NULL_RTX, NULL_RTX, NULL_RTX, NULL_RTX, d))
22328 : : return true;
22329 : :
22330 : : /* See if we can get the same permutation in different vector integer
22331 : : mode. */
22332 : 124077 : if (canonicalize_vector_int_perm (d, &nd) && expand_vec_perm_1 (&nd))
22333 : : {
22334 : 6511 : if (!d->testing_p)
22335 : 1180 : emit_move_insn (d->target, gen_lowpart (d->vmode, nd.target));
22336 : 6511 : return true;
22337 : : }
22338 : : return false;
22339 : : }
22340 : :
22341 : : /* Canonicalize vec_perm index to make the first index
22342 : : always comes from the first vector. */
22343 : : static void
22344 : 8158 : ix86_vec_perm_index_canon (struct expand_vec_perm_d *d)
22345 : : {
22346 : 8158 : unsigned nelt = d->nelt;
22347 : 8158 : if (d->perm[0] < nelt)
22348 : : return;
22349 : :
22350 : 5 : for (unsigned i = 0; i != nelt; i++)
22351 : 4 : d->perm[i] = (d->perm[i] + nelt) % (2 * nelt);
22352 : :
22353 : 1 : std::swap (d->op0, d->op1);
22354 : 1 : return;
22355 : : }
22356 : :
22357 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement D
22358 : : in terms of a pair of shufps+ shufps/pshufd instructions. */
22359 : : static bool
22360 : 85338 : expand_vec_perm_shufps_shufps (struct expand_vec_perm_d *d)
22361 : : {
22362 : 85338 : unsigned char perm1[4];
22363 : 85338 : machine_mode vmode = d->vmode;
22364 : 85338 : bool ok;
22365 : 85338 : unsigned i, j, k, count = 0;
22366 : :
22367 : 85338 : if (d->one_operand_p
22368 : 80121 : || (vmode != V4SImode && vmode != V4SFmode))
22369 : : return false;
22370 : :
22371 : 37710 : if (d->testing_p)
22372 : : return true;
22373 : :
22374 : 8158 : ix86_vec_perm_index_canon (d);
22375 : 48948 : for (i = 0; i < 4; ++i)
22376 : 51073 : count += d->perm[i] > 3 ? 1 : 0;
22377 : :
22378 : 8158 : gcc_assert (count & 3);
22379 : :
22380 : 8158 : rtx tmp = gen_reg_rtx (vmode);
22381 : : /* 2 from op0 and 2 from op1. */
22382 : 8158 : if (count == 2)
22383 : : {
22384 : : unsigned char perm2[4];
22385 : 18135 : for (i = 0, j = 0, k = 2; i < 4; ++i)
22386 : 14508 : if (d->perm[i] & 4)
22387 : : {
22388 : 7254 : perm1[k++] = d->perm[i];
22389 : 7254 : perm2[i] = k - 1;
22390 : : }
22391 : : else
22392 : : {
22393 : 7254 : perm1[j++] = d->perm[i];
22394 : 7254 : perm2[i] = j - 1;
22395 : : }
22396 : :
22397 : : /* shufps. */
22398 : 7254 : ok = expand_vselect_vconcat (tmp, d->op0, d->op1,
22399 : 3627 : perm1, d->nelt, false);
22400 : 3627 : gcc_assert (ok);
22401 : 3627 : if (vmode == V4SImode && TARGET_SSE2)
22402 : : /* pshufd. */
22403 : 2066 : ok = expand_vselect (d->target, tmp,
22404 : 2066 : perm2, d->nelt, false);
22405 : : else
22406 : : {
22407 : : /* shufps. */
22408 : 1561 : perm2[2] += 4;
22409 : 1561 : perm2[3] += 4;
22410 : 1561 : ok = expand_vselect_vconcat (d->target, tmp, tmp,
22411 : 1561 : perm2, d->nelt, false);
22412 : : }
22413 : 3627 : gcc_assert (ok);
22414 : : }
22415 : : /* 3 from one op and 1 from another. */
22416 : : else
22417 : : {
22418 : 22655 : unsigned pair_idx = 8, lone_idx = 8, shift;
22419 : :
22420 : : /* Find the lone index. */
22421 : 22655 : for (i = 0; i < 4; ++i)
22422 : 18124 : if ((d->perm[i] > 3 && count == 1)
22423 : 14796 : || (d->perm[i] < 4 && count == 3))
22424 : 18124 : lone_idx = i;
22425 : :
22426 : : /* When lone_idx is not 0, it must from second op(count == 1). */
22427 : 5734 : gcc_assert (count == (lone_idx ? 1 : 3));
22428 : :
22429 : : /* Find the pair index that sits in the same half as the lone index. */
22430 : 4531 : shift = lone_idx & 2;
22431 : 4531 : pair_idx = 1 - lone_idx + 2 * shift;
22432 : :
22433 : : /* First permutate lone index and pair index into the same vector as
22434 : : [ lone, lone, pair, pair ]. */
22435 : 9062 : perm1[1] = perm1[0]
22436 : 4531 : = (count == 3) ? d->perm[lone_idx] : d->perm[lone_idx] - 4;
22437 : 9062 : perm1[3] = perm1[2]
22438 : 4531 : = (count == 3) ? d->perm[pair_idx] : d->perm[pair_idx] + 4;
22439 : :
22440 : : /* Alway put the vector contains lone indx at the first. */
22441 : 4531 : if (count == 1)
22442 : 3328 : std::swap (d->op0, d->op1);
22443 : :
22444 : : /* shufps. */
22445 : 9062 : ok = expand_vselect_vconcat (tmp, d->op0, d->op1,
22446 : 4531 : perm1, d->nelt, false);
22447 : 4531 : gcc_assert (ok);
22448 : :
22449 : : /* Refine lone and pair index to original order. */
22450 : 4531 : perm1[shift] = lone_idx << 1;
22451 : 4531 : perm1[shift + 1] = pair_idx << 1;
22452 : :
22453 : : /* Select the remaining 2 elements in another vector. */
22454 : 13593 : for (i = 2 - shift; i < 4 - shift; ++i)
22455 : 9062 : perm1[i] = lone_idx == 1 ? d->perm[i] + 4 : d->perm[i];
22456 : :
22457 : : /* Adjust to original selector. */
22458 : 4531 : if (lone_idx > 1)
22459 : 2243 : std::swap (tmp, d->op1);
22460 : :
22461 : : /* shufps. */
22462 : 9062 : ok = expand_vselect_vconcat (d->target, tmp, d->op1,
22463 : 4531 : perm1, d->nelt, false);
22464 : :
22465 : 4531 : gcc_assert (ok);
22466 : : }
22467 : :
22468 : : return true;
22469 : : }
22470 : :
22471 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement D
22472 : : in terms of a pair of pshuflw + pshufhw instructions. */
22473 : :
22474 : : static bool
22475 : 102482 : expand_vec_perm_pshuflw_pshufhw (struct expand_vec_perm_d *d)
22476 : : {
22477 : 102482 : unsigned char perm2[MAX_VECT_LEN];
22478 : 102482 : unsigned i;
22479 : 102482 : bool ok;
22480 : :
22481 : 102482 : if (d->vmode != V8HImode || !d->one_operand_p)
22482 : : return false;
22483 : :
22484 : : /* The two permutations only operate in 64-bit lanes. */
22485 : 12835 : for (i = 0; i < 4; ++i)
22486 : 10358 : if (d->perm[i] >= 4)
22487 : : return false;
22488 : 12329 : for (i = 4; i < 8; ++i)
22489 : 9866 : if (d->perm[i] < 4)
22490 : : return false;
22491 : :
22492 : 2463 : if (d->testing_p)
22493 : : return true;
22494 : :
22495 : : /* Emit the pshuflw. */
22496 : 134 : memcpy (perm2, d->perm, 4);
22497 : 670 : for (i = 4; i < 8; ++i)
22498 : 536 : perm2[i] = i;
22499 : 134 : ok = expand_vselect (d->target, d->op0, perm2, 8, d->testing_p);
22500 : 134 : gcc_assert (ok);
22501 : :
22502 : : /* Emit the pshufhw. */
22503 : 134 : memcpy (perm2 + 4, d->perm + 4, 4);
22504 : 670 : for (i = 0; i < 4; ++i)
22505 : 536 : perm2[i] = i;
22506 : 134 : ok = expand_vselect (d->target, d->target, perm2, 8, d->testing_p);
22507 : 134 : gcc_assert (ok);
22508 : :
22509 : : return true;
22510 : : }
22511 : :
22512 : : /* Try to permute 2 64-bit vectors by punpckldq + 128-bit vector shuffle. */
22513 : : static bool
22514 : 47628 : expand_vec_perm_punpckldq_pshuf (struct expand_vec_perm_d *d)
22515 : : {
22516 : 47628 : if (GET_MODE_BITSIZE (d->vmode) != 64
22517 : 14585 : || !TARGET_MMX_WITH_SSE
22518 : 62213 : || d->one_operand_p)
22519 : : return false;
22520 : :
22521 : 13178 : machine_mode widen_vmode;
22522 : 13178 : switch (d->vmode)
22523 : : {
22524 : : /* pshufd. */
22525 : : case E_V2SImode:
22526 : : widen_vmode = V4SImode;
22527 : : break;
22528 : :
22529 : : /* pshufd. */
22530 : 1087 : case E_V2SFmode:
22531 : 1087 : widen_vmode = V4SFmode;
22532 : 1087 : break;
22533 : :
22534 : 4683 : case E_V4HImode:
22535 : 4683 : widen_vmode = V8HImode;
22536 : : /* pshufb. */
22537 : 4683 : if (!TARGET_SSSE3)
22538 : : return false;
22539 : : break;
22540 : :
22541 : 5512 : case E_V8QImode:
22542 : : /* pshufb. */
22543 : 5512 : widen_vmode = V16QImode;
22544 : 5512 : if (!TARGET_SSSE3)
22545 : : return false;
22546 : : break;
22547 : :
22548 : : default:
22549 : : return false;
22550 : : }
22551 : :
22552 : 4725 : if (d->testing_p)
22553 : : return true;
22554 : :
22555 : 244 : struct expand_vec_perm_d dperm;
22556 : 244 : dperm.target = gen_reg_rtx (widen_vmode);
22557 : 244 : rtx op0 = gen_reg_rtx (widen_vmode);
22558 : 244 : emit_move_insn (op0, gen_rtx_VEC_CONCAT (widen_vmode, d->op0, d->op1));
22559 : 244 : dperm.op0 = op0;
22560 : 244 : dperm.op1 = op0;
22561 : 244 : dperm.vmode = widen_vmode;
22562 : 244 : unsigned nelt = GET_MODE_NUNITS (widen_vmode);
22563 : 244 : dperm.nelt = nelt;
22564 : 244 : dperm.one_operand_p = true;
22565 : 244 : dperm.testing_p = false;
22566 : :
22567 : 1604 : for (unsigned i = 0; i != nelt / 2; i++)
22568 : : {
22569 : 1360 : dperm.perm[i] = d->perm[i];
22570 : 1360 : dperm.perm[i + nelt / 2] = d->perm[i];
22571 : : }
22572 : :
22573 : 244 : gcc_assert (expand_vec_perm_1 (&dperm));
22574 : 244 : emit_move_insn (d->target, lowpart_subreg (d->vmode,
22575 : : dperm.target,
22576 : : dperm.vmode));
22577 : 244 : return true;
22578 : : }
22579 : :
22580 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to simplify
22581 : : the permutation using the SSSE3 palignr instruction. This succeeds
22582 : : when all of the elements in PERM fit within one vector and we merely
22583 : : need to shift them down so that a single vector permutation has a
22584 : : chance to succeed. If SINGLE_INSN_ONLY_P, succeed if only
22585 : : the vpalignr instruction itself can perform the requested permutation. */
22586 : :
22587 : : static bool
22588 : 225337 : expand_vec_perm_palignr (struct expand_vec_perm_d *d, bool single_insn_only_p)
22589 : : {
22590 : 225337 : unsigned i, nelt = d->nelt;
22591 : 225337 : unsigned min, max, minswap, maxswap;
22592 : 225337 : bool in_order, ok, swap = false;
22593 : 225337 : rtx shift, target;
22594 : 225337 : struct expand_vec_perm_d dcopy;
22595 : :
22596 : : /* Even with AVX, palignr only operates on 128-bit vectors,
22597 : : in AVX2 palignr operates on both 128-bit lanes. */
22598 : 118002 : if ((!TARGET_SSSE3 || GET_MODE_SIZE (d->vmode) != 16)
22599 : 268433 : && (!TARGET_AVX2 || GET_MODE_SIZE (d->vmode) != 32))
22600 : : return false;
22601 : :
22602 : 35236 : min = 2 * nelt;
22603 : 35236 : max = 0;
22604 : 35236 : minswap = 2 * nelt;
22605 : 35236 : maxswap = 0;
22606 : 256960 : for (i = 0; i < nelt; ++i)
22607 : : {
22608 : 221724 : unsigned e = d->perm[i];
22609 : 221724 : unsigned eswap = d->perm[i] ^ nelt;
22610 : 443448 : if (GET_MODE_SIZE (d->vmode) == 32)
22611 : : {
22612 : 87472 : e = (e & ((nelt / 2) - 1)) | ((e & nelt) >> 1);
22613 : 87472 : eswap = e ^ (nelt / 2);
22614 : : }
22615 : 221724 : if (e < min)
22616 : : min = e;
22617 : 221724 : if (e > max)
22618 : : max = e;
22619 : 221724 : if (eswap < minswap)
22620 : : minswap = eswap;
22621 : 221724 : if (eswap > maxswap)
22622 : : maxswap = eswap;
22623 : : }
22624 : 35236 : if (min == 0
22625 : 51134 : || max - min >= (GET_MODE_SIZE (d->vmode) == 32 ? nelt / 2 : nelt))
22626 : : {
22627 : 32040 : if (d->one_operand_p
22628 : 31774 : || minswap == 0
22629 : 67900 : || maxswap - minswap >= (GET_MODE_SIZE (d->vmode) == 32
22630 : 17930 : ? nelt / 2 : nelt))
22631 : : return false;
22632 : : swap = true;
22633 : : min = minswap;
22634 : 6416 : max = maxswap;
22635 : : }
22636 : :
22637 : : /* Given that we have SSSE3, we know we'll be able to implement the
22638 : : single operand permutation after the palignr with pshufb for
22639 : : 128-bit vectors. If SINGLE_INSN_ONLY_P, in_order has to be computed
22640 : : first. */
22641 : 6466 : if (d->testing_p && GET_MODE_SIZE (d->vmode) == 16 && !single_insn_only_p)
22642 : : return true;
22643 : :
22644 : 6416 : dcopy = *d;
22645 : 6416 : if (swap)
22646 : : {
22647 : 3220 : dcopy.op0 = d->op1;
22648 : 3220 : dcopy.op1 = d->op0;
22649 : 16172 : for (i = 0; i < nelt; ++i)
22650 : 12952 : dcopy.perm[i] ^= nelt;
22651 : : }
22652 : :
22653 : : in_order = true;
22654 : 32632 : for (i = 0; i < nelt; ++i)
22655 : : {
22656 : 26216 : unsigned e = dcopy.perm[i];
22657 : 26216 : if (GET_MODE_SIZE (d->vmode) == 32
22658 : 1120 : && e >= nelt
22659 : 26466 : && (e & (nelt / 2 - 1)) < min)
22660 : 250 : e = e - min - (nelt / 2);
22661 : : else
22662 : 25966 : e = e - min;
22663 : 26216 : if (e != i)
22664 : 19394 : in_order = false;
22665 : 26216 : dcopy.perm[i] = e;
22666 : : }
22667 : 6416 : dcopy.one_operand_p = true;
22668 : :
22669 : 6416 : if (single_insn_only_p && !in_order)
22670 : : return false;
22671 : :
22672 : : /* For AVX2, test whether we can permute the result in one instruction. */
22673 : 3267 : if (d->testing_p)
22674 : : {
22675 : 50 : if (in_order)
22676 : : return true;
22677 : 0 : dcopy.op1 = dcopy.op0;
22678 : 0 : return expand_vec_perm_1 (&dcopy);
22679 : : }
22680 : :
22681 : 6434 : shift = GEN_INT (min * GET_MODE_UNIT_BITSIZE (d->vmode));
22682 : 6434 : if (GET_MODE_SIZE (d->vmode) == 16)
22683 : : {
22684 : 3145 : target = gen_reg_rtx (V1TImode);
22685 : 3145 : emit_insn (gen_ssse3_palignrv1ti (target,
22686 : 3145 : gen_lowpart (V1TImode, dcopy.op1),
22687 : 3145 : gen_lowpart (V1TImode, dcopy.op0),
22688 : : shift));
22689 : : }
22690 : : else
22691 : : {
22692 : 72 : target = gen_reg_rtx (V2TImode);
22693 : 72 : emit_insn (gen_avx2_palignrv2ti (target,
22694 : 72 : gen_lowpart (V2TImode, dcopy.op1),
22695 : 72 : gen_lowpart (V2TImode, dcopy.op0),
22696 : : shift));
22697 : : }
22698 : :
22699 : 3217 : dcopy.op0 = dcopy.op1 = gen_lowpart (d->vmode, target);
22700 : :
22701 : : /* Test for the degenerate case where the alignment by itself
22702 : : produces the desired permutation. */
22703 : 3217 : if (in_order)
22704 : : {
22705 : 70 : emit_move_insn (d->target, dcopy.op0);
22706 : 70 : return true;
22707 : : }
22708 : :
22709 : 3147 : ok = expand_vec_perm_1 (&dcopy);
22710 : 3159 : gcc_assert (ok || GET_MODE_SIZE (d->vmode) == 32);
22711 : :
22712 : : return ok;
22713 : : }
22714 : :
22715 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to simplify
22716 : : the permutation using the SSE4_1 pblendv instruction. Potentially
22717 : : reduces permutation from 2 pshufb and or to 1 pshufb and pblendv. */
22718 : :
22719 : : static bool
22720 : 90447 : expand_vec_perm_pblendv (struct expand_vec_perm_d *d)
22721 : : {
22722 : 90447 : unsigned i, which, nelt = d->nelt;
22723 : 90447 : struct expand_vec_perm_d dcopy, dcopy1;
22724 : 90447 : machine_mode vmode = d->vmode;
22725 : 90447 : bool ok;
22726 : :
22727 : : /* Use the same checks as in expand_vec_perm_blend. */
22728 : 90447 : if (d->one_operand_p)
22729 : : return false;
22730 : 89215 : if (TARGET_AVX2 && GET_MODE_SIZE (vmode) == 32)
22731 : : ;
22732 : 83099 : else if (TARGET_AVX && (vmode == V4DFmode || vmode == V8SFmode))
22733 : : ;
22734 : 79324 : else if (TARGET_SSE4_1
22735 : 88963 : && (GET_MODE_SIZE (vmode) == 16
22736 : 7420 : || (TARGET_MMX_WITH_SSE && GET_MODE_SIZE (vmode) == 8)
22737 : 2081 : || GET_MODE_SIZE (vmode) == 4))
22738 : : ;
22739 : : else
22740 : : return false;
22741 : :
22742 : : /* Figure out where permutation elements stay not in their
22743 : : respective lanes. */
22744 : 115914 : for (i = 0, which = 0; i < nelt; ++i)
22745 : : {
22746 : 100736 : unsigned e = d->perm[i];
22747 : 100736 : if (e != i)
22748 : 137797 : which |= (e < nelt ? 1 : 2);
22749 : : }
22750 : : /* We can pblend the part where elements stay not in their
22751 : : respective lanes only when these elements are all in one
22752 : : half of a permutation.
22753 : : {0 1 8 3 4 5 9 7} is ok as 8, 9 are at not at their respective
22754 : : lanes, but both 8 and 9 >= 8
22755 : : {0 1 8 3 4 5 2 7} is not ok as 2 and 8 are not at their
22756 : : respective lanes and 8 >= 8, but 2 not. */
22757 : 15178 : if (which != 1 && which != 2)
22758 : : return false;
22759 : 3256 : if (d->testing_p && GET_MODE_SIZE (vmode) == 16)
22760 : : return true;
22761 : :
22762 : : /* First we apply one operand permutation to the part where
22763 : : elements stay not in their respective lanes. */
22764 : 1994 : dcopy = *d;
22765 : 1994 : if (which == 2)
22766 : 1994 : dcopy.op0 = dcopy.op1 = d->op1;
22767 : : else
22768 : 0 : dcopy.op0 = dcopy.op1 = d->op0;
22769 : 1994 : if (!d->testing_p)
22770 : 732 : dcopy.target = gen_reg_rtx (vmode);
22771 : 1994 : dcopy.one_operand_p = true;
22772 : :
22773 : 16318 : for (i = 0; i < nelt; ++i)
22774 : 14324 : dcopy.perm[i] = d->perm[i] & (nelt - 1);
22775 : :
22776 : 1994 : ok = expand_vec_perm_1 (&dcopy);
22777 : 3988 : if (GET_MODE_SIZE (vmode) != 16 && !ok)
22778 : : return false;
22779 : : else
22780 : 1699 : gcc_assert (ok);
22781 : 1699 : if (d->testing_p)
22782 : : return true;
22783 : :
22784 : : /* Next we put permuted elements into their positions. */
22785 : 670 : dcopy1 = *d;
22786 : 670 : if (which == 2)
22787 : 670 : dcopy1.op1 = dcopy.target;
22788 : : else
22789 : 0 : dcopy1.op0 = dcopy.target;
22790 : :
22791 : 5706 : for (i = 0; i < nelt; ++i)
22792 : 5036 : dcopy1.perm[i] = ((d->perm[i] >= nelt) ? (nelt + i) : i);
22793 : :
22794 : 670 : ok = expand_vec_perm_blend (&dcopy1);
22795 : 670 : gcc_assert (ok);
22796 : :
22797 : : return true;
22798 : : }
22799 : :
22800 : : static bool expand_vec_perm_interleave3 (struct expand_vec_perm_d *d);
22801 : :
22802 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to simplify
22803 : : a two vector permutation into a single vector permutation by using
22804 : : an interleave operation to merge the vectors. */
22805 : :
22806 : : static bool
22807 : 96884 : expand_vec_perm_interleave2 (struct expand_vec_perm_d *d)
22808 : : {
22809 : 96884 : struct expand_vec_perm_d dremap, dfinal;
22810 : 96884 : unsigned i, nelt = d->nelt, nelt2 = nelt / 2;
22811 : 96884 : unsigned HOST_WIDE_INT contents;
22812 : 96884 : unsigned char remap[2 * MAX_VECT_LEN];
22813 : 96884 : rtx_insn *seq;
22814 : 96884 : bool ok, same_halves = false;
22815 : :
22816 : 96884 : if (GET_MODE_SIZE (d->vmode) == 4
22817 : 175986 : || GET_MODE_SIZE (d->vmode) == 8
22818 : 239980 : || GET_MODE_SIZE (d->vmode) == 16)
22819 : : {
22820 : 89615 : if (d->one_operand_p)
22821 : : return false;
22822 : : }
22823 : 14538 : else if (GET_MODE_SIZE (d->vmode) == 32)
22824 : : {
22825 : 6925 : if (!TARGET_AVX)
22826 : : return false;
22827 : : /* For 32-byte modes allow even d->one_operand_p.
22828 : : The lack of cross-lane shuffling in some instructions
22829 : : might prevent a single insn shuffle. */
22830 : 6925 : dfinal = *d;
22831 : 6925 : dfinal.testing_p = true;
22832 : : /* If expand_vec_perm_interleave3 can expand this into
22833 : : a 3 insn sequence, give up and let it be expanded as
22834 : : 3 insn sequence. While that is one insn longer,
22835 : : it doesn't need a memory operand and in the common
22836 : : case that both interleave low and high permutations
22837 : : with the same operands are adjacent needs 4 insns
22838 : : for both after CSE. */
22839 : 6925 : if (expand_vec_perm_interleave3 (&dfinal))
22840 : : return false;
22841 : : }
22842 : : else
22843 : : return false;
22844 : :
22845 : : /* Examine from whence the elements come. */
22846 : 91184 : contents = 0;
22847 : 687802 : for (i = 0; i < nelt; ++i)
22848 : 596618 : contents |= HOST_WIDE_INT_1U << d->perm[i];
22849 : :
22850 : 91184 : memset (remap, 0xff, sizeof (remap));
22851 : 91184 : dremap = *d;
22852 : :
22853 : 91184 : if (GET_MODE_SIZE (d->vmode) == 4
22854 : 175114 : || GET_MODE_SIZE (d->vmode) == 8)
22855 : : {
22856 : 22288 : unsigned HOST_WIDE_INT h1, h2, h3, h4;
22857 : :
22858 : : /* Split the two input vectors into 4 halves. */
22859 : 22288 : h1 = (HOST_WIDE_INT_1U << nelt2) - 1;
22860 : 22288 : h2 = h1 << nelt2;
22861 : 22288 : h3 = h2 << nelt2;
22862 : 22288 : h4 = h3 << nelt2;
22863 : :
22864 : : /* If the elements from the low halves use interleave low,
22865 : : and similarly for interleave high. */
22866 : 22288 : if ((contents & (h1 | h3)) == contents)
22867 : : {
22868 : : /* punpckl* */
22869 : 3211 : for (i = 0; i < nelt2; ++i)
22870 : : {
22871 : 2268 : remap[i] = i * 2;
22872 : 2268 : remap[i + nelt] = i * 2 + 1;
22873 : 2268 : dremap.perm[i * 2] = i;
22874 : 2268 : dremap.perm[i * 2 + 1] = i + nelt;
22875 : : }
22876 : : }
22877 : 21345 : else if ((contents & (h2 | h4)) == contents)
22878 : : {
22879 : : /* punpckh* */
22880 : 2836 : for (i = 0; i < nelt2; ++i)
22881 : : {
22882 : 2000 : remap[i + nelt2] = i * 2;
22883 : 2000 : remap[i + nelt + nelt2] = i * 2 + 1;
22884 : 2000 : dremap.perm[i * 2] = i + nelt2;
22885 : 2000 : dremap.perm[i * 2 + 1] = i + nelt + nelt2;
22886 : : }
22887 : : }
22888 : : else
22889 : : return false;
22890 : : }
22891 : 137792 : else if (GET_MODE_SIZE (d->vmode) == 16)
22892 : : {
22893 : 62189 : unsigned HOST_WIDE_INT h1, h2, h3, h4;
22894 : :
22895 : : /* Split the two input vectors into 4 halves. */
22896 : 62189 : h1 = (HOST_WIDE_INT_1U << nelt2) - 1;
22897 : 62189 : h2 = h1 << nelt2;
22898 : 62189 : h3 = h2 << nelt2;
22899 : 62189 : h4 = h3 << nelt2;
22900 : :
22901 : : /* If the elements from the low halves use interleave low, and similarly
22902 : : for interleave high. If the elements are from mis-matched halves, we
22903 : : can use shufps for V4SF/V4SI or do a DImode shuffle. */
22904 : 62189 : if ((contents & (h1 | h3)) == contents)
22905 : : {
22906 : : /* punpckl* */
22907 : 5902 : for (i = 0; i < nelt2; ++i)
22908 : : {
22909 : 4368 : remap[i] = i * 2;
22910 : 4368 : remap[i + nelt] = i * 2 + 1;
22911 : 4368 : dremap.perm[i * 2] = i;
22912 : 4368 : dremap.perm[i * 2 + 1] = i + nelt;
22913 : : }
22914 : 1534 : if (!TARGET_SSE2 && d->vmode == V4SImode)
22915 : 0 : dremap.vmode = V4SFmode;
22916 : : }
22917 : 60655 : else if ((contents & (h2 | h4)) == contents)
22918 : : {
22919 : : /* punpckh* */
22920 : 5106 : for (i = 0; i < nelt2; ++i)
22921 : : {
22922 : 3746 : remap[i + nelt2] = i * 2;
22923 : 3746 : remap[i + nelt + nelt2] = i * 2 + 1;
22924 : 3746 : dremap.perm[i * 2] = i + nelt2;
22925 : 3746 : dremap.perm[i * 2 + 1] = i + nelt + nelt2;
22926 : : }
22927 : 1360 : if (!TARGET_SSE2 && d->vmode == V4SImode)
22928 : 0 : dremap.vmode = V4SFmode;
22929 : : }
22930 : 59295 : else if ((contents & (h1 | h4)) == contents)
22931 : : {
22932 : : /* shufps */
22933 : 2537 : for (i = 0; i < nelt2; ++i)
22934 : : {
22935 : 1828 : remap[i] = i;
22936 : 1828 : remap[i + nelt + nelt2] = i + nelt2;
22937 : 1828 : dremap.perm[i] = i;
22938 : 1828 : dremap.perm[i + nelt2] = i + nelt + nelt2;
22939 : : }
22940 : 709 : if (nelt != 4)
22941 : : {
22942 : : /* shufpd */
22943 : 69 : dremap.vmode = V2DImode;
22944 : 69 : dremap.nelt = 2;
22945 : 69 : dremap.perm[0] = 0;
22946 : 69 : dremap.perm[1] = 3;
22947 : : }
22948 : : }
22949 : 58586 : else if ((contents & (h2 | h3)) == contents)
22950 : : {
22951 : : /* shufps */
22952 : 3423 : for (i = 0; i < nelt2; ++i)
22953 : : {
22954 : 2410 : remap[i + nelt2] = i;
22955 : 2410 : remap[i + nelt] = i + nelt2;
22956 : 2410 : dremap.perm[i] = i + nelt2;
22957 : 2410 : dremap.perm[i + nelt2] = i + nelt;
22958 : : }
22959 : 1013 : if (nelt != 4)
22960 : : {
22961 : : /* shufpd */
22962 : 64 : dremap.vmode = V2DImode;
22963 : 64 : dremap.nelt = 2;
22964 : 64 : dremap.perm[0] = 1;
22965 : 64 : dremap.perm[1] = 2;
22966 : : }
22967 : : }
22968 : : else
22969 : : return false;
22970 : : }
22971 : : else
22972 : : {
22973 : 6707 : unsigned int nelt4 = nelt / 4, nzcnt = 0;
22974 : 6707 : unsigned HOST_WIDE_INT q[8];
22975 : 6707 : unsigned int nonzero_halves[4];
22976 : :
22977 : : /* Split the two input vectors into 8 quarters. */
22978 : 6707 : q[0] = (HOST_WIDE_INT_1U << nelt4) - 1;
22979 : 53656 : for (i = 1; i < 8; ++i)
22980 : 46949 : q[i] = q[0] << (nelt4 * i);
22981 : 33535 : for (i = 0; i < 4; ++i)
22982 : 26828 : if (((q[2 * i] | q[2 * i + 1]) & contents) != 0)
22983 : : {
22984 : 24155 : nonzero_halves[nzcnt] = i;
22985 : 24155 : ++nzcnt;
22986 : : }
22987 : :
22988 : 6707 : if (nzcnt == 1)
22989 : : {
22990 : 225 : gcc_assert (d->one_operand_p);
22991 : 225 : nonzero_halves[1] = nonzero_halves[0];
22992 : 225 : same_halves = true;
22993 : : }
22994 : 6482 : else if (d->one_operand_p)
22995 : : {
22996 : 22 : gcc_assert (nonzero_halves[0] == 0);
22997 : 22 : gcc_assert (nonzero_halves[1] == 1);
22998 : : }
22999 : :
23000 : 6707 : if (nzcnt <= 2)
23001 : : {
23002 : 460 : if (d->perm[0] / nelt2 == nonzero_halves[1])
23003 : : {
23004 : : /* Attempt to increase the likelihood that dfinal
23005 : : shuffle will be intra-lane. */
23006 : 233 : std::swap (nonzero_halves[0], nonzero_halves[1]);
23007 : : }
23008 : :
23009 : : /* vperm2f128 or vperm2i128. */
23010 : 3260 : for (i = 0; i < nelt2; ++i)
23011 : : {
23012 : 2800 : remap[i + nonzero_halves[1] * nelt2] = i + nelt2;
23013 : 2800 : remap[i + nonzero_halves[0] * nelt2] = i;
23014 : 2800 : dremap.perm[i + nelt2] = i + nonzero_halves[1] * nelt2;
23015 : 2800 : dremap.perm[i] = i + nonzero_halves[0] * nelt2;
23016 : : }
23017 : :
23018 : 460 : if (d->vmode != V8SFmode
23019 : : && d->vmode != V4DFmode
23020 : : && d->vmode != V8SImode)
23021 : : {
23022 : 131 : dremap.vmode = V8SImode;
23023 : 131 : dremap.nelt = 8;
23024 : 655 : for (i = 0; i < 4; ++i)
23025 : : {
23026 : 524 : dremap.perm[i] = i + nonzero_halves[0] * 4;
23027 : 524 : dremap.perm[i + 4] = i + nonzero_halves[1] * 4;
23028 : : }
23029 : : }
23030 : : }
23031 : 6247 : else if (d->one_operand_p)
23032 : 5782 : return false;
23033 : 6247 : else if (TARGET_AVX2
23034 : 2552 : && (contents & (q[0] | q[2] | q[4] | q[6])) == contents)
23035 : : {
23036 : : /* vpunpckl* */
23037 : 491 : for (i = 0; i < nelt4; ++i)
23038 : : {
23039 : 247 : remap[i] = i * 2;
23040 : 247 : remap[i + nelt] = i * 2 + 1;
23041 : 247 : remap[i + nelt2] = i * 2 + nelt2;
23042 : 247 : remap[i + nelt + nelt2] = i * 2 + nelt2 + 1;
23043 : 247 : dremap.perm[i * 2] = i;
23044 : 247 : dremap.perm[i * 2 + 1] = i + nelt;
23045 : 247 : dremap.perm[i * 2 + nelt2] = i + nelt2;
23046 : 247 : dremap.perm[i * 2 + nelt2 + 1] = i + nelt + nelt2;
23047 : : }
23048 : : }
23049 : 6003 : else if (TARGET_AVX2
23050 : 2308 : && (contents & (q[1] | q[3] | q[5] | q[7])) == contents)
23051 : : {
23052 : : /* vpunpckh* */
23053 : 445 : for (i = 0; i < nelt4; ++i)
23054 : : {
23055 : 224 : remap[i + nelt4] = i * 2;
23056 : 224 : remap[i + nelt + nelt4] = i * 2 + 1;
23057 : 224 : remap[i + nelt2 + nelt4] = i * 2 + nelt2;
23058 : 224 : remap[i + nelt + nelt2 + nelt4] = i * 2 + nelt2 + 1;
23059 : 224 : dremap.perm[i * 2] = i + nelt4;
23060 : 224 : dremap.perm[i * 2 + 1] = i + nelt + nelt4;
23061 : 224 : dremap.perm[i * 2 + nelt2] = i + nelt2 + nelt4;
23062 : 224 : dremap.perm[i * 2 + nelt2 + 1] = i + nelt + nelt2 + nelt4;
23063 : : }
23064 : : }
23065 : : else
23066 : : return false;
23067 : : }
23068 : :
23069 : : /* Use the remapping array set up above to move the elements from their
23070 : : swizzled locations into their final destinations. */
23071 : 7320 : dfinal = *d;
23072 : 48044 : for (i = 0; i < nelt; ++i)
23073 : : {
23074 : 40724 : unsigned e = remap[d->perm[i]];
23075 : 40724 : gcc_assert (e < nelt);
23076 : : /* If same_halves is true, both halves of the remapped vector are the
23077 : : same. Avoid cross-lane accesses if possible. */
23078 : 40724 : if (same_halves && i >= nelt2)
23079 : : {
23080 : 824 : gcc_assert (e < nelt2);
23081 : 824 : dfinal.perm[i] = e + nelt2;
23082 : : }
23083 : : else
23084 : 39900 : dfinal.perm[i] = e;
23085 : : }
23086 : 7320 : if (!d->testing_p)
23087 : : {
23088 : 2682 : dremap.target = gen_reg_rtx (dremap.vmode);
23089 : 2682 : dfinal.op0 = gen_lowpart (dfinal.vmode, dremap.target);
23090 : : }
23091 : 7320 : dfinal.op1 = dfinal.op0;
23092 : 7320 : dfinal.one_operand_p = true;
23093 : :
23094 : : /* Test if the final remap can be done with a single insn. For V4SFmode or
23095 : : V4SImode this *will* succeed. For V8HImode or V16QImode it may not. */
23096 : 7320 : start_sequence ();
23097 : 7320 : ok = expand_vec_perm_1 (&dfinal);
23098 : 7320 : seq = end_sequence ();
23099 : :
23100 : 7320 : if (!ok)
23101 : : return false;
23102 : :
23103 : 6273 : if (d->testing_p)
23104 : : return true;
23105 : :
23106 : 2644 : if (dremap.vmode != dfinal.vmode)
23107 : : {
23108 : 53 : dremap.op0 = gen_lowpart (dremap.vmode, dremap.op0);
23109 : 53 : dremap.op1 = gen_lowpart (dremap.vmode, dremap.op1);
23110 : : }
23111 : :
23112 : 2644 : ok = expand_vec_perm_1 (&dremap);
23113 : 2644 : gcc_assert (ok);
23114 : :
23115 : 2644 : emit_insn (seq);
23116 : 2644 : return true;
23117 : : }
23118 : :
23119 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to simplify
23120 : : a single vector cross-lane permutation into vpermq followed
23121 : : by any of the single insn permutations. */
23122 : :
23123 : : static bool
23124 : 90511 : expand_vec_perm_vpermq_perm_1 (struct expand_vec_perm_d *d)
23125 : : {
23126 : 90511 : struct expand_vec_perm_d dremap, dfinal;
23127 : 90511 : unsigned i, j, nelt = d->nelt, nelt2 = nelt / 2, nelt4 = nelt / 4;
23128 : 90511 : unsigned contents[2];
23129 : 90511 : bool ok;
23130 : :
23131 : 90511 : if (!(TARGET_AVX2
23132 : 4210 : && (d->vmode == V32QImode || d->vmode == V16HImode)
23133 : 486 : && d->one_operand_p))
23134 : : return false;
23135 : :
23136 : 6 : contents[0] = 0;
23137 : 6 : contents[1] = 0;
23138 : 86 : for (i = 0; i < nelt2; ++i)
23139 : : {
23140 : 80 : contents[0] |= 1u << (d->perm[i] / nelt4);
23141 : 80 : contents[1] |= 1u << (d->perm[i + nelt2] / nelt4);
23142 : : }
23143 : :
23144 : 6 : for (i = 0; i < 2; ++i)
23145 : : {
23146 : : unsigned int cnt = 0;
23147 : 18 : for (j = 0; j < 4; ++j)
23148 : 18 : if ((contents[i] & (1u << j)) != 0 && ++cnt > 2)
23149 : : return false;
23150 : : }
23151 : :
23152 : 0 : if (d->testing_p)
23153 : : return true;
23154 : :
23155 : 0 : dremap = *d;
23156 : 0 : dremap.vmode = V4DImode;
23157 : 0 : dremap.nelt = 4;
23158 : 0 : dremap.target = gen_reg_rtx (V4DImode);
23159 : 0 : dremap.op0 = gen_lowpart (V4DImode, d->op0);
23160 : 0 : dremap.op1 = dremap.op0;
23161 : 0 : dremap.one_operand_p = true;
23162 : 0 : for (i = 0; i < 2; ++i)
23163 : : {
23164 : : unsigned int cnt = 0;
23165 : 0 : for (j = 0; j < 4; ++j)
23166 : 0 : if ((contents[i] & (1u << j)) != 0)
23167 : 0 : dremap.perm[2 * i + cnt++] = j;
23168 : 0 : for (; cnt < 2; ++cnt)
23169 : 0 : dremap.perm[2 * i + cnt] = 0;
23170 : : }
23171 : :
23172 : 0 : dfinal = *d;
23173 : 0 : dfinal.op0 = gen_lowpart (dfinal.vmode, dremap.target);
23174 : 0 : dfinal.op1 = dfinal.op0;
23175 : 0 : dfinal.one_operand_p = true;
23176 : 0 : for (i = 0, j = 0; i < nelt; ++i)
23177 : : {
23178 : 0 : if (i == nelt2)
23179 : 0 : j = 2;
23180 : 0 : dfinal.perm[i] = (d->perm[i] & (nelt4 - 1)) | (j ? nelt2 : 0);
23181 : 0 : if ((d->perm[i] / nelt4) == dremap.perm[j])
23182 : : ;
23183 : 0 : else if ((d->perm[i] / nelt4) == dremap.perm[j + 1])
23184 : 0 : dfinal.perm[i] |= nelt4;
23185 : : else
23186 : 0 : gcc_unreachable ();
23187 : : }
23188 : :
23189 : 0 : ok = expand_vec_perm_1 (&dremap);
23190 : 0 : gcc_assert (ok);
23191 : :
23192 : 0 : ok = expand_vec_perm_1 (&dfinal);
23193 : 0 : gcc_assert (ok);
23194 : :
23195 : : return true;
23196 : : }
23197 : :
23198 : : static bool canonicalize_perm (struct expand_vec_perm_d *d);
23199 : :
23200 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to expand
23201 : : a vector permutation using two instructions, vperm2f128 resp.
23202 : : vperm2i128 followed by any single in-lane permutation. */
23203 : :
23204 : : static bool
23205 : 90511 : expand_vec_perm_vperm2f128 (struct expand_vec_perm_d *d)
23206 : : {
23207 : 90511 : struct expand_vec_perm_d dfirst, dsecond;
23208 : 90511 : unsigned i, j, nelt = d->nelt, nelt2 = nelt / 2, perm;
23209 : 90511 : bool ok;
23210 : :
23211 : 90511 : if (!TARGET_AVX
23212 : 23108 : || GET_MODE_SIZE (d->vmode) != 32
23213 : 96683 : || (d->vmode != V8SFmode && d->vmode != V4DFmode && !TARGET_AVX2))
23214 : : return false;
23215 : :
23216 : 5984 : dsecond = *d;
23217 : 5984 : dsecond.one_operand_p = false;
23218 : 5984 : dsecond.testing_p = true;
23219 : :
23220 : : /* ((perm << 2)|perm) & 0x33 is the vperm2[fi]128
23221 : : immediate. For perm < 16 the second permutation uses
23222 : : d->op0 as first operand, for perm >= 16 it uses d->op1
23223 : : as first operand. The second operand is the result of
23224 : : vperm2[fi]128. */
23225 : 196281 : for (perm = 0; perm < 32; perm++)
23226 : : {
23227 : : /* Ignore permutations which do not move anything cross-lane. */
23228 : 190375 : if (perm < 16)
23229 : : {
23230 : : /* The second shuffle for e.g. V4DFmode has
23231 : : 0123 and ABCD operands.
23232 : : Ignore AB23, as 23 is already in the second lane
23233 : : of the first operand. */
23234 : 95420 : if ((perm & 0xc) == (1 << 2)) continue;
23235 : : /* And 01CD, as 01 is in the first lane of the first
23236 : : operand. */
23237 : 71556 : if ((perm & 3) == 0) continue;
23238 : : /* And 4567, as then the vperm2[fi]128 doesn't change
23239 : : anything on the original 4567 second operand. */
23240 : 53652 : if ((perm & 0xf) == ((3 << 2) | 2)) continue;
23241 : : }
23242 : : else
23243 : : {
23244 : : /* The second shuffle for e.g. V4DFmode has
23245 : : 4567 and ABCD operands.
23246 : : Ignore AB67, as 67 is already in the second lane
23247 : : of the first operand. */
23248 : 94955 : if ((perm & 0xc) == (3 << 2)) continue;
23249 : : /* And 45CD, as 45 is in the first lane of the first
23250 : : operand. */
23251 : 71331 : if ((perm & 3) == 2) continue;
23252 : : /* And 0123, as then the vperm2[fi]128 doesn't change
23253 : : anything on the original 0123 first operand. */
23254 : 53522 : if ((perm & 0xf) == (1 << 2)) continue;
23255 : : }
23256 : :
23257 : 274987 : for (i = 0; i < nelt; i++)
23258 : : {
23259 : 273169 : j = d->perm[i] / nelt2;
23260 : 505683 : if (j == ((perm >> (2 * (i >= nelt2))) & 3))
23261 : 66301 : dsecond.perm[i] = nelt + (i & nelt2) + (d->perm[i] & (nelt2 - 1));
23262 : 346345 : else if (j == (unsigned) (i >= nelt2) + 2 * (perm >= 16))
23263 : 113418 : dsecond.perm[i] = d->perm[i] & (nelt - 1);
23264 : : else
23265 : : break;
23266 : : }
23267 : :
23268 : 95268 : if (i == nelt)
23269 : : {
23270 : 1818 : start_sequence ();
23271 : 1818 : ok = expand_vec_perm_1 (&dsecond);
23272 : 1818 : end_sequence ();
23273 : : }
23274 : : else
23275 : : ok = false;
23276 : :
23277 : 1818 : if (ok)
23278 : : {
23279 : 64 : if (d->testing_p)
23280 : : return true;
23281 : :
23282 : : /* Found a usable second shuffle. dfirst will be
23283 : : vperm2f128 on d->op0 and d->op1. */
23284 : 46 : dsecond.testing_p = false;
23285 : 46 : dfirst = *d;
23286 : 46 : dfirst.target = gen_reg_rtx (d->vmode);
23287 : 270 : for (i = 0; i < nelt; i++)
23288 : 448 : dfirst.perm[i] = (i & (nelt2 - 1))
23289 : 336 : + ((perm >> (2 * (i >= nelt2))) & 3) * nelt2;
23290 : :
23291 : 46 : canonicalize_perm (&dfirst);
23292 : 46 : ok = expand_vec_perm_1 (&dfirst);
23293 : 46 : gcc_assert (ok);
23294 : :
23295 : : /* And dsecond is some single insn shuffle, taking
23296 : : d->op0 and result of vperm2f128 (if perm < 16) or
23297 : : d->op1 and result of vperm2f128 (otherwise). */
23298 : 46 : if (perm >= 16)
23299 : 46 : dsecond.op0 = dsecond.op1;
23300 : 46 : dsecond.op1 = dfirst.target;
23301 : :
23302 : 46 : ok = expand_vec_perm_1 (&dsecond);
23303 : 46 : gcc_assert (ok);
23304 : :
23305 : : return true;
23306 : : }
23307 : :
23308 : : /* For one operand, the only useful vperm2f128 permutation is 0x01
23309 : : aka lanes swap. */
23310 : 95204 : if (d->one_operand_p)
23311 : : return false;
23312 : : }
23313 : :
23314 : : return false;
23315 : : }
23316 : :
23317 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to simplify
23318 : : a two vector permutation using 2 intra-lane interleave insns
23319 : : and cross-lane shuffle for 32-byte vectors. */
23320 : :
23321 : : static bool
23322 : 34064 : expand_vec_perm_interleave3 (struct expand_vec_perm_d *d)
23323 : : {
23324 : 34064 : unsigned i, nelt;
23325 : 34064 : rtx (*gen) (rtx, rtx, rtx);
23326 : :
23327 : 34064 : if (d->one_operand_p)
23328 : : return false;
23329 : 32665 : if (TARGET_AVX2 && GET_MODE_SIZE (d->vmode) == 32)
23330 : : ;
23331 : 24800 : else if (TARGET_AVX && (d->vmode == V8SFmode || d->vmode == V4DFmode))
23332 : : ;
23333 : : else
23334 : : return false;
23335 : :
23336 : 9558 : nelt = d->nelt;
23337 : 9558 : if (d->perm[0] != 0 && d->perm[0] != nelt / 2)
23338 : : return false;
23339 : 9801 : for (i = 0; i < nelt; i += 2)
23340 : 9445 : if (d->perm[i] != d->perm[0] + i / 2
23341 : 8572 : || d->perm[i + 1] != d->perm[0] + i / 2 + nelt)
23342 : : return false;
23343 : :
23344 : 356 : if (d->testing_p)
23345 : : return true;
23346 : :
23347 : 56 : switch (d->vmode)
23348 : : {
23349 : 32 : case E_V32QImode:
23350 : 32 : if (d->perm[0])
23351 : : gen = gen_vec_interleave_highv32qi;
23352 : : else
23353 : 16 : gen = gen_vec_interleave_lowv32qi;
23354 : : break;
23355 : 18 : case E_V16HImode:
23356 : 18 : if (d->perm[0])
23357 : : gen = gen_vec_interleave_highv16hi;
23358 : : else
23359 : 9 : gen = gen_vec_interleave_lowv16hi;
23360 : : break;
23361 : 0 : case E_V8SImode:
23362 : 0 : if (d->perm[0])
23363 : : gen = gen_vec_interleave_highv8si;
23364 : : else
23365 : 0 : gen = gen_vec_interleave_lowv8si;
23366 : : break;
23367 : 4 : case E_V4DImode:
23368 : 4 : if (d->perm[0])
23369 : : gen = gen_vec_interleave_highv4di;
23370 : : else
23371 : 2 : gen = gen_vec_interleave_lowv4di;
23372 : : break;
23373 : 2 : case E_V8SFmode:
23374 : 2 : if (d->perm[0])
23375 : : gen = gen_vec_interleave_highv8sf;
23376 : : else
23377 : 1 : gen = gen_vec_interleave_lowv8sf;
23378 : : break;
23379 : 0 : case E_V4DFmode:
23380 : 0 : if (d->perm[0])
23381 : : gen = gen_vec_interleave_highv4df;
23382 : : else
23383 : 0 : gen = gen_vec_interleave_lowv4df;
23384 : : break;
23385 : 0 : default:
23386 : 0 : gcc_unreachable ();
23387 : : }
23388 : :
23389 : 56 : emit_insn (gen (d->target, d->op0, d->op1));
23390 : 56 : return true;
23391 : : }
23392 : :
23393 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement
23394 : : a single vector permutation using a single intra-lane vector
23395 : : permutation, vperm2f128 swapping the lanes and vblend* insn blending
23396 : : the non-swapped and swapped vectors together. */
23397 : :
23398 : : static bool
23399 : 27001 : expand_vec_perm_vperm2f128_vblend (struct expand_vec_perm_d *d)
23400 : : {
23401 : 27001 : struct expand_vec_perm_d dfirst, dsecond;
23402 : 27001 : unsigned i, j, msk, nelt = d->nelt, nelt2 = nelt / 2;
23403 : 27001 : rtx_insn *seq;
23404 : 27001 : bool ok;
23405 : 27001 : rtx (*blend) (rtx, rtx, rtx, rtx) = NULL;
23406 : :
23407 : 27001 : if (!TARGET_AVX
23408 : 3475 : || TARGET_AVX2
23409 : 2038 : || (d->vmode != V8SFmode && d->vmode != V4DFmode)
23410 : 1850 : || !d->one_operand_p)
23411 : : return false;
23412 : :
23413 : 0 : dfirst = *d;
23414 : 0 : for (i = 0; i < nelt; i++)
23415 : 0 : dfirst.perm[i] = 0xff;
23416 : 0 : for (i = 0, msk = 0; i < nelt; i++)
23417 : : {
23418 : 0 : j = (d->perm[i] & nelt2) ? i | nelt2 : i & ~nelt2;
23419 : 0 : if (dfirst.perm[j] != 0xff && dfirst.perm[j] != d->perm[i])
23420 : : return false;
23421 : 0 : dfirst.perm[j] = d->perm[i];
23422 : 0 : if (j != i)
23423 : 0 : msk |= (1 << i);
23424 : : }
23425 : 0 : for (i = 0; i < nelt; i++)
23426 : 0 : if (dfirst.perm[i] == 0xff)
23427 : 0 : dfirst.perm[i] = i;
23428 : :
23429 : 0 : if (!d->testing_p)
23430 : 0 : dfirst.target = gen_reg_rtx (dfirst.vmode);
23431 : :
23432 : 0 : start_sequence ();
23433 : 0 : ok = expand_vec_perm_1 (&dfirst);
23434 : 0 : seq = end_sequence ();
23435 : :
23436 : 0 : if (!ok)
23437 : : return false;
23438 : :
23439 : 0 : if (d->testing_p)
23440 : : return true;
23441 : :
23442 : 0 : emit_insn (seq);
23443 : :
23444 : 0 : dsecond = *d;
23445 : 0 : dsecond.op0 = dfirst.target;
23446 : 0 : dsecond.op1 = dfirst.target;
23447 : 0 : dsecond.one_operand_p = true;
23448 : 0 : dsecond.target = gen_reg_rtx (dsecond.vmode);
23449 : 0 : for (i = 0; i < nelt; i++)
23450 : 0 : dsecond.perm[i] = i ^ nelt2;
23451 : :
23452 : 0 : ok = expand_vec_perm_1 (&dsecond);
23453 : 0 : gcc_assert (ok);
23454 : :
23455 : 0 : blend = d->vmode == V8SFmode ? gen_avx_blendps256 : gen_avx_blendpd256;
23456 : 0 : emit_insn (blend (d->target, dfirst.target, dsecond.target, GEN_INT (msk)));
23457 : 0 : return true;
23458 : : }
23459 : :
23460 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement
23461 : : a two vector permutation using two single vector permutations and
23462 : : {,v}{,p}unpckl{ps,pd,bw,wd,dq}. If two_insn, succeed only if one
23463 : : of dfirst or dsecond is identity permutation. */
23464 : :
23465 : : static bool
23466 : 115749 : expand_vec_perm_2perm_interleave (struct expand_vec_perm_d *d, bool two_insn)
23467 : : {
23468 : 115749 : unsigned i, nelt = d->nelt, nelt2 = nelt / 2, lane = nelt;
23469 : 115749 : struct expand_vec_perm_d dfirst, dsecond, dfinal;
23470 : 115749 : bool ident1 = true, ident2 = true;
23471 : :
23472 : 115749 : if (d->one_operand_p)
23473 : : return false;
23474 : :
23475 : 210716 : if (GET_MODE_SIZE (d->vmode) == 16)
23476 : : {
23477 : 65032 : if (!TARGET_SSE)
23478 : : return false;
23479 : 65032 : if (d->vmode != V4SFmode && d->vmode != V2DFmode && !TARGET_SSE2)
23480 : : return false;
23481 : : }
23482 : 80652 : else if (GET_MODE_SIZE (d->vmode) == 32)
23483 : : {
23484 : 8535 : if (!TARGET_AVX)
23485 : : return false;
23486 : 8535 : if (d->vmode != V8SFmode && d->vmode != V4DFmode && !TARGET_AVX2)
23487 : : return false;
23488 : : lane = nelt2;
23489 : : }
23490 : : else
23491 : : return false;
23492 : :
23493 : 243401 : for (i = 1; i < nelt; i++)
23494 : 207531 : if ((d->perm[i] >= nelt) != ((d->perm[0] >= nelt) ^ (i & 1)))
23495 : : return false;
23496 : :
23497 : 35870 : dfirst = *d;
23498 : 35870 : dsecond = *d;
23499 : 35870 : dfinal = *d;
23500 : 35870 : dfirst.op1 = dfirst.op0;
23501 : 35870 : dfirst.one_operand_p = true;
23502 : 35870 : dsecond.op0 = dsecond.op1;
23503 : 35870 : dsecond.one_operand_p = true;
23504 : :
23505 : 232342 : for (i = 0; i < nelt; i++)
23506 : 196472 : if (d->perm[i] >= nelt)
23507 : : {
23508 : 98236 : dsecond.perm[i / 2 + (i >= lane ? lane / 2 : 0)] = d->perm[i] - nelt;
23509 : 98236 : if (d->perm[i] - nelt != i / 2 + (i >= lane ? lane / 2 : 0))
23510 : 89763 : ident2 = false;
23511 : 98236 : dsecond.perm[i / 2 + (i >= lane ? lane : lane / 2)]
23512 : 98236 : = d->perm[i] - nelt;
23513 : : }
23514 : : else
23515 : : {
23516 : 98236 : dfirst.perm[i / 2 + (i >= lane ? lane / 2 : 0)] = d->perm[i];
23517 : 98236 : if (d->perm[i] != i / 2 + (i >= lane ? lane / 2 : 0))
23518 : 81392 : ident1 = false;
23519 : 98236 : dfirst.perm[i / 2 + (i >= lane ? lane : lane / 2)] = d->perm[i];
23520 : : }
23521 : :
23522 : 35870 : if (two_insn && !ident1 && !ident2)
23523 : : return false;
23524 : :
23525 : 3955 : if (!d->testing_p)
23526 : : {
23527 : 214 : if (!ident1)
23528 : 144 : dfinal.op0 = dfirst.target = gen_reg_rtx (d->vmode);
23529 : 214 : if (!ident2)
23530 : 148 : dfinal.op1 = dsecond.target = gen_reg_rtx (d->vmode);
23531 : 214 : if (d->perm[0] >= nelt)
23532 : 0 : std::swap (dfinal.op0, dfinal.op1);
23533 : : }
23534 : :
23535 : 3955 : bool ok;
23536 : 3955 : rtx_insn *seq1 = NULL, *seq2 = NULL;
23537 : :
23538 : 3955 : if (!ident1)
23539 : : {
23540 : 2643 : start_sequence ();
23541 : 2643 : ok = expand_vec_perm_1 (&dfirst);
23542 : 2643 : seq1 = end_sequence ();
23543 : :
23544 : 2643 : if (!ok)
23545 : : return false;
23546 : : }
23547 : :
23548 : 2166 : if (!ident2)
23549 : : {
23550 : 2074 : start_sequence ();
23551 : 2074 : ok = expand_vec_perm_1 (&dsecond);
23552 : 2074 : seq2 = end_sequence ();
23553 : :
23554 : 2074 : if (!ok)
23555 : : return false;
23556 : : }
23557 : :
23558 : 600 : if (d->testing_p)
23559 : : return true;
23560 : :
23561 : 680 : for (i = 0; i < nelt; i++)
23562 : : {
23563 : 544 : dfinal.perm[i] = i / 2;
23564 : 544 : if (i >= lane)
23565 : 4 : dfinal.perm[i] += lane / 2;
23566 : 544 : if ((i & 1) != 0)
23567 : 272 : dfinal.perm[i] += nelt;
23568 : : }
23569 : 136 : emit_insn (seq1);
23570 : 136 : emit_insn (seq2);
23571 : 136 : ok = expand_vselect_vconcat (dfinal.target, dfinal.op0, dfinal.op1,
23572 : : dfinal.perm, dfinal.nelt, false);
23573 : 136 : gcc_assert (ok);
23574 : : return true;
23575 : : }
23576 : :
23577 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to simplify
23578 : : the permutation using two single vector permutations and the SSE4_1 pblendv
23579 : : instruction. If two_insn, succeed only if one of dfirst or dsecond is
23580 : : identity permutation. */
23581 : :
23582 : : static bool
23583 : 115149 : expand_vec_perm_2perm_pblendv (struct expand_vec_perm_d *d, bool two_insn)
23584 : : {
23585 : 115149 : unsigned i, nelt = d->nelt;
23586 : 115149 : struct expand_vec_perm_d dfirst, dsecond, dfinal;
23587 : 115149 : machine_mode vmode = d->vmode;
23588 : 115149 : bool ident1 = true, ident2 = true;
23589 : :
23590 : : /* Use the same checks as in expand_vec_perm_blend. */
23591 : 115149 : if (d->one_operand_p)
23592 : : return false;
23593 : 109182 : if (TARGET_AVX2 && GET_MODE_SIZE (vmode) == 32)
23594 : : ;
23595 : 102096 : else if (TARGET_AVX && (vmode == V4DFmode || vmode == V8SFmode))
23596 : : ;
23597 : 96847 : else if (TARGET_SSE4_1
23598 : 105774 : && (GET_MODE_SIZE (vmode) == 16
23599 : 7232 : || (TARGET_MMX_WITH_SSE && GET_MODE_SIZE (vmode) == 8)
23600 : 2057 : || GET_MODE_SIZE (vmode) == 4))
23601 : : ;
23602 : : else
23603 : : return false;
23604 : :
23605 : 16104 : dfirst = *d;
23606 : 16104 : dsecond = *d;
23607 : 16104 : dfinal = *d;
23608 : 16104 : dfirst.op1 = dfirst.op0;
23609 : 16104 : dfirst.one_operand_p = true;
23610 : 16104 : dsecond.op0 = dsecond.op1;
23611 : 16104 : dsecond.one_operand_p = true;
23612 : :
23613 : 134188 : for (i = 0; i < nelt; ++i)
23614 : 118084 : if (d->perm[i] >= nelt)
23615 : : {
23616 : 59258 : dfirst.perm[i] = 0xff;
23617 : 59258 : dsecond.perm[i] = d->perm[i] - nelt;
23618 : 59258 : if (d->perm[i] != i + nelt)
23619 : 118084 : ident2 = false;
23620 : : }
23621 : : else
23622 : : {
23623 : 58826 : dsecond.perm[i] = 0xff;
23624 : 58826 : dfirst.perm[i] = d->perm[i];
23625 : 58826 : if (d->perm[i] != i)
23626 : 118084 : ident1 = false;
23627 : : }
23628 : :
23629 : 16104 : if (two_insn && !ident1 && !ident2)
23630 : : return false;
23631 : :
23632 : : /* For now. Ideally treat 0xff as a wildcard. */
23633 : 56738 : for (i = 0; i < nelt; ++i)
23634 : 50600 : if (dfirst.perm[i] == 0xff)
23635 : : {
23636 : 26387 : if (GET_MODE_SIZE (vmode) == 32
23637 : 26387 : && dfirst.perm[i ^ (nelt / 2)] != 0xff)
23638 : 14740 : dfirst.perm[i] = dfirst.perm[i ^ (nelt / 2)] ^ (nelt / 2);
23639 : : else
23640 : 11647 : dfirst.perm[i] = i;
23641 : : }
23642 : : else
23643 : : {
23644 : 24213 : if (GET_MODE_SIZE (vmode) == 32
23645 : 24213 : && dsecond.perm[i ^ (nelt / 2)] != 0xff)
23646 : 13164 : dsecond.perm[i] = dsecond.perm[i ^ (nelt / 2)] ^ (nelt / 2);
23647 : : else
23648 : 11049 : dsecond.perm[i] = i;
23649 : : }
23650 : :
23651 : 6138 : if (!d->testing_p)
23652 : : {
23653 : 2347 : if (!ident1)
23654 : 2223 : dfinal.op0 = dfirst.target = gen_reg_rtx (d->vmode);
23655 : 2347 : if (!ident2)
23656 : 1059 : dfinal.op1 = dsecond.target = gen_reg_rtx (d->vmode);
23657 : : }
23658 : :
23659 : 6138 : bool ok;
23660 : 6138 : rtx_insn *seq1 = NULL, *seq2 = NULL;
23661 : :
23662 : 6138 : if (!ident1)
23663 : : {
23664 : 5549 : start_sequence ();
23665 : 5549 : ok = expand_vec_perm_1 (&dfirst);
23666 : 5549 : seq1 = end_sequence ();
23667 : :
23668 : 5549 : if (!ok)
23669 : : return false;
23670 : : }
23671 : :
23672 : 4507 : if (!ident2)
23673 : : {
23674 : 1457 : start_sequence ();
23675 : 1457 : ok = expand_vec_perm_1 (&dsecond);
23676 : 1457 : seq2 = end_sequence ();
23677 : :
23678 : 1457 : if (!ok)
23679 : : return false;
23680 : : }
23681 : :
23682 : 3918 : if (d->testing_p)
23683 : : return true;
23684 : :
23685 : 21385 : for (i = 0; i < nelt; ++i)
23686 : 19380 : dfinal.perm[i] = (d->perm[i] >= nelt ? i + nelt : i);
23687 : :
23688 : 2005 : emit_insn (seq1);
23689 : 2005 : emit_insn (seq2);
23690 : 2005 : ok = expand_vec_perm_blend (&dfinal);
23691 : 2005 : gcc_assert (ok);
23692 : : return true;
23693 : : }
23694 : :
23695 : : /* A subroutine of ix86_expand_vec_perm_const_1.
23696 : : Implement a permutation with psrlw, psllw and por.
23697 : : It handles case:
23698 : : __builtin_shufflevector (v,v,1,0,3,2,5,4,7,6,9,8,11,10,13,12,15,14);
23699 : : __builtin_shufflevector (v,v,1,0,3,2,5,4,7,6); */
23700 : :
23701 : : static bool
23702 : 25893 : expand_vec_perm_psrlw_psllw_por (struct expand_vec_perm_d *d)
23703 : : {
23704 : 25893 : unsigned i;
23705 : 25893 : rtx (*gen_shr) (rtx, rtx, rtx);
23706 : 25893 : rtx (*gen_shl) (rtx, rtx, rtx);
23707 : 25893 : rtx (*gen_or) (rtx, rtx, rtx);
23708 : 25893 : machine_mode mode = VOIDmode;
23709 : :
23710 : 25893 : if (!TARGET_SSE2 || !d->one_operand_p)
23711 : : return false;
23712 : :
23713 : 5174 : switch (d->vmode)
23714 : : {
23715 : 1407 : case E_V8QImode:
23716 : 1407 : if (!TARGET_MMX_WITH_SSE)
23717 : : return false;
23718 : : mode = V4HImode;
23719 : : gen_shr = gen_lshrv4hi3;
23720 : : gen_shl = gen_ashlv4hi3;
23721 : : gen_or = gen_iorv4hi3;
23722 : : break;
23723 : : case E_V16QImode:
23724 : : mode = V8HImode;
23725 : : gen_shr = gen_lshrv8hi3;
23726 : : gen_shl = gen_ashlv8hi3;
23727 : : gen_or = gen_iorv8hi3;
23728 : : break;
23729 : : default: return false;
23730 : : }
23731 : :
23732 : 3100 : if (!rtx_equal_p (d->op0, d->op1))
23733 : : return false;
23734 : :
23735 : 12140 : for (i = 0; i < d->nelt; i += 2)
23736 : 10702 : if (d->perm[i] != i + 1 || d->perm[i + 1] != i)
23737 : : return false;
23738 : :
23739 : 1438 : if (d->testing_p)
23740 : : return true;
23741 : :
23742 : 26 : rtx tmp1 = gen_reg_rtx (mode);
23743 : 26 : rtx tmp2 = gen_reg_rtx (mode);
23744 : 26 : rtx op0 = force_reg (d->vmode, d->op0);
23745 : :
23746 : 26 : emit_move_insn (tmp1, lowpart_subreg (mode, op0, d->vmode));
23747 : 26 : emit_move_insn (tmp2, lowpart_subreg (mode, op0, d->vmode));
23748 : 26 : emit_insn (gen_shr (tmp1, tmp1, GEN_INT (8)));
23749 : 26 : emit_insn (gen_shl (tmp2, tmp2, GEN_INT (8)));
23750 : 26 : emit_insn (gen_or (tmp1, tmp1, tmp2));
23751 : 26 : emit_move_insn (d->target, lowpart_subreg (d->vmode, tmp1, mode));
23752 : :
23753 : 26 : return true;
23754 : : }
23755 : :
23756 : : /* A subroutine of ix86_expand_vec_perm_const_1. Implement a V4DF
23757 : : permutation using two vperm2f128, followed by a vshufpd insn blending
23758 : : the two vectors together. */
23759 : :
23760 : : static bool
23761 : 29316 : expand_vec_perm_2vperm2f128_vshuf (struct expand_vec_perm_d *d)
23762 : : {
23763 : 29316 : struct expand_vec_perm_d dfirst, dsecond, dthird;
23764 : 29316 : bool ok;
23765 : :
23766 : 29316 : if (!TARGET_AVX || (d->vmode != V4DFmode))
23767 : : return false;
23768 : :
23769 : 1277 : if (d->testing_p)
23770 : : return true;
23771 : :
23772 : 206 : dfirst = *d;
23773 : 206 : dsecond = *d;
23774 : 206 : dthird = *d;
23775 : :
23776 : 206 : dfirst.perm[0] = (d->perm[0] & ~1);
23777 : 206 : dfirst.perm[1] = (d->perm[0] & ~1) + 1;
23778 : 206 : dfirst.perm[2] = (d->perm[2] & ~1);
23779 : 206 : dfirst.perm[3] = (d->perm[2] & ~1) + 1;
23780 : 206 : dsecond.perm[0] = (d->perm[1] & ~1);
23781 : 206 : dsecond.perm[1] = (d->perm[1] & ~1) + 1;
23782 : 206 : dsecond.perm[2] = (d->perm[3] & ~1);
23783 : 206 : dsecond.perm[3] = (d->perm[3] & ~1) + 1;
23784 : 206 : dthird.perm[0] = (d->perm[0] % 2);
23785 : 206 : dthird.perm[1] = (d->perm[1] % 2) + 4;
23786 : 206 : dthird.perm[2] = (d->perm[2] % 2) + 2;
23787 : 206 : dthird.perm[3] = (d->perm[3] % 2) + 6;
23788 : :
23789 : 206 : dfirst.target = gen_reg_rtx (dfirst.vmode);
23790 : 206 : dsecond.target = gen_reg_rtx (dsecond.vmode);
23791 : 206 : dthird.op0 = dfirst.target;
23792 : 206 : dthird.op1 = dsecond.target;
23793 : 206 : dthird.one_operand_p = false;
23794 : :
23795 : 206 : canonicalize_perm (&dfirst);
23796 : 206 : canonicalize_perm (&dsecond);
23797 : :
23798 : 206 : ok = expand_vec_perm_1 (&dfirst)
23799 : 206 : && expand_vec_perm_1 (&dsecond)
23800 : 412 : && expand_vec_perm_1 (&dthird);
23801 : :
23802 : 0 : gcc_assert (ok);
23803 : :
23804 : : return true;
23805 : : }
23806 : :
23807 : : static bool ix86_expand_vec_perm_const_1 (struct expand_vec_perm_d *);
23808 : :
23809 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement
23810 : : a two vector permutation using two intra-lane vector
23811 : : permutations, vperm2f128 swapping the lanes and vblend* insn blending
23812 : : the non-swapped and swapped vectors together. */
23813 : :
23814 : : static bool
23815 : 15772 : expand_vec_perm2_vperm2f128_vblend (struct expand_vec_perm_d *d)
23816 : : {
23817 : 15772 : struct expand_vec_perm_d dfirst, dsecond, dthird;
23818 : 15772 : unsigned i, j, msk, nelt = d->nelt, nelt2 = nelt / 2, which1 = 0, which2 = 0;
23819 : 15772 : rtx_insn *seq1, *seq2;
23820 : 15772 : bool ok;
23821 : 15772 : rtx (*blend) (rtx, rtx, rtx, rtx) = NULL;
23822 : :
23823 : 15772 : if (!TARGET_AVX
23824 : 990 : || TARGET_AVX2
23825 : 722 : || (d->vmode != V8SFmode && d->vmode != V4DFmode)
23826 : 595 : || d->one_operand_p)
23827 : : return false;
23828 : :
23829 : 595 : dfirst = *d;
23830 : 595 : dsecond = *d;
23831 : 5355 : for (i = 0; i < nelt; i++)
23832 : : {
23833 : 4760 : dfirst.perm[i] = 0xff;
23834 : 4760 : dsecond.perm[i] = 0xff;
23835 : : }
23836 : 5355 : for (i = 0, msk = 0; i < nelt; i++)
23837 : : {
23838 : 4760 : j = (d->perm[i] & nelt2) ? i | nelt2 : i & ~nelt2;
23839 : 4760 : if (j == i)
23840 : : {
23841 : 3458 : dfirst.perm[j] = d->perm[i];
23842 : 5858 : which1 |= (d->perm[i] < nelt ? 1 : 2);
23843 : : }
23844 : : else
23845 : : {
23846 : 1302 : dsecond.perm[j] = d->perm[i];
23847 : 1302 : which2 |= (d->perm[i] < nelt ? 1 : 2);
23848 : 1302 : msk |= (1U << i);
23849 : : }
23850 : : }
23851 : 595 : if (msk == 0 || msk == (1U << nelt) - 1)
23852 : : return false;
23853 : :
23854 : 595 : if (!d->testing_p)
23855 : : {
23856 : 40 : dfirst.target = gen_reg_rtx (dfirst.vmode);
23857 : 40 : dsecond.target = gen_reg_rtx (dsecond.vmode);
23858 : : }
23859 : :
23860 : 5355 : for (i = 0; i < nelt; i++)
23861 : : {
23862 : 4760 : if (dfirst.perm[i] == 0xff)
23863 : 1302 : dfirst.perm[i] = (which1 == 2 ? i + nelt : i);
23864 : 4760 : if (dsecond.perm[i] == 0xff)
23865 : 3458 : dsecond.perm[i] = (which2 == 2 ? i + nelt : i);
23866 : : }
23867 : 595 : canonicalize_perm (&dfirst);
23868 : 595 : start_sequence ();
23869 : 595 : ok = ix86_expand_vec_perm_const_1 (&dfirst);
23870 : 595 : seq1 = end_sequence ();
23871 : :
23872 : 595 : if (!ok)
23873 : : return false;
23874 : :
23875 : 595 : canonicalize_perm (&dsecond);
23876 : 595 : start_sequence ();
23877 : 595 : ok = ix86_expand_vec_perm_const_1 (&dsecond);
23878 : 595 : seq2 = end_sequence ();
23879 : :
23880 : 595 : if (!ok)
23881 : : return false;
23882 : :
23883 : 595 : if (d->testing_p)
23884 : : return true;
23885 : :
23886 : 40 : emit_insn (seq1);
23887 : 40 : emit_insn (seq2);
23888 : :
23889 : 40 : dthird = *d;
23890 : 40 : dthird.op0 = dsecond.target;
23891 : 40 : dthird.op1 = dsecond.target;
23892 : 40 : dthird.one_operand_p = true;
23893 : 40 : dthird.target = gen_reg_rtx (dthird.vmode);
23894 : 360 : for (i = 0; i < nelt; i++)
23895 : 320 : dthird.perm[i] = i ^ nelt2;
23896 : :
23897 : 40 : ok = expand_vec_perm_1 (&dthird);
23898 : 40 : gcc_assert (ok);
23899 : :
23900 : 40 : blend = d->vmode == V8SFmode ? gen_avx_blendps256 : gen_avx_blendpd256;
23901 : 40 : emit_insn (blend (d->target, dfirst.target, dthird.target, GEN_INT (msk)));
23902 : 40 : return true;
23903 : : }
23904 : :
23905 : : /* A subroutine of expand_vec_perm_even_odd_1. Implement the double-word
23906 : : permutation with two pshufb insns and an ior. We should have already
23907 : : failed all two instruction sequences. */
23908 : :
23909 : : static bool
23910 : 28060 : expand_vec_perm_pshufb2 (struct expand_vec_perm_d *d)
23911 : : {
23912 : 28060 : rtx rperm[2][16], vperm, l, h, op, m128;
23913 : 28060 : unsigned int i, nelt, eltsz;
23914 : 28060 : machine_mode mode;
23915 : 28060 : rtx (*gen) (rtx, rtx, rtx);
23916 : :
23917 : 32355 : if (!TARGET_SSSE3 || (GET_MODE_SIZE (d->vmode) != 16
23918 : 8500 : && GET_MODE_SIZE (d->vmode) != 8
23919 : 8460 : && GET_MODE_SIZE (d->vmode) != 4))
23920 : : return false;
23921 : 682 : gcc_assert (!d->one_operand_p);
23922 : :
23923 : 682 : if (d->testing_p)
23924 : : return true;
23925 : :
23926 : 130 : switch (GET_MODE_SIZE (d->vmode))
23927 : : {
23928 : : case 4:
23929 : : mode = V4QImode;
23930 : : gen = gen_mmx_pshufbv4qi3;
23931 : : break;
23932 : 20 : case 8:
23933 : 20 : mode = V8QImode;
23934 : 20 : gen = gen_mmx_pshufbv8qi3;
23935 : 20 : break;
23936 : 45 : case 16:
23937 : 45 : mode = V16QImode;
23938 : 45 : gen = gen_ssse3_pshufbv16qi3;
23939 : 45 : break;
23940 : 0 : default:
23941 : 0 : gcc_unreachable ();
23942 : : }
23943 : :
23944 : 65 : nelt = d->nelt;
23945 : 65 : eltsz = GET_MODE_UNIT_SIZE (d->vmode);
23946 : :
23947 : : /* Generate two permutation masks. If the required element is within
23948 : : the given vector it is shuffled into the proper lane. If the required
23949 : : element is in the other vector, force a zero into the lane by setting
23950 : : bit 7 in the permutation mask. */
23951 : 65 : m128 = GEN_INT (-128);
23952 : 849 : for (i = 0; i < nelt; ++i)
23953 : : {
23954 : 784 : unsigned j, k, e = d->perm[i];
23955 : 784 : unsigned which = (e >= nelt);
23956 : 784 : if (e >= nelt)
23957 : 393 : e -= nelt;
23958 : :
23959 : 1664 : for (j = 0; j < eltsz; ++j)
23960 : : {
23961 : 880 : rperm[which][i*eltsz + j] = GEN_INT (e*eltsz + j);
23962 : 880 : rperm[1-which][i*eltsz + j] = m128;
23963 : : }
23964 : :
23965 : 6936 : for (k = i*eltsz + j; k < 16; ++k)
23966 : 6152 : rperm[0][k] = rperm[1][k] = m128;
23967 : : }
23968 : :
23969 : 65 : vperm = gen_rtx_CONST_VECTOR (V16QImode, gen_rtvec_v (16, rperm[0]));
23970 : 65 : vperm = force_reg (V16QImode, vperm);
23971 : :
23972 : 65 : l = gen_reg_rtx (mode);
23973 : 65 : op = gen_lowpart (mode, d->op0);
23974 : 65 : emit_insn (gen (l, op, vperm));
23975 : :
23976 : 65 : vperm = gen_rtx_CONST_VECTOR (V16QImode, gen_rtvec_v (16, rperm[1]));
23977 : 65 : vperm = force_reg (V16QImode, vperm);
23978 : :
23979 : 65 : h = gen_reg_rtx (mode);
23980 : 65 : op = gen_lowpart (mode, d->op1);
23981 : 65 : emit_insn (gen (h, op, vperm));
23982 : :
23983 : 65 : op = d->target;
23984 : 65 : if (d->vmode != mode)
23985 : 22 : op = gen_reg_rtx (mode);
23986 : 65 : ix86_emit_vec_binop (IOR, mode, op, l, h);
23987 : 65 : if (op != d->target)
23988 : 22 : emit_move_insn (d->target, gen_lowpart (d->vmode, op));
23989 : :
23990 : : return true;
23991 : : }
23992 : :
23993 : : /* Implement arbitrary permutation of one V32QImode and V16QImode operand
23994 : : with two vpshufb insns, vpermq and vpor. We should have already failed
23995 : : all two or three instruction sequences. */
23996 : :
23997 : : static bool
23998 : 23434 : expand_vec_perm_vpshufb2_vpermq (struct expand_vec_perm_d *d)
23999 : : {
24000 : 23434 : rtx rperm[2][32], vperm, l, h, hp, op, m128;
24001 : 23434 : unsigned int i, nelt, eltsz;
24002 : :
24003 : 23434 : if (!TARGET_AVX2
24004 : 400 : || !d->one_operand_p
24005 : 171 : || (d->vmode != V32QImode && d->vmode != V16HImode))
24006 : : return false;
24007 : :
24008 : 6 : if (d->testing_p)
24009 : : return true;
24010 : :
24011 : 6 : nelt = d->nelt;
24012 : 6 : eltsz = GET_MODE_UNIT_SIZE (d->vmode);
24013 : :
24014 : : /* Generate two permutation masks. If the required element is within
24015 : : the same lane, it is shuffled in. If the required element from the
24016 : : other lane, force a zero by setting bit 7 in the permutation mask.
24017 : : In the other mask the mask has non-negative elements if element
24018 : : is requested from the other lane, but also moved to the other lane,
24019 : : so that the result of vpshufb can have the two V2TImode halves
24020 : : swapped. */
24021 : 6 : m128 = GEN_INT (-128);
24022 : 166 : for (i = 0; i < nelt; ++i)
24023 : : {
24024 : 160 : unsigned j, e = d->perm[i] & (nelt / 2 - 1);
24025 : 160 : unsigned which = ((d->perm[i] ^ i) & (nelt / 2)) * eltsz;
24026 : :
24027 : 352 : for (j = 0; j < eltsz; ++j)
24028 : : {
24029 : 192 : rperm[!!which][(i * eltsz + j) ^ which] = GEN_INT (e * eltsz + j);
24030 : 192 : rperm[!which][(i * eltsz + j) ^ (which ^ 16)] = m128;
24031 : : }
24032 : : }
24033 : :
24034 : 6 : vperm = gen_rtx_CONST_VECTOR (V32QImode, gen_rtvec_v (32, rperm[1]));
24035 : 6 : vperm = force_reg (V32QImode, vperm);
24036 : :
24037 : 6 : h = gen_reg_rtx (V32QImode);
24038 : 6 : op = gen_lowpart (V32QImode, d->op0);
24039 : 6 : emit_insn (gen_avx2_pshufbv32qi3 (h, op, vperm));
24040 : :
24041 : : /* Swap the 128-byte lanes of h into hp. */
24042 : 6 : hp = gen_reg_rtx (V4DImode);
24043 : 6 : op = gen_lowpart (V4DImode, h);
24044 : 6 : emit_insn (gen_avx2_permv4di_1 (hp, op, const2_rtx, GEN_INT (3), const0_rtx,
24045 : : const1_rtx));
24046 : :
24047 : 6 : vperm = gen_rtx_CONST_VECTOR (V32QImode, gen_rtvec_v (32, rperm[0]));
24048 : 6 : vperm = force_reg (V32QImode, vperm);
24049 : :
24050 : 6 : l = gen_reg_rtx (V32QImode);
24051 : 6 : op = gen_lowpart (V32QImode, d->op0);
24052 : 6 : emit_insn (gen_avx2_pshufbv32qi3 (l, op, vperm));
24053 : :
24054 : 6 : op = d->target;
24055 : 6 : if (d->vmode != V32QImode)
24056 : 2 : op = gen_reg_rtx (V32QImode);
24057 : 6 : emit_insn (gen_iorv32qi3 (op, l, gen_lowpart (V32QImode, hp)));
24058 : 6 : if (op != d->target)
24059 : 2 : emit_move_insn (d->target, gen_lowpart (d->vmode, op));
24060 : :
24061 : : return true;
24062 : : }
24063 : :
24064 : : /* A subroutine of expand_vec_perm_even_odd_1. Implement extract-even
24065 : : and extract-odd permutations of two V32QImode and V16QImode operand
24066 : : with two vpshufb insns, vpor and vpermq. We should have already
24067 : : failed all two or three instruction sequences. */
24068 : :
24069 : : static bool
24070 : 23428 : expand_vec_perm_vpshufb2_vpermq_even_odd (struct expand_vec_perm_d *d)
24071 : : {
24072 : 23428 : rtx rperm[2][32], vperm, l, h, ior, op, m128;
24073 : 23428 : unsigned int i, nelt, eltsz;
24074 : :
24075 : 23428 : if (!TARGET_AVX2
24076 : 394 : || d->one_operand_p
24077 : 229 : || (d->vmode != V32QImode && d->vmode != V16HImode))
24078 : : return false;
24079 : :
24080 : 112 : for (i = 0; i < d->nelt; ++i)
24081 : 112 : if ((d->perm[i] ^ (i * 2)) & (3 * d->nelt / 2))
24082 : : return false;
24083 : :
24084 : 0 : if (d->testing_p)
24085 : : return true;
24086 : :
24087 : 0 : nelt = d->nelt;
24088 : 0 : eltsz = GET_MODE_UNIT_SIZE (d->vmode);
24089 : :
24090 : : /* Generate two permutation masks. In the first permutation mask
24091 : : the first quarter will contain indexes for the first half
24092 : : of the op0, the second quarter will contain bit 7 set, third quarter
24093 : : will contain indexes for the second half of the op0 and the
24094 : : last quarter bit 7 set. In the second permutation mask
24095 : : the first quarter will contain bit 7 set, the second quarter
24096 : : indexes for the first half of the op1, the third quarter bit 7 set
24097 : : and last quarter indexes for the second half of the op1.
24098 : : I.e. the first mask e.g. for V32QImode extract even will be:
24099 : : 0, 2, ..., 0xe, -128, ..., -128, 0, 2, ..., 0xe, -128, ..., -128
24100 : : (all values masked with 0xf except for -128) and second mask
24101 : : for extract even will be
24102 : : -128, ..., -128, 0, 2, ..., 0xe, -128, ..., -128, 0, 2, ..., 0xe. */
24103 : 0 : m128 = GEN_INT (-128);
24104 : 0 : for (i = 0; i < nelt; ++i)
24105 : : {
24106 : 0 : unsigned j, e = d->perm[i] & (nelt / 2 - 1);
24107 : 0 : unsigned which = d->perm[i] >= nelt;
24108 : 0 : unsigned xorv = (i >= nelt / 4 && i < 3 * nelt / 4) ? 24 : 0;
24109 : :
24110 : 0 : for (j = 0; j < eltsz; ++j)
24111 : : {
24112 : 0 : rperm[which][(i * eltsz + j) ^ xorv] = GEN_INT (e * eltsz + j);
24113 : 0 : rperm[1 - which][(i * eltsz + j) ^ xorv] = m128;
24114 : : }
24115 : : }
24116 : :
24117 : 0 : vperm = gen_rtx_CONST_VECTOR (V32QImode, gen_rtvec_v (32, rperm[0]));
24118 : 0 : vperm = force_reg (V32QImode, vperm);
24119 : :
24120 : 0 : l = gen_reg_rtx (V32QImode);
24121 : 0 : op = gen_lowpart (V32QImode, d->op0);
24122 : 0 : emit_insn (gen_avx2_pshufbv32qi3 (l, op, vperm));
24123 : :
24124 : 0 : vperm = gen_rtx_CONST_VECTOR (V32QImode, gen_rtvec_v (32, rperm[1]));
24125 : 0 : vperm = force_reg (V32QImode, vperm);
24126 : :
24127 : 0 : h = gen_reg_rtx (V32QImode);
24128 : 0 : op = gen_lowpart (V32QImode, d->op1);
24129 : 0 : emit_insn (gen_avx2_pshufbv32qi3 (h, op, vperm));
24130 : :
24131 : 0 : ior = gen_reg_rtx (V32QImode);
24132 : 0 : emit_insn (gen_iorv32qi3 (ior, l, h));
24133 : :
24134 : : /* Permute the V4DImode quarters using { 0, 2, 1, 3 } permutation. */
24135 : 0 : op = gen_reg_rtx (V4DImode);
24136 : 0 : ior = gen_lowpart (V4DImode, ior);
24137 : 0 : emit_insn (gen_avx2_permv4di_1 (op, ior, const0_rtx, const2_rtx,
24138 : : const1_rtx, GEN_INT (3)));
24139 : 0 : emit_move_insn (d->target, gen_lowpart (d->vmode, op));
24140 : :
24141 : 0 : return true;
24142 : : }
24143 : :
24144 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement a
24145 : : permutation (which is a bland) with and, andnot and or when pshufb is not available.
24146 : :
24147 : : It handles case:
24148 : : __builtin_shufflevector (v1, v2, 0, 9, 2, 11, 4, 13, 6, 15);
24149 : : __builtin_shufflevector (v1, v2, 8, 1, 2, 11, 4, 13, 6, 15);
24150 : :
24151 : : An element[i] must be chosen between op0[i] and op1[i] to satisfy the
24152 : : requirement.
24153 : : */
24154 : :
24155 : : static bool
24156 : 24455 : expand_vec_perm_pand_pandn_por (struct expand_vec_perm_d *d)
24157 : : {
24158 : 24455 : rtx rperm[16], vperm;
24159 : 24455 : unsigned int i, nelt = d->nelt;
24160 : :
24161 : 24455 : if (!TARGET_SSE2
24162 : 24455 : || d->one_operand_p
24163 : 20719 : || (d->vmode != V16QImode && d->vmode != V8HImode))
24164 : : return false;
24165 : :
24166 : 7525 : if (d->perm[0] != 0)
24167 : : return false;
24168 : :
24169 : : /* The dest[i] must select an element between op0[i] and op1[i]. */
24170 : 15453 : for (i = 1; i < nelt; i++)
24171 : 14436 : if ((d->perm[i] % nelt) != i)
24172 : : return false;
24173 : :
24174 : 1017 : if (d->testing_p)
24175 : : return true;
24176 : :
24177 : : /* Generates a blend mask for the operators AND and ANDNOT. */
24178 : 108 : machine_mode inner_mode = GET_MODE_INNER (d->vmode);
24179 : 1148 : for (i = 0; i < nelt; i++)
24180 : 1581 : rperm[i] = (d->perm[i] < nelt) ? CONSTM1_RTX (inner_mode)
24181 : 541 : : CONST0_RTX (inner_mode);
24182 : :
24183 : 108 : vperm = gen_rtx_CONST_VECTOR (d->vmode, gen_rtvec_v (nelt, rperm));
24184 : 108 : vperm = force_reg (d->vmode, vperm);
24185 : :
24186 : 108 : ix86_expand_sse_movcc (d->target, vperm, d->op0, d->op1);
24187 : :
24188 : 108 : return true;
24189 : : }
24190 : :
24191 : : /* Implement permutation with pslldq + psrldq + por when pshufb is not
24192 : : available. */
24193 : : static bool
24194 : 43428 : expand_vec_perm_pslldq_psrldq_por (struct expand_vec_perm_d *d, bool pandn)
24195 : : {
24196 : 43428 : unsigned i, nelt = d->nelt;
24197 : 43428 : unsigned start1, end1 = -1;
24198 : 43428 : machine_mode vmode = d->vmode, imode;
24199 : 43428 : int start2 = -1;
24200 : 43428 : bool clear_op0, clear_op1;
24201 : 43428 : unsigned inner_size;
24202 : 43428 : rtx op0, op1, dop1;
24203 : 43428 : rtx (*gen_vec_shr) (rtx, rtx, rtx);
24204 : 43428 : rtx (*gen_vec_shl) (rtx, rtx, rtx);
24205 : :
24206 : : /* pshufd can be used for V4SI/V2DI under TARGET_SSE2. */
24207 : 43428 : if (!TARGET_SSE2 || (vmode != E_V16QImode && vmode != E_V8HImode))
24208 : : return false;
24209 : :
24210 : 13446 : start1 = d->perm[0];
24211 : 35980 : for (i = 1; i < nelt; i++)
24212 : : {
24213 : 35293 : if (d->perm[i] != d->perm[i-1] + 1
24214 : 9298 : || d->perm[i] == nelt)
24215 : : {
24216 : 26205 : if (start2 == -1)
24217 : : {
24218 : 13446 : start2 = d->perm[i];
24219 : 13446 : end1 = d->perm[i-1];
24220 : : }
24221 : : else
24222 : : return false;
24223 : : }
24224 : : }
24225 : :
24226 : 687 : clear_op0 = end1 != nelt - 1;
24227 : 687 : clear_op1 = start2 % nelt != 0;
24228 : : /* pandn/pand is needed to clear upper/lower bits of op0/op1. */
24229 : 687 : if (!pandn && (clear_op0 || clear_op1))
24230 : : return false;
24231 : :
24232 : 463 : if (d->testing_p)
24233 : : return true;
24234 : :
24235 : 44 : gen_vec_shr = vmode == E_V16QImode ? gen_vec_shr_v16qi : gen_vec_shr_v8hi;
24236 : 20 : gen_vec_shl = vmode == E_V16QImode ? gen_vec_shl_v16qi : gen_vec_shl_v8hi;
24237 : 44 : imode = GET_MODE_INNER (vmode);
24238 : 44 : inner_size = GET_MODE_BITSIZE (imode);
24239 : 44 : op0 = gen_reg_rtx (vmode);
24240 : 44 : op1 = gen_reg_rtx (vmode);
24241 : :
24242 : 44 : if (start1)
24243 : 41 : emit_insn (gen_vec_shr (op0, d->op0, GEN_INT (start1 * inner_size)));
24244 : : else
24245 : 3 : emit_move_insn (op0, d->op0);
24246 : :
24247 : 44 : dop1 = d->op1;
24248 : 44 : if (d->one_operand_p)
24249 : 24 : dop1 = d->op0;
24250 : :
24251 : 44 : int shl_offset = end1 - start1 + 1 - start2 % nelt;
24252 : 44 : if (shl_offset)
24253 : 44 : emit_insn (gen_vec_shl (op1, dop1, GEN_INT (shl_offset * inner_size)));
24254 : : else
24255 : 0 : emit_move_insn (op1, dop1);
24256 : :
24257 : : /* Clear lower/upper bits for op0/op1. */
24258 : 44 : if (clear_op0 || clear_op1)
24259 : : {
24260 : : rtx vec[16];
24261 : : rtx const_vec;
24262 : : rtx clear;
24263 : 339 : for (i = 0; i != nelt; i++)
24264 : : {
24265 : 312 : if (i < (end1 - start1 + 1))
24266 : 156 : vec[i] = gen_int_mode ((HOST_WIDE_INT_1U << inner_size) - 1, imode);
24267 : : else
24268 : 156 : vec[i] = CONST0_RTX (imode);
24269 : : }
24270 : 27 : const_vec = gen_rtx_CONST_VECTOR (vmode, gen_rtvec_v (nelt, vec));
24271 : 27 : const_vec = validize_mem (force_const_mem (vmode, const_vec));
24272 : 27 : clear = force_reg (vmode, const_vec);
24273 : :
24274 : 27 : if (clear_op0)
24275 : 19 : emit_move_insn (op0, gen_rtx_AND (vmode, op0, clear));
24276 : 27 : if (clear_op1)
24277 : 16 : emit_move_insn (op1, gen_rtx_AND (vmode,
24278 : : gen_rtx_NOT (vmode, clear),
24279 : : op1));
24280 : : }
24281 : :
24282 : 44 : emit_move_insn (d->target, gen_rtx_IOR (vmode, op0, op1));
24283 : 44 : return true;
24284 : : }
24285 : :
24286 : : /* A subroutine of expand_vec_perm_even_odd_1. Implement extract-even
24287 : : and extract-odd permutations of two V8QI, V8HI, V16QI, V16HI or V32QI
24288 : : operands with two "and" and "pack" or two "shift" and "pack" insns.
24289 : : We should have already failed all two instruction sequences. */
24290 : :
24291 : : static bool
24292 : 45195 : expand_vec_perm_even_odd_pack (struct expand_vec_perm_d *d)
24293 : : {
24294 : 45195 : rtx op, dop0, dop1, t;
24295 : 45195 : unsigned i, odd, c, s, nelt = d->nelt;
24296 : 45195 : int pblendw_i = 0;
24297 : 45195 : bool end_perm = false;
24298 : 45195 : machine_mode half_mode;
24299 : 45195 : rtx (*gen_and) (rtx, rtx, rtx);
24300 : 45195 : rtx (*gen_pack) (rtx, rtx, rtx);
24301 : 45195 : rtx (*gen_shift) (rtx, rtx, rtx);
24302 : :
24303 : 45195 : if (d->one_operand_p)
24304 : : return false;
24305 : :
24306 : 39978 : switch (d->vmode)
24307 : : {
24308 : 4242 : case E_V4HImode:
24309 : : /* Required for "pack". */
24310 : 4242 : if (!TARGET_SSE4_1)
24311 : : return false;
24312 : : c = 0xffff;
24313 : : s = 16;
24314 : : half_mode = V2SImode;
24315 : : gen_and = gen_andv2si3;
24316 : : gen_pack = gen_mmx_packusdw;
24317 : : gen_shift = gen_lshrv2si3;
24318 : : pblendw_i = 0x5;
24319 : : break;
24320 : 5775 : case E_V8HImode:
24321 : : /* Required for "pack". */
24322 : 5775 : if (!TARGET_SSE4_1)
24323 : : return false;
24324 : : c = 0xffff;
24325 : : s = 16;
24326 : : half_mode = V4SImode;
24327 : : gen_and = gen_andv4si3;
24328 : : gen_pack = gen_sse4_1_packusdw;
24329 : : gen_shift = gen_lshrv4si3;
24330 : : pblendw_i = 0x55;
24331 : : break;
24332 : : case E_V8QImode:
24333 : : /* No check as all instructions are SSE2. */
24334 : : c = 0xff;
24335 : : s = 8;
24336 : : half_mode = V4HImode;
24337 : : gen_and = gen_andv4hi3;
24338 : : gen_pack = gen_mmx_packuswb;
24339 : : gen_shift = gen_lshrv4hi3;
24340 : : break;
24341 : 14121 : case E_V16QImode:
24342 : : /* No check as all instructions are SSE2. */
24343 : 14121 : c = 0xff;
24344 : 14121 : s = 8;
24345 : 14121 : half_mode = V8HImode;
24346 : 14121 : gen_and = gen_andv8hi3;
24347 : 14121 : gen_pack = gen_sse2_packuswb;
24348 : 14121 : gen_shift = gen_lshrv8hi3;
24349 : 14121 : break;
24350 : 428 : case E_V16HImode:
24351 : 428 : if (!TARGET_AVX2)
24352 : : return false;
24353 : : c = 0xffff;
24354 : : s = 16;
24355 : : half_mode = V8SImode;
24356 : : gen_and = gen_andv8si3;
24357 : : gen_pack = gen_avx2_packusdw;
24358 : : gen_shift = gen_lshrv8si3;
24359 : : pblendw_i = 0x5555;
24360 : : end_perm = true;
24361 : : break;
24362 : 500 : case E_V32QImode:
24363 : 500 : if (!TARGET_AVX2)
24364 : : return false;
24365 : : c = 0xff;
24366 : : s = 8;
24367 : : half_mode = V16HImode;
24368 : : gen_and = gen_andv16hi3;
24369 : : gen_pack = gen_avx2_packuswb;
24370 : : gen_shift = gen_lshrv16hi3;
24371 : : end_perm = true;
24372 : : break;
24373 : : default:
24374 : : /* Only V4HI, V8QI, V8HI, V16QI, V16HI and V32QI modes
24375 : : are more profitable than general shuffles. */
24376 : : return false;
24377 : : }
24378 : :
24379 : : /* Check that permutation is even or odd. */
24380 : 19976 : odd = d->perm[0];
24381 : 19976 : if (odd > 1)
24382 : : return false;
24383 : :
24384 : 228781 : for (i = 1; i < nelt; ++i)
24385 : 212962 : if (d->perm[i] != 2 * i + odd)
24386 : : return false;
24387 : :
24388 : 15819 : if (d->testing_p)
24389 : : return true;
24390 : :
24391 : 5453 : dop0 = gen_reg_rtx (half_mode);
24392 : 5453 : dop1 = gen_reg_rtx (half_mode);
24393 : 5453 : if (odd == 0)
24394 : : {
24395 : : /* Use pblendw since const_vector 0 should be cheaper than
24396 : : const_vector 0xffff. */
24397 : 4736 : if (d->vmode == V4HImode
24398 : : || d->vmode == E_V8HImode
24399 : : || d->vmode == E_V16HImode)
24400 : : {
24401 : 853 : rtx dop0_t = gen_reg_rtx (d->vmode);
24402 : 853 : rtx dop1_t = gen_reg_rtx (d->vmode);
24403 : 853 : t = gen_reg_rtx (d->vmode);
24404 : 853 : emit_move_insn (t, CONST0_RTX (d->vmode));
24405 : :
24406 : 853 : emit_move_insn (dop0_t, gen_rtx_VEC_MERGE (d->vmode, d->op0, t,
24407 : : GEN_INT (pblendw_i)));
24408 : 853 : emit_move_insn (dop1_t, gen_rtx_VEC_MERGE (d->vmode, d->op1, t,
24409 : : GEN_INT (pblendw_i)));
24410 : :
24411 : 853 : emit_move_insn (dop0, gen_lowpart (half_mode, dop0_t));
24412 : 853 : emit_move_insn (dop1, gen_lowpart (half_mode, dop1_t));
24413 : 853 : }
24414 : : else
24415 : : {
24416 : 3883 : t = gen_const_vec_duplicate (half_mode, GEN_INT (c));
24417 : 3883 : t = force_reg (half_mode, t);
24418 : 3883 : emit_insn (gen_and (dop0, t, gen_lowpart (half_mode, d->op0)));
24419 : 3883 : emit_insn (gen_and (dop1, t, gen_lowpart (half_mode, d->op1)));
24420 : : }
24421 : : }
24422 : : else
24423 : : {
24424 : 1434 : emit_insn (gen_shift (dop0,
24425 : 717 : gen_lowpart (half_mode, d->op0),
24426 : : GEN_INT (s)));
24427 : 1434 : emit_insn (gen_shift (dop1,
24428 : 717 : gen_lowpart (half_mode, d->op1),
24429 : : GEN_INT (s)));
24430 : : }
24431 : : /* In AVX2 for 256 bit case we need to permute pack result. */
24432 : 5453 : if (TARGET_AVX2 && end_perm)
24433 : : {
24434 : 395 : op = gen_reg_rtx (d->vmode);
24435 : 395 : t = gen_reg_rtx (V4DImode);
24436 : 395 : emit_insn (gen_pack (op, dop0, dop1));
24437 : 790 : emit_insn (gen_avx2_permv4di_1 (t,
24438 : 395 : gen_lowpart (V4DImode, op),
24439 : : const0_rtx,
24440 : : const2_rtx,
24441 : : const1_rtx,
24442 : : GEN_INT (3)));
24443 : 395 : emit_move_insn (d->target, gen_lowpart (d->vmode, t));
24444 : : }
24445 : : else
24446 : 5058 : emit_insn (gen_pack (d->target, dop0, dop1));
24447 : :
24448 : : return true;
24449 : : }
24450 : :
24451 : : /* A subroutine of expand_vec_perm_even_odd_1. Implement extract-even
24452 : : and extract-odd permutations of two V64QI operands
24453 : : with two "shifts", two "truncs" and one "concat" insns for "odd"
24454 : : and two "truncs" and one concat insn for "even."
24455 : : Have already failed all two instruction sequences. */
24456 : :
24457 : : static bool
24458 : 23474 : expand_vec_perm_even_odd_trunc (struct expand_vec_perm_d *d)
24459 : : {
24460 : 23474 : rtx t1, t2, t3, t4;
24461 : 23474 : unsigned i, odd, nelt = d->nelt;
24462 : :
24463 : 23474 : if (!TARGET_AVX512BW
24464 : 98 : || d->one_operand_p
24465 : 62 : || d->vmode != V64QImode)
24466 : : return false;
24467 : :
24468 : : /* Check that permutation is even or odd. */
24469 : 62 : odd = d->perm[0];
24470 : 62 : if (odd > 1)
24471 : : return false;
24472 : :
24473 : 1910 : for (i = 1; i < nelt; ++i)
24474 : 1884 : if (d->perm[i] != 2 * i + odd)
24475 : : return false;
24476 : :
24477 : 26 : if (d->testing_p)
24478 : : return true;
24479 : :
24480 : :
24481 : 26 : if (odd)
24482 : : {
24483 : 1 : t1 = gen_reg_rtx (V32HImode);
24484 : 1 : t2 = gen_reg_rtx (V32HImode);
24485 : 2 : emit_insn (gen_lshrv32hi3 (t1,
24486 : 1 : gen_lowpart (V32HImode, d->op0),
24487 : : GEN_INT (8)));
24488 : 2 : emit_insn (gen_lshrv32hi3 (t2,
24489 : 1 : gen_lowpart (V32HImode, d->op1),
24490 : : GEN_INT (8)));
24491 : : }
24492 : : else
24493 : : {
24494 : 25 : t1 = gen_lowpart (V32HImode, d->op0);
24495 : 25 : t2 = gen_lowpart (V32HImode, d->op1);
24496 : : }
24497 : :
24498 : 26 : t3 = gen_reg_rtx (V32QImode);
24499 : 26 : t4 = gen_reg_rtx (V32QImode);
24500 : 26 : emit_insn (gen_avx512bw_truncatev32hiv32qi2 (t3, t1));
24501 : 26 : emit_insn (gen_avx512bw_truncatev32hiv32qi2 (t4, t2));
24502 : 26 : emit_insn (gen_avx_vec_concatv64qi (d->target, t3, t4));
24503 : :
24504 : 26 : return true;
24505 : : }
24506 : :
24507 : : /* A subroutine of ix86_expand_vec_perm_const_1. Implement extract-even
24508 : : and extract-odd permutations. */
24509 : :
24510 : : static bool
24511 : 12403 : expand_vec_perm_even_odd_1 (struct expand_vec_perm_d *d, unsigned odd)
24512 : : {
24513 : 12403 : rtx t1, t2, t3, t4, t5;
24514 : :
24515 : 12403 : switch (d->vmode)
24516 : : {
24517 : 19 : case E_V4DFmode:
24518 : 19 : if (d->testing_p)
24519 : : break;
24520 : 1 : t1 = gen_reg_rtx (V4DFmode);
24521 : 1 : t2 = gen_reg_rtx (V4DFmode);
24522 : :
24523 : : /* Shuffle the lanes around into { 0 1 4 5 } and { 2 3 6 7 }. */
24524 : 1 : emit_insn (gen_avx_vperm2f128v4df3 (t1, d->op0, d->op1, GEN_INT (0x20)));
24525 : 1 : emit_insn (gen_avx_vperm2f128v4df3 (t2, d->op0, d->op1, GEN_INT (0x31)));
24526 : :
24527 : : /* Now an unpck[lh]pd will produce the result required. */
24528 : 1 : if (odd)
24529 : 0 : t3 = gen_avx_unpckhpd256 (d->target, t1, t2);
24530 : : else
24531 : 1 : t3 = gen_avx_unpcklpd256 (d->target, t1, t2);
24532 : 1 : emit_insn (t3);
24533 : 1 : break;
24534 : :
24535 : 1222 : case E_V8SFmode:
24536 : 1222 : {
24537 : 1222 : int mask = odd ? 0xdd : 0x88;
24538 : :
24539 : 1222 : if (d->testing_p)
24540 : : break;
24541 : 186 : t1 = gen_reg_rtx (V8SFmode);
24542 : 186 : t2 = gen_reg_rtx (V8SFmode);
24543 : 186 : t3 = gen_reg_rtx (V8SFmode);
24544 : :
24545 : : /* Shuffle within the 128-bit lanes to produce:
24546 : : { 0 2 8 a 4 6 c e } | { 1 3 9 b 5 7 d f }. */
24547 : 186 : emit_insn (gen_avx_shufps256 (t1, d->op0, d->op1,
24548 : : GEN_INT (mask)));
24549 : :
24550 : : /* Shuffle the lanes around to produce:
24551 : : { 4 6 c e 0 2 8 a } and { 5 7 d f 1 3 9 b }. */
24552 : 186 : emit_insn (gen_avx_vperm2f128v8sf3 (t2, t1, t1,
24553 : : GEN_INT (0x3)));
24554 : :
24555 : : /* Shuffle within the 128-bit lanes to produce:
24556 : : { 0 2 4 6 4 6 0 2 } | { 1 3 5 7 5 7 1 3 }. */
24557 : 186 : emit_insn (gen_avx_shufps256 (t3, t1, t2, GEN_INT (0x44)));
24558 : :
24559 : : /* Shuffle within the 128-bit lanes to produce:
24560 : : { 8 a c e c e 8 a } | { 9 b d f d f 9 b }. */
24561 : 186 : emit_insn (gen_avx_shufps256 (t2, t1, t2, GEN_INT (0xee)));
24562 : :
24563 : : /* Shuffle the lanes around to produce:
24564 : : { 0 2 4 6 8 a c e } | { 1 3 5 7 9 b d f }. */
24565 : 186 : emit_insn (gen_avx_vperm2f128v8sf3 (d->target, t3, t2,
24566 : : GEN_INT (0x20)));
24567 : : }
24568 : 186 : break;
24569 : :
24570 : 0 : case E_V2DFmode:
24571 : 0 : case E_V4SFmode:
24572 : 0 : case E_V2DImode:
24573 : 0 : case E_V2SImode:
24574 : 0 : case E_V4SImode:
24575 : 0 : case E_V2HImode:
24576 : : /* These are always directly implementable by expand_vec_perm_1. */
24577 : 0 : gcc_unreachable ();
24578 : :
24579 : 0 : case E_V2SFmode:
24580 : 0 : gcc_assert (TARGET_MMX_WITH_SSE);
24581 : : /* We have no suitable instructions. */
24582 : 0 : if (d->testing_p)
24583 : : return false;
24584 : : break;
24585 : :
24586 : 1395 : case E_V4QImode:
24587 : 1395 : if (TARGET_SSSE3 && !TARGET_SLOW_PSHUFB)
24588 : 0 : return expand_vec_perm_pshufb2 (d);
24589 : : else
24590 : : {
24591 : 1395 : if (d->testing_p)
24592 : : break;
24593 : : /* We need 2*log2(N)-1 operations to achieve odd/even
24594 : : with interleave. */
24595 : 195 : t1 = gen_reg_rtx (V4QImode);
24596 : 195 : emit_insn (gen_mmx_punpckhbw_low (t1, d->op0, d->op1));
24597 : 195 : emit_insn (gen_mmx_punpcklbw_low (d->target, d->op0, d->op1));
24598 : 195 : if (odd)
24599 : 38 : t2 = gen_mmx_punpckhbw_low (d->target, d->target, t1);
24600 : : else
24601 : 157 : t2 = gen_mmx_punpcklbw_low (d->target, d->target, t1);
24602 : 195 : emit_insn (t2);
24603 : : }
24604 : 195 : break;
24605 : :
24606 : 1304 : case E_V4HImode:
24607 : 1304 : if (TARGET_SSE4_1)
24608 : 90 : return expand_vec_perm_even_odd_pack (d);
24609 : 1214 : else if (TARGET_SSSE3 && !TARGET_SLOW_PSHUFB)
24610 : 20 : return expand_vec_perm_pshufb2 (d);
24611 : : else
24612 : : {
24613 : 1194 : if (d->testing_p)
24614 : : break;
24615 : : /* We need 2*log2(N)-1 operations to achieve odd/even
24616 : : with interleave. */
24617 : 492 : t1 = gen_reg_rtx (V4HImode);
24618 : 492 : emit_insn (gen_mmx_punpckhwd (t1, d->op0, d->op1));
24619 : 492 : emit_insn (gen_mmx_punpcklwd (d->target, d->op0, d->op1));
24620 : 492 : if (odd)
24621 : 8 : t2 = gen_mmx_punpckhwd (d->target, d->target, t1);
24622 : : else
24623 : 484 : t2 = gen_mmx_punpcklwd (d->target, d->target, t1);
24624 : 492 : emit_insn (t2);
24625 : : }
24626 : 492 : break;
24627 : :
24628 : 6461 : case E_V8HImode:
24629 : 6461 : if (TARGET_SSE4_1)
24630 : 435 : return expand_vec_perm_even_odd_pack (d);
24631 : 6026 : else if (TARGET_SSSE3 && !TARGET_SLOW_PSHUFB)
24632 : 1 : return expand_vec_perm_pshufb2 (d);
24633 : : else
24634 : : {
24635 : 6025 : if (d->testing_p)
24636 : : break;
24637 : : /* We need 2*log2(N)-1 operations to achieve odd/even
24638 : : with interleave. */
24639 : 2644 : t1 = gen_reg_rtx (V8HImode);
24640 : 2644 : t2 = gen_reg_rtx (V8HImode);
24641 : 2644 : emit_insn (gen_vec_interleave_highv8hi (t1, d->op0, d->op1));
24642 : 2644 : emit_insn (gen_vec_interleave_lowv8hi (d->target, d->op0, d->op1));
24643 : 2644 : emit_insn (gen_vec_interleave_highv8hi (t2, d->target, t1));
24644 : 2644 : emit_insn (gen_vec_interleave_lowv8hi (d->target, d->target, t1));
24645 : 2644 : if (odd)
24646 : 86 : t3 = gen_vec_interleave_highv8hi (d->target, d->target, t2);
24647 : : else
24648 : 2558 : t3 = gen_vec_interleave_lowv8hi (d->target, d->target, t2);
24649 : 2644 : emit_insn (t3);
24650 : : }
24651 : 2644 : break;
24652 : :
24653 : 1319 : case E_V8QImode:
24654 : 1319 : case E_V16QImode:
24655 : 1319 : return expand_vec_perm_even_odd_pack (d);
24656 : :
24657 : 448 : case E_V16HImode:
24658 : 448 : case E_V32QImode:
24659 : 448 : return expand_vec_perm_even_odd_pack (d);
24660 : :
24661 : 36 : case E_V64QImode:
24662 : 36 : return expand_vec_perm_even_odd_trunc (d);
24663 : :
24664 : 19 : case E_V4DImode:
24665 : 19 : if (!TARGET_AVX2)
24666 : : {
24667 : 19 : struct expand_vec_perm_d d_copy = *d;
24668 : 19 : d_copy.vmode = V4DFmode;
24669 : 19 : if (d->testing_p)
24670 : 18 : d_copy.target = gen_raw_REG (V4DFmode, LAST_VIRTUAL_REGISTER + 1);
24671 : : else
24672 : 1 : d_copy.target = gen_reg_rtx (V4DFmode);
24673 : 19 : d_copy.op0 = gen_lowpart (V4DFmode, d->op0);
24674 : 19 : d_copy.op1 = gen_lowpart (V4DFmode, d->op1);
24675 : 19 : if (expand_vec_perm_even_odd_1 (&d_copy, odd))
24676 : : {
24677 : 19 : if (!d->testing_p)
24678 : 1 : emit_move_insn (d->target,
24679 : 1 : gen_lowpart (V4DImode, d_copy.target));
24680 : 19 : return true;
24681 : : }
24682 : : return false;
24683 : : }
24684 : :
24685 : 0 : if (d->testing_p)
24686 : : break;
24687 : :
24688 : 0 : t1 = gen_reg_rtx (V4DImode);
24689 : 0 : t2 = gen_reg_rtx (V4DImode);
24690 : :
24691 : : /* Shuffle the lanes around into { 0 1 4 5 } and { 2 3 6 7 }. */
24692 : 0 : emit_insn (gen_avx2_permv2ti (t1, d->op0, d->op1, GEN_INT (0x20)));
24693 : 0 : emit_insn (gen_avx2_permv2ti (t2, d->op0, d->op1, GEN_INT (0x31)));
24694 : :
24695 : : /* Now an vpunpck[lh]qdq will produce the result required. */
24696 : 0 : if (odd)
24697 : 0 : t3 = gen_avx2_interleave_highv4di (d->target, t1, t2);
24698 : : else
24699 : 0 : t3 = gen_avx2_interleave_lowv4di (d->target, t1, t2);
24700 : 0 : emit_insn (t3);
24701 : 0 : break;
24702 : :
24703 : 180 : case E_V8SImode:
24704 : 180 : if (!TARGET_AVX2)
24705 : : {
24706 : 42 : struct expand_vec_perm_d d_copy = *d;
24707 : 42 : d_copy.vmode = V8SFmode;
24708 : 42 : if (d->testing_p)
24709 : 42 : d_copy.target = gen_raw_REG (V8SFmode, LAST_VIRTUAL_REGISTER + 1);
24710 : : else
24711 : 0 : d_copy.target = gen_reg_rtx (V8SFmode);
24712 : 42 : d_copy.op0 = gen_lowpart (V8SFmode, d->op0);
24713 : 42 : d_copy.op1 = gen_lowpart (V8SFmode, d->op1);
24714 : 42 : if (expand_vec_perm_even_odd_1 (&d_copy, odd))
24715 : : {
24716 : 42 : if (!d->testing_p)
24717 : 0 : emit_move_insn (d->target,
24718 : 0 : gen_lowpart (V8SImode, d_copy.target));
24719 : 42 : return true;
24720 : : }
24721 : : return false;
24722 : : }
24723 : :
24724 : 138 : if (d->testing_p)
24725 : : break;
24726 : :
24727 : 138 : t1 = gen_reg_rtx (V8SImode);
24728 : 138 : t2 = gen_reg_rtx (V8SImode);
24729 : 138 : t3 = gen_reg_rtx (V4DImode);
24730 : 138 : t4 = gen_reg_rtx (V4DImode);
24731 : 138 : t5 = gen_reg_rtx (V4DImode);
24732 : :
24733 : : /* Shuffle the lanes around into
24734 : : { 0 1 2 3 8 9 a b } and { 4 5 6 7 c d e f }. */
24735 : 276 : emit_insn (gen_avx2_permv2ti (t3, gen_lowpart (V4DImode, d->op0),
24736 : 138 : gen_lowpart (V4DImode, d->op1),
24737 : : GEN_INT (0x20)));
24738 : 276 : emit_insn (gen_avx2_permv2ti (t4, gen_lowpart (V4DImode, d->op0),
24739 : 138 : gen_lowpart (V4DImode, d->op1),
24740 : : GEN_INT (0x31)));
24741 : :
24742 : : /* Swap the 2nd and 3rd position in each lane into
24743 : : { 0 2 1 3 8 a 9 b } and { 4 6 5 7 c e d f }. */
24744 : 138 : emit_insn (gen_avx2_pshufdv3 (t1, gen_lowpart (V8SImode, t3),
24745 : : GEN_INT (2 * 4 + 1 * 16 + 3 * 64)));
24746 : 138 : emit_insn (gen_avx2_pshufdv3 (t2, gen_lowpart (V8SImode, t4),
24747 : : GEN_INT (2 * 4 + 1 * 16 + 3 * 64)));
24748 : :
24749 : : /* Now an vpunpck[lh]qdq will produce
24750 : : { 0 2 4 6 8 a c e } resp. { 1 3 5 7 9 b d f }. */
24751 : 138 : if (odd)
24752 : 0 : t3 = gen_avx2_interleave_highv4di (t5, gen_lowpart (V4DImode, t1),
24753 : 0 : gen_lowpart (V4DImode, t2));
24754 : : else
24755 : 138 : t3 = gen_avx2_interleave_lowv4di (t5, gen_lowpart (V4DImode, t1),
24756 : 138 : gen_lowpart (V4DImode, t2));
24757 : 138 : emit_insn (t3);
24758 : 138 : emit_move_insn (d->target, gen_lowpart (V8SImode, t5));
24759 : 138 : break;
24760 : :
24761 : 0 : default:
24762 : 0 : gcc_unreachable ();
24763 : : }
24764 : :
24765 : : return true;
24766 : : }
24767 : :
24768 : : /* A subroutine of ix86_expand_vec_perm_const_1. Pattern match
24769 : : extract-even and extract-odd permutations. */
24770 : :
24771 : : static bool
24772 : 23356 : expand_vec_perm_even_odd (struct expand_vec_perm_d *d)
24773 : : {
24774 : 23356 : unsigned i, odd, nelt = d->nelt;
24775 : :
24776 : 23356 : odd = d->perm[0];
24777 : 23356 : if (odd != 0 && odd != 1)
24778 : : return false;
24779 : :
24780 : 62985 : for (i = 1; i < nelt; ++i)
24781 : 55593 : if (d->perm[i] != 2 * i + odd)
24782 : : return false;
24783 : :
24784 : 7392 : if (d->vmode == E_V32HImode
24785 : 12 : && d->testing_p
24786 : 12 : && !TARGET_AVX512BW)
24787 : : return false;
24788 : :
24789 : 7380 : return expand_vec_perm_even_odd_1 (d, odd);
24790 : : }
24791 : :
24792 : : /* A subroutine of ix86_expand_vec_perm_const_1. Implement broadcast
24793 : : permutations. We assume that expand_vec_perm_1 has already failed. */
24794 : :
24795 : : static bool
24796 : 1011 : expand_vec_perm_broadcast_1 (struct expand_vec_perm_d *d)
24797 : : {
24798 : 1011 : unsigned elt = d->perm[0], nelt2 = d->nelt / 2;
24799 : 1011 : machine_mode vmode = d->vmode;
24800 : 1011 : rtx (*gen) (rtx, rtx, rtx);
24801 : 1011 : unsigned char perm2[4];
24802 : 1011 : rtx op0 = d->op0, dest;
24803 : 1011 : bool ok;
24804 : :
24805 : 1011 : switch (vmode)
24806 : : {
24807 : 0 : case E_V4DFmode:
24808 : 0 : case E_V8SFmode:
24809 : : /* These are special-cased in sse.md so that we can optionally
24810 : : use the vbroadcast instruction. They expand to two insns
24811 : : if the input happens to be in a register. */
24812 : 0 : gcc_unreachable ();
24813 : :
24814 : 0 : case E_V2DFmode:
24815 : 0 : case E_V2SFmode:
24816 : 0 : case E_V4SFmode:
24817 : 0 : case E_V2DImode:
24818 : 0 : case E_V2SImode:
24819 : 0 : case E_V4SImode:
24820 : 0 : case E_V2HImode:
24821 : 0 : case E_V4HImode:
24822 : : /* These are always implementable using standard shuffle patterns. */
24823 : 0 : gcc_unreachable ();
24824 : :
24825 : 16 : case E_V4QImode:
24826 : : /* This can be implemented via interleave and pshuflw. */
24827 : 16 : if (d->testing_p)
24828 : : return true;
24829 : :
24830 : 8 : if (elt >= nelt2)
24831 : : {
24832 : 4 : gen = gen_mmx_punpckhbw_low;
24833 : 4 : elt -= nelt2;
24834 : : }
24835 : : else
24836 : : gen = gen_mmx_punpcklbw_low;
24837 : :
24838 : 8 : dest = gen_reg_rtx (vmode);
24839 : 8 : emit_insn (gen (dest, op0, op0));
24840 : 8 : vmode = get_mode_wider_vector (vmode);
24841 : 8 : op0 = gen_lowpart (vmode, dest);
24842 : :
24843 : 8 : memset (perm2, elt, 2);
24844 : 8 : dest = gen_reg_rtx (vmode);
24845 : 8 : ok = expand_vselect (dest, op0, perm2, 2, d->testing_p);
24846 : 8 : gcc_assert (ok);
24847 : :
24848 : 8 : emit_move_insn (d->target, gen_lowpart (d->vmode, dest));
24849 : 8 : return true;
24850 : :
24851 : 4 : case E_V8QImode:
24852 : : /* This can be implemented via interleave. We save one insn by
24853 : : stopping once we have promoted to V2SImode and then use pshufd. */
24854 : 4 : if (d->testing_p)
24855 : : return true;
24856 : 4 : do
24857 : : {
24858 : 4 : if (elt >= nelt2)
24859 : : {
24860 : 1 : gen = vmode == V8QImode ? gen_mmx_punpckhbw
24861 : : : gen_mmx_punpckhwd;
24862 : 1 : elt -= nelt2;
24863 : : }
24864 : : else
24865 : 3 : gen = vmode == V8QImode ? gen_mmx_punpcklbw
24866 : : : gen_mmx_punpcklwd;
24867 : 4 : nelt2 /= 2;
24868 : :
24869 : 4 : dest = gen_reg_rtx (vmode);
24870 : 4 : emit_insn (gen (dest, op0, op0));
24871 : 4 : vmode = get_mode_wider_vector (vmode);
24872 : 4 : op0 = gen_lowpart (vmode, dest);
24873 : : }
24874 : 4 : while (vmode != V2SImode);
24875 : :
24876 : 2 : memset (perm2, elt, 2);
24877 : 2 : dest = gen_reg_rtx (vmode);
24878 : 2 : ok = expand_vselect (dest, op0, perm2, 2, d->testing_p);
24879 : 2 : gcc_assert (ok);
24880 : :
24881 : 2 : emit_move_insn (d->target, gen_lowpart (d->vmode, dest));
24882 : 2 : return true;
24883 : :
24884 : 982 : case E_V8HImode:
24885 : 982 : case E_V16QImode:
24886 : : /* These can be implemented via interleave. We save one insn by
24887 : : stopping once we have promoted to V4SImode and then use pshufd. */
24888 : 982 : if (d->testing_p)
24889 : : return true;
24890 : 1536 : do
24891 : : {
24892 : 1536 : if (elt >= nelt2)
24893 : : {
24894 : 16 : gen = vmode == V16QImode ? gen_vec_interleave_highv16qi
24895 : : : gen_vec_interleave_highv8hi;
24896 : 16 : elt -= nelt2;
24897 : : }
24898 : : else
24899 : 1520 : gen = vmode == V16QImode ? gen_vec_interleave_lowv16qi
24900 : : : gen_vec_interleave_lowv8hi;
24901 : 1536 : nelt2 /= 2;
24902 : :
24903 : 1536 : dest = gen_reg_rtx (vmode);
24904 : 1536 : emit_insn (gen (dest, op0, op0));
24905 : 1536 : vmode = get_mode_wider_vector (vmode);
24906 : 1536 : op0 = gen_lowpart (vmode, dest);
24907 : : }
24908 : 1536 : while (vmode != V4SImode);
24909 : :
24910 : 918 : memset (perm2, elt, 4);
24911 : 918 : dest = gen_reg_rtx (vmode);
24912 : 918 : ok = expand_vselect (dest, op0, perm2, 4, d->testing_p);
24913 : 918 : gcc_assert (ok);
24914 : :
24915 : 918 : emit_move_insn (d->target, gen_lowpart (d->vmode, dest));
24916 : 918 : return true;
24917 : :
24918 : 1 : case E_V8HFmode:
24919 : 1 : case E_V8BFmode:
24920 : : /* This can be implemented via interleave and pshufd. */
24921 : 1 : if (d->testing_p)
24922 : : return true;
24923 : :
24924 : 1 : rtx (*gen_interleave) (machine_mode, rtx, rtx, rtx);
24925 : 1 : if (elt >= nelt2)
24926 : : {
24927 : 0 : gen_interleave = gen_vec_interleave_high;
24928 : 0 : elt -= nelt2;
24929 : : }
24930 : : else
24931 : : gen_interleave = gen_vec_interleave_low;
24932 : 1 : nelt2 /= 2;
24933 : :
24934 : 1 : dest = gen_reg_rtx (vmode);
24935 : 1 : emit_insn (gen_interleave (vmode, dest, op0, op0));
24936 : :
24937 : 1 : vmode = V4SImode;
24938 : 1 : op0 = gen_lowpart (vmode, dest);
24939 : :
24940 : 1 : memset (perm2, elt, 4);
24941 : 1 : dest = gen_reg_rtx (vmode);
24942 : 1 : ok = expand_vselect (dest, op0, perm2, 4, d->testing_p);
24943 : 1 : gcc_assert (ok);
24944 : :
24945 : 1 : emit_move_insn (d->target, gen_lowpart (d->vmode, dest));
24946 : 1 : return true;
24947 : :
24948 : 0 : case E_V32QImode:
24949 : 0 : case E_V16HImode:
24950 : 0 : case E_V8SImode:
24951 : 0 : case E_V4DImode:
24952 : : /* For AVX2 broadcasts of the first element vpbroadcast* or
24953 : : vpermq should be used by expand_vec_perm_1. */
24954 : 0 : gcc_assert (!TARGET_AVX2 || d->perm[0]);
24955 : : return false;
24956 : :
24957 : 6 : case E_V64QImode:
24958 : 6 : gcc_assert (!TARGET_AVX512BW || d->perm[0]);
24959 : : return false;
24960 : :
24961 : 2 : case E_V32HImode:
24962 : 2 : gcc_assert (!TARGET_AVX512BW);
24963 : : return false;
24964 : :
24965 : 0 : default:
24966 : 0 : gcc_unreachable ();
24967 : : }
24968 : : }
24969 : :
24970 : : /* A subroutine of ix86_expand_vec_perm_const_1. Pattern match
24971 : : broadcast permutations. */
24972 : :
24973 : : static bool
24974 : 90611 : expand_vec_perm_broadcast (struct expand_vec_perm_d *d)
24975 : : {
24976 : 90611 : unsigned i, elt, nelt = d->nelt;
24977 : :
24978 : 90611 : if (!d->one_operand_p)
24979 : : return false;
24980 : :
24981 : 5321 : elt = d->perm[0];
24982 : 8104 : for (i = 1; i < nelt; ++i)
24983 : 7996 : if (d->perm[i] != elt)
24984 : : return false;
24985 : :
24986 : 108 : return expand_vec_perm_broadcast_1 (d);
24987 : : }
24988 : :
24989 : : /* Implement arbitrary permutations of two V64QImode operands
24990 : : with 2 vperm[it]2w, 2 vpshufb and one vpor instruction. */
24991 : : static bool
24992 : 23428 : expand_vec_perm_vpermt2_vpshub2 (struct expand_vec_perm_d *d)
24993 : : {
24994 : 23428 : if (!TARGET_AVX512BW || !(d->vmode == V64QImode))
24995 : : return false;
24996 : :
24997 : 72 : if (d->testing_p)
24998 : : return true;
24999 : :
25000 : 72 : struct expand_vec_perm_d ds[2];
25001 : 72 : rtx rperm[128], vperm, target0, target1;
25002 : 72 : unsigned int i, nelt;
25003 : 72 : machine_mode vmode;
25004 : :
25005 : 72 : nelt = d->nelt;
25006 : 72 : vmode = V64QImode;
25007 : :
25008 : 216 : for (i = 0; i < 2; i++)
25009 : : {
25010 : 144 : ds[i] = *d;
25011 : 144 : ds[i].vmode = V32HImode;
25012 : 144 : ds[i].nelt = 32;
25013 : 144 : ds[i].target = gen_reg_rtx (V32HImode);
25014 : 144 : ds[i].op0 = gen_lowpart (V32HImode, d->op0);
25015 : 144 : ds[i].op1 = gen_lowpart (V32HImode, d->op1);
25016 : : }
25017 : :
25018 : : /* Prepare permutations such that the first one takes care of
25019 : : putting the even bytes into the right positions or one higher
25020 : : positions (ds[0]) and the second one takes care of
25021 : : putting the odd bytes into the right positions or one below
25022 : : (ds[1]). */
25023 : :
25024 : 4680 : for (i = 0; i < nelt; i++)
25025 : : {
25026 : 4608 : ds[i & 1].perm[i / 2] = d->perm[i] / 2;
25027 : 4608 : if (i & 1)
25028 : : {
25029 : 2304 : rperm[i] = constm1_rtx;
25030 : 2304 : rperm[i + 64] = GEN_INT ((i & 14) + (d->perm[i] & 1));
25031 : : }
25032 : : else
25033 : : {
25034 : 2304 : rperm[i] = GEN_INT ((i & 14) + (d->perm[i] & 1));
25035 : 2304 : rperm[i + 64] = constm1_rtx;
25036 : : }
25037 : : }
25038 : :
25039 : 72 : bool ok = expand_vec_perm_1 (&ds[0]);
25040 : 72 : gcc_assert (ok);
25041 : 72 : ds[0].target = gen_lowpart (V64QImode, ds[0].target);
25042 : :
25043 : 72 : ok = expand_vec_perm_1 (&ds[1]);
25044 : 72 : gcc_assert (ok);
25045 : 72 : ds[1].target = gen_lowpart (V64QImode, ds[1].target);
25046 : :
25047 : 72 : vperm = gen_rtx_CONST_VECTOR (V64QImode, gen_rtvec_v (64, rperm));
25048 : 72 : vperm = force_reg (vmode, vperm);
25049 : 72 : target0 = gen_reg_rtx (V64QImode);
25050 : 72 : emit_insn (gen_avx512bw_pshufbv64qi3 (target0, ds[0].target, vperm));
25051 : :
25052 : 72 : vperm = gen_rtx_CONST_VECTOR (V64QImode, gen_rtvec_v (64, rperm + 64));
25053 : 72 : vperm = force_reg (vmode, vperm);
25054 : 72 : target1 = gen_reg_rtx (V64QImode);
25055 : 72 : emit_insn (gen_avx512bw_pshufbv64qi3 (target1, ds[1].target, vperm));
25056 : :
25057 : 72 : emit_insn (gen_iorv64qi3 (d->target, target0, target1));
25058 : 72 : return true;
25059 : : }
25060 : :
25061 : : /* Implement arbitrary permutation of two V32QImode and V16QImode operands
25062 : : with 4 vpshufb insns, 2 vpermq and 3 vpor. We should have already failed
25063 : : all the shorter instruction sequences. */
25064 : :
25065 : : static bool
25066 : 15826 : expand_vec_perm_vpshufb4_vpermq2 (struct expand_vec_perm_d *d)
25067 : : {
25068 : 15826 : rtx rperm[4][32], vperm, l[2], h[2], op, m128;
25069 : 15826 : unsigned int i, nelt, eltsz;
25070 : 15826 : bool used[4];
25071 : :
25072 : 15826 : if (!TARGET_AVX2
25073 : 322 : || d->one_operand_p
25074 : 193 : || (d->vmode != V32QImode && d->vmode != V16HImode))
25075 : : return false;
25076 : :
25077 : 54 : if (d->testing_p)
25078 : : return true;
25079 : :
25080 : 54 : nelt = d->nelt;
25081 : 54 : eltsz = GET_MODE_UNIT_SIZE (d->vmode);
25082 : :
25083 : : /* Generate 4 permutation masks. If the required element is within
25084 : : the same lane, it is shuffled in. If the required element from the
25085 : : other lane, force a zero by setting bit 7 in the permutation mask.
25086 : : In the other mask the mask has non-negative elements if element
25087 : : is requested from the other lane, but also moved to the other lane,
25088 : : so that the result of vpshufb can have the two V2TImode halves
25089 : : swapped. */
25090 : 54 : m128 = GEN_INT (-128);
25091 : 1836 : for (i = 0; i < 32; ++i)
25092 : : {
25093 : 1728 : rperm[0][i] = m128;
25094 : 1728 : rperm[1][i] = m128;
25095 : 1728 : rperm[2][i] = m128;
25096 : 1728 : rperm[3][i] = m128;
25097 : : }
25098 : 54 : used[0] = false;
25099 : 54 : used[1] = false;
25100 : 54 : used[2] = false;
25101 : 54 : used[3] = false;
25102 : 1590 : for (i = 0; i < nelt; ++i)
25103 : : {
25104 : 1536 : unsigned j, e = d->perm[i] & (nelt / 2 - 1);
25105 : 1536 : unsigned xlane = ((d->perm[i] ^ i) & (nelt / 2)) * eltsz;
25106 : 2074 : unsigned int which = ((d->perm[i] & nelt) ? 2 : 0) + (xlane ? 1 : 0);
25107 : :
25108 : 3264 : for (j = 0; j < eltsz; ++j)
25109 : 1728 : rperm[which][(i * eltsz + j) ^ xlane] = GEN_INT (e * eltsz + j);
25110 : 1536 : used[which] = true;
25111 : : }
25112 : :
25113 : 162 : for (i = 0; i < 2; ++i)
25114 : : {
25115 : 108 : if (!used[2 * i + 1])
25116 : : {
25117 : 22 : h[i] = NULL_RTX;
25118 : 22 : continue;
25119 : : }
25120 : 86 : vperm = gen_rtx_CONST_VECTOR (V32QImode,
25121 : 86 : gen_rtvec_v (32, rperm[2 * i + 1]));
25122 : 86 : vperm = force_reg (V32QImode, vperm);
25123 : 86 : h[i] = gen_reg_rtx (V32QImode);
25124 : 86 : op = gen_lowpart (V32QImode, i ? d->op1 : d->op0);
25125 : 86 : emit_insn (gen_avx2_pshufbv32qi3 (h[i], op, vperm));
25126 : : }
25127 : :
25128 : : /* Swap the 128-byte lanes of h[X]. */
25129 : 162 : for (i = 0; i < 2; ++i)
25130 : : {
25131 : 108 : if (h[i] == NULL_RTX)
25132 : 22 : continue;
25133 : 86 : op = gen_reg_rtx (V4DImode);
25134 : 86 : emit_insn (gen_avx2_permv4di_1 (op, gen_lowpart (V4DImode, h[i]),
25135 : : const2_rtx, GEN_INT (3), const0_rtx,
25136 : : const1_rtx));
25137 : 86 : h[i] = gen_lowpart (V32QImode, op);
25138 : : }
25139 : :
25140 : 162 : for (i = 0; i < 2; ++i)
25141 : : {
25142 : 108 : if (!used[2 * i])
25143 : : {
25144 : 0 : l[i] = NULL_RTX;
25145 : 0 : continue;
25146 : : }
25147 : 108 : vperm = gen_rtx_CONST_VECTOR (V32QImode, gen_rtvec_v (32, rperm[2 * i]));
25148 : 108 : vperm = force_reg (V32QImode, vperm);
25149 : 108 : l[i] = gen_reg_rtx (V32QImode);
25150 : 108 : op = gen_lowpart (V32QImode, i ? d->op1 : d->op0);
25151 : 108 : emit_insn (gen_avx2_pshufbv32qi3 (l[i], op, vperm));
25152 : : }
25153 : :
25154 : 162 : for (i = 0; i < 2; ++i)
25155 : : {
25156 : 108 : if (h[i] && l[i])
25157 : : {
25158 : 86 : op = gen_reg_rtx (V32QImode);
25159 : 86 : emit_insn (gen_iorv32qi3 (op, l[i], h[i]));
25160 : 86 : l[i] = op;
25161 : : }
25162 : 22 : else if (h[i])
25163 : 0 : l[i] = h[i];
25164 : : }
25165 : :
25166 : 54 : gcc_assert (l[0] && l[1]);
25167 : 54 : op = d->target;
25168 : 54 : if (d->vmode != V32QImode)
25169 : 12 : op = gen_reg_rtx (V32QImode);
25170 : 54 : emit_insn (gen_iorv32qi3 (op, l[0], l[1]));
25171 : 54 : if (op != d->target)
25172 : 12 : emit_move_insn (d->target, gen_lowpart (d->vmode, op));
25173 : : return true;
25174 : : }
25175 : :
25176 : : /* The guts of ix86_vectorize_vec_perm_const. With all of the interface bits
25177 : : taken care of, perform the expansion in D and return true on success. */
25178 : :
25179 : : static bool
25180 : 303169 : ix86_expand_vec_perm_const_1 (struct expand_vec_perm_d *d)
25181 : : {
25182 : : /* Try a single instruction expansion. */
25183 : 303169 : if (expand_vec_perm_1 (d))
25184 : : return true;
25185 : :
25186 : : /* Try sequences of two instructions. */
25187 : :
25188 : 102482 : if (expand_vec_perm_pshuflw_pshufhw (d))
25189 : : return true;
25190 : :
25191 : 100019 : if (expand_vec_perm_palignr (d, false))
25192 : : return true;
25193 : :
25194 : 96884 : if (expand_vec_perm_interleave2 (d))
25195 : : return true;
25196 : :
25197 : 90611 : if (expand_vec_perm_broadcast (d))
25198 : : return true;
25199 : :
25200 : 90511 : if (expand_vec_perm_vpermq_perm_1 (d))
25201 : : return true;
25202 : :
25203 : 90511 : if (expand_vec_perm_vperm2f128 (d))
25204 : : return true;
25205 : :
25206 : 90447 : if (expand_vec_perm_pblendv (d))
25207 : : return true;
25208 : :
25209 : 88748 : if (expand_vec_perm_2perm_interleave (d, true))
25210 : : return true;
25211 : :
25212 : 88388 : if (expand_vec_perm_2perm_pblendv (d, true))
25213 : : return true;
25214 : :
25215 : 85338 : if (expand_vec_perm_shufps_shufps (d))
25216 : : return true;
25217 : :
25218 : 47628 : if (expand_vec_perm_punpckldq_pshuf (d))
25219 : : return true;
25220 : :
25221 : : /* Try sequences of three instructions. */
25222 : :
25223 : 42903 : if (expand_vec_perm_even_odd_pack (d))
25224 : : return true;
25225 : :
25226 : 29316 : if (expand_vec_perm_2vperm2f128_vshuf (d))
25227 : : return true;
25228 : :
25229 : 28039 : if (expand_vec_perm_pshufb2 (d))
25230 : : return true;
25231 : :
25232 : 27378 : if (expand_vec_perm_pslldq_psrldq_por (d, false))
25233 : : return true;
25234 : :
25235 : 27139 : if (expand_vec_perm_interleave3 (d))
25236 : : return true;
25237 : :
25238 : 27001 : if (expand_vec_perm_vperm2f128_vblend (d))
25239 : : return true;
25240 : :
25241 : 27001 : if (expand_vec_perm_2perm_interleave (d, false))
25242 : : return true;
25243 : :
25244 : 26761 : if (expand_vec_perm_2perm_pblendv (d, false))
25245 : : return true;
25246 : :
25247 : 25893 : if (expand_vec_perm_psrlw_psllw_por (d))
25248 : : return true;
25249 : :
25250 : 24455 : if (expand_vec_perm_pand_pandn_por (d))
25251 : : return true;
25252 : :
25253 : : /* Try sequences of four instructions. */
25254 : :
25255 : 23438 : if (expand_vec_perm_even_odd_trunc (d))
25256 : : return true;
25257 : 23434 : if (expand_vec_perm_vpshufb2_vpermq (d))
25258 : : return true;
25259 : :
25260 : 23428 : if (expand_vec_perm_vpshufb2_vpermq_even_odd (d))
25261 : : return true;
25262 : :
25263 : 23428 : if (expand_vec_perm_vpermt2_vpshub2 (d))
25264 : : return true;
25265 : :
25266 : : /* ??? Look for narrow permutations whose element orderings would
25267 : : allow the promotion to a wider mode. */
25268 : :
25269 : : /* ??? Look for sequences of interleave or a wider permute that place
25270 : : the data into the correct lanes for a half-vector shuffle like
25271 : : pshuf[lh]w or vpermilps. */
25272 : :
25273 : : /* ??? Look for sequences of interleave that produce the desired results.
25274 : : The combinatorics of punpck[lh] get pretty ugly... */
25275 : :
25276 : 23356 : if (expand_vec_perm_even_odd (d))
25277 : : return true;
25278 : :
25279 : : /* Generate four or five instructions. */
25280 : 16050 : if (expand_vec_perm_pslldq_psrldq_por (d, true))
25281 : : return true;
25282 : :
25283 : : /* Even longer sequences. */
25284 : 15826 : if (expand_vec_perm_vpshufb4_vpermq2 (d))
25285 : : return true;
25286 : :
25287 : : /* See if we can get the same permutation in different vector integer
25288 : : mode. */
25289 : 15772 : struct expand_vec_perm_d nd;
25290 : 15772 : if (canonicalize_vector_int_perm (d, &nd) && expand_vec_perm_1 (&nd))
25291 : : {
25292 : 0 : if (!d->testing_p)
25293 : 0 : emit_move_insn (d->target, gen_lowpart (d->vmode, nd.target));
25294 : 0 : return true;
25295 : : }
25296 : :
25297 : : /* Even longer, including recursion to ix86_expand_vec_perm_const_1. */
25298 : 15772 : if (expand_vec_perm2_vperm2f128_vblend (d))
25299 : : return true;
25300 : :
25301 : : return false;
25302 : : }
25303 : :
25304 : : /* If a permutation only uses one operand, make it clear. Returns true
25305 : : if the permutation references both operands. */
25306 : :
25307 : : static bool
25308 : 72018 : canonicalize_perm (struct expand_vec_perm_d *d)
25309 : : {
25310 : 72018 : int i, which, nelt = d->nelt;
25311 : :
25312 : 438036 : for (i = which = 0; i < nelt; ++i)
25313 : 497048 : which |= (d->perm[i] < nelt ? 1 : 2);
25314 : :
25315 : 72018 : d->one_operand_p = true;
25316 : 72018 : switch (which)
25317 : : {
25318 : 0 : default:
25319 : 0 : gcc_unreachable();
25320 : :
25321 : 53477 : case 3:
25322 : 53477 : if (!rtx_equal_p (d->op0, d->op1))
25323 : : {
25324 : 53426 : d->one_operand_p = false;
25325 : 53426 : break;
25326 : : }
25327 : : /* The elements of PERM do not suggest that only the first operand
25328 : : is used, but both operands are identical. Allow easier matching
25329 : : of the permutation by folding the permutation into the single
25330 : : input vector. */
25331 : : /* FALLTHRU */
25332 : :
25333 : : case 2:
25334 : 2913 : for (i = 0; i < nelt; ++i)
25335 : 2576 : d->perm[i] &= nelt - 1;
25336 : 337 : d->op0 = d->op1;
25337 : 337 : break;
25338 : :
25339 : 18255 : case 1:
25340 : 18255 : d->op1 = d->op0;
25341 : 18255 : break;
25342 : : }
25343 : :
25344 : 72018 : return (which == 3);
25345 : : }
25346 : :
25347 : : /* Implement TARGET_VECTORIZE_VEC_PERM_CONST. */
25348 : :
25349 : : bool
25350 : 809139 : ix86_vectorize_vec_perm_const (machine_mode vmode, machine_mode op_mode,
25351 : : rtx target, rtx op0, rtx op1,
25352 : : const vec_perm_indices &sel)
25353 : : {
25354 : 809139 : if (vmode != op_mode)
25355 : : return false;
25356 : :
25357 : 807549 : struct expand_vec_perm_d d;
25358 : 807549 : unsigned char perm[MAX_VECT_LEN];
25359 : 807549 : unsigned int i, nelt, which;
25360 : 807549 : bool two_args;
25361 : :
25362 : : /* For HF and BF mode vector, convert it to HI using subreg. */
25363 : 2422189 : if (GET_MODE_INNER (vmode) == HFmode || GET_MODE_INNER (vmode) == BFmode)
25364 : : {
25365 : 484 : machine_mode orig_mode = vmode;
25366 : 968 : vmode = mode_for_vector (HImode,
25367 : 484 : GET_MODE_NUNITS (vmode)).require ();
25368 : 484 : if (target)
25369 : 441 : target = lowpart_subreg (vmode, target, orig_mode);
25370 : 484 : if (op0)
25371 : 441 : op0 = lowpart_subreg (vmode, op0, orig_mode);
25372 : 484 : if (op1)
25373 : 441 : op1 = lowpart_subreg (vmode, op1, orig_mode);
25374 : : }
25375 : :
25376 : 807549 : d.target = target;
25377 : 807549 : d.op0 = op0;
25378 : 807549 : d.op1 = op1;
25379 : :
25380 : 807549 : d.vmode = vmode;
25381 : 807549 : gcc_assert (VECTOR_MODE_P (d.vmode));
25382 : 807549 : d.nelt = nelt = GET_MODE_NUNITS (d.vmode);
25383 : 807549 : d.testing_p = !target;
25384 : :
25385 : 807549 : gcc_assert (sel.length () == nelt);
25386 : 807549 : gcc_checking_assert (sizeof (d.perm) == sizeof (perm));
25387 : :
25388 : : /* Given sufficient ISA support we can just return true here
25389 : : for selected vector modes. */
25390 : 807549 : switch (d.vmode)
25391 : : {
25392 : 2007 : case E_V16SFmode:
25393 : 2007 : case E_V16SImode:
25394 : 2007 : case E_V8DImode:
25395 : 2007 : case E_V8DFmode:
25396 : 2007 : if (!TARGET_AVX512F)
25397 : : return false;
25398 : : /* All implementable with a single vperm[it]2 insn. */
25399 : 2007 : if (d.testing_p)
25400 : : return true;
25401 : : break;
25402 : 323 : case E_V32HImode:
25403 : 323 : if (!TARGET_AVX512F)
25404 : : return false;
25405 : 323 : if (d.testing_p && TARGET_AVX512BW)
25406 : : /* All implementable with a single vperm[it]2 insn. */
25407 : : return true;
25408 : : break;
25409 : 714 : case E_V64QImode:
25410 : 714 : if (!TARGET_AVX512F)
25411 : : return false;
25412 : 714 : if (d.testing_p && TARGET_AVX512BW)
25413 : : /* Implementable with 2 vperm[it]2, 2 vpshufb and 1 or insn. */
25414 : : return true;
25415 : : break;
25416 : 12738 : case E_V8SImode:
25417 : 12738 : case E_V8SFmode:
25418 : 12738 : case E_V4DFmode:
25419 : 12738 : case E_V4DImode:
25420 : 12738 : if (!TARGET_AVX)
25421 : : return false;
25422 : 12738 : if (d.testing_p && TARGET_AVX512VL)
25423 : : /* All implementable with a single vperm[it]2 insn. */
25424 : : return true;
25425 : : break;
25426 : 614 : case E_V16HImode:
25427 : 614 : if (!TARGET_SSE2)
25428 : : return false;
25429 : 614 : if (d.testing_p && TARGET_AVX2)
25430 : : /* Implementable with 4 vpshufb insns, 2 vpermq and 3 vpor insns. */
25431 : : return true;
25432 : : break;
25433 : 688 : case E_V32QImode:
25434 : 688 : if (!TARGET_SSE2)
25435 : : return false;
25436 : 688 : if (d.testing_p && TARGET_AVX2)
25437 : : /* Implementable with 4 vpshufb insns, 2 vpermq and 3 vpor insns. */
25438 : : return true;
25439 : : break;
25440 : 37593 : case E_V8HImode:
25441 : 37593 : case E_V16QImode:
25442 : 37593 : if (!TARGET_SSE2)
25443 : : return false;
25444 : : /* Fall through. */
25445 : 236729 : case E_V4SImode:
25446 : 236729 : case E_V4SFmode:
25447 : 236729 : if (!TARGET_SSE)
25448 : : return false;
25449 : : /* All implementable with a single vpperm insn. */
25450 : 236729 : if (d.testing_p && TARGET_XOP)
25451 : : return true;
25452 : : /* All implementable with 2 pshufb + 1 ior. */
25453 : 236623 : if (d.testing_p && TARGET_SSSE3)
25454 : : return true;
25455 : : break;
25456 : 136139 : case E_V2SFmode:
25457 : 136139 : case E_V2SImode:
25458 : 136139 : case E_V4HImode:
25459 : 136139 : case E_V8QImode:
25460 : 136139 : if (!TARGET_MMX_WITH_SSE)
25461 : : return false;
25462 : : break;
25463 : 24990 : case E_V2HImode:
25464 : 24990 : if (!TARGET_SSE2)
25465 : : return false;
25466 : : /* All implementable with *punpckwd. */
25467 : 24990 : if (d.testing_p)
25468 : : return true;
25469 : : break;
25470 : 10166 : case E_V4QImode:
25471 : 10166 : if (!TARGET_SSE2)
25472 : : return false;
25473 : : break;
25474 : 380544 : case E_V2DImode:
25475 : 380544 : case E_V2DFmode:
25476 : 380544 : if (!TARGET_SSE)
25477 : : return false;
25478 : : /* All implementable with shufpd or unpck[lh]pd. */
25479 : 380544 : if (d.testing_p)
25480 : : return true;
25481 : : break;
25482 : : default:
25483 : : return false;
25484 : : }
25485 : :
25486 : 2209542 : for (i = which = 0; i < nelt; ++i)
25487 : : {
25488 : 1808528 : unsigned char e = sel[i];
25489 : 1808528 : gcc_assert (e < 2 * nelt);
25490 : 1808528 : d.perm[i] = e;
25491 : 1808528 : perm[i] = e;
25492 : 2450539 : which |= (e < nelt ? 1 : 2);
25493 : : }
25494 : :
25495 : 401014 : if (d.testing_p)
25496 : : {
25497 : : /* For all elements from second vector, fold the elements to first. */
25498 : 330644 : if (which == 2)
25499 : 1345 : for (i = 0; i < nelt; ++i)
25500 : 1240 : d.perm[i] -= nelt;
25501 : :
25502 : : /* Check whether the mask can be applied to the vector type. */
25503 : 330644 : d.one_operand_p = (which != 3);
25504 : :
25505 : : /* Implementable with shufps, pshufd or pshuflw. */
25506 : 330644 : if (d.one_operand_p
25507 : : && (d.vmode == V4SFmode || d.vmode == V2SFmode
25508 : : || d.vmode == V4SImode || d.vmode == V2SImode
25509 : : || d.vmode == V4HImode || d.vmode == V2HImode))
25510 : : return true;
25511 : :
25512 : : /* Otherwise we have to go through the motions and see if we can
25513 : : figure out how to generate the requested permutation. */
25514 : 228321 : d.target = gen_raw_REG (d.vmode, LAST_VIRTUAL_REGISTER + 1);
25515 : 228321 : d.op1 = d.op0 = gen_raw_REG (d.vmode, LAST_VIRTUAL_REGISTER + 2);
25516 : 228321 : if (!d.one_operand_p)
25517 : 214501 : d.op1 = gen_raw_REG (d.vmode, LAST_VIRTUAL_REGISTER + 3);
25518 : :
25519 : 228321 : start_sequence ();
25520 : 228321 : bool ret = ix86_expand_vec_perm_const_1 (&d);
25521 : 228321 : end_sequence ();
25522 : :
25523 : 228321 : return ret;
25524 : : }
25525 : :
25526 : 70370 : two_args = canonicalize_perm (&d);
25527 : :
25528 : : /* If one of the operands is a zero vector, try to match pmovzx. */
25529 : 70370 : if (two_args && (d.op0 == CONST0_RTX (vmode) || d.op1 == CONST0_RTX (vmode)))
25530 : : {
25531 : 573 : struct expand_vec_perm_d dzero = d;
25532 : 573 : if (d.op0 == CONST0_RTX (vmode))
25533 : : {
25534 : 387 : d.op1 = dzero.op1 = force_reg (vmode, d.op1);
25535 : 387 : std::swap (dzero.op0, dzero.op1);
25536 : 7527 : for (i = 0; i < nelt; ++i)
25537 : 7140 : dzero.perm[i] ^= nelt;
25538 : : }
25539 : : else
25540 : 186 : d.op0 = dzero.op0 = force_reg (vmode, d.op0);
25541 : :
25542 : 573 : if (expand_vselect_vconcat (dzero.target, dzero.op0, dzero.op1,
25543 : 573 : dzero.perm, nelt, dzero.testing_p))
25544 : 116 : return true;
25545 : : }
25546 : :
25547 : : /* Force operands into registers. */
25548 : 70254 : rtx nop0 = force_reg (vmode, d.op0);
25549 : 70254 : if (d.op0 == d.op1)
25550 : 18095 : d.op1 = nop0;
25551 : 70254 : d.op0 = nop0;
25552 : 70254 : d.op1 = force_reg (vmode, d.op1);
25553 : :
25554 : 70254 : if (ix86_expand_vec_perm_const_1 (&d))
25555 : : return true;
25556 : :
25557 : : /* If the selector says both arguments are needed, but the operands are the
25558 : : same, the above tried to expand with one_operand_p and flattened selector.
25559 : : If that didn't work, retry without one_operand_p; we succeeded with that
25560 : : during testing. */
25561 : 22 : if (two_args && d.one_operand_p)
25562 : : {
25563 : 22 : d.one_operand_p = false;
25564 : 22 : memcpy (d.perm, perm, sizeof (perm));
25565 : 22 : return ix86_expand_vec_perm_const_1 (&d);
25566 : : }
25567 : :
25568 : : return false;
25569 : : }
25570 : :
25571 : : void
25572 : 8125 : ix86_expand_vec_extract_even_odd (rtx targ, rtx op0, rtx op1, unsigned odd)
25573 : : {
25574 : 8125 : struct expand_vec_perm_d d;
25575 : 8125 : unsigned i, nelt;
25576 : :
25577 : 8125 : d.target = targ;
25578 : 8125 : d.op0 = op0;
25579 : 8125 : d.op1 = op1;
25580 : 8125 : d.vmode = GET_MODE (targ);
25581 : 8125 : d.nelt = nelt = GET_MODE_NUNITS (d.vmode);
25582 : 8125 : d.one_operand_p = false;
25583 : 8125 : d.testing_p = false;
25584 : :
25585 : 77037 : for (i = 0; i < nelt; ++i)
25586 : 68912 : d.perm[i] = i * 2 + odd;
25587 : :
25588 : : /* We'll either be able to implement the permutation directly... */
25589 : 8125 : if (expand_vec_perm_1 (&d))
25590 : 3163 : return;
25591 : :
25592 : : /* ... or we use the special-case patterns. */
25593 : 4962 : expand_vec_perm_even_odd_1 (&d, odd);
25594 : : }
25595 : :
25596 : : static void
25597 : 916 : ix86_expand_vec_interleave (rtx targ, rtx op0, rtx op1, bool high_p)
25598 : : {
25599 : 916 : struct expand_vec_perm_d d;
25600 : 916 : unsigned i, nelt, base;
25601 : 916 : bool ok;
25602 : :
25603 : 916 : d.target = targ;
25604 : 916 : d.op0 = op0;
25605 : 916 : d.op1 = op1;
25606 : 916 : d.vmode = GET_MODE (targ);
25607 : 916 : d.nelt = nelt = GET_MODE_NUNITS (d.vmode);
25608 : 916 : d.one_operand_p = false;
25609 : 916 : d.testing_p = false;
25610 : :
25611 : 916 : base = high_p ? nelt / 2 : 0;
25612 : 3612 : for (i = 0; i < nelt / 2; ++i)
25613 : : {
25614 : 2696 : d.perm[i * 2] = i + base;
25615 : 2696 : d.perm[i * 2 + 1] = i + base + nelt;
25616 : : }
25617 : :
25618 : : /* Note that for AVX this isn't one instruction. */
25619 : 916 : ok = ix86_expand_vec_perm_const_1 (&d);
25620 : 916 : gcc_assert (ok);
25621 : 916 : }
25622 : :
25623 : : /* Expand a vector operation shift by constant for a V*QImode in terms of the
25624 : : same operation on V*HImode. Return true if success. */
25625 : : static bool
25626 : 378 : ix86_expand_vec_shift_qihi_constant (enum rtx_code code,
25627 : : rtx dest, rtx op1, rtx op2)
25628 : : {
25629 : 378 : machine_mode qimode, himode;
25630 : 378 : HOST_WIDE_INT and_constant, xor_constant;
25631 : 378 : HOST_WIDE_INT shift_amount;
25632 : 378 : rtx vec_const_and, vec_const_xor;
25633 : 378 : rtx tmp, op1_subreg;
25634 : 378 : rtx (*gen_shift) (rtx, rtx, rtx);
25635 : 378 : rtx (*gen_and) (rtx, rtx, rtx);
25636 : 378 : rtx (*gen_xor) (rtx, rtx, rtx);
25637 : 378 : rtx (*gen_sub) (rtx, rtx, rtx);
25638 : :
25639 : : /* Only optimize shift by constant. */
25640 : 378 : if (!CONST_INT_P (op2))
25641 : : return false;
25642 : :
25643 : 378 : qimode = GET_MODE (dest);
25644 : 378 : shift_amount = INTVAL (op2);
25645 : : /* Do nothing when shift amount greater equal 8. */
25646 : 378 : if (shift_amount > 7)
25647 : : return false;
25648 : :
25649 : 378 : gcc_assert (code == ASHIFT || code == ASHIFTRT || code == LSHIFTRT);
25650 : :
25651 : :
25652 : 378 : if (shift_amount == 7
25653 : 378 : && code == ASHIFTRT)
25654 : : {
25655 : 32 : if (qimode == V16QImode
25656 : 10 : || qimode == V32QImode)
25657 : : {
25658 : 31 : rtx zero = gen_reg_rtx (qimode);
25659 : 31 : emit_move_insn (zero, CONST0_RTX (qimode));
25660 : 31 : emit_move_insn (dest, gen_rtx_fmt_ee (GT, qimode, zero, op1));
25661 : 31 : }
25662 : : else
25663 : : {
25664 : 1 : gcc_assert (qimode == V64QImode);
25665 : 1 : rtx kmask = gen_reg_rtx (DImode);
25666 : 1 : emit_insn (gen_avx512bw_cvtb2maskv64qi (kmask, op1));
25667 : 1 : emit_insn (gen_avx512bw_cvtmask2bv64qi (dest, kmask));
25668 : : }
25669 : 32 : return true;
25670 : : }
25671 : :
25672 : : /* Record sign bit. */
25673 : 346 : xor_constant = 1 << (8 - shift_amount - 1);
25674 : :
25675 : : /* Zero upper/lower bits shift from left/right element. */
25676 : 346 : and_constant
25677 : 346 : = (code == ASHIFT ? 256 - (1 << shift_amount)
25678 : 317 : : (1 << (8 - shift_amount)) - 1);
25679 : :
25680 : 346 : switch (qimode)
25681 : : {
25682 : 330 : case V16QImode:
25683 : 330 : himode = V8HImode;
25684 : 281 : gen_shift =
25685 : : ((code == ASHIFT)
25686 : 330 : ? gen_ashlv8hi3
25687 : 313 : : (code == ASHIFTRT) ? gen_ashrv8hi3 : gen_lshrv8hi3);
25688 : : gen_and = gen_andv16qi3;
25689 : : gen_xor = gen_xorv16qi3;
25690 : : gen_sub = gen_subv16qi3;
25691 : : break;
25692 : 5 : case V32QImode:
25693 : 5 : himode = V16HImode;
25694 : 1 : gen_shift =
25695 : : ((code == ASHIFT)
25696 : 5 : ? gen_ashlv16hi3
25697 : 2 : : (code == ASHIFTRT) ? gen_ashrv16hi3 : gen_lshrv16hi3);
25698 : : gen_and = gen_andv32qi3;
25699 : : gen_xor = gen_xorv32qi3;
25700 : : gen_sub = gen_subv32qi3;
25701 : : break;
25702 : 11 : case V64QImode:
25703 : 11 : himode = V32HImode;
25704 : 1 : gen_shift =
25705 : : ((code == ASHIFT)
25706 : 11 : ? gen_ashlv32hi3
25707 : 2 : : (code == ASHIFTRT) ? gen_ashrv32hi3 : gen_lshrv32hi3);
25708 : : gen_and = gen_andv64qi3;
25709 : : gen_xor = gen_xorv64qi3;
25710 : : gen_sub = gen_subv64qi3;
25711 : : break;
25712 : 0 : default:
25713 : 0 : gcc_unreachable ();
25714 : : }
25715 : :
25716 : 346 : tmp = gen_reg_rtx (himode);
25717 : 346 : vec_const_and = gen_reg_rtx (qimode);
25718 : 346 : op1_subreg = lowpart_subreg (himode, op1, qimode);
25719 : :
25720 : : /* For ASHIFT and LSHIFTRT, perform operation like
25721 : : vpsllw/vpsrlw $shift_amount, %op1, %dest.
25722 : : vpand %vec_const_and, %dest. */
25723 : 346 : emit_insn (gen_shift (tmp, op1_subreg, op2));
25724 : 346 : emit_move_insn (dest, simplify_gen_subreg (qimode, tmp, himode, 0));
25725 : 346 : emit_move_insn (vec_const_and,
25726 : : ix86_build_const_vector (qimode, true,
25727 : 346 : gen_int_mode (and_constant, QImode)));
25728 : 346 : emit_insn (gen_and (dest, dest, vec_const_and));
25729 : :
25730 : : /* For ASHIFTRT, perform extra operation like
25731 : : vpxor %vec_const_xor, %dest, %dest
25732 : : vpsubb %vec_const_xor, %dest, %dest */
25733 : 346 : if (code == ASHIFTRT)
25734 : : {
25735 : 34 : vec_const_xor = gen_reg_rtx (qimode);
25736 : 34 : emit_move_insn (vec_const_xor,
25737 : : ix86_build_const_vector (qimode, true,
25738 : 34 : gen_int_mode (xor_constant, QImode)));
25739 : 34 : emit_insn (gen_xor (dest, dest, vec_const_xor));
25740 : 34 : emit_insn (gen_sub (dest, dest, vec_const_xor));
25741 : : }
25742 : : return true;
25743 : : }
25744 : :
25745 : : void
25746 : 1412 : ix86_expand_vecop_qihi_partial (enum rtx_code code, rtx dest, rtx op1, rtx op2)
25747 : : {
25748 : 1412 : machine_mode qimode = GET_MODE (dest);
25749 : 1412 : rtx qop1, qop2, hop1, hop2, qdest, hdest;
25750 : 1412 : bool op2vec = GET_MODE_CLASS (GET_MODE (op2)) == MODE_VECTOR_INT;
25751 : 1412 : bool uns_p = code != ASHIFTRT;
25752 : :
25753 : 1412 : switch (qimode)
25754 : : {
25755 : 1412 : case E_V4QImode:
25756 : 1412 : case E_V8QImode:
25757 : 1412 : break;
25758 : 0 : default:
25759 : 0 : gcc_unreachable ();
25760 : : }
25761 : :
25762 : 1412 : qop1 = lowpart_subreg (V16QImode, force_reg (qimode, op1), qimode);
25763 : :
25764 : 1412 : if (op2vec)
25765 : 1310 : qop2 = lowpart_subreg (V16QImode, force_reg (qimode, op2), qimode);
25766 : : else
25767 : : qop2 = op2;
25768 : :
25769 : 1412 : qdest = gen_reg_rtx (V16QImode);
25770 : :
25771 : 1412 : if (CONST_INT_P (op2)
25772 : 90 : && (code == ASHIFT || code == LSHIFTRT || code == ASHIFTRT)
25773 : : /* With AVX512 it's cheaper to do vpmovsxbw/op/vpmovwb.
25774 : : Even with SSE4.1 the alternative is better. */
25775 : 90 : && !TARGET_SSE4_1
25776 : 1466 : && ix86_expand_vec_shift_qihi_constant (code, qdest, qop1, qop2))
25777 : : {
25778 : 54 : emit_move_insn (dest, gen_lowpart (qimode, qdest));
25779 : 54 : return;
25780 : : }
25781 : :
25782 : 1358 : if (CONST_INT_P (op2)
25783 : 36 : && code == ASHIFTRT
25784 : 10 : && INTVAL (op2) == 7)
25785 : : {
25786 : 3 : rtx zero = gen_reg_rtx (qimode);
25787 : 3 : emit_move_insn (zero, CONST0_RTX (qimode));
25788 : 3 : emit_move_insn (dest, gen_rtx_fmt_ee (GT, qimode, zero, op1));
25789 : 3 : return;
25790 : : }
25791 : :
25792 : 1355 : switch (code)
25793 : : {
25794 : 1297 : case MULT:
25795 : 1297 : gcc_assert (op2vec);
25796 : 1297 : if (!TARGET_SSE4_1)
25797 : : {
25798 : : /* Unpack data such that we've got a source byte in each low byte
25799 : : of each word. We don't care what goes into the high byte of
25800 : : each word. Rather than trying to get zero in there, most
25801 : : convenient is to let it be a copy of the low byte. */
25802 : 244 : hop1 = copy_to_reg (qop1);
25803 : 244 : hop2 = copy_to_reg (qop2);
25804 : 244 : emit_insn (gen_vec_interleave_lowv16qi (hop1, hop1, hop1));
25805 : 244 : emit_insn (gen_vec_interleave_lowv16qi (hop2, hop2, hop2));
25806 : 244 : break;
25807 : : }
25808 : : /* FALLTHRU */
25809 : 1111 : case ASHIFT:
25810 : 1111 : case ASHIFTRT:
25811 : 1111 : case LSHIFTRT:
25812 : 1111 : hop1 = gen_reg_rtx (V8HImode);
25813 : 1111 : ix86_expand_sse_unpack (hop1, qop1, uns_p, false);
25814 : : /* mult/vashr/vlshr/vashl */
25815 : 1111 : if (op2vec)
25816 : : {
25817 : 1066 : hop2 = gen_reg_rtx (V8HImode);
25818 : 1066 : ix86_expand_sse_unpack (hop2, qop2, uns_p, false);
25819 : : }
25820 : : else
25821 : : hop2 = qop2;
25822 : :
25823 : : break;
25824 : 0 : default:
25825 : 0 : gcc_unreachable ();
25826 : : }
25827 : :
25828 : 1355 : if (code != MULT && op2vec)
25829 : : {
25830 : : /* Expand vashr/vlshr/vashl. */
25831 : 13 : hdest = gen_reg_rtx (V8HImode);
25832 : 13 : emit_insn (gen_rtx_SET (hdest,
25833 : : simplify_gen_binary (code, V8HImode,
25834 : : hop1, hop2)));
25835 : : }
25836 : : else
25837 : : /* Expand mult/ashr/lshr/ashl. */
25838 : 1342 : hdest = expand_simple_binop (V8HImode, code, hop1, hop2,
25839 : : NULL_RTX, 1, OPTAB_DIRECT);
25840 : :
25841 : 1355 : if (TARGET_AVX512BW && TARGET_AVX512VL)
25842 : : {
25843 : 30 : if (qimode == V8QImode)
25844 : : qdest = dest;
25845 : : else
25846 : 10 : qdest = gen_reg_rtx (V8QImode);
25847 : :
25848 : 30 : emit_insn (gen_truncv8hiv8qi2 (qdest, hdest));
25849 : : }
25850 : : else
25851 : : {
25852 : 1325 : struct expand_vec_perm_d d;
25853 : 1325 : rtx qres = gen_lowpart (V16QImode, hdest);
25854 : 1325 : bool ok;
25855 : 1325 : int i;
25856 : :
25857 : : /* Merge the data back into the right place. */
25858 : 1325 : d.target = qdest;
25859 : 1325 : d.op0 = d.op1 = qres;
25860 : 1325 : d.vmode = V16QImode;
25861 : 1325 : d.nelt = 16;
25862 : 1325 : d.one_operand_p = TARGET_SSSE3;
25863 : 1325 : d.testing_p = false;
25864 : :
25865 : 22525 : for (i = 0; i < d.nelt; ++i)
25866 : 21200 : d.perm[i] = i * 2;
25867 : :
25868 : 1325 : ok = ix86_expand_vec_perm_const_1 (&d);
25869 : 1325 : gcc_assert (ok);
25870 : : }
25871 : :
25872 : 1355 : if (qdest != dest)
25873 : 1335 : emit_move_insn (dest, gen_lowpart (qimode, qdest));
25874 : : }
25875 : :
25876 : : /* Emit instruction in 2x wider mode. For example, optimize
25877 : : vector MUL generation like
25878 : :
25879 : : vpmovzxbw ymm2, xmm0
25880 : : vpmovzxbw ymm3, xmm1
25881 : : vpmullw ymm4, ymm2, ymm3
25882 : : vpmovwb xmm0, ymm4
25883 : :
25884 : : it would take less instructions than ix86_expand_vecop_qihi.
25885 : : Return true if success. */
25886 : :
25887 : : static bool
25888 : 1339 : ix86_expand_vecop_qihi2 (enum rtx_code code, rtx dest, rtx op1, rtx op2)
25889 : : {
25890 : 1339 : machine_mode himode, qimode = GET_MODE (dest);
25891 : 1339 : machine_mode wqimode;
25892 : 1339 : rtx qop1, qop2, hop1, hop2, hdest;
25893 : 1339 : rtx (*gen_truncate)(rtx, rtx) = NULL;
25894 : 1339 : bool op2vec = GET_MODE_CLASS (GET_MODE (op2)) == MODE_VECTOR_INT;
25895 : 1339 : bool uns_p = code != ASHIFTRT;
25896 : :
25897 : : /* Without VPMOVWB (provided by AVX512BW ISA), the expansion uses the
25898 : : generic permutation to merge the data back into the right place. This
25899 : : permutation results in VPERMQ, which is slow, so better fall back to
25900 : : ix86_expand_vecop_qihi. */
25901 : 1339 : if (!TARGET_AVX512BW
25902 : 301 : || (qimode == V16QImode && !TARGET_AVX512VL)
25903 : : /* There are no V64HImode instructions. */
25904 : 301 : || qimode == V64QImode)
25905 : : return false;
25906 : :
25907 : : /* Do not generate ymm/zmm instructions when
25908 : : target prefers 128/256 bit vector width. */
25909 : 267 : if ((qimode == V16QImode && TARGET_PREFER_AVX128)
25910 : 267 : || (qimode == V32QImode && TARGET_PREFER_AVX256))
25911 : : return false;
25912 : :
25913 : 260 : switch (qimode)
25914 : : {
25915 : : case E_V16QImode:
25916 : : himode = V16HImode;
25917 : : gen_truncate = gen_truncv16hiv16qi2;
25918 : : break;
25919 : 17 : case E_V32QImode:
25920 : 17 : himode = V32HImode;
25921 : 17 : gen_truncate = gen_truncv32hiv32qi2;
25922 : 17 : break;
25923 : 0 : default:
25924 : 0 : gcc_unreachable ();
25925 : : }
25926 : :
25927 : 260 : wqimode = GET_MODE_2XWIDER_MODE (qimode).require ();
25928 : 260 : qop1 = lowpart_subreg (wqimode, force_reg (qimode, op1), qimode);
25929 : :
25930 : 260 : if (op2vec)
25931 : 260 : qop2 = lowpart_subreg (wqimode, force_reg (qimode, op2), qimode);
25932 : : else
25933 : : qop2 = op2;
25934 : :
25935 : 260 : hop1 = gen_reg_rtx (himode);
25936 : 260 : ix86_expand_sse_unpack (hop1, qop1, uns_p, false);
25937 : :
25938 : 260 : if (op2vec)
25939 : : {
25940 : 260 : hop2 = gen_reg_rtx (himode);
25941 : 260 : ix86_expand_sse_unpack (hop2, qop2, uns_p, false);
25942 : : }
25943 : : else
25944 : : hop2 = qop2;
25945 : :
25946 : 260 : if (code != MULT && op2vec)
25947 : : {
25948 : : /* Expand vashr/vlshr/vashl. */
25949 : 14 : hdest = gen_reg_rtx (himode);
25950 : 14 : emit_insn (gen_rtx_SET (hdest,
25951 : : simplify_gen_binary (code, himode,
25952 : : hop1, hop2)));
25953 : : }
25954 : : else
25955 : : /* Expand mult/ashr/lshr/ashl. */
25956 : 246 : hdest = expand_simple_binop (himode, code, hop1, hop2,
25957 : : NULL_RTX, 1, OPTAB_DIRECT);
25958 : :
25959 : 260 : emit_insn (gen_truncate (dest, hdest));
25960 : 260 : return true;
25961 : : }
25962 : :
25963 : : /* Expand a vector operation CODE for a V*QImode in terms of the
25964 : : same operation on V*HImode. */
25965 : :
25966 : : void
25967 : 1663 : ix86_expand_vecop_qihi (enum rtx_code code, rtx dest, rtx op1, rtx op2)
25968 : : {
25969 : 1663 : machine_mode qimode = GET_MODE (dest);
25970 : 1663 : machine_mode himode;
25971 : 1663 : rtx (*gen_il) (rtx, rtx, rtx);
25972 : 1663 : rtx (*gen_ih) (rtx, rtx, rtx);
25973 : 1663 : rtx op1_l, op1_h, op2_l, op2_h, res_l, res_h;
25974 : 1663 : bool op2vec = GET_MODE_CLASS (GET_MODE (op2)) == MODE_VECTOR_INT;
25975 : 1663 : struct expand_vec_perm_d d;
25976 : 1663 : bool full_interleave = true;
25977 : 1663 : bool uns_p = code != ASHIFTRT;
25978 : 1663 : bool ok;
25979 : 1663 : int i;
25980 : :
25981 : 1663 : if (CONST_INT_P (op2)
25982 : 324 : && (code == ASHIFT || code == LSHIFTRT || code == ASHIFTRT)
25983 : 1987 : && ix86_expand_vec_shift_qihi_constant (code, dest, op1, op2))
25984 : 584 : return;
25985 : :
25986 : 1339 : if (ix86_expand_vecop_qihi2 (code, dest, op1, op2))
25987 : : return;
25988 : :
25989 : 1079 : switch (qimode)
25990 : : {
25991 : : case E_V16QImode:
25992 : : himode = V8HImode;
25993 : : break;
25994 : 280 : case E_V32QImode:
25995 : 280 : himode = V16HImode;
25996 : 280 : break;
25997 : 34 : case E_V64QImode:
25998 : 34 : himode = V32HImode;
25999 : 34 : break;
26000 : 0 : default:
26001 : 0 : gcc_unreachable ();
26002 : : }
26003 : :
26004 : 1079 : switch (code)
26005 : : {
26006 : 1071 : case MULT:
26007 : 1071 : gcc_assert (op2vec);
26008 : : /* Unpack data such that we've got a source byte in each low byte of
26009 : : each word. We don't care what goes into the high byte of each word.
26010 : : Rather than trying to get zero in there, most convenient is to let
26011 : : it be a copy of the low byte. */
26012 : 1071 : switch (qimode)
26013 : : {
26014 : : case E_V16QImode:
26015 : : gen_il = gen_vec_interleave_lowv16qi;
26016 : : gen_ih = gen_vec_interleave_highv16qi;
26017 : : break;
26018 : 280 : case E_V32QImode:
26019 : 280 : gen_il = gen_avx2_interleave_lowv32qi;
26020 : 280 : gen_ih = gen_avx2_interleave_highv32qi;
26021 : 280 : full_interleave = false;
26022 : 280 : break;
26023 : 32 : case E_V64QImode:
26024 : 32 : gen_il = gen_avx512bw_interleave_lowv64qi;
26025 : 32 : gen_ih = gen_avx512bw_interleave_highv64qi;
26026 : 32 : full_interleave = false;
26027 : 32 : break;
26028 : 0 : default:
26029 : 0 : gcc_unreachable ();
26030 : : }
26031 : :
26032 : 1071 : op2_l = gen_reg_rtx (qimode);
26033 : 1071 : op2_h = gen_reg_rtx (qimode);
26034 : 1071 : emit_insn (gen_il (op2_l, op2, op2));
26035 : 1071 : emit_insn (gen_ih (op2_h, op2, op2));
26036 : :
26037 : 1071 : op1_l = gen_reg_rtx (qimode);
26038 : 1071 : op1_h = gen_reg_rtx (qimode);
26039 : 1071 : emit_insn (gen_il (op1_l, op1, op1));
26040 : 1071 : emit_insn (gen_ih (op1_h, op1, op1));
26041 : 1071 : break;
26042 : :
26043 : 8 : case ASHIFT:
26044 : 8 : case ASHIFTRT:
26045 : 8 : case LSHIFTRT:
26046 : 8 : op1_l = gen_reg_rtx (himode);
26047 : 8 : op1_h = gen_reg_rtx (himode);
26048 : 8 : ix86_expand_sse_unpack (op1_l, op1, uns_p, false);
26049 : 8 : ix86_expand_sse_unpack (op1_h, op1, uns_p, true);
26050 : : /* vashr/vlshr/vashl */
26051 : 8 : if (op2vec)
26052 : : {
26053 : 2 : rtx tmp = force_reg (qimode, op2);
26054 : 2 : op2_l = gen_reg_rtx (himode);
26055 : 2 : op2_h = gen_reg_rtx (himode);
26056 : 2 : ix86_expand_sse_unpack (op2_l, tmp, uns_p, false);
26057 : 2 : ix86_expand_sse_unpack (op2_h, tmp, uns_p, true);
26058 : : }
26059 : : else
26060 : : op2_l = op2_h = op2;
26061 : :
26062 : : break;
26063 : 0 : default:
26064 : 0 : gcc_unreachable ();
26065 : : }
26066 : :
26067 : 1079 : if (code != MULT && op2vec)
26068 : : {
26069 : : /* Expand vashr/vlshr/vashl. */
26070 : 2 : res_l = gen_reg_rtx (himode);
26071 : 2 : res_h = gen_reg_rtx (himode);
26072 : 2 : emit_insn (gen_rtx_SET (res_l,
26073 : : simplify_gen_binary (code, himode,
26074 : : op1_l, op2_l)));
26075 : 2 : emit_insn (gen_rtx_SET (res_h,
26076 : : simplify_gen_binary (code, himode,
26077 : : op1_h, op2_h)));
26078 : : }
26079 : : else
26080 : : {
26081 : : /* Expand mult/ashr/lshr/ashl. */
26082 : 1077 : res_l = expand_simple_binop (himode, code, op1_l, op2_l, NULL_RTX,
26083 : : 1, OPTAB_DIRECT);
26084 : 1077 : res_h = expand_simple_binop (himode, code, op1_h, op2_h, NULL_RTX,
26085 : : 1, OPTAB_DIRECT);
26086 : : }
26087 : :
26088 : 1079 : gcc_assert (res_l && res_h);
26089 : :
26090 : : /* Merge the data back into the right place. */
26091 : 1079 : d.target = dest;
26092 : 1079 : d.op0 = gen_lowpart (qimode, res_l);
26093 : 1079 : d.op1 = gen_lowpart (qimode, res_h);
26094 : 1079 : d.vmode = qimode;
26095 : 1079 : d.nelt = GET_MODE_NUNITS (qimode);
26096 : 1079 : d.one_operand_p = false;
26097 : 1079 : d.testing_p = false;
26098 : :
26099 : 1079 : if (full_interleave)
26100 : : {
26101 : : /* We used the full interleave, the desired
26102 : : results are in the even elements. */
26103 : 13135 : for (i = 0; i < d.nelt; ++i)
26104 : 12368 : d.perm[i] = i * 2;
26105 : : }
26106 : : else
26107 : : {
26108 : : /* For AVX, the interleave used above was not cross-lane. So the
26109 : : extraction is evens but with the second and third quarter swapped.
26110 : : Happily, that is even one insn shorter than even extraction.
26111 : : For AVX512BW we have 4 lanes. We extract evens from within a lane,
26112 : : always first from the first and then from the second source operand,
26113 : : the index bits above the low 4 bits remains the same.
26114 : : Thus, for d.nelt == 32 we want permutation
26115 : : 0,2,4,..14, 32,34,36,..46, 16,18,20,..30, 48,50,52,..62
26116 : : and for d.nelt == 64 we want permutation
26117 : : 0,2,4,..14, 64,66,68,..78, 16,18,20,..30, 80,82,84,..94,
26118 : : 32,34,36,..46, 96,98,100,..110, 48,50,52,..62, 112,114,116,..126. */
26119 : 11320 : for (i = 0; i < d.nelt; ++i)
26120 : 16512 : d.perm[i] = ((i * 2) & 14) + ((i & 8) ? d.nelt : 0) + (i & ~15);
26121 : : }
26122 : :
26123 : 1079 : ok = ix86_expand_vec_perm_const_1 (&d);
26124 : 1079 : gcc_assert (ok);
26125 : : }
26126 : :
26127 : : /* Helper function of ix86_expand_mul_widen_evenodd. Return true
26128 : : if op is CONST_VECTOR with all odd elements equal to their
26129 : : preceding element. */
26130 : :
26131 : : static bool
26132 : 8620 : const_vector_equal_evenodd_p (rtx op)
26133 : : {
26134 : 8620 : machine_mode mode = GET_MODE (op);
26135 : 8620 : int i, nunits = GET_MODE_NUNITS (mode);
26136 : 8620 : if (!CONST_VECTOR_P (op)
26137 : 8620 : || nunits != CONST_VECTOR_NUNITS (op))
26138 : : return false;
26139 : 3504 : for (i = 0; i < nunits; i += 2)
26140 : 2830 : if (CONST_VECTOR_ELT (op, i) != CONST_VECTOR_ELT (op, i + 1))
26141 : : return false;
26142 : : return true;
26143 : : }
26144 : :
26145 : : void
26146 : 8745 : ix86_expand_mul_widen_evenodd (rtx dest, rtx op1, rtx op2,
26147 : : bool uns_p, bool odd_p)
26148 : : {
26149 : 8745 : machine_mode mode = GET_MODE (op1);
26150 : 8745 : machine_mode wmode = GET_MODE (dest);
26151 : 8745 : rtx x;
26152 : 8745 : rtx orig_op1 = op1, orig_op2 = op2;
26153 : :
26154 : 8745 : if (!nonimmediate_operand (op1, mode))
26155 : 0 : op1 = force_reg (mode, op1);
26156 : 8745 : if (!nonimmediate_operand (op2, mode))
26157 : 3297 : op2 = force_reg (mode, op2);
26158 : :
26159 : : /* We only play even/odd games with vectors of SImode. */
26160 : 8745 : gcc_assert (mode == V4SImode || mode == V8SImode || mode == V16SImode);
26161 : :
26162 : : /* If we're looking for the odd results, shift those members down to
26163 : : the even slots. For some cpus this is faster than a PSHUFD. */
26164 : 8745 : if (odd_p)
26165 : : {
26166 : : /* For XOP use vpmacsdqh, but only for smult, as it is only
26167 : : signed. */
26168 : 4328 : if (TARGET_XOP && mode == V4SImode && !uns_p)
26169 : : {
26170 : 18 : x = force_reg (wmode, CONST0_RTX (wmode));
26171 : 18 : emit_insn (gen_xop_pmacsdqh (dest, op1, op2, x));
26172 : 18 : return;
26173 : : }
26174 : :
26175 : 8620 : x = GEN_INT (GET_MODE_UNIT_BITSIZE (mode));
26176 : 4310 : if (!const_vector_equal_evenodd_p (orig_op1))
26177 : 4310 : op1 = expand_binop (wmode, lshr_optab, gen_lowpart (wmode, op1),
26178 : : x, NULL, 1, OPTAB_DIRECT);
26179 : 4310 : if (!const_vector_equal_evenodd_p (orig_op2))
26180 : 3636 : op2 = expand_binop (wmode, lshr_optab, gen_lowpart (wmode, op2),
26181 : : x, NULL, 1, OPTAB_DIRECT);
26182 : 4310 : op1 = gen_lowpart (mode, op1);
26183 : 4310 : op2 = gen_lowpart (mode, op2);
26184 : : }
26185 : :
26186 : 8727 : if (mode == V16SImode)
26187 : : {
26188 : 10 : if (uns_p)
26189 : 0 : x = gen_vec_widen_umult_even_v16si (dest, op1, op2);
26190 : : else
26191 : 10 : x = gen_vec_widen_smult_even_v16si (dest, op1, op2);
26192 : : }
26193 : 8717 : else if (mode == V8SImode)
26194 : : {
26195 : 139 : if (uns_p)
26196 : 59 : x = gen_vec_widen_umult_even_v8si (dest, op1, op2);
26197 : : else
26198 : 80 : x = gen_vec_widen_smult_even_v8si (dest, op1, op2);
26199 : : }
26200 : 8578 : else if (uns_p)
26201 : 7543 : x = gen_vec_widen_umult_even_v4si (dest, op1, op2);
26202 : 1035 : else if (TARGET_SSE4_1)
26203 : 349 : x = gen_sse4_1_mulv2siv2di3 (dest, op1, op2);
26204 : : else
26205 : : {
26206 : 686 : rtx s1, s2, t0, t1, t2;
26207 : :
26208 : : /* The easiest way to implement this without PMULDQ is to go through
26209 : : the motions as if we are performing a full 64-bit multiply. With
26210 : : the exception that we need to do less shuffling of the elements. */
26211 : :
26212 : : /* Compute the sign-extension, aka highparts, of the two operands. */
26213 : 686 : s1 = ix86_expand_sse_cmp (gen_reg_rtx (mode), GT, CONST0_RTX (mode),
26214 : : op1, pc_rtx, pc_rtx);
26215 : 686 : s2 = ix86_expand_sse_cmp (gen_reg_rtx (mode), GT, CONST0_RTX (mode),
26216 : : op2, pc_rtx, pc_rtx);
26217 : :
26218 : : /* Multiply LO(A) * HI(B), and vice-versa. */
26219 : 686 : t1 = gen_reg_rtx (wmode);
26220 : 686 : t2 = gen_reg_rtx (wmode);
26221 : 686 : emit_insn (gen_vec_widen_umult_even_v4si (t1, s1, op2));
26222 : 686 : emit_insn (gen_vec_widen_umult_even_v4si (t2, s2, op1));
26223 : :
26224 : : /* Multiply LO(A) * LO(B). */
26225 : 686 : t0 = gen_reg_rtx (wmode);
26226 : 686 : emit_insn (gen_vec_widen_umult_even_v4si (t0, op1, op2));
26227 : :
26228 : : /* Combine and shift the highparts into place. */
26229 : 686 : t1 = expand_binop (wmode, add_optab, t1, t2, t1, 1, OPTAB_DIRECT);
26230 : 686 : t1 = expand_binop (wmode, ashl_optab, t1, GEN_INT (32), t1,
26231 : : 1, OPTAB_DIRECT);
26232 : :
26233 : : /* Combine high and low parts. */
26234 : 686 : force_expand_binop (wmode, add_optab, t0, t1, dest, 1, OPTAB_DIRECT);
26235 : 686 : return;
26236 : : }
26237 : 8041 : emit_insn (x);
26238 : : }
26239 : :
26240 : : void
26241 : 975 : ix86_expand_mul_widen_hilo (rtx dest, rtx op1, rtx op2,
26242 : : bool uns_p, bool high_p)
26243 : : {
26244 : 975 : machine_mode wmode = GET_MODE (dest);
26245 : 975 : machine_mode mode = GET_MODE (op1);
26246 : 975 : rtx t1, t2, t3, t4, mask;
26247 : :
26248 : 975 : switch (mode)
26249 : : {
26250 : 297 : case E_V4SImode:
26251 : 297 : t1 = gen_reg_rtx (mode);
26252 : 297 : t2 = gen_reg_rtx (mode);
26253 : 297 : if (TARGET_XOP && !uns_p)
26254 : : {
26255 : : /* With XOP, we have pmacsdqh, aka mul_widen_odd. In this case,
26256 : : shuffle the elements once so that all elements are in the right
26257 : : place for immediate use: { A C B D }. */
26258 : 33 : emit_insn (gen_sse2_pshufd_1 (t1, op1, const0_rtx, const2_rtx,
26259 : : const1_rtx, GEN_INT (3)));
26260 : 33 : emit_insn (gen_sse2_pshufd_1 (t2, op2, const0_rtx, const2_rtx,
26261 : : const1_rtx, GEN_INT (3)));
26262 : : }
26263 : : else
26264 : : {
26265 : : /* Put the elements into place for the multiply. */
26266 : 264 : ix86_expand_vec_interleave (t1, op1, op1, high_p);
26267 : 264 : ix86_expand_vec_interleave (t2, op2, op2, high_p);
26268 : 264 : high_p = false;
26269 : : }
26270 : 297 : ix86_expand_mul_widen_evenodd (dest, t1, t2, uns_p, high_p);
26271 : 297 : break;
26272 : :
26273 : 78 : case E_V8SImode:
26274 : : /* Shuffle the elements between the lanes. After this we
26275 : : have { A B E F | C D G H } for each operand. */
26276 : 78 : t1 = gen_reg_rtx (V4DImode);
26277 : 78 : t2 = gen_reg_rtx (V4DImode);
26278 : 78 : emit_insn (gen_avx2_permv4di_1 (t1, gen_lowpart (V4DImode, op1),
26279 : : const0_rtx, const2_rtx,
26280 : : const1_rtx, GEN_INT (3)));
26281 : 78 : emit_insn (gen_avx2_permv4di_1 (t2, gen_lowpart (V4DImode, op2),
26282 : : const0_rtx, const2_rtx,
26283 : : const1_rtx, GEN_INT (3)));
26284 : :
26285 : : /* Shuffle the elements within the lanes. After this we
26286 : : have { A A B B | C C D D } or { E E F F | G G H H }. */
26287 : 78 : t3 = gen_reg_rtx (V8SImode);
26288 : 78 : t4 = gen_reg_rtx (V8SImode);
26289 : 117 : mask = GEN_INT (high_p
26290 : : ? 2 + (2 << 2) + (3 << 4) + (3 << 6)
26291 : : : 0 + (0 << 2) + (1 << 4) + (1 << 6));
26292 : 78 : emit_insn (gen_avx2_pshufdv3 (t3, gen_lowpart (V8SImode, t1), mask));
26293 : 78 : emit_insn (gen_avx2_pshufdv3 (t4, gen_lowpart (V8SImode, t2), mask));
26294 : :
26295 : 78 : ix86_expand_mul_widen_evenodd (dest, t3, t4, uns_p, false);
26296 : 78 : break;
26297 : :
26298 : 388 : case E_V8HImode:
26299 : 388 : case E_V16HImode:
26300 : 388 : t1 = expand_binop (mode, smul_optab, op1, op2, NULL_RTX,
26301 : : uns_p, OPTAB_DIRECT);
26302 : 622 : t2 = expand_binop (mode,
26303 : : uns_p ? umul_highpart_optab : smul_highpart_optab,
26304 : : op1, op2, NULL_RTX, uns_p, OPTAB_DIRECT);
26305 : 388 : gcc_assert (t1 && t2);
26306 : :
26307 : 388 : t3 = gen_reg_rtx (mode);
26308 : 388 : ix86_expand_vec_interleave (t3, t1, t2, high_p);
26309 : 388 : emit_move_insn (dest, gen_lowpart (wmode, t3));
26310 : 388 : break;
26311 : :
26312 : 212 : case E_V16QImode:
26313 : 212 : case E_V32QImode:
26314 : 212 : case E_V32HImode:
26315 : 212 : case E_V16SImode:
26316 : 212 : case E_V64QImode:
26317 : 212 : t1 = gen_reg_rtx (wmode);
26318 : 212 : t2 = gen_reg_rtx (wmode);
26319 : 212 : ix86_expand_sse_unpack (t1, op1, uns_p, high_p);
26320 : 212 : ix86_expand_sse_unpack (t2, op2, uns_p, high_p);
26321 : :
26322 : 212 : emit_insn (gen_rtx_SET (dest, gen_rtx_MULT (wmode, t1, t2)));
26323 : 212 : break;
26324 : :
26325 : 0 : default:
26326 : 0 : gcc_unreachable ();
26327 : : }
26328 : 975 : }
26329 : :
26330 : : void
26331 : 3604 : ix86_expand_sse2_mulv4si3 (rtx op0, rtx op1, rtx op2)
26332 : : {
26333 : 3604 : rtx res_1, res_2, res_3, res_4;
26334 : :
26335 : 3604 : res_1 = gen_reg_rtx (V4SImode);
26336 : 3604 : res_2 = gen_reg_rtx (V4SImode);
26337 : 3604 : res_3 = gen_reg_rtx (V2DImode);
26338 : 3604 : res_4 = gen_reg_rtx (V2DImode);
26339 : 3604 : ix86_expand_mul_widen_evenodd (res_3, op1, op2, true, false);
26340 : 3604 : ix86_expand_mul_widen_evenodd (res_4, op1, op2, true, true);
26341 : :
26342 : : /* Move the results in element 2 down to element 1; we don't care
26343 : : what goes in elements 2 and 3. Then we can merge the parts
26344 : : back together with an interleave.
26345 : :
26346 : : Note that two other sequences were tried:
26347 : : (1) Use interleaves at the start instead of psrldq, which allows
26348 : : us to use a single shufps to merge things back at the end.
26349 : : (2) Use shufps here to combine the two vectors, then pshufd to
26350 : : put the elements in the correct order.
26351 : : In both cases the cost of the reformatting stall was too high
26352 : : and the overall sequence slower. */
26353 : :
26354 : 3604 : emit_insn (gen_sse2_pshufd_1 (res_1, gen_lowpart (V4SImode, res_3),
26355 : : const0_rtx, const2_rtx,
26356 : : const0_rtx, const0_rtx));
26357 : 3604 : emit_insn (gen_sse2_pshufd_1 (res_2, gen_lowpart (V4SImode, res_4),
26358 : : const0_rtx, const2_rtx,
26359 : : const0_rtx, const0_rtx));
26360 : 3604 : res_1 = emit_insn (gen_vec_interleave_lowv4si (op0, res_1, res_2));
26361 : :
26362 : 3604 : set_unique_reg_note (res_1, REG_EQUAL, gen_rtx_MULT (V4SImode, op1, op2));
26363 : 3604 : }
26364 : :
26365 : : void
26366 : 534 : ix86_expand_sse2_mulvxdi3 (rtx op0, rtx op1, rtx op2)
26367 : : {
26368 : 534 : machine_mode mode = GET_MODE (op0);
26369 : 534 : rtx t1, t2, t3, t4, t5, t6;
26370 : :
26371 : 534 : if (TARGET_AVX512DQ && mode == V8DImode)
26372 : 32 : emit_insn (gen_avx512dq_mulv8di3 (op0, op1, op2));
26373 : 502 : else if (TARGET_AVX512DQ && TARGET_AVX512VL && mode == V4DImode)
26374 : 32 : emit_insn (gen_avx512dq_mulv4di3 (op0, op1, op2));
26375 : 470 : else if (TARGET_AVX512DQ && TARGET_AVX512VL && mode == V2DImode)
26376 : 36 : emit_insn (gen_avx512dq_mulv2di3 (op0, op1, op2));
26377 : 434 : else if (TARGET_XOP && mode == V2DImode)
26378 : : {
26379 : : /* op1: A,B,C,D, op2: E,F,G,H */
26380 : 2 : op1 = gen_lowpart (V4SImode, op1);
26381 : 2 : op2 = gen_lowpart (V4SImode, op2);
26382 : :
26383 : 2 : t1 = gen_reg_rtx (V4SImode);
26384 : 2 : t2 = gen_reg_rtx (V4SImode);
26385 : 2 : t3 = gen_reg_rtx (V2DImode);
26386 : 2 : t4 = gen_reg_rtx (V2DImode);
26387 : :
26388 : : /* t1: B,A,D,C */
26389 : 2 : emit_insn (gen_sse2_pshufd_1 (t1, op1,
26390 : : GEN_INT (1),
26391 : : GEN_INT (0),
26392 : : GEN_INT (3),
26393 : : GEN_INT (2)));
26394 : :
26395 : : /* t2: (B*E),(A*F),(D*G),(C*H) */
26396 : 2 : emit_insn (gen_mulv4si3 (t2, t1, op2));
26397 : :
26398 : : /* t3: (B*E)+(A*F), (D*G)+(C*H) */
26399 : 2 : emit_insn (gen_xop_phadddq (t3, t2));
26400 : :
26401 : : /* t4: ((B*E)+(A*F))<<32, ((D*G)+(C*H))<<32 */
26402 : 2 : emit_insn (gen_ashlv2di3 (t4, t3, GEN_INT (32)));
26403 : :
26404 : : /* Multiply lower parts and add all */
26405 : 2 : t5 = gen_reg_rtx (V2DImode);
26406 : 2 : emit_insn (gen_vec_widen_umult_even_v4si (t5,
26407 : 2 : gen_lowpart (V4SImode, op1),
26408 : 2 : gen_lowpart (V4SImode, op2)));
26409 : 2 : force_expand_binop (mode, add_optab, t5, t4, op0, 1, OPTAB_DIRECT);
26410 : : }
26411 : : else
26412 : : {
26413 : 432 : machine_mode nmode;
26414 : 432 : rtx (*umul) (rtx, rtx, rtx);
26415 : :
26416 : 432 : if (mode == V2DImode)
26417 : : {
26418 : : umul = gen_vec_widen_umult_even_v4si;
26419 : : nmode = V4SImode;
26420 : : }
26421 : 327 : else if (mode == V4DImode)
26422 : : {
26423 : : umul = gen_vec_widen_umult_even_v8si;
26424 : : nmode = V8SImode;
26425 : : }
26426 : 116 : else if (mode == V8DImode)
26427 : : {
26428 : : umul = gen_vec_widen_umult_even_v16si;
26429 : : nmode = V16SImode;
26430 : : }
26431 : : else
26432 : 0 : gcc_unreachable ();
26433 : :
26434 : :
26435 : : /* Multiply low parts. */
26436 : 432 : t1 = gen_reg_rtx (mode);
26437 : 432 : emit_insn (umul (t1, gen_lowpart (nmode, op1), gen_lowpart (nmode, op2)));
26438 : :
26439 : : /* Shift input vectors right 32 bits so we can multiply high parts. */
26440 : 432 : t6 = GEN_INT (32);
26441 : 432 : t2 = expand_binop (mode, lshr_optab, op1, t6, NULL, 1, OPTAB_DIRECT);
26442 : 432 : t3 = expand_binop (mode, lshr_optab, op2, t6, NULL, 1, OPTAB_DIRECT);
26443 : :
26444 : : /* Multiply high parts by low parts. */
26445 : 432 : t4 = gen_reg_rtx (mode);
26446 : 432 : t5 = gen_reg_rtx (mode);
26447 : 432 : emit_insn (umul (t4, gen_lowpart (nmode, t2), gen_lowpart (nmode, op2)));
26448 : 432 : emit_insn (umul (t5, gen_lowpart (nmode, t3), gen_lowpart (nmode, op1)));
26449 : :
26450 : : /* Combine and shift the highparts back. */
26451 : 432 : t4 = expand_binop (mode, add_optab, t4, t5, t4, 1, OPTAB_DIRECT);
26452 : 432 : t4 = expand_binop (mode, ashl_optab, t4, t6, t4, 1, OPTAB_DIRECT);
26453 : :
26454 : : /* Combine high and low parts. */
26455 : 432 : force_expand_binop (mode, add_optab, t1, t4, op0, 1, OPTAB_DIRECT);
26456 : : }
26457 : :
26458 : 534 : set_unique_reg_note (get_last_insn (), REG_EQUAL,
26459 : : gen_rtx_MULT (mode, op1, op2));
26460 : 534 : }
26461 : :
26462 : : /* Return 1 if control tansfer instruction INSN
26463 : : should be encoded with notrack prefix. */
26464 : :
26465 : : bool
26466 : 15022636 : ix86_notrack_prefixed_insn_p (rtx_insn *insn)
26467 : : {
26468 : 15022636 : if (!insn || !((flag_cf_protection & CF_BRANCH)))
26469 : : return false;
26470 : :
26471 : 4201727 : if (CALL_P (insn))
26472 : : {
26473 : 1442630 : rtx call = get_call_rtx_from (insn);
26474 : 1442630 : gcc_assert (call != NULL_RTX);
26475 : 1442630 : rtx addr = XEXP (call, 0);
26476 : :
26477 : : /* Do not emit 'notrack' if it's not an indirect call. */
26478 : 1442630 : if (MEM_P (addr)
26479 : 1442630 : && SYMBOL_REF_P (XEXP (addr, 0)))
26480 : : return false;
26481 : : else
26482 : 76861 : return find_reg_note (insn, REG_CALL_NOCF_CHECK, 0);
26483 : : }
26484 : :
26485 : 2759097 : if (JUMP_P (insn) && !flag_cet_switch)
26486 : : {
26487 : 2745741 : rtx target = JUMP_LABEL (insn);
26488 : 2745741 : if (target == NULL_RTX || ANY_RETURN_P (target))
26489 : : return false;
26490 : :
26491 : : /* Check the jump is a switch table. */
26492 : 2745703 : rtx_insn *label = as_a<rtx_insn *> (target);
26493 : 2745703 : rtx_insn *table = next_insn (label);
26494 : 2745703 : if (table == NULL_RTX || !JUMP_TABLE_DATA_P (table))
26495 : : return false;
26496 : : else
26497 : : return true;
26498 : : }
26499 : : return false;
26500 : : }
26501 : :
26502 : : /* Calculate integer abs() using only SSE2 instructions. */
26503 : :
26504 : : void
26505 : 555 : ix86_expand_sse2_abs (rtx target, rtx input)
26506 : : {
26507 : 555 : machine_mode mode = GET_MODE (target);
26508 : 555 : rtx tmp0, tmp1, x;
26509 : :
26510 : 555 : switch (mode)
26511 : : {
26512 : 21 : case E_V2DImode:
26513 : 21 : case E_V4DImode:
26514 : : /* For 64-bit signed integer X, with SSE4.2 use
26515 : : pxor t0, t0; pcmpgtq X, t0; pxor t0, X; psubq t0, X.
26516 : : Otherwise handle it similarly to V4SImode, except use 64 as W instead of
26517 : : 32 and use logical instead of arithmetic right shift (which is
26518 : : unimplemented) and subtract. */
26519 : 21 : if (TARGET_SSE4_2)
26520 : : {
26521 : 9 : tmp0 = gen_reg_rtx (mode);
26522 : 9 : tmp1 = gen_reg_rtx (mode);
26523 : 9 : emit_move_insn (tmp1, CONST0_RTX (mode));
26524 : 9 : if (mode == E_V2DImode)
26525 : 6 : emit_insn (gen_sse4_2_gtv2di3 (tmp0, tmp1, input));
26526 : : else
26527 : 3 : emit_insn (gen_avx2_gtv4di3 (tmp0, tmp1, input));
26528 : : }
26529 : : else
26530 : : {
26531 : 24 : tmp0 = expand_simple_binop (mode, LSHIFTRT, input,
26532 : 12 : GEN_INT (GET_MODE_UNIT_BITSIZE (mode)
26533 : : - 1), NULL, 0, OPTAB_DIRECT);
26534 : 12 : tmp0 = expand_simple_unop (mode, NEG, tmp0, NULL, false);
26535 : : }
26536 : :
26537 : 21 : tmp1 = expand_simple_binop (mode, XOR, tmp0, input,
26538 : : NULL, 0, OPTAB_DIRECT);
26539 : 21 : x = expand_simple_binop (mode, MINUS, tmp1, tmp0,
26540 : : target, 0, OPTAB_DIRECT);
26541 : 21 : break;
26542 : :
26543 : 49 : case E_V4SImode:
26544 : : /* For 32-bit signed integer X, the best way to calculate the absolute
26545 : : value of X is (((signed) X >> (W-1)) ^ X) - ((signed) X >> (W-1)). */
26546 : 49 : tmp0 = expand_simple_binop (mode, ASHIFTRT, input,
26547 : 49 : GEN_INT (GET_MODE_UNIT_BITSIZE (mode) - 1),
26548 : : NULL, 0, OPTAB_DIRECT);
26549 : 49 : tmp1 = expand_simple_binop (mode, XOR, tmp0, input,
26550 : : NULL, 0, OPTAB_DIRECT);
26551 : 49 : x = expand_simple_binop (mode, MINUS, tmp1, tmp0,
26552 : : target, 0, OPTAB_DIRECT);
26553 : 49 : break;
26554 : :
26555 : 85 : case E_V8HImode:
26556 : : /* For 16-bit signed integer X, the best way to calculate the absolute
26557 : : value of X is max (X, -X), as SSE2 provides the PMAXSW insn. */
26558 : 85 : tmp0 = expand_unop (mode, neg_optab, input, NULL_RTX, 0);
26559 : :
26560 : 85 : x = expand_simple_binop (mode, SMAX, tmp0, input,
26561 : : target, 0, OPTAB_DIRECT);
26562 : 85 : break;
26563 : :
26564 : 400 : case E_V16QImode:
26565 : : /* For 8-bit signed integer X, the best way to calculate the absolute
26566 : : value of X is min ((unsigned char) X, (unsigned char) (-X)),
26567 : : as SSE2 provides the PMINUB insn. */
26568 : 400 : tmp0 = expand_unop (mode, neg_optab, input, NULL_RTX, 0);
26569 : :
26570 : 400 : x = expand_simple_binop (V16QImode, UMIN, tmp0, input,
26571 : : target, 0, OPTAB_DIRECT);
26572 : 400 : break;
26573 : :
26574 : 0 : default:
26575 : 0 : gcc_unreachable ();
26576 : : }
26577 : :
26578 : 555 : if (x != target)
26579 : 0 : emit_move_insn (target, x);
26580 : 555 : }
26581 : :
26582 : : /* Expand an extract from a vector register through pextr insn.
26583 : : Return true if successful. */
26584 : :
26585 : : bool
26586 : 108555 : ix86_expand_pextr (rtx *operands)
26587 : : {
26588 : 108555 : rtx dst = operands[0];
26589 : 108555 : rtx src = operands[1];
26590 : :
26591 : 108555 : unsigned int size = INTVAL (operands[2]);
26592 : 108555 : unsigned int pos = INTVAL (operands[3]);
26593 : :
26594 : 108555 : if (SUBREG_P (dst))
26595 : : {
26596 : : /* Reject non-lowpart subregs. */
26597 : 64622 : if (SUBREG_BYTE (dst) > 0)
26598 : : return false;
26599 : 64527 : dst = SUBREG_REG (dst);
26600 : : }
26601 : :
26602 : 108460 : if (SUBREG_P (src))
26603 : : {
26604 : 39741 : pos += SUBREG_BYTE (src) * BITS_PER_UNIT;
26605 : 39741 : src = SUBREG_REG (src);
26606 : : }
26607 : :
26608 : 108460 : switch (GET_MODE (src))
26609 : : {
26610 : 0 : case E_V16QImode:
26611 : 0 : case E_V8HImode:
26612 : 0 : case E_V4SImode:
26613 : 0 : case E_V2DImode:
26614 : 0 : case E_V1TImode:
26615 : 0 : {
26616 : 0 : machine_mode srcmode, dstmode;
26617 : 0 : rtx d, pat;
26618 : :
26619 : 0 : if (!int_mode_for_size (size, 0).exists (&dstmode))
26620 : 0 : return false;
26621 : :
26622 : 0 : switch (dstmode)
26623 : : {
26624 : 0 : case E_QImode:
26625 : 0 : if (!TARGET_SSE4_1)
26626 : : return false;
26627 : : srcmode = V16QImode;
26628 : : break;
26629 : :
26630 : 0 : case E_HImode:
26631 : 0 : if (!TARGET_SSE2)
26632 : : return false;
26633 : : srcmode = V8HImode;
26634 : : break;
26635 : :
26636 : 0 : case E_SImode:
26637 : 0 : if (!TARGET_SSE4_1)
26638 : : return false;
26639 : : srcmode = V4SImode;
26640 : : break;
26641 : :
26642 : 0 : case E_DImode:
26643 : 0 : gcc_assert (TARGET_64BIT);
26644 : 0 : if (!TARGET_SSE4_1)
26645 : : return false;
26646 : : srcmode = V2DImode;
26647 : : break;
26648 : :
26649 : : default:
26650 : : return false;
26651 : : }
26652 : :
26653 : : /* Reject extractions from misaligned positions. */
26654 : 0 : if (pos & (size-1))
26655 : : return false;
26656 : :
26657 : 0 : if (GET_MODE (dst) == dstmode)
26658 : : d = dst;
26659 : : else
26660 : 0 : d = gen_reg_rtx (dstmode);
26661 : :
26662 : : /* Construct insn pattern. */
26663 : 0 : pat = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (1, GEN_INT (pos / size)));
26664 : 0 : pat = gen_rtx_VEC_SELECT (dstmode, gen_lowpart (srcmode, src), pat);
26665 : :
26666 : : /* Let the rtl optimizers know about the zero extension performed. */
26667 : 0 : if (dstmode == QImode || dstmode == HImode)
26668 : : {
26669 : 0 : pat = gen_rtx_ZERO_EXTEND (SImode, pat);
26670 : 0 : d = gen_lowpart (SImode, d);
26671 : : }
26672 : :
26673 : 0 : emit_insn (gen_rtx_SET (d, pat));
26674 : :
26675 : 0 : if (d != dst)
26676 : 0 : emit_move_insn (dst, gen_lowpart (GET_MODE (dst), d));
26677 : : return true;
26678 : : }
26679 : :
26680 : : default:
26681 : : return false;
26682 : : }
26683 : : }
26684 : :
26685 : : /* Expand an insert into a vector register through pinsr insn.
26686 : : Return true if successful. */
26687 : :
26688 : : bool
26689 : 111986 : ix86_expand_pinsr (rtx *operands)
26690 : : {
26691 : 111986 : rtx dst = operands[0];
26692 : 111986 : rtx src = operands[3];
26693 : :
26694 : 111986 : unsigned int size = INTVAL (operands[1]);
26695 : 111986 : unsigned int pos = INTVAL (operands[2]);
26696 : :
26697 : 111986 : if (SUBREG_P (dst))
26698 : : {
26699 : 65640 : pos += SUBREG_BYTE (dst) * BITS_PER_UNIT;
26700 : 65640 : dst = SUBREG_REG (dst);
26701 : : }
26702 : :
26703 : 111986 : switch (GET_MODE (dst))
26704 : : {
26705 : 20 : case E_V16QImode:
26706 : 20 : case E_V8HImode:
26707 : 20 : case E_V4SImode:
26708 : 20 : case E_V2DImode:
26709 : 20 : case E_V1TImode:
26710 : 20 : {
26711 : 20 : machine_mode srcmode, dstmode;
26712 : 20 : rtx (*pinsr)(rtx, rtx, rtx, rtx);
26713 : 20 : rtx d;
26714 : :
26715 : 20 : if (!int_mode_for_size (size, 0).exists (&srcmode))
26716 : 0 : return false;
26717 : :
26718 : 20 : switch (srcmode)
26719 : : {
26720 : 1 : case E_QImode:
26721 : 1 : if (!TARGET_SSE4_1)
26722 : : return false;
26723 : : dstmode = V16QImode;
26724 : : pinsr = gen_sse4_1_pinsrb;
26725 : : break;
26726 : :
26727 : 5 : case E_HImode:
26728 : 5 : if (!TARGET_SSE2)
26729 : : return false;
26730 : : dstmode = V8HImode;
26731 : : pinsr = gen_sse2_pinsrw;
26732 : : break;
26733 : :
26734 : 14 : case E_SImode:
26735 : 14 : if (!TARGET_SSE4_1)
26736 : : return false;
26737 : : dstmode = V4SImode;
26738 : : pinsr = gen_sse4_1_pinsrd;
26739 : : break;
26740 : :
26741 : 0 : case E_DImode:
26742 : 0 : gcc_assert (TARGET_64BIT);
26743 : 0 : if (!TARGET_SSE4_1)
26744 : : return false;
26745 : : dstmode = V2DImode;
26746 : : pinsr = gen_sse4_1_pinsrq;
26747 : : break;
26748 : :
26749 : : default:
26750 : : return false;
26751 : : }
26752 : :
26753 : : /* Reject insertions to misaligned positions. */
26754 : 7 : if (pos & (size-1))
26755 : : return false;
26756 : :
26757 : 7 : if (SUBREG_P (src))
26758 : : {
26759 : 7 : unsigned int srcpos = SUBREG_BYTE (src);
26760 : :
26761 : 7 : if (srcpos > 0)
26762 : : {
26763 : 0 : rtx extr_ops[4];
26764 : :
26765 : 0 : extr_ops[0] = gen_reg_rtx (srcmode);
26766 : 0 : extr_ops[1] = gen_lowpart (srcmode, SUBREG_REG (src));
26767 : 0 : extr_ops[2] = GEN_INT (size);
26768 : 0 : extr_ops[3] = GEN_INT (srcpos * BITS_PER_UNIT);
26769 : :
26770 : 0 : if (!ix86_expand_pextr (extr_ops))
26771 : 0 : return false;
26772 : :
26773 : 0 : src = extr_ops[0];
26774 : : }
26775 : : else
26776 : 7 : src = gen_lowpart (srcmode, SUBREG_REG (src));
26777 : : }
26778 : :
26779 : 7 : if (GET_MODE (dst) == dstmode)
26780 : : d = dst;
26781 : : else
26782 : 7 : d = gen_reg_rtx (dstmode);
26783 : :
26784 : 7 : emit_insn (pinsr (d, gen_lowpart (dstmode, dst),
26785 : 7 : gen_lowpart (srcmode, src),
26786 : 7 : GEN_INT (1 << (pos / size))));
26787 : 7 : if (d != dst)
26788 : 7 : emit_move_insn (dst, gen_lowpart (GET_MODE (dst), d));
26789 : : return true;
26790 : : }
26791 : :
26792 : : default:
26793 : : return false;
26794 : : }
26795 : : }
26796 : :
26797 : : /* All CPUs prefer to avoid cross-lane operations so perform reductions
26798 : : upper against lower halves up to SSE reg size. */
26799 : :
26800 : : machine_mode
26801 : 1867 : ix86_split_reduction (machine_mode mode)
26802 : : {
26803 : : /* Reduce lowpart against highpart until we reach SSE reg width to
26804 : : avoid cross-lane operations. */
26805 : 1867 : switch (mode)
26806 : : {
26807 : : case E_V8DImode:
26808 : : case E_V4DImode:
26809 : : return V2DImode;
26810 : 9 : case E_V16SImode:
26811 : 9 : case E_V8SImode:
26812 : 9 : return V4SImode;
26813 : 8 : case E_V32HImode:
26814 : 8 : case E_V16HImode:
26815 : 8 : return V8HImode;
26816 : 4 : case E_V64QImode:
26817 : 4 : case E_V32QImode:
26818 : 4 : return V16QImode;
26819 : 5 : case E_V16SFmode:
26820 : 5 : case E_V8SFmode:
26821 : 5 : return V4SFmode;
26822 : 16 : case E_V8DFmode:
26823 : 16 : case E_V4DFmode:
26824 : 16 : return V2DFmode;
26825 : 1820 : default:
26826 : 1820 : return mode;
26827 : : }
26828 : : }
26829 : :
26830 : : /* Generate call to __divmoddi4. */
26831 : :
26832 : : void
26833 : 902 : ix86_expand_divmod_libfunc (rtx libfunc, machine_mode mode,
26834 : : rtx op0, rtx op1,
26835 : : rtx *quot_p, rtx *rem_p)
26836 : : {
26837 : 1804 : rtx rem = assign_stack_temp (mode, GET_MODE_SIZE (mode));
26838 : :
26839 : 902 : rtx quot = emit_library_call_value (libfunc, NULL_RTX, LCT_NORMAL,
26840 : : mode, op0, mode, op1, mode,
26841 : 902 : XEXP (rem, 0), Pmode);
26842 : 902 : *quot_p = quot;
26843 : 902 : *rem_p = rem;
26844 : 902 : }
26845 : :
26846 : : void
26847 : 64 : ix86_expand_atomic_fetch_op_loop (rtx target, rtx mem, rtx val,
26848 : : enum rtx_code code, bool after,
26849 : : bool doubleword)
26850 : : {
26851 : 64 : rtx old_reg, new_reg, old_mem, success;
26852 : 64 : machine_mode mode = GET_MODE (target);
26853 : 64 : rtx_code_label *loop_label = NULL;
26854 : :
26855 : 64 : old_reg = gen_reg_rtx (mode);
26856 : 64 : new_reg = old_reg;
26857 : 64 : old_mem = copy_to_reg (mem);
26858 : 64 : loop_label = gen_label_rtx ();
26859 : 64 : emit_label (loop_label);
26860 : 64 : emit_move_insn (old_reg, old_mem);
26861 : :
26862 : : /* return value for atomic_fetch_op. */
26863 : 64 : if (!after)
26864 : 32 : emit_move_insn (target, old_reg);
26865 : :
26866 : 64 : if (code == NOT)
26867 : : {
26868 : 16 : new_reg = expand_simple_binop (mode, AND, new_reg, val, NULL_RTX,
26869 : : true, OPTAB_LIB_WIDEN);
26870 : 16 : new_reg = expand_simple_unop (mode, code, new_reg, NULL_RTX, true);
26871 : : }
26872 : : else
26873 : 48 : new_reg = expand_simple_binop (mode, code, new_reg, val, NULL_RTX,
26874 : : true, OPTAB_LIB_WIDEN);
26875 : :
26876 : : /* return value for atomic_op_fetch. */
26877 : 64 : if (after)
26878 : 32 : emit_move_insn (target, new_reg);
26879 : :
26880 : 64 : success = NULL_RTX;
26881 : :
26882 : 64 : ix86_expand_cmpxchg_loop (&success, old_mem, mem, old_reg, new_reg,
26883 : : gen_int_mode (MEMMODEL_SYNC_SEQ_CST,
26884 : : SImode),
26885 : : doubleword, loop_label);
26886 : 64 : }
26887 : :
26888 : : /* Relax cmpxchg instruction, param loop_label indicates whether
26889 : : the instruction should be relaxed with a pause loop. If not,
26890 : : it will be relaxed to an atomic load + compare, and skip
26891 : : cmpxchg instruction if mem != exp_input. */
26892 : :
26893 : : void
26894 : 72 : ix86_expand_cmpxchg_loop (rtx *ptarget_bool, rtx target_val,
26895 : : rtx mem, rtx exp_input, rtx new_input,
26896 : : rtx mem_model, bool doubleword,
26897 : : rtx_code_label *loop_label)
26898 : : {
26899 : 72 : rtx_code_label *cmp_label = NULL;
26900 : 72 : rtx_code_label *done_label = NULL;
26901 : 72 : rtx target_bool = NULL_RTX, new_mem = NULL_RTX;
26902 : 72 : rtx (*gen) (rtx, rtx, rtx, rtx, rtx) = NULL;
26903 : 72 : rtx (*gendw) (rtx, rtx, rtx, rtx, rtx, rtx) = NULL;
26904 : 72 : machine_mode mode = GET_MODE (target_val), hmode = mode;
26905 : :
26906 : 72 : if (*ptarget_bool == NULL)
26907 : 64 : target_bool = gen_reg_rtx (QImode);
26908 : : else
26909 : : target_bool = *ptarget_bool;
26910 : :
26911 : 72 : cmp_label = gen_label_rtx ();
26912 : 72 : done_label = gen_label_rtx ();
26913 : :
26914 : 72 : new_mem = gen_reg_rtx (mode);
26915 : : /* Load memory first. */
26916 : 72 : expand_atomic_load (new_mem, mem, MEMMODEL_SEQ_CST);
26917 : :
26918 : 72 : switch (mode)
26919 : : {
26920 : : case E_TImode:
26921 : : gendw = gen_atomic_compare_and_swapti_doubleword;
26922 : : hmode = DImode;
26923 : : break;
26924 : 18 : case E_DImode:
26925 : 18 : if (doubleword)
26926 : : {
26927 : : gendw = gen_atomic_compare_and_swapdi_doubleword;
26928 : : hmode = SImode;
26929 : : }
26930 : : else
26931 : : gen = gen_atomic_compare_and_swapdi_1;
26932 : : break;
26933 : 18 : case E_SImode:
26934 : 18 : gen = gen_atomic_compare_and_swapsi_1;
26935 : 18 : break;
26936 : 18 : case E_HImode:
26937 : 18 : gen = gen_atomic_compare_and_swaphi_1;
26938 : 18 : break;
26939 : 18 : case E_QImode:
26940 : 18 : gen = gen_atomic_compare_and_swapqi_1;
26941 : 18 : break;
26942 : 0 : default:
26943 : 0 : gcc_unreachable ();
26944 : : }
26945 : :
26946 : : /* Compare mem value with expected value. */
26947 : 54 : if (doubleword)
26948 : : {
26949 : 0 : rtx low_new_mem = gen_lowpart (hmode, new_mem);
26950 : 0 : rtx low_exp_input = gen_lowpart (hmode, exp_input);
26951 : 0 : rtx high_new_mem = gen_highpart (hmode, new_mem);
26952 : 0 : rtx high_exp_input = gen_highpart (hmode, exp_input);
26953 : 0 : emit_cmp_and_jump_insns (low_new_mem, low_exp_input, NE, NULL_RTX,
26954 : : hmode, 1, cmp_label,
26955 : : profile_probability::guessed_never ());
26956 : 0 : emit_cmp_and_jump_insns (high_new_mem, high_exp_input, NE, NULL_RTX,
26957 : : hmode, 1, cmp_label,
26958 : : profile_probability::guessed_never ());
26959 : : }
26960 : : else
26961 : 72 : emit_cmp_and_jump_insns (new_mem, exp_input, NE, NULL_RTX,
26962 : 72 : GET_MODE (exp_input), 1, cmp_label,
26963 : : profile_probability::guessed_never ());
26964 : :
26965 : : /* Directly emits cmpxchg here. */
26966 : 72 : if (doubleword)
26967 : 0 : emit_insn (gendw (target_val, mem, exp_input,
26968 : 0 : gen_lowpart (hmode, new_input),
26969 : : gen_highpart (hmode, new_input),
26970 : : mem_model));
26971 : : else
26972 : 72 : emit_insn (gen (target_val, mem, exp_input, new_input, mem_model));
26973 : :
26974 : 72 : if (!loop_label)
26975 : : {
26976 : 8 : emit_jump_insn (gen_jump (done_label));
26977 : 8 : emit_barrier ();
26978 : 8 : emit_label (cmp_label);
26979 : 8 : emit_move_insn (target_val, new_mem);
26980 : 8 : emit_label (done_label);
26981 : 8 : ix86_expand_setcc (target_bool, EQ, gen_rtx_REG (CCZmode, FLAGS_REG),
26982 : : const0_rtx);
26983 : : }
26984 : : else
26985 : : {
26986 : 64 : ix86_expand_setcc (target_bool, EQ, gen_rtx_REG (CCZmode, FLAGS_REG),
26987 : : const0_rtx);
26988 : 64 : emit_cmp_and_jump_insns (target_bool, const0_rtx, EQ, const0_rtx,
26989 : 64 : GET_MODE (target_bool), 1, loop_label,
26990 : : profile_probability::guessed_never ());
26991 : 64 : emit_jump_insn (gen_jump (done_label));
26992 : 64 : emit_barrier ();
26993 : :
26994 : : /* If mem is not expected, pause and loop back. */
26995 : 64 : emit_label (cmp_label);
26996 : 64 : emit_move_insn (target_val, new_mem);
26997 : 64 : emit_insn (gen_pause ());
26998 : 64 : emit_jump_insn (gen_jump (loop_label));
26999 : 64 : emit_barrier ();
27000 : 64 : emit_label (done_label);
27001 : : }
27002 : :
27003 : 72 : *ptarget_bool = target_bool;
27004 : 72 : }
27005 : :
27006 : : /* Convert a BFmode VAL to SFmode without signaling sNaNs.
27007 : : This is done by returning SF SUBREG of ((HI SUBREG) (VAL)) << 16. */
27008 : :
27009 : : rtx
27010 : 2832 : ix86_expand_fast_convert_bf_to_sf (rtx val)
27011 : : {
27012 : 2832 : rtx op = gen_lowpart (HImode, val), ret;
27013 : 2832 : if (CONST_INT_P (op))
27014 : : {
27015 : 514 : ret = simplify_const_unary_operation (FLOAT_EXTEND, SFmode,
27016 : : val, BFmode);
27017 : 514 : if (ret)
27018 : : return ret;
27019 : : /* FLOAT_EXTEND simplification will fail if VAL is a sNaN. */
27020 : 1 : ret = gen_reg_rtx (SImode);
27021 : 1 : emit_move_insn (ret, GEN_INT (INTVAL (op) & 0xffff));
27022 : 1 : emit_insn (gen_ashlsi3 (ret, ret, GEN_INT (16)));
27023 : 1 : return gen_lowpart (SFmode, ret);
27024 : : }
27025 : :
27026 : 2318 : ret = gen_reg_rtx (SFmode);
27027 : 2318 : emit_insn (gen_extendbfsf2_1 (ret, force_reg (BFmode, val)));
27028 : 2318 : return ret;
27029 : : }
27030 : :
27031 : : rtx
27032 : 65576 : ix86_gen_ccmp_first (rtx_insn **prep_seq, rtx_insn **gen_seq,
27033 : : rtx_code code, tree treeop0, tree treeop1)
27034 : : {
27035 : 65576 : if (!TARGET_APX_CCMP)
27036 : : return NULL_RTX;
27037 : :
27038 : 65576 : rtx op0, op1, res;
27039 : 65576 : machine_mode op_mode;
27040 : :
27041 : 65576 : start_sequence ();
27042 : 65576 : expand_operands (treeop0, treeop1, NULL_RTX, &op0, &op1, EXPAND_NORMAL);
27043 : :
27044 : 65576 : op_mode = GET_MODE (op0);
27045 : 65576 : if (op_mode == VOIDmode)
27046 : 0 : op_mode = GET_MODE (op1);
27047 : :
27048 : : /* We only supports following scalar comparisons that use just 1
27049 : : instruction: DI/SI/QI/HI/DF/SF/HF.
27050 : : Unordered/Ordered compare cannot be corretly indentified by
27051 : : ccmp so they are not supported. */
27052 : 98348 : if (!(op_mode == DImode || op_mode == SImode || op_mode == HImode
27053 : 65576 : || op_mode == QImode || op_mode == DFmode || op_mode == SFmode
27054 : 32772 : || op_mode == HFmode)
27055 : 32806 : || code == ORDERED
27056 : 32806 : || code == UNORDERED)
27057 : : {
27058 : 32770 : end_sequence ();
27059 : 32770 : return NULL_RTX;
27060 : : }
27061 : :
27062 : : /* Canonicalize the operands according to mode. */
27063 : 32806 : if (SCALAR_INT_MODE_P (op_mode))
27064 : : {
27065 : 32799 : if (!nonimmediate_operand (op0, op_mode))
27066 : 0 : op0 = force_reg (op_mode, op0);
27067 : 32799 : if (!x86_64_general_operand (op1, op_mode))
27068 : 0 : op1 = force_reg (op_mode, op1);
27069 : : }
27070 : : else
27071 : : {
27072 : : /* op0/op1 can be canonicallized from expand_fp_compare, so
27073 : : just adjust the code to make it generate supported fp
27074 : : condition. */
27075 : 7 : if (ix86_fp_compare_code_to_integer (code) == UNKNOWN)
27076 : : {
27077 : : /* First try to split condition if we don't need to honor
27078 : : NaNs, as the ORDERED/UNORDERED check always fall
27079 : : through. */
27080 : 6 : if (!HONOR_NANS (op_mode))
27081 : : {
27082 : 6 : rtx_code first_code;
27083 : 6 : split_comparison (code, op_mode, &first_code, &code);
27084 : : }
27085 : : /* Otherwise try to swap the operand order and check if
27086 : : the comparison is supported. */
27087 : : else
27088 : : {
27089 : 0 : code = swap_condition (code);
27090 : 0 : std::swap (op0, op1);
27091 : : }
27092 : :
27093 : 6 : if (ix86_fp_compare_code_to_integer (code) == UNKNOWN)
27094 : : {
27095 : 0 : end_sequence ();
27096 : 0 : return NULL_RTX;
27097 : : }
27098 : : }
27099 : : }
27100 : :
27101 : 32806 : *prep_seq = end_sequence ();
27102 : :
27103 : 32806 : start_sequence ();
27104 : :
27105 : 32806 : res = ix86_expand_compare (code, op0, op1);
27106 : :
27107 : 32806 : if (!res)
27108 : : {
27109 : : end_sequence ();
27110 : : return NULL_RTX;
27111 : : }
27112 : 32806 : *gen_seq = end_sequence ();
27113 : :
27114 : 32806 : return res;
27115 : : }
27116 : :
27117 : : rtx
27118 : 32809 : ix86_gen_ccmp_next (rtx_insn **prep_seq, rtx_insn **gen_seq, rtx prev,
27119 : : rtx_code cmp_code, tree treeop0, tree treeop1,
27120 : : rtx_code bit_code)
27121 : : {
27122 : 32809 : if (!TARGET_APX_CCMP)
27123 : : return NULL_RTX;
27124 : :
27125 : 32809 : rtx op0, op1, target;
27126 : 32809 : machine_mode op_mode, cmp_mode, cc_mode = CCmode;
27127 : 32809 : int unsignedp = TYPE_UNSIGNED (TREE_TYPE (treeop0));
27128 : 32809 : insn_code icode;
27129 : 32809 : rtx_code prev_code;
27130 : 32809 : struct expand_operand ops[5];
27131 : 32809 : int dfv;
27132 : :
27133 : : /* Exit early for non integer modes to avoid O(n^2) part of expand_operands. */
27134 : 32809 : cmp_mode = op_mode = TYPE_MODE (TREE_TYPE (treeop0));
27135 : :
27136 : 32809 : if (!(op_mode == DImode || op_mode == SImode || op_mode == HImode
27137 : : || op_mode == QImode))
27138 : : return NULL_RTX;
27139 : :
27140 : 32 : push_to_sequence (*prep_seq);
27141 : 32 : expand_operands (treeop0, treeop1, NULL_RTX, &op0, &op1, EXPAND_NORMAL);
27142 : :
27143 : 32 : icode = code_for_ccmp (op_mode);
27144 : :
27145 : 32 : op0 = prepare_operand (icode, op0, 2, op_mode, cmp_mode, unsignedp);
27146 : 32 : op1 = prepare_operand (icode, op1, 3, op_mode, cmp_mode, unsignedp);
27147 : 32 : if (!op0 || !op1)
27148 : : {
27149 : 0 : end_sequence ();
27150 : 0 : return NULL_RTX;
27151 : : }
27152 : :
27153 : 32 : *prep_seq = end_sequence ();
27154 : :
27155 : 32 : target = gen_rtx_REG (cc_mode, FLAGS_REG);
27156 : 32 : dfv = ix86_get_flags_cc ((rtx_code) cmp_code);
27157 : :
27158 : 32 : prev_code = GET_CODE (prev);
27159 : : /* Fixup FP compare code here. */
27160 : 32 : if (GET_MODE (XEXP (prev, 0)) == CCFPmode)
27161 : 7 : prev_code = ix86_fp_compare_code_to_integer (prev_code);
27162 : :
27163 : 32 : if (bit_code != AND)
27164 : 17 : prev_code = reverse_condition (prev_code);
27165 : : else
27166 : 15 : dfv = (int)(dfv ^ 1);
27167 : :
27168 : 32 : prev = gen_rtx_fmt_ee (prev_code, VOIDmode, XEXP (prev, 0),
27169 : : const0_rtx);
27170 : :
27171 : 32 : create_fixed_operand (&ops[0], target);
27172 : 32 : create_fixed_operand (&ops[1], prev);
27173 : 32 : create_fixed_operand (&ops[2], op0);
27174 : 32 : create_fixed_operand (&ops[3], op1);
27175 : 32 : create_fixed_operand (&ops[4], GEN_INT (dfv));
27176 : :
27177 : 32 : push_to_sequence (*gen_seq);
27178 : 32 : if (!maybe_expand_insn (icode, 5, ops))
27179 : : {
27180 : 0 : end_sequence ();
27181 : 0 : return NULL_RTX;
27182 : : }
27183 : :
27184 : 32 : *gen_seq = end_sequence ();
27185 : :
27186 : 32 : return gen_rtx_fmt_ee ((rtx_code) cmp_code, VOIDmode, target, const0_rtx);
27187 : : }
27188 : :
27189 : : /* Attempt to convert a CONST_VECTOR into a bcst_mem_operand.
27190 : : Returns NULL_RTX if X is cannot be expressed as a suitable
27191 : : VEC_DUPLICATE in mode MODE. */
27192 : :
27193 : : static rtx
27194 : 47 : ix86_gen_bcst_mem (machine_mode mode, rtx x)
27195 : : {
27196 : 47 : if (!TARGET_AVX512F
27197 : 47 : || !CONST_VECTOR_P (x)
27198 : 63 : || (!TARGET_AVX512VL && GET_MODE_SIZE (mode) != 64)
27199 : 142 : || !VALID_BCST_MODE_P (GET_MODE_INNER (mode))
27200 : : /* Disallow HFmode broadcast. */
27201 : 123 : || GET_MODE_SIZE (GET_MODE_INNER (mode)) < 4)
27202 : : return NULL_RTX;
27203 : :
27204 : 21 : rtx cst = CONST_VECTOR_ELT (x, 0);
27205 : 21 : if (!CONST_SCALAR_INT_P (cst)
27206 : 15 : && !CONST_DOUBLE_P (cst)
27207 : 0 : && !CONST_FIXED_P (cst))
27208 : : return NULL_RTX;
27209 : :
27210 : 21 : int n_elts = GET_MODE_NUNITS (mode);
27211 : 42 : if (CONST_VECTOR_NUNITS (x) != n_elts)
27212 : : return NULL_RTX;
27213 : :
27214 : 150 : for (int i = 1; i < n_elts; i++)
27215 : 129 : if (!rtx_equal_p (cst, CONST_VECTOR_ELT (x, i)))
27216 : : return NULL_RTX;
27217 : :
27218 : 42 : rtx mem = force_const_mem (GET_MODE_INNER (mode), cst);
27219 : 21 : return gen_rtx_VEC_DUPLICATE (mode, validize_mem (mem));
27220 : : }
27221 : :
27222 : : /* Determine the ternlog immediate index that implements 3-operand
27223 : : ternary logic expression OP. This uses and modifies the 3 element
27224 : : array ARGS to record and check the leaves, either 3 REGs, or 2 REGs
27225 : : and MEM. Returns an index between 0 and 255 for a valid ternlog,
27226 : : or -1 if the expression isn't suitable. */
27227 : :
27228 : : int
27229 : 7097114 : ix86_ternlog_idx (rtx op, rtx *args)
27230 : : {
27231 : 7097114 : int idx0, idx1;
27232 : :
27233 : 7097114 : if (!op)
27234 : : return -1;
27235 : :
27236 : 7097114 : switch (GET_CODE (op))
27237 : : {
27238 : 737562 : case SUBREG:
27239 : 737562 : if (!register_operand (op, GET_MODE (op)))
27240 : : return -1;
27241 : : /* FALLTHRU */
27242 : :
27243 : 3468170 : case REG:
27244 : 3468170 : if (!args[0])
27245 : : {
27246 : 1800155 : args[0] = op;
27247 : 1800155 : return 0xf0;
27248 : : }
27249 : 1668015 : if (rtx_equal_p (op, args[0]))
27250 : : return 0xf0;
27251 : 1642113 : if (!args[1])
27252 : : {
27253 : 1382236 : args[1] = op;
27254 : 1382236 : return 0xcc;
27255 : : }
27256 : 259877 : if (rtx_equal_p (op, args[1]))
27257 : : return 0xcc;
27258 : 243457 : if (!args[2])
27259 : : {
27260 : 221515 : args[2] = op;
27261 : 221515 : return 0xaa;
27262 : : }
27263 : 21942 : if (rtx_equal_p (op, args[2]))
27264 : : return 0xaa;
27265 : : return -1;
27266 : :
27267 : 18033 : case VEC_DUPLICATE:
27268 : 18033 : if (!bcst_mem_operand (op, GET_MODE (op)))
27269 : : return -1;
27270 : 302 : goto do_mem_operand;
27271 : :
27272 : 364690 : case MEM:
27273 : 364690 : if (!memory_operand (op, GET_MODE (op)))
27274 : : return -1;
27275 : 364516 : if (MEM_P (op)
27276 : 364516 : && MEM_VOLATILE_P (op)
27277 : 364610 : && !volatile_ok)
27278 : : return -1;
27279 : : /* FALLTHRU */
27280 : :
27281 : 471757 : case CONST_VECTOR:
27282 : 471757 : do_mem_operand:
27283 : 471757 : if (!args[2])
27284 : : {
27285 : 424787 : args[2] = op;
27286 : 424787 : return 0xaa;
27287 : : }
27288 : : /* Maximum of one volatile memory reference per expression. */
27289 : 46970 : if (side_effects_p (op))
27290 : : return -1;
27291 : 46970 : if (rtx_equal_p (op, args[2]))
27292 : : return 0xaa;
27293 : : /* Check if CONST_VECTOR is the ones-complement of args[2]. */
27294 : 46939 : if (CONST_VECTOR_P (op)
27295 : 3335 : && CONST_VECTOR_P (args[2])
27296 : 47174 : && rtx_equal_p (simplify_const_unary_operation (NOT, GET_MODE (op),
27297 : 235 : op, GET_MODE (op)),
27298 : : args[2]))
27299 : : return 0x55;
27300 : 46762 : if (!args[0])
27301 : : {
27302 : 44999 : args[0] = op;
27303 : 44999 : return 0xf0;
27304 : : }
27305 : 1763 : if (rtx_equal_p (op, args[0]))
27306 : : return 0xf0;
27307 : : /* Check if CONST_VECTOR is the ones-complement of args[0]. */
27308 : 1763 : if (CONST_VECTOR_P (op)
27309 : 101 : && CONST_VECTOR_P (args[0])
27310 : 1805 : && rtx_equal_p (simplify_const_unary_operation (NOT, GET_MODE (op),
27311 : 42 : op, GET_MODE (op)),
27312 : : args[0]))
27313 : : return 0x0f;
27314 : 1721 : if (!args[1])
27315 : : {
27316 : 1709 : args[1] = op;
27317 : 1709 : return 0xcc;
27318 : : }
27319 : 12 : if (rtx_equal_p (op, args[1]))
27320 : : return 0xcc;
27321 : : /* Check if CONST_VECTOR is the ones-complement of args[1]. */
27322 : 12 : if (CONST_VECTOR_P (op)
27323 : 0 : && CONST_VECTOR_P (args[1])
27324 : 12 : && rtx_equal_p (simplify_const_unary_operation (NOT, GET_MODE (op),
27325 : 0 : op, GET_MODE (op)),
27326 : : args[1]))
27327 : : return 0x33;
27328 : : return -1;
27329 : :
27330 : 171096 : case NOT:
27331 : 171096 : idx0 = ix86_ternlog_idx (XEXP (op, 0), args);
27332 : 171096 : return (idx0 >= 0) ? idx0 ^ 0xff : -1;
27333 : :
27334 : 1258126 : case AND:
27335 : 1258126 : idx0 = ix86_ternlog_idx (XEXP (op, 0), args);
27336 : 1258126 : if (idx0 < 0)
27337 : : return -1;
27338 : 1037055 : idx1 = ix86_ternlog_idx (XEXP (op, 1), args);
27339 : 1037055 : return (idx1 >= 0) ? idx0 & idx1 : -1;
27340 : :
27341 : 945924 : case IOR:
27342 : 945924 : idx0 = ix86_ternlog_idx (XEXP (op, 0), args);
27343 : 945924 : if (idx0 < 0)
27344 : : return -1;
27345 : 701903 : idx1 = ix86_ternlog_idx (XEXP (op, 1), args);
27346 : 701903 : return (idx1 >= 0) ? idx0 | idx1 : -1;
27347 : :
27348 : 392393 : case XOR:
27349 : 392393 : idx0 = ix86_ternlog_idx (XEXP (op, 0), args);
27350 : 392393 : if (idx0 < 0)
27351 : : return -1;
27352 : 373849 : if (vector_all_ones_operand (XEXP (op, 1), GET_MODE (op)))
27353 : 6111 : return idx0 ^ 0xff;
27354 : 367738 : idx1 = ix86_ternlog_idx (XEXP (op, 1), args);
27355 : 367738 : return (idx1 >= 0) ? idx0 ^ idx1 : -1;
27356 : :
27357 : 7376 : case UNSPEC:
27358 : 7376 : if (XINT (op, 1) != UNSPEC_VTERNLOG
27359 : 0 : || XVECLEN (op, 0) != 4
27360 : 0 : || !CONST_INT_P (XVECEXP (op, 0, 3)))
27361 : : return -1;
27362 : :
27363 : : /* TODO: Handle permuted operands. */
27364 : 0 : if (ix86_ternlog_idx (XVECEXP (op, 0, 0), args) != 0xf0
27365 : 0 : || ix86_ternlog_idx (XVECEXP (op, 0, 1), args) != 0xcc
27366 : 0 : || ix86_ternlog_idx (XVECEXP (op, 0, 2), args) != 0xaa)
27367 : 0 : return -1;
27368 : 0 : return INTVAL (XVECEXP (op, 0, 3));
27369 : :
27370 : : default:
27371 : : return -1;
27372 : : }
27373 : : }
27374 : :
27375 : : /* Return TRUE if OP (in mode MODE) is the leaf of a ternary logic
27376 : : expression, such as a register or a memory reference. */
27377 : :
27378 : : bool
27379 : 3294258 : ix86_ternlog_leaf_p (rtx op, machine_mode mode)
27380 : : {
27381 : : /* We can't use memory_operand here, as it may return a different
27382 : : value before and after reload (for volatile MEMs) which creates
27383 : : problems splitting instructions. */
27384 : 3294258 : return register_operand (op, mode)
27385 : 724486 : || MEM_P (op)
27386 : 373506 : || CONST_VECTOR_P (op)
27387 : 3567065 : || bcst_mem_operand (op, mode);
27388 : : }
27389 : :
27390 : : /* Test whether OP is a 3-operand ternary logic expression suitable
27391 : : for use in a ternlog instruction. */
27392 : :
27393 : : bool
27394 : 2187767 : ix86_ternlog_operand_p (rtx op)
27395 : : {
27396 : 2187767 : rtx op0, op1;
27397 : 2187767 : rtx args[3];
27398 : :
27399 : 2187767 : args[0] = NULL_RTX;
27400 : 2187767 : args[1] = NULL_RTX;
27401 : 2187767 : args[2] = NULL_RTX;
27402 : 2187767 : int idx = ix86_ternlog_idx (op, args);
27403 : 2187767 : if (idx < 0)
27404 : : return false;
27405 : :
27406 : : /* Don't match simple (binary or unary) expressions. */
27407 : 1777626 : machine_mode mode = GET_MODE (op);
27408 : 1777626 : switch (GET_CODE (op))
27409 : : {
27410 : 812773 : case AND:
27411 : 812773 : op0 = XEXP (op, 0);
27412 : 812773 : op1 = XEXP (op, 1);
27413 : :
27414 : : /* Prefer pand. */
27415 : 812773 : if (ix86_ternlog_leaf_p (op0, mode)
27416 : 812773 : && ix86_ternlog_leaf_p (op1, mode))
27417 : : return false;
27418 : : /* Prefer pandn. */
27419 : 103334 : if (GET_CODE (op0) == NOT
27420 : 72796 : && register_operand (XEXP (op0, 0), mode)
27421 : 172539 : && ix86_ternlog_leaf_p (op1, mode))
27422 : : return false;
27423 : : break;
27424 : :
27425 : 617730 : case IOR:
27426 : : /* Prefer por. */
27427 : 617730 : if (ix86_ternlog_leaf_p (XEXP (op, 0), mode)
27428 : 617730 : && ix86_ternlog_leaf_p (XEXP (op, 1), mode))
27429 : : return false;
27430 : : break;
27431 : :
27432 : 317587 : case XOR:
27433 : 317587 : op1 = XEXP (op, 1);
27434 : : /* Prefer pxor, or one_cmpl<vmode>2. */
27435 : 317587 : if (ix86_ternlog_leaf_p (XEXP (op, 0), mode)
27436 : 317587 : && ix86_ternlog_leaf_p (XEXP (op, 1), mode))
27437 : : return false;
27438 : : break;
27439 : :
27440 : : default:
27441 : : break;
27442 : : }
27443 : : return true;
27444 : : }
27445 : :
27446 : : /* Helper function for ix86_expand_ternlog. */
27447 : : static rtx
27448 : 0 : ix86_expand_ternlog_binop (enum rtx_code code, machine_mode mode,
27449 : : rtx op0, rtx op1, rtx target)
27450 : : {
27451 : 0 : if (GET_MODE (op0) != mode)
27452 : 0 : op0 = gen_lowpart (mode, op0);
27453 : 0 : if (GET_MODE (op1) != mode)
27454 : 0 : op1 = gen_lowpart (mode, op1);
27455 : :
27456 : 0 : if (CONST_VECTOR_P (op0))
27457 : 0 : op0 = validize_mem (force_const_mem (mode, op0));
27458 : 0 : if (CONST_VECTOR_P (op1))
27459 : 0 : op1 = validize_mem (force_const_mem (mode, op1));
27460 : :
27461 : 0 : if (!register_operand (op0, mode))
27462 : : {
27463 : 0 : if (!register_operand (op1, mode))
27464 : : {
27465 : : /* We can't use force_reg (op0, mode). */
27466 : 0 : rtx reg = gen_reg_rtx (mode);
27467 : 0 : emit_move_insn (reg, op0);
27468 : 0 : op0 = reg;
27469 : : }
27470 : : else
27471 : : std::swap (op0, op1);
27472 : : }
27473 : 0 : rtx ops[3] = { target, op0, op1 };
27474 : 0 : ix86_expand_vector_logical_operator (code, mode, ops);
27475 : 0 : return target;
27476 : : }
27477 : :
27478 : :
27479 : : /* Helper function for ix86_expand_ternlog. */
27480 : : static rtx
27481 : 0 : ix86_expand_ternlog_andnot (machine_mode mode, rtx op0, rtx op1, rtx target)
27482 : : {
27483 : 0 : if (GET_MODE (op0) != mode)
27484 : 0 : op0 = gen_lowpart (mode, op0);
27485 : 0 : op0 = gen_rtx_NOT (mode, op0);
27486 : 0 : if (GET_MODE (op1) != mode)
27487 : 0 : op1 = gen_lowpart (mode, op1);
27488 : 0 : if (CONST_VECTOR_P (op1))
27489 : 0 : op1 = validize_mem (force_const_mem (mode, op1));
27490 : 0 : emit_move_insn (target, gen_rtx_AND (mode, op0, op1));
27491 : 0 : return target;
27492 : : }
27493 : :
27494 : : /* Expand a 3-operand ternary logic expression. Return TARGET. */
27495 : : rtx
27496 : 2353 : ix86_expand_ternlog (machine_mode mode, rtx op0, rtx op1, rtx op2, int idx,
27497 : : rtx target)
27498 : : {
27499 : 2353 : rtx tmp0, tmp1, tmp2;
27500 : :
27501 : 2353 : if (!target)
27502 : 3 : target = gen_reg_rtx (mode);
27503 : :
27504 : : /* Canonicalize ternlog index for degenerate (duplicated) operands. */
27505 : 2353 : if (rtx_equal_p (op0, op1) && rtx_equal_p (op0, op2))
27506 : 0 : switch (idx & 0x81)
27507 : : {
27508 : : case 0x00:
27509 : : idx = 0x00;
27510 : : break;
27511 : : case 0x01:
27512 : : idx = 0x0f;
27513 : : break;
27514 : : case 0x80:
27515 : : idx = 0xf0;
27516 : : break;
27517 : : case 0x81:
27518 : : idx = 0xff;
27519 : : break;
27520 : : }
27521 : :
27522 : 2353 : switch (idx & 0xff)
27523 : : {
27524 : 0 : case 0x00:
27525 : 0 : if ((!op0 || !side_effects_p (op0))
27526 : 0 : && (!op1 || !side_effects_p (op1))
27527 : 0 : && (!op2 || !side_effects_p (op2)))
27528 : : {
27529 : 0 : emit_move_insn (target, CONST0_RTX (mode));
27530 : 0 : return target;
27531 : : }
27532 : : break;
27533 : :
27534 : 0 : case 0x0a: /* ~a&c */
27535 : 0 : if ((!op1 || !side_effects_p (op1))
27536 : 0 : && op0 && register_operand (op0, mode)
27537 : 0 : && op2 && ix86_ternlog_leaf_p (op2, mode))
27538 : 0 : return ix86_expand_ternlog_andnot (mode, op0, op2, target);
27539 : : break;
27540 : :
27541 : 0 : case 0x0c: /* ~a&b */
27542 : 0 : if ((!op2 || !side_effects_p (op2))
27543 : 0 : && op0 && register_operand (op0, mode)
27544 : 0 : && op1 && ix86_ternlog_leaf_p (op1, mode))
27545 : 0 : return ix86_expand_ternlog_andnot (mode, op0, op1, target);
27546 : : break;
27547 : :
27548 : 14 : case 0x0f: /* ~a */
27549 : 0 : if ((!op1 || !side_effects_p (op1))
27550 : 14 : && (!op2 || !side_effects_p (op2))
27551 : 28 : && op0)
27552 : : {
27553 : 14 : emit_move_insn (target, gen_rtx_XOR (mode, op0, CONSTM1_RTX (mode)));
27554 : 14 : return target;
27555 : : }
27556 : : break;
27557 : :
27558 : 0 : case 0x22: /* ~b&c */
27559 : 0 : if ((!op0 || !side_effects_p (op0))
27560 : 0 : && op1 && register_operand (op1, mode)
27561 : 0 : && op2 && ix86_ternlog_leaf_p (op2, mode))
27562 : 0 : return ix86_expand_ternlog_andnot (mode, op1, op2, target);
27563 : : break;
27564 : :
27565 : 0 : case 0x30: /* ~b&a */
27566 : 0 : if ((!op2 || !side_effects_p (op2))
27567 : 0 : && op0 && ix86_ternlog_leaf_p (op0, mode)
27568 : 0 : && op1 && register_operand (op1, mode))
27569 : 0 : return ix86_expand_ternlog_andnot (mode, op1, op0, target);
27570 : : break;
27571 : :
27572 : 0 : case 0x33: /* ~b */
27573 : 0 : if ((!op0 || !side_effects_p (op0))
27574 : 0 : && (!op2 || !side_effects_p (op2))
27575 : 0 : && op1)
27576 : : {
27577 : 0 : emit_move_insn (target, gen_rtx_XOR (mode, op1, CONSTM1_RTX (mode)));
27578 : 0 : return target;
27579 : : }
27580 : : break;
27581 : :
27582 : 0 : case 0x3c: /* a^b */
27583 : 0 : if (op0 && ix86_ternlog_leaf_p (op0, mode)
27584 : 0 : && op1 && ix86_ternlog_leaf_p (op1, mode)
27585 : 0 : && (!op2 || !side_effects_p (op2)))
27586 : 0 : return ix86_expand_ternlog_binop (XOR, mode, op0, op1, target);
27587 : : break;
27588 : :
27589 : 0 : case 0x44: /* ~c&b */
27590 : 0 : if ((!op0 || !side_effects_p (op0))
27591 : 0 : && op1 && ix86_ternlog_leaf_p (op1, mode)
27592 : 0 : && op2 && register_operand (op2, mode))
27593 : 0 : return ix86_expand_ternlog_andnot (mode, op2, op1, target);
27594 : : break;
27595 : :
27596 : 2 : case 0x50: /* ~c&a */
27597 : 0 : if ((!op1 || !side_effects_p (op1))
27598 : 2 : && op0 && ix86_ternlog_leaf_p (op0, mode)
27599 : 4 : && op2 && register_operand (op2, mode))
27600 : 0 : return ix86_expand_ternlog_andnot (mode, op2, op0, target);
27601 : : break;
27602 : :
27603 : 4 : case 0x55: /* ~c */
27604 : 1 : if ((!op0 || !side_effects_p (op0))
27605 : 4 : && (!op1 || !side_effects_p (op1))
27606 : 8 : && op2)
27607 : : {
27608 : 4 : emit_move_insn (target, gen_rtx_XOR (mode, op2, CONSTM1_RTX (mode)));
27609 : 4 : return target;
27610 : : }
27611 : : break;
27612 : :
27613 : 0 : case 0x5a: /* a^c */
27614 : 0 : if (op0 && ix86_ternlog_leaf_p (op0, mode)
27615 : 0 : && op2 && ix86_ternlog_leaf_p (op2, mode)
27616 : 0 : && (!op1 || !side_effects_p (op1)))
27617 : 0 : return ix86_expand_ternlog_binop (XOR, mode, op0, op2, target);
27618 : : break;
27619 : :
27620 : 0 : case 0x66: /* b^c */
27621 : 0 : if ((!op0 || !side_effects_p (op0))
27622 : 0 : && op1 && ix86_ternlog_leaf_p (op1, mode)
27623 : 0 : && op2 && ix86_ternlog_leaf_p (op2, mode))
27624 : 0 : return ix86_expand_ternlog_binop (XOR, mode, op1, op2, target);
27625 : : break;
27626 : :
27627 : 0 : case 0x88: /* b&c */
27628 : 0 : if ((!op0 || !side_effects_p (op0))
27629 : 0 : && op1 && ix86_ternlog_leaf_p (op1, mode)
27630 : 0 : && op2 && ix86_ternlog_leaf_p (op2, mode))
27631 : 0 : return ix86_expand_ternlog_binop (AND, mode, op1, op2, target);
27632 : : break;
27633 : :
27634 : 0 : case 0xa0: /* a&c */
27635 : 0 : if ((!op1 || !side_effects_p (op1))
27636 : 0 : && op0 && ix86_ternlog_leaf_p (op0, mode)
27637 : 0 : && op2 && ix86_ternlog_leaf_p (op2, mode))
27638 : 0 : return ix86_expand_ternlog_binop (AND, mode, op0, op2, target);
27639 : : break;
27640 : :
27641 : 0 : case 0xaa: /* c */
27642 : 0 : if ((!op0 || !side_effects_p (op0))
27643 : 0 : && (!op1 || !side_effects_p (op1))
27644 : 0 : && op2)
27645 : : {
27646 : 0 : if (GET_MODE (op2) != mode)
27647 : 0 : op2 = gen_lowpart (mode, op2);
27648 : 0 : emit_move_insn (target, op2);
27649 : 0 : return target;
27650 : : }
27651 : : break;
27652 : :
27653 : 0 : case 0xc0: /* a&b */
27654 : 0 : if (op0 && ix86_ternlog_leaf_p (op0, mode)
27655 : 0 : && op1 && ix86_ternlog_leaf_p (op1, mode)
27656 : 0 : && (!op2 || !side_effects_p (op2)))
27657 : 0 : return ix86_expand_ternlog_binop (AND, mode, op0, op1, target);
27658 : : break;
27659 : :
27660 : 0 : case 0xcc: /* b */
27661 : 0 : if ((!op0 || !side_effects_p (op0))
27662 : 0 : && op1
27663 : 0 : && (!op2 || !side_effects_p (op2)))
27664 : : {
27665 : 0 : if (GET_MODE (op1) != mode)
27666 : 0 : op1 = gen_lowpart (mode, op1);
27667 : 0 : emit_move_insn (target, op1);
27668 : 0 : return target;
27669 : : }
27670 : : break;
27671 : :
27672 : 0 : case 0xee: /* b|c */
27673 : 0 : if ((!op0 || !side_effects_p (op0))
27674 : 0 : && op1 && ix86_ternlog_leaf_p (op1, mode)
27675 : 0 : && op2 && ix86_ternlog_leaf_p (op2, mode))
27676 : 0 : return ix86_expand_ternlog_binop (IOR, mode, op1, op2, target);
27677 : : break;
27678 : :
27679 : 6 : case 0xf0: /* a */
27680 : 6 : if (op0
27681 : 6 : && (!op1 || !side_effects_p (op1))
27682 : 12 : && (!op2 || !side_effects_p (op2)))
27683 : : {
27684 : 6 : if (GET_MODE (op0) != mode)
27685 : 0 : op0 = gen_lowpart (mode, op0);
27686 : 6 : emit_move_insn (target, op0);
27687 : 6 : return target;
27688 : : }
27689 : : break;
27690 : :
27691 : 0 : case 0xfa: /* a|c */
27692 : 0 : if (op0 && ix86_ternlog_leaf_p (op0, mode)
27693 : 0 : && op2 && ix86_ternlog_leaf_p (op2, mode)
27694 : 0 : && (!op1 || !side_effects_p (op1)))
27695 : 0 : return ix86_expand_ternlog_binop (IOR, mode, op0, op2, target);
27696 : : break;
27697 : :
27698 : 0 : case 0xfc: /* a|b */
27699 : 0 : if (op0 && ix86_ternlog_leaf_p (op0, mode)
27700 : 0 : && op1 && ix86_ternlog_leaf_p (op1, mode)
27701 : 0 : && (!op2 || !side_effects_p (op2)))
27702 : 0 : return ix86_expand_ternlog_binop (IOR, mode, op0, op1, target);
27703 : : break;
27704 : :
27705 : 0 : case 0xff:
27706 : 0 : if ((!op0 || !side_effects_p (op0))
27707 : 0 : && (!op1 || !side_effects_p (op1))
27708 : 0 : && (!op2 || !side_effects_p (op2)))
27709 : : {
27710 : 0 : emit_move_insn (target, CONSTM1_RTX (mode));
27711 : 0 : return target;
27712 : : }
27713 : : break;
27714 : : }
27715 : :
27716 : 2329 : if (!register_operand (op0, mode))
27717 : : {
27718 : : /* We can't use force_reg (mode, op0). */
27719 : 12 : tmp0 = gen_reg_rtx (GET_MODE (op0));
27720 : 12 : emit_move_insn (tmp0,op0);
27721 : : }
27722 : : else
27723 : : tmp0 = op0;
27724 : 2329 : if (GET_MODE (tmp0) != mode)
27725 : 0 : tmp0 = gen_lowpart (mode, tmp0);
27726 : :
27727 : 2329 : if (!op1 || rtx_equal_p (op0, op1))
27728 : 6 : tmp1 = copy_rtx (tmp0);
27729 : 2323 : else if (!register_operand (op1, mode))
27730 : : {
27731 : : /* We can't use force_reg (mode, op1). */
27732 : 28 : tmp1 = gen_reg_rtx (GET_MODE (op1));
27733 : 28 : emit_move_insn (tmp1, op1);
27734 : : }
27735 : : else
27736 : : tmp1 = op1;
27737 : 2329 : if (GET_MODE (tmp1) != mode)
27738 : 0 : tmp1 = gen_lowpart (mode, tmp1);
27739 : :
27740 : 2329 : if (!op2 || rtx_equal_p (op0, op2))
27741 : 71 : tmp2 = copy_rtx (tmp0);
27742 : 2258 : else if (rtx_equal_p (op1, op2))
27743 : 0 : tmp2 = copy_rtx (tmp1);
27744 : 2258 : else if (CONST_VECTOR_P (op2))
27745 : : {
27746 : 42 : if (GET_MODE (op2) != mode)
27747 : 0 : op2 = gen_lowpart (mode, op2);
27748 : 42 : tmp2 = ix86_gen_bcst_mem (mode, op2);
27749 : 42 : if (!tmp2)
27750 : : {
27751 : 24 : machine_mode bcst32_mode = mode;
27752 : 24 : machine_mode bcst64_mode = mode;
27753 : 24 : switch (mode)
27754 : : {
27755 : 1 : case V1TImode:
27756 : 1 : case V4SImode:
27757 : 1 : case V4SFmode:
27758 : 1 : case V8HImode:
27759 : 1 : case V16QImode:
27760 : 1 : bcst32_mode = V4SImode;
27761 : 1 : bcst64_mode = V2DImode;
27762 : 1 : break;
27763 : :
27764 : 0 : case V2TImode:
27765 : 0 : case V8SImode:
27766 : 0 : case V8SFmode:
27767 : 0 : case V16HImode:
27768 : 0 : case V32QImode:
27769 : 0 : bcst32_mode = V8SImode;
27770 : 0 : bcst64_mode = V4DImode;
27771 : 0 : break;
27772 : :
27773 : 3 : case V4TImode:
27774 : 3 : case V16SImode:
27775 : 3 : case V16SFmode:
27776 : 3 : case V32HImode:
27777 : 3 : case V64QImode:
27778 : 3 : bcst32_mode = V16SImode;
27779 : 3 : bcst64_mode = V8DImode;
27780 : 3 : break;
27781 : :
27782 : : default:
27783 : : break;
27784 : : }
27785 : :
27786 : 24 : if (bcst32_mode != mode)
27787 : : {
27788 : 4 : tmp2 = gen_lowpart (bcst32_mode, op2);
27789 : 4 : if (ix86_gen_bcst_mem (bcst32_mode, tmp2))
27790 : : {
27791 : 3 : tmp2 = ix86_expand_ternlog (bcst32_mode,
27792 : 3 : gen_lowpart (bcst32_mode, tmp0),
27793 : 3 : gen_lowpart (bcst32_mode, tmp1),
27794 : : tmp2, idx, NULL_RTX);
27795 : 3 : emit_move_insn (target, gen_lowpart (mode, tmp2));
27796 : 3 : return target;
27797 : : }
27798 : : }
27799 : :
27800 : 21 : if (bcst64_mode != mode)
27801 : : {
27802 : 1 : tmp2 = gen_lowpart (bcst64_mode, op2);
27803 : 1 : if (ix86_gen_bcst_mem (bcst64_mode, tmp2))
27804 : : {
27805 : 0 : tmp2 = ix86_expand_ternlog (bcst64_mode,
27806 : 0 : gen_lowpart (bcst64_mode, tmp0),
27807 : 0 : gen_lowpart (bcst64_mode, tmp1),
27808 : : tmp2, idx, NULL_RTX);
27809 : 0 : emit_move_insn (target, gen_lowpart (mode, tmp2));
27810 : 0 : return target;
27811 : : }
27812 : : }
27813 : :
27814 : 21 : tmp2 = force_const_mem (mode, op2);
27815 : 21 : rtx bcast = ix86_broadcast_from_constant (mode, tmp2);
27816 : 21 : tmp2 = validize_mem (tmp2);
27817 : 21 : if (bcast)
27818 : : {
27819 : 12 : rtx reg2 = gen_reg_rtx (mode);
27820 : 12 : bool ok = ix86_expand_vector_init_duplicate (false, mode,
27821 : : reg2, bcast);
27822 : 12 : if (ok)
27823 : 2326 : tmp2 = reg2;
27824 : : }
27825 : : }
27826 : : }
27827 : : else
27828 : : tmp2 = op2;
27829 : 2326 : if (GET_MODE (tmp2) != mode)
27830 : 0 : tmp2 = gen_lowpart (mode, tmp2);
27831 : : /* Some memory_operands are not vector_memory_operands. */
27832 : 2326 : if (!bcst_vector_operand (tmp2, mode))
27833 : 0 : tmp2 = force_reg (mode, tmp2);
27834 : :
27835 : 2326 : rtvec vec = gen_rtvec (4, tmp0, tmp1, tmp2, GEN_INT (idx));
27836 : 2326 : emit_move_insn (target, gen_rtx_UNSPEC (mode, vec, UNSPEC_VTERNLOG));
27837 : 2326 : return target;
27838 : : }
27839 : :
27840 : : /* GF2P8AFFINEQB matrixes to implement shift and rotate. */
27841 : :
27842 : : static const uint64_t matrix_ashift[8] =
27843 : : {
27844 : : 0,
27845 : : 0x0001020408102040, /* 1 l */
27846 : : 0x0000010204081020, /* 2 l */
27847 : : 0x0000000102040810, /* 3 l */
27848 : : 0x0000000001020408, /* 4 l */
27849 : : 0x0000000000010204, /* 5 l */
27850 : : 0x0000000000000102, /* 6 l */
27851 : : 0x0000000000000001 /* 7 l */
27852 : : };
27853 : :
27854 : : static const uint64_t matrix_lshiftrt[8] =
27855 : : {
27856 : : 0,
27857 : : 0x0204081020408000, /* 1 r */
27858 : : 0x0408102040800000, /* 2 r */
27859 : : 0x0810204080000000, /* 3 r */
27860 : : 0x1020408000000000, /* 4 r */
27861 : : 0x2040800000000000, /* 5 r */
27862 : : 0x4080000000000000, /* 6 r */
27863 : : 0x8000000000000000 /* 7 r */
27864 : : };
27865 : :
27866 : : static const uint64_t matrix_ashiftrt[8] =
27867 : : {
27868 : : 0,
27869 : : 0x0204081020408080, /* 1 r */
27870 : : 0x0408102040808080, /* 2 r */
27871 : : 0x0810204080808080, /* 3 r */
27872 : : 0x1020408080808080, /* 4 r */
27873 : : 0x2040808080808080, /* 5 r */
27874 : : 0x4080808080808080, /* 6 r */
27875 : : 0x8080808080808080 /* 7 r */
27876 : : };
27877 : :
27878 : : static const uint64_t matrix_rotate[8] =
27879 : : {
27880 : : 0,
27881 : : 0x8001020408102040, /* 1 rol8 */
27882 : : 0x4080010204081020, /* 2 rol8 */
27883 : : 0x2040800102040810, /* 3 rol8 */
27884 : : 0x1020408001020408, /* 4 rol8 */
27885 : : 0x0810204080010204, /* 5 rol8 */
27886 : : 0x0408102040800102, /* 6 rol8 */
27887 : : 0x0204081020408001 /* 7 rol8 */
27888 : : };
27889 : :
27890 : : static const uint64_t matrix_rotatert[8] =
27891 : : {
27892 : : 0,
27893 : : 0x0204081020408001, /* 1 ror8 */
27894 : : 0x0408102040800102, /* 2 ror8 */
27895 : : 0x0810204080010204, /* 3 ror8 */
27896 : : 0x1020408001020408, /* 4 ror8 */
27897 : : 0x2040800102040810, /* 5 ror8 */
27898 : : 0x4080010204081020, /* 6 ror8 */
27899 : : 0x8001020408102040 /* 7 ror8 */
27900 : : };
27901 : :
27902 : : /* Return rtx to load a 64bit GF2P8AFFINE GP(2) matrix implementing a shift
27903 : : for CODE and shift count COUNT into register with vector of size of SRC. */
27904 : :
27905 : : rtx
27906 : 189 : ix86_vgf2p8affine_shift_matrix (rtx src, rtx count, enum rtx_code code)
27907 : : {
27908 : 189 : machine_mode mode = GET_MODE (src);
27909 : 189 : const uint64_t *matrix;
27910 : 189 : unsigned shift = INTVAL (count) & 7;
27911 : 189 : gcc_assert (shift > 0 && shift < 8);
27912 : :
27913 : 189 : switch (code)
27914 : : {
27915 : : case ASHIFT:
27916 : : matrix = matrix_ashift;
27917 : : break;
27918 : 26 : case ASHIFTRT:
27919 : 26 : matrix = matrix_ashiftrt;
27920 : 26 : break;
27921 : 28 : case LSHIFTRT:
27922 : 28 : matrix = matrix_lshiftrt;
27923 : 28 : break;
27924 : 32 : case ROTATE:
27925 : 32 : matrix = matrix_rotate;
27926 : 32 : break;
27927 : 33 : case ROTATERT:
27928 : 33 : matrix = matrix_rotatert;
27929 : 33 : break;
27930 : 0 : default:
27931 : 0 : gcc_unreachable ();
27932 : : }
27933 : :
27934 : 189 : int nelts = GET_MODE_NUNITS (mode);
27935 : 189 : rtvec vec = rtvec_alloc (nelts);
27936 : 189 : uint64_t ma = matrix[shift];
27937 : 7741 : for (int i = 0; i < nelts; i++)
27938 : 7552 : RTVEC_ELT (vec, i) = gen_int_mode ((ma >> ((i % 8) * 8)) & 0xff, QImode);
27939 : :
27940 : 189 : return force_reg (mode, gen_rtx_CONST_VECTOR (mode, vec));
27941 : : }
27942 : :
27943 : : /* Trunc a vector to a narrow vector, like v4di -> v4si. */
27944 : :
27945 : : void
27946 : 62 : ix86_expand_trunc_with_avx2_noavx512f (rtx output, rtx input, machine_mode cvt_mode)
27947 : : {
27948 : 62 : machine_mode out_mode = GET_MODE (output);
27949 : 62 : machine_mode in_mode = GET_MODE (input);
27950 : 62 : int len = GET_MODE_SIZE (in_mode);
27951 : 248 : gcc_assert (len == GET_MODE_SIZE (cvt_mode)
27952 : : && GET_MODE_INNER (out_mode) == GET_MODE_INNER (cvt_mode)
27953 : : && (REG_P (input) || SUBREG_P (input)));
27954 : 62 : scalar_mode inner_out_mode = GET_MODE_INNER (out_mode);
27955 : 124 : int in_innersize = GET_MODE_SIZE (GET_MODE_INNER (in_mode));
27956 : 62 : int out_innersize = GET_MODE_SIZE (inner_out_mode);
27957 : :
27958 : 62 : struct expand_vec_perm_d d;
27959 : 62 : d.target = gen_reg_rtx (cvt_mode);
27960 : 62 : d.op0 = lowpart_subreg (cvt_mode, force_reg(in_mode, input), in_mode);
27961 : 62 : d.op1 = d.op0;
27962 : 62 : d.vmode = cvt_mode;
27963 : 62 : d.nelt = GET_MODE_NUNITS (cvt_mode);
27964 : 62 : d.testing_p = false;
27965 : 62 : d.one_operand_p = true;
27966 : :
27967 : : /* Init perm. Put the needed bits of input in order and
27968 : : fill the rest of bits by default. */
27969 : 654 : for (int i = 0; i < d.nelt; ++i)
27970 : : {
27971 : 592 : d.perm[i] = i;
27972 : 1184 : if (i < GET_MODE_NUNITS (out_mode))
27973 : 238 : d.perm[i] = i * (in_innersize / out_innersize);
27974 : : }
27975 : :
27976 : 62 : bool ok = ix86_expand_vec_perm_const_1(&d);
27977 : 62 : gcc_assert (ok);
27978 : 62 : emit_move_insn (output, gen_lowpart (out_mode, d.target));
27979 : 62 : }
27980 : :
27981 : : /* Implement truncv8sfv8bf2 with vector permutation. */
27982 : : void
27983 : 8 : ix86_expand_vector_sf2bf_with_vec_perm (rtx dest, rtx src)
27984 : : {
27985 : 8 : machine_mode vperm_mode, src_mode = GET_MODE (src);
27986 : 8 : switch (src_mode)
27987 : : {
27988 : : case V16SFmode:
27989 : : vperm_mode = V32BFmode;
27990 : : break;
27991 : 2 : case V8SFmode:
27992 : 2 : vperm_mode = V16BFmode;
27993 : 2 : break;
27994 : 4 : case V4SFmode:
27995 : 4 : vperm_mode = V8BFmode;
27996 : 4 : break;
27997 : 0 : default:
27998 : 0 : gcc_unreachable ();
27999 : : }
28000 : :
28001 : 8 : int nelt = GET_MODE_NUNITS (vperm_mode);
28002 : 8 : vec_perm_builder sel (nelt, nelt, 1);
28003 : 8 : sel.quick_grow (nelt);
28004 : 136 : for (int i = 0; i != nelt; i++)
28005 : 128 : sel[i] = (2 * i + 1) % nelt;
28006 : 16 : vec_perm_indices indices (sel, 1, nelt);
28007 : :
28008 : 8 : rtx target = gen_reg_rtx (vperm_mode);
28009 : 8 : rtx op0 = lowpart_subreg (vperm_mode,
28010 : : force_reg (src_mode, src),
28011 : : src_mode);
28012 : 8 : bool ok = targetm.vectorize.vec_perm_const (vperm_mode, vperm_mode,
28013 : : target, op0, op0, indices);
28014 : 8 : gcc_assert (ok);
28015 : 8 : emit_move_insn (dest, lowpart_subreg (GET_MODE (dest), target, vperm_mode));
28016 : 8 : }
28017 : :
28018 : : /* Implement extendv8bf2v8sf2 with vector permutation. */
28019 : : void
28020 : 8 : ix86_expand_vector_bf2sf_with_vec_perm (rtx dest, rtx src)
28021 : : {
28022 : 8 : machine_mode vperm_mode, src_mode = GET_MODE (src);
28023 : 8 : switch (src_mode)
28024 : : {
28025 : : case V16BFmode:
28026 : : vperm_mode = V32BFmode;
28027 : : break;
28028 : 2 : case V8BFmode:
28029 : 2 : vperm_mode = V16BFmode;
28030 : 2 : break;
28031 : 4 : case V4BFmode:
28032 : 4 : vperm_mode = V8BFmode;
28033 : 4 : break;
28034 : 0 : default:
28035 : 0 : gcc_unreachable ();
28036 : : }
28037 : :
28038 : 8 : int nelt = GET_MODE_NUNITS (vperm_mode);
28039 : 8 : vec_perm_builder sel (nelt, nelt, 1);
28040 : 8 : sel.quick_grow (nelt);
28041 : 136 : for (int i = 0, k = 0, j = nelt; i != nelt; i++)
28042 : 128 : sel[i] = i & 1 ? j++ : k++;
28043 : :
28044 : 16 : vec_perm_indices indices (sel, 2, nelt);
28045 : :
28046 : 8 : rtx target = gen_reg_rtx (vperm_mode);
28047 : 8 : rtx op1 = lowpart_subreg (vperm_mode,
28048 : : force_reg (src_mode, src),
28049 : : src_mode);
28050 : 8 : rtx op0 = CONST0_RTX (vperm_mode);
28051 : 8 : bool ok = targetm.vectorize.vec_perm_const (vperm_mode, vperm_mode,
28052 : : target, op0, op1, indices);
28053 : 8 : gcc_assert (ok);
28054 : 8 : emit_move_insn (dest, lowpart_subreg (GET_MODE (dest), target, vperm_mode));
28055 : 8 : }
28056 : :
28057 : :
28058 : : #include "gt-i386-expand.h"
|