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 : 4154705 : split_double_mode (machine_mode mode, rtx operands[],
106 : : int num, rtx lo_half[], rtx hi_half[])
107 : : {
108 : 4154705 : machine_mode half_mode;
109 : 4154705 : unsigned int byte;
110 : 4154705 : rtx mem_op = NULL_RTX;
111 : 4154705 : int mem_num = 0;
112 : :
113 : 4154705 : switch (mode)
114 : : {
115 : : case E_TImode:
116 : : half_mode = DImode;
117 : : break;
118 : 608588 : case E_DImode:
119 : 608588 : half_mode = SImode;
120 : 608588 : 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 : 4154705 : byte = GET_MODE_SIZE (half_mode);
132 : :
133 : 8519059 : while (num--)
134 : : {
135 : 4364354 : rtx op = operands[num];
136 : :
137 : : /* simplify_subreg refuse to split volatile memory addresses,
138 : : but we still have to handle it. */
139 : 4364354 : if (MEM_P (op))
140 : : {
141 : 1699926 : if (mem_op && rtx_equal_p (op, mem_op))
142 : : {
143 : 2416 : lo_half[num] = lo_half[mem_num];
144 : 2416 : hi_half[num] = hi_half[mem_num];
145 : : }
146 : : else
147 : : {
148 : 1697510 : mem_op = op;
149 : 1697510 : mem_num = num;
150 : 1697510 : lo_half[num] = adjust_address (op, half_mode, 0);
151 : 1697510 : hi_half[num] = adjust_address (op, half_mode, byte);
152 : : }
153 : : }
154 : : else
155 : : {
156 : 2664428 : lo_half[num] = simplify_gen_subreg (half_mode, op,
157 : 2664428 : GET_MODE (op) == VOIDmode
158 : : ? mode : GET_MODE (op), 0);
159 : :
160 : 2664428 : rtx tmp = simplify_gen_subreg (half_mode, op,
161 : 2664428 : GET_MODE (op) == VOIDmode
162 : 2664428 : ? mode : GET_MODE (op), byte);
163 : : /* simplify_gen_subreg will return NULL RTX for the
164 : : high half of the paradoxical subreg. */
165 : 2664428 : hi_half[num] = tmp ? tmp : gen_reg_rtx (half_mode);
166 : : }
167 : : }
168 : 4154705 : }
169 : :
170 : : /* Emit the double word assignment DST = { LO, HI }. */
171 : :
172 : : void
173 : 105167 : split_double_concat (machine_mode mode, rtx dst, rtx lo, rtx hi)
174 : : {
175 : 105167 : rtx dlo, dhi;
176 : 105167 : int deleted_move_count = 0;
177 : 105167 : 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 : 105167 : if (MEM_P (lo)
183 : 4875 : && rtx_equal_p (dlo, hi)
184 : 106069 : && 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 : 179 : emit_move_insn (dhi, lo);
192 : 179 : lo = dhi;
193 : : }
194 : 104988 : else if (MEM_P (hi)
195 : 9244 : && !MEM_P (lo)
196 : 7140 : && !rtx_equal_p (dlo, lo)
197 : 106634 : && 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 : 16 : 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 : 7 : emit_move_insn (dhi, hi);
213 : 7 : hi = dhi;
214 : : }
215 : : }
216 : 105167 : if (!rtx_equal_p (dlo, hi))
217 : : {
218 : 90925 : if (!rtx_equal_p (dlo, lo))
219 : 40868 : emit_move_insn (dlo, lo);
220 : : else
221 : : deleted_move_count++;
222 : 90925 : if (!rtx_equal_p (dhi, hi))
223 : 83879 : emit_move_insn (dhi, hi);
224 : : else
225 : 7046 : deleted_move_count++;
226 : : }
227 : 14242 : else if (!rtx_equal_p (lo, dhi))
228 : : {
229 : 7061 : if (!rtx_equal_p (dhi, hi))
230 : 7061 : emit_move_insn (dhi, hi);
231 : : else
232 : : deleted_move_count++;
233 : 7061 : if (!rtx_equal_p (dlo, lo))
234 : 6945 : emit_move_insn (dlo, lo);
235 : : else
236 : 116 : deleted_move_count++;
237 : : }
238 : 7181 : else if (mode == TImode)
239 : 7163 : emit_insn (gen_swapdi (dlo, dhi));
240 : : else
241 : 18 : emit_insn (gen_swapsi (dlo, dhi));
242 : :
243 : 105167 : if (deleted_move_count == 2)
244 : 3819 : emit_note (NOTE_INSN_DELETED);
245 : 105167 : }
246 : :
247 : :
248 : : /* Generate either "mov $0, reg" or "xor reg, reg", as appropriate
249 : : for the target. */
250 : :
251 : : void
252 : 111747 : ix86_expand_clear (rtx dest)
253 : : {
254 : 111747 : rtx tmp;
255 : :
256 : : /* We play register width games, which are only valid after reload. */
257 : 111747 : gcc_assert (reload_completed);
258 : :
259 : : /* Avoid HImode and its attendant prefix byte. */
260 : 223494 : if (GET_MODE_SIZE (GET_MODE (dest)) < 4)
261 : 1030 : dest = gen_rtx_REG (SImode, REGNO (dest));
262 : 111747 : tmp = gen_rtx_SET (dest, const0_rtx);
263 : :
264 : 111747 : if (!TARGET_USE_MOV0 || optimize_insn_for_size_p ())
265 : : {
266 : 111747 : rtx clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
267 : 111747 : tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, tmp, clob));
268 : : }
269 : :
270 : 111747 : emit_insn (tmp);
271 : 111747 : }
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 : 4841 : ix86_broadcast (HOST_WIDE_INT v, unsigned int width,
278 : : HOST_WIDE_INT &val_broadcast)
279 : : {
280 : 4841 : wide_int val = wi::uhwi (v, HOST_BITS_PER_WIDE_INT);
281 : 4841 : val_broadcast = wi::extract_uhwi (val, 0, width);
282 : 6513 : for (unsigned int i = width; i < HOST_BITS_PER_WIDE_INT; i += width)
283 : : {
284 : 5065 : HOST_WIDE_INT each = wi::extract_uhwi (val, i, width);
285 : 5065 : if (val_broadcast != each)
286 : : return false;
287 : : }
288 : 1448 : val_broadcast = sext_hwi (val_broadcast, width);
289 : 1448 : return true;
290 : 4841 : }
291 : :
292 : : /* Convert the CONST_WIDE_INT operand OP to broadcast in MODE. */
293 : :
294 : : rtx
295 : 40302 : 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 : 40302 : if (!TARGET_INTER_UNIT_MOVES_TO_VEC)
300 : : return nullptr;
301 : :
302 : 40302 : unsigned int msize = GET_MODE_SIZE (mode);
303 : :
304 : : /* Only optimized for vpbroadcast[bwsd]/vbroadcastss with xmm/ymm/zmm. */
305 : 40302 : 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 : 40302 : if (!TARGET_AVX
311 : 1604 : || !CONST_WIDE_INT_P (op)
312 : 1597 : || standard_sse_constant_p (op, mode)
313 : 41899 : || (CONST_WIDE_INT_NUNITS (op) * HOST_BITS_PER_WIDE_INT
314 : 1597 : != GET_MODE_BITSIZE (mode)))
315 : 38713 : return nullptr;
316 : :
317 : 1589 : HOST_WIDE_INT val = CONST_WIDE_INT_ELT (op, 0);
318 : 1589 : HOST_WIDE_INT val_broadcast;
319 : 1589 : scalar_int_mode broadcast_mode;
320 : : /* vpbroadcastb zmm requires TARGET_AVX512BW. */
321 : 707 : if ((msize == 64 ? TARGET_AVX512BW : TARGET_AVX2)
322 : 2078 : && ix86_broadcast (val, GET_MODE_BITSIZE (QImode),
323 : : val_broadcast))
324 : : broadcast_mode = QImode;
325 : 651 : else if ((msize == 64 ? TARGET_AVX512BW : TARGET_AVX2)
326 : 1961 : && 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 : 409 : else if ((msize != 32 || TARGET_AVX2)
333 : 1761 : && ix86_broadcast (val, GET_MODE_BITSIZE (SImode),
334 : : val_broadcast))
335 : : broadcast_mode = SImode;
336 : 1389 : else if (TARGET_64BIT && (msize != 32 || TARGET_AVX2)
337 : 2637 : && 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 : 1770 : for (int i = 1; i < CONST_WIDE_INT_NUNITS (op); i++)
345 : 1555 : 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 : 72879384 : ix86_expand_move (machine_mode mode, rtx operands[])
365 : : {
366 : 72879384 : rtx op0, op1;
367 : 72879384 : rtx tmp, addend = NULL_RTX;
368 : 72879384 : enum tls_model model;
369 : :
370 : 72879384 : op0 = operands[0];
371 : 72879384 : op1 = operands[1];
372 : :
373 : : /* Avoid complex sets of likely spilled hard registers before reload. */
374 : 72879384 : if (!ix86_hardreg_mov_ok (op0, op1))
375 : : {
376 : 140062 : tmp = gen_reg_rtx (mode);
377 : 140062 : operands[0] = tmp;
378 : 140062 : ix86_expand_move (mode, operands);
379 : 140062 : operands[0] = op0;
380 : 140062 : operands[1] = tmp;
381 : 140062 : op1 = tmp;
382 : : }
383 : :
384 : 72879384 : switch (GET_CODE (op1))
385 : : {
386 : 358910 : case CONST:
387 : 358910 : tmp = XEXP (op1, 0);
388 : :
389 : 358910 : if (GET_CODE (tmp) != PLUS
390 : 347229 : || GET_CODE (XEXP (tmp, 0)) != SYMBOL_REF)
391 : : break;
392 : :
393 : 344582 : op1 = XEXP (tmp, 0);
394 : 344582 : addend = XEXP (tmp, 1);
395 : : /* FALLTHRU */
396 : :
397 : 4921204 : case SYMBOL_REF:
398 : 4921204 : model = SYMBOL_REF_TLS_MODEL (op1);
399 : :
400 : 4921204 : if (model)
401 : 9824 : op1 = legitimize_tls_address (op1, model, true);
402 : 4911380 : 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 : 4911360 : {
427 : 4911360 : op1 = operands[1];
428 : 4911360 : break;
429 : : }
430 : : }
431 : :
432 : 9844 : 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 : 7058 : op1 = force_operand (op1, op0);
440 : :
441 : 9844 : if (op1 == op0)
442 : : return;
443 : :
444 : 4531 : op1 = convert_to_mode (mode, op1, 1);
445 : :
446 : : default:
447 : : break;
448 : :
449 : 1520953 : case SUBREG:
450 : : /* Transform TImode paradoxical SUBREG into zero_extendditi2. */
451 : 1520953 : if (TARGET_64BIT
452 : 1296105 : && mode == TImode
453 : : && SUBREG_P (op1)
454 : 74900 : && GET_MODE (SUBREG_REG (op1)) == DImode
455 : 1567277 : && SUBREG_BYTE (op1) == 0)
456 : 46324 : 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 : 1520953 : if (mode == XFmode
460 : 2573 : && CONSTANT_P (SUBREG_REG (op1))
461 : 2 : && can_create_pseudo_p ())
462 : : {
463 : 2 : machine_mode imode = GET_MODE (SUBREG_REG (op1));
464 : 2 : rtx r = force_const_mem (imode, SUBREG_REG (op1));
465 : 2 : if (r)
466 : 2 : r = validize_mem (r);
467 : : else
468 : 0 : r = force_reg (imode, SUBREG_REG (op1));
469 : 2 : op1 = simplify_gen_subreg (mode, r, imode, SUBREG_BYTE (op1));
470 : : }
471 : : break;
472 : : }
473 : :
474 : 72874071 : if ((flag_pic || MACHOPIC_INDIRECT)
475 : 72874071 : && 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 && GET_CODE (op0) != MEM)
491 : : {
492 : : rtx insn = gen_rtx_SET (op0, op1);
493 : : emit_insn (insn);
494 : : return;
495 : : }
496 : : }
497 : : #endif
498 : :
499 : 328754 : if (MEM_P (op0))
500 : 86325 : op1 = force_reg (mode, op1);
501 : 242429 : else if (!(TARGET_64BIT && x86_64_movabs_operand (op1, DImode)))
502 : : {
503 : 242391 : rtx reg = can_create_pseudo_p () ? NULL_RTX : op0;
504 : 242391 : op1 = legitimize_pic_address (op1, reg);
505 : 242391 : if (op0 == op1)
506 : : return;
507 : 242391 : op1 = convert_to_mode (mode, op1, 1);
508 : : }
509 : : }
510 : : else
511 : : {
512 : 72545317 : if (MEM_P (op0)
513 : 98591801 : && (PUSH_ROUNDING (GET_MODE_SIZE (mode)) != GET_MODE_SIZE (mode)
514 : 10619544 : || !push_operand (op0, mode))
515 : 84612159 : && MEM_P (op1))
516 : 2217830 : op1 = force_reg (mode, op1);
517 : :
518 : 72545317 : if (push_operand (op0, mode)
519 : 72545317 : && ! general_no_elim_operand (op1, mode))
520 : 1003 : op1 = copy_to_mode_reg (mode, op1);
521 : :
522 : : /* Force large constants in 64bit compilation into register
523 : : to get them CSEed. */
524 : 72545317 : if (can_create_pseudo_p ()
525 : 66856561 : && (mode == DImode) && TARGET_64BIT
526 : 34717088 : && immediate_operand (op1, mode)
527 : 7971530 : && !x86_64_zext_immediate_operand (op1, VOIDmode)
528 : 696374 : && !register_operand (op0, mode)
529 : 72717750 : && optimize)
530 : 121180 : op1 = copy_to_mode_reg (mode, op1);
531 : :
532 : 72545317 : if (can_create_pseudo_p ())
533 : : {
534 : 66856561 : 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 : 888411 : op1 = validize_mem (force_const_mem (mode, op1));
541 : 888411 : if (!register_operand (op0, mode))
542 : : {
543 : 128197 : tmp = gen_reg_rtx (mode);
544 : 128197 : emit_insn (gen_rtx_SET (tmp, op1));
545 : 128197 : emit_move_insn (op0, tmp);
546 : 128197 : return;
547 : : }
548 : : }
549 : : }
550 : : }
551 : :
552 : : /* Special case inserting 64-bit values into a TImode register. */
553 : 72745874 : if (TARGET_64BIT
554 : : /* Disable for -O0 (see PR110587) unless naked (PR110533). */
555 : 63025326 : && (optimize || ix86_function_naked (current_function_decl))
556 : 43540977 : && (mode == DImode || mode == DFmode)
557 : 29574003 : && SUBREG_P (op0)
558 : 499076 : && GET_MODE (SUBREG_REG (op0)) == TImode
559 : 412401 : && REG_P (SUBREG_REG (op0))
560 : 73158275 : && REG_P (op1))
561 : : {
562 : : /* Use *insvti_lowpart_1 to set lowpart. */
563 : 187105 : if (SUBREG_BYTE (op0) == 0)
564 : : {
565 : 56919 : wide_int mask = wi::mask (64, true, 128);
566 : 56919 : tmp = immed_wide_int_const (mask, TImode);
567 : 56919 : op0 = SUBREG_REG (op0);
568 : 56919 : tmp = gen_rtx_AND (TImode, copy_rtx (op0), tmp);
569 : 56919 : if (mode == DFmode)
570 : 348 : op1 = gen_lowpart (DImode, op1);
571 : 56919 : op1 = gen_rtx_ZERO_EXTEND (TImode, op1);
572 : 56919 : op1 = gen_rtx_IOR (TImode, tmp, op1);
573 : 56919 : }
574 : : /* Use *insvti_highpart_1 to set highpart. */
575 : 130186 : else if (SUBREG_BYTE (op0) == 8)
576 : : {
577 : 130186 : wide_int mask = wi::mask (64, false, 128);
578 : 130186 : tmp = immed_wide_int_const (mask, TImode);
579 : 130186 : op0 = SUBREG_REG (op0);
580 : 130186 : tmp = gen_rtx_AND (TImode, copy_rtx (op0), tmp);
581 : 130186 : if (mode == DFmode)
582 : 196 : op1 = gen_lowpart (DImode, op1);
583 : 130186 : op1 = gen_rtx_ZERO_EXTEND (TImode, op1);
584 : 130186 : op1 = gen_rtx_ASHIFT (TImode, op1, GEN_INT (64));
585 : 130186 : op1 = gen_rtx_IOR (TImode, tmp, op1);
586 : 130186 : }
587 : : }
588 : :
589 : 72745874 : 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 : 2435171 : ix86_broadcast_from_constant (machine_mode mode, rtx op)
596 : : {
597 : 2435171 : int nunits = GET_MODE_NUNITS (mode);
598 : 2435171 : 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 : 2274077 : if (!TARGET_INTER_UNIT_MOVES_TO_VEC
604 : 8222 : && 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 : 2268476 : if (standard_sse_constant_p (op, mode))
610 : : return nullptr;
611 : :
612 : 4536946 : if (GET_MODE_INNER (mode) == TImode)
613 : : return nullptr;
614 : :
615 : 2268363 : rtx constant = get_pool_constant (XEXP (op, 0));
616 : 2268363 : 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 : 2268363 : if (GET_MODE (constant) != mode)
623 : : {
624 : 569 : constant = simplify_subreg (mode, constant, GET_MODE (constant),
625 : : 0);
626 : 569 : if (constant == nullptr || !CONST_VECTOR_P (constant))
627 : : return nullptr;
628 : : }
629 : :
630 : 2268363 : rtx first = XVECEXP (constant, 0, 0);
631 : :
632 : 6606022 : for (int i = 1; i < nunits; ++i)
633 : : {
634 : 6073691 : rtx tmp = XVECEXP (constant, 0, i);
635 : : /* Vector duplicate value. */
636 : 6073691 : if (!rtx_equal_p (tmp, first))
637 : : return nullptr;
638 : : }
639 : :
640 : : return first;
641 : : }
642 : :
643 : : void
644 : 4595094 : ix86_expand_vector_move (machine_mode mode, rtx operands[])
645 : : {
646 : 4595094 : 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 : 4595094 : unsigned int align = (TARGET_IAMCU
650 : 4595094 : ? GET_MODE_BITSIZE (mode)
651 : 4595094 : : GET_MODE_ALIGNMENT (mode));
652 : :
653 : 4595094 : 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 : 4595094 : if (can_create_pseudo_p ()
661 : 4400604 : && (CONSTANT_P (op1)
662 : 4101201 : || (SUBREG_P (op1)
663 : 289723 : && CONSTANT_P (SUBREG_REG (op1))))
664 : 4894511 : && ((register_operand (op0, mode)
665 : 242494 : && !standard_sse_constant_p (op1, mode))
666 : : /* ix86_expand_vector_move_misalign() does not like constants. */
667 : : || (SSE_REG_MODE_P (mode)
668 : 242762 : && MEM_P (op0)
669 : 41071 : && MEM_ALIGN (op0) < align)))
670 : : {
671 : 2025 : 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 : 2011 : machine_mode mode = GET_MODE (op0);
684 : 2011 : rtx tmp = ix86_convert_const_wide_int_to_broadcast
685 : 2011 : (mode, op1);
686 : 2011 : if (tmp == nullptr)
687 : 1990 : op1 = validize_mem (force_const_mem (mode, op1));
688 : : else
689 : : op1 = tmp;
690 : : }
691 : : }
692 : :
693 : 4595094 : if (can_create_pseudo_p ()
694 : 4400604 : && GET_MODE_SIZE (mode) >= 16
695 : 3712879 : && VECTOR_MODE_P (mode)
696 : 8073141 : && (MEM_P (op1)
697 : 821399 : && SYMBOL_REF_P (XEXP (op1, 0))
698 : 488526 : && CONSTANT_POOL_ADDRESS_P (XEXP (op1, 0))))
699 : : {
700 : 472738 : rtx first = ix86_broadcast_from_constant (mode, op1);
701 : 472738 : if (first != nullptr)
702 : : {
703 : : /* Broadcast to XMM/YMM/ZMM register from an integer
704 : : constant or scalar mem. */
705 : 116654 : rtx tmp = gen_reg_rtx (mode);
706 : 116654 : if (FLOAT_MODE_P (mode))
707 : 28302 : first = force_const_mem (GET_MODE_INNER (mode), first);
708 : 116654 : bool ok = ix86_expand_vector_init_duplicate (false, mode,
709 : : tmp, first);
710 : 116654 : 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 : 116654 : if (ok)
717 : : {
718 : 116654 : emit_move_insn (op0, tmp);
719 : 116654 : return;
720 : : }
721 : : }
722 : : }
723 : :
724 : : /* We need to check memory alignment for SSE mode since attribute
725 : : can make operands unaligned. */
726 : 4478440 : if (can_create_pseudo_p ()
727 : : && SSE_REG_MODE_P (mode)
728 : 9084136 : && ((MEM_P (op0) && (MEM_ALIGN (op0) < align))
729 : 4036639 : || (MEM_P (op1) && (MEM_ALIGN (op1) < align))))
730 : : {
731 : 475880 : rtx tmp[2];
732 : :
733 : : /* ix86_expand_vector_move_misalign() does not like both
734 : : arguments in memory. */
735 : 475880 : if (!register_operand (op0, mode)
736 : 475880 : && !register_operand (op1, mode))
737 : : {
738 : 153960 : rtx scratch = gen_reg_rtx (mode);
739 : 153960 : emit_move_insn (scratch, op1);
740 : 153960 : op1 = scratch;
741 : : }
742 : :
743 : 475880 : tmp[0] = op0; tmp[1] = op1;
744 : 475880 : ix86_expand_vector_move_misalign (mode, tmp);
745 : 475880 : return;
746 : : }
747 : :
748 : : /* Special case TImode to 128-bit vector conversions via V2DI. */
749 : 1108216 : if (VECTOR_MODE_P (mode)
750 : 3953970 : && GET_MODE_SIZE (mode) == 16
751 : 2786076 : && SUBREG_P (op1)
752 : 226282 : && GET_MODE (SUBREG_REG (op1)) == TImode
753 : 2864 : && TARGET_64BIT && TARGET_SSE
754 : 4004817 : && ix86_pre_reload_split ())
755 : : {
756 : 2185 : rtx tmp = gen_reg_rtx (V2DImode);
757 : 2185 : rtx lo = gen_reg_rtx (DImode);
758 : 2185 : rtx hi = gen_reg_rtx (DImode);
759 : 2185 : emit_move_insn (lo, gen_lowpart (DImode, SUBREG_REG (op1)));
760 : 2185 : emit_move_insn (hi, gen_highpart (DImode, SUBREG_REG (op1)));
761 : 2185 : emit_insn (gen_vec_concatv2di (tmp, lo, hi));
762 : 2185 : emit_move_insn (op0, gen_lowpart (mode, tmp));
763 : 2185 : return;
764 : : }
765 : :
766 : : /* If operand0 is a hard register, make operand1 a pseudo. */
767 : 4000375 : if (can_create_pseudo_p ()
768 : 7806260 : && !ix86_hardreg_mov_ok (op0, op1))
769 : : {
770 : 45 : rtx tmp = gen_reg_rtx (GET_MODE (op0));
771 : 45 : emit_move_insn (tmp, op1);
772 : 45 : emit_move_insn (op0, tmp);
773 : 45 : return;
774 : : }
775 : :
776 : : /* Make operand1 a register if it isn't already. */
777 : 4000330 : if (can_create_pseudo_p ()
778 : 3805840 : && !register_operand (op0, mode)
779 : 5078805 : && !register_operand (op1, mode))
780 : : {
781 : 217468 : rtx tmp = gen_reg_rtx (GET_MODE (op0));
782 : 217468 : emit_move_insn (tmp, op1);
783 : 217468 : emit_move_insn (op0, tmp);
784 : 217468 : return;
785 : : }
786 : :
787 : 3782862 : 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 : 10243 : ix86_avx256_split_vector_move_misalign (rtx op0, rtx op1)
794 : : {
795 : 10243 : rtx m;
796 : 10243 : rtx (*extract) (rtx, rtx, rtx);
797 : 10243 : machine_mode mode;
798 : :
799 : 10243 : if ((MEM_P (op1) && !TARGET_AVX256_SPLIT_UNALIGNED_LOAD)
800 : 3652 : || (MEM_P (op0) && !TARGET_AVX256_SPLIT_UNALIGNED_STORE))
801 : : {
802 : 10191 : emit_insn (gen_rtx_SET (op0, op1));
803 : 10191 : 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 : 792231 : ix86_expand_vector_move_misalign (machine_mode mode, rtx operands[])
934 : : {
935 : 792231 : rtx op0, op1, m;
936 : :
937 : 792231 : op0 = operands[0];
938 : 792231 : op1 = operands[1];
939 : :
940 : : /* Use unaligned load/store for AVX512 or when optimizing for size. */
941 : 1584462 : if (GET_MODE_SIZE (mode) == 64 || optimize_insn_for_size_p ())
942 : : {
943 : 20373 : emit_insn (gen_rtx_SET (op0, op1));
944 : 20373 : return;
945 : : }
946 : :
947 : 771858 : if (TARGET_AVX)
948 : : {
949 : 50322 : if (GET_MODE_SIZE (mode) == 32)
950 : 10243 : ix86_avx256_split_vector_move_misalign (op0, op1);
951 : : else
952 : : /* Always use 128-bit mov<mode>_internal pattern for AVX. */
953 : 14918 : emit_insn (gen_rtx_SET (op0, op1));
954 : 25161 : return;
955 : : }
956 : :
957 : 746697 : if (TARGET_SSE_UNALIGNED_LOAD_OPTIMAL
958 : 95 : || TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL)
959 : : {
960 : 746602 : emit_insn (gen_rtx_SET (op0, op1));
961 : 746602 : 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 : 806 : ix86_move_vector_high_sse_to_mmx (rtx op)
1054 : : {
1055 : 806 : rtx mask = gen_rtx_PARALLEL (VOIDmode,
1056 : : gen_rtvec (4, GEN_INT (0), GEN_INT (2),
1057 : : GEN_INT (0), GEN_INT (0)));
1058 : 806 : rtx dest = lowpart_subreg (V4SImode, op, GET_MODE (op));
1059 : 806 : op = gen_rtx_VEC_SELECT (V4SImode, dest, mask);
1060 : 806 : rtx insn = gen_rtx_SET (dest, op);
1061 : 806 : emit_insn (insn);
1062 : 806 : }
1063 : :
1064 : : /* Split MMX pack with signed/unsigned saturation with SSE/SSE2. */
1065 : :
1066 : : void
1067 : 716 : ix86_split_mmx_pack (rtx operands[], enum rtx_code code)
1068 : : {
1069 : 716 : rtx op0 = operands[0];
1070 : 716 : rtx op1 = operands[1];
1071 : 716 : rtx op2 = operands[2];
1072 : 716 : rtx src;
1073 : :
1074 : 716 : machine_mode dmode = GET_MODE (op0);
1075 : 716 : machine_mode smode = GET_MODE (op1);
1076 : 716 : machine_mode inner_dmode = GET_MODE_INNER (dmode);
1077 : 716 : machine_mode inner_smode = GET_MODE_INNER (smode);
1078 : :
1079 : : /* Get the corresponding SSE mode for destination. */
1080 : 716 : int nunits = 16 / GET_MODE_SIZE (inner_dmode);
1081 : 1432 : machine_mode sse_dmode = mode_for_vector (GET_MODE_INNER (dmode),
1082 : 1432 : nunits).require ();
1083 : 716 : machine_mode sse_half_dmode = mode_for_vector (GET_MODE_INNER (dmode),
1084 : 1432 : nunits / 2).require ();
1085 : :
1086 : : /* Get the corresponding SSE mode for source. */
1087 : 716 : nunits = 16 / GET_MODE_SIZE (inner_smode);
1088 : 1432 : machine_mode sse_smode = mode_for_vector (GET_MODE_INNER (smode),
1089 : 1432 : nunits).require ();
1090 : :
1091 : : /* Generate SSE pack with signed/unsigned saturation. */
1092 : 716 : rtx dest = lowpart_subreg (sse_dmode, op0, GET_MODE (op0));
1093 : 716 : op1 = lowpart_subreg (sse_smode, op1, GET_MODE (op1));
1094 : 716 : 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 : 716 : if (code == US_TRUNCATE)
1099 : 614 : 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 : 716 : emit_move_insn (dest, src);
1110 : :
1111 : 716 : ix86_move_vector_high_sse_to_mmx (op0);
1112 : 716 : }
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 : 4870 : ix86_split_mmx_punpck (rtx operands[], bool high_p)
1120 : : {
1121 : 4870 : rtx op0 = operands[0];
1122 : 4870 : rtx op1 = operands[1];
1123 : 4870 : rtx op2 = operands[2];
1124 : 4870 : machine_mode mode = GET_MODE (op1);
1125 : 4870 : rtx mask;
1126 : : /* The corresponding SSE mode. */
1127 : 4870 : machine_mode sse_mode, double_sse_mode;
1128 : :
1129 : 4870 : switch (mode)
1130 : : {
1131 : 1408 : case E_V8QImode:
1132 : 1408 : case E_V4QImode:
1133 : 1408 : case E_V2QImode:
1134 : 1408 : sse_mode = V16QImode;
1135 : 1408 : double_sse_mode = V32QImode;
1136 : 1408 : 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 : 1408 : break;
1147 : :
1148 : 2590 : case E_V4HImode:
1149 : 2590 : case E_V2HImode:
1150 : 2590 : sse_mode = V8HImode;
1151 : 2590 : double_sse_mode = V16HImode;
1152 : 2590 : 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 : 2590 : break;
1159 : :
1160 : 620 : case E_V2SImode:
1161 : 620 : sse_mode = V4SImode;
1162 : 620 : double_sse_mode = V8SImode;
1163 : 620 : mask = gen_rtx_PARALLEL (VOIDmode,
1164 : : gen_rtvec (4,
1165 : : GEN_INT (0), GEN_INT (4),
1166 : : GEN_INT (1), GEN_INT (5)));
1167 : 620 : break;
1168 : :
1169 : 252 : case E_V2SFmode:
1170 : 252 : sse_mode = V4SFmode;
1171 : 252 : double_sse_mode = V8SFmode;
1172 : 252 : mask = gen_rtx_PARALLEL (VOIDmode,
1173 : : gen_rtvec (4,
1174 : : GEN_INT (0), GEN_INT (4),
1175 : : GEN_INT (1), GEN_INT (5)));
1176 : 252 : break;
1177 : :
1178 : 0 : default:
1179 : 0 : gcc_unreachable ();
1180 : : }
1181 : :
1182 : : /* Generate SSE punpcklXX. */
1183 : 4870 : rtx dest = lowpart_subreg (sse_mode, op0, GET_MODE (op0));
1184 : 4870 : op1 = lowpart_subreg (sse_mode, op1, GET_MODE (op1));
1185 : 4870 : op2 = lowpart_subreg (sse_mode, op2, GET_MODE (op2));
1186 : :
1187 : 4870 : op1 = gen_rtx_VEC_CONCAT (double_sse_mode, op1, op2);
1188 : 4870 : op2 = gen_rtx_VEC_SELECT (sse_mode, op1, mask);
1189 : 4870 : rtx insn = gen_rtx_SET (dest, op2);
1190 : 4870 : emit_insn (insn);
1191 : :
1192 : : /* Move high bits to low bits. */
1193 : 4870 : if (high_p)
1194 : : {
1195 : 2004 : if (sse_mode == V4SFmode)
1196 : : {
1197 : 112 : mask = gen_rtx_PARALLEL (VOIDmode,
1198 : : gen_rtvec (4, GEN_INT (2), GEN_INT (3),
1199 : : GEN_INT (4), GEN_INT (5)));
1200 : 112 : op2 = gen_rtx_VEC_CONCAT (V8SFmode, dest, dest);
1201 : 112 : op1 = gen_rtx_VEC_SELECT (V4SFmode, op2, mask);
1202 : : }
1203 : : else
1204 : : {
1205 : 1892 : int sz = GET_MODE_SIZE (mode);
1206 : :
1207 : 1892 : if (sz == 4)
1208 : 252 : mask = gen_rtx_PARALLEL (VOIDmode,
1209 : : gen_rtvec (4, GEN_INT (1), GEN_INT (0),
1210 : : GEN_INT (0), GEN_INT (1)));
1211 : 1640 : else if (sz == 8)
1212 : 1640 : 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 : 1892 : dest = lowpart_subreg (V4SImode, dest, GET_MODE (dest));
1219 : 1892 : op1 = gen_rtx_VEC_SELECT (V4SImode, dest, mask);
1220 : : }
1221 : :
1222 : 2004 : insn = gen_rtx_SET (dest, op1);
1223 : 2004 : emit_insn (insn);
1224 : : }
1225 : 4870 : }
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 : 173533547 : ix86_swap_binary_operands_p (enum rtx_code code, machine_mode mode,
1232 : : rtx operands[])
1233 : : {
1234 : 173533547 : rtx dst = operands[0];
1235 : 173533547 : rtx src1 = operands[1];
1236 : 173533547 : rtx src2 = operands[2];
1237 : :
1238 : : /* If the operation is not commutative, we can't do anything. */
1239 : 173533547 : if (GET_RTX_CLASS (code) != RTX_COMM_ARITH
1240 : 26815397 : && GET_RTX_CLASS (code) != RTX_COMM_COMPARE)
1241 : : return false;
1242 : :
1243 : : /* Highest priority is that src1 should match dst. */
1244 : 146727996 : if (rtx_equal_p (dst, src1))
1245 : : return false;
1246 : 106932176 : if (rtx_equal_p (dst, src2))
1247 : : return true;
1248 : :
1249 : : /* Next highest priority is that immediate constants come second. */
1250 : 106854560 : if (immediate_operand (src2, mode))
1251 : : return false;
1252 : 24766943 : if (immediate_operand (src1, mode))
1253 : : return true;
1254 : :
1255 : : /* Lowest priority is that memory references should come second. */
1256 : 24766943 : if (MEM_P (src2))
1257 : : return false;
1258 : 23436420 : 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 : 13349519 : ix86_fixup_binary_operands (enum rtx_code code, machine_mode mode,
1271 : : rtx operands[], bool use_ndd)
1272 : : {
1273 : 13349519 : rtx dst = operands[0];
1274 : 13349519 : rtx src1 = operands[1];
1275 : 13349519 : rtx src2 = operands[2];
1276 : :
1277 : : /* Canonicalize operand order. */
1278 : 13349519 : if (ix86_swap_binary_operands_p (code, mode, operands))
1279 : : {
1280 : : /* It is invalid to swap operands of different modes. */
1281 : 85071 : 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 : 13349519 : if (MEM_P (src1) && MEM_P (src2))
1288 : : {
1289 : : /* Optimization: Only read from memory once. */
1290 : 87271 : if (rtx_equal_p (src1, src2))
1291 : : {
1292 : 9 : src2 = force_reg (mode, src2);
1293 : 9 : src1 = src2;
1294 : : }
1295 : 87262 : else if (rtx_equal_p (dst, src1))
1296 : 3084 : src2 = force_reg (mode, src2);
1297 : : else
1298 : 84178 : 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 : 13349519 : if (MEM_P (dst) && !rtx_equal_p (dst, src1))
1304 : 500253 : dst = gen_reg_rtx (mode);
1305 : :
1306 : : /* Source 1 cannot be a constant. */
1307 : 13349519 : if (CONSTANT_P (src1))
1308 : 716 : src1 = force_reg (mode, src1);
1309 : :
1310 : : /* Source 1 cannot be a non-matching memory. */
1311 : 13349519 : if (!use_ndd && MEM_P (src1) && !rtx_equal_p (dst, src1))
1312 : 460131 : src1 = force_reg (mode, src1);
1313 : :
1314 : : /* Improve address combine. */
1315 : 13349519 : if (code == PLUS
1316 : 9780739 : && GET_MODE_CLASS (mode) == MODE_INT
1317 : 9674696 : && MEM_P (src2))
1318 : 178978 : src2 = force_reg (mode, src2);
1319 : :
1320 : 13349519 : operands[1] = src1;
1321 : 13349519 : operands[2] = src2;
1322 : 13349519 : return dst;
1323 : : }
1324 : :
1325 : : /* Similarly, but assume that the destination has already been
1326 : : set up properly. */
1327 : :
1328 : : void
1329 : 263879 : ix86_fixup_binary_operands_no_copy (enum rtx_code code,
1330 : : machine_mode mode, rtx operands[],
1331 : : bool use_ndd)
1332 : : {
1333 : 263879 : rtx dst = ix86_fixup_binary_operands (code, mode, operands, use_ndd);
1334 : 263879 : gcc_assert (dst == operands[0]);
1335 : 263879 : }
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 : 13085511 : ix86_expand_binary_operator (enum rtx_code code, machine_mode mode,
1343 : : rtx operands[], bool use_ndd)
1344 : : {
1345 : 13085511 : rtx src1, src2, dst, op, clob;
1346 : :
1347 : 13085511 : dst = ix86_fixup_binary_operands (code, mode, operands, use_ndd);
1348 : 13085511 : src1 = operands[1];
1349 : 13085511 : src2 = operands[2];
1350 : :
1351 : : /* Emit the instruction. */
1352 : :
1353 : 13085511 : op = gen_rtx_SET (dst, gen_rtx_fmt_ee (code, mode, src1, src2));
1354 : :
1355 : 13085511 : if (reload_completed
1356 : 84120 : && code == PLUS
1357 : 894 : && !rtx_equal_p (dst, src1)
1358 : 13085511 : && !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 : 13085511 : clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
1366 : 13085511 : emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, op, clob)));
1367 : : }
1368 : :
1369 : : /* Fix up the destination if needed. */
1370 : 13085511 : if (dst != operands[0])
1371 : 500244 : emit_move_insn (operands[0], dst);
1372 : 13085511 : }
1373 : :
1374 : : /* Expand vector logical operation CODE (AND, IOR, XOR) in MODE with
1375 : : the given OPERANDS. */
1376 : :
1377 : : void
1378 : 65535 : ix86_expand_vector_logical_operator (enum rtx_code code, machine_mode mode,
1379 : : rtx operands[])
1380 : : {
1381 : 65535 : rtx op1 = NULL_RTX, op2 = NULL_RTX;
1382 : 65535 : if (SUBREG_P (operands[1]))
1383 : : {
1384 : 312 : op1 = operands[1];
1385 : 312 : op2 = operands[2];
1386 : : }
1387 : 65223 : 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 : 3157 : if (op1
1398 : 3157 : && !TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL
1399 : 3157 : && (SUBREG_P (op2) || GET_CODE (op2) == CONST_VECTOR)
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 : && (GET_CODE (op2) == CONST_VECTOR
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 (GET_CODE (op2) == CONST_VECTOR)
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 : 65518 : if (!vector_operand (operands[1], mode))
1443 : 0 : operands[1] = force_reg (mode, operands[1]);
1444 : 65518 : if (!vector_operand (operands[2], mode))
1445 : 9419 : operands[2] = force_reg (mode, operands[2]);
1446 : 65518 : ix86_fixup_binary_operands_no_copy (code, mode, operands);
1447 : 65518 : 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 : 161083131 : ix86_binary_operator_ok (enum rtx_code code, machine_mode mode,
1457 : : rtx operands[3], bool use_ndd)
1458 : : {
1459 : 161083131 : rtx dst = operands[0];
1460 : 161083131 : rtx src1 = operands[1];
1461 : 161083131 : rtx src2 = operands[2];
1462 : :
1463 : : /* Both source operands cannot be in memory. */
1464 : 153686802 : if ((MEM_P (src1) || bcst_mem_operand (src1, mode))
1465 : 161083528 : && (MEM_P (src2) || bcst_mem_operand (src2, mode)))
1466 : 899103 : return false;
1467 : :
1468 : : /* Canonicalize operand order for commutative operators. */
1469 : 160184028 : if (ix86_swap_binary_operands_p (code, mode, operands))
1470 : 548660 : std::swap (src1, src2);
1471 : :
1472 : : /* If the destination is memory, we must have a matching source operand. */
1473 : 160184028 : if (MEM_P (dst) && !rtx_equal_p (dst, src1))
1474 : : return false;
1475 : :
1476 : : /* Source 1 cannot be a constant. */
1477 : 154871876 : if (CONSTANT_P (src1))
1478 : : return false;
1479 : :
1480 : : /* Source 1 cannot be a non-matching memory. */
1481 : 154869079 : if (!use_ndd && MEM_P (src1) && !rtx_equal_p (dst, src1))
1482 : : /* Support "andhi/andsi/anddi" as a zero-extending move. */
1483 : 4526972 : return (code == AND
1484 : 666944 : && (mode == HImode
1485 : 666944 : || mode == SImode
1486 : 398915 : || (TARGET_64BIT && mode == DImode))
1487 : 4887459 : && 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 : 118423 : ix86_expand_unary_operator (enum rtx_code code, machine_mode mode,
1498 : : rtx operands[], bool use_ndd)
1499 : : {
1500 : 118423 : bool matching_memory = false;
1501 : 118423 : rtx src, dst, op, clob;
1502 : :
1503 : 118423 : dst = operands[0];
1504 : 118423 : src = operands[1];
1505 : :
1506 : : /* If the destination is memory, and we do not have matching source
1507 : : operands, do things in registers. */
1508 : 118423 : if (MEM_P (dst))
1509 : : {
1510 : 2975 : if (rtx_equal_p (dst, src))
1511 : : matching_memory = true;
1512 : : else
1513 : 2658 : dst = gen_reg_rtx (mode);
1514 : : }
1515 : :
1516 : : /* When source operand is memory, destination must match. */
1517 : 118423 : if (!use_ndd && MEM_P (src) && !matching_memory)
1518 : 4462 : src = force_reg (mode, src);
1519 : :
1520 : : /* Emit the instruction. */
1521 : :
1522 : 118423 : op = gen_rtx_SET (dst, gen_rtx_fmt_e (code, mode, src));
1523 : :
1524 : 118423 : if (code == NOT)
1525 : 67755 : emit_insn (op);
1526 : : else
1527 : : {
1528 : 50668 : clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
1529 : 50668 : emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, op, clob)));
1530 : : }
1531 : :
1532 : : /* Fix up the destination if needed. */
1533 : 118423 : if (dst != operands[0])
1534 : 2658 : emit_move_insn (operands[0], dst);
1535 : 118423 : }
1536 : :
1537 : : /* Return TRUE or FALSE depending on whether the unary operator meets the
1538 : : appropriate constraints. */
1539 : :
1540 : : bool
1541 : 1723413 : 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 : 1723413 : if ((MEM_P (operands[0])
1548 : 1680507 : || (!use_ndd && MEM_P (operands[1])))
1549 : 1753035 : && ! 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 : 59277 : predict_jump (int prob)
1558 : : {
1559 : 59277 : rtx_insn *insn = get_last_insn ();
1560 : 59277 : gcc_assert (JUMP_P (insn));
1561 : 59277 : add_reg_br_prob_note (insn, profile_probability::from_reg_br_prob_base (prob));
1562 : 59277 : }
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 : 8305 : ix86_emit_binop (enum rtx_code code, machine_mode mode,
1681 : : rtx dst, rtx src)
1682 : : {
1683 : 8305 : rtx op, clob;
1684 : :
1685 : 8305 : op = gen_rtx_SET (dst, gen_rtx_fmt_ee (code, mode, dst, src));
1686 : 8305 : clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
1687 : :
1688 : 8305 : emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, op, clob)));
1689 : 8305 : }
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 : 6486 : ix86_split_lea_for_addr (rtx_insn *insn, rtx operands[], machine_mode mode)
1729 : : {
1730 : 6486 : unsigned int regno0, regno1, regno2;
1731 : 6486 : struct ix86_address parts;
1732 : 6486 : rtx target, tmp;
1733 : 6486 : int ok, adds;
1734 : :
1735 : 6486 : ok = ix86_decompose_address (operands[1], &parts);
1736 : 6486 : gcc_assert (ok);
1737 : :
1738 : 6486 : target = gen_lowpart (mode, operands[0]);
1739 : :
1740 : 6486 : regno0 = true_regnum (target);
1741 : 6486 : regno1 = INVALID_REGNUM;
1742 : 6486 : regno2 = INVALID_REGNUM;
1743 : :
1744 : 6486 : if (parts.base)
1745 : : {
1746 : 6478 : parts.base = gen_lowpart (mode, parts.base);
1747 : 6478 : regno1 = true_regnum (parts.base);
1748 : : }
1749 : :
1750 : 6486 : if (parts.index)
1751 : : {
1752 : 6483 : parts.index = gen_lowpart (mode, parts.index);
1753 : 6483 : regno2 = true_regnum (parts.index);
1754 : : }
1755 : :
1756 : 6486 : if (parts.disp)
1757 : 176 : parts.disp = gen_lowpart (mode, parts.disp);
1758 : :
1759 : 6486 : 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 : 7 : 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 : 6475 : 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 : 6475 : if (!parts.base)
1799 : : {
1800 : 0 : if (regno0 != regno2)
1801 : 0 : emit_insn (gen_rtx_SET (target, parts.index));
1802 : : }
1803 : 6475 : 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 : 6472 : if (regno0 == regno1)
1811 : : tmp = parts.index;
1812 : 2886 : 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 : 6457 : ix86_emit_binop (PLUS, mode, target, tmp);
1835 : : }
1836 : :
1837 : 6460 : 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 : 48 : ix86_expand_vector_convert_uns_vsivsf (rtx target, rtx val)
2073 : : {
2074 : 48 : rtx tmp[8];
2075 : 48 : REAL_VALUE_TYPE TWO16r;
2076 : 48 : machine_mode intmode = GET_MODE (val);
2077 : 48 : machine_mode fltmode = GET_MODE (target);
2078 : 48 : rtx (*cvt) (rtx, rtx);
2079 : :
2080 : 48 : if (intmode == V4SImode)
2081 : : cvt = gen_floatv4siv4sf2;
2082 : : else
2083 : 2 : cvt = gen_floatv8siv8sf2;
2084 : 48 : tmp[0] = ix86_build_const_vector (intmode, 1, GEN_INT (0xffff));
2085 : 48 : tmp[0] = force_reg (intmode, tmp[0]);
2086 : 48 : tmp[1] = expand_simple_binop (intmode, AND, val, tmp[0], NULL_RTX, 1,
2087 : : OPTAB_DIRECT);
2088 : 48 : tmp[2] = expand_simple_binop (intmode, LSHIFTRT, val, GEN_INT (16),
2089 : : NULL_RTX, 1, OPTAB_DIRECT);
2090 : 48 : tmp[3] = gen_reg_rtx (fltmode);
2091 : 48 : emit_insn (cvt (tmp[3], tmp[1]));
2092 : 48 : tmp[4] = gen_reg_rtx (fltmode);
2093 : 48 : emit_insn (cvt (tmp[4], tmp[2]));
2094 : 48 : real_ldexp (&TWO16r, &dconst1, 16);
2095 : 48 : tmp[5] = const_double_from_real_value (TWO16r, SFmode);
2096 : 48 : tmp[5] = force_reg (fltmode, ix86_build_const_vector (fltmode, 1, tmp[5]));
2097 : 48 : 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 : 47 : tmp[6] = expand_simple_binop (fltmode, MULT, tmp[4], tmp[5],
2105 : : NULL_RTX, 1, OPTAB_DIRECT);
2106 : 47 : tmp[7] = expand_simple_binop (fltmode, PLUS, tmp[3], tmp[6],
2107 : : target, 1, OPTAB_DIRECT);
2108 : 47 : if (tmp[7] != target)
2109 : 0 : emit_move_insn (target, tmp[7]);
2110 : : }
2111 : 48 : }
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 : 244 : ix86_expand_adjust_ufix_to_sfix_si (rtx val, rtx *xorp)
2120 : : {
2121 : 244 : REAL_VALUE_TYPE TWO31r;
2122 : 244 : rtx two31r, tmp[4];
2123 : 244 : machine_mode mode = GET_MODE (val);
2124 : 244 : machine_mode scalarmode = GET_MODE_INNER (mode);
2125 : 488 : machine_mode intmode = GET_MODE_SIZE (mode) == 32 ? V8SImode : V4SImode;
2126 : 244 : rtx (*cmp) (rtx, rtx, rtx, rtx);
2127 : 244 : int i;
2128 : :
2129 : 976 : for (i = 0; i < 3; i++)
2130 : 732 : tmp[i] = gen_reg_rtx (mode);
2131 : 244 : real_ldexp (&TWO31r, &dconst1, 31);
2132 : 244 : two31r = const_double_from_real_value (TWO31r, scalarmode);
2133 : 244 : two31r = ix86_build_const_vector (mode, 1, two31r);
2134 : 244 : two31r = force_reg (mode, two31r);
2135 : 244 : switch (mode)
2136 : : {
2137 : : case E_V8SFmode: cmp = gen_avx_maskcmpv8sf3; break;
2138 : 10 : case E_V4SFmode: cmp = gen_sse_maskcmpv4sf3; break;
2139 : 0 : case E_V4DFmode: cmp = gen_avx_maskcmpv4df3; break;
2140 : 234 : case E_V2DFmode: cmp = gen_sse2_maskcmpv2df3; break;
2141 : 0 : default: gcc_unreachable ();
2142 : : }
2143 : 244 : tmp[3] = gen_rtx_LE (mode, two31r, val);
2144 : 244 : emit_insn (cmp (tmp[0], two31r, val, tmp[3]));
2145 : 244 : tmp[1] = expand_simple_binop (mode, AND, tmp[0], two31r, tmp[1],
2146 : : 0, OPTAB_DIRECT);
2147 : 244 : if (intmode == V4SImode || TARGET_AVX2)
2148 : 488 : *xorp = expand_simple_binop (intmode, ASHIFT,
2149 : 244 : 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 : 244 : return expand_simple_binop (mode, MINUS, val, tmp[1], tmp[2],
2162 : 244 : 0, OPTAB_DIRECT);
2163 : : }
2164 : :
2165 : : /* Generate code for floating point ABS or NEG. */
2166 : :
2167 : : void
2168 : 34412 : ix86_expand_fp_absneg_operator (enum rtx_code code, machine_mode mode,
2169 : : rtx operands[])
2170 : : {
2171 : 34412 : rtx set, dst, src;
2172 : 34412 : bool use_sse = false;
2173 : 34412 : bool vector_mode = VECTOR_MODE_P (mode);
2174 : 34412 : machine_mode vmode = mode;
2175 : 34412 : rtvec par;
2176 : :
2177 : 34412 : 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 : 9792 : case E_SFmode:
2188 : 9792 : use_sse = TARGET_SSE_MATH && TARGET_SSE;
2189 : : vmode = V4SFmode;
2190 : : break;
2191 : 15507 : case E_DFmode:
2192 : 15507 : use_sse = TARGET_SSE_MATH && TARGET_SSE2;
2193 : : vmode = V2DFmode;
2194 : : break;
2195 : 9014 : default:
2196 : 9014 : use_sse = vector_mode || mode == TFmode;
2197 : 9014 : break;
2198 : : }
2199 : :
2200 : 34412 : dst = operands[0];
2201 : 34412 : src = operands[1];
2202 : :
2203 : 34412 : set = gen_rtx_fmt_e (code, mode, src);
2204 : 34412 : set = gen_rtx_SET (dst, set);
2205 : :
2206 : 34412 : if (use_sse)
2207 : : {
2208 : 28833 : rtx mask, use, clob;
2209 : :
2210 : : /* NEG and ABS performed with SSE use bitwise mask operations.
2211 : : Create the appropriate mask now. */
2212 : 28833 : mask = ix86_build_signbit_mask (vmode, vector_mode, code == ABS);
2213 : 28833 : use = gen_rtx_USE (VOIDmode, mask);
2214 : 28833 : if (vector_mode || mode == TFmode)
2215 : 4784 : par = gen_rtvec (2, set, use);
2216 : : else
2217 : : {
2218 : 24049 : clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
2219 : 24049 : par = gen_rtvec (3, set, use, clob);
2220 : : }
2221 : : }
2222 : : else
2223 : : {
2224 : 5579 : rtx clob;
2225 : :
2226 : : /* Changing of sign for FP values is doable using integer unit too. */
2227 : 5579 : clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
2228 : 5579 : par = gen_rtvec (2, set, clob);
2229 : : }
2230 : :
2231 : 34412 : emit_insn (gen_rtx_PARALLEL (VOIDmode, par));
2232 : 34412 : }
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 : 23211 : ix86_expand_copysign (rtx operands[])
2325 : : {
2326 : 23211 : machine_mode mode, vmode;
2327 : 23211 : rtx dest, vdest, op0, op1, mask, op2, op3;
2328 : :
2329 : 23211 : mode = GET_MODE (operands[0]);
2330 : :
2331 : 23211 : 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 : 11562 : case E_SFmode:
2340 : 11562 : vmode = V4SFmode;
2341 : 11562 : break;
2342 : 11516 : case E_DFmode:
2343 : 11516 : vmode = V2DFmode;
2344 : 11516 : break;
2345 : 121 : case E_TFmode:
2346 : 121 : vmode = mode;
2347 : 121 : break;
2348 : 0 : default:
2349 : 0 : gcc_unreachable();
2350 : : }
2351 : :
2352 : 23211 : if (rtx_equal_p (operands[1], operands[2]))
2353 : : {
2354 : 0 : emit_move_insn (operands[0], operands[1]);
2355 : 0 : return;
2356 : : }
2357 : :
2358 : 23211 : dest = operands[0];
2359 : 23211 : vdest = lowpart_subreg (vmode, dest, mode);
2360 : 23211 : if (vdest == NULL_RTX)
2361 : 0 : vdest = gen_reg_rtx (vmode);
2362 : : else
2363 : : dest = NULL_RTX;
2364 : 23211 : op1 = lowpart_subreg (vmode, force_reg (mode, operands[2]), mode);
2365 : 46408 : mask = ix86_build_signbit_mask (vmode, TARGET_AVX512F && mode != HFmode, 0);
2366 : :
2367 : 23211 : if (CONST_DOUBLE_P (operands[1]))
2368 : : {
2369 : 22738 : op0 = simplify_unary_operation (ABS, mode, operands[1], mode);
2370 : : /* Optimize for 0, simplify b = copy_signf (0.0f, a) to b = mask & a. */
2371 : 22738 : if (op0 == CONST0_RTX (mode))
2372 : : {
2373 : 109 : emit_move_insn (vdest, gen_rtx_AND (vmode, mask, op1));
2374 : 109 : if (dest)
2375 : 0 : emit_move_insn (dest, lowpart_subreg (mode, vdest, vmode));
2376 : 109 : return;
2377 : : }
2378 : :
2379 : 45258 : if (GET_MODE_SIZE (mode) < 16)
2380 : 22617 : op0 = ix86_build_const_vector (vmode, false, op0);
2381 : 22629 : op0 = force_reg (vmode, op0);
2382 : : }
2383 : : else
2384 : 473 : op0 = lowpart_subreg (vmode, force_reg (mode, operands[1]), mode);
2385 : :
2386 : 23102 : op2 = gen_reg_rtx (vmode);
2387 : 23102 : op3 = gen_reg_rtx (vmode);
2388 : 23102 : emit_move_insn (op2, gen_rtx_AND (vmode,
2389 : : gen_rtx_NOT (vmode, mask),
2390 : : op0));
2391 : 23102 : emit_move_insn (op3, gen_rtx_AND (vmode, mask, op1));
2392 : 23102 : emit_move_insn (vdest, gen_rtx_IOR (vmode, op2, op3));
2393 : 23102 : if (dest)
2394 : 0 : emit_move_insn (dest, lowpart_subreg (mode, vdest, vmode));
2395 : : }
2396 : :
2397 : : /* Expand an xorsign operation. */
2398 : :
2399 : : void
2400 : 20 : ix86_expand_xorsign (rtx operands[])
2401 : : {
2402 : 20 : machine_mode mode, vmode;
2403 : 20 : rtx dest, vdest, op0, op1, mask, x, temp;
2404 : :
2405 : 20 : dest = operands[0];
2406 : 20 : op0 = operands[1];
2407 : 20 : op1 = operands[2];
2408 : :
2409 : 20 : mode = GET_MODE (dest);
2410 : :
2411 : 20 : switch (mode)
2412 : : {
2413 : : case E_HFmode:
2414 : : vmode = V8HFmode;
2415 : : break;
2416 : : case E_BFmode:
2417 : : vmode = V8BFmode;
2418 : : break;
2419 : : case E_SFmode:
2420 : : vmode = V4SFmode;
2421 : : break;
2422 : : case E_DFmode:
2423 : : vmode = V2DFmode;
2424 : : break;
2425 : 0 : default:
2426 : 0 : gcc_unreachable ();
2427 : 20 : break;
2428 : : }
2429 : :
2430 : 20 : temp = gen_reg_rtx (vmode);
2431 : 20 : mask = ix86_build_signbit_mask (vmode, 0, 0);
2432 : :
2433 : 20 : op1 = lowpart_subreg (vmode, force_reg (mode, op1), mode);
2434 : 20 : x = gen_rtx_AND (vmode, op1, mask);
2435 : 20 : emit_insn (gen_rtx_SET (temp, x));
2436 : :
2437 : 20 : op0 = lowpart_subreg (vmode, force_reg (mode, op0), mode);
2438 : 20 : x = gen_rtx_XOR (vmode, temp, op0);
2439 : :
2440 : 20 : vdest = lowpart_subreg (vmode, dest, mode);
2441 : 20 : if (vdest == NULL_RTX)
2442 : 0 : vdest = gen_reg_rtx (vmode);
2443 : : else
2444 : : dest = NULL_RTX;
2445 : 20 : emit_insn (gen_rtx_SET (vdest, x));
2446 : :
2447 : 20 : if (dest)
2448 : 0 : emit_move_insn (dest, lowpart_subreg (mode, vdest, vmode));
2449 : 20 : }
2450 : :
2451 : : static rtx ix86_expand_compare (enum rtx_code code, rtx op0, rtx op1);
2452 : :
2453 : : void
2454 : 6525216 : ix86_expand_branch (enum rtx_code code, rtx op0, rtx op1, rtx label)
2455 : : {
2456 : 6525216 : machine_mode mode = GET_MODE (op0);
2457 : 6525216 : rtx tmp;
2458 : :
2459 : : /* Handle special case - vector comparsion with boolean result, transform
2460 : : it using ptest instruction or vpcmpeq + kortest. */
2461 : 6525216 : if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT
2462 : 6520280 : || (mode == TImode && !TARGET_64BIT)
2463 : 6520280 : || mode == OImode
2464 : 13045496 : || GET_MODE_SIZE (mode) == 64)
2465 : : {
2466 : 4936 : unsigned msize = GET_MODE_SIZE (mode);
2467 : 4936 : machine_mode p_mode
2468 : 4936 : = msize == 64 ? V16SImode : msize == 32 ? V4DImode : V2DImode;
2469 : : /* kortest set CF when result is 0xFFFF (op0 == op1). */
2470 : 4936 : rtx flag = gen_rtx_REG (msize == 64 ? CCCmode : CCZmode, FLAGS_REG);
2471 : :
2472 : 4936 : gcc_assert (code == EQ || code == NE);
2473 : :
2474 : : /* Using vpcmpeq zmm zmm k + kortest for 512-bit vectors. */
2475 : 4936 : if (msize == 64)
2476 : : {
2477 : 1356 : if (mode != V16SImode)
2478 : : {
2479 : 1356 : op0 = lowpart_subreg (p_mode, force_reg (mode, op0), mode);
2480 : 1356 : op1 = lowpart_subreg (p_mode, force_reg (mode, op1), mode);
2481 : : }
2482 : :
2483 : 1356 : tmp = gen_reg_rtx (HImode);
2484 : 1356 : emit_insn (gen_avx512f_cmpv16si3 (tmp, op0, op1, GEN_INT (0)));
2485 : 1356 : emit_insn (gen_kortesthi_ccc (tmp, tmp));
2486 : : }
2487 : : /* Using ptest for 128/256-bit vectors. */
2488 : : else
2489 : : {
2490 : 3580 : if (GET_MODE_CLASS (mode) != MODE_VECTOR_INT)
2491 : : {
2492 : 0 : op0 = lowpart_subreg (p_mode, force_reg (mode, op0), mode);
2493 : 0 : op1 = lowpart_subreg (p_mode, force_reg (mode, op1), mode);
2494 : 0 : mode = p_mode;
2495 : : }
2496 : :
2497 : : /* Generate XOR since we can't check that one operand is zero
2498 : : vector. */
2499 : 3580 : tmp = gen_reg_rtx (mode);
2500 : 3580 : rtx ops[3] = { tmp, op0, op1 };
2501 : 3580 : ix86_expand_vector_logical_operator (XOR, mode, ops);
2502 : 3580 : tmp = gen_lowpart (p_mode, tmp);
2503 : 3580 : emit_insn (gen_rtx_SET (gen_rtx_REG (CCZmode, FLAGS_REG),
2504 : : gen_rtx_UNSPEC (CCZmode,
2505 : : gen_rtvec (2, tmp, tmp),
2506 : : UNSPEC_PTEST)));
2507 : : }
2508 : 4936 : tmp = gen_rtx_fmt_ee (code, VOIDmode, flag, const0_rtx);
2509 : 4936 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
2510 : : gen_rtx_LABEL_REF (VOIDmode, label),
2511 : : pc_rtx);
2512 : 4936 : emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
2513 : 4936 : return;
2514 : : }
2515 : :
2516 : 6520280 : switch (mode)
2517 : : {
2518 : 6484831 : case E_HFmode:
2519 : 6484831 : case E_SFmode:
2520 : 6484831 : case E_DFmode:
2521 : 6484831 : case E_XFmode:
2522 : 6484831 : case E_QImode:
2523 : 6484831 : case E_HImode:
2524 : 6484831 : case E_SImode:
2525 : 6484831 : simple:
2526 : 6484831 : tmp = ix86_expand_compare (code, op0, op1);
2527 : 6484831 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
2528 : : gen_rtx_LABEL_REF (VOIDmode, label),
2529 : : pc_rtx);
2530 : 6484831 : emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
2531 : 6484831 : return;
2532 : :
2533 : 7 : case E_BFmode:
2534 : 7 : gcc_assert (TARGET_AVX10_2 && !flag_trapping_math);
2535 : 7 : goto simple;
2536 : :
2537 : 2556987 : case E_DImode:
2538 : 2556987 : if (TARGET_64BIT)
2539 : 2529385 : goto simple;
2540 : : /* FALLTHRU */
2541 : 83472 : case E_TImode:
2542 : : /* DI and TI mode equality/inequality comparisons may be performed
2543 : : on SSE registers. Avoid splitting them, except when optimizing
2544 : : for size. */
2545 : 83472 : if ((code == EQ || code == NE)
2546 : 83472 : && !optimize_insn_for_size_p ())
2547 : 48023 : goto simple;
2548 : :
2549 : : /* Expand DImode branch into multiple compare+branch. */
2550 : 35449 : {
2551 : 35449 : rtx lo[2], hi[2];
2552 : 35449 : rtx_code_label *label2;
2553 : 35449 : enum rtx_code code1, code2, code3;
2554 : 35449 : machine_mode submode;
2555 : :
2556 : 35449 : if (CONSTANT_P (op0) && !CONSTANT_P (op1))
2557 : : {
2558 : 0 : std::swap (op0, op1);
2559 : 0 : code = swap_condition (code);
2560 : : }
2561 : :
2562 : 35449 : split_double_mode (mode, &op0, 1, lo+0, hi+0);
2563 : 35449 : split_double_mode (mode, &op1, 1, lo+1, hi+1);
2564 : :
2565 : 35449 : submode = mode == DImode ? SImode : DImode;
2566 : :
2567 : : /* If we are doing less-than or greater-or-equal-than,
2568 : : op1 is a constant and the low word is zero, then we can just
2569 : : examine the high word. Similarly for low word -1 and
2570 : : less-or-equal-than or greater-than. */
2571 : :
2572 : 35449 : if (CONST_INT_P (hi[1]))
2573 : 24106 : switch (code)
2574 : : {
2575 : 10772 : case LT: case LTU: case GE: case GEU:
2576 : 10772 : if (lo[1] == const0_rtx)
2577 : : {
2578 : 10365 : ix86_expand_branch (code, hi[0], hi[1], label);
2579 : 10365 : return;
2580 : : }
2581 : : break;
2582 : 11767 : case LE: case LEU: case GT: case GTU:
2583 : 11767 : if (lo[1] == constm1_rtx)
2584 : : {
2585 : 530 : ix86_expand_branch (code, hi[0], hi[1], label);
2586 : 530 : return;
2587 : : }
2588 : : break;
2589 : : default:
2590 : : break;
2591 : : }
2592 : :
2593 : : /* Emulate comparisons that do not depend on Zero flag with
2594 : : double-word subtraction. Note that only Overflow, Sign
2595 : : and Carry flags are valid, so swap arguments and condition
2596 : : of comparisons that would otherwise test Zero flag. */
2597 : :
2598 : 24554 : switch (code)
2599 : : {
2600 : 17051 : case LE: case LEU: case GT: case GTU:
2601 : 17051 : std::swap (lo[0], lo[1]);
2602 : 17051 : std::swap (hi[0], hi[1]);
2603 : 17051 : code = swap_condition (code);
2604 : : /* FALLTHRU */
2605 : :
2606 : 21513 : case LT: case LTU: case GE: case GEU:
2607 : 21513 : {
2608 : 21513 : bool uns = (code == LTU || code == GEU);
2609 : 3966 : rtx (*sbb_insn) (machine_mode, rtx, rtx, rtx)
2610 : 21513 : = uns ? gen_sub3_carry_ccc : gen_sub3_carry_ccgz;
2611 : :
2612 : 21513 : if (!nonimmediate_operand (lo[0], submode))
2613 : 11237 : lo[0] = force_reg (submode, lo[0]);
2614 : 21513 : if (!x86_64_general_operand (lo[1], submode))
2615 : 0 : lo[1] = force_reg (submode, lo[1]);
2616 : :
2617 : 21513 : if (!register_operand (hi[0], submode))
2618 : 12060 : hi[0] = force_reg (submode, hi[0]);
2619 : 17547 : if ((uns && !nonimmediate_operand (hi[1], submode))
2620 : 21513 : || (!uns && !x86_64_general_operand (hi[1], submode)))
2621 : 315 : hi[1] = force_reg (submode, hi[1]);
2622 : :
2623 : 21513 : emit_insn (gen_cmp_1 (submode, lo[0], lo[1]));
2624 : :
2625 : 21513 : tmp = gen_rtx_SCRATCH (submode);
2626 : 21513 : emit_insn (sbb_insn (submode, tmp, hi[0], hi[1]));
2627 : :
2628 : 25479 : tmp = gen_rtx_REG (uns ? CCCmode : CCGZmode, FLAGS_REG);
2629 : 21513 : ix86_expand_branch (code, tmp, const0_rtx, label);
2630 : 21513 : return;
2631 : : }
2632 : :
2633 : 3041 : default:
2634 : 3041 : break;
2635 : : }
2636 : :
2637 : : /* Otherwise, we need two or three jumps. */
2638 : :
2639 : 3041 : label2 = gen_label_rtx ();
2640 : :
2641 : 3041 : code1 = code;
2642 : 3041 : code2 = swap_condition (code);
2643 : 3041 : code3 = unsigned_condition (code);
2644 : :
2645 : 3041 : switch (code)
2646 : : {
2647 : : case LT: case GT: case LTU: case GTU:
2648 : : break;
2649 : :
2650 : : case LE: code1 = LT; code2 = GT; break;
2651 : : case GE: code1 = GT; code2 = LT; break;
2652 : 0 : case LEU: code1 = LTU; code2 = GTU; break;
2653 : 0 : case GEU: code1 = GTU; code2 = LTU; break;
2654 : :
2655 : : case EQ: code1 = UNKNOWN; code2 = NE; break;
2656 : : case NE: code2 = UNKNOWN; break;
2657 : :
2658 : 0 : default:
2659 : 0 : gcc_unreachable ();
2660 : : }
2661 : :
2662 : : /*
2663 : : * a < b =>
2664 : : * if (hi(a) < hi(b)) goto true;
2665 : : * if (hi(a) > hi(b)) goto false;
2666 : : * if (lo(a) < lo(b)) goto true;
2667 : : * false:
2668 : : */
2669 : :
2670 : 0 : if (code1 != UNKNOWN)
2671 : 2317 : ix86_expand_branch (code1, hi[0], hi[1], label);
2672 : 3041 : if (code2 != UNKNOWN)
2673 : 724 : ix86_expand_branch (code2, hi[0], hi[1], label2);
2674 : :
2675 : 3041 : ix86_expand_branch (code3, lo[0], lo[1], label);
2676 : :
2677 : 3041 : if (code2 != UNKNOWN)
2678 : 724 : emit_label (label2);
2679 : : return;
2680 : : }
2681 : :
2682 : 21951 : default:
2683 : 21951 : gcc_assert (GET_MODE_CLASS (GET_MODE (op0)) == MODE_CC);
2684 : 21951 : goto simple;
2685 : : }
2686 : : }
2687 : :
2688 : : /* Figure out whether to use unordered fp comparisons. */
2689 : :
2690 : : static bool
2691 : 1165721 : ix86_unordered_fp_compare (enum rtx_code code)
2692 : : {
2693 : 1165721 : if (!TARGET_IEEE_FP)
2694 : : return false;
2695 : :
2696 : 1161509 : switch (code)
2697 : : {
2698 : : case LT:
2699 : : case LE:
2700 : : case GT:
2701 : : case GE:
2702 : : case LTGT:
2703 : : return false;
2704 : :
2705 : : case EQ:
2706 : : case NE:
2707 : :
2708 : : case UNORDERED:
2709 : : case ORDERED:
2710 : : case UNLT:
2711 : : case UNLE:
2712 : : case UNGT:
2713 : : case UNGE:
2714 : : case UNEQ:
2715 : : return true;
2716 : :
2717 : 0 : default:
2718 : 0 : gcc_unreachable ();
2719 : : }
2720 : : }
2721 : :
2722 : : /* Return a comparison we can do and that it is equivalent to
2723 : : swap_condition (code) apart possibly from orderedness.
2724 : : But, never change orderedness if TARGET_IEEE_FP, returning
2725 : : UNKNOWN in that case if necessary. */
2726 : :
2727 : : static enum rtx_code
2728 : 36771 : ix86_fp_swap_condition (enum rtx_code code)
2729 : : {
2730 : 36771 : switch (code)
2731 : : {
2732 : 1859 : case GT: /* GTU - CF=0 & ZF=0 */
2733 : 1859 : return TARGET_IEEE_FP ? UNKNOWN : UNLT;
2734 : 518 : case GE: /* GEU - CF=0 */
2735 : 518 : return TARGET_IEEE_FP ? UNKNOWN : UNLE;
2736 : 440 : case UNLT: /* LTU - CF=1 */
2737 : 440 : return TARGET_IEEE_FP ? UNKNOWN : GT;
2738 : 6315 : case UNLE: /* LEU - CF=1 | ZF=1 */
2739 : 6315 : return TARGET_IEEE_FP ? UNKNOWN : GE;
2740 : 27639 : default:
2741 : 27639 : return swap_condition (code);
2742 : : }
2743 : : }
2744 : :
2745 : : /* Return cost of comparison CODE using the best strategy for performance.
2746 : : All following functions do use number of instructions as a cost metrics.
2747 : : In future this should be tweaked to compute bytes for optimize_size and
2748 : : take into account performance of various instructions on various CPUs. */
2749 : :
2750 : : static int
2751 : 1164596 : ix86_fp_comparison_cost (enum rtx_code code)
2752 : : {
2753 : 1164596 : int arith_cost;
2754 : :
2755 : : /* The cost of code using bit-twiddling on %ah. */
2756 : 1164596 : switch (code)
2757 : : {
2758 : : case UNLE:
2759 : : case UNLT:
2760 : : case LTGT:
2761 : : case GT:
2762 : : case GE:
2763 : : case UNORDERED:
2764 : : case ORDERED:
2765 : : case UNEQ:
2766 : : arith_cost = 4;
2767 : : break;
2768 : 93651 : case LT:
2769 : 93651 : case NE:
2770 : 93651 : case EQ:
2771 : 93651 : case UNGE:
2772 : 93651 : arith_cost = TARGET_IEEE_FP ? 5 : 4;
2773 : : break;
2774 : 26454 : case LE:
2775 : 26454 : case UNGT:
2776 : 1071734 : arith_cost = TARGET_IEEE_FP ? 6 : 4;
2777 : : break;
2778 : 0 : default:
2779 : 0 : gcc_unreachable ();
2780 : : }
2781 : :
2782 : 1164596 : switch (ix86_fp_comparison_strategy (code))
2783 : : {
2784 : 1164596 : case IX86_FPCMP_COMI:
2785 : 1164596 : return arith_cost > 4 ? 3 : 2;
2786 : 0 : case IX86_FPCMP_SAHF:
2787 : 0 : return arith_cost > 4 ? 4 : 3;
2788 : : default:
2789 : : return arith_cost;
2790 : : }
2791 : : }
2792 : :
2793 : : /* Swap, force into registers, or otherwise massage the two operands
2794 : : to a fp comparison. The operands are updated in place; the new
2795 : : comparison code is returned. */
2796 : :
2797 : : static enum rtx_code
2798 : 582298 : ix86_prepare_fp_compare_args (enum rtx_code code, rtx *pop0, rtx *pop1)
2799 : : {
2800 : 582368 : bool unordered_compare = ix86_unordered_fp_compare (code);
2801 : 582368 : rtx op0 = *pop0, op1 = *pop1;
2802 : 582368 : machine_mode op_mode = GET_MODE (op0);
2803 : 582368 : bool is_sse = SSE_FLOAT_MODE_SSEMATH_OR_HFBF_P (op_mode);
2804 : :
2805 : 580426 : if (op_mode == BFmode && (!TARGET_AVX10_2 || flag_trapping_math))
2806 : : {
2807 : 70 : rtx op = gen_lowpart (HImode, op0);
2808 : 70 : if (CONST_INT_P (op))
2809 : 0 : op = simplify_const_unary_operation (FLOAT_EXTEND, SFmode,
2810 : : op0, BFmode);
2811 : : else
2812 : : {
2813 : 70 : rtx t1 = gen_reg_rtx (SImode);
2814 : 70 : emit_insn (gen_zero_extendhisi2 (t1, op));
2815 : 70 : emit_insn (gen_ashlsi3 (t1, t1, GEN_INT (16)));
2816 : 70 : op = gen_lowpart (SFmode, t1);
2817 : : }
2818 : 70 : *pop0 = op;
2819 : 70 : op = gen_lowpart (HImode, op1);
2820 : 70 : if (CONST_INT_P (op))
2821 : 6 : op = simplify_const_unary_operation (FLOAT_EXTEND, SFmode,
2822 : : op1, BFmode);
2823 : : else
2824 : : {
2825 : 64 : rtx t1 = gen_reg_rtx (SImode);
2826 : 64 : emit_insn (gen_zero_extendhisi2 (t1, op));
2827 : 64 : emit_insn (gen_ashlsi3 (t1, t1, GEN_INT (16)));
2828 : 64 : op = gen_lowpart (SFmode, t1);
2829 : : }
2830 : 70 : *pop1 = op;
2831 : 70 : return ix86_prepare_fp_compare_args (code, pop0, pop1);
2832 : : }
2833 : :
2834 : : /* All of the unordered compare instructions only work on registers.
2835 : : The same is true of the fcomi compare instructions. The XFmode
2836 : : compare instructions require registers except when comparing
2837 : : against zero or when converting operand 1 from fixed point to
2838 : : floating point. */
2839 : :
2840 : 582298 : if (!is_sse
2841 : 582298 : && (unordered_compare
2842 : 8310 : || (op_mode == XFmode
2843 : 10579 : && ! (standard_80387_constant_p (op0) == 1
2844 : 5287 : || standard_80387_constant_p (op1) == 1)
2845 : 4947 : && GET_CODE (op1) != FLOAT)
2846 : 3363 : || ix86_fp_comparison_strategy (code) == IX86_FPCMP_COMI))
2847 : : {
2848 : 147931 : op0 = force_reg (op_mode, op0);
2849 : 147931 : op1 = force_reg (op_mode, op1);
2850 : : }
2851 : : else
2852 : : {
2853 : : /* %%% We only allow op1 in memory; op0 must be st(0). So swap
2854 : : things around if they appear profitable, otherwise force op0
2855 : : into a register. */
2856 : :
2857 : 434367 : if (standard_80387_constant_p (op0) == 0
2858 : 434367 : || (MEM_P (op0)
2859 : 55152 : && ! (standard_80387_constant_p (op1) == 0
2860 : 40367 : || MEM_P (op1))))
2861 : : {
2862 : 36771 : enum rtx_code new_code = ix86_fp_swap_condition (code);
2863 : 36771 : if (new_code != UNKNOWN)
2864 : : {
2865 : : std::swap (op0, op1);
2866 : 434367 : code = new_code;
2867 : : }
2868 : : }
2869 : :
2870 : 434367 : if (!REG_P (op0))
2871 : 52295 : op0 = force_reg (op_mode, op0);
2872 : :
2873 : 434367 : if (CONSTANT_P (op1))
2874 : : {
2875 : 191173 : int tmp = standard_80387_constant_p (op1);
2876 : 191173 : if (tmp == 0)
2877 : 72813 : op1 = validize_mem (force_const_mem (op_mode, op1));
2878 : 118360 : else if (tmp == 1)
2879 : : {
2880 : 64578 : if (TARGET_CMOVE)
2881 : 64578 : op1 = force_reg (op_mode, op1);
2882 : : }
2883 : : else
2884 : 53782 : op1 = force_reg (op_mode, op1);
2885 : : }
2886 : : }
2887 : :
2888 : : /* Try to rearrange the comparison to make it cheaper. */
2889 : 582298 : if (ix86_fp_comparison_cost (code)
2890 : 582298 : > ix86_fp_comparison_cost (swap_condition (code))
2891 : 582298 : && (REG_P (op1) || can_create_pseudo_p ()))
2892 : : {
2893 : 0 : std::swap (op0, op1);
2894 : 0 : code = swap_condition (code);
2895 : 0 : if (!REG_P (op0))
2896 : 0 : op0 = force_reg (op_mode, op0);
2897 : : }
2898 : :
2899 : 582298 : *pop0 = op0;
2900 : 582298 : *pop1 = op1;
2901 : 582298 : return code;
2902 : : }
2903 : :
2904 : : /* Generate insn patterns to do a floating point compare of OPERANDS. */
2905 : :
2906 : : static rtx
2907 : 582298 : ix86_expand_fp_compare (enum rtx_code code, rtx op0, rtx op1)
2908 : : {
2909 : 582298 : bool unordered_compare = ix86_unordered_fp_compare (code);
2910 : 582298 : machine_mode cmp_mode;
2911 : 582298 : rtx tmp, scratch;
2912 : :
2913 : 582298 : code = ix86_prepare_fp_compare_args (code, &op0, &op1);
2914 : :
2915 : 582298 : tmp = gen_rtx_COMPARE (CCFPmode, op0, op1);
2916 : 582298 : if (unordered_compare)
2917 : 499107 : tmp = gen_rtx_UNSPEC (CCFPmode, gen_rtvec (1, tmp), UNSPEC_NOTRAP);
2918 : :
2919 : : /* Do fcomi/sahf based test when profitable. */
2920 : 582298 : switch (ix86_fp_comparison_strategy (code))
2921 : : {
2922 : 582298 : case IX86_FPCMP_COMI:
2923 : 582298 : tmp = gen_rtx_COMPARE (CCFPmode, op0, op1);
2924 : : /* We only have vcomisbf16, No vcomubf16 nor vcomxbf16 */
2925 : 582298 : if (GET_MODE (op0) != E_BFmode)
2926 : : {
2927 : 582282 : if (TARGET_AVX10_2 && (code == EQ || code == NE))
2928 : 12 : tmp = gen_rtx_UNSPEC (CCFPmode, gen_rtvec (1, tmp), UNSPEC_OPTCOMX);
2929 : 582282 : if (unordered_compare)
2930 : 499103 : tmp = gen_rtx_UNSPEC (CCFPmode, gen_rtvec (1, tmp), UNSPEC_NOTRAP);
2931 : : }
2932 : 582298 : cmp_mode = CCFPmode;
2933 : 582298 : emit_insn (gen_rtx_SET (gen_rtx_REG (CCFPmode, FLAGS_REG), tmp));
2934 : 582298 : break;
2935 : :
2936 : 0 : case IX86_FPCMP_SAHF:
2937 : 0 : cmp_mode = CCFPmode;
2938 : 0 : tmp = gen_rtx_UNSPEC (HImode, gen_rtvec (1, tmp), UNSPEC_FNSTSW);
2939 : 0 : scratch = gen_reg_rtx (HImode);
2940 : 0 : emit_insn (gen_rtx_SET (scratch, tmp));
2941 : 0 : emit_insn (gen_x86_sahf_1 (scratch));
2942 : 0 : break;
2943 : :
2944 : 0 : case IX86_FPCMP_ARITH:
2945 : 0 : cmp_mode = CCNOmode;
2946 : 0 : tmp = gen_rtx_UNSPEC (HImode, gen_rtvec (1, tmp), UNSPEC_FNSTSW);
2947 : 0 : scratch = gen_reg_rtx (HImode);
2948 : 0 : emit_insn (gen_rtx_SET (scratch, tmp));
2949 : :
2950 : : /* In the unordered case, we have to check C2 for NaN's, which
2951 : : doesn't happen to work out to anything nice combination-wise.
2952 : : So do some bit twiddling on the value we've got in AH to come
2953 : : up with an appropriate set of condition codes. */
2954 : :
2955 : 0 : switch (code)
2956 : : {
2957 : 0 : case GT:
2958 : 0 : case UNGT:
2959 : 0 : if (code == GT || !TARGET_IEEE_FP)
2960 : : {
2961 : 0 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x45)));
2962 : 0 : code = EQ;
2963 : : }
2964 : : else
2965 : : {
2966 : 0 : emit_insn (gen_andqi_ext_1 (scratch, scratch, GEN_INT (0x45)));
2967 : 0 : emit_insn (gen_addqi_ext_1 (scratch, scratch, constm1_rtx));
2968 : 0 : emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x44)));
2969 : 0 : cmp_mode = CCmode;
2970 : 0 : code = GEU;
2971 : : }
2972 : : break;
2973 : 0 : case LT:
2974 : 0 : case UNLT:
2975 : 0 : if (code == LT && TARGET_IEEE_FP)
2976 : : {
2977 : 0 : emit_insn (gen_andqi_ext_1 (scratch, scratch, GEN_INT (0x45)));
2978 : 0 : emit_insn (gen_cmpqi_ext_3 (scratch, const1_rtx));
2979 : 0 : cmp_mode = CCmode;
2980 : 0 : code = EQ;
2981 : : }
2982 : : else
2983 : : {
2984 : 0 : emit_insn (gen_testqi_ext_1_ccno (scratch, const1_rtx));
2985 : 0 : code = NE;
2986 : : }
2987 : : break;
2988 : 0 : case GE:
2989 : 0 : case UNGE:
2990 : 0 : if (code == GE || !TARGET_IEEE_FP)
2991 : : {
2992 : 0 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x05)));
2993 : 0 : code = EQ;
2994 : : }
2995 : : else
2996 : : {
2997 : 0 : emit_insn (gen_andqi_ext_1 (scratch, scratch, GEN_INT (0x45)));
2998 : 0 : emit_insn (gen_xorqi_ext_1_cc (scratch, scratch, const1_rtx));
2999 : 0 : code = NE;
3000 : : }
3001 : : break;
3002 : 0 : case LE:
3003 : 0 : case UNLE:
3004 : 0 : if (code == LE && TARGET_IEEE_FP)
3005 : : {
3006 : 0 : emit_insn (gen_andqi_ext_1 (scratch, scratch, GEN_INT (0x45)));
3007 : 0 : emit_insn (gen_addqi_ext_1 (scratch, scratch, constm1_rtx));
3008 : 0 : emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x40)));
3009 : 0 : cmp_mode = CCmode;
3010 : 0 : code = LTU;
3011 : : }
3012 : : else
3013 : : {
3014 : 0 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x45)));
3015 : 0 : code = NE;
3016 : : }
3017 : : break;
3018 : 0 : case EQ:
3019 : 0 : case UNEQ:
3020 : 0 : if (code == EQ && TARGET_IEEE_FP)
3021 : : {
3022 : 0 : emit_insn (gen_andqi_ext_1 (scratch, scratch, GEN_INT (0x45)));
3023 : 0 : emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x40)));
3024 : 0 : cmp_mode = CCmode;
3025 : 0 : code = EQ;
3026 : : }
3027 : : else
3028 : : {
3029 : 0 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x40)));
3030 : 0 : code = NE;
3031 : : }
3032 : : break;
3033 : 0 : case NE:
3034 : 0 : case LTGT:
3035 : 0 : if (code == NE && TARGET_IEEE_FP)
3036 : : {
3037 : 0 : emit_insn (gen_andqi_ext_1 (scratch, scratch, GEN_INT (0x45)));
3038 : 0 : emit_insn (gen_xorqi_ext_1_cc (scratch, scratch,
3039 : : GEN_INT (0x40)));
3040 : 0 : code = NE;
3041 : : }
3042 : : else
3043 : : {
3044 : 0 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x40)));
3045 : 0 : code = EQ;
3046 : : }
3047 : : break;
3048 : :
3049 : 0 : case UNORDERED:
3050 : 0 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x04)));
3051 : 0 : code = NE;
3052 : 0 : break;
3053 : 0 : case ORDERED:
3054 : 0 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x04)));
3055 : 0 : code = EQ;
3056 : 0 : break;
3057 : :
3058 : 0 : default:
3059 : 0 : gcc_unreachable ();
3060 : : }
3061 : : break;
3062 : :
3063 : 0 : default:
3064 : 0 : gcc_unreachable();
3065 : : }
3066 : :
3067 : : /* Return the test that should be put into the flags user, i.e.
3068 : : the bcc, scc, or cmov instruction. */
3069 : 582298 : return gen_rtx_fmt_ee (code, VOIDmode,
3070 : : gen_rtx_REG (cmp_mode, FLAGS_REG),
3071 : : const0_rtx);
3072 : : }
3073 : :
3074 : : /* Generate insn patterns to do an integer compare of OPERANDS. */
3075 : :
3076 : : static rtx
3077 : 6820013 : ix86_expand_int_compare (enum rtx_code code, rtx op0, rtx op1)
3078 : : {
3079 : 6820013 : machine_mode cmpmode;
3080 : 6820013 : rtx tmp, flags;
3081 : :
3082 : : /* Swap operands to emit carry flag comparison. */
3083 : 6820013 : if ((code == GTU || code == LEU)
3084 : 6820013 : && nonimmediate_operand (op1, VOIDmode))
3085 : : {
3086 : 137486 : std::swap (op0, op1);
3087 : 137486 : code = swap_condition (code);
3088 : : }
3089 : :
3090 : 6820013 : cmpmode = SELECT_CC_MODE (code, op0, op1);
3091 : 6820013 : flags = gen_rtx_REG (cmpmode, FLAGS_REG);
3092 : :
3093 : : /* Attempt to use PTEST, if available, when testing vector modes for
3094 : : equality/inequality against zero. */
3095 : 6820013 : if (op1 == const0_rtx
3096 : 2852625 : && SUBREG_P (op0)
3097 : 23583 : && cmpmode == CCZmode
3098 : 10795 : && SUBREG_BYTE (op0) == 0
3099 : 8698 : && REG_P (SUBREG_REG (op0))
3100 : 8698 : && VECTOR_MODE_P (GET_MODE (SUBREG_REG (op0)))
3101 : 7 : && TARGET_SSE4_1
3102 : 1 : && GET_MODE (op0) == TImode
3103 : 6820015 : && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op0))) == 16)
3104 : : {
3105 : 1 : tmp = SUBREG_REG (op0);
3106 : 1 : if (GET_MODE (tmp) == V8HFmode || GET_MODE (tmp) == V8BFmode)
3107 : 1 : tmp = gen_lowpart (V8HImode, tmp);
3108 : 1 : tmp = gen_rtx_UNSPEC (CCZmode, gen_rtvec (2, tmp, tmp), UNSPEC_PTEST);
3109 : : }
3110 : : else
3111 : 6820012 : tmp = gen_rtx_COMPARE (cmpmode, op0, op1);
3112 : :
3113 : : /* This is very simple, but making the interface the same as in the
3114 : : FP case makes the rest of the code easier. */
3115 : 6820013 : emit_insn (gen_rtx_SET (flags, tmp));
3116 : :
3117 : : /* Return the test that should be put into the flags user, i.e.
3118 : : the bcc, scc, or cmov instruction. */
3119 : 6820013 : return gen_rtx_fmt_ee (code, VOIDmode, flags, const0_rtx);
3120 : : }
3121 : :
3122 : : static rtx
3123 : 7563805 : ix86_expand_compare (enum rtx_code code, rtx op0, rtx op1)
3124 : : {
3125 : 7563805 : rtx ret;
3126 : :
3127 : 7563805 : if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_CC)
3128 : 165315 : ret = gen_rtx_fmt_ee (code, VOIDmode, op0, op1);
3129 : :
3130 : 7398490 : else if (SCALAR_FLOAT_MODE_P (GET_MODE (op0)))
3131 : : {
3132 : 578477 : gcc_assert (!DECIMAL_FLOAT_MODE_P (GET_MODE (op0)));
3133 : 578477 : ret = ix86_expand_fp_compare (code, op0, op1);
3134 : : }
3135 : : else
3136 : 6820013 : ret = ix86_expand_int_compare (code, op0, op1);
3137 : :
3138 : 7563805 : return ret;
3139 : : }
3140 : :
3141 : : void
3142 : 529305 : ix86_expand_setcc (rtx dest, enum rtx_code code, rtx op0, rtx op1)
3143 : : {
3144 : 529305 : rtx ret;
3145 : :
3146 : 529305 : gcc_assert (GET_MODE (dest) == QImode);
3147 : :
3148 : 529305 : ret = ix86_expand_compare (code, op0, op1);
3149 : 529305 : PUT_MODE (ret, QImode);
3150 : 529305 : emit_insn (gen_rtx_SET (dest, ret));
3151 : 529305 : }
3152 : :
3153 : : /* Expand floating point op0 <=> op1, i.e.
3154 : : dest = op0 == op1 ? 0 : op0 < op1 ? -1 : op0 > op1 ? 1 : 2. */
3155 : :
3156 : : void
3157 : 250 : ix86_expand_fp_spaceship (rtx dest, rtx op0, rtx op1, rtx op2)
3158 : : {
3159 : 250 : gcc_checking_assert (ix86_fp_comparison_strategy (GT) != IX86_FPCMP_ARITH);
3160 : 250 : rtx zero = NULL_RTX;
3161 : 250 : if (op2 != const0_rtx
3162 : 52 : && (TARGET_IEEE_FP || TARGET_ZERO_EXTEND_WITH_AND)
3163 : 34 : && GET_MODE (dest) == SImode)
3164 : 34 : zero = force_reg (SImode, const0_rtx);
3165 : 250 : rtx gt = ix86_expand_fp_compare (GT, op0, op1);
3166 : 250 : rtx l0 = op2 == const0_rtx ? gen_label_rtx () : NULL_RTX;
3167 : 250 : rtx l1 = op2 == const0_rtx ? gen_label_rtx () : NULL_RTX;
3168 : 250 : rtx l2 = TARGET_IEEE_FP ? gen_label_rtx () : NULL_RTX;
3169 : 250 : rtx lend = gen_label_rtx ();
3170 : 250 : rtx tmp;
3171 : 250 : rtx_insn *jmp;
3172 : 250 : if (l2)
3173 : : {
3174 : 213 : rtx un = gen_rtx_fmt_ee (UNORDERED, VOIDmode,
3175 : : gen_rtx_REG (CCFPmode, FLAGS_REG), const0_rtx);
3176 : 213 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, un,
3177 : : gen_rtx_LABEL_REF (VOIDmode, l2), pc_rtx);
3178 : 213 : jmp = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
3179 : 213 : add_reg_br_prob_note (jmp, profile_probability:: very_unlikely ());
3180 : : }
3181 : 250 : if (op2 == const0_rtx)
3182 : : {
3183 : 198 : rtx eq = gen_rtx_fmt_ee (UNEQ, VOIDmode,
3184 : : gen_rtx_REG (CCFPmode, FLAGS_REG), const0_rtx);
3185 : 198 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, eq,
3186 : : gen_rtx_LABEL_REF (VOIDmode, l0), pc_rtx);
3187 : 198 : jmp = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
3188 : 198 : add_reg_br_prob_note (jmp, profile_probability::unlikely ());
3189 : 198 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, gt,
3190 : : gen_rtx_LABEL_REF (VOIDmode, l1), pc_rtx);
3191 : 198 : jmp = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
3192 : 198 : add_reg_br_prob_note (jmp, profile_probability::even ());
3193 : 198 : emit_move_insn (dest, constm1_rtx);
3194 : 198 : emit_jump (lend);
3195 : 198 : emit_label (l0);
3196 : 198 : emit_move_insn (dest, const0_rtx);
3197 : 198 : emit_jump (lend);
3198 : 198 : emit_label (l1);
3199 : 198 : emit_move_insn (dest, const1_rtx);
3200 : : }
3201 : : else
3202 : : {
3203 : 52 : rtx lt_tmp = NULL_RTX;
3204 : 52 : if (GET_MODE (dest) != SImode || !TARGET_ZERO_EXTEND_WITH_AND)
3205 : : {
3206 : 52 : lt_tmp = gen_reg_rtx (QImode);
3207 : 52 : ix86_expand_setcc (lt_tmp, UNLT, gen_rtx_REG (CCFPmode, FLAGS_REG),
3208 : : const0_rtx);
3209 : 52 : if (GET_MODE (dest) != QImode)
3210 : : {
3211 : 52 : tmp = gen_reg_rtx (GET_MODE (dest));
3212 : 52 : emit_insn (gen_rtx_SET (tmp,
3213 : : gen_rtx_ZERO_EXTEND (GET_MODE (dest),
3214 : : lt_tmp)));
3215 : 52 : lt_tmp = tmp;
3216 : : }
3217 : : }
3218 : 52 : rtx gt_tmp;
3219 : 52 : if (zero)
3220 : : {
3221 : : /* If TARGET_IEEE_FP and dest has SImode, emit SImode clear
3222 : : before the floating point comparison and use setcc_si_slp
3223 : : pattern to hide it from the combiner, so that it doesn't
3224 : : undo it. Similarly for TARGET_ZERO_EXTEND_WITH_AND, where
3225 : : the ZERO_EXTEND normally emitted would need to be AND
3226 : : with flags clobber. */
3227 : 34 : tmp = ix86_expand_compare (GT, XEXP (gt, 0), const0_rtx);
3228 : 34 : PUT_MODE (tmp, QImode);
3229 : 34 : emit_insn (gen_setcc_si_slp (zero, tmp, zero));
3230 : 34 : gt_tmp = zero;
3231 : : }
3232 : : else
3233 : : {
3234 : 18 : gt_tmp = gen_reg_rtx (QImode);
3235 : 18 : ix86_expand_setcc (gt_tmp, GT, XEXP (gt, 0), const0_rtx);
3236 : 18 : if (GET_MODE (dest) != QImode)
3237 : : {
3238 : 18 : tmp = gen_reg_rtx (GET_MODE (dest));
3239 : 18 : emit_insn (gen_rtx_SET (tmp,
3240 : : gen_rtx_ZERO_EXTEND (GET_MODE (dest),
3241 : : gt_tmp)));
3242 : 18 : gt_tmp = tmp;
3243 : : }
3244 : : }
3245 : 52 : if (lt_tmp)
3246 : : {
3247 : 52 : tmp = expand_simple_binop (GET_MODE (dest), MINUS, gt_tmp, lt_tmp,
3248 : : dest, 0, OPTAB_DIRECT);
3249 : 52 : if (!rtx_equal_p (tmp, dest))
3250 : 0 : emit_move_insn (dest, tmp);
3251 : : }
3252 : : else
3253 : : {
3254 : : /* For TARGET_ZERO_EXTEND_WITH_AND emit sbb directly, as we can't
3255 : : do ZERO_EXTEND without clobbering flags. */
3256 : 0 : tmp = ix86_expand_compare (UNLT, XEXP (gt, 0), const0_rtx);
3257 : 0 : PUT_MODE (tmp, SImode);
3258 : 0 : emit_insn (gen_subsi3_carry (dest, gt_tmp,
3259 : 0 : force_reg (GET_MODE (dest), const0_rtx),
3260 : : XEXP (gt, 0), tmp));
3261 : : }
3262 : : }
3263 : 250 : emit_jump (lend);
3264 : 250 : if (l2)
3265 : : {
3266 : 213 : emit_label (l2);
3267 : 213 : emit_move_insn (dest, op2 == const0_rtx ? const2_rtx : op2);
3268 : : }
3269 : 250 : emit_label (lend);
3270 : 250 : }
3271 : :
3272 : : /* Expand integral op0 <=> op1, i.e.
3273 : : dest = op0 == op1 ? 0 : op0 < op1 ? -1 : 1. */
3274 : :
3275 : : void
3276 : 25 : ix86_expand_int_spaceship (rtx dest, rtx op0, rtx op1, rtx op2)
3277 : : {
3278 : 25 : gcc_assert (INTVAL (op2));
3279 : 25 : rtx zero1 = NULL_RTX, zero2 = NULL_RTX;
3280 : 25 : if (TARGET_ZERO_EXTEND_WITH_AND && GET_MODE (dest) == SImode)
3281 : : {
3282 : 0 : zero1 = force_reg (SImode, const0_rtx);
3283 : 0 : if (INTVAL (op2) != 1)
3284 : 0 : zero2 = force_reg (SImode, const0_rtx);
3285 : : }
3286 : :
3287 : : /* Not using ix86_expand_int_compare here, so that it doesn't swap
3288 : : operands nor optimize CC mode - we need a mode usable for both
3289 : : LT and GT resp. LTU and GTU comparisons with the same unswapped
3290 : : operands. */
3291 : 37 : rtx flags = gen_rtx_REG (INTVAL (op2) != 1 ? CCGCmode : CCmode, FLAGS_REG);
3292 : 25 : rtx tmp = gen_rtx_COMPARE (GET_MODE (flags), op0, op1);
3293 : 25 : emit_insn (gen_rtx_SET (flags, tmp));
3294 : 25 : rtx lt_tmp = NULL_RTX;
3295 : 25 : if (zero2)
3296 : : {
3297 : : /* For TARGET_ZERO_EXTEND_WITH_AND, emit setcc_si_slp to avoid
3298 : : ZERO_EXTEND. */
3299 : 0 : tmp = ix86_expand_compare (LT, flags, const0_rtx);
3300 : 0 : PUT_MODE (tmp, QImode);
3301 : 0 : emit_insn (gen_setcc_si_slp (zero2, tmp, zero2));
3302 : 0 : lt_tmp = zero2;
3303 : : }
3304 : 25 : else if (!zero1)
3305 : : {
3306 : 25 : lt_tmp = gen_reg_rtx (QImode);
3307 : 37 : ix86_expand_setcc (lt_tmp, INTVAL (op2) != 1 ? LT : LTU, flags,
3308 : : const0_rtx);
3309 : 25 : if (GET_MODE (dest) != QImode)
3310 : : {
3311 : 25 : tmp = gen_reg_rtx (GET_MODE (dest));
3312 : 25 : emit_insn (gen_rtx_SET (tmp, gen_rtx_ZERO_EXTEND (GET_MODE (dest),
3313 : : lt_tmp)));
3314 : 25 : lt_tmp = tmp;
3315 : : }
3316 : : }
3317 : 25 : rtx gt_tmp;
3318 : 25 : if (zero1)
3319 : : {
3320 : : /* For TARGET_ZERO_EXTEND_WITH_AND, emit setcc_si_slp to avoid
3321 : : ZERO_EXTEND. */
3322 : 0 : tmp = ix86_expand_compare (INTVAL (op2) != 1 ? GT : GTU, flags,
3323 : : const0_rtx);
3324 : 0 : PUT_MODE (tmp, QImode);
3325 : 0 : emit_insn (gen_setcc_si_slp (zero1, tmp, zero1));
3326 : 0 : gt_tmp = zero1;
3327 : : }
3328 : : else
3329 : : {
3330 : 25 : gt_tmp = gen_reg_rtx (QImode);
3331 : 37 : ix86_expand_setcc (gt_tmp, INTVAL (op2) != 1 ? GT : GTU, flags,
3332 : : const0_rtx);
3333 : 25 : if (GET_MODE (dest) != QImode)
3334 : : {
3335 : 25 : tmp = gen_reg_rtx (GET_MODE (dest));
3336 : 25 : emit_insn (gen_rtx_SET (tmp, gen_rtx_ZERO_EXTEND (GET_MODE (dest),
3337 : : gt_tmp)));
3338 : 25 : gt_tmp = tmp;
3339 : : }
3340 : : }
3341 : 25 : if (lt_tmp)
3342 : : {
3343 : 25 : tmp = expand_simple_binop (GET_MODE (dest), MINUS, gt_tmp, lt_tmp, dest,
3344 : : 0, OPTAB_DIRECT);
3345 : 25 : if (!rtx_equal_p (tmp, dest))
3346 : 0 : emit_move_insn (dest, tmp);
3347 : : }
3348 : : else
3349 : : {
3350 : : /* For TARGET_ZERO_EXTEND_WITH_AND emit sbb directly, as we can't
3351 : : do ZERO_EXTEND without clobbering flags. */
3352 : 0 : tmp = ix86_expand_compare (LTU, flags, const0_rtx);
3353 : 0 : PUT_MODE (tmp, SImode);
3354 : 0 : emit_insn (gen_subsi3_carry (dest, gt_tmp,
3355 : 0 : force_reg (GET_MODE (dest), const0_rtx),
3356 : : flags, tmp));
3357 : : }
3358 : 25 : }
3359 : :
3360 : : /* Expand comparison setting or clearing carry flag. Return true when
3361 : : successful and set pop for the operation. */
3362 : : static bool
3363 : 32157 : ix86_expand_carry_flag_compare (enum rtx_code code, rtx op0, rtx op1, rtx *pop)
3364 : : {
3365 : 64314 : machine_mode mode
3366 : 32157 : = GET_MODE (op0) != VOIDmode ? GET_MODE (op0) : GET_MODE (op1);
3367 : :
3368 : : /* Do not handle double-mode compares that go through special path. */
3369 : 34224 : if (mode == (TARGET_64BIT ? TImode : DImode))
3370 : : return false;
3371 : :
3372 : 32149 : if (SCALAR_FLOAT_MODE_P (mode))
3373 : : {
3374 : 3573 : rtx compare_op;
3375 : 3573 : rtx_insn *compare_seq;
3376 : :
3377 : 3573 : gcc_assert (!DECIMAL_FLOAT_MODE_P (mode));
3378 : :
3379 : : /* Shortcut: following common codes never translate
3380 : : into carry flag compares. */
3381 : 3573 : if (code == EQ || code == NE || code == UNEQ || code == LTGT
3382 : : || code == ORDERED || code == UNORDERED)
3383 : : return false;
3384 : :
3385 : : /* These comparisons require zero flag; swap operands so they won't. */
3386 : : if ((code == GT || code == UNLE || code == LE || code == UNGT)
3387 : 3500 : && !TARGET_IEEE_FP)
3388 : : {
3389 : 2 : std::swap (op0, op1);
3390 : 2 : code = swap_condition (code);
3391 : : }
3392 : :
3393 : : /* Try to expand the comparison and verify that we end up with
3394 : : carry flag based comparison. This fails to be true only when
3395 : : we decide to expand comparison using arithmetic that is not
3396 : : too common scenario. */
3397 : 3571 : start_sequence ();
3398 : 3571 : compare_op = ix86_expand_fp_compare (code, op0, op1);
3399 : 3571 : compare_seq = end_sequence ();
3400 : :
3401 : 3571 : if (GET_MODE (XEXP (compare_op, 0)) == CCFPmode)
3402 : 3571 : code = ix86_fp_compare_code_to_integer (GET_CODE (compare_op));
3403 : : else
3404 : 0 : code = GET_CODE (compare_op);
3405 : :
3406 : 3571 : if (code != LTU && code != GEU)
3407 : : return false;
3408 : :
3409 : 71 : emit_insn (compare_seq);
3410 : 71 : *pop = compare_op;
3411 : 71 : return true;
3412 : : }
3413 : :
3414 : 28576 : if (!INTEGRAL_MODE_P (mode))
3415 : : return false;
3416 : :
3417 : 28500 : switch (code)
3418 : : {
3419 : : case LTU:
3420 : : case GEU:
3421 : : break;
3422 : :
3423 : : /* Convert a==0 into (unsigned)a<1. */
3424 : 24881 : case EQ:
3425 : 24881 : case NE:
3426 : 24881 : if (op1 != const0_rtx)
3427 : : return false;
3428 : 9033 : op1 = const1_rtx;
3429 : 9033 : code = (code == EQ ? LTU : GEU);
3430 : : break;
3431 : :
3432 : : /* Convert a>b into b<a or a>=b-1. */
3433 : 833 : case GTU:
3434 : 833 : case LEU:
3435 : 833 : if (CONST_INT_P (op1))
3436 : : {
3437 : 791 : op1 = gen_int_mode (INTVAL (op1) + 1, GET_MODE (op0));
3438 : : /* Bail out on overflow. We still can swap operands but that
3439 : : would force loading of the constant into register. */
3440 : 791 : if (op1 == const0_rtx
3441 : 791 : || !x86_64_immediate_operand (op1, GET_MODE (op1)))
3442 : 0 : return false;
3443 : 791 : code = (code == GTU ? GEU : LTU);
3444 : : }
3445 : : else
3446 : : {
3447 : 42 : std::swap (op0, op1);
3448 : 42 : code = (code == GTU ? LTU : GEU);
3449 : : }
3450 : : break;
3451 : :
3452 : : /* Convert a>=0 into (unsigned)a<0x80000000. */
3453 : 1570 : case LT:
3454 : 1570 : case GE:
3455 : 1570 : if (mode == DImode || op1 != const0_rtx)
3456 : : return false;
3457 : 198 : op1 = gen_int_mode (1 << (GET_MODE_BITSIZE (mode) - 1), mode);
3458 : 99 : code = (code == LT ? GEU : LTU);
3459 : : break;
3460 : 621 : case LE:
3461 : 621 : case GT:
3462 : 621 : if (mode == DImode || op1 != constm1_rtx)
3463 : : return false;
3464 : 0 : op1 = gen_int_mode (1 << (GET_MODE_BITSIZE (mode) - 1), mode);
3465 : 0 : code = (code == LE ? GEU : LTU);
3466 : : break;
3467 : :
3468 : : default:
3469 : : return false;
3470 : : }
3471 : : /* Swapping operands may cause constant to appear as first operand. */
3472 : 10560 : if (!nonimmediate_operand (op0, VOIDmode))
3473 : : {
3474 : 0 : if (!can_create_pseudo_p ())
3475 : : return false;
3476 : 0 : op0 = force_reg (mode, op0);
3477 : : }
3478 : 10560 : *pop = ix86_expand_compare (code, op0, op1);
3479 : 10560 : gcc_assert (GET_CODE (*pop) == LTU || GET_CODE (*pop) == GEU);
3480 : : return true;
3481 : : }
3482 : :
3483 : : /* Expand conditional increment or decrement using adb/sbb instructions.
3484 : : The default case using setcc followed by the conditional move can be
3485 : : done by generic code. */
3486 : : bool
3487 : 8053 : ix86_expand_int_addcc (rtx operands[])
3488 : : {
3489 : 8053 : enum rtx_code code = GET_CODE (operands[1]);
3490 : 8053 : rtx flags;
3491 : 8053 : rtx (*insn) (machine_mode, rtx, rtx, rtx, rtx, rtx);
3492 : 8053 : rtx compare_op;
3493 : 8053 : rtx val = const0_rtx;
3494 : 8053 : bool fpcmp = false;
3495 : 8053 : machine_mode mode;
3496 : 8053 : rtx op0 = XEXP (operands[1], 0);
3497 : 8053 : rtx op1 = XEXP (operands[1], 1);
3498 : :
3499 : 8053 : if (operands[3] != const1_rtx
3500 : 3457 : && operands[3] != constm1_rtx)
3501 : : return false;
3502 : 5465 : if (!ix86_expand_carry_flag_compare (code, op0, op1, &compare_op))
3503 : : return false;
3504 : 1235 : code = GET_CODE (compare_op);
3505 : :
3506 : 1235 : flags = XEXP (compare_op, 0);
3507 : :
3508 : 1235 : if (GET_MODE (flags) == CCFPmode)
3509 : : {
3510 : 4 : fpcmp = true;
3511 : 4 : code = ix86_fp_compare_code_to_integer (code);
3512 : : }
3513 : :
3514 : 1235 : if (code != LTU)
3515 : : {
3516 : 749 : val = constm1_rtx;
3517 : 749 : if (fpcmp)
3518 : 4 : PUT_CODE (compare_op,
3519 : : reverse_condition_maybe_unordered
3520 : : (GET_CODE (compare_op)));
3521 : : else
3522 : 745 : PUT_CODE (compare_op, reverse_condition (GET_CODE (compare_op)));
3523 : : }
3524 : :
3525 : 1235 : mode = GET_MODE (operands[0]);
3526 : :
3527 : : /* Construct either adc or sbb insn. */
3528 : 1235 : if ((code == LTU) == (operands[3] == constm1_rtx))
3529 : : insn = gen_sub3_carry;
3530 : : else
3531 : 463 : insn = gen_add3_carry;
3532 : :
3533 : 1235 : emit_insn (insn (mode, operands[0], operands[2], val, flags, compare_op));
3534 : :
3535 : 1235 : return true;
3536 : : }
3537 : :
3538 : : bool
3539 : 524976 : ix86_expand_int_movcc (rtx operands[])
3540 : : {
3541 : 524976 : enum rtx_code code = GET_CODE (operands[1]), compare_code;
3542 : 524976 : rtx_insn *compare_seq;
3543 : 524976 : rtx compare_op;
3544 : 524976 : machine_mode mode = GET_MODE (operands[0]);
3545 : 524976 : bool sign_bit_compare_p = false;
3546 : 524976 : bool negate_cc_compare_p = false;
3547 : 524976 : rtx op0 = XEXP (operands[1], 0);
3548 : 524976 : rtx op1 = XEXP (operands[1], 1);
3549 : 524976 : rtx op2 = operands[2];
3550 : 524976 : rtx op3 = operands[3];
3551 : :
3552 : 524976 : if (GET_MODE (op0) == TImode
3553 : 509424 : || (GET_MODE (op0) == DImode
3554 : 111018 : && !TARGET_64BIT))
3555 : : return false;
3556 : :
3557 : 508304 : if (GET_MODE (op0) == BFmode
3558 : 508304 : && !ix86_fp_comparison_operator (operands[1], VOIDmode))
3559 : : return false;
3560 : :
3561 : 508304 : start_sequence ();
3562 : 508304 : compare_op = ix86_expand_compare (code, op0, op1);
3563 : 508304 : compare_seq = end_sequence ();
3564 : :
3565 : 508304 : compare_code = GET_CODE (compare_op);
3566 : :
3567 : 508304 : if ((op1 == const0_rtx && (code == GE || code == LT))
3568 : 452533 : || (op1 == constm1_rtx && (code == GT || code == LE)))
3569 : : sign_bit_compare_p = true;
3570 : :
3571 : : /* op0 == op1 ? op0 : op3 is equivalent to op0 == op1 ? op1 : op3,
3572 : : but if op1 is a constant, the latter form allows more optimizations,
3573 : : either through the last 2 ops being constant handling, or the one
3574 : : constant and one variable cases. On the other side, for cmov the
3575 : : former might be better as we don't need to load the constant into
3576 : : another register. */
3577 : 452533 : if (code == EQ && CONST_INT_P (op1) && rtx_equal_p (op0, op2))
3578 : : op2 = op1;
3579 : : /* Similarly for op0 != op1 ? op2 : op0 and op0 != op1 ? op2 : op1. */
3580 : 507783 : else if (code == NE && CONST_INT_P (op1) && rtx_equal_p (op0, op3))
3581 : : op3 = op1;
3582 : :
3583 : : /* Don't attempt mode expansion here -- if we had to expand 5 or 6
3584 : : HImode insns, we'd be swallowed in word prefix ops. */
3585 : :
3586 : 4708 : if ((mode != HImode || TARGET_FAST_PREFIX)
3587 : 540035 : && (mode != (TARGET_64BIT ? TImode : DImode))
3588 : 508304 : && CONST_INT_P (op2)
3589 : 543648 : && CONST_INT_P (op3))
3590 : : {
3591 : 27696 : rtx out = operands[0];
3592 : 27696 : HOST_WIDE_INT ct = INTVAL (op2);
3593 : 27696 : HOST_WIDE_INT cf = INTVAL (op3);
3594 : 27696 : HOST_WIDE_INT diff;
3595 : :
3596 : 27696 : if ((mode == SImode
3597 : 15364 : || (TARGET_64BIT && mode == DImode))
3598 : 18569 : && (GET_MODE (op0) == SImode
3599 : 14372 : || (TARGET_64BIT && GET_MODE (op0) == DImode)))
3600 : : {
3601 : : /* Special case x != 0 ? -1 : y. */
3602 : 11642 : if (code == NE && op1 == const0_rtx && ct == -1)
3603 : : {
3604 : : negate_cc_compare_p = true;
3605 : : std::swap (ct, cf);
3606 : : code = EQ;
3607 : : }
3608 : 11499 : else if (code == EQ && op1 == const0_rtx && cf == -1)
3609 : 27696 : negate_cc_compare_p = true;
3610 : : }
3611 : :
3612 : 27696 : diff = (unsigned HOST_WIDE_INT) ct - cf;
3613 : : /* Make sure we can represent the difference between the two values. */
3614 : 27696 : if ((diff > 0) != ((cf < 0) != (ct < 0) ? cf < 0 : cf < ct))
3615 : 524976 : return false;
3616 : :
3617 : : /* Sign bit compares are better done using shifts than we do by using
3618 : : sbb. */
3619 : 27640 : if (sign_bit_compare_p
3620 : 27640 : || negate_cc_compare_p
3621 : 27640 : || ix86_expand_carry_flag_compare (code, op0, op1, &compare_op))
3622 : : {
3623 : : /* Detect overlap between destination and compare sources. */
3624 : 10344 : rtx tmp = out;
3625 : :
3626 : 10344 : if (negate_cc_compare_p)
3627 : : {
3628 : 319 : if (GET_MODE (op0) == DImode)
3629 : 125 : emit_insn (gen_x86_negdi_ccc (gen_reg_rtx (DImode), op0));
3630 : : else
3631 : 194 : emit_insn (gen_x86_negsi_ccc (gen_reg_rtx (SImode),
3632 : 194 : gen_lowpart (SImode, op0)));
3633 : :
3634 : 319 : tmp = gen_reg_rtx (mode);
3635 : 319 : if (mode == DImode)
3636 : 130 : emit_insn (gen_x86_movdicc_0_m1_neg (tmp));
3637 : : else
3638 : 189 : emit_insn (gen_x86_movsicc_0_m1_neg (gen_lowpart (SImode,
3639 : : tmp)));
3640 : : }
3641 : 10025 : else if (!sign_bit_compare_p)
3642 : : {
3643 : 9396 : rtx flags;
3644 : 9396 : bool fpcmp = false;
3645 : :
3646 : 9396 : compare_code = GET_CODE (compare_op);
3647 : :
3648 : 9396 : flags = XEXP (compare_op, 0);
3649 : :
3650 : 9396 : if (GET_MODE (flags) == CCFPmode)
3651 : : {
3652 : 67 : fpcmp = true;
3653 : 67 : compare_code
3654 : 67 : = ix86_fp_compare_code_to_integer (compare_code);
3655 : : }
3656 : :
3657 : : /* To simplify rest of code, restrict to the GEU case. */
3658 : 9396 : if (compare_code == LTU)
3659 : : {
3660 : 4934 : std::swap (ct, cf);
3661 : 4934 : compare_code = reverse_condition (compare_code);
3662 : 4934 : code = reverse_condition (code);
3663 : : }
3664 : : else
3665 : : {
3666 : 4462 : if (fpcmp)
3667 : 67 : PUT_CODE (compare_op,
3668 : : reverse_condition_maybe_unordered
3669 : : (GET_CODE (compare_op)));
3670 : : else
3671 : 4395 : PUT_CODE (compare_op,
3672 : : reverse_condition (GET_CODE (compare_op)));
3673 : : }
3674 : :
3675 : 9396 : diff = (unsigned HOST_WIDE_INT) ct - cf;
3676 : : /* Make sure we can represent the difference
3677 : : between the two values. */
3678 : 9396 : if ((diff > 0) != ((cf < 0) != (ct < 0) ? cf < 0 : cf < ct))
3679 : : return false;
3680 : :
3681 : 9395 : if (reg_overlap_mentioned_p (out, compare_op))
3682 : 0 : tmp = gen_reg_rtx (mode);
3683 : :
3684 : 9395 : if (mode == DImode)
3685 : 1801 : emit_insn (gen_x86_movdicc_0_m1 (tmp, flags, compare_op));
3686 : : else
3687 : 7594 : emit_insn (gen_x86_movsicc_0_m1 (gen_lowpart (SImode, tmp),
3688 : : flags, compare_op));
3689 : : }
3690 : : else
3691 : : {
3692 : 629 : if (code == GT || code == GE)
3693 : 175 : code = reverse_condition (code);
3694 : : else
3695 : : {
3696 : 454 : std::swap (ct, cf);
3697 : :
3698 : 454 : diff = (unsigned HOST_WIDE_INT) ct - cf;
3699 : : /* Make sure we can represent the difference
3700 : : between the two values. */
3701 : 454 : if ((diff > 0) != ((cf < 0) != (ct < 0) ? cf < 0 : cf < ct))
3702 : : return false;
3703 : : }
3704 : 626 : tmp = emit_store_flag (tmp, code, op0, op1, VOIDmode, 0, -1);
3705 : : }
3706 : :
3707 : 10340 : if (diff == 1)
3708 : : {
3709 : : /*
3710 : : * cmpl op0,op1
3711 : : * sbbl dest,dest
3712 : : * [addl dest, ct]
3713 : : *
3714 : : * Size 5 - 8.
3715 : : */
3716 : 1160 : if (ct)
3717 : 980 : tmp = expand_simple_binop (mode, PLUS,
3718 : : tmp, GEN_INT (ct),
3719 : : copy_rtx (tmp), 1, OPTAB_DIRECT);
3720 : : }
3721 : 9180 : else if (cf == -1)
3722 : : {
3723 : : /*
3724 : : * cmpl op0,op1
3725 : : * sbbl dest,dest
3726 : : * orl $ct, dest
3727 : : *
3728 : : * Size 8.
3729 : : */
3730 : 722 : tmp = expand_simple_binop (mode, IOR,
3731 : : tmp, GEN_INT (ct),
3732 : : copy_rtx (tmp), 1, OPTAB_DIRECT);
3733 : : }
3734 : 8458 : else if (diff == -1 && ct)
3735 : : {
3736 : : /*
3737 : : * cmpl op0,op1
3738 : : * sbbl dest,dest
3739 : : * notl dest
3740 : : * [addl dest, cf]
3741 : : *
3742 : : * Size 8 - 11.
3743 : : */
3744 : 882 : tmp = expand_simple_unop (mode, NOT, tmp, copy_rtx (tmp), 1);
3745 : 882 : if (cf)
3746 : 866 : tmp = expand_simple_binop (mode, PLUS,
3747 : : copy_rtx (tmp), GEN_INT (cf),
3748 : : copy_rtx (tmp), 1, OPTAB_DIRECT);
3749 : : }
3750 : : else
3751 : : {
3752 : : /*
3753 : : * cmpl op0,op1
3754 : : * sbbl dest,dest
3755 : : * [notl dest]
3756 : : * andl cf - ct, dest
3757 : : * [addl dest, ct]
3758 : : *
3759 : : * Size 8 - 11.
3760 : : */
3761 : :
3762 : 7576 : if (cf == 0)
3763 : : {
3764 : 871 : cf = ct;
3765 : 871 : ct = 0;
3766 : 871 : tmp = expand_simple_unop (mode, NOT, tmp, copy_rtx (tmp), 1);
3767 : : }
3768 : :
3769 : 7576 : HOST_WIDE_INT ival = (unsigned HOST_WIDE_INT) cf - ct;
3770 : : /* Make sure we can represent the difference
3771 : : between the two values. */
3772 : 7576 : if ((ival > 0) != ((ct < 0) != (cf < 0) ? ct < 0 : ct < cf))
3773 : 16732 : return false;
3774 : :
3775 : 7576 : tmp = expand_simple_binop (mode, AND,
3776 : : copy_rtx (tmp),
3777 : 7576 : gen_int_mode (ival, mode),
3778 : : copy_rtx (tmp), 1, OPTAB_DIRECT);
3779 : 7576 : if (ct)
3780 : 5861 : tmp = expand_simple_binop (mode, PLUS,
3781 : : copy_rtx (tmp), GEN_INT (ct),
3782 : : copy_rtx (tmp), 1, OPTAB_DIRECT);
3783 : : }
3784 : :
3785 : 10340 : if (!rtx_equal_p (tmp, out))
3786 : 412 : emit_move_insn (copy_rtx (out), copy_rtx (tmp));
3787 : :
3788 : 10340 : return true;
3789 : : }
3790 : :
3791 : 17296 : if (diff < 0)
3792 : : {
3793 : 6841 : machine_mode cmp_mode = GET_MODE (op0);
3794 : 6841 : enum rtx_code new_code;
3795 : :
3796 : 6841 : if (SCALAR_FLOAT_MODE_P (cmp_mode))
3797 : : {
3798 : 41 : gcc_assert (!DECIMAL_FLOAT_MODE_P (cmp_mode));
3799 : :
3800 : : /* We may be reversing a non-trapping
3801 : : comparison to a trapping comparison. */
3802 : 78 : if (HONOR_NANS (cmp_mode) && flag_trapping_math
3803 : 29 : && code != EQ && code != NE
3804 : 70 : && code != ORDERED && code != UNORDERED)
3805 : : new_code = UNKNOWN;
3806 : : else
3807 : 12 : new_code = reverse_condition_maybe_unordered (code);
3808 : : }
3809 : : else
3810 : 6800 : new_code = ix86_reverse_condition (code, cmp_mode);
3811 : 6812 : if (new_code != UNKNOWN)
3812 : : {
3813 : 6812 : std::swap (ct, cf);
3814 : :
3815 : 6812 : diff = (unsigned HOST_WIDE_INT) ct - cf;
3816 : : /* Make sure we can represent the difference
3817 : : between the two values. */
3818 : 6812 : if ((diff > 0) != ((cf < 0) != (ct < 0) ? cf < 0 : cf < ct))
3819 : : return false;
3820 : :
3821 : : code = new_code;
3822 : : }
3823 : : }
3824 : :
3825 : 17296 : compare_code = UNKNOWN;
3826 : 17296 : if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT
3827 : 13868 : && CONST_INT_P (op1))
3828 : : {
3829 : 9053 : if (op1 == const0_rtx
3830 : 93 : && (code == LT || code == GE))
3831 : : compare_code = code;
3832 : 9053 : else if (op1 == constm1_rtx)
3833 : : {
3834 : 286 : if (code == LE)
3835 : : compare_code = LT;
3836 : 286 : else if (code == GT)
3837 : : compare_code = GE;
3838 : : }
3839 : : }
3840 : :
3841 : : /* Optimize dest = (op0 < 0) ? -1 : cf. */
3842 : : if (compare_code != UNKNOWN
3843 : 0 : && GET_MODE (op0) == GET_MODE (out)
3844 : 0 : && (cf == -1 || ct == -1))
3845 : : {
3846 : : /* If lea code below could be used, only optimize
3847 : : if it results in a 2 insn sequence. */
3848 : :
3849 : 0 : if (! (diff == 1 || diff == 2 || diff == 4 || diff == 8
3850 : 0 : || diff == 3 || diff == 5 || diff == 9)
3851 : 0 : || (compare_code == LT && ct == -1)
3852 : 0 : || (compare_code == GE && cf == -1))
3853 : : {
3854 : : /*
3855 : : * notl op1 (if necessary)
3856 : : * sarl $31, op1
3857 : : * orl cf, op1
3858 : : */
3859 : 0 : if (ct != -1)
3860 : : {
3861 : 0 : cf = ct;
3862 : 0 : ct = -1;
3863 : 0 : code = reverse_condition (code);
3864 : : }
3865 : :
3866 : 0 : out = emit_store_flag (out, code, op0, op1, VOIDmode, 0, -1);
3867 : :
3868 : 0 : out = expand_simple_binop (mode, IOR,
3869 : : out, GEN_INT (cf),
3870 : : out, 1, OPTAB_DIRECT);
3871 : 0 : if (out != operands[0])
3872 : 0 : emit_move_insn (operands[0], out);
3873 : :
3874 : 0 : return true;
3875 : : }
3876 : : }
3877 : :
3878 : :
3879 : 26690 : if ((diff == 1 || diff == 2 || diff == 4 || diff == 8
3880 : 9394 : || diff == 3 || diff == 5 || diff == 9)
3881 : 8167 : && ((mode != QImode && mode != HImode) || !TARGET_PARTIAL_REG_STALL)
3882 : 25463 : && (mode != DImode
3883 : 3567 : || x86_64_immediate_operand (GEN_INT (cf), VOIDmode)))
3884 : : {
3885 : : /*
3886 : : * xorl dest,dest
3887 : : * cmpl op1,op2
3888 : : * setcc dest
3889 : : * lea cf(dest*(ct-cf)),dest
3890 : : *
3891 : : * Size 14.
3892 : : *
3893 : : * This also catches the degenerate setcc-only case.
3894 : : */
3895 : :
3896 : 8167 : rtx tmp;
3897 : 8167 : int nops;
3898 : :
3899 : 8167 : out = emit_store_flag (out, code, op0, op1, VOIDmode, 0, 1);
3900 : :
3901 : 8167 : nops = 0;
3902 : : /* On x86_64 the lea instruction operates on Pmode, so we need
3903 : : to get arithmetics done in proper mode to match. */
3904 : 8167 : if (diff == 1)
3905 : 7132 : tmp = copy_rtx (out);
3906 : : else
3907 : : {
3908 : 1035 : rtx out1;
3909 : 1035 : out1 = copy_rtx (out);
3910 : 1035 : tmp = gen_rtx_MULT (mode, out1, GEN_INT (diff & ~1));
3911 : 1035 : nops++;
3912 : 1035 : if (diff & 1)
3913 : : {
3914 : 229 : tmp = gen_rtx_PLUS (mode, tmp, out1);
3915 : 229 : nops++;
3916 : : }
3917 : : }
3918 : 8167 : if (cf != 0)
3919 : : {
3920 : 7339 : tmp = plus_constant (mode, tmp, cf);
3921 : 7339 : nops++;
3922 : : }
3923 : 8167 : if (!rtx_equal_p (tmp, out))
3924 : : {
3925 : 7485 : if (nops == 1)
3926 : 6456 : out = force_operand (tmp, copy_rtx (out));
3927 : : else
3928 : 1029 : emit_insn (gen_rtx_SET (copy_rtx (out), copy_rtx (tmp)));
3929 : : }
3930 : 8167 : if (!rtx_equal_p (out, operands[0]))
3931 : 785 : emit_move_insn (operands[0], copy_rtx (out));
3932 : :
3933 : 8167 : return true;
3934 : : }
3935 : :
3936 : : /*
3937 : : * General case: Jumpful:
3938 : : * xorl dest,dest cmpl op1, op2
3939 : : * cmpl op1, op2 movl ct, dest
3940 : : * setcc dest jcc 1f
3941 : : * decl dest movl cf, dest
3942 : : * andl (cf-ct),dest 1:
3943 : : * addl ct,dest
3944 : : *
3945 : : * Size 20. Size 14.
3946 : : *
3947 : : * This is reasonably steep, but branch mispredict costs are
3948 : : * high on modern cpus, so consider failing only if optimizing
3949 : : * for space.
3950 : : */
3951 : :
3952 : 9129 : if ((!TARGET_CMOVE || (mode == QImode && TARGET_PARTIAL_REG_STALL))
3953 : 9129 : && BRANCH_COST (optimize_insn_for_speed_p (),
3954 : : false) >= 2)
3955 : : {
3956 : 0 : if (cf == 0)
3957 : : {
3958 : 0 : machine_mode cmp_mode = GET_MODE (op0);
3959 : 0 : enum rtx_code new_code;
3960 : :
3961 : 0 : if (SCALAR_FLOAT_MODE_P (cmp_mode))
3962 : : {
3963 : 0 : gcc_assert (!DECIMAL_FLOAT_MODE_P (cmp_mode));
3964 : :
3965 : : /* We may be reversing a non-trapping
3966 : : comparison to a trapping comparison. */
3967 : 0 : if (HONOR_NANS (cmp_mode) && flag_trapping_math
3968 : 0 : && code != EQ && code != NE
3969 : 0 : && code != ORDERED && code != UNORDERED)
3970 : : new_code = UNKNOWN;
3971 : : else
3972 : 0 : new_code = reverse_condition_maybe_unordered (code);
3973 : :
3974 : : }
3975 : : else
3976 : : {
3977 : 0 : new_code = ix86_reverse_condition (code, cmp_mode);
3978 : 0 : if (compare_code != UNKNOWN && new_code != UNKNOWN)
3979 : 0 : compare_code = reverse_condition (compare_code);
3980 : : }
3981 : :
3982 : 0 : if (new_code != UNKNOWN)
3983 : : {
3984 : 0 : cf = ct;
3985 : 0 : ct = 0;
3986 : 0 : code = new_code;
3987 : : }
3988 : : }
3989 : :
3990 : 0 : if (compare_code != UNKNOWN)
3991 : : {
3992 : : /* notl op1 (if needed)
3993 : : sarl $31, op1
3994 : : andl (cf-ct), op1
3995 : : addl ct, op1
3996 : :
3997 : : For x < 0 (resp. x <= -1) there will be no notl,
3998 : : so if possible swap the constants to get rid of the
3999 : : complement.
4000 : : True/false will be -1/0 while code below (store flag
4001 : : followed by decrement) is 0/-1, so the constants need
4002 : : to be exchanged once more. */
4003 : :
4004 : 0 : if (compare_code == GE || !cf)
4005 : : {
4006 : 0 : code = reverse_condition (code);
4007 : 0 : compare_code = LT;
4008 : : }
4009 : : else
4010 : : std::swap (ct, cf);
4011 : :
4012 : 0 : out = emit_store_flag (out, code, op0, op1, VOIDmode, 0, -1);
4013 : : }
4014 : : else
4015 : : {
4016 : 0 : out = emit_store_flag (out, code, op0, op1, VOIDmode, 0, 1);
4017 : :
4018 : 0 : out = expand_simple_binop (mode, PLUS, copy_rtx (out),
4019 : : constm1_rtx,
4020 : : copy_rtx (out), 1, OPTAB_DIRECT);
4021 : : }
4022 : :
4023 : 0 : HOST_WIDE_INT ival = (unsigned HOST_WIDE_INT) cf - ct;
4024 : : /* Make sure we can represent the difference
4025 : : between the two values. */
4026 : 0 : if ((ival > 0) != ((ct < 0) != (cf < 0) ? ct < 0 : ct < cf))
4027 : : return false;
4028 : :
4029 : 0 : out = expand_simple_binop (mode, AND, copy_rtx (out),
4030 : 0 : gen_int_mode (ival, mode),
4031 : : copy_rtx (out), 1, OPTAB_DIRECT);
4032 : 0 : if (ct)
4033 : 0 : out = expand_simple_binop (mode, PLUS, copy_rtx (out), GEN_INT (ct),
4034 : : copy_rtx (out), 1, OPTAB_DIRECT);
4035 : 0 : if (!rtx_equal_p (out, operands[0]))
4036 : 0 : emit_move_insn (operands[0], copy_rtx (out));
4037 : :
4038 : 0 : return true;
4039 : : }
4040 : : }
4041 : :
4042 : 489737 : if (!TARGET_CMOVE || (mode == QImode && TARGET_PARTIAL_REG_STALL))
4043 : : {
4044 : : /* Try a few things more with specific constants and a variable. */
4045 : :
4046 : 0 : optab op;
4047 : 0 : rtx var, orig_out, out, tmp;
4048 : :
4049 : 0 : if (BRANCH_COST (optimize_insn_for_speed_p (), false) <= 2)
4050 : : return false;
4051 : :
4052 : 0 : operands[2] = op2;
4053 : 0 : operands[3] = op3;
4054 : :
4055 : : /* If one of the two operands is an interesting constant, load a
4056 : : constant with the above and mask it in with a logical operation. */
4057 : :
4058 : 0 : if (CONST_INT_P (operands[2]))
4059 : : {
4060 : 0 : var = operands[3];
4061 : 0 : if (INTVAL (operands[2]) == 0 && operands[3] != constm1_rtx)
4062 : 0 : operands[3] = constm1_rtx, op = and_optab;
4063 : 0 : else if (INTVAL (operands[2]) == -1 && operands[3] != const0_rtx)
4064 : 0 : operands[3] = const0_rtx, op = ior_optab;
4065 : : else
4066 : : return false;
4067 : : }
4068 : 0 : else if (CONST_INT_P (operands[3]))
4069 : : {
4070 : 0 : var = operands[2];
4071 : 0 : if (INTVAL (operands[3]) == 0 && operands[2] != constm1_rtx)
4072 : : {
4073 : : /* For smin (x, 0), expand as "x < 0 ? x : 0" instead of
4074 : : "x <= 0 ? x : 0" to enable sign_bit_compare_p. */
4075 : 0 : if (code == LE && op1 == const0_rtx && rtx_equal_p (op0, var))
4076 : 0 : operands[1] = simplify_gen_relational (LT, VOIDmode,
4077 : 0 : GET_MODE (op0),
4078 : : op0, const0_rtx);
4079 : :
4080 : 0 : operands[2] = constm1_rtx;
4081 : 0 : op = and_optab;
4082 : : }
4083 : 0 : else if (INTVAL (operands[3]) == -1 && operands[3] != const0_rtx)
4084 : 0 : operands[2] = const0_rtx, op = ior_optab;
4085 : : else
4086 : : return false;
4087 : : }
4088 : : else
4089 : : return false;
4090 : :
4091 : 0 : orig_out = operands[0];
4092 : 0 : tmp = gen_reg_rtx (mode);
4093 : 0 : operands[0] = tmp;
4094 : :
4095 : : /* Recurse to get the constant loaded. */
4096 : 0 : if (!ix86_expand_int_movcc (operands))
4097 : : return false;
4098 : :
4099 : : /* Mask in the interesting variable. */
4100 : 0 : out = expand_binop (mode, op, var, tmp, orig_out, 0,
4101 : : OPTAB_WIDEN);
4102 : 0 : if (!rtx_equal_p (out, orig_out))
4103 : 0 : emit_move_insn (copy_rtx (orig_out), copy_rtx (out));
4104 : :
4105 : 0 : return true;
4106 : : }
4107 : :
4108 : : /*
4109 : : * For comparison with above,
4110 : : *
4111 : : * movl cf,dest
4112 : : * movl ct,tmp
4113 : : * cmpl op1,op2
4114 : : * cmovcc tmp,dest
4115 : : *
4116 : : * Size 15.
4117 : : */
4118 : :
4119 : 489737 : if (! nonimmediate_operand (operands[2], mode))
4120 : 27633 : operands[2] = force_reg (mode, operands[2]);
4121 : 489737 : if (! nonimmediate_operand (operands[3], mode))
4122 : 213473 : operands[3] = force_reg (mode, operands[3]);
4123 : :
4124 : 489737 : if (! register_operand (operands[2], VOIDmode)
4125 : 489737 : && (mode == QImode
4126 : 1100 : || ! register_operand (operands[3], VOIDmode)))
4127 : 1564 : operands[2] = force_reg (mode, operands[2]);
4128 : :
4129 : 489737 : if (mode == QImode
4130 : 489737 : && ! register_operand (operands[3], VOIDmode))
4131 : 592 : operands[3] = force_reg (mode, operands[3]);
4132 : :
4133 : 489737 : emit_insn (compare_seq);
4134 : 489737 : emit_insn (gen_rtx_SET (operands[0],
4135 : : gen_rtx_IF_THEN_ELSE (mode,
4136 : : compare_op, operands[2],
4137 : : operands[3])));
4138 : 489737 : return true;
4139 : : }
4140 : :
4141 : : /* Detect conditional moves that exactly match min/max operational
4142 : : semantics. Note that this is IEEE safe, as long as we don't
4143 : : interchange the operands.
4144 : :
4145 : : Returns FALSE if this conditional move doesn't match a MIN/MAX,
4146 : : and TRUE if the operation is successful and instructions are emitted. */
4147 : :
4148 : : static bool
4149 : 10821 : ix86_expand_sse_fp_minmax (rtx dest, enum rtx_code code, rtx cmp_op0,
4150 : : rtx cmp_op1, rtx if_true, rtx if_false)
4151 : : {
4152 : 10821 : machine_mode mode;
4153 : 10821 : bool is_min;
4154 : 10821 : rtx tmp;
4155 : :
4156 : 10821 : if (code == LT)
4157 : : ;
4158 : 3149 : else if (code == UNGE)
4159 : : std::swap (if_true, if_false);
4160 : : else
4161 : : return false;
4162 : :
4163 : 9850 : if (rtx_equal_p (cmp_op0, if_true) && rtx_equal_p (cmp_op1, if_false))
4164 : : is_min = true;
4165 : 4802 : else if (rtx_equal_p (cmp_op1, if_true) && rtx_equal_p (cmp_op0, if_false))
4166 : : is_min = false;
4167 : : else
4168 : 1075 : return false;
4169 : :
4170 : 8775 : mode = GET_MODE (dest);
4171 : 8775 : if (immediate_operand (if_false, mode))
4172 : 8 : if_false = force_reg (mode, if_false);
4173 : 8775 : if (immediate_operand (if_true, mode))
4174 : 0 : if_true = force_reg (mode, if_true);
4175 : :
4176 : : /* We want to check HONOR_NANS and HONOR_SIGNED_ZEROS here,
4177 : : but MODE may be a vector mode and thus not appropriate. */
4178 : 8775 : if (!flag_finite_math_only || flag_signed_zeros)
4179 : : {
4180 : 8775 : int u = is_min ? UNSPEC_IEEE_MIN : UNSPEC_IEEE_MAX;
4181 : 8775 : rtvec v;
4182 : :
4183 : 8775 : if_true = force_reg (mode, if_true);
4184 : 8775 : v = gen_rtvec (2, if_true, if_false);
4185 : 8775 : tmp = gen_rtx_UNSPEC (mode, v, u);
4186 : 8775 : }
4187 : : else
4188 : : {
4189 : 0 : code = is_min ? SMIN : SMAX;
4190 : 0 : if (MEM_P (if_true) && MEM_P (if_false))
4191 : 0 : if_true = force_reg (mode, if_true);
4192 : 0 : tmp = gen_rtx_fmt_ee (code, mode, if_true, if_false);
4193 : : }
4194 : :
4195 : 8775 : emit_insn (gen_rtx_SET (dest, tmp));
4196 : 8775 : return true;
4197 : : }
4198 : :
4199 : : /* Return true if MODE is valid for vector compare to mask register,
4200 : : Same result for conditionl vector move with mask register. */
4201 : : static bool
4202 : 14006 : ix86_valid_mask_cmp_mode (machine_mode mode)
4203 : : {
4204 : : /* XOP has its own vector conditional movement. */
4205 : 14006 : if (TARGET_XOP && !TARGET_AVX512F)
4206 : : return false;
4207 : :
4208 : : /* HFmode only supports vcmpsh whose dest is mask register. */
4209 : 14000 : if (TARGET_AVX512FP16 && mode == HFmode)
4210 : : return true;
4211 : :
4212 : : /* AVX512F is needed for mask operation. */
4213 : 13996 : if (!(TARGET_AVX512F && VECTOR_MODE_P (mode)))
4214 : : return false;
4215 : :
4216 : : /* AVX512BW is needed for vector QI/HImode,
4217 : : AVX512VL is needed for 128/256-bit vector. */
4218 : 190 : machine_mode inner_mode = GET_MODE_INNER (mode);
4219 : 190 : int vector_size = GET_MODE_SIZE (mode);
4220 : 190 : if ((inner_mode == QImode || inner_mode == HImode) && !TARGET_AVX512BW)
4221 : : return false;
4222 : :
4223 : 170 : return vector_size == 64 || TARGET_AVX512VL;
4224 : : }
4225 : :
4226 : : /* Return true if integer mask comparison should be used. */
4227 : : static bool
4228 : 46881 : ix86_use_mask_cmp_p (machine_mode mode, machine_mode cmp_mode,
4229 : : rtx op_true, rtx op_false)
4230 : : {
4231 : 46881 : int vector_size = GET_MODE_SIZE (mode);
4232 : :
4233 : 46881 : if (cmp_mode == HFmode)
4234 : : return true;
4235 : 46877 : else if (vector_size < 16)
4236 : : return false;
4237 : 41602 : else if (vector_size == 64)
4238 : : return true;
4239 : 83088 : else if (GET_MODE_INNER (cmp_mode) == HFmode)
4240 : : return true;
4241 : 83088 : else if (GET_MODE_INNER (cmp_mode) == BFmode)
4242 : : return true;
4243 : :
4244 : : /* When op_true is NULL, op_false must be NULL, or vice versa. */
4245 : 41544 : gcc_assert (!op_true == !op_false);
4246 : :
4247 : : /* When op_true/op_false is NULL or cmp_mode is not valid mask cmp mode,
4248 : : vector dest is required. */
4249 : 41544 : if (!op_true || !ix86_valid_mask_cmp_mode (cmp_mode))
4250 : : return false;
4251 : :
4252 : : /* Exclude those that could be optimized in ix86_expand_sse_movcc. */
4253 : 48 : if (op_false == CONST0_RTX (mode)
4254 : 48 : || op_true == CONST0_RTX (mode)
4255 : 48 : || (INTEGRAL_MODE_P (mode)
4256 : 40 : && (op_true == CONSTM1_RTX (mode)
4257 : 40 : || op_false == CONSTM1_RTX (mode))))
4258 : 0 : return false;
4259 : :
4260 : : return true;
4261 : : }
4262 : :
4263 : : /* Expand an SSE comparison. Return the register with the result. */
4264 : :
4265 : : static rtx
4266 : 32014 : ix86_expand_sse_cmp (rtx dest, enum rtx_code code, rtx cmp_op0, rtx cmp_op1,
4267 : : rtx op_true, rtx op_false)
4268 : : {
4269 : 32014 : machine_mode mode = GET_MODE (dest);
4270 : 32014 : machine_mode cmp_ops_mode = GET_MODE (cmp_op0);
4271 : :
4272 : : /* In general case result of comparison can differ from operands' type. */
4273 : 32014 : machine_mode cmp_mode;
4274 : :
4275 : : /* In AVX512F the result of comparison is an integer mask. */
4276 : 32014 : bool maskcmp = false;
4277 : 32014 : rtx x;
4278 : :
4279 : 32014 : if (ix86_use_mask_cmp_p (mode, cmp_ops_mode, op_true, op_false))
4280 : : {
4281 : 57 : unsigned int nbits = GET_MODE_NUNITS (cmp_ops_mode);
4282 : 57 : maskcmp = true;
4283 : 57 : cmp_mode = nbits > 8 ? int_mode_for_size (nbits, 0).require () : E_QImode;
4284 : : }
4285 : : else
4286 : : cmp_mode = cmp_ops_mode;
4287 : :
4288 : 32014 : cmp_op0 = force_reg (cmp_ops_mode, cmp_op0);
4289 : :
4290 : 64028 : bool (*op1_predicate)(rtx, machine_mode)
4291 : 32014 : = VECTOR_MODE_P (cmp_ops_mode) ? vector_operand : nonimmediate_operand;
4292 : :
4293 : 32014 : if (!op1_predicate (cmp_op1, cmp_ops_mode))
4294 : 0 : cmp_op1 = force_reg (cmp_ops_mode, cmp_op1);
4295 : :
4296 : 32014 : if (optimize
4297 : 503 : || (maskcmp && cmp_mode != mode)
4298 : 503 : || (op_true && reg_overlap_mentioned_p (dest, op_true))
4299 : 32517 : || (op_false && reg_overlap_mentioned_p (dest, op_false)))
4300 : 62965 : dest = gen_reg_rtx (maskcmp ? cmp_mode : mode);
4301 : :
4302 : 32014 : if (maskcmp)
4303 : : {
4304 : 57 : bool ok = ix86_expand_mask_vec_cmp (dest, code, cmp_op0, cmp_op1);
4305 : 57 : gcc_assert (ok);
4306 : : return dest;
4307 : : }
4308 : :
4309 : 31957 : x = gen_rtx_fmt_ee (code, cmp_mode, cmp_op0, cmp_op1);
4310 : :
4311 : 31957 : if (cmp_mode != mode)
4312 : : {
4313 : 6960 : x = force_reg (cmp_ops_mode, x);
4314 : 6960 : convert_move (dest, x, false);
4315 : : }
4316 : : else
4317 : 24997 : emit_insn (gen_rtx_SET (dest, x));
4318 : :
4319 : : return dest;
4320 : : }
4321 : :
4322 : : /* Emit x86 binary operand CODE in mode MODE for SSE vector
4323 : : instructions that can be performed using GP registers. */
4324 : :
4325 : : static void
4326 : 6809 : ix86_emit_vec_binop (enum rtx_code code, machine_mode mode,
4327 : : rtx dst, rtx src1, rtx src2)
4328 : : {
4329 : 6809 : rtx tmp;
4330 : :
4331 : 6809 : tmp = gen_rtx_SET (dst, gen_rtx_fmt_ee (code, mode, src1, src2));
4332 : :
4333 : 6809 : if (GET_MODE_SIZE (mode) <= GET_MODE_SIZE (SImode)
4334 : 6809 : && GET_MODE_CLASS (mode) == MODE_VECTOR_INT)
4335 : : {
4336 : 48 : rtx clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
4337 : 48 : tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, tmp, clob));
4338 : : }
4339 : :
4340 : 6809 : emit_insn (tmp);
4341 : 6809 : }
4342 : :
4343 : : /* Expand DEST = CMP ? OP_TRUE : OP_FALSE into a sequence of logical
4344 : : operations. This is used for both scalar and vector conditional moves. */
4345 : :
4346 : : void
4347 : 8793 : ix86_expand_sse_movcc (rtx dest, rtx cmp, rtx op_true, rtx op_false)
4348 : : {
4349 : 8793 : machine_mode mode = GET_MODE (dest);
4350 : 8793 : machine_mode cmpmode = GET_MODE (cmp);
4351 : 8793 : rtx x;
4352 : :
4353 : : /* Simplify trivial VEC_COND_EXPR to avoid ICE in pr97506. */
4354 : 8793 : if (rtx_equal_p (op_true, op_false))
4355 : : {
4356 : 0 : emit_move_insn (dest, op_true);
4357 : 0 : return;
4358 : : }
4359 : :
4360 : : /* If we have an integer mask and FP value then we need
4361 : : to cast mask to FP mode. */
4362 : 8793 : if (mode != cmpmode && VECTOR_MODE_P (cmpmode))
4363 : : {
4364 : 958 : cmp = force_reg (cmpmode, cmp);
4365 : 958 : cmp = gen_rtx_SUBREG (mode, cmp, 0);
4366 : : }
4367 : :
4368 : : /* In AVX512F the result of comparison is an integer mask. */
4369 : 8793 : if (mode != cmpmode
4370 : 1015 : && GET_MODE_CLASS (cmpmode) == MODE_INT)
4371 : : {
4372 : 57 : gcc_assert (ix86_valid_mask_cmp_mode (mode));
4373 : : /* Using scalar/vector move with mask register. */
4374 : 57 : cmp = force_reg (cmpmode, cmp);
4375 : : /* Optimize for mask zero. */
4376 : 114 : op_true = (op_true != CONST0_RTX (mode)
4377 : 57 : ? force_reg (mode, op_true) : op_true);
4378 : 114 : op_false = (op_false != CONST0_RTX (mode)
4379 : 57 : ? force_reg (mode, op_false) : op_false);
4380 : 57 : if (op_true == CONST0_RTX (mode))
4381 : : {
4382 : 0 : if (cmpmode == E_DImode && !TARGET_64BIT)
4383 : : {
4384 : 0 : x = gen_reg_rtx (cmpmode);
4385 : 0 : emit_insn (gen_knotdi (x, cmp));
4386 : : }
4387 : : else
4388 : 0 : x = expand_simple_unop (cmpmode, NOT, cmp, NULL, 1);
4389 : : cmp = x;
4390 : : /* Reverse op_true op_false. */
4391 : : std::swap (op_true, op_false);
4392 : : }
4393 : :
4394 : 57 : if (mode == HFmode)
4395 : 4 : emit_insn (gen_movhf_mask (dest, op_true, op_false, cmp));
4396 : : else
4397 : 53 : emit_insn (gen_rtx_SET (dest,
4398 : : gen_rtx_VEC_MERGE (mode,
4399 : : op_true, op_false, cmp)));
4400 : 57 : return;
4401 : : }
4402 : :
4403 : 8736 : if (vector_all_ones_operand (op_true, mode)
4404 : 8736 : && op_false == CONST0_RTX (mode))
4405 : : {
4406 : 2 : emit_move_insn (dest, cmp);
4407 : 2 : return;
4408 : : }
4409 : 8734 : else if (op_false == CONST0_RTX (mode))
4410 : : {
4411 : 362 : x = expand_simple_binop (mode, AND, cmp, op_true,
4412 : : dest, 1, OPTAB_DIRECT);
4413 : 362 : if (x != dest)
4414 : 0 : emit_move_insn (dest, x);
4415 : 362 : return;
4416 : : }
4417 : 8372 : else if (op_true == CONST0_RTX (mode))
4418 : : {
4419 : 96 : op_false = force_reg (mode, op_false);
4420 : 96 : x = gen_rtx_NOT (mode, cmp);
4421 : 96 : ix86_emit_vec_binop (AND, mode, dest, x, op_false);
4422 : 96 : return;
4423 : : }
4424 : 8276 : else if (vector_all_ones_operand (op_true, mode))
4425 : : {
4426 : 0 : x = expand_simple_binop (mode, IOR, cmp, op_false,
4427 : : dest, 1, OPTAB_DIRECT);
4428 : 0 : if (x != dest)
4429 : 0 : emit_move_insn (dest, x);
4430 : 0 : return;
4431 : : }
4432 : :
4433 : 8276 : if (TARGET_XOP)
4434 : : {
4435 : 65 : op_true = force_reg (mode, op_true);
4436 : :
4437 : 65 : if (GET_MODE_SIZE (mode) < 16
4438 : 65 : || !nonimmediate_operand (op_false, mode))
4439 : 49 : op_false = force_reg (mode, op_false);
4440 : :
4441 : 65 : emit_insn (gen_rtx_SET (dest,
4442 : : gen_rtx_IF_THEN_ELSE (mode, cmp,
4443 : : op_true, op_false)));
4444 : 65 : return;
4445 : : }
4446 : :
4447 : 8211 : rtx (*gen) (rtx, rtx, rtx, rtx) = NULL;
4448 : 8211 : machine_mode blend_mode = mode;
4449 : :
4450 : 8211 : if (GET_MODE_SIZE (mode) < 16
4451 : 8211 : || !vector_operand (op_true, mode))
4452 : 2223 : op_true = force_reg (mode, op_true);
4453 : :
4454 : 8211 : op_false = force_reg (mode, op_false);
4455 : :
4456 : 8211 : switch (mode)
4457 : : {
4458 : 29 : case E_V2SFmode:
4459 : 29 : if (TARGET_SSE_MOVCC_USE_BLENDV && TARGET_SSE4_1)
4460 : : gen = gen_mmx_blendvps;
4461 : : break;
4462 : 287 : case E_V4SFmode:
4463 : 287 : if (TARGET_SSE_MOVCC_USE_BLENDV && TARGET_SSE4_1)
4464 : : gen = gen_sse4_1_blendvps;
4465 : : break;
4466 : 130 : case E_V2DFmode:
4467 : 130 : if (TARGET_SSE_MOVCC_USE_BLENDV && TARGET_SSE4_1)
4468 : : gen = gen_sse4_1_blendvpd;
4469 : : break;
4470 : 1043 : case E_SFmode:
4471 : 1043 : if (TARGET_SSE_MOVCC_USE_BLENDV && TARGET_SSE4_1)
4472 : : gen = gen_sse4_1_blendvss;
4473 : : break;
4474 : 848 : case E_DFmode:
4475 : 848 : if (TARGET_SSE_MOVCC_USE_BLENDV && TARGET_SSE4_1)
4476 : : gen = gen_sse4_1_blendvsd;
4477 : : break;
4478 : 190 : case E_V8QImode:
4479 : 190 : case E_V4HImode:
4480 : 190 : case E_V4HFmode:
4481 : 190 : case E_V4BFmode:
4482 : 190 : case E_V2SImode:
4483 : 190 : if (TARGET_SSE_MOVCC_USE_BLENDV && TARGET_SSE4_1)
4484 : : {
4485 : : gen = gen_mmx_pblendvb_v8qi;
4486 : : blend_mode = V8QImode;
4487 : : }
4488 : : break;
4489 : 77 : case E_V4QImode:
4490 : 77 : case E_V2HImode:
4491 : 77 : case E_V2HFmode:
4492 : 77 : case E_V2BFmode:
4493 : 77 : if (TARGET_SSE_MOVCC_USE_BLENDV && TARGET_SSE4_1)
4494 : : {
4495 : : gen = gen_mmx_pblendvb_v4qi;
4496 : : blend_mode = V4QImode;
4497 : : }
4498 : : break;
4499 : 36 : case E_V2QImode:
4500 : 36 : if (TARGET_SSE_MOVCC_USE_BLENDV && TARGET_SSE4_1)
4501 : : gen = gen_mmx_pblendvb_v2qi;
4502 : : break;
4503 : 5210 : case E_V16QImode:
4504 : 5210 : case E_V8HImode:
4505 : 5210 : case E_V8HFmode:
4506 : 5210 : case E_V8BFmode:
4507 : 5210 : case E_V4SImode:
4508 : 5210 : case E_V2DImode:
4509 : 5210 : case E_V1TImode:
4510 : 5210 : if (TARGET_SSE_MOVCC_USE_BLENDV && TARGET_SSE4_1)
4511 : : {
4512 : : gen = gen_sse4_1_pblendvb;
4513 : : blend_mode = V16QImode;
4514 : : }
4515 : : break;
4516 : 72 : case E_V8SFmode:
4517 : 72 : if (TARGET_AVX && TARGET_SSE_MOVCC_USE_BLENDV)
4518 : : gen = gen_avx_blendvps256;
4519 : : break;
4520 : 84 : case E_V4DFmode:
4521 : 84 : if (TARGET_AVX && TARGET_SSE_MOVCC_USE_BLENDV)
4522 : : gen = gen_avx_blendvpd256;
4523 : : break;
4524 : 205 : case E_V32QImode:
4525 : 205 : case E_V16HImode:
4526 : 205 : case E_V16HFmode:
4527 : 205 : case E_V16BFmode:
4528 : 205 : case E_V8SImode:
4529 : 205 : case E_V4DImode:
4530 : 205 : if (TARGET_AVX2 && TARGET_SSE_MOVCC_USE_BLENDV)
4531 : : {
4532 : : gen = gen_avx2_pblendvb;
4533 : : blend_mode = V32QImode;
4534 : : }
4535 : : break;
4536 : :
4537 : 0 : case E_V64QImode:
4538 : 0 : gen = gen_avx512bw_blendmv64qi;
4539 : 0 : break;
4540 : 0 : case E_V32HImode:
4541 : 0 : gen = gen_avx512bw_blendmv32hi;
4542 : 0 : break;
4543 : 0 : case E_V32HFmode:
4544 : 0 : gen = gen_avx512bw_blendmv32hf;
4545 : 0 : break;
4546 : 0 : case E_V32BFmode:
4547 : 0 : gen = gen_avx512bw_blendmv32bf;
4548 : 0 : break;
4549 : 0 : case E_V16SImode:
4550 : 0 : gen = gen_avx512f_blendmv16si;
4551 : 0 : break;
4552 : 0 : case E_V8DImode:
4553 : 0 : gen = gen_avx512f_blendmv8di;
4554 : 0 : break;
4555 : 0 : case E_V8DFmode:
4556 : 0 : gen = gen_avx512f_blendmv8df;
4557 : 0 : break;
4558 : : case E_V16SFmode:
4559 : : gen = gen_avx512f_blendmv16sf;
4560 : : break;
4561 : :
4562 : : default:
4563 : : break;
4564 : : }
4565 : :
4566 : 0 : if (gen != NULL)
4567 : : {
4568 : 1563 : if (blend_mode == mode)
4569 : : x = dest;
4570 : : else
4571 : : {
4572 : 826 : x = gen_reg_rtx (blend_mode);
4573 : 826 : op_false = gen_lowpart (blend_mode, op_false);
4574 : 826 : op_true = gen_lowpart (blend_mode, op_true);
4575 : 826 : cmp = gen_lowpart (blend_mode, cmp);
4576 : : }
4577 : :
4578 : 1563 : emit_insn (gen (x, op_false, op_true, cmp));
4579 : :
4580 : 1563 : if (x != dest)
4581 : 826 : emit_move_insn (dest, gen_lowpart (mode, x));
4582 : : }
4583 : : else
4584 : : {
4585 : 6648 : rtx t2, t3;
4586 : :
4587 : 6648 : t2 = expand_simple_binop (mode, AND, op_true, cmp,
4588 : : NULL, 1, OPTAB_DIRECT);
4589 : :
4590 : 6648 : t3 = gen_reg_rtx (mode);
4591 : 6648 : x = gen_rtx_NOT (mode, cmp);
4592 : 6648 : ix86_emit_vec_binop (AND, mode, t3, x, op_false);
4593 : :
4594 : 6648 : x = expand_simple_binop (mode, IOR, t3, t2,
4595 : : dest, 1, OPTAB_DIRECT);
4596 : 6648 : if (x != dest)
4597 : 0 : emit_move_insn (dest, x);
4598 : : }
4599 : : }
4600 : :
4601 : : /* Swap, force into registers, or otherwise massage the two operands
4602 : : to an sse comparison with a mask result. Thus we differ a bit from
4603 : : ix86_prepare_fp_compare_args which expects to produce a flags result.
4604 : :
4605 : : The DEST operand exists to help determine whether to commute commutative
4606 : : operators. The POP0/POP1 operands are updated in place. The new
4607 : : comparison code is returned, or UNKNOWN if not implementable. */
4608 : :
4609 : : static enum rtx_code
4610 : 17781 : ix86_prepare_sse_fp_compare_args (rtx dest, enum rtx_code code,
4611 : : rtx *pop0, rtx *pop1)
4612 : : {
4613 : 17781 : switch (code)
4614 : : {
4615 : 67 : case LTGT:
4616 : 67 : case UNEQ:
4617 : : /* AVX supports all the needed comparisons. */
4618 : 67 : if (TARGET_AVX)
4619 : : break;
4620 : : /* We have no LTGT as an operator. We could implement it with
4621 : : NE & ORDERED, but this requires an extra temporary. It's
4622 : : not clear that it's worth it. */
4623 : : return UNKNOWN;
4624 : :
4625 : : case LT:
4626 : : case LE:
4627 : : case UNGT:
4628 : : case UNGE:
4629 : : /* These are supported directly. */
4630 : : break;
4631 : :
4632 : 5099 : case EQ:
4633 : 5099 : case NE:
4634 : 5099 : case UNORDERED:
4635 : 5099 : case ORDERED:
4636 : : /* AVX has 3 operand comparisons, no need to swap anything. */
4637 : 5099 : if (TARGET_AVX)
4638 : : break;
4639 : : /* For commutative operators, try to canonicalize the destination
4640 : : operand to be first in the comparison - this helps reload to
4641 : : avoid extra moves. */
4642 : 333 : if (!dest || !rtx_equal_p (dest, *pop1))
4643 : : break;
4644 : : /* FALLTHRU */
4645 : :
4646 : 11593 : case GE:
4647 : 11593 : case GT:
4648 : 11593 : case UNLE:
4649 : 11593 : case UNLT:
4650 : : /* These are not supported directly before AVX, and furthermore
4651 : : ix86_expand_sse_fp_minmax only optimizes LT/UNGE. Swap the
4652 : : comparison operands to transform into something that is
4653 : : supported. */
4654 : 11593 : std::swap (*pop0, *pop1);
4655 : 11593 : code = swap_condition (code);
4656 : 11593 : break;
4657 : :
4658 : 0 : default:
4659 : 0 : gcc_unreachable ();
4660 : : }
4661 : :
4662 : : return code;
4663 : : }
4664 : :
4665 : : /* Expand a floating-point conditional move. Return true if successful. */
4666 : :
4667 : : bool
4668 : 100257 : ix86_expand_fp_movcc (rtx operands[])
4669 : : {
4670 : 100257 : machine_mode mode = GET_MODE (operands[0]);
4671 : 100257 : enum rtx_code code = GET_CODE (operands[1]);
4672 : 100257 : rtx tmp, compare_op;
4673 : 100257 : rtx op0 = XEXP (operands[1], 0);
4674 : 100257 : rtx op1 = XEXP (operands[1], 1);
4675 : :
4676 : 100257 : if (GET_MODE (op0) == BFmode
4677 : 100257 : && !ix86_fp_comparison_operator (operands[1], VOIDmode))
4678 : : return false;
4679 : :
4680 : 100257 : if (SSE_FLOAT_MODE_SSEMATH_OR_HFBF_P (mode))
4681 : : {
4682 : 69593 : machine_mode cmode;
4683 : :
4684 : : /* Since we've no cmove for sse registers, don't force bad register
4685 : : allocation just to gain access to it. Deny movcc when the
4686 : : comparison mode doesn't match the move mode. */
4687 : 69593 : cmode = GET_MODE (op0);
4688 : 69593 : if (cmode == VOIDmode)
4689 : 0 : cmode = GET_MODE (op1);
4690 : 69593 : if (cmode != mode)
4691 : : return false;
4692 : :
4693 : 10841 : code = ix86_prepare_sse_fp_compare_args (operands[0], code, &op0, &op1);
4694 : 10841 : if (code == UNKNOWN)
4695 : : return false;
4696 : :
4697 : 10821 : if (ix86_expand_sse_fp_minmax (operands[0], code, op0, op1,
4698 : : operands[2], operands[3]))
4699 : : return true;
4700 : :
4701 : 2046 : tmp = ix86_expand_sse_cmp (operands[0], code, op0, op1,
4702 : : operands[2], operands[3]);
4703 : 2046 : ix86_expand_sse_movcc (operands[0], tmp, operands[2], operands[3]);
4704 : 2046 : return true;
4705 : : }
4706 : :
4707 : 30664 : if (GET_MODE (op0) == TImode
4708 : 30664 : || (GET_MODE (op0) == DImode
4709 : 72 : && !TARGET_64BIT))
4710 : : return false;
4711 : :
4712 : : /* The floating point conditional move instructions don't directly
4713 : : support conditions resulting from a signed integer comparison. */
4714 : :
4715 : 30592 : compare_op = ix86_expand_compare (code, op0, op1);
4716 : 30592 : if (!fcmov_comparison_operator (compare_op, VOIDmode))
4717 : : {
4718 : 143 : tmp = gen_reg_rtx (QImode);
4719 : 143 : ix86_expand_setcc (tmp, code, op0, op1);
4720 : :
4721 : 143 : compare_op = ix86_expand_compare (NE, tmp, const0_rtx);
4722 : : }
4723 : :
4724 : 30592 : operands[2] = force_reg (mode, operands[2]);
4725 : 30592 : operands[3] = force_reg (mode, operands[3]);
4726 : 30592 : emit_insn (gen_rtx_SET (operands[0],
4727 : : gen_rtx_IF_THEN_ELSE (mode, compare_op,
4728 : : operands[2], operands[3])));
4729 : :
4730 : 30592 : return true;
4731 : : }
4732 : :
4733 : : /* Helper for ix86_cmp_code_to_pcmp_immediate for int modes. */
4734 : :
4735 : : static int
4736 : 3065 : ix86_int_cmp_code_to_pcmp_immediate (enum rtx_code code)
4737 : : {
4738 : 3065 : switch (code)
4739 : : {
4740 : : case EQ:
4741 : : return 0;
4742 : 360 : case LT:
4743 : 360 : case LTU:
4744 : 360 : return 1;
4745 : 189 : case LE:
4746 : 189 : case LEU:
4747 : 189 : return 2;
4748 : 1420 : case NE:
4749 : 1420 : return 4;
4750 : 287 : case GE:
4751 : 287 : case GEU:
4752 : 287 : return 5;
4753 : 425 : case GT:
4754 : 425 : case GTU:
4755 : 425 : return 6;
4756 : 0 : default:
4757 : 0 : gcc_unreachable ();
4758 : : }
4759 : : }
4760 : :
4761 : : /* Helper for ix86_cmp_code_to_pcmp_immediate for fp modes. */
4762 : :
4763 : : static int
4764 : 1740 : ix86_fp_cmp_code_to_pcmp_immediate (enum rtx_code code)
4765 : : {
4766 : 1740 : switch (code)
4767 : : {
4768 : : case EQ:
4769 : : return 0x00;
4770 : 413 : case NE:
4771 : 413 : return 0x04;
4772 : 508 : case GT:
4773 : 508 : return 0x0e;
4774 : 46 : case LE:
4775 : 46 : return 0x02;
4776 : 53 : case GE:
4777 : 53 : return 0x0d;
4778 : 610 : case LT:
4779 : 610 : return 0x01;
4780 : 2 : case UNLE:
4781 : 2 : return 0x0a;
4782 : 2 : case UNLT:
4783 : 2 : return 0x09;
4784 : 11 : case UNGE:
4785 : 11 : return 0x05;
4786 : 2 : case UNGT:
4787 : 2 : return 0x06;
4788 : 2 : case UNEQ:
4789 : 2 : return 0x18;
4790 : 0 : case LTGT:
4791 : 0 : return 0x0c;
4792 : 2 : case ORDERED:
4793 : 2 : return 0x07;
4794 : 2 : case UNORDERED:
4795 : 2 : return 0x03;
4796 : 0 : default:
4797 : 0 : gcc_unreachable ();
4798 : : }
4799 : : }
4800 : :
4801 : : /* Return immediate value to be used in UNSPEC_PCMP
4802 : : for comparison CODE in MODE. */
4803 : :
4804 : : static int
4805 : 4805 : ix86_cmp_code_to_pcmp_immediate (enum rtx_code code, machine_mode mode)
4806 : : {
4807 : 4805 : if (FLOAT_MODE_P (mode))
4808 : 1740 : return ix86_fp_cmp_code_to_pcmp_immediate (code);
4809 : 3065 : return ix86_int_cmp_code_to_pcmp_immediate (code);
4810 : : }
4811 : :
4812 : : /* Expand AVX-512 vector comparison. */
4813 : :
4814 : : bool
4815 : 4805 : ix86_expand_mask_vec_cmp (rtx dest, enum rtx_code code, rtx cmp_op0, rtx cmp_op1)
4816 : : {
4817 : 4805 : machine_mode mask_mode = GET_MODE (dest);
4818 : 4805 : machine_mode cmp_mode = GET_MODE (cmp_op0);
4819 : 4805 : rtx imm = GEN_INT (ix86_cmp_code_to_pcmp_immediate (code, cmp_mode));
4820 : 4805 : int unspec_code;
4821 : 4805 : rtx unspec;
4822 : :
4823 : 4805 : switch (code)
4824 : : {
4825 : : case LEU:
4826 : : case GTU:
4827 : : case GEU:
4828 : : case LTU:
4829 : : unspec_code = UNSPEC_UNSIGNED_PCMP;
4830 : : break;
4831 : :
4832 : 4486 : default:
4833 : 4486 : unspec_code = UNSPEC_PCMP;
4834 : : }
4835 : :
4836 : 4805 : unspec = gen_rtx_UNSPEC (mask_mode, gen_rtvec (3, cmp_op0, cmp_op1, imm),
4837 : : unspec_code);
4838 : 4805 : emit_insn (gen_rtx_SET (dest, unspec));
4839 : :
4840 : 4805 : return true;
4841 : : }
4842 : :
4843 : : /* Expand fp vector comparison. */
4844 : :
4845 : : bool
4846 : 6940 : ix86_expand_fp_vec_cmp (rtx operands[])
4847 : : {
4848 : 6940 : enum rtx_code code = GET_CODE (operands[1]);
4849 : 6940 : rtx cmp;
4850 : :
4851 : 6940 : code = ix86_prepare_sse_fp_compare_args (operands[0], code,
4852 : : &operands[2], &operands[3]);
4853 : 6940 : if (code == UNKNOWN)
4854 : : {
4855 : 20 : rtx temp;
4856 : 20 : switch (GET_CODE (operands[1]))
4857 : : {
4858 : 2 : case LTGT:
4859 : 2 : temp = ix86_expand_sse_cmp (operands[0], ORDERED, operands[2],
4860 : : operands[3], NULL, NULL);
4861 : 2 : cmp = ix86_expand_sse_cmp (operands[0], NE, operands[2],
4862 : : operands[3], NULL, NULL);
4863 : 2 : code = AND;
4864 : 2 : break;
4865 : 18 : case UNEQ:
4866 : 18 : temp = ix86_expand_sse_cmp (operands[0], UNORDERED, operands[2],
4867 : : operands[3], NULL, NULL);
4868 : 18 : cmp = ix86_expand_sse_cmp (operands[0], EQ, operands[2],
4869 : : operands[3], NULL, NULL);
4870 : 18 : code = IOR;
4871 : 18 : break;
4872 : 0 : default:
4873 : 0 : gcc_unreachable ();
4874 : : }
4875 : 20 : cmp = expand_simple_binop (GET_MODE (cmp), code, temp, cmp, cmp, 1,
4876 : : OPTAB_DIRECT);
4877 : : }
4878 : : else
4879 : 6920 : cmp = ix86_expand_sse_cmp (operands[0], code, operands[2], operands[3],
4880 : : NULL, NULL);
4881 : :
4882 : 6940 : if (operands[0] != cmp)
4883 : 6857 : emit_move_insn (operands[0], cmp);
4884 : :
4885 : 6940 : return true;
4886 : : }
4887 : :
4888 : : static rtx
4889 : 15065 : ix86_expand_int_sse_cmp (rtx dest, enum rtx_code code, rtx cop0, rtx cop1,
4890 : : rtx op_true, rtx op_false, bool *negate)
4891 : : {
4892 : 15065 : machine_mode data_mode = GET_MODE (dest);
4893 : 15065 : machine_mode mode = GET_MODE (cop0);
4894 : 15065 : rtx x;
4895 : :
4896 : 15065 : *negate = false;
4897 : :
4898 : : /* XOP supports all of the comparisons on all 128-bit vector int types. */
4899 : 15065 : if (TARGET_XOP
4900 : 201 : && GET_MODE_CLASS (mode) == MODE_VECTOR_INT
4901 : 15266 : && GET_MODE_SIZE (mode) <= 16)
4902 : : ;
4903 : : /* AVX512F supports all of the comparsions
4904 : : on all 128/256/512-bit vector int types. */
4905 : 14867 : else if (ix86_use_mask_cmp_p (data_mode, mode, op_true, op_false))
4906 : : ;
4907 : : else
4908 : : {
4909 : : /* Canonicalize the comparison to EQ, GT, GTU. */
4910 : 14814 : switch (code)
4911 : : {
4912 : : case EQ:
4913 : : case GT:
4914 : : case GTU:
4915 : : break;
4916 : :
4917 : 697 : case LE:
4918 : 697 : case LEU:
4919 : : /* x <= cst can be handled as x < cst + 1 unless there is
4920 : : wrap around in cst + 1. */
4921 : 697 : if (GET_CODE (cop1) == CONST_VECTOR
4922 : 1184 : && GET_MODE_INNER (mode) != TImode)
4923 : : {
4924 : 487 : unsigned int n_elts = GET_MODE_NUNITS (mode), i;
4925 : 487 : machine_mode eltmode = GET_MODE_INNER (mode);
4926 : 3116 : for (i = 0; i < n_elts; ++i)
4927 : : {
4928 : 2630 : rtx elt = CONST_VECTOR_ELT (cop1, i);
4929 : 2630 : if (!CONST_INT_P (elt))
4930 : : break;
4931 : 2630 : if (code == LE)
4932 : : {
4933 : : /* For LE punt if some element is signed maximum. */
4934 : 1790 : if ((INTVAL (elt) & (GET_MODE_MASK (eltmode) >> 1))
4935 : : == (GET_MODE_MASK (eltmode) >> 1))
4936 : : break;
4937 : : }
4938 : : /* For LEU punt if some element is unsigned maximum. */
4939 : 840 : else if (elt == constm1_rtx)
4940 : : break;
4941 : : }
4942 : 487 : if (i == n_elts)
4943 : : {
4944 : 486 : rtvec v = rtvec_alloc (n_elts);
4945 : 3600 : for (i = 0; i < n_elts; ++i)
4946 : 2628 : RTVEC_ELT (v, i)
4947 : 2628 : = gen_int_mode (INTVAL (CONST_VECTOR_ELT (cop1, i)) + 1,
4948 : : eltmode);
4949 : 486 : cop1 = gen_rtx_CONST_VECTOR (mode, v);
4950 : 486 : std::swap (cop0, cop1);
4951 : 486 : code = code == LE ? GT : GTU;
4952 : : break;
4953 : : }
4954 : : }
4955 : : /* FALLTHRU */
4956 : 3089 : case NE:
4957 : 3089 : code = reverse_condition (code);
4958 : 3089 : *negate = true;
4959 : 3089 : break;
4960 : :
4961 : 376 : case GE:
4962 : 376 : case GEU:
4963 : : /* x >= cst can be handled as x > cst - 1 unless there is
4964 : : wrap around in cst - 1. */
4965 : 376 : if (GET_CODE (cop1) == CONST_VECTOR
4966 : 544 : && GET_MODE_INNER (mode) != TImode)
4967 : : {
4968 : 168 : unsigned int n_elts = GET_MODE_NUNITS (mode), i;
4969 : 168 : machine_mode eltmode = GET_MODE_INNER (mode);
4970 : 1118 : for (i = 0; i < n_elts; ++i)
4971 : : {
4972 : 998 : rtx elt = CONST_VECTOR_ELT (cop1, i);
4973 : 998 : if (!CONST_INT_P (elt))
4974 : : break;
4975 : 998 : if (code == GE)
4976 : : {
4977 : : /* For GE punt if some element is signed minimum. */
4978 : 950 : if (INTVAL (elt) < 0
4979 : 136 : && ((INTVAL (elt) & (GET_MODE_MASK (eltmode) >> 1))
4980 : : == 0))
4981 : : break;
4982 : : }
4983 : : /* For GEU punt if some element is zero. */
4984 : 48 : else if (elt == const0_rtx)
4985 : : break;
4986 : : }
4987 : 168 : if (i == n_elts)
4988 : : {
4989 : 120 : rtvec v = rtvec_alloc (n_elts);
4990 : 1190 : for (i = 0; i < n_elts; ++i)
4991 : 950 : RTVEC_ELT (v, i)
4992 : 950 : = gen_int_mode (INTVAL (CONST_VECTOR_ELT (cop1, i)) - 1,
4993 : : eltmode);
4994 : 120 : cop1 = gen_rtx_CONST_VECTOR (mode, v);
4995 : 120 : code = code == GE ? GT : GTU;
4996 : : break;
4997 : : }
4998 : : }
4999 : 256 : code = reverse_condition (code);
5000 : 256 : *negate = true;
5001 : : /* FALLTHRU */
5002 : :
5003 : 1490 : case LT:
5004 : 1490 : case LTU:
5005 : 1490 : std::swap (cop0, cop1);
5006 : 1490 : code = swap_condition (code);
5007 : 1490 : break;
5008 : :
5009 : 0 : default:
5010 : 0 : gcc_unreachable ();
5011 : : }
5012 : :
5013 : : /* Only SSE4.1/SSE4.2 supports V2DImode. */
5014 : 14814 : if (mode == V2DImode)
5015 : : {
5016 : 719 : switch (code)
5017 : : {
5018 : 511 : case EQ:
5019 : : /* SSE4.1 supports EQ. */
5020 : 511 : if (!TARGET_SSE4_1)
5021 : 15065 : return NULL;
5022 : : break;
5023 : :
5024 : 208 : case GT:
5025 : 208 : case GTU:
5026 : : /* SSE4.2 supports GT/GTU. */
5027 : 208 : if (!TARGET_SSE4_2)
5028 : : return NULL;
5029 : : break;
5030 : :
5031 : 0 : default:
5032 : 0 : gcc_unreachable ();
5033 : : }
5034 : : }
5035 : :
5036 : 14814 : if (GET_CODE (cop0) == CONST_VECTOR)
5037 : 1038 : cop0 = force_reg (mode, cop0);
5038 : 13776 : else if (GET_CODE (cop1) == CONST_VECTOR)
5039 : 6434 : cop1 = force_reg (mode, cop1);
5040 : :
5041 : 14814 : rtx optrue = op_true ? op_true : CONSTM1_RTX (data_mode);
5042 : 14814 : rtx opfalse = op_false ? op_false : CONST0_RTX (data_mode);
5043 : 14814 : if (*negate)
5044 : 3345 : std::swap (optrue, opfalse);
5045 : :
5046 : : /* Transform x > y ? 0 : -1 (i.e. x <= y ? -1 : 0 or x <= y) when
5047 : : not using integer masks into min (x, y) == x ? -1 : 0 (i.e.
5048 : : min (x, y) == x). While we add one instruction (the minimum),
5049 : : we remove the need for two instructions in the negation, as the
5050 : : result is done this way.
5051 : : When using masks, do it for SI/DImode element types, as it is shorter
5052 : : than the two subtractions. */
5053 : 14814 : if ((code != EQ
5054 : 6498 : && GET_MODE_SIZE (mode) != 64
5055 : 6498 : && vector_all_ones_operand (opfalse, data_mode)
5056 : 467 : && optrue == CONST0_RTX (data_mode))
5057 : 20845 : || (code == GTU
5058 : 1634 : && GET_MODE_SIZE (GET_MODE_INNER (mode)) >= 4
5059 : : /* Don't do it if not using integer masks and we'd end up with
5060 : : the right values in the registers though. */
5061 : 501 : && (GET_MODE_SIZE (mode) == 64
5062 : 501 : || !vector_all_ones_operand (optrue, data_mode)
5063 : 392 : || opfalse != CONST0_RTX (data_mode))))
5064 : : {
5065 : 576 : rtx (*gen) (rtx, rtx, rtx) = NULL;
5066 : :
5067 : 576 : switch (mode)
5068 : : {
5069 : 0 : case E_V16SImode:
5070 : 0 : gen = (code == GTU) ? gen_uminv16si3 : gen_sminv16si3;
5071 : : break;
5072 : 0 : case E_V8DImode:
5073 : 0 : gen = (code == GTU) ? gen_uminv8di3 : gen_sminv8di3;
5074 : 0 : cop0 = force_reg (mode, cop0);
5075 : 0 : cop1 = force_reg (mode, cop1);
5076 : 0 : break;
5077 : 16 : case E_V32QImode:
5078 : 16 : if (TARGET_AVX2)
5079 : 16 : gen = (code == GTU) ? gen_uminv32qi3 : gen_sminv32qi3;
5080 : : break;
5081 : 16 : case E_V16HImode:
5082 : 16 : if (TARGET_AVX2)
5083 : 16 : gen = (code == GTU) ? gen_uminv16hi3 : gen_sminv16hi3;
5084 : : break;
5085 : 22 : case E_V8SImode:
5086 : 22 : if (TARGET_AVX2)
5087 : 22 : gen = (code == GTU) ? gen_uminv8si3 : gen_sminv8si3;
5088 : : break;
5089 : 20 : case E_V4DImode:
5090 : 20 : if (TARGET_AVX512VL)
5091 : : {
5092 : 0 : gen = (code == GTU) ? gen_uminv4di3 : gen_sminv4di3;
5093 : 0 : cop0 = force_reg (mode, cop0);
5094 : 0 : cop1 = force_reg (mode, cop1);
5095 : : }
5096 : : break;
5097 : 55 : case E_V16QImode:
5098 : 55 : if (code == GTU && TARGET_SSE2)
5099 : : gen = gen_uminv16qi3;
5100 : 18 : else if (code == GT && TARGET_SSE4_1)
5101 : : gen = gen_sminv16qi3;
5102 : : break;
5103 : 40 : case E_V8QImode:
5104 : 40 : if (code == GTU && TARGET_SSE2)
5105 : : gen = gen_uminv8qi3;
5106 : 38 : else if (code == GT && TARGET_SSE4_1)
5107 : : gen = gen_sminv8qi3;
5108 : : break;
5109 : 13 : case E_V4QImode:
5110 : 13 : if (code == GTU && TARGET_SSE2)
5111 : : gen = gen_uminv4qi3;
5112 : 2 : else if (code == GT && TARGET_SSE4_1)
5113 : : gen = gen_sminv4qi3;
5114 : : break;
5115 : 8 : case E_V2QImode:
5116 : 8 : if (code == GTU && TARGET_SSE2)
5117 : : gen = gen_uminv2qi3;
5118 : 6 : else if (code == GT && TARGET_SSE4_1)
5119 : : gen = gen_sminv2qi3;
5120 : : break;
5121 : 61 : case E_V8HImode:
5122 : 61 : if (code == GTU && TARGET_SSE4_1)
5123 : : gen = gen_uminv8hi3;
5124 : 53 : else if (code == GT && TARGET_SSE2)
5125 : : gen = gen_sminv8hi3;
5126 : : break;
5127 : 4 : case E_V4HImode:
5128 : 4 : if (code == GTU && TARGET_SSE4_1)
5129 : : gen = gen_uminv4hi3;
5130 : 4 : else if (code == GT && TARGET_SSE2)
5131 : : gen = gen_sminv4hi3;
5132 : : break;
5133 : 13 : case E_V2HImode:
5134 : 13 : if (code == GTU && TARGET_SSE4_1)
5135 : : gen = gen_uminv2hi3;
5136 : 13 : else if (code == GT && TARGET_SSE2)
5137 : : gen = gen_sminv2hi3;
5138 : : break;
5139 : 211 : case E_V4SImode:
5140 : 211 : if (TARGET_SSE4_1)
5141 : 33 : gen = (code == GTU) ? gen_uminv4si3 : gen_sminv4si3;
5142 : : break;
5143 : 69 : case E_V2SImode:
5144 : 69 : if (TARGET_SSE4_1)
5145 : 0 : gen = (code == GTU) ? gen_uminv2si3 : gen_sminv2si3;
5146 : : break;
5147 : 28 : case E_V2DImode:
5148 : 28 : if (TARGET_AVX512VL)
5149 : : {
5150 : 0 : gen = (code == GTU) ? gen_uminv2di3 : gen_sminv2di3;
5151 : 0 : cop0 = force_reg (mode, cop0);
5152 : 0 : cop1 = force_reg (mode, cop1);
5153 : : }
5154 : : break;
5155 : : default:
5156 : : break;
5157 : : }
5158 : :
5159 : 0 : if (gen)
5160 : : {
5161 : 226 : rtx tem = gen_reg_rtx (mode);
5162 : 226 : if (!vector_operand (cop0, mode))
5163 : 0 : cop0 = force_reg (mode, cop0);
5164 : 226 : if (!vector_operand (cop1, mode))
5165 : 0 : cop1 = force_reg (mode, cop1);
5166 : 226 : *negate = !*negate;
5167 : 226 : emit_insn (gen (tem, cop0, cop1));
5168 : 226 : cop1 = tem;
5169 : 226 : code = EQ;
5170 : : }
5171 : : }
5172 : :
5173 : : /* Unsigned parallel compare is not supported by the hardware.
5174 : : Play some tricks to turn this into a signed comparison
5175 : : against 0. */
5176 : 14814 : if (code == GTU)
5177 : : {
5178 : 923 : cop0 = force_reg (mode, cop0);
5179 : :
5180 : 923 : switch (mode)
5181 : : {
5182 : 576 : case E_V16SImode:
5183 : 576 : case E_V8DImode:
5184 : 576 : case E_V8SImode:
5185 : 576 : case E_V4DImode:
5186 : 576 : case E_V4SImode:
5187 : 576 : case E_V2SImode:
5188 : 576 : case E_V2DImode:
5189 : 576 : {
5190 : 576 : rtx t1, t2, mask;
5191 : :
5192 : : /* Subtract (-(INT MAX) - 1) from both operands to make
5193 : : them signed. */
5194 : 576 : mask = ix86_build_signbit_mask (mode, true, false);
5195 : 576 : t1 = gen_reg_rtx (mode);
5196 : 576 : emit_insn (gen_sub3_insn (t1, cop0, mask));
5197 : :
5198 : 576 : t2 = gen_reg_rtx (mode);
5199 : 576 : emit_insn (gen_sub3_insn (t2, cop1, mask));
5200 : :
5201 : 576 : cop0 = t1;
5202 : 576 : cop1 = t2;
5203 : 576 : code = GT;
5204 : : }
5205 : 576 : break;
5206 : :
5207 : 347 : case E_V64QImode:
5208 : 347 : case E_V32HImode:
5209 : 347 : case E_V32QImode:
5210 : 347 : case E_V16HImode:
5211 : 347 : case E_V16QImode:
5212 : 347 : case E_V8QImode:
5213 : 347 : case E_V4QImode:
5214 : 347 : case E_V2QImode:
5215 : 347 : case E_V8HImode:
5216 : 347 : case E_V4HImode:
5217 : 347 : case E_V2HImode:
5218 : : /* Perform a parallel unsigned saturating subtraction. */
5219 : 347 : x = gen_reg_rtx (mode);
5220 : 347 : emit_insn (gen_rtx_SET
5221 : : (x, gen_rtx_US_MINUS (mode, cop0, cop1)));
5222 : 347 : cop0 = x;
5223 : 347 : cop1 = CONST0_RTX (mode);
5224 : 347 : code = EQ;
5225 : 347 : *negate = !*negate;
5226 : 347 : break;
5227 : :
5228 : 0 : default:
5229 : 0 : gcc_unreachable ();
5230 : : }
5231 : : }
5232 : : }
5233 : :
5234 : 15065 : if (*negate)
5235 : 3404 : std::swap (op_true, op_false);
5236 : :
5237 : 15065 : if (GET_CODE (cop1) == CONST_VECTOR)
5238 : 416 : cop1 = force_reg (mode, cop1);
5239 : :
5240 : : /* Allow the comparison to be done in one mode, but the movcc to
5241 : : happen in another mode. */
5242 : 15065 : if (data_mode == mode)
5243 : 15023 : x = ix86_expand_sse_cmp (dest, code, cop0, cop1, op_true, op_false);
5244 : : else
5245 : : {
5246 : 126 : gcc_assert (GET_MODE_SIZE (data_mode) == GET_MODE_SIZE (mode));
5247 : 42 : x = ix86_expand_sse_cmp (gen_reg_rtx (mode), code, cop0, cop1,
5248 : : op_true, op_false);
5249 : 42 : if (GET_MODE (x) == mode)
5250 : 24 : x = gen_lowpart (data_mode, x);
5251 : : }
5252 : :
5253 : : return x;
5254 : : }
5255 : :
5256 : : /* Expand integer vector comparison. */
5257 : :
5258 : : bool
5259 : 8485 : ix86_expand_int_vec_cmp (rtx operands[])
5260 : : {
5261 : 8485 : rtx_code code = GET_CODE (operands[1]);
5262 : 8485 : bool negate = false;
5263 : 8485 : rtx cmp = ix86_expand_int_sse_cmp (operands[0], code, operands[2],
5264 : : operands[3], NULL, NULL, &negate);
5265 : :
5266 : 8485 : if (!cmp)
5267 : : return false;
5268 : :
5269 : 8485 : if (negate)
5270 : 3308 : cmp = ix86_expand_int_sse_cmp (operands[0], EQ, cmp,
5271 : 3308 : CONST0_RTX (GET_MODE (cmp)),
5272 : : NULL, NULL, &negate);
5273 : :
5274 : 8485 : gcc_assert (!negate);
5275 : :
5276 : 8485 : if (operands[0] != cmp)
5277 : 8192 : emit_move_insn (operands[0], cmp);
5278 : :
5279 : : return true;
5280 : : }
5281 : :
5282 : : /* Expand a floating-point vector conditional move; a vcond operation
5283 : : rather than a movcc operation. */
5284 : :
5285 : : bool
5286 : 0 : ix86_expand_fp_vcond (rtx operands[])
5287 : : {
5288 : 0 : enum rtx_code code = GET_CODE (operands[3]);
5289 : 0 : rtx cmp;
5290 : :
5291 : 0 : code = ix86_prepare_sse_fp_compare_args (operands[0], code,
5292 : : &operands[4], &operands[5]);
5293 : 0 : if (code == UNKNOWN)
5294 : : {
5295 : 0 : rtx temp;
5296 : 0 : switch (GET_CODE (operands[3]))
5297 : : {
5298 : 0 : case LTGT:
5299 : 0 : temp = ix86_expand_sse_cmp (operands[0], ORDERED, operands[4],
5300 : : operands[5], operands[0], operands[0]);
5301 : 0 : cmp = ix86_expand_sse_cmp (operands[0], NE, operands[4],
5302 : : operands[5], operands[1], operands[2]);
5303 : 0 : code = AND;
5304 : 0 : break;
5305 : 0 : case UNEQ:
5306 : 0 : temp = ix86_expand_sse_cmp (operands[0], UNORDERED, operands[4],
5307 : : operands[5], operands[0], operands[0]);
5308 : 0 : cmp = ix86_expand_sse_cmp (operands[0], EQ, operands[4],
5309 : : operands[5], operands[1], operands[2]);
5310 : 0 : code = IOR;
5311 : 0 : break;
5312 : 0 : default:
5313 : 0 : gcc_unreachable ();
5314 : : }
5315 : 0 : cmp = expand_simple_binop (GET_MODE (cmp), code, temp, cmp, cmp, 1,
5316 : : OPTAB_DIRECT);
5317 : 0 : ix86_expand_sse_movcc (operands[0], cmp, operands[1], operands[2]);
5318 : 0 : return true;
5319 : : }
5320 : :
5321 : 0 : if (ix86_expand_sse_fp_minmax (operands[0], code, operands[4],
5322 : : operands[5], operands[1], operands[2]))
5323 : : return true;
5324 : :
5325 : 0 : cmp = ix86_expand_sse_cmp (operands[0], code, operands[4], operands[5],
5326 : : operands[1], operands[2]);
5327 : 0 : ix86_expand_sse_movcc (operands[0], cmp, operands[1], operands[2]);
5328 : 0 : return true;
5329 : : }
5330 : :
5331 : : /* Expand a signed/unsigned integral vector conditional move. */
5332 : :
5333 : : bool
5334 : 3272 : ix86_expand_int_vcond (rtx operands[])
5335 : : {
5336 : 3272 : machine_mode data_mode = GET_MODE (operands[0]);
5337 : 3272 : machine_mode mode = GET_MODE (operands[4]);
5338 : 3272 : enum rtx_code code = GET_CODE (operands[3]);
5339 : 3272 : bool negate = false;
5340 : 3272 : rtx x, cop0, cop1;
5341 : :
5342 : 3272 : cop0 = operands[4];
5343 : 3272 : cop1 = operands[5];
5344 : :
5345 : : /* Try to optimize x < 0 ? -1 : 0 into (signed) x >> 31
5346 : : and x < 0 ? 1 : 0 into (unsigned) x >> 31. */
5347 : 3272 : if ((code == LT || code == GE)
5348 : 0 : && data_mode == mode
5349 : 0 : && cop1 == CONST0_RTX (mode)
5350 : 0 : && operands[1 + (code == LT)] == CONST0_RTX (data_mode)
5351 : 0 : && GET_MODE_UNIT_SIZE (data_mode) > 1
5352 : 0 : && GET_MODE_UNIT_SIZE (data_mode) <= 8
5353 : 3272 : && (GET_MODE_SIZE (data_mode) == 16
5354 : 0 : || (TARGET_AVX2 && GET_MODE_SIZE (data_mode) == 32)))
5355 : : {
5356 : 0 : rtx negop = operands[2 - (code == LT)];
5357 : 0 : int shift = GET_MODE_UNIT_BITSIZE (data_mode) - 1;
5358 : 0 : if (negop == CONST1_RTX (data_mode))
5359 : : {
5360 : 0 : rtx res = expand_simple_binop (mode, LSHIFTRT, cop0, GEN_INT (shift),
5361 : : operands[0], 1, OPTAB_DIRECT);
5362 : 0 : if (res != operands[0])
5363 : 0 : emit_move_insn (operands[0], res);
5364 : 0 : return true;
5365 : : }
5366 : 0 : else if (GET_MODE_INNER (data_mode) != DImode
5367 : 0 : && vector_all_ones_operand (negop, data_mode))
5368 : : {
5369 : 0 : rtx res = expand_simple_binop (mode, ASHIFTRT, cop0, GEN_INT (shift),
5370 : : operands[0], 0, OPTAB_DIRECT);
5371 : 0 : if (res != operands[0])
5372 : 0 : emit_move_insn (operands[0], res);
5373 : 0 : return true;
5374 : : }
5375 : : }
5376 : :
5377 : 3272 : if (!nonimmediate_operand (cop1, mode))
5378 : 125 : cop1 = force_reg (mode, cop1);
5379 : 3272 : if (!general_operand (operands[1], data_mode))
5380 : 0 : operands[1] = force_reg (data_mode, operands[1]);
5381 : 3272 : if (!general_operand (operands[2], data_mode))
5382 : 0 : operands[2] = force_reg (data_mode, operands[2]);
5383 : :
5384 : 3272 : x = ix86_expand_int_sse_cmp (operands[0], code, cop0, cop1,
5385 : : operands[1], operands[2], &negate);
5386 : :
5387 : 3272 : if (!x)
5388 : : return false;
5389 : :
5390 : 3272 : ix86_expand_sse_movcc (operands[0], x, operands[1+negate],
5391 : 3272 : operands[2-negate]);
5392 : 3272 : return true;
5393 : : }
5394 : :
5395 : : static bool
5396 : 126590 : ix86_expand_vec_perm_vpermt2 (rtx target, rtx mask, rtx op0, rtx op1,
5397 : : struct expand_vec_perm_d *d)
5398 : : {
5399 : : /* ix86_expand_vec_perm_vpermt2 is called from both const and non-const
5400 : : expander, so args are either in d, or in op0, op1 etc. */
5401 : 126590 : machine_mode mode = GET_MODE (d ? d->op0 : op0);
5402 : 126590 : machine_mode maskmode = mode;
5403 : 126590 : rtx (*gen) (rtx, rtx, rtx, rtx) = NULL;
5404 : :
5405 : 126590 : switch (mode)
5406 : : {
5407 : 23714 : case E_V16QImode:
5408 : 23714 : if (TARGET_AVX512VL && TARGET_AVX512VBMI)
5409 : : gen = gen_avx512vl_vpermt2varv16qi3;
5410 : : break;
5411 : 750 : case E_V32QImode:
5412 : 750 : if (TARGET_AVX512VL && TARGET_AVX512VBMI)
5413 : : gen = gen_avx512vl_vpermt2varv32qi3;
5414 : : break;
5415 : 191 : case E_V64QImode:
5416 : 191 : if (TARGET_AVX512VBMI)
5417 : : gen = gen_avx512bw_vpermt2varv64qi3;
5418 : : break;
5419 : 13349 : case E_V8HImode:
5420 : 13349 : if (TARGET_AVX512VL && TARGET_AVX512BW)
5421 : : gen = gen_avx512vl_vpermt2varv8hi3;
5422 : : break;
5423 : 733 : case E_V16HImode:
5424 : 733 : if (TARGET_AVX512VL && TARGET_AVX512BW)
5425 : : gen = gen_avx512vl_vpermt2varv16hi3;
5426 : : break;
5427 : 383 : case E_V32HImode:
5428 : 383 : if (TARGET_AVX512BW)
5429 : : gen = gen_avx512bw_vpermt2varv32hi3;
5430 : : break;
5431 : 36152 : case E_V4SImode:
5432 : 36152 : if (TARGET_AVX512VL)
5433 : : gen = gen_avx512vl_vpermt2varv4si3;
5434 : : break;
5435 : 1156 : case E_V8SImode:
5436 : 1156 : if (TARGET_AVX512VL)
5437 : : gen = gen_avx512vl_vpermt2varv8si3;
5438 : : break;
5439 : 119 : case E_V16SImode:
5440 : 119 : if (TARGET_AVX512F)
5441 : : gen = gen_avx512f_vpermt2varv16si3;
5442 : : break;
5443 : 9931 : case E_V4SFmode:
5444 : 9931 : if (TARGET_AVX512VL)
5445 : : {
5446 : : gen = gen_avx512vl_vpermt2varv4sf3;
5447 : : maskmode = V4SImode;
5448 : : }
5449 : : break;
5450 : 8661 : case E_V8SFmode:
5451 : 8661 : if (TARGET_AVX512VL)
5452 : : {
5453 : : gen = gen_avx512vl_vpermt2varv8sf3;
5454 : : maskmode = V8SImode;
5455 : : }
5456 : : break;
5457 : 207 : case E_V16SFmode:
5458 : 207 : if (TARGET_AVX512F)
5459 : : {
5460 : : gen = gen_avx512f_vpermt2varv16sf3;
5461 : : maskmode = V16SImode;
5462 : : }
5463 : : break;
5464 : 0 : case E_V2DImode:
5465 : 0 : if (TARGET_AVX512VL)
5466 : : gen = gen_avx512vl_vpermt2varv2di3;
5467 : : break;
5468 : 304 : case E_V4DImode:
5469 : 304 : if (TARGET_AVX512VL)
5470 : : gen = gen_avx512vl_vpermt2varv4di3;
5471 : : break;
5472 : 10 : case E_V8DImode:
5473 : 10 : if (TARGET_AVX512F)
5474 : : gen = gen_avx512f_vpermt2varv8di3;
5475 : : break;
5476 : 0 : case E_V2DFmode:
5477 : 0 : if (TARGET_AVX512VL)
5478 : : {
5479 : : gen = gen_avx512vl_vpermt2varv2df3;
5480 : : maskmode = V2DImode;
5481 : : }
5482 : : break;
5483 : 2197 : case E_V4DFmode:
5484 : 2197 : if (TARGET_AVX512VL)
5485 : : {
5486 : : gen = gen_avx512vl_vpermt2varv4df3;
5487 : : maskmode = V4DImode;
5488 : : }
5489 : : break;
5490 : 194 : case E_V8DFmode:
5491 : 194 : if (TARGET_AVX512F)
5492 : : {
5493 : : gen = gen_avx512f_vpermt2varv8df3;
5494 : : maskmode = V8DImode;
5495 : : }
5496 : : break;
5497 : : default:
5498 : : break;
5499 : : }
5500 : :
5501 : : if (gen == NULL)
5502 : : return false;
5503 : :
5504 : 896 : if (d && d->testing_p)
5505 : : return true;
5506 : :
5507 : : /* ix86_expand_vec_perm_vpermt2 is called from both const and non-const
5508 : : expander, so args are either in d, or in op0, op1 etc. */
5509 : 885 : if (d)
5510 : : {
5511 : 885 : rtx vec[64];
5512 : 885 : target = d->target;
5513 : 885 : op0 = d->op0;
5514 : 885 : op1 = d->op1;
5515 : 16105 : for (int i = 0; i < d->nelt; ++i)
5516 : 15220 : vec[i] = GEN_INT (d->perm[i]);
5517 : 885 : mask = gen_rtx_CONST_VECTOR (maskmode, gen_rtvec_v (d->nelt, vec));
5518 : : }
5519 : :
5520 : 893 : emit_insn (gen (target, force_reg (maskmode, mask), op0, op1));
5521 : 893 : return true;
5522 : : }
5523 : :
5524 : : /* Expand a variable vector permutation. */
5525 : :
5526 : : void
5527 : 10 : ix86_expand_vec_perm (rtx operands[])
5528 : : {
5529 : 10 : rtx target = operands[0];
5530 : 10 : rtx op0 = operands[1];
5531 : 10 : rtx op1 = operands[2];
5532 : 10 : rtx mask = operands[3];
5533 : 10 : rtx t1, t2, t3, t4, t5, t6, t7, t8, vt, vt2, vec[32];
5534 : 10 : machine_mode mode = GET_MODE (op0);
5535 : 10 : machine_mode maskmode = GET_MODE (mask);
5536 : 10 : int w, e, i;
5537 : 10 : bool one_operand_shuffle = rtx_equal_p (op0, op1);
5538 : :
5539 : : /* Number of elements in the vector. */
5540 : 10 : w = GET_MODE_NUNITS (mode);
5541 : 10 : e = GET_MODE_UNIT_SIZE (mode);
5542 : 10 : gcc_assert (w <= 64);
5543 : :
5544 : : /* For HF mode vector, convert it to HI using subreg. */
5545 : 20 : if (GET_MODE_INNER (mode) == HFmode)
5546 : : {
5547 : 6 : machine_mode orig_mode = mode;
5548 : 6 : mode = mode_for_vector (HImode, w).require ();
5549 : 6 : target = lowpart_subreg (mode, target, orig_mode);
5550 : 6 : op0 = lowpart_subreg (mode, op0, orig_mode);
5551 : 6 : op1 = lowpart_subreg (mode, op1, orig_mode);
5552 : : }
5553 : :
5554 : 10 : if (TARGET_AVX512F && one_operand_shuffle)
5555 : : {
5556 : 5 : rtx (*gen) (rtx, rtx, rtx) = NULL;
5557 : 5 : switch (mode)
5558 : : {
5559 : : case E_V16SImode:
5560 : : gen =gen_avx512f_permvarv16si;
5561 : : break;
5562 : 0 : case E_V16SFmode:
5563 : 0 : gen = gen_avx512f_permvarv16sf;
5564 : 0 : break;
5565 : 0 : case E_V8DImode:
5566 : 0 : gen = gen_avx512f_permvarv8di;
5567 : 0 : break;
5568 : 0 : case E_V8DFmode:
5569 : 0 : gen = gen_avx512f_permvarv8df;
5570 : 0 : break;
5571 : : default:
5572 : : break;
5573 : : }
5574 : 0 : if (gen != NULL)
5575 : : {
5576 : 0 : emit_insn (gen (target, op0, mask));
5577 : 8 : return;
5578 : : }
5579 : : }
5580 : :
5581 : 10 : if (ix86_expand_vec_perm_vpermt2 (target, mask, op0, op1, NULL))
5582 : : return;
5583 : :
5584 : 2 : if (TARGET_AVX2)
5585 : : {
5586 : 1 : if (mode == V4DImode || mode == V4DFmode || mode == V16HImode)
5587 : : {
5588 : : /* Unfortunately, the VPERMQ and VPERMPD instructions only support
5589 : : an constant shuffle operand. With a tiny bit of effort we can
5590 : : use VPERMD instead. A re-interpretation stall for V4DFmode is
5591 : : unfortunate but there's no avoiding it.
5592 : : Similarly for V16HImode we don't have instructions for variable
5593 : : shuffling, while for V32QImode we can use after preparing suitable
5594 : : masks vpshufb; vpshufb; vpermq; vpor. */
5595 : :
5596 : : if (mode == V16HImode)
5597 : : {
5598 : : maskmode = mode = V32QImode;
5599 : : w = 32;
5600 : : e = 1;
5601 : : }
5602 : : else
5603 : : {
5604 : : maskmode = mode = V8SImode;
5605 : : w = 8;
5606 : : e = 4;
5607 : : }
5608 : 0 : t1 = gen_reg_rtx (maskmode);
5609 : :
5610 : : /* Replicate the low bits of the V4DImode mask into V8SImode:
5611 : : mask = { A B C D }
5612 : : t1 = { A A B B C C D D }. */
5613 : 0 : for (i = 0; i < w / 2; ++i)
5614 : 0 : vec[i*2 + 1] = vec[i*2] = GEN_INT (i * 2);
5615 : 0 : vt = gen_rtx_CONST_VECTOR (maskmode, gen_rtvec_v (w, vec));
5616 : 0 : vt = force_reg (maskmode, vt);
5617 : 0 : mask = gen_lowpart (maskmode, mask);
5618 : 0 : if (maskmode == V8SImode)
5619 : 0 : emit_insn (gen_avx2_permvarv8si (t1, mask, vt));
5620 : : else
5621 : 0 : emit_insn (gen_avx2_pshufbv32qi3 (t1, mask, vt));
5622 : :
5623 : : /* Multiply the shuffle indicies by two. */
5624 : 0 : t1 = expand_simple_binop (maskmode, PLUS, t1, t1, t1, 1,
5625 : : OPTAB_DIRECT);
5626 : :
5627 : : /* Add one to the odd shuffle indicies:
5628 : : t1 = { A*2, A*2+1, B*2, B*2+1, ... }. */
5629 : 0 : for (i = 0; i < w / 2; ++i)
5630 : : {
5631 : 0 : vec[i * 2] = const0_rtx;
5632 : 0 : vec[i * 2 + 1] = const1_rtx;
5633 : : }
5634 : 0 : vt = gen_rtx_CONST_VECTOR (maskmode, gen_rtvec_v (w, vec));
5635 : 0 : vt = validize_mem (force_const_mem (maskmode, vt));
5636 : 0 : t1 = expand_simple_binop (maskmode, PLUS, t1, vt, t1, 1,
5637 : : OPTAB_DIRECT);
5638 : :
5639 : : /* Continue as if V8SImode (resp. V32QImode) was used initially. */
5640 : 0 : operands[3] = mask = t1;
5641 : 0 : target = gen_reg_rtx (mode);
5642 : 0 : op0 = gen_lowpart (mode, op0);
5643 : 0 : op1 = gen_lowpart (mode, op1);
5644 : : }
5645 : :
5646 : 1 : switch (mode)
5647 : : {
5648 : 1 : case E_V8SImode:
5649 : : /* The VPERMD and VPERMPS instructions already properly ignore
5650 : : the high bits of the shuffle elements. No need for us to
5651 : : perform an AND ourselves. */
5652 : 1 : if (one_operand_shuffle)
5653 : : {
5654 : 0 : emit_insn (gen_avx2_permvarv8si (target, op0, mask));
5655 : 0 : if (target != operands[0])
5656 : 0 : emit_move_insn (operands[0],
5657 : 0 : gen_lowpart (GET_MODE (operands[0]), target));
5658 : : }
5659 : : else
5660 : : {
5661 : 1 : t1 = gen_reg_rtx (V8SImode);
5662 : 1 : t2 = gen_reg_rtx (V8SImode);
5663 : 1 : emit_insn (gen_avx2_permvarv8si (t1, op0, mask));
5664 : 1 : emit_insn (gen_avx2_permvarv8si (t2, op1, mask));
5665 : 1 : goto merge_two;
5666 : : }
5667 : 0 : return;
5668 : :
5669 : 0 : case E_V8SFmode:
5670 : 0 : mask = gen_lowpart (V8SImode, mask);
5671 : 0 : if (one_operand_shuffle)
5672 : 0 : emit_insn (gen_avx2_permvarv8sf (target, op0, mask));
5673 : : else
5674 : : {
5675 : 0 : t1 = gen_reg_rtx (V8SFmode);
5676 : 0 : t2 = gen_reg_rtx (V8SFmode);
5677 : 0 : emit_insn (gen_avx2_permvarv8sf (t1, op0, mask));
5678 : 0 : emit_insn (gen_avx2_permvarv8sf (t2, op1, mask));
5679 : 0 : goto merge_two;
5680 : : }
5681 : 0 : return;
5682 : :
5683 : 0 : case E_V4SImode:
5684 : : /* By combining the two 128-bit input vectors into one 256-bit
5685 : : input vector, we can use VPERMD and VPERMPS for the full
5686 : : two-operand shuffle. */
5687 : 0 : t1 = gen_reg_rtx (V8SImode);
5688 : 0 : t2 = gen_reg_rtx (V8SImode);
5689 : 0 : emit_insn (gen_avx_vec_concatv8si (t1, op0, op1));
5690 : 0 : emit_insn (gen_avx_vec_concatv8si (t2, mask, mask));
5691 : 0 : emit_insn (gen_avx2_permvarv8si (t1, t1, t2));
5692 : 0 : emit_insn (gen_avx_vextractf128v8si (target, t1, const0_rtx));
5693 : 0 : return;
5694 : :
5695 : 0 : case E_V4SFmode:
5696 : 0 : t1 = gen_reg_rtx (V8SFmode);
5697 : 0 : t2 = gen_reg_rtx (V8SImode);
5698 : 0 : mask = gen_lowpart (V4SImode, mask);
5699 : 0 : emit_insn (gen_avx_vec_concatv8sf (t1, op0, op1));
5700 : 0 : emit_insn (gen_avx_vec_concatv8si (t2, mask, mask));
5701 : 0 : emit_insn (gen_avx2_permvarv8sf (t1, t1, t2));
5702 : 0 : emit_insn (gen_avx_vextractf128v8sf (target, t1, const0_rtx));
5703 : 0 : return;
5704 : :
5705 : 0 : case E_V32QImode:
5706 : 0 : t1 = gen_reg_rtx (V32QImode);
5707 : 0 : t2 = gen_reg_rtx (V32QImode);
5708 : 0 : t3 = gen_reg_rtx (V32QImode);
5709 : 0 : vt2 = GEN_INT (-128);
5710 : 0 : vt = gen_const_vec_duplicate (V32QImode, vt2);
5711 : 0 : vt = force_reg (V32QImode, vt);
5712 : 0 : for (i = 0; i < 32; i++)
5713 : 0 : vec[i] = i < 16 ? vt2 : const0_rtx;
5714 : 0 : vt2 = gen_rtx_CONST_VECTOR (V32QImode, gen_rtvec_v (32, vec));
5715 : 0 : vt2 = force_reg (V32QImode, vt2);
5716 : : /* From mask create two adjusted masks, which contain the same
5717 : : bits as mask in the low 7 bits of each vector element.
5718 : : The first mask will have the most significant bit clear
5719 : : if it requests element from the same 128-bit lane
5720 : : and MSB set if it requests element from the other 128-bit lane.
5721 : : The second mask will have the opposite values of the MSB,
5722 : : and additionally will have its 128-bit lanes swapped.
5723 : : E.g. { 07 12 1e 09 ... | 17 19 05 1f ... } mask vector will have
5724 : : t1 { 07 92 9e 09 ... | 17 19 85 1f ... } and
5725 : : t3 { 97 99 05 9f ... | 87 12 1e 89 ... } where each ...
5726 : : stands for other 12 bytes. */
5727 : : /* The bit whether element is from the same lane or the other
5728 : : lane is bit 4, so shift it up by 3 to the MSB position. */
5729 : 0 : t5 = gen_reg_rtx (V4DImode);
5730 : 0 : emit_insn (gen_ashlv4di3 (t5, gen_lowpart (V4DImode, mask),
5731 : : GEN_INT (3)));
5732 : : /* Clear MSB bits from the mask just in case it had them set. */
5733 : 0 : emit_insn (gen_avx2_andnotv32qi3 (t2, vt, mask));
5734 : : /* After this t1 will have MSB set for elements from other lane. */
5735 : 0 : emit_insn (gen_xorv32qi3 (t1, gen_lowpart (V32QImode, t5), vt2));
5736 : : /* Clear bits other than MSB. */
5737 : 0 : emit_insn (gen_andv32qi3 (t1, t1, vt));
5738 : : /* Or in the lower bits from mask into t3. */
5739 : 0 : emit_insn (gen_iorv32qi3 (t3, t1, t2));
5740 : : /* And invert MSB bits in t1, so MSB is set for elements from the same
5741 : : lane. */
5742 : 0 : emit_insn (gen_xorv32qi3 (t1, t1, vt));
5743 : : /* Swap 128-bit lanes in t3. */
5744 : 0 : t6 = gen_reg_rtx (V4DImode);
5745 : 0 : emit_insn (gen_avx2_permv4di_1 (t6, gen_lowpart (V4DImode, t3),
5746 : : const2_rtx, GEN_INT (3),
5747 : : const0_rtx, const1_rtx));
5748 : : /* And or in the lower bits from mask into t1. */
5749 : 0 : emit_insn (gen_iorv32qi3 (t1, t1, t2));
5750 : 0 : if (one_operand_shuffle)
5751 : : {
5752 : : /* Each of these shuffles will put 0s in places where
5753 : : element from the other 128-bit lane is needed, otherwise
5754 : : will shuffle in the requested value. */
5755 : 0 : emit_insn (gen_avx2_pshufbv32qi3 (t3, op0,
5756 : 0 : gen_lowpart (V32QImode, t6)));
5757 : 0 : emit_insn (gen_avx2_pshufbv32qi3 (t1, op0, t1));
5758 : : /* For t3 the 128-bit lanes are swapped again. */
5759 : 0 : t7 = gen_reg_rtx (V4DImode);
5760 : 0 : emit_insn (gen_avx2_permv4di_1 (t7, gen_lowpart (V4DImode, t3),
5761 : : const2_rtx, GEN_INT (3),
5762 : : const0_rtx, const1_rtx));
5763 : : /* And oring both together leads to the result. */
5764 : 0 : emit_insn (gen_iorv32qi3 (target, t1,
5765 : 0 : gen_lowpart (V32QImode, t7)));
5766 : 0 : if (target != operands[0])
5767 : 0 : emit_move_insn (operands[0],
5768 : 0 : gen_lowpart (GET_MODE (operands[0]), target));
5769 : 0 : return;
5770 : : }
5771 : :
5772 : 0 : t4 = gen_reg_rtx (V32QImode);
5773 : : /* Similarly to the above one_operand_shuffle code,
5774 : : just for repeated twice for each operand. merge_two:
5775 : : code will merge the two results together. */
5776 : 0 : emit_insn (gen_avx2_pshufbv32qi3 (t4, op0,
5777 : 0 : gen_lowpart (V32QImode, t6)));
5778 : 0 : emit_insn (gen_avx2_pshufbv32qi3 (t3, op1,
5779 : 0 : gen_lowpart (V32QImode, t6)));
5780 : 0 : emit_insn (gen_avx2_pshufbv32qi3 (t2, op0, t1));
5781 : 0 : emit_insn (gen_avx2_pshufbv32qi3 (t1, op1, t1));
5782 : 0 : t7 = gen_reg_rtx (V4DImode);
5783 : 0 : emit_insn (gen_avx2_permv4di_1 (t7, gen_lowpart (V4DImode, t4),
5784 : : const2_rtx, GEN_INT (3),
5785 : : const0_rtx, const1_rtx));
5786 : 0 : t8 = gen_reg_rtx (V4DImode);
5787 : 0 : emit_insn (gen_avx2_permv4di_1 (t8, gen_lowpart (V4DImode, t3),
5788 : : const2_rtx, GEN_INT (3),
5789 : : const0_rtx, const1_rtx));
5790 : 0 : emit_insn (gen_iorv32qi3 (t4, t2, gen_lowpart (V32QImode, t7)));
5791 : 0 : emit_insn (gen_iorv32qi3 (t3, t1, gen_lowpart (V32QImode, t8)));
5792 : 0 : t1 = t4;
5793 : 0 : t2 = t3;
5794 : 0 : goto merge_two;
5795 : :
5796 : 0 : default:
5797 : 0 : gcc_assert (GET_MODE_SIZE (mode) <= 16);
5798 : : break;
5799 : : }
5800 : : }
5801 : :
5802 : 1 : if (TARGET_XOP)
5803 : : {
5804 : : /* The XOP VPPERM insn supports three inputs. By ignoring the
5805 : : one_operand_shuffle special case, we avoid creating another
5806 : : set of constant vectors in memory. */
5807 : 0 : one_operand_shuffle = false;
5808 : :
5809 : : /* mask = mask & {2*w-1, ...} */
5810 : 0 : vt = GEN_INT (2*w - 1);
5811 : : }
5812 : : else
5813 : : {
5814 : : /* mask = mask & {w-1, ...} */
5815 : 1 : vt = GEN_INT (w - 1);
5816 : : }
5817 : :
5818 : 1 : vt = gen_const_vec_duplicate (maskmode, vt);
5819 : 1 : mask = expand_simple_binop (maskmode, AND, mask, vt,
5820 : : NULL_RTX, 0, OPTAB_DIRECT);
5821 : :
5822 : : /* For non-QImode operations, convert the word permutation control
5823 : : into a byte permutation control. */
5824 : 1 : if (mode != V16QImode)
5825 : : {
5826 : 1 : mask = expand_simple_binop (maskmode, ASHIFT, mask,
5827 : 2 : GEN_INT (exact_log2 (e)),
5828 : : NULL_RTX, 0, OPTAB_DIRECT);
5829 : :
5830 : : /* Convert mask to vector of chars. */
5831 : 1 : mask = force_reg (V16QImode, gen_lowpart (V16QImode, mask));
5832 : :
5833 : : /* Replicate each of the input bytes into byte positions:
5834 : : (v2di) --> {0,0,0,0,0,0,0,0, 8,8,8,8,8,8,8,8}
5835 : : (v4si) --> {0,0,0,0, 4,4,4,4, 8,8,8,8, 12,12,12,12}
5836 : : (v8hi) --> {0,0, 2,2, 4,4, 6,6, ...}. */
5837 : 18 : for (i = 0; i < 16; ++i)
5838 : 16 : vec[i] = GEN_INT (i/e * e);
5839 : 1 : vt = gen_rtx_CONST_VECTOR (V16QImode, gen_rtvec_v (16, vec));
5840 : 1 : vt = validize_mem (force_const_mem (V16QImode, vt));
5841 : 1 : if (TARGET_XOP)
5842 : 0 : emit_insn (gen_xop_pperm (mask, mask, mask, vt));
5843 : : else
5844 : 1 : emit_insn (gen_ssse3_pshufbv16qi3 (mask, mask, vt));
5845 : :
5846 : : /* Convert it into the byte positions by doing
5847 : : mask = mask + {0,1,..,16/w, 0,1,..,16/w, ...} */
5848 : 17 : for (i = 0; i < 16; ++i)
5849 : 16 : vec[i] = GEN_INT (i % e);
5850 : 1 : vt = gen_rtx_CONST_VECTOR (V16QImode, gen_rtvec_v (16, vec));
5851 : 1 : vt = validize_mem (force_const_mem (V16QImode, vt));
5852 : 1 : emit_insn (gen_addv16qi3 (mask, mask, vt));
5853 : : }
5854 : :
5855 : : /* The actual shuffle operations all operate on V16QImode. */
5856 : 1 : op0 = gen_lowpart (V16QImode, op0);
5857 : 1 : op1 = gen_lowpart (V16QImode, op1);
5858 : :
5859 : 1 : if (TARGET_XOP)
5860 : : {
5861 : 0 : if (GET_MODE (target) != V16QImode)
5862 : 0 : target = gen_reg_rtx (V16QImode);
5863 : 0 : emit_insn (gen_xop_pperm (target, op0, op1, mask));
5864 : 0 : if (target != operands[0])
5865 : 0 : emit_move_insn (operands[0],
5866 : 0 : gen_lowpart (GET_MODE (operands[0]), target));
5867 : : }
5868 : 1 : else if (one_operand_shuffle)
5869 : : {
5870 : 1 : if (GET_MODE (target) != V16QImode)
5871 : 1 : target = gen_reg_rtx (V16QImode);
5872 : 1 : emit_insn (gen_ssse3_pshufbv16qi3 (target, op0, mask));
5873 : 1 : if (target != operands[0])
5874 : 1 : emit_move_insn (operands[0],
5875 : 1 : gen_lowpart (GET_MODE (operands[0]), target));
5876 : : }
5877 : : else
5878 : : {
5879 : 0 : rtx xops[6];
5880 : 0 : bool ok;
5881 : :
5882 : : /* Shuffle the two input vectors independently. */
5883 : 0 : t1 = gen_reg_rtx (V16QImode);
5884 : 0 : t2 = gen_reg_rtx (V16QImode);
5885 : 0 : emit_insn (gen_ssse3_pshufbv16qi3 (t1, op0, mask));
5886 : 0 : emit_insn (gen_ssse3_pshufbv16qi3 (t2, op1, mask));
5887 : :
5888 : 1 : merge_two:
5889 : : /* Then merge them together. The key is whether any given control
5890 : : element contained a bit set that indicates the second word. */
5891 : 1 : mask = operands[3];
5892 : 1 : vt = GEN_INT (w);
5893 : 1 : if (maskmode == V2DImode && !TARGET_SSE4_1)
5894 : : {
5895 : : /* Without SSE4.1, we don't have V2DImode EQ. Perform one
5896 : : more shuffle to convert the V2DI input mask into a V4SI
5897 : : input mask. At which point the masking that expand_int_vcond
5898 : : will work as desired. */
5899 : 0 : rtx t3 = gen_reg_rtx (V4SImode);
5900 : 0 : emit_insn (gen_sse2_pshufd_1 (t3, gen_lowpart (V4SImode, mask),
5901 : : const0_rtx, const0_rtx,
5902 : : const2_rtx, const2_rtx));
5903 : 0 : mask = t3;
5904 : 0 : maskmode = V4SImode;
5905 : 0 : e = w = 4;
5906 : : }
5907 : :
5908 : 1 : vt = gen_const_vec_duplicate (maskmode, vt);
5909 : 1 : vt = force_reg (maskmode, vt);
5910 : 1 : mask = expand_simple_binop (maskmode, AND, mask, vt,
5911 : : NULL_RTX, 0, OPTAB_DIRECT);
5912 : :
5913 : 1 : if (GET_MODE (target) != mode)
5914 : 0 : target = gen_reg_rtx (mode);
5915 : 1 : xops[0] = target;
5916 : 1 : xops[1] = gen_lowpart (mode, t2);
5917 : 1 : xops[2] = gen_lowpart (mode, t1);
5918 : 1 : xops[3] = gen_rtx_EQ (maskmode, mask, vt);
5919 : 1 : xops[4] = mask;
5920 : 1 : xops[5] = vt;
5921 : 1 : ok = ix86_expand_int_vcond (xops);
5922 : 1 : gcc_assert (ok);
5923 : 1 : if (target != operands[0])
5924 : 0 : emit_move_insn (operands[0],
5925 : 0 : gen_lowpart (GET_MODE (operands[0]), target));
5926 : : }
5927 : : }
5928 : :
5929 : : /* Extend SRC into next wider integer vector type. UNSIGNED_P is
5930 : : true if we should do zero extension, else sign extension. */
5931 : :
5932 : : void
5933 : 227 : ix86_expand_sse_extend (rtx dest, rtx src, bool unsigned_p)
5934 : : {
5935 : 227 : machine_mode imode = GET_MODE (src);
5936 : 227 : rtx ops[3];
5937 : :
5938 : 227 : switch (imode)
5939 : : {
5940 : 227 : case E_V8QImode:
5941 : 227 : case E_V4QImode:
5942 : 227 : case E_V2QImode:
5943 : 227 : case E_V4HImode:
5944 : 227 : case E_V2HImode:
5945 : 227 : case E_V2SImode:
5946 : 227 : break;
5947 : 0 : default:
5948 : 0 : gcc_unreachable ();
5949 : : }
5950 : :
5951 : 227 : ops[0] = dest;
5952 : :
5953 : 227 : ops[1] = force_reg (imode, src);
5954 : :
5955 : 227 : if (unsigned_p)
5956 : 68 : ops[2] = force_reg (imode, CONST0_RTX (imode));
5957 : : else
5958 : 159 : ops[2] = ix86_expand_sse_cmp (gen_reg_rtx (imode), GT, CONST0_RTX (imode),
5959 : : ops[1], pc_rtx, pc_rtx);
5960 : :
5961 : 227 : ix86_split_mmx_punpck (ops, false);
5962 : 227 : }
5963 : :
5964 : : /* Unpack SRC into the next wider integer vector type. UNSIGNED_P is
5965 : : true if we should do zero extension, else sign extension. HIGH_P is
5966 : : true if we want the N/2 high elements, else the low elements. */
5967 : :
5968 : : void
5969 : 17252 : ix86_expand_sse_unpack (rtx dest, rtx src, bool unsigned_p, bool high_p)
5970 : : {
5971 : 17252 : machine_mode imode = GET_MODE (src);
5972 : 17252 : rtx tmp;
5973 : :
5974 : 17252 : if (TARGET_SSE4_1)
5975 : : {
5976 : 5976 : rtx (*unpack)(rtx, rtx);
5977 : 5976 : rtx (*extract)(rtx, rtx) = NULL;
5978 : 5976 : machine_mode halfmode = BLKmode;
5979 : :
5980 : 5976 : switch (imode)
5981 : : {
5982 : 88 : case E_V64QImode:
5983 : 88 : if (unsigned_p)
5984 : : unpack = gen_avx512bw_zero_extendv32qiv32hi2;
5985 : : else
5986 : 46 : unpack = gen_avx512bw_sign_extendv32qiv32hi2;
5987 : 88 : halfmode = V32QImode;
5988 : 88 : extract
5989 : 88 : = high_p ? gen_vec_extract_hi_v64qi : gen_vec_extract_lo_v64qi;
5990 : : break;
5991 : 637 : case E_V32QImode:
5992 : 637 : if (unsigned_p)
5993 : : unpack = gen_avx2_zero_extendv16qiv16hi2;
5994 : : else
5995 : 114 : unpack = gen_avx2_sign_extendv16qiv16hi2;
5996 : 637 : halfmode = V16QImode;
5997 : 637 : extract
5998 : 637 : = high_p ? gen_vec_extract_hi_v32qi : gen_vec_extract_lo_v32qi;
5999 : : break;
6000 : 66 : case E_V32HImode:
6001 : 66 : if (unsigned_p)
6002 : : unpack = gen_avx512f_zero_extendv16hiv16si2;
6003 : : else
6004 : 44 : unpack = gen_avx512f_sign_extendv16hiv16si2;
6005 : 66 : halfmode = V16HImode;
6006 : 66 : extract
6007 : 66 : = high_p ? gen_vec_extract_hi_v32hi : gen_vec_extract_lo_v32hi;
6008 : : break;
6009 : 415 : case E_V16HImode:
6010 : 415 : if (unsigned_p)
6011 : : unpack = gen_avx2_zero_extendv8hiv8si2;
6012 : : else
6013 : 316 : unpack = gen_avx2_sign_extendv8hiv8si2;
6014 : 415 : halfmode = V8HImode;
6015 : 415 : extract
6016 : 415 : = high_p ? gen_vec_extract_hi_v16hi : gen_vec_extract_lo_v16hi;
6017 : : break;
6018 : 120 : case E_V16SImode:
6019 : 120 : if (unsigned_p)
6020 : : unpack = gen_avx512f_zero_extendv8siv8di2;
6021 : : else
6022 : 112 : unpack = gen_avx512f_sign_extendv8siv8di2;
6023 : 120 : halfmode = V8SImode;
6024 : 120 : extract
6025 : 120 : = high_p ? gen_vec_extract_hi_v16si : gen_vec_extract_lo_v16si;
6026 : : break;
6027 : 356 : case E_V8SImode:
6028 : 356 : if (unsigned_p)
6029 : : unpack = gen_avx2_zero_extendv4siv4di2;
6030 : : else
6031 : 312 : unpack = gen_avx2_sign_extendv4siv4di2;
6032 : 356 : halfmode = V4SImode;
6033 : 356 : extract
6034 : 356 : = high_p ? gen_vec_extract_hi_v8si : gen_vec_extract_lo_v8si;
6035 : : break;
6036 : 2509 : case E_V16QImode:
6037 : 2509 : if (unsigned_p)
6038 : : unpack = gen_sse4_1_zero_extendv8qiv8hi2;
6039 : : else
6040 : 224 : unpack = gen_sse4_1_sign_extendv8qiv8hi2;
6041 : : break;
6042 : 899 : case E_V8HImode:
6043 : 899 : if (unsigned_p)
6044 : : unpack = gen_sse4_1_zero_extendv4hiv4si2;
6045 : : else
6046 : 706 : unpack = gen_sse4_1_sign_extendv4hiv4si2;
6047 : : break;
6048 : 512 : case E_V4SImode:
6049 : 512 : if (unsigned_p)
6050 : : unpack = gen_sse4_1_zero_extendv2siv2di2;
6051 : : else
6052 : 472 : unpack = gen_sse4_1_sign_extendv2siv2di2;
6053 : : break;
6054 : 111 : case E_V8QImode:
6055 : 111 : if (unsigned_p)
6056 : : unpack = gen_sse4_1_zero_extendv4qiv4hi2;
6057 : : else
6058 : 72 : unpack = gen_sse4_1_sign_extendv4qiv4hi2;
6059 : : break;
6060 : 263 : case E_V4HImode:
6061 : 263 : if (unsigned_p)
6062 : : unpack = gen_sse4_1_zero_extendv2hiv2si2;
6063 : : else
6064 : 208 : unpack = gen_sse4_1_sign_extendv2hiv2si2;
6065 : : break;
6066 : 0 : case E_V4QImode:
6067 : 0 : if (unsigned_p)
6068 : : unpack = gen_sse4_1_zero_extendv2qiv2hi2;
6069 : : else
6070 : 0 : unpack = gen_sse4_1_sign_extendv2qiv2hi2;
6071 : : break;
6072 : 0 : default:
6073 : 0 : gcc_unreachable ();
6074 : : }
6075 : :
6076 : 11952 : if (GET_MODE_SIZE (imode) >= 32)
6077 : : {
6078 : 1682 : tmp = gen_reg_rtx (halfmode);
6079 : 1682 : emit_insn (extract (tmp, src));
6080 : : }
6081 : 4294 : else if (high_p)
6082 : : {
6083 : 2134 : switch (GET_MODE_SIZE (imode))
6084 : : {
6085 : 877 : case 16:
6086 : : /* Shift higher 8 bytes to lower 8 bytes. */
6087 : 877 : tmp = gen_reg_rtx (V1TImode);
6088 : 877 : emit_insn (gen_sse2_lshrv1ti3 (tmp, gen_lowpart (V1TImode, src),
6089 : : GEN_INT (64)));
6090 : 877 : break;
6091 : 190 : case 8:
6092 : : /* Shift higher 4 bytes to lower 4 bytes. */
6093 : 190 : tmp = gen_reg_rtx (V1DImode);
6094 : 190 : emit_insn (gen_mmx_lshrv1di3 (tmp, gen_lowpart (V1DImode, src),
6095 : : GEN_INT (32)));
6096 : 190 : break;
6097 : 0 : case 4:
6098 : : /* Shift higher 2 bytes to lower 2 bytes. */
6099 : 0 : tmp = gen_reg_rtx (V1SImode);
6100 : 0 : emit_insn (gen_mmx_lshrv1si3 (tmp, gen_lowpart (V1SImode, src),
6101 : : GEN_INT (16)));
6102 : 0 : break;
6103 : 0 : default:
6104 : 0 : gcc_unreachable ();
6105 : : }
6106 : :
6107 : 1067 : tmp = gen_lowpart (imode, tmp);
6108 : : }
6109 : : else
6110 : : tmp = src;
6111 : :
6112 : 5976 : emit_insn (unpack (dest, tmp));
6113 : : }
6114 : : else
6115 : : {
6116 : 11276 : rtx (*unpack)(rtx, rtx, rtx);
6117 : :
6118 : 11276 : switch (imode)
6119 : : {
6120 : 3132 : case E_V16QImode:
6121 : 3132 : if (high_p)
6122 : : unpack = gen_vec_interleave_highv16qi;
6123 : : else
6124 : 1569 : unpack = gen_vec_interleave_lowv16qi;
6125 : : break;
6126 : 4778 : case E_V8HImode:
6127 : 4778 : if (high_p)
6128 : : unpack = gen_vec_interleave_highv8hi;
6129 : : else
6130 : 2389 : unpack = gen_vec_interleave_lowv8hi;
6131 : : break;
6132 : 2302 : case E_V4SImode:
6133 : 2302 : if (high_p)
6134 : : unpack = gen_vec_interleave_highv4si;
6135 : : else
6136 : 1151 : unpack = gen_vec_interleave_lowv4si;
6137 : : break;
6138 : 364 : case E_V8QImode:
6139 : 364 : if (high_p)
6140 : : unpack = gen_mmx_punpckhbw;
6141 : : else
6142 : 182 : unpack = gen_mmx_punpcklbw;
6143 : : break;
6144 : 690 : case E_V4HImode:
6145 : 690 : if (high_p)
6146 : : unpack = gen_mmx_punpckhwd;
6147 : : else
6148 : 345 : unpack = gen_mmx_punpcklwd;
6149 : : break;
6150 : 10 : case E_V4QImode:
6151 : 10 : if (high_p)
6152 : : unpack = gen_mmx_punpckhbw_low;
6153 : : else
6154 : 5 : unpack = gen_mmx_punpcklbw_low;
6155 : : break;
6156 : 0 : default:
6157 : 0 : gcc_unreachable ();
6158 : : }
6159 : :
6160 : 11276 : if (unsigned_p)
6161 : 4768 : tmp = force_reg (imode, CONST0_RTX (imode));
6162 : : else
6163 : 6508 : tmp = ix86_expand_sse_cmp (gen_reg_rtx (imode), GT, CONST0_RTX (imode),
6164 : : src, pc_rtx, pc_rtx);
6165 : :
6166 : 11276 : rtx tmp2 = gen_reg_rtx (imode);
6167 : 11276 : emit_insn (unpack (tmp2, src, tmp));
6168 : 11276 : emit_move_insn (dest, gen_lowpart (GET_MODE (dest), tmp2));
6169 : : }
6170 : 17252 : }
6171 : :
6172 : : /* Return true if mem is pool constant which contains a const_vector
6173 : : perm index, assign the index to PERM. */
6174 : : bool
6175 : 35 : ix86_extract_perm_from_pool_constant (int* perm, rtx mem)
6176 : : {
6177 : 35 : machine_mode mode = GET_MODE (mem);
6178 : 35 : int nelt = GET_MODE_NUNITS (mode);
6179 : :
6180 : 35 : if (!INTEGRAL_MODE_P (mode))
6181 : : return false;
6182 : :
6183 : : /* Needs to be constant pool. */
6184 : 35 : if (!(MEM_P (mem))
6185 : 35 : || !SYMBOL_REF_P (XEXP (mem, 0))
6186 : 70 : || !CONSTANT_POOL_ADDRESS_P (XEXP (mem, 0)))
6187 : : return false;
6188 : :
6189 : 35 : rtx constant = get_pool_constant (XEXP (mem, 0));
6190 : :
6191 : 35 : if (GET_CODE (constant) != CONST_VECTOR)
6192 : : return false;
6193 : :
6194 : : /* There could be some rtx like
6195 : : (mem/u/c:V16QI (symbol_ref/u:DI ("*.LC1")))
6196 : : but with "*.LC1" refer to V2DI constant vector. */
6197 : 35 : if (GET_MODE (constant) != mode)
6198 : : {
6199 : 0 : constant = simplify_subreg (mode, constant, GET_MODE (constant), 0);
6200 : :
6201 : 0 : if (constant == nullptr || GET_CODE (constant) != CONST_VECTOR)
6202 : : return false;
6203 : : }
6204 : :
6205 : 771 : for (int i = 0; i != nelt; i++)
6206 : 736 : perm[i] = UINTVAL (XVECEXP (constant, 0, i));
6207 : :
6208 : : return true;
6209 : : }
6210 : :
6211 : : /* Split operands 0 and 1 into half-mode parts. Similar to split_double_mode,
6212 : : but works for floating pointer parameters and nonoffsetable memories.
6213 : : For pushes, it returns just stack offsets; the values will be saved
6214 : : in the right order. Maximally three parts are generated. */
6215 : :
6216 : : static int
6217 : 4101732 : ix86_split_to_parts (rtx operand, rtx *parts, machine_mode mode)
6218 : : {
6219 : 4101732 : int size;
6220 : :
6221 : 4101732 : if (!TARGET_64BIT)
6222 : 1568186 : size = mode==XFmode ? 3 : GET_MODE_SIZE (mode) / 4;
6223 : : else
6224 : 6634096 : size = (GET_MODE_SIZE (mode) + 4) / 8;
6225 : :
6226 : 4101732 : gcc_assert (!REG_P (operand) || !MMX_REGNO_P (REGNO (operand)));
6227 : 4101732 : gcc_assert (size >= 2 && size <= 4);
6228 : :
6229 : : /* Optimize constant pool reference to immediates. This is used by fp
6230 : : moves, that force all constants to memory to allow combining. */
6231 : 4101732 : if (MEM_P (operand) && MEM_READONLY_P (operand))
6232 : 35143 : operand = avoid_constant_pool_reference (operand);
6233 : :
6234 : 4101732 : if (MEM_P (operand) && !offsettable_memref_p (operand))
6235 : : {
6236 : : /* The only non-offsetable memories we handle are pushes. */
6237 : 182430 : int ok = push_operand (operand, VOIDmode);
6238 : :
6239 : 182430 : gcc_assert (ok);
6240 : :
6241 : 182430 : operand = copy_rtx (operand);
6242 : 182430 : PUT_MODE (operand, word_mode);
6243 : 182430 : parts[0] = parts[1] = parts[2] = parts[3] = operand;
6244 : 182430 : return size;
6245 : : }
6246 : :
6247 : 3919302 : if (GET_CODE (operand) == CONST_VECTOR)
6248 : : {
6249 : 41894 : scalar_int_mode imode = int_mode_for_mode (mode).require ();
6250 : : /* Caution: if we looked through a constant pool memory above,
6251 : : the operand may actually have a different mode now. That's
6252 : : ok, since we want to pun this all the way back to an integer. */
6253 : 41894 : operand = simplify_subreg (imode, operand, GET_MODE (operand), 0);
6254 : 41894 : gcc_assert (operand != NULL);
6255 : 41894 : mode = imode;
6256 : : }
6257 : :
6258 : 3919302 : if (!TARGET_64BIT)
6259 : : {
6260 : 626807 : if (mode == DImode)
6261 : 496897 : split_double_mode (mode, &operand, 1, &parts[0], &parts[1]);
6262 : : else
6263 : : {
6264 : 129910 : int i;
6265 : :
6266 : 129910 : if (REG_P (operand))
6267 : : {
6268 : 67260 : gcc_assert (reload_completed);
6269 : 201780 : for (i = 0; i < size; i++)
6270 : 134520 : parts[i] = gen_rtx_REG (SImode, REGNO (operand) + i);
6271 : : }
6272 : 62650 : else if (offsettable_memref_p (operand))
6273 : : {
6274 : 61328 : operand = adjust_address (operand, SImode, 0);
6275 : 61328 : parts[0] = operand;
6276 : 123122 : for (i = 1; i < size; i++)
6277 : 61794 : parts[i] = adjust_address (operand, SImode, 4 * i);
6278 : : }
6279 : 1322 : else if (CONST_DOUBLE_P (operand))
6280 : : {
6281 : 1322 : const REAL_VALUE_TYPE *r;
6282 : 1322 : long l[4];
6283 : :
6284 : 1322 : r = CONST_DOUBLE_REAL_VALUE (operand);
6285 : 1322 : switch (mode)
6286 : : {
6287 : 0 : case E_TFmode:
6288 : 0 : real_to_target (l, r, mode);
6289 : 0 : parts[3] = gen_int_mode (l[3], SImode);
6290 : 0 : parts[2] = gen_int_mode (l[2], SImode);
6291 : 0 : break;
6292 : 198 : case E_XFmode:
6293 : : /* We can't use REAL_VALUE_TO_TARGET_LONG_DOUBLE since
6294 : : long double may not be 80-bit. */
6295 : 198 : real_to_target (l, r, mode);
6296 : 198 : parts[2] = gen_int_mode (l[2], SImode);
6297 : 198 : break;
6298 : 1124 : case E_DFmode:
6299 : 1124 : REAL_VALUE_TO_TARGET_DOUBLE (*r, l);
6300 : 1124 : break;
6301 : 0 : default:
6302 : 0 : gcc_unreachable ();
6303 : : }
6304 : 1322 : parts[1] = gen_int_mode (l[1], SImode);
6305 : 1322 : parts[0] = gen_int_mode (l[0], SImode);
6306 : : }
6307 : : else
6308 : 0 : gcc_unreachable ();
6309 : : }
6310 : : }
6311 : : else
6312 : : {
6313 : 3292495 : if (mode == TImode)
6314 : 3277312 : split_double_mode (mode, &operand, 1, &parts[0], &parts[1]);
6315 : 3292495 : if (mode == XFmode || mode == TFmode)
6316 : : {
6317 : 15183 : machine_mode upper_mode = mode==XFmode ? SImode : DImode;
6318 : 15183 : if (REG_P (operand))
6319 : : {
6320 : 1599 : gcc_assert (reload_completed);
6321 : 1599 : parts[0] = gen_rtx_REG (DImode, REGNO (operand) + 0);
6322 : 1599 : parts[1] = gen_rtx_REG (upper_mode, REGNO (operand) + 1);
6323 : : }
6324 : 13584 : else if (offsettable_memref_p (operand))
6325 : : {
6326 : 11620 : operand = adjust_address (operand, DImode, 0);
6327 : 11620 : parts[0] = operand;
6328 : 11620 : parts[1] = adjust_address (operand, upper_mode, 8);
6329 : : }
6330 : 1964 : else if (CONST_DOUBLE_P (operand))
6331 : : {
6332 : 1964 : long l[4];
6333 : :
6334 : 1964 : real_to_target (l, CONST_DOUBLE_REAL_VALUE (operand), mode);
6335 : :
6336 : : /* real_to_target puts 32-bit pieces in each long. */
6337 : 3928 : parts[0] = gen_int_mode ((l[0] & HOST_WIDE_INT_C (0xffffffff))
6338 : 1964 : | ((l[1] & HOST_WIDE_INT_C (0xffffffff))
6339 : 1964 : << 32), DImode);
6340 : :
6341 : 1964 : if (upper_mode == SImode)
6342 : 1584 : parts[1] = gen_int_mode (l[2], SImode);
6343 : : else
6344 : 380 : parts[1]
6345 : 380 : = gen_int_mode ((l[2] & HOST_WIDE_INT_C (0xffffffff))
6346 : 380 : | ((l[3] & HOST_WIDE_INT_C (0xffffffff))
6347 : 380 : << 32), DImode);
6348 : : }
6349 : : else
6350 : 0 : gcc_unreachable ();
6351 : : }
6352 : : }
6353 : :
6354 : : return size;
6355 : : }
6356 : :
6357 : : /* Emit insns to perform a move or push of DI, DF, XF, and TF values.
6358 : : Return false when normal moves are needed; true when all required
6359 : : insns have been emitted. Operands 2-4 contain the input values
6360 : : int the correct order; operands 5-7 contain the output values. */
6361 : :
6362 : : void
6363 : 2063816 : ix86_split_long_move (rtx operands[])
6364 : : {
6365 : 2063816 : rtx part[2][4];
6366 : 2063816 : int nparts, i, j;
6367 : 2063816 : int push = 0;
6368 : 2063816 : int collisions = 0;
6369 : 2063816 : machine_mode mode = GET_MODE (operands[0]);
6370 : 2063816 : bool collisionparts[4];
6371 : :
6372 : : /* The DFmode expanders may ask us to move double.
6373 : : For 64bit target this is single move. By hiding the fact
6374 : : here we simplify i386.md splitters. */
6375 : 3735290 : if (TARGET_64BIT && GET_MODE_SIZE (GET_MODE (operands[0])) == 8)
6376 : : {
6377 : : /* Optimize constant pool reference to immediates. This is used by
6378 : : fp moves, that force all constants to memory to allow combining. */
6379 : :
6380 : 12950 : if (MEM_P (operands[1])
6381 : 12516 : && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
6382 : 13556 : && CONSTANT_POOL_ADDRESS_P (XEXP (operands[1], 0)))
6383 : 117 : operands[1] = get_pool_constant (XEXP (operands[1], 0));
6384 : 12950 : if (push_operand (operands[0], VOIDmode))
6385 : : {
6386 : 12950 : operands[0] = copy_rtx (operands[0]);
6387 : 12950 : PUT_MODE (operands[0], word_mode);
6388 : : }
6389 : : else
6390 : 0 : operands[0] = gen_lowpart (DImode, operands[0]);
6391 : 12950 : operands[1] = gen_lowpart (DImode, operands[1]);
6392 : 12950 : emit_move_insn (operands[0], operands[1]);
6393 : 12950 : return;
6394 : : }
6395 : :
6396 : : /* The only non-offsettable memory we handle is push. */
6397 : 2050866 : if (push_operand (operands[0], VOIDmode))
6398 : : push = 1;
6399 : : else
6400 : 1868436 : gcc_assert (!MEM_P (operands[0])
6401 : : || offsettable_memref_p (operands[0]));
6402 : :
6403 : 2050866 : nparts = ix86_split_to_parts (operands[1], part[1], GET_MODE (operands[0]));
6404 : 2050866 : ix86_split_to_parts (operands[0], part[0], GET_MODE (operands[0]));
6405 : :
6406 : : /* When emitting push, take care for source operands on the stack. */
6407 : 182430 : if (push && MEM_P (operands[1])
6408 : 2144692 : && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
6409 : : {
6410 : 53753 : rtx src_base = XEXP (part[1][nparts - 1], 0);
6411 : :
6412 : : /* Compensate for the stack decrement by 4. */
6413 : 53753 : if (!TARGET_64BIT && nparts == 3
6414 : 49085 : && mode == XFmode && TARGET_128BIT_LONG_DOUBLE)
6415 : 0 : src_base = plus_constant (Pmode, src_base, 4);
6416 : :
6417 : : /* src_base refers to the stack pointer and is
6418 : : automatically decreased by emitted push. */
6419 : 161536 : for (i = 0; i < nparts; i++)
6420 : 107783 : part[1][i] = change_address (part[1][i],
6421 : 107783 : GET_MODE (part[1][i]), src_base);
6422 : : }
6423 : :
6424 : : /* We need to do copy in the right order in case an address register
6425 : : of the source overlaps the destination. */
6426 : 2050866 : if (REG_P (part[0][0]) && MEM_P (part[1][0]))
6427 : : {
6428 : : rtx tmp;
6429 : :
6430 : 2344674 : for (i = 0; i < nparts; i++)
6431 : : {
6432 : 1563116 : collisionparts[i]
6433 : 1563116 : = reg_overlap_mentioned_p (part[0][i], XEXP (part[1][0], 0));
6434 : 1563116 : if (collisionparts[i])
6435 : 16496 : collisions++;
6436 : : }
6437 : :
6438 : : /* Collision in the middle part can be handled by reordering. */
6439 : 781558 : if (collisions == 1 && nparts == 3 && collisionparts [1])
6440 : : {
6441 : 0 : std::swap (part[0][1], part[0][2]);
6442 : 0 : std::swap (part[1][1], part[1][2]);
6443 : : }
6444 : 781558 : else if (collisions == 1
6445 : 781558 : && nparts == 4
6446 : 0 : && (collisionparts [1] || collisionparts [2]))
6447 : : {
6448 : 0 : if (collisionparts [1])
6449 : : {
6450 : 0 : std::swap (part[0][1], part[0][2]);
6451 : 0 : std::swap (part[1][1], part[1][2]);
6452 : : }
6453 : : else
6454 : : {
6455 : 0 : std::swap (part[0][2], part[0][3]);
6456 : 0 : std::swap (part[1][2], part[1][3]);
6457 : : }
6458 : : }
6459 : :
6460 : : /* If there are more collisions, we can't handle it by reordering.
6461 : : Do an lea to the last part and use only one colliding move. */
6462 : 781558 : else if (collisions > 1)
6463 : : {
6464 : 79 : rtx base, addr;
6465 : :
6466 : 79 : collisions = 1;
6467 : :
6468 : 79 : base = part[0][nparts - 1];
6469 : :
6470 : : /* Handle the case when the last part isn't valid for lea.
6471 : : Happens in 64-bit mode storing the 12-byte XFmode. */
6472 : 112 : if (GET_MODE (base) != Pmode)
6473 : 0 : base = gen_rtx_REG (Pmode, REGNO (base));
6474 : :
6475 : 79 : addr = XEXP (part[1][0], 0);
6476 : 79 : if (TARGET_TLS_DIRECT_SEG_REFS)
6477 : : {
6478 : 79 : struct ix86_address parts;
6479 : 79 : int ok = ix86_decompose_address (addr, &parts);
6480 : 79 : gcc_assert (ok);
6481 : : /* It is not valid to use %gs: or %fs: in lea. */
6482 : 79 : gcc_assert (parts.seg == ADDR_SPACE_GENERIC);
6483 : : }
6484 : 79 : emit_insn (gen_rtx_SET (base, addr));
6485 : 79 : part[1][0] = replace_equiv_address (part[1][0], base);
6486 : 158 : for (i = 1; i < nparts; i++)
6487 : : {
6488 : 145 : tmp = plus_constant (Pmode, base, UNITS_PER_WORD * i);
6489 : 79 : part[1][i] = replace_equiv_address (part[1][i], tmp);
6490 : : }
6491 : : }
6492 : : }
6493 : :
6494 : 2050866 : if (push)
6495 : : {
6496 : 182430 : if (!TARGET_64BIT)
6497 : : {
6498 : 157877 : if (nparts == 3)
6499 : : {
6500 : 518 : if (TARGET_128BIT_LONG_DOUBLE && mode == XFmode)
6501 : 0 : emit_insn (gen_add2_insn (stack_pointer_rtx, GEN_INT (-4)));
6502 : 518 : emit_move_insn (part[0][2], part[1][2]);
6503 : : }
6504 : 157359 : else if (nparts == 4)
6505 : : {
6506 : 0 : emit_move_insn (part[0][3], part[1][3]);
6507 : 0 : emit_move_insn (part[0][2], part[1][2]);
6508 : : }
6509 : : }
6510 : : else
6511 : : {
6512 : : /* In 64bit mode we don't have 32bit push available. In case this is
6513 : : register, it is OK - we will just use larger counterpart. We also
6514 : : retype memory - these comes from attempt to avoid REX prefix on
6515 : : moving of second half of TFmode value. */
6516 : 24553 : if (GET_MODE (part[1][1]) == SImode)
6517 : : {
6518 : 10514 : switch (GET_CODE (part[1][1]))
6519 : : {
6520 : 10046 : case MEM:
6521 : 10046 : part[1][1] = adjust_address (part[1][1], DImode, 0);
6522 : 10046 : break;
6523 : :
6524 : 468 : case REG:
6525 : 468 : part[1][1] = gen_rtx_REG (DImode, REGNO (part[1][1]));
6526 : 468 : break;
6527 : :
6528 : 0 : default:
6529 : 0 : gcc_unreachable ();
6530 : : }
6531 : :
6532 : 10514 : if (GET_MODE (part[1][0]) == SImode)
6533 : 0 : part[1][0] = part[1][1];
6534 : : }
6535 : : }
6536 : 182430 : emit_move_insn (part[0][1], part[1][1]);
6537 : 182430 : emit_move_insn (part[0][0], part[1][0]);
6538 : 182430 : return;
6539 : : }
6540 : :
6541 : : /* Choose correct order to not overwrite the source before it is copied. */
6542 : 1868436 : if ((REG_P (part[0][0])
6543 : 1023547 : && REG_P (part[1][1])
6544 : 83543 : && (REGNO (part[0][0]) == REGNO (part[1][1])
6545 : 68010 : || (nparts == 3
6546 : 0 : && REGNO (part[0][0]) == REGNO (part[1][2]))
6547 : 68010 : || (nparts == 4
6548 : 0 : && REGNO (part[0][0]) == REGNO (part[1][3]))))
6549 : 2876450 : || (collisions > 0
6550 : 16417 : && reg_overlap_mentioned_p (part[0][0], XEXP (part[1][0], 0))))
6551 : : {
6552 : 95031 : for (i = 0, j = nparts - 1; i < nparts; i++, j--)
6553 : : {
6554 : 63354 : operands[2 + i] = part[0][j];
6555 : 63354 : operands[6 + i] = part[1][j];
6556 : : }
6557 : : }
6558 : : else
6559 : : {
6560 : 5510350 : for (i = 0; i < nparts; i++)
6561 : : {
6562 : 3673591 : operands[2 + i] = part[0][i];
6563 : 3673591 : operands[6 + i] = part[1][i];
6564 : : }
6565 : : }
6566 : :
6567 : : /* Attempt to locally unCSE nonzero constants. */
6568 : 3736945 : for (j = 0; j < nparts - 1; j++)
6569 : 1868509 : if (CONST_INT_P (operands[6 + j])
6570 : 222888 : && operands[6 + j] != const0_rtx
6571 : 64131 : && REG_P (operands[2 + j]))
6572 : 114312 : for (i = j; i < nparts - 1; i++)
6573 : 57156 : if (CONST_INT_P (operands[7 + i])
6574 : 57156 : && INTVAL (operands[7 + i]) == INTVAL (operands[6 + j]))
6575 : 22374 : operands[7 + i] = operands[2 + j];
6576 : :
6577 : 5605381 : for (i = 0; i < nparts; i++)
6578 : 3736945 : emit_move_insn (operands[2 + i], operands[6 + i]);
6579 : :
6580 : : return;
6581 : : }
6582 : :
6583 : : /* Helper function of ix86_split_ashl used to generate an SImode/DImode
6584 : : left shift by a constant, either using a single shift or
6585 : : a sequence of add instructions. */
6586 : :
6587 : : static void
6588 : 4477 : ix86_expand_ashl_const (rtx operand, int count, machine_mode mode)
6589 : : {
6590 : 4477 : if (count == 1
6591 : 4477 : || (count * ix86_cost->add <= ix86_cost->shift_const
6592 : 0 : && !optimize_insn_for_size_p ()))
6593 : : {
6594 : 16 : while (count-- > 0)
6595 : 8 : emit_insn (gen_add2_insn (operand, operand));
6596 : : }
6597 : : else
6598 : : {
6599 : 4469 : rtx (*insn)(rtx, rtx, rtx);
6600 : :
6601 : 4469 : insn = mode == DImode ? gen_ashlsi3 : gen_ashldi3;
6602 : 4469 : emit_insn (insn (operand, operand, GEN_INT (count)));
6603 : : }
6604 : 4477 : }
6605 : :
6606 : : void
6607 : 10586 : ix86_split_ashl (rtx *operands, rtx scratch, machine_mode mode)
6608 : : {
6609 : 10586 : rtx (*gen_ashl3)(rtx, rtx, rtx);
6610 : 10586 : rtx (*gen_shld)(rtx, rtx, rtx);
6611 : 10586 : int half_width = GET_MODE_BITSIZE (mode) >> 1;
6612 : 10586 : machine_mode half_mode;
6613 : :
6614 : 10586 : rtx low[2], high[2];
6615 : 10586 : int count;
6616 : :
6617 : 10586 : if (CONST_INT_P (operands[2]))
6618 : : {
6619 : 8885 : split_double_mode (mode, operands, 2, low, high);
6620 : 8885 : count = INTVAL (operands[2]) & (GET_MODE_BITSIZE (mode) - 1);
6621 : :
6622 : 8885 : if (count >= half_width)
6623 : : {
6624 : 2473 : emit_move_insn (high[0], low[1]);
6625 : 2473 : ix86_expand_clear (low[0]);
6626 : :
6627 : 2473 : if (count > half_width)
6628 : 151 : ix86_expand_ashl_const (high[0], count - half_width, mode);
6629 : : }
6630 : 6412 : else if (count == 1)
6631 : : {
6632 : 2086 : if (!rtx_equal_p (operands[0], operands[1]))
6633 : 0 : emit_move_insn (operands[0], operands[1]);
6634 : 2086 : rtx x3 = gen_rtx_REG (CCCmode, FLAGS_REG);
6635 : 2086 : rtx x4 = gen_rtx_LTU (mode, x3, const0_rtx);
6636 : 2086 : half_mode = mode == DImode ? SImode : DImode;
6637 : 2086 : emit_insn (gen_add3_cc_overflow_1 (half_mode, low[0],
6638 : : low[0], low[0]));
6639 : 2086 : emit_insn (gen_add3_carry (half_mode, high[0], high[0], high[0],
6640 : : x3, x4));
6641 : : }
6642 : : else
6643 : : {
6644 : 4326 : gen_shld = mode == DImode ? gen_x86_shld : gen_x86_64_shld;
6645 : :
6646 : 4326 : if (!rtx_equal_p (operands[0], operands[1]))
6647 : 0 : emit_move_insn (operands[0], operands[1]);
6648 : :
6649 : 4326 : emit_insn (gen_shld (high[0], low[0], GEN_INT (count)));
6650 : 4326 : ix86_expand_ashl_const (low[0], count, mode);
6651 : : }
6652 : 9160 : return;
6653 : : }
6654 : :
6655 : 1701 : split_double_mode (mode, operands, 1, low, high);
6656 : 1701 : half_mode = mode == DImode ? SImode : DImode;
6657 : :
6658 : 1701 : gen_ashl3 = mode == DImode ? gen_ashlsi3 : gen_ashldi3;
6659 : :
6660 : 1701 : if (operands[1] == const1_rtx)
6661 : : {
6662 : : /* Assuming we've chosen a QImode capable registers, then 1 << N
6663 : : can be done with two 32/64-bit shifts, no branches, no cmoves. */
6664 : 275 : if (ANY_QI_REG_P (low[0]) && ANY_QI_REG_P (high[0]))
6665 : : {
6666 : 163 : rtx s, d, flags = gen_rtx_REG (CCZmode, FLAGS_REG);
6667 : :
6668 : 163 : ix86_expand_clear (low[0]);
6669 : 163 : ix86_expand_clear (high[0]);
6670 : 163 : emit_insn (gen_testqi_ccz_1 (operands[2], GEN_INT (half_width)));
6671 : :
6672 : 163 : d = gen_lowpart (QImode, low[0]);
6673 : 163 : d = gen_rtx_STRICT_LOW_PART (VOIDmode, d);
6674 : 163 : s = gen_rtx_EQ (QImode, flags, const0_rtx);
6675 : 163 : emit_insn (gen_rtx_SET (d, s));
6676 : :
6677 : 163 : d = gen_lowpart (QImode, high[0]);
6678 : 163 : d = gen_rtx_STRICT_LOW_PART (VOIDmode, d);
6679 : 163 : s = gen_rtx_NE (QImode, flags, const0_rtx);
6680 : 163 : emit_insn (gen_rtx_SET (d, s));
6681 : : }
6682 : :
6683 : : /* Otherwise, we can get the same results by manually performing
6684 : : a bit extract operation on bit 5/6, and then performing the two
6685 : : shifts. The two methods of getting 0/1 into low/high are exactly
6686 : : the same size. Avoiding the shift in the bit extract case helps
6687 : : pentium4 a bit; no one else seems to care much either way. */
6688 : : else
6689 : : {
6690 : 112 : rtx (*gen_lshr3)(rtx, rtx, rtx);
6691 : 112 : rtx (*gen_and3)(rtx, rtx, rtx);
6692 : 112 : rtx (*gen_xor3)(rtx, rtx, rtx);
6693 : 112 : HOST_WIDE_INT bits;
6694 : 112 : rtx x;
6695 : :
6696 : 112 : if (mode == DImode)
6697 : : {
6698 : : gen_lshr3 = gen_lshrsi3;
6699 : : gen_and3 = gen_andsi3;
6700 : : gen_xor3 = gen_xorsi3;
6701 : : bits = 5;
6702 : : }
6703 : : else
6704 : : {
6705 : 0 : gen_lshr3 = gen_lshrdi3;
6706 : 0 : gen_and3 = gen_anddi3;
6707 : 0 : gen_xor3 = gen_xordi3;
6708 : 0 : bits = 6;
6709 : : }
6710 : :
6711 : 112 : if (TARGET_PARTIAL_REG_STALL && !optimize_insn_for_size_p ())
6712 : 0 : x = gen_rtx_ZERO_EXTEND (half_mode, operands[2]);
6713 : : else
6714 : 112 : x = gen_lowpart (half_mode, operands[2]);
6715 : 112 : emit_insn (gen_rtx_SET (high[0], x));
6716 : :
6717 : 112 : emit_insn (gen_lshr3 (high[0], high[0], GEN_INT (bits)));
6718 : 112 : emit_insn (gen_and3 (high[0], high[0], const1_rtx));
6719 : 112 : emit_move_insn (low[0], high[0]);
6720 : 112 : emit_insn (gen_xor3 (low[0], low[0], const1_rtx));
6721 : : }
6722 : :
6723 : 275 : emit_insn (gen_ashl3 (low[0], low[0], operands[2]));
6724 : 275 : emit_insn (gen_ashl3 (high[0], high[0], operands[2]));
6725 : 275 : return;
6726 : : }
6727 : :
6728 : 1426 : if (operands[1] == constm1_rtx)
6729 : : {
6730 : : /* For -1 << N, we can avoid the shld instruction, because we
6731 : : know that we're shifting 0...31/63 ones into a -1. */
6732 : 118 : emit_move_insn (low[0], constm1_rtx);
6733 : 118 : if (optimize_insn_for_size_p ())
6734 : 6 : emit_move_insn (high[0], low[0]);
6735 : : else
6736 : 112 : emit_move_insn (high[0], constm1_rtx);
6737 : : }
6738 : : else
6739 : : {
6740 : 1308 : gen_shld = mode == DImode ? gen_x86_shld : gen_x86_64_shld;
6741 : :
6742 : 1308 : if (!rtx_equal_p (operands[0], operands[1]))
6743 : 0 : emit_move_insn (operands[0], operands[1]);
6744 : :
6745 : 1308 : split_double_mode (mode, operands, 1, low, high);
6746 : 1308 : emit_insn (gen_shld (high[0], low[0], operands[2]));
6747 : : }
6748 : :
6749 : 1426 : emit_insn (gen_ashl3 (low[0], low[0], operands[2]));
6750 : :
6751 : 1426 : if (TARGET_CMOVE && scratch)
6752 : : {
6753 : 951 : ix86_expand_clear (scratch);
6754 : 951 : emit_insn (gen_x86_shift_adj_1
6755 : : (half_mode, high[0], low[0], operands[2], scratch));
6756 : : }
6757 : : else
6758 : 475 : emit_insn (gen_x86_shift_adj_2 (half_mode, high[0], low[0], operands[2]));
6759 : : }
6760 : :
6761 : : void
6762 : 6059 : ix86_split_ashr (rtx *operands, rtx scratch, machine_mode mode)
6763 : : {
6764 : 4809 : rtx (*gen_ashr3)(rtx, rtx, rtx)
6765 : 6059 : = mode == DImode ? gen_ashrsi3 : gen_ashrdi3;
6766 : 6059 : rtx (*gen_shrd)(rtx, rtx, rtx);
6767 : 6059 : int half_width = GET_MODE_BITSIZE (mode) >> 1;
6768 : :
6769 : 6059 : rtx low[2], high[2];
6770 : 6059 : int count;
6771 : :
6772 : 6059 : if (CONST_INT_P (operands[2]))
6773 : : {
6774 : 5879 : split_double_mode (mode, operands, 2, low, high);
6775 : 5879 : count = INTVAL (operands[2]) & (GET_MODE_BITSIZE (mode) - 1);
6776 : :
6777 : 11758 : if (count == GET_MODE_BITSIZE (mode) - 1)
6778 : : {
6779 : 82 : emit_move_insn (high[0], high[1]);
6780 : 82 : emit_insn (gen_ashr3 (high[0], high[0],
6781 : 82 : GEN_INT (half_width - 1)));
6782 : 82 : emit_move_insn (low[0], high[0]);
6783 : :
6784 : : }
6785 : 5797 : else if (count >= half_width)
6786 : : {
6787 : 1608 : emit_move_insn (low[0], high[1]);
6788 : 1608 : emit_move_insn (high[0], low[0]);
6789 : 1608 : emit_insn (gen_ashr3 (high[0], high[0],
6790 : 1608 : GEN_INT (half_width - 1)));
6791 : :
6792 : 1608 : if (count > half_width)
6793 : 30 : emit_insn (gen_ashr3 (low[0], low[0],
6794 : 30 : GEN_INT (count - half_width)));
6795 : : }
6796 : 4189 : else if (count == 1
6797 : 799 : && (TARGET_USE_RCR || optimize_size > 1))
6798 : : {
6799 : 1 : if (!rtx_equal_p (operands[0], operands[1]))
6800 : 0 : emit_move_insn (operands[0], operands[1]);
6801 : 1 : if (mode == DImode)
6802 : : {
6803 : 0 : emit_insn (gen_ashrsi3_carry (high[0], high[0]));
6804 : 0 : emit_insn (gen_rcrsi2 (low[0], low[0]));
6805 : : }
6806 : : else
6807 : : {
6808 : 1 : emit_insn (gen_ashrdi3_carry (high[0], high[0]));
6809 : 1 : emit_insn (gen_rcrdi2 (low[0], low[0]));
6810 : : }
6811 : : }
6812 : : else
6813 : : {
6814 : 4188 : gen_shrd = mode == DImode ? gen_x86_shrd : gen_x86_64_shrd;
6815 : :
6816 : 4188 : if (!rtx_equal_p (operands[0], operands[1]))
6817 : 0 : emit_move_insn (operands[0], operands[1]);
6818 : :
6819 : 4188 : emit_insn (gen_shrd (low[0], high[0], GEN_INT (count)));
6820 : 4188 : emit_insn (gen_ashr3 (high[0], high[0], GEN_INT (count)));
6821 : : }
6822 : : }
6823 : : else
6824 : : {
6825 : 180 : machine_mode half_mode;
6826 : :
6827 : 180 : gen_shrd = mode == DImode ? gen_x86_shrd : gen_x86_64_shrd;
6828 : :
6829 : 180 : if (!rtx_equal_p (operands[0], operands[1]))
6830 : 0 : emit_move_insn (operands[0], operands[1]);
6831 : :
6832 : 180 : split_double_mode (mode, operands, 1, low, high);
6833 : 180 : half_mode = mode == DImode ? SImode : DImode;
6834 : :
6835 : 180 : emit_insn (gen_shrd (low[0], high[0], operands[2]));
6836 : 180 : emit_insn (gen_ashr3 (high[0], high[0], operands[2]));
6837 : :
6838 : 180 : if (TARGET_CMOVE && scratch)
6839 : : {
6840 : 142 : emit_move_insn (scratch, high[0]);
6841 : 142 : emit_insn (gen_ashr3 (scratch, scratch,
6842 : 142 : GEN_INT (half_width - 1)));
6843 : 142 : emit_insn (gen_x86_shift_adj_1
6844 : : (half_mode, low[0], high[0], operands[2], scratch));
6845 : : }
6846 : : else
6847 : 38 : emit_insn (gen_x86_shift_adj_3
6848 : : (half_mode, low[0], high[0], operands[2]));
6849 : : }
6850 : 6059 : }
6851 : :
6852 : : void
6853 : 14914 : ix86_split_lshr (rtx *operands, rtx scratch, machine_mode mode)
6854 : : {
6855 : 7552 : rtx (*gen_lshr3)(rtx, rtx, rtx)
6856 : 14914 : = mode == DImode ? gen_lshrsi3 : gen_lshrdi3;
6857 : 14914 : rtx (*gen_shrd)(rtx, rtx, rtx);
6858 : 14914 : int half_width = GET_MODE_BITSIZE (mode) >> 1;
6859 : :
6860 : 14914 : rtx low[2], high[2];
6861 : 14914 : int count;
6862 : :
6863 : 14914 : if (CONST_INT_P (operands[2]))
6864 : : {
6865 : 13521 : split_double_mode (mode, operands, 2, low, high);
6866 : 13521 : count = INTVAL (operands[2]) & (GET_MODE_BITSIZE (mode) - 1);
6867 : :
6868 : 13521 : if (count >= half_width)
6869 : : {
6870 : 8465 : emit_move_insn (low[0], high[1]);
6871 : 8465 : ix86_expand_clear (high[0]);
6872 : :
6873 : 8465 : if (count > half_width)
6874 : 653 : emit_insn (gen_lshr3 (low[0], low[0],
6875 : 653 : GEN_INT (count - half_width)));
6876 : : }
6877 : 5056 : else if (count == 1
6878 : 928 : && (TARGET_USE_RCR || optimize_size > 1))
6879 : : {
6880 : 1 : if (!rtx_equal_p (operands[0], operands[1]))
6881 : 0 : emit_move_insn (operands[0], operands[1]);
6882 : 1 : if (mode == DImode)
6883 : : {
6884 : 0 : emit_insn (gen_lshrsi3_carry (high[0], high[0]));
6885 : 0 : emit_insn (gen_rcrsi2 (low[0], low[0]));
6886 : : }
6887 : : else
6888 : : {
6889 : 1 : emit_insn (gen_lshrdi3_carry (high[0], high[0]));
6890 : 1 : emit_insn (gen_rcrdi2 (low[0], low[0]));
6891 : : }
6892 : : }
6893 : : else
6894 : : {
6895 : 5055 : gen_shrd = mode == DImode ? gen_x86_shrd : gen_x86_64_shrd;
6896 : :
6897 : 5055 : if (!rtx_equal_p (operands[0], operands[1]))
6898 : 0 : emit_move_insn (operands[0], operands[1]);
6899 : :
6900 : 5055 : emit_insn (gen_shrd (low[0], high[0], GEN_INT (count)));
6901 : 5055 : emit_insn (gen_lshr3 (high[0], high[0], GEN_INT (count)));
6902 : : }
6903 : : }
6904 : : else
6905 : : {
6906 : 1393 : machine_mode half_mode;
6907 : :
6908 : 1393 : gen_shrd = mode == DImode ? gen_x86_shrd : gen_x86_64_shrd;
6909 : :
6910 : 1393 : if (!rtx_equal_p (operands[0], operands[1]))
6911 : 0 : emit_move_insn (operands[0], operands[1]);
6912 : :
6913 : 1393 : split_double_mode (mode, operands, 1, low, high);
6914 : 1393 : half_mode = mode == DImode ? SImode : DImode;
6915 : :
6916 : 1393 : emit_insn (gen_shrd (low[0], high[0], operands[2]));
6917 : 1393 : emit_insn (gen_lshr3 (high[0], high[0], operands[2]));
6918 : :
6919 : 1393 : if (TARGET_CMOVE && scratch)
6920 : : {
6921 : 1117 : ix86_expand_clear (scratch);
6922 : 1117 : emit_insn (gen_x86_shift_adj_1
6923 : : (half_mode, low[0], high[0], operands[2], scratch));
6924 : : }
6925 : : else
6926 : 276 : emit_insn (gen_x86_shift_adj_2
6927 : : (half_mode, low[0], high[0], operands[2]));
6928 : : }
6929 : 14914 : }
6930 : :
6931 : : /* Helper function to split TImode ashl under NDD. */
6932 : : void
6933 : 1 : ix86_split_ashl_ndd (rtx *operands, rtx scratch)
6934 : : {
6935 : 1 : gcc_assert (TARGET_APX_NDD);
6936 : 1 : int half_width = GET_MODE_BITSIZE (TImode) >> 1;
6937 : :
6938 : 1 : rtx low[2], high[2];
6939 : 1 : int count;
6940 : :
6941 : 1 : split_double_mode (TImode, operands, 2, low, high);
6942 : 1 : if (CONST_INT_P (operands[2]))
6943 : : {
6944 : 0 : count = INTVAL (operands[2]) & (GET_MODE_BITSIZE (TImode) - 1);
6945 : :
6946 : 0 : if (count >= half_width)
6947 : : {
6948 : 0 : count = count - half_width;
6949 : 0 : if (count == 0)
6950 : : {
6951 : 0 : if (!rtx_equal_p (high[0], low[1]))
6952 : 0 : emit_move_insn (high[0], low[1]);
6953 : : }
6954 : 0 : else if (count == 1)
6955 : 0 : emit_insn (gen_adddi3 (high[0], low[1], low[1]));
6956 : : else
6957 : 0 : emit_insn (gen_ashldi3 (high[0], low[1], GEN_INT (count)));
6958 : :
6959 : 0 : ix86_expand_clear (low[0]);
6960 : : }
6961 : 0 : else if (count == 1)
6962 : : {
6963 : 0 : rtx x3 = gen_rtx_REG (CCCmode, FLAGS_REG);
6964 : 0 : rtx x4 = gen_rtx_LTU (TImode, x3, const0_rtx);
6965 : 0 : emit_insn (gen_add3_cc_overflow_1 (DImode, low[0],
6966 : : low[1], low[1]));
6967 : 0 : emit_insn (gen_add3_carry (DImode, high[0], high[1], high[1],
6968 : : x3, x4));
6969 : : }
6970 : : else
6971 : : {
6972 : 0 : emit_insn (gen_x86_64_shld_ndd (high[0], high[1], low[1],
6973 : : GEN_INT (count)));
6974 : 0 : emit_insn (gen_ashldi3 (low[0], low[1], GEN_INT (count)));
6975 : : }
6976 : : }
6977 : : else
6978 : : {
6979 : 1 : emit_insn (gen_x86_64_shld_ndd (high[0], high[1], low[1],
6980 : : operands[2]));
6981 : 1 : emit_insn (gen_ashldi3 (low[0], low[1], operands[2]));
6982 : 1 : if (TARGET_CMOVE && scratch)
6983 : : {
6984 : 1 : ix86_expand_clear (scratch);
6985 : 1 : emit_insn (gen_x86_shift_adj_1
6986 : : (DImode, high[0], low[0], operands[2], scratch));
6987 : : }
6988 : : else
6989 : 0 : emit_insn (gen_x86_shift_adj_2 (DImode, high[0], low[0], operands[2]));
6990 : : }
6991 : 1 : }
6992 : :
6993 : : /* Helper function to split TImode l/ashr under NDD. */
6994 : : void
6995 : 2 : ix86_split_rshift_ndd (enum rtx_code code, rtx *operands, rtx scratch)
6996 : : {
6997 : 2 : gcc_assert (TARGET_APX_NDD);
6998 : 2 : int half_width = GET_MODE_BITSIZE (TImode) >> 1;
6999 : 2 : bool ashr_p = code == ASHIFTRT;
7000 : 2 : rtx (*gen_shr)(rtx, rtx, rtx) = ashr_p ? gen_ashrdi3
7001 : : : gen_lshrdi3;
7002 : :
7003 : 2 : rtx low[2], high[2];
7004 : 2 : int count;
7005 : :
7006 : 2 : split_double_mode (TImode, operands, 2, low, high);
7007 : 2 : if (CONST_INT_P (operands[2]))
7008 : : {
7009 : 0 : count = INTVAL (operands[2]) & (GET_MODE_BITSIZE (TImode) - 1);
7010 : :
7011 : 0 : if (ashr_p && (count == GET_MODE_BITSIZE (TImode) - 1))
7012 : : {
7013 : 0 : emit_insn (gen_shr (high[0], high[1],
7014 : : GEN_INT (half_width - 1)));
7015 : 0 : emit_move_insn (low[0], high[0]);
7016 : : }
7017 : 0 : else if (count >= half_width)
7018 : : {
7019 : 0 : if (ashr_p)
7020 : 0 : emit_insn (gen_shr (high[0], high[1],
7021 : : GEN_INT (half_width - 1)));
7022 : : else
7023 : 0 : ix86_expand_clear (high[0]);
7024 : :
7025 : 0 : if (count > half_width)
7026 : 0 : emit_insn (gen_shr (low[0], high[1],
7027 : 0 : GEN_INT (count - half_width)));
7028 : : else
7029 : 0 : emit_move_insn (low[0], high[1]);
7030 : : }
7031 : : else
7032 : : {
7033 : 0 : emit_insn (gen_x86_64_shrd_ndd (low[0], low[1], high[1],
7034 : : GEN_INT (count)));
7035 : 0 : emit_insn (gen_shr (high[0], high[1], GEN_INT (count)));
7036 : : }
7037 : : }
7038 : : else
7039 : : {
7040 : 2 : emit_insn (gen_x86_64_shrd_ndd (low[0], low[1], high[1],
7041 : : operands[2]));
7042 : 2 : emit_insn (gen_shr (high[0], high[1], operands[2]));
7043 : :
7044 : 2 : if (TARGET_CMOVE && scratch)
7045 : : {
7046 : 2 : if (ashr_p)
7047 : : {
7048 : 1 : emit_move_insn (scratch, high[0]);
7049 : 1 : emit_insn (gen_shr (scratch, scratch,
7050 : : GEN_INT (half_width - 1)));
7051 : : }
7052 : : else
7053 : 1 : ix86_expand_clear (scratch);
7054 : :
7055 : 2 : emit_insn (gen_x86_shift_adj_1
7056 : : (DImode, low[0], high[0], operands[2], scratch));
7057 : : }
7058 : 0 : else if (ashr_p)
7059 : 0 : emit_insn (gen_x86_shift_adj_3
7060 : : (DImode, low[0], high[0], operands[2]));
7061 : : else
7062 : 0 : emit_insn (gen_x86_shift_adj_2
7063 : : (DImode, low[0], high[0], operands[2]));
7064 : : }
7065 : 2 : }
7066 : :
7067 : : /* Expand move of V1TI mode register X to a new TI mode register. */
7068 : : static rtx
7069 : 17 : ix86_expand_v1ti_to_ti (rtx x)
7070 : : {
7071 : 17 : rtx result = gen_reg_rtx (TImode);
7072 : 17 : if (TARGET_SSE2)
7073 : : {
7074 : 17 : rtx temp = force_reg (V2DImode, gen_lowpart (V2DImode, x));
7075 : 17 : rtx lo = gen_lowpart (DImode, result);
7076 : 17 : emit_insn (gen_vec_extractv2didi (lo, temp, const0_rtx));
7077 : 17 : rtx hi = gen_highpart (DImode, result);
7078 : 17 : emit_insn (gen_vec_extractv2didi (hi, temp, const1_rtx));
7079 : : }
7080 : : else
7081 : 0 : emit_move_insn (result, gen_lowpart (TImode, x));
7082 : 17 : return result;
7083 : : }
7084 : :
7085 : : /* Expand move of TI mode register X to a new V1TI mode register. */
7086 : : static rtx
7087 : 17 : ix86_expand_ti_to_v1ti (rtx x)
7088 : : {
7089 : 17 : if (TARGET_SSE2)
7090 : : {
7091 : 17 : rtx lo = gen_lowpart (DImode, x);
7092 : 17 : rtx hi = gen_highpart (DImode, x);
7093 : 17 : rtx tmp = gen_reg_rtx (V2DImode);
7094 : 17 : emit_insn (gen_vec_concatv2di (tmp, lo, hi));
7095 : 17 : return force_reg (V1TImode, gen_lowpart (V1TImode, tmp));
7096 : : }
7097 : :
7098 : 0 : return force_reg (V1TImode, gen_lowpart (V1TImode, x));
7099 : : }
7100 : :
7101 : : /* Expand V1TI mode shift (of rtx_code CODE) by constant. */
7102 : : void
7103 : 42 : ix86_expand_v1ti_shift (enum rtx_code code, rtx operands[])
7104 : : {
7105 : 42 : rtx op1 = force_reg (V1TImode, operands[1]);
7106 : :
7107 : 42 : if (!CONST_INT_P (operands[2]))
7108 : : {
7109 : 6 : rtx tmp1 = ix86_expand_v1ti_to_ti (op1);
7110 : 6 : rtx tmp2 = gen_reg_rtx (TImode);
7111 : 3 : rtx (*shift) (rtx, rtx, rtx)
7112 : 6 : = (code == ASHIFT) ? gen_ashlti3 : gen_lshrti3;
7113 : 6 : emit_insn (shift (tmp2, tmp1, operands[2]));
7114 : 6 : rtx tmp3 = ix86_expand_ti_to_v1ti (tmp2);
7115 : 6 : emit_move_insn (operands[0], tmp3);
7116 : 6 : return;
7117 : : }
7118 : :
7119 : 36 : HOST_WIDE_INT bits = INTVAL (operands[2]) & 127;
7120 : :
7121 : 36 : if (bits == 0)
7122 : : {
7123 : 0 : emit_move_insn (operands[0], op1);
7124 : 0 : return;
7125 : : }
7126 : :
7127 : 36 : if ((bits & 7) == 0)
7128 : : {
7129 : 0 : rtx tmp = gen_reg_rtx (V1TImode);
7130 : 0 : if (code == ASHIFT)
7131 : 0 : emit_insn (gen_sse2_ashlv1ti3 (tmp, op1, GEN_INT (bits)));
7132 : : else
7133 : 0 : emit_insn (gen_sse2_lshrv1ti3 (tmp, op1, GEN_INT (bits)));
7134 : 0 : emit_move_insn (operands[0], tmp);
7135 : 0 : return;
7136 : : }
7137 : :
7138 : 36 : rtx tmp1 = gen_reg_rtx (V1TImode);
7139 : 36 : if (code == ASHIFT)
7140 : 18 : emit_insn (gen_sse2_ashlv1ti3 (tmp1, op1, GEN_INT (64)));
7141 : : else
7142 : 18 : emit_insn (gen_sse2_lshrv1ti3 (tmp1, op1, GEN_INT (64)));
7143 : :
7144 : : /* tmp2 is operands[1] shifted by 64, in V2DImode. */
7145 : 36 : rtx tmp2 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp1));
7146 : :
7147 : : /* tmp3 will be the V2DImode result. */
7148 : 36 : rtx tmp3 = gen_reg_rtx (V2DImode);
7149 : :
7150 : 36 : if (bits > 64)
7151 : : {
7152 : 18 : if (code == ASHIFT)
7153 : 9 : emit_insn (gen_ashlv2di3 (tmp3, tmp2, GEN_INT (bits - 64)));
7154 : : else
7155 : 9 : emit_insn (gen_lshrv2di3 (tmp3, tmp2, GEN_INT (bits - 64)));
7156 : : }
7157 : : else
7158 : : {
7159 : : /* tmp4 is operands[1], in V2DImode. */
7160 : 18 : rtx tmp4 = force_reg (V2DImode, gen_lowpart (V2DImode, op1));
7161 : :
7162 : 18 : rtx tmp5 = gen_reg_rtx (V2DImode);
7163 : 18 : if (code == ASHIFT)
7164 : 9 : emit_insn (gen_ashlv2di3 (tmp5, tmp4, GEN_INT (bits)));
7165 : : else
7166 : 9 : emit_insn (gen_lshrv2di3 (tmp5, tmp4, GEN_INT (bits)));
7167 : :
7168 : 18 : rtx tmp6 = gen_reg_rtx (V2DImode);
7169 : 18 : if (code == ASHIFT)
7170 : 9 : emit_insn (gen_lshrv2di3 (tmp6, tmp2, GEN_INT (64 - bits)));
7171 : : else
7172 : 9 : emit_insn (gen_ashlv2di3 (tmp6, tmp2, GEN_INT (64 - bits)));
7173 : :
7174 : 18 : emit_insn (gen_iorv2di3 (tmp3, tmp5, tmp6));
7175 : : }
7176 : :
7177 : : /* Convert the result back to V1TImode and store in operands[0]. */
7178 : 36 : rtx tmp7 = force_reg (V1TImode, gen_lowpart (V1TImode, tmp3));
7179 : 36 : emit_move_insn (operands[0], tmp7);
7180 : : }
7181 : :
7182 : : /* Expand V1TI mode rotate (of rtx_code CODE) by constant. */
7183 : : void
7184 : 39 : ix86_expand_v1ti_rotate (enum rtx_code code, rtx operands[])
7185 : : {
7186 : 39 : rtx op1 = force_reg (V1TImode, operands[1]);
7187 : :
7188 : 39 : if (!CONST_INT_P (operands[2]))
7189 : : {
7190 : 8 : rtx tmp1 = ix86_expand_v1ti_to_ti (op1);
7191 : 8 : rtx tmp2 = gen_reg_rtx (TImode);
7192 : 4 : rtx (*rotate) (rtx, rtx, rtx)
7193 : 8 : = (code == ROTATE) ? gen_rotlti3 : gen_rotrti3;
7194 : 8 : emit_insn (rotate (tmp2, tmp1, operands[2]));
7195 : 8 : rtx tmp3 = ix86_expand_ti_to_v1ti (tmp2);
7196 : 8 : emit_move_insn (operands[0], tmp3);
7197 : 8 : return;
7198 : : }
7199 : :
7200 : 31 : HOST_WIDE_INT bits = INTVAL (operands[2]) & 127;
7201 : :
7202 : 31 : if (bits == 0)
7203 : : {
7204 : 0 : emit_move_insn (operands[0], op1);
7205 : 0 : return;
7206 : : }
7207 : :
7208 : 31 : if (code == ROTATERT)
7209 : 16 : bits = 128 - bits;
7210 : :
7211 : 31 : if ((bits & 31) == 0)
7212 : : {
7213 : 5 : rtx tmp2 = gen_reg_rtx (V4SImode);
7214 : 5 : rtx tmp1 = force_reg (V4SImode, gen_lowpart (V4SImode, op1));
7215 : 5 : if (bits == 32)
7216 : 1 : emit_insn (gen_sse2_pshufd (tmp2, tmp1, GEN_INT (0x93)));
7217 : 4 : else if (bits == 64)
7218 : 2 : emit_insn (gen_sse2_pshufd (tmp2, tmp1, GEN_INT (0x4e)));
7219 : : else
7220 : 2 : emit_insn (gen_sse2_pshufd (tmp2, tmp1, GEN_INT (0x39)));
7221 : 5 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp2));
7222 : 5 : return;
7223 : : }
7224 : :
7225 : 26 : if ((bits & 7) == 0)
7226 : : {
7227 : 6 : rtx tmp1 = gen_reg_rtx (V1TImode);
7228 : 6 : rtx tmp2 = gen_reg_rtx (V1TImode);
7229 : 6 : rtx tmp3 = gen_reg_rtx (V1TImode);
7230 : :
7231 : 6 : emit_insn (gen_sse2_ashlv1ti3 (tmp1, op1, GEN_INT (bits)));
7232 : 6 : emit_insn (gen_sse2_lshrv1ti3 (tmp2, op1, GEN_INT (128 - bits)));
7233 : 6 : emit_insn (gen_iorv1ti3 (tmp3, tmp1, tmp2));
7234 : 6 : emit_move_insn (operands[0], tmp3);
7235 : 6 : return;
7236 : : }
7237 : :
7238 : 20 : rtx op1_v4si = force_reg (V4SImode, gen_lowpart (V4SImode, op1));
7239 : :
7240 : 20 : rtx lobits;
7241 : 20 : rtx hibits;
7242 : :
7243 : 20 : switch (bits >> 5)
7244 : : {
7245 : 7 : case 0:
7246 : 7 : lobits = op1_v4si;
7247 : 7 : hibits = gen_reg_rtx (V4SImode);
7248 : 7 : emit_insn (gen_sse2_pshufd (hibits, op1_v4si, GEN_INT (0x93)));
7249 : 7 : break;
7250 : :
7251 : 2 : case 1:
7252 : 2 : lobits = gen_reg_rtx (V4SImode);
7253 : 2 : hibits = gen_reg_rtx (V4SImode);
7254 : 2 : emit_insn (gen_sse2_pshufd (lobits, op1_v4si, GEN_INT (0x93)));
7255 : 2 : emit_insn (gen_sse2_pshufd (hibits, op1_v4si, GEN_INT (0x4e)));
7256 : 2 : break;
7257 : :
7258 : 2 : case 2:
7259 : 2 : lobits = gen_reg_rtx (V4SImode);
7260 : 2 : hibits = gen_reg_rtx (V4SImode);
7261 : 2 : emit_insn (gen_sse2_pshufd (lobits, op1_v4si, GEN_INT (0x4e)));
7262 : 2 : emit_insn (gen_sse2_pshufd (hibits, op1_v4si, GEN_INT (0x39)));
7263 : 2 : break;
7264 : :
7265 : 9 : default:
7266 : 9 : lobits = gen_reg_rtx (V4SImode);
7267 : 9 : emit_insn (gen_sse2_pshufd (lobits, op1_v4si, GEN_INT (0x39)));
7268 : 9 : hibits = op1_v4si;
7269 : 9 : break;
7270 : : }
7271 : :
7272 : 20 : rtx tmp1 = gen_reg_rtx (V4SImode);
7273 : 20 : rtx tmp2 = gen_reg_rtx (V4SImode);
7274 : 20 : rtx tmp3 = gen_reg_rtx (V4SImode);
7275 : :
7276 : 20 : emit_insn (gen_ashlv4si3 (tmp1, lobits, GEN_INT (bits & 31)));
7277 : 20 : emit_insn (gen_lshrv4si3 (tmp2, hibits, GEN_INT (32 - (bits & 31))));
7278 : 20 : emit_insn (gen_iorv4si3 (tmp3, tmp1, tmp2));
7279 : :
7280 : 20 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp3));
7281 : : }
7282 : :
7283 : : /* Expand V1TI mode ashiftrt by constant. */
7284 : : void
7285 : 109 : ix86_expand_v1ti_ashiftrt (rtx operands[])
7286 : : {
7287 : 109 : rtx op1 = force_reg (V1TImode, operands[1]);
7288 : :
7289 : 109 : if (!CONST_INT_P (operands[2]))
7290 : : {
7291 : 3 : rtx tmp1 = ix86_expand_v1ti_to_ti (op1);
7292 : 3 : rtx tmp2 = gen_reg_rtx (TImode);
7293 : 3 : emit_insn (gen_ashrti3 (tmp2, tmp1, operands[2]));
7294 : 3 : rtx tmp3 = ix86_expand_ti_to_v1ti (tmp2);
7295 : 3 : emit_move_insn (operands[0], tmp3);
7296 : 3 : return;
7297 : : }
7298 : :
7299 : 106 : HOST_WIDE_INT bits = INTVAL (operands[2]) & 127;
7300 : :
7301 : 106 : if (bits == 0)
7302 : : {
7303 : 0 : emit_move_insn (operands[0], op1);
7304 : 0 : return;
7305 : : }
7306 : :
7307 : 106 : if (bits == 127)
7308 : : {
7309 : : /* Two operations. */
7310 : 3 : rtx tmp1 = force_reg(V4SImode, gen_lowpart (V4SImode, op1));
7311 : 3 : rtx tmp2 = gen_reg_rtx (V4SImode);
7312 : 3 : emit_insn (gen_sse2_pshufd (tmp2, tmp1, GEN_INT (0xff)));
7313 : :
7314 : 3 : rtx tmp3 = gen_reg_rtx (V4SImode);
7315 : 3 : emit_insn (gen_ashrv4si3 (tmp3, tmp2, GEN_INT (31)));
7316 : :
7317 : 3 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp3));
7318 : 3 : return;
7319 : : }
7320 : :
7321 : 103 : if (bits == 64)
7322 : : {
7323 : : /* Three operations. */
7324 : 3 : rtx tmp1 = force_reg(V4SImode, gen_lowpart (V4SImode, op1));
7325 : 3 : rtx tmp2 = gen_reg_rtx (V4SImode);
7326 : 3 : emit_insn (gen_sse2_pshufd (tmp2, tmp1, GEN_INT (0xff)));
7327 : :
7328 : 3 : rtx tmp3 = gen_reg_rtx (V4SImode);
7329 : 3 : emit_insn (gen_ashrv4si3 (tmp3, tmp2, GEN_INT (31)));
7330 : :
7331 : 3 : rtx tmp4 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp1));
7332 : 3 : rtx tmp5 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp3));
7333 : 3 : rtx tmp6 = gen_reg_rtx (V2DImode);
7334 : 3 : emit_insn (gen_vec_interleave_highv2di (tmp6, tmp4, tmp5));
7335 : :
7336 : 3 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp6));
7337 : 3 : return;
7338 : : }
7339 : :
7340 : 100 : if (bits == 96)
7341 : : {
7342 : : /* Three operations. */
7343 : 3 : rtx tmp1 = force_reg(V4SImode, gen_lowpart (V4SImode, op1));
7344 : 3 : rtx tmp2 = gen_reg_rtx (V4SImode);
7345 : 3 : emit_insn (gen_ashrv4si3 (tmp2, tmp1, GEN_INT (31)));
7346 : :
7347 : 3 : rtx tmp3 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp1));
7348 : 3 : rtx tmp4 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp2));
7349 : 3 : rtx tmp5 = gen_reg_rtx (V2DImode);
7350 : 3 : emit_insn (gen_vec_interleave_highv2di (tmp5, tmp3, tmp4));
7351 : :
7352 : 3 : rtx tmp6 = force_reg(V4SImode, gen_lowpart (V4SImode, tmp5));
7353 : 3 : rtx tmp7 = gen_reg_rtx (V4SImode);
7354 : 3 : emit_insn (gen_sse2_pshufd (tmp7, tmp6, GEN_INT (0xfd)));
7355 : :
7356 : 3 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp7));
7357 : 3 : return;
7358 : : }
7359 : :
7360 : 97 : if (bits >= 111)
7361 : : {
7362 : : /* Three operations. */
7363 : 21 : rtx tmp1 = force_reg (V4SImode, gen_lowpart (V4SImode, op1));
7364 : 21 : rtx tmp2 = gen_reg_rtx (V4SImode);
7365 : 21 : emit_insn (gen_ashrv4si3 (tmp2, tmp1, GEN_INT (bits - 96)));
7366 : :
7367 : 21 : rtx tmp3 = force_reg (V8HImode, gen_lowpart (V8HImode, tmp2));
7368 : 21 : rtx tmp4 = gen_reg_rtx (V8HImode);
7369 : 21 : emit_insn (gen_sse2_pshufhw (tmp4, tmp3, GEN_INT (0xfe)));
7370 : :
7371 : 21 : rtx tmp5 = force_reg (V4SImode, gen_lowpart (V4SImode, tmp4));
7372 : 21 : rtx tmp6 = gen_reg_rtx (V4SImode);
7373 : 21 : emit_insn (gen_sse2_pshufd (tmp6, tmp5, GEN_INT (0xfe)));
7374 : :
7375 : 21 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp6));
7376 : 21 : return;
7377 : : }
7378 : :
7379 : 76 : if (TARGET_AVX2 || TARGET_SSE4_1)
7380 : : {
7381 : : /* Three operations. */
7382 : 50 : if (bits == 32)
7383 : : {
7384 : 2 : rtx tmp1 = force_reg (V4SImode, gen_lowpart (V4SImode, op1));
7385 : 2 : rtx tmp2 = gen_reg_rtx (V4SImode);
7386 : 2 : emit_insn (gen_ashrv4si3 (tmp2, tmp1, GEN_INT (31)));
7387 : :
7388 : 2 : rtx tmp3 = gen_reg_rtx (V1TImode);
7389 : 2 : emit_insn (gen_sse2_lshrv1ti3 (tmp3, op1, GEN_INT (32)));
7390 : :
7391 : 2 : if (TARGET_AVX2)
7392 : : {
7393 : 1 : rtx tmp4 = force_reg (V4SImode, gen_lowpart (V4SImode, tmp3));
7394 : 1 : rtx tmp5 = gen_reg_rtx (V4SImode);
7395 : 1 : emit_insn (gen_avx2_pblenddv4si (tmp5, tmp2, tmp4,
7396 : : GEN_INT (7)));
7397 : :
7398 : 1 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp5));
7399 : : }
7400 : : else
7401 : : {
7402 : 1 : rtx tmp4 = force_reg (V8HImode, gen_lowpart (V8HImode, tmp2));
7403 : 1 : rtx tmp5 = force_reg (V8HImode, gen_lowpart (V8HImode, tmp3));
7404 : 1 : rtx tmp6 = gen_reg_rtx (V8HImode);
7405 : 1 : emit_insn (gen_sse4_1_pblendw (tmp6, tmp4, tmp5,
7406 : : GEN_INT (0x3f)));
7407 : :
7408 : 1 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp6));
7409 : : }
7410 : 2 : return;
7411 : : }
7412 : :
7413 : : /* Three operations. */
7414 : 48 : if (bits == 8 || bits == 16 || bits == 24)
7415 : : {
7416 : 6 : rtx tmp1 = force_reg (V4SImode, gen_lowpart (V4SImode, op1));
7417 : 6 : rtx tmp2 = gen_reg_rtx (V4SImode);
7418 : 6 : emit_insn (gen_ashrv4si3 (tmp2, tmp1, GEN_INT (bits)));
7419 : :
7420 : 6 : rtx tmp3 = gen_reg_rtx (V1TImode);
7421 : 6 : emit_insn (gen_sse2_lshrv1ti3 (tmp3, op1, GEN_INT (bits)));
7422 : :
7423 : 6 : if (TARGET_AVX2)
7424 : : {
7425 : 3 : rtx tmp4 = force_reg (V4SImode, gen_lowpart (V4SImode, tmp3));
7426 : 3 : rtx tmp5 = gen_reg_rtx (V4SImode);
7427 : 3 : emit_insn (gen_avx2_pblenddv4si (tmp5, tmp2, tmp4,
7428 : : GEN_INT (7)));
7429 : :
7430 : 3 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp5));
7431 : : }
7432 : : else
7433 : : {
7434 : 3 : rtx tmp4 = force_reg (V8HImode, gen_lowpart (V8HImode, tmp2));
7435 : 3 : rtx tmp5 = force_reg (V8HImode, gen_lowpart (V8HImode, tmp3));
7436 : 3 : rtx tmp6 = gen_reg_rtx (V8HImode);
7437 : 3 : emit_insn (gen_sse4_1_pblendw (tmp6, tmp4, tmp5,
7438 : : GEN_INT (0x3f)));
7439 : :
7440 : 3 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp6));
7441 : : }
7442 : 6 : return;
7443 : : }
7444 : : }
7445 : :
7446 : 68 : if (bits > 96)
7447 : : {
7448 : : /* Four operations. */
7449 : 3 : rtx tmp1 = force_reg (V4SImode, gen_lowpart (V4SImode, op1));
7450 : 3 : rtx tmp2 = gen_reg_rtx (V4SImode);
7451 : 3 : emit_insn (gen_ashrv4si3 (tmp2, tmp1, GEN_INT (bits - 96)));
7452 : :
7453 : 3 : rtx tmp3 = gen_reg_rtx (V4SImode);
7454 : 3 : emit_insn (gen_ashrv4si3 (tmp3, tmp1, GEN_INT (31)));
7455 : :
7456 : 3 : rtx tmp4 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp2));
7457 : 3 : rtx tmp5 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp3));
7458 : 3 : rtx tmp6 = gen_reg_rtx (V2DImode);
7459 : 3 : emit_insn (gen_vec_interleave_highv2di (tmp6, tmp4, tmp5));
7460 : :
7461 : 3 : rtx tmp7 = force_reg (V4SImode, gen_lowpart (V4SImode, tmp6));
7462 : 3 : rtx tmp8 = gen_reg_rtx (V4SImode);
7463 : 3 : emit_insn (gen_sse2_pshufd (tmp8, tmp7, GEN_INT (0xfd)));
7464 : :
7465 : 3 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp8));
7466 : 3 : return;
7467 : : }
7468 : :
7469 : 65 : if (TARGET_SSE4_1 && (bits == 48 || bits == 80))
7470 : : {
7471 : : /* Four operations. */
7472 : 4 : rtx tmp1 = force_reg (V4SImode, gen_lowpart (V4SImode, op1));
7473 : 4 : rtx tmp2 = gen_reg_rtx (V4SImode);
7474 : 4 : emit_insn (gen_sse2_pshufd (tmp2, tmp1, GEN_INT (0xff)));
7475 : :
7476 : 4 : rtx tmp3 = gen_reg_rtx (V4SImode);
7477 : 4 : emit_insn (gen_ashrv4si3 (tmp3, tmp2, GEN_INT (31)));
7478 : :
7479 : 4 : rtx tmp4 = gen_reg_rtx (V1TImode);
7480 : 4 : emit_insn (gen_sse2_lshrv1ti3 (tmp4, op1, GEN_INT (bits)));
7481 : :
7482 : 4 : rtx tmp5 = force_reg (V8HImode, gen_lowpart (V8HImode, tmp3));
7483 : 4 : rtx tmp6 = force_reg (V8HImode, gen_lowpart (V8HImode, tmp4));
7484 : 4 : rtx tmp7 = gen_reg_rtx (V8HImode);
7485 : 6 : emit_insn (gen_sse4_1_pblendw (tmp7, tmp5, tmp6,
7486 : : GEN_INT (bits == 48 ? 0x1f : 0x07)));
7487 : :
7488 : 4 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp7));
7489 : 4 : return;
7490 : : }
7491 : :
7492 : 61 : if ((bits & 7) == 0)
7493 : : {
7494 : : /* Five operations. */
7495 : 9 : rtx tmp1 = force_reg (V4SImode, gen_lowpart (V4SImode, op1));
7496 : 9 : rtx tmp2 = gen_reg_rtx (V4SImode);
7497 : 9 : emit_insn (gen_sse2_pshufd (tmp2, tmp1, GEN_INT (0xff)));
7498 : :
7499 : 9 : rtx tmp3 = gen_reg_rtx (V4SImode);
7500 : 9 : emit_insn (gen_ashrv4si3 (tmp3, tmp2, GEN_INT (31)));
7501 : :
7502 : 9 : rtx tmp4 = gen_reg_rtx (V1TImode);
7503 : 9 : emit_insn (gen_sse2_lshrv1ti3 (tmp4, op1, GEN_INT (bits)));
7504 : :
7505 : 9 : rtx tmp5 = force_reg (V1TImode, gen_lowpart (V1TImode, tmp3));
7506 : 9 : rtx tmp6 = gen_reg_rtx (V1TImode);
7507 : 9 : emit_insn (gen_sse2_ashlv1ti3 (tmp6, tmp5, GEN_INT (128 - bits)));
7508 : :
7509 : 9 : rtx tmp7 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp4));
7510 : 9 : rtx tmp8 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp6));
7511 : 9 : rtx tmp9 = gen_reg_rtx (V2DImode);
7512 : 9 : emit_insn (gen_iorv2di3 (tmp9, tmp7, tmp8));
7513 : :
7514 : 9 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp9));
7515 : 9 : return;
7516 : : }
7517 : :
7518 : 52 : if (TARGET_AVX2 && bits < 32)
7519 : : {
7520 : : /* Six operations. */
7521 : 9 : rtx tmp1 = force_reg (V4SImode, gen_lowpart (V4SImode, op1));
7522 : 9 : rtx tmp2 = gen_reg_rtx (V4SImode);
7523 : 9 : emit_insn (gen_ashrv4si3 (tmp2, tmp1, GEN_INT (bits)));
7524 : :
7525 : 9 : rtx tmp3 = gen_reg_rtx (V1TImode);
7526 : 9 : emit_insn (gen_sse2_lshrv1ti3 (tmp3, op1, GEN_INT (64)));
7527 : :
7528 : 9 : rtx tmp4 = force_reg (V2DImode, gen_lowpart (V2DImode, op1));
7529 : 9 : rtx tmp5 = gen_reg_rtx (V2DImode);
7530 : 9 : emit_insn (gen_lshrv2di3 (tmp5, tmp4, GEN_INT (bits)));
7531 : :
7532 : 9 : rtx tmp6 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp3));
7533 : 9 : rtx tmp7 = gen_reg_rtx (V2DImode);
7534 : 9 : emit_insn (gen_ashlv2di3 (tmp7, tmp6, GEN_INT (64 - bits)));
7535 : :
7536 : 9 : rtx tmp8 = gen_reg_rtx (V2DImode);
7537 : 9 : emit_insn (gen_iorv2di3 (tmp8, tmp5, tmp7));
7538 : :
7539 : 9 : rtx tmp9 = force_reg (V4SImode, gen_lowpart (V4SImode, tmp8));
7540 : 9 : rtx tmp10 = gen_reg_rtx (V4SImode);
7541 : 9 : emit_insn (gen_avx2_pblenddv4si (tmp10, tmp2, tmp9, GEN_INT (7)));
7542 : :
7543 : 9 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp10));
7544 : 9 : return;
7545 : : }
7546 : :
7547 : 43 : if (TARGET_SSE4_1 && bits < 15)
7548 : : {
7549 : : /* Six operations. */
7550 : 4 : rtx tmp1 = force_reg (V4SImode, gen_lowpart (V4SImode, op1));
7551 : 4 : rtx tmp2 = gen_reg_rtx (V4SImode);
7552 : 4 : emit_insn (gen_ashrv4si3 (tmp2, tmp1, GEN_INT (bits)));
7553 : :
7554 : 4 : rtx tmp3 = gen_reg_rtx (V1TImode);
7555 : 4 : emit_insn (gen_sse2_lshrv1ti3 (tmp3, op1, GEN_INT (64)));
7556 : :
7557 : 4 : rtx tmp4 = force_reg (V2DImode, gen_lowpart (V2DImode, op1));
7558 : 4 : rtx tmp5 = gen_reg_rtx (V2DImode);
7559 : 4 : emit_insn (gen_lshrv2di3 (tmp5, tmp4, GEN_INT (bits)));
7560 : :
7561 : 4 : rtx tmp6 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp3));
7562 : 4 : rtx tmp7 = gen_reg_rtx (V2DImode);
7563 : 4 : emit_insn (gen_ashlv2di3 (tmp7, tmp6, GEN_INT (64 - bits)));
7564 : :
7565 : 4 : rtx tmp8 = gen_reg_rtx (V2DImode);
7566 : 4 : emit_insn (gen_iorv2di3 (tmp8, tmp5, tmp7));
7567 : :
7568 : 4 : rtx tmp9 = force_reg (V8HImode, gen_lowpart (V8HImode, tmp2));
7569 : 4 : rtx tmp10 = force_reg (V8HImode, gen_lowpart (V8HImode, tmp8));
7570 : 4 : rtx tmp11 = gen_reg_rtx (V8HImode);
7571 : 4 : emit_insn (gen_sse4_1_pblendw (tmp11, tmp9, tmp10, GEN_INT (0x3f)));
7572 : :
7573 : 4 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp11));
7574 : 4 : return;
7575 : : }
7576 : :
7577 : 18 : if (bits == 1)
7578 : : {
7579 : : /* Eight operations. */
7580 : 1 : rtx tmp1 = gen_reg_rtx (V1TImode);
7581 : 1 : emit_insn (gen_sse2_lshrv1ti3 (tmp1, op1, GEN_INT (64)));
7582 : :
7583 : 1 : rtx tmp2 = force_reg (V2DImode, gen_lowpart (V2DImode, op1));
7584 : 1 : rtx tmp3 = gen_reg_rtx (V2DImode);
7585 : 1 : emit_insn (gen_lshrv2di3 (tmp3, tmp2, GEN_INT (1)));
7586 : :
7587 : 1 : rtx tmp4 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp1));
7588 : 1 : rtx tmp5 = gen_reg_rtx (V2DImode);
7589 : 1 : emit_insn (gen_ashlv2di3 (tmp5, tmp4, GEN_INT (63)));
7590 : :
7591 : 1 : rtx tmp6 = gen_reg_rtx (V2DImode);
7592 : 1 : emit_insn (gen_iorv2di3 (tmp6, tmp3, tmp5));
7593 : :
7594 : 1 : rtx tmp7 = gen_reg_rtx (V2DImode);
7595 : 1 : emit_insn (gen_lshrv2di3 (tmp7, tmp2, GEN_INT (63)));
7596 : :
7597 : 1 : rtx tmp8 = force_reg (V4SImode, gen_lowpart (V4SImode, tmp7));
7598 : 1 : rtx tmp9 = gen_reg_rtx (V4SImode);
7599 : 1 : emit_insn (gen_sse2_pshufd (tmp9, tmp8, GEN_INT (0xbf)));
7600 : :
7601 : 1 : rtx tmp10 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp9));
7602 : 1 : rtx tmp11 = gen_reg_rtx (V2DImode);
7603 : 1 : emit_insn (gen_ashlv2di3 (tmp11, tmp10, GEN_INT (31)));
7604 : :
7605 : 1 : rtx tmp12 = gen_reg_rtx (V2DImode);
7606 : 1 : emit_insn (gen_iorv2di3 (tmp12, tmp6, tmp11));
7607 : :
7608 : 1 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp12));
7609 : 1 : return;
7610 : : }
7611 : :
7612 : 38 : if (bits > 64)
7613 : : {
7614 : : /* Eight operations. */
7615 : 12 : rtx tmp1 = force_reg (V4SImode, gen_lowpart (V4SImode, op1));
7616 : 12 : rtx tmp2 = gen_reg_rtx (V4SImode);
7617 : 12 : emit_insn (gen_sse2_pshufd (tmp2, tmp1, GEN_INT (0xff)));
7618 : :
7619 : 12 : rtx tmp3 = gen_reg_rtx (V4SImode);
7620 : 12 : emit_insn (gen_ashrv4si3 (tmp3, tmp2, GEN_INT (31)));
7621 : :
7622 : 12 : rtx tmp4 = gen_reg_rtx (V1TImode);
7623 : 12 : emit_insn (gen_sse2_lshrv1ti3 (tmp4, op1, GEN_INT (64)));
7624 : :
7625 : 12 : rtx tmp5 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp4));
7626 : 12 : rtx tmp6 = gen_reg_rtx (V2DImode);
7627 : 12 : emit_insn (gen_lshrv2di3 (tmp6, tmp5, GEN_INT (bits - 64)));
7628 : :
7629 : 12 : rtx tmp7 = force_reg (V1TImode, gen_lowpart (V1TImode, tmp3));
7630 : 12 : rtx tmp8 = gen_reg_rtx (V1TImode);
7631 : 12 : emit_insn (gen_sse2_ashlv1ti3 (tmp8, tmp7, GEN_INT (64)));
7632 : :
7633 : 12 : rtx tmp9 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp3));
7634 : 12 : rtx tmp10 = gen_reg_rtx (V2DImode);
7635 : 12 : emit_insn (gen_ashlv2di3 (tmp10, tmp9, GEN_INT (128 - bits)));
7636 : :
7637 : 12 : rtx tmp11 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp8));
7638 : 12 : rtx tmp12 = gen_reg_rtx (V2DImode);
7639 : 12 : emit_insn (gen_iorv2di3 (tmp12, tmp10, tmp11));
7640 : :
7641 : 12 : rtx tmp13 = gen_reg_rtx (V2DImode);
7642 : 12 : emit_insn (gen_iorv2di3 (tmp13, tmp6, tmp12));
7643 : :
7644 : 12 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp13));
7645 : : }
7646 : : else
7647 : : {
7648 : : /* Nine operations. */
7649 : 26 : rtx tmp1 = force_reg (V4SImode, gen_lowpart (V4SImode, op1));
7650 : 26 : rtx tmp2 = gen_reg_rtx (V4SImode);
7651 : 26 : emit_insn (gen_sse2_pshufd (tmp2, tmp1, GEN_INT (0xff)));
7652 : :
7653 : 26 : rtx tmp3 = gen_reg_rtx (V4SImode);
7654 : 26 : emit_insn (gen_ashrv4si3 (tmp3, tmp2, GEN_INT (31)));
7655 : :
7656 : 26 : rtx tmp4 = gen_reg_rtx (V1TImode);
7657 : 26 : emit_insn (gen_sse2_lshrv1ti3 (tmp4, op1, GEN_INT (64)));
7658 : :
7659 : 26 : rtx tmp5 = force_reg (V2DImode, gen_lowpart (V2DImode, op1));
7660 : 26 : rtx tmp6 = gen_reg_rtx (V2DImode);
7661 : 26 : emit_insn (gen_lshrv2di3 (tmp6, tmp5, GEN_INT (bits)));
7662 : :
7663 : 26 : rtx tmp7 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp4));
7664 : 26 : rtx tmp8 = gen_reg_rtx (V2DImode);
7665 : 26 : emit_insn (gen_ashlv2di3 (tmp8, tmp7, GEN_INT (64 - bits)));
7666 : :
7667 : 26 : rtx tmp9 = gen_reg_rtx (V2DImode);
7668 : 26 : emit_insn (gen_iorv2di3 (tmp9, tmp6, tmp8));
7669 : :
7670 : 26 : rtx tmp10 = force_reg (V1TImode, gen_lowpart (V1TImode, tmp3));
7671 : 26 : rtx tmp11 = gen_reg_rtx (V1TImode);
7672 : 26 : emit_insn (gen_sse2_ashlv1ti3 (tmp11, tmp10, GEN_INT (64)));
7673 : :
7674 : 26 : rtx tmp12 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp11));
7675 : 26 : rtx tmp13 = gen_reg_rtx (V2DImode);
7676 : 26 : emit_insn (gen_ashlv2di3 (tmp13, tmp12, GEN_INT (64 - bits)));
7677 : :
7678 : 26 : rtx tmp14 = gen_reg_rtx (V2DImode);
7679 : 26 : emit_insn (gen_iorv2di3 (tmp14, tmp9, tmp13));
7680 : :
7681 : 26 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp14));
7682 : : }
7683 : : }
7684 : :
7685 : : /* Expand V2DI mode ashiftrt. */
7686 : : void
7687 : 362 : ix86_expand_v2di_ashiftrt (rtx operands[])
7688 : : {
7689 : 362 : if (operands[2] == const0_rtx)
7690 : : {
7691 : 0 : emit_move_insn (operands[0], operands[1]);
7692 : 0 : return;
7693 : : }
7694 : :
7695 : 362 : if (TARGET_SSE4_2
7696 : 133 : && CONST_INT_P (operands[2])
7697 : 133 : && UINTVAL (operands[2]) >= 63
7698 : 370 : && !optimize_insn_for_size_p ())
7699 : : {
7700 : 8 : rtx zero = force_reg (V2DImode, CONST0_RTX (V2DImode));
7701 : 8 : emit_insn (gen_sse4_2_gtv2di3 (operands[0], zero, operands[1]));
7702 : 8 : return;
7703 : : }
7704 : :
7705 : 354 : if (CONST_INT_P (operands[2])
7706 : 346 : && (!TARGET_XOP || UINTVAL (operands[2]) >= 63))
7707 : : {
7708 : 250 : vec_perm_builder sel (4, 4, 1);
7709 : 250 : sel.quick_grow (4);
7710 : 250 : rtx arg0, arg1;
7711 : 250 : rtx op1 = lowpart_subreg (V4SImode,
7712 : : force_reg (V2DImode, operands[1]),
7713 : : V2DImode);
7714 : 250 : rtx target = gen_reg_rtx (V4SImode);
7715 : 250 : if (UINTVAL (operands[2]) >= 63)
7716 : : {
7717 : 84 : arg0 = arg1 = gen_reg_rtx (V4SImode);
7718 : 84 : emit_insn (gen_ashrv4si3 (arg0, op1, GEN_INT (31)));
7719 : 84 : sel[0] = 1;
7720 : 84 : sel[1] = 1;
7721 : 84 : sel[2] = 3;
7722 : 84 : sel[3] = 3;
7723 : : }
7724 : 166 : else if (INTVAL (operands[2]) > 32)
7725 : : {
7726 : 15 : arg0 = gen_reg_rtx (V4SImode);
7727 : 15 : arg1 = gen_reg_rtx (V4SImode);
7728 : 15 : emit_insn (gen_ashrv4si3 (arg1, op1, GEN_INT (31)));
7729 : 15 : emit_insn (gen_ashrv4si3 (arg0, op1,
7730 : 15 : GEN_INT (INTVAL (operands[2]) - 32)));
7731 : 15 : sel[0] = 1;
7732 : 15 : sel[1] = 5;
7733 : 15 : sel[2] = 3;
7734 : 15 : sel[3] = 7;
7735 : : }
7736 : 151 : else if (INTVAL (operands[2]) == 32)
7737 : : {
7738 : 3 : arg0 = op1;
7739 : 3 : arg1 = gen_reg_rtx (V4SImode);
7740 : 3 : emit_insn (gen_ashrv4si3 (arg1, op1, GEN_INT (31)));
7741 : 3 : sel[0] = 1;
7742 : 3 : sel[1] = 5;
7743 : 3 : sel[2] = 3;
7744 : 3 : sel[3] = 7;
7745 : : }
7746 : : else
7747 : : {
7748 : 148 : arg0 = gen_reg_rtx (V2DImode);
7749 : 148 : arg1 = gen_reg_rtx (V4SImode);
7750 : 148 : emit_insn (gen_lshrv2di3 (arg0, operands[1], operands[2]));
7751 : 148 : emit_insn (gen_ashrv4si3 (arg1, op1, operands[2]));
7752 : 148 : arg0 = lowpart_subreg (V4SImode, arg0, V2DImode);
7753 : 148 : sel[0] = 0;
7754 : 148 : sel[1] = 5;
7755 : 148 : sel[2] = 2;
7756 : 148 : sel[3] = 7;
7757 : : }
7758 : 334 : vec_perm_indices indices (sel, arg0 != arg1 ? 2 : 1, 4);
7759 : 250 : rtx op0 = operands[0];
7760 : 250 : bool ok = targetm.vectorize.vec_perm_const (V4SImode, V4SImode,
7761 : : target, arg0, arg1,
7762 : : indices);
7763 : 250 : gcc_assert (ok);
7764 : 250 : emit_move_insn (op0, lowpart_subreg (V2DImode, target, V4SImode));
7765 : 250 : return;
7766 : 250 : }
7767 : 104 : if (!TARGET_XOP)
7768 : : {
7769 : 8 : rtx zero = force_reg (V2DImode, CONST0_RTX (V2DImode));
7770 : 8 : rtx zero_or_all_ones;
7771 : 8 : if (TARGET_SSE4_2)
7772 : : {
7773 : 0 : zero_or_all_ones = gen_reg_rtx (V2DImode);
7774 : 0 : emit_insn (gen_sse4_2_gtv2di3 (zero_or_all_ones, zero,
7775 : : operands[1]));
7776 : : }
7777 : : else
7778 : : {
7779 : 8 : rtx temp = gen_reg_rtx (V4SImode);
7780 : 8 : emit_insn (gen_ashrv4si3 (temp,
7781 : : lowpart_subreg (V4SImode,
7782 : : force_reg (V2DImode,
7783 : : operands[1]),
7784 : : V2DImode),
7785 : : GEN_INT (31)));
7786 : 8 : zero_or_all_ones = gen_reg_rtx (V4SImode);
7787 : 8 : emit_insn (gen_sse2_pshufd_1 (zero_or_all_ones, temp,
7788 : : const1_rtx, const1_rtx,
7789 : : GEN_INT (3), GEN_INT (3)));
7790 : 8 : zero_or_all_ones = lowpart_subreg (V2DImode, zero_or_all_ones,
7791 : : V4SImode);
7792 : : }
7793 : 8 : rtx lshr_res = gen_reg_rtx (V2DImode);
7794 : 8 : emit_insn (gen_lshrv2di3 (lshr_res, operands[1], operands[2]));
7795 : 8 : rtx ashl_res = gen_reg_rtx (V2DImode);
7796 : 8 : rtx amount;
7797 : 8 : if (TARGET_64BIT)
7798 : : {
7799 : 8 : amount = gen_reg_rtx (DImode);
7800 : 8 : emit_insn (gen_subdi3 (amount, force_reg (DImode, GEN_INT (64)),
7801 : : operands[2]));
7802 : : }
7803 : : else
7804 : : {
7805 : 0 : rtx temp = gen_reg_rtx (SImode);
7806 : 0 : emit_insn (gen_subsi3 (temp, force_reg (SImode, GEN_INT (64)),
7807 : : lowpart_subreg (SImode, operands[2],
7808 : : DImode)));
7809 : 0 : amount = gen_reg_rtx (V4SImode);
7810 : 0 : emit_insn (gen_vec_setv4si_0 (amount, CONST0_RTX (V4SImode),
7811 : : temp));
7812 : : }
7813 : 8 : amount = lowpart_subreg (DImode, amount, GET_MODE (amount));
7814 : 8 : emit_insn (gen_ashlv2di3 (ashl_res, zero_or_all_ones, amount));
7815 : 8 : emit_insn (gen_iorv2di3 (operands[0], lshr_res, ashl_res));
7816 : 8 : return;
7817 : : }
7818 : :
7819 : 96 : rtx reg = gen_reg_rtx (V2DImode);
7820 : 96 : rtx par;
7821 : 96 : bool negate = false;
7822 : 96 : int i;
7823 : :
7824 : 96 : if (CONST_INT_P (operands[2]))
7825 : 96 : operands[2] = GEN_INT (-INTVAL (operands[2]));
7826 : : else
7827 : : negate = true;
7828 : :
7829 : 96 : par = gen_rtx_PARALLEL (V2DImode, rtvec_alloc (2));
7830 : 288 : for (i = 0; i < 2; i++)
7831 : 192 : XVECEXP (par, 0, i) = operands[2];
7832 : :
7833 : 96 : emit_insn (gen_vec_initv2didi (reg, par));
7834 : :
7835 : 96 : if (negate)
7836 : 0 : emit_insn (gen_negv2di2 (reg, reg));
7837 : :
7838 : 96 : emit_insn (gen_xop_shav2di3 (operands[0], operands[1], reg));
7839 : : }
7840 : :
7841 : : /* Replace all occurrences of REG FROM with REG TO in X, including
7842 : : occurrences with different modes. */
7843 : :
7844 : : rtx
7845 : 39219 : ix86_replace_reg_with_reg (rtx x, rtx from, rtx to)
7846 : : {
7847 : 39219 : gcc_checking_assert (REG_P (from)
7848 : : && REG_P (to)
7849 : : && GET_MODE (from) == GET_MODE (to));
7850 : 39219 : if (!reg_overlap_mentioned_p (from, x))
7851 : : return x;
7852 : 46 : rtx ret = copy_rtx (x);
7853 : 46 : subrtx_ptr_iterator::array_type array;
7854 : 218 : FOR_EACH_SUBRTX_PTR (iter, array, &ret, NONCONST)
7855 : : {
7856 : 172 : rtx *loc = *iter;
7857 : 172 : x = *loc;
7858 : 172 : if (REG_P (x) && REGNO (x) == REGNO (from))
7859 : : {
7860 : 46 : if (x == from)
7861 : 46 : *loc = to;
7862 : : else
7863 : : {
7864 : 0 : gcc_checking_assert (REG_NREGS (x) == 1);
7865 : 0 : *loc = gen_rtx_REG (GET_MODE (x), REGNO (to));
7866 : : }
7867 : : }
7868 : : }
7869 : 46 : return ret;
7870 : 46 : }
7871 : :
7872 : : /* Return mode for the memcpy/memset loop counter. Prefer SImode over
7873 : : DImode for constant loop counts. */
7874 : :
7875 : : static machine_mode
7876 : 24336 : counter_mode (rtx count_exp)
7877 : : {
7878 : 6279 : if (GET_MODE (count_exp) != VOIDmode)
7879 : 17710 : return GET_MODE (count_exp);
7880 : 6626 : if (!CONST_INT_P (count_exp))
7881 : 0 : return Pmode;
7882 : : if (TARGET_64BIT && (INTVAL (count_exp) & ~0xffffffff))
7883 : : return DImode;
7884 : : return SImode;
7885 : : }
7886 : :
7887 : : /* When ISSETMEM is FALSE, output simple loop to move memory pointer to SRCPTR
7888 : : to DESTPTR via chunks of MODE unrolled UNROLL times, overall size is COUNT
7889 : : specified in bytes. When ISSETMEM is TRUE, output the equivalent loop to set
7890 : : memory by VALUE (supposed to be in MODE).
7891 : :
7892 : : The size is rounded down to whole number of chunk size moved at once.
7893 : : SRCMEM and DESTMEM provide MEMrtx to feed proper aliasing info. */
7894 : :
7895 : :
7896 : : static void
7897 : 17618 : expand_set_or_cpymem_via_loop (rtx destmem, rtx srcmem,
7898 : : rtx destptr, rtx srcptr, rtx value,
7899 : : rtx count, machine_mode mode, int unroll,
7900 : : int expected_size, bool issetmem)
7901 : : {
7902 : 17618 : rtx_code_label *out_label = nullptr;
7903 : 17618 : rtx_code_label *top_label = nullptr;
7904 : 17618 : rtx iter, tmp;
7905 : 17618 : machine_mode iter_mode = counter_mode (count);
7906 : 17618 : int piece_size_n = GET_MODE_SIZE (mode) * unroll;
7907 : 17618 : rtx piece_size = GEN_INT (piece_size_n);
7908 : 35236 : rtx piece_size_mask = GEN_INT (~((GET_MODE_SIZE (mode) * unroll) - 1));
7909 : 17618 : rtx size;
7910 : 17618 : int i;
7911 : 17618 : int loop_count;
7912 : :
7913 : 17618 : if (expected_size != -1 && CONST_INT_P (count))
7914 : 6556 : loop_count = INTVAL (count) / GET_MODE_SIZE (mode) / unroll;
7915 : : else
7916 : : loop_count = -1;
7917 : :
7918 : : /* Don't generate the loop if the loop count is 1. */
7919 : 6556 : if (loop_count != 1)
7920 : : {
7921 : 17617 : top_label = gen_label_rtx ();
7922 : 17617 : out_label = gen_label_rtx ();
7923 : : }
7924 : 17618 : iter = gen_reg_rtx (iter_mode);
7925 : :
7926 : 17618 : size = expand_simple_binop (iter_mode, AND, count, piece_size_mask,
7927 : : NULL, 1, OPTAB_DIRECT);
7928 : : /* Those two should combine. */
7929 : 17618 : if (piece_size == const1_rtx)
7930 : : {
7931 : 4833 : emit_cmp_and_jump_insns (size, const0_rtx, EQ, NULL_RTX, iter_mode,
7932 : : true, out_label);
7933 : 4833 : predict_jump (REG_BR_PROB_BASE * 10 / 100);
7934 : : }
7935 : 17618 : emit_move_insn (iter, const0_rtx);
7936 : :
7937 : 17618 : if (loop_count != 1)
7938 : 17617 : emit_label (top_label);
7939 : :
7940 : 20419 : tmp = convert_modes (Pmode, iter_mode, iter, true);
7941 : :
7942 : : /* This assert could be relaxed - in this case we'll need to compute
7943 : : smallest power of two, containing in PIECE_SIZE_N and pass it to
7944 : : offset_address. */
7945 : 17618 : gcc_assert ((piece_size_n & (piece_size_n - 1)) == 0);
7946 : 17618 : destmem = offset_address (destmem, tmp, piece_size_n);
7947 : 17618 : destmem = adjust_address (destmem, mode, 0);
7948 : :
7949 : 17618 : if (!issetmem)
7950 : : {
7951 : 11391 : srcmem = offset_address (srcmem, copy_rtx (tmp), piece_size_n);
7952 : 11391 : srcmem = adjust_address (srcmem, mode, 0);
7953 : :
7954 : : /* When unrolling for chips that reorder memory reads and writes,
7955 : : we can save registers by using single temporary.
7956 : : Also using 4 temporaries is overkill in 32bit mode. */
7957 : 11391 : if (!TARGET_64BIT && 0)
7958 : : {
7959 : : for (i = 0; i < unroll; i++)
7960 : : {
7961 : : if (i)
7962 : : {
7963 : : destmem = adjust_address (copy_rtx (destmem), mode,
7964 : : GET_MODE_SIZE (mode));
7965 : : srcmem = adjust_address (copy_rtx (srcmem), mode,
7966 : : GET_MODE_SIZE (mode));
7967 : : }
7968 : : emit_move_insn (destmem, srcmem);
7969 : : }
7970 : : }
7971 : : else
7972 : : {
7973 : 11391 : rtx tmpreg[4];
7974 : 11391 : gcc_assert (unroll <= 4);
7975 : 44966 : for (i = 0; i < unroll; i++)
7976 : : {
7977 : 33575 : tmpreg[i] = gen_reg_rtx (mode);
7978 : 33575 : if (i)
7979 : 44368 : srcmem = adjust_address (copy_rtx (srcmem), mode,
7980 : : GET_MODE_SIZE (mode));
7981 : 33575 : emit_move_insn (tmpreg[i], srcmem);
7982 : : }
7983 : 44966 : for (i = 0; i < unroll; i++)
7984 : : {
7985 : 33575 : if (i)
7986 : 44368 : destmem = adjust_address (copy_rtx (destmem), mode,
7987 : : GET_MODE_SIZE (mode));
7988 : 33575 : emit_move_insn (destmem, tmpreg[i]);
7989 : : }
7990 : : }
7991 : : }
7992 : : else
7993 : 28474 : for (i = 0; i < unroll; i++)
7994 : : {
7995 : 22247 : if (i)
7996 : 32040 : destmem = adjust_address (copy_rtx (destmem), mode,
7997 : : GET_MODE_SIZE (mode));
7998 : 22247 : emit_move_insn (destmem, value);
7999 : : }
8000 : :
8001 : 17618 : tmp = expand_simple_binop (iter_mode, PLUS, iter, piece_size, iter,
8002 : : true, OPTAB_LIB_WIDEN);
8003 : 17618 : if (tmp != iter)
8004 : 0 : emit_move_insn (iter, tmp);
8005 : :
8006 : 17618 : if (loop_count != 1)
8007 : : {
8008 : 17617 : emit_cmp_and_jump_insns (iter, size, LT, NULL_RTX, iter_mode,
8009 : : true, top_label);
8010 : 17617 : if (expected_size != -1)
8011 : : {
8012 : 8921 : expected_size /= GET_MODE_SIZE (mode) * unroll;
8013 : 8921 : if (expected_size == 0)
8014 : 1 : predict_jump (0);
8015 : 8920 : else if (expected_size > REG_BR_PROB_BASE)
8016 : 2 : predict_jump (REG_BR_PROB_BASE - 1);
8017 : : else
8018 : 8918 : predict_jump (REG_BR_PROB_BASE
8019 : 8918 : - (REG_BR_PROB_BASE + expected_size / 2)
8020 : 8918 : / expected_size);
8021 : : }
8022 : : else
8023 : 8696 : predict_jump (REG_BR_PROB_BASE * 80 / 100);
8024 : : }
8025 : 17618 : iter = ix86_zero_extend_to_Pmode (iter);
8026 : 20419 : tmp = expand_simple_binop (Pmode, PLUS, destptr, iter, destptr,
8027 : : true, OPTAB_LIB_WIDEN);
8028 : 17618 : if (tmp != destptr)
8029 : 0 : emit_move_insn (destptr, tmp);
8030 : 17618 : if (!issetmem)
8031 : : {
8032 : 12766 : tmp = expand_simple_binop (Pmode, PLUS, srcptr, iter, srcptr,
8033 : : true, OPTAB_LIB_WIDEN);
8034 : 11391 : if (tmp != srcptr)
8035 : 0 : emit_move_insn (srcptr, tmp);
8036 : : }
8037 : 17618 : if (loop_count != 1)
8038 : 17617 : emit_label (out_label);
8039 : 17618 : }
8040 : :
8041 : : /* Divide COUNTREG by SCALE. */
8042 : : static rtx
8043 : 11490 : scale_counter (rtx countreg, int scale)
8044 : : {
8045 : 11490 : rtx sc;
8046 : :
8047 : 11490 : if (scale == 1)
8048 : : return countreg;
8049 : 6817 : if (CONST_INT_P (countreg))
8050 : 6801 : return GEN_INT (INTVAL (countreg) / scale);
8051 : 16 : gcc_assert (REG_P (countreg));
8052 : :
8053 : 48 : sc = expand_simple_binop (GET_MODE (countreg), LSHIFTRT, countreg,
8054 : 32 : GEN_INT (exact_log2 (scale)),
8055 : : NULL, 1, OPTAB_DIRECT);
8056 : 16 : return sc;
8057 : : }
8058 : :
8059 : : /* Output "rep; mov" or "rep; stos" instruction depending on ISSETMEM argument.
8060 : : When ISSETMEM is true, arguments SRCMEM and SRCPTR are ignored.
8061 : : When ISSETMEM is false, arguments VALUE and ORIG_VALUE are ignored.
8062 : : For setmem case, VALUE is a promoted to a wider size ORIG_VALUE.
8063 : : ORIG_VALUE is the original value passed to memset to fill the memory with.
8064 : : Other arguments have same meaning as for previous function. */
8065 : :
8066 : : static void
8067 : 11490 : expand_set_or_cpymem_via_rep (rtx destmem, rtx srcmem,
8068 : : rtx destptr, rtx srcptr, rtx value, rtx orig_value,
8069 : : rtx count,
8070 : : machine_mode mode, bool issetmem)
8071 : : {
8072 : 11490 : rtx destexp;
8073 : 11490 : rtx srcexp;
8074 : 11490 : rtx countreg;
8075 : 11490 : HOST_WIDE_INT rounded_count;
8076 : :
8077 : : /* If possible, it is shorter to use rep movs.
8078 : : TODO: Maybe it is better to move this logic to decide_alg. */
8079 : 11490 : if (mode == QImode && CONST_INT_P (count) && !(INTVAL (count) & 3)
8080 : 240 : && !TARGET_PREFER_KNOWN_REP_MOVSB_STOSB
8081 : 236 : && (!issetmem || orig_value == const0_rtx))
8082 : 11490 : mode = SImode;
8083 : :
8084 : 11490 : if (destptr != XEXP (destmem, 0) || GET_MODE (destmem) != BLKmode)
8085 : 11236 : destmem = adjust_automodify_address_nv (destmem, BLKmode, destptr, 0);
8086 : :
8087 : 22980 : countreg = ix86_zero_extend_to_Pmode (scale_counter (count,
8088 : 11490 : GET_MODE_SIZE (mode)));
8089 : 11490 : if (mode != QImode)
8090 : : {
8091 : 20716 : destexp = gen_rtx_ASHIFT (Pmode, countreg,
8092 : : GEN_INT (exact_log2 (GET_MODE_SIZE (mode))));
8093 : 7082 : destexp = gen_rtx_PLUS (Pmode, destexp, destptr);
8094 : : }
8095 : : else
8096 : 4695 : destexp = gen_rtx_PLUS (Pmode, destptr, countreg);
8097 : 11490 : if ((!issetmem || orig_value == const0_rtx) && CONST_INT_P (count))
8098 : : {
8099 : 7463 : rounded_count
8100 : 7463 : = ROUND_DOWN (INTVAL (count), (HOST_WIDE_INT) GET_MODE_SIZE (mode));
8101 : 7463 : destmem = shallow_copy_rtx (destmem);
8102 : 7463 : set_mem_size (destmem, rounded_count);
8103 : : }
8104 : 4034 : else if (MEM_SIZE_KNOWN_P (destmem))
8105 : 330 : clear_mem_size (destmem);
8106 : :
8107 : 11490 : if (issetmem)
8108 : : {
8109 : 3196 : value = force_reg (mode, gen_lowpart (mode, value));
8110 : 3196 : emit_insn (gen_rep_stos (destptr, countreg, destmem, value, destexp));
8111 : : }
8112 : : else
8113 : : {
8114 : 8294 : if (srcptr != XEXP (srcmem, 0) || GET_MODE (srcmem) != BLKmode)
8115 : 8090 : srcmem = adjust_automodify_address_nv (srcmem, BLKmode, srcptr, 0);
8116 : 8294 : if (mode != QImode)
8117 : : {
8118 : 14933 : srcexp = gen_rtx_ASHIFT (Pmode, countreg,
8119 : : GEN_INT (exact_log2 (GET_MODE_SIZE (mode))));
8120 : 5105 : srcexp = gen_rtx_PLUS (Pmode, srcexp, srcptr);
8121 : : }
8122 : : else
8123 : 3398 : srcexp = gen_rtx_PLUS (Pmode, srcptr, countreg);
8124 : 8294 : if (CONST_INT_P (count))
8125 : : {
8126 : 5389 : rounded_count
8127 : 5389 : = ROUND_DOWN (INTVAL (count), (HOST_WIDE_INT) GET_MODE_SIZE (mode));
8128 : 5389 : srcmem = shallow_copy_rtx (srcmem);
8129 : 5389 : set_mem_size (srcmem, rounded_count);
8130 : : }
8131 : : else
8132 : : {
8133 : 2919 : if (MEM_SIZE_KNOWN_P (srcmem))
8134 : 0 : clear_mem_size (srcmem);
8135 : : }
8136 : 8294 : emit_insn (gen_rep_mov (destptr, destmem, srcptr, srcmem, countreg,
8137 : : destexp, srcexp));
8138 : : }
8139 : 11490 : }
8140 : :
8141 : : /* This function emits moves to copy SIZE_TO_MOVE bytes from SRCMEM to
8142 : : DESTMEM.
8143 : : SRC is passed by pointer to be updated on return.
8144 : : Return value is updated DST. */
8145 : : static rtx
8146 : 13 : emit_memmov (rtx destmem, rtx *srcmem, rtx destptr, rtx srcptr,
8147 : : HOST_WIDE_INT size_to_move)
8148 : : {
8149 : 13 : rtx dst = destmem, src = *srcmem, tempreg;
8150 : 13 : enum insn_code code;
8151 : 13 : machine_mode move_mode;
8152 : 13 : int piece_size, i;
8153 : :
8154 : : /* Find the widest mode in which we could perform moves.
8155 : : Start with the biggest power of 2 less than SIZE_TO_MOVE and half
8156 : : it until move of such size is supported. */
8157 : 13 : piece_size = 1 << floor_log2 (size_to_move);
8158 : 26 : while (!int_mode_for_size (piece_size * BITS_PER_UNIT, 0).exists (&move_mode)
8159 : 26 : || (code = optab_handler (mov_optab, move_mode)) == CODE_FOR_nothing)
8160 : : {
8161 : 0 : gcc_assert (piece_size > 1);
8162 : 0 : piece_size >>= 1;
8163 : : }
8164 : :
8165 : : /* Find the corresponding vector mode with the same size as MOVE_MODE.
8166 : : MOVE_MODE is an integer mode at the moment (SI, DI, TI, etc.). */
8167 : 39 : if (GET_MODE_SIZE (move_mode) > GET_MODE_SIZE (word_mode))
8168 : : {
8169 : 0 : int nunits = GET_MODE_SIZE (move_mode) / GET_MODE_SIZE (word_mode);
8170 : 0 : if (!mode_for_vector (word_mode, nunits).exists (&move_mode)
8171 : 0 : || (code = optab_handler (mov_optab, move_mode)) == CODE_FOR_nothing)
8172 : : {
8173 : 0 : move_mode = word_mode;
8174 : 0 : piece_size = GET_MODE_SIZE (move_mode);
8175 : 0 : code = optab_handler (mov_optab, move_mode);
8176 : : }
8177 : : }
8178 : 13 : gcc_assert (code != CODE_FOR_nothing);
8179 : :
8180 : 13 : dst = adjust_automodify_address_nv (dst, move_mode, destptr, 0);
8181 : 13 : src = adjust_automodify_address_nv (src, move_mode, srcptr, 0);
8182 : :
8183 : : /* Emit moves. We'll need SIZE_TO_MOVE/PIECE_SIZES moves. */
8184 : 13 : gcc_assert (size_to_move % piece_size == 0);
8185 : :
8186 : 26 : for (i = 0; i < size_to_move; i += piece_size)
8187 : : {
8188 : : /* We move from memory to memory, so we'll need to do it via
8189 : : a temporary register. */
8190 : 13 : tempreg = gen_reg_rtx (move_mode);
8191 : 13 : emit_insn (GEN_FCN (code) (tempreg, src));
8192 : 13 : emit_insn (GEN_FCN (code) (dst, tempreg));
8193 : :
8194 : 26 : emit_move_insn (destptr,
8195 : 13 : plus_constant (Pmode, copy_rtx (destptr), piece_size));
8196 : 26 : emit_move_insn (srcptr,
8197 : 13 : plus_constant (Pmode, copy_rtx (srcptr), piece_size));
8198 : :
8199 : 13 : dst = adjust_automodify_address_nv (dst, move_mode, destptr,
8200 : : piece_size);
8201 : 13 : src = adjust_automodify_address_nv (src, move_mode, srcptr,
8202 : : piece_size);
8203 : : }
8204 : :
8205 : : /* Update DST and SRC rtx. */
8206 : 13 : *srcmem = src;
8207 : 13 : return dst;
8208 : : }
8209 : :
8210 : : /* Helper function for the string operations below. Dest VARIABLE whether
8211 : : it is aligned to VALUE bytes. If true, jump to the label. */
8212 : :
8213 : : static rtx_code_label *
8214 : 30065 : ix86_expand_aligntest (rtx variable, int value, bool epilogue)
8215 : : {
8216 : 30065 : rtx_code_label *label = gen_label_rtx ();
8217 : 30065 : rtx tmpcount = gen_reg_rtx (GET_MODE (variable));
8218 : 30065 : if (GET_MODE (variable) == DImode)
8219 : 912 : emit_insn (gen_anddi3 (tmpcount, variable, GEN_INT (value)));
8220 : : else
8221 : 29153 : emit_insn (gen_andsi3 (tmpcount, variable, GEN_INT (value)));
8222 : 30065 : emit_cmp_and_jump_insns (tmpcount, const0_rtx, EQ, 0, GET_MODE (variable),
8223 : : 1, label);
8224 : 30065 : if (epilogue)
8225 : 3 : predict_jump (REG_BR_PROB_BASE * 50 / 100);
8226 : : else
8227 : 30062 : predict_jump (REG_BR_PROB_BASE * 90 / 100);
8228 : 30065 : return label;
8229 : : }
8230 : :
8231 : :
8232 : : /* Output code to copy at most count & (max_size - 1) bytes from SRC to DEST. */
8233 : :
8234 : : static void
8235 : 7329 : expand_cpymem_epilogue (rtx destmem, rtx srcmem,
8236 : : rtx destptr, rtx srcptr, rtx count, int max_size)
8237 : : {
8238 : 7329 : rtx src, dest;
8239 : 7329 : if (CONST_INT_P (count))
8240 : : {
8241 : 5392 : unsigned HOST_WIDE_INT countval = UINTVAL (count);
8242 : 5392 : unsigned HOST_WIDE_INT epilogue_size = countval % max_size;
8243 : 5392 : unsigned int destalign = MEM_ALIGN (destmem);
8244 : 5392 : move_by_pieces (destmem, srcmem, epilogue_size, destalign,
8245 : : RETURN_BEGIN);
8246 : 5392 : return;
8247 : : }
8248 : 1937 : if (max_size > 8)
8249 : : {
8250 : 1937 : count = expand_simple_binop (GET_MODE (count), AND, count, GEN_INT (max_size - 1),
8251 : : count, 1, OPTAB_DIRECT);
8252 : 1937 : expand_set_or_cpymem_via_loop (destmem, srcmem, destptr, srcptr, NULL,
8253 : : count, QImode, 1, 4, false);
8254 : 1937 : return;
8255 : : }
8256 : :
8257 : : /* When there are stringops, we can cheaply increase dest and src pointers.
8258 : : Otherwise we save code size by maintaining offset (zero is readily
8259 : : available from preceding rep operation) and using x86 addressing modes.
8260 : : */
8261 : 0 : if (TARGET_SINGLE_STRINGOP)
8262 : : {
8263 : 0 : if (max_size > 4)
8264 : : {
8265 : 0 : rtx_code_label *label = ix86_expand_aligntest (count, 4, true);
8266 : 0 : src = change_address (srcmem, SImode, srcptr);
8267 : 0 : dest = change_address (destmem, SImode, destptr);
8268 : 0 : emit_insn (gen_strmov (destptr, dest, srcptr, src));
8269 : 0 : emit_label (label);
8270 : 0 : LABEL_NUSES (label) = 1;
8271 : : }
8272 : 0 : if (max_size > 2)
8273 : : {
8274 : 0 : rtx_code_label *label = ix86_expand_aligntest (count, 2, true);
8275 : 0 : src = change_address (srcmem, HImode, srcptr);
8276 : 0 : dest = change_address (destmem, HImode, destptr);
8277 : 0 : emit_insn (gen_strmov (destptr, dest, srcptr, src));
8278 : 0 : emit_label (label);
8279 : 0 : LABEL_NUSES (label) = 1;
8280 : : }
8281 : 0 : if (max_size > 1)
8282 : : {
8283 : 0 : rtx_code_label *label = ix86_expand_aligntest (count, 1, true);
8284 : 0 : src = change_address (srcmem, QImode, srcptr);
8285 : 0 : dest = change_address (destmem, QImode, destptr);
8286 : 0 : emit_insn (gen_strmov (destptr, dest, srcptr, src));
8287 : 0 : emit_label (label);
8288 : 0 : LABEL_NUSES (label) = 1;
8289 : : }
8290 : : }
8291 : : else
8292 : : {
8293 : 0 : rtx offset = force_reg (Pmode, const0_rtx);
8294 : 0 : rtx tmp;
8295 : :
8296 : 0 : if (max_size > 4)
8297 : : {
8298 : 0 : rtx_code_label *label = ix86_expand_aligntest (count, 4, true);
8299 : 0 : src = change_address (srcmem, SImode, srcptr);
8300 : 0 : dest = change_address (destmem, SImode, destptr);
8301 : 0 : emit_move_insn (dest, src);
8302 : 0 : tmp = expand_simple_binop (Pmode, PLUS, offset, GEN_INT (4), NULL,
8303 : : true, OPTAB_LIB_WIDEN);
8304 : 0 : if (tmp != offset)
8305 : 0 : emit_move_insn (offset, tmp);
8306 : 0 : emit_label (label);
8307 : 0 : LABEL_NUSES (label) = 1;
8308 : : }
8309 : 0 : if (max_size > 2)
8310 : : {
8311 : 0 : rtx_code_label *label = ix86_expand_aligntest (count, 2, true);
8312 : 0 : tmp = gen_rtx_PLUS (Pmode, srcptr, offset);
8313 : 0 : src = change_address (srcmem, HImode, tmp);
8314 : 0 : tmp = gen_rtx_PLUS (Pmode, destptr, offset);
8315 : 0 : dest = change_address (destmem, HImode, tmp);
8316 : 0 : emit_move_insn (dest, src);
8317 : 0 : tmp = expand_simple_binop (Pmode, PLUS, offset, GEN_INT (2), tmp,
8318 : : true, OPTAB_LIB_WIDEN);
8319 : 0 : if (tmp != offset)
8320 : 0 : emit_move_insn (offset, tmp);
8321 : 0 : emit_label (label);
8322 : 0 : LABEL_NUSES (label) = 1;
8323 : : }
8324 : 0 : if (max_size > 1)
8325 : : {
8326 : 0 : rtx_code_label *label = ix86_expand_aligntest (count, 1, true);
8327 : 0 : tmp = gen_rtx_PLUS (Pmode, srcptr, offset);
8328 : 0 : src = change_address (srcmem, QImode, tmp);
8329 : 0 : tmp = gen_rtx_PLUS (Pmode, destptr, offset);
8330 : 0 : dest = change_address (destmem, QImode, tmp);
8331 : 0 : emit_move_insn (dest, src);
8332 : 0 : emit_label (label);
8333 : 0 : LABEL_NUSES (label) = 1;
8334 : : }
8335 : : }
8336 : : }
8337 : :
8338 : : /* This function emits moves to fill SIZE_TO_MOVE bytes starting from DESTMEM
8339 : : with value PROMOTED_VAL.
8340 : : SRC is passed by pointer to be updated on return.
8341 : : Return value is updated DST. */
8342 : : static rtx
8343 : 6 : emit_memset (rtx destmem, rtx destptr, rtx promoted_val,
8344 : : HOST_WIDE_INT size_to_move)
8345 : : {
8346 : 6 : rtx dst = destmem;
8347 : 6 : enum insn_code code;
8348 : 6 : machine_mode move_mode;
8349 : 6 : int piece_size, i;
8350 : :
8351 : : /* Find the widest mode in which we could perform moves.
8352 : : Start with the biggest power of 2 less than SIZE_TO_MOVE and half
8353 : : it until move of such size is supported. */
8354 : 6 : move_mode = GET_MODE (promoted_val);
8355 : 6 : if (move_mode == VOIDmode)
8356 : 0 : move_mode = QImode;
8357 : 12 : if (size_to_move < GET_MODE_SIZE (move_mode))
8358 : : {
8359 : 5 : unsigned int move_bits = size_to_move * BITS_PER_UNIT;
8360 : 5 : move_mode = int_mode_for_size (move_bits, 0).require ();
8361 : 5 : promoted_val = gen_lowpart (move_mode, promoted_val);
8362 : : }
8363 : 6 : piece_size = GET_MODE_SIZE (move_mode);
8364 : 6 : code = optab_handler (mov_optab, move_mode);
8365 : 6 : gcc_assert (code != CODE_FOR_nothing && promoted_val != NULL_RTX);
8366 : :
8367 : 6 : dst = adjust_automodify_address_nv (dst, move_mode, destptr, 0);
8368 : :
8369 : : /* Emit moves. We'll need SIZE_TO_MOVE/PIECE_SIZES moves. */
8370 : 6 : gcc_assert (size_to_move % piece_size == 0);
8371 : :
8372 : 12 : for (i = 0; i < size_to_move; i += piece_size)
8373 : : {
8374 : 12 : if (piece_size <= GET_MODE_SIZE (word_mode))
8375 : : {
8376 : 4 : emit_insn (gen_strset (destptr, dst, promoted_val));
8377 : 4 : dst = adjust_automodify_address_nv (dst, move_mode, destptr,
8378 : : piece_size);
8379 : 4 : continue;
8380 : : }
8381 : :
8382 : 2 : emit_insn (GEN_FCN (code) (dst, promoted_val));
8383 : :
8384 : 4 : emit_move_insn (destptr,
8385 : 2 : plus_constant (Pmode, copy_rtx (destptr), piece_size));
8386 : :
8387 : 2 : dst = adjust_automodify_address_nv (dst, move_mode, destptr,
8388 : : piece_size);
8389 : : }
8390 : :
8391 : : /* Update DST rtx. */
8392 : 6 : return dst;
8393 : : }
8394 : : /* Output code to set at most count & (max_size - 1) bytes starting by DEST. */
8395 : : static void
8396 : 419 : expand_setmem_epilogue_via_loop (rtx destmem, rtx destptr, rtx value,
8397 : : rtx count, int max_size)
8398 : : {
8399 : 838 : count = expand_simple_binop (counter_mode (count), AND, count,
8400 : 419 : GEN_INT (max_size - 1), count, 1, OPTAB_DIRECT);
8401 : 419 : expand_set_or_cpymem_via_loop (destmem, NULL, destptr, NULL,
8402 : 419 : gen_lowpart (QImode, value), count, QImode,
8403 : : 1, max_size / 2, true);
8404 : 419 : }
8405 : :
8406 : : /* Callback routine for store_by_pieces. Return the RTL of a register
8407 : : containing GET_MODE_SIZE (MODE) bytes in the RTL register op_p which
8408 : : is a word or a word vector register. If PREV_P isn't nullptr, it
8409 : : has the RTL info from the previous iteration. */
8410 : :
8411 : : static rtx
8412 : 4840 : setmem_epilogue_gen_val (void *op_p, void *prev_p, HOST_WIDE_INT,
8413 : : fixed_size_mode mode)
8414 : : {
8415 : 4840 : rtx target;
8416 : 4840 : by_pieces_prev *prev = (by_pieces_prev *) prev_p;
8417 : 4840 : if (prev)
8418 : : {
8419 : 4840 : rtx prev_op = prev->data;
8420 : 4840 : if (prev_op)
8421 : : {
8422 : 2804 : machine_mode prev_mode = GET_MODE (prev_op);
8423 : 2804 : if (prev_mode == mode)
8424 : : return prev_op;
8425 : 48 : if (VECTOR_MODE_P (prev_mode)
8426 : 1068 : && VECTOR_MODE_P (mode)
8427 : 1116 : && GET_MODE_INNER (prev_mode) == GET_MODE_INNER (mode))
8428 : : {
8429 : 0 : target = gen_rtx_SUBREG (mode, prev_op, 0);
8430 : 0 : return target;
8431 : : }
8432 : : }
8433 : : }
8434 : :
8435 : 3152 : rtx op = (rtx) op_p;
8436 : 3152 : machine_mode op_mode = GET_MODE (op);
8437 : :
8438 : 6302 : gcc_assert (op_mode == word_mode
8439 : : || (VECTOR_MODE_P (op_mode)
8440 : : && GET_MODE_INNER (op_mode) == word_mode));
8441 : :
8442 : 3152 : if (VECTOR_MODE_P (mode))
8443 : : {
8444 : 3572 : gcc_assert (GET_MODE_INNER (mode) == QImode);
8445 : :
8446 : 1786 : unsigned int op_size = GET_MODE_SIZE (op_mode);
8447 : 1786 : unsigned int size = GET_MODE_SIZE (mode);
8448 : 1786 : unsigned int nunits = op_size / GET_MODE_SIZE (QImode);
8449 : 1786 : machine_mode vec_mode
8450 : 1786 : = mode_for_vector (QImode, nunits).require ();
8451 : 1786 : target = gen_reg_rtx (vec_mode);
8452 : 1786 : op = gen_rtx_SUBREG (vec_mode, op, 0);
8453 : 1786 : emit_move_insn (target, op);
8454 : 1786 : if (op_size == size)
8455 : : return target;
8456 : :
8457 : 0 : rtx tmp = gen_reg_rtx (mode);
8458 : 0 : target = gen_rtx_SUBREG (mode, target, 0);
8459 : 0 : emit_move_insn (tmp, target);
8460 : 0 : return tmp;
8461 : : }
8462 : :
8463 : 1366 : target = gen_reg_rtx (word_mode);
8464 : 1366 : if (VECTOR_MODE_P (op_mode))
8465 : : {
8466 : 1364 : op = gen_rtx_SUBREG (word_mode, op, 0);
8467 : 1364 : emit_move_insn (target, op);
8468 : : }
8469 : : else
8470 : : target = op;
8471 : :
8472 : 1366 : if (mode == word_mode)
8473 : : return target;
8474 : :
8475 : 226 : rtx tmp = gen_reg_rtx (mode);
8476 : 226 : target = gen_rtx_SUBREG (mode, target, 0);
8477 : 226 : emit_move_insn (tmp, target);
8478 : 226 : return tmp;
8479 : : }
8480 : :
8481 : : /* Output code to set at most count & (max_size - 1) bytes starting by DEST. */
8482 : : static void
8483 : 5062 : expand_setmem_epilogue (rtx destmem, rtx destptr, rtx value, rtx vec_value,
8484 : : rtx count, int max_size)
8485 : : {
8486 : 5062 : rtx dest;
8487 : :
8488 : 5062 : if (CONST_INT_P (count))
8489 : : {
8490 : 4642 : unsigned HOST_WIDE_INT countval = UINTVAL (count);
8491 : 4642 : unsigned HOST_WIDE_INT epilogue_size = countval % max_size;
8492 : 4642 : unsigned int destalign = MEM_ALIGN (destmem);
8493 : 4642 : store_by_pieces (destmem, epilogue_size, setmem_epilogue_gen_val,
8494 : : vec_value ? vec_value : value, destalign, true,
8495 : : RETURN_BEGIN);
8496 : 4642 : return;
8497 : : }
8498 : 420 : if (max_size > 32)
8499 : : {
8500 : 419 : expand_setmem_epilogue_via_loop (destmem, destptr, value, count, max_size);
8501 : 419 : return;
8502 : : }
8503 : 1 : if (max_size > 16)
8504 : : {
8505 : 0 : rtx_code_label *label = ix86_expand_aligntest (count, 16, true);
8506 : 0 : if (TARGET_64BIT)
8507 : : {
8508 : 0 : dest = change_address (destmem, DImode, destptr);
8509 : 0 : emit_insn (gen_strset (destptr, dest, value));
8510 : 0 : dest = adjust_automodify_address_nv (dest, DImode, destptr, 8);
8511 : 0 : emit_insn (gen_strset (destptr, dest, value));
8512 : : }
8513 : : else
8514 : : {
8515 : 0 : dest = change_address (destmem, SImode, destptr);
8516 : 0 : emit_insn (gen_strset (destptr, dest, value));
8517 : 0 : dest = adjust_automodify_address_nv (dest, SImode, destptr, 4);
8518 : 0 : emit_insn (gen_strset (destptr, dest, value));
8519 : 0 : dest = adjust_automodify_address_nv (dest, SImode, destptr, 8);
8520 : 0 : emit_insn (gen_strset (destptr, dest, value));
8521 : 0 : dest = adjust_automodify_address_nv (dest, SImode, destptr, 12);
8522 : 0 : emit_insn (gen_strset (destptr, dest, value));
8523 : : }
8524 : 0 : emit_label (label);
8525 : 0 : LABEL_NUSES (label) = 1;
8526 : : }
8527 : 1 : if (max_size > 8)
8528 : : {
8529 : 0 : rtx_code_label *label = ix86_expand_aligntest (count, 8, true);
8530 : 0 : if (TARGET_64BIT)
8531 : : {
8532 : 0 : dest = change_address (destmem, DImode, destptr);
8533 : 0 : emit_insn (gen_strset (destptr, dest, value));
8534 : : }
8535 : : else
8536 : : {
8537 : 0 : dest = change_address (destmem, SImode, destptr);
8538 : 0 : emit_insn (gen_strset (destptr, dest, value));
8539 : 0 : dest = adjust_automodify_address_nv (dest, SImode, destptr, 4);
8540 : 0 : emit_insn (gen_strset (destptr, dest, value));
8541 : : }
8542 : 0 : emit_label (label);
8543 : 0 : LABEL_NUSES (label) = 1;
8544 : : }
8545 : 1 : if (max_size > 4)
8546 : : {
8547 : 1 : rtx_code_label *label = ix86_expand_aligntest (count, 4, true);
8548 : 1 : dest = change_address (destmem, SImode, destptr);
8549 : 1 : emit_insn (gen_strset (destptr, dest, gen_lowpart (SImode, value)));
8550 : 1 : emit_label (label);
8551 : 1 : LABEL_NUSES (label) = 1;
8552 : : }
8553 : 1 : if (max_size > 2)
8554 : : {
8555 : 1 : rtx_code_label *label = ix86_expand_aligntest (count, 2, true);
8556 : 1 : dest = change_address (destmem, HImode, destptr);
8557 : 1 : emit_insn (gen_strset (destptr, dest, gen_lowpart (HImode, value)));
8558 : 1 : emit_label (label);
8559 : 1 : LABEL_NUSES (label) = 1;
8560 : : }
8561 : 1 : if (max_size > 1)
8562 : : {
8563 : 1 : rtx_code_label *label = ix86_expand_aligntest (count, 1, true);
8564 : 1 : dest = change_address (destmem, QImode, destptr);
8565 : 1 : emit_insn (gen_strset (destptr, dest, gen_lowpart (QImode, value)));
8566 : 1 : emit_label (label);
8567 : 1 : LABEL_NUSES (label) = 1;
8568 : : }
8569 : : }
8570 : :
8571 : : /* Adjust COUNTER by the VALUE. */
8572 : : static void
8573 : 19 : ix86_adjust_counter (rtx countreg, HOST_WIDE_INT value)
8574 : : {
8575 : 19 : emit_insn (gen_add2_insn (countreg, GEN_INT (-value)));
8576 : 19 : }
8577 : :
8578 : : /* Depending on ISSETMEM, copy enough from SRCMEM to DESTMEM or set enough to
8579 : : DESTMEM to align it to DESIRED_ALIGNMENT. Original alignment is ALIGN.
8580 : : Depending on ISSETMEM, either arguments SRCMEM/SRCPTR or VALUE/VEC_VALUE are
8581 : : ignored.
8582 : : Return value is updated DESTMEM. */
8583 : :
8584 : : static rtx
8585 : 7 : expand_set_or_cpymem_prologue (rtx destmem, rtx srcmem,
8586 : : rtx destptr, rtx srcptr, rtx value,
8587 : : rtx vec_value, rtx count, int align,
8588 : : int desired_alignment, bool issetmem)
8589 : : {
8590 : 7 : int i;
8591 : 35 : for (i = 1; i < desired_alignment; i <<= 1)
8592 : : {
8593 : 28 : if (align <= i)
8594 : : {
8595 : 19 : rtx_code_label *label = ix86_expand_aligntest (destptr, i, false);
8596 : 19 : if (issetmem)
8597 : : {
8598 : 12 : if (vec_value && i > GET_MODE_SIZE (GET_MODE (value)))
8599 : 2 : destmem = emit_memset (destmem, destptr, vec_value, i);
8600 : : else
8601 : 4 : destmem = emit_memset (destmem, destptr, value, i);
8602 : : }
8603 : : else
8604 : 13 : destmem = emit_memmov (destmem, &srcmem, destptr, srcptr, i);
8605 : 19 : ix86_adjust_counter (count, i);
8606 : 19 : emit_label (label);
8607 : 19 : LABEL_NUSES (label) = 1;
8608 : 19 : set_mem_align (destmem, i * 2 * BITS_PER_UNIT);
8609 : : }
8610 : : }
8611 : 7 : return destmem;
8612 : : }
8613 : :
8614 : : /* Test if COUNT&SIZE is nonzero and if so, expand movme
8615 : : or setmem sequence that is valid for SIZE..2*SIZE-1 bytes
8616 : : and jump to DONE_LABEL. */
8617 : : static void
8618 : 24030 : expand_small_cpymem_or_setmem (rtx destmem, rtx srcmem,
8619 : : rtx destptr, rtx srcptr,
8620 : : rtx value, rtx vec_value,
8621 : : rtx count, int size,
8622 : : rtx done_label, bool issetmem)
8623 : : {
8624 : 24030 : rtx_code_label *label = ix86_expand_aligntest (count, size, false);
8625 : 24030 : machine_mode mode = int_mode_for_size (size * BITS_PER_UNIT, 1).else_blk ();
8626 : 24030 : rtx modesize;
8627 : 24030 : rtx scalar_value = value;
8628 : 24030 : int n;
8629 : :
8630 : : /* If we do not have vector value to copy, we must reduce size. */
8631 : 24030 : if (issetmem)
8632 : : {
8633 : 3636 : if (!vec_value)
8634 : : {
8635 : 7 : if (GET_MODE (value) == VOIDmode && size > 8)
8636 : 0 : mode = Pmode;
8637 : 21 : else if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (value)))
8638 : 1 : mode = GET_MODE (value);
8639 : : }
8640 : : else
8641 : 3629 : mode = GET_MODE (vec_value), value = vec_value;
8642 : : }
8643 : : else
8644 : : {
8645 : : /* Choose appropriate vector mode. */
8646 : 20394 : if (size >= 32)
8647 : 5097 : switch (MOVE_MAX)
8648 : : {
8649 : 0 : case 64:
8650 : 0 : if (size >= 64)
8651 : : {
8652 : : mode = V64QImode;
8653 : : break;
8654 : : }
8655 : : /* FALLTHRU */
8656 : 0 : case 32:
8657 : 0 : mode = V32QImode;
8658 : 0 : break;
8659 : : case 16:
8660 : : mode = V16QImode;
8661 : : break;
8662 : : case 8:
8663 : : mode = DImode;
8664 : : break;
8665 : 0 : default:
8666 : 0 : gcc_unreachable ();
8667 : : }
8668 : 15297 : else if (size >= 16)
8669 : 5097 : mode = TARGET_SSE ? V16QImode : DImode;
8670 : 20394 : srcmem = change_address (srcmem, mode, srcptr);
8671 : : }
8672 : 27659 : if (issetmem && vec_value && GET_MODE_SIZE (mode) > size)
8673 : : {
8674 : : /* For memset with vector and the size is smaller than the vector
8675 : : size, first try the narrower vector, otherwise, use the
8676 : : original value. */
8677 : 1819 : machine_mode inner_mode = GET_MODE_INNER (mode);
8678 : 1819 : unsigned int nunits = size / GET_MODE_SIZE (inner_mode);
8679 : 1819 : if (nunits > 1)
8680 : : {
8681 : 364 : mode = mode_for_vector (GET_MODE_INNER (mode),
8682 : 364 : nunits).require ();
8683 : 182 : value = gen_rtx_SUBREG (mode, value, 0);
8684 : : }
8685 : : else
8686 : : {
8687 : 1637 : scalar_int_mode smode
8688 : 1637 : = smallest_int_mode_for_size (size * BITS_PER_UNIT).require ();
8689 : 4911 : gcc_assert (GET_MODE_SIZE (GET_MODE (scalar_value))
8690 : : >= GET_MODE_SIZE (smode));
8691 : 1637 : mode = smode;
8692 : 1637 : if (GET_MODE (scalar_value) == mode)
8693 : : value = scalar_value;
8694 : : else
8695 : 732 : value = gen_rtx_SUBREG (mode, scalar_value, 0);
8696 : : }
8697 : : }
8698 : 24030 : destmem = change_address (destmem, mode, destptr);
8699 : 48060 : modesize = GEN_INT (GET_MODE_SIZE (mode));
8700 : 48060 : gcc_assert (GET_MODE_SIZE (mode) <= size);
8701 : 108126 : for (n = 0; n * GET_MODE_SIZE (mode) < size; n++)
8702 : : {
8703 : 30033 : if (issetmem)
8704 : 4542 : emit_move_insn (destmem, gen_lowpart (mode, value));
8705 : : else
8706 : : {
8707 : 25491 : emit_move_insn (destmem, srcmem);
8708 : 50982 : srcmem = offset_address (srcmem, modesize, GET_MODE_SIZE (mode));
8709 : : }
8710 : 60066 : destmem = offset_address (destmem, modesize, GET_MODE_SIZE (mode));
8711 : : }
8712 : :
8713 : 24030 : destmem = offset_address (destmem, count, 1);
8714 : 48060 : destmem = offset_address (destmem, GEN_INT (-2 * size),
8715 : 24030 : GET_MODE_SIZE (mode));
8716 : 24030 : if (!issetmem)
8717 : : {
8718 : 20394 : srcmem = offset_address (srcmem, count, 1);
8719 : 40788 : srcmem = offset_address (srcmem, GEN_INT (-2 * size),
8720 : 20394 : GET_MODE_SIZE (mode));
8721 : : }
8722 : 108126 : for (n = 0; n * GET_MODE_SIZE (mode) < size; n++)
8723 : : {
8724 : 30033 : if (issetmem)
8725 : 4542 : emit_move_insn (destmem, gen_lowpart (mode, value));
8726 : : else
8727 : : {
8728 : 25491 : emit_move_insn (destmem, srcmem);
8729 : 50982 : srcmem = offset_address (srcmem, modesize, GET_MODE_SIZE (mode));
8730 : : }
8731 : 60066 : destmem = offset_address (destmem, modesize, GET_MODE_SIZE (mode));
8732 : : }
8733 : 24030 : emit_jump_insn (gen_jump (done_label));
8734 : 24030 : emit_barrier ();
8735 : :
8736 : 24030 : emit_label (label);
8737 : 24030 : LABEL_NUSES (label) = 1;
8738 : 24030 : }
8739 : :
8740 : : /* Handle small memcpy (up to SIZE that is supposed to be small power of 2.
8741 : : and get ready for the main memcpy loop by copying iniital DESIRED_ALIGN-ALIGN
8742 : : bytes and last SIZE bytes adjusitng DESTPTR/SRCPTR/COUNT in a way we can
8743 : : proceed with an loop copying SIZE bytes at once. Do moves in MODE.
8744 : : DONE_LABEL is a label after the whole copying sequence. The label is created
8745 : : on demand if *DONE_LABEL is NULL.
8746 : : MIN_SIZE is minimal size of block copied. This value gets adjusted for new
8747 : : bounds after the initial copies.
8748 : :
8749 : : DESTMEM/SRCMEM are memory expressions pointing to the copies block,
8750 : : DESTPTR/SRCPTR are pointers to the block. DYNAMIC_CHECK indicate whether
8751 : : we will dispatch to a library call for large blocks.
8752 : :
8753 : : In pseudocode we do:
8754 : :
8755 : : if (COUNT < SIZE)
8756 : : {
8757 : : Assume that SIZE is 4. Bigger sizes are handled analogously
8758 : : if (COUNT & 4)
8759 : : {
8760 : : copy 4 bytes from SRCPTR to DESTPTR
8761 : : copy 4 bytes from SRCPTR + COUNT - 4 to DESTPTR + COUNT - 4
8762 : : goto done_label
8763 : : }
8764 : : if (!COUNT)
8765 : : goto done_label;
8766 : : copy 1 byte from SRCPTR to DESTPTR
8767 : : if (COUNT & 2)
8768 : : {
8769 : : copy 2 bytes from SRCPTR to DESTPTR
8770 : : copy 2 bytes from SRCPTR + COUNT - 2 to DESTPTR + COUNT - 2
8771 : : }
8772 : : }
8773 : : else
8774 : : {
8775 : : copy at least DESIRED_ALIGN-ALIGN bytes from SRCPTR to DESTPTR
8776 : : copy SIZE bytes from SRCPTR + COUNT - SIZE to DESTPTR + COUNT -SIZE
8777 : :
8778 : : OLD_DESPTR = DESTPTR;
8779 : : Align DESTPTR up to DESIRED_ALIGN
8780 : : SRCPTR += DESTPTR - OLD_DESTPTR
8781 : : COUNT -= DEST_PTR - OLD_DESTPTR
8782 : : if (DYNAMIC_CHECK)
8783 : : Round COUNT down to multiple of SIZE
8784 : : << optional caller supplied zero size guard is here >>
8785 : : << optional caller supplied dynamic check is here >>
8786 : : << caller supplied main copy loop is here >>
8787 : : }
8788 : : done_label:
8789 : : */
8790 : : static void
8791 : 9351 : expand_set_or_cpymem_prologue_epilogue_by_misaligned_moves (rtx destmem, rtx srcmem,
8792 : : rtx *destptr, rtx *srcptr,
8793 : : machine_mode mode,
8794 : : rtx value, rtx vec_value,
8795 : : rtx *count,
8796 : : rtx_code_label **done_label,
8797 : : int size,
8798 : : int desired_align,
8799 : : int align,
8800 : : unsigned HOST_WIDE_INT *min_size,
8801 : : bool dynamic_check,
8802 : : bool issetmem)
8803 : : {
8804 : 9351 : rtx_code_label *loop_label = NULL, *label;
8805 : 9351 : int n;
8806 : 9351 : rtx modesize;
8807 : 9351 : int prolog_size = 0;
8808 : 9351 : rtx mode_value;
8809 : :
8810 : : /* Chose proper value to copy. */
8811 : 9351 : if (issetmem && VECTOR_MODE_P (mode))
8812 : : mode_value = vec_value;
8813 : : else
8814 : 9351 : mode_value = value;
8815 : 18702 : gcc_assert (GET_MODE_SIZE (mode) <= size);
8816 : :
8817 : : /* See if block is big or small, handle small blocks. */
8818 : 9351 : if (!CONST_INT_P (*count) && *min_size < (unsigned HOST_WIDE_INT)size)
8819 : : {
8820 : 6013 : int size2 = size;
8821 : 6013 : loop_label = gen_label_rtx ();
8822 : :
8823 : 6013 : if (!*done_label)
8824 : 6013 : *done_label = gen_label_rtx ();
8825 : :
8826 : 6013 : emit_cmp_and_jump_insns (*count, GEN_INT (size2), GE, 0, GET_MODE (*count),
8827 : : 1, loop_label);
8828 : 6013 : size2 >>= 1;
8829 : :
8830 : : /* Handle sizes > 3. */
8831 : 30043 : for (;size2 > 2; size2 >>= 1)
8832 : 24030 : expand_small_cpymem_or_setmem (destmem, srcmem,
8833 : : *destptr, *srcptr,
8834 : : value, vec_value,
8835 : : *count,
8836 : : size2, *done_label, issetmem);
8837 : : /* Nothing to copy? Jump to DONE_LABEL if so */
8838 : 6013 : emit_cmp_and_jump_insns (*count, const0_rtx, EQ, 0, GET_MODE (*count),
8839 : : 1, *done_label);
8840 : :
8841 : : /* Do a byte copy. */
8842 : 6013 : destmem = change_address (destmem, QImode, *destptr);
8843 : 6013 : if (issetmem)
8844 : 910 : emit_move_insn (destmem, gen_lowpart (QImode, value));
8845 : : else
8846 : : {
8847 : 5103 : srcmem = change_address (srcmem, QImode, *srcptr);
8848 : 5103 : emit_move_insn (destmem, srcmem);
8849 : : }
8850 : :
8851 : : /* Handle sizes 2 and 3. */
8852 : 6013 : label = ix86_expand_aligntest (*count, 2, false);
8853 : 6013 : destmem = change_address (destmem, HImode, *destptr);
8854 : 6013 : destmem = offset_address (destmem, *count, 1);
8855 : 6013 : destmem = offset_address (destmem, GEN_INT (-2), 2);
8856 : 6013 : if (issetmem)
8857 : 910 : emit_move_insn (destmem, gen_lowpart (HImode, value));
8858 : : else
8859 : : {
8860 : 5103 : srcmem = change_address (srcmem, HImode, *srcptr);
8861 : 5103 : srcmem = offset_address (srcmem, *count, 1);
8862 : 5103 : srcmem = offset_address (srcmem, GEN_INT (-2), 2);
8863 : 5103 : emit_move_insn (destmem, srcmem);
8864 : : }
8865 : :
8866 : 6013 : emit_label (label);
8867 : 6013 : LABEL_NUSES (label) = 1;
8868 : 6013 : emit_jump_insn (gen_jump (*done_label));
8869 : 6013 : emit_barrier ();
8870 : : }
8871 : : else
8872 : 3338 : gcc_assert (*min_size >= (unsigned HOST_WIDE_INT)size
8873 : : || UINTVAL (*count) >= (unsigned HOST_WIDE_INT)size);
8874 : :
8875 : : /* Start memcpy for COUNT >= SIZE. */
8876 : 6013 : if (loop_label)
8877 : : {
8878 : 6013 : emit_label (loop_label);
8879 : 6013 : LABEL_NUSES (loop_label) = 1;
8880 : : }
8881 : :
8882 : : /* Copy first desired_align bytes. */
8883 : 9351 : if (!issetmem)
8884 : 6778 : srcmem = change_address (srcmem, mode, *srcptr);
8885 : 9351 : destmem = change_address (destmem, mode, *destptr);
8886 : 9351 : modesize = GEN_INT (GET_MODE_SIZE (mode));
8887 : 18723 : for (n = 0; prolog_size < desired_align - align; n++)
8888 : : {
8889 : 21 : if (issetmem)
8890 : 3 : emit_move_insn (destmem, mode_value);
8891 : : else
8892 : : {
8893 : 18 : emit_move_insn (destmem, srcmem);
8894 : 36 : srcmem = offset_address (srcmem, modesize, GET_MODE_SIZE (mode));
8895 : : }
8896 : 42 : destmem = offset_address (destmem, modesize, GET_MODE_SIZE (mode));
8897 : 42 : prolog_size += GET_MODE_SIZE (mode);
8898 : : }
8899 : :
8900 : :
8901 : : /* Copy last SIZE bytes. */
8902 : 9351 : destmem = offset_address (destmem, *count, 1);
8903 : 9351 : destmem = offset_address (destmem,
8904 : 9351 : GEN_INT (-size - prolog_size),
8905 : : 1);
8906 : 9351 : if (issetmem)
8907 : 2573 : emit_move_insn (destmem, mode_value);
8908 : : else
8909 : : {
8910 : 6778 : srcmem = offset_address (srcmem, *count, 1);
8911 : 6778 : srcmem = offset_address (srcmem,
8912 : : GEN_INT (-size - prolog_size),
8913 : : 1);
8914 : 6778 : emit_move_insn (destmem, srcmem);
8915 : : }
8916 : 73230 : for (n = 1; n * GET_MODE_SIZE (mode) < size; n++)
8917 : : {
8918 : 27264 : destmem = offset_address (destmem, modesize, 1);
8919 : 27264 : if (issetmem)
8920 : 7560 : emit_move_insn (destmem, mode_value);
8921 : : else
8922 : : {
8923 : 19704 : srcmem = offset_address (srcmem, modesize, 1);
8924 : 19704 : emit_move_insn (destmem, srcmem);
8925 : : }
8926 : : }
8927 : :
8928 : : /* Align destination. */
8929 : 9351 : if (desired_align > 1 && desired_align > align)
8930 : : {
8931 : 21 : rtx saveddest = *destptr;
8932 : :
8933 : 21 : gcc_assert (desired_align <= size);
8934 : : /* Align destptr up, place it to new register. */
8935 : 21 : *destptr = expand_simple_binop (GET_MODE (*destptr), PLUS, *destptr,
8936 : : GEN_INT (prolog_size),
8937 : : NULL_RTX, 1, OPTAB_DIRECT);
8938 : 21 : if (REG_P (*destptr) && REG_P (saveddest) && REG_POINTER (saveddest))
8939 : 21 : REG_POINTER (*destptr) = 1;
8940 : 21 : *destptr = expand_simple_binop (GET_MODE (*destptr), AND, *destptr,
8941 : 21 : GEN_INT (-desired_align),
8942 : : *destptr, 1, OPTAB_DIRECT);
8943 : : /* See how many bytes we skipped. */
8944 : 21 : saveddest = expand_simple_binop (GET_MODE (*destptr), MINUS, saveddest,
8945 : : *destptr,
8946 : : NULL_RTX, 1, OPTAB_DIRECT);
8947 : : /* Adjust srcptr and count. */
8948 : 21 : if (!issetmem)
8949 : 18 : *srcptr = expand_simple_binop (GET_MODE (*srcptr), MINUS, *srcptr,
8950 : : saveddest, *srcptr, 1, OPTAB_DIRECT);
8951 : 21 : *count = expand_simple_binop (GET_MODE (*count), PLUS, *count,
8952 : : saveddest, *count, 1, OPTAB_DIRECT);
8953 : : /* We copied at most size + prolog_size. */
8954 : 21 : if (*min_size > (unsigned HOST_WIDE_INT)(size + prolog_size))
8955 : 14 : *min_size
8956 : 14 : = ROUND_DOWN (*min_size - size, (unsigned HOST_WIDE_INT)size);
8957 : : else
8958 : 7 : *min_size = 0;
8959 : :
8960 : : /* Our loops always round down the block size, but for dispatch to
8961 : : library we need precise value. */
8962 : 21 : if (dynamic_check)
8963 : 21 : *count = expand_simple_binop (GET_MODE (*count), AND, *count,
8964 : : GEN_INT (-size), *count, 1, OPTAB_DIRECT);
8965 : : }
8966 : : else
8967 : : {
8968 : 9330 : gcc_assert (prolog_size == 0);
8969 : : /* Decrease count, so we won't end up copying last word twice. */
8970 : 9330 : if (!CONST_INT_P (*count))
8971 : 6011 : *count = expand_simple_binop (GET_MODE (*count), PLUS, *count,
8972 : : constm1_rtx, *count, 1, OPTAB_DIRECT);
8973 : : else
8974 : 3319 : *count = GEN_INT (ROUND_DOWN (UINTVAL (*count) - 1,
8975 : : (unsigned HOST_WIDE_INT)size));
8976 : 9330 : if (*min_size)
8977 : 8718 : *min_size = ROUND_DOWN (*min_size - 1, (unsigned HOST_WIDE_INT)size);
8978 : : }
8979 : 9351 : }
8980 : :
8981 : :
8982 : : /* This function is like the previous one, except here we know how many bytes
8983 : : need to be copied. That allows us to update alignment not only of DST, which
8984 : : is returned, but also of SRC, which is passed as a pointer for that
8985 : : reason. */
8986 : : static rtx
8987 : 0 : expand_set_or_cpymem_constant_prologue (rtx dst, rtx *srcp, rtx destreg,
8988 : : rtx srcreg, rtx value, rtx vec_value,
8989 : : int desired_align, int align_bytes,
8990 : : bool issetmem)
8991 : : {
8992 : 0 : rtx src = NULL;
8993 : 0 : rtx orig_dst = dst;
8994 : 0 : rtx orig_src = NULL;
8995 : 0 : int piece_size = 1;
8996 : 0 : int copied_bytes = 0;
8997 : :
8998 : 0 : if (!issetmem)
8999 : : {
9000 : 0 : gcc_assert (srcp != NULL);
9001 : 0 : src = *srcp;
9002 : 0 : orig_src = src;
9003 : : }
9004 : :
9005 : 0 : for (piece_size = 1;
9006 : 0 : piece_size <= desired_align && copied_bytes < align_bytes;
9007 : 0 : piece_size <<= 1)
9008 : : {
9009 : 0 : if (align_bytes & piece_size)
9010 : : {
9011 : 0 : if (issetmem)
9012 : : {
9013 : 0 : if (vec_value && piece_size > GET_MODE_SIZE (GET_MODE (value)))
9014 : 0 : dst = emit_memset (dst, destreg, vec_value, piece_size);
9015 : : else
9016 : 0 : dst = emit_memset (dst, destreg, value, piece_size);
9017 : : }
9018 : : else
9019 : 0 : dst = emit_memmov (dst, &src, destreg, srcreg, piece_size);
9020 : 0 : copied_bytes += piece_size;
9021 : : }
9022 : : }
9023 : 0 : if (MEM_ALIGN (dst) < (unsigned int) desired_align * BITS_PER_UNIT)
9024 : 0 : set_mem_align (dst, desired_align * BITS_PER_UNIT);
9025 : 0 : if (MEM_SIZE_KNOWN_P (orig_dst))
9026 : 0 : set_mem_size (dst, MEM_SIZE (orig_dst) - align_bytes);
9027 : :
9028 : 0 : if (!issetmem)
9029 : : {
9030 : 0 : int src_align_bytes = get_mem_align_offset (src, desired_align
9031 : : * BITS_PER_UNIT);
9032 : 0 : if (src_align_bytes >= 0)
9033 : 0 : src_align_bytes = desired_align - src_align_bytes;
9034 : 0 : if (src_align_bytes >= 0)
9035 : : {
9036 : : unsigned int src_align;
9037 : 0 : for (src_align = desired_align; src_align >= 2; src_align >>= 1)
9038 : : {
9039 : 0 : if ((src_align_bytes & (src_align - 1))
9040 : 0 : == (align_bytes & (src_align - 1)))
9041 : : break;
9042 : : }
9043 : 0 : if (src_align > (unsigned int) desired_align)
9044 : : src_align = desired_align;
9045 : 0 : if (MEM_ALIGN (src) < src_align * BITS_PER_UNIT)
9046 : 0 : set_mem_align (src, src_align * BITS_PER_UNIT);
9047 : : }
9048 : 0 : if (MEM_SIZE_KNOWN_P (orig_src))
9049 : 0 : set_mem_size (src, MEM_SIZE (orig_src) - align_bytes);
9050 : 0 : *srcp = src;
9051 : : }
9052 : :
9053 : 0 : return dst;
9054 : : }
9055 : :
9056 : : /* Return true if ALG can be used in current context.
9057 : : Assume we expand memset if MEMSET is true. */
9058 : : static bool
9059 : 669255 : alg_usable_p (enum stringop_alg alg, bool memset,
9060 : : addr_space_t dst_as, addr_space_t src_as)
9061 : : {
9062 : 669255 : if (alg == no_stringop)
9063 : : return false;
9064 : : /* It is not possible to use a library call if we have non-default
9065 : : address space. We can do better than the generic byte-at-a-time
9066 : : loop, used as a fallback. */
9067 : 669255 : if (alg == libcall &&
9068 : 377800 : !(ADDR_SPACE_GENERIC_P (dst_as) && ADDR_SPACE_GENERIC_P (src_as)))
9069 : : return false;
9070 : 669248 : if (alg == vector_loop)
9071 : 293951 : return TARGET_SSE || TARGET_AVX;
9072 : : /* Algorithms using the rep prefix want at least edi and ecx;
9073 : : additionally, memset wants eax and memcpy wants esi. Don't
9074 : : consider such algorithms if the user has appropriated those
9075 : : registers for their own purposes, or if we have the destination
9076 : : in the non-default address space, since string insns cannot
9077 : : override the destination segment. */
9078 : 522250 : if (alg == rep_prefix_1_byte
9079 : : || alg == rep_prefix_4_byte
9080 : 522250 : || alg == rep_prefix_8_byte)
9081 : : {
9082 : 23163 : if (fixed_regs[CX_REG]
9083 : 23159 : || fixed_regs[DI_REG]
9084 : 23155 : || (memset ? fixed_regs[AX_REG] : fixed_regs[SI_REG])
9085 : 23151 : || !ADDR_SPACE_GENERIC_P (dst_as)
9086 : 46314 : || !(ADDR_SPACE_GENERIC_P (src_as) || Pmode == word_mode))
9087 : 12 : return false;
9088 : : }
9089 : : return true;
9090 : : }
9091 : :
9092 : : /* Given COUNT and EXPECTED_SIZE, decide on codegen of string operation. */
9093 : : static enum stringop_alg
9094 : 132791 : decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size,
9095 : : unsigned HOST_WIDE_INT min_size, unsigned HOST_WIDE_INT max_size,
9096 : : bool memset, bool zero_memset, addr_space_t dst_as,
9097 : : addr_space_t src_as, int *dynamic_check, bool *noalign, bool recur)
9098 : : {
9099 : 132791 : const struct stringop_algs *algs;
9100 : 132791 : bool optimize_for_speed;
9101 : 132791 : int max = 0;
9102 : 132791 : const struct processor_costs *cost;
9103 : 132791 : int i;
9104 : 132791 : bool any_alg_usable_p = false;
9105 : :
9106 : 132791 : *noalign = false;
9107 : 132791 : *dynamic_check = -1;
9108 : :
9109 : : /* Even if the string operation call is cold, we still might spend a lot
9110 : : of time processing large blocks. */
9111 : 132791 : if (optimize_function_for_size_p (cfun)
9112 : 132791 : || (optimize_insn_for_size_p ()
9113 : 4626 : && (max_size < 256
9114 : 2207 : || (expected_size != -1 && expected_size < 256))))
9115 : : optimize_for_speed = false;
9116 : : else
9117 : 121251 : optimize_for_speed = true;
9118 : :
9119 : 121251 : cost = optimize_for_speed ? ix86_cost : &ix86_size_cost;
9120 : 132791 : if (memset)
9121 : 44929 : algs = &cost->memset[TARGET_64BIT != 0];
9122 : : else
9123 : 96588 : algs = &cost->memcpy[TARGET_64BIT != 0];
9124 : :
9125 : : /* See maximal size for user defined algorithm. */
9126 : 663955 : for (i = 0; i < MAX_STRINGOP_ALGS; i++)
9127 : : {
9128 : 531164 : enum stringop_alg candidate = algs->size[i].alg;
9129 : 531164 : bool usable = alg_usable_p (candidate, memset, dst_as, src_as);
9130 : 531164 : any_alg_usable_p |= usable;
9131 : :
9132 : 531164 : if (candidate != libcall && candidate && usable)
9133 : 253987 : max = algs->size[i].max;
9134 : : }
9135 : :
9136 : : /* If expected size is not known but max size is small enough
9137 : : so inline version is a win, set expected size into
9138 : : the range. */
9139 : 132791 : if (((max > 1 && (unsigned HOST_WIDE_INT) max >= max_size) || max == -1)
9140 : 25730 : && expected_size == -1)
9141 : 14271 : expected_size = min_size / 2 + max_size / 2;
9142 : :
9143 : : /* If user specified the algorithm, honor it if possible. */
9144 : 132791 : if (ix86_stringop_alg != no_stringop
9145 : 132791 : && alg_usable_p (ix86_stringop_alg, memset, dst_as, src_as))
9146 : : return ix86_stringop_alg;
9147 : : /* rep; movq or rep; movl is the smallest variant. */
9148 : 132691 : else if (!optimize_for_speed)
9149 : : {
9150 : 11467 : *noalign = true;
9151 : 11467 : if (!count || (count & 3) || (memset && !zero_memset))
9152 : 4669 : return alg_usable_p (rep_prefix_1_byte, memset, dst_as, src_as)
9153 : 4669 : ? rep_prefix_1_byte : loop_1_byte;
9154 : : else
9155 : 6798 : return alg_usable_p (rep_prefix_4_byte, memset, dst_as, src_as)
9156 : 6798 : ? rep_prefix_4_byte : loop;
9157 : : }
9158 : : /* Very tiny blocks are best handled via the loop, REP is expensive to
9159 : : setup. */
9160 : 121224 : else if (expected_size != -1 && expected_size < 4)
9161 : : return loop_1_byte;
9162 : 118751 : else if (expected_size != -1)
9163 : : {
9164 : : enum stringop_alg alg = libcall;
9165 : : bool alg_noalign = false;
9166 : 169609 : for (i = 0; i < MAX_STRINGOP_ALGS; i++)
9167 : : {
9168 : : /* We get here if the algorithms that were not libcall-based
9169 : : were rep-prefix based and we are unable to use rep prefixes
9170 : : based on global register usage. Break out of the loop and
9171 : : use the heuristic below. */
9172 : 166583 : if (algs->size[i].max == 0)
9173 : : break;
9174 : 166583 : if (algs->size[i].max >= expected_size || algs->size[i].max == -1)
9175 : : {
9176 : 67486 : enum stringop_alg candidate = algs->size[i].alg;
9177 : :
9178 : 67486 : if (candidate != libcall
9179 : 67486 : && alg_usable_p (candidate, memset, dst_as, src_as))
9180 : : {
9181 : 14895 : alg = candidate;
9182 : 14895 : alg_noalign = algs->size[i].noalign;
9183 : : }
9184 : : /* Honor TARGET_INLINE_ALL_STRINGOPS by picking
9185 : : last non-libcall inline algorithm. */
9186 : 67486 : if (TARGET_INLINE_ALL_STRINGOPS)
9187 : : {
9188 : : /* When the current size is best to be copied by a libcall,
9189 : : but we are still forced to inline, run the heuristic below
9190 : : that will pick code for medium sized blocks. */
9191 : 9955 : if (alg != libcall)
9192 : : {
9193 : 3902 : *noalign = alg_noalign;
9194 : 3902 : return alg;
9195 : : }
9196 : 6053 : else if (!any_alg_usable_p)
9197 : : break;
9198 : : }
9199 : 57531 : else if (alg_usable_p (candidate, memset, dst_as, src_as)
9200 : 57531 : && !(TARGET_PREFER_KNOWN_REP_MOVSB_STOSB
9201 : 22 : && candidate == rep_prefix_1_byte
9202 : : /* NB: If min_size != max_size, size is
9203 : : unknown. */
9204 : 22 : && min_size != max_size))
9205 : : {
9206 : 57512 : *noalign = algs->size[i].noalign;
9207 : 57512 : return candidate;
9208 : : }
9209 : : }
9210 : : }
9211 : : }
9212 : : /* When asked to inline the call anyway, try to pick meaningful choice.
9213 : : We look for maximal size of block that is faster to copy by hand and
9214 : : take blocks of at most of that size guessing that average size will
9215 : : be roughly half of the block.
9216 : :
9217 : : If this turns out to be bad, we might simply specify the preferred
9218 : : choice in ix86_costs. */
9219 : 54090 : if ((TARGET_INLINE_ALL_STRINGOPS || TARGET_INLINE_STRINGOPS_DYNAMICALLY)
9220 : 57343 : && (algs->unknown_size == libcall
9221 : 0 : || !alg_usable_p (algs->unknown_size, memset, dst_as, src_as)))
9222 : : {
9223 : 3253 : enum stringop_alg alg;
9224 : 3253 : HOST_WIDE_INT new_expected_size = (max > 0 ? max : 4096) / 2;
9225 : :
9226 : : /* If there aren't any usable algorithms or if recursing already,
9227 : : then recursing on smaller sizes or same size isn't going to
9228 : : find anything. Just return the simple byte-at-a-time copy loop. */
9229 : 3253 : if (!any_alg_usable_p || recur)
9230 : : {
9231 : : /* Pick something reasonable. */
9232 : 0 : if (TARGET_INLINE_STRINGOPS_DYNAMICALLY && !recur)
9233 : 0 : *dynamic_check = 128;
9234 : 0 : return loop_1_byte;
9235 : : }
9236 : 3253 : alg = decide_alg (count, new_expected_size, min_size, max_size,
9237 : : memset, zero_memset, dst_as, src_as,
9238 : : dynamic_check, noalign, true);
9239 : 3253 : gcc_assert (*dynamic_check == -1);
9240 : 3253 : if (TARGET_INLINE_STRINGOPS_DYNAMICALLY)
9241 : 8 : *dynamic_check = max;
9242 : : else
9243 : 3245 : gcc_assert (alg != libcall);
9244 : 3253 : return alg;
9245 : : }
9246 : :
9247 : : /* Try to use some reasonable fallback algorithm. Note that for
9248 : : non-default address spaces we default to a loop instead of
9249 : : a libcall. */
9250 : :
9251 : 54084 : bool have_as = !(ADDR_SPACE_GENERIC_P (dst_as)
9252 : : && ADDR_SPACE_GENERIC_P (src_as));
9253 : :
9254 : 54084 : return (alg_usable_p (algs->unknown_size, memset, dst_as, src_as)
9255 : 54084 : ? algs->unknown_size : have_as ? loop : libcall);
9256 : : }
9257 : :
9258 : : /* Decide on alignment. We know that the operand is already aligned to ALIGN
9259 : : (ALIGN can be based on profile feedback and thus it is not 100% guaranteed). */
9260 : : static int
9261 : 28893 : decide_alignment (int align,
9262 : : enum stringop_alg alg,
9263 : : int expected_size,
9264 : : machine_mode move_mode)
9265 : : {
9266 : 28893 : int desired_align = 0;
9267 : :
9268 : 28893 : gcc_assert (alg != no_stringop);
9269 : :
9270 : 28893 : if (alg == libcall)
9271 : : return 0;
9272 : 28893 : if (move_mode == VOIDmode)
9273 : : return 0;
9274 : :
9275 : 28893 : desired_align = GET_MODE_SIZE (move_mode);
9276 : : /* PentiumPro has special logic triggering for 8 byte aligned blocks.
9277 : : copying whole cacheline at once. */
9278 : 28893 : if (TARGET_CPU_P (PENTIUMPRO)
9279 : 0 : && (alg == rep_prefix_4_byte || alg == rep_prefix_1_byte))
9280 : 28893 : desired_align = 8;
9281 : :
9282 : 28893 : if (optimize_size)
9283 : 8672 : desired_align = 1;
9284 : 28893 : if (desired_align < align)
9285 : : desired_align = align;
9286 : 28893 : if (expected_size != -1 && expected_size < 4)
9287 : 0 : desired_align = align;
9288 : :
9289 : : return desired_align;
9290 : : }
9291 : :
9292 : :
9293 : : /* Helper function for memcpy. For QImode value 0xXY produce
9294 : : 0xXYXYXYXY of wide specified by MODE. This is essentially
9295 : : a * 0x10101010, but we can do slightly better than
9296 : : synth_mult by unwinding the sequence by hand on CPUs with
9297 : : slow multiply. */
9298 : : static rtx
9299 : 13736 : promote_duplicated_reg (machine_mode mode, rtx val)
9300 : : {
9301 : 13736 : if (val == const0_rtx)
9302 : 11878 : return copy_to_mode_reg (mode, CONST0_RTX (mode));
9303 : :
9304 : 1858 : machine_mode valmode = GET_MODE (val);
9305 : 1858 : if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT)
9306 : : {
9307 : : /* Duplicate the scalar value for integer vector. */
9308 : 1449 : gcc_assert ((val == const0_rtx || val == constm1_rtx)
9309 : : || GET_MODE_INNER (mode) == valmode);
9310 : 733 : rtx dup = gen_reg_rtx (mode);
9311 : 733 : bool ok = ix86_expand_vector_init_duplicate (false, mode, dup,
9312 : : val);
9313 : 733 : gcc_assert (ok);
9314 : : return dup;
9315 : : }
9316 : :
9317 : 1125 : rtx tmp;
9318 : 1125 : int nops = mode == DImode ? 3 : 2;
9319 : :
9320 : 30 : gcc_assert (mode == SImode || mode == DImode);
9321 : 1125 : if (CONST_INT_P (val))
9322 : : {
9323 : 739 : HOST_WIDE_INT v = INTVAL (val) & 255;
9324 : :
9325 : 739 : v |= v << 8;
9326 : 739 : v |= v << 16;
9327 : 739 : if (mode == DImode)
9328 : 717 : v |= (v << 16) << 16;
9329 : 739 : return copy_to_mode_reg (mode, gen_int_mode (v, mode));
9330 : : }
9331 : :
9332 : 386 : if (valmode == VOIDmode)
9333 : : valmode = QImode;
9334 : 386 : if (valmode != QImode)
9335 : 0 : val = gen_lowpart (QImode, val);
9336 : 386 : if (mode == QImode)
9337 : : return val;
9338 : 386 : if (!TARGET_PARTIAL_REG_STALL)
9339 : 386 : nops--;
9340 : 386 : if (ix86_cost->mult_init[mode == DImode ? 3 : 2]
9341 : 386 : + ix86_cost->mult_bit * (mode == DImode ? 8 : 4)
9342 : 386 : <= (ix86_cost->shift_const + ix86_cost->add) * nops
9343 : 386 : + (COSTS_N_INSNS (TARGET_PARTIAL_REG_STALL == 0)))
9344 : : {
9345 : 386 : rtx reg = convert_modes (mode, QImode, val, true);
9346 : 386 : tmp = promote_duplicated_reg (mode, const1_rtx);
9347 : 386 : return expand_simple_binop (mode, MULT, reg, tmp, NULL, 1,
9348 : 386 : OPTAB_DIRECT);
9349 : : }
9350 : : else
9351 : : {
9352 : 0 : rtx reg = convert_modes (mode, QImode, val, true);
9353 : :
9354 : 0 : if (!TARGET_PARTIAL_REG_STALL)
9355 : 0 : emit_insn (gen_insv_1 (mode, reg, reg));
9356 : : else
9357 : : {
9358 : 0 : tmp = expand_simple_binop (mode, ASHIFT, reg, GEN_INT (8),
9359 : : NULL, 1, OPTAB_DIRECT);
9360 : 0 : reg = expand_simple_binop (mode, IOR, reg, tmp, reg, 1,
9361 : : OPTAB_DIRECT);
9362 : : }
9363 : 0 : tmp = expand_simple_binop (mode, ASHIFT, reg, GEN_INT (16),
9364 : : NULL, 1, OPTAB_DIRECT);
9365 : 0 : reg = expand_simple_binop (mode, IOR, reg, tmp, reg, 1, OPTAB_DIRECT);
9366 : 0 : if (mode == SImode)
9367 : : return reg;
9368 : 0 : tmp = expand_simple_binop (mode, ASHIFT, reg, GEN_INT (32),
9369 : : NULL, 1, OPTAB_DIRECT);
9370 : 0 : reg = expand_simple_binop (mode, IOR, reg, tmp, reg, 1, OPTAB_DIRECT);
9371 : 0 : return reg;
9372 : : }
9373 : : }
9374 : :
9375 : : /* Duplicate value VAL using promote_duplicated_reg into maximal size that will
9376 : : be needed by main loop copying SIZE_NEEDED chunks and prologue getting
9377 : : alignment from ALIGN to DESIRED_ALIGN. */
9378 : : static rtx
9379 : 9384 : promote_duplicated_reg_to_size (rtx val, int size_needed, int desired_align,
9380 : : int align)
9381 : : {
9382 : 9384 : rtx promoted_val;
9383 : :
9384 : 9384 : if (TARGET_64BIT
9385 : 7881 : && (size_needed > 4 || (desired_align > align && desired_align > 4)))
9386 : 4316 : promoted_val = promote_duplicated_reg (DImode, val);
9387 : 5068 : else if (size_needed > 2 || (desired_align > align && desired_align > 2))
9388 : 3319 : promoted_val = promote_duplicated_reg (SImode, val);
9389 : 1749 : else if (size_needed > 1 || (desired_align > align && desired_align > 1))
9390 : 0 : promoted_val = promote_duplicated_reg (HImode, val);
9391 : : else
9392 : : promoted_val = val;
9393 : :
9394 : 9384 : return promoted_val;
9395 : : }
9396 : :
9397 : : /* Copy the address to a Pmode register. This is used for x32 to
9398 : : truncate DImode TLS address to a SImode register. */
9399 : :
9400 : : static rtx
9401 : 48402 : ix86_copy_addr_to_reg (rtx addr)
9402 : : {
9403 : 48402 : rtx reg;
9404 : 53073 : if (GET_MODE (addr) == Pmode || GET_MODE (addr) == VOIDmode)
9405 : : {
9406 : 48402 : reg = copy_addr_to_reg (addr);
9407 : 48402 : REG_POINTER (reg) = 1;
9408 : 48402 : return reg;
9409 : : }
9410 : : else
9411 : : {
9412 : 0 : gcc_assert (GET_MODE (addr) == DImode && Pmode == SImode);
9413 : 0 : reg = copy_to_mode_reg (DImode, addr);
9414 : 0 : REG_POINTER (reg) = 1;
9415 : 0 : return gen_rtx_SUBREG (SImode, reg, 0);
9416 : : }
9417 : : }
9418 : :
9419 : : /* Expand string move (memcpy) ot store (memset) operation. Use i386 string
9420 : : operations when profitable. The code depends upon architecture, block size
9421 : : and alignment, but always has one of the following overall structures:
9422 : :
9423 : : Aligned move sequence:
9424 : :
9425 : : 1) Prologue guard: Conditional that jumps up to epilogues for small
9426 : : blocks that can be handled by epilogue alone. This is faster
9427 : : but also needed for correctness, since prologue assume the block
9428 : : is larger than the desired alignment.
9429 : :
9430 : : Optional dynamic check for size and libcall for large
9431 : : blocks is emitted here too, with -minline-stringops-dynamically.
9432 : :
9433 : : 2) Prologue: copy first few bytes in order to get destination
9434 : : aligned to DESIRED_ALIGN. It is emitted only when ALIGN is less
9435 : : than DESIRED_ALIGN and up to DESIRED_ALIGN - ALIGN bytes can be
9436 : : copied. We emit either a jump tree on power of two sized
9437 : : blocks, or a byte loop.
9438 : :
9439 : : 3) Main body: the copying loop itself, copying in SIZE_NEEDED chunks
9440 : : with specified algorithm.
9441 : :
9442 : : 4) Epilogue: code copying tail of the block that is too small to be
9443 : : handled by main body (or up to size guarded by prologue guard).
9444 : :
9445 : : Misaligned move sequence
9446 : :
9447 : : 1) missaligned move prologue/epilogue containing:
9448 : : a) Prologue handling small memory blocks and jumping to done_label
9449 : : (skipped if blocks are known to be large enough)
9450 : : b) Signle move copying first DESIRED_ALIGN-ALIGN bytes if alignment is
9451 : : needed by single possibly misaligned move
9452 : : (skipped if alignment is not needed)
9453 : : c) Copy of last SIZE_NEEDED bytes by possibly misaligned moves
9454 : :
9455 : : 2) Zero size guard dispatching to done_label, if needed
9456 : :
9457 : : 3) dispatch to library call, if needed,
9458 : :
9459 : : 3) Main body: the copying loop itself, copying in SIZE_NEEDED chunks
9460 : : with specified algorithm. */
9461 : : bool
9462 : 129716 : ix86_expand_set_or_cpymem (rtx dst, rtx src, rtx count_exp, rtx val_exp,
9463 : : rtx align_exp, rtx expected_align_exp,
9464 : : rtx expected_size_exp, rtx min_size_exp,
9465 : : rtx max_size_exp, rtx probable_max_size_exp,
9466 : : bool issetmem)
9467 : : {
9468 : 129716 : rtx destreg;
9469 : 129716 : rtx srcreg = NULL;
9470 : 129716 : rtx_code_label *label = NULL;
9471 : 129716 : rtx tmp;
9472 : 129716 : rtx_code_label *jump_around_label = NULL;
9473 : 129716 : HOST_WIDE_INT align = 1;
9474 : 129716 : unsigned HOST_WIDE_INT count = 0;
9475 : 129716 : HOST_WIDE_INT expected_size = -1;
9476 : 129716 : int size_needed = 0, epilogue_size_needed;
9477 : 129716 : int desired_align = 0, align_bytes = 0;
9478 : 129716 : enum stringop_alg alg;
9479 : 129716 : rtx promoted_val = NULL;
9480 : 129716 : rtx vec_promoted_val = NULL;
9481 : 129716 : bool force_loopy_epilogue = false;
9482 : 129716 : int dynamic_check;
9483 : 129716 : bool need_zero_guard = false;
9484 : 129716 : bool noalign;
9485 : 129716 : machine_mode move_mode = VOIDmode;
9486 : 129716 : int unroll_factor = 1;
9487 : : /* TODO: Once value ranges are available, fill in proper data. */
9488 : 129716 : unsigned HOST_WIDE_INT min_size = 0;
9489 : 129716 : unsigned HOST_WIDE_INT max_size = -1;
9490 : 129716 : unsigned HOST_WIDE_INT probable_max_size = -1;
9491 : 129716 : bool misaligned_prologue_used = false;
9492 : 129716 : addr_space_t dst_as, src_as = ADDR_SPACE_GENERIC;
9493 : :
9494 : 129716 : if (CONST_INT_P (align_exp))
9495 : 129716 : align = INTVAL (align_exp);
9496 : : /* i386 can do misaligned access on reasonably increased cost. */
9497 : 129716 : if (CONST_INT_P (expected_align_exp)
9498 : 129716 : && INTVAL (expected_align_exp) > align)
9499 : : align = INTVAL (expected_align_exp);
9500 : : /* ALIGN is the minimum of destination and source alignment, but we care here
9501 : : just about destination alignment. */
9502 : 124070 : else if (!issetmem
9503 : 207774 : && MEM_ALIGN (dst) > (unsigned HOST_WIDE_INT) align * BITS_PER_UNIT)
9504 : 3185 : align = MEM_ALIGN (dst) / BITS_PER_UNIT;
9505 : :
9506 : 129716 : if (CONST_INT_P (count_exp))
9507 : : {
9508 : 61119 : min_size = max_size = probable_max_size = count = expected_size
9509 : 61119 : = INTVAL (count_exp);
9510 : : /* When COUNT is 0, there is nothing to do. */
9511 : 61119 : if (!count)
9512 : : return true;
9513 : : }
9514 : : else
9515 : : {
9516 : 68597 : if (min_size_exp)
9517 : 68597 : min_size = INTVAL (min_size_exp);
9518 : 68597 : if (max_size_exp)
9519 : 53637 : max_size = INTVAL (max_size_exp);
9520 : 68597 : if (probable_max_size_exp)
9521 : 55561 : probable_max_size = INTVAL (probable_max_size_exp);
9522 : 68597 : if (CONST_INT_P (expected_size_exp))
9523 : 68597 : expected_size = INTVAL (expected_size_exp);
9524 : : }
9525 : :
9526 : : /* Make sure we don't need to care about overflow later on. */
9527 : 129714 : if (count > (HOST_WIDE_INT_1U << 30))
9528 : : return false;
9529 : :
9530 : 129538 : dst_as = MEM_ADDR_SPACE (dst);
9531 : 129538 : if (!issetmem)
9532 : 89237 : src_as = MEM_ADDR_SPACE (src);
9533 : :
9534 : : /* Step 0: Decide on preferred algorithm, desired alignment and
9535 : : size of chunks to be copied by main loop. */
9536 : 129538 : alg = decide_alg (count, expected_size, min_size, probable_max_size,
9537 : 40301 : issetmem, issetmem && val_exp == const0_rtx,
9538 : : dst_as, src_as, &dynamic_check, &noalign, false);
9539 : :
9540 : 129538 : if (dump_file)
9541 : 7 : fprintf (dump_file, "Selected stringop expansion strategy: %s\n",
9542 : 7 : stringop_alg_names[alg]);
9543 : :
9544 : 129538 : if (alg == libcall)
9545 : : return false;
9546 : 28893 : gcc_assert (alg != no_stringop);
9547 : :
9548 : 28893 : if (!count)
9549 : 14508 : count_exp = copy_to_mode_reg (GET_MODE (count_exp), count_exp);
9550 : 28893 : destreg = ix86_copy_addr_to_reg (XEXP (dst, 0));
9551 : 28893 : if (!issetmem)
9552 : 19509 : srcreg = ix86_copy_addr_to_reg (XEXP (src, 0));
9553 : :
9554 : 28893 : unroll_factor = 1;
9555 : 28893 : move_mode = word_mode;
9556 : 28893 : int nunits;
9557 : 28893 : switch (alg)
9558 : : {
9559 : 0 : case libcall:
9560 : 0 : case no_stringop:
9561 : 0 : case last_alg:
9562 : 0 : gcc_unreachable ();
9563 : 2477 : case loop_1_byte:
9564 : 2477 : need_zero_guard = true;
9565 : 2477 : move_mode = QImode;
9566 : 2477 : break;
9567 : 45 : case loop:
9568 : 45 : need_zero_guard = true;
9569 : 45 : break;
9570 : 18 : case unrolled_loop:
9571 : 18 : need_zero_guard = true;
9572 : 18 : unroll_factor = (TARGET_64BIT ? 4 : 2);
9573 : : break;
9574 : 14863 : case vector_loop:
9575 : 14863 : need_zero_guard = true;
9576 : 14863 : unroll_factor = 4;
9577 : : /* Get the vector mode to move MOVE_MAX bytes. */
9578 : 14863 : nunits = MOVE_MAX / GET_MODE_SIZE (word_mode);
9579 : 14863 : if (nunits > 1)
9580 : : {
9581 : 14859 : move_mode = mode_for_vector (word_mode, nunits).require ();
9582 : 14859 : gcc_assert (optab_handler (mov_optab, move_mode)
9583 : : != CODE_FOR_nothing);
9584 : : }
9585 : : break;
9586 : 24 : case rep_prefix_8_byte:
9587 : 24 : move_mode = DImode;
9588 : 24 : break;
9589 : 6792 : case rep_prefix_4_byte:
9590 : 6792 : move_mode = SImode;
9591 : 6792 : break;
9592 : 4674 : case rep_prefix_1_byte:
9593 : 4674 : move_mode = QImode;
9594 : 4674 : break;
9595 : : }
9596 : 28893 : size_needed = GET_MODE_SIZE (move_mode) * unroll_factor;
9597 : 28893 : epilogue_size_needed = size_needed;
9598 : :
9599 : : /* If we are going to call any library calls conditionally, make sure any
9600 : : pending stack adjustment happen before the first conditional branch,
9601 : : otherwise they will be emitted before the library call only and won't
9602 : : happen from the other branches. */
9603 : 28893 : if (dynamic_check != -1)
9604 : 7 : do_pending_stack_adjust ();
9605 : :
9606 : 28893 : desired_align = decide_alignment (align, alg, expected_size, move_mode);
9607 : 28893 : if (!TARGET_ALIGN_STRINGOPS || noalign)
9608 : 26341 : align = desired_align;
9609 : :
9610 : : /* Step 1: Prologue guard. */
9611 : :
9612 : : /* Alignment code needs count to be in register. */
9613 : 28893 : if (CONST_INT_P (count_exp) && desired_align > align)
9614 : : {
9615 : 20 : if (INTVAL (count_exp) > desired_align
9616 : 20 : && INTVAL (count_exp) > size_needed)
9617 : : {
9618 : 20 : align_bytes
9619 : 20 : = get_mem_align_offset (dst, desired_align * BITS_PER_UNIT);
9620 : 20 : if (align_bytes <= 0)
9621 : : align_bytes = 0;
9622 : : else
9623 : 0 : align_bytes = desired_align - align_bytes;
9624 : : }
9625 : 0 : if (align_bytes == 0)
9626 : 40 : count_exp = force_reg (counter_mode (count_exp), count_exp);
9627 : : }
9628 : 28893 : gcc_assert (desired_align >= 1 && align >= 1);
9629 : :
9630 : : /* Misaligned move sequences handle both prologue and epilogue at once.
9631 : : Default code generation results in a smaller code for large alignments
9632 : : and also avoids redundant job when sizes are known precisely. */
9633 : 28893 : misaligned_prologue_used
9634 : 57786 : = (TARGET_MISALIGNED_MOVE_STRING_PRO_EPILOGUES
9635 : 28887 : && MAX (desired_align, epilogue_size_needed) <= 32
9636 : 13767 : && desired_align <= epilogue_size_needed
9637 : 35007 : && ((desired_align > align && !align_bytes)
9638 : 6093 : || (!count && epilogue_size_needed > 1)));
9639 : :
9640 : : /* Destination is aligned after the misaligned prologue. */
9641 : 28893 : bool aligned_dstmem = misaligned_prologue_used;
9642 : :
9643 : 28893 : if (noalign && !misaligned_prologue_used)
9644 : : {
9645 : : /* Also use misaligned prologue if alignment isn't needed and
9646 : : destination isn't aligned. Since alignment isn't needed,
9647 : : the destination after prologue won't be aligned. */
9648 : 26341 : aligned_dstmem = (GET_MODE_ALIGNMENT (move_mode)
9649 : 26341 : <= MEM_ALIGN (dst));
9650 : 26341 : if (!aligned_dstmem)
9651 : 9330 : misaligned_prologue_used = true;
9652 : : }
9653 : :
9654 : : /* Do the cheap promotion to allow better CSE across the
9655 : : main loop and epilogue (ie one load of the big constant in the
9656 : : front of all code.
9657 : : For now the misaligned move sequences do not have fast path
9658 : : without broadcasting. */
9659 : 28893 : if (issetmem
9660 : 9384 : && (alg == vector_loop
9661 : 3669 : || CONST_INT_P (val_exp)
9662 : 46 : || misaligned_prologue_used))
9663 : : {
9664 : 3623 : if (alg == vector_loop)
9665 : : {
9666 : 5715 : promoted_val = promote_duplicated_reg_to_size (val_exp,
9667 : 11430 : GET_MODE_SIZE (word_mode),
9668 : : desired_align, align);
9669 : : /* Duplicate the promoted scalar value if not 0 nor -1. */
9670 : 5715 : vec_promoted_val
9671 : 5715 : = promote_duplicated_reg (move_mode,
9672 : 5715 : (val_exp == const0_rtx
9673 : 733 : || val_exp == constm1_rtx)
9674 : : ? val_exp : promoted_val);
9675 : : }
9676 : : else
9677 : : {
9678 : 3623 : promoted_val = promote_duplicated_reg_to_size (val_exp, size_needed,
9679 : : desired_align, align);
9680 : : }
9681 : : }
9682 : : /* Misaligned move sequences handles both prologues and epilogues at once.
9683 : : Default code generation results in smaller code for large alignments and
9684 : : also avoids redundant job when sizes are known precisely. */
9685 : 28847 : if (misaligned_prologue_used)
9686 : : {
9687 : : /* Misaligned move prologue handled small blocks by itself. */
9688 : 9351 : expand_set_or_cpymem_prologue_epilogue_by_misaligned_moves
9689 : 9351 : (dst, src, &destreg, &srcreg,
9690 : : move_mode, promoted_val, vec_promoted_val,
9691 : : &count_exp,
9692 : : &jump_around_label,
9693 : 9351 : desired_align < align
9694 : 0 : ? MAX (desired_align, epilogue_size_needed) : epilogue_size_needed,
9695 : : desired_align, align, &min_size, dynamic_check, issetmem);
9696 : 9351 : if (!issetmem)
9697 : 6778 : src = change_address (src, BLKmode, srcreg);
9698 : 9351 : dst = change_address (dst, BLKmode, destreg);
9699 : 9351 : if (aligned_dstmem)
9700 : 21 : set_mem_align (dst, desired_align * BITS_PER_UNIT);
9701 : 9351 : epilogue_size_needed = 0;
9702 : 9351 : if (need_zero_guard
9703 : 9097 : && min_size < (unsigned HOST_WIDE_INT) size_needed)
9704 : : {
9705 : : /* It is possible that we copied enough so the main loop will not
9706 : : execute. */
9707 : 6061 : gcc_assert (size_needed > 1);
9708 : 6061 : if (jump_around_label == NULL_RTX)
9709 : 49 : jump_around_label = gen_label_rtx ();
9710 : 12122 : emit_cmp_and_jump_insns (count_exp,
9711 : : GEN_INT (size_needed),
9712 : : LTU, 0, counter_mode (count_exp), 1, jump_around_label);
9713 : 6061 : if (expected_size == -1
9714 : 53 : || expected_size < (desired_align - align) / 2 + size_needed)
9715 : 6009 : predict_jump (REG_BR_PROB_BASE * 20 / 100);
9716 : : else
9717 : 52 : predict_jump (REG_BR_PROB_BASE * 60 / 100);
9718 : : }
9719 : : }
9720 : : /* Ensure that alignment prologue won't copy past end of block. */
9721 : 19542 : else if (size_needed > 1 || (desired_align > 1 && desired_align > align))
9722 : : {
9723 : 12391 : epilogue_size_needed = MAX (size_needed - 1, desired_align - align);
9724 : : /* Epilogue always copies COUNT_EXP & EPILOGUE_SIZE_NEEDED bytes.
9725 : : Make sure it is power of 2. */
9726 : 12391 : epilogue_size_needed = 1 << (floor_log2 (epilogue_size_needed) + 1);
9727 : :
9728 : : /* To improve performance of small blocks, we jump around the VAL
9729 : : promoting mode. This mean that if the promoted VAL is not constant,
9730 : : we might not use it in the epilogue and have to use byte
9731 : : loop variant. */
9732 : 12391 : if (issetmem && epilogue_size_needed > 2 && !promoted_val)
9733 : 12391 : force_loopy_epilogue = true;
9734 : 12391 : if ((count && count < (unsigned HOST_WIDE_INT) epilogue_size_needed)
9735 : 12391 : || max_size < (unsigned HOST_WIDE_INT) epilogue_size_needed)
9736 : : {
9737 : : /* If main algorithm works on QImode, no epilogue is needed.
9738 : : For small sizes just don't align anything. */
9739 : 2140 : if (size_needed == 1)
9740 : 0 : desired_align = align;
9741 : : else
9742 : 2140 : goto epilogue;
9743 : : }
9744 : 10251 : else if (!count
9745 : 211 : && min_size < (unsigned HOST_WIDE_INT) epilogue_size_needed)
9746 : : {
9747 : 211 : label = gen_label_rtx ();
9748 : 422 : emit_cmp_and_jump_insns (count_exp,
9749 : : GEN_INT (epilogue_size_needed),
9750 : : LTU, 0, counter_mode (count_exp), 1, label);
9751 : 211 : if (expected_size == -1 || expected_size < epilogue_size_needed)
9752 : 211 : predict_jump (REG_BR_PROB_BASE * 60 / 100);
9753 : : else
9754 : 0 : predict_jump (REG_BR_PROB_BASE * 20 / 100);
9755 : : }
9756 : : }
9757 : :
9758 : : /* Emit code to decide on runtime whether library call or inline should be
9759 : : used. */
9760 : 26753 : if (dynamic_check != -1)
9761 : : {
9762 : 7 : if (!issetmem && CONST_INT_P (count_exp))
9763 : : {
9764 : 1 : if (UINTVAL (count_exp) >= (unsigned HOST_WIDE_INT)dynamic_check)
9765 : : {
9766 : 1 : emit_block_copy_via_libcall (dst, src, count_exp);
9767 : 1 : count_exp = const0_rtx;
9768 : 1 : goto epilogue;
9769 : : }
9770 : : }
9771 : : else
9772 : : {
9773 : 6 : rtx_code_label *hot_label = gen_label_rtx ();
9774 : 6 : if (jump_around_label == NULL_RTX)
9775 : 1 : jump_around_label = gen_label_rtx ();
9776 : 12 : emit_cmp_and_jump_insns (count_exp, GEN_INT (dynamic_check - 1),
9777 : : LEU, 0, counter_mode (count_exp),
9778 : : 1, hot_label);
9779 : 6 : predict_jump (REG_BR_PROB_BASE * 90 / 100);
9780 : 6 : if (issetmem)
9781 : 4 : set_storage_via_libcall (dst, count_exp, val_exp);
9782 : : else
9783 : 2 : emit_block_copy_via_libcall (dst, src, count_exp);
9784 : 6 : emit_jump (jump_around_label);
9785 : 6 : emit_label (hot_label);
9786 : : }
9787 : : }
9788 : :
9789 : : /* Step 2: Alignment prologue. */
9790 : : /* Do the expensive promotion once we branched off the small blocks. */
9791 : 26752 : if (issetmem && !promoted_val)
9792 : 46 : promoted_val = promote_duplicated_reg_to_size (val_exp, size_needed,
9793 : : desired_align, align);
9794 : :
9795 : 26752 : if (desired_align > align && !misaligned_prologue_used)
9796 : : {
9797 : 7 : if (align_bytes == 0)
9798 : : {
9799 : : /* Except for the first move in prologue, we no longer know
9800 : : constant offset in aliasing info. It don't seems to worth
9801 : : the pain to maintain it for the first move, so throw away
9802 : : the info early. */
9803 : 7 : dst = change_address (dst, BLKmode, destreg);
9804 : 7 : if (!issetmem)
9805 : 5 : src = change_address (src, BLKmode, srcreg);
9806 : 7 : dst = expand_set_or_cpymem_prologue (dst, src, destreg, srcreg,
9807 : : promoted_val, vec_promoted_val,
9808 : : count_exp, align, desired_align,
9809 : : issetmem);
9810 : : /* At most desired_align - align bytes are copied. */
9811 : 7 : if (min_size < (unsigned)(desired_align - align))
9812 : 0 : min_size = 0;
9813 : : else
9814 : 7 : min_size -= desired_align - align;
9815 : : }
9816 : : else
9817 : : {
9818 : : /* If we know how many bytes need to be stored before dst is
9819 : : sufficiently aligned, maintain aliasing info accurately. */
9820 : 0 : dst = expand_set_or_cpymem_constant_prologue (dst, &src, destreg,
9821 : : srcreg,
9822 : : promoted_val,
9823 : : vec_promoted_val,
9824 : : desired_align,
9825 : : align_bytes,
9826 : : issetmem);
9827 : :
9828 : 0 : count_exp = plus_constant (counter_mode (count_exp),
9829 : 0 : count_exp, -align_bytes);
9830 : 0 : count -= align_bytes;
9831 : 0 : min_size -= align_bytes;
9832 : 0 : max_size -= align_bytes;
9833 : : }
9834 : 7 : if (need_zero_guard
9835 : 7 : && min_size < (unsigned HOST_WIDE_INT) size_needed
9836 : 1 : && (count < (unsigned HOST_WIDE_INT) size_needed
9837 : 0 : || (align_bytes == 0
9838 : 0 : && count < ((unsigned HOST_WIDE_INT) size_needed
9839 : 0 : + desired_align - align))))
9840 : : {
9841 : : /* It is possible that we copied enough so the main loop will not
9842 : : execute. */
9843 : 1 : gcc_assert (size_needed > 1);
9844 : 1 : if (label == NULL_RTX)
9845 : 0 : label = gen_label_rtx ();
9846 : 2 : emit_cmp_and_jump_insns (count_exp,
9847 : : GEN_INT (size_needed),
9848 : : LTU, 0, counter_mode (count_exp), 1, label);
9849 : 1 : if (expected_size == -1
9850 : 0 : || expected_size < (desired_align - align) / 2 + size_needed)
9851 : 1 : predict_jump (REG_BR_PROB_BASE * 20 / 100);
9852 : : else
9853 : 0 : predict_jump (REG_BR_PROB_BASE * 60 / 100);
9854 : : }
9855 : : }
9856 : 26752 : if (label && size_needed == 1)
9857 : : {
9858 : 0 : emit_label (label);
9859 : 0 : LABEL_NUSES (label) = 1;
9860 : 0 : label = NULL;
9861 : 0 : epilogue_size_needed = 1;
9862 : 0 : if (issetmem)
9863 : 0 : promoted_val = val_exp;
9864 : : }
9865 : 26752 : else if (label == NULL_RTX && !misaligned_prologue_used)
9866 : 17191 : epilogue_size_needed = size_needed;
9867 : :
9868 : : /* Step 3: Main loop. */
9869 : :
9870 : 26752 : switch (alg)
9871 : : {
9872 : 0 : case libcall:
9873 : 0 : case no_stringop:
9874 : 0 : case last_alg:
9875 : 0 : gcc_unreachable ();
9876 : 2540 : case loop_1_byte:
9877 : 2540 : case loop:
9878 : 2540 : case unrolled_loop:
9879 : 2540 : expand_set_or_cpymem_via_loop (dst, src, destreg, srcreg, promoted_val,
9880 : : count_exp, move_mode, unroll_factor,
9881 : : expected_size, issetmem);
9882 : 2540 : break;
9883 : 12722 : case vector_loop:
9884 : 12722 : expand_set_or_cpymem_via_loop (dst, src, destreg, srcreg,
9885 : : vec_promoted_val, count_exp, move_mode,
9886 : : unroll_factor, expected_size, issetmem);
9887 : 12722 : break;
9888 : 11490 : case rep_prefix_8_byte:
9889 : 11490 : case rep_prefix_4_byte:
9890 : 11490 : case rep_prefix_1_byte:
9891 : 11490 : expand_set_or_cpymem_via_rep (dst, src, destreg, srcreg, promoted_val,
9892 : : val_exp, count_exp, move_mode, issetmem);
9893 : 11490 : break;
9894 : : }
9895 : : /* Adjust properly the offset of src and dest memory for aliasing. */
9896 : 26752 : if (CONST_INT_P (count_exp))
9897 : : {
9898 : 14364 : if (!issetmem)
9899 : 7546 : src = adjust_automodify_address_nv (src, BLKmode, srcreg,
9900 : : (count / size_needed) * size_needed);
9901 : 14364 : dst = adjust_automodify_address_nv (dst, BLKmode, destreg,
9902 : : (count / size_needed) * size_needed);
9903 : : }
9904 : : else
9905 : : {
9906 : 12388 : if (!issetmem)
9907 : 10202 : src = change_address (src, BLKmode, srcreg);
9908 : 12388 : dst = change_address (dst, BLKmode, destreg);
9909 : : }
9910 : :
9911 : : /* Step 4: Epilogue to copy the remaining bytes. */
9912 : 28893 : epilogue:
9913 : 28893 : if (label)
9914 : : {
9915 : : /* When the main loop is done, COUNT_EXP might hold original count,
9916 : : while we want to copy only COUNT_EXP & SIZE_NEEDED bytes.
9917 : : Epilogue code will actually copy COUNT_EXP & EPILOGUE_SIZE_NEEDED
9918 : : bytes. Compensate if needed. */
9919 : :
9920 : 211 : if (size_needed < epilogue_size_needed)
9921 : : {
9922 : 0 : tmp = expand_simple_binop (counter_mode (count_exp), AND, count_exp,
9923 : 0 : GEN_INT (size_needed - 1), count_exp, 1,
9924 : : OPTAB_DIRECT);
9925 : 0 : if (tmp != count_exp)
9926 : 0 : emit_move_insn (count_exp, tmp);
9927 : : }
9928 : 211 : emit_label (label);
9929 : 211 : LABEL_NUSES (label) = 1;
9930 : : }
9931 : :
9932 : 28893 : if (count_exp != const0_rtx && epilogue_size_needed > 1)
9933 : : {
9934 : 12391 : if (force_loopy_epilogue)
9935 : 0 : expand_setmem_epilogue_via_loop (dst, destreg, val_exp, count_exp,
9936 : : epilogue_size_needed);
9937 : : else
9938 : : {
9939 : 12391 : if (issetmem)
9940 : 5062 : expand_setmem_epilogue (dst, destreg, promoted_val,
9941 : : vec_promoted_val, count_exp,
9942 : : epilogue_size_needed);
9943 : : else
9944 : 7329 : expand_cpymem_epilogue (dst, src, destreg, srcreg, count_exp,
9945 : : epilogue_size_needed);
9946 : : }
9947 : : }
9948 : 28893 : if (jump_around_label)
9949 : 6063 : emit_label (jump_around_label);
9950 : : return true;
9951 : : }
9952 : :
9953 : : /* Expand cmpstrn or memcmp. */
9954 : :
9955 : : bool
9956 : 205141 : ix86_expand_cmpstrn_or_cmpmem (rtx result, rtx src1, rtx src2,
9957 : : rtx length, rtx align, bool is_cmpstrn)
9958 : : {
9959 : : /* Expand strncmp and memcmp only with -minline-all-stringops since
9960 : : "repz cmpsb" can be much slower than strncmp and memcmp functions
9961 : : implemented with vector instructions, see
9962 : :
9963 : : https://gcc.gnu.org/bugzilla/show_bug.cgi?id=43052
9964 : : */
9965 : 205141 : if (!TARGET_INLINE_ALL_STRINGOPS)
9966 : : return false;
9967 : :
9968 : : /* Can't use this if the user has appropriated ecx, esi or edi. */
9969 : 5777 : if (fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG])
9970 : : return false;
9971 : :
9972 : 5777 : if (is_cmpstrn)
9973 : : {
9974 : : /* For strncmp, length is the maximum length, which can be larger
9975 : : than actual string lengths. We can expand the cmpstrn pattern
9976 : : to "repz cmpsb" only if one of the strings is a constant so
9977 : : that expand_builtin_strncmp() can write the length argument to
9978 : : be the minimum of the const string length and the actual length
9979 : : argument. Otherwise, "repz cmpsb" may pass the 0 byte. */
9980 : 73 : tree t1 = MEM_EXPR (src1);
9981 : 73 : tree t2 = MEM_EXPR (src2);
9982 : 146 : if (!((t1 && TREE_CODE (t1) == MEM_REF
9983 : 73 : && TREE_CODE (TREE_OPERAND (t1, 0)) == ADDR_EXPR
9984 : 0 : && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (t1, 0), 0))
9985 : : == STRING_CST))
9986 : 73 : || (t2 && TREE_CODE (t2) == MEM_REF
9987 : 73 : && TREE_CODE (TREE_OPERAND (t2, 0)) == ADDR_EXPR
9988 : 73 : && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (t2, 0), 0))
9989 : : == STRING_CST))))
9990 : : return false;
9991 : : }
9992 : :
9993 : 5777 : rtx addr1 = copy_addr_to_reg (XEXP (src1, 0));
9994 : 5777 : rtx addr2 = copy_addr_to_reg (XEXP (src2, 0));
9995 : 5777 : if (addr1 != XEXP (src1, 0))
9996 : 5777 : src1 = replace_equiv_address_nv (src1, addr1);
9997 : 5777 : if (addr2 != XEXP (src2, 0))
9998 : 5777 : src2 = replace_equiv_address_nv (src2, addr2);
9999 : :
10000 : : /* NB: Make a copy of the data length to avoid changing the original
10001 : : data length by cmpstrnqi patterns. */
10002 : 5777 : length = ix86_zero_extend_to_Pmode (length);
10003 : 8663 : rtx lengthreg = gen_reg_rtx (Pmode);
10004 : 5777 : emit_move_insn (lengthreg, length);
10005 : :
10006 : : /* If we are testing strict equality, we can use known alignment to
10007 : : good advantage. This may be possible with combine, particularly
10008 : : once cc0 is dead. */
10009 : 5777 : if (CONST_INT_P (length))
10010 : : {
10011 : 0 : if (length == const0_rtx)
10012 : : {
10013 : 0 : emit_move_insn (result, const0_rtx);
10014 : 0 : return true;
10015 : : }
10016 : 0 : emit_insn (gen_cmpstrnqi_nz_1 (addr1, addr2, lengthreg, align,
10017 : : src1, src2));
10018 : : }
10019 : : else
10020 : : {
10021 : 8663 : emit_insn (gen_cmp_1 (Pmode, lengthreg, lengthreg));
10022 : 5777 : emit_insn (gen_cmpstrnqi_1 (addr1, addr2, lengthreg, align,
10023 : : src1, src2));
10024 : : }
10025 : :
10026 : 5777 : rtx out = gen_lowpart (QImode, result);
10027 : 5777 : emit_insn (gen_cmpintqi (out));
10028 : 5777 : emit_move_insn (result, gen_rtx_SIGN_EXTEND (SImode, out));
10029 : :
10030 : 5777 : return true;
10031 : : }
10032 : :
10033 : : /* Expand the appropriate insns for doing strlen if not just doing
10034 : : repnz; scasb
10035 : :
10036 : : out = result, initialized with the start address
10037 : : align_rtx = alignment of the address.
10038 : : scratch = scratch register, initialized with the startaddress when
10039 : : not aligned, otherwise undefined
10040 : :
10041 : : This is just the body. It needs the initializations mentioned above and
10042 : : some address computing at the end. These things are done in i386.md. */
10043 : :
10044 : : static void
10045 : 11 : ix86_expand_strlensi_unroll_1 (rtx out, rtx src, rtx align_rtx)
10046 : : {
10047 : 11 : int align;
10048 : 11 : rtx tmp;
10049 : 11 : rtx_code_label *align_2_label = NULL;
10050 : 11 : rtx_code_label *align_3_label = NULL;
10051 : 11 : rtx_code_label *align_4_label = gen_label_rtx ();
10052 : 11 : rtx_code_label *end_0_label = gen_label_rtx ();
10053 : 11 : rtx mem;
10054 : 11 : rtx tmpreg = gen_reg_rtx (SImode);
10055 : 11 : rtx scratch = gen_reg_rtx (SImode);
10056 : 11 : rtx cmp;
10057 : :
10058 : 11 : align = 0;
10059 : 11 : if (CONST_INT_P (align_rtx))
10060 : 11 : align = INTVAL (align_rtx);
10061 : :
10062 : : /* Loop to check 1..3 bytes for null to get an aligned pointer. */
10063 : :
10064 : : /* Is there a known alignment and is it less than 4? */
10065 : 11 : if (align < 4)
10066 : : {
10067 : 15 : rtx scratch1 = gen_reg_rtx (Pmode);
10068 : 11 : emit_move_insn (scratch1, out);
10069 : : /* Is there a known alignment and is it not 2? */
10070 : 11 : if (align != 2)
10071 : : {
10072 : 11 : align_3_label = gen_label_rtx (); /* Label when aligned to 3-byte */
10073 : 11 : align_2_label = gen_label_rtx (); /* Label when aligned to 2-byte */
10074 : :
10075 : : /* Leave just the 3 lower bits. */
10076 : 15 : align_rtx = expand_binop (Pmode, and_optab, scratch1, GEN_INT (3),
10077 : : NULL_RTX, 0, OPTAB_WIDEN);
10078 : :
10079 : 15 : emit_cmp_and_jump_insns (align_rtx, const0_rtx, EQ, NULL,
10080 : 11 : Pmode, 1, align_4_label);
10081 : 15 : emit_cmp_and_jump_insns (align_rtx, const2_rtx, EQ, NULL,
10082 : 11 : Pmode, 1, align_2_label);
10083 : 15 : emit_cmp_and_jump_insns (align_rtx, const2_rtx, GTU, NULL,
10084 : 11 : Pmode, 1, align_3_label);
10085 : : }
10086 : : else
10087 : : {
10088 : : /* Since the alignment is 2, we have to check 2 or 0 bytes;
10089 : : check if is aligned to 4 - byte. */
10090 : :
10091 : 0 : align_rtx = expand_binop (Pmode, and_optab, scratch1, const2_rtx,
10092 : : NULL_RTX, 0, OPTAB_WIDEN);
10093 : :
10094 : 0 : emit_cmp_and_jump_insns (align_rtx, const0_rtx, EQ, NULL,
10095 : 0 : Pmode, 1, align_4_label);
10096 : : }
10097 : :
10098 : 11 : mem = change_address (src, QImode, out);
10099 : :
10100 : : /* Now compare the bytes. */
10101 : :
10102 : : /* Compare the first n unaligned byte on a byte per byte basis. */
10103 : 11 : emit_cmp_and_jump_insns (mem, const0_rtx, EQ, NULL,
10104 : : QImode, 1, end_0_label);
10105 : :
10106 : : /* Increment the address. */
10107 : 11 : emit_insn (gen_add2_insn (out, const1_rtx));
10108 : :
10109 : : /* Not needed with an alignment of 2 */
10110 : 11 : if (align != 2)
10111 : : {
10112 : 11 : emit_label (align_2_label);
10113 : :
10114 : 11 : emit_cmp_and_jump_insns (mem, const0_rtx, EQ, NULL, QImode, 1,
10115 : : end_0_label);
10116 : :
10117 : 11 : emit_insn (gen_add2_insn (out, const1_rtx));
10118 : :
10119 : 11 : emit_label (align_3_label);
10120 : : }
10121 : :
10122 : 11 : emit_cmp_and_jump_insns (mem, const0_rtx, EQ, NULL, QImode, 1,
10123 : : end_0_label);
10124 : :
10125 : 11 : emit_insn (gen_add2_insn (out, const1_rtx));
10126 : : }
10127 : :
10128 : : /* Generate loop to check 4 bytes at a time. It is not a good idea to
10129 : : align this loop. It gives only huge programs, but does not help to
10130 : : speed up. */
10131 : 11 : emit_label (align_4_label);
10132 : :
10133 : 11 : mem = change_address (src, SImode, out);
10134 : 11 : emit_move_insn (scratch, mem);
10135 : 11 : emit_insn (gen_add2_insn (out, GEN_INT (4)));
10136 : :
10137 : : /* This formula yields a nonzero result iff one of the bytes is zero.
10138 : : This saves three branches inside loop and many cycles. */
10139 : :
10140 : 11 : emit_insn (gen_addsi3 (tmpreg, scratch, GEN_INT (-0x01010101)));
10141 : 11 : emit_insn (gen_one_cmplsi2 (scratch, scratch));
10142 : 11 : emit_insn (gen_andsi3 (tmpreg, tmpreg, scratch));
10143 : 11 : emit_insn (gen_andsi3 (tmpreg, tmpreg,
10144 : : gen_int_mode (0x80808080, SImode)));
10145 : 11 : emit_cmp_and_jump_insns (tmpreg, const0_rtx, EQ, 0, SImode, 1,
10146 : : align_4_label);
10147 : :
10148 : 11 : if (TARGET_CMOVE)
10149 : : {
10150 : 11 : rtx reg = gen_reg_rtx (SImode);
10151 : 15 : rtx reg2 = gen_reg_rtx (Pmode);
10152 : 11 : emit_move_insn (reg, tmpreg);
10153 : 11 : emit_insn (gen_lshrsi3 (reg, reg, GEN_INT (16)));
10154 : :
10155 : : /* If zero is not in the first two bytes, move two bytes forward. */
10156 : 11 : emit_insn (gen_testsi_ccno_1 (tmpreg, GEN_INT (0x8080)));
10157 : 11 : tmp = gen_rtx_REG (CCNOmode, FLAGS_REG);
10158 : 11 : tmp = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
10159 : 11 : emit_insn (gen_rtx_SET (tmpreg,
10160 : : gen_rtx_IF_THEN_ELSE (SImode, tmp,
10161 : : reg,
10162 : : tmpreg)));
10163 : : /* Emit lea manually to avoid clobbering of flags. */
10164 : 15 : emit_insn (gen_rtx_SET (reg2, plus_constant (Pmode, out, 2)));
10165 : :
10166 : 11 : tmp = gen_rtx_REG (CCNOmode, FLAGS_REG);
10167 : 11 : tmp = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
10168 : 15 : emit_insn (gen_rtx_SET (out,
10169 : : gen_rtx_IF_THEN_ELSE (Pmode, tmp,
10170 : : reg2,
10171 : : out)));
10172 : 11 : }
10173 : : else
10174 : : {
10175 : 0 : rtx_code_label *end_2_label = gen_label_rtx ();
10176 : : /* Is zero in the first two bytes? */
10177 : :
10178 : 0 : emit_insn (gen_testsi_ccno_1 (tmpreg, GEN_INT (0x8080)));
10179 : 0 : tmp = gen_rtx_REG (CCNOmode, FLAGS_REG);
10180 : 0 : tmp = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
10181 : 0 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
10182 : : gen_rtx_LABEL_REF (VOIDmode, end_2_label),
10183 : : pc_rtx);
10184 : 0 : tmp = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
10185 : 0 : JUMP_LABEL (tmp) = end_2_label;
10186 : :
10187 : : /* Not in the first two. Move two bytes forward. */
10188 : 0 : emit_insn (gen_lshrsi3 (tmpreg, tmpreg, GEN_INT (16)));
10189 : 0 : emit_insn (gen_add2_insn (out, const2_rtx));
10190 : :
10191 : 0 : emit_label (end_2_label);
10192 : :
10193 : : }
10194 : :
10195 : : /* Avoid branch in fixing the byte. */
10196 : 11 : tmpreg = gen_lowpart (QImode, tmpreg);
10197 : 11 : emit_insn (gen_addqi3_cconly_overflow (tmpreg, tmpreg));
10198 : 11 : tmp = gen_rtx_REG (CCmode, FLAGS_REG);
10199 : 11 : cmp = gen_rtx_LTU (VOIDmode, tmp, const0_rtx);
10200 : 15 : emit_insn (gen_sub3_carry (Pmode, out, out, GEN_INT (3), tmp, cmp));
10201 : :
10202 : 11 : emit_label (end_0_label);
10203 : 11 : }
10204 : :
10205 : : /* Expand strlen. */
10206 : :
10207 : : bool
10208 : 13442 : ix86_expand_strlen (rtx out, rtx src, rtx eoschar, rtx align)
10209 : : {
10210 : 13442 : if (TARGET_UNROLL_STRLEN
10211 : 13442 : && TARGET_INLINE_ALL_STRINGOPS
10212 : 11 : && eoschar == const0_rtx
10213 : 11 : && optimize > 1)
10214 : : {
10215 : : /* The generic case of strlen expander is long. Avoid it's
10216 : : expanding unless TARGET_INLINE_ALL_STRINGOPS. */
10217 : 15 : rtx addr = force_reg (Pmode, XEXP (src, 0));
10218 : : /* Well it seems that some optimizer does not combine a call like
10219 : : foo(strlen(bar), strlen(bar));
10220 : : when the move and the subtraction is done here. It does calculate
10221 : : the length just once when these instructions are done inside of
10222 : : output_strlen_unroll(). But I think since &bar[strlen(bar)] is
10223 : : often used and I use one fewer register for the lifetime of
10224 : : output_strlen_unroll() this is better. */
10225 : :
10226 : 11 : emit_move_insn (out, addr);
10227 : :
10228 : 11 : ix86_expand_strlensi_unroll_1 (out, src, align);
10229 : :
10230 : : /* strlensi_unroll_1 returns the address of the zero at the end of
10231 : : the string, like memchr(), so compute the length by subtracting
10232 : : the start address. */
10233 : 11 : emit_insn (gen_sub2_insn (out, addr));
10234 : 11 : return true;
10235 : : }
10236 : : else
10237 : : return false;
10238 : : }
10239 : :
10240 : : /* For given symbol (function) construct code to compute address of it's PLT
10241 : : entry in large x86-64 PIC model. */
10242 : :
10243 : : static rtx
10244 : 31 : construct_plt_address (rtx symbol)
10245 : : {
10246 : 31 : rtx tmp, unspec;
10247 : :
10248 : 31 : gcc_assert (GET_CODE (symbol) == SYMBOL_REF);
10249 : 31 : gcc_assert (ix86_cmodel == CM_LARGE_PIC && !TARGET_PECOFF);
10250 : 31 : gcc_assert (Pmode == DImode);
10251 : :
10252 : 31 : tmp = gen_reg_rtx (Pmode);
10253 : 31 : unspec = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, symbol), UNSPEC_PLTOFF);
10254 : :
10255 : 31 : emit_move_insn (tmp, gen_rtx_CONST (Pmode, unspec));
10256 : 31 : emit_insn (gen_add2_insn (tmp, pic_offset_table_rtx));
10257 : 31 : return tmp;
10258 : : }
10259 : :
10260 : : /* Additional registers that are clobbered by SYSV calls. */
10261 : :
10262 : : static int const x86_64_ms_sysv_extra_clobbered_registers
10263 : : [NUM_X86_64_MS_CLOBBERED_REGS] =
10264 : : {
10265 : : SI_REG, DI_REG,
10266 : : XMM6_REG, XMM7_REG,
10267 : : XMM8_REG, XMM9_REG, XMM10_REG, XMM11_REG,
10268 : : XMM12_REG, XMM13_REG, XMM14_REG, XMM15_REG
10269 : : };
10270 : :
10271 : : rtx_insn *
10272 : 6187928 : ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1,
10273 : : rtx callarg2,
10274 : : rtx pop, bool sibcall)
10275 : : {
10276 : 6187928 : rtx vec[3];
10277 : 6187928 : rtx use = NULL, call;
10278 : 6187928 : unsigned int vec_len = 0;
10279 : 6187928 : tree fndecl;
10280 : 6187928 : bool call_no_callee_saved_registers = false;
10281 : :
10282 : 6187928 : if (GET_CODE (XEXP (fnaddr, 0)) == SYMBOL_REF)
10283 : : {
10284 : 5998624 : fndecl = SYMBOL_REF_DECL (XEXP (fnaddr, 0));
10285 : 5998624 : if (fndecl)
10286 : : {
10287 : 5738835 : if (lookup_attribute ("interrupt",
10288 : 5738835 : TYPE_ATTRIBUTES (TREE_TYPE (fndecl))))
10289 : 1 : error ("interrupt service routine cannot be called directly");
10290 : 5738834 : else if (ix86_type_no_callee_saved_registers_p (TREE_TYPE (fndecl)))
10291 : 5738835 : call_no_callee_saved_registers = true;
10292 : 5738835 : if (fndecl == current_function_decl
10293 : 5738835 : && decl_binds_to_current_def_p (fndecl))
10294 : 10343 : cfun->machine->recursive_function = true;
10295 : : }
10296 : : }
10297 : : else
10298 : : {
10299 : 189304 : if (MEM_P (fnaddr))
10300 : : {
10301 : 189304 : tree mem_expr = MEM_EXPR (fnaddr);
10302 : 189304 : if (mem_expr != nullptr
10303 : 189259 : && TREE_CODE (mem_expr) == MEM_REF
10304 : 378563 : && ix86_type_no_callee_saved_registers_p (TREE_TYPE (mem_expr)))
10305 : : call_no_callee_saved_registers = true;
10306 : : }
10307 : :
10308 : : fndecl = NULL_TREE;
10309 : : }
10310 : :
10311 : 6187928 : if (pop == const0_rtx)
10312 : 0 : pop = NULL;
10313 : 6187928 : gcc_assert (!TARGET_64BIT || !pop);
10314 : :
10315 : 6187928 : rtx addr = XEXP (fnaddr, 0);
10316 : 6187928 : if (TARGET_MACHO && !TARGET_64BIT)
10317 : : {
10318 : : #if TARGET_MACHO
10319 : : if (flag_pic && GET_CODE (XEXP (fnaddr, 0)) == SYMBOL_REF)
10320 : : fnaddr = machopic_indirect_call_target (fnaddr);
10321 : : #endif
10322 : : }
10323 : : else
10324 : : {
10325 : : /* Static functions and indirect calls don't need the pic register. Also,
10326 : : check if PLT was explicitly avoided via no-plt or "noplt" attribute, making
10327 : : it an indirect call. */
10328 : 6187928 : if (flag_pic
10329 : 510882 : && GET_CODE (addr) == SYMBOL_REF
10330 : 6672946 : && ix86_call_use_plt_p (addr))
10331 : : {
10332 : 387938 : if (flag_plt
10333 : 387938 : && (SYMBOL_REF_DECL (addr) == NULL_TREE
10334 : 387904 : || !lookup_attribute ("noplt",
10335 : 387904 : DECL_ATTRIBUTES (SYMBOL_REF_DECL (addr)))))
10336 : : {
10337 : 387903 : if (!TARGET_64BIT
10338 : 212812 : || (ix86_cmodel == CM_LARGE_PIC
10339 : : && DEFAULT_ABI != MS_ABI))
10340 : : {
10341 : 525304 : use_reg (&use, gen_rtx_REG (Pmode,
10342 : : REAL_PIC_OFFSET_TABLE_REGNUM));
10343 : 175122 : if (ix86_use_pseudo_pic_reg ())
10344 : 350213 : emit_move_insn (gen_rtx_REG (Pmode,
10345 : 175122 : REAL_PIC_OFFSET_TABLE_REGNUM),
10346 : : pic_offset_table_rtx);
10347 : : }
10348 : : }
10349 : 35 : else if (!TARGET_PECOFF && !TARGET_MACHO)
10350 : : {
10351 : 35 : if (TARGET_64BIT
10352 : 35 : && ix86_cmodel == CM_LARGE_PIC
10353 : : && DEFAULT_ABI != MS_ABI)
10354 : : {
10355 : 1 : fnaddr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr),
10356 : : UNSPEC_GOT);
10357 : 1 : fnaddr = gen_rtx_CONST (Pmode, fnaddr);
10358 : 1 : fnaddr = force_reg (Pmode, fnaddr);
10359 : 1 : fnaddr = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, fnaddr);
10360 : : }
10361 : 34 : else if (TARGET_64BIT)
10362 : : {
10363 : 38 : fnaddr = gen_rtx_UNSPEC (Pmode,
10364 : : gen_rtvec (1, addr),
10365 : : UNSPEC_GOTPCREL);
10366 : 38 : fnaddr = gen_rtx_CONST (Pmode, fnaddr);
10367 : : }
10368 : : else
10369 : : {
10370 : 0 : fnaddr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr),
10371 : : UNSPEC_GOT);
10372 : 0 : fnaddr = gen_rtx_CONST (Pmode, fnaddr);
10373 : 0 : fnaddr = gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
10374 : : fnaddr);
10375 : : }
10376 : 39 : fnaddr = gen_const_mem (Pmode, fnaddr);
10377 : : /* Pmode may not be the same as word_mode for x32, which
10378 : : doesn't support indirect branch via 32-bit memory slot.
10379 : : Since x32 GOT slot is 64 bit with zero upper 32 bits,
10380 : : indirect branch via x32 GOT slot is OK. */
10381 : 35 : if (GET_MODE (fnaddr) != word_mode)
10382 : 4 : fnaddr = gen_rtx_ZERO_EXTEND (word_mode, fnaddr);
10383 : 35 : fnaddr = gen_rtx_MEM (QImode, fnaddr);
10384 : : }
10385 : : }
10386 : : }
10387 : :
10388 : : /* Skip setting up RAX register for -mskip-rax-setup when there are no
10389 : : parameters passed in vector registers. */
10390 : 6187928 : if (TARGET_64BIT
10391 : 5354151 : && (INTVAL (callarg2) > 0
10392 : 5293028 : || (INTVAL (callarg2) == 0
10393 : 317683 : && (TARGET_SSE || !flag_skip_rax_setup))))
10394 : : {
10395 : 378804 : rtx al = gen_rtx_REG (QImode, AX_REG);
10396 : 378804 : emit_move_insn (al, callarg2);
10397 : 378804 : use_reg (&use, al);
10398 : : }
10399 : :
10400 : 6187928 : if (ix86_cmodel == CM_LARGE_PIC
10401 : : && !TARGET_PECOFF
10402 : 41 : && MEM_P (fnaddr)
10403 : 41 : && GET_CODE (XEXP (fnaddr, 0)) == SYMBOL_REF
10404 : 6187961 : && !local_symbolic_operand (XEXP (fnaddr, 0), VOIDmode))
10405 : 31 : fnaddr = gen_rtx_MEM (QImode, construct_plt_address (XEXP (fnaddr, 0)));
10406 : : /* Since x32 GOT slot is 64 bit with zero upper 32 bits, indirect
10407 : : branch via x32 GOT slot is OK. */
10408 : 6187897 : else if (TARGET_X32
10409 : 75 : && MEM_P (fnaddr)
10410 : 75 : && GET_CODE (XEXP (fnaddr, 0)) == ZERO_EXTEND
10411 : 8 : && GOT_memory_operand (XEXP (XEXP (fnaddr, 0), 0), Pmode)
10412 : 6187901 : && !TARGET_INDIRECT_BRANCH_REGISTER)
10413 : : ;
10414 : 6187897 : else if (sibcall
10415 : 6187897 : ? !sibcall_insn_operand (XEXP (fnaddr, 0), word_mode)
10416 : 6062632 : : !call_insn_operand (XEXP (fnaddr, 0), word_mode))
10417 : : {
10418 : 531 : fnaddr = convert_to_mode (word_mode, XEXP (fnaddr, 0), 1);
10419 : 531 : fnaddr = gen_rtx_MEM (QImode, copy_to_mode_reg (word_mode, fnaddr));
10420 : : }
10421 : :
10422 : : /* PR100665: Hwasan may tag code pointer which is not supported by LAM,
10423 : : mask off code pointers here.
10424 : : TODO: also need to handle indirect jump. */
10425 : 6189008 : if (ix86_memtag_can_tag_addresses () && !fndecl
10426 : 6187952 : && sanitize_flags_p (SANITIZE_HWADDRESS))
10427 : : {
10428 : 24 : rtx untagged_addr = ix86_memtag_untagged_pointer (XEXP (fnaddr, 0),
10429 : : NULL_RTX);
10430 : 24 : fnaddr = gen_rtx_MEM (QImode, untagged_addr);
10431 : : }
10432 : :
10433 : 6187928 : call = gen_rtx_CALL (VOIDmode, fnaddr, callarg1);
10434 : :
10435 : 6187928 : if (retval)
10436 : 2466958 : call = gen_rtx_SET (retval, call);
10437 : 6187928 : vec[vec_len++] = call;
10438 : :
10439 : 6187928 : if (pop)
10440 : : {
10441 : 449060 : pop = gen_rtx_PLUS (Pmode, stack_pointer_rtx, pop);
10442 : 224530 : pop = gen_rtx_SET (stack_pointer_rtx, pop);
10443 : 224530 : vec[vec_len++] = pop;
10444 : : }
10445 : :
10446 : 6187928 : static const char ix86_call_used_regs[] = CALL_USED_REGISTERS;
10447 : :
10448 : 6187928 : if ((cfun->machine->call_saved_registers
10449 : 6187928 : == TYPE_NO_CALLER_SAVED_REGISTERS)
10450 : 6187928 : && (!fndecl
10451 : 465 : || (!TREE_THIS_VOLATILE (fndecl)
10452 : 183 : && !lookup_attribute ("no_caller_saved_registers",
10453 : 183 : TYPE_ATTRIBUTES (TREE_TYPE (fndecl))))))
10454 : : {
10455 : 179 : bool is_64bit_ms_abi = (TARGET_64BIT
10456 : 179 : && ix86_function_abi (fndecl) == MS_ABI);
10457 : 179 : char c_mask = CALL_USED_REGISTERS_MASK (is_64bit_ms_abi);
10458 : :
10459 : : /* If there are no caller-saved registers, add all registers
10460 : : that are clobbered by the call which returns. */
10461 : 16647 : for (int i = 0; i < FIRST_PSEUDO_REGISTER; i++)
10462 : 16468 : if (!fixed_regs[i]
10463 : 3245 : && (ix86_call_used_regs[i] == 1
10464 : 1472 : || (ix86_call_used_regs[i] & c_mask))
10465 : 2171 : && !STACK_REGNO_P (i)
10466 : 2139 : && !MMX_REGNO_P (i))
10467 : 2107 : clobber_reg (&use,
10468 : 2107 : gen_rtx_REG (GET_MODE (regno_reg_rtx[i]), i));
10469 : : }
10470 : 5353972 : else if (TARGET_64BIT_MS_ABI
10471 : 6261152 : && (!callarg2 || INTVAL (callarg2) != -2))
10472 : : {
10473 : : unsigned i;
10474 : :
10475 : 861718 : for (i = 0; i < NUM_X86_64_MS_CLOBBERED_REGS; i++)
10476 : : {
10477 : 795432 : int regno = x86_64_ms_sysv_extra_clobbered_registers[i];
10478 : 795432 : machine_mode mode = SSE_REGNO_P (regno) ? TImode : DImode;
10479 : :
10480 : 795432 : clobber_reg (&use, gen_rtx_REG (mode, regno));
10481 : : }
10482 : :
10483 : : /* Set here, but it may get cleared later. */
10484 : 66286 : if (TARGET_CALL_MS2SYSV_XLOGUES)
10485 : : {
10486 : 7046 : if (!TARGET_SSE)
10487 : : ;
10488 : :
10489 : : /* Don't break hot-patched functions. */
10490 : 7046 : else if (ix86_function_ms_hook_prologue (current_function_decl))
10491 : : ;
10492 : :
10493 : : /* TODO: Cases not yet examined. */
10494 : 7046 : else if (flag_split_stack)
10495 : 0 : warn_once_call_ms2sysv_xlogues ("-fsplit-stack");
10496 : :
10497 : : else
10498 : : {
10499 : 7046 : gcc_assert (!reload_completed);
10500 : 7046 : cfun->machine->call_ms2sysv = true;
10501 : : }
10502 : : }
10503 : : }
10504 : :
10505 : 6187928 : if (TARGET_MACHO && TARGET_64BIT && !sibcall
10506 : : && ((GET_CODE (addr) == SYMBOL_REF && !SYMBOL_REF_LOCAL_P (addr))
10507 : : || !fndecl || TREE_PUBLIC (fndecl)))
10508 : : {
10509 : : /* We allow public functions defined in a TU to bind locally for PIC
10510 : : code (the default) on 64bit Mach-O.
10511 : : If such functions are not inlined, we cannot tell at compile-time if
10512 : : they will be called via the lazy symbol resolver (this can depend on
10513 : : options given at link-time). Therefore, we must assume that the lazy
10514 : : resolver could be used which clobbers R11 and R10. */
10515 : : clobber_reg (&use, gen_rtx_REG (DImode, R11_REG));
10516 : : clobber_reg (&use, gen_rtx_REG (DImode, R10_REG));
10517 : : }
10518 : :
10519 : 6187928 : if (call_no_callee_saved_registers)
10520 : : {
10521 : : /* After calling a no_callee_saved_registers function, all
10522 : : registers may be clobbered. Clobber all registers that are
10523 : : not used by the callee. */
10524 : 59 : bool is_64bit_ms_abi = (TARGET_64BIT
10525 : 59 : && ix86_function_abi (fndecl) == MS_ABI);
10526 : 59 : char c_mask = CALL_USED_REGISTERS_MASK (is_64bit_ms_abi);
10527 : 5487 : for (int i = 0; i < FIRST_PSEUDO_REGISTER; i++)
10528 : 5428 : if (!fixed_regs[i]
10529 : 2789 : && i != HARD_FRAME_POINTER_REGNUM
10530 : 2730 : && !(ix86_call_used_regs[i] == 1
10531 : 973 : || (ix86_call_used_regs[i] & c_mask))
10532 : 295 : && !STACK_REGNO_P (i)
10533 : 295 : && !MMX_REGNO_P (i))
10534 : 295 : clobber_reg (&use,
10535 : 295 : gen_rtx_REG (GET_MODE (regno_reg_rtx[i]), i));
10536 : : }
10537 : :
10538 : 6187928 : if (vec_len > 1)
10539 : 224530 : call = gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (vec_len, vec));
10540 : 6187928 : rtx_insn *call_insn = emit_call_insn (call);
10541 : 6187928 : if (use)
10542 : 594351 : CALL_INSN_FUNCTION_USAGE (call_insn) = use;
10543 : :
10544 : 6187928 : return call_insn;
10545 : : }
10546 : :
10547 : : /* Split simple return with popping POPC bytes from stack to indirect
10548 : : branch with stack adjustment . */
10549 : :
10550 : : void
10551 : 0 : ix86_split_simple_return_pop_internal (rtx popc)
10552 : : {
10553 : 0 : struct machine_function *m = cfun->machine;
10554 : 0 : rtx ecx = gen_rtx_REG (SImode, CX_REG);
10555 : 0 : rtx_insn *insn;
10556 : :
10557 : : /* There is no "pascal" calling convention in any 64bit ABI. */
10558 : 0 : gcc_assert (!TARGET_64BIT);
10559 : :
10560 : 0 : insn = emit_insn (gen_pop (ecx));
10561 : 0 : m->fs.cfa_offset -= UNITS_PER_WORD;
10562 : 0 : m->fs.sp_offset -= UNITS_PER_WORD;
10563 : :
10564 : 0 : rtx x = plus_constant (Pmode, stack_pointer_rtx, UNITS_PER_WORD);
10565 : 0 : x = gen_rtx_SET (stack_pointer_rtx, x);
10566 : 0 : add_reg_note (insn, REG_CFA_ADJUST_CFA, x);
10567 : 0 : add_reg_note (insn, REG_CFA_REGISTER, gen_rtx_SET (ecx, pc_rtx));
10568 : 0 : RTX_FRAME_RELATED_P (insn) = 1;
10569 : :
10570 : 0 : x = gen_rtx_PLUS (Pmode, stack_pointer_rtx, popc);
10571 : 0 : x = gen_rtx_SET (stack_pointer_rtx, x);
10572 : 0 : insn = emit_insn (x);
10573 : 0 : add_reg_note (insn, REG_CFA_ADJUST_CFA, x);
10574 : 0 : RTX_FRAME_RELATED_P (insn) = 1;
10575 : :
10576 : : /* Now return address is in ECX. */
10577 : 0 : emit_jump_insn (gen_simple_return_indirect_internal (ecx));
10578 : 0 : }
10579 : :
10580 : : /* Errors in the source file can cause expand_expr to return const0_rtx
10581 : : where we expect a vector. To avoid crashing, use one of the vector
10582 : : clear instructions. */
10583 : :
10584 : : static rtx
10585 : 192966 : safe_vector_operand (rtx x, machine_mode mode)
10586 : : {
10587 : 0 : if (x == const0_rtx)
10588 : 0 : x = CONST0_RTX (mode);
10589 : 24 : return x;
10590 : : }
10591 : :
10592 : : /* Subroutine of ix86_expand_builtin to take care of binop insns. */
10593 : :
10594 : : static rtx
10595 : 8939 : ix86_expand_binop_builtin (enum insn_code icode, tree exp, rtx target)
10596 : : {
10597 : 8939 : rtx pat;
10598 : 8939 : tree arg0 = CALL_EXPR_ARG (exp, 0);
10599 : 8939 : tree arg1 = CALL_EXPR_ARG (exp, 1);
10600 : 8939 : rtx op0 = expand_normal (arg0);
10601 : 8939 : rtx op1 = expand_normal (arg1);
10602 : 8939 : machine_mode tmode = insn_data[icode].operand[0].mode;
10603 : 8939 : machine_mode mode0 = insn_data[icode].operand[1].mode;
10604 : 8939 : machine_mode mode1 = insn_data[icode].operand[2].mode;
10605 : :
10606 : 8939 : if (VECTOR_MODE_P (mode0))
10607 : 8934 : op0 = safe_vector_operand (op0, mode0);
10608 : 8939 : if (VECTOR_MODE_P (mode1))
10609 : 8798 : op1 = safe_vector_operand (op1, mode1);
10610 : :
10611 : 2858 : if (optimize || !target
10612 : 2858 : || GET_MODE (target) != tmode
10613 : 11797 : || !insn_data[icode].operand[0].predicate (target, tmode))
10614 : 6134 : target = gen_reg_rtx (tmode);
10615 : :
10616 : 8939 : if (GET_MODE (op1) == SImode && mode1 == TImode)
10617 : : {
10618 : 0 : rtx x = gen_reg_rtx (V4SImode);
10619 : 0 : emit_insn (gen_sse2_loadd (x, op1));
10620 : 0 : op1 = gen_lowpart (TImode, x);
10621 : : }
10622 : :
10623 : 8939 : if (!insn_data[icode].operand[1].predicate (op0, mode0))
10624 : 1405 : op0 = copy_to_mode_reg (mode0, op0);
10625 : 8939 : if (!insn_data[icode].operand[2].predicate (op1, mode1))
10626 : 815 : op1 = copy_to_mode_reg (mode1, op1);
10627 : :
10628 : 8939 : pat = GEN_FCN (icode) (target, op0, op1);
10629 : 8939 : if (! pat)
10630 : : return 0;
10631 : :
10632 : 8939 : emit_insn (pat);
10633 : :
10634 : 8939 : return target;
10635 : : }
10636 : :
10637 : : /* Subroutine of ix86_expand_builtin to take care of 2-4 argument insns. */
10638 : :
10639 : : static rtx
10640 : 1795 : ix86_expand_multi_arg_builtin (enum insn_code icode, tree exp, rtx target,
10641 : : enum ix86_builtin_func_type m_type,
10642 : : enum rtx_code sub_code)
10643 : : {
10644 : 1795 : rtx pat;
10645 : 1795 : unsigned int i, nargs;
10646 : 1795 : bool comparison_p = false;
10647 : 1795 : bool tf_p = false;
10648 : 1795 : bool last_arg_constant = false;
10649 : 1795 : int num_memory = 0;
10650 : 1795 : rtx xops[4];
10651 : :
10652 : 1795 : machine_mode tmode = insn_data[icode].operand[0].mode;
10653 : :
10654 : 1795 : switch (m_type)
10655 : : {
10656 : : case MULTI_ARG_4_DF2_DI_I:
10657 : : case MULTI_ARG_4_DF2_DI_I1:
10658 : : case MULTI_ARG_4_SF2_SI_I:
10659 : : case MULTI_ARG_4_SF2_SI_I1:
10660 : : nargs = 4;
10661 : : last_arg_constant = true;
10662 : : break;
10663 : :
10664 : 824 : case MULTI_ARG_3_SF:
10665 : 824 : case MULTI_ARG_3_DF:
10666 : 824 : case MULTI_ARG_3_SF2:
10667 : 824 : case MULTI_ARG_3_DF2:
10668 : 824 : case MULTI_ARG_3_DI:
10669 : 824 : case MULTI_ARG_3_SI:
10670 : 824 : case MULTI_ARG_3_SI_DI:
10671 : 824 : case MULTI_ARG_3_HI:
10672 : 824 : case MULTI_ARG_3_HI_SI:
10673 : 824 : case MULTI_ARG_3_QI:
10674 : 824 : case MULTI_ARG_3_DI2:
10675 : 824 : case MULTI_ARG_3_SI2:
10676 : 824 : case MULTI_ARG_3_HI2:
10677 : 824 : case MULTI_ARG_3_QI2:
10678 : 824 : nargs = 3;
10679 : 824 : break;
10680 : :
10681 : 128 : case MULTI_ARG_2_SF:
10682 : 128 : case MULTI_ARG_2_DF:
10683 : 128 : case MULTI_ARG_2_DI:
10684 : 128 : case MULTI_ARG_2_SI:
10685 : 128 : case MULTI_ARG_2_HI:
10686 : 128 : case MULTI_ARG_2_QI:
10687 : 128 : nargs = 2;
10688 : 128 : break;
10689 : :
10690 : 64 : case MULTI_ARG_2_DI_IMM:
10691 : 64 : case MULTI_ARG_2_SI_IMM:
10692 : 64 : case MULTI_ARG_2_HI_IMM:
10693 : 64 : case MULTI_ARG_2_QI_IMM:
10694 : 64 : nargs = 2;
10695 : 64 : last_arg_constant = true;
10696 : 64 : break;
10697 : :
10698 : 187 : case MULTI_ARG_1_SF:
10699 : 187 : case MULTI_ARG_1_DF:
10700 : 187 : case MULTI_ARG_1_SF2:
10701 : 187 : case MULTI_ARG_1_DF2:
10702 : 187 : case MULTI_ARG_1_DI:
10703 : 187 : case MULTI_ARG_1_SI:
10704 : 187 : case MULTI_ARG_1_HI:
10705 : 187 : case MULTI_ARG_1_QI:
10706 : 187 : case MULTI_ARG_1_SI_DI:
10707 : 187 : case MULTI_ARG_1_HI_DI:
10708 : 187 : case MULTI_ARG_1_HI_SI:
10709 : 187 : case MULTI_ARG_1_QI_DI:
10710 : 187 : case MULTI_ARG_1_QI_SI:
10711 : 187 : case MULTI_ARG_1_QI_HI:
10712 : 187 : nargs = 1;
10713 : 187 : break;
10714 : :
10715 : 384 : case MULTI_ARG_2_DI_CMP:
10716 : 384 : case MULTI_ARG_2_SI_CMP:
10717 : 384 : case MULTI_ARG_2_HI_CMP:
10718 : 384 : case MULTI_ARG_2_QI_CMP:
10719 : 384 : nargs = 2;
10720 : 384 : comparison_p = true;
10721 : 384 : break;
10722 : :
10723 : 128 : case MULTI_ARG_2_SF_TF:
10724 : 128 : case MULTI_ARG_2_DF_TF:
10725 : 128 : case MULTI_ARG_2_DI_TF:
10726 : 128 : case MULTI_ARG_2_SI_TF:
10727 : 128 : case MULTI_ARG_2_HI_TF:
10728 : 128 : case MULTI_ARG_2_QI_TF:
10729 : 128 : nargs = 2;
10730 : 128 : tf_p = true;
10731 : 128 : break;
10732 : :
10733 : 0 : default:
10734 : 0 : gcc_unreachable ();
10735 : : }
10736 : :
10737 : 628 : if (optimize || !target
10738 : 628 : || GET_MODE (target) != tmode
10739 : 2399 : || !insn_data[icode].operand[0].predicate (target, tmode))
10740 : 1191 : target = gen_reg_rtx (tmode);
10741 : 604 : else if (memory_operand (target, tmode))
10742 : 0 : num_memory++;
10743 : :
10744 : 1795 : gcc_assert (nargs <= ARRAY_SIZE (xops));
10745 : :
10746 : 6174 : for (i = 0; i < nargs; i++)
10747 : : {
10748 : 4387 : tree arg = CALL_EXPR_ARG (exp, i);
10749 : 4387 : rtx op = expand_normal (arg);
10750 : 4387 : int adjust = (comparison_p) ? 1 : 0;
10751 : 4387 : machine_mode mode = insn_data[icode].operand[i+adjust+1].mode;
10752 : :
10753 : 4387 : if (last_arg_constant && i == nargs - 1)
10754 : : {
10755 : 144 : if (!insn_data[icode].operand[i + 1].predicate (op, mode))
10756 : : {
10757 : 30 : enum insn_code new_icode = icode;
10758 : 30 : switch (icode)
10759 : : {
10760 : 8 : case CODE_FOR_xop_vpermil2v2df3:
10761 : 8 : case CODE_FOR_xop_vpermil2v4sf3:
10762 : 8 : case CODE_FOR_xop_vpermil2v4df3:
10763 : 8 : case CODE_FOR_xop_vpermil2v8sf3:
10764 : 8 : error ("the last argument must be a 2-bit immediate");
10765 : 8 : return gen_reg_rtx (tmode);
10766 : 5 : case CODE_FOR_xop_rotlv2di3:
10767 : 5 : new_icode = CODE_FOR_rotlv2di3;
10768 : 5 : goto xop_rotl;
10769 : 5 : case CODE_FOR_xop_rotlv4si3:
10770 : 5 : new_icode = CODE_FOR_rotlv4si3;
10771 : 5 : goto xop_rotl;
10772 : 6 : case CODE_FOR_xop_rotlv8hi3:
10773 : 6 : new_icode = CODE_FOR_rotlv8hi3;
10774 : 6 : goto xop_rotl;
10775 : : case CODE_FOR_xop_rotlv16qi3:
10776 : : new_icode = CODE_FOR_rotlv16qi3;
10777 : 22 : xop_rotl:
10778 : 22 : if (CONST_INT_P (op))
10779 : : {
10780 : 6 : int mask = GET_MODE_UNIT_BITSIZE (tmode) - 1;
10781 : 6 : op = GEN_INT (INTVAL (op) & mask);
10782 : 6 : gcc_checking_assert
10783 : : (insn_data[icode].operand[i + 1].predicate (op, mode));
10784 : : }
10785 : : else
10786 : : {
10787 : 16 : gcc_checking_assert
10788 : : (nargs == 2
10789 : : && insn_data[new_icode].operand[0].mode == tmode
10790 : : && insn_data[new_icode].operand[1].mode == tmode
10791 : : && insn_data[new_icode].operand[2].mode == mode
10792 : : && insn_data[new_icode].operand[0].predicate
10793 : : == insn_data[icode].operand[0].predicate
10794 : : && insn_data[new_icode].operand[1].predicate
10795 : : == insn_data[icode].operand[1].predicate);
10796 : 16 : icode = new_icode;
10797 : 16 : goto non_constant;
10798 : : }
10799 : : break;
10800 : 0 : default:
10801 : 0 : gcc_unreachable ();
10802 : : }
10803 : : }
10804 : : }
10805 : : else
10806 : : {
10807 : 4243 : non_constant:
10808 : 4259 : if (VECTOR_MODE_P (mode))
10809 : 4243 : op = safe_vector_operand (op, mode);
10810 : :
10811 : : /* If we aren't optimizing, only allow one memory operand to be
10812 : : generated. */
10813 : 4259 : if (memory_operand (op, mode))
10814 : 826 : num_memory++;
10815 : :
10816 : 4259 : gcc_assert (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode);
10817 : :
10818 : 4259 : if (optimize
10819 : 1506 : || !insn_data[icode].operand[i+adjust+1].predicate (op, mode)
10820 : 5687 : || num_memory > 1)
10821 : 3338 : op = force_reg (mode, op);
10822 : : }
10823 : :
10824 : 4379 : xops[i] = op;
10825 : : }
10826 : :
10827 : 1787 : switch (nargs)
10828 : : {
10829 : 187 : case 1:
10830 : 187 : pat = GEN_FCN (icode) (target, xops[0]);
10831 : 187 : break;
10832 : :
10833 : 704 : case 2:
10834 : 704 : if (tf_p)
10835 : 128 : pat = GEN_FCN (icode) (target, xops[0], xops[1],
10836 : 128 : GEN_INT ((int)sub_code));
10837 : 576 : else if (! comparison_p)
10838 : 192 : pat = GEN_FCN (icode) (target, xops[0], xops[1]);
10839 : : else
10840 : : {
10841 : 384 : rtx cmp_op = gen_rtx_fmt_ee (sub_code, GET_MODE (target),
10842 : : xops[0], xops[1]);
10843 : :
10844 : 384 : pat = GEN_FCN (icode) (target, cmp_op, xops[0], xops[1]);
10845 : : }
10846 : : break;
10847 : :
10848 : 824 : case 3:
10849 : 824 : pat = GEN_FCN (icode) (target, xops[0], xops[1], xops[2]);
10850 : 824 : break;
10851 : :
10852 : 72 : case 4:
10853 : 72 : pat = GEN_FCN (icode) (target, xops[0], xops[1], xops[2], xops[3]);
10854 : 72 : break;
10855 : :
10856 : : default:
10857 : : gcc_unreachable ();
10858 : : }
10859 : :
10860 : 1787 : if (! pat)
10861 : : return 0;
10862 : :
10863 : 1787 : emit_insn (pat);
10864 : 1787 : return target;
10865 : : }
10866 : :
10867 : : /* Subroutine of ix86_expand_args_builtin to take care of scalar unop
10868 : : insns with vec_merge. */
10869 : :
10870 : : static rtx
10871 : 52 : ix86_expand_unop_vec_merge_builtin (enum insn_code icode, tree exp,
10872 : : rtx target)
10873 : : {
10874 : 52 : rtx pat;
10875 : 52 : tree arg0 = CALL_EXPR_ARG (exp, 0);
10876 : 52 : rtx op1, op0 = expand_normal (arg0);
10877 : 52 : machine_mode tmode = insn_data[icode].operand[0].mode;
10878 : 52 : machine_mode mode0 = insn_data[icode].operand[1].mode;
10879 : :
10880 : 16 : if (optimize || !target
10881 : 16 : || GET_MODE (target) != tmode
10882 : 68 : || !insn_data[icode].operand[0].predicate (target, tmode))
10883 : 36 : target = gen_reg_rtx (tmode);
10884 : :
10885 : 52 : if (VECTOR_MODE_P (mode0))
10886 : 52 : op0 = safe_vector_operand (op0, mode0);
10887 : :
10888 : 36 : if ((optimize && !register_operand (op0, mode0))
10889 : 88 : || !insn_data[icode].operand[1].predicate (op0, mode0))
10890 : 0 : op0 = copy_to_mode_reg (mode0, op0);
10891 : :
10892 : 52 : op1 = op0;
10893 : 52 : if (!insn_data[icode].operand[2].predicate (op1, mode0))
10894 : 16 : op1 = copy_to_mode_reg (mode0, op1);
10895 : :
10896 : 52 : pat = GEN_FCN (icode) (target, op0, op1);
10897 : 52 : if (! pat)
10898 : : return 0;
10899 : 52 : emit_insn (pat);
10900 : 52 : return target;
10901 : : }
10902 : :
10903 : : /* Subroutine of ix86_expand_builtin to take care of comparison insns. */
10904 : :
10905 : : static rtx
10906 : 614 : ix86_expand_sse_compare (const struct builtin_description *d,
10907 : : tree exp, rtx target, bool swap)
10908 : : {
10909 : 614 : rtx pat;
10910 : 614 : tree arg0 = CALL_EXPR_ARG (exp, 0);
10911 : 614 : tree arg1 = CALL_EXPR_ARG (exp, 1);
10912 : 614 : rtx op0 = expand_normal (arg0);
10913 : 614 : rtx op1 = expand_normal (arg1);
10914 : 614 : rtx op2;
10915 : 614 : machine_mode tmode = insn_data[d->icode].operand[0].mode;
10916 : 614 : machine_mode mode0 = insn_data[d->icode].operand[1].mode;
10917 : 614 : machine_mode mode1 = insn_data[d->icode].operand[2].mode;
10918 : 614 : enum rtx_code comparison = d->comparison;
10919 : :
10920 : 614 : if (VECTOR_MODE_P (mode0))
10921 : 614 : op0 = safe_vector_operand (op0, mode0);
10922 : 614 : if (VECTOR_MODE_P (mode1))
10923 : 614 : op1 = safe_vector_operand (op1, mode1);
10924 : :
10925 : : /* Swap operands if we have a comparison that isn't available in
10926 : : hardware. */
10927 : 614 : if (swap)
10928 : 80 : std::swap (op0, op1);
10929 : :
10930 : 202 : if (optimize || !target
10931 : 202 : || GET_MODE (target) != tmode
10932 : 816 : || !insn_data[d->icode].operand[0].predicate (target, tmode))
10933 : 412 : target = gen_reg_rtx (tmode);
10934 : :
10935 : 412 : if ((optimize && !register_operand (op0, mode0))
10936 : 956 : || !insn_data[d->icode].operand[1].predicate (op0, mode0))
10937 : 272 : op0 = copy_to_mode_reg (mode0, op0);
10938 : 412 : if ((optimize && !register_operand (op1, mode1))
10939 : 972 : || !insn_data[d->icode].operand[2].predicate (op1, mode1))
10940 : 54 : op1 = copy_to_mode_reg (mode1, op1);
10941 : :
10942 : 614 : op2 = gen_rtx_fmt_ee (comparison, mode0, op0, op1);
10943 : 614 : pat = GEN_FCN (d->icode) (target, op0, op1, op2);
10944 : 614 : if (! pat)
10945 : : return 0;
10946 : 614 : emit_insn (pat);
10947 : 614 : return target;
10948 : : }
10949 : :
10950 : : /* Subroutine of ix86_sse_comi and ix86_sse_comi_round to take care of
10951 : : * ordered EQ or unordered NE, generate PF jump. */
10952 : :
10953 : : static rtx
10954 : 632 : ix86_ssecom_setcc (const enum rtx_code comparison,
10955 : : bool check_unordered, machine_mode mode,
10956 : : rtx set_dst, rtx target)
10957 : : {
10958 : :
10959 : 632 : rtx_code_label *label = NULL;
10960 : :
10961 : : /* NB: For ordered EQ or unordered NE, check ZF alone isn't sufficient
10962 : : with NAN operands.
10963 : : Under TARGET_AVX10_2, VCOMX/VUCOMX are generated instead of
10964 : : COMI/UCOMI. VCOMX/VUCOMX will not set ZF for NAN operands. */
10965 : 632 : if (check_unordered)
10966 : : {
10967 : 120 : gcc_assert (comparison == EQ || comparison == NE);
10968 : :
10969 : 120 : rtx flag = gen_rtx_REG (CCFPmode, FLAGS_REG);
10970 : 120 : label = gen_label_rtx ();
10971 : 120 : rtx tmp = gen_rtx_fmt_ee (UNORDERED, VOIDmode, flag, const0_rtx);
10972 : 120 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
10973 : : gen_rtx_LABEL_REF (VOIDmode, label),
10974 : : pc_rtx);
10975 : 120 : emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
10976 : : }
10977 : :
10978 : : /* NB: Set CCFPmode and check a different CCmode which is in subset
10979 : : of CCFPmode. */
10980 : 632 : if (GET_MODE (set_dst) != mode)
10981 : : {
10982 : 196 : gcc_assert (mode == CCAmode || mode == CCCmode
10983 : : || mode == CCOmode || mode == CCPmode
10984 : : || mode == CCSmode || mode == CCZmode);
10985 : 196 : set_dst = gen_rtx_REG (mode, FLAGS_REG);
10986 : : }
10987 : :
10988 : 632 : emit_insn (gen_rtx_SET (gen_rtx_STRICT_LOW_PART (VOIDmode, target),
10989 : : gen_rtx_fmt_ee (comparison, QImode,
10990 : : set_dst,
10991 : : const0_rtx)));
10992 : :
10993 : 632 : if (label)
10994 : 120 : emit_label (label);
10995 : :
10996 : 632 : return SUBREG_REG (target);
10997 : : }
10998 : :
10999 : : /* Subroutine of ix86_expand_builtin to take care of comi insns. */
11000 : :
11001 : : static rtx
11002 : 539 : ix86_expand_sse_comi (const struct builtin_description *d, tree exp,
11003 : : rtx target, bool comx_ok)
11004 : : {
11005 : 539 : rtx pat, set_dst;
11006 : 539 : tree arg0 = CALL_EXPR_ARG (exp, 0);
11007 : 539 : tree arg1 = CALL_EXPR_ARG (exp, 1);
11008 : 539 : rtx op0 = expand_normal (arg0);
11009 : 539 : rtx op1 = expand_normal (arg1);
11010 : 539 : enum insn_code icode = d->icode;
11011 : 539 : const struct insn_data_d *insn_p = &insn_data[icode];
11012 : 539 : machine_mode mode0 = insn_p->operand[0].mode;
11013 : 539 : machine_mode mode1 = insn_p->operand[1].mode;
11014 : :
11015 : 539 : if (VECTOR_MODE_P (mode0))
11016 : 539 : op0 = safe_vector_operand (op0, mode0);
11017 : 539 : if (VECTOR_MODE_P (mode1))
11018 : 539 : op1 = safe_vector_operand (op1, mode1);
11019 : :
11020 : 539 : enum rtx_code comparison = d->comparison;
11021 : 539 : rtx const_val = const0_rtx;
11022 : :
11023 : 539 : bool check_unordered = false;
11024 : 539 : machine_mode mode = CCFPmode;
11025 : 539 : switch (comparison)
11026 : : {
11027 : 190 : case LE: /* -> GE */
11028 : 190 : case LT: /* -> GT */
11029 : 190 : std::swap (op0, op1);
11030 : 190 : comparison = swap_condition (comparison);
11031 : : /* FALLTHRU */
11032 : : case GT:
11033 : : case GE:
11034 : : break;
11035 : 72 : case EQ:
11036 : 72 : if (!TARGET_AVX10_2 || !comx_ok)
11037 : 44 : check_unordered = true;
11038 : : mode = CCZmode;
11039 : : break;
11040 : 95 : case NE:
11041 : 95 : if (!TARGET_AVX10_2 || !comx_ok)
11042 : 67 : check_unordered = true;
11043 : 95 : mode = CCZmode;
11044 : 95 : const_val = const1_rtx;
11045 : 95 : break;
11046 : 0 : default:
11047 : 0 : gcc_unreachable ();
11048 : : }
11049 : :
11050 : 539 : target = gen_reg_rtx (SImode);
11051 : 539 : emit_move_insn (target, const_val);
11052 : 539 : target = gen_rtx_SUBREG (QImode, target, 0);
11053 : :
11054 : 418 : if ((optimize && !register_operand (op0, mode0))
11055 : 909 : || !insn_p->operand[0].predicate (op0, mode0))
11056 : 169 : op0 = copy_to_mode_reg (mode0, op0);
11057 : 418 : if ((optimize && !register_operand (op1, mode1))
11058 : 909 : || !insn_p->operand[1].predicate (op1, mode1))
11059 : 48 : op1 = copy_to_mode_reg (mode1, op1);
11060 : :
11061 : 539 : if ((comparison == EQ || comparison == NE)
11062 : 167 : && TARGET_AVX10_2 && comx_ok)
11063 : : {
11064 : 56 : switch (icode)
11065 : : {
11066 : : case CODE_FOR_sse_comi:
11067 : : icode = CODE_FOR_avx10_2_comxsf;
11068 : : break;
11069 : 14 : case CODE_FOR_sse_ucomi:
11070 : 14 : icode = CODE_FOR_avx10_2_ucomxsf;
11071 : 14 : break;
11072 : 14 : case CODE_FOR_sse2_comi:
11073 : 14 : icode = CODE_FOR_avx10_2_comxdf;
11074 : 14 : break;
11075 : 14 : case CODE_FOR_sse2_ucomi:
11076 : 14 : icode = CODE_FOR_avx10_2_ucomxdf;
11077 : 14 : break;
11078 : :
11079 : 0 : default:
11080 : 0 : gcc_unreachable ();
11081 : : }
11082 : : }
11083 : 539 : pat = GEN_FCN (icode) (op0, op1);
11084 : 539 : if (! pat)
11085 : : return 0;
11086 : :
11087 : 539 : set_dst = SET_DEST (pat);
11088 : 539 : emit_insn (pat);
11089 : 539 : return ix86_ssecom_setcc (comparison, check_unordered, mode,
11090 : 539 : set_dst, target);
11091 : : }
11092 : :
11093 : : /* Subroutines of ix86_expand_args_builtin to take care of round insns. */
11094 : :
11095 : : static rtx
11096 : 0 : ix86_expand_sse_round (const struct builtin_description *d, tree exp,
11097 : : rtx target)
11098 : : {
11099 : 0 : rtx pat;
11100 : 0 : tree arg0 = CALL_EXPR_ARG (exp, 0);
11101 : 0 : rtx op1, op0 = expand_normal (arg0);
11102 : 0 : machine_mode tmode = insn_data[d->icode].operand[0].mode;
11103 : 0 : machine_mode mode0 = insn_data[d->icode].operand[1].mode;
11104 : :
11105 : 0 : if (optimize || target == 0
11106 : 0 : || GET_MODE (target) != tmode
11107 : 0 : || !insn_data[d->icode].operand[0].predicate (target, tmode))
11108 : 0 : target = gen_reg_rtx (tmode);
11109 : :
11110 : 0 : if (VECTOR_MODE_P (mode0))
11111 : 0 : op0 = safe_vector_operand (op0, mode0);
11112 : :
11113 : 0 : if ((optimize && !register_operand (op0, mode0))
11114 : 0 : || !insn_data[d->icode].operand[0].predicate (op0, mode0))
11115 : 0 : op0 = copy_to_mode_reg (mode0, op0);
11116 : :
11117 : 0 : op1 = GEN_INT (d->comparison);
11118 : :
11119 : 0 : pat = GEN_FCN (d->icode) (target, op0, op1);
11120 : 0 : if (! pat)
11121 : : return 0;
11122 : 0 : emit_insn (pat);
11123 : 0 : return target;
11124 : : }
11125 : :
11126 : : static rtx
11127 : 12 : ix86_expand_sse_round_vec_pack_sfix (const struct builtin_description *d,
11128 : : tree exp, rtx target)
11129 : : {
11130 : 12 : rtx pat;
11131 : 12 : tree arg0 = CALL_EXPR_ARG (exp, 0);
11132 : 12 : tree arg1 = CALL_EXPR_ARG (exp, 1);
11133 : 12 : rtx op0 = expand_normal (arg0);
11134 : 12 : rtx op1 = expand_normal (arg1);
11135 : 12 : rtx op2;
11136 : 12 : machine_mode tmode = insn_data[d->icode].operand[0].mode;
11137 : 12 : machine_mode mode0 = insn_data[d->icode].operand[1].mode;
11138 : 12 : machine_mode mode1 = insn_data[d->icode].operand[2].mode;
11139 : :
11140 : 0 : if (optimize || target == 0
11141 : 0 : || GET_MODE (target) != tmode
11142 : 12 : || !insn_data[d->icode].operand[0].predicate (target, tmode))
11143 : 12 : target = gen_reg_rtx (tmode);
11144 : :
11145 : 12 : op0 = safe_vector_operand (op0, mode0);
11146 : 12 : op1 = safe_vector_operand (op1, mode1);
11147 : :
11148 : 12 : if ((optimize && !register_operand (op0, mode0))
11149 : 12 : || !insn_data[d->icode].operand[0].predicate (op0, mode0))
11150 : 12 : op0 = copy_to_mode_reg (mode0, op0);
11151 : 12 : if ((optimize && !register_operand (op1, mode1))
11152 : 12 : || !insn_data[d->icode].operand[1].predicate (op1, mode1))
11153 : 12 : op1 = copy_to_mode_reg (mode1, op1);
11154 : :
11155 : 12 : op2 = GEN_INT (d->comparison);
11156 : :
11157 : 12 : pat = GEN_FCN (d->icode) (target, op0, op1, op2);
11158 : 12 : if (! pat)
11159 : : return 0;
11160 : 12 : emit_insn (pat);
11161 : 12 : return target;
11162 : : }
11163 : :
11164 : : /* Subroutine of ix86_expand_builtin to take care of ptest insns. */
11165 : :
11166 : : static rtx
11167 : 235 : ix86_expand_sse_ptest (const struct builtin_description *d, tree exp,
11168 : : rtx target)
11169 : : {
11170 : 235 : rtx pat;
11171 : 235 : tree arg0 = CALL_EXPR_ARG (exp, 0);
11172 : 235 : tree arg1 = CALL_EXPR_ARG (exp, 1);
11173 : 235 : rtx op0 = expand_normal (arg0);
11174 : 235 : rtx op1 = expand_normal (arg1);
11175 : 235 : machine_mode mode0 = insn_data[d->icode].operand[0].mode;
11176 : 235 : machine_mode mode1 = insn_data[d->icode].operand[1].mode;
11177 : 235 : enum rtx_code comparison = d->comparison;
11178 : :
11179 : : /* ptest reg, reg sets the carry flag. */
11180 : 235 : if (comparison == LTU
11181 : 75 : && (d->code == IX86_BUILTIN_PTESTC
11182 : 57 : || d->code == IX86_BUILTIN_PTESTC256)
11183 : 266 : && rtx_equal_p (op0, op1))
11184 : : {
11185 : 2 : if (!target)
11186 : 0 : target = gen_reg_rtx (SImode);
11187 : 2 : emit_move_insn (target, const1_rtx);
11188 : 2 : return target;
11189 : : }
11190 : :
11191 : 233 : if (VECTOR_MODE_P (mode0))
11192 : 233 : op0 = safe_vector_operand (op0, mode0);
11193 : 233 : if (VECTOR_MODE_P (mode1))
11194 : 233 : op1 = safe_vector_operand (op1, mode1);
11195 : :
11196 : 233 : target = gen_reg_rtx (SImode);
11197 : 233 : emit_move_insn (target, const0_rtx);
11198 : 233 : target = gen_rtx_SUBREG (QImode, target, 0);
11199 : :
11200 : 161 : if ((optimize && !register_operand (op0, mode0))
11201 : 366 : || !insn_data[d->icode].operand[0].predicate (op0, mode0))
11202 : 100 : op0 = copy_to_mode_reg (mode0, op0);
11203 : 161 : if ((optimize && !register_operand (op1, mode1))
11204 : 367 : || !insn_data[d->icode].operand[1].predicate (op1, mode1))
11205 : 27 : op1 = copy_to_mode_reg (mode1, op1);
11206 : :
11207 : 233 : pat = GEN_FCN (d->icode) (op0, op1);
11208 : 233 : if (! pat)
11209 : : return 0;
11210 : 233 : emit_insn (pat);
11211 : 233 : emit_insn (gen_rtx_SET (gen_rtx_STRICT_LOW_PART (VOIDmode, target),
11212 : : gen_rtx_fmt_ee (comparison, QImode,
11213 : : SET_DEST (pat),
11214 : : const0_rtx)));
11215 : :
11216 : 233 : return SUBREG_REG (target);
11217 : : }
11218 : :
11219 : : /* Subroutine of ix86_expand_builtin to take care of pcmpestr[im] insns. */
11220 : :
11221 : : static rtx
11222 : 216 : ix86_expand_sse_pcmpestr (const struct builtin_description *d,
11223 : : tree exp, rtx target)
11224 : : {
11225 : 216 : rtx pat;
11226 : 216 : tree arg0 = CALL_EXPR_ARG (exp, 0);
11227 : 216 : tree arg1 = CALL_EXPR_ARG (exp, 1);
11228 : 216 : tree arg2 = CALL_EXPR_ARG (exp, 2);
11229 : 216 : tree arg3 = CALL_EXPR_ARG (exp, 3);
11230 : 216 : tree arg4 = CALL_EXPR_ARG (exp, 4);
11231 : 216 : rtx scratch0, scratch1;
11232 : 216 : rtx op0 = expand_normal (arg0);
11233 : 216 : rtx op1 = expand_normal (arg1);
11234 : 216 : rtx op2 = expand_normal (arg2);
11235 : 216 : rtx op3 = expand_normal (arg3);
11236 : 216 : rtx op4 = expand_normal (arg4);
11237 : 216 : machine_mode tmode0, tmode1, modev2, modei3, modev4, modei5, modeimm;
11238 : :
11239 : 216 : tmode0 = insn_data[d->icode].operand[0].mode;
11240 : 216 : tmode1 = insn_data[d->icode].operand[1].mode;
11241 : 216 : modev2 = insn_data[d->icode].operand[2].mode;
11242 : 216 : modei3 = insn_data[d->icode].operand[3].mode;
11243 : 216 : modev4 = insn_data[d->icode].operand[4].mode;
11244 : 216 : modei5 = insn_data[d->icode].operand[5].mode;
11245 : 216 : modeimm = insn_data[d->icode].operand[6].mode;
11246 : :
11247 : 216 : if (VECTOR_MODE_P (modev2))
11248 : 216 : op0 = safe_vector_operand (op0, modev2);
11249 : 216 : if (VECTOR_MODE_P (modev4))
11250 : 216 : op2 = safe_vector_operand (op2, modev4);
11251 : :
11252 : 216 : if (!insn_data[d->icode].operand[2].predicate (op0, modev2))
11253 : 6 : op0 = copy_to_mode_reg (modev2, op0);
11254 : 216 : if (!insn_data[d->icode].operand[3].predicate (op1, modei3))
11255 : 34 : op1 = copy_to_mode_reg (modei3, op1);
11256 : 160 : if ((optimize && !register_operand (op2, modev4))
11257 : 371 : || !insn_data[d->icode].operand[4].predicate (op2, modev4))
11258 : 5 : op2 = copy_to_mode_reg (modev4, op2);
11259 : 216 : if (!insn_data[d->icode].operand[5].predicate (op3, modei5))
11260 : 34 : op3 = copy_to_mode_reg (modei5, op3);
11261 : :
11262 : 216 : if (!insn_data[d->icode].operand[6].predicate (op4, modeimm))
11263 : : {
11264 : 21 : error ("the fifth argument must be an 8-bit immediate");
11265 : 21 : return const0_rtx;
11266 : : }
11267 : :
11268 : 195 : if (d->code == IX86_BUILTIN_PCMPESTRI128)
11269 : : {
11270 : 5 : if (optimize || !target
11271 : 5 : || GET_MODE (target) != tmode0
11272 : 34 : || !insn_data[d->icode].operand[0].predicate (target, tmode0))
11273 : 24 : target = gen_reg_rtx (tmode0);
11274 : :
11275 : 29 : scratch1 = gen_reg_rtx (tmode1);
11276 : :
11277 : 29 : pat = GEN_FCN (d->icode) (target, scratch1, op0, op1, op2, op3, op4);
11278 : : }
11279 : 166 : else if (d->code == IX86_BUILTIN_PCMPESTRM128)
11280 : : {
11281 : 5 : if (optimize || !target
11282 : 5 : || GET_MODE (target) != tmode1
11283 : 36 : || !insn_data[d->icode].operand[1].predicate (target, tmode1))
11284 : 26 : target = gen_reg_rtx (tmode1);
11285 : :
11286 : 31 : scratch0 = gen_reg_rtx (tmode0);
11287 : :
11288 : 31 : pat = GEN_FCN (d->icode) (scratch0, target, op0, op1, op2, op3, op4);
11289 : : }
11290 : : else
11291 : : {
11292 : 135 : gcc_assert (d->flag);
11293 : :
11294 : 135 : scratch0 = gen_reg_rtx (tmode0);
11295 : 135 : scratch1 = gen_reg_rtx (tmode1);
11296 : :
11297 : 135 : pat = GEN_FCN (d->icode) (scratch0, scratch1, op0, op1, op2, op3, op4);
11298 : : }
11299 : :
11300 : 195 : if (! pat)
11301 : : return 0;
11302 : :
11303 : 195 : emit_insn (pat);
11304 : :
11305 : 195 : if (d->flag)
11306 : : {
11307 : 135 : target = gen_reg_rtx (SImode);
11308 : 135 : emit_move_insn (target, const0_rtx);
11309 : 135 : target = gen_rtx_SUBREG (QImode, target, 0);
11310 : :
11311 : 135 : emit_insn
11312 : 135 : (gen_rtx_SET (gen_rtx_STRICT_LOW_PART (VOIDmode, target),
11313 : : gen_rtx_fmt_ee (EQ, QImode,
11314 : : gen_rtx_REG ((machine_mode) d->flag,
11315 : : FLAGS_REG),
11316 : : const0_rtx)));
11317 : 135 : return SUBREG_REG (target);
11318 : : }
11319 : : else
11320 : : return target;
11321 : : }
11322 : :
11323 : :
11324 : : /* Subroutine of ix86_expand_builtin to take care of pcmpistr[im] insns. */
11325 : :
11326 : : static rtx
11327 : 275 : ix86_expand_sse_pcmpistr (const struct builtin_description *d,
11328 : : tree exp, rtx target)
11329 : : {
11330 : 275 : rtx pat;
11331 : 275 : tree arg0 = CALL_EXPR_ARG (exp, 0);
11332 : 275 : tree arg1 = CALL_EXPR_ARG (exp, 1);
11333 : 275 : tree arg2 = CALL_EXPR_ARG (exp, 2);
11334 : 275 : rtx scratch0, scratch1;
11335 : 275 : rtx op0 = expand_normal (arg0);
11336 : 275 : rtx op1 = expand_normal (arg1);
11337 : 275 : rtx op2 = expand_normal (arg2);
11338 : 275 : machine_mode tmode0, tmode1, modev2, modev3, modeimm;
11339 : :
11340 : 275 : tmode0 = insn_data[d->icode].operand[0].mode;
11341 : 275 : tmode1 = insn_data[d->icode].operand[1].mode;
11342 : 275 : modev2 = insn_data[d->icode].operand[2].mode;
11343 : 275 : modev3 = insn_data[d->icode].operand[3].mode;
11344 : 275 : modeimm = insn_data[d->icode].operand[4].mode;
11345 : :
11346 : 275 : if (VECTOR_MODE_P (modev2))
11347 : 275 : op0 = safe_vector_operand (op0, modev2);
11348 : 275 : if (VECTOR_MODE_P (modev3))
11349 : 275 : op1 = safe_vector_operand (op1, modev3);
11350 : :
11351 : 275 : if (!insn_data[d->icode].operand[2].predicate (op0, modev2))
11352 : 4 : op0 = copy_to_mode_reg (modev2, op0);
11353 : 210 : if ((optimize && !register_operand (op1, modev3))
11354 : 481 : || !insn_data[d->icode].operand[3].predicate (op1, modev3))
11355 : 4 : op1 = copy_to_mode_reg (modev3, op1);
11356 : :
11357 : 275 : if (!insn_data[d->icode].operand[4].predicate (op2, modeimm))
11358 : : {
11359 : 21 : error ("the third argument must be an 8-bit immediate");
11360 : 21 : return const0_rtx;
11361 : : }
11362 : :
11363 : 254 : if (d->code == IX86_BUILTIN_PCMPISTRI128)
11364 : : {
11365 : 5 : if (optimize || !target
11366 : 5 : || GET_MODE (target) != tmode0
11367 : 38 : || !insn_data[d->icode].operand[0].predicate (target, tmode0))
11368 : 28 : target = gen_reg_rtx (tmode0);
11369 : :
11370 : 33 : scratch1 = gen_reg_rtx (tmode1);
11371 : :
11372 : 33 : pat = GEN_FCN (d->icode) (target, scratch1, op0, op1, op2);
11373 : : }
11374 : 221 : else if (d->code == IX86_BUILTIN_PCMPISTRM128)
11375 : : {
11376 : 8 : if (optimize || !target
11377 : 8 : || GET_MODE (target) != tmode1
11378 : 58 : || !insn_data[d->icode].operand[1].predicate (target, tmode1))
11379 : 42 : target = gen_reg_rtx (tmode1);
11380 : :
11381 : 50 : scratch0 = gen_reg_rtx (tmode0);
11382 : :
11383 : 50 : pat = GEN_FCN (d->icode) (scratch0, target, op0, op1, op2);
11384 : : }
11385 : : else
11386 : : {
11387 : 171 : gcc_assert (d->flag);
11388 : :
11389 : 171 : scratch0 = gen_reg_rtx (tmode0);
11390 : 171 : scratch1 = gen_reg_rtx (tmode1);
11391 : :
11392 : 171 : pat = GEN_FCN (d->icode) (scratch0, scratch1, op0, op1, op2);
11393 : : }
11394 : :
11395 : 254 : if (! pat)
11396 : : return 0;
11397 : :
11398 : 254 : emit_insn (pat);
11399 : :
11400 : 254 : if (d->flag)
11401 : : {
11402 : 171 : target = gen_reg_rtx (SImode);
11403 : 171 : emit_move_insn (target, const0_rtx);
11404 : 171 : target = gen_rtx_SUBREG (QImode, target, 0);
11405 : :
11406 : 171 : emit_insn
11407 : 171 : (gen_rtx_SET (gen_rtx_STRICT_LOW_PART (VOIDmode, target),
11408 : : gen_rtx_fmt_ee (EQ, QImode,
11409 : : gen_rtx_REG ((machine_mode) d->flag,
11410 : : FLAGS_REG),
11411 : : const0_rtx)));
11412 : 171 : return SUBREG_REG (target);
11413 : : }
11414 : : else
11415 : : return target;
11416 : : }
11417 : :
11418 : : /* Fixup modeless constants to fit required mode. */
11419 : :
11420 : : static rtx
11421 : 254190 : fixup_modeless_constant (rtx x, machine_mode mode)
11422 : : {
11423 : 254190 : if (GET_MODE (x) == VOIDmode)
11424 : 39799 : x = convert_to_mode (mode, x, 1);
11425 : 254190 : return x;
11426 : : }
11427 : :
11428 : : /* Expand the outgoing argument ARG to extract unsigned char and short
11429 : : integer constants suitable for the predicates and the instruction
11430 : : templates which expect the unsigned expanded value. */
11431 : :
11432 : : static rtx
11433 : 275242 : ix86_expand_unsigned_small_int_cst_argument (tree arg)
11434 : : {
11435 : : /* When passing 0xff as an unsigned char function argument with the
11436 : : C frontend promotion, expand_normal gets
11437 : :
11438 : : <integer_cst 0x7fffe6aa23a8 type <integer_type 0x7fffe98225e8 int> constant 255>
11439 : :
11440 : : and returns the rtx value using the sign-extended representation:
11441 : :
11442 : : (const_int 255 [0xff])
11443 : :
11444 : : Without the C frontend promotion, expand_normal gets
11445 : :
11446 : : <integer_cst 0x7fffe9824018 type <integer_type 0x7fffe9822348 unsigned char > constant 255>
11447 : :
11448 : : and returns
11449 : :
11450 : : (const_int -1 [0xffffffffffffffff])
11451 : :
11452 : : which doesn't work with the predicates nor the instruction templates
11453 : : which expect the unsigned expanded value. Extract the unsigned char
11454 : : and short integer constants to return
11455 : :
11456 : : (const_int 255 [0xff])
11457 : :
11458 : : so that the expanded value is always unsigned, without the C frontend
11459 : : promotion. */
11460 : :
11461 : 275242 : if (TREE_CODE (arg) == INTEGER_CST)
11462 : : {
11463 : 58498 : tree type = TREE_TYPE (arg);
11464 : 58498 : if (INTEGRAL_TYPE_P (type)
11465 : 58498 : && TYPE_UNSIGNED (type)
11466 : 79142 : && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
11467 : : {
11468 : 17357 : HOST_WIDE_INT cst = TREE_INT_CST_LOW (arg);
11469 : 17357 : return GEN_INT (cst);
11470 : : }
11471 : : }
11472 : :
11473 : 257885 : return expand_normal (arg);
11474 : : }
11475 : :
11476 : : /* Subroutine of ix86_expand_builtin to take care of insns with
11477 : : variable number of operands. */
11478 : :
11479 : : static rtx
11480 : 68083 : ix86_expand_args_builtin (const struct builtin_description *d,
11481 : : tree exp, rtx target)
11482 : : {
11483 : 68083 : rtx pat, real_target;
11484 : 68083 : unsigned int i, nargs;
11485 : 68083 : unsigned int nargs_constant = 0;
11486 : 68083 : unsigned int mask_pos = 0;
11487 : 68083 : int num_memory = 0;
11488 : 68083 : rtx xops[6];
11489 : 68083 : bool second_arg_count = false;
11490 : 68083 : enum insn_code icode = d->icode;
11491 : 68083 : const struct insn_data_d *insn_p = &insn_data[icode];
11492 : 68083 : machine_mode tmode = insn_p->operand[0].mode;
11493 : 68083 : machine_mode rmode = VOIDmode;
11494 : 68083 : bool swap = false;
11495 : 68083 : enum rtx_code comparison = d->comparison;
11496 : :
11497 : 68083 : switch ((enum ix86_builtin_func_type) d->flag)
11498 : : {
11499 : 0 : case V2DF_FTYPE_V2DF_ROUND:
11500 : 0 : case V4DF_FTYPE_V4DF_ROUND:
11501 : 0 : case V8DF_FTYPE_V8DF_ROUND:
11502 : 0 : case V4SF_FTYPE_V4SF_ROUND:
11503 : 0 : case V8SF_FTYPE_V8SF_ROUND:
11504 : 0 : case V16SF_FTYPE_V16SF_ROUND:
11505 : 0 : case V8HF_FTYPE_V8HF_ROUND:
11506 : 0 : case V16HF_FTYPE_V16HF_ROUND:
11507 : 0 : case V32HF_FTYPE_V32HF_ROUND:
11508 : 0 : case V4SI_FTYPE_V4SF_ROUND:
11509 : 0 : case V8SI_FTYPE_V8SF_ROUND:
11510 : 0 : case V16SI_FTYPE_V16SF_ROUND:
11511 : 0 : return ix86_expand_sse_round (d, exp, target);
11512 : 12 : case V4SI_FTYPE_V2DF_V2DF_ROUND:
11513 : 12 : case V8SI_FTYPE_V4DF_V4DF_ROUND:
11514 : 12 : case V16SI_FTYPE_V8DF_V8DF_ROUND:
11515 : 12 : return ix86_expand_sse_round_vec_pack_sfix (d, exp, target);
11516 : 235 : case INT_FTYPE_V8SF_V8SF_PTEST:
11517 : 235 : case INT_FTYPE_V4DI_V4DI_PTEST:
11518 : 235 : case INT_FTYPE_V4DF_V4DF_PTEST:
11519 : 235 : case INT_FTYPE_V4SF_V4SF_PTEST:
11520 : 235 : case INT_FTYPE_V2DI_V2DI_PTEST:
11521 : 235 : case INT_FTYPE_V2DF_V2DF_PTEST:
11522 : 235 : return ix86_expand_sse_ptest (d, exp, target);
11523 : : case FLOAT128_FTYPE_FLOAT128:
11524 : : case FLOAT_FTYPE_FLOAT:
11525 : : case FLOAT_FTYPE_BFLOAT16:
11526 : : case INT_FTYPE_INT:
11527 : : case UINT_FTYPE_UINT:
11528 : : case UINT16_FTYPE_UINT16:
11529 : : case UINT64_FTYPE_INT:
11530 : : case UINT64_FTYPE_UINT64:
11531 : : case INT64_FTYPE_INT64:
11532 : : case INT64_FTYPE_V4SF:
11533 : : case INT64_FTYPE_V2DF:
11534 : : case INT_FTYPE_V16QI:
11535 : : case INT_FTYPE_V8QI:
11536 : : case INT_FTYPE_V8SF:
11537 : : case INT_FTYPE_V4DF:
11538 : : case INT_FTYPE_V4SF:
11539 : : case INT_FTYPE_V2DF:
11540 : : case INT_FTYPE_V32QI:
11541 : : case V16QI_FTYPE_V16QI:
11542 : : case V8SI_FTYPE_V8SF:
11543 : : case V8SI_FTYPE_V4SI:
11544 : : case V8HI_FTYPE_V8HI:
11545 : : case V8HI_FTYPE_V16QI:
11546 : : case V8QI_FTYPE_V8QI:
11547 : : case V8SF_FTYPE_V8SF:
11548 : : case V8SF_FTYPE_V8SI:
11549 : : case V8SF_FTYPE_V4SF:
11550 : : case V8SF_FTYPE_V8HI:
11551 : : case V4SI_FTYPE_V4SI:
11552 : : case V4SI_FTYPE_V16QI:
11553 : : case V4SI_FTYPE_V4SF:
11554 : : case V4SI_FTYPE_V8SI:
11555 : : case V4SI_FTYPE_V8HI:
11556 : : case V4SI_FTYPE_V4DF:
11557 : : case V4SI_FTYPE_V2DF:
11558 : : case V4HI_FTYPE_V4HI:
11559 : : case V4DF_FTYPE_V4DF:
11560 : : case V4DF_FTYPE_V4SI:
11561 : : case V4DF_FTYPE_V4SF:
11562 : : case V4DF_FTYPE_V2DF:
11563 : : case V4SF_FTYPE_V4SF:
11564 : : case V4SF_FTYPE_V4SI:
11565 : : case V4SF_FTYPE_V8SF:
11566 : : case V4SF_FTYPE_V4DF:
11567 : : case V4SF_FTYPE_V8HI:
11568 : : case V4SF_FTYPE_V2DF:
11569 : : case V2DI_FTYPE_V2DI:
11570 : : case V2DI_FTYPE_V16QI:
11571 : : case V2DI_FTYPE_V8HI:
11572 : : case V2DI_FTYPE_V4SI:
11573 : : case V2DF_FTYPE_V2DF:
11574 : : case V2DF_FTYPE_V4SI:
11575 : : case V2DF_FTYPE_V4DF:
11576 : : case V2DF_FTYPE_V4SF:
11577 : : case V2DF_FTYPE_V2SI:
11578 : : case V2SI_FTYPE_V2SI:
11579 : : case V2SI_FTYPE_V4SF:
11580 : : case V2SI_FTYPE_V2SF:
11581 : : case V2SI_FTYPE_V2DF:
11582 : : case V2SF_FTYPE_V2SF:
11583 : : case V2SF_FTYPE_V2SI:
11584 : : case V32QI_FTYPE_V32QI:
11585 : : case V32QI_FTYPE_V16QI:
11586 : : case V16HI_FTYPE_V16HI:
11587 : : case V16HI_FTYPE_V8HI:
11588 : : case V8SI_FTYPE_V8SI:
11589 : : case V16HI_FTYPE_V16QI:
11590 : : case V8SI_FTYPE_V16QI:
11591 : : case V4DI_FTYPE_V16QI:
11592 : : case V8SI_FTYPE_V8HI:
11593 : : case V4DI_FTYPE_V8HI:
11594 : : case V4DI_FTYPE_V4SI:
11595 : : case V4DI_FTYPE_V2DI:
11596 : : case UQI_FTYPE_UQI:
11597 : : case UHI_FTYPE_UHI:
11598 : : case USI_FTYPE_USI:
11599 : : case USI_FTYPE_UQI:
11600 : : case USI_FTYPE_UHI:
11601 : : case UDI_FTYPE_UDI:
11602 : : case UHI_FTYPE_V16QI:
11603 : : case USI_FTYPE_V32QI:
11604 : : case UDI_FTYPE_V64QI:
11605 : : case V16QI_FTYPE_UHI:
11606 : : case V32QI_FTYPE_USI:
11607 : : case V64QI_FTYPE_UDI:
11608 : : case V8HI_FTYPE_UQI:
11609 : : case V16HI_FTYPE_UHI:
11610 : : case V32HI_FTYPE_USI:
11611 : : case V4SI_FTYPE_UQI:
11612 : : case V8SI_FTYPE_UQI:
11613 : : case V4SI_FTYPE_UHI:
11614 : : case V8SI_FTYPE_UHI:
11615 : : case UQI_FTYPE_V8HI:
11616 : : case UHI_FTYPE_V16HI:
11617 : : case USI_FTYPE_V32HI:
11618 : : case UQI_FTYPE_V4SI:
11619 : : case UQI_FTYPE_V8SI:
11620 : : case UHI_FTYPE_V16SI:
11621 : : case UQI_FTYPE_V2DI:
11622 : : case UQI_FTYPE_V4DI:
11623 : : case UQI_FTYPE_V8DI:
11624 : : case V16SI_FTYPE_UHI:
11625 : : case V2DI_FTYPE_UQI:
11626 : : case V4DI_FTYPE_UQI:
11627 : : case V16SI_FTYPE_INT:
11628 : : case V16SF_FTYPE_V8SF:
11629 : : case V16SI_FTYPE_V8SI:
11630 : : case V16SF_FTYPE_V4SF:
11631 : : case V16SI_FTYPE_V4SI:
11632 : : case V16SI_FTYPE_V16SF:
11633 : : case V16SI_FTYPE_V16SI:
11634 : : case V64QI_FTYPE_V64QI:
11635 : : case V32HI_FTYPE_V32HI:
11636 : : case V16SF_FTYPE_V16SF:
11637 : : case V8DI_FTYPE_UQI:
11638 : : case V8DI_FTYPE_V8DI:
11639 : : case V8DF_FTYPE_V4DF:
11640 : : case V8DF_FTYPE_V2DF:
11641 : : case V8DF_FTYPE_V8DF:
11642 : : case V4DI_FTYPE_V4DI:
11643 : : case V16BF_FTYPE_V16SF:
11644 : : case V8BF_FTYPE_V8SF:
11645 : : case V8BF_FTYPE_V4SF:
11646 : : nargs = 1;
11647 : : break;
11648 : 52 : case V4SF_FTYPE_V4SF_VEC_MERGE:
11649 : 52 : case V2DF_FTYPE_V2DF_VEC_MERGE:
11650 : 52 : return ix86_expand_unop_vec_merge_builtin (icode, exp, target);
11651 : 9473 : case FLOAT128_FTYPE_FLOAT128_FLOAT128:
11652 : 9473 : case V16QI_FTYPE_V16QI_V16QI:
11653 : 9473 : case V16QI_FTYPE_V8HI_V8HI:
11654 : 9473 : case V16HF_FTYPE_V16HF_V16HF:
11655 : 9473 : case V16SF_FTYPE_V16SF_V16SF:
11656 : 9473 : case V16SI_FTYPE_V16SI_V16SI:
11657 : 9473 : case V8QI_FTYPE_V8QI_V8QI:
11658 : 9473 : case V8QI_FTYPE_V4HI_V4HI:
11659 : 9473 : case V8HI_FTYPE_V8HI_V8HI:
11660 : 9473 : case V8HI_FTYPE_V16QI_V16QI:
11661 : 9473 : case V8HI_FTYPE_V4SI_V4SI:
11662 : 9473 : case V8HF_FTYPE_V8HF_V8HF:
11663 : 9473 : case V8SF_FTYPE_V8SF_V8SF:
11664 : 9473 : case V8SF_FTYPE_V8SF_V8SI:
11665 : 9473 : case V8DF_FTYPE_V8DF_V8DF:
11666 : 9473 : case V4SI_FTYPE_V4SI_V4SI:
11667 : 9473 : case V4SI_FTYPE_V8HI_V8HI:
11668 : 9473 : case V4SI_FTYPE_V2DF_V2DF:
11669 : 9473 : case V4HI_FTYPE_V4HI_V4HI:
11670 : 9473 : case V4HI_FTYPE_V8QI_V8QI:
11671 : 9473 : case V4HI_FTYPE_V2SI_V2SI:
11672 : 9473 : case V4DF_FTYPE_V4DF_V4DF:
11673 : 9473 : case V4DF_FTYPE_V4DF_V4DI:
11674 : 9473 : case V4SF_FTYPE_V4SF_V4SF:
11675 : 9473 : case V4SF_FTYPE_V4SF_V4SI:
11676 : 9473 : case V4SF_FTYPE_V4SF_V2SI:
11677 : 9473 : case V4SF_FTYPE_V4SF_V2DF:
11678 : 9473 : case V4SF_FTYPE_V4SF_UINT:
11679 : 9473 : case V4SF_FTYPE_V4SF_DI:
11680 : 9473 : case V4SF_FTYPE_V4SF_SI:
11681 : 9473 : case V4DI_FTYPE_V4DI_V2DI:
11682 : 9473 : case V2DI_FTYPE_V2DI_V2DI:
11683 : 9473 : case V2DI_FTYPE_V16QI_V16QI:
11684 : 9473 : case V2DI_FTYPE_V4SI_V4SI:
11685 : 9473 : case V2DI_FTYPE_V2DI_V16QI:
11686 : 9473 : case V2SI_FTYPE_V2SI_V2SI:
11687 : 9473 : case V2SI_FTYPE_V4HI_V4HI:
11688 : 9473 : case V2SI_FTYPE_V2SF_V2SF:
11689 : 9473 : case V2DF_FTYPE_V2DF_V2DF:
11690 : 9473 : case V2DF_FTYPE_V2DF_V4SF:
11691 : 9473 : case V2DF_FTYPE_V2DF_V2DI:
11692 : 9473 : case V2DF_FTYPE_V2DF_DI:
11693 : 9473 : case V2DF_FTYPE_V2DF_SI:
11694 : 9473 : case V2DF_FTYPE_V2DF_UINT:
11695 : 9473 : case V2SF_FTYPE_V2SF_V2SF:
11696 : 9473 : case V1DI_FTYPE_V1DI_V1DI:
11697 : 9473 : case V1DI_FTYPE_V8QI_V8QI:
11698 : 9473 : case V1DI_FTYPE_V2SI_V2SI:
11699 : 9473 : case V32QI_FTYPE_V16HI_V16HI:
11700 : 9473 : case V16HI_FTYPE_V8SI_V8SI:
11701 : 9473 : case V64QI_FTYPE_V64QI_V64QI:
11702 : 9473 : case V32QI_FTYPE_V32QI_V32QI:
11703 : 9473 : case V32BF_FTYPE_V32BF_V32BF:
11704 : 9473 : case V16BF_FTYPE_V16BF_V16BF:
11705 : 9473 : case V8BF_FTYPE_V8BF_V8BF:
11706 : 9473 : case V16HI_FTYPE_V32QI_V32QI:
11707 : 9473 : case V16HI_FTYPE_V16HI_V16HI:
11708 : 9473 : case V8SI_FTYPE_V4DF_V4DF:
11709 : 9473 : case V8SI_FTYPE_V8SI_V8SI:
11710 : 9473 : case V8SI_FTYPE_V16HI_V16HI:
11711 : 9473 : case V4DI_FTYPE_V4DI_V4DI:
11712 : 9473 : case V4DI_FTYPE_V8SI_V8SI:
11713 : 9473 : case V4DI_FTYPE_V32QI_V32QI:
11714 : 9473 : case V8DI_FTYPE_V64QI_V64QI:
11715 : 9473 : if (comparison == UNKNOWN)
11716 : 8939 : return ix86_expand_binop_builtin (icode, exp, target);
11717 : : nargs = 2;
11718 : : break;
11719 : 80 : case V4SF_FTYPE_V4SF_V4SF_SWAP:
11720 : 80 : case V2DF_FTYPE_V2DF_V2DF_SWAP:
11721 : 80 : gcc_assert (comparison != UNKNOWN);
11722 : : nargs = 2;
11723 : : swap = true;
11724 : : break;
11725 : 1481 : case V16HI_FTYPE_V16HI_V8HI_COUNT:
11726 : 1481 : case V16HI_FTYPE_V16HI_SI_COUNT:
11727 : 1481 : case V8SI_FTYPE_V8SI_V4SI_COUNT:
11728 : 1481 : case V8SI_FTYPE_V8SI_SI_COUNT:
11729 : 1481 : case V4DI_FTYPE_V4DI_V2DI_COUNT:
11730 : 1481 : case V4DI_FTYPE_V4DI_INT_COUNT:
11731 : 1481 : case V8HI_FTYPE_V8HI_V8HI_COUNT:
11732 : 1481 : case V8HI_FTYPE_V8HI_SI_COUNT:
11733 : 1481 : case V4SI_FTYPE_V4SI_V4SI_COUNT:
11734 : 1481 : case V4SI_FTYPE_V4SI_SI_COUNT:
11735 : 1481 : case V4HI_FTYPE_V4HI_V4HI_COUNT:
11736 : 1481 : case V4HI_FTYPE_V4HI_SI_COUNT:
11737 : 1481 : case V2DI_FTYPE_V2DI_V2DI_COUNT:
11738 : 1481 : case V2DI_FTYPE_V2DI_SI_COUNT:
11739 : 1481 : case V2SI_FTYPE_V2SI_V2SI_COUNT:
11740 : 1481 : case V2SI_FTYPE_V2SI_SI_COUNT:
11741 : 1481 : case V1DI_FTYPE_V1DI_V1DI_COUNT:
11742 : 1481 : case V1DI_FTYPE_V1DI_SI_COUNT:
11743 : 1481 : nargs = 2;
11744 : 1481 : second_arg_count = true;
11745 : 1481 : break;
11746 : 1406 : case V16HI_FTYPE_V16HI_INT_V16HI_UHI_COUNT:
11747 : 1406 : case V16HI_FTYPE_V16HI_V8HI_V16HI_UHI_COUNT:
11748 : 1406 : case V16SI_FTYPE_V16SI_INT_V16SI_UHI_COUNT:
11749 : 1406 : case V16SI_FTYPE_V16SI_V4SI_V16SI_UHI_COUNT:
11750 : 1406 : case V2DI_FTYPE_V2DI_INT_V2DI_UQI_COUNT:
11751 : 1406 : case V2DI_FTYPE_V2DI_V2DI_V2DI_UQI_COUNT:
11752 : 1406 : case V32HI_FTYPE_V32HI_INT_V32HI_USI_COUNT:
11753 : 1406 : case V32HI_FTYPE_V32HI_V8HI_V32HI_USI_COUNT:
11754 : 1406 : case V4DI_FTYPE_V4DI_INT_V4DI_UQI_COUNT:
11755 : 1406 : case V4DI_FTYPE_V4DI_V2DI_V4DI_UQI_COUNT:
11756 : 1406 : case V4SI_FTYPE_V4SI_INT_V4SI_UQI_COUNT:
11757 : 1406 : case V4SI_FTYPE_V4SI_V4SI_V4SI_UQI_COUNT:
11758 : 1406 : case V8DI_FTYPE_V8DI_INT_V8DI_UQI_COUNT:
11759 : 1406 : case V8DI_FTYPE_V8DI_V2DI_V8DI_UQI_COUNT:
11760 : 1406 : case V8HI_FTYPE_V8HI_INT_V8HI_UQI_COUNT:
11761 : 1406 : case V8HI_FTYPE_V8HI_V8HI_V8HI_UQI_COUNT:
11762 : 1406 : case V8SI_FTYPE_V8SI_INT_V8SI_UQI_COUNT:
11763 : 1406 : case V8SI_FTYPE_V8SI_V4SI_V8SI_UQI_COUNT:
11764 : 1406 : nargs = 4;
11765 : 1406 : second_arg_count = true;
11766 : 1406 : break;
11767 : 957 : case UINT64_FTYPE_UINT64_UINT64:
11768 : 957 : case UINT_FTYPE_UINT_UINT:
11769 : 957 : case UINT_FTYPE_UINT_USHORT:
11770 : 957 : case UINT_FTYPE_UINT_UCHAR:
11771 : 957 : case UINT16_FTYPE_UINT16_INT:
11772 : 957 : case UINT8_FTYPE_UINT8_INT:
11773 : 957 : case UQI_FTYPE_UQI_UQI:
11774 : 957 : case UHI_FTYPE_UHI_UHI:
11775 : 957 : case USI_FTYPE_USI_USI:
11776 : 957 : case UDI_FTYPE_UDI_UDI:
11777 : 957 : case V16SI_FTYPE_V8DF_V8DF:
11778 : 957 : case V32BF_FTYPE_V16SF_V16SF:
11779 : 957 : case V16BF_FTYPE_V8SF_V8SF:
11780 : 957 : case V8BF_FTYPE_V4SF_V4SF:
11781 : 957 : case V16BF_FTYPE_V16SF_UHI:
11782 : 957 : case V8BF_FTYPE_V8SF_UQI:
11783 : 957 : case V8BF_FTYPE_V4SF_UQI:
11784 : 957 : case V16QI_FTYPE_V16QI_V8HF:
11785 : 957 : nargs = 2;
11786 : 957 : break;
11787 : 797 : case V2DI_FTYPE_V2DI_INT_CONVERT:
11788 : 797 : nargs = 2;
11789 : 797 : rmode = V1TImode;
11790 : 797 : nargs_constant = 1;
11791 : 797 : break;
11792 : 42 : case V4DI_FTYPE_V4DI_INT_CONVERT:
11793 : 42 : nargs = 2;
11794 : 42 : rmode = V2TImode;
11795 : 42 : nargs_constant = 1;
11796 : 42 : break;
11797 : 16 : case V8DI_FTYPE_V8DI_INT_CONVERT:
11798 : 16 : nargs = 2;
11799 : 16 : rmode = V4TImode;
11800 : 16 : nargs_constant = 1;
11801 : 16 : break;
11802 : 2376 : case V8HI_FTYPE_V8HI_INT:
11803 : 2376 : case V8HI_FTYPE_V8SF_INT:
11804 : 2376 : case V16HI_FTYPE_V16SF_INT:
11805 : 2376 : case V8HI_FTYPE_V4SF_INT:
11806 : 2376 : case V8SF_FTYPE_V8SF_INT:
11807 : 2376 : case V4SF_FTYPE_V16SF_INT:
11808 : 2376 : case V16SF_FTYPE_V16SF_INT:
11809 : 2376 : case V4SI_FTYPE_V4SI_INT:
11810 : 2376 : case V4SI_FTYPE_V8SI_INT:
11811 : 2376 : case V4HI_FTYPE_V4HI_INT:
11812 : 2376 : case V4DF_FTYPE_V4DF_INT:
11813 : 2376 : case V4DF_FTYPE_V8DF_INT:
11814 : 2376 : case V4SF_FTYPE_V4SF_INT:
11815 : 2376 : case V4SF_FTYPE_V8SF_INT:
11816 : 2376 : case V2DI_FTYPE_V2DI_INT:
11817 : 2376 : case V2DF_FTYPE_V2DF_INT:
11818 : 2376 : case V2DF_FTYPE_V4DF_INT:
11819 : 2376 : case V16HI_FTYPE_V16HI_INT:
11820 : 2376 : case V8SI_FTYPE_V8SI_INT:
11821 : 2376 : case V16SI_FTYPE_V16SI_INT:
11822 : 2376 : case V4SI_FTYPE_V16SI_INT:
11823 : 2376 : case V4DI_FTYPE_V4DI_INT:
11824 : 2376 : case V2DI_FTYPE_V4DI_INT:
11825 : 2376 : case V4DI_FTYPE_V8DI_INT:
11826 : 2376 : case UQI_FTYPE_UQI_UQI_CONST:
11827 : 2376 : case UHI_FTYPE_UHI_UQI:
11828 : 2376 : case USI_FTYPE_USI_UQI:
11829 : 2376 : case UDI_FTYPE_UDI_UQI:
11830 : 2376 : nargs = 2;
11831 : 2376 : nargs_constant = 1;
11832 : 2376 : break;
11833 : 18172 : case V16QI_FTYPE_V16QI_V16QI_V16QI:
11834 : 18172 : case V8SF_FTYPE_V8SF_V8SF_V8SF:
11835 : 18172 : case V4DF_FTYPE_V4DF_V4DF_V4DF:
11836 : 18172 : case V4SF_FTYPE_V4SF_V4SF_V4SF:
11837 : 18172 : case V2DF_FTYPE_V2DF_V2DF_V2DF:
11838 : 18172 : case V32QI_FTYPE_V32QI_V32QI_V32QI:
11839 : 18172 : case UHI_FTYPE_V16SI_V16SI_UHI:
11840 : 18172 : case UQI_FTYPE_V8DI_V8DI_UQI:
11841 : 18172 : case V16HI_FTYPE_V16SI_V16HI_UHI:
11842 : 18172 : case V16QI_FTYPE_V16SI_V16QI_UHI:
11843 : 18172 : case V16QI_FTYPE_V8DI_V16QI_UQI:
11844 : 18172 : case V32HF_FTYPE_V32HF_V32HF_USI:
11845 : 18172 : case V16SF_FTYPE_V16SF_V16SF_UHI:
11846 : 18172 : case V16SF_FTYPE_V4SF_V16SF_UHI:
11847 : 18172 : case V16SI_FTYPE_SI_V16SI_UHI:
11848 : 18172 : case V16SI_FTYPE_V16HI_V16SI_UHI:
11849 : 18172 : case V16SI_FTYPE_V16QI_V16SI_UHI:
11850 : 18172 : case V8SF_FTYPE_V4SF_V8SF_UQI:
11851 : 18172 : case V4DF_FTYPE_V2DF_V4DF_UQI:
11852 : 18172 : case V8SI_FTYPE_V4SI_V8SI_UQI:
11853 : 18172 : case V8SI_FTYPE_SI_V8SI_UQI:
11854 : 18172 : case V4SI_FTYPE_V4SI_V4SI_UQI:
11855 : 18172 : case V4SI_FTYPE_SI_V4SI_UQI:
11856 : 18172 : case V4DI_FTYPE_V2DI_V4DI_UQI:
11857 : 18172 : case V4DI_FTYPE_DI_V4DI_UQI:
11858 : 18172 : case V2DI_FTYPE_V2DI_V2DI_UQI:
11859 : 18172 : case V2DI_FTYPE_DI_V2DI_UQI:
11860 : 18172 : case V64QI_FTYPE_V64QI_V64QI_UDI:
11861 : 18172 : case V64QI_FTYPE_V16QI_V64QI_UDI:
11862 : 18172 : case V64QI_FTYPE_QI_V64QI_UDI:
11863 : 18172 : case V32QI_FTYPE_V32QI_V32QI_USI:
11864 : 18172 : case V32QI_FTYPE_V16QI_V32QI_USI:
11865 : 18172 : case V32QI_FTYPE_QI_V32QI_USI:
11866 : 18172 : case V16QI_FTYPE_V16QI_V16QI_UHI:
11867 : 18172 : case V16QI_FTYPE_QI_V16QI_UHI:
11868 : 18172 : case V32HI_FTYPE_V8HI_V32HI_USI:
11869 : 18172 : case V32HI_FTYPE_V32BF_V32HI_USI:
11870 : 18172 : case V32HI_FTYPE_HI_V32HI_USI:
11871 : 18172 : case V16HI_FTYPE_V8HI_V16HI_UHI:
11872 : 18172 : case V16HI_FTYPE_V16BF_V16HI_UHI:
11873 : 18172 : case V16HI_FTYPE_HI_V16HI_UHI:
11874 : 18172 : case V8HI_FTYPE_V8HI_V8HI_UQI:
11875 : 18172 : case V8HI_FTYPE_V8BF_V8HI_UQI:
11876 : 18172 : case V8BF_FTYPE_V8BF_V8BF_UQI:
11877 : 18172 : case V8HI_FTYPE_HI_V8HI_UQI:
11878 : 18172 : case V16HF_FTYPE_V16HF_V16HF_UHI:
11879 : 18172 : case V8SF_FTYPE_V8HI_V8SF_UQI:
11880 : 18172 : case V4SF_FTYPE_V8HI_V4SF_UQI:
11881 : 18172 : case V8SI_FTYPE_V8HF_V8SI_UQI:
11882 : 18172 : case V8SF_FTYPE_V8HF_V8SF_UQI:
11883 : 18172 : case V8SI_FTYPE_V8SF_V8SI_UQI:
11884 : 18172 : case V4SI_FTYPE_V4SF_V4SI_UQI:
11885 : 18172 : case V4SI_FTYPE_V8HF_V4SI_UQI:
11886 : 18172 : case V4SF_FTYPE_V8HF_V4SF_UQI:
11887 : 18172 : case V4DI_FTYPE_V8HF_V4DI_UQI:
11888 : 18172 : case V4DI_FTYPE_V4SF_V4DI_UQI:
11889 : 18172 : case V2DI_FTYPE_V8HF_V2DI_UQI:
11890 : 18172 : case V2DI_FTYPE_V4SF_V2DI_UQI:
11891 : 18172 : case V8HF_FTYPE_V8HF_V8HF_UQI:
11892 : 18172 : case V8HF_FTYPE_V8HF_V8HF_V8HF:
11893 : 18172 : case V8HF_FTYPE_V8HI_V8HF_UQI:
11894 : 18172 : case V8HF_FTYPE_V8SI_V8HF_UQI:
11895 : 18172 : case V8HF_FTYPE_V8SF_V8HF_UQI:
11896 : 18172 : case V8HF_FTYPE_V4SI_V8HF_UQI:
11897 : 18172 : case V8HF_FTYPE_V4SF_V8HF_UQI:
11898 : 18172 : case V8HF_FTYPE_V4DI_V8HF_UQI:
11899 : 18172 : case V8HF_FTYPE_V4DF_V8HF_UQI:
11900 : 18172 : case V8HF_FTYPE_V2DI_V8HF_UQI:
11901 : 18172 : case V8HF_FTYPE_V2DF_V8HF_UQI:
11902 : 18172 : case V4SF_FTYPE_V4DI_V4SF_UQI:
11903 : 18172 : case V4SF_FTYPE_V2DI_V4SF_UQI:
11904 : 18172 : case V4DF_FTYPE_V4DI_V4DF_UQI:
11905 : 18172 : case V4DF_FTYPE_V8HF_V4DF_UQI:
11906 : 18172 : case V2DF_FTYPE_V8HF_V2DF_UQI:
11907 : 18172 : case V2DF_FTYPE_V2DI_V2DF_UQI:
11908 : 18172 : case V16QI_FTYPE_V8HI_V16QI_UQI:
11909 : 18172 : case V16QI_FTYPE_V16HI_V16QI_UHI:
11910 : 18172 : case V16QI_FTYPE_V4SI_V16QI_UQI:
11911 : 18172 : case V16QI_FTYPE_V8SI_V16QI_UQI:
11912 : 18172 : case V8HI_FTYPE_V8HF_V8HI_UQI:
11913 : 18172 : case V8HI_FTYPE_V4SI_V8HI_UQI:
11914 : 18172 : case V8HI_FTYPE_V8SI_V8HI_UQI:
11915 : 18172 : case V16QI_FTYPE_V2DI_V16QI_UQI:
11916 : 18172 : case V16QI_FTYPE_V4DI_V16QI_UQI:
11917 : 18172 : case V8HI_FTYPE_V2DI_V8HI_UQI:
11918 : 18172 : case V8HI_FTYPE_V4DI_V8HI_UQI:
11919 : 18172 : case V4SI_FTYPE_V2DI_V4SI_UQI:
11920 : 18172 : case V4SI_FTYPE_V4DI_V4SI_UQI:
11921 : 18172 : case V32QI_FTYPE_V32HI_V32QI_USI:
11922 : 18172 : case UHI_FTYPE_V16QI_V16QI_UHI:
11923 : 18172 : case USI_FTYPE_V32QI_V32QI_USI:
11924 : 18172 : case UDI_FTYPE_V64QI_V64QI_UDI:
11925 : 18172 : case UQI_FTYPE_V8HI_V8HI_UQI:
11926 : 18172 : case UHI_FTYPE_V16HI_V16HI_UHI:
11927 : 18172 : case USI_FTYPE_V32HI_V32HI_USI:
11928 : 18172 : case UQI_FTYPE_V4SI_V4SI_UQI:
11929 : 18172 : case UQI_FTYPE_V8SI_V8SI_UQI:
11930 : 18172 : case UQI_FTYPE_V2DI_V2DI_UQI:
11931 : 18172 : case UQI_FTYPE_V4DI_V4DI_UQI:
11932 : 18172 : case V4SF_FTYPE_V2DF_V4SF_UQI:
11933 : 18172 : case V4SF_FTYPE_V4DF_V4SF_UQI:
11934 : 18172 : case V16SI_FTYPE_V16SI_V16SI_UHI:
11935 : 18172 : case V16SI_FTYPE_V4SI_V16SI_UHI:
11936 : 18172 : case V2DI_FTYPE_V4SI_V2DI_UQI:
11937 : 18172 : case V2DI_FTYPE_V8HI_V2DI_UQI:
11938 : 18172 : case V2DI_FTYPE_V16QI_V2DI_UQI:
11939 : 18172 : case V4DI_FTYPE_V4DI_V4DI_UQI:
11940 : 18172 : case V4DI_FTYPE_V4SI_V4DI_UQI:
11941 : 18172 : case V4DI_FTYPE_V8HI_V4DI_UQI:
11942 : 18172 : case V4DI_FTYPE_V16QI_V4DI_UQI:
11943 : 18172 : case V4DI_FTYPE_V4DF_V4DI_UQI:
11944 : 18172 : case V2DI_FTYPE_V2DF_V2DI_UQI:
11945 : 18172 : case V4SI_FTYPE_V4DF_V4SI_UQI:
11946 : 18172 : case V4SI_FTYPE_V2DF_V4SI_UQI:
11947 : 18172 : case V4SI_FTYPE_V8HI_V4SI_UQI:
11948 : 18172 : case V4SI_FTYPE_V16QI_V4SI_UQI:
11949 : 18172 : case V4DI_FTYPE_V4DI_V4DI_V4DI:
11950 : 18172 : case V8DF_FTYPE_V2DF_V8DF_UQI:
11951 : 18172 : case V8DF_FTYPE_V4DF_V8DF_UQI:
11952 : 18172 : case V8DF_FTYPE_V8DF_V8DF_UQI:
11953 : 18172 : case V8SF_FTYPE_V8SF_V8SF_UQI:
11954 : 18172 : case V8SF_FTYPE_V8SI_V8SF_UQI:
11955 : 18172 : case V4DF_FTYPE_V4DF_V4DF_UQI:
11956 : 18172 : case V4SF_FTYPE_V4SF_V4SF_UQI:
11957 : 18172 : case V2DF_FTYPE_V2DF_V2DF_UQI:
11958 : 18172 : case V2DF_FTYPE_V4SF_V2DF_UQI:
11959 : 18172 : case V2DF_FTYPE_V4SI_V2DF_UQI:
11960 : 18172 : case V4SF_FTYPE_V4SI_V4SF_UQI:
11961 : 18172 : case V4DF_FTYPE_V4SF_V4DF_UQI:
11962 : 18172 : case V4DF_FTYPE_V4SI_V4DF_UQI:
11963 : 18172 : case V8SI_FTYPE_V8SI_V8SI_UQI:
11964 : 18172 : case V8SI_FTYPE_V8HI_V8SI_UQI:
11965 : 18172 : case V8SI_FTYPE_V16QI_V8SI_UQI:
11966 : 18172 : case V8DF_FTYPE_V8SI_V8DF_UQI:
11967 : 18172 : case V8DI_FTYPE_DI_V8DI_UQI:
11968 : 18172 : case V16SF_FTYPE_V8SF_V16SF_UHI:
11969 : 18172 : case V16SI_FTYPE_V8SI_V16SI_UHI:
11970 : 18172 : case V16HF_FTYPE_V16HI_V16HF_UHI:
11971 : 18172 : case V16HF_FTYPE_V16HF_V16HF_V16HF:
11972 : 18172 : case V16HI_FTYPE_V16HF_V16HI_UHI:
11973 : 18172 : case V16HI_FTYPE_V16HI_V16HI_UHI:
11974 : 18172 : case V16BF_FTYPE_V16BF_V16BF_UHI:
11975 : 18172 : case V8HI_FTYPE_V16QI_V8HI_UQI:
11976 : 18172 : case V16HI_FTYPE_V16QI_V16HI_UHI:
11977 : 18172 : case V32HI_FTYPE_V32HI_V32HI_USI:
11978 : 18172 : case V32BF_FTYPE_V32BF_V32BF_USI:
11979 : 18172 : case V32HI_FTYPE_V32QI_V32HI_USI:
11980 : 18172 : case V8DI_FTYPE_V16QI_V8DI_UQI:
11981 : 18172 : case V8DI_FTYPE_V2DI_V8DI_UQI:
11982 : 18172 : case V8DI_FTYPE_V4DI_V8DI_UQI:
11983 : 18172 : case V8DI_FTYPE_V8DI_V8DI_UQI:
11984 : 18172 : case V8DI_FTYPE_V8HI_V8DI_UQI:
11985 : 18172 : case V8DI_FTYPE_V8SI_V8DI_UQI:
11986 : 18172 : case V8HI_FTYPE_V8DI_V8HI_UQI:
11987 : 18172 : case V8SI_FTYPE_V8DI_V8SI_UQI:
11988 : 18172 : case V4SI_FTYPE_V4SI_V4SI_V4SI:
11989 : 18172 : case V4DI_FTYPE_V4DI_V4DI_V2DI:
11990 : 18172 : case V16SI_FTYPE_V16SI_V16SI_V16SI:
11991 : 18172 : case V8DI_FTYPE_V8DI_V8DI_V8DI:
11992 : 18172 : case V32HI_FTYPE_V32HI_V32HI_V32HI:
11993 : 18172 : case V2DI_FTYPE_V2DI_V2DI_V2DI:
11994 : 18172 : case V16HI_FTYPE_V16HI_V16HI_V16HI:
11995 : 18172 : case V8SI_FTYPE_V8SI_V8SI_V8SI:
11996 : 18172 : case V8HI_FTYPE_V8HI_V8HI_V8HI:
11997 : 18172 : case V32BF_FTYPE_V16SF_V16SF_USI:
11998 : 18172 : case V16BF_FTYPE_V8SF_V8SF_UHI:
11999 : 18172 : case V8BF_FTYPE_V4SF_V4SF_UQI:
12000 : 18172 : case V16BF_FTYPE_V16SF_V16BF_UHI:
12001 : 18172 : case V8BF_FTYPE_V8SF_V8BF_UQI:
12002 : 18172 : case V8BF_FTYPE_V4SF_V8BF_UQI:
12003 : 18172 : case V16SF_FTYPE_V16SF_V32BF_V32BF:
12004 : 18172 : case V8SF_FTYPE_V8SF_V16BF_V16BF:
12005 : 18172 : case V4SF_FTYPE_V4SF_V8BF_V8BF:
12006 : 18172 : case V16QI_FTYPE_V16QI_V8HF_V8HF:
12007 : 18172 : case V32QI_FTYPE_V32QI_V16HF_V16HF:
12008 : 18172 : case V64QI_FTYPE_V64QI_V32HF_V32HF:
12009 : 18172 : case V16QI_FTYPE_V8HF_V16QI_UQI:
12010 : 18172 : case V16QI_FTYPE_V16HF_V16QI_UHI:
12011 : 18172 : case V32QI_FTYPE_V32HF_V32QI_USI:
12012 : 18172 : case V8HF_FTYPE_V16QI_V8HF_UQI:
12013 : 18172 : case V16HF_FTYPE_V16QI_V16HF_UHI:
12014 : 18172 : case V32HF_FTYPE_V32QI_V32HF_USI:
12015 : 18172 : case V16SI_FTYPE_V16SF_V16SI_UHI:
12016 : 18172 : case V32HI_FTYPE_V32HF_V32HI_USI:
12017 : 18172 : case V8DI_FTYPE_V8SF_V8DI_UQI:
12018 : 18172 : case V8DI_FTYPE_V8DF_V8DI_UQI:
12019 : 18172 : case V8SI_FTYPE_V8DF_V8SI_UQI:
12020 : 18172 : nargs = 3;
12021 : 18172 : break;
12022 : 1475 : case V32QI_FTYPE_V32QI_V32QI_INT:
12023 : 1475 : case V16HI_FTYPE_V16HI_V16HI_INT:
12024 : 1475 : case V16QI_FTYPE_V16QI_V16QI_INT:
12025 : 1475 : case V4DI_FTYPE_V4DI_V4DI_INT:
12026 : 1475 : case V8HI_FTYPE_V8HI_V8HI_INT:
12027 : 1475 : case V8SI_FTYPE_V8SI_V8SI_INT:
12028 : 1475 : case V8SI_FTYPE_V8SI_V4SI_INT:
12029 : 1475 : case V8SF_FTYPE_V8SF_V8SF_INT:
12030 : 1475 : case V8SF_FTYPE_V8SF_V4SF_INT:
12031 : 1475 : case V4SI_FTYPE_V4SI_V4SI_INT:
12032 : 1475 : case V4DF_FTYPE_V4DF_V4DF_INT:
12033 : 1475 : case V16SF_FTYPE_V16SF_V16SF_INT:
12034 : 1475 : case V16SF_FTYPE_V16SF_V4SF_INT:
12035 : 1475 : case V16SI_FTYPE_V16SI_V4SI_INT:
12036 : 1475 : case V4DF_FTYPE_V4DF_V2DF_INT:
12037 : 1475 : case V4SF_FTYPE_V4SF_V4SF_INT:
12038 : 1475 : case V2DI_FTYPE_V2DI_V2DI_INT:
12039 : 1475 : case V4DI_FTYPE_V4DI_V2DI_INT:
12040 : 1475 : case V2DF_FTYPE_V2DF_V2DF_INT:
12041 : 1475 : case UQI_FTYPE_V8DI_V8UDI_INT:
12042 : 1475 : case UQI_FTYPE_V8DF_V8DF_INT:
12043 : 1475 : case UQI_FTYPE_V2DF_V2DF_INT:
12044 : 1475 : case UQI_FTYPE_V4SF_V4SF_INT:
12045 : 1475 : case UHI_FTYPE_V16SI_V16SI_INT:
12046 : 1475 : case UHI_FTYPE_V16SF_V16SF_INT:
12047 : 1475 : case V64QI_FTYPE_V64QI_V64QI_INT:
12048 : 1475 : case V32HI_FTYPE_V32HI_V32HI_INT:
12049 : 1475 : case V16SI_FTYPE_V16SI_V16SI_INT:
12050 : 1475 : case V8DI_FTYPE_V8DI_V8DI_INT:
12051 : 1475 : nargs = 3;
12052 : 1475 : nargs_constant = 1;
12053 : 1475 : break;
12054 : 47 : case V4DI_FTYPE_V4DI_V4DI_INT_CONVERT:
12055 : 47 : nargs = 3;
12056 : 47 : rmode = V4DImode;
12057 : 47 : nargs_constant = 1;
12058 : 47 : break;
12059 : 80 : case V2DI_FTYPE_V2DI_V2DI_INT_CONVERT:
12060 : 80 : nargs = 3;
12061 : 80 : rmode = V2DImode;
12062 : 80 : nargs_constant = 1;
12063 : 80 : break;
12064 : 48 : case V1DI_FTYPE_V1DI_V1DI_INT_CONVERT:
12065 : 48 : nargs = 3;
12066 : 48 : rmode = DImode;
12067 : 48 : nargs_constant = 1;
12068 : 48 : break;
12069 : 20 : case V2DI_FTYPE_V2DI_UINT_UINT:
12070 : 20 : nargs = 3;
12071 : 20 : nargs_constant = 2;
12072 : 20 : break;
12073 : 8 : case V8DI_FTYPE_V8DI_V8DI_INT_CONVERT:
12074 : 8 : nargs = 3;
12075 : 8 : rmode = V8DImode;
12076 : 8 : nargs_constant = 1;
12077 : 8 : break;
12078 : 16 : case V8DI_FTYPE_V8DI_V8DI_INT_V8DI_UDI_CONVERT:
12079 : 16 : nargs = 5;
12080 : 16 : rmode = V8DImode;
12081 : 16 : mask_pos = 2;
12082 : 16 : nargs_constant = 1;
12083 : 16 : break;
12084 : 311 : case QI_FTYPE_V8DF_INT_UQI:
12085 : 311 : case QI_FTYPE_V4DF_INT_UQI:
12086 : 311 : case QI_FTYPE_V2DF_INT_UQI:
12087 : 311 : case HI_FTYPE_V16SF_INT_UHI:
12088 : 311 : case QI_FTYPE_V8SF_INT_UQI:
12089 : 311 : case QI_FTYPE_V4SF_INT_UQI:
12090 : 311 : case QI_FTYPE_V8HF_INT_UQI:
12091 : 311 : case HI_FTYPE_V16HF_INT_UHI:
12092 : 311 : case SI_FTYPE_V32HF_INT_USI:
12093 : 311 : case QI_FTYPE_V8BF_INT_UQI:
12094 : 311 : case HI_FTYPE_V16BF_INT_UHI:
12095 : 311 : case SI_FTYPE_V32BF_INT_USI:
12096 : 311 : case V4SI_FTYPE_V4SI_V4SI_UHI:
12097 : 311 : case V8SI_FTYPE_V8SI_V8SI_UHI:
12098 : 311 : nargs = 3;
12099 : 311 : mask_pos = 1;
12100 : 311 : nargs_constant = 1;
12101 : 311 : break;
12102 : 17 : case V4DI_FTYPE_V4DI_V4DI_INT_V4DI_USI_CONVERT:
12103 : 17 : nargs = 5;
12104 : 17 : rmode = V4DImode;
12105 : 17 : mask_pos = 2;
12106 : 17 : nargs_constant = 1;
12107 : 17 : break;
12108 : 17 : case V2DI_FTYPE_V2DI_V2DI_INT_V2DI_UHI_CONVERT:
12109 : 17 : nargs = 5;
12110 : 17 : rmode = V2DImode;
12111 : 17 : mask_pos = 2;
12112 : 17 : nargs_constant = 1;
12113 : 17 : break;
12114 : 17063 : case V32QI_FTYPE_V32QI_V32QI_V32QI_USI:
12115 : 17063 : case V32HI_FTYPE_V32HI_V32HI_V32HI_USI:
12116 : 17063 : case V32BF_FTYPE_V32BF_V32BF_V32BF_USI:
12117 : 17063 : case V32HI_FTYPE_V64QI_V64QI_V32HI_USI:
12118 : 17063 : case V16SI_FTYPE_V32HI_V32HI_V16SI_UHI:
12119 : 17063 : case V64QI_FTYPE_V64QI_V64QI_V64QI_UDI:
12120 : 17063 : case V32HI_FTYPE_V32HI_V8HI_V32HI_USI:
12121 : 17063 : case V16HI_FTYPE_V16HI_V8HI_V16HI_UHI:
12122 : 17063 : case V8SI_FTYPE_V8SI_V4SI_V8SI_UQI:
12123 : 17063 : case V4DI_FTYPE_V4DI_V2DI_V4DI_UQI:
12124 : 17063 : case V64QI_FTYPE_V32HI_V32HI_V64QI_UDI:
12125 : 17063 : case V32QI_FTYPE_V16HI_V16HI_V32QI_USI:
12126 : 17063 : case V16QI_FTYPE_V8HI_V8HI_V16QI_UHI:
12127 : 17063 : case V32HI_FTYPE_V16SI_V16SI_V32HI_USI:
12128 : 17063 : case V16HI_FTYPE_V8SI_V8SI_V16HI_UHI:
12129 : 17063 : case V8HI_FTYPE_V4SI_V4SI_V8HI_UQI:
12130 : 17063 : case V4DF_FTYPE_V4DF_V4DI_V4DF_UQI:
12131 : 17063 : case V32HF_FTYPE_V32HF_V32HF_V32HF_USI:
12132 : 17063 : case V8SF_FTYPE_V8SF_V8SI_V8SF_UQI:
12133 : 17063 : case V4SF_FTYPE_V4SF_V4SI_V4SF_UQI:
12134 : 17063 : case V2DF_FTYPE_V2DF_V2DI_V2DF_UQI:
12135 : 17063 : case V2DI_FTYPE_V4SI_V4SI_V2DI_UQI:
12136 : 17063 : case V4DI_FTYPE_V8SI_V8SI_V4DI_UQI:
12137 : 17063 : case V4DF_FTYPE_V4DI_V4DF_V4DF_UQI:
12138 : 17063 : case V8SF_FTYPE_V8SI_V8SF_V8SF_UQI:
12139 : 17063 : case V2DF_FTYPE_V2DI_V2DF_V2DF_UQI:
12140 : 17063 : case V4SF_FTYPE_V4SI_V4SF_V4SF_UQI:
12141 : 17063 : case V16SF_FTYPE_V16SF_V16SF_V16SF_UHI:
12142 : 17063 : case V16SF_FTYPE_V16SF_V16SI_V16SF_UHI:
12143 : 17063 : case V16SF_FTYPE_V16SI_V16SF_V16SF_UHI:
12144 : 17063 : case V16SI_FTYPE_V16SI_V16SI_V16SI_UHI:
12145 : 17063 : case V16SI_FTYPE_V16SI_V4SI_V16SI_UHI:
12146 : 17063 : case V8HI_FTYPE_V8HI_V8HI_V8HI_UQI:
12147 : 17063 : case V8BF_FTYPE_V8BF_V8BF_V8BF_UQI:
12148 : 17063 : case V8SI_FTYPE_V8SI_V8SI_V8SI_UQI:
12149 : 17063 : case V4SI_FTYPE_V4SI_V4SI_V4SI_UQI:
12150 : 17063 : case V16HF_FTYPE_V16HF_V16HF_V16HF_UQI:
12151 : 17063 : case V16HF_FTYPE_V16HF_V16HF_V16HF_UHI:
12152 : 17063 : case V8SF_FTYPE_V8SF_V8SF_V8SF_UQI:
12153 : 17063 : case V16QI_FTYPE_V16QI_V16QI_V16QI_UHI:
12154 : 17063 : case V16HI_FTYPE_V16HI_V16HI_V16HI_UHI:
12155 : 17063 : case V16BF_FTYPE_V16BF_V16BF_V16BF_UHI:
12156 : 17063 : case V2DI_FTYPE_V2DI_V2DI_V2DI_UQI:
12157 : 17063 : case V2DF_FTYPE_V2DF_V2DF_V2DF_UQI:
12158 : 17063 : case V4DI_FTYPE_V4DI_V4DI_V4DI_UQI:
12159 : 17063 : case V4DF_FTYPE_V4DF_V4DF_V4DF_UQI:
12160 : 17063 : case V8HF_FTYPE_V8HF_V8HF_V8HF_UQI:
12161 : 17063 : case V4SF_FTYPE_V4SF_V4SF_V4SF_UQI:
12162 : 17063 : case V8DF_FTYPE_V8DF_V8DF_V8DF_UQI:
12163 : 17063 : case V8DF_FTYPE_V8DF_V8DI_V8DF_UQI:
12164 : 17063 : case V8DF_FTYPE_V8DI_V8DF_V8DF_UQI:
12165 : 17063 : case V8DI_FTYPE_V16SI_V16SI_V8DI_UQI:
12166 : 17063 : case V8DI_FTYPE_V8DI_V2DI_V8DI_UQI:
12167 : 17063 : case V8DI_FTYPE_V8DI_V8DI_V8DI_UQI:
12168 : 17063 : case V8HI_FTYPE_V16QI_V16QI_V8HI_UQI:
12169 : 17063 : case V16HI_FTYPE_V32QI_V32QI_V16HI_UHI:
12170 : 17063 : case V8SI_FTYPE_V16HI_V16HI_V8SI_UQI:
12171 : 17063 : case V4SI_FTYPE_V8HI_V8HI_V4SI_UQI:
12172 : 17063 : case V32BF_FTYPE_V16SF_V16SF_V32BF_USI:
12173 : 17063 : case V16BF_FTYPE_V8SF_V8SF_V16BF_UHI:
12174 : 17063 : case V8BF_FTYPE_V4SF_V4SF_V8BF_UQI:
12175 : 17063 : case V32HF_FTYPE_V16SF_V16SF_V32HF_USI:
12176 : 17063 : case V16HF_FTYPE_V8SF_V8SF_V16HF_UHI:
12177 : 17063 : case V8HF_FTYPE_V4SF_V4SF_V8HF_UQI:
12178 : 17063 : case V16QI_FTYPE_V8HF_V8HF_V16QI_UHI:
12179 : 17063 : case V32QI_FTYPE_V16HF_V16HF_V32QI_USI:
12180 : 17063 : case V64QI_FTYPE_V32HF_V32HF_V64QI_UDI:
12181 : 17063 : case V16QI_FTYPE_V16QI_V8HF_V16QI_UHI:
12182 : 17063 : case V16QI_FTYPE_V32QI_V16HF_V16QI_UHI:
12183 : 17063 : case V32QI_FTYPE_V64QI_V32HF_V32QI_USI:
12184 : 17063 : nargs = 4;
12185 : 17063 : break;
12186 : 11 : case V2DF_FTYPE_V2DF_V2DF_V2DI_INT:
12187 : 11 : case V4DF_FTYPE_V4DF_V4DF_V4DI_INT:
12188 : 11 : case V4SF_FTYPE_V4SF_V4SF_V4SI_INT:
12189 : 11 : case V8SF_FTYPE_V8SF_V8SF_V8SI_INT:
12190 : 11 : case V16SF_FTYPE_V16SF_V16SF_V16SI_INT:
12191 : 11 : case V4SI_FTYPE_V4SI_V4SI_V4SI_INT:
12192 : 11 : nargs = 4;
12193 : 11 : nargs_constant = 1;
12194 : 11 : break;
12195 : 3687 : case UQI_FTYPE_V4DI_V4DI_INT_UQI:
12196 : 3687 : case UQI_FTYPE_V8SI_V8SI_INT_UQI:
12197 : 3687 : case QI_FTYPE_V4DF_V4DF_INT_UQI:
12198 : 3687 : case QI_FTYPE_V8SF_V8SF_INT_UQI:
12199 : 3687 : case UHI_FTYPE_V16HF_V16HF_INT_UHI:
12200 : 3687 : case UQI_FTYPE_V2DI_V2DI_INT_UQI:
12201 : 3687 : case UQI_FTYPE_V4SI_V4SI_INT_UQI:
12202 : 3687 : case UQI_FTYPE_V2DF_V2DF_INT_UQI:
12203 : 3687 : case UQI_FTYPE_V4SF_V4SF_INT_UQI:
12204 : 3687 : case UQI_FTYPE_V8HF_V8HF_INT_UQI:
12205 : 3687 : case UDI_FTYPE_V64QI_V64QI_INT_UDI:
12206 : 3687 : case USI_FTYPE_V32QI_V32QI_INT_USI:
12207 : 3687 : case UHI_FTYPE_V16QI_V16QI_INT_UHI:
12208 : 3687 : case USI_FTYPE_V32HI_V32HI_INT_USI:
12209 : 3687 : case USI_FTYPE_V32BF_V32BF_INT_USI:
12210 : 3687 : case USI_FTYPE_V32HF_V32HF_INT_USI:
12211 : 3687 : case UHI_FTYPE_V16HI_V16HI_INT_UHI:
12212 : 3687 : case UHI_FTYPE_V16BF_V16BF_INT_UHI:
12213 : 3687 : case UQI_FTYPE_V8HI_V8HI_INT_UQI:
12214 : 3687 : case UQI_FTYPE_V8BF_V8BF_INT_UQI:
12215 : 3687 : nargs = 4;
12216 : 3687 : mask_pos = 1;
12217 : 3687 : nargs_constant = 1;
12218 : 3687 : break;
12219 : 23 : case V2DI_FTYPE_V2DI_V2DI_UINT_UINT:
12220 : 23 : nargs = 4;
12221 : 23 : nargs_constant = 2;
12222 : 23 : break;
12223 : 67 : case UCHAR_FTYPE_UCHAR_UINT_UINT_PUNSIGNED:
12224 : 67 : case UCHAR_FTYPE_UCHAR_ULONGLONG_ULONGLONG_PULONGLONG:
12225 : 67 : case V16SF_FTYPE_V16SF_V32BF_V32BF_UHI:
12226 : 67 : case V8SF_FTYPE_V8SF_V16BF_V16BF_UQI:
12227 : 67 : case V4SF_FTYPE_V4SF_V8BF_V8BF_UQI:
12228 : 67 : nargs = 4;
12229 : 67 : break;
12230 : 667 : case UQI_FTYPE_V8DI_V8DI_INT_UQI:
12231 : 667 : case UHI_FTYPE_V16SI_V16SI_INT_UHI:
12232 : 667 : mask_pos = 1;
12233 : 667 : nargs = 4;
12234 : 667 : nargs_constant = 1;
12235 : 667 : break;
12236 : 3754 : case V8SF_FTYPE_V8SF_INT_V8SF_UQI:
12237 : 3754 : case V4SF_FTYPE_V4SF_INT_V4SF_UQI:
12238 : 3754 : case V2DF_FTYPE_V4DF_INT_V2DF_UQI:
12239 : 3754 : case V2DI_FTYPE_V4DI_INT_V2DI_UQI:
12240 : 3754 : case V8SF_FTYPE_V16SF_INT_V8SF_UQI:
12241 : 3754 : case V8SI_FTYPE_V16SI_INT_V8SI_UQI:
12242 : 3754 : case V2DF_FTYPE_V8DF_INT_V2DF_UQI:
12243 : 3754 : case V2DI_FTYPE_V8DI_INT_V2DI_UQI:
12244 : 3754 : case V4SF_FTYPE_V8SF_INT_V4SF_UQI:
12245 : 3754 : case V4SI_FTYPE_V8SI_INT_V4SI_UQI:
12246 : 3754 : case V8HI_FTYPE_V8SF_INT_V8HI_UQI:
12247 : 3754 : case V8HI_FTYPE_V4SF_INT_V8HI_UQI:
12248 : 3754 : case V32HI_FTYPE_V32HI_INT_V32HI_USI:
12249 : 3754 : case V16HI_FTYPE_V16HI_INT_V16HI_UHI:
12250 : 3754 : case V8HI_FTYPE_V8HI_INT_V8HI_UQI:
12251 : 3754 : case V32BF_FTYPE_V32BF_INT_V32BF_USI:
12252 : 3754 : case V16BF_FTYPE_V16BF_INT_V16BF_UHI:
12253 : 3754 : case V8BF_FTYPE_V8BF_INT_V8BF_UQI:
12254 : 3754 : case V4DI_FTYPE_V4DI_INT_V4DI_UQI:
12255 : 3754 : case V2DI_FTYPE_V2DI_INT_V2DI_UQI:
12256 : 3754 : case V8SI_FTYPE_V8SI_INT_V8SI_UQI:
12257 : 3754 : case V4SI_FTYPE_V4SI_INT_V4SI_UQI:
12258 : 3754 : case V4DF_FTYPE_V4DF_INT_V4DF_UQI:
12259 : 3754 : case V2DF_FTYPE_V2DF_INT_V2DF_UQI:
12260 : 3754 : case V8DF_FTYPE_V8DF_INT_V8DF_UQI:
12261 : 3754 : case V16SF_FTYPE_V16SF_INT_V16SF_UHI:
12262 : 3754 : case V16HI_FTYPE_V16SF_INT_V16HI_UHI:
12263 : 3754 : case V16SI_FTYPE_V16SI_INT_V16SI_UHI:
12264 : 3754 : case V16HF_FTYPE_V16HF_INT_V16HF_UHI:
12265 : 3754 : case V8HF_FTYPE_V8HF_INT_V8HF_UQI:
12266 : 3754 : case V4SI_FTYPE_V16SI_INT_V4SI_UQI:
12267 : 3754 : case V4DI_FTYPE_V8DI_INT_V4DI_UQI:
12268 : 3754 : case V4DF_FTYPE_V8DF_INT_V4DF_UQI:
12269 : 3754 : case V4SF_FTYPE_V16SF_INT_V4SF_UQI:
12270 : 3754 : case V8DI_FTYPE_V8DI_INT_V8DI_UQI:
12271 : 3754 : nargs = 4;
12272 : 3754 : mask_pos = 2;
12273 : 3754 : nargs_constant = 1;
12274 : 3754 : break;
12275 : 1648 : case V16SF_FTYPE_V16SF_V4SF_INT_V16SF_UHI:
12276 : 1648 : case V16SI_FTYPE_V16SI_V4SI_INT_V16SI_UHI:
12277 : 1648 : case V8DF_FTYPE_V8DF_V8DF_INT_V8DF_UQI:
12278 : 1648 : case V8DI_FTYPE_V8DI_V8DI_INT_V8DI_UQI:
12279 : 1648 : case V16SF_FTYPE_V16SF_V16SF_INT_V16SF_UHI:
12280 : 1648 : case V16SI_FTYPE_V16SI_V16SI_INT_V16SI_UHI:
12281 : 1648 : case V4SF_FTYPE_V4SF_V4SF_INT_V4SF_UQI:
12282 : 1648 : case V2DF_FTYPE_V2DF_V2DF_INT_V2DF_UQI:
12283 : 1648 : case V8DF_FTYPE_V8DF_V4DF_INT_V8DF_UQI:
12284 : 1648 : case V8DI_FTYPE_V8DI_V4DI_INT_V8DI_UQI:
12285 : 1648 : case V4DF_FTYPE_V4DF_V4DF_INT_V4DF_UQI:
12286 : 1648 : case V8SF_FTYPE_V8SF_V8SF_INT_V8SF_UQI:
12287 : 1648 : case V8DF_FTYPE_V8DF_V2DF_INT_V8DF_UQI:
12288 : 1648 : case V8DI_FTYPE_V8DI_V2DI_INT_V8DI_UQI:
12289 : 1648 : case V8SI_FTYPE_V8SI_V8SI_INT_V8SI_UQI:
12290 : 1648 : case V4DI_FTYPE_V4DI_V4DI_INT_V4DI_UQI:
12291 : 1648 : case V4SI_FTYPE_V4SI_V4SI_INT_V4SI_UQI:
12292 : 1648 : case V2DI_FTYPE_V2DI_V2DI_INT_V2DI_UQI:
12293 : 1648 : case V32HI_FTYPE_V64QI_V64QI_INT_V32HI_USI:
12294 : 1648 : case V16HI_FTYPE_V32QI_V32QI_INT_V16HI_UHI:
12295 : 1648 : case V8HI_FTYPE_V16QI_V16QI_INT_V8HI_UQI:
12296 : 1648 : case V16SF_FTYPE_V16SF_V8SF_INT_V16SF_UHI:
12297 : 1648 : case V16SI_FTYPE_V16SI_V8SI_INT_V16SI_UHI:
12298 : 1648 : case V8SF_FTYPE_V8SF_V4SF_INT_V8SF_UQI:
12299 : 1648 : case V8SI_FTYPE_V8SI_V4SI_INT_V8SI_UQI:
12300 : 1648 : case V4DI_FTYPE_V4DI_V2DI_INT_V4DI_UQI:
12301 : 1648 : case V4DF_FTYPE_V4DF_V2DF_INT_V4DF_UQI:
12302 : 1648 : nargs = 5;
12303 : 1648 : mask_pos = 2;
12304 : 1648 : nargs_constant = 1;
12305 : 1648 : break;
12306 : 268 : case V8DI_FTYPE_V8DI_V8DI_V8DI_INT_UQI:
12307 : 268 : case V16SI_FTYPE_V16SI_V16SI_V16SI_INT_UHI:
12308 : 268 : case V2DF_FTYPE_V2DF_V2DF_V2DI_INT_UQI:
12309 : 268 : case V4SF_FTYPE_V4SF_V4SF_V4SI_INT_UQI:
12310 : 268 : case V8SF_FTYPE_V8SF_V8SF_V8SI_INT_UQI:
12311 : 268 : case V8SI_FTYPE_V8SI_V8SI_V8SI_INT_UQI:
12312 : 268 : case V4DF_FTYPE_V4DF_V4DF_V4DI_INT_UQI:
12313 : 268 : case V4DI_FTYPE_V4DI_V4DI_V4DI_INT_UQI:
12314 : 268 : case V4SI_FTYPE_V4SI_V4SI_V4SI_INT_UQI:
12315 : 268 : case V2DI_FTYPE_V2DI_V2DI_V2DI_INT_UQI:
12316 : 268 : nargs = 5;
12317 : 268 : mask_pos = 1;
12318 : 268 : nargs_constant = 1;
12319 : 268 : break;
12320 : 642 : case V64QI_FTYPE_V64QI_V64QI_INT_V64QI_UDI:
12321 : 642 : case V32QI_FTYPE_V32QI_V32QI_INT_V32QI_USI:
12322 : 642 : case V16QI_FTYPE_V16QI_V16QI_INT_V16QI_UHI:
12323 : 642 : case V32HI_FTYPE_V32HI_V32HI_INT_V32HI_INT:
12324 : 642 : case V16SI_FTYPE_V16SI_V16SI_INT_V16SI_INT:
12325 : 642 : case V8DI_FTYPE_V8DI_V8DI_INT_V8DI_INT:
12326 : 642 : case V16HI_FTYPE_V16HI_V16HI_INT_V16HI_INT:
12327 : 642 : case V8SI_FTYPE_V8SI_V8SI_INT_V8SI_INT:
12328 : 642 : case V4DI_FTYPE_V4DI_V4DI_INT_V4DI_INT:
12329 : 642 : case V8HI_FTYPE_V8HI_V8HI_INT_V8HI_INT:
12330 : 642 : case V4SI_FTYPE_V4SI_V4SI_INT_V4SI_INT:
12331 : 642 : case V2DI_FTYPE_V2DI_V2DI_INT_V2DI_INT:
12332 : 642 : case V8BF_FTYPE_V8BF_V8BF_INT_V8BF_UQI:
12333 : 642 : case V16BF_FTYPE_V16BF_V16BF_INT_V16BF_UHI:
12334 : 642 : case V32BF_FTYPE_V32BF_V32BF_INT_V32BF_USI:
12335 : 642 : case V16HF_FTYPE_V16HF_V16HF_INT_V16HF_UHI:
12336 : 642 : case V8HF_FTYPE_V8HF_V8HF_INT_V8HF_UQI:
12337 : 642 : nargs = 5;
12338 : 642 : mask_pos = 1;
12339 : 642 : nargs_constant = 2;
12340 : 642 : break;
12341 : :
12342 : 0 : default:
12343 : 0 : gcc_unreachable ();
12344 : : }
12345 : :
12346 : 55116 : gcc_assert (nargs <= ARRAY_SIZE (xops));
12347 : :
12348 : 58845 : if (comparison != UNKNOWN)
12349 : : {
12350 : 614 : gcc_assert (nargs == 2);
12351 : 614 : return ix86_expand_sse_compare (d, exp, target, swap);
12352 : : }
12353 : :
12354 : 58231 : if (rmode == VOIDmode || rmode == tmode)
12355 : : {
12356 : 58046 : if (optimize
12357 : 17690 : || target == 0
12358 : 17690 : || GET_MODE (target) != tmode
12359 : 75534 : || !insn_p->operand[0].predicate (target, tmode))
12360 : 40646 : target = gen_reg_rtx (tmode);
12361 : 17400 : else if (memory_operand (target, tmode))
12362 : 578 : num_memory++;
12363 : : real_target = target;
12364 : : }
12365 : : else
12366 : : {
12367 : 185 : real_target = gen_reg_rtx (tmode);
12368 : 185 : target = lowpart_subreg (rmode, real_target, tmode);
12369 : : }
12370 : :
12371 : 252518 : for (i = 0; i < nargs; i++)
12372 : : {
12373 : 194520 : tree arg = CALL_EXPR_ARG (exp, i);
12374 : 194520 : rtx op = ix86_expand_unsigned_small_int_cst_argument (arg);
12375 : 194520 : machine_mode mode = insn_p->operand[i + 1].mode;
12376 : : /* Need to fixup modeless constant before testing predicate. */
12377 : 194520 : op = fixup_modeless_constant (op, mode);
12378 : 194520 : bool match = insn_p->operand[i + 1].predicate (op, mode);
12379 : :
12380 : 194520 : if (second_arg_count && i == 1)
12381 : : {
12382 : : /* SIMD shift insns take either an 8-bit immediate or
12383 : : register as count. But builtin functions take int as
12384 : : count. If count doesn't match, we put it in register.
12385 : : The instructions are using 64-bit count, if op is just
12386 : : 32-bit, zero-extend it, as negative shift counts
12387 : : are undefined behavior and zero-extension is more
12388 : : efficient. */
12389 : 2887 : if (!match)
12390 : : {
12391 : 1748 : if (SCALAR_INT_MODE_P (GET_MODE (op)))
12392 : 489 : op = convert_modes (mode, GET_MODE (op), op, 1);
12393 : : else
12394 : 1259 : op = lowpart_subreg (mode, op, GET_MODE (op));
12395 : 1748 : if (!insn_p->operand[i + 1].predicate (op, mode))
12396 : 190 : op = copy_to_reg (op);
12397 : : }
12398 : : }
12399 : 191633 : else if ((mask_pos && (nargs - i - mask_pos) == nargs_constant) ||
12400 : 145392 : (!mask_pos && (nargs - i) <= nargs_constant))
12401 : : {
12402 : 16009 : if (!match)
12403 : 233 : switch (icode)
12404 : : {
12405 : 2 : case CODE_FOR_avx_vinsertf128v4di:
12406 : 2 : case CODE_FOR_avx_vextractf128v4di:
12407 : 2 : error ("the last argument must be an 1-bit immediate");
12408 : 2 : return const0_rtx;
12409 : :
12410 : 8 : case CODE_FOR_avx512f_cmpv8di3_mask:
12411 : 8 : case CODE_FOR_avx512f_cmpv16si3_mask:
12412 : 8 : case CODE_FOR_avx512f_ucmpv8di3_mask:
12413 : 8 : case CODE_FOR_avx512f_ucmpv16si3_mask:
12414 : 8 : case CODE_FOR_avx512vl_cmpv4di3_mask:
12415 : 8 : case CODE_FOR_avx512vl_cmpv8si3_mask:
12416 : 8 : case CODE_FOR_avx512vl_ucmpv4di3_mask:
12417 : 8 : case CODE_FOR_avx512vl_ucmpv8si3_mask:
12418 : 8 : case CODE_FOR_avx512vl_cmpv2di3_mask:
12419 : 8 : case CODE_FOR_avx512vl_cmpv4si3_mask:
12420 : 8 : case CODE_FOR_avx512vl_ucmpv2di3_mask:
12421 : 8 : case CODE_FOR_avx512vl_ucmpv4si3_mask:
12422 : 8 : error ("the last argument must be a 3-bit immediate");
12423 : 8 : return const0_rtx;
12424 : :
12425 : 24 : case CODE_FOR_sse4_1_roundsd:
12426 : 24 : case CODE_FOR_sse4_1_roundss:
12427 : :
12428 : 24 : case CODE_FOR_sse4_1_roundpd:
12429 : 24 : case CODE_FOR_sse4_1_roundps:
12430 : 24 : case CODE_FOR_avx_roundpd256:
12431 : 24 : case CODE_FOR_avx_roundps256:
12432 : :
12433 : 24 : case CODE_FOR_sse4_1_roundpd_vec_pack_sfix:
12434 : 24 : case CODE_FOR_sse4_1_roundps_sfix:
12435 : 24 : case CODE_FOR_avx_roundpd_vec_pack_sfix256:
12436 : 24 : case CODE_FOR_avx_roundps_sfix256:
12437 : :
12438 : 24 : case CODE_FOR_sse4_1_blendps:
12439 : 24 : case CODE_FOR_avx_blendpd256:
12440 : 24 : case CODE_FOR_avx_vpermilv4df:
12441 : 24 : case CODE_FOR_avx_vpermilv4df_mask:
12442 : 24 : case CODE_FOR_avx512f_getmantv8df_mask:
12443 : 24 : case CODE_FOR_avx512f_getmantv16sf_mask:
12444 : 24 : case CODE_FOR_avx512vl_getmantv16hf_mask:
12445 : 24 : case CODE_FOR_avx512vl_getmantv8sf_mask:
12446 : 24 : case CODE_FOR_avx512vl_getmantv4df_mask:
12447 : 24 : case CODE_FOR_avx512fp16_getmantv8hf_mask:
12448 : 24 : case CODE_FOR_avx512vl_getmantv4sf_mask:
12449 : 24 : case CODE_FOR_avx512vl_getmantv2df_mask:
12450 : 24 : case CODE_FOR_avx512dq_rangepv8df_mask_round:
12451 : 24 : case CODE_FOR_avx512dq_rangepv16sf_mask_round:
12452 : 24 : case CODE_FOR_avx512dq_rangepv4df_mask:
12453 : 24 : case CODE_FOR_avx512dq_rangepv8sf_mask:
12454 : 24 : case CODE_FOR_avx512dq_rangepv2df_mask:
12455 : 24 : case CODE_FOR_avx512dq_rangepv4sf_mask:
12456 : 24 : case CODE_FOR_avx_shufpd256_mask:
12457 : 24 : error ("the last argument must be a 4-bit immediate");
12458 : 24 : return const0_rtx;
12459 : :
12460 : 15 : case CODE_FOR_sha1rnds4:
12461 : 15 : case CODE_FOR_sse4_1_blendpd:
12462 : 15 : case CODE_FOR_avx_vpermilv2df:
12463 : 15 : case CODE_FOR_avx_vpermilv2df_mask:
12464 : 15 : case CODE_FOR_xop_vpermil2v2df3:
12465 : 15 : case CODE_FOR_xop_vpermil2v4sf3:
12466 : 15 : case CODE_FOR_xop_vpermil2v4df3:
12467 : 15 : case CODE_FOR_xop_vpermil2v8sf3:
12468 : 15 : case CODE_FOR_avx512f_vinsertf32x4_mask:
12469 : 15 : case CODE_FOR_avx512f_vinserti32x4_mask:
12470 : 15 : case CODE_FOR_avx512f_vextractf32x4_mask:
12471 : 15 : case CODE_FOR_avx512f_vextracti32x4_mask:
12472 : 15 : case CODE_FOR_sse2_shufpd:
12473 : 15 : case CODE_FOR_sse2_shufpd_mask:
12474 : 15 : case CODE_FOR_avx512dq_shuf_f64x2_mask:
12475 : 15 : case CODE_FOR_avx512dq_shuf_i64x2_mask:
12476 : 15 : case CODE_FOR_avx512vl_shuf_i32x4_mask:
12477 : 15 : case CODE_FOR_avx512vl_shuf_f32x4_mask:
12478 : 15 : error ("the last argument must be a 2-bit immediate");
12479 : 15 : return const0_rtx;
12480 : :
12481 : 30 : case CODE_FOR_avx_vextractf128v4df:
12482 : 30 : case CODE_FOR_avx_vextractf128v8sf:
12483 : 30 : case CODE_FOR_avx_vextractf128v8si:
12484 : 30 : case CODE_FOR_avx_vinsertf128v4df:
12485 : 30 : case CODE_FOR_avx_vinsertf128v8sf:
12486 : 30 : case CODE_FOR_avx_vinsertf128v8si:
12487 : 30 : case CODE_FOR_avx512f_vinsertf64x4_mask:
12488 : 30 : case CODE_FOR_avx512f_vinserti64x4_mask:
12489 : 30 : case CODE_FOR_avx512f_vextractf64x4_mask:
12490 : 30 : case CODE_FOR_avx512f_vextracti64x4_mask:
12491 : 30 : case CODE_FOR_avx512dq_vinsertf32x8_mask:
12492 : 30 : case CODE_FOR_avx512dq_vinserti32x8_mask:
12493 : 30 : case CODE_FOR_avx512vl_vinsertv4df:
12494 : 30 : case CODE_FOR_avx512vl_vinsertv4di:
12495 : 30 : case CODE_FOR_avx512vl_vinsertv8sf:
12496 : 30 : case CODE_FOR_avx512vl_vinsertv8si:
12497 : 30 : error ("the last argument must be a 1-bit immediate");
12498 : 30 : return const0_rtx;
12499 : :
12500 : 16 : case CODE_FOR_avx_vmcmpv2df3:
12501 : 16 : case CODE_FOR_avx_vmcmpv4sf3:
12502 : 16 : case CODE_FOR_avx_cmpv2df3:
12503 : 16 : case CODE_FOR_avx_cmpv4sf3:
12504 : 16 : if (CONST_INT_P (op) && IN_RANGE (INTVAL (op), 8, 31))
12505 : : {
12506 : 4 : error ("'%s' needs isa option %s", d->name, "-mavx");
12507 : 4 : return const0_rtx;
12508 : : }
12509 : : /* FALLTHRU */
12510 : 18 : case CODE_FOR_avx_cmpv4df3:
12511 : 18 : case CODE_FOR_avx_cmpv8sf3:
12512 : 18 : case CODE_FOR_avx512f_cmpv8df3_mask:
12513 : 18 : case CODE_FOR_avx512f_cmpv16sf3_mask:
12514 : 18 : case CODE_FOR_avx512f_vmcmpv2df3_mask:
12515 : 18 : case CODE_FOR_avx512f_vmcmpv4sf3_mask:
12516 : 18 : case CODE_FOR_avx512bw_cmpv32hf3_mask:
12517 : 18 : case CODE_FOR_avx512vl_cmpv16hf3_mask:
12518 : 18 : case CODE_FOR_avx512fp16_cmpv8hf3_mask:
12519 : 18 : error ("the last argument must be a 5-bit immediate");
12520 : 18 : return const0_rtx;
12521 : :
12522 : 132 : default:
12523 : 132 : switch (nargs_constant)
12524 : : {
12525 : 8 : case 2:
12526 : 8 : if ((mask_pos && (nargs - i - mask_pos) == nargs_constant) ||
12527 : 8 : (!mask_pos && (nargs - i) == nargs_constant))
12528 : : {
12529 : 4 : error ("the next to last argument must be an 8-bit immediate");
12530 : 4 : break;
12531 : : }
12532 : : /* FALLTHRU */
12533 : 128 : case 1:
12534 : 128 : error ("the last argument must be an 8-bit immediate");
12535 : 128 : break;
12536 : 0 : default:
12537 : 0 : gcc_unreachable ();
12538 : : }
12539 : 132 : return const0_rtx;
12540 : : }
12541 : : }
12542 : : else
12543 : : {
12544 : 175624 : if (VECTOR_MODE_P (mode))
12545 : 126109 : op = safe_vector_operand (op, mode);
12546 : :
12547 : : /* If we aren't optimizing, only allow one memory operand to
12548 : : be generated. */
12549 : 175624 : if (memory_operand (op, mode))
12550 : : {
12551 : 29821 : num_memory++;
12552 : 29821 : if (!optimize && num_memory > 1)
12553 : 13663 : op = copy_to_mode_reg (mode, op);
12554 : : }
12555 : :
12556 : 175624 : if (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)
12557 : : {
12558 : 173329 : if (!match)
12559 : 40648 : op = copy_to_mode_reg (mode, op);
12560 : : }
12561 : : else
12562 : : {
12563 : 2295 : op = copy_to_reg (op);
12564 : 2295 : op = lowpart_subreg (mode, op, GET_MODE (op));
12565 : : }
12566 : : }
12567 : :
12568 : 194287 : xops[i] = op;
12569 : : }
12570 : :
12571 : 57998 : switch (nargs)
12572 : : {
12573 : 3115 : case 1:
12574 : 3115 : pat = GEN_FCN (icode) (real_target, xops[0]);
12575 : 3115 : break;
12576 : 5616 : case 2:
12577 : 5616 : pat = GEN_FCN (icode) (real_target, xops[0], xops[1]);
12578 : 5616 : break;
12579 : 20071 : case 3:
12580 : 20071 : pat = GEN_FCN (icode) (real_target, xops[0], xops[1], xops[2]);
12581 : 20071 : break;
12582 : 26624 : case 4:
12583 : 26624 : pat = GEN_FCN (icode) (real_target, xops[0], xops[1],
12584 : 26624 : xops[2], xops[3]);
12585 : 26624 : break;
12586 : 2572 : case 5:
12587 : 2572 : pat = GEN_FCN (icode) (real_target, xops[0], xops[1],
12588 : 2572 : xops[2], xops[3], xops[4]);
12589 : 2572 : break;
12590 : : case 6:
12591 : : pat = GEN_FCN (icode) (real_target, xops[0], xops[1],
12592 : : xops[2], xops[3], xops[4], xops[5]);
12593 : : break;
12594 : : default:
12595 : : gcc_unreachable ();
12596 : : }
12597 : :
12598 : 57998 : if (! pat)
12599 : : return 0;
12600 : :
12601 : 57998 : emit_insn (pat);
12602 : 57998 : return target;
12603 : : }
12604 : :
12605 : : /* Transform pattern of following layout:
12606 : : (set A
12607 : : (unspec [B C] UNSPEC_EMBEDDED_ROUNDING))
12608 : : )
12609 : : into:
12610 : : (set (A B)) */
12611 : :
12612 : : static rtx
12613 : 4784 : ix86_erase_embedded_rounding (rtx pat)
12614 : : {
12615 : 4784 : if (GET_CODE (pat) == INSN)
12616 : 748 : pat = PATTERN (pat);
12617 : :
12618 : 4784 : gcc_assert (GET_CODE (pat) == SET);
12619 : 4784 : rtx src = SET_SRC (pat);
12620 : 4784 : gcc_assert (XVECLEN (src, 0) == 2);
12621 : 4784 : rtx p0 = XVECEXP (src, 0, 0);
12622 : 4784 : gcc_assert (GET_CODE (src) == UNSPEC
12623 : : && XINT (src, 1) == UNSPEC_EMBEDDED_ROUNDING);
12624 : 4784 : rtx res = gen_rtx_SET (SET_DEST (pat), p0);
12625 : 4784 : return res;
12626 : : }
12627 : :
12628 : : /* Subroutine of ix86_expand_round_builtin to take care of comi insns
12629 : : with rounding. */
12630 : : static rtx
12631 : 97 : ix86_expand_sse_comi_round (const struct builtin_description *d,
12632 : : tree exp, rtx target, bool comx_ok)
12633 : : {
12634 : 97 : rtx pat, set_dst;
12635 : 97 : tree arg0 = CALL_EXPR_ARG (exp, 0);
12636 : 97 : tree arg1 = CALL_EXPR_ARG (exp, 1);
12637 : 97 : tree arg2 = CALL_EXPR_ARG (exp, 2);
12638 : 97 : tree arg3 = CALL_EXPR_ARG (exp, 3);
12639 : 97 : rtx op0 = expand_normal (arg0);
12640 : 97 : rtx op1 = expand_normal (arg1);
12641 : 97 : rtx op2 = expand_normal (arg2);
12642 : 97 : rtx op3 = expand_normal (arg3);
12643 : 97 : enum insn_code icode = d->icode;
12644 : 97 : const struct insn_data_d *insn_p = &insn_data[icode];
12645 : 97 : machine_mode mode0 = insn_p->operand[0].mode;
12646 : 97 : machine_mode mode1 = insn_p->operand[1].mode;
12647 : :
12648 : : /* See avxintrin.h for values. */
12649 : 97 : static const enum rtx_code comparisons[32] =
12650 : : {
12651 : : EQ, LT, LE, UNORDERED, NE, UNGE, UNGT, ORDERED,
12652 : : UNEQ, UNLT, UNLE, UNORDERED, LTGT, GE, GT, ORDERED,
12653 : : EQ, LT, LE, UNORDERED, NE, UNGE, UNGT, ORDERED,
12654 : : UNEQ, UNLT, UNLE, UNORDERED, LTGT, GE, GT, ORDERED
12655 : : };
12656 : 97 : static const bool ordereds[32] =
12657 : : {
12658 : : true, true, true, false, false, false, false, true,
12659 : : false, false, false, true, true, true, true, false,
12660 : : true, true, true, false, false, false, false, true,
12661 : : false, false, false, true, true, true, true, false
12662 : : };
12663 : 97 : static const bool non_signalings[32] =
12664 : : {
12665 : : true, false, false, true, true, false, false, true,
12666 : : true, false, false, true, true, false, false, true,
12667 : : false, true, true, false, false, true, true, false,
12668 : : false, true, true, false, false, true, true, false
12669 : : };
12670 : :
12671 : 97 : if (!CONST_INT_P (op2))
12672 : : {
12673 : 0 : error ("the third argument must be comparison constant");
12674 : 0 : return const0_rtx;
12675 : : }
12676 : 97 : if (INTVAL (op2) < 0 || INTVAL (op2) >= 32)
12677 : : {
12678 : 0 : error ("incorrect comparison mode");
12679 : 0 : return const0_rtx;
12680 : : }
12681 : :
12682 : 97 : if (!insn_p->operand[2].predicate (op3, SImode))
12683 : : {
12684 : 4 : error ("incorrect rounding operand");
12685 : 4 : return const0_rtx;
12686 : : }
12687 : :
12688 : 93 : if (VECTOR_MODE_P (mode0))
12689 : 93 : op0 = safe_vector_operand (op0, mode0);
12690 : 93 : if (VECTOR_MODE_P (mode1))
12691 : 93 : op1 = safe_vector_operand (op1, mode1);
12692 : :
12693 : 93 : enum rtx_code comparison = comparisons[INTVAL (op2)];
12694 : 93 : enum rtx_code orig_comp = comparison;
12695 : 93 : bool ordered = ordereds[INTVAL (op2)];
12696 : 93 : bool non_signaling = non_signalings[INTVAL (op2)];
12697 : 93 : rtx const_val = const0_rtx;
12698 : :
12699 : 93 : bool check_unordered = false;
12700 : 93 : machine_mode mode = CCFPmode;
12701 : 93 : switch (comparison)
12702 : : {
12703 : 8 : case ORDERED:
12704 : 8 : if (!ordered)
12705 : : {
12706 : 4 : if (TARGET_AVX10_2 && comx_ok)
12707 : : {
12708 : : /* Unlike VCOMI{SH,SS,SD}, VCOMX{SH,SS,SD} will set SF
12709 : : differently. So directly return true here. */
12710 : 0 : target = gen_reg_rtx (SImode);
12711 : 0 : emit_move_insn (target, const1_rtx);
12712 : 0 : return target;
12713 : : }
12714 : : else
12715 : : {
12716 : : /* NB: Use CCSmode/NE for _CMP_TRUE_UQ/_CMP_TRUE_US. */
12717 : : if (!non_signaling)
12718 : 93 : ordered = true;
12719 : 93 : mode = CCSmode;
12720 : : }
12721 : : }
12722 : : else
12723 : : {
12724 : : /* NB: Use CCPmode/NE for _CMP_ORD_Q/_CMP_ORD_S. */
12725 : : if (non_signaling)
12726 : : ordered = false;
12727 : : mode = CCPmode;
12728 : : }
12729 : : comparison = NE;
12730 : : break;
12731 : 8 : case UNORDERED:
12732 : 8 : if (ordered)
12733 : : {
12734 : 4 : if (TARGET_AVX10_2 && comx_ok)
12735 : : {
12736 : : /* Unlike VCOMI{SH,SS,SD}, VCOMX{SH,SS,SD} will set SF
12737 : : differently. So directly return false here. */
12738 : 0 : target = gen_reg_rtx (SImode);
12739 : 0 : emit_move_insn (target, const0_rtx);
12740 : 0 : return target;
12741 : : }
12742 : : else
12743 : : {
12744 : : /* NB: Use CCSmode/EQ for _CMP_FALSE_OQ/_CMP_FALSE_OS. */
12745 : : if (non_signaling)
12746 : 93 : ordered = false;
12747 : : mode = CCSmode;
12748 : : }
12749 : : }
12750 : : else
12751 : : {
12752 : : /* NB: Use CCPmode/NE for _CMP_UNORD_Q/_CMP_UNORD_S. */
12753 : : if (!non_signaling)
12754 : 93 : ordered = true;
12755 : 93 : mode = CCPmode;
12756 : : }
12757 : : comparison = EQ;
12758 : : break;
12759 : :
12760 : 38 : case LE: /* -> GE */
12761 : 38 : case LT: /* -> GT */
12762 : 38 : case UNGE: /* -> UNLE */
12763 : 38 : case UNGT: /* -> UNLT */
12764 : 38 : std::swap (op0, op1);
12765 : 38 : comparison = swap_condition (comparison);
12766 : : /* FALLTHRU */
12767 : 64 : case GT:
12768 : 64 : case GE:
12769 : 64 : case UNEQ:
12770 : 64 : case UNLT:
12771 : 64 : case UNLE:
12772 : 64 : case LTGT:
12773 : : /* These are supported by CCFPmode. NB: Use ordered/signaling
12774 : : COMI or unordered/non-signaling UCOMI. Both set ZF, PF, CF
12775 : : with NAN operands. */
12776 : 64 : if (ordered == non_signaling)
12777 : : ordered = !ordered;
12778 : : break;
12779 : : /* NB: COMI/UCOMI will set ZF with NAN operands. Use CCZmode for
12780 : : _CMP_EQ_OQ/_CMP_EQ_OS.
12781 : : Under TARGET_AVX10_2, VCOMX/VUCOMX are always generated instead
12782 : : of COMI/UCOMI, VCOMX/VUCOMX will not set ZF with NAN. */
12783 : 7 : case EQ:
12784 : 7 : if (!TARGET_AVX10_2 || !comx_ok)
12785 : 5 : check_unordered = true;
12786 : : mode = CCZmode;
12787 : : break;
12788 : 6 : case NE:
12789 : : /* NB: COMI/UCOMI will set ZF with NAN operands. Use CCZmode for
12790 : : _CMP_NEQ_UQ/_CMP_NEQ_US.
12791 : : Under TARGET_AVX10_2, VCOMX/VUCOMX are always generated instead
12792 : : of COMI/UCOMI, VCOMX/VUCOMX will not set ZF with NAN. */
12793 : 6 : gcc_assert (!ordered);
12794 : 6 : if (!TARGET_AVX10_2 || !comx_ok)
12795 : 4 : check_unordered = true;
12796 : 6 : mode = CCZmode;
12797 : 6 : const_val = const1_rtx;
12798 : 6 : break;
12799 : 0 : default:
12800 : 0 : gcc_unreachable ();
12801 : : }
12802 : :
12803 : 93 : target = gen_reg_rtx (SImode);
12804 : 93 : emit_move_insn (target, const_val);
12805 : 93 : target = gen_rtx_SUBREG (QImode, target, 0);
12806 : :
12807 : 87 : if ((optimize && !register_operand (op0, mode0))
12808 : 180 : || !insn_p->operand[0].predicate (op0, mode0))
12809 : 6 : op0 = copy_to_mode_reg (mode0, op0);
12810 : 87 : if ((optimize && !register_operand (op1, mode1))
12811 : 180 : || !insn_p->operand[1].predicate (op1, mode1))
12812 : 6 : op1 = copy_to_mode_reg (mode1, op1);
12813 : :
12814 : : /* Generate comx instead of comi when EQ/NE to avoid NAN checks.
12815 : : Use orig_comp to exclude ORDERED/UNORDERED cases. */
12816 : 93 : if ((orig_comp == EQ || orig_comp == NE)
12817 : 13 : && TARGET_AVX10_2 && comx_ok)
12818 : : {
12819 : 4 : switch (icode)
12820 : : {
12821 : : case CODE_FOR_avx512fp16_comi_round:
12822 : 93 : icode = CODE_FOR_avx10_2_comxhf_round;
12823 : : break;
12824 : 2 : case CODE_FOR_sse_comi_round:
12825 : 2 : icode = CODE_FOR_avx10_2_comxsf_round;
12826 : 2 : break;
12827 : 2 : case CODE_FOR_sse2_comi_round:
12828 : 2 : icode = CODE_FOR_avx10_2_comxdf_round;
12829 : 2 : break;
12830 : :
12831 : : default:
12832 : : break;
12833 : : }
12834 : : }
12835 : :
12836 : : /* Generate comi instead of comx when UNEQ/LTGT to avoid NAN checks. */
12837 : 93 : if ((comparison == UNEQ || comparison == LTGT)
12838 : 8 : && TARGET_AVX10_2 && comx_ok)
12839 : : {
12840 : 0 : switch (icode)
12841 : : {
12842 : : case CODE_FOR_avx10_2_comxhf_round:
12843 : 93 : icode = CODE_FOR_avx512fp16_comi_round;
12844 : : break;
12845 : 0 : case CODE_FOR_avx10_2_comxsf_round:
12846 : 0 : icode = CODE_FOR_sse_comi_round;
12847 : 0 : break;
12848 : 0 : case CODE_FOR_avx10_2_comxdf_round:
12849 : 0 : icode = CODE_FOR_sse2_comi_round;
12850 : 0 : break;
12851 : :
12852 : : default:
12853 : : break;
12854 : : }
12855 : : }
12856 : :
12857 : : /*
12858 : : 1. COMI/VCOMX: ordered and signaling.
12859 : : 2. UCOMI/VUCOMX: unordered and non-signaling.
12860 : : */
12861 : 93 : if (non_signaling)
12862 : 36 : switch (icode)
12863 : : {
12864 : : case CODE_FOR_sse_comi_round:
12865 : : icode = CODE_FOR_sse_ucomi_round;
12866 : : break;
12867 : 17 : case CODE_FOR_sse2_comi_round:
12868 : 17 : icode = CODE_FOR_sse2_ucomi_round;
12869 : 17 : break;
12870 : 0 : case CODE_FOR_avx512fp16_comi_round:
12871 : 0 : icode = CODE_FOR_avx512fp16_ucomi_round;
12872 : 0 : break;
12873 : 1 : case CODE_FOR_avx10_2_comxsf_round:
12874 : 1 : icode = CODE_FOR_avx10_2_ucomxsf_round;
12875 : 1 : break;
12876 : 0 : case CODE_FOR_avx10_2_comxhf_round:
12877 : 0 : icode = CODE_FOR_avx10_2_ucomxhf_round;
12878 : 0 : break;
12879 : 1 : case CODE_FOR_avx10_2_comxdf_round:
12880 : 1 : icode = CODE_FOR_avx10_2_ucomxdf_round;
12881 : 1 : break;
12882 : 0 : default:
12883 : 0 : gcc_unreachable ();
12884 : : }
12885 : :
12886 : 93 : pat = GEN_FCN (icode) (op0, op1, op3);
12887 : 93 : if (! pat)
12888 : : return 0;
12889 : :
12890 : : /* Rounding operand can be either NO_ROUND or ROUND_SAE at this point. */
12891 : 93 : if (INTVAL (op3) == NO_ROUND)
12892 : : {
12893 : 1 : pat = ix86_erase_embedded_rounding (pat);
12894 : 1 : if (! pat)
12895 : : return 0;
12896 : :
12897 : 1 : set_dst = SET_DEST (pat);
12898 : : }
12899 : : else
12900 : : {
12901 : 92 : gcc_assert (GET_CODE (pat) == SET);
12902 : 92 : set_dst = SET_DEST (pat);
12903 : : }
12904 : :
12905 : 93 : emit_insn (pat);
12906 : :
12907 : 93 : return ix86_ssecom_setcc (comparison, check_unordered, mode,
12908 : 93 : set_dst, target);
12909 : : }
12910 : :
12911 : : static rtx
12912 : 15467 : ix86_expand_round_builtin (const struct builtin_description *d,
12913 : : tree exp, rtx target)
12914 : : {
12915 : 15467 : rtx pat;
12916 : 15467 : unsigned int i, nargs;
12917 : 15467 : rtx xops[6];
12918 : 15467 : enum insn_code icode = d->icode;
12919 : 15467 : const struct insn_data_d *insn_p = &insn_data[icode];
12920 : 15467 : machine_mode tmode = insn_p->operand[0].mode;
12921 : 15467 : unsigned int nargs_constant = 0;
12922 : 15467 : unsigned int redundant_embed_rnd = 0;
12923 : :
12924 : 15467 : switch ((enum ix86_builtin_func_type) d->flag)
12925 : : {
12926 : : case UINT64_FTYPE_V2DF_INT:
12927 : : case UINT64_FTYPE_V4SF_INT:
12928 : : case UINT64_FTYPE_V8HF_INT:
12929 : : case UINT_FTYPE_V2DF_INT:
12930 : : case UINT_FTYPE_V4SF_INT:
12931 : : case UINT_FTYPE_V8HF_INT:
12932 : : case INT64_FTYPE_V2DF_INT:
12933 : : case INT64_FTYPE_V4SF_INT:
12934 : : case INT64_FTYPE_V8HF_INT:
12935 : : case INT_FTYPE_V2DF_INT:
12936 : : case INT_FTYPE_V4SF_INT:
12937 : : case INT_FTYPE_V8HF_INT:
12938 : : nargs = 2;
12939 : : break;
12940 : 705 : case V32HF_FTYPE_V32HF_V32HF_INT:
12941 : 705 : case V8HF_FTYPE_V8HF_V8HF_INT:
12942 : 705 : case V8HF_FTYPE_V8HF_INT_INT:
12943 : 705 : case V8HF_FTYPE_V8HF_UINT_INT:
12944 : 705 : case V8HF_FTYPE_V8HF_INT64_INT:
12945 : 705 : case V8HF_FTYPE_V8HF_UINT64_INT:
12946 : 705 : case V4SF_FTYPE_V4SF_UINT_INT:
12947 : 705 : case V4SF_FTYPE_V4SF_UINT64_INT:
12948 : 705 : case V2DF_FTYPE_V2DF_UINT64_INT:
12949 : 705 : case V4SF_FTYPE_V4SF_INT_INT:
12950 : 705 : case V4SF_FTYPE_V4SF_INT64_INT:
12951 : 705 : case V2DF_FTYPE_V2DF_INT64_INT:
12952 : 705 : case V4SF_FTYPE_V4SF_V4SF_INT:
12953 : 705 : case V2DF_FTYPE_V2DF_V2DF_INT:
12954 : 705 : case V4SF_FTYPE_V4SF_V2DF_INT:
12955 : 705 : case V2DF_FTYPE_V2DF_V4SF_INT:
12956 : 705 : nargs = 3;
12957 : 705 : break;
12958 : 4506 : case V8SF_FTYPE_V8DF_V8SF_QI_INT:
12959 : 4506 : case V8DF_FTYPE_V8DF_V8DF_QI_INT:
12960 : 4506 : case V32HI_FTYPE_V32HF_V32HI_USI_INT:
12961 : 4506 : case V32HI_FTYPE_V32BF_V32HI_USI_INT:
12962 : 4506 : case V8SI_FTYPE_V8DF_V8SI_QI_INT:
12963 : 4506 : case V8DI_FTYPE_V8HF_V8DI_UQI_INT:
12964 : 4506 : case V8DI_FTYPE_V8DF_V8DI_QI_INT:
12965 : 4506 : case V8SF_FTYPE_V8DI_V8SF_QI_INT:
12966 : 4506 : case V8DF_FTYPE_V8DI_V8DF_QI_INT:
12967 : 4506 : case V8DF_FTYPE_V8HF_V8DF_UQI_INT:
12968 : 4506 : case V16SF_FTYPE_V16HF_V16SF_UHI_INT:
12969 : 4506 : case V32HF_FTYPE_V32HI_V32HF_USI_INT:
12970 : 4506 : case V32HF_FTYPE_V32HF_V32HF_USI_INT:
12971 : 4506 : case V32HF_FTYPE_V32HF_V32HF_V32HF_INT:
12972 : 4506 : case V16SF_FTYPE_V16SF_V16SF_HI_INT:
12973 : 4506 : case V8DI_FTYPE_V8SF_V8DI_QI_INT:
12974 : 4506 : case V16SF_FTYPE_V16SI_V16SF_HI_INT:
12975 : 4506 : case V16SI_FTYPE_V16SF_V16SI_HI_INT:
12976 : 4506 : case V16SI_FTYPE_V16SF_V16SI_UHI_INT:
12977 : 4506 : case V16SI_FTYPE_V16HF_V16SI_UHI_INT:
12978 : 4506 : case V16HF_FTYPE_V16SI_V16HF_UHI_INT:
12979 : 4506 : case V8DF_FTYPE_V8SF_V8DF_QI_INT:
12980 : 4506 : case V16SF_FTYPE_V16HI_V16SF_HI_INT:
12981 : 4506 : case V2DF_FTYPE_V2DF_V2DF_V2DF_INT:
12982 : 4506 : case V4SF_FTYPE_V4SF_V4SF_V4SF_INT:
12983 : 4506 : case V8HF_FTYPE_V8DI_V8HF_UQI_INT:
12984 : 4506 : case V8HF_FTYPE_V8DF_V8HF_UQI_INT:
12985 : 4506 : case V16HF_FTYPE_V16SF_V16HF_UHI_INT:
12986 : 4506 : case V16HI_FTYPE_V16BF_V16HI_UHI_INT:
12987 : 4506 : case V8HF_FTYPE_V8HF_V8HF_V8HF_INT:
12988 : 4506 : nargs = 4;
12989 : 4506 : break;
12990 : 234 : case V4SF_FTYPE_V4SF_V4SF_INT_INT:
12991 : 234 : case V2DF_FTYPE_V2DF_V2DF_INT_INT:
12992 : 234 : nargs_constant = 2;
12993 : 234 : nargs = 4;
12994 : 234 : break;
12995 : 97 : case INT_FTYPE_V4SF_V4SF_INT_INT:
12996 : 97 : case INT_FTYPE_V2DF_V2DF_INT_INT:
12997 : 97 : return ix86_expand_sse_comi_round (d, exp, target, true);
12998 : 6189 : case V8DF_FTYPE_V8DF_V8DF_V8DF_UQI_INT:
12999 : 6189 : case V2DF_FTYPE_V2DF_V2DF_V2DF_UQI_INT:
13000 : 6189 : case V4SF_FTYPE_V4SF_V4SF_V4SF_UQI_INT:
13001 : 6189 : case V4SF_FTYPE_V8HF_V4SF_V4SF_UQI_INT:
13002 : 6189 : case V16SF_FTYPE_V16SF_V16SF_V16SF_HI_INT:
13003 : 6189 : case V32HF_FTYPE_V32HF_V32HF_V32HF_UHI_INT:
13004 : 6189 : case V32HF_FTYPE_V32HF_V32HF_V32HF_USI_INT:
13005 : 6189 : case V2DF_FTYPE_V8HF_V2DF_V2DF_UQI_INT:
13006 : 6189 : case V2DF_FTYPE_V2DF_V2DF_V2DF_QI_INT:
13007 : 6189 : case V2DF_FTYPE_V2DF_V4SF_V2DF_QI_INT:
13008 : 6189 : case V2DF_FTYPE_V2DF_V4SF_V2DF_UQI_INT:
13009 : 6189 : case V4SF_FTYPE_V4SF_V4SF_V4SF_QI_INT:
13010 : 6189 : case V4SF_FTYPE_V4SF_V2DF_V4SF_QI_INT:
13011 : 6189 : case V4SF_FTYPE_V4SF_V2DF_V4SF_UQI_INT:
13012 : 6189 : case V8HF_FTYPE_V8HF_V8HF_V8HF_UQI_INT:
13013 : 6189 : case V8HF_FTYPE_V2DF_V8HF_V8HF_UQI_INT:
13014 : 6189 : case V8HF_FTYPE_V4SF_V8HF_V8HF_UQI_INT:
13015 : 6189 : case V32HF_FTYPE_V16SF_V16SF_V32HF_USI_INT:
13016 : 6189 : nargs = 5;
13017 : 6189 : break;
13018 : 635 : case V32HF_FTYPE_V32HF_INT_V32HF_USI_INT:
13019 : 635 : case V16SF_FTYPE_V16SF_INT_V16SF_HI_INT:
13020 : 635 : case V8DF_FTYPE_V8DF_INT_V8DF_QI_INT:
13021 : 635 : case V8DF_FTYPE_V8DF_INT_V8DF_UQI_INT:
13022 : 635 : case V16SF_FTYPE_V16SF_INT_V16SF_UHI_INT:
13023 : 635 : nargs_constant = 4;
13024 : 635 : nargs = 5;
13025 : 635 : break;
13026 : 1181 : case UQI_FTYPE_V8DF_V8DF_INT_UQI_INT:
13027 : 1181 : case UQI_FTYPE_V2DF_V2DF_INT_UQI_INT:
13028 : 1181 : case UHI_FTYPE_V16SF_V16SF_INT_UHI_INT:
13029 : 1181 : case UQI_FTYPE_V4SF_V4SF_INT_UQI_INT:
13030 : 1181 : case USI_FTYPE_V32HF_V32HF_INT_USI_INT:
13031 : 1181 : case UQI_FTYPE_V8HF_V8HF_INT_UQI_INT:
13032 : 1181 : nargs_constant = 3;
13033 : 1181 : nargs = 5;
13034 : 1181 : break;
13035 : 963 : case V16SF_FTYPE_V16SF_V16SF_INT_V16SF_HI_INT:
13036 : 963 : case V8DF_FTYPE_V8DF_V8DF_INT_V8DF_QI_INT:
13037 : 963 : case V4SF_FTYPE_V4SF_V4SF_INT_V4SF_QI_INT:
13038 : 963 : case V2DF_FTYPE_V2DF_V2DF_INT_V2DF_QI_INT:
13039 : 963 : case V2DF_FTYPE_V2DF_V2DF_INT_V2DF_UQI_INT:
13040 : 963 : case V4SF_FTYPE_V4SF_V4SF_INT_V4SF_UQI_INT:
13041 : 963 : case V8HF_FTYPE_V8HF_V8HF_INT_V8HF_UQI_INT:
13042 : 963 : case V8DF_FTYPE_V8DF_V8DF_INT_V8DF_UQI_INT:
13043 : 963 : case V32HF_FTYPE_V32HF_V32HF_INT_V32HF_USI_INT:
13044 : 963 : case V16SF_FTYPE_V16SF_V16SF_INT_V16SF_UHI_INT:
13045 : 963 : nargs = 6;
13046 : 963 : nargs_constant = 4;
13047 : 963 : break;
13048 : 252 : case V8DF_FTYPE_V8DF_V8DF_V8DI_INT_QI_INT:
13049 : 252 : case V16SF_FTYPE_V16SF_V16SF_V16SI_INT_HI_INT:
13050 : 252 : case V2DF_FTYPE_V2DF_V2DF_V2DI_INT_QI_INT:
13051 : 252 : case V4SF_FTYPE_V4SF_V4SF_V4SI_INT_QI_INT:
13052 : 252 : nargs = 6;
13053 : 252 : nargs_constant = 3;
13054 : 252 : break;
13055 : 0 : default:
13056 : 0 : gcc_unreachable ();
13057 : : }
13058 : 14665 : gcc_assert (nargs <= ARRAY_SIZE (xops));
13059 : :
13060 : 15370 : if (optimize
13061 : 4261 : || target == 0
13062 : 4261 : || GET_MODE (target) != tmode
13063 : 19631 : || !insn_p->operand[0].predicate (target, tmode))
13064 : 11109 : target = gen_reg_rtx (tmode);
13065 : :
13066 : 84519 : for (i = 0; i < nargs; i++)
13067 : : {
13068 : 69704 : tree arg = CALL_EXPR_ARG (exp, i);
13069 : 69704 : rtx op = ix86_expand_unsigned_small_int_cst_argument (arg);
13070 : 69704 : machine_mode mode = insn_p->operand[i + 1].mode;
13071 : 69704 : bool match = insn_p->operand[i + 1].predicate (op, mode);
13072 : :
13073 : 69704 : if (i == nargs - nargs_constant)
13074 : : {
13075 : 3265 : if (!match)
13076 : : {
13077 : 40 : switch (icode)
13078 : : {
13079 : 12 : case CODE_FOR_avx512f_getmantv8df_mask_round:
13080 : 12 : case CODE_FOR_avx512f_getmantv16sf_mask_round:
13081 : 12 : case CODE_FOR_avx512bw_getmantv32hf_mask_round:
13082 : 12 : case CODE_FOR_avx512f_vgetmantv2df_round:
13083 : 12 : case CODE_FOR_avx512f_vgetmantv2df_mask_round:
13084 : 12 : case CODE_FOR_avx512f_vgetmantv4sf_round:
13085 : 12 : case CODE_FOR_avx512f_vgetmantv4sf_mask_round:
13086 : 12 : case CODE_FOR_avx512f_vgetmantv8hf_mask_round:
13087 : 12 : error ("the immediate argument must be a 4-bit immediate");
13088 : 12 : return const0_rtx;
13089 : 8 : case CODE_FOR_avx512f_cmpv8df3_mask_round:
13090 : 8 : case CODE_FOR_avx512f_cmpv16sf3_mask_round:
13091 : 8 : case CODE_FOR_avx512f_vmcmpv2df3_mask_round:
13092 : 8 : case CODE_FOR_avx512f_vmcmpv4sf3_mask_round:
13093 : 8 : case CODE_FOR_avx512f_vmcmpv8hf3_mask_round:
13094 : 8 : case CODE_FOR_avx512bw_cmpv32hf3_mask_round:
13095 : 8 : error ("the immediate argument must be a 5-bit immediate");
13096 : 8 : return const0_rtx;
13097 : 20 : default:
13098 : 20 : error ("the immediate argument must be an 8-bit immediate");
13099 : 20 : return const0_rtx;
13100 : : }
13101 : : }
13102 : : }
13103 : 66439 : else if (i == nargs-1)
13104 : : {
13105 : 15330 : if (!insn_p->operand[nargs].predicate (op, SImode))
13106 : : {
13107 : 515 : error ("incorrect rounding operand");
13108 : 515 : return const0_rtx;
13109 : : }
13110 : :
13111 : : /* If there is no rounding use normal version of the pattern. */
13112 : 14815 : if (INTVAL (op) == NO_ROUND)
13113 : : {
13114 : : /* Skip erasing embedded rounding for below expanders who
13115 : : generates multiple insns. In ix86_erase_embedded_rounding
13116 : : the pattern will be transformed to a single set, and emit_insn
13117 : : appends the set instead of insert it to chain. So the insns
13118 : : emitted inside define_expander would be ignored. */
13119 : 4815 : switch (icode)
13120 : : {
13121 : : case CODE_FOR_avx512bw_fmaddc_v32hf_mask1_round:
13122 : : case CODE_FOR_avx512bw_fcmaddc_v32hf_mask1_round:
13123 : : case CODE_FOR_avx512fp16_fmaddcsh_v8hf_mask1_round:
13124 : : case CODE_FOR_avx512fp16_fcmaddcsh_v8hf_mask1_round:
13125 : : case CODE_FOR_avx512fp16_fmaddcsh_v8hf_mask3_round:
13126 : : case CODE_FOR_avx512fp16_fcmaddcsh_v8hf_mask3_round:
13127 : : redundant_embed_rnd = 0;
13128 : : break;
13129 : 4783 : default:
13130 : 4783 : redundant_embed_rnd = 1;
13131 : 4783 : break;
13132 : : }
13133 : : }
13134 : : }
13135 : : else
13136 : : {
13137 : 51109 : if (VECTOR_MODE_P (mode))
13138 : 37392 : op = safe_vector_operand (op, mode);
13139 : :
13140 : 51109 : op = fixup_modeless_constant (op, mode);
13141 : :
13142 : 51109 : if (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)
13143 : : {
13144 : 51109 : if (optimize || !match)
13145 : 44781 : op = copy_to_mode_reg (mode, op);
13146 : : }
13147 : : else
13148 : : {
13149 : 0 : op = copy_to_reg (op);
13150 : 0 : op = lowpart_subreg (mode, op, GET_MODE (op));
13151 : : }
13152 : : }
13153 : :
13154 : 69149 : xops[i] = op;
13155 : : }
13156 : :
13157 : 14815 : switch (nargs)
13158 : : {
13159 : : case 1:
13160 : : pat = GEN_FCN (icode) (target, xops[0]);
13161 : : break;
13162 : 672 : case 2:
13163 : 672 : pat = GEN_FCN (icode) (target, xops[0], xops[1]);
13164 : 672 : break;
13165 : 661 : case 3:
13166 : 661 : pat = GEN_FCN (icode) (target, xops[0], xops[1], xops[2]);
13167 : 661 : break;
13168 : 4616 : case 4:
13169 : 4616 : pat = GEN_FCN (icode) (target, xops[0], xops[1],
13170 : 4616 : xops[2], xops[3]);
13171 : 4616 : break;
13172 : 7701 : case 5:
13173 : 7701 : pat = GEN_FCN (icode) (target, xops[0], xops[1],
13174 : 7701 : xops[2], xops[3], xops[4]);
13175 : 7701 : break;
13176 : 1165 : case 6:
13177 : 1165 : pat = GEN_FCN (icode) (target, xops[0], xops[1],
13178 : 1165 : xops[2], xops[3], xops[4], xops[5]);
13179 : 1165 : break;
13180 : : default:
13181 : : gcc_unreachable ();
13182 : : }
13183 : :
13184 : 14815 : if (!pat)
13185 : : return 0;
13186 : :
13187 : 14815 : if (redundant_embed_rnd)
13188 : 4783 : pat = ix86_erase_embedded_rounding (pat);
13189 : :
13190 : 14815 : emit_insn (pat);
13191 : 14815 : return target;
13192 : : }
13193 : :
13194 : : /* Subroutine of ix86_expand_builtin to take care of special insns
13195 : : with variable number of operands. */
13196 : :
13197 : : static rtx
13198 : 27352 : ix86_expand_special_args_builtin (const struct builtin_description *d,
13199 : : tree exp, rtx target)
13200 : : {
13201 : 27352 : tree arg;
13202 : 27352 : rtx pat, op;
13203 : 27352 : unsigned int i, nargs, arg_adjust, memory;
13204 : 27352 : unsigned int constant = 100;
13205 : 27352 : bool aligned_mem = false;
13206 : 27352 : rtx xops[4];
13207 : 27352 : enum insn_code icode = d->icode;
13208 : 27352 : const struct insn_data_d *insn_p = &insn_data[icode];
13209 : 27352 : machine_mode tmode = insn_p->operand[0].mode;
13210 : 27352 : enum { load, store } klass;
13211 : :
13212 : 27352 : switch ((enum ix86_builtin_func_type) d->flag)
13213 : : {
13214 : 15545 : case VOID_FTYPE_VOID:
13215 : 15545 : emit_insn (GEN_FCN (icode) (target));
13216 : 15545 : return 0;
13217 : : case VOID_FTYPE_UINT64:
13218 : : case VOID_FTYPE_UNSIGNED:
13219 : : nargs = 0;
13220 : : klass = store;
13221 : : memory = 0;
13222 : : break;
13223 : :
13224 : 7581 : case INT_FTYPE_VOID:
13225 : 7581 : case USHORT_FTYPE_VOID:
13226 : 7581 : case UINT64_FTYPE_VOID:
13227 : 7581 : case UINT_FTYPE_VOID:
13228 : 7581 : case UINT8_FTYPE_VOID:
13229 : 7581 : case UNSIGNED_FTYPE_VOID:
13230 : 7581 : nargs = 0;
13231 : 7581 : klass = load;
13232 : 7581 : memory = 0;
13233 : 7581 : break;
13234 : 358 : case CHAR_FTYPE_PCCHAR:
13235 : 358 : case SHORT_FTYPE_PCSHORT:
13236 : 358 : case INT_FTYPE_PCINT:
13237 : 358 : case INT64_FTYPE_PCINT64:
13238 : 358 : case UINT64_FTYPE_PUNSIGNED:
13239 : 358 : case V2DI_FTYPE_PV2DI:
13240 : 358 : case V4DI_FTYPE_PV4DI:
13241 : 358 : case V32QI_FTYPE_PCCHAR:
13242 : 358 : case V16QI_FTYPE_PCCHAR:
13243 : 358 : case V8SF_FTYPE_PCV4SF:
13244 : 358 : case V8SF_FTYPE_PCFLOAT:
13245 : 358 : case V4SF_FTYPE_PCFLOAT:
13246 : 358 : case V4SF_FTYPE_PCFLOAT16:
13247 : 358 : case V4SF_FTYPE_PCBFLOAT16:
13248 : 358 : case V4SF_FTYPE_PCV8BF:
13249 : 358 : case V4SF_FTYPE_PCV8HF:
13250 : 358 : case V8SF_FTYPE_PCFLOAT16:
13251 : 358 : case V8SF_FTYPE_PCBFLOAT16:
13252 : 358 : case V8SF_FTYPE_PCV16HF:
13253 : 358 : case V8SF_FTYPE_PCV16BF:
13254 : 358 : case V4DF_FTYPE_PCV2DF:
13255 : 358 : case V4DF_FTYPE_PCDOUBLE:
13256 : 358 : case V2DF_FTYPE_PCDOUBLE:
13257 : 358 : case VOID_FTYPE_PVOID:
13258 : 358 : case V8DI_FTYPE_PV8DI:
13259 : 358 : nargs = 1;
13260 : 358 : klass = load;
13261 : 358 : memory = 0;
13262 : 358 : switch (icode)
13263 : : {
13264 : : case CODE_FOR_sse4_1_movntdqa:
13265 : : case CODE_FOR_avx2_movntdqa:
13266 : : case CODE_FOR_avx512f_movntdqa:
13267 : : aligned_mem = true;
13268 : : break;
13269 : : default:
13270 : : break;
13271 : : }
13272 : : break;
13273 : 371 : case VOID_FTYPE_PV2SF_V4SF:
13274 : 371 : case VOID_FTYPE_PV8DI_V8DI:
13275 : 371 : case VOID_FTYPE_PV4DI_V4DI:
13276 : 371 : case VOID_FTYPE_PV2DI_V2DI:
13277 : 371 : case VOID_FTYPE_PCHAR_V32QI:
13278 : 371 : case VOID_FTYPE_PCHAR_V16QI:
13279 : 371 : case VOID_FTYPE_PFLOAT_V16SF:
13280 : 371 : case VOID_FTYPE_PFLOAT_V8SF:
13281 : 371 : case VOID_FTYPE_PFLOAT_V4SF:
13282 : 371 : case VOID_FTYPE_PDOUBLE_V8DF:
13283 : 371 : case VOID_FTYPE_PDOUBLE_V4DF:
13284 : 371 : case VOID_FTYPE_PDOUBLE_V2DF:
13285 : 371 : case VOID_FTYPE_PLONGLONG_LONGLONG:
13286 : 371 : case VOID_FTYPE_PULONGLONG_ULONGLONG:
13287 : 371 : case VOID_FTYPE_PUNSIGNED_UNSIGNED:
13288 : 371 : case VOID_FTYPE_PINT_INT:
13289 : 371 : nargs = 1;
13290 : 371 : klass = store;
13291 : : /* Reserve memory operand for target. */
13292 : 371 : memory = ARRAY_SIZE (xops);
13293 : 371 : switch (icode)
13294 : : {
13295 : : /* These builtins and instructions require the memory
13296 : : to be properly aligned. */
13297 : : case CODE_FOR_avx_movntv4di:
13298 : : case CODE_FOR_sse2_movntv2di:
13299 : : case CODE_FOR_avx_movntv8sf:
13300 : : case CODE_FOR_sse_movntv4sf:
13301 : : case CODE_FOR_sse4a_vmmovntv4sf:
13302 : : case CODE_FOR_avx_movntv4df:
13303 : : case CODE_FOR_sse2_movntv2df:
13304 : : case CODE_FOR_sse4a_vmmovntv2df:
13305 : : case CODE_FOR_sse2_movntidi:
13306 : : case CODE_FOR_sse_movntq:
13307 : : case CODE_FOR_sse2_movntisi:
13308 : : case CODE_FOR_avx512f_movntv16sf:
13309 : : case CODE_FOR_avx512f_movntv8df:
13310 : : case CODE_FOR_avx512f_movntv8di:
13311 : : aligned_mem = true;
13312 : : break;
13313 : : default:
13314 : : break;
13315 : : }
13316 : : break;
13317 : 0 : case VOID_FTYPE_PVOID_PCVOID:
13318 : 0 : nargs = 1;
13319 : 0 : klass = store;
13320 : 0 : memory = 0;
13321 : :
13322 : 0 : break;
13323 : 26 : case V4SF_FTYPE_V4SF_PCV2SF:
13324 : 26 : case V2DF_FTYPE_V2DF_PCDOUBLE:
13325 : 26 : nargs = 2;
13326 : 26 : klass = load;
13327 : 26 : memory = 1;
13328 : 26 : break;
13329 : 93 : case V8SF_FTYPE_PCV8SF_V8SI:
13330 : 93 : case V4DF_FTYPE_PCV4DF_V4DI:
13331 : 93 : case V4SF_FTYPE_PCV4SF_V4SI:
13332 : 93 : case V2DF_FTYPE_PCV2DF_V2DI:
13333 : 93 : case V8SI_FTYPE_PCV8SI_V8SI:
13334 : 93 : case V4DI_FTYPE_PCV4DI_V4DI:
13335 : 93 : case V4SI_FTYPE_PCV4SI_V4SI:
13336 : 93 : case V2DI_FTYPE_PCV2DI_V2DI:
13337 : 93 : case VOID_FTYPE_INT_INT64:
13338 : 93 : nargs = 2;
13339 : 93 : klass = load;
13340 : 93 : memory = 0;
13341 : 93 : break;
13342 : 360 : case VOID_FTYPE_PV8DF_V8DF_UQI:
13343 : 360 : case VOID_FTYPE_PV4DF_V4DF_UQI:
13344 : 360 : case VOID_FTYPE_PV2DF_V2DF_UQI:
13345 : 360 : case VOID_FTYPE_PV16SF_V16SF_UHI:
13346 : 360 : case VOID_FTYPE_PV8SF_V8SF_UQI:
13347 : 360 : case VOID_FTYPE_PV4SF_V4SF_UQI:
13348 : 360 : case VOID_FTYPE_PV8DI_V8DI_UQI:
13349 : 360 : case VOID_FTYPE_PV4DI_V4DI_UQI:
13350 : 360 : case VOID_FTYPE_PV2DI_V2DI_UQI:
13351 : 360 : case VOID_FTYPE_PV16SI_V16SI_UHI:
13352 : 360 : case VOID_FTYPE_PV8SI_V8SI_UQI:
13353 : 360 : case VOID_FTYPE_PV4SI_V4SI_UQI:
13354 : 360 : case VOID_FTYPE_PV64QI_V64QI_UDI:
13355 : 360 : case VOID_FTYPE_PV32HI_V32HI_USI:
13356 : 360 : case VOID_FTYPE_PV32QI_V32QI_USI:
13357 : 360 : case VOID_FTYPE_PV16QI_V16QI_UHI:
13358 : 360 : case VOID_FTYPE_PV16HI_V16HI_UHI:
13359 : 360 : case VOID_FTYPE_PV8HI_V8HI_UQI:
13360 : 360 : switch (icode)
13361 : : {
13362 : : /* These builtins and instructions require the memory
13363 : : to be properly aligned. */
13364 : : case CODE_FOR_avx512f_storev16sf_mask:
13365 : : case CODE_FOR_avx512f_storev16si_mask:
13366 : : case CODE_FOR_avx512f_storev8df_mask:
13367 : : case CODE_FOR_avx512f_storev8di_mask:
13368 : : case CODE_FOR_avx512vl_storev8sf_mask:
13369 : : case CODE_FOR_avx512vl_storev8si_mask:
13370 : : case CODE_FOR_avx512vl_storev4df_mask:
13371 : : case CODE_FOR_avx512vl_storev4di_mask:
13372 : : case CODE_FOR_avx512vl_storev4sf_mask:
13373 : : case CODE_FOR_avx512vl_storev4si_mask:
13374 : : case CODE_FOR_avx512vl_storev2df_mask:
13375 : : case CODE_FOR_avx512vl_storev2di_mask:
13376 : 11807 : aligned_mem = true;
13377 : : break;
13378 : : default:
13379 : : break;
13380 : : }
13381 : : /* FALLTHRU */
13382 : : case VOID_FTYPE_PV8SF_V8SI_V8SF:
13383 : : case VOID_FTYPE_PV4DF_V4DI_V4DF:
13384 : : case VOID_FTYPE_PV4SF_V4SI_V4SF:
13385 : : case VOID_FTYPE_PV2DF_V2DI_V2DF:
13386 : : case VOID_FTYPE_PV8SI_V8SI_V8SI:
13387 : : case VOID_FTYPE_PV4DI_V4DI_V4DI:
13388 : : case VOID_FTYPE_PV4SI_V4SI_V4SI:
13389 : : case VOID_FTYPE_PV2DI_V2DI_V2DI:
13390 : : case VOID_FTYPE_PV8SI_V8DI_UQI:
13391 : : case VOID_FTYPE_PV8HI_V8DI_UQI:
13392 : : case VOID_FTYPE_PV16HI_V16SI_UHI:
13393 : : case VOID_FTYPE_PUDI_V8DI_UQI:
13394 : : case VOID_FTYPE_PV16QI_V16SI_UHI:
13395 : : case VOID_FTYPE_PV4SI_V4DI_UQI:
13396 : : case VOID_FTYPE_PUDI_V2DI_UQI:
13397 : : case VOID_FTYPE_PUDI_V4DI_UQI:
13398 : : case VOID_FTYPE_PUSI_V2DI_UQI:
13399 : : case VOID_FTYPE_PV8HI_V8SI_UQI:
13400 : : case VOID_FTYPE_PUDI_V4SI_UQI:
13401 : : case VOID_FTYPE_PUSI_V4DI_UQI:
13402 : : case VOID_FTYPE_PUHI_V2DI_UQI:
13403 : : case VOID_FTYPE_PUDI_V8SI_UQI:
13404 : : case VOID_FTYPE_PUSI_V4SI_UQI:
13405 : : case VOID_FTYPE_PCHAR_V64QI_UDI:
13406 : : case VOID_FTYPE_PCHAR_V32QI_USI:
13407 : : case VOID_FTYPE_PCHAR_V16QI_UHI:
13408 : : case VOID_FTYPE_PSHORT_V32HI_USI:
13409 : : case VOID_FTYPE_PSHORT_V16HI_UHI:
13410 : : case VOID_FTYPE_PSHORT_V8HI_UQI:
13411 : : case VOID_FTYPE_PINT_V16SI_UHI:
13412 : : case VOID_FTYPE_PINT_V8SI_UQI:
13413 : : case VOID_FTYPE_PINT_V4SI_UQI:
13414 : : case VOID_FTYPE_PINT64_V8DI_UQI:
13415 : : case VOID_FTYPE_PINT64_V4DI_UQI:
13416 : : case VOID_FTYPE_PINT64_V2DI_UQI:
13417 : : case VOID_FTYPE_PDOUBLE_V8DF_UQI:
13418 : : case VOID_FTYPE_PDOUBLE_V4DF_UQI:
13419 : : case VOID_FTYPE_PDOUBLE_V2DF_UQI:
13420 : : case VOID_FTYPE_PFLOAT_V16SF_UHI:
13421 : : case VOID_FTYPE_PFLOAT_V8SF_UQI:
13422 : : case VOID_FTYPE_PFLOAT_V4SF_UQI:
13423 : : case VOID_FTYPE_PCFLOAT16_V8HF_UQI:
13424 : : case VOID_FTYPE_PV32QI_V32HI_USI:
13425 : : case VOID_FTYPE_PV16QI_V16HI_UHI:
13426 : : case VOID_FTYPE_PUDI_V8HI_UQI:
13427 : : nargs = 2;
13428 : : klass = store;
13429 : : /* Reserve memory operand for target. */
13430 : : memory = ARRAY_SIZE (xops);
13431 : : break;
13432 : 1243 : case V4SF_FTYPE_PCV4SF_V4SF_UQI:
13433 : 1243 : case V8SF_FTYPE_PCV8SF_V8SF_UQI:
13434 : 1243 : case V16SF_FTYPE_PCV16SF_V16SF_UHI:
13435 : 1243 : case V4SI_FTYPE_PCV4SI_V4SI_UQI:
13436 : 1243 : case V8SI_FTYPE_PCV8SI_V8SI_UQI:
13437 : 1243 : case V16SI_FTYPE_PCV16SI_V16SI_UHI:
13438 : 1243 : case V2DF_FTYPE_PCV2DF_V2DF_UQI:
13439 : 1243 : case V4DF_FTYPE_PCV4DF_V4DF_UQI:
13440 : 1243 : case V8DF_FTYPE_PCV8DF_V8DF_UQI:
13441 : 1243 : case V2DI_FTYPE_PCV2DI_V2DI_UQI:
13442 : 1243 : case V4DI_FTYPE_PCV4DI_V4DI_UQI:
13443 : 1243 : case V8DI_FTYPE_PCV8DI_V8DI_UQI:
13444 : 1243 : case V64QI_FTYPE_PCV64QI_V64QI_UDI:
13445 : 1243 : case V32HI_FTYPE_PCV32HI_V32HI_USI:
13446 : 1243 : case V32QI_FTYPE_PCV32QI_V32QI_USI:
13447 : 1243 : case V16QI_FTYPE_PCV16QI_V16QI_UHI:
13448 : 1243 : case V16HI_FTYPE_PCV16HI_V16HI_UHI:
13449 : 1243 : case V8HI_FTYPE_PCV8HI_V8HI_UQI:
13450 : 1243 : switch (icode)
13451 : : {
13452 : : /* These builtins and instructions require the memory
13453 : : to be properly aligned. */
13454 : : case CODE_FOR_avx512f_loadv16sf_mask:
13455 : : case CODE_FOR_avx512f_loadv16si_mask:
13456 : : case CODE_FOR_avx512f_loadv8df_mask:
13457 : : case CODE_FOR_avx512f_loadv8di_mask:
13458 : : case CODE_FOR_avx512vl_loadv8sf_mask:
13459 : : case CODE_FOR_avx512vl_loadv8si_mask:
13460 : : case CODE_FOR_avx512vl_loadv4df_mask:
13461 : : case CODE_FOR_avx512vl_loadv4di_mask:
13462 : : case CODE_FOR_avx512vl_loadv4sf_mask:
13463 : : case CODE_FOR_avx512vl_loadv4si_mask:
13464 : : case CODE_FOR_avx512vl_loadv2df_mask:
13465 : : case CODE_FOR_avx512vl_loadv2di_mask:
13466 : : case CODE_FOR_avx512bw_loadv64qi_mask:
13467 : : case CODE_FOR_avx512vl_loadv32qi_mask:
13468 : : case CODE_FOR_avx512vl_loadv16qi_mask:
13469 : : case CODE_FOR_avx512bw_loadv32hi_mask:
13470 : : case CODE_FOR_avx512vl_loadv16hi_mask:
13471 : : case CODE_FOR_avx512vl_loadv8hi_mask:
13472 : 11807 : aligned_mem = true;
13473 : : break;
13474 : : default:
13475 : : break;
13476 : : }
13477 : : /* FALLTHRU */
13478 : : case V64QI_FTYPE_PCCHAR_V64QI_UDI:
13479 : : case V32QI_FTYPE_PCCHAR_V32QI_USI:
13480 : : case V16QI_FTYPE_PCCHAR_V16QI_UHI:
13481 : : case V32HI_FTYPE_PCSHORT_V32HI_USI:
13482 : : case V16HI_FTYPE_PCSHORT_V16HI_UHI:
13483 : : case V8HI_FTYPE_PCSHORT_V8HI_UQI:
13484 : : case V16SI_FTYPE_PCINT_V16SI_UHI:
13485 : : case V8SI_FTYPE_PCINT_V8SI_UQI:
13486 : : case V4SI_FTYPE_PCINT_V4SI_UQI:
13487 : : case V8DI_FTYPE_PCINT64_V8DI_UQI:
13488 : : case V4DI_FTYPE_PCINT64_V4DI_UQI:
13489 : : case V2DI_FTYPE_PCINT64_V2DI_UQI:
13490 : : case V8DF_FTYPE_PCDOUBLE_V8DF_UQI:
13491 : : case V4DF_FTYPE_PCDOUBLE_V4DF_UQI:
13492 : : case V2DF_FTYPE_PCDOUBLE_V2DF_UQI:
13493 : : case V16SF_FTYPE_PCFLOAT_V16SF_UHI:
13494 : : case V8SF_FTYPE_PCFLOAT_V8SF_UQI:
13495 : : case V4SF_FTYPE_PCFLOAT_V4SF_UQI:
13496 : : case V8HF_FTYPE_PCFLOAT16_V8HF_UQI:
13497 : : nargs = 3;
13498 : : klass = load;
13499 : : memory = 0;
13500 : : break;
13501 : 105 : case INT_FTYPE_PINT_INT_INT_INT:
13502 : 105 : case LONGLONG_FTYPE_PLONGLONG_LONGLONG_LONGLONG_INT:
13503 : 105 : nargs = 4;
13504 : 105 : klass = load;
13505 : 105 : memory = 0;
13506 : 105 : constant = 3;
13507 : 105 : break;
13508 : 0 : default:
13509 : 0 : gcc_unreachable ();
13510 : : }
13511 : :
13512 : 8338 : gcc_assert (nargs <= ARRAY_SIZE (xops));
13513 : :
13514 : 11807 : if (klass == store)
13515 : : {
13516 : 1874 : arg = CALL_EXPR_ARG (exp, 0);
13517 : 1874 : op = expand_normal (arg);
13518 : 1874 : gcc_assert (target == 0);
13519 : 1874 : if (memory)
13520 : : {
13521 : 1715 : op = ix86_zero_extend_to_Pmode (op);
13522 : 1715 : target = gen_rtx_MEM (tmode, op);
13523 : : /* target at this point has just BITS_PER_UNIT MEM_ALIGN
13524 : : on it. Try to improve it using get_pointer_alignment,
13525 : : and if the special builtin is one that requires strict
13526 : : mode alignment, also from it's GET_MODE_ALIGNMENT.
13527 : : Failure to do so could lead to ix86_legitimate_combined_insn
13528 : : rejecting all changes to such insns. */
13529 : 1715 : unsigned int align = get_pointer_alignment (arg);
13530 : 1715 : if (aligned_mem && align < GET_MODE_ALIGNMENT (tmode))
13531 : 275 : align = GET_MODE_ALIGNMENT (tmode);
13532 : 3430 : if (MEM_ALIGN (target) < align)
13533 : 422 : set_mem_align (target, align);
13534 : : }
13535 : : else
13536 : 159 : target = force_reg (tmode, op);
13537 : : arg_adjust = 1;
13538 : : }
13539 : : else
13540 : : {
13541 : 9933 : arg_adjust = 0;
13542 : 9933 : if (optimize
13543 : 2918 : || target == 0
13544 : 2918 : || !register_operand (target, tmode)
13545 : 12840 : || GET_MODE (target) != tmode)
13546 : 7026 : target = gen_reg_rtx (tmode);
13547 : : }
13548 : :
13549 : 21192 : for (i = 0; i < nargs; i++)
13550 : : {
13551 : 9385 : machine_mode mode = insn_p->operand[i + 1].mode;
13552 : :
13553 : 9385 : arg = CALL_EXPR_ARG (exp, i + arg_adjust);
13554 : 9385 : op = ix86_expand_unsigned_small_int_cst_argument (arg);
13555 : :
13556 : 9385 : if (i == memory)
13557 : : {
13558 : : /* This must be the memory operand. */
13559 : 2352 : op = ix86_zero_extend_to_Pmode (op);
13560 : 2352 : op = gen_rtx_MEM (mode, op);
13561 : : /* op at this point has just BITS_PER_UNIT MEM_ALIGN
13562 : : on it. Try to improve it using get_pointer_alignment,
13563 : : and if the special builtin is one that requires strict
13564 : : mode alignment, also from it's GET_MODE_ALIGNMENT.
13565 : : Failure to do so could lead to ix86_legitimate_combined_insn
13566 : : rejecting all changes to such insns. */
13567 : 2352 : unsigned int align = get_pointer_alignment (arg);
13568 : 2352 : if (aligned_mem && align < GET_MODE_ALIGNMENT (mode))
13569 : 299 : align = GET_MODE_ALIGNMENT (mode);
13570 : 4704 : if (MEM_ALIGN (op) < align)
13571 : 523 : set_mem_align (op, align);
13572 : : }
13573 : 7033 : else if (i == constant)
13574 : : {
13575 : : /* This must be the constant. */
13576 : 105 : if (!insn_p->operand[nargs].predicate(op, SImode))
13577 : : {
13578 : 0 : error ("the fourth argument must be one of enum %qs", "_CMPCCX_ENUM");
13579 : 0 : return const0_rtx;
13580 : : }
13581 : : }
13582 : : else
13583 : : {
13584 : : /* This must be register. */
13585 : 6928 : if (VECTOR_MODE_P (mode))
13586 : 3474 : op = safe_vector_operand (op, mode);
13587 : :
13588 : 6928 : op = fixup_modeless_constant (op, mode);
13589 : :
13590 : : /* NB: 3-operands load implied it's a mask load or v{p}expand*,
13591 : : and that mask operand shoud be at the end.
13592 : : Keep all-ones mask which would be simplified by the expander. */
13593 : 1770 : if (nargs == 3 && i == 2 && klass == load
13594 : 1770 : && constm1_operand (op, mode)
13595 : 7101 : && insn_p->operand[i].predicate (op, mode))
13596 : : ;
13597 : 6928 : else if (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)
13598 : 6928 : op = copy_to_mode_reg (mode, op);
13599 : : else
13600 : : {
13601 : 0 : op = copy_to_reg (op);
13602 : 0 : op = lowpart_subreg (mode, op, GET_MODE (op));
13603 : : }
13604 : : }
13605 : :
13606 : 9385 : xops[i]= op;
13607 : : }
13608 : :
13609 : 11807 : switch (nargs)
13610 : : {
13611 : 7740 : case 0:
13612 : 7740 : pat = GEN_FCN (icode) (target);
13613 : 7740 : break;
13614 : 729 : case 1:
13615 : 729 : pat = GEN_FCN (icode) (target, xops[0]);
13616 : 729 : break;
13617 : 1463 : case 2:
13618 : 1463 : pat = GEN_FCN (icode) (target, xops[0], xops[1]);
13619 : 1463 : break;
13620 : 1770 : case 3:
13621 : 1770 : pat = GEN_FCN (icode) (target, xops[0], xops[1], xops[2]);
13622 : 1770 : break;
13623 : 105 : case 4:
13624 : 105 : pat = GEN_FCN (icode) (target, xops[0], xops[1], xops[2], xops[3]);
13625 : 105 : break;
13626 : : default:
13627 : : gcc_unreachable ();
13628 : : }
13629 : :
13630 : 11807 : if (! pat)
13631 : : return 0;
13632 : :
13633 : 11807 : emit_insn (pat);
13634 : 11807 : return klass == store ? 0 : target;
13635 : : }
13636 : :
13637 : : /* Return the integer constant in ARG. Constrain it to be in the range
13638 : : of the subparts of VEC_TYPE; issue an error if not. */
13639 : :
13640 : : static int
13641 : 596 : get_element_number (tree vec_type, tree arg)
13642 : : {
13643 : 596 : unsigned HOST_WIDE_INT elt, max = TYPE_VECTOR_SUBPARTS (vec_type) - 1;
13644 : :
13645 : 596 : if (!tree_fits_uhwi_p (arg)
13646 : 596 : || (elt = tree_to_uhwi (arg), elt > max))
13647 : : {
13648 : 0 : error ("selector must be an integer constant in the range "
13649 : : "[0, %wi]", max);
13650 : 0 : return 0;
13651 : : }
13652 : :
13653 : 596 : return elt;
13654 : : }
13655 : :
13656 : : /* A subroutine of ix86_expand_builtin. These builtins are a wrapper around
13657 : : ix86_expand_vector_init. We DO have language-level syntax for this, in
13658 : : the form of (type){ init-list }. Except that since we can't place emms
13659 : : instructions from inside the compiler, we can't allow the use of MMX
13660 : : registers unless the user explicitly asks for it. So we do *not* define
13661 : : vec_set/vec_extract/vec_init patterns for MMX modes in mmx.md. Instead
13662 : : we have builtins invoked by mmintrin.h that gives us license to emit
13663 : : these sorts of instructions. */
13664 : :
13665 : : static rtx
13666 : 229 : ix86_expand_vec_init_builtin (tree type, tree exp, rtx target)
13667 : : {
13668 : 229 : machine_mode tmode = TYPE_MODE (type);
13669 : 229 : machine_mode inner_mode = GET_MODE_INNER (tmode);
13670 : 229 : int i, n_elt = GET_MODE_NUNITS (tmode);
13671 : 229 : rtvec v = rtvec_alloc (n_elt);
13672 : :
13673 : 229 : gcc_assert (VECTOR_MODE_P (tmode));
13674 : 229 : gcc_assert (call_expr_nargs (exp) == n_elt);
13675 : :
13676 : 1203 : for (i = 0; i < n_elt; ++i)
13677 : : {
13678 : 974 : rtx x = expand_normal (CALL_EXPR_ARG (exp, i));
13679 : 974 : RTVEC_ELT (v, i) = gen_lowpart (inner_mode, x);
13680 : : }
13681 : :
13682 : 229 : if (!target || !register_operand (target, tmode))
13683 : 0 : target = gen_reg_rtx (tmode);
13684 : :
13685 : 229 : ix86_expand_vector_init (true, target, gen_rtx_PARALLEL (tmode, v));
13686 : 229 : return target;
13687 : : }
13688 : :
13689 : : /* A subroutine of ix86_expand_builtin. These builtins are a wrapper around
13690 : : ix86_expand_vector_extract. They would be redundant (for non-MMX) if we
13691 : : had a language-level syntax for referencing vector elements. */
13692 : :
13693 : : static rtx
13694 : 392 : ix86_expand_vec_ext_builtin (tree exp, rtx target)
13695 : : {
13696 : 392 : machine_mode tmode, mode0;
13697 : 392 : tree arg0, arg1;
13698 : 392 : int elt;
13699 : 392 : rtx op0;
13700 : :
13701 : 392 : arg0 = CALL_EXPR_ARG (exp, 0);
13702 : 392 : arg1 = CALL_EXPR_ARG (exp, 1);
13703 : :
13704 : 392 : op0 = expand_normal (arg0);
13705 : 392 : elt = get_element_number (TREE_TYPE (arg0), arg1);
13706 : :
13707 : 392 : tmode = TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0)));
13708 : 392 : mode0 = TYPE_MODE (TREE_TYPE (arg0));
13709 : 392 : gcc_assert (VECTOR_MODE_P (mode0));
13710 : :
13711 : 392 : op0 = force_reg (mode0, op0);
13712 : :
13713 : 392 : if (optimize || !target || !register_operand (target, tmode))
13714 : 313 : target = gen_reg_rtx (tmode);
13715 : :
13716 : 392 : ix86_expand_vector_extract (true, target, op0, elt);
13717 : :
13718 : 392 : return target;
13719 : : }
13720 : :
13721 : : /* A subroutine of ix86_expand_builtin. These builtins are a wrapper around
13722 : : ix86_expand_vector_set. They would be redundant (for non-MMX) if we had
13723 : : a language-level syntax for referencing vector elements. */
13724 : :
13725 : : static rtx
13726 : 204 : ix86_expand_vec_set_builtin (tree exp)
13727 : : {
13728 : 204 : machine_mode tmode, mode1;
13729 : 204 : tree arg0, arg1, arg2;
13730 : 204 : int elt;
13731 : 204 : rtx op0, op1, target;
13732 : :
13733 : 204 : arg0 = CALL_EXPR_ARG (exp, 0);
13734 : 204 : arg1 = CALL_EXPR_ARG (exp, 1);
13735 : 204 : arg2 = CALL_EXPR_ARG (exp, 2);
13736 : :
13737 : 204 : tmode = TYPE_MODE (TREE_TYPE (arg0));
13738 : 204 : mode1 = TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0)));
13739 : 204 : gcc_assert (VECTOR_MODE_P (tmode));
13740 : :
13741 : 204 : op0 = expand_expr (arg0, NULL_RTX, tmode, EXPAND_NORMAL);
13742 : 204 : op1 = expand_expr (arg1, NULL_RTX, mode1, EXPAND_NORMAL);
13743 : 204 : elt = get_element_number (TREE_TYPE (arg0), arg2);
13744 : :
13745 : 204 : if (GET_MODE (op1) != mode1)
13746 : 82 : op1 = convert_modes (mode1, GET_MODE (op1), op1, true);
13747 : :
13748 : 204 : op0 = force_reg (tmode, op0);
13749 : 204 : op1 = force_reg (mode1, op1);
13750 : :
13751 : : /* OP0 is the source of these builtin functions and shouldn't be
13752 : : modified. Create a copy, use it and return it as target. */
13753 : 204 : target = gen_reg_rtx (tmode);
13754 : 204 : emit_move_insn (target, op0);
13755 : 204 : ix86_expand_vector_set (true, target, op1, elt);
13756 : :
13757 : 204 : return target;
13758 : : }
13759 : :
13760 : : /* Return true if the necessary isa options for this builtin exist,
13761 : : else false.
13762 : : fcode = DECL_MD_FUNCTION_CODE (fndecl); */
13763 : : bool
13764 : 1247662 : ix86_check_builtin_isa_match (unsigned int fcode,
13765 : : HOST_WIDE_INT* pbisa,
13766 : : HOST_WIDE_INT* pbisa2)
13767 : : {
13768 : 1247662 : HOST_WIDE_INT isa = ix86_isa_flags;
13769 : 1247662 : HOST_WIDE_INT isa2 = ix86_isa_flags2;
13770 : 1247662 : HOST_WIDE_INT bisa = ix86_builtins_isa[fcode].isa;
13771 : 1247662 : HOST_WIDE_INT bisa2 = ix86_builtins_isa[fcode].isa2;
13772 : 1247662 : HOST_WIDE_INT tmp_isa = isa, tmp_isa2 = isa2;
13773 : : /* The general case is we require all the ISAs specified in bisa{,2}
13774 : : to be enabled.
13775 : : The exceptions are:
13776 : : OPTION_MASK_ISA_SSE | OPTION_MASK_ISA_3DNOW_A
13777 : : OPTION_MASK_ISA_SSE4_2 | OPTION_MASK_ISA_CRC32
13778 : : OPTION_MASK_ISA_FMA | OPTION_MASK_ISA_FMA4
13779 : : (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL) or
13780 : : OPTION_MASK_ISA2_AVXVNNI
13781 : : (OPTION_MASK_ISA_AVX512IFMA | OPTION_MASK_ISA_AVX512VL) or
13782 : : OPTION_MASK_ISA2_AVXIFMA
13783 : : (OPTION_MASK_ISA_AVX512VL | OPTION_MASK_ISA2_AVX512BF16) or
13784 : : OPTION_MASK_ISA2_AVXNECONVERT
13785 : : OPTION_MASK_ISA_AES or (OPTION_MASK_ISA_AVX512VL | OPTION_MASK_ISA2_VAES)
13786 : : OPTION_MASK_ISA2_AVX10_2 or OPTION_MASK_ISA2_AVXVNNIINT8
13787 : : OPTION_MASK_ISA2_AVX10_2 or OPTION_MASK_ISA2_AVXVNNIINT16
13788 : : where for each such pair it is sufficient if either of the ISAs is
13789 : : enabled, plus if it is ored with other options also those others.
13790 : : OPTION_MASK_ISA_MMX in bisa is satisfied also if TARGET_MMX_WITH_SSE. */
13791 : :
13792 : : #define SHARE_BUILTIN(A1, A2, B1, B2) \
13793 : : if ((((bisa & (A1)) == (A1) && (bisa2 & (A2)) == (A2)) \
13794 : : && ((bisa & (B1)) == (B1) && (bisa2 & (B2)) == (B2))) \
13795 : : && (((isa & (A1)) == (A1) && (isa2 & (A2)) == (A2)) \
13796 : : || ((isa & (B1)) == (B1) && (isa2 & (B2)) == (B2)))) \
13797 : : { \
13798 : : tmp_isa |= (A1) | (B1); \
13799 : : tmp_isa2 |= (A2) | (B2); \
13800 : : }
13801 : :
13802 : 1247662 : SHARE_BUILTIN (OPTION_MASK_ISA_SSE, 0, OPTION_MASK_ISA_3DNOW_A, 0);
13803 : 1247662 : SHARE_BUILTIN (OPTION_MASK_ISA_SSE4_2, 0, OPTION_MASK_ISA_CRC32, 0);
13804 : 1247662 : SHARE_BUILTIN (OPTION_MASK_ISA_FMA, 0, OPTION_MASK_ISA_FMA4, 0);
13805 : 1247662 : SHARE_BUILTIN (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, 0,
13806 : 1247662 : OPTION_MASK_ISA2_AVXVNNI);
13807 : 1247662 : SHARE_BUILTIN (OPTION_MASK_ISA_AVX512IFMA | OPTION_MASK_ISA_AVX512VL, 0, 0,
13808 : 1247662 : OPTION_MASK_ISA2_AVXIFMA);
13809 : 1247662 : SHARE_BUILTIN (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512BF16, 0,
13810 : 1247662 : OPTION_MASK_ISA2_AVXNECONVERT);
13811 : 1247662 : SHARE_BUILTIN (OPTION_MASK_ISA_AES, 0, OPTION_MASK_ISA_AVX512VL,
13812 : 1247662 : OPTION_MASK_ISA2_VAES);
13813 : 1247662 : SHARE_BUILTIN (0, OPTION_MASK_ISA2_AVXVNNIINT8, 0,
13814 : 1247662 : OPTION_MASK_ISA2_AVX10_2);
13815 : 1247662 : SHARE_BUILTIN (0, OPTION_MASK_ISA2_AVXVNNIINT16, 0,
13816 : 1247662 : OPTION_MASK_ISA2_AVX10_2);
13817 : 1247662 : isa = tmp_isa;
13818 : 1247662 : isa2 = tmp_isa2;
13819 : :
13820 : 1247662 : if ((bisa & OPTION_MASK_ISA_MMX) && !TARGET_MMX && TARGET_MMX_WITH_SSE
13821 : : /* __builtin_ia32_maskmovq requires MMX registers. */
13822 : 4563 : && fcode != IX86_BUILTIN_MASKMOVQ)
13823 : : {
13824 : 4554 : bisa &= ~OPTION_MASK_ISA_MMX;
13825 : 4554 : bisa |= OPTION_MASK_ISA_SSE2;
13826 : : }
13827 : :
13828 : 1247662 : if (pbisa)
13829 : 170298 : *pbisa = bisa;
13830 : 1247662 : if (pbisa2)
13831 : 170298 : *pbisa2 = bisa2;
13832 : :
13833 : 1247662 : return (bisa & isa) == bisa && (bisa2 & isa2) == bisa2;
13834 : : }
13835 : :
13836 : : /* Emit instructions to set the carry flag from ARG. */
13837 : :
13838 : : void
13839 : 13052 : ix86_expand_carry (rtx arg)
13840 : : {
13841 : 13052 : if (!CONST_INT_P (arg) || arg == const0_rtx)
13842 : : {
13843 : 13046 : arg = convert_to_mode (QImode, arg, 1);
13844 : 13046 : arg = copy_to_mode_reg (QImode, arg);
13845 : 13046 : emit_insn (gen_addqi3_cconly_overflow (arg, constm1_rtx));
13846 : : }
13847 : : else
13848 : 6 : emit_insn (gen_x86_stc ());
13849 : 13052 : }
13850 : :
13851 : : /* Expand an expression EXP that calls a built-in function,
13852 : : with result going to TARGET if that's convenient
13853 : : (and in mode MODE if that's convenient).
13854 : : SUBTARGET may be used as the target for computing one of EXP's operands.
13855 : : IGNORE is nonzero if the value is to be ignored. */
13856 : :
13857 : : rtx
13858 : 171067 : ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
13859 : : machine_mode mode, int ignore)
13860 : : {
13861 : 171067 : size_t i;
13862 : 171067 : enum insn_code icode, icode2;
13863 : 171067 : tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
13864 : 171067 : tree arg0, arg1, arg2, arg3, arg4;
13865 : 171067 : rtx op0, op1, op2, op3, op4, pat, pat2, insn;
13866 : 171067 : machine_mode mode0, mode1, mode2, mode3, mode4;
13867 : 171067 : unsigned int fcode = DECL_MD_FUNCTION_CODE (fndecl);
13868 : 171067 : HOST_WIDE_INT bisa, bisa2;
13869 : :
13870 : : /* For CPU builtins that can be folded, fold first and expand the fold. */
13871 : 171067 : switch (fcode)
13872 : : {
13873 : 191 : case IX86_BUILTIN_CPU_INIT:
13874 : 191 : {
13875 : : /* Make it call __cpu_indicator_init in libgcc. */
13876 : 191 : tree call_expr, fndecl, type;
13877 : 191 : type = build_function_type_list (integer_type_node, NULL_TREE);
13878 : 191 : fndecl = build_fn_decl ("__cpu_indicator_init", type);
13879 : 191 : call_expr = build_call_expr (fndecl, 0);
13880 : 191 : return expand_expr (call_expr, target, mode, EXPAND_NORMAL);
13881 : : }
13882 : 578 : case IX86_BUILTIN_CPU_IS:
13883 : 578 : case IX86_BUILTIN_CPU_SUPPORTS:
13884 : 578 : {
13885 : 578 : tree arg0 = CALL_EXPR_ARG (exp, 0);
13886 : 578 : tree fold_expr = fold_builtin_cpu (fndecl, &arg0);
13887 : 578 : gcc_assert (fold_expr != NULL_TREE);
13888 : 578 : return expand_expr (fold_expr, target, mode, EXPAND_NORMAL);
13889 : : }
13890 : : }
13891 : :
13892 : 170298 : if (!ix86_check_builtin_isa_match (fcode, &bisa, &bisa2))
13893 : : {
13894 : 23 : bool add_abi_p = bisa & OPTION_MASK_ISA_64BIT;
13895 : 23 : if (TARGET_ABI_X32)
13896 : 0 : bisa |= OPTION_MASK_ABI_X32;
13897 : : else
13898 : 23 : bisa |= OPTION_MASK_ABI_64;
13899 : 23 : char *opts = ix86_target_string (bisa, bisa2, 0, 0, NULL, NULL,
13900 : : (enum fpmath_unit) 0,
13901 : : (enum prefer_vector_width) 0,
13902 : : PVW_NONE, PVW_NONE,
13903 : : false, add_abi_p);
13904 : 23 : if (!opts)
13905 : 0 : error ("%qE needs unknown isa option", fndecl);
13906 : : else
13907 : : {
13908 : 23 : gcc_assert (opts != NULL);
13909 : 23 : error ("%qE needs isa option %s", fndecl, opts);
13910 : 23 : free (opts);
13911 : : }
13912 : 23 : return expand_call (exp, target, ignore);
13913 : : }
13914 : :
13915 : 170275 : switch (fcode)
13916 : : {
13917 : 35 : case IX86_BUILTIN_MASKMOVQ:
13918 : 35 : case IX86_BUILTIN_MASKMOVDQU:
13919 : 34 : icode = (fcode == IX86_BUILTIN_MASKMOVQ
13920 : 35 : ? CODE_FOR_mmx_maskmovq
13921 : : : CODE_FOR_sse2_maskmovdqu);
13922 : : /* Note the arg order is different from the operand order. */
13923 : 35 : arg1 = CALL_EXPR_ARG (exp, 0);
13924 : 35 : arg2 = CALL_EXPR_ARG (exp, 1);
13925 : 35 : arg0 = CALL_EXPR_ARG (exp, 2);
13926 : 35 : op0 = expand_normal (arg0);
13927 : 35 : op1 = expand_normal (arg1);
13928 : 35 : op2 = expand_normal (arg2);
13929 : 35 : mode0 = insn_data[icode].operand[0].mode;
13930 : 35 : mode1 = insn_data[icode].operand[1].mode;
13931 : 35 : mode2 = insn_data[icode].operand[2].mode;
13932 : :
13933 : 35 : op0 = ix86_zero_extend_to_Pmode (op0);
13934 : 35 : op0 = gen_rtx_MEM (mode1, op0);
13935 : :
13936 : 35 : if (!insn_data[icode].operand[0].predicate (op0, mode0))
13937 : 0 : op0 = copy_to_mode_reg (mode0, op0);
13938 : 35 : if (!insn_data[icode].operand[1].predicate (op1, mode1))
13939 : 2 : op1 = copy_to_mode_reg (mode1, op1);
13940 : 35 : if (!insn_data[icode].operand[2].predicate (op2, mode2))
13941 : 2 : op2 = copy_to_mode_reg (mode2, op2);
13942 : 35 : pat = GEN_FCN (icode) (op0, op1, op2);
13943 : 35 : if (! pat)
13944 : 56548 : return 0;
13945 : 35 : emit_insn (pat);
13946 : 35 : return 0;
13947 : :
13948 : 22002 : case IX86_BUILTIN_LDMXCSR:
13949 : 22002 : op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
13950 : 22002 : target = assign_stack_temp (SImode, GET_MODE_SIZE (SImode));
13951 : 22002 : emit_move_insn (target, op0);
13952 : 22002 : emit_insn (gen_sse_ldmxcsr (target));
13953 : 22002 : return 0;
13954 : :
13955 : 14785 : case IX86_BUILTIN_STMXCSR:
13956 : 14785 : target = assign_stack_temp (SImode, GET_MODE_SIZE (SImode));
13957 : 14785 : emit_insn (gen_sse_stmxcsr (target));
13958 : 14785 : return copy_to_mode_reg (SImode, target);
13959 : :
13960 : 11 : case IX86_BUILTIN_CLFLUSH:
13961 : 11 : arg0 = CALL_EXPR_ARG (exp, 0);
13962 : 11 : op0 = expand_normal (arg0);
13963 : 11 : icode = CODE_FOR_sse2_clflush;
13964 : 11 : if (!insn_data[icode].operand[0].predicate (op0, Pmode))
13965 : 5 : op0 = ix86_zero_extend_to_Pmode (op0);
13966 : :
13967 : 11 : emit_insn (gen_sse2_clflush (op0));
13968 : 11 : return 0;
13969 : :
13970 : 19 : case IX86_BUILTIN_CLWB:
13971 : 19 : arg0 = CALL_EXPR_ARG (exp, 0);
13972 : 19 : op0 = expand_normal (arg0);
13973 : 19 : icode = CODE_FOR_clwb;
13974 : 19 : if (!insn_data[icode].operand[0].predicate (op0, Pmode))
13975 : 9 : op0 = ix86_zero_extend_to_Pmode (op0);
13976 : :
13977 : 19 : emit_insn (gen_clwb (op0));
13978 : 19 : return 0;
13979 : :
13980 : 19 : case IX86_BUILTIN_CLFLUSHOPT:
13981 : 19 : arg0 = CALL_EXPR_ARG (exp, 0);
13982 : 19 : op0 = expand_normal (arg0);
13983 : 19 : icode = CODE_FOR_clflushopt;
13984 : 19 : if (!insn_data[icode].operand[0].predicate (op0, Pmode))
13985 : 9 : op0 = ix86_zero_extend_to_Pmode (op0);
13986 : :
13987 : 19 : emit_insn (gen_clflushopt (op0));
13988 : 19 : return 0;
13989 : :
13990 : 47 : case IX86_BUILTIN_MONITOR:
13991 : 47 : case IX86_BUILTIN_MONITORX:
13992 : 47 : arg0 = CALL_EXPR_ARG (exp, 0);
13993 : 47 : arg1 = CALL_EXPR_ARG (exp, 1);
13994 : 47 : arg2 = CALL_EXPR_ARG (exp, 2);
13995 : 47 : op0 = expand_normal (arg0);
13996 : 47 : op1 = expand_normal (arg1);
13997 : 47 : op2 = expand_normal (arg2);
13998 : 47 : if (!REG_P (op0))
13999 : 19 : op0 = ix86_zero_extend_to_Pmode (op0);
14000 : 47 : if (!REG_P (op1))
14001 : 22 : op1 = copy_to_mode_reg (SImode, op1);
14002 : 47 : if (!REG_P (op2))
14003 : 25 : op2 = copy_to_mode_reg (SImode, op2);
14004 : :
14005 : 47 : emit_insn (fcode == IX86_BUILTIN_MONITOR
14006 : 26 : ? gen_sse3_monitor (Pmode, op0, op1, op2)
14007 : 21 : : gen_monitorx (Pmode, op0, op1, op2));
14008 : 47 : return 0;
14009 : :
14010 : 25 : case IX86_BUILTIN_MWAIT:
14011 : 25 : arg0 = CALL_EXPR_ARG (exp, 0);
14012 : 25 : arg1 = CALL_EXPR_ARG (exp, 1);
14013 : 25 : op0 = expand_normal (arg0);
14014 : 25 : op1 = expand_normal (arg1);
14015 : 25 : if (!REG_P (op0))
14016 : 13 : op0 = copy_to_mode_reg (SImode, op0);
14017 : 25 : if (!REG_P (op1))
14018 : 11 : op1 = copy_to_mode_reg (SImode, op1);
14019 : 25 : emit_insn (gen_sse3_mwait (op0, op1));
14020 : 25 : return 0;
14021 : :
14022 : 21 : case IX86_BUILTIN_MWAITX:
14023 : 21 : arg0 = CALL_EXPR_ARG (exp, 0);
14024 : 21 : arg1 = CALL_EXPR_ARG (exp, 1);
14025 : 21 : arg2 = CALL_EXPR_ARG (exp, 2);
14026 : 21 : op0 = expand_normal (arg0);
14027 : 21 : op1 = expand_normal (arg1);
14028 : 21 : op2 = expand_normal (arg2);
14029 : 21 : if (!REG_P (op0))
14030 : 11 : op0 = copy_to_mode_reg (SImode, op0);
14031 : 21 : if (!REG_P (op1))
14032 : 10 : op1 = copy_to_mode_reg (SImode, op1);
14033 : 21 : if (!REG_P (op2))
14034 : 11 : op2 = copy_to_mode_reg (SImode, op2);
14035 : 21 : emit_insn (gen_mwaitx (op0, op1, op2));
14036 : 21 : return 0;
14037 : :
14038 : 21 : case IX86_BUILTIN_UMONITOR:
14039 : 21 : arg0 = CALL_EXPR_ARG (exp, 0);
14040 : 21 : op0 = expand_normal (arg0);
14041 : :
14042 : 21 : op0 = ix86_zero_extend_to_Pmode (op0);
14043 : 21 : emit_insn (gen_umonitor (Pmode, op0));
14044 : 21 : return 0;
14045 : :
14046 : 42 : case IX86_BUILTIN_UMWAIT:
14047 : 42 : case IX86_BUILTIN_TPAUSE:
14048 : 42 : arg0 = CALL_EXPR_ARG (exp, 0);
14049 : 42 : arg1 = CALL_EXPR_ARG (exp, 1);
14050 : 42 : op0 = expand_normal (arg0);
14051 : 42 : op1 = expand_normal (arg1);
14052 : :
14053 : 42 : if (!REG_P (op0))
14054 : 20 : op0 = copy_to_mode_reg (SImode, op0);
14055 : :
14056 : 42 : op1 = force_reg (DImode, op1);
14057 : :
14058 : 42 : if (TARGET_64BIT)
14059 : : {
14060 : 42 : op2 = expand_simple_binop (DImode, LSHIFTRT, op1, GEN_INT (32),
14061 : : NULL, 1, OPTAB_DIRECT);
14062 : 42 : switch (fcode)
14063 : : {
14064 : : case IX86_BUILTIN_UMWAIT:
14065 : : icode = CODE_FOR_umwait_rex64;
14066 : : break;
14067 : 21 : case IX86_BUILTIN_TPAUSE:
14068 : 21 : icode = CODE_FOR_tpause_rex64;
14069 : 21 : break;
14070 : 0 : default:
14071 : 0 : gcc_unreachable ();
14072 : : }
14073 : :
14074 : 42 : op2 = gen_lowpart (SImode, op2);
14075 : 42 : op1 = gen_lowpart (SImode, op1);
14076 : 42 : pat = GEN_FCN (icode) (op0, op1, op2);
14077 : : }
14078 : : else
14079 : : {
14080 : 0 : switch (fcode)
14081 : : {
14082 : : case IX86_BUILTIN_UMWAIT:
14083 : : icode = CODE_FOR_umwait;
14084 : : break;
14085 : 0 : case IX86_BUILTIN_TPAUSE:
14086 : 0 : icode = CODE_FOR_tpause;
14087 : 0 : break;
14088 : 0 : default:
14089 : 0 : gcc_unreachable ();
14090 : : }
14091 : 0 : pat = GEN_FCN (icode) (op0, op1);
14092 : : }
14093 : :
14094 : 42 : if (!pat)
14095 : : return 0;
14096 : :
14097 : 42 : emit_insn (pat);
14098 : :
14099 : 42 : if (target == 0
14100 : 42 : || !register_operand (target, QImode))
14101 : 0 : target = gen_reg_rtx (QImode);
14102 : :
14103 : 42 : pat = gen_rtx_EQ (QImode, gen_rtx_REG (CCCmode, FLAGS_REG),
14104 : : const0_rtx);
14105 : 42 : emit_insn (gen_rtx_SET (target, pat));
14106 : :
14107 : 42 : return target;
14108 : :
14109 : 20 : case IX86_BUILTIN_TESTUI:
14110 : 20 : emit_insn (gen_testui ());
14111 : :
14112 : 20 : if (target == 0
14113 : 20 : || !register_operand (target, QImode))
14114 : 0 : target = gen_reg_rtx (QImode);
14115 : :
14116 : 20 : pat = gen_rtx_LTU (QImode, gen_rtx_REG (CCCmode, FLAGS_REG),
14117 : : const0_rtx);
14118 : 20 : emit_insn (gen_rtx_SET (target, pat));
14119 : :
14120 : 20 : return target;
14121 : :
14122 : 19 : case IX86_BUILTIN_CLZERO:
14123 : 19 : arg0 = CALL_EXPR_ARG (exp, 0);
14124 : 19 : op0 = expand_normal (arg0);
14125 : 19 : if (!REG_P (op0))
14126 : 9 : op0 = ix86_zero_extend_to_Pmode (op0);
14127 : 19 : emit_insn (gen_clzero (Pmode, op0));
14128 : 19 : return 0;
14129 : :
14130 : 19 : case IX86_BUILTIN_CLDEMOTE:
14131 : 19 : arg0 = CALL_EXPR_ARG (exp, 0);
14132 : 19 : op0 = expand_normal (arg0);
14133 : 19 : icode = CODE_FOR_cldemote;
14134 : 19 : if (!insn_data[icode].operand[0].predicate (op0, Pmode))
14135 : 9 : op0 = ix86_zero_extend_to_Pmode (op0);
14136 : :
14137 : 19 : emit_insn (gen_cldemote (op0));
14138 : 19 : return 0;
14139 : :
14140 : 11 : case IX86_BUILTIN_LOADIWKEY:
14141 : 11 : {
14142 : 11 : arg0 = CALL_EXPR_ARG (exp, 0);
14143 : 11 : arg1 = CALL_EXPR_ARG (exp, 1);
14144 : 11 : arg2 = CALL_EXPR_ARG (exp, 2);
14145 : 11 : arg3 = CALL_EXPR_ARG (exp, 3);
14146 : :
14147 : 11 : op0 = expand_normal (arg0);
14148 : 11 : op1 = expand_normal (arg1);
14149 : 11 : op2 = expand_normal (arg2);
14150 : 11 : op3 = expand_normal (arg3);
14151 : :
14152 : 11 : if (!REG_P (op0))
14153 : 5 : op0 = copy_to_mode_reg (V2DImode, op0);
14154 : 11 : if (!REG_P (op1))
14155 : 5 : op1 = copy_to_mode_reg (V2DImode, op1);
14156 : 11 : if (!REG_P (op2))
14157 : 5 : op2 = copy_to_mode_reg (V2DImode, op2);
14158 : 11 : if (!REG_P (op3))
14159 : 5 : op3 = copy_to_mode_reg (SImode, op3);
14160 : :
14161 : 11 : emit_insn (gen_loadiwkey (op0, op1, op2, op3));
14162 : :
14163 : 11 : return 0;
14164 : : }
14165 : :
14166 : 12 : case IX86_BUILTIN_AESDEC128KLU8:
14167 : 12 : icode = CODE_FOR_aesdec128klu8;
14168 : 12 : goto aesdecenc_expand;
14169 : :
14170 : 12 : case IX86_BUILTIN_AESDEC256KLU8:
14171 : 12 : icode = CODE_FOR_aesdec256klu8;
14172 : 12 : goto aesdecenc_expand;
14173 : :
14174 : 12 : case IX86_BUILTIN_AESENC128KLU8:
14175 : 12 : icode = CODE_FOR_aesenc128klu8;
14176 : 12 : goto aesdecenc_expand;
14177 : :
14178 : : case IX86_BUILTIN_AESENC256KLU8:
14179 : : icode = CODE_FOR_aesenc256klu8;
14180 : :
14181 : 48 : aesdecenc_expand:
14182 : :
14183 : 48 : arg0 = CALL_EXPR_ARG (exp, 0); // __m128i *odata
14184 : 48 : arg1 = CALL_EXPR_ARG (exp, 1); // __m128i idata
14185 : 48 : arg2 = CALL_EXPR_ARG (exp, 2); // const void *p
14186 : :
14187 : 48 : op0 = expand_normal (arg0);
14188 : 48 : op1 = expand_normal (arg1);
14189 : 48 : op2 = expand_normal (arg2);
14190 : :
14191 : 48 : if (!address_operand (op0, V2DImode))
14192 : : {
14193 : 16 : op0 = convert_memory_address (Pmode, op0);
14194 : 16 : op0 = copy_addr_to_reg (op0);
14195 : : }
14196 : 48 : op0 = gen_rtx_MEM (V2DImode, op0);
14197 : :
14198 : 48 : if (!REG_P (op1))
14199 : 20 : op1 = copy_to_mode_reg (V2DImode, op1);
14200 : :
14201 : 48 : if (!address_operand (op2, VOIDmode))
14202 : : {
14203 : 16 : op2 = convert_memory_address (Pmode, op2);
14204 : 16 : op2 = copy_addr_to_reg (op2);
14205 : : }
14206 : 48 : op2 = gen_rtx_MEM (BLKmode, op2);
14207 : :
14208 : 48 : emit_insn (GEN_FCN (icode) (op1, op1, op2));
14209 : :
14210 : 48 : if (target == 0)
14211 : 4 : target = gen_reg_rtx (QImode);
14212 : :
14213 : : /* NB: For aesenc/aesdec keylocker insn, ZF will be set when runtime
14214 : : error occurs. Then the output should be cleared for safety. */
14215 : 48 : rtx_code_label *ok_label;
14216 : 48 : rtx tmp;
14217 : :
14218 : 48 : tmp = gen_rtx_REG (CCZmode, FLAGS_REG);
14219 : 48 : pat = gen_rtx_EQ (QImode, tmp, const0_rtx);
14220 : 48 : ok_label = gen_label_rtx ();
14221 : 48 : emit_cmp_and_jump_insns (tmp, const0_rtx, NE, 0, GET_MODE (tmp),
14222 : : true, ok_label);
14223 : : /* Usually the runtime error seldom occur, so predict OK path as
14224 : : hotspot to optimize it as fallthrough block. */
14225 : 48 : predict_jump (REG_BR_PROB_BASE * 90 / 100);
14226 : :
14227 : 48 : emit_insn (gen_rtx_SET (op1, const0_rtx));
14228 : :
14229 : 48 : emit_label (ok_label);
14230 : 48 : emit_insn (gen_rtx_SET (target, pat));
14231 : 48 : emit_insn (gen_rtx_SET (op0, op1));
14232 : :
14233 : 48 : return target;
14234 : :
14235 : 11 : case IX86_BUILTIN_AESDECWIDE128KLU8:
14236 : 11 : icode = CODE_FOR_aesdecwide128klu8;
14237 : 11 : goto wideaesdecenc_expand;
14238 : :
14239 : 11 : case IX86_BUILTIN_AESDECWIDE256KLU8:
14240 : 11 : icode = CODE_FOR_aesdecwide256klu8;
14241 : 11 : goto wideaesdecenc_expand;
14242 : :
14243 : 11 : case IX86_BUILTIN_AESENCWIDE128KLU8:
14244 : 11 : icode = CODE_FOR_aesencwide128klu8;
14245 : 11 : goto wideaesdecenc_expand;
14246 : :
14247 : : case IX86_BUILTIN_AESENCWIDE256KLU8:
14248 : : icode = CODE_FOR_aesencwide256klu8;
14249 : :
14250 : 44 : wideaesdecenc_expand:
14251 : :
14252 : 44 : rtx xmm_regs[8];
14253 : 44 : rtx op;
14254 : :
14255 : 44 : arg0 = CALL_EXPR_ARG (exp, 0); // __m128i * odata
14256 : 44 : arg1 = CALL_EXPR_ARG (exp, 1); // const __m128i * idata
14257 : 44 : arg2 = CALL_EXPR_ARG (exp, 2); // const void *p
14258 : :
14259 : 44 : op0 = expand_normal (arg0);
14260 : 44 : op1 = expand_normal (arg1);
14261 : 44 : op2 = expand_normal (arg2);
14262 : :
14263 : 44 : if (GET_MODE (op1) != Pmode)
14264 : 0 : op1 = convert_to_mode (Pmode, op1, 1);
14265 : :
14266 : 44 : if (!address_operand (op2, VOIDmode))
14267 : : {
14268 : 16 : op2 = convert_memory_address (Pmode, op2);
14269 : 16 : op2 = copy_addr_to_reg (op2);
14270 : : }
14271 : 44 : op2 = gen_rtx_MEM (BLKmode, op2);
14272 : :
14273 : 440 : for (i = 0; i < 8; i++)
14274 : : {
14275 : 352 : xmm_regs[i] = gen_rtx_REG (V2DImode, GET_SSE_REGNO (i));
14276 : :
14277 : 352 : op = gen_rtx_MEM (V2DImode,
14278 : 352 : plus_constant (Pmode, op1, (i * 16)));
14279 : :
14280 : 352 : emit_move_insn (xmm_regs[i], op);
14281 : : }
14282 : :
14283 : 44 : emit_insn (GEN_FCN (icode) (op2));
14284 : :
14285 : 44 : if (target == 0)
14286 : 0 : target = gen_reg_rtx (QImode);
14287 : :
14288 : 44 : tmp = gen_rtx_REG (CCZmode, FLAGS_REG);
14289 : 44 : pat = gen_rtx_EQ (QImode, tmp, const0_rtx);
14290 : 44 : ok_label = gen_label_rtx ();
14291 : 44 : emit_cmp_and_jump_insns (tmp, const0_rtx, NE, 0, GET_MODE (tmp),
14292 : : true, ok_label);
14293 : 44 : predict_jump (REG_BR_PROB_BASE * 90 / 100);
14294 : :
14295 : 440 : for (i = 0; i < 8; i++)
14296 : 352 : emit_insn (gen_rtx_SET (xmm_regs[i], const0_rtx));
14297 : :
14298 : 44 : emit_label (ok_label);
14299 : 44 : emit_insn (gen_rtx_SET (target, pat));
14300 : :
14301 : 44 : if (GET_MODE (op0) != Pmode)
14302 : 0 : op0 = convert_to_mode (Pmode, op0, 1);
14303 : :
14304 : 396 : for (i = 0; i < 8; i++)
14305 : : {
14306 : 352 : op = gen_rtx_MEM (V2DImode,
14307 : 352 : plus_constant (Pmode, op0, (i * 16)));
14308 : 352 : emit_move_insn (op, xmm_regs[i]);
14309 : : }
14310 : :
14311 : : return target;
14312 : :
14313 : 12 : case IX86_BUILTIN_ENCODEKEY128U32:
14314 : 12 : {
14315 : 12 : rtx op, xmm_regs[7];
14316 : :
14317 : 12 : arg0 = CALL_EXPR_ARG (exp, 0); // unsigned int htype
14318 : 12 : arg1 = CALL_EXPR_ARG (exp, 1); // __m128i key
14319 : 12 : arg2 = CALL_EXPR_ARG (exp, 2); // void *h
14320 : :
14321 : 12 : op0 = expand_normal (arg0);
14322 : 12 : op1 = expand_normal (arg1);
14323 : 12 : op2 = expand_normal (arg2);
14324 : :
14325 : 12 : if (!REG_P (op0))
14326 : 6 : op0 = copy_to_mode_reg (SImode, op0);
14327 : :
14328 : 12 : if (GET_MODE (op2) != Pmode)
14329 : 1 : op2 = convert_to_mode (Pmode, op2, 1);
14330 : :
14331 : 12 : op = gen_rtx_REG (V2DImode, GET_SSE_REGNO (0));
14332 : 12 : emit_move_insn (op, op1);
14333 : :
14334 : 60 : for (i = 0; i < 3; i++)
14335 : 36 : xmm_regs[i] = gen_rtx_REG (V2DImode, GET_SSE_REGNO (i));
14336 : :
14337 : 12 : if (target == 0)
14338 : 1 : target = gen_reg_rtx (SImode);
14339 : :
14340 : 12 : emit_insn (gen_encodekey128u32 (target, op0));
14341 : :
14342 : 60 : for (i = 0; i < 3; i++)
14343 : : {
14344 : 36 : op = gen_rtx_MEM (V2DImode,
14345 : 36 : plus_constant (Pmode, op2, (i * 16)));
14346 : 36 : emit_move_insn (op, xmm_regs[i]);
14347 : : }
14348 : :
14349 : 12 : return target;
14350 : : }
14351 : 12 : case IX86_BUILTIN_ENCODEKEY256U32:
14352 : 12 : {
14353 : 12 : rtx op, xmm_regs[7];
14354 : :
14355 : 12 : arg0 = CALL_EXPR_ARG (exp, 0); // unsigned int htype
14356 : 12 : arg1 = CALL_EXPR_ARG (exp, 1); // __m128i keylow
14357 : 12 : arg2 = CALL_EXPR_ARG (exp, 2); // __m128i keyhi
14358 : 12 : arg3 = CALL_EXPR_ARG (exp, 3); // void *h
14359 : :
14360 : 12 : op0 = expand_normal (arg0);
14361 : 12 : op1 = expand_normal (arg1);
14362 : 12 : op2 = expand_normal (arg2);
14363 : 12 : op3 = expand_normal (arg3);
14364 : :
14365 : 12 : if (!REG_P (op0))
14366 : 6 : op0 = copy_to_mode_reg (SImode, op0);
14367 : :
14368 : 12 : if (GET_MODE (op3) != Pmode)
14369 : 1 : op3 = convert_to_mode (Pmode, op3, 1);
14370 : :
14371 : : /* Force to use xmm0, xmm1 for keylow, keyhi*/
14372 : 12 : op = gen_rtx_REG (V2DImode, GET_SSE_REGNO (0));
14373 : 12 : emit_move_insn (op, op1);
14374 : 12 : op = gen_rtx_REG (V2DImode, GET_SSE_REGNO (1));
14375 : 12 : emit_move_insn (op, op2);
14376 : :
14377 : 72 : for (i = 0; i < 4; i++)
14378 : 48 : xmm_regs[i] = gen_rtx_REG (V2DImode, GET_SSE_REGNO (i));
14379 : :
14380 : 12 : if (target == 0)
14381 : 1 : target = gen_reg_rtx (SImode);
14382 : :
14383 : 12 : emit_insn (gen_encodekey256u32 (target, op0));
14384 : :
14385 : 72 : for (i = 0; i < 4; i++)
14386 : : {
14387 : 48 : op = gen_rtx_MEM (V2DImode,
14388 : 48 : plus_constant (Pmode, op3, (i * 16)));
14389 : 48 : emit_move_insn (op, xmm_regs[i]);
14390 : : }
14391 : :
14392 : 12 : return target;
14393 : : }
14394 : :
14395 : 48 : case IX86_BUILTIN_PREFETCH:
14396 : 48 : {
14397 : 48 : arg0 = CALL_EXPR_ARG (exp, 0); // const void *
14398 : 48 : arg1 = CALL_EXPR_ARG (exp, 1); // const int
14399 : 48 : arg2 = CALL_EXPR_ARG (exp, 2); // const int
14400 : 48 : arg3 = CALL_EXPR_ARG (exp, 3); // const int
14401 : :
14402 : 48 : op0 = expand_normal (arg0);
14403 : 48 : op1 = expand_normal (arg1);
14404 : 48 : op2 = expand_normal (arg2);
14405 : 48 : op3 = expand_normal (arg3);
14406 : :
14407 : 48 : if (!CONST_INT_P (op1) || !CONST_INT_P (op2) || !CONST_INT_P (op3))
14408 : : {
14409 : 0 : error ("second, third and fourth argument must be a const");
14410 : 0 : return const0_rtx;
14411 : : }
14412 : :
14413 : 48 : if (!IN_RANGE (INTVAL (op1), 0, 2))
14414 : : {
14415 : 1 : warning (0, "invalid second argument to"
14416 : : " %<__builtin_ia32_prefetch%>; using zero");
14417 : 1 : op1 = const0_rtx;
14418 : : }
14419 : :
14420 : 48 : if (INTVAL (op3) == 1)
14421 : : {
14422 : 4 : if (!IN_RANGE (INTVAL (op2), 2, 3))
14423 : : {
14424 : 1 : error ("invalid third argument");
14425 : 1 : return const0_rtx;
14426 : : }
14427 : :
14428 : 3 : if (TARGET_64BIT && TARGET_PREFETCHI
14429 : 6 : && local_func_symbolic_operand (op0, GET_MODE (op0)))
14430 : 2 : emit_insn (gen_prefetchi (op0, op2));
14431 : : else
14432 : : {
14433 : 1 : warning (0, "instruction prefetch applies when in 64-bit mode"
14434 : : " with RIP-relative addressing and"
14435 : : " option %<-mprefetchi%>;"
14436 : : " they stay NOPs otherwise");
14437 : 1 : emit_insn (gen_nop ());
14438 : : }
14439 : : }
14440 : : else
14441 : : {
14442 : 44 : if (INTVAL (op3) != 0)
14443 : 1 : warning (0, "invalid forth argument to"
14444 : : " %<__builtin_ia32_prefetch%>; using zero");
14445 : :
14446 : 44 : if (!address_operand (op0, VOIDmode))
14447 : : {
14448 : 10 : op0 = convert_memory_address (Pmode, op0);
14449 : 10 : op0 = copy_addr_to_reg (op0);
14450 : : }
14451 : :
14452 : 44 : if (!IN_RANGE (INTVAL (op2), 0, 3))
14453 : : {
14454 : 1 : warning (0, "invalid third argument to %<__builtin_ia32_prefetch%>; using zero");
14455 : 1 : op2 = const0_rtx;
14456 : : }
14457 : :
14458 : 44 : if (TARGET_3DNOW
14459 : 26 : || TARGET_PREFETCH_SSE
14460 : 0 : || TARGET_PRFCHW
14461 : 0 : || TARGET_MOVRS)
14462 : 44 : emit_insn (gen_prefetch (op0, op1, op2));
14463 : 0 : else if (!MEM_P (op0) && side_effects_p (op0))
14464 : : /* Don't do anything with direct references to volatile memory,
14465 : : but generate code to handle other side effects. */
14466 : 0 : emit_insn (op0);
14467 : : }
14468 : :
14469 : : return 0;
14470 : : }
14471 : :
14472 : 21 : case IX86_BUILTIN_PREFETCHI:
14473 : 21 : {
14474 : 21 : arg0 = CALL_EXPR_ARG (exp, 0); // const void *
14475 : 21 : arg1 = CALL_EXPR_ARG (exp, 1); // const int
14476 : :
14477 : 21 : op0 = expand_normal (arg0);
14478 : 21 : op1 = expand_normal (arg1);
14479 : :
14480 : 21 : if (!CONST_INT_P (op1))
14481 : : {
14482 : 0 : error ("second argument must be a const");
14483 : 0 : return const0_rtx;
14484 : : }
14485 : :
14486 : : /* GOT/PLT_PIC should not be available for instruction prefetch.
14487 : : It must be real instruction address. */
14488 : 21 : if (TARGET_64BIT
14489 : 21 : && local_func_symbolic_operand (op0, GET_MODE (op0)))
14490 : 4 : emit_insn (gen_prefetchi (op0, op1));
14491 : : else
14492 : : {
14493 : : /* Ignore the hint. */
14494 : 17 : warning (0, "instruction prefetch applies when in 64-bit mode"
14495 : : " with RIP-relative addressing and"
14496 : : " option %<-mprefetchi%>;"
14497 : : " they stay NOPs otherwise");
14498 : 17 : emit_insn (gen_nop ());
14499 : : }
14500 : :
14501 : : return 0;
14502 : : }
14503 : :
14504 : 52 : case IX86_BUILTIN_URDMSR:
14505 : 52 : case IX86_BUILTIN_UWRMSR:
14506 : 52 : {
14507 : 52 : arg0 = CALL_EXPR_ARG (exp, 0);
14508 : 52 : op0 = expand_normal (arg0);
14509 : :
14510 : 52 : if (CONST_INT_P (op0))
14511 : : {
14512 : 12 : unsigned HOST_WIDE_INT val = UINTVAL (op0);
14513 : 12 : if (val > 0xffffffff)
14514 : 2 : op0 = force_reg (DImode, op0);
14515 : : }
14516 : : else
14517 : 40 : op0 = force_reg (DImode, op0);
14518 : :
14519 : 52 : if (fcode == IX86_BUILTIN_UWRMSR)
14520 : : {
14521 : 26 : arg1 = CALL_EXPR_ARG (exp, 1);
14522 : 26 : op1 = expand_normal (arg1);
14523 : 26 : op1 = force_reg (DImode, op1);
14524 : 26 : icode = CODE_FOR_uwrmsr;
14525 : 26 : target = 0;
14526 : : }
14527 : : else
14528 : : {
14529 : 26 : if (target == 0)
14530 : 0 : target = gen_reg_rtx (DImode);
14531 : : icode = CODE_FOR_urdmsr;
14532 : : op1 = op0;
14533 : : op0 = target;
14534 : : }
14535 : 52 : emit_insn (GEN_FCN (icode) (op0, op1));
14536 : 52 : return target;
14537 : : }
14538 : :
14539 : 229 : case IX86_BUILTIN_VEC_INIT_V2SI:
14540 : 229 : case IX86_BUILTIN_VEC_INIT_V4HI:
14541 : 229 : case IX86_BUILTIN_VEC_INIT_V8QI:
14542 : 229 : return ix86_expand_vec_init_builtin (TREE_TYPE (exp), exp, target);
14543 : :
14544 : 392 : case IX86_BUILTIN_VEC_EXT_V2DF:
14545 : 392 : case IX86_BUILTIN_VEC_EXT_V2DI:
14546 : 392 : case IX86_BUILTIN_VEC_EXT_V4SF:
14547 : 392 : case IX86_BUILTIN_VEC_EXT_V4SI:
14548 : 392 : case IX86_BUILTIN_VEC_EXT_V8HI:
14549 : 392 : case IX86_BUILTIN_VEC_EXT_V2SI:
14550 : 392 : case IX86_BUILTIN_VEC_EXT_V4HI:
14551 : 392 : case IX86_BUILTIN_VEC_EXT_V16QI:
14552 : 392 : return ix86_expand_vec_ext_builtin (exp, target);
14553 : :
14554 : 204 : case IX86_BUILTIN_VEC_SET_V2DI:
14555 : 204 : case IX86_BUILTIN_VEC_SET_V4SF:
14556 : 204 : case IX86_BUILTIN_VEC_SET_V4SI:
14557 : 204 : case IX86_BUILTIN_VEC_SET_V8HI:
14558 : 204 : case IX86_BUILTIN_VEC_SET_V4HI:
14559 : 204 : case IX86_BUILTIN_VEC_SET_V16QI:
14560 : 204 : return ix86_expand_vec_set_builtin (exp);
14561 : :
14562 : 0 : case IX86_BUILTIN_NANQ:
14563 : 0 : case IX86_BUILTIN_NANSQ:
14564 : 0 : return expand_call (exp, target, ignore);
14565 : :
14566 : 18 : case IX86_BUILTIN_RDPID:
14567 : :
14568 : 18 : op0 = gen_reg_rtx (word_mode);
14569 : :
14570 : 18 : if (TARGET_64BIT)
14571 : : {
14572 : 18 : insn = gen_rdpid_rex64 (op0);
14573 : 18 : op0 = convert_to_mode (SImode, op0, 1);
14574 : : }
14575 : : else
14576 : 0 : insn = gen_rdpid (op0);
14577 : :
14578 : 18 : emit_insn (insn);
14579 : :
14580 : 18 : if (target == 0
14581 : 18 : || !register_operand (target, SImode))
14582 : 0 : target = gen_reg_rtx (SImode);
14583 : :
14584 : 18 : emit_move_insn (target, op0);
14585 : 18 : return target;
14586 : :
14587 : 76 : case IX86_BUILTIN_2INTERSECTD512:
14588 : 76 : case IX86_BUILTIN_2INTERSECTQ512:
14589 : 76 : case IX86_BUILTIN_2INTERSECTD256:
14590 : 76 : case IX86_BUILTIN_2INTERSECTQ256:
14591 : 76 : case IX86_BUILTIN_2INTERSECTD128:
14592 : 76 : case IX86_BUILTIN_2INTERSECTQ128:
14593 : 76 : arg0 = CALL_EXPR_ARG (exp, 0);
14594 : 76 : arg1 = CALL_EXPR_ARG (exp, 1);
14595 : 76 : arg2 = CALL_EXPR_ARG (exp, 2);
14596 : 76 : arg3 = CALL_EXPR_ARG (exp, 3);
14597 : 76 : op0 = expand_normal (arg0);
14598 : 76 : op1 = expand_normal (arg1);
14599 : 76 : op2 = expand_normal (arg2);
14600 : 76 : op3 = expand_normal (arg3);
14601 : :
14602 : 76 : if (!address_operand (op0, VOIDmode))
14603 : : {
14604 : 26 : op0 = convert_memory_address (Pmode, op0);
14605 : 26 : op0 = copy_addr_to_reg (op0);
14606 : : }
14607 : 76 : if (!address_operand (op1, VOIDmode))
14608 : : {
14609 : 26 : op1 = convert_memory_address (Pmode, op1);
14610 : 26 : op1 = copy_addr_to_reg (op1);
14611 : : }
14612 : :
14613 : 76 : switch (fcode)
14614 : : {
14615 : : case IX86_BUILTIN_2INTERSECTD512:
14616 : : mode4 = P2HImode;
14617 : : icode = CODE_FOR_avx512vp2intersect_2intersectv16si;
14618 : : break;
14619 : : case IX86_BUILTIN_2INTERSECTQ512:
14620 : : mode4 = P2QImode;
14621 : : icode = CODE_FOR_avx512vp2intersect_2intersectv8di;
14622 : : break;
14623 : : case IX86_BUILTIN_2INTERSECTD256:
14624 : : mode4 = P2QImode;
14625 : : icode = CODE_FOR_avx512vp2intersect_2intersectv8si;
14626 : : break;
14627 : : case IX86_BUILTIN_2INTERSECTQ256:
14628 : : mode4 = P2QImode;
14629 : : icode = CODE_FOR_avx512vp2intersect_2intersectv4di;
14630 : : break;
14631 : : case IX86_BUILTIN_2INTERSECTD128:
14632 : : mode4 = P2QImode;
14633 : : icode = CODE_FOR_avx512vp2intersect_2intersectv4si;
14634 : : break;
14635 : : case IX86_BUILTIN_2INTERSECTQ128:
14636 : : mode4 = P2QImode;
14637 : : icode = CODE_FOR_avx512vp2intersect_2intersectv2di;
14638 : : break;
14639 : 0 : default:
14640 : 0 : gcc_unreachable ();
14641 : : }
14642 : :
14643 : 76 : mode2 = insn_data[icode].operand[1].mode;
14644 : 76 : mode3 = insn_data[icode].operand[2].mode;
14645 : 76 : if (!insn_data[icode].operand[1].predicate (op2, mode2))
14646 : 26 : op2 = copy_to_mode_reg (mode2, op2);
14647 : 76 : if (!insn_data[icode].operand[2].predicate (op3, mode3))
14648 : 6 : op3 = copy_to_mode_reg (mode3, op3);
14649 : :
14650 : 76 : op4 = gen_reg_rtx (mode4);
14651 : 76 : emit_insn (GEN_FCN (icode) (op4, op2, op3));
14652 : 76 : mode0 = mode4 == P2HImode ? HImode : QImode;
14653 : 76 : emit_move_insn (gen_rtx_MEM (mode0, op0),
14654 : 76 : gen_lowpart (mode0, op4));
14655 : 76 : emit_move_insn (gen_rtx_MEM (mode0, op1),
14656 : : gen_highpart (mode0, op4));
14657 : :
14658 : 76 : return 0;
14659 : :
14660 : 102 : case IX86_BUILTIN_RDPMC:
14661 : 102 : case IX86_BUILTIN_RDTSC:
14662 : 102 : case IX86_BUILTIN_RDTSCP:
14663 : 102 : case IX86_BUILTIN_XGETBV:
14664 : :
14665 : 102 : op0 = gen_reg_rtx (DImode);
14666 : 102 : op1 = gen_reg_rtx (DImode);
14667 : :
14668 : 102 : if (fcode == IX86_BUILTIN_RDPMC)
14669 : : {
14670 : 22 : arg0 = CALL_EXPR_ARG (exp, 0);
14671 : 22 : op2 = expand_normal (arg0);
14672 : 22 : if (!register_operand (op2, SImode))
14673 : 11 : op2 = copy_to_mode_reg (SImode, op2);
14674 : :
14675 : 22 : insn = (TARGET_64BIT
14676 : 22 : ? gen_rdpmc_rex64 (op0, op1, op2)
14677 : 0 : : gen_rdpmc (op0, op2));
14678 : 22 : emit_insn (insn);
14679 : : }
14680 : 80 : else if (fcode == IX86_BUILTIN_XGETBV)
14681 : : {
14682 : 22 : arg0 = CALL_EXPR_ARG (exp, 0);
14683 : 22 : op2 = expand_normal (arg0);
14684 : 22 : if (!register_operand (op2, SImode))
14685 : 1 : op2 = copy_to_mode_reg (SImode, op2);
14686 : :
14687 : 22 : insn = (TARGET_64BIT
14688 : 22 : ? gen_xgetbv_rex64 (op0, op1, op2)
14689 : 0 : : gen_xgetbv (op0, op2));
14690 : 22 : emit_insn (insn);
14691 : : }
14692 : 58 : else if (fcode == IX86_BUILTIN_RDTSC)
14693 : : {
14694 : 36 : insn = (TARGET_64BIT
14695 : 36 : ? gen_rdtsc_rex64 (op0, op1)
14696 : 2 : : gen_rdtsc (op0));
14697 : 36 : emit_insn (insn);
14698 : : }
14699 : : else
14700 : : {
14701 : 22 : op2 = gen_reg_rtx (SImode);
14702 : :
14703 : 22 : insn = (TARGET_64BIT
14704 : 22 : ? gen_rdtscp_rex64 (op0, op1, op2)
14705 : 0 : : gen_rdtscp (op0, op2));
14706 : 22 : emit_insn (insn);
14707 : :
14708 : 22 : arg0 = CALL_EXPR_ARG (exp, 0);
14709 : 22 : op4 = expand_normal (arg0);
14710 : 22 : if (!address_operand (op4, VOIDmode))
14711 : : {
14712 : 10 : op4 = convert_memory_address (Pmode, op4);
14713 : 10 : op4 = copy_addr_to_reg (op4);
14714 : : }
14715 : 22 : emit_move_insn (gen_rtx_MEM (SImode, op4), op2);
14716 : : }
14717 : :
14718 : 102 : if (target == 0
14719 : 102 : || !register_operand (target, DImode))
14720 : 10 : target = gen_reg_rtx (DImode);
14721 : :
14722 : 102 : if (TARGET_64BIT)
14723 : : {
14724 : 100 : op1 = expand_simple_binop (DImode, ASHIFT, op1, GEN_INT (32),
14725 : : op1, 1, OPTAB_DIRECT);
14726 : 100 : op0 = expand_simple_binop (DImode, IOR, op0, op1,
14727 : : op0, 1, OPTAB_DIRECT);
14728 : : }
14729 : :
14730 : 102 : emit_move_insn (target, op0);
14731 : 102 : return target;
14732 : :
14733 : 61 : case IX86_BUILTIN_ENQCMD:
14734 : 61 : case IX86_BUILTIN_ENQCMDS:
14735 : 61 : case IX86_BUILTIN_MOVDIR64B:
14736 : :
14737 : 61 : arg0 = CALL_EXPR_ARG (exp, 0);
14738 : 61 : arg1 = CALL_EXPR_ARG (exp, 1);
14739 : 61 : op0 = expand_normal (arg0);
14740 : 61 : op1 = expand_normal (arg1);
14741 : :
14742 : 61 : op0 = ix86_zero_extend_to_Pmode (op0);
14743 : 61 : if (!address_operand (op1, VOIDmode))
14744 : : {
14745 : 28 : op1 = convert_memory_address (Pmode, op1);
14746 : 28 : op1 = copy_addr_to_reg (op1);
14747 : : }
14748 : 61 : op1 = gen_rtx_MEM (XImode, op1);
14749 : :
14750 : 61 : if (fcode == IX86_BUILTIN_MOVDIR64B)
14751 : : {
14752 : 24 : emit_insn (gen_movdir64b (Pmode, op0, op1));
14753 : 23 : return 0;
14754 : : }
14755 : : else
14756 : : {
14757 : 38 : if (target == 0
14758 : 38 : || !register_operand (target, SImode))
14759 : 0 : target = gen_reg_rtx (SImode);
14760 : :
14761 : 38 : emit_move_insn (target, const0_rtx);
14762 : 38 : target = gen_rtx_SUBREG (QImode, target, 0);
14763 : :
14764 : 19 : int unspecv = (fcode == IX86_BUILTIN_ENQCMD
14765 : 38 : ? UNSPECV_ENQCMD
14766 : : : UNSPECV_ENQCMDS);
14767 : 38 : icode = code_for_enqcmd (unspecv, Pmode);
14768 : 38 : emit_insn (GEN_FCN (icode) (op0, op1));
14769 : :
14770 : 38 : emit_insn
14771 : 38 : (gen_rtx_SET (gen_rtx_STRICT_LOW_PART (VOIDmode, target),
14772 : : gen_rtx_fmt_ee (EQ, QImode,
14773 : : gen_rtx_REG (CCZmode, FLAGS_REG),
14774 : : const0_rtx)));
14775 : 38 : return SUBREG_REG (target);
14776 : : }
14777 : :
14778 : 14775 : case IX86_BUILTIN_FXSAVE:
14779 : 14775 : case IX86_BUILTIN_FXRSTOR:
14780 : 14775 : case IX86_BUILTIN_FXSAVE64:
14781 : 14775 : case IX86_BUILTIN_FXRSTOR64:
14782 : 14775 : case IX86_BUILTIN_FNSTENV:
14783 : 14775 : case IX86_BUILTIN_FLDENV:
14784 : 14775 : mode0 = BLKmode;
14785 : 14775 : switch (fcode)
14786 : : {
14787 : : case IX86_BUILTIN_FXSAVE:
14788 : : icode = CODE_FOR_fxsave;
14789 : : break;
14790 : 19 : case IX86_BUILTIN_FXRSTOR:
14791 : 19 : icode = CODE_FOR_fxrstor;
14792 : 19 : break;
14793 : 23 : case IX86_BUILTIN_FXSAVE64:
14794 : 23 : icode = CODE_FOR_fxsave64;
14795 : 23 : break;
14796 : 21 : case IX86_BUILTIN_FXRSTOR64:
14797 : 21 : icode = CODE_FOR_fxrstor64;
14798 : 21 : break;
14799 : 7257 : case IX86_BUILTIN_FNSTENV:
14800 : 7257 : icode = CODE_FOR_fnstenv;
14801 : 7257 : break;
14802 : 7435 : case IX86_BUILTIN_FLDENV:
14803 : 7435 : icode = CODE_FOR_fldenv;
14804 : 7435 : break;
14805 : 0 : default:
14806 : 0 : gcc_unreachable ();
14807 : : }
14808 : :
14809 : 14775 : arg0 = CALL_EXPR_ARG (exp, 0);
14810 : 14775 : op0 = expand_normal (arg0);
14811 : :
14812 : 14775 : if (!address_operand (op0, VOIDmode))
14813 : : {
14814 : 36 : op0 = convert_memory_address (Pmode, op0);
14815 : 36 : op0 = copy_addr_to_reg (op0);
14816 : : }
14817 : 14775 : op0 = gen_rtx_MEM (mode0, op0);
14818 : :
14819 : 14775 : pat = GEN_FCN (icode) (op0);
14820 : 14775 : if (pat)
14821 : 14775 : emit_insn (pat);
14822 : : return 0;
14823 : :
14824 : 21 : case IX86_BUILTIN_XSETBV:
14825 : 21 : arg0 = CALL_EXPR_ARG (exp, 0);
14826 : 21 : arg1 = CALL_EXPR_ARG (exp, 1);
14827 : 21 : op0 = expand_normal (arg0);
14828 : 21 : op1 = expand_normal (arg1);
14829 : :
14830 : 21 : if (!REG_P (op0))
14831 : 1 : op0 = copy_to_mode_reg (SImode, op0);
14832 : :
14833 : 21 : op1 = force_reg (DImode, op1);
14834 : :
14835 : 21 : if (TARGET_64BIT)
14836 : : {
14837 : 21 : op2 = expand_simple_binop (DImode, LSHIFTRT, op1, GEN_INT (32),
14838 : : NULL, 1, OPTAB_DIRECT);
14839 : :
14840 : 21 : icode = CODE_FOR_xsetbv_rex64;
14841 : :
14842 : 21 : op2 = gen_lowpart (SImode, op2);
14843 : 21 : op1 = gen_lowpart (SImode, op1);
14844 : 21 : pat = GEN_FCN (icode) (op0, op1, op2);
14845 : : }
14846 : : else
14847 : : {
14848 : 0 : icode = CODE_FOR_xsetbv;
14849 : :
14850 : 0 : pat = GEN_FCN (icode) (op0, op1);
14851 : : }
14852 : 21 : if (pat)
14853 : 21 : emit_insn (pat);
14854 : : return 0;
14855 : :
14856 : 232 : case IX86_BUILTIN_XSAVE:
14857 : 232 : case IX86_BUILTIN_XRSTOR:
14858 : 232 : case IX86_BUILTIN_XSAVE64:
14859 : 232 : case IX86_BUILTIN_XRSTOR64:
14860 : 232 : case IX86_BUILTIN_XSAVEOPT:
14861 : 232 : case IX86_BUILTIN_XSAVEOPT64:
14862 : 232 : case IX86_BUILTIN_XSAVES:
14863 : 232 : case IX86_BUILTIN_XRSTORS:
14864 : 232 : case IX86_BUILTIN_XSAVES64:
14865 : 232 : case IX86_BUILTIN_XRSTORS64:
14866 : 232 : case IX86_BUILTIN_XSAVEC:
14867 : 232 : case IX86_BUILTIN_XSAVEC64:
14868 : 232 : arg0 = CALL_EXPR_ARG (exp, 0);
14869 : 232 : arg1 = CALL_EXPR_ARG (exp, 1);
14870 : 232 : op0 = expand_normal (arg0);
14871 : 232 : op1 = expand_normal (arg1);
14872 : :
14873 : 232 : if (!address_operand (op0, VOIDmode))
14874 : : {
14875 : 108 : op0 = convert_memory_address (Pmode, op0);
14876 : 108 : op0 = copy_addr_to_reg (op0);
14877 : : }
14878 : 232 : op0 = gen_rtx_MEM (BLKmode, op0);
14879 : :
14880 : 232 : op1 = force_reg (DImode, op1);
14881 : :
14882 : 232 : if (TARGET_64BIT)
14883 : : {
14884 : 232 : op2 = expand_simple_binop (DImode, LSHIFTRT, op1, GEN_INT (32),
14885 : : NULL, 1, OPTAB_DIRECT);
14886 : 232 : switch (fcode)
14887 : : {
14888 : : case IX86_BUILTIN_XSAVE:
14889 : : icode = CODE_FOR_xsave_rex64;
14890 : : break;
14891 : 19 : case IX86_BUILTIN_XRSTOR:
14892 : 19 : icode = CODE_FOR_xrstor_rex64;
14893 : 19 : break;
14894 : 21 : case IX86_BUILTIN_XSAVE64:
14895 : 21 : icode = CODE_FOR_xsave64;
14896 : 21 : break;
14897 : 21 : case IX86_BUILTIN_XRSTOR64:
14898 : 21 : icode = CODE_FOR_xrstor64;
14899 : 21 : break;
14900 : 19 : case IX86_BUILTIN_XSAVEOPT:
14901 : 19 : icode = CODE_FOR_xsaveopt_rex64;
14902 : 19 : break;
14903 : 19 : case IX86_BUILTIN_XSAVEOPT64:
14904 : 19 : icode = CODE_FOR_xsaveopt64;
14905 : 19 : break;
14906 : 19 : case IX86_BUILTIN_XSAVES:
14907 : 19 : icode = CODE_FOR_xsaves_rex64;
14908 : 19 : break;
14909 : 19 : case IX86_BUILTIN_XRSTORS:
14910 : 19 : icode = CODE_FOR_xrstors_rex64;
14911 : 19 : break;
14912 : 19 : case IX86_BUILTIN_XSAVES64:
14913 : 19 : icode = CODE_FOR_xsaves64;
14914 : 19 : break;
14915 : 19 : case IX86_BUILTIN_XRSTORS64:
14916 : 19 : icode = CODE_FOR_xrstors64;
14917 : 19 : break;
14918 : 19 : case IX86_BUILTIN_XSAVEC:
14919 : 19 : icode = CODE_FOR_xsavec_rex64;
14920 : 19 : break;
14921 : 19 : case IX86_BUILTIN_XSAVEC64:
14922 : 19 : icode = CODE_FOR_xsavec64;
14923 : 19 : break;
14924 : 0 : default:
14925 : 0 : gcc_unreachable ();
14926 : : }
14927 : :
14928 : 232 : op2 = gen_lowpart (SImode, op2);
14929 : 232 : op1 = gen_lowpart (SImode, op1);
14930 : 232 : pat = GEN_FCN (icode) (op0, op1, op2);
14931 : : }
14932 : : else
14933 : : {
14934 : 0 : switch (fcode)
14935 : : {
14936 : : case IX86_BUILTIN_XSAVE:
14937 : : icode = CODE_FOR_xsave;
14938 : : break;
14939 : : case IX86_BUILTIN_XRSTOR:
14940 : : icode = CODE_FOR_xrstor;
14941 : : break;
14942 : : case IX86_BUILTIN_XSAVEOPT:
14943 : : icode = CODE_FOR_xsaveopt;
14944 : : break;
14945 : : case IX86_BUILTIN_XSAVES:
14946 : : icode = CODE_FOR_xsaves;
14947 : : break;
14948 : : case IX86_BUILTIN_XRSTORS:
14949 : : icode = CODE_FOR_xrstors;
14950 : : break;
14951 : : case IX86_BUILTIN_XSAVEC:
14952 : : icode = CODE_FOR_xsavec;
14953 : : break;
14954 : 0 : default:
14955 : 0 : gcc_unreachable ();
14956 : : }
14957 : 0 : pat = GEN_FCN (icode) (op0, op1);
14958 : : }
14959 : :
14960 : 232 : if (pat)
14961 : 232 : emit_insn (pat);
14962 : : return 0;
14963 : :
14964 : 83 : case IX86_BUILTIN_LDTILECFG:
14965 : 83 : case IX86_BUILTIN_STTILECFG:
14966 : 83 : arg0 = CALL_EXPR_ARG (exp, 0);
14967 : 83 : op0 = expand_normal (arg0);
14968 : :
14969 : 83 : if (!address_operand (op0, VOIDmode))
14970 : : {
14971 : 8 : op0 = convert_memory_address (Pmode, op0);
14972 : 8 : op0 = copy_addr_to_reg (op0);
14973 : : }
14974 : 83 : op0 = gen_rtx_MEM (BLKmode, op0);
14975 : 83 : if (fcode == IX86_BUILTIN_LDTILECFG)
14976 : : icode = CODE_FOR_ldtilecfg;
14977 : : else
14978 : 52 : icode = CODE_FOR_sttilecfg;
14979 : 83 : pat = GEN_FCN (icode) (op0);
14980 : 83 : emit_insn (pat);
14981 : 83 : return 0;
14982 : :
14983 : 18 : case IX86_BUILTIN_LLWPCB:
14984 : 18 : arg0 = CALL_EXPR_ARG (exp, 0);
14985 : 18 : op0 = expand_normal (arg0);
14986 : :
14987 : 18 : if (!register_operand (op0, Pmode))
14988 : 9 : op0 = ix86_zero_extend_to_Pmode (op0);
14989 : 18 : emit_insn (gen_lwp_llwpcb (Pmode, op0));
14990 : 18 : return 0;
14991 : :
14992 : 18 : case IX86_BUILTIN_SLWPCB:
14993 : 18 : if (!target
14994 : 18 : || !register_operand (target, Pmode))
14995 : 0 : target = gen_reg_rtx (Pmode);
14996 : 18 : emit_insn (gen_lwp_slwpcb (Pmode, target));
14997 : 18 : return target;
14998 : :
14999 : 51 : case IX86_BUILTIN_LWPVAL32:
15000 : 51 : case IX86_BUILTIN_LWPVAL64:
15001 : 51 : case IX86_BUILTIN_LWPINS32:
15002 : 51 : case IX86_BUILTIN_LWPINS64:
15003 : 51 : mode = ((fcode == IX86_BUILTIN_LWPVAL32
15004 : 51 : || fcode == IX86_BUILTIN_LWPINS32)
15005 : 51 : ? SImode : DImode);
15006 : :
15007 : 51 : if (fcode == IX86_BUILTIN_LWPVAL32
15008 : 51 : || fcode == IX86_BUILTIN_LWPVAL64)
15009 : 26 : icode = code_for_lwp_lwpval (mode);
15010 : : else
15011 : 25 : icode = code_for_lwp_lwpins (mode);
15012 : :
15013 : 51 : arg0 = CALL_EXPR_ARG (exp, 0);
15014 : 51 : arg1 = CALL_EXPR_ARG (exp, 1);
15015 : 51 : arg2 = CALL_EXPR_ARG (exp, 2);
15016 : 51 : op0 = expand_normal (arg0);
15017 : 51 : op1 = expand_normal (arg1);
15018 : 51 : op2 = expand_normal (arg2);
15019 : 51 : mode0 = insn_data[icode].operand[0].mode;
15020 : :
15021 : 51 : if (!insn_data[icode].operand[0].predicate (op0, mode0))
15022 : 13 : op0 = copy_to_mode_reg (mode0, op0);
15023 : 51 : if (!insn_data[icode].operand[1].predicate (op1, SImode))
15024 : 0 : op1 = copy_to_mode_reg (SImode, op1);
15025 : :
15026 : 51 : if (!CONST_INT_P (op2))
15027 : : {
15028 : 0 : error ("the last argument must be a 32-bit immediate");
15029 : 0 : return const0_rtx;
15030 : : }
15031 : :
15032 : 51 : emit_insn (GEN_FCN (icode) (op0, op1, op2));
15033 : :
15034 : 51 : if (fcode == IX86_BUILTIN_LWPINS32
15035 : 51 : || fcode == IX86_BUILTIN_LWPINS64)
15036 : : {
15037 : 25 : if (target == 0
15038 : 25 : || !nonimmediate_operand (target, QImode))
15039 : 0 : target = gen_reg_rtx (QImode);
15040 : :
15041 : 25 : pat = gen_rtx_EQ (QImode, gen_rtx_REG (CCCmode, FLAGS_REG),
15042 : : const0_rtx);
15043 : 25 : emit_insn (gen_rtx_SET (target, pat));
15044 : :
15045 : 25 : return target;
15046 : : }
15047 : : else
15048 : : return 0;
15049 : :
15050 : 18 : case IX86_BUILTIN_BEXTRI32:
15051 : 18 : case IX86_BUILTIN_BEXTRI64:
15052 : 18 : mode = (fcode == IX86_BUILTIN_BEXTRI32 ? SImode : DImode);
15053 : :
15054 : 18 : arg0 = CALL_EXPR_ARG (exp, 0);
15055 : 18 : arg1 = CALL_EXPR_ARG (exp, 1);
15056 : 18 : op0 = expand_normal (arg0);
15057 : 18 : op1 = expand_normal (arg1);
15058 : :
15059 : 18 : if (!CONST_INT_P (op1))
15060 : : {
15061 : 0 : error ("last argument must be an immediate");
15062 : 0 : return const0_rtx;
15063 : : }
15064 : : else
15065 : : {
15066 : 18 : unsigned char lsb_index = UINTVAL (op1);
15067 : 18 : unsigned char length = UINTVAL (op1) >> 8;
15068 : :
15069 : 18 : unsigned char bitsize = GET_MODE_BITSIZE (mode);
15070 : :
15071 : 18 : icode = code_for_tbm_bextri (mode);
15072 : :
15073 : 18 : mode1 = insn_data[icode].operand[1].mode;
15074 : 18 : if (!insn_data[icode].operand[1].predicate (op0, mode1))
15075 : 12 : op0 = copy_to_mode_reg (mode1, op0);
15076 : :
15077 : 18 : mode0 = insn_data[icode].operand[0].mode;
15078 : 18 : if (target == 0
15079 : 18 : || !register_operand (target, mode0))
15080 : 0 : target = gen_reg_rtx (mode0);
15081 : :
15082 : 18 : if (length == 0 || lsb_index >= bitsize)
15083 : : {
15084 : 8 : emit_move_insn (target, const0_rtx);
15085 : 8 : return target;
15086 : : }
15087 : :
15088 : 10 : if (length + lsb_index > bitsize)
15089 : 5 : length = bitsize - lsb_index;
15090 : :
15091 : 10 : op1 = GEN_INT (length);
15092 : 10 : op2 = GEN_INT (lsb_index);
15093 : :
15094 : 10 : emit_insn (GEN_FCN (icode) (target, op0, op1, op2));
15095 : 10 : return target;
15096 : : }
15097 : :
15098 : 21 : case IX86_BUILTIN_RDRAND16_STEP:
15099 : 21 : mode = HImode;
15100 : 21 : goto rdrand_step;
15101 : :
15102 : 42 : case IX86_BUILTIN_RDRAND32_STEP:
15103 : 42 : mode = SImode;
15104 : 42 : goto rdrand_step;
15105 : :
15106 : : case IX86_BUILTIN_RDRAND64_STEP:
15107 : : mode = DImode;
15108 : :
15109 : 83 : rdrand_step:
15110 : 83 : arg0 = CALL_EXPR_ARG (exp, 0);
15111 : 83 : op1 = expand_normal (arg0);
15112 : 83 : if (!address_operand (op1, VOIDmode))
15113 : : {
15114 : 29 : op1 = convert_memory_address (Pmode, op1);
15115 : 29 : op1 = copy_addr_to_reg (op1);
15116 : : }
15117 : :
15118 : 83 : op0 = gen_reg_rtx (mode);
15119 : 83 : emit_insn (gen_rdrand (mode, op0));
15120 : :
15121 : 83 : emit_move_insn (gen_rtx_MEM (mode, op1), op0);
15122 : :
15123 : 83 : op1 = force_reg (SImode, const1_rtx);
15124 : :
15125 : : /* Emit SImode conditional move. */
15126 : 83 : if (mode == HImode)
15127 : : {
15128 : 21 : if (TARGET_ZERO_EXTEND_WITH_AND
15129 : 21 : && optimize_function_for_speed_p (cfun))
15130 : : {
15131 : 0 : op2 = force_reg (SImode, const0_rtx);
15132 : :
15133 : 0 : emit_insn (gen_movstricthi
15134 : 0 : (gen_lowpart (HImode, op2), op0));
15135 : : }
15136 : : else
15137 : : {
15138 : 21 : op2 = gen_reg_rtx (SImode);
15139 : :
15140 : 21 : emit_insn (gen_zero_extendhisi2 (op2, op0));
15141 : : }
15142 : : }
15143 : 62 : else if (mode == SImode)
15144 : : op2 = op0;
15145 : : else
15146 : 20 : op2 = gen_rtx_SUBREG (SImode, op0, 0);
15147 : :
15148 : 83 : if (target == 0
15149 : 83 : || !register_operand (target, SImode))
15150 : 7 : target = gen_reg_rtx (SImode);
15151 : :
15152 : 83 : pat = gen_rtx_GEU (VOIDmode, gen_rtx_REG (CCCmode, FLAGS_REG),
15153 : : const0_rtx);
15154 : 83 : emit_insn (gen_rtx_SET (target,
15155 : : gen_rtx_IF_THEN_ELSE (SImode, pat, op2, op1)));
15156 : 83 : return target;
15157 : :
15158 : 19 : case IX86_BUILTIN_RDSEED16_STEP:
15159 : 19 : mode = HImode;
15160 : 19 : goto rdseed_step;
15161 : :
15162 : 28 : case IX86_BUILTIN_RDSEED32_STEP:
15163 : 28 : mode = SImode;
15164 : 28 : goto rdseed_step;
15165 : :
15166 : : case IX86_BUILTIN_RDSEED64_STEP:
15167 : : mode = DImode;
15168 : :
15169 : 66 : rdseed_step:
15170 : 66 : arg0 = CALL_EXPR_ARG (exp, 0);
15171 : 66 : op1 = expand_normal (arg0);
15172 : 66 : if (!address_operand (op1, VOIDmode))
15173 : : {
15174 : 28 : op1 = convert_memory_address (Pmode, op1);
15175 : 28 : op1 = copy_addr_to_reg (op1);
15176 : : }
15177 : :
15178 : 66 : op0 = gen_reg_rtx (mode);
15179 : 66 : emit_insn (gen_rdseed (mode, op0));
15180 : :
15181 : 66 : emit_move_insn (gen_rtx_MEM (mode, op1), op0);
15182 : :
15183 : 66 : op2 = gen_reg_rtx (QImode);
15184 : :
15185 : 66 : pat = gen_rtx_LTU (QImode, gen_rtx_REG (CCCmode, FLAGS_REG),
15186 : : const0_rtx);
15187 : 66 : emit_insn (gen_rtx_SET (op2, pat));
15188 : :
15189 : 66 : if (target == 0
15190 : 66 : || !register_operand (target, SImode))
15191 : 1 : target = gen_reg_rtx (SImode);
15192 : :
15193 : 66 : emit_insn (gen_zero_extendqisi2 (target, op2));
15194 : 66 : return target;
15195 : :
15196 : 38 : case IX86_BUILTIN_SBB32:
15197 : 38 : icode = CODE_FOR_subborrowsi;
15198 : 38 : icode2 = CODE_FOR_subborrowsi_0;
15199 : 38 : mode0 = SImode;
15200 : 38 : mode1 = DImode;
15201 : 38 : mode2 = CCmode;
15202 : 38 : goto handlecarry;
15203 : :
15204 : 44 : case IX86_BUILTIN_SBB64:
15205 : 44 : icode = CODE_FOR_subborrowdi;
15206 : 44 : icode2 = CODE_FOR_subborrowdi_0;
15207 : 44 : mode0 = DImode;
15208 : 44 : mode1 = TImode;
15209 : 44 : mode2 = CCmode;
15210 : 44 : goto handlecarry;
15211 : :
15212 : 69 : case IX86_BUILTIN_ADDCARRYX32:
15213 : 69 : icode = CODE_FOR_addcarrysi;
15214 : 69 : icode2 = CODE_FOR_addcarrysi_0;
15215 : 69 : mode0 = SImode;
15216 : 69 : mode1 = DImode;
15217 : 69 : mode2 = CCCmode;
15218 : 69 : goto handlecarry;
15219 : :
15220 : : case IX86_BUILTIN_ADDCARRYX64:
15221 : : icode = CODE_FOR_addcarrydi;
15222 : : icode2 = CODE_FOR_addcarrydi_0;
15223 : : mode0 = DImode;
15224 : : mode1 = TImode;
15225 : : mode2 = CCCmode;
15226 : :
15227 : 213 : handlecarry:
15228 : 213 : arg0 = CALL_EXPR_ARG (exp, 0); /* unsigned char c_in. */
15229 : 213 : arg1 = CALL_EXPR_ARG (exp, 1); /* unsigned int src1. */
15230 : 213 : arg2 = CALL_EXPR_ARG (exp, 2); /* unsigned int src2. */
15231 : 213 : arg3 = CALL_EXPR_ARG (exp, 3); /* unsigned int *sum_out. */
15232 : :
15233 : 213 : op1 = expand_normal (arg0);
15234 : :
15235 : 213 : op2 = expand_normal (arg1);
15236 : 213 : if (!register_operand (op2, mode0))
15237 : 118 : op2 = copy_to_mode_reg (mode0, op2);
15238 : :
15239 : 213 : op3 = expand_normal (arg2);
15240 : 213 : if (!register_operand (op3, mode0))
15241 : 121 : op3 = copy_to_mode_reg (mode0, op3);
15242 : :
15243 : 213 : op4 = expand_normal (arg3);
15244 : 213 : if (!address_operand (op4, VOIDmode))
15245 : : {
15246 : 68 : op4 = convert_memory_address (Pmode, op4);
15247 : 68 : op4 = copy_addr_to_reg (op4);
15248 : : }
15249 : :
15250 : 213 : op0 = gen_reg_rtx (mode0);
15251 : 213 : if (op1 == const0_rtx)
15252 : : {
15253 : : /* If arg0 is 0, optimize right away into add or sub
15254 : : instruction that sets CCCmode flags. */
15255 : 21 : op1 = gen_rtx_REG (mode2, FLAGS_REG);
15256 : 21 : emit_insn (GEN_FCN (icode2) (op0, op2, op3));
15257 : : }
15258 : : else
15259 : : {
15260 : : /* Generate CF from input operand. */
15261 : 192 : ix86_expand_carry (op1);
15262 : :
15263 : : /* Generate instruction that consumes CF. */
15264 : 192 : op1 = gen_rtx_REG (CCCmode, FLAGS_REG);
15265 : 192 : pat = gen_rtx_LTU (mode1, op1, const0_rtx);
15266 : 192 : pat2 = gen_rtx_LTU (mode0, op1, const0_rtx);
15267 : 192 : emit_insn (GEN_FCN (icode) (op0, op2, op3, op1, pat, pat2));
15268 : : }
15269 : :
15270 : : /* Return current CF value. */
15271 : 213 : if (target == 0)
15272 : 14 : target = gen_reg_rtx (QImode);
15273 : :
15274 : 213 : pat = gen_rtx_LTU (QImode, op1, const0_rtx);
15275 : 213 : emit_insn (gen_rtx_SET (target, pat));
15276 : :
15277 : : /* Store the result. */
15278 : 213 : emit_move_insn (gen_rtx_MEM (mode0, op4), op0);
15279 : :
15280 : 213 : return target;
15281 : :
15282 : 24 : case IX86_BUILTIN_READ_FLAGS:
15283 : 24 : if (ignore)
15284 : 1 : return const0_rtx;
15285 : :
15286 : 23 : emit_insn (gen_pushfl ());
15287 : :
15288 : 23 : if (optimize
15289 : 11 : || target == NULL_RTX
15290 : 11 : || !nonimmediate_operand (target, word_mode)
15291 : 34 : || GET_MODE (target) != word_mode)
15292 : 12 : target = gen_reg_rtx (word_mode);
15293 : :
15294 : 23 : emit_insn (gen_pop (target));
15295 : 23 : return target;
15296 : :
15297 : 21 : case IX86_BUILTIN_WRITE_FLAGS:
15298 : :
15299 : 21 : arg0 = CALL_EXPR_ARG (exp, 0);
15300 : 21 : op0 = expand_normal (arg0);
15301 : 21 : if (!general_no_elim_operand (op0, word_mode))
15302 : 0 : op0 = copy_to_mode_reg (word_mode, op0);
15303 : :
15304 : 21 : emit_insn (gen_push (op0));
15305 : 21 : emit_insn (gen_popfl ());
15306 : 21 : return 0;
15307 : :
15308 : 22 : case IX86_BUILTIN_KTESTC8:
15309 : 22 : icode = CODE_FOR_ktestqi;
15310 : 22 : mode3 = CCCmode;
15311 : 22 : goto kortest;
15312 : :
15313 : 22 : case IX86_BUILTIN_KTESTZ8:
15314 : 22 : icode = CODE_FOR_ktestqi;
15315 : 22 : mode3 = CCZmode;
15316 : 22 : goto kortest;
15317 : :
15318 : 22 : case IX86_BUILTIN_KTESTC16:
15319 : 22 : icode = CODE_FOR_ktesthi;
15320 : 22 : mode3 = CCCmode;
15321 : 22 : goto kortest;
15322 : :
15323 : 22 : case IX86_BUILTIN_KTESTZ16:
15324 : 22 : icode = CODE_FOR_ktesthi;
15325 : 22 : mode3 = CCZmode;
15326 : 22 : goto kortest;
15327 : :
15328 : 22 : case IX86_BUILTIN_KTESTC32:
15329 : 22 : icode = CODE_FOR_ktestsi;
15330 : 22 : mode3 = CCCmode;
15331 : 22 : goto kortest;
15332 : :
15333 : 22 : case IX86_BUILTIN_KTESTZ32:
15334 : 22 : icode = CODE_FOR_ktestsi;
15335 : 22 : mode3 = CCZmode;
15336 : 22 : goto kortest;
15337 : :
15338 : 22 : case IX86_BUILTIN_KTESTC64:
15339 : 22 : icode = CODE_FOR_ktestdi;
15340 : 22 : mode3 = CCCmode;
15341 : 22 : goto kortest;
15342 : :
15343 : 22 : case IX86_BUILTIN_KTESTZ64:
15344 : 22 : icode = CODE_FOR_ktestdi;
15345 : 22 : mode3 = CCZmode;
15346 : 22 : goto kortest;
15347 : :
15348 : 22 : case IX86_BUILTIN_KORTESTC8:
15349 : 22 : icode = CODE_FOR_kortestqi;
15350 : 22 : mode3 = CCCmode;
15351 : 22 : goto kortest;
15352 : :
15353 : 76 : case IX86_BUILTIN_KORTESTZ8:
15354 : 76 : icode = CODE_FOR_kortestqi;
15355 : 76 : mode3 = CCZmode;
15356 : 76 : goto kortest;
15357 : :
15358 : 38 : case IX86_BUILTIN_KORTESTC16:
15359 : 38 : icode = CODE_FOR_kortesthi;
15360 : 38 : mode3 = CCCmode;
15361 : 38 : goto kortest;
15362 : :
15363 : 91 : case IX86_BUILTIN_KORTESTZ16:
15364 : 91 : icode = CODE_FOR_kortesthi;
15365 : 91 : mode3 = CCZmode;
15366 : 91 : goto kortest;
15367 : :
15368 : 22 : case IX86_BUILTIN_KORTESTC32:
15369 : 22 : icode = CODE_FOR_kortestsi;
15370 : 22 : mode3 = CCCmode;
15371 : 22 : goto kortest;
15372 : :
15373 : 79 : case IX86_BUILTIN_KORTESTZ32:
15374 : 79 : icode = CODE_FOR_kortestsi;
15375 : 79 : mode3 = CCZmode;
15376 : 79 : goto kortest;
15377 : :
15378 : 22 : case IX86_BUILTIN_KORTESTC64:
15379 : 22 : icode = CODE_FOR_kortestdi;
15380 : 22 : mode3 = CCCmode;
15381 : 22 : goto kortest;
15382 : :
15383 : : case IX86_BUILTIN_KORTESTZ64:
15384 : : icode = CODE_FOR_kortestdi;
15385 : : mode3 = CCZmode;
15386 : :
15387 : 610 : kortest:
15388 : 610 : arg0 = CALL_EXPR_ARG (exp, 0); /* Mask reg src1. */
15389 : 610 : arg1 = CALL_EXPR_ARG (exp, 1); /* Mask reg src2. */
15390 : 610 : op0 = expand_normal (arg0);
15391 : 610 : op1 = expand_normal (arg1);
15392 : :
15393 : 610 : mode0 = insn_data[icode].operand[0].mode;
15394 : 610 : mode1 = insn_data[icode].operand[1].mode;
15395 : :
15396 : 610 : if (GET_MODE (op0) != VOIDmode)
15397 : 610 : op0 = force_reg (GET_MODE (op0), op0);
15398 : :
15399 : 610 : op0 = gen_lowpart (mode0, op0);
15400 : :
15401 : 610 : if (!insn_data[icode].operand[0].predicate (op0, mode0))
15402 : 0 : op0 = copy_to_mode_reg (mode0, op0);
15403 : :
15404 : 610 : if (GET_MODE (op1) != VOIDmode)
15405 : 609 : op1 = force_reg (GET_MODE (op1), op1);
15406 : :
15407 : 610 : op1 = gen_lowpart (mode1, op1);
15408 : :
15409 : 610 : if (!insn_data[icode].operand[1].predicate (op1, mode1))
15410 : 1 : op1 = copy_to_mode_reg (mode1, op1);
15411 : :
15412 : 610 : target = gen_reg_rtx (QImode);
15413 : :
15414 : : /* Emit kortest. */
15415 : 610 : emit_insn (GEN_FCN (icode) (op0, op1));
15416 : : /* And use setcc to return result from flags. */
15417 : 610 : ix86_expand_setcc (target, EQ,
15418 : : gen_rtx_REG (mode3, FLAGS_REG), const0_rtx);
15419 : 610 : return target;
15420 : :
15421 : 24 : case IX86_BUILTIN_GATHERSIV2DF:
15422 : 24 : icode = CODE_FOR_avx2_gathersiv2df;
15423 : 24 : goto gather_gen;
15424 : 18 : case IX86_BUILTIN_GATHERSIV4DF:
15425 : 18 : icode = CODE_FOR_avx2_gathersiv4df;
15426 : 18 : goto gather_gen;
15427 : 21 : case IX86_BUILTIN_GATHERDIV2DF:
15428 : 21 : icode = CODE_FOR_avx2_gatherdiv2df;
15429 : 21 : goto gather_gen;
15430 : 32 : case IX86_BUILTIN_GATHERDIV4DF:
15431 : 32 : icode = CODE_FOR_avx2_gatherdiv4df;
15432 : 32 : goto gather_gen;
15433 : 29 : case IX86_BUILTIN_GATHERSIV4SF:
15434 : 29 : icode = CODE_FOR_avx2_gathersiv4sf;
15435 : 29 : goto gather_gen;
15436 : 36 : case IX86_BUILTIN_GATHERSIV8SF:
15437 : 36 : icode = CODE_FOR_avx2_gathersiv8sf;
15438 : 36 : goto gather_gen;
15439 : 24 : case IX86_BUILTIN_GATHERDIV4SF:
15440 : 24 : icode = CODE_FOR_avx2_gatherdiv4sf;
15441 : 24 : goto gather_gen;
15442 : 18 : case IX86_BUILTIN_GATHERDIV8SF:
15443 : 18 : icode = CODE_FOR_avx2_gatherdiv8sf;
15444 : 18 : goto gather_gen;
15445 : 18 : case IX86_BUILTIN_GATHERSIV2DI:
15446 : 18 : icode = CODE_FOR_avx2_gathersiv2di;
15447 : 18 : goto gather_gen;
15448 : 18 : case IX86_BUILTIN_GATHERSIV4DI:
15449 : 18 : icode = CODE_FOR_avx2_gathersiv4di;
15450 : 18 : goto gather_gen;
15451 : 27 : case IX86_BUILTIN_GATHERDIV2DI:
15452 : 27 : icode = CODE_FOR_avx2_gatherdiv2di;
15453 : 27 : goto gather_gen;
15454 : 29 : case IX86_BUILTIN_GATHERDIV4DI:
15455 : 29 : icode = CODE_FOR_avx2_gatherdiv4di;
15456 : 29 : goto gather_gen;
15457 : 20 : case IX86_BUILTIN_GATHERSIV4SI:
15458 : 20 : icode = CODE_FOR_avx2_gathersiv4si;
15459 : 20 : goto gather_gen;
15460 : 22 : case IX86_BUILTIN_GATHERSIV8SI:
15461 : 22 : icode = CODE_FOR_avx2_gathersiv8si;
15462 : 22 : goto gather_gen;
15463 : 28 : case IX86_BUILTIN_GATHERDIV4SI:
15464 : 28 : icode = CODE_FOR_avx2_gatherdiv4si;
15465 : 28 : goto gather_gen;
15466 : 18 : case IX86_BUILTIN_GATHERDIV8SI:
15467 : 18 : icode = CODE_FOR_avx2_gatherdiv8si;
15468 : 18 : goto gather_gen;
15469 : 20 : case IX86_BUILTIN_GATHERALTSIV4DF:
15470 : 20 : icode = CODE_FOR_avx2_gathersiv4df;
15471 : 20 : goto gather_gen;
15472 : 16 : case IX86_BUILTIN_GATHERALTDIV8SF:
15473 : 16 : icode = CODE_FOR_avx2_gatherdiv8sf;
15474 : 16 : goto gather_gen;
15475 : 4 : case IX86_BUILTIN_GATHERALTSIV4DI:
15476 : 4 : icode = CODE_FOR_avx2_gathersiv4di;
15477 : 4 : goto gather_gen;
15478 : 10 : case IX86_BUILTIN_GATHERALTDIV8SI:
15479 : 10 : icode = CODE_FOR_avx2_gatherdiv8si;
15480 : 10 : goto gather_gen;
15481 : 36 : case IX86_BUILTIN_GATHER3SIV16SF:
15482 : 36 : icode = CODE_FOR_avx512f_gathersiv16sf;
15483 : 36 : goto gather_gen;
15484 : 24 : case IX86_BUILTIN_GATHER3SIV8DF:
15485 : 24 : icode = CODE_FOR_avx512f_gathersiv8df;
15486 : 24 : goto gather_gen;
15487 : 24 : case IX86_BUILTIN_GATHER3DIV16SF:
15488 : 24 : icode = CODE_FOR_avx512f_gatherdiv16sf;
15489 : 24 : goto gather_gen;
15490 : 37 : case IX86_BUILTIN_GATHER3DIV8DF:
15491 : 37 : icode = CODE_FOR_avx512f_gatherdiv8df;
15492 : 37 : goto gather_gen;
15493 : 30 : case IX86_BUILTIN_GATHER3SIV16SI:
15494 : 30 : icode = CODE_FOR_avx512f_gathersiv16si;
15495 : 30 : goto gather_gen;
15496 : 24 : case IX86_BUILTIN_GATHER3SIV8DI:
15497 : 24 : icode = CODE_FOR_avx512f_gathersiv8di;
15498 : 24 : goto gather_gen;
15499 : 24 : case IX86_BUILTIN_GATHER3DIV16SI:
15500 : 24 : icode = CODE_FOR_avx512f_gatherdiv16si;
15501 : 24 : goto gather_gen;
15502 : 37 : case IX86_BUILTIN_GATHER3DIV8DI:
15503 : 37 : icode = CODE_FOR_avx512f_gatherdiv8di;
15504 : 37 : goto gather_gen;
15505 : 16 : case IX86_BUILTIN_GATHER3ALTSIV8DF:
15506 : 16 : icode = CODE_FOR_avx512f_gathersiv8df;
15507 : 16 : goto gather_gen;
15508 : 22 : case IX86_BUILTIN_GATHER3ALTDIV16SF:
15509 : 22 : icode = CODE_FOR_avx512f_gatherdiv16sf;
15510 : 22 : goto gather_gen;
15511 : 14 : case IX86_BUILTIN_GATHER3ALTSIV8DI:
15512 : 14 : icode = CODE_FOR_avx512f_gathersiv8di;
15513 : 14 : goto gather_gen;
15514 : 20 : case IX86_BUILTIN_GATHER3ALTDIV16SI:
15515 : 20 : icode = CODE_FOR_avx512f_gatherdiv16si;
15516 : 20 : goto gather_gen;
15517 : 18 : case IX86_BUILTIN_GATHER3SIV2DF:
15518 : 18 : icode = CODE_FOR_avx512vl_gathersiv2df;
15519 : 18 : goto gather_gen;
15520 : 10 : case IX86_BUILTIN_GATHER3SIV4DF:
15521 : 10 : icode = CODE_FOR_avx512vl_gathersiv4df;
15522 : 10 : goto gather_gen;
15523 : 15 : case IX86_BUILTIN_GATHER3DIV2DF:
15524 : 15 : icode = CODE_FOR_avx512vl_gatherdiv2df;
15525 : 15 : goto gather_gen;
15526 : 16 : case IX86_BUILTIN_GATHER3DIV4DF:
15527 : 16 : icode = CODE_FOR_avx512vl_gatherdiv4df;
15528 : 16 : goto gather_gen;
15529 : 14 : case IX86_BUILTIN_GATHER3SIV4SF:
15530 : 14 : icode = CODE_FOR_avx512vl_gathersiv4sf;
15531 : 14 : goto gather_gen;
15532 : 12 : case IX86_BUILTIN_GATHER3SIV8SF:
15533 : 12 : icode = CODE_FOR_avx512vl_gathersiv8sf;
15534 : 12 : goto gather_gen;
15535 : 22 : case IX86_BUILTIN_GATHER3DIV4SF:
15536 : 22 : icode = CODE_FOR_avx512vl_gatherdiv4sf;
15537 : 22 : goto gather_gen;
15538 : 10 : case IX86_BUILTIN_GATHER3DIV8SF:
15539 : 10 : icode = CODE_FOR_avx512vl_gatherdiv8sf;
15540 : 10 : goto gather_gen;
15541 : 20 : case IX86_BUILTIN_GATHER3SIV2DI:
15542 : 20 : icode = CODE_FOR_avx512vl_gathersiv2di;
15543 : 20 : goto gather_gen;
15544 : 10 : case IX86_BUILTIN_GATHER3SIV4DI:
15545 : 10 : icode = CODE_FOR_avx512vl_gathersiv4di;
15546 : 10 : goto gather_gen;
15547 : 14 : case IX86_BUILTIN_GATHER3DIV2DI:
15548 : 14 : icode = CODE_FOR_avx512vl_gatherdiv2di;
15549 : 14 : goto gather_gen;
15550 : 13 : case IX86_BUILTIN_GATHER3DIV4DI:
15551 : 13 : icode = CODE_FOR_avx512vl_gatherdiv4di;
15552 : 13 : goto gather_gen;
15553 : 14 : case IX86_BUILTIN_GATHER3SIV4SI:
15554 : 14 : icode = CODE_FOR_avx512vl_gathersiv4si;
15555 : 14 : goto gather_gen;
15556 : 12 : case IX86_BUILTIN_GATHER3SIV8SI:
15557 : 12 : icode = CODE_FOR_avx512vl_gathersiv8si;
15558 : 12 : goto gather_gen;
15559 : 24 : case IX86_BUILTIN_GATHER3DIV4SI:
15560 : 24 : icode = CODE_FOR_avx512vl_gatherdiv4si;
15561 : 24 : goto gather_gen;
15562 : 10 : case IX86_BUILTIN_GATHER3DIV8SI:
15563 : 10 : icode = CODE_FOR_avx512vl_gatherdiv8si;
15564 : 10 : goto gather_gen;
15565 : 4 : case IX86_BUILTIN_GATHER3ALTSIV4DF:
15566 : 4 : icode = CODE_FOR_avx512vl_gathersiv4df;
15567 : 4 : goto gather_gen;
15568 : 8 : case IX86_BUILTIN_GATHER3ALTDIV8SF:
15569 : 8 : icode = CODE_FOR_avx512vl_gatherdiv8sf;
15570 : 8 : goto gather_gen;
15571 : 6 : case IX86_BUILTIN_GATHER3ALTSIV4DI:
15572 : 6 : icode = CODE_FOR_avx512vl_gathersiv4di;
15573 : 6 : goto gather_gen;
15574 : 10 : case IX86_BUILTIN_GATHER3ALTDIV8SI:
15575 : 10 : icode = CODE_FOR_avx512vl_gatherdiv8si;
15576 : 10 : goto gather_gen;
15577 : 40 : case IX86_BUILTIN_SCATTERSIV16SF:
15578 : 40 : icode = CODE_FOR_avx512f_scattersiv16sf;
15579 : 40 : goto scatter_gen;
15580 : 27 : case IX86_BUILTIN_SCATTERSIV8DF:
15581 : 27 : icode = CODE_FOR_avx512f_scattersiv8df;
15582 : 27 : goto scatter_gen;
15583 : 24 : case IX86_BUILTIN_SCATTERDIV16SF:
15584 : 24 : icode = CODE_FOR_avx512f_scatterdiv16sf;
15585 : 24 : goto scatter_gen;
15586 : 41 : case IX86_BUILTIN_SCATTERDIV8DF:
15587 : 41 : icode = CODE_FOR_avx512f_scatterdiv8df;
15588 : 41 : goto scatter_gen;
15589 : 30 : case IX86_BUILTIN_SCATTERSIV16SI:
15590 : 30 : icode = CODE_FOR_avx512f_scattersiv16si;
15591 : 30 : goto scatter_gen;
15592 : 24 : case IX86_BUILTIN_SCATTERSIV8DI:
15593 : 24 : icode = CODE_FOR_avx512f_scattersiv8di;
15594 : 24 : goto scatter_gen;
15595 : 24 : case IX86_BUILTIN_SCATTERDIV16SI:
15596 : 24 : icode = CODE_FOR_avx512f_scatterdiv16si;
15597 : 24 : goto scatter_gen;
15598 : 29 : case IX86_BUILTIN_SCATTERDIV8DI:
15599 : 29 : icode = CODE_FOR_avx512f_scatterdiv8di;
15600 : 29 : goto scatter_gen;
15601 : 18 : case IX86_BUILTIN_SCATTERSIV8SF:
15602 : 18 : icode = CODE_FOR_avx512vl_scattersiv8sf;
15603 : 18 : goto scatter_gen;
15604 : 20 : case IX86_BUILTIN_SCATTERSIV4SF:
15605 : 20 : icode = CODE_FOR_avx512vl_scattersiv4sf;
15606 : 20 : goto scatter_gen;
15607 : 16 : case IX86_BUILTIN_SCATTERSIV4DF:
15608 : 16 : icode = CODE_FOR_avx512vl_scattersiv4df;
15609 : 16 : goto scatter_gen;
15610 : 16 : case IX86_BUILTIN_SCATTERSIV2DF:
15611 : 16 : icode = CODE_FOR_avx512vl_scattersiv2df;
15612 : 16 : goto scatter_gen;
15613 : 16 : case IX86_BUILTIN_SCATTERDIV8SF:
15614 : 16 : icode = CODE_FOR_avx512vl_scatterdiv8sf;
15615 : 16 : goto scatter_gen;
15616 : 16 : case IX86_BUILTIN_SCATTERDIV4SF:
15617 : 16 : icode = CODE_FOR_avx512vl_scatterdiv4sf;
15618 : 16 : goto scatter_gen;
15619 : 18 : case IX86_BUILTIN_SCATTERDIV4DF:
15620 : 18 : icode = CODE_FOR_avx512vl_scatterdiv4df;
15621 : 18 : goto scatter_gen;
15622 : 18 : case IX86_BUILTIN_SCATTERDIV2DF:
15623 : 18 : icode = CODE_FOR_avx512vl_scatterdiv2df;
15624 : 18 : goto scatter_gen;
15625 : 22 : case IX86_BUILTIN_SCATTERSIV8SI:
15626 : 22 : icode = CODE_FOR_avx512vl_scattersiv8si;
15627 : 22 : goto scatter_gen;
15628 : 24 : case IX86_BUILTIN_SCATTERSIV4SI:
15629 : 24 : icode = CODE_FOR_avx512vl_scattersiv4si;
15630 : 24 : goto scatter_gen;
15631 : 16 : case IX86_BUILTIN_SCATTERSIV4DI:
15632 : 16 : icode = CODE_FOR_avx512vl_scattersiv4di;
15633 : 16 : goto scatter_gen;
15634 : 16 : case IX86_BUILTIN_SCATTERSIV2DI:
15635 : 16 : icode = CODE_FOR_avx512vl_scattersiv2di;
15636 : 16 : goto scatter_gen;
15637 : 16 : case IX86_BUILTIN_SCATTERDIV8SI:
15638 : 16 : icode = CODE_FOR_avx512vl_scatterdiv8si;
15639 : 16 : goto scatter_gen;
15640 : 16 : case IX86_BUILTIN_SCATTERDIV4SI:
15641 : 16 : icode = CODE_FOR_avx512vl_scatterdiv4si;
15642 : 16 : goto scatter_gen;
15643 : 18 : case IX86_BUILTIN_SCATTERDIV4DI:
15644 : 18 : icode = CODE_FOR_avx512vl_scatterdiv4di;
15645 : 18 : goto scatter_gen;
15646 : 18 : case IX86_BUILTIN_SCATTERDIV2DI:
15647 : 18 : icode = CODE_FOR_avx512vl_scatterdiv2di;
15648 : 18 : goto scatter_gen;
15649 : 16 : case IX86_BUILTIN_SCATTERALTSIV8DF:
15650 : 16 : icode = CODE_FOR_avx512f_scattersiv8df;
15651 : 16 : goto scatter_gen;
15652 : 12 : case IX86_BUILTIN_SCATTERALTDIV16SF:
15653 : 12 : icode = CODE_FOR_avx512f_scatterdiv16sf;
15654 : 12 : goto scatter_gen;
15655 : 8 : case IX86_BUILTIN_SCATTERALTSIV8DI:
15656 : 8 : icode = CODE_FOR_avx512f_scattersiv8di;
15657 : 8 : goto scatter_gen;
15658 : 24 : case IX86_BUILTIN_SCATTERALTDIV16SI:
15659 : 24 : icode = CODE_FOR_avx512f_scatterdiv16si;
15660 : 24 : goto scatter_gen;
15661 : 4 : case IX86_BUILTIN_SCATTERALTSIV4DF:
15662 : 4 : icode = CODE_FOR_avx512vl_scattersiv4df;
15663 : 4 : goto scatter_gen;
15664 : 4 : case IX86_BUILTIN_SCATTERALTDIV8SF:
15665 : 4 : icode = CODE_FOR_avx512vl_scatterdiv8sf;
15666 : 4 : goto scatter_gen;
15667 : 4 : case IX86_BUILTIN_SCATTERALTSIV4DI:
15668 : 4 : icode = CODE_FOR_avx512vl_scattersiv4di;
15669 : 4 : goto scatter_gen;
15670 : 4 : case IX86_BUILTIN_SCATTERALTDIV8SI:
15671 : 4 : icode = CODE_FOR_avx512vl_scatterdiv8si;
15672 : 4 : goto scatter_gen;
15673 : 8 : case IX86_BUILTIN_SCATTERALTSIV2DF:
15674 : 8 : icode = CODE_FOR_avx512vl_scattersiv2df;
15675 : 8 : goto scatter_gen;
15676 : 8 : case IX86_BUILTIN_SCATTERALTDIV4SF:
15677 : 8 : icode = CODE_FOR_avx512vl_scatterdiv4sf;
15678 : 8 : goto scatter_gen;
15679 : 8 : case IX86_BUILTIN_SCATTERALTSIV2DI:
15680 : 8 : icode = CODE_FOR_avx512vl_scattersiv2di;
15681 : 8 : goto scatter_gen;
15682 : 8 : case IX86_BUILTIN_SCATTERALTDIV4SI:
15683 : 8 : icode = CODE_FOR_avx512vl_scatterdiv4si;
15684 : 8 : goto scatter_gen;
15685 : :
15686 : 1002 : gather_gen:
15687 : 1002 : rtx half;
15688 : 1002 : rtx (*gen) (rtx, rtx);
15689 : :
15690 : 1002 : arg0 = CALL_EXPR_ARG (exp, 0);
15691 : 1002 : arg1 = CALL_EXPR_ARG (exp, 1);
15692 : 1002 : arg2 = CALL_EXPR_ARG (exp, 2);
15693 : 1002 : arg3 = CALL_EXPR_ARG (exp, 3);
15694 : 1002 : arg4 = CALL_EXPR_ARG (exp, 4);
15695 : 1002 : op0 = expand_normal (arg0);
15696 : 1002 : op1 = expand_normal (arg1);
15697 : 1002 : op2 = expand_normal (arg2);
15698 : 1002 : op3 = ix86_expand_unsigned_small_int_cst_argument (arg3);
15699 : 1002 : op4 = expand_normal (arg4);
15700 : : /* Note the arg order is different from the operand order. */
15701 : 1002 : mode0 = insn_data[icode].operand[1].mode;
15702 : 1002 : mode2 = insn_data[icode].operand[3].mode;
15703 : 1002 : mode3 = insn_data[icode].operand[4].mode;
15704 : 1002 : mode4 = insn_data[icode].operand[5].mode;
15705 : :
15706 : 1002 : if (target == NULL_RTX
15707 : 1002 : || GET_MODE (target) != insn_data[icode].operand[0].mode
15708 : 1900 : || !insn_data[icode].operand[0].predicate (target,
15709 : : GET_MODE (target)))
15710 : 105 : subtarget = gen_reg_rtx (insn_data[icode].operand[0].mode);
15711 : : else
15712 : : subtarget = target;
15713 : :
15714 : 1002 : switch (fcode)
15715 : : {
15716 : 30 : case IX86_BUILTIN_GATHER3ALTSIV8DF:
15717 : 30 : case IX86_BUILTIN_GATHER3ALTSIV8DI:
15718 : 30 : half = gen_reg_rtx (V8SImode);
15719 : 30 : if (!nonimmediate_operand (op2, V16SImode))
15720 : 0 : op2 = copy_to_mode_reg (V16SImode, op2);
15721 : 30 : emit_insn (gen_vec_extract_lo_v16si (half, op2));
15722 : 30 : op2 = half;
15723 : 30 : break;
15724 : 34 : case IX86_BUILTIN_GATHER3ALTSIV4DF:
15725 : 34 : case IX86_BUILTIN_GATHER3ALTSIV4DI:
15726 : 34 : case IX86_BUILTIN_GATHERALTSIV4DF:
15727 : 34 : case IX86_BUILTIN_GATHERALTSIV4DI:
15728 : 34 : half = gen_reg_rtx (V4SImode);
15729 : 34 : if (!nonimmediate_operand (op2, V8SImode))
15730 : 0 : op2 = copy_to_mode_reg (V8SImode, op2);
15731 : 34 : emit_insn (gen_vec_extract_lo_v8si (half, op2));
15732 : 34 : op2 = half;
15733 : 34 : break;
15734 : 42 : case IX86_BUILTIN_GATHER3ALTDIV16SF:
15735 : 42 : case IX86_BUILTIN_GATHER3ALTDIV16SI:
15736 : 42 : half = gen_reg_rtx (mode0);
15737 : 42 : if (mode0 == V8SFmode)
15738 : : gen = gen_vec_extract_lo_v16sf;
15739 : : else
15740 : 20 : gen = gen_vec_extract_lo_v16si;
15741 : 42 : if (!nonimmediate_operand (op0, GET_MODE (op0)))
15742 : 42 : op0 = copy_to_mode_reg (GET_MODE (op0), op0);
15743 : 42 : emit_insn (gen (half, op0));
15744 : 42 : op0 = half;
15745 : 42 : op3 = lowpart_subreg (QImode, op3, HImode);
15746 : 42 : break;
15747 : 44 : case IX86_BUILTIN_GATHER3ALTDIV8SF:
15748 : 44 : case IX86_BUILTIN_GATHER3ALTDIV8SI:
15749 : 44 : case IX86_BUILTIN_GATHERALTDIV8SF:
15750 : 44 : case IX86_BUILTIN_GATHERALTDIV8SI:
15751 : 44 : half = gen_reg_rtx (mode0);
15752 : 44 : if (mode0 == V4SFmode)
15753 : : gen = gen_vec_extract_lo_v8sf;
15754 : : else
15755 : 20 : gen = gen_vec_extract_lo_v8si;
15756 : 44 : if (!nonimmediate_operand (op0, GET_MODE (op0)))
15757 : 44 : op0 = copy_to_mode_reg (GET_MODE (op0), op0);
15758 : 44 : emit_insn (gen (half, op0));
15759 : 44 : op0 = half;
15760 : 44 : if (VECTOR_MODE_P (GET_MODE (op3)))
15761 : : {
15762 : 26 : half = gen_reg_rtx (mode0);
15763 : 26 : if (!nonimmediate_operand (op3, GET_MODE (op3)))
15764 : 12 : op3 = copy_to_mode_reg (GET_MODE (op3), op3);
15765 : 26 : emit_insn (gen (half, op3));
15766 : 26 : op3 = half;
15767 : : }
15768 : : break;
15769 : : default:
15770 : : break;
15771 : : }
15772 : :
15773 : : /* Force memory operand only with base register here. But we
15774 : : don't want to do it on memory operand for other builtin
15775 : : functions. */
15776 : 1002 : op1 = ix86_zero_extend_to_Pmode (op1);
15777 : :
15778 : 1002 : if (!insn_data[icode].operand[1].predicate (op0, mode0))
15779 : 401 : op0 = copy_to_mode_reg (mode0, op0);
15780 : 1007 : if (!insn_data[icode].operand[2].predicate (op1, Pmode))
15781 : 0 : op1 = copy_to_mode_reg (Pmode, op1);
15782 : 1002 : if (!insn_data[icode].operand[3].predicate (op2, mode2))
15783 : 221 : op2 = copy_to_mode_reg (mode2, op2);
15784 : :
15785 : 1002 : op3 = fixup_modeless_constant (op3, mode3);
15786 : :
15787 : 1002 : if (GET_MODE (op3) == mode3 || GET_MODE (op3) == VOIDmode)
15788 : : {
15789 : 1002 : if (!insn_data[icode].operand[4].predicate (op3, mode3))
15790 : 354 : op3 = copy_to_mode_reg (mode3, op3);
15791 : : }
15792 : : else
15793 : : {
15794 : 0 : op3 = copy_to_reg (op3);
15795 : 0 : op3 = lowpart_subreg (mode3, op3, GET_MODE (op3));
15796 : : }
15797 : 1002 : if (!insn_data[icode].operand[5].predicate (op4, mode4))
15798 : : {
15799 : 0 : error ("the last argument must be scale 1, 2, 4, 8");
15800 : 0 : return const0_rtx;
15801 : : }
15802 : :
15803 : : /* Optimize. If mask is known to have all high bits set,
15804 : : replace op0 with pc_rtx to signal that the instruction
15805 : : overwrites the whole destination and doesn't use its
15806 : : previous contents. */
15807 : 1002 : if (optimize)
15808 : : {
15809 : 912 : if (TREE_CODE (arg3) == INTEGER_CST)
15810 : : {
15811 : 209 : if (integer_all_onesp (arg3))
15812 : 201 : op0 = pc_rtx;
15813 : : }
15814 : 703 : else if (TREE_CODE (arg3) == VECTOR_CST)
15815 : : {
15816 : : unsigned int negative = 0;
15817 : 741 : for (i = 0; i < VECTOR_CST_NELTS (arg3); ++i)
15818 : : {
15819 : 608 : tree cst = VECTOR_CST_ELT (arg3, i);
15820 : 608 : if (TREE_CODE (cst) == INTEGER_CST
15821 : 608 : && tree_int_cst_sign_bit (cst))
15822 : 286 : negative++;
15823 : 322 : else if (TREE_CODE (cst) == REAL_CST
15824 : 322 : && REAL_VALUE_NEGATIVE (TREE_REAL_CST (cst)))
15825 : 294 : negative++;
15826 : : }
15827 : 133 : if (negative == TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg3)))
15828 : 119 : op0 = pc_rtx;
15829 : : }
15830 : 570 : else if (TREE_CODE (arg3) == SSA_NAME
15831 : 570 : && VECTOR_TYPE_P (TREE_TYPE (arg3)))
15832 : : {
15833 : : /* Recognize also when mask is like:
15834 : : __v2df src = _mm_setzero_pd ();
15835 : : __v2df mask = _mm_cmpeq_pd (src, src);
15836 : : or
15837 : : __v8sf src = _mm256_setzero_ps ();
15838 : : __v8sf mask = _mm256_cmp_ps (src, src, _CMP_EQ_OQ);
15839 : : as that is a cheaper way to load all ones into
15840 : : a register than having to load a constant from
15841 : : memory. */
15842 : 257 : gimple *def_stmt = SSA_NAME_DEF_STMT (arg3);
15843 : 257 : if (is_gimple_call (def_stmt))
15844 : : {
15845 : 76 : tree fndecl = gimple_call_fndecl (def_stmt);
15846 : 76 : if (fndecl
15847 : 76 : && fndecl_built_in_p (fndecl, BUILT_IN_MD))
15848 : 67 : switch (DECL_MD_FUNCTION_CODE (fndecl))
15849 : : {
15850 : 24 : case IX86_BUILTIN_CMPPD:
15851 : 24 : case IX86_BUILTIN_CMPPS:
15852 : 24 : case IX86_BUILTIN_CMPPD256:
15853 : 24 : case IX86_BUILTIN_CMPPS256:
15854 : 24 : if (!integer_zerop (gimple_call_arg (def_stmt, 2)))
15855 : : break;
15856 : : /* FALLTHRU */
15857 : 49 : case IX86_BUILTIN_CMPEQPD:
15858 : 49 : case IX86_BUILTIN_CMPEQPS:
15859 : 49 : if (initializer_zerop (gimple_call_arg (def_stmt, 0))
15860 : 49 : && initializer_zerop (gimple_call_arg (def_stmt,
15861 : : 1)))
15862 : 49 : op0 = pc_rtx;
15863 : : break;
15864 : : default:
15865 : : break;
15866 : : }
15867 : : }
15868 : : }
15869 : : }
15870 : :
15871 : 1002 : pat = GEN_FCN (icode) (subtarget, op0, op1, op2, op3, op4);
15872 : 1002 : if (! pat)
15873 : 0 : return const0_rtx;
15874 : 1002 : emit_insn (pat);
15875 : :
15876 : 1002 : switch (fcode)
15877 : : {
15878 : 24 : case IX86_BUILTIN_GATHER3DIV16SF:
15879 : 24 : if (target == NULL_RTX)
15880 : 0 : target = gen_reg_rtx (V8SFmode);
15881 : 24 : emit_insn (gen_vec_extract_lo_v16sf (target, subtarget));
15882 : 24 : break;
15883 : 24 : case IX86_BUILTIN_GATHER3DIV16SI:
15884 : 24 : if (target == NULL_RTX)
15885 : 0 : target = gen_reg_rtx (V8SImode);
15886 : 24 : emit_insn (gen_vec_extract_lo_v16si (target, subtarget));
15887 : 24 : break;
15888 : 28 : case IX86_BUILTIN_GATHER3DIV8SF:
15889 : 28 : case IX86_BUILTIN_GATHERDIV8SF:
15890 : 28 : if (target == NULL_RTX)
15891 : 0 : target = gen_reg_rtx (V4SFmode);
15892 : 28 : emit_insn (gen_vec_extract_lo_v8sf (target, subtarget));
15893 : 28 : break;
15894 : 28 : case IX86_BUILTIN_GATHER3DIV8SI:
15895 : 28 : case IX86_BUILTIN_GATHERDIV8SI:
15896 : 28 : if (target == NULL_RTX)
15897 : 0 : target = gen_reg_rtx (V4SImode);
15898 : 28 : emit_insn (gen_vec_extract_lo_v8si (target, subtarget));
15899 : 28 : break;
15900 : : default:
15901 : : target = subtarget;
15902 : : break;
15903 : : }
15904 : : return target;
15905 : :
15906 : 631 : scatter_gen:
15907 : 631 : arg0 = CALL_EXPR_ARG (exp, 0);
15908 : 631 : arg1 = CALL_EXPR_ARG (exp, 1);
15909 : 631 : arg2 = CALL_EXPR_ARG (exp, 2);
15910 : 631 : arg3 = CALL_EXPR_ARG (exp, 3);
15911 : 631 : arg4 = CALL_EXPR_ARG (exp, 4);
15912 : 631 : op0 = expand_normal (arg0);
15913 : 631 : op1 = ix86_expand_unsigned_small_int_cst_argument (arg1);
15914 : 631 : op2 = expand_normal (arg2);
15915 : 631 : op3 = expand_normal (arg3);
15916 : 631 : op4 = expand_normal (arg4);
15917 : 631 : mode1 = insn_data[icode].operand[1].mode;
15918 : 631 : mode2 = insn_data[icode].operand[2].mode;
15919 : 631 : mode3 = insn_data[icode].operand[3].mode;
15920 : 631 : mode4 = insn_data[icode].operand[4].mode;
15921 : :
15922 : : /* Scatter instruction stores operand op3 to memory with
15923 : : indices from op2 and scale from op4 under writemask op1.
15924 : : If index operand op2 has more elements then source operand
15925 : : op3 one need to use only its low half. And vice versa. */
15926 : 631 : switch (fcode)
15927 : : {
15928 : 24 : case IX86_BUILTIN_SCATTERALTSIV8DF:
15929 : 24 : case IX86_BUILTIN_SCATTERALTSIV8DI:
15930 : 24 : half = gen_reg_rtx (V8SImode);
15931 : 24 : if (!nonimmediate_operand (op2, V16SImode))
15932 : 0 : op2 = copy_to_mode_reg (V16SImode, op2);
15933 : 24 : emit_insn (gen_vec_extract_lo_v16si (half, op2));
15934 : 24 : op2 = half;
15935 : 24 : break;
15936 : 36 : case IX86_BUILTIN_SCATTERALTDIV16SF:
15937 : 36 : case IX86_BUILTIN_SCATTERALTDIV16SI:
15938 : 36 : half = gen_reg_rtx (mode3);
15939 : 36 : if (mode3 == V8SFmode)
15940 : : gen = gen_vec_extract_lo_v16sf;
15941 : : else
15942 : 24 : gen = gen_vec_extract_lo_v16si;
15943 : 36 : if (!nonimmediate_operand (op3, GET_MODE (op3)))
15944 : 0 : op3 = copy_to_mode_reg (GET_MODE (op3), op3);
15945 : 36 : emit_insn (gen (half, op3));
15946 : 36 : op3 = half;
15947 : 36 : break;
15948 : 8 : case IX86_BUILTIN_SCATTERALTSIV4DF:
15949 : 8 : case IX86_BUILTIN_SCATTERALTSIV4DI:
15950 : 8 : half = gen_reg_rtx (V4SImode);
15951 : 8 : if (!nonimmediate_operand (op2, V8SImode))
15952 : 0 : op2 = copy_to_mode_reg (V8SImode, op2);
15953 : 8 : emit_insn (gen_vec_extract_lo_v8si (half, op2));
15954 : 8 : op2 = half;
15955 : 8 : break;
15956 : 8 : case IX86_BUILTIN_SCATTERALTDIV8SF:
15957 : 8 : case IX86_BUILTIN_SCATTERALTDIV8SI:
15958 : 8 : half = gen_reg_rtx (mode3);
15959 : 8 : if (mode3 == V4SFmode)
15960 : : gen = gen_vec_extract_lo_v8sf;
15961 : : else
15962 : 4 : gen = gen_vec_extract_lo_v8si;
15963 : 8 : if (!nonimmediate_operand (op3, GET_MODE (op3)))
15964 : 0 : op3 = copy_to_mode_reg (GET_MODE (op3), op3);
15965 : 8 : emit_insn (gen (half, op3));
15966 : 8 : op3 = half;
15967 : 8 : break;
15968 : 16 : case IX86_BUILTIN_SCATTERALTSIV2DF:
15969 : 16 : case IX86_BUILTIN_SCATTERALTSIV2DI:
15970 : 16 : if (!nonimmediate_operand (op2, V4SImode))
15971 : 0 : op2 = copy_to_mode_reg (V4SImode, op2);
15972 : : break;
15973 : 16 : case IX86_BUILTIN_SCATTERALTDIV4SF:
15974 : 16 : case IX86_BUILTIN_SCATTERALTDIV4SI:
15975 : 16 : if (!nonimmediate_operand (op3, GET_MODE (op3)))
15976 : 0 : op3 = copy_to_mode_reg (GET_MODE (op3), op3);
15977 : : break;
15978 : : default:
15979 : : break;
15980 : : }
15981 : :
15982 : : /* Force memory operand only with base register here. But we
15983 : : don't want to do it on memory operand for other builtin
15984 : : functions. */
15985 : 641 : op0 = force_reg (Pmode, convert_to_mode (Pmode, op0, 1));
15986 : :
15987 : 636 : if (!insn_data[icode].operand[0].predicate (op0, Pmode))
15988 : 0 : op0 = copy_to_mode_reg (Pmode, op0);
15989 : :
15990 : 631 : op1 = fixup_modeless_constant (op1, mode1);
15991 : :
15992 : 631 : if (GET_MODE (op1) == mode1 || GET_MODE (op1) == VOIDmode)
15993 : : {
15994 : 615 : if (!insn_data[icode].operand[1].predicate (op1, mode1))
15995 : 281 : op1 = copy_to_mode_reg (mode1, op1);
15996 : : }
15997 : : else
15998 : : {
15999 : 16 : op1 = copy_to_reg (op1);
16000 : 16 : op1 = lowpart_subreg (mode1, op1, GET_MODE (op1));
16001 : : }
16002 : :
16003 : 631 : if (!insn_data[icode].operand[2].predicate (op2, mode2))
16004 : 57 : op2 = copy_to_mode_reg (mode2, op2);
16005 : :
16006 : 631 : if (!insn_data[icode].operand[3].predicate (op3, mode3))
16007 : 90 : op3 = copy_to_mode_reg (mode3, op3);
16008 : :
16009 : 631 : if (!insn_data[icode].operand[4].predicate (op4, mode4))
16010 : : {
16011 : 0 : error ("the last argument must be scale 1, 2, 4, 8");
16012 : 0 : return const0_rtx;
16013 : : }
16014 : :
16015 : 631 : pat = GEN_FCN (icode) (op0, op1, op2, op3, op4);
16016 : 631 : if (! pat)
16017 : 0 : return const0_rtx;
16018 : :
16019 : 631 : emit_insn (pat);
16020 : 631 : return 0;
16021 : :
16022 : 23 : case IX86_BUILTIN_XABORT:
16023 : 23 : icode = CODE_FOR_xabort;
16024 : 23 : arg0 = CALL_EXPR_ARG (exp, 0);
16025 : 23 : op0 = expand_normal (arg0);
16026 : 23 : mode0 = insn_data[icode].operand[0].mode;
16027 : 23 : if (!insn_data[icode].operand[0].predicate (op0, mode0))
16028 : : {
16029 : 0 : error ("the argument to %<xabort%> intrinsic must "
16030 : : "be an 8-bit immediate");
16031 : 0 : return const0_rtx;
16032 : : }
16033 : 23 : emit_insn (gen_xabort (op0));
16034 : 23 : return 0;
16035 : :
16036 : 55 : case IX86_BUILTIN_RDSSPD:
16037 : 55 : case IX86_BUILTIN_RDSSPQ:
16038 : 55 : mode = (fcode == IX86_BUILTIN_RDSSPD ? SImode : DImode);
16039 : :
16040 : 55 : if (target == 0
16041 : 55 : || !register_operand (target, mode))
16042 : 0 : target = gen_reg_rtx (mode);
16043 : :
16044 : 55 : op0 = force_reg (mode, const0_rtx);
16045 : :
16046 : 55 : emit_insn (gen_rdssp (mode, target, op0));
16047 : 55 : return target;
16048 : :
16049 : 55 : case IX86_BUILTIN_INCSSPD:
16050 : 55 : case IX86_BUILTIN_INCSSPQ:
16051 : 55 : mode = (fcode == IX86_BUILTIN_INCSSPD ? SImode : DImode);
16052 : :
16053 : 55 : arg0 = CALL_EXPR_ARG (exp, 0);
16054 : 55 : op0 = expand_normal (arg0);
16055 : :
16056 : 55 : op0 = force_reg (mode, op0);
16057 : :
16058 : 55 : emit_insn (gen_incssp (mode, op0));
16059 : 55 : return 0;
16060 : :
16061 : 20 : case IX86_BUILTIN_HRESET:
16062 : 20 : icode = CODE_FOR_hreset;
16063 : 20 : arg0 = CALL_EXPR_ARG (exp, 0);
16064 : 20 : op0 = expand_normal (arg0);
16065 : 20 : op0 = force_reg (SImode, op0);
16066 : 20 : emit_insn (gen_hreset (op0));
16067 : 20 : return 0;
16068 : :
16069 : 38 : case IX86_BUILTIN_RSTORSSP:
16070 : 38 : case IX86_BUILTIN_CLRSSBSY:
16071 : 38 : arg0 = CALL_EXPR_ARG (exp, 0);
16072 : 38 : op0 = expand_normal (arg0);
16073 : 19 : icode = (fcode == IX86_BUILTIN_RSTORSSP
16074 : 38 : ? CODE_FOR_rstorssp
16075 : : : CODE_FOR_clrssbsy);
16076 : :
16077 : 38 : if (!address_operand (op0, VOIDmode))
16078 : : {
16079 : 18 : op0 = convert_memory_address (Pmode, op0);
16080 : 18 : op0 = copy_addr_to_reg (op0);
16081 : : }
16082 : 38 : emit_insn (GEN_FCN (icode) (gen_rtx_MEM (DImode, op0)));
16083 : 38 : return 0;
16084 : :
16085 : 76 : case IX86_BUILTIN_WRSSD:
16086 : 76 : case IX86_BUILTIN_WRSSQ:
16087 : 76 : case IX86_BUILTIN_WRUSSD:
16088 : 76 : case IX86_BUILTIN_WRUSSQ:
16089 : 76 : mode = ((fcode == IX86_BUILTIN_WRSSD
16090 : 76 : || fcode == IX86_BUILTIN_WRUSSD)
16091 : 76 : ? SImode : DImode);
16092 : :
16093 : 76 : arg0 = CALL_EXPR_ARG (exp, 0);
16094 : 76 : op0 = expand_normal (arg0);
16095 : 76 : arg1 = CALL_EXPR_ARG (exp, 1);
16096 : 76 : op1 = expand_normal (arg1);
16097 : :
16098 : 76 : op0 = force_reg (mode, op0);
16099 : :
16100 : 76 : if (!address_operand (op1, VOIDmode))
16101 : : {
16102 : 36 : op1 = convert_memory_address (Pmode, op1);
16103 : 36 : op1 = copy_addr_to_reg (op1);
16104 : : }
16105 : 76 : op1 = gen_rtx_MEM (mode, op1);
16106 : :
16107 : 76 : icode = ((fcode == IX86_BUILTIN_WRSSD
16108 : 76 : || fcode == IX86_BUILTIN_WRSSQ)
16109 : 76 : ? code_for_wrss (mode)
16110 : 38 : : code_for_wruss (mode));
16111 : 76 : emit_insn (GEN_FCN (icode) (op0, op1));
16112 : :
16113 : 76 : return 0;
16114 : :
16115 : 113727 : default:
16116 : 113727 : break;
16117 : : }
16118 : :
16119 : 113727 : if (fcode >= IX86_BUILTIN__BDESC_SPECIAL_ARGS_FIRST
16120 : 113727 : && fcode <= IX86_BUILTIN__BDESC_SPECIAL_ARGS_LAST)
16121 : : {
16122 : 27221 : i = fcode - IX86_BUILTIN__BDESC_SPECIAL_ARGS_FIRST;
16123 : 27221 : return ix86_expand_special_args_builtin (bdesc_special_args + i, exp,
16124 : 27221 : target);
16125 : : }
16126 : :
16127 : 86506 : if (fcode >= IX86_BUILTIN__BDESC_PURE_ARGS_FIRST
16128 : 86506 : && fcode <= IX86_BUILTIN__BDESC_PURE_ARGS_LAST)
16129 : : {
16130 : 93 : i = fcode - IX86_BUILTIN__BDESC_PURE_ARGS_FIRST;
16131 : 93 : return ix86_expand_special_args_builtin (bdesc_pure_args + i, exp,
16132 : 93 : target);
16133 : : }
16134 : :
16135 : 86413 : if (fcode >= IX86_BUILTIN__BDESC_ARGS_FIRST
16136 : 86413 : && fcode <= IX86_BUILTIN__BDESC_ARGS_LAST)
16137 : : {
16138 : 68149 : i = fcode - IX86_BUILTIN__BDESC_ARGS_FIRST;
16139 : :
16140 : 68149 : switch (fcode)
16141 : : {
16142 : 0 : case IX86_BUILTIN_RDPID:
16143 : 0 : return ix86_expand_special_args_builtin (bdesc_args + i, exp,
16144 : 0 : target);
16145 : 66 : case IX86_BUILTIN_VCOMISBF16EQ:
16146 : 66 : case IX86_BUILTIN_VCOMISBF16NE:
16147 : 66 : case IX86_BUILTIN_VCOMISBF16GT:
16148 : 66 : case IX86_BUILTIN_VCOMISBF16GE:
16149 : 66 : case IX86_BUILTIN_VCOMISBF16LT:
16150 : 66 : case IX86_BUILTIN_VCOMISBF16LE:
16151 : 66 : return ix86_expand_sse_comi (bdesc_args + i, exp, target, false);
16152 : 9 : case IX86_BUILTIN_FABSQ:
16153 : 9 : case IX86_BUILTIN_COPYSIGNQ:
16154 : 9 : if (!TARGET_SSE)
16155 : : /* Emit a normal call if SSE isn't available. */
16156 : 0 : return expand_call (exp, target, ignore);
16157 : : /* FALLTHRU */
16158 : 68083 : default:
16159 : 68083 : return ix86_expand_args_builtin (bdesc_args + i, exp, target);
16160 : : }
16161 : : }
16162 : :
16163 : 18264 : if (fcode >= IX86_BUILTIN__BDESC_COMI_FIRST
16164 : 18264 : && fcode <= IX86_BUILTIN__BDESC_COMI_LAST)
16165 : : {
16166 : 473 : i = fcode - IX86_BUILTIN__BDESC_COMI_FIRST;
16167 : 473 : return ix86_expand_sse_comi (bdesc_comi + i, exp, target, true);
16168 : : }
16169 : :
16170 : 17791 : if (fcode >= IX86_BUILTIN__BDESC_ROUND_ARGS_FIRST
16171 : 17791 : && fcode <= IX86_BUILTIN__BDESC_ROUND_ARGS_LAST)
16172 : : {
16173 : 15467 : i = fcode - IX86_BUILTIN__BDESC_ROUND_ARGS_FIRST;
16174 : 15467 : return ix86_expand_round_builtin (bdesc_round_args + i, exp, target);
16175 : : }
16176 : :
16177 : 2324 : if (fcode >= IX86_BUILTIN__BDESC_PCMPESTR_FIRST
16178 : 2324 : && fcode <= IX86_BUILTIN__BDESC_PCMPESTR_LAST)
16179 : : {
16180 : 216 : i = fcode - IX86_BUILTIN__BDESC_PCMPESTR_FIRST;
16181 : 216 : return ix86_expand_sse_pcmpestr (bdesc_pcmpestr + i, exp, target);
16182 : : }
16183 : :
16184 : 2108 : if (fcode >= IX86_BUILTIN__BDESC_PCMPISTR_FIRST
16185 : 2108 : && fcode <= IX86_BUILTIN__BDESC_PCMPISTR_LAST)
16186 : : {
16187 : 275 : i = fcode - IX86_BUILTIN__BDESC_PCMPISTR_FIRST;
16188 : 275 : return ix86_expand_sse_pcmpistr (bdesc_pcmpistr + i, exp, target);
16189 : : }
16190 : :
16191 : 1833 : if (fcode >= IX86_BUILTIN__BDESC_MULTI_ARG_FIRST
16192 : 1833 : && fcode <= IX86_BUILTIN__BDESC_MULTI_ARG_LAST)
16193 : : {
16194 : 1795 : i = fcode - IX86_BUILTIN__BDESC_MULTI_ARG_FIRST;
16195 : 1795 : const struct builtin_description *d = bdesc_multi_arg + i;
16196 : 1795 : return ix86_expand_multi_arg_builtin (d->icode, exp, target,
16197 : : (enum ix86_builtin_func_type)
16198 : 1795 : d->flag, d->comparison);
16199 : : }
16200 : :
16201 : 38 : if (fcode >= IX86_BUILTIN__BDESC_CET_FIRST
16202 : 38 : && fcode <= IX86_BUILTIN__BDESC_CET_LAST)
16203 : : {
16204 : 38 : i = fcode - IX86_BUILTIN__BDESC_CET_FIRST;
16205 : 38 : return ix86_expand_special_args_builtin (bdesc_cet + i, exp,
16206 : 38 : target);
16207 : : }
16208 : :
16209 : 0 : gcc_unreachable ();
16210 : : }
16211 : :
16212 : : /* See below where shifts are handled for explanation of this enum. */
16213 : : enum ix86_vec_bcast_alg
16214 : : {
16215 : : VEC_BCAST_PXOR,
16216 : : VEC_BCAST_PCMPEQ,
16217 : : VEC_BCAST_PABSB,
16218 : : VEC_BCAST_PADDB,
16219 : : VEC_BCAST_PSRLW,
16220 : : VEC_BCAST_PSRLD,
16221 : : VEC_BCAST_PSLLW,
16222 : : VEC_BCAST_PSLLD
16223 : : };
16224 : :
16225 : : struct ix86_vec_bcast_map_simode_t
16226 : : {
16227 : : unsigned int key;
16228 : : enum ix86_vec_bcast_alg alg;
16229 : : unsigned int arg;
16230 : : };
16231 : :
16232 : : /* This table must be kept sorted as values are looked-up using bsearch. */
16233 : : static const ix86_vec_bcast_map_simode_t ix86_vec_bcast_map_simode[] = {
16234 : : { 0x00000000, VEC_BCAST_PXOR, 0 },
16235 : : { 0x00000001, VEC_BCAST_PSRLD, 31 },
16236 : : { 0x00000003, VEC_BCAST_PSRLD, 30 },
16237 : : { 0x00000007, VEC_BCAST_PSRLD, 29 },
16238 : : { 0x0000000f, VEC_BCAST_PSRLD, 28 },
16239 : : { 0x0000001f, VEC_BCAST_PSRLD, 27 },
16240 : : { 0x0000003f, VEC_BCAST_PSRLD, 26 },
16241 : : { 0x0000007f, VEC_BCAST_PSRLD, 25 },
16242 : : { 0x000000ff, VEC_BCAST_PSRLD, 24 },
16243 : : { 0x000001ff, VEC_BCAST_PSRLD, 23 },
16244 : : { 0x000003ff, VEC_BCAST_PSRLD, 22 },
16245 : : { 0x000007ff, VEC_BCAST_PSRLD, 21 },
16246 : : { 0x00000fff, VEC_BCAST_PSRLD, 20 },
16247 : : { 0x00001fff, VEC_BCAST_PSRLD, 19 },
16248 : : { 0x00003fff, VEC_BCAST_PSRLD, 18 },
16249 : : { 0x00007fff, VEC_BCAST_PSRLD, 17 },
16250 : : { 0x0000ffff, VEC_BCAST_PSRLD, 16 },
16251 : : { 0x00010001, VEC_BCAST_PSRLW, 15 },
16252 : : { 0x0001ffff, VEC_BCAST_PSRLD, 15 },
16253 : : { 0x00030003, VEC_BCAST_PSRLW, 14 },
16254 : : { 0x0003ffff, VEC_BCAST_PSRLD, 14 },
16255 : : { 0x00070007, VEC_BCAST_PSRLW, 13 },
16256 : : { 0x0007ffff, VEC_BCAST_PSRLD, 13 },
16257 : : { 0x000f000f, VEC_BCAST_PSRLW, 12 },
16258 : : { 0x000fffff, VEC_BCAST_PSRLD, 12 },
16259 : : { 0x001f001f, VEC_BCAST_PSRLW, 11 },
16260 : : { 0x001fffff, VEC_BCAST_PSRLD, 11 },
16261 : : { 0x003f003f, VEC_BCAST_PSRLW, 10 },
16262 : : { 0x003fffff, VEC_BCAST_PSRLD, 10 },
16263 : : { 0x007f007f, VEC_BCAST_PSRLW, 9 },
16264 : : { 0x007fffff, VEC_BCAST_PSRLD, 9 },
16265 : : { 0x00ff00ff, VEC_BCAST_PSRLW, 8 },
16266 : : { 0x00ffffff, VEC_BCAST_PSRLD, 8 },
16267 : : { 0x01010101, VEC_BCAST_PABSB, 0 },
16268 : : { 0x01ff01ff, VEC_BCAST_PSRLW, 7 },
16269 : : { 0x01ffffff, VEC_BCAST_PSRLD, 7 },
16270 : : { 0x03ff03ff, VEC_BCAST_PSRLW, 6 },
16271 : : { 0x03ffffff, VEC_BCAST_PSRLD, 6 },
16272 : : { 0x07ff07ff, VEC_BCAST_PSRLW, 5 },
16273 : : { 0x07ffffff, VEC_BCAST_PSRLD, 5 },
16274 : : { 0x0fff0fff, VEC_BCAST_PSRLW, 4 },
16275 : : { 0x0fffffff, VEC_BCAST_PSRLD, 4 },
16276 : : { 0x1fff1fff, VEC_BCAST_PSRLW, 3 },
16277 : : { 0x1fffffff, VEC_BCAST_PSRLD, 3 },
16278 : : { 0x3fff3fff, VEC_BCAST_PSRLW, 2 },
16279 : : { 0x3fffffff, VEC_BCAST_PSRLD, 2 },
16280 : : { 0x7fff7fff, VEC_BCAST_PSRLW, 1 },
16281 : : { 0x7fffffff, VEC_BCAST_PSRLD, 1 },
16282 : : { 0x80000000, VEC_BCAST_PSLLD, 31 },
16283 : : { 0x80008000, VEC_BCAST_PSLLW, 15 },
16284 : : { 0xc0000000, VEC_BCAST_PSLLD, 30 },
16285 : : { 0xc000c000, VEC_BCAST_PSLLW, 14 },
16286 : : { 0xe0000000, VEC_BCAST_PSLLD, 29 },
16287 : : { 0xe000e000, VEC_BCAST_PSLLW, 13 },
16288 : : { 0xf0000000, VEC_BCAST_PSLLD, 28 },
16289 : : { 0xf000f000, VEC_BCAST_PSLLW, 12 },
16290 : : { 0xf8000000, VEC_BCAST_PSLLD, 27 },
16291 : : { 0xf800f800, VEC_BCAST_PSLLW, 11 },
16292 : : { 0xfc000000, VEC_BCAST_PSLLD, 26 },
16293 : : { 0xfc00fc00, VEC_BCAST_PSLLW, 10 },
16294 : : { 0xfe000000, VEC_BCAST_PSLLD, 25 },
16295 : : { 0xfe00fe00, VEC_BCAST_PSLLW, 9 },
16296 : : { 0xfefefefe, VEC_BCAST_PADDB, 0 },
16297 : : { 0xff000000, VEC_BCAST_PSLLD, 24 },
16298 : : { 0xff00ff00, VEC_BCAST_PSLLW, 8 },
16299 : : { 0xff800000, VEC_BCAST_PSLLD, 23 },
16300 : : { 0xff80ff80, VEC_BCAST_PSLLW, 7 },
16301 : : { 0xffc00000, VEC_BCAST_PSLLD, 22 },
16302 : : { 0xffc0ffc0, VEC_BCAST_PSLLW, 6 },
16303 : : { 0xffe00000, VEC_BCAST_PSLLD, 21 },
16304 : : { 0xffe0ffe0, VEC_BCAST_PSLLW, 5 },
16305 : : { 0xfff00000, VEC_BCAST_PSLLD, 20 },
16306 : : { 0xfff0fff0, VEC_BCAST_PSLLW, 4 },
16307 : : { 0xfff80000, VEC_BCAST_PSLLD, 19 },
16308 : : { 0xfff8fff8, VEC_BCAST_PSLLW, 3 },
16309 : : { 0xfffc0000, VEC_BCAST_PSLLD, 18 },
16310 : : { 0xfffcfffc, VEC_BCAST_PSLLW, 2 },
16311 : : { 0xfffe0000, VEC_BCAST_PSLLD, 17 },
16312 : : { 0xfffefffe, VEC_BCAST_PSLLW, 1 },
16313 : : { 0xffff0000, VEC_BCAST_PSLLD, 16 },
16314 : : { 0xffff8000, VEC_BCAST_PSLLD, 15 },
16315 : : { 0xffffc000, VEC_BCAST_PSLLD, 14 },
16316 : : { 0xffffe000, VEC_BCAST_PSLLD, 13 },
16317 : : { 0xfffff000, VEC_BCAST_PSLLD, 12 },
16318 : : { 0xfffff800, VEC_BCAST_PSLLD, 11 },
16319 : : { 0xfffffc00, VEC_BCAST_PSLLD, 10 },
16320 : : { 0xfffffe00, VEC_BCAST_PSLLD, 9 },
16321 : : { 0xffffff00, VEC_BCAST_PSLLD, 8 },
16322 : : { 0xffffff80, VEC_BCAST_PSLLD, 7 },
16323 : : { 0xffffffc0, VEC_BCAST_PSLLD, 6 },
16324 : : { 0xffffffe0, VEC_BCAST_PSLLD, 5 },
16325 : : { 0xfffffff0, VEC_BCAST_PSLLD, 4 },
16326 : : { 0xfffffff8, VEC_BCAST_PSLLD, 3 },
16327 : : { 0xfffffffc, VEC_BCAST_PSLLD, 2 },
16328 : : { 0xfffffffe, VEC_BCAST_PSLLD, 1 },
16329 : : { 0xffffffff, VEC_BCAST_PCMPEQ, 0 }
16330 : : };
16331 : :
16332 : : /* Comparator for bsearch on ix86_vec_bcast_map. */
16333 : : static int
16334 : 269508 : ix86_vec_bcast_map_simode_cmp (const void *key, const void *entry)
16335 : : {
16336 : 269508 : return (*(const unsigned int*)key)
16337 : 269508 : - ((const ix86_vec_bcast_map_simode_t*)entry)->key;
16338 : : }
16339 : :
16340 : : /* A subroutine of ix86_vector_duplicate_value. Tries to efficiently
16341 : : materialize V4SImode, V8SImode and V16SImode vectors from SImode
16342 : : integer constants. */
16343 : : static bool
16344 : 41419 : ix86_vector_duplicate_simode_const (machine_mode mode, rtx target,
16345 : : unsigned int val)
16346 : : {
16347 : 41419 : const ix86_vec_bcast_map_simode_t *entry;
16348 : 41419 : rtx tmp1, tmp2;
16349 : :
16350 : 41419 : entry = (const ix86_vec_bcast_map_simode_t*)
16351 : 41419 : bsearch(&val, ix86_vec_bcast_map_simode,
16352 : : ARRAY_SIZE (ix86_vec_bcast_map_simode),
16353 : : sizeof (ix86_vec_bcast_map_simode_t),
16354 : : ix86_vec_bcast_map_simode_cmp);
16355 : 41419 : if (!entry)
16356 : : return false;
16357 : :
16358 : 18241 : switch (entry->alg)
16359 : : {
16360 : 0 : case VEC_BCAST_PXOR:
16361 : 0 : if ((mode == V8SImode && !TARGET_AVX2)
16362 : 0 : || (mode == V16SImode && !TARGET_AVX512F))
16363 : : return false;
16364 : 0 : emit_move_insn (target, CONST0_RTX (mode));
16365 : 0 : return true;
16366 : :
16367 : 119 : case VEC_BCAST_PCMPEQ:
16368 : 119 : if ((mode == V4SImode && !TARGET_SSE2)
16369 : 118 : || (mode == V8SImode && !TARGET_AVX2)
16370 : 101 : || (mode == V16SImode && !TARGET_AVX512F))
16371 : : return false;
16372 : 101 : emit_move_insn (target, CONSTM1_RTX (mode));
16373 : 101 : return true;
16374 : :
16375 : 501 : case VEC_BCAST_PABSB:
16376 : 501 : if (mode == V4SImode && TARGET_SSE2)
16377 : : {
16378 : 412 : tmp1 = gen_reg_rtx (V16QImode);
16379 : 412 : emit_move_insn (tmp1, CONSTM1_RTX (V16QImode));
16380 : 412 : tmp2 = gen_reg_rtx (V16QImode);
16381 : 412 : emit_insn (gen_absv16qi2 (tmp2, tmp1));
16382 : : }
16383 : 89 : else if (mode == V8SImode && TARGET_AVX2)
16384 : : {
16385 : 43 : tmp1 = gen_reg_rtx (V32QImode);
16386 : 43 : emit_move_insn (tmp1, CONSTM1_RTX (V32QImode));
16387 : 43 : tmp2 = gen_reg_rtx (V32QImode);
16388 : 43 : emit_insn (gen_absv32qi2 (tmp2, tmp1));
16389 : : }
16390 : 46 : else if (mode == V16SImode && TARGET_AVX512BW)
16391 : : {
16392 : 38 : tmp1 = gen_reg_rtx (V64QImode);
16393 : 38 : emit_move_insn (tmp1, CONSTM1_RTX (V64QImode));
16394 : 38 : tmp2 = gen_reg_rtx (V64QImode);
16395 : 38 : emit_insn (gen_absv64qi2 (tmp2, tmp1));
16396 : : }
16397 : : else
16398 : : return false;
16399 : : break;
16400 : :
16401 : 100 : case VEC_BCAST_PADDB:
16402 : 100 : if (mode == V4SImode && TARGET_SSE2)
16403 : : {
16404 : 95 : tmp1 = gen_reg_rtx (V16QImode);
16405 : 95 : emit_move_insn (tmp1, CONSTM1_RTX (V16QImode));
16406 : 95 : tmp2 = gen_reg_rtx (V16QImode);
16407 : 95 : emit_insn (gen_addv16qi3 (tmp2, tmp1, tmp1));
16408 : : }
16409 : 5 : else if (mode == V8SImode && TARGET_AVX2)
16410 : : {
16411 : 1 : tmp1 = gen_reg_rtx (V32QImode);
16412 : 1 : emit_move_insn (tmp1, CONSTM1_RTX (V32QImode));
16413 : 1 : tmp2 = gen_reg_rtx (V32QImode);
16414 : 1 : emit_insn (gen_addv32qi3 (tmp2, tmp1, tmp1));
16415 : : }
16416 : 4 : else if (mode == V16SImode && TARGET_AVX512BW)
16417 : : {
16418 : 4 : tmp1 = gen_reg_rtx (V64QImode);
16419 : 4 : emit_move_insn (tmp1, CONSTM1_RTX (V64QImode));
16420 : 4 : tmp2 = gen_reg_rtx (V64QImode);
16421 : 4 : emit_insn (gen_addv64qi3 (tmp2, tmp1, tmp1));
16422 : : }
16423 : : else
16424 : : return false;
16425 : : break;
16426 : :
16427 : 3787 : case VEC_BCAST_PSRLW:
16428 : 3787 : if (mode == V4SImode && TARGET_SSE2)
16429 : : {
16430 : 3516 : tmp1 = gen_reg_rtx (V8HImode);
16431 : 3516 : emit_move_insn (tmp1, CONSTM1_RTX (V8HImode));
16432 : 3516 : tmp2 = gen_reg_rtx (V8HImode);
16433 : 3516 : emit_insn (gen_lshrv8hi3 (tmp2, tmp1, GEN_INT (entry->arg)));
16434 : : }
16435 : 271 : else if (mode == V8SImode && TARGET_AVX2)
16436 : : {
16437 : 178 : tmp1 = gen_reg_rtx (V16HImode);
16438 : 178 : emit_move_insn (tmp1, CONSTM1_RTX (V16HImode));
16439 : 178 : tmp2 = gen_reg_rtx (V16HImode);
16440 : 178 : emit_insn (gen_lshrv16hi3 (tmp2, tmp1, GEN_INT (entry->arg)));
16441 : : }
16442 : 93 : else if (mode == V16SImode && TARGET_AVX512BW)
16443 : : {
16444 : 91 : tmp1 = gen_reg_rtx (V32HImode);
16445 : 91 : emit_move_insn (tmp1, CONSTM1_RTX (V32HImode));
16446 : 91 : tmp2 = gen_reg_rtx (V32HImode);
16447 : 91 : emit_insn (gen_lshrv32hi3 (tmp2, tmp1, GEN_INT (entry->arg)));
16448 : : }
16449 : : else
16450 : : return false;
16451 : : break;
16452 : :
16453 : 11653 : case VEC_BCAST_PSRLD:
16454 : 11653 : if (mode == V4SImode && TARGET_SSE2)
16455 : : {
16456 : 9050 : tmp1 = gen_reg_rtx (V4SImode);
16457 : 9050 : emit_move_insn (tmp1, CONSTM1_RTX (V4SImode));
16458 : 9050 : emit_insn (gen_lshrv4si3 (target, tmp1, GEN_INT (entry->arg)));
16459 : 9050 : return true;
16460 : : }
16461 : 2603 : else if (mode == V8SImode && TARGET_AVX2)
16462 : : {
16463 : 921 : tmp1 = gen_reg_rtx (V8SImode);
16464 : 921 : emit_move_insn (tmp1, CONSTM1_RTX (V8SImode));
16465 : 921 : emit_insn (gen_lshrv8si3 (target, tmp1, GEN_INT (entry->arg)));
16466 : 921 : return true;
16467 : : }
16468 : 1682 : else if (mode == V16SImode && TARGET_AVX512F)
16469 : : {
16470 : 843 : tmp1 = gen_reg_rtx (V16SImode);
16471 : 843 : emit_move_insn (tmp1, CONSTM1_RTX (V16SImode));
16472 : 843 : emit_insn (gen_lshrv16si3 (target, tmp1, GEN_INT (entry->arg)));
16473 : 843 : return true;
16474 : : }
16475 : : else
16476 : : return false;
16477 : 114 : break;
16478 : :
16479 : 114 : case VEC_BCAST_PSLLW:
16480 : 114 : if (mode == V4SImode && TARGET_SSE2)
16481 : : {
16482 : 85 : tmp1 = gen_reg_rtx (V8HImode);
16483 : 85 : emit_move_insn (tmp1, CONSTM1_RTX (V8HImode));
16484 : 85 : tmp2 = gen_reg_rtx (V8HImode);
16485 : 85 : emit_insn (gen_ashlv8hi3 (tmp2, tmp1, GEN_INT (entry->arg)));
16486 : : }
16487 : 29 : else if (mode == V8SImode && TARGET_AVX2)
16488 : : {
16489 : 21 : tmp1 = gen_reg_rtx (V16HImode);
16490 : 21 : emit_move_insn (tmp1, CONSTM1_RTX (V16HImode));
16491 : 21 : tmp2 = gen_reg_rtx (V16HImode);
16492 : 21 : emit_insn (gen_ashlv16hi3 (tmp2, tmp1, GEN_INT (entry->arg)));
16493 : : }
16494 : 8 : else if (mode == V16SImode && TARGET_AVX512BW)
16495 : : {
16496 : 8 : tmp1 = gen_reg_rtx (V32HImode);
16497 : 8 : emit_move_insn (tmp1, CONSTM1_RTX (V32HImode));
16498 : 8 : tmp2 = gen_reg_rtx (V32HImode);
16499 : 8 : emit_insn (gen_ashlv32hi3 (tmp2, tmp1, GEN_INT (entry->arg)));
16500 : : }
16501 : : else
16502 : : return false;
16503 : : break;
16504 : :
16505 : 1967 : case VEC_BCAST_PSLLD:
16506 : 1967 : if (mode == V4SImode && TARGET_SSE2)
16507 : : {
16508 : 1700 : tmp1 = gen_reg_rtx (V4SImode);
16509 : 1700 : emit_move_insn (tmp1, CONSTM1_RTX (V4SImode));
16510 : 1700 : emit_insn (gen_ashlv4si3 (target, tmp1, GEN_INT (entry->arg)));
16511 : 1700 : return true;
16512 : : }
16513 : 267 : else if (mode == V8SImode && TARGET_AVX2)
16514 : : {
16515 : 174 : tmp1 = gen_reg_rtx (V8SImode);
16516 : 174 : emit_move_insn (tmp1, CONSTM1_RTX (V8SImode));
16517 : 174 : emit_insn (gen_ashlv8si3 (target, tmp1, GEN_INT (entry->arg)));
16518 : 174 : return true;
16519 : : }
16520 : 93 : else if (mode == V16SImode && TARGET_AVX512F)
16521 : : {
16522 : 93 : tmp1 = gen_reg_rtx (V16SImode);
16523 : 93 : emit_move_insn (tmp1, CONSTM1_RTX (V16SImode));
16524 : 93 : emit_insn (gen_ashlv16si3 (target, tmp1, GEN_INT (entry->arg)));
16525 : 93 : return true;
16526 : : }
16527 : : else
16528 : : return false;
16529 : :
16530 : : default:
16531 : : return false;
16532 : : }
16533 : :
16534 : 4492 : emit_move_insn (target, gen_lowpart (mode, tmp2));
16535 : 4492 : return true;
16536 : : }
16537 : :
16538 : : /* A subroutine of ix86_expand_vector_init_duplicate. Tries to
16539 : : fill target with val via vec_duplicate. */
16540 : :
16541 : : static bool
16542 : 138819 : ix86_vector_duplicate_value (machine_mode mode, rtx target, rtx val)
16543 : : {
16544 : 138819 : bool ok;
16545 : 138819 : rtx_insn *insn;
16546 : 138819 : rtx dup;
16547 : :
16548 : 138819 : if ((mode == V4SImode || mode == V8SImode || mode == V16SImode)
16549 : 48865 : && CONST_INT_P (val)
16550 : 41419 : && ix86_vector_duplicate_simode_const (mode, target, INTVAL (val)))
16551 : : return true;
16552 : :
16553 : : /* Save/restore recog_data in case this is called from splitters
16554 : : or other routines where recog_data needs to stay valid across
16555 : : force_reg. See PR106577. */
16556 : 121445 : recog_data_d recog_data_save = recog_data;
16557 : :
16558 : : /* First attempt to recognize VAL as-is. */
16559 : 121445 : dup = gen_vec_duplicate (mode, val);
16560 : 121445 : insn = emit_insn (gen_rtx_SET (target, dup));
16561 : 121445 : if (recog_memoized (insn) < 0)
16562 : : {
16563 : 85493 : rtx_insn *seq;
16564 : 85493 : machine_mode innermode = GET_MODE_INNER (mode);
16565 : 85493 : rtx reg;
16566 : :
16567 : : /* If that fails, force VAL into a register. */
16568 : :
16569 : 85493 : start_sequence ();
16570 : 85493 : reg = force_reg (innermode, val);
16571 : 85493 : if (GET_MODE (reg) != innermode)
16572 : 0 : reg = gen_lowpart (innermode, reg);
16573 : 85493 : SET_SRC (PATTERN (insn)) = gen_vec_duplicate (mode, reg);
16574 : 85493 : seq = end_sequence ();
16575 : 85493 : if (seq)
16576 : 85493 : emit_insn_before (seq, insn);
16577 : :
16578 : 85493 : ok = recog_memoized (insn) >= 0;
16579 : 85493 : gcc_assert (ok);
16580 : : }
16581 : 121445 : recog_data = recog_data_save;
16582 : 121445 : return true;
16583 : : }
16584 : :
16585 : : /* Get a vector mode of the same size as the original but with elements
16586 : : twice as wide. This is only guaranteed to apply to integral vectors. */
16587 : :
16588 : : static machine_mode
16589 : 15976 : get_mode_wider_vector (machine_mode o)
16590 : : {
16591 : : /* ??? Rely on the ordering that genmodes.cc gives to vectors. */
16592 : 15976 : machine_mode n = GET_MODE_NEXT_MODE (o).require ();
16593 : 47928 : gcc_assert (GET_MODE_NUNITS (o) == GET_MODE_NUNITS (n) * 2);
16594 : 47928 : gcc_assert (GET_MODE_SIZE (o) == GET_MODE_SIZE (n));
16595 : 15976 : return n;
16596 : : }
16597 : :
16598 : : static bool expand_vec_perm_broadcast_1 (struct expand_vec_perm_d *d);
16599 : : static bool expand_vec_perm_1 (struct expand_vec_perm_d *d);
16600 : :
16601 : : /* A subroutine of ix86_expand_vector_init. Store into TARGET a vector
16602 : : with all elements equal to VAR. Return true if successful. */
16603 : :
16604 : : bool
16605 : 155809 : ix86_expand_vector_init_duplicate (bool mmx_ok, machine_mode mode,
16606 : : rtx target, rtx val)
16607 : : {
16608 : 155809 : bool ok;
16609 : :
16610 : 155809 : switch (mode)
16611 : : {
16612 : 69885 : case E_V2DImode:
16613 : 69885 : if (CONST_INT_P (val))
16614 : : {
16615 : 60768 : int tmp = (int)INTVAL (val);
16616 : 60768 : if (tmp == (int)(INTVAL (val) >> 32))
16617 : : {
16618 : 141 : rtx reg = gen_reg_rtx (V4SImode);
16619 : 141 : ok = ix86_vector_duplicate_value (V4SImode, reg,
16620 : : GEN_INT (tmp));
16621 : 141 : if (ok)
16622 : : {
16623 : 141 : emit_move_insn (target, gen_lowpart (V2DImode, reg));
16624 : 141 : return true;
16625 : : }
16626 : : }
16627 : : }
16628 : 69744 : return ix86_vector_duplicate_value (mode, target, val);
16629 : :
16630 : 715 : case E_V4DImode:
16631 : 715 : if (CONST_INT_P (val))
16632 : : {
16633 : 614 : int tmp = (int)INTVAL (val);
16634 : 614 : if (tmp == (int)(INTVAL (val) >> 32))
16635 : : {
16636 : 43 : rtx reg = gen_reg_rtx (V8SImode);
16637 : 43 : ok = ix86_vector_duplicate_value (V8SImode, reg,
16638 : : GEN_INT (tmp));
16639 : 43 : if (ok)
16640 : : {
16641 : 43 : emit_move_insn (target, gen_lowpart (V4DImode, reg));
16642 : 43 : return true;
16643 : : }
16644 : : }
16645 : : }
16646 : 672 : return ix86_vector_duplicate_value (mode, target, val);
16647 : :
16648 : 321 : case E_V8DImode:
16649 : 321 : if (CONST_INT_P (val))
16650 : : {
16651 : 235 : int tmp = (int)INTVAL (val);
16652 : 235 : if (tmp == (int)(INTVAL (val) >> 32))
16653 : : {
16654 : 21 : rtx reg = gen_reg_rtx (V16SImode);
16655 : 21 : ok = ix86_vector_duplicate_value (V16SImode, reg,
16656 : : GEN_INT (tmp));
16657 : 21 : if (ok)
16658 : : {
16659 : 21 : emit_move_insn (target, gen_lowpart (V8DImode, reg));
16660 : 21 : return true;
16661 : : }
16662 : : }
16663 : : }
16664 : 300 : return ix86_vector_duplicate_value (mode, target, val);
16665 : :
16666 : 2305 : case E_V2SImode:
16667 : 2305 : case E_V2SFmode:
16668 : 2305 : if (!mmx_ok)
16669 : : return false;
16670 : : /* FALLTHRU */
16671 : :
16672 : 67101 : case E_V4DFmode:
16673 : 67101 : case E_V8SFmode:
16674 : 67101 : case E_V8SImode:
16675 : 67101 : case E_V2DFmode:
16676 : 67101 : case E_V4SFmode:
16677 : 67101 : case E_V4SImode:
16678 : 67101 : case E_V16SImode:
16679 : 67101 : case E_V16SFmode:
16680 : 67101 : case E_V8DFmode:
16681 : 67101 : return ix86_vector_duplicate_value (mode, target, val);
16682 : :
16683 : 381 : case E_V4HImode:
16684 : 381 : if (!mmx_ok)
16685 : : return false;
16686 : 378 : if (TARGET_SSE || TARGET_3DNOW_A)
16687 : : {
16688 : 378 : rtx x;
16689 : :
16690 : 378 : val = gen_lowpart (SImode, val);
16691 : 378 : if (CONST_INT_P (val))
16692 : : return false;
16693 : 376 : x = gen_rtx_TRUNCATE (HImode, val);
16694 : 376 : x = gen_rtx_VEC_DUPLICATE (mode, x);
16695 : 376 : emit_insn (gen_rtx_SET (target, x));
16696 : 376 : return true;
16697 : : }
16698 : 0 : goto widen;
16699 : :
16700 : 5 : case E_V4HFmode:
16701 : 5 : case E_V4BFmode:
16702 : 5 : if (TARGET_MMX_WITH_SSE)
16703 : : {
16704 : 10 : val = force_reg (GET_MODE_INNER (mode), val);
16705 : 5 : rtx x = gen_rtx_VEC_DUPLICATE (mode, val);
16706 : 5 : emit_insn (gen_rtx_SET (target, x));
16707 : 5 : return true;
16708 : : }
16709 : : return false;
16710 : :
16711 : 101 : case E_V2HImode:
16712 : 101 : if (TARGET_SSE2)
16713 : : {
16714 : 101 : rtx x;
16715 : :
16716 : 101 : val = gen_lowpart (SImode, val);
16717 : 101 : if (CONST_INT_P (val))
16718 : : return false;
16719 : 101 : x = gen_rtx_TRUNCATE (HImode, val);
16720 : 101 : x = gen_rtx_VEC_DUPLICATE (mode, x);
16721 : 101 : emit_insn (gen_rtx_SET (target, x));
16722 : 101 : return true;
16723 : : }
16724 : : return false;
16725 : :
16726 : 3 : case E_V2HFmode:
16727 : 3 : case E_V2BFmode:
16728 : 3 : if (TARGET_SSE2)
16729 : : {
16730 : 6 : val = force_reg (GET_MODE_INNER (mode), val);
16731 : 3 : rtx x = gen_rtx_VEC_DUPLICATE (mode, val);
16732 : 3 : emit_insn (gen_rtx_SET (target, x));
16733 : 3 : return true;
16734 : : }
16735 : : return false;
16736 : :
16737 : 286 : case E_V8QImode:
16738 : 286 : case E_V4QImode:
16739 : 286 : if (!mmx_ok)
16740 : : return false;
16741 : 282 : goto widen;
16742 : :
16743 : 9065 : case E_V8HImode:
16744 : 9065 : if (CONST_INT_P (val))
16745 : 8619 : goto widen;
16746 : : /* FALLTHRU */
16747 : :
16748 : 735 : case E_V8HFmode:
16749 : 735 : case E_V8BFmode:
16750 : 735 : if (TARGET_AVX2)
16751 : 334 : return ix86_vector_duplicate_value (mode, target, val);
16752 : :
16753 : 401 : if (TARGET_SSE2)
16754 : : {
16755 : 1112 : struct expand_vec_perm_d dperm;
16756 : 1112 : rtx tmp1, tmp2;
16757 : :
16758 : 401 : permute:
16759 : 1112 : memset (&dperm, 0, sizeof (dperm));
16760 : 1112 : dperm.target = target;
16761 : 1112 : dperm.vmode = mode;
16762 : 1112 : dperm.nelt = GET_MODE_NUNITS (mode);
16763 : 1112 : dperm.op0 = dperm.op1 = gen_reg_rtx (mode);
16764 : 1112 : dperm.one_operand_p = true;
16765 : :
16766 : 1112 : if (mode == V8HFmode || mode == V8BFmode)
16767 : : {
16768 : 3 : tmp1 = force_reg (GET_MODE_INNER (mode), val);
16769 : 3 : tmp2 = gen_reg_rtx (mode);
16770 : 3 : emit_insn (gen_vec_set_0 (mode, tmp2, CONST0_RTX (mode), tmp1));
16771 : 3 : tmp1 = gen_lowpart (mode, tmp2);
16772 : : }
16773 : : else
16774 : : {
16775 : : /* Extend to SImode using a paradoxical SUBREG. */
16776 : 1109 : tmp1 = gen_reg_rtx (SImode);
16777 : 1109 : emit_move_insn (tmp1, gen_lowpart (SImode, val));
16778 : :
16779 : : /* Insert the SImode value as
16780 : : low element of a V4SImode vector. */
16781 : 1109 : tmp2 = gen_reg_rtx (V4SImode);
16782 : 1109 : emit_insn (gen_vec_setv4si_0 (tmp2, CONST0_RTX (V4SImode), tmp1));
16783 : 1109 : tmp1 = gen_lowpart (mode, tmp2);
16784 : : }
16785 : :
16786 : 1112 : emit_move_insn (dperm.op0, tmp1);
16787 : 1112 : ok = (expand_vec_perm_1 (&dperm)
16788 : 1112 : || expand_vec_perm_broadcast_1 (&dperm));
16789 : 0 : gcc_assert (ok);
16790 : 1112 : return ok;
16791 : : }
16792 : 0 : goto widen;
16793 : :
16794 : 4931 : case E_V16QImode:
16795 : 4931 : if (CONST_INT_P (val))
16796 : 4167 : goto widen;
16797 : 764 : if (TARGET_AVX2)
16798 : 53 : return ix86_vector_duplicate_value (mode, target, val);
16799 : :
16800 : 711 : if (TARGET_SSE2)
16801 : 711 : goto permute;
16802 : 0 : goto widen;
16803 : :
16804 : 14417 : widen:
16805 : : /* Replicate the value once into the next wider mode and recurse. */
16806 : 14417 : {
16807 : 14417 : machine_mode smode, wsmode, wvmode;
16808 : 14417 : rtx x;
16809 : :
16810 : 14417 : smode = GET_MODE_INNER (mode);
16811 : 14417 : wvmode = get_mode_wider_vector (mode);
16812 : 14417 : wsmode = GET_MODE_INNER (wvmode);
16813 : :
16814 : 14417 : val = convert_modes (wsmode, smode, val, true);
16815 : :
16816 : 14417 : if (CONST_INT_P (val))
16817 : : {
16818 : 28272 : x = simplify_binary_operation (ASHIFT, wsmode, val,
16819 : 14136 : GEN_INT (GET_MODE_BITSIZE (smode)));
16820 : 14136 : val = simplify_binary_operation (IOR, wsmode, val, x);
16821 : : }
16822 : 281 : else if (smode == QImode && !TARGET_PARTIAL_REG_STALL)
16823 : 281 : emit_insn (gen_insv_1 (wsmode, val, val));
16824 : : else
16825 : : {
16826 : 0 : x = expand_simple_binop (wsmode, ASHIFT, val,
16827 : 0 : GEN_INT (GET_MODE_BITSIZE (smode)),
16828 : : NULL_RTX, 1, OPTAB_LIB_WIDEN);
16829 : 0 : val = expand_simple_binop (wsmode, IOR, val, x, x, 1,
16830 : : OPTAB_LIB_WIDEN);
16831 : : }
16832 : :
16833 : 14417 : x = gen_reg_rtx (wvmode);
16834 : 14417 : ok = ix86_expand_vector_init_duplicate (mmx_ok, wvmode, x, val);
16835 : 14417 : if (!ok)
16836 : : return false;
16837 : 14416 : emit_move_insn (target, gen_lowpart (GET_MODE (target), x));
16838 : 14416 : return true;
16839 : : }
16840 : :
16841 : 1068 : case E_V16HImode:
16842 : 1068 : case E_V32QImode:
16843 : 1068 : if (CONST_INT_P (val))
16844 : 808 : goto widen;
16845 : : /* FALLTHRU */
16846 : :
16847 : 318 : case E_V16HFmode:
16848 : 318 : case E_V16BFmode:
16849 : 318 : if (TARGET_AVX2)
16850 : 290 : return ix86_vector_duplicate_value (mode, target, val);
16851 : : else
16852 : : {
16853 : 28 : machine_mode hvmode;
16854 : 28 : switch (mode)
16855 : : {
16856 : : case V16HImode:
16857 : : hvmode = V8HImode;
16858 : : break;
16859 : 0 : case V16HFmode:
16860 : 0 : hvmode = V8HFmode;
16861 : 0 : break;
16862 : 1 : case V16BFmode:
16863 : 1 : hvmode = V8BFmode;
16864 : 1 : break;
16865 : 14 : case V32QImode:
16866 : 14 : hvmode = V16QImode;
16867 : 14 : break;
16868 : 0 : default:
16869 : 0 : gcc_unreachable ();
16870 : : }
16871 : 28 : rtx x = gen_reg_rtx (hvmode);
16872 : :
16873 : 28 : ok = ix86_expand_vector_init_duplicate (false, hvmode, x, val);
16874 : 28 : if (!ok)
16875 : : return false;
16876 : :
16877 : 28 : x = gen_rtx_VEC_CONCAT (mode, x, x);
16878 : 28 : emit_insn (gen_rtx_SET (target, x));
16879 : : }
16880 : 28 : return true;
16881 : :
16882 : 631 : case E_V32HImode:
16883 : 631 : case E_V64QImode:
16884 : 631 : if (CONST_INT_P (val))
16885 : 541 : goto widen;
16886 : : /* FALLTHRU */
16887 : :
16888 : 140 : case E_V32HFmode:
16889 : 140 : case E_V32BFmode:
16890 : 140 : if (TARGET_AVX512BW)
16891 : 120 : return ix86_vector_duplicate_value (mode, target, val);
16892 : : else
16893 : : {
16894 : 20 : machine_mode hvmode;
16895 : 20 : switch (mode)
16896 : : {
16897 : : case V32HImode:
16898 : : hvmode = V16HImode;
16899 : : break;
16900 : 0 : case V32HFmode:
16901 : 0 : hvmode = V16HFmode;
16902 : 0 : break;
16903 : 1 : case V32BFmode:
16904 : 1 : hvmode = V16BFmode;
16905 : 1 : break;
16906 : 10 : case V64QImode:
16907 : 10 : hvmode = V32QImode;
16908 : 10 : break;
16909 : 0 : default:
16910 : 0 : gcc_unreachable ();
16911 : : }
16912 : 20 : rtx x = gen_reg_rtx (hvmode);
16913 : :
16914 : 20 : ok = ix86_expand_vector_init_duplicate (false, hvmode, x, val);
16915 : 20 : if (!ok)
16916 : : return false;
16917 : :
16918 : 20 : x = gen_rtx_VEC_CONCAT (mode, x, x);
16919 : 20 : emit_insn (gen_rtx_SET (target, x));
16920 : : }
16921 : 20 : return true;
16922 : :
16923 : : default:
16924 : : return false;
16925 : : }
16926 : : }
16927 : :
16928 : : /* A subroutine of ix86_expand_vector_init. Store into TARGET a vector
16929 : : whose ONE_VAR element is VAR, and other elements are zero. Return true
16930 : : if successful. */
16931 : :
16932 : : bool
16933 : 11411 : ix86_expand_vector_init_one_nonzero (bool mmx_ok, machine_mode mode,
16934 : : rtx target, rtx var, int one_var)
16935 : : {
16936 : 11411 : machine_mode vsimode;
16937 : 11411 : rtx new_target;
16938 : 11411 : rtx x, tmp;
16939 : 11411 : bool use_vector_set = false;
16940 : 11411 : rtx (*gen_vec_set_0) (rtx, rtx, rtx) = NULL;
16941 : :
16942 : 11411 : switch (mode)
16943 : : {
16944 : 9363 : case E_V2DImode:
16945 : : /* For SSE4.1, we normally use vector set. But if the second
16946 : : element is zero and inter-unit moves are OK, we use movq
16947 : : instead. */
16948 : 9354 : use_vector_set = (TARGET_64BIT && TARGET_SSE4_1
16949 : 9468 : && !(TARGET_INTER_UNIT_MOVES_TO_VEC
16950 : : && one_var == 0));
16951 : : break;
16952 : 447 : case E_V16QImode:
16953 : 447 : case E_V4SImode:
16954 : 447 : case E_V4SFmode:
16955 : 447 : use_vector_set = TARGET_SSE4_1;
16956 : 447 : break;
16957 : 84 : case E_V8HImode:
16958 : 84 : use_vector_set = TARGET_SSE2;
16959 : 84 : gen_vec_set_0 = TARGET_AVX512FP16 && one_var == 0
16960 : 84 : ? gen_vec_setv8hi_0 : NULL;
16961 : : break;
16962 : 7 : case E_V8QImode:
16963 : 7 : use_vector_set = TARGET_MMX_WITH_SSE && TARGET_SSE4_1;
16964 : : break;
16965 : 14 : case E_V4HImode:
16966 : 14 : case E_V4HFmode:
16967 : 14 : case E_V4BFmode:
16968 : 14 : use_vector_set = TARGET_SSE || TARGET_3DNOW_A;
16969 : : break;
16970 : 17 : case E_V4QImode:
16971 : 17 : use_vector_set = TARGET_SSE4_1;
16972 : 17 : break;
16973 : 0 : case E_V32QImode:
16974 : 0 : use_vector_set = TARGET_AVX;
16975 : 0 : break;
16976 : 5 : case E_V16HImode:
16977 : 5 : use_vector_set = TARGET_AVX;
16978 : 5 : gen_vec_set_0 = TARGET_AVX512FP16 && one_var == 0
16979 : 5 : ? gen_vec_setv16hi_0 : NULL;
16980 : : break;
16981 : 3 : case E_V8SImode:
16982 : 3 : use_vector_set = TARGET_AVX;
16983 : 3 : gen_vec_set_0 = gen_vec_setv8si_0;
16984 : 3 : break;
16985 : 22 : case E_V8SFmode:
16986 : 22 : use_vector_set = TARGET_AVX;
16987 : 22 : gen_vec_set_0 = gen_vec_setv8sf_0;
16988 : 22 : break;
16989 : 13 : case E_V4DFmode:
16990 : 13 : use_vector_set = TARGET_AVX;
16991 : 13 : gen_vec_set_0 = gen_vec_setv4df_0;
16992 : 13 : break;
16993 : 7 : case E_V4DImode:
16994 : : /* Use ix86_expand_vector_set in 64bit mode only. */
16995 : 7 : use_vector_set = TARGET_AVX && TARGET_64BIT;
16996 : : gen_vec_set_0 = gen_vec_setv4di_0;
16997 : : break;
16998 : 17 : case E_V16SImode:
16999 : 17 : use_vector_set = TARGET_AVX512F && one_var == 0;
17000 : : gen_vec_set_0 = gen_vec_setv16si_0;
17001 : : break;
17002 : 22 : case E_V16SFmode:
17003 : 22 : use_vector_set = TARGET_AVX512F && one_var == 0;
17004 : : gen_vec_set_0 = gen_vec_setv16sf_0;
17005 : : break;
17006 : 0 : case E_V8DFmode:
17007 : 0 : use_vector_set = TARGET_AVX512F && one_var == 0;
17008 : : gen_vec_set_0 = gen_vec_setv8df_0;
17009 : : break;
17010 : 2 : case E_V8DImode:
17011 : : /* Use ix86_expand_vector_set in 64bit mode only. */
17012 : 2 : use_vector_set = TARGET_AVX512F && TARGET_64BIT && one_var == 0;
17013 : : gen_vec_set_0 = gen_vec_setv8di_0;
17014 : : break;
17015 : 38 : case E_V8HFmode:
17016 : 38 : use_vector_set = TARGET_AVX512FP16 && one_var == 0;
17017 : : gen_vec_set_0 = gen_vec_setv8hf_0;
17018 : : break;
17019 : 8 : case E_V16HFmode:
17020 : 8 : use_vector_set = TARGET_AVX512FP16 && one_var == 0;
17021 : : gen_vec_set_0 = gen_vec_setv16hf_0;
17022 : : break;
17023 : 6 : case E_V32HFmode:
17024 : 6 : use_vector_set = TARGET_AVX512FP16 && one_var == 0;
17025 : : gen_vec_set_0 = gen_vec_setv32hf_0;
17026 : : break;
17027 : 1 : case E_V8BFmode:
17028 : 1 : use_vector_set = TARGET_AVX512FP16 && one_var == 0;
17029 : : gen_vec_set_0 = gen_vec_setv8bf_0;
17030 : : break;
17031 : 0 : case E_V16BFmode:
17032 : 0 : use_vector_set = TARGET_AVX512FP16 && one_var == 0;
17033 : : gen_vec_set_0 = gen_vec_setv16bf_0;
17034 : : break;
17035 : 0 : case E_V32BFmode:
17036 : 0 : use_vector_set = TARGET_AVX512FP16 && one_var == 0;
17037 : : gen_vec_set_0 = gen_vec_setv32bf_0;
17038 : : break;
17039 : 4 : case E_V32HImode:
17040 : 4 : use_vector_set = TARGET_AVX512FP16 && one_var == 0;
17041 : : gen_vec_set_0 = gen_vec_setv32hi_0;
17042 : : default:
17043 : : break;
17044 : : }
17045 : :
17046 : 9968 : if (use_vector_set)
17047 : : {
17048 : 423 : if (gen_vec_set_0 && one_var == 0)
17049 : : {
17050 : 344 : var = force_reg (GET_MODE_INNER (mode), var);
17051 : 172 : emit_insn (gen_vec_set_0 (target, CONST0_RTX (mode), var));
17052 : 172 : return true;
17053 : : }
17054 : 251 : emit_insn (gen_rtx_SET (target, CONST0_RTX (mode)));
17055 : 502 : var = force_reg (GET_MODE_INNER (mode), var);
17056 : 251 : ix86_expand_vector_set (mmx_ok, target, var, one_var);
17057 : 251 : return true;
17058 : : }
17059 : :
17060 : 10988 : switch (mode)
17061 : : {
17062 : 1243 : case E_V2SFmode:
17063 : 1243 : case E_V2SImode:
17064 : 1243 : if (!mmx_ok)
17065 : : return false;
17066 : : /* FALLTHRU */
17067 : :
17068 : 9569 : case E_V2DFmode:
17069 : 9569 : case E_V2DImode:
17070 : 9569 : if (one_var != 0)
17071 : : return false;
17072 : 6138 : var = force_reg (GET_MODE_INNER (mode), var);
17073 : 6138 : x = gen_rtx_VEC_CONCAT (mode, var, CONST0_RTX (GET_MODE_INNER (mode)));
17074 : 3069 : emit_insn (gen_rtx_SET (target, x));
17075 : 3069 : return true;
17076 : :
17077 : 316 : case E_V4SFmode:
17078 : 316 : case E_V4SImode:
17079 : 316 : if (!REG_P (target) || REGNO (target) < FIRST_PSEUDO_REGISTER)
17080 : 0 : new_target = gen_reg_rtx (mode);
17081 : : else
17082 : : new_target = target;
17083 : 632 : var = force_reg (GET_MODE_INNER (mode), var);
17084 : 316 : x = gen_rtx_VEC_DUPLICATE (mode, var);
17085 : 316 : x = gen_rtx_VEC_MERGE (mode, x, CONST0_RTX (mode), const1_rtx);
17086 : 316 : emit_insn (gen_rtx_SET (new_target, x));
17087 : 316 : if (one_var != 0)
17088 : : {
17089 : : /* We need to shuffle the value to the correct position, so
17090 : : create a new pseudo to store the intermediate result. */
17091 : :
17092 : : /* With SSE2, we can use the integer shuffle insns. */
17093 : 43 : if (mode != V4SFmode && TARGET_SSE2)
17094 : : {
17095 : 30 : emit_insn (gen_sse2_pshufd_1 (new_target, new_target,
17096 : : const1_rtx,
17097 : 30 : GEN_INT (one_var == 1 ? 0 : 1),
17098 : 30 : GEN_INT (one_var == 2 ? 0 : 1),
17099 : 30 : GEN_INT (one_var == 3 ? 0 : 1)));
17100 : 30 : if (target != new_target)
17101 : 0 : emit_move_insn (target, new_target);
17102 : 30 : return true;
17103 : : }
17104 : :
17105 : : /* Otherwise convert the intermediate result to V4SFmode and
17106 : : use the SSE1 shuffle instructions. */
17107 : 0 : if (mode != V4SFmode)
17108 : : {
17109 : 0 : tmp = gen_reg_rtx (V4SFmode);
17110 : 0 : emit_move_insn (tmp, gen_lowpart (V4SFmode, new_target));
17111 : : }
17112 : : else
17113 : : tmp = new_target;
17114 : :
17115 : 43 : emit_insn (gen_sse_shufps_v4sf (tmp, tmp, tmp,
17116 : : const1_rtx,
17117 : 13 : GEN_INT (one_var == 1 ? 0 : 1),
17118 : : GEN_INT (one_var == 2 ? 0+4 : 1+4),
17119 : : GEN_INT (one_var == 3 ? 0+4 : 1+4)));
17120 : :
17121 : 13 : if (mode != V4SFmode)
17122 : 0 : emit_move_insn (target, gen_lowpart (V4SImode, tmp));
17123 : 13 : else if (tmp != target)
17124 : 0 : emit_move_insn (target, tmp);
17125 : : }
17126 : 273 : else if (target != new_target)
17127 : 0 : emit_move_insn (target, new_target);
17128 : : return true;
17129 : :
17130 : 12 : case E_V8HImode:
17131 : 12 : case E_V16QImode:
17132 : 12 : vsimode = V4SImode;
17133 : 12 : goto widen;
17134 : 2 : case E_V4HImode:
17135 : 2 : case E_V8QImode:
17136 : 2 : if (!mmx_ok)
17137 : : return false;
17138 : 2 : vsimode = V2SImode;
17139 : 2 : goto widen;
17140 : 14 : widen:
17141 : 14 : if (one_var != 0)
17142 : : return false;
17143 : :
17144 : : /* Zero extend the variable element to SImode and recurse. */
17145 : 14 : var = convert_modes (SImode, GET_MODE_INNER (mode), var, true);
17146 : :
17147 : 7 : x = gen_reg_rtx (vsimode);
17148 : 7 : if (!ix86_expand_vector_init_one_nonzero (mmx_ok, vsimode, x,
17149 : : var, one_var))
17150 : 0 : gcc_unreachable ();
17151 : :
17152 : 7 : emit_move_insn (target, gen_lowpart (mode, x));
17153 : 7 : return true;
17154 : :
17155 : : default:
17156 : : return false;
17157 : : }
17158 : : }
17159 : :
17160 : : /* A subroutine of ix86_expand_vector_init. Store into TARGET a vector
17161 : : consisting of the values in VALS. It is known that all elements
17162 : : except ONE_VAR are constants. Return true if successful. */
17163 : :
17164 : : static bool
17165 : 8727 : ix86_expand_vector_init_one_var (bool mmx_ok, machine_mode mode,
17166 : : rtx target, rtx vals, int one_var)
17167 : : {
17168 : 8727 : rtx var = XVECEXP (vals, 0, one_var);
17169 : 8727 : machine_mode wmode;
17170 : 8727 : rtx const_vec, x;
17171 : :
17172 : 8727 : const_vec = copy_rtx (vals);
17173 : 8727 : XVECEXP (const_vec, 0, one_var) = CONST0_RTX (GET_MODE_INNER (mode));
17174 : 8727 : const_vec = gen_rtx_CONST_VECTOR (mode, XVEC (const_vec, 0));
17175 : :
17176 : 8727 : switch (mode)
17177 : : {
17178 : : case E_V2DFmode:
17179 : : case E_V2DImode:
17180 : : case E_V2SFmode:
17181 : : case E_V2SImode:
17182 : : /* For the two element vectors, it's just as easy to use
17183 : : the general case. */
17184 : : return false;
17185 : :
17186 : 3 : case E_V4DImode:
17187 : : /* Use ix86_expand_vector_set in 64bit mode only. */
17188 : 3 : if (!TARGET_64BIT)
17189 : : return false;
17190 : : /* FALLTHRU */
17191 : : case E_V8HFmode:
17192 : : case E_V16HFmode:
17193 : : case E_V8BFmode:
17194 : : case E_V16BFmode:
17195 : : case E_V4DFmode:
17196 : : case E_V8SFmode:
17197 : : case E_V8SImode:
17198 : : case E_V16HImode:
17199 : : case E_V32QImode:
17200 : : case E_V4SFmode:
17201 : : case E_V4SImode:
17202 : : case E_V8HImode:
17203 : : case E_V4HImode:
17204 : : case E_V4HFmode:
17205 : : case E_V4BFmode:
17206 : : break;
17207 : :
17208 : 8 : case E_V16QImode:
17209 : 8 : if (TARGET_SSE4_1)
17210 : : break;
17211 : 8 : wmode = V8HImode;
17212 : 8 : goto widen;
17213 : 0 : case E_V8QImode:
17214 : 0 : if (TARGET_MMX_WITH_SSE && TARGET_SSE4_1)
17215 : : break;
17216 : 0 : wmode = V4HImode;
17217 : 0 : goto widen;
17218 : 23 : case E_V4QImode:
17219 : 23 : if (TARGET_SSE4_1)
17220 : : break;
17221 : : wmode = V2HImode;
17222 : 31 : widen:
17223 : : /* There's no way to set one QImode entry easily. Combine
17224 : : the variable value with its adjacent constant value, and
17225 : : promote to an HImode set. */
17226 : 31 : x = XVECEXP (vals, 0, one_var ^ 1);
17227 : 31 : if (one_var & 1)
17228 : : {
17229 : 12 : var = convert_modes (HImode, QImode, var, true);
17230 : 12 : var = expand_simple_binop (HImode, ASHIFT, var, GEN_INT (8),
17231 : : NULL_RTX, 1, OPTAB_LIB_WIDEN);
17232 : 12 : x = GEN_INT (INTVAL (x) & 0xff);
17233 : : }
17234 : : else
17235 : : {
17236 : 19 : var = convert_modes (HImode, QImode, var, true);
17237 : 19 : x = gen_int_mode (UINTVAL (x) << 8, HImode);
17238 : : }
17239 : 31 : if (x != const0_rtx)
17240 : 7 : var = expand_simple_binop (HImode, IOR, var, x, var,
17241 : : 1, OPTAB_LIB_WIDEN);
17242 : :
17243 : 31 : x = gen_reg_rtx (wmode);
17244 : 31 : emit_move_insn (x, gen_lowpart (wmode, const_vec));
17245 : 31 : ix86_expand_vector_set (mmx_ok, x, var, one_var >> 1);
17246 : :
17247 : 31 : emit_move_insn (target, gen_lowpart (mode, x));
17248 : 31 : return true;
17249 : :
17250 : : default:
17251 : : return false;
17252 : : }
17253 : :
17254 : 187 : emit_move_insn (target, const_vec);
17255 : 187 : ix86_expand_vector_set (mmx_ok, target, var, one_var);
17256 : 187 : return true;
17257 : : }
17258 : :
17259 : : /* A subroutine of ix86_expand_vector_init_general. Use vector
17260 : : concatenate to handle the most general case: all values variable,
17261 : : and none identical. */
17262 : :
17263 : : static void
17264 : 120133 : ix86_expand_vector_init_concat (machine_mode mode,
17265 : : rtx target, rtx *ops, int n)
17266 : : {
17267 : 120133 : machine_mode half_mode = VOIDmode;
17268 : 120133 : rtx half[2];
17269 : 120133 : rtvec v;
17270 : 120133 : int i, j;
17271 : :
17272 : 120133 : switch (n)
17273 : : {
17274 : 112338 : case 2:
17275 : 112338 : switch (mode)
17276 : : {
17277 : : case E_V32HFmode:
17278 : : half_mode = V16HFmode;
17279 : : break;
17280 : 0 : case E_V32BFmode:
17281 : 0 : half_mode = V16BFmode;
17282 : 0 : break;
17283 : 82 : case E_V16SImode:
17284 : 82 : half_mode = V8SImode;
17285 : 82 : break;
17286 : 33 : case E_V16SFmode:
17287 : 33 : half_mode = V8SFmode;
17288 : 33 : break;
17289 : 88 : case E_V8DImode:
17290 : 88 : half_mode = V4DImode;
17291 : 88 : break;
17292 : 76 : case E_V8DFmode:
17293 : 76 : half_mode = V4DFmode;
17294 : 76 : break;
17295 : 0 : case E_V16HFmode:
17296 : 0 : half_mode = V8HFmode;
17297 : 0 : break;
17298 : 0 : case E_V16BFmode:
17299 : 0 : half_mode = V8BFmode;
17300 : 0 : break;
17301 : 187 : case E_V8SImode:
17302 : 187 : half_mode = V4SImode;
17303 : 187 : break;
17304 : 143 : case E_V8SFmode:
17305 : 143 : half_mode = V4SFmode;
17306 : 143 : break;
17307 : 296 : case E_V4DImode:
17308 : 296 : half_mode = V2DImode;
17309 : 296 : break;
17310 : 480 : case E_V4DFmode:
17311 : 480 : half_mode = V2DFmode;
17312 : 480 : break;
17313 : 5757 : case E_V4SImode:
17314 : 5757 : half_mode = V2SImode;
17315 : 5757 : break;
17316 : 1873 : case E_V4SFmode:
17317 : 1873 : half_mode = V2SFmode;
17318 : 1873 : break;
17319 : 68040 : case E_V2DImode:
17320 : 68040 : half_mode = DImode;
17321 : 68040 : break;
17322 : 27082 : case E_V2SImode:
17323 : 27082 : half_mode = SImode;
17324 : 27082 : break;
17325 : 3559 : case E_V2DFmode:
17326 : 3559 : half_mode = DFmode;
17327 : 3559 : break;
17328 : 4642 : case E_V2SFmode:
17329 : 4642 : half_mode = SFmode;
17330 : 4642 : break;
17331 : 0 : default:
17332 : 0 : gcc_unreachable ();
17333 : : }
17334 : :
17335 : 112338 : if (!register_operand (ops[1], half_mode))
17336 : 50780 : ops[1] = force_reg (half_mode, ops[1]);
17337 : 112338 : if (!register_operand (ops[0], half_mode))
17338 : 39607 : ops[0] = force_reg (half_mode, ops[0]);
17339 : 112338 : emit_insn (gen_rtx_SET (target, gen_rtx_VEC_CONCAT (mode, ops[0],
17340 : : ops[1])));
17341 : 112338 : break;
17342 : :
17343 : 7289 : case 4:
17344 : 7289 : switch (mode)
17345 : : {
17346 : : case E_V4DImode:
17347 : : half_mode = V2DImode;
17348 : : break;
17349 : 406 : case E_V4DFmode:
17350 : 406 : half_mode = V2DFmode;
17351 : 406 : break;
17352 : 4967 : case E_V4SImode:
17353 : 4967 : half_mode = V2SImode;
17354 : 4967 : break;
17355 : 1746 : case E_V4SFmode:
17356 : 1746 : half_mode = V2SFmode;
17357 : 1746 : break;
17358 : 0 : default:
17359 : 0 : gcc_unreachable ();
17360 : : }
17361 : 7289 : goto half;
17362 : :
17363 : 412 : case 8:
17364 : 412 : switch (mode)
17365 : : {
17366 : : case E_V8DImode:
17367 : : half_mode = V4DImode;
17368 : : break;
17369 : 76 : case E_V8DFmode:
17370 : 76 : half_mode = V4DFmode;
17371 : 76 : break;
17372 : 152 : case E_V8SImode:
17373 : 152 : half_mode = V4SImode;
17374 : 152 : break;
17375 : 137 : case E_V8SFmode:
17376 : 137 : half_mode = V4SFmode;
17377 : 137 : break;
17378 : 0 : default:
17379 : 0 : gcc_unreachable ();
17380 : : }
17381 : 412 : goto half;
17382 : :
17383 : 94 : case 16:
17384 : 94 : switch (mode)
17385 : : {
17386 : : case E_V16SImode:
17387 : : half_mode = V8SImode;
17388 : : break;
17389 : 33 : case E_V16SFmode:
17390 : 33 : half_mode = V8SFmode;
17391 : 33 : break;
17392 : 0 : default:
17393 : 0 : gcc_unreachable ();
17394 : : }
17395 : 94 : goto half;
17396 : :
17397 : 7795 : half:
17398 : : /* FIXME: We process inputs backward to help RA. PR 36222. */
17399 : 7795 : i = n - 1;
17400 : 23385 : for (j = 1; j != -1; j--)
17401 : : {
17402 : 15590 : half[j] = gen_reg_rtx (half_mode);
17403 : 15590 : switch (n >> 1)
17404 : : {
17405 : 14578 : case 2:
17406 : 14578 : v = gen_rtvec (2, ops[i-1], ops[i]);
17407 : 14578 : i -= 2;
17408 : 14578 : break;
17409 : 824 : case 4:
17410 : 824 : v = gen_rtvec (4, ops[i-3], ops[i-2], ops[i-1], ops[i]);
17411 : 824 : i -= 4;
17412 : 824 : break;
17413 : 188 : case 8:
17414 : 376 : v = gen_rtvec (8, ops[i-7], ops[i-6], ops[i-5], ops[i-4],
17415 : 188 : ops[i-3], ops[i-2], ops[i-1], ops[i]);
17416 : 188 : i -= 8;
17417 : 188 : break;
17418 : 0 : default:
17419 : 0 : gcc_unreachable ();
17420 : : }
17421 : 15590 : ix86_expand_vector_init (false, half[j],
17422 : : gen_rtx_PARALLEL (half_mode, v));
17423 : : }
17424 : :
17425 : 7795 : ix86_expand_vector_init_concat (mode, target, half, 2);
17426 : 7795 : break;
17427 : :
17428 : 0 : default:
17429 : 0 : gcc_unreachable ();
17430 : : }
17431 : 120133 : }
17432 : :
17433 : : /* A subroutine of ix86_expand_vector_init_general. Use vector
17434 : : interleave to handle the most general case: all values variable,
17435 : : and none identical. */
17436 : :
17437 : : static void
17438 : 3825 : ix86_expand_vector_init_interleave (machine_mode mode,
17439 : : rtx target, rtx *ops, int n)
17440 : : {
17441 : 3825 : machine_mode first_imode, second_imode, third_imode, inner_mode;
17442 : 3825 : int i, j;
17443 : 3825 : rtx op, op0, op1;
17444 : 3825 : rtx (*gen_load_even) (rtx, rtx, rtx);
17445 : 3825 : rtx (*gen_interleave_first_low) (rtx, rtx, rtx);
17446 : 3825 : rtx (*gen_interleave_second_low) (rtx, rtx, rtx);
17447 : :
17448 : 3825 : switch (mode)
17449 : : {
17450 : : case E_V8HFmode:
17451 : : gen_load_even = gen_vec_interleave_lowv8hf;
17452 : : gen_interleave_first_low = gen_vec_interleave_lowv4si;
17453 : : gen_interleave_second_low = gen_vec_interleave_lowv2di;
17454 : : inner_mode = HFmode;
17455 : : first_imode = V4SImode;
17456 : : second_imode = V2DImode;
17457 : : third_imode = VOIDmode;
17458 : : break;
17459 : 487 : case E_V8BFmode:
17460 : 487 : gen_load_even = gen_vec_interleave_lowv8bf;
17461 : 487 : gen_interleave_first_low = gen_vec_interleave_lowv4si;
17462 : 487 : gen_interleave_second_low = gen_vec_interleave_lowv2di;
17463 : 487 : inner_mode = BFmode;
17464 : 487 : first_imode = V4SImode;
17465 : 487 : second_imode = V2DImode;
17466 : 487 : third_imode = VOIDmode;
17467 : 487 : break;
17468 : 744 : case E_V8HImode:
17469 : 744 : gen_load_even = gen_vec_setv8hi;
17470 : 744 : gen_interleave_first_low = gen_vec_interleave_lowv4si;
17471 : 744 : gen_interleave_second_low = gen_vec_interleave_lowv2di;
17472 : 744 : inner_mode = HImode;
17473 : 744 : first_imode = V4SImode;
17474 : 744 : second_imode = V2DImode;
17475 : 744 : third_imode = VOIDmode;
17476 : 744 : break;
17477 : 368 : case E_V16QImode:
17478 : 368 : gen_load_even = gen_vec_setv16qi;
17479 : 368 : gen_interleave_first_low = gen_vec_interleave_lowv8hi;
17480 : 368 : gen_interleave_second_low = gen_vec_interleave_lowv4si;
17481 : 368 : inner_mode = QImode;
17482 : 368 : first_imode = V8HImode;
17483 : 368 : second_imode = V4SImode;
17484 : 368 : third_imode = V2DImode;
17485 : 368 : break;
17486 : 0 : default:
17487 : 0 : gcc_unreachable ();
17488 : : }
17489 : :
17490 : 20597 : for (i = 0; i < n; i++)
17491 : : {
17492 : 16772 : op = ops [i + i];
17493 : 16772 : if (inner_mode == HFmode || inner_mode == BFmode)
17494 : : {
17495 : 10852 : rtx even, odd;
17496 : : /* Use vpuncklwd to pack 2 HFmode or BFmode. */
17497 : 1948 : machine_mode vec_mode =
17498 : 10852 : (inner_mode == HFmode) ? V8HFmode : V8BFmode;
17499 : 10852 : op0 = gen_reg_rtx (vec_mode);
17500 : 10852 : even = lowpart_subreg (vec_mode,
17501 : : force_reg (inner_mode, op), inner_mode);
17502 : 10852 : odd = lowpart_subreg (vec_mode,
17503 : 10852 : force_reg (inner_mode, ops[i + i + 1]),
17504 : : inner_mode);
17505 : 10852 : emit_insn (gen_load_even (op0, even, odd));
17506 : : }
17507 : : else
17508 : : {
17509 : : /* Extend the odd elment to SImode using a paradoxical SUBREG. */
17510 : 5920 : op0 = gen_reg_rtx (SImode);
17511 : 5920 : emit_move_insn (op0, gen_lowpart (SImode, op));
17512 : :
17513 : : /* Insert the SImode value as low element of V4SImode vector. */
17514 : 5920 : op1 = gen_reg_rtx (V4SImode);
17515 : 5920 : op0 = gen_rtx_VEC_MERGE (V4SImode,
17516 : : gen_rtx_VEC_DUPLICATE (V4SImode,
17517 : : op0),
17518 : : CONST0_RTX (V4SImode),
17519 : : const1_rtx);
17520 : 5920 : emit_insn (gen_rtx_SET (op1, op0));
17521 : :
17522 : : /* Cast the V4SImode vector back to a vector in orignal mode. */
17523 : 5920 : op0 = gen_reg_rtx (mode);
17524 : 5920 : emit_move_insn (op0, gen_lowpart (mode, op1));
17525 : :
17526 : : /* Load even elements into the second position. */
17527 : 5920 : emit_insn (gen_load_even (op0,
17528 : : force_reg (inner_mode,
17529 : 5920 : ops[i + i + 1]),
17530 : : const1_rtx));
17531 : : }
17532 : :
17533 : : /* Cast vector to FIRST_IMODE vector. */
17534 : 16772 : ops[i] = gen_reg_rtx (first_imode);
17535 : 16772 : emit_move_insn (ops[i], gen_lowpart (first_imode, op0));
17536 : : }
17537 : :
17538 : : /* Interleave low FIRST_IMODE vectors. */
17539 : 12211 : for (i = j = 0; i < n; i += 2, j++)
17540 : : {
17541 : 8386 : op0 = gen_reg_rtx (first_imode);
17542 : 8386 : emit_insn (gen_interleave_first_low (op0, ops[i], ops[i + 1]));
17543 : :
17544 : : /* Cast FIRST_IMODE vector to SECOND_IMODE vector. */
17545 : 8386 : ops[j] = gen_reg_rtx (second_imode);
17546 : 8386 : emit_move_insn (ops[j], gen_lowpart (second_imode, op0));
17547 : : }
17548 : :
17549 : : /* Interleave low SECOND_IMODE vectors. */
17550 : 3825 : switch (second_imode)
17551 : : {
17552 : : case E_V4SImode:
17553 : 1104 : for (i = j = 0; i < n / 2; i += 2, j++)
17554 : : {
17555 : 736 : op0 = gen_reg_rtx (second_imode);
17556 : 736 : emit_insn (gen_interleave_second_low (op0, ops[i],
17557 : 736 : ops[i + 1]));
17558 : :
17559 : : /* Cast the SECOND_IMODE vector to the THIRD_IMODE
17560 : : vector. */
17561 : 736 : ops[j] = gen_reg_rtx (third_imode);
17562 : 736 : emit_move_insn (ops[j], gen_lowpart (third_imode, op0));
17563 : : }
17564 : : second_imode = V2DImode;
17565 : : gen_interleave_second_low = gen_vec_interleave_lowv2di;
17566 : : /* FALLTHRU */
17567 : :
17568 : 3825 : case E_V2DImode:
17569 : 3825 : op0 = gen_reg_rtx (second_imode);
17570 : 3825 : emit_insn (gen_interleave_second_low (op0, ops[0],
17571 : : ops[1]));
17572 : :
17573 : : /* Cast the SECOND_IMODE vector back to a vector on original
17574 : : mode. */
17575 : 3825 : emit_insn (gen_rtx_SET (target, gen_lowpart (mode, op0)));
17576 : 3825 : break;
17577 : :
17578 : : default:
17579 : : gcc_unreachable ();
17580 : : }
17581 : 3825 : }
17582 : :
17583 : : /* A subroutine of ix86_expand_vector_init. Handle the most general case:
17584 : : all values variable, and none identical. */
17585 : :
17586 : : static void
17587 : 121496 : ix86_expand_vector_init_general (bool mmx_ok, machine_mode mode,
17588 : : rtx target, rtx vals)
17589 : : {
17590 : 121496 : rtx ops[64], op0, op1, op2, op3, op4, op5;
17591 : 121496 : machine_mode half_mode = VOIDmode;
17592 : 121496 : machine_mode quarter_mode = VOIDmode;
17593 : 121496 : machine_mode int_inner_mode = VOIDmode;
17594 : 121496 : int n, i;
17595 : :
17596 : 121496 : switch (mode)
17597 : : {
17598 : 31724 : case E_V2SFmode:
17599 : 31724 : case E_V2SImode:
17600 : 31724 : if (!mmx_ok && !TARGET_SSE)
17601 : : break;
17602 : : /* FALLTHRU */
17603 : :
17604 : 111118 : case E_V16SImode:
17605 : 111118 : case E_V16SFmode:
17606 : 111118 : case E_V8DFmode:
17607 : 111118 : case E_V8DImode:
17608 : 111118 : case E_V8SFmode:
17609 : 111118 : case E_V8SImode:
17610 : 111118 : case E_V4DFmode:
17611 : 111118 : case E_V4DImode:
17612 : 111118 : case E_V4SFmode:
17613 : 111118 : case E_V4SImode:
17614 : 111118 : case E_V2DFmode:
17615 : 111118 : case E_V2DImode:
17616 : 111118 : n = GET_MODE_NUNITS (mode);
17617 : 351720 : for (i = 0; i < n; i++)
17618 : 240602 : ops[i] = XVECEXP (vals, 0, i);
17619 : 111118 : ix86_expand_vector_init_concat (mode, target, ops, n);
17620 : 224289 : return;
17621 : :
17622 : : case E_V2TImode:
17623 : 135 : for (i = 0; i < 2; i++)
17624 : 90 : ops[i] = gen_lowpart (V2DImode, XVECEXP (vals, 0, i));
17625 : 45 : op0 = gen_reg_rtx (V4DImode);
17626 : 45 : ix86_expand_vector_init_concat (V4DImode, op0, ops, 2);
17627 : 45 : emit_move_insn (target, gen_lowpart (GET_MODE (target), op0));
17628 : 45 : return;
17629 : :
17630 : : case E_V4TImode:
17631 : 195 : for (i = 0; i < 4; i++)
17632 : 156 : ops[i] = gen_lowpart (V2DImode, XVECEXP (vals, 0, i));
17633 : 39 : ops[4] = gen_reg_rtx (V4DImode);
17634 : 39 : ix86_expand_vector_init_concat (V4DImode, ops[4], ops, 2);
17635 : 39 : ops[5] = gen_reg_rtx (V4DImode);
17636 : 39 : ix86_expand_vector_init_concat (V4DImode, ops[5], ops + 2, 2);
17637 : 39 : op0 = gen_reg_rtx (V8DImode);
17638 : 39 : ix86_expand_vector_init_concat (V8DImode, op0, ops + 4, 2);
17639 : 39 : emit_move_insn (target, gen_lowpart (GET_MODE (target), op0));
17640 : 39 : return;
17641 : :
17642 : 68 : case E_V32QImode:
17643 : 68 : half_mode = V16QImode;
17644 : 68 : goto half;
17645 : :
17646 : 64 : case E_V16HImode:
17647 : 64 : half_mode = V8HImode;
17648 : 64 : goto half;
17649 : :
17650 : 237 : case E_V16HFmode:
17651 : 237 : half_mode = V8HFmode;
17652 : 237 : goto half;
17653 : :
17654 : 95 : case E_V16BFmode:
17655 : 95 : half_mode = V8BFmode;
17656 : 95 : goto half;
17657 : :
17658 : 464 : half:
17659 : 464 : n = GET_MODE_NUNITS (mode);
17660 : 8976 : for (i = 0; i < n; i++)
17661 : 8512 : ops[i] = XVECEXP (vals, 0, i);
17662 : 464 : op0 = gen_reg_rtx (half_mode);
17663 : 464 : op1 = gen_reg_rtx (half_mode);
17664 : 464 : ix86_expand_vector_init_interleave (half_mode, op0, ops,
17665 : : n >> 2);
17666 : 464 : ix86_expand_vector_init_interleave (half_mode, op1,
17667 : 464 : &ops [n >> 1], n >> 2);
17668 : 464 : emit_insn (gen_rtx_SET (target, gen_rtx_VEC_CONCAT (mode, op0, op1)));
17669 : 464 : return;
17670 : :
17671 : 55 : case E_V64QImode:
17672 : 55 : quarter_mode = V16QImode;
17673 : 55 : half_mode = V32QImode;
17674 : 55 : goto quarter;
17675 : :
17676 : 71 : case E_V32HImode:
17677 : 71 : quarter_mode = V8HImode;
17678 : 71 : half_mode = V16HImode;
17679 : 71 : goto quarter;
17680 : :
17681 : 287 : case E_V32HFmode:
17682 : 287 : quarter_mode = V8HFmode;
17683 : 287 : half_mode = V16HFmode;
17684 : 287 : goto quarter;
17685 : :
17686 : 51 : case E_V32BFmode:
17687 : 51 : quarter_mode = V8BFmode;
17688 : 51 : half_mode = V16BFmode;
17689 : 51 : goto quarter;
17690 : :
17691 : 464 : quarter:
17692 : 464 : n = GET_MODE_NUNITS (mode);
17693 : 17072 : for (i = 0; i < n; i++)
17694 : 16608 : ops[i] = XVECEXP (vals, 0, i);
17695 : 464 : op0 = gen_reg_rtx (quarter_mode);
17696 : 464 : op1 = gen_reg_rtx (quarter_mode);
17697 : 464 : op2 = gen_reg_rtx (quarter_mode);
17698 : 464 : op3 = gen_reg_rtx (quarter_mode);
17699 : 464 : op4 = gen_reg_rtx (half_mode);
17700 : 464 : op5 = gen_reg_rtx (half_mode);
17701 : 464 : ix86_expand_vector_init_interleave (quarter_mode, op0, ops,
17702 : : n >> 3);
17703 : 464 : ix86_expand_vector_init_interleave (quarter_mode, op1,
17704 : 464 : &ops [n >> 2], n >> 3);
17705 : 464 : ix86_expand_vector_init_interleave (quarter_mode, op2,
17706 : 464 : &ops [n >> 1], n >> 3);
17707 : 464 : ix86_expand_vector_init_interleave (quarter_mode, op3,
17708 : 464 : &ops [(n >> 1) | (n >> 2)], n >> 3);
17709 : 464 : emit_insn (gen_rtx_SET (op4, gen_rtx_VEC_CONCAT (half_mode, op0, op1)));
17710 : 464 : emit_insn (gen_rtx_SET (op5, gen_rtx_VEC_CONCAT (half_mode, op2, op3)));
17711 : 464 : emit_insn (gen_rtx_SET (target, gen_rtx_VEC_CONCAT (mode, op4, op5)));
17712 : 464 : return;
17713 : :
17714 : 264 : case E_V16QImode:
17715 : 264 : if (!TARGET_SSE4_1)
17716 : : break;
17717 : : /* FALLTHRU */
17718 : :
17719 : 468 : case E_V8HImode:
17720 : 468 : if (!TARGET_SSE2)
17721 : : break;
17722 : :
17723 : : /* Don't use ix86_expand_vector_init_interleave if we can't
17724 : : move from GPR to SSE register directly. */
17725 : 468 : if (!TARGET_INTER_UNIT_MOVES_TO_VEC)
17726 : : break;
17727 : : /* FALLTHRU */
17728 : :
17729 : 1041 : case E_V8HFmode:
17730 : 1041 : case E_V8BFmode:
17731 : :
17732 : 1041 : n = GET_MODE_NUNITS (mode);
17733 : 9465 : for (i = 0; i < n; i++)
17734 : 8424 : ops[i] = XVECEXP (vals, 0, i);
17735 : 1041 : ix86_expand_vector_init_interleave (mode, target, ops, n >> 1);
17736 : 1041 : return;
17737 : :
17738 : : case E_V4HFmode:
17739 : : case E_V4BFmode:
17740 : : case E_V2HFmode:
17741 : : case E_V2BFmode:
17742 : 8325 : int_inner_mode = HImode;
17743 : : break;
17744 : :
17745 : : case E_V4HImode:
17746 : : case E_V8QImode:
17747 : :
17748 : : case E_V2HImode:
17749 : : case E_V4QImode:
17750 : : break;
17751 : :
17752 : 0 : default:
17753 : 0 : gcc_unreachable ();
17754 : : }
17755 : :
17756 : 8325 : {
17757 : 8325 : int i, j, n_elts, n_words, n_elt_per_word;
17758 : 8325 : machine_mode tmp_mode, inner_mode;
17759 : 8325 : rtx words[4], shift;
17760 : :
17761 : 16807 : tmp_mode = (GET_MODE_SIZE (mode) < UNITS_PER_WORD) ? SImode : word_mode;
17762 : :
17763 : 8325 : inner_mode = GET_MODE_INNER (mode);
17764 : 8325 : n_elts = GET_MODE_NUNITS (mode);
17765 : 16650 : n_words = GET_MODE_SIZE (mode) / GET_MODE_SIZE (tmp_mode);
17766 : 8325 : n_elt_per_word = n_elts / n_words;
17767 : 8325 : shift = GEN_INT (GET_MODE_BITSIZE (inner_mode));
17768 : :
17769 : 16977 : for (i = 0; i < n_words; ++i)
17770 : : {
17771 : : rtx word = NULL_RTX;
17772 : :
17773 : 45284 : for (j = 0; j < n_elt_per_word; ++j)
17774 : : {
17775 : 36632 : rtx elt = XVECEXP (vals, 0, (i+1)*n_elt_per_word - j - 1);
17776 : 36632 : if (int_inner_mode != E_VOIDmode)
17777 : : {
17778 : 134 : gcc_assert (TARGET_SSE2 && int_inner_mode == HImode);
17779 : 134 : rtx tmp = gen_reg_rtx (int_inner_mode);
17780 : 134 : elt = lowpart_subreg (int_inner_mode,
17781 : : force_reg (inner_mode, elt),
17782 : : inner_mode);
17783 : 134 : emit_move_insn (tmp, elt);
17784 : 134 : elt = tmp;
17785 : : }
17786 : 36632 : elt = convert_modes (tmp_mode, inner_mode, elt, true);
17787 : :
17788 : 36632 : if (j == 0)
17789 : : word = elt;
17790 : : else
17791 : : {
17792 : 27980 : word = expand_simple_binop (tmp_mode, ASHIFT, word, shift,
17793 : : NULL_RTX, 1, OPTAB_LIB_WIDEN);
17794 : 27980 : word = expand_simple_binop (tmp_mode, IOR, word, elt,
17795 : : NULL_RTX, 1, OPTAB_LIB_WIDEN);
17796 : : }
17797 : : }
17798 : :
17799 : 8652 : words[i] = word;
17800 : : }
17801 : :
17802 : 8325 : if (n_words == 1)
17803 : 7998 : emit_move_insn (target, gen_lowpart (mode, words[0]));
17804 : 327 : else if (n_words == 2)
17805 : : {
17806 : 327 : gcc_assert (tmp_mode == DImode || tmp_mode == SImode);
17807 : 327 : machine_mode concat_mode = tmp_mode == DImode ? V2DImode : V2SImode;
17808 : 327 : rtx tmp = gen_reg_rtx (concat_mode);
17809 : 327 : vals = gen_rtx_PARALLEL (concat_mode, gen_rtvec_v (2, words));
17810 : 327 : ix86_expand_vector_init_general (mmx_ok, concat_mode, tmp, vals);
17811 : 327 : emit_move_insn (target, gen_lowpart (mode, tmp));
17812 : : }
17813 : 0 : else if (n_words == 4)
17814 : : {
17815 : 0 : rtx tmp = gen_reg_rtx (V4SImode);
17816 : 0 : gcc_assert (tmp_mode == SImode);
17817 : 0 : vals = gen_rtx_PARALLEL (V4SImode, gen_rtvec_v (4, words));
17818 : 0 : ix86_expand_vector_init_general (false, V4SImode, tmp, vals);
17819 : 0 : emit_move_insn (target, gen_lowpart (mode, tmp));
17820 : : }
17821 : : else
17822 : 0 : gcc_unreachable ();
17823 : : }
17824 : : }
17825 : :
17826 : : /* Initialize vector TARGET via VALS. Suppress the use of MMX
17827 : : instructions unless MMX_OK is true. */
17828 : :
17829 : : void
17830 : 132197 : ix86_expand_vector_init (bool mmx_ok, rtx target, rtx vals)
17831 : : {
17832 : 132197 : machine_mode mode = GET_MODE (target);
17833 : 132197 : machine_mode inner_mode = GET_MODE_INNER (mode);
17834 : 132197 : int n_elts = GET_MODE_NUNITS (mode);
17835 : 132197 : int n_var = 0, one_var = -1;
17836 : 132197 : bool all_same = true, all_const_zero = true;
17837 : 132197 : int i;
17838 : 132197 : rtx x;
17839 : :
17840 : : /* Handle first initialization from vector elts. */
17841 : 132197 : if (n_elts != XVECLEN (vals, 0))
17842 : : {
17843 : 1058 : rtx subtarget = target;
17844 : 1058 : x = XVECEXP (vals, 0, 0);
17845 : 2116 : gcc_assert (GET_MODE_INNER (GET_MODE (x)) == inner_mode);
17846 : 2116 : if (GET_MODE_NUNITS (GET_MODE (x)) * 2 == n_elts)
17847 : : {
17848 : 1058 : rtx ops[2] = { XVECEXP (vals, 0, 0), XVECEXP (vals, 0, 1) };
17849 : 1058 : if (inner_mode == QImode
17850 : 1058 : || inner_mode == HImode
17851 : 1058 : || inner_mode == TImode
17852 : : || inner_mode == HFmode
17853 : : || inner_mode == BFmode)
17854 : : {
17855 : 146 : unsigned int n_bits = n_elts * GET_MODE_SIZE (inner_mode);
17856 : 146 : scalar_mode elt_mode = inner_mode == TImode ? DImode : SImode;
17857 : 146 : n_bits /= GET_MODE_SIZE (elt_mode);
17858 : 146 : mode = mode_for_vector (elt_mode, n_bits).require ();
17859 : 146 : inner_mode = mode_for_vector (elt_mode, n_bits / 2).require ();
17860 : 146 : ops[0] = gen_lowpart (inner_mode, ops[0]);
17861 : 146 : ops[1] = gen_lowpart (inner_mode, ops[1]);
17862 : 146 : subtarget = gen_reg_rtx (mode);
17863 : : }
17864 : 1058 : ix86_expand_vector_init_concat (mode, subtarget, ops, 2);
17865 : 1058 : if (subtarget != target)
17866 : 146 : emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
17867 : 1058 : return;
17868 : : }
17869 : 0 : gcc_unreachable ();
17870 : : }
17871 : :
17872 : 476903 : for (i = 0; i < n_elts; ++i)
17873 : : {
17874 : 345764 : x = XVECEXP (vals, 0, i);
17875 : 671053 : if (!(CONST_SCALAR_INT_P (x)
17876 : 327998 : || CONST_DOUBLE_P (x)
17877 : : || CONST_FIXED_P (x)))
17878 : 325289 : n_var++, one_var = i;
17879 : 20475 : else if (x != CONST0_RTX (inner_mode))
17880 : 3207 : all_const_zero = false;
17881 : 345764 : if (i > 0 && !rtx_equal_p (x, XVECEXP (vals, 0, 0)))
17882 : : all_same = false;
17883 : : }
17884 : :
17885 : : /* Handle the zero vector as special case. */
17886 : 131139 : if (n_var == 0 && all_const_zero)
17887 : : {
17888 : 353 : emit_move_insn (target, CONST0_RTX (mode));
17889 : 353 : return;
17890 : : }
17891 : :
17892 : : /* If all values are identical, broadcast the value. */
17893 : 130786 : if (all_same
17894 : 137264 : && ix86_expand_vector_init_duplicate (mmx_ok, mode, target,
17895 : 6478 : XVECEXP (vals, 0, 0)))
17896 : : return;
17897 : :
17898 : : /* Constants are best loaded from the constant pool. */
17899 : 125236 : if (n_var == 0)
17900 : : {
17901 : 41 : emit_move_insn (target, gen_rtx_CONST_VECTOR (mode, XVEC (vals, 0)));
17902 : 41 : return;
17903 : : }
17904 : :
17905 : : /* Values where only one field is non-constant are best loaded from
17906 : : the pool and overwritten via move later. */
17907 : 125195 : if (n_var == 1)
17908 : : {
17909 : 12535 : if (all_const_zero
17910 : 23939 : && ix86_expand_vector_init_one_nonzero (mmx_ok, mode, target,
17911 : 11404 : XVECEXP (vals, 0, one_var),
17912 : : one_var))
17913 : : return;
17914 : :
17915 : 8727 : if (ix86_expand_vector_init_one_var (mmx_ok, mode, target, vals, one_var))
17916 : : return;
17917 : : }
17918 : :
17919 : 121169 : ix86_expand_vector_init_general (mmx_ok, mode, target, vals);
17920 : : }
17921 : :
17922 : : /* Implemented as
17923 : : V setg (V v, int idx, T val)
17924 : : {
17925 : : V idxv = (V){idx, idx, idx, idx, idx, idx, idx, idx};
17926 : : V valv = (V){val, val, val, val, val, val, val, val};
17927 : : V mask = ((V){0, 1, 2, 3, 4, 5, 6, 7} == idxv);
17928 : : v = (v & ~mask) | (valv & mask);
17929 : : return v;
17930 : : }. */
17931 : : void
17932 : 128 : ix86_expand_vector_set_var (rtx target, rtx val, rtx idx)
17933 : : {
17934 : 128 : rtx vec[64];
17935 : 128 : machine_mode mode = GET_MODE (target);
17936 : 128 : machine_mode cmp_mode = mode;
17937 : 128 : int n_elts = GET_MODE_NUNITS (mode);
17938 : 128 : rtx valv,idxv,constv,idx_tmp;
17939 : 128 : bool ok = false;
17940 : :
17941 : : /* 512-bits vector byte/word broadcast and comparison only available
17942 : : under TARGET_AVX512BW, break 512-bits vector into two 256-bits vector
17943 : : when without TARGET_AVX512BW. */
17944 : 128 : if ((mode == V32HImode || mode == V32HFmode || mode == V32BFmode
17945 : 122 : || mode == V64QImode)
17946 : 10 : && !TARGET_AVX512BW)
17947 : : {
17948 : 3 : gcc_assert (TARGET_AVX512F);
17949 : 3 : rtx vhi, vlo, idx_hi;
17950 : 3 : machine_mode half_mode;
17951 : 3 : rtx (*extract_hi)(rtx, rtx);
17952 : 3 : rtx (*extract_lo)(rtx, rtx);
17953 : :
17954 : 3 : if (mode == V32HImode)
17955 : : {
17956 : : half_mode = V16HImode;
17957 : : extract_hi = gen_vec_extract_hi_v32hi;
17958 : : extract_lo = gen_vec_extract_lo_v32hi;
17959 : : }
17960 : : else if (mode == V32HFmode)
17961 : : {
17962 : : half_mode = V16HFmode;
17963 : : extract_hi = gen_vec_extract_hi_v32hf;
17964 : : extract_lo = gen_vec_extract_lo_v32hf;
17965 : : }
17966 : : else if (mode == V32BFmode)
17967 : : {
17968 : : half_mode = V16BFmode;
17969 : : extract_hi = gen_vec_extract_hi_v32bf;
17970 : : extract_lo = gen_vec_extract_lo_v32bf;
17971 : : }
17972 : : else
17973 : : {
17974 : 3 : half_mode = V32QImode;
17975 : 3 : extract_hi = gen_vec_extract_hi_v64qi;
17976 : 3 : extract_lo = gen_vec_extract_lo_v64qi;
17977 : : }
17978 : :
17979 : 3 : vhi = gen_reg_rtx (half_mode);
17980 : 3 : vlo = gen_reg_rtx (half_mode);
17981 : 3 : idx_hi = gen_reg_rtx (GET_MODE (idx));
17982 : 3 : emit_insn (extract_hi (vhi, target));
17983 : 3 : emit_insn (extract_lo (vlo, target));
17984 : 3 : vec[0] = idx_hi;
17985 : 3 : vec[1] = idx;
17986 : 3 : vec[2] = GEN_INT (n_elts/2);
17987 : 3 : ix86_expand_binary_operator (MINUS, GET_MODE (idx), vec);
17988 : 3 : ix86_expand_vector_set_var (vhi, val, idx_hi);
17989 : 3 : ix86_expand_vector_set_var (vlo, val, idx);
17990 : 3 : emit_insn (gen_rtx_SET (target, gen_rtx_VEC_CONCAT (mode, vlo, vhi)));
17991 : 3 : return;
17992 : : }
17993 : :
17994 : 499 : if (FLOAT_MODE_P (GET_MODE_INNER (mode)))
17995 : : {
17996 : 42 : switch (mode)
17997 : : {
17998 : : case E_V2DFmode:
17999 : : cmp_mode = V2DImode;
18000 : : break;
18001 : 6 : case E_V4DFmode:
18002 : 6 : cmp_mode = V4DImode;
18003 : 6 : break;
18004 : 4 : case E_V8DFmode:
18005 : 4 : cmp_mode = V8DImode;
18006 : 4 : break;
18007 : 2 : case E_V2SFmode:
18008 : 2 : cmp_mode = V2SImode;
18009 : 2 : break;
18010 : 6 : case E_V4SFmode:
18011 : 6 : cmp_mode = V4SImode;
18012 : 6 : break;
18013 : 6 : case E_V8SFmode:
18014 : 6 : cmp_mode = V8SImode;
18015 : 6 : break;
18016 : 5 : case E_V16SFmode:
18017 : 5 : cmp_mode = V16SImode;
18018 : 5 : break;
18019 : 1 : case E_V2HFmode:
18020 : 1 : case E_V2BFmode:
18021 : 1 : cmp_mode = V2HImode;
18022 : 1 : break;
18023 : 1 : case E_V4HFmode:
18024 : 1 : case E_V4BFmode:
18025 : 1 : cmp_mode = V4HImode;
18026 : 1 : break;
18027 : : case E_V8HFmode:
18028 : 2 : cmp_mode = V8HImode;
18029 : : break;
18030 : : case E_V16HFmode:
18031 : 2 : cmp_mode = V16HImode;
18032 : : break;
18033 : : case E_V32HFmode:
18034 : 1 : cmp_mode = V32HImode;
18035 : : break;
18036 : : case E_V8BFmode:
18037 : 2 : cmp_mode = V8HImode;
18038 : : break;
18039 : : case E_V16BFmode:
18040 : 2 : cmp_mode = V16HImode;
18041 : : break;
18042 : : case E_V32BFmode:
18043 : 1 : cmp_mode = V32HImode;
18044 : : break;
18045 : 0 : default:
18046 : 0 : gcc_unreachable ();
18047 : : }
18048 : : }
18049 : :
18050 : 1599 : for (int i = 0; i != n_elts; i++)
18051 : 1474 : vec[i] = GEN_INT (i);
18052 : 125 : constv = gen_rtx_CONST_VECTOR (cmp_mode, gen_rtvec_v (n_elts, vec));
18053 : 125 : valv = gen_reg_rtx (mode);
18054 : 125 : idxv = gen_reg_rtx (cmp_mode);
18055 : 250 : idx_tmp = convert_to_mode (GET_MODE_INNER (cmp_mode), idx, 1);
18056 : :
18057 : 125 : ok = ix86_expand_vector_init_duplicate (TARGET_MMX_WITH_SSE,
18058 : : mode, valv, val);
18059 : 125 : gcc_assert (ok);
18060 : 125 : ok = ix86_expand_vector_init_duplicate (TARGET_MMX_WITH_SSE,
18061 : : cmp_mode, idxv, idx_tmp);
18062 : 125 : gcc_assert (ok);
18063 : 125 : vec[0] = target;
18064 : 125 : vec[1] = valv;
18065 : 125 : vec[2] = target;
18066 : 125 : vec[3] = gen_rtx_EQ (mode, idxv, constv);
18067 : 125 : vec[4] = idxv;
18068 : 125 : vec[5] = constv;
18069 : 125 : ok = ix86_expand_int_vcond (vec);
18070 : 125 : gcc_assert (ok);
18071 : : }
18072 : :
18073 : : void
18074 : 7590 : ix86_expand_vector_set (bool mmx_ok, rtx target, rtx val, int elt)
18075 : : {
18076 : 7590 : machine_mode mode = GET_MODE (target);
18077 : 7590 : machine_mode inner_mode = GET_MODE_INNER (mode);
18078 : 7590 : machine_mode half_mode;
18079 : 7590 : bool use_vec_merge = false;
18080 : 7590 : bool blendm_const = false;
18081 : 7590 : rtx tmp;
18082 : 7590 : static rtx (*gen_extract[8][2]) (rtx, rtx)
18083 : : = {
18084 : : { gen_vec_extract_lo_v32qi, gen_vec_extract_hi_v32qi },
18085 : : { gen_vec_extract_lo_v16hi, gen_vec_extract_hi_v16hi },
18086 : : { gen_vec_extract_lo_v8si, gen_vec_extract_hi_v8si },
18087 : : { gen_vec_extract_lo_v4di, gen_vec_extract_hi_v4di },
18088 : : { gen_vec_extract_lo_v8sf, gen_vec_extract_hi_v8sf },
18089 : : { gen_vec_extract_lo_v4df, gen_vec_extract_hi_v4df },
18090 : : { gen_vec_extract_lo_v16hf, gen_vec_extract_hi_v16hf },
18091 : : { gen_vec_extract_lo_v16bf, gen_vec_extract_hi_v16bf }
18092 : : };
18093 : 7590 : static rtx (*gen_insert[8][2]) (rtx, rtx, rtx)
18094 : : = {
18095 : : { gen_vec_set_lo_v32qi, gen_vec_set_hi_v32qi },
18096 : : { gen_vec_set_lo_v16hi, gen_vec_set_hi_v16hi },
18097 : : { gen_vec_set_lo_v8si, gen_vec_set_hi_v8si },
18098 : : { gen_vec_set_lo_v4di, gen_vec_set_hi_v4di },
18099 : : { gen_vec_set_lo_v8sf, gen_vec_set_hi_v8sf },
18100 : : { gen_vec_set_lo_v4df, gen_vec_set_hi_v4df },
18101 : : { gen_vec_set_lo_v16hf, gen_vec_set_hi_v16hf },
18102 : : { gen_vec_set_lo_v16bf, gen_vec_set_hi_v16bf },
18103 : : };
18104 : 7590 : int i, j, n;
18105 : 7590 : machine_mode mmode = VOIDmode;
18106 : 7590 : rtx (*gen_blendm) (rtx, rtx, rtx, rtx);
18107 : :
18108 : 7590 : switch (mode)
18109 : : {
18110 : 167 : case E_V2SImode:
18111 : 167 : use_vec_merge = TARGET_MMX_WITH_SSE && TARGET_SSE4_1;
18112 : : if (use_vec_merge)
18113 : : break;
18114 : : /* FALLTHRU */
18115 : :
18116 : 150 : case E_V2SFmode:
18117 : 150 : if (mmx_ok)
18118 : : {
18119 : 150 : tmp = gen_reg_rtx (GET_MODE_INNER (mode));
18120 : 150 : ix86_expand_vector_extract (true, tmp, target, 1 - elt);
18121 : 150 : if (elt == 0)
18122 : 3 : tmp = gen_rtx_VEC_CONCAT (mode, val, tmp);
18123 : : else
18124 : 147 : tmp = gen_rtx_VEC_CONCAT (mode, tmp, val);
18125 : 150 : emit_insn (gen_rtx_SET (target, tmp));
18126 : 150 : return;
18127 : : }
18128 : : break;
18129 : :
18130 : 230 : case E_V2DImode:
18131 : 230 : use_vec_merge = TARGET_SSE4_1 && TARGET_64BIT;
18132 : 88 : if (use_vec_merge)
18133 : : break;
18134 : :
18135 : 88 : tmp = gen_reg_rtx (GET_MODE_INNER (mode));
18136 : 88 : ix86_expand_vector_extract (false, tmp, target, 1 - elt);
18137 : 88 : if (elt == 0)
18138 : 77 : tmp = gen_rtx_VEC_CONCAT (mode, val, tmp);
18139 : : else
18140 : 11 : tmp = gen_rtx_VEC_CONCAT (mode, tmp, val);
18141 : 88 : emit_insn (gen_rtx_SET (target, tmp));
18142 : 88 : return;
18143 : :
18144 : 148 : case E_V2DFmode:
18145 : : /* NB: For ELT == 0, use standard scalar operation patterns which
18146 : : preserve the rest of the vector for combiner:
18147 : :
18148 : : (vec_merge:V2DF
18149 : : (vec_duplicate:V2DF (reg:DF))
18150 : : (reg:V2DF)
18151 : : (const_int 1))
18152 : : */
18153 : 148 : if (elt == 0)
18154 : 61 : goto do_vec_merge;
18155 : :
18156 : 87 : {
18157 : 87 : rtx op0, op1;
18158 : :
18159 : : /* For the two element vectors, we implement a VEC_CONCAT with
18160 : : the extraction of the other element. */
18161 : :
18162 : 87 : tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (1, GEN_INT (1 - elt)));
18163 : 87 : tmp = gen_rtx_VEC_SELECT (inner_mode, target, tmp);
18164 : :
18165 : 87 : if (elt == 0)
18166 : : op0 = val, op1 = tmp;
18167 : : else
18168 : 87 : op0 = tmp, op1 = val;
18169 : :
18170 : 87 : tmp = gen_rtx_VEC_CONCAT (mode, op0, op1);
18171 : 87 : emit_insn (gen_rtx_SET (target, tmp));
18172 : : }
18173 : 87 : return;
18174 : :
18175 : 153 : case E_V4SFmode:
18176 : 153 : use_vec_merge = TARGET_SSE4_1;
18177 : 153 : if (use_vec_merge)
18178 : : break;
18179 : :
18180 : 62 : switch (elt)
18181 : : {
18182 : : case 0:
18183 : : use_vec_merge = true;
18184 : : break;
18185 : :
18186 : 1 : case 1:
18187 : : /* tmp = target = A B C D */
18188 : 1 : tmp = copy_to_reg (target);
18189 : : /* target = A A B B */
18190 : 1 : emit_insn (gen_vec_interleave_lowv4sf (target, target, target));
18191 : : /* target = X A B B */
18192 : 1 : ix86_expand_vector_set (false, target, val, 0);
18193 : : /* target = A X C D */
18194 : 1 : emit_insn (gen_sse_shufps_v4sf (target, target, tmp,
18195 : : const1_rtx, const0_rtx,
18196 : : GEN_INT (2+4), GEN_INT (3+4)));
18197 : 1 : return;
18198 : :
18199 : 0 : case 2:
18200 : : /* tmp = target = A B C D */
18201 : 0 : tmp = copy_to_reg (target);
18202 : : /* tmp = X B C D */
18203 : 0 : ix86_expand_vector_set (false, tmp, val, 0);
18204 : : /* target = A B X D */
18205 : 0 : emit_insn (gen_sse_shufps_v4sf (target, target, tmp,
18206 : : const0_rtx, const1_rtx,
18207 : : GEN_INT (0+4), GEN_INT (3+4)));
18208 : 0 : return;
18209 : :
18210 : 4 : case 3:
18211 : : /* tmp = target = A B C D */
18212 : 4 : tmp = copy_to_reg (target);
18213 : : /* tmp = X B C D */
18214 : 4 : ix86_expand_vector_set (false, tmp, val, 0);
18215 : : /* target = A B X D */
18216 : 4 : emit_insn (gen_sse_shufps_v4sf (target, target, tmp,
18217 : : const0_rtx, const1_rtx,
18218 : : GEN_INT (2+4), GEN_INT (0+4)));
18219 : 4 : return;
18220 : :
18221 : 0 : default:
18222 : 0 : gcc_unreachable ();
18223 : : }
18224 : : break;
18225 : :
18226 : 375 : case E_V4SImode:
18227 : 375 : use_vec_merge = TARGET_SSE4_1;
18228 : 375 : if (use_vec_merge)
18229 : : break;
18230 : :
18231 : : /* Element 0 handled by vec_merge below. */
18232 : 229 : if (elt == 0)
18233 : : {
18234 : : use_vec_merge = true;
18235 : : break;
18236 : : }
18237 : :
18238 : 74 : if (TARGET_SSE2)
18239 : : {
18240 : : /* With SSE2, use integer shuffles to swap element 0 and ELT,
18241 : : store into element 0, then shuffle them back. */
18242 : :
18243 : 74 : rtx order[4];
18244 : :
18245 : 74 : order[0] = GEN_INT (elt);
18246 : 74 : order[1] = const1_rtx;
18247 : 74 : order[2] = const2_rtx;
18248 : 74 : order[3] = GEN_INT (3);
18249 : 74 : order[elt] = const0_rtx;
18250 : :
18251 : 74 : emit_insn (gen_sse2_pshufd_1 (target, target, order[0],
18252 : : order[1], order[2], order[3]));
18253 : :
18254 : 74 : ix86_expand_vector_set (false, target, val, 0);
18255 : :
18256 : 74 : emit_insn (gen_sse2_pshufd_1 (target, target, order[0],
18257 : : order[1], order[2], order[3]));
18258 : : }
18259 : : else
18260 : : {
18261 : : /* For SSE1, we have to reuse the V4SF code. */
18262 : 0 : rtx t = gen_reg_rtx (V4SFmode);
18263 : 0 : emit_move_insn (t, gen_lowpart (V4SFmode, target));
18264 : 0 : ix86_expand_vector_set (false, t, gen_lowpart (SFmode, val), elt);
18265 : 0 : emit_move_insn (target, gen_lowpart (mode, t));
18266 : : }
18267 : : return;
18268 : :
18269 : 3303 : case E_V8HImode:
18270 : 3303 : case E_V8HFmode:
18271 : 3303 : case E_V8BFmode:
18272 : 3303 : case E_V2HImode:
18273 : 3303 : case E_V2HFmode:
18274 : 3303 : case E_V2BFmode:
18275 : 3303 : use_vec_merge = TARGET_SSE2;
18276 : 3303 : break;
18277 : 49 : case E_V4HImode:
18278 : 49 : case E_V4HFmode:
18279 : 49 : case E_V4BFmode:
18280 : 49 : use_vec_merge = mmx_ok && (TARGET_SSE || TARGET_3DNOW_A);
18281 : : break;
18282 : :
18283 : 3019 : case E_V16QImode:
18284 : 3019 : case E_V4QImode:
18285 : 3019 : use_vec_merge = TARGET_SSE4_1;
18286 : 3019 : break;
18287 : :
18288 : 5 : case E_V8QImode:
18289 : 5 : use_vec_merge = TARGET_MMX_WITH_SSE && TARGET_SSE4_1;
18290 : : break;
18291 : :
18292 : 3 : case E_V32QImode:
18293 : 3 : half_mode = V16QImode;
18294 : 3 : j = 0;
18295 : 3 : n = 16;
18296 : 3 : goto half;
18297 : :
18298 : 17 : case E_V16HFmode:
18299 : 17 : case E_V16BFmode:
18300 : : /* For ELT == 0, vec_setv8hf_0 can save 1 vpbroadcastw. */
18301 : 17 : if (TARGET_AVX2 && elt != 0)
18302 : : {
18303 : 12 : mmode = SImode;
18304 : 12 : gen_blendm = ((mode == E_V16HFmode) ? gen_avx2_pblendph_1
18305 : : : gen_avx2_pblendbf_1);
18306 : : blendm_const = true;
18307 : : break;
18308 : : }
18309 : : else
18310 : : {
18311 : 5 : half_mode = ((mode == E_V16HFmode) ? V8HFmode : V8BFmode);
18312 : 3 : j = ((mode == E_V16HFmode) ? 6 : 7);
18313 : 5 : n = 8;
18314 : 5 : goto half;
18315 : : }
18316 : :
18317 : 5 : case E_V16HImode:
18318 : 5 : half_mode = V8HImode;
18319 : 5 : j = 1;
18320 : 5 : n = 8;
18321 : 5 : goto half;
18322 : :
18323 : 13 : case E_V8SImode:
18324 : 13 : half_mode = V4SImode;
18325 : 13 : j = 2;
18326 : 13 : n = 4;
18327 : 13 : goto half;
18328 : :
18329 : 15 : case E_V4DImode:
18330 : 15 : half_mode = V2DImode;
18331 : 15 : j = 3;
18332 : 15 : n = 2;
18333 : 15 : goto half;
18334 : :
18335 : 4 : case E_V8SFmode:
18336 : 4 : half_mode = V4SFmode;
18337 : 4 : j = 4;
18338 : 4 : n = 4;
18339 : 4 : goto half;
18340 : :
18341 : 6 : case E_V4DFmode:
18342 : 6 : half_mode = V2DFmode;
18343 : 6 : j = 5;
18344 : 6 : n = 2;
18345 : 6 : goto half;
18346 : :
18347 : 51 : half:
18348 : : /* Compute offset. */
18349 : 51 : i = elt / n;
18350 : 51 : elt %= n;
18351 : :
18352 : 51 : gcc_assert (i <= 1);
18353 : :
18354 : : /* Extract the half. */
18355 : 51 : tmp = gen_reg_rtx (half_mode);
18356 : 51 : emit_insn (gen_extract[j][i] (tmp, target));
18357 : :
18358 : : /* Put val in tmp at elt. */
18359 : 51 : ix86_expand_vector_set (false, tmp, val, elt);
18360 : :
18361 : : /* Put it back. */
18362 : 51 : emit_insn (gen_insert[j][i] (target, target, tmp));
18363 : 51 : return;
18364 : :
18365 : 8 : case E_V8DFmode:
18366 : 8 : if (TARGET_AVX512F)
18367 : : {
18368 : : mmode = QImode;
18369 : : gen_blendm = gen_avx512f_blendmv8df;
18370 : : }
18371 : : break;
18372 : :
18373 : 6 : case E_V8DImode:
18374 : 6 : if (TARGET_AVX512F)
18375 : : {
18376 : : mmode = QImode;
18377 : : gen_blendm = gen_avx512f_blendmv8di;
18378 : : }
18379 : : break;
18380 : :
18381 : 0 : case E_V16SFmode:
18382 : 0 : if (TARGET_AVX512F)
18383 : : {
18384 : : mmode = HImode;
18385 : : gen_blendm = gen_avx512f_blendmv16sf;
18386 : : }
18387 : : break;
18388 : :
18389 : 0 : case E_V16SImode:
18390 : 0 : if (TARGET_AVX512F)
18391 : : {
18392 : : mmode = HImode;
18393 : : gen_blendm = gen_avx512f_blendmv16si;
18394 : : }
18395 : : break;
18396 : :
18397 : 12 : case E_V32HFmode:
18398 : 12 : if (TARGET_AVX512BW)
18399 : : {
18400 : : mmode = SImode;
18401 : : gen_blendm = gen_avx512bw_blendmv32hf;
18402 : : }
18403 : : break;
18404 : 12 : case E_V32BFmode:
18405 : 12 : if (TARGET_AVX512BW)
18406 : : {
18407 : : mmode = SImode;
18408 : : gen_blendm = gen_avx512bw_blendmv32bf;
18409 : : }
18410 : : break;
18411 : 11 : case E_V32HImode:
18412 : 11 : if (TARGET_AVX512BW)
18413 : : {
18414 : : mmode = SImode;
18415 : : gen_blendm = gen_avx512bw_blendmv32hi;
18416 : : }
18417 : 7 : else if (TARGET_AVX512F)
18418 : : {
18419 : 7 : half_mode = E_V8HImode;
18420 : 7 : n = 8;
18421 : 7 : goto quarter;
18422 : : }
18423 : : break;
18424 : :
18425 : 12 : case E_V64QImode:
18426 : 12 : if (TARGET_AVX512BW)
18427 : : {
18428 : : mmode = DImode;
18429 : : gen_blendm = gen_avx512bw_blendmv64qi;
18430 : : }
18431 : 6 : else if (TARGET_AVX512F)
18432 : : {
18433 : 6 : half_mode = E_V16QImode;
18434 : 6 : n = 16;
18435 : 6 : goto quarter;
18436 : : }
18437 : : break;
18438 : :
18439 : 13 : quarter:
18440 : : /* Compute offset. */
18441 : 13 : i = elt / n;
18442 : 13 : elt %= n;
18443 : :
18444 : 13 : gcc_assert (i <= 3);
18445 : :
18446 : 13 : {
18447 : : /* Extract the quarter. */
18448 : 13 : tmp = gen_reg_rtx (V4SImode);
18449 : 13 : rtx tmp2 = gen_lowpart (V16SImode, target);
18450 : 13 : rtx mask = gen_reg_rtx (QImode);
18451 : :
18452 : 13 : emit_move_insn (mask, constm1_rtx);
18453 : 13 : emit_insn (gen_avx512f_vextracti32x4_mask (tmp, tmp2, GEN_INT (i),
18454 : : tmp, mask));
18455 : :
18456 : 13 : tmp2 = gen_reg_rtx (half_mode);
18457 : 13 : emit_move_insn (tmp2, gen_lowpart (half_mode, tmp));
18458 : 13 : tmp = tmp2;
18459 : :
18460 : : /* Put val in tmp at elt. */
18461 : 13 : ix86_expand_vector_set (false, tmp, val, elt);
18462 : :
18463 : : /* Put it back. */
18464 : 13 : tmp2 = gen_reg_rtx (V16SImode);
18465 : 13 : rtx tmp3 = gen_lowpart (V16SImode, target);
18466 : 13 : mask = gen_reg_rtx (HImode);
18467 : 13 : emit_move_insn (mask, constm1_rtx);
18468 : 13 : tmp = gen_lowpart (V4SImode, tmp);
18469 : 13 : emit_insn (gen_avx512f_vinserti32x4_mask (tmp2, tmp3, tmp, GEN_INT (i),
18470 : : tmp3, mask));
18471 : 13 : emit_move_insn (target, gen_lowpart (mode, tmp2));
18472 : : }
18473 : 13 : return;
18474 : :
18475 : : default:
18476 : : break;
18477 : : }
18478 : :
18479 : 6322 : if (mmode != VOIDmode)
18480 : : {
18481 : 54 : tmp = gen_reg_rtx (mode);
18482 : 54 : emit_insn (gen_rtx_SET (tmp, gen_rtx_VEC_DUPLICATE (mode, val)));
18483 : 54 : rtx merge_mask = gen_int_mode (HOST_WIDE_INT_1U << elt, mmode);
18484 : : /* The avx512*_blendm<mode> expanders have different operand order
18485 : : from VEC_MERGE. In VEC_MERGE, the first input operand is used for
18486 : : elements where the mask is set and second input operand otherwise,
18487 : : in {sse,avx}*_*blend* the first input operand is used for elements
18488 : : where the mask is clear and second input operand otherwise. */
18489 : 54 : if (!blendm_const)
18490 : 42 : merge_mask = force_reg (mmode, merge_mask);
18491 : 54 : emit_insn (gen_blendm (target, target, tmp, merge_mask));
18492 : : }
18493 : 7007 : else if (use_vec_merge)
18494 : : {
18495 : 6997 : do_vec_merge:
18496 : 7058 : if (!nonimmediate_operand (val, inner_mode))
18497 : 1 : val = force_reg (inner_mode, val);
18498 : 7058 : tmp = gen_rtx_VEC_DUPLICATE (mode, val);
18499 : 7058 : tmp = gen_rtx_VEC_MERGE (mode, tmp, target,
18500 : : GEN_INT (HOST_WIDE_INT_1U << elt));
18501 : 7058 : emit_insn (gen_rtx_SET (target, tmp));
18502 : : }
18503 : : else
18504 : : {
18505 : 20 : rtx mem = assign_stack_temp (mode, GET_MODE_SIZE (mode));
18506 : :
18507 : 10 : emit_move_insn (mem, target);
18508 : :
18509 : 20 : tmp = adjust_address (mem, inner_mode, elt * GET_MODE_SIZE (inner_mode));
18510 : 10 : emit_move_insn (tmp, val);
18511 : :
18512 : 10 : emit_move_insn (target, mem);
18513 : : }
18514 : : }
18515 : :
18516 : : void
18517 : 103009 : ix86_expand_vector_extract (bool mmx_ok, rtx target, rtx vec, int elt)
18518 : : {
18519 : 103009 : machine_mode mode = GET_MODE (vec);
18520 : 103009 : machine_mode inner_mode = GET_MODE_INNER (mode);
18521 : 103009 : bool use_vec_extr = false;
18522 : 103009 : rtx tmp;
18523 : :
18524 : 103009 : switch (mode)
18525 : : {
18526 : 8783 : case E_V2SImode:
18527 : 8783 : use_vec_extr = TARGET_MMX_WITH_SSE && TARGET_SSE4_1;
18528 : : if (use_vec_extr)
18529 : : break;
18530 : : /* FALLTHRU */
18531 : :
18532 : 9584 : case E_V2SFmode:
18533 : 9584 : if (!mmx_ok)
18534 : : break;
18535 : : /* FALLTHRU */
18536 : :
18537 : : case E_V2DFmode:
18538 : : case E_V2DImode:
18539 : : case E_V2TImode:
18540 : : case E_V4TImode:
18541 : : use_vec_extr = true;
18542 : : break;
18543 : :
18544 : 7105 : case E_V4SFmode:
18545 : 7105 : use_vec_extr = TARGET_SSE4_1;
18546 : 7105 : if (use_vec_extr)
18547 : : break;
18548 : :
18549 : 3995 : switch (elt)
18550 : : {
18551 : : case 0:
18552 : : tmp = vec;
18553 : : break;
18554 : :
18555 : 1652 : case 1:
18556 : 1652 : case 3:
18557 : 1652 : tmp = gen_reg_rtx (mode);
18558 : 1652 : emit_insn (gen_sse_shufps_v4sf (tmp, vec, vec,
18559 : : GEN_INT (elt), GEN_INT (elt),
18560 : 1652 : GEN_INT (elt+4), GEN_INT (elt+4)));
18561 : 1652 : break;
18562 : :
18563 : 923 : case 2:
18564 : 923 : tmp = gen_reg_rtx (mode);
18565 : 923 : emit_insn (gen_vec_interleave_highv4sf (tmp, vec, vec));
18566 : 923 : break;
18567 : :
18568 : 0 : default:
18569 : 0 : gcc_unreachable ();
18570 : : }
18571 : : vec = tmp;
18572 : : use_vec_extr = true;
18573 : : elt = 0;
18574 : : break;
18575 : :
18576 : 23200 : case E_V4SImode:
18577 : 23200 : use_vec_extr = TARGET_SSE4_1;
18578 : 23200 : if (use_vec_extr)
18579 : : break;
18580 : :
18581 : 16376 : if (TARGET_SSE2)
18582 : : {
18583 : 16372 : switch (elt)
18584 : : {
18585 : : case 0:
18586 : : tmp = vec;
18587 : : break;
18588 : :
18589 : 5301 : case 1:
18590 : 5301 : case 3:
18591 : 5301 : tmp = gen_reg_rtx (mode);
18592 : 5301 : emit_insn (gen_sse2_pshufd_1 (tmp, vec,
18593 : : GEN_INT (elt), GEN_INT (elt),
18594 : : GEN_INT (elt), GEN_INT (elt)));
18595 : 5301 : break;
18596 : :
18597 : 2590 : case 2:
18598 : 2590 : tmp = gen_reg_rtx (mode);
18599 : 2590 : emit_insn (gen_vec_interleave_highv4si (tmp, vec, vec));
18600 : 2590 : break;
18601 : :
18602 : 0 : default:
18603 : 0 : gcc_unreachable ();
18604 : : }
18605 : : vec = tmp;
18606 : : use_vec_extr = true;
18607 : : elt = 0;
18608 : : }
18609 : : else
18610 : : {
18611 : : /* For SSE1, we have to reuse the V4SF code. */
18612 : 4 : ix86_expand_vector_extract (false, gen_lowpart (SFmode, target),
18613 : 4 : gen_lowpart (V4SFmode, vec), elt);
18614 : 4 : return;
18615 : : }
18616 : : break;
18617 : :
18618 : 6136 : case E_V8HImode:
18619 : 6136 : case E_V8HFmode:
18620 : 6136 : case E_V8BFmode:
18621 : 6136 : case E_V2HImode:
18622 : 6136 : case E_V2HFmode:
18623 : 6136 : case E_V2BFmode:
18624 : 6136 : use_vec_extr = TARGET_SSE2;
18625 : 6136 : break;
18626 : 796 : case E_V4HImode:
18627 : 796 : case E_V4HFmode:
18628 : 796 : case E_V4BFmode:
18629 : 796 : use_vec_extr = mmx_ok && (TARGET_SSE || TARGET_3DNOW_A);
18630 : : break;
18631 : :
18632 : 7246 : case E_V16QImode:
18633 : 7246 : use_vec_extr = TARGET_SSE4_1;
18634 : 7246 : if (!use_vec_extr
18635 : 5511 : && TARGET_SSE2
18636 : 5511 : && elt == 0
18637 : 10964 : && (optimize_insn_for_size_p () || TARGET_INTER_UNIT_MOVES_FROM_VEC))
18638 : : {
18639 : 3717 : tmp = gen_reg_rtx (SImode);
18640 : 3717 : ix86_expand_vector_extract (false, tmp, gen_lowpart (V4SImode, vec),
18641 : : 0);
18642 : 3717 : emit_insn (gen_rtx_SET (target, gen_lowpart (QImode, tmp)));
18643 : 3717 : return;
18644 : : }
18645 : : break;
18646 : 48 : case E_V4QImode:
18647 : 48 : use_vec_extr = TARGET_SSE4_1;
18648 : 48 : break;
18649 : :
18650 : 244 : case E_V8SFmode:
18651 : 244 : if (TARGET_AVX)
18652 : : {
18653 : 244 : tmp = gen_reg_rtx (V4SFmode);
18654 : 244 : if (elt < 4)
18655 : 118 : emit_insn (gen_vec_extract_lo_v8sf (tmp, vec));
18656 : : else
18657 : 126 : emit_insn (gen_vec_extract_hi_v8sf (tmp, vec));
18658 : 244 : ix86_expand_vector_extract (false, target, tmp, elt & 3);
18659 : 244 : return;
18660 : : }
18661 : : break;
18662 : :
18663 : 335 : case E_V4DFmode:
18664 : 335 : if (TARGET_AVX)
18665 : : {
18666 : 335 : tmp = gen_reg_rtx (V2DFmode);
18667 : 335 : if (elt < 2)
18668 : 183 : emit_insn (gen_vec_extract_lo_v4df (tmp, vec));
18669 : : else
18670 : 152 : emit_insn (gen_vec_extract_hi_v4df (tmp, vec));
18671 : 335 : ix86_expand_vector_extract (false, target, tmp, elt & 1);
18672 : 335 : return;
18673 : : }
18674 : : break;
18675 : :
18676 : 190 : case E_V32QImode:
18677 : 190 : if (TARGET_AVX)
18678 : : {
18679 : 190 : tmp = gen_reg_rtx (V16QImode);
18680 : 190 : if (elt < 16)
18681 : 99 : emit_insn (gen_vec_extract_lo_v32qi (tmp, vec));
18682 : : else
18683 : 91 : emit_insn (gen_vec_extract_hi_v32qi (tmp, vec));
18684 : 190 : ix86_expand_vector_extract (false, target, tmp, elt & 15);
18685 : 190 : return;
18686 : : }
18687 : : break;
18688 : :
18689 : 586 : case E_V16HImode:
18690 : 586 : if (TARGET_AVX)
18691 : : {
18692 : 586 : tmp = gen_reg_rtx (V8HImode);
18693 : 586 : if (elt < 8)
18694 : 290 : emit_insn (gen_vec_extract_lo_v16hi (tmp, vec));
18695 : : else
18696 : 296 : emit_insn (gen_vec_extract_hi_v16hi (tmp, vec));
18697 : 586 : ix86_expand_vector_extract (false, target, tmp, elt & 7);
18698 : 586 : return;
18699 : : }
18700 : : break;
18701 : :
18702 : 1485 : case E_V8SImode:
18703 : 1485 : if (TARGET_AVX)
18704 : : {
18705 : 1485 : tmp = gen_reg_rtx (V4SImode);
18706 : 1485 : if (elt < 4)
18707 : 1021 : emit_insn (gen_vec_extract_lo_v8si (tmp, vec));
18708 : : else
18709 : 464 : emit_insn (gen_vec_extract_hi_v8si (tmp, vec));
18710 : 1485 : ix86_expand_vector_extract (false, target, tmp, elt & 3);
18711 : 1485 : return;
18712 : : }
18713 : : break;
18714 : :
18715 : 1451 : case E_V4DImode:
18716 : 1451 : if (TARGET_AVX)
18717 : : {
18718 : 1451 : tmp = gen_reg_rtx (V2DImode);
18719 : 1451 : if (elt < 2)
18720 : 764 : emit_insn (gen_vec_extract_lo_v4di (tmp, vec));
18721 : : else
18722 : 687 : emit_insn (gen_vec_extract_hi_v4di (tmp, vec));
18723 : 1451 : ix86_expand_vector_extract (false, target, tmp, elt & 1);
18724 : 1451 : return;
18725 : : }
18726 : : break;
18727 : :
18728 : 10 : case E_V32HImode:
18729 : 10 : if (TARGET_AVX512BW)
18730 : : {
18731 : 10 : tmp = gen_reg_rtx (V16HImode);
18732 : 10 : if (elt < 16)
18733 : 5 : emit_insn (gen_vec_extract_lo_v32hi (tmp, vec));
18734 : : else
18735 : 5 : emit_insn (gen_vec_extract_hi_v32hi (tmp, vec));
18736 : 10 : ix86_expand_vector_extract (false, target, tmp, elt & 15);
18737 : 10 : return;
18738 : : }
18739 : : break;
18740 : :
18741 : 12 : case E_V64QImode:
18742 : 12 : if (TARGET_AVX512BW)
18743 : : {
18744 : 12 : tmp = gen_reg_rtx (V32QImode);
18745 : 12 : if (elt < 32)
18746 : 6 : emit_insn (gen_vec_extract_lo_v64qi (tmp, vec));
18747 : : else
18748 : 6 : emit_insn (gen_vec_extract_hi_v64qi (tmp, vec));
18749 : 12 : ix86_expand_vector_extract (false, target, tmp, elt & 31);
18750 : 12 : return;
18751 : : }
18752 : : break;
18753 : :
18754 : 55 : case E_V16SFmode:
18755 : 55 : tmp = gen_reg_rtx (V8SFmode);
18756 : 55 : if (elt < 8)
18757 : 29 : emit_insn (gen_vec_extract_lo_v16sf (tmp, vec));
18758 : : else
18759 : 26 : emit_insn (gen_vec_extract_hi_v16sf (tmp, vec));
18760 : 55 : ix86_expand_vector_extract (false, target, tmp, elt & 7);
18761 : 55 : return;
18762 : :
18763 : 72 : case E_V8DFmode:
18764 : 72 : tmp = gen_reg_rtx (V4DFmode);
18765 : 72 : if (elt < 4)
18766 : 48 : emit_insn (gen_vec_extract_lo_v8df (tmp, vec));
18767 : : else
18768 : 24 : emit_insn (gen_vec_extract_hi_v8df (tmp, vec));
18769 : 72 : ix86_expand_vector_extract (false, target, tmp, elt & 3);
18770 : 72 : return;
18771 : :
18772 : 489 : case E_V16SImode:
18773 : 489 : tmp = gen_reg_rtx (V8SImode);
18774 : 489 : if (elt < 8)
18775 : 320 : emit_insn (gen_vec_extract_lo_v16si (tmp, vec));
18776 : : else
18777 : 169 : emit_insn (gen_vec_extract_hi_v16si (tmp, vec));
18778 : 489 : ix86_expand_vector_extract (false, target, tmp, elt & 7);
18779 : 489 : return;
18780 : :
18781 : 742 : case E_V8DImode:
18782 : 742 : tmp = gen_reg_rtx (V4DImode);
18783 : 742 : if (elt < 4)
18784 : 421 : emit_insn (gen_vec_extract_lo_v8di (tmp, vec));
18785 : : else
18786 : 321 : emit_insn (gen_vec_extract_hi_v8di (tmp, vec));
18787 : 742 : ix86_expand_vector_extract (false, target, tmp, elt & 3);
18788 : 742 : return;
18789 : :
18790 : 45 : case E_V32HFmode:
18791 : 45 : case E_V32BFmode:
18792 : 45 : if (TARGET_AVX512BW)
18793 : : {
18794 : 45 : tmp = (mode == E_V32HFmode
18795 : 45 : ? gen_reg_rtx (V16HFmode)
18796 : 7 : : gen_reg_rtx (V16BFmode));
18797 : 45 : if (elt < 16)
18798 : 31 : emit_insn (gen_vec_extract_lo (mode, tmp, vec));
18799 : : else
18800 : 14 : emit_insn (gen_vec_extract_hi (mode, tmp, vec));
18801 : 45 : ix86_expand_vector_extract (false, target, tmp, elt & 15);
18802 : 45 : return;
18803 : : }
18804 : : break;
18805 : :
18806 : 474 : case E_V16HFmode:
18807 : 474 : case E_V16BFmode:
18808 : 474 : if (TARGET_AVX)
18809 : : {
18810 : 474 : tmp = (mode == E_V16HFmode
18811 : 474 : ? gen_reg_rtx (V8HFmode)
18812 : 339 : : gen_reg_rtx (V8BFmode));
18813 : 474 : if (elt < 8)
18814 : 249 : emit_insn (gen_vec_extract_lo (mode, tmp, vec));
18815 : : else
18816 : 225 : emit_insn (gen_vec_extract_hi (mode, tmp, vec));
18817 : 474 : ix86_expand_vector_extract (false, target, tmp, elt & 7);
18818 : 474 : return;
18819 : : }
18820 : : break;
18821 : :
18822 : 598 : case E_V8QImode:
18823 : 598 : use_vec_extr = TARGET_MMX_WITH_SSE && TARGET_SSE4_1;
18824 : : /* ??? Could extract the appropriate HImode element and shift. */
18825 : : break;
18826 : :
18827 : : default:
18828 : : break;
18829 : : }
18830 : :
18831 : 26632 : if (use_vec_extr)
18832 : : {
18833 : 85405 : tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (1, GEN_INT (elt)));
18834 : 85405 : tmp = gen_rtx_VEC_SELECT (inner_mode, vec, tmp);
18835 : :
18836 : : /* Let the rtl optimizers know about the zero extension performed. */
18837 : 85405 : if (inner_mode == QImode || inner_mode == HImode)
18838 : : {
18839 : 8150 : rtx reg = gen_reg_rtx (SImode);
18840 : 8150 : tmp = gen_rtx_ZERO_EXTEND (SImode, tmp);
18841 : 8150 : emit_move_insn (reg, tmp);
18842 : 8150 : tmp = gen_lowpart (inner_mode, reg);
18843 : 8150 : SUBREG_PROMOTED_VAR_P (tmp) = 1;
18844 : 8150 : SUBREG_PROMOTED_SET (tmp, 1);
18845 : : }
18846 : :
18847 : 85405 : emit_move_insn (target, tmp);
18848 : : }
18849 : : else
18850 : : {
18851 : 15386 : rtx mem = assign_stack_temp (mode, GET_MODE_SIZE (mode));
18852 : :
18853 : 7693 : emit_move_insn (mem, vec);
18854 : :
18855 : 15386 : tmp = adjust_address (mem, inner_mode, elt*GET_MODE_SIZE (inner_mode));
18856 : 7693 : emit_move_insn (target, tmp);
18857 : : }
18858 : : }
18859 : :
18860 : : /* Generate code to copy vector bits i / 2 ... i - 1 from vector SRC
18861 : : to bits 0 ... i / 2 - 1 of vector DEST, which has the same mode.
18862 : : The upper bits of DEST are undefined, though they shouldn't cause
18863 : : exceptions (some bits from src or all zeros are ok). */
18864 : :
18865 : : static void
18866 : 40126 : emit_reduc_half (rtx dest, rtx src, int i)
18867 : : {
18868 : 40126 : rtx tem, d = dest;
18869 : 40126 : switch (GET_MODE (src))
18870 : : {
18871 : 6034 : case E_V4SFmode:
18872 : 6034 : if (i == 128)
18873 : 3017 : tem = gen_sse_movhlps (dest, src, src);
18874 : : else
18875 : 3017 : tem = gen_sse_shufps_v4sf (dest, src, src, const1_rtx, const1_rtx,
18876 : : GEN_INT (1 + 4), GEN_INT (1 + 4));
18877 : : break;
18878 : 3226 : case E_V2DFmode:
18879 : 3226 : tem = gen_vec_interleave_highv2df (dest, src, src);
18880 : 3226 : break;
18881 : 64 : case E_V4QImode:
18882 : 64 : d = gen_reg_rtx (V1SImode);
18883 : 64 : tem = gen_mmx_lshrv1si3 (d, gen_lowpart (V1SImode, src),
18884 : 64 : GEN_INT (i / 2));
18885 : 64 : break;
18886 : 524 : case E_V8QImode:
18887 : 524 : case E_V4HImode:
18888 : 524 : d = gen_reg_rtx (V1DImode);
18889 : 524 : tem = gen_mmx_lshrv1di3 (d, gen_lowpart (V1DImode, src),
18890 : 524 : GEN_INT (i / 2));
18891 : 524 : break;
18892 : 30278 : case E_V16QImode:
18893 : 30278 : case E_V8HImode:
18894 : 30278 : case E_V8HFmode:
18895 : 30278 : case E_V4SImode:
18896 : 30278 : case E_V2DImode:
18897 : 30278 : if (TARGET_SSE_REDUCTION_PREFER_PSHUF)
18898 : : {
18899 : 11 : if (i == 128)
18900 : : {
18901 : 5 : d = gen_reg_rtx (V4SImode);
18902 : 10 : tem = gen_sse2_pshufd_1 (
18903 : 5 : d, force_reg (V4SImode, gen_lowpart (V4SImode, src)),
18904 : : GEN_INT (2), GEN_INT (3), GEN_INT (2), GEN_INT (3));
18905 : 5 : break;
18906 : : }
18907 : 6 : else if (i == 64)
18908 : : {
18909 : 5 : d = gen_reg_rtx (V4SImode);
18910 : 10 : tem = gen_sse2_pshufd_1 (
18911 : 5 : d, force_reg (V4SImode, gen_lowpart (V4SImode, src)),
18912 : : GEN_INT (1), GEN_INT (1), GEN_INT (1), GEN_INT (1));
18913 : 5 : break;
18914 : : }
18915 : 1 : else if (i == 32)
18916 : : {
18917 : 1 : d = gen_reg_rtx (V8HImode);
18918 : 2 : tem = gen_sse2_pshuflw_1 (
18919 : 1 : d, force_reg (V8HImode, gen_lowpart (V8HImode, src)),
18920 : : GEN_INT (1), GEN_INT (1), GEN_INT (1), GEN_INT (1));
18921 : 1 : break;
18922 : : }
18923 : : }
18924 : 30267 : d = gen_reg_rtx (V1TImode);
18925 : 30267 : tem = gen_sse2_lshrv1ti3 (d, gen_lowpart (V1TImode, src),
18926 : 30267 : GEN_INT (i / 2));
18927 : 30267 : break;
18928 : 0 : case E_V8SFmode:
18929 : 0 : if (i == 256)
18930 : 0 : tem = gen_avx_vperm2f128v8sf3 (dest, src, src, const1_rtx);
18931 : : else
18932 : 0 : tem = gen_avx_shufps256 (dest, src, src,
18933 : : GEN_INT (i == 128 ? 2 + (3 << 2) : 1));
18934 : : break;
18935 : 0 : case E_V4DFmode:
18936 : 0 : if (i == 256)
18937 : 0 : tem = gen_avx_vperm2f128v4df3 (dest, src, src, const1_rtx);
18938 : : else
18939 : 0 : tem = gen_avx_shufpd256 (dest, src, src, const1_rtx);
18940 : : break;
18941 : 0 : case E_V32QImode:
18942 : 0 : case E_V16HImode:
18943 : 0 : case E_V16HFmode:
18944 : 0 : case E_V8SImode:
18945 : 0 : case E_V4DImode:
18946 : 0 : if (i == 256)
18947 : : {
18948 : 0 : if (GET_MODE (dest) != V4DImode)
18949 : 0 : d = gen_reg_rtx (V4DImode);
18950 : 0 : tem = gen_avx2_permv2ti (d, gen_lowpart (V4DImode, src),
18951 : 0 : gen_lowpart (V4DImode, src),
18952 : : const1_rtx);
18953 : : }
18954 : : else
18955 : : {
18956 : 0 : d = gen_reg_rtx (V2TImode);
18957 : 0 : tem = gen_avx2_lshrv2ti3 (d, gen_lowpart (V2TImode, src),
18958 : 0 : GEN_INT (i / 2));
18959 : : }
18960 : : break;
18961 : 0 : case E_V64QImode:
18962 : 0 : case E_V32HImode:
18963 : 0 : case E_V32HFmode:
18964 : 0 : if (i < 64)
18965 : : {
18966 : 0 : d = gen_reg_rtx (V4TImode);
18967 : 0 : tem = gen_avx512bw_lshrv4ti3 (d, gen_lowpart (V4TImode, src),
18968 : 0 : GEN_INT (i / 2));
18969 : 0 : break;
18970 : : }
18971 : : /* FALLTHRU */
18972 : 0 : case E_V16SImode:
18973 : 0 : case E_V16SFmode:
18974 : 0 : case E_V8DImode:
18975 : 0 : case E_V8DFmode:
18976 : 0 : if (i > 128)
18977 : 0 : tem = gen_avx512f_shuf_i32x4_1 (gen_lowpart (V16SImode, dest),
18978 : 0 : gen_lowpart (V16SImode, src),
18979 : 0 : gen_lowpart (V16SImode, src),
18980 : : GEN_INT (0x4 + (i == 512 ? 4 : 0)),
18981 : : GEN_INT (0x5 + (i == 512 ? 4 : 0)),
18982 : : GEN_INT (0x6 + (i == 512 ? 4 : 0)),
18983 : : GEN_INT (0x7 + (i == 512 ? 4 : 0)),
18984 : : GEN_INT (0xC), GEN_INT (0xD),
18985 : : GEN_INT (0xE), GEN_INT (0xF),
18986 : : GEN_INT (0x10), GEN_INT (0x11),
18987 : : GEN_INT (0x12), GEN_INT (0x13),
18988 : : GEN_INT (0x14), GEN_INT (0x15),
18989 : : GEN_INT (0x16), GEN_INT (0x17));
18990 : : else
18991 : 0 : tem = gen_avx512f_pshufd_1 (gen_lowpart (V16SImode, dest),
18992 : 0 : gen_lowpart (V16SImode, src),
18993 : : GEN_INT (i == 128 ? 0x2 : 0x1),
18994 : : GEN_INT (0x3),
18995 : : GEN_INT (0x3),
18996 : : GEN_INT (0x3),
18997 : : GEN_INT (i == 128 ? 0x6 : 0x5),
18998 : : GEN_INT (0x7),
18999 : : GEN_INT (0x7),
19000 : : GEN_INT (0x7),
19001 : : GEN_INT (i == 128 ? 0xA : 0x9),
19002 : : GEN_INT (0xB),
19003 : : GEN_INT (0xB),
19004 : : GEN_INT (0xB),
19005 : : GEN_INT (i == 128 ? 0xE : 0xD),
19006 : : GEN_INT (0xF),
19007 : : GEN_INT (0xF),
19008 : : GEN_INT (0xF));
19009 : : break;
19010 : 0 : default:
19011 : 0 : gcc_unreachable ();
19012 : : }
19013 : 40126 : emit_insn (tem);
19014 : 40126 : if (d != dest)
19015 : 30866 : emit_move_insn (dest, gen_lowpart (GET_MODE (dest), d));
19016 : 40126 : }
19017 : :
19018 : : /* Expand a vector reduction. FN is the binary pattern to reduce;
19019 : : DEST is the destination; IN is the input vector. */
19020 : :
19021 : : void
19022 : 20024 : ix86_expand_reduc (rtx (*fn) (rtx, rtx, rtx), rtx dest, rtx in)
19023 : : {
19024 : 20024 : rtx half, dst, vec = in;
19025 : 20024 : machine_mode mode = GET_MODE (in);
19026 : 20024 : int i;
19027 : :
19028 : : /* SSE4 has a special instruction for V8HImode UMIN reduction. */
19029 : 20024 : if (TARGET_SSE4_1
19030 : 9472 : && mode == V8HImode
19031 : 755 : && fn == gen_uminv8hi3)
19032 : : {
19033 : 4 : emit_insn (gen_sse4_1_phminposuw (dest, in));
19034 : 4 : return;
19035 : : }
19036 : :
19037 : 40040 : for (i = GET_MODE_BITSIZE (mode);
19038 : 120292 : i > GET_MODE_UNIT_BITSIZE (mode);
19039 : 40126 : i >>= 1)
19040 : : {
19041 : 40126 : half = gen_reg_rtx (mode);
19042 : 40126 : emit_reduc_half (half, vec, i);
19043 : 80252 : if (i == GET_MODE_UNIT_BITSIZE (mode) * 2)
19044 : : dst = dest;
19045 : : else
19046 : 20106 : dst = gen_reg_rtx (mode);
19047 : 40126 : emit_insn (fn (dst, half, vec));
19048 : 40126 : vec = dst;
19049 : : }
19050 : : }
19051 : :
19052 : : /* Output code to perform a conditional jump to LABEL, if C2 flag in
19053 : : FP status register is set. */
19054 : :
19055 : : void
19056 : 284 : ix86_emit_fp_unordered_jump (rtx label)
19057 : : {
19058 : 284 : rtx reg = gen_reg_rtx (HImode);
19059 : 284 : rtx_insn *insn;
19060 : 284 : rtx temp;
19061 : :
19062 : 284 : emit_insn (gen_x86_fnstsw_1 (reg));
19063 : :
19064 : 284 : if (TARGET_SAHF && (TARGET_USE_SAHF || optimize_insn_for_size_p ()))
19065 : : {
19066 : 37 : emit_insn (gen_x86_sahf_1 (reg));
19067 : :
19068 : 37 : temp = gen_rtx_REG (CCmode, FLAGS_REG);
19069 : 37 : temp = gen_rtx_UNORDERED (VOIDmode, temp, const0_rtx);
19070 : : }
19071 : : else
19072 : : {
19073 : 247 : emit_insn (gen_testqi_ext_1_ccno (reg, GEN_INT (0x04)));
19074 : :
19075 : 247 : temp = gen_rtx_REG (CCNOmode, FLAGS_REG);
19076 : 247 : temp = gen_rtx_NE (VOIDmode, temp, const0_rtx);
19077 : : }
19078 : :
19079 : 284 : temp = gen_rtx_IF_THEN_ELSE (VOIDmode, temp,
19080 : : gen_rtx_LABEL_REF (VOIDmode, label),
19081 : : pc_rtx);
19082 : 284 : insn = emit_jump_insn (gen_rtx_SET (pc_rtx, temp));
19083 : 284 : predict_jump (REG_BR_PROB_BASE * 10 / 100);
19084 : 284 : JUMP_LABEL (insn) = label;
19085 : 284 : }
19086 : :
19087 : : /* Output code to perform an sinh XFmode calculation. */
19088 : :
19089 : : void
19090 : 2 : ix86_emit_i387_sinh (rtx op0, rtx op1)
19091 : : {
19092 : 2 : rtx e1 = gen_reg_rtx (XFmode);
19093 : 2 : rtx e2 = gen_reg_rtx (XFmode);
19094 : 2 : rtx scratch = gen_reg_rtx (HImode);
19095 : 2 : rtx flags = gen_rtx_REG (CCNOmode, FLAGS_REG);
19096 : 2 : rtx half = const_double_from_real_value (dconsthalf, XFmode);
19097 : 2 : rtx cst1, tmp;
19098 : 2 : rtx_code_label *jump_label = gen_label_rtx ();
19099 : 2 : rtx_insn *insn;
19100 : :
19101 : : /* scratch = fxam (op1) */
19102 : 2 : emit_insn (gen_fxamxf2_i387 (scratch, op1));
19103 : :
19104 : : /* e1 = expm1 (|op1|) */
19105 : 2 : emit_insn (gen_absxf2 (e2, op1));
19106 : 2 : emit_insn (gen_expm1xf2 (e1, e2));
19107 : :
19108 : : /* e2 = e1 / (e1 + 1.0) + e1 */
19109 : 2 : cst1 = force_reg (XFmode, CONST1_RTX (XFmode));
19110 : 2 : emit_insn (gen_addxf3 (e2, e1, cst1));
19111 : 2 : emit_insn (gen_divxf3 (e2, e1, e2));
19112 : 2 : emit_insn (gen_addxf3 (e2, e2, e1));
19113 : :
19114 : : /* flags = signbit (op1) */
19115 : 2 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x02)));
19116 : :
19117 : : /* if (flags) then e2 = -e2 */
19118 : 2 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode,
19119 : : gen_rtx_EQ (VOIDmode, flags, const0_rtx),
19120 : : gen_rtx_LABEL_REF (VOIDmode, jump_label),
19121 : : pc_rtx);
19122 : 2 : insn = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
19123 : 2 : predict_jump (REG_BR_PROB_BASE * 50 / 100);
19124 : 2 : JUMP_LABEL (insn) = jump_label;
19125 : :
19126 : 2 : emit_insn (gen_negxf2 (e2, e2));
19127 : :
19128 : 2 : emit_label (jump_label);
19129 : 2 : LABEL_NUSES (jump_label) = 1;
19130 : :
19131 : : /* op0 = 0.5 * e2 */
19132 : 2 : half = force_reg (XFmode, half);
19133 : 2 : emit_insn (gen_mulxf3 (op0, e2, half));
19134 : 2 : }
19135 : :
19136 : : /* Output code to perform an cosh XFmode calculation. */
19137 : :
19138 : : void
19139 : 3 : ix86_emit_i387_cosh (rtx op0, rtx op1)
19140 : : {
19141 : 3 : rtx e1 = gen_reg_rtx (XFmode);
19142 : 3 : rtx e2 = gen_reg_rtx (XFmode);
19143 : 3 : rtx half = const_double_from_real_value (dconsthalf, XFmode);
19144 : 3 : rtx cst1;
19145 : :
19146 : : /* e1 = exp (op1) */
19147 : 3 : emit_insn (gen_expxf2 (e1, op1));
19148 : :
19149 : : /* e2 = e1 + 1.0 / e1 */
19150 : 3 : cst1 = force_reg (XFmode, CONST1_RTX (XFmode));
19151 : 3 : emit_insn (gen_divxf3 (e2, cst1, e1));
19152 : 3 : emit_insn (gen_addxf3 (e2, e1, e2));
19153 : :
19154 : : /* op0 = 0.5 * e2 */
19155 : 3 : half = force_reg (XFmode, half);
19156 : 3 : emit_insn (gen_mulxf3 (op0, e2, half));
19157 : 3 : }
19158 : :
19159 : : /* Output code to perform an tanh XFmode calculation. */
19160 : :
19161 : : void
19162 : 1 : ix86_emit_i387_tanh (rtx op0, rtx op1)
19163 : : {
19164 : 1 : rtx e1 = gen_reg_rtx (XFmode);
19165 : 1 : rtx e2 = gen_reg_rtx (XFmode);
19166 : 1 : rtx scratch = gen_reg_rtx (HImode);
19167 : 1 : rtx flags = gen_rtx_REG (CCNOmode, FLAGS_REG);
19168 : 1 : rtx cst2, tmp;
19169 : 1 : rtx_code_label *jump_label = gen_label_rtx ();
19170 : 1 : rtx_insn *insn;
19171 : :
19172 : : /* scratch = fxam (op1) */
19173 : 1 : emit_insn (gen_fxamxf2_i387 (scratch, op1));
19174 : :
19175 : : /* e1 = expm1 (-|2 * op1|) */
19176 : 1 : emit_insn (gen_addxf3 (e2, op1, op1));
19177 : 1 : emit_insn (gen_absxf2 (e2, e2));
19178 : 1 : emit_insn (gen_negxf2 (e2, e2));
19179 : 1 : emit_insn (gen_expm1xf2 (e1, e2));
19180 : :
19181 : : /* e2 = e1 / (e1 + 2.0) */
19182 : 1 : cst2 = force_reg (XFmode, CONST2_RTX (XFmode));
19183 : 1 : emit_insn (gen_addxf3 (e2, e1, cst2));
19184 : 1 : emit_insn (gen_divxf3 (e2, e1, e2));
19185 : :
19186 : : /* flags = signbit (op1) */
19187 : 1 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x02)));
19188 : :
19189 : : /* if (!flags) then e2 = -e2 */
19190 : 1 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode,
19191 : : gen_rtx_NE (VOIDmode, flags, const0_rtx),
19192 : : gen_rtx_LABEL_REF (VOIDmode, jump_label),
19193 : : pc_rtx);
19194 : 1 : insn = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
19195 : 1 : predict_jump (REG_BR_PROB_BASE * 50 / 100);
19196 : 1 : JUMP_LABEL (insn) = jump_label;
19197 : :
19198 : 1 : emit_insn (gen_negxf2 (e2, e2));
19199 : :
19200 : 1 : emit_label (jump_label);
19201 : 1 : LABEL_NUSES (jump_label) = 1;
19202 : :
19203 : 1 : emit_move_insn (op0, e2);
19204 : 1 : }
19205 : :
19206 : : /* Output code to perform an asinh XFmode calculation. */
19207 : :
19208 : : void
19209 : 0 : ix86_emit_i387_asinh (rtx op0, rtx op1)
19210 : : {
19211 : 0 : rtx e1 = gen_reg_rtx (XFmode);
19212 : 0 : rtx e2 = gen_reg_rtx (XFmode);
19213 : 0 : rtx scratch = gen_reg_rtx (HImode);
19214 : 0 : rtx flags = gen_rtx_REG (CCNOmode, FLAGS_REG);
19215 : 0 : rtx cst1, tmp;
19216 : 0 : rtx_code_label *jump_label = gen_label_rtx ();
19217 : 0 : rtx_insn *insn;
19218 : :
19219 : : /* e2 = sqrt (op1^2 + 1.0) + 1.0 */
19220 : 0 : emit_insn (gen_mulxf3 (e1, op1, op1));
19221 : 0 : cst1 = force_reg (XFmode, CONST1_RTX (XFmode));
19222 : 0 : emit_insn (gen_addxf3 (e2, e1, cst1));
19223 : 0 : emit_insn (gen_sqrtxf2 (e2, e2));
19224 : 0 : emit_insn (gen_addxf3 (e2, e2, cst1));
19225 : :
19226 : : /* e1 = e1 / e2 */
19227 : 0 : emit_insn (gen_divxf3 (e1, e1, e2));
19228 : :
19229 : : /* scratch = fxam (op1) */
19230 : 0 : emit_insn (gen_fxamxf2_i387 (scratch, op1));
19231 : :
19232 : : /* e1 = e1 + |op1| */
19233 : 0 : emit_insn (gen_absxf2 (e2, op1));
19234 : 0 : emit_insn (gen_addxf3 (e1, e1, e2));
19235 : :
19236 : : /* e2 = log1p (e1) */
19237 : 0 : ix86_emit_i387_log1p (e2, e1);
19238 : :
19239 : : /* flags = signbit (op1) */
19240 : 0 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x02)));
19241 : :
19242 : : /* if (flags) then e2 = -e2 */
19243 : 0 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode,
19244 : : gen_rtx_EQ (VOIDmode, flags, const0_rtx),
19245 : : gen_rtx_LABEL_REF (VOIDmode, jump_label),
19246 : : pc_rtx);
19247 : 0 : insn = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
19248 : 0 : predict_jump (REG_BR_PROB_BASE * 50 / 100);
19249 : 0 : JUMP_LABEL (insn) = jump_label;
19250 : :
19251 : 0 : emit_insn (gen_negxf2 (e2, e2));
19252 : :
19253 : 0 : emit_label (jump_label);
19254 : 0 : LABEL_NUSES (jump_label) = 1;
19255 : :
19256 : 0 : emit_move_insn (op0, e2);
19257 : 0 : }
19258 : :
19259 : : /* Output code to perform an acosh XFmode calculation. */
19260 : :
19261 : : void
19262 : 0 : ix86_emit_i387_acosh (rtx op0, rtx op1)
19263 : : {
19264 : 0 : rtx e1 = gen_reg_rtx (XFmode);
19265 : 0 : rtx e2 = gen_reg_rtx (XFmode);
19266 : 0 : rtx cst1 = force_reg (XFmode, CONST1_RTX (XFmode));
19267 : :
19268 : : /* e2 = sqrt (op1 + 1.0) */
19269 : 0 : emit_insn (gen_addxf3 (e2, op1, cst1));
19270 : 0 : emit_insn (gen_sqrtxf2 (e2, e2));
19271 : :
19272 : : /* e1 = sqrt (op1 - 1.0) */
19273 : 0 : emit_insn (gen_subxf3 (e1, op1, cst1));
19274 : 0 : emit_insn (gen_sqrtxf2 (e1, e1));
19275 : :
19276 : : /* e1 = e1 * e2 */
19277 : 0 : emit_insn (gen_mulxf3 (e1, e1, e2));
19278 : :
19279 : : /* e1 = e1 + op1 */
19280 : 0 : emit_insn (gen_addxf3 (e1, e1, op1));
19281 : :
19282 : : /* op0 = log (e1) */
19283 : 0 : emit_insn (gen_logxf2 (op0, e1));
19284 : 0 : }
19285 : :
19286 : : /* Output code to perform an atanh XFmode calculation. */
19287 : :
19288 : : void
19289 : 4 : ix86_emit_i387_atanh (rtx op0, rtx op1)
19290 : : {
19291 : 4 : rtx e1 = gen_reg_rtx (XFmode);
19292 : 4 : rtx e2 = gen_reg_rtx (XFmode);
19293 : 4 : rtx scratch = gen_reg_rtx (HImode);
19294 : 4 : rtx flags = gen_rtx_REG (CCNOmode, FLAGS_REG);
19295 : 4 : rtx half = const_double_from_real_value (dconsthalf, XFmode);
19296 : 4 : rtx cst1, tmp;
19297 : 4 : rtx_code_label *jump_label = gen_label_rtx ();
19298 : 4 : rtx_insn *insn;
19299 : :
19300 : : /* scratch = fxam (op1) */
19301 : 4 : emit_insn (gen_fxamxf2_i387 (scratch, op1));
19302 : :
19303 : : /* e2 = |op1| */
19304 : 4 : emit_insn (gen_absxf2 (e2, op1));
19305 : :
19306 : : /* e1 = -(e2 + e2) / (e2 + 1.0) */
19307 : 4 : cst1 = force_reg (XFmode, CONST1_RTX (XFmode));
19308 : 4 : emit_insn (gen_addxf3 (e1, e2, cst1));
19309 : 4 : emit_insn (gen_addxf3 (e2, e2, e2));
19310 : 4 : emit_insn (gen_negxf2 (e2, e2));
19311 : 4 : emit_insn (gen_divxf3 (e1, e2, e1));
19312 : :
19313 : : /* e2 = log1p (e1) */
19314 : 4 : ix86_emit_i387_log1p (e2, e1);
19315 : :
19316 : : /* flags = signbit (op1) */
19317 : 4 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x02)));
19318 : :
19319 : : /* if (!flags) then e2 = -e2 */
19320 : 4 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode,
19321 : : gen_rtx_NE (VOIDmode, flags, const0_rtx),
19322 : : gen_rtx_LABEL_REF (VOIDmode, jump_label),
19323 : : pc_rtx);
19324 : 4 : insn = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
19325 : 4 : predict_jump (REG_BR_PROB_BASE * 50 / 100);
19326 : 4 : JUMP_LABEL (insn) = jump_label;
19327 : :
19328 : 4 : emit_insn (gen_negxf2 (e2, e2));
19329 : :
19330 : 4 : emit_label (jump_label);
19331 : 4 : LABEL_NUSES (jump_label) = 1;
19332 : :
19333 : : /* op0 = 0.5 * e2 */
19334 : 4 : half = force_reg (XFmode, half);
19335 : 4 : emit_insn (gen_mulxf3 (op0, e2, half));
19336 : 4 : }
19337 : :
19338 : : /* Output code to perform a log1p XFmode calculation. */
19339 : :
19340 : : void
19341 : 5 : ix86_emit_i387_log1p (rtx op0, rtx op1)
19342 : : {
19343 : 5 : rtx_code_label *label1 = gen_label_rtx ();
19344 : 5 : rtx_code_label *label2 = gen_label_rtx ();
19345 : :
19346 : 5 : rtx tmp = gen_reg_rtx (XFmode);
19347 : 5 : rtx res = gen_reg_rtx (XFmode);
19348 : 5 : rtx cst, cstln2, cst1;
19349 : 5 : rtx_insn *insn;
19350 : :
19351 : : /* The emit_jump call emits pending stack adjust, make sure it is emitted
19352 : : before the conditional jump, otherwise the stack adjustment will be
19353 : : only conditional. */
19354 : 5 : do_pending_stack_adjust ();
19355 : :
19356 : 5 : cst = const_double_from_real_value
19357 : 5 : (REAL_VALUE_ATOF ("0.29289321881345247561810596348408353", XFmode), XFmode);
19358 : 5 : cstln2 = force_reg (XFmode, standard_80387_constant_rtx (4)); /* fldln2 */
19359 : :
19360 : 5 : emit_insn (gen_absxf2 (tmp, op1));
19361 : :
19362 : 5 : cst = force_reg (XFmode, cst);
19363 : 5 : ix86_expand_branch (GE, tmp, cst, label1);
19364 : 5 : predict_jump (REG_BR_PROB_BASE * 10 / 100);
19365 : 5 : insn = get_last_insn ();
19366 : 5 : JUMP_LABEL (insn) = label1;
19367 : :
19368 : 5 : emit_insn (gen_fyl2xp1xf3_i387 (res, op1, cstln2));
19369 : 5 : emit_jump (label2);
19370 : :
19371 : 5 : emit_label (label1);
19372 : 5 : LABEL_NUSES (label1) = 1;
19373 : :
19374 : 5 : cst1 = force_reg (XFmode, CONST1_RTX (XFmode));
19375 : 5 : emit_insn (gen_rtx_SET (tmp, gen_rtx_PLUS (XFmode, op1, cst1)));
19376 : 5 : emit_insn (gen_fyl2xxf3_i387 (res, tmp, cstln2));
19377 : :
19378 : 5 : emit_label (label2);
19379 : 5 : LABEL_NUSES (label2) = 1;
19380 : :
19381 : 5 : emit_move_insn (op0, res);
19382 : 5 : }
19383 : :
19384 : : /* Emit code for round calculation. */
19385 : : void
19386 : 68 : ix86_emit_i387_round (rtx op0, rtx op1)
19387 : : {
19388 : 68 : machine_mode inmode = GET_MODE (op1);
19389 : 68 : machine_mode outmode = GET_MODE (op0);
19390 : 68 : rtx e1 = gen_reg_rtx (XFmode);
19391 : 68 : rtx e2 = gen_reg_rtx (XFmode);
19392 : 68 : rtx scratch = gen_reg_rtx (HImode);
19393 : 68 : rtx flags = gen_rtx_REG (CCNOmode, FLAGS_REG);
19394 : 68 : rtx half = const_double_from_real_value (dconsthalf, XFmode);
19395 : 68 : rtx res = gen_reg_rtx (outmode);
19396 : 68 : rtx_code_label *jump_label = gen_label_rtx ();
19397 : 68 : rtx (*floor_insn) (rtx, rtx);
19398 : 68 : rtx (*neg_insn) (rtx, rtx);
19399 : 68 : rtx_insn *insn;
19400 : 68 : rtx tmp;
19401 : :
19402 : 68 : switch (inmode)
19403 : : {
19404 : 37 : case E_SFmode:
19405 : 37 : case E_DFmode:
19406 : 37 : tmp = gen_reg_rtx (XFmode);
19407 : :
19408 : 37 : emit_insn (gen_rtx_SET (tmp, gen_rtx_FLOAT_EXTEND (XFmode, op1)));
19409 : 37 : op1 = tmp;
19410 : 37 : break;
19411 : : case E_XFmode:
19412 : : break;
19413 : 0 : default:
19414 : 0 : gcc_unreachable ();
19415 : : }
19416 : :
19417 : 68 : switch (outmode)
19418 : : {
19419 : : case E_SFmode:
19420 : : floor_insn = gen_frndintxf2_floor;
19421 : : neg_insn = gen_negsf2;
19422 : : break;
19423 : 8 : case E_DFmode:
19424 : 8 : floor_insn = gen_frndintxf2_floor;
19425 : 8 : neg_insn = gen_negdf2;
19426 : 8 : break;
19427 : 10 : case E_XFmode:
19428 : 10 : floor_insn = gen_frndintxf2_floor;
19429 : 10 : neg_insn = gen_negxf2;
19430 : 10 : break;
19431 : 0 : case E_HImode:
19432 : 0 : floor_insn = gen_lfloorxfhi2;
19433 : 0 : neg_insn = gen_neghi2;
19434 : 0 : break;
19435 : 10 : case E_SImode:
19436 : 10 : floor_insn = gen_lfloorxfsi2;
19437 : 10 : neg_insn = gen_negsi2;
19438 : 10 : break;
19439 : 36 : case E_DImode:
19440 : 36 : floor_insn = gen_lfloorxfdi2;
19441 : 36 : neg_insn = gen_negdi2;
19442 : 36 : break;
19443 : 0 : default:
19444 : 0 : gcc_unreachable ();
19445 : : }
19446 : :
19447 : : /* round(a) = sgn(a) * floor(fabs(a) + 0.5) */
19448 : :
19449 : : /* scratch = fxam(op1) */
19450 : 68 : emit_insn (gen_fxamxf2_i387 (scratch, op1));
19451 : :
19452 : : /* e1 = fabs(op1) */
19453 : 68 : emit_insn (gen_absxf2 (e1, op1));
19454 : :
19455 : : /* e2 = e1 + 0.5 */
19456 : 68 : half = force_reg (XFmode, half);
19457 : 68 : emit_insn (gen_rtx_SET (e2, gen_rtx_PLUS (XFmode, e1, half)));
19458 : :
19459 : : /* res = floor(e2) */
19460 : 68 : switch (outmode)
19461 : : {
19462 : 12 : case E_SFmode:
19463 : 12 : case E_DFmode:
19464 : 12 : {
19465 : 12 : tmp = gen_reg_rtx (XFmode);
19466 : :
19467 : 12 : emit_insn (floor_insn (tmp, e2));
19468 : 12 : emit_insn (gen_rtx_SET (res,
19469 : : gen_rtx_UNSPEC (outmode, gen_rtvec (1, tmp),
19470 : : UNSPEC_TRUNC_NOOP)));
19471 : : }
19472 : 12 : break;
19473 : 56 : default:
19474 : 56 : emit_insn (floor_insn (res, e2));
19475 : : }
19476 : :
19477 : : /* flags = signbit(a) */
19478 : 68 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x02)));
19479 : :
19480 : : /* if (flags) then res = -res */
19481 : 68 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode,
19482 : : gen_rtx_EQ (VOIDmode, flags, const0_rtx),
19483 : : gen_rtx_LABEL_REF (VOIDmode, jump_label),
19484 : : pc_rtx);
19485 : 68 : insn = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
19486 : 68 : predict_jump (REG_BR_PROB_BASE * 50 / 100);
19487 : 68 : JUMP_LABEL (insn) = jump_label;
19488 : :
19489 : 68 : emit_insn (neg_insn (res, res));
19490 : :
19491 : 68 : emit_label (jump_label);
19492 : 68 : LABEL_NUSES (jump_label) = 1;
19493 : :
19494 : 68 : emit_move_insn (op0, res);
19495 : 68 : }
19496 : :
19497 : : /* Output code to perform a Newton-Rhapson approximation of a single precision
19498 : : floating point divide [http://en.wikipedia.org/wiki/N-th_root_algorithm]. */
19499 : :
19500 : : void
19501 : 49 : ix86_emit_swdivsf (rtx res, rtx a, rtx b, machine_mode mode)
19502 : : {
19503 : 49 : rtx x0, x1, e0, e1;
19504 : :
19505 : 49 : x0 = gen_reg_rtx (mode);
19506 : 49 : e0 = gen_reg_rtx (mode);
19507 : 49 : e1 = gen_reg_rtx (mode);
19508 : 49 : x1 = gen_reg_rtx (mode);
19509 : :
19510 : 49 : b = force_reg (mode, b);
19511 : :
19512 : : /* x0 = rcp(b) estimate */
19513 : 49 : if (mode == V16SFmode || mode == V8DFmode)
19514 : : {
19515 : 0 : emit_insn (gen_rtx_SET (x0, gen_rtx_UNSPEC (mode, gen_rtvec (1, b),
19516 : : UNSPEC_RCP14)));
19517 : : }
19518 : : else
19519 : 49 : emit_insn (gen_rtx_SET (x0, gen_rtx_UNSPEC (mode, gen_rtvec (1, b),
19520 : : UNSPEC_RCP)));
19521 : :
19522 : 49 : unsigned vector_size = GET_MODE_SIZE (mode);
19523 : :
19524 : : /* (a - (rcp(b) * a * b)) * rcp(b) + rcp(b) * a
19525 : : N-R step with 2 fma implementation. */
19526 : 49 : if (TARGET_FMA
19527 : 48 : || (TARGET_AVX512F && vector_size == 64)
19528 : 48 : || (TARGET_AVX512VL && (vector_size == 32 || vector_size == 16)))
19529 : : {
19530 : : /* e0 = x0 * a */
19531 : 1 : emit_insn (gen_rtx_SET (e0, gen_rtx_MULT (mode, x0, a)));
19532 : : /* e1 = e0 * b - a */
19533 : 1 : emit_insn (gen_rtx_SET (e1, gen_rtx_FMA (mode, e0, b,
19534 : : gen_rtx_NEG (mode, a))));
19535 : : /* res = - e1 * x0 + e0 */
19536 : 1 : emit_insn (gen_rtx_SET (res, gen_rtx_FMA (mode,
19537 : : gen_rtx_NEG (mode, e1),
19538 : : x0, e0)));
19539 : : }
19540 : : else
19541 : : /* a / b = a * ((rcp(b) + rcp(b)) - (b * rcp(b) * rcp (b))) */
19542 : : {
19543 : : /* e0 = x0 * b */
19544 : 48 : emit_insn (gen_rtx_SET (e0, gen_rtx_MULT (mode, x0, b)));
19545 : :
19546 : : /* e1 = x0 + x0 */
19547 : 48 : emit_insn (gen_rtx_SET (e1, gen_rtx_PLUS (mode, x0, x0)));
19548 : :
19549 : : /* e0 = x0 * e0 */
19550 : 48 : emit_insn (gen_rtx_SET (e0, gen_rtx_MULT (mode, x0, e0)));
19551 : :
19552 : : /* x1 = e1 - e0 */
19553 : 48 : emit_insn (gen_rtx_SET (x1, gen_rtx_MINUS (mode, e1, e0)));
19554 : :
19555 : : /* res = a * x1 */
19556 : 48 : emit_insn (gen_rtx_SET (res, gen_rtx_MULT (mode, a, x1)));
19557 : : }
19558 : 49 : }
19559 : :
19560 : : /* Output code to perform a Newton-Rhapson approximation of a
19561 : : single precision floating point [reciprocal] square root. */
19562 : :
19563 : : void
19564 : 85 : ix86_emit_swsqrtsf (rtx res, rtx a, machine_mode mode, bool recip)
19565 : : {
19566 : 85 : rtx x0, e0, e1, e2, e3, mthree, mhalf;
19567 : 85 : REAL_VALUE_TYPE r;
19568 : 85 : int unspec;
19569 : :
19570 : 85 : x0 = gen_reg_rtx (mode);
19571 : 85 : e0 = gen_reg_rtx (mode);
19572 : 85 : e1 = gen_reg_rtx (mode);
19573 : 85 : e2 = gen_reg_rtx (mode);
19574 : 85 : e3 = gen_reg_rtx (mode);
19575 : :
19576 : 85 : real_from_integer (&r, VOIDmode, -3, SIGNED);
19577 : 85 : mthree = const_double_from_real_value (r, SFmode);
19578 : :
19579 : 85 : real_arithmetic (&r, NEGATE_EXPR, &dconsthalf, NULL);
19580 : 85 : mhalf = const_double_from_real_value (r, SFmode);
19581 : 85 : unspec = UNSPEC_RSQRT;
19582 : :
19583 : 85 : if (VECTOR_MODE_P (mode))
19584 : : {
19585 : 66 : mthree = ix86_build_const_vector (mode, true, mthree);
19586 : 66 : mhalf = ix86_build_const_vector (mode, true, mhalf);
19587 : : /* There is no 512-bit rsqrt. There is however rsqrt14. */
19588 : 132 : if (GET_MODE_SIZE (mode) == 64)
19589 : 0 : unspec = UNSPEC_RSQRT14;
19590 : : }
19591 : :
19592 : : /* sqrt(a) = -0.5 * a * rsqrtss(a) * (a * rsqrtss(a) * rsqrtss(a) - 3.0)
19593 : : rsqrt(a) = -0.5 * rsqrtss(a) * (a * rsqrtss(a) * rsqrtss(a) - 3.0) */
19594 : :
19595 : 85 : a = force_reg (mode, a);
19596 : :
19597 : : /* x0 = rsqrt(a) estimate */
19598 : 85 : emit_insn (gen_rtx_SET (x0, gen_rtx_UNSPEC (mode, gen_rtvec (1, a),
19599 : : unspec)));
19600 : :
19601 : : /* If (a == 0.0) Filter out infinity to prevent NaN for sqrt(0.0). */
19602 : 85 : if (!recip)
19603 : : {
19604 : 57 : rtx zero = force_reg (mode, CONST0_RTX(mode));
19605 : 57 : rtx mask;
19606 : :
19607 : : /* Handle masked compare. */
19608 : 110 : if (VECTOR_MODE_P (mode) && GET_MODE_SIZE (mode) == 64)
19609 : : {
19610 : 0 : mask = gen_reg_rtx (HImode);
19611 : : /* Imm value 0x4 corresponds to not-equal comparison. */
19612 : 0 : emit_insn (gen_avx512f_cmpv16sf3 (mask, zero, a, GEN_INT (0x4)));
19613 : 0 : emit_insn (gen_avx512f_blendmv16sf (x0, zero, x0, mask));
19614 : : }
19615 : : else
19616 : : {
19617 : 57 : mask = gen_reg_rtx (mode);
19618 : 57 : emit_insn (gen_rtx_SET (mask, gen_rtx_NE (mode, zero, a)));
19619 : 57 : emit_insn (gen_rtx_SET (x0, gen_rtx_AND (mode, x0, mask)));
19620 : : }
19621 : : }
19622 : :
19623 : 85 : mthree = force_reg (mode, mthree);
19624 : :
19625 : : /* e0 = x0 * a */
19626 : 85 : emit_insn (gen_rtx_SET (e0, gen_rtx_MULT (mode, x0, a)));
19627 : :
19628 : 85 : unsigned vector_size = GET_MODE_SIZE (mode);
19629 : 85 : if (TARGET_FMA
19630 : 77 : || (TARGET_AVX512F && vector_size == 64)
19631 : 77 : || (TARGET_AVX512VL && (vector_size == 32 || vector_size == 16)))
19632 : 16 : emit_insn (gen_rtx_SET (e2,
19633 : : gen_rtx_FMA (mode, e0, x0, mthree)));
19634 : : else
19635 : : {
19636 : : /* e1 = e0 * x0 */
19637 : 69 : emit_insn (gen_rtx_SET (e1, gen_rtx_MULT (mode, e0, x0)));
19638 : :
19639 : : /* e2 = e1 - 3. */
19640 : 69 : emit_insn (gen_rtx_SET (e2, gen_rtx_PLUS (mode, e1, mthree)));
19641 : : }
19642 : :
19643 : 85 : mhalf = force_reg (mode, mhalf);
19644 : 85 : if (recip)
19645 : : /* e3 = -.5 * x0 */
19646 : 28 : emit_insn (gen_rtx_SET (e3, gen_rtx_MULT (mode, x0, mhalf)));
19647 : : else
19648 : : /* e3 = -.5 * e0 */
19649 : 57 : emit_insn (gen_rtx_SET (e3, gen_rtx_MULT (mode, e0, mhalf)));
19650 : : /* ret = e2 * e3 */
19651 : 85 : emit_insn (gen_rtx_SET (res, gen_rtx_MULT (mode, e2, e3)));
19652 : 85 : }
19653 : :
19654 : : /* Expand fabs (OP0) and return a new rtx that holds the result. The
19655 : : mask for masking out the sign-bit is stored in *SMASK, if that is
19656 : : non-null. */
19657 : :
19658 : : static rtx
19659 : 1040 : ix86_expand_sse_fabs (rtx op0, rtx *smask)
19660 : : {
19661 : 1040 : machine_mode vmode, mode = GET_MODE (op0);
19662 : 1040 : rtx xa, mask;
19663 : :
19664 : 1040 : xa = gen_reg_rtx (mode);
19665 : 1040 : if (mode == SFmode)
19666 : : vmode = V4SFmode;
19667 : 491 : else if (mode == DFmode)
19668 : : vmode = V2DFmode;
19669 : : else
19670 : 0 : vmode = mode;
19671 : 1040 : mask = ix86_build_signbit_mask (vmode, VECTOR_MODE_P (mode), true);
19672 : 1040 : if (!VECTOR_MODE_P (mode))
19673 : : {
19674 : : /* We need to generate a scalar mode mask in this case. */
19675 : 1040 : rtx tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (1, const0_rtx));
19676 : 1040 : tmp = gen_rtx_VEC_SELECT (mode, mask, tmp);
19677 : 1040 : mask = gen_reg_rtx (mode);
19678 : 1040 : emit_insn (gen_rtx_SET (mask, tmp));
19679 : : }
19680 : 1040 : emit_insn (gen_rtx_SET (xa, gen_rtx_AND (mode, op0, mask)));
19681 : :
19682 : 1040 : if (smask)
19683 : 987 : *smask = mask;
19684 : :
19685 : 1040 : return xa;
19686 : : }
19687 : :
19688 : : /* Expands a comparison of OP0 with OP1 using comparison code CODE,
19689 : : swapping the operands if SWAP_OPERANDS is true. The expanded
19690 : : code is a forward jump to a newly created label in case the
19691 : : comparison is true. The generated label rtx is returned. */
19692 : : static rtx_code_label *
19693 : 1055 : ix86_expand_sse_compare_and_jump (enum rtx_code code, rtx op0, rtx op1,
19694 : : bool swap_operands)
19695 : : {
19696 : 1055 : bool unordered_compare = ix86_unordered_fp_compare (code);
19697 : 1055 : rtx_code_label *label;
19698 : 1055 : rtx tmp, reg;
19699 : :
19700 : 1055 : if (swap_operands)
19701 : 34 : std::swap (op0, op1);
19702 : :
19703 : 1055 : label = gen_label_rtx ();
19704 : 1055 : tmp = gen_rtx_COMPARE (CCFPmode, op0, op1);
19705 : 1055 : if (unordered_compare)
19706 : 899 : tmp = gen_rtx_UNSPEC (CCFPmode, gen_rtvec (1, tmp), UNSPEC_NOTRAP);
19707 : 1055 : reg = gen_rtx_REG (CCFPmode, FLAGS_REG);
19708 : 1055 : emit_insn (gen_rtx_SET (reg, tmp));
19709 : 1055 : tmp = gen_rtx_fmt_ee (code, VOIDmode, reg, const0_rtx);
19710 : 1055 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
19711 : : gen_rtx_LABEL_REF (VOIDmode, label), pc_rtx);
19712 : 1055 : tmp = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
19713 : 1055 : JUMP_LABEL (tmp) = label;
19714 : :
19715 : 1055 : return label;
19716 : : }
19717 : :
19718 : : /* Expand a mask generating SSE comparison instruction comparing OP0 with OP1
19719 : : using comparison code CODE. Operands are swapped for the comparison if
19720 : : SWAP_OPERANDS is true. Returns a rtx for the generated mask. */
19721 : : static rtx
19722 : 567 : ix86_expand_sse_compare_mask (enum rtx_code code, rtx op0, rtx op1,
19723 : : bool swap_operands)
19724 : : {
19725 : 567 : rtx (*insn)(rtx, rtx, rtx, rtx);
19726 : 567 : machine_mode mode = GET_MODE (op0);
19727 : 567 : rtx mask = gen_reg_rtx (mode);
19728 : :
19729 : 567 : if (swap_operands)
19730 : 388 : std::swap (op0, op1);
19731 : :
19732 : 567 : insn = mode == DFmode ? gen_setcc_df_sse : gen_setcc_sf_sse;
19733 : :
19734 : 567 : emit_insn (insn (mask, op0, op1,
19735 : : gen_rtx_fmt_ee (code, mode, op0, op1)));
19736 : 567 : return mask;
19737 : : }
19738 : :
19739 : : /* Expand copysign from SIGN to the positive value ABS_VALUE
19740 : : storing in RESULT. If MASK is non-null, it shall be a mask to mask out
19741 : : the sign-bit. */
19742 : :
19743 : : static void
19744 : 1007 : ix86_sse_copysign_to_positive (rtx result, rtx abs_value, rtx sign, rtx mask)
19745 : : {
19746 : 1007 : machine_mode mode = GET_MODE (sign);
19747 : 1007 : rtx sgn = gen_reg_rtx (mode);
19748 : 1007 : if (mask == NULL_RTX)
19749 : : {
19750 : 28 : machine_mode vmode;
19751 : :
19752 : 28 : if (mode == SFmode)
19753 : : vmode = V4SFmode;
19754 : : else if (mode == DFmode)
19755 : : vmode = V2DFmode;
19756 : : else if (mode == HFmode)
19757 : : vmode = V8HFmode;
19758 : : else
19759 : 28 : vmode = mode;
19760 : :
19761 : 28 : mask = ix86_build_signbit_mask (vmode, VECTOR_MODE_P (mode), false);
19762 : 28 : if (!VECTOR_MODE_P (mode))
19763 : : {
19764 : : /* We need to generate a scalar mode mask in this case. */
19765 : 28 : rtx tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (1, const0_rtx));
19766 : 28 : tmp = gen_rtx_VEC_SELECT (mode, mask, tmp);
19767 : 28 : mask = gen_reg_rtx (mode);
19768 : 28 : emit_insn (gen_rtx_SET (mask, tmp));
19769 : : }
19770 : : }
19771 : : else
19772 : 979 : mask = gen_rtx_NOT (mode, mask);
19773 : 1007 : emit_insn (gen_rtx_SET (sgn, gen_rtx_AND (mode, mask, sign)));
19774 : 1007 : emit_insn (gen_rtx_SET (result, gen_rtx_IOR (mode, abs_value, sgn)));
19775 : 1007 : }
19776 : :
19777 : : /* Expand SSE sequence for computing lround from OP1 storing
19778 : : into OP0. */
19779 : :
19780 : : void
19781 : 28 : ix86_expand_lround (rtx op0, rtx op1)
19782 : : {
19783 : : /* C code for the stuff we're doing below:
19784 : : tmp = op1 + copysign (nextafter (0.5, 0.0), op1)
19785 : : return (long)tmp;
19786 : : */
19787 : 28 : machine_mode mode = GET_MODE (op1);
19788 : 28 : const struct real_format *fmt;
19789 : 28 : REAL_VALUE_TYPE pred_half, half_minus_pred_half;
19790 : 28 : rtx adj;
19791 : :
19792 : : /* load nextafter (0.5, 0.0) */
19793 : 28 : fmt = REAL_MODE_FORMAT (mode);
19794 : 28 : real_2expN (&half_minus_pred_half, -(fmt->p) - 1, mode);
19795 : 28 : real_arithmetic (&pred_half, MINUS_EXPR, &dconsthalf, &half_minus_pred_half);
19796 : :
19797 : : /* adj = copysign (0.5, op1) */
19798 : 28 : adj = force_reg (mode, const_double_from_real_value (pred_half, mode));
19799 : 28 : ix86_sse_copysign_to_positive (adj, adj, force_reg (mode, op1), NULL_RTX);
19800 : :
19801 : : /* adj = op1 + adj */
19802 : 28 : adj = expand_simple_binop (mode, PLUS, adj, op1, NULL_RTX, 0, OPTAB_DIRECT);
19803 : :
19804 : : /* op0 = (imode)adj */
19805 : 28 : expand_fix (op0, adj, 0);
19806 : 28 : }
19807 : :
19808 : : /* Expand SSE2 sequence for computing lround from OPERAND1 storing
19809 : : into OPERAND0. */
19810 : :
19811 : : void
19812 : 68 : ix86_expand_lfloorceil (rtx op0, rtx op1, bool do_floor)
19813 : : {
19814 : : /* C code for the stuff we're doing below (for do_floor):
19815 : : xi = (long)op1;
19816 : : xi -= (double)xi > op1 ? 1 : 0;
19817 : : return xi;
19818 : : */
19819 : 68 : machine_mode fmode = GET_MODE (op1);
19820 : 68 : machine_mode imode = GET_MODE (op0);
19821 : 68 : rtx ireg, freg, tmp;
19822 : 68 : rtx_code_label *label;
19823 : :
19824 : : /* reg = (long)op1 */
19825 : 68 : ireg = gen_reg_rtx (imode);
19826 : 68 : expand_fix (ireg, op1, 0);
19827 : :
19828 : : /* freg = (double)reg */
19829 : 68 : freg = gen_reg_rtx (fmode);
19830 : 68 : expand_float (freg, ireg, 0);
19831 : :
19832 : : /* ireg = (freg > op1) ? ireg - 1 : ireg */
19833 : 136 : label = ix86_expand_sse_compare_and_jump (UNLE,
19834 : 68 : freg, op1, !do_floor);
19835 : 102 : tmp = expand_simple_binop (imode, do_floor ? MINUS : PLUS,
19836 : : ireg, const1_rtx, NULL_RTX, 0, OPTAB_DIRECT);
19837 : 68 : emit_move_insn (ireg, tmp);
19838 : :
19839 : 68 : emit_label (label);
19840 : 68 : LABEL_NUSES (label) = 1;
19841 : :
19842 : 68 : emit_move_insn (op0, ireg);
19843 : 68 : }
19844 : :
19845 : : /* Generate and return a rtx of mode MODE for 2**n where n is the number
19846 : : of bits of the mantissa of MODE, which must be one of DFmode or SFmode. */
19847 : :
19848 : : static rtx
19849 : 987 : ix86_gen_TWO52 (machine_mode mode)
19850 : : {
19851 : 987 : const struct real_format *fmt;
19852 : 987 : REAL_VALUE_TYPE TWO52r;
19853 : 987 : rtx TWO52;
19854 : :
19855 : 987 : fmt = REAL_MODE_FORMAT (mode);
19856 : 987 : real_2expN (&TWO52r, fmt->p - 1, mode);
19857 : 987 : TWO52 = const_double_from_real_value (TWO52r, mode);
19858 : 987 : TWO52 = force_reg (mode, TWO52);
19859 : :
19860 : 987 : return TWO52;
19861 : : }
19862 : :
19863 : : /* Expand rint rounding OPERAND1 and storing the result in OPERAND0. */
19864 : :
19865 : : void
19866 : 122 : ix86_expand_rint (rtx operand0, rtx operand1)
19867 : : {
19868 : : /* C code for the stuff we're doing below:
19869 : : xa = fabs (operand1);
19870 : : if (!isless (xa, 2**52))
19871 : : return operand1;
19872 : : two52 = 2**52;
19873 : : if (flag_rounding_math)
19874 : : {
19875 : : two52 = copysign (two52, operand1);
19876 : : xa = operand1;
19877 : : }
19878 : : xa = xa + two52 - two52;
19879 : : return copysign (xa, operand1);
19880 : : */
19881 : 122 : machine_mode mode = GET_MODE (operand0);
19882 : 122 : rtx res, xa, TWO52, mask;
19883 : 122 : rtx_code_label *label;
19884 : :
19885 : 122 : TWO52 = ix86_gen_TWO52 (mode);
19886 : :
19887 : : /* Temporary for holding the result, initialized to the input
19888 : : operand to ease control flow. */
19889 : 122 : res = copy_to_reg (operand1);
19890 : :
19891 : : /* xa = abs (operand1) */
19892 : 122 : xa = ix86_expand_sse_fabs (res, &mask);
19893 : :
19894 : : /* if (!isless (xa, TWO52)) goto label; */
19895 : 122 : label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
19896 : :
19897 : 122 : if (flag_rounding_math)
19898 : : {
19899 : 53 : ix86_sse_copysign_to_positive (TWO52, TWO52, res, mask);
19900 : 53 : xa = res;
19901 : : }
19902 : :
19903 : 122 : xa = expand_simple_binop (mode, PLUS, xa, TWO52, NULL_RTX, 0, OPTAB_DIRECT);
19904 : 122 : xa = expand_simple_binop (mode, MINUS, xa, TWO52, xa, 0, OPTAB_DIRECT);
19905 : :
19906 : : /* Remove the sign with FE_DOWNWARD, where x - x = -0.0. */
19907 : 122 : if (HONOR_SIGNED_ZEROS (mode) && flag_rounding_math)
19908 : 53 : xa = ix86_expand_sse_fabs (xa, NULL);
19909 : :
19910 : 122 : ix86_sse_copysign_to_positive (res, xa, res, mask);
19911 : :
19912 : 122 : emit_label (label);
19913 : 122 : LABEL_NUSES (label) = 1;
19914 : :
19915 : 122 : emit_move_insn (operand0, res);
19916 : 122 : }
19917 : :
19918 : : /* Expand SSE2 sequence for computing floor or ceil
19919 : : from OPERAND1 storing into OPERAND0. */
19920 : : void
19921 : 567 : ix86_expand_floorceil (rtx operand0, rtx operand1, bool do_floor)
19922 : : {
19923 : : /* C code for the stuff we expand below.
19924 : : double xa = fabs (x), x2;
19925 : : if (!isless (xa, TWO52))
19926 : : return x;
19927 : : x2 = (double)(long)x;
19928 : :
19929 : : Compensate. Floor:
19930 : : if (x2 > x)
19931 : : x2 -= 1;
19932 : : Compensate. Ceil:
19933 : : if (x2 < x)
19934 : : x2 += 1;
19935 : :
19936 : : if (HONOR_SIGNED_ZEROS (mode))
19937 : : return copysign (x2, x);
19938 : : return x2;
19939 : : */
19940 : 567 : machine_mode mode = GET_MODE (operand0);
19941 : 567 : rtx xa, xi, TWO52, tmp, one, res, mask;
19942 : 567 : rtx_code_label *label;
19943 : :
19944 : 567 : TWO52 = ix86_gen_TWO52 (mode);
19945 : :
19946 : : /* Temporary for holding the result, initialized to the input
19947 : : operand to ease control flow. */
19948 : 567 : res = copy_to_reg (operand1);
19949 : :
19950 : : /* xa = abs (operand1) */
19951 : 567 : xa = ix86_expand_sse_fabs (res, &mask);
19952 : :
19953 : : /* if (!isless (xa, TWO52)) goto label; */
19954 : 567 : label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
19955 : :
19956 : : /* xa = (double)(long)x */
19957 : 567 : xi = gen_reg_rtx (int_mode_for_mode (mode).require ());
19958 : 567 : expand_fix (xi, res, 0);
19959 : 567 : expand_float (xa, xi, 0);
19960 : :
19961 : : /* generate 1.0 */
19962 : 567 : one = force_reg (mode, const_double_from_real_value (dconst1, mode));
19963 : :
19964 : : /* Compensate: xa = xa - (xa > operand1 ? 1 : 0) */
19965 : 567 : tmp = ix86_expand_sse_compare_mask (UNGT, xa, res, !do_floor);
19966 : 567 : emit_insn (gen_rtx_SET (tmp, gen_rtx_AND (mode, one, tmp)));
19967 : 955 : tmp = expand_simple_binop (mode, do_floor ? MINUS : PLUS,
19968 : : xa, tmp, NULL_RTX, 0, OPTAB_DIRECT);
19969 : 567 : if (HONOR_SIGNED_ZEROS (mode))
19970 : : {
19971 : : /* Remove the sign with FE_DOWNWARD, where x - x = -0.0. */
19972 : 520 : if (do_floor && flag_rounding_math)
19973 : 0 : tmp = ix86_expand_sse_fabs (tmp, NULL);
19974 : :
19975 : 520 : ix86_sse_copysign_to_positive (tmp, tmp, res, mask);
19976 : : }
19977 : 567 : emit_move_insn (res, tmp);
19978 : :
19979 : 567 : emit_label (label);
19980 : 567 : LABEL_NUSES (label) = 1;
19981 : :
19982 : 567 : emit_move_insn (operand0, res);
19983 : 567 : }
19984 : :
19985 : : /* Expand SSE2 sequence for computing floor or ceil from OPERAND1 storing
19986 : : into OPERAND0 without relying on DImode truncation via cvttsd2siq
19987 : : that is only available on 64bit targets. */
19988 : : void
19989 : 0 : ix86_expand_floorceildf_32 (rtx operand0, rtx operand1, bool do_floor)
19990 : : {
19991 : : /* C code for the stuff we expand below.
19992 : : double xa = fabs (x), x2;
19993 : : if (!isless (xa, TWO52))
19994 : : return x;
19995 : : xa = xa + TWO52 - TWO52;
19996 : : x2 = copysign (xa, x);
19997 : :
19998 : : Compensate. Floor:
19999 : : if (x2 > x)
20000 : : x2 -= 1;
20001 : : Compensate. Ceil:
20002 : : if (x2 < x)
20003 : : x2 += 1;
20004 : :
20005 : : if (HONOR_SIGNED_ZEROS (mode))
20006 : : x2 = copysign (x2, x);
20007 : : return x2;
20008 : : */
20009 : 0 : machine_mode mode = GET_MODE (operand0);
20010 : 0 : rtx xa, TWO52, tmp, one, res, mask;
20011 : 0 : rtx_code_label *label;
20012 : :
20013 : 0 : TWO52 = ix86_gen_TWO52 (mode);
20014 : :
20015 : : /* Temporary for holding the result, initialized to the input
20016 : : operand to ease control flow. */
20017 : 0 : res = copy_to_reg (operand1);
20018 : :
20019 : : /* xa = abs (operand1) */
20020 : 0 : xa = ix86_expand_sse_fabs (res, &mask);
20021 : :
20022 : : /* if (!isless (xa, TWO52)) goto label; */
20023 : 0 : label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
20024 : :
20025 : : /* xa = xa + TWO52 - TWO52; */
20026 : 0 : xa = expand_simple_binop (mode, PLUS, xa, TWO52, NULL_RTX, 0, OPTAB_DIRECT);
20027 : 0 : xa = expand_simple_binop (mode, MINUS, xa, TWO52, xa, 0, OPTAB_DIRECT);
20028 : :
20029 : : /* xa = copysign (xa, operand1) */
20030 : 0 : ix86_sse_copysign_to_positive (xa, xa, res, mask);
20031 : :
20032 : : /* generate 1.0 */
20033 : 0 : one = force_reg (mode, const_double_from_real_value (dconst1, mode));
20034 : :
20035 : : /* Compensate: xa = xa - (xa > operand1 ? 1 : 0) */
20036 : 0 : tmp = ix86_expand_sse_compare_mask (UNGT, xa, res, !do_floor);
20037 : 0 : emit_insn (gen_rtx_SET (tmp, gen_rtx_AND (mode, one, tmp)));
20038 : 0 : tmp = expand_simple_binop (mode, do_floor ? MINUS : PLUS,
20039 : : xa, tmp, NULL_RTX, 0, OPTAB_DIRECT);
20040 : 0 : if (HONOR_SIGNED_ZEROS (mode))
20041 : : {
20042 : : /* Remove the sign with FE_DOWNWARD, where x - x = -0.0. */
20043 : 0 : if (do_floor && flag_rounding_math)
20044 : 0 : tmp = ix86_expand_sse_fabs (tmp, NULL);
20045 : :
20046 : 0 : ix86_sse_copysign_to_positive (tmp, tmp, res, mask);
20047 : : }
20048 : 0 : emit_move_insn (res, tmp);
20049 : :
20050 : 0 : emit_label (label);
20051 : 0 : LABEL_NUSES (label) = 1;
20052 : :
20053 : 0 : emit_move_insn (operand0, res);
20054 : 0 : }
20055 : :
20056 : : /* Expand SSE sequence for computing trunc
20057 : : from OPERAND1 storing into OPERAND0. */
20058 : : void
20059 : 284 : ix86_expand_trunc (rtx operand0, rtx operand1)
20060 : : {
20061 : : /* C code for SSE variant we expand below.
20062 : : double xa = fabs (x), x2;
20063 : : if (!isless (xa, TWO52))
20064 : : return x;
20065 : : x2 = (double)(long)x;
20066 : : if (HONOR_SIGNED_ZEROS (mode))
20067 : : return copysign (x2, x);
20068 : : return x2;
20069 : : */
20070 : 284 : machine_mode mode = GET_MODE (operand0);
20071 : 284 : rtx xa, xi, TWO52, res, mask;
20072 : 284 : rtx_code_label *label;
20073 : :
20074 : 284 : TWO52 = ix86_gen_TWO52 (mode);
20075 : :
20076 : : /* Temporary for holding the result, initialized to the input
20077 : : operand to ease control flow. */
20078 : 284 : res = copy_to_reg (operand1);
20079 : :
20080 : : /* xa = abs (operand1) */
20081 : 284 : xa = ix86_expand_sse_fabs (res, &mask);
20082 : :
20083 : : /* if (!isless (xa, TWO52)) goto label; */
20084 : 284 : label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
20085 : :
20086 : : /* xa = (double)(long)x */
20087 : 284 : xi = gen_reg_rtx (int_mode_for_mode (mode).require ());
20088 : 284 : expand_fix (xi, res, 0);
20089 : 284 : expand_float (xa, xi, 0);
20090 : :
20091 : 284 : if (HONOR_SIGNED_ZEROS (mode))
20092 : 270 : ix86_sse_copysign_to_positive (xa, xa, res, mask);
20093 : :
20094 : 284 : emit_move_insn (res, xa);
20095 : :
20096 : 284 : emit_label (label);
20097 : 284 : LABEL_NUSES (label) = 1;
20098 : :
20099 : 284 : emit_move_insn (operand0, res);
20100 : 284 : }
20101 : :
20102 : : /* Expand SSE sequence for computing trunc from OPERAND1 storing
20103 : : into OPERAND0 without relying on DImode truncation via cvttsd2siq
20104 : : that is only available on 64bit targets. */
20105 : : void
20106 : 0 : ix86_expand_truncdf_32 (rtx operand0, rtx operand1)
20107 : : {
20108 : 0 : machine_mode mode = GET_MODE (operand0);
20109 : 0 : rtx xa, xa2, TWO52, tmp, one, res, mask;
20110 : 0 : rtx_code_label *label;
20111 : :
20112 : : /* C code for SSE variant we expand below.
20113 : : double xa = fabs (x), x2;
20114 : : if (!isless (xa, TWO52))
20115 : : return x;
20116 : : xa2 = xa + TWO52 - TWO52;
20117 : : Compensate:
20118 : : if (xa2 > xa)
20119 : : xa2 -= 1.0;
20120 : : x2 = copysign (xa2, x);
20121 : : return x2;
20122 : : */
20123 : :
20124 : 0 : TWO52 = ix86_gen_TWO52 (mode);
20125 : :
20126 : : /* Temporary for holding the result, initialized to the input
20127 : : operand to ease control flow. */
20128 : 0 : res =copy_to_reg (operand1);
20129 : :
20130 : : /* xa = abs (operand1) */
20131 : 0 : xa = ix86_expand_sse_fabs (res, &mask);
20132 : :
20133 : : /* if (!isless (xa, TWO52)) goto label; */
20134 : 0 : label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
20135 : :
20136 : : /* xa2 = xa + TWO52 - TWO52; */
20137 : 0 : xa2 = expand_simple_binop (mode, PLUS, xa, TWO52, NULL_RTX, 0, OPTAB_DIRECT);
20138 : 0 : xa2 = expand_simple_binop (mode, MINUS, xa2, TWO52, xa2, 0, OPTAB_DIRECT);
20139 : :
20140 : : /* generate 1.0 */
20141 : 0 : one = force_reg (mode, const_double_from_real_value (dconst1, mode));
20142 : :
20143 : : /* Compensate: xa2 = xa2 - (xa2 > xa ? 1 : 0) */
20144 : 0 : tmp = ix86_expand_sse_compare_mask (UNGT, xa2, xa, false);
20145 : 0 : emit_insn (gen_rtx_SET (tmp, gen_rtx_AND (mode, one, tmp)));
20146 : 0 : tmp = expand_simple_binop (mode, MINUS,
20147 : : xa2, tmp, NULL_RTX, 0, OPTAB_DIRECT);
20148 : : /* Remove the sign with FE_DOWNWARD, where x - x = -0.0. */
20149 : 0 : if (HONOR_SIGNED_ZEROS (mode) && flag_rounding_math)
20150 : 0 : tmp = ix86_expand_sse_fabs (tmp, NULL);
20151 : :
20152 : : /* res = copysign (xa2, operand1) */
20153 : 0 : ix86_sse_copysign_to_positive (res, tmp, res, mask);
20154 : :
20155 : 0 : emit_label (label);
20156 : 0 : LABEL_NUSES (label) = 1;
20157 : :
20158 : 0 : emit_move_insn (operand0, res);
20159 : 0 : }
20160 : :
20161 : : /* Expand SSE sequence for computing round
20162 : : from OPERAND1 storing into OPERAND0. */
20163 : : void
20164 : 14 : ix86_expand_round (rtx operand0, rtx operand1)
20165 : : {
20166 : : /* C code for the stuff we're doing below:
20167 : : double xa = fabs (x);
20168 : : if (!isless (xa, TWO52))
20169 : : return x;
20170 : : xa = (double)(long)(xa + nextafter (0.5, 0.0));
20171 : : return copysign (xa, x);
20172 : : */
20173 : 14 : machine_mode mode = GET_MODE (operand0);
20174 : 14 : rtx res, TWO52, xa, xi, half, mask;
20175 : 14 : rtx_code_label *label;
20176 : 14 : const struct real_format *fmt;
20177 : 14 : REAL_VALUE_TYPE pred_half, half_minus_pred_half;
20178 : :
20179 : : /* Temporary for holding the result, initialized to the input
20180 : : operand to ease control flow. */
20181 : 14 : res = copy_to_reg (operand1);
20182 : :
20183 : 14 : TWO52 = ix86_gen_TWO52 (mode);
20184 : 14 : xa = ix86_expand_sse_fabs (res, &mask);
20185 : 14 : label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
20186 : :
20187 : : /* load nextafter (0.5, 0.0) */
20188 : 14 : fmt = REAL_MODE_FORMAT (mode);
20189 : 14 : real_2expN (&half_minus_pred_half, -(fmt->p) - 1, mode);
20190 : 14 : real_arithmetic (&pred_half, MINUS_EXPR, &dconsthalf, &half_minus_pred_half);
20191 : :
20192 : : /* xa = xa + 0.5 */
20193 : 14 : half = force_reg (mode, const_double_from_real_value (pred_half, mode));
20194 : 14 : xa = expand_simple_binop (mode, PLUS, xa, half, NULL_RTX, 0, OPTAB_DIRECT);
20195 : :
20196 : : /* xa = (double)(int64_t)xa */
20197 : 14 : xi = gen_reg_rtx (int_mode_for_mode (mode).require ());
20198 : 14 : expand_fix (xi, xa, 0);
20199 : 14 : expand_float (xa, xi, 0);
20200 : :
20201 : : /* res = copysign (xa, operand1) */
20202 : 14 : ix86_sse_copysign_to_positive (res, xa, res, mask);
20203 : :
20204 : 14 : emit_label (label);
20205 : 14 : LABEL_NUSES (label) = 1;
20206 : :
20207 : 14 : emit_move_insn (operand0, res);
20208 : 14 : }
20209 : :
20210 : : /* Expand SSE sequence for computing round from OPERAND1 storing
20211 : : into OPERAND0 without relying on DImode truncation via cvttsd2siq
20212 : : that is only available on 64bit targets. */
20213 : : void
20214 : 0 : ix86_expand_rounddf_32 (rtx operand0, rtx operand1)
20215 : : {
20216 : : /* C code for the stuff we expand below.
20217 : : double xa = fabs (x), xa2, x2;
20218 : : if (!isless (xa, TWO52))
20219 : : return x;
20220 : : Using the absolute value and copying back sign makes
20221 : : -0.0 -> -0.0 correct.
20222 : : xa2 = xa + TWO52 - TWO52;
20223 : : Compensate.
20224 : : dxa = xa2 - xa;
20225 : : if (dxa <= -0.5)
20226 : : xa2 += 1;
20227 : : else if (dxa > 0.5)
20228 : : xa2 -= 1;
20229 : : x2 = copysign (xa2, x);
20230 : : return x2;
20231 : : */
20232 : 0 : machine_mode mode = GET_MODE (operand0);
20233 : 0 : rtx xa, xa2, dxa, TWO52, tmp, half, mhalf, one, res, mask;
20234 : 0 : rtx_code_label *label;
20235 : :
20236 : 0 : TWO52 = ix86_gen_TWO52 (mode);
20237 : :
20238 : : /* Temporary for holding the result, initialized to the input
20239 : : operand to ease control flow. */
20240 : 0 : res = copy_to_reg (operand1);
20241 : :
20242 : : /* xa = abs (operand1) */
20243 : 0 : xa = ix86_expand_sse_fabs (res, &mask);
20244 : :
20245 : : /* if (!isless (xa, TWO52)) goto label; */
20246 : 0 : label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
20247 : :
20248 : : /* xa2 = xa + TWO52 - TWO52; */
20249 : 0 : xa2 = expand_simple_binop (mode, PLUS, xa, TWO52, NULL_RTX, 0, OPTAB_DIRECT);
20250 : 0 : xa2 = expand_simple_binop (mode, MINUS, xa2, TWO52, xa2, 0, OPTAB_DIRECT);
20251 : :
20252 : : /* dxa = xa2 - xa; */
20253 : 0 : dxa = expand_simple_binop (mode, MINUS, xa2, xa, NULL_RTX, 0, OPTAB_DIRECT);
20254 : :
20255 : : /* generate 0.5, 1.0 and -0.5 */
20256 : 0 : half = force_reg (mode, const_double_from_real_value (dconsthalf, mode));
20257 : 0 : one = expand_simple_binop (mode, PLUS, half, half, NULL_RTX, 0, OPTAB_DIRECT);
20258 : 0 : mhalf = expand_simple_binop (mode, MINUS, half, one, NULL_RTX,
20259 : : 0, OPTAB_DIRECT);
20260 : :
20261 : : /* Compensate. */
20262 : : /* xa2 = xa2 - (dxa > 0.5 ? 1 : 0) */
20263 : 0 : tmp = ix86_expand_sse_compare_mask (UNGT, dxa, half, false);
20264 : 0 : emit_insn (gen_rtx_SET (tmp, gen_rtx_AND (mode, tmp, one)));
20265 : 0 : xa2 = expand_simple_binop (mode, MINUS, xa2, tmp, NULL_RTX, 0, OPTAB_DIRECT);
20266 : : /* xa2 = xa2 + (dxa <= -0.5 ? 1 : 0) */
20267 : 0 : tmp = ix86_expand_sse_compare_mask (UNGE, mhalf, dxa, false);
20268 : 0 : emit_insn (gen_rtx_SET (tmp, gen_rtx_AND (mode, tmp, one)));
20269 : 0 : xa2 = expand_simple_binop (mode, PLUS, xa2, tmp, NULL_RTX, 0, OPTAB_DIRECT);
20270 : :
20271 : : /* res = copysign (xa2, operand1) */
20272 : 0 : ix86_sse_copysign_to_positive (res, xa2, res, mask);
20273 : :
20274 : 0 : emit_label (label);
20275 : 0 : LABEL_NUSES (label) = 1;
20276 : :
20277 : 0 : emit_move_insn (operand0, res);
20278 : 0 : }
20279 : :
20280 : : /* Expand SSE sequence for computing round
20281 : : from OP1 storing into OP0 using sse4 round insn. */
20282 : : void
20283 : 9 : ix86_expand_round_sse4 (rtx op0, rtx op1)
20284 : : {
20285 : 9 : machine_mode mode = GET_MODE (op0);
20286 : 9 : rtx e1, e2, res, half;
20287 : 9 : const struct real_format *fmt;
20288 : 9 : REAL_VALUE_TYPE pred_half, half_minus_pred_half;
20289 : 9 : rtx (*gen_copysign) (rtx, rtx, rtx);
20290 : 9 : rtx (*gen_round) (rtx, rtx, rtx);
20291 : :
20292 : 9 : switch (mode)
20293 : : {
20294 : : case E_HFmode:
20295 : : gen_copysign = gen_copysignhf3;
20296 : : gen_round = gen_sse4_1_roundhf2;
20297 : : break;
20298 : 4 : case E_SFmode:
20299 : 4 : gen_copysign = gen_copysignsf3;
20300 : 4 : gen_round = gen_sse4_1_roundsf2;
20301 : 4 : break;
20302 : 4 : case E_DFmode:
20303 : 4 : gen_copysign = gen_copysigndf3;
20304 : 4 : gen_round = gen_sse4_1_rounddf2;
20305 : 4 : break;
20306 : 0 : default:
20307 : 0 : gcc_unreachable ();
20308 : : }
20309 : :
20310 : : /* round (a) = trunc (a + copysign (0.5, a)) */
20311 : :
20312 : : /* load nextafter (0.5, 0.0) */
20313 : 9 : fmt = REAL_MODE_FORMAT (mode);
20314 : 9 : real_2expN (&half_minus_pred_half, -(fmt->p) - 1, mode);
20315 : 9 : real_arithmetic (&pred_half, MINUS_EXPR, &dconsthalf, &half_minus_pred_half);
20316 : 9 : half = const_double_from_real_value (pred_half, mode);
20317 : :
20318 : : /* e1 = copysign (0.5, op1) */
20319 : 9 : e1 = gen_reg_rtx (mode);
20320 : 9 : emit_insn (gen_copysign (e1, half, op1));
20321 : :
20322 : : /* e2 = op1 + e1 */
20323 : 9 : e2 = expand_simple_binop (mode, PLUS, op1, e1, NULL_RTX, 0, OPTAB_DIRECT);
20324 : :
20325 : : /* res = trunc (e2) */
20326 : 9 : res = gen_reg_rtx (mode);
20327 : 9 : emit_insn (gen_round (res, e2, GEN_INT (ROUND_TRUNC)));
20328 : :
20329 : 9 : emit_move_insn (op0, res);
20330 : 9 : }
20331 : :
20332 : : /* A cached (set (nil) (vselect (vconcat (nil) (nil)) (parallel [])))
20333 : : insn, so that expand_vselect{,_vconcat} doesn't have to create a fresh
20334 : : insn every time. */
20335 : :
20336 : : static GTY(()) rtx_insn *vselect_insn;
20337 : :
20338 : : /* Initialize vselect_insn. */
20339 : :
20340 : : static void
20341 : 6683 : init_vselect_insn (void)
20342 : : {
20343 : 6683 : unsigned i;
20344 : 6683 : rtx x;
20345 : :
20346 : 6683 : x = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (MAX_VECT_LEN));
20347 : 434395 : for (i = 0; i < MAX_VECT_LEN; ++i)
20348 : 427712 : XVECEXP (x, 0, i) = const0_rtx;
20349 : 6683 : x = gen_rtx_VEC_SELECT (V2DFmode, gen_rtx_VEC_CONCAT (V4DFmode, const0_rtx,
20350 : : const0_rtx), x);
20351 : 6683 : x = gen_rtx_SET (const0_rtx, x);
20352 : 6683 : start_sequence ();
20353 : 6683 : vselect_insn = emit_insn (x);
20354 : 6683 : end_sequence ();
20355 : 6683 : }
20356 : :
20357 : : /* Construct (set target (vec_select op0 (parallel perm))) and
20358 : : return true if that's a valid instruction in the active ISA. */
20359 : :
20360 : : static bool
20361 : 538910 : expand_vselect (rtx target, rtx op0, const unsigned char *perm,
20362 : : unsigned nelt, bool testing_p)
20363 : : {
20364 : 538910 : unsigned int i;
20365 : 538910 : rtx x, save_vconcat;
20366 : 538910 : int icode;
20367 : :
20368 : 538910 : if (vselect_insn == NULL_RTX)
20369 : 1582 : init_vselect_insn ();
20370 : :
20371 : 538910 : x = XEXP (SET_SRC (PATTERN (vselect_insn)), 1);
20372 : 538910 : PUT_NUM_ELEM (XVEC (x, 0), nelt);
20373 : 4220602 : for (i = 0; i < nelt; ++i)
20374 : 3681692 : XVECEXP (x, 0, i) = GEN_INT (perm[i]);
20375 : 538910 : save_vconcat = XEXP (SET_SRC (PATTERN (vselect_insn)), 0);
20376 : 538910 : XEXP (SET_SRC (PATTERN (vselect_insn)), 0) = op0;
20377 : 538910 : PUT_MODE (SET_SRC (PATTERN (vselect_insn)), GET_MODE (target));
20378 : 538910 : SET_DEST (PATTERN (vselect_insn)) = target;
20379 : 538910 : icode = recog_memoized (vselect_insn);
20380 : :
20381 : 538910 : if (icode >= 0 && !testing_p)
20382 : 68321 : emit_insn (copy_rtx (PATTERN (vselect_insn)));
20383 : :
20384 : 538910 : SET_DEST (PATTERN (vselect_insn)) = const0_rtx;
20385 : 538910 : XEXP (SET_SRC (PATTERN (vselect_insn)), 0) = save_vconcat;
20386 : 538910 : INSN_CODE (vselect_insn) = -1;
20387 : :
20388 : 538910 : return icode >= 0;
20389 : : }
20390 : :
20391 : : /* Similar, but generate a vec_concat from op0 and op1 as well. */
20392 : :
20393 : : static bool
20394 : 478608 : expand_vselect_vconcat (rtx target, rtx op0, rtx op1,
20395 : : const unsigned char *perm, unsigned nelt,
20396 : : bool testing_p)
20397 : : {
20398 : 478608 : machine_mode v2mode;
20399 : 478608 : rtx x;
20400 : 478608 : bool ok;
20401 : :
20402 : 478608 : if (vselect_insn == NULL_RTX)
20403 : 5101 : init_vselect_insn ();
20404 : :
20405 : 478608 : if (!GET_MODE_2XWIDER_MODE (GET_MODE (op0)).exists (&v2mode))
20406 : : return false;
20407 : 478608 : x = XEXP (SET_SRC (PATTERN (vselect_insn)), 0);
20408 : 478608 : PUT_MODE (x, v2mode);
20409 : 478608 : XEXP (x, 0) = op0;
20410 : 478608 : XEXP (x, 1) = op1;
20411 : 478608 : ok = expand_vselect (target, x, perm, nelt, testing_p);
20412 : 478608 : XEXP (x, 0) = const0_rtx;
20413 : 478608 : XEXP (x, 1) = const0_rtx;
20414 : 478608 : return ok;
20415 : : }
20416 : :
20417 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement D
20418 : : using movss or movsd. */
20419 : : static bool
20420 : 317175 : expand_vec_perm_movs (struct expand_vec_perm_d *d)
20421 : : {
20422 : 317175 : machine_mode vmode = d->vmode;
20423 : 317175 : unsigned i, nelt = d->nelt;
20424 : 317175 : rtx x;
20425 : :
20426 : 317175 : if (d->one_operand_p)
20427 : : return false;
20428 : :
20429 : 290124 : if (!(TARGET_SSE && (vmode == V4SFmode || vmode == V4SImode))
20430 : 137029 : && !(TARGET_MMX_WITH_SSE && (vmode == V2SFmode || vmode == V2SImode))
20431 : 83293 : && !(TARGET_SSE2 && (vmode == V2DFmode || vmode == V2DImode)))
20432 : : return false;
20433 : :
20434 : : /* Only the first element is changed. */
20435 : 214583 : if (d->perm[0] != nelt && d->perm[0] != 0)
20436 : : return false;
20437 : 155730 : for (i = 1; i < nelt; ++i)
20438 : 122763 : if (d->perm[i] != i + nelt - d->perm[0])
20439 : : return false;
20440 : :
20441 : 32967 : if (d->testing_p)
20442 : : return true;
20443 : :
20444 : 5123 : if (d->perm[0] == nelt)
20445 : 0 : x = gen_rtx_VEC_MERGE (vmode, d->op1, d->op0, GEN_INT (1));
20446 : : else
20447 : 5123 : x = gen_rtx_VEC_MERGE (vmode, d->op0, d->op1, GEN_INT (1));
20448 : :
20449 : 5123 : emit_insn (gen_rtx_SET (d->target, x));
20450 : :
20451 : 5123 : return true;
20452 : : }
20453 : :
20454 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement D
20455 : : using insertps. */
20456 : : static bool
20457 : 284208 : expand_vec_perm_insertps (struct expand_vec_perm_d *d)
20458 : : {
20459 : 284208 : machine_mode vmode = d->vmode;
20460 : 284208 : unsigned i, cnt_s, nelt = d->nelt;
20461 : 284208 : int cnt_d = -1;
20462 : 284208 : rtx src, dst;
20463 : :
20464 : 284208 : if (d->one_operand_p)
20465 : : return false;
20466 : :
20467 : 257157 : if (!(TARGET_SSE4_1
20468 : 37711 : && (vmode == V4SFmode || vmode == V4SImode
20469 : 27510 : || (TARGET_MMX_WITH_SSE
20470 : 19530 : && (vmode == V2SFmode || vmode == V2SImode)))))
20471 : : return false;
20472 : :
20473 : 51299 : for (i = 0; i < nelt; ++i)
20474 : : {
20475 : 48946 : if (d->perm[i] == i)
20476 : 9683 : continue;
20477 : 39263 : if (cnt_d != -1)
20478 : : {
20479 : : cnt_d = -1;
20480 : : break;
20481 : : }
20482 : 20808 : cnt_d = i;
20483 : : }
20484 : :
20485 : 20808 : if (cnt_d == -1)
20486 : : {
20487 : 41189 : for (i = 0; i < nelt; ++i)
20488 : : {
20489 : 39113 : if (d->perm[i] == i + nelt)
20490 : 4279 : continue;
20491 : 34834 : if (cnt_d != -1)
20492 : : return false;
20493 : 18455 : cnt_d = i;
20494 : : }
20495 : :
20496 : 2076 : if (cnt_d == -1)
20497 : : return false;
20498 : : }
20499 : :
20500 : 4429 : if (d->testing_p)
20501 : : return true;
20502 : :
20503 : 425 : gcc_assert (cnt_d != -1);
20504 : :
20505 : 425 : cnt_s = d->perm[cnt_d];
20506 : 425 : if (cnt_s < nelt)
20507 : : {
20508 : 195 : src = d->op0;
20509 : 195 : dst = d->op1;
20510 : : }
20511 : : else
20512 : : {
20513 : 230 : cnt_s -= nelt;
20514 : 230 : src = d->op1;
20515 : 230 : dst = d->op0;
20516 : : }
20517 : 425 : gcc_assert (cnt_s < nelt);
20518 : :
20519 : 425 : rtx x = gen_sse4_1_insertps (vmode, d->target, dst, src,
20520 : 425 : GEN_INT (cnt_s << 6 | cnt_d << 4));
20521 : 425 : emit_insn (x);
20522 : :
20523 : 425 : return true;
20524 : : }
20525 : :
20526 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement D
20527 : : in terms of blendp[sd] / pblendw / pblendvb / vpblendd. */
20528 : :
20529 : : static bool
20530 : 320736 : expand_vec_perm_blend (struct expand_vec_perm_d *d)
20531 : : {
20532 : 320736 : machine_mode mmode, vmode = d->vmode;
20533 : 320736 : unsigned i, nelt = d->nelt;
20534 : 320736 : unsigned HOST_WIDE_INT mask;
20535 : 320736 : rtx target, op0, op1, maskop, x;
20536 : 320736 : rtx rperm[32], vperm;
20537 : :
20538 : 320736 : if (d->one_operand_p)
20539 : : return false;
20540 : 6063 : if (TARGET_AVX512F && GET_MODE_SIZE (vmode) == 64
20541 : 294760 : && (TARGET_AVX512BW
20542 : 670 : || GET_MODE_UNIT_SIZE (vmode) >= 4))
20543 : : ;
20544 : 304070 : else if (TARGET_AVX2 && GET_MODE_SIZE (vmode) == 32)
20545 : : ;
20546 : 286283 : else if (TARGET_AVX && (vmode == V4DFmode || vmode == V8SFmode))
20547 : : ;
20548 : 279025 : else if (TARGET_SSE4_1
20549 : 310587 : && (GET_MODE_SIZE (vmode) == 16
20550 : 21840 : || (TARGET_MMX_WITH_SSE && GET_MODE_SIZE (vmode) == 8)
20551 : 2621 : || GET_MODE_SIZE (vmode) == 4))
20552 : : ;
20553 : : else
20554 : : return false;
20555 : :
20556 : : /* This is a blend, not a permute. Elements must stay in their
20557 : : respective lanes. */
20558 : 102060 : for (i = 0; i < nelt; ++i)
20559 : : {
20560 : 98499 : unsigned e = d->perm[i];
20561 : 98499 : if (!(e == i || e == i + nelt))
20562 : : return false;
20563 : : }
20564 : :
20565 : 3561 : if (d->testing_p)
20566 : : return true;
20567 : :
20568 : : /* ??? Without SSE4.1, we could implement this with and/andn/or. This
20569 : : decision should be extracted elsewhere, so that we only try that
20570 : : sequence once all budget==3 options have been tried. */
20571 : 2792 : target = d->target;
20572 : 2792 : op0 = d->op0;
20573 : 2792 : op1 = d->op1;
20574 : 2792 : mask = 0;
20575 : :
20576 : 2792 : switch (vmode)
20577 : : {
20578 : : case E_V8DFmode:
20579 : : case E_V16SFmode:
20580 : : case E_V4DFmode:
20581 : : case E_V8SFmode:
20582 : : case E_V2DFmode:
20583 : : case E_V4SFmode:
20584 : : case E_V2SFmode:
20585 : : case E_V2HImode:
20586 : : case E_V4HImode:
20587 : : case E_V8HImode:
20588 : : case E_V8SImode:
20589 : : case E_V32HImode:
20590 : : case E_V64QImode:
20591 : : case E_V16SImode:
20592 : : case E_V8DImode:
20593 : 9776 : for (i = 0; i < nelt; ++i)
20594 : 8448 : mask |= ((unsigned HOST_WIDE_INT) (d->perm[i] >= nelt)) << i;
20595 : : break;
20596 : :
20597 : : case E_V2DImode:
20598 : 18 : for (i = 0; i < 2; ++i)
20599 : 18 : mask |= (d->perm[i] >= 2 ? 15 : 0) << (i * 4);
20600 : 6 : vmode = V8HImode;
20601 : 6 : goto do_subreg;
20602 : :
20603 : : case E_V2SImode:
20604 : 30 : for (i = 0; i < 2; ++i)
20605 : 30 : mask |= (d->perm[i] >= 2 ? 3 : 0) << (i * 2);
20606 : 10 : vmode = V4HImode;
20607 : 10 : goto do_subreg;
20608 : :
20609 : 827 : case E_V4SImode:
20610 : 827 : if (TARGET_AVX2)
20611 : : {
20612 : : /* Use vpblendd instead of vpblendw. */
20613 : 130 : for (i = 0; i < nelt; ++i)
20614 : 104 : mask |= ((unsigned HOST_WIDE_INT) (d->perm[i] >= nelt)) << i;
20615 : : break;
20616 : : }
20617 : : else
20618 : : {
20619 : 4005 : for (i = 0; i < 4; ++i)
20620 : 5002 : mask |= (d->perm[i] >= 4 ? 3 : 0) << (i * 2);
20621 : 801 : vmode = V8HImode;
20622 : 801 : goto do_subreg;
20623 : : }
20624 : :
20625 : : case E_V16QImode:
20626 : : /* See if bytes move in pairs so we can use pblendw with
20627 : : an immediate argument, rather than pblendvb with a vector
20628 : : argument. */
20629 : 84 : for (i = 0; i < 16; i += 2)
20630 : 84 : if (d->perm[i] + 1 != d->perm[i + 1])
20631 : : {
20632 : 83 : use_pblendvb:
20633 : 3427 : for (i = 0; i < nelt; ++i)
20634 : 3152 : rperm[i] = (d->perm[i] < nelt ? const0_rtx : constm1_rtx);
20635 : :
20636 : 275 : finish_pblendvb:
20637 : 276 : vperm = gen_rtx_CONST_VECTOR (vmode, gen_rtvec_v (nelt, rperm));
20638 : 276 : vperm = force_reg (vmode, vperm);
20639 : :
20640 : 552 : if (GET_MODE_SIZE (vmode) == 4)
20641 : 120 : emit_insn (gen_mmx_pblendvb_v4qi (target, op0, op1, vperm));
20642 : 312 : else if (GET_MODE_SIZE (vmode) == 8)
20643 : 40 : emit_insn (gen_mmx_pblendvb_v8qi (target, op0, op1, vperm));
20644 : 232 : else if (GET_MODE_SIZE (vmode) == 16)
20645 : 83 : emit_insn (gen_sse4_1_pblendvb (target, op0, op1, vperm));
20646 : : else
20647 : 33 : emit_insn (gen_avx2_pblendvb (target, op0, op1, vperm));
20648 : 276 : if (target != d->target)
20649 : 1 : emit_move_insn (d->target, gen_lowpart (d->vmode, target));
20650 : 276 : return true;
20651 : : }
20652 : :
20653 : 0 : for (i = 0; i < 8; ++i)
20654 : 0 : mask |= (d->perm[i * 2] >= 16) << i;
20655 : : vmode = V8HImode;
20656 : : /* FALLTHRU */
20657 : :
20658 : 1130 : do_subreg:
20659 : 1130 : target = gen_reg_rtx (vmode);
20660 : 1130 : op0 = gen_lowpart (vmode, op0);
20661 : 1130 : op1 = gen_lowpart (vmode, op1);
20662 : 1130 : break;
20663 : :
20664 : : case E_V8QImode:
20665 : 40 : for (i = 0; i < 8; i += 2)
20666 : 40 : if (d->perm[i] + 1 != d->perm[i + 1])
20667 : 40 : goto use_pblendvb;
20668 : :
20669 : 0 : for (i = 0; i < 4; ++i)
20670 : 0 : mask |= (d->perm[i * 2] >= 8) << i;
20671 : 0 : vmode = V4HImode;
20672 : 0 : goto do_subreg;
20673 : :
20674 : : case E_V4QImode:
20675 : 120 : for (i = 0; i < 4; i += 2)
20676 : 120 : if (d->perm[i] + 1 != d->perm[i + 1])
20677 : 120 : goto use_pblendvb;
20678 : :
20679 : 0 : for (i = 0; i < 2; ++i)
20680 : 0 : mask |= (d->perm[i * 2] >= 4) << i;
20681 : 0 : vmode = V2HImode;
20682 : 0 : goto do_subreg;
20683 : :
20684 : : case E_V32QImode:
20685 : : /* See if bytes move in pairs. If not, vpblendvb must be used. */
20686 : 4928 : for (i = 0; i < 32; i += 2)
20687 : 4640 : if (d->perm[i] + 1 != d->perm[i + 1])
20688 : 32 : goto use_pblendvb;
20689 : : /* See if bytes move in quadruplets. If yes, vpblendd
20690 : : with immediate can be used. */
20691 : 2592 : for (i = 0; i < 32; i += 4)
20692 : 2304 : if (d->perm[i] + 2 != d->perm[i + 2])
20693 : : break;
20694 : 288 : if (i < 32)
20695 : : {
20696 : : /* See if bytes move the same in both lanes. If yes,
20697 : : vpblendw with immediate can be used. */
20698 : 0 : for (i = 0; i < 16; i += 2)
20699 : 0 : if (d->perm[i] + 16 != d->perm[i + 16])
20700 : 0 : goto use_pblendvb;
20701 : :
20702 : : /* Use vpblendw. */
20703 : 0 : for (i = 0; i < 16; ++i)
20704 : 0 : mask |= (d->perm[i * 2] >= 32) << i;
20705 : 0 : vmode = V16HImode;
20706 : 0 : goto do_subreg;
20707 : : }
20708 : :
20709 : : /* Use vpblendd. */
20710 : 2592 : for (i = 0; i < 8; ++i)
20711 : 2304 : mask |= (d->perm[i * 4] >= 32) << i;
20712 : 288 : vmode = V8SImode;
20713 : 288 : goto do_subreg;
20714 : :
20715 : : case E_V16HImode:
20716 : : /* See if words move in pairs. If yes, vpblendd can be used. */
20717 : 177 : for (i = 0; i < 16; i += 2)
20718 : 161 : if (d->perm[i] + 1 != d->perm[i + 1])
20719 : : break;
20720 : 49 : if (i < 16)
20721 : : {
20722 : : /* See if words move the same in both lanes. If not,
20723 : : vpblendvb must be used. */
20724 : 290 : for (i = 0; i < 8; i++)
20725 : 258 : if (d->perm[i] + 8 != d->perm[i + 8])
20726 : : {
20727 : : /* Use vpblendvb. */
20728 : 33 : for (i = 0; i < 32; ++i)
20729 : 32 : rperm[i] = (d->perm[i / 2] < 16 ? const0_rtx : constm1_rtx);
20730 : :
20731 : 1 : vmode = V32QImode;
20732 : 1 : nelt = 32;
20733 : 1 : target = gen_reg_rtx (vmode);
20734 : 1 : op0 = gen_lowpart (vmode, op0);
20735 : 1 : op1 = gen_lowpart (vmode, op1);
20736 : 1 : goto finish_pblendvb;
20737 : : }
20738 : :
20739 : : /* Use vpblendw. */
20740 : 544 : for (i = 0; i < 16; ++i)
20741 : 512 : mask |= (d->perm[i] >= 16) << i;
20742 : : break;
20743 : : }
20744 : :
20745 : : /* Use vpblendd. */
20746 : 144 : for (i = 0; i < 8; ++i)
20747 : 128 : mask |= (d->perm[i * 2] >= 16) << i;
20748 : 16 : vmode = V8SImode;
20749 : 16 : goto do_subreg;
20750 : :
20751 : : case E_V4DImode:
20752 : : /* Use vpblendd. */
20753 : 45 : for (i = 0; i < 4; ++i)
20754 : 54 : mask |= (d->perm[i] >= 4 ? 3 : 0) << (i * 2);
20755 : 9 : vmode = V8SImode;
20756 : 9 : goto do_subreg;
20757 : :
20758 : 0 : default:
20759 : 0 : gcc_unreachable ();
20760 : : }
20761 : :
20762 : 2516 : switch (vmode)
20763 : : {
20764 : : case E_V8DFmode:
20765 : : case E_V8DImode:
20766 : : mmode = QImode;
20767 : : break;
20768 : 5 : case E_V16SFmode:
20769 : 5 : case E_V16SImode:
20770 : 5 : mmode = HImode;
20771 : 5 : break;
20772 : 6 : case E_V32HImode:
20773 : 6 : mmode = SImode;
20774 : 6 : break;
20775 : 1 : case E_V64QImode:
20776 : 1 : mmode = DImode;
20777 : 1 : break;
20778 : : default:
20779 : : mmode = VOIDmode;
20780 : : }
20781 : :
20782 : : /* Canonicalize vec_merge. */
20783 : 2516 : if (swap_commutative_operands_p (op1, op0)
20784 : : /* Two operands have same precedence, then
20785 : : first bit of mask select first operand. */
20786 : 2516 : || (!swap_commutative_operands_p (op0, op1)
20787 : 2516 : && !(mask & 1)))
20788 : : {
20789 : 2509 : unsigned n_elts = GET_MODE_NUNITS (vmode);
20790 : 2509 : std::swap (op0, op1);
20791 : 2509 : unsigned HOST_WIDE_INT mask_all = HOST_WIDE_INT_1U;
20792 : 2509 : if (n_elts == HOST_BITS_PER_WIDE_INT)
20793 : : mask_all = -1;
20794 : : else
20795 : 2508 : mask_all = (HOST_WIDE_INT_1U << n_elts) - 1;
20796 : 2509 : mask = ~mask & mask_all;
20797 : : }
20798 : :
20799 : 2516 : if (mmode != VOIDmode)
20800 : 16 : maskop = force_reg (mmode, gen_int_mode (mask, mmode));
20801 : : else
20802 : 2500 : maskop = GEN_INT (mask);
20803 : :
20804 : : /* This matches five different patterns with the different modes. */
20805 : 2516 : x = gen_rtx_VEC_MERGE (vmode, op1, op0, maskop);
20806 : 2516 : x = gen_rtx_SET (target, x);
20807 : 2516 : emit_insn (x);
20808 : 2516 : if (target != d->target)
20809 : 1130 : emit_move_insn (d->target, gen_lowpart (d->vmode, target));
20810 : :
20811 : : return true;
20812 : : }
20813 : :
20814 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement D
20815 : : in terms of the variable form of vpermilps.
20816 : :
20817 : : Note that we will have already failed the immediate input vpermilps,
20818 : : which requires that the high and low part shuffle be identical; the
20819 : : variable form doesn't require that. */
20820 : :
20821 : : static bool
20822 : 139957 : expand_vec_perm_vpermil (struct expand_vec_perm_d *d)
20823 : : {
20824 : 139957 : rtx rperm[8], vperm;
20825 : 139957 : unsigned i;
20826 : :
20827 : 139957 : if (!TARGET_AVX || d->vmode != V8SFmode || !d->one_operand_p)
20828 : : return false;
20829 : :
20830 : : /* We can only permute within the 128-bit lane. */
20831 : 20166 : for (i = 0; i < 8; ++i)
20832 : : {
20833 : 19204 : unsigned e = d->perm[i];
20834 : 19204 : if (i < 4 ? e >= 4 : e < 4)
20835 : : return false;
20836 : : }
20837 : :
20838 : 962 : if (d->testing_p)
20839 : : return true;
20840 : :
20841 : 468 : for (i = 0; i < 8; ++i)
20842 : : {
20843 : 416 : unsigned e = d->perm[i];
20844 : :
20845 : : /* Within each 128-bit lane, the elements of op0 are numbered
20846 : : from 0 and the elements of op1 are numbered from 4. */
20847 : 416 : if (e >= 8 + 4)
20848 : 0 : e -= 8;
20849 : 416 : else if (e >= 4)
20850 : 208 : e -= 4;
20851 : :
20852 : 416 : rperm[i] = GEN_INT (e);
20853 : : }
20854 : :
20855 : 52 : vperm = gen_rtx_CONST_VECTOR (V8SImode, gen_rtvec_v (8, rperm));
20856 : 52 : vperm = force_reg (V8SImode, vperm);
20857 : 52 : emit_insn (gen_avx_vpermilvarv8sf3 (d->target, d->op0, vperm));
20858 : :
20859 : 52 : return true;
20860 : : }
20861 : :
20862 : : /* For V*[QHS]Imode permutations, check if the same permutation
20863 : : can't be performed in a 2x, 4x or 8x wider inner mode. */
20864 : :
20865 : : static bool
20866 : 162632 : canonicalize_vector_int_perm (const struct expand_vec_perm_d *d,
20867 : : struct expand_vec_perm_d *nd)
20868 : : {
20869 : 162632 : int i;
20870 : 162632 : machine_mode mode = VOIDmode;
20871 : :
20872 : 162632 : switch (d->vmode)
20873 : : {
20874 : : case E_V8QImode: mode = V4HImode; break;
20875 : 29617 : case E_V16QImode: mode = V8HImode; break;
20876 : 1418 : case E_V32QImode: mode = V16HImode; break;
20877 : 273 : case E_V64QImode: mode = V32HImode; break;
20878 : 11722 : case E_V4HImode: mode = V2SImode; break;
20879 : 20626 : case E_V8HImode: mode = V4SImode; break;
20880 : 984 : case E_V16HImode: mode = V8SImode; break;
20881 : 397 : case E_V32HImode: mode = V16SImode; break;
20882 : 43246 : case E_V4SImode: mode = V2DImode; break;
20883 : 1472 : case E_V8SImode: mode = V4DImode; break;
20884 : 61 : case E_V16SImode: mode = V8DImode; break;
20885 : : default: return false;
20886 : : }
20887 : 203319 : for (i = 0; i < d->nelt; i += 2)
20888 : 189249 : if ((d->perm[i] & 1) || d->perm[i + 1] != d->perm[i] + 1)
20889 : : return false;
20890 : 14070 : nd->vmode = mode;
20891 : 14070 : nd->nelt = d->nelt / 2;
20892 : 92396 : for (i = 0; i < nd->nelt; i++)
20893 : 78326 : nd->perm[i] = d->perm[2 * i] / 2;
20894 : 28140 : if (GET_MODE_INNER (mode) != DImode)
20895 : 12377 : canonicalize_vector_int_perm (nd, nd);
20896 : 14070 : if (nd != d)
20897 : : {
20898 : 8924 : nd->one_operand_p = d->one_operand_p;
20899 : 8924 : nd->testing_p = d->testing_p;
20900 : 8924 : if (d->op0 == d->op1)
20901 : 3000 : nd->op0 = nd->op1 = gen_lowpart (nd->vmode, d->op0);
20902 : : else
20903 : : {
20904 : 5924 : nd->op0 = gen_lowpart (nd->vmode, d->op0);
20905 : 5924 : nd->op1 = gen_lowpart (nd->vmode, d->op1);
20906 : : }
20907 : 8924 : if (d->testing_p)
20908 : 5692 : nd->target = gen_raw_REG (nd->vmode, LAST_VIRTUAL_REGISTER + 1);
20909 : : else
20910 : 3232 : nd->target = gen_reg_rtx (nd->vmode);
20911 : : }
20912 : : return true;
20913 : : }
20914 : :
20915 : : /* Return true if permutation D can be performed as VMODE permutation
20916 : : instead. */
20917 : :
20918 : : static bool
20919 : 6980 : valid_perm_using_mode_p (machine_mode vmode, struct expand_vec_perm_d *d)
20920 : : {
20921 : 6980 : unsigned int i, j, chunk;
20922 : :
20923 : 6980 : if (GET_MODE_CLASS (vmode) != MODE_VECTOR_INT
20924 : 6980 : || GET_MODE_CLASS (d->vmode) != MODE_VECTOR_INT
20925 : 17234 : || GET_MODE_SIZE (vmode) != GET_MODE_SIZE (d->vmode))
20926 : : return false;
20927 : :
20928 : 10254 : if (GET_MODE_NUNITS (vmode) >= d->nelt)
20929 : : return true;
20930 : :
20931 : 4865 : chunk = d->nelt / GET_MODE_NUNITS (vmode);
20932 : 6808 : for (i = 0; i < d->nelt; i += chunk)
20933 : 6565 : if (d->perm[i] & (chunk - 1))
20934 : : return false;
20935 : : else
20936 : 12443 : for (j = 1; j < chunk; ++j)
20937 : 10500 : if (d->perm[i] + j != d->perm[i + j])
20938 : : return false;
20939 : :
20940 : : return true;
20941 : : }
20942 : :
20943 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement D
20944 : : in terms of pshufb, vpperm, vpermq, vpermd, vpermps or vperm2i128. */
20945 : :
20946 : : static bool
20947 : 138995 : expand_vec_perm_pshufb (struct expand_vec_perm_d *d)
20948 : : {
20949 : 138995 : unsigned i, nelt, eltsz, mask;
20950 : 138995 : unsigned char perm[64];
20951 : 138995 : machine_mode vmode;
20952 : 138995 : struct expand_vec_perm_d nd;
20953 : 138995 : rtx rperm[64], vperm, target, op0, op1;
20954 : :
20955 : 138995 : nelt = d->nelt;
20956 : :
20957 : 138995 : if (!d->one_operand_p)
20958 : 226008 : switch (GET_MODE_SIZE (d->vmode))
20959 : : {
20960 : 6894 : case 4:
20961 : 6894 : if (!TARGET_XOP)
20962 : : return false;
20963 : : vmode = V4QImode;
20964 : : break;
20965 : :
20966 : 18653 : case 8:
20967 : 18653 : if (!TARGET_XOP)
20968 : : return false;
20969 : : vmode = V8QImode;
20970 : : break;
20971 : :
20972 : 76135 : case 16:
20973 : 76135 : if (!TARGET_XOP)
20974 : : return false;
20975 : : vmode = V16QImode;
20976 : : break;
20977 : :
20978 : 10368 : case 32:
20979 : 10368 : if (!TARGET_AVX2)
20980 : : return false;
20981 : :
20982 : 4304 : if (valid_perm_using_mode_p (V2TImode, d))
20983 : : {
20984 : 52 : if (d->testing_p)
20985 : : return true;
20986 : :
20987 : : /* Use vperm2i128 insn. The pattern uses
20988 : : V4DImode instead of V2TImode. */
20989 : 48 : target = d->target;
20990 : 48 : if (d->vmode != V4DImode)
20991 : 12 : target = gen_reg_rtx (V4DImode);
20992 : 48 : op0 = gen_lowpart (V4DImode, d->op0);
20993 : 48 : op1 = gen_lowpart (V4DImode, d->op1);
20994 : 48 : rperm[0]
20995 : 48 : = GEN_INT ((d->perm[0] / (nelt / 2))
20996 : : | ((d->perm[nelt / 2] / (nelt / 2)) * 16));
20997 : 48 : emit_insn (gen_avx2_permv2ti (target, op0, op1, rperm[0]));
20998 : 48 : if (target != d->target)
20999 : 12 : emit_move_insn (d->target, gen_lowpart (d->vmode, target));
21000 : 48 : return true;
21001 : : }
21002 : : /* FALLTHRU */
21003 : :
21004 : : default:
21005 : : return false;
21006 : : }
21007 : : else
21008 : 51982 : switch (GET_MODE_SIZE (d->vmode))
21009 : : {
21010 : 3239 : case 4:
21011 : 3239 : if (!TARGET_SSSE3)
21012 : : return false;
21013 : : vmode = V4QImode;
21014 : : break;
21015 : :
21016 : 2342 : case 8:
21017 : 2342 : if (!TARGET_SSSE3)
21018 : : return false;
21019 : : vmode = V8QImode;
21020 : : break;
21021 : :
21022 : 14316 : case 16:
21023 : 14316 : if (!TARGET_SSSE3)
21024 : : return false;
21025 : : vmode = V16QImode;
21026 : : break;
21027 : :
21028 : 5809 : case 32:
21029 : 5809 : if (!TARGET_AVX2)
21030 : : return false;
21031 : :
21032 : : /* V4DImode should be already handled through
21033 : : expand_vselect by vpermq instruction. */
21034 : 2507 : gcc_assert (d->vmode != V4DImode);
21035 : :
21036 : 2507 : vmode = V32QImode;
21037 : 2507 : if (d->vmode == V8SImode
21038 : 2140 : || d->vmode == V16HImode
21039 : 1924 : || d->vmode == V32QImode)
21040 : : {
21041 : : /* First see if vpermq can be used for
21042 : : V8SImode/V16HImode/V32QImode. */
21043 : 1351 : if (valid_perm_using_mode_p (V4DImode, d))
21044 : : {
21045 : 770 : for (i = 0; i < 4; i++)
21046 : 616 : perm[i] = (d->perm[i * nelt / 4] * 4 / nelt) & 3;
21047 : 154 : if (d->testing_p)
21048 : : return true;
21049 : 58 : target = gen_reg_rtx (V4DImode);
21050 : 58 : if (expand_vselect (target, gen_lowpart (V4DImode, d->op0),
21051 : : perm, 4, false))
21052 : : {
21053 : 116 : emit_move_insn (d->target,
21054 : 58 : gen_lowpart (d->vmode, target));
21055 : 58 : return true;
21056 : : }
21057 : : return false;
21058 : : }
21059 : :
21060 : : /* Next see if vpermd can be used. */
21061 : 1197 : if (valid_perm_using_mode_p (V8SImode, d))
21062 : : vmode = V8SImode;
21063 : : }
21064 : : /* Or if vpermps can be used. */
21065 : 1156 : else if (d->vmode == V8SFmode)
21066 : : vmode = V8SImode;
21067 : :
21068 : : if (vmode == V32QImode)
21069 : : {
21070 : : /* vpshufb only works intra lanes, it is not
21071 : : possible to shuffle bytes in between the lanes. */
21072 : 22039 : for (i = 0; i < nelt; ++i)
21073 : 21385 : if ((d->perm[i] ^ i) & (nelt / 2))
21074 : : return false;
21075 : : }
21076 : : break;
21077 : :
21078 : 285 : case 64:
21079 : 285 : if (!TARGET_AVX512BW)
21080 : : return false;
21081 : :
21082 : : /* If vpermq didn't work, vpshufb won't work either. */
21083 : 104 : if (d->vmode == V8DFmode || d->vmode == V8DImode)
21084 : : return false;
21085 : :
21086 : 75 : vmode = V64QImode;
21087 : 75 : if (d->vmode == V16SImode
21088 : 54 : || d->vmode == V32HImode
21089 : 18 : || d->vmode == V64QImode)
21090 : : {
21091 : : /* First see if vpermq can be used for
21092 : : V16SImode/V32HImode/V64QImode. */
21093 : 64 : if (valid_perm_using_mode_p (V8DImode, d))
21094 : : {
21095 : 0 : for (i = 0; i < 8; i++)
21096 : 0 : perm[i] = (d->perm[i * nelt / 8] * 8 / nelt) & 7;
21097 : 0 : if (d->testing_p)
21098 : : return true;
21099 : 0 : target = gen_reg_rtx (V8DImode);
21100 : 0 : if (expand_vselect (target, gen_lowpart (V8DImode, d->op0),
21101 : : perm, 8, false))
21102 : : {
21103 : 0 : emit_move_insn (d->target,
21104 : 0 : gen_lowpart (d->vmode, target));
21105 : 0 : return true;
21106 : : }
21107 : : return false;
21108 : : }
21109 : :
21110 : : /* Next see if vpermd can be used. */
21111 : 64 : if (valid_perm_using_mode_p (V16SImode, d))
21112 : : vmode = V16SImode;
21113 : : }
21114 : : /* Or if vpermps can be used. */
21115 : 11 : else if (d->vmode == V16SFmode)
21116 : : vmode = V16SImode;
21117 : :
21118 : : if (vmode == V64QImode)
21119 : : {
21120 : : /* vpshufb only works intra lanes, it is not
21121 : : possible to shuffle bytes in between the lanes. */
21122 : 226 : for (i = 0; i < nelt; ++i)
21123 : 226 : if ((d->perm[i] ^ i) & (3 * nelt / 4))
21124 : : return false;
21125 : : }
21126 : : break;
21127 : :
21128 : : default:
21129 : : return false;
21130 : : }
21131 : :
21132 : 11986 : if (d->testing_p)
21133 : : return true;
21134 : :
21135 : : /* Try to avoid variable permutation instruction. */
21136 : 9117 : if (canonicalize_vector_int_perm (d, &nd) && expand_vec_perm_1 (&nd))
21137 : : {
21138 : 1838 : emit_move_insn (d->target, gen_lowpart (d->vmode, nd.target));
21139 : 1838 : return true;
21140 : : }
21141 : :
21142 : 7279 : if (vmode == V8SImode)
21143 : 8253 : for (i = 0; i < 8; ++i)
21144 : 7336 : rperm[i] = GEN_INT ((d->perm[i * nelt / 8] * 8 / nelt) & 7);
21145 : 6362 : else if (vmode == V16SImode)
21146 : 544 : for (i = 0; i < 16; ++i)
21147 : 512 : rperm[i] = GEN_INT ((d->perm[i * nelt / 16] * 16 / nelt) & 15);
21148 : : else
21149 : : {
21150 : 6330 : eltsz = GET_MODE_UNIT_SIZE (d->vmode);
21151 : 6330 : if (!d->one_operand_p)
21152 : 3201 : mask = 2 * nelt - 1;
21153 : 3129 : else if (vmode == V64QImode)
21154 : 0 : mask = nelt / 4 - 1;
21155 : 3129 : else if (vmode == V32QImode)
21156 : 648 : mask = nelt / 2 - 1;
21157 : : else
21158 : 2481 : mask = nelt - 1;
21159 : :
21160 : 74002 : for (i = 0; i < nelt; ++i)
21161 : : {
21162 : 67672 : unsigned j, e = d->perm[i] & mask;
21163 : 177240 : for (j = 0; j < eltsz; ++j)
21164 : 109568 : rperm[i * eltsz + j] = GEN_INT (e * eltsz + j);
21165 : : }
21166 : : }
21167 : :
21168 : 7279 : machine_mode vpmode = vmode;
21169 : :
21170 : 7279 : nelt = GET_MODE_SIZE (vmode);
21171 : :
21172 : : /* Emulate narrow modes with V16QI instructions. */
21173 : 7279 : if (nelt < 16)
21174 : : {
21175 : 199 : rtx m128 = GEN_INT (-128);
21176 : :
21177 : : /* Remap elements from the second operand, as we have to
21178 : : account for inactive top elements from the first operand. */
21179 : 199 : if (!d->one_operand_p)
21180 : : {
21181 : 243 : for (i = 0; i < nelt; ++i)
21182 : : {
21183 : 216 : unsigned ival = UINTVAL (rperm[i]);
21184 : 216 : if (ival >= nelt)
21185 : 108 : rperm[i] = GEN_INT (ival + 16 - nelt);
21186 : : }
21187 : : }
21188 : :
21189 : : /* Fill inactive elements in the top positions with zeros. */
21190 : 2279 : for (i = nelt; i < 16; ++i)
21191 : 2080 : rperm[i] = m128;
21192 : :
21193 : : vpmode = V16QImode;
21194 : : }
21195 : :
21196 : 14558 : vperm = gen_rtx_CONST_VECTOR (vpmode,
21197 : 7279 : gen_rtvec_v (GET_MODE_NUNITS (vpmode), rperm));
21198 : 7279 : vperm = force_reg (vpmode, vperm);
21199 : :
21200 : 7279 : if (vmode == d->vmode)
21201 : 2821 : target = d->target;
21202 : : else
21203 : 4458 : target = gen_reg_rtx (vmode);
21204 : :
21205 : 7279 : op0 = gen_lowpart (vmode, d->op0);
21206 : :
21207 : 7279 : if (d->one_operand_p)
21208 : : {
21209 : 4078 : rtx (*gen) (rtx, rtx, rtx);
21210 : :
21211 : 4078 : if (vmode == V4QImode)
21212 : : gen = gen_mmx_pshufbv4qi3;
21213 : : else if (vmode == V8QImode)
21214 : : gen = gen_mmx_pshufbv8qi3;
21215 : : else if (vmode == V16QImode)
21216 : : gen = gen_ssse3_pshufbv16qi3;
21217 : : else if (vmode == V32QImode)
21218 : : gen = gen_avx2_pshufbv32qi3;
21219 : : else if (vmode == V64QImode)
21220 : : gen = gen_avx512bw_pshufbv64qi3;
21221 : : else if (vmode == V8SFmode)
21222 : : gen = gen_avx2_permvarv8sf;
21223 : : else if (vmode == V8SImode)
21224 : : gen = gen_avx2_permvarv8si;
21225 : : else if (vmode == V16SFmode)
21226 : : gen = gen_avx512f_permvarv16sf;
21227 : : else if (vmode == V16SImode)
21228 : : gen = gen_avx512f_permvarv16si;
21229 : : else
21230 : : gcc_unreachable ();
21231 : :
21232 : 4078 : emit_insn (gen (target, op0, vperm));
21233 : : }
21234 : : else
21235 : : {
21236 : 3201 : rtx (*gen) (rtx, rtx, rtx, rtx);
21237 : :
21238 : 3201 : op1 = gen_lowpart (vmode, d->op1);
21239 : :
21240 : 3201 : if (vmode == V4QImode)
21241 : : gen = gen_mmx_ppermv32;
21242 : : else if (vmode == V8QImode)
21243 : : gen = gen_mmx_ppermv64;
21244 : : else if (vmode == V16QImode)
21245 : : gen = gen_xop_pperm;
21246 : : else
21247 : 0 : gcc_unreachable ();
21248 : :
21249 : 3201 : emit_insn (gen (target, op0, op1, vperm));
21250 : : }
21251 : :
21252 : 7279 : if (target != d->target)
21253 : 4458 : emit_move_insn (d->target, gen_lowpart (d->vmode, target));
21254 : :
21255 : : return true;
21256 : : }
21257 : :
21258 : : /* Try to expand one-operand permutation with constant mask. */
21259 : :
21260 : : static bool
21261 : 126709 : ix86_expand_vec_one_operand_perm_avx512 (struct expand_vec_perm_d *d)
21262 : : {
21263 : 126709 : machine_mode mode = GET_MODE (d->op0);
21264 : 126709 : machine_mode maskmode = mode;
21265 : 253418 : unsigned inner_size = GET_MODE_SIZE (GET_MODE_INNER (mode));
21266 : 126709 : rtx (*gen) (rtx, rtx, rtx) = NULL;
21267 : 126709 : rtx target, op0, mask;
21268 : 126709 : rtx vec[64];
21269 : :
21270 : 126709 : if (!rtx_equal_p (d->op0, d->op1))
21271 : : return false;
21272 : :
21273 : 18098 : if (!TARGET_AVX512F)
21274 : : return false;
21275 : :
21276 : : /* Accept VNxHImode and VNxQImode now. */
21277 : 607 : if (!TARGET_AVX512VL && GET_MODE_SIZE (mode) < 64)
21278 : : return false;
21279 : :
21280 : : /* vpermw. */
21281 : 353 : if (!TARGET_AVX512BW && inner_size == 2)
21282 : : return false;
21283 : :
21284 : : /* vpermb. */
21285 : 219 : if (!TARGET_AVX512VBMI && inner_size == 1)
21286 : : return false;
21287 : :
21288 : 130 : switch (mode)
21289 : : {
21290 : : case E_V16SImode:
21291 : : gen = gen_avx512f_permvarv16si;
21292 : : break;
21293 : 4 : case E_V16SFmode:
21294 : 4 : gen = gen_avx512f_permvarv16sf;
21295 : 4 : maskmode = V16SImode;
21296 : 4 : break;
21297 : 0 : case E_V8DImode:
21298 : 0 : gen = gen_avx512f_permvarv8di;
21299 : 0 : break;
21300 : 29 : case E_V8DFmode:
21301 : 29 : gen = gen_avx512f_permvarv8df;
21302 : 29 : maskmode = V8DImode;
21303 : 29 : break;
21304 : 42 : case E_V32HImode:
21305 : 42 : gen = gen_avx512bw_permvarv32hi;
21306 : 42 : break;
21307 : 14 : case E_V16HImode:
21308 : 14 : gen = gen_avx512vl_permvarv16hi;
21309 : 14 : break;
21310 : 6 : case E_V8HImode:
21311 : 6 : gen = gen_avx512vl_permvarv8hi;
21312 : 6 : break;
21313 : 2 : case E_V64QImode:
21314 : 2 : gen = gen_avx512bw_permvarv64qi;
21315 : 2 : break;
21316 : 2 : case E_V32QImode:
21317 : 2 : gen = gen_avx512vl_permvarv32qi;
21318 : 2 : break;
21319 : 0 : case E_V16QImode:
21320 : 0 : gen = gen_avx512vl_permvarv16qi;
21321 : 0 : break;
21322 : :
21323 : : default:
21324 : : return false;
21325 : : }
21326 : :
21327 : 129 : if (d->testing_p)
21328 : : return true;
21329 : :
21330 : 120 : target = d->target;
21331 : 120 : op0 = d->op0;
21332 : 2560 : for (int i = 0; i < d->nelt; ++i)
21333 : 2440 : vec[i] = GEN_INT (d->perm[i]);
21334 : 120 : mask = gen_rtx_CONST_VECTOR (maskmode, gen_rtvec_v (d->nelt, vec));
21335 : 120 : emit_insn (gen (target, op0, force_reg (maskmode, mask)));
21336 : 120 : return true;
21337 : : }
21338 : :
21339 : : static bool expand_vec_perm_palignr (struct expand_vec_perm_d *d, bool);
21340 : :
21341 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to instantiate D
21342 : : in a single instruction. */
21343 : :
21344 : : static bool
21345 : 348190 : expand_vec_perm_1 (struct expand_vec_perm_d *d)
21346 : : {
21347 : 348190 : unsigned i, nelt = d->nelt;
21348 : 348190 : struct expand_vec_perm_d nd;
21349 : :
21350 : : /* Check plain VEC_SELECT first, because AVX has instructions that could
21351 : : match both SEL and SEL+CONCAT, but the plain SEL will allow a memory
21352 : : input where SEL+CONCAT may not. */
21353 : 348190 : if (d->one_operand_p)
21354 : : {
21355 : : int mask = nelt - 1;
21356 : : bool identity_perm = true;
21357 : : bool broadcast_perm = true;
21358 : :
21359 : 491816 : for (i = 0; i < nelt; i++)
21360 : : {
21361 : 434728 : nd.perm[i] = d->perm[i] & mask;
21362 : 434728 : if (nd.perm[i] != i)
21363 : 320532 : identity_perm = false;
21364 : 434728 : if (nd.perm[i])
21365 : 361575 : broadcast_perm = false;
21366 : : }
21367 : :
21368 : 57088 : if (identity_perm)
21369 : : {
21370 : 59 : if (!d->testing_p)
21371 : 5 : emit_move_insn (d->target, d->op0);
21372 : 59 : return true;
21373 : : }
21374 : 57029 : else if (broadcast_perm && TARGET_AVX2)
21375 : : {
21376 : : /* Use vpbroadcast{b,w,d}. */
21377 : 199 : rtx (*gen) (rtx, rtx) = NULL;
21378 : 199 : switch (d->vmode)
21379 : : {
21380 : 1 : case E_V64QImode:
21381 : 1 : if (TARGET_AVX512BW)
21382 : : gen = gen_avx512bw_vec_dupv64qi_1;
21383 : : break;
21384 : 4 : case E_V32QImode:
21385 : 4 : gen = gen_avx2_pbroadcastv32qi_1;
21386 : 4 : break;
21387 : 1 : case E_V32HImode:
21388 : 1 : if (TARGET_AVX512BW)
21389 : : gen = gen_avx512bw_vec_dupv32hi_1;
21390 : : break;
21391 : 4 : case E_V16HImode:
21392 : 4 : gen = gen_avx2_pbroadcastv16hi_1;
21393 : 4 : break;
21394 : 1 : case E_V16SImode:
21395 : 1 : if (TARGET_AVX512F)
21396 : : gen = gen_avx512f_vec_dupv16si_1;
21397 : : break;
21398 : 4 : case E_V8SImode:
21399 : 4 : gen = gen_avx2_pbroadcastv8si_1;
21400 : 4 : break;
21401 : 4 : case E_V16QImode:
21402 : 4 : gen = gen_avx2_pbroadcastv16qi;
21403 : 4 : break;
21404 : 4 : case E_V8HImode:
21405 : 4 : gen = gen_avx2_pbroadcastv8hi;
21406 : 4 : break;
21407 : 0 : case E_V16SFmode:
21408 : 0 : if (TARGET_AVX512F)
21409 : : gen = gen_avx512f_vec_dupv16sf_1;
21410 : : break;
21411 : : case E_V8SFmode:
21412 : : gen = gen_avx2_vec_dupv8sf_1;
21413 : : break;
21414 : 0 : case E_V8DFmode:
21415 : 0 : if (TARGET_AVX512F)
21416 : : gen = gen_avx512f_vec_dupv8df_1;
21417 : : break;
21418 : 0 : case E_V8DImode:
21419 : 0 : if (TARGET_AVX512F)
21420 : : gen = gen_avx512f_vec_dupv8di_1;
21421 : : break;
21422 : : /* For other modes prefer other shuffles this function creates. */
21423 : : default: break;
21424 : : }
21425 : 20 : if (gen != NULL)
21426 : : {
21427 : 23 : if (!d->testing_p)
21428 : 23 : emit_insn (gen (d->target, d->op0));
21429 : 23 : return true;
21430 : : }
21431 : : }
21432 : :
21433 : 57006 : if (expand_vselect (d->target, d->op0, nd.perm, nelt, d->testing_p))
21434 : : return true;
21435 : :
21436 : : /* There are plenty of patterns in sse.md that are written for
21437 : : SEL+CONCAT and are not replicated for a single op. Perhaps
21438 : : that should be changed, to avoid the nastiness here. */
21439 : :
21440 : : /* Recognize interleave style patterns, which means incrementing
21441 : : every other permutation operand. */
21442 : 212107 : for (i = 0; i < nelt; i += 2)
21443 : : {
21444 : 173861 : nd.perm[i] = d->perm[i] & mask;
21445 : 173861 : nd.perm[i + 1] = (d->perm[i + 1] & mask) + nelt;
21446 : : }
21447 : 38246 : if (expand_vselect_vconcat (d->target, d->op0, d->op0, nd.perm, nelt,
21448 : 38246 : d->testing_p))
21449 : : return true;
21450 : :
21451 : : /* Recognize shufps, which means adding {0, 0, nelt, nelt}. */
21452 : 32717 : if (nelt >= 4)
21453 : : {
21454 : 113470 : for (i = 0; i < nelt; i += 4)
21455 : : {
21456 : 80753 : nd.perm[i + 0] = d->perm[i + 0] & mask;
21457 : 80753 : nd.perm[i + 1] = d->perm[i + 1] & mask;
21458 : 80753 : nd.perm[i + 2] = (d->perm[i + 2] & mask) + nelt;
21459 : 80753 : nd.perm[i + 3] = (d->perm[i + 3] & mask) + nelt;
21460 : : }
21461 : :
21462 : 32717 : if (expand_vselect_vconcat (d->target, d->op0, d->op0, nd.perm, nelt,
21463 : 32717 : d->testing_p))
21464 : : return true;
21465 : : }
21466 : : }
21467 : :
21468 : : /* Try the SSE4.1 blend variable merge instructions. */
21469 : 318153 : if (expand_vec_perm_blend (d))
21470 : : return true;
21471 : :
21472 : : /* Try movss/movsd instructions. */
21473 : 317175 : if (expand_vec_perm_movs (d))
21474 : : return true;
21475 : :
21476 : : /* Try the SSE4.1 insertps instruction. */
21477 : 284208 : if (expand_vec_perm_insertps (d))
21478 : : return true;
21479 : :
21480 : : /* Try the fully general two operand permute. */
21481 : 279779 : if (expand_vselect_vconcat (d->target, d->op0, d->op1, d->perm, nelt,
21482 : 279779 : d->testing_p))
21483 : : return true;
21484 : :
21485 : : /* Recognize interleave style patterns with reversed operands. */
21486 : 139962 : if (!d->one_operand_p)
21487 : : {
21488 : 912357 : for (i = 0; i < nelt; ++i)
21489 : : {
21490 : 799348 : unsigned e = d->perm[i];
21491 : 799348 : if (e >= nelt)
21492 : 390949 : e -= nelt;
21493 : : else
21494 : 408399 : e += nelt;
21495 : 799348 : nd.perm[i] = e;
21496 : : }
21497 : :
21498 : 113009 : if (expand_vselect_vconcat (d->target, d->op1, d->op0, nd.perm, nelt,
21499 : 113009 : d->testing_p))
21500 : : return true;
21501 : : }
21502 : :
21503 : : /* Try one of the AVX vpermil variable permutations. */
21504 : 139957 : if (expand_vec_perm_vpermil (d))
21505 : : return true;
21506 : :
21507 : : /* Try the SSSE3 pshufb or XOP vpperm or AVX2 vperm2i128,
21508 : : vpshufb, vpermd, vpermps or vpermq variable permutation. */
21509 : 138995 : if (expand_vec_perm_pshufb (d))
21510 : : return true;
21511 : :
21512 : : /* Try the AVX2 vpalignr instruction. */
21513 : 126803 : if (expand_vec_perm_palignr (d, true))
21514 : : return true;
21515 : :
21516 : : /* Try the AVX512F vperm{w,b,s,d} instructions */
21517 : 126709 : if (ix86_expand_vec_one_operand_perm_avx512 (d))
21518 : : return true;
21519 : :
21520 : : /* Try the AVX512F vpermt2/vpermi2 instructions. */
21521 : 126580 : if (ix86_expand_vec_perm_vpermt2 (NULL_RTX, NULL_RTX, NULL_RTX, NULL_RTX, d))
21522 : : return true;
21523 : :
21524 : : /* See if we can get the same permutation in different vector integer
21525 : : mode. */
21526 : 125692 : if (canonicalize_vector_int_perm (d, &nd) && expand_vec_perm_1 (&nd))
21527 : : {
21528 : 6567 : if (!d->testing_p)
21529 : 1188 : emit_move_insn (d->target, gen_lowpart (d->vmode, nd.target));
21530 : 6567 : return true;
21531 : : }
21532 : : return false;
21533 : : }
21534 : :
21535 : : /* Canonicalize vec_perm index to make the first index
21536 : : always comes from the first vector. */
21537 : : static void
21538 : 8096 : ix86_vec_perm_index_canon (struct expand_vec_perm_d *d)
21539 : : {
21540 : 8096 : unsigned nelt = d->nelt;
21541 : 8096 : if (d->perm[0] < nelt)
21542 : : return;
21543 : :
21544 : 5 : for (unsigned i = 0; i != nelt; i++)
21545 : 4 : d->perm[i] = (d->perm[i] + nelt) % (2 * nelt);
21546 : :
21547 : 1 : std::swap (d->op0, d->op1);
21548 : 1 : return;
21549 : : }
21550 : :
21551 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement D
21552 : : in terms of a pair of shufps+ shufps/pshufd instructions. */
21553 : : static bool
21554 : 86068 : expand_vec_perm_shufps_shufps (struct expand_vec_perm_d *d)
21555 : : {
21556 : 86068 : unsigned char perm1[4];
21557 : 86068 : machine_mode vmode = d->vmode;
21558 : 86068 : bool ok;
21559 : 86068 : unsigned i, j, k, count = 0;
21560 : :
21561 : 86068 : if (d->one_operand_p
21562 : 81015 : || (vmode != V4SImode && vmode != V4SFmode))
21563 : : return false;
21564 : :
21565 : 36864 : if (d->testing_p)
21566 : : return true;
21567 : :
21568 : 8096 : ix86_vec_perm_index_canon (d);
21569 : 48576 : for (i = 0; i < 4; ++i)
21570 : 50703 : count += d->perm[i] > 3 ? 1 : 0;
21571 : :
21572 : 8096 : gcc_assert (count & 3);
21573 : :
21574 : 8096 : rtx tmp = gen_reg_rtx (vmode);
21575 : : /* 2 from op0 and 2 from op1. */
21576 : 8096 : if (count == 2)
21577 : : {
21578 : : unsigned char perm2[4];
21579 : 17905 : for (i = 0, j = 0, k = 2; i < 4; ++i)
21580 : 14324 : if (d->perm[i] & 4)
21581 : : {
21582 : 7162 : perm1[k++] = d->perm[i];
21583 : 7162 : perm2[i] = k - 1;
21584 : : }
21585 : : else
21586 : : {
21587 : 7162 : perm1[j++] = d->perm[i];
21588 : 7162 : perm2[i] = j - 1;
21589 : : }
21590 : :
21591 : : /* shufps. */
21592 : 7162 : ok = expand_vselect_vconcat (tmp, d->op0, d->op1,
21593 : 3581 : perm1, d->nelt, false);
21594 : 3581 : gcc_assert (ok);
21595 : 3581 : if (vmode == V4SImode && TARGET_SSE2)
21596 : : /* pshufd. */
21597 : 2036 : ok = expand_vselect (d->target, tmp,
21598 : 2036 : perm2, d->nelt, false);
21599 : : else
21600 : : {
21601 : : /* shufps. */
21602 : 1545 : perm2[2] += 4;
21603 : 1545 : perm2[3] += 4;
21604 : 1545 : ok = expand_vselect_vconcat (d->target, tmp, tmp,
21605 : 1545 : perm2, d->nelt, false);
21606 : : }
21607 : 3581 : gcc_assert (ok);
21608 : : }
21609 : : /* 3 from one op and 1 from another. */
21610 : : else
21611 : : {
21612 : 22575 : unsigned pair_idx = 8, lone_idx = 8, shift;
21613 : :
21614 : : /* Find the lone index. */
21615 : 22575 : for (i = 0; i < 4; ++i)
21616 : 18060 : if ((d->perm[i] > 3 && count == 1)
21617 : 14739 : || (d->perm[i] < 4 && count == 3))
21618 : 18060 : lone_idx = i;
21619 : :
21620 : : /* When lone_idx is not 0, it must from second op(count == 1). */
21621 : 5709 : gcc_assert (count == (lone_idx ? 1 : 3));
21622 : :
21623 : : /* Find the pair index that sits in the same half as the lone index. */
21624 : 4515 : shift = lone_idx & 2;
21625 : 4515 : pair_idx = 1 - lone_idx + 2 * shift;
21626 : :
21627 : : /* First permutate lone index and pair index into the same vector as
21628 : : [ lone, lone, pair, pair ]. */
21629 : 9030 : perm1[1] = perm1[0]
21630 : 4515 : = (count == 3) ? d->perm[lone_idx] : d->perm[lone_idx] - 4;
21631 : 9030 : perm1[3] = perm1[2]
21632 : 4515 : = (count == 3) ? d->perm[pair_idx] : d->perm[pair_idx] + 4;
21633 : :
21634 : : /* Alway put the vector contains lone indx at the first. */
21635 : 4515 : if (count == 1)
21636 : 3321 : std::swap (d->op0, d->op1);
21637 : :
21638 : : /* shufps. */
21639 : 9030 : ok = expand_vselect_vconcat (tmp, d->op0, d->op1,
21640 : 4515 : perm1, d->nelt, false);
21641 : 4515 : gcc_assert (ok);
21642 : :
21643 : : /* Refine lone and pair index to original order. */
21644 : 4515 : perm1[shift] = lone_idx << 1;
21645 : 4515 : perm1[shift + 1] = pair_idx << 1;
21646 : :
21647 : : /* Select the remaining 2 elements in another vector. */
21648 : 13545 : for (i = 2 - shift; i < 4 - shift; ++i)
21649 : 9030 : perm1[i] = lone_idx == 1 ? d->perm[i] + 4 : d->perm[i];
21650 : :
21651 : : /* Adjust to original selector. */
21652 : 4515 : if (lone_idx > 1)
21653 : 2237 : std::swap (tmp, d->op1);
21654 : :
21655 : : /* shufps. */
21656 : 9030 : ok = expand_vselect_vconcat (d->target, tmp, d->op1,
21657 : 4515 : perm1, d->nelt, false);
21658 : :
21659 : 4515 : gcc_assert (ok);
21660 : : }
21661 : :
21662 : : return true;
21663 : : }
21664 : :
21665 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement D
21666 : : in terms of a pair of pshuflw + pshufhw instructions. */
21667 : :
21668 : : static bool
21669 : 103759 : expand_vec_perm_pshuflw_pshufhw (struct expand_vec_perm_d *d)
21670 : : {
21671 : 103759 : unsigned char perm2[MAX_VECT_LEN];
21672 : 103759 : unsigned i;
21673 : 103759 : bool ok;
21674 : :
21675 : 103759 : if (d->vmode != V8HImode || !d->one_operand_p)
21676 : : return false;
21677 : :
21678 : : /* The two permutations only operate in 64-bit lanes. */
21679 : 14492 : for (i = 0; i < 4; ++i)
21680 : 11691 : if (d->perm[i] >= 4)
21681 : : return false;
21682 : 13949 : for (i = 4; i < 8; ++i)
21683 : 11162 : if (d->perm[i] < 4)
21684 : : return false;
21685 : :
21686 : 2787 : if (d->testing_p)
21687 : : return true;
21688 : :
21689 : : /* Emit the pshuflw. */
21690 : 134 : memcpy (perm2, d->perm, 4);
21691 : 670 : for (i = 4; i < 8; ++i)
21692 : 536 : perm2[i] = i;
21693 : 134 : ok = expand_vselect (d->target, d->op0, perm2, 8, d->testing_p);
21694 : 134 : gcc_assert (ok);
21695 : :
21696 : : /* Emit the pshufhw. */
21697 : 134 : memcpy (perm2 + 4, d->perm + 4, 4);
21698 : 670 : for (i = 0; i < 4; ++i)
21699 : 536 : perm2[i] = i;
21700 : 134 : ok = expand_vselect (d->target, d->target, perm2, 8, d->testing_p);
21701 : 134 : gcc_assert (ok);
21702 : :
21703 : : return true;
21704 : : }
21705 : :
21706 : : /* Try to permute 2 64-bit vectors by punpckldq + 128-bit vector shuffle. */
21707 : : static bool
21708 : 49204 : expand_vec_perm_punpckldq_pshuf (struct expand_vec_perm_d *d)
21709 : : {
21710 : 49204 : if (GET_MODE_BITSIZE (d->vmode) != 64
21711 : 15256 : || !TARGET_MMX_WITH_SSE
21712 : 64460 : || d->one_operand_p)
21713 : : return false;
21714 : :
21715 : 13961 : machine_mode widen_vmode;
21716 : 13961 : switch (d->vmode)
21717 : : {
21718 : : /* pshufd. */
21719 : : case E_V2SImode:
21720 : : widen_vmode = V4SImode;
21721 : : break;
21722 : :
21723 : : /* pshufd. */
21724 : 1151 : case E_V2SFmode:
21725 : 1151 : widen_vmode = V4SFmode;
21726 : 1151 : break;
21727 : :
21728 : 4892 : case E_V4HImode:
21729 : 4892 : widen_vmode = V8HImode;
21730 : : /* pshufb. */
21731 : 4892 : if (!TARGET_SSSE3)
21732 : : return false;
21733 : : break;
21734 : :
21735 : 5340 : case E_V8QImode:
21736 : : /* pshufb. */
21737 : 5340 : widen_vmode = V16QImode;
21738 : 5340 : if (!TARGET_SSSE3)
21739 : : return false;
21740 : : break;
21741 : :
21742 : : default:
21743 : : return false;
21744 : : }
21745 : :
21746 : 5776 : if (d->testing_p)
21747 : : return true;
21748 : :
21749 : 240 : struct expand_vec_perm_d dperm;
21750 : 240 : dperm.target = gen_reg_rtx (widen_vmode);
21751 : 240 : rtx op0 = gen_reg_rtx (widen_vmode);
21752 : 240 : emit_move_insn (op0, gen_rtx_VEC_CONCAT (widen_vmode, d->op0, d->op1));
21753 : 240 : dperm.op0 = op0;
21754 : 240 : dperm.op1 = op0;
21755 : 240 : dperm.vmode = widen_vmode;
21756 : 240 : unsigned nelt = GET_MODE_NUNITS (widen_vmode);
21757 : 240 : dperm.nelt = nelt;
21758 : 240 : dperm.one_operand_p = true;
21759 : 240 : dperm.testing_p = false;
21760 : :
21761 : 1590 : for (unsigned i = 0; i != nelt / 2; i++)
21762 : : {
21763 : 1350 : dperm.perm[i] = d->perm[i];
21764 : 1350 : dperm.perm[i + nelt / 2] = d->perm[i];
21765 : : }
21766 : :
21767 : 240 : gcc_assert (expand_vec_perm_1 (&dperm));
21768 : 240 : emit_move_insn (d->target, lowpart_subreg (d->vmode,
21769 : : dperm.target,
21770 : : dperm.vmode));
21771 : 240 : return true;
21772 : : }
21773 : :
21774 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to simplify
21775 : : the permutation using the SSSE3 palignr instruction. This succeeds
21776 : : when all of the elements in PERM fit within one vector and we merely
21777 : : need to shift them down so that a single vector permutation has a
21778 : : chance to succeed. If SINGLE_INSN_ONLY_P, succeed if only
21779 : : the vpalignr instruction itself can perform the requested permutation. */
21780 : :
21781 : : static bool
21782 : 227775 : expand_vec_perm_palignr (struct expand_vec_perm_d *d, bool single_insn_only_p)
21783 : : {
21784 : 227775 : unsigned i, nelt = d->nelt;
21785 : 227775 : unsigned min, max, minswap, maxswap;
21786 : 227775 : bool in_order, ok, swap = false;
21787 : 227775 : rtx shift, target;
21788 : 227775 : struct expand_vec_perm_d dcopy;
21789 : :
21790 : : /* Even with AVX, palignr only operates on 128-bit vectors,
21791 : : in AVX2 palignr operates on both 128-bit lanes. */
21792 : 123256 : if ((!TARGET_SSSE3 || GET_MODE_SIZE (d->vmode) != 16)
21793 : 273245 : && (!TARGET_AVX2 || GET_MODE_SIZE (d->vmode) != 32))
21794 : : return false;
21795 : :
21796 : 34849 : min = 2 * nelt;
21797 : 34849 : max = 0;
21798 : 34849 : minswap = 2 * nelt;
21799 : 34849 : maxswap = 0;
21800 : 254637 : for (i = 0; i < nelt; ++i)
21801 : : {
21802 : 219788 : unsigned e = d->perm[i];
21803 : 219788 : unsigned eswap = d->perm[i] ^ nelt;
21804 : 439576 : if (GET_MODE_SIZE (d->vmode) == 32)
21805 : : {
21806 : 85576 : e = (e & ((nelt / 2) - 1)) | ((e & nelt) >> 1);
21807 : 85576 : eswap = e ^ (nelt / 2);
21808 : : }
21809 : 219788 : if (e < min)
21810 : : min = e;
21811 : 219788 : if (e > max)
21812 : : max = e;
21813 : 219788 : if (eswap < minswap)
21814 : : minswap = eswap;
21815 : 219788 : if (eswap > maxswap)
21816 : : maxswap = eswap;
21817 : : }
21818 : 34849 : if (min == 0
21819 : 50502 : || max - min >= (GET_MODE_SIZE (d->vmode) == 32 ? nelt / 2 : nelt))
21820 : : {
21821 : 31661 : if (d->one_operand_p
21822 : 31395 : || minswap == 0
21823 : 67051 : || maxswap - minswap >= (GET_MODE_SIZE (d->vmode) == 32
21824 : 17695 : ? nelt / 2 : nelt))
21825 : : return false;
21826 : : swap = true;
21827 : : min = minswap;
21828 : 6382 : max = maxswap;
21829 : : }
21830 : :
21831 : : /* Given that we have SSSE3, we know we'll be able to implement the
21832 : : single operand permutation after the palignr with pshufb for
21833 : : 128-bit vectors. If SINGLE_INSN_ONLY_P, in_order has to be computed
21834 : : first. */
21835 : 6419 : if (d->testing_p && GET_MODE_SIZE (d->vmode) == 16 && !single_insn_only_p)
21836 : : return true;
21837 : :
21838 : 6382 : dcopy = *d;
21839 : 6382 : if (swap)
21840 : : {
21841 : 3194 : dcopy.op0 = d->op1;
21842 : 3194 : dcopy.op1 = d->op0;
21843 : 15970 : for (i = 0; i < nelt; ++i)
21844 : 12776 : dcopy.perm[i] ^= nelt;
21845 : : }
21846 : :
21847 : : in_order = true;
21848 : 32390 : for (i = 0; i < nelt; ++i)
21849 : : {
21850 : 26008 : unsigned e = dcopy.perm[i];
21851 : 26008 : if (GET_MODE_SIZE (d->vmode) == 32
21852 : 944 : && e >= nelt
21853 : 26206 : && (e & (nelt / 2 - 1)) < min)
21854 : 198 : e = e - min - (nelt / 2);
21855 : : else
21856 : 25810 : e = e - min;
21857 : 26008 : if (e != i)
21858 : 19378 : in_order = false;
21859 : 26008 : dcopy.perm[i] = e;
21860 : : }
21861 : 6382 : dcopy.one_operand_p = true;
21862 : :
21863 : 6382 : if (single_insn_only_p && !in_order)
21864 : : return false;
21865 : :
21866 : : /* For AVX2, test whether we can permute the result in one instruction. */
21867 : 3237 : if (d->testing_p)
21868 : : {
21869 : 37 : if (in_order)
21870 : : return true;
21871 : 0 : dcopy.op1 = dcopy.op0;
21872 : 0 : return expand_vec_perm_1 (&dcopy);
21873 : : }
21874 : :
21875 : 6400 : shift = GEN_INT (min * GET_MODE_UNIT_BITSIZE (d->vmode));
21876 : 6400 : if (GET_MODE_SIZE (d->vmode) == 16)
21877 : : {
21878 : 3141 : target = gen_reg_rtx (V1TImode);
21879 : 3141 : emit_insn (gen_ssse3_palignrv1ti (target,
21880 : 3141 : gen_lowpart (V1TImode, dcopy.op1),
21881 : 3141 : gen_lowpart (V1TImode, dcopy.op0),
21882 : : shift));
21883 : : }
21884 : : else
21885 : : {
21886 : 59 : target = gen_reg_rtx (V2TImode);
21887 : 59 : emit_insn (gen_avx2_palignrv2ti (target,
21888 : 59 : gen_lowpart (V2TImode, dcopy.op1),
21889 : 59 : gen_lowpart (V2TImode, dcopy.op0),
21890 : : shift));
21891 : : }
21892 : :
21893 : 3200 : dcopy.op0 = dcopy.op1 = gen_lowpart (d->vmode, target);
21894 : :
21895 : : /* Test for the degenerate case where the alignment by itself
21896 : : produces the desired permutation. */
21897 : 3200 : if (in_order)
21898 : : {
21899 : 57 : emit_move_insn (d->target, dcopy.op0);
21900 : 57 : return true;
21901 : : }
21902 : :
21903 : 3143 : ok = expand_vec_perm_1 (&dcopy);
21904 : 3155 : gcc_assert (ok || GET_MODE_SIZE (d->vmode) == 32);
21905 : :
21906 : : return ok;
21907 : : }
21908 : :
21909 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to simplify
21910 : : the permutation using the SSE4_1 pblendv instruction. Potentially
21911 : : reduces permutation from 2 pshufb and or to 1 pshufb and pblendv. */
21912 : :
21913 : : static bool
21914 : 91186 : expand_vec_perm_pblendv (struct expand_vec_perm_d *d)
21915 : : {
21916 : 91186 : unsigned i, which, nelt = d->nelt;
21917 : 91186 : struct expand_vec_perm_d dcopy, dcopy1;
21918 : 91186 : machine_mode vmode = d->vmode;
21919 : 91186 : bool ok;
21920 : :
21921 : : /* Use the same checks as in expand_vec_perm_blend. */
21922 : 91186 : if (d->one_operand_p)
21923 : : return false;
21924 : 90128 : if (TARGET_AVX2 && GET_MODE_SIZE (vmode) == 32)
21925 : : ;
21926 : 84062 : else if (TARGET_AVX && (vmode == V4DFmode || vmode == V8SFmode))
21927 : : ;
21928 : 79385 : else if (TARGET_SSE4_1
21929 : 89342 : && (GET_MODE_SIZE (vmode) == 16
21930 : 8046 : || (TARGET_MMX_WITH_SSE && GET_MODE_SIZE (vmode) == 8)
21931 : 2197 : || GET_MODE_SIZE (vmode) == 4))
21932 : : ;
21933 : : else
21934 : : return false;
21935 : :
21936 : : /* Figure out where permutation elements stay not in their
21937 : : respective lanes. */
21938 : 123764 : for (i = 0, which = 0; i < nelt; ++i)
21939 : : {
21940 : 107486 : unsigned e = d->perm[i];
21941 : 107486 : if (e != i)
21942 : 146890 : which |= (e < nelt ? 1 : 2);
21943 : : }
21944 : : /* We can pblend the part where elements stay not in their
21945 : : respective lanes only when these elements are all in one
21946 : : half of a permutation.
21947 : : {0 1 8 3 4 5 9 7} is ok as 8, 9 are at not at their respective
21948 : : lanes, but both 8 and 9 >= 8
21949 : : {0 1 8 3 4 5 2 7} is not ok as 2 and 8 are not at their
21950 : : respective lanes and 8 >= 8, but 2 not. */
21951 : 16278 : if (which != 1 && which != 2)
21952 : : return false;
21953 : 3316 : if (d->testing_p && GET_MODE_SIZE (vmode) == 16)
21954 : : return true;
21955 : :
21956 : : /* First we apply one operand permutation to the part where
21957 : : elements stay not in their respective lanes. */
21958 : 2024 : dcopy = *d;
21959 : 2024 : if (which == 2)
21960 : 2024 : dcopy.op0 = dcopy.op1 = d->op1;
21961 : : else
21962 : 0 : dcopy.op0 = dcopy.op1 = d->op0;
21963 : 2024 : if (!d->testing_p)
21964 : 732 : dcopy.target = gen_reg_rtx (vmode);
21965 : 2024 : dcopy.one_operand_p = true;
21966 : :
21967 : 16596 : for (i = 0; i < nelt; ++i)
21968 : 14572 : dcopy.perm[i] = d->perm[i] & (nelt - 1);
21969 : :
21970 : 2024 : ok = expand_vec_perm_1 (&dcopy);
21971 : 4048 : if (GET_MODE_SIZE (vmode) != 16 && !ok)
21972 : : return false;
21973 : : else
21974 : 1729 : gcc_assert (ok);
21975 : 1729 : if (d->testing_p)
21976 : : return true;
21977 : :
21978 : : /* Next we put permuted elements into their positions. */
21979 : 670 : dcopy1 = *d;
21980 : 670 : if (which == 2)
21981 : 670 : dcopy1.op1 = dcopy.target;
21982 : : else
21983 : 0 : dcopy1.op0 = dcopy.target;
21984 : :
21985 : 5706 : for (i = 0; i < nelt; ++i)
21986 : 5036 : dcopy1.perm[i] = ((d->perm[i] >= nelt) ? (nelt + i) : i);
21987 : :
21988 : 670 : ok = expand_vec_perm_blend (&dcopy1);
21989 : 670 : gcc_assert (ok);
21990 : :
21991 : : return true;
21992 : : }
21993 : :
21994 : : static bool expand_vec_perm_interleave3 (struct expand_vec_perm_d *d);
21995 : :
21996 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to simplify
21997 : : a two vector permutation into a single vector permutation by using
21998 : : an interleave operation to merge the vectors. */
21999 : :
22000 : : static bool
22001 : 97841 : expand_vec_perm_interleave2 (struct expand_vec_perm_d *d)
22002 : : {
22003 : 97841 : struct expand_vec_perm_d dremap, dfinal;
22004 : 97841 : unsigned i, nelt = d->nelt, nelt2 = nelt / 2;
22005 : 97841 : unsigned HOST_WIDE_INT contents;
22006 : 97841 : unsigned char remap[2 * MAX_VECT_LEN];
22007 : 97841 : rtx_insn *seq;
22008 : 97841 : bool ok, same_halves = false;
22009 : :
22010 : 97841 : if (GET_MODE_SIZE (d->vmode) == 4
22011 : 178932 : || GET_MODE_SIZE (d->vmode) == 8
22012 : 242527 : || GET_MODE_SIZE (d->vmode) == 16)
22013 : : {
22014 : 89781 : if (d->one_operand_p)
22015 : : return false;
22016 : : }
22017 : 16120 : else if (GET_MODE_SIZE (d->vmode) == 32)
22018 : : {
22019 : 7749 : if (!TARGET_AVX)
22020 : : return false;
22021 : : /* For 32-byte modes allow even d->one_operand_p.
22022 : : The lack of cross-lane shuffling in some instructions
22023 : : might prevent a single insn shuffle. */
22024 : 7749 : dfinal = *d;
22025 : 7749 : dfinal.testing_p = true;
22026 : : /* If expand_vec_perm_interleave3 can expand this into
22027 : : a 3 insn sequence, give up and let it be expanded as
22028 : : 3 insn sequence. While that is one insn longer,
22029 : : it doesn't need a memory operand and in the common
22030 : : case that both interleave low and high permutations
22031 : : with the same operands are adjacent needs 4 insns
22032 : : for both after CSE. */
22033 : 7749 : if (expand_vec_perm_interleave3 (&dfinal))
22034 : : return false;
22035 : : }
22036 : : else
22037 : : return false;
22038 : :
22039 : : /* Examine from whence the elements come. */
22040 : 92319 : contents = 0;
22041 : 697909 : for (i = 0; i < nelt; ++i)
22042 : 605590 : contents |= HOST_WIDE_INT_1U << d->perm[i];
22043 : :
22044 : 92319 : memset (remap, 0xff, sizeof (remap));
22045 : 92319 : dremap = *d;
22046 : :
22047 : 92319 : if (GET_MODE_SIZE (d->vmode) == 4
22048 : 177795 : || GET_MODE_SIZE (d->vmode) == 8)
22049 : : {
22050 : 22667 : unsigned HOST_WIDE_INT h1, h2, h3, h4;
22051 : :
22052 : : /* Split the two input vectors into 4 halves. */
22053 : 22667 : h1 = (HOST_WIDE_INT_1U << nelt2) - 1;
22054 : 22667 : h2 = h1 << nelt2;
22055 : 22667 : h3 = h2 << nelt2;
22056 : 22667 : h4 = h3 << nelt2;
22057 : :
22058 : : /* If the elements from the low halves use interleave low,
22059 : : and similarly for interleave high. */
22060 : 22667 : if ((contents & (h1 | h3)) == contents)
22061 : : {
22062 : : /* punpckl* */
22063 : 3235 : for (i = 0; i < nelt2; ++i)
22064 : : {
22065 : 2284 : remap[i] = i * 2;
22066 : 2284 : remap[i + nelt] = i * 2 + 1;
22067 : 2284 : dremap.perm[i * 2] = i;
22068 : 2284 : dremap.perm[i * 2 + 1] = i + nelt;
22069 : : }
22070 : : }
22071 : 21716 : else if ((contents & (h2 | h4)) == contents)
22072 : : {
22073 : : /* punpckh* */
22074 : 2836 : for (i = 0; i < nelt2; ++i)
22075 : : {
22076 : 2000 : remap[i + nelt2] = i * 2;
22077 : 2000 : remap[i + nelt + nelt2] = i * 2 + 1;
22078 : 2000 : dremap.perm[i * 2] = i + nelt2;
22079 : 2000 : dremap.perm[i * 2 + 1] = i + nelt + nelt2;
22080 : : }
22081 : : }
22082 : : else
22083 : : return false;
22084 : : }
22085 : 139304 : else if (GET_MODE_SIZE (d->vmode) == 16)
22086 : : {
22087 : 62121 : unsigned HOST_WIDE_INT h1, h2, h3, h4;
22088 : :
22089 : : /* Split the two input vectors into 4 halves. */
22090 : 62121 : h1 = (HOST_WIDE_INT_1U << nelt2) - 1;
22091 : 62121 : h2 = h1 << nelt2;
22092 : 62121 : h3 = h2 << nelt2;
22093 : 62121 : h4 = h3 << nelt2;
22094 : :
22095 : : /* If the elements from the low halves use interleave low, and similarly
22096 : : for interleave high. If the elements are from mis-matched halves, we
22097 : : can use shufps for V4SF/V4SI or do a DImode shuffle. */
22098 : 62121 : if ((contents & (h1 | h3)) == contents)
22099 : : {
22100 : : /* punpckl* */
22101 : 6118 : for (i = 0; i < nelt2; ++i)
22102 : : {
22103 : 4504 : remap[i] = i * 2;
22104 : 4504 : remap[i + nelt] = i * 2 + 1;
22105 : 4504 : dremap.perm[i * 2] = i;
22106 : 4504 : dremap.perm[i * 2 + 1] = i + nelt;
22107 : : }
22108 : 1614 : if (!TARGET_SSE2 && d->vmode == V4SImode)
22109 : 0 : dremap.vmode = V4SFmode;
22110 : : }
22111 : 60507 : else if ((contents & (h2 | h4)) == contents)
22112 : : {
22113 : : /* punpckh* */
22114 : 5376 : for (i = 0; i < nelt2; ++i)
22115 : : {
22116 : 3926 : remap[i + nelt2] = i * 2;
22117 : 3926 : remap[i + nelt + nelt2] = i * 2 + 1;
22118 : 3926 : dremap.perm[i * 2] = i + nelt2;
22119 : 3926 : dremap.perm[i * 2 + 1] = i + nelt + nelt2;
22120 : : }
22121 : 1450 : if (!TARGET_SSE2 && d->vmode == V4SImode)
22122 : 0 : dremap.vmode = V4SFmode;
22123 : : }
22124 : 59057 : else if ((contents & (h1 | h4)) == contents)
22125 : : {
22126 : : /* shufps */
22127 : 2639 : for (i = 0; i < nelt2; ++i)
22128 : : {
22129 : 1896 : remap[i] = i;
22130 : 1896 : remap[i + nelt + nelt2] = i + nelt2;
22131 : 1896 : dremap.perm[i] = i;
22132 : 1896 : dremap.perm[i + nelt2] = i + nelt + nelt2;
22133 : : }
22134 : 743 : if (nelt != 4)
22135 : : {
22136 : : /* shufpd */
22137 : 69 : dremap.vmode = V2DImode;
22138 : 69 : dremap.nelt = 2;
22139 : 69 : dremap.perm[0] = 0;
22140 : 69 : dremap.perm[1] = 3;
22141 : : }
22142 : : }
22143 : 58314 : else if ((contents & (h2 | h3)) == contents)
22144 : : {
22145 : : /* shufps */
22146 : 3687 : for (i = 0; i < nelt2; ++i)
22147 : : {
22148 : 2586 : remap[i + nelt2] = i;
22149 : 2586 : remap[i + nelt] = i + nelt2;
22150 : 2586 : dremap.perm[i] = i + nelt2;
22151 : 2586 : dremap.perm[i + nelt2] = i + nelt;
22152 : : }
22153 : 1101 : if (nelt != 4)
22154 : : {
22155 : : /* shufpd */
22156 : 64 : dremap.vmode = V2DImode;
22157 : 64 : dremap.nelt = 2;
22158 : 64 : dremap.perm[0] = 1;
22159 : 64 : dremap.perm[1] = 2;
22160 : : }
22161 : : }
22162 : : else
22163 : : return false;
22164 : : }
22165 : : else
22166 : : {
22167 : 7531 : unsigned int nelt4 = nelt / 4, nzcnt = 0;
22168 : 7531 : unsigned HOST_WIDE_INT q[8];
22169 : 7531 : unsigned int nonzero_halves[4];
22170 : :
22171 : : /* Split the two input vectors into 8 quarters. */
22172 : 7531 : q[0] = (HOST_WIDE_INT_1U << nelt4) - 1;
22173 : 60248 : for (i = 1; i < 8; ++i)
22174 : 52717 : q[i] = q[0] << (nelt4 * i);
22175 : 37655 : for (i = 0; i < 4; ++i)
22176 : 30124 : if (((q[2 * i] | q[2 * i + 1]) & contents) != 0)
22177 : : {
22178 : 27455 : nonzero_halves[nzcnt] = i;
22179 : 27455 : ++nzcnt;
22180 : : }
22181 : :
22182 : 7531 : if (nzcnt == 1)
22183 : : {
22184 : 212 : gcc_assert (d->one_operand_p);
22185 : 212 : nonzero_halves[1] = nonzero_halves[0];
22186 : 212 : same_halves = true;
22187 : : }
22188 : 7319 : else if (d->one_operand_p)
22189 : : {
22190 : 10 : gcc_assert (nonzero_halves[0] == 0);
22191 : 10 : gcc_assert (nonzero_halves[1] == 1);
22192 : : }
22193 : :
22194 : 7531 : if (nzcnt <= 2)
22195 : : {
22196 : 443 : if (d->perm[0] / nelt2 == nonzero_halves[1])
22197 : : {
22198 : : /* Attempt to increase the likelihood that dfinal
22199 : : shuffle will be intra-lane. */
22200 : 216 : std::swap (nonzero_halves[0], nonzero_halves[1]);
22201 : : }
22202 : :
22203 : : /* vperm2f128 or vperm2i128. */
22204 : 3175 : for (i = 0; i < nelt2; ++i)
22205 : : {
22206 : 2732 : remap[i + nonzero_halves[1] * nelt2] = i + nelt2;
22207 : 2732 : remap[i + nonzero_halves[0] * nelt2] = i;
22208 : 2732 : dremap.perm[i + nelt2] = i + nonzero_halves[1] * nelt2;
22209 : 2732 : dremap.perm[i] = i + nonzero_halves[0] * nelt2;
22210 : : }
22211 : :
22212 : 443 : if (d->vmode != V8SFmode
22213 : : && d->vmode != V4DFmode
22214 : : && d->vmode != V8SImode)
22215 : : {
22216 : 131 : dremap.vmode = V8SImode;
22217 : 131 : dremap.nelt = 8;
22218 : 655 : for (i = 0; i < 4; ++i)
22219 : : {
22220 : 524 : dremap.perm[i] = i + nonzero_halves[0] * 4;
22221 : 524 : dremap.perm[i + 4] = i + nonzero_halves[1] * 4;
22222 : : }
22223 : : }
22224 : : }
22225 : 7088 : else if (d->one_operand_p)
22226 : 6671 : return false;
22227 : 7088 : else if (TARGET_AVX2
22228 : 2431 : && (contents & (q[0] | q[2] | q[4] | q[6])) == contents)
22229 : : {
22230 : : /* vpunpckl* */
22231 : 443 : for (i = 0; i < nelt4; ++i)
22232 : : {
22233 : 223 : remap[i] = i * 2;
22234 : 223 : remap[i + nelt] = i * 2 + 1;
22235 : 223 : remap[i + nelt2] = i * 2 + nelt2;
22236 : 223 : remap[i + nelt + nelt2] = i * 2 + nelt2 + 1;
22237 : 223 : dremap.perm[i * 2] = i;
22238 : 223 : dremap.perm[i * 2 + 1] = i + nelt;
22239 : 223 : dremap.perm[i * 2 + nelt2] = i + nelt2;
22240 : 223 : dremap.perm[i * 2 + nelt2 + 1] = i + nelt + nelt2;
22241 : : }
22242 : : }
22243 : 6868 : else if (TARGET_AVX2
22244 : 2211 : && (contents & (q[1] | q[3] | q[5] | q[7])) == contents)
22245 : : {
22246 : : /* vpunpckh* */
22247 : 397 : for (i = 0; i < nelt4; ++i)
22248 : : {
22249 : 200 : remap[i + nelt4] = i * 2;
22250 : 200 : remap[i + nelt + nelt4] = i * 2 + 1;
22251 : 200 : remap[i + nelt2 + nelt4] = i * 2 + nelt2;
22252 : 200 : remap[i + nelt + nelt2 + nelt4] = i * 2 + nelt2 + 1;
22253 : 200 : dremap.perm[i * 2] = i + nelt4;
22254 : 200 : dremap.perm[i * 2 + 1] = i + nelt + nelt4;
22255 : 200 : dremap.perm[i * 2 + nelt2] = i + nelt2 + nelt4;
22256 : 200 : dremap.perm[i * 2 + nelt2 + 1] = i + nelt + nelt2 + nelt4;
22257 : : }
22258 : : }
22259 : : else
22260 : : return false;
22261 : : }
22262 : :
22263 : : /* Use the remapping array set up above to move the elements from their
22264 : : swizzled locations into their final destinations. */
22265 : 7555 : dfinal = *d;
22266 : 49103 : for (i = 0; i < nelt; ++i)
22267 : : {
22268 : 41548 : unsigned e = remap[d->perm[i]];
22269 : 41548 : gcc_assert (e < nelt);
22270 : : /* If same_halves is true, both halves of the remapped vector are the
22271 : : same. Avoid cross-lane accesses if possible. */
22272 : 41548 : if (same_halves && i >= nelt2)
22273 : : {
22274 : 764 : gcc_assert (e < nelt2);
22275 : 764 : dfinal.perm[i] = e + nelt2;
22276 : : }
22277 : : else
22278 : 40784 : dfinal.perm[i] = e;
22279 : : }
22280 : 7555 : if (!d->testing_p)
22281 : : {
22282 : 2633 : dremap.target = gen_reg_rtx (dremap.vmode);
22283 : 2633 : dfinal.op0 = gen_lowpart (dfinal.vmode, dremap.target);
22284 : : }
22285 : 7555 : dfinal.op1 = dfinal.op0;
22286 : 7555 : dfinal.one_operand_p = true;
22287 : :
22288 : : /* Test if the final remap can be done with a single insn. For V4SFmode or
22289 : : V4SImode this *will* succeed. For V8HImode or V16QImode it may not. */
22290 : 7555 : start_sequence ();
22291 : 7555 : ok = expand_vec_perm_1 (&dfinal);
22292 : 7555 : seq = end_sequence ();
22293 : :
22294 : 7555 : if (!ok)
22295 : : return false;
22296 : :
22297 : 6508 : if (d->testing_p)
22298 : : return true;
22299 : :
22300 : 2595 : if (dremap.vmode != dfinal.vmode)
22301 : : {
22302 : 53 : dremap.op0 = gen_lowpart (dremap.vmode, dremap.op0);
22303 : 53 : dremap.op1 = gen_lowpart (dremap.vmode, dremap.op1);
22304 : : }
22305 : :
22306 : 2595 : ok = expand_vec_perm_1 (&dremap);
22307 : 2595 : gcc_assert (ok);
22308 : :
22309 : 2595 : emit_insn (seq);
22310 : 2595 : return true;
22311 : : }
22312 : :
22313 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to simplify
22314 : : a single vector cross-lane permutation into vpermq followed
22315 : : by any of the single insn permutations. */
22316 : :
22317 : : static bool
22318 : 91233 : expand_vec_perm_vpermq_perm_1 (struct expand_vec_perm_d *d)
22319 : : {
22320 : 91233 : struct expand_vec_perm_d dremap, dfinal;
22321 : 91233 : unsigned i, j, nelt = d->nelt, nelt2 = nelt / 2, nelt4 = nelt / 4;
22322 : 91233 : unsigned contents[2];
22323 : 91233 : bool ok;
22324 : :
22325 : 91233 : if (!(TARGET_AVX2
22326 : 4175 : && (d->vmode == V32QImode || d->vmode == V16HImode)
22327 : 486 : && d->one_operand_p))
22328 : : return false;
22329 : :
22330 : 6 : contents[0] = 0;
22331 : 6 : contents[1] = 0;
22332 : 86 : for (i = 0; i < nelt2; ++i)
22333 : : {
22334 : 80 : contents[0] |= 1u << (d->perm[i] / nelt4);
22335 : 80 : contents[1] |= 1u << (d->perm[i + nelt2] / nelt4);
22336 : : }
22337 : :
22338 : 6 : for (i = 0; i < 2; ++i)
22339 : : {
22340 : : unsigned int cnt = 0;
22341 : 18 : for (j = 0; j < 4; ++j)
22342 : 18 : if ((contents[i] & (1u << j)) != 0 && ++cnt > 2)
22343 : : return false;
22344 : : }
22345 : :
22346 : 0 : if (d->testing_p)
22347 : : return true;
22348 : :
22349 : 0 : dremap = *d;
22350 : 0 : dremap.vmode = V4DImode;
22351 : 0 : dremap.nelt = 4;
22352 : 0 : dremap.target = gen_reg_rtx (V4DImode);
22353 : 0 : dremap.op0 = gen_lowpart (V4DImode, d->op0);
22354 : 0 : dremap.op1 = dremap.op0;
22355 : 0 : dremap.one_operand_p = true;
22356 : 0 : for (i = 0; i < 2; ++i)
22357 : : {
22358 : : unsigned int cnt = 0;
22359 : 0 : for (j = 0; j < 4; ++j)
22360 : 0 : if ((contents[i] & (1u << j)) != 0)
22361 : 0 : dremap.perm[2 * i + cnt++] = j;
22362 : 0 : for (; cnt < 2; ++cnt)
22363 : 0 : dremap.perm[2 * i + cnt] = 0;
22364 : : }
22365 : :
22366 : 0 : dfinal = *d;
22367 : 0 : dfinal.op0 = gen_lowpart (dfinal.vmode, dremap.target);
22368 : 0 : dfinal.op1 = dfinal.op0;
22369 : 0 : dfinal.one_operand_p = true;
22370 : 0 : for (i = 0, j = 0; i < nelt; ++i)
22371 : : {
22372 : 0 : if (i == nelt2)
22373 : 0 : j = 2;
22374 : 0 : dfinal.perm[i] = (d->perm[i] & (nelt4 - 1)) | (j ? nelt2 : 0);
22375 : 0 : if ((d->perm[i] / nelt4) == dremap.perm[j])
22376 : : ;
22377 : 0 : else if ((d->perm[i] / nelt4) == dremap.perm[j + 1])
22378 : 0 : dfinal.perm[i] |= nelt4;
22379 : : else
22380 : 0 : gcc_unreachable ();
22381 : : }
22382 : :
22383 : 0 : ok = expand_vec_perm_1 (&dremap);
22384 : 0 : gcc_assert (ok);
22385 : :
22386 : 0 : ok = expand_vec_perm_1 (&dfinal);
22387 : 0 : gcc_assert (ok);
22388 : :
22389 : : return true;
22390 : : }
22391 : :
22392 : : static bool canonicalize_perm (struct expand_vec_perm_d *d);
22393 : :
22394 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to expand
22395 : : a vector permutation using two instructions, vperm2f128 resp.
22396 : : vperm2i128 followed by any single in-lane permutation. */
22397 : :
22398 : : static bool
22399 : 91233 : expand_vec_perm_vperm2f128 (struct expand_vec_perm_d *d)
22400 : : {
22401 : 91233 : struct expand_vec_perm_d dfirst, dsecond;
22402 : 91233 : unsigned i, j, nelt = d->nelt, nelt2 = nelt / 2, perm;
22403 : 91233 : bool ok;
22404 : :
22405 : 91233 : if (!TARGET_AVX
22406 : 25340 : || GET_MODE_SIZE (d->vmode) != 32
22407 : 98304 : || (d->vmode != V8SFmode && d->vmode != V4DFmode && !TARGET_AVX2))
22408 : : return false;
22409 : :
22410 : 6801 : dsecond = *d;
22411 : 6801 : dsecond.one_operand_p = false;
22412 : 6801 : dsecond.testing_p = true;
22413 : :
22414 : : /* ((perm << 2)|perm) & 0x33 is the vperm2[fi]128
22415 : : immediate. For perm < 16 the second permutation uses
22416 : : d->op0 as first operand, for perm >= 16 it uses d->op1
22417 : : as first operand. The second operand is the result of
22418 : : vperm2[fi]128. */
22419 : 223705 : for (perm = 0; perm < 32; perm++)
22420 : : {
22421 : : /* Ignore permutations which do not move anything cross-lane. */
22422 : 216957 : if (perm < 16)
22423 : : {
22424 : : /* The second shuffle for e.g. V4DFmode has
22425 : : 0123 and ABCD operands.
22426 : : Ignore AB23, as 23 is already in the second lane
22427 : : of the first operand. */
22428 : 108660 : if ((perm & 0xc) == (1 << 2)) continue;
22429 : : /* And 01CD, as 01 is in the first lane of the first
22430 : : operand. */
22431 : 81480 : if ((perm & 3) == 0) continue;
22432 : : /* And 4567, as then the vperm2[fi]128 doesn't change
22433 : : anything on the original 4567 second operand. */
22434 : 61101 : if ((perm & 0xf) == ((3 << 2) | 2)) continue;
22435 : : }
22436 : : else
22437 : : {
22438 : : /* The second shuffle for e.g. V4DFmode has
22439 : : 4567 and ABCD operands.
22440 : : Ignore AB67, as 67 is already in the second lane
22441 : : of the first operand. */
22442 : 108297 : if ((perm & 0xc) == (3 << 2)) continue;
22443 : : /* And 45CD, as 45 is in the first lane of the first
22444 : : operand. */
22445 : 81305 : if ((perm & 3) == 2) continue;
22446 : : /* And 0123, as then the vperm2[fi]128 doesn't change
22447 : : anything on the original 0123 first operand. */
22448 : 60996 : if ((perm & 0xf) == (1 << 2)) continue;
22449 : : }
22450 : :
22451 : 307447 : for (i = 0; i < nelt; i++)
22452 : : {
22453 : 305550 : j = d->perm[i] / nelt2;
22454 : 565897 : if (j == ((perm >> (2 * (i >= nelt2))) & 3))
22455 : 73836 : dsecond.perm[i] = nelt + (i & nelt2) + (d->perm[i] & (nelt2 - 1));
22456 : 389143 : else if (j == (unsigned) (i >= nelt2) + 2 * (perm >= 16))
22457 : 125078 : dsecond.perm[i] = d->perm[i] & (nelt - 1);
22458 : : else
22459 : : break;
22460 : : }
22461 : :
22462 : 108533 : if (i == nelt)
22463 : : {
22464 : 1897 : start_sequence ();
22465 : 1897 : ok = expand_vec_perm_1 (&dsecond);
22466 : 1897 : end_sequence ();
22467 : : }
22468 : : else
22469 : : ok = false;
22470 : :
22471 : 1897 : if (ok)
22472 : : {
22473 : 47 : if (d->testing_p)
22474 : : return true;
22475 : :
22476 : : /* Found a usable second shuffle. dfirst will be
22477 : : vperm2f128 on d->op0 and d->op1. */
22478 : 33 : dsecond.testing_p = false;
22479 : 33 : dfirst = *d;
22480 : 33 : dfirst.target = gen_reg_rtx (d->vmode);
22481 : 169 : for (i = 0; i < nelt; i++)
22482 : 272 : dfirst.perm[i] = (i & (nelt2 - 1))
22483 : 204 : + ((perm >> (2 * (i >= nelt2))) & 3) * nelt2;
22484 : :
22485 : 33 : canonicalize_perm (&dfirst);
22486 : 33 : ok = expand_vec_perm_1 (&dfirst);
22487 : 33 : gcc_assert (ok);
22488 : :
22489 : : /* And dsecond is some single insn shuffle, taking
22490 : : d->op0 and result of vperm2f128 (if perm < 16) or
22491 : : d->op1 and result of vperm2f128 (otherwise). */
22492 : 33 : if (perm >= 16)
22493 : 33 : dsecond.op0 = dsecond.op1;
22494 : 33 : dsecond.op1 = dfirst.target;
22495 : :
22496 : 33 : ok = expand_vec_perm_1 (&dsecond);
22497 : 33 : gcc_assert (ok);
22498 : :
22499 : : return true;
22500 : : }
22501 : :
22502 : : /* For one operand, the only useful vperm2f128 permutation is 0x01
22503 : : aka lanes swap. */
22504 : 108486 : if (d->one_operand_p)
22505 : : return false;
22506 : : }
22507 : :
22508 : : return false;
22509 : : }
22510 : :
22511 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to simplify
22512 : : a two vector permutation using 2 intra-lane interleave insns
22513 : : and cross-lane shuffle for 32-byte vectors. */
22514 : :
22515 : : static bool
22516 : 34912 : expand_vec_perm_interleave3 (struct expand_vec_perm_d *d)
22517 : : {
22518 : 34912 : unsigned i, nelt;
22519 : 34912 : rtx (*gen) (rtx, rtx, rtx);
22520 : :
22521 : 34912 : if (d->one_operand_p)
22522 : : return false;
22523 : 33532 : if (TARGET_AVX2 && GET_MODE_SIZE (d->vmode) == 32)
22524 : : ;
22525 : 25990 : else if (TARGET_AVX && (d->vmode == V8SFmode || d->vmode == V4DFmode))
22526 : : ;
22527 : : else
22528 : : return false;
22529 : :
22530 : 10757 : nelt = d->nelt;
22531 : 10757 : if (d->perm[0] != 0 && d->perm[0] != nelt / 2)
22532 : : return false;
22533 : 10401 : for (i = 0; i < nelt; i += 2)
22534 : 10045 : if (d->perm[i] != d->perm[0] + i / 2
22535 : 9172 : || d->perm[i + 1] != d->perm[0] + i / 2 + nelt)
22536 : : return false;
22537 : :
22538 : 356 : if (d->testing_p)
22539 : : return true;
22540 : :
22541 : 56 : switch (d->vmode)
22542 : : {
22543 : 32 : case E_V32QImode:
22544 : 32 : if (d->perm[0])
22545 : : gen = gen_vec_interleave_highv32qi;
22546 : : else
22547 : 16 : gen = gen_vec_interleave_lowv32qi;
22548 : : break;
22549 : 18 : case E_V16HImode:
22550 : 18 : if (d->perm[0])
22551 : : gen = gen_vec_interleave_highv16hi;
22552 : : else
22553 : 9 : gen = gen_vec_interleave_lowv16hi;
22554 : : break;
22555 : 0 : case E_V8SImode:
22556 : 0 : if (d->perm[0])
22557 : : gen = gen_vec_interleave_highv8si;
22558 : : else
22559 : 0 : gen = gen_vec_interleave_lowv8si;
22560 : : break;
22561 : 4 : case E_V4DImode:
22562 : 4 : if (d->perm[0])
22563 : : gen = gen_vec_interleave_highv4di;
22564 : : else
22565 : 2 : gen = gen_vec_interleave_lowv4di;
22566 : : break;
22567 : 2 : case E_V8SFmode:
22568 : 2 : if (d->perm[0])
22569 : : gen = gen_vec_interleave_highv8sf;
22570 : : else
22571 : 1 : gen = gen_vec_interleave_lowv8sf;
22572 : : break;
22573 : 0 : case E_V4DFmode:
22574 : 0 : if (d->perm[0])
22575 : : gen = gen_vec_interleave_highv4df;
22576 : : else
22577 : 0 : gen = gen_vec_interleave_lowv4df;
22578 : : break;
22579 : 0 : default:
22580 : 0 : gcc_unreachable ();
22581 : : }
22582 : :
22583 : 56 : emit_insn (gen (d->target, d->op0, d->op1));
22584 : 56 : return true;
22585 : : }
22586 : :
22587 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement
22588 : : a single vector permutation using a single intra-lane vector
22589 : : permutation, vperm2f128 swapping the lanes and vblend* insn blending
22590 : : the non-swapped and swapped vectors together. */
22591 : :
22592 : : static bool
22593 : 27025 : expand_vec_perm_vperm2f128_vblend (struct expand_vec_perm_d *d)
22594 : : {
22595 : 27025 : struct expand_vec_perm_d dfirst, dsecond;
22596 : 27025 : unsigned i, j, msk, nelt = d->nelt, nelt2 = nelt / 2;
22597 : 27025 : rtx_insn *seq;
22598 : 27025 : bool ok;
22599 : 27025 : rtx (*blend) (rtx, rtx, rtx, rtx) = NULL;
22600 : :
22601 : 27025 : if (!TARGET_AVX
22602 : 3934 : || TARGET_AVX2
22603 : 2570 : || (d->vmode != V8SFmode && d->vmode != V4DFmode)
22604 : 2300 : || !d->one_operand_p)
22605 : : return false;
22606 : :
22607 : 0 : dfirst = *d;
22608 : 0 : for (i = 0; i < nelt; i++)
22609 : 0 : dfirst.perm[i] = 0xff;
22610 : 0 : for (i = 0, msk = 0; i < nelt; i++)
22611 : : {
22612 : 0 : j = (d->perm[i] & nelt2) ? i | nelt2 : i & ~nelt2;
22613 : 0 : if (dfirst.perm[j] != 0xff && dfirst.perm[j] != d->perm[i])
22614 : : return false;
22615 : 0 : dfirst.perm[j] = d->perm[i];
22616 : 0 : if (j != i)
22617 : 0 : msk |= (1 << i);
22618 : : }
22619 : 0 : for (i = 0; i < nelt; i++)
22620 : 0 : if (dfirst.perm[i] == 0xff)
22621 : 0 : dfirst.perm[i] = i;
22622 : :
22623 : 0 : if (!d->testing_p)
22624 : 0 : dfirst.target = gen_reg_rtx (dfirst.vmode);
22625 : :
22626 : 0 : start_sequence ();
22627 : 0 : ok = expand_vec_perm_1 (&dfirst);
22628 : 0 : seq = end_sequence ();
22629 : :
22630 : 0 : if (!ok)
22631 : : return false;
22632 : :
22633 : 0 : if (d->testing_p)
22634 : : return true;
22635 : :
22636 : 0 : emit_insn (seq);
22637 : :
22638 : 0 : dsecond = *d;
22639 : 0 : dsecond.op0 = dfirst.target;
22640 : 0 : dsecond.op1 = dfirst.target;
22641 : 0 : dsecond.one_operand_p = true;
22642 : 0 : dsecond.target = gen_reg_rtx (dsecond.vmode);
22643 : 0 : for (i = 0; i < nelt; i++)
22644 : 0 : dsecond.perm[i] = i ^ nelt2;
22645 : :
22646 : 0 : ok = expand_vec_perm_1 (&dsecond);
22647 : 0 : gcc_assert (ok);
22648 : :
22649 : 0 : blend = d->vmode == V8SFmode ? gen_avx_blendps256 : gen_avx_blendpd256;
22650 : 0 : emit_insn (blend (d->target, dfirst.target, dsecond.target, GEN_INT (msk)));
22651 : 0 : return true;
22652 : : }
22653 : :
22654 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement
22655 : : a two vector permutation using two single vector permutations and
22656 : : {,v}{,p}unpckl{ps,pd,bw,wd,dq}. If two_insn, succeed only if one
22657 : : of dfirst or dsecond is identity permutation. */
22658 : :
22659 : : static bool
22660 : 116482 : expand_vec_perm_2perm_interleave (struct expand_vec_perm_d *d, bool two_insn)
22661 : : {
22662 : 116482 : unsigned i, nelt = d->nelt, nelt2 = nelt / 2, lane = nelt;
22663 : 116482 : struct expand_vec_perm_d dfirst, dsecond, dfinal;
22664 : 116482 : bool ident1 = true, ident2 = true;
22665 : :
22666 : 116482 : if (d->one_operand_p)
22667 : : return false;
22668 : :
22669 : 212822 : if (GET_MODE_SIZE (d->vmode) == 16)
22670 : : {
22671 : 64831 : if (!TARGET_SSE)
22672 : : return false;
22673 : 64831 : if (d->vmode != V4SFmode && d->vmode != V2DFmode && !TARGET_SSE2)
22674 : : return false;
22675 : : }
22676 : 83160 : else if (GET_MODE_SIZE (d->vmode) == 32)
22677 : : {
22678 : 9877 : if (!TARGET_AVX)
22679 : : return false;
22680 : 9877 : if (d->vmode != V8SFmode && d->vmode != V4DFmode && !TARGET_AVX2)
22681 : : return false;
22682 : : lane = nelt2;
22683 : : }
22684 : : else
22685 : : return false;
22686 : :
22687 : 241504 : for (i = 1; i < nelt; i++)
22688 : 206538 : if ((d->perm[i] >= nelt) != ((d->perm[0] >= nelt) ^ (i & 1)))
22689 : : return false;
22690 : :
22691 : 34966 : dfirst = *d;
22692 : 34966 : dsecond = *d;
22693 : 34966 : dfinal = *d;
22694 : 34966 : dfirst.op1 = dfirst.op0;
22695 : 34966 : dfirst.one_operand_p = true;
22696 : 34966 : dsecond.op0 = dsecond.op1;
22697 : 34966 : dsecond.one_operand_p = true;
22698 : :
22699 : 227742 : for (i = 0; i < nelt; i++)
22700 : 192776 : if (d->perm[i] >= nelt)
22701 : : {
22702 : 96388 : dsecond.perm[i / 2 + (i >= lane ? lane / 2 : 0)] = d->perm[i] - nelt;
22703 : 96388 : if (d->perm[i] - nelt != i / 2 + (i >= lane ? lane / 2 : 0))
22704 : 87942 : ident2 = false;
22705 : 96388 : dsecond.perm[i / 2 + (i >= lane ? lane : lane / 2)]
22706 : 96388 : = d->perm[i] - nelt;
22707 : : }
22708 : : else
22709 : : {
22710 : 96388 : dfirst.perm[i / 2 + (i >= lane ? lane / 2 : 0)] = d->perm[i];
22711 : 96388 : if (d->perm[i] != i / 2 + (i >= lane ? lane / 2 : 0))
22712 : 79865 : ident1 = false;
22713 : 96388 : dfirst.perm[i / 2 + (i >= lane ? lane : lane / 2)] = d->perm[i];
22714 : : }
22715 : :
22716 : 34966 : if (two_insn && !ident1 && !ident2)
22717 : : return false;
22718 : :
22719 : 3955 : if (!d->testing_p)
22720 : : {
22721 : 214 : if (!ident1)
22722 : 144 : dfinal.op0 = dfirst.target = gen_reg_rtx (d->vmode);
22723 : 214 : if (!ident2)
22724 : 148 : dfinal.op1 = dsecond.target = gen_reg_rtx (d->vmode);
22725 : 214 : if (d->perm[0] >= nelt)
22726 : 0 : std::swap (dfinal.op0, dfinal.op1);
22727 : : }
22728 : :
22729 : 3955 : bool ok;
22730 : 3955 : rtx_insn *seq1 = NULL, *seq2 = NULL;
22731 : :
22732 : 3955 : if (!ident1)
22733 : : {
22734 : 2643 : start_sequence ();
22735 : 2643 : ok = expand_vec_perm_1 (&dfirst);
22736 : 2643 : seq1 = end_sequence ();
22737 : :
22738 : 2643 : if (!ok)
22739 : : return false;
22740 : : }
22741 : :
22742 : 2166 : if (!ident2)
22743 : : {
22744 : 2074 : start_sequence ();
22745 : 2074 : ok = expand_vec_perm_1 (&dsecond);
22746 : 2074 : seq2 = end_sequence ();
22747 : :
22748 : 2074 : if (!ok)
22749 : : return false;
22750 : : }
22751 : :
22752 : 600 : if (d->testing_p)
22753 : : return true;
22754 : :
22755 : 680 : for (i = 0; i < nelt; i++)
22756 : : {
22757 : 544 : dfinal.perm[i] = i / 2;
22758 : 544 : if (i >= lane)
22759 : 4 : dfinal.perm[i] += lane / 2;
22760 : 544 : if ((i & 1) != 0)
22761 : 272 : dfinal.perm[i] += nelt;
22762 : : }
22763 : 136 : emit_insn (seq1);
22764 : 136 : emit_insn (seq2);
22765 : 136 : ok = expand_vselect_vconcat (dfinal.target, dfinal.op0, dfinal.op1,
22766 : : dfinal.perm, dfinal.nelt, false);
22767 : 136 : gcc_assert (ok);
22768 : : return true;
22769 : : }
22770 : :
22771 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to simplify
22772 : : the permutation using two single vector permutations and the SSE4_1 pblendv
22773 : : instruction. If two_insn, succeed only if one of dfirst or dsecond is
22774 : : identity permutation. */
22775 : :
22776 : : static bool
22777 : 115882 : expand_vec_perm_2perm_pblendv (struct expand_vec_perm_d *d, bool two_insn)
22778 : : {
22779 : 115882 : unsigned i, nelt = d->nelt;
22780 : 115882 : struct expand_vec_perm_d dfirst, dsecond, dfinal;
22781 : 115882 : machine_mode vmode = d->vmode;
22782 : 115882 : bool ident1 = true, ident2 = true;
22783 : :
22784 : : /* Use the same checks as in expand_vec_perm_blend. */
22785 : 115882 : if (d->one_operand_p)
22786 : : return false;
22787 : 110207 : if (TARGET_AVX2 && GET_MODE_SIZE (vmode) == 32)
22788 : : ;
22789 : 103249 : else if (TARGET_AVX && (vmode == V4DFmode || vmode == V8SFmode))
22790 : : ;
22791 : 96680 : else if (TARGET_SSE4_1
22792 : 105987 : && (GET_MODE_SIZE (vmode) == 16
22793 : 7974 : || (TARGET_MMX_WITH_SSE && GET_MODE_SIZE (vmode) == 8)
22794 : 2229 : || GET_MODE_SIZE (vmode) == 4))
22795 : : ;
22796 : : else
22797 : : return false;
22798 : :
22799 : 17584 : dfirst = *d;
22800 : 17584 : dsecond = *d;
22801 : 17584 : dfinal = *d;
22802 : 17584 : dfirst.op1 = dfirst.op0;
22803 : 17584 : dfirst.one_operand_p = true;
22804 : 17584 : dsecond.op0 = dsecond.op1;
22805 : 17584 : dsecond.one_operand_p = true;
22806 : :
22807 : 145450 : for (i = 0; i < nelt; ++i)
22808 : 127866 : if (d->perm[i] >= nelt)
22809 : : {
22810 : 64032 : dfirst.perm[i] = 0xff;
22811 : 64032 : dsecond.perm[i] = d->perm[i] - nelt;
22812 : 64032 : if (d->perm[i] != i + nelt)
22813 : 127866 : ident2 = false;
22814 : : }
22815 : : else
22816 : : {
22817 : 63834 : dsecond.perm[i] = 0xff;
22818 : 63834 : dfirst.perm[i] = d->perm[i];
22819 : 63834 : if (d->perm[i] != i)
22820 : 127866 : ident1 = false;
22821 : : }
22822 : :
22823 : 17584 : if (two_insn && !ident1 && !ident2)
22824 : : return false;
22825 : :
22826 : : /* For now. Ideally treat 0xff as a wildcard. */
22827 : 60359 : for (i = 0; i < nelt; ++i)
22828 : 53832 : if (dfirst.perm[i] == 0xff)
22829 : : {
22830 : 27908 : if (GET_MODE_SIZE (vmode) == 32
22831 : 27908 : && dfirst.perm[i ^ (nelt / 2)] != 0xff)
22832 : 16404 : dfirst.perm[i] = dfirst.perm[i ^ (nelt / 2)] ^ (nelt / 2);
22833 : : else
22834 : 11504 : dfirst.perm[i] = i;
22835 : : }
22836 : : else
22837 : : {
22838 : 25924 : if (GET_MODE_SIZE (vmode) == 32
22839 : 25924 : && dsecond.perm[i ^ (nelt / 2)] != 0xff)
22840 : 14916 : dsecond.perm[i] = dsecond.perm[i ^ (nelt / 2)] ^ (nelt / 2);
22841 : : else
22842 : 11008 : dsecond.perm[i] = i;
22843 : : }
22844 : :
22845 : 6527 : if (!d->testing_p)
22846 : : {
22847 : 2255 : if (!ident1)
22848 : 2131 : dfinal.op0 = dfirst.target = gen_reg_rtx (d->vmode);
22849 : 2255 : if (!ident2)
22850 : 1019 : dfinal.op1 = dsecond.target = gen_reg_rtx (d->vmode);
22851 : : }
22852 : :
22853 : 6527 : bool ok;
22854 : 6527 : rtx_insn *seq1 = NULL, *seq2 = NULL;
22855 : :
22856 : 6527 : if (!ident1)
22857 : : {
22858 : 5938 : start_sequence ();
22859 : 5938 : ok = expand_vec_perm_1 (&dfirst);
22860 : 5938 : seq1 = end_sequence ();
22861 : :
22862 : 5938 : if (!ok)
22863 : : return false;
22864 : : }
22865 : :
22866 : 4446 : if (!ident2)
22867 : : {
22868 : 1417 : start_sequence ();
22869 : 1417 : ok = expand_vec_perm_1 (&dsecond);
22870 : 1417 : seq2 = end_sequence ();
22871 : :
22872 : 1417 : if (!ok)
22873 : : return false;
22874 : : }
22875 : :
22876 : 3857 : if (d->testing_p)
22877 : : return true;
22878 : :
22879 : 20673 : for (i = 0; i < nelt; ++i)
22880 : 18760 : dfinal.perm[i] = (d->perm[i] >= nelt ? i + nelt : i);
22881 : :
22882 : 1913 : emit_insn (seq1);
22883 : 1913 : emit_insn (seq2);
22884 : 1913 : ok = expand_vec_perm_blend (&dfinal);
22885 : 1913 : gcc_assert (ok);
22886 : : return true;
22887 : : }
22888 : :
22889 : : /* A subroutine of ix86_expand_vec_perm_const_1.
22890 : : Implement a permutation with psrlw, psllw and por.
22891 : : It handles case:
22892 : : __builtin_shufflevector (v,v,1,0,3,2,5,4,7,6,9,8,11,10,13,12,15,14);
22893 : : __builtin_shufflevector (v,v,1,0,3,2,5,4,7,6); */
22894 : :
22895 : : static bool
22896 : 25957 : expand_vec_perm_psrlw_psllw_por (struct expand_vec_perm_d *d)
22897 : : {
22898 : 25957 : unsigned i;
22899 : 25957 : rtx (*gen_shr) (rtx, rtx, rtx);
22900 : 25957 : rtx (*gen_shl) (rtx, rtx, rtx);
22901 : 25957 : rtx (*gen_or) (rtx, rtx, rtx);
22902 : 25957 : machine_mode mode = VOIDmode;
22903 : :
22904 : 25957 : if (!TARGET_SSE2 || !d->one_operand_p)
22905 : : return false;
22906 : :
22907 : 5018 : switch (d->vmode)
22908 : : {
22909 : 1295 : case E_V8QImode:
22910 : 1295 : if (!TARGET_MMX_WITH_SSE)
22911 : : return false;
22912 : : mode = V4HImode;
22913 : : gen_shr = gen_lshrv4hi3;
22914 : : gen_shl = gen_ashlv4hi3;
22915 : : gen_or = gen_iorv4hi3;
22916 : : break;
22917 : : case E_V16QImode:
22918 : : mode = V8HImode;
22919 : : gen_shr = gen_lshrv8hi3;
22920 : : gen_shl = gen_ashlv8hi3;
22921 : : gen_or = gen_iorv8hi3;
22922 : : break;
22923 : : default: return false;
22924 : : }
22925 : :
22926 : 3023 : if (!rtx_equal_p (d->op0, d->op1))
22927 : : return false;
22928 : :
22929 : 12463 : for (i = 0; i < d->nelt; i += 2)
22930 : 10965 : if (d->perm[i] != i + 1 || d->perm[i + 1] != i)
22931 : : return false;
22932 : :
22933 : 1498 : if (d->testing_p)
22934 : : return true;
22935 : :
22936 : 26 : rtx tmp1 = gen_reg_rtx (mode);
22937 : 26 : rtx tmp2 = gen_reg_rtx (mode);
22938 : 26 : rtx op0 = force_reg (d->vmode, d->op0);
22939 : :
22940 : 26 : emit_move_insn (tmp1, lowpart_subreg (mode, op0, d->vmode));
22941 : 26 : emit_move_insn (tmp2, lowpart_subreg (mode, op0, d->vmode));
22942 : 26 : emit_insn (gen_shr (tmp1, tmp1, GEN_INT (8)));
22943 : 26 : emit_insn (gen_shl (tmp2, tmp2, GEN_INT (8)));
22944 : 26 : emit_insn (gen_or (tmp1, tmp1, tmp2));
22945 : 26 : emit_move_insn (d->target, lowpart_subreg (d->vmode, tmp1, mode));
22946 : :
22947 : 26 : return true;
22948 : : }
22949 : :
22950 : : /* A subroutine of ix86_expand_vec_perm_const_1. Implement a V4DF
22951 : : permutation using two vperm2f128, followed by a vshufpd insn blending
22952 : : the two vectors together. */
22953 : :
22954 : : static bool
22955 : 29720 : expand_vec_perm_2vperm2f128_vshuf (struct expand_vec_perm_d *d)
22956 : : {
22957 : 29720 : struct expand_vec_perm_d dfirst, dsecond, dthird;
22958 : 29720 : bool ok;
22959 : :
22960 : 29720 : if (!TARGET_AVX || (d->vmode != V4DFmode))
22961 : : return false;
22962 : :
22963 : 1657 : if (d->testing_p)
22964 : : return true;
22965 : :
22966 : 206 : dfirst = *d;
22967 : 206 : dsecond = *d;
22968 : 206 : dthird = *d;
22969 : :
22970 : 206 : dfirst.perm[0] = (d->perm[0] & ~1);
22971 : 206 : dfirst.perm[1] = (d->perm[0] & ~1) + 1;
22972 : 206 : dfirst.perm[2] = (d->perm[2] & ~1);
22973 : 206 : dfirst.perm[3] = (d->perm[2] & ~1) + 1;
22974 : 206 : dsecond.perm[0] = (d->perm[1] & ~1);
22975 : 206 : dsecond.perm[1] = (d->perm[1] & ~1) + 1;
22976 : 206 : dsecond.perm[2] = (d->perm[3] & ~1);
22977 : 206 : dsecond.perm[3] = (d->perm[3] & ~1) + 1;
22978 : 206 : dthird.perm[0] = (d->perm[0] % 2);
22979 : 206 : dthird.perm[1] = (d->perm[1] % 2) + 4;
22980 : 206 : dthird.perm[2] = (d->perm[2] % 2) + 2;
22981 : 206 : dthird.perm[3] = (d->perm[3] % 2) + 6;
22982 : :
22983 : 206 : dfirst.target = gen_reg_rtx (dfirst.vmode);
22984 : 206 : dsecond.target = gen_reg_rtx (dsecond.vmode);
22985 : 206 : dthird.op0 = dfirst.target;
22986 : 206 : dthird.op1 = dsecond.target;
22987 : 206 : dthird.one_operand_p = false;
22988 : :
22989 : 206 : canonicalize_perm (&dfirst);
22990 : 206 : canonicalize_perm (&dsecond);
22991 : :
22992 : 206 : ok = expand_vec_perm_1 (&dfirst)
22993 : 206 : && expand_vec_perm_1 (&dsecond)
22994 : 412 : && expand_vec_perm_1 (&dthird);
22995 : :
22996 : 0 : gcc_assert (ok);
22997 : :
22998 : : return true;
22999 : : }
23000 : :
23001 : : static bool ix86_expand_vec_perm_const_1 (struct expand_vec_perm_d *);
23002 : :
23003 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement
23004 : : a two vector permutation using two intra-lane vector
23005 : : permutations, vperm2f128 swapping the lanes and vblend* insn blending
23006 : : the non-swapped and swapped vectors together. */
23007 : :
23008 : : static bool
23009 : 15446 : expand_vec_perm2_vperm2f128_vblend (struct expand_vec_perm_d *d)
23010 : : {
23011 : 15446 : struct expand_vec_perm_d dfirst, dsecond, dthird;
23012 : 15446 : unsigned i, j, msk, nelt = d->nelt, nelt2 = nelt / 2, which1 = 0, which2 = 0;
23013 : 15446 : rtx_insn *seq1, *seq2;
23014 : 15446 : bool ok;
23015 : 15446 : rtx (*blend) (rtx, rtx, rtx, rtx) = NULL;
23016 : :
23017 : 15446 : if (!TARGET_AVX
23018 : 1041 : || TARGET_AVX2
23019 : 774 : || (d->vmode != V8SFmode && d->vmode != V4DFmode)
23020 : 627 : || d->one_operand_p)
23021 : : return false;
23022 : :
23023 : 627 : dfirst = *d;
23024 : 627 : dsecond = *d;
23025 : 5643 : for (i = 0; i < nelt; i++)
23026 : : {
23027 : 5016 : dfirst.perm[i] = 0xff;
23028 : 5016 : dsecond.perm[i] = 0xff;
23029 : : }
23030 : 5643 : for (i = 0, msk = 0; i < nelt; i++)
23031 : : {
23032 : 5016 : j = (d->perm[i] & nelt2) ? i | nelt2 : i & ~nelt2;
23033 : 5016 : if (j == i)
23034 : : {
23035 : 3586 : dfirst.perm[j] = d->perm[i];
23036 : 6050 : which1 |= (d->perm[i] < nelt ? 1 : 2);
23037 : : }
23038 : : else
23039 : : {
23040 : 1430 : dsecond.perm[j] = d->perm[i];
23041 : 1430 : which2 |= (d->perm[i] < nelt ? 1 : 2);
23042 : 1430 : msk |= (1U << i);
23043 : : }
23044 : : }
23045 : 627 : if (msk == 0 || msk == (1U << nelt) - 1)
23046 : : return false;
23047 : :
23048 : 627 : if (!d->testing_p)
23049 : : {
23050 : 40 : dfirst.target = gen_reg_rtx (dfirst.vmode);
23051 : 40 : dsecond.target = gen_reg_rtx (dsecond.vmode);
23052 : : }
23053 : :
23054 : 5643 : for (i = 0; i < nelt; i++)
23055 : : {
23056 : 5016 : if (dfirst.perm[i] == 0xff)
23057 : 1430 : dfirst.perm[i] = (which1 == 2 ? i + nelt : i);
23058 : 5016 : if (dsecond.perm[i] == 0xff)
23059 : 3586 : dsecond.perm[i] = (which2 == 2 ? i + nelt : i);
23060 : : }
23061 : 627 : canonicalize_perm (&dfirst);
23062 : 627 : start_sequence ();
23063 : 627 : ok = ix86_expand_vec_perm_const_1 (&dfirst);
23064 : 627 : seq1 = end_sequence ();
23065 : :
23066 : 627 : if (!ok)
23067 : : return false;
23068 : :
23069 : 627 : canonicalize_perm (&dsecond);
23070 : 627 : start_sequence ();
23071 : 627 : ok = ix86_expand_vec_perm_const_1 (&dsecond);
23072 : 627 : seq2 = end_sequence ();
23073 : :
23074 : 627 : if (!ok)
23075 : : return false;
23076 : :
23077 : 627 : if (d->testing_p)
23078 : : return true;
23079 : :
23080 : 40 : emit_insn (seq1);
23081 : 40 : emit_insn (seq2);
23082 : :
23083 : 40 : dthird = *d;
23084 : 40 : dthird.op0 = dsecond.target;
23085 : 40 : dthird.op1 = dsecond.target;
23086 : 40 : dthird.one_operand_p = true;
23087 : 40 : dthird.target = gen_reg_rtx (dthird.vmode);
23088 : 360 : for (i = 0; i < nelt; i++)
23089 : 320 : dthird.perm[i] = i ^ nelt2;
23090 : :
23091 : 40 : ok = expand_vec_perm_1 (&dthird);
23092 : 40 : gcc_assert (ok);
23093 : :
23094 : 40 : blend = d->vmode == V8SFmode ? gen_avx_blendps256 : gen_avx_blendpd256;
23095 : 40 : emit_insn (blend (d->target, dfirst.target, dthird.target, GEN_INT (msk)));
23096 : 40 : return true;
23097 : : }
23098 : :
23099 : : /* A subroutine of expand_vec_perm_even_odd_1. Implement the double-word
23100 : : permutation with two pshufb insns and an ior. We should have already
23101 : : failed all two instruction sequences. */
23102 : :
23103 : : static bool
23104 : 28084 : expand_vec_perm_pshufb2 (struct expand_vec_perm_d *d)
23105 : : {
23106 : 28084 : rtx rperm[2][16], vperm, l, h, op, m128;
23107 : 28084 : unsigned int i, nelt, eltsz;
23108 : 28084 : machine_mode mode;
23109 : 28084 : rtx (*gen) (rtx, rtx, rtx);
23110 : :
23111 : 32890 : if (!TARGET_SSSE3 || (GET_MODE_SIZE (d->vmode) != 16
23112 : 9522 : && GET_MODE_SIZE (d->vmode) != 8
23113 : 9482 : && GET_MODE_SIZE (d->vmode) != 4))
23114 : : return false;
23115 : 734 : gcc_assert (!d->one_operand_p);
23116 : :
23117 : 734 : if (d->testing_p)
23118 : : return true;
23119 : :
23120 : 130 : switch (GET_MODE_SIZE (d->vmode))
23121 : : {
23122 : : case 4:
23123 : : mode = V4QImode;
23124 : : gen = gen_mmx_pshufbv4qi3;
23125 : : break;
23126 : 20 : case 8:
23127 : 20 : mode = V8QImode;
23128 : 20 : gen = gen_mmx_pshufbv8qi3;
23129 : 20 : break;
23130 : 45 : case 16:
23131 : 45 : mode = V16QImode;
23132 : 45 : gen = gen_ssse3_pshufbv16qi3;
23133 : 45 : break;
23134 : 0 : default:
23135 : 0 : gcc_unreachable ();
23136 : : }
23137 : :
23138 : 65 : nelt = d->nelt;
23139 : 65 : eltsz = GET_MODE_UNIT_SIZE (d->vmode);
23140 : :
23141 : : /* Generate two permutation masks. If the required element is within
23142 : : the given vector it is shuffled into the proper lane. If the required
23143 : : element is in the other vector, force a zero into the lane by setting
23144 : : bit 7 in the permutation mask. */
23145 : 65 : m128 = GEN_INT (-128);
23146 : 849 : for (i = 0; i < nelt; ++i)
23147 : : {
23148 : 784 : unsigned j, k, e = d->perm[i];
23149 : 784 : unsigned which = (e >= nelt);
23150 : 784 : if (e >= nelt)
23151 : 393 : e -= nelt;
23152 : :
23153 : 1664 : for (j = 0; j < eltsz; ++j)
23154 : : {
23155 : 880 : rperm[which][i*eltsz + j] = GEN_INT (e*eltsz + j);
23156 : 880 : rperm[1-which][i*eltsz + j] = m128;
23157 : : }
23158 : :
23159 : 6936 : for (k = i*eltsz + j; k < 16; ++k)
23160 : 6152 : rperm[0][k] = rperm[1][k] = m128;
23161 : : }
23162 : :
23163 : 65 : vperm = gen_rtx_CONST_VECTOR (V16QImode, gen_rtvec_v (16, rperm[0]));
23164 : 65 : vperm = force_reg (V16QImode, vperm);
23165 : :
23166 : 65 : l = gen_reg_rtx (mode);
23167 : 65 : op = gen_lowpart (mode, d->op0);
23168 : 65 : emit_insn (gen (l, op, vperm));
23169 : :
23170 : 65 : vperm = gen_rtx_CONST_VECTOR (V16QImode, gen_rtvec_v (16, rperm[1]));
23171 : 65 : vperm = force_reg (V16QImode, vperm);
23172 : :
23173 : 65 : h = gen_reg_rtx (mode);
23174 : 65 : op = gen_lowpart (mode, d->op1);
23175 : 65 : emit_insn (gen (h, op, vperm));
23176 : :
23177 : 65 : op = d->target;
23178 : 65 : if (d->vmode != mode)
23179 : 22 : op = gen_reg_rtx (mode);
23180 : 65 : ix86_emit_vec_binop (IOR, mode, op, l, h);
23181 : 65 : if (op != d->target)
23182 : 22 : emit_move_insn (d->target, gen_lowpart (d->vmode, op));
23183 : :
23184 : : return true;
23185 : : }
23186 : :
23187 : : /* Implement arbitrary permutation of one V32QImode and V16QImode operand
23188 : : with two vpshufb insns, vpermq and vpor. We should have already failed
23189 : : all two or three instruction sequences. */
23190 : :
23191 : : static bool
23192 : 23438 : expand_vec_perm_vpshufb2_vpermq (struct expand_vec_perm_d *d)
23193 : : {
23194 : 23438 : rtx rperm[2][32], vperm, l, h, hp, op, m128;
23195 : 23438 : unsigned int i, nelt, eltsz;
23196 : :
23197 : 23438 : if (!TARGET_AVX2
23198 : 367 : || !d->one_operand_p
23199 : 139 : || (d->vmode != V32QImode && d->vmode != V16HImode))
23200 : : return false;
23201 : :
23202 : 6 : if (d->testing_p)
23203 : : return true;
23204 : :
23205 : 6 : nelt = d->nelt;
23206 : 6 : eltsz = GET_MODE_UNIT_SIZE (d->vmode);
23207 : :
23208 : : /* Generate two permutation masks. If the required element is within
23209 : : the same lane, it is shuffled in. If the required element from the
23210 : : other lane, force a zero by setting bit 7 in the permutation mask.
23211 : : In the other mask the mask has non-negative elements if element
23212 : : is requested from the other lane, but also moved to the other lane,
23213 : : so that the result of vpshufb can have the two V2TImode halves
23214 : : swapped. */
23215 : 6 : m128 = GEN_INT (-128);
23216 : 166 : for (i = 0; i < nelt; ++i)
23217 : : {
23218 : 160 : unsigned j, e = d->perm[i] & (nelt / 2 - 1);
23219 : 160 : unsigned which = ((d->perm[i] ^ i) & (nelt / 2)) * eltsz;
23220 : :
23221 : 352 : for (j = 0; j < eltsz; ++j)
23222 : : {
23223 : 192 : rperm[!!which][(i * eltsz + j) ^ which] = GEN_INT (e * eltsz + j);
23224 : 192 : rperm[!which][(i * eltsz + j) ^ (which ^ 16)] = m128;
23225 : : }
23226 : : }
23227 : :
23228 : 6 : vperm = gen_rtx_CONST_VECTOR (V32QImode, gen_rtvec_v (32, rperm[1]));
23229 : 6 : vperm = force_reg (V32QImode, vperm);
23230 : :
23231 : 6 : h = gen_reg_rtx (V32QImode);
23232 : 6 : op = gen_lowpart (V32QImode, d->op0);
23233 : 6 : emit_insn (gen_avx2_pshufbv32qi3 (h, op, vperm));
23234 : :
23235 : : /* Swap the 128-byte lanes of h into hp. */
23236 : 6 : hp = gen_reg_rtx (V4DImode);
23237 : 6 : op = gen_lowpart (V4DImode, h);
23238 : 6 : emit_insn (gen_avx2_permv4di_1 (hp, op, const2_rtx, GEN_INT (3), const0_rtx,
23239 : : const1_rtx));
23240 : :
23241 : 6 : vperm = gen_rtx_CONST_VECTOR (V32QImode, gen_rtvec_v (32, rperm[0]));
23242 : 6 : vperm = force_reg (V32QImode, vperm);
23243 : :
23244 : 6 : l = gen_reg_rtx (V32QImode);
23245 : 6 : op = gen_lowpart (V32QImode, d->op0);
23246 : 6 : emit_insn (gen_avx2_pshufbv32qi3 (l, op, vperm));
23247 : :
23248 : 6 : op = d->target;
23249 : 6 : if (d->vmode != V32QImode)
23250 : 2 : op = gen_reg_rtx (V32QImode);
23251 : 6 : emit_insn (gen_iorv32qi3 (op, l, gen_lowpart (V32QImode, hp)));
23252 : 6 : if (op != d->target)
23253 : 2 : emit_move_insn (d->target, gen_lowpart (d->vmode, op));
23254 : :
23255 : : return true;
23256 : : }
23257 : :
23258 : : /* A subroutine of expand_vec_perm_even_odd_1. Implement extract-even
23259 : : and extract-odd permutations of two V32QImode and V16QImode operand
23260 : : with two vpshufb insns, vpor and vpermq. We should have already
23261 : : failed all two or three instruction sequences. */
23262 : :
23263 : : static bool
23264 : 23432 : expand_vec_perm_vpshufb2_vpermq_even_odd (struct expand_vec_perm_d *d)
23265 : : {
23266 : 23432 : rtx rperm[2][32], vperm, l, h, ior, op, m128;
23267 : 23432 : unsigned int i, nelt, eltsz;
23268 : :
23269 : 23432 : if (!TARGET_AVX2
23270 : 361 : || d->one_operand_p
23271 : 228 : || (d->vmode != V32QImode && d->vmode != V16HImode))
23272 : : return false;
23273 : :
23274 : 112 : for (i = 0; i < d->nelt; ++i)
23275 : 112 : if ((d->perm[i] ^ (i * 2)) & (3 * d->nelt / 2))
23276 : : return false;
23277 : :
23278 : 0 : if (d->testing_p)
23279 : : return true;
23280 : :
23281 : 0 : nelt = d->nelt;
23282 : 0 : eltsz = GET_MODE_UNIT_SIZE (d->vmode);
23283 : :
23284 : : /* Generate two permutation masks. In the first permutation mask
23285 : : the first quarter will contain indexes for the first half
23286 : : of the op0, the second quarter will contain bit 7 set, third quarter
23287 : : will contain indexes for the second half of the op0 and the
23288 : : last quarter bit 7 set. In the second permutation mask
23289 : : the first quarter will contain bit 7 set, the second quarter
23290 : : indexes for the first half of the op1, the third quarter bit 7 set
23291 : : and last quarter indexes for the second half of the op1.
23292 : : I.e. the first mask e.g. for V32QImode extract even will be:
23293 : : 0, 2, ..., 0xe, -128, ..., -128, 0, 2, ..., 0xe, -128, ..., -128
23294 : : (all values masked with 0xf except for -128) and second mask
23295 : : for extract even will be
23296 : : -128, ..., -128, 0, 2, ..., 0xe, -128, ..., -128, 0, 2, ..., 0xe. */
23297 : 0 : m128 = GEN_INT (-128);
23298 : 0 : for (i = 0; i < nelt; ++i)
23299 : : {
23300 : 0 : unsigned j, e = d->perm[i] & (nelt / 2 - 1);
23301 : 0 : unsigned which = d->perm[i] >= nelt;
23302 : 0 : unsigned xorv = (i >= nelt / 4 && i < 3 * nelt / 4) ? 24 : 0;
23303 : :
23304 : 0 : for (j = 0; j < eltsz; ++j)
23305 : : {
23306 : 0 : rperm[which][(i * eltsz + j) ^ xorv] = GEN_INT (e * eltsz + j);
23307 : 0 : rperm[1 - which][(i * eltsz + j) ^ xorv] = m128;
23308 : : }
23309 : : }
23310 : :
23311 : 0 : vperm = gen_rtx_CONST_VECTOR (V32QImode, gen_rtvec_v (32, rperm[0]));
23312 : 0 : vperm = force_reg (V32QImode, vperm);
23313 : :
23314 : 0 : l = gen_reg_rtx (V32QImode);
23315 : 0 : op = gen_lowpart (V32QImode, d->op0);
23316 : 0 : emit_insn (gen_avx2_pshufbv32qi3 (l, op, vperm));
23317 : :
23318 : 0 : vperm = gen_rtx_CONST_VECTOR (V32QImode, gen_rtvec_v (32, rperm[1]));
23319 : 0 : vperm = force_reg (V32QImode, vperm);
23320 : :
23321 : 0 : h = gen_reg_rtx (V32QImode);
23322 : 0 : op = gen_lowpart (V32QImode, d->op1);
23323 : 0 : emit_insn (gen_avx2_pshufbv32qi3 (h, op, vperm));
23324 : :
23325 : 0 : ior = gen_reg_rtx (V32QImode);
23326 : 0 : emit_insn (gen_iorv32qi3 (ior, l, h));
23327 : :
23328 : : /* Permute the V4DImode quarters using { 0, 2, 1, 3 } permutation. */
23329 : 0 : op = gen_reg_rtx (V4DImode);
23330 : 0 : ior = gen_lowpart (V4DImode, ior);
23331 : 0 : emit_insn (gen_avx2_permv4di_1 (op, ior, const0_rtx, const2_rtx,
23332 : : const1_rtx, GEN_INT (3)));
23333 : 0 : emit_move_insn (d->target, gen_lowpart (d->vmode, op));
23334 : :
23335 : 0 : return true;
23336 : : }
23337 : :
23338 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement a
23339 : : permutation (which is a bland) with and, andnot and or when pshufb is not available.
23340 : :
23341 : : It handles case:
23342 : : __builtin_shufflevector (v1, v2, 0, 9, 2, 11, 4, 13, 6, 15);
23343 : : __builtin_shufflevector (v1, v2, 8, 1, 2, 11, 4, 13, 6, 15);
23344 : :
23345 : : An element[i] must be chosen between op0[i] and op1[i] to satisfy the
23346 : : requirement.
23347 : : */
23348 : :
23349 : : static bool
23350 : 24459 : expand_vec_perm_pand_pandn_por (struct expand_vec_perm_d *d)
23351 : : {
23352 : 24459 : rtx rperm[16], vperm;
23353 : 24459 : unsigned int i, nelt = d->nelt;
23354 : :
23355 : 24459 : if (!TARGET_SSE2
23356 : 24459 : || d->one_operand_p
23357 : 20939 : || (d->vmode != V16QImode && d->vmode != V8HImode))
23358 : : return false;
23359 : :
23360 : 7688 : if (d->perm[0] != 0)
23361 : : return false;
23362 : :
23363 : : /* The dest[i] must select an element between op0[i] and op1[i]. */
23364 : 15523 : for (i = 1; i < nelt; i++)
23365 : 14506 : if ((d->perm[i] % nelt) != i)
23366 : : return false;
23367 : :
23368 : 1017 : if (d->testing_p)
23369 : : return true;
23370 : :
23371 : : /* Generates a blend mask for the operators AND and ANDNOT. */
23372 : 108 : machine_mode inner_mode = GET_MODE_INNER (d->vmode);
23373 : 1148 : for (i = 0; i < nelt; i++)
23374 : 1581 : rperm[i] = (d->perm[i] < nelt) ? CONSTM1_RTX (inner_mode)
23375 : 541 : : CONST0_RTX (inner_mode);
23376 : :
23377 : 108 : vperm = gen_rtx_CONST_VECTOR (d->vmode, gen_rtvec_v (nelt, rperm));
23378 : 108 : vperm = force_reg (d->vmode, vperm);
23379 : :
23380 : 108 : ix86_expand_sse_movcc (d->target, vperm, d->op0, d->op1);
23381 : :
23382 : 108 : return true;
23383 : : }
23384 : :
23385 : : /* Implement permutation with pslldq + psrldq + por when pshufb is not
23386 : : available. */
23387 : : static bool
23388 : 43074 : expand_vec_perm_pslldq_psrldq_por (struct expand_vec_perm_d *d, bool pandn)
23389 : : {
23390 : 43074 : unsigned i, nelt = d->nelt;
23391 : 43074 : unsigned start1, end1 = -1;
23392 : 43074 : machine_mode vmode = d->vmode, imode;
23393 : 43074 : int start2 = -1;
23394 : 43074 : bool clear_op0, clear_op1;
23395 : 43074 : unsigned inner_size;
23396 : 43074 : rtx op0, op1, dop1;
23397 : 43074 : rtx (*gen_vec_shr) (rtx, rtx, rtx);
23398 : 43074 : rtx (*gen_vec_shl) (rtx, rtx, rtx);
23399 : :
23400 : : /* pshufd can be used for V4SI/V2DI under TARGET_SSE2. */
23401 : 43074 : if (!TARGET_SSE2 || (vmode != E_V16QImode && vmode != E_V8HImode))
23402 : : return false;
23403 : :
23404 : 13648 : start1 = d->perm[0];
23405 : 35688 : for (i = 1; i < nelt; i++)
23406 : : {
23407 : 35053 : if (d->perm[i] != d->perm[i-1] + 1
23408 : 8546 : || d->perm[i] == nelt)
23409 : : {
23410 : 26661 : if (start2 == -1)
23411 : : {
23412 : 13648 : start2 = d->perm[i];
23413 : 13648 : end1 = d->perm[i-1];
23414 : : }
23415 : : else
23416 : : return false;
23417 : : }
23418 : : }
23419 : :
23420 : 635 : clear_op0 = end1 != nelt - 1;
23421 : 635 : clear_op1 = start2 % nelt != 0;
23422 : : /* pandn/pand is needed to clear upper/lower bits of op0/op1. */
23423 : 635 : if (!pandn && (clear_op0 || clear_op1))
23424 : : return false;
23425 : :
23426 : 411 : if (d->testing_p)
23427 : : return true;
23428 : :
23429 : 44 : gen_vec_shr = vmode == E_V16QImode ? gen_vec_shr_v16qi : gen_vec_shr_v8hi;
23430 : 20 : gen_vec_shl = vmode == E_V16QImode ? gen_vec_shl_v16qi : gen_vec_shl_v8hi;
23431 : 44 : imode = GET_MODE_INNER (vmode);
23432 : 44 : inner_size = GET_MODE_BITSIZE (imode);
23433 : 44 : op0 = gen_reg_rtx (vmode);
23434 : 44 : op1 = gen_reg_rtx (vmode);
23435 : :
23436 : 44 : if (start1)
23437 : 41 : emit_insn (gen_vec_shr (op0, d->op0, GEN_INT (start1 * inner_size)));
23438 : : else
23439 : 3 : emit_move_insn (op0, d->op0);
23440 : :
23441 : 44 : dop1 = d->op1;
23442 : 44 : if (d->one_operand_p)
23443 : 24 : dop1 = d->op0;
23444 : :
23445 : 44 : int shl_offset = end1 - start1 + 1 - start2 % nelt;
23446 : 44 : if (shl_offset)
23447 : 44 : emit_insn (gen_vec_shl (op1, dop1, GEN_INT (shl_offset * inner_size)));
23448 : : else
23449 : 0 : emit_move_insn (op1, dop1);
23450 : :
23451 : : /* Clear lower/upper bits for op0/op1. */
23452 : 44 : if (clear_op0 || clear_op1)
23453 : : {
23454 : : rtx vec[16];
23455 : : rtx const_vec;
23456 : : rtx clear;
23457 : 339 : for (i = 0; i != nelt; i++)
23458 : : {
23459 : 312 : if (i < (end1 - start1 + 1))
23460 : 156 : vec[i] = gen_int_mode ((HOST_WIDE_INT_1U << inner_size) - 1, imode);
23461 : : else
23462 : 156 : vec[i] = CONST0_RTX (imode);
23463 : : }
23464 : 27 : const_vec = gen_rtx_CONST_VECTOR (vmode, gen_rtvec_v (nelt, vec));
23465 : 27 : const_vec = validize_mem (force_const_mem (vmode, const_vec));
23466 : 27 : clear = force_reg (vmode, const_vec);
23467 : :
23468 : 27 : if (clear_op0)
23469 : 19 : emit_move_insn (op0, gen_rtx_AND (vmode, op0, clear));
23470 : 27 : if (clear_op1)
23471 : 16 : emit_move_insn (op1, gen_rtx_AND (vmode,
23472 : : gen_rtx_NOT (vmode, clear),
23473 : : op1));
23474 : : }
23475 : :
23476 : 44 : emit_move_insn (d->target, gen_rtx_IOR (vmode, op0, op1));
23477 : 44 : return true;
23478 : : }
23479 : :
23480 : : /* A subroutine of expand_vec_perm_even_odd_1. Implement extract-even
23481 : : and extract-odd permutations of two V8QI, V8HI, V16QI, V16HI or V32QI
23482 : : operands with two "and" and "pack" or two "shift" and "pack" insns.
23483 : : We should have already failed all two instruction sequences. */
23484 : :
23485 : : static bool
23486 : 45662 : expand_vec_perm_even_odd_pack (struct expand_vec_perm_d *d)
23487 : : {
23488 : 45662 : rtx op, dop0, dop1, t;
23489 : 45662 : unsigned i, odd, c, s, nelt = d->nelt;
23490 : 45662 : int pblendw_i = 0;
23491 : 45662 : bool end_perm = false;
23492 : 45662 : machine_mode half_mode;
23493 : 45662 : rtx (*gen_and) (rtx, rtx, rtx);
23494 : 45662 : rtx (*gen_pack) (rtx, rtx, rtx);
23495 : 45662 : rtx (*gen_shift) (rtx, rtx, rtx);
23496 : :
23497 : 45662 : if (d->one_operand_p)
23498 : : return false;
23499 : :
23500 : 40609 : switch (d->vmode)
23501 : : {
23502 : 4302 : case E_V4HImode:
23503 : : /* Required for "pack". */
23504 : 4302 : if (!TARGET_SSE4_1)
23505 : : return false;
23506 : : c = 0xffff;
23507 : : s = 16;
23508 : : half_mode = V2SImode;
23509 : : gen_and = gen_andv2si3;
23510 : : gen_pack = gen_mmx_packusdw;
23511 : : gen_shift = gen_lshrv2si3;
23512 : : pblendw_i = 0x5;
23513 : : break;
23514 : 5939 : case E_V8HImode:
23515 : : /* Required for "pack". */
23516 : 5939 : if (!TARGET_SSE4_1)
23517 : : return false;
23518 : : c = 0xffff;
23519 : : s = 16;
23520 : : half_mode = V4SImode;
23521 : : gen_and = gen_andv4si3;
23522 : : gen_pack = gen_sse4_1_packusdw;
23523 : : gen_shift = gen_lshrv4si3;
23524 : : pblendw_i = 0x55;
23525 : : break;
23526 : : case E_V8QImode:
23527 : : /* No check as all instructions are SSE2. */
23528 : : c = 0xff;
23529 : : s = 8;
23530 : : half_mode = V4HImode;
23531 : : gen_and = gen_andv4hi3;
23532 : : gen_pack = gen_mmx_packuswb;
23533 : : gen_shift = gen_lshrv4hi3;
23534 : : break;
23535 : 14473 : case E_V16QImode:
23536 : : /* No check as all instructions are SSE2. */
23537 : 14473 : c = 0xff;
23538 : 14473 : s = 8;
23539 : 14473 : half_mode = V8HImode;
23540 : 14473 : gen_and = gen_andv8hi3;
23541 : 14473 : gen_pack = gen_sse2_packuswb;
23542 : 14473 : gen_shift = gen_lshrv8hi3;
23543 : 14473 : break;
23544 : 418 : case E_V16HImode:
23545 : 418 : if (!TARGET_AVX2)
23546 : : return false;
23547 : : c = 0xffff;
23548 : : s = 16;
23549 : : half_mode = V8SImode;
23550 : : gen_and = gen_andv8si3;
23551 : : gen_pack = gen_avx2_packusdw;
23552 : : gen_shift = gen_lshrv8si3;
23553 : : pblendw_i = 0x5555;
23554 : : end_perm = true;
23555 : : break;
23556 : 510 : case E_V32QImode:
23557 : 510 : if (!TARGET_AVX2)
23558 : : return false;
23559 : : c = 0xff;
23560 : : s = 8;
23561 : : half_mode = V16HImode;
23562 : : gen_and = gen_andv16hi3;
23563 : : gen_pack = gen_avx2_packuswb;
23564 : : gen_shift = gen_lshrv16hi3;
23565 : : end_perm = true;
23566 : : break;
23567 : : default:
23568 : : /* Only V4HI, V8QI, V8HI, V16QI, V16HI and V32QI modes
23569 : : are more profitable than general shuffles. */
23570 : : return false;
23571 : : }
23572 : :
23573 : : /* Check that permutation is even or odd. */
23574 : 19930 : odd = d->perm[0];
23575 : 19930 : if (odd > 1)
23576 : : return false;
23577 : :
23578 : 232856 : for (i = 1; i < nelt; ++i)
23579 : 216972 : if (d->perm[i] != 2 * i + odd)
23580 : : return false;
23581 : :
23582 : 15884 : if (d->testing_p)
23583 : : return true;
23584 : :
23585 : 5491 : dop0 = gen_reg_rtx (half_mode);
23586 : 5491 : dop1 = gen_reg_rtx (half_mode);
23587 : 5491 : if (odd == 0)
23588 : : {
23589 : : /* Use pblendw since const_vector 0 should be cheaper than
23590 : : const_vector 0xffff. */
23591 : 4720 : if (d->vmode == V4HImode
23592 : : || d->vmode == E_V8HImode
23593 : : || d->vmode == E_V16HImode)
23594 : : {
23595 : 831 : rtx dop0_t = gen_reg_rtx (d->vmode);
23596 : 831 : rtx dop1_t = gen_reg_rtx (d->vmode);
23597 : 831 : t = gen_reg_rtx (d->vmode);
23598 : 831 : emit_move_insn (t, CONST0_RTX (d->vmode));
23599 : :
23600 : 831 : emit_move_insn (dop0_t, gen_rtx_VEC_MERGE (d->vmode, d->op0, t,
23601 : : GEN_INT (pblendw_i)));
23602 : 831 : emit_move_insn (dop1_t, gen_rtx_VEC_MERGE (d->vmode, d->op1, t,
23603 : : GEN_INT (pblendw_i)));
23604 : :
23605 : 831 : emit_move_insn (dop0, gen_lowpart (half_mode, dop0_t));
23606 : 831 : emit_move_insn (dop1, gen_lowpart (half_mode, dop1_t));
23607 : 831 : }
23608 : : else
23609 : : {
23610 : 3889 : t = gen_const_vec_duplicate (half_mode, GEN_INT (c));
23611 : 3889 : t = force_reg (half_mode, t);
23612 : 3889 : emit_insn (gen_and (dop0, t, gen_lowpart (half_mode, d->op0)));
23613 : 3889 : emit_insn (gen_and (dop1, t, gen_lowpart (half_mode, d->op1)));
23614 : : }
23615 : : }
23616 : : else
23617 : : {
23618 : 1542 : emit_insn (gen_shift (dop0,
23619 : 771 : gen_lowpart (half_mode, d->op0),
23620 : : GEN_INT (s)));
23621 : 1542 : emit_insn (gen_shift (dop1,
23622 : 771 : gen_lowpart (half_mode, d->op1),
23623 : : GEN_INT (s)));
23624 : : }
23625 : : /* In AVX2 for 256 bit case we need to permute pack result. */
23626 : 5491 : if (TARGET_AVX2 && end_perm)
23627 : : {
23628 : 399 : op = gen_reg_rtx (d->vmode);
23629 : 399 : t = gen_reg_rtx (V4DImode);
23630 : 399 : emit_insn (gen_pack (op, dop0, dop1));
23631 : 798 : emit_insn (gen_avx2_permv4di_1 (t,
23632 : 399 : gen_lowpart (V4DImode, op),
23633 : : const0_rtx,
23634 : : const2_rtx,
23635 : : const1_rtx,
23636 : : GEN_INT (3)));
23637 : 399 : emit_move_insn (d->target, gen_lowpart (d->vmode, t));
23638 : : }
23639 : : else
23640 : 5092 : emit_insn (gen_pack (d->target, dop0, dop1));
23641 : :
23642 : : return true;
23643 : : }
23644 : :
23645 : : /* A subroutine of expand_vec_perm_even_odd_1. Implement extract-even
23646 : : and extract-odd permutations of two V64QI operands
23647 : : with two "shifts", two "truncs" and one "concat" insns for "odd"
23648 : : and two "truncs" and one concat insn for "even."
23649 : : Have already failed all two instruction sequences. */
23650 : :
23651 : : static bool
23652 : 23478 : expand_vec_perm_even_odd_trunc (struct expand_vec_perm_d *d)
23653 : : {
23654 : 23478 : rtx t1, t2, t3, t4;
23655 : 23478 : unsigned i, odd, nelt = d->nelt;
23656 : :
23657 : 23478 : if (!TARGET_AVX512BW
23658 : 66 : || d->one_operand_p
23659 : 62 : || d->vmode != V64QImode)
23660 : : return false;
23661 : :
23662 : : /* Check that permutation is even or odd. */
23663 : 62 : odd = d->perm[0];
23664 : 62 : if (odd > 1)
23665 : : return false;
23666 : :
23667 : 1910 : for (i = 1; i < nelt; ++i)
23668 : 1884 : if (d->perm[i] != 2 * i + odd)
23669 : : return false;
23670 : :
23671 : 26 : if (d->testing_p)
23672 : : return true;
23673 : :
23674 : :
23675 : 26 : if (odd)
23676 : : {
23677 : 1 : t1 = gen_reg_rtx (V32HImode);
23678 : 1 : t2 = gen_reg_rtx (V32HImode);
23679 : 2 : emit_insn (gen_lshrv32hi3 (t1,
23680 : 1 : gen_lowpart (V32HImode, d->op0),
23681 : : GEN_INT (8)));
23682 : 2 : emit_insn (gen_lshrv32hi3 (t2,
23683 : 1 : gen_lowpart (V32HImode, d->op1),
23684 : : GEN_INT (8)));
23685 : : }
23686 : : else
23687 : : {
23688 : 25 : t1 = gen_lowpart (V32HImode, d->op0);
23689 : 25 : t2 = gen_lowpart (V32HImode, d->op1);
23690 : : }
23691 : :
23692 : 26 : t3 = gen_reg_rtx (V32QImode);
23693 : 26 : t4 = gen_reg_rtx (V32QImode);
23694 : 26 : emit_insn (gen_avx512bw_truncatev32hiv32qi2 (t3, t1));
23695 : 26 : emit_insn (gen_avx512bw_truncatev32hiv32qi2 (t4, t2));
23696 : 26 : emit_insn (gen_avx_vec_concatv64qi (d->target, t3, t4));
23697 : :
23698 : 26 : return true;
23699 : : }
23700 : :
23701 : : /* A subroutine of ix86_expand_vec_perm_const_1. Implement extract-even
23702 : : and extract-odd permutations. */
23703 : :
23704 : : static bool
23705 : 12573 : expand_vec_perm_even_odd_1 (struct expand_vec_perm_d *d, unsigned odd)
23706 : : {
23707 : 12573 : rtx t1, t2, t3, t4, t5;
23708 : :
23709 : 12573 : switch (d->vmode)
23710 : : {
23711 : 37 : case E_V4DFmode:
23712 : 37 : if (d->testing_p)
23713 : : break;
23714 : 1 : t1 = gen_reg_rtx (V4DFmode);
23715 : 1 : t2 = gen_reg_rtx (V4DFmode);
23716 : :
23717 : : /* Shuffle the lanes around into { 0 1 4 5 } and { 2 3 6 7 }. */
23718 : 1 : emit_insn (gen_avx_vperm2f128v4df3 (t1, d->op0, d->op1, GEN_INT (0x20)));
23719 : 1 : emit_insn (gen_avx_vperm2f128v4df3 (t2, d->op0, d->op1, GEN_INT (0x31)));
23720 : :
23721 : : /* Now an unpck[lh]pd will produce the result required. */
23722 : 1 : if (odd)
23723 : 0 : t3 = gen_avx_unpckhpd256 (d->target, t1, t2);
23724 : : else
23725 : 1 : t3 = gen_avx_unpcklpd256 (d->target, t1, t2);
23726 : 1 : emit_insn (t3);
23727 : 1 : break;
23728 : :
23729 : 1684 : case E_V8SFmode:
23730 : 1684 : {
23731 : 1684 : int mask = odd ? 0xdd : 0x88;
23732 : :
23733 : 1684 : if (d->testing_p)
23734 : : break;
23735 : 186 : t1 = gen_reg_rtx (V8SFmode);
23736 : 186 : t2 = gen_reg_rtx (V8SFmode);
23737 : 186 : t3 = gen_reg_rtx (V8SFmode);
23738 : :
23739 : : /* Shuffle within the 128-bit lanes to produce:
23740 : : { 0 2 8 a 4 6 c e } | { 1 3 9 b 5 7 d f }. */
23741 : 186 : emit_insn (gen_avx_shufps256 (t1, d->op0, d->op1,
23742 : : GEN_INT (mask)));
23743 : :
23744 : : /* Shuffle the lanes around to produce:
23745 : : { 4 6 c e 0 2 8 a } and { 5 7 d f 1 3 9 b }. */
23746 : 186 : emit_insn (gen_avx_vperm2f128v8sf3 (t2, t1, t1,
23747 : : GEN_INT (0x3)));
23748 : :
23749 : : /* Shuffle within the 128-bit lanes to produce:
23750 : : { 0 2 4 6 4 6 0 2 } | { 1 3 5 7 5 7 1 3 }. */
23751 : 186 : emit_insn (gen_avx_shufps256 (t3, t1, t2, GEN_INT (0x44)));
23752 : :
23753 : : /* Shuffle within the 128-bit lanes to produce:
23754 : : { 8 a c e c e 8 a } | { 9 b d f d f 9 b }. */
23755 : 186 : emit_insn (gen_avx_shufps256 (t2, t1, t2, GEN_INT (0xee)));
23756 : :
23757 : : /* Shuffle the lanes around to produce:
23758 : : { 0 2 4 6 8 a c e } | { 1 3 5 7 9 b d f }. */
23759 : 186 : emit_insn (gen_avx_vperm2f128v8sf3 (d->target, t3, t2,
23760 : : GEN_INT (0x20)));
23761 : : }
23762 : 186 : break;
23763 : :
23764 : 0 : case E_V2DFmode:
23765 : 0 : case E_V4SFmode:
23766 : 0 : case E_V2DImode:
23767 : 0 : case E_V2SImode:
23768 : 0 : case E_V4SImode:
23769 : 0 : case E_V2HImode:
23770 : : /* These are always directly implementable by expand_vec_perm_1. */
23771 : 0 : gcc_unreachable ();
23772 : :
23773 : 0 : case E_V2SFmode:
23774 : 0 : gcc_assert (TARGET_MMX_WITH_SSE);
23775 : : /* We have no suitable instructions. */
23776 : 0 : if (d->testing_p)
23777 : : return false;
23778 : : break;
23779 : :
23780 : 1025 : case E_V4QImode:
23781 : 1025 : if (TARGET_SSSE3 && !TARGET_SLOW_PSHUFB)
23782 : 0 : return expand_vec_perm_pshufb2 (d);
23783 : : else
23784 : : {
23785 : 1025 : if (d->testing_p)
23786 : : break;
23787 : : /* We need 2*log2(N)-1 operations to achieve odd/even
23788 : : with interleave. */
23789 : 193 : t1 = gen_reg_rtx (V4QImode);
23790 : 193 : emit_insn (gen_mmx_punpckhbw_low (t1, d->op0, d->op1));
23791 : 193 : emit_insn (gen_mmx_punpcklbw_low (d->target, d->op0, d->op1));
23792 : 193 : if (odd)
23793 : 38 : t2 = gen_mmx_punpckhbw_low (d->target, d->target, t1);
23794 : : else
23795 : 155 : t2 = gen_mmx_punpcklbw_low (d->target, d->target, t1);
23796 : 193 : emit_insn (t2);
23797 : : }
23798 : 193 : break;
23799 : :
23800 : 1261 : case E_V4HImode:
23801 : 1261 : if (TARGET_SSE4_1)
23802 : 86 : return expand_vec_perm_even_odd_pack (d);
23803 : 1175 : else if (TARGET_SSSE3 && !TARGET_SLOW_PSHUFB)
23804 : 20 : return expand_vec_perm_pshufb2 (d);
23805 : : else
23806 : : {
23807 : 1155 : if (d->testing_p)
23808 : : break;
23809 : : /* We need 2*log2(N)-1 operations to achieve odd/even
23810 : : with interleave. */
23811 : 375 : t1 = gen_reg_rtx (V4HImode);
23812 : 375 : emit_insn (gen_mmx_punpckhwd (t1, d->op0, d->op1));
23813 : 375 : emit_insn (gen_mmx_punpcklwd (d->target, d->op0, d->op1));
23814 : 375 : if (odd)
23815 : 8 : t2 = gen_mmx_punpckhwd (d->target, d->target, t1);
23816 : : else
23817 : 367 : t2 = gen_mmx_punpcklwd (d->target, d->target, t1);
23818 : 375 : emit_insn (t2);
23819 : : }
23820 : 375 : break;
23821 : :
23822 : 6569 : case E_V8HImode:
23823 : 6569 : if (TARGET_SSE4_1)
23824 : 427 : return expand_vec_perm_even_odd_pack (d);
23825 : 6142 : else if (TARGET_SSSE3 && !TARGET_SLOW_PSHUFB)
23826 : 1 : return expand_vec_perm_pshufb2 (d);
23827 : : else
23828 : : {
23829 : 6141 : if (d->testing_p)
23830 : : break;
23831 : : /* We need 2*log2(N)-1 operations to achieve odd/even
23832 : : with interleave. */
23833 : 2580 : t1 = gen_reg_rtx (V8HImode);
23834 : 2580 : t2 = gen_reg_rtx (V8HImode);
23835 : 2580 : emit_insn (gen_vec_interleave_highv8hi (t1, d->op0, d->op1));
23836 : 2580 : emit_insn (gen_vec_interleave_lowv8hi (d->target, d->op0, d->op1));
23837 : 2580 : emit_insn (gen_vec_interleave_highv8hi (t2, d->target, t1));
23838 : 2580 : emit_insn (gen_vec_interleave_lowv8hi (d->target, d->target, t1));
23839 : 2580 : if (odd)
23840 : 86 : t3 = gen_vec_interleave_highv8hi (d->target, d->target, t2);
23841 : : else
23842 : 2494 : t3 = gen_vec_interleave_lowv8hi (d->target, d->target, t2);
23843 : 2580 : emit_insn (t3);
23844 : : }
23845 : 2580 : break;
23846 : :
23847 : 1271 : case E_V8QImode:
23848 : 1271 : case E_V16QImode:
23849 : 1271 : return expand_vec_perm_even_odd_pack (d);
23850 : :
23851 : 450 : case E_V16HImode:
23852 : 450 : case E_V32QImode:
23853 : 450 : return expand_vec_perm_even_odd_pack (d);
23854 : :
23855 : 36 : case E_V64QImode:
23856 : 36 : return expand_vec_perm_even_odd_trunc (d);
23857 : :
23858 : 37 : case E_V4DImode:
23859 : 37 : if (!TARGET_AVX2)
23860 : : {
23861 : 37 : struct expand_vec_perm_d d_copy = *d;
23862 : 37 : d_copy.vmode = V4DFmode;
23863 : 37 : if (d->testing_p)
23864 : 36 : d_copy.target = gen_raw_REG (V4DFmode, LAST_VIRTUAL_REGISTER + 1);
23865 : : else
23866 : 1 : d_copy.target = gen_reg_rtx (V4DFmode);
23867 : 37 : d_copy.op0 = gen_lowpart (V4DFmode, d->op0);
23868 : 37 : d_copy.op1 = gen_lowpart (V4DFmode, d->op1);
23869 : 37 : if (expand_vec_perm_even_odd_1 (&d_copy, odd))
23870 : : {
23871 : 37 : if (!d->testing_p)
23872 : 1 : emit_move_insn (d->target,
23873 : 1 : gen_lowpart (V4DImode, d_copy.target));
23874 : 37 : return true;
23875 : : }
23876 : : return false;
23877 : : }
23878 : :
23879 : 0 : if (d->testing_p)
23880 : : break;
23881 : :
23882 : 0 : t1 = gen_reg_rtx (V4DImode);
23883 : 0 : t2 = gen_reg_rtx (V4DImode);
23884 : :
23885 : : /* Shuffle the lanes around into { 0 1 4 5 } and { 2 3 6 7 }. */
23886 : 0 : emit_insn (gen_avx2_permv2ti (t1, d->op0, d->op1, GEN_INT (0x20)));
23887 : 0 : emit_insn (gen_avx2_permv2ti (t2, d->op0, d->op1, GEN_INT (0x31)));
23888 : :
23889 : : /* Now an vpunpck[lh]qdq will produce the result required. */
23890 : 0 : if (odd)
23891 : 0 : t3 = gen_avx2_interleave_highv4di (d->target, t1, t2);
23892 : : else
23893 : 0 : t3 = gen_avx2_interleave_lowv4di (d->target, t1, t2);
23894 : 0 : emit_insn (t3);
23895 : 0 : break;
23896 : :
23897 : 203 : case E_V8SImode:
23898 : 203 : if (!TARGET_AVX2)
23899 : : {
23900 : 86 : struct expand_vec_perm_d d_copy = *d;
23901 : 86 : d_copy.vmode = V8SFmode;
23902 : 86 : if (d->testing_p)
23903 : 86 : d_copy.target = gen_raw_REG (V8SFmode, LAST_VIRTUAL_REGISTER + 1);
23904 : : else
23905 : 0 : d_copy.target = gen_reg_rtx (V8SFmode);
23906 : 86 : d_copy.op0 = gen_lowpart (V8SFmode, d->op0);
23907 : 86 : d_copy.op1 = gen_lowpart (V8SFmode, d->op1);
23908 : 86 : if (expand_vec_perm_even_odd_1 (&d_copy, odd))
23909 : : {
23910 : 86 : if (!d->testing_p)
23911 : 0 : emit_move_insn (d->target,
23912 : 0 : gen_lowpart (V8SImode, d_copy.target));
23913 : 86 : return true;
23914 : : }
23915 : : return false;
23916 : : }
23917 : :
23918 : 117 : if (d->testing_p)
23919 : : break;
23920 : :
23921 : 117 : t1 = gen_reg_rtx (V8SImode);
23922 : 117 : t2 = gen_reg_rtx (V8SImode);
23923 : 117 : t3 = gen_reg_rtx (V4DImode);
23924 : 117 : t4 = gen_reg_rtx (V4DImode);
23925 : 117 : t5 = gen_reg_rtx (V4DImode);
23926 : :
23927 : : /* Shuffle the lanes around into
23928 : : { 0 1 2 3 8 9 a b } and { 4 5 6 7 c d e f }. */
23929 : 234 : emit_insn (gen_avx2_permv2ti (t3, gen_lowpart (V4DImode, d->op0),
23930 : 117 : gen_lowpart (V4DImode, d->op1),
23931 : : GEN_INT (0x20)));
23932 : 234 : emit_insn (gen_avx2_permv2ti (t4, gen_lowpart (V4DImode, d->op0),
23933 : 117 : gen_lowpart (V4DImode, d->op1),
23934 : : GEN_INT (0x31)));
23935 : :
23936 : : /* Swap the 2nd and 3rd position in each lane into
23937 : : { 0 2 1 3 8 a 9 b } and { 4 6 5 7 c e d f }. */
23938 : 117 : emit_insn (gen_avx2_pshufdv3 (t1, gen_lowpart (V8SImode, t3),
23939 : : GEN_INT (2 * 4 + 1 * 16 + 3 * 64)));
23940 : 117 : emit_insn (gen_avx2_pshufdv3 (t2, gen_lowpart (V8SImode, t4),
23941 : : GEN_INT (2 * 4 + 1 * 16 + 3 * 64)));
23942 : :
23943 : : /* Now an vpunpck[lh]qdq will produce
23944 : : { 0 2 4 6 8 a c e } resp. { 1 3 5 7 9 b d f }. */
23945 : 117 : if (odd)
23946 : 0 : t3 = gen_avx2_interleave_highv4di (t5, gen_lowpart (V4DImode, t1),
23947 : 0 : gen_lowpart (V4DImode, t2));
23948 : : else
23949 : 117 : t3 = gen_avx2_interleave_lowv4di (t5, gen_lowpart (V4DImode, t1),
23950 : 117 : gen_lowpart (V4DImode, t2));
23951 : 117 : emit_insn (t3);
23952 : 117 : emit_move_insn (d->target, gen_lowpart (V8SImode, t5));
23953 : 117 : break;
23954 : :
23955 : 0 : default:
23956 : 0 : gcc_unreachable ();
23957 : : }
23958 : :
23959 : : return true;
23960 : : }
23961 : :
23962 : : /* A subroutine of ix86_expand_vec_perm_const_1. Pattern match
23963 : : extract-even and extract-odd permutations. */
23964 : :
23965 : : static bool
23966 : 23392 : expand_vec_perm_even_odd (struct expand_vec_perm_d *d)
23967 : : {
23968 : 23392 : unsigned i, odd, nelt = d->nelt;
23969 : :
23970 : 23392 : odd = d->perm[0];
23971 : 23392 : if (odd != 0 && odd != 1)
23972 : : return false;
23973 : :
23974 : 66872 : for (i = 1; i < nelt; ++i)
23975 : 59120 : if (d->perm[i] != 2 * i + odd)
23976 : : return false;
23977 : :
23978 : 7752 : if (d->vmode == E_V32HImode
23979 : 12 : && d->testing_p
23980 : 12 : && !TARGET_AVX512BW)
23981 : : return false;
23982 : :
23983 : 7740 : return expand_vec_perm_even_odd_1 (d, odd);
23984 : : }
23985 : :
23986 : : /* A subroutine of ix86_expand_vec_perm_const_1. Implement broadcast
23987 : : permutations. We assume that expand_vec_perm_1 has already failed. */
23988 : :
23989 : : static bool
23990 : 1037 : expand_vec_perm_broadcast_1 (struct expand_vec_perm_d *d)
23991 : : {
23992 : 1037 : unsigned elt = d->perm[0], nelt2 = d->nelt / 2;
23993 : 1037 : machine_mode vmode = d->vmode;
23994 : 1037 : rtx (*gen) (rtx, rtx, rtx);
23995 : 1037 : unsigned char perm2[4];
23996 : 1037 : rtx op0 = d->op0, dest;
23997 : 1037 : bool ok;
23998 : :
23999 : 1037 : switch (vmode)
24000 : : {
24001 : 0 : case E_V4DFmode:
24002 : 0 : case E_V8SFmode:
24003 : : /* These are special-cased in sse.md so that we can optionally
24004 : : use the vbroadcast instruction. They expand to two insns
24005 : : if the input happens to be in a register. */
24006 : 0 : gcc_unreachable ();
24007 : :
24008 : 0 : case E_V2DFmode:
24009 : 0 : case E_V2SFmode:
24010 : 0 : case E_V4SFmode:
24011 : 0 : case E_V2DImode:
24012 : 0 : case E_V2SImode:
24013 : 0 : case E_V4SImode:
24014 : 0 : case E_V2HImode:
24015 : 0 : case E_V4HImode:
24016 : : /* These are always implementable using standard shuffle patterns. */
24017 : 0 : gcc_unreachable ();
24018 : :
24019 : 16 : case E_V4QImode:
24020 : : /* This can be implemented via interleave and pshuflw. */
24021 : 16 : if (d->testing_p)
24022 : : return true;
24023 : :
24024 : 8 : if (elt >= nelt2)
24025 : : {
24026 : 4 : gen = gen_mmx_punpckhbw_low;
24027 : 4 : elt -= nelt2;
24028 : : }
24029 : : else
24030 : : gen = gen_mmx_punpcklbw_low;
24031 : :
24032 : 8 : dest = gen_reg_rtx (vmode);
24033 : 8 : emit_insn (gen (dest, op0, op0));
24034 : 8 : vmode = get_mode_wider_vector (vmode);
24035 : 8 : op0 = gen_lowpart (vmode, dest);
24036 : :
24037 : 8 : memset (perm2, elt, 2);
24038 : 8 : dest = gen_reg_rtx (vmode);
24039 : 8 : ok = expand_vselect (dest, op0, perm2, 2, d->testing_p);
24040 : 8 : gcc_assert (ok);
24041 : :
24042 : 8 : emit_move_insn (d->target, gen_lowpart (d->vmode, dest));
24043 : 8 : return true;
24044 : :
24045 : 4 : case E_V8QImode:
24046 : : /* This can be implemented via interleave. We save one insn by
24047 : : stopping once we have promoted to V2SImode and then use pshufd. */
24048 : 4 : if (d->testing_p)
24049 : : return true;
24050 : 4 : do
24051 : : {
24052 : 4 : if (elt >= nelt2)
24053 : : {
24054 : 1 : gen = vmode == V8QImode ? gen_mmx_punpckhbw
24055 : : : gen_mmx_punpckhwd;
24056 : 1 : elt -= nelt2;
24057 : : }
24058 : : else
24059 : 3 : gen = vmode == V8QImode ? gen_mmx_punpcklbw
24060 : : : gen_mmx_punpcklwd;
24061 : 4 : nelt2 /= 2;
24062 : :
24063 : 4 : dest = gen_reg_rtx (vmode);
24064 : 4 : emit_insn (gen (dest, op0, op0));
24065 : 4 : vmode = get_mode_wider_vector (vmode);
24066 : 4 : op0 = gen_lowpart (vmode, dest);
24067 : : }
24068 : 4 : while (vmode != V2SImode);
24069 : :
24070 : 2 : memset (perm2, elt, 2);
24071 : 2 : dest = gen_reg_rtx (vmode);
24072 : 2 : ok = expand_vselect (dest, op0, perm2, 2, d->testing_p);
24073 : 2 : gcc_assert (ok);
24074 : :
24075 : 2 : emit_move_insn (d->target, gen_lowpart (d->vmode, dest));
24076 : 2 : return true;
24077 : :
24078 : 987 : case E_V8HImode:
24079 : 987 : case E_V16QImode:
24080 : : /* These can be implemented via interleave. We save one insn by
24081 : : stopping once we have promoted to V4SImode and then use pshufd. */
24082 : 987 : if (d->testing_p)
24083 : : return true;
24084 : 1547 : do
24085 : : {
24086 : 1547 : if (elt >= nelt2)
24087 : : {
24088 : 16 : gen = vmode == V16QImode ? gen_vec_interleave_highv16qi
24089 : : : gen_vec_interleave_highv8hi;
24090 : 16 : elt -= nelt2;
24091 : : }
24092 : : else
24093 : 1531 : gen = vmode == V16QImode ? gen_vec_interleave_lowv16qi
24094 : : : gen_vec_interleave_lowv8hi;
24095 : 1547 : nelt2 /= 2;
24096 : :
24097 : 1547 : dest = gen_reg_rtx (vmode);
24098 : 1547 : emit_insn (gen (dest, op0, op0));
24099 : 1547 : vmode = get_mode_wider_vector (vmode);
24100 : 1547 : op0 = gen_lowpart (vmode, dest);
24101 : : }
24102 : 1547 : while (vmode != V4SImode);
24103 : :
24104 : 923 : memset (perm2, elt, 4);
24105 : 923 : dest = gen_reg_rtx (vmode);
24106 : 923 : ok = expand_vselect (dest, op0, perm2, 4, d->testing_p);
24107 : 923 : gcc_assert (ok);
24108 : :
24109 : 923 : emit_move_insn (d->target, gen_lowpart (d->vmode, dest));
24110 : 923 : return true;
24111 : :
24112 : 1 : case E_V8HFmode:
24113 : 1 : case E_V8BFmode:
24114 : : /* This can be implemented via interleave and pshufd. */
24115 : 1 : if (d->testing_p)
24116 : : return true;
24117 : :
24118 : 1 : rtx (*gen_interleave) (machine_mode, rtx, rtx, rtx);
24119 : 1 : if (elt >= nelt2)
24120 : : {
24121 : 0 : gen_interleave = gen_vec_interleave_high;
24122 : 0 : elt -= nelt2;
24123 : : }
24124 : : else
24125 : : gen_interleave = gen_vec_interleave_low;
24126 : 1 : nelt2 /= 2;
24127 : :
24128 : 1 : dest = gen_reg_rtx (vmode);
24129 : 1 : emit_insn (gen_interleave (vmode, dest, op0, op0));
24130 : :
24131 : 1 : vmode = V4SImode;
24132 : 1 : op0 = gen_lowpart (vmode, dest);
24133 : :
24134 : 1 : memset (perm2, elt, 4);
24135 : 1 : dest = gen_reg_rtx (vmode);
24136 : 1 : ok = expand_vselect (dest, op0, perm2, 4, d->testing_p);
24137 : 1 : gcc_assert (ok);
24138 : :
24139 : 1 : emit_move_insn (d->target, gen_lowpart (d->vmode, dest));
24140 : 1 : return true;
24141 : :
24142 : 21 : case E_V32QImode:
24143 : 21 : case E_V16HImode:
24144 : 21 : case E_V8SImode:
24145 : 21 : case E_V4DImode:
24146 : : /* For AVX2 broadcasts of the first element vpbroadcast* or
24147 : : vpermq should be used by expand_vec_perm_1. */
24148 : 21 : gcc_assert (!TARGET_AVX2 || d->perm[0]);
24149 : : return false;
24150 : :
24151 : 6 : case E_V64QImode:
24152 : 6 : gcc_assert (!TARGET_AVX512BW || d->perm[0]);
24153 : : return false;
24154 : :
24155 : 2 : case E_V32HImode:
24156 : 2 : gcc_assert (!TARGET_AVX512BW);
24157 : : return false;
24158 : :
24159 : 0 : default:
24160 : 0 : gcc_unreachable ();
24161 : : }
24162 : : }
24163 : :
24164 : : /* A subroutine of ix86_expand_vec_perm_const_1. Pattern match
24165 : : broadcast permutations. */
24166 : :
24167 : : static bool
24168 : 91333 : expand_vec_perm_broadcast (struct expand_vec_perm_d *d)
24169 : : {
24170 : 91333 : unsigned i, elt, nelt = d->nelt;
24171 : :
24172 : 91333 : if (!d->one_operand_p)
24173 : : return false;
24174 : :
24175 : 5153 : elt = d->perm[0];
24176 : 7987 : for (i = 1; i < nelt; ++i)
24177 : 7858 : if (d->perm[i] != elt)
24178 : : return false;
24179 : :
24180 : 129 : return expand_vec_perm_broadcast_1 (d);
24181 : : }
24182 : :
24183 : : /* Implement arbitrary permutations of two V64QImode operands
24184 : : with 2 vperm[it]2w, 2 vpshufb and one vpor instruction. */
24185 : : static bool
24186 : 23432 : expand_vec_perm_vpermt2_vpshub2 (struct expand_vec_perm_d *d)
24187 : : {
24188 : 23432 : if (!TARGET_AVX512BW || !(d->vmode == V64QImode))
24189 : : return false;
24190 : :
24191 : 40 : if (d->testing_p)
24192 : : return true;
24193 : :
24194 : 40 : struct expand_vec_perm_d ds[2];
24195 : 40 : rtx rperm[128], vperm, target0, target1;
24196 : 40 : unsigned int i, nelt;
24197 : 40 : machine_mode vmode;
24198 : :
24199 : 40 : nelt = d->nelt;
24200 : 40 : vmode = V64QImode;
24201 : :
24202 : 120 : for (i = 0; i < 2; i++)
24203 : : {
24204 : 80 : ds[i] = *d;
24205 : 80 : ds[i].vmode = V32HImode;
24206 : 80 : ds[i].nelt = 32;
24207 : 80 : ds[i].target = gen_reg_rtx (V32HImode);
24208 : 80 : ds[i].op0 = gen_lowpart (V32HImode, d->op0);
24209 : 80 : ds[i].op1 = gen_lowpart (V32HImode, d->op1);
24210 : : }
24211 : :
24212 : : /* Prepare permutations such that the first one takes care of
24213 : : putting the even bytes into the right positions or one higher
24214 : : positions (ds[0]) and the second one takes care of
24215 : : putting the odd bytes into the right positions or one below
24216 : : (ds[1]). */
24217 : :
24218 : 2600 : for (i = 0; i < nelt; i++)
24219 : : {
24220 : 2560 : ds[i & 1].perm[i / 2] = d->perm[i] / 2;
24221 : 2560 : if (i & 1)
24222 : : {
24223 : 1280 : rperm[i] = constm1_rtx;
24224 : 1280 : rperm[i + 64] = GEN_INT ((i & 14) + (d->perm[i] & 1));
24225 : : }
24226 : : else
24227 : : {
24228 : 1280 : rperm[i] = GEN_INT ((i & 14) + (d->perm[i] & 1));
24229 : 1280 : rperm[i + 64] = constm1_rtx;
24230 : : }
24231 : : }
24232 : :
24233 : 40 : bool ok = expand_vec_perm_1 (&ds[0]);
24234 : 40 : gcc_assert (ok);
24235 : 40 : ds[0].target = gen_lowpart (V64QImode, ds[0].target);
24236 : :
24237 : 40 : ok = expand_vec_perm_1 (&ds[1]);
24238 : 40 : gcc_assert (ok);
24239 : 40 : ds[1].target = gen_lowpart (V64QImode, ds[1].target);
24240 : :
24241 : 40 : vperm = gen_rtx_CONST_VECTOR (V64QImode, gen_rtvec_v (64, rperm));
24242 : 40 : vperm = force_reg (vmode, vperm);
24243 : 40 : target0 = gen_reg_rtx (V64QImode);
24244 : 40 : emit_insn (gen_avx512bw_pshufbv64qi3 (target0, ds[0].target, vperm));
24245 : :
24246 : 40 : vperm = gen_rtx_CONST_VECTOR (V64QImode, gen_rtvec_v (64, rperm + 64));
24247 : 40 : vperm = force_reg (vmode, vperm);
24248 : 40 : target1 = gen_reg_rtx (V64QImode);
24249 : 40 : emit_insn (gen_avx512bw_pshufbv64qi3 (target1, ds[1].target, vperm));
24250 : :
24251 : 40 : emit_insn (gen_iorv64qi3 (d->target, target0, target1));
24252 : 40 : return true;
24253 : : }
24254 : :
24255 : : /* Implement arbitrary permutation of two V32QImode and V16QImode operands
24256 : : with 4 vpshufb insns, 2 vpermq and 3 vpor. We should have already failed
24257 : : all the shorter instruction sequences. */
24258 : :
24259 : : static bool
24260 : 15500 : expand_vec_perm_vpshufb4_vpermq2 (struct expand_vec_perm_d *d)
24261 : : {
24262 : 15500 : rtx rperm[4][32], vperm, l[2], h[2], op, m128;
24263 : 15500 : unsigned int i, nelt, eltsz;
24264 : 15500 : bool used[4];
24265 : :
24266 : 15500 : if (!TARGET_AVX2
24267 : 321 : || d->one_operand_p
24268 : 192 : || (d->vmode != V32QImode && d->vmode != V16HImode))
24269 : : return false;
24270 : :
24271 : 54 : if (d->testing_p)
24272 : : return true;
24273 : :
24274 : 54 : nelt = d->nelt;
24275 : 54 : eltsz = GET_MODE_UNIT_SIZE (d->vmode);
24276 : :
24277 : : /* Generate 4 permutation masks. If the required element is within
24278 : : the same lane, it is shuffled in. If the required element from the
24279 : : other lane, force a zero by setting bit 7 in the permutation mask.
24280 : : In the other mask the mask has non-negative elements if element
24281 : : is requested from the other lane, but also moved to the other lane,
24282 : : so that the result of vpshufb can have the two V2TImode halves
24283 : : swapped. */
24284 : 54 : m128 = GEN_INT (-128);
24285 : 1836 : for (i = 0; i < 32; ++i)
24286 : : {
24287 : 1728 : rperm[0][i] = m128;
24288 : 1728 : rperm[1][i] = m128;
24289 : 1728 : rperm[2][i] = m128;
24290 : 1728 : rperm[3][i] = m128;
24291 : : }
24292 : 54 : used[0] = false;
24293 : 54 : used[1] = false;
24294 : 54 : used[2] = false;
24295 : 54 : used[3] = false;
24296 : 1590 : for (i = 0; i < nelt; ++i)
24297 : : {
24298 : 1536 : unsigned j, e = d->perm[i] & (nelt / 2 - 1);
24299 : 1536 : unsigned xlane = ((d->perm[i] ^ i) & (nelt / 2)) * eltsz;
24300 : 2074 : unsigned int which = ((d->perm[i] & nelt) ? 2 : 0) + (xlane ? 1 : 0);
24301 : :
24302 : 3264 : for (j = 0; j < eltsz; ++j)
24303 : 1728 : rperm[which][(i * eltsz + j) ^ xlane] = GEN_INT (e * eltsz + j);
24304 : 1536 : used[which] = true;
24305 : : }
24306 : :
24307 : 162 : for (i = 0; i < 2; ++i)
24308 : : {
24309 : 108 : if (!used[2 * i + 1])
24310 : : {
24311 : 22 : h[i] = NULL_RTX;
24312 : 22 : continue;
24313 : : }
24314 : 86 : vperm = gen_rtx_CONST_VECTOR (V32QImode,
24315 : 86 : gen_rtvec_v (32, rperm[2 * i + 1]));
24316 : 86 : vperm = force_reg (V32QImode, vperm);
24317 : 86 : h[i] = gen_reg_rtx (V32QImode);
24318 : 86 : op = gen_lowpart (V32QImode, i ? d->op1 : d->op0);
24319 : 86 : emit_insn (gen_avx2_pshufbv32qi3 (h[i], op, vperm));
24320 : : }
24321 : :
24322 : : /* Swap the 128-byte lanes of h[X]. */
24323 : 162 : for (i = 0; i < 2; ++i)
24324 : : {
24325 : 108 : if (h[i] == NULL_RTX)
24326 : 22 : continue;
24327 : 86 : op = gen_reg_rtx (V4DImode);
24328 : 86 : emit_insn (gen_avx2_permv4di_1 (op, gen_lowpart (V4DImode, h[i]),
24329 : : const2_rtx, GEN_INT (3), const0_rtx,
24330 : : const1_rtx));
24331 : 86 : h[i] = gen_lowpart (V32QImode, op);
24332 : : }
24333 : :
24334 : 162 : for (i = 0; i < 2; ++i)
24335 : : {
24336 : 108 : if (!used[2 * i])
24337 : : {
24338 : 0 : l[i] = NULL_RTX;
24339 : 0 : continue;
24340 : : }
24341 : 108 : vperm = gen_rtx_CONST_VECTOR (V32QImode, gen_rtvec_v (32, rperm[2 * i]));
24342 : 108 : vperm = force_reg (V32QImode, vperm);
24343 : 108 : l[i] = gen_reg_rtx (V32QImode);
24344 : 108 : op = gen_lowpart (V32QImode, i ? d->op1 : d->op0);
24345 : 108 : emit_insn (gen_avx2_pshufbv32qi3 (l[i], op, vperm));
24346 : : }
24347 : :
24348 : 162 : for (i = 0; i < 2; ++i)
24349 : : {
24350 : 108 : if (h[i] && l[i])
24351 : : {
24352 : 86 : op = gen_reg_rtx (V32QImode);
24353 : 86 : emit_insn (gen_iorv32qi3 (op, l[i], h[i]));
24354 : 86 : l[i] = op;
24355 : : }
24356 : 22 : else if (h[i])
24357 : 0 : l[i] = h[i];
24358 : : }
24359 : :
24360 : 54 : gcc_assert (l[0] && l[1]);
24361 : 54 : op = d->target;
24362 : 54 : if (d->vmode != V32QImode)
24363 : 12 : op = gen_reg_rtx (V32QImode);
24364 : 54 : emit_insn (gen_iorv32qi3 (op, l[0], l[1]));
24365 : 54 : if (op != d->target)
24366 : 12 : emit_move_insn (d->target, gen_lowpart (d->vmode, op));
24367 : : return true;
24368 : : }
24369 : :
24370 : : /* The guts of ix86_vectorize_vec_perm_const. With all of the interface bits
24371 : : taken care of, perform the expansion in D and return true on success. */
24372 : :
24373 : : static bool
24374 : 300030 : ix86_expand_vec_perm_const_1 (struct expand_vec_perm_d *d)
24375 : : {
24376 : : /* Try a single instruction expansion. */
24377 : 300030 : if (expand_vec_perm_1 (d))
24378 : : return true;
24379 : :
24380 : : /* Try sequences of two instructions. */
24381 : :
24382 : 103759 : if (expand_vec_perm_pshuflw_pshufhw (d))
24383 : : return true;
24384 : :
24385 : 100972 : if (expand_vec_perm_palignr (d, false))
24386 : : return true;
24387 : :
24388 : 97841 : if (expand_vec_perm_interleave2 (d))
24389 : : return true;
24390 : :
24391 : 91333 : if (expand_vec_perm_broadcast (d))
24392 : : return true;
24393 : :
24394 : 91233 : if (expand_vec_perm_vpermq_perm_1 (d))
24395 : : return true;
24396 : :
24397 : 91233 : if (expand_vec_perm_vperm2f128 (d))
24398 : : return true;
24399 : :
24400 : 91186 : if (expand_vec_perm_pblendv (d))
24401 : : return true;
24402 : :
24403 : 89457 : if (expand_vec_perm_2perm_interleave (d, true))
24404 : : return true;
24405 : :
24406 : 89097 : if (expand_vec_perm_2perm_pblendv (d, true))
24407 : : return true;
24408 : :
24409 : 86068 : if (expand_vec_perm_shufps_shufps (d))
24410 : : return true;
24411 : :
24412 : 49204 : if (expand_vec_perm_punpckldq_pshuf (d))
24413 : : return true;
24414 : :
24415 : : /* Try sequences of three instructions. */
24416 : :
24417 : 43428 : if (expand_vec_perm_even_odd_pack (d))
24418 : : return true;
24419 : :
24420 : 29720 : if (expand_vec_perm_2vperm2f128_vshuf (d))
24421 : : return true;
24422 : :
24423 : 28063 : if (expand_vec_perm_pshufb2 (d))
24424 : : return true;
24425 : :
24426 : 27350 : if (expand_vec_perm_pslldq_psrldq_por (d, false))
24427 : : return true;
24428 : :
24429 : 27163 : if (expand_vec_perm_interleave3 (d))
24430 : : return true;
24431 : :
24432 : 27025 : if (expand_vec_perm_vperm2f128_vblend (d))
24433 : : return true;
24434 : :
24435 : 27025 : if (expand_vec_perm_2perm_interleave (d, false))
24436 : : return true;
24437 : :
24438 : 26785 : if (expand_vec_perm_2perm_pblendv (d, false))
24439 : : return true;
24440 : :
24441 : 25957 : if (expand_vec_perm_psrlw_psllw_por (d))
24442 : : return true;
24443 : :
24444 : 24459 : if (expand_vec_perm_pand_pandn_por (d))
24445 : : return true;
24446 : :
24447 : : /* Try sequences of four instructions. */
24448 : :
24449 : 23442 : if (expand_vec_perm_even_odd_trunc (d))
24450 : : return true;
24451 : 23438 : if (expand_vec_perm_vpshufb2_vpermq (d))
24452 : : return true;
24453 : :
24454 : 23432 : if (expand_vec_perm_vpshufb2_vpermq_even_odd (d))
24455 : : return true;
24456 : :
24457 : 23432 : if (expand_vec_perm_vpermt2_vpshub2 (d))
24458 : : return true;
24459 : :
24460 : : /* ??? Look for narrow permutations whose element orderings would
24461 : : allow the promotion to a wider mode. */
24462 : :
24463 : : /* ??? Look for sequences of interleave or a wider permute that place
24464 : : the data into the correct lanes for a half-vector shuffle like
24465 : : pshuf[lh]w or vpermilps. */
24466 : :
24467 : : /* ??? Look for sequences of interleave that produce the desired results.
24468 : : The combinatorics of punpck[lh] get pretty ugly... */
24469 : :
24470 : 23392 : if (expand_vec_perm_even_odd (d))
24471 : : return true;
24472 : :
24473 : : /* Generate four or five instructions. */
24474 : 15724 : if (expand_vec_perm_pslldq_psrldq_por (d, true))
24475 : : return true;
24476 : :
24477 : : /* Even longer sequences. */
24478 : 15500 : if (expand_vec_perm_vpshufb4_vpermq2 (d))
24479 : : return true;
24480 : :
24481 : : /* See if we can get the same permutation in different vector integer
24482 : : mode. */
24483 : 15446 : struct expand_vec_perm_d nd;
24484 : 15446 : if (canonicalize_vector_int_perm (d, &nd) && expand_vec_perm_1 (&nd))
24485 : : {
24486 : 0 : if (!d->testing_p)
24487 : 0 : emit_move_insn (d->target, gen_lowpart (d->vmode, nd.target));
24488 : 0 : return true;
24489 : : }
24490 : :
24491 : : /* Even longer, including recursion to ix86_expand_vec_perm_const_1. */
24492 : 15446 : if (expand_vec_perm2_vperm2f128_vblend (d))
24493 : : return true;
24494 : :
24495 : : return false;
24496 : : }
24497 : :
24498 : : /* If a permutation only uses one operand, make it clear. Returns true
24499 : : if the permutation references both operands. */
24500 : :
24501 : : static bool
24502 : 69162 : canonicalize_perm (struct expand_vec_perm_d *d)
24503 : : {
24504 : 69162 : int i, which, nelt = d->nelt;
24505 : :
24506 : 427576 : for (i = which = 0; i < nelt; ++i)
24507 : 488560 : which |= (d->perm[i] < nelt ? 1 : 2);
24508 : :
24509 : 69162 : d->one_operand_p = true;
24510 : 69162 : switch (which)
24511 : : {
24512 : 0 : default:
24513 : 0 : gcc_unreachable();
24514 : :
24515 : 52499 : case 3:
24516 : 52499 : if (!rtx_equal_p (d->op0, d->op1))
24517 : : {
24518 : 52448 : d->one_operand_p = false;
24519 : 52448 : break;
24520 : : }
24521 : : /* The elements of PERM do not suggest that only the first operand
24522 : : is used, but both operands are identical. Allow easier matching
24523 : : of the permutation by folding the permutation into the single
24524 : : input vector. */
24525 : : /* FALLTHRU */
24526 : :
24527 : : case 2:
24528 : 2913 : for (i = 0; i < nelt; ++i)
24529 : 2576 : d->perm[i] &= nelt - 1;
24530 : 337 : d->op0 = d->op1;
24531 : 337 : break;
24532 : :
24533 : 16377 : case 1:
24534 : 16377 : d->op1 = d->op0;
24535 : 16377 : break;
24536 : : }
24537 : :
24538 : 69162 : return (which == 3);
24539 : : }
24540 : :
24541 : : /* Implement TARGET_VECTORIZE_VEC_PERM_CONST. */
24542 : :
24543 : : bool
24544 : 816857 : ix86_vectorize_vec_perm_const (machine_mode vmode, machine_mode op_mode,
24545 : : rtx target, rtx op0, rtx op1,
24546 : : const vec_perm_indices &sel)
24547 : : {
24548 : 816857 : if (vmode != op_mode)
24549 : : return false;
24550 : :
24551 : 815198 : struct expand_vec_perm_d d;
24552 : 815198 : unsigned char perm[MAX_VECT_LEN];
24553 : 815198 : unsigned int i, nelt, which;
24554 : 815198 : bool two_args;
24555 : :
24556 : : /* For HF and BF mode vector, convert it to HI using subreg. */
24557 : 2445124 : if (GET_MODE_INNER (vmode) == HFmode || GET_MODE_INNER (vmode) == BFmode)
24558 : : {
24559 : 495 : machine_mode orig_mode = vmode;
24560 : 990 : vmode = mode_for_vector (HImode,
24561 : 495 : GET_MODE_NUNITS (vmode)).require ();
24562 : 495 : if (target)
24563 : 431 : target = lowpart_subreg (vmode, target, orig_mode);
24564 : 495 : if (op0)
24565 : 431 : op0 = lowpart_subreg (vmode, op0, orig_mode);
24566 : 495 : if (op1)
24567 : 431 : op1 = lowpart_subreg (vmode, op1, orig_mode);
24568 : : }
24569 : :
24570 : 815198 : d.target = target;
24571 : 815198 : d.op0 = op0;
24572 : 815198 : d.op1 = op1;
24573 : :
24574 : 815198 : d.vmode = vmode;
24575 : 815198 : gcc_assert (VECTOR_MODE_P (d.vmode));
24576 : 815198 : d.nelt = nelt = GET_MODE_NUNITS (d.vmode);
24577 : 815198 : d.testing_p = !target;
24578 : :
24579 : 815198 : gcc_assert (sel.length () == nelt);
24580 : 815198 : gcc_checking_assert (sizeof (d.perm) == sizeof (perm));
24581 : :
24582 : : /* Given sufficient ISA support we can just return true here
24583 : : for selected vector modes. */
24584 : 815198 : switch (d.vmode)
24585 : : {
24586 : 1986 : case E_V16SFmode:
24587 : 1986 : case E_V16SImode:
24588 : 1986 : case E_V8DImode:
24589 : 1986 : case E_V8DFmode:
24590 : 1986 : if (!TARGET_AVX512F)
24591 : : return false;
24592 : : /* All implementable with a single vperm[it]2 insn. */
24593 : 1986 : if (d.testing_p)
24594 : : return true;
24595 : : break;
24596 : 323 : case E_V32HImode:
24597 : 323 : if (!TARGET_AVX512F)
24598 : : return false;
24599 : 323 : if (d.testing_p && TARGET_AVX512BW)
24600 : : /* All implementable with a single vperm[it]2 insn. */
24601 : : return true;
24602 : : break;
24603 : 562 : case E_V64QImode:
24604 : 562 : if (!TARGET_AVX512F)
24605 : : return false;
24606 : 562 : if (d.testing_p && TARGET_AVX512BW)
24607 : : /* Implementable with 2 vperm[it]2, 2 vpshufb and 1 or insn. */
24608 : : return true;
24609 : : break;
24610 : 8958 : case E_V8SImode:
24611 : 8958 : case E_V8SFmode:
24612 : 8958 : case E_V4DFmode:
24613 : 8958 : case E_V4DImode:
24614 : 8958 : if (!TARGET_AVX)
24615 : : return false;
24616 : 8958 : if (d.testing_p && TARGET_AVX512VL)
24617 : : /* All implementable with a single vperm[it]2 insn. */
24618 : : return true;
24619 : : break;
24620 : 593 : case E_V16HImode:
24621 : 593 : if (!TARGET_SSE2)
24622 : : return false;
24623 : 593 : if (d.testing_p && TARGET_AVX2)
24624 : : /* Implementable with 4 vpshufb insns, 2 vpermq and 3 vpor insns. */
24625 : : return true;
24626 : : break;
24627 : 686 : case E_V32QImode:
24628 : 686 : if (!TARGET_SSE2)
24629 : : return false;
24630 : 686 : if (d.testing_p && TARGET_AVX2)
24631 : : /* Implementable with 4 vpshufb insns, 2 vpermq and 3 vpor insns. */
24632 : : return true;
24633 : : break;
24634 : 38541 : case E_V8HImode:
24635 : 38541 : case E_V16QImode:
24636 : 38541 : if (!TARGET_SSE2)
24637 : : return false;
24638 : : /* Fall through. */
24639 : 243634 : case E_V4SImode:
24640 : 243634 : case E_V4SFmode:
24641 : 243634 : if (!TARGET_SSE)
24642 : : return false;
24643 : : /* All implementable with a single vpperm insn. */
24644 : 243634 : if (d.testing_p && TARGET_XOP)
24645 : : return true;
24646 : : /* All implementable with 2 pshufb + 1 ior. */
24647 : 243528 : if (d.testing_p && TARGET_SSSE3)
24648 : : return true;
24649 : : break;
24650 : 133023 : case E_V2SFmode:
24651 : 133023 : case E_V2SImode:
24652 : 133023 : case E_V4HImode:
24653 : 133023 : case E_V8QImode:
24654 : 133023 : if (!TARGET_MMX_WITH_SSE)
24655 : : return false;
24656 : : break;
24657 : 26738 : case E_V2HImode:
24658 : 26738 : if (!TARGET_SSE2)
24659 : : return false;
24660 : : /* All implementable with *punpckwd. */
24661 : 26738 : if (d.testing_p)
24662 : : return true;
24663 : : break;
24664 : 9679 : case E_V4QImode:
24665 : 9679 : if (!TARGET_SSE2)
24666 : : return false;
24667 : : break;
24668 : 385741 : case E_V2DImode:
24669 : 385741 : case E_V2DFmode:
24670 : 385741 : if (!TARGET_SSE)
24671 : : return false;
24672 : : /* All implementable with shufpd or unpck[lh]pd. */
24673 : 385741 : if (d.testing_p)
24674 : : return true;
24675 : : break;
24676 : : default:
24677 : : return false;
24678 : : }
24679 : :
24680 : 2205864 : for (i = which = 0; i < nelt; ++i)
24681 : : {
24682 : 1806754 : unsigned char e = sel[i];
24683 : 1806754 : gcc_assert (e < 2 * nelt);
24684 : 1806754 : d.perm[i] = e;
24685 : 1806754 : perm[i] = e;
24686 : 2456166 : which |= (e < nelt ? 1 : 2);
24687 : : }
24688 : :
24689 : 399110 : if (d.testing_p)
24690 : : {
24691 : : /* For all elements from second vector, fold the elements to first. */
24692 : 331647 : if (which == 2)
24693 : 1345 : for (i = 0; i < nelt; ++i)
24694 : 1240 : d.perm[i] -= nelt;
24695 : :
24696 : : /* Check whether the mask can be applied to the vector type. */
24697 : 331647 : d.one_operand_p = (which != 3);
24698 : :
24699 : : /* Implementable with shufps, pshufd or pshuflw. */
24700 : 331647 : if (d.one_operand_p
24701 : : && (d.vmode == V4SFmode || d.vmode == V2SFmode
24702 : : || d.vmode == V4SImode || d.vmode == V2SImode
24703 : : || d.vmode == V4HImode || d.vmode == V2HImode))
24704 : : return true;
24705 : :
24706 : : /* Otherwise we have to go through the motions and see if we can
24707 : : figure out how to generate the requested permutation. */
24708 : 228104 : d.target = gen_raw_REG (d.vmode, LAST_VIRTUAL_REGISTER + 1);
24709 : 228104 : d.op1 = d.op0 = gen_raw_REG (d.vmode, LAST_VIRTUAL_REGISTER + 2);
24710 : 228104 : if (!d.one_operand_p)
24711 : 218089 : d.op1 = gen_raw_REG (d.vmode, LAST_VIRTUAL_REGISTER + 3);
24712 : :
24713 : 228104 : start_sequence ();
24714 : 228104 : bool ret = ix86_expand_vec_perm_const_1 (&d);
24715 : 228104 : end_sequence ();
24716 : :
24717 : 228104 : return ret;
24718 : : }
24719 : :
24720 : 67463 : two_args = canonicalize_perm (&d);
24721 : :
24722 : : /* If one of the operands is a zero vector, try to match pmovzx. */
24723 : 67463 : if (two_args && (d.op0 == CONST0_RTX (vmode) || d.op1 == CONST0_RTX (vmode)))
24724 : : {
24725 : 565 : struct expand_vec_perm_d dzero = d;
24726 : 565 : if (d.op0 == CONST0_RTX (vmode))
24727 : : {
24728 : 387 : d.op1 = dzero.op1 = force_reg (vmode, d.op1);
24729 : 387 : std::swap (dzero.op0, dzero.op1);
24730 : 7527 : for (i = 0; i < nelt; ++i)
24731 : 7140 : dzero.perm[i] ^= nelt;
24732 : : }
24733 : : else
24734 : 178 : d.op0 = dzero.op0 = force_reg (vmode, d.op0);
24735 : :
24736 : 565 : if (expand_vselect_vconcat (dzero.target, dzero.op0, dzero.op1,
24737 : 565 : dzero.perm, nelt, dzero.testing_p))
24738 : 116 : return true;
24739 : : }
24740 : :
24741 : : /* Force operands into registers. */
24742 : 67347 : rtx nop0 = force_reg (vmode, d.op0);
24743 : 67347 : if (d.op0 == d.op1)
24744 : 16217 : d.op1 = nop0;
24745 : 67347 : d.op0 = nop0;
24746 : 67347 : d.op1 = force_reg (vmode, d.op1);
24747 : :
24748 : 67347 : if (ix86_expand_vec_perm_const_1 (&d))
24749 : : return true;
24750 : :
24751 : : /* If the selector says both arguments are needed, but the operands are the
24752 : : same, the above tried to expand with one_operand_p and flattened selector.
24753 : : If that didn't work, retry without one_operand_p; we succeeded with that
24754 : : during testing. */
24755 : 22 : if (two_args && d.one_operand_p)
24756 : : {
24757 : 22 : d.one_operand_p = false;
24758 : 22 : memcpy (d.perm, perm, sizeof (perm));
24759 : 22 : return ix86_expand_vec_perm_const_1 (&d);
24760 : : }
24761 : :
24762 : : return false;
24763 : : }
24764 : :
24765 : : void
24766 : 7794 : ix86_expand_vec_extract_even_odd (rtx targ, rtx op0, rtx op1, unsigned odd)
24767 : : {
24768 : 7794 : struct expand_vec_perm_d d;
24769 : 7794 : unsigned i, nelt;
24770 : :
24771 : 7794 : d.target = targ;
24772 : 7794 : d.op0 = op0;
24773 : 7794 : d.op1 = op1;
24774 : 7794 : d.vmode = GET_MODE (targ);
24775 : 7794 : d.nelt = nelt = GET_MODE_NUNITS (d.vmode);
24776 : 7794 : d.one_operand_p = false;
24777 : 7794 : d.testing_p = false;
24778 : :
24779 : 74454 : for (i = 0; i < nelt; ++i)
24780 : 66660 : d.perm[i] = i * 2 + odd;
24781 : :
24782 : : /* We'll either be able to implement the permutation directly... */
24783 : 7794 : if (expand_vec_perm_1 (&d))
24784 : 3084 : return;
24785 : :
24786 : : /* ... or we use the special-case patterns. */
24787 : 4710 : expand_vec_perm_even_odd_1 (&d, odd);
24788 : : }
24789 : :
24790 : : static void
24791 : 854 : ix86_expand_vec_interleave (rtx targ, rtx op0, rtx op1, bool high_p)
24792 : : {
24793 : 854 : struct expand_vec_perm_d d;
24794 : 854 : unsigned i, nelt, base;
24795 : 854 : bool ok;
24796 : :
24797 : 854 : d.target = targ;
24798 : 854 : d.op0 = op0;
24799 : 854 : d.op1 = op1;
24800 : 854 : d.vmode = GET_MODE (targ);
24801 : 854 : d.nelt = nelt = GET_MODE_NUNITS (d.vmode);
24802 : 854 : d.one_operand_p = false;
24803 : 854 : d.testing_p = false;
24804 : :
24805 : 854 : base = high_p ? nelt / 2 : 0;
24806 : 3398 : for (i = 0; i < nelt / 2; ++i)
24807 : : {
24808 : 2544 : d.perm[i * 2] = i + base;
24809 : 2544 : d.perm[i * 2 + 1] = i + base + nelt;
24810 : : }
24811 : :
24812 : : /* Note that for AVX this isn't one instruction. */
24813 : 854 : ok = ix86_expand_vec_perm_const_1 (&d);
24814 : 854 : gcc_assert (ok);
24815 : 854 : }
24816 : :
24817 : : /* Expand a vector operation shift by constant for a V*QImode in terms of the
24818 : : same operation on V*HImode. Return true if success. */
24819 : : static bool
24820 : 334 : ix86_expand_vec_shift_qihi_constant (enum rtx_code code,
24821 : : rtx dest, rtx op1, rtx op2)
24822 : : {
24823 : 334 : machine_mode qimode, himode;
24824 : 334 : HOST_WIDE_INT and_constant, xor_constant;
24825 : 334 : HOST_WIDE_INT shift_amount;
24826 : 334 : rtx vec_const_and, vec_const_xor;
24827 : 334 : rtx tmp, op1_subreg;
24828 : 334 : rtx (*gen_shift) (rtx, rtx, rtx);
24829 : 334 : rtx (*gen_and) (rtx, rtx, rtx);
24830 : 334 : rtx (*gen_xor) (rtx, rtx, rtx);
24831 : 334 : rtx (*gen_sub) (rtx, rtx, rtx);
24832 : :
24833 : : /* Only optimize shift by constant. */
24834 : 334 : if (!CONST_INT_P (op2))
24835 : : return false;
24836 : :
24837 : 334 : qimode = GET_MODE (dest);
24838 : 334 : shift_amount = INTVAL (op2);
24839 : : /* Do nothing when shift amount greater equal 8. */
24840 : 334 : if (shift_amount > 7)
24841 : : return false;
24842 : :
24843 : 334 : gcc_assert (code == ASHIFT || code == ASHIFTRT || code == LSHIFTRT);
24844 : :
24845 : :
24846 : 334 : if (shift_amount == 7
24847 : 334 : && code == ASHIFTRT)
24848 : : {
24849 : 26 : if (qimode == V16QImode
24850 : 8 : || qimode == V32QImode)
24851 : : {
24852 : 25 : rtx zero = gen_reg_rtx (qimode);
24853 : 25 : emit_move_insn (zero, CONST0_RTX (qimode));
24854 : 25 : emit_move_insn (dest, gen_rtx_fmt_ee (GT, qimode, zero, op1));
24855 : 25 : }
24856 : : else
24857 : : {
24858 : 1 : gcc_assert (qimode == V64QImode);
24859 : 1 : rtx kmask = gen_reg_rtx (DImode);
24860 : 1 : emit_insn (gen_avx512bw_cvtb2maskv64qi (kmask, op1));
24861 : 1 : emit_insn (gen_avx512bw_cvtmask2bv64qi (dest, kmask));
24862 : : }
24863 : 26 : return true;
24864 : : }
24865 : :
24866 : : /* Record sign bit. */
24867 : 308 : xor_constant = 1 << (8 - shift_amount - 1);
24868 : :
24869 : : /* Zero upper/lower bits shift from left/right element. */
24870 : 308 : and_constant
24871 : 308 : = (code == ASHIFT ? 256 - (1 << shift_amount)
24872 : 290 : : (1 << (8 - shift_amount)) - 1);
24873 : :
24874 : 308 : switch (qimode)
24875 : : {
24876 : 295 : case V16QImode:
24877 : 295 : himode = V8HImode;
24878 : 257 : gen_shift =
24879 : : ((code == ASHIFT)
24880 : 295 : ? gen_ashlv8hi3
24881 : 286 : : (code == ASHIFTRT) ? gen_ashrv8hi3 : gen_lshrv8hi3);
24882 : : gen_and = gen_andv16qi3;
24883 : : gen_xor = gen_xorv16qi3;
24884 : : gen_sub = gen_subv16qi3;
24885 : : break;
24886 : 5 : case V32QImode:
24887 : 5 : himode = V16HImode;
24888 : 1 : gen_shift =
24889 : : ((code == ASHIFT)
24890 : 5 : ? gen_ashlv16hi3
24891 : 2 : : (code == ASHIFTRT) ? gen_ashrv16hi3 : gen_lshrv16hi3);
24892 : : gen_and = gen_andv32qi3;
24893 : : gen_xor = gen_xorv32qi3;
24894 : : gen_sub = gen_subv32qi3;
24895 : : break;
24896 : 8 : case V64QImode:
24897 : 8 : himode = V32HImode;
24898 : 1 : gen_shift =
24899 : : ((code == ASHIFT)
24900 : 8 : ? gen_ashlv32hi3
24901 : 2 : : (code == ASHIFTRT) ? gen_ashrv32hi3 : gen_lshrv32hi3);
24902 : : gen_and = gen_andv64qi3;
24903 : : gen_xor = gen_xorv64qi3;
24904 : : gen_sub = gen_subv64qi3;
24905 : : break;
24906 : 0 : default:
24907 : 0 : gcc_unreachable ();
24908 : : }
24909 : :
24910 : 308 : tmp = gen_reg_rtx (himode);
24911 : 308 : vec_const_and = gen_reg_rtx (qimode);
24912 : 308 : op1_subreg = lowpart_subreg (himode, op1, qimode);
24913 : :
24914 : : /* For ASHIFT and LSHIFTRT, perform operation like
24915 : : vpsllw/vpsrlw $shift_amount, %op1, %dest.
24916 : : vpand %vec_const_and, %dest. */
24917 : 308 : emit_insn (gen_shift (tmp, op1_subreg, op2));
24918 : 308 : emit_move_insn (dest, simplify_gen_subreg (qimode, tmp, himode, 0));
24919 : 308 : emit_move_insn (vec_const_and,
24920 : : ix86_build_const_vector (qimode, true,
24921 : 308 : gen_int_mode (and_constant, QImode)));
24922 : 308 : emit_insn (gen_and (dest, dest, vec_const_and));
24923 : :
24924 : : /* For ASHIFTRT, perform extra operation like
24925 : : vpxor %vec_const_xor, %dest, %dest
24926 : : vpsubb %vec_const_xor, %dest, %dest */
24927 : 308 : if (code == ASHIFTRT)
24928 : : {
24929 : 31 : vec_const_xor = gen_reg_rtx (qimode);
24930 : 31 : emit_move_insn (vec_const_xor,
24931 : : ix86_build_const_vector (qimode, true,
24932 : 31 : gen_int_mode (xor_constant, QImode)));
24933 : 31 : emit_insn (gen_xor (dest, dest, vec_const_xor));
24934 : 31 : emit_insn (gen_sub (dest, dest, vec_const_xor));
24935 : : }
24936 : : return true;
24937 : : }
24938 : :
24939 : : void
24940 : 1374 : ix86_expand_vecop_qihi_partial (enum rtx_code code, rtx dest, rtx op1, rtx op2)
24941 : : {
24942 : 1374 : machine_mode qimode = GET_MODE (dest);
24943 : 1374 : rtx qop1, qop2, hop1, hop2, qdest, hdest;
24944 : 1374 : bool op2vec = GET_MODE_CLASS (GET_MODE (op2)) == MODE_VECTOR_INT;
24945 : 1374 : bool uns_p = code != ASHIFTRT;
24946 : :
24947 : 1374 : switch (qimode)
24948 : : {
24949 : 1374 : case E_V4QImode:
24950 : 1374 : case E_V8QImode:
24951 : 1374 : break;
24952 : 0 : default:
24953 : 0 : gcc_unreachable ();
24954 : : }
24955 : :
24956 : 1374 : qop1 = lowpart_subreg (V16QImode, force_reg (qimode, op1), qimode);
24957 : :
24958 : 1374 : if (op2vec)
24959 : 1320 : qop2 = lowpart_subreg (V16QImode, force_reg (qimode, op2), qimode);
24960 : : else
24961 : : qop2 = op2;
24962 : :
24963 : 1374 : qdest = gen_reg_rtx (V16QImode);
24964 : :
24965 : 1374 : if (CONST_INT_P (op2)
24966 : 42 : && (code == ASHIFT || code == LSHIFTRT || code == ASHIFTRT)
24967 : : /* With AVX512 it's cheaper to do vpmovsxbw/op/vpmovwb.
24968 : : Even with SSE4.1 the alternative is better. */
24969 : 42 : && !TARGET_SSE4_1
24970 : 1404 : && ix86_expand_vec_shift_qihi_constant (code, qdest, qop1, qop2))
24971 : : {
24972 : 30 : emit_move_insn (dest, gen_lowpart (qimode, qdest));
24973 : 30 : return;
24974 : : }
24975 : :
24976 : 1344 : if (CONST_INT_P (op2)
24977 : 12 : && code == ASHIFTRT
24978 : 6 : && INTVAL (op2) == 7)
24979 : : {
24980 : 2 : rtx zero = gen_reg_rtx (qimode);
24981 : 2 : emit_move_insn (zero, CONST0_RTX (qimode));
24982 : 2 : emit_move_insn (dest, gen_rtx_fmt_ee (GT, qimode, zero, op1));
24983 : 2 : return;
24984 : : }
24985 : :
24986 : 1342 : switch (code)
24987 : : {
24988 : 1307 : case MULT:
24989 : 1307 : gcc_assert (op2vec);
24990 : 1307 : if (!TARGET_SSE4_1)
24991 : : {
24992 : : /* Unpack data such that we've got a source byte in each low byte
24993 : : of each word. We don't care what goes into the high byte of
24994 : : each word. Rather than trying to get zero in there, most
24995 : : convenient is to let it be a copy of the low byte. */
24996 : 242 : hop1 = copy_to_reg (qop1);
24997 : 242 : hop2 = copy_to_reg (qop2);
24998 : 242 : emit_insn (gen_vec_interleave_lowv16qi (hop1, hop1, hop1));
24999 : 242 : emit_insn (gen_vec_interleave_lowv16qi (hop2, hop2, hop2));
25000 : 242 : break;
25001 : : }
25002 : : /* FALLTHRU */
25003 : 1100 : case ASHIFT:
25004 : 1100 : case ASHIFTRT:
25005 : 1100 : case LSHIFTRT:
25006 : 1100 : hop1 = gen_reg_rtx (V8HImode);
25007 : 1100 : ix86_expand_sse_unpack (hop1, qop1, uns_p, false);
25008 : : /* mult/vashr/vlshr/vashl */
25009 : 1100 : if (op2vec)
25010 : : {
25011 : 1078 : hop2 = gen_reg_rtx (V8HImode);
25012 : 1078 : ix86_expand_sse_unpack (hop2, qop2, uns_p, false);
25013 : : }
25014 : : else
25015 : : hop2 = qop2;
25016 : :
25017 : : break;
25018 : 0 : default:
25019 : 0 : gcc_unreachable ();
25020 : : }
25021 : :
25022 : 1342 : if (code != MULT && op2vec)
25023 : : {
25024 : : /* Expand vashr/vlshr/vashl. */
25025 : 13 : hdest = gen_reg_rtx (V8HImode);
25026 : 13 : emit_insn (gen_rtx_SET (hdest,
25027 : : simplify_gen_binary (code, V8HImode,
25028 : : hop1, hop2)));
25029 : : }
25030 : : else
25031 : : /* Expand mult/ashr/lshr/ashl. */
25032 : 1329 : hdest = expand_simple_binop (V8HImode, code, hop1, hop2,
25033 : : NULL_RTX, 1, OPTAB_DIRECT);
25034 : :
25035 : 1342 : if (TARGET_AVX512BW && TARGET_AVX512VL)
25036 : : {
25037 : 30 : if (qimode == V8QImode)
25038 : : qdest = dest;
25039 : : else
25040 : 10 : qdest = gen_reg_rtx (V8QImode);
25041 : :
25042 : 30 : emit_insn (gen_truncv8hiv8qi2 (qdest, hdest));
25043 : : }
25044 : : else
25045 : : {
25046 : 1312 : struct expand_vec_perm_d d;
25047 : 1312 : rtx qres = gen_lowpart (V16QImode, hdest);
25048 : 1312 : bool ok;
25049 : 1312 : int i;
25050 : :
25051 : : /* Merge the data back into the right place. */
25052 : 1312 : d.target = qdest;
25053 : 1312 : d.op0 = d.op1 = qres;
25054 : 1312 : d.vmode = V16QImode;
25055 : 1312 : d.nelt = 16;
25056 : 1312 : d.one_operand_p = TARGET_SSSE3;
25057 : 1312 : d.testing_p = false;
25058 : :
25059 : 22304 : for (i = 0; i < d.nelt; ++i)
25060 : 20992 : d.perm[i] = i * 2;
25061 : :
25062 : 1312 : ok = ix86_expand_vec_perm_const_1 (&d);
25063 : 1312 : gcc_assert (ok);
25064 : : }
25065 : :
25066 : 1342 : if (qdest != dest)
25067 : 1322 : emit_move_insn (dest, gen_lowpart (qimode, qdest));
25068 : : }
25069 : :
25070 : : /* Emit instruction in 2x wider mode. For example, optimize
25071 : : vector MUL generation like
25072 : :
25073 : : vpmovzxbw ymm2, xmm0
25074 : : vpmovzxbw ymm3, xmm1
25075 : : vpmullw ymm4, ymm2, ymm3
25076 : : vpmovwb xmm0, ymm4
25077 : :
25078 : : it would take less instructions than ix86_expand_vecop_qihi.
25079 : : Return true if success. */
25080 : :
25081 : : static bool
25082 : 1337 : ix86_expand_vecop_qihi2 (enum rtx_code code, rtx dest, rtx op1, rtx op2)
25083 : : {
25084 : 1337 : machine_mode himode, qimode = GET_MODE (dest);
25085 : 1337 : machine_mode wqimode;
25086 : 1337 : rtx qop1, qop2, hop1, hop2, hdest;
25087 : 1337 : rtx (*gen_truncate)(rtx, rtx) = NULL;
25088 : 1337 : bool op2vec = GET_MODE_CLASS (GET_MODE (op2)) == MODE_VECTOR_INT;
25089 : 1337 : bool uns_p = code != ASHIFTRT;
25090 : :
25091 : : /* Without VPMOVWB (provided by AVX512BW ISA), the expansion uses the
25092 : : generic permutation to merge the data back into the right place. This
25093 : : permutation results in VPERMQ, which is slow, so better fall back to
25094 : : ix86_expand_vecop_qihi. */
25095 : 1337 : if (!TARGET_AVX512BW
25096 : 301 : || (qimode == V16QImode && !TARGET_AVX512VL)
25097 : : /* There are no V64HImode instructions. */
25098 : 301 : || qimode == V64QImode)
25099 : : return false;
25100 : :
25101 : : /* Do not generate ymm/zmm instructions when
25102 : : target prefers 128/256 bit vector width. */
25103 : 267 : if ((qimode == V16QImode && TARGET_PREFER_AVX128)
25104 : 267 : || (qimode == V32QImode && TARGET_PREFER_AVX256))
25105 : : return false;
25106 : :
25107 : 260 : switch (qimode)
25108 : : {
25109 : : case E_V16QImode:
25110 : : himode = V16HImode;
25111 : : gen_truncate = gen_truncv16hiv16qi2;
25112 : : break;
25113 : 17 : case E_V32QImode:
25114 : 17 : himode = V32HImode;
25115 : 17 : gen_truncate = gen_truncv32hiv32qi2;
25116 : 17 : break;
25117 : 0 : default:
25118 : 0 : gcc_unreachable ();
25119 : : }
25120 : :
25121 : 260 : wqimode = GET_MODE_2XWIDER_MODE (qimode).require ();
25122 : 260 : qop1 = lowpart_subreg (wqimode, force_reg (qimode, op1), qimode);
25123 : :
25124 : 260 : if (op2vec)
25125 : 260 : qop2 = lowpart_subreg (wqimode, force_reg (qimode, op2), qimode);
25126 : : else
25127 : : qop2 = op2;
25128 : :
25129 : 260 : hop1 = gen_reg_rtx (himode);
25130 : 260 : ix86_expand_sse_unpack (hop1, qop1, uns_p, false);
25131 : :
25132 : 260 : if (op2vec)
25133 : : {
25134 : 260 : hop2 = gen_reg_rtx (himode);
25135 : 260 : ix86_expand_sse_unpack (hop2, qop2, uns_p, false);
25136 : : }
25137 : : else
25138 : : hop2 = qop2;
25139 : :
25140 : 260 : if (code != MULT && op2vec)
25141 : : {
25142 : : /* Expand vashr/vlshr/vashl. */
25143 : 14 : hdest = gen_reg_rtx (himode);
25144 : 14 : emit_insn (gen_rtx_SET (hdest,
25145 : : simplify_gen_binary (code, himode,
25146 : : hop1, hop2)));
25147 : : }
25148 : : else
25149 : : /* Expand mult/ashr/lshr/ashl. */
25150 : 246 : hdest = expand_simple_binop (himode, code, hop1, hop2,
25151 : : NULL_RTX, 1, OPTAB_DIRECT);
25152 : :
25153 : 260 : emit_insn (gen_truncate (dest, hdest));
25154 : 260 : return true;
25155 : : }
25156 : :
25157 : : /* Expand a vector operation CODE for a V*QImode in terms of the
25158 : : same operation on V*HImode. */
25159 : :
25160 : : void
25161 : 1641 : ix86_expand_vecop_qihi (enum rtx_code code, rtx dest, rtx op1, rtx op2)
25162 : : {
25163 : 1641 : machine_mode qimode = GET_MODE (dest);
25164 : 1641 : machine_mode himode;
25165 : 1641 : rtx (*gen_il) (rtx, rtx, rtx);
25166 : 1641 : rtx (*gen_ih) (rtx, rtx, rtx);
25167 : 1641 : rtx op1_l, op1_h, op2_l, op2_h, res_l, res_h;
25168 : 1641 : bool op2vec = GET_MODE_CLASS (GET_MODE (op2)) == MODE_VECTOR_INT;
25169 : 1641 : struct expand_vec_perm_d d;
25170 : 1641 : bool full_interleave = true;
25171 : 1641 : bool uns_p = code != ASHIFTRT;
25172 : 1641 : bool ok;
25173 : 1641 : int i;
25174 : :
25175 : 1641 : if (CONST_INT_P (op2)
25176 : 304 : && (code == ASHIFT || code == LSHIFTRT || code == ASHIFTRT)
25177 : 1945 : && ix86_expand_vec_shift_qihi_constant (code, dest, op1, op2))
25178 : 564 : return;
25179 : :
25180 : 1337 : if (ix86_expand_vecop_qihi2 (code, dest, op1, op2))
25181 : : return;
25182 : :
25183 : 1077 : switch (qimode)
25184 : : {
25185 : : case E_V16QImode:
25186 : : himode = V8HImode;
25187 : : break;
25188 : 280 : case E_V32QImode:
25189 : 280 : himode = V16HImode;
25190 : 280 : break;
25191 : 34 : case E_V64QImode:
25192 : 34 : himode = V32HImode;
25193 : 34 : break;
25194 : 0 : default:
25195 : 0 : gcc_unreachable ();
25196 : : }
25197 : :
25198 : 1077 : switch (code)
25199 : : {
25200 : 1069 : case MULT:
25201 : 1069 : gcc_assert (op2vec);
25202 : : /* Unpack data such that we've got a source byte in each low byte of
25203 : : each word. We don't care what goes into the high byte of each word.
25204 : : Rather than trying to get zero in there, most convenient is to let
25205 : : it be a copy of the low byte. */
25206 : 1069 : switch (qimode)
25207 : : {
25208 : : case E_V16QImode:
25209 : : gen_il = gen_vec_interleave_lowv16qi;
25210 : : gen_ih = gen_vec_interleave_highv16qi;
25211 : : break;
25212 : 280 : case E_V32QImode:
25213 : 280 : gen_il = gen_avx2_interleave_lowv32qi;
25214 : 280 : gen_ih = gen_avx2_interleave_highv32qi;
25215 : 280 : full_interleave = false;
25216 : 280 : break;
25217 : 32 : case E_V64QImode:
25218 : 32 : gen_il = gen_avx512bw_interleave_lowv64qi;
25219 : 32 : gen_ih = gen_avx512bw_interleave_highv64qi;
25220 : 32 : full_interleave = false;
25221 : 32 : break;
25222 : 0 : default:
25223 : 0 : gcc_unreachable ();
25224 : : }
25225 : :
25226 : 1069 : op2_l = gen_reg_rtx (qimode);
25227 : 1069 : op2_h = gen_reg_rtx (qimode);
25228 : 1069 : emit_insn (gen_il (op2_l, op2, op2));
25229 : 1069 : emit_insn (gen_ih (op2_h, op2, op2));
25230 : :
25231 : 1069 : op1_l = gen_reg_rtx (qimode);
25232 : 1069 : op1_h = gen_reg_rtx (qimode);
25233 : 1069 : emit_insn (gen_il (op1_l, op1, op1));
25234 : 1069 : emit_insn (gen_ih (op1_h, op1, op1));
25235 : 1069 : break;
25236 : :
25237 : 8 : case ASHIFT:
25238 : 8 : case ASHIFTRT:
25239 : 8 : case LSHIFTRT:
25240 : 8 : op1_l = gen_reg_rtx (himode);
25241 : 8 : op1_h = gen_reg_rtx (himode);
25242 : 8 : ix86_expand_sse_unpack (op1_l, op1, uns_p, false);
25243 : 8 : ix86_expand_sse_unpack (op1_h, op1, uns_p, true);
25244 : : /* vashr/vlshr/vashl */
25245 : 8 : if (op2vec)
25246 : : {
25247 : 2 : rtx tmp = force_reg (qimode, op2);
25248 : 2 : op2_l = gen_reg_rtx (himode);
25249 : 2 : op2_h = gen_reg_rtx (himode);
25250 : 2 : ix86_expand_sse_unpack (op2_l, tmp, uns_p, false);
25251 : 2 : ix86_expand_sse_unpack (op2_h, tmp, uns_p, true);
25252 : : }
25253 : : else
25254 : : op2_l = op2_h = op2;
25255 : :
25256 : : break;
25257 : 0 : default:
25258 : 0 : gcc_unreachable ();
25259 : : }
25260 : :
25261 : 1077 : if (code != MULT && op2vec)
25262 : : {
25263 : : /* Expand vashr/vlshr/vashl. */
25264 : 2 : res_l = gen_reg_rtx (himode);
25265 : 2 : res_h = gen_reg_rtx (himode);
25266 : 2 : emit_insn (gen_rtx_SET (res_l,
25267 : : simplify_gen_binary (code, himode,
25268 : : op1_l, op2_l)));
25269 : 2 : emit_insn (gen_rtx_SET (res_h,
25270 : : simplify_gen_binary (code, himode,
25271 : : op1_h, op2_h)));
25272 : : }
25273 : : else
25274 : : {
25275 : : /* Expand mult/ashr/lshr/ashl. */
25276 : 1075 : res_l = expand_simple_binop (himode, code, op1_l, op2_l, NULL_RTX,
25277 : : 1, OPTAB_DIRECT);
25278 : 1075 : res_h = expand_simple_binop (himode, code, op1_h, op2_h, NULL_RTX,
25279 : : 1, OPTAB_DIRECT);
25280 : : }
25281 : :
25282 : 1077 : gcc_assert (res_l && res_h);
25283 : :
25284 : : /* Merge the data back into the right place. */
25285 : 1077 : d.target = dest;
25286 : 1077 : d.op0 = gen_lowpart (qimode, res_l);
25287 : 1077 : d.op1 = gen_lowpart (qimode, res_h);
25288 : 1077 : d.vmode = qimode;
25289 : 1077 : d.nelt = GET_MODE_NUNITS (qimode);
25290 : 1077 : d.one_operand_p = false;
25291 : 1077 : d.testing_p = false;
25292 : :
25293 : 1077 : if (full_interleave)
25294 : : {
25295 : : /* We used the full interleave, the desired
25296 : : results are in the even elements. */
25297 : 13101 : for (i = 0; i < d.nelt; ++i)
25298 : 12336 : d.perm[i] = i * 2;
25299 : : }
25300 : : else
25301 : : {
25302 : : /* For AVX, the interleave used above was not cross-lane. So the
25303 : : extraction is evens but with the second and third quarter swapped.
25304 : : Happily, that is even one insn shorter than even extraction.
25305 : : For AVX512BW we have 4 lanes. We extract evens from within a lane,
25306 : : always first from the first and then from the second source operand,
25307 : : the index bits above the low 4 bits remains the same.
25308 : : Thus, for d.nelt == 32 we want permutation
25309 : : 0,2,4,..14, 32,34,36,..46, 16,18,20,..30, 48,50,52,..62
25310 : : and for d.nelt == 64 we want permutation
25311 : : 0,2,4,..14, 64,66,68,..78, 16,18,20,..30, 80,82,84,..94,
25312 : : 32,34,36,..46, 96,98,100,..110, 48,50,52,..62, 112,114,116,..126. */
25313 : 11320 : for (i = 0; i < d.nelt; ++i)
25314 : 16512 : d.perm[i] = ((i * 2) & 14) + ((i & 8) ? d.nelt : 0) + (i & ~15);
25315 : : }
25316 : :
25317 : 1077 : ok = ix86_expand_vec_perm_const_1 (&d);
25318 : 1077 : gcc_assert (ok);
25319 : : }
25320 : :
25321 : : /* Helper function of ix86_expand_mul_widen_evenodd. Return true
25322 : : if op is CONST_VECTOR with all odd elements equal to their
25323 : : preceding element. */
25324 : :
25325 : : static bool
25326 : 8448 : const_vector_equal_evenodd_p (rtx op)
25327 : : {
25328 : 8448 : machine_mode mode = GET_MODE (op);
25329 : 8448 : int i, nunits = GET_MODE_NUNITS (mode);
25330 : 8448 : if (GET_CODE (op) != CONST_VECTOR
25331 : 8448 : || nunits != CONST_VECTOR_NUNITS (op))
25332 : : return false;
25333 : 3156 : for (i = 0; i < nunits; i += 2)
25334 : 2574 : if (CONST_VECTOR_ELT (op, i) != CONST_VECTOR_ELT (op, i + 1))
25335 : : return false;
25336 : : return true;
25337 : : }
25338 : :
25339 : : void
25340 : 8561 : ix86_expand_mul_widen_evenodd (rtx dest, rtx op1, rtx op2,
25341 : : bool uns_p, bool odd_p)
25342 : : {
25343 : 8561 : machine_mode mode = GET_MODE (op1);
25344 : 8561 : machine_mode wmode = GET_MODE (dest);
25345 : 8561 : rtx x;
25346 : 8561 : rtx orig_op1 = op1, orig_op2 = op2;
25347 : :
25348 : 8561 : if (!nonimmediate_operand (op1, mode))
25349 : 0 : op1 = force_reg (mode, op1);
25350 : 8561 : if (!nonimmediate_operand (op2, mode))
25351 : 3189 : op2 = force_reg (mode, op2);
25352 : :
25353 : : /* We only play even/odd games with vectors of SImode. */
25354 : 8561 : gcc_assert (mode == V4SImode || mode == V8SImode || mode == V16SImode);
25355 : :
25356 : : /* If we're looking for the odd results, shift those members down to
25357 : : the even slots. For some cpus this is faster than a PSHUFD. */
25358 : 8561 : if (odd_p)
25359 : : {
25360 : : /* For XOP use vpmacsdqh, but only for smult, as it is only
25361 : : signed. */
25362 : 4242 : if (TARGET_XOP && mode == V4SImode && !uns_p)
25363 : : {
25364 : 18 : x = force_reg (wmode, CONST0_RTX (wmode));
25365 : 18 : emit_insn (gen_xop_pmacsdqh (dest, op1, op2, x));
25366 : 18 : return;
25367 : : }
25368 : :
25369 : 8448 : x = GEN_INT (GET_MODE_UNIT_BITSIZE (mode));
25370 : 4224 : if (!const_vector_equal_evenodd_p (orig_op1))
25371 : 4224 : op1 = expand_binop (wmode, lshr_optab, gen_lowpart (wmode, op1),
25372 : : x, NULL, 1, OPTAB_DIRECT);
25373 : 4224 : if (!const_vector_equal_evenodd_p (orig_op2))
25374 : 3642 : op2 = expand_binop (wmode, lshr_optab, gen_lowpart (wmode, op2),
25375 : : x, NULL, 1, OPTAB_DIRECT);
25376 : 4224 : op1 = gen_lowpart (mode, op1);
25377 : 4224 : op2 = gen_lowpart (mode, op2);
25378 : : }
25379 : :
25380 : 8543 : if (mode == V16SImode)
25381 : : {
25382 : 4 : if (uns_p)
25383 : 0 : x = gen_vec_widen_umult_even_v16si (dest, op1, op2);
25384 : : else
25385 : 4 : x = gen_vec_widen_smult_even_v16si (dest, op1, op2);
25386 : : }
25387 : 8539 : else if (mode == V8SImode)
25388 : : {
25389 : 89 : if (uns_p)
25390 : 39 : x = gen_vec_widen_umult_even_v8si (dest, op1, op2);
25391 : : else
25392 : 50 : x = gen_vec_widen_smult_even_v8si (dest, op1, op2);
25393 : : }
25394 : 8450 : else if (uns_p)
25395 : 7507 : x = gen_vec_widen_umult_even_v4si (dest, op1, op2);
25396 : 943 : else if (TARGET_SSE4_1)
25397 : 305 : x = gen_sse4_1_mulv2siv2di3 (dest, op1, op2);
25398 : : else
25399 : : {
25400 : 638 : rtx s1, s2, t0, t1, t2;
25401 : :
25402 : : /* The easiest way to implement this without PMULDQ is to go through
25403 : : the motions as if we are performing a full 64-bit multiply. With
25404 : : the exception that we need to do less shuffling of the elements. */
25405 : :
25406 : : /* Compute the sign-extension, aka highparts, of the two operands. */
25407 : 638 : s1 = ix86_expand_sse_cmp (gen_reg_rtx (mode), GT, CONST0_RTX (mode),
25408 : : op1, pc_rtx, pc_rtx);
25409 : 638 : s2 = ix86_expand_sse_cmp (gen_reg_rtx (mode), GT, CONST0_RTX (mode),
25410 : : op2, pc_rtx, pc_rtx);
25411 : :
25412 : : /* Multiply LO(A) * HI(B), and vice-versa. */
25413 : 638 : t1 = gen_reg_rtx (wmode);
25414 : 638 : t2 = gen_reg_rtx (wmode);
25415 : 638 : emit_insn (gen_vec_widen_umult_even_v4si (t1, s1, op2));
25416 : 638 : emit_insn (gen_vec_widen_umult_even_v4si (t2, s2, op1));
25417 : :
25418 : : /* Multiply LO(A) * LO(B). */
25419 : 638 : t0 = gen_reg_rtx (wmode);
25420 : 638 : emit_insn (gen_vec_widen_umult_even_v4si (t0, op1, op2));
25421 : :
25422 : : /* Combine and shift the highparts into place. */
25423 : 638 : t1 = expand_binop (wmode, add_optab, t1, t2, t1, 1, OPTAB_DIRECT);
25424 : 638 : t1 = expand_binop (wmode, ashl_optab, t1, GEN_INT (32), t1,
25425 : : 1, OPTAB_DIRECT);
25426 : :
25427 : : /* Combine high and low parts. */
25428 : 638 : force_expand_binop (wmode, add_optab, t0, t1, dest, 1, OPTAB_DIRECT);
25429 : 638 : return;
25430 : : }
25431 : 7905 : emit_insn (x);
25432 : : }
25433 : :
25434 : : void
25435 : 867 : ix86_expand_mul_widen_hilo (rtx dest, rtx op1, rtx op2,
25436 : : bool uns_p, bool high_p)
25437 : : {
25438 : 867 : machine_mode wmode = GET_MODE (dest);
25439 : 867 : machine_mode mode = GET_MODE (op1);
25440 : 867 : rtx t1, t2, t3, t4, mask;
25441 : :
25442 : 867 : switch (mode)
25443 : : {
25444 : 269 : case E_V4SImode:
25445 : 269 : t1 = gen_reg_rtx (mode);
25446 : 269 : t2 = gen_reg_rtx (mode);
25447 : 269 : if (TARGET_XOP && !uns_p)
25448 : : {
25449 : : /* With XOP, we have pmacsdqh, aka mul_widen_odd. In this case,
25450 : : shuffle the elements once so that all elements are in the right
25451 : : place for immediate use: { A C B D }. */
25452 : 33 : emit_insn (gen_sse2_pshufd_1 (t1, op1, const0_rtx, const2_rtx,
25453 : : const1_rtx, GEN_INT (3)));
25454 : 33 : emit_insn (gen_sse2_pshufd_1 (t2, op2, const0_rtx, const2_rtx,
25455 : : const1_rtx, GEN_INT (3)));
25456 : : }
25457 : : else
25458 : : {
25459 : : /* Put the elements into place for the multiply. */
25460 : 236 : ix86_expand_vec_interleave (t1, op1, op1, high_p);
25461 : 236 : ix86_expand_vec_interleave (t2, op2, op2, high_p);
25462 : 236 : high_p = false;
25463 : : }
25464 : 269 : ix86_expand_mul_widen_evenodd (dest, t1, t2, uns_p, high_p);
25465 : 269 : break;
25466 : :
25467 : 48 : case E_V8SImode:
25468 : : /* Shuffle the elements between the lanes. After this we
25469 : : have { A B E F | C D G H } for each operand. */
25470 : 48 : t1 = gen_reg_rtx (V4DImode);
25471 : 48 : t2 = gen_reg_rtx (V4DImode);
25472 : 48 : emit_insn (gen_avx2_permv4di_1 (t1, gen_lowpart (V4DImode, op1),
25473 : : const0_rtx, const2_rtx,
25474 : : const1_rtx, GEN_INT (3)));
25475 : 48 : emit_insn (gen_avx2_permv4di_1 (t2, gen_lowpart (V4DImode, op2),
25476 : : const0_rtx, const2_rtx,
25477 : : const1_rtx, GEN_INT (3)));
25478 : :
25479 : : /* Shuffle the elements within the lanes. After this we
25480 : : have { A A B B | C C D D } or { E E F F | G G H H }. */
25481 : 48 : t3 = gen_reg_rtx (V8SImode);
25482 : 48 : t4 = gen_reg_rtx (V8SImode);
25483 : 72 : mask = GEN_INT (high_p
25484 : : ? 2 + (2 << 2) + (3 << 4) + (3 << 6)
25485 : : : 0 + (0 << 2) + (1 << 4) + (1 << 6));
25486 : 48 : emit_insn (gen_avx2_pshufdv3 (t3, gen_lowpart (V8SImode, t1), mask));
25487 : 48 : emit_insn (gen_avx2_pshufdv3 (t4, gen_lowpart (V8SImode, t2), mask));
25488 : :
25489 : 48 : ix86_expand_mul_widen_evenodd (dest, t3, t4, uns_p, false);
25490 : 48 : break;
25491 : :
25492 : 382 : case E_V8HImode:
25493 : 382 : case E_V16HImode:
25494 : 382 : t1 = expand_binop (mode, smul_optab, op1, op2, NULL_RTX,
25495 : : uns_p, OPTAB_DIRECT);
25496 : 618 : t2 = expand_binop (mode,
25497 : : uns_p ? umul_highpart_optab : smul_highpart_optab,
25498 : : op1, op2, NULL_RTX, uns_p, OPTAB_DIRECT);
25499 : 382 : gcc_assert (t1 && t2);
25500 : :
25501 : 382 : t3 = gen_reg_rtx (mode);
25502 : 382 : ix86_expand_vec_interleave (t3, t1, t2, high_p);
25503 : 382 : emit_move_insn (dest, gen_lowpart (wmode, t3));
25504 : 382 : break;
25505 : :
25506 : 168 : case E_V16QImode:
25507 : 168 : case E_V32QImode:
25508 : 168 : case E_V32HImode:
25509 : 168 : case E_V16SImode:
25510 : 168 : case E_V64QImode:
25511 : 168 : t1 = gen_reg_rtx (wmode);
25512 : 168 : t2 = gen_reg_rtx (wmode);
25513 : 168 : ix86_expand_sse_unpack (t1, op1, uns_p, high_p);
25514 : 168 : ix86_expand_sse_unpack (t2, op2, uns_p, high_p);
25515 : :
25516 : 168 : emit_insn (gen_rtx_SET (dest, gen_rtx_MULT (wmode, t1, t2)));
25517 : 168 : break;
25518 : :
25519 : 0 : default:
25520 : 0 : gcc_unreachable ();
25521 : : }
25522 : 867 : }
25523 : :
25524 : : void
25525 : 3612 : ix86_expand_sse2_mulv4si3 (rtx op0, rtx op1, rtx op2)
25526 : : {
25527 : 3612 : rtx res_1, res_2, res_3, res_4;
25528 : :
25529 : 3612 : res_1 = gen_reg_rtx (V4SImode);
25530 : 3612 : res_2 = gen_reg_rtx (V4SImode);
25531 : 3612 : res_3 = gen_reg_rtx (V2DImode);
25532 : 3612 : res_4 = gen_reg_rtx (V2DImode);
25533 : 3612 : ix86_expand_mul_widen_evenodd (res_3, op1, op2, true, false);
25534 : 3612 : ix86_expand_mul_widen_evenodd (res_4, op1, op2, true, true);
25535 : :
25536 : : /* Move the results in element 2 down to element 1; we don't care
25537 : : what goes in elements 2 and 3. Then we can merge the parts
25538 : : back together with an interleave.
25539 : :
25540 : : Note that two other sequences were tried:
25541 : : (1) Use interleaves at the start instead of psrldq, which allows
25542 : : us to use a single shufps to merge things back at the end.
25543 : : (2) Use shufps here to combine the two vectors, then pshufd to
25544 : : put the elements in the correct order.
25545 : : In both cases the cost of the reformatting stall was too high
25546 : : and the overall sequence slower. */
25547 : :
25548 : 3612 : emit_insn (gen_sse2_pshufd_1 (res_1, gen_lowpart (V4SImode, res_3),
25549 : : const0_rtx, const2_rtx,
25550 : : const0_rtx, const0_rtx));
25551 : 3612 : emit_insn (gen_sse2_pshufd_1 (res_2, gen_lowpart (V4SImode, res_4),
25552 : : const0_rtx, const2_rtx,
25553 : : const0_rtx, const0_rtx));
25554 : 3612 : res_1 = emit_insn (gen_vec_interleave_lowv4si (op0, res_1, res_2));
25555 : :
25556 : 3612 : set_unique_reg_note (res_1, REG_EQUAL, gen_rtx_MULT (V4SImode, op1, op2));
25557 : 3612 : }
25558 : :
25559 : : void
25560 : 536 : ix86_expand_sse2_mulvxdi3 (rtx op0, rtx op1, rtx op2)
25561 : : {
25562 : 536 : machine_mode mode = GET_MODE (op0);
25563 : 536 : rtx t1, t2, t3, t4, t5, t6;
25564 : :
25565 : 536 : if (TARGET_AVX512DQ && mode == V8DImode)
25566 : 32 : emit_insn (gen_avx512dq_mulv8di3 (op0, op1, op2));
25567 : 504 : else if (TARGET_AVX512DQ && TARGET_AVX512VL && mode == V4DImode)
25568 : 32 : emit_insn (gen_avx512dq_mulv4di3 (op0, op1, op2));
25569 : 472 : else if (TARGET_AVX512DQ && TARGET_AVX512VL && mode == V2DImode)
25570 : 36 : emit_insn (gen_avx512dq_mulv2di3 (op0, op1, op2));
25571 : 436 : else if (TARGET_XOP && mode == V2DImode)
25572 : : {
25573 : : /* op1: A,B,C,D, op2: E,F,G,H */
25574 : 2 : op1 = gen_lowpart (V4SImode, op1);
25575 : 2 : op2 = gen_lowpart (V4SImode, op2);
25576 : :
25577 : 2 : t1 = gen_reg_rtx (V4SImode);
25578 : 2 : t2 = gen_reg_rtx (V4SImode);
25579 : 2 : t3 = gen_reg_rtx (V2DImode);
25580 : 2 : t4 = gen_reg_rtx (V2DImode);
25581 : :
25582 : : /* t1: B,A,D,C */
25583 : 2 : emit_insn (gen_sse2_pshufd_1 (t1, op1,
25584 : : GEN_INT (1),
25585 : : GEN_INT (0),
25586 : : GEN_INT (3),
25587 : : GEN_INT (2)));
25588 : :
25589 : : /* t2: (B*E),(A*F),(D*G),(C*H) */
25590 : 2 : emit_insn (gen_mulv4si3 (t2, t1, op2));
25591 : :
25592 : : /* t3: (B*E)+(A*F), (D*G)+(C*H) */
25593 : 2 : emit_insn (gen_xop_phadddq (t3, t2));
25594 : :
25595 : : /* t4: ((B*E)+(A*F))<<32, ((D*G)+(C*H))<<32 */
25596 : 2 : emit_insn (gen_ashlv2di3 (t4, t3, GEN_INT (32)));
25597 : :
25598 : : /* Multiply lower parts and add all */
25599 : 2 : t5 = gen_reg_rtx (V2DImode);
25600 : 2 : emit_insn (gen_vec_widen_umult_even_v4si (t5,
25601 : 2 : gen_lowpart (V4SImode, op1),
25602 : 2 : gen_lowpart (V4SImode, op2)));
25603 : 2 : force_expand_binop (mode, add_optab, t5, t4, op0, 1, OPTAB_DIRECT);
25604 : : }
25605 : : else
25606 : : {
25607 : 434 : machine_mode nmode;
25608 : 434 : rtx (*umul) (rtx, rtx, rtx);
25609 : :
25610 : 434 : if (mode == V2DImode)
25611 : : {
25612 : : umul = gen_vec_widen_umult_even_v4si;
25613 : : nmode = V4SImode;
25614 : : }
25615 : 329 : else if (mode == V4DImode)
25616 : : {
25617 : : umul = gen_vec_widen_umult_even_v8si;
25618 : : nmode = V8SImode;
25619 : : }
25620 : 118 : else if (mode == V8DImode)
25621 : : {
25622 : : umul = gen_vec_widen_umult_even_v16si;
25623 : : nmode = V16SImode;
25624 : : }
25625 : : else
25626 : 0 : gcc_unreachable ();
25627 : :
25628 : :
25629 : : /* Multiply low parts. */
25630 : 434 : t1 = gen_reg_rtx (mode);
25631 : 434 : emit_insn (umul (t1, gen_lowpart (nmode, op1), gen_lowpart (nmode, op2)));
25632 : :
25633 : : /* Shift input vectors right 32 bits so we can multiply high parts. */
25634 : 434 : t6 = GEN_INT (32);
25635 : 434 : t2 = expand_binop (mode, lshr_optab, op1, t6, NULL, 1, OPTAB_DIRECT);
25636 : 434 : t3 = expand_binop (mode, lshr_optab, op2, t6, NULL, 1, OPTAB_DIRECT);
25637 : :
25638 : : /* Multiply high parts by low parts. */
25639 : 434 : t4 = gen_reg_rtx (mode);
25640 : 434 : t5 = gen_reg_rtx (mode);
25641 : 434 : emit_insn (umul (t4, gen_lowpart (nmode, t2), gen_lowpart (nmode, op2)));
25642 : 434 : emit_insn (umul (t5, gen_lowpart (nmode, t3), gen_lowpart (nmode, op1)));
25643 : :
25644 : : /* Combine and shift the highparts back. */
25645 : 434 : t4 = expand_binop (mode, add_optab, t4, t5, t4, 1, OPTAB_DIRECT);
25646 : 434 : t4 = expand_binop (mode, ashl_optab, t4, t6, t4, 1, OPTAB_DIRECT);
25647 : :
25648 : : /* Combine high and low parts. */
25649 : 434 : force_expand_binop (mode, add_optab, t1, t4, op0, 1, OPTAB_DIRECT);
25650 : : }
25651 : :
25652 : 536 : set_unique_reg_note (get_last_insn (), REG_EQUAL,
25653 : : gen_rtx_MULT (mode, op1, op2));
25654 : 536 : }
25655 : :
25656 : : /* Return 1 if control tansfer instruction INSN
25657 : : should be encoded with notrack prefix. */
25658 : :
25659 : : bool
25660 : 14710721 : ix86_notrack_prefixed_insn_p (rtx_insn *insn)
25661 : : {
25662 : 14710721 : if (!insn || !((flag_cf_protection & CF_BRANCH)))
25663 : : return false;
25664 : :
25665 : 4018619 : if (CALL_P (insn))
25666 : : {
25667 : 1405098 : rtx call = get_call_rtx_from (insn);
25668 : 1405098 : gcc_assert (call != NULL_RTX);
25669 : 1405098 : rtx addr = XEXP (call, 0);
25670 : :
25671 : : /* Do not emit 'notrack' if it's not an indirect call. */
25672 : 1405098 : if (MEM_P (addr)
25673 : 1405098 : && GET_CODE (XEXP (addr, 0)) == SYMBOL_REF)
25674 : : return false;
25675 : : else
25676 : 73771 : return find_reg_note (insn, REG_CALL_NOCF_CHECK, 0);
25677 : : }
25678 : :
25679 : 2613521 : if (JUMP_P (insn) && !flag_cet_switch)
25680 : : {
25681 : 2600481 : rtx target = JUMP_LABEL (insn);
25682 : 2600481 : if (target == NULL_RTX || ANY_RETURN_P (target))
25683 : : return false;
25684 : :
25685 : : /* Check the jump is a switch table. */
25686 : 2600443 : rtx_insn *label = as_a<rtx_insn *> (target);
25687 : 2600443 : rtx_insn *table = next_insn (label);
25688 : 2600443 : if (table == NULL_RTX || !JUMP_TABLE_DATA_P (table))
25689 : : return false;
25690 : : else
25691 : : return true;
25692 : : }
25693 : : return false;
25694 : : }
25695 : :
25696 : : /* Calculate integer abs() using only SSE2 instructions. */
25697 : :
25698 : : void
25699 : 515 : ix86_expand_sse2_abs (rtx target, rtx input)
25700 : : {
25701 : 515 : machine_mode mode = GET_MODE (target);
25702 : 515 : rtx tmp0, tmp1, x;
25703 : :
25704 : 515 : switch (mode)
25705 : : {
25706 : 21 : case E_V2DImode:
25707 : 21 : case E_V4DImode:
25708 : : /* For 64-bit signed integer X, with SSE4.2 use
25709 : : pxor t0, t0; pcmpgtq X, t0; pxor t0, X; psubq t0, X.
25710 : : Otherwise handle it similarly to V4SImode, except use 64 as W instead of
25711 : : 32 and use logical instead of arithmetic right shift (which is
25712 : : unimplemented) and subtract. */
25713 : 21 : if (TARGET_SSE4_2)
25714 : : {
25715 : 9 : tmp0 = gen_reg_rtx (mode);
25716 : 9 : tmp1 = gen_reg_rtx (mode);
25717 : 9 : emit_move_insn (tmp1, CONST0_RTX (mode));
25718 : 9 : if (mode == E_V2DImode)
25719 : 6 : emit_insn (gen_sse4_2_gtv2di3 (tmp0, tmp1, input));
25720 : : else
25721 : 3 : emit_insn (gen_avx2_gtv4di3 (tmp0, tmp1, input));
25722 : : }
25723 : : else
25724 : : {
25725 : 24 : tmp0 = expand_simple_binop (mode, LSHIFTRT, input,
25726 : 12 : GEN_INT (GET_MODE_UNIT_BITSIZE (mode)
25727 : : - 1), NULL, 0, OPTAB_DIRECT);
25728 : 12 : tmp0 = expand_simple_unop (mode, NEG, tmp0, NULL, false);
25729 : : }
25730 : :
25731 : 21 : tmp1 = expand_simple_binop (mode, XOR, tmp0, input,
25732 : : NULL, 0, OPTAB_DIRECT);
25733 : 21 : x = expand_simple_binop (mode, MINUS, tmp1, tmp0,
25734 : : target, 0, OPTAB_DIRECT);
25735 : 21 : break;
25736 : :
25737 : 31 : case E_V4SImode:
25738 : : /* For 32-bit signed integer X, the best way to calculate the absolute
25739 : : value of X is (((signed) X >> (W-1)) ^ X) - ((signed) X >> (W-1)). */
25740 : 31 : tmp0 = expand_simple_binop (mode, ASHIFTRT, input,
25741 : 31 : GEN_INT (GET_MODE_UNIT_BITSIZE (mode) - 1),
25742 : : NULL, 0, OPTAB_DIRECT);
25743 : 31 : tmp1 = expand_simple_binop (mode, XOR, tmp0, input,
25744 : : NULL, 0, OPTAB_DIRECT);
25745 : 31 : x = expand_simple_binop (mode, MINUS, tmp1, tmp0,
25746 : : target, 0, OPTAB_DIRECT);
25747 : 31 : break;
25748 : :
25749 : 133 : case E_V8HImode:
25750 : : /* For 16-bit signed integer X, the best way to calculate the absolute
25751 : : value of X is max (X, -X), as SSE2 provides the PMAXSW insn. */
25752 : 133 : tmp0 = expand_unop (mode, neg_optab, input, NULL_RTX, 0);
25753 : :
25754 : 133 : x = expand_simple_binop (mode, SMAX, tmp0, input,
25755 : : target, 0, OPTAB_DIRECT);
25756 : 133 : break;
25757 : :
25758 : 330 : case E_V16QImode:
25759 : : /* For 8-bit signed integer X, the best way to calculate the absolute
25760 : : value of X is min ((unsigned char) X, (unsigned char) (-X)),
25761 : : as SSE2 provides the PMINUB insn. */
25762 : 330 : tmp0 = expand_unop (mode, neg_optab, input, NULL_RTX, 0);
25763 : :
25764 : 330 : x = expand_simple_binop (V16QImode, UMIN, tmp0, input,
25765 : : target, 0, OPTAB_DIRECT);
25766 : 330 : break;
25767 : :
25768 : 0 : default:
25769 : 0 : gcc_unreachable ();
25770 : : }
25771 : :
25772 : 515 : if (x != target)
25773 : 0 : emit_move_insn (target, x);
25774 : 515 : }
25775 : :
25776 : : /* Expand an extract from a vector register through pextr insn.
25777 : : Return true if successful. */
25778 : :
25779 : : bool
25780 : 106885 : ix86_expand_pextr (rtx *operands)
25781 : : {
25782 : 106885 : rtx dst = operands[0];
25783 : 106885 : rtx src = operands[1];
25784 : :
25785 : 106885 : unsigned int size = INTVAL (operands[2]);
25786 : 106885 : unsigned int pos = INTVAL (operands[3]);
25787 : :
25788 : 106885 : if (SUBREG_P (dst))
25789 : : {
25790 : : /* Reject non-lowpart subregs. */
25791 : 63335 : if (SUBREG_BYTE (dst) > 0)
25792 : : return false;
25793 : 63241 : dst = SUBREG_REG (dst);
25794 : : }
25795 : :
25796 : 106791 : if (SUBREG_P (src))
25797 : : {
25798 : 39516 : pos += SUBREG_BYTE (src) * BITS_PER_UNIT;
25799 : 39516 : src = SUBREG_REG (src);
25800 : : }
25801 : :
25802 : 106791 : switch (GET_MODE (src))
25803 : : {
25804 : 0 : case E_V16QImode:
25805 : 0 : case E_V8HImode:
25806 : 0 : case E_V4SImode:
25807 : 0 : case E_V2DImode:
25808 : 0 : case E_V1TImode:
25809 : 0 : {
25810 : 0 : machine_mode srcmode, dstmode;
25811 : 0 : rtx d, pat;
25812 : :
25813 : 0 : if (!int_mode_for_size (size, 0).exists (&dstmode))
25814 : 0 : return false;
25815 : :
25816 : 0 : switch (dstmode)
25817 : : {
25818 : 0 : case E_QImode:
25819 : 0 : if (!TARGET_SSE4_1)
25820 : : return false;
25821 : : srcmode = V16QImode;
25822 : : break;
25823 : :
25824 : 0 : case E_HImode:
25825 : 0 : if (!TARGET_SSE2)
25826 : : return false;
25827 : : srcmode = V8HImode;
25828 : : break;
25829 : :
25830 : 0 : case E_SImode:
25831 : 0 : if (!TARGET_SSE4_1)
25832 : : return false;
25833 : : srcmode = V4SImode;
25834 : : break;
25835 : :
25836 : 0 : case E_DImode:
25837 : 0 : gcc_assert (TARGET_64BIT);
25838 : 0 : if (!TARGET_SSE4_1)
25839 : : return false;
25840 : : srcmode = V2DImode;
25841 : : break;
25842 : :
25843 : : default:
25844 : : return false;
25845 : : }
25846 : :
25847 : : /* Reject extractions from misaligned positions. */
25848 : 0 : if (pos & (size-1))
25849 : : return false;
25850 : :
25851 : 0 : if (GET_MODE (dst) == dstmode)
25852 : : d = dst;
25853 : : else
25854 : 0 : d = gen_reg_rtx (dstmode);
25855 : :
25856 : : /* Construct insn pattern. */
25857 : 0 : pat = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (1, GEN_INT (pos / size)));
25858 : 0 : pat = gen_rtx_VEC_SELECT (dstmode, gen_lowpart (srcmode, src), pat);
25859 : :
25860 : : /* Let the rtl optimizers know about the zero extension performed. */
25861 : 0 : if (dstmode == QImode || dstmode == HImode)
25862 : : {
25863 : 0 : pat = gen_rtx_ZERO_EXTEND (SImode, pat);
25864 : 0 : d = gen_lowpart (SImode, d);
25865 : : }
25866 : :
25867 : 0 : emit_insn (gen_rtx_SET (d, pat));
25868 : :
25869 : 0 : if (d != dst)
25870 : 0 : emit_move_insn (dst, gen_lowpart (GET_MODE (dst), d));
25871 : : return true;
25872 : : }
25873 : :
25874 : : default:
25875 : : return false;
25876 : : }
25877 : : }
25878 : :
25879 : : /* Expand an insert into a vector register through pinsr insn.
25880 : : Return true if successful. */
25881 : :
25882 : : bool
25883 : 108476 : ix86_expand_pinsr (rtx *operands)
25884 : : {
25885 : 108476 : rtx dst = operands[0];
25886 : 108476 : rtx src = operands[3];
25887 : :
25888 : 108476 : unsigned int size = INTVAL (operands[1]);
25889 : 108476 : unsigned int pos = INTVAL (operands[2]);
25890 : :
25891 : 108476 : if (SUBREG_P (dst))
25892 : : {
25893 : 59124 : pos += SUBREG_BYTE (dst) * BITS_PER_UNIT;
25894 : 59124 : dst = SUBREG_REG (dst);
25895 : : }
25896 : :
25897 : 108476 : switch (GET_MODE (dst))
25898 : : {
25899 : 21 : case E_V16QImode:
25900 : 21 : case E_V8HImode:
25901 : 21 : case E_V4SImode:
25902 : 21 : case E_V2DImode:
25903 : 21 : case E_V1TImode:
25904 : 21 : {
25905 : 21 : machine_mode srcmode, dstmode;
25906 : 21 : rtx (*pinsr)(rtx, rtx, rtx, rtx);
25907 : 21 : rtx d;
25908 : :
25909 : 21 : if (!int_mode_for_size (size, 0).exists (&srcmode))
25910 : 0 : return false;
25911 : :
25912 : 21 : switch (srcmode)
25913 : : {
25914 : 1 : case E_QImode:
25915 : 1 : if (!TARGET_SSE4_1)
25916 : : return false;
25917 : : dstmode = V16QImode;
25918 : : pinsr = gen_sse4_1_pinsrb;
25919 : : break;
25920 : :
25921 : 5 : case E_HImode:
25922 : 5 : if (!TARGET_SSE2)
25923 : : return false;
25924 : : dstmode = V8HImode;
25925 : : pinsr = gen_sse2_pinsrw;
25926 : : break;
25927 : :
25928 : 15 : case E_SImode:
25929 : 15 : if (!TARGET_SSE4_1)
25930 : : return false;
25931 : : dstmode = V4SImode;
25932 : : pinsr = gen_sse4_1_pinsrd;
25933 : : break;
25934 : :
25935 : 0 : case E_DImode:
25936 : 0 : gcc_assert (TARGET_64BIT);
25937 : 0 : if (!TARGET_SSE4_1)
25938 : : return false;
25939 : : dstmode = V2DImode;
25940 : : pinsr = gen_sse4_1_pinsrq;
25941 : : break;
25942 : :
25943 : : default:
25944 : : return false;
25945 : : }
25946 : :
25947 : : /* Reject insertions to misaligned positions. */
25948 : 8 : if (pos & (size-1))
25949 : : return false;
25950 : :
25951 : 8 : if (SUBREG_P (src))
25952 : : {
25953 : 8 : unsigned int srcpos = SUBREG_BYTE (src);
25954 : :
25955 : 8 : if (srcpos > 0)
25956 : : {
25957 : 0 : rtx extr_ops[4];
25958 : :
25959 : 0 : extr_ops[0] = gen_reg_rtx (srcmode);
25960 : 0 : extr_ops[1] = gen_lowpart (srcmode, SUBREG_REG (src));
25961 : 0 : extr_ops[2] = GEN_INT (size);
25962 : 0 : extr_ops[3] = GEN_INT (srcpos * BITS_PER_UNIT);
25963 : :
25964 : 0 : if (!ix86_expand_pextr (extr_ops))
25965 : 0 : return false;
25966 : :
25967 : 0 : src = extr_ops[0];
25968 : : }
25969 : : else
25970 : 8 : src = gen_lowpart (srcmode, SUBREG_REG (src));
25971 : : }
25972 : :
25973 : 8 : if (GET_MODE (dst) == dstmode)
25974 : : d = dst;
25975 : : else
25976 : 8 : d = gen_reg_rtx (dstmode);
25977 : :
25978 : 8 : emit_insn (pinsr (d, gen_lowpart (dstmode, dst),
25979 : 8 : gen_lowpart (srcmode, src),
25980 : 8 : GEN_INT (1 << (pos / size))));
25981 : 8 : if (d != dst)
25982 : 8 : emit_move_insn (dst, gen_lowpart (GET_MODE (dst), d));
25983 : : return true;
25984 : : }
25985 : :
25986 : : default:
25987 : : return false;
25988 : : }
25989 : : }
25990 : :
25991 : : /* All CPUs prefer to avoid cross-lane operations so perform reductions
25992 : : upper against lower halves up to SSE reg size. */
25993 : :
25994 : : machine_mode
25995 : 1733 : ix86_split_reduction (machine_mode mode)
25996 : : {
25997 : : /* Reduce lowpart against highpart until we reach SSE reg width to
25998 : : avoid cross-lane operations. */
25999 : 1733 : switch (mode)
26000 : : {
26001 : : case E_V8DImode:
26002 : : case E_V4DImode:
26003 : : return V2DImode;
26004 : 7 : case E_V16SImode:
26005 : 7 : case E_V8SImode:
26006 : 7 : return V4SImode;
26007 : 6 : case E_V32HImode:
26008 : 6 : case E_V16HImode:
26009 : 6 : return V8HImode;
26010 : 4 : case E_V64QImode:
26011 : 4 : case E_V32QImode:
26012 : 4 : return V16QImode;
26013 : 5 : case E_V16SFmode:
26014 : 5 : case E_V8SFmode:
26015 : 5 : return V4SFmode;
26016 : 16 : case E_V8DFmode:
26017 : 16 : case E_V4DFmode:
26018 : 16 : return V2DFmode;
26019 : 1693 : default:
26020 : 1693 : return mode;
26021 : : }
26022 : : }
26023 : :
26024 : : /* Generate call to __divmoddi4. */
26025 : :
26026 : : void
26027 : 906 : ix86_expand_divmod_libfunc (rtx libfunc, machine_mode mode,
26028 : : rtx op0, rtx op1,
26029 : : rtx *quot_p, rtx *rem_p)
26030 : : {
26031 : 1812 : rtx rem = assign_stack_temp (mode, GET_MODE_SIZE (mode));
26032 : :
26033 : 906 : rtx quot = emit_library_call_value (libfunc, NULL_RTX, LCT_NORMAL,
26034 : : mode, op0, mode, op1, mode,
26035 : 906 : XEXP (rem, 0), Pmode);
26036 : 906 : *quot_p = quot;
26037 : 906 : *rem_p = rem;
26038 : 906 : }
26039 : :
26040 : : void
26041 : 64 : ix86_expand_atomic_fetch_op_loop (rtx target, rtx mem, rtx val,
26042 : : enum rtx_code code, bool after,
26043 : : bool doubleword)
26044 : : {
26045 : 64 : rtx old_reg, new_reg, old_mem, success;
26046 : 64 : machine_mode mode = GET_MODE (target);
26047 : 64 : rtx_code_label *loop_label = NULL;
26048 : :
26049 : 64 : old_reg = gen_reg_rtx (mode);
26050 : 64 : new_reg = old_reg;
26051 : 64 : old_mem = copy_to_reg (mem);
26052 : 64 : loop_label = gen_label_rtx ();
26053 : 64 : emit_label (loop_label);
26054 : 64 : emit_move_insn (old_reg, old_mem);
26055 : :
26056 : : /* return value for atomic_fetch_op. */
26057 : 64 : if (!after)
26058 : 32 : emit_move_insn (target, old_reg);
26059 : :
26060 : 64 : if (code == NOT)
26061 : : {
26062 : 16 : new_reg = expand_simple_binop (mode, AND, new_reg, val, NULL_RTX,
26063 : : true, OPTAB_LIB_WIDEN);
26064 : 16 : new_reg = expand_simple_unop (mode, code, new_reg, NULL_RTX, true);
26065 : : }
26066 : : else
26067 : 48 : new_reg = expand_simple_binop (mode, code, new_reg, val, NULL_RTX,
26068 : : true, OPTAB_LIB_WIDEN);
26069 : :
26070 : : /* return value for atomic_op_fetch. */
26071 : 64 : if (after)
26072 : 32 : emit_move_insn (target, new_reg);
26073 : :
26074 : 64 : success = NULL_RTX;
26075 : :
26076 : 64 : ix86_expand_cmpxchg_loop (&success, old_mem, mem, old_reg, new_reg,
26077 : : gen_int_mode (MEMMODEL_SYNC_SEQ_CST,
26078 : : SImode),
26079 : : doubleword, loop_label);
26080 : 64 : }
26081 : :
26082 : : /* Relax cmpxchg instruction, param loop_label indicates whether
26083 : : the instruction should be relaxed with a pause loop. If not,
26084 : : it will be relaxed to an atomic load + compare, and skip
26085 : : cmpxchg instruction if mem != exp_input. */
26086 : :
26087 : : void
26088 : 72 : ix86_expand_cmpxchg_loop (rtx *ptarget_bool, rtx target_val,
26089 : : rtx mem, rtx exp_input, rtx new_input,
26090 : : rtx mem_model, bool doubleword,
26091 : : rtx_code_label *loop_label)
26092 : : {
26093 : 72 : rtx_code_label *cmp_label = NULL;
26094 : 72 : rtx_code_label *done_label = NULL;
26095 : 72 : rtx target_bool = NULL_RTX, new_mem = NULL_RTX;
26096 : 72 : rtx (*gen) (rtx, rtx, rtx, rtx, rtx) = NULL;
26097 : 72 : rtx (*gendw) (rtx, rtx, rtx, rtx, rtx, rtx) = NULL;
26098 : 72 : machine_mode mode = GET_MODE (target_val), hmode = mode;
26099 : :
26100 : 72 : if (*ptarget_bool == NULL)
26101 : 64 : target_bool = gen_reg_rtx (QImode);
26102 : : else
26103 : : target_bool = *ptarget_bool;
26104 : :
26105 : 72 : cmp_label = gen_label_rtx ();
26106 : 72 : done_label = gen_label_rtx ();
26107 : :
26108 : 72 : new_mem = gen_reg_rtx (mode);
26109 : : /* Load memory first. */
26110 : 72 : expand_atomic_load (new_mem, mem, MEMMODEL_SEQ_CST);
26111 : :
26112 : 72 : switch (mode)
26113 : : {
26114 : : case E_TImode:
26115 : : gendw = gen_atomic_compare_and_swapti_doubleword;
26116 : : hmode = DImode;
26117 : : break;
26118 : 18 : case E_DImode:
26119 : 18 : if (doubleword)
26120 : : {
26121 : : gendw = gen_atomic_compare_and_swapdi_doubleword;
26122 : : hmode = SImode;
26123 : : }
26124 : : else
26125 : : gen = gen_atomic_compare_and_swapdi_1;
26126 : : break;
26127 : 18 : case E_SImode:
26128 : 18 : gen = gen_atomic_compare_and_swapsi_1;
26129 : 18 : break;
26130 : 18 : case E_HImode:
26131 : 18 : gen = gen_atomic_compare_and_swaphi_1;
26132 : 18 : break;
26133 : 18 : case E_QImode:
26134 : 18 : gen = gen_atomic_compare_and_swapqi_1;
26135 : 18 : break;
26136 : 0 : default:
26137 : 0 : gcc_unreachable ();
26138 : : }
26139 : :
26140 : : /* Compare mem value with expected value. */
26141 : 54 : if (doubleword)
26142 : : {
26143 : 0 : rtx low_new_mem = gen_lowpart (hmode, new_mem);
26144 : 0 : rtx low_exp_input = gen_lowpart (hmode, exp_input);
26145 : 0 : rtx high_new_mem = gen_highpart (hmode, new_mem);
26146 : 0 : rtx high_exp_input = gen_highpart (hmode, exp_input);
26147 : 0 : emit_cmp_and_jump_insns (low_new_mem, low_exp_input, NE, NULL_RTX,
26148 : : hmode, 1, cmp_label,
26149 : : profile_probability::guessed_never ());
26150 : 0 : emit_cmp_and_jump_insns (high_new_mem, high_exp_input, NE, NULL_RTX,
26151 : : hmode, 1, cmp_label,
26152 : : profile_probability::guessed_never ());
26153 : : }
26154 : : else
26155 : 72 : emit_cmp_and_jump_insns (new_mem, exp_input, NE, NULL_RTX,
26156 : 72 : GET_MODE (exp_input), 1, cmp_label,
26157 : : profile_probability::guessed_never ());
26158 : :
26159 : : /* Directly emits cmpxchg here. */
26160 : 72 : if (doubleword)
26161 : 0 : emit_insn (gendw (target_val, mem, exp_input,
26162 : 0 : gen_lowpart (hmode, new_input),
26163 : : gen_highpart (hmode, new_input),
26164 : : mem_model));
26165 : : else
26166 : 72 : emit_insn (gen (target_val, mem, exp_input, new_input, mem_model));
26167 : :
26168 : 72 : if (!loop_label)
26169 : : {
26170 : 8 : emit_jump_insn (gen_jump (done_label));
26171 : 8 : emit_barrier ();
26172 : 8 : emit_label (cmp_label);
26173 : 8 : emit_move_insn (target_val, new_mem);
26174 : 8 : emit_label (done_label);
26175 : 8 : ix86_expand_setcc (target_bool, EQ, gen_rtx_REG (CCZmode, FLAGS_REG),
26176 : : const0_rtx);
26177 : : }
26178 : : else
26179 : : {
26180 : 64 : ix86_expand_setcc (target_bool, EQ, gen_rtx_REG (CCZmode, FLAGS_REG),
26181 : : const0_rtx);
26182 : 64 : emit_cmp_and_jump_insns (target_bool, const0_rtx, EQ, const0_rtx,
26183 : 64 : GET_MODE (target_bool), 1, loop_label,
26184 : : profile_probability::guessed_never ());
26185 : 64 : emit_jump_insn (gen_jump (done_label));
26186 : 64 : emit_barrier ();
26187 : :
26188 : : /* If mem is not expected, pause and loop back. */
26189 : 64 : emit_label (cmp_label);
26190 : 64 : emit_move_insn (target_val, new_mem);
26191 : 64 : emit_insn (gen_pause ());
26192 : 64 : emit_jump_insn (gen_jump (loop_label));
26193 : 64 : emit_barrier ();
26194 : 64 : emit_label (done_label);
26195 : : }
26196 : :
26197 : 72 : *ptarget_bool = target_bool;
26198 : 72 : }
26199 : :
26200 : : /* Convert a BFmode VAL to SFmode without signaling sNaNs.
26201 : : This is done by returning SF SUBREG of ((HI SUBREG) (VAL)) << 16. */
26202 : :
26203 : : rtx
26204 : 1958 : ix86_expand_fast_convert_bf_to_sf (rtx val)
26205 : : {
26206 : 1958 : rtx op = gen_lowpart (HImode, val), ret;
26207 : 1958 : if (CONST_INT_P (op))
26208 : : {
26209 : 376 : ret = simplify_const_unary_operation (FLOAT_EXTEND, SFmode,
26210 : : val, BFmode);
26211 : 376 : if (ret)
26212 : : return ret;
26213 : : /* FLOAT_EXTEND simplification will fail if VAL is a sNaN. */
26214 : 1 : ret = gen_reg_rtx (SImode);
26215 : 1 : emit_move_insn (ret, GEN_INT (INTVAL (op) & 0xffff));
26216 : 1 : emit_insn (gen_ashlsi3 (ret, ret, GEN_INT (16)));
26217 : 1 : return gen_lowpart (SFmode, ret);
26218 : : }
26219 : :
26220 : 1582 : ret = gen_reg_rtx (SFmode);
26221 : 1582 : emit_insn (gen_extendbfsf2_1 (ret, force_reg (BFmode, val)));
26222 : 1582 : return ret;
26223 : : }
26224 : :
26225 : : rtx
26226 : 36 : ix86_gen_ccmp_first (rtx_insn **prep_seq, rtx_insn **gen_seq,
26227 : : rtx_code code, tree treeop0, tree treeop1)
26228 : : {
26229 : 36 : if (!TARGET_APX_CCMP)
26230 : : return NULL_RTX;
26231 : :
26232 : 36 : rtx op0, op1, res;
26233 : 36 : machine_mode op_mode;
26234 : :
26235 : 36 : start_sequence ();
26236 : 36 : expand_operands (treeop0, treeop1, NULL_RTX, &op0, &op1, EXPAND_NORMAL);
26237 : :
26238 : 36 : op_mode = GET_MODE (op0);
26239 : 36 : if (op_mode == VOIDmode)
26240 : 0 : op_mode = GET_MODE (op1);
26241 : :
26242 : : /* We only supports following scalar comparisons that use just 1
26243 : : instruction: DI/SI/QI/HI/DF/SF/HF.
26244 : : Unordered/Ordered compare cannot be corretly indentified by
26245 : : ccmp so they are not supported. */
26246 : 38 : if (!(op_mode == DImode || op_mode == SImode || op_mode == HImode
26247 : 36 : || op_mode == QImode || op_mode == DFmode || op_mode == SFmode
26248 : 2 : || op_mode == HFmode)
26249 : 36 : || code == ORDERED
26250 : 36 : || code == UNORDERED)
26251 : : {
26252 : 0 : end_sequence ();
26253 : 0 : return NULL_RTX;
26254 : : }
26255 : :
26256 : : /* Canonicalize the operands according to mode. */
26257 : 36 : if (SCALAR_INT_MODE_P (op_mode))
26258 : : {
26259 : 29 : if (!nonimmediate_operand (op0, op_mode))
26260 : 0 : op0 = force_reg (op_mode, op0);
26261 : 29 : if (!x86_64_general_operand (op1, op_mode))
26262 : 0 : op1 = force_reg (op_mode, op1);
26263 : : }
26264 : : else
26265 : : {
26266 : : /* op0/op1 can be canonicallized from expand_fp_compare, so
26267 : : just adjust the code to make it generate supported fp
26268 : : condition. */
26269 : 7 : if (ix86_fp_compare_code_to_integer (code) == UNKNOWN)
26270 : : {
26271 : : /* First try to split condition if we don't need to honor
26272 : : NaNs, as the ORDERED/UNORDERED check always fall
26273 : : through. */
26274 : 6 : if (!HONOR_NANS (op_mode))
26275 : : {
26276 : 6 : rtx_code first_code;
26277 : 6 : split_comparison (code, op_mode, &first_code, &code);
26278 : : }
26279 : : /* Otherwise try to swap the operand order and check if
26280 : : the comparison is supported. */
26281 : : else
26282 : : {
26283 : 0 : code = swap_condition (code);
26284 : 0 : std::swap (op0, op1);
26285 : : }
26286 : :
26287 : 6 : if (ix86_fp_compare_code_to_integer (code) == UNKNOWN)
26288 : : {
26289 : 0 : end_sequence ();
26290 : 0 : return NULL_RTX;
26291 : : }
26292 : : }
26293 : : }
26294 : :
26295 : 36 : *prep_seq = end_sequence ();
26296 : :
26297 : 36 : start_sequence ();
26298 : :
26299 : 36 : res = ix86_expand_compare (code, op0, op1);
26300 : :
26301 : 36 : if (!res)
26302 : : {
26303 : : end_sequence ();
26304 : : return NULL_RTX;
26305 : : }
26306 : 36 : *gen_seq = end_sequence ();
26307 : :
26308 : 36 : return res;
26309 : : }
26310 : :
26311 : : rtx
26312 : 39 : ix86_gen_ccmp_next (rtx_insn **prep_seq, rtx_insn **gen_seq, rtx prev,
26313 : : rtx_code cmp_code, tree treeop0, tree treeop1,
26314 : : rtx_code bit_code)
26315 : : {
26316 : 39 : if (!TARGET_APX_CCMP)
26317 : : return NULL_RTX;
26318 : :
26319 : 39 : rtx op0, op1, target;
26320 : 39 : machine_mode op_mode, cmp_mode, cc_mode = CCmode;
26321 : 39 : int unsignedp = TYPE_UNSIGNED (TREE_TYPE (treeop0));
26322 : 39 : insn_code icode;
26323 : 39 : rtx_code prev_code;
26324 : 39 : struct expand_operand ops[5];
26325 : 39 : int dfv;
26326 : :
26327 : 39 : push_to_sequence (*prep_seq);
26328 : 39 : expand_operands (treeop0, treeop1, NULL_RTX, &op0, &op1, EXPAND_NORMAL);
26329 : :
26330 : 39 : cmp_mode = op_mode = GET_MODE (op0);
26331 : :
26332 : 39 : if (!(op_mode == DImode || op_mode == SImode || op_mode == HImode
26333 : : || op_mode == QImode))
26334 : : {
26335 : 7 : end_sequence ();
26336 : 7 : return NULL_RTX;
26337 : : }
26338 : :
26339 : 32 : icode = code_for_ccmp (op_mode);
26340 : :
26341 : 32 : op0 = prepare_operand (icode, op0, 2, op_mode, cmp_mode, unsignedp);
26342 : 32 : op1 = prepare_operand (icode, op1, 3, op_mode, cmp_mode, unsignedp);
26343 : 32 : if (!op0 || !op1)
26344 : : {
26345 : 0 : end_sequence ();
26346 : 0 : return NULL_RTX;
26347 : : }
26348 : :
26349 : 32 : *prep_seq = end_sequence ();
26350 : :
26351 : 32 : target = gen_rtx_REG (cc_mode, FLAGS_REG);
26352 : 32 : dfv = ix86_get_flags_cc ((rtx_code) cmp_code);
26353 : :
26354 : 32 : prev_code = GET_CODE (prev);
26355 : : /* Fixup FP compare code here. */
26356 : 32 : if (GET_MODE (XEXP (prev, 0)) == CCFPmode)
26357 : 7 : prev_code = ix86_fp_compare_code_to_integer (prev_code);
26358 : :
26359 : 32 : if (bit_code != AND)
26360 : 17 : prev_code = reverse_condition (prev_code);
26361 : : else
26362 : 15 : dfv = (int)(dfv ^ 1);
26363 : :
26364 : 32 : prev = gen_rtx_fmt_ee (prev_code, VOIDmode, XEXP (prev, 0),
26365 : : const0_rtx);
26366 : :
26367 : 32 : create_fixed_operand (&ops[0], target);
26368 : 32 : create_fixed_operand (&ops[1], prev);
26369 : 32 : create_fixed_operand (&ops[2], op0);
26370 : 32 : create_fixed_operand (&ops[3], op1);
26371 : 32 : create_fixed_operand (&ops[4], GEN_INT (dfv));
26372 : :
26373 : 32 : push_to_sequence (*gen_seq);
26374 : 32 : if (!maybe_expand_insn (icode, 5, ops))
26375 : : {
26376 : 0 : end_sequence ();
26377 : 0 : return NULL_RTX;
26378 : : }
26379 : :
26380 : 32 : *gen_seq = end_sequence ();
26381 : :
26382 : 32 : return gen_rtx_fmt_ee ((rtx_code) cmp_code, VOIDmode, target, const0_rtx);
26383 : : }
26384 : :
26385 : : /* Attempt to convert a CONST_VECTOR into a bcst_mem_operand.
26386 : : Returns NULL_RTX if X is cannot be expressed as a suitable
26387 : : VEC_DUPLICATE in mode MODE. */
26388 : :
26389 : : static rtx
26390 : 49 : ix86_gen_bcst_mem (machine_mode mode, rtx x)
26391 : : {
26392 : 49 : if (!TARGET_AVX512F
26393 : 49 : || !CONST_VECTOR_P (x)
26394 : 65 : || (!TARGET_AVX512VL && GET_MODE_SIZE (mode) != 64)
26395 : 152 : || !VALID_BCST_MODE_P (GET_MODE_INNER (mode))
26396 : : /* Disallow HFmode broadcast. */
26397 : 129 : || GET_MODE_SIZE (GET_MODE_INNER (mode)) < 4)
26398 : : return NULL_RTX;
26399 : :
26400 : 21 : rtx cst = CONST_VECTOR_ELT (x, 0);
26401 : 21 : if (!CONST_SCALAR_INT_P (cst)
26402 : 15 : && !CONST_DOUBLE_P (cst)
26403 : 0 : && !CONST_FIXED_P (cst))
26404 : : return NULL_RTX;
26405 : :
26406 : 21 : int n_elts = GET_MODE_NUNITS (mode);
26407 : 42 : if (CONST_VECTOR_NUNITS (x) != n_elts)
26408 : : return NULL_RTX;
26409 : :
26410 : 150 : for (int i = 1; i < n_elts; i++)
26411 : 129 : if (!rtx_equal_p (cst, CONST_VECTOR_ELT (x, i)))
26412 : : return NULL_RTX;
26413 : :
26414 : 42 : rtx mem = force_const_mem (GET_MODE_INNER (mode), cst);
26415 : 21 : return gen_rtx_VEC_DUPLICATE (mode, validize_mem (mem));
26416 : : }
26417 : :
26418 : : /* Determine the ternlog immediate index that implements 3-operand
26419 : : ternary logic expression OP. This uses and modifies the 3 element
26420 : : array ARGS to record and check the leaves, either 3 REGs, or 2 REGs
26421 : : and MEM. Returns an index between 0 and 255 for a valid ternlog,
26422 : : or -1 if the expression isn't suitable. */
26423 : :
26424 : : int
26425 : 6040768 : ix86_ternlog_idx (rtx op, rtx *args)
26426 : : {
26427 : 6040768 : int idx0, idx1;
26428 : :
26429 : 6040768 : if (!op)
26430 : : return -1;
26431 : :
26432 : 6040768 : switch (GET_CODE (op))
26433 : : {
26434 : 646417 : case SUBREG:
26435 : 646417 : if (!register_operand (op, GET_MODE (op)))
26436 : : return -1;
26437 : : /* FALLTHRU */
26438 : :
26439 : 3015975 : case REG:
26440 : 3015975 : if (!args[0])
26441 : : {
26442 : 1524813 : args[0] = op;
26443 : 1524813 : return 0xf0;
26444 : : }
26445 : 1491162 : if (rtx_equal_p (op, args[0]))
26446 : : return 0xf0;
26447 : 1465040 : if (!args[1])
26448 : : {
26449 : 1260397 : args[1] = op;
26450 : 1260397 : return 0xcc;
26451 : : }
26452 : 204643 : if (rtx_equal_p (op, args[1]))
26453 : : return 0xcc;
26454 : 188243 : if (!args[2])
26455 : : {
26456 : 177280 : args[2] = op;
26457 : 177280 : return 0xaa;
26458 : : }
26459 : 10963 : if (rtx_equal_p (op, args[2]))
26460 : : return 0xaa;
26461 : : return -1;
26462 : :
26463 : 14726 : case VEC_DUPLICATE:
26464 : 14726 : if (!bcst_mem_operand (op, GET_MODE (op)))
26465 : : return -1;
26466 : 302 : goto do_mem_operand;
26467 : :
26468 : 206372 : case MEM:
26469 : 206372 : if (!memory_operand (op, GET_MODE (op)))
26470 : : return -1;
26471 : 206157 : if (MEM_P (op)
26472 : 206157 : && MEM_VOLATILE_P (op)
26473 : 206157 : && !volatile_ok)
26474 : : return -1;
26475 : : /* FALLTHRU */
26476 : :
26477 : 267214 : case CONST_VECTOR:
26478 : 267214 : do_mem_operand:
26479 : 267214 : if (!args[2])
26480 : : {
26481 : 248773 : args[2] = op;
26482 : 248773 : return 0xaa;
26483 : : }
26484 : : /* Maximum of one volatile memory reference per expression. */
26485 : 18441 : if (side_effects_p (op))
26486 : : return -1;
26487 : 18441 : if (rtx_equal_p (op, args[2]))
26488 : : return 0xaa;
26489 : : /* Check if CONST_VECTOR is the ones-complement of args[2]. */
26490 : 18410 : if (GET_CODE (op) == CONST_VECTOR
26491 : 2065 : && GET_CODE (args[2]) == CONST_VECTOR
26492 : 18791 : && rtx_equal_p (simplify_const_unary_operation (NOT, GET_MODE (op),
26493 : 381 : op, GET_MODE (op)),
26494 : : args[2]))
26495 : : return 0x55;
26496 : 18297 : if (!args[0])
26497 : : {
26498 : 16307 : args[0] = op;
26499 : 16307 : return 0xf0;
26500 : : }
26501 : 1990 : if (rtx_equal_p (op, args[0]))
26502 : : return 0xf0;
26503 : : /* Check if CONST_VECTOR is the ones-complement of args[0]. */
26504 : 1990 : if (GET_CODE (op) == CONST_VECTOR
26505 : 338 : && GET_CODE (args[0]) == CONST_VECTOR
26506 : 2032 : && rtx_equal_p (simplify_const_unary_operation (NOT, GET_MODE (op),
26507 : 42 : op, GET_MODE (op)),
26508 : : args[0]))
26509 : : return 0x0f;
26510 : 1948 : if (!args[1])
26511 : : {
26512 : 1936 : args[1] = op;
26513 : 1936 : return 0xcc;
26514 : : }
26515 : 12 : if (rtx_equal_p (op, args[1]))
26516 : : return 0xcc;
26517 : : /* Check if CONST_VECTOR is the ones-complement of args[1]. */
26518 : 12 : if (GET_CODE (op) == CONST_VECTOR
26519 : 0 : && GET_CODE (args[1]) == CONST_VECTOR
26520 : 12 : && rtx_equal_p (simplify_const_unary_operation (NOT, GET_MODE (op),
26521 : 0 : op, GET_MODE (op)),
26522 : : args[1]))
26523 : : return 0x33;
26524 : : return -1;
26525 : :
26526 : 178300 : case NOT:
26527 : 178300 : idx0 = ix86_ternlog_idx (XEXP (op, 0), args);
26528 : 178300 : return (idx0 >= 0) ? idx0 ^ 0xff : -1;
26529 : :
26530 : 1062955 : case AND:
26531 : 1062955 : idx0 = ix86_ternlog_idx (XEXP (op, 0), args);
26532 : 1062955 : if (idx0 < 0)
26533 : : return -1;
26534 : 853092 : idx1 = ix86_ternlog_idx (XEXP (op, 1), args);
26535 : 853092 : return (idx1 >= 0) ? idx0 & idx1 : -1;
26536 : :
26537 : 892144 : case IOR:
26538 : 892144 : idx0 = ix86_ternlog_idx (XEXP (op, 0), args);
26539 : 892144 : if (idx0 < 0)
26540 : : return -1;
26541 : 657863 : idx1 = ix86_ternlog_idx (XEXP (op, 1), args);
26542 : 657863 : return (idx1 >= 0) ? idx0 | idx1 : -1;
26543 : :
26544 : 258313 : case XOR:
26545 : 258313 : idx0 = ix86_ternlog_idx (XEXP (op, 0), args);
26546 : 258313 : if (idx0 < 0)
26547 : : return -1;
26548 : 242703 : if (vector_all_ones_operand (XEXP (op, 1), GET_MODE (op)))
26549 : 6110 : return idx0 ^ 0xff;
26550 : 236593 : idx1 = ix86_ternlog_idx (XEXP (op, 1), args);
26551 : 236593 : return (idx1 >= 0) ? idx0 ^ idx1 : -1;
26552 : :
26553 : 6632 : case UNSPEC:
26554 : 6632 : if (XINT (op, 1) != UNSPEC_VTERNLOG
26555 : 0 : || XVECLEN (op, 0) != 4
26556 : 0 : || !CONST_INT_P (XVECEXP (op, 0, 3)))
26557 : : return -1;
26558 : :
26559 : : /* TODO: Handle permuted operands. */
26560 : 0 : if (ix86_ternlog_idx (XVECEXP (op, 0, 0), args) != 0xf0
26561 : 0 : || ix86_ternlog_idx (XVECEXP (op, 0, 1), args) != 0xcc
26562 : 0 : || ix86_ternlog_idx (XVECEXP (op, 0, 2), args) != 0xaa)
26563 : 0 : return -1;
26564 : 0 : return INTVAL (XVECEXP (op, 0, 3));
26565 : :
26566 : : default:
26567 : : return -1;
26568 : : }
26569 : : }
26570 : :
26571 : : /* Return TRUE if OP (in mode MODE) is the leaf of a ternary logic
26572 : : expression, such as a register or a memory reference. */
26573 : :
26574 : : bool
26575 : 2754418 : ix86_ternlog_leaf_p (rtx op, machine_mode mode)
26576 : : {
26577 : : /* We can't use memory_operand here, as it may return a different
26578 : : value before and after reload (for volatile MEMs) which creates
26579 : : problems splitting instructions. */
26580 : 2754418 : return register_operand (op, mode)
26581 : 493668 : || MEM_P (op)
26582 : 301084 : || CONST_VECTOR_P (op)
26583 : 3001428 : || bcst_mem_operand (op, mode);
26584 : : }
26585 : :
26586 : : /* Test whether OP is a 3-operand ternary logic expression suitable
26587 : : for use in a ternlog instruction. */
26588 : :
26589 : : bool
26590 : 1866508 : ix86_ternlog_operand_p (rtx op)
26591 : : {
26592 : 1866508 : rtx op0, op1;
26593 : 1866508 : rtx args[3];
26594 : :
26595 : 1866508 : args[0] = NULL_RTX;
26596 : 1866508 : args[1] = NULL_RTX;
26597 : 1866508 : args[2] = NULL_RTX;
26598 : 1866508 : int idx = ix86_ternlog_idx (op, args);
26599 : 1866508 : if (idx < 0)
26600 : : return false;
26601 : :
26602 : : /* Don't match simple (binary or unary) expressions. */
26603 : 1491127 : machine_mode mode = GET_MODE (op);
26604 : 1491127 : switch (GET_CODE (op))
26605 : : {
26606 : 687005 : case AND:
26607 : 687005 : op0 = XEXP (op, 0);
26608 : 687005 : op1 = XEXP (op, 1);
26609 : :
26610 : : /* Prefer pand. */
26611 : 687005 : if (ix86_ternlog_leaf_p (op0, mode)
26612 : 687005 : && ix86_ternlog_leaf_p (op1, mode))
26613 : : return false;
26614 : : /* Prefer pandn. */
26615 : 109686 : if (GET_CODE (op0) == NOT
26616 : 79900 : && register_operand (XEXP (op0, 0), mode)
26617 : 185910 : && ix86_ternlog_leaf_p (op1, mode))
26618 : : return false;
26619 : : break;
26620 : :
26621 : 586902 : case IOR:
26622 : : /* Prefer por. */
26623 : 586902 : if (ix86_ternlog_leaf_p (XEXP (op, 0), mode)
26624 : 586902 : && ix86_ternlog_leaf_p (XEXP (op, 1), mode))
26625 : : return false;
26626 : : break;
26627 : :
26628 : 187863 : case XOR:
26629 : 187863 : op1 = XEXP (op, 1);
26630 : : /* Prefer pxor, or one_cmpl<vmode>2. */
26631 : 187863 : if (ix86_ternlog_leaf_p (XEXP (op, 0), mode)
26632 : 187863 : && ix86_ternlog_leaf_p (XEXP (op, 1), mode))
26633 : : return false;
26634 : : break;
26635 : :
26636 : : default:
26637 : : break;
26638 : : }
26639 : : return true;
26640 : : }
26641 : :
26642 : : /* Helper function for ix86_expand_ternlog. */
26643 : : static rtx
26644 : 0 : ix86_expand_ternlog_binop (enum rtx_code code, machine_mode mode,
26645 : : rtx op0, rtx op1, rtx target)
26646 : : {
26647 : 0 : if (GET_MODE (op0) != mode)
26648 : 0 : op0 = gen_lowpart (mode, op0);
26649 : 0 : if (GET_MODE (op1) != mode)
26650 : 0 : op1 = gen_lowpart (mode, op1);
26651 : :
26652 : 0 : if (CONST_VECTOR_P (op0))
26653 : 0 : op0 = validize_mem (force_const_mem (mode, op0));
26654 : 0 : if (CONST_VECTOR_P (op1))
26655 : 0 : op1 = validize_mem (force_const_mem (mode, op1));
26656 : :
26657 : 0 : if (!register_operand (op0, mode))
26658 : : {
26659 : 0 : if (!register_operand (op1, mode))
26660 : : {
26661 : : /* We can't use force_reg (op0, mode). */
26662 : 0 : rtx reg = gen_reg_rtx (mode);
26663 : 0 : emit_move_insn (reg, op0);
26664 : 0 : op0 = reg;
26665 : : }
26666 : : else
26667 : : std::swap (op0, op1);
26668 : : }
26669 : 0 : rtx ops[3] = { target, op0, op1 };
26670 : 0 : ix86_expand_vector_logical_operator (code, mode, ops);
26671 : 0 : return target;
26672 : : }
26673 : :
26674 : :
26675 : : /* Helper function for ix86_expand_ternlog. */
26676 : : static rtx
26677 : 0 : ix86_expand_ternlog_andnot (machine_mode mode, rtx op0, rtx op1, rtx target)
26678 : : {
26679 : 0 : if (GET_MODE (op0) != mode)
26680 : 0 : op0 = gen_lowpart (mode, op0);
26681 : 0 : op0 = gen_rtx_NOT (mode, op0);
26682 : 0 : if (GET_MODE (op1) != mode)
26683 : 0 : op1 = gen_lowpart (mode, op1);
26684 : 0 : if (CONST_VECTOR_P (op1))
26685 : 0 : op1 = validize_mem (force_const_mem (mode, op1));
26686 : 0 : emit_move_insn (target, gen_rtx_AND (mode, op0, op1));
26687 : 0 : return target;
26688 : : }
26689 : :
26690 : : /* Expand a 3-operand ternary logic expression. Return TARGET. */
26691 : : rtx
26692 : 2348 : ix86_expand_ternlog (machine_mode mode, rtx op0, rtx op1, rtx op2, int idx,
26693 : : rtx target)
26694 : : {
26695 : 2348 : rtx tmp0, tmp1, tmp2;
26696 : :
26697 : 2348 : if (!target)
26698 : 3 : target = gen_reg_rtx (mode);
26699 : :
26700 : : /* Canonicalize ternlog index for degenerate (duplicated) operands. */
26701 : 2348 : if (rtx_equal_p (op0, op1) && rtx_equal_p (op0, op2))
26702 : 0 : switch (idx & 0x81)
26703 : : {
26704 : : case 0x00:
26705 : : idx = 0x00;
26706 : : break;
26707 : : case 0x01:
26708 : : idx = 0x0f;
26709 : : break;
26710 : : case 0x80:
26711 : : idx = 0xf0;
26712 : : break;
26713 : : case 0x81:
26714 : : idx = 0xff;
26715 : : break;
26716 : : }
26717 : :
26718 : 2348 : switch (idx & 0xff)
26719 : : {
26720 : 0 : case 0x00:
26721 : 0 : if ((!op0 || !side_effects_p (op0))
26722 : 0 : && (!op1 || !side_effects_p (op1))
26723 : 0 : && (!op2 || !side_effects_p (op2)))
26724 : : {
26725 : 0 : emit_move_insn (target, CONST0_RTX (mode));
26726 : 0 : return target;
26727 : : }
26728 : : break;
26729 : :
26730 : 0 : case 0x0a: /* ~a&c */
26731 : 0 : if ((!op1 || !side_effects_p (op1))
26732 : 0 : && op0 && register_operand (op0, mode)
26733 : 0 : && op2 && ix86_ternlog_leaf_p (op2, mode))
26734 : 0 : return ix86_expand_ternlog_andnot (mode, op0, op2, target);
26735 : : break;
26736 : :
26737 : 0 : case 0x0c: /* ~a&b */
26738 : 0 : if ((!op2 || !side_effects_p (op2))
26739 : 0 : && op0 && register_operand (op0, mode)
26740 : 0 : && op1 && ix86_ternlog_leaf_p (op1, mode))
26741 : 0 : return ix86_expand_ternlog_andnot (mode, op0, op1, target);
26742 : : break;
26743 : :
26744 : 14 : case 0x0f: /* ~a */
26745 : 0 : if ((!op1 || !side_effects_p (op1))
26746 : 14 : && (!op2 || !side_effects_p (op2))
26747 : 28 : && op0)
26748 : : {
26749 : 14 : if (GET_MODE (op0) != mode)
26750 : 0 : op0 = gen_lowpart (mode, op0);
26751 : 14 : if (!TARGET_64BIT && !register_operand (op0, mode))
26752 : : {
26753 : : /* Avoid force_reg (mode, op0). */
26754 : 0 : rtx reg = gen_reg_rtx (mode);
26755 : 0 : emit_move_insn (reg, op0);
26756 : 0 : op0 = reg;
26757 : : }
26758 : 14 : emit_move_insn (target, gen_rtx_XOR (mode, op0, CONSTM1_RTX (mode)));
26759 : 14 : return target;
26760 : : }
26761 : : break;
26762 : :
26763 : 0 : case 0x22: /* ~b&c */
26764 : 0 : if ((!op0 || !side_effects_p (op0))
26765 : 0 : && op1 && register_operand (op1, mode)
26766 : 0 : && op2 && ix86_ternlog_leaf_p (op2, mode))
26767 : 0 : return ix86_expand_ternlog_andnot (mode, op1, op2, target);
26768 : : break;
26769 : :
26770 : 0 : case 0x30: /* ~b&a */
26771 : 0 : if ((!op2 || !side_effects_p (op2))
26772 : 0 : && op0 && ix86_ternlog_leaf_p (op0, mode)
26773 : 0 : && op1 && register_operand (op1, mode))
26774 : 0 : return ix86_expand_ternlog_andnot (mode, op1, op0, target);
26775 : : break;
26776 : :
26777 : 0 : case 0x33: /* ~b */
26778 : 0 : if ((!op0 || !side_effects_p (op0))
26779 : 0 : && (!op2 || !side_effects_p (op2))
26780 : 0 : && op1)
26781 : : {
26782 : 0 : if (GET_MODE (op1) != mode)
26783 : 0 : op1 = gen_lowpart (mode, op1);
26784 : 0 : if (!TARGET_64BIT && !register_operand (op1, mode))
26785 : : {
26786 : : /* Avoid force_reg (mode, op1). */
26787 : 0 : rtx reg = gen_reg_rtx (mode);
26788 : 0 : emit_move_insn (reg, op1);
26789 : 0 : op1 = reg;
26790 : : }
26791 : 0 : emit_move_insn (target, gen_rtx_XOR (mode, op1, CONSTM1_RTX (mode)));
26792 : 0 : return target;
26793 : : }
26794 : : break;
26795 : :
26796 : 0 : case 0x3c: /* a^b */
26797 : 0 : if (op0 && ix86_ternlog_leaf_p (op0, mode)
26798 : 0 : && op1 && ix86_ternlog_leaf_p (op1, mode)
26799 : 0 : && (!op2 || !side_effects_p (op2)))
26800 : 0 : return ix86_expand_ternlog_binop (XOR, mode, op0, op1, target);
26801 : : break;
26802 : :
26803 : 0 : case 0x44: /* ~c&b */
26804 : 0 : if ((!op0 || !side_effects_p (op0))
26805 : 0 : && op1 && ix86_ternlog_leaf_p (op1, mode)
26806 : 0 : && op2 && register_operand (op2, mode))
26807 : 0 : return ix86_expand_ternlog_andnot (mode, op2, op1, target);
26808 : : break;
26809 : :
26810 : 2 : case 0x50: /* ~c&a */
26811 : 0 : if ((!op1 || !side_effects_p (op1))
26812 : 2 : && op0 && ix86_ternlog_leaf_p (op0, mode)
26813 : 4 : && op2 && register_operand (op2, mode))
26814 : 0 : return ix86_expand_ternlog_andnot (mode, op2, op0, target);
26815 : : break;
26816 : :
26817 : 4 : case 0x55: /* ~c */
26818 : 1 : if ((!op0 || !side_effects_p (op0))
26819 : 4 : && (!op1 || !side_effects_p (op1))
26820 : 8 : && op2)
26821 : : {
26822 : 4 : if (GET_MODE (op2) != mode)
26823 : 0 : op2 = gen_lowpart (mode, op2);
26824 : 4 : if (!TARGET_64BIT && !register_operand (op2, mode))
26825 : : {
26826 : : /* Avoid force_reg (mode, op2). */
26827 : 0 : rtx reg = gen_reg_rtx (mode);
26828 : 0 : emit_move_insn (reg, op2);
26829 : 0 : op2 = reg;
26830 : : }
26831 : 4 : emit_move_insn (target, gen_rtx_XOR (mode, op2, CONSTM1_RTX (mode)));
26832 : 4 : return target;
26833 : : }
26834 : : break;
26835 : :
26836 : 0 : case 0x5a: /* a^c */
26837 : 0 : if (op0 && ix86_ternlog_leaf_p (op0, mode)
26838 : 0 : && op2 && ix86_ternlog_leaf_p (op2, mode)
26839 : 0 : && (!op1 || !side_effects_p (op1)))
26840 : 0 : return ix86_expand_ternlog_binop (XOR, mode, op0, op2, target);
26841 : : break;
26842 : :
26843 : 0 : case 0x66: /* b^c */
26844 : 0 : if ((!op0 || !side_effects_p (op0))
26845 : 0 : && op1 && ix86_ternlog_leaf_p (op1, mode)
26846 : 0 : && op2 && ix86_ternlog_leaf_p (op2, mode))
26847 : 0 : return ix86_expand_ternlog_binop (XOR, mode, op1, op2, target);
26848 : : break;
26849 : :
26850 : 0 : case 0x88: /* b&c */
26851 : 0 : if ((!op0 || !side_effects_p (op0))
26852 : 0 : && op1 && ix86_ternlog_leaf_p (op1, mode)
26853 : 0 : && op2 && ix86_ternlog_leaf_p (op2, mode))
26854 : 0 : return ix86_expand_ternlog_binop (AND, mode, op1, op2, target);
26855 : : break;
26856 : :
26857 : 0 : case 0xa0: /* a&c */
26858 : 0 : if ((!op1 || !side_effects_p (op1))
26859 : 0 : && op0 && ix86_ternlog_leaf_p (op0, mode)
26860 : 0 : && op2 && ix86_ternlog_leaf_p (op2, mode))
26861 : 0 : return ix86_expand_ternlog_binop (AND, mode, op0, op2, target);
26862 : : break;
26863 : :
26864 : 0 : case 0xaa: /* c */
26865 : 0 : if ((!op0 || !side_effects_p (op0))
26866 : 0 : && (!op1 || !side_effects_p (op1))
26867 : 0 : && op2)
26868 : : {
26869 : 0 : if (GET_MODE (op2) != mode)
26870 : 0 : op2 = gen_lowpart (mode, op2);
26871 : 0 : emit_move_insn (target, op2);
26872 : 0 : return target;
26873 : : }
26874 : : break;
26875 : :
26876 : 0 : case 0xc0: /* a&b */
26877 : 0 : if (op0 && ix86_ternlog_leaf_p (op0, mode)
26878 : 0 : && op1 && ix86_ternlog_leaf_p (op1, mode)
26879 : 0 : && (!op2 || !side_effects_p (op2)))
26880 : 0 : return ix86_expand_ternlog_binop (AND, mode, op0, op1, target);
26881 : : break;
26882 : :
26883 : 0 : case 0xcc: /* b */
26884 : 0 : if ((!op0 || !side_effects_p (op0))
26885 : 0 : && op1
26886 : 0 : && (!op2 || !side_effects_p (op2)))
26887 : : {
26888 : 0 : if (GET_MODE (op1) != mode)
26889 : 0 : op1 = gen_lowpart (mode, op1);
26890 : 0 : emit_move_insn (target, op1);
26891 : 0 : return target;
26892 : : }
26893 : : break;
26894 : :
26895 : 0 : case 0xee: /* b|c */
26896 : 0 : if ((!op0 || !side_effects_p (op0))
26897 : 0 : && op1 && ix86_ternlog_leaf_p (op1, mode)
26898 : 0 : && op2 && ix86_ternlog_leaf_p (op2, mode))
26899 : 0 : return ix86_expand_ternlog_binop (IOR, mode, op1, op2, target);
26900 : : break;
26901 : :
26902 : 6 : case 0xf0: /* a */
26903 : 6 : if (op0
26904 : 6 : && (!op1 || !side_effects_p (op1))
26905 : 12 : && (!op2 || !side_effects_p (op2)))
26906 : : {
26907 : 6 : if (GET_MODE (op0) != mode)
26908 : 0 : op0 = gen_lowpart (mode, op0);
26909 : 6 : emit_move_insn (target, op0);
26910 : 6 : return target;
26911 : : }
26912 : : break;
26913 : :
26914 : 0 : case 0xfa: /* a|c */
26915 : 0 : if (op0 && ix86_ternlog_leaf_p (op0, mode)
26916 : 0 : && op2 && ix86_ternlog_leaf_p (op2, mode)
26917 : 0 : && (!op1 || !side_effects_p (op1)))
26918 : 0 : return ix86_expand_ternlog_binop (IOR, mode, op0, op2, target);
26919 : : break;
26920 : :
26921 : 0 : case 0xfc: /* a|b */
26922 : 0 : if (op0 && ix86_ternlog_leaf_p (op0, mode)
26923 : 0 : && op1 && ix86_ternlog_leaf_p (op1, mode)
26924 : 0 : && (!op2 || !side_effects_p (op2)))
26925 : 0 : return ix86_expand_ternlog_binop (IOR, mode, op0, op1, target);
26926 : : break;
26927 : :
26928 : 0 : case 0xff:
26929 : 0 : if ((!op0 || !side_effects_p (op0))
26930 : 0 : && (!op1 || !side_effects_p (op1))
26931 : 0 : && (!op2 || !side_effects_p (op2)))
26932 : : {
26933 : 0 : emit_move_insn (target, CONSTM1_RTX (mode));
26934 : 0 : return target;
26935 : : }
26936 : : break;
26937 : : }
26938 : :
26939 : 2324 : if (!register_operand (op0, mode))
26940 : : {
26941 : : /* We can't use force_reg (mode, op0). */
26942 : 12 : tmp0 = gen_reg_rtx (GET_MODE (op0));
26943 : 12 : emit_move_insn (tmp0,op0);
26944 : : }
26945 : : else
26946 : : tmp0 = op0;
26947 : 2324 : if (GET_MODE (tmp0) != mode)
26948 : 0 : tmp0 = gen_lowpart (mode, tmp0);
26949 : :
26950 : 2324 : if (!op1 || rtx_equal_p (op0, op1))
26951 : 6 : tmp1 = copy_rtx (tmp0);
26952 : 2318 : else if (!register_operand (op1, mode))
26953 : : {
26954 : : /* We can't use force_reg (mode, op1). */
26955 : 37 : tmp1 = gen_reg_rtx (GET_MODE (op1));
26956 : 37 : emit_move_insn (tmp1, op1);
26957 : : }
26958 : : else
26959 : : tmp1 = op1;
26960 : 2324 : if (GET_MODE (tmp1) != mode)
26961 : 0 : tmp1 = gen_lowpart (mode, tmp1);
26962 : :
26963 : 2324 : if (!op2 || rtx_equal_p (op0, op2))
26964 : 71 : tmp2 = copy_rtx (tmp0);
26965 : 2253 : else if (rtx_equal_p (op1, op2))
26966 : 0 : tmp2 = copy_rtx (tmp1);
26967 : 2253 : else if (CONST_VECTOR_P (op2))
26968 : : {
26969 : 44 : if (GET_MODE (op2) != mode)
26970 : 0 : op2 = gen_lowpart (mode, op2);
26971 : 44 : tmp2 = ix86_gen_bcst_mem (mode, op2);
26972 : 44 : if (!tmp2)
26973 : : {
26974 : 26 : machine_mode bcst32_mode = mode;
26975 : 26 : machine_mode bcst64_mode = mode;
26976 : 26 : switch (mode)
26977 : : {
26978 : 1 : case V1TImode:
26979 : 1 : case V4SImode:
26980 : 1 : case V4SFmode:
26981 : 1 : case V8HImode:
26982 : 1 : case V16QImode:
26983 : 1 : bcst32_mode = V4SImode;
26984 : 1 : bcst64_mode = V2DImode;
26985 : 1 : break;
26986 : :
26987 : 0 : case V2TImode:
26988 : 0 : case V8SImode:
26989 : 0 : case V8SFmode:
26990 : 0 : case V16HImode:
26991 : 0 : case V32QImode:
26992 : 0 : bcst32_mode = V8SImode;
26993 : 0 : bcst64_mode = V4DImode;
26994 : 0 : break;
26995 : :
26996 : 3 : case V4TImode:
26997 : 3 : case V16SImode:
26998 : 3 : case V16SFmode:
26999 : 3 : case V32HImode:
27000 : 3 : case V64QImode:
27001 : 3 : bcst32_mode = V16SImode;
27002 : 3 : bcst64_mode = V8DImode;
27003 : 3 : break;
27004 : :
27005 : : default:
27006 : : break;
27007 : : }
27008 : :
27009 : 26 : if (bcst32_mode != mode)
27010 : : {
27011 : 4 : tmp2 = gen_lowpart (bcst32_mode, op2);
27012 : 4 : if (ix86_gen_bcst_mem (bcst32_mode, tmp2))
27013 : : {
27014 : 3 : tmp2 = ix86_expand_ternlog (bcst32_mode,
27015 : 3 : gen_lowpart (bcst32_mode, tmp0),
27016 : 3 : gen_lowpart (bcst32_mode, tmp1),
27017 : : tmp2, idx, NULL_RTX);
27018 : 3 : emit_move_insn (target, gen_lowpart (mode, tmp2));
27019 : 3 : return target;
27020 : : }
27021 : : }
27022 : :
27023 : 23 : if (bcst64_mode != mode)
27024 : : {
27025 : 1 : tmp2 = gen_lowpart (bcst64_mode, op2);
27026 : 1 : if (ix86_gen_bcst_mem (bcst64_mode, tmp2))
27027 : : {
27028 : 0 : tmp2 = ix86_expand_ternlog (bcst64_mode,
27029 : 0 : gen_lowpart (bcst64_mode, tmp0),
27030 : 0 : gen_lowpart (bcst64_mode, tmp1),
27031 : : tmp2, idx, NULL_RTX);
27032 : 0 : emit_move_insn (target, gen_lowpart (mode, tmp2));
27033 : 0 : return target;
27034 : : }
27035 : : }
27036 : :
27037 : 23 : tmp2 = force_const_mem (mode, op2);
27038 : 23 : rtx bcast = ix86_broadcast_from_constant (mode, tmp2);
27039 : 23 : tmp2 = validize_mem (tmp2);
27040 : 23 : if (bcast)
27041 : : {
27042 : 12 : rtx reg2 = gen_reg_rtx (mode);
27043 : 12 : bool ok = ix86_expand_vector_init_duplicate (false, mode,
27044 : : reg2, bcast);
27045 : 12 : if (ok)
27046 : 2321 : tmp2 = reg2;
27047 : : }
27048 : : }
27049 : : }
27050 : : else
27051 : : tmp2 = op2;
27052 : 2321 : if (GET_MODE (tmp2) != mode)
27053 : 0 : tmp2 = gen_lowpart (mode, tmp2);
27054 : : /* Some memory_operands are not vector_memory_operands. */
27055 : 2321 : if (!bcst_vector_operand (tmp2, mode))
27056 : 0 : tmp2 = force_reg (mode, tmp2);
27057 : :
27058 : 2321 : rtvec vec = gen_rtvec (4, tmp0, tmp1, tmp2, GEN_INT (idx));
27059 : 2321 : emit_move_insn (target, gen_rtx_UNSPEC (mode, vec, UNSPEC_VTERNLOG));
27060 : 2321 : return target;
27061 : : }
27062 : :
27063 : : /* Trunc a vector to a narrow vector, like v4di -> v4si. */
27064 : :
27065 : : void
27066 : 60 : ix86_expand_trunc_with_avx2_noavx512f (rtx output, rtx input, machine_mode cvt_mode)
27067 : : {
27068 : 60 : machine_mode out_mode = GET_MODE (output);
27069 : 60 : machine_mode in_mode = GET_MODE (input);
27070 : 60 : int len = GET_MODE_SIZE (in_mode);
27071 : 240 : gcc_assert (len == GET_MODE_SIZE (cvt_mode)
27072 : : && GET_MODE_INNER (out_mode) == GET_MODE_INNER (cvt_mode)
27073 : : && (REG_P (input) || SUBREG_P (input)));
27074 : 60 : scalar_mode inner_out_mode = GET_MODE_INNER (out_mode);
27075 : 120 : int in_innersize = GET_MODE_SIZE (GET_MODE_INNER (in_mode));
27076 : 60 : int out_innersize = GET_MODE_SIZE (inner_out_mode);
27077 : :
27078 : 60 : struct expand_vec_perm_d d;
27079 : 60 : d.target = gen_reg_rtx (cvt_mode);
27080 : 60 : d.op0 = lowpart_subreg (cvt_mode, force_reg(in_mode, input), in_mode);
27081 : 60 : d.op1 = d.op0;
27082 : 60 : d.vmode = cvt_mode;
27083 : 60 : d.nelt = GET_MODE_NUNITS (cvt_mode);
27084 : 60 : d.testing_p = false;
27085 : 60 : d.one_operand_p = true;
27086 : :
27087 : : /* Init perm. Put the needed bits of input in order and
27088 : : fill the rest of bits by default. */
27089 : 636 : for (int i = 0; i < d.nelt; ++i)
27090 : : {
27091 : 576 : d.perm[i] = i;
27092 : 1152 : if (i < GET_MODE_NUNITS (out_mode))
27093 : 234 : d.perm[i] = i * (in_innersize / out_innersize);
27094 : : }
27095 : :
27096 : 60 : bool ok = ix86_expand_vec_perm_const_1(&d);
27097 : 60 : gcc_assert (ok);
27098 : 60 : emit_move_insn (output, gen_lowpart (out_mode, d.target));
27099 : 60 : }
27100 : :
27101 : : /* Implement truncv8sfv8bf2 with vector permutation. */
27102 : : void
27103 : 8 : ix86_expand_vector_sf2bf_with_vec_perm (rtx dest, rtx src)
27104 : : {
27105 : 8 : machine_mode vperm_mode, src_mode = GET_MODE (src);
27106 : 8 : switch (src_mode)
27107 : : {
27108 : : case V16SFmode:
27109 : : vperm_mode = V32BFmode;
27110 : : break;
27111 : 2 : case V8SFmode:
27112 : 2 : vperm_mode = V16BFmode;
27113 : 2 : break;
27114 : 4 : case V4SFmode:
27115 : 4 : vperm_mode = V8BFmode;
27116 : 4 : break;
27117 : 0 : default:
27118 : 0 : gcc_unreachable ();
27119 : : }
27120 : :
27121 : 8 : int nelt = GET_MODE_NUNITS (vperm_mode);
27122 : 8 : vec_perm_builder sel (nelt, nelt, 1);
27123 : 8 : sel.quick_grow (nelt);
27124 : 136 : for (int i = 0; i != nelt; i++)
27125 : 128 : sel[i] = (2 * i + 1) % nelt;
27126 : 16 : vec_perm_indices indices (sel, 1, nelt);
27127 : :
27128 : 8 : rtx target = gen_reg_rtx (vperm_mode);
27129 : 8 : rtx op0 = lowpart_subreg (vperm_mode,
27130 : : force_reg (src_mode, src),
27131 : : src_mode);
27132 : 8 : bool ok = targetm.vectorize.vec_perm_const (vperm_mode, vperm_mode,
27133 : : target, op0, op0, indices);
27134 : 8 : gcc_assert (ok);
27135 : 8 : emit_move_insn (dest, lowpart_subreg (GET_MODE (dest), target, vperm_mode));
27136 : 8 : }
27137 : :
27138 : : /* Implement extendv8bf2v8sf2 with vector permutation. */
27139 : : void
27140 : 8 : ix86_expand_vector_bf2sf_with_vec_perm (rtx dest, rtx src)
27141 : : {
27142 : 8 : machine_mode vperm_mode, src_mode = GET_MODE (src);
27143 : 8 : switch (src_mode)
27144 : : {
27145 : : case V16BFmode:
27146 : : vperm_mode = V32BFmode;
27147 : : break;
27148 : 2 : case V8BFmode:
27149 : 2 : vperm_mode = V16BFmode;
27150 : 2 : break;
27151 : 4 : case V4BFmode:
27152 : 4 : vperm_mode = V8BFmode;
27153 : 4 : break;
27154 : 0 : default:
27155 : 0 : gcc_unreachable ();
27156 : : }
27157 : :
27158 : 8 : int nelt = GET_MODE_NUNITS (vperm_mode);
27159 : 8 : vec_perm_builder sel (nelt, nelt, 1);
27160 : 8 : sel.quick_grow (nelt);
27161 : 136 : for (int i = 0, k = 0, j = nelt; i != nelt; i++)
27162 : 128 : sel[i] = i & 1 ? j++ : k++;
27163 : :
27164 : 16 : vec_perm_indices indices (sel, 2, nelt);
27165 : :
27166 : 8 : rtx target = gen_reg_rtx (vperm_mode);
27167 : 8 : rtx op1 = lowpart_subreg (vperm_mode,
27168 : : force_reg (src_mode, src),
27169 : : src_mode);
27170 : 8 : rtx op0 = CONST0_RTX (vperm_mode);
27171 : 8 : bool ok = targetm.vectorize.vec_perm_const (vperm_mode, vperm_mode,
27172 : : target, op0, op1, indices);
27173 : 8 : gcc_assert (ok);
27174 : 8 : emit_move_insn (dest, lowpart_subreg (GET_MODE (dest), target, vperm_mode));
27175 : 8 : }
27176 : :
27177 : :
27178 : : #include "gt-i386-expand.h"
|