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 : 4155761 : split_double_mode (machine_mode mode, rtx operands[],
106 : : int num, rtx lo_half[], rtx hi_half[])
107 : : {
108 : 4155761 : machine_mode half_mode;
109 : 4155761 : unsigned int byte;
110 : 4155761 : rtx mem_op = NULL_RTX;
111 : 4155761 : int mem_num = 0;
112 : :
113 : 4155761 : switch (mode)
114 : : {
115 : : case E_TImode:
116 : : half_mode = DImode;
117 : : break;
118 : 607994 : case E_DImode:
119 : 607994 : half_mode = SImode;
120 : 607994 : 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 : 4155761 : byte = GET_MODE_SIZE (half_mode);
132 : :
133 : 8517239 : while (num--)
134 : : {
135 : 4361478 : rtx op = operands[num];
136 : :
137 : : /* simplify_subreg refuse to split volatile memory addresses,
138 : : but we still have to handle it. */
139 : 4361478 : if (MEM_P (op))
140 : : {
141 : 1704894 : if (mem_op && rtx_equal_p (op, mem_op))
142 : : {
143 : 2424 : lo_half[num] = lo_half[mem_num];
144 : 2424 : hi_half[num] = hi_half[mem_num];
145 : : }
146 : : else
147 : : {
148 : 1702470 : mem_op = op;
149 : 1702470 : mem_num = num;
150 : 1702470 : lo_half[num] = adjust_address (op, half_mode, 0);
151 : 1702470 : hi_half[num] = adjust_address (op, half_mode, byte);
152 : : }
153 : : }
154 : : else
155 : : {
156 : 2656584 : lo_half[num] = simplify_gen_subreg (half_mode, op,
157 : 2656584 : GET_MODE (op) == VOIDmode
158 : : ? mode : GET_MODE (op), 0);
159 : :
160 : 2656584 : rtx tmp = simplify_gen_subreg (half_mode, op,
161 : 2656584 : GET_MODE (op) == VOIDmode
162 : 2656584 : ? mode : GET_MODE (op), byte);
163 : : /* simplify_gen_subreg will return NULL RTX for the
164 : : high half of the paradoxical subreg. */
165 : 2656584 : hi_half[num] = tmp ? tmp : gen_reg_rtx (half_mode);
166 : : }
167 : : }
168 : 4155761 : }
169 : :
170 : : /* Emit the double word assignment DST = { LO, HI }. */
171 : :
172 : : void
173 : 109823 : split_double_concat (machine_mode mode, rtx dst, rtx lo, rtx hi)
174 : : {
175 : 109823 : rtx dlo, dhi;
176 : 109823 : int deleted_move_count = 0;
177 : 109823 : 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 : 109823 : if (MEM_P (lo)
183 : 4782 : && rtx_equal_p (dlo, hi)
184 : 110715 : && 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 : 175 : emit_move_insn (dhi, lo);
192 : 175 : lo = dhi;
193 : : }
194 : 109648 : else if (MEM_P (hi)
195 : 9103 : && !MEM_P (lo)
196 : 6929 : && !rtx_equal_p (dlo, lo)
197 : 111343 : && 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 : 109823 : if (!rtx_equal_p (dlo, hi))
217 : : {
218 : 95381 : if (!rtx_equal_p (dlo, lo))
219 : 44173 : emit_move_insn (dlo, lo);
220 : : else
221 : : deleted_move_count++;
222 : 95381 : if (!rtx_equal_p (dhi, hi))
223 : 88135 : emit_move_insn (dhi, hi);
224 : : else
225 : 7246 : deleted_move_count++;
226 : : }
227 : 14442 : else if (!rtx_equal_p (lo, dhi))
228 : : {
229 : 7434 : if (!rtx_equal_p (dhi, hi))
230 : 7434 : emit_move_insn (dhi, hi);
231 : : else
232 : : deleted_move_count++;
233 : 7434 : if (!rtx_equal_p (dlo, lo))
234 : 7318 : emit_move_insn (dlo, lo);
235 : : else
236 : 116 : deleted_move_count++;
237 : : }
238 : 7008 : else if (mode == TImode)
239 : 6990 : emit_insn (gen_swapdi (dlo, dhi));
240 : : else
241 : 18 : emit_insn (gen_swapsi (dlo, dhi));
242 : :
243 : 109823 : if (deleted_move_count == 2)
244 : 3848 : emit_note (NOTE_INSN_DELETED);
245 : 109823 : }
246 : :
247 : :
248 : : /* Generate either "mov $0, reg" or "xor reg, reg", as appropriate
249 : : for the target. */
250 : :
251 : : void
252 : 112312 : ix86_expand_clear (rtx dest)
253 : : {
254 : 112312 : rtx tmp;
255 : :
256 : : /* We play register width games, which are only valid after reload. */
257 : 112312 : gcc_assert (reload_completed);
258 : :
259 : : /* Avoid HImode and its attendant prefix byte. */
260 : 224624 : if (GET_MODE_SIZE (GET_MODE (dest)) < 4)
261 : 1029 : dest = gen_rtx_REG (SImode, REGNO (dest));
262 : 112312 : tmp = gen_rtx_SET (dest, const0_rtx);
263 : :
264 : 112312 : if (!TARGET_USE_MOV0 || optimize_insn_for_size_p ())
265 : : {
266 : 112312 : rtx clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
267 : 112312 : tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, tmp, clob));
268 : : }
269 : :
270 : 112312 : emit_insn (tmp);
271 : 112312 : }
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 : 39973 : 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 : 39973 : if (!TARGET_INTER_UNIT_MOVES_TO_VEC)
300 : : return nullptr;
301 : :
302 : 39973 : unsigned int msize = GET_MODE_SIZE (mode);
303 : :
304 : : /* Only optimized for vpbroadcast[bwsd]/vbroadcastss with xmm/ymm/zmm. */
305 : 39973 : 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 : 39973 : if (!TARGET_AVX
311 : 1604 : || !CONST_WIDE_INT_P (op)
312 : 1597 : || standard_sse_constant_p (op, mode)
313 : 41570 : || (CONST_WIDE_INT_NUNITS (op) * HOST_BITS_PER_WIDE_INT
314 : 1597 : != GET_MODE_BITSIZE (mode)))
315 : 38384 : 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 : 73125089 : ix86_expand_move (machine_mode mode, rtx operands[])
365 : : {
366 : 73125089 : rtx op0, op1;
367 : 73125089 : rtx tmp, addend = NULL_RTX;
368 : 73125089 : enum tls_model model;
369 : :
370 : 73125089 : op0 = operands[0];
371 : 73125089 : op1 = operands[1];
372 : :
373 : : /* Avoid complex sets of likely spilled hard registers before reload. */
374 : 73125089 : if (!ix86_hardreg_mov_ok (op0, op1))
375 : : {
376 : 139812 : tmp = gen_reg_rtx (mode);
377 : 139812 : operands[0] = tmp;
378 : 139812 : ix86_expand_move (mode, operands);
379 : 139812 : operands[0] = op0;
380 : 139812 : operands[1] = tmp;
381 : 139812 : op1 = tmp;
382 : : }
383 : :
384 : 73125089 : switch (GET_CODE (op1))
385 : : {
386 : 362463 : case CONST:
387 : 362463 : tmp = XEXP (op1, 0);
388 : :
389 : 362463 : if (GET_CODE (tmp) != PLUS
390 : 350797 : || GET_CODE (XEXP (tmp, 0)) != SYMBOL_REF)
391 : : break;
392 : :
393 : 348168 : op1 = XEXP (tmp, 0);
394 : 348168 : addend = XEXP (tmp, 1);
395 : : /* FALLTHRU */
396 : :
397 : 4928122 : case SYMBOL_REF:
398 : 4928122 : model = SYMBOL_REF_TLS_MODEL (op1);
399 : :
400 : 4928122 : if (model)
401 : 9822 : op1 = legitimize_tls_address (op1, model, true);
402 : 4918300 : 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 : 4918280 : {
427 : 4918280 : op1 = operands[1];
428 : 4918280 : break;
429 : : }
430 : : }
431 : :
432 : 9842 : 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 : 7056 : op1 = force_operand (op1, op0);
440 : :
441 : 9842 : if (op1 == op0)
442 : : return;
443 : :
444 : 4529 : op1 = convert_to_mode (mode, op1, 1);
445 : :
446 : : default:
447 : : break;
448 : :
449 : 1536627 : case SUBREG:
450 : : /* Transform TImode paradoxical SUBREG into zero_extendditi2. */
451 : 1536627 : if (TARGET_64BIT
452 : 1312286 : && mode == TImode
453 : : && SUBREG_P (op1)
454 : 74899 : && GET_MODE (SUBREG_REG (op1)) == DImode
455 : 1582976 : && SUBREG_BYTE (op1) == 0)
456 : 46349 : 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 : 1536627 : 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 : 73119776 : if ((flag_pic || MACHOPIC_INDIRECT)
475 : 73119776 : && 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 : 328654 : if (MEM_P (op0))
500 : 86383 : op1 = force_reg (mode, op1);
501 : 242271 : else if (!(TARGET_64BIT && x86_64_movabs_operand (op1, DImode)))
502 : : {
503 : 242233 : rtx reg = can_create_pseudo_p () ? NULL_RTX : op0;
504 : 242233 : op1 = legitimize_pic_address (op1, reg);
505 : 242233 : if (op0 == op1)
506 : : return;
507 : 242233 : op1 = convert_to_mode (mode, op1, 1);
508 : : }
509 : : }
510 : : else
511 : : {
512 : 72791122 : if (MEM_P (op0)
513 : 98823939 : && (PUSH_ROUNDING (GET_MODE_SIZE (mode)) != GET_MODE_SIZE (mode)
514 : 10602102 : || !push_operand (op0, mode))
515 : 84857079 : && MEM_P (op1))
516 : 2219037 : op1 = force_reg (mode, op1);
517 : :
518 : 72791122 : if (push_operand (op0, mode)
519 : 72791122 : && ! general_no_elim_operand (op1, mode))
520 : 1002 : op1 = copy_to_mode_reg (mode, op1);
521 : :
522 : : /* Force large constants in 64bit compilation into register
523 : : to get them CSEed. */
524 : 72791122 : if (can_create_pseudo_p ()
525 : 67092898 : && (mode == DImode) && TARGET_64BIT
526 : 34928006 : && immediate_operand (op1, mode)
527 : 8001767 : && !x86_64_zext_immediate_operand (op1, VOIDmode)
528 : 701782 : && !register_operand (op0, mode)
529 : 72961713 : && optimize)
530 : 119357 : op1 = copy_to_mode_reg (mode, op1);
531 : :
532 : 72791122 : if (can_create_pseudo_p ())
533 : : {
534 : 67092898 : 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 : 888477 : op1 = validize_mem (force_const_mem (mode, op1));
541 : 888477 : if (!register_operand (op0, mode))
542 : : {
543 : 128152 : tmp = gen_reg_rtx (mode);
544 : 128152 : emit_insn (gen_rtx_SET (tmp, op1));
545 : 128152 : emit_move_insn (op0, tmp);
546 : 128152 : return;
547 : : }
548 : : }
549 : : }
550 : : }
551 : :
552 : : /* Special case inserting 64-bit values into a TImode register. */
553 : 72991624 : if (TARGET_64BIT
554 : : /* Disable for -O0 (see PR110587) unless naked (PR110533). */
555 : 63308426 : && (optimize || ix86_function_naked (current_function_decl))
556 : 43795124 : && (mode == DImode || mode == DFmode)
557 : 29787887 : && SUBREG_P (op0)
558 : 504584 : && GET_MODE (SUBREG_REG (op0)) == TImode
559 : 422728 : && REG_P (SUBREG_REG (op0))
560 : 73414352 : && REG_P (op1))
561 : : {
562 : : /* Use *insvti_lowpart_1 to set lowpart. */
563 : 193262 : if (SUBREG_BYTE (op0) == 0)
564 : : {
565 : 59132 : wide_int mask = wi::mask (64, true, 128);
566 : 59132 : tmp = immed_wide_int_const (mask, TImode);
567 : 59132 : op0 = SUBREG_REG (op0);
568 : 59132 : tmp = gen_rtx_AND (TImode, copy_rtx (op0), tmp);
569 : 59132 : if (mode == DFmode)
570 : 348 : op1 = gen_lowpart (DImode, op1);
571 : 59132 : op1 = gen_rtx_ZERO_EXTEND (TImode, op1);
572 : 59132 : op1 = gen_rtx_IOR (TImode, tmp, op1);
573 : 59132 : }
574 : : /* Use *insvti_highpart_1 to set highpart. */
575 : 134130 : else if (SUBREG_BYTE (op0) == 8)
576 : : {
577 : 134130 : wide_int mask = wi::mask (64, false, 128);
578 : 134130 : tmp = immed_wide_int_const (mask, TImode);
579 : 134130 : op0 = SUBREG_REG (op0);
580 : 134130 : tmp = gen_rtx_AND (TImode, copy_rtx (op0), tmp);
581 : 134130 : if (mode == DFmode)
582 : 196 : op1 = gen_lowpart (DImode, op1);
583 : 134130 : op1 = gen_rtx_ZERO_EXTEND (TImode, op1);
584 : 134130 : op1 = gen_rtx_ASHIFT (TImode, op1, GEN_INT (64));
585 : 134130 : op1 = gen_rtx_IOR (TImode, tmp, op1);
586 : 134130 : }
587 : : }
588 : :
589 : 72991624 : 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 : 2350805 : ix86_broadcast_from_constant (machine_mode mode, rtx op)
596 : : {
597 : 2350805 : int nunits = GET_MODE_NUNITS (mode);
598 : 2350805 : 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 : 2191036 : 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 : 2185435 : if (standard_sse_constant_p (op, mode))
610 : : return nullptr;
611 : :
612 : 4370864 : if (GET_MODE_INNER (mode) == TImode)
613 : : return nullptr;
614 : :
615 : 2185322 : rtx constant = get_pool_constant (XEXP (op, 0));
616 : 2185322 : 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 : 2185322 : if (GET_MODE (constant) != mode)
623 : : {
624 : 565 : constant = simplify_subreg (mode, constant, GET_MODE (constant),
625 : : 0);
626 : 565 : if (constant == nullptr || !CONST_VECTOR_P (constant))
627 : : return nullptr;
628 : : }
629 : :
630 : 2185322 : rtx first = XVECEXP (constant, 0, 0);
631 : :
632 : 5538063 : for (int i = 1; i < nunits; ++i)
633 : : {
634 : 5070590 : rtx tmp = XVECEXP (constant, 0, i);
635 : : /* Vector duplicate value. */
636 : 5070590 : if (!rtx_equal_p (tmp, first))
637 : : return nullptr;
638 : : }
639 : :
640 : : return first;
641 : : }
642 : :
643 : : void
644 : 4304988 : ix86_expand_vector_move (machine_mode mode, rtx operands[])
645 : : {
646 : 4304988 : 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 : 4304988 : unsigned int align = (TARGET_IAMCU
650 : 4304988 : ? GET_MODE_BITSIZE (mode)
651 : 4304988 : : GET_MODE_ALIGNMENT (mode));
652 : :
653 : 4304988 : 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 : 4304988 : if (can_create_pseudo_p ()
661 : 4111031 : && (CONSTANT_P (op1)
662 : 3823573 : || (SUBREG_P (op1)
663 : 287337 : && CONSTANT_P (SUBREG_REG (op1))))
664 : 4592460 : && ((register_operand (op0, mode)
665 : 232455 : && !standard_sse_constant_p (op1, mode))
666 : : /* ix86_expand_vector_move_misalign() does not like constants. */
667 : : || (SSE_REG_MODE_P (mode)
668 : 233993 : && MEM_P (op0)
669 : 40734 : && 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 : 4304988 : if (can_create_pseudo_p ()
694 : 4111031 : && GET_MODE_SIZE (mode) >= 16
695 : 3426533 : && VECTOR_MODE_P (mode)
696 : 7497041 : && (MEM_P (op1)
697 : 675285 : && SYMBOL_REF_P (XEXP (op1, 0))
698 : 487232 : && CONSTANT_POOL_ADDRESS_P (XEXP (op1, 0))))
699 : : {
700 : 471456 : rtx first = ix86_broadcast_from_constant (mode, op1);
701 : 471456 : if (first != nullptr)
702 : : {
703 : : /* Broadcast to XMM/YMM/ZMM register from an integer
704 : : constant or scalar mem. */
705 : 116145 : rtx tmp = gen_reg_rtx (mode);
706 : 116145 : if (FLOAT_MODE_P (mode))
707 : 27836 : first = force_const_mem (GET_MODE_INNER (mode), first);
708 : 116145 : bool ok = ix86_expand_vector_init_duplicate (false, mode,
709 : : tmp, first);
710 : 116145 : 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 : 116145 : if (ok)
717 : : {
718 : 116145 : emit_move_insn (op0, tmp);
719 : 116145 : return;
720 : : }
721 : : }
722 : : }
723 : :
724 : : /* We need to check memory alignment for SSE mode since attribute
725 : : can make operands unaligned. */
726 : 4188843 : if (can_create_pseudo_p ()
727 : : && SSE_REG_MODE_P (mode)
728 : 8355942 : && ((MEM_P (op0) && (MEM_ALIGN (op0) < align))
729 : 3784175 : || (MEM_P (op1) && (MEM_ALIGN (op1) < align))))
730 : : {
731 : 267961 : rtx tmp[2];
732 : :
733 : : /* ix86_expand_vector_move_misalign() does not like both
734 : : arguments in memory. */
735 : 267961 : if (!register_operand (op0, mode)
736 : 267961 : && !register_operand (op1, mode))
737 : : {
738 : 97072 : rtx scratch = gen_reg_rtx (mode);
739 : 97072 : emit_move_insn (scratch, op1);
740 : 97072 : op1 = scratch;
741 : : }
742 : :
743 : 267961 : tmp[0] = op0; tmp[1] = op1;
744 : 267961 : ix86_expand_vector_move_misalign (mode, tmp);
745 : 267961 : return;
746 : : }
747 : :
748 : : /* Special case TImode to 128-bit vector conversions via V2DI. */
749 : 1104782 : if (VECTOR_MODE_P (mode)
750 : 3872568 : && GET_MODE_SIZE (mode) == 16
751 : 2714062 : && SUBREG_P (op1)
752 : 224262 : && GET_MODE (SUBREG_REG (op1)) == TImode
753 : 2755 : && TARGET_64BIT && TARGET_SSE
754 : 3923046 : && ix86_pre_reload_split ())
755 : : {
756 : 2092 : rtx tmp = gen_reg_rtx (V2DImode);
757 : 2092 : rtx lo = gen_reg_rtx (DImode);
758 : 2092 : rtx hi = gen_reg_rtx (DImode);
759 : 2092 : emit_move_insn (lo, gen_lowpart (DImode, SUBREG_REG (op1)));
760 : 2092 : emit_move_insn (hi, gen_highpart (DImode, SUBREG_REG (op1)));
761 : 2092 : emit_insn (gen_vec_concatv2di (tmp, lo, hi));
762 : 2092 : emit_move_insn (op0, gen_lowpart (mode, tmp));
763 : 2092 : return;
764 : : }
765 : :
766 : : /* If operand0 is a hard register, make operand1 a pseudo. */
767 : 3918790 : if (can_create_pseudo_p ()
768 : 7643623 : && !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 : 3918745 : if (can_create_pseudo_p ()
778 : 3724788 : && !register_operand (op0, mode)
779 : 4964643 : && !register_operand (op1, mode))
780 : : {
781 : 216250 : rtx tmp = gen_reg_rtx (GET_MODE (op0));
782 : 216250 : emit_move_insn (tmp, op1);
783 : 216250 : emit_move_insn (op0, tmp);
784 : 216250 : return;
785 : : }
786 : :
787 : 3702495 : 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 : 10076 : ix86_avx256_split_vector_move_misalign (rtx op0, rtx op1)
794 : : {
795 : 10076 : rtx m;
796 : 10076 : rtx (*extract) (rtx, rtx, rtx);
797 : 10076 : machine_mode mode;
798 : :
799 : 10076 : if ((MEM_P (op1) && !TARGET_AVX256_SPLIT_UNALIGNED_LOAD)
800 : 3484 : || (MEM_P (op0) && !TARGET_AVX256_SPLIT_UNALIGNED_STORE))
801 : : {
802 : 10024 : emit_insn (gen_rtx_SET (op0, op1));
803 : 10024 : 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 : 582561 : ix86_expand_vector_move_misalign (machine_mode mode, rtx operands[])
934 : : {
935 : 582561 : rtx op0, op1, m;
936 : :
937 : 582561 : op0 = operands[0];
938 : 582561 : op1 = operands[1];
939 : :
940 : : /* Use unaligned load/store for AVX512 or when optimizing for size. */
941 : 1165122 : if (GET_MODE_SIZE (mode) == 64 || optimize_insn_for_size_p ())
942 : : {
943 : 16650 : emit_insn (gen_rtx_SET (op0, op1));
944 : 16650 : return;
945 : : }
946 : :
947 : 565911 : if (TARGET_AVX)
948 : : {
949 : 49686 : if (GET_MODE_SIZE (mode) == 32)
950 : 10076 : ix86_avx256_split_vector_move_misalign (op0, op1);
951 : : else
952 : : /* Always use 128-bit mov<mode>_internal pattern for AVX. */
953 : 14767 : emit_insn (gen_rtx_SET (op0, op1));
954 : 24843 : return;
955 : : }
956 : :
957 : 541068 : if (TARGET_SSE_UNALIGNED_LOAD_OPTIMAL
958 : 95 : || TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL)
959 : : {
960 : 540973 : emit_insn (gen_rtx_SET (op0, op1));
961 : 540973 : 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 : 818 : ix86_move_vector_high_sse_to_mmx (rtx op)
1054 : : {
1055 : 818 : rtx mask = gen_rtx_PARALLEL (VOIDmode,
1056 : : gen_rtvec (4, GEN_INT (0), GEN_INT (2),
1057 : : GEN_INT (0), GEN_INT (0)));
1058 : 818 : rtx dest = lowpart_subreg (V4SImode, op, GET_MODE (op));
1059 : 818 : op = gen_rtx_VEC_SELECT (V4SImode, dest, mask);
1060 : 818 : rtx insn = gen_rtx_SET (dest, op);
1061 : 818 : emit_insn (insn);
1062 : 818 : }
1063 : :
1064 : : /* Split MMX pack with signed/unsigned saturation with SSE/SSE2. */
1065 : :
1066 : : void
1067 : 728 : ix86_split_mmx_pack (rtx operands[], enum rtx_code code)
1068 : : {
1069 : 728 : rtx op0 = operands[0];
1070 : 728 : rtx op1 = operands[1];
1071 : 728 : rtx op2 = operands[2];
1072 : 728 : rtx src;
1073 : :
1074 : 728 : machine_mode dmode = GET_MODE (op0);
1075 : 728 : machine_mode smode = GET_MODE (op1);
1076 : 728 : machine_mode inner_dmode = GET_MODE_INNER (dmode);
1077 : 728 : machine_mode inner_smode = GET_MODE_INNER (smode);
1078 : :
1079 : : /* Get the corresponding SSE mode for destination. */
1080 : 728 : int nunits = 16 / GET_MODE_SIZE (inner_dmode);
1081 : 1456 : machine_mode sse_dmode = mode_for_vector (GET_MODE_INNER (dmode),
1082 : 1456 : nunits).require ();
1083 : 728 : machine_mode sse_half_dmode = mode_for_vector (GET_MODE_INNER (dmode),
1084 : 1456 : nunits / 2).require ();
1085 : :
1086 : : /* Get the corresponding SSE mode for source. */
1087 : 728 : nunits = 16 / GET_MODE_SIZE (inner_smode);
1088 : 1456 : machine_mode sse_smode = mode_for_vector (GET_MODE_INNER (smode),
1089 : 1456 : nunits).require ();
1090 : :
1091 : : /* Generate SSE pack with signed/unsigned saturation. */
1092 : 728 : rtx dest = lowpart_subreg (sse_dmode, op0, GET_MODE (op0));
1093 : 728 : op1 = lowpart_subreg (sse_smode, op1, GET_MODE (op1));
1094 : 728 : 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 : 728 : if (code == US_TRUNCATE)
1099 : 626 : 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 : 728 : emit_move_insn (dest, src);
1110 : :
1111 : 728 : ix86_move_vector_high_sse_to_mmx (op0);
1112 : 728 : }
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 : 4764 : ix86_split_mmx_punpck (rtx operands[], bool high_p)
1120 : : {
1121 : 4764 : rtx op0 = operands[0];
1122 : 4764 : rtx op1 = operands[1];
1123 : 4764 : rtx op2 = operands[2];
1124 : 4764 : machine_mode mode = GET_MODE (op1);
1125 : 4764 : rtx mask;
1126 : : /* The corresponding SSE mode. */
1127 : 4764 : machine_mode sse_mode, double_sse_mode;
1128 : :
1129 : 4764 : switch (mode)
1130 : : {
1131 : 1318 : case E_V8QImode:
1132 : 1318 : case E_V4QImode:
1133 : 1318 : case E_V2QImode:
1134 : 1318 : sse_mode = V16QImode;
1135 : 1318 : double_sse_mode = V32QImode;
1136 : 1318 : 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 : 1318 : 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 : 604 : case E_V2SImode:
1161 : 604 : sse_mode = V4SImode;
1162 : 604 : double_sse_mode = V8SImode;
1163 : 604 : mask = gen_rtx_PARALLEL (VOIDmode,
1164 : : gen_rtvec (4,
1165 : : GEN_INT (0), GEN_INT (4),
1166 : : GEN_INT (1), GEN_INT (5)));
1167 : 604 : 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 : 4764 : rtx dest = lowpart_subreg (sse_mode, op0, GET_MODE (op0));
1184 : 4764 : op1 = lowpart_subreg (sse_mode, op1, GET_MODE (op1));
1185 : 4764 : op2 = lowpart_subreg (sse_mode, op2, GET_MODE (op2));
1186 : :
1187 : 4764 : op1 = gen_rtx_VEC_CONCAT (double_sse_mode, op1, op2);
1188 : 4764 : op2 = gen_rtx_VEC_SELECT (sse_mode, op1, mask);
1189 : 4764 : rtx insn = gen_rtx_SET (dest, op2);
1190 : 4764 : emit_insn (insn);
1191 : :
1192 : : /* Move high bits to low bits. */
1193 : 4764 : if (high_p)
1194 : : {
1195 : 1974 : 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 : 1862 : int sz = GET_MODE_SIZE (mode);
1206 : :
1207 : 1862 : if (sz == 4)
1208 : 222 : 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 : 1862 : dest = lowpart_subreg (V4SImode, dest, GET_MODE (dest));
1219 : 1862 : op1 = gen_rtx_VEC_SELECT (V4SImode, dest, mask);
1220 : : }
1221 : :
1222 : 1974 : insn = gen_rtx_SET (dest, op1);
1223 : 1974 : emit_insn (insn);
1224 : : }
1225 : 4764 : }
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 : 174665075 : ix86_swap_binary_operands_p (enum rtx_code code, machine_mode mode,
1232 : : rtx operands[])
1233 : : {
1234 : 174665075 : rtx dst = operands[0];
1235 : 174665075 : rtx src1 = operands[1];
1236 : 174665075 : rtx src2 = operands[2];
1237 : :
1238 : : /* If the operation is not commutative, we can't do anything. */
1239 : 174665075 : if (GET_RTX_CLASS (code) != RTX_COMM_ARITH
1240 : 27906729 : && GET_RTX_CLASS (code) != RTX_COMM_COMPARE)
1241 : : return false;
1242 : :
1243 : : /* Highest priority is that src1 should match dst. */
1244 : 146768328 : if (rtx_equal_p (dst, src1))
1245 : : return false;
1246 : 106815820 : if (rtx_equal_p (dst, src2))
1247 : : return true;
1248 : :
1249 : : /* Next highest priority is that immediate constants come second. */
1250 : 106736528 : if (immediate_operand (src2, mode))
1251 : : return false;
1252 : 24352123 : if (immediate_operand (src1, mode))
1253 : : return true;
1254 : :
1255 : : /* Lowest priority is that memory references should come second. */
1256 : 24352123 : if (MEM_P (src2))
1257 : : return false;
1258 : 23023029 : 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 : 13441621 : ix86_fixup_binary_operands (enum rtx_code code, machine_mode mode,
1271 : : rtx operands[], bool use_ndd)
1272 : : {
1273 : 13441621 : rtx dst = operands[0];
1274 : 13441621 : rtx src1 = operands[1];
1275 : 13441621 : rtx src2 = operands[2];
1276 : :
1277 : : /* Canonicalize operand order. */
1278 : 13441621 : if (ix86_swap_binary_operands_p (code, mode, operands))
1279 : : {
1280 : : /* It is invalid to swap operands of different modes. */
1281 : 85250 : 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 : 13441621 : if (MEM_P (src1) && MEM_P (src2))
1288 : : {
1289 : : /* Optimization: Only read from memory once. */
1290 : 87146 : if (rtx_equal_p (src1, src2))
1291 : : {
1292 : 9 : src2 = force_reg (mode, src2);
1293 : 9 : src1 = src2;
1294 : : }
1295 : 87137 : else if (rtx_equal_p (dst, src1))
1296 : 3084 : src2 = force_reg (mode, src2);
1297 : : else
1298 : 84053 : 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 : 13441621 : if (MEM_P (dst) && !rtx_equal_p (dst, src1))
1304 : 496518 : dst = gen_reg_rtx (mode);
1305 : :
1306 : : /* Source 1 cannot be a constant. */
1307 : 13441621 : if (CONSTANT_P (src1))
1308 : 716 : src1 = force_reg (mode, src1);
1309 : :
1310 : : /* Source 1 cannot be a non-matching memory. */
1311 : 13441621 : if (!use_ndd && MEM_P (src1) && !rtx_equal_p (dst, src1))
1312 : 465556 : src1 = force_reg (mode, src1);
1313 : :
1314 : : /* Improve address combine. */
1315 : 13441621 : if (code == PLUS
1316 : 9772428 : && GET_MODE_CLASS (mode) == MODE_INT
1317 : 9667740 : && MEM_P (src2))
1318 : 179155 : src2 = force_reg (mode, src2);
1319 : :
1320 : 13441621 : operands[1] = src1;
1321 : 13441621 : operands[2] = src2;
1322 : 13441621 : return dst;
1323 : : }
1324 : :
1325 : : /* Similarly, but assume that the destination has already been
1326 : : set up properly. */
1327 : :
1328 : : void
1329 : 260700 : ix86_fixup_binary_operands_no_copy (enum rtx_code code,
1330 : : machine_mode mode, rtx operands[],
1331 : : bool use_ndd)
1332 : : {
1333 : 260700 : rtx dst = ix86_fixup_binary_operands (code, mode, operands, use_ndd);
1334 : 260700 : gcc_assert (dst == operands[0]);
1335 : 260700 : }
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 : 13180792 : ix86_expand_binary_operator (enum rtx_code code, machine_mode mode,
1343 : : rtx operands[], bool use_ndd)
1344 : : {
1345 : 13180792 : rtx src1, src2, dst, op, clob;
1346 : :
1347 : 13180792 : dst = ix86_fixup_binary_operands (code, mode, operands, use_ndd);
1348 : 13180792 : src1 = operands[1];
1349 : 13180792 : src2 = operands[2];
1350 : :
1351 : : /* Emit the instruction. */
1352 : :
1353 : 13180792 : op = gen_rtx_SET (dst, gen_rtx_fmt_ee (code, mode, src1, src2));
1354 : :
1355 : 13180792 : if (reload_completed
1356 : 84056 : && code == PLUS
1357 : 894 : && !rtx_equal_p (dst, src1)
1358 : 13180792 : && !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 : 13180792 : clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
1366 : 13180792 : emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, op, clob)));
1367 : : }
1368 : :
1369 : : /* Fix up the destination if needed. */
1370 : 13180792 : if (dst != operands[0])
1371 : 496509 : emit_move_insn (operands[0], dst);
1372 : 13180792 : }
1373 : :
1374 : : /* Expand vector logical operation CODE (AND, IOR, XOR) in MODE with
1375 : : the given OPERANDS. */
1376 : :
1377 : : void
1378 : 65194 : ix86_expand_vector_logical_operator (enum rtx_code code, machine_mode mode,
1379 : : rtx operands[])
1380 : : {
1381 : 65194 : rtx op1 = NULL_RTX, op2 = NULL_RTX;
1382 : 65194 : if (SUBREG_P (operands[1]))
1383 : : {
1384 : 312 : op1 = operands[1];
1385 : 312 : op2 = operands[2];
1386 : : }
1387 : 64882 : 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 : 3029 : if (op1
1398 : 3029 : && !TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL
1399 : 3029 : && (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 : 65177 : if (!vector_operand (operands[1], mode))
1443 : 0 : operands[1] = force_reg (mode, operands[1]);
1444 : 65177 : if (!vector_operand (operands[2], mode))
1445 : 9416 : operands[2] = force_reg (mode, operands[2]);
1446 : 65177 : ix86_fixup_binary_operands_no_copy (code, mode, operands);
1447 : 65177 : 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 : 162119335 : ix86_binary_operator_ok (enum rtx_code code, machine_mode mode,
1457 : : rtx operands[3], bool use_ndd)
1458 : : {
1459 : 162119335 : rtx dst = operands[0];
1460 : 162119335 : rtx src1 = operands[1];
1461 : 162119335 : rtx src2 = operands[2];
1462 : :
1463 : : /* Both source operands cannot be in memory. */
1464 : 154703464 : if ((MEM_P (src1) || bcst_mem_operand (src1, mode))
1465 : 162119734 : && (MEM_P (src2) || bcst_mem_operand (src2, mode)))
1466 : 895881 : return false;
1467 : :
1468 : : /* Canonicalize operand order for commutative operators. */
1469 : 161223454 : if (ix86_swap_binary_operands_p (code, mode, operands))
1470 : 547819 : std::swap (src1, src2);
1471 : :
1472 : : /* If the destination is memory, we must have a matching source operand. */
1473 : 161223454 : if (MEM_P (dst) && !rtx_equal_p (dst, src1))
1474 : : return false;
1475 : :
1476 : : /* Source 1 cannot be a constant. */
1477 : 155959980 : if (CONSTANT_P (src1))
1478 : : return false;
1479 : :
1480 : : /* Source 1 cannot be a non-matching memory. */
1481 : 155957183 : if (!use_ndd && MEM_P (src1) && !rtx_equal_p (dst, src1))
1482 : : /* Support "andhi/andsi/anddi" as a zero-extending move. */
1483 : 4551389 : return (code == AND
1484 : 674522 : && (mode == HImode
1485 : 674522 : || mode == SImode
1486 : 410300 : || (TARGET_64BIT && mode == DImode))
1487 : 4906653 : && 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 : 118087 : ix86_expand_unary_operator (enum rtx_code code, machine_mode mode,
1498 : : rtx operands[], bool use_ndd)
1499 : : {
1500 : 118087 : bool matching_memory = false;
1501 : 118087 : rtx src, dst, op, clob;
1502 : :
1503 : 118087 : dst = operands[0];
1504 : 118087 : src = operands[1];
1505 : :
1506 : : /* If the destination is memory, and we do not have matching source
1507 : : operands, do things in registers. */
1508 : 118087 : if (MEM_P (dst))
1509 : : {
1510 : 2999 : if (rtx_equal_p (dst, src))
1511 : : matching_memory = true;
1512 : : else
1513 : 2682 : dst = gen_reg_rtx (mode);
1514 : : }
1515 : :
1516 : : /* When source operand is memory, destination must match. */
1517 : 118087 : if (!use_ndd && MEM_P (src) && !matching_memory)
1518 : 4114 : src = force_reg (mode, src);
1519 : :
1520 : : /* Emit the instruction. */
1521 : :
1522 : 118087 : op = gen_rtx_SET (dst, gen_rtx_fmt_e (code, mode, src));
1523 : :
1524 : 118087 : if (code == NOT)
1525 : 67712 : emit_insn (op);
1526 : : else
1527 : : {
1528 : 50375 : clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
1529 : 50375 : emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, op, clob)));
1530 : : }
1531 : :
1532 : : /* Fix up the destination if needed. */
1533 : 118087 : if (dst != operands[0])
1534 : 2682 : emit_move_insn (operands[0], dst);
1535 : 118087 : }
1536 : :
1537 : : /* Return TRUE or FALSE depending on whether the unary operator meets the
1538 : : appropriate constraints. */
1539 : :
1540 : : bool
1541 : 1712028 : 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 : 1712028 : if ((MEM_P (operands[0])
1548 : 1669310 : || (!use_ndd && MEM_P (operands[1])))
1549 : 1740476 : && ! 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 : 41118 : predict_jump (int prob)
1558 : : {
1559 : 41118 : rtx_insn *insn = get_last_insn ();
1560 : 41118 : gcc_assert (JUMP_P (insn));
1561 : 41118 : add_reg_br_prob_note (insn, profile_probability::from_reg_br_prob_base (prob));
1562 : 41118 : }
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 : 7986 : ix86_emit_binop (enum rtx_code code, machine_mode mode,
1681 : : rtx dst, rtx src)
1682 : : {
1683 : 7986 : rtx op, clob;
1684 : :
1685 : 7986 : op = gen_rtx_SET (dst, gen_rtx_fmt_ee (code, mode, dst, src));
1686 : 7986 : clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
1687 : :
1688 : 7986 : emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, op, clob)));
1689 : 7986 : }
1690 : :
1691 : : /* Return true if regno1 def is nearest to the insn. */
1692 : :
1693 : : static bool
1694 : 16 : find_nearest_reg_def (rtx_insn *insn, int regno1, int regno2)
1695 : : {
1696 : 16 : rtx_insn *prev = insn;
1697 : 16 : rtx_insn *start = BB_HEAD (BLOCK_FOR_INSN (insn));
1698 : :
1699 : 16 : if (insn == start)
1700 : : return false;
1701 : 44 : while (prev && prev != start)
1702 : : {
1703 : 34 : if (!INSN_P (prev) || !NONDEBUG_INSN_P (prev))
1704 : : {
1705 : 10 : prev = PREV_INSN (prev);
1706 : 10 : continue;
1707 : : }
1708 : 24 : if (insn_defines_reg (regno1, INVALID_REGNUM, prev))
1709 : : return true;
1710 : 18 : else if (insn_defines_reg (regno2, INVALID_REGNUM, prev))
1711 : : return false;
1712 : 18 : 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 : 6173 : ix86_split_lea_for_addr (rtx_insn *insn, rtx operands[], machine_mode mode)
1729 : : {
1730 : 6173 : unsigned int regno0, regno1, regno2;
1731 : 6173 : struct ix86_address parts;
1732 : 6173 : rtx target, tmp;
1733 : 6173 : int ok, adds;
1734 : :
1735 : 6173 : ok = ix86_decompose_address (operands[1], &parts);
1736 : 6173 : gcc_assert (ok);
1737 : :
1738 : 6173 : target = gen_lowpart (mode, operands[0]);
1739 : :
1740 : 6173 : regno0 = true_regnum (target);
1741 : 6173 : regno1 = INVALID_REGNUM;
1742 : 6173 : regno2 = INVALID_REGNUM;
1743 : :
1744 : 6173 : if (parts.base)
1745 : : {
1746 : 6165 : parts.base = gen_lowpart (mode, parts.base);
1747 : 6165 : regno1 = true_regnum (parts.base);
1748 : : }
1749 : :
1750 : 6173 : if (parts.index)
1751 : : {
1752 : 6172 : parts.index = gen_lowpart (mode, parts.index);
1753 : 6172 : regno2 = true_regnum (parts.index);
1754 : : }
1755 : :
1756 : 6173 : if (parts.disp)
1757 : 184 : parts.disp = gen_lowpart (mode, parts.disp);
1758 : :
1759 : 6173 : 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 : 6162 : 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 : 6162 : if (!parts.base)
1799 : : {
1800 : 0 : if (regno0 != regno2)
1801 : 0 : emit_insn (gen_rtx_SET (target, parts.index));
1802 : : }
1803 : 6162 : else if (!parts.index)
1804 : : {
1805 : 1 : if (regno0 != regno1)
1806 : 1 : emit_insn (gen_rtx_SET (target, parts.base));
1807 : : }
1808 : : else
1809 : : {
1810 : 6161 : if (regno0 == regno1)
1811 : : tmp = parts.index;
1812 : 2444 : else if (regno0 == regno2)
1813 : : tmp = parts.base;
1814 : : else
1815 : : {
1816 : 16 : rtx tmp1;
1817 : :
1818 : : /* Find better operand for SET instruction, depending
1819 : : on which definition is farther from the insn. */
1820 : 16 : if (find_nearest_reg_def (insn, regno1, regno2))
1821 : 6 : tmp = parts.index, tmp1 = parts.base;
1822 : : else
1823 : 10 : tmp = parts.base, tmp1 = parts.index;
1824 : :
1825 : 16 : emit_insn (gen_rtx_SET (target, tmp));
1826 : :
1827 : 16 : if (parts.disp && parts.disp != const0_rtx)
1828 : 0 : ix86_emit_binop (PLUS, mode, target, parts.disp);
1829 : :
1830 : 16 : ix86_emit_binop (PLUS, mode, target, tmp1);
1831 : 16 : return;
1832 : : }
1833 : :
1834 : 6145 : ix86_emit_binop (PLUS, mode, target, tmp);
1835 : : }
1836 : :
1837 : 6146 : if (parts.disp && parts.disp != const0_rtx)
1838 : 2 : 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 : 34383 : ix86_expand_fp_absneg_operator (enum rtx_code code, machine_mode mode,
2169 : : rtx operands[])
2170 : : {
2171 : 34383 : rtx set, dst, src;
2172 : 34383 : bool use_sse = false;
2173 : 34383 : bool vector_mode = VECTOR_MODE_P (mode);
2174 : 34383 : machine_mode vmode = mode;
2175 : 34383 : rtvec par;
2176 : :
2177 : 34383 : 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 : 9818 : case E_SFmode:
2188 : 9818 : use_sse = TARGET_SSE_MATH && TARGET_SSE;
2189 : : vmode = V4SFmode;
2190 : : break;
2191 : 15469 : case E_DFmode:
2192 : 15469 : use_sse = TARGET_SSE_MATH && TARGET_SSE2;
2193 : : vmode = V2DFmode;
2194 : : break;
2195 : 8997 : default:
2196 : 8997 : use_sse = vector_mode || mode == TFmode;
2197 : 8997 : break;
2198 : : }
2199 : :
2200 : 34383 : dst = operands[0];
2201 : 34383 : src = operands[1];
2202 : :
2203 : 34383 : set = gen_rtx_fmt_e (code, mode, src);
2204 : 34383 : set = gen_rtx_SET (dst, set);
2205 : :
2206 : 34383 : if (use_sse)
2207 : : {
2208 : 28806 : rtx mask, use, clob;
2209 : :
2210 : : /* NEG and ABS performed with SSE use bitwise mask operations.
2211 : : Create the appropriate mask now. */
2212 : 28806 : mask = ix86_build_signbit_mask (vmode, vector_mode, code == ABS);
2213 : 28806 : use = gen_rtx_USE (VOIDmode, mask);
2214 : 28806 : if (vector_mode || mode == TFmode)
2215 : 4769 : par = gen_rtvec (2, set, use);
2216 : : else
2217 : : {
2218 : 24037 : clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
2219 : 24037 : par = gen_rtvec (3, set, use, clob);
2220 : : }
2221 : : }
2222 : : else
2223 : : {
2224 : 5577 : rtx clob;
2225 : :
2226 : : /* Changing of sign for FP values is doable using integer unit too. */
2227 : 5577 : clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
2228 : 5577 : par = gen_rtvec (2, set, clob);
2229 : : }
2230 : :
2231 : 34383 : emit_insn (gen_rtx_PARALLEL (VOIDmode, par));
2232 : 34383 : }
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 : 6522031 : ix86_expand_branch (enum rtx_code code, rtx op0, rtx op1, rtx label)
2455 : : {
2456 : 6522031 : machine_mode mode = GET_MODE (op0);
2457 : 6522031 : rtx tmp;
2458 : :
2459 : : /* Handle special case - vector comparsion with boolean result, transform
2460 : : it using ptest instruction or vpcmpeq + kortest. */
2461 : 6522031 : if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT
2462 : 6517183 : || (mode == TImode && !TARGET_64BIT)
2463 : 6517183 : || mode == OImode
2464 : 13039214 : || GET_MODE_SIZE (mode) == 64)
2465 : : {
2466 : 4848 : unsigned msize = GET_MODE_SIZE (mode);
2467 : 4848 : machine_mode p_mode
2468 : 4848 : = msize == 64 ? V16SImode : msize == 32 ? V4DImode : V2DImode;
2469 : : /* kortest set CF when result is 0xFFFF (op0 == op1). */
2470 : 4848 : rtx flag = gen_rtx_REG (msize == 64 ? CCCmode : CCZmode, FLAGS_REG);
2471 : :
2472 : 4848 : gcc_assert (code == EQ || code == NE);
2473 : :
2474 : : /* Using vpcmpeq zmm zmm k + kortest for 512-bit vectors. */
2475 : 4848 : 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 : 3492 : 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 : 3492 : tmp = gen_reg_rtx (mode);
2500 : 3492 : rtx ops[3] = { tmp, op0, op1 };
2501 : 3492 : ix86_expand_vector_logical_operator (XOR, mode, ops);
2502 : 3492 : tmp = gen_lowpart (p_mode, tmp);
2503 : 3492 : 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 : 4848 : tmp = gen_rtx_fmt_ee (code, VOIDmode, flag, const0_rtx);
2509 : 4848 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
2510 : : gen_rtx_LABEL_REF (VOIDmode, label),
2511 : : pc_rtx);
2512 : 4848 : emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
2513 : 4848 : return;
2514 : : }
2515 : :
2516 : 6517183 : switch (mode)
2517 : : {
2518 : 6482482 : case E_HFmode:
2519 : 6482482 : case E_SFmode:
2520 : 6482482 : case E_DFmode:
2521 : 6482482 : case E_XFmode:
2522 : 6482482 : case E_QImode:
2523 : 6482482 : case E_HImode:
2524 : 6482482 : case E_SImode:
2525 : 6482482 : simple:
2526 : 6482482 : tmp = ix86_expand_compare (code, op0, op1);
2527 : 6482482 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
2528 : : gen_rtx_LABEL_REF (VOIDmode, label),
2529 : : pc_rtx);
2530 : 6482482 : emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
2531 : 6482482 : return;
2532 : :
2533 : 7 : case E_BFmode:
2534 : 7 : gcc_assert (TARGET_AVX10_2 && !flag_trapping_math);
2535 : 7 : goto simple;
2536 : :
2537 : 2559687 : case E_DImode:
2538 : 2559687 : if (TARGET_64BIT)
2539 : 2532085 : goto simple;
2540 : : /* FALLTHRU */
2541 : 82261 : 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 : 82261 : if ((code == EQ || code == NE)
2546 : 82261 : && !optimize_insn_for_size_p ())
2547 : 47560 : goto simple;
2548 : :
2549 : : /* Expand DImode branch into multiple compare+branch. */
2550 : 34701 : {
2551 : 34701 : rtx lo[2], hi[2];
2552 : 34701 : rtx_code_label *label2;
2553 : 34701 : enum rtx_code code1, code2, code3;
2554 : 34701 : machine_mode submode;
2555 : :
2556 : 34701 : if (CONSTANT_P (op0) && !CONSTANT_P (op1))
2557 : : {
2558 : 0 : std::swap (op0, op1);
2559 : 0 : code = swap_condition (code);
2560 : : }
2561 : :
2562 : 34701 : split_double_mode (mode, &op0, 1, lo+0, hi+0);
2563 : 34701 : split_double_mode (mode, &op1, 1, lo+1, hi+1);
2564 : :
2565 : 34701 : 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 : 34701 : if (CONST_INT_P (hi[1]))
2573 : 24024 : switch (code)
2574 : : {
2575 : 10768 : case LT: case LTU: case GE: case GEU:
2576 : 10768 : if (lo[1] == const0_rtx)
2577 : : {
2578 : 10361 : ix86_expand_branch (code, hi[0], hi[1], label);
2579 : 10361 : return;
2580 : : }
2581 : : break;
2582 : 11689 : case LE: case LEU: case GT: case GTU:
2583 : 11689 : 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 : 23810 : switch (code)
2599 : : {
2600 : 16432 : case LE: case LEU: case GT: case GTU:
2601 : 16432 : std::swap (lo[0], lo[1]);
2602 : 16432 : std::swap (hi[0], hi[1]);
2603 : 16432 : code = swap_condition (code);
2604 : : /* FALLTHRU */
2605 : :
2606 : 20771 : case LT: case LTU: case GE: case GEU:
2607 : 20771 : {
2608 : 20771 : bool uns = (code == LTU || code == GEU);
2609 : 3960 : rtx (*sbb_insn) (machine_mode, rtx, rtx, rtx)
2610 : 20771 : = uns ? gen_sub3_carry_ccc : gen_sub3_carry_ccgz;
2611 : :
2612 : 20771 : if (!nonimmediate_operand (lo[0], submode))
2613 : 11159 : lo[0] = force_reg (submode, lo[0]);
2614 : 20771 : if (!x86_64_general_operand (lo[1], submode))
2615 : 0 : lo[1] = force_reg (submode, lo[1]);
2616 : :
2617 : 20771 : if (!register_operand (hi[0], submode))
2618 : 11982 : hi[0] = force_reg (submode, hi[0]);
2619 : 16811 : if ((uns && !nonimmediate_operand (hi[1], submode))
2620 : 20771 : || (!uns && !x86_64_general_operand (hi[1], submode)))
2621 : 315 : hi[1] = force_reg (submode, hi[1]);
2622 : :
2623 : 20771 : emit_insn (gen_cmp_1 (submode, lo[0], lo[1]));
2624 : :
2625 : 20771 : tmp = gen_rtx_SCRATCH (submode);
2626 : 20771 : emit_insn (sbb_insn (submode, tmp, hi[0], hi[1]));
2627 : :
2628 : 24731 : tmp = gen_rtx_REG (uns ? CCCmode : CCGZmode, FLAGS_REG);
2629 : 20771 : ix86_expand_branch (code, tmp, const0_rtx, label);
2630 : 20771 : return;
2631 : : }
2632 : :
2633 : 3039 : default:
2634 : 3039 : break;
2635 : : }
2636 : :
2637 : : /* Otherwise, we need two or three jumps. */
2638 : :
2639 : 3039 : label2 = gen_label_rtx ();
2640 : :
2641 : 3039 : code1 = code;
2642 : 3039 : code2 = swap_condition (code);
2643 : 3039 : code3 = unsigned_condition (code);
2644 : :
2645 : 3039 : 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 : 3039 : if (code2 != UNKNOWN)
2673 : 722 : ix86_expand_branch (code2, hi[0], hi[1], label2);
2674 : :
2675 : 3039 : ix86_expand_branch (code3, lo[0], lo[1], label);
2676 : :
2677 : 3039 : if (code2 != UNKNOWN)
2678 : 722 : emit_label (label2);
2679 : : return;
2680 : : }
2681 : :
2682 : 21210 : default:
2683 : 21210 : gcc_assert (GET_MODE_CLASS (GET_MODE (op0)) == MODE_CC);
2684 : 21210 : goto simple;
2685 : : }
2686 : : }
2687 : :
2688 : : /* Figure out whether to use unordered fp comparisons. */
2689 : :
2690 : : static bool
2691 : 1165837 : ix86_unordered_fp_compare (enum rtx_code code)
2692 : : {
2693 : 1165837 : if (!TARGET_IEEE_FP)
2694 : : return false;
2695 : :
2696 : 1161625 : 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 : 36709 : ix86_fp_swap_condition (enum rtx_code code)
2729 : : {
2730 : 36709 : 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 : 27577 : default:
2741 : 27577 : 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 : 1164688 : ix86_fp_comparison_cost (enum rtx_code code)
2752 : : {
2753 : 1164688 : int arith_cost;
2754 : :
2755 : : /* The cost of code using bit-twiddling on %ah. */
2756 : 1164688 : 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 : 93769 : case LT:
2769 : 93769 : case NE:
2770 : 93769 : case EQ:
2771 : 93769 : case UNGE:
2772 : 93769 : arith_cost = TARGET_IEEE_FP ? 5 : 4;
2773 : : break;
2774 : 26346 : case LE:
2775 : 26346 : case UNGT:
2776 : 1071708 : arith_cost = TARGET_IEEE_FP ? 6 : 4;
2777 : : break;
2778 : 0 : default:
2779 : 0 : gcc_unreachable ();
2780 : : }
2781 : :
2782 : 1164688 : switch (ix86_fp_comparison_strategy (code))
2783 : : {
2784 : 1164688 : case IX86_FPCMP_COMI:
2785 : 1164688 : 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 : 582344 : ix86_prepare_fp_compare_args (enum rtx_code code, rtx *pop0, rtx *pop1)
2799 : : {
2800 : 582438 : bool unordered_compare = ix86_unordered_fp_compare (code);
2801 : 582438 : rtx op0 = *pop0, op1 = *pop1;
2802 : 582438 : machine_mode op_mode = GET_MODE (op0);
2803 : 582438 : bool is_sse = SSE_FLOAT_MODE_SSEMATH_OR_HFBF_P (op_mode);
2804 : :
2805 : 580496 : if (op_mode == BFmode && (!TARGET_AVX10_2 || flag_trapping_math))
2806 : : {
2807 : 94 : rtx op = gen_lowpart (HImode, op0);
2808 : 94 : if (CONST_INT_P (op))
2809 : 0 : op = simplify_const_unary_operation (FLOAT_EXTEND, SFmode,
2810 : : op0, BFmode);
2811 : : else
2812 : : {
2813 : 94 : rtx t1 = gen_reg_rtx (SImode);
2814 : 94 : emit_insn (gen_zero_extendhisi2 (t1, op));
2815 : 94 : emit_insn (gen_ashlsi3 (t1, t1, GEN_INT (16)));
2816 : 94 : op = gen_lowpart (SFmode, t1);
2817 : : }
2818 : 94 : *pop0 = op;
2819 : 94 : op = gen_lowpart (HImode, op1);
2820 : 94 : if (CONST_INT_P (op))
2821 : 6 : op = simplify_const_unary_operation (FLOAT_EXTEND, SFmode,
2822 : : op1, BFmode);
2823 : : else
2824 : : {
2825 : 88 : rtx t1 = gen_reg_rtx (SImode);
2826 : 88 : emit_insn (gen_zero_extendhisi2 (t1, op));
2827 : 88 : emit_insn (gen_ashlsi3 (t1, t1, GEN_INT (16)));
2828 : 88 : op = gen_lowpart (SFmode, t1);
2829 : : }
2830 : 94 : *pop1 = op;
2831 : 94 : 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 : 582344 : if (!is_sse
2841 : 582344 : && (unordered_compare
2842 : 8388 : || (op_mode == XFmode
2843 : 10735 : && ! (standard_80387_constant_p (op0) == 1
2844 : 5365 : || standard_80387_constant_p (op1) == 1)
2845 : 5017 : && GET_CODE (op1) != FLOAT)
2846 : 3371 : || ix86_fp_comparison_strategy (code) == IX86_FPCMP_COMI))
2847 : : {
2848 : 148003 : op0 = force_reg (op_mode, op0);
2849 : 148003 : 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 : 434341 : if (standard_80387_constant_p (op0) == 0
2858 : 434341 : || (MEM_P (op0)
2859 : 55126 : && ! (standard_80387_constant_p (op1) == 0
2860 : 40341 : || MEM_P (op1))))
2861 : : {
2862 : 36709 : enum rtx_code new_code = ix86_fp_swap_condition (code);
2863 : 36709 : if (new_code != UNKNOWN)
2864 : : {
2865 : : std::swap (op0, op1);
2866 : 434341 : code = new_code;
2867 : : }
2868 : : }
2869 : :
2870 : 434341 : if (!REG_P (op0))
2871 : 52357 : op0 = force_reg (op_mode, op0);
2872 : :
2873 : 434341 : if (CONSTANT_P (op1))
2874 : : {
2875 : 191163 : int tmp = standard_80387_constant_p (op1);
2876 : 191163 : if (tmp == 0)
2877 : 72779 : op1 = validize_mem (force_const_mem (op_mode, op1));
2878 : 118384 : else if (tmp == 1)
2879 : : {
2880 : 64602 : if (TARGET_CMOVE)
2881 : 64602 : 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 : 582344 : if (ix86_fp_comparison_cost (code)
2890 : 582344 : > ix86_fp_comparison_cost (swap_condition (code))
2891 : 582344 : && (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 : 582344 : *pop0 = op0;
2900 : 582344 : *pop1 = op1;
2901 : 582344 : return code;
2902 : : }
2903 : :
2904 : : /* Generate insn patterns to do a floating point compare of OPERANDS. */
2905 : :
2906 : : static rtx
2907 : 582344 : ix86_expand_fp_compare (enum rtx_code code, rtx op0, rtx op1)
2908 : : {
2909 : 582344 : bool unordered_compare = ix86_unordered_fp_compare (code);
2910 : 582344 : machine_mode cmp_mode;
2911 : 582344 : rtx tmp, scratch;
2912 : :
2913 : 582344 : code = ix86_prepare_fp_compare_args (code, &op0, &op1);
2914 : :
2915 : 582344 : tmp = gen_rtx_COMPARE (CCFPmode, op0, op1);
2916 : 582344 : if (unordered_compare)
2917 : 499129 : tmp = gen_rtx_UNSPEC (CCFPmode, gen_rtvec (1, tmp), UNSPEC_NOTRAP);
2918 : :
2919 : : /* Do fcomi/sahf based test when profitable. */
2920 : 582344 : switch (ix86_fp_comparison_strategy (code))
2921 : : {
2922 : 582344 : case IX86_FPCMP_COMI:
2923 : 582344 : tmp = gen_rtx_COMPARE (CCFPmode, op0, op1);
2924 : : /* We only have vcomisbf16, No vcomubf16 nor vcomxbf16 */
2925 : 582344 : if (GET_MODE (op0) != E_BFmode)
2926 : : {
2927 : 582328 : if (TARGET_AVX10_2 && (code == EQ || code == NE))
2928 : 12 : tmp = gen_rtx_UNSPEC (CCFPmode, gen_rtvec (1, tmp), UNSPEC_OPTCOMX);
2929 : 582328 : if (unordered_compare)
2930 : 499125 : tmp = gen_rtx_UNSPEC (CCFPmode, gen_rtvec (1, tmp), UNSPEC_NOTRAP);
2931 : : }
2932 : 582344 : cmp_mode = CCFPmode;
2933 : 582344 : emit_insn (gen_rtx_SET (gen_rtx_REG (CCFPmode, FLAGS_REG), tmp));
2934 : 582344 : 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 : 582344 : 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 : 6830838 : ix86_expand_int_compare (enum rtx_code code, rtx op0, rtx op1)
3078 : : {
3079 : 6830838 : machine_mode cmpmode;
3080 : 6830838 : rtx tmp, flags;
3081 : :
3082 : : /* Swap operands to emit carry flag comparison. */
3083 : 6830838 : if ((code == GTU || code == LEU)
3084 : 6830838 : && nonimmediate_operand (op1, VOIDmode))
3085 : : {
3086 : 136560 : std::swap (op0, op1);
3087 : 136560 : code = swap_condition (code);
3088 : : }
3089 : :
3090 : 6830838 : cmpmode = SELECT_CC_MODE (code, op0, op1);
3091 : 6830838 : 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 : 6830838 : if (op1 == const0_rtx
3096 : 2862569 : && SUBREG_P (op0)
3097 : 23571 : && cmpmode == CCZmode
3098 : 10786 : && SUBREG_BYTE (op0) == 0
3099 : 8689 : && REG_P (SUBREG_REG (op0))
3100 : 8689 : && VECTOR_MODE_P (GET_MODE (SUBREG_REG (op0)))
3101 : 7 : && TARGET_SSE4_1
3102 : 1 : && GET_MODE (op0) == TImode
3103 : 6830840 : && 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 : 6830837 : 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 : 6830838 : 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 : 6830838 : return gen_rtx_fmt_ee (code, VOIDmode, flags, const0_rtx);
3120 : : }
3121 : :
3122 : : static rtx
3123 : 7573681 : ix86_expand_compare (enum rtx_code code, rtx op0, rtx op1)
3124 : : {
3125 : 7573681 : rtx ret;
3126 : :
3127 : 7573681 : if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_CC)
3128 : 164458 : ret = gen_rtx_fmt_ee (code, VOIDmode, op0, op1);
3129 : :
3130 : 7409223 : else if (SCALAR_FLOAT_MODE_P (GET_MODE (op0)))
3131 : : {
3132 : 578385 : gcc_assert (!DECIMAL_FLOAT_MODE_P (GET_MODE (op0)));
3133 : 578385 : ret = ix86_expand_fp_compare (code, op0, op1);
3134 : : }
3135 : : else
3136 : 6830838 : ret = ix86_expand_int_compare (code, op0, op1);
3137 : :
3138 : 7573681 : return ret;
3139 : : }
3140 : :
3141 : : void
3142 : 533975 : ix86_expand_setcc (rtx dest, enum rtx_code code, rtx op0, rtx op1)
3143 : : {
3144 : 533975 : rtx ret;
3145 : :
3146 : 533975 : gcc_assert (GET_MODE (dest) == QImode);
3147 : :
3148 : 533975 : ret = ix86_expand_compare (code, op0, op1);
3149 : 533975 : PUT_MODE (ret, QImode);
3150 : 533975 : emit_insn (gen_rtx_SET (dest, ret));
3151 : 533975 : }
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 : 388 : ix86_expand_fp_spaceship (rtx dest, rtx op0, rtx op1, rtx op2)
3158 : : {
3159 : 388 : gcc_checking_assert (ix86_fp_comparison_strategy (GT) != IX86_FPCMP_ARITH);
3160 : 388 : rtx zero = NULL_RTX;
3161 : 388 : 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 : 388 : rtx gt = ix86_expand_fp_compare (GT, op0, op1);
3166 : 388 : rtx l0 = op2 == const0_rtx ? gen_label_rtx () : NULL_RTX;
3167 : 388 : rtx l1 = op2 == const0_rtx ? gen_label_rtx () : NULL_RTX;
3168 : 388 : rtx l2 = TARGET_IEEE_FP ? gen_label_rtx () : NULL_RTX;
3169 : 388 : rtx lend = gen_label_rtx ();
3170 : 388 : rtx tmp;
3171 : 388 : rtx_insn *jmp;
3172 : 388 : if (l2)
3173 : : {
3174 : 351 : rtx un = gen_rtx_fmt_ee (UNORDERED, VOIDmode,
3175 : : gen_rtx_REG (CCFPmode, FLAGS_REG), const0_rtx);
3176 : 351 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, un,
3177 : : gen_rtx_LABEL_REF (VOIDmode, l2), pc_rtx);
3178 : 351 : jmp = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
3179 : 351 : add_reg_br_prob_note (jmp, profile_probability:: very_unlikely ());
3180 : : }
3181 : 388 : if (op2 == const0_rtx)
3182 : : {
3183 : 336 : rtx eq = gen_rtx_fmt_ee (UNEQ, VOIDmode,
3184 : : gen_rtx_REG (CCFPmode, FLAGS_REG), const0_rtx);
3185 : 336 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, eq,
3186 : : gen_rtx_LABEL_REF (VOIDmode, l0), pc_rtx);
3187 : 336 : jmp = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
3188 : 336 : add_reg_br_prob_note (jmp, profile_probability::unlikely ());
3189 : 336 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, gt,
3190 : : gen_rtx_LABEL_REF (VOIDmode, l1), pc_rtx);
3191 : 336 : jmp = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
3192 : 336 : add_reg_br_prob_note (jmp, profile_probability::even ());
3193 : 336 : emit_move_insn (dest, constm1_rtx);
3194 : 336 : emit_jump (lend);
3195 : 336 : emit_label (l0);
3196 : 336 : emit_move_insn (dest, const0_rtx);
3197 : 336 : emit_jump (lend);
3198 : 336 : emit_label (l1);
3199 : 336 : 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 : 388 : emit_jump (lend);
3264 : 388 : if (l2)
3265 : : {
3266 : 351 : emit_label (l2);
3267 : 351 : emit_move_insn (dest, op2 == const0_rtx ? const2_rtx : op2);
3268 : : }
3269 : 388 : emit_label (lend);
3270 : 388 : }
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 : 35253 : ix86_expand_carry_flag_compare (enum rtx_code code, rtx op0, rtx op1, rtx *pop)
3364 : : {
3365 : 70506 : machine_mode mode
3366 : 35253 : = GET_MODE (op0) != VOIDmode ? GET_MODE (op0) : GET_MODE (op1);
3367 : :
3368 : : /* Do not handle double-mode compares that go through special path. */
3369 : 37320 : if (mode == (TARGET_64BIT ? TImode : DImode))
3370 : : return false;
3371 : :
3372 : 35245 : 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 : 31672 : if (!INTEGRAL_MODE_P (mode))
3415 : : return false;
3416 : :
3417 : 31600 : switch (code)
3418 : : {
3419 : : case LTU:
3420 : : case GEU:
3421 : : break;
3422 : :
3423 : : /* Convert a==0 into (unsigned)a<1. */
3424 : 25932 : case EQ:
3425 : 25932 : case NE:
3426 : 25932 : if (op1 != const0_rtx)
3427 : : return false;
3428 : 9670 : op1 = const1_rtx;
3429 : 9670 : code = (code == EQ ? LTU : GEU);
3430 : : break;
3431 : :
3432 : : /* Convert a>b into b<a or a>=b-1. */
3433 : 991 : case GTU:
3434 : 991 : case LEU:
3435 : 991 : if (CONST_INT_P (op1))
3436 : : {
3437 : 949 : 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 : 949 : if (op1 == const0_rtx
3441 : 949 : || !x86_64_immediate_operand (op1, GET_MODE (op1)))
3442 : 0 : return false;
3443 : 949 : 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 : 3278 : case LT:
3454 : 3278 : case GE:
3455 : 3278 : 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 : 818 : case LE:
3461 : 818 : case GT:
3462 : 818 : 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 : 11341 : 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 : 11341 : *pop = ix86_expand_compare (code, op0, op1);
3479 : 11341 : 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 : 11833 : ix86_expand_int_addcc (rtx operands[])
3488 : : {
3489 : 11833 : enum rtx_code code = GET_CODE (operands[1]);
3490 : 11833 : rtx flags;
3491 : 11833 : rtx (*insn) (machine_mode, rtx, rtx, rtx, rtx, rtx);
3492 : 11833 : rtx compare_op;
3493 : 11833 : rtx val = const0_rtx;
3494 : 11833 : bool fpcmp = false;
3495 : 11833 : machine_mode mode;
3496 : 11833 : rtx op0 = XEXP (operands[1], 0);
3497 : 11833 : rtx op1 = XEXP (operands[1], 1);
3498 : :
3499 : 11833 : if (operands[3] != const1_rtx
3500 : 7026 : && operands[3] != constm1_rtx)
3501 : : return false;
3502 : 7578 : if (!ix86_expand_carry_flag_compare (code, op0, op1, &compare_op))
3503 : : return false;
3504 : 1233 : code = GET_CODE (compare_op);
3505 : :
3506 : 1233 : flags = XEXP (compare_op, 0);
3507 : :
3508 : 1233 : if (GET_MODE (flags) == CCFPmode)
3509 : : {
3510 : 4 : fpcmp = true;
3511 : 4 : code = ix86_fp_compare_code_to_integer (code);
3512 : : }
3513 : :
3514 : 1233 : if (code != LTU)
3515 : : {
3516 : 747 : val = constm1_rtx;
3517 : 747 : if (fpcmp)
3518 : 4 : PUT_CODE (compare_op,
3519 : : reverse_condition_maybe_unordered
3520 : : (GET_CODE (compare_op)));
3521 : : else
3522 : 743 : PUT_CODE (compare_op, reverse_condition (GET_CODE (compare_op)));
3523 : : }
3524 : :
3525 : 1233 : mode = GET_MODE (operands[0]);
3526 : :
3527 : : /* Construct either adc or sbb insn. */
3528 : 1233 : if ((code == LTU) == (operands[3] == constm1_rtx))
3529 : : insn = gen_sub3_carry;
3530 : : else
3531 : 463 : insn = gen_add3_carry;
3532 : :
3533 : 1233 : emit_insn (insn (mode, operands[0], operands[2], val, flags, compare_op));
3534 : :
3535 : 1233 : return true;
3536 : : }
3537 : :
3538 : : bool
3539 : 531706 : ix86_expand_int_movcc (rtx operands[])
3540 : : {
3541 : 531706 : enum rtx_code code = GET_CODE (operands[1]), compare_code;
3542 : 531706 : rtx_insn *compare_seq;
3543 : 531706 : rtx compare_op;
3544 : 531706 : machine_mode mode = GET_MODE (operands[0]);
3545 : 531706 : bool sign_bit_compare_p = false;
3546 : 531706 : bool negate_cc_compare_p = false;
3547 : 531706 : rtx op0 = XEXP (operands[1], 0);
3548 : 531706 : rtx op1 = XEXP (operands[1], 1);
3549 : 531706 : rtx op2 = operands[2];
3550 : 531706 : rtx op3 = operands[3];
3551 : :
3552 : 531706 : if (GET_MODE (op0) == TImode
3553 : 516202 : || (GET_MODE (op0) == DImode
3554 : 113472 : && !TARGET_64BIT))
3555 : : return false;
3556 : :
3557 : 515082 : if (GET_MODE (op0) == BFmode
3558 : 515082 : && !ix86_fp_comparison_operator (operands[1], VOIDmode))
3559 : : return false;
3560 : :
3561 : 515082 : start_sequence ();
3562 : 515082 : compare_op = ix86_expand_compare (code, op0, op1);
3563 : 515082 : compare_seq = end_sequence ();
3564 : :
3565 : 515082 : compare_code = GET_CODE (compare_op);
3566 : :
3567 : 515082 : if ((op1 == const0_rtx && (code == GE || code == LT))
3568 : 457889 : || (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 : 457889 : 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 : 514567 : 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 : 4654 : if ((mode != HImode || TARGET_FAST_PREFIX)
3587 : 546820 : && (mode != (TARGET_64BIT ? TImode : DImode))
3588 : 515082 : && CONST_INT_P (op2)
3589 : 552793 : && CONST_INT_P (op3))
3590 : : {
3591 : 30073 : rtx out = operands[0];
3592 : 30073 : HOST_WIDE_INT ct = INTVAL (op2);
3593 : 30073 : HOST_WIDE_INT cf = INTVAL (op3);
3594 : 30073 : HOST_WIDE_INT diff;
3595 : :
3596 : 30073 : if ((mode == SImode
3597 : 17483 : || (TARGET_64BIT && mode == DImode))
3598 : 21092 : && (GET_MODE (op0) == SImode
3599 : 16237 : || (TARGET_64BIT && GET_MODE (op0) == DImode)))
3600 : : {
3601 : : /* Special case x != 0 ? -1 : y. */
3602 : 13534 : 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 : 13391 : else if (code == EQ && op1 == const0_rtx && cf == -1)
3609 : 30073 : negate_cc_compare_p = true;
3610 : : }
3611 : :
3612 : 30073 : diff = (unsigned HOST_WIDE_INT) ct - cf;
3613 : : /* Make sure we can represent the difference between the two values. */
3614 : 30073 : if ((diff > 0) != ((cf < 0) != (ct < 0) ? cf < 0 : cf < ct))
3615 : 531706 : return false;
3616 : :
3617 : : /* Sign bit compares are better done using shifts than we do by using
3618 : : sbb. */
3619 : 30017 : if (sign_bit_compare_p
3620 : 30017 : || negate_cc_compare_p
3621 : 30017 : || ix86_expand_carry_flag_compare (code, op0, op1, &compare_op))
3622 : : {
3623 : : /* Detect overlap between destination and compare sources. */
3624 : 12521 : rtx tmp = out;
3625 : :
3626 : 12521 : 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 : 12202 : else if (!sign_bit_compare_p)
3642 : : {
3643 : 10179 : rtx flags;
3644 : 10179 : bool fpcmp = false;
3645 : :
3646 : 10179 : compare_code = GET_CODE (compare_op);
3647 : :
3648 : 10179 : flags = XEXP (compare_op, 0);
3649 : :
3650 : 10179 : 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 : 10179 : if (compare_code == LTU)
3659 : : {
3660 : 5669 : std::swap (ct, cf);
3661 : 5669 : compare_code = reverse_condition (compare_code);
3662 : 5669 : code = reverse_condition (code);
3663 : : }
3664 : : else
3665 : : {
3666 : 4510 : if (fpcmp)
3667 : 67 : PUT_CODE (compare_op,
3668 : : reverse_condition_maybe_unordered
3669 : : (GET_CODE (compare_op)));
3670 : : else
3671 : 4443 : PUT_CODE (compare_op,
3672 : : reverse_condition (GET_CODE (compare_op)));
3673 : : }
3674 : :
3675 : 10179 : diff = (unsigned HOST_WIDE_INT) ct - cf;
3676 : : /* Make sure we can represent the difference
3677 : : between the two values. */
3678 : 10179 : if ((diff > 0) != ((cf < 0) != (ct < 0) ? cf < 0 : cf < ct))
3679 : : return false;
3680 : :
3681 : 10178 : if (reg_overlap_mentioned_p (out, compare_op))
3682 : 0 : tmp = gen_reg_rtx (mode);
3683 : :
3684 : 10178 : if (mode == DImode)
3685 : 2521 : emit_insn (gen_x86_movdicc_0_m1 (tmp, flags, compare_op));
3686 : : else
3687 : 7657 : emit_insn (gen_x86_movsicc_0_m1 (gen_lowpart (SImode, tmp),
3688 : : flags, compare_op));
3689 : : }
3690 : : else
3691 : : {
3692 : 2023 : if (code == GT || code == GE)
3693 : 175 : code = reverse_condition (code);
3694 : : else
3695 : : {
3696 : 1848 : std::swap (ct, cf);
3697 : :
3698 : 1848 : diff = (unsigned HOST_WIDE_INT) ct - cf;
3699 : : /* Make sure we can represent the difference
3700 : : between the two values. */
3701 : 1848 : if ((diff > 0) != ((cf < 0) != (ct < 0) ? cf < 0 : cf < ct))
3702 : : return false;
3703 : : }
3704 : 2020 : tmp = emit_store_flag (tmp, code, op0, op1, VOIDmode, 0, -1);
3705 : : }
3706 : :
3707 : 12517 : if (diff == 1)
3708 : : {
3709 : : /*
3710 : : * cmpl op0,op1
3711 : : * sbbl dest,dest
3712 : : * [addl dest, ct]
3713 : : *
3714 : : * Size 5 - 8.
3715 : : */
3716 : 1881 : if (ct)
3717 : 1747 : tmp = expand_simple_binop (mode, PLUS,
3718 : : tmp, GEN_INT (ct),
3719 : : copy_rtx (tmp), 1, OPTAB_DIRECT);
3720 : : }
3721 : 10636 : else if (cf == -1)
3722 : : {
3723 : : /*
3724 : : * cmpl op0,op1
3725 : : * sbbl dest,dest
3726 : : * orl $ct, dest
3727 : : *
3728 : : * Size 8.
3729 : : */
3730 : 718 : tmp = expand_simple_binop (mode, IOR,
3731 : : tmp, GEN_INT (ct),
3732 : : copy_rtx (tmp), 1, OPTAB_DIRECT);
3733 : : }
3734 : 9918 : 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 : 869 : tmp = expand_simple_unop (mode, NOT, tmp, copy_rtx (tmp), 1);
3745 : 869 : if (cf)
3746 : 853 : 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 : 9049 : if (cf == 0)
3763 : : {
3764 : 825 : cf = ct;
3765 : 825 : ct = 0;
3766 : 825 : tmp = expand_simple_unop (mode, NOT, tmp, copy_rtx (tmp), 1);
3767 : : }
3768 : :
3769 : 9049 : HOST_WIDE_INT ival = (unsigned HOST_WIDE_INT) cf - ct;
3770 : : /* Make sure we can represent the difference
3771 : : between the two values. */
3772 : 9049 : if ((ival > 0) != ((ct < 0) != (cf < 0) ? ct < 0 : ct < cf))
3773 : 16684 : return false;
3774 : :
3775 : 9049 : tmp = expand_simple_binop (mode, AND,
3776 : : copy_rtx (tmp),
3777 : 9049 : gen_int_mode (ival, mode),
3778 : : copy_rtx (tmp), 1, OPTAB_DIRECT);
3779 : 9049 : if (ct)
3780 : 5986 : tmp = expand_simple_binop (mode, PLUS,
3781 : : copy_rtx (tmp), GEN_INT (ct),
3782 : : copy_rtx (tmp), 1, OPTAB_DIRECT);
3783 : : }
3784 : :
3785 : 12517 : if (!rtx_equal_p (tmp, out))
3786 : 412 : emit_move_insn (copy_rtx (out), copy_rtx (tmp));
3787 : :
3788 : 12517 : return true;
3789 : : }
3790 : :
3791 : 17496 : if (diff < 0)
3792 : : {
3793 : 6762 : machine_mode cmp_mode = GET_MODE (op0);
3794 : 6762 : enum rtx_code new_code;
3795 : :
3796 : 6762 : 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 : 6721 : new_code = ix86_reverse_condition (code, cmp_mode);
3811 : 6733 : if (new_code != UNKNOWN)
3812 : : {
3813 : 6733 : std::swap (ct, cf);
3814 : :
3815 : 6733 : diff = (unsigned HOST_WIDE_INT) ct - cf;
3816 : : /* Make sure we can represent the difference
3817 : : between the two values. */
3818 : 6733 : if ((diff > 0) != ((cf < 0) != (ct < 0) ? cf < 0 : cf < ct))
3819 : : return false;
3820 : :
3821 : : code = new_code;
3822 : : }
3823 : : }
3824 : :
3825 : 17496 : compare_code = UNKNOWN;
3826 : 17496 : if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT
3827 : 14072 : && CONST_INT_P (op1))
3828 : : {
3829 : 9264 : if (op1 == const0_rtx
3830 : 96 : && (code == LT || code == GE))
3831 : : compare_code = code;
3832 : 9264 : 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 : 26950 : if ((diff == 1 || diff == 2 || diff == 4 || diff == 8
3880 : 9454 : || diff == 3 || diff == 5 || diff == 9)
3881 : 8307 : && ((mode != QImode && mode != HImode) || !TARGET_PARTIAL_REG_STALL)
3882 : 25803 : && (mode != DImode
3883 : 3714 : || 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 : 8307 : rtx tmp;
3897 : 8307 : int nops;
3898 : :
3899 : 8307 : out = emit_store_flag (out, code, op0, op1, VOIDmode, 0, 1);
3900 : :
3901 : 8307 : 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 : 8307 : if (diff == 1)
3905 : 7273 : tmp = copy_rtx (out);
3906 : : else
3907 : : {
3908 : 1034 : rtx out1;
3909 : 1034 : out1 = copy_rtx (out);
3910 : 1034 : tmp = gen_rtx_MULT (mode, out1, GEN_INT (diff & ~1));
3911 : 1034 : nops++;
3912 : 1034 : if (diff & 1)
3913 : : {
3914 : 229 : tmp = gen_rtx_PLUS (mode, tmp, out1);
3915 : 229 : nops++;
3916 : : }
3917 : : }
3918 : 8307 : if (cf != 0)
3919 : : {
3920 : 7479 : tmp = plus_constant (mode, tmp, cf);
3921 : 7479 : nops++;
3922 : : }
3923 : 8307 : if (!rtx_equal_p (tmp, out))
3924 : : {
3925 : 7625 : if (nops == 1)
3926 : 6597 : out = force_operand (tmp, copy_rtx (out));
3927 : : else
3928 : 1028 : emit_insn (gen_rtx_SET (copy_rtx (out), copy_rtx (tmp)));
3929 : : }
3930 : 8307 : if (!rtx_equal_p (out, operands[0]))
3931 : 781 : emit_move_insn (operands[0], copy_rtx (out));
3932 : :
3933 : 8307 : 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 : 9189 : if ((!TARGET_CMOVE || (mode == QImode && TARGET_PARTIAL_REG_STALL))
3953 : 9189 : && 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 : 494198 : 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 : 494198 : if (! nonimmediate_operand (operands[2], mode))
4120 : 28357 : operands[2] = force_reg (mode, operands[2]);
4121 : 494198 : if (! nonimmediate_operand (operands[3], mode))
4122 : 214684 : operands[3] = force_reg (mode, operands[3]);
4123 : :
4124 : 494198 : if (! register_operand (operands[2], VOIDmode)
4125 : 494198 : && (mode == QImode
4126 : 1100 : || ! register_operand (operands[3], VOIDmode)))
4127 : 1564 : operands[2] = force_reg (mode, operands[2]);
4128 : :
4129 : 494198 : if (mode == QImode
4130 : 494198 : && ! register_operand (operands[3], VOIDmode))
4131 : 592 : operands[3] = force_reg (mode, operands[3]);
4132 : :
4133 : 494198 : emit_insn (compare_seq);
4134 : 494198 : emit_insn (gen_rtx_SET (operands[0],
4135 : : gen_rtx_IF_THEN_ELSE (mode,
4136 : : compare_op, operands[2],
4137 : : operands[3])));
4138 : 494198 : 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 : 10829 : 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 : 10829 : machine_mode mode;
4153 : 10829 : bool is_min;
4154 : 10829 : rtx tmp;
4155 : :
4156 : 10829 : if (code == LT)
4157 : : ;
4158 : 3149 : else if (code == UNGE)
4159 : : std::swap (if_true, if_false);
4160 : : else
4161 : : return false;
4162 : :
4163 : 9858 : if (rtx_equal_p (cmp_op0, if_true) && rtx_equal_p (cmp_op1, if_false))
4164 : : is_min = true;
4165 : 4808 : 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 : 8783 : mode = GET_MODE (dest);
4171 : 8783 : if (immediate_operand (if_false, mode))
4172 : 8 : if_false = force_reg (mode, if_false);
4173 : 8783 : 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 : 8783 : if (!flag_finite_math_only || flag_signed_zeros)
4179 : : {
4180 : 8783 : int u = is_min ? UNSPEC_IEEE_MIN : UNSPEC_IEEE_MAX;
4181 : 8783 : rtvec v;
4182 : :
4183 : 8783 : if_true = force_reg (mode, if_true);
4184 : 8783 : v = gen_rtvec (2, if_true, if_false);
4185 : 8783 : tmp = gen_rtx_UNSPEC (mode, v, u);
4186 : 8783 : }
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 : 8783 : emit_insn (gen_rtx_SET (dest, tmp));
4196 : 8783 : 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 : 13794 : ix86_valid_mask_cmp_mode (machine_mode mode)
4203 : : {
4204 : : /* XOP has its own vector conditional movement. */
4205 : 13794 : if (TARGET_XOP && !TARGET_AVX512F)
4206 : : return false;
4207 : :
4208 : : /* HFmode only supports vcmpsh whose dest is mask register. */
4209 : 13788 : if (TARGET_AVX512FP16 && mode == HFmode)
4210 : : return true;
4211 : :
4212 : : /* AVX512F is needed for mask operation. */
4213 : 13784 : 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 : 46195 : ix86_use_mask_cmp_p (machine_mode mode, machine_mode cmp_mode,
4229 : : rtx op_true, rtx op_false)
4230 : : {
4231 : 46195 : int vector_size = GET_MODE_SIZE (mode);
4232 : :
4233 : 46195 : if (cmp_mode == HFmode)
4234 : : return true;
4235 : 46191 : else if (vector_size < 16)
4236 : : return false;
4237 : 40916 : else if (vector_size == 64)
4238 : : return true;
4239 : 81716 : else if (GET_MODE_INNER (cmp_mode) == HFmode)
4240 : : return true;
4241 : 81716 : 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 : 40858 : 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 : 40858 : 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 : 31534 : 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 : 31534 : machine_mode mode = GET_MODE (dest);
4270 : 31534 : machine_mode cmp_ops_mode = GET_MODE (cmp_op0);
4271 : :
4272 : : /* In general case result of comparison can differ from operands' type. */
4273 : 31534 : machine_mode cmp_mode;
4274 : :
4275 : : /* In AVX512F the result of comparison is an integer mask. */
4276 : 31534 : bool maskcmp = false;
4277 : 31534 : rtx x;
4278 : :
4279 : 31534 : 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 : 31534 : cmp_op0 = force_reg (cmp_ops_mode, cmp_op0);
4289 : :
4290 : 63068 : bool (*op1_predicate)(rtx, machine_mode)
4291 : 31534 : = VECTOR_MODE_P (cmp_ops_mode) ? vector_operand : nonimmediate_operand;
4292 : :
4293 : 31534 : if (!op1_predicate (cmp_op1, cmp_ops_mode))
4294 : 0 : cmp_op1 = force_reg (cmp_ops_mode, cmp_op1);
4295 : :
4296 : 31534 : if (optimize
4297 : 503 : || (maskcmp && cmp_mode != mode)
4298 : 503 : || (op_true && reg_overlap_mentioned_p (dest, op_true))
4299 : 32037 : || (op_false && reg_overlap_mentioned_p (dest, op_false)))
4300 : 62005 : dest = gen_reg_rtx (maskcmp ? cmp_mode : mode);
4301 : :
4302 : 31534 : 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 : 31477 : x = gen_rtx_fmt_ee (code, cmp_mode, cmp_op0, cmp_op1);
4310 : :
4311 : 31477 : if (cmp_mode != mode)
4312 : : {
4313 : 6866 : x = force_reg (cmp_ops_mode, x);
4314 : 6866 : convert_move (dest, x, false);
4315 : : }
4316 : : else
4317 : 24611 : 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 : 6753 : ix86_emit_vec_binop (enum rtx_code code, machine_mode mode,
4327 : : rtx dst, rtx src1, rtx src2)
4328 : : {
4329 : 6753 : rtx tmp;
4330 : :
4331 : 6753 : tmp = gen_rtx_SET (dst, gen_rtx_fmt_ee (code, mode, src1, src2));
4332 : :
4333 : 6753 : if (GET_MODE_SIZE (mode) <= GET_MODE_SIZE (SImode)
4334 : 6753 : && 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 : 6753 : emit_insn (tmp);
4341 : 6753 : }
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 : 8701 : ix86_expand_sse_movcc (rtx dest, rtx cmp, rtx op_true, rtx op_false)
4348 : : {
4349 : 8701 : machine_mode mode = GET_MODE (dest);
4350 : 8701 : machine_mode cmpmode = GET_MODE (cmp);
4351 : 8701 : rtx x;
4352 : :
4353 : : /* Simplify trivial VEC_COND_EXPR to avoid ICE in pr97506. */
4354 : 8701 : 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 : 8701 : 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 : 8701 : 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 : 8644 : if (vector_all_ones_operand (op_true, mode)
4404 : 8644 : && op_false == CONST0_RTX (mode))
4405 : : {
4406 : 2 : emit_move_insn (dest, cmp);
4407 : 2 : return;
4408 : : }
4409 : 8642 : 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 : 8280 : 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 : 8184 : 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 : 8184 : 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 : 8119 : rtx (*gen) (rtx, rtx, rtx, rtx) = NULL;
4448 : 8119 : machine_mode blend_mode = mode;
4449 : :
4450 : 8119 : if (GET_MODE_SIZE (mode) < 16
4451 : 8119 : || !vector_operand (op_true, mode))
4452 : 2223 : op_true = force_reg (mode, op_true);
4453 : :
4454 : 8119 : op_false = force_reg (mode, op_false);
4455 : :
4456 : 8119 : 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 : 285 : case E_V4SFmode:
4463 : 285 : 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 : 5118 : case E_V16QImode:
4504 : 5118 : case E_V8HImode:
4505 : 5118 : case E_V8HFmode:
4506 : 5118 : case E_V8BFmode:
4507 : 5118 : case E_V4SImode:
4508 : 5118 : case E_V2DImode:
4509 : 5118 : case E_V1TImode:
4510 : 5118 : if (TARGET_SSE_MOVCC_USE_BLENDV && TARGET_SSE4_1)
4511 : : {
4512 : : gen = gen_sse4_1_pblendvb;
4513 : : blend_mode = V16QImode;
4514 : : }
4515 : : break;
4516 : 74 : case E_V8SFmode:
4517 : 74 : 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 : 1527 : if (blend_mode == mode)
4569 : : x = dest;
4570 : : else
4571 : : {
4572 : 790 : x = gen_reg_rtx (blend_mode);
4573 : 790 : op_false = gen_lowpart (blend_mode, op_false);
4574 : 790 : op_true = gen_lowpart (blend_mode, op_true);
4575 : 790 : cmp = gen_lowpart (blend_mode, cmp);
4576 : : }
4577 : :
4578 : 1527 : emit_insn (gen (x, op_false, op_true, cmp));
4579 : :
4580 : 1527 : if (x != dest)
4581 : 790 : emit_move_insn (dest, gen_lowpart (mode, x));
4582 : : }
4583 : : else
4584 : : {
4585 : 6592 : rtx t2, t3;
4586 : :
4587 : 6592 : t2 = expand_simple_binop (mode, AND, op_true, cmp,
4588 : : NULL, 1, OPTAB_DIRECT);
4589 : :
4590 : 6592 : t3 = gen_reg_rtx (mode);
4591 : 6592 : x = gen_rtx_NOT (mode, cmp);
4592 : 6592 : ix86_emit_vec_binop (AND, mode, t3, x, op_false);
4593 : :
4594 : 6592 : x = expand_simple_binop (mode, IOR, t3, t2,
4595 : : dest, 1, OPTAB_DIRECT);
4596 : 6592 : 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 : 17695 : ix86_prepare_sse_fp_compare_args (rtx dest, enum rtx_code code,
4611 : : rtx *pop0, rtx *pop1)
4612 : : {
4613 : 17695 : 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 : 11507 : case GE:
4647 : 11507 : case GT:
4648 : 11507 : case UNLE:
4649 : 11507 : 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 : 11507 : std::swap (*pop0, *pop1);
4655 : 11507 : code = swap_condition (code);
4656 : 11507 : 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 : 100223 : ix86_expand_fp_movcc (rtx operands[])
4669 : : {
4670 : 100223 : machine_mode mode = GET_MODE (operands[0]);
4671 : 100223 : enum rtx_code code = GET_CODE (operands[1]);
4672 : 100223 : rtx tmp, compare_op;
4673 : 100223 : rtx op0 = XEXP (operands[1], 0);
4674 : 100223 : rtx op1 = XEXP (operands[1], 1);
4675 : :
4676 : 100223 : if (GET_MODE (op0) == BFmode
4677 : 100223 : && !ix86_fp_comparison_operator (operands[1], VOIDmode))
4678 : : return false;
4679 : :
4680 : 100223 : if (SSE_FLOAT_MODE_SSEMATH_OR_HFBF_P (mode))
4681 : : {
4682 : 69563 : 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 : 69563 : cmode = GET_MODE (op0);
4688 : 69563 : if (cmode == VOIDmode)
4689 : 0 : cmode = GET_MODE (op1);
4690 : 69563 : if (cmode != mode)
4691 : : return false;
4692 : :
4693 : 10849 : code = ix86_prepare_sse_fp_compare_args (operands[0], code, &op0, &op1);
4694 : 10849 : if (code == UNKNOWN)
4695 : : return false;
4696 : :
4697 : 10829 : 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 : 30660 : if (GET_MODE (op0) == TImode
4708 : 30660 : || (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 : 30588 : compare_op = ix86_expand_compare (code, op0, op1);
4716 : 30588 : 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 : 30588 : operands[2] = force_reg (mode, operands[2]);
4725 : 30588 : operands[3] = force_reg (mode, operands[3]);
4726 : 30588 : emit_insn (gen_rtx_SET (operands[0],
4727 : : gen_rtx_IF_THEN_ELSE (mode, compare_op,
4728 : : operands[2], operands[3])));
4729 : :
4730 : 30588 : return true;
4731 : : }
4732 : :
4733 : : /* Helper for ix86_cmp_code_to_pcmp_immediate for int modes. */
4734 : :
4735 : : static int
4736 : 3064 : ix86_int_cmp_code_to_pcmp_immediate (enum rtx_code code)
4737 : : {
4738 : 3064 : 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 : 424 : case GT:
4754 : 424 : case GTU:
4755 : 424 : 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 : 1738 : ix86_fp_cmp_code_to_pcmp_immediate (enum rtx_code code)
4765 : : {
4766 : 1738 : 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 : 608 : case LT:
4779 : 608 : 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 : 4802 : ix86_cmp_code_to_pcmp_immediate (enum rtx_code code, machine_mode mode)
4806 : : {
4807 : 4802 : if (FLOAT_MODE_P (mode))
4808 : 1738 : return ix86_fp_cmp_code_to_pcmp_immediate (code);
4809 : 3064 : return ix86_int_cmp_code_to_pcmp_immediate (code);
4810 : : }
4811 : :
4812 : : /* Expand AVX-512 vector comparison. */
4813 : :
4814 : : bool
4815 : 4802 : ix86_expand_mask_vec_cmp (rtx dest, enum rtx_code code, rtx cmp_op0, rtx cmp_op1)
4816 : : {
4817 : 4802 : machine_mode mask_mode = GET_MODE (dest);
4818 : 4802 : machine_mode cmp_mode = GET_MODE (cmp_op0);
4819 : 4802 : rtx imm = GEN_INT (ix86_cmp_code_to_pcmp_immediate (code, cmp_mode));
4820 : 4802 : int unspec_code;
4821 : 4802 : rtx unspec;
4822 : :
4823 : 4802 : 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 : 4484 : default:
4833 : 4484 : unspec_code = UNSPEC_PCMP;
4834 : : }
4835 : :
4836 : 4802 : unspec = gen_rtx_UNSPEC (mask_mode, gen_rtvec (3, cmp_op0, cmp_op1, imm),
4837 : : unspec_code);
4838 : 4802 : emit_insn (gen_rtx_SET (dest, unspec));
4839 : :
4840 : 4802 : return true;
4841 : : }
4842 : :
4843 : : /* Expand fp vector comparison. */
4844 : :
4845 : : bool
4846 : 6846 : ix86_expand_fp_vec_cmp (rtx operands[])
4847 : : {
4848 : 6846 : enum rtx_code code = GET_CODE (operands[1]);
4849 : 6846 : rtx cmp;
4850 : :
4851 : 6846 : code = ix86_prepare_sse_fp_compare_args (operands[0], code,
4852 : : &operands[2], &operands[3]);
4853 : 6846 : 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 : 6826 : cmp = ix86_expand_sse_cmp (operands[0], code, operands[2], operands[3],
4880 : : NULL, NULL);
4881 : :
4882 : 6846 : if (operands[0] != cmp)
4883 : 6763 : emit_move_insn (operands[0], cmp);
4884 : :
4885 : 6846 : return true;
4886 : : }
4887 : :
4888 : : static rtx
4889 : 14859 : 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 : 14859 : machine_mode data_mode = GET_MODE (dest);
4893 : 14859 : machine_mode mode = GET_MODE (cop0);
4894 : 14859 : rtx x;
4895 : :
4896 : 14859 : *negate = false;
4897 : :
4898 : : /* XOP supports all of the comparisons on all 128-bit vector int types. */
4899 : 14859 : if (TARGET_XOP
4900 : 201 : && GET_MODE_CLASS (mode) == MODE_VECTOR_INT
4901 : 15060 : && GET_MODE_SIZE (mode) <= 16)
4902 : : ;
4903 : : /* AVX512F supports all of the comparsions
4904 : : on all 128/256/512-bit vector int types. */
4905 : 14661 : 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 : 14608 : switch (code)
4911 : : {
4912 : : case EQ:
4913 : : case GT:
4914 : : case GTU:
4915 : : break;
4916 : :
4917 : 700 : case LE:
4918 : 700 : case LEU:
4919 : : /* x <= cst can be handled as x < cst + 1 unless there is
4920 : : wrap around in cst + 1. */
4921 : 700 : if (GET_CODE (cop1) == CONST_VECTOR
4922 : 1187 : && 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 : 3004 : case NE:
4957 : 3004 : code = reverse_condition (code);
4958 : 3004 : *negate = true;
4959 : 3004 : break;
4960 : :
4961 : 373 : case GE:
4962 : 373 : case GEU:
4963 : : /* x >= cst can be handled as x > cst - 1 unless there is
4964 : : wrap around in cst - 1. */
4965 : 373 : if (GET_CODE (cop1) == CONST_VECTOR
4966 : 541 : && 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 : 253 : code = reverse_condition (code);
5000 : 253 : *negate = true;
5001 : : /* FALLTHRU */
5002 : :
5003 : 1472 : case LT:
5004 : 1472 : case LTU:
5005 : 1472 : std::swap (cop0, cop1);
5006 : 1472 : code = swap_condition (code);
5007 : 1472 : break;
5008 : :
5009 : 0 : default:
5010 : 0 : gcc_unreachable ();
5011 : : }
5012 : :
5013 : : /* Only SSE4.1/SSE4.2 supports V2DImode. */
5014 : 14608 : 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 : 14859 : 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 : 14608 : if (GET_CODE (cop0) == CONST_VECTOR)
5037 : 1028 : cop0 = force_reg (mode, cop0);
5038 : 13580 : else if (GET_CODE (cop1) == CONST_VECTOR)
5039 : 6282 : cop1 = force_reg (mode, cop1);
5040 : :
5041 : 14608 : rtx optrue = op_true ? op_true : CONSTM1_RTX (data_mode);
5042 : 14608 : rtx opfalse = op_false ? op_false : CONST0_RTX (data_mode);
5043 : 14608 : if (*negate)
5044 : 3257 : 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 : 14608 : if ((code != EQ
5054 : 6468 : && GET_MODE_SIZE (mode) != 64
5055 : 6468 : && vector_all_ones_operand (opfalse, data_mode)
5056 : 467 : && optrue == CONST0_RTX (data_mode))
5057 : 20609 : || (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 : 14608 : 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 : 14859 : if (*negate)
5235 : 3316 : std::swap (op_true, op_false);
5236 : :
5237 : 14859 : 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 : 14859 : if (data_mode == mode)
5243 : 14817 : 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 : 8383 : ix86_expand_int_vec_cmp (rtx operands[])
5260 : : {
5261 : 8383 : rtx_code code = GET_CODE (operands[1]);
5262 : 8383 : bool negate = false;
5263 : 8383 : rtx cmp = ix86_expand_int_sse_cmp (operands[0], code, operands[2],
5264 : : operands[3], NULL, NULL, &negate);
5265 : :
5266 : 8383 : if (!cmp)
5267 : : return false;
5268 : :
5269 : 8383 : if (negate)
5270 : 3220 : cmp = ix86_expand_int_sse_cmp (operands[0], EQ, cmp,
5271 : 3220 : CONST0_RTX (GET_MODE (cmp)),
5272 : : NULL, NULL, &negate);
5273 : :
5274 : 8383 : gcc_assert (!negate);
5275 : :
5276 : 8383 : if (operands[0] != cmp)
5277 : 8090 : 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 : 3256 : ix86_expand_int_vcond (rtx operands[])
5335 : : {
5336 : 3256 : machine_mode data_mode = GET_MODE (operands[0]);
5337 : 3256 : machine_mode mode = GET_MODE (operands[4]);
5338 : 3256 : enum rtx_code code = GET_CODE (operands[3]);
5339 : 3256 : bool negate = false;
5340 : 3256 : rtx x, cop0, cop1;
5341 : :
5342 : 3256 : cop0 = operands[4];
5343 : 3256 : 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 : 3256 : 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 : 3256 : && (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 : 3256 : if (!nonimmediate_operand (cop1, mode))
5378 : 125 : cop1 = force_reg (mode, cop1);
5379 : 3256 : if (!general_operand (operands[1], data_mode))
5380 : 0 : operands[1] = force_reg (data_mode, operands[1]);
5381 : 3256 : if (!general_operand (operands[2], data_mode))
5382 : 0 : operands[2] = force_reg (data_mode, operands[2]);
5383 : :
5384 : 3256 : x = ix86_expand_int_sse_cmp (operands[0], code, cop0, cop1,
5385 : : operands[1], operands[2], &negate);
5386 : :
5387 : 3256 : if (!x)
5388 : : return false;
5389 : :
5390 : 3256 : ix86_expand_sse_movcc (operands[0], x, operands[1+negate],
5391 : 3256 : operands[2-negate]);
5392 : 3256 : return true;
5393 : : }
5394 : :
5395 : : static bool
5396 : 140550 : 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 : 140550 : machine_mode mode = GET_MODE (d ? d->op0 : op0);
5402 : 140550 : machine_mode maskmode = mode;
5403 : 140550 : rtx (*gen) (rtx, rtx, rtx, rtx) = NULL;
5404 : :
5405 : 140550 : switch (mode)
5406 : : {
5407 : 25001 : case E_V16QImode:
5408 : 25001 : if (TARGET_AVX512VL && TARGET_AVX512VBMI)
5409 : : gen = gen_avx512vl_vpermt2varv16qi3;
5410 : : break;
5411 : 762 : case E_V32QImode:
5412 : 762 : 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 : 13889 : case E_V8HImode:
5420 : 13889 : if (TARGET_AVX512VL && TARGET_AVX512BW)
5421 : : gen = gen_avx512vl_vpermt2varv8hi3;
5422 : : break;
5423 : 745 : case E_V16HImode:
5424 : 745 : 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 : 45096 : case E_V4SImode:
5432 : 45096 : if (TARGET_AVX512VL)
5433 : : gen = gen_avx512vl_vpermt2varv4si3;
5434 : : break;
5435 : 1232 : case E_V8SImode:
5436 : 1232 : 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 : 10174 : case E_V4SFmode:
5444 : 10174 : if (TARGET_AVX512VL)
5445 : : {
5446 : : gen = gen_avx512vl_vpermt2varv4sf3;
5447 : : maskmode = V4SImode;
5448 : : }
5449 : : break;
5450 : 10047 : case E_V8SFmode:
5451 : 10047 : 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 : 343 : case E_V4DImode:
5469 : 343 : 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 : 2732 : case E_V4DFmode:
5484 : 2732 : 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 : 17064 : ix86_expand_sse_unpack (rtx dest, rtx src, bool unsigned_p, bool high_p)
5970 : : {
5971 : 17064 : machine_mode imode = GET_MODE (src);
5972 : 17064 : rtx tmp;
5973 : :
5974 : 17064 : 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 : 11088 : rtx (*unpack)(rtx, rtx, rtx);
6117 : :
6118 : 11088 : switch (imode)
6119 : : {
6120 : 3068 : case E_V16QImode:
6121 : 3068 : if (high_p)
6122 : : unpack = gen_vec_interleave_highv16qi;
6123 : : else
6124 : 1537 : unpack = gen_vec_interleave_lowv16qi;
6125 : : break;
6126 : 4658 : case E_V8HImode:
6127 : 4658 : if (high_p)
6128 : : unpack = gen_vec_interleave_highv8hi;
6129 : : else
6130 : 2329 : unpack = gen_vec_interleave_lowv8hi;
6131 : : break;
6132 : 2298 : case E_V4SImode:
6133 : 2298 : if (high_p)
6134 : : unpack = gen_vec_interleave_highv4si;
6135 : : else
6136 : 1149 : 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 : 11088 : if (unsigned_p)
6161 : 4760 : tmp = force_reg (imode, CONST0_RTX (imode));
6162 : : else
6163 : 6328 : tmp = ix86_expand_sse_cmp (gen_reg_rtx (imode), GT, CONST0_RTX (imode),
6164 : : src, pc_rtx, pc_rtx);
6165 : :
6166 : 11088 : rtx tmp2 = gen_reg_rtx (imode);
6167 : 11088 : emit_insn (unpack (tmp2, src, tmp));
6168 : 11088 : emit_move_insn (dest, gen_lowpart (GET_MODE (dest), tmp2));
6169 : : }
6170 : 17064 : }
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 : 4099180 : ix86_split_to_parts (rtx operand, rtx *parts, machine_mode mode)
6218 : : {
6219 : 4099180 : int size;
6220 : :
6221 : 4099180 : if (!TARGET_64BIT)
6222 : 1560894 : size = mode==XFmode ? 3 : GET_MODE_SIZE (mode) / 4;
6223 : : else
6224 : 6636284 : size = (GET_MODE_SIZE (mode) + 4) / 8;
6225 : :
6226 : 4099180 : gcc_assert (!REG_P (operand) || !MMX_REGNO_P (REGNO (operand)));
6227 : 4099180 : 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 : 4099180 : if (MEM_P (operand) && MEM_READONLY_P (operand))
6232 : 34884 : operand = avoid_constant_pool_reference (operand);
6233 : :
6234 : 4099180 : if (MEM_P (operand) && !offsettable_memref_p (operand))
6235 : : {
6236 : : /* The only non-offsetable memories we handle are pushes. */
6237 : 182287 : int ok = push_operand (operand, VOIDmode);
6238 : :
6239 : 182287 : gcc_assert (ok);
6240 : :
6241 : 182287 : operand = copy_rtx (operand);
6242 : 182287 : PUT_MODE (operand, word_mode);
6243 : 182287 : parts[0] = parts[1] = parts[2] = parts[3] = operand;
6244 : 182287 : return size;
6245 : : }
6246 : :
6247 : 3916893 : if (GET_CODE (operand) == CONST_VECTOR)
6248 : : {
6249 : 41306 : 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 : 41306 : operand = simplify_subreg (imode, operand, GET_MODE (operand), 0);
6254 : 41306 : gcc_assert (operand != NULL);
6255 : 41306 : mode = imode;
6256 : : }
6257 : :
6258 : 3916893 : if (!TARGET_64BIT)
6259 : : {
6260 : 623149 : if (mode == DImode)
6261 : 496349 : split_double_mode (mode, &operand, 1, &parts[0], &parts[1]);
6262 : : else
6263 : : {
6264 : 126800 : int i;
6265 : :
6266 : 126800 : if (REG_P (operand))
6267 : : {
6268 : 65749 : gcc_assert (reload_completed);
6269 : 197247 : for (i = 0; i < size; i++)
6270 : 131498 : parts[i] = gen_rtx_REG (SImode, REGNO (operand) + i);
6271 : : }
6272 : 61051 : else if (offsettable_memref_p (operand))
6273 : : {
6274 : 59729 : operand = adjust_address (operand, SImode, 0);
6275 : 59729 : parts[0] = operand;
6276 : 119924 : for (i = 1; i < size; i++)
6277 : 60195 : 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 : 3293744 : if (mode == TImode)
6314 : 3278700 : split_double_mode (mode, &operand, 1, &parts[0], &parts[1]);
6315 : 3293744 : if (mode == XFmode || mode == TFmode)
6316 : : {
6317 : 15044 : machine_mode upper_mode = mode==XFmode ? SImode : DImode;
6318 : 15044 : 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 : 13445 : else if (offsettable_memref_p (operand))
6325 : : {
6326 : 11481 : operand = adjust_address (operand, DImode, 0);
6327 : 11481 : parts[0] = operand;
6328 : 11481 : 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 : 2062572 : ix86_split_long_move (rtx operands[])
6364 : : {
6365 : 2062572 : rtx part[2][4];
6366 : 2062572 : int nparts, i, j;
6367 : 2062572 : int push = 0;
6368 : 2062572 : int collisions = 0;
6369 : 2062572 : machine_mode mode = GET_MODE (operands[0]);
6370 : 2062572 : 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 : 3734625 : 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 : 12982 : if (MEM_P (operands[1])
6381 : 12476 : && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
6382 : 13548 : && CONSTANT_POOL_ADDRESS_P (XEXP (operands[1], 0)))
6383 : 77 : operands[1] = get_pool_constant (XEXP (operands[1], 0));
6384 : 12982 : if (push_operand (operands[0], VOIDmode))
6385 : : {
6386 : 12982 : operands[0] = copy_rtx (operands[0]);
6387 : 12982 : PUT_MODE (operands[0], word_mode);
6388 : : }
6389 : : else
6390 : 0 : operands[0] = gen_lowpart (DImode, operands[0]);
6391 : 12982 : operands[1] = gen_lowpart (DImode, operands[1]);
6392 : 12982 : emit_move_insn (operands[0], operands[1]);
6393 : 12982 : return;
6394 : : }
6395 : :
6396 : : /* The only non-offsettable memory we handle is push. */
6397 : 2049590 : if (push_operand (operands[0], VOIDmode))
6398 : : push = 1;
6399 : : else
6400 : 1867303 : gcc_assert (!MEM_P (operands[0])
6401 : : || offsettable_memref_p (operands[0]));
6402 : :
6403 : 2049590 : nparts = ix86_split_to_parts (operands[1], part[1], GET_MODE (operands[0]));
6404 : 2049590 : 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 : 182287 : if (push && MEM_P (operands[1])
6408 : 2143341 : && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
6409 : : {
6410 : 54706 : rtx src_base = XEXP (part[1][nparts - 1], 0);
6411 : :
6412 : : /* Compensate for the stack decrement by 4. */
6413 : 54706 : if (!TARGET_64BIT && nparts == 3
6414 : 50184 : && 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 : 164395 : for (i = 0; i < nparts; i++)
6420 : 109689 : part[1][i] = change_address (part[1][i],
6421 : 109689 : 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 : 2049590 : if (REG_P (part[0][0]) && MEM_P (part[1][0]))
6427 : : {
6428 : : rtx tmp;
6429 : :
6430 : 2357205 : for (i = 0; i < nparts; i++)
6431 : : {
6432 : 1571470 : collisionparts[i]
6433 : 1571470 : = reg_overlap_mentioned_p (part[0][i], XEXP (part[1][0], 0));
6434 : 1571470 : if (collisionparts[i])
6435 : 16489 : collisions++;
6436 : : }
6437 : :
6438 : : /* Collision in the middle part can be handled by reordering. */
6439 : 785735 : 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 : 785735 : else if (collisions == 1
6445 : 785735 : && 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 : 785735 : 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 : 2049590 : if (push)
6495 : : {
6496 : 182287 : if (!TARGET_64BIT)
6497 : : {
6498 : 157889 : 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 : 157371 : 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 : 24398 : if (GET_MODE (part[1][1]) == SImode)
6517 : : {
6518 : 10375 : switch (GET_CODE (part[1][1]))
6519 : : {
6520 : 9907 : case MEM:
6521 : 9907 : part[1][1] = adjust_address (part[1][1], DImode, 0);
6522 : 9907 : 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 : 10375 : if (GET_MODE (part[1][0]) == SImode)
6533 : 0 : part[1][0] = part[1][1];
6534 : : }
6535 : : }
6536 : 182287 : emit_move_insn (part[0][1], part[1][1]);
6537 : 182287 : emit_move_insn (part[0][0], part[1][0]);
6538 : 182287 : return;
6539 : : }
6540 : :
6541 : : /* Choose correct order to not overwrite the source before it is copied. */
6542 : 1867303 : if ((REG_P (part[0][0])
6543 : 1025764 : && REG_P (part[1][1])
6544 : 81804 : && (REGNO (part[0][0]) == REGNO (part[1][1])
6545 : 66686 : || (nparts == 3
6546 : 0 : && REGNO (part[0][0]) == REGNO (part[1][2]))
6547 : 66686 : || (nparts == 4
6548 : 0 : && REGNO (part[0][0]) == REGNO (part[1][3]))))
6549 : 2877949 : || (collisions > 0
6550 : 16410 : && reg_overlap_mentioned_p (part[0][0], XEXP (part[1][0], 0))))
6551 : : {
6552 : 93759 : for (i = 0, j = nparts - 1; i < nparts; i++, j--)
6553 : : {
6554 : 62506 : operands[2 + i] = part[0][j];
6555 : 62506 : operands[6 + i] = part[1][j];
6556 : : }
6557 : : }
6558 : : else
6559 : : {
6560 : 5508223 : for (i = 0; i < nparts; i++)
6561 : : {
6562 : 3672173 : operands[2 + i] = part[0][i];
6563 : 3672173 : operands[6 + i] = part[1][i];
6564 : : }
6565 : : }
6566 : :
6567 : : /* Attempt to locally unCSE nonzero constants. */
6568 : 3734679 : for (j = 0; j < nparts - 1; j++)
6569 : 1867376 : if (CONST_INT_P (operands[6 + j])
6570 : 222024 : && operands[6 + j] != const0_rtx
6571 : 63716 : && REG_P (operands[2 + j]))
6572 : 114052 : for (i = j; i < nparts - 1; i++)
6573 : 57026 : if (CONST_INT_P (operands[7 + i])
6574 : 57026 : && INTVAL (operands[7 + i]) == INTVAL (operands[6 + j]))
6575 : 22133 : operands[7 + i] = operands[2 + j];
6576 : :
6577 : 5601982 : for (i = 0; i < nparts; i++)
6578 : 3734679 : 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 : 4476 : ix86_expand_ashl_const (rtx operand, int count, machine_mode mode)
6589 : : {
6590 : 4476 : if (count == 1
6591 : 4476 : || (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 : 4468 : rtx (*insn)(rtx, rtx, rtx);
6600 : :
6601 : 4468 : insn = mode == DImode ? gen_ashlsi3 : gen_ashldi3;
6602 : 4468 : emit_insn (insn (operand, operand, GEN_INT (count)));
6603 : : }
6604 : 4476 : }
6605 : :
6606 : : void
6607 : 10564 : ix86_split_ashl (rtx *operands, rtx scratch, machine_mode mode)
6608 : : {
6609 : 10564 : rtx (*gen_ashl3)(rtx, rtx, rtx);
6610 : 10564 : rtx (*gen_shld)(rtx, rtx, rtx);
6611 : 10564 : int half_width = GET_MODE_BITSIZE (mode) >> 1;
6612 : 10564 : machine_mode half_mode;
6613 : :
6614 : 10564 : rtx low[2], high[2];
6615 : 10564 : int count;
6616 : :
6617 : 10564 : if (CONST_INT_P (operands[2]))
6618 : : {
6619 : 8863 : split_double_mode (mode, operands, 2, low, high);
6620 : 8863 : count = INTVAL (operands[2]) & (GET_MODE_BITSIZE (mode) - 1);
6621 : :
6622 : 8863 : 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 : 6390 : else if (count == 1)
6631 : : {
6632 : 2065 : if (!rtx_equal_p (operands[0], operands[1]))
6633 : 0 : emit_move_insn (operands[0], operands[1]);
6634 : 2065 : rtx x3 = gen_rtx_REG (CCCmode, FLAGS_REG);
6635 : 2065 : rtx x4 = gen_rtx_LTU (mode, x3, const0_rtx);
6636 : 2065 : half_mode = mode == DImode ? SImode : DImode;
6637 : 2065 : emit_insn (gen_add3_cc_overflow_1 (half_mode, low[0],
6638 : : low[0], low[0]));
6639 : 2065 : emit_insn (gen_add3_carry (half_mode, high[0], high[0], high[0],
6640 : : x3, x4));
6641 : : }
6642 : : else
6643 : : {
6644 : 4325 : gen_shld = mode == DImode ? gen_x86_shld : gen_x86_64_shld;
6645 : :
6646 : 4325 : if (!rtx_equal_p (operands[0], operands[1]))
6647 : 0 : emit_move_insn (operands[0], operands[1]);
6648 : :
6649 : 4325 : emit_insn (gen_shld (high[0], low[0], GEN_INT (count)));
6650 : 4325 : ix86_expand_ashl_const (low[0], count, mode);
6651 : : }
6652 : 9132 : 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 : 269 : if (ANY_QI_REG_P (low[0]) && ANY_QI_REG_P (high[0]))
6665 : : {
6666 : 156 : rtx s, d, flags = gen_rtx_REG (CCZmode, FLAGS_REG);
6667 : :
6668 : 156 : ix86_expand_clear (low[0]);
6669 : 156 : ix86_expand_clear (high[0]);
6670 : 156 : emit_insn (gen_testqi_ccz_1 (operands[2], GEN_INT (half_width)));
6671 : :
6672 : 156 : d = gen_lowpart (QImode, low[0]);
6673 : 156 : d = gen_rtx_STRICT_LOW_PART (VOIDmode, d);
6674 : 156 : s = gen_rtx_EQ (QImode, flags, const0_rtx);
6675 : 156 : emit_insn (gen_rtx_SET (d, s));
6676 : :
6677 : 156 : d = gen_lowpart (QImode, high[0]);
6678 : 156 : d = gen_rtx_STRICT_LOW_PART (VOIDmode, d);
6679 : 156 : s = gen_rtx_NE (QImode, flags, const0_rtx);
6680 : 156 : 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 : 113 : rtx (*gen_lshr3)(rtx, rtx, rtx);
6691 : 113 : rtx (*gen_and3)(rtx, rtx, rtx);
6692 : 113 : rtx (*gen_xor3)(rtx, rtx, rtx);
6693 : 113 : HOST_WIDE_INT bits;
6694 : 113 : rtx x;
6695 : :
6696 : 113 : 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 : 113 : if (TARGET_PARTIAL_REG_STALL && !optimize_insn_for_size_p ())
6712 : 0 : x = gen_rtx_ZERO_EXTEND (half_mode, operands[2]);
6713 : : else
6714 : 113 : x = gen_lowpart (half_mode, operands[2]);
6715 : 113 : emit_insn (gen_rtx_SET (high[0], x));
6716 : :
6717 : 113 : emit_insn (gen_lshr3 (high[0], high[0], GEN_INT (bits)));
6718 : 113 : emit_insn (gen_and3 (high[0], high[0], const1_rtx));
6719 : 113 : emit_move_insn (low[0], high[0]);
6720 : 113 : emit_insn (gen_xor3 (low[0], low[0], const1_rtx));
6721 : : }
6722 : :
6723 : 269 : emit_insn (gen_ashl3 (low[0], low[0], operands[2]));
6724 : 269 : emit_insn (gen_ashl3 (high[0], high[0], operands[2]));
6725 : 269 : return;
6726 : : }
6727 : :
6728 : 1432 : 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 : 120 : emit_move_insn (low[0], constm1_rtx);
6733 : 120 : if (optimize_insn_for_size_p ())
6734 : 6 : emit_move_insn (high[0], low[0]);
6735 : : else
6736 : 114 : emit_move_insn (high[0], constm1_rtx);
6737 : : }
6738 : : else
6739 : : {
6740 : 1312 : gen_shld = mode == DImode ? gen_x86_shld : gen_x86_64_shld;
6741 : :
6742 : 1312 : if (!rtx_equal_p (operands[0], operands[1]))
6743 : 0 : emit_move_insn (operands[0], operands[1]);
6744 : :
6745 : 1312 : split_double_mode (mode, operands, 1, low, high);
6746 : 1312 : emit_insn (gen_shld (high[0], low[0], operands[2]));
6747 : : }
6748 : :
6749 : 1432 : emit_insn (gen_ashl3 (low[0], low[0], operands[2]));
6750 : :
6751 : 1432 : if (TARGET_CMOVE && scratch)
6752 : : {
6753 : 968 : ix86_expand_clear (scratch);
6754 : 968 : emit_insn (gen_x86_shift_adj_1
6755 : : (half_mode, high[0], low[0], operands[2], scratch));
6756 : : }
6757 : : else
6758 : 464 : 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 : 14900 : ix86_split_lshr (rtx *operands, rtx scratch, machine_mode mode)
6854 : : {
6855 : 7538 : rtx (*gen_lshr3)(rtx, rtx, rtx)
6856 : 14900 : = mode == DImode ? gen_lshrsi3 : gen_lshrdi3;
6857 : 14900 : rtx (*gen_shrd)(rtx, rtx, rtx);
6858 : 14900 : int half_width = GET_MODE_BITSIZE (mode) >> 1;
6859 : :
6860 : 14900 : rtx low[2], high[2];
6861 : 14900 : int count;
6862 : :
6863 : 14900 : if (CONST_INT_P (operands[2]))
6864 : : {
6865 : 13507 : split_double_mode (mode, operands, 2, low, high);
6866 : 13507 : count = INTVAL (operands[2]) & (GET_MODE_BITSIZE (mode) - 1);
6867 : :
6868 : 13507 : 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 : 5042 : else if (count == 1
6878 : 904 : && (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 : 5041 : gen_shrd = mode == DImode ? gen_x86_shrd : gen_x86_64_shrd;
6896 : :
6897 : 5041 : if (!rtx_equal_p (operands[0], operands[1]))
6898 : 0 : emit_move_insn (operands[0], operands[1]);
6899 : :
6900 : 5041 : emit_insn (gen_shrd (low[0], high[0], GEN_INT (count)));
6901 : 5041 : 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 : 1119 : ix86_expand_clear (scratch);
6922 : 1119 : emit_insn (gen_x86_shift_adj_1
6923 : : (half_mode, low[0], high[0], operands[2], scratch));
6924 : : }
6925 : : else
6926 : 274 : emit_insn (gen_x86_shift_adj_2
6927 : : (half_mode, low[0], high[0], operands[2]));
6928 : : }
6929 : 14900 : }
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 : 39302 : ix86_replace_reg_with_reg (rtx x, rtx from, rtx to)
7846 : : {
7847 : 39302 : gcc_checking_assert (REG_P (from)
7848 : : && REG_P (to)
7849 : : && GET_MODE (from) == GET_MODE (to));
7850 : 39302 : if (!reg_overlap_mentioned_p (from, x))
7851 : : return x;
7852 : 42 : rtx ret = copy_rtx (x);
7853 : 42 : subrtx_ptr_iterator::array_type array;
7854 : 198 : FOR_EACH_SUBRTX_PTR (iter, array, &ret, NONCONST)
7855 : : {
7856 : 156 : rtx *loc = *iter;
7857 : 156 : x = *loc;
7858 : 156 : if (REG_P (x) && REGNO (x) == REGNO (from))
7859 : : {
7860 : 42 : if (x == from)
7861 : 42 : *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 : 42 : return ret;
7870 : 42 : }
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 : 20736 : counter_mode (rtx count_exp)
7877 : : {
7878 : 7804 : if (GET_MODE (count_exp) != VOIDmode)
7879 : 18701 : return GET_MODE (count_exp);
7880 : 2035 : 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 : 10680 : 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 : 10680 : rtx_code_label *out_label, *top_label;
7903 : 10680 : rtx iter, tmp;
7904 : 10680 : machine_mode iter_mode = counter_mode (count);
7905 : 10680 : int piece_size_n = GET_MODE_SIZE (mode) * unroll;
7906 : 10680 : rtx piece_size = GEN_INT (piece_size_n);
7907 : 21360 : rtx piece_size_mask = GEN_INT (~((GET_MODE_SIZE (mode) * unroll) - 1));
7908 : 10680 : rtx size;
7909 : 10680 : int i;
7910 : :
7911 : 10680 : top_label = gen_label_rtx ();
7912 : 10680 : out_label = gen_label_rtx ();
7913 : 10680 : iter = gen_reg_rtx (iter_mode);
7914 : :
7915 : 10680 : size = expand_simple_binop (iter_mode, AND, count, piece_size_mask,
7916 : : NULL, 1, OPTAB_DIRECT);
7917 : : /* Those two should combine. */
7918 : 10680 : if (piece_size == const1_rtx)
7919 : : {
7920 : 2745 : emit_cmp_and_jump_insns (size, const0_rtx, EQ, NULL_RTX, iter_mode,
7921 : : true, out_label);
7922 : 2745 : predict_jump (REG_BR_PROB_BASE * 10 / 100);
7923 : : }
7924 : 10680 : emit_move_insn (iter, const0_rtx);
7925 : :
7926 : 10680 : emit_label (top_label);
7927 : :
7928 : 11195 : tmp = convert_modes (Pmode, iter_mode, iter, true);
7929 : :
7930 : : /* This assert could be relaxed - in this case we'll need to compute
7931 : : smallest power of two, containing in PIECE_SIZE_N and pass it to
7932 : : offset_address. */
7933 : 10680 : gcc_assert ((piece_size_n & (piece_size_n - 1)) == 0);
7934 : 10680 : destmem = offset_address (destmem, tmp, piece_size_n);
7935 : 10680 : destmem = adjust_address (destmem, mode, 0);
7936 : :
7937 : 10680 : if (!issetmem)
7938 : : {
7939 : 8968 : srcmem = offset_address (srcmem, copy_rtx (tmp), piece_size_n);
7940 : 8968 : srcmem = adjust_address (srcmem, mode, 0);
7941 : :
7942 : : /* When unrolling for chips that reorder memory reads and writes,
7943 : : we can save registers by using single temporary.
7944 : : Also using 4 temporaries is overkill in 32bit mode. */
7945 : 8968 : if (!TARGET_64BIT && 0)
7946 : : {
7947 : : for (i = 0; i < unroll; i++)
7948 : : {
7949 : : if (i)
7950 : : {
7951 : : destmem = adjust_address (copy_rtx (destmem), mode,
7952 : : GET_MODE_SIZE (mode));
7953 : : srcmem = adjust_address (copy_rtx (srcmem), mode,
7954 : : GET_MODE_SIZE (mode));
7955 : : }
7956 : : emit_move_insn (destmem, srcmem);
7957 : : }
7958 : : }
7959 : : else
7960 : : {
7961 : 8968 : rtx tmpreg[4];
7962 : 8968 : gcc_assert (unroll <= 4);
7963 : 17975 : for (i = 0; i < unroll; i++)
7964 : : {
7965 : 9007 : tmpreg[i] = gen_reg_rtx (mode);
7966 : 9007 : if (i)
7967 : 78 : srcmem = adjust_address (copy_rtx (srcmem), mode,
7968 : : GET_MODE_SIZE (mode));
7969 : 9007 : emit_move_insn (tmpreg[i], srcmem);
7970 : : }
7971 : 17975 : for (i = 0; i < unroll; i++)
7972 : : {
7973 : 9007 : if (i)
7974 : 78 : destmem = adjust_address (copy_rtx (destmem), mode,
7975 : : GET_MODE_SIZE (mode));
7976 : 9007 : emit_move_insn (destmem, tmpreg[i]);
7977 : : }
7978 : : }
7979 : : }
7980 : : else
7981 : 3445 : for (i = 0; i < unroll; i++)
7982 : : {
7983 : 1733 : if (i)
7984 : 42 : destmem = adjust_address (copy_rtx (destmem), mode,
7985 : : GET_MODE_SIZE (mode));
7986 : 1733 : emit_move_insn (destmem, value);
7987 : : }
7988 : :
7989 : 10680 : tmp = expand_simple_binop (iter_mode, PLUS, iter, piece_size, iter,
7990 : : true, OPTAB_LIB_WIDEN);
7991 : 10680 : if (tmp != iter)
7992 : 0 : emit_move_insn (iter, tmp);
7993 : :
7994 : 10680 : emit_cmp_and_jump_insns (iter, size, LT, NULL_RTX, iter_mode,
7995 : : true, top_label);
7996 : 10680 : if (expected_size != -1)
7997 : : {
7998 : 344 : expected_size /= GET_MODE_SIZE (mode) * unroll;
7999 : 344 : if (expected_size == 0)
8000 : 1 : predict_jump (0);
8001 : 343 : else if (expected_size > REG_BR_PROB_BASE)
8002 : 0 : predict_jump (REG_BR_PROB_BASE - 1);
8003 : : else
8004 : 343 : predict_jump (REG_BR_PROB_BASE - (REG_BR_PROB_BASE + expected_size / 2)
8005 : 343 : / expected_size);
8006 : : }
8007 : : else
8008 : 10336 : predict_jump (REG_BR_PROB_BASE * 80 / 100);
8009 : 10680 : iter = ix86_zero_extend_to_Pmode (iter);
8010 : 11195 : tmp = expand_simple_binop (Pmode, PLUS, destptr, iter, destptr,
8011 : : true, OPTAB_LIB_WIDEN);
8012 : 10680 : if (tmp != destptr)
8013 : 0 : emit_move_insn (destptr, tmp);
8014 : 10680 : if (!issetmem)
8015 : : {
8016 : 9363 : tmp = expand_simple_binop (Pmode, PLUS, srcptr, iter, srcptr,
8017 : : true, OPTAB_LIB_WIDEN);
8018 : 8968 : if (tmp != srcptr)
8019 : 0 : emit_move_insn (srcptr, tmp);
8020 : : }
8021 : 10680 : emit_label (out_label);
8022 : 10680 : }
8023 : :
8024 : : /* Divide COUNTREG by SCALE. */
8025 : : static rtx
8026 : 47294 : scale_counter (rtx countreg, int scale)
8027 : : {
8028 : 47294 : rtx sc;
8029 : :
8030 : 47294 : if (scale == 1)
8031 : : return countreg;
8032 : 42638 : if (CONST_INT_P (countreg))
8033 : 39050 : return GEN_INT (INTVAL (countreg) / scale);
8034 : 3588 : gcc_assert (REG_P (countreg));
8035 : :
8036 : 10764 : sc = expand_simple_binop (GET_MODE (countreg), LSHIFTRT, countreg,
8037 : 7176 : GEN_INT (exact_log2 (scale)),
8038 : : NULL, 1, OPTAB_DIRECT);
8039 : 3588 : return sc;
8040 : : }
8041 : :
8042 : : /* Output "rep; mov" or "rep; stos" instruction depending on ISSETMEM argument.
8043 : : When ISSETMEM is true, arguments SRCMEM and SRCPTR are ignored.
8044 : : When ISSETMEM is false, arguments VALUE and ORIG_VALUE are ignored.
8045 : : For setmem case, VALUE is a promoted to a wider size ORIG_VALUE.
8046 : : ORIG_VALUE is the original value passed to memset to fill the memory with.
8047 : : Other arguments have same meaning as for previous function. */
8048 : :
8049 : : static void
8050 : 47294 : expand_set_or_cpymem_via_rep (rtx destmem, rtx srcmem,
8051 : : rtx destptr, rtx srcptr, rtx value, rtx orig_value,
8052 : : rtx count,
8053 : : machine_mode mode, bool issetmem)
8054 : : {
8055 : 47294 : rtx destexp;
8056 : 47294 : rtx srcexp;
8057 : 47294 : rtx countreg;
8058 : 47294 : HOST_WIDE_INT rounded_count;
8059 : :
8060 : : /* If possible, it is shorter to use rep movs.
8061 : : TODO: Maybe it is better to move this logic to decide_alg. */
8062 : 47294 : if (mode == QImode && CONST_INT_P (count) && !(INTVAL (count) & 3)
8063 : 238 : && !TARGET_PREFER_KNOWN_REP_MOVSB_STOSB
8064 : 234 : && (!issetmem || orig_value == const0_rtx))
8065 : 47294 : mode = SImode;
8066 : :
8067 : 47294 : if (destptr != XEXP (destmem, 0) || GET_MODE (destmem) != BLKmode)
8068 : 44630 : destmem = adjust_automodify_address_nv (destmem, BLKmode, destptr, 0);
8069 : :
8070 : 94588 : countreg = ix86_zero_extend_to_Pmode (scale_counter (count,
8071 : 47294 : GET_MODE_SIZE (mode)));
8072 : 47294 : if (mode != QImode)
8073 : : {
8074 : 132997 : destexp = gen_rtx_ASHIFT (Pmode, countreg,
8075 : : GEN_INT (exact_log2 (GET_MODE_SIZE (mode))));
8076 : 47721 : destexp = gen_rtx_PLUS (Pmode, destexp, destptr);
8077 : : }
8078 : : else
8079 : 4679 : destexp = gen_rtx_PLUS (Pmode, destptr, countreg);
8080 : 47294 : if ((!issetmem || orig_value == const0_rtx) && CONST_INT_P (count))
8081 : : {
8082 : 39507 : rounded_count
8083 : 39507 : = ROUND_DOWN (INTVAL (count), (HOST_WIDE_INT) GET_MODE_SIZE (mode));
8084 : 39507 : destmem = shallow_copy_rtx (destmem);
8085 : 39507 : set_mem_size (destmem, rounded_count);
8086 : : }
8087 : 7793 : else if (MEM_SIZE_KNOWN_P (destmem))
8088 : 533 : clear_mem_size (destmem);
8089 : :
8090 : 47294 : if (issetmem)
8091 : : {
8092 : 21750 : value = force_reg (mode, gen_lowpart (mode, value));
8093 : 21750 : emit_insn (gen_rep_stos (destptr, countreg, destmem, value, destexp));
8094 : : }
8095 : : else
8096 : : {
8097 : 25544 : if (srcptr != XEXP (srcmem, 0) || GET_MODE (srcmem) != BLKmode)
8098 : 24541 : srcmem = adjust_automodify_address_nv (srcmem, BLKmode, srcptr, 0);
8099 : 25544 : if (mode != QImode)
8100 : : {
8101 : 68735 : srcexp = gen_rtx_ASHIFT (Pmode, countreg,
8102 : : GEN_INT (exact_log2 (GET_MODE_SIZE (mode))));
8103 : 24375 : srcexp = gen_rtx_PLUS (Pmode, srcexp, srcptr);
8104 : : }
8105 : : else
8106 : 3383 : srcexp = gen_rtx_PLUS (Pmode, srcptr, countreg);
8107 : 25544 : if (CONST_INT_P (count))
8108 : : {
8109 : 21480 : rounded_count
8110 : 21480 : = ROUND_DOWN (INTVAL (count), (HOST_WIDE_INT) GET_MODE_SIZE (mode));
8111 : 21480 : srcmem = shallow_copy_rtx (srcmem);
8112 : 21480 : set_mem_size (srcmem, rounded_count);
8113 : : }
8114 : : else
8115 : : {
8116 : 4987 : if (MEM_SIZE_KNOWN_P (srcmem))
8117 : 0 : clear_mem_size (srcmem);
8118 : : }
8119 : 25544 : emit_insn (gen_rep_mov (destptr, destmem, srcptr, srcmem, countreg,
8120 : : destexp, srcexp));
8121 : : }
8122 : 47294 : }
8123 : :
8124 : : /* This function emits moves to copy SIZE_TO_MOVE bytes from SRCMEM to
8125 : : DESTMEM.
8126 : : SRC is passed by pointer to be updated on return.
8127 : : Return value is updated DST. */
8128 : : static rtx
8129 : 3465 : emit_memmov (rtx destmem, rtx *srcmem, rtx destptr, rtx srcptr,
8130 : : HOST_WIDE_INT size_to_move)
8131 : : {
8132 : 3465 : rtx dst = destmem, src = *srcmem, tempreg;
8133 : 3465 : enum insn_code code;
8134 : 3465 : machine_mode move_mode;
8135 : 3465 : int piece_size, i;
8136 : :
8137 : : /* Find the widest mode in which we could perform moves.
8138 : : Start with the biggest power of 2 less than SIZE_TO_MOVE and half
8139 : : it until move of such size is supported. */
8140 : 3465 : piece_size = 1 << floor_log2 (size_to_move);
8141 : 6930 : while (!int_mode_for_size (piece_size * BITS_PER_UNIT, 0).exists (&move_mode)
8142 : 6930 : || (code = optab_handler (mov_optab, move_mode)) == CODE_FOR_nothing)
8143 : : {
8144 : 0 : gcc_assert (piece_size > 1);
8145 : 0 : piece_size >>= 1;
8146 : : }
8147 : :
8148 : : /* Find the corresponding vector mode with the same size as MOVE_MODE.
8149 : : MOVE_MODE is an integer mode at the moment (SI, DI, TI, etc.). */
8150 : 10395 : if (GET_MODE_SIZE (move_mode) > GET_MODE_SIZE (word_mode))
8151 : : {
8152 : 4 : int nunits = GET_MODE_SIZE (move_mode) / GET_MODE_SIZE (word_mode);
8153 : 4 : if (!mode_for_vector (word_mode, nunits).exists (&move_mode)
8154 : 2 : || (code = optab_handler (mov_optab, move_mode)) == CODE_FOR_nothing)
8155 : : {
8156 : 0 : move_mode = word_mode;
8157 : 0 : piece_size = GET_MODE_SIZE (move_mode);
8158 : 0 : code = optab_handler (mov_optab, move_mode);
8159 : : }
8160 : : }
8161 : 3465 : gcc_assert (code != CODE_FOR_nothing);
8162 : :
8163 : 3465 : dst = adjust_automodify_address_nv (dst, move_mode, destptr, 0);
8164 : 3465 : src = adjust_automodify_address_nv (src, move_mode, srcptr, 0);
8165 : :
8166 : : /* Emit moves. We'll need SIZE_TO_MOVE/PIECE_SIZES moves. */
8167 : 3465 : gcc_assert (size_to_move % piece_size == 0);
8168 : :
8169 : 6930 : for (i = 0; i < size_to_move; i += piece_size)
8170 : : {
8171 : : /* We move from memory to memory, so we'll need to do it via
8172 : : a temporary register. */
8173 : 3465 : tempreg = gen_reg_rtx (move_mode);
8174 : 3465 : emit_insn (GEN_FCN (code) (tempreg, src));
8175 : 3465 : emit_insn (GEN_FCN (code) (dst, tempreg));
8176 : :
8177 : 6930 : emit_move_insn (destptr,
8178 : 3465 : plus_constant (Pmode, copy_rtx (destptr), piece_size));
8179 : 6930 : emit_move_insn (srcptr,
8180 : 3465 : plus_constant (Pmode, copy_rtx (srcptr), piece_size));
8181 : :
8182 : 3465 : dst = adjust_automodify_address_nv (dst, move_mode, destptr,
8183 : : piece_size);
8184 : 3465 : src = adjust_automodify_address_nv (src, move_mode, srcptr,
8185 : : piece_size);
8186 : : }
8187 : :
8188 : : /* Update DST and SRC rtx. */
8189 : 3465 : *srcmem = src;
8190 : 3465 : return dst;
8191 : : }
8192 : :
8193 : : /* Helper function for the string operations below. Dest VARIABLE whether
8194 : : it is aligned to VALUE bytes. If true, jump to the label. */
8195 : :
8196 : : static rtx_code_label *
8197 : 19416 : ix86_expand_aligntest (rtx variable, int value, bool epilogue)
8198 : : {
8199 : 19416 : rtx_code_label *label = gen_label_rtx ();
8200 : 19416 : rtx tmpcount = gen_reg_rtx (GET_MODE (variable));
8201 : 19416 : if (GET_MODE (variable) == DImode)
8202 : 438 : emit_insn (gen_anddi3 (tmpcount, variable, GEN_INT (value)));
8203 : : else
8204 : 18978 : emit_insn (gen_andsi3 (tmpcount, variable, GEN_INT (value)));
8205 : 19416 : emit_cmp_and_jump_insns (tmpcount, const0_rtx, EQ, 0, GET_MODE (variable),
8206 : : 1, label);
8207 : 19416 : if (epilogue)
8208 : 8922 : predict_jump (REG_BR_PROB_BASE * 50 / 100);
8209 : : else
8210 : 10494 : predict_jump (REG_BR_PROB_BASE * 90 / 100);
8211 : 19416 : return label;
8212 : : }
8213 : :
8214 : :
8215 : : /* Output code to copy at most count & (max_size - 1) bytes from SRC to DEST. */
8216 : :
8217 : : static void
8218 : 23245 : expand_cpymem_epilogue (rtx destmem, rtx srcmem,
8219 : : rtx destptr, rtx srcptr, rtx count, int max_size)
8220 : : {
8221 : 23245 : rtx src, dest;
8222 : 23245 : if (CONST_INT_P (count))
8223 : : {
8224 : 21028 : HOST_WIDE_INT countval = INTVAL (count);
8225 : 21028 : HOST_WIDE_INT epilogue_size = countval % max_size;
8226 : 21028 : int i;
8227 : :
8228 : : /* For now MAX_SIZE should be a power of 2. This assert could be
8229 : : relaxed, but it'll require a bit more complicated epilogue
8230 : : expanding. */
8231 : 21028 : gcc_assert ((max_size & (max_size - 1)) == 0);
8232 : 98374 : for (i = max_size; i >= 1; i >>= 1)
8233 : : {
8234 : 77346 : if (epilogue_size & i)
8235 : 3446 : destmem = emit_memmov (destmem, &srcmem, destptr, srcptr, i);
8236 : : }
8237 : : return;
8238 : : }
8239 : 2217 : if (max_size > 8)
8240 : : {
8241 : 5 : count = expand_simple_binop (GET_MODE (count), AND, count, GEN_INT (max_size - 1),
8242 : : count, 1, OPTAB_DIRECT);
8243 : 5 : expand_set_or_cpymem_via_loop (destmem, srcmem, destptr, srcptr, NULL,
8244 : : count, QImode, 1, 4, false);
8245 : 5 : return;
8246 : : }
8247 : :
8248 : : /* When there are stringops, we can cheaply increase dest and src pointers.
8249 : : Otherwise we save code size by maintaining offset (zero is readily
8250 : : available from preceding rep operation) and using x86 addressing modes.
8251 : : */
8252 : 2212 : if (TARGET_SINGLE_STRINGOP)
8253 : : {
8254 : 0 : if (max_size > 4)
8255 : : {
8256 : 0 : rtx_code_label *label = ix86_expand_aligntest (count, 4, true);
8257 : 0 : src = change_address (srcmem, SImode, srcptr);
8258 : 0 : dest = change_address (destmem, SImode, destptr);
8259 : 0 : emit_insn (gen_strmov (destptr, dest, srcptr, src));
8260 : 0 : emit_label (label);
8261 : 0 : LABEL_NUSES (label) = 1;
8262 : : }
8263 : 0 : if (max_size > 2)
8264 : : {
8265 : 0 : rtx_code_label *label = ix86_expand_aligntest (count, 2, true);
8266 : 0 : src = change_address (srcmem, HImode, srcptr);
8267 : 0 : dest = change_address (destmem, HImode, 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 > 1)
8273 : : {
8274 : 0 : rtx_code_label *label = ix86_expand_aligntest (count, 1, true);
8275 : 0 : src = change_address (srcmem, QImode, srcptr);
8276 : 0 : dest = change_address (destmem, QImode, destptr);
8277 : 0 : emit_insn (gen_strmov (destptr, dest, srcptr, src));
8278 : 0 : emit_label (label);
8279 : 0 : LABEL_NUSES (label) = 1;
8280 : : }
8281 : : }
8282 : : else
8283 : : {
8284 : 2289 : rtx offset = force_reg (Pmode, const0_rtx);
8285 : 2212 : rtx tmp;
8286 : :
8287 : 2212 : if (max_size > 4)
8288 : : {
8289 : 2135 : rtx_code_label *label = ix86_expand_aligntest (count, 4, true);
8290 : 2135 : src = change_address (srcmem, SImode, srcptr);
8291 : 2135 : dest = change_address (destmem, SImode, destptr);
8292 : 2135 : emit_move_insn (dest, src);
8293 : 2135 : tmp = expand_simple_binop (Pmode, PLUS, offset, GEN_INT (4), NULL,
8294 : : true, OPTAB_LIB_WIDEN);
8295 : 2135 : if (tmp != offset)
8296 : 2135 : emit_move_insn (offset, tmp);
8297 : 2135 : emit_label (label);
8298 : 2135 : LABEL_NUSES (label) = 1;
8299 : : }
8300 : 2212 : if (max_size > 2)
8301 : : {
8302 : 2212 : rtx_code_label *label = ix86_expand_aligntest (count, 2, true);
8303 : 2289 : tmp = gen_rtx_PLUS (Pmode, srcptr, offset);
8304 : 2212 : src = change_address (srcmem, HImode, tmp);
8305 : 2289 : tmp = gen_rtx_PLUS (Pmode, destptr, offset);
8306 : 2212 : dest = change_address (destmem, HImode, tmp);
8307 : 2212 : emit_move_insn (dest, src);
8308 : 2289 : tmp = expand_simple_binop (Pmode, PLUS, offset, GEN_INT (2), tmp,
8309 : : true, OPTAB_LIB_WIDEN);
8310 : 2212 : if (tmp != offset)
8311 : 2212 : emit_move_insn (offset, tmp);
8312 : 2212 : emit_label (label);
8313 : 2212 : LABEL_NUSES (label) = 1;
8314 : : }
8315 : 2212 : if (max_size > 1)
8316 : : {
8317 : 2212 : rtx_code_label *label = ix86_expand_aligntest (count, 1, true);
8318 : 2289 : tmp = gen_rtx_PLUS (Pmode, srcptr, offset);
8319 : 2212 : src = change_address (srcmem, QImode, tmp);
8320 : 2289 : tmp = gen_rtx_PLUS (Pmode, destptr, offset);
8321 : 2212 : dest = change_address (destmem, QImode, tmp);
8322 : 2212 : emit_move_insn (dest, src);
8323 : 2212 : emit_label (label);
8324 : 2212 : LABEL_NUSES (label) = 1;
8325 : : }
8326 : : }
8327 : : }
8328 : :
8329 : : /* This function emits moves to fill SIZE_TO_MOVE bytes starting from DESTMEM
8330 : : with value PROMOTED_VAL.
8331 : : SRC is passed by pointer to be updated on return.
8332 : : Return value is updated DST. */
8333 : : static rtx
8334 : 5526 : emit_memset (rtx destmem, rtx destptr, rtx promoted_val,
8335 : : HOST_WIDE_INT size_to_move)
8336 : : {
8337 : 5526 : rtx dst = destmem;
8338 : 5526 : enum insn_code code;
8339 : 5526 : machine_mode move_mode;
8340 : 5526 : int piece_size, i;
8341 : :
8342 : : /* Find the widest mode in which we could perform moves.
8343 : : Start with the biggest power of 2 less than SIZE_TO_MOVE and half
8344 : : it until move of such size is supported. */
8345 : 5526 : move_mode = GET_MODE (promoted_val);
8346 : 5526 : if (move_mode == VOIDmode)
8347 : 0 : move_mode = QImode;
8348 : 11052 : if (size_to_move < GET_MODE_SIZE (move_mode))
8349 : : {
8350 : 5518 : unsigned int move_bits = size_to_move * BITS_PER_UNIT;
8351 : 5518 : move_mode = int_mode_for_size (move_bits, 0).require ();
8352 : 5518 : promoted_val = gen_lowpart (move_mode, promoted_val);
8353 : : }
8354 : 5526 : piece_size = GET_MODE_SIZE (move_mode);
8355 : 5526 : code = optab_handler (mov_optab, move_mode);
8356 : 5526 : gcc_assert (code != CODE_FOR_nothing && promoted_val != NULL_RTX);
8357 : :
8358 : 5526 : dst = adjust_automodify_address_nv (dst, move_mode, destptr, 0);
8359 : :
8360 : : /* Emit moves. We'll need SIZE_TO_MOVE/PIECE_SIZES moves. */
8361 : 5526 : gcc_assert (size_to_move % piece_size == 0);
8362 : :
8363 : 11055 : for (i = 0; i < size_to_move; i += piece_size)
8364 : : {
8365 : 11058 : if (piece_size <= GET_MODE_SIZE (word_mode))
8366 : : {
8367 : 5520 : emit_insn (gen_strset (destptr, dst, promoted_val));
8368 : 5520 : dst = adjust_automodify_address_nv (dst, move_mode, destptr,
8369 : : piece_size);
8370 : 5520 : continue;
8371 : : }
8372 : :
8373 : 9 : emit_insn (GEN_FCN (code) (dst, promoted_val));
8374 : :
8375 : 18 : emit_move_insn (destptr,
8376 : 9 : plus_constant (Pmode, copy_rtx (destptr), piece_size));
8377 : :
8378 : 9 : dst = adjust_automodify_address_nv (dst, move_mode, destptr,
8379 : : piece_size);
8380 : : }
8381 : :
8382 : : /* Update DST rtx. */
8383 : 5526 : return dst;
8384 : : }
8385 : : /* Output code to set at most count & (max_size - 1) bytes starting by DEST. */
8386 : : static void
8387 : 277 : expand_setmem_epilogue_via_loop (rtx destmem, rtx destptr, rtx value,
8388 : : rtx count, int max_size)
8389 : : {
8390 : 554 : count = expand_simple_binop (counter_mode (count), AND, count,
8391 : 277 : GEN_INT (max_size - 1), count, 1, OPTAB_DIRECT);
8392 : 277 : expand_set_or_cpymem_via_loop (destmem, NULL, destptr, NULL,
8393 : 277 : gen_lowpart (QImode, value), count, QImode,
8394 : : 1, max_size / 2, true);
8395 : 277 : }
8396 : :
8397 : : /* Output code to set at most count & (max_size - 1) bytes starting by DEST. */
8398 : : static void
8399 : 18914 : expand_setmem_epilogue (rtx destmem, rtx destptr, rtx value, rtx vec_value,
8400 : : rtx count, int max_size)
8401 : : {
8402 : 18914 : rtx dest;
8403 : :
8404 : 18914 : if (CONST_INT_P (count))
8405 : : {
8406 : 18069 : HOST_WIDE_INT countval = INTVAL (count);
8407 : 18069 : HOST_WIDE_INT epilogue_size = countval % max_size;
8408 : 18069 : int i;
8409 : :
8410 : : /* For now MAX_SIZE should be a power of 2. This assert could be
8411 : : relaxed, but it'll require a bit more complicated epilogue
8412 : : expanding. */
8413 : 18069 : gcc_assert ((max_size & (max_size - 1)) == 0);
8414 : 85918 : for (i = max_size; i >= 1; i >>= 1)
8415 : : {
8416 : 67849 : if (epilogue_size & i)
8417 : : {
8418 : 5531 : if (vec_value && i > GET_MODE_SIZE (GET_MODE (value)))
8419 : 5 : destmem = emit_memset (destmem, destptr, vec_value, i);
8420 : : else
8421 : 5515 : destmem = emit_memset (destmem, destptr, value, i);
8422 : : }
8423 : : }
8424 : : return;
8425 : : }
8426 : 845 : if (max_size > 32)
8427 : : {
8428 : 2 : expand_setmem_epilogue_via_loop (destmem, destptr, value, count, max_size);
8429 : 2 : return;
8430 : : }
8431 : 843 : if (max_size > 16)
8432 : : {
8433 : 0 : rtx_code_label *label = ix86_expand_aligntest (count, 16, true);
8434 : 0 : if (TARGET_64BIT)
8435 : : {
8436 : 0 : dest = change_address (destmem, DImode, destptr);
8437 : 0 : emit_insn (gen_strset (destptr, dest, value));
8438 : 0 : dest = adjust_automodify_address_nv (dest, DImode, destptr, 8);
8439 : 0 : emit_insn (gen_strset (destptr, dest, value));
8440 : : }
8441 : : else
8442 : : {
8443 : 0 : dest = change_address (destmem, SImode, destptr);
8444 : 0 : emit_insn (gen_strset (destptr, dest, value));
8445 : 0 : dest = adjust_automodify_address_nv (dest, SImode, destptr, 4);
8446 : 0 : emit_insn (gen_strset (destptr, dest, value));
8447 : 0 : dest = adjust_automodify_address_nv (dest, SImode, destptr, 8);
8448 : 0 : emit_insn (gen_strset (destptr, dest, value));
8449 : 0 : dest = adjust_automodify_address_nv (dest, SImode, destptr, 12);
8450 : 0 : emit_insn (gen_strset (destptr, dest, value));
8451 : : }
8452 : 0 : emit_label (label);
8453 : 0 : LABEL_NUSES (label) = 1;
8454 : : }
8455 : 843 : if (max_size > 8)
8456 : : {
8457 : 0 : rtx_code_label *label = ix86_expand_aligntest (count, 8, true);
8458 : 0 : if (TARGET_64BIT)
8459 : : {
8460 : 0 : dest = change_address (destmem, DImode, destptr);
8461 : 0 : emit_insn (gen_strset (destptr, dest, value));
8462 : : }
8463 : : else
8464 : : {
8465 : 0 : dest = change_address (destmem, SImode, destptr);
8466 : 0 : emit_insn (gen_strset (destptr, dest, value));
8467 : 0 : dest = adjust_automodify_address_nv (dest, SImode, destptr, 4);
8468 : 0 : emit_insn (gen_strset (destptr, dest, value));
8469 : : }
8470 : 0 : emit_label (label);
8471 : 0 : LABEL_NUSES (label) = 1;
8472 : : }
8473 : 843 : if (max_size > 4)
8474 : : {
8475 : 677 : rtx_code_label *label = ix86_expand_aligntest (count, 4, true);
8476 : 677 : dest = change_address (destmem, SImode, destptr);
8477 : 677 : emit_insn (gen_strset (destptr, dest, gen_lowpart (SImode, value)));
8478 : 677 : emit_label (label);
8479 : 677 : LABEL_NUSES (label) = 1;
8480 : : }
8481 : 843 : if (max_size > 2)
8482 : : {
8483 : 843 : rtx_code_label *label = ix86_expand_aligntest (count, 2, true);
8484 : 843 : dest = change_address (destmem, HImode, destptr);
8485 : 843 : emit_insn (gen_strset (destptr, dest, gen_lowpart (HImode, value)));
8486 : 843 : emit_label (label);
8487 : 843 : LABEL_NUSES (label) = 1;
8488 : : }
8489 : 843 : if (max_size > 1)
8490 : : {
8491 : 843 : rtx_code_label *label = ix86_expand_aligntest (count, 1, true);
8492 : 843 : dest = change_address (destmem, QImode, destptr);
8493 : 843 : emit_insn (gen_strset (destptr, dest, gen_lowpart (QImode, value)));
8494 : 843 : emit_label (label);
8495 : 843 : LABEL_NUSES (label) = 1;
8496 : : }
8497 : : }
8498 : :
8499 : : /* Adjust COUNTER by the VALUE. */
8500 : : static void
8501 : 19 : ix86_adjust_counter (rtx countreg, HOST_WIDE_INT value)
8502 : : {
8503 : 19 : emit_insn (gen_add2_insn (countreg, GEN_INT (-value)));
8504 : 19 : }
8505 : :
8506 : : /* Depending on ISSETMEM, copy enough from SRCMEM to DESTMEM or set enough to
8507 : : DESTMEM to align it to DESIRED_ALIGNMENT. Original alignment is ALIGN.
8508 : : Depending on ISSETMEM, either arguments SRCMEM/SRCPTR or VALUE/VEC_VALUE are
8509 : : ignored.
8510 : : Return value is updated DESTMEM. */
8511 : :
8512 : : static rtx
8513 : 7 : expand_set_or_cpymem_prologue (rtx destmem, rtx srcmem,
8514 : : rtx destptr, rtx srcptr, rtx value,
8515 : : rtx vec_value, rtx count, int align,
8516 : : int desired_alignment, bool issetmem)
8517 : : {
8518 : 7 : int i;
8519 : 35 : for (i = 1; i < desired_alignment; i <<= 1)
8520 : : {
8521 : 28 : if (align <= i)
8522 : : {
8523 : 19 : rtx_code_label *label = ix86_expand_aligntest (destptr, i, false);
8524 : 19 : if (issetmem)
8525 : : {
8526 : 12 : if (vec_value && i > GET_MODE_SIZE (GET_MODE (value)))
8527 : 2 : destmem = emit_memset (destmem, destptr, vec_value, i);
8528 : : else
8529 : 4 : destmem = emit_memset (destmem, destptr, value, i);
8530 : : }
8531 : : else
8532 : 13 : destmem = emit_memmov (destmem, &srcmem, destptr, srcptr, i);
8533 : 19 : ix86_adjust_counter (count, i);
8534 : 19 : emit_label (label);
8535 : 19 : LABEL_NUSES (label) = 1;
8536 : 19 : set_mem_align (destmem, i * 2 * BITS_PER_UNIT);
8537 : : }
8538 : : }
8539 : 7 : return destmem;
8540 : : }
8541 : :
8542 : : /* Test if COUNT&SIZE is nonzero and if so, expand movme
8543 : : or setmem sequence that is valid for SIZE..2*SIZE-1 bytes
8544 : : and jump to DONE_LABEL. */
8545 : : static void
8546 : 5074 : expand_small_cpymem_or_setmem (rtx destmem, rtx srcmem,
8547 : : rtx destptr, rtx srcptr,
8548 : : rtx value, rtx vec_value,
8549 : : rtx count, int size,
8550 : : rtx done_label, bool issetmem)
8551 : : {
8552 : 5074 : rtx_code_label *label = ix86_expand_aligntest (count, size, false);
8553 : 5074 : machine_mode mode = int_mode_for_size (size * BITS_PER_UNIT, 1).else_blk ();
8554 : 5074 : rtx modesize;
8555 : 5074 : int n;
8556 : :
8557 : : /* If we do not have vector value to copy, we must reduce size. */
8558 : 5074 : if (issetmem)
8559 : : {
8560 : 631 : if (!vec_value)
8561 : : {
8562 : 631 : if (GET_MODE (value) == VOIDmode && size > 8)
8563 : 0 : mode = Pmode;
8564 : 1893 : else if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (value)))
8565 : 1 : mode = GET_MODE (value);
8566 : : }
8567 : : else
8568 : 0 : mode = GET_MODE (vec_value), value = vec_value;
8569 : : }
8570 : : else
8571 : : {
8572 : : /* Choose appropriate vector mode. */
8573 : 4443 : if (size >= 32)
8574 : 0 : mode = TARGET_AVX ? V32QImode : TARGET_SSE ? V16QImode : DImode;
8575 : 4443 : else if (size >= 16)
8576 : 0 : mode = TARGET_SSE ? V16QImode : DImode;
8577 : 4443 : srcmem = change_address (srcmem, mode, srcptr);
8578 : : }
8579 : 5074 : destmem = change_address (destmem, mode, destptr);
8580 : 10148 : modesize = GEN_INT (GET_MODE_SIZE (mode));
8581 : 10148 : gcc_assert (GET_MODE_SIZE (mode) <= size);
8582 : 20298 : for (n = 0; n * GET_MODE_SIZE (mode) < size; n++)
8583 : : {
8584 : 5075 : if (issetmem)
8585 : 632 : emit_move_insn (destmem, gen_lowpart (mode, value));
8586 : : else
8587 : : {
8588 : 4443 : emit_move_insn (destmem, srcmem);
8589 : 8886 : srcmem = offset_address (srcmem, modesize, GET_MODE_SIZE (mode));
8590 : : }
8591 : 10150 : destmem = offset_address (destmem, modesize, GET_MODE_SIZE (mode));
8592 : : }
8593 : :
8594 : 5074 : destmem = offset_address (destmem, count, 1);
8595 : 10148 : destmem = offset_address (destmem, GEN_INT (-2 * size),
8596 : 5074 : GET_MODE_SIZE (mode));
8597 : 5074 : if (!issetmem)
8598 : : {
8599 : 4443 : srcmem = offset_address (srcmem, count, 1);
8600 : 8886 : srcmem = offset_address (srcmem, GEN_INT (-2 * size),
8601 : 4443 : GET_MODE_SIZE (mode));
8602 : : }
8603 : 20298 : for (n = 0; n * GET_MODE_SIZE (mode) < size; n++)
8604 : : {
8605 : 5075 : if (issetmem)
8606 : 632 : emit_move_insn (destmem, gen_lowpart (mode, value));
8607 : : else
8608 : : {
8609 : 4443 : emit_move_insn (destmem, srcmem);
8610 : 8886 : srcmem = offset_address (srcmem, modesize, GET_MODE_SIZE (mode));
8611 : : }
8612 : 10150 : destmem = offset_address (destmem, modesize, GET_MODE_SIZE (mode));
8613 : : }
8614 : 5074 : emit_jump_insn (gen_jump (done_label));
8615 : 5074 : emit_barrier ();
8616 : :
8617 : 5074 : emit_label (label);
8618 : 5074 : LABEL_NUSES (label) = 1;
8619 : 5074 : }
8620 : :
8621 : : /* Handle small memcpy (up to SIZE that is supposed to be small power of 2.
8622 : : and get ready for the main memcpy loop by copying iniital DESIRED_ALIGN-ALIGN
8623 : : bytes and last SIZE bytes adjusitng DESTPTR/SRCPTR/COUNT in a way we can
8624 : : proceed with an loop copying SIZE bytes at once. Do moves in MODE.
8625 : : DONE_LABEL is a label after the whole copying sequence. The label is created
8626 : : on demand if *DONE_LABEL is NULL.
8627 : : MIN_SIZE is minimal size of block copied. This value gets adjusted for new
8628 : : bounds after the initial copies.
8629 : :
8630 : : DESTMEM/SRCMEM are memory expressions pointing to the copies block,
8631 : : DESTPTR/SRCPTR are pointers to the block. DYNAMIC_CHECK indicate whether
8632 : : we will dispatch to a library call for large blocks.
8633 : :
8634 : : In pseudocode we do:
8635 : :
8636 : : if (COUNT < SIZE)
8637 : : {
8638 : : Assume that SIZE is 4. Bigger sizes are handled analogously
8639 : : if (COUNT & 4)
8640 : : {
8641 : : copy 4 bytes from SRCPTR to DESTPTR
8642 : : copy 4 bytes from SRCPTR + COUNT - 4 to DESTPTR + COUNT - 4
8643 : : goto done_label
8644 : : }
8645 : : if (!COUNT)
8646 : : goto done_label;
8647 : : copy 1 byte from SRCPTR to DESTPTR
8648 : : if (COUNT & 2)
8649 : : {
8650 : : copy 2 bytes from SRCPTR to DESTPTR
8651 : : copy 2 bytes from SRCPTR + COUNT - 2 to DESTPTR + COUNT - 2
8652 : : }
8653 : : }
8654 : : else
8655 : : {
8656 : : copy at least DESIRED_ALIGN-ALIGN bytes from SRCPTR to DESTPTR
8657 : : copy SIZE bytes from SRCPTR + COUNT - SIZE to DESTPTR + COUNT -SIZE
8658 : :
8659 : : OLD_DESPTR = DESTPTR;
8660 : : Align DESTPTR up to DESIRED_ALIGN
8661 : : SRCPTR += DESTPTR - OLD_DESTPTR
8662 : : COUNT -= DEST_PTR - OLD_DESTPTR
8663 : : if (DYNAMIC_CHECK)
8664 : : Round COUNT down to multiple of SIZE
8665 : : << optional caller supplied zero size guard is here >>
8666 : : << optional caller supplied dynamic check is here >>
8667 : : << caller supplied main copy loop is here >>
8668 : : }
8669 : : done_label:
8670 : : */
8671 : : static void
8672 : 8272 : expand_set_or_cpymem_prologue_epilogue_by_misaligned_moves (rtx destmem, rtx srcmem,
8673 : : rtx *destptr, rtx *srcptr,
8674 : : machine_mode mode,
8675 : : rtx value, rtx vec_value,
8676 : : rtx *count,
8677 : : rtx_code_label **done_label,
8678 : : int size,
8679 : : int desired_align,
8680 : : int align,
8681 : : unsigned HOST_WIDE_INT *min_size,
8682 : : bool dynamic_check,
8683 : : bool issetmem)
8684 : : {
8685 : 8272 : rtx_code_label *loop_label = NULL, *label;
8686 : 8272 : int n;
8687 : 8272 : rtx modesize;
8688 : 8272 : int prolog_size = 0;
8689 : 8272 : rtx mode_value;
8690 : :
8691 : : /* Chose proper value to copy. */
8692 : 8272 : if (issetmem && VECTOR_MODE_P (mode))
8693 : : mode_value = vec_value;
8694 : : else
8695 : 8272 : mode_value = value;
8696 : 16544 : gcc_assert (GET_MODE_SIZE (mode) <= size);
8697 : :
8698 : : /* See if block is big or small, handle small blocks. */
8699 : 8272 : if (!CONST_INT_P (*count) && *min_size < (unsigned HOST_WIDE_INT)size)
8700 : : {
8701 : 5401 : int size2 = size;
8702 : 5401 : loop_label = gen_label_rtx ();
8703 : :
8704 : 5401 : if (!*done_label)
8705 : 5401 : *done_label = gen_label_rtx ();
8706 : :
8707 : 5401 : emit_cmp_and_jump_insns (*count, GEN_INT (size2), GE, 0, GET_MODE (*count),
8708 : : 1, loop_label);
8709 : 5401 : size2 >>= 1;
8710 : :
8711 : : /* Handle sizes > 3. */
8712 : 10475 : for (;size2 > 2; size2 >>= 1)
8713 : 5074 : expand_small_cpymem_or_setmem (destmem, srcmem,
8714 : : *destptr, *srcptr,
8715 : : value, vec_value,
8716 : : *count,
8717 : : size2, *done_label, issetmem);
8718 : : /* Nothing to copy? Jump to DONE_LABEL if so */
8719 : 5401 : emit_cmp_and_jump_insns (*count, const0_rtx, EQ, 0, GET_MODE (*count),
8720 : : 1, *done_label);
8721 : :
8722 : : /* Do a byte copy. */
8723 : 5401 : destmem = change_address (destmem, QImode, *destptr);
8724 : 5401 : if (issetmem)
8725 : 725 : emit_move_insn (destmem, gen_lowpart (QImode, value));
8726 : : else
8727 : : {
8728 : 4676 : srcmem = change_address (srcmem, QImode, *srcptr);
8729 : 4676 : emit_move_insn (destmem, srcmem);
8730 : : }
8731 : :
8732 : : /* Handle sizes 2 and 3. */
8733 : 5401 : label = ix86_expand_aligntest (*count, 2, false);
8734 : 5401 : destmem = change_address (destmem, HImode, *destptr);
8735 : 5401 : destmem = offset_address (destmem, *count, 1);
8736 : 5401 : destmem = offset_address (destmem, GEN_INT (-2), 2);
8737 : 5401 : if (issetmem)
8738 : 725 : emit_move_insn (destmem, gen_lowpart (HImode, value));
8739 : : else
8740 : : {
8741 : 4676 : srcmem = change_address (srcmem, HImode, *srcptr);
8742 : 4676 : srcmem = offset_address (srcmem, *count, 1);
8743 : 4676 : srcmem = offset_address (srcmem, GEN_INT (-2), 2);
8744 : 4676 : emit_move_insn (destmem, srcmem);
8745 : : }
8746 : :
8747 : 5401 : emit_label (label);
8748 : 5401 : LABEL_NUSES (label) = 1;
8749 : 5401 : emit_jump_insn (gen_jump (*done_label));
8750 : 5401 : emit_barrier ();
8751 : : }
8752 : : else
8753 : 2871 : gcc_assert (*min_size >= (unsigned HOST_WIDE_INT)size
8754 : : || UINTVAL (*count) >= (unsigned HOST_WIDE_INT)size);
8755 : :
8756 : : /* Start memcpy for COUNT >= SIZE. */
8757 : 5401 : if (loop_label)
8758 : : {
8759 : 5401 : emit_label (loop_label);
8760 : 5401 : LABEL_NUSES (loop_label) = 1;
8761 : : }
8762 : :
8763 : : /* Copy first desired_align bytes. */
8764 : 8272 : if (!issetmem)
8765 : 6023 : srcmem = change_address (srcmem, mode, *srcptr);
8766 : 8272 : destmem = change_address (destmem, mode, *destptr);
8767 : 8272 : modesize = GEN_INT (GET_MODE_SIZE (mode));
8768 : 23884 : for (n = 0; prolog_size < desired_align - align; n++)
8769 : : {
8770 : 7340 : if (issetmem)
8771 : 2045 : emit_move_insn (destmem, mode_value);
8772 : : else
8773 : : {
8774 : 5295 : emit_move_insn (destmem, srcmem);
8775 : 10590 : srcmem = offset_address (srcmem, modesize, GET_MODE_SIZE (mode));
8776 : : }
8777 : 14680 : destmem = offset_address (destmem, modesize, GET_MODE_SIZE (mode));
8778 : 14680 : prolog_size += GET_MODE_SIZE (mode);
8779 : : }
8780 : :
8781 : :
8782 : : /* Copy last SIZE bytes. */
8783 : 8272 : destmem = offset_address (destmem, *count, 1);
8784 : 8272 : destmem = offset_address (destmem,
8785 : 8272 : GEN_INT (-size - prolog_size),
8786 : : 1);
8787 : 8272 : if (issetmem)
8788 : 2249 : emit_move_insn (destmem, mode_value);
8789 : : else
8790 : : {
8791 : 6023 : srcmem = offset_address (srcmem, *count, 1);
8792 : 6023 : srcmem = offset_address (srcmem,
8793 : : GEN_INT (-size - prolog_size),
8794 : : 1);
8795 : 6023 : emit_move_insn (destmem, srcmem);
8796 : : }
8797 : 16550 : for (n = 1; n * GET_MODE_SIZE (mode) < size; n++)
8798 : : {
8799 : 3 : destmem = offset_address (destmem, modesize, 1);
8800 : 3 : if (issetmem)
8801 : 3 : emit_move_insn (destmem, mode_value);
8802 : : else
8803 : : {
8804 : 0 : srcmem = offset_address (srcmem, modesize, 1);
8805 : 0 : emit_move_insn (destmem, srcmem);
8806 : : }
8807 : : }
8808 : :
8809 : : /* Align destination. */
8810 : 8272 : if (desired_align > 1 && desired_align > align)
8811 : : {
8812 : 7340 : rtx saveddest = *destptr;
8813 : :
8814 : 7340 : gcc_assert (desired_align <= size);
8815 : : /* Align destptr up, place it to new register. */
8816 : 7340 : *destptr = expand_simple_binop (GET_MODE (*destptr), PLUS, *destptr,
8817 : : GEN_INT (prolog_size),
8818 : : NULL_RTX, 1, OPTAB_DIRECT);
8819 : 7340 : if (REG_P (*destptr) && REG_P (saveddest) && REG_POINTER (saveddest))
8820 : 7340 : REG_POINTER (*destptr) = 1;
8821 : 7340 : *destptr = expand_simple_binop (GET_MODE (*destptr), AND, *destptr,
8822 : 7340 : GEN_INT (-desired_align),
8823 : : *destptr, 1, OPTAB_DIRECT);
8824 : : /* See how many bytes we skipped. */
8825 : 7340 : saveddest = expand_simple_binop (GET_MODE (*destptr), MINUS, saveddest,
8826 : : *destptr,
8827 : : NULL_RTX, 1, OPTAB_DIRECT);
8828 : : /* Adjust srcptr and count. */
8829 : 7340 : if (!issetmem)
8830 : 5295 : *srcptr = expand_simple_binop (GET_MODE (*srcptr), MINUS, *srcptr,
8831 : : saveddest, *srcptr, 1, OPTAB_DIRECT);
8832 : 7340 : *count = expand_simple_binop (GET_MODE (*count), PLUS, *count,
8833 : : saveddest, *count, 1, OPTAB_DIRECT);
8834 : : /* We copied at most size + prolog_size. */
8835 : 7340 : if (*min_size > (unsigned HOST_WIDE_INT)(size + prolog_size))
8836 : 2029 : *min_size
8837 : 2029 : = ROUND_DOWN (*min_size - size, (unsigned HOST_WIDE_INT)size);
8838 : : else
8839 : 5311 : *min_size = 0;
8840 : :
8841 : : /* Our loops always round down the block size, but for dispatch to
8842 : : library we need precise value. */
8843 : 7340 : if (dynamic_check)
8844 : 7340 : *count = expand_simple_binop (GET_MODE (*count), AND, *count,
8845 : : GEN_INT (-size), *count, 1, OPTAB_DIRECT);
8846 : : }
8847 : : else
8848 : : {
8849 : 932 : gcc_assert (prolog_size == 0);
8850 : : /* Decrease count, so we won't end up copying last word twice. */
8851 : 932 : if (!CONST_INT_P (*count))
8852 : 932 : *count = expand_simple_binop (GET_MODE (*count), PLUS, *count,
8853 : : constm1_rtx, *count, 1, OPTAB_DIRECT);
8854 : : else
8855 : 0 : *count = GEN_INT (ROUND_DOWN (UINTVAL (*count) - 1,
8856 : : (unsigned HOST_WIDE_INT)size));
8857 : 932 : if (*min_size)
8858 : 871 : *min_size = ROUND_DOWN (*min_size - 1, (unsigned HOST_WIDE_INT)size);
8859 : : }
8860 : 8272 : }
8861 : :
8862 : :
8863 : : /* This function is like the previous one, except here we know how many bytes
8864 : : need to be copied. That allows us to update alignment not only of DST, which
8865 : : is returned, but also of SRC, which is passed as a pointer for that
8866 : : reason. */
8867 : : static rtx
8868 : 6 : expand_set_or_cpymem_constant_prologue (rtx dst, rtx *srcp, rtx destreg,
8869 : : rtx srcreg, rtx value, rtx vec_value,
8870 : : int desired_align, int align_bytes,
8871 : : bool issetmem)
8872 : : {
8873 : 6 : rtx src = NULL;
8874 : 6 : rtx orig_dst = dst;
8875 : 6 : rtx orig_src = NULL;
8876 : 6 : int piece_size = 1;
8877 : 6 : int copied_bytes = 0;
8878 : :
8879 : 6 : if (!issetmem)
8880 : : {
8881 : 6 : gcc_assert (srcp != NULL);
8882 : 6 : src = *srcp;
8883 : 6 : orig_src = src;
8884 : : }
8885 : :
8886 : 6 : for (piece_size = 1;
8887 : 24 : piece_size <= desired_align && copied_bytes < align_bytes;
8888 : 18 : piece_size <<= 1)
8889 : : {
8890 : 18 : if (align_bytes & piece_size)
8891 : : {
8892 : 6 : if (issetmem)
8893 : : {
8894 : 0 : if (vec_value && piece_size > GET_MODE_SIZE (GET_MODE (value)))
8895 : 0 : dst = emit_memset (dst, destreg, vec_value, piece_size);
8896 : : else
8897 : 0 : dst = emit_memset (dst, destreg, value, piece_size);
8898 : : }
8899 : : else
8900 : 6 : dst = emit_memmov (dst, &src, destreg, srcreg, piece_size);
8901 : 6 : copied_bytes += piece_size;
8902 : : }
8903 : : }
8904 : 6 : if (MEM_ALIGN (dst) < (unsigned int) desired_align * BITS_PER_UNIT)
8905 : 6 : set_mem_align (dst, desired_align * BITS_PER_UNIT);
8906 : 6 : if (MEM_SIZE_KNOWN_P (orig_dst))
8907 : 6 : set_mem_size (dst, MEM_SIZE (orig_dst) - align_bytes);
8908 : :
8909 : 6 : if (!issetmem)
8910 : : {
8911 : 6 : int src_align_bytes = get_mem_align_offset (src, desired_align
8912 : : * BITS_PER_UNIT);
8913 : 6 : if (src_align_bytes >= 0)
8914 : 0 : src_align_bytes = desired_align - src_align_bytes;
8915 : 0 : if (src_align_bytes >= 0)
8916 : : {
8917 : : unsigned int src_align;
8918 : 0 : for (src_align = desired_align; src_align >= 2; src_align >>= 1)
8919 : : {
8920 : 0 : if ((src_align_bytes & (src_align - 1))
8921 : 0 : == (align_bytes & (src_align - 1)))
8922 : : break;
8923 : : }
8924 : 0 : if (src_align > (unsigned int) desired_align)
8925 : : src_align = desired_align;
8926 : 0 : if (MEM_ALIGN (src) < src_align * BITS_PER_UNIT)
8927 : 0 : set_mem_align (src, src_align * BITS_PER_UNIT);
8928 : : }
8929 : 6 : if (MEM_SIZE_KNOWN_P (orig_src))
8930 : 6 : set_mem_size (src, MEM_SIZE (orig_src) - align_bytes);
8931 : 6 : *srcp = src;
8932 : : }
8933 : :
8934 : 6 : return dst;
8935 : : }
8936 : :
8937 : : /* Return true if ALG can be used in current context.
8938 : : Assume we expand memset if MEMSET is true. */
8939 : : static bool
8940 : 599697 : alg_usable_p (enum stringop_alg alg, bool memset,
8941 : : addr_space_t dst_as, addr_space_t src_as)
8942 : : {
8943 : 599697 : if (alg == no_stringop)
8944 : : return false;
8945 : : /* It is not possible to use a library call if we have non-default
8946 : : address space. We can do better than the generic byte-at-a-time
8947 : : loop, used as a fallback. */
8948 : 599697 : if (alg == libcall &&
8949 : 291790 : !(ADDR_SPACE_GENERIC_P (dst_as) && ADDR_SPACE_GENERIC_P (src_as)))
8950 : : return false;
8951 : 599690 : if (alg == vector_loop)
8952 : 70 : return TARGET_SSE || TARGET_AVX;
8953 : : /* Algorithms using the rep prefix want at least edi and ecx;
8954 : : additionally, memset wants eax and memcpy wants esi. Don't
8955 : : consider such algorithms if the user has appropriated those
8956 : : registers for their own purposes, or if we have the destination
8957 : : in the non-default address space, since string insns cannot
8958 : : override the destination segment. */
8959 : 599655 : if (alg == rep_prefix_1_byte
8960 : : || alg == rep_prefix_4_byte
8961 : 599655 : || alg == rep_prefix_8_byte)
8962 : : {
8963 : 190862 : if (fixed_regs[CX_REG]
8964 : 190858 : || fixed_regs[DI_REG]
8965 : 190854 : || (memset ? fixed_regs[AX_REG] : fixed_regs[SI_REG])
8966 : 190850 : || !ADDR_SPACE_GENERIC_P (dst_as)
8967 : 381711 : || !(ADDR_SPACE_GENERIC_P (src_as) || Pmode == word_mode))
8968 : 13 : return false;
8969 : : }
8970 : : return true;
8971 : : }
8972 : :
8973 : : /* Given COUNT and EXPECTED_SIZE, decide on codegen of string operation. */
8974 : : static enum stringop_alg
8975 : 112778 : decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size,
8976 : : unsigned HOST_WIDE_INT min_size, unsigned HOST_WIDE_INT max_size,
8977 : : bool memset, bool zero_memset, addr_space_t dst_as,
8978 : : addr_space_t src_as, int *dynamic_check, bool *noalign, bool recur)
8979 : : {
8980 : 112778 : const struct stringop_algs *algs;
8981 : 112778 : bool optimize_for_speed;
8982 : 112778 : int max = 0;
8983 : 112778 : const struct processor_costs *cost;
8984 : 112778 : int i;
8985 : 112778 : bool any_alg_usable_p = false;
8986 : :
8987 : 112778 : *noalign = false;
8988 : 112778 : *dynamic_check = -1;
8989 : :
8990 : : /* Even if the string operation call is cold, we still might spend a lot
8991 : : of time processing large blocks. */
8992 : 112778 : if (optimize_function_for_size_p (cfun)
8993 : 112778 : || (optimize_insn_for_size_p ()
8994 : 4655 : && (max_size < 256
8995 : 1908 : || (expected_size != -1 && expected_size < 256))))
8996 : : optimize_for_speed = false;
8997 : : else
8998 : 101010 : optimize_for_speed = true;
8999 : :
9000 : 101010 : cost = optimize_for_speed ? ix86_cost : &ix86_size_cost;
9001 : 112778 : if (memset)
9002 : 40722 : algs = &cost->memset[TARGET_64BIT != 0];
9003 : : else
9004 : 80459 : algs = &cost->memcpy[TARGET_64BIT != 0];
9005 : :
9006 : : /* See maximal size for user defined algorithm. */
9007 : 563890 : for (i = 0; i < MAX_STRINGOP_ALGS; i++)
9008 : : {
9009 : 451112 : enum stringop_alg candidate = algs->size[i].alg;
9010 : 451112 : bool usable = alg_usable_p (candidate, memset, dst_as, src_as);
9011 : 451112 : any_alg_usable_p |= usable;
9012 : :
9013 : 451112 : if (candidate != libcall && candidate && usable)
9014 : 213784 : max = algs->size[i].max;
9015 : : }
9016 : :
9017 : : /* If expected size is not known but max size is small enough
9018 : : so inline version is a win, set expected size into
9019 : : the range. */
9020 : 112778 : if (((max > 1 && (unsigned HOST_WIDE_INT) max >= max_size) || max == -1)
9021 : 57369 : && expected_size == -1)
9022 : 15520 : expected_size = min_size / 2 + max_size / 2;
9023 : :
9024 : : /* If user specified the algorithm, honor it if possible. */
9025 : 112778 : if (ix86_stringop_alg != no_stringop
9026 : 112778 : && alg_usable_p (ix86_stringop_alg, memset, dst_as, src_as))
9027 : : return ix86_stringop_alg;
9028 : : /* rep; movq or rep; movl is the smallest variant. */
9029 : 112679 : else if (!optimize_for_speed)
9030 : : {
9031 : 11695 : *noalign = true;
9032 : 11695 : if (!count || (count & 3) || (memset && !zero_memset))
9033 : 4652 : return alg_usable_p (rep_prefix_1_byte, memset, dst_as, src_as)
9034 : 4652 : ? rep_prefix_1_byte : loop_1_byte;
9035 : : else
9036 : 7043 : return alg_usable_p (rep_prefix_4_byte, memset, dst_as, src_as)
9037 : 7043 : ? rep_prefix_4_byte : loop;
9038 : : }
9039 : : /* Very tiny blocks are best handled via the loop, REP is expensive to
9040 : : setup. */
9041 : 100984 : else if (expected_size != -1 && expected_size < 4)
9042 : : return loop_1_byte;
9043 : 98525 : else if (expected_size != -1)
9044 : : {
9045 : : enum stringop_alg alg = libcall;
9046 : : bool alg_noalign = false;
9047 : 87208 : for (i = 0; i < MAX_STRINGOP_ALGS; i++)
9048 : : {
9049 : : /* We get here if the algorithms that were not libcall-based
9050 : : were rep-prefix based and we are unable to use rep prefixes
9051 : : based on global register usage. Break out of the loop and
9052 : : use the heuristic below. */
9053 : 86936 : if (algs->size[i].max == 0)
9054 : : break;
9055 : 86936 : if (algs->size[i].max >= expected_size || algs->size[i].max == -1)
9056 : : {
9057 : 46377 : enum stringop_alg candidate = algs->size[i].alg;
9058 : :
9059 : 46377 : if (candidate != libcall
9060 : 46377 : && alg_usable_p (candidate, memset, dst_as, src_as))
9061 : : {
9062 : 43614 : alg = candidate;
9063 : 43614 : alg_noalign = algs->size[i].noalign;
9064 : : }
9065 : : /* Honor TARGET_INLINE_ALL_STRINGOPS by picking
9066 : : last non-libcall inline algorithm. */
9067 : 46377 : if (TARGET_INLINE_ALL_STRINGOPS)
9068 : : {
9069 : : /* When the current size is best to be copied by a libcall,
9070 : : but we are still forced to inline, run the heuristic below
9071 : : that will pick code for medium sized blocks. */
9072 : 5413 : if (alg != libcall)
9073 : : {
9074 : 4868 : *noalign = alg_noalign;
9075 : 4868 : return alg;
9076 : : }
9077 : 545 : else if (!any_alg_usable_p)
9078 : : break;
9079 : : }
9080 : 40964 : else if (alg_usable_p (candidate, memset, dst_as, src_as)
9081 : 40964 : && !(TARGET_PREFER_KNOWN_REP_MOVSB_STOSB
9082 : 22 : && candidate == rep_prefix_1_byte
9083 : : /* NB: If min_size != max_size, size is
9084 : : unknown. */
9085 : 22 : && min_size != max_size))
9086 : : {
9087 : 40959 : *noalign = algs->size[i].noalign;
9088 : 40959 : return candidate;
9089 : : }
9090 : : }
9091 : : }
9092 : : }
9093 : : /* When asked to inline the call anyway, try to pick meaningful choice.
9094 : : We look for maximal size of block that is faster to copy by hand and
9095 : : take blocks of at most of that size guessing that average size will
9096 : : be roughly half of the block.
9097 : :
9098 : : If this turns out to be bad, we might simply specify the preferred
9099 : : choice in ix86_costs. */
9100 : 52219 : if ((TARGET_INLINE_ALL_STRINGOPS || TARGET_INLINE_STRINGOPS_DYNAMICALLY)
9101 : 52704 : && (algs->unknown_size == libcall
9102 : 0 : || !alg_usable_p (algs->unknown_size, memset, dst_as, src_as)))
9103 : : {
9104 : 485 : enum stringop_alg alg;
9105 : 485 : HOST_WIDE_INT new_expected_size = (max > 0 ? max : 4096) / 2;
9106 : :
9107 : : /* If there aren't any usable algorithms or if recursing already,
9108 : : then recursing on smaller sizes or same size isn't going to
9109 : : find anything. Just return the simple byte-at-a-time copy loop. */
9110 : 485 : if (!any_alg_usable_p || recur)
9111 : : {
9112 : : /* Pick something reasonable. */
9113 : 0 : if (TARGET_INLINE_STRINGOPS_DYNAMICALLY && !recur)
9114 : 0 : *dynamic_check = 128;
9115 : 0 : return loop_1_byte;
9116 : : }
9117 : 485 : alg = decide_alg (count, new_expected_size, min_size, max_size,
9118 : : memset, zero_memset, dst_as, src_as,
9119 : : dynamic_check, noalign, true);
9120 : 485 : gcc_assert (*dynamic_check == -1);
9121 : 485 : if (TARGET_INLINE_STRINGOPS_DYNAMICALLY)
9122 : 8 : *dynamic_check = max;
9123 : : else
9124 : 477 : gcc_assert (alg != libcall);
9125 : 485 : return alg;
9126 : : }
9127 : :
9128 : : /* Try to use some reasonable fallback algorithm. Note that for
9129 : : non-default address spaces we default to a loop instead of
9130 : : a libcall. */
9131 : :
9132 : 52213 : bool have_as = !(ADDR_SPACE_GENERIC_P (dst_as)
9133 : : && ADDR_SPACE_GENERIC_P (src_as));
9134 : :
9135 : 52213 : return (alg_usable_p (algs->unknown_size, memset, dst_as, src_as)
9136 : 52213 : ? algs->unknown_size : have_as ? loop : libcall);
9137 : : }
9138 : :
9139 : : /* Decide on alignment. We know that the operand is already aligned to ALIGN
9140 : : (ALIGN can be based on profile feedback and thus it is not 100% guaranteed). */
9141 : : static int
9142 : 57825 : decide_alignment (int align,
9143 : : enum stringop_alg alg,
9144 : : int expected_size,
9145 : : machine_mode move_mode)
9146 : : {
9147 : 57825 : int desired_align = 0;
9148 : :
9149 : 57825 : gcc_assert (alg != no_stringop);
9150 : :
9151 : 57825 : if (alg == libcall)
9152 : : return 0;
9153 : 57825 : if (move_mode == VOIDmode)
9154 : : return 0;
9155 : :
9156 : 57825 : desired_align = GET_MODE_SIZE (move_mode);
9157 : : /* PentiumPro has special logic triggering for 8 byte aligned blocks.
9158 : : copying whole cacheline at once. */
9159 : 57825 : if (TARGET_CPU_P (PENTIUMPRO)
9160 : 0 : && (alg == rep_prefix_4_byte || alg == rep_prefix_1_byte))
9161 : 57825 : desired_align = 8;
9162 : :
9163 : 57825 : if (optimize_size)
9164 : 8639 : desired_align = 1;
9165 : 57825 : if (desired_align < align)
9166 : : desired_align = align;
9167 : 57825 : if (expected_size != -1 && expected_size < 4)
9168 : 0 : desired_align = align;
9169 : :
9170 : : return desired_align;
9171 : : }
9172 : :
9173 : :
9174 : : /* Helper function for memcpy. For QImode value 0xXY produce
9175 : : 0xXYXYXYXY of wide specified by MODE. This is essentially
9176 : : a * 0x10101010, but we can do slightly better than
9177 : : synth_mult by unwinding the sequence by hand on CPUs with
9178 : : slow multiply. */
9179 : : static rtx
9180 : 21836 : promote_duplicated_reg (machine_mode mode, rtx val)
9181 : : {
9182 : 21836 : machine_mode valmode = GET_MODE (val);
9183 : 21836 : rtx tmp;
9184 : 21836 : int nops = mode == DImode ? 3 : 2;
9185 : :
9186 : 5024 : gcc_assert (mode == SImode || mode == DImode || val == const0_rtx);
9187 : 21836 : if (val == const0_rtx)
9188 : 20374 : return copy_to_mode_reg (mode, CONST0_RTX (mode));
9189 : 1462 : if (CONST_INT_P (val))
9190 : : {
9191 : 1069 : HOST_WIDE_INT v = INTVAL (val) & 255;
9192 : :
9193 : 1069 : v |= v << 8;
9194 : 1069 : v |= v << 16;
9195 : 1069 : if (mode == DImode)
9196 : 1033 : v |= (v << 16) << 16;
9197 : 1069 : return copy_to_mode_reg (mode, gen_int_mode (v, mode));
9198 : : }
9199 : :
9200 : 393 : if (valmode == VOIDmode)
9201 : : valmode = QImode;
9202 : 393 : if (valmode != QImode)
9203 : 0 : val = gen_lowpart (QImode, val);
9204 : 393 : if (mode == QImode)
9205 : : return val;
9206 : 393 : if (!TARGET_PARTIAL_REG_STALL)
9207 : 393 : nops--;
9208 : 393 : if (ix86_cost->mult_init[mode == DImode ? 3 : 2]
9209 : 393 : + ix86_cost->mult_bit * (mode == DImode ? 8 : 4)
9210 : 393 : <= (ix86_cost->shift_const + ix86_cost->add) * nops
9211 : 393 : + (COSTS_N_INSNS (TARGET_PARTIAL_REG_STALL == 0)))
9212 : : {
9213 : 393 : rtx reg = convert_modes (mode, QImode, val, true);
9214 : 393 : tmp = promote_duplicated_reg (mode, const1_rtx);
9215 : 393 : return expand_simple_binop (mode, MULT, reg, tmp, NULL, 1,
9216 : 393 : OPTAB_DIRECT);
9217 : : }
9218 : : else
9219 : : {
9220 : 0 : rtx reg = convert_modes (mode, QImode, val, true);
9221 : :
9222 : 0 : if (!TARGET_PARTIAL_REG_STALL)
9223 : 0 : emit_insn (gen_insv_1 (mode, reg, reg));
9224 : : else
9225 : : {
9226 : 0 : tmp = expand_simple_binop (mode, ASHIFT, reg, GEN_INT (8),
9227 : : NULL, 1, OPTAB_DIRECT);
9228 : 0 : reg = expand_simple_binop (mode, IOR, reg, tmp, reg, 1,
9229 : : OPTAB_DIRECT);
9230 : : }
9231 : 0 : tmp = expand_simple_binop (mode, ASHIFT, reg, GEN_INT (16),
9232 : : NULL, 1, OPTAB_DIRECT);
9233 : 0 : reg = expand_simple_binop (mode, IOR, reg, tmp, reg, 1, OPTAB_DIRECT);
9234 : 0 : if (mode == SImode)
9235 : : return reg;
9236 : 0 : tmp = expand_simple_binop (mode, ASHIFT, reg, GEN_INT (32),
9237 : : NULL, 1, OPTAB_DIRECT);
9238 : 0 : reg = expand_simple_binop (mode, IOR, reg, tmp, reg, 1, OPTAB_DIRECT);
9239 : 0 : return reg;
9240 : : }
9241 : : }
9242 : :
9243 : : /* Duplicate value VAL using promote_duplicated_reg into maximal size that will
9244 : : be needed by main loop copying SIZE_NEEDED chunks and prologue getting
9245 : : alignment from ALIGN to DESIRED_ALIGN. */
9246 : : static rtx
9247 : 23186 : promote_duplicated_reg_to_size (rtx val, int size_needed, int desired_align,
9248 : : int align)
9249 : : {
9250 : 23186 : rtx promoted_val;
9251 : :
9252 : 23186 : if (TARGET_64BIT
9253 : 20174 : && (size_needed > 4 || (desired_align > align && desired_align > 4)))
9254 : 16431 : promoted_val = promote_duplicated_reg (DImode, val);
9255 : 6755 : else if (size_needed > 2 || (desired_align > align && desired_align > 2))
9256 : 5007 : promoted_val = promote_duplicated_reg (SImode, val);
9257 : 1748 : else if (size_needed > 1 || (desired_align > align && desired_align > 1))
9258 : 0 : promoted_val = promote_duplicated_reg (HImode, val);
9259 : : else
9260 : : promoted_val = val;
9261 : :
9262 : 23186 : return promoted_val;
9263 : : }
9264 : :
9265 : : /* Copy the address to a Pmode register. This is used for x32 to
9266 : : truncate DImode TLS address to a SImode register. */
9267 : :
9268 : : static rtx
9269 : 92464 : ix86_copy_addr_to_reg (rtx addr)
9270 : : {
9271 : 92464 : rtx reg;
9272 : 100694 : if (GET_MODE (addr) == Pmode || GET_MODE (addr) == VOIDmode)
9273 : : {
9274 : 92464 : reg = copy_addr_to_reg (addr);
9275 : 92464 : REG_POINTER (reg) = 1;
9276 : 92464 : return reg;
9277 : : }
9278 : : else
9279 : : {
9280 : 0 : gcc_assert (GET_MODE (addr) == DImode && Pmode == SImode);
9281 : 0 : reg = copy_to_mode_reg (DImode, addr);
9282 : 0 : REG_POINTER (reg) = 1;
9283 : 0 : return gen_rtx_SUBREG (SImode, reg, 0);
9284 : : }
9285 : : }
9286 : :
9287 : : /* Expand string move (memcpy) ot store (memset) operation. Use i386 string
9288 : : operations when profitable. The code depends upon architecture, block size
9289 : : and alignment, but always has one of the following overall structures:
9290 : :
9291 : : Aligned move sequence:
9292 : :
9293 : : 1) Prologue guard: Conditional that jumps up to epilogues for small
9294 : : blocks that can be handled by epilogue alone. This is faster
9295 : : but also needed for correctness, since prologue assume the block
9296 : : is larger than the desired alignment.
9297 : :
9298 : : Optional dynamic check for size and libcall for large
9299 : : blocks is emitted here too, with -minline-stringops-dynamically.
9300 : :
9301 : : 2) Prologue: copy first few bytes in order to get destination
9302 : : aligned to DESIRED_ALIGN. It is emitted only when ALIGN is less
9303 : : than DESIRED_ALIGN and up to DESIRED_ALIGN - ALIGN bytes can be
9304 : : copied. We emit either a jump tree on power of two sized
9305 : : blocks, or a byte loop.
9306 : :
9307 : : 3) Main body: the copying loop itself, copying in SIZE_NEEDED chunks
9308 : : with specified algorithm.
9309 : :
9310 : : 4) Epilogue: code copying tail of the block that is too small to be
9311 : : handled by main body (or up to size guarded by prologue guard).
9312 : :
9313 : : Misaligned move sequence
9314 : :
9315 : : 1) missaligned move prologue/epilogue containing:
9316 : : a) Prologue handling small memory blocks and jumping to done_label
9317 : : (skipped if blocks are known to be large enough)
9318 : : b) Signle move copying first DESIRED_ALIGN-ALIGN bytes if alignment is
9319 : : needed by single possibly misaligned move
9320 : : (skipped if alignment is not needed)
9321 : : c) Copy of last SIZE_NEEDED bytes by possibly misaligned moves
9322 : :
9323 : : 2) Zero size guard dispatching to done_label, if needed
9324 : :
9325 : : 3) dispatch to library call, if needed,
9326 : :
9327 : : 3) Main body: the copying loop itself, copying in SIZE_NEEDED chunks
9328 : : with specified algorithm. */
9329 : : bool
9330 : 112471 : ix86_expand_set_or_cpymem (rtx dst, rtx src, rtx count_exp, rtx val_exp,
9331 : : rtx align_exp, rtx expected_align_exp,
9332 : : rtx expected_size_exp, rtx min_size_exp,
9333 : : rtx max_size_exp, rtx probable_max_size_exp,
9334 : : bool issetmem)
9335 : : {
9336 : 112471 : rtx destreg;
9337 : 112471 : rtx srcreg = NULL;
9338 : 112471 : rtx_code_label *label = NULL;
9339 : 112471 : rtx tmp;
9340 : 112471 : rtx_code_label *jump_around_label = NULL;
9341 : 112471 : HOST_WIDE_INT align = 1;
9342 : 112471 : unsigned HOST_WIDE_INT count = 0;
9343 : 112471 : HOST_WIDE_INT expected_size = -1;
9344 : 112471 : int size_needed = 0, epilogue_size_needed;
9345 : 112471 : int desired_align = 0, align_bytes = 0;
9346 : 112471 : enum stringop_alg alg;
9347 : 112471 : rtx promoted_val = NULL;
9348 : 112471 : rtx vec_promoted_val = NULL;
9349 : 112471 : bool force_loopy_epilogue = false;
9350 : 112471 : int dynamic_check;
9351 : 112471 : bool need_zero_guard = false;
9352 : 112471 : bool noalign;
9353 : 112471 : machine_mode move_mode = VOIDmode;
9354 : 112471 : int unroll_factor = 1;
9355 : : /* TODO: Once value ranges are available, fill in proper data. */
9356 : 112471 : unsigned HOST_WIDE_INT min_size = 0;
9357 : 112471 : unsigned HOST_WIDE_INT max_size = -1;
9358 : 112471 : unsigned HOST_WIDE_INT probable_max_size = -1;
9359 : 112471 : bool misaligned_prologue_used = false;
9360 : 112471 : addr_space_t dst_as, src_as = ADDR_SPACE_GENERIC;
9361 : :
9362 : 112471 : if (CONST_INT_P (align_exp))
9363 : 112471 : align = INTVAL (align_exp);
9364 : : /* i386 can do misaligned access on reasonably increased cost. */
9365 : 112471 : if (CONST_INT_P (expected_align_exp)
9366 : 112471 : && INTVAL (expected_align_exp) > align)
9367 : : align = INTVAL (expected_align_exp);
9368 : : /* ALIGN is the minimum of destination and source alignment, but we care here
9369 : : just about destination alignment. */
9370 : 106914 : else if (!issetmem
9371 : 177368 : && MEM_ALIGN (dst) > (unsigned HOST_WIDE_INT) align * BITS_PER_UNIT)
9372 : 2226 : align = MEM_ALIGN (dst) / BITS_PER_UNIT;
9373 : :
9374 : 112471 : if (CONST_INT_P (count_exp))
9375 : : {
9376 : 44510 : min_size = max_size = probable_max_size = count = expected_size
9377 : 44510 : = INTVAL (count_exp);
9378 : : /* When COUNT is 0, there is nothing to do. */
9379 : 44510 : if (!count)
9380 : : return true;
9381 : : }
9382 : : else
9383 : : {
9384 : 67961 : if (min_size_exp)
9385 : 67961 : min_size = INTVAL (min_size_exp);
9386 : 67961 : if (max_size_exp)
9387 : 52932 : max_size = INTVAL (max_size_exp);
9388 : 67961 : if (probable_max_size_exp)
9389 : 54852 : probable_max_size = INTVAL (probable_max_size_exp);
9390 : 67961 : if (CONST_INT_P (expected_size_exp))
9391 : 67961 : expected_size = INTVAL (expected_size_exp);
9392 : : }
9393 : :
9394 : : /* Make sure we don't need to care about overflow later on. */
9395 : 112469 : if (count > (HOST_WIDE_INT_1U << 30))
9396 : : return false;
9397 : :
9398 : 112293 : dst_as = MEM_ADDR_SPACE (dst);
9399 : 112293 : if (!issetmem)
9400 : 75898 : src_as = MEM_ADDR_SPACE (src);
9401 : :
9402 : : /* Step 0: Decide on preferred algorithm, desired alignment and
9403 : : size of chunks to be copied by main loop. */
9404 : 112293 : alg = decide_alg (count, expected_size, min_size, probable_max_size,
9405 : 36395 : issetmem, issetmem && val_exp == const0_rtx,
9406 : : dst_as, src_as, &dynamic_check, &noalign, false);
9407 : :
9408 : 112293 : if (dump_file)
9409 : 7 : fprintf (dump_file, "Selected stringop expansion strategy: %s\n",
9410 : 7 : stringop_alg_names[alg]);
9411 : :
9412 : 112293 : if (alg == libcall)
9413 : : return false;
9414 : 57825 : gcc_assert (alg != no_stringop);
9415 : :
9416 : : /* For now vector-version of memset is generated only for memory zeroing, as
9417 : : creating of promoted vector value is very cheap in this case. */
9418 : 57825 : if (issetmem && alg == vector_loop && val_exp != const0_rtx)
9419 : 0 : alg = unrolled_loop;
9420 : :
9421 : 57825 : if (!count)
9422 : 15744 : count_exp = copy_to_mode_reg (GET_MODE (count_exp), count_exp);
9423 : 57825 : destreg = ix86_copy_addr_to_reg (XEXP (dst, 0));
9424 : 57825 : if (!issetmem)
9425 : 34639 : srcreg = ix86_copy_addr_to_reg (XEXP (src, 0));
9426 : :
9427 : 57825 : unroll_factor = 1;
9428 : 57825 : move_mode = word_mode;
9429 : 57825 : int nunits;
9430 : 57825 : switch (alg)
9431 : : {
9432 : 0 : case libcall:
9433 : 0 : case no_stringop:
9434 : 0 : case last_alg:
9435 : 0 : gcc_unreachable ();
9436 : 2463 : case loop_1_byte:
9437 : 2463 : need_zero_guard = true;
9438 : 2463 : move_mode = QImode;
9439 : 2463 : break;
9440 : 8048 : case loop:
9441 : 8048 : need_zero_guard = true;
9442 : 8048 : break;
9443 : 3 : case unrolled_loop:
9444 : 3 : need_zero_guard = true;
9445 : 3 : unroll_factor = (TARGET_64BIT ? 4 : 2);
9446 : : break;
9447 : 17 : case vector_loop:
9448 : 17 : need_zero_guard = true;
9449 : 17 : unroll_factor = 4;
9450 : : /* Get the vector mode to move MOVE_MAX bytes. */
9451 : 17 : nunits = MOVE_MAX / GET_MODE_SIZE (word_mode);
9452 : 17 : if (nunits > 1)
9453 : : {
9454 : 13 : move_mode = mode_for_vector (word_mode, nunits).require ();
9455 : 13 : gcc_assert (optab_handler (mov_optab, move_mode)
9456 : : != CODE_FOR_nothing);
9457 : : }
9458 : : break;
9459 : 30755 : case rep_prefix_8_byte:
9460 : 30755 : move_mode = DImode;
9461 : 30755 : break;
9462 : 11883 : case rep_prefix_4_byte:
9463 : 11883 : move_mode = SImode;
9464 : 11883 : break;
9465 : 4656 : case rep_prefix_1_byte:
9466 : 4656 : move_mode = QImode;
9467 : 4656 : break;
9468 : : }
9469 : 57825 : size_needed = GET_MODE_SIZE (move_mode) * unroll_factor;
9470 : 57825 : epilogue_size_needed = size_needed;
9471 : :
9472 : : /* If we are going to call any library calls conditionally, make sure any
9473 : : pending stack adjustment happen before the first conditional branch,
9474 : : otherwise they will be emitted before the library call only and won't
9475 : : happen from the other branches. */
9476 : 57825 : if (dynamic_check != -1)
9477 : 7 : do_pending_stack_adjust ();
9478 : :
9479 : 57825 : desired_align = decide_alignment (align, alg, expected_size, move_mode);
9480 : 57825 : if (!TARGET_ALIGN_STRINGOPS || noalign)
9481 : 11708 : align = desired_align;
9482 : :
9483 : : /* Step 1: Prologue guard. */
9484 : :
9485 : : /* Alignment code needs count to be in register. */
9486 : 57825 : if (CONST_INT_P (count_exp) && desired_align > align)
9487 : : {
9488 : 1981 : if (INTVAL (count_exp) > desired_align
9489 : 1981 : && INTVAL (count_exp) > size_needed)
9490 : : {
9491 : 1981 : align_bytes
9492 : 1981 : = get_mem_align_offset (dst, desired_align * BITS_PER_UNIT);
9493 : 1981 : if (align_bytes <= 0)
9494 : : align_bytes = 0;
9495 : : else
9496 : 6 : align_bytes = desired_align - align_bytes;
9497 : : }
9498 : 6 : if (align_bytes == 0)
9499 : 3950 : count_exp = force_reg (counter_mode (count_exp), count_exp);
9500 : : }
9501 : 57825 : gcc_assert (desired_align >= 1 && align >= 1);
9502 : :
9503 : : /* Misaligned move sequences handle both prologue and epilogue at once.
9504 : : Default code generation results in a smaller code for large alignments
9505 : : and also avoids redundant job when sizes are known precisely. */
9506 : 57825 : misaligned_prologue_used
9507 : 115650 : = (TARGET_MISALIGNED_MOVE_STRING_PRO_EPILOGUES
9508 : 57816 : && MAX (desired_align, epilogue_size_needed) <= 32
9509 : 56637 : && desired_align <= epilogue_size_needed
9510 : 78361 : && ((desired_align > align && !align_bytes)
9511 : 13196 : || (!count && epilogue_size_needed > 1)));
9512 : :
9513 : : /* Do the cheap promotion to allow better CSE across the
9514 : : main loop and epilogue (ie one load of the big constant in the
9515 : : front of all code.
9516 : : For now the misaligned move sequences do not have fast path
9517 : : without broadcasting. */
9518 : 57825 : if (issetmem && ((CONST_INT_P (val_exp) || misaligned_prologue_used)))
9519 : : {
9520 : 22865 : if (alg == vector_loop)
9521 : : {
9522 : 5 : gcc_assert (val_exp == const0_rtx);
9523 : 5 : vec_promoted_val = promote_duplicated_reg (move_mode, val_exp);
9524 : 5 : promoted_val = promote_duplicated_reg_to_size (val_exp,
9525 : 10 : GET_MODE_SIZE (word_mode),
9526 : : desired_align, align);
9527 : : }
9528 : : else
9529 : : {
9530 : 22860 : promoted_val = promote_duplicated_reg_to_size (val_exp, size_needed,
9531 : : desired_align, align);
9532 : : }
9533 : : }
9534 : : /* Misaligned move sequences handles both prologues and epilogues at once.
9535 : : Default code generation results in smaller code for large alignments and
9536 : : also avoids redundant job when sizes are known precisely. */
9537 : 57504 : if (misaligned_prologue_used)
9538 : : {
9539 : : /* Misaligned move prologue handled small blocks by itself. */
9540 : 8272 : expand_set_or_cpymem_prologue_epilogue_by_misaligned_moves
9541 : 8272 : (dst, src, &destreg, &srcreg,
9542 : : move_mode, promoted_val, vec_promoted_val,
9543 : : &count_exp,
9544 : : &jump_around_label,
9545 : 8272 : desired_align < align
9546 : 0 : ? MAX (desired_align, epilogue_size_needed) : epilogue_size_needed,
9547 : : desired_align, align, &min_size, dynamic_check, issetmem);
9548 : 8272 : if (!issetmem)
9549 : 6023 : src = change_address (src, BLKmode, srcreg);
9550 : 8272 : dst = change_address (dst, BLKmode, destreg);
9551 : 8272 : set_mem_align (dst, desired_align * BITS_PER_UNIT);
9552 : 8272 : epilogue_size_needed = 0;
9553 : 8272 : if (need_zero_guard
9554 : 5608 : && min_size < (unsigned HOST_WIDE_INT) size_needed)
9555 : : {
9556 : : /* It is possible that we copied enough so the main loop will not
9557 : : execute. */
9558 : 5597 : gcc_assert (size_needed > 1);
9559 : 5597 : if (jump_around_label == NULL_RTX)
9560 : 643 : jump_around_label = gen_label_rtx ();
9561 : 11194 : emit_cmp_and_jump_insns (count_exp,
9562 : : GEN_INT (size_needed),
9563 : : LTU, 0, counter_mode (count_exp), 1, jump_around_label);
9564 : 5597 : if (expected_size == -1
9565 : 1 : || expected_size < (desired_align - align) / 2 + size_needed)
9566 : 5597 : predict_jump (REG_BR_PROB_BASE * 20 / 100);
9567 : : else
9568 : 0 : predict_jump (REG_BR_PROB_BASE * 60 / 100);
9569 : : }
9570 : : }
9571 : : /* Ensure that alignment prologue won't copy past end of block. */
9572 : 49553 : else if (size_needed > 1 || (desired_align > 1 && desired_align > align))
9573 : : {
9574 : 42434 : epilogue_size_needed = MAX (size_needed - 1, desired_align - align);
9575 : : /* Epilogue always copies COUNT_EXP & EPILOGUE_SIZE_NEEDED bytes.
9576 : : Make sure it is power of 2. */
9577 : 42434 : epilogue_size_needed = 1 << (floor_log2 (epilogue_size_needed) + 1);
9578 : :
9579 : : /* To improve performance of small blocks, we jump around the VAL
9580 : : promoting mode. This mean that if the promoted VAL is not constant,
9581 : : we might not use it in the epilogue and have to use byte
9582 : : loop variant. */
9583 : 42434 : if (issetmem && epilogue_size_needed > 2 && !promoted_val)
9584 : 42434 : force_loopy_epilogue = true;
9585 : 42434 : if ((count && count < (unsigned HOST_WIDE_INT) epilogue_size_needed)
9586 : 42434 : || max_size < (unsigned HOST_WIDE_INT) epilogue_size_needed)
9587 : : {
9588 : : /* If main algorithm works on QImode, no epilogue is needed.
9589 : : For small sizes just don't align anything. */
9590 : 133 : if (size_needed == 1)
9591 : 0 : desired_align = align;
9592 : : else
9593 : 133 : goto epilogue;
9594 : : }
9595 : 42301 : else if (!count
9596 : 3197 : && min_size < (unsigned HOST_WIDE_INT) epilogue_size_needed)
9597 : : {
9598 : 2193 : label = gen_label_rtx ();
9599 : 4386 : emit_cmp_and_jump_insns (count_exp,
9600 : : GEN_INT (epilogue_size_needed),
9601 : : LTU, 0, counter_mode (count_exp), 1, label);
9602 : 2193 : if (expected_size == -1 || expected_size < epilogue_size_needed)
9603 : 2188 : predict_jump (REG_BR_PROB_BASE * 60 / 100);
9604 : : else
9605 : 5 : predict_jump (REG_BR_PROB_BASE * 20 / 100);
9606 : : }
9607 : : }
9608 : :
9609 : : /* Emit code to decide on runtime whether library call or inline should be
9610 : : used. */
9611 : 57692 : if (dynamic_check != -1)
9612 : : {
9613 : 7 : if (!issetmem && CONST_INT_P (count_exp))
9614 : : {
9615 : 0 : if (UINTVAL (count_exp) >= (unsigned HOST_WIDE_INT)dynamic_check)
9616 : : {
9617 : 0 : emit_block_copy_via_libcall (dst, src, count_exp);
9618 : 0 : count_exp = const0_rtx;
9619 : 0 : goto epilogue;
9620 : : }
9621 : : }
9622 : : else
9623 : : {
9624 : 7 : rtx_code_label *hot_label = gen_label_rtx ();
9625 : 7 : if (jump_around_label == NULL_RTX)
9626 : 2 : jump_around_label = gen_label_rtx ();
9627 : 14 : emit_cmp_and_jump_insns (count_exp, GEN_INT (dynamic_check - 1),
9628 : : LEU, 0, counter_mode (count_exp),
9629 : : 1, hot_label);
9630 : 7 : predict_jump (REG_BR_PROB_BASE * 90 / 100);
9631 : 7 : if (issetmem)
9632 : 4 : set_storage_via_libcall (dst, count_exp, val_exp);
9633 : : else
9634 : 3 : emit_block_copy_via_libcall (dst, src, count_exp);
9635 : 7 : emit_jump (jump_around_label);
9636 : 7 : emit_label (hot_label);
9637 : : }
9638 : : }
9639 : :
9640 : : /* Step 2: Alignment prologue. */
9641 : : /* Do the expensive promotion once we branched off the small blocks. */
9642 : 57692 : if (issetmem && !promoted_val)
9643 : 321 : promoted_val = promote_duplicated_reg_to_size (val_exp, size_needed,
9644 : : desired_align, align);
9645 : :
9646 : 57692 : if (desired_align > align && !misaligned_prologue_used)
9647 : : {
9648 : 13 : if (align_bytes == 0)
9649 : : {
9650 : : /* Except for the first move in prologue, we no longer know
9651 : : constant offset in aliasing info. It don't seems to worth
9652 : : the pain to maintain it for the first move, so throw away
9653 : : the info early. */
9654 : 7 : dst = change_address (dst, BLKmode, destreg);
9655 : 7 : if (!issetmem)
9656 : 5 : src = change_address (src, BLKmode, srcreg);
9657 : 7 : dst = expand_set_or_cpymem_prologue (dst, src, destreg, srcreg,
9658 : : promoted_val, vec_promoted_val,
9659 : : count_exp, align, desired_align,
9660 : : issetmem);
9661 : : /* At most desired_align - align bytes are copied. */
9662 : 7 : if (min_size < (unsigned)(desired_align - align))
9663 : 0 : min_size = 0;
9664 : : else
9665 : 7 : min_size -= desired_align - align;
9666 : : }
9667 : : else
9668 : : {
9669 : : /* If we know how many bytes need to be stored before dst is
9670 : : sufficiently aligned, maintain aliasing info accurately. */
9671 : 6 : dst = expand_set_or_cpymem_constant_prologue (dst, &src, destreg,
9672 : : srcreg,
9673 : : promoted_val,
9674 : : vec_promoted_val,
9675 : : desired_align,
9676 : : align_bytes,
9677 : : issetmem);
9678 : :
9679 : 6 : count_exp = plus_constant (counter_mode (count_exp),
9680 : 6 : count_exp, -align_bytes);
9681 : 6 : count -= align_bytes;
9682 : 6 : min_size -= align_bytes;
9683 : 6 : max_size -= align_bytes;
9684 : : }
9685 : 13 : if (need_zero_guard
9686 : 7 : && min_size < (unsigned HOST_WIDE_INT) size_needed
9687 : 1 : && (count < (unsigned HOST_WIDE_INT) size_needed
9688 : 0 : || (align_bytes == 0
9689 : 0 : && count < ((unsigned HOST_WIDE_INT) size_needed
9690 : 0 : + desired_align - align))))
9691 : : {
9692 : : /* It is possible that we copied enough so the main loop will not
9693 : : execute. */
9694 : 1 : gcc_assert (size_needed > 1);
9695 : 1 : if (label == NULL_RTX)
9696 : 0 : label = gen_label_rtx ();
9697 : 2 : emit_cmp_and_jump_insns (count_exp,
9698 : : GEN_INT (size_needed),
9699 : : LTU, 0, counter_mode (count_exp), 1, label);
9700 : 1 : if (expected_size == -1
9701 : 0 : || expected_size < (desired_align - align) / 2 + size_needed)
9702 : 1 : predict_jump (REG_BR_PROB_BASE * 20 / 100);
9703 : : else
9704 : 0 : predict_jump (REG_BR_PROB_BASE * 60 / 100);
9705 : : }
9706 : : }
9707 : 57692 : if (label && size_needed == 1)
9708 : : {
9709 : 0 : emit_label (label);
9710 : 0 : LABEL_NUSES (label) = 1;
9711 : 0 : label = NULL;
9712 : 0 : epilogue_size_needed = 1;
9713 : 0 : if (issetmem)
9714 : 0 : promoted_val = val_exp;
9715 : : }
9716 : 57692 : else if (label == NULL_RTX && !misaligned_prologue_used)
9717 : 47227 : epilogue_size_needed = size_needed;
9718 : :
9719 : : /* Step 3: Main loop. */
9720 : :
9721 : 57692 : switch (alg)
9722 : : {
9723 : 0 : case libcall:
9724 : 0 : case no_stringop:
9725 : 0 : case last_alg:
9726 : 0 : gcc_unreachable ();
9727 : 10381 : case loop_1_byte:
9728 : 10381 : case loop:
9729 : 10381 : case unrolled_loop:
9730 : 10381 : expand_set_or_cpymem_via_loop (dst, src, destreg, srcreg, promoted_val,
9731 : : count_exp, move_mode, unroll_factor,
9732 : : expected_size, issetmem);
9733 : 10381 : break;
9734 : 17 : case vector_loop:
9735 : 17 : expand_set_or_cpymem_via_loop (dst, src, destreg, srcreg,
9736 : : vec_promoted_val, count_exp, move_mode,
9737 : : unroll_factor, expected_size, issetmem);
9738 : 17 : break;
9739 : 47294 : case rep_prefix_8_byte:
9740 : 47294 : case rep_prefix_4_byte:
9741 : 47294 : case rep_prefix_1_byte:
9742 : 47294 : expand_set_or_cpymem_via_rep (dst, src, destreg, srcreg, promoted_val,
9743 : : val_exp, count_exp, move_mode, issetmem);
9744 : 47294 : break;
9745 : : }
9746 : : /* Adjust properly the offset of src and dest memory for aliasing. */
9747 : 57692 : if (CONST_INT_P (count_exp))
9748 : : {
9749 : 40106 : if (!issetmem)
9750 : 21519 : src = adjust_automodify_address_nv (src, BLKmode, srcreg,
9751 : : (count / size_needed) * size_needed);
9752 : 40106 : dst = adjust_automodify_address_nv (dst, BLKmode, destreg,
9753 : : (count / size_needed) * size_needed);
9754 : : }
9755 : : else
9756 : : {
9757 : 17586 : if (!issetmem)
9758 : 12988 : src = change_address (src, BLKmode, srcreg);
9759 : 17586 : dst = change_address (dst, BLKmode, destreg);
9760 : : }
9761 : :
9762 : : /* Step 4: Epilogue to copy the remaining bytes. */
9763 : 57825 : epilogue:
9764 : 57825 : if (label)
9765 : : {
9766 : : /* When the main loop is done, COUNT_EXP might hold original count,
9767 : : while we want to copy only COUNT_EXP & SIZE_NEEDED bytes.
9768 : : Epilogue code will actually copy COUNT_EXP & EPILOGUE_SIZE_NEEDED
9769 : : bytes. Compensate if needed. */
9770 : :
9771 : 2193 : if (size_needed < epilogue_size_needed)
9772 : : {
9773 : 0 : tmp = expand_simple_binop (counter_mode (count_exp), AND, count_exp,
9774 : 0 : GEN_INT (size_needed - 1), count_exp, 1,
9775 : : OPTAB_DIRECT);
9776 : 0 : if (tmp != count_exp)
9777 : 0 : emit_move_insn (count_exp, tmp);
9778 : : }
9779 : 2193 : emit_label (label);
9780 : 2193 : LABEL_NUSES (label) = 1;
9781 : : }
9782 : :
9783 : 57825 : if (count_exp != const0_rtx && epilogue_size_needed > 1)
9784 : : {
9785 : 42434 : if (force_loopy_epilogue)
9786 : 275 : expand_setmem_epilogue_via_loop (dst, destreg, val_exp, count_exp,
9787 : : epilogue_size_needed);
9788 : : else
9789 : : {
9790 : 42159 : if (issetmem)
9791 : 18914 : expand_setmem_epilogue (dst, destreg, promoted_val,
9792 : : vec_promoted_val, count_exp,
9793 : : epilogue_size_needed);
9794 : : else
9795 : 23245 : expand_cpymem_epilogue (dst, src, destreg, srcreg, count_exp,
9796 : : epilogue_size_needed);
9797 : : }
9798 : : }
9799 : 57825 : if (jump_around_label)
9800 : 6046 : emit_label (jump_around_label);
9801 : : return true;
9802 : : }
9803 : :
9804 : : /* Expand cmpstrn or memcmp. */
9805 : :
9806 : : bool
9807 : 205182 : ix86_expand_cmpstrn_or_cmpmem (rtx result, rtx src1, rtx src2,
9808 : : rtx length, rtx align, bool is_cmpstrn)
9809 : : {
9810 : : /* Expand strncmp and memcmp only with -minline-all-stringops since
9811 : : "repz cmpsb" can be much slower than strncmp and memcmp functions
9812 : : implemented with vector instructions, see
9813 : :
9814 : : https://gcc.gnu.org/bugzilla/show_bug.cgi?id=43052
9815 : : */
9816 : 205182 : if (!TARGET_INLINE_ALL_STRINGOPS)
9817 : : return false;
9818 : :
9819 : : /* Can't use this if the user has appropriated ecx, esi or edi. */
9820 : 5777 : if (fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG])
9821 : : return false;
9822 : :
9823 : 5777 : if (is_cmpstrn)
9824 : : {
9825 : : /* For strncmp, length is the maximum length, which can be larger
9826 : : than actual string lengths. We can expand the cmpstrn pattern
9827 : : to "repz cmpsb" only if one of the strings is a constant so
9828 : : that expand_builtin_strncmp() can write the length argument to
9829 : : be the minimum of the const string length and the actual length
9830 : : argument. Otherwise, "repz cmpsb" may pass the 0 byte. */
9831 : 73 : tree t1 = MEM_EXPR (src1);
9832 : 73 : tree t2 = MEM_EXPR (src2);
9833 : 146 : if (!((t1 && TREE_CODE (t1) == MEM_REF
9834 : 73 : && TREE_CODE (TREE_OPERAND (t1, 0)) == ADDR_EXPR
9835 : 0 : && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (t1, 0), 0))
9836 : : == STRING_CST))
9837 : 73 : || (t2 && TREE_CODE (t2) == MEM_REF
9838 : 73 : && TREE_CODE (TREE_OPERAND (t2, 0)) == ADDR_EXPR
9839 : 73 : && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (t2, 0), 0))
9840 : : == STRING_CST))))
9841 : : return false;
9842 : : }
9843 : :
9844 : 5777 : rtx addr1 = copy_addr_to_reg (XEXP (src1, 0));
9845 : 5777 : rtx addr2 = copy_addr_to_reg (XEXP (src2, 0));
9846 : 5777 : if (addr1 != XEXP (src1, 0))
9847 : 5777 : src1 = replace_equiv_address_nv (src1, addr1);
9848 : 5777 : if (addr2 != XEXP (src2, 0))
9849 : 5777 : src2 = replace_equiv_address_nv (src2, addr2);
9850 : :
9851 : : /* NB: Make a copy of the data length to avoid changing the original
9852 : : data length by cmpstrnqi patterns. */
9853 : 5777 : length = ix86_zero_extend_to_Pmode (length);
9854 : 8663 : rtx lengthreg = gen_reg_rtx (Pmode);
9855 : 5777 : emit_move_insn (lengthreg, length);
9856 : :
9857 : : /* If we are testing strict equality, we can use known alignment to
9858 : : good advantage. This may be possible with combine, particularly
9859 : : once cc0 is dead. */
9860 : 5777 : if (CONST_INT_P (length))
9861 : : {
9862 : 0 : if (length == const0_rtx)
9863 : : {
9864 : 0 : emit_move_insn (result, const0_rtx);
9865 : 0 : return true;
9866 : : }
9867 : 0 : emit_insn (gen_cmpstrnqi_nz_1 (addr1, addr2, lengthreg, align,
9868 : : src1, src2));
9869 : : }
9870 : : else
9871 : : {
9872 : 8663 : emit_insn (gen_cmp_1 (Pmode, lengthreg, lengthreg));
9873 : 5777 : emit_insn (gen_cmpstrnqi_1 (addr1, addr2, lengthreg, align,
9874 : : src1, src2));
9875 : : }
9876 : :
9877 : 5777 : rtx out = gen_lowpart (QImode, result);
9878 : 5777 : emit_insn (gen_cmpintqi (out));
9879 : 5777 : emit_move_insn (result, gen_rtx_SIGN_EXTEND (SImode, out));
9880 : :
9881 : 5777 : return true;
9882 : : }
9883 : :
9884 : : /* Expand the appropriate insns for doing strlen if not just doing
9885 : : repnz; scasb
9886 : :
9887 : : out = result, initialized with the start address
9888 : : align_rtx = alignment of the address.
9889 : : scratch = scratch register, initialized with the startaddress when
9890 : : not aligned, otherwise undefined
9891 : :
9892 : : This is just the body. It needs the initializations mentioned above and
9893 : : some address computing at the end. These things are done in i386.md. */
9894 : :
9895 : : static void
9896 : 11 : ix86_expand_strlensi_unroll_1 (rtx out, rtx src, rtx align_rtx)
9897 : : {
9898 : 11 : int align;
9899 : 11 : rtx tmp;
9900 : 11 : rtx_code_label *align_2_label = NULL;
9901 : 11 : rtx_code_label *align_3_label = NULL;
9902 : 11 : rtx_code_label *align_4_label = gen_label_rtx ();
9903 : 11 : rtx_code_label *end_0_label = gen_label_rtx ();
9904 : 11 : rtx mem;
9905 : 11 : rtx tmpreg = gen_reg_rtx (SImode);
9906 : 11 : rtx scratch = gen_reg_rtx (SImode);
9907 : 11 : rtx cmp;
9908 : :
9909 : 11 : align = 0;
9910 : 11 : if (CONST_INT_P (align_rtx))
9911 : 11 : align = INTVAL (align_rtx);
9912 : :
9913 : : /* Loop to check 1..3 bytes for null to get an aligned pointer. */
9914 : :
9915 : : /* Is there a known alignment and is it less than 4? */
9916 : 11 : if (align < 4)
9917 : : {
9918 : 15 : rtx scratch1 = gen_reg_rtx (Pmode);
9919 : 11 : emit_move_insn (scratch1, out);
9920 : : /* Is there a known alignment and is it not 2? */
9921 : 11 : if (align != 2)
9922 : : {
9923 : 11 : align_3_label = gen_label_rtx (); /* Label when aligned to 3-byte */
9924 : 11 : align_2_label = gen_label_rtx (); /* Label when aligned to 2-byte */
9925 : :
9926 : : /* Leave just the 3 lower bits. */
9927 : 15 : align_rtx = expand_binop (Pmode, and_optab, scratch1, GEN_INT (3),
9928 : : NULL_RTX, 0, OPTAB_WIDEN);
9929 : :
9930 : 15 : emit_cmp_and_jump_insns (align_rtx, const0_rtx, EQ, NULL,
9931 : 11 : Pmode, 1, align_4_label);
9932 : 15 : emit_cmp_and_jump_insns (align_rtx, const2_rtx, EQ, NULL,
9933 : 11 : Pmode, 1, align_2_label);
9934 : 15 : emit_cmp_and_jump_insns (align_rtx, const2_rtx, GTU, NULL,
9935 : 11 : Pmode, 1, align_3_label);
9936 : : }
9937 : : else
9938 : : {
9939 : : /* Since the alignment is 2, we have to check 2 or 0 bytes;
9940 : : check if is aligned to 4 - byte. */
9941 : :
9942 : 0 : align_rtx = expand_binop (Pmode, and_optab, scratch1, const2_rtx,
9943 : : NULL_RTX, 0, OPTAB_WIDEN);
9944 : :
9945 : 0 : emit_cmp_and_jump_insns (align_rtx, const0_rtx, EQ, NULL,
9946 : 0 : Pmode, 1, align_4_label);
9947 : : }
9948 : :
9949 : 11 : mem = change_address (src, QImode, out);
9950 : :
9951 : : /* Now compare the bytes. */
9952 : :
9953 : : /* Compare the first n unaligned byte on a byte per byte basis. */
9954 : 11 : emit_cmp_and_jump_insns (mem, const0_rtx, EQ, NULL,
9955 : : QImode, 1, end_0_label);
9956 : :
9957 : : /* Increment the address. */
9958 : 11 : emit_insn (gen_add2_insn (out, const1_rtx));
9959 : :
9960 : : /* Not needed with an alignment of 2 */
9961 : 11 : if (align != 2)
9962 : : {
9963 : 11 : emit_label (align_2_label);
9964 : :
9965 : 11 : emit_cmp_and_jump_insns (mem, const0_rtx, EQ, NULL, QImode, 1,
9966 : : end_0_label);
9967 : :
9968 : 11 : emit_insn (gen_add2_insn (out, const1_rtx));
9969 : :
9970 : 11 : emit_label (align_3_label);
9971 : : }
9972 : :
9973 : 11 : emit_cmp_and_jump_insns (mem, const0_rtx, EQ, NULL, QImode, 1,
9974 : : end_0_label);
9975 : :
9976 : 11 : emit_insn (gen_add2_insn (out, const1_rtx));
9977 : : }
9978 : :
9979 : : /* Generate loop to check 4 bytes at a time. It is not a good idea to
9980 : : align this loop. It gives only huge programs, but does not help to
9981 : : speed up. */
9982 : 11 : emit_label (align_4_label);
9983 : :
9984 : 11 : mem = change_address (src, SImode, out);
9985 : 11 : emit_move_insn (scratch, mem);
9986 : 11 : emit_insn (gen_add2_insn (out, GEN_INT (4)));
9987 : :
9988 : : /* This formula yields a nonzero result iff one of the bytes is zero.
9989 : : This saves three branches inside loop and many cycles. */
9990 : :
9991 : 11 : emit_insn (gen_addsi3 (tmpreg, scratch, GEN_INT (-0x01010101)));
9992 : 11 : emit_insn (gen_one_cmplsi2 (scratch, scratch));
9993 : 11 : emit_insn (gen_andsi3 (tmpreg, tmpreg, scratch));
9994 : 11 : emit_insn (gen_andsi3 (tmpreg, tmpreg,
9995 : : gen_int_mode (0x80808080, SImode)));
9996 : 11 : emit_cmp_and_jump_insns (tmpreg, const0_rtx, EQ, 0, SImode, 1,
9997 : : align_4_label);
9998 : :
9999 : 11 : if (TARGET_CMOVE)
10000 : : {
10001 : 11 : rtx reg = gen_reg_rtx (SImode);
10002 : 15 : rtx reg2 = gen_reg_rtx (Pmode);
10003 : 11 : emit_move_insn (reg, tmpreg);
10004 : 11 : emit_insn (gen_lshrsi3 (reg, reg, GEN_INT (16)));
10005 : :
10006 : : /* If zero is not in the first two bytes, move two bytes forward. */
10007 : 11 : emit_insn (gen_testsi_ccno_1 (tmpreg, GEN_INT (0x8080)));
10008 : 11 : tmp = gen_rtx_REG (CCNOmode, FLAGS_REG);
10009 : 11 : tmp = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
10010 : 11 : emit_insn (gen_rtx_SET (tmpreg,
10011 : : gen_rtx_IF_THEN_ELSE (SImode, tmp,
10012 : : reg,
10013 : : tmpreg)));
10014 : : /* Emit lea manually to avoid clobbering of flags. */
10015 : 15 : emit_insn (gen_rtx_SET (reg2, plus_constant (Pmode, out, 2)));
10016 : :
10017 : 11 : tmp = gen_rtx_REG (CCNOmode, FLAGS_REG);
10018 : 11 : tmp = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
10019 : 15 : emit_insn (gen_rtx_SET (out,
10020 : : gen_rtx_IF_THEN_ELSE (Pmode, tmp,
10021 : : reg2,
10022 : : out)));
10023 : 11 : }
10024 : : else
10025 : : {
10026 : 0 : rtx_code_label *end_2_label = gen_label_rtx ();
10027 : : /* Is zero in the first two bytes? */
10028 : :
10029 : 0 : emit_insn (gen_testsi_ccno_1 (tmpreg, GEN_INT (0x8080)));
10030 : 0 : tmp = gen_rtx_REG (CCNOmode, FLAGS_REG);
10031 : 0 : tmp = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
10032 : 0 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
10033 : : gen_rtx_LABEL_REF (VOIDmode, end_2_label),
10034 : : pc_rtx);
10035 : 0 : tmp = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
10036 : 0 : JUMP_LABEL (tmp) = end_2_label;
10037 : :
10038 : : /* Not in the first two. Move two bytes forward. */
10039 : 0 : emit_insn (gen_lshrsi3 (tmpreg, tmpreg, GEN_INT (16)));
10040 : 0 : emit_insn (gen_add2_insn (out, const2_rtx));
10041 : :
10042 : 0 : emit_label (end_2_label);
10043 : :
10044 : : }
10045 : :
10046 : : /* Avoid branch in fixing the byte. */
10047 : 11 : tmpreg = gen_lowpart (QImode, tmpreg);
10048 : 11 : emit_insn (gen_addqi3_cconly_overflow (tmpreg, tmpreg));
10049 : 11 : tmp = gen_rtx_REG (CCmode, FLAGS_REG);
10050 : 11 : cmp = gen_rtx_LTU (VOIDmode, tmp, const0_rtx);
10051 : 15 : emit_insn (gen_sub3_carry (Pmode, out, out, GEN_INT (3), tmp, cmp));
10052 : :
10053 : 11 : emit_label (end_0_label);
10054 : 11 : }
10055 : :
10056 : : /* Expand strlen. */
10057 : :
10058 : : bool
10059 : 13622 : ix86_expand_strlen (rtx out, rtx src, rtx eoschar, rtx align)
10060 : : {
10061 : 13622 : if (TARGET_UNROLL_STRLEN
10062 : 13622 : && TARGET_INLINE_ALL_STRINGOPS
10063 : 11 : && eoschar == const0_rtx
10064 : 11 : && optimize > 1)
10065 : : {
10066 : : /* The generic case of strlen expander is long. Avoid it's
10067 : : expanding unless TARGET_INLINE_ALL_STRINGOPS. */
10068 : 15 : rtx addr = force_reg (Pmode, XEXP (src, 0));
10069 : : /* Well it seems that some optimizer does not combine a call like
10070 : : foo(strlen(bar), strlen(bar));
10071 : : when the move and the subtraction is done here. It does calculate
10072 : : the length just once when these instructions are done inside of
10073 : : output_strlen_unroll(). But I think since &bar[strlen(bar)] is
10074 : : often used and I use one fewer register for the lifetime of
10075 : : output_strlen_unroll() this is better. */
10076 : :
10077 : 11 : emit_move_insn (out, addr);
10078 : :
10079 : 11 : ix86_expand_strlensi_unroll_1 (out, src, align);
10080 : :
10081 : : /* strlensi_unroll_1 returns the address of the zero at the end of
10082 : : the string, like memchr(), so compute the length by subtracting
10083 : : the start address. */
10084 : 11 : emit_insn (gen_sub2_insn (out, addr));
10085 : 11 : return true;
10086 : : }
10087 : : else
10088 : : return false;
10089 : : }
10090 : :
10091 : : /* For given symbol (function) construct code to compute address of it's PLT
10092 : : entry in large x86-64 PIC model. */
10093 : :
10094 : : static rtx
10095 : 31 : construct_plt_address (rtx symbol)
10096 : : {
10097 : 31 : rtx tmp, unspec;
10098 : :
10099 : 31 : gcc_assert (GET_CODE (symbol) == SYMBOL_REF);
10100 : 31 : gcc_assert (ix86_cmodel == CM_LARGE_PIC && !TARGET_PECOFF);
10101 : 31 : gcc_assert (Pmode == DImode);
10102 : :
10103 : 31 : tmp = gen_reg_rtx (Pmode);
10104 : 31 : unspec = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, symbol), UNSPEC_PLTOFF);
10105 : :
10106 : 31 : emit_move_insn (tmp, gen_rtx_CONST (Pmode, unspec));
10107 : 31 : emit_insn (gen_add2_insn (tmp, pic_offset_table_rtx));
10108 : 31 : return tmp;
10109 : : }
10110 : :
10111 : : /* Additional registers that are clobbered by SYSV calls. */
10112 : :
10113 : : static int const x86_64_ms_sysv_extra_clobbered_registers
10114 : : [NUM_X86_64_MS_CLOBBERED_REGS] =
10115 : : {
10116 : : SI_REG, DI_REG,
10117 : : XMM6_REG, XMM7_REG,
10118 : : XMM8_REG, XMM9_REG, XMM10_REG, XMM11_REG,
10119 : : XMM12_REG, XMM13_REG, XMM14_REG, XMM15_REG
10120 : : };
10121 : :
10122 : : rtx_insn *
10123 : 6196817 : ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1,
10124 : : rtx callarg2,
10125 : : rtx pop, bool sibcall)
10126 : : {
10127 : 6196817 : rtx vec[3];
10128 : 6196817 : rtx use = NULL, call;
10129 : 6196817 : unsigned int vec_len = 0;
10130 : 6196817 : tree fndecl;
10131 : 6196817 : bool call_no_callee_saved_registers = false;
10132 : :
10133 : 6196817 : if (GET_CODE (XEXP (fnaddr, 0)) == SYMBOL_REF)
10134 : : {
10135 : 6007684 : fndecl = SYMBOL_REF_DECL (XEXP (fnaddr, 0));
10136 : 6007684 : if (fndecl)
10137 : : {
10138 : 5747894 : if (lookup_attribute ("interrupt",
10139 : 5747894 : TYPE_ATTRIBUTES (TREE_TYPE (fndecl))))
10140 : 1 : error ("interrupt service routine cannot be called directly");
10141 : 5747893 : else if (lookup_attribute ("no_callee_saved_registers",
10142 : 5747893 : TYPE_ATTRIBUTES (TREE_TYPE (fndecl))))
10143 : 10 : call_no_callee_saved_registers = true;
10144 : : }
10145 : : }
10146 : : else
10147 : : {
10148 : 189133 : if (MEM_P (fnaddr))
10149 : : {
10150 : 189133 : tree mem_expr = MEM_EXPR (fnaddr);
10151 : 189133 : if (mem_expr != nullptr
10152 : 189088 : && TREE_CODE (mem_expr) == MEM_REF
10153 : 378221 : && lookup_attribute ("no_callee_saved_registers",
10154 : 189088 : TYPE_ATTRIBUTES (TREE_TYPE (mem_expr))))
10155 : : call_no_callee_saved_registers = true;
10156 : : }
10157 : :
10158 : : fndecl = NULL_TREE;
10159 : : }
10160 : :
10161 : 6196817 : if (pop == const0_rtx)
10162 : 0 : pop = NULL;
10163 : 6196817 : gcc_assert (!TARGET_64BIT || !pop);
10164 : :
10165 : 6196817 : rtx addr = XEXP (fnaddr, 0);
10166 : 6196817 : if (TARGET_MACHO && !TARGET_64BIT)
10167 : : {
10168 : : #if TARGET_MACHO
10169 : : if (flag_pic && GET_CODE (XEXP (fnaddr, 0)) == SYMBOL_REF)
10170 : : fnaddr = machopic_indirect_call_target (fnaddr);
10171 : : #endif
10172 : : }
10173 : : else
10174 : : {
10175 : : /* Static functions and indirect calls don't need the pic register. Also,
10176 : : check if PLT was explicitly avoided via no-plt or "noplt" attribute, making
10177 : : it an indirect call. */
10178 : 6196817 : if (flag_pic
10179 : 507703 : && GET_CODE (addr) == SYMBOL_REF
10180 : 6678657 : && ix86_call_use_plt_p (addr))
10181 : : {
10182 : 385515 : if (flag_plt
10183 : 385515 : && (SYMBOL_REF_DECL (addr) == NULL_TREE
10184 : 385481 : || !lookup_attribute ("noplt",
10185 : 385481 : DECL_ATTRIBUTES (SYMBOL_REF_DECL (addr)))))
10186 : : {
10187 : 385480 : if (!TARGET_64BIT
10188 : 210558 : || (ix86_cmodel == CM_LARGE_PIC
10189 : : && DEFAULT_ABI != MS_ABI))
10190 : : {
10191 : 524797 : use_reg (&use, gen_rtx_REG (Pmode,
10192 : : REAL_PIC_OFFSET_TABLE_REGNUM));
10193 : 174953 : if (ix86_use_pseudo_pic_reg ())
10194 : 349875 : emit_move_insn (gen_rtx_REG (Pmode,
10195 : 174953 : REAL_PIC_OFFSET_TABLE_REGNUM),
10196 : : pic_offset_table_rtx);
10197 : : }
10198 : : }
10199 : 35 : else if (!TARGET_PECOFF && !TARGET_MACHO)
10200 : : {
10201 : 35 : if (TARGET_64BIT
10202 : 35 : && ix86_cmodel == CM_LARGE_PIC
10203 : : && DEFAULT_ABI != MS_ABI)
10204 : : {
10205 : 1 : fnaddr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr),
10206 : : UNSPEC_GOT);
10207 : 1 : fnaddr = gen_rtx_CONST (Pmode, fnaddr);
10208 : 1 : fnaddr = force_reg (Pmode, fnaddr);
10209 : 1 : fnaddr = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, fnaddr);
10210 : : }
10211 : 34 : else if (TARGET_64BIT)
10212 : : {
10213 : 38 : fnaddr = gen_rtx_UNSPEC (Pmode,
10214 : : gen_rtvec (1, addr),
10215 : : UNSPEC_GOTPCREL);
10216 : 38 : fnaddr = gen_rtx_CONST (Pmode, fnaddr);
10217 : : }
10218 : : else
10219 : : {
10220 : 0 : fnaddr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr),
10221 : : UNSPEC_GOT);
10222 : 0 : fnaddr = gen_rtx_CONST (Pmode, fnaddr);
10223 : 0 : fnaddr = gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
10224 : : fnaddr);
10225 : : }
10226 : 39 : fnaddr = gen_const_mem (Pmode, fnaddr);
10227 : : /* Pmode may not be the same as word_mode for x32, which
10228 : : doesn't support indirect branch via 32-bit memory slot.
10229 : : Since x32 GOT slot is 64 bit with zero upper 32 bits,
10230 : : indirect branch via x32 GOT slot is OK. */
10231 : 35 : if (GET_MODE (fnaddr) != word_mode)
10232 : 4 : fnaddr = gen_rtx_ZERO_EXTEND (word_mode, fnaddr);
10233 : 35 : fnaddr = gen_rtx_MEM (QImode, fnaddr);
10234 : : }
10235 : : }
10236 : : }
10237 : :
10238 : : /* Skip setting up RAX register for -mskip-rax-setup when there are no
10239 : : parameters passed in vector registers. */
10240 : 6196817 : if (TARGET_64BIT
10241 : 5364804 : && (INTVAL (callarg2) > 0
10242 : 5303681 : || (INTVAL (callarg2) == 0
10243 : 317051 : && (TARGET_SSE || !flag_skip_rax_setup))))
10244 : : {
10245 : 378172 : rtx al = gen_rtx_REG (QImode, AX_REG);
10246 : 378172 : emit_move_insn (al, callarg2);
10247 : 378172 : use_reg (&use, al);
10248 : : }
10249 : :
10250 : 6196817 : if (ix86_cmodel == CM_LARGE_PIC
10251 : : && !TARGET_PECOFF
10252 : 41 : && MEM_P (fnaddr)
10253 : 41 : && GET_CODE (XEXP (fnaddr, 0)) == SYMBOL_REF
10254 : 6196850 : && !local_symbolic_operand (XEXP (fnaddr, 0), VOIDmode))
10255 : 31 : fnaddr = gen_rtx_MEM (QImode, construct_plt_address (XEXP (fnaddr, 0)));
10256 : : /* Since x32 GOT slot is 64 bit with zero upper 32 bits, indirect
10257 : : branch via x32 GOT slot is OK. */
10258 : 6196786 : else if (TARGET_X32
10259 : 67 : && MEM_P (fnaddr)
10260 : 67 : && GET_CODE (XEXP (fnaddr, 0)) == ZERO_EXTEND
10261 : 8 : && GOT_memory_operand (XEXP (XEXP (fnaddr, 0), 0), Pmode)
10262 : 6196790 : && !TARGET_INDIRECT_BRANCH_REGISTER)
10263 : : ;
10264 : 6196786 : else if (sibcall
10265 : 6196786 : ? !sibcall_insn_operand (XEXP (fnaddr, 0), word_mode)
10266 : 6072128 : : !call_insn_operand (XEXP (fnaddr, 0), word_mode))
10267 : : {
10268 : 524 : fnaddr = convert_to_mode (word_mode, XEXP (fnaddr, 0), 1);
10269 : 524 : fnaddr = gen_rtx_MEM (QImode, copy_to_mode_reg (word_mode, fnaddr));
10270 : : }
10271 : :
10272 : : /* PR100665: Hwasan may tag code pointer which is not supported by LAM,
10273 : : mask off code pointers here.
10274 : : TODO: also need to handle indirect jump. */
10275 : 6197903 : if (ix86_memtag_can_tag_addresses () && !fndecl
10276 : 6196841 : && sanitize_flags_p (SANITIZE_HWADDRESS))
10277 : : {
10278 : 24 : rtx untagged_addr = ix86_memtag_untagged_pointer (XEXP (fnaddr, 0),
10279 : : NULL_RTX);
10280 : 24 : fnaddr = gen_rtx_MEM (QImode, untagged_addr);
10281 : : }
10282 : :
10283 : 6196817 : call = gen_rtx_CALL (VOIDmode, fnaddr, callarg1);
10284 : :
10285 : 6196817 : if (retval)
10286 : 2462711 : call = gen_rtx_SET (retval, call);
10287 : 6196817 : vec[vec_len++] = call;
10288 : :
10289 : 6196817 : if (pop)
10290 : : {
10291 : 449036 : pop = gen_rtx_PLUS (Pmode, stack_pointer_rtx, pop);
10292 : 224518 : pop = gen_rtx_SET (stack_pointer_rtx, pop);
10293 : 224518 : vec[vec_len++] = pop;
10294 : : }
10295 : :
10296 : 6196817 : static const char ix86_call_used_regs[] = CALL_USED_REGISTERS;
10297 : :
10298 : 6196817 : if ((cfun->machine->call_saved_registers
10299 : 6196817 : == TYPE_NO_CALLER_SAVED_REGISTERS)
10300 : 6196817 : && (!fndecl
10301 : 464 : || (!TREE_THIS_VOLATILE (fndecl)
10302 : 182 : && !lookup_attribute ("no_caller_saved_registers",
10303 : 182 : TYPE_ATTRIBUTES (TREE_TYPE (fndecl))))))
10304 : : {
10305 : 174 : bool is_64bit_ms_abi = (TARGET_64BIT
10306 : 174 : && ix86_function_abi (fndecl) == MS_ABI);
10307 : 174 : char c_mask = CALL_USED_REGISTERS_MASK (is_64bit_ms_abi);
10308 : :
10309 : : /* If there are no caller-saved registers, add all registers
10310 : : that are clobbered by the call which returns. */
10311 : 16182 : for (int i = 0; i < FIRST_PSEUDO_REGISTER; i++)
10312 : 16008 : if (!fixed_regs[i]
10313 : 3010 : && (ix86_call_used_regs[i] == 1
10314 : 1392 : || (ix86_call_used_regs[i] & c_mask))
10315 : 1966 : && !STACK_REGNO_P (i)
10316 : 1966 : && !MMX_REGNO_P (i))
10317 : 1966 : clobber_reg (&use,
10318 : 1966 : gen_rtx_REG (GET_MODE (regno_reg_rtx[i]), i));
10319 : : }
10320 : 5364630 : else if (TARGET_64BIT_MS_ABI
10321 : 6270045 : && (!callarg2 || INTVAL (callarg2) != -2))
10322 : : {
10323 : : unsigned i;
10324 : :
10325 : 861705 : for (i = 0; i < NUM_X86_64_MS_CLOBBERED_REGS; i++)
10326 : : {
10327 : 795420 : int regno = x86_64_ms_sysv_extra_clobbered_registers[i];
10328 : 795420 : machine_mode mode = SSE_REGNO_P (regno) ? TImode : DImode;
10329 : :
10330 : 795420 : clobber_reg (&use, gen_rtx_REG (mode, regno));
10331 : : }
10332 : :
10333 : : /* Set here, but it may get cleared later. */
10334 : 66285 : if (TARGET_CALL_MS2SYSV_XLOGUES)
10335 : : {
10336 : 7046 : if (!TARGET_SSE)
10337 : : ;
10338 : :
10339 : : /* Don't break hot-patched functions. */
10340 : 7046 : else if (ix86_function_ms_hook_prologue (current_function_decl))
10341 : : ;
10342 : :
10343 : : /* TODO: Cases not yet examined. */
10344 : 7046 : else if (flag_split_stack)
10345 : 0 : warn_once_call_ms2sysv_xlogues ("-fsplit-stack");
10346 : :
10347 : : else
10348 : : {
10349 : 7046 : gcc_assert (!reload_completed);
10350 : 7046 : cfun->machine->call_ms2sysv = true;
10351 : : }
10352 : : }
10353 : : }
10354 : :
10355 : 6196817 : if (TARGET_MACHO && TARGET_64BIT && !sibcall
10356 : : && ((GET_CODE (addr) == SYMBOL_REF && !SYMBOL_REF_LOCAL_P (addr))
10357 : : || !fndecl || TREE_PUBLIC (fndecl)))
10358 : : {
10359 : : /* We allow public functions defined in a TU to bind locally for PIC
10360 : : code (the default) on 64bit Mach-O.
10361 : : If such functions are not inlined, we cannot tell at compile-time if
10362 : : they will be called via the lazy symbol resolver (this can depend on
10363 : : options given at link-time). Therefore, we must assume that the lazy
10364 : : resolver could be used which clobbers R11 and R10. */
10365 : : clobber_reg (&use, gen_rtx_REG (DImode, R11_REG));
10366 : : clobber_reg (&use, gen_rtx_REG (DImode, R10_REG));
10367 : : }
10368 : :
10369 : 6196817 : if (call_no_callee_saved_registers)
10370 : : {
10371 : : /* After calling a no_callee_saved_registers function, all
10372 : : registers may be clobbered. Clobber all registers that are
10373 : : not used by the callee. */
10374 : 18 : bool is_64bit_ms_abi = (TARGET_64BIT
10375 : 18 : && ix86_function_abi (fndecl) == MS_ABI);
10376 : 18 : char c_mask = CALL_USED_REGISTERS_MASK (is_64bit_ms_abi);
10377 : 1674 : for (int i = 0; i < FIRST_PSEUDO_REGISTER; i++)
10378 : 1656 : if (!fixed_regs[i]
10379 : 798 : && !(ix86_call_used_regs[i] == 1
10380 : 304 : || (ix86_call_used_regs[i] & c_mask))
10381 : 108 : && !STACK_REGNO_P (i)
10382 : 108 : && !MMX_REGNO_P (i))
10383 : 108 : clobber_reg (&use,
10384 : 108 : gen_rtx_REG (GET_MODE (regno_reg_rtx[i]), i));
10385 : : }
10386 : :
10387 : 6196817 : if (vec_len > 1)
10388 : 224518 : call = gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (vec_len, vec));
10389 : 6196817 : rtx_insn *call_insn = emit_call_insn (call);
10390 : 6196817 : if (use)
10391 : 593510 : CALL_INSN_FUNCTION_USAGE (call_insn) = use;
10392 : :
10393 : 6196817 : return call_insn;
10394 : : }
10395 : :
10396 : : /* Split simple return with popping POPC bytes from stack to indirect
10397 : : branch with stack adjustment . */
10398 : :
10399 : : void
10400 : 0 : ix86_split_simple_return_pop_internal (rtx popc)
10401 : : {
10402 : 0 : struct machine_function *m = cfun->machine;
10403 : 0 : rtx ecx = gen_rtx_REG (SImode, CX_REG);
10404 : 0 : rtx_insn *insn;
10405 : :
10406 : : /* There is no "pascal" calling convention in any 64bit ABI. */
10407 : 0 : gcc_assert (!TARGET_64BIT);
10408 : :
10409 : 0 : insn = emit_insn (gen_pop (ecx));
10410 : 0 : m->fs.cfa_offset -= UNITS_PER_WORD;
10411 : 0 : m->fs.sp_offset -= UNITS_PER_WORD;
10412 : :
10413 : 0 : rtx x = plus_constant (Pmode, stack_pointer_rtx, UNITS_PER_WORD);
10414 : 0 : x = gen_rtx_SET (stack_pointer_rtx, x);
10415 : 0 : add_reg_note (insn, REG_CFA_ADJUST_CFA, x);
10416 : 0 : add_reg_note (insn, REG_CFA_REGISTER, gen_rtx_SET (ecx, pc_rtx));
10417 : 0 : RTX_FRAME_RELATED_P (insn) = 1;
10418 : :
10419 : 0 : x = gen_rtx_PLUS (Pmode, stack_pointer_rtx, popc);
10420 : 0 : x = gen_rtx_SET (stack_pointer_rtx, x);
10421 : 0 : insn = emit_insn (x);
10422 : 0 : add_reg_note (insn, REG_CFA_ADJUST_CFA, x);
10423 : 0 : RTX_FRAME_RELATED_P (insn) = 1;
10424 : :
10425 : : /* Now return address is in ECX. */
10426 : 0 : emit_jump_insn (gen_simple_return_indirect_internal (ecx));
10427 : 0 : }
10428 : :
10429 : : /* Errors in the source file can cause expand_expr to return const0_rtx
10430 : : where we expect a vector. To avoid crashing, use one of the vector
10431 : : clear instructions. */
10432 : :
10433 : : static rtx
10434 : 193077 : safe_vector_operand (rtx x, machine_mode mode)
10435 : : {
10436 : 0 : if (x == const0_rtx)
10437 : 0 : x = CONST0_RTX (mode);
10438 : 24 : return x;
10439 : : }
10440 : :
10441 : : /* Subroutine of ix86_expand_builtin to take care of binop insns. */
10442 : :
10443 : : static rtx
10444 : 8956 : ix86_expand_binop_builtin (enum insn_code icode, tree exp, rtx target)
10445 : : {
10446 : 8956 : rtx pat;
10447 : 8956 : tree arg0 = CALL_EXPR_ARG (exp, 0);
10448 : 8956 : tree arg1 = CALL_EXPR_ARG (exp, 1);
10449 : 8956 : rtx op0 = expand_normal (arg0);
10450 : 8956 : rtx op1 = expand_normal (arg1);
10451 : 8956 : machine_mode tmode = insn_data[icode].operand[0].mode;
10452 : 8956 : machine_mode mode0 = insn_data[icode].operand[1].mode;
10453 : 8956 : machine_mode mode1 = insn_data[icode].operand[2].mode;
10454 : :
10455 : 8956 : if (VECTOR_MODE_P (mode0))
10456 : 8951 : op0 = safe_vector_operand (op0, mode0);
10457 : 8956 : if (VECTOR_MODE_P (mode1))
10458 : 8815 : op1 = safe_vector_operand (op1, mode1);
10459 : :
10460 : 2868 : if (optimize || !target
10461 : 2868 : || GET_MODE (target) != tmode
10462 : 11824 : || !insn_data[icode].operand[0].predicate (target, tmode))
10463 : 6141 : target = gen_reg_rtx (tmode);
10464 : :
10465 : 8956 : if (GET_MODE (op1) == SImode && mode1 == TImode)
10466 : : {
10467 : 0 : rtx x = gen_reg_rtx (V4SImode);
10468 : 0 : emit_insn (gen_sse2_loadd (x, op1));
10469 : 0 : op1 = gen_lowpart (TImode, x);
10470 : : }
10471 : :
10472 : 8956 : if (!insn_data[icode].operand[1].predicate (op0, mode0))
10473 : 1414 : op0 = copy_to_mode_reg (mode0, op0);
10474 : 8956 : if (!insn_data[icode].operand[2].predicate (op1, mode1))
10475 : 815 : op1 = copy_to_mode_reg (mode1, op1);
10476 : :
10477 : 8956 : pat = GEN_FCN (icode) (target, op0, op1);
10478 : 8956 : if (! pat)
10479 : : return 0;
10480 : :
10481 : 8956 : emit_insn (pat);
10482 : :
10483 : 8956 : return target;
10484 : : }
10485 : :
10486 : : /* Subroutine of ix86_expand_builtin to take care of 2-4 argument insns. */
10487 : :
10488 : : static rtx
10489 : 1790 : ix86_expand_multi_arg_builtin (enum insn_code icode, tree exp, rtx target,
10490 : : enum ix86_builtin_func_type m_type,
10491 : : enum rtx_code sub_code)
10492 : : {
10493 : 1790 : rtx pat;
10494 : 1790 : unsigned int i, nargs;
10495 : 1790 : bool comparison_p = false;
10496 : 1790 : bool tf_p = false;
10497 : 1790 : bool last_arg_constant = false;
10498 : 1790 : int num_memory = 0;
10499 : 1790 : rtx xops[4];
10500 : :
10501 : 1790 : machine_mode tmode = insn_data[icode].operand[0].mode;
10502 : :
10503 : 1790 : switch (m_type)
10504 : : {
10505 : : case MULTI_ARG_4_DF2_DI_I:
10506 : : case MULTI_ARG_4_DF2_DI_I1:
10507 : : case MULTI_ARG_4_SF2_SI_I:
10508 : : case MULTI_ARG_4_SF2_SI_I1:
10509 : : nargs = 4;
10510 : : last_arg_constant = true;
10511 : : break;
10512 : :
10513 : 819 : case MULTI_ARG_3_SF:
10514 : 819 : case MULTI_ARG_3_DF:
10515 : 819 : case MULTI_ARG_3_SF2:
10516 : 819 : case MULTI_ARG_3_DF2:
10517 : 819 : case MULTI_ARG_3_DI:
10518 : 819 : case MULTI_ARG_3_SI:
10519 : 819 : case MULTI_ARG_3_SI_DI:
10520 : 819 : case MULTI_ARG_3_HI:
10521 : 819 : case MULTI_ARG_3_HI_SI:
10522 : 819 : case MULTI_ARG_3_QI:
10523 : 819 : case MULTI_ARG_3_DI2:
10524 : 819 : case MULTI_ARG_3_SI2:
10525 : 819 : case MULTI_ARG_3_HI2:
10526 : 819 : case MULTI_ARG_3_QI2:
10527 : 819 : nargs = 3;
10528 : 819 : break;
10529 : :
10530 : 128 : case MULTI_ARG_2_SF:
10531 : 128 : case MULTI_ARG_2_DF:
10532 : 128 : case MULTI_ARG_2_DI:
10533 : 128 : case MULTI_ARG_2_SI:
10534 : 128 : case MULTI_ARG_2_HI:
10535 : 128 : case MULTI_ARG_2_QI:
10536 : 128 : nargs = 2;
10537 : 128 : break;
10538 : :
10539 : 64 : case MULTI_ARG_2_DI_IMM:
10540 : 64 : case MULTI_ARG_2_SI_IMM:
10541 : 64 : case MULTI_ARG_2_HI_IMM:
10542 : 64 : case MULTI_ARG_2_QI_IMM:
10543 : 64 : nargs = 2;
10544 : 64 : last_arg_constant = true;
10545 : 64 : break;
10546 : :
10547 : 187 : case MULTI_ARG_1_SF:
10548 : 187 : case MULTI_ARG_1_DF:
10549 : 187 : case MULTI_ARG_1_SF2:
10550 : 187 : case MULTI_ARG_1_DF2:
10551 : 187 : case MULTI_ARG_1_DI:
10552 : 187 : case MULTI_ARG_1_SI:
10553 : 187 : case MULTI_ARG_1_HI:
10554 : 187 : case MULTI_ARG_1_QI:
10555 : 187 : case MULTI_ARG_1_SI_DI:
10556 : 187 : case MULTI_ARG_1_HI_DI:
10557 : 187 : case MULTI_ARG_1_HI_SI:
10558 : 187 : case MULTI_ARG_1_QI_DI:
10559 : 187 : case MULTI_ARG_1_QI_SI:
10560 : 187 : case MULTI_ARG_1_QI_HI:
10561 : 187 : nargs = 1;
10562 : 187 : break;
10563 : :
10564 : 384 : case MULTI_ARG_2_DI_CMP:
10565 : 384 : case MULTI_ARG_2_SI_CMP:
10566 : 384 : case MULTI_ARG_2_HI_CMP:
10567 : 384 : case MULTI_ARG_2_QI_CMP:
10568 : 384 : nargs = 2;
10569 : 384 : comparison_p = true;
10570 : 384 : break;
10571 : :
10572 : 128 : case MULTI_ARG_2_SF_TF:
10573 : 128 : case MULTI_ARG_2_DF_TF:
10574 : 128 : case MULTI_ARG_2_DI_TF:
10575 : 128 : case MULTI_ARG_2_SI_TF:
10576 : 128 : case MULTI_ARG_2_HI_TF:
10577 : 128 : case MULTI_ARG_2_QI_TF:
10578 : 128 : nargs = 2;
10579 : 128 : tf_p = true;
10580 : 128 : break;
10581 : :
10582 : 0 : default:
10583 : 0 : gcc_unreachable ();
10584 : : }
10585 : :
10586 : 628 : if (optimize || !target
10587 : 628 : || GET_MODE (target) != tmode
10588 : 2394 : || !insn_data[icode].operand[0].predicate (target, tmode))
10589 : 1186 : target = gen_reg_rtx (tmode);
10590 : 604 : else if (memory_operand (target, tmode))
10591 : 0 : num_memory++;
10592 : :
10593 : 1790 : gcc_assert (nargs <= ARRAY_SIZE (xops));
10594 : :
10595 : 6154 : for (i = 0; i < nargs; i++)
10596 : : {
10597 : 4372 : tree arg = CALL_EXPR_ARG (exp, i);
10598 : 4372 : rtx op = expand_normal (arg);
10599 : 4372 : int adjust = (comparison_p) ? 1 : 0;
10600 : 4372 : machine_mode mode = insn_data[icode].operand[i+adjust+1].mode;
10601 : :
10602 : 4372 : if (last_arg_constant && i == nargs - 1)
10603 : : {
10604 : 144 : if (!insn_data[icode].operand[i + 1].predicate (op, mode))
10605 : : {
10606 : 30 : enum insn_code new_icode = icode;
10607 : 30 : switch (icode)
10608 : : {
10609 : 8 : case CODE_FOR_xop_vpermil2v2df3:
10610 : 8 : case CODE_FOR_xop_vpermil2v4sf3:
10611 : 8 : case CODE_FOR_xop_vpermil2v4df3:
10612 : 8 : case CODE_FOR_xop_vpermil2v8sf3:
10613 : 8 : error ("the last argument must be a 2-bit immediate");
10614 : 8 : return gen_reg_rtx (tmode);
10615 : 5 : case CODE_FOR_xop_rotlv2di3:
10616 : 5 : new_icode = CODE_FOR_rotlv2di3;
10617 : 5 : goto xop_rotl;
10618 : 5 : case CODE_FOR_xop_rotlv4si3:
10619 : 5 : new_icode = CODE_FOR_rotlv4si3;
10620 : 5 : goto xop_rotl;
10621 : 6 : case CODE_FOR_xop_rotlv8hi3:
10622 : 6 : new_icode = CODE_FOR_rotlv8hi3;
10623 : 6 : goto xop_rotl;
10624 : : case CODE_FOR_xop_rotlv16qi3:
10625 : : new_icode = CODE_FOR_rotlv16qi3;
10626 : 22 : xop_rotl:
10627 : 22 : if (CONST_INT_P (op))
10628 : : {
10629 : 6 : int mask = GET_MODE_UNIT_BITSIZE (tmode) - 1;
10630 : 6 : op = GEN_INT (INTVAL (op) & mask);
10631 : 6 : gcc_checking_assert
10632 : : (insn_data[icode].operand[i + 1].predicate (op, mode));
10633 : : }
10634 : : else
10635 : : {
10636 : 16 : gcc_checking_assert
10637 : : (nargs == 2
10638 : : && insn_data[new_icode].operand[0].mode == tmode
10639 : : && insn_data[new_icode].operand[1].mode == tmode
10640 : : && insn_data[new_icode].operand[2].mode == mode
10641 : : && insn_data[new_icode].operand[0].predicate
10642 : : == insn_data[icode].operand[0].predicate
10643 : : && insn_data[new_icode].operand[1].predicate
10644 : : == insn_data[icode].operand[1].predicate);
10645 : 16 : icode = new_icode;
10646 : 16 : goto non_constant;
10647 : : }
10648 : : break;
10649 : 0 : default:
10650 : 0 : gcc_unreachable ();
10651 : : }
10652 : : }
10653 : : }
10654 : : else
10655 : : {
10656 : 4228 : non_constant:
10657 : 4244 : if (VECTOR_MODE_P (mode))
10658 : 4228 : op = safe_vector_operand (op, mode);
10659 : :
10660 : : /* If we aren't optimizing, only allow one memory operand to be
10661 : : generated. */
10662 : 4244 : if (memory_operand (op, mode))
10663 : 826 : num_memory++;
10664 : :
10665 : 4244 : gcc_assert (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode);
10666 : :
10667 : 4244 : if (optimize
10668 : 1506 : || !insn_data[icode].operand[i+adjust+1].predicate (op, mode)
10669 : 5672 : || num_memory > 1)
10670 : 3323 : op = force_reg (mode, op);
10671 : : }
10672 : :
10673 : 4364 : xops[i] = op;
10674 : : }
10675 : :
10676 : 1782 : switch (nargs)
10677 : : {
10678 : 187 : case 1:
10679 : 187 : pat = GEN_FCN (icode) (target, xops[0]);
10680 : 187 : break;
10681 : :
10682 : 704 : case 2:
10683 : 704 : if (tf_p)
10684 : 128 : pat = GEN_FCN (icode) (target, xops[0], xops[1],
10685 : 128 : GEN_INT ((int)sub_code));
10686 : 576 : else if (! comparison_p)
10687 : 192 : pat = GEN_FCN (icode) (target, xops[0], xops[1]);
10688 : : else
10689 : : {
10690 : 384 : rtx cmp_op = gen_rtx_fmt_ee (sub_code, GET_MODE (target),
10691 : : xops[0], xops[1]);
10692 : :
10693 : 384 : pat = GEN_FCN (icode) (target, cmp_op, xops[0], xops[1]);
10694 : : }
10695 : : break;
10696 : :
10697 : 819 : case 3:
10698 : 819 : pat = GEN_FCN (icode) (target, xops[0], xops[1], xops[2]);
10699 : 819 : break;
10700 : :
10701 : 72 : case 4:
10702 : 72 : pat = GEN_FCN (icode) (target, xops[0], xops[1], xops[2], xops[3]);
10703 : 72 : break;
10704 : :
10705 : : default:
10706 : : gcc_unreachable ();
10707 : : }
10708 : :
10709 : 1782 : if (! pat)
10710 : : return 0;
10711 : :
10712 : 1782 : emit_insn (pat);
10713 : 1782 : return target;
10714 : : }
10715 : :
10716 : : /* Subroutine of ix86_expand_args_builtin to take care of scalar unop
10717 : : insns with vec_merge. */
10718 : :
10719 : : static rtx
10720 : 52 : ix86_expand_unop_vec_merge_builtin (enum insn_code icode, tree exp,
10721 : : rtx target)
10722 : : {
10723 : 52 : rtx pat;
10724 : 52 : tree arg0 = CALL_EXPR_ARG (exp, 0);
10725 : 52 : rtx op1, op0 = expand_normal (arg0);
10726 : 52 : machine_mode tmode = insn_data[icode].operand[0].mode;
10727 : 52 : machine_mode mode0 = insn_data[icode].operand[1].mode;
10728 : :
10729 : 16 : if (optimize || !target
10730 : 16 : || GET_MODE (target) != tmode
10731 : 68 : || !insn_data[icode].operand[0].predicate (target, tmode))
10732 : 36 : target = gen_reg_rtx (tmode);
10733 : :
10734 : 52 : if (VECTOR_MODE_P (mode0))
10735 : 52 : op0 = safe_vector_operand (op0, mode0);
10736 : :
10737 : 36 : if ((optimize && !register_operand (op0, mode0))
10738 : 88 : || !insn_data[icode].operand[1].predicate (op0, mode0))
10739 : 0 : op0 = copy_to_mode_reg (mode0, op0);
10740 : :
10741 : 52 : op1 = op0;
10742 : 52 : if (!insn_data[icode].operand[2].predicate (op1, mode0))
10743 : 16 : op1 = copy_to_mode_reg (mode0, op1);
10744 : :
10745 : 52 : pat = GEN_FCN (icode) (target, op0, op1);
10746 : 52 : if (! pat)
10747 : : return 0;
10748 : 52 : emit_insn (pat);
10749 : 52 : return target;
10750 : : }
10751 : :
10752 : : /* Subroutine of ix86_expand_builtin to take care of comparison insns. */
10753 : :
10754 : : static rtx
10755 : 614 : ix86_expand_sse_compare (const struct builtin_description *d,
10756 : : tree exp, rtx target, bool swap)
10757 : : {
10758 : 614 : rtx pat;
10759 : 614 : tree arg0 = CALL_EXPR_ARG (exp, 0);
10760 : 614 : tree arg1 = CALL_EXPR_ARG (exp, 1);
10761 : 614 : rtx op0 = expand_normal (arg0);
10762 : 614 : rtx op1 = expand_normal (arg1);
10763 : 614 : rtx op2;
10764 : 614 : machine_mode tmode = insn_data[d->icode].operand[0].mode;
10765 : 614 : machine_mode mode0 = insn_data[d->icode].operand[1].mode;
10766 : 614 : machine_mode mode1 = insn_data[d->icode].operand[2].mode;
10767 : 614 : enum rtx_code comparison = d->comparison;
10768 : :
10769 : 614 : if (VECTOR_MODE_P (mode0))
10770 : 614 : op0 = safe_vector_operand (op0, mode0);
10771 : 614 : if (VECTOR_MODE_P (mode1))
10772 : 614 : op1 = safe_vector_operand (op1, mode1);
10773 : :
10774 : : /* Swap operands if we have a comparison that isn't available in
10775 : : hardware. */
10776 : 614 : if (swap)
10777 : 80 : std::swap (op0, op1);
10778 : :
10779 : 202 : if (optimize || !target
10780 : 202 : || GET_MODE (target) != tmode
10781 : 816 : || !insn_data[d->icode].operand[0].predicate (target, tmode))
10782 : 412 : target = gen_reg_rtx (tmode);
10783 : :
10784 : 412 : if ((optimize && !register_operand (op0, mode0))
10785 : 956 : || !insn_data[d->icode].operand[1].predicate (op0, mode0))
10786 : 272 : op0 = copy_to_mode_reg (mode0, op0);
10787 : 412 : if ((optimize && !register_operand (op1, mode1))
10788 : 972 : || !insn_data[d->icode].operand[2].predicate (op1, mode1))
10789 : 54 : op1 = copy_to_mode_reg (mode1, op1);
10790 : :
10791 : 614 : op2 = gen_rtx_fmt_ee (comparison, mode0, op0, op1);
10792 : 614 : pat = GEN_FCN (d->icode) (target, op0, op1, op2);
10793 : 614 : if (! pat)
10794 : : return 0;
10795 : 614 : emit_insn (pat);
10796 : 614 : return target;
10797 : : }
10798 : :
10799 : : /* Subroutine of ix86_sse_comi and ix86_sse_comi_round to take care of
10800 : : * ordered EQ or unordered NE, generate PF jump. */
10801 : :
10802 : : static rtx
10803 : 632 : ix86_ssecom_setcc (const enum rtx_code comparison,
10804 : : bool check_unordered, machine_mode mode,
10805 : : rtx set_dst, rtx target)
10806 : : {
10807 : :
10808 : 632 : rtx_code_label *label = NULL;
10809 : :
10810 : : /* NB: For ordered EQ or unordered NE, check ZF alone isn't sufficient
10811 : : with NAN operands.
10812 : : Under TARGET_AVX10_2, VCOMX/VUCOMX are generated instead of
10813 : : COMI/UCOMI. VCOMX/VUCOMX will not set ZF for NAN operands. */
10814 : 632 : if (check_unordered)
10815 : : {
10816 : 120 : gcc_assert (comparison == EQ || comparison == NE);
10817 : :
10818 : 120 : rtx flag = gen_rtx_REG (CCFPmode, FLAGS_REG);
10819 : 120 : label = gen_label_rtx ();
10820 : 120 : rtx tmp = gen_rtx_fmt_ee (UNORDERED, VOIDmode, flag, const0_rtx);
10821 : 120 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
10822 : : gen_rtx_LABEL_REF (VOIDmode, label),
10823 : : pc_rtx);
10824 : 120 : emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
10825 : : }
10826 : :
10827 : : /* NB: Set CCFPmode and check a different CCmode which is in subset
10828 : : of CCFPmode. */
10829 : 632 : if (GET_MODE (set_dst) != mode)
10830 : : {
10831 : 196 : gcc_assert (mode == CCAmode || mode == CCCmode
10832 : : || mode == CCOmode || mode == CCPmode
10833 : : || mode == CCSmode || mode == CCZmode);
10834 : 196 : set_dst = gen_rtx_REG (mode, FLAGS_REG);
10835 : : }
10836 : :
10837 : 632 : emit_insn (gen_rtx_SET (gen_rtx_STRICT_LOW_PART (VOIDmode, target),
10838 : : gen_rtx_fmt_ee (comparison, QImode,
10839 : : set_dst,
10840 : : const0_rtx)));
10841 : :
10842 : 632 : if (label)
10843 : 120 : emit_label (label);
10844 : :
10845 : 632 : return SUBREG_REG (target);
10846 : : }
10847 : :
10848 : : /* Subroutine of ix86_expand_builtin to take care of comi insns. */
10849 : :
10850 : : static rtx
10851 : 539 : ix86_expand_sse_comi (const struct builtin_description *d, tree exp,
10852 : : rtx target, bool comx_ok)
10853 : : {
10854 : 539 : rtx pat, set_dst;
10855 : 539 : tree arg0 = CALL_EXPR_ARG (exp, 0);
10856 : 539 : tree arg1 = CALL_EXPR_ARG (exp, 1);
10857 : 539 : rtx op0 = expand_normal (arg0);
10858 : 539 : rtx op1 = expand_normal (arg1);
10859 : 539 : enum insn_code icode = d->icode;
10860 : 539 : const struct insn_data_d *insn_p = &insn_data[icode];
10861 : 539 : machine_mode mode0 = insn_p->operand[0].mode;
10862 : 539 : machine_mode mode1 = insn_p->operand[1].mode;
10863 : :
10864 : 539 : if (VECTOR_MODE_P (mode0))
10865 : 539 : op0 = safe_vector_operand (op0, mode0);
10866 : 539 : if (VECTOR_MODE_P (mode1))
10867 : 539 : op1 = safe_vector_operand (op1, mode1);
10868 : :
10869 : 539 : enum rtx_code comparison = d->comparison;
10870 : 539 : rtx const_val = const0_rtx;
10871 : :
10872 : 539 : bool check_unordered = false;
10873 : 539 : machine_mode mode = CCFPmode;
10874 : 539 : switch (comparison)
10875 : : {
10876 : 190 : case LE: /* -> GE */
10877 : 190 : case LT: /* -> GT */
10878 : 190 : std::swap (op0, op1);
10879 : 190 : comparison = swap_condition (comparison);
10880 : : /* FALLTHRU */
10881 : : case GT:
10882 : : case GE:
10883 : : break;
10884 : 72 : case EQ:
10885 : 72 : if (!TARGET_AVX10_2 || !comx_ok)
10886 : 44 : check_unordered = true;
10887 : : mode = CCZmode;
10888 : : break;
10889 : 95 : case NE:
10890 : 95 : if (!TARGET_AVX10_2 || !comx_ok)
10891 : 67 : check_unordered = true;
10892 : 95 : mode = CCZmode;
10893 : 95 : const_val = const1_rtx;
10894 : 95 : break;
10895 : 0 : default:
10896 : 0 : gcc_unreachable ();
10897 : : }
10898 : :
10899 : 539 : target = gen_reg_rtx (SImode);
10900 : 539 : emit_move_insn (target, const_val);
10901 : 539 : target = gen_rtx_SUBREG (QImode, target, 0);
10902 : :
10903 : 418 : if ((optimize && !register_operand (op0, mode0))
10904 : 909 : || !insn_p->operand[0].predicate (op0, mode0))
10905 : 169 : op0 = copy_to_mode_reg (mode0, op0);
10906 : 418 : if ((optimize && !register_operand (op1, mode1))
10907 : 909 : || !insn_p->operand[1].predicate (op1, mode1))
10908 : 48 : op1 = copy_to_mode_reg (mode1, op1);
10909 : :
10910 : 539 : if ((comparison == EQ || comparison == NE)
10911 : 167 : && TARGET_AVX10_2 && comx_ok)
10912 : : {
10913 : 56 : switch (icode)
10914 : : {
10915 : : case CODE_FOR_sse_comi:
10916 : : icode = CODE_FOR_avx10_2_comxsf;
10917 : : break;
10918 : 14 : case CODE_FOR_sse_ucomi:
10919 : 14 : icode = CODE_FOR_avx10_2_ucomxsf;
10920 : 14 : break;
10921 : 14 : case CODE_FOR_sse2_comi:
10922 : 14 : icode = CODE_FOR_avx10_2_comxdf;
10923 : 14 : break;
10924 : 14 : case CODE_FOR_sse2_ucomi:
10925 : 14 : icode = CODE_FOR_avx10_2_ucomxdf;
10926 : 14 : break;
10927 : :
10928 : 0 : default:
10929 : 0 : gcc_unreachable ();
10930 : : }
10931 : : }
10932 : 539 : pat = GEN_FCN (icode) (op0, op1);
10933 : 539 : if (! pat)
10934 : : return 0;
10935 : :
10936 : 539 : set_dst = SET_DEST (pat);
10937 : 539 : emit_insn (pat);
10938 : 539 : return ix86_ssecom_setcc (comparison, check_unordered, mode,
10939 : 539 : set_dst, target);
10940 : : }
10941 : :
10942 : : /* Subroutines of ix86_expand_args_builtin to take care of round insns. */
10943 : :
10944 : : static rtx
10945 : 0 : ix86_expand_sse_round (const struct builtin_description *d, tree exp,
10946 : : rtx target)
10947 : : {
10948 : 0 : rtx pat;
10949 : 0 : tree arg0 = CALL_EXPR_ARG (exp, 0);
10950 : 0 : rtx op1, op0 = expand_normal (arg0);
10951 : 0 : machine_mode tmode = insn_data[d->icode].operand[0].mode;
10952 : 0 : machine_mode mode0 = insn_data[d->icode].operand[1].mode;
10953 : :
10954 : 0 : if (optimize || target == 0
10955 : 0 : || GET_MODE (target) != tmode
10956 : 0 : || !insn_data[d->icode].operand[0].predicate (target, tmode))
10957 : 0 : target = gen_reg_rtx (tmode);
10958 : :
10959 : 0 : if (VECTOR_MODE_P (mode0))
10960 : 0 : op0 = safe_vector_operand (op0, mode0);
10961 : :
10962 : 0 : if ((optimize && !register_operand (op0, mode0))
10963 : 0 : || !insn_data[d->icode].operand[0].predicate (op0, mode0))
10964 : 0 : op0 = copy_to_mode_reg (mode0, op0);
10965 : :
10966 : 0 : op1 = GEN_INT (d->comparison);
10967 : :
10968 : 0 : pat = GEN_FCN (d->icode) (target, op0, op1);
10969 : 0 : if (! pat)
10970 : : return 0;
10971 : 0 : emit_insn (pat);
10972 : 0 : return target;
10973 : : }
10974 : :
10975 : : static rtx
10976 : 12 : ix86_expand_sse_round_vec_pack_sfix (const struct builtin_description *d,
10977 : : tree exp, rtx target)
10978 : : {
10979 : 12 : rtx pat;
10980 : 12 : tree arg0 = CALL_EXPR_ARG (exp, 0);
10981 : 12 : tree arg1 = CALL_EXPR_ARG (exp, 1);
10982 : 12 : rtx op0 = expand_normal (arg0);
10983 : 12 : rtx op1 = expand_normal (arg1);
10984 : 12 : rtx op2;
10985 : 12 : machine_mode tmode = insn_data[d->icode].operand[0].mode;
10986 : 12 : machine_mode mode0 = insn_data[d->icode].operand[1].mode;
10987 : 12 : machine_mode mode1 = insn_data[d->icode].operand[2].mode;
10988 : :
10989 : 0 : if (optimize || target == 0
10990 : 0 : || GET_MODE (target) != tmode
10991 : 12 : || !insn_data[d->icode].operand[0].predicate (target, tmode))
10992 : 12 : target = gen_reg_rtx (tmode);
10993 : :
10994 : 12 : op0 = safe_vector_operand (op0, mode0);
10995 : 12 : op1 = safe_vector_operand (op1, mode1);
10996 : :
10997 : 12 : if ((optimize && !register_operand (op0, mode0))
10998 : 12 : || !insn_data[d->icode].operand[0].predicate (op0, mode0))
10999 : 12 : op0 = copy_to_mode_reg (mode0, op0);
11000 : 12 : if ((optimize && !register_operand (op1, mode1))
11001 : 12 : || !insn_data[d->icode].operand[1].predicate (op1, mode1))
11002 : 12 : op1 = copy_to_mode_reg (mode1, op1);
11003 : :
11004 : 12 : op2 = GEN_INT (d->comparison);
11005 : :
11006 : 12 : pat = GEN_FCN (d->icode) (target, op0, op1, op2);
11007 : 12 : if (! pat)
11008 : : return 0;
11009 : 12 : emit_insn (pat);
11010 : 12 : return target;
11011 : : }
11012 : :
11013 : : /* Subroutine of ix86_expand_builtin to take care of ptest insns. */
11014 : :
11015 : : static rtx
11016 : 235 : ix86_expand_sse_ptest (const struct builtin_description *d, tree exp,
11017 : : rtx target)
11018 : : {
11019 : 235 : rtx pat;
11020 : 235 : tree arg0 = CALL_EXPR_ARG (exp, 0);
11021 : 235 : tree arg1 = CALL_EXPR_ARG (exp, 1);
11022 : 235 : rtx op0 = expand_normal (arg0);
11023 : 235 : rtx op1 = expand_normal (arg1);
11024 : 235 : machine_mode mode0 = insn_data[d->icode].operand[0].mode;
11025 : 235 : machine_mode mode1 = insn_data[d->icode].operand[1].mode;
11026 : 235 : enum rtx_code comparison = d->comparison;
11027 : :
11028 : : /* ptest reg, reg sets the carry flag. */
11029 : 235 : if (comparison == LTU
11030 : 75 : && (d->code == IX86_BUILTIN_PTESTC
11031 : 57 : || d->code == IX86_BUILTIN_PTESTC256)
11032 : 266 : && rtx_equal_p (op0, op1))
11033 : : {
11034 : 2 : if (!target)
11035 : 0 : target = gen_reg_rtx (SImode);
11036 : 2 : emit_move_insn (target, const1_rtx);
11037 : 2 : return target;
11038 : : }
11039 : :
11040 : 233 : if (VECTOR_MODE_P (mode0))
11041 : 233 : op0 = safe_vector_operand (op0, mode0);
11042 : 233 : if (VECTOR_MODE_P (mode1))
11043 : 233 : op1 = safe_vector_operand (op1, mode1);
11044 : :
11045 : 233 : target = gen_reg_rtx (SImode);
11046 : 233 : emit_move_insn (target, const0_rtx);
11047 : 233 : target = gen_rtx_SUBREG (QImode, target, 0);
11048 : :
11049 : 161 : if ((optimize && !register_operand (op0, mode0))
11050 : 366 : || !insn_data[d->icode].operand[0].predicate (op0, mode0))
11051 : 100 : op0 = copy_to_mode_reg (mode0, op0);
11052 : 161 : if ((optimize && !register_operand (op1, mode1))
11053 : 367 : || !insn_data[d->icode].operand[1].predicate (op1, mode1))
11054 : 27 : op1 = copy_to_mode_reg (mode1, op1);
11055 : :
11056 : 233 : pat = GEN_FCN (d->icode) (op0, op1);
11057 : 233 : if (! pat)
11058 : : return 0;
11059 : 233 : emit_insn (pat);
11060 : 233 : emit_insn (gen_rtx_SET (gen_rtx_STRICT_LOW_PART (VOIDmode, target),
11061 : : gen_rtx_fmt_ee (comparison, QImode,
11062 : : SET_DEST (pat),
11063 : : const0_rtx)));
11064 : :
11065 : 233 : return SUBREG_REG (target);
11066 : : }
11067 : :
11068 : : /* Subroutine of ix86_expand_builtin to take care of pcmpestr[im] insns. */
11069 : :
11070 : : static rtx
11071 : 216 : ix86_expand_sse_pcmpestr (const struct builtin_description *d,
11072 : : tree exp, rtx target)
11073 : : {
11074 : 216 : rtx pat;
11075 : 216 : tree arg0 = CALL_EXPR_ARG (exp, 0);
11076 : 216 : tree arg1 = CALL_EXPR_ARG (exp, 1);
11077 : 216 : tree arg2 = CALL_EXPR_ARG (exp, 2);
11078 : 216 : tree arg3 = CALL_EXPR_ARG (exp, 3);
11079 : 216 : tree arg4 = CALL_EXPR_ARG (exp, 4);
11080 : 216 : rtx scratch0, scratch1;
11081 : 216 : rtx op0 = expand_normal (arg0);
11082 : 216 : rtx op1 = expand_normal (arg1);
11083 : 216 : rtx op2 = expand_normal (arg2);
11084 : 216 : rtx op3 = expand_normal (arg3);
11085 : 216 : rtx op4 = expand_normal (arg4);
11086 : 216 : machine_mode tmode0, tmode1, modev2, modei3, modev4, modei5, modeimm;
11087 : :
11088 : 216 : tmode0 = insn_data[d->icode].operand[0].mode;
11089 : 216 : tmode1 = insn_data[d->icode].operand[1].mode;
11090 : 216 : modev2 = insn_data[d->icode].operand[2].mode;
11091 : 216 : modei3 = insn_data[d->icode].operand[3].mode;
11092 : 216 : modev4 = insn_data[d->icode].operand[4].mode;
11093 : 216 : modei5 = insn_data[d->icode].operand[5].mode;
11094 : 216 : modeimm = insn_data[d->icode].operand[6].mode;
11095 : :
11096 : 216 : if (VECTOR_MODE_P (modev2))
11097 : 216 : op0 = safe_vector_operand (op0, modev2);
11098 : 216 : if (VECTOR_MODE_P (modev4))
11099 : 216 : op2 = safe_vector_operand (op2, modev4);
11100 : :
11101 : 216 : if (!insn_data[d->icode].operand[2].predicate (op0, modev2))
11102 : 6 : op0 = copy_to_mode_reg (modev2, op0);
11103 : 216 : if (!insn_data[d->icode].operand[3].predicate (op1, modei3))
11104 : 34 : op1 = copy_to_mode_reg (modei3, op1);
11105 : 160 : if ((optimize && !register_operand (op2, modev4))
11106 : 371 : || !insn_data[d->icode].operand[4].predicate (op2, modev4))
11107 : 5 : op2 = copy_to_mode_reg (modev4, op2);
11108 : 216 : if (!insn_data[d->icode].operand[5].predicate (op3, modei5))
11109 : 34 : op3 = copy_to_mode_reg (modei5, op3);
11110 : :
11111 : 216 : if (!insn_data[d->icode].operand[6].predicate (op4, modeimm))
11112 : : {
11113 : 21 : error ("the fifth argument must be an 8-bit immediate");
11114 : 21 : return const0_rtx;
11115 : : }
11116 : :
11117 : 195 : if (d->code == IX86_BUILTIN_PCMPESTRI128)
11118 : : {
11119 : 5 : if (optimize || !target
11120 : 5 : || GET_MODE (target) != tmode0
11121 : 34 : || !insn_data[d->icode].operand[0].predicate (target, tmode0))
11122 : 24 : target = gen_reg_rtx (tmode0);
11123 : :
11124 : 29 : scratch1 = gen_reg_rtx (tmode1);
11125 : :
11126 : 29 : pat = GEN_FCN (d->icode) (target, scratch1, op0, op1, op2, op3, op4);
11127 : : }
11128 : 166 : else if (d->code == IX86_BUILTIN_PCMPESTRM128)
11129 : : {
11130 : 5 : if (optimize || !target
11131 : 5 : || GET_MODE (target) != tmode1
11132 : 36 : || !insn_data[d->icode].operand[1].predicate (target, tmode1))
11133 : 26 : target = gen_reg_rtx (tmode1);
11134 : :
11135 : 31 : scratch0 = gen_reg_rtx (tmode0);
11136 : :
11137 : 31 : pat = GEN_FCN (d->icode) (scratch0, target, op0, op1, op2, op3, op4);
11138 : : }
11139 : : else
11140 : : {
11141 : 135 : gcc_assert (d->flag);
11142 : :
11143 : 135 : scratch0 = gen_reg_rtx (tmode0);
11144 : 135 : scratch1 = gen_reg_rtx (tmode1);
11145 : :
11146 : 135 : pat = GEN_FCN (d->icode) (scratch0, scratch1, op0, op1, op2, op3, op4);
11147 : : }
11148 : :
11149 : 195 : if (! pat)
11150 : : return 0;
11151 : :
11152 : 195 : emit_insn (pat);
11153 : :
11154 : 195 : if (d->flag)
11155 : : {
11156 : 135 : target = gen_reg_rtx (SImode);
11157 : 135 : emit_move_insn (target, const0_rtx);
11158 : 135 : target = gen_rtx_SUBREG (QImode, target, 0);
11159 : :
11160 : 135 : emit_insn
11161 : 135 : (gen_rtx_SET (gen_rtx_STRICT_LOW_PART (VOIDmode, target),
11162 : : gen_rtx_fmt_ee (EQ, QImode,
11163 : : gen_rtx_REG ((machine_mode) d->flag,
11164 : : FLAGS_REG),
11165 : : const0_rtx)));
11166 : 135 : return SUBREG_REG (target);
11167 : : }
11168 : : else
11169 : : return target;
11170 : : }
11171 : :
11172 : :
11173 : : /* Subroutine of ix86_expand_builtin to take care of pcmpistr[im] insns. */
11174 : :
11175 : : static rtx
11176 : 275 : ix86_expand_sse_pcmpistr (const struct builtin_description *d,
11177 : : tree exp, rtx target)
11178 : : {
11179 : 275 : rtx pat;
11180 : 275 : tree arg0 = CALL_EXPR_ARG (exp, 0);
11181 : 275 : tree arg1 = CALL_EXPR_ARG (exp, 1);
11182 : 275 : tree arg2 = CALL_EXPR_ARG (exp, 2);
11183 : 275 : rtx scratch0, scratch1;
11184 : 275 : rtx op0 = expand_normal (arg0);
11185 : 275 : rtx op1 = expand_normal (arg1);
11186 : 275 : rtx op2 = expand_normal (arg2);
11187 : 275 : machine_mode tmode0, tmode1, modev2, modev3, modeimm;
11188 : :
11189 : 275 : tmode0 = insn_data[d->icode].operand[0].mode;
11190 : 275 : tmode1 = insn_data[d->icode].operand[1].mode;
11191 : 275 : modev2 = insn_data[d->icode].operand[2].mode;
11192 : 275 : modev3 = insn_data[d->icode].operand[3].mode;
11193 : 275 : modeimm = insn_data[d->icode].operand[4].mode;
11194 : :
11195 : 275 : if (VECTOR_MODE_P (modev2))
11196 : 275 : op0 = safe_vector_operand (op0, modev2);
11197 : 275 : if (VECTOR_MODE_P (modev3))
11198 : 275 : op1 = safe_vector_operand (op1, modev3);
11199 : :
11200 : 275 : if (!insn_data[d->icode].operand[2].predicate (op0, modev2))
11201 : 4 : op0 = copy_to_mode_reg (modev2, op0);
11202 : 210 : if ((optimize && !register_operand (op1, modev3))
11203 : 481 : || !insn_data[d->icode].operand[3].predicate (op1, modev3))
11204 : 4 : op1 = copy_to_mode_reg (modev3, op1);
11205 : :
11206 : 275 : if (!insn_data[d->icode].operand[4].predicate (op2, modeimm))
11207 : : {
11208 : 21 : error ("the third argument must be an 8-bit immediate");
11209 : 21 : return const0_rtx;
11210 : : }
11211 : :
11212 : 254 : if (d->code == IX86_BUILTIN_PCMPISTRI128)
11213 : : {
11214 : 5 : if (optimize || !target
11215 : 5 : || GET_MODE (target) != tmode0
11216 : 38 : || !insn_data[d->icode].operand[0].predicate (target, tmode0))
11217 : 28 : target = gen_reg_rtx (tmode0);
11218 : :
11219 : 33 : scratch1 = gen_reg_rtx (tmode1);
11220 : :
11221 : 33 : pat = GEN_FCN (d->icode) (target, scratch1, op0, op1, op2);
11222 : : }
11223 : 221 : else if (d->code == IX86_BUILTIN_PCMPISTRM128)
11224 : : {
11225 : 8 : if (optimize || !target
11226 : 8 : || GET_MODE (target) != tmode1
11227 : 58 : || !insn_data[d->icode].operand[1].predicate (target, tmode1))
11228 : 42 : target = gen_reg_rtx (tmode1);
11229 : :
11230 : 50 : scratch0 = gen_reg_rtx (tmode0);
11231 : :
11232 : 50 : pat = GEN_FCN (d->icode) (scratch0, target, op0, op1, op2);
11233 : : }
11234 : : else
11235 : : {
11236 : 171 : gcc_assert (d->flag);
11237 : :
11238 : 171 : scratch0 = gen_reg_rtx (tmode0);
11239 : 171 : scratch1 = gen_reg_rtx (tmode1);
11240 : :
11241 : 171 : pat = GEN_FCN (d->icode) (scratch0, scratch1, op0, op1, op2);
11242 : : }
11243 : :
11244 : 254 : if (! pat)
11245 : : return 0;
11246 : :
11247 : 254 : emit_insn (pat);
11248 : :
11249 : 254 : if (d->flag)
11250 : : {
11251 : 171 : target = gen_reg_rtx (SImode);
11252 : 171 : emit_move_insn (target, const0_rtx);
11253 : 171 : target = gen_rtx_SUBREG (QImode, target, 0);
11254 : :
11255 : 171 : emit_insn
11256 : 171 : (gen_rtx_SET (gen_rtx_STRICT_LOW_PART (VOIDmode, target),
11257 : : gen_rtx_fmt_ee (EQ, QImode,
11258 : : gen_rtx_REG ((machine_mode) d->flag,
11259 : : FLAGS_REG),
11260 : : const0_rtx)));
11261 : 171 : return SUBREG_REG (target);
11262 : : }
11263 : : else
11264 : : return target;
11265 : : }
11266 : :
11267 : : /* Fixup modeless constants to fit required mode. */
11268 : :
11269 : : static rtx
11270 : 254301 : fixup_modeless_constant (rtx x, machine_mode mode)
11271 : : {
11272 : 254301 : if (GET_MODE (x) == VOIDmode)
11273 : 39820 : x = convert_to_mode (mode, x, 1);
11274 : 254301 : return x;
11275 : : }
11276 : :
11277 : : /* Expand the outgoing argument ARG to extract unsigned char and short
11278 : : integer constants suitable for the predicates and the instruction
11279 : : templates which expect the unsigned expanded value. */
11280 : :
11281 : : static rtx
11282 : 275388 : ix86_expand_unsigned_small_int_cst_argument (tree arg)
11283 : : {
11284 : : /* When passing 0xff as an unsigned char function argument with the
11285 : : C frontend promotion, expand_normal gets
11286 : :
11287 : : <integer_cst 0x7fffe6aa23a8 type <integer_type 0x7fffe98225e8 int> constant 255>
11288 : :
11289 : : and returns the rtx value using the sign-extended representation:
11290 : :
11291 : : (const_int 255 [0xff])
11292 : :
11293 : : Without the C frontend promotion, expand_normal gets
11294 : :
11295 : : <integer_cst 0x7fffe9824018 type <integer_type 0x7fffe9822348 unsigned char > constant 255>
11296 : :
11297 : : and returns
11298 : :
11299 : : (const_int -1 [0xffffffffffffffff])
11300 : :
11301 : : which doesn't work with the predicates nor the instruction templates
11302 : : which expect the unsigned expanded value. Extract the unsigned char
11303 : : and short integer constants to return
11304 : :
11305 : : (const_int 255 [0xff])
11306 : :
11307 : : so that the expanded value is always unsigned, without the C frontend
11308 : : promotion. */
11309 : :
11310 : 275388 : if (TREE_CODE (arg) == INTEGER_CST)
11311 : : {
11312 : 58555 : tree type = TREE_TYPE (arg);
11313 : 58555 : if (INTEGRAL_TYPE_P (type)
11314 : 58555 : && TYPE_UNSIGNED (type)
11315 : 79214 : && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
11316 : : {
11317 : 17368 : HOST_WIDE_INT cst = TREE_INT_CST_LOW (arg);
11318 : 17368 : return GEN_INT (cst);
11319 : : }
11320 : : }
11321 : :
11322 : 258020 : return expand_normal (arg);
11323 : : }
11324 : :
11325 : : /* Subroutine of ix86_expand_builtin to take care of insns with
11326 : : variable number of operands. */
11327 : :
11328 : : static rtx
11329 : 68111 : ix86_expand_args_builtin (const struct builtin_description *d,
11330 : : tree exp, rtx target)
11331 : : {
11332 : 68111 : rtx pat, real_target;
11333 : 68111 : unsigned int i, nargs;
11334 : 68111 : unsigned int nargs_constant = 0;
11335 : 68111 : unsigned int mask_pos = 0;
11336 : 68111 : int num_memory = 0;
11337 : 68111 : rtx xops[6];
11338 : 68111 : bool second_arg_count = false;
11339 : 68111 : enum insn_code icode = d->icode;
11340 : 68111 : const struct insn_data_d *insn_p = &insn_data[icode];
11341 : 68111 : machine_mode tmode = insn_p->operand[0].mode;
11342 : 68111 : machine_mode rmode = VOIDmode;
11343 : 68111 : bool swap = false;
11344 : 68111 : enum rtx_code comparison = d->comparison;
11345 : :
11346 : 68111 : switch ((enum ix86_builtin_func_type) d->flag)
11347 : : {
11348 : 0 : case V2DF_FTYPE_V2DF_ROUND:
11349 : 0 : case V4DF_FTYPE_V4DF_ROUND:
11350 : 0 : case V8DF_FTYPE_V8DF_ROUND:
11351 : 0 : case V4SF_FTYPE_V4SF_ROUND:
11352 : 0 : case V8SF_FTYPE_V8SF_ROUND:
11353 : 0 : case V16SF_FTYPE_V16SF_ROUND:
11354 : 0 : case V8HF_FTYPE_V8HF_ROUND:
11355 : 0 : case V16HF_FTYPE_V16HF_ROUND:
11356 : 0 : case V32HF_FTYPE_V32HF_ROUND:
11357 : 0 : case V4SI_FTYPE_V4SF_ROUND:
11358 : 0 : case V8SI_FTYPE_V8SF_ROUND:
11359 : 0 : case V16SI_FTYPE_V16SF_ROUND:
11360 : 0 : return ix86_expand_sse_round (d, exp, target);
11361 : 12 : case V4SI_FTYPE_V2DF_V2DF_ROUND:
11362 : 12 : case V8SI_FTYPE_V4DF_V4DF_ROUND:
11363 : 12 : case V16SI_FTYPE_V8DF_V8DF_ROUND:
11364 : 12 : return ix86_expand_sse_round_vec_pack_sfix (d, exp, target);
11365 : 235 : case INT_FTYPE_V8SF_V8SF_PTEST:
11366 : 235 : case INT_FTYPE_V4DI_V4DI_PTEST:
11367 : 235 : case INT_FTYPE_V4DF_V4DF_PTEST:
11368 : 235 : case INT_FTYPE_V4SF_V4SF_PTEST:
11369 : 235 : case INT_FTYPE_V2DI_V2DI_PTEST:
11370 : 235 : case INT_FTYPE_V2DF_V2DF_PTEST:
11371 : 235 : return ix86_expand_sse_ptest (d, exp, target);
11372 : : case FLOAT128_FTYPE_FLOAT128:
11373 : : case FLOAT_FTYPE_FLOAT:
11374 : : case FLOAT_FTYPE_BFLOAT16:
11375 : : case INT_FTYPE_INT:
11376 : : case UINT_FTYPE_UINT:
11377 : : case UINT16_FTYPE_UINT16:
11378 : : case UINT64_FTYPE_INT:
11379 : : case UINT64_FTYPE_UINT64:
11380 : : case INT64_FTYPE_INT64:
11381 : : case INT64_FTYPE_V4SF:
11382 : : case INT64_FTYPE_V2DF:
11383 : : case INT_FTYPE_V16QI:
11384 : : case INT_FTYPE_V8QI:
11385 : : case INT_FTYPE_V8SF:
11386 : : case INT_FTYPE_V4DF:
11387 : : case INT_FTYPE_V4SF:
11388 : : case INT_FTYPE_V2DF:
11389 : : case INT_FTYPE_V32QI:
11390 : : case V16QI_FTYPE_V16QI:
11391 : : case V8SI_FTYPE_V8SF:
11392 : : case V8SI_FTYPE_V4SI:
11393 : : case V8HI_FTYPE_V8HI:
11394 : : case V8HI_FTYPE_V16QI:
11395 : : case V8QI_FTYPE_V8QI:
11396 : : case V8SF_FTYPE_V8SF:
11397 : : case V8SF_FTYPE_V8SI:
11398 : : case V8SF_FTYPE_V4SF:
11399 : : case V8SF_FTYPE_V8HI:
11400 : : case V4SI_FTYPE_V4SI:
11401 : : case V4SI_FTYPE_V16QI:
11402 : : case V4SI_FTYPE_V4SF:
11403 : : case V4SI_FTYPE_V8SI:
11404 : : case V4SI_FTYPE_V8HI:
11405 : : case V4SI_FTYPE_V4DF:
11406 : : case V4SI_FTYPE_V2DF:
11407 : : case V4HI_FTYPE_V4HI:
11408 : : case V4DF_FTYPE_V4DF:
11409 : : case V4DF_FTYPE_V4SI:
11410 : : case V4DF_FTYPE_V4SF:
11411 : : case V4DF_FTYPE_V2DF:
11412 : : case V4SF_FTYPE_V4SF:
11413 : : case V4SF_FTYPE_V4SI:
11414 : : case V4SF_FTYPE_V8SF:
11415 : : case V4SF_FTYPE_V4DF:
11416 : : case V4SF_FTYPE_V8HI:
11417 : : case V4SF_FTYPE_V2DF:
11418 : : case V2DI_FTYPE_V2DI:
11419 : : case V2DI_FTYPE_V16QI:
11420 : : case V2DI_FTYPE_V8HI:
11421 : : case V2DI_FTYPE_V4SI:
11422 : : case V2DF_FTYPE_V2DF:
11423 : : case V2DF_FTYPE_V4SI:
11424 : : case V2DF_FTYPE_V4DF:
11425 : : case V2DF_FTYPE_V4SF:
11426 : : case V2DF_FTYPE_V2SI:
11427 : : case V2SI_FTYPE_V2SI:
11428 : : case V2SI_FTYPE_V4SF:
11429 : : case V2SI_FTYPE_V2SF:
11430 : : case V2SI_FTYPE_V2DF:
11431 : : case V2SF_FTYPE_V2SF:
11432 : : case V2SF_FTYPE_V2SI:
11433 : : case V32QI_FTYPE_V32QI:
11434 : : case V32QI_FTYPE_V16QI:
11435 : : case V16HI_FTYPE_V16HI:
11436 : : case V16HI_FTYPE_V8HI:
11437 : : case V8SI_FTYPE_V8SI:
11438 : : case V16HI_FTYPE_V16QI:
11439 : : case V8SI_FTYPE_V16QI:
11440 : : case V4DI_FTYPE_V16QI:
11441 : : case V8SI_FTYPE_V8HI:
11442 : : case V4DI_FTYPE_V8HI:
11443 : : case V4DI_FTYPE_V4SI:
11444 : : case V4DI_FTYPE_V2DI:
11445 : : case UQI_FTYPE_UQI:
11446 : : case UHI_FTYPE_UHI:
11447 : : case USI_FTYPE_USI:
11448 : : case USI_FTYPE_UQI:
11449 : : case USI_FTYPE_UHI:
11450 : : case UDI_FTYPE_UDI:
11451 : : case UHI_FTYPE_V16QI:
11452 : : case USI_FTYPE_V32QI:
11453 : : case UDI_FTYPE_V64QI:
11454 : : case V16QI_FTYPE_UHI:
11455 : : case V32QI_FTYPE_USI:
11456 : : case V64QI_FTYPE_UDI:
11457 : : case V8HI_FTYPE_UQI:
11458 : : case V16HI_FTYPE_UHI:
11459 : : case V32HI_FTYPE_USI:
11460 : : case V4SI_FTYPE_UQI:
11461 : : case V8SI_FTYPE_UQI:
11462 : : case V4SI_FTYPE_UHI:
11463 : : case V8SI_FTYPE_UHI:
11464 : : case UQI_FTYPE_V8HI:
11465 : : case UHI_FTYPE_V16HI:
11466 : : case USI_FTYPE_V32HI:
11467 : : case UQI_FTYPE_V4SI:
11468 : : case UQI_FTYPE_V8SI:
11469 : : case UHI_FTYPE_V16SI:
11470 : : case UQI_FTYPE_V2DI:
11471 : : case UQI_FTYPE_V4DI:
11472 : : case UQI_FTYPE_V8DI:
11473 : : case V16SI_FTYPE_UHI:
11474 : : case V2DI_FTYPE_UQI:
11475 : : case V4DI_FTYPE_UQI:
11476 : : case V16SI_FTYPE_INT:
11477 : : case V16SF_FTYPE_V8SF:
11478 : : case V16SI_FTYPE_V8SI:
11479 : : case V16SF_FTYPE_V4SF:
11480 : : case V16SI_FTYPE_V4SI:
11481 : : case V16SI_FTYPE_V16SF:
11482 : : case V16SI_FTYPE_V16SI:
11483 : : case V64QI_FTYPE_V64QI:
11484 : : case V32HI_FTYPE_V32HI:
11485 : : case V16SF_FTYPE_V16SF:
11486 : : case V8DI_FTYPE_UQI:
11487 : : case V8DI_FTYPE_V8DI:
11488 : : case V8DF_FTYPE_V4DF:
11489 : : case V8DF_FTYPE_V2DF:
11490 : : case V8DF_FTYPE_V8DF:
11491 : : case V4DI_FTYPE_V4DI:
11492 : : case V16BF_FTYPE_V16SF:
11493 : : case V8BF_FTYPE_V8SF:
11494 : : case V8BF_FTYPE_V4SF:
11495 : : nargs = 1;
11496 : : break;
11497 : 52 : case V4SF_FTYPE_V4SF_VEC_MERGE:
11498 : 52 : case V2DF_FTYPE_V2DF_VEC_MERGE:
11499 : 52 : return ix86_expand_unop_vec_merge_builtin (icode, exp, target);
11500 : 9490 : case FLOAT128_FTYPE_FLOAT128_FLOAT128:
11501 : 9490 : case V16QI_FTYPE_V16QI_V16QI:
11502 : 9490 : case V16QI_FTYPE_V8HI_V8HI:
11503 : 9490 : case V16HF_FTYPE_V16HF_V16HF:
11504 : 9490 : case V16SF_FTYPE_V16SF_V16SF:
11505 : 9490 : case V16SI_FTYPE_V16SI_V16SI:
11506 : 9490 : case V8QI_FTYPE_V8QI_V8QI:
11507 : 9490 : case V8QI_FTYPE_V4HI_V4HI:
11508 : 9490 : case V8HI_FTYPE_V8HI_V8HI:
11509 : 9490 : case V8HI_FTYPE_V16QI_V16QI:
11510 : 9490 : case V8HI_FTYPE_V4SI_V4SI:
11511 : 9490 : case V8HF_FTYPE_V8HF_V8HF:
11512 : 9490 : case V8SF_FTYPE_V8SF_V8SF:
11513 : 9490 : case V8SF_FTYPE_V8SF_V8SI:
11514 : 9490 : case V8DF_FTYPE_V8DF_V8DF:
11515 : 9490 : case V4SI_FTYPE_V4SI_V4SI:
11516 : 9490 : case V4SI_FTYPE_V8HI_V8HI:
11517 : 9490 : case V4SI_FTYPE_V2DF_V2DF:
11518 : 9490 : case V4HI_FTYPE_V4HI_V4HI:
11519 : 9490 : case V4HI_FTYPE_V8QI_V8QI:
11520 : 9490 : case V4HI_FTYPE_V2SI_V2SI:
11521 : 9490 : case V4DF_FTYPE_V4DF_V4DF:
11522 : 9490 : case V4DF_FTYPE_V4DF_V4DI:
11523 : 9490 : case V4SF_FTYPE_V4SF_V4SF:
11524 : 9490 : case V4SF_FTYPE_V4SF_V4SI:
11525 : 9490 : case V4SF_FTYPE_V4SF_V2SI:
11526 : 9490 : case V4SF_FTYPE_V4SF_V2DF:
11527 : 9490 : case V4SF_FTYPE_V4SF_UINT:
11528 : 9490 : case V4SF_FTYPE_V4SF_DI:
11529 : 9490 : case V4SF_FTYPE_V4SF_SI:
11530 : 9490 : case V4DI_FTYPE_V4DI_V2DI:
11531 : 9490 : case V2DI_FTYPE_V2DI_V2DI:
11532 : 9490 : case V2DI_FTYPE_V16QI_V16QI:
11533 : 9490 : case V2DI_FTYPE_V4SI_V4SI:
11534 : 9490 : case V2DI_FTYPE_V2DI_V16QI:
11535 : 9490 : case V2SI_FTYPE_V2SI_V2SI:
11536 : 9490 : case V2SI_FTYPE_V4HI_V4HI:
11537 : 9490 : case V2SI_FTYPE_V2SF_V2SF:
11538 : 9490 : case V2DF_FTYPE_V2DF_V2DF:
11539 : 9490 : case V2DF_FTYPE_V2DF_V4SF:
11540 : 9490 : case V2DF_FTYPE_V2DF_V2DI:
11541 : 9490 : case V2DF_FTYPE_V2DF_DI:
11542 : 9490 : case V2DF_FTYPE_V2DF_SI:
11543 : 9490 : case V2DF_FTYPE_V2DF_UINT:
11544 : 9490 : case V2SF_FTYPE_V2SF_V2SF:
11545 : 9490 : case V1DI_FTYPE_V1DI_V1DI:
11546 : 9490 : case V1DI_FTYPE_V8QI_V8QI:
11547 : 9490 : case V1DI_FTYPE_V2SI_V2SI:
11548 : 9490 : case V32QI_FTYPE_V16HI_V16HI:
11549 : 9490 : case V16HI_FTYPE_V8SI_V8SI:
11550 : 9490 : case V64QI_FTYPE_V64QI_V64QI:
11551 : 9490 : case V32QI_FTYPE_V32QI_V32QI:
11552 : 9490 : case V32BF_FTYPE_V32BF_V32BF:
11553 : 9490 : case V16BF_FTYPE_V16BF_V16BF:
11554 : 9490 : case V8BF_FTYPE_V8BF_V8BF:
11555 : 9490 : case V16HI_FTYPE_V32QI_V32QI:
11556 : 9490 : case V16HI_FTYPE_V16HI_V16HI:
11557 : 9490 : case V8SI_FTYPE_V4DF_V4DF:
11558 : 9490 : case V8SI_FTYPE_V8SI_V8SI:
11559 : 9490 : case V8SI_FTYPE_V16HI_V16HI:
11560 : 9490 : case V4DI_FTYPE_V4DI_V4DI:
11561 : 9490 : case V4DI_FTYPE_V8SI_V8SI:
11562 : 9490 : case V4DI_FTYPE_V32QI_V32QI:
11563 : 9490 : case V8DI_FTYPE_V64QI_V64QI:
11564 : 9490 : if (comparison == UNKNOWN)
11565 : 8956 : return ix86_expand_binop_builtin (icode, exp, target);
11566 : : nargs = 2;
11567 : : break;
11568 : 80 : case V4SF_FTYPE_V4SF_V4SF_SWAP:
11569 : 80 : case V2DF_FTYPE_V2DF_V2DF_SWAP:
11570 : 80 : gcc_assert (comparison != UNKNOWN);
11571 : : nargs = 2;
11572 : : swap = true;
11573 : : break;
11574 : 1481 : case V16HI_FTYPE_V16HI_V8HI_COUNT:
11575 : 1481 : case V16HI_FTYPE_V16HI_SI_COUNT:
11576 : 1481 : case V8SI_FTYPE_V8SI_V4SI_COUNT:
11577 : 1481 : case V8SI_FTYPE_V8SI_SI_COUNT:
11578 : 1481 : case V4DI_FTYPE_V4DI_V2DI_COUNT:
11579 : 1481 : case V4DI_FTYPE_V4DI_INT_COUNT:
11580 : 1481 : case V8HI_FTYPE_V8HI_V8HI_COUNT:
11581 : 1481 : case V8HI_FTYPE_V8HI_SI_COUNT:
11582 : 1481 : case V4SI_FTYPE_V4SI_V4SI_COUNT:
11583 : 1481 : case V4SI_FTYPE_V4SI_SI_COUNT:
11584 : 1481 : case V4HI_FTYPE_V4HI_V4HI_COUNT:
11585 : 1481 : case V4HI_FTYPE_V4HI_SI_COUNT:
11586 : 1481 : case V2DI_FTYPE_V2DI_V2DI_COUNT:
11587 : 1481 : case V2DI_FTYPE_V2DI_SI_COUNT:
11588 : 1481 : case V2SI_FTYPE_V2SI_V2SI_COUNT:
11589 : 1481 : case V2SI_FTYPE_V2SI_SI_COUNT:
11590 : 1481 : case V1DI_FTYPE_V1DI_V1DI_COUNT:
11591 : 1481 : case V1DI_FTYPE_V1DI_SI_COUNT:
11592 : 1481 : nargs = 2;
11593 : 1481 : second_arg_count = true;
11594 : 1481 : break;
11595 : 1406 : case V16HI_FTYPE_V16HI_INT_V16HI_UHI_COUNT:
11596 : 1406 : case V16HI_FTYPE_V16HI_V8HI_V16HI_UHI_COUNT:
11597 : 1406 : case V16SI_FTYPE_V16SI_INT_V16SI_UHI_COUNT:
11598 : 1406 : case V16SI_FTYPE_V16SI_V4SI_V16SI_UHI_COUNT:
11599 : 1406 : case V2DI_FTYPE_V2DI_INT_V2DI_UQI_COUNT:
11600 : 1406 : case V2DI_FTYPE_V2DI_V2DI_V2DI_UQI_COUNT:
11601 : 1406 : case V32HI_FTYPE_V32HI_INT_V32HI_USI_COUNT:
11602 : 1406 : case V32HI_FTYPE_V32HI_V8HI_V32HI_USI_COUNT:
11603 : 1406 : case V4DI_FTYPE_V4DI_INT_V4DI_UQI_COUNT:
11604 : 1406 : case V4DI_FTYPE_V4DI_V2DI_V4DI_UQI_COUNT:
11605 : 1406 : case V4SI_FTYPE_V4SI_INT_V4SI_UQI_COUNT:
11606 : 1406 : case V4SI_FTYPE_V4SI_V4SI_V4SI_UQI_COUNT:
11607 : 1406 : case V8DI_FTYPE_V8DI_INT_V8DI_UQI_COUNT:
11608 : 1406 : case V8DI_FTYPE_V8DI_V2DI_V8DI_UQI_COUNT:
11609 : 1406 : case V8HI_FTYPE_V8HI_INT_V8HI_UQI_COUNT:
11610 : 1406 : case V8HI_FTYPE_V8HI_V8HI_V8HI_UQI_COUNT:
11611 : 1406 : case V8SI_FTYPE_V8SI_INT_V8SI_UQI_COUNT:
11612 : 1406 : case V8SI_FTYPE_V8SI_V4SI_V8SI_UQI_COUNT:
11613 : 1406 : nargs = 4;
11614 : 1406 : second_arg_count = true;
11615 : 1406 : break;
11616 : 957 : case UINT64_FTYPE_UINT64_UINT64:
11617 : 957 : case UINT_FTYPE_UINT_UINT:
11618 : 957 : case UINT_FTYPE_UINT_USHORT:
11619 : 957 : case UINT_FTYPE_UINT_UCHAR:
11620 : 957 : case UINT16_FTYPE_UINT16_INT:
11621 : 957 : case UINT8_FTYPE_UINT8_INT:
11622 : 957 : case UQI_FTYPE_UQI_UQI:
11623 : 957 : case UHI_FTYPE_UHI_UHI:
11624 : 957 : case USI_FTYPE_USI_USI:
11625 : 957 : case UDI_FTYPE_UDI_UDI:
11626 : 957 : case V16SI_FTYPE_V8DF_V8DF:
11627 : 957 : case V32BF_FTYPE_V16SF_V16SF:
11628 : 957 : case V16BF_FTYPE_V8SF_V8SF:
11629 : 957 : case V8BF_FTYPE_V4SF_V4SF:
11630 : 957 : case V16BF_FTYPE_V16SF_UHI:
11631 : 957 : case V8BF_FTYPE_V8SF_UQI:
11632 : 957 : case V8BF_FTYPE_V4SF_UQI:
11633 : 957 : case V16QI_FTYPE_V16QI_V8HF:
11634 : 957 : nargs = 2;
11635 : 957 : break;
11636 : 803 : case V2DI_FTYPE_V2DI_INT_CONVERT:
11637 : 803 : nargs = 2;
11638 : 803 : rmode = V1TImode;
11639 : 803 : nargs_constant = 1;
11640 : 803 : break;
11641 : 42 : case V4DI_FTYPE_V4DI_INT_CONVERT:
11642 : 42 : nargs = 2;
11643 : 42 : rmode = V2TImode;
11644 : 42 : nargs_constant = 1;
11645 : 42 : break;
11646 : 16 : case V8DI_FTYPE_V8DI_INT_CONVERT:
11647 : 16 : nargs = 2;
11648 : 16 : rmode = V4TImode;
11649 : 16 : nargs_constant = 1;
11650 : 16 : break;
11651 : 2376 : case V8HI_FTYPE_V8HI_INT:
11652 : 2376 : case V8HI_FTYPE_V8SF_INT:
11653 : 2376 : case V16HI_FTYPE_V16SF_INT:
11654 : 2376 : case V8HI_FTYPE_V4SF_INT:
11655 : 2376 : case V8SF_FTYPE_V8SF_INT:
11656 : 2376 : case V4SF_FTYPE_V16SF_INT:
11657 : 2376 : case V16SF_FTYPE_V16SF_INT:
11658 : 2376 : case V4SI_FTYPE_V4SI_INT:
11659 : 2376 : case V4SI_FTYPE_V8SI_INT:
11660 : 2376 : case V4HI_FTYPE_V4HI_INT:
11661 : 2376 : case V4DF_FTYPE_V4DF_INT:
11662 : 2376 : case V4DF_FTYPE_V8DF_INT:
11663 : 2376 : case V4SF_FTYPE_V4SF_INT:
11664 : 2376 : case V4SF_FTYPE_V8SF_INT:
11665 : 2376 : case V2DI_FTYPE_V2DI_INT:
11666 : 2376 : case V2DF_FTYPE_V2DF_INT:
11667 : 2376 : case V2DF_FTYPE_V4DF_INT:
11668 : 2376 : case V16HI_FTYPE_V16HI_INT:
11669 : 2376 : case V8SI_FTYPE_V8SI_INT:
11670 : 2376 : case V16SI_FTYPE_V16SI_INT:
11671 : 2376 : case V4SI_FTYPE_V16SI_INT:
11672 : 2376 : case V4DI_FTYPE_V4DI_INT:
11673 : 2376 : case V2DI_FTYPE_V4DI_INT:
11674 : 2376 : case V4DI_FTYPE_V8DI_INT:
11675 : 2376 : case UQI_FTYPE_UQI_UQI_CONST:
11676 : 2376 : case UHI_FTYPE_UHI_UQI:
11677 : 2376 : case USI_FTYPE_USI_UQI:
11678 : 2376 : case UDI_FTYPE_UDI_UQI:
11679 : 2376 : nargs = 2;
11680 : 2376 : nargs_constant = 1;
11681 : 2376 : break;
11682 : 18168 : case V16QI_FTYPE_V16QI_V16QI_V16QI:
11683 : 18168 : case V8SF_FTYPE_V8SF_V8SF_V8SF:
11684 : 18168 : case V4DF_FTYPE_V4DF_V4DF_V4DF:
11685 : 18168 : case V4SF_FTYPE_V4SF_V4SF_V4SF:
11686 : 18168 : case V2DF_FTYPE_V2DF_V2DF_V2DF:
11687 : 18168 : case V32QI_FTYPE_V32QI_V32QI_V32QI:
11688 : 18168 : case UHI_FTYPE_V16SI_V16SI_UHI:
11689 : 18168 : case UQI_FTYPE_V8DI_V8DI_UQI:
11690 : 18168 : case V16HI_FTYPE_V16SI_V16HI_UHI:
11691 : 18168 : case V16QI_FTYPE_V16SI_V16QI_UHI:
11692 : 18168 : case V16QI_FTYPE_V8DI_V16QI_UQI:
11693 : 18168 : case V32HF_FTYPE_V32HF_V32HF_USI:
11694 : 18168 : case V16SF_FTYPE_V16SF_V16SF_UHI:
11695 : 18168 : case V16SF_FTYPE_V4SF_V16SF_UHI:
11696 : 18168 : case V16SI_FTYPE_SI_V16SI_UHI:
11697 : 18168 : case V16SI_FTYPE_V16HI_V16SI_UHI:
11698 : 18168 : case V16SI_FTYPE_V16QI_V16SI_UHI:
11699 : 18168 : case V8SF_FTYPE_V4SF_V8SF_UQI:
11700 : 18168 : case V4DF_FTYPE_V2DF_V4DF_UQI:
11701 : 18168 : case V8SI_FTYPE_V4SI_V8SI_UQI:
11702 : 18168 : case V8SI_FTYPE_SI_V8SI_UQI:
11703 : 18168 : case V4SI_FTYPE_V4SI_V4SI_UQI:
11704 : 18168 : case V4SI_FTYPE_SI_V4SI_UQI:
11705 : 18168 : case V4DI_FTYPE_V2DI_V4DI_UQI:
11706 : 18168 : case V4DI_FTYPE_DI_V4DI_UQI:
11707 : 18168 : case V2DI_FTYPE_V2DI_V2DI_UQI:
11708 : 18168 : case V2DI_FTYPE_DI_V2DI_UQI:
11709 : 18168 : case V64QI_FTYPE_V64QI_V64QI_UDI:
11710 : 18168 : case V64QI_FTYPE_V16QI_V64QI_UDI:
11711 : 18168 : case V64QI_FTYPE_QI_V64QI_UDI:
11712 : 18168 : case V32QI_FTYPE_V32QI_V32QI_USI:
11713 : 18168 : case V32QI_FTYPE_V16QI_V32QI_USI:
11714 : 18168 : case V32QI_FTYPE_QI_V32QI_USI:
11715 : 18168 : case V16QI_FTYPE_V16QI_V16QI_UHI:
11716 : 18168 : case V16QI_FTYPE_QI_V16QI_UHI:
11717 : 18168 : case V32HI_FTYPE_V8HI_V32HI_USI:
11718 : 18168 : case V32HI_FTYPE_V32BF_V32HI_USI:
11719 : 18168 : case V32HI_FTYPE_HI_V32HI_USI:
11720 : 18168 : case V16HI_FTYPE_V8HI_V16HI_UHI:
11721 : 18168 : case V16HI_FTYPE_V16BF_V16HI_UHI:
11722 : 18168 : case V16HI_FTYPE_HI_V16HI_UHI:
11723 : 18168 : case V8HI_FTYPE_V8HI_V8HI_UQI:
11724 : 18168 : case V8HI_FTYPE_V8BF_V8HI_UQI:
11725 : 18168 : case V8BF_FTYPE_V8BF_V8BF_UQI:
11726 : 18168 : case V8HI_FTYPE_HI_V8HI_UQI:
11727 : 18168 : case V16HF_FTYPE_V16HF_V16HF_UHI:
11728 : 18168 : case V8SF_FTYPE_V8HI_V8SF_UQI:
11729 : 18168 : case V4SF_FTYPE_V8HI_V4SF_UQI:
11730 : 18168 : case V8SI_FTYPE_V8HF_V8SI_UQI:
11731 : 18168 : case V8SF_FTYPE_V8HF_V8SF_UQI:
11732 : 18168 : case V8SI_FTYPE_V8SF_V8SI_UQI:
11733 : 18168 : case V4SI_FTYPE_V4SF_V4SI_UQI:
11734 : 18168 : case V4SI_FTYPE_V8HF_V4SI_UQI:
11735 : 18168 : case V4SF_FTYPE_V8HF_V4SF_UQI:
11736 : 18168 : case V4DI_FTYPE_V8HF_V4DI_UQI:
11737 : 18168 : case V4DI_FTYPE_V4SF_V4DI_UQI:
11738 : 18168 : case V2DI_FTYPE_V8HF_V2DI_UQI:
11739 : 18168 : case V2DI_FTYPE_V4SF_V2DI_UQI:
11740 : 18168 : case V8HF_FTYPE_V8HF_V8HF_UQI:
11741 : 18168 : case V8HF_FTYPE_V8HF_V8HF_V8HF:
11742 : 18168 : case V8HF_FTYPE_V8HI_V8HF_UQI:
11743 : 18168 : case V8HF_FTYPE_V8SI_V8HF_UQI:
11744 : 18168 : case V8HF_FTYPE_V8SF_V8HF_UQI:
11745 : 18168 : case V8HF_FTYPE_V4SI_V8HF_UQI:
11746 : 18168 : case V8HF_FTYPE_V4SF_V8HF_UQI:
11747 : 18168 : case V8HF_FTYPE_V4DI_V8HF_UQI:
11748 : 18168 : case V8HF_FTYPE_V4DF_V8HF_UQI:
11749 : 18168 : case V8HF_FTYPE_V2DI_V8HF_UQI:
11750 : 18168 : case V8HF_FTYPE_V2DF_V8HF_UQI:
11751 : 18168 : case V4SF_FTYPE_V4DI_V4SF_UQI:
11752 : 18168 : case V4SF_FTYPE_V2DI_V4SF_UQI:
11753 : 18168 : case V4DF_FTYPE_V4DI_V4DF_UQI:
11754 : 18168 : case V4DF_FTYPE_V8HF_V4DF_UQI:
11755 : 18168 : case V2DF_FTYPE_V8HF_V2DF_UQI:
11756 : 18168 : case V2DF_FTYPE_V2DI_V2DF_UQI:
11757 : 18168 : case V16QI_FTYPE_V8HI_V16QI_UQI:
11758 : 18168 : case V16QI_FTYPE_V16HI_V16QI_UHI:
11759 : 18168 : case V16QI_FTYPE_V4SI_V16QI_UQI:
11760 : 18168 : case V16QI_FTYPE_V8SI_V16QI_UQI:
11761 : 18168 : case V8HI_FTYPE_V8HF_V8HI_UQI:
11762 : 18168 : case V8HI_FTYPE_V4SI_V8HI_UQI:
11763 : 18168 : case V8HI_FTYPE_V8SI_V8HI_UQI:
11764 : 18168 : case V16QI_FTYPE_V2DI_V16QI_UQI:
11765 : 18168 : case V16QI_FTYPE_V4DI_V16QI_UQI:
11766 : 18168 : case V8HI_FTYPE_V2DI_V8HI_UQI:
11767 : 18168 : case V8HI_FTYPE_V4DI_V8HI_UQI:
11768 : 18168 : case V4SI_FTYPE_V2DI_V4SI_UQI:
11769 : 18168 : case V4SI_FTYPE_V4DI_V4SI_UQI:
11770 : 18168 : case V32QI_FTYPE_V32HI_V32QI_USI:
11771 : 18168 : case UHI_FTYPE_V16QI_V16QI_UHI:
11772 : 18168 : case USI_FTYPE_V32QI_V32QI_USI:
11773 : 18168 : case UDI_FTYPE_V64QI_V64QI_UDI:
11774 : 18168 : case UQI_FTYPE_V8HI_V8HI_UQI:
11775 : 18168 : case UHI_FTYPE_V16HI_V16HI_UHI:
11776 : 18168 : case USI_FTYPE_V32HI_V32HI_USI:
11777 : 18168 : case UQI_FTYPE_V4SI_V4SI_UQI:
11778 : 18168 : case UQI_FTYPE_V8SI_V8SI_UQI:
11779 : 18168 : case UQI_FTYPE_V2DI_V2DI_UQI:
11780 : 18168 : case UQI_FTYPE_V4DI_V4DI_UQI:
11781 : 18168 : case V4SF_FTYPE_V2DF_V4SF_UQI:
11782 : 18168 : case V4SF_FTYPE_V4DF_V4SF_UQI:
11783 : 18168 : case V16SI_FTYPE_V16SI_V16SI_UHI:
11784 : 18168 : case V16SI_FTYPE_V4SI_V16SI_UHI:
11785 : 18168 : case V2DI_FTYPE_V4SI_V2DI_UQI:
11786 : 18168 : case V2DI_FTYPE_V8HI_V2DI_UQI:
11787 : 18168 : case V2DI_FTYPE_V16QI_V2DI_UQI:
11788 : 18168 : case V4DI_FTYPE_V4DI_V4DI_UQI:
11789 : 18168 : case V4DI_FTYPE_V4SI_V4DI_UQI:
11790 : 18168 : case V4DI_FTYPE_V8HI_V4DI_UQI:
11791 : 18168 : case V4DI_FTYPE_V16QI_V4DI_UQI:
11792 : 18168 : case V4DI_FTYPE_V4DF_V4DI_UQI:
11793 : 18168 : case V2DI_FTYPE_V2DF_V2DI_UQI:
11794 : 18168 : case V4SI_FTYPE_V4DF_V4SI_UQI:
11795 : 18168 : case V4SI_FTYPE_V2DF_V4SI_UQI:
11796 : 18168 : case V4SI_FTYPE_V8HI_V4SI_UQI:
11797 : 18168 : case V4SI_FTYPE_V16QI_V4SI_UQI:
11798 : 18168 : case V4DI_FTYPE_V4DI_V4DI_V4DI:
11799 : 18168 : case V8DF_FTYPE_V2DF_V8DF_UQI:
11800 : 18168 : case V8DF_FTYPE_V4DF_V8DF_UQI:
11801 : 18168 : case V8DF_FTYPE_V8DF_V8DF_UQI:
11802 : 18168 : case V8SF_FTYPE_V8SF_V8SF_UQI:
11803 : 18168 : case V8SF_FTYPE_V8SI_V8SF_UQI:
11804 : 18168 : case V4DF_FTYPE_V4DF_V4DF_UQI:
11805 : 18168 : case V4SF_FTYPE_V4SF_V4SF_UQI:
11806 : 18168 : case V2DF_FTYPE_V2DF_V2DF_UQI:
11807 : 18168 : case V2DF_FTYPE_V4SF_V2DF_UQI:
11808 : 18168 : case V2DF_FTYPE_V4SI_V2DF_UQI:
11809 : 18168 : case V4SF_FTYPE_V4SI_V4SF_UQI:
11810 : 18168 : case V4DF_FTYPE_V4SF_V4DF_UQI:
11811 : 18168 : case V4DF_FTYPE_V4SI_V4DF_UQI:
11812 : 18168 : case V8SI_FTYPE_V8SI_V8SI_UQI:
11813 : 18168 : case V8SI_FTYPE_V8HI_V8SI_UQI:
11814 : 18168 : case V8SI_FTYPE_V16QI_V8SI_UQI:
11815 : 18168 : case V8DF_FTYPE_V8SI_V8DF_UQI:
11816 : 18168 : case V8DI_FTYPE_DI_V8DI_UQI:
11817 : 18168 : case V16SF_FTYPE_V8SF_V16SF_UHI:
11818 : 18168 : case V16SI_FTYPE_V8SI_V16SI_UHI:
11819 : 18168 : case V16HF_FTYPE_V16HI_V16HF_UHI:
11820 : 18168 : case V16HF_FTYPE_V16HF_V16HF_V16HF:
11821 : 18168 : case V16HI_FTYPE_V16HF_V16HI_UHI:
11822 : 18168 : case V16HI_FTYPE_V16HI_V16HI_UHI:
11823 : 18168 : case V16BF_FTYPE_V16BF_V16BF_UHI:
11824 : 18168 : case V8HI_FTYPE_V16QI_V8HI_UQI:
11825 : 18168 : case V16HI_FTYPE_V16QI_V16HI_UHI:
11826 : 18168 : case V32HI_FTYPE_V32HI_V32HI_USI:
11827 : 18168 : case V32BF_FTYPE_V32BF_V32BF_USI:
11828 : 18168 : case V32HI_FTYPE_V32QI_V32HI_USI:
11829 : 18168 : case V8DI_FTYPE_V16QI_V8DI_UQI:
11830 : 18168 : case V8DI_FTYPE_V2DI_V8DI_UQI:
11831 : 18168 : case V8DI_FTYPE_V4DI_V8DI_UQI:
11832 : 18168 : case V8DI_FTYPE_V8DI_V8DI_UQI:
11833 : 18168 : case V8DI_FTYPE_V8HI_V8DI_UQI:
11834 : 18168 : case V8DI_FTYPE_V8SI_V8DI_UQI:
11835 : 18168 : case V8HI_FTYPE_V8DI_V8HI_UQI:
11836 : 18168 : case V8SI_FTYPE_V8DI_V8SI_UQI:
11837 : 18168 : case V4SI_FTYPE_V4SI_V4SI_V4SI:
11838 : 18168 : case V4DI_FTYPE_V4DI_V4DI_V2DI:
11839 : 18168 : case V16SI_FTYPE_V16SI_V16SI_V16SI:
11840 : 18168 : case V8DI_FTYPE_V8DI_V8DI_V8DI:
11841 : 18168 : case V32HI_FTYPE_V32HI_V32HI_V32HI:
11842 : 18168 : case V2DI_FTYPE_V2DI_V2DI_V2DI:
11843 : 18168 : case V16HI_FTYPE_V16HI_V16HI_V16HI:
11844 : 18168 : case V8SI_FTYPE_V8SI_V8SI_V8SI:
11845 : 18168 : case V8HI_FTYPE_V8HI_V8HI_V8HI:
11846 : 18168 : case V32BF_FTYPE_V16SF_V16SF_USI:
11847 : 18168 : case V16BF_FTYPE_V8SF_V8SF_UHI:
11848 : 18168 : case V8BF_FTYPE_V4SF_V4SF_UQI:
11849 : 18168 : case V16BF_FTYPE_V16SF_V16BF_UHI:
11850 : 18168 : case V8BF_FTYPE_V8SF_V8BF_UQI:
11851 : 18168 : case V8BF_FTYPE_V4SF_V8BF_UQI:
11852 : 18168 : case V16SF_FTYPE_V16SF_V32BF_V32BF:
11853 : 18168 : case V8SF_FTYPE_V8SF_V16BF_V16BF:
11854 : 18168 : case V4SF_FTYPE_V4SF_V8BF_V8BF:
11855 : 18168 : case V16QI_FTYPE_V16QI_V8HF_V8HF:
11856 : 18168 : case V32QI_FTYPE_V32QI_V16HF_V16HF:
11857 : 18168 : case V64QI_FTYPE_V64QI_V32HF_V32HF:
11858 : 18168 : case V16QI_FTYPE_V8HF_V16QI_UQI:
11859 : 18168 : case V16QI_FTYPE_V16HF_V16QI_UHI:
11860 : 18168 : case V32QI_FTYPE_V32HF_V32QI_USI:
11861 : 18168 : case V8HF_FTYPE_V16QI_V8HF_UQI:
11862 : 18168 : case V16HF_FTYPE_V16QI_V16HF_UHI:
11863 : 18168 : case V32HF_FTYPE_V32QI_V32HF_USI:
11864 : 18168 : case V16SI_FTYPE_V16SF_V16SI_UHI:
11865 : 18168 : case V32HI_FTYPE_V32HF_V32HI_USI:
11866 : 18168 : case V8DI_FTYPE_V8SF_V8DI_UQI:
11867 : 18168 : case V8DI_FTYPE_V8DF_V8DI_UQI:
11868 : 18168 : case V8SI_FTYPE_V8DF_V8SI_UQI:
11869 : 18168 : nargs = 3;
11870 : 18168 : break;
11871 : 1475 : case V32QI_FTYPE_V32QI_V32QI_INT:
11872 : 1475 : case V16HI_FTYPE_V16HI_V16HI_INT:
11873 : 1475 : case V16QI_FTYPE_V16QI_V16QI_INT:
11874 : 1475 : case V4DI_FTYPE_V4DI_V4DI_INT:
11875 : 1475 : case V8HI_FTYPE_V8HI_V8HI_INT:
11876 : 1475 : case V8SI_FTYPE_V8SI_V8SI_INT:
11877 : 1475 : case V8SI_FTYPE_V8SI_V4SI_INT:
11878 : 1475 : case V8SF_FTYPE_V8SF_V8SF_INT:
11879 : 1475 : case V8SF_FTYPE_V8SF_V4SF_INT:
11880 : 1475 : case V4SI_FTYPE_V4SI_V4SI_INT:
11881 : 1475 : case V4DF_FTYPE_V4DF_V4DF_INT:
11882 : 1475 : case V16SF_FTYPE_V16SF_V16SF_INT:
11883 : 1475 : case V16SF_FTYPE_V16SF_V4SF_INT:
11884 : 1475 : case V16SI_FTYPE_V16SI_V4SI_INT:
11885 : 1475 : case V4DF_FTYPE_V4DF_V2DF_INT:
11886 : 1475 : case V4SF_FTYPE_V4SF_V4SF_INT:
11887 : 1475 : case V2DI_FTYPE_V2DI_V2DI_INT:
11888 : 1475 : case V4DI_FTYPE_V4DI_V2DI_INT:
11889 : 1475 : case V2DF_FTYPE_V2DF_V2DF_INT:
11890 : 1475 : case UQI_FTYPE_V8DI_V8UDI_INT:
11891 : 1475 : case UQI_FTYPE_V8DF_V8DF_INT:
11892 : 1475 : case UQI_FTYPE_V2DF_V2DF_INT:
11893 : 1475 : case UQI_FTYPE_V4SF_V4SF_INT:
11894 : 1475 : case UHI_FTYPE_V16SI_V16SI_INT:
11895 : 1475 : case UHI_FTYPE_V16SF_V16SF_INT:
11896 : 1475 : case V64QI_FTYPE_V64QI_V64QI_INT:
11897 : 1475 : case V32HI_FTYPE_V32HI_V32HI_INT:
11898 : 1475 : case V16SI_FTYPE_V16SI_V16SI_INT:
11899 : 1475 : case V8DI_FTYPE_V8DI_V8DI_INT:
11900 : 1475 : nargs = 3;
11901 : 1475 : nargs_constant = 1;
11902 : 1475 : break;
11903 : 47 : case V4DI_FTYPE_V4DI_V4DI_INT_CONVERT:
11904 : 47 : nargs = 3;
11905 : 47 : rmode = V4DImode;
11906 : 47 : nargs_constant = 1;
11907 : 47 : break;
11908 : 80 : case V2DI_FTYPE_V2DI_V2DI_INT_CONVERT:
11909 : 80 : nargs = 3;
11910 : 80 : rmode = V2DImode;
11911 : 80 : nargs_constant = 1;
11912 : 80 : break;
11913 : 48 : case V1DI_FTYPE_V1DI_V1DI_INT_CONVERT:
11914 : 48 : nargs = 3;
11915 : 48 : rmode = DImode;
11916 : 48 : nargs_constant = 1;
11917 : 48 : break;
11918 : 20 : case V2DI_FTYPE_V2DI_UINT_UINT:
11919 : 20 : nargs = 3;
11920 : 20 : nargs_constant = 2;
11921 : 20 : break;
11922 : 8 : case V8DI_FTYPE_V8DI_V8DI_INT_CONVERT:
11923 : 8 : nargs = 3;
11924 : 8 : rmode = V8DImode;
11925 : 8 : nargs_constant = 1;
11926 : 8 : break;
11927 : 16 : case V8DI_FTYPE_V8DI_V8DI_INT_V8DI_UDI_CONVERT:
11928 : 16 : nargs = 5;
11929 : 16 : rmode = V8DImode;
11930 : 16 : mask_pos = 2;
11931 : 16 : nargs_constant = 1;
11932 : 16 : break;
11933 : 311 : case QI_FTYPE_V8DF_INT_UQI:
11934 : 311 : case QI_FTYPE_V4DF_INT_UQI:
11935 : 311 : case QI_FTYPE_V2DF_INT_UQI:
11936 : 311 : case HI_FTYPE_V16SF_INT_UHI:
11937 : 311 : case QI_FTYPE_V8SF_INT_UQI:
11938 : 311 : case QI_FTYPE_V4SF_INT_UQI:
11939 : 311 : case QI_FTYPE_V8HF_INT_UQI:
11940 : 311 : case HI_FTYPE_V16HF_INT_UHI:
11941 : 311 : case SI_FTYPE_V32HF_INT_USI:
11942 : 311 : case QI_FTYPE_V8BF_INT_UQI:
11943 : 311 : case HI_FTYPE_V16BF_INT_UHI:
11944 : 311 : case SI_FTYPE_V32BF_INT_USI:
11945 : 311 : case V4SI_FTYPE_V4SI_V4SI_UHI:
11946 : 311 : case V8SI_FTYPE_V8SI_V8SI_UHI:
11947 : 311 : nargs = 3;
11948 : 311 : mask_pos = 1;
11949 : 311 : nargs_constant = 1;
11950 : 311 : break;
11951 : 17 : case V4DI_FTYPE_V4DI_V4DI_INT_V4DI_USI_CONVERT:
11952 : 17 : nargs = 5;
11953 : 17 : rmode = V4DImode;
11954 : 17 : mask_pos = 2;
11955 : 17 : nargs_constant = 1;
11956 : 17 : break;
11957 : 17 : case V2DI_FTYPE_V2DI_V2DI_INT_V2DI_UHI_CONVERT:
11958 : 17 : nargs = 5;
11959 : 17 : rmode = V2DImode;
11960 : 17 : mask_pos = 2;
11961 : 17 : nargs_constant = 1;
11962 : 17 : break;
11963 : 17073 : case V32QI_FTYPE_V32QI_V32QI_V32QI_USI:
11964 : 17073 : case V32HI_FTYPE_V32HI_V32HI_V32HI_USI:
11965 : 17073 : case V32BF_FTYPE_V32BF_V32BF_V32BF_USI:
11966 : 17073 : case V32HI_FTYPE_V64QI_V64QI_V32HI_USI:
11967 : 17073 : case V16SI_FTYPE_V32HI_V32HI_V16SI_UHI:
11968 : 17073 : case V64QI_FTYPE_V64QI_V64QI_V64QI_UDI:
11969 : 17073 : case V32HI_FTYPE_V32HI_V8HI_V32HI_USI:
11970 : 17073 : case V16HI_FTYPE_V16HI_V8HI_V16HI_UHI:
11971 : 17073 : case V8SI_FTYPE_V8SI_V4SI_V8SI_UQI:
11972 : 17073 : case V4DI_FTYPE_V4DI_V2DI_V4DI_UQI:
11973 : 17073 : case V64QI_FTYPE_V32HI_V32HI_V64QI_UDI:
11974 : 17073 : case V32QI_FTYPE_V16HI_V16HI_V32QI_USI:
11975 : 17073 : case V16QI_FTYPE_V8HI_V8HI_V16QI_UHI:
11976 : 17073 : case V32HI_FTYPE_V16SI_V16SI_V32HI_USI:
11977 : 17073 : case V16HI_FTYPE_V8SI_V8SI_V16HI_UHI:
11978 : 17073 : case V8HI_FTYPE_V4SI_V4SI_V8HI_UQI:
11979 : 17073 : case V4DF_FTYPE_V4DF_V4DI_V4DF_UQI:
11980 : 17073 : case V32HF_FTYPE_V32HF_V32HF_V32HF_USI:
11981 : 17073 : case V8SF_FTYPE_V8SF_V8SI_V8SF_UQI:
11982 : 17073 : case V4SF_FTYPE_V4SF_V4SI_V4SF_UQI:
11983 : 17073 : case V2DF_FTYPE_V2DF_V2DI_V2DF_UQI:
11984 : 17073 : case V2DI_FTYPE_V4SI_V4SI_V2DI_UQI:
11985 : 17073 : case V4DI_FTYPE_V8SI_V8SI_V4DI_UQI:
11986 : 17073 : case V4DF_FTYPE_V4DI_V4DF_V4DF_UQI:
11987 : 17073 : case V8SF_FTYPE_V8SI_V8SF_V8SF_UQI:
11988 : 17073 : case V2DF_FTYPE_V2DI_V2DF_V2DF_UQI:
11989 : 17073 : case V4SF_FTYPE_V4SI_V4SF_V4SF_UQI:
11990 : 17073 : case V16SF_FTYPE_V16SF_V16SF_V16SF_UHI:
11991 : 17073 : case V16SF_FTYPE_V16SF_V16SI_V16SF_UHI:
11992 : 17073 : case V16SF_FTYPE_V16SI_V16SF_V16SF_UHI:
11993 : 17073 : case V16SI_FTYPE_V16SI_V16SI_V16SI_UHI:
11994 : 17073 : case V16SI_FTYPE_V16SI_V4SI_V16SI_UHI:
11995 : 17073 : case V8HI_FTYPE_V8HI_V8HI_V8HI_UQI:
11996 : 17073 : case V8BF_FTYPE_V8BF_V8BF_V8BF_UQI:
11997 : 17073 : case V8SI_FTYPE_V8SI_V8SI_V8SI_UQI:
11998 : 17073 : case V4SI_FTYPE_V4SI_V4SI_V4SI_UQI:
11999 : 17073 : case V16HF_FTYPE_V16HF_V16HF_V16HF_UQI:
12000 : 17073 : case V16HF_FTYPE_V16HF_V16HF_V16HF_UHI:
12001 : 17073 : case V8SF_FTYPE_V8SF_V8SF_V8SF_UQI:
12002 : 17073 : case V16QI_FTYPE_V16QI_V16QI_V16QI_UHI:
12003 : 17073 : case V16HI_FTYPE_V16HI_V16HI_V16HI_UHI:
12004 : 17073 : case V16BF_FTYPE_V16BF_V16BF_V16BF_UHI:
12005 : 17073 : case V2DI_FTYPE_V2DI_V2DI_V2DI_UQI:
12006 : 17073 : case V2DF_FTYPE_V2DF_V2DF_V2DF_UQI:
12007 : 17073 : case V4DI_FTYPE_V4DI_V4DI_V4DI_UQI:
12008 : 17073 : case V4DF_FTYPE_V4DF_V4DF_V4DF_UQI:
12009 : 17073 : case V8HF_FTYPE_V8HF_V8HF_V8HF_UQI:
12010 : 17073 : case V4SF_FTYPE_V4SF_V4SF_V4SF_UQI:
12011 : 17073 : case V8DF_FTYPE_V8DF_V8DF_V8DF_UQI:
12012 : 17073 : case V8DF_FTYPE_V8DF_V8DI_V8DF_UQI:
12013 : 17073 : case V8DF_FTYPE_V8DI_V8DF_V8DF_UQI:
12014 : 17073 : case V8DI_FTYPE_V16SI_V16SI_V8DI_UQI:
12015 : 17073 : case V8DI_FTYPE_V8DI_V2DI_V8DI_UQI:
12016 : 17073 : case V8DI_FTYPE_V8DI_V8DI_V8DI_UQI:
12017 : 17073 : case V8HI_FTYPE_V16QI_V16QI_V8HI_UQI:
12018 : 17073 : case V16HI_FTYPE_V32QI_V32QI_V16HI_UHI:
12019 : 17073 : case V8SI_FTYPE_V16HI_V16HI_V8SI_UQI:
12020 : 17073 : case V4SI_FTYPE_V8HI_V8HI_V4SI_UQI:
12021 : 17073 : case V32BF_FTYPE_V16SF_V16SF_V32BF_USI:
12022 : 17073 : case V16BF_FTYPE_V8SF_V8SF_V16BF_UHI:
12023 : 17073 : case V8BF_FTYPE_V4SF_V4SF_V8BF_UQI:
12024 : 17073 : case V32HF_FTYPE_V16SF_V16SF_V32HF_USI:
12025 : 17073 : case V16HF_FTYPE_V8SF_V8SF_V16HF_UHI:
12026 : 17073 : case V8HF_FTYPE_V4SF_V4SF_V8HF_UQI:
12027 : 17073 : case V16QI_FTYPE_V8HF_V8HF_V16QI_UHI:
12028 : 17073 : case V32QI_FTYPE_V16HF_V16HF_V32QI_USI:
12029 : 17073 : case V64QI_FTYPE_V32HF_V32HF_V64QI_UDI:
12030 : 17073 : case V16QI_FTYPE_V16QI_V8HF_V16QI_UHI:
12031 : 17073 : case V16QI_FTYPE_V32QI_V16HF_V16QI_UHI:
12032 : 17073 : case V32QI_FTYPE_V64QI_V32HF_V32QI_USI:
12033 : 17073 : nargs = 4;
12034 : 17073 : break;
12035 : 11 : case V2DF_FTYPE_V2DF_V2DF_V2DI_INT:
12036 : 11 : case V4DF_FTYPE_V4DF_V4DF_V4DI_INT:
12037 : 11 : case V4SF_FTYPE_V4SF_V4SF_V4SI_INT:
12038 : 11 : case V8SF_FTYPE_V8SF_V8SF_V8SI_INT:
12039 : 11 : case V16SF_FTYPE_V16SF_V16SF_V16SI_INT:
12040 : 11 : case V4SI_FTYPE_V4SI_V4SI_V4SI_INT:
12041 : 11 : nargs = 4;
12042 : 11 : nargs_constant = 1;
12043 : 11 : break;
12044 : 3687 : case UQI_FTYPE_V4DI_V4DI_INT_UQI:
12045 : 3687 : case UQI_FTYPE_V8SI_V8SI_INT_UQI:
12046 : 3687 : case QI_FTYPE_V4DF_V4DF_INT_UQI:
12047 : 3687 : case QI_FTYPE_V8SF_V8SF_INT_UQI:
12048 : 3687 : case UHI_FTYPE_V16HF_V16HF_INT_UHI:
12049 : 3687 : case UQI_FTYPE_V2DI_V2DI_INT_UQI:
12050 : 3687 : case UQI_FTYPE_V4SI_V4SI_INT_UQI:
12051 : 3687 : case UQI_FTYPE_V2DF_V2DF_INT_UQI:
12052 : 3687 : case UQI_FTYPE_V4SF_V4SF_INT_UQI:
12053 : 3687 : case UQI_FTYPE_V8HF_V8HF_INT_UQI:
12054 : 3687 : case UDI_FTYPE_V64QI_V64QI_INT_UDI:
12055 : 3687 : case USI_FTYPE_V32QI_V32QI_INT_USI:
12056 : 3687 : case UHI_FTYPE_V16QI_V16QI_INT_UHI:
12057 : 3687 : case USI_FTYPE_V32HI_V32HI_INT_USI:
12058 : 3687 : case USI_FTYPE_V32BF_V32BF_INT_USI:
12059 : 3687 : case USI_FTYPE_V32HF_V32HF_INT_USI:
12060 : 3687 : case UHI_FTYPE_V16HI_V16HI_INT_UHI:
12061 : 3687 : case UHI_FTYPE_V16BF_V16BF_INT_UHI:
12062 : 3687 : case UQI_FTYPE_V8HI_V8HI_INT_UQI:
12063 : 3687 : case UQI_FTYPE_V8BF_V8BF_INT_UQI:
12064 : 3687 : nargs = 4;
12065 : 3687 : mask_pos = 1;
12066 : 3687 : nargs_constant = 1;
12067 : 3687 : break;
12068 : 23 : case V2DI_FTYPE_V2DI_V2DI_UINT_UINT:
12069 : 23 : nargs = 4;
12070 : 23 : nargs_constant = 2;
12071 : 23 : break;
12072 : 67 : case UCHAR_FTYPE_UCHAR_UINT_UINT_PUNSIGNED:
12073 : 67 : case UCHAR_FTYPE_UCHAR_ULONGLONG_ULONGLONG_PULONGLONG:
12074 : 67 : case V16SF_FTYPE_V16SF_V32BF_V32BF_UHI:
12075 : 67 : case V8SF_FTYPE_V8SF_V16BF_V16BF_UQI:
12076 : 67 : case V4SF_FTYPE_V4SF_V8BF_V8BF_UQI:
12077 : 67 : nargs = 4;
12078 : 67 : break;
12079 : 667 : case UQI_FTYPE_V8DI_V8DI_INT_UQI:
12080 : 667 : case UHI_FTYPE_V16SI_V16SI_INT_UHI:
12081 : 667 : mask_pos = 1;
12082 : 667 : nargs = 4;
12083 : 667 : nargs_constant = 1;
12084 : 667 : break;
12085 : 3754 : case V8SF_FTYPE_V8SF_INT_V8SF_UQI:
12086 : 3754 : case V4SF_FTYPE_V4SF_INT_V4SF_UQI:
12087 : 3754 : case V2DF_FTYPE_V4DF_INT_V2DF_UQI:
12088 : 3754 : case V2DI_FTYPE_V4DI_INT_V2DI_UQI:
12089 : 3754 : case V8SF_FTYPE_V16SF_INT_V8SF_UQI:
12090 : 3754 : case V8SI_FTYPE_V16SI_INT_V8SI_UQI:
12091 : 3754 : case V2DF_FTYPE_V8DF_INT_V2DF_UQI:
12092 : 3754 : case V2DI_FTYPE_V8DI_INT_V2DI_UQI:
12093 : 3754 : case V4SF_FTYPE_V8SF_INT_V4SF_UQI:
12094 : 3754 : case V4SI_FTYPE_V8SI_INT_V4SI_UQI:
12095 : 3754 : case V8HI_FTYPE_V8SF_INT_V8HI_UQI:
12096 : 3754 : case V8HI_FTYPE_V4SF_INT_V8HI_UQI:
12097 : 3754 : case V32HI_FTYPE_V32HI_INT_V32HI_USI:
12098 : 3754 : case V16HI_FTYPE_V16HI_INT_V16HI_UHI:
12099 : 3754 : case V8HI_FTYPE_V8HI_INT_V8HI_UQI:
12100 : 3754 : case V32BF_FTYPE_V32BF_INT_V32BF_USI:
12101 : 3754 : case V16BF_FTYPE_V16BF_INT_V16BF_UHI:
12102 : 3754 : case V8BF_FTYPE_V8BF_INT_V8BF_UQI:
12103 : 3754 : case V4DI_FTYPE_V4DI_INT_V4DI_UQI:
12104 : 3754 : case V2DI_FTYPE_V2DI_INT_V2DI_UQI:
12105 : 3754 : case V8SI_FTYPE_V8SI_INT_V8SI_UQI:
12106 : 3754 : case V4SI_FTYPE_V4SI_INT_V4SI_UQI:
12107 : 3754 : case V4DF_FTYPE_V4DF_INT_V4DF_UQI:
12108 : 3754 : case V2DF_FTYPE_V2DF_INT_V2DF_UQI:
12109 : 3754 : case V8DF_FTYPE_V8DF_INT_V8DF_UQI:
12110 : 3754 : case V16SF_FTYPE_V16SF_INT_V16SF_UHI:
12111 : 3754 : case V16HI_FTYPE_V16SF_INT_V16HI_UHI:
12112 : 3754 : case V16SI_FTYPE_V16SI_INT_V16SI_UHI:
12113 : 3754 : case V16HF_FTYPE_V16HF_INT_V16HF_UHI:
12114 : 3754 : case V8HF_FTYPE_V8HF_INT_V8HF_UQI:
12115 : 3754 : case V4SI_FTYPE_V16SI_INT_V4SI_UQI:
12116 : 3754 : case V4DI_FTYPE_V8DI_INT_V4DI_UQI:
12117 : 3754 : case V4DF_FTYPE_V8DF_INT_V4DF_UQI:
12118 : 3754 : case V4SF_FTYPE_V16SF_INT_V4SF_UQI:
12119 : 3754 : case V8DI_FTYPE_V8DI_INT_V8DI_UQI:
12120 : 3754 : nargs = 4;
12121 : 3754 : mask_pos = 2;
12122 : 3754 : nargs_constant = 1;
12123 : 3754 : break;
12124 : 1648 : case V16SF_FTYPE_V16SF_V4SF_INT_V16SF_UHI:
12125 : 1648 : case V16SI_FTYPE_V16SI_V4SI_INT_V16SI_UHI:
12126 : 1648 : case V8DF_FTYPE_V8DF_V8DF_INT_V8DF_UQI:
12127 : 1648 : case V8DI_FTYPE_V8DI_V8DI_INT_V8DI_UQI:
12128 : 1648 : case V16SF_FTYPE_V16SF_V16SF_INT_V16SF_UHI:
12129 : 1648 : case V16SI_FTYPE_V16SI_V16SI_INT_V16SI_UHI:
12130 : 1648 : case V4SF_FTYPE_V4SF_V4SF_INT_V4SF_UQI:
12131 : 1648 : case V2DF_FTYPE_V2DF_V2DF_INT_V2DF_UQI:
12132 : 1648 : case V8DF_FTYPE_V8DF_V4DF_INT_V8DF_UQI:
12133 : 1648 : case V8DI_FTYPE_V8DI_V4DI_INT_V8DI_UQI:
12134 : 1648 : case V4DF_FTYPE_V4DF_V4DF_INT_V4DF_UQI:
12135 : 1648 : case V8SF_FTYPE_V8SF_V8SF_INT_V8SF_UQI:
12136 : 1648 : case V8DF_FTYPE_V8DF_V2DF_INT_V8DF_UQI:
12137 : 1648 : case V8DI_FTYPE_V8DI_V2DI_INT_V8DI_UQI:
12138 : 1648 : case V8SI_FTYPE_V8SI_V8SI_INT_V8SI_UQI:
12139 : 1648 : case V4DI_FTYPE_V4DI_V4DI_INT_V4DI_UQI:
12140 : 1648 : case V4SI_FTYPE_V4SI_V4SI_INT_V4SI_UQI:
12141 : 1648 : case V2DI_FTYPE_V2DI_V2DI_INT_V2DI_UQI:
12142 : 1648 : case V32HI_FTYPE_V64QI_V64QI_INT_V32HI_USI:
12143 : 1648 : case V16HI_FTYPE_V32QI_V32QI_INT_V16HI_UHI:
12144 : 1648 : case V8HI_FTYPE_V16QI_V16QI_INT_V8HI_UQI:
12145 : 1648 : case V16SF_FTYPE_V16SF_V8SF_INT_V16SF_UHI:
12146 : 1648 : case V16SI_FTYPE_V16SI_V8SI_INT_V16SI_UHI:
12147 : 1648 : case V8SF_FTYPE_V8SF_V4SF_INT_V8SF_UQI:
12148 : 1648 : case V8SI_FTYPE_V8SI_V4SI_INT_V8SI_UQI:
12149 : 1648 : case V4DI_FTYPE_V4DI_V2DI_INT_V4DI_UQI:
12150 : 1648 : case V4DF_FTYPE_V4DF_V2DF_INT_V4DF_UQI:
12151 : 1648 : nargs = 5;
12152 : 1648 : mask_pos = 2;
12153 : 1648 : nargs_constant = 1;
12154 : 1648 : break;
12155 : 268 : case V8DI_FTYPE_V8DI_V8DI_V8DI_INT_UQI:
12156 : 268 : case V16SI_FTYPE_V16SI_V16SI_V16SI_INT_UHI:
12157 : 268 : case V2DF_FTYPE_V2DF_V2DF_V2DI_INT_UQI:
12158 : 268 : case V4SF_FTYPE_V4SF_V4SF_V4SI_INT_UQI:
12159 : 268 : case V8SF_FTYPE_V8SF_V8SF_V8SI_INT_UQI:
12160 : 268 : case V8SI_FTYPE_V8SI_V8SI_V8SI_INT_UQI:
12161 : 268 : case V4DF_FTYPE_V4DF_V4DF_V4DI_INT_UQI:
12162 : 268 : case V4DI_FTYPE_V4DI_V4DI_V4DI_INT_UQI:
12163 : 268 : case V4SI_FTYPE_V4SI_V4SI_V4SI_INT_UQI:
12164 : 268 : case V2DI_FTYPE_V2DI_V2DI_V2DI_INT_UQI:
12165 : 268 : nargs = 5;
12166 : 268 : mask_pos = 1;
12167 : 268 : nargs_constant = 1;
12168 : 268 : break;
12169 : 642 : case V64QI_FTYPE_V64QI_V64QI_INT_V64QI_UDI:
12170 : 642 : case V32QI_FTYPE_V32QI_V32QI_INT_V32QI_USI:
12171 : 642 : case V16QI_FTYPE_V16QI_V16QI_INT_V16QI_UHI:
12172 : 642 : case V32HI_FTYPE_V32HI_V32HI_INT_V32HI_INT:
12173 : 642 : case V16SI_FTYPE_V16SI_V16SI_INT_V16SI_INT:
12174 : 642 : case V8DI_FTYPE_V8DI_V8DI_INT_V8DI_INT:
12175 : 642 : case V16HI_FTYPE_V16HI_V16HI_INT_V16HI_INT:
12176 : 642 : case V8SI_FTYPE_V8SI_V8SI_INT_V8SI_INT:
12177 : 642 : case V4DI_FTYPE_V4DI_V4DI_INT_V4DI_INT:
12178 : 642 : case V8HI_FTYPE_V8HI_V8HI_INT_V8HI_INT:
12179 : 642 : case V4SI_FTYPE_V4SI_V4SI_INT_V4SI_INT:
12180 : 642 : case V2DI_FTYPE_V2DI_V2DI_INT_V2DI_INT:
12181 : 642 : case V8BF_FTYPE_V8BF_V8BF_INT_V8BF_UQI:
12182 : 642 : case V16BF_FTYPE_V16BF_V16BF_INT_V16BF_UHI:
12183 : 642 : case V32BF_FTYPE_V32BF_V32BF_INT_V32BF_USI:
12184 : 642 : case V16HF_FTYPE_V16HF_V16HF_INT_V16HF_UHI:
12185 : 642 : case V8HF_FTYPE_V8HF_V8HF_INT_V8HF_UQI:
12186 : 642 : nargs = 5;
12187 : 642 : mask_pos = 1;
12188 : 642 : nargs_constant = 2;
12189 : 642 : break;
12190 : :
12191 : 0 : default:
12192 : 0 : gcc_unreachable ();
12193 : : }
12194 : :
12195 : 55128 : gcc_assert (nargs <= ARRAY_SIZE (xops));
12196 : :
12197 : 58856 : if (comparison != UNKNOWN)
12198 : : {
12199 : 614 : gcc_assert (nargs == 2);
12200 : 614 : return ix86_expand_sse_compare (d, exp, target, swap);
12201 : : }
12202 : :
12203 : 58242 : if (rmode == VOIDmode || rmode == tmode)
12204 : : {
12205 : 58057 : if (optimize
12206 : 17698 : || target == 0
12207 : 17698 : || GET_MODE (target) != tmode
12208 : 75553 : || !insn_p->operand[0].predicate (target, tmode))
12209 : 40649 : target = gen_reg_rtx (tmode);
12210 : 17408 : else if (memory_operand (target, tmode))
12211 : 578 : num_memory++;
12212 : : real_target = target;
12213 : : }
12214 : : else
12215 : : {
12216 : 185 : real_target = gen_reg_rtx (tmode);
12217 : 185 : target = lowpart_subreg (rmode, real_target, tmode);
12218 : : }
12219 : :
12220 : 252568 : for (i = 0; i < nargs; i++)
12221 : : {
12222 : 194559 : tree arg = CALL_EXPR_ARG (exp, i);
12223 : 194559 : rtx op = ix86_expand_unsigned_small_int_cst_argument (arg);
12224 : 194559 : machine_mode mode = insn_p->operand[i + 1].mode;
12225 : : /* Need to fixup modeless constant before testing predicate. */
12226 : 194559 : op = fixup_modeless_constant (op, mode);
12227 : 194559 : bool match = insn_p->operand[i + 1].predicate (op, mode);
12228 : :
12229 : 194559 : if (second_arg_count && i == 1)
12230 : : {
12231 : : /* SIMD shift insns take either an 8-bit immediate or
12232 : : register as count. But builtin functions take int as
12233 : : count. If count doesn't match, we put it in register.
12234 : : The instructions are using 64-bit count, if op is just
12235 : : 32-bit, zero-extend it, as negative shift counts
12236 : : are undefined behavior and zero-extension is more
12237 : : efficient. */
12238 : 2887 : if (!match)
12239 : : {
12240 : 1748 : if (SCALAR_INT_MODE_P (GET_MODE (op)))
12241 : 489 : op = convert_modes (mode, GET_MODE (op), op, 1);
12242 : : else
12243 : 1259 : op = lowpart_subreg (mode, op, GET_MODE (op));
12244 : 1748 : if (!insn_p->operand[i + 1].predicate (op, mode))
12245 : 190 : op = copy_to_reg (op);
12246 : : }
12247 : : }
12248 : 191672 : else if ((mask_pos && (nargs - i - mask_pos) == nargs_constant) ||
12249 : 145431 : (!mask_pos && (nargs - i) <= nargs_constant))
12250 : : {
12251 : 16015 : if (!match)
12252 : 233 : switch (icode)
12253 : : {
12254 : 2 : case CODE_FOR_avx_vinsertf128v4di:
12255 : 2 : case CODE_FOR_avx_vextractf128v4di:
12256 : 2 : error ("the last argument must be an 1-bit immediate");
12257 : 2 : return const0_rtx;
12258 : :
12259 : 8 : case CODE_FOR_avx512f_cmpv8di3_mask:
12260 : 8 : case CODE_FOR_avx512f_cmpv16si3_mask:
12261 : 8 : case CODE_FOR_avx512f_ucmpv8di3_mask:
12262 : 8 : case CODE_FOR_avx512f_ucmpv16si3_mask:
12263 : 8 : case CODE_FOR_avx512vl_cmpv4di3_mask:
12264 : 8 : case CODE_FOR_avx512vl_cmpv8si3_mask:
12265 : 8 : case CODE_FOR_avx512vl_ucmpv4di3_mask:
12266 : 8 : case CODE_FOR_avx512vl_ucmpv8si3_mask:
12267 : 8 : case CODE_FOR_avx512vl_cmpv2di3_mask:
12268 : 8 : case CODE_FOR_avx512vl_cmpv4si3_mask:
12269 : 8 : case CODE_FOR_avx512vl_ucmpv2di3_mask:
12270 : 8 : case CODE_FOR_avx512vl_ucmpv4si3_mask:
12271 : 8 : error ("the last argument must be a 3-bit immediate");
12272 : 8 : return const0_rtx;
12273 : :
12274 : 24 : case CODE_FOR_sse4_1_roundsd:
12275 : 24 : case CODE_FOR_sse4_1_roundss:
12276 : :
12277 : 24 : case CODE_FOR_sse4_1_roundpd:
12278 : 24 : case CODE_FOR_sse4_1_roundps:
12279 : 24 : case CODE_FOR_avx_roundpd256:
12280 : 24 : case CODE_FOR_avx_roundps256:
12281 : :
12282 : 24 : case CODE_FOR_sse4_1_roundpd_vec_pack_sfix:
12283 : 24 : case CODE_FOR_sse4_1_roundps_sfix:
12284 : 24 : case CODE_FOR_avx_roundpd_vec_pack_sfix256:
12285 : 24 : case CODE_FOR_avx_roundps_sfix256:
12286 : :
12287 : 24 : case CODE_FOR_sse4_1_blendps:
12288 : 24 : case CODE_FOR_avx_blendpd256:
12289 : 24 : case CODE_FOR_avx_vpermilv4df:
12290 : 24 : case CODE_FOR_avx_vpermilv4df_mask:
12291 : 24 : case CODE_FOR_avx512f_getmantv8df_mask:
12292 : 24 : case CODE_FOR_avx512f_getmantv16sf_mask:
12293 : 24 : case CODE_FOR_avx512vl_getmantv16hf_mask:
12294 : 24 : case CODE_FOR_avx512vl_getmantv8sf_mask:
12295 : 24 : case CODE_FOR_avx512vl_getmantv4df_mask:
12296 : 24 : case CODE_FOR_avx512fp16_getmantv8hf_mask:
12297 : 24 : case CODE_FOR_avx512vl_getmantv4sf_mask:
12298 : 24 : case CODE_FOR_avx512vl_getmantv2df_mask:
12299 : 24 : case CODE_FOR_avx512dq_rangepv8df_mask_round:
12300 : 24 : case CODE_FOR_avx512dq_rangepv16sf_mask_round:
12301 : 24 : case CODE_FOR_avx512dq_rangepv4df_mask:
12302 : 24 : case CODE_FOR_avx512dq_rangepv8sf_mask:
12303 : 24 : case CODE_FOR_avx512dq_rangepv2df_mask:
12304 : 24 : case CODE_FOR_avx512dq_rangepv4sf_mask:
12305 : 24 : case CODE_FOR_avx_shufpd256_mask:
12306 : 24 : error ("the last argument must be a 4-bit immediate");
12307 : 24 : return const0_rtx;
12308 : :
12309 : 15 : case CODE_FOR_sha1rnds4:
12310 : 15 : case CODE_FOR_sse4_1_blendpd:
12311 : 15 : case CODE_FOR_avx_vpermilv2df:
12312 : 15 : case CODE_FOR_avx_vpermilv2df_mask:
12313 : 15 : case CODE_FOR_xop_vpermil2v2df3:
12314 : 15 : case CODE_FOR_xop_vpermil2v4sf3:
12315 : 15 : case CODE_FOR_xop_vpermil2v4df3:
12316 : 15 : case CODE_FOR_xop_vpermil2v8sf3:
12317 : 15 : case CODE_FOR_avx512f_vinsertf32x4_mask:
12318 : 15 : case CODE_FOR_avx512f_vinserti32x4_mask:
12319 : 15 : case CODE_FOR_avx512f_vextractf32x4_mask:
12320 : 15 : case CODE_FOR_avx512f_vextracti32x4_mask:
12321 : 15 : case CODE_FOR_sse2_shufpd:
12322 : 15 : case CODE_FOR_sse2_shufpd_mask:
12323 : 15 : case CODE_FOR_avx512dq_shuf_f64x2_mask:
12324 : 15 : case CODE_FOR_avx512dq_shuf_i64x2_mask:
12325 : 15 : case CODE_FOR_avx512vl_shuf_i32x4_mask:
12326 : 15 : case CODE_FOR_avx512vl_shuf_f32x4_mask:
12327 : 15 : error ("the last argument must be a 2-bit immediate");
12328 : 15 : return const0_rtx;
12329 : :
12330 : 30 : case CODE_FOR_avx_vextractf128v4df:
12331 : 30 : case CODE_FOR_avx_vextractf128v8sf:
12332 : 30 : case CODE_FOR_avx_vextractf128v8si:
12333 : 30 : case CODE_FOR_avx_vinsertf128v4df:
12334 : 30 : case CODE_FOR_avx_vinsertf128v8sf:
12335 : 30 : case CODE_FOR_avx_vinsertf128v8si:
12336 : 30 : case CODE_FOR_avx512f_vinsertf64x4_mask:
12337 : 30 : case CODE_FOR_avx512f_vinserti64x4_mask:
12338 : 30 : case CODE_FOR_avx512f_vextractf64x4_mask:
12339 : 30 : case CODE_FOR_avx512f_vextracti64x4_mask:
12340 : 30 : case CODE_FOR_avx512dq_vinsertf32x8_mask:
12341 : 30 : case CODE_FOR_avx512dq_vinserti32x8_mask:
12342 : 30 : case CODE_FOR_avx512vl_vinsertv4df:
12343 : 30 : case CODE_FOR_avx512vl_vinsertv4di:
12344 : 30 : case CODE_FOR_avx512vl_vinsertv8sf:
12345 : 30 : case CODE_FOR_avx512vl_vinsertv8si:
12346 : 30 : error ("the last argument must be a 1-bit immediate");
12347 : 30 : return const0_rtx;
12348 : :
12349 : 16 : case CODE_FOR_avx_vmcmpv2df3:
12350 : 16 : case CODE_FOR_avx_vmcmpv4sf3:
12351 : 16 : case CODE_FOR_avx_cmpv2df3:
12352 : 16 : case CODE_FOR_avx_cmpv4sf3:
12353 : 16 : if (CONST_INT_P (op) && IN_RANGE (INTVAL (op), 8, 31))
12354 : : {
12355 : 4 : error ("'%s' needs isa option %s", d->name, "-mavx");
12356 : 4 : return const0_rtx;
12357 : : }
12358 : : /* FALLTHRU */
12359 : 18 : case CODE_FOR_avx_cmpv4df3:
12360 : 18 : case CODE_FOR_avx_cmpv8sf3:
12361 : 18 : case CODE_FOR_avx512f_cmpv8df3_mask:
12362 : 18 : case CODE_FOR_avx512f_cmpv16sf3_mask:
12363 : 18 : case CODE_FOR_avx512f_vmcmpv2df3_mask:
12364 : 18 : case CODE_FOR_avx512f_vmcmpv4sf3_mask:
12365 : 18 : case CODE_FOR_avx512bw_cmpv32hf3_mask:
12366 : 18 : case CODE_FOR_avx512vl_cmpv16hf3_mask:
12367 : 18 : case CODE_FOR_avx512fp16_cmpv8hf3_mask:
12368 : 18 : error ("the last argument must be a 5-bit immediate");
12369 : 18 : return const0_rtx;
12370 : :
12371 : 132 : default:
12372 : 132 : switch (nargs_constant)
12373 : : {
12374 : 8 : case 2:
12375 : 8 : if ((mask_pos && (nargs - i - mask_pos) == nargs_constant) ||
12376 : 8 : (!mask_pos && (nargs - i) == nargs_constant))
12377 : : {
12378 : 4 : error ("the next to last argument must be an 8-bit immediate");
12379 : 4 : break;
12380 : : }
12381 : : /* FALLTHRU */
12382 : 128 : case 1:
12383 : 128 : error ("the last argument must be an 8-bit immediate");
12384 : 128 : break;
12385 : 0 : default:
12386 : 0 : gcc_unreachable ();
12387 : : }
12388 : 132 : return const0_rtx;
12389 : : }
12390 : : }
12391 : : else
12392 : : {
12393 : 175657 : if (VECTOR_MODE_P (mode))
12394 : 126138 : op = safe_vector_operand (op, mode);
12395 : :
12396 : : /* If we aren't optimizing, only allow one memory operand to
12397 : : be generated. */
12398 : 175657 : if (memory_operand (op, mode))
12399 : : {
12400 : 29846 : num_memory++;
12401 : 29846 : if (!optimize && num_memory > 1)
12402 : 13684 : op = copy_to_mode_reg (mode, op);
12403 : : }
12404 : :
12405 : 175657 : if (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)
12406 : : {
12407 : 173356 : if (!match)
12408 : 40659 : op = copy_to_mode_reg (mode, op);
12409 : : }
12410 : : else
12411 : : {
12412 : 2301 : op = copy_to_reg (op);
12413 : 2301 : op = lowpart_subreg (mode, op, GET_MODE (op));
12414 : : }
12415 : : }
12416 : :
12417 : 194326 : xops[i] = op;
12418 : : }
12419 : :
12420 : 58009 : switch (nargs)
12421 : : {
12422 : 3114 : case 1:
12423 : 3114 : pat = GEN_FCN (icode) (real_target, xops[0]);
12424 : 3114 : break;
12425 : 5622 : case 2:
12426 : 5622 : pat = GEN_FCN (icode) (real_target, xops[0], xops[1]);
12427 : 5622 : break;
12428 : 20067 : case 3:
12429 : 20067 : pat = GEN_FCN (icode) (real_target, xops[0], xops[1], xops[2]);
12430 : 20067 : break;
12431 : 26634 : case 4:
12432 : 26634 : pat = GEN_FCN (icode) (real_target, xops[0], xops[1],
12433 : 26634 : xops[2], xops[3]);
12434 : 26634 : break;
12435 : 2572 : case 5:
12436 : 2572 : pat = GEN_FCN (icode) (real_target, xops[0], xops[1],
12437 : 2572 : xops[2], xops[3], xops[4]);
12438 : 2572 : break;
12439 : : case 6:
12440 : : pat = GEN_FCN (icode) (real_target, xops[0], xops[1],
12441 : : xops[2], xops[3], xops[4], xops[5]);
12442 : : break;
12443 : : default:
12444 : : gcc_unreachable ();
12445 : : }
12446 : :
12447 : 58009 : if (! pat)
12448 : : return 0;
12449 : :
12450 : 58009 : emit_insn (pat);
12451 : 58009 : return target;
12452 : : }
12453 : :
12454 : : /* Transform pattern of following layout:
12455 : : (set A
12456 : : (unspec [B C] UNSPEC_EMBEDDED_ROUNDING))
12457 : : )
12458 : : into:
12459 : : (set (A B)) */
12460 : :
12461 : : static rtx
12462 : 4793 : ix86_erase_embedded_rounding (rtx pat)
12463 : : {
12464 : 4793 : if (GET_CODE (pat) == INSN)
12465 : 757 : pat = PATTERN (pat);
12466 : :
12467 : 4793 : gcc_assert (GET_CODE (pat) == SET);
12468 : 4793 : rtx src = SET_SRC (pat);
12469 : 4793 : gcc_assert (XVECLEN (src, 0) == 2);
12470 : 4793 : rtx p0 = XVECEXP (src, 0, 0);
12471 : 4793 : gcc_assert (GET_CODE (src) == UNSPEC
12472 : : && XINT (src, 1) == UNSPEC_EMBEDDED_ROUNDING);
12473 : 4793 : rtx res = gen_rtx_SET (SET_DEST (pat), p0);
12474 : 4793 : return res;
12475 : : }
12476 : :
12477 : : /* Subroutine of ix86_expand_round_builtin to take care of comi insns
12478 : : with rounding. */
12479 : : static rtx
12480 : 97 : ix86_expand_sse_comi_round (const struct builtin_description *d,
12481 : : tree exp, rtx target, bool comx_ok)
12482 : : {
12483 : 97 : rtx pat, set_dst;
12484 : 97 : tree arg0 = CALL_EXPR_ARG (exp, 0);
12485 : 97 : tree arg1 = CALL_EXPR_ARG (exp, 1);
12486 : 97 : tree arg2 = CALL_EXPR_ARG (exp, 2);
12487 : 97 : tree arg3 = CALL_EXPR_ARG (exp, 3);
12488 : 97 : rtx op0 = expand_normal (arg0);
12489 : 97 : rtx op1 = expand_normal (arg1);
12490 : 97 : rtx op2 = expand_normal (arg2);
12491 : 97 : rtx op3 = expand_normal (arg3);
12492 : 97 : enum insn_code icode = d->icode;
12493 : 97 : const struct insn_data_d *insn_p = &insn_data[icode];
12494 : 97 : machine_mode mode0 = insn_p->operand[0].mode;
12495 : 97 : machine_mode mode1 = insn_p->operand[1].mode;
12496 : :
12497 : : /* See avxintrin.h for values. */
12498 : 97 : static const enum rtx_code comparisons[32] =
12499 : : {
12500 : : EQ, LT, LE, UNORDERED, NE, UNGE, UNGT, ORDERED,
12501 : : UNEQ, UNLT, UNLE, UNORDERED, LTGT, GE, GT, ORDERED,
12502 : : EQ, LT, LE, UNORDERED, NE, UNGE, UNGT, ORDERED,
12503 : : UNEQ, UNLT, UNLE, UNORDERED, LTGT, GE, GT, ORDERED
12504 : : };
12505 : 97 : static const bool ordereds[32] =
12506 : : {
12507 : : true, true, true, false, false, false, false, true,
12508 : : false, false, false, true, true, true, true, false,
12509 : : true, true, true, false, false, false, false, true,
12510 : : false, false, false, true, true, true, true, false
12511 : : };
12512 : 97 : static const bool non_signalings[32] =
12513 : : {
12514 : : true, false, false, true, true, false, false, true,
12515 : : true, false, false, true, true, false, false, true,
12516 : : false, true, true, false, false, true, true, false,
12517 : : false, true, true, false, false, true, true, false
12518 : : };
12519 : :
12520 : 97 : if (!CONST_INT_P (op2))
12521 : : {
12522 : 0 : error ("the third argument must be comparison constant");
12523 : 0 : return const0_rtx;
12524 : : }
12525 : 97 : if (INTVAL (op2) < 0 || INTVAL (op2) >= 32)
12526 : : {
12527 : 0 : error ("incorrect comparison mode");
12528 : 0 : return const0_rtx;
12529 : : }
12530 : :
12531 : 97 : if (!insn_p->operand[2].predicate (op3, SImode))
12532 : : {
12533 : 4 : error ("incorrect rounding operand");
12534 : 4 : return const0_rtx;
12535 : : }
12536 : :
12537 : 93 : if (VECTOR_MODE_P (mode0))
12538 : 93 : op0 = safe_vector_operand (op0, mode0);
12539 : 93 : if (VECTOR_MODE_P (mode1))
12540 : 93 : op1 = safe_vector_operand (op1, mode1);
12541 : :
12542 : 93 : enum rtx_code comparison = comparisons[INTVAL (op2)];
12543 : 93 : enum rtx_code orig_comp = comparison;
12544 : 93 : bool ordered = ordereds[INTVAL (op2)];
12545 : 93 : bool non_signaling = non_signalings[INTVAL (op2)];
12546 : 93 : rtx const_val = const0_rtx;
12547 : :
12548 : 93 : bool check_unordered = false;
12549 : 93 : machine_mode mode = CCFPmode;
12550 : 93 : switch (comparison)
12551 : : {
12552 : 8 : case ORDERED:
12553 : 8 : if (!ordered)
12554 : : {
12555 : 4 : if (TARGET_AVX10_2 && comx_ok)
12556 : : {
12557 : : /* Unlike VCOMI{SH,SS,SD}, VCOMX{SH,SS,SD} will set SF
12558 : : differently. So directly return true here. */
12559 : 0 : target = gen_reg_rtx (SImode);
12560 : 0 : emit_move_insn (target, const1_rtx);
12561 : 0 : return target;
12562 : : }
12563 : : else
12564 : : {
12565 : : /* NB: Use CCSmode/NE for _CMP_TRUE_UQ/_CMP_TRUE_US. */
12566 : : if (!non_signaling)
12567 : 93 : ordered = true;
12568 : 93 : mode = CCSmode;
12569 : : }
12570 : : }
12571 : : else
12572 : : {
12573 : : /* NB: Use CCPmode/NE for _CMP_ORD_Q/_CMP_ORD_S. */
12574 : : if (non_signaling)
12575 : : ordered = false;
12576 : : mode = CCPmode;
12577 : : }
12578 : : comparison = NE;
12579 : : break;
12580 : 8 : case UNORDERED:
12581 : 8 : if (ordered)
12582 : : {
12583 : 4 : if (TARGET_AVX10_2 && comx_ok)
12584 : : {
12585 : : /* Unlike VCOMI{SH,SS,SD}, VCOMX{SH,SS,SD} will set SF
12586 : : differently. So directly return false here. */
12587 : 0 : target = gen_reg_rtx (SImode);
12588 : 0 : emit_move_insn (target, const0_rtx);
12589 : 0 : return target;
12590 : : }
12591 : : else
12592 : : {
12593 : : /* NB: Use CCSmode/EQ for _CMP_FALSE_OQ/_CMP_FALSE_OS. */
12594 : : if (non_signaling)
12595 : 93 : ordered = false;
12596 : : mode = CCSmode;
12597 : : }
12598 : : }
12599 : : else
12600 : : {
12601 : : /* NB: Use CCPmode/NE for _CMP_UNORD_Q/_CMP_UNORD_S. */
12602 : : if (!non_signaling)
12603 : 93 : ordered = true;
12604 : 93 : mode = CCPmode;
12605 : : }
12606 : : comparison = EQ;
12607 : : break;
12608 : :
12609 : 38 : case LE: /* -> GE */
12610 : 38 : case LT: /* -> GT */
12611 : 38 : case UNGE: /* -> UNLE */
12612 : 38 : case UNGT: /* -> UNLT */
12613 : 38 : std::swap (op0, op1);
12614 : 38 : comparison = swap_condition (comparison);
12615 : : /* FALLTHRU */
12616 : 64 : case GT:
12617 : 64 : case GE:
12618 : 64 : case UNEQ:
12619 : 64 : case UNLT:
12620 : 64 : case UNLE:
12621 : 64 : case LTGT:
12622 : : /* These are supported by CCFPmode. NB: Use ordered/signaling
12623 : : COMI or unordered/non-signaling UCOMI. Both set ZF, PF, CF
12624 : : with NAN operands. */
12625 : 64 : if (ordered == non_signaling)
12626 : : ordered = !ordered;
12627 : : break;
12628 : : /* NB: COMI/UCOMI will set ZF with NAN operands. Use CCZmode for
12629 : : _CMP_EQ_OQ/_CMP_EQ_OS.
12630 : : Under TARGET_AVX10_2, VCOMX/VUCOMX are always generated instead
12631 : : of COMI/UCOMI, VCOMX/VUCOMX will not set ZF with NAN. */
12632 : 7 : case EQ:
12633 : 7 : if (!TARGET_AVX10_2 || !comx_ok)
12634 : 5 : check_unordered = true;
12635 : : mode = CCZmode;
12636 : : break;
12637 : 6 : case NE:
12638 : : /* NB: COMI/UCOMI will set ZF with NAN operands. Use CCZmode for
12639 : : _CMP_NEQ_UQ/_CMP_NEQ_US.
12640 : : Under TARGET_AVX10_2, VCOMX/VUCOMX are always generated instead
12641 : : of COMI/UCOMI, VCOMX/VUCOMX will not set ZF with NAN. */
12642 : 6 : gcc_assert (!ordered);
12643 : 6 : if (!TARGET_AVX10_2 || !comx_ok)
12644 : 4 : check_unordered = true;
12645 : 6 : mode = CCZmode;
12646 : 6 : const_val = const1_rtx;
12647 : 6 : break;
12648 : 0 : default:
12649 : 0 : gcc_unreachable ();
12650 : : }
12651 : :
12652 : 93 : target = gen_reg_rtx (SImode);
12653 : 93 : emit_move_insn (target, const_val);
12654 : 93 : target = gen_rtx_SUBREG (QImode, target, 0);
12655 : :
12656 : 87 : if ((optimize && !register_operand (op0, mode0))
12657 : 180 : || !insn_p->operand[0].predicate (op0, mode0))
12658 : 6 : op0 = copy_to_mode_reg (mode0, op0);
12659 : 87 : if ((optimize && !register_operand (op1, mode1))
12660 : 180 : || !insn_p->operand[1].predicate (op1, mode1))
12661 : 6 : op1 = copy_to_mode_reg (mode1, op1);
12662 : :
12663 : : /* Generate comx instead of comi when EQ/NE to avoid NAN checks.
12664 : : Use orig_comp to exclude ORDERED/UNORDERED cases. */
12665 : 93 : if ((orig_comp == EQ || orig_comp == NE)
12666 : 13 : && TARGET_AVX10_2 && comx_ok)
12667 : : {
12668 : 4 : switch (icode)
12669 : : {
12670 : : case CODE_FOR_avx512fp16_comi_round:
12671 : 93 : icode = CODE_FOR_avx10_2_comxhf_round;
12672 : : break;
12673 : 2 : case CODE_FOR_sse_comi_round:
12674 : 2 : icode = CODE_FOR_avx10_2_comxsf_round;
12675 : 2 : break;
12676 : 2 : case CODE_FOR_sse2_comi_round:
12677 : 2 : icode = CODE_FOR_avx10_2_comxdf_round;
12678 : 2 : break;
12679 : :
12680 : : default:
12681 : : break;
12682 : : }
12683 : : }
12684 : :
12685 : : /* Generate comi instead of comx when UNEQ/LTGT to avoid NAN checks. */
12686 : 93 : if ((comparison == UNEQ || comparison == LTGT)
12687 : 8 : && TARGET_AVX10_2 && comx_ok)
12688 : : {
12689 : 0 : switch (icode)
12690 : : {
12691 : : case CODE_FOR_avx10_2_comxhf_round:
12692 : 93 : icode = CODE_FOR_avx512fp16_comi_round;
12693 : : break;
12694 : 0 : case CODE_FOR_avx10_2_comxsf_round:
12695 : 0 : icode = CODE_FOR_sse_comi_round;
12696 : 0 : break;
12697 : 0 : case CODE_FOR_avx10_2_comxdf_round:
12698 : 0 : icode = CODE_FOR_sse2_comi_round;
12699 : 0 : break;
12700 : :
12701 : : default:
12702 : : break;
12703 : : }
12704 : : }
12705 : :
12706 : : /*
12707 : : 1. COMI/VCOMX: ordered and signaling.
12708 : : 2. UCOMI/VUCOMX: unordered and non-signaling.
12709 : : */
12710 : 93 : if (non_signaling)
12711 : 36 : switch (icode)
12712 : : {
12713 : : case CODE_FOR_sse_comi_round:
12714 : : icode = CODE_FOR_sse_ucomi_round;
12715 : : break;
12716 : 17 : case CODE_FOR_sse2_comi_round:
12717 : 17 : icode = CODE_FOR_sse2_ucomi_round;
12718 : 17 : break;
12719 : 0 : case CODE_FOR_avx512fp16_comi_round:
12720 : 0 : icode = CODE_FOR_avx512fp16_ucomi_round;
12721 : 0 : break;
12722 : 1 : case CODE_FOR_avx10_2_comxsf_round:
12723 : 1 : icode = CODE_FOR_avx10_2_ucomxsf_round;
12724 : 1 : break;
12725 : 0 : case CODE_FOR_avx10_2_comxhf_round:
12726 : 0 : icode = CODE_FOR_avx10_2_ucomxhf_round;
12727 : 0 : break;
12728 : 1 : case CODE_FOR_avx10_2_comxdf_round:
12729 : 1 : icode = CODE_FOR_avx10_2_ucomxdf_round;
12730 : 1 : break;
12731 : 0 : default:
12732 : 0 : gcc_unreachable ();
12733 : : }
12734 : :
12735 : 93 : pat = GEN_FCN (icode) (op0, op1, op3);
12736 : 93 : if (! pat)
12737 : : return 0;
12738 : :
12739 : : /* Rounding operand can be either NO_ROUND or ROUND_SAE at this point. */
12740 : 93 : if (INTVAL (op3) == NO_ROUND)
12741 : : {
12742 : 1 : pat = ix86_erase_embedded_rounding (pat);
12743 : 1 : if (! pat)
12744 : : return 0;
12745 : :
12746 : 1 : set_dst = SET_DEST (pat);
12747 : : }
12748 : : else
12749 : : {
12750 : 92 : gcc_assert (GET_CODE (pat) == SET);
12751 : 92 : set_dst = SET_DEST (pat);
12752 : : }
12753 : :
12754 : 93 : emit_insn (pat);
12755 : :
12756 : 93 : return ix86_ssecom_setcc (comparison, check_unordered, mode,
12757 : 93 : set_dst, target);
12758 : : }
12759 : :
12760 : : static rtx
12761 : 15494 : ix86_expand_round_builtin (const struct builtin_description *d,
12762 : : tree exp, rtx target)
12763 : : {
12764 : 15494 : rtx pat;
12765 : 15494 : unsigned int i, nargs;
12766 : 15494 : rtx xops[6];
12767 : 15494 : enum insn_code icode = d->icode;
12768 : 15494 : const struct insn_data_d *insn_p = &insn_data[icode];
12769 : 15494 : machine_mode tmode = insn_p->operand[0].mode;
12770 : 15494 : unsigned int nargs_constant = 0;
12771 : 15494 : unsigned int redundant_embed_rnd = 0;
12772 : :
12773 : 15494 : switch ((enum ix86_builtin_func_type) d->flag)
12774 : : {
12775 : : case UINT64_FTYPE_V2DF_INT:
12776 : : case UINT64_FTYPE_V4SF_INT:
12777 : : case UINT64_FTYPE_V8HF_INT:
12778 : : case UINT_FTYPE_V2DF_INT:
12779 : : case UINT_FTYPE_V4SF_INT:
12780 : : case UINT_FTYPE_V8HF_INT:
12781 : : case INT64_FTYPE_V2DF_INT:
12782 : : case INT64_FTYPE_V4SF_INT:
12783 : : case INT64_FTYPE_V8HF_INT:
12784 : : case INT_FTYPE_V2DF_INT:
12785 : : case INT_FTYPE_V4SF_INT:
12786 : : case INT_FTYPE_V8HF_INT:
12787 : : nargs = 2;
12788 : : break;
12789 : 714 : case V32HF_FTYPE_V32HF_V32HF_INT:
12790 : 714 : case V8HF_FTYPE_V8HF_V8HF_INT:
12791 : 714 : case V8HF_FTYPE_V8HF_INT_INT:
12792 : 714 : case V8HF_FTYPE_V8HF_UINT_INT:
12793 : 714 : case V8HF_FTYPE_V8HF_INT64_INT:
12794 : 714 : case V8HF_FTYPE_V8HF_UINT64_INT:
12795 : 714 : case V4SF_FTYPE_V4SF_UINT_INT:
12796 : 714 : case V4SF_FTYPE_V4SF_UINT64_INT:
12797 : 714 : case V2DF_FTYPE_V2DF_UINT64_INT:
12798 : 714 : case V4SF_FTYPE_V4SF_INT_INT:
12799 : 714 : case V4SF_FTYPE_V4SF_INT64_INT:
12800 : 714 : case V2DF_FTYPE_V2DF_INT64_INT:
12801 : 714 : case V4SF_FTYPE_V4SF_V4SF_INT:
12802 : 714 : case V2DF_FTYPE_V2DF_V2DF_INT:
12803 : 714 : case V4SF_FTYPE_V4SF_V2DF_INT:
12804 : 714 : case V2DF_FTYPE_V2DF_V4SF_INT:
12805 : 714 : nargs = 3;
12806 : 714 : break;
12807 : 4506 : case V8SF_FTYPE_V8DF_V8SF_QI_INT:
12808 : 4506 : case V8DF_FTYPE_V8DF_V8DF_QI_INT:
12809 : 4506 : case V32HI_FTYPE_V32HF_V32HI_USI_INT:
12810 : 4506 : case V32HI_FTYPE_V32BF_V32HI_USI_INT:
12811 : 4506 : case V8SI_FTYPE_V8DF_V8SI_QI_INT:
12812 : 4506 : case V8DI_FTYPE_V8HF_V8DI_UQI_INT:
12813 : 4506 : case V8DI_FTYPE_V8DF_V8DI_QI_INT:
12814 : 4506 : case V8SF_FTYPE_V8DI_V8SF_QI_INT:
12815 : 4506 : case V8DF_FTYPE_V8DI_V8DF_QI_INT:
12816 : 4506 : case V8DF_FTYPE_V8HF_V8DF_UQI_INT:
12817 : 4506 : case V16SF_FTYPE_V16HF_V16SF_UHI_INT:
12818 : 4506 : case V32HF_FTYPE_V32HI_V32HF_USI_INT:
12819 : 4506 : case V32HF_FTYPE_V32HF_V32HF_USI_INT:
12820 : 4506 : case V32HF_FTYPE_V32HF_V32HF_V32HF_INT:
12821 : 4506 : case V16SF_FTYPE_V16SF_V16SF_HI_INT:
12822 : 4506 : case V8DI_FTYPE_V8SF_V8DI_QI_INT:
12823 : 4506 : case V16SF_FTYPE_V16SI_V16SF_HI_INT:
12824 : 4506 : case V16SI_FTYPE_V16SF_V16SI_HI_INT:
12825 : 4506 : case V16SI_FTYPE_V16SF_V16SI_UHI_INT:
12826 : 4506 : case V16SI_FTYPE_V16HF_V16SI_UHI_INT:
12827 : 4506 : case V16HF_FTYPE_V16SI_V16HF_UHI_INT:
12828 : 4506 : case V8DF_FTYPE_V8SF_V8DF_QI_INT:
12829 : 4506 : case V16SF_FTYPE_V16HI_V16SF_HI_INT:
12830 : 4506 : case V2DF_FTYPE_V2DF_V2DF_V2DF_INT:
12831 : 4506 : case V4SF_FTYPE_V4SF_V4SF_V4SF_INT:
12832 : 4506 : case V8HF_FTYPE_V8DI_V8HF_UQI_INT:
12833 : 4506 : case V8HF_FTYPE_V8DF_V8HF_UQI_INT:
12834 : 4506 : case V16HF_FTYPE_V16SF_V16HF_UHI_INT:
12835 : 4506 : case V16HI_FTYPE_V16BF_V16HI_UHI_INT:
12836 : 4506 : case V8HF_FTYPE_V8HF_V8HF_V8HF_INT:
12837 : 4506 : nargs = 4;
12838 : 4506 : break;
12839 : 243 : case V4SF_FTYPE_V4SF_V4SF_INT_INT:
12840 : 243 : case V2DF_FTYPE_V2DF_V2DF_INT_INT:
12841 : 243 : nargs_constant = 2;
12842 : 243 : nargs = 4;
12843 : 243 : break;
12844 : 97 : case INT_FTYPE_V4SF_V4SF_INT_INT:
12845 : 97 : case INT_FTYPE_V2DF_V2DF_INT_INT:
12846 : 97 : return ix86_expand_sse_comi_round (d, exp, target, true);
12847 : 6198 : case V8DF_FTYPE_V8DF_V8DF_V8DF_UQI_INT:
12848 : 6198 : case V2DF_FTYPE_V2DF_V2DF_V2DF_UQI_INT:
12849 : 6198 : case V4SF_FTYPE_V4SF_V4SF_V4SF_UQI_INT:
12850 : 6198 : case V4SF_FTYPE_V8HF_V4SF_V4SF_UQI_INT:
12851 : 6198 : case V16SF_FTYPE_V16SF_V16SF_V16SF_HI_INT:
12852 : 6198 : case V32HF_FTYPE_V32HF_V32HF_V32HF_UHI_INT:
12853 : 6198 : case V32HF_FTYPE_V32HF_V32HF_V32HF_USI_INT:
12854 : 6198 : case V2DF_FTYPE_V8HF_V2DF_V2DF_UQI_INT:
12855 : 6198 : case V2DF_FTYPE_V2DF_V2DF_V2DF_QI_INT:
12856 : 6198 : case V2DF_FTYPE_V2DF_V4SF_V2DF_QI_INT:
12857 : 6198 : case V2DF_FTYPE_V2DF_V4SF_V2DF_UQI_INT:
12858 : 6198 : case V4SF_FTYPE_V4SF_V4SF_V4SF_QI_INT:
12859 : 6198 : case V4SF_FTYPE_V4SF_V2DF_V4SF_QI_INT:
12860 : 6198 : case V4SF_FTYPE_V4SF_V2DF_V4SF_UQI_INT:
12861 : 6198 : case V8HF_FTYPE_V8HF_V8HF_V8HF_UQI_INT:
12862 : 6198 : case V8HF_FTYPE_V2DF_V8HF_V8HF_UQI_INT:
12863 : 6198 : case V8HF_FTYPE_V4SF_V8HF_V8HF_UQI_INT:
12864 : 6198 : case V32HF_FTYPE_V16SF_V16SF_V32HF_USI_INT:
12865 : 6198 : nargs = 5;
12866 : 6198 : break;
12867 : 635 : case V32HF_FTYPE_V32HF_INT_V32HF_USI_INT:
12868 : 635 : case V16SF_FTYPE_V16SF_INT_V16SF_HI_INT:
12869 : 635 : case V8DF_FTYPE_V8DF_INT_V8DF_QI_INT:
12870 : 635 : case V8DF_FTYPE_V8DF_INT_V8DF_UQI_INT:
12871 : 635 : case V16SF_FTYPE_V16SF_INT_V16SF_UHI_INT:
12872 : 635 : nargs_constant = 4;
12873 : 635 : nargs = 5;
12874 : 635 : break;
12875 : 1181 : case UQI_FTYPE_V8DF_V8DF_INT_UQI_INT:
12876 : 1181 : case UQI_FTYPE_V2DF_V2DF_INT_UQI_INT:
12877 : 1181 : case UHI_FTYPE_V16SF_V16SF_INT_UHI_INT:
12878 : 1181 : case UQI_FTYPE_V4SF_V4SF_INT_UQI_INT:
12879 : 1181 : case USI_FTYPE_V32HF_V32HF_INT_USI_INT:
12880 : 1181 : case UQI_FTYPE_V8HF_V8HF_INT_UQI_INT:
12881 : 1181 : nargs_constant = 3;
12882 : 1181 : nargs = 5;
12883 : 1181 : break;
12884 : 963 : case V16SF_FTYPE_V16SF_V16SF_INT_V16SF_HI_INT:
12885 : 963 : case V8DF_FTYPE_V8DF_V8DF_INT_V8DF_QI_INT:
12886 : 963 : case V4SF_FTYPE_V4SF_V4SF_INT_V4SF_QI_INT:
12887 : 963 : case V2DF_FTYPE_V2DF_V2DF_INT_V2DF_QI_INT:
12888 : 963 : case V2DF_FTYPE_V2DF_V2DF_INT_V2DF_UQI_INT:
12889 : 963 : case V4SF_FTYPE_V4SF_V4SF_INT_V4SF_UQI_INT:
12890 : 963 : case V8HF_FTYPE_V8HF_V8HF_INT_V8HF_UQI_INT:
12891 : 963 : case V8DF_FTYPE_V8DF_V8DF_INT_V8DF_UQI_INT:
12892 : 963 : case V32HF_FTYPE_V32HF_V32HF_INT_V32HF_USI_INT:
12893 : 963 : case V16SF_FTYPE_V16SF_V16SF_INT_V16SF_UHI_INT:
12894 : 963 : nargs = 6;
12895 : 963 : nargs_constant = 4;
12896 : 963 : break;
12897 : 252 : case V8DF_FTYPE_V8DF_V8DF_V8DI_INT_QI_INT:
12898 : 252 : case V16SF_FTYPE_V16SF_V16SF_V16SI_INT_HI_INT:
12899 : 252 : case V2DF_FTYPE_V2DF_V2DF_V2DI_INT_QI_INT:
12900 : 252 : case V4SF_FTYPE_V4SF_V4SF_V4SI_INT_QI_INT:
12901 : 252 : nargs = 6;
12902 : 252 : nargs_constant = 3;
12903 : 252 : break;
12904 : 0 : default:
12905 : 0 : gcc_unreachable ();
12906 : : }
12907 : 14692 : gcc_assert (nargs <= ARRAY_SIZE (xops));
12908 : :
12909 : 15397 : if (optimize
12910 : 4261 : || target == 0
12911 : 4261 : || GET_MODE (target) != tmode
12912 : 19658 : || !insn_p->operand[0].predicate (target, tmode))
12913 : 11136 : target = gen_reg_rtx (tmode);
12914 : :
12915 : 84654 : for (i = 0; i < nargs; i++)
12916 : : {
12917 : 69812 : tree arg = CALL_EXPR_ARG (exp, i);
12918 : 69812 : rtx op = ix86_expand_unsigned_small_int_cst_argument (arg);
12919 : 69812 : machine_mode mode = insn_p->operand[i + 1].mode;
12920 : 69812 : bool match = insn_p->operand[i + 1].predicate (op, mode);
12921 : :
12922 : 69812 : if (i == nargs - nargs_constant)
12923 : : {
12924 : 3274 : if (!match)
12925 : : {
12926 : 40 : switch (icode)
12927 : : {
12928 : 12 : case CODE_FOR_avx512f_getmantv8df_mask_round:
12929 : 12 : case CODE_FOR_avx512f_getmantv16sf_mask_round:
12930 : 12 : case CODE_FOR_avx512bw_getmantv32hf_mask_round:
12931 : 12 : case CODE_FOR_avx512f_vgetmantv2df_round:
12932 : 12 : case CODE_FOR_avx512f_vgetmantv2df_mask_round:
12933 : 12 : case CODE_FOR_avx512f_vgetmantv4sf_round:
12934 : 12 : case CODE_FOR_avx512f_vgetmantv4sf_mask_round:
12935 : 12 : case CODE_FOR_avx512f_vgetmantv8hf_mask_round:
12936 : 12 : error ("the immediate argument must be a 4-bit immediate");
12937 : 12 : return const0_rtx;
12938 : 8 : case CODE_FOR_avx512f_cmpv8df3_mask_round:
12939 : 8 : case CODE_FOR_avx512f_cmpv16sf3_mask_round:
12940 : 8 : case CODE_FOR_avx512f_vmcmpv2df3_mask_round:
12941 : 8 : case CODE_FOR_avx512f_vmcmpv4sf3_mask_round:
12942 : 8 : case CODE_FOR_avx512f_vmcmpv8hf3_mask_round:
12943 : 8 : case CODE_FOR_avx512bw_cmpv32hf3_mask_round:
12944 : 8 : error ("the immediate argument must be a 5-bit immediate");
12945 : 8 : return const0_rtx;
12946 : 20 : default:
12947 : 20 : error ("the immediate argument must be an 8-bit immediate");
12948 : 20 : return const0_rtx;
12949 : : }
12950 : : }
12951 : : }
12952 : 66538 : else if (i == nargs-1)
12953 : : {
12954 : 15357 : if (!insn_p->operand[nargs].predicate (op, SImode))
12955 : : {
12956 : 515 : error ("incorrect rounding operand");
12957 : 515 : return const0_rtx;
12958 : : }
12959 : :
12960 : : /* If there is no rounding use normal version of the pattern. */
12961 : 14842 : if (INTVAL (op) == NO_ROUND)
12962 : : {
12963 : : /* Skip erasing embedded rounding for below expanders who
12964 : : generates multiple insns. In ix86_erase_embedded_rounding
12965 : : the pattern will be transformed to a single set, and emit_insn
12966 : : appends the set instead of insert it to chain. So the insns
12967 : : emitted inside define_expander would be ignored. */
12968 : 4824 : switch (icode)
12969 : : {
12970 : : case CODE_FOR_avx512bw_fmaddc_v32hf_mask1_round:
12971 : : case CODE_FOR_avx512bw_fcmaddc_v32hf_mask1_round:
12972 : : case CODE_FOR_avx512fp16_fmaddcsh_v8hf_mask1_round:
12973 : : case CODE_FOR_avx512fp16_fcmaddcsh_v8hf_mask1_round:
12974 : : case CODE_FOR_avx512fp16_fmaddcsh_v8hf_mask3_round:
12975 : : case CODE_FOR_avx512fp16_fcmaddcsh_v8hf_mask3_round:
12976 : : redundant_embed_rnd = 0;
12977 : : break;
12978 : 4792 : default:
12979 : 4792 : redundant_embed_rnd = 1;
12980 : 4792 : break;
12981 : : }
12982 : : }
12983 : : }
12984 : : else
12985 : : {
12986 : 51181 : if (VECTOR_MODE_P (mode))
12987 : 37455 : op = safe_vector_operand (op, mode);
12988 : :
12989 : 51181 : op = fixup_modeless_constant (op, mode);
12990 : :
12991 : 51181 : if (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)
12992 : : {
12993 : 51181 : if (optimize || !match)
12994 : 44853 : op = copy_to_mode_reg (mode, op);
12995 : : }
12996 : : else
12997 : : {
12998 : 0 : op = copy_to_reg (op);
12999 : 0 : op = lowpart_subreg (mode, op, GET_MODE (op));
13000 : : }
13001 : : }
13002 : :
13003 : 69257 : xops[i] = op;
13004 : : }
13005 : :
13006 : 14842 : switch (nargs)
13007 : : {
13008 : : case 1:
13009 : : pat = GEN_FCN (icode) (target, xops[0]);
13010 : : break;
13011 : 672 : case 2:
13012 : 672 : pat = GEN_FCN (icode) (target, xops[0], xops[1]);
13013 : 672 : break;
13014 : 670 : case 3:
13015 : 670 : pat = GEN_FCN (icode) (target, xops[0], xops[1], xops[2]);
13016 : 670 : break;
13017 : 4625 : case 4:
13018 : 4625 : pat = GEN_FCN (icode) (target, xops[0], xops[1],
13019 : 4625 : xops[2], xops[3]);
13020 : 4625 : break;
13021 : 7710 : case 5:
13022 : 7710 : pat = GEN_FCN (icode) (target, xops[0], xops[1],
13023 : 7710 : xops[2], xops[3], xops[4]);
13024 : 7710 : break;
13025 : 1165 : case 6:
13026 : 1165 : pat = GEN_FCN (icode) (target, xops[0], xops[1],
13027 : 1165 : xops[2], xops[3], xops[4], xops[5]);
13028 : 1165 : break;
13029 : : default:
13030 : : gcc_unreachable ();
13031 : : }
13032 : :
13033 : 14842 : if (!pat)
13034 : : return 0;
13035 : :
13036 : 14842 : if (redundant_embed_rnd)
13037 : 4792 : pat = ix86_erase_embedded_rounding (pat);
13038 : :
13039 : 14842 : emit_insn (pat);
13040 : 14842 : return target;
13041 : : }
13042 : :
13043 : : /* Subroutine of ix86_expand_builtin to take care of special insns
13044 : : with variable number of operands. */
13045 : :
13046 : : static rtx
13047 : 27353 : ix86_expand_special_args_builtin (const struct builtin_description *d,
13048 : : tree exp, rtx target)
13049 : : {
13050 : 27353 : tree arg;
13051 : 27353 : rtx pat, op;
13052 : 27353 : unsigned int i, nargs, arg_adjust, memory;
13053 : 27353 : unsigned int constant = 100;
13054 : 27353 : bool aligned_mem = false;
13055 : 27353 : rtx xops[4];
13056 : 27353 : enum insn_code icode = d->icode;
13057 : 27353 : const struct insn_data_d *insn_p = &insn_data[icode];
13058 : 27353 : machine_mode tmode = insn_p->operand[0].mode;
13059 : 27353 : enum { load, store } klass;
13060 : :
13061 : 27353 : switch ((enum ix86_builtin_func_type) d->flag)
13062 : : {
13063 : 15547 : case VOID_FTYPE_VOID:
13064 : 15547 : emit_insn (GEN_FCN (icode) (target));
13065 : 15547 : return 0;
13066 : : case VOID_FTYPE_UINT64:
13067 : : case VOID_FTYPE_UNSIGNED:
13068 : : nargs = 0;
13069 : : klass = store;
13070 : : memory = 0;
13071 : : break;
13072 : :
13073 : 7581 : case INT_FTYPE_VOID:
13074 : 7581 : case USHORT_FTYPE_VOID:
13075 : 7581 : case UINT64_FTYPE_VOID:
13076 : 7581 : case UINT_FTYPE_VOID:
13077 : 7581 : case UINT8_FTYPE_VOID:
13078 : 7581 : case UNSIGNED_FTYPE_VOID:
13079 : 7581 : nargs = 0;
13080 : 7581 : klass = load;
13081 : 7581 : memory = 0;
13082 : 7581 : break;
13083 : 357 : case CHAR_FTYPE_PCCHAR:
13084 : 357 : case SHORT_FTYPE_PCSHORT:
13085 : 357 : case INT_FTYPE_PCINT:
13086 : 357 : case INT64_FTYPE_PCINT64:
13087 : 357 : case UINT64_FTYPE_PUNSIGNED:
13088 : 357 : case V2DI_FTYPE_PV2DI:
13089 : 357 : case V4DI_FTYPE_PV4DI:
13090 : 357 : case V32QI_FTYPE_PCCHAR:
13091 : 357 : case V16QI_FTYPE_PCCHAR:
13092 : 357 : case V8SF_FTYPE_PCV4SF:
13093 : 357 : case V8SF_FTYPE_PCFLOAT:
13094 : 357 : case V4SF_FTYPE_PCFLOAT:
13095 : 357 : case V4SF_FTYPE_PCFLOAT16:
13096 : 357 : case V4SF_FTYPE_PCBFLOAT16:
13097 : 357 : case V4SF_FTYPE_PCV8BF:
13098 : 357 : case V4SF_FTYPE_PCV8HF:
13099 : 357 : case V8SF_FTYPE_PCFLOAT16:
13100 : 357 : case V8SF_FTYPE_PCBFLOAT16:
13101 : 357 : case V8SF_FTYPE_PCV16HF:
13102 : 357 : case V8SF_FTYPE_PCV16BF:
13103 : 357 : case V4DF_FTYPE_PCV2DF:
13104 : 357 : case V4DF_FTYPE_PCDOUBLE:
13105 : 357 : case V2DF_FTYPE_PCDOUBLE:
13106 : 357 : case VOID_FTYPE_PVOID:
13107 : 357 : case V8DI_FTYPE_PV8DI:
13108 : 357 : nargs = 1;
13109 : 357 : klass = load;
13110 : 357 : memory = 0;
13111 : 357 : switch (icode)
13112 : : {
13113 : : case CODE_FOR_sse4_1_movntdqa:
13114 : : case CODE_FOR_avx2_movntdqa:
13115 : : case CODE_FOR_avx512f_movntdqa:
13116 : : aligned_mem = true;
13117 : : break;
13118 : : default:
13119 : : break;
13120 : : }
13121 : : break;
13122 : 371 : case VOID_FTYPE_PV2SF_V4SF:
13123 : 371 : case VOID_FTYPE_PV8DI_V8DI:
13124 : 371 : case VOID_FTYPE_PV4DI_V4DI:
13125 : 371 : case VOID_FTYPE_PV2DI_V2DI:
13126 : 371 : case VOID_FTYPE_PCHAR_V32QI:
13127 : 371 : case VOID_FTYPE_PCHAR_V16QI:
13128 : 371 : case VOID_FTYPE_PFLOAT_V16SF:
13129 : 371 : case VOID_FTYPE_PFLOAT_V8SF:
13130 : 371 : case VOID_FTYPE_PFLOAT_V4SF:
13131 : 371 : case VOID_FTYPE_PDOUBLE_V8DF:
13132 : 371 : case VOID_FTYPE_PDOUBLE_V4DF:
13133 : 371 : case VOID_FTYPE_PDOUBLE_V2DF:
13134 : 371 : case VOID_FTYPE_PLONGLONG_LONGLONG:
13135 : 371 : case VOID_FTYPE_PULONGLONG_ULONGLONG:
13136 : 371 : case VOID_FTYPE_PUNSIGNED_UNSIGNED:
13137 : 371 : case VOID_FTYPE_PINT_INT:
13138 : 371 : nargs = 1;
13139 : 371 : klass = store;
13140 : : /* Reserve memory operand for target. */
13141 : 371 : memory = ARRAY_SIZE (xops);
13142 : 371 : switch (icode)
13143 : : {
13144 : : /* These builtins and instructions require the memory
13145 : : to be properly aligned. */
13146 : : case CODE_FOR_avx_movntv4di:
13147 : : case CODE_FOR_sse2_movntv2di:
13148 : : case CODE_FOR_avx_movntv8sf:
13149 : : case CODE_FOR_sse_movntv4sf:
13150 : : case CODE_FOR_sse4a_vmmovntv4sf:
13151 : : case CODE_FOR_avx_movntv4df:
13152 : : case CODE_FOR_sse2_movntv2df:
13153 : : case CODE_FOR_sse4a_vmmovntv2df:
13154 : : case CODE_FOR_sse2_movntidi:
13155 : : case CODE_FOR_sse_movntq:
13156 : : case CODE_FOR_sse2_movntisi:
13157 : : case CODE_FOR_avx512f_movntv16sf:
13158 : : case CODE_FOR_avx512f_movntv8df:
13159 : : case CODE_FOR_avx512f_movntv8di:
13160 : : aligned_mem = true;
13161 : : break;
13162 : : default:
13163 : : break;
13164 : : }
13165 : : break;
13166 : 0 : case VOID_FTYPE_PVOID_PCVOID:
13167 : 0 : nargs = 1;
13168 : 0 : klass = store;
13169 : 0 : memory = 0;
13170 : :
13171 : 0 : break;
13172 : 26 : case V4SF_FTYPE_V4SF_PCV2SF:
13173 : 26 : case V2DF_FTYPE_V2DF_PCDOUBLE:
13174 : 26 : nargs = 2;
13175 : 26 : klass = load;
13176 : 26 : memory = 1;
13177 : 26 : break;
13178 : 93 : case V8SF_FTYPE_PCV8SF_V8SI:
13179 : 93 : case V4DF_FTYPE_PCV4DF_V4DI:
13180 : 93 : case V4SF_FTYPE_PCV4SF_V4SI:
13181 : 93 : case V2DF_FTYPE_PCV2DF_V2DI:
13182 : 93 : case V8SI_FTYPE_PCV8SI_V8SI:
13183 : 93 : case V4DI_FTYPE_PCV4DI_V4DI:
13184 : 93 : case V4SI_FTYPE_PCV4SI_V4SI:
13185 : 93 : case V2DI_FTYPE_PCV2DI_V2DI:
13186 : 93 : case VOID_FTYPE_INT_INT64:
13187 : 93 : nargs = 2;
13188 : 93 : klass = load;
13189 : 93 : memory = 0;
13190 : 93 : break;
13191 : 360 : case VOID_FTYPE_PV8DF_V8DF_UQI:
13192 : 360 : case VOID_FTYPE_PV4DF_V4DF_UQI:
13193 : 360 : case VOID_FTYPE_PV2DF_V2DF_UQI:
13194 : 360 : case VOID_FTYPE_PV16SF_V16SF_UHI:
13195 : 360 : case VOID_FTYPE_PV8SF_V8SF_UQI:
13196 : 360 : case VOID_FTYPE_PV4SF_V4SF_UQI:
13197 : 360 : case VOID_FTYPE_PV8DI_V8DI_UQI:
13198 : 360 : case VOID_FTYPE_PV4DI_V4DI_UQI:
13199 : 360 : case VOID_FTYPE_PV2DI_V2DI_UQI:
13200 : 360 : case VOID_FTYPE_PV16SI_V16SI_UHI:
13201 : 360 : case VOID_FTYPE_PV8SI_V8SI_UQI:
13202 : 360 : case VOID_FTYPE_PV4SI_V4SI_UQI:
13203 : 360 : case VOID_FTYPE_PV64QI_V64QI_UDI:
13204 : 360 : case VOID_FTYPE_PV32HI_V32HI_USI:
13205 : 360 : case VOID_FTYPE_PV32QI_V32QI_USI:
13206 : 360 : case VOID_FTYPE_PV16QI_V16QI_UHI:
13207 : 360 : case VOID_FTYPE_PV16HI_V16HI_UHI:
13208 : 360 : case VOID_FTYPE_PV8HI_V8HI_UQI:
13209 : 360 : switch (icode)
13210 : : {
13211 : : /* These builtins and instructions require the memory
13212 : : to be properly aligned. */
13213 : : case CODE_FOR_avx512f_storev16sf_mask:
13214 : : case CODE_FOR_avx512f_storev16si_mask:
13215 : : case CODE_FOR_avx512f_storev8df_mask:
13216 : : case CODE_FOR_avx512f_storev8di_mask:
13217 : : case CODE_FOR_avx512vl_storev8sf_mask:
13218 : : case CODE_FOR_avx512vl_storev8si_mask:
13219 : : case CODE_FOR_avx512vl_storev4df_mask:
13220 : : case CODE_FOR_avx512vl_storev4di_mask:
13221 : : case CODE_FOR_avx512vl_storev4sf_mask:
13222 : : case CODE_FOR_avx512vl_storev4si_mask:
13223 : : case CODE_FOR_avx512vl_storev2df_mask:
13224 : : case CODE_FOR_avx512vl_storev2di_mask:
13225 : 11806 : aligned_mem = true;
13226 : : break;
13227 : : default:
13228 : : break;
13229 : : }
13230 : : /* FALLTHRU */
13231 : : case VOID_FTYPE_PV8SF_V8SI_V8SF:
13232 : : case VOID_FTYPE_PV4DF_V4DI_V4DF:
13233 : : case VOID_FTYPE_PV4SF_V4SI_V4SF:
13234 : : case VOID_FTYPE_PV2DF_V2DI_V2DF:
13235 : : case VOID_FTYPE_PV8SI_V8SI_V8SI:
13236 : : case VOID_FTYPE_PV4DI_V4DI_V4DI:
13237 : : case VOID_FTYPE_PV4SI_V4SI_V4SI:
13238 : : case VOID_FTYPE_PV2DI_V2DI_V2DI:
13239 : : case VOID_FTYPE_PV8SI_V8DI_UQI:
13240 : : case VOID_FTYPE_PV8HI_V8DI_UQI:
13241 : : case VOID_FTYPE_PV16HI_V16SI_UHI:
13242 : : case VOID_FTYPE_PUDI_V8DI_UQI:
13243 : : case VOID_FTYPE_PV16QI_V16SI_UHI:
13244 : : case VOID_FTYPE_PV4SI_V4DI_UQI:
13245 : : case VOID_FTYPE_PUDI_V2DI_UQI:
13246 : : case VOID_FTYPE_PUDI_V4DI_UQI:
13247 : : case VOID_FTYPE_PUSI_V2DI_UQI:
13248 : : case VOID_FTYPE_PV8HI_V8SI_UQI:
13249 : : case VOID_FTYPE_PUDI_V4SI_UQI:
13250 : : case VOID_FTYPE_PUSI_V4DI_UQI:
13251 : : case VOID_FTYPE_PUHI_V2DI_UQI:
13252 : : case VOID_FTYPE_PUDI_V8SI_UQI:
13253 : : case VOID_FTYPE_PUSI_V4SI_UQI:
13254 : : case VOID_FTYPE_PCHAR_V64QI_UDI:
13255 : : case VOID_FTYPE_PCHAR_V32QI_USI:
13256 : : case VOID_FTYPE_PCHAR_V16QI_UHI:
13257 : : case VOID_FTYPE_PSHORT_V32HI_USI:
13258 : : case VOID_FTYPE_PSHORT_V16HI_UHI:
13259 : : case VOID_FTYPE_PSHORT_V8HI_UQI:
13260 : : case VOID_FTYPE_PINT_V16SI_UHI:
13261 : : case VOID_FTYPE_PINT_V8SI_UQI:
13262 : : case VOID_FTYPE_PINT_V4SI_UQI:
13263 : : case VOID_FTYPE_PINT64_V8DI_UQI:
13264 : : case VOID_FTYPE_PINT64_V4DI_UQI:
13265 : : case VOID_FTYPE_PINT64_V2DI_UQI:
13266 : : case VOID_FTYPE_PDOUBLE_V8DF_UQI:
13267 : : case VOID_FTYPE_PDOUBLE_V4DF_UQI:
13268 : : case VOID_FTYPE_PDOUBLE_V2DF_UQI:
13269 : : case VOID_FTYPE_PFLOAT_V16SF_UHI:
13270 : : case VOID_FTYPE_PFLOAT_V8SF_UQI:
13271 : : case VOID_FTYPE_PFLOAT_V4SF_UQI:
13272 : : case VOID_FTYPE_PCFLOAT16_V8HF_UQI:
13273 : : case VOID_FTYPE_PV32QI_V32HI_USI:
13274 : : case VOID_FTYPE_PV16QI_V16HI_UHI:
13275 : : case VOID_FTYPE_PUDI_V8HI_UQI:
13276 : : nargs = 2;
13277 : : klass = store;
13278 : : /* Reserve memory operand for target. */
13279 : : memory = ARRAY_SIZE (xops);
13280 : : break;
13281 : 1243 : case V4SF_FTYPE_PCV4SF_V4SF_UQI:
13282 : 1243 : case V8SF_FTYPE_PCV8SF_V8SF_UQI:
13283 : 1243 : case V16SF_FTYPE_PCV16SF_V16SF_UHI:
13284 : 1243 : case V4SI_FTYPE_PCV4SI_V4SI_UQI:
13285 : 1243 : case V8SI_FTYPE_PCV8SI_V8SI_UQI:
13286 : 1243 : case V16SI_FTYPE_PCV16SI_V16SI_UHI:
13287 : 1243 : case V2DF_FTYPE_PCV2DF_V2DF_UQI:
13288 : 1243 : case V4DF_FTYPE_PCV4DF_V4DF_UQI:
13289 : 1243 : case V8DF_FTYPE_PCV8DF_V8DF_UQI:
13290 : 1243 : case V2DI_FTYPE_PCV2DI_V2DI_UQI:
13291 : 1243 : case V4DI_FTYPE_PCV4DI_V4DI_UQI:
13292 : 1243 : case V8DI_FTYPE_PCV8DI_V8DI_UQI:
13293 : 1243 : case V64QI_FTYPE_PCV64QI_V64QI_UDI:
13294 : 1243 : case V32HI_FTYPE_PCV32HI_V32HI_USI:
13295 : 1243 : case V32QI_FTYPE_PCV32QI_V32QI_USI:
13296 : 1243 : case V16QI_FTYPE_PCV16QI_V16QI_UHI:
13297 : 1243 : case V16HI_FTYPE_PCV16HI_V16HI_UHI:
13298 : 1243 : case V8HI_FTYPE_PCV8HI_V8HI_UQI:
13299 : 1243 : switch (icode)
13300 : : {
13301 : : /* These builtins and instructions require the memory
13302 : : to be properly aligned. */
13303 : : case CODE_FOR_avx512f_loadv16sf_mask:
13304 : : case CODE_FOR_avx512f_loadv16si_mask:
13305 : : case CODE_FOR_avx512f_loadv8df_mask:
13306 : : case CODE_FOR_avx512f_loadv8di_mask:
13307 : : case CODE_FOR_avx512vl_loadv8sf_mask:
13308 : : case CODE_FOR_avx512vl_loadv8si_mask:
13309 : : case CODE_FOR_avx512vl_loadv4df_mask:
13310 : : case CODE_FOR_avx512vl_loadv4di_mask:
13311 : : case CODE_FOR_avx512vl_loadv4sf_mask:
13312 : : case CODE_FOR_avx512vl_loadv4si_mask:
13313 : : case CODE_FOR_avx512vl_loadv2df_mask:
13314 : : case CODE_FOR_avx512vl_loadv2di_mask:
13315 : : case CODE_FOR_avx512bw_loadv64qi_mask:
13316 : : case CODE_FOR_avx512vl_loadv32qi_mask:
13317 : : case CODE_FOR_avx512vl_loadv16qi_mask:
13318 : : case CODE_FOR_avx512bw_loadv32hi_mask:
13319 : : case CODE_FOR_avx512vl_loadv16hi_mask:
13320 : : case CODE_FOR_avx512vl_loadv8hi_mask:
13321 : 11806 : aligned_mem = true;
13322 : : break;
13323 : : default:
13324 : : break;
13325 : : }
13326 : : /* FALLTHRU */
13327 : : case V64QI_FTYPE_PCCHAR_V64QI_UDI:
13328 : : case V32QI_FTYPE_PCCHAR_V32QI_USI:
13329 : : case V16QI_FTYPE_PCCHAR_V16QI_UHI:
13330 : : case V32HI_FTYPE_PCSHORT_V32HI_USI:
13331 : : case V16HI_FTYPE_PCSHORT_V16HI_UHI:
13332 : : case V8HI_FTYPE_PCSHORT_V8HI_UQI:
13333 : : case V16SI_FTYPE_PCINT_V16SI_UHI:
13334 : : case V8SI_FTYPE_PCINT_V8SI_UQI:
13335 : : case V4SI_FTYPE_PCINT_V4SI_UQI:
13336 : : case V8DI_FTYPE_PCINT64_V8DI_UQI:
13337 : : case V4DI_FTYPE_PCINT64_V4DI_UQI:
13338 : : case V2DI_FTYPE_PCINT64_V2DI_UQI:
13339 : : case V8DF_FTYPE_PCDOUBLE_V8DF_UQI:
13340 : : case V4DF_FTYPE_PCDOUBLE_V4DF_UQI:
13341 : : case V2DF_FTYPE_PCDOUBLE_V2DF_UQI:
13342 : : case V16SF_FTYPE_PCFLOAT_V16SF_UHI:
13343 : : case V8SF_FTYPE_PCFLOAT_V8SF_UQI:
13344 : : case V4SF_FTYPE_PCFLOAT_V4SF_UQI:
13345 : : case V8HF_FTYPE_PCFLOAT16_V8HF_UQI:
13346 : : nargs = 3;
13347 : : klass = load;
13348 : : memory = 0;
13349 : : break;
13350 : 105 : case INT_FTYPE_PINT_INT_INT_INT:
13351 : 105 : case LONGLONG_FTYPE_PLONGLONG_LONGLONG_LONGLONG_INT:
13352 : 105 : nargs = 4;
13353 : 105 : klass = load;
13354 : 105 : memory = 0;
13355 : 105 : constant = 3;
13356 : 105 : break;
13357 : 0 : default:
13358 : 0 : gcc_unreachable ();
13359 : : }
13360 : :
13361 : 8337 : gcc_assert (nargs <= ARRAY_SIZE (xops));
13362 : :
13363 : 11806 : if (klass == store)
13364 : : {
13365 : 1874 : arg = CALL_EXPR_ARG (exp, 0);
13366 : 1874 : op = expand_normal (arg);
13367 : 1874 : gcc_assert (target == 0);
13368 : 1874 : if (memory)
13369 : : {
13370 : 1715 : op = ix86_zero_extend_to_Pmode (op);
13371 : 1715 : target = gen_rtx_MEM (tmode, op);
13372 : : /* target at this point has just BITS_PER_UNIT MEM_ALIGN
13373 : : on it. Try to improve it using get_pointer_alignment,
13374 : : and if the special builtin is one that requires strict
13375 : : mode alignment, also from it's GET_MODE_ALIGNMENT.
13376 : : Failure to do so could lead to ix86_legitimate_combined_insn
13377 : : rejecting all changes to such insns. */
13378 : 1715 : unsigned int align = get_pointer_alignment (arg);
13379 : 1715 : if (aligned_mem && align < GET_MODE_ALIGNMENT (tmode))
13380 : 275 : align = GET_MODE_ALIGNMENT (tmode);
13381 : 3430 : if (MEM_ALIGN (target) < align)
13382 : 422 : set_mem_align (target, align);
13383 : : }
13384 : : else
13385 : 159 : target = force_reg (tmode, op);
13386 : : arg_adjust = 1;
13387 : : }
13388 : : else
13389 : : {
13390 : 9932 : arg_adjust = 0;
13391 : 9932 : if (optimize
13392 : 2917 : || target == 0
13393 : 2917 : || !register_operand (target, tmode)
13394 : 12838 : || GET_MODE (target) != tmode)
13395 : 7026 : target = gen_reg_rtx (tmode);
13396 : : }
13397 : :
13398 : 21190 : for (i = 0; i < nargs; i++)
13399 : : {
13400 : 9384 : machine_mode mode = insn_p->operand[i + 1].mode;
13401 : :
13402 : 9384 : arg = CALL_EXPR_ARG (exp, i + arg_adjust);
13403 : 9384 : op = ix86_expand_unsigned_small_int_cst_argument (arg);
13404 : :
13405 : 9384 : if (i == memory)
13406 : : {
13407 : : /* This must be the memory operand. */
13408 : 2351 : op = ix86_zero_extend_to_Pmode (op);
13409 : 2351 : op = gen_rtx_MEM (mode, op);
13410 : : /* op at this point has just BITS_PER_UNIT MEM_ALIGN
13411 : : on it. Try to improve it using get_pointer_alignment,
13412 : : and if the special builtin is one that requires strict
13413 : : mode alignment, also from it's GET_MODE_ALIGNMENT.
13414 : : Failure to do so could lead to ix86_legitimate_combined_insn
13415 : : rejecting all changes to such insns. */
13416 : 2351 : unsigned int align = get_pointer_alignment (arg);
13417 : 2351 : if (aligned_mem && align < GET_MODE_ALIGNMENT (mode))
13418 : 299 : align = GET_MODE_ALIGNMENT (mode);
13419 : 4702 : if (MEM_ALIGN (op) < align)
13420 : 523 : set_mem_align (op, align);
13421 : : }
13422 : 7033 : else if (i == constant)
13423 : : {
13424 : : /* This must be the constant. */
13425 : 105 : if (!insn_p->operand[nargs].predicate(op, SImode))
13426 : : {
13427 : 0 : error ("the fourth argument must be one of enum %qs", "_CMPCCX_ENUM");
13428 : 0 : return const0_rtx;
13429 : : }
13430 : : }
13431 : : else
13432 : : {
13433 : : /* This must be register. */
13434 : 6928 : if (VECTOR_MODE_P (mode))
13435 : 3474 : op = safe_vector_operand (op, mode);
13436 : :
13437 : 6928 : op = fixup_modeless_constant (op, mode);
13438 : :
13439 : : /* NB: 3-operands load implied it's a mask load or v{p}expand*,
13440 : : and that mask operand shoud be at the end.
13441 : : Keep all-ones mask which would be simplified by the expander. */
13442 : 1770 : if (nargs == 3 && i == 2 && klass == load
13443 : 1770 : && constm1_operand (op, mode)
13444 : 7101 : && insn_p->operand[i].predicate (op, mode))
13445 : : ;
13446 : 6928 : else if (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)
13447 : 6928 : op = copy_to_mode_reg (mode, op);
13448 : : else
13449 : : {
13450 : 0 : op = copy_to_reg (op);
13451 : 0 : op = lowpart_subreg (mode, op, GET_MODE (op));
13452 : : }
13453 : : }
13454 : :
13455 : 9384 : xops[i]= op;
13456 : : }
13457 : :
13458 : 11806 : switch (nargs)
13459 : : {
13460 : 7740 : case 0:
13461 : 7740 : pat = GEN_FCN (icode) (target);
13462 : 7740 : break;
13463 : 728 : case 1:
13464 : 728 : pat = GEN_FCN (icode) (target, xops[0]);
13465 : 728 : break;
13466 : 1463 : case 2:
13467 : 1463 : pat = GEN_FCN (icode) (target, xops[0], xops[1]);
13468 : 1463 : break;
13469 : 1770 : case 3:
13470 : 1770 : pat = GEN_FCN (icode) (target, xops[0], xops[1], xops[2]);
13471 : 1770 : break;
13472 : 105 : case 4:
13473 : 105 : pat = GEN_FCN (icode) (target, xops[0], xops[1], xops[2], xops[3]);
13474 : 105 : break;
13475 : : default:
13476 : : gcc_unreachable ();
13477 : : }
13478 : :
13479 : 11806 : if (! pat)
13480 : : return 0;
13481 : :
13482 : 11806 : emit_insn (pat);
13483 : 11806 : return klass == store ? 0 : target;
13484 : : }
13485 : :
13486 : : /* Return the integer constant in ARG. Constrain it to be in the range
13487 : : of the subparts of VEC_TYPE; issue an error if not. */
13488 : :
13489 : : static int
13490 : 595 : get_element_number (tree vec_type, tree arg)
13491 : : {
13492 : 595 : unsigned HOST_WIDE_INT elt, max = TYPE_VECTOR_SUBPARTS (vec_type) - 1;
13493 : :
13494 : 595 : if (!tree_fits_uhwi_p (arg)
13495 : 595 : || (elt = tree_to_uhwi (arg), elt > max))
13496 : : {
13497 : 0 : error ("selector must be an integer constant in the range "
13498 : : "[0, %wi]", max);
13499 : 0 : return 0;
13500 : : }
13501 : :
13502 : 595 : return elt;
13503 : : }
13504 : :
13505 : : /* A subroutine of ix86_expand_builtin. These builtins are a wrapper around
13506 : : ix86_expand_vector_init. We DO have language-level syntax for this, in
13507 : : the form of (type){ init-list }. Except that since we can't place emms
13508 : : instructions from inside the compiler, we can't allow the use of MMX
13509 : : registers unless the user explicitly asks for it. So we do *not* define
13510 : : vec_set/vec_extract/vec_init patterns for MMX modes in mmx.md. Instead
13511 : : we have builtins invoked by mmintrin.h that gives us license to emit
13512 : : these sorts of instructions. */
13513 : :
13514 : : static rtx
13515 : 229 : ix86_expand_vec_init_builtin (tree type, tree exp, rtx target)
13516 : : {
13517 : 229 : machine_mode tmode = TYPE_MODE (type);
13518 : 229 : machine_mode inner_mode = GET_MODE_INNER (tmode);
13519 : 229 : int i, n_elt = GET_MODE_NUNITS (tmode);
13520 : 229 : rtvec v = rtvec_alloc (n_elt);
13521 : :
13522 : 229 : gcc_assert (VECTOR_MODE_P (tmode));
13523 : 229 : gcc_assert (call_expr_nargs (exp) == n_elt);
13524 : :
13525 : 1203 : for (i = 0; i < n_elt; ++i)
13526 : : {
13527 : 974 : rtx x = expand_normal (CALL_EXPR_ARG (exp, i));
13528 : 974 : RTVEC_ELT (v, i) = gen_lowpart (inner_mode, x);
13529 : : }
13530 : :
13531 : 229 : if (!target || !register_operand (target, tmode))
13532 : 0 : target = gen_reg_rtx (tmode);
13533 : :
13534 : 229 : ix86_expand_vector_init (true, target, gen_rtx_PARALLEL (tmode, v));
13535 : 229 : return target;
13536 : : }
13537 : :
13538 : : /* A subroutine of ix86_expand_builtin. These builtins are a wrapper around
13539 : : ix86_expand_vector_extract. They would be redundant (for non-MMX) if we
13540 : : had a language-level syntax for referencing vector elements. */
13541 : :
13542 : : static rtx
13543 : 391 : ix86_expand_vec_ext_builtin (tree exp, rtx target)
13544 : : {
13545 : 391 : machine_mode tmode, mode0;
13546 : 391 : tree arg0, arg1;
13547 : 391 : int elt;
13548 : 391 : rtx op0;
13549 : :
13550 : 391 : arg0 = CALL_EXPR_ARG (exp, 0);
13551 : 391 : arg1 = CALL_EXPR_ARG (exp, 1);
13552 : :
13553 : 391 : op0 = expand_normal (arg0);
13554 : 391 : elt = get_element_number (TREE_TYPE (arg0), arg1);
13555 : :
13556 : 391 : tmode = TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0)));
13557 : 391 : mode0 = TYPE_MODE (TREE_TYPE (arg0));
13558 : 391 : gcc_assert (VECTOR_MODE_P (mode0));
13559 : :
13560 : 391 : op0 = force_reg (mode0, op0);
13561 : :
13562 : 391 : if (optimize || !target || !register_operand (target, tmode))
13563 : 312 : target = gen_reg_rtx (tmode);
13564 : :
13565 : 391 : ix86_expand_vector_extract (true, target, op0, elt);
13566 : :
13567 : 391 : return target;
13568 : : }
13569 : :
13570 : : /* A subroutine of ix86_expand_builtin. These builtins are a wrapper around
13571 : : ix86_expand_vector_set. They would be redundant (for non-MMX) if we had
13572 : : a language-level syntax for referencing vector elements. */
13573 : :
13574 : : static rtx
13575 : 204 : ix86_expand_vec_set_builtin (tree exp)
13576 : : {
13577 : 204 : machine_mode tmode, mode1;
13578 : 204 : tree arg0, arg1, arg2;
13579 : 204 : int elt;
13580 : 204 : rtx op0, op1, target;
13581 : :
13582 : 204 : arg0 = CALL_EXPR_ARG (exp, 0);
13583 : 204 : arg1 = CALL_EXPR_ARG (exp, 1);
13584 : 204 : arg2 = CALL_EXPR_ARG (exp, 2);
13585 : :
13586 : 204 : tmode = TYPE_MODE (TREE_TYPE (arg0));
13587 : 204 : mode1 = TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0)));
13588 : 204 : gcc_assert (VECTOR_MODE_P (tmode));
13589 : :
13590 : 204 : op0 = expand_expr (arg0, NULL_RTX, tmode, EXPAND_NORMAL);
13591 : 204 : op1 = expand_expr (arg1, NULL_RTX, mode1, EXPAND_NORMAL);
13592 : 204 : elt = get_element_number (TREE_TYPE (arg0), arg2);
13593 : :
13594 : 204 : if (GET_MODE (op1) != mode1)
13595 : 82 : op1 = convert_modes (mode1, GET_MODE (op1), op1, true);
13596 : :
13597 : 204 : op0 = force_reg (tmode, op0);
13598 : 204 : op1 = force_reg (mode1, op1);
13599 : :
13600 : : /* OP0 is the source of these builtin functions and shouldn't be
13601 : : modified. Create a copy, use it and return it as target. */
13602 : 204 : target = gen_reg_rtx (tmode);
13603 : 204 : emit_move_insn (target, op0);
13604 : 204 : ix86_expand_vector_set (true, target, op1, elt);
13605 : :
13606 : 204 : return target;
13607 : : }
13608 : :
13609 : : /* Return true if the necessary isa options for this builtin exist,
13610 : : else false.
13611 : : fcode = DECL_MD_FUNCTION_CODE (fndecl); */
13612 : : bool
13613 : 1247986 : ix86_check_builtin_isa_match (unsigned int fcode,
13614 : : HOST_WIDE_INT* pbisa,
13615 : : HOST_WIDE_INT* pbisa2)
13616 : : {
13617 : 1247986 : HOST_WIDE_INT isa = ix86_isa_flags;
13618 : 1247986 : HOST_WIDE_INT isa2 = ix86_isa_flags2;
13619 : 1247986 : HOST_WIDE_INT bisa = ix86_builtins_isa[fcode].isa;
13620 : 1247986 : HOST_WIDE_INT bisa2 = ix86_builtins_isa[fcode].isa2;
13621 : 1247986 : HOST_WIDE_INT tmp_isa = isa, tmp_isa2 = isa2;
13622 : : /* The general case is we require all the ISAs specified in bisa{,2}
13623 : : to be enabled.
13624 : : The exceptions are:
13625 : : OPTION_MASK_ISA_SSE | OPTION_MASK_ISA_3DNOW_A
13626 : : OPTION_MASK_ISA_SSE4_2 | OPTION_MASK_ISA_CRC32
13627 : : OPTION_MASK_ISA_FMA | OPTION_MASK_ISA_FMA4
13628 : : (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL) or
13629 : : OPTION_MASK_ISA2_AVXVNNI
13630 : : (OPTION_MASK_ISA_AVX512IFMA | OPTION_MASK_ISA_AVX512VL) or
13631 : : OPTION_MASK_ISA2_AVXIFMA
13632 : : (OPTION_MASK_ISA_AVX512VL | OPTION_MASK_ISA2_AVX512BF16) or
13633 : : OPTION_MASK_ISA2_AVXNECONVERT
13634 : : OPTION_MASK_ISA_AES or (OPTION_MASK_ISA_AVX512VL | OPTION_MASK_ISA2_VAES)
13635 : : OPTION_MASK_ISA2_AVX10_2 or OPTION_MASK_ISA2_AVXVNNIINT8
13636 : : OPTION_MASK_ISA2_AVX10_2 or OPTION_MASK_ISA2_AVXVNNIINT16
13637 : : where for each such pair it is sufficient if either of the ISAs is
13638 : : enabled, plus if it is ored with other options also those others.
13639 : : OPTION_MASK_ISA_MMX in bisa is satisfied also if TARGET_MMX_WITH_SSE. */
13640 : :
13641 : : #define SHARE_BUILTIN(A1, A2, B1, B2) \
13642 : : if ((((bisa & (A1)) == (A1) && (bisa2 & (A2)) == (A2)) \
13643 : : && ((bisa & (B1)) == (B1) && (bisa2 & (B2)) == (B2))) \
13644 : : && (((isa & (A1)) == (A1) && (isa2 & (A2)) == (A2)) \
13645 : : || ((isa & (B1)) == (B1) && (isa2 & (B2)) == (B2)))) \
13646 : : { \
13647 : : tmp_isa |= (A1) | (B1); \
13648 : : tmp_isa2 |= (A2) | (B2); \
13649 : : }
13650 : :
13651 : 1247986 : SHARE_BUILTIN (OPTION_MASK_ISA_SSE, 0, OPTION_MASK_ISA_3DNOW_A, 0);
13652 : 1247986 : SHARE_BUILTIN (OPTION_MASK_ISA_SSE4_2, 0, OPTION_MASK_ISA_CRC32, 0);
13653 : 1247986 : SHARE_BUILTIN (OPTION_MASK_ISA_FMA, 0, OPTION_MASK_ISA_FMA4, 0);
13654 : 1247986 : SHARE_BUILTIN (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, 0,
13655 : 1247986 : OPTION_MASK_ISA2_AVXVNNI);
13656 : 1247986 : SHARE_BUILTIN (OPTION_MASK_ISA_AVX512IFMA | OPTION_MASK_ISA_AVX512VL, 0, 0,
13657 : 1247986 : OPTION_MASK_ISA2_AVXIFMA);
13658 : 1247986 : SHARE_BUILTIN (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512BF16, 0,
13659 : 1247986 : OPTION_MASK_ISA2_AVXNECONVERT);
13660 : 1247986 : SHARE_BUILTIN (OPTION_MASK_ISA_AES, 0, OPTION_MASK_ISA_AVX512VL,
13661 : 1247986 : OPTION_MASK_ISA2_VAES);
13662 : 1247986 : SHARE_BUILTIN (0, OPTION_MASK_ISA2_AVXVNNIINT8, 0,
13663 : 1247986 : OPTION_MASK_ISA2_AVX10_2);
13664 : 1247986 : SHARE_BUILTIN (0, OPTION_MASK_ISA2_AVXVNNIINT16, 0,
13665 : 1247986 : OPTION_MASK_ISA2_AVX10_2);
13666 : 1247986 : isa = tmp_isa;
13667 : 1247986 : isa2 = tmp_isa2;
13668 : :
13669 : 1247986 : if ((bisa & OPTION_MASK_ISA_MMX) && !TARGET_MMX && TARGET_MMX_WITH_SSE
13670 : : /* __builtin_ia32_maskmovq requires MMX registers. */
13671 : 4563 : && fcode != IX86_BUILTIN_MASKMOVQ)
13672 : : {
13673 : 4554 : bisa &= ~OPTION_MASK_ISA_MMX;
13674 : 4554 : bisa |= OPTION_MASK_ISA_SSE2;
13675 : : }
13676 : :
13677 : 1247986 : if (pbisa)
13678 : 170346 : *pbisa = bisa;
13679 : 1247986 : if (pbisa2)
13680 : 170346 : *pbisa2 = bisa2;
13681 : :
13682 : 1247986 : return (bisa & isa) == bisa && (bisa2 & isa2) == bisa2;
13683 : : }
13684 : :
13685 : : /* Emit instructions to set the carry flag from ARG. */
13686 : :
13687 : : void
13688 : 13051 : ix86_expand_carry (rtx arg)
13689 : : {
13690 : 13051 : if (!CONST_INT_P (arg) || arg == const0_rtx)
13691 : : {
13692 : 13045 : arg = convert_to_mode (QImode, arg, 1);
13693 : 13045 : arg = copy_to_mode_reg (QImode, arg);
13694 : 13045 : emit_insn (gen_addqi3_cconly_overflow (arg, constm1_rtx));
13695 : : }
13696 : : else
13697 : 6 : emit_insn (gen_x86_stc ());
13698 : 13051 : }
13699 : :
13700 : : /* Expand an expression EXP that calls a built-in function,
13701 : : with result going to TARGET if that's convenient
13702 : : (and in mode MODE if that's convenient).
13703 : : SUBTARGET may be used as the target for computing one of EXP's operands.
13704 : : IGNORE is nonzero if the value is to be ignored. */
13705 : :
13706 : : rtx
13707 : 171115 : ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
13708 : : machine_mode mode, int ignore)
13709 : : {
13710 : 171115 : size_t i;
13711 : 171115 : enum insn_code icode, icode2;
13712 : 171115 : tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
13713 : 171115 : tree arg0, arg1, arg2, arg3, arg4;
13714 : 171115 : rtx op0, op1, op2, op3, op4, pat, pat2, insn;
13715 : 171115 : machine_mode mode0, mode1, mode2, mode3, mode4;
13716 : 171115 : unsigned int fcode = DECL_MD_FUNCTION_CODE (fndecl);
13717 : 171115 : HOST_WIDE_INT bisa, bisa2;
13718 : :
13719 : : /* For CPU builtins that can be folded, fold first and expand the fold. */
13720 : 171115 : switch (fcode)
13721 : : {
13722 : 191 : case IX86_BUILTIN_CPU_INIT:
13723 : 191 : {
13724 : : /* Make it call __cpu_indicator_init in libgcc. */
13725 : 191 : tree call_expr, fndecl, type;
13726 : 191 : type = build_function_type_list (integer_type_node, NULL_TREE);
13727 : 191 : fndecl = build_fn_decl ("__cpu_indicator_init", type);
13728 : 191 : call_expr = build_call_expr (fndecl, 0);
13729 : 191 : return expand_expr (call_expr, target, mode, EXPAND_NORMAL);
13730 : : }
13731 : 578 : case IX86_BUILTIN_CPU_IS:
13732 : 578 : case IX86_BUILTIN_CPU_SUPPORTS:
13733 : 578 : {
13734 : 578 : tree arg0 = CALL_EXPR_ARG (exp, 0);
13735 : 578 : tree fold_expr = fold_builtin_cpu (fndecl, &arg0);
13736 : 578 : gcc_assert (fold_expr != NULL_TREE);
13737 : 578 : return expand_expr (fold_expr, target, mode, EXPAND_NORMAL);
13738 : : }
13739 : : }
13740 : :
13741 : 170346 : if (!ix86_check_builtin_isa_match (fcode, &bisa, &bisa2))
13742 : : {
13743 : 23 : bool add_abi_p = bisa & OPTION_MASK_ISA_64BIT;
13744 : 23 : if (TARGET_ABI_X32)
13745 : 0 : bisa |= OPTION_MASK_ABI_X32;
13746 : : else
13747 : 23 : bisa |= OPTION_MASK_ABI_64;
13748 : 23 : char *opts = ix86_target_string (bisa, bisa2, 0, 0, NULL, NULL,
13749 : : (enum fpmath_unit) 0,
13750 : : (enum prefer_vector_width) 0,
13751 : : PVW_NONE, PVW_NONE,
13752 : : false, add_abi_p);
13753 : 23 : if (!opts)
13754 : 0 : error ("%qE needs unknown isa option", fndecl);
13755 : : else
13756 : : {
13757 : 23 : gcc_assert (opts != NULL);
13758 : 23 : error ("%qE needs isa option %s", fndecl, opts);
13759 : 23 : free (opts);
13760 : : }
13761 : 23 : return expand_call (exp, target, ignore);
13762 : : }
13763 : :
13764 : 170323 : switch (fcode)
13765 : : {
13766 : 35 : case IX86_BUILTIN_MASKMOVQ:
13767 : 35 : case IX86_BUILTIN_MASKMOVDQU:
13768 : 34 : icode = (fcode == IX86_BUILTIN_MASKMOVQ
13769 : 35 : ? CODE_FOR_mmx_maskmovq
13770 : : : CODE_FOR_sse2_maskmovdqu);
13771 : : /* Note the arg order is different from the operand order. */
13772 : 35 : arg1 = CALL_EXPR_ARG (exp, 0);
13773 : 35 : arg2 = CALL_EXPR_ARG (exp, 1);
13774 : 35 : arg0 = CALL_EXPR_ARG (exp, 2);
13775 : 35 : op0 = expand_normal (arg0);
13776 : 35 : op1 = expand_normal (arg1);
13777 : 35 : op2 = expand_normal (arg2);
13778 : 35 : mode0 = insn_data[icode].operand[0].mode;
13779 : 35 : mode1 = insn_data[icode].operand[1].mode;
13780 : 35 : mode2 = insn_data[icode].operand[2].mode;
13781 : :
13782 : 35 : op0 = ix86_zero_extend_to_Pmode (op0);
13783 : 35 : op0 = gen_rtx_MEM (mode1, op0);
13784 : :
13785 : 35 : if (!insn_data[icode].operand[0].predicate (op0, mode0))
13786 : 0 : op0 = copy_to_mode_reg (mode0, op0);
13787 : 35 : if (!insn_data[icode].operand[1].predicate (op1, mode1))
13788 : 2 : op1 = copy_to_mode_reg (mode1, op1);
13789 : 35 : if (!insn_data[icode].operand[2].predicate (op2, mode2))
13790 : 2 : op2 = copy_to_mode_reg (mode2, op2);
13791 : 35 : pat = GEN_FCN (icode) (op0, op1, op2);
13792 : 35 : if (! pat)
13793 : 56545 : return 0;
13794 : 35 : emit_insn (pat);
13795 : 35 : return 0;
13796 : :
13797 : 22002 : case IX86_BUILTIN_LDMXCSR:
13798 : 22002 : op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
13799 : 22002 : target = assign_stack_temp (SImode, GET_MODE_SIZE (SImode));
13800 : 22002 : emit_move_insn (target, op0);
13801 : 22002 : emit_insn (gen_sse_ldmxcsr (target));
13802 : 22002 : return 0;
13803 : :
13804 : 14785 : case IX86_BUILTIN_STMXCSR:
13805 : 14785 : target = assign_stack_temp (SImode, GET_MODE_SIZE (SImode));
13806 : 14785 : emit_insn (gen_sse_stmxcsr (target));
13807 : 14785 : return copy_to_mode_reg (SImode, target);
13808 : :
13809 : 11 : case IX86_BUILTIN_CLFLUSH:
13810 : 11 : arg0 = CALL_EXPR_ARG (exp, 0);
13811 : 11 : op0 = expand_normal (arg0);
13812 : 11 : icode = CODE_FOR_sse2_clflush;
13813 : 11 : if (!insn_data[icode].operand[0].predicate (op0, Pmode))
13814 : 5 : op0 = ix86_zero_extend_to_Pmode (op0);
13815 : :
13816 : 11 : emit_insn (gen_sse2_clflush (op0));
13817 : 11 : return 0;
13818 : :
13819 : 19 : case IX86_BUILTIN_CLWB:
13820 : 19 : arg0 = CALL_EXPR_ARG (exp, 0);
13821 : 19 : op0 = expand_normal (arg0);
13822 : 19 : icode = CODE_FOR_clwb;
13823 : 19 : if (!insn_data[icode].operand[0].predicate (op0, Pmode))
13824 : 9 : op0 = ix86_zero_extend_to_Pmode (op0);
13825 : :
13826 : 19 : emit_insn (gen_clwb (op0));
13827 : 19 : return 0;
13828 : :
13829 : 19 : case IX86_BUILTIN_CLFLUSHOPT:
13830 : 19 : arg0 = CALL_EXPR_ARG (exp, 0);
13831 : 19 : op0 = expand_normal (arg0);
13832 : 19 : icode = CODE_FOR_clflushopt;
13833 : 19 : if (!insn_data[icode].operand[0].predicate (op0, Pmode))
13834 : 9 : op0 = ix86_zero_extend_to_Pmode (op0);
13835 : :
13836 : 19 : emit_insn (gen_clflushopt (op0));
13837 : 19 : return 0;
13838 : :
13839 : 47 : case IX86_BUILTIN_MONITOR:
13840 : 47 : case IX86_BUILTIN_MONITORX:
13841 : 47 : arg0 = CALL_EXPR_ARG (exp, 0);
13842 : 47 : arg1 = CALL_EXPR_ARG (exp, 1);
13843 : 47 : arg2 = CALL_EXPR_ARG (exp, 2);
13844 : 47 : op0 = expand_normal (arg0);
13845 : 47 : op1 = expand_normal (arg1);
13846 : 47 : op2 = expand_normal (arg2);
13847 : 47 : if (!REG_P (op0))
13848 : 19 : op0 = ix86_zero_extend_to_Pmode (op0);
13849 : 47 : if (!REG_P (op1))
13850 : 22 : op1 = copy_to_mode_reg (SImode, op1);
13851 : 47 : if (!REG_P (op2))
13852 : 25 : op2 = copy_to_mode_reg (SImode, op2);
13853 : :
13854 : 47 : emit_insn (fcode == IX86_BUILTIN_MONITOR
13855 : 26 : ? gen_sse3_monitor (Pmode, op0, op1, op2)
13856 : 21 : : gen_monitorx (Pmode, op0, op1, op2));
13857 : 47 : return 0;
13858 : :
13859 : 25 : case IX86_BUILTIN_MWAIT:
13860 : 25 : arg0 = CALL_EXPR_ARG (exp, 0);
13861 : 25 : arg1 = CALL_EXPR_ARG (exp, 1);
13862 : 25 : op0 = expand_normal (arg0);
13863 : 25 : op1 = expand_normal (arg1);
13864 : 25 : if (!REG_P (op0))
13865 : 13 : op0 = copy_to_mode_reg (SImode, op0);
13866 : 25 : if (!REG_P (op1))
13867 : 11 : op1 = copy_to_mode_reg (SImode, op1);
13868 : 25 : emit_insn (gen_sse3_mwait (op0, op1));
13869 : 25 : return 0;
13870 : :
13871 : 21 : case IX86_BUILTIN_MWAITX:
13872 : 21 : arg0 = CALL_EXPR_ARG (exp, 0);
13873 : 21 : arg1 = CALL_EXPR_ARG (exp, 1);
13874 : 21 : arg2 = CALL_EXPR_ARG (exp, 2);
13875 : 21 : op0 = expand_normal (arg0);
13876 : 21 : op1 = expand_normal (arg1);
13877 : 21 : op2 = expand_normal (arg2);
13878 : 21 : if (!REG_P (op0))
13879 : 11 : op0 = copy_to_mode_reg (SImode, op0);
13880 : 21 : if (!REG_P (op1))
13881 : 10 : op1 = copy_to_mode_reg (SImode, op1);
13882 : 21 : if (!REG_P (op2))
13883 : 11 : op2 = copy_to_mode_reg (SImode, op2);
13884 : 21 : emit_insn (gen_mwaitx (op0, op1, op2));
13885 : 21 : return 0;
13886 : :
13887 : 21 : case IX86_BUILTIN_UMONITOR:
13888 : 21 : arg0 = CALL_EXPR_ARG (exp, 0);
13889 : 21 : op0 = expand_normal (arg0);
13890 : :
13891 : 21 : op0 = ix86_zero_extend_to_Pmode (op0);
13892 : 21 : emit_insn (gen_umonitor (Pmode, op0));
13893 : 21 : return 0;
13894 : :
13895 : 42 : case IX86_BUILTIN_UMWAIT:
13896 : 42 : case IX86_BUILTIN_TPAUSE:
13897 : 42 : arg0 = CALL_EXPR_ARG (exp, 0);
13898 : 42 : arg1 = CALL_EXPR_ARG (exp, 1);
13899 : 42 : op0 = expand_normal (arg0);
13900 : 42 : op1 = expand_normal (arg1);
13901 : :
13902 : 42 : if (!REG_P (op0))
13903 : 20 : op0 = copy_to_mode_reg (SImode, op0);
13904 : :
13905 : 42 : op1 = force_reg (DImode, op1);
13906 : :
13907 : 42 : if (TARGET_64BIT)
13908 : : {
13909 : 42 : op2 = expand_simple_binop (DImode, LSHIFTRT, op1, GEN_INT (32),
13910 : : NULL, 1, OPTAB_DIRECT);
13911 : 42 : switch (fcode)
13912 : : {
13913 : : case IX86_BUILTIN_UMWAIT:
13914 : : icode = CODE_FOR_umwait_rex64;
13915 : : break;
13916 : 21 : case IX86_BUILTIN_TPAUSE:
13917 : 21 : icode = CODE_FOR_tpause_rex64;
13918 : 21 : break;
13919 : 0 : default:
13920 : 0 : gcc_unreachable ();
13921 : : }
13922 : :
13923 : 42 : op2 = gen_lowpart (SImode, op2);
13924 : 42 : op1 = gen_lowpart (SImode, op1);
13925 : 42 : pat = GEN_FCN (icode) (op0, op1, op2);
13926 : : }
13927 : : else
13928 : : {
13929 : 0 : switch (fcode)
13930 : : {
13931 : : case IX86_BUILTIN_UMWAIT:
13932 : : icode = CODE_FOR_umwait;
13933 : : break;
13934 : 0 : case IX86_BUILTIN_TPAUSE:
13935 : 0 : icode = CODE_FOR_tpause;
13936 : 0 : break;
13937 : 0 : default:
13938 : 0 : gcc_unreachable ();
13939 : : }
13940 : 0 : pat = GEN_FCN (icode) (op0, op1);
13941 : : }
13942 : :
13943 : 42 : if (!pat)
13944 : : return 0;
13945 : :
13946 : 42 : emit_insn (pat);
13947 : :
13948 : 42 : if (target == 0
13949 : 42 : || !register_operand (target, QImode))
13950 : 0 : target = gen_reg_rtx (QImode);
13951 : :
13952 : 42 : pat = gen_rtx_EQ (QImode, gen_rtx_REG (CCCmode, FLAGS_REG),
13953 : : const0_rtx);
13954 : 42 : emit_insn (gen_rtx_SET (target, pat));
13955 : :
13956 : 42 : return target;
13957 : :
13958 : 20 : case IX86_BUILTIN_TESTUI:
13959 : 20 : emit_insn (gen_testui ());
13960 : :
13961 : 20 : if (target == 0
13962 : 20 : || !register_operand (target, QImode))
13963 : 0 : target = gen_reg_rtx (QImode);
13964 : :
13965 : 20 : pat = gen_rtx_LTU (QImode, gen_rtx_REG (CCCmode, FLAGS_REG),
13966 : : const0_rtx);
13967 : 20 : emit_insn (gen_rtx_SET (target, pat));
13968 : :
13969 : 20 : return target;
13970 : :
13971 : 19 : case IX86_BUILTIN_CLZERO:
13972 : 19 : arg0 = CALL_EXPR_ARG (exp, 0);
13973 : 19 : op0 = expand_normal (arg0);
13974 : 19 : if (!REG_P (op0))
13975 : 9 : op0 = ix86_zero_extend_to_Pmode (op0);
13976 : 19 : emit_insn (gen_clzero (Pmode, op0));
13977 : 19 : return 0;
13978 : :
13979 : 19 : case IX86_BUILTIN_CLDEMOTE:
13980 : 19 : arg0 = CALL_EXPR_ARG (exp, 0);
13981 : 19 : op0 = expand_normal (arg0);
13982 : 19 : icode = CODE_FOR_cldemote;
13983 : 19 : if (!insn_data[icode].operand[0].predicate (op0, Pmode))
13984 : 9 : op0 = ix86_zero_extend_to_Pmode (op0);
13985 : :
13986 : 19 : emit_insn (gen_cldemote (op0));
13987 : 19 : return 0;
13988 : :
13989 : 11 : case IX86_BUILTIN_LOADIWKEY:
13990 : 11 : {
13991 : 11 : arg0 = CALL_EXPR_ARG (exp, 0);
13992 : 11 : arg1 = CALL_EXPR_ARG (exp, 1);
13993 : 11 : arg2 = CALL_EXPR_ARG (exp, 2);
13994 : 11 : arg3 = CALL_EXPR_ARG (exp, 3);
13995 : :
13996 : 11 : op0 = expand_normal (arg0);
13997 : 11 : op1 = expand_normal (arg1);
13998 : 11 : op2 = expand_normal (arg2);
13999 : 11 : op3 = expand_normal (arg3);
14000 : :
14001 : 11 : if (!REG_P (op0))
14002 : 5 : op0 = copy_to_mode_reg (V2DImode, op0);
14003 : 11 : if (!REG_P (op1))
14004 : 5 : op1 = copy_to_mode_reg (V2DImode, op1);
14005 : 11 : if (!REG_P (op2))
14006 : 5 : op2 = copy_to_mode_reg (V2DImode, op2);
14007 : 11 : if (!REG_P (op3))
14008 : 5 : op3 = copy_to_mode_reg (SImode, op3);
14009 : :
14010 : 11 : emit_insn (gen_loadiwkey (op0, op1, op2, op3));
14011 : :
14012 : 11 : return 0;
14013 : : }
14014 : :
14015 : 12 : case IX86_BUILTIN_AESDEC128KLU8:
14016 : 12 : icode = CODE_FOR_aesdec128klu8;
14017 : 12 : goto aesdecenc_expand;
14018 : :
14019 : 12 : case IX86_BUILTIN_AESDEC256KLU8:
14020 : 12 : icode = CODE_FOR_aesdec256klu8;
14021 : 12 : goto aesdecenc_expand;
14022 : :
14023 : 12 : case IX86_BUILTIN_AESENC128KLU8:
14024 : 12 : icode = CODE_FOR_aesenc128klu8;
14025 : 12 : goto aesdecenc_expand;
14026 : :
14027 : : case IX86_BUILTIN_AESENC256KLU8:
14028 : : icode = CODE_FOR_aesenc256klu8;
14029 : :
14030 : 48 : aesdecenc_expand:
14031 : :
14032 : 48 : arg0 = CALL_EXPR_ARG (exp, 0); // __m128i *odata
14033 : 48 : arg1 = CALL_EXPR_ARG (exp, 1); // __m128i idata
14034 : 48 : arg2 = CALL_EXPR_ARG (exp, 2); // const void *p
14035 : :
14036 : 48 : op0 = expand_normal (arg0);
14037 : 48 : op1 = expand_normal (arg1);
14038 : 48 : op2 = expand_normal (arg2);
14039 : :
14040 : 48 : if (!address_operand (op0, V2DImode))
14041 : : {
14042 : 16 : op0 = convert_memory_address (Pmode, op0);
14043 : 16 : op0 = copy_addr_to_reg (op0);
14044 : : }
14045 : 48 : op0 = gen_rtx_MEM (V2DImode, op0);
14046 : :
14047 : 48 : if (!REG_P (op1))
14048 : 20 : op1 = copy_to_mode_reg (V2DImode, op1);
14049 : :
14050 : 48 : if (!address_operand (op2, VOIDmode))
14051 : : {
14052 : 16 : op2 = convert_memory_address (Pmode, op2);
14053 : 16 : op2 = copy_addr_to_reg (op2);
14054 : : }
14055 : 48 : op2 = gen_rtx_MEM (BLKmode, op2);
14056 : :
14057 : 48 : emit_insn (GEN_FCN (icode) (op1, op1, op2));
14058 : :
14059 : 48 : if (target == 0)
14060 : 4 : target = gen_reg_rtx (QImode);
14061 : :
14062 : : /* NB: For aesenc/aesdec keylocker insn, ZF will be set when runtime
14063 : : error occurs. Then the output should be cleared for safety. */
14064 : 48 : rtx_code_label *ok_label;
14065 : 48 : rtx tmp;
14066 : :
14067 : 48 : tmp = gen_rtx_REG (CCZmode, FLAGS_REG);
14068 : 48 : pat = gen_rtx_EQ (QImode, tmp, const0_rtx);
14069 : 48 : ok_label = gen_label_rtx ();
14070 : 48 : emit_cmp_and_jump_insns (tmp, const0_rtx, NE, 0, GET_MODE (tmp),
14071 : : true, ok_label);
14072 : : /* Usually the runtime error seldom occur, so predict OK path as
14073 : : hotspot to optimize it as fallthrough block. */
14074 : 48 : predict_jump (REG_BR_PROB_BASE * 90 / 100);
14075 : :
14076 : 48 : emit_insn (gen_rtx_SET (op1, const0_rtx));
14077 : :
14078 : 48 : emit_label (ok_label);
14079 : 48 : emit_insn (gen_rtx_SET (target, pat));
14080 : 48 : emit_insn (gen_rtx_SET (op0, op1));
14081 : :
14082 : 48 : return target;
14083 : :
14084 : 11 : case IX86_BUILTIN_AESDECWIDE128KLU8:
14085 : 11 : icode = CODE_FOR_aesdecwide128klu8;
14086 : 11 : goto wideaesdecenc_expand;
14087 : :
14088 : 11 : case IX86_BUILTIN_AESDECWIDE256KLU8:
14089 : 11 : icode = CODE_FOR_aesdecwide256klu8;
14090 : 11 : goto wideaesdecenc_expand;
14091 : :
14092 : 11 : case IX86_BUILTIN_AESENCWIDE128KLU8:
14093 : 11 : icode = CODE_FOR_aesencwide128klu8;
14094 : 11 : goto wideaesdecenc_expand;
14095 : :
14096 : : case IX86_BUILTIN_AESENCWIDE256KLU8:
14097 : : icode = CODE_FOR_aesencwide256klu8;
14098 : :
14099 : 44 : wideaesdecenc_expand:
14100 : :
14101 : 44 : rtx xmm_regs[8];
14102 : 44 : rtx op;
14103 : :
14104 : 44 : arg0 = CALL_EXPR_ARG (exp, 0); // __m128i * odata
14105 : 44 : arg1 = CALL_EXPR_ARG (exp, 1); // const __m128i * idata
14106 : 44 : arg2 = CALL_EXPR_ARG (exp, 2); // const void *p
14107 : :
14108 : 44 : op0 = expand_normal (arg0);
14109 : 44 : op1 = expand_normal (arg1);
14110 : 44 : op2 = expand_normal (arg2);
14111 : :
14112 : 44 : if (GET_MODE (op1) != Pmode)
14113 : 0 : op1 = convert_to_mode (Pmode, op1, 1);
14114 : :
14115 : 44 : if (!address_operand (op2, VOIDmode))
14116 : : {
14117 : 16 : op2 = convert_memory_address (Pmode, op2);
14118 : 16 : op2 = copy_addr_to_reg (op2);
14119 : : }
14120 : 44 : op2 = gen_rtx_MEM (BLKmode, op2);
14121 : :
14122 : 440 : for (i = 0; i < 8; i++)
14123 : : {
14124 : 352 : xmm_regs[i] = gen_rtx_REG (V2DImode, GET_SSE_REGNO (i));
14125 : :
14126 : 352 : op = gen_rtx_MEM (V2DImode,
14127 : 352 : plus_constant (Pmode, op1, (i * 16)));
14128 : :
14129 : 352 : emit_move_insn (xmm_regs[i], op);
14130 : : }
14131 : :
14132 : 44 : emit_insn (GEN_FCN (icode) (op2));
14133 : :
14134 : 44 : if (target == 0)
14135 : 0 : target = gen_reg_rtx (QImode);
14136 : :
14137 : 44 : tmp = gen_rtx_REG (CCZmode, FLAGS_REG);
14138 : 44 : pat = gen_rtx_EQ (QImode, tmp, const0_rtx);
14139 : 44 : ok_label = gen_label_rtx ();
14140 : 44 : emit_cmp_and_jump_insns (tmp, const0_rtx, NE, 0, GET_MODE (tmp),
14141 : : true, ok_label);
14142 : 44 : predict_jump (REG_BR_PROB_BASE * 90 / 100);
14143 : :
14144 : 440 : for (i = 0; i < 8; i++)
14145 : 352 : emit_insn (gen_rtx_SET (xmm_regs[i], const0_rtx));
14146 : :
14147 : 44 : emit_label (ok_label);
14148 : 44 : emit_insn (gen_rtx_SET (target, pat));
14149 : :
14150 : 44 : if (GET_MODE (op0) != Pmode)
14151 : 0 : op0 = convert_to_mode (Pmode, op0, 1);
14152 : :
14153 : 396 : for (i = 0; i < 8; i++)
14154 : : {
14155 : 352 : op = gen_rtx_MEM (V2DImode,
14156 : 352 : plus_constant (Pmode, op0, (i * 16)));
14157 : 352 : emit_move_insn (op, xmm_regs[i]);
14158 : : }
14159 : :
14160 : : return target;
14161 : :
14162 : 12 : case IX86_BUILTIN_ENCODEKEY128U32:
14163 : 12 : {
14164 : 12 : rtx op, xmm_regs[7];
14165 : :
14166 : 12 : arg0 = CALL_EXPR_ARG (exp, 0); // unsigned int htype
14167 : 12 : arg1 = CALL_EXPR_ARG (exp, 1); // __m128i key
14168 : 12 : arg2 = CALL_EXPR_ARG (exp, 2); // void *h
14169 : :
14170 : 12 : op0 = expand_normal (arg0);
14171 : 12 : op1 = expand_normal (arg1);
14172 : 12 : op2 = expand_normal (arg2);
14173 : :
14174 : 12 : if (!REG_P (op0))
14175 : 6 : op0 = copy_to_mode_reg (SImode, op0);
14176 : :
14177 : 12 : if (GET_MODE (op2) != Pmode)
14178 : 1 : op2 = convert_to_mode (Pmode, op2, 1);
14179 : :
14180 : 12 : op = gen_rtx_REG (V2DImode, GET_SSE_REGNO (0));
14181 : 12 : emit_move_insn (op, op1);
14182 : :
14183 : 60 : for (i = 0; i < 3; i++)
14184 : 36 : xmm_regs[i] = gen_rtx_REG (V2DImode, GET_SSE_REGNO (i));
14185 : :
14186 : 12 : if (target == 0)
14187 : 1 : target = gen_reg_rtx (SImode);
14188 : :
14189 : 12 : emit_insn (gen_encodekey128u32 (target, op0));
14190 : :
14191 : 60 : for (i = 0; i < 3; i++)
14192 : : {
14193 : 36 : op = gen_rtx_MEM (V2DImode,
14194 : 36 : plus_constant (Pmode, op2, (i * 16)));
14195 : 36 : emit_move_insn (op, xmm_regs[i]);
14196 : : }
14197 : :
14198 : 12 : return target;
14199 : : }
14200 : 12 : case IX86_BUILTIN_ENCODEKEY256U32:
14201 : 12 : {
14202 : 12 : rtx op, xmm_regs[7];
14203 : :
14204 : 12 : arg0 = CALL_EXPR_ARG (exp, 0); // unsigned int htype
14205 : 12 : arg1 = CALL_EXPR_ARG (exp, 1); // __m128i keylow
14206 : 12 : arg2 = CALL_EXPR_ARG (exp, 2); // __m128i keyhi
14207 : 12 : arg3 = CALL_EXPR_ARG (exp, 3); // void *h
14208 : :
14209 : 12 : op0 = expand_normal (arg0);
14210 : 12 : op1 = expand_normal (arg1);
14211 : 12 : op2 = expand_normal (arg2);
14212 : 12 : op3 = expand_normal (arg3);
14213 : :
14214 : 12 : if (!REG_P (op0))
14215 : 6 : op0 = copy_to_mode_reg (SImode, op0);
14216 : :
14217 : 12 : if (GET_MODE (op3) != Pmode)
14218 : 1 : op3 = convert_to_mode (Pmode, op3, 1);
14219 : :
14220 : : /* Force to use xmm0, xmm1 for keylow, keyhi*/
14221 : 12 : op = gen_rtx_REG (V2DImode, GET_SSE_REGNO (0));
14222 : 12 : emit_move_insn (op, op1);
14223 : 12 : op = gen_rtx_REG (V2DImode, GET_SSE_REGNO (1));
14224 : 12 : emit_move_insn (op, op2);
14225 : :
14226 : 72 : for (i = 0; i < 4; i++)
14227 : 48 : xmm_regs[i] = gen_rtx_REG (V2DImode, GET_SSE_REGNO (i));
14228 : :
14229 : 12 : if (target == 0)
14230 : 1 : target = gen_reg_rtx (SImode);
14231 : :
14232 : 12 : emit_insn (gen_encodekey256u32 (target, op0));
14233 : :
14234 : 72 : for (i = 0; i < 4; i++)
14235 : : {
14236 : 48 : op = gen_rtx_MEM (V2DImode,
14237 : 48 : plus_constant (Pmode, op3, (i * 16)));
14238 : 48 : emit_move_insn (op, xmm_regs[i]);
14239 : : }
14240 : :
14241 : 12 : return target;
14242 : : }
14243 : :
14244 : 48 : case IX86_BUILTIN_PREFETCH:
14245 : 48 : {
14246 : 48 : arg0 = CALL_EXPR_ARG (exp, 0); // const void *
14247 : 48 : arg1 = CALL_EXPR_ARG (exp, 1); // const int
14248 : 48 : arg2 = CALL_EXPR_ARG (exp, 2); // const int
14249 : 48 : arg3 = CALL_EXPR_ARG (exp, 3); // const int
14250 : :
14251 : 48 : op0 = expand_normal (arg0);
14252 : 48 : op1 = expand_normal (arg1);
14253 : 48 : op2 = expand_normal (arg2);
14254 : 48 : op3 = expand_normal (arg3);
14255 : :
14256 : 48 : if (!CONST_INT_P (op1) || !CONST_INT_P (op2) || !CONST_INT_P (op3))
14257 : : {
14258 : 0 : error ("second, third and fourth argument must be a const");
14259 : 0 : return const0_rtx;
14260 : : }
14261 : :
14262 : 48 : if (!IN_RANGE (INTVAL (op1), 0, 2))
14263 : : {
14264 : 1 : warning (0, "invalid second argument to"
14265 : : " %<__builtin_ia32_prefetch%>; using zero");
14266 : 1 : op1 = const0_rtx;
14267 : : }
14268 : :
14269 : 48 : if (INTVAL (op3) == 1)
14270 : : {
14271 : 4 : if (!IN_RANGE (INTVAL (op2), 2, 3))
14272 : : {
14273 : 1 : error ("invalid third argument");
14274 : 1 : return const0_rtx;
14275 : : }
14276 : :
14277 : 3 : if (TARGET_64BIT && TARGET_PREFETCHI
14278 : 6 : && local_func_symbolic_operand (op0, GET_MODE (op0)))
14279 : 2 : emit_insn (gen_prefetchi (op0, op2));
14280 : : else
14281 : : {
14282 : 1 : warning (0, "instruction prefetch applies when in 64-bit mode"
14283 : : " with RIP-relative addressing and"
14284 : : " option %<-mprefetchi%>;"
14285 : : " they stay NOPs otherwise");
14286 : 1 : emit_insn (gen_nop ());
14287 : : }
14288 : : }
14289 : : else
14290 : : {
14291 : 44 : if (INTVAL (op3) != 0)
14292 : 1 : warning (0, "invalid forth argument to"
14293 : : " %<__builtin_ia32_prefetch%>; using zero");
14294 : :
14295 : 44 : if (!address_operand (op0, VOIDmode))
14296 : : {
14297 : 10 : op0 = convert_memory_address (Pmode, op0);
14298 : 10 : op0 = copy_addr_to_reg (op0);
14299 : : }
14300 : :
14301 : 44 : if (!IN_RANGE (INTVAL (op2), 0, 3))
14302 : : {
14303 : 1 : warning (0, "invalid third argument to %<__builtin_ia32_prefetch%>; using zero");
14304 : 1 : op2 = const0_rtx;
14305 : : }
14306 : :
14307 : 44 : if (TARGET_3DNOW
14308 : 26 : || TARGET_PREFETCH_SSE
14309 : 0 : || TARGET_PRFCHW
14310 : 0 : || TARGET_MOVRS)
14311 : 44 : emit_insn (gen_prefetch (op0, op1, op2));
14312 : 0 : else if (!MEM_P (op0) && side_effects_p (op0))
14313 : : /* Don't do anything with direct references to volatile memory,
14314 : : but generate code to handle other side effects. */
14315 : 0 : emit_insn (op0);
14316 : : }
14317 : :
14318 : : return 0;
14319 : : }
14320 : :
14321 : 21 : case IX86_BUILTIN_PREFETCHI:
14322 : 21 : {
14323 : 21 : arg0 = CALL_EXPR_ARG (exp, 0); // const void *
14324 : 21 : arg1 = CALL_EXPR_ARG (exp, 1); // const int
14325 : :
14326 : 21 : op0 = expand_normal (arg0);
14327 : 21 : op1 = expand_normal (arg1);
14328 : :
14329 : 21 : if (!CONST_INT_P (op1))
14330 : : {
14331 : 0 : error ("second argument must be a const");
14332 : 0 : return const0_rtx;
14333 : : }
14334 : :
14335 : : /* GOT/PLT_PIC should not be available for instruction prefetch.
14336 : : It must be real instruction address. */
14337 : 21 : if (TARGET_64BIT
14338 : 21 : && local_func_symbolic_operand (op0, GET_MODE (op0)))
14339 : 4 : emit_insn (gen_prefetchi (op0, op1));
14340 : : else
14341 : : {
14342 : : /* Ignore the hint. */
14343 : 17 : warning (0, "instruction prefetch applies when in 64-bit mode"
14344 : : " with RIP-relative addressing and"
14345 : : " option %<-mprefetchi%>;"
14346 : : " they stay NOPs otherwise");
14347 : 17 : emit_insn (gen_nop ());
14348 : : }
14349 : :
14350 : : return 0;
14351 : : }
14352 : :
14353 : 52 : case IX86_BUILTIN_URDMSR:
14354 : 52 : case IX86_BUILTIN_UWRMSR:
14355 : 52 : {
14356 : 52 : arg0 = CALL_EXPR_ARG (exp, 0);
14357 : 52 : op0 = expand_normal (arg0);
14358 : :
14359 : 52 : if (CONST_INT_P (op0))
14360 : : {
14361 : 12 : unsigned HOST_WIDE_INT val = UINTVAL (op0);
14362 : 12 : if (val > 0xffffffff)
14363 : 2 : op0 = force_reg (DImode, op0);
14364 : : }
14365 : : else
14366 : 40 : op0 = force_reg (DImode, op0);
14367 : :
14368 : 52 : if (fcode == IX86_BUILTIN_UWRMSR)
14369 : : {
14370 : 26 : arg1 = CALL_EXPR_ARG (exp, 1);
14371 : 26 : op1 = expand_normal (arg1);
14372 : 26 : op1 = force_reg (DImode, op1);
14373 : 26 : icode = CODE_FOR_uwrmsr;
14374 : 26 : target = 0;
14375 : : }
14376 : : else
14377 : : {
14378 : 26 : if (target == 0)
14379 : 0 : target = gen_reg_rtx (DImode);
14380 : : icode = CODE_FOR_urdmsr;
14381 : : op1 = op0;
14382 : : op0 = target;
14383 : : }
14384 : 52 : emit_insn (GEN_FCN (icode) (op0, op1));
14385 : 52 : return target;
14386 : : }
14387 : :
14388 : 229 : case IX86_BUILTIN_VEC_INIT_V2SI:
14389 : 229 : case IX86_BUILTIN_VEC_INIT_V4HI:
14390 : 229 : case IX86_BUILTIN_VEC_INIT_V8QI:
14391 : 229 : return ix86_expand_vec_init_builtin (TREE_TYPE (exp), exp, target);
14392 : :
14393 : 391 : case IX86_BUILTIN_VEC_EXT_V2DF:
14394 : 391 : case IX86_BUILTIN_VEC_EXT_V2DI:
14395 : 391 : case IX86_BUILTIN_VEC_EXT_V4SF:
14396 : 391 : case IX86_BUILTIN_VEC_EXT_V4SI:
14397 : 391 : case IX86_BUILTIN_VEC_EXT_V8HI:
14398 : 391 : case IX86_BUILTIN_VEC_EXT_V2SI:
14399 : 391 : case IX86_BUILTIN_VEC_EXT_V4HI:
14400 : 391 : case IX86_BUILTIN_VEC_EXT_V16QI:
14401 : 391 : return ix86_expand_vec_ext_builtin (exp, target);
14402 : :
14403 : 204 : case IX86_BUILTIN_VEC_SET_V2DI:
14404 : 204 : case IX86_BUILTIN_VEC_SET_V4SF:
14405 : 204 : case IX86_BUILTIN_VEC_SET_V4SI:
14406 : 204 : case IX86_BUILTIN_VEC_SET_V8HI:
14407 : 204 : case IX86_BUILTIN_VEC_SET_V4HI:
14408 : 204 : case IX86_BUILTIN_VEC_SET_V16QI:
14409 : 204 : return ix86_expand_vec_set_builtin (exp);
14410 : :
14411 : 0 : case IX86_BUILTIN_NANQ:
14412 : 0 : case IX86_BUILTIN_NANSQ:
14413 : 0 : return expand_call (exp, target, ignore);
14414 : :
14415 : 18 : case IX86_BUILTIN_RDPID:
14416 : :
14417 : 18 : op0 = gen_reg_rtx (word_mode);
14418 : :
14419 : 18 : if (TARGET_64BIT)
14420 : : {
14421 : 18 : insn = gen_rdpid_rex64 (op0);
14422 : 18 : op0 = convert_to_mode (SImode, op0, 1);
14423 : : }
14424 : : else
14425 : 0 : insn = gen_rdpid (op0);
14426 : :
14427 : 18 : emit_insn (insn);
14428 : :
14429 : 18 : if (target == 0
14430 : 18 : || !register_operand (target, SImode))
14431 : 0 : target = gen_reg_rtx (SImode);
14432 : :
14433 : 18 : emit_move_insn (target, op0);
14434 : 18 : return target;
14435 : :
14436 : 75 : case IX86_BUILTIN_2INTERSECTD512:
14437 : 75 : case IX86_BUILTIN_2INTERSECTQ512:
14438 : 75 : case IX86_BUILTIN_2INTERSECTD256:
14439 : 75 : case IX86_BUILTIN_2INTERSECTQ256:
14440 : 75 : case IX86_BUILTIN_2INTERSECTD128:
14441 : 75 : case IX86_BUILTIN_2INTERSECTQ128:
14442 : 75 : arg0 = CALL_EXPR_ARG (exp, 0);
14443 : 75 : arg1 = CALL_EXPR_ARG (exp, 1);
14444 : 75 : arg2 = CALL_EXPR_ARG (exp, 2);
14445 : 75 : arg3 = CALL_EXPR_ARG (exp, 3);
14446 : 75 : op0 = expand_normal (arg0);
14447 : 75 : op1 = expand_normal (arg1);
14448 : 75 : op2 = expand_normal (arg2);
14449 : 75 : op3 = expand_normal (arg3);
14450 : :
14451 : 75 : if (!address_operand (op0, VOIDmode))
14452 : : {
14453 : 25 : op0 = convert_memory_address (Pmode, op0);
14454 : 25 : op0 = copy_addr_to_reg (op0);
14455 : : }
14456 : 75 : if (!address_operand (op1, VOIDmode))
14457 : : {
14458 : 25 : op1 = convert_memory_address (Pmode, op1);
14459 : 25 : op1 = copy_addr_to_reg (op1);
14460 : : }
14461 : :
14462 : 75 : switch (fcode)
14463 : : {
14464 : : case IX86_BUILTIN_2INTERSECTD512:
14465 : : mode4 = P2HImode;
14466 : : icode = CODE_FOR_avx512vp2intersect_2intersectv16si;
14467 : : break;
14468 : : case IX86_BUILTIN_2INTERSECTQ512:
14469 : : mode4 = P2QImode;
14470 : : icode = CODE_FOR_avx512vp2intersect_2intersectv8di;
14471 : : break;
14472 : : case IX86_BUILTIN_2INTERSECTD256:
14473 : : mode4 = P2QImode;
14474 : : icode = CODE_FOR_avx512vp2intersect_2intersectv8si;
14475 : : break;
14476 : : case IX86_BUILTIN_2INTERSECTQ256:
14477 : : mode4 = P2QImode;
14478 : : icode = CODE_FOR_avx512vp2intersect_2intersectv4di;
14479 : : break;
14480 : : case IX86_BUILTIN_2INTERSECTD128:
14481 : : mode4 = P2QImode;
14482 : : icode = CODE_FOR_avx512vp2intersect_2intersectv4si;
14483 : : break;
14484 : : case IX86_BUILTIN_2INTERSECTQ128:
14485 : : mode4 = P2QImode;
14486 : : icode = CODE_FOR_avx512vp2intersect_2intersectv2di;
14487 : : break;
14488 : 0 : default:
14489 : 0 : gcc_unreachable ();
14490 : : }
14491 : :
14492 : 75 : mode2 = insn_data[icode].operand[1].mode;
14493 : 75 : mode3 = insn_data[icode].operand[2].mode;
14494 : 75 : if (!insn_data[icode].operand[1].predicate (op2, mode2))
14495 : 25 : op2 = copy_to_mode_reg (mode2, op2);
14496 : 75 : if (!insn_data[icode].operand[2].predicate (op3, mode3))
14497 : 6 : op3 = copy_to_mode_reg (mode3, op3);
14498 : :
14499 : 75 : op4 = gen_reg_rtx (mode4);
14500 : 75 : emit_insn (GEN_FCN (icode) (op4, op2, op3));
14501 : 75 : mode0 = mode4 == P2HImode ? HImode : QImode;
14502 : 75 : emit_move_insn (gen_rtx_MEM (mode0, op0),
14503 : 75 : gen_lowpart (mode0, op4));
14504 : 75 : emit_move_insn (gen_rtx_MEM (mode0, op1),
14505 : : gen_highpart (mode0, op4));
14506 : :
14507 : 75 : return 0;
14508 : :
14509 : 102 : case IX86_BUILTIN_RDPMC:
14510 : 102 : case IX86_BUILTIN_RDTSC:
14511 : 102 : case IX86_BUILTIN_RDTSCP:
14512 : 102 : case IX86_BUILTIN_XGETBV:
14513 : :
14514 : 102 : op0 = gen_reg_rtx (DImode);
14515 : 102 : op1 = gen_reg_rtx (DImode);
14516 : :
14517 : 102 : if (fcode == IX86_BUILTIN_RDPMC)
14518 : : {
14519 : 22 : arg0 = CALL_EXPR_ARG (exp, 0);
14520 : 22 : op2 = expand_normal (arg0);
14521 : 22 : if (!register_operand (op2, SImode))
14522 : 11 : op2 = copy_to_mode_reg (SImode, op2);
14523 : :
14524 : 22 : insn = (TARGET_64BIT
14525 : 22 : ? gen_rdpmc_rex64 (op0, op1, op2)
14526 : 0 : : gen_rdpmc (op0, op2));
14527 : 22 : emit_insn (insn);
14528 : : }
14529 : 80 : else if (fcode == IX86_BUILTIN_XGETBV)
14530 : : {
14531 : 22 : arg0 = CALL_EXPR_ARG (exp, 0);
14532 : 22 : op2 = expand_normal (arg0);
14533 : 22 : if (!register_operand (op2, SImode))
14534 : 1 : op2 = copy_to_mode_reg (SImode, op2);
14535 : :
14536 : 22 : insn = (TARGET_64BIT
14537 : 22 : ? gen_xgetbv_rex64 (op0, op1, op2)
14538 : 0 : : gen_xgetbv (op0, op2));
14539 : 22 : emit_insn (insn);
14540 : : }
14541 : 58 : else if (fcode == IX86_BUILTIN_RDTSC)
14542 : : {
14543 : 36 : insn = (TARGET_64BIT
14544 : 36 : ? gen_rdtsc_rex64 (op0, op1)
14545 : 2 : : gen_rdtsc (op0));
14546 : 36 : emit_insn (insn);
14547 : : }
14548 : : else
14549 : : {
14550 : 22 : op2 = gen_reg_rtx (SImode);
14551 : :
14552 : 22 : insn = (TARGET_64BIT
14553 : 22 : ? gen_rdtscp_rex64 (op0, op1, op2)
14554 : 0 : : gen_rdtscp (op0, op2));
14555 : 22 : emit_insn (insn);
14556 : :
14557 : 22 : arg0 = CALL_EXPR_ARG (exp, 0);
14558 : 22 : op4 = expand_normal (arg0);
14559 : 22 : if (!address_operand (op4, VOIDmode))
14560 : : {
14561 : 10 : op4 = convert_memory_address (Pmode, op4);
14562 : 10 : op4 = copy_addr_to_reg (op4);
14563 : : }
14564 : 22 : emit_move_insn (gen_rtx_MEM (SImode, op4), op2);
14565 : : }
14566 : :
14567 : 102 : if (target == 0
14568 : 102 : || !register_operand (target, DImode))
14569 : 10 : target = gen_reg_rtx (DImode);
14570 : :
14571 : 102 : if (TARGET_64BIT)
14572 : : {
14573 : 100 : op1 = expand_simple_binop (DImode, ASHIFT, op1, GEN_INT (32),
14574 : : op1, 1, OPTAB_DIRECT);
14575 : 100 : op0 = expand_simple_binop (DImode, IOR, op0, op1,
14576 : : op0, 1, OPTAB_DIRECT);
14577 : : }
14578 : :
14579 : 102 : emit_move_insn (target, op0);
14580 : 102 : return target;
14581 : :
14582 : 61 : case IX86_BUILTIN_ENQCMD:
14583 : 61 : case IX86_BUILTIN_ENQCMDS:
14584 : 61 : case IX86_BUILTIN_MOVDIR64B:
14585 : :
14586 : 61 : arg0 = CALL_EXPR_ARG (exp, 0);
14587 : 61 : arg1 = CALL_EXPR_ARG (exp, 1);
14588 : 61 : op0 = expand_normal (arg0);
14589 : 61 : op1 = expand_normal (arg1);
14590 : :
14591 : 61 : op0 = ix86_zero_extend_to_Pmode (op0);
14592 : 61 : if (!address_operand (op1, VOIDmode))
14593 : : {
14594 : 28 : op1 = convert_memory_address (Pmode, op1);
14595 : 28 : op1 = copy_addr_to_reg (op1);
14596 : : }
14597 : 61 : op1 = gen_rtx_MEM (XImode, op1);
14598 : :
14599 : 61 : if (fcode == IX86_BUILTIN_MOVDIR64B)
14600 : : {
14601 : 24 : emit_insn (gen_movdir64b (Pmode, op0, op1));
14602 : 23 : return 0;
14603 : : }
14604 : : else
14605 : : {
14606 : 38 : if (target == 0
14607 : 38 : || !register_operand (target, SImode))
14608 : 0 : target = gen_reg_rtx (SImode);
14609 : :
14610 : 38 : emit_move_insn (target, const0_rtx);
14611 : 38 : target = gen_rtx_SUBREG (QImode, target, 0);
14612 : :
14613 : 19 : int unspecv = (fcode == IX86_BUILTIN_ENQCMD
14614 : 38 : ? UNSPECV_ENQCMD
14615 : : : UNSPECV_ENQCMDS);
14616 : 38 : icode = code_for_enqcmd (unspecv, Pmode);
14617 : 38 : emit_insn (GEN_FCN (icode) (op0, op1));
14618 : :
14619 : 38 : emit_insn
14620 : 38 : (gen_rtx_SET (gen_rtx_STRICT_LOW_PART (VOIDmode, target),
14621 : : gen_rtx_fmt_ee (EQ, QImode,
14622 : : gen_rtx_REG (CCZmode, FLAGS_REG),
14623 : : const0_rtx)));
14624 : 38 : return SUBREG_REG (target);
14625 : : }
14626 : :
14627 : 14775 : case IX86_BUILTIN_FXSAVE:
14628 : 14775 : case IX86_BUILTIN_FXRSTOR:
14629 : 14775 : case IX86_BUILTIN_FXSAVE64:
14630 : 14775 : case IX86_BUILTIN_FXRSTOR64:
14631 : 14775 : case IX86_BUILTIN_FNSTENV:
14632 : 14775 : case IX86_BUILTIN_FLDENV:
14633 : 14775 : mode0 = BLKmode;
14634 : 14775 : switch (fcode)
14635 : : {
14636 : : case IX86_BUILTIN_FXSAVE:
14637 : : icode = CODE_FOR_fxsave;
14638 : : break;
14639 : 19 : case IX86_BUILTIN_FXRSTOR:
14640 : 19 : icode = CODE_FOR_fxrstor;
14641 : 19 : break;
14642 : 23 : case IX86_BUILTIN_FXSAVE64:
14643 : 23 : icode = CODE_FOR_fxsave64;
14644 : 23 : break;
14645 : 21 : case IX86_BUILTIN_FXRSTOR64:
14646 : 21 : icode = CODE_FOR_fxrstor64;
14647 : 21 : break;
14648 : 7257 : case IX86_BUILTIN_FNSTENV:
14649 : 7257 : icode = CODE_FOR_fnstenv;
14650 : 7257 : break;
14651 : 7435 : case IX86_BUILTIN_FLDENV:
14652 : 7435 : icode = CODE_FOR_fldenv;
14653 : 7435 : break;
14654 : 0 : default:
14655 : 0 : gcc_unreachable ();
14656 : : }
14657 : :
14658 : 14775 : arg0 = CALL_EXPR_ARG (exp, 0);
14659 : 14775 : op0 = expand_normal (arg0);
14660 : :
14661 : 14775 : if (!address_operand (op0, VOIDmode))
14662 : : {
14663 : 36 : op0 = convert_memory_address (Pmode, op0);
14664 : 36 : op0 = copy_addr_to_reg (op0);
14665 : : }
14666 : 14775 : op0 = gen_rtx_MEM (mode0, op0);
14667 : :
14668 : 14775 : pat = GEN_FCN (icode) (op0);
14669 : 14775 : if (pat)
14670 : 14775 : emit_insn (pat);
14671 : : return 0;
14672 : :
14673 : 21 : case IX86_BUILTIN_XSETBV:
14674 : 21 : arg0 = CALL_EXPR_ARG (exp, 0);
14675 : 21 : arg1 = CALL_EXPR_ARG (exp, 1);
14676 : 21 : op0 = expand_normal (arg0);
14677 : 21 : op1 = expand_normal (arg1);
14678 : :
14679 : 21 : if (!REG_P (op0))
14680 : 1 : op0 = copy_to_mode_reg (SImode, op0);
14681 : :
14682 : 21 : op1 = force_reg (DImode, op1);
14683 : :
14684 : 21 : if (TARGET_64BIT)
14685 : : {
14686 : 21 : op2 = expand_simple_binop (DImode, LSHIFTRT, op1, GEN_INT (32),
14687 : : NULL, 1, OPTAB_DIRECT);
14688 : :
14689 : 21 : icode = CODE_FOR_xsetbv_rex64;
14690 : :
14691 : 21 : op2 = gen_lowpart (SImode, op2);
14692 : 21 : op1 = gen_lowpart (SImode, op1);
14693 : 21 : pat = GEN_FCN (icode) (op0, op1, op2);
14694 : : }
14695 : : else
14696 : : {
14697 : 0 : icode = CODE_FOR_xsetbv;
14698 : :
14699 : 0 : pat = GEN_FCN (icode) (op0, op1);
14700 : : }
14701 : 21 : if (pat)
14702 : 21 : emit_insn (pat);
14703 : : return 0;
14704 : :
14705 : 232 : case IX86_BUILTIN_XSAVE:
14706 : 232 : case IX86_BUILTIN_XRSTOR:
14707 : 232 : case IX86_BUILTIN_XSAVE64:
14708 : 232 : case IX86_BUILTIN_XRSTOR64:
14709 : 232 : case IX86_BUILTIN_XSAVEOPT:
14710 : 232 : case IX86_BUILTIN_XSAVEOPT64:
14711 : 232 : case IX86_BUILTIN_XSAVES:
14712 : 232 : case IX86_BUILTIN_XRSTORS:
14713 : 232 : case IX86_BUILTIN_XSAVES64:
14714 : 232 : case IX86_BUILTIN_XRSTORS64:
14715 : 232 : case IX86_BUILTIN_XSAVEC:
14716 : 232 : case IX86_BUILTIN_XSAVEC64:
14717 : 232 : arg0 = CALL_EXPR_ARG (exp, 0);
14718 : 232 : arg1 = CALL_EXPR_ARG (exp, 1);
14719 : 232 : op0 = expand_normal (arg0);
14720 : 232 : op1 = expand_normal (arg1);
14721 : :
14722 : 232 : if (!address_operand (op0, VOIDmode))
14723 : : {
14724 : 108 : op0 = convert_memory_address (Pmode, op0);
14725 : 108 : op0 = copy_addr_to_reg (op0);
14726 : : }
14727 : 232 : op0 = gen_rtx_MEM (BLKmode, op0);
14728 : :
14729 : 232 : op1 = force_reg (DImode, op1);
14730 : :
14731 : 232 : if (TARGET_64BIT)
14732 : : {
14733 : 232 : op2 = expand_simple_binop (DImode, LSHIFTRT, op1, GEN_INT (32),
14734 : : NULL, 1, OPTAB_DIRECT);
14735 : 232 : switch (fcode)
14736 : : {
14737 : : case IX86_BUILTIN_XSAVE:
14738 : : icode = CODE_FOR_xsave_rex64;
14739 : : break;
14740 : 19 : case IX86_BUILTIN_XRSTOR:
14741 : 19 : icode = CODE_FOR_xrstor_rex64;
14742 : 19 : break;
14743 : 21 : case IX86_BUILTIN_XSAVE64:
14744 : 21 : icode = CODE_FOR_xsave64;
14745 : 21 : break;
14746 : 21 : case IX86_BUILTIN_XRSTOR64:
14747 : 21 : icode = CODE_FOR_xrstor64;
14748 : 21 : break;
14749 : 19 : case IX86_BUILTIN_XSAVEOPT:
14750 : 19 : icode = CODE_FOR_xsaveopt_rex64;
14751 : 19 : break;
14752 : 19 : case IX86_BUILTIN_XSAVEOPT64:
14753 : 19 : icode = CODE_FOR_xsaveopt64;
14754 : 19 : break;
14755 : 19 : case IX86_BUILTIN_XSAVES:
14756 : 19 : icode = CODE_FOR_xsaves_rex64;
14757 : 19 : break;
14758 : 19 : case IX86_BUILTIN_XRSTORS:
14759 : 19 : icode = CODE_FOR_xrstors_rex64;
14760 : 19 : break;
14761 : 19 : case IX86_BUILTIN_XSAVES64:
14762 : 19 : icode = CODE_FOR_xsaves64;
14763 : 19 : break;
14764 : 19 : case IX86_BUILTIN_XRSTORS64:
14765 : 19 : icode = CODE_FOR_xrstors64;
14766 : 19 : break;
14767 : 19 : case IX86_BUILTIN_XSAVEC:
14768 : 19 : icode = CODE_FOR_xsavec_rex64;
14769 : 19 : break;
14770 : 19 : case IX86_BUILTIN_XSAVEC64:
14771 : 19 : icode = CODE_FOR_xsavec64;
14772 : 19 : break;
14773 : 0 : default:
14774 : 0 : gcc_unreachable ();
14775 : : }
14776 : :
14777 : 232 : op2 = gen_lowpart (SImode, op2);
14778 : 232 : op1 = gen_lowpart (SImode, op1);
14779 : 232 : pat = GEN_FCN (icode) (op0, op1, op2);
14780 : : }
14781 : : else
14782 : : {
14783 : 0 : switch (fcode)
14784 : : {
14785 : : case IX86_BUILTIN_XSAVE:
14786 : : icode = CODE_FOR_xsave;
14787 : : break;
14788 : : case IX86_BUILTIN_XRSTOR:
14789 : : icode = CODE_FOR_xrstor;
14790 : : break;
14791 : : case IX86_BUILTIN_XSAVEOPT:
14792 : : icode = CODE_FOR_xsaveopt;
14793 : : break;
14794 : : case IX86_BUILTIN_XSAVES:
14795 : : icode = CODE_FOR_xsaves;
14796 : : break;
14797 : : case IX86_BUILTIN_XRSTORS:
14798 : : icode = CODE_FOR_xrstors;
14799 : : break;
14800 : : case IX86_BUILTIN_XSAVEC:
14801 : : icode = CODE_FOR_xsavec;
14802 : : break;
14803 : 0 : default:
14804 : 0 : gcc_unreachable ();
14805 : : }
14806 : 0 : pat = GEN_FCN (icode) (op0, op1);
14807 : : }
14808 : :
14809 : 232 : if (pat)
14810 : 232 : emit_insn (pat);
14811 : : return 0;
14812 : :
14813 : 83 : case IX86_BUILTIN_LDTILECFG:
14814 : 83 : case IX86_BUILTIN_STTILECFG:
14815 : 83 : arg0 = CALL_EXPR_ARG (exp, 0);
14816 : 83 : op0 = expand_normal (arg0);
14817 : :
14818 : 83 : if (!address_operand (op0, VOIDmode))
14819 : : {
14820 : 8 : op0 = convert_memory_address (Pmode, op0);
14821 : 8 : op0 = copy_addr_to_reg (op0);
14822 : : }
14823 : 83 : op0 = gen_rtx_MEM (BLKmode, op0);
14824 : 83 : if (fcode == IX86_BUILTIN_LDTILECFG)
14825 : : icode = CODE_FOR_ldtilecfg;
14826 : : else
14827 : 52 : icode = CODE_FOR_sttilecfg;
14828 : 83 : pat = GEN_FCN (icode) (op0);
14829 : 83 : emit_insn (pat);
14830 : 83 : return 0;
14831 : :
14832 : 18 : case IX86_BUILTIN_LLWPCB:
14833 : 18 : arg0 = CALL_EXPR_ARG (exp, 0);
14834 : 18 : op0 = expand_normal (arg0);
14835 : :
14836 : 18 : if (!register_operand (op0, Pmode))
14837 : 9 : op0 = ix86_zero_extend_to_Pmode (op0);
14838 : 18 : emit_insn (gen_lwp_llwpcb (Pmode, op0));
14839 : 18 : return 0;
14840 : :
14841 : 18 : case IX86_BUILTIN_SLWPCB:
14842 : 18 : if (!target
14843 : 18 : || !register_operand (target, Pmode))
14844 : 0 : target = gen_reg_rtx (Pmode);
14845 : 18 : emit_insn (gen_lwp_slwpcb (Pmode, target));
14846 : 18 : return target;
14847 : :
14848 : 51 : case IX86_BUILTIN_LWPVAL32:
14849 : 51 : case IX86_BUILTIN_LWPVAL64:
14850 : 51 : case IX86_BUILTIN_LWPINS32:
14851 : 51 : case IX86_BUILTIN_LWPINS64:
14852 : 51 : mode = ((fcode == IX86_BUILTIN_LWPVAL32
14853 : 51 : || fcode == IX86_BUILTIN_LWPINS32)
14854 : 51 : ? SImode : DImode);
14855 : :
14856 : 51 : if (fcode == IX86_BUILTIN_LWPVAL32
14857 : 51 : || fcode == IX86_BUILTIN_LWPVAL64)
14858 : 26 : icode = code_for_lwp_lwpval (mode);
14859 : : else
14860 : 25 : icode = code_for_lwp_lwpins (mode);
14861 : :
14862 : 51 : arg0 = CALL_EXPR_ARG (exp, 0);
14863 : 51 : arg1 = CALL_EXPR_ARG (exp, 1);
14864 : 51 : arg2 = CALL_EXPR_ARG (exp, 2);
14865 : 51 : op0 = expand_normal (arg0);
14866 : 51 : op1 = expand_normal (arg1);
14867 : 51 : op2 = expand_normal (arg2);
14868 : 51 : mode0 = insn_data[icode].operand[0].mode;
14869 : :
14870 : 51 : if (!insn_data[icode].operand[0].predicate (op0, mode0))
14871 : 13 : op0 = copy_to_mode_reg (mode0, op0);
14872 : 51 : if (!insn_data[icode].operand[1].predicate (op1, SImode))
14873 : 0 : op1 = copy_to_mode_reg (SImode, op1);
14874 : :
14875 : 51 : if (!CONST_INT_P (op2))
14876 : : {
14877 : 0 : error ("the last argument must be a 32-bit immediate");
14878 : 0 : return const0_rtx;
14879 : : }
14880 : :
14881 : 51 : emit_insn (GEN_FCN (icode) (op0, op1, op2));
14882 : :
14883 : 51 : if (fcode == IX86_BUILTIN_LWPINS32
14884 : 51 : || fcode == IX86_BUILTIN_LWPINS64)
14885 : : {
14886 : 25 : if (target == 0
14887 : 25 : || !nonimmediate_operand (target, QImode))
14888 : 0 : target = gen_reg_rtx (QImode);
14889 : :
14890 : 25 : pat = gen_rtx_EQ (QImode, gen_rtx_REG (CCCmode, FLAGS_REG),
14891 : : const0_rtx);
14892 : 25 : emit_insn (gen_rtx_SET (target, pat));
14893 : :
14894 : 25 : return target;
14895 : : }
14896 : : else
14897 : : return 0;
14898 : :
14899 : 18 : case IX86_BUILTIN_BEXTRI32:
14900 : 18 : case IX86_BUILTIN_BEXTRI64:
14901 : 18 : mode = (fcode == IX86_BUILTIN_BEXTRI32 ? SImode : DImode);
14902 : :
14903 : 18 : arg0 = CALL_EXPR_ARG (exp, 0);
14904 : 18 : arg1 = CALL_EXPR_ARG (exp, 1);
14905 : 18 : op0 = expand_normal (arg0);
14906 : 18 : op1 = expand_normal (arg1);
14907 : :
14908 : 18 : if (!CONST_INT_P (op1))
14909 : : {
14910 : 0 : error ("last argument must be an immediate");
14911 : 0 : return const0_rtx;
14912 : : }
14913 : : else
14914 : : {
14915 : 18 : unsigned char lsb_index = UINTVAL (op1);
14916 : 18 : unsigned char length = UINTVAL (op1) >> 8;
14917 : :
14918 : 18 : unsigned char bitsize = GET_MODE_BITSIZE (mode);
14919 : :
14920 : 18 : icode = code_for_tbm_bextri (mode);
14921 : :
14922 : 18 : mode1 = insn_data[icode].operand[1].mode;
14923 : 18 : if (!insn_data[icode].operand[1].predicate (op0, mode1))
14924 : 12 : op0 = copy_to_mode_reg (mode1, op0);
14925 : :
14926 : 18 : mode0 = insn_data[icode].operand[0].mode;
14927 : 18 : if (target == 0
14928 : 18 : || !register_operand (target, mode0))
14929 : 0 : target = gen_reg_rtx (mode0);
14930 : :
14931 : 18 : if (length == 0 || lsb_index >= bitsize)
14932 : : {
14933 : 8 : emit_move_insn (target, const0_rtx);
14934 : 8 : return target;
14935 : : }
14936 : :
14937 : 10 : if (length + lsb_index > bitsize)
14938 : 5 : length = bitsize - lsb_index;
14939 : :
14940 : 10 : op1 = GEN_INT (length);
14941 : 10 : op2 = GEN_INT (lsb_index);
14942 : :
14943 : 10 : emit_insn (GEN_FCN (icode) (target, op0, op1, op2));
14944 : 10 : return target;
14945 : : }
14946 : :
14947 : 21 : case IX86_BUILTIN_RDRAND16_STEP:
14948 : 21 : mode = HImode;
14949 : 21 : goto rdrand_step;
14950 : :
14951 : 42 : case IX86_BUILTIN_RDRAND32_STEP:
14952 : 42 : mode = SImode;
14953 : 42 : goto rdrand_step;
14954 : :
14955 : : case IX86_BUILTIN_RDRAND64_STEP:
14956 : : mode = DImode;
14957 : :
14958 : 83 : rdrand_step:
14959 : 83 : arg0 = CALL_EXPR_ARG (exp, 0);
14960 : 83 : op1 = expand_normal (arg0);
14961 : 83 : if (!address_operand (op1, VOIDmode))
14962 : : {
14963 : 29 : op1 = convert_memory_address (Pmode, op1);
14964 : 29 : op1 = copy_addr_to_reg (op1);
14965 : : }
14966 : :
14967 : 83 : op0 = gen_reg_rtx (mode);
14968 : 83 : emit_insn (gen_rdrand (mode, op0));
14969 : :
14970 : 83 : emit_move_insn (gen_rtx_MEM (mode, op1), op0);
14971 : :
14972 : 83 : op1 = force_reg (SImode, const1_rtx);
14973 : :
14974 : : /* Emit SImode conditional move. */
14975 : 83 : if (mode == HImode)
14976 : : {
14977 : 21 : if (TARGET_ZERO_EXTEND_WITH_AND
14978 : 21 : && optimize_function_for_speed_p (cfun))
14979 : : {
14980 : 0 : op2 = force_reg (SImode, const0_rtx);
14981 : :
14982 : 0 : emit_insn (gen_movstricthi
14983 : 0 : (gen_lowpart (HImode, op2), op0));
14984 : : }
14985 : : else
14986 : : {
14987 : 21 : op2 = gen_reg_rtx (SImode);
14988 : :
14989 : 21 : emit_insn (gen_zero_extendhisi2 (op2, op0));
14990 : : }
14991 : : }
14992 : 62 : else if (mode == SImode)
14993 : : op2 = op0;
14994 : : else
14995 : 20 : op2 = gen_rtx_SUBREG (SImode, op0, 0);
14996 : :
14997 : 83 : if (target == 0
14998 : 83 : || !register_operand (target, SImode))
14999 : 7 : target = gen_reg_rtx (SImode);
15000 : :
15001 : 83 : pat = gen_rtx_GEU (VOIDmode, gen_rtx_REG (CCCmode, FLAGS_REG),
15002 : : const0_rtx);
15003 : 83 : emit_insn (gen_rtx_SET (target,
15004 : : gen_rtx_IF_THEN_ELSE (SImode, pat, op2, op1)));
15005 : 83 : return target;
15006 : :
15007 : 19 : case IX86_BUILTIN_RDSEED16_STEP:
15008 : 19 : mode = HImode;
15009 : 19 : goto rdseed_step;
15010 : :
15011 : 28 : case IX86_BUILTIN_RDSEED32_STEP:
15012 : 28 : mode = SImode;
15013 : 28 : goto rdseed_step;
15014 : :
15015 : : case IX86_BUILTIN_RDSEED64_STEP:
15016 : : mode = DImode;
15017 : :
15018 : 66 : rdseed_step:
15019 : 66 : arg0 = CALL_EXPR_ARG (exp, 0);
15020 : 66 : op1 = expand_normal (arg0);
15021 : 66 : if (!address_operand (op1, VOIDmode))
15022 : : {
15023 : 28 : op1 = convert_memory_address (Pmode, op1);
15024 : 28 : op1 = copy_addr_to_reg (op1);
15025 : : }
15026 : :
15027 : 66 : op0 = gen_reg_rtx (mode);
15028 : 66 : emit_insn (gen_rdseed (mode, op0));
15029 : :
15030 : 66 : emit_move_insn (gen_rtx_MEM (mode, op1), op0);
15031 : :
15032 : 66 : op2 = gen_reg_rtx (QImode);
15033 : :
15034 : 66 : pat = gen_rtx_LTU (QImode, gen_rtx_REG (CCCmode, FLAGS_REG),
15035 : : const0_rtx);
15036 : 66 : emit_insn (gen_rtx_SET (op2, pat));
15037 : :
15038 : 66 : if (target == 0
15039 : 66 : || !register_operand (target, SImode))
15040 : 1 : target = gen_reg_rtx (SImode);
15041 : :
15042 : 66 : emit_insn (gen_zero_extendqisi2 (target, op2));
15043 : 66 : return target;
15044 : :
15045 : 38 : case IX86_BUILTIN_SBB32:
15046 : 38 : icode = CODE_FOR_subborrowsi;
15047 : 38 : icode2 = CODE_FOR_subborrowsi_0;
15048 : 38 : mode0 = SImode;
15049 : 38 : mode1 = DImode;
15050 : 38 : mode2 = CCmode;
15051 : 38 : goto handlecarry;
15052 : :
15053 : 44 : case IX86_BUILTIN_SBB64:
15054 : 44 : icode = CODE_FOR_subborrowdi;
15055 : 44 : icode2 = CODE_FOR_subborrowdi_0;
15056 : 44 : mode0 = DImode;
15057 : 44 : mode1 = TImode;
15058 : 44 : mode2 = CCmode;
15059 : 44 : goto handlecarry;
15060 : :
15061 : 68 : case IX86_BUILTIN_ADDCARRYX32:
15062 : 68 : icode = CODE_FOR_addcarrysi;
15063 : 68 : icode2 = CODE_FOR_addcarrysi_0;
15064 : 68 : mode0 = SImode;
15065 : 68 : mode1 = DImode;
15066 : 68 : mode2 = CCCmode;
15067 : 68 : goto handlecarry;
15068 : :
15069 : : case IX86_BUILTIN_ADDCARRYX64:
15070 : : icode = CODE_FOR_addcarrydi;
15071 : : icode2 = CODE_FOR_addcarrydi_0;
15072 : : mode0 = DImode;
15073 : : mode1 = TImode;
15074 : : mode2 = CCCmode;
15075 : :
15076 : 212 : handlecarry:
15077 : 212 : arg0 = CALL_EXPR_ARG (exp, 0); /* unsigned char c_in. */
15078 : 212 : arg1 = CALL_EXPR_ARG (exp, 1); /* unsigned int src1. */
15079 : 212 : arg2 = CALL_EXPR_ARG (exp, 2); /* unsigned int src2. */
15080 : 212 : arg3 = CALL_EXPR_ARG (exp, 3); /* unsigned int *sum_out. */
15081 : :
15082 : 212 : op1 = expand_normal (arg0);
15083 : :
15084 : 212 : op2 = expand_normal (arg1);
15085 : 212 : if (!register_operand (op2, mode0))
15086 : 117 : op2 = copy_to_mode_reg (mode0, op2);
15087 : :
15088 : 212 : op3 = expand_normal (arg2);
15089 : 212 : if (!register_operand (op3, mode0))
15090 : 120 : op3 = copy_to_mode_reg (mode0, op3);
15091 : :
15092 : 212 : op4 = expand_normal (arg3);
15093 : 212 : if (!address_operand (op4, VOIDmode))
15094 : : {
15095 : 67 : op4 = convert_memory_address (Pmode, op4);
15096 : 67 : op4 = copy_addr_to_reg (op4);
15097 : : }
15098 : :
15099 : 212 : op0 = gen_reg_rtx (mode0);
15100 : 212 : if (op1 == const0_rtx)
15101 : : {
15102 : : /* If arg0 is 0, optimize right away into add or sub
15103 : : instruction that sets CCCmode flags. */
15104 : 21 : op1 = gen_rtx_REG (mode2, FLAGS_REG);
15105 : 21 : emit_insn (GEN_FCN (icode2) (op0, op2, op3));
15106 : : }
15107 : : else
15108 : : {
15109 : : /* Generate CF from input operand. */
15110 : 191 : ix86_expand_carry (op1);
15111 : :
15112 : : /* Generate instruction that consumes CF. */
15113 : 191 : op1 = gen_rtx_REG (CCCmode, FLAGS_REG);
15114 : 191 : pat = gen_rtx_LTU (mode1, op1, const0_rtx);
15115 : 191 : pat2 = gen_rtx_LTU (mode0, op1, const0_rtx);
15116 : 191 : emit_insn (GEN_FCN (icode) (op0, op2, op3, op1, pat, pat2));
15117 : : }
15118 : :
15119 : : /* Return current CF value. */
15120 : 212 : if (target == 0)
15121 : 14 : target = gen_reg_rtx (QImode);
15122 : :
15123 : 212 : pat = gen_rtx_LTU (QImode, op1, const0_rtx);
15124 : 212 : emit_insn (gen_rtx_SET (target, pat));
15125 : :
15126 : : /* Store the result. */
15127 : 212 : emit_move_insn (gen_rtx_MEM (mode0, op4), op0);
15128 : :
15129 : 212 : return target;
15130 : :
15131 : 24 : case IX86_BUILTIN_READ_FLAGS:
15132 : 24 : if (ignore)
15133 : 1 : return const0_rtx;
15134 : :
15135 : 23 : emit_insn (gen_pushfl ());
15136 : :
15137 : 23 : if (optimize
15138 : 11 : || target == NULL_RTX
15139 : 11 : || !nonimmediate_operand (target, word_mode)
15140 : 34 : || GET_MODE (target) != word_mode)
15141 : 12 : target = gen_reg_rtx (word_mode);
15142 : :
15143 : 23 : emit_insn (gen_pop (target));
15144 : 23 : return target;
15145 : :
15146 : 21 : case IX86_BUILTIN_WRITE_FLAGS:
15147 : :
15148 : 21 : arg0 = CALL_EXPR_ARG (exp, 0);
15149 : 21 : op0 = expand_normal (arg0);
15150 : 21 : if (!general_no_elim_operand (op0, word_mode))
15151 : 0 : op0 = copy_to_mode_reg (word_mode, op0);
15152 : :
15153 : 21 : emit_insn (gen_push (op0));
15154 : 21 : emit_insn (gen_popfl ());
15155 : 21 : return 0;
15156 : :
15157 : 22 : case IX86_BUILTIN_KTESTC8:
15158 : 22 : icode = CODE_FOR_ktestqi;
15159 : 22 : mode3 = CCCmode;
15160 : 22 : goto kortest;
15161 : :
15162 : 22 : case IX86_BUILTIN_KTESTZ8:
15163 : 22 : icode = CODE_FOR_ktestqi;
15164 : 22 : mode3 = CCZmode;
15165 : 22 : goto kortest;
15166 : :
15167 : 22 : case IX86_BUILTIN_KTESTC16:
15168 : 22 : icode = CODE_FOR_ktesthi;
15169 : 22 : mode3 = CCCmode;
15170 : 22 : goto kortest;
15171 : :
15172 : 22 : case IX86_BUILTIN_KTESTZ16:
15173 : 22 : icode = CODE_FOR_ktesthi;
15174 : 22 : mode3 = CCZmode;
15175 : 22 : goto kortest;
15176 : :
15177 : 22 : case IX86_BUILTIN_KTESTC32:
15178 : 22 : icode = CODE_FOR_ktestsi;
15179 : 22 : mode3 = CCCmode;
15180 : 22 : goto kortest;
15181 : :
15182 : 22 : case IX86_BUILTIN_KTESTZ32:
15183 : 22 : icode = CODE_FOR_ktestsi;
15184 : 22 : mode3 = CCZmode;
15185 : 22 : goto kortest;
15186 : :
15187 : 22 : case IX86_BUILTIN_KTESTC64:
15188 : 22 : icode = CODE_FOR_ktestdi;
15189 : 22 : mode3 = CCCmode;
15190 : 22 : goto kortest;
15191 : :
15192 : 22 : case IX86_BUILTIN_KTESTZ64:
15193 : 22 : icode = CODE_FOR_ktestdi;
15194 : 22 : mode3 = CCZmode;
15195 : 22 : goto kortest;
15196 : :
15197 : 22 : case IX86_BUILTIN_KORTESTC8:
15198 : 22 : icode = CODE_FOR_kortestqi;
15199 : 22 : mode3 = CCCmode;
15200 : 22 : goto kortest;
15201 : :
15202 : 76 : case IX86_BUILTIN_KORTESTZ8:
15203 : 76 : icode = CODE_FOR_kortestqi;
15204 : 76 : mode3 = CCZmode;
15205 : 76 : goto kortest;
15206 : :
15207 : 38 : case IX86_BUILTIN_KORTESTC16:
15208 : 38 : icode = CODE_FOR_kortesthi;
15209 : 38 : mode3 = CCCmode;
15210 : 38 : goto kortest;
15211 : :
15212 : 91 : case IX86_BUILTIN_KORTESTZ16:
15213 : 91 : icode = CODE_FOR_kortesthi;
15214 : 91 : mode3 = CCZmode;
15215 : 91 : goto kortest;
15216 : :
15217 : 22 : case IX86_BUILTIN_KORTESTC32:
15218 : 22 : icode = CODE_FOR_kortestsi;
15219 : 22 : mode3 = CCCmode;
15220 : 22 : goto kortest;
15221 : :
15222 : 79 : case IX86_BUILTIN_KORTESTZ32:
15223 : 79 : icode = CODE_FOR_kortestsi;
15224 : 79 : mode3 = CCZmode;
15225 : 79 : goto kortest;
15226 : :
15227 : 22 : case IX86_BUILTIN_KORTESTC64:
15228 : 22 : icode = CODE_FOR_kortestdi;
15229 : 22 : mode3 = CCCmode;
15230 : 22 : goto kortest;
15231 : :
15232 : : case IX86_BUILTIN_KORTESTZ64:
15233 : : icode = CODE_FOR_kortestdi;
15234 : : mode3 = CCZmode;
15235 : :
15236 : 610 : kortest:
15237 : 610 : arg0 = CALL_EXPR_ARG (exp, 0); /* Mask reg src1. */
15238 : 610 : arg1 = CALL_EXPR_ARG (exp, 1); /* Mask reg src2. */
15239 : 610 : op0 = expand_normal (arg0);
15240 : 610 : op1 = expand_normal (arg1);
15241 : :
15242 : 610 : mode0 = insn_data[icode].operand[0].mode;
15243 : 610 : mode1 = insn_data[icode].operand[1].mode;
15244 : :
15245 : 610 : if (GET_MODE (op0) != VOIDmode)
15246 : 610 : op0 = force_reg (GET_MODE (op0), op0);
15247 : :
15248 : 610 : op0 = gen_lowpart (mode0, op0);
15249 : :
15250 : 610 : if (!insn_data[icode].operand[0].predicate (op0, mode0))
15251 : 0 : op0 = copy_to_mode_reg (mode0, op0);
15252 : :
15253 : 610 : if (GET_MODE (op1) != VOIDmode)
15254 : 609 : op1 = force_reg (GET_MODE (op1), op1);
15255 : :
15256 : 610 : op1 = gen_lowpart (mode1, op1);
15257 : :
15258 : 610 : if (!insn_data[icode].operand[1].predicate (op1, mode1))
15259 : 1 : op1 = copy_to_mode_reg (mode1, op1);
15260 : :
15261 : 610 : target = gen_reg_rtx (QImode);
15262 : :
15263 : : /* Emit kortest. */
15264 : 610 : emit_insn (GEN_FCN (icode) (op0, op1));
15265 : : /* And use setcc to return result from flags. */
15266 : 610 : ix86_expand_setcc (target, EQ,
15267 : : gen_rtx_REG (mode3, FLAGS_REG), const0_rtx);
15268 : 610 : return target;
15269 : :
15270 : 24 : case IX86_BUILTIN_GATHERSIV2DF:
15271 : 24 : icode = CODE_FOR_avx2_gathersiv2df;
15272 : 24 : goto gather_gen;
15273 : 18 : case IX86_BUILTIN_GATHERSIV4DF:
15274 : 18 : icode = CODE_FOR_avx2_gathersiv4df;
15275 : 18 : goto gather_gen;
15276 : 21 : case IX86_BUILTIN_GATHERDIV2DF:
15277 : 21 : icode = CODE_FOR_avx2_gatherdiv2df;
15278 : 21 : goto gather_gen;
15279 : 32 : case IX86_BUILTIN_GATHERDIV4DF:
15280 : 32 : icode = CODE_FOR_avx2_gatherdiv4df;
15281 : 32 : goto gather_gen;
15282 : 29 : case IX86_BUILTIN_GATHERSIV4SF:
15283 : 29 : icode = CODE_FOR_avx2_gathersiv4sf;
15284 : 29 : goto gather_gen;
15285 : 36 : case IX86_BUILTIN_GATHERSIV8SF:
15286 : 36 : icode = CODE_FOR_avx2_gathersiv8sf;
15287 : 36 : goto gather_gen;
15288 : 24 : case IX86_BUILTIN_GATHERDIV4SF:
15289 : 24 : icode = CODE_FOR_avx2_gatherdiv4sf;
15290 : 24 : goto gather_gen;
15291 : 18 : case IX86_BUILTIN_GATHERDIV8SF:
15292 : 18 : icode = CODE_FOR_avx2_gatherdiv8sf;
15293 : 18 : goto gather_gen;
15294 : 18 : case IX86_BUILTIN_GATHERSIV2DI:
15295 : 18 : icode = CODE_FOR_avx2_gathersiv2di;
15296 : 18 : goto gather_gen;
15297 : 18 : case IX86_BUILTIN_GATHERSIV4DI:
15298 : 18 : icode = CODE_FOR_avx2_gathersiv4di;
15299 : 18 : goto gather_gen;
15300 : 27 : case IX86_BUILTIN_GATHERDIV2DI:
15301 : 27 : icode = CODE_FOR_avx2_gatherdiv2di;
15302 : 27 : goto gather_gen;
15303 : 29 : case IX86_BUILTIN_GATHERDIV4DI:
15304 : 29 : icode = CODE_FOR_avx2_gatherdiv4di;
15305 : 29 : goto gather_gen;
15306 : 20 : case IX86_BUILTIN_GATHERSIV4SI:
15307 : 20 : icode = CODE_FOR_avx2_gathersiv4si;
15308 : 20 : goto gather_gen;
15309 : 22 : case IX86_BUILTIN_GATHERSIV8SI:
15310 : 22 : icode = CODE_FOR_avx2_gathersiv8si;
15311 : 22 : goto gather_gen;
15312 : 28 : case IX86_BUILTIN_GATHERDIV4SI:
15313 : 28 : icode = CODE_FOR_avx2_gatherdiv4si;
15314 : 28 : goto gather_gen;
15315 : 18 : case IX86_BUILTIN_GATHERDIV8SI:
15316 : 18 : icode = CODE_FOR_avx2_gatherdiv8si;
15317 : 18 : goto gather_gen;
15318 : 20 : case IX86_BUILTIN_GATHERALTSIV4DF:
15319 : 20 : icode = CODE_FOR_avx2_gathersiv4df;
15320 : 20 : goto gather_gen;
15321 : 16 : case IX86_BUILTIN_GATHERALTDIV8SF:
15322 : 16 : icode = CODE_FOR_avx2_gatherdiv8sf;
15323 : 16 : goto gather_gen;
15324 : 4 : case IX86_BUILTIN_GATHERALTSIV4DI:
15325 : 4 : icode = CODE_FOR_avx2_gathersiv4di;
15326 : 4 : goto gather_gen;
15327 : 10 : case IX86_BUILTIN_GATHERALTDIV8SI:
15328 : 10 : icode = CODE_FOR_avx2_gatherdiv8si;
15329 : 10 : goto gather_gen;
15330 : 36 : case IX86_BUILTIN_GATHER3SIV16SF:
15331 : 36 : icode = CODE_FOR_avx512f_gathersiv16sf;
15332 : 36 : goto gather_gen;
15333 : 24 : case IX86_BUILTIN_GATHER3SIV8DF:
15334 : 24 : icode = CODE_FOR_avx512f_gathersiv8df;
15335 : 24 : goto gather_gen;
15336 : 24 : case IX86_BUILTIN_GATHER3DIV16SF:
15337 : 24 : icode = CODE_FOR_avx512f_gatherdiv16sf;
15338 : 24 : goto gather_gen;
15339 : 37 : case IX86_BUILTIN_GATHER3DIV8DF:
15340 : 37 : icode = CODE_FOR_avx512f_gatherdiv8df;
15341 : 37 : goto gather_gen;
15342 : 30 : case IX86_BUILTIN_GATHER3SIV16SI:
15343 : 30 : icode = CODE_FOR_avx512f_gathersiv16si;
15344 : 30 : goto gather_gen;
15345 : 24 : case IX86_BUILTIN_GATHER3SIV8DI:
15346 : 24 : icode = CODE_FOR_avx512f_gathersiv8di;
15347 : 24 : goto gather_gen;
15348 : 24 : case IX86_BUILTIN_GATHER3DIV16SI:
15349 : 24 : icode = CODE_FOR_avx512f_gatherdiv16si;
15350 : 24 : goto gather_gen;
15351 : 37 : case IX86_BUILTIN_GATHER3DIV8DI:
15352 : 37 : icode = CODE_FOR_avx512f_gatherdiv8di;
15353 : 37 : goto gather_gen;
15354 : 16 : case IX86_BUILTIN_GATHER3ALTSIV8DF:
15355 : 16 : icode = CODE_FOR_avx512f_gathersiv8df;
15356 : 16 : goto gather_gen;
15357 : 22 : case IX86_BUILTIN_GATHER3ALTDIV16SF:
15358 : 22 : icode = CODE_FOR_avx512f_gatherdiv16sf;
15359 : 22 : goto gather_gen;
15360 : 14 : case IX86_BUILTIN_GATHER3ALTSIV8DI:
15361 : 14 : icode = CODE_FOR_avx512f_gathersiv8di;
15362 : 14 : goto gather_gen;
15363 : 20 : case IX86_BUILTIN_GATHER3ALTDIV16SI:
15364 : 20 : icode = CODE_FOR_avx512f_gatherdiv16si;
15365 : 20 : goto gather_gen;
15366 : 18 : case IX86_BUILTIN_GATHER3SIV2DF:
15367 : 18 : icode = CODE_FOR_avx512vl_gathersiv2df;
15368 : 18 : goto gather_gen;
15369 : 10 : case IX86_BUILTIN_GATHER3SIV4DF:
15370 : 10 : icode = CODE_FOR_avx512vl_gathersiv4df;
15371 : 10 : goto gather_gen;
15372 : 15 : case IX86_BUILTIN_GATHER3DIV2DF:
15373 : 15 : icode = CODE_FOR_avx512vl_gatherdiv2df;
15374 : 15 : goto gather_gen;
15375 : 16 : case IX86_BUILTIN_GATHER3DIV4DF:
15376 : 16 : icode = CODE_FOR_avx512vl_gatherdiv4df;
15377 : 16 : goto gather_gen;
15378 : 14 : case IX86_BUILTIN_GATHER3SIV4SF:
15379 : 14 : icode = CODE_FOR_avx512vl_gathersiv4sf;
15380 : 14 : goto gather_gen;
15381 : 12 : case IX86_BUILTIN_GATHER3SIV8SF:
15382 : 12 : icode = CODE_FOR_avx512vl_gathersiv8sf;
15383 : 12 : goto gather_gen;
15384 : 22 : case IX86_BUILTIN_GATHER3DIV4SF:
15385 : 22 : icode = CODE_FOR_avx512vl_gatherdiv4sf;
15386 : 22 : goto gather_gen;
15387 : 10 : case IX86_BUILTIN_GATHER3DIV8SF:
15388 : 10 : icode = CODE_FOR_avx512vl_gatherdiv8sf;
15389 : 10 : goto gather_gen;
15390 : 20 : case IX86_BUILTIN_GATHER3SIV2DI:
15391 : 20 : icode = CODE_FOR_avx512vl_gathersiv2di;
15392 : 20 : goto gather_gen;
15393 : 10 : case IX86_BUILTIN_GATHER3SIV4DI:
15394 : 10 : icode = CODE_FOR_avx512vl_gathersiv4di;
15395 : 10 : goto gather_gen;
15396 : 14 : case IX86_BUILTIN_GATHER3DIV2DI:
15397 : 14 : icode = CODE_FOR_avx512vl_gatherdiv2di;
15398 : 14 : goto gather_gen;
15399 : 13 : case IX86_BUILTIN_GATHER3DIV4DI:
15400 : 13 : icode = CODE_FOR_avx512vl_gatherdiv4di;
15401 : 13 : goto gather_gen;
15402 : 14 : case IX86_BUILTIN_GATHER3SIV4SI:
15403 : 14 : icode = CODE_FOR_avx512vl_gathersiv4si;
15404 : 14 : goto gather_gen;
15405 : 12 : case IX86_BUILTIN_GATHER3SIV8SI:
15406 : 12 : icode = CODE_FOR_avx512vl_gathersiv8si;
15407 : 12 : goto gather_gen;
15408 : 24 : case IX86_BUILTIN_GATHER3DIV4SI:
15409 : 24 : icode = CODE_FOR_avx512vl_gatherdiv4si;
15410 : 24 : goto gather_gen;
15411 : 10 : case IX86_BUILTIN_GATHER3DIV8SI:
15412 : 10 : icode = CODE_FOR_avx512vl_gatherdiv8si;
15413 : 10 : goto gather_gen;
15414 : 4 : case IX86_BUILTIN_GATHER3ALTSIV4DF:
15415 : 4 : icode = CODE_FOR_avx512vl_gathersiv4df;
15416 : 4 : goto gather_gen;
15417 : 8 : case IX86_BUILTIN_GATHER3ALTDIV8SF:
15418 : 8 : icode = CODE_FOR_avx512vl_gatherdiv8sf;
15419 : 8 : goto gather_gen;
15420 : 6 : case IX86_BUILTIN_GATHER3ALTSIV4DI:
15421 : 6 : icode = CODE_FOR_avx512vl_gathersiv4di;
15422 : 6 : goto gather_gen;
15423 : 10 : case IX86_BUILTIN_GATHER3ALTDIV8SI:
15424 : 10 : icode = CODE_FOR_avx512vl_gatherdiv8si;
15425 : 10 : goto gather_gen;
15426 : 40 : case IX86_BUILTIN_SCATTERSIV16SF:
15427 : 40 : icode = CODE_FOR_avx512f_scattersiv16sf;
15428 : 40 : goto scatter_gen;
15429 : 27 : case IX86_BUILTIN_SCATTERSIV8DF:
15430 : 27 : icode = CODE_FOR_avx512f_scattersiv8df;
15431 : 27 : goto scatter_gen;
15432 : 24 : case IX86_BUILTIN_SCATTERDIV16SF:
15433 : 24 : icode = CODE_FOR_avx512f_scatterdiv16sf;
15434 : 24 : goto scatter_gen;
15435 : 41 : case IX86_BUILTIN_SCATTERDIV8DF:
15436 : 41 : icode = CODE_FOR_avx512f_scatterdiv8df;
15437 : 41 : goto scatter_gen;
15438 : 30 : case IX86_BUILTIN_SCATTERSIV16SI:
15439 : 30 : icode = CODE_FOR_avx512f_scattersiv16si;
15440 : 30 : goto scatter_gen;
15441 : 24 : case IX86_BUILTIN_SCATTERSIV8DI:
15442 : 24 : icode = CODE_FOR_avx512f_scattersiv8di;
15443 : 24 : goto scatter_gen;
15444 : 24 : case IX86_BUILTIN_SCATTERDIV16SI:
15445 : 24 : icode = CODE_FOR_avx512f_scatterdiv16si;
15446 : 24 : goto scatter_gen;
15447 : 29 : case IX86_BUILTIN_SCATTERDIV8DI:
15448 : 29 : icode = CODE_FOR_avx512f_scatterdiv8di;
15449 : 29 : goto scatter_gen;
15450 : 18 : case IX86_BUILTIN_SCATTERSIV8SF:
15451 : 18 : icode = CODE_FOR_avx512vl_scattersiv8sf;
15452 : 18 : goto scatter_gen;
15453 : 20 : case IX86_BUILTIN_SCATTERSIV4SF:
15454 : 20 : icode = CODE_FOR_avx512vl_scattersiv4sf;
15455 : 20 : goto scatter_gen;
15456 : 16 : case IX86_BUILTIN_SCATTERSIV4DF:
15457 : 16 : icode = CODE_FOR_avx512vl_scattersiv4df;
15458 : 16 : goto scatter_gen;
15459 : 16 : case IX86_BUILTIN_SCATTERSIV2DF:
15460 : 16 : icode = CODE_FOR_avx512vl_scattersiv2df;
15461 : 16 : goto scatter_gen;
15462 : 16 : case IX86_BUILTIN_SCATTERDIV8SF:
15463 : 16 : icode = CODE_FOR_avx512vl_scatterdiv8sf;
15464 : 16 : goto scatter_gen;
15465 : 16 : case IX86_BUILTIN_SCATTERDIV4SF:
15466 : 16 : icode = CODE_FOR_avx512vl_scatterdiv4sf;
15467 : 16 : goto scatter_gen;
15468 : 18 : case IX86_BUILTIN_SCATTERDIV4DF:
15469 : 18 : icode = CODE_FOR_avx512vl_scatterdiv4df;
15470 : 18 : goto scatter_gen;
15471 : 18 : case IX86_BUILTIN_SCATTERDIV2DF:
15472 : 18 : icode = CODE_FOR_avx512vl_scatterdiv2df;
15473 : 18 : goto scatter_gen;
15474 : 22 : case IX86_BUILTIN_SCATTERSIV8SI:
15475 : 22 : icode = CODE_FOR_avx512vl_scattersiv8si;
15476 : 22 : goto scatter_gen;
15477 : 24 : case IX86_BUILTIN_SCATTERSIV4SI:
15478 : 24 : icode = CODE_FOR_avx512vl_scattersiv4si;
15479 : 24 : goto scatter_gen;
15480 : 16 : case IX86_BUILTIN_SCATTERSIV4DI:
15481 : 16 : icode = CODE_FOR_avx512vl_scattersiv4di;
15482 : 16 : goto scatter_gen;
15483 : 16 : case IX86_BUILTIN_SCATTERSIV2DI:
15484 : 16 : icode = CODE_FOR_avx512vl_scattersiv2di;
15485 : 16 : goto scatter_gen;
15486 : 16 : case IX86_BUILTIN_SCATTERDIV8SI:
15487 : 16 : icode = CODE_FOR_avx512vl_scatterdiv8si;
15488 : 16 : goto scatter_gen;
15489 : 16 : case IX86_BUILTIN_SCATTERDIV4SI:
15490 : 16 : icode = CODE_FOR_avx512vl_scatterdiv4si;
15491 : 16 : goto scatter_gen;
15492 : 18 : case IX86_BUILTIN_SCATTERDIV4DI:
15493 : 18 : icode = CODE_FOR_avx512vl_scatterdiv4di;
15494 : 18 : goto scatter_gen;
15495 : 18 : case IX86_BUILTIN_SCATTERDIV2DI:
15496 : 18 : icode = CODE_FOR_avx512vl_scatterdiv2di;
15497 : 18 : goto scatter_gen;
15498 : 16 : case IX86_BUILTIN_SCATTERALTSIV8DF:
15499 : 16 : icode = CODE_FOR_avx512f_scattersiv8df;
15500 : 16 : goto scatter_gen;
15501 : 12 : case IX86_BUILTIN_SCATTERALTDIV16SF:
15502 : 12 : icode = CODE_FOR_avx512f_scatterdiv16sf;
15503 : 12 : goto scatter_gen;
15504 : 8 : case IX86_BUILTIN_SCATTERALTSIV8DI:
15505 : 8 : icode = CODE_FOR_avx512f_scattersiv8di;
15506 : 8 : goto scatter_gen;
15507 : 24 : case IX86_BUILTIN_SCATTERALTDIV16SI:
15508 : 24 : icode = CODE_FOR_avx512f_scatterdiv16si;
15509 : 24 : goto scatter_gen;
15510 : 4 : case IX86_BUILTIN_SCATTERALTSIV4DF:
15511 : 4 : icode = CODE_FOR_avx512vl_scattersiv4df;
15512 : 4 : goto scatter_gen;
15513 : 4 : case IX86_BUILTIN_SCATTERALTDIV8SF:
15514 : 4 : icode = CODE_FOR_avx512vl_scatterdiv8sf;
15515 : 4 : goto scatter_gen;
15516 : 4 : case IX86_BUILTIN_SCATTERALTSIV4DI:
15517 : 4 : icode = CODE_FOR_avx512vl_scattersiv4di;
15518 : 4 : goto scatter_gen;
15519 : 4 : case IX86_BUILTIN_SCATTERALTDIV8SI:
15520 : 4 : icode = CODE_FOR_avx512vl_scatterdiv8si;
15521 : 4 : goto scatter_gen;
15522 : 8 : case IX86_BUILTIN_SCATTERALTSIV2DF:
15523 : 8 : icode = CODE_FOR_avx512vl_scattersiv2df;
15524 : 8 : goto scatter_gen;
15525 : 8 : case IX86_BUILTIN_SCATTERALTDIV4SF:
15526 : 8 : icode = CODE_FOR_avx512vl_scatterdiv4sf;
15527 : 8 : goto scatter_gen;
15528 : 8 : case IX86_BUILTIN_SCATTERALTSIV2DI:
15529 : 8 : icode = CODE_FOR_avx512vl_scattersiv2di;
15530 : 8 : goto scatter_gen;
15531 : 8 : case IX86_BUILTIN_SCATTERALTDIV4SI:
15532 : 8 : icode = CODE_FOR_avx512vl_scatterdiv4si;
15533 : 8 : goto scatter_gen;
15534 : :
15535 : 1002 : gather_gen:
15536 : 1002 : rtx half;
15537 : 1002 : rtx (*gen) (rtx, rtx);
15538 : :
15539 : 1002 : arg0 = CALL_EXPR_ARG (exp, 0);
15540 : 1002 : arg1 = CALL_EXPR_ARG (exp, 1);
15541 : 1002 : arg2 = CALL_EXPR_ARG (exp, 2);
15542 : 1002 : arg3 = CALL_EXPR_ARG (exp, 3);
15543 : 1002 : arg4 = CALL_EXPR_ARG (exp, 4);
15544 : 1002 : op0 = expand_normal (arg0);
15545 : 1002 : op1 = expand_normal (arg1);
15546 : 1002 : op2 = expand_normal (arg2);
15547 : 1002 : op3 = ix86_expand_unsigned_small_int_cst_argument (arg3);
15548 : 1002 : op4 = expand_normal (arg4);
15549 : : /* Note the arg order is different from the operand order. */
15550 : 1002 : mode0 = insn_data[icode].operand[1].mode;
15551 : 1002 : mode2 = insn_data[icode].operand[3].mode;
15552 : 1002 : mode3 = insn_data[icode].operand[4].mode;
15553 : 1002 : mode4 = insn_data[icode].operand[5].mode;
15554 : :
15555 : 1002 : if (target == NULL_RTX
15556 : 1002 : || GET_MODE (target) != insn_data[icode].operand[0].mode
15557 : 1900 : || !insn_data[icode].operand[0].predicate (target,
15558 : : GET_MODE (target)))
15559 : 105 : subtarget = gen_reg_rtx (insn_data[icode].operand[0].mode);
15560 : : else
15561 : : subtarget = target;
15562 : :
15563 : 1002 : switch (fcode)
15564 : : {
15565 : 30 : case IX86_BUILTIN_GATHER3ALTSIV8DF:
15566 : 30 : case IX86_BUILTIN_GATHER3ALTSIV8DI:
15567 : 30 : half = gen_reg_rtx (V8SImode);
15568 : 30 : if (!nonimmediate_operand (op2, V16SImode))
15569 : 0 : op2 = copy_to_mode_reg (V16SImode, op2);
15570 : 30 : emit_insn (gen_vec_extract_lo_v16si (half, op2));
15571 : 30 : op2 = half;
15572 : 30 : break;
15573 : 34 : case IX86_BUILTIN_GATHER3ALTSIV4DF:
15574 : 34 : case IX86_BUILTIN_GATHER3ALTSIV4DI:
15575 : 34 : case IX86_BUILTIN_GATHERALTSIV4DF:
15576 : 34 : case IX86_BUILTIN_GATHERALTSIV4DI:
15577 : 34 : half = gen_reg_rtx (V4SImode);
15578 : 34 : if (!nonimmediate_operand (op2, V8SImode))
15579 : 0 : op2 = copy_to_mode_reg (V8SImode, op2);
15580 : 34 : emit_insn (gen_vec_extract_lo_v8si (half, op2));
15581 : 34 : op2 = half;
15582 : 34 : break;
15583 : 42 : case IX86_BUILTIN_GATHER3ALTDIV16SF:
15584 : 42 : case IX86_BUILTIN_GATHER3ALTDIV16SI:
15585 : 42 : half = gen_reg_rtx (mode0);
15586 : 42 : if (mode0 == V8SFmode)
15587 : : gen = gen_vec_extract_lo_v16sf;
15588 : : else
15589 : 20 : gen = gen_vec_extract_lo_v16si;
15590 : 42 : if (!nonimmediate_operand (op0, GET_MODE (op0)))
15591 : 42 : op0 = copy_to_mode_reg (GET_MODE (op0), op0);
15592 : 42 : emit_insn (gen (half, op0));
15593 : 42 : op0 = half;
15594 : 42 : op3 = lowpart_subreg (QImode, op3, HImode);
15595 : 42 : break;
15596 : 44 : case IX86_BUILTIN_GATHER3ALTDIV8SF:
15597 : 44 : case IX86_BUILTIN_GATHER3ALTDIV8SI:
15598 : 44 : case IX86_BUILTIN_GATHERALTDIV8SF:
15599 : 44 : case IX86_BUILTIN_GATHERALTDIV8SI:
15600 : 44 : half = gen_reg_rtx (mode0);
15601 : 44 : if (mode0 == V4SFmode)
15602 : : gen = gen_vec_extract_lo_v8sf;
15603 : : else
15604 : 20 : gen = gen_vec_extract_lo_v8si;
15605 : 44 : if (!nonimmediate_operand (op0, GET_MODE (op0)))
15606 : 44 : op0 = copy_to_mode_reg (GET_MODE (op0), op0);
15607 : 44 : emit_insn (gen (half, op0));
15608 : 44 : op0 = half;
15609 : 44 : if (VECTOR_MODE_P (GET_MODE (op3)))
15610 : : {
15611 : 26 : half = gen_reg_rtx (mode0);
15612 : 26 : if (!nonimmediate_operand (op3, GET_MODE (op3)))
15613 : 12 : op3 = copy_to_mode_reg (GET_MODE (op3), op3);
15614 : 26 : emit_insn (gen (half, op3));
15615 : 26 : op3 = half;
15616 : : }
15617 : : break;
15618 : : default:
15619 : : break;
15620 : : }
15621 : :
15622 : : /* Force memory operand only with base register here. But we
15623 : : don't want to do it on memory operand for other builtin
15624 : : functions. */
15625 : 1002 : op1 = ix86_zero_extend_to_Pmode (op1);
15626 : :
15627 : 1002 : if (!insn_data[icode].operand[1].predicate (op0, mode0))
15628 : 401 : op0 = copy_to_mode_reg (mode0, op0);
15629 : 1007 : if (!insn_data[icode].operand[2].predicate (op1, Pmode))
15630 : 0 : op1 = copy_to_mode_reg (Pmode, op1);
15631 : 1002 : if (!insn_data[icode].operand[3].predicate (op2, mode2))
15632 : 221 : op2 = copy_to_mode_reg (mode2, op2);
15633 : :
15634 : 1002 : op3 = fixup_modeless_constant (op3, mode3);
15635 : :
15636 : 1002 : if (GET_MODE (op3) == mode3 || GET_MODE (op3) == VOIDmode)
15637 : : {
15638 : 1002 : if (!insn_data[icode].operand[4].predicate (op3, mode3))
15639 : 354 : op3 = copy_to_mode_reg (mode3, op3);
15640 : : }
15641 : : else
15642 : : {
15643 : 0 : op3 = copy_to_reg (op3);
15644 : 0 : op3 = lowpart_subreg (mode3, op3, GET_MODE (op3));
15645 : : }
15646 : 1002 : if (!insn_data[icode].operand[5].predicate (op4, mode4))
15647 : : {
15648 : 0 : error ("the last argument must be scale 1, 2, 4, 8");
15649 : 0 : return const0_rtx;
15650 : : }
15651 : :
15652 : : /* Optimize. If mask is known to have all high bits set,
15653 : : replace op0 with pc_rtx to signal that the instruction
15654 : : overwrites the whole destination and doesn't use its
15655 : : previous contents. */
15656 : 1002 : if (optimize)
15657 : : {
15658 : 912 : if (TREE_CODE (arg3) == INTEGER_CST)
15659 : : {
15660 : 209 : if (integer_all_onesp (arg3))
15661 : 201 : op0 = pc_rtx;
15662 : : }
15663 : 703 : else if (TREE_CODE (arg3) == VECTOR_CST)
15664 : : {
15665 : : unsigned int negative = 0;
15666 : 741 : for (i = 0; i < VECTOR_CST_NELTS (arg3); ++i)
15667 : : {
15668 : 608 : tree cst = VECTOR_CST_ELT (arg3, i);
15669 : 608 : if (TREE_CODE (cst) == INTEGER_CST
15670 : 608 : && tree_int_cst_sign_bit (cst))
15671 : 286 : negative++;
15672 : 322 : else if (TREE_CODE (cst) == REAL_CST
15673 : 322 : && REAL_VALUE_NEGATIVE (TREE_REAL_CST (cst)))
15674 : 294 : negative++;
15675 : : }
15676 : 133 : if (negative == TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg3)))
15677 : 119 : op0 = pc_rtx;
15678 : : }
15679 : 570 : else if (TREE_CODE (arg3) == SSA_NAME
15680 : 570 : && VECTOR_TYPE_P (TREE_TYPE (arg3)))
15681 : : {
15682 : : /* Recognize also when mask is like:
15683 : : __v2df src = _mm_setzero_pd ();
15684 : : __v2df mask = _mm_cmpeq_pd (src, src);
15685 : : or
15686 : : __v8sf src = _mm256_setzero_ps ();
15687 : : __v8sf mask = _mm256_cmp_ps (src, src, _CMP_EQ_OQ);
15688 : : as that is a cheaper way to load all ones into
15689 : : a register than having to load a constant from
15690 : : memory. */
15691 : 257 : gimple *def_stmt = SSA_NAME_DEF_STMT (arg3);
15692 : 257 : if (is_gimple_call (def_stmt))
15693 : : {
15694 : 76 : tree fndecl = gimple_call_fndecl (def_stmt);
15695 : 76 : if (fndecl
15696 : 76 : && fndecl_built_in_p (fndecl, BUILT_IN_MD))
15697 : 67 : switch (DECL_MD_FUNCTION_CODE (fndecl))
15698 : : {
15699 : 24 : case IX86_BUILTIN_CMPPD:
15700 : 24 : case IX86_BUILTIN_CMPPS:
15701 : 24 : case IX86_BUILTIN_CMPPD256:
15702 : 24 : case IX86_BUILTIN_CMPPS256:
15703 : 24 : if (!integer_zerop (gimple_call_arg (def_stmt, 2)))
15704 : : break;
15705 : : /* FALLTHRU */
15706 : 49 : case IX86_BUILTIN_CMPEQPD:
15707 : 49 : case IX86_BUILTIN_CMPEQPS:
15708 : 49 : if (initializer_zerop (gimple_call_arg (def_stmt, 0))
15709 : 49 : && initializer_zerop (gimple_call_arg (def_stmt,
15710 : : 1)))
15711 : 49 : op0 = pc_rtx;
15712 : : break;
15713 : : default:
15714 : : break;
15715 : : }
15716 : : }
15717 : : }
15718 : : }
15719 : :
15720 : 1002 : pat = GEN_FCN (icode) (subtarget, op0, op1, op2, op3, op4);
15721 : 1002 : if (! pat)
15722 : 0 : return const0_rtx;
15723 : 1002 : emit_insn (pat);
15724 : :
15725 : 1002 : switch (fcode)
15726 : : {
15727 : 24 : case IX86_BUILTIN_GATHER3DIV16SF:
15728 : 24 : if (target == NULL_RTX)
15729 : 0 : target = gen_reg_rtx (V8SFmode);
15730 : 24 : emit_insn (gen_vec_extract_lo_v16sf (target, subtarget));
15731 : 24 : break;
15732 : 24 : case IX86_BUILTIN_GATHER3DIV16SI:
15733 : 24 : if (target == NULL_RTX)
15734 : 0 : target = gen_reg_rtx (V8SImode);
15735 : 24 : emit_insn (gen_vec_extract_lo_v16si (target, subtarget));
15736 : 24 : break;
15737 : 28 : case IX86_BUILTIN_GATHER3DIV8SF:
15738 : 28 : case IX86_BUILTIN_GATHERDIV8SF:
15739 : 28 : if (target == NULL_RTX)
15740 : 0 : target = gen_reg_rtx (V4SFmode);
15741 : 28 : emit_insn (gen_vec_extract_lo_v8sf (target, subtarget));
15742 : 28 : break;
15743 : 28 : case IX86_BUILTIN_GATHER3DIV8SI:
15744 : 28 : case IX86_BUILTIN_GATHERDIV8SI:
15745 : 28 : if (target == NULL_RTX)
15746 : 0 : target = gen_reg_rtx (V4SImode);
15747 : 28 : emit_insn (gen_vec_extract_lo_v8si (target, subtarget));
15748 : 28 : break;
15749 : : default:
15750 : : target = subtarget;
15751 : : break;
15752 : : }
15753 : : return target;
15754 : :
15755 : 631 : scatter_gen:
15756 : 631 : arg0 = CALL_EXPR_ARG (exp, 0);
15757 : 631 : arg1 = CALL_EXPR_ARG (exp, 1);
15758 : 631 : arg2 = CALL_EXPR_ARG (exp, 2);
15759 : 631 : arg3 = CALL_EXPR_ARG (exp, 3);
15760 : 631 : arg4 = CALL_EXPR_ARG (exp, 4);
15761 : 631 : op0 = expand_normal (arg0);
15762 : 631 : op1 = ix86_expand_unsigned_small_int_cst_argument (arg1);
15763 : 631 : op2 = expand_normal (arg2);
15764 : 631 : op3 = expand_normal (arg3);
15765 : 631 : op4 = expand_normal (arg4);
15766 : 631 : mode1 = insn_data[icode].operand[1].mode;
15767 : 631 : mode2 = insn_data[icode].operand[2].mode;
15768 : 631 : mode3 = insn_data[icode].operand[3].mode;
15769 : 631 : mode4 = insn_data[icode].operand[4].mode;
15770 : :
15771 : : /* Scatter instruction stores operand op3 to memory with
15772 : : indices from op2 and scale from op4 under writemask op1.
15773 : : If index operand op2 has more elements then source operand
15774 : : op3 one need to use only its low half. And vice versa. */
15775 : 631 : switch (fcode)
15776 : : {
15777 : 24 : case IX86_BUILTIN_SCATTERALTSIV8DF:
15778 : 24 : case IX86_BUILTIN_SCATTERALTSIV8DI:
15779 : 24 : half = gen_reg_rtx (V8SImode);
15780 : 24 : if (!nonimmediate_operand (op2, V16SImode))
15781 : 0 : op2 = copy_to_mode_reg (V16SImode, op2);
15782 : 24 : emit_insn (gen_vec_extract_lo_v16si (half, op2));
15783 : 24 : op2 = half;
15784 : 24 : break;
15785 : 36 : case IX86_BUILTIN_SCATTERALTDIV16SF:
15786 : 36 : case IX86_BUILTIN_SCATTERALTDIV16SI:
15787 : 36 : half = gen_reg_rtx (mode3);
15788 : 36 : if (mode3 == V8SFmode)
15789 : : gen = gen_vec_extract_lo_v16sf;
15790 : : else
15791 : 24 : gen = gen_vec_extract_lo_v16si;
15792 : 36 : if (!nonimmediate_operand (op3, GET_MODE (op3)))
15793 : 0 : op3 = copy_to_mode_reg (GET_MODE (op3), op3);
15794 : 36 : emit_insn (gen (half, op3));
15795 : 36 : op3 = half;
15796 : 36 : break;
15797 : 8 : case IX86_BUILTIN_SCATTERALTSIV4DF:
15798 : 8 : case IX86_BUILTIN_SCATTERALTSIV4DI:
15799 : 8 : half = gen_reg_rtx (V4SImode);
15800 : 8 : if (!nonimmediate_operand (op2, V8SImode))
15801 : 0 : op2 = copy_to_mode_reg (V8SImode, op2);
15802 : 8 : emit_insn (gen_vec_extract_lo_v8si (half, op2));
15803 : 8 : op2 = half;
15804 : 8 : break;
15805 : 8 : case IX86_BUILTIN_SCATTERALTDIV8SF:
15806 : 8 : case IX86_BUILTIN_SCATTERALTDIV8SI:
15807 : 8 : half = gen_reg_rtx (mode3);
15808 : 8 : if (mode3 == V4SFmode)
15809 : : gen = gen_vec_extract_lo_v8sf;
15810 : : else
15811 : 4 : gen = gen_vec_extract_lo_v8si;
15812 : 8 : if (!nonimmediate_operand (op3, GET_MODE (op3)))
15813 : 0 : op3 = copy_to_mode_reg (GET_MODE (op3), op3);
15814 : 8 : emit_insn (gen (half, op3));
15815 : 8 : op3 = half;
15816 : 8 : break;
15817 : 16 : case IX86_BUILTIN_SCATTERALTSIV2DF:
15818 : 16 : case IX86_BUILTIN_SCATTERALTSIV2DI:
15819 : 16 : if (!nonimmediate_operand (op2, V4SImode))
15820 : 0 : op2 = copy_to_mode_reg (V4SImode, op2);
15821 : : break;
15822 : 16 : case IX86_BUILTIN_SCATTERALTDIV4SF:
15823 : 16 : case IX86_BUILTIN_SCATTERALTDIV4SI:
15824 : 16 : if (!nonimmediate_operand (op3, GET_MODE (op3)))
15825 : 0 : op3 = copy_to_mode_reg (GET_MODE (op3), op3);
15826 : : break;
15827 : : default:
15828 : : break;
15829 : : }
15830 : :
15831 : : /* Force memory operand only with base register here. But we
15832 : : don't want to do it on memory operand for other builtin
15833 : : functions. */
15834 : 641 : op0 = force_reg (Pmode, convert_to_mode (Pmode, op0, 1));
15835 : :
15836 : 636 : if (!insn_data[icode].operand[0].predicate (op0, Pmode))
15837 : 0 : op0 = copy_to_mode_reg (Pmode, op0);
15838 : :
15839 : 631 : op1 = fixup_modeless_constant (op1, mode1);
15840 : :
15841 : 631 : if (GET_MODE (op1) == mode1 || GET_MODE (op1) == VOIDmode)
15842 : : {
15843 : 615 : if (!insn_data[icode].operand[1].predicate (op1, mode1))
15844 : 281 : op1 = copy_to_mode_reg (mode1, op1);
15845 : : }
15846 : : else
15847 : : {
15848 : 16 : op1 = copy_to_reg (op1);
15849 : 16 : op1 = lowpart_subreg (mode1, op1, GET_MODE (op1));
15850 : : }
15851 : :
15852 : 631 : if (!insn_data[icode].operand[2].predicate (op2, mode2))
15853 : 57 : op2 = copy_to_mode_reg (mode2, op2);
15854 : :
15855 : 631 : if (!insn_data[icode].operand[3].predicate (op3, mode3))
15856 : 90 : op3 = copy_to_mode_reg (mode3, op3);
15857 : :
15858 : 631 : if (!insn_data[icode].operand[4].predicate (op4, mode4))
15859 : : {
15860 : 0 : error ("the last argument must be scale 1, 2, 4, 8");
15861 : 0 : return const0_rtx;
15862 : : }
15863 : :
15864 : 631 : pat = GEN_FCN (icode) (op0, op1, op2, op3, op4);
15865 : 631 : if (! pat)
15866 : 0 : return const0_rtx;
15867 : :
15868 : 631 : emit_insn (pat);
15869 : 631 : return 0;
15870 : :
15871 : 23 : case IX86_BUILTIN_XABORT:
15872 : 23 : icode = CODE_FOR_xabort;
15873 : 23 : arg0 = CALL_EXPR_ARG (exp, 0);
15874 : 23 : op0 = expand_normal (arg0);
15875 : 23 : mode0 = insn_data[icode].operand[0].mode;
15876 : 23 : if (!insn_data[icode].operand[0].predicate (op0, mode0))
15877 : : {
15878 : 0 : error ("the argument to %<xabort%> intrinsic must "
15879 : : "be an 8-bit immediate");
15880 : 0 : return const0_rtx;
15881 : : }
15882 : 23 : emit_insn (gen_xabort (op0));
15883 : 23 : return 0;
15884 : :
15885 : 55 : case IX86_BUILTIN_RDSSPD:
15886 : 55 : case IX86_BUILTIN_RDSSPQ:
15887 : 55 : mode = (fcode == IX86_BUILTIN_RDSSPD ? SImode : DImode);
15888 : :
15889 : 55 : if (target == 0
15890 : 55 : || !register_operand (target, mode))
15891 : 0 : target = gen_reg_rtx (mode);
15892 : :
15893 : 55 : op0 = force_reg (mode, const0_rtx);
15894 : :
15895 : 55 : emit_insn (gen_rdssp (mode, target, op0));
15896 : 55 : return target;
15897 : :
15898 : 55 : case IX86_BUILTIN_INCSSPD:
15899 : 55 : case IX86_BUILTIN_INCSSPQ:
15900 : 55 : mode = (fcode == IX86_BUILTIN_INCSSPD ? SImode : DImode);
15901 : :
15902 : 55 : arg0 = CALL_EXPR_ARG (exp, 0);
15903 : 55 : op0 = expand_normal (arg0);
15904 : :
15905 : 55 : op0 = force_reg (mode, op0);
15906 : :
15907 : 55 : emit_insn (gen_incssp (mode, op0));
15908 : 55 : return 0;
15909 : :
15910 : 20 : case IX86_BUILTIN_HRESET:
15911 : 20 : icode = CODE_FOR_hreset;
15912 : 20 : arg0 = CALL_EXPR_ARG (exp, 0);
15913 : 20 : op0 = expand_normal (arg0);
15914 : 20 : op0 = force_reg (SImode, op0);
15915 : 20 : emit_insn (gen_hreset (op0));
15916 : 20 : return 0;
15917 : :
15918 : 38 : case IX86_BUILTIN_RSTORSSP:
15919 : 38 : case IX86_BUILTIN_CLRSSBSY:
15920 : 38 : arg0 = CALL_EXPR_ARG (exp, 0);
15921 : 38 : op0 = expand_normal (arg0);
15922 : 19 : icode = (fcode == IX86_BUILTIN_RSTORSSP
15923 : 38 : ? CODE_FOR_rstorssp
15924 : : : CODE_FOR_clrssbsy);
15925 : :
15926 : 38 : if (!address_operand (op0, VOIDmode))
15927 : : {
15928 : 18 : op0 = convert_memory_address (Pmode, op0);
15929 : 18 : op0 = copy_addr_to_reg (op0);
15930 : : }
15931 : 38 : emit_insn (GEN_FCN (icode) (gen_rtx_MEM (DImode, op0)));
15932 : 38 : return 0;
15933 : :
15934 : 76 : case IX86_BUILTIN_WRSSD:
15935 : 76 : case IX86_BUILTIN_WRSSQ:
15936 : 76 : case IX86_BUILTIN_WRUSSD:
15937 : 76 : case IX86_BUILTIN_WRUSSQ:
15938 : 76 : mode = ((fcode == IX86_BUILTIN_WRSSD
15939 : 76 : || fcode == IX86_BUILTIN_WRUSSD)
15940 : 76 : ? SImode : DImode);
15941 : :
15942 : 76 : arg0 = CALL_EXPR_ARG (exp, 0);
15943 : 76 : op0 = expand_normal (arg0);
15944 : 76 : arg1 = CALL_EXPR_ARG (exp, 1);
15945 : 76 : op1 = expand_normal (arg1);
15946 : :
15947 : 76 : op0 = force_reg (mode, op0);
15948 : :
15949 : 76 : if (!address_operand (op1, VOIDmode))
15950 : : {
15951 : 36 : op1 = convert_memory_address (Pmode, op1);
15952 : 36 : op1 = copy_addr_to_reg (op1);
15953 : : }
15954 : 76 : op1 = gen_rtx_MEM (mode, op1);
15955 : :
15956 : 76 : icode = ((fcode == IX86_BUILTIN_WRSSD
15957 : 76 : || fcode == IX86_BUILTIN_WRSSQ)
15958 : 76 : ? code_for_wrss (mode)
15959 : 38 : : code_for_wruss (mode));
15960 : 76 : emit_insn (GEN_FCN (icode) (op0, op1));
15961 : :
15962 : 76 : return 0;
15963 : :
15964 : 113778 : default:
15965 : 113778 : break;
15966 : : }
15967 : :
15968 : 113778 : if (fcode >= IX86_BUILTIN__BDESC_SPECIAL_ARGS_FIRST
15969 : 113778 : && fcode <= IX86_BUILTIN__BDESC_SPECIAL_ARGS_LAST)
15970 : : {
15971 : 27222 : i = fcode - IX86_BUILTIN__BDESC_SPECIAL_ARGS_FIRST;
15972 : 27222 : return ix86_expand_special_args_builtin (bdesc_special_args + i, exp,
15973 : 27222 : target);
15974 : : }
15975 : :
15976 : 86556 : if (fcode >= IX86_BUILTIN__BDESC_PURE_ARGS_FIRST
15977 : 86556 : && fcode <= IX86_BUILTIN__BDESC_PURE_ARGS_LAST)
15978 : : {
15979 : 93 : i = fcode - IX86_BUILTIN__BDESC_PURE_ARGS_FIRST;
15980 : 93 : return ix86_expand_special_args_builtin (bdesc_pure_args + i, exp,
15981 : 93 : target);
15982 : : }
15983 : :
15984 : 86463 : if (fcode >= IX86_BUILTIN__BDESC_ARGS_FIRST
15985 : 86463 : && fcode <= IX86_BUILTIN__BDESC_ARGS_LAST)
15986 : : {
15987 : 68177 : i = fcode - IX86_BUILTIN__BDESC_ARGS_FIRST;
15988 : :
15989 : 68177 : switch (fcode)
15990 : : {
15991 : 0 : case IX86_BUILTIN_RDPID:
15992 : 0 : return ix86_expand_special_args_builtin (bdesc_args + i, exp,
15993 : 0 : target);
15994 : 66 : case IX86_BUILTIN_VCOMISBF16EQ:
15995 : 66 : case IX86_BUILTIN_VCOMISBF16NE:
15996 : 66 : case IX86_BUILTIN_VCOMISBF16GT:
15997 : 66 : case IX86_BUILTIN_VCOMISBF16GE:
15998 : 66 : case IX86_BUILTIN_VCOMISBF16LT:
15999 : 66 : case IX86_BUILTIN_VCOMISBF16LE:
16000 : 66 : return ix86_expand_sse_comi (bdesc_args + i, exp, target, false);
16001 : 9 : case IX86_BUILTIN_FABSQ:
16002 : 9 : case IX86_BUILTIN_COPYSIGNQ:
16003 : 9 : if (!TARGET_SSE)
16004 : : /* Emit a normal call if SSE isn't available. */
16005 : 0 : return expand_call (exp, target, ignore);
16006 : : /* FALLTHRU */
16007 : 68111 : default:
16008 : 68111 : return ix86_expand_args_builtin (bdesc_args + i, exp, target);
16009 : : }
16010 : : }
16011 : :
16012 : 18286 : if (fcode >= IX86_BUILTIN__BDESC_COMI_FIRST
16013 : 18286 : && fcode <= IX86_BUILTIN__BDESC_COMI_LAST)
16014 : : {
16015 : 473 : i = fcode - IX86_BUILTIN__BDESC_COMI_FIRST;
16016 : 473 : return ix86_expand_sse_comi (bdesc_comi + i, exp, target, true);
16017 : : }
16018 : :
16019 : 17813 : if (fcode >= IX86_BUILTIN__BDESC_ROUND_ARGS_FIRST
16020 : 17813 : && fcode <= IX86_BUILTIN__BDESC_ROUND_ARGS_LAST)
16021 : : {
16022 : 15494 : i = fcode - IX86_BUILTIN__BDESC_ROUND_ARGS_FIRST;
16023 : 15494 : return ix86_expand_round_builtin (bdesc_round_args + i, exp, target);
16024 : : }
16025 : :
16026 : 2319 : if (fcode >= IX86_BUILTIN__BDESC_PCMPESTR_FIRST
16027 : 2319 : && fcode <= IX86_BUILTIN__BDESC_PCMPESTR_LAST)
16028 : : {
16029 : 216 : i = fcode - IX86_BUILTIN__BDESC_PCMPESTR_FIRST;
16030 : 216 : return ix86_expand_sse_pcmpestr (bdesc_pcmpestr + i, exp, target);
16031 : : }
16032 : :
16033 : 2103 : if (fcode >= IX86_BUILTIN__BDESC_PCMPISTR_FIRST
16034 : 2103 : && fcode <= IX86_BUILTIN__BDESC_PCMPISTR_LAST)
16035 : : {
16036 : 275 : i = fcode - IX86_BUILTIN__BDESC_PCMPISTR_FIRST;
16037 : 275 : return ix86_expand_sse_pcmpistr (bdesc_pcmpistr + i, exp, target);
16038 : : }
16039 : :
16040 : 1828 : if (fcode >= IX86_BUILTIN__BDESC_MULTI_ARG_FIRST
16041 : 1828 : && fcode <= IX86_BUILTIN__BDESC_MULTI_ARG_LAST)
16042 : : {
16043 : 1790 : i = fcode - IX86_BUILTIN__BDESC_MULTI_ARG_FIRST;
16044 : 1790 : const struct builtin_description *d = bdesc_multi_arg + i;
16045 : 1790 : return ix86_expand_multi_arg_builtin (d->icode, exp, target,
16046 : : (enum ix86_builtin_func_type)
16047 : 1790 : d->flag, d->comparison);
16048 : : }
16049 : :
16050 : 38 : if (fcode >= IX86_BUILTIN__BDESC_CET_FIRST
16051 : 38 : && fcode <= IX86_BUILTIN__BDESC_CET_LAST)
16052 : : {
16053 : 38 : i = fcode - IX86_BUILTIN__BDESC_CET_FIRST;
16054 : 38 : return ix86_expand_special_args_builtin (bdesc_cet + i, exp,
16055 : 38 : target);
16056 : : }
16057 : :
16058 : 0 : gcc_unreachable ();
16059 : : }
16060 : :
16061 : : /* See below where shifts are handled for explanation of this enum. */
16062 : : enum ix86_vec_bcast_alg
16063 : : {
16064 : : VEC_BCAST_PXOR,
16065 : : VEC_BCAST_PCMPEQ,
16066 : : VEC_BCAST_PABSB,
16067 : : VEC_BCAST_PADDB,
16068 : : VEC_BCAST_PSRLW,
16069 : : VEC_BCAST_PSRLD,
16070 : : VEC_BCAST_PSLLW,
16071 : : VEC_BCAST_PSLLD
16072 : : };
16073 : :
16074 : : struct ix86_vec_bcast_map_simode_t
16075 : : {
16076 : : unsigned int key;
16077 : : enum ix86_vec_bcast_alg alg;
16078 : : unsigned int arg;
16079 : : };
16080 : :
16081 : : /* This table must be kept sorted as values are looked-up using bsearch. */
16082 : : static const ix86_vec_bcast_map_simode_t ix86_vec_bcast_map_simode[] = {
16083 : : { 0x00000000, VEC_BCAST_PXOR, 0 },
16084 : : { 0x00000001, VEC_BCAST_PSRLD, 31 },
16085 : : { 0x00000003, VEC_BCAST_PSRLD, 30 },
16086 : : { 0x00000007, VEC_BCAST_PSRLD, 29 },
16087 : : { 0x0000000f, VEC_BCAST_PSRLD, 28 },
16088 : : { 0x0000001f, VEC_BCAST_PSRLD, 27 },
16089 : : { 0x0000003f, VEC_BCAST_PSRLD, 26 },
16090 : : { 0x0000007f, VEC_BCAST_PSRLD, 25 },
16091 : : { 0x000000ff, VEC_BCAST_PSRLD, 24 },
16092 : : { 0x000001ff, VEC_BCAST_PSRLD, 23 },
16093 : : { 0x000003ff, VEC_BCAST_PSRLD, 22 },
16094 : : { 0x000007ff, VEC_BCAST_PSRLD, 21 },
16095 : : { 0x00000fff, VEC_BCAST_PSRLD, 20 },
16096 : : { 0x00001fff, VEC_BCAST_PSRLD, 19 },
16097 : : { 0x00003fff, VEC_BCAST_PSRLD, 18 },
16098 : : { 0x00007fff, VEC_BCAST_PSRLD, 17 },
16099 : : { 0x0000ffff, VEC_BCAST_PSRLD, 16 },
16100 : : { 0x00010001, VEC_BCAST_PSRLW, 15 },
16101 : : { 0x0001ffff, VEC_BCAST_PSRLD, 15 },
16102 : : { 0x00030003, VEC_BCAST_PSRLW, 14 },
16103 : : { 0x0003ffff, VEC_BCAST_PSRLD, 14 },
16104 : : { 0x00070007, VEC_BCAST_PSRLW, 13 },
16105 : : { 0x0007ffff, VEC_BCAST_PSRLD, 13 },
16106 : : { 0x000f000f, VEC_BCAST_PSRLW, 12 },
16107 : : { 0x000fffff, VEC_BCAST_PSRLD, 12 },
16108 : : { 0x001f001f, VEC_BCAST_PSRLW, 11 },
16109 : : { 0x001fffff, VEC_BCAST_PSRLD, 11 },
16110 : : { 0x003f003f, VEC_BCAST_PSRLW, 10 },
16111 : : { 0x003fffff, VEC_BCAST_PSRLD, 10 },
16112 : : { 0x007f007f, VEC_BCAST_PSRLW, 9 },
16113 : : { 0x007fffff, VEC_BCAST_PSRLD, 9 },
16114 : : { 0x00ff00ff, VEC_BCAST_PSRLW, 8 },
16115 : : { 0x00ffffff, VEC_BCAST_PSRLD, 8 },
16116 : : { 0x01010101, VEC_BCAST_PABSB, 0 },
16117 : : { 0x01ff01ff, VEC_BCAST_PSRLW, 7 },
16118 : : { 0x01ffffff, VEC_BCAST_PSRLD, 7 },
16119 : : { 0x03ff03ff, VEC_BCAST_PSRLW, 6 },
16120 : : { 0x03ffffff, VEC_BCAST_PSRLD, 6 },
16121 : : { 0x07ff07ff, VEC_BCAST_PSRLW, 5 },
16122 : : { 0x07ffffff, VEC_BCAST_PSRLD, 5 },
16123 : : { 0x0fff0fff, VEC_BCAST_PSRLW, 4 },
16124 : : { 0x0fffffff, VEC_BCAST_PSRLD, 4 },
16125 : : { 0x1fff1fff, VEC_BCAST_PSRLW, 3 },
16126 : : { 0x1fffffff, VEC_BCAST_PSRLD, 3 },
16127 : : { 0x3fff3fff, VEC_BCAST_PSRLW, 2 },
16128 : : { 0x3fffffff, VEC_BCAST_PSRLD, 2 },
16129 : : { 0x7fff7fff, VEC_BCAST_PSRLW, 1 },
16130 : : { 0x7fffffff, VEC_BCAST_PSRLD, 1 },
16131 : : { 0x80000000, VEC_BCAST_PSLLD, 31 },
16132 : : { 0x80008000, VEC_BCAST_PSLLW, 15 },
16133 : : { 0xc0000000, VEC_BCAST_PSLLD, 30 },
16134 : : { 0xc000c000, VEC_BCAST_PSLLW, 14 },
16135 : : { 0xe0000000, VEC_BCAST_PSLLD, 29 },
16136 : : { 0xe000e000, VEC_BCAST_PSLLW, 13 },
16137 : : { 0xf0000000, VEC_BCAST_PSLLD, 28 },
16138 : : { 0xf000f000, VEC_BCAST_PSLLW, 12 },
16139 : : { 0xf8000000, VEC_BCAST_PSLLD, 27 },
16140 : : { 0xf800f800, VEC_BCAST_PSLLW, 11 },
16141 : : { 0xfc000000, VEC_BCAST_PSLLD, 26 },
16142 : : { 0xfc00fc00, VEC_BCAST_PSLLW, 10 },
16143 : : { 0xfe000000, VEC_BCAST_PSLLD, 25 },
16144 : : { 0xfe00fe00, VEC_BCAST_PSLLW, 9 },
16145 : : { 0xfefefefe, VEC_BCAST_PADDB, 0 },
16146 : : { 0xff000000, VEC_BCAST_PSLLD, 24 },
16147 : : { 0xff00ff00, VEC_BCAST_PSLLW, 8 },
16148 : : { 0xff800000, VEC_BCAST_PSLLD, 23 },
16149 : : { 0xff80ff80, VEC_BCAST_PSLLW, 7 },
16150 : : { 0xffc00000, VEC_BCAST_PSLLD, 22 },
16151 : : { 0xffc0ffc0, VEC_BCAST_PSLLW, 6 },
16152 : : { 0xffe00000, VEC_BCAST_PSLLD, 21 },
16153 : : { 0xffe0ffe0, VEC_BCAST_PSLLW, 5 },
16154 : : { 0xfff00000, VEC_BCAST_PSLLD, 20 },
16155 : : { 0xfff0fff0, VEC_BCAST_PSLLW, 4 },
16156 : : { 0xfff80000, VEC_BCAST_PSLLD, 19 },
16157 : : { 0xfff8fff8, VEC_BCAST_PSLLW, 3 },
16158 : : { 0xfffc0000, VEC_BCAST_PSLLD, 18 },
16159 : : { 0xfffcfffc, VEC_BCAST_PSLLW, 2 },
16160 : : { 0xfffe0000, VEC_BCAST_PSLLD, 17 },
16161 : : { 0xfffefffe, VEC_BCAST_PSLLW, 1 },
16162 : : { 0xffff0000, VEC_BCAST_PSLLD, 16 },
16163 : : { 0xffff8000, VEC_BCAST_PSLLD, 15 },
16164 : : { 0xffffc000, VEC_BCAST_PSLLD, 14 },
16165 : : { 0xffffe000, VEC_BCAST_PSLLD, 13 },
16166 : : { 0xfffff000, VEC_BCAST_PSLLD, 12 },
16167 : : { 0xfffff800, VEC_BCAST_PSLLD, 11 },
16168 : : { 0xfffffc00, VEC_BCAST_PSLLD, 10 },
16169 : : { 0xfffffe00, VEC_BCAST_PSLLD, 9 },
16170 : : { 0xffffff00, VEC_BCAST_PSLLD, 8 },
16171 : : { 0xffffff80, VEC_BCAST_PSLLD, 7 },
16172 : : { 0xffffffc0, VEC_BCAST_PSLLD, 6 },
16173 : : { 0xffffffe0, VEC_BCAST_PSLLD, 5 },
16174 : : { 0xfffffff0, VEC_BCAST_PSLLD, 4 },
16175 : : { 0xfffffff8, VEC_BCAST_PSLLD, 3 },
16176 : : { 0xfffffffc, VEC_BCAST_PSLLD, 2 },
16177 : : { 0xfffffffe, VEC_BCAST_PSLLD, 1 },
16178 : : { 0xffffffff, VEC_BCAST_PCMPEQ, 0 }
16179 : : };
16180 : :
16181 : : /* Comparator for bsearch on ix86_vec_bcast_map. */
16182 : : static int
16183 : 267671 : ix86_vec_bcast_map_simode_cmp (const void *key, const void *entry)
16184 : : {
16185 : 267671 : return (*(const unsigned int*)key)
16186 : 267671 : - ((const ix86_vec_bcast_map_simode_t*)entry)->key;
16187 : : }
16188 : :
16189 : : /* A subroutine of ix86_vector_duplicate_value. Tries to efficiently
16190 : : materialize V4SImode, V8SImode and V16SImode vectors from SImode
16191 : : integer constants. */
16192 : : static bool
16193 : 41167 : ix86_vector_duplicate_simode_const (machine_mode mode, rtx target,
16194 : : unsigned int val)
16195 : : {
16196 : 41167 : const ix86_vec_bcast_map_simode_t *entry;
16197 : 41167 : rtx tmp1, tmp2;
16198 : :
16199 : 41167 : entry = (const ix86_vec_bcast_map_simode_t*)
16200 : 41167 : bsearch(&val, ix86_vec_bcast_map_simode,
16201 : : ARRAY_SIZE (ix86_vec_bcast_map_simode),
16202 : : sizeof (ix86_vec_bcast_map_simode_t),
16203 : : ix86_vec_bcast_map_simode_cmp);
16204 : 41167 : if (!entry)
16205 : : return false;
16206 : :
16207 : 18296 : switch (entry->alg)
16208 : : {
16209 : 0 : case VEC_BCAST_PXOR:
16210 : 0 : if ((mode == V8SImode && !TARGET_AVX2)
16211 : 0 : || (mode == V16SImode && !TARGET_AVX512F))
16212 : : return false;
16213 : 0 : emit_move_insn (target, CONST0_RTX (mode));
16214 : 0 : return true;
16215 : :
16216 : 104 : case VEC_BCAST_PCMPEQ:
16217 : 104 : if ((mode == V4SImode && !TARGET_SSE2)
16218 : 103 : || (mode == V8SImode && !TARGET_AVX2)
16219 : 86 : || (mode == V16SImode && !TARGET_AVX512F))
16220 : : return false;
16221 : 86 : emit_move_insn (target, CONSTM1_RTX (mode));
16222 : 86 : return true;
16223 : :
16224 : 562 : case VEC_BCAST_PABSB:
16225 : 562 : if (mode == V4SImode && TARGET_SSE2)
16226 : : {
16227 : 473 : tmp1 = gen_reg_rtx (V16QImode);
16228 : 473 : emit_move_insn (tmp1, CONSTM1_RTX (V16QImode));
16229 : 473 : tmp2 = gen_reg_rtx (V16QImode);
16230 : 473 : emit_insn (gen_absv16qi2 (tmp2, tmp1));
16231 : : }
16232 : 89 : else if (mode == V8SImode && TARGET_AVX2)
16233 : : {
16234 : 43 : tmp1 = gen_reg_rtx (V32QImode);
16235 : 43 : emit_move_insn (tmp1, CONSTM1_RTX (V32QImode));
16236 : 43 : tmp2 = gen_reg_rtx (V32QImode);
16237 : 43 : emit_insn (gen_absv32qi2 (tmp2, tmp1));
16238 : : }
16239 : 46 : else if (mode == V16SImode && TARGET_AVX512BW)
16240 : : {
16241 : 38 : tmp1 = gen_reg_rtx (V64QImode);
16242 : 38 : emit_move_insn (tmp1, CONSTM1_RTX (V64QImode));
16243 : 38 : tmp2 = gen_reg_rtx (V64QImode);
16244 : 38 : emit_insn (gen_absv64qi2 (tmp2, tmp1));
16245 : : }
16246 : : else
16247 : : return false;
16248 : : break;
16249 : :
16250 : 100 : case VEC_BCAST_PADDB:
16251 : 100 : if (mode == V4SImode && TARGET_SSE2)
16252 : : {
16253 : 95 : tmp1 = gen_reg_rtx (V16QImode);
16254 : 95 : emit_move_insn (tmp1, CONSTM1_RTX (V16QImode));
16255 : 95 : tmp2 = gen_reg_rtx (V16QImode);
16256 : 95 : emit_insn (gen_addv16qi3 (tmp2, tmp1, tmp1));
16257 : : }
16258 : 5 : else if (mode == V8SImode && TARGET_AVX2)
16259 : : {
16260 : 1 : tmp1 = gen_reg_rtx (V32QImode);
16261 : 1 : emit_move_insn (tmp1, CONSTM1_RTX (V32QImode));
16262 : 1 : tmp2 = gen_reg_rtx (V32QImode);
16263 : 1 : emit_insn (gen_addv32qi3 (tmp2, tmp1, tmp1));
16264 : : }
16265 : 4 : else if (mode == V16SImode && TARGET_AVX512BW)
16266 : : {
16267 : 4 : tmp1 = gen_reg_rtx (V64QImode);
16268 : 4 : emit_move_insn (tmp1, CONSTM1_RTX (V64QImode));
16269 : 4 : tmp2 = gen_reg_rtx (V64QImode);
16270 : 4 : emit_insn (gen_addv64qi3 (tmp2, tmp1, tmp1));
16271 : : }
16272 : : else
16273 : : return false;
16274 : : break;
16275 : :
16276 : 3723 : case VEC_BCAST_PSRLW:
16277 : 3723 : if (mode == V4SImode && TARGET_SSE2)
16278 : : {
16279 : 3452 : tmp1 = gen_reg_rtx (V8HImode);
16280 : 3452 : emit_move_insn (tmp1, CONSTM1_RTX (V8HImode));
16281 : 3452 : tmp2 = gen_reg_rtx (V8HImode);
16282 : 3452 : emit_insn (gen_lshrv8hi3 (tmp2, tmp1, GEN_INT (entry->arg)));
16283 : : }
16284 : 271 : else if (mode == V8SImode && TARGET_AVX2)
16285 : : {
16286 : 178 : tmp1 = gen_reg_rtx (V16HImode);
16287 : 178 : emit_move_insn (tmp1, CONSTM1_RTX (V16HImode));
16288 : 178 : tmp2 = gen_reg_rtx (V16HImode);
16289 : 178 : emit_insn (gen_lshrv16hi3 (tmp2, tmp1, GEN_INT (entry->arg)));
16290 : : }
16291 : 93 : else if (mode == V16SImode && TARGET_AVX512BW)
16292 : : {
16293 : 91 : tmp1 = gen_reg_rtx (V32HImode);
16294 : 91 : emit_move_insn (tmp1, CONSTM1_RTX (V32HImode));
16295 : 91 : tmp2 = gen_reg_rtx (V32HImode);
16296 : 91 : emit_insn (gen_lshrv32hi3 (tmp2, tmp1, GEN_INT (entry->arg)));
16297 : : }
16298 : : else
16299 : : return false;
16300 : : break;
16301 : :
16302 : 11727 : case VEC_BCAST_PSRLD:
16303 : 11727 : if (mode == V4SImode && TARGET_SSE2)
16304 : : {
16305 : 9132 : tmp1 = gen_reg_rtx (V4SImode);
16306 : 9132 : emit_move_insn (tmp1, CONSTM1_RTX (V4SImode));
16307 : 9132 : emit_insn (gen_lshrv4si3 (target, tmp1, GEN_INT (entry->arg)));
16308 : 9132 : return true;
16309 : : }
16310 : 2595 : else if (mode == V8SImode && TARGET_AVX2)
16311 : : {
16312 : 921 : tmp1 = gen_reg_rtx (V8SImode);
16313 : 921 : emit_move_insn (tmp1, CONSTM1_RTX (V8SImode));
16314 : 921 : emit_insn (gen_lshrv8si3 (target, tmp1, GEN_INT (entry->arg)));
16315 : 921 : return true;
16316 : : }
16317 : 1674 : else if (mode == V16SImode && TARGET_AVX512F)
16318 : : {
16319 : 843 : tmp1 = gen_reg_rtx (V16SImode);
16320 : 843 : emit_move_insn (tmp1, CONSTM1_RTX (V16SImode));
16321 : 843 : emit_insn (gen_lshrv16si3 (target, tmp1, GEN_INT (entry->arg)));
16322 : 843 : return true;
16323 : : }
16324 : : else
16325 : : return false;
16326 : 114 : break;
16327 : :
16328 : 114 : case VEC_BCAST_PSLLW:
16329 : 114 : if (mode == V4SImode && TARGET_SSE2)
16330 : : {
16331 : 85 : tmp1 = gen_reg_rtx (V8HImode);
16332 : 85 : emit_move_insn (tmp1, CONSTM1_RTX (V8HImode));
16333 : 85 : tmp2 = gen_reg_rtx (V8HImode);
16334 : 85 : emit_insn (gen_ashlv8hi3 (tmp2, tmp1, GEN_INT (entry->arg)));
16335 : : }
16336 : 29 : else if (mode == V8SImode && TARGET_AVX2)
16337 : : {
16338 : 21 : tmp1 = gen_reg_rtx (V16HImode);
16339 : 21 : emit_move_insn (tmp1, CONSTM1_RTX (V16HImode));
16340 : 21 : tmp2 = gen_reg_rtx (V16HImode);
16341 : 21 : emit_insn (gen_ashlv16hi3 (tmp2, tmp1, GEN_INT (entry->arg)));
16342 : : }
16343 : 8 : else if (mode == V16SImode && TARGET_AVX512BW)
16344 : : {
16345 : 8 : tmp1 = gen_reg_rtx (V32HImode);
16346 : 8 : emit_move_insn (tmp1, CONSTM1_RTX (V32HImode));
16347 : 8 : tmp2 = gen_reg_rtx (V32HImode);
16348 : 8 : emit_insn (gen_ashlv32hi3 (tmp2, tmp1, GEN_INT (entry->arg)));
16349 : : }
16350 : : else
16351 : : return false;
16352 : : break;
16353 : :
16354 : 1966 : case VEC_BCAST_PSLLD:
16355 : 1966 : if (mode == V4SImode && TARGET_SSE2)
16356 : : {
16357 : 1699 : tmp1 = gen_reg_rtx (V4SImode);
16358 : 1699 : emit_move_insn (tmp1, CONSTM1_RTX (V4SImode));
16359 : 1699 : emit_insn (gen_ashlv4si3 (target, tmp1, GEN_INT (entry->arg)));
16360 : 1699 : return true;
16361 : : }
16362 : 267 : else if (mode == V8SImode && TARGET_AVX2)
16363 : : {
16364 : 174 : tmp1 = gen_reg_rtx (V8SImode);
16365 : 174 : emit_move_insn (tmp1, CONSTM1_RTX (V8SImode));
16366 : 174 : emit_insn (gen_ashlv8si3 (target, tmp1, GEN_INT (entry->arg)));
16367 : 174 : return true;
16368 : : }
16369 : 93 : else if (mode == V16SImode && TARGET_AVX512F)
16370 : : {
16371 : 93 : tmp1 = gen_reg_rtx (V16SImode);
16372 : 93 : emit_move_insn (tmp1, CONSTM1_RTX (V16SImode));
16373 : 93 : emit_insn (gen_ashlv16si3 (target, tmp1, GEN_INT (entry->arg)));
16374 : 93 : return true;
16375 : : }
16376 : : else
16377 : : return false;
16378 : :
16379 : : default:
16380 : : return false;
16381 : : }
16382 : :
16383 : 4489 : emit_move_insn (target, gen_lowpart (mode, tmp2));
16384 : 4489 : return true;
16385 : : }
16386 : :
16387 : : /* A subroutine of ix86_expand_vector_init_duplicate. Tries to
16388 : : fill target with val via vec_duplicate. */
16389 : :
16390 : : static bool
16391 : 137305 : ix86_vector_duplicate_value (machine_mode mode, rtx target, rtx val)
16392 : : {
16393 : 137305 : bool ok;
16394 : 137305 : rtx_insn *insn;
16395 : 137305 : rtx dup;
16396 : :
16397 : 137305 : if ((mode == V4SImode || mode == V8SImode || mode == V16SImode)
16398 : 48548 : && CONST_INT_P (val)
16399 : 41167 : && ix86_vector_duplicate_simode_const (mode, target, INTVAL (val)))
16400 : : return true;
16401 : :
16402 : : /* Save/restore recog_data in case this is called from splitters
16403 : : or other routines where recog_data needs to stay valid across
16404 : : force_reg. See PR106577. */
16405 : 119868 : recog_data_d recog_data_save = recog_data;
16406 : :
16407 : : /* First attempt to recognize VAL as-is. */
16408 : 119868 : dup = gen_vec_duplicate (mode, val);
16409 : 119868 : insn = emit_insn (gen_rtx_SET (target, dup));
16410 : 119868 : if (recog_memoized (insn) < 0)
16411 : : {
16412 : 85137 : rtx_insn *seq;
16413 : 85137 : machine_mode innermode = GET_MODE_INNER (mode);
16414 : 85137 : rtx reg;
16415 : :
16416 : : /* If that fails, force VAL into a register. */
16417 : :
16418 : 85137 : start_sequence ();
16419 : 85137 : reg = force_reg (innermode, val);
16420 : 85137 : if (GET_MODE (reg) != innermode)
16421 : 0 : reg = gen_lowpart (innermode, reg);
16422 : 85137 : SET_SRC (PATTERN (insn)) = gen_vec_duplicate (mode, reg);
16423 : 85137 : seq = end_sequence ();
16424 : 85137 : if (seq)
16425 : 85137 : emit_insn_before (seq, insn);
16426 : :
16427 : 85137 : ok = recog_memoized (insn) >= 0;
16428 : 85137 : gcc_assert (ok);
16429 : : }
16430 : 119868 : recog_data = recog_data_save;
16431 : 119868 : return true;
16432 : : }
16433 : :
16434 : : /* Get a vector mode of the same size as the original but with elements
16435 : : twice as wide. This is only guaranteed to apply to integral vectors. */
16436 : :
16437 : : static machine_mode
16438 : 15950 : get_mode_wider_vector (machine_mode o)
16439 : : {
16440 : : /* ??? Rely on the ordering that genmodes.cc gives to vectors. */
16441 : 15950 : machine_mode n = GET_MODE_NEXT_MODE (o).require ();
16442 : 47850 : gcc_assert (GET_MODE_NUNITS (o) == GET_MODE_NUNITS (n) * 2);
16443 : 47850 : gcc_assert (GET_MODE_SIZE (o) == GET_MODE_SIZE (n));
16444 : 15950 : return n;
16445 : : }
16446 : :
16447 : : static bool expand_vec_perm_broadcast_1 (struct expand_vec_perm_d *d);
16448 : : static bool expand_vec_perm_1 (struct expand_vec_perm_d *d);
16449 : :
16450 : : /* A subroutine of ix86_expand_vector_init. Store into TARGET a vector
16451 : : with all elements equal to VAR. Return true if successful. */
16452 : :
16453 : : bool
16454 : 154269 : ix86_expand_vector_init_duplicate (bool mmx_ok, machine_mode mode,
16455 : : rtx target, rtx val)
16456 : : {
16457 : 154269 : bool ok;
16458 : :
16459 : 154269 : switch (mode)
16460 : : {
16461 : 68948 : case E_V2DImode:
16462 : 68948 : if (CONST_INT_P (val))
16463 : : {
16464 : 60707 : int tmp = (int)INTVAL (val);
16465 : 60707 : if (tmp == (int)(INTVAL (val) >> 32))
16466 : : {
16467 : 125 : rtx reg = gen_reg_rtx (V4SImode);
16468 : 125 : ok = ix86_vector_duplicate_value (V4SImode, reg,
16469 : : GEN_INT (tmp));
16470 : 125 : if (ok)
16471 : : {
16472 : 125 : emit_move_insn (target, gen_lowpart (V2DImode, reg));
16473 : 125 : return true;
16474 : : }
16475 : : }
16476 : : }
16477 : 68823 : return ix86_vector_duplicate_value (mode, target, val);
16478 : :
16479 : 714 : case E_V4DImode:
16480 : 714 : if (CONST_INT_P (val))
16481 : : {
16482 : 616 : int tmp = (int)INTVAL (val);
16483 : 616 : if (tmp == (int)(INTVAL (val) >> 32))
16484 : : {
16485 : 42 : rtx reg = gen_reg_rtx (V8SImode);
16486 : 42 : ok = ix86_vector_duplicate_value (V8SImode, reg,
16487 : : GEN_INT (tmp));
16488 : 42 : if (ok)
16489 : : {
16490 : 42 : emit_move_insn (target, gen_lowpart (V4DImode, reg));
16491 : 42 : return true;
16492 : : }
16493 : : }
16494 : : }
16495 : 672 : return ix86_vector_duplicate_value (mode, target, val);
16496 : :
16497 : 318 : case E_V8DImode:
16498 : 318 : if (CONST_INT_P (val))
16499 : : {
16500 : 235 : int tmp = (int)INTVAL (val);
16501 : 235 : if (tmp == (int)(INTVAL (val) >> 32))
16502 : : {
16503 : 20 : rtx reg = gen_reg_rtx (V16SImode);
16504 : 20 : ok = ix86_vector_duplicate_value (V16SImode, reg,
16505 : : GEN_INT (tmp));
16506 : 20 : if (ok)
16507 : : {
16508 : 20 : emit_move_insn (target, gen_lowpart (V8DImode, reg));
16509 : 20 : return true;
16510 : : }
16511 : : }
16512 : : }
16513 : 298 : return ix86_vector_duplicate_value (mode, target, val);
16514 : :
16515 : 2297 : case E_V2SImode:
16516 : 2297 : case E_V2SFmode:
16517 : 2297 : if (!mmx_ok)
16518 : : return false;
16519 : : /* FALLTHRU */
16520 : :
16521 : 66543 : case E_V4DFmode:
16522 : 66543 : case E_V8SFmode:
16523 : 66543 : case E_V8SImode:
16524 : 66543 : case E_V2DFmode:
16525 : 66543 : case E_V4SFmode:
16526 : 66543 : case E_V4SImode:
16527 : 66543 : case E_V16SImode:
16528 : 66543 : case E_V16SFmode:
16529 : 66543 : case E_V8DFmode:
16530 : 66543 : return ix86_vector_duplicate_value (mode, target, val);
16531 : :
16532 : 380 : case E_V4HImode:
16533 : 380 : if (!mmx_ok)
16534 : : return false;
16535 : 377 : if (TARGET_SSE || TARGET_3DNOW_A)
16536 : : {
16537 : 377 : rtx x;
16538 : :
16539 : 377 : val = gen_lowpart (SImode, val);
16540 : 377 : if (CONST_INT_P (val))
16541 : : return false;
16542 : 375 : x = gen_rtx_TRUNCATE (HImode, val);
16543 : 375 : x = gen_rtx_VEC_DUPLICATE (mode, x);
16544 : 375 : emit_insn (gen_rtx_SET (target, x));
16545 : 375 : return true;
16546 : : }
16547 : 0 : goto widen;
16548 : :
16549 : 5 : case E_V4HFmode:
16550 : 5 : case E_V4BFmode:
16551 : 5 : if (TARGET_MMX_WITH_SSE)
16552 : : {
16553 : 10 : val = force_reg (GET_MODE_INNER (mode), val);
16554 : 5 : rtx x = gen_rtx_VEC_DUPLICATE (mode, val);
16555 : 5 : emit_insn (gen_rtx_SET (target, x));
16556 : 5 : return true;
16557 : : }
16558 : : return false;
16559 : :
16560 : 101 : case E_V2HImode:
16561 : 101 : if (TARGET_SSE2)
16562 : : {
16563 : 101 : rtx x;
16564 : :
16565 : 101 : val = gen_lowpart (SImode, val);
16566 : 101 : if (CONST_INT_P (val))
16567 : : return false;
16568 : 101 : x = gen_rtx_TRUNCATE (HImode, val);
16569 : 101 : x = gen_rtx_VEC_DUPLICATE (mode, x);
16570 : 101 : emit_insn (gen_rtx_SET (target, x));
16571 : 101 : return true;
16572 : : }
16573 : : return false;
16574 : :
16575 : 3 : case E_V2HFmode:
16576 : 3 : case E_V2BFmode:
16577 : 3 : if (TARGET_SSE2)
16578 : : {
16579 : 6 : val = force_reg (GET_MODE_INNER (mode), val);
16580 : 3 : rtx x = gen_rtx_VEC_DUPLICATE (mode, val);
16581 : 3 : emit_insn (gen_rtx_SET (target, x));
16582 : 3 : return true;
16583 : : }
16584 : : return false;
16585 : :
16586 : 286 : case E_V8QImode:
16587 : 286 : case E_V4QImode:
16588 : 286 : if (!mmx_ok)
16589 : : return false;
16590 : 282 : goto widen;
16591 : :
16592 : 9022 : case E_V8HImode:
16593 : 9022 : if (CONST_INT_P (val))
16594 : 8581 : goto widen;
16595 : : /* FALLTHRU */
16596 : :
16597 : 730 : case E_V8HFmode:
16598 : 730 : case E_V8BFmode:
16599 : 730 : if (TARGET_AVX2)
16600 : 331 : return ix86_vector_duplicate_value (mode, target, val);
16601 : :
16602 : 399 : if (TARGET_SSE2)
16603 : : {
16604 : 1104 : struct expand_vec_perm_d dperm;
16605 : 1104 : rtx tmp1, tmp2;
16606 : :
16607 : 399 : permute:
16608 : 1104 : memset (&dperm, 0, sizeof (dperm));
16609 : 1104 : dperm.target = target;
16610 : 1104 : dperm.vmode = mode;
16611 : 1104 : dperm.nelt = GET_MODE_NUNITS (mode);
16612 : 1104 : dperm.op0 = dperm.op1 = gen_reg_rtx (mode);
16613 : 1104 : dperm.one_operand_p = true;
16614 : :
16615 : 1104 : if (mode == V8HFmode || mode == V8BFmode)
16616 : : {
16617 : 3 : tmp1 = force_reg (GET_MODE_INNER (mode), val);
16618 : 3 : tmp2 = gen_reg_rtx (mode);
16619 : 3 : emit_insn (gen_vec_set_0 (mode, tmp2, CONST0_RTX (mode), tmp1));
16620 : 3 : tmp1 = gen_lowpart (mode, tmp2);
16621 : : }
16622 : : else
16623 : : {
16624 : : /* Extend to SImode using a paradoxical SUBREG. */
16625 : 1101 : tmp1 = gen_reg_rtx (SImode);
16626 : 1101 : emit_move_insn (tmp1, gen_lowpart (SImode, val));
16627 : :
16628 : : /* Insert the SImode value as
16629 : : low element of a V4SImode vector. */
16630 : 1101 : tmp2 = gen_reg_rtx (V4SImode);
16631 : 1101 : emit_insn (gen_vec_setv4si_0 (tmp2, CONST0_RTX (V4SImode), tmp1));
16632 : 1101 : tmp1 = gen_lowpart (mode, tmp2);
16633 : : }
16634 : :
16635 : 1104 : emit_move_insn (dperm.op0, tmp1);
16636 : 1104 : ok = (expand_vec_perm_1 (&dperm)
16637 : 1104 : || expand_vec_perm_broadcast_1 (&dperm));
16638 : 0 : gcc_assert (ok);
16639 : 1104 : return ok;
16640 : : }
16641 : 0 : goto widen;
16642 : :
16643 : 4951 : case E_V16QImode:
16644 : 4951 : if (CONST_INT_P (val))
16645 : 4195 : goto widen;
16646 : 756 : if (TARGET_AVX2)
16647 : 51 : return ix86_vector_duplicate_value (mode, target, val);
16648 : :
16649 : 705 : if (TARGET_SSE2)
16650 : 705 : goto permute;
16651 : 0 : goto widen;
16652 : :
16653 : 14401 : widen:
16654 : : /* Replicate the value once into the next wider mode and recurse. */
16655 : 14401 : {
16656 : 14401 : machine_mode smode, wsmode, wvmode;
16657 : 14401 : rtx x;
16658 : :
16659 : 14401 : smode = GET_MODE_INNER (mode);
16660 : 14401 : wvmode = get_mode_wider_vector (mode);
16661 : 14401 : wsmode = GET_MODE_INNER (wvmode);
16662 : :
16663 : 14401 : val = convert_modes (wsmode, smode, val, true);
16664 : :
16665 : 14401 : if (CONST_INT_P (val))
16666 : : {
16667 : 28240 : x = simplify_binary_operation (ASHIFT, wsmode, val,
16668 : 14120 : GEN_INT (GET_MODE_BITSIZE (smode)));
16669 : 14120 : val = simplify_binary_operation (IOR, wsmode, val, x);
16670 : : }
16671 : 281 : else if (smode == QImode && !TARGET_PARTIAL_REG_STALL)
16672 : 281 : emit_insn (gen_insv_1 (wsmode, val, val));
16673 : : else
16674 : : {
16675 : 0 : x = expand_simple_binop (wsmode, ASHIFT, val,
16676 : 0 : GEN_INT (GET_MODE_BITSIZE (smode)),
16677 : : NULL_RTX, 1, OPTAB_LIB_WIDEN);
16678 : 0 : val = expand_simple_binop (wsmode, IOR, val, x, x, 1,
16679 : : OPTAB_LIB_WIDEN);
16680 : : }
16681 : :
16682 : 14401 : x = gen_reg_rtx (wvmode);
16683 : 14401 : ok = ix86_expand_vector_init_duplicate (mmx_ok, wvmode, x, val);
16684 : 14401 : if (!ok)
16685 : : return false;
16686 : 14400 : emit_move_insn (target, gen_lowpart (GET_MODE (target), x));
16687 : 14400 : return true;
16688 : : }
16689 : :
16690 : 1062 : case E_V16HImode:
16691 : 1062 : case E_V32QImode:
16692 : 1062 : if (CONST_INT_P (val))
16693 : 808 : goto widen;
16694 : : /* FALLTHRU */
16695 : :
16696 : 312 : case E_V16HFmode:
16697 : 312 : case E_V16BFmode:
16698 : 312 : if (TARGET_AVX2)
16699 : 284 : return ix86_vector_duplicate_value (mode, target, val);
16700 : : else
16701 : : {
16702 : 28 : machine_mode hvmode;
16703 : 28 : switch (mode)
16704 : : {
16705 : : case V16HImode:
16706 : : hvmode = V8HImode;
16707 : : break;
16708 : 0 : case V16HFmode:
16709 : 0 : hvmode = V8HFmode;
16710 : 0 : break;
16711 : 1 : case V16BFmode:
16712 : 1 : hvmode = V8BFmode;
16713 : 1 : break;
16714 : 14 : case V32QImode:
16715 : 14 : hvmode = V16QImode;
16716 : 14 : break;
16717 : 0 : default:
16718 : 0 : gcc_unreachable ();
16719 : : }
16720 : 28 : rtx x = gen_reg_rtx (hvmode);
16721 : :
16722 : 28 : ok = ix86_expand_vector_init_duplicate (false, hvmode, x, val);
16723 : 28 : if (!ok)
16724 : : return false;
16725 : :
16726 : 28 : x = gen_rtx_VEC_CONCAT (mode, x, x);
16727 : 28 : emit_insn (gen_rtx_SET (target, x));
16728 : : }
16729 : 28 : return true;
16730 : :
16731 : 621 : case E_V32HImode:
16732 : 621 : case E_V64QImode:
16733 : 621 : if (CONST_INT_P (val))
16734 : 535 : goto widen;
16735 : : /* FALLTHRU */
16736 : :
16737 : 136 : case E_V32HFmode:
16738 : 136 : case E_V32BFmode:
16739 : 136 : if (TARGET_AVX512BW)
16740 : 116 : return ix86_vector_duplicate_value (mode, target, val);
16741 : : else
16742 : : {
16743 : 20 : machine_mode hvmode;
16744 : 20 : switch (mode)
16745 : : {
16746 : : case V32HImode:
16747 : : hvmode = V16HImode;
16748 : : break;
16749 : 0 : case V32HFmode:
16750 : 0 : hvmode = V16HFmode;
16751 : 0 : break;
16752 : 1 : case V32BFmode:
16753 : 1 : hvmode = V16BFmode;
16754 : 1 : break;
16755 : 10 : case V64QImode:
16756 : 10 : hvmode = V32QImode;
16757 : 10 : break;
16758 : 0 : default:
16759 : 0 : gcc_unreachable ();
16760 : : }
16761 : 20 : rtx x = gen_reg_rtx (hvmode);
16762 : :
16763 : 20 : ok = ix86_expand_vector_init_duplicate (false, hvmode, x, val);
16764 : 20 : if (!ok)
16765 : : return false;
16766 : :
16767 : 20 : x = gen_rtx_VEC_CONCAT (mode, x, x);
16768 : 20 : emit_insn (gen_rtx_SET (target, x));
16769 : : }
16770 : 20 : return true;
16771 : :
16772 : : default:
16773 : : return false;
16774 : : }
16775 : : }
16776 : :
16777 : : /* A subroutine of ix86_expand_vector_init. Store into TARGET a vector
16778 : : whose ONE_VAR element is VAR, and other elements are zero. Return true
16779 : : if successful. */
16780 : :
16781 : : bool
16782 : 11173 : ix86_expand_vector_init_one_nonzero (bool mmx_ok, machine_mode mode,
16783 : : rtx target, rtx var, int one_var)
16784 : : {
16785 : 11173 : machine_mode vsimode;
16786 : 11173 : rtx new_target;
16787 : 11173 : rtx x, tmp;
16788 : 11173 : bool use_vector_set = false;
16789 : 11173 : rtx (*gen_vec_set_0) (rtx, rtx, rtx) = NULL;
16790 : :
16791 : 11173 : switch (mode)
16792 : : {
16793 : 9142 : case E_V2DImode:
16794 : : /* For SSE4.1, we normally use vector set. But if the second
16795 : : element is zero and inter-unit moves are OK, we use movq
16796 : : instead. */
16797 : 9133 : use_vector_set = (TARGET_64BIT && TARGET_SSE4_1
16798 : 9246 : && !(TARGET_INTER_UNIT_MOVES_TO_VEC
16799 : : && one_var == 0));
16800 : : break;
16801 : 444 : case E_V16QImode:
16802 : 444 : case E_V4SImode:
16803 : 444 : case E_V4SFmode:
16804 : 444 : use_vector_set = TARGET_SSE4_1;
16805 : 444 : break;
16806 : 83 : case E_V8HImode:
16807 : 83 : use_vector_set = TARGET_SSE2;
16808 : 83 : gen_vec_set_0 = TARGET_AVX512FP16 && one_var == 0
16809 : 83 : ? gen_vec_setv8hi_0 : NULL;
16810 : : break;
16811 : 7 : case E_V8QImode:
16812 : 7 : use_vector_set = TARGET_MMX_WITH_SSE && TARGET_SSE4_1;
16813 : : break;
16814 : 14 : case E_V4HImode:
16815 : 14 : case E_V4HFmode:
16816 : 14 : case E_V4BFmode:
16817 : 14 : use_vector_set = TARGET_SSE || TARGET_3DNOW_A;
16818 : : break;
16819 : 7 : case E_V4QImode:
16820 : 7 : use_vector_set = TARGET_SSE4_1;
16821 : 7 : break;
16822 : 0 : case E_V32QImode:
16823 : 0 : use_vector_set = TARGET_AVX;
16824 : 0 : break;
16825 : 5 : case E_V16HImode:
16826 : 5 : use_vector_set = TARGET_AVX;
16827 : 5 : gen_vec_set_0 = TARGET_AVX512FP16 && one_var == 0
16828 : 5 : ? gen_vec_setv16hi_0 : NULL;
16829 : : break;
16830 : 3 : case E_V8SImode:
16831 : 3 : use_vector_set = TARGET_AVX;
16832 : 3 : gen_vec_set_0 = gen_vec_setv8si_0;
16833 : 3 : break;
16834 : 22 : case E_V8SFmode:
16835 : 22 : use_vector_set = TARGET_AVX;
16836 : 22 : gen_vec_set_0 = gen_vec_setv8sf_0;
16837 : 22 : break;
16838 : 13 : case E_V4DFmode:
16839 : 13 : use_vector_set = TARGET_AVX;
16840 : 13 : gen_vec_set_0 = gen_vec_setv4df_0;
16841 : 13 : break;
16842 : 7 : case E_V4DImode:
16843 : : /* Use ix86_expand_vector_set in 64bit mode only. */
16844 : 7 : use_vector_set = TARGET_AVX && TARGET_64BIT;
16845 : : gen_vec_set_0 = gen_vec_setv4di_0;
16846 : : break;
16847 : 17 : case E_V16SImode:
16848 : 17 : use_vector_set = TARGET_AVX512F && one_var == 0;
16849 : : gen_vec_set_0 = gen_vec_setv16si_0;
16850 : : break;
16851 : 22 : case E_V16SFmode:
16852 : 22 : use_vector_set = TARGET_AVX512F && one_var == 0;
16853 : : gen_vec_set_0 = gen_vec_setv16sf_0;
16854 : : break;
16855 : 0 : case E_V8DFmode:
16856 : 0 : use_vector_set = TARGET_AVX512F && one_var == 0;
16857 : : gen_vec_set_0 = gen_vec_setv8df_0;
16858 : : break;
16859 : 2 : case E_V8DImode:
16860 : : /* Use ix86_expand_vector_set in 64bit mode only. */
16861 : 2 : use_vector_set = TARGET_AVX512F && TARGET_64BIT && one_var == 0;
16862 : : gen_vec_set_0 = gen_vec_setv8di_0;
16863 : : break;
16864 : 38 : case E_V8HFmode:
16865 : 38 : use_vector_set = TARGET_AVX512FP16 && one_var == 0;
16866 : : gen_vec_set_0 = gen_vec_setv8hf_0;
16867 : : break;
16868 : 8 : case E_V16HFmode:
16869 : 8 : use_vector_set = TARGET_AVX512FP16 && one_var == 0;
16870 : : gen_vec_set_0 = gen_vec_setv16hf_0;
16871 : : break;
16872 : 6 : case E_V32HFmode:
16873 : 6 : use_vector_set = TARGET_AVX512FP16 && one_var == 0;
16874 : : gen_vec_set_0 = gen_vec_setv32hf_0;
16875 : : break;
16876 : 1 : case E_V8BFmode:
16877 : 1 : use_vector_set = TARGET_AVX512FP16 && one_var == 0;
16878 : : gen_vec_set_0 = gen_vec_setv8bf_0;
16879 : : break;
16880 : 0 : case E_V16BFmode:
16881 : 0 : use_vector_set = TARGET_AVX512FP16 && one_var == 0;
16882 : : gen_vec_set_0 = gen_vec_setv16bf_0;
16883 : : break;
16884 : 0 : case E_V32BFmode:
16885 : 0 : use_vector_set = TARGET_AVX512FP16 && one_var == 0;
16886 : : gen_vec_set_0 = gen_vec_setv32bf_0;
16887 : : break;
16888 : 4 : case E_V32HImode:
16889 : 4 : use_vector_set = TARGET_AVX512FP16 && one_var == 0;
16890 : : gen_vec_set_0 = gen_vec_setv32hi_0;
16891 : : default:
16892 : : break;
16893 : : }
16894 : :
16895 : 9733 : if (use_vector_set)
16896 : : {
16897 : 422 : if (gen_vec_set_0 && one_var == 0)
16898 : : {
16899 : 344 : var = force_reg (GET_MODE_INNER (mode), var);
16900 : 172 : emit_insn (gen_vec_set_0 (target, CONST0_RTX (mode), var));
16901 : 172 : return true;
16902 : : }
16903 : 250 : emit_insn (gen_rtx_SET (target, CONST0_RTX (mode)));
16904 : 500 : var = force_reg (GET_MODE_INNER (mode), var);
16905 : 250 : ix86_expand_vector_set (mmx_ok, target, var, one_var);
16906 : 250 : return true;
16907 : : }
16908 : :
16909 : 10751 : switch (mode)
16910 : : {
16911 : 1240 : case E_V2SFmode:
16912 : 1240 : case E_V2SImode:
16913 : 1240 : if (!mmx_ok)
16914 : : return false;
16915 : : /* FALLTHRU */
16916 : :
16917 : 9348 : case E_V2DFmode:
16918 : 9348 : case E_V2DImode:
16919 : 9348 : if (one_var != 0)
16920 : : return false;
16921 : 6106 : var = force_reg (GET_MODE_INNER (mode), var);
16922 : 6106 : x = gen_rtx_VEC_CONCAT (mode, var, CONST0_RTX (GET_MODE_INNER (mode)));
16923 : 3053 : emit_insn (gen_rtx_SET (target, x));
16924 : 3053 : return true;
16925 : :
16926 : 313 : case E_V4SFmode:
16927 : 313 : case E_V4SImode:
16928 : 313 : if (!REG_P (target) || REGNO (target) < FIRST_PSEUDO_REGISTER)
16929 : 0 : new_target = gen_reg_rtx (mode);
16930 : : else
16931 : : new_target = target;
16932 : 626 : var = force_reg (GET_MODE_INNER (mode), var);
16933 : 313 : x = gen_rtx_VEC_DUPLICATE (mode, var);
16934 : 313 : x = gen_rtx_VEC_MERGE (mode, x, CONST0_RTX (mode), const1_rtx);
16935 : 313 : emit_insn (gen_rtx_SET (new_target, x));
16936 : 313 : if (one_var != 0)
16937 : : {
16938 : : /* We need to shuffle the value to the correct position, so
16939 : : create a new pseudo to store the intermediate result. */
16940 : :
16941 : : /* With SSE2, we can use the integer shuffle insns. */
16942 : 44 : if (mode != V4SFmode && TARGET_SSE2)
16943 : : {
16944 : 31 : emit_insn (gen_sse2_pshufd_1 (new_target, new_target,
16945 : : const1_rtx,
16946 : 31 : GEN_INT (one_var == 1 ? 0 : 1),
16947 : 31 : GEN_INT (one_var == 2 ? 0 : 1),
16948 : 31 : GEN_INT (one_var == 3 ? 0 : 1)));
16949 : 31 : if (target != new_target)
16950 : 0 : emit_move_insn (target, new_target);
16951 : 31 : return true;
16952 : : }
16953 : :
16954 : : /* Otherwise convert the intermediate result to V4SFmode and
16955 : : use the SSE1 shuffle instructions. */
16956 : 0 : if (mode != V4SFmode)
16957 : : {
16958 : 0 : tmp = gen_reg_rtx (V4SFmode);
16959 : 0 : emit_move_insn (tmp, gen_lowpart (V4SFmode, new_target));
16960 : : }
16961 : : else
16962 : : tmp = new_target;
16963 : :
16964 : 43 : emit_insn (gen_sse_shufps_v4sf (tmp, tmp, tmp,
16965 : : const1_rtx,
16966 : 13 : GEN_INT (one_var == 1 ? 0 : 1),
16967 : : GEN_INT (one_var == 2 ? 0+4 : 1+4),
16968 : : GEN_INT (one_var == 3 ? 0+4 : 1+4)));
16969 : :
16970 : 13 : if (mode != V4SFmode)
16971 : 0 : emit_move_insn (target, gen_lowpart (V4SImode, tmp));
16972 : 13 : else if (tmp != target)
16973 : 0 : emit_move_insn (target, tmp);
16974 : : }
16975 : 269 : else if (target != new_target)
16976 : 0 : emit_move_insn (target, new_target);
16977 : : return true;
16978 : :
16979 : 12 : case E_V8HImode:
16980 : 12 : case E_V16QImode:
16981 : 12 : vsimode = V4SImode;
16982 : 12 : goto widen;
16983 : 2 : case E_V4HImode:
16984 : 2 : case E_V8QImode:
16985 : 2 : if (!mmx_ok)
16986 : : return false;
16987 : 2 : vsimode = V2SImode;
16988 : 2 : goto widen;
16989 : 14 : widen:
16990 : 14 : if (one_var != 0)
16991 : : return false;
16992 : :
16993 : : /* Zero extend the variable element to SImode and recurse. */
16994 : 14 : var = convert_modes (SImode, GET_MODE_INNER (mode), var, true);
16995 : :
16996 : 7 : x = gen_reg_rtx (vsimode);
16997 : 7 : if (!ix86_expand_vector_init_one_nonzero (mmx_ok, vsimode, x,
16998 : : var, one_var))
16999 : 0 : gcc_unreachable ();
17000 : :
17001 : 7 : emit_move_insn (target, gen_lowpart (mode, x));
17002 : 7 : return true;
17003 : :
17004 : : default:
17005 : : return false;
17006 : : }
17007 : : }
17008 : :
17009 : : /* A subroutine of ix86_expand_vector_init. Store into TARGET a vector
17010 : : consisting of the values in VALS. It is known that all elements
17011 : : except ONE_VAR are constants. Return true if successful. */
17012 : :
17013 : : static bool
17014 : 8509 : ix86_expand_vector_init_one_var (bool mmx_ok, machine_mode mode,
17015 : : rtx target, rtx vals, int one_var)
17016 : : {
17017 : 8509 : rtx var = XVECEXP (vals, 0, one_var);
17018 : 8509 : machine_mode wmode;
17019 : 8509 : rtx const_vec, x;
17020 : :
17021 : 8509 : const_vec = copy_rtx (vals);
17022 : 8509 : XVECEXP (const_vec, 0, one_var) = CONST0_RTX (GET_MODE_INNER (mode));
17023 : 8509 : const_vec = gen_rtx_CONST_VECTOR (mode, XVEC (const_vec, 0));
17024 : :
17025 : 8509 : switch (mode)
17026 : : {
17027 : : case E_V2DFmode:
17028 : : case E_V2DImode:
17029 : : case E_V2SFmode:
17030 : : case E_V2SImode:
17031 : : /* For the two element vectors, it's just as easy to use
17032 : : the general case. */
17033 : : return false;
17034 : :
17035 : 3 : case E_V4DImode:
17036 : : /* Use ix86_expand_vector_set in 64bit mode only. */
17037 : 3 : if (!TARGET_64BIT)
17038 : : return false;
17039 : : /* FALLTHRU */
17040 : : case E_V8HFmode:
17041 : : case E_V16HFmode:
17042 : : case E_V8BFmode:
17043 : : case E_V16BFmode:
17044 : : case E_V4DFmode:
17045 : : case E_V8SFmode:
17046 : : case E_V8SImode:
17047 : : case E_V16HImode:
17048 : : case E_V32QImode:
17049 : : case E_V4SFmode:
17050 : : case E_V4SImode:
17051 : : case E_V8HImode:
17052 : : case E_V4HImode:
17053 : : case E_V4HFmode:
17054 : : case E_V4BFmode:
17055 : : break;
17056 : :
17057 : 8 : case E_V16QImode:
17058 : 8 : if (TARGET_SSE4_1)
17059 : : break;
17060 : 8 : wmode = V8HImode;
17061 : 8 : goto widen;
17062 : 0 : case E_V8QImode:
17063 : 0 : if (TARGET_MMX_WITH_SSE && TARGET_SSE4_1)
17064 : : break;
17065 : 0 : wmode = V4HImode;
17066 : 0 : goto widen;
17067 : 13 : case E_V4QImode:
17068 : 13 : if (TARGET_SSE4_1)
17069 : : break;
17070 : : wmode = V2HImode;
17071 : 21 : widen:
17072 : : /* There's no way to set one QImode entry easily. Combine
17073 : : the variable value with its adjacent constant value, and
17074 : : promote to an HImode set. */
17075 : 21 : x = XVECEXP (vals, 0, one_var ^ 1);
17076 : 21 : if (one_var & 1)
17077 : : {
17078 : 12 : var = convert_modes (HImode, QImode, var, true);
17079 : 12 : var = expand_simple_binop (HImode, ASHIFT, var, GEN_INT (8),
17080 : : NULL_RTX, 1, OPTAB_LIB_WIDEN);
17081 : 12 : x = GEN_INT (INTVAL (x) & 0xff);
17082 : : }
17083 : : else
17084 : : {
17085 : 9 : var = convert_modes (HImode, QImode, var, true);
17086 : 9 : x = gen_int_mode (UINTVAL (x) << 8, HImode);
17087 : : }
17088 : 21 : if (x != const0_rtx)
17089 : 7 : var = expand_simple_binop (HImode, IOR, var, x, var,
17090 : : 1, OPTAB_LIB_WIDEN);
17091 : :
17092 : 21 : x = gen_reg_rtx (wmode);
17093 : 21 : emit_move_insn (x, gen_lowpart (wmode, const_vec));
17094 : 21 : ix86_expand_vector_set (mmx_ok, x, var, one_var >> 1);
17095 : :
17096 : 21 : emit_move_insn (target, gen_lowpart (mode, x));
17097 : 21 : return true;
17098 : :
17099 : : default:
17100 : : return false;
17101 : : }
17102 : :
17103 : 187 : emit_move_insn (target, const_vec);
17104 : 187 : ix86_expand_vector_set (mmx_ok, target, var, one_var);
17105 : 187 : return true;
17106 : : }
17107 : :
17108 : : /* A subroutine of ix86_expand_vector_init_general. Use vector
17109 : : concatenate to handle the most general case: all values variable,
17110 : : and none identical. */
17111 : :
17112 : : static void
17113 : 120968 : ix86_expand_vector_init_concat (machine_mode mode,
17114 : : rtx target, rtx *ops, int n)
17115 : : {
17116 : 120968 : machine_mode half_mode = VOIDmode;
17117 : 120968 : rtx half[2];
17118 : 120968 : rtvec v;
17119 : 120968 : int i, j;
17120 : :
17121 : 120968 : switch (n)
17122 : : {
17123 : 113173 : case 2:
17124 : 113173 : switch (mode)
17125 : : {
17126 : : case E_V32HFmode:
17127 : : half_mode = V16HFmode;
17128 : : break;
17129 : 0 : case E_V32BFmode:
17130 : 0 : half_mode = V16BFmode;
17131 : 0 : break;
17132 : 82 : case E_V16SImode:
17133 : 82 : half_mode = V8SImode;
17134 : 82 : break;
17135 : 33 : case E_V16SFmode:
17136 : 33 : half_mode = V8SFmode;
17137 : 33 : break;
17138 : 88 : case E_V8DImode:
17139 : 88 : half_mode = V4DImode;
17140 : 88 : break;
17141 : 76 : case E_V8DFmode:
17142 : 76 : half_mode = V4DFmode;
17143 : 76 : break;
17144 : 0 : case E_V16HFmode:
17145 : 0 : half_mode = V8HFmode;
17146 : 0 : break;
17147 : 0 : case E_V16BFmode:
17148 : 0 : half_mode = V8BFmode;
17149 : 0 : break;
17150 : 187 : case E_V8SImode:
17151 : 187 : half_mode = V4SImode;
17152 : 187 : break;
17153 : 143 : case E_V8SFmode:
17154 : 143 : half_mode = V4SFmode;
17155 : 143 : break;
17156 : 296 : case E_V4DImode:
17157 : 296 : half_mode = V2DImode;
17158 : 296 : break;
17159 : 480 : case E_V4DFmode:
17160 : 480 : half_mode = V2DFmode;
17161 : 480 : break;
17162 : 5757 : case E_V4SImode:
17163 : 5757 : half_mode = V2SImode;
17164 : 5757 : break;
17165 : 1873 : case E_V4SFmode:
17166 : 1873 : half_mode = V2SFmode;
17167 : 1873 : break;
17168 : 68870 : case E_V2DImode:
17169 : 68870 : half_mode = DImode;
17170 : 68870 : break;
17171 : 27055 : case E_V2SImode:
17172 : 27055 : half_mode = SImode;
17173 : 27055 : break;
17174 : 3559 : case E_V2DFmode:
17175 : 3559 : half_mode = DFmode;
17176 : 3559 : break;
17177 : 4674 : case E_V2SFmode:
17178 : 4674 : half_mode = SFmode;
17179 : 4674 : break;
17180 : 0 : default:
17181 : 0 : gcc_unreachable ();
17182 : : }
17183 : :
17184 : 113173 : if (!register_operand (ops[1], half_mode))
17185 : 51265 : ops[1] = force_reg (half_mode, ops[1]);
17186 : 113173 : if (!register_operand (ops[0], half_mode))
17187 : 39811 : ops[0] = force_reg (half_mode, ops[0]);
17188 : 113173 : emit_insn (gen_rtx_SET (target, gen_rtx_VEC_CONCAT (mode, ops[0],
17189 : : ops[1])));
17190 : 113173 : break;
17191 : :
17192 : 7289 : case 4:
17193 : 7289 : switch (mode)
17194 : : {
17195 : : case E_V4DImode:
17196 : : half_mode = V2DImode;
17197 : : break;
17198 : 406 : case E_V4DFmode:
17199 : 406 : half_mode = V2DFmode;
17200 : 406 : break;
17201 : 4967 : case E_V4SImode:
17202 : 4967 : half_mode = V2SImode;
17203 : 4967 : break;
17204 : 1746 : case E_V4SFmode:
17205 : 1746 : half_mode = V2SFmode;
17206 : 1746 : break;
17207 : 0 : default:
17208 : 0 : gcc_unreachable ();
17209 : : }
17210 : 7289 : goto half;
17211 : :
17212 : 412 : case 8:
17213 : 412 : switch (mode)
17214 : : {
17215 : : case E_V8DImode:
17216 : : half_mode = V4DImode;
17217 : : break;
17218 : 76 : case E_V8DFmode:
17219 : 76 : half_mode = V4DFmode;
17220 : 76 : break;
17221 : 152 : case E_V8SImode:
17222 : 152 : half_mode = V4SImode;
17223 : 152 : break;
17224 : 137 : case E_V8SFmode:
17225 : 137 : half_mode = V4SFmode;
17226 : 137 : break;
17227 : 0 : default:
17228 : 0 : gcc_unreachable ();
17229 : : }
17230 : 412 : goto half;
17231 : :
17232 : 94 : case 16:
17233 : 94 : switch (mode)
17234 : : {
17235 : : case E_V16SImode:
17236 : : half_mode = V8SImode;
17237 : : break;
17238 : 33 : case E_V16SFmode:
17239 : 33 : half_mode = V8SFmode;
17240 : 33 : break;
17241 : 0 : default:
17242 : 0 : gcc_unreachable ();
17243 : : }
17244 : 94 : goto half;
17245 : :
17246 : 7795 : half:
17247 : : /* FIXME: We process inputs backward to help RA. PR 36222. */
17248 : 7795 : i = n - 1;
17249 : 23385 : for (j = 1; j != -1; j--)
17250 : : {
17251 : 15590 : half[j] = gen_reg_rtx (half_mode);
17252 : 15590 : switch (n >> 1)
17253 : : {
17254 : 14578 : case 2:
17255 : 14578 : v = gen_rtvec (2, ops[i-1], ops[i]);
17256 : 14578 : i -= 2;
17257 : 14578 : break;
17258 : 824 : case 4:
17259 : 824 : v = gen_rtvec (4, ops[i-3], ops[i-2], ops[i-1], ops[i]);
17260 : 824 : i -= 4;
17261 : 824 : break;
17262 : 188 : case 8:
17263 : 376 : v = gen_rtvec (8, ops[i-7], ops[i-6], ops[i-5], ops[i-4],
17264 : 188 : ops[i-3], ops[i-2], ops[i-1], ops[i]);
17265 : 188 : i -= 8;
17266 : 188 : break;
17267 : 0 : default:
17268 : 0 : gcc_unreachable ();
17269 : : }
17270 : 15590 : ix86_expand_vector_init (false, half[j],
17271 : : gen_rtx_PARALLEL (half_mode, v));
17272 : : }
17273 : :
17274 : 7795 : ix86_expand_vector_init_concat (mode, target, half, 2);
17275 : 7795 : break;
17276 : :
17277 : 0 : default:
17278 : 0 : gcc_unreachable ();
17279 : : }
17280 : 120968 : }
17281 : :
17282 : : /* A subroutine of ix86_expand_vector_init_general. Use vector
17283 : : interleave to handle the most general case: all values variable,
17284 : : and none identical. */
17285 : :
17286 : : static void
17287 : 3825 : ix86_expand_vector_init_interleave (machine_mode mode,
17288 : : rtx target, rtx *ops, int n)
17289 : : {
17290 : 3825 : machine_mode first_imode, second_imode, third_imode, inner_mode;
17291 : 3825 : int i, j;
17292 : 3825 : rtx op, op0, op1;
17293 : 3825 : rtx (*gen_load_even) (rtx, rtx, rtx);
17294 : 3825 : rtx (*gen_interleave_first_low) (rtx, rtx, rtx);
17295 : 3825 : rtx (*gen_interleave_second_low) (rtx, rtx, rtx);
17296 : :
17297 : 3825 : switch (mode)
17298 : : {
17299 : : case E_V8HFmode:
17300 : : gen_load_even = gen_vec_interleave_lowv8hf;
17301 : : gen_interleave_first_low = gen_vec_interleave_lowv4si;
17302 : : gen_interleave_second_low = gen_vec_interleave_lowv2di;
17303 : : inner_mode = HFmode;
17304 : : first_imode = V4SImode;
17305 : : second_imode = V2DImode;
17306 : : third_imode = VOIDmode;
17307 : : break;
17308 : 487 : case E_V8BFmode:
17309 : 487 : gen_load_even = gen_vec_interleave_lowv8bf;
17310 : 487 : gen_interleave_first_low = gen_vec_interleave_lowv4si;
17311 : 487 : gen_interleave_second_low = gen_vec_interleave_lowv2di;
17312 : 487 : inner_mode = BFmode;
17313 : 487 : first_imode = V4SImode;
17314 : 487 : second_imode = V2DImode;
17315 : 487 : third_imode = VOIDmode;
17316 : 487 : break;
17317 : 744 : case E_V8HImode:
17318 : 744 : gen_load_even = gen_vec_setv8hi;
17319 : 744 : gen_interleave_first_low = gen_vec_interleave_lowv4si;
17320 : 744 : gen_interleave_second_low = gen_vec_interleave_lowv2di;
17321 : 744 : inner_mode = HImode;
17322 : 744 : first_imode = V4SImode;
17323 : 744 : second_imode = V2DImode;
17324 : 744 : third_imode = VOIDmode;
17325 : 744 : break;
17326 : 368 : case E_V16QImode:
17327 : 368 : gen_load_even = gen_vec_setv16qi;
17328 : 368 : gen_interleave_first_low = gen_vec_interleave_lowv8hi;
17329 : 368 : gen_interleave_second_low = gen_vec_interleave_lowv4si;
17330 : 368 : inner_mode = QImode;
17331 : 368 : first_imode = V8HImode;
17332 : 368 : second_imode = V4SImode;
17333 : 368 : third_imode = V2DImode;
17334 : 368 : break;
17335 : 0 : default:
17336 : 0 : gcc_unreachable ();
17337 : : }
17338 : :
17339 : 20597 : for (i = 0; i < n; i++)
17340 : : {
17341 : 16772 : op = ops [i + i];
17342 : 16772 : if (inner_mode == HFmode || inner_mode == BFmode)
17343 : : {
17344 : 10852 : rtx even, odd;
17345 : : /* Use vpuncklwd to pack 2 HFmode or BFmode. */
17346 : 1948 : machine_mode vec_mode =
17347 : 10852 : (inner_mode == HFmode) ? V8HFmode : V8BFmode;
17348 : 10852 : op0 = gen_reg_rtx (vec_mode);
17349 : 10852 : even = lowpart_subreg (vec_mode,
17350 : : force_reg (inner_mode, op), inner_mode);
17351 : 10852 : odd = lowpart_subreg (vec_mode,
17352 : 10852 : force_reg (inner_mode, ops[i + i + 1]),
17353 : : inner_mode);
17354 : 10852 : emit_insn (gen_load_even (op0, even, odd));
17355 : : }
17356 : : else
17357 : : {
17358 : : /* Extend the odd elment to SImode using a paradoxical SUBREG. */
17359 : 5920 : op0 = gen_reg_rtx (SImode);
17360 : 5920 : emit_move_insn (op0, gen_lowpart (SImode, op));
17361 : :
17362 : : /* Insert the SImode value as low element of V4SImode vector. */
17363 : 5920 : op1 = gen_reg_rtx (V4SImode);
17364 : 5920 : op0 = gen_rtx_VEC_MERGE (V4SImode,
17365 : : gen_rtx_VEC_DUPLICATE (V4SImode,
17366 : : op0),
17367 : : CONST0_RTX (V4SImode),
17368 : : const1_rtx);
17369 : 5920 : emit_insn (gen_rtx_SET (op1, op0));
17370 : :
17371 : : /* Cast the V4SImode vector back to a vector in orignal mode. */
17372 : 5920 : op0 = gen_reg_rtx (mode);
17373 : 5920 : emit_move_insn (op0, gen_lowpart (mode, op1));
17374 : :
17375 : : /* Load even elements into the second position. */
17376 : 5920 : emit_insn (gen_load_even (op0,
17377 : : force_reg (inner_mode,
17378 : 5920 : ops[i + i + 1]),
17379 : : const1_rtx));
17380 : : }
17381 : :
17382 : : /* Cast vector to FIRST_IMODE vector. */
17383 : 16772 : ops[i] = gen_reg_rtx (first_imode);
17384 : 16772 : emit_move_insn (ops[i], gen_lowpart (first_imode, op0));
17385 : : }
17386 : :
17387 : : /* Interleave low FIRST_IMODE vectors. */
17388 : 12211 : for (i = j = 0; i < n; i += 2, j++)
17389 : : {
17390 : 8386 : op0 = gen_reg_rtx (first_imode);
17391 : 8386 : emit_insn (gen_interleave_first_low (op0, ops[i], ops[i + 1]));
17392 : :
17393 : : /* Cast FIRST_IMODE vector to SECOND_IMODE vector. */
17394 : 8386 : ops[j] = gen_reg_rtx (second_imode);
17395 : 8386 : emit_move_insn (ops[j], gen_lowpart (second_imode, op0));
17396 : : }
17397 : :
17398 : : /* Interleave low SECOND_IMODE vectors. */
17399 : 3825 : switch (second_imode)
17400 : : {
17401 : : case E_V4SImode:
17402 : 1104 : for (i = j = 0; i < n / 2; i += 2, j++)
17403 : : {
17404 : 736 : op0 = gen_reg_rtx (second_imode);
17405 : 736 : emit_insn (gen_interleave_second_low (op0, ops[i],
17406 : 736 : ops[i + 1]));
17407 : :
17408 : : /* Cast the SECOND_IMODE vector to the THIRD_IMODE
17409 : : vector. */
17410 : 736 : ops[j] = gen_reg_rtx (third_imode);
17411 : 736 : emit_move_insn (ops[j], gen_lowpart (third_imode, op0));
17412 : : }
17413 : : second_imode = V2DImode;
17414 : : gen_interleave_second_low = gen_vec_interleave_lowv2di;
17415 : : /* FALLTHRU */
17416 : :
17417 : 3825 : case E_V2DImode:
17418 : 3825 : op0 = gen_reg_rtx (second_imode);
17419 : 3825 : emit_insn (gen_interleave_second_low (op0, ops[0],
17420 : : ops[1]));
17421 : :
17422 : : /* Cast the SECOND_IMODE vector back to a vector on original
17423 : : mode. */
17424 : 3825 : emit_insn (gen_rtx_SET (target, gen_lowpart (mode, op0)));
17425 : 3825 : break;
17426 : :
17427 : : default:
17428 : : gcc_unreachable ();
17429 : : }
17430 : 3825 : }
17431 : :
17432 : : /* A subroutine of ix86_expand_vector_init. Handle the most general case:
17433 : : all values variable, and none identical. */
17434 : :
17435 : : static void
17436 : 122331 : ix86_expand_vector_init_general (bool mmx_ok, machine_mode mode,
17437 : : rtx target, rtx vals)
17438 : : {
17439 : 122331 : rtx ops[64], op0, op1, op2, op3, op4, op5;
17440 : 122331 : machine_mode half_mode = VOIDmode;
17441 : 122331 : machine_mode quarter_mode = VOIDmode;
17442 : 122331 : machine_mode int_inner_mode = VOIDmode;
17443 : 122331 : int n, i;
17444 : :
17445 : 122331 : switch (mode)
17446 : : {
17447 : 31729 : case E_V2SFmode:
17448 : 31729 : case E_V2SImode:
17449 : 31729 : if (!mmx_ok && !TARGET_SSE)
17450 : : break;
17451 : : /* FALLTHRU */
17452 : :
17453 : 111953 : case E_V16SImode:
17454 : 111953 : case E_V16SFmode:
17455 : 111953 : case E_V8DFmode:
17456 : 111953 : case E_V8DImode:
17457 : 111953 : case E_V8SFmode:
17458 : 111953 : case E_V8SImode:
17459 : 111953 : case E_V4DFmode:
17460 : 111953 : case E_V4DImode:
17461 : 111953 : case E_V4SFmode:
17462 : 111953 : case E_V4SImode:
17463 : 111953 : case E_V2DFmode:
17464 : 111953 : case E_V2DImode:
17465 : 111953 : n = GET_MODE_NUNITS (mode);
17466 : 354225 : for (i = 0; i < n; i++)
17467 : 242272 : ops[i] = XVECEXP (vals, 0, i);
17468 : 111953 : ix86_expand_vector_init_concat (mode, target, ops, n);
17469 : 225959 : return;
17470 : :
17471 : : case E_V2TImode:
17472 : 135 : for (i = 0; i < 2; i++)
17473 : 90 : ops[i] = gen_lowpart (V2DImode, XVECEXP (vals, 0, i));
17474 : 45 : op0 = gen_reg_rtx (V4DImode);
17475 : 45 : ix86_expand_vector_init_concat (V4DImode, op0, ops, 2);
17476 : 45 : emit_move_insn (target, gen_lowpart (GET_MODE (target), op0));
17477 : 45 : return;
17478 : :
17479 : : case E_V4TImode:
17480 : 195 : for (i = 0; i < 4; i++)
17481 : 156 : ops[i] = gen_lowpart (V2DImode, XVECEXP (vals, 0, i));
17482 : 39 : ops[4] = gen_reg_rtx (V4DImode);
17483 : 39 : ix86_expand_vector_init_concat (V4DImode, ops[4], ops, 2);
17484 : 39 : ops[5] = gen_reg_rtx (V4DImode);
17485 : 39 : ix86_expand_vector_init_concat (V4DImode, ops[5], ops + 2, 2);
17486 : 39 : op0 = gen_reg_rtx (V8DImode);
17487 : 39 : ix86_expand_vector_init_concat (V8DImode, op0, ops + 4, 2);
17488 : 39 : emit_move_insn (target, gen_lowpart (GET_MODE (target), op0));
17489 : 39 : return;
17490 : :
17491 : 68 : case E_V32QImode:
17492 : 68 : half_mode = V16QImode;
17493 : 68 : goto half;
17494 : :
17495 : 64 : case E_V16HImode:
17496 : 64 : half_mode = V8HImode;
17497 : 64 : goto half;
17498 : :
17499 : 237 : case E_V16HFmode:
17500 : 237 : half_mode = V8HFmode;
17501 : 237 : goto half;
17502 : :
17503 : 95 : case E_V16BFmode:
17504 : 95 : half_mode = V8BFmode;
17505 : 95 : goto half;
17506 : :
17507 : 464 : half:
17508 : 464 : n = GET_MODE_NUNITS (mode);
17509 : 8976 : for (i = 0; i < n; i++)
17510 : 8512 : ops[i] = XVECEXP (vals, 0, i);
17511 : 464 : op0 = gen_reg_rtx (half_mode);
17512 : 464 : op1 = gen_reg_rtx (half_mode);
17513 : 464 : ix86_expand_vector_init_interleave (half_mode, op0, ops,
17514 : : n >> 2);
17515 : 464 : ix86_expand_vector_init_interleave (half_mode, op1,
17516 : 464 : &ops [n >> 1], n >> 2);
17517 : 464 : emit_insn (gen_rtx_SET (target, gen_rtx_VEC_CONCAT (mode, op0, op1)));
17518 : 464 : return;
17519 : :
17520 : 55 : case E_V64QImode:
17521 : 55 : quarter_mode = V16QImode;
17522 : 55 : half_mode = V32QImode;
17523 : 55 : goto quarter;
17524 : :
17525 : 71 : case E_V32HImode:
17526 : 71 : quarter_mode = V8HImode;
17527 : 71 : half_mode = V16HImode;
17528 : 71 : goto quarter;
17529 : :
17530 : 287 : case E_V32HFmode:
17531 : 287 : quarter_mode = V8HFmode;
17532 : 287 : half_mode = V16HFmode;
17533 : 287 : goto quarter;
17534 : :
17535 : 51 : case E_V32BFmode:
17536 : 51 : quarter_mode = V8BFmode;
17537 : 51 : half_mode = V16BFmode;
17538 : 51 : goto quarter;
17539 : :
17540 : 464 : quarter:
17541 : 464 : n = GET_MODE_NUNITS (mode);
17542 : 17072 : for (i = 0; i < n; i++)
17543 : 16608 : ops[i] = XVECEXP (vals, 0, i);
17544 : 464 : op0 = gen_reg_rtx (quarter_mode);
17545 : 464 : op1 = gen_reg_rtx (quarter_mode);
17546 : 464 : op2 = gen_reg_rtx (quarter_mode);
17547 : 464 : op3 = gen_reg_rtx (quarter_mode);
17548 : 464 : op4 = gen_reg_rtx (half_mode);
17549 : 464 : op5 = gen_reg_rtx (half_mode);
17550 : 464 : ix86_expand_vector_init_interleave (quarter_mode, op0, ops,
17551 : : n >> 3);
17552 : 464 : ix86_expand_vector_init_interleave (quarter_mode, op1,
17553 : 464 : &ops [n >> 2], n >> 3);
17554 : 464 : ix86_expand_vector_init_interleave (quarter_mode, op2,
17555 : 464 : &ops [n >> 1], n >> 3);
17556 : 464 : ix86_expand_vector_init_interleave (quarter_mode, op3,
17557 : 464 : &ops [(n >> 1) | (n >> 2)], n >> 3);
17558 : 464 : emit_insn (gen_rtx_SET (op4, gen_rtx_VEC_CONCAT (half_mode, op0, op1)));
17559 : 464 : emit_insn (gen_rtx_SET (op5, gen_rtx_VEC_CONCAT (half_mode, op2, op3)));
17560 : 464 : emit_insn (gen_rtx_SET (target, gen_rtx_VEC_CONCAT (mode, op4, op5)));
17561 : 464 : return;
17562 : :
17563 : 264 : case E_V16QImode:
17564 : 264 : if (!TARGET_SSE4_1)
17565 : : break;
17566 : : /* FALLTHRU */
17567 : :
17568 : 468 : case E_V8HImode:
17569 : 468 : if (!TARGET_SSE2)
17570 : : break;
17571 : :
17572 : : /* Don't use ix86_expand_vector_init_interleave if we can't
17573 : : move from GPR to SSE register directly. */
17574 : 468 : if (!TARGET_INTER_UNIT_MOVES_TO_VEC)
17575 : : break;
17576 : : /* FALLTHRU */
17577 : :
17578 : 1041 : case E_V8HFmode:
17579 : 1041 : case E_V8BFmode:
17580 : :
17581 : 1041 : n = GET_MODE_NUNITS (mode);
17582 : 9465 : for (i = 0; i < n; i++)
17583 : 8424 : ops[i] = XVECEXP (vals, 0, i);
17584 : 1041 : ix86_expand_vector_init_interleave (mode, target, ops, n >> 1);
17585 : 1041 : return;
17586 : :
17587 : : case E_V4HFmode:
17588 : : case E_V4BFmode:
17589 : : case E_V2HFmode:
17590 : : case E_V2BFmode:
17591 : 8325 : int_inner_mode = HImode;
17592 : : break;
17593 : :
17594 : : case E_V4HImode:
17595 : : case E_V8QImode:
17596 : :
17597 : : case E_V2HImode:
17598 : : case E_V4QImode:
17599 : : break;
17600 : :
17601 : 0 : default:
17602 : 0 : gcc_unreachable ();
17603 : : }
17604 : :
17605 : 8325 : {
17606 : 8325 : int i, j, n_elts, n_words, n_elt_per_word;
17607 : 8325 : machine_mode tmp_mode, inner_mode;
17608 : 8325 : rtx words[4], shift;
17609 : :
17610 : 16807 : tmp_mode = (GET_MODE_SIZE (mode) < UNITS_PER_WORD) ? SImode : word_mode;
17611 : :
17612 : 8325 : inner_mode = GET_MODE_INNER (mode);
17613 : 8325 : n_elts = GET_MODE_NUNITS (mode);
17614 : 16650 : n_words = GET_MODE_SIZE (mode) / GET_MODE_SIZE (tmp_mode);
17615 : 8325 : n_elt_per_word = n_elts / n_words;
17616 : 8325 : shift = GEN_INT (GET_MODE_BITSIZE (inner_mode));
17617 : :
17618 : 16977 : for (i = 0; i < n_words; ++i)
17619 : : {
17620 : : rtx word = NULL_RTX;
17621 : :
17622 : 45284 : for (j = 0; j < n_elt_per_word; ++j)
17623 : : {
17624 : 36632 : rtx elt = XVECEXP (vals, 0, (i+1)*n_elt_per_word - j - 1);
17625 : 36632 : if (int_inner_mode != E_VOIDmode)
17626 : : {
17627 : 134 : gcc_assert (TARGET_SSE2 && int_inner_mode == HImode);
17628 : 134 : rtx tmp = gen_reg_rtx (int_inner_mode);
17629 : 134 : elt = lowpart_subreg (int_inner_mode,
17630 : : force_reg (inner_mode, elt),
17631 : : inner_mode);
17632 : 134 : emit_move_insn (tmp, elt);
17633 : 134 : elt = tmp;
17634 : : }
17635 : 36632 : elt = convert_modes (tmp_mode, inner_mode, elt, true);
17636 : :
17637 : 36632 : if (j == 0)
17638 : : word = elt;
17639 : : else
17640 : : {
17641 : 27980 : word = expand_simple_binop (tmp_mode, ASHIFT, word, shift,
17642 : : NULL_RTX, 1, OPTAB_LIB_WIDEN);
17643 : 27980 : word = expand_simple_binop (tmp_mode, IOR, word, elt,
17644 : : NULL_RTX, 1, OPTAB_LIB_WIDEN);
17645 : : }
17646 : : }
17647 : :
17648 : 8652 : words[i] = word;
17649 : : }
17650 : :
17651 : 8325 : if (n_words == 1)
17652 : 7998 : emit_move_insn (target, gen_lowpart (mode, words[0]));
17653 : 327 : else if (n_words == 2)
17654 : : {
17655 : 327 : gcc_assert (tmp_mode == DImode || tmp_mode == SImode);
17656 : 327 : machine_mode concat_mode = tmp_mode == DImode ? V2DImode : V2SImode;
17657 : 327 : rtx tmp = gen_reg_rtx (concat_mode);
17658 : 327 : vals = gen_rtx_PARALLEL (concat_mode, gen_rtvec_v (2, words));
17659 : 327 : ix86_expand_vector_init_general (mmx_ok, concat_mode, tmp, vals);
17660 : 327 : emit_move_insn (target, gen_lowpart (mode, tmp));
17661 : : }
17662 : 0 : else if (n_words == 4)
17663 : : {
17664 : 0 : rtx tmp = gen_reg_rtx (V4SImode);
17665 : 0 : gcc_assert (tmp_mode == SImode);
17666 : 0 : vals = gen_rtx_PARALLEL (V4SImode, gen_rtvec_v (4, words));
17667 : 0 : ix86_expand_vector_init_general (false, V4SImode, tmp, vals);
17668 : 0 : emit_move_insn (target, gen_lowpart (mode, tmp));
17669 : : }
17670 : : else
17671 : 0 : gcc_unreachable ();
17672 : : }
17673 : : }
17674 : :
17675 : : /* Initialize vector TARGET via VALS. Suppress the use of MMX
17676 : : instructions unless MMX_OK is true. */
17677 : :
17678 : : void
17679 : 132975 : ix86_expand_vector_init (bool mmx_ok, rtx target, rtx vals)
17680 : : {
17681 : 132975 : machine_mode mode = GET_MODE (target);
17682 : 132975 : machine_mode inner_mode = GET_MODE_INNER (mode);
17683 : 132975 : int n_elts = GET_MODE_NUNITS (mode);
17684 : 132975 : int n_var = 0, one_var = -1;
17685 : 132975 : bool all_same = true, all_const_zero = true;
17686 : 132975 : int i;
17687 : 132975 : rtx x;
17688 : :
17689 : : /* Handle first initialization from vector elts. */
17690 : 132975 : if (n_elts != XVECLEN (vals, 0))
17691 : : {
17692 : 1058 : rtx subtarget = target;
17693 : 1058 : x = XVECEXP (vals, 0, 0);
17694 : 2116 : gcc_assert (GET_MODE_INNER (GET_MODE (x)) == inner_mode);
17695 : 2116 : if (GET_MODE_NUNITS (GET_MODE (x)) * 2 == n_elts)
17696 : : {
17697 : 1058 : rtx ops[2] = { XVECEXP (vals, 0, 0), XVECEXP (vals, 0, 1) };
17698 : 1058 : if (inner_mode == QImode
17699 : 1058 : || inner_mode == HImode
17700 : 1058 : || inner_mode == TImode
17701 : : || inner_mode == HFmode
17702 : : || inner_mode == BFmode)
17703 : : {
17704 : 146 : unsigned int n_bits = n_elts * GET_MODE_SIZE (inner_mode);
17705 : 146 : scalar_mode elt_mode = inner_mode == TImode ? DImode : SImode;
17706 : 146 : n_bits /= GET_MODE_SIZE (elt_mode);
17707 : 146 : mode = mode_for_vector (elt_mode, n_bits).require ();
17708 : 146 : inner_mode = mode_for_vector (elt_mode, n_bits / 2).require ();
17709 : 146 : ops[0] = gen_lowpart (inner_mode, ops[0]);
17710 : 146 : ops[1] = gen_lowpart (inner_mode, ops[1]);
17711 : 146 : subtarget = gen_reg_rtx (mode);
17712 : : }
17713 : 1058 : ix86_expand_vector_init_concat (mode, subtarget, ops, 2);
17714 : 1058 : if (subtarget != target)
17715 : 146 : emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
17716 : 1058 : return;
17717 : : }
17718 : 0 : gcc_unreachable ();
17719 : : }
17720 : :
17721 : 479163 : for (i = 0; i < n_elts; ++i)
17722 : : {
17723 : 347246 : x = XVECEXP (vals, 0, i);
17724 : 674287 : if (!(CONST_SCALAR_INT_P (x)
17725 : 329750 : || CONST_DOUBLE_P (x)
17726 : : || CONST_FIXED_P (x)))
17727 : 327041 : n_var++, one_var = i;
17728 : 20205 : else if (x != CONST0_RTX (inner_mode))
17729 : 3207 : all_const_zero = false;
17730 : 347246 : if (i > 0 && !rtx_equal_p (x, XVECEXP (vals, 0, 0)))
17731 : : all_same = false;
17732 : : }
17733 : :
17734 : : /* Handle the zero vector as special case. */
17735 : 131917 : if (n_var == 0 && all_const_zero)
17736 : : {
17737 : 353 : emit_move_insn (target, CONST0_RTX (mode));
17738 : 353 : return;
17739 : : }
17740 : :
17741 : : /* If all values are identical, broadcast the value. */
17742 : 131564 : if (all_same
17743 : 138014 : && ix86_expand_vector_init_duplicate (mmx_ok, mode, target,
17744 : 6450 : XVECEXP (vals, 0, 0)))
17745 : : return;
17746 : :
17747 : : /* Constants are best loaded from the constant pool. */
17748 : 126041 : if (n_var == 0)
17749 : : {
17750 : 41 : emit_move_insn (target, gen_rtx_CONST_VECTOR (mode, XVEC (vals, 0)));
17751 : 41 : return;
17752 : : }
17753 : :
17754 : : /* Values where only one field is non-constant are best loaded from
17755 : : the pool and overwritten via move later. */
17756 : 126000 : if (n_var == 1)
17757 : : {
17758 : 12297 : if (all_const_zero
17759 : 23463 : && ix86_expand_vector_init_one_nonzero (mmx_ok, mode, target,
17760 : 11166 : XVECEXP (vals, 0, one_var),
17761 : : one_var))
17762 : : return;
17763 : :
17764 : 8509 : if (ix86_expand_vector_init_one_var (mmx_ok, mode, target, vals, one_var))
17765 : : return;
17766 : : }
17767 : :
17768 : 122004 : ix86_expand_vector_init_general (mmx_ok, mode, target, vals);
17769 : : }
17770 : :
17771 : : /* Implemented as
17772 : : V setg (V v, int idx, T val)
17773 : : {
17774 : : V idxv = (V){idx, idx, idx, idx, idx, idx, idx, idx};
17775 : : V valv = (V){val, val, val, val, val, val, val, val};
17776 : : V mask = ((V){0, 1, 2, 3, 4, 5, 6, 7} == idxv);
17777 : : v = (v & ~mask) | (valv & mask);
17778 : : return v;
17779 : : }. */
17780 : : void
17781 : 128 : ix86_expand_vector_set_var (rtx target, rtx val, rtx idx)
17782 : : {
17783 : 128 : rtx vec[64];
17784 : 128 : machine_mode mode = GET_MODE (target);
17785 : 128 : machine_mode cmp_mode = mode;
17786 : 128 : int n_elts = GET_MODE_NUNITS (mode);
17787 : 128 : rtx valv,idxv,constv,idx_tmp;
17788 : 128 : bool ok = false;
17789 : :
17790 : : /* 512-bits vector byte/word broadcast and comparison only available
17791 : : under TARGET_AVX512BW, break 512-bits vector into two 256-bits vector
17792 : : when without TARGET_AVX512BW. */
17793 : 128 : if ((mode == V32HImode || mode == V32HFmode || mode == V32BFmode
17794 : 122 : || mode == V64QImode)
17795 : 10 : && !TARGET_AVX512BW)
17796 : : {
17797 : 3 : gcc_assert (TARGET_AVX512F);
17798 : 3 : rtx vhi, vlo, idx_hi;
17799 : 3 : machine_mode half_mode;
17800 : 3 : rtx (*extract_hi)(rtx, rtx);
17801 : 3 : rtx (*extract_lo)(rtx, rtx);
17802 : :
17803 : 3 : if (mode == V32HImode)
17804 : : {
17805 : : half_mode = V16HImode;
17806 : : extract_hi = gen_vec_extract_hi_v32hi;
17807 : : extract_lo = gen_vec_extract_lo_v32hi;
17808 : : }
17809 : : else if (mode == V32HFmode)
17810 : : {
17811 : : half_mode = V16HFmode;
17812 : : extract_hi = gen_vec_extract_hi_v32hf;
17813 : : extract_lo = gen_vec_extract_lo_v32hf;
17814 : : }
17815 : : else if (mode == V32BFmode)
17816 : : {
17817 : : half_mode = V16BFmode;
17818 : : extract_hi = gen_vec_extract_hi_v32bf;
17819 : : extract_lo = gen_vec_extract_lo_v32bf;
17820 : : }
17821 : : else
17822 : : {
17823 : 3 : half_mode = V32QImode;
17824 : 3 : extract_hi = gen_vec_extract_hi_v64qi;
17825 : 3 : extract_lo = gen_vec_extract_lo_v64qi;
17826 : : }
17827 : :
17828 : 3 : vhi = gen_reg_rtx (half_mode);
17829 : 3 : vlo = gen_reg_rtx (half_mode);
17830 : 3 : idx_hi = gen_reg_rtx (GET_MODE (idx));
17831 : 3 : emit_insn (extract_hi (vhi, target));
17832 : 3 : emit_insn (extract_lo (vlo, target));
17833 : 3 : vec[0] = idx_hi;
17834 : 3 : vec[1] = idx;
17835 : 3 : vec[2] = GEN_INT (n_elts/2);
17836 : 3 : ix86_expand_binary_operator (MINUS, GET_MODE (idx), vec);
17837 : 3 : ix86_expand_vector_set_var (vhi, val, idx_hi);
17838 : 3 : ix86_expand_vector_set_var (vlo, val, idx);
17839 : 3 : emit_insn (gen_rtx_SET (target, gen_rtx_VEC_CONCAT (mode, vlo, vhi)));
17840 : 3 : return;
17841 : : }
17842 : :
17843 : 499 : if (FLOAT_MODE_P (GET_MODE_INNER (mode)))
17844 : : {
17845 : 42 : switch (mode)
17846 : : {
17847 : : case E_V2DFmode:
17848 : : cmp_mode = V2DImode;
17849 : : break;
17850 : 6 : case E_V4DFmode:
17851 : 6 : cmp_mode = V4DImode;
17852 : 6 : break;
17853 : 4 : case E_V8DFmode:
17854 : 4 : cmp_mode = V8DImode;
17855 : 4 : break;
17856 : 2 : case E_V2SFmode:
17857 : 2 : cmp_mode = V2SImode;
17858 : 2 : break;
17859 : 6 : case E_V4SFmode:
17860 : 6 : cmp_mode = V4SImode;
17861 : 6 : break;
17862 : 6 : case E_V8SFmode:
17863 : 6 : cmp_mode = V8SImode;
17864 : 6 : break;
17865 : 5 : case E_V16SFmode:
17866 : 5 : cmp_mode = V16SImode;
17867 : 5 : break;
17868 : 1 : case E_V2HFmode:
17869 : 1 : case E_V2BFmode:
17870 : 1 : cmp_mode = V2HImode;
17871 : 1 : break;
17872 : 1 : case E_V4HFmode:
17873 : 1 : case E_V4BFmode:
17874 : 1 : cmp_mode = V4HImode;
17875 : 1 : break;
17876 : : case E_V8HFmode:
17877 : 2 : cmp_mode = V8HImode;
17878 : : break;
17879 : : case E_V16HFmode:
17880 : 2 : cmp_mode = V16HImode;
17881 : : break;
17882 : : case E_V32HFmode:
17883 : 1 : cmp_mode = V32HImode;
17884 : : break;
17885 : : case E_V8BFmode:
17886 : 2 : cmp_mode = V8HImode;
17887 : : break;
17888 : : case E_V16BFmode:
17889 : 2 : cmp_mode = V16HImode;
17890 : : break;
17891 : : case E_V32BFmode:
17892 : 1 : cmp_mode = V32HImode;
17893 : : break;
17894 : 0 : default:
17895 : 0 : gcc_unreachable ();
17896 : : }
17897 : : }
17898 : :
17899 : 1599 : for (int i = 0; i != n_elts; i++)
17900 : 1474 : vec[i] = GEN_INT (i);
17901 : 125 : constv = gen_rtx_CONST_VECTOR (cmp_mode, gen_rtvec_v (n_elts, vec));
17902 : 125 : valv = gen_reg_rtx (mode);
17903 : 125 : idxv = gen_reg_rtx (cmp_mode);
17904 : 250 : idx_tmp = convert_to_mode (GET_MODE_INNER (cmp_mode), idx, 1);
17905 : :
17906 : 125 : ok = ix86_expand_vector_init_duplicate (TARGET_MMX_WITH_SSE,
17907 : : mode, valv, val);
17908 : 125 : gcc_assert (ok);
17909 : 125 : ok = ix86_expand_vector_init_duplicate (TARGET_MMX_WITH_SSE,
17910 : : cmp_mode, idxv, idx_tmp);
17911 : 125 : gcc_assert (ok);
17912 : 125 : vec[0] = target;
17913 : 125 : vec[1] = valv;
17914 : 125 : vec[2] = target;
17915 : 125 : vec[3] = gen_rtx_EQ (mode, idxv, constv);
17916 : 125 : vec[4] = idxv;
17917 : 125 : vec[5] = constv;
17918 : 125 : ok = ix86_expand_int_vcond (vec);
17919 : 125 : gcc_assert (ok);
17920 : : }
17921 : :
17922 : : void
17923 : 7575 : ix86_expand_vector_set (bool mmx_ok, rtx target, rtx val, int elt)
17924 : : {
17925 : 7575 : machine_mode mode = GET_MODE (target);
17926 : 7575 : machine_mode inner_mode = GET_MODE_INNER (mode);
17927 : 7575 : machine_mode half_mode;
17928 : 7575 : bool use_vec_merge = false;
17929 : 7575 : bool blendm_const = false;
17930 : 7575 : rtx tmp;
17931 : 7575 : static rtx (*gen_extract[8][2]) (rtx, rtx)
17932 : : = {
17933 : : { gen_vec_extract_lo_v32qi, gen_vec_extract_hi_v32qi },
17934 : : { gen_vec_extract_lo_v16hi, gen_vec_extract_hi_v16hi },
17935 : : { gen_vec_extract_lo_v8si, gen_vec_extract_hi_v8si },
17936 : : { gen_vec_extract_lo_v4di, gen_vec_extract_hi_v4di },
17937 : : { gen_vec_extract_lo_v8sf, gen_vec_extract_hi_v8sf },
17938 : : { gen_vec_extract_lo_v4df, gen_vec_extract_hi_v4df },
17939 : : { gen_vec_extract_lo_v16hf, gen_vec_extract_hi_v16hf },
17940 : : { gen_vec_extract_lo_v16bf, gen_vec_extract_hi_v16bf }
17941 : : };
17942 : 7575 : static rtx (*gen_insert[8][2]) (rtx, rtx, rtx)
17943 : : = {
17944 : : { gen_vec_set_lo_v32qi, gen_vec_set_hi_v32qi },
17945 : : { gen_vec_set_lo_v16hi, gen_vec_set_hi_v16hi },
17946 : : { gen_vec_set_lo_v8si, gen_vec_set_hi_v8si },
17947 : : { gen_vec_set_lo_v4di, gen_vec_set_hi_v4di },
17948 : : { gen_vec_set_lo_v8sf, gen_vec_set_hi_v8sf },
17949 : : { gen_vec_set_lo_v4df, gen_vec_set_hi_v4df },
17950 : : { gen_vec_set_lo_v16hf, gen_vec_set_hi_v16hf },
17951 : : { gen_vec_set_lo_v16bf, gen_vec_set_hi_v16bf },
17952 : : };
17953 : 7575 : int i, j, n;
17954 : 7575 : machine_mode mmode = VOIDmode;
17955 : 7575 : rtx (*gen_blendm) (rtx, rtx, rtx, rtx);
17956 : :
17957 : 7575 : switch (mode)
17958 : : {
17959 : 163 : case E_V2SImode:
17960 : 163 : use_vec_merge = TARGET_MMX_WITH_SSE && TARGET_SSE4_1;
17961 : : if (use_vec_merge)
17962 : : break;
17963 : : /* FALLTHRU */
17964 : :
17965 : 146 : case E_V2SFmode:
17966 : 146 : if (mmx_ok)
17967 : : {
17968 : 146 : tmp = gen_reg_rtx (GET_MODE_INNER (mode));
17969 : 146 : ix86_expand_vector_extract (true, tmp, target, 1 - elt);
17970 : 146 : if (elt == 0)
17971 : 3 : tmp = gen_rtx_VEC_CONCAT (mode, val, tmp);
17972 : : else
17973 : 143 : tmp = gen_rtx_VEC_CONCAT (mode, tmp, val);
17974 : 146 : emit_insn (gen_rtx_SET (target, tmp));
17975 : 146 : return;
17976 : : }
17977 : : break;
17978 : :
17979 : 230 : case E_V2DImode:
17980 : 230 : use_vec_merge = TARGET_SSE4_1 && TARGET_64BIT;
17981 : 88 : if (use_vec_merge)
17982 : : break;
17983 : :
17984 : 88 : tmp = gen_reg_rtx (GET_MODE_INNER (mode));
17985 : 88 : ix86_expand_vector_extract (false, tmp, target, 1 - elt);
17986 : 88 : if (elt == 0)
17987 : 77 : tmp = gen_rtx_VEC_CONCAT (mode, val, tmp);
17988 : : else
17989 : 11 : tmp = gen_rtx_VEC_CONCAT (mode, tmp, val);
17990 : 88 : emit_insn (gen_rtx_SET (target, tmp));
17991 : 88 : return;
17992 : :
17993 : 148 : case E_V2DFmode:
17994 : : /* NB: For ELT == 0, use standard scalar operation patterns which
17995 : : preserve the rest of the vector for combiner:
17996 : :
17997 : : (vec_merge:V2DF
17998 : : (vec_duplicate:V2DF (reg:DF))
17999 : : (reg:V2DF)
18000 : : (const_int 1))
18001 : : */
18002 : 148 : if (elt == 0)
18003 : 61 : goto do_vec_merge;
18004 : :
18005 : 87 : {
18006 : 87 : rtx op0, op1;
18007 : :
18008 : : /* For the two element vectors, we implement a VEC_CONCAT with
18009 : : the extraction of the other element. */
18010 : :
18011 : 87 : tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (1, GEN_INT (1 - elt)));
18012 : 87 : tmp = gen_rtx_VEC_SELECT (inner_mode, target, tmp);
18013 : :
18014 : 87 : if (elt == 0)
18015 : : op0 = val, op1 = tmp;
18016 : : else
18017 : 87 : op0 = tmp, op1 = val;
18018 : :
18019 : 87 : tmp = gen_rtx_VEC_CONCAT (mode, op0, op1);
18020 : 87 : emit_insn (gen_rtx_SET (target, tmp));
18021 : : }
18022 : 87 : return;
18023 : :
18024 : 153 : case E_V4SFmode:
18025 : 153 : use_vec_merge = TARGET_SSE4_1;
18026 : 153 : if (use_vec_merge)
18027 : : break;
18028 : :
18029 : 62 : switch (elt)
18030 : : {
18031 : : case 0:
18032 : : use_vec_merge = true;
18033 : : break;
18034 : :
18035 : 1 : case 1:
18036 : : /* tmp = target = A B C D */
18037 : 1 : tmp = copy_to_reg (target);
18038 : : /* target = A A B B */
18039 : 1 : emit_insn (gen_vec_interleave_lowv4sf (target, target, target));
18040 : : /* target = X A B B */
18041 : 1 : ix86_expand_vector_set (false, target, val, 0);
18042 : : /* target = A X C D */
18043 : 1 : emit_insn (gen_sse_shufps_v4sf (target, target, tmp,
18044 : : const1_rtx, const0_rtx,
18045 : : GEN_INT (2+4), GEN_INT (3+4)));
18046 : 1 : return;
18047 : :
18048 : 0 : case 2:
18049 : : /* tmp = target = A B C D */
18050 : 0 : tmp = copy_to_reg (target);
18051 : : /* tmp = X B C D */
18052 : 0 : ix86_expand_vector_set (false, tmp, val, 0);
18053 : : /* target = A B X D */
18054 : 0 : emit_insn (gen_sse_shufps_v4sf (target, target, tmp,
18055 : : const0_rtx, const1_rtx,
18056 : : GEN_INT (0+4), GEN_INT (3+4)));
18057 : 0 : return;
18058 : :
18059 : 4 : case 3:
18060 : : /* tmp = target = A B C D */
18061 : 4 : tmp = copy_to_reg (target);
18062 : : /* tmp = X B C D */
18063 : 4 : ix86_expand_vector_set (false, tmp, val, 0);
18064 : : /* target = A B X D */
18065 : 4 : emit_insn (gen_sse_shufps_v4sf (target, target, tmp,
18066 : : const0_rtx, const1_rtx,
18067 : : GEN_INT (2+4), GEN_INT (0+4)));
18068 : 4 : return;
18069 : :
18070 : 0 : default:
18071 : 0 : gcc_unreachable ();
18072 : : }
18073 : : break;
18074 : :
18075 : 375 : case E_V4SImode:
18076 : 375 : use_vec_merge = TARGET_SSE4_1;
18077 : 375 : if (use_vec_merge)
18078 : : break;
18079 : :
18080 : : /* Element 0 handled by vec_merge below. */
18081 : 229 : if (elt == 0)
18082 : : {
18083 : : use_vec_merge = true;
18084 : : break;
18085 : : }
18086 : :
18087 : 74 : if (TARGET_SSE2)
18088 : : {
18089 : : /* With SSE2, use integer shuffles to swap element 0 and ELT,
18090 : : store into element 0, then shuffle them back. */
18091 : :
18092 : 74 : rtx order[4];
18093 : :
18094 : 74 : order[0] = GEN_INT (elt);
18095 : 74 : order[1] = const1_rtx;
18096 : 74 : order[2] = const2_rtx;
18097 : 74 : order[3] = GEN_INT (3);
18098 : 74 : order[elt] = const0_rtx;
18099 : :
18100 : 74 : emit_insn (gen_sse2_pshufd_1 (target, target, order[0],
18101 : : order[1], order[2], order[3]));
18102 : :
18103 : 74 : ix86_expand_vector_set (false, target, val, 0);
18104 : :
18105 : 74 : emit_insn (gen_sse2_pshufd_1 (target, target, order[0],
18106 : : order[1], order[2], order[3]));
18107 : : }
18108 : : else
18109 : : {
18110 : : /* For SSE1, we have to reuse the V4SF code. */
18111 : 0 : rtx t = gen_reg_rtx (V4SFmode);
18112 : 0 : emit_move_insn (t, gen_lowpart (V4SFmode, target));
18113 : 0 : ix86_expand_vector_set (false, t, gen_lowpart (SFmode, val), elt);
18114 : 0 : emit_move_insn (target, gen_lowpart (mode, t));
18115 : : }
18116 : : return;
18117 : :
18118 : 3292 : case E_V8HImode:
18119 : 3292 : case E_V8HFmode:
18120 : 3292 : case E_V8BFmode:
18121 : 3292 : case E_V2HImode:
18122 : 3292 : case E_V2HFmode:
18123 : 3292 : case E_V2BFmode:
18124 : 3292 : use_vec_merge = TARGET_SSE2;
18125 : 3292 : break;
18126 : 49 : case E_V4HImode:
18127 : 49 : case E_V4HFmode:
18128 : 49 : case E_V4BFmode:
18129 : 49 : use_vec_merge = mmx_ok && (TARGET_SSE || TARGET_3DNOW_A);
18130 : : break;
18131 : :
18132 : 3019 : case E_V16QImode:
18133 : 3019 : case E_V4QImode:
18134 : 3019 : use_vec_merge = TARGET_SSE4_1;
18135 : 3019 : break;
18136 : :
18137 : 5 : case E_V8QImode:
18138 : 5 : use_vec_merge = TARGET_MMX_WITH_SSE && TARGET_SSE4_1;
18139 : : break;
18140 : :
18141 : 3 : case E_V32QImode:
18142 : 3 : half_mode = V16QImode;
18143 : 3 : j = 0;
18144 : 3 : n = 16;
18145 : 3 : goto half;
18146 : :
18147 : 17 : case E_V16HFmode:
18148 : 17 : case E_V16BFmode:
18149 : : /* For ELT == 0, vec_setv8hf_0 can save 1 vpbroadcastw. */
18150 : 17 : if (TARGET_AVX2 && elt != 0)
18151 : : {
18152 : 12 : mmode = SImode;
18153 : 12 : gen_blendm = ((mode == E_V16HFmode) ? gen_avx2_pblendph_1
18154 : : : gen_avx2_pblendbf_1);
18155 : : blendm_const = true;
18156 : : break;
18157 : : }
18158 : : else
18159 : : {
18160 : 5 : half_mode = ((mode == E_V16HFmode) ? V8HFmode : V8BFmode);
18161 : 3 : j = ((mode == E_V16HFmode) ? 6 : 7);
18162 : 5 : n = 8;
18163 : 5 : goto half;
18164 : : }
18165 : :
18166 : 5 : case E_V16HImode:
18167 : 5 : half_mode = V8HImode;
18168 : 5 : j = 1;
18169 : 5 : n = 8;
18170 : 5 : goto half;
18171 : :
18172 : 13 : case E_V8SImode:
18173 : 13 : half_mode = V4SImode;
18174 : 13 : j = 2;
18175 : 13 : n = 4;
18176 : 13 : goto half;
18177 : :
18178 : 15 : case E_V4DImode:
18179 : 15 : half_mode = V2DImode;
18180 : 15 : j = 3;
18181 : 15 : n = 2;
18182 : 15 : goto half;
18183 : :
18184 : 4 : case E_V8SFmode:
18185 : 4 : half_mode = V4SFmode;
18186 : 4 : j = 4;
18187 : 4 : n = 4;
18188 : 4 : goto half;
18189 : :
18190 : 6 : case E_V4DFmode:
18191 : 6 : half_mode = V2DFmode;
18192 : 6 : j = 5;
18193 : 6 : n = 2;
18194 : 6 : goto half;
18195 : :
18196 : 51 : half:
18197 : : /* Compute offset. */
18198 : 51 : i = elt / n;
18199 : 51 : elt %= n;
18200 : :
18201 : 51 : gcc_assert (i <= 1);
18202 : :
18203 : : /* Extract the half. */
18204 : 51 : tmp = gen_reg_rtx (half_mode);
18205 : 51 : emit_insn (gen_extract[j][i] (tmp, target));
18206 : :
18207 : : /* Put val in tmp at elt. */
18208 : 51 : ix86_expand_vector_set (false, tmp, val, elt);
18209 : :
18210 : : /* Put it back. */
18211 : 51 : emit_insn (gen_insert[j][i] (target, target, tmp));
18212 : 51 : return;
18213 : :
18214 : 8 : case E_V8DFmode:
18215 : 8 : if (TARGET_AVX512F)
18216 : : {
18217 : : mmode = QImode;
18218 : : gen_blendm = gen_avx512f_blendmv8df;
18219 : : }
18220 : : break;
18221 : :
18222 : 6 : case E_V8DImode:
18223 : 6 : if (TARGET_AVX512F)
18224 : : {
18225 : : mmode = QImode;
18226 : : gen_blendm = gen_avx512f_blendmv8di;
18227 : : }
18228 : : break;
18229 : :
18230 : 0 : case E_V16SFmode:
18231 : 0 : if (TARGET_AVX512F)
18232 : : {
18233 : : mmode = HImode;
18234 : : gen_blendm = gen_avx512f_blendmv16sf;
18235 : : }
18236 : : break;
18237 : :
18238 : 0 : case E_V16SImode:
18239 : 0 : if (TARGET_AVX512F)
18240 : : {
18241 : : mmode = HImode;
18242 : : gen_blendm = gen_avx512f_blendmv16si;
18243 : : }
18244 : : break;
18245 : :
18246 : 12 : case E_V32HFmode:
18247 : 12 : if (TARGET_AVX512BW)
18248 : : {
18249 : : mmode = SImode;
18250 : : gen_blendm = gen_avx512bw_blendmv32hf;
18251 : : }
18252 : : break;
18253 : 12 : case E_V32BFmode:
18254 : 12 : if (TARGET_AVX512BW)
18255 : : {
18256 : : mmode = SImode;
18257 : : gen_blendm = gen_avx512bw_blendmv32bf;
18258 : : }
18259 : : break;
18260 : 11 : case E_V32HImode:
18261 : 11 : if (TARGET_AVX512BW)
18262 : : {
18263 : : mmode = SImode;
18264 : : gen_blendm = gen_avx512bw_blendmv32hi;
18265 : : }
18266 : 7 : else if (TARGET_AVX512F)
18267 : : {
18268 : 7 : half_mode = E_V8HImode;
18269 : 7 : n = 8;
18270 : 7 : goto quarter;
18271 : : }
18272 : : break;
18273 : :
18274 : 12 : case E_V64QImode:
18275 : 12 : if (TARGET_AVX512BW)
18276 : : {
18277 : : mmode = DImode;
18278 : : gen_blendm = gen_avx512bw_blendmv64qi;
18279 : : }
18280 : 6 : else if (TARGET_AVX512F)
18281 : : {
18282 : 6 : half_mode = E_V16QImode;
18283 : 6 : n = 16;
18284 : 6 : goto quarter;
18285 : : }
18286 : : break;
18287 : :
18288 : 13 : quarter:
18289 : : /* Compute offset. */
18290 : 13 : i = elt / n;
18291 : 13 : elt %= n;
18292 : :
18293 : 13 : gcc_assert (i <= 3);
18294 : :
18295 : 13 : {
18296 : : /* Extract the quarter. */
18297 : 13 : tmp = gen_reg_rtx (V4SImode);
18298 : 13 : rtx tmp2 = gen_lowpart (V16SImode, target);
18299 : 13 : rtx mask = gen_reg_rtx (QImode);
18300 : :
18301 : 13 : emit_move_insn (mask, constm1_rtx);
18302 : 13 : emit_insn (gen_avx512f_vextracti32x4_mask (tmp, tmp2, GEN_INT (i),
18303 : : tmp, mask));
18304 : :
18305 : 13 : tmp2 = gen_reg_rtx (half_mode);
18306 : 13 : emit_move_insn (tmp2, gen_lowpart (half_mode, tmp));
18307 : 13 : tmp = tmp2;
18308 : :
18309 : : /* Put val in tmp at elt. */
18310 : 13 : ix86_expand_vector_set (false, tmp, val, elt);
18311 : :
18312 : : /* Put it back. */
18313 : 13 : tmp2 = gen_reg_rtx (V16SImode);
18314 : 13 : rtx tmp3 = gen_lowpart (V16SImode, target);
18315 : 13 : mask = gen_reg_rtx (HImode);
18316 : 13 : emit_move_insn (mask, constm1_rtx);
18317 : 13 : tmp = gen_lowpart (V4SImode, tmp);
18318 : 13 : emit_insn (gen_avx512f_vinserti32x4_mask (tmp2, tmp3, tmp, GEN_INT (i),
18319 : : tmp3, mask));
18320 : 13 : emit_move_insn (target, gen_lowpart (mode, tmp2));
18321 : : }
18322 : 13 : return;
18323 : :
18324 : : default:
18325 : : break;
18326 : : }
18327 : :
18328 : 6311 : if (mmode != VOIDmode)
18329 : : {
18330 : 54 : tmp = gen_reg_rtx (mode);
18331 : 54 : emit_insn (gen_rtx_SET (tmp, gen_rtx_VEC_DUPLICATE (mode, val)));
18332 : 54 : rtx merge_mask = gen_int_mode (HOST_WIDE_INT_1U << elt, mmode);
18333 : : /* The avx512*_blendm<mode> expanders have different operand order
18334 : : from VEC_MERGE. In VEC_MERGE, the first input operand is used for
18335 : : elements where the mask is set and second input operand otherwise,
18336 : : in {sse,avx}*_*blend* the first input operand is used for elements
18337 : : where the mask is clear and second input operand otherwise. */
18338 : 54 : if (!blendm_const)
18339 : 42 : merge_mask = force_reg (mmode, merge_mask);
18340 : 54 : emit_insn (gen_blendm (target, target, tmp, merge_mask));
18341 : : }
18342 : 6996 : else if (use_vec_merge)
18343 : : {
18344 : 6986 : do_vec_merge:
18345 : 7047 : if (!nonimmediate_operand (val, inner_mode))
18346 : 1 : val = force_reg (inner_mode, val);
18347 : 7047 : tmp = gen_rtx_VEC_DUPLICATE (mode, val);
18348 : 7047 : tmp = gen_rtx_VEC_MERGE (mode, tmp, target,
18349 : : GEN_INT (HOST_WIDE_INT_1U << elt));
18350 : 7047 : emit_insn (gen_rtx_SET (target, tmp));
18351 : : }
18352 : : else
18353 : : {
18354 : 20 : rtx mem = assign_stack_temp (mode, GET_MODE_SIZE (mode));
18355 : :
18356 : 10 : emit_move_insn (mem, target);
18357 : :
18358 : 20 : tmp = adjust_address (mem, inner_mode, elt * GET_MODE_SIZE (inner_mode));
18359 : 10 : emit_move_insn (tmp, val);
18360 : :
18361 : 10 : emit_move_insn (target, mem);
18362 : : }
18363 : : }
18364 : :
18365 : : void
18366 : 103195 : ix86_expand_vector_extract (bool mmx_ok, rtx target, rtx vec, int elt)
18367 : : {
18368 : 103195 : machine_mode mode = GET_MODE (vec);
18369 : 103195 : machine_mode inner_mode = GET_MODE_INNER (mode);
18370 : 103195 : bool use_vec_extr = false;
18371 : 103195 : rtx tmp;
18372 : :
18373 : 103195 : switch (mode)
18374 : : {
18375 : 8722 : case E_V2SImode:
18376 : 8722 : use_vec_extr = TARGET_MMX_WITH_SSE && TARGET_SSE4_1;
18377 : : if (use_vec_extr)
18378 : : break;
18379 : : /* FALLTHRU */
18380 : :
18381 : 9547 : case E_V2SFmode:
18382 : 9547 : if (!mmx_ok)
18383 : : break;
18384 : : /* FALLTHRU */
18385 : :
18386 : : case E_V2DFmode:
18387 : : case E_V2DImode:
18388 : : case E_V2TImode:
18389 : : case E_V4TImode:
18390 : : use_vec_extr = true;
18391 : : break;
18392 : :
18393 : 7104 : case E_V4SFmode:
18394 : 7104 : use_vec_extr = TARGET_SSE4_1;
18395 : 7104 : if (use_vec_extr)
18396 : : break;
18397 : :
18398 : 3995 : switch (elt)
18399 : : {
18400 : : case 0:
18401 : : tmp = vec;
18402 : : break;
18403 : :
18404 : 1652 : case 1:
18405 : 1652 : case 3:
18406 : 1652 : tmp = gen_reg_rtx (mode);
18407 : 1652 : emit_insn (gen_sse_shufps_v4sf (tmp, vec, vec,
18408 : : GEN_INT (elt), GEN_INT (elt),
18409 : 1652 : GEN_INT (elt+4), GEN_INT (elt+4)));
18410 : 1652 : break;
18411 : :
18412 : 923 : case 2:
18413 : 923 : tmp = gen_reg_rtx (mode);
18414 : 923 : emit_insn (gen_vec_interleave_highv4sf (tmp, vec, vec));
18415 : 923 : break;
18416 : :
18417 : 0 : default:
18418 : 0 : gcc_unreachable ();
18419 : : }
18420 : : vec = tmp;
18421 : : use_vec_extr = true;
18422 : : elt = 0;
18423 : : break;
18424 : :
18425 : 23137 : case E_V4SImode:
18426 : 23137 : use_vec_extr = TARGET_SSE4_1;
18427 : 23137 : if (use_vec_extr)
18428 : : break;
18429 : :
18430 : 16361 : if (TARGET_SSE2)
18431 : : {
18432 : 16357 : switch (elt)
18433 : : {
18434 : : case 0:
18435 : : tmp = vec;
18436 : : break;
18437 : :
18438 : 5298 : case 1:
18439 : 5298 : case 3:
18440 : 5298 : tmp = gen_reg_rtx (mode);
18441 : 5298 : emit_insn (gen_sse2_pshufd_1 (tmp, vec,
18442 : : GEN_INT (elt), GEN_INT (elt),
18443 : : GEN_INT (elt), GEN_INT (elt)));
18444 : 5298 : break;
18445 : :
18446 : 2590 : case 2:
18447 : 2590 : tmp = gen_reg_rtx (mode);
18448 : 2590 : emit_insn (gen_vec_interleave_highv4si (tmp, vec, vec));
18449 : 2590 : break;
18450 : :
18451 : 0 : default:
18452 : 0 : gcc_unreachable ();
18453 : : }
18454 : : vec = tmp;
18455 : : use_vec_extr = true;
18456 : : elt = 0;
18457 : : }
18458 : : else
18459 : : {
18460 : : /* For SSE1, we have to reuse the V4SF code. */
18461 : 4 : ix86_expand_vector_extract (false, gen_lowpart (SFmode, target),
18462 : 4 : gen_lowpart (V4SFmode, vec), elt);
18463 : 4 : return;
18464 : : }
18465 : : break;
18466 : :
18467 : 6136 : case E_V8HImode:
18468 : 6136 : case E_V8HFmode:
18469 : 6136 : case E_V8BFmode:
18470 : 6136 : case E_V2HImode:
18471 : 6136 : case E_V2HFmode:
18472 : 6136 : case E_V2BFmode:
18473 : 6136 : use_vec_extr = TARGET_SSE2;
18474 : 6136 : break;
18475 : 796 : case E_V4HImode:
18476 : 796 : case E_V4HFmode:
18477 : 796 : case E_V4BFmode:
18478 : 796 : use_vec_extr = mmx_ok && (TARGET_SSE || TARGET_3DNOW_A);
18479 : : break;
18480 : :
18481 : 7244 : case E_V16QImode:
18482 : 7244 : use_vec_extr = TARGET_SSE4_1;
18483 : 7244 : if (!use_vec_extr
18484 : 5511 : && TARGET_SSE2
18485 : 5511 : && elt == 0
18486 : 10962 : && (optimize_insn_for_size_p () || TARGET_INTER_UNIT_MOVES_FROM_VEC))
18487 : : {
18488 : 3717 : tmp = gen_reg_rtx (SImode);
18489 : 3717 : ix86_expand_vector_extract (false, tmp, gen_lowpart (V4SImode, vec),
18490 : : 0);
18491 : 3717 : emit_insn (gen_rtx_SET (target, gen_lowpart (QImode, tmp)));
18492 : 3717 : return;
18493 : : }
18494 : : break;
18495 : 48 : case E_V4QImode:
18496 : 48 : use_vec_extr = TARGET_SSE4_1;
18497 : 48 : break;
18498 : :
18499 : 244 : case E_V8SFmode:
18500 : 244 : if (TARGET_AVX)
18501 : : {
18502 : 244 : tmp = gen_reg_rtx (V4SFmode);
18503 : 244 : if (elt < 4)
18504 : 118 : emit_insn (gen_vec_extract_lo_v8sf (tmp, vec));
18505 : : else
18506 : 126 : emit_insn (gen_vec_extract_hi_v8sf (tmp, vec));
18507 : 244 : ix86_expand_vector_extract (false, target, tmp, elt & 3);
18508 : 244 : return;
18509 : : }
18510 : : break;
18511 : :
18512 : 335 : case E_V4DFmode:
18513 : 335 : if (TARGET_AVX)
18514 : : {
18515 : 335 : tmp = gen_reg_rtx (V2DFmode);
18516 : 335 : if (elt < 2)
18517 : 183 : emit_insn (gen_vec_extract_lo_v4df (tmp, vec));
18518 : : else
18519 : 152 : emit_insn (gen_vec_extract_hi_v4df (tmp, vec));
18520 : 335 : ix86_expand_vector_extract (false, target, tmp, elt & 1);
18521 : 335 : return;
18522 : : }
18523 : : break;
18524 : :
18525 : 190 : case E_V32QImode:
18526 : 190 : if (TARGET_AVX)
18527 : : {
18528 : 190 : tmp = gen_reg_rtx (V16QImode);
18529 : 190 : if (elt < 16)
18530 : 99 : emit_insn (gen_vec_extract_lo_v32qi (tmp, vec));
18531 : : else
18532 : 91 : emit_insn (gen_vec_extract_hi_v32qi (tmp, vec));
18533 : 190 : ix86_expand_vector_extract (false, target, tmp, elt & 15);
18534 : 190 : return;
18535 : : }
18536 : : break;
18537 : :
18538 : 586 : case E_V16HImode:
18539 : 586 : if (TARGET_AVX)
18540 : : {
18541 : 586 : tmp = gen_reg_rtx (V8HImode);
18542 : 586 : if (elt < 8)
18543 : 290 : emit_insn (gen_vec_extract_lo_v16hi (tmp, vec));
18544 : : else
18545 : 296 : emit_insn (gen_vec_extract_hi_v16hi (tmp, vec));
18546 : 586 : ix86_expand_vector_extract (false, target, tmp, elt & 7);
18547 : 586 : return;
18548 : : }
18549 : : break;
18550 : :
18551 : 1485 : case E_V8SImode:
18552 : 1485 : if (TARGET_AVX)
18553 : : {
18554 : 1485 : tmp = gen_reg_rtx (V4SImode);
18555 : 1485 : if (elt < 4)
18556 : 1021 : emit_insn (gen_vec_extract_lo_v8si (tmp, vec));
18557 : : else
18558 : 464 : emit_insn (gen_vec_extract_hi_v8si (tmp, vec));
18559 : 1485 : ix86_expand_vector_extract (false, target, tmp, elt & 3);
18560 : 1485 : return;
18561 : : }
18562 : : break;
18563 : :
18564 : 1447 : case E_V4DImode:
18565 : 1447 : if (TARGET_AVX)
18566 : : {
18567 : 1447 : tmp = gen_reg_rtx (V2DImode);
18568 : 1447 : if (elt < 2)
18569 : 764 : emit_insn (gen_vec_extract_lo_v4di (tmp, vec));
18570 : : else
18571 : 683 : emit_insn (gen_vec_extract_hi_v4di (tmp, vec));
18572 : 1447 : ix86_expand_vector_extract (false, target, tmp, elt & 1);
18573 : 1447 : return;
18574 : : }
18575 : : break;
18576 : :
18577 : 10 : case E_V32HImode:
18578 : 10 : if (TARGET_AVX512BW)
18579 : : {
18580 : 10 : tmp = gen_reg_rtx (V16HImode);
18581 : 10 : if (elt < 16)
18582 : 5 : emit_insn (gen_vec_extract_lo_v32hi (tmp, vec));
18583 : : else
18584 : 5 : emit_insn (gen_vec_extract_hi_v32hi (tmp, vec));
18585 : 10 : ix86_expand_vector_extract (false, target, tmp, elt & 15);
18586 : 10 : return;
18587 : : }
18588 : : break;
18589 : :
18590 : 12 : case E_V64QImode:
18591 : 12 : if (TARGET_AVX512BW)
18592 : : {
18593 : 12 : tmp = gen_reg_rtx (V32QImode);
18594 : 12 : if (elt < 32)
18595 : 6 : emit_insn (gen_vec_extract_lo_v64qi (tmp, vec));
18596 : : else
18597 : 6 : emit_insn (gen_vec_extract_hi_v64qi (tmp, vec));
18598 : 12 : ix86_expand_vector_extract (false, target, tmp, elt & 31);
18599 : 12 : return;
18600 : : }
18601 : : break;
18602 : :
18603 : 55 : case E_V16SFmode:
18604 : 55 : tmp = gen_reg_rtx (V8SFmode);
18605 : 55 : if (elt < 8)
18606 : 29 : emit_insn (gen_vec_extract_lo_v16sf (tmp, vec));
18607 : : else
18608 : 26 : emit_insn (gen_vec_extract_hi_v16sf (tmp, vec));
18609 : 55 : ix86_expand_vector_extract (false, target, tmp, elt & 7);
18610 : 55 : return;
18611 : :
18612 : 72 : case E_V8DFmode:
18613 : 72 : tmp = gen_reg_rtx (V4DFmode);
18614 : 72 : if (elt < 4)
18615 : 48 : emit_insn (gen_vec_extract_lo_v8df (tmp, vec));
18616 : : else
18617 : 24 : emit_insn (gen_vec_extract_hi_v8df (tmp, vec));
18618 : 72 : ix86_expand_vector_extract (false, target, tmp, elt & 3);
18619 : 72 : return;
18620 : :
18621 : 489 : case E_V16SImode:
18622 : 489 : tmp = gen_reg_rtx (V8SImode);
18623 : 489 : if (elt < 8)
18624 : 320 : emit_insn (gen_vec_extract_lo_v16si (tmp, vec));
18625 : : else
18626 : 169 : emit_insn (gen_vec_extract_hi_v16si (tmp, vec));
18627 : 489 : ix86_expand_vector_extract (false, target, tmp, elt & 7);
18628 : 489 : return;
18629 : :
18630 : 742 : case E_V8DImode:
18631 : 742 : tmp = gen_reg_rtx (V4DImode);
18632 : 742 : if (elt < 4)
18633 : 421 : emit_insn (gen_vec_extract_lo_v8di (tmp, vec));
18634 : : else
18635 : 321 : emit_insn (gen_vec_extract_hi_v8di (tmp, vec));
18636 : 742 : ix86_expand_vector_extract (false, target, tmp, elt & 3);
18637 : 742 : return;
18638 : :
18639 : 45 : case E_V32HFmode:
18640 : 45 : case E_V32BFmode:
18641 : 45 : if (TARGET_AVX512BW)
18642 : : {
18643 : 45 : tmp = (mode == E_V32HFmode
18644 : 45 : ? gen_reg_rtx (V16HFmode)
18645 : 7 : : gen_reg_rtx (V16BFmode));
18646 : 45 : if (elt < 16)
18647 : 31 : emit_insn (gen_vec_extract_lo (mode, tmp, vec));
18648 : : else
18649 : 14 : emit_insn (gen_vec_extract_hi (mode, tmp, vec));
18650 : 45 : ix86_expand_vector_extract (false, target, tmp, elt & 15);
18651 : 45 : return;
18652 : : }
18653 : : break;
18654 : :
18655 : 474 : case E_V16HFmode:
18656 : 474 : case E_V16BFmode:
18657 : 474 : if (TARGET_AVX)
18658 : : {
18659 : 474 : tmp = (mode == E_V16HFmode
18660 : 474 : ? gen_reg_rtx (V8HFmode)
18661 : 339 : : gen_reg_rtx (V8BFmode));
18662 : 474 : if (elt < 8)
18663 : 249 : emit_insn (gen_vec_extract_lo (mode, tmp, vec));
18664 : : else
18665 : 225 : emit_insn (gen_vec_extract_hi (mode, tmp, vec));
18666 : 474 : ix86_expand_vector_extract (false, target, tmp, elt & 7);
18667 : 474 : return;
18668 : : }
18669 : : break;
18670 : :
18671 : 598 : case E_V8QImode:
18672 : 598 : use_vec_extr = TARGET_MMX_WITH_SSE && TARGET_SSE4_1;
18673 : : /* ??? Could extract the appropriate HImode element and shift. */
18674 : : break;
18675 : :
18676 : : default:
18677 : : break;
18678 : : }
18679 : :
18680 : 26557 : if (use_vec_extr)
18681 : : {
18682 : 85595 : tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (1, GEN_INT (elt)));
18683 : 85595 : tmp = gen_rtx_VEC_SELECT (inner_mode, vec, tmp);
18684 : :
18685 : : /* Let the rtl optimizers know about the zero extension performed. */
18686 : 85595 : if (inner_mode == QImode || inner_mode == HImode)
18687 : : {
18688 : 8148 : rtx reg = gen_reg_rtx (SImode);
18689 : 8148 : tmp = gen_rtx_ZERO_EXTEND (SImode, tmp);
18690 : 8148 : emit_move_insn (reg, tmp);
18691 : 8148 : tmp = gen_lowpart (inner_mode, reg);
18692 : 8148 : SUBREG_PROMOTED_VAR_P (tmp) = 1;
18693 : 8148 : SUBREG_PROMOTED_SET (tmp, 1);
18694 : : }
18695 : :
18696 : 85595 : emit_move_insn (target, tmp);
18697 : : }
18698 : : else
18699 : : {
18700 : 15386 : rtx mem = assign_stack_temp (mode, GET_MODE_SIZE (mode));
18701 : :
18702 : 7693 : emit_move_insn (mem, vec);
18703 : :
18704 : 15386 : tmp = adjust_address (mem, inner_mode, elt*GET_MODE_SIZE (inner_mode));
18705 : 7693 : emit_move_insn (target, tmp);
18706 : : }
18707 : : }
18708 : :
18709 : : /* Generate code to copy vector bits i / 2 ... i - 1 from vector SRC
18710 : : to bits 0 ... i / 2 - 1 of vector DEST, which has the same mode.
18711 : : The upper bits of DEST are undefined, though they shouldn't cause
18712 : : exceptions (some bits from src or all zeros are ok). */
18713 : :
18714 : : static void
18715 : 40092 : emit_reduc_half (rtx dest, rtx src, int i)
18716 : : {
18717 : 40092 : rtx tem, d = dest;
18718 : 40092 : switch (GET_MODE (src))
18719 : : {
18720 : 6034 : case E_V4SFmode:
18721 : 6034 : if (i == 128)
18722 : 3017 : tem = gen_sse_movhlps (dest, src, src);
18723 : : else
18724 : 3017 : tem = gen_sse_shufps_v4sf (dest, src, src, const1_rtx, const1_rtx,
18725 : : GEN_INT (1 + 4), GEN_INT (1 + 4));
18726 : : break;
18727 : 3224 : case E_V2DFmode:
18728 : 3224 : tem = gen_vec_interleave_highv2df (dest, src, src);
18729 : 3224 : break;
18730 : 64 : case E_V4QImode:
18731 : 64 : d = gen_reg_rtx (V1SImode);
18732 : 64 : tem = gen_mmx_lshrv1si3 (d, gen_lowpart (V1SImode, src),
18733 : 64 : GEN_INT (i / 2));
18734 : 64 : break;
18735 : 524 : case E_V8QImode:
18736 : 524 : case E_V4HImode:
18737 : 524 : d = gen_reg_rtx (V1DImode);
18738 : 524 : tem = gen_mmx_lshrv1di3 (d, gen_lowpart (V1DImode, src),
18739 : 524 : GEN_INT (i / 2));
18740 : 524 : break;
18741 : 30246 : case E_V16QImode:
18742 : 30246 : case E_V8HImode:
18743 : 30246 : case E_V8HFmode:
18744 : 30246 : case E_V4SImode:
18745 : 30246 : case E_V2DImode:
18746 : 30246 : if (TARGET_SSE_REDUCTION_PREFER_PSHUF)
18747 : : {
18748 : 11 : if (i == 128)
18749 : : {
18750 : 5 : d = gen_reg_rtx (V4SImode);
18751 : 10 : tem = gen_sse2_pshufd_1 (
18752 : 5 : d, force_reg (V4SImode, gen_lowpart (V4SImode, src)),
18753 : : GEN_INT (2), GEN_INT (3), GEN_INT (2), GEN_INT (3));
18754 : 5 : break;
18755 : : }
18756 : 6 : else if (i == 64)
18757 : : {
18758 : 5 : d = gen_reg_rtx (V4SImode);
18759 : 10 : tem = gen_sse2_pshufd_1 (
18760 : 5 : d, force_reg (V4SImode, gen_lowpart (V4SImode, src)),
18761 : : GEN_INT (1), GEN_INT (1), GEN_INT (1), GEN_INT (1));
18762 : 5 : break;
18763 : : }
18764 : 1 : else if (i == 32)
18765 : : {
18766 : 1 : d = gen_reg_rtx (V8HImode);
18767 : 2 : tem = gen_sse2_pshuflw_1 (
18768 : 1 : d, force_reg (V8HImode, gen_lowpart (V8HImode, src)),
18769 : : GEN_INT (1), GEN_INT (1), GEN_INT (1), GEN_INT (1));
18770 : 1 : break;
18771 : : }
18772 : : }
18773 : 30235 : d = gen_reg_rtx (V1TImode);
18774 : 30235 : tem = gen_sse2_lshrv1ti3 (d, gen_lowpart (V1TImode, src),
18775 : 30235 : GEN_INT (i / 2));
18776 : 30235 : break;
18777 : 0 : case E_V8SFmode:
18778 : 0 : if (i == 256)
18779 : 0 : tem = gen_avx_vperm2f128v8sf3 (dest, src, src, const1_rtx);
18780 : : else
18781 : 0 : tem = gen_avx_shufps256 (dest, src, src,
18782 : : GEN_INT (i == 128 ? 2 + (3 << 2) : 1));
18783 : : break;
18784 : 0 : case E_V4DFmode:
18785 : 0 : if (i == 256)
18786 : 0 : tem = gen_avx_vperm2f128v4df3 (dest, src, src, const1_rtx);
18787 : : else
18788 : 0 : tem = gen_avx_shufpd256 (dest, src, src, const1_rtx);
18789 : : break;
18790 : 0 : case E_V32QImode:
18791 : 0 : case E_V16HImode:
18792 : 0 : case E_V16HFmode:
18793 : 0 : case E_V8SImode:
18794 : 0 : case E_V4DImode:
18795 : 0 : if (i == 256)
18796 : : {
18797 : 0 : if (GET_MODE (dest) != V4DImode)
18798 : 0 : d = gen_reg_rtx (V4DImode);
18799 : 0 : tem = gen_avx2_permv2ti (d, gen_lowpart (V4DImode, src),
18800 : 0 : gen_lowpart (V4DImode, src),
18801 : : const1_rtx);
18802 : : }
18803 : : else
18804 : : {
18805 : 0 : d = gen_reg_rtx (V2TImode);
18806 : 0 : tem = gen_avx2_lshrv2ti3 (d, gen_lowpart (V2TImode, src),
18807 : 0 : GEN_INT (i / 2));
18808 : : }
18809 : : break;
18810 : 0 : case E_V64QImode:
18811 : 0 : case E_V32HImode:
18812 : 0 : case E_V32HFmode:
18813 : 0 : if (i < 64)
18814 : : {
18815 : 0 : d = gen_reg_rtx (V4TImode);
18816 : 0 : tem = gen_avx512bw_lshrv4ti3 (d, gen_lowpart (V4TImode, src),
18817 : 0 : GEN_INT (i / 2));
18818 : 0 : break;
18819 : : }
18820 : : /* FALLTHRU */
18821 : 0 : case E_V16SImode:
18822 : 0 : case E_V16SFmode:
18823 : 0 : case E_V8DImode:
18824 : 0 : case E_V8DFmode:
18825 : 0 : if (i > 128)
18826 : 0 : tem = gen_avx512f_shuf_i32x4_1 (gen_lowpart (V16SImode, dest),
18827 : 0 : gen_lowpart (V16SImode, src),
18828 : 0 : gen_lowpart (V16SImode, src),
18829 : : GEN_INT (0x4 + (i == 512 ? 4 : 0)),
18830 : : GEN_INT (0x5 + (i == 512 ? 4 : 0)),
18831 : : GEN_INT (0x6 + (i == 512 ? 4 : 0)),
18832 : : GEN_INT (0x7 + (i == 512 ? 4 : 0)),
18833 : : GEN_INT (0xC), GEN_INT (0xD),
18834 : : GEN_INT (0xE), GEN_INT (0xF),
18835 : : GEN_INT (0x10), GEN_INT (0x11),
18836 : : GEN_INT (0x12), GEN_INT (0x13),
18837 : : GEN_INT (0x14), GEN_INT (0x15),
18838 : : GEN_INT (0x16), GEN_INT (0x17));
18839 : : else
18840 : 0 : tem = gen_avx512f_pshufd_1 (gen_lowpart (V16SImode, dest),
18841 : 0 : gen_lowpart (V16SImode, src),
18842 : : GEN_INT (i == 128 ? 0x2 : 0x1),
18843 : : GEN_INT (0x3),
18844 : : GEN_INT (0x3),
18845 : : GEN_INT (0x3),
18846 : : GEN_INT (i == 128 ? 0x6 : 0x5),
18847 : : GEN_INT (0x7),
18848 : : GEN_INT (0x7),
18849 : : GEN_INT (0x7),
18850 : : GEN_INT (i == 128 ? 0xA : 0x9),
18851 : : GEN_INT (0xB),
18852 : : GEN_INT (0xB),
18853 : : GEN_INT (0xB),
18854 : : GEN_INT (i == 128 ? 0xE : 0xD),
18855 : : GEN_INT (0xF),
18856 : : GEN_INT (0xF),
18857 : : GEN_INT (0xF));
18858 : : break;
18859 : 0 : default:
18860 : 0 : gcc_unreachable ();
18861 : : }
18862 : 40092 : emit_insn (tem);
18863 : 40092 : if (d != dest)
18864 : 30834 : emit_move_insn (dest, gen_lowpart (GET_MODE (dest), d));
18865 : 40092 : }
18866 : :
18867 : : /* Expand a vector reduction. FN is the binary pattern to reduce;
18868 : : DEST is the destination; IN is the input vector. */
18869 : :
18870 : : void
18871 : 20008 : ix86_expand_reduc (rtx (*fn) (rtx, rtx, rtx), rtx dest, rtx in)
18872 : : {
18873 : 20008 : rtx half, dst, vec = in;
18874 : 20008 : machine_mode mode = GET_MODE (in);
18875 : 20008 : int i;
18876 : :
18877 : : /* SSE4 has a special instruction for V8HImode UMIN reduction. */
18878 : 20008 : if (TARGET_SSE4_1
18879 : 9468 : && mode == V8HImode
18880 : 755 : && fn == gen_uminv8hi3)
18881 : : {
18882 : 4 : emit_insn (gen_sse4_1_phminposuw (dest, in));
18883 : 4 : return;
18884 : : }
18885 : :
18886 : 40008 : for (i = GET_MODE_BITSIZE (mode);
18887 : 120192 : i > GET_MODE_UNIT_BITSIZE (mode);
18888 : 40092 : i >>= 1)
18889 : : {
18890 : 40092 : half = gen_reg_rtx (mode);
18891 : 40092 : emit_reduc_half (half, vec, i);
18892 : 80184 : if (i == GET_MODE_UNIT_BITSIZE (mode) * 2)
18893 : : dst = dest;
18894 : : else
18895 : 20088 : dst = gen_reg_rtx (mode);
18896 : 40092 : emit_insn (fn (dst, half, vec));
18897 : 40092 : vec = dst;
18898 : : }
18899 : : }
18900 : :
18901 : : /* Output code to perform a conditional jump to LABEL, if C2 flag in
18902 : : FP status register is set. */
18903 : :
18904 : : void
18905 : 280 : ix86_emit_fp_unordered_jump (rtx label)
18906 : : {
18907 : 280 : rtx reg = gen_reg_rtx (HImode);
18908 : 280 : rtx_insn *insn;
18909 : 280 : rtx temp;
18910 : :
18911 : 280 : emit_insn (gen_x86_fnstsw_1 (reg));
18912 : :
18913 : 280 : if (TARGET_SAHF && (TARGET_USE_SAHF || optimize_insn_for_size_p ()))
18914 : : {
18915 : 37 : emit_insn (gen_x86_sahf_1 (reg));
18916 : :
18917 : 37 : temp = gen_rtx_REG (CCmode, FLAGS_REG);
18918 : 37 : temp = gen_rtx_UNORDERED (VOIDmode, temp, const0_rtx);
18919 : : }
18920 : : else
18921 : : {
18922 : 243 : emit_insn (gen_testqi_ext_1_ccno (reg, GEN_INT (0x04)));
18923 : :
18924 : 243 : temp = gen_rtx_REG (CCNOmode, FLAGS_REG);
18925 : 243 : temp = gen_rtx_NE (VOIDmode, temp, const0_rtx);
18926 : : }
18927 : :
18928 : 280 : temp = gen_rtx_IF_THEN_ELSE (VOIDmode, temp,
18929 : : gen_rtx_LABEL_REF (VOIDmode, label),
18930 : : pc_rtx);
18931 : 280 : insn = emit_jump_insn (gen_rtx_SET (pc_rtx, temp));
18932 : 280 : predict_jump (REG_BR_PROB_BASE * 10 / 100);
18933 : 280 : JUMP_LABEL (insn) = label;
18934 : 280 : }
18935 : :
18936 : : /* Output code to perform an sinh XFmode calculation. */
18937 : :
18938 : : void
18939 : 2 : ix86_emit_i387_sinh (rtx op0, rtx op1)
18940 : : {
18941 : 2 : rtx e1 = gen_reg_rtx (XFmode);
18942 : 2 : rtx e2 = gen_reg_rtx (XFmode);
18943 : 2 : rtx scratch = gen_reg_rtx (HImode);
18944 : 2 : rtx flags = gen_rtx_REG (CCNOmode, FLAGS_REG);
18945 : 2 : rtx half = const_double_from_real_value (dconsthalf, XFmode);
18946 : 2 : rtx cst1, tmp;
18947 : 2 : rtx_code_label *jump_label = gen_label_rtx ();
18948 : 2 : rtx_insn *insn;
18949 : :
18950 : : /* scratch = fxam (op1) */
18951 : 2 : emit_insn (gen_fxamxf2_i387 (scratch, op1));
18952 : :
18953 : : /* e1 = expm1 (|op1|) */
18954 : 2 : emit_insn (gen_absxf2 (e2, op1));
18955 : 2 : emit_insn (gen_expm1xf2 (e1, e2));
18956 : :
18957 : : /* e2 = e1 / (e1 + 1.0) + e1 */
18958 : 2 : cst1 = force_reg (XFmode, CONST1_RTX (XFmode));
18959 : 2 : emit_insn (gen_addxf3 (e2, e1, cst1));
18960 : 2 : emit_insn (gen_divxf3 (e2, e1, e2));
18961 : 2 : emit_insn (gen_addxf3 (e2, e2, e1));
18962 : :
18963 : : /* flags = signbit (op1) */
18964 : 2 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x02)));
18965 : :
18966 : : /* if (flags) then e2 = -e2 */
18967 : 2 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode,
18968 : : gen_rtx_EQ (VOIDmode, flags, const0_rtx),
18969 : : gen_rtx_LABEL_REF (VOIDmode, jump_label),
18970 : : pc_rtx);
18971 : 2 : insn = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
18972 : 2 : predict_jump (REG_BR_PROB_BASE * 50 / 100);
18973 : 2 : JUMP_LABEL (insn) = jump_label;
18974 : :
18975 : 2 : emit_insn (gen_negxf2 (e2, e2));
18976 : :
18977 : 2 : emit_label (jump_label);
18978 : 2 : LABEL_NUSES (jump_label) = 1;
18979 : :
18980 : : /* op0 = 0.5 * e2 */
18981 : 2 : half = force_reg (XFmode, half);
18982 : 2 : emit_insn (gen_mulxf3 (op0, e2, half));
18983 : 2 : }
18984 : :
18985 : : /* Output code to perform an cosh XFmode calculation. */
18986 : :
18987 : : void
18988 : 3 : ix86_emit_i387_cosh (rtx op0, rtx op1)
18989 : : {
18990 : 3 : rtx e1 = gen_reg_rtx (XFmode);
18991 : 3 : rtx e2 = gen_reg_rtx (XFmode);
18992 : 3 : rtx half = const_double_from_real_value (dconsthalf, XFmode);
18993 : 3 : rtx cst1;
18994 : :
18995 : : /* e1 = exp (op1) */
18996 : 3 : emit_insn (gen_expxf2 (e1, op1));
18997 : :
18998 : : /* e2 = e1 + 1.0 / e1 */
18999 : 3 : cst1 = force_reg (XFmode, CONST1_RTX (XFmode));
19000 : 3 : emit_insn (gen_divxf3 (e2, cst1, e1));
19001 : 3 : emit_insn (gen_addxf3 (e2, e1, e2));
19002 : :
19003 : : /* op0 = 0.5 * e2 */
19004 : 3 : half = force_reg (XFmode, half);
19005 : 3 : emit_insn (gen_mulxf3 (op0, e2, half));
19006 : 3 : }
19007 : :
19008 : : /* Output code to perform an tanh XFmode calculation. */
19009 : :
19010 : : void
19011 : 1 : ix86_emit_i387_tanh (rtx op0, rtx op1)
19012 : : {
19013 : 1 : rtx e1 = gen_reg_rtx (XFmode);
19014 : 1 : rtx e2 = gen_reg_rtx (XFmode);
19015 : 1 : rtx scratch = gen_reg_rtx (HImode);
19016 : 1 : rtx flags = gen_rtx_REG (CCNOmode, FLAGS_REG);
19017 : 1 : rtx cst2, tmp;
19018 : 1 : rtx_code_label *jump_label = gen_label_rtx ();
19019 : 1 : rtx_insn *insn;
19020 : :
19021 : : /* scratch = fxam (op1) */
19022 : 1 : emit_insn (gen_fxamxf2_i387 (scratch, op1));
19023 : :
19024 : : /* e1 = expm1 (-|2 * op1|) */
19025 : 1 : emit_insn (gen_addxf3 (e2, op1, op1));
19026 : 1 : emit_insn (gen_absxf2 (e2, e2));
19027 : 1 : emit_insn (gen_negxf2 (e2, e2));
19028 : 1 : emit_insn (gen_expm1xf2 (e1, e2));
19029 : :
19030 : : /* e2 = e1 / (e1 + 2.0) */
19031 : 1 : cst2 = force_reg (XFmode, CONST2_RTX (XFmode));
19032 : 1 : emit_insn (gen_addxf3 (e2, e1, cst2));
19033 : 1 : emit_insn (gen_divxf3 (e2, e1, e2));
19034 : :
19035 : : /* flags = signbit (op1) */
19036 : 1 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x02)));
19037 : :
19038 : : /* if (!flags) then e2 = -e2 */
19039 : 1 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode,
19040 : : gen_rtx_NE (VOIDmode, flags, const0_rtx),
19041 : : gen_rtx_LABEL_REF (VOIDmode, jump_label),
19042 : : pc_rtx);
19043 : 1 : insn = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
19044 : 1 : predict_jump (REG_BR_PROB_BASE * 50 / 100);
19045 : 1 : JUMP_LABEL (insn) = jump_label;
19046 : :
19047 : 1 : emit_insn (gen_negxf2 (e2, e2));
19048 : :
19049 : 1 : emit_label (jump_label);
19050 : 1 : LABEL_NUSES (jump_label) = 1;
19051 : :
19052 : 1 : emit_move_insn (op0, e2);
19053 : 1 : }
19054 : :
19055 : : /* Output code to perform an asinh XFmode calculation. */
19056 : :
19057 : : void
19058 : 0 : ix86_emit_i387_asinh (rtx op0, rtx op1)
19059 : : {
19060 : 0 : rtx e1 = gen_reg_rtx (XFmode);
19061 : 0 : rtx e2 = gen_reg_rtx (XFmode);
19062 : 0 : rtx scratch = gen_reg_rtx (HImode);
19063 : 0 : rtx flags = gen_rtx_REG (CCNOmode, FLAGS_REG);
19064 : 0 : rtx cst1, tmp;
19065 : 0 : rtx_code_label *jump_label = gen_label_rtx ();
19066 : 0 : rtx_insn *insn;
19067 : :
19068 : : /* e2 = sqrt (op1^2 + 1.0) + 1.0 */
19069 : 0 : emit_insn (gen_mulxf3 (e1, op1, op1));
19070 : 0 : cst1 = force_reg (XFmode, CONST1_RTX (XFmode));
19071 : 0 : emit_insn (gen_addxf3 (e2, e1, cst1));
19072 : 0 : emit_insn (gen_sqrtxf2 (e2, e2));
19073 : 0 : emit_insn (gen_addxf3 (e2, e2, cst1));
19074 : :
19075 : : /* e1 = e1 / e2 */
19076 : 0 : emit_insn (gen_divxf3 (e1, e1, e2));
19077 : :
19078 : : /* scratch = fxam (op1) */
19079 : 0 : emit_insn (gen_fxamxf2_i387 (scratch, op1));
19080 : :
19081 : : /* e1 = e1 + |op1| */
19082 : 0 : emit_insn (gen_absxf2 (e2, op1));
19083 : 0 : emit_insn (gen_addxf3 (e1, e1, e2));
19084 : :
19085 : : /* e2 = log1p (e1) */
19086 : 0 : ix86_emit_i387_log1p (e2, e1);
19087 : :
19088 : : /* flags = signbit (op1) */
19089 : 0 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x02)));
19090 : :
19091 : : /* if (flags) then e2 = -e2 */
19092 : 0 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode,
19093 : : gen_rtx_EQ (VOIDmode, flags, const0_rtx),
19094 : : gen_rtx_LABEL_REF (VOIDmode, jump_label),
19095 : : pc_rtx);
19096 : 0 : insn = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
19097 : 0 : predict_jump (REG_BR_PROB_BASE * 50 / 100);
19098 : 0 : JUMP_LABEL (insn) = jump_label;
19099 : :
19100 : 0 : emit_insn (gen_negxf2 (e2, e2));
19101 : :
19102 : 0 : emit_label (jump_label);
19103 : 0 : LABEL_NUSES (jump_label) = 1;
19104 : :
19105 : 0 : emit_move_insn (op0, e2);
19106 : 0 : }
19107 : :
19108 : : /* Output code to perform an acosh XFmode calculation. */
19109 : :
19110 : : void
19111 : 0 : ix86_emit_i387_acosh (rtx op0, rtx op1)
19112 : : {
19113 : 0 : rtx e1 = gen_reg_rtx (XFmode);
19114 : 0 : rtx e2 = gen_reg_rtx (XFmode);
19115 : 0 : rtx cst1 = force_reg (XFmode, CONST1_RTX (XFmode));
19116 : :
19117 : : /* e2 = sqrt (op1 + 1.0) */
19118 : 0 : emit_insn (gen_addxf3 (e2, op1, cst1));
19119 : 0 : emit_insn (gen_sqrtxf2 (e2, e2));
19120 : :
19121 : : /* e1 = sqrt (op1 - 1.0) */
19122 : 0 : emit_insn (gen_subxf3 (e1, op1, cst1));
19123 : 0 : emit_insn (gen_sqrtxf2 (e1, e1));
19124 : :
19125 : : /* e1 = e1 * e2 */
19126 : 0 : emit_insn (gen_mulxf3 (e1, e1, e2));
19127 : :
19128 : : /* e1 = e1 + op1 */
19129 : 0 : emit_insn (gen_addxf3 (e1, e1, op1));
19130 : :
19131 : : /* op0 = log (e1) */
19132 : 0 : emit_insn (gen_logxf2 (op0, e1));
19133 : 0 : }
19134 : :
19135 : : /* Output code to perform an atanh XFmode calculation. */
19136 : :
19137 : : void
19138 : 4 : ix86_emit_i387_atanh (rtx op0, rtx op1)
19139 : : {
19140 : 4 : rtx e1 = gen_reg_rtx (XFmode);
19141 : 4 : rtx e2 = gen_reg_rtx (XFmode);
19142 : 4 : rtx scratch = gen_reg_rtx (HImode);
19143 : 4 : rtx flags = gen_rtx_REG (CCNOmode, FLAGS_REG);
19144 : 4 : rtx half = const_double_from_real_value (dconsthalf, XFmode);
19145 : 4 : rtx cst1, tmp;
19146 : 4 : rtx_code_label *jump_label = gen_label_rtx ();
19147 : 4 : rtx_insn *insn;
19148 : :
19149 : : /* scratch = fxam (op1) */
19150 : 4 : emit_insn (gen_fxamxf2_i387 (scratch, op1));
19151 : :
19152 : : /* e2 = |op1| */
19153 : 4 : emit_insn (gen_absxf2 (e2, op1));
19154 : :
19155 : : /* e1 = -(e2 + e2) / (e2 + 1.0) */
19156 : 4 : cst1 = force_reg (XFmode, CONST1_RTX (XFmode));
19157 : 4 : emit_insn (gen_addxf3 (e1, e2, cst1));
19158 : 4 : emit_insn (gen_addxf3 (e2, e2, e2));
19159 : 4 : emit_insn (gen_negxf2 (e2, e2));
19160 : 4 : emit_insn (gen_divxf3 (e1, e2, e1));
19161 : :
19162 : : /* e2 = log1p (e1) */
19163 : 4 : ix86_emit_i387_log1p (e2, e1);
19164 : :
19165 : : /* flags = signbit (op1) */
19166 : 4 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x02)));
19167 : :
19168 : : /* if (!flags) then e2 = -e2 */
19169 : 4 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode,
19170 : : gen_rtx_NE (VOIDmode, flags, const0_rtx),
19171 : : gen_rtx_LABEL_REF (VOIDmode, jump_label),
19172 : : pc_rtx);
19173 : 4 : insn = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
19174 : 4 : predict_jump (REG_BR_PROB_BASE * 50 / 100);
19175 : 4 : JUMP_LABEL (insn) = jump_label;
19176 : :
19177 : 4 : emit_insn (gen_negxf2 (e2, e2));
19178 : :
19179 : 4 : emit_label (jump_label);
19180 : 4 : LABEL_NUSES (jump_label) = 1;
19181 : :
19182 : : /* op0 = 0.5 * e2 */
19183 : 4 : half = force_reg (XFmode, half);
19184 : 4 : emit_insn (gen_mulxf3 (op0, e2, half));
19185 : 4 : }
19186 : :
19187 : : /* Output code to perform a log1p XFmode calculation. */
19188 : :
19189 : : void
19190 : 5 : ix86_emit_i387_log1p (rtx op0, rtx op1)
19191 : : {
19192 : 5 : rtx_code_label *label1 = gen_label_rtx ();
19193 : 5 : rtx_code_label *label2 = gen_label_rtx ();
19194 : :
19195 : 5 : rtx tmp = gen_reg_rtx (XFmode);
19196 : 5 : rtx res = gen_reg_rtx (XFmode);
19197 : 5 : rtx cst, cstln2, cst1;
19198 : 5 : rtx_insn *insn;
19199 : :
19200 : : /* The emit_jump call emits pending stack adjust, make sure it is emitted
19201 : : before the conditional jump, otherwise the stack adjustment will be
19202 : : only conditional. */
19203 : 5 : do_pending_stack_adjust ();
19204 : :
19205 : 5 : cst = const_double_from_real_value
19206 : 5 : (REAL_VALUE_ATOF ("0.29289321881345247561810596348408353", XFmode), XFmode);
19207 : 5 : cstln2 = force_reg (XFmode, standard_80387_constant_rtx (4)); /* fldln2 */
19208 : :
19209 : 5 : emit_insn (gen_absxf2 (tmp, op1));
19210 : :
19211 : 5 : cst = force_reg (XFmode, cst);
19212 : 5 : ix86_expand_branch (GE, tmp, cst, label1);
19213 : 5 : predict_jump (REG_BR_PROB_BASE * 10 / 100);
19214 : 5 : insn = get_last_insn ();
19215 : 5 : JUMP_LABEL (insn) = label1;
19216 : :
19217 : 5 : emit_insn (gen_fyl2xp1xf3_i387 (res, op1, cstln2));
19218 : 5 : emit_jump (label2);
19219 : :
19220 : 5 : emit_label (label1);
19221 : 5 : LABEL_NUSES (label1) = 1;
19222 : :
19223 : 5 : cst1 = force_reg (XFmode, CONST1_RTX (XFmode));
19224 : 5 : emit_insn (gen_rtx_SET (tmp, gen_rtx_PLUS (XFmode, op1, cst1)));
19225 : 5 : emit_insn (gen_fyl2xxf3_i387 (res, tmp, cstln2));
19226 : :
19227 : 5 : emit_label (label2);
19228 : 5 : LABEL_NUSES (label2) = 1;
19229 : :
19230 : 5 : emit_move_insn (op0, res);
19231 : 5 : }
19232 : :
19233 : : /* Emit code for round calculation. */
19234 : : void
19235 : 68 : ix86_emit_i387_round (rtx op0, rtx op1)
19236 : : {
19237 : 68 : machine_mode inmode = GET_MODE (op1);
19238 : 68 : machine_mode outmode = GET_MODE (op0);
19239 : 68 : rtx e1 = gen_reg_rtx (XFmode);
19240 : 68 : rtx e2 = gen_reg_rtx (XFmode);
19241 : 68 : rtx scratch = gen_reg_rtx (HImode);
19242 : 68 : rtx flags = gen_rtx_REG (CCNOmode, FLAGS_REG);
19243 : 68 : rtx half = const_double_from_real_value (dconsthalf, XFmode);
19244 : 68 : rtx res = gen_reg_rtx (outmode);
19245 : 68 : rtx_code_label *jump_label = gen_label_rtx ();
19246 : 68 : rtx (*floor_insn) (rtx, rtx);
19247 : 68 : rtx (*neg_insn) (rtx, rtx);
19248 : 68 : rtx_insn *insn;
19249 : 68 : rtx tmp;
19250 : :
19251 : 68 : switch (inmode)
19252 : : {
19253 : 37 : case E_SFmode:
19254 : 37 : case E_DFmode:
19255 : 37 : tmp = gen_reg_rtx (XFmode);
19256 : :
19257 : 37 : emit_insn (gen_rtx_SET (tmp, gen_rtx_FLOAT_EXTEND (XFmode, op1)));
19258 : 37 : op1 = tmp;
19259 : 37 : break;
19260 : : case E_XFmode:
19261 : : break;
19262 : 0 : default:
19263 : 0 : gcc_unreachable ();
19264 : : }
19265 : :
19266 : 68 : switch (outmode)
19267 : : {
19268 : : case E_SFmode:
19269 : : floor_insn = gen_frndintxf2_floor;
19270 : : neg_insn = gen_negsf2;
19271 : : break;
19272 : 8 : case E_DFmode:
19273 : 8 : floor_insn = gen_frndintxf2_floor;
19274 : 8 : neg_insn = gen_negdf2;
19275 : 8 : break;
19276 : 10 : case E_XFmode:
19277 : 10 : floor_insn = gen_frndintxf2_floor;
19278 : 10 : neg_insn = gen_negxf2;
19279 : 10 : break;
19280 : 0 : case E_HImode:
19281 : 0 : floor_insn = gen_lfloorxfhi2;
19282 : 0 : neg_insn = gen_neghi2;
19283 : 0 : break;
19284 : 10 : case E_SImode:
19285 : 10 : floor_insn = gen_lfloorxfsi2;
19286 : 10 : neg_insn = gen_negsi2;
19287 : 10 : break;
19288 : 36 : case E_DImode:
19289 : 36 : floor_insn = gen_lfloorxfdi2;
19290 : 36 : neg_insn = gen_negdi2;
19291 : 36 : break;
19292 : 0 : default:
19293 : 0 : gcc_unreachable ();
19294 : : }
19295 : :
19296 : : /* round(a) = sgn(a) * floor(fabs(a) + 0.5) */
19297 : :
19298 : : /* scratch = fxam(op1) */
19299 : 68 : emit_insn (gen_fxamxf2_i387 (scratch, op1));
19300 : :
19301 : : /* e1 = fabs(op1) */
19302 : 68 : emit_insn (gen_absxf2 (e1, op1));
19303 : :
19304 : : /* e2 = e1 + 0.5 */
19305 : 68 : half = force_reg (XFmode, half);
19306 : 68 : emit_insn (gen_rtx_SET (e2, gen_rtx_PLUS (XFmode, e1, half)));
19307 : :
19308 : : /* res = floor(e2) */
19309 : 68 : switch (outmode)
19310 : : {
19311 : 12 : case E_SFmode:
19312 : 12 : case E_DFmode:
19313 : 12 : {
19314 : 12 : tmp = gen_reg_rtx (XFmode);
19315 : :
19316 : 12 : emit_insn (floor_insn (tmp, e2));
19317 : 12 : emit_insn (gen_rtx_SET (res,
19318 : : gen_rtx_UNSPEC (outmode, gen_rtvec (1, tmp),
19319 : : UNSPEC_TRUNC_NOOP)));
19320 : : }
19321 : 12 : break;
19322 : 56 : default:
19323 : 56 : emit_insn (floor_insn (res, e2));
19324 : : }
19325 : :
19326 : : /* flags = signbit(a) */
19327 : 68 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x02)));
19328 : :
19329 : : /* if (flags) then res = -res */
19330 : 68 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode,
19331 : : gen_rtx_EQ (VOIDmode, flags, const0_rtx),
19332 : : gen_rtx_LABEL_REF (VOIDmode, jump_label),
19333 : : pc_rtx);
19334 : 68 : insn = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
19335 : 68 : predict_jump (REG_BR_PROB_BASE * 50 / 100);
19336 : 68 : JUMP_LABEL (insn) = jump_label;
19337 : :
19338 : 68 : emit_insn (neg_insn (res, res));
19339 : :
19340 : 68 : emit_label (jump_label);
19341 : 68 : LABEL_NUSES (jump_label) = 1;
19342 : :
19343 : 68 : emit_move_insn (op0, res);
19344 : 68 : }
19345 : :
19346 : : /* Output code to perform a Newton-Rhapson approximation of a single precision
19347 : : floating point divide [http://en.wikipedia.org/wiki/N-th_root_algorithm]. */
19348 : :
19349 : : void
19350 : 49 : ix86_emit_swdivsf (rtx res, rtx a, rtx b, machine_mode mode)
19351 : : {
19352 : 49 : rtx x0, x1, e0, e1;
19353 : :
19354 : 49 : x0 = gen_reg_rtx (mode);
19355 : 49 : e0 = gen_reg_rtx (mode);
19356 : 49 : e1 = gen_reg_rtx (mode);
19357 : 49 : x1 = gen_reg_rtx (mode);
19358 : :
19359 : 49 : b = force_reg (mode, b);
19360 : :
19361 : : /* x0 = rcp(b) estimate */
19362 : 49 : if (mode == V16SFmode || mode == V8DFmode)
19363 : : {
19364 : 0 : emit_insn (gen_rtx_SET (x0, gen_rtx_UNSPEC (mode, gen_rtvec (1, b),
19365 : : UNSPEC_RCP14)));
19366 : : }
19367 : : else
19368 : 49 : emit_insn (gen_rtx_SET (x0, gen_rtx_UNSPEC (mode, gen_rtvec (1, b),
19369 : : UNSPEC_RCP)));
19370 : :
19371 : 49 : unsigned vector_size = GET_MODE_SIZE (mode);
19372 : :
19373 : : /* (a - (rcp(b) * a * b)) * rcp(b) + rcp(b) * a
19374 : : N-R step with 2 fma implementation. */
19375 : 49 : if (TARGET_FMA
19376 : 48 : || (TARGET_AVX512F && vector_size == 64)
19377 : 48 : || (TARGET_AVX512VL && (vector_size == 32 || vector_size == 16)))
19378 : : {
19379 : : /* e0 = x0 * a */
19380 : 1 : emit_insn (gen_rtx_SET (e0, gen_rtx_MULT (mode, x0, a)));
19381 : : /* e1 = e0 * b - a */
19382 : 1 : emit_insn (gen_rtx_SET (e1, gen_rtx_FMA (mode, e0, b,
19383 : : gen_rtx_NEG (mode, a))));
19384 : : /* res = - e1 * x0 + e0 */
19385 : 1 : emit_insn (gen_rtx_SET (res, gen_rtx_FMA (mode,
19386 : : gen_rtx_NEG (mode, e1),
19387 : : x0, e0)));
19388 : : }
19389 : : else
19390 : : /* a / b = a * ((rcp(b) + rcp(b)) - (b * rcp(b) * rcp (b))) */
19391 : : {
19392 : : /* e0 = x0 * b */
19393 : 48 : emit_insn (gen_rtx_SET (e0, gen_rtx_MULT (mode, x0, b)));
19394 : :
19395 : : /* e1 = x0 + x0 */
19396 : 48 : emit_insn (gen_rtx_SET (e1, gen_rtx_PLUS (mode, x0, x0)));
19397 : :
19398 : : /* e0 = x0 * e0 */
19399 : 48 : emit_insn (gen_rtx_SET (e0, gen_rtx_MULT (mode, x0, e0)));
19400 : :
19401 : : /* x1 = e1 - e0 */
19402 : 48 : emit_insn (gen_rtx_SET (x1, gen_rtx_MINUS (mode, e1, e0)));
19403 : :
19404 : : /* res = a * x1 */
19405 : 48 : emit_insn (gen_rtx_SET (res, gen_rtx_MULT (mode, a, x1)));
19406 : : }
19407 : 49 : }
19408 : :
19409 : : /* Output code to perform a Newton-Rhapson approximation of a
19410 : : single precision floating point [reciprocal] square root. */
19411 : :
19412 : : void
19413 : 85 : ix86_emit_swsqrtsf (rtx res, rtx a, machine_mode mode, bool recip)
19414 : : {
19415 : 85 : rtx x0, e0, e1, e2, e3, mthree, mhalf;
19416 : 85 : REAL_VALUE_TYPE r;
19417 : 85 : int unspec;
19418 : :
19419 : 85 : x0 = gen_reg_rtx (mode);
19420 : 85 : e0 = gen_reg_rtx (mode);
19421 : 85 : e1 = gen_reg_rtx (mode);
19422 : 85 : e2 = gen_reg_rtx (mode);
19423 : 85 : e3 = gen_reg_rtx (mode);
19424 : :
19425 : 85 : real_from_integer (&r, VOIDmode, -3, SIGNED);
19426 : 85 : mthree = const_double_from_real_value (r, SFmode);
19427 : :
19428 : 85 : real_arithmetic (&r, NEGATE_EXPR, &dconsthalf, NULL);
19429 : 85 : mhalf = const_double_from_real_value (r, SFmode);
19430 : 85 : unspec = UNSPEC_RSQRT;
19431 : :
19432 : 85 : if (VECTOR_MODE_P (mode))
19433 : : {
19434 : 66 : mthree = ix86_build_const_vector (mode, true, mthree);
19435 : 66 : mhalf = ix86_build_const_vector (mode, true, mhalf);
19436 : : /* There is no 512-bit rsqrt. There is however rsqrt14. */
19437 : 132 : if (GET_MODE_SIZE (mode) == 64)
19438 : 0 : unspec = UNSPEC_RSQRT14;
19439 : : }
19440 : :
19441 : : /* sqrt(a) = -0.5 * a * rsqrtss(a) * (a * rsqrtss(a) * rsqrtss(a) - 3.0)
19442 : : rsqrt(a) = -0.5 * rsqrtss(a) * (a * rsqrtss(a) * rsqrtss(a) - 3.0) */
19443 : :
19444 : 85 : a = force_reg (mode, a);
19445 : :
19446 : : /* x0 = rsqrt(a) estimate */
19447 : 85 : emit_insn (gen_rtx_SET (x0, gen_rtx_UNSPEC (mode, gen_rtvec (1, a),
19448 : : unspec)));
19449 : :
19450 : : /* If (a == 0.0) Filter out infinity to prevent NaN for sqrt(0.0). */
19451 : 85 : if (!recip)
19452 : : {
19453 : 57 : rtx zero = force_reg (mode, CONST0_RTX(mode));
19454 : 57 : rtx mask;
19455 : :
19456 : : /* Handle masked compare. */
19457 : 110 : if (VECTOR_MODE_P (mode) && GET_MODE_SIZE (mode) == 64)
19458 : : {
19459 : 0 : mask = gen_reg_rtx (HImode);
19460 : : /* Imm value 0x4 corresponds to not-equal comparison. */
19461 : 0 : emit_insn (gen_avx512f_cmpv16sf3 (mask, zero, a, GEN_INT (0x4)));
19462 : 0 : emit_insn (gen_avx512f_blendmv16sf (x0, zero, x0, mask));
19463 : : }
19464 : : else
19465 : : {
19466 : 57 : mask = gen_reg_rtx (mode);
19467 : 57 : emit_insn (gen_rtx_SET (mask, gen_rtx_NE (mode, zero, a)));
19468 : 57 : emit_insn (gen_rtx_SET (x0, gen_rtx_AND (mode, x0, mask)));
19469 : : }
19470 : : }
19471 : :
19472 : 85 : mthree = force_reg (mode, mthree);
19473 : :
19474 : : /* e0 = x0 * a */
19475 : 85 : emit_insn (gen_rtx_SET (e0, gen_rtx_MULT (mode, x0, a)));
19476 : :
19477 : 85 : unsigned vector_size = GET_MODE_SIZE (mode);
19478 : 85 : if (TARGET_FMA
19479 : 77 : || (TARGET_AVX512F && vector_size == 64)
19480 : 77 : || (TARGET_AVX512VL && (vector_size == 32 || vector_size == 16)))
19481 : 16 : emit_insn (gen_rtx_SET (e2,
19482 : : gen_rtx_FMA (mode, e0, x0, mthree)));
19483 : : else
19484 : : {
19485 : : /* e1 = e0 * x0 */
19486 : 69 : emit_insn (gen_rtx_SET (e1, gen_rtx_MULT (mode, e0, x0)));
19487 : :
19488 : : /* e2 = e1 - 3. */
19489 : 69 : emit_insn (gen_rtx_SET (e2, gen_rtx_PLUS (mode, e1, mthree)));
19490 : : }
19491 : :
19492 : 85 : mhalf = force_reg (mode, mhalf);
19493 : 85 : if (recip)
19494 : : /* e3 = -.5 * x0 */
19495 : 28 : emit_insn (gen_rtx_SET (e3, gen_rtx_MULT (mode, x0, mhalf)));
19496 : : else
19497 : : /* e3 = -.5 * e0 */
19498 : 57 : emit_insn (gen_rtx_SET (e3, gen_rtx_MULT (mode, e0, mhalf)));
19499 : : /* ret = e2 * e3 */
19500 : 85 : emit_insn (gen_rtx_SET (res, gen_rtx_MULT (mode, e2, e3)));
19501 : 85 : }
19502 : :
19503 : : /* Expand fabs (OP0) and return a new rtx that holds the result. The
19504 : : mask for masking out the sign-bit is stored in *SMASK, if that is
19505 : : non-null. */
19506 : :
19507 : : static rtx
19508 : 1040 : ix86_expand_sse_fabs (rtx op0, rtx *smask)
19509 : : {
19510 : 1040 : machine_mode vmode, mode = GET_MODE (op0);
19511 : 1040 : rtx xa, mask;
19512 : :
19513 : 1040 : xa = gen_reg_rtx (mode);
19514 : 1040 : if (mode == SFmode)
19515 : : vmode = V4SFmode;
19516 : 491 : else if (mode == DFmode)
19517 : : vmode = V2DFmode;
19518 : : else
19519 : 0 : vmode = mode;
19520 : 1040 : mask = ix86_build_signbit_mask (vmode, VECTOR_MODE_P (mode), true);
19521 : 1040 : if (!VECTOR_MODE_P (mode))
19522 : : {
19523 : : /* We need to generate a scalar mode mask in this case. */
19524 : 1040 : rtx tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (1, const0_rtx));
19525 : 1040 : tmp = gen_rtx_VEC_SELECT (mode, mask, tmp);
19526 : 1040 : mask = gen_reg_rtx (mode);
19527 : 1040 : emit_insn (gen_rtx_SET (mask, tmp));
19528 : : }
19529 : 1040 : emit_insn (gen_rtx_SET (xa, gen_rtx_AND (mode, op0, mask)));
19530 : :
19531 : 1040 : if (smask)
19532 : 987 : *smask = mask;
19533 : :
19534 : 1040 : return xa;
19535 : : }
19536 : :
19537 : : /* Expands a comparison of OP0 with OP1 using comparison code CODE,
19538 : : swapping the operands if SWAP_OPERANDS is true. The expanded
19539 : : code is a forward jump to a newly created label in case the
19540 : : comparison is true. The generated label rtx is returned. */
19541 : : static rtx_code_label *
19542 : 1055 : ix86_expand_sse_compare_and_jump (enum rtx_code code, rtx op0, rtx op1,
19543 : : bool swap_operands)
19544 : : {
19545 : 1055 : bool unordered_compare = ix86_unordered_fp_compare (code);
19546 : 1055 : rtx_code_label *label;
19547 : 1055 : rtx tmp, reg;
19548 : :
19549 : 1055 : if (swap_operands)
19550 : 34 : std::swap (op0, op1);
19551 : :
19552 : 1055 : label = gen_label_rtx ();
19553 : 1055 : tmp = gen_rtx_COMPARE (CCFPmode, op0, op1);
19554 : 1055 : if (unordered_compare)
19555 : 899 : tmp = gen_rtx_UNSPEC (CCFPmode, gen_rtvec (1, tmp), UNSPEC_NOTRAP);
19556 : 1055 : reg = gen_rtx_REG (CCFPmode, FLAGS_REG);
19557 : 1055 : emit_insn (gen_rtx_SET (reg, tmp));
19558 : 1055 : tmp = gen_rtx_fmt_ee (code, VOIDmode, reg, const0_rtx);
19559 : 1055 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
19560 : : gen_rtx_LABEL_REF (VOIDmode, label), pc_rtx);
19561 : 1055 : tmp = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
19562 : 1055 : JUMP_LABEL (tmp) = label;
19563 : :
19564 : 1055 : return label;
19565 : : }
19566 : :
19567 : : /* Expand a mask generating SSE comparison instruction comparing OP0 with OP1
19568 : : using comparison code CODE. Operands are swapped for the comparison if
19569 : : SWAP_OPERANDS is true. Returns a rtx for the generated mask. */
19570 : : static rtx
19571 : 567 : ix86_expand_sse_compare_mask (enum rtx_code code, rtx op0, rtx op1,
19572 : : bool swap_operands)
19573 : : {
19574 : 567 : rtx (*insn)(rtx, rtx, rtx, rtx);
19575 : 567 : machine_mode mode = GET_MODE (op0);
19576 : 567 : rtx mask = gen_reg_rtx (mode);
19577 : :
19578 : 567 : if (swap_operands)
19579 : 388 : std::swap (op0, op1);
19580 : :
19581 : 567 : insn = mode == DFmode ? gen_setcc_df_sse : gen_setcc_sf_sse;
19582 : :
19583 : 567 : emit_insn (insn (mask, op0, op1,
19584 : : gen_rtx_fmt_ee (code, mode, op0, op1)));
19585 : 567 : return mask;
19586 : : }
19587 : :
19588 : : /* Expand copysign from SIGN to the positive value ABS_VALUE
19589 : : storing in RESULT. If MASK is non-null, it shall be a mask to mask out
19590 : : the sign-bit. */
19591 : :
19592 : : static void
19593 : 1007 : ix86_sse_copysign_to_positive (rtx result, rtx abs_value, rtx sign, rtx mask)
19594 : : {
19595 : 1007 : machine_mode mode = GET_MODE (sign);
19596 : 1007 : rtx sgn = gen_reg_rtx (mode);
19597 : 1007 : if (mask == NULL_RTX)
19598 : : {
19599 : 28 : machine_mode vmode;
19600 : :
19601 : 28 : if (mode == SFmode)
19602 : : vmode = V4SFmode;
19603 : : else if (mode == DFmode)
19604 : : vmode = V2DFmode;
19605 : : else if (mode == HFmode)
19606 : : vmode = V8HFmode;
19607 : : else
19608 : 28 : vmode = mode;
19609 : :
19610 : 28 : mask = ix86_build_signbit_mask (vmode, VECTOR_MODE_P (mode), false);
19611 : 28 : if (!VECTOR_MODE_P (mode))
19612 : : {
19613 : : /* We need to generate a scalar mode mask in this case. */
19614 : 28 : rtx tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (1, const0_rtx));
19615 : 28 : tmp = gen_rtx_VEC_SELECT (mode, mask, tmp);
19616 : 28 : mask = gen_reg_rtx (mode);
19617 : 28 : emit_insn (gen_rtx_SET (mask, tmp));
19618 : : }
19619 : : }
19620 : : else
19621 : 979 : mask = gen_rtx_NOT (mode, mask);
19622 : 1007 : emit_insn (gen_rtx_SET (sgn, gen_rtx_AND (mode, mask, sign)));
19623 : 1007 : emit_insn (gen_rtx_SET (result, gen_rtx_IOR (mode, abs_value, sgn)));
19624 : 1007 : }
19625 : :
19626 : : /* Expand SSE sequence for computing lround from OP1 storing
19627 : : into OP0. */
19628 : :
19629 : : void
19630 : 28 : ix86_expand_lround (rtx op0, rtx op1)
19631 : : {
19632 : : /* C code for the stuff we're doing below:
19633 : : tmp = op1 + copysign (nextafter (0.5, 0.0), op1)
19634 : : return (long)tmp;
19635 : : */
19636 : 28 : machine_mode mode = GET_MODE (op1);
19637 : 28 : const struct real_format *fmt;
19638 : 28 : REAL_VALUE_TYPE pred_half, half_minus_pred_half;
19639 : 28 : rtx adj;
19640 : :
19641 : : /* load nextafter (0.5, 0.0) */
19642 : 28 : fmt = REAL_MODE_FORMAT (mode);
19643 : 28 : real_2expN (&half_minus_pred_half, -(fmt->p) - 1, mode);
19644 : 28 : real_arithmetic (&pred_half, MINUS_EXPR, &dconsthalf, &half_minus_pred_half);
19645 : :
19646 : : /* adj = copysign (0.5, op1) */
19647 : 28 : adj = force_reg (mode, const_double_from_real_value (pred_half, mode));
19648 : 28 : ix86_sse_copysign_to_positive (adj, adj, force_reg (mode, op1), NULL_RTX);
19649 : :
19650 : : /* adj = op1 + adj */
19651 : 28 : adj = expand_simple_binop (mode, PLUS, adj, op1, NULL_RTX, 0, OPTAB_DIRECT);
19652 : :
19653 : : /* op0 = (imode)adj */
19654 : 28 : expand_fix (op0, adj, 0);
19655 : 28 : }
19656 : :
19657 : : /* Expand SSE2 sequence for computing lround from OPERAND1 storing
19658 : : into OPERAND0. */
19659 : :
19660 : : void
19661 : 68 : ix86_expand_lfloorceil (rtx op0, rtx op1, bool do_floor)
19662 : : {
19663 : : /* C code for the stuff we're doing below (for do_floor):
19664 : : xi = (long)op1;
19665 : : xi -= (double)xi > op1 ? 1 : 0;
19666 : : return xi;
19667 : : */
19668 : 68 : machine_mode fmode = GET_MODE (op1);
19669 : 68 : machine_mode imode = GET_MODE (op0);
19670 : 68 : rtx ireg, freg, tmp;
19671 : 68 : rtx_code_label *label;
19672 : :
19673 : : /* reg = (long)op1 */
19674 : 68 : ireg = gen_reg_rtx (imode);
19675 : 68 : expand_fix (ireg, op1, 0);
19676 : :
19677 : : /* freg = (double)reg */
19678 : 68 : freg = gen_reg_rtx (fmode);
19679 : 68 : expand_float (freg, ireg, 0);
19680 : :
19681 : : /* ireg = (freg > op1) ? ireg - 1 : ireg */
19682 : 136 : label = ix86_expand_sse_compare_and_jump (UNLE,
19683 : 68 : freg, op1, !do_floor);
19684 : 102 : tmp = expand_simple_binop (imode, do_floor ? MINUS : PLUS,
19685 : : ireg, const1_rtx, NULL_RTX, 0, OPTAB_DIRECT);
19686 : 68 : emit_move_insn (ireg, tmp);
19687 : :
19688 : 68 : emit_label (label);
19689 : 68 : LABEL_NUSES (label) = 1;
19690 : :
19691 : 68 : emit_move_insn (op0, ireg);
19692 : 68 : }
19693 : :
19694 : : /* Generate and return a rtx of mode MODE for 2**n where n is the number
19695 : : of bits of the mantissa of MODE, which must be one of DFmode or SFmode. */
19696 : :
19697 : : static rtx
19698 : 987 : ix86_gen_TWO52 (machine_mode mode)
19699 : : {
19700 : 987 : const struct real_format *fmt;
19701 : 987 : REAL_VALUE_TYPE TWO52r;
19702 : 987 : rtx TWO52;
19703 : :
19704 : 987 : fmt = REAL_MODE_FORMAT (mode);
19705 : 987 : real_2expN (&TWO52r, fmt->p - 1, mode);
19706 : 987 : TWO52 = const_double_from_real_value (TWO52r, mode);
19707 : 987 : TWO52 = force_reg (mode, TWO52);
19708 : :
19709 : 987 : return TWO52;
19710 : : }
19711 : :
19712 : : /* Expand rint rounding OPERAND1 and storing the result in OPERAND0. */
19713 : :
19714 : : void
19715 : 122 : ix86_expand_rint (rtx operand0, rtx operand1)
19716 : : {
19717 : : /* C code for the stuff we're doing below:
19718 : : xa = fabs (operand1);
19719 : : if (!isless (xa, 2**52))
19720 : : return operand1;
19721 : : two52 = 2**52;
19722 : : if (flag_rounding_math)
19723 : : {
19724 : : two52 = copysign (two52, operand1);
19725 : : xa = operand1;
19726 : : }
19727 : : xa = xa + two52 - two52;
19728 : : return copysign (xa, operand1);
19729 : : */
19730 : 122 : machine_mode mode = GET_MODE (operand0);
19731 : 122 : rtx res, xa, TWO52, mask;
19732 : 122 : rtx_code_label *label;
19733 : :
19734 : 122 : TWO52 = ix86_gen_TWO52 (mode);
19735 : :
19736 : : /* Temporary for holding the result, initialized to the input
19737 : : operand to ease control flow. */
19738 : 122 : res = copy_to_reg (operand1);
19739 : :
19740 : : /* xa = abs (operand1) */
19741 : 122 : xa = ix86_expand_sse_fabs (res, &mask);
19742 : :
19743 : : /* if (!isless (xa, TWO52)) goto label; */
19744 : 122 : label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
19745 : :
19746 : 122 : if (flag_rounding_math)
19747 : : {
19748 : 53 : ix86_sse_copysign_to_positive (TWO52, TWO52, res, mask);
19749 : 53 : xa = res;
19750 : : }
19751 : :
19752 : 122 : xa = expand_simple_binop (mode, PLUS, xa, TWO52, NULL_RTX, 0, OPTAB_DIRECT);
19753 : 122 : xa = expand_simple_binop (mode, MINUS, xa, TWO52, xa, 0, OPTAB_DIRECT);
19754 : :
19755 : : /* Remove the sign with FE_DOWNWARD, where x - x = -0.0. */
19756 : 122 : if (HONOR_SIGNED_ZEROS (mode) && flag_rounding_math)
19757 : 53 : xa = ix86_expand_sse_fabs (xa, NULL);
19758 : :
19759 : 122 : ix86_sse_copysign_to_positive (res, xa, res, mask);
19760 : :
19761 : 122 : emit_label (label);
19762 : 122 : LABEL_NUSES (label) = 1;
19763 : :
19764 : 122 : emit_move_insn (operand0, res);
19765 : 122 : }
19766 : :
19767 : : /* Expand SSE2 sequence for computing floor or ceil
19768 : : from OPERAND1 storing into OPERAND0. */
19769 : : void
19770 : 567 : ix86_expand_floorceil (rtx operand0, rtx operand1, bool do_floor)
19771 : : {
19772 : : /* C code for the stuff we expand below.
19773 : : double xa = fabs (x), x2;
19774 : : if (!isless (xa, TWO52))
19775 : : return x;
19776 : : x2 = (double)(long)x;
19777 : :
19778 : : Compensate. Floor:
19779 : : if (x2 > x)
19780 : : x2 -= 1;
19781 : : Compensate. Ceil:
19782 : : if (x2 < x)
19783 : : x2 += 1;
19784 : :
19785 : : if (HONOR_SIGNED_ZEROS (mode))
19786 : : return copysign (x2, x);
19787 : : return x2;
19788 : : */
19789 : 567 : machine_mode mode = GET_MODE (operand0);
19790 : 567 : rtx xa, xi, TWO52, tmp, one, res, mask;
19791 : 567 : rtx_code_label *label;
19792 : :
19793 : 567 : TWO52 = ix86_gen_TWO52 (mode);
19794 : :
19795 : : /* Temporary for holding the result, initialized to the input
19796 : : operand to ease control flow. */
19797 : 567 : res = copy_to_reg (operand1);
19798 : :
19799 : : /* xa = abs (operand1) */
19800 : 567 : xa = ix86_expand_sse_fabs (res, &mask);
19801 : :
19802 : : /* if (!isless (xa, TWO52)) goto label; */
19803 : 567 : label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
19804 : :
19805 : : /* xa = (double)(long)x */
19806 : 567 : xi = gen_reg_rtx (int_mode_for_mode (mode).require ());
19807 : 567 : expand_fix (xi, res, 0);
19808 : 567 : expand_float (xa, xi, 0);
19809 : :
19810 : : /* generate 1.0 */
19811 : 567 : one = force_reg (mode, const_double_from_real_value (dconst1, mode));
19812 : :
19813 : : /* Compensate: xa = xa - (xa > operand1 ? 1 : 0) */
19814 : 567 : tmp = ix86_expand_sse_compare_mask (UNGT, xa, res, !do_floor);
19815 : 567 : emit_insn (gen_rtx_SET (tmp, gen_rtx_AND (mode, one, tmp)));
19816 : 955 : tmp = expand_simple_binop (mode, do_floor ? MINUS : PLUS,
19817 : : xa, tmp, NULL_RTX, 0, OPTAB_DIRECT);
19818 : 567 : if (HONOR_SIGNED_ZEROS (mode))
19819 : : {
19820 : : /* Remove the sign with FE_DOWNWARD, where x - x = -0.0. */
19821 : 520 : if (do_floor && flag_rounding_math)
19822 : 0 : tmp = ix86_expand_sse_fabs (tmp, NULL);
19823 : :
19824 : 520 : ix86_sse_copysign_to_positive (tmp, tmp, res, mask);
19825 : : }
19826 : 567 : emit_move_insn (res, tmp);
19827 : :
19828 : 567 : emit_label (label);
19829 : 567 : LABEL_NUSES (label) = 1;
19830 : :
19831 : 567 : emit_move_insn (operand0, res);
19832 : 567 : }
19833 : :
19834 : : /* Expand SSE2 sequence for computing floor or ceil from OPERAND1 storing
19835 : : into OPERAND0 without relying on DImode truncation via cvttsd2siq
19836 : : that is only available on 64bit targets. */
19837 : : void
19838 : 0 : ix86_expand_floorceildf_32 (rtx operand0, rtx operand1, bool do_floor)
19839 : : {
19840 : : /* C code for the stuff we expand below.
19841 : : double xa = fabs (x), x2;
19842 : : if (!isless (xa, TWO52))
19843 : : return x;
19844 : : xa = xa + TWO52 - TWO52;
19845 : : x2 = copysign (xa, x);
19846 : :
19847 : : Compensate. Floor:
19848 : : if (x2 > x)
19849 : : x2 -= 1;
19850 : : Compensate. Ceil:
19851 : : if (x2 < x)
19852 : : x2 += 1;
19853 : :
19854 : : if (HONOR_SIGNED_ZEROS (mode))
19855 : : x2 = copysign (x2, x);
19856 : : return x2;
19857 : : */
19858 : 0 : machine_mode mode = GET_MODE (operand0);
19859 : 0 : rtx xa, TWO52, tmp, one, res, mask;
19860 : 0 : rtx_code_label *label;
19861 : :
19862 : 0 : TWO52 = ix86_gen_TWO52 (mode);
19863 : :
19864 : : /* Temporary for holding the result, initialized to the input
19865 : : operand to ease control flow. */
19866 : 0 : res = copy_to_reg (operand1);
19867 : :
19868 : : /* xa = abs (operand1) */
19869 : 0 : xa = ix86_expand_sse_fabs (res, &mask);
19870 : :
19871 : : /* if (!isless (xa, TWO52)) goto label; */
19872 : 0 : label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
19873 : :
19874 : : /* xa = xa + TWO52 - TWO52; */
19875 : 0 : xa = expand_simple_binop (mode, PLUS, xa, TWO52, NULL_RTX, 0, OPTAB_DIRECT);
19876 : 0 : xa = expand_simple_binop (mode, MINUS, xa, TWO52, xa, 0, OPTAB_DIRECT);
19877 : :
19878 : : /* xa = copysign (xa, operand1) */
19879 : 0 : ix86_sse_copysign_to_positive (xa, xa, res, mask);
19880 : :
19881 : : /* generate 1.0 */
19882 : 0 : one = force_reg (mode, const_double_from_real_value (dconst1, mode));
19883 : :
19884 : : /* Compensate: xa = xa - (xa > operand1 ? 1 : 0) */
19885 : 0 : tmp = ix86_expand_sse_compare_mask (UNGT, xa, res, !do_floor);
19886 : 0 : emit_insn (gen_rtx_SET (tmp, gen_rtx_AND (mode, one, tmp)));
19887 : 0 : tmp = expand_simple_binop (mode, do_floor ? MINUS : PLUS,
19888 : : xa, tmp, NULL_RTX, 0, OPTAB_DIRECT);
19889 : 0 : if (HONOR_SIGNED_ZEROS (mode))
19890 : : {
19891 : : /* Remove the sign with FE_DOWNWARD, where x - x = -0.0. */
19892 : 0 : if (do_floor && flag_rounding_math)
19893 : 0 : tmp = ix86_expand_sse_fabs (tmp, NULL);
19894 : :
19895 : 0 : ix86_sse_copysign_to_positive (tmp, tmp, res, mask);
19896 : : }
19897 : 0 : emit_move_insn (res, tmp);
19898 : :
19899 : 0 : emit_label (label);
19900 : 0 : LABEL_NUSES (label) = 1;
19901 : :
19902 : 0 : emit_move_insn (operand0, res);
19903 : 0 : }
19904 : :
19905 : : /* Expand SSE sequence for computing trunc
19906 : : from OPERAND1 storing into OPERAND0. */
19907 : : void
19908 : 284 : ix86_expand_trunc (rtx operand0, rtx operand1)
19909 : : {
19910 : : /* C code for SSE variant we expand below.
19911 : : double xa = fabs (x), x2;
19912 : : if (!isless (xa, TWO52))
19913 : : return x;
19914 : : x2 = (double)(long)x;
19915 : : if (HONOR_SIGNED_ZEROS (mode))
19916 : : return copysign (x2, x);
19917 : : return x2;
19918 : : */
19919 : 284 : machine_mode mode = GET_MODE (operand0);
19920 : 284 : rtx xa, xi, TWO52, res, mask;
19921 : 284 : rtx_code_label *label;
19922 : :
19923 : 284 : TWO52 = ix86_gen_TWO52 (mode);
19924 : :
19925 : : /* Temporary for holding the result, initialized to the input
19926 : : operand to ease control flow. */
19927 : 284 : res = copy_to_reg (operand1);
19928 : :
19929 : : /* xa = abs (operand1) */
19930 : 284 : xa = ix86_expand_sse_fabs (res, &mask);
19931 : :
19932 : : /* if (!isless (xa, TWO52)) goto label; */
19933 : 284 : label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
19934 : :
19935 : : /* xa = (double)(long)x */
19936 : 284 : xi = gen_reg_rtx (int_mode_for_mode (mode).require ());
19937 : 284 : expand_fix (xi, res, 0);
19938 : 284 : expand_float (xa, xi, 0);
19939 : :
19940 : 284 : if (HONOR_SIGNED_ZEROS (mode))
19941 : 270 : ix86_sse_copysign_to_positive (xa, xa, res, mask);
19942 : :
19943 : 284 : emit_move_insn (res, xa);
19944 : :
19945 : 284 : emit_label (label);
19946 : 284 : LABEL_NUSES (label) = 1;
19947 : :
19948 : 284 : emit_move_insn (operand0, res);
19949 : 284 : }
19950 : :
19951 : : /* Expand SSE sequence for computing trunc from OPERAND1 storing
19952 : : into OPERAND0 without relying on DImode truncation via cvttsd2siq
19953 : : that is only available on 64bit targets. */
19954 : : void
19955 : 0 : ix86_expand_truncdf_32 (rtx operand0, rtx operand1)
19956 : : {
19957 : 0 : machine_mode mode = GET_MODE (operand0);
19958 : 0 : rtx xa, xa2, TWO52, tmp, one, res, mask;
19959 : 0 : rtx_code_label *label;
19960 : :
19961 : : /* C code for SSE variant we expand below.
19962 : : double xa = fabs (x), x2;
19963 : : if (!isless (xa, TWO52))
19964 : : return x;
19965 : : xa2 = xa + TWO52 - TWO52;
19966 : : Compensate:
19967 : : if (xa2 > xa)
19968 : : xa2 -= 1.0;
19969 : : x2 = copysign (xa2, x);
19970 : : return x2;
19971 : : */
19972 : :
19973 : 0 : TWO52 = ix86_gen_TWO52 (mode);
19974 : :
19975 : : /* Temporary for holding the result, initialized to the input
19976 : : operand to ease control flow. */
19977 : 0 : res =copy_to_reg (operand1);
19978 : :
19979 : : /* xa = abs (operand1) */
19980 : 0 : xa = ix86_expand_sse_fabs (res, &mask);
19981 : :
19982 : : /* if (!isless (xa, TWO52)) goto label; */
19983 : 0 : label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
19984 : :
19985 : : /* xa2 = xa + TWO52 - TWO52; */
19986 : 0 : xa2 = expand_simple_binop (mode, PLUS, xa, TWO52, NULL_RTX, 0, OPTAB_DIRECT);
19987 : 0 : xa2 = expand_simple_binop (mode, MINUS, xa2, TWO52, xa2, 0, OPTAB_DIRECT);
19988 : :
19989 : : /* generate 1.0 */
19990 : 0 : one = force_reg (mode, const_double_from_real_value (dconst1, mode));
19991 : :
19992 : : /* Compensate: xa2 = xa2 - (xa2 > xa ? 1 : 0) */
19993 : 0 : tmp = ix86_expand_sse_compare_mask (UNGT, xa2, xa, false);
19994 : 0 : emit_insn (gen_rtx_SET (tmp, gen_rtx_AND (mode, one, tmp)));
19995 : 0 : tmp = expand_simple_binop (mode, MINUS,
19996 : : xa2, tmp, NULL_RTX, 0, OPTAB_DIRECT);
19997 : : /* Remove the sign with FE_DOWNWARD, where x - x = -0.0. */
19998 : 0 : if (HONOR_SIGNED_ZEROS (mode) && flag_rounding_math)
19999 : 0 : tmp = ix86_expand_sse_fabs (tmp, NULL);
20000 : :
20001 : : /* res = copysign (xa2, operand1) */
20002 : 0 : ix86_sse_copysign_to_positive (res, tmp, res, mask);
20003 : :
20004 : 0 : emit_label (label);
20005 : 0 : LABEL_NUSES (label) = 1;
20006 : :
20007 : 0 : emit_move_insn (operand0, res);
20008 : 0 : }
20009 : :
20010 : : /* Expand SSE sequence for computing round
20011 : : from OPERAND1 storing into OPERAND0. */
20012 : : void
20013 : 14 : ix86_expand_round (rtx operand0, rtx operand1)
20014 : : {
20015 : : /* C code for the stuff we're doing below:
20016 : : double xa = fabs (x);
20017 : : if (!isless (xa, TWO52))
20018 : : return x;
20019 : : xa = (double)(long)(xa + nextafter (0.5, 0.0));
20020 : : return copysign (xa, x);
20021 : : */
20022 : 14 : machine_mode mode = GET_MODE (operand0);
20023 : 14 : rtx res, TWO52, xa, xi, half, mask;
20024 : 14 : rtx_code_label *label;
20025 : 14 : const struct real_format *fmt;
20026 : 14 : REAL_VALUE_TYPE pred_half, half_minus_pred_half;
20027 : :
20028 : : /* Temporary for holding the result, initialized to the input
20029 : : operand to ease control flow. */
20030 : 14 : res = copy_to_reg (operand1);
20031 : :
20032 : 14 : TWO52 = ix86_gen_TWO52 (mode);
20033 : 14 : xa = ix86_expand_sse_fabs (res, &mask);
20034 : 14 : label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
20035 : :
20036 : : /* load nextafter (0.5, 0.0) */
20037 : 14 : fmt = REAL_MODE_FORMAT (mode);
20038 : 14 : real_2expN (&half_minus_pred_half, -(fmt->p) - 1, mode);
20039 : 14 : real_arithmetic (&pred_half, MINUS_EXPR, &dconsthalf, &half_minus_pred_half);
20040 : :
20041 : : /* xa = xa + 0.5 */
20042 : 14 : half = force_reg (mode, const_double_from_real_value (pred_half, mode));
20043 : 14 : xa = expand_simple_binop (mode, PLUS, xa, half, NULL_RTX, 0, OPTAB_DIRECT);
20044 : :
20045 : : /* xa = (double)(int64_t)xa */
20046 : 14 : xi = gen_reg_rtx (int_mode_for_mode (mode).require ());
20047 : 14 : expand_fix (xi, xa, 0);
20048 : 14 : expand_float (xa, xi, 0);
20049 : :
20050 : : /* res = copysign (xa, operand1) */
20051 : 14 : ix86_sse_copysign_to_positive (res, xa, res, mask);
20052 : :
20053 : 14 : emit_label (label);
20054 : 14 : LABEL_NUSES (label) = 1;
20055 : :
20056 : 14 : emit_move_insn (operand0, res);
20057 : 14 : }
20058 : :
20059 : : /* Expand SSE sequence for computing round from OPERAND1 storing
20060 : : into OPERAND0 without relying on DImode truncation via cvttsd2siq
20061 : : that is only available on 64bit targets. */
20062 : : void
20063 : 0 : ix86_expand_rounddf_32 (rtx operand0, rtx operand1)
20064 : : {
20065 : : /* C code for the stuff we expand below.
20066 : : double xa = fabs (x), xa2, x2;
20067 : : if (!isless (xa, TWO52))
20068 : : return x;
20069 : : Using the absolute value and copying back sign makes
20070 : : -0.0 -> -0.0 correct.
20071 : : xa2 = xa + TWO52 - TWO52;
20072 : : Compensate.
20073 : : dxa = xa2 - xa;
20074 : : if (dxa <= -0.5)
20075 : : xa2 += 1;
20076 : : else if (dxa > 0.5)
20077 : : xa2 -= 1;
20078 : : x2 = copysign (xa2, x);
20079 : : return x2;
20080 : : */
20081 : 0 : machine_mode mode = GET_MODE (operand0);
20082 : 0 : rtx xa, xa2, dxa, TWO52, tmp, half, mhalf, one, res, mask;
20083 : 0 : rtx_code_label *label;
20084 : :
20085 : 0 : TWO52 = ix86_gen_TWO52 (mode);
20086 : :
20087 : : /* Temporary for holding the result, initialized to the input
20088 : : operand to ease control flow. */
20089 : 0 : res = copy_to_reg (operand1);
20090 : :
20091 : : /* xa = abs (operand1) */
20092 : 0 : xa = ix86_expand_sse_fabs (res, &mask);
20093 : :
20094 : : /* if (!isless (xa, TWO52)) goto label; */
20095 : 0 : label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
20096 : :
20097 : : /* xa2 = xa + TWO52 - TWO52; */
20098 : 0 : xa2 = expand_simple_binop (mode, PLUS, xa, TWO52, NULL_RTX, 0, OPTAB_DIRECT);
20099 : 0 : xa2 = expand_simple_binop (mode, MINUS, xa2, TWO52, xa2, 0, OPTAB_DIRECT);
20100 : :
20101 : : /* dxa = xa2 - xa; */
20102 : 0 : dxa = expand_simple_binop (mode, MINUS, xa2, xa, NULL_RTX, 0, OPTAB_DIRECT);
20103 : :
20104 : : /* generate 0.5, 1.0 and -0.5 */
20105 : 0 : half = force_reg (mode, const_double_from_real_value (dconsthalf, mode));
20106 : 0 : one = expand_simple_binop (mode, PLUS, half, half, NULL_RTX, 0, OPTAB_DIRECT);
20107 : 0 : mhalf = expand_simple_binop (mode, MINUS, half, one, NULL_RTX,
20108 : : 0, OPTAB_DIRECT);
20109 : :
20110 : : /* Compensate. */
20111 : : /* xa2 = xa2 - (dxa > 0.5 ? 1 : 0) */
20112 : 0 : tmp = ix86_expand_sse_compare_mask (UNGT, dxa, half, false);
20113 : 0 : emit_insn (gen_rtx_SET (tmp, gen_rtx_AND (mode, tmp, one)));
20114 : 0 : xa2 = expand_simple_binop (mode, MINUS, xa2, tmp, NULL_RTX, 0, OPTAB_DIRECT);
20115 : : /* xa2 = xa2 + (dxa <= -0.5 ? 1 : 0) */
20116 : 0 : tmp = ix86_expand_sse_compare_mask (UNGE, mhalf, dxa, false);
20117 : 0 : emit_insn (gen_rtx_SET (tmp, gen_rtx_AND (mode, tmp, one)));
20118 : 0 : xa2 = expand_simple_binop (mode, PLUS, xa2, tmp, NULL_RTX, 0, OPTAB_DIRECT);
20119 : :
20120 : : /* res = copysign (xa2, operand1) */
20121 : 0 : ix86_sse_copysign_to_positive (res, xa2, res, mask);
20122 : :
20123 : 0 : emit_label (label);
20124 : 0 : LABEL_NUSES (label) = 1;
20125 : :
20126 : 0 : emit_move_insn (operand0, res);
20127 : 0 : }
20128 : :
20129 : : /* Expand SSE sequence for computing round
20130 : : from OP1 storing into OP0 using sse4 round insn. */
20131 : : void
20132 : 9 : ix86_expand_round_sse4 (rtx op0, rtx op1)
20133 : : {
20134 : 9 : machine_mode mode = GET_MODE (op0);
20135 : 9 : rtx e1, e2, res, half;
20136 : 9 : const struct real_format *fmt;
20137 : 9 : REAL_VALUE_TYPE pred_half, half_minus_pred_half;
20138 : 9 : rtx (*gen_copysign) (rtx, rtx, rtx);
20139 : 9 : rtx (*gen_round) (rtx, rtx, rtx);
20140 : :
20141 : 9 : switch (mode)
20142 : : {
20143 : : case E_HFmode:
20144 : : gen_copysign = gen_copysignhf3;
20145 : : gen_round = gen_sse4_1_roundhf2;
20146 : : break;
20147 : 4 : case E_SFmode:
20148 : 4 : gen_copysign = gen_copysignsf3;
20149 : 4 : gen_round = gen_sse4_1_roundsf2;
20150 : 4 : break;
20151 : 4 : case E_DFmode:
20152 : 4 : gen_copysign = gen_copysigndf3;
20153 : 4 : gen_round = gen_sse4_1_rounddf2;
20154 : 4 : break;
20155 : 0 : default:
20156 : 0 : gcc_unreachable ();
20157 : : }
20158 : :
20159 : : /* round (a) = trunc (a + copysign (0.5, a)) */
20160 : :
20161 : : /* load nextafter (0.5, 0.0) */
20162 : 9 : fmt = REAL_MODE_FORMAT (mode);
20163 : 9 : real_2expN (&half_minus_pred_half, -(fmt->p) - 1, mode);
20164 : 9 : real_arithmetic (&pred_half, MINUS_EXPR, &dconsthalf, &half_minus_pred_half);
20165 : 9 : half = const_double_from_real_value (pred_half, mode);
20166 : :
20167 : : /* e1 = copysign (0.5, op1) */
20168 : 9 : e1 = gen_reg_rtx (mode);
20169 : 9 : emit_insn (gen_copysign (e1, half, op1));
20170 : :
20171 : : /* e2 = op1 + e1 */
20172 : 9 : e2 = expand_simple_binop (mode, PLUS, op1, e1, NULL_RTX, 0, OPTAB_DIRECT);
20173 : :
20174 : : /* res = trunc (e2) */
20175 : 9 : res = gen_reg_rtx (mode);
20176 : 9 : emit_insn (gen_round (res, e2, GEN_INT (ROUND_TRUNC)));
20177 : :
20178 : 9 : emit_move_insn (op0, res);
20179 : 9 : }
20180 : :
20181 : : /* A cached (set (nil) (vselect (vconcat (nil) (nil)) (parallel [])))
20182 : : insn, so that expand_vselect{,_vconcat} doesn't have to create a fresh
20183 : : insn every time. */
20184 : :
20185 : : static GTY(()) rtx_insn *vselect_insn;
20186 : :
20187 : : /* Initialize vselect_insn. */
20188 : :
20189 : : static void
20190 : 6661 : init_vselect_insn (void)
20191 : : {
20192 : 6661 : unsigned i;
20193 : 6661 : rtx x;
20194 : :
20195 : 6661 : x = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (MAX_VECT_LEN));
20196 : 432965 : for (i = 0; i < MAX_VECT_LEN; ++i)
20197 : 426304 : XVECEXP (x, 0, i) = const0_rtx;
20198 : 6661 : x = gen_rtx_VEC_SELECT (V2DFmode, gen_rtx_VEC_CONCAT (V4DFmode, const0_rtx,
20199 : : const0_rtx), x);
20200 : 6661 : x = gen_rtx_SET (const0_rtx, x);
20201 : 6661 : start_sequence ();
20202 : 6661 : vselect_insn = emit_insn (x);
20203 : 6661 : end_sequence ();
20204 : 6661 : }
20205 : :
20206 : : /* Construct (set target (vec_select op0 (parallel perm))) and
20207 : : return true if that's a valid instruction in the active ISA. */
20208 : :
20209 : : static bool
20210 : 575646 : expand_vselect (rtx target, rtx op0, const unsigned char *perm,
20211 : : unsigned nelt, bool testing_p)
20212 : : {
20213 : 575646 : unsigned int i;
20214 : 575646 : rtx x, save_vconcat;
20215 : 575646 : int icode;
20216 : :
20217 : 575646 : if (vselect_insn == NULL_RTX)
20218 : 1569 : init_vselect_insn ();
20219 : :
20220 : 575646 : x = XEXP (SET_SRC (PATTERN (vselect_insn)), 1);
20221 : 575646 : PUT_NUM_ELEM (XVEC (x, 0), nelt);
20222 : 4494046 : for (i = 0; i < nelt; ++i)
20223 : 3918400 : XVECEXP (x, 0, i) = GEN_INT (perm[i]);
20224 : 575646 : save_vconcat = XEXP (SET_SRC (PATTERN (vselect_insn)), 0);
20225 : 575646 : XEXP (SET_SRC (PATTERN (vselect_insn)), 0) = op0;
20226 : 575646 : PUT_MODE (SET_SRC (PATTERN (vselect_insn)), GET_MODE (target));
20227 : 575646 : SET_DEST (PATTERN (vselect_insn)) = target;
20228 : 575646 : icode = recog_memoized (vselect_insn);
20229 : :
20230 : 575646 : if (icode >= 0 && !testing_p)
20231 : 67577 : emit_insn (copy_rtx (PATTERN (vselect_insn)));
20232 : :
20233 : 575646 : SET_DEST (PATTERN (vselect_insn)) = const0_rtx;
20234 : 575646 : XEXP (SET_SRC (PATTERN (vselect_insn)), 0) = save_vconcat;
20235 : 575646 : INSN_CODE (vselect_insn) = -1;
20236 : :
20237 : 575646 : return icode >= 0;
20238 : : }
20239 : :
20240 : : /* Similar, but generate a vec_concat from op0 and op1 as well. */
20241 : :
20242 : : static bool
20243 : 513278 : expand_vselect_vconcat (rtx target, rtx op0, rtx op1,
20244 : : const unsigned char *perm, unsigned nelt,
20245 : : bool testing_p)
20246 : : {
20247 : 513278 : machine_mode v2mode;
20248 : 513278 : rtx x;
20249 : 513278 : bool ok;
20250 : :
20251 : 513278 : if (vselect_insn == NULL_RTX)
20252 : 5092 : init_vselect_insn ();
20253 : :
20254 : 513278 : if (!GET_MODE_2XWIDER_MODE (GET_MODE (op0)).exists (&v2mode))
20255 : : return false;
20256 : 513278 : x = XEXP (SET_SRC (PATTERN (vselect_insn)), 0);
20257 : 513278 : PUT_MODE (x, v2mode);
20258 : 513278 : XEXP (x, 0) = op0;
20259 : 513278 : XEXP (x, 1) = op1;
20260 : 513278 : ok = expand_vselect (target, x, perm, nelt, testing_p);
20261 : 513278 : XEXP (x, 0) = const0_rtx;
20262 : 513278 : XEXP (x, 1) = const0_rtx;
20263 : 513278 : return ok;
20264 : : }
20265 : :
20266 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement D
20267 : : using movss or movsd. */
20268 : : static bool
20269 : 335602 : expand_vec_perm_movs (struct expand_vec_perm_d *d)
20270 : : {
20271 : 335602 : machine_mode vmode = d->vmode;
20272 : 335602 : unsigned i, nelt = d->nelt;
20273 : 335602 : rtx x;
20274 : :
20275 : 335602 : if (d->one_operand_p)
20276 : : return false;
20277 : :
20278 : 306456 : if (!(TARGET_SSE && (vmode == V4SFmode || vmode == V4SImode))
20279 : 141262 : && !(TARGET_MMX_WITH_SSE && (vmode == V2SFmode || vmode == V2SImode))
20280 : 86329 : && !(TARGET_SSE2 && (vmode == V2DFmode || vmode == V2DImode)))
20281 : : return false;
20282 : :
20283 : : /* Only the first element is changed. */
20284 : 227311 : if (d->perm[0] != nelt && d->perm[0] != 0)
20285 : : return false;
20286 : 157938 : for (i = 1; i < nelt; ++i)
20287 : 125530 : if (d->perm[i] != i + nelt - d->perm[0])
20288 : : return false;
20289 : :
20290 : 32408 : if (d->testing_p)
20291 : : return true;
20292 : :
20293 : 4611 : if (d->perm[0] == nelt)
20294 : 0 : x = gen_rtx_VEC_MERGE (vmode, d->op1, d->op0, GEN_INT (1));
20295 : : else
20296 : 4611 : x = gen_rtx_VEC_MERGE (vmode, d->op0, d->op1, GEN_INT (1));
20297 : :
20298 : 4611 : emit_insn (gen_rtx_SET (d->target, x));
20299 : :
20300 : 4611 : return true;
20301 : : }
20302 : :
20303 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement D
20304 : : using insertps. */
20305 : : static bool
20306 : 303194 : expand_vec_perm_insertps (struct expand_vec_perm_d *d)
20307 : : {
20308 : 303194 : machine_mode vmode = d->vmode;
20309 : 303194 : unsigned i, cnt_s, nelt = d->nelt;
20310 : 303194 : int cnt_d = -1;
20311 : 303194 : rtx src, dst;
20312 : :
20313 : 303194 : if (d->one_operand_p)
20314 : : return false;
20315 : :
20316 : 274048 : if (!(TARGET_SSE4_1
20317 : 39547 : && (vmode == V4SFmode || vmode == V4SImode
20318 : 29382 : || (TARGET_MMX_WITH_SSE
20319 : 20714 : && (vmode == V2SFmode || vmode == V2SImode)))))
20320 : : return false;
20321 : :
20322 : 51525 : for (i = 0; i < nelt; ++i)
20323 : : {
20324 : 49126 : if (d->perm[i] == i)
20325 : 9693 : continue;
20326 : 39433 : if (cnt_d != -1)
20327 : : {
20328 : : cnt_d = -1;
20329 : : break;
20330 : : }
20331 : 20916 : cnt_d = i;
20332 : : }
20333 : :
20334 : 20916 : if (cnt_d == -1)
20335 : : {
20336 : 41411 : for (i = 0; i < nelt; ++i)
20337 : : {
20338 : 39237 : if (d->perm[i] == i + nelt)
20339 : 4377 : continue;
20340 : 34860 : if (cnt_d != -1)
20341 : : return false;
20342 : 18517 : cnt_d = i;
20343 : : }
20344 : :
20345 : 2174 : if (cnt_d == -1)
20346 : : return false;
20347 : : }
20348 : :
20349 : 4573 : if (d->testing_p)
20350 : : return true;
20351 : :
20352 : 425 : gcc_assert (cnt_d != -1);
20353 : :
20354 : 425 : cnt_s = d->perm[cnt_d];
20355 : 425 : if (cnt_s < nelt)
20356 : : {
20357 : 195 : src = d->op0;
20358 : 195 : dst = d->op1;
20359 : : }
20360 : : else
20361 : : {
20362 : 230 : cnt_s -= nelt;
20363 : 230 : src = d->op1;
20364 : 230 : dst = d->op0;
20365 : : }
20366 : 425 : gcc_assert (cnt_s < nelt);
20367 : :
20368 : 425 : rtx x = gen_sse4_1_insertps (vmode, d->target, dst, src,
20369 : 425 : GEN_INT (cnt_s << 6 | cnt_d << 4));
20370 : 425 : emit_insn (x);
20371 : :
20372 : 425 : return true;
20373 : : }
20374 : :
20375 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement D
20376 : : in terms of blendp[sd] / pblendw / pblendvb / vpblendd. */
20377 : :
20378 : : static bool
20379 : 339219 : expand_vec_perm_blend (struct expand_vec_perm_d *d)
20380 : : {
20381 : 339219 : machine_mode mmode, vmode = d->vmode;
20382 : 339219 : unsigned i, nelt = d->nelt;
20383 : 339219 : unsigned HOST_WIDE_INT mask;
20384 : 339219 : rtx target, op0, op1, maskop, x;
20385 : 339219 : rtx rperm[32], vperm;
20386 : :
20387 : 339219 : if (d->one_operand_p)
20388 : : return false;
20389 : 6295 : if (TARGET_AVX512F && GET_MODE_SIZE (vmode) == 64
20390 : 311148 : && (TARGET_AVX512BW
20391 : 670 : || GET_MODE_UNIT_SIZE (vmode) >= 4))
20392 : : ;
20393 : 320701 : else if (TARGET_AVX2 && GET_MODE_SIZE (vmode) == 32)
20394 : : ;
20395 : 302666 : else if (TARGET_AVX && (vmode == V4DFmode || vmode == V8SFmode))
20396 : : ;
20397 : 294034 : else if (TARGET_SSE4_1
20398 : 326109 : && (GET_MODE_SIZE (vmode) == 16
20399 : 22906 : || (TARGET_MMX_WITH_SSE && GET_MODE_SIZE (vmode) == 8)
20400 : 2840 : || GET_MODE_SIZE (vmode) == 4))
20401 : : ;
20402 : : else
20403 : : return false;
20404 : :
20405 : : /* This is a blend, not a permute. Elements must stay in their
20406 : : respective lanes. */
20407 : 105575 : for (i = 0; i < nelt; ++i)
20408 : : {
20409 : 101958 : unsigned e = d->perm[i];
20410 : 101958 : if (!(e == i || e == i + nelt))
20411 : : return false;
20412 : : }
20413 : :
20414 : 3617 : if (d->testing_p)
20415 : : return true;
20416 : :
20417 : : /* ??? Without SSE4.1, we could implement this with and/andn/or. This
20418 : : decision should be extracted elsewhere, so that we only try that
20419 : : sequence once all budget==3 options have been tried. */
20420 : 2792 : target = d->target;
20421 : 2792 : op0 = d->op0;
20422 : 2792 : op1 = d->op1;
20423 : 2792 : mask = 0;
20424 : :
20425 : 2792 : switch (vmode)
20426 : : {
20427 : : case E_V8DFmode:
20428 : : case E_V16SFmode:
20429 : : case E_V4DFmode:
20430 : : case E_V8SFmode:
20431 : : case E_V2DFmode:
20432 : : case E_V4SFmode:
20433 : : case E_V2SFmode:
20434 : : case E_V2HImode:
20435 : : case E_V4HImode:
20436 : : case E_V8HImode:
20437 : : case E_V8SImode:
20438 : : case E_V32HImode:
20439 : : case E_V64QImode:
20440 : : case E_V16SImode:
20441 : : case E_V8DImode:
20442 : 9776 : for (i = 0; i < nelt; ++i)
20443 : 8448 : mask |= ((unsigned HOST_WIDE_INT) (d->perm[i] >= nelt)) << i;
20444 : : break;
20445 : :
20446 : : case E_V2DImode:
20447 : 18 : for (i = 0; i < 2; ++i)
20448 : 18 : mask |= (d->perm[i] >= 2 ? 15 : 0) << (i * 4);
20449 : 6 : vmode = V8HImode;
20450 : 6 : goto do_subreg;
20451 : :
20452 : : case E_V2SImode:
20453 : 30 : for (i = 0; i < 2; ++i)
20454 : 30 : mask |= (d->perm[i] >= 2 ? 3 : 0) << (i * 2);
20455 : 10 : vmode = V4HImode;
20456 : 10 : goto do_subreg;
20457 : :
20458 : 827 : case E_V4SImode:
20459 : 827 : if (TARGET_AVX2)
20460 : : {
20461 : : /* Use vpblendd instead of vpblendw. */
20462 : 130 : for (i = 0; i < nelt; ++i)
20463 : 104 : mask |= ((unsigned HOST_WIDE_INT) (d->perm[i] >= nelt)) << i;
20464 : : break;
20465 : : }
20466 : : else
20467 : : {
20468 : 4005 : for (i = 0; i < 4; ++i)
20469 : 5002 : mask |= (d->perm[i] >= 4 ? 3 : 0) << (i * 2);
20470 : 801 : vmode = V8HImode;
20471 : 801 : goto do_subreg;
20472 : : }
20473 : :
20474 : : case E_V16QImode:
20475 : : /* See if bytes move in pairs so we can use pblendw with
20476 : : an immediate argument, rather than pblendvb with a vector
20477 : : argument. */
20478 : 84 : for (i = 0; i < 16; i += 2)
20479 : 84 : if (d->perm[i] + 1 != d->perm[i + 1])
20480 : : {
20481 : 83 : use_pblendvb:
20482 : 3427 : for (i = 0; i < nelt; ++i)
20483 : 3152 : rperm[i] = (d->perm[i] < nelt ? const0_rtx : constm1_rtx);
20484 : :
20485 : 275 : finish_pblendvb:
20486 : 276 : vperm = gen_rtx_CONST_VECTOR (vmode, gen_rtvec_v (nelt, rperm));
20487 : 276 : vperm = force_reg (vmode, vperm);
20488 : :
20489 : 552 : if (GET_MODE_SIZE (vmode) == 4)
20490 : 120 : emit_insn (gen_mmx_pblendvb_v4qi (target, op0, op1, vperm));
20491 : 312 : else if (GET_MODE_SIZE (vmode) == 8)
20492 : 40 : emit_insn (gen_mmx_pblendvb_v8qi (target, op0, op1, vperm));
20493 : 232 : else if (GET_MODE_SIZE (vmode) == 16)
20494 : 83 : emit_insn (gen_sse4_1_pblendvb (target, op0, op1, vperm));
20495 : : else
20496 : 33 : emit_insn (gen_avx2_pblendvb (target, op0, op1, vperm));
20497 : 276 : if (target != d->target)
20498 : 1 : emit_move_insn (d->target, gen_lowpart (d->vmode, target));
20499 : 276 : return true;
20500 : : }
20501 : :
20502 : 0 : for (i = 0; i < 8; ++i)
20503 : 0 : mask |= (d->perm[i * 2] >= 16) << i;
20504 : : vmode = V8HImode;
20505 : : /* FALLTHRU */
20506 : :
20507 : 1130 : do_subreg:
20508 : 1130 : target = gen_reg_rtx (vmode);
20509 : 1130 : op0 = gen_lowpart (vmode, op0);
20510 : 1130 : op1 = gen_lowpart (vmode, op1);
20511 : 1130 : break;
20512 : :
20513 : : case E_V8QImode:
20514 : 40 : for (i = 0; i < 8; i += 2)
20515 : 40 : if (d->perm[i] + 1 != d->perm[i + 1])
20516 : 40 : goto use_pblendvb;
20517 : :
20518 : 0 : for (i = 0; i < 4; ++i)
20519 : 0 : mask |= (d->perm[i * 2] >= 8) << i;
20520 : 0 : vmode = V4HImode;
20521 : 0 : goto do_subreg;
20522 : :
20523 : : case E_V4QImode:
20524 : 120 : for (i = 0; i < 4; i += 2)
20525 : 120 : if (d->perm[i] + 1 != d->perm[i + 1])
20526 : 120 : goto use_pblendvb;
20527 : :
20528 : 0 : for (i = 0; i < 2; ++i)
20529 : 0 : mask |= (d->perm[i * 2] >= 4) << i;
20530 : 0 : vmode = V2HImode;
20531 : 0 : goto do_subreg;
20532 : :
20533 : : case E_V32QImode:
20534 : : /* See if bytes move in pairs. If not, vpblendvb must be used. */
20535 : 4928 : for (i = 0; i < 32; i += 2)
20536 : 4640 : if (d->perm[i] + 1 != d->perm[i + 1])
20537 : 32 : goto use_pblendvb;
20538 : : /* See if bytes move in quadruplets. If yes, vpblendd
20539 : : with immediate can be used. */
20540 : 2592 : for (i = 0; i < 32; i += 4)
20541 : 2304 : if (d->perm[i] + 2 != d->perm[i + 2])
20542 : : break;
20543 : 288 : if (i < 32)
20544 : : {
20545 : : /* See if bytes move the same in both lanes. If yes,
20546 : : vpblendw with immediate can be used. */
20547 : 0 : for (i = 0; i < 16; i += 2)
20548 : 0 : if (d->perm[i] + 16 != d->perm[i + 16])
20549 : 0 : goto use_pblendvb;
20550 : :
20551 : : /* Use vpblendw. */
20552 : 0 : for (i = 0; i < 16; ++i)
20553 : 0 : mask |= (d->perm[i * 2] >= 32) << i;
20554 : 0 : vmode = V16HImode;
20555 : 0 : goto do_subreg;
20556 : : }
20557 : :
20558 : : /* Use vpblendd. */
20559 : 2592 : for (i = 0; i < 8; ++i)
20560 : 2304 : mask |= (d->perm[i * 4] >= 32) << i;
20561 : 288 : vmode = V8SImode;
20562 : 288 : goto do_subreg;
20563 : :
20564 : : case E_V16HImode:
20565 : : /* See if words move in pairs. If yes, vpblendd can be used. */
20566 : 177 : for (i = 0; i < 16; i += 2)
20567 : 161 : if (d->perm[i] + 1 != d->perm[i + 1])
20568 : : break;
20569 : 49 : if (i < 16)
20570 : : {
20571 : : /* See if words move the same in both lanes. If not,
20572 : : vpblendvb must be used. */
20573 : 290 : for (i = 0; i < 8; i++)
20574 : 258 : if (d->perm[i] + 8 != d->perm[i + 8])
20575 : : {
20576 : : /* Use vpblendvb. */
20577 : 33 : for (i = 0; i < 32; ++i)
20578 : 32 : rperm[i] = (d->perm[i / 2] < 16 ? const0_rtx : constm1_rtx);
20579 : :
20580 : 1 : vmode = V32QImode;
20581 : 1 : nelt = 32;
20582 : 1 : target = gen_reg_rtx (vmode);
20583 : 1 : op0 = gen_lowpart (vmode, op0);
20584 : 1 : op1 = gen_lowpart (vmode, op1);
20585 : 1 : goto finish_pblendvb;
20586 : : }
20587 : :
20588 : : /* Use vpblendw. */
20589 : 544 : for (i = 0; i < 16; ++i)
20590 : 512 : mask |= (d->perm[i] >= 16) << i;
20591 : : break;
20592 : : }
20593 : :
20594 : : /* Use vpblendd. */
20595 : 144 : for (i = 0; i < 8; ++i)
20596 : 128 : mask |= (d->perm[i * 2] >= 16) << i;
20597 : 16 : vmode = V8SImode;
20598 : 16 : goto do_subreg;
20599 : :
20600 : : case E_V4DImode:
20601 : : /* Use vpblendd. */
20602 : 45 : for (i = 0; i < 4; ++i)
20603 : 54 : mask |= (d->perm[i] >= 4 ? 3 : 0) << (i * 2);
20604 : 9 : vmode = V8SImode;
20605 : 9 : goto do_subreg;
20606 : :
20607 : 0 : default:
20608 : 0 : gcc_unreachable ();
20609 : : }
20610 : :
20611 : 2516 : switch (vmode)
20612 : : {
20613 : : case E_V8DFmode:
20614 : : case E_V8DImode:
20615 : : mmode = QImode;
20616 : : break;
20617 : 5 : case E_V16SFmode:
20618 : 5 : case E_V16SImode:
20619 : 5 : mmode = HImode;
20620 : 5 : break;
20621 : 6 : case E_V32HImode:
20622 : 6 : mmode = SImode;
20623 : 6 : break;
20624 : 1 : case E_V64QImode:
20625 : 1 : mmode = DImode;
20626 : 1 : break;
20627 : : default:
20628 : : mmode = VOIDmode;
20629 : : }
20630 : :
20631 : : /* Canonicalize vec_merge. */
20632 : 2516 : if (swap_commutative_operands_p (op1, op0)
20633 : : /* Two operands have same precedence, then
20634 : : first bit of mask select first operand. */
20635 : 2516 : || (!swap_commutative_operands_p (op0, op1)
20636 : 2516 : && !(mask & 1)))
20637 : : {
20638 : 2509 : unsigned n_elts = GET_MODE_NUNITS (vmode);
20639 : 2509 : std::swap (op0, op1);
20640 : 2509 : unsigned HOST_WIDE_INT mask_all = HOST_WIDE_INT_1U;
20641 : 2509 : if (n_elts == HOST_BITS_PER_WIDE_INT)
20642 : : mask_all = -1;
20643 : : else
20644 : 2508 : mask_all = (HOST_WIDE_INT_1U << n_elts) - 1;
20645 : 2509 : mask = ~mask & mask_all;
20646 : : }
20647 : :
20648 : 2516 : if (mmode != VOIDmode)
20649 : 16 : maskop = force_reg (mmode, gen_int_mode (mask, mmode));
20650 : : else
20651 : 2500 : maskop = GEN_INT (mask);
20652 : :
20653 : : /* This matches five different patterns with the different modes. */
20654 : 2516 : x = gen_rtx_VEC_MERGE (vmode, op1, op0, maskop);
20655 : 2516 : x = gen_rtx_SET (target, x);
20656 : 2516 : emit_insn (x);
20657 : 2516 : if (target != d->target)
20658 : 1130 : emit_move_insn (d->target, gen_lowpart (d->vmode, target));
20659 : :
20660 : : return true;
20661 : : }
20662 : :
20663 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement D
20664 : : in terms of the variable form of vpermilps.
20665 : :
20666 : : Note that we will have already failed the immediate input vpermilps,
20667 : : which requires that the high and low part shuffle be identical; the
20668 : : variable form doesn't require that. */
20669 : :
20670 : : static bool
20671 : 154156 : expand_vec_perm_vpermil (struct expand_vec_perm_d *d)
20672 : : {
20673 : 154156 : rtx rperm[8], vperm;
20674 : 154156 : unsigned i;
20675 : :
20676 : 154156 : if (!TARGET_AVX || d->vmode != V8SFmode || !d->one_operand_p)
20677 : : return false;
20678 : :
20679 : : /* We can only permute within the 128-bit lane. */
20680 : 22956 : for (i = 0; i < 8; ++i)
20681 : : {
20682 : 21874 : unsigned e = d->perm[i];
20683 : 21874 : if (i < 4 ? e >= 4 : e < 4)
20684 : : return false;
20685 : : }
20686 : :
20687 : 1082 : if (d->testing_p)
20688 : : return true;
20689 : :
20690 : 468 : for (i = 0; i < 8; ++i)
20691 : : {
20692 : 416 : unsigned e = d->perm[i];
20693 : :
20694 : : /* Within each 128-bit lane, the elements of op0 are numbered
20695 : : from 0 and the elements of op1 are numbered from 4. */
20696 : 416 : if (e >= 8 + 4)
20697 : 0 : e -= 8;
20698 : 416 : else if (e >= 4)
20699 : 208 : e -= 4;
20700 : :
20701 : 416 : rperm[i] = GEN_INT (e);
20702 : : }
20703 : :
20704 : 52 : vperm = gen_rtx_CONST_VECTOR (V8SImode, gen_rtvec_v (8, rperm));
20705 : 52 : vperm = force_reg (V8SImode, vperm);
20706 : 52 : emit_insn (gen_avx_vpermilvarv8sf3 (d->target, d->op0, vperm));
20707 : :
20708 : 52 : return true;
20709 : : }
20710 : :
20711 : : /* For V*[QHS]Imode permutations, check if the same permutation
20712 : : can't be performed in a 2x, 4x or 8x wider inner mode. */
20713 : :
20714 : : static bool
20715 : 177267 : canonicalize_vector_int_perm (const struct expand_vec_perm_d *d,
20716 : : struct expand_vec_perm_d *nd)
20717 : : {
20718 : 177267 : int i;
20719 : 177267 : machine_mode mode = VOIDmode;
20720 : :
20721 : 177267 : switch (d->vmode)
20722 : : {
20723 : : case E_V8QImode: mode = V4HImode; break;
20724 : 31000 : case E_V16QImode: mode = V8HImode; break;
20725 : 1438 : case E_V32QImode: mode = V16HImode; break;
20726 : 273 : case E_V64QImode: mode = V32HImode; break;
20727 : 11828 : case E_V4HImode: mode = V2SImode; break;
20728 : 21390 : case E_V8HImode: mode = V4SImode; break;
20729 : 1004 : case E_V16HImode: mode = V8SImode; break;
20730 : 397 : case E_V32HImode: mode = V16SImode; break;
20731 : 52244 : case E_V4SImode: mode = V2DImode; break;
20732 : 1566 : case E_V8SImode: mode = V4DImode; break;
20733 : 61 : case E_V16SImode: mode = V8DImode; break;
20734 : : default: return false;
20735 : : }
20736 : 216917 : for (i = 0; i < d->nelt; i += 2)
20737 : 202635 : if ((d->perm[i] & 1) || d->perm[i + 1] != d->perm[i] + 1)
20738 : : return false;
20739 : 14282 : nd->vmode = mode;
20740 : 14282 : nd->nelt = d->nelt / 2;
20741 : 94076 : for (i = 0; i < nd->nelt; i++)
20742 : 79794 : nd->perm[i] = d->perm[2 * i] / 2;
20743 : 28564 : if (GET_MODE_INNER (mode) != DImode)
20744 : 12587 : canonicalize_vector_int_perm (nd, nd);
20745 : 14282 : if (nd != d)
20746 : : {
20747 : 9092 : nd->one_operand_p = d->one_operand_p;
20748 : 9092 : nd->testing_p = d->testing_p;
20749 : 9092 : if (d->op0 == d->op1)
20750 : 3000 : nd->op0 = nd->op1 = gen_lowpart (nd->vmode, d->op0);
20751 : : else
20752 : : {
20753 : 6092 : nd->op0 = gen_lowpart (nd->vmode, d->op0);
20754 : 6092 : nd->op1 = gen_lowpart (nd->vmode, d->op1);
20755 : : }
20756 : 9092 : if (d->testing_p)
20757 : 5860 : nd->target = gen_raw_REG (nd->vmode, LAST_VIRTUAL_REGISTER + 1);
20758 : : else
20759 : 3232 : nd->target = gen_reg_rtx (nd->vmode);
20760 : : }
20761 : : return true;
20762 : : }
20763 : :
20764 : : /* Return true if permutation D can be performed as VMODE permutation
20765 : : instead. */
20766 : :
20767 : : static bool
20768 : 6983 : valid_perm_using_mode_p (machine_mode vmode, struct expand_vec_perm_d *d)
20769 : : {
20770 : 6983 : unsigned int i, j, chunk;
20771 : :
20772 : 6983 : if (GET_MODE_CLASS (vmode) != MODE_VECTOR_INT
20773 : 6983 : || GET_MODE_CLASS (d->vmode) != MODE_VECTOR_INT
20774 : 17237 : || GET_MODE_SIZE (vmode) != GET_MODE_SIZE (d->vmode))
20775 : : return false;
20776 : :
20777 : 10254 : if (GET_MODE_NUNITS (vmode) >= d->nelt)
20778 : : return true;
20779 : :
20780 : 4865 : chunk = d->nelt / GET_MODE_NUNITS (vmode);
20781 : 6808 : for (i = 0; i < d->nelt; i += chunk)
20782 : 6565 : if (d->perm[i] & (chunk - 1))
20783 : : return false;
20784 : : else
20785 : 12443 : for (j = 1; j < chunk; ++j)
20786 : 10500 : if (d->perm[i] + j != d->perm[i + j])
20787 : : return false;
20788 : :
20789 : : return true;
20790 : : }
20791 : :
20792 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement D
20793 : : in terms of pshufb, vpperm, vpermq, vpermd, vpermps or vperm2i128. */
20794 : :
20795 : : static bool
20796 : 153074 : expand_vec_perm_pshufb (struct expand_vec_perm_d *d)
20797 : : {
20798 : 153074 : unsigned i, nelt, eltsz, mask;
20799 : 153074 : unsigned char perm[64];
20800 : 153074 : machine_mode vmode;
20801 : 153074 : struct expand_vec_perm_d nd;
20802 : 153074 : rtx rperm[64], vperm, target, op0, op1;
20803 : :
20804 : 153074 : nelt = d->nelt;
20805 : :
20806 : 153074 : if (!d->one_operand_p)
20807 : 250216 : switch (GET_MODE_SIZE (d->vmode))
20808 : : {
20809 : 7093 : case 4:
20810 : 7093 : if (!TARGET_XOP)
20811 : : return false;
20812 : : vmode = V4QImode;
20813 : : break;
20814 : :
20815 : 19246 : case 8:
20816 : 19246 : if (!TARGET_XOP)
20817 : : return false;
20818 : : vmode = V8QImode;
20819 : : break;
20820 : :
20821 : 86016 : case 16:
20822 : 86016 : if (!TARGET_XOP)
20823 : : return false;
20824 : : vmode = V16QImode;
20825 : : break;
20826 : :
20827 : 11799 : case 32:
20828 : 11799 : if (!TARGET_AVX2)
20829 : : return false;
20830 : :
20831 : 4307 : if (valid_perm_using_mode_p (V2TImode, d))
20832 : : {
20833 : 52 : if (d->testing_p)
20834 : : return true;
20835 : :
20836 : : /* Use vperm2i128 insn. The pattern uses
20837 : : V4DImode instead of V2TImode. */
20838 : 48 : target = d->target;
20839 : 48 : if (d->vmode != V4DImode)
20840 : 12 : target = gen_reg_rtx (V4DImode);
20841 : 48 : op0 = gen_lowpart (V4DImode, d->op0);
20842 : 48 : op1 = gen_lowpart (V4DImode, d->op1);
20843 : 48 : rperm[0]
20844 : 48 : = GEN_INT ((d->perm[0] / (nelt / 2))
20845 : : | ((d->perm[nelt / 2] / (nelt / 2)) * 16));
20846 : 48 : emit_insn (gen_avx2_permv2ti (target, op0, op1, rperm[0]));
20847 : 48 : if (target != d->target)
20848 : 12 : emit_move_insn (d->target, gen_lowpart (d->vmode, target));
20849 : 48 : return true;
20850 : : }
20851 : : /* FALLTHRU */
20852 : :
20853 : : default:
20854 : : return false;
20855 : : }
20856 : : else
20857 : 55932 : switch (GET_MODE_SIZE (d->vmode))
20858 : : {
20859 : 3329 : case 4:
20860 : 3329 : if (!TARGET_SSSE3)
20861 : : return false;
20862 : : vmode = V4QImode;
20863 : : break;
20864 : :
20865 : 2466 : case 8:
20866 : 2466 : if (!TARGET_SSSE3)
20867 : : return false;
20868 : : vmode = V8QImode;
20869 : : break;
20870 : :
20871 : 15447 : case 16:
20872 : 15447 : if (!TARGET_SSSE3)
20873 : : return false;
20874 : : vmode = V16QImode;
20875 : : break;
20876 : :
20877 : 6439 : case 32:
20878 : 6439 : if (!TARGET_AVX2)
20879 : : return false;
20880 : :
20881 : : /* V4DImode should be already handled through
20882 : : expand_vselect by vpermq instruction. */
20883 : 2507 : gcc_assert (d->vmode != V4DImode);
20884 : :
20885 : 2507 : vmode = V32QImode;
20886 : 2507 : if (d->vmode == V8SImode
20887 : 2140 : || d->vmode == V16HImode
20888 : 1924 : || d->vmode == V32QImode)
20889 : : {
20890 : : /* First see if vpermq can be used for
20891 : : V8SImode/V16HImode/V32QImode. */
20892 : 1351 : if (valid_perm_using_mode_p (V4DImode, d))
20893 : : {
20894 : 770 : for (i = 0; i < 4; i++)
20895 : 616 : perm[i] = (d->perm[i * nelt / 4] * 4 / nelt) & 3;
20896 : 154 : if (d->testing_p)
20897 : : return true;
20898 : 58 : target = gen_reg_rtx (V4DImode);
20899 : 58 : if (expand_vselect (target, gen_lowpart (V4DImode, d->op0),
20900 : : perm, 4, false))
20901 : : {
20902 : 116 : emit_move_insn (d->target,
20903 : 58 : gen_lowpart (d->vmode, target));
20904 : 58 : return true;
20905 : : }
20906 : : return false;
20907 : : }
20908 : :
20909 : : /* Next see if vpermd can be used. */
20910 : 1197 : if (valid_perm_using_mode_p (V8SImode, d))
20911 : : vmode = V8SImode;
20912 : : }
20913 : : /* Or if vpermps can be used. */
20914 : 1156 : else if (d->vmode == V8SFmode)
20915 : : vmode = V8SImode;
20916 : :
20917 : : if (vmode == V32QImode)
20918 : : {
20919 : : /* vpshufb only works intra lanes, it is not
20920 : : possible to shuffle bytes in between the lanes. */
20921 : 22039 : for (i = 0; i < nelt; ++i)
20922 : 21385 : if ((d->perm[i] ^ i) & (nelt / 2))
20923 : : return false;
20924 : : }
20925 : : break;
20926 : :
20927 : 285 : case 64:
20928 : 285 : if (!TARGET_AVX512BW)
20929 : : return false;
20930 : :
20931 : : /* If vpermq didn't work, vpshufb won't work either. */
20932 : 104 : if (d->vmode == V8DFmode || d->vmode == V8DImode)
20933 : : return false;
20934 : :
20935 : 75 : vmode = V64QImode;
20936 : 75 : if (d->vmode == V16SImode
20937 : 54 : || d->vmode == V32HImode
20938 : 18 : || d->vmode == V64QImode)
20939 : : {
20940 : : /* First see if vpermq can be used for
20941 : : V16SImode/V32HImode/V64QImode. */
20942 : 64 : if (valid_perm_using_mode_p (V8DImode, d))
20943 : : {
20944 : 0 : for (i = 0; i < 8; i++)
20945 : 0 : perm[i] = (d->perm[i * nelt / 8] * 8 / nelt) & 7;
20946 : 0 : if (d->testing_p)
20947 : : return true;
20948 : 0 : target = gen_reg_rtx (V8DImode);
20949 : 0 : if (expand_vselect (target, gen_lowpart (V8DImode, d->op0),
20950 : : perm, 8, false))
20951 : : {
20952 : 0 : emit_move_insn (d->target,
20953 : 0 : gen_lowpart (d->vmode, target));
20954 : 0 : return true;
20955 : : }
20956 : : return false;
20957 : : }
20958 : :
20959 : : /* Next see if vpermd can be used. */
20960 : 64 : if (valid_perm_using_mode_p (V16SImode, d))
20961 : : vmode = V16SImode;
20962 : : }
20963 : : /* Or if vpermps can be used. */
20964 : 11 : else if (d->vmode == V16SFmode)
20965 : : vmode = V16SImode;
20966 : :
20967 : : if (vmode == V64QImode)
20968 : : {
20969 : : /* vpshufb only works intra lanes, it is not
20970 : : possible to shuffle bytes in between the lanes. */
20971 : 226 : for (i = 0; i < nelt; ++i)
20972 : 226 : if ((d->perm[i] ^ i) & (3 * nelt / 4))
20973 : : return false;
20974 : : }
20975 : : break;
20976 : :
20977 : : default:
20978 : : return false;
20979 : : }
20980 : :
20981 : 12104 : if (d->testing_p)
20982 : : return true;
20983 : :
20984 : : /* Try to avoid variable permutation instruction. */
20985 : 9115 : if (canonicalize_vector_int_perm (d, &nd) && expand_vec_perm_1 (&nd))
20986 : : {
20987 : 1838 : emit_move_insn (d->target, gen_lowpart (d->vmode, nd.target));
20988 : 1838 : return true;
20989 : : }
20990 : :
20991 : 7277 : if (vmode == V8SImode)
20992 : 8253 : for (i = 0; i < 8; ++i)
20993 : 7336 : rperm[i] = GEN_INT ((d->perm[i * nelt / 8] * 8 / nelt) & 7);
20994 : 6360 : else if (vmode == V16SImode)
20995 : 544 : for (i = 0; i < 16; ++i)
20996 : 512 : rperm[i] = GEN_INT ((d->perm[i * nelt / 16] * 16 / nelt) & 15);
20997 : : else
20998 : : {
20999 : 6328 : eltsz = GET_MODE_UNIT_SIZE (d->vmode);
21000 : 6328 : if (!d->one_operand_p)
21001 : 3201 : mask = 2 * nelt - 1;
21002 : 3127 : else if (vmode == V64QImode)
21003 : 0 : mask = nelt / 4 - 1;
21004 : 3127 : else if (vmode == V32QImode)
21005 : 648 : mask = nelt / 2 - 1;
21006 : : else
21007 : 2479 : mask = nelt - 1;
21008 : :
21009 : 73968 : for (i = 0; i < nelt; ++i)
21010 : : {
21011 : 67640 : unsigned j, e = d->perm[i] & mask;
21012 : 177176 : for (j = 0; j < eltsz; ++j)
21013 : 109536 : rperm[i * eltsz + j] = GEN_INT (e * eltsz + j);
21014 : : }
21015 : : }
21016 : :
21017 : 7277 : machine_mode vpmode = vmode;
21018 : :
21019 : 7277 : nelt = GET_MODE_SIZE (vmode);
21020 : :
21021 : : /* Emulate narrow modes with V16QI instructions. */
21022 : 7277 : if (nelt < 16)
21023 : : {
21024 : 199 : rtx m128 = GEN_INT (-128);
21025 : :
21026 : : /* Remap elements from the second operand, as we have to
21027 : : account for inactive top elements from the first operand. */
21028 : 199 : if (!d->one_operand_p)
21029 : : {
21030 : 243 : for (i = 0; i < nelt; ++i)
21031 : : {
21032 : 216 : unsigned ival = UINTVAL (rperm[i]);
21033 : 216 : if (ival >= nelt)
21034 : 108 : rperm[i] = GEN_INT (ival + 16 - nelt);
21035 : : }
21036 : : }
21037 : :
21038 : : /* Fill inactive elements in the top positions with zeros. */
21039 : 2279 : for (i = nelt; i < 16; ++i)
21040 : 2080 : rperm[i] = m128;
21041 : :
21042 : : vpmode = V16QImode;
21043 : : }
21044 : :
21045 : 14554 : vperm = gen_rtx_CONST_VECTOR (vpmode,
21046 : 7277 : gen_rtvec_v (GET_MODE_NUNITS (vpmode), rperm));
21047 : 7277 : vperm = force_reg (vpmode, vperm);
21048 : :
21049 : 7277 : if (vmode == d->vmode)
21050 : 2819 : target = d->target;
21051 : : else
21052 : 4458 : target = gen_reg_rtx (vmode);
21053 : :
21054 : 7277 : op0 = gen_lowpart (vmode, d->op0);
21055 : :
21056 : 7277 : if (d->one_operand_p)
21057 : : {
21058 : 4076 : rtx (*gen) (rtx, rtx, rtx);
21059 : :
21060 : 4076 : if (vmode == V4QImode)
21061 : : gen = gen_mmx_pshufbv4qi3;
21062 : : else if (vmode == V8QImode)
21063 : : gen = gen_mmx_pshufbv8qi3;
21064 : : else if (vmode == V16QImode)
21065 : : gen = gen_ssse3_pshufbv16qi3;
21066 : : else if (vmode == V32QImode)
21067 : : gen = gen_avx2_pshufbv32qi3;
21068 : : else if (vmode == V64QImode)
21069 : : gen = gen_avx512bw_pshufbv64qi3;
21070 : : else if (vmode == V8SFmode)
21071 : : gen = gen_avx2_permvarv8sf;
21072 : : else if (vmode == V8SImode)
21073 : : gen = gen_avx2_permvarv8si;
21074 : : else if (vmode == V16SFmode)
21075 : : gen = gen_avx512f_permvarv16sf;
21076 : : else if (vmode == V16SImode)
21077 : : gen = gen_avx512f_permvarv16si;
21078 : : else
21079 : : gcc_unreachable ();
21080 : :
21081 : 4076 : emit_insn (gen (target, op0, vperm));
21082 : : }
21083 : : else
21084 : : {
21085 : 3201 : rtx (*gen) (rtx, rtx, rtx, rtx);
21086 : :
21087 : 3201 : op1 = gen_lowpart (vmode, d->op1);
21088 : :
21089 : 3201 : if (vmode == V4QImode)
21090 : : gen = gen_mmx_ppermv32;
21091 : : else if (vmode == V8QImode)
21092 : : gen = gen_mmx_ppermv64;
21093 : : else if (vmode == V16QImode)
21094 : : gen = gen_xop_pperm;
21095 : : else
21096 : 0 : gcc_unreachable ();
21097 : :
21098 : 3201 : emit_insn (gen (target, op0, op1, vperm));
21099 : : }
21100 : :
21101 : 7277 : if (target != d->target)
21102 : 4458 : emit_move_insn (d->target, gen_lowpart (d->vmode, target));
21103 : :
21104 : : return true;
21105 : : }
21106 : :
21107 : : /* Try to expand one-operand permutation with constant mask. */
21108 : :
21109 : : static bool
21110 : 140669 : ix86_expand_vec_one_operand_perm_avx512 (struct expand_vec_perm_d *d)
21111 : : {
21112 : 140669 : machine_mode mode = GET_MODE (d->op0);
21113 : 140669 : machine_mode maskmode = mode;
21114 : 281338 : unsigned inner_size = GET_MODE_SIZE (GET_MODE_INNER (mode));
21115 : 140669 : rtx (*gen) (rtx, rtx, rtx) = NULL;
21116 : 140669 : rtx target, op0, mask;
21117 : 140669 : rtx vec[64];
21118 : :
21119 : 140669 : if (!rtx_equal_p (d->op0, d->op1))
21120 : : return false;
21121 : :
21122 : 20059 : if (!TARGET_AVX512F)
21123 : : return false;
21124 : :
21125 : : /* Accept VNxHImode and VNxQImode now. */
21126 : 607 : if (!TARGET_AVX512VL && GET_MODE_SIZE (mode) < 64)
21127 : : return false;
21128 : :
21129 : : /* vpermw. */
21130 : 353 : if (!TARGET_AVX512BW && inner_size == 2)
21131 : : return false;
21132 : :
21133 : : /* vpermb. */
21134 : 219 : if (!TARGET_AVX512VBMI && inner_size == 1)
21135 : : return false;
21136 : :
21137 : 130 : switch (mode)
21138 : : {
21139 : : case E_V16SImode:
21140 : : gen = gen_avx512f_permvarv16si;
21141 : : break;
21142 : 4 : case E_V16SFmode:
21143 : 4 : gen = gen_avx512f_permvarv16sf;
21144 : 4 : maskmode = V16SImode;
21145 : 4 : break;
21146 : 0 : case E_V8DImode:
21147 : 0 : gen = gen_avx512f_permvarv8di;
21148 : 0 : break;
21149 : 29 : case E_V8DFmode:
21150 : 29 : gen = gen_avx512f_permvarv8df;
21151 : 29 : maskmode = V8DImode;
21152 : 29 : break;
21153 : 42 : case E_V32HImode:
21154 : 42 : gen = gen_avx512bw_permvarv32hi;
21155 : 42 : break;
21156 : 14 : case E_V16HImode:
21157 : 14 : gen = gen_avx512vl_permvarv16hi;
21158 : 14 : break;
21159 : 6 : case E_V8HImode:
21160 : 6 : gen = gen_avx512vl_permvarv8hi;
21161 : 6 : break;
21162 : 2 : case E_V64QImode:
21163 : 2 : gen = gen_avx512bw_permvarv64qi;
21164 : 2 : break;
21165 : 2 : case E_V32QImode:
21166 : 2 : gen = gen_avx512vl_permvarv32qi;
21167 : 2 : break;
21168 : 0 : case E_V16QImode:
21169 : 0 : gen = gen_avx512vl_permvarv16qi;
21170 : 0 : break;
21171 : :
21172 : : default:
21173 : : return false;
21174 : : }
21175 : :
21176 : 129 : if (d->testing_p)
21177 : : return true;
21178 : :
21179 : 120 : target = d->target;
21180 : 120 : op0 = d->op0;
21181 : 2560 : for (int i = 0; i < d->nelt; ++i)
21182 : 2440 : vec[i] = GEN_INT (d->perm[i]);
21183 : 120 : mask = gen_rtx_CONST_VECTOR (maskmode, gen_rtvec_v (d->nelt, vec));
21184 : 120 : emit_insn (gen (target, op0, force_reg (maskmode, mask)));
21185 : 120 : return true;
21186 : : }
21187 : :
21188 : : static bool expand_vec_perm_palignr (struct expand_vec_perm_d *d, bool);
21189 : :
21190 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to instantiate D
21191 : : in a single instruction. */
21192 : :
21193 : : static bool
21194 : 366650 : expand_vec_perm_1 (struct expand_vec_perm_d *d)
21195 : : {
21196 : 366650 : unsigned i, nelt = d->nelt;
21197 : 366650 : struct expand_vec_perm_d nd;
21198 : :
21199 : : /* Check plain VEC_SELECT first, because AVX has instructions that could
21200 : : match both SEL and SEL+CONCAT, but the plain SEL will allow a memory
21201 : : input where SEL+CONCAT may not. */
21202 : 366650 : if (d->one_operand_p)
21203 : : {
21204 : : int mask = nelt - 1;
21205 : : bool identity_perm = true;
21206 : : bool broadcast_perm = true;
21207 : :
21208 : 519184 : for (i = 0; i < nelt; i++)
21209 : : {
21210 : 460024 : nd.perm[i] = d->perm[i] & mask;
21211 : 460024 : if (nd.perm[i] != i)
21212 : 343632 : identity_perm = false;
21213 : 460024 : if (nd.perm[i])
21214 : 384661 : broadcast_perm = false;
21215 : : }
21216 : :
21217 : 59160 : if (identity_perm)
21218 : : {
21219 : 59 : if (!d->testing_p)
21220 : 5 : emit_move_insn (d->target, d->op0);
21221 : 59 : return true;
21222 : : }
21223 : 59101 : else if (broadcast_perm && TARGET_AVX2)
21224 : : {
21225 : : /* Use vpbroadcast{b,w,d}. */
21226 : 199 : rtx (*gen) (rtx, rtx) = NULL;
21227 : 199 : switch (d->vmode)
21228 : : {
21229 : 1 : case E_V64QImode:
21230 : 1 : if (TARGET_AVX512BW)
21231 : : gen = gen_avx512bw_vec_dupv64qi_1;
21232 : : break;
21233 : 4 : case E_V32QImode:
21234 : 4 : gen = gen_avx2_pbroadcastv32qi_1;
21235 : 4 : break;
21236 : 1 : case E_V32HImode:
21237 : 1 : if (TARGET_AVX512BW)
21238 : : gen = gen_avx512bw_vec_dupv32hi_1;
21239 : : break;
21240 : 4 : case E_V16HImode:
21241 : 4 : gen = gen_avx2_pbroadcastv16hi_1;
21242 : 4 : break;
21243 : 1 : case E_V16SImode:
21244 : 1 : if (TARGET_AVX512F)
21245 : : gen = gen_avx512f_vec_dupv16si_1;
21246 : : break;
21247 : 4 : case E_V8SImode:
21248 : 4 : gen = gen_avx2_pbroadcastv8si_1;
21249 : 4 : break;
21250 : 4 : case E_V16QImode:
21251 : 4 : gen = gen_avx2_pbroadcastv16qi;
21252 : 4 : break;
21253 : 4 : case E_V8HImode:
21254 : 4 : gen = gen_avx2_pbroadcastv8hi;
21255 : 4 : break;
21256 : 0 : case E_V16SFmode:
21257 : 0 : if (TARGET_AVX512F)
21258 : : gen = gen_avx512f_vec_dupv16sf_1;
21259 : : break;
21260 : : case E_V8SFmode:
21261 : : gen = gen_avx2_vec_dupv8sf_1;
21262 : : break;
21263 : 0 : case E_V8DFmode:
21264 : 0 : if (TARGET_AVX512F)
21265 : : gen = gen_avx512f_vec_dupv8df_1;
21266 : : break;
21267 : 0 : case E_V8DImode:
21268 : 0 : if (TARGET_AVX512F)
21269 : : gen = gen_avx512f_vec_dupv8di_1;
21270 : : break;
21271 : : /* For other modes prefer other shuffles this function creates. */
21272 : : default: break;
21273 : : }
21274 : 20 : if (gen != NULL)
21275 : : {
21276 : 23 : if (!d->testing_p)
21277 : 23 : emit_insn (gen (d->target, d->op0));
21278 : 23 : return true;
21279 : : }
21280 : : }
21281 : :
21282 : 59078 : if (expand_vselect (d->target, d->op0, nd.perm, nelt, d->testing_p))
21283 : : return true;
21284 : :
21285 : : /* There are plenty of patterns in sse.md that are written for
21286 : : SEL+CONCAT and are not replicated for a single op. Perhaps
21287 : : that should be changed, to avoid the nastiness here. */
21288 : :
21289 : : /* Recognize interleave style patterns, which means incrementing
21290 : : every other permutation operand. */
21291 : 224892 : for (i = 0; i < nelt; i += 2)
21292 : : {
21293 : 185057 : nd.perm[i] = d->perm[i] & mask;
21294 : 185057 : nd.perm[i + 1] = (d->perm[i + 1] & mask) + nelt;
21295 : : }
21296 : 39835 : if (expand_vselect_vconcat (d->target, d->op0, d->op0, nd.perm, nelt,
21297 : 39835 : d->testing_p))
21298 : : return true;
21299 : :
21300 : : /* Recognize shufps, which means adding {0, 0, nelt, nelt}. */
21301 : 34852 : if (nelt >= 4)
21302 : : {
21303 : 121441 : for (i = 0; i < nelt; i += 4)
21304 : : {
21305 : 86589 : nd.perm[i + 0] = d->perm[i + 0] & mask;
21306 : 86589 : nd.perm[i + 1] = d->perm[i + 1] & mask;
21307 : 86589 : nd.perm[i + 2] = (d->perm[i + 2] & mask) + nelt;
21308 : 86589 : nd.perm[i + 3] = (d->perm[i + 3] & mask) + nelt;
21309 : : }
21310 : :
21311 : 34852 : if (expand_vselect_vconcat (d->target, d->op0, d->op0, nd.perm, nelt,
21312 : 34852 : d->testing_p))
21313 : : return true;
21314 : : }
21315 : : }
21316 : :
21317 : : /* Try the SSE4.1 blend variable merge instructions. */
21318 : 336636 : if (expand_vec_perm_blend (d))
21319 : : return true;
21320 : :
21321 : : /* Try movss/movsd instructions. */
21322 : 335602 : if (expand_vec_perm_movs (d))
21323 : : return true;
21324 : :
21325 : : /* Try the SSE4.1 insertps instruction. */
21326 : 303194 : if (expand_vec_perm_insertps (d))
21327 : : return true;
21328 : :
21329 : : /* Try the fully general two operand permute. */
21330 : 298621 : if (expand_vselect_vconcat (d->target, d->op0, d->op1, d->perm, nelt,
21331 : 298621 : d->testing_p))
21332 : : return true;
21333 : :
21334 : : /* Recognize interleave style patterns with reversed operands. */
21335 : 154161 : if (!d->one_operand_p)
21336 : : {
21337 : 985005 : for (i = 0; i < nelt; ++i)
21338 : : {
21339 : 859892 : unsigned e = d->perm[i];
21340 : 859892 : if (e >= nelt)
21341 : 420443 : e -= nelt;
21342 : : else
21343 : 439449 : e += nelt;
21344 : 859892 : nd.perm[i] = e;
21345 : : }
21346 : :
21347 : 125113 : if (expand_vselect_vconcat (d->target, d->op1, d->op0, nd.perm, nelt,
21348 : 125113 : d->testing_p))
21349 : : return true;
21350 : : }
21351 : :
21352 : : /* Try one of the AVX vpermil variable permutations. */
21353 : 154156 : if (expand_vec_perm_vpermil (d))
21354 : : return true;
21355 : :
21356 : : /* Try the SSSE3 pshufb or XOP vpperm or AVX2 vperm2i128,
21357 : : vpshufb, vpermd, vpermps or vpermq variable permutation. */
21358 : 153074 : if (expand_vec_perm_pshufb (d))
21359 : : return true;
21360 : :
21361 : : /* Try the AVX2 vpalignr instruction. */
21362 : 140764 : if (expand_vec_perm_palignr (d, true))
21363 : : return true;
21364 : :
21365 : : /* Try the AVX512F vperm{w,b,s,d} instructions */
21366 : 140669 : if (ix86_expand_vec_one_operand_perm_avx512 (d))
21367 : : return true;
21368 : :
21369 : : /* Try the AVX512F vpermt2/vpermi2 instructions. */
21370 : 140540 : if (ix86_expand_vec_perm_vpermt2 (NULL_RTX, NULL_RTX, NULL_RTX, NULL_RTX, d))
21371 : : return true;
21372 : :
21373 : : /* See if we can get the same permutation in different vector integer
21374 : : mode. */
21375 : 139652 : if (canonicalize_vector_int_perm (d, &nd) && expand_vec_perm_1 (&nd))
21376 : : {
21377 : 6729 : if (!d->testing_p)
21378 : 1188 : emit_move_insn (d->target, gen_lowpart (d->vmode, nd.target));
21379 : 6729 : return true;
21380 : : }
21381 : : return false;
21382 : : }
21383 : :
21384 : : /* Canonicalize vec_perm index to make the first index
21385 : : always comes from the first vector. */
21386 : : static void
21387 : 8096 : ix86_vec_perm_index_canon (struct expand_vec_perm_d *d)
21388 : : {
21389 : 8096 : unsigned nelt = d->nelt;
21390 : 8096 : if (d->perm[0] < nelt)
21391 : : return;
21392 : :
21393 : 5 : for (unsigned i = 0; i != nelt; i++)
21394 : 4 : d->perm[i] = (d->perm[i] + nelt) % (2 * nelt);
21395 : :
21396 : 1 : std::swap (d->op0, d->op1);
21397 : 1 : return;
21398 : : }
21399 : :
21400 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement D
21401 : : in terms of a pair of shufps+ shufps/pshufd instructions. */
21402 : : static bool
21403 : 98376 : expand_vec_perm_shufps_shufps (struct expand_vec_perm_d *d)
21404 : : {
21405 : 98376 : unsigned char perm1[4];
21406 : 98376 : machine_mode vmode = d->vmode;
21407 : 98376 : bool ok;
21408 : 98376 : unsigned i, j, k, count = 0;
21409 : :
21410 : 98376 : if (d->one_operand_p
21411 : 92374 : || (vmode != V4SImode && vmode != V4SFmode))
21412 : : return false;
21413 : :
21414 : 45880 : if (d->testing_p)
21415 : : return true;
21416 : :
21417 : 8096 : ix86_vec_perm_index_canon (d);
21418 : 48576 : for (i = 0; i < 4; ++i)
21419 : 50703 : count += d->perm[i] > 3 ? 1 : 0;
21420 : :
21421 : 8096 : gcc_assert (count & 3);
21422 : :
21423 : 8096 : rtx tmp = gen_reg_rtx (vmode);
21424 : : /* 2 from op0 and 2 from op1. */
21425 : 8096 : if (count == 2)
21426 : : {
21427 : : unsigned char perm2[4];
21428 : 17905 : for (i = 0, j = 0, k = 2; i < 4; ++i)
21429 : 14324 : if (d->perm[i] & 4)
21430 : : {
21431 : 7162 : perm1[k++] = d->perm[i];
21432 : 7162 : perm2[i] = k - 1;
21433 : : }
21434 : : else
21435 : : {
21436 : 7162 : perm1[j++] = d->perm[i];
21437 : 7162 : perm2[i] = j - 1;
21438 : : }
21439 : :
21440 : : /* shufps. */
21441 : 7162 : ok = expand_vselect_vconcat (tmp, d->op0, d->op1,
21442 : 3581 : perm1, d->nelt, false);
21443 : 3581 : gcc_assert (ok);
21444 : 3581 : if (vmode == V4SImode && TARGET_SSE2)
21445 : : /* pshufd. */
21446 : 2036 : ok = expand_vselect (d->target, tmp,
21447 : 2036 : perm2, d->nelt, false);
21448 : : else
21449 : : {
21450 : : /* shufps. */
21451 : 1545 : perm2[2] += 4;
21452 : 1545 : perm2[3] += 4;
21453 : 1545 : ok = expand_vselect_vconcat (d->target, tmp, tmp,
21454 : 1545 : perm2, d->nelt, false);
21455 : : }
21456 : 3581 : gcc_assert (ok);
21457 : : }
21458 : : /* 3 from one op and 1 from another. */
21459 : : else
21460 : : {
21461 : 22575 : unsigned pair_idx = 8, lone_idx = 8, shift;
21462 : :
21463 : : /* Find the lone index. */
21464 : 22575 : for (i = 0; i < 4; ++i)
21465 : 18060 : if ((d->perm[i] > 3 && count == 1)
21466 : 14739 : || (d->perm[i] < 4 && count == 3))
21467 : 18060 : lone_idx = i;
21468 : :
21469 : : /* When lone_idx is not 0, it must from second op(count == 1). */
21470 : 5709 : gcc_assert (count == (lone_idx ? 1 : 3));
21471 : :
21472 : : /* Find the pair index that sits in the same half as the lone index. */
21473 : 4515 : shift = lone_idx & 2;
21474 : 4515 : pair_idx = 1 - lone_idx + 2 * shift;
21475 : :
21476 : : /* First permutate lone index and pair index into the same vector as
21477 : : [ lone, lone, pair, pair ]. */
21478 : 9030 : perm1[1] = perm1[0]
21479 : 4515 : = (count == 3) ? d->perm[lone_idx] : d->perm[lone_idx] - 4;
21480 : 9030 : perm1[3] = perm1[2]
21481 : 4515 : = (count == 3) ? d->perm[pair_idx] : d->perm[pair_idx] + 4;
21482 : :
21483 : : /* Alway put the vector contains lone indx at the first. */
21484 : 4515 : if (count == 1)
21485 : 3321 : std::swap (d->op0, d->op1);
21486 : :
21487 : : /* shufps. */
21488 : 9030 : ok = expand_vselect_vconcat (tmp, d->op0, d->op1,
21489 : 4515 : perm1, d->nelt, false);
21490 : 4515 : gcc_assert (ok);
21491 : :
21492 : : /* Refine lone and pair index to original order. */
21493 : 4515 : perm1[shift] = lone_idx << 1;
21494 : 4515 : perm1[shift + 1] = pair_idx << 1;
21495 : :
21496 : : /* Select the remaining 2 elements in another vector. */
21497 : 13545 : for (i = 2 - shift; i < 4 - shift; ++i)
21498 : 9030 : perm1[i] = lone_idx == 1 ? d->perm[i] + 4 : d->perm[i];
21499 : :
21500 : : /* Adjust to original selector. */
21501 : 4515 : if (lone_idx > 1)
21502 : 2237 : std::swap (tmp, d->op1);
21503 : :
21504 : : /* shufps. */
21505 : 9030 : ok = expand_vselect_vconcat (d->target, tmp, d->op1,
21506 : 4515 : perm1, d->nelt, false);
21507 : :
21508 : 4515 : gcc_assert (ok);
21509 : : }
21510 : :
21511 : : return true;
21512 : : }
21513 : :
21514 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement D
21515 : : in terms of a pair of pshuflw + pshufhw instructions. */
21516 : :
21517 : : static bool
21518 : 116593 : expand_vec_perm_pshuflw_pshufhw (struct expand_vec_perm_d *d)
21519 : : {
21520 : 116593 : unsigned char perm2[MAX_VECT_LEN];
21521 : 116593 : unsigned i;
21522 : 116593 : bool ok;
21523 : :
21524 : 116593 : if (d->vmode != V8HImode || !d->one_operand_p)
21525 : : return false;
21526 : :
21527 : : /* The two permutations only operate in 64-bit lanes. */
21528 : 15456 : for (i = 0; i < 4; ++i)
21529 : 12473 : if (d->perm[i] >= 4)
21530 : : return false;
21531 : 14859 : for (i = 4; i < 8; ++i)
21532 : 11890 : if (d->perm[i] < 4)
21533 : : return false;
21534 : :
21535 : 2969 : if (d->testing_p)
21536 : : return true;
21537 : :
21538 : : /* Emit the pshuflw. */
21539 : 134 : memcpy (perm2, d->perm, 4);
21540 : 670 : for (i = 4; i < 8; ++i)
21541 : 536 : perm2[i] = i;
21542 : 134 : ok = expand_vselect (d->target, d->op0, perm2, 8, d->testing_p);
21543 : 134 : gcc_assert (ok);
21544 : :
21545 : : /* Emit the pshufhw. */
21546 : 134 : memcpy (perm2 + 4, d->perm + 4, 4);
21547 : 670 : for (i = 0; i < 4; ++i)
21548 : 536 : perm2[i] = i;
21549 : 134 : ok = expand_vselect (d->target, d->target, perm2, 8, d->testing_p);
21550 : 134 : gcc_assert (ok);
21551 : :
21552 : : return true;
21553 : : }
21554 : :
21555 : : /* Try to permute 2 64-bit vectors by punpckldq + 128-bit vector shuffle. */
21556 : : static bool
21557 : 52496 : expand_vec_perm_punpckldq_pshuf (struct expand_vec_perm_d *d)
21558 : : {
21559 : 52496 : if (GET_MODE_BITSIZE (d->vmode) != 64
21560 : 15869 : || !TARGET_MMX_WITH_SSE
21561 : 68365 : || d->one_operand_p)
21562 : : return false;
21563 : :
21564 : 14466 : machine_mode widen_vmode;
21565 : 14466 : switch (d->vmode)
21566 : : {
21567 : : /* pshufd. */
21568 : : case E_V2SImode:
21569 : : widen_vmode = V4SImode;
21570 : : break;
21571 : :
21572 : : /* pshufd. */
21573 : 1151 : case E_V2SFmode:
21574 : 1151 : widen_vmode = V4SFmode;
21575 : 1151 : break;
21576 : :
21577 : 4990 : case E_V4HImode:
21578 : 4990 : widen_vmode = V8HImode;
21579 : : /* pshufb. */
21580 : 4990 : if (!TARGET_SSSE3)
21581 : : return false;
21582 : : break;
21583 : :
21584 : 5779 : case E_V8QImode:
21585 : : /* pshufb. */
21586 : 5779 : widen_vmode = V16QImode;
21587 : 5779 : if (!TARGET_SSSE3)
21588 : : return false;
21589 : : break;
21590 : :
21591 : : default:
21592 : : return false;
21593 : : }
21594 : :
21595 : 5786 : if (d->testing_p)
21596 : : return true;
21597 : :
21598 : 240 : struct expand_vec_perm_d dperm;
21599 : 240 : dperm.target = gen_reg_rtx (widen_vmode);
21600 : 240 : rtx op0 = gen_reg_rtx (widen_vmode);
21601 : 240 : emit_move_insn (op0, gen_rtx_VEC_CONCAT (widen_vmode, d->op0, d->op1));
21602 : 240 : dperm.op0 = op0;
21603 : 240 : dperm.op1 = op0;
21604 : 240 : dperm.vmode = widen_vmode;
21605 : 240 : unsigned nelt = GET_MODE_NUNITS (widen_vmode);
21606 : 240 : dperm.nelt = nelt;
21607 : 240 : dperm.one_operand_p = true;
21608 : 240 : dperm.testing_p = false;
21609 : :
21610 : 1590 : for (unsigned i = 0; i != nelt / 2; i++)
21611 : : {
21612 : 1350 : dperm.perm[i] = d->perm[i];
21613 : 1350 : dperm.perm[i + nelt / 2] = d->perm[i];
21614 : : }
21615 : :
21616 : 240 : gcc_assert (expand_vec_perm_1 (&dperm));
21617 : 240 : emit_move_insn (d->target, lowpart_subreg (d->vmode,
21618 : : dperm.target,
21619 : : dperm.vmode));
21620 : 240 : return true;
21621 : : }
21622 : :
21623 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to simplify
21624 : : the permutation using the SSSE3 palignr instruction. This succeeds
21625 : : when all of the elements in PERM fit within one vector and we merely
21626 : : need to shift them down so that a single vector permutation has a
21627 : : chance to succeed. If SINGLE_INSN_ONLY_P, succeed if only
21628 : : the vpalignr instruction itself can perform the requested permutation. */
21629 : :
21630 : : static bool
21631 : 254388 : expand_vec_perm_palignr (struct expand_vec_perm_d *d, bool single_insn_only_p)
21632 : : {
21633 : 254388 : unsigned i, nelt = d->nelt;
21634 : 254388 : unsigned min, max, minswap, maxswap;
21635 : 254388 : bool in_order, ok, swap = false;
21636 : 254388 : rtx shift, target;
21637 : 254388 : struct expand_vec_perm_d dcopy;
21638 : :
21639 : : /* Even with AVX, palignr only operates on 128-bit vectors,
21640 : : in AVX2 palignr operates on both 128-bit lanes. */
21641 : 130294 : if ((!TARGET_SSSE3 || GET_MODE_SIZE (d->vmode) != 16)
21642 : 303482 : && (!TARGET_AVX2 || GET_MODE_SIZE (d->vmode) != 32))
21643 : : return false;
21644 : :
21645 : 34854 : min = 2 * nelt;
21646 : 34854 : max = 0;
21647 : 34854 : minswap = 2 * nelt;
21648 : 34854 : maxswap = 0;
21649 : 254682 : for (i = 0; i < nelt; ++i)
21650 : : {
21651 : 219828 : unsigned e = d->perm[i];
21652 : 219828 : unsigned eswap = d->perm[i] ^ nelt;
21653 : 439656 : if (GET_MODE_SIZE (d->vmode) == 32)
21654 : : {
21655 : 85616 : e = (e & ((nelt / 2) - 1)) | ((e & nelt) >> 1);
21656 : 85616 : eswap = e ^ (nelt / 2);
21657 : : }
21658 : 219828 : if (e < min)
21659 : : min = e;
21660 : 219828 : if (e > max)
21661 : : max = e;
21662 : 219828 : if (eswap < minswap)
21663 : : minswap = eswap;
21664 : 219828 : if (eswap > maxswap)
21665 : : maxswap = eswap;
21666 : : }
21667 : 34854 : if (min == 0
21668 : 50508 : || max - min >= (GET_MODE_SIZE (d->vmode) == 32 ? nelt / 2 : nelt))
21669 : : {
21670 : 31665 : if (d->one_operand_p
21671 : 31399 : || minswap == 0
21672 : 67055 : || maxswap - minswap >= (GET_MODE_SIZE (d->vmode) == 32
21673 : 17695 : ? nelt / 2 : nelt))
21674 : : return false;
21675 : : swap = true;
21676 : : min = minswap;
21677 : 6383 : max = maxswap;
21678 : : }
21679 : :
21680 : : /* Given that we have SSSE3, we know we'll be able to implement the
21681 : : single operand permutation after the palignr with pshufb for
21682 : : 128-bit vectors. If SINGLE_INSN_ONLY_P, in_order has to be computed
21683 : : first. */
21684 : 6421 : if (d->testing_p && GET_MODE_SIZE (d->vmode) == 16 && !single_insn_only_p)
21685 : : return true;
21686 : :
21687 : 6383 : dcopy = *d;
21688 : 6383 : if (swap)
21689 : : {
21690 : 3194 : dcopy.op0 = d->op1;
21691 : 3194 : dcopy.op1 = d->op0;
21692 : 15970 : for (i = 0; i < nelt; ++i)
21693 : 12776 : dcopy.perm[i] ^= nelt;
21694 : : }
21695 : :
21696 : : in_order = true;
21697 : 32399 : for (i = 0; i < nelt; ++i)
21698 : : {
21699 : 26016 : unsigned e = dcopy.perm[i];
21700 : 26016 : if (GET_MODE_SIZE (d->vmode) == 32
21701 : 952 : && e >= nelt
21702 : 26216 : && (e & (nelt / 2 - 1)) < min)
21703 : 200 : e = e - min - (nelt / 2);
21704 : : else
21705 : 25816 : e = e - min;
21706 : 26016 : if (e != i)
21707 : 19378 : in_order = false;
21708 : 26016 : dcopy.perm[i] = e;
21709 : : }
21710 : 6383 : dcopy.one_operand_p = true;
21711 : :
21712 : 6383 : if (single_insn_only_p && !in_order)
21713 : : return false;
21714 : :
21715 : : /* For AVX2, test whether we can permute the result in one instruction. */
21716 : 3238 : if (d->testing_p)
21717 : : {
21718 : 38 : if (in_order)
21719 : : return true;
21720 : 0 : dcopy.op1 = dcopy.op0;
21721 : 0 : return expand_vec_perm_1 (&dcopy);
21722 : : }
21723 : :
21724 : 6400 : shift = GEN_INT (min * GET_MODE_UNIT_BITSIZE (d->vmode));
21725 : 6400 : if (GET_MODE_SIZE (d->vmode) == 16)
21726 : : {
21727 : 3141 : target = gen_reg_rtx (V1TImode);
21728 : 3141 : emit_insn (gen_ssse3_palignrv1ti (target,
21729 : 3141 : gen_lowpart (V1TImode, dcopy.op1),
21730 : 3141 : gen_lowpart (V1TImode, dcopy.op0),
21731 : : shift));
21732 : : }
21733 : : else
21734 : : {
21735 : 59 : target = gen_reg_rtx (V2TImode);
21736 : 59 : emit_insn (gen_avx2_palignrv2ti (target,
21737 : 59 : gen_lowpart (V2TImode, dcopy.op1),
21738 : 59 : gen_lowpart (V2TImode, dcopy.op0),
21739 : : shift));
21740 : : }
21741 : :
21742 : 3200 : dcopy.op0 = dcopy.op1 = gen_lowpart (d->vmode, target);
21743 : :
21744 : : /* Test for the degenerate case where the alignment by itself
21745 : : produces the desired permutation. */
21746 : 3200 : if (in_order)
21747 : : {
21748 : 57 : emit_move_insn (d->target, dcopy.op0);
21749 : 57 : return true;
21750 : : }
21751 : :
21752 : 3143 : ok = expand_vec_perm_1 (&dcopy);
21753 : 3155 : gcc_assert (ok || GET_MODE_SIZE (d->vmode) == 32);
21754 : :
21755 : : return ok;
21756 : : }
21757 : :
21758 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to simplify
21759 : : the permutation using the SSE4_1 pblendv instruction. Potentially
21760 : : reduces permutation from 2 pshufb and or to 1 pshufb and pblendv. */
21761 : :
21762 : : static bool
21763 : 103598 : expand_vec_perm_pblendv (struct expand_vec_perm_d *d)
21764 : : {
21765 : 103598 : unsigned i, which, nelt = d->nelt;
21766 : 103598 : struct expand_vec_perm_d dcopy, dcopy1;
21767 : 103598 : machine_mode vmode = d->vmode;
21768 : 103598 : bool ok;
21769 : :
21770 : : /* Use the same checks as in expand_vec_perm_blend. */
21771 : 103598 : if (d->one_operand_p)
21772 : : return false;
21773 : 101641 : if (TARGET_AVX2 && GET_MODE_SIZE (vmode) == 32)
21774 : : ;
21775 : 95525 : else if (TARGET_AVX && (vmode == V4DFmode || vmode == V8SFmode))
21776 : : ;
21777 : 89718 : else if (TARGET_SSE4_1
21778 : 99856 : && (GET_MODE_SIZE (vmode) == 16
21779 : 8376 : || (TARGET_MMX_WITH_SSE && GET_MODE_SIZE (vmode) == 8)
21780 : 2328 : || GET_MODE_SIZE (vmode) == 4))
21781 : : ;
21782 : : else
21783 : : return false;
21784 : :
21785 : : /* Figure out where permutation elements stay not in their
21786 : : respective lanes. */
21787 : 132356 : for (i = 0, which = 0; i < nelt; ++i)
21788 : : {
21789 : 114870 : unsigned e = d->perm[i];
21790 : 114870 : if (e != i)
21791 : 156678 : which |= (e < nelt ? 1 : 2);
21792 : : }
21793 : : /* We can pblend the part where elements stay not in their
21794 : : respective lanes only when these elements are all in one
21795 : : half of a permutation.
21796 : : {0 1 8 3 4 5 9 7} is ok as 8, 9 are at not at their respective
21797 : : lanes, but both 8 and 9 >= 8
21798 : : {0 1 8 3 4 5 2 7} is not ok as 2 and 8 are not at their
21799 : : respective lanes and 8 >= 8, but 2 not. */
21800 : 17486 : if (which != 1 && which != 2)
21801 : : return false;
21802 : 3428 : if (d->testing_p && GET_MODE_SIZE (vmode) == 16)
21803 : : return true;
21804 : :
21805 : : /* First we apply one operand permutation to the part where
21806 : : elements stay not in their respective lanes. */
21807 : 2080 : dcopy = *d;
21808 : 2080 : if (which == 2)
21809 : 2080 : dcopy.op0 = dcopy.op1 = d->op1;
21810 : : else
21811 : 0 : dcopy.op0 = dcopy.op1 = d->op0;
21812 : 2080 : if (!d->testing_p)
21813 : 732 : dcopy.target = gen_reg_rtx (vmode);
21814 : 2080 : dcopy.one_operand_p = true;
21815 : :
21816 : 17068 : for (i = 0; i < nelt; ++i)
21817 : 14988 : dcopy.perm[i] = d->perm[i] & (nelt - 1);
21818 : :
21819 : 2080 : ok = expand_vec_perm_1 (&dcopy);
21820 : 4160 : if (GET_MODE_SIZE (vmode) != 16 && !ok)
21821 : : return false;
21822 : : else
21823 : 1785 : gcc_assert (ok);
21824 : 1785 : if (d->testing_p)
21825 : : return true;
21826 : :
21827 : : /* Next we put permuted elements into their positions. */
21828 : 670 : dcopy1 = *d;
21829 : 670 : if (which == 2)
21830 : 670 : dcopy1.op1 = dcopy.target;
21831 : : else
21832 : 0 : dcopy1.op0 = dcopy.target;
21833 : :
21834 : 5706 : for (i = 0; i < nelt; ++i)
21835 : 5036 : dcopy1.perm[i] = ((d->perm[i] >= nelt) ? (nelt + i) : i);
21836 : :
21837 : 670 : ok = expand_vec_perm_blend (&dcopy1);
21838 : 670 : gcc_assert (ok);
21839 : :
21840 : : return true;
21841 : : }
21842 : :
21843 : : static bool expand_vec_perm_interleave3 (struct expand_vec_perm_d *d);
21844 : :
21845 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to simplify
21846 : : a two vector permutation into a single vector permutation by using
21847 : : an interleave operation to merge the vectors. */
21848 : :
21849 : : static bool
21850 : 110493 : expand_vec_perm_interleave2 (struct expand_vec_perm_d *d)
21851 : : {
21852 : 110493 : struct expand_vec_perm_d dremap, dfinal;
21853 : 110493 : unsigned i, nelt = d->nelt, nelt2 = nelt / 2;
21854 : 110493 : unsigned HOST_WIDE_INT contents;
21855 : 110493 : unsigned char remap[2 * MAX_VECT_LEN];
21856 : 110493 : rtx_insn *seq;
21857 : 110493 : bool ok, same_halves = false;
21858 : :
21859 : 110493 : if (GET_MODE_SIZE (d->vmode) == 4
21860 : 203718 : || GET_MODE_SIZE (d->vmode) == 8
21861 : 278723 : || GET_MODE_SIZE (d->vmode) == 16)
21862 : : {
21863 : 101131 : if (d->one_operand_p)
21864 : : return false;
21865 : : }
21866 : 18724 : else if (GET_MODE_SIZE (d->vmode) == 32)
21867 : : {
21868 : 9051 : if (!TARGET_AVX)
21869 : : return false;
21870 : : /* For 32-byte modes allow even d->one_operand_p.
21871 : : The lack of cross-lane shuffling in some instructions
21872 : : might prevent a single insn shuffle. */
21873 : 9051 : dfinal = *d;
21874 : 9051 : dfinal.testing_p = true;
21875 : : /* If expand_vec_perm_interleave3 can expand this into
21876 : : a 3 insn sequence, give up and let it be expanded as
21877 : : 3 insn sequence. While that is one insn longer,
21878 : : it doesn't need a memory operand and in the common
21879 : : case that both interleave low and high permutations
21880 : : with the same operands are adjacent needs 4 insns
21881 : : for both after CSE. */
21882 : 9051 : if (expand_vec_perm_interleave3 (&dfinal))
21883 : : return false;
21884 : : }
21885 : : else
21886 : : return false;
21887 : :
21888 : : /* Examine from whence the elements come. */
21889 : 103974 : contents = 0;
21890 : 765428 : for (i = 0; i < nelt; ++i)
21891 : 661454 : contents |= HOST_WIDE_INT_1U << d->perm[i];
21892 : :
21893 : 103974 : memset (remap, 0xff, sizeof (remap));
21894 : 103974 : dremap = *d;
21895 : :
21896 : 103974 : if (GET_MODE_SIZE (d->vmode) == 4
21897 : 200930 : || GET_MODE_SIZE (d->vmode) == 8)
21898 : : {
21899 : 23355 : unsigned HOST_WIDE_INT h1, h2, h3, h4;
21900 : :
21901 : : /* Split the two input vectors into 4 halves. */
21902 : 23355 : h1 = (HOST_WIDE_INT_1U << nelt2) - 1;
21903 : 23355 : h2 = h1 << nelt2;
21904 : 23355 : h3 = h2 << nelt2;
21905 : 23355 : h4 = h3 << nelt2;
21906 : :
21907 : : /* If the elements from the low halves use interleave low,
21908 : : and similarly for interleave high. */
21909 : 23355 : if ((contents & (h1 | h3)) == contents)
21910 : : {
21911 : : /* punpckl* */
21912 : 3253 : for (i = 0; i < nelt2; ++i)
21913 : : {
21914 : 2296 : remap[i] = i * 2;
21915 : 2296 : remap[i + nelt] = i * 2 + 1;
21916 : 2296 : dremap.perm[i * 2] = i;
21917 : 2296 : dremap.perm[i * 2 + 1] = i + nelt;
21918 : : }
21919 : : }
21920 : 22398 : else if ((contents & (h2 | h4)) == contents)
21921 : : {
21922 : : /* punpckh* */
21923 : 2836 : for (i = 0; i < nelt2; ++i)
21924 : : {
21925 : 2000 : remap[i + nelt2] = i * 2;
21926 : 2000 : remap[i + nelt + nelt2] = i * 2 + 1;
21927 : 2000 : dremap.perm[i * 2] = i + nelt2;
21928 : 2000 : dremap.perm[i * 2 + 1] = i + nelt + nelt2;
21929 : : }
21930 : : }
21931 : : else
21932 : : return false;
21933 : : }
21934 : 161238 : else if (GET_MODE_SIZE (d->vmode) == 16)
21935 : : {
21936 : 71834 : unsigned HOST_WIDE_INT h1, h2, h3, h4;
21937 : :
21938 : : /* Split the two input vectors into 4 halves. */
21939 : 71834 : h1 = (HOST_WIDE_INT_1U << nelt2) - 1;
21940 : 71834 : h2 = h1 << nelt2;
21941 : 71834 : h3 = h2 << nelt2;
21942 : 71834 : h4 = h3 << nelt2;
21943 : :
21944 : : /* If the elements from the low halves use interleave low, and similarly
21945 : : for interleave high. If the elements are from mis-matched halves, we
21946 : : can use shufps for V4SF/V4SI or do a DImode shuffle. */
21947 : 71834 : if ((contents & (h1 | h3)) == contents)
21948 : : {
21949 : : /* punpckl* */
21950 : 6301 : for (i = 0; i < nelt2; ++i)
21951 : : {
21952 : 4626 : remap[i] = i * 2;
21953 : 4626 : remap[i + nelt] = i * 2 + 1;
21954 : 4626 : dremap.perm[i * 2] = i;
21955 : 4626 : dremap.perm[i * 2 + 1] = i + nelt;
21956 : : }
21957 : 1675 : if (!TARGET_SSE2 && d->vmode == V4SImode)
21958 : 0 : dremap.vmode = V4SFmode;
21959 : : }
21960 : 70159 : else if ((contents & (h2 | h4)) == contents)
21961 : : {
21962 : : /* punpckh* */
21963 : 5526 : for (i = 0; i < nelt2; ++i)
21964 : : {
21965 : 4026 : remap[i + nelt2] = i * 2;
21966 : 4026 : remap[i + nelt + nelt2] = i * 2 + 1;
21967 : 4026 : dremap.perm[i * 2] = i + nelt2;
21968 : 4026 : dremap.perm[i * 2 + 1] = i + nelt + nelt2;
21969 : : }
21970 : 1500 : if (!TARGET_SSE2 && d->vmode == V4SImode)
21971 : 0 : dremap.vmode = V4SFmode;
21972 : : }
21973 : 68659 : else if ((contents & (h1 | h4)) == contents)
21974 : : {
21975 : : /* shufps */
21976 : 2639 : for (i = 0; i < nelt2; ++i)
21977 : : {
21978 : 1896 : remap[i] = i;
21979 : 1896 : remap[i + nelt + nelt2] = i + nelt2;
21980 : 1896 : dremap.perm[i] = i;
21981 : 1896 : dremap.perm[i + nelt2] = i + nelt + nelt2;
21982 : : }
21983 : 743 : if (nelt != 4)
21984 : : {
21985 : : /* shufpd */
21986 : 69 : dremap.vmode = V2DImode;
21987 : 69 : dremap.nelt = 2;
21988 : 69 : dremap.perm[0] = 0;
21989 : 69 : dremap.perm[1] = 3;
21990 : : }
21991 : : }
21992 : 67916 : else if ((contents & (h2 | h3)) == contents)
21993 : : {
21994 : : /* shufps */
21995 : 3867 : for (i = 0; i < nelt2; ++i)
21996 : : {
21997 : 2706 : remap[i + nelt2] = i;
21998 : 2706 : remap[i + nelt] = i + nelt2;
21999 : 2706 : dremap.perm[i] = i + nelt2;
22000 : 2706 : dremap.perm[i + nelt2] = i + nelt;
22001 : : }
22002 : 1161 : if (nelt != 4)
22003 : : {
22004 : : /* shufpd */
22005 : 64 : dremap.vmode = V2DImode;
22006 : 64 : dremap.nelt = 2;
22007 : 64 : dremap.perm[0] = 1;
22008 : 64 : dremap.perm[1] = 2;
22009 : : }
22010 : : }
22011 : : else
22012 : : return false;
22013 : : }
22014 : : else
22015 : : {
22016 : 8785 : unsigned int nelt4 = nelt / 4, nzcnt = 0;
22017 : 8785 : unsigned HOST_WIDE_INT q[8];
22018 : 8785 : unsigned int nonzero_halves[4];
22019 : :
22020 : : /* Split the two input vectors into 8 quarters. */
22021 : 8785 : q[0] = (HOST_WIDE_INT_1U << nelt4) - 1;
22022 : 70280 : for (i = 1; i < 8; ++i)
22023 : 61495 : q[i] = q[0] << (nelt4 * i);
22024 : 43925 : for (i = 0; i < 4; ++i)
22025 : 35140 : if (((q[2 * i] | q[2 * i + 1]) & contents) != 0)
22026 : : {
22027 : 32071 : nonzero_halves[nzcnt] = i;
22028 : 32071 : ++nzcnt;
22029 : : }
22030 : :
22031 : 8785 : if (nzcnt == 1)
22032 : : {
22033 : 276 : gcc_assert (d->one_operand_p);
22034 : 276 : nonzero_halves[1] = nonzero_halves[0];
22035 : 276 : same_halves = true;
22036 : : }
22037 : 8509 : else if (d->one_operand_p)
22038 : : {
22039 : 10 : gcc_assert (nonzero_halves[0] == 0);
22040 : 10 : gcc_assert (nonzero_halves[1] == 1);
22041 : : }
22042 : :
22043 : 8785 : if (nzcnt <= 2)
22044 : : {
22045 : 562 : if (d->perm[0] / nelt2 == nonzero_halves[1])
22046 : : {
22047 : : /* Attempt to increase the likelihood that dfinal
22048 : : shuffle will be intra-lane. */
22049 : 280 : std::swap (nonzero_halves[0], nonzero_halves[1]);
22050 : : }
22051 : :
22052 : : /* vperm2f128 or vperm2i128. */
22053 : 3728 : for (i = 0; i < nelt2; ++i)
22054 : : {
22055 : 3166 : remap[i + nonzero_halves[1] * nelt2] = i + nelt2;
22056 : 3166 : remap[i + nonzero_halves[0] * nelt2] = i;
22057 : 3166 : dremap.perm[i + nelt2] = i + nonzero_halves[1] * nelt2;
22058 : 3166 : dremap.perm[i] = i + nonzero_halves[0] * nelt2;
22059 : : }
22060 : :
22061 : 562 : if (d->vmode != V8SFmode
22062 : : && d->vmode != V4DFmode
22063 : : && d->vmode != V8SImode)
22064 : : {
22065 : 149 : dremap.vmode = V8SImode;
22066 : 149 : dremap.nelt = 8;
22067 : 745 : for (i = 0; i < 4; ++i)
22068 : : {
22069 : 596 : dremap.perm[i] = i + nonzero_halves[0] * 4;
22070 : 596 : dremap.perm[i + 4] = i + nonzero_halves[1] * 4;
22071 : : }
22072 : : }
22073 : : }
22074 : 8223 : else if (d->one_operand_p)
22075 : 7806 : return false;
22076 : 8223 : else if (TARGET_AVX2
22077 : 2433 : && (contents & (q[0] | q[2] | q[4] | q[6])) == contents)
22078 : : {
22079 : : /* vpunpckl* */
22080 : 443 : for (i = 0; i < nelt4; ++i)
22081 : : {
22082 : 223 : remap[i] = i * 2;
22083 : 223 : remap[i + nelt] = i * 2 + 1;
22084 : 223 : remap[i + nelt2] = i * 2 + nelt2;
22085 : 223 : remap[i + nelt + nelt2] = i * 2 + nelt2 + 1;
22086 : 223 : dremap.perm[i * 2] = i;
22087 : 223 : dremap.perm[i * 2 + 1] = i + nelt;
22088 : 223 : dremap.perm[i * 2 + nelt2] = i + nelt2;
22089 : 223 : dremap.perm[i * 2 + nelt2 + 1] = i + nelt + nelt2;
22090 : : }
22091 : : }
22092 : 8003 : else if (TARGET_AVX2
22093 : 2213 : && (contents & (q[1] | q[3] | q[5] | q[7])) == contents)
22094 : : {
22095 : : /* vpunpckh* */
22096 : 397 : for (i = 0; i < nelt4; ++i)
22097 : : {
22098 : 200 : remap[i + nelt4] = i * 2;
22099 : 200 : remap[i + nelt + nelt4] = i * 2 + 1;
22100 : 200 : remap[i + nelt2 + nelt4] = i * 2 + nelt2;
22101 : 200 : remap[i + nelt + nelt2 + nelt4] = i * 2 + nelt2 + 1;
22102 : 200 : dremap.perm[i * 2] = i + nelt4;
22103 : 200 : dremap.perm[i * 2 + 1] = i + nelt + nelt4;
22104 : 200 : dremap.perm[i * 2 + nelt2] = i + nelt2 + nelt4;
22105 : 200 : dremap.perm[i * 2 + nelt2 + 1] = i + nelt + nelt2 + nelt4;
22106 : : }
22107 : : }
22108 : : else
22109 : : return false;
22110 : : }
22111 : :
22112 : : /* Use the remapping array set up above to move the elements from their
22113 : : swizzled locations into their final destinations. */
22114 : 7851 : dfinal = *d;
22115 : 50975 : for (i = 0; i < nelt; ++i)
22116 : : {
22117 : 43124 : unsigned e = remap[d->perm[i]];
22118 : 43124 : gcc_assert (e < nelt);
22119 : : /* If same_halves is true, both halves of the remapped vector are the
22120 : : same. Avoid cross-lane accesses if possible. */
22121 : 43124 : if (same_halves && i >= nelt2)
22122 : : {
22123 : 940 : gcc_assert (e < nelt2);
22124 : 940 : dfinal.perm[i] = e + nelt2;
22125 : : }
22126 : : else
22127 : 42184 : dfinal.perm[i] = e;
22128 : : }
22129 : 7851 : if (!d->testing_p)
22130 : : {
22131 : 2633 : dremap.target = gen_reg_rtx (dremap.vmode);
22132 : 2633 : dfinal.op0 = gen_lowpart (dfinal.vmode, dremap.target);
22133 : : }
22134 : 7851 : dfinal.op1 = dfinal.op0;
22135 : 7851 : dfinal.one_operand_p = true;
22136 : :
22137 : : /* Test if the final remap can be done with a single insn. For V4SFmode or
22138 : : V4SImode this *will* succeed. For V8HImode or V16QImode it may not. */
22139 : 7851 : start_sequence ();
22140 : 7851 : ok = expand_vec_perm_1 (&dfinal);
22141 : 7851 : seq = end_sequence ();
22142 : :
22143 : 7851 : if (!ok)
22144 : : return false;
22145 : :
22146 : 6746 : if (d->testing_p)
22147 : : return true;
22148 : :
22149 : 2595 : if (dremap.vmode != dfinal.vmode)
22150 : : {
22151 : 53 : dremap.op0 = gen_lowpart (dremap.vmode, dremap.op0);
22152 : 53 : dremap.op1 = gen_lowpart (dremap.vmode, dremap.op1);
22153 : : }
22154 : :
22155 : 2595 : ok = expand_vec_perm_1 (&dremap);
22156 : 2595 : gcc_assert (ok);
22157 : :
22158 : 2595 : emit_insn (seq);
22159 : 2595 : return true;
22160 : : }
22161 : :
22162 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to simplify
22163 : : a single vector cross-lane permutation into vpermq followed
22164 : : by any of the single insn permutations. */
22165 : :
22166 : : static bool
22167 : 103647 : expand_vec_perm_vpermq_perm_1 (struct expand_vec_perm_d *d)
22168 : : {
22169 : 103647 : struct expand_vec_perm_d dremap, dfinal;
22170 : 103647 : unsigned i, j, nelt = d->nelt, nelt2 = nelt / 2, nelt4 = nelt / 4;
22171 : 103647 : unsigned contents[2];
22172 : 103647 : bool ok;
22173 : :
22174 : 103647 : if (!(TARGET_AVX2
22175 : 4227 : && (d->vmode == V32QImode || d->vmode == V16HImode)
22176 : 486 : && d->one_operand_p))
22177 : : return false;
22178 : :
22179 : 6 : contents[0] = 0;
22180 : 6 : contents[1] = 0;
22181 : 86 : for (i = 0; i < nelt2; ++i)
22182 : : {
22183 : 80 : contents[0] |= 1u << (d->perm[i] / nelt4);
22184 : 80 : contents[1] |= 1u << (d->perm[i + nelt2] / nelt4);
22185 : : }
22186 : :
22187 : 6 : for (i = 0; i < 2; ++i)
22188 : : {
22189 : : unsigned int cnt = 0;
22190 : 18 : for (j = 0; j < 4; ++j)
22191 : 18 : if ((contents[i] & (1u << j)) != 0 && ++cnt > 2)
22192 : : return false;
22193 : : }
22194 : :
22195 : 0 : if (d->testing_p)
22196 : : return true;
22197 : :
22198 : 0 : dremap = *d;
22199 : 0 : dremap.vmode = V4DImode;
22200 : 0 : dremap.nelt = 4;
22201 : 0 : dremap.target = gen_reg_rtx (V4DImode);
22202 : 0 : dremap.op0 = gen_lowpart (V4DImode, d->op0);
22203 : 0 : dremap.op1 = dremap.op0;
22204 : 0 : dremap.one_operand_p = true;
22205 : 0 : for (i = 0; i < 2; ++i)
22206 : : {
22207 : : unsigned int cnt = 0;
22208 : 0 : for (j = 0; j < 4; ++j)
22209 : 0 : if ((contents[i] & (1u << j)) != 0)
22210 : 0 : dremap.perm[2 * i + cnt++] = j;
22211 : 0 : for (; cnt < 2; ++cnt)
22212 : 0 : dremap.perm[2 * i + cnt] = 0;
22213 : : }
22214 : :
22215 : 0 : dfinal = *d;
22216 : 0 : dfinal.op0 = gen_lowpart (dfinal.vmode, dremap.target);
22217 : 0 : dfinal.op1 = dfinal.op0;
22218 : 0 : dfinal.one_operand_p = true;
22219 : 0 : for (i = 0, j = 0; i < nelt; ++i)
22220 : : {
22221 : 0 : if (i == nelt2)
22222 : 0 : j = 2;
22223 : 0 : dfinal.perm[i] = (d->perm[i] & (nelt4 - 1)) | (j ? nelt2 : 0);
22224 : 0 : if ((d->perm[i] / nelt4) == dremap.perm[j])
22225 : : ;
22226 : 0 : else if ((d->perm[i] / nelt4) == dremap.perm[j + 1])
22227 : 0 : dfinal.perm[i] |= nelt4;
22228 : : else
22229 : 0 : gcc_unreachable ();
22230 : : }
22231 : :
22232 : 0 : ok = expand_vec_perm_1 (&dremap);
22233 : 0 : gcc_assert (ok);
22234 : :
22235 : 0 : ok = expand_vec_perm_1 (&dfinal);
22236 : 0 : gcc_assert (ok);
22237 : :
22238 : : return true;
22239 : : }
22240 : :
22241 : : static bool canonicalize_perm (struct expand_vec_perm_d *d);
22242 : :
22243 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to expand
22244 : : a vector permutation using two instructions, vperm2f128 resp.
22245 : : vperm2i128 followed by any single in-lane permutation. */
22246 : :
22247 : : static bool
22248 : 103647 : expand_vec_perm_vperm2f128 (struct expand_vec_perm_d *d)
22249 : : {
22250 : 103647 : struct expand_vec_perm_d dfirst, dsecond;
22251 : 103647 : unsigned i, j, nelt = d->nelt, nelt2 = nelt / 2, perm;
22252 : 103647 : bool ok;
22253 : :
22254 : 103647 : if (!TARGET_AVX
22255 : 27910 : || GET_MODE_SIZE (d->vmode) != 32
22256 : 111953 : || (d->vmode != V8SFmode && d->vmode != V4DFmode && !TARGET_AVX2))
22257 : : return false;
22258 : :
22259 : 7933 : dsecond = *d;
22260 : 7933 : dsecond.one_operand_p = false;
22261 : 7933 : dsecond.testing_p = true;
22262 : :
22263 : : /* ((perm << 2)|perm) & 0x33 is the vperm2[fi]128
22264 : : immediate. For perm < 16 the second permutation uses
22265 : : d->op0 as first operand, for perm >= 16 it uses d->op1
22266 : : as first operand. The second operand is the result of
22267 : : vperm2[fi]128. */
22268 : 261015 : for (perm = 0; perm < 32; perm++)
22269 : : {
22270 : : /* Ignore permutations which do not move anything cross-lane. */
22271 : 253137 : if (perm < 16)
22272 : : {
22273 : : /* The second shuffle for e.g. V4DFmode has
22274 : : 0123 and ABCD operands.
22275 : : Ignore AB23, as 23 is already in the second lane
22276 : : of the first operand. */
22277 : 126760 : if ((perm & 0xc) == (1 << 2)) continue;
22278 : : /* And 01CD, as 01 is in the first lane of the first
22279 : : operand. */
22280 : 95052 : if ((perm & 3) == 0) continue;
22281 : : /* And 4567, as then the vperm2[fi]128 doesn't change
22282 : : anything on the original 4567 second operand. */
22283 : 71279 : if ((perm & 0xf) == ((3 << 2) | 2)) continue;
22284 : : }
22285 : : else
22286 : : {
22287 : : /* The second shuffle for e.g. V4DFmode has
22288 : : 4567 and ABCD operands.
22289 : : Ignore AB67, as 67 is already in the second lane
22290 : : of the first operand. */
22291 : 126377 : if ((perm & 0xc) == (3 << 2)) continue;
22292 : : /* And 45CD, as 45 is in the first lane of the first
22293 : : operand. */
22294 : 94865 : if ((perm & 3) == 2) continue;
22295 : : /* And 0123, as then the vperm2[fi]128 doesn't change
22296 : : anything on the original 0123 first operand. */
22297 : 71166 : if ((perm & 0xf) == (1 << 2)) continue;
22298 : : }
22299 : :
22300 : 351726 : for (i = 0; i < nelt; i++)
22301 : : {
22302 : 349635 : j = d->perm[i] / nelt2;
22303 : 647642 : if (j == ((perm >> (2 * (i >= nelt2))) & 3))
22304 : 84149 : dsecond.perm[i] = nelt + (i & nelt2) + (d->perm[i] & (nelt2 - 1));
22305 : 446963 : else if (j == (unsigned) (i >= nelt2) + 2 * (perm >= 16))
22306 : 140956 : dsecond.perm[i] = d->perm[i] & (nelt - 1);
22307 : : else
22308 : : break;
22309 : : }
22310 : :
22311 : 126621 : if (i == nelt)
22312 : : {
22313 : 2091 : start_sequence ();
22314 : 2091 : ok = expand_vec_perm_1 (&dsecond);
22315 : 2091 : end_sequence ();
22316 : : }
22317 : : else
22318 : : ok = false;
22319 : :
22320 : 2091 : if (ok)
22321 : : {
22322 : 49 : if (d->testing_p)
22323 : : return true;
22324 : :
22325 : : /* Found a usable second shuffle. dfirst will be
22326 : : vperm2f128 on d->op0 and d->op1. */
22327 : 33 : dsecond.testing_p = false;
22328 : 33 : dfirst = *d;
22329 : 33 : dfirst.target = gen_reg_rtx (d->vmode);
22330 : 169 : for (i = 0; i < nelt; i++)
22331 : 272 : dfirst.perm[i] = (i & (nelt2 - 1))
22332 : 204 : + ((perm >> (2 * (i >= nelt2))) & 3) * nelt2;
22333 : :
22334 : 33 : canonicalize_perm (&dfirst);
22335 : 33 : ok = expand_vec_perm_1 (&dfirst);
22336 : 33 : gcc_assert (ok);
22337 : :
22338 : : /* And dsecond is some single insn shuffle, taking
22339 : : d->op0 and result of vperm2f128 (if perm < 16) or
22340 : : d->op1 and result of vperm2f128 (otherwise). */
22341 : 33 : if (perm >= 16)
22342 : 33 : dsecond.op0 = dsecond.op1;
22343 : 33 : dsecond.op1 = dfirst.target;
22344 : :
22345 : 33 : ok = expand_vec_perm_1 (&dsecond);
22346 : 33 : gcc_assert (ok);
22347 : :
22348 : : return true;
22349 : : }
22350 : :
22351 : : /* For one operand, the only useful vperm2f128 permutation is 0x01
22352 : : aka lanes swap. */
22353 : 126572 : if (d->one_operand_p)
22354 : : return false;
22355 : : }
22356 : :
22357 : : return false;
22358 : : }
22359 : :
22360 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to simplify
22361 : : a two vector permutation using 2 intra-lane interleave insns
22362 : : and cross-lane shuffle for 32-byte vectors. */
22363 : :
22364 : : static bool
22365 : 38483 : expand_vec_perm_interleave3 (struct expand_vec_perm_d *d)
22366 : : {
22367 : 38483 : unsigned i, nelt;
22368 : 38483 : rtx (*gen) (rtx, rtx, rtx);
22369 : :
22370 : 38483 : if (d->one_operand_p)
22371 : : return false;
22372 : 36092 : if (TARGET_AVX2 && GET_MODE_SIZE (d->vmode) == 32)
22373 : : ;
22374 : 28546 : else if (TARGET_AVX && (d->vmode == V8SFmode || d->vmode == V4DFmode))
22375 : : ;
22376 : : else
22377 : : return false;
22378 : :
22379 : 12434 : nelt = d->nelt;
22380 : 12434 : if (d->perm[0] != 0 && d->perm[0] != nelt / 2)
22381 : : return false;
22382 : 11545 : for (i = 0; i < nelt; i += 2)
22383 : 11113 : if (d->perm[i] != d->perm[0] + i / 2
22384 : 10240 : || d->perm[i + 1] != d->perm[0] + i / 2 + nelt)
22385 : : return false;
22386 : :
22387 : 432 : if (d->testing_p)
22388 : : return true;
22389 : :
22390 : 56 : switch (d->vmode)
22391 : : {
22392 : 32 : case E_V32QImode:
22393 : 32 : if (d->perm[0])
22394 : : gen = gen_vec_interleave_highv32qi;
22395 : : else
22396 : 16 : gen = gen_vec_interleave_lowv32qi;
22397 : : break;
22398 : 18 : case E_V16HImode:
22399 : 18 : if (d->perm[0])
22400 : : gen = gen_vec_interleave_highv16hi;
22401 : : else
22402 : 9 : gen = gen_vec_interleave_lowv16hi;
22403 : : break;
22404 : 0 : case E_V8SImode:
22405 : 0 : if (d->perm[0])
22406 : : gen = gen_vec_interleave_highv8si;
22407 : : else
22408 : 0 : gen = gen_vec_interleave_lowv8si;
22409 : : break;
22410 : 4 : case E_V4DImode:
22411 : 4 : if (d->perm[0])
22412 : : gen = gen_vec_interleave_highv4di;
22413 : : else
22414 : 2 : gen = gen_vec_interleave_lowv4di;
22415 : : break;
22416 : 2 : case E_V8SFmode:
22417 : 2 : if (d->perm[0])
22418 : : gen = gen_vec_interleave_highv8sf;
22419 : : else
22420 : 1 : gen = gen_vec_interleave_lowv8sf;
22421 : : break;
22422 : 0 : case E_V4DFmode:
22423 : 0 : if (d->perm[0])
22424 : : gen = gen_vec_interleave_highv4df;
22425 : : else
22426 : 0 : gen = gen_vec_interleave_lowv4df;
22427 : : break;
22428 : 0 : default:
22429 : 0 : gcc_unreachable ();
22430 : : }
22431 : :
22432 : 56 : emit_insn (gen (d->target, d->op0, d->op1));
22433 : 56 : return true;
22434 : : }
22435 : :
22436 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement
22437 : : a single vector permutation using a single intra-lane vector
22438 : : permutation, vperm2f128 swapping the lanes and vblend* insn blending
22439 : : the non-swapped and swapped vectors together. */
22440 : :
22441 : : static bool
22442 : 29266 : expand_vec_perm_vperm2f128_vblend (struct expand_vec_perm_d *d)
22443 : : {
22444 : 29266 : struct expand_vec_perm_d dfirst, dsecond;
22445 : 29266 : unsigned i, j, msk, nelt = d->nelt, nelt2 = nelt / 2;
22446 : 29266 : rtx_insn *seq;
22447 : 29266 : bool ok;
22448 : 29266 : rtx (*blend) (rtx, rtx, rtx, rtx) = NULL;
22449 : :
22450 : 29266 : if (!TARGET_AVX
22451 : 4551 : || TARGET_AVX2
22452 : 3187 : || (d->vmode != V8SFmode && d->vmode != V4DFmode)
22453 : 2814 : || !d->one_operand_p)
22454 : : return false;
22455 : :
22456 : 0 : dfirst = *d;
22457 : 0 : for (i = 0; i < nelt; i++)
22458 : 0 : dfirst.perm[i] = 0xff;
22459 : 0 : for (i = 0, msk = 0; i < nelt; i++)
22460 : : {
22461 : 0 : j = (d->perm[i] & nelt2) ? i | nelt2 : i & ~nelt2;
22462 : 0 : if (dfirst.perm[j] != 0xff && dfirst.perm[j] != d->perm[i])
22463 : : return false;
22464 : 0 : dfirst.perm[j] = d->perm[i];
22465 : 0 : if (j != i)
22466 : 0 : msk |= (1 << i);
22467 : : }
22468 : 0 : for (i = 0; i < nelt; i++)
22469 : 0 : if (dfirst.perm[i] == 0xff)
22470 : 0 : dfirst.perm[i] = i;
22471 : :
22472 : 0 : if (!d->testing_p)
22473 : 0 : dfirst.target = gen_reg_rtx (dfirst.vmode);
22474 : :
22475 : 0 : start_sequence ();
22476 : 0 : ok = expand_vec_perm_1 (&dfirst);
22477 : 0 : seq = end_sequence ();
22478 : :
22479 : 0 : if (!ok)
22480 : : return false;
22481 : :
22482 : 0 : if (d->testing_p)
22483 : : return true;
22484 : :
22485 : 0 : emit_insn (seq);
22486 : :
22487 : 0 : dsecond = *d;
22488 : 0 : dsecond.op0 = dfirst.target;
22489 : 0 : dsecond.op1 = dfirst.target;
22490 : 0 : dsecond.one_operand_p = true;
22491 : 0 : dsecond.target = gen_reg_rtx (dsecond.vmode);
22492 : 0 : for (i = 0; i < nelt; i++)
22493 : 0 : dsecond.perm[i] = i ^ nelt2;
22494 : :
22495 : 0 : ok = expand_vec_perm_1 (&dsecond);
22496 : 0 : gcc_assert (ok);
22497 : :
22498 : 0 : blend = d->vmode == V8SFmode ? gen_avx_blendps256 : gen_avx_blendpd256;
22499 : 0 : emit_insn (blend (d->target, dfirst.target, dsecond.target, GEN_INT (msk)));
22500 : 0 : return true;
22501 : : }
22502 : :
22503 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement
22504 : : a two vector permutation using two single vector permutations and
22505 : : {,v}{,p}unpckl{ps,pd,bw,wd,dq}. If two_insn, succeed only if one
22506 : : of dfirst or dsecond is identity permutation. */
22507 : :
22508 : : static bool
22509 : 131079 : expand_vec_perm_2perm_interleave (struct expand_vec_perm_d *d, bool two_insn)
22510 : : {
22511 : 131079 : unsigned i, nelt = d->nelt, nelt2 = nelt / 2, lane = nelt;
22512 : 131079 : struct expand_vec_perm_d dfirst, dsecond, dfinal;
22513 : 131079 : bool ident1 = true, ident2 = true;
22514 : :
22515 : 131079 : if (d->one_operand_p)
22516 : : return false;
22517 : :
22518 : 238220 : if (GET_MODE_SIZE (d->vmode) == 16)
22519 : : {
22520 : 74845 : if (!TARGET_SSE)
22521 : : return false;
22522 : 74845 : if (d->vmode != V4SFmode && d->vmode != V2DFmode && !TARGET_SSE2)
22523 : : return false;
22524 : : }
22525 : 88530 : else if (GET_MODE_SIZE (d->vmode) == 32)
22526 : : {
22527 : 11679 : if (!TARGET_AVX)
22528 : : return false;
22529 : 11679 : if (d->vmode != V8SFmode && d->vmode != V4DFmode && !TARGET_AVX2)
22530 : : return false;
22531 : : lane = nelt2;
22532 : : }
22533 : : else
22534 : : return false;
22535 : :
22536 : 285391 : for (i = 1; i < nelt; i++)
22537 : 241174 : if ((d->perm[i] >= nelt) != ((d->perm[0] >= nelt) ^ (i & 1)))
22538 : : return false;
22539 : :
22540 : 44217 : dfirst = *d;
22541 : 44217 : dsecond = *d;
22542 : 44217 : dfinal = *d;
22543 : 44217 : dfirst.op1 = dfirst.op0;
22544 : 44217 : dfirst.one_operand_p = true;
22545 : 44217 : dsecond.op0 = dsecond.op1;
22546 : 44217 : dsecond.one_operand_p = true;
22547 : :
22548 : 278269 : for (i = 0; i < nelt; i++)
22549 : 234052 : if (d->perm[i] >= nelt)
22550 : : {
22551 : 117026 : dsecond.perm[i / 2 + (i >= lane ? lane / 2 : 0)] = d->perm[i] - nelt;
22552 : 117026 : if (d->perm[i] - nelt != i / 2 + (i >= lane ? lane / 2 : 0))
22553 : 108410 : ident2 = false;
22554 : 117026 : dsecond.perm[i / 2 + (i >= lane ? lane : lane / 2)]
22555 : 117026 : = d->perm[i] - nelt;
22556 : : }
22557 : : else
22558 : : {
22559 : 117026 : dfirst.perm[i / 2 + (i >= lane ? lane / 2 : 0)] = d->perm[i];
22560 : 117026 : if (d->perm[i] != i / 2 + (i >= lane ? lane / 2 : 0))
22561 : 99980 : ident1 = false;
22562 : 117026 : dfirst.perm[i / 2 + (i >= lane ? lane : lane / 2)] = d->perm[i];
22563 : : }
22564 : :
22565 : 44217 : if (two_insn && !ident1 && !ident2)
22566 : : return false;
22567 : :
22568 : 4155 : if (!d->testing_p)
22569 : : {
22570 : 214 : if (!ident1)
22571 : 144 : dfinal.op0 = dfirst.target = gen_reg_rtx (d->vmode);
22572 : 214 : if (!ident2)
22573 : 148 : dfinal.op1 = dsecond.target = gen_reg_rtx (d->vmode);
22574 : 214 : if (d->perm[0] >= nelt)
22575 : 0 : std::swap (dfinal.op0, dfinal.op1);
22576 : : }
22577 : :
22578 : 4155 : bool ok;
22579 : 4155 : rtx_insn *seq1 = NULL, *seq2 = NULL;
22580 : :
22581 : 4155 : if (!ident1)
22582 : : {
22583 : 2843 : start_sequence ();
22584 : 2843 : ok = expand_vec_perm_1 (&dfirst);
22585 : 2843 : seq1 = end_sequence ();
22586 : :
22587 : 2843 : if (!ok)
22588 : : return false;
22589 : : }
22590 : :
22591 : 2166 : if (!ident2)
22592 : : {
22593 : 2074 : start_sequence ();
22594 : 2074 : ok = expand_vec_perm_1 (&dsecond);
22595 : 2074 : seq2 = end_sequence ();
22596 : :
22597 : 2074 : if (!ok)
22598 : : return false;
22599 : : }
22600 : :
22601 : 600 : if (d->testing_p)
22602 : : return true;
22603 : :
22604 : 680 : for (i = 0; i < nelt; i++)
22605 : : {
22606 : 544 : dfinal.perm[i] = i / 2;
22607 : 544 : if (i >= lane)
22608 : 4 : dfinal.perm[i] += lane / 2;
22609 : 544 : if ((i & 1) != 0)
22610 : 272 : dfinal.perm[i] += nelt;
22611 : : }
22612 : 136 : emit_insn (seq1);
22613 : 136 : emit_insn (seq2);
22614 : 136 : ok = expand_vselect_vconcat (dfinal.target, dfinal.op0, dfinal.op1,
22615 : : dfinal.perm, dfinal.nelt, false);
22616 : 136 : gcc_assert (ok);
22617 : : return true;
22618 : : }
22619 : :
22620 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to simplify
22621 : : the permutation using two single vector permutations and the SSE4_1 pblendv
22622 : : instruction. If two_insn, succeed only if one of dfirst or dsecond is
22623 : : identity permutation. */
22624 : :
22625 : : static bool
22626 : 130479 : expand_vec_perm_2perm_pblendv (struct expand_vec_perm_d *d, bool two_insn)
22627 : : {
22628 : 130479 : unsigned i, nelt = d->nelt;
22629 : 130479 : struct expand_vec_perm_d dfirst, dsecond, dfinal;
22630 : 130479 : machine_mode vmode = d->vmode;
22631 : 130479 : bool ident1 = true, ident2 = true;
22632 : :
22633 : : /* Use the same checks as in expand_vec_perm_blend. */
22634 : 130479 : if (d->one_operand_p)
22635 : : return false;
22636 : 122948 : if (TARGET_AVX2 && GET_MODE_SIZE (vmode) == 32)
22637 : : ;
22638 : 115948 : else if (TARGET_AVX && (vmode == V4DFmode || vmode == V8SFmode))
22639 : : ;
22640 : 107783 : else if (TARGET_SSE4_1
22641 : 117366 : && (GET_MODE_SIZE (vmode) == 16
22642 : 8462 : || (TARGET_MMX_WITH_SSE && GET_MODE_SIZE (vmode) == 8)
22643 : 2463 : || GET_MODE_SIZE (vmode) == 4))
22644 : : ;
22645 : : else
22646 : : return false;
22647 : :
22648 : 19250 : dfirst = *d;
22649 : 19250 : dsecond = *d;
22650 : 19250 : dfinal = *d;
22651 : 19250 : dfirst.op1 = dfirst.op0;
22652 : 19250 : dfirst.one_operand_p = true;
22653 : 19250 : dsecond.op0 = dsecond.op1;
22654 : 19250 : dsecond.one_operand_p = true;
22655 : :
22656 : 158196 : for (i = 0; i < nelt; ++i)
22657 : 138946 : if (d->perm[i] >= nelt)
22658 : : {
22659 : 69470 : dfirst.perm[i] = 0xff;
22660 : 69470 : dsecond.perm[i] = d->perm[i] - nelt;
22661 : 69470 : if (d->perm[i] != i + nelt)
22662 : 138946 : ident2 = false;
22663 : : }
22664 : : else
22665 : : {
22666 : 69476 : dsecond.perm[i] = 0xff;
22667 : 69476 : dfirst.perm[i] = d->perm[i];
22668 : 69476 : if (d->perm[i] != i)
22669 : 138946 : ident1 = false;
22670 : : }
22671 : :
22672 : 19250 : if (two_insn && !ident1 && !ident2)
22673 : : return false;
22674 : :
22675 : : /* For now. Ideally treat 0xff as a wildcard. */
22676 : 65417 : for (i = 0; i < nelt; ++i)
22677 : 58328 : if (dfirst.perm[i] == 0xff)
22678 : : {
22679 : 30060 : if (GET_MODE_SIZE (vmode) == 32
22680 : 30060 : && dfirst.perm[i ^ (nelt / 2)] != 0xff)
22681 : 18524 : dfirst.perm[i] = dfirst.perm[i ^ (nelt / 2)] ^ (nelt / 2);
22682 : : else
22683 : 11536 : dfirst.perm[i] = i;
22684 : : }
22685 : : else
22686 : : {
22687 : 28268 : if (GET_MODE_SIZE (vmode) == 32
22688 : 28268 : && dsecond.perm[i ^ (nelt / 2)] != 0xff)
22689 : 17132 : dsecond.perm[i] = dsecond.perm[i ^ (nelt / 2)] ^ (nelt / 2);
22690 : : else
22691 : 11136 : dsecond.perm[i] = i;
22692 : : }
22693 : :
22694 : 7089 : if (!d->testing_p)
22695 : : {
22696 : 2255 : if (!ident1)
22697 : 2131 : dfinal.op0 = dfirst.target = gen_reg_rtx (d->vmode);
22698 : 2255 : if (!ident2)
22699 : 1019 : dfinal.op1 = dsecond.target = gen_reg_rtx (d->vmode);
22700 : : }
22701 : :
22702 : 7089 : bool ok;
22703 : 7089 : rtx_insn *seq1 = NULL, *seq2 = NULL;
22704 : :
22705 : 7089 : if (!ident1)
22706 : : {
22707 : 6500 : start_sequence ();
22708 : 6500 : ok = expand_vec_perm_1 (&dfirst);
22709 : 6500 : seq1 = end_sequence ();
22710 : :
22711 : 6500 : if (!ok)
22712 : : return false;
22713 : : }
22714 : :
22715 : 4494 : if (!ident2)
22716 : : {
22717 : 1417 : start_sequence ();
22718 : 1417 : ok = expand_vec_perm_1 (&dsecond);
22719 : 1417 : seq2 = end_sequence ();
22720 : :
22721 : 1417 : if (!ok)
22722 : : return false;
22723 : : }
22724 : :
22725 : 3905 : if (d->testing_p)
22726 : : return true;
22727 : :
22728 : 20673 : for (i = 0; i < nelt; ++i)
22729 : 18760 : dfinal.perm[i] = (d->perm[i] >= nelt ? i + nelt : i);
22730 : :
22731 : 1913 : emit_insn (seq1);
22732 : 1913 : emit_insn (seq2);
22733 : 1913 : ok = expand_vec_perm_blend (&dfinal);
22734 : 1913 : gcc_assert (ok);
22735 : : return true;
22736 : : }
22737 : :
22738 : : /* A subroutine of ix86_expand_vec_perm_const_1.
22739 : : Implement a permutation with psrlw, psllw and por.
22740 : : It handles case:
22741 : : __builtin_shufflevector (v,v,1,0,3,2,5,4,7,6,9,8,11,10,13,12,15,14);
22742 : : __builtin_shufflevector (v,v,1,0,3,2,5,4,7,6); */
22743 : :
22744 : : static bool
22745 : 28198 : expand_vec_perm_psrlw_psllw_por (struct expand_vec_perm_d *d)
22746 : : {
22747 : 28198 : unsigned i;
22748 : 28198 : rtx (*gen_shr) (rtx, rtx, rtx);
22749 : 28198 : rtx (*gen_shl) (rtx, rtx, rtx);
22750 : 28198 : rtx (*gen_or) (rtx, rtx, rtx);
22751 : 28198 : machine_mode mode = VOIDmode;
22752 : :
22753 : 28198 : if (!TARGET_SSE2 || !d->one_operand_p)
22754 : : return false;
22755 : :
22756 : 5967 : switch (d->vmode)
22757 : : {
22758 : 1403 : case E_V8QImode:
22759 : 1403 : if (!TARGET_MMX_WITH_SSE)
22760 : : return false;
22761 : : mode = V4HImode;
22762 : : gen_shr = gen_lshrv4hi3;
22763 : : gen_shl = gen_ashlv4hi3;
22764 : : gen_or = gen_iorv4hi3;
22765 : : break;
22766 : : case E_V16QImode:
22767 : : mode = V8HImode;
22768 : : gen_shr = gen_lshrv8hi3;
22769 : : gen_shl = gen_ashlv8hi3;
22770 : : gen_or = gen_iorv8hi3;
22771 : : break;
22772 : : default: return false;
22773 : : }
22774 : :
22775 : 3834 : if (!rtx_equal_p (d->op0, d->op1))
22776 : : return false;
22777 : :
22778 : 18810 : for (i = 0; i < d->nelt; i += 2)
22779 : 16620 : if (d->perm[i] != i + 1 || d->perm[i + 1] != i)
22780 : : return false;
22781 : :
22782 : 2190 : if (d->testing_p)
22783 : : return true;
22784 : :
22785 : 26 : rtx tmp1 = gen_reg_rtx (mode);
22786 : 26 : rtx tmp2 = gen_reg_rtx (mode);
22787 : 26 : rtx op0 = force_reg (d->vmode, d->op0);
22788 : :
22789 : 26 : emit_move_insn (tmp1, lowpart_subreg (mode, op0, d->vmode));
22790 : 26 : emit_move_insn (tmp2, lowpart_subreg (mode, op0, d->vmode));
22791 : 26 : emit_insn (gen_shr (tmp1, tmp1, GEN_INT (8)));
22792 : 26 : emit_insn (gen_shl (tmp2, tmp2, GEN_INT (8)));
22793 : 26 : emit_insn (gen_or (tmp1, tmp1, tmp2));
22794 : 26 : emit_move_insn (d->target, lowpart_subreg (d->vmode, tmp1, mode));
22795 : :
22796 : 26 : return true;
22797 : : }
22798 : :
22799 : : /* A subroutine of ix86_expand_vec_perm_const_1. Implement a V4DF
22800 : : permutation using two vperm2f128, followed by a vshufpd insn blending
22801 : : the two vectors together. */
22802 : :
22803 : : static bool
22804 : 32509 : expand_vec_perm_2vperm2f128_vshuf (struct expand_vec_perm_d *d)
22805 : : {
22806 : 32509 : struct expand_vec_perm_d dfirst, dsecond, dthird;
22807 : 32509 : bool ok;
22808 : :
22809 : 32509 : if (!TARGET_AVX || (d->vmode != V4DFmode))
22810 : : return false;
22811 : :
22812 : 2149 : if (d->testing_p)
22813 : : return true;
22814 : :
22815 : 206 : dfirst = *d;
22816 : 206 : dsecond = *d;
22817 : 206 : dthird = *d;
22818 : :
22819 : 206 : dfirst.perm[0] = (d->perm[0] & ~1);
22820 : 206 : dfirst.perm[1] = (d->perm[0] & ~1) + 1;
22821 : 206 : dfirst.perm[2] = (d->perm[2] & ~1);
22822 : 206 : dfirst.perm[3] = (d->perm[2] & ~1) + 1;
22823 : 206 : dsecond.perm[0] = (d->perm[1] & ~1);
22824 : 206 : dsecond.perm[1] = (d->perm[1] & ~1) + 1;
22825 : 206 : dsecond.perm[2] = (d->perm[3] & ~1);
22826 : 206 : dsecond.perm[3] = (d->perm[3] & ~1) + 1;
22827 : 206 : dthird.perm[0] = (d->perm[0] % 2);
22828 : 206 : dthird.perm[1] = (d->perm[1] % 2) + 4;
22829 : 206 : dthird.perm[2] = (d->perm[2] % 2) + 2;
22830 : 206 : dthird.perm[3] = (d->perm[3] % 2) + 6;
22831 : :
22832 : 206 : dfirst.target = gen_reg_rtx (dfirst.vmode);
22833 : 206 : dsecond.target = gen_reg_rtx (dsecond.vmode);
22834 : 206 : dthird.op0 = dfirst.target;
22835 : 206 : dthird.op1 = dsecond.target;
22836 : 206 : dthird.one_operand_p = false;
22837 : :
22838 : 206 : canonicalize_perm (&dfirst);
22839 : 206 : canonicalize_perm (&dsecond);
22840 : :
22841 : 206 : ok = expand_vec_perm_1 (&dfirst)
22842 : 206 : && expand_vec_perm_1 (&dsecond)
22843 : 412 : && expand_vec_perm_1 (&dthird);
22844 : :
22845 : 0 : gcc_assert (ok);
22846 : :
22847 : : return true;
22848 : : }
22849 : :
22850 : : static bool ix86_expand_vec_perm_const_1 (struct expand_vec_perm_d *);
22851 : :
22852 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement
22853 : : a two vector permutation using two intra-lane vector
22854 : : permutations, vperm2f128 swapping the lanes and vblend* insn blending
22855 : : the non-swapped and swapped vectors together. */
22856 : :
22857 : : static bool
22858 : 15913 : expand_vec_perm2_vperm2f128_vblend (struct expand_vec_perm_d *d)
22859 : : {
22860 : 15913 : struct expand_vec_perm_d dfirst, dsecond, dthird;
22861 : 15913 : unsigned i, j, msk, nelt = d->nelt, nelt2 = nelt / 2, which1 = 0, which2 = 0;
22862 : 15913 : rtx_insn *seq1, *seq2;
22863 : 15913 : bool ok;
22864 : 15913 : rtx (*blend) (rtx, rtx, rtx, rtx) = NULL;
22865 : :
22866 : 15913 : if (!TARGET_AVX
22867 : 1133 : || TARGET_AVX2
22868 : 866 : || (d->vmode != V8SFmode && d->vmode != V4DFmode)
22869 : 675 : || d->one_operand_p)
22870 : : return false;
22871 : :
22872 : 675 : dfirst = *d;
22873 : 675 : dsecond = *d;
22874 : 6075 : for (i = 0; i < nelt; i++)
22875 : : {
22876 : 5400 : dfirst.perm[i] = 0xff;
22877 : 5400 : dsecond.perm[i] = 0xff;
22878 : : }
22879 : 6075 : for (i = 0, msk = 0; i < nelt; i++)
22880 : : {
22881 : 5400 : j = (d->perm[i] & nelt2) ? i | nelt2 : i & ~nelt2;
22882 : 5400 : if (j == i)
22883 : : {
22884 : 3778 : dfirst.perm[j] = d->perm[i];
22885 : 6338 : which1 |= (d->perm[i] < nelt ? 1 : 2);
22886 : : }
22887 : : else
22888 : : {
22889 : 1622 : dsecond.perm[j] = d->perm[i];
22890 : 1622 : which2 |= (d->perm[i] < nelt ? 1 : 2);
22891 : 1622 : msk |= (1U << i);
22892 : : }
22893 : : }
22894 : 675 : if (msk == 0 || msk == (1U << nelt) - 1)
22895 : : return false;
22896 : :
22897 : 675 : if (!d->testing_p)
22898 : : {
22899 : 40 : dfirst.target = gen_reg_rtx (dfirst.vmode);
22900 : 40 : dsecond.target = gen_reg_rtx (dsecond.vmode);
22901 : : }
22902 : :
22903 : 6075 : for (i = 0; i < nelt; i++)
22904 : : {
22905 : 5400 : if (dfirst.perm[i] == 0xff)
22906 : 1622 : dfirst.perm[i] = (which1 == 2 ? i + nelt : i);
22907 : 5400 : if (dsecond.perm[i] == 0xff)
22908 : 3778 : dsecond.perm[i] = (which2 == 2 ? i + nelt : i);
22909 : : }
22910 : 675 : canonicalize_perm (&dfirst);
22911 : 675 : start_sequence ();
22912 : 675 : ok = ix86_expand_vec_perm_const_1 (&dfirst);
22913 : 675 : seq1 = end_sequence ();
22914 : :
22915 : 675 : if (!ok)
22916 : : return false;
22917 : :
22918 : 675 : canonicalize_perm (&dsecond);
22919 : 675 : start_sequence ();
22920 : 675 : ok = ix86_expand_vec_perm_const_1 (&dsecond);
22921 : 675 : seq2 = end_sequence ();
22922 : :
22923 : 675 : if (!ok)
22924 : : return false;
22925 : :
22926 : 675 : if (d->testing_p)
22927 : : return true;
22928 : :
22929 : 40 : emit_insn (seq1);
22930 : 40 : emit_insn (seq2);
22931 : :
22932 : 40 : dthird = *d;
22933 : 40 : dthird.op0 = dsecond.target;
22934 : 40 : dthird.op1 = dsecond.target;
22935 : 40 : dthird.one_operand_p = true;
22936 : 40 : dthird.target = gen_reg_rtx (dthird.vmode);
22937 : 360 : for (i = 0; i < nelt; i++)
22938 : 320 : dthird.perm[i] = i ^ nelt2;
22939 : :
22940 : 40 : ok = expand_vec_perm_1 (&dthird);
22941 : 40 : gcc_assert (ok);
22942 : :
22943 : 40 : blend = d->vmode == V8SFmode ? gen_avx_blendps256 : gen_avx_blendpd256;
22944 : 40 : emit_insn (blend (d->target, dfirst.target, dthird.target, GEN_INT (msk)));
22945 : 40 : return true;
22946 : : }
22947 : :
22948 : : /* A subroutine of expand_vec_perm_even_odd_1. Implement the double-word
22949 : : permutation with two pshufb insns and an ior. We should have already
22950 : : failed all two instruction sequences. */
22951 : :
22952 : : static bool
22953 : 30381 : expand_vec_perm_pshufb2 (struct expand_vec_perm_d *d)
22954 : : {
22955 : 30381 : rtx rperm[2][16], vperm, l, h, op, m128;
22956 : 30381 : unsigned int i, nelt, eltsz;
22957 : 30381 : machine_mode mode;
22958 : 30381 : rtx (*gen) (rtx, rtx, rtx);
22959 : :
22960 : 35860 : if (!TARGET_SSSE3 || (GET_MODE_SIZE (d->vmode) != 16
22961 : 10868 : && GET_MODE_SIZE (d->vmode) != 8
22962 : 10828 : && GET_MODE_SIZE (d->vmode) != 4))
22963 : : return false;
22964 : 762 : gcc_assert (!d->one_operand_p);
22965 : :
22966 : 762 : if (d->testing_p)
22967 : : return true;
22968 : :
22969 : 130 : switch (GET_MODE_SIZE (d->vmode))
22970 : : {
22971 : : case 4:
22972 : : mode = V4QImode;
22973 : : gen = gen_mmx_pshufbv4qi3;
22974 : : break;
22975 : 20 : case 8:
22976 : 20 : mode = V8QImode;
22977 : 20 : gen = gen_mmx_pshufbv8qi3;
22978 : 20 : break;
22979 : 45 : case 16:
22980 : 45 : mode = V16QImode;
22981 : 45 : gen = gen_ssse3_pshufbv16qi3;
22982 : 45 : break;
22983 : 0 : default:
22984 : 0 : gcc_unreachable ();
22985 : : }
22986 : :
22987 : 65 : nelt = d->nelt;
22988 : 65 : eltsz = GET_MODE_UNIT_SIZE (d->vmode);
22989 : :
22990 : : /* Generate two permutation masks. If the required element is within
22991 : : the given vector it is shuffled into the proper lane. If the required
22992 : : element is in the other vector, force a zero into the lane by setting
22993 : : bit 7 in the permutation mask. */
22994 : 65 : m128 = GEN_INT (-128);
22995 : 849 : for (i = 0; i < nelt; ++i)
22996 : : {
22997 : 784 : unsigned j, k, e = d->perm[i];
22998 : 784 : unsigned which = (e >= nelt);
22999 : 784 : if (e >= nelt)
23000 : 393 : e -= nelt;
23001 : :
23002 : 1664 : for (j = 0; j < eltsz; ++j)
23003 : : {
23004 : 880 : rperm[which][i*eltsz + j] = GEN_INT (e*eltsz + j);
23005 : 880 : rperm[1-which][i*eltsz + j] = m128;
23006 : : }
23007 : :
23008 : 6936 : for (k = i*eltsz + j; k < 16; ++k)
23009 : 6152 : rperm[0][k] = rperm[1][k] = m128;
23010 : : }
23011 : :
23012 : 65 : vperm = gen_rtx_CONST_VECTOR (V16QImode, gen_rtvec_v (16, rperm[0]));
23013 : 65 : vperm = force_reg (V16QImode, vperm);
23014 : :
23015 : 65 : l = gen_reg_rtx (mode);
23016 : 65 : op = gen_lowpart (mode, d->op0);
23017 : 65 : emit_insn (gen (l, op, vperm));
23018 : :
23019 : 65 : vperm = gen_rtx_CONST_VECTOR (V16QImode, gen_rtvec_v (16, rperm[1]));
23020 : 65 : vperm = force_reg (V16QImode, vperm);
23021 : :
23022 : 65 : h = gen_reg_rtx (mode);
23023 : 65 : op = gen_lowpart (mode, d->op1);
23024 : 65 : emit_insn (gen (h, op, vperm));
23025 : :
23026 : 65 : op = d->target;
23027 : 65 : if (d->vmode != mode)
23028 : 22 : op = gen_reg_rtx (mode);
23029 : 65 : ix86_emit_vec_binop (IOR, mode, op, l, h);
23030 : 65 : if (op != d->target)
23031 : 22 : emit_move_insn (d->target, gen_lowpart (d->vmode, op));
23032 : :
23033 : : return true;
23034 : : }
23035 : :
23036 : : /* Implement arbitrary permutation of one V32QImode and V16QImode operand
23037 : : with two vpshufb insns, vpermq and vpor. We should have already failed
23038 : : all two or three instruction sequences. */
23039 : :
23040 : : static bool
23041 : 24823 : expand_vec_perm_vpshufb2_vpermq (struct expand_vec_perm_d *d)
23042 : : {
23043 : 24823 : rtx rperm[2][32], vperm, l, h, hp, op, m128;
23044 : 24823 : unsigned int i, nelt, eltsz;
23045 : :
23046 : 24823 : if (!TARGET_AVX2
23047 : 367 : || !d->one_operand_p
23048 : 139 : || (d->vmode != V32QImode && d->vmode != V16HImode))
23049 : : return false;
23050 : :
23051 : 6 : if (d->testing_p)
23052 : : return true;
23053 : :
23054 : 6 : nelt = d->nelt;
23055 : 6 : eltsz = GET_MODE_UNIT_SIZE (d->vmode);
23056 : :
23057 : : /* Generate two permutation masks. If the required element is within
23058 : : the same lane, it is shuffled in. If the required element from the
23059 : : other lane, force a zero by setting bit 7 in the permutation mask.
23060 : : In the other mask the mask has non-negative elements if element
23061 : : is requested from the other lane, but also moved to the other lane,
23062 : : so that the result of vpshufb can have the two V2TImode halves
23063 : : swapped. */
23064 : 6 : m128 = GEN_INT (-128);
23065 : 166 : for (i = 0; i < nelt; ++i)
23066 : : {
23067 : 160 : unsigned j, e = d->perm[i] & (nelt / 2 - 1);
23068 : 160 : unsigned which = ((d->perm[i] ^ i) & (nelt / 2)) * eltsz;
23069 : :
23070 : 352 : for (j = 0; j < eltsz; ++j)
23071 : : {
23072 : 192 : rperm[!!which][(i * eltsz + j) ^ which] = GEN_INT (e * eltsz + j);
23073 : 192 : rperm[!which][(i * eltsz + j) ^ (which ^ 16)] = m128;
23074 : : }
23075 : : }
23076 : :
23077 : 6 : vperm = gen_rtx_CONST_VECTOR (V32QImode, gen_rtvec_v (32, rperm[1]));
23078 : 6 : vperm = force_reg (V32QImode, vperm);
23079 : :
23080 : 6 : h = gen_reg_rtx (V32QImode);
23081 : 6 : op = gen_lowpart (V32QImode, d->op0);
23082 : 6 : emit_insn (gen_avx2_pshufbv32qi3 (h, op, vperm));
23083 : :
23084 : : /* Swap the 128-byte lanes of h into hp. */
23085 : 6 : hp = gen_reg_rtx (V4DImode);
23086 : 6 : op = gen_lowpart (V4DImode, h);
23087 : 6 : emit_insn (gen_avx2_permv4di_1 (hp, op, const2_rtx, GEN_INT (3), const0_rtx,
23088 : : const1_rtx));
23089 : :
23090 : 6 : vperm = gen_rtx_CONST_VECTOR (V32QImode, gen_rtvec_v (32, rperm[0]));
23091 : 6 : vperm = force_reg (V32QImode, vperm);
23092 : :
23093 : 6 : l = gen_reg_rtx (V32QImode);
23094 : 6 : op = gen_lowpart (V32QImode, d->op0);
23095 : 6 : emit_insn (gen_avx2_pshufbv32qi3 (l, op, vperm));
23096 : :
23097 : 6 : op = d->target;
23098 : 6 : if (d->vmode != V32QImode)
23099 : 2 : op = gen_reg_rtx (V32QImode);
23100 : 6 : emit_insn (gen_iorv32qi3 (op, l, gen_lowpart (V32QImode, hp)));
23101 : 6 : if (op != d->target)
23102 : 2 : emit_move_insn (d->target, gen_lowpart (d->vmode, op));
23103 : :
23104 : : return true;
23105 : : }
23106 : :
23107 : : /* A subroutine of expand_vec_perm_even_odd_1. Implement extract-even
23108 : : and extract-odd permutations of two V32QImode and V16QImode operand
23109 : : with two vpshufb insns, vpor and vpermq. We should have already
23110 : : failed all two or three instruction sequences. */
23111 : :
23112 : : static bool
23113 : 24817 : expand_vec_perm_vpshufb2_vpermq_even_odd (struct expand_vec_perm_d *d)
23114 : : {
23115 : 24817 : rtx rperm[2][32], vperm, l, h, ior, op, m128;
23116 : 24817 : unsigned int i, nelt, eltsz;
23117 : :
23118 : 24817 : if (!TARGET_AVX2
23119 : 361 : || d->one_operand_p
23120 : 228 : || (d->vmode != V32QImode && d->vmode != V16HImode))
23121 : : return false;
23122 : :
23123 : 112 : for (i = 0; i < d->nelt; ++i)
23124 : 112 : if ((d->perm[i] ^ (i * 2)) & (3 * d->nelt / 2))
23125 : : return false;
23126 : :
23127 : 0 : if (d->testing_p)
23128 : : return true;
23129 : :
23130 : 0 : nelt = d->nelt;
23131 : 0 : eltsz = GET_MODE_UNIT_SIZE (d->vmode);
23132 : :
23133 : : /* Generate two permutation masks. In the first permutation mask
23134 : : the first quarter will contain indexes for the first half
23135 : : of the op0, the second quarter will contain bit 7 set, third quarter
23136 : : will contain indexes for the second half of the op0 and the
23137 : : last quarter bit 7 set. In the second permutation mask
23138 : : the first quarter will contain bit 7 set, the second quarter
23139 : : indexes for the first half of the op1, the third quarter bit 7 set
23140 : : and last quarter indexes for the second half of the op1.
23141 : : I.e. the first mask e.g. for V32QImode extract even will be:
23142 : : 0, 2, ..., 0xe, -128, ..., -128, 0, 2, ..., 0xe, -128, ..., -128
23143 : : (all values masked with 0xf except for -128) and second mask
23144 : : for extract even will be
23145 : : -128, ..., -128, 0, 2, ..., 0xe, -128, ..., -128, 0, 2, ..., 0xe. */
23146 : 0 : m128 = GEN_INT (-128);
23147 : 0 : for (i = 0; i < nelt; ++i)
23148 : : {
23149 : 0 : unsigned j, e = d->perm[i] & (nelt / 2 - 1);
23150 : 0 : unsigned which = d->perm[i] >= nelt;
23151 : 0 : unsigned xorv = (i >= nelt / 4 && i < 3 * nelt / 4) ? 24 : 0;
23152 : :
23153 : 0 : for (j = 0; j < eltsz; ++j)
23154 : : {
23155 : 0 : rperm[which][(i * eltsz + j) ^ xorv] = GEN_INT (e * eltsz + j);
23156 : 0 : rperm[1 - which][(i * eltsz + j) ^ xorv] = m128;
23157 : : }
23158 : : }
23159 : :
23160 : 0 : vperm = gen_rtx_CONST_VECTOR (V32QImode, gen_rtvec_v (32, rperm[0]));
23161 : 0 : vperm = force_reg (V32QImode, vperm);
23162 : :
23163 : 0 : l = gen_reg_rtx (V32QImode);
23164 : 0 : op = gen_lowpart (V32QImode, d->op0);
23165 : 0 : emit_insn (gen_avx2_pshufbv32qi3 (l, op, vperm));
23166 : :
23167 : 0 : vperm = gen_rtx_CONST_VECTOR (V32QImode, gen_rtvec_v (32, rperm[1]));
23168 : 0 : vperm = force_reg (V32QImode, vperm);
23169 : :
23170 : 0 : h = gen_reg_rtx (V32QImode);
23171 : 0 : op = gen_lowpart (V32QImode, d->op1);
23172 : 0 : emit_insn (gen_avx2_pshufbv32qi3 (h, op, vperm));
23173 : :
23174 : 0 : ior = gen_reg_rtx (V32QImode);
23175 : 0 : emit_insn (gen_iorv32qi3 (ior, l, h));
23176 : :
23177 : : /* Permute the V4DImode quarters using { 0, 2, 1, 3 } permutation. */
23178 : 0 : op = gen_reg_rtx (V4DImode);
23179 : 0 : ior = gen_lowpart (V4DImode, ior);
23180 : 0 : emit_insn (gen_avx2_permv4di_1 (op, ior, const0_rtx, const2_rtx,
23181 : : const1_rtx, GEN_INT (3)));
23182 : 0 : emit_move_insn (d->target, gen_lowpart (d->vmode, op));
23183 : :
23184 : 0 : return true;
23185 : : }
23186 : :
23187 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement a
23188 : : permutation (which is a bland) with and, andnot and or when pshufb is not available.
23189 : :
23190 : : It handles case:
23191 : : __builtin_shufflevector (v1, v2, 0, 9, 2, 11, 4, 13, 6, 15);
23192 : : __builtin_shufflevector (v1, v2, 8, 1, 2, 11, 4, 13, 6, 15);
23193 : :
23194 : : An element[i] must be chosen between op0[i] and op1[i] to satisfy the
23195 : : requirement.
23196 : : */
23197 : :
23198 : : static bool
23199 : 26008 : expand_vec_perm_pand_pandn_por (struct expand_vec_perm_d *d)
23200 : : {
23201 : 26008 : rtx rperm[16], vperm;
23202 : 26008 : unsigned int i, nelt = d->nelt;
23203 : :
23204 : 26008 : if (!TARGET_SSE2
23205 : 26008 : || d->one_operand_p
23206 : 22231 : || (d->vmode != V16QImode && d->vmode != V8HImode))
23207 : : return false;
23208 : :
23209 : 8160 : if (d->perm[0] != 0)
23210 : : return false;
23211 : :
23212 : : /* The dest[i] must select an element between op0[i] and op1[i]. */
23213 : 18131 : for (i = 1; i < nelt; i++)
23214 : 16950 : if ((d->perm[i] % nelt) != i)
23215 : : return false;
23216 : :
23217 : 1181 : if (d->testing_p)
23218 : : return true;
23219 : :
23220 : : /* Generates a blend mask for the operators AND and ANDNOT. */
23221 : 108 : machine_mode inner_mode = GET_MODE_INNER (d->vmode);
23222 : 1148 : for (i = 0; i < nelt; i++)
23223 : 1581 : rperm[i] = (d->perm[i] < nelt) ? CONSTM1_RTX (inner_mode)
23224 : 541 : : CONST0_RTX (inner_mode);
23225 : :
23226 : 108 : vperm = gen_rtx_CONST_VECTOR (d->vmode, gen_rtvec_v (nelt, rperm));
23227 : 108 : vperm = force_reg (d->vmode, vperm);
23228 : :
23229 : 108 : ix86_expand_sse_movcc (d->target, vperm, d->op0, d->op1);
23230 : :
23231 : 108 : return true;
23232 : : }
23233 : :
23234 : : /* Implement permutation with pslldq + psrldq + por when pshufb is not
23235 : : available. */
23236 : : static bool
23237 : 45811 : expand_vec_perm_pslldq_psrldq_por (struct expand_vec_perm_d *d, bool pandn)
23238 : : {
23239 : 45811 : unsigned i, nelt = d->nelt;
23240 : 45811 : unsigned start1, end1 = -1;
23241 : 45811 : machine_mode vmode = d->vmode, imode;
23242 : 45811 : int start2 = -1;
23243 : 45811 : bool clear_op0, clear_op1;
23244 : 45811 : unsigned inner_size;
23245 : 45811 : rtx op0, op1, dop1;
23246 : 45811 : rtx (*gen_vec_shr) (rtx, rtx, rtx);
23247 : 45811 : rtx (*gen_vec_shl) (rtx, rtx, rtx);
23248 : :
23249 : : /* pshufd can be used for V4SI/V2DI under TARGET_SSE2. */
23250 : 45811 : if (!TARGET_SSE2 || (vmode != E_V16QImode && vmode != E_V8HImode))
23251 : : return false;
23252 : :
23253 : 15044 : start1 = d->perm[0];
23254 : 38586 : for (i = 1; i < nelt; i++)
23255 : : {
23256 : 37949 : if (d->perm[i] != d->perm[i-1] + 1
23257 : 8652 : || d->perm[i] == nelt)
23258 : : {
23259 : 29451 : if (start2 == -1)
23260 : : {
23261 : 15044 : start2 = d->perm[i];
23262 : 15044 : end1 = d->perm[i-1];
23263 : : }
23264 : : else
23265 : : return false;
23266 : : }
23267 : : }
23268 : :
23269 : 637 : clear_op0 = end1 != nelt - 1;
23270 : 637 : clear_op1 = start2 % nelt != 0;
23271 : : /* pandn/pand is needed to clear upper/lower bits of op0/op1. */
23272 : 637 : if (!pandn && (clear_op0 || clear_op1))
23273 : : return false;
23274 : :
23275 : 412 : if (d->testing_p)
23276 : : return true;
23277 : :
23278 : 44 : gen_vec_shr = vmode == E_V16QImode ? gen_vec_shr_v16qi : gen_vec_shr_v8hi;
23279 : 20 : gen_vec_shl = vmode == E_V16QImode ? gen_vec_shl_v16qi : gen_vec_shl_v8hi;
23280 : 44 : imode = GET_MODE_INNER (vmode);
23281 : 44 : inner_size = GET_MODE_BITSIZE (imode);
23282 : 44 : op0 = gen_reg_rtx (vmode);
23283 : 44 : op1 = gen_reg_rtx (vmode);
23284 : :
23285 : 44 : if (start1)
23286 : 41 : emit_insn (gen_vec_shr (op0, d->op0, GEN_INT (start1 * inner_size)));
23287 : : else
23288 : 3 : emit_move_insn (op0, d->op0);
23289 : :
23290 : 44 : dop1 = d->op1;
23291 : 44 : if (d->one_operand_p)
23292 : 24 : dop1 = d->op0;
23293 : :
23294 : 44 : int shl_offset = end1 - start1 + 1 - start2 % nelt;
23295 : 44 : if (shl_offset)
23296 : 44 : emit_insn (gen_vec_shl (op1, dop1, GEN_INT (shl_offset * inner_size)));
23297 : : else
23298 : 0 : emit_move_insn (op1, dop1);
23299 : :
23300 : : /* Clear lower/upper bits for op0/op1. */
23301 : 44 : if (clear_op0 || clear_op1)
23302 : : {
23303 : : rtx vec[16];
23304 : : rtx const_vec;
23305 : : rtx clear;
23306 : 339 : for (i = 0; i != nelt; i++)
23307 : : {
23308 : 312 : if (i < (end1 - start1 + 1))
23309 : 156 : vec[i] = gen_int_mode ((HOST_WIDE_INT_1U << inner_size) - 1, imode);
23310 : : else
23311 : 156 : vec[i] = CONST0_RTX (imode);
23312 : : }
23313 : 27 : const_vec = gen_rtx_CONST_VECTOR (vmode, gen_rtvec_v (nelt, vec));
23314 : 27 : const_vec = validize_mem (force_const_mem (vmode, const_vec));
23315 : 27 : clear = force_reg (vmode, const_vec);
23316 : :
23317 : 27 : if (clear_op0)
23318 : 19 : emit_move_insn (op0, gen_rtx_AND (vmode, op0, clear));
23319 : 27 : if (clear_op1)
23320 : 16 : emit_move_insn (op1, gen_rtx_AND (vmode,
23321 : : gen_rtx_NOT (vmode, clear),
23322 : : op1));
23323 : : }
23324 : :
23325 : 44 : emit_move_insn (d->target, gen_rtx_IOR (vmode, op0, op1));
23326 : 44 : return true;
23327 : : }
23328 : :
23329 : : /* A subroutine of expand_vec_perm_even_odd_1. Implement extract-even
23330 : : and extract-odd permutations of two V8QI, V8HI, V16QI, V16HI or V32QI
23331 : : operands with two "and" and "pack" or two "shift" and "pack" insns.
23332 : : We should have already failed all two instruction sequences. */
23333 : :
23334 : : static bool
23335 : 48952 : expand_vec_perm_even_odd_pack (struct expand_vec_perm_d *d)
23336 : : {
23337 : 48952 : rtx op, dop0, dop1, t;
23338 : 48952 : unsigned i, odd, c, s, nelt = d->nelt;
23339 : 48952 : int pblendw_i = 0;
23340 : 48952 : bool end_perm = false;
23341 : 48952 : machine_mode half_mode;
23342 : 48952 : rtx (*gen_and) (rtx, rtx, rtx);
23343 : 48952 : rtx (*gen_pack) (rtx, rtx, rtx);
23344 : 48952 : rtx (*gen_shift) (rtx, rtx, rtx);
23345 : :
23346 : 48952 : if (d->one_operand_p)
23347 : : return false;
23348 : :
23349 : 42950 : switch (d->vmode)
23350 : : {
23351 : 4358 : case E_V4HImode:
23352 : : /* Required for "pack". */
23353 : 4358 : if (!TARGET_SSE4_1)
23354 : : return false;
23355 : : c = 0xffff;
23356 : : s = 16;
23357 : : half_mode = V2SImode;
23358 : : gen_and = gen_andv2si3;
23359 : : gen_pack = gen_mmx_packusdw;
23360 : : gen_shift = gen_lshrv2si3;
23361 : : pblendw_i = 0x5;
23362 : : break;
23363 : 6187 : case E_V8HImode:
23364 : : /* Required for "pack". */
23365 : 6187 : if (!TARGET_SSE4_1)
23366 : : return false;
23367 : : c = 0xffff;
23368 : : s = 16;
23369 : : half_mode = V4SImode;
23370 : : gen_and = gen_andv4si3;
23371 : : gen_pack = gen_sse4_1_packusdw;
23372 : : gen_shift = gen_lshrv4si3;
23373 : : pblendw_i = 0x55;
23374 : : break;
23375 : : case E_V8QImode:
23376 : : /* No check as all instructions are SSE2. */
23377 : : c = 0xff;
23378 : : s = 8;
23379 : : half_mode = V4HImode;
23380 : : gen_and = gen_andv4hi3;
23381 : : gen_pack = gen_mmx_packuswb;
23382 : : gen_shift = gen_lshrv4hi3;
23383 : : break;
23384 : 14751 : case E_V16QImode:
23385 : : /* No check as all instructions are SSE2. */
23386 : 14751 : c = 0xff;
23387 : 14751 : s = 8;
23388 : 14751 : half_mode = V8HImode;
23389 : 14751 : gen_and = gen_andv8hi3;
23390 : 14751 : gen_pack = gen_sse2_packuswb;
23391 : 14751 : gen_shift = gen_lshrv8hi3;
23392 : 14751 : break;
23393 : 430 : case E_V16HImode:
23394 : 430 : if (!TARGET_AVX2)
23395 : : return false;
23396 : : c = 0xffff;
23397 : : s = 16;
23398 : : half_mode = V8SImode;
23399 : : gen_and = gen_andv8si3;
23400 : : gen_pack = gen_avx2_packusdw;
23401 : : gen_shift = gen_lshrv8si3;
23402 : : pblendw_i = 0x5555;
23403 : : end_perm = true;
23404 : : break;
23405 : 522 : case E_V32QImode:
23406 : 522 : if (!TARGET_AVX2)
23407 : : return false;
23408 : : c = 0xff;
23409 : : s = 8;
23410 : : half_mode = V16HImode;
23411 : : gen_and = gen_andv16hi3;
23412 : : gen_pack = gen_avx2_packuswb;
23413 : : gen_shift = gen_lshrv16hi3;
23414 : : end_perm = true;
23415 : : break;
23416 : : default:
23417 : : /* Only V4HI, V8QI, V8HI, V16QI, V16HI and V32QI modes
23418 : : are more profitable than general shuffles. */
23419 : : return false;
23420 : : }
23421 : :
23422 : : /* Check that permutation is even or odd. */
23423 : 20647 : odd = d->perm[0];
23424 : 20647 : if (odd > 1)
23425 : : return false;
23426 : :
23427 : 237450 : for (i = 1; i < nelt; ++i)
23428 : 221073 : if (d->perm[i] != 2 * i + odd)
23429 : : return false;
23430 : :
23431 : 16377 : if (d->testing_p)
23432 : : return true;
23433 : :
23434 : 5375 : dop0 = gen_reg_rtx (half_mode);
23435 : 5375 : dop1 = gen_reg_rtx (half_mode);
23436 : 5375 : if (odd == 0)
23437 : : {
23438 : : /* Use pblendw since const_vector 0 should be cheaper than
23439 : : const_vector 0xffff. */
23440 : 4668 : if (d->vmode == V4HImode
23441 : : || d->vmode == E_V8HImode
23442 : : || d->vmode == E_V16HImode)
23443 : : {
23444 : 831 : rtx dop0_t = gen_reg_rtx (d->vmode);
23445 : 831 : rtx dop1_t = gen_reg_rtx (d->vmode);
23446 : 831 : t = gen_reg_rtx (d->vmode);
23447 : 831 : emit_move_insn (t, CONST0_RTX (d->vmode));
23448 : :
23449 : 831 : emit_move_insn (dop0_t, gen_rtx_VEC_MERGE (d->vmode, d->op0, t,
23450 : : GEN_INT (pblendw_i)));
23451 : 831 : emit_move_insn (dop1_t, gen_rtx_VEC_MERGE (d->vmode, d->op1, t,
23452 : : GEN_INT (pblendw_i)));
23453 : :
23454 : 831 : emit_move_insn (dop0, gen_lowpart (half_mode, dop0_t));
23455 : 831 : emit_move_insn (dop1, gen_lowpart (half_mode, dop1_t));
23456 : 831 : }
23457 : : else
23458 : : {
23459 : 3837 : t = gen_const_vec_duplicate (half_mode, GEN_INT (c));
23460 : 3837 : t = force_reg (half_mode, t);
23461 : 3837 : emit_insn (gen_and (dop0, t, gen_lowpart (half_mode, d->op0)));
23462 : 3837 : emit_insn (gen_and (dop1, t, gen_lowpart (half_mode, d->op1)));
23463 : : }
23464 : : }
23465 : : else
23466 : : {
23467 : 1414 : emit_insn (gen_shift (dop0,
23468 : 707 : gen_lowpart (half_mode, d->op0),
23469 : : GEN_INT (s)));
23470 : 1414 : emit_insn (gen_shift (dop1,
23471 : 707 : gen_lowpart (half_mode, d->op1),
23472 : : GEN_INT (s)));
23473 : : }
23474 : : /* In AVX2 for 256 bit case we need to permute pack result. */
23475 : 5375 : if (TARGET_AVX2 && end_perm)
23476 : : {
23477 : 399 : op = gen_reg_rtx (d->vmode);
23478 : 399 : t = gen_reg_rtx (V4DImode);
23479 : 399 : emit_insn (gen_pack (op, dop0, dop1));
23480 : 798 : emit_insn (gen_avx2_permv4di_1 (t,
23481 : 399 : gen_lowpart (V4DImode, op),
23482 : : const0_rtx,
23483 : : const2_rtx,
23484 : : const1_rtx,
23485 : : GEN_INT (3)));
23486 : 399 : emit_move_insn (d->target, gen_lowpart (d->vmode, t));
23487 : : }
23488 : : else
23489 : 4976 : emit_insn (gen_pack (d->target, dop0, dop1));
23490 : :
23491 : : return true;
23492 : : }
23493 : :
23494 : : /* A subroutine of expand_vec_perm_even_odd_1. Implement extract-even
23495 : : and extract-odd permutations of two V64QI operands
23496 : : with two "shifts", two "truncs" and one "concat" insns for "odd"
23497 : : and two "truncs" and one concat insn for "even."
23498 : : Have already failed all two instruction sequences. */
23499 : :
23500 : : static bool
23501 : 24863 : expand_vec_perm_even_odd_trunc (struct expand_vec_perm_d *d)
23502 : : {
23503 : 24863 : rtx t1, t2, t3, t4;
23504 : 24863 : unsigned i, odd, nelt = d->nelt;
23505 : :
23506 : 24863 : if (!TARGET_AVX512BW
23507 : 66 : || d->one_operand_p
23508 : 62 : || d->vmode != V64QImode)
23509 : : return false;
23510 : :
23511 : : /* Check that permutation is even or odd. */
23512 : 62 : odd = d->perm[0];
23513 : 62 : if (odd > 1)
23514 : : return false;
23515 : :
23516 : 1910 : for (i = 1; i < nelt; ++i)
23517 : 1884 : if (d->perm[i] != 2 * i + odd)
23518 : : return false;
23519 : :
23520 : 26 : if (d->testing_p)
23521 : : return true;
23522 : :
23523 : :
23524 : 26 : if (odd)
23525 : : {
23526 : 1 : t1 = gen_reg_rtx (V32HImode);
23527 : 1 : t2 = gen_reg_rtx (V32HImode);
23528 : 2 : emit_insn (gen_lshrv32hi3 (t1,
23529 : 1 : gen_lowpart (V32HImode, d->op0),
23530 : : GEN_INT (8)));
23531 : 2 : emit_insn (gen_lshrv32hi3 (t2,
23532 : 1 : gen_lowpart (V32HImode, d->op1),
23533 : : GEN_INT (8)));
23534 : : }
23535 : : else
23536 : : {
23537 : 25 : t1 = gen_lowpart (V32HImode, d->op0);
23538 : 25 : t2 = gen_lowpart (V32HImode, d->op1);
23539 : : }
23540 : :
23541 : 26 : t3 = gen_reg_rtx (V32QImode);
23542 : 26 : t4 = gen_reg_rtx (V32QImode);
23543 : 26 : emit_insn (gen_avx512bw_truncatev32hiv32qi2 (t3, t1));
23544 : 26 : emit_insn (gen_avx512bw_truncatev32hiv32qi2 (t4, t2));
23545 : 26 : emit_insn (gen_avx_vec_concatv64qi (d->target, t3, t4));
23546 : :
23547 : 26 : return true;
23548 : : }
23549 : :
23550 : : /* A subroutine of ix86_expand_vec_perm_const_1. Implement extract-even
23551 : : and extract-odd permutations. */
23552 : :
23553 : : static bool
23554 : 13557 : expand_vec_perm_even_odd_1 (struct expand_vec_perm_d *d, unsigned odd)
23555 : : {
23556 : 13557 : rtx t1, t2, t3, t4, t5;
23557 : :
23558 : 13557 : switch (d->vmode)
23559 : : {
23560 : 56 : case E_V4DFmode:
23561 : 56 : if (d->testing_p)
23562 : : break;
23563 : 1 : t1 = gen_reg_rtx (V4DFmode);
23564 : 1 : t2 = gen_reg_rtx (V4DFmode);
23565 : :
23566 : : /* Shuffle the lanes around into { 0 1 4 5 } and { 2 3 6 7 }. */
23567 : 1 : emit_insn (gen_avx_vperm2f128v4df3 (t1, d->op0, d->op1, GEN_INT (0x20)));
23568 : 1 : emit_insn (gen_avx_vperm2f128v4df3 (t2, d->op0, d->op1, GEN_INT (0x31)));
23569 : :
23570 : : /* Now an unpck[lh]pd will produce the result required. */
23571 : 1 : if (odd)
23572 : 0 : t3 = gen_avx_unpckhpd256 (d->target, t1, t2);
23573 : : else
23574 : 1 : t3 = gen_avx_unpcklpd256 (d->target, t1, t2);
23575 : 1 : emit_insn (t3);
23576 : 1 : break;
23577 : :
23578 : 2190 : case E_V8SFmode:
23579 : 2190 : {
23580 : 2190 : int mask = odd ? 0xdd : 0x88;
23581 : :
23582 : 2190 : if (d->testing_p)
23583 : : break;
23584 : 186 : t1 = gen_reg_rtx (V8SFmode);
23585 : 186 : t2 = gen_reg_rtx (V8SFmode);
23586 : 186 : t3 = gen_reg_rtx (V8SFmode);
23587 : :
23588 : : /* Shuffle within the 128-bit lanes to produce:
23589 : : { 0 2 8 a 4 6 c e } | { 1 3 9 b 5 7 d f }. */
23590 : 186 : emit_insn (gen_avx_shufps256 (t1, d->op0, d->op1,
23591 : : GEN_INT (mask)));
23592 : :
23593 : : /* Shuffle the lanes around to produce:
23594 : : { 4 6 c e 0 2 8 a } and { 5 7 d f 1 3 9 b }. */
23595 : 186 : emit_insn (gen_avx_vperm2f128v8sf3 (t2, t1, t1,
23596 : : GEN_INT (0x3)));
23597 : :
23598 : : /* Shuffle within the 128-bit lanes to produce:
23599 : : { 0 2 4 6 4 6 0 2 } | { 1 3 5 7 5 7 1 3 }. */
23600 : 186 : emit_insn (gen_avx_shufps256 (t3, t1, t2, GEN_INT (0x44)));
23601 : :
23602 : : /* Shuffle within the 128-bit lanes to produce:
23603 : : { 8 a c e c e 8 a } | { 9 b d f d f 9 b }. */
23604 : 186 : emit_insn (gen_avx_shufps256 (t2, t1, t2, GEN_INT (0xee)));
23605 : :
23606 : : /* Shuffle the lanes around to produce:
23607 : : { 0 2 4 6 8 a c e } | { 1 3 5 7 9 b d f }. */
23608 : 186 : emit_insn (gen_avx_vperm2f128v8sf3 (d->target, t3, t2,
23609 : : GEN_INT (0x20)));
23610 : : }
23611 : 186 : break;
23612 : :
23613 : 0 : case E_V2DFmode:
23614 : 0 : case E_V4SFmode:
23615 : 0 : case E_V2DImode:
23616 : 0 : case E_V2SImode:
23617 : 0 : case E_V4SImode:
23618 : 0 : case E_V2HImode:
23619 : : /* These are always directly implementable by expand_vec_perm_1. */
23620 : 0 : gcc_unreachable ();
23621 : :
23622 : 0 : case E_V2SFmode:
23623 : 0 : gcc_assert (TARGET_MMX_WITH_SSE);
23624 : : /* We have no suitable instructions. */
23625 : 0 : if (d->testing_p)
23626 : : return false;
23627 : : break;
23628 : :
23629 : 1155 : case E_V4QImode:
23630 : 1155 : if (TARGET_SSSE3 && !TARGET_SLOW_PSHUFB)
23631 : 0 : return expand_vec_perm_pshufb2 (d);
23632 : : else
23633 : : {
23634 : 1155 : if (d->testing_p)
23635 : : break;
23636 : : /* We need 2*log2(N)-1 operations to achieve odd/even
23637 : : with interleave. */
23638 : 163 : t1 = gen_reg_rtx (V4QImode);
23639 : 163 : emit_insn (gen_mmx_punpckhbw_low (t1, d->op0, d->op1));
23640 : 163 : emit_insn (gen_mmx_punpcklbw_low (d->target, d->op0, d->op1));
23641 : 163 : if (odd)
23642 : 38 : t2 = gen_mmx_punpckhbw_low (d->target, d->target, t1);
23643 : : else
23644 : 125 : t2 = gen_mmx_punpcklbw_low (d->target, d->target, t1);
23645 : 163 : emit_insn (t2);
23646 : : }
23647 : 163 : break;
23648 : :
23649 : 1317 : case E_V4HImode:
23650 : 1317 : if (TARGET_SSE4_1)
23651 : 86 : return expand_vec_perm_even_odd_pack (d);
23652 : 1231 : else if (TARGET_SSSE3 && !TARGET_SLOW_PSHUFB)
23653 : 20 : return expand_vec_perm_pshufb2 (d);
23654 : : else
23655 : : {
23656 : 1211 : if (d->testing_p)
23657 : : break;
23658 : : /* We need 2*log2(N)-1 operations to achieve odd/even
23659 : : with interleave. */
23660 : 375 : t1 = gen_reg_rtx (V4HImode);
23661 : 375 : emit_insn (gen_mmx_punpckhwd (t1, d->op0, d->op1));
23662 : 375 : emit_insn (gen_mmx_punpcklwd (d->target, d->op0, d->op1));
23663 : 375 : if (odd)
23664 : 8 : t2 = gen_mmx_punpckhwd (d->target, d->target, t1);
23665 : : else
23666 : 367 : t2 = gen_mmx_punpcklwd (d->target, d->target, t1);
23667 : 375 : emit_insn (t2);
23668 : : }
23669 : 375 : break;
23670 : :
23671 : 6775 : case E_V8HImode:
23672 : 6775 : if (TARGET_SSE4_1)
23673 : 427 : return expand_vec_perm_even_odd_pack (d);
23674 : 6348 : else if (TARGET_SSSE3 && !TARGET_SLOW_PSHUFB)
23675 : 1 : return expand_vec_perm_pshufb2 (d);
23676 : : else
23677 : : {
23678 : 6347 : if (d->testing_p)
23679 : : break;
23680 : : /* We need 2*log2(N)-1 operations to achieve odd/even
23681 : : with interleave. */
23682 : 2580 : t1 = gen_reg_rtx (V8HImode);
23683 : 2580 : t2 = gen_reg_rtx (V8HImode);
23684 : 2580 : emit_insn (gen_vec_interleave_highv8hi (t1, d->op0, d->op1));
23685 : 2580 : emit_insn (gen_vec_interleave_lowv8hi (d->target, d->op0, d->op1));
23686 : 2580 : emit_insn (gen_vec_interleave_highv8hi (t2, d->target, t1));
23687 : 2580 : emit_insn (gen_vec_interleave_lowv8hi (d->target, d->target, t1));
23688 : 2580 : if (odd)
23689 : 86 : t3 = gen_vec_interleave_highv8hi (d->target, d->target, t2);
23690 : : else
23691 : 2494 : t3 = gen_vec_interleave_lowv8hi (d->target, d->target, t2);
23692 : 2580 : emit_insn (t3);
23693 : : }
23694 : 2580 : break;
23695 : :
23696 : 1271 : case E_V8QImode:
23697 : 1271 : case E_V16QImode:
23698 : 1271 : return expand_vec_perm_even_odd_pack (d);
23699 : :
23700 : 458 : case E_V16HImode:
23701 : 458 : case E_V32QImode:
23702 : 458 : return expand_vec_perm_even_odd_pack (d);
23703 : :
23704 : 36 : case E_V64QImode:
23705 : 36 : return expand_vec_perm_even_odd_trunc (d);
23706 : :
23707 : 56 : case E_V4DImode:
23708 : 56 : if (!TARGET_AVX2)
23709 : : {
23710 : 56 : struct expand_vec_perm_d d_copy = *d;
23711 : 56 : d_copy.vmode = V4DFmode;
23712 : 56 : if (d->testing_p)
23713 : 55 : d_copy.target = gen_raw_REG (V4DFmode, LAST_VIRTUAL_REGISTER + 1);
23714 : : else
23715 : 1 : d_copy.target = gen_reg_rtx (V4DFmode);
23716 : 56 : d_copy.op0 = gen_lowpart (V4DFmode, d->op0);
23717 : 56 : d_copy.op1 = gen_lowpart (V4DFmode, d->op1);
23718 : 56 : if (expand_vec_perm_even_odd_1 (&d_copy, odd))
23719 : : {
23720 : 56 : if (!d->testing_p)
23721 : 1 : emit_move_insn (d->target,
23722 : 1 : gen_lowpart (V4DImode, d_copy.target));
23723 : 56 : return true;
23724 : : }
23725 : : return false;
23726 : : }
23727 : :
23728 : 0 : if (d->testing_p)
23729 : : break;
23730 : :
23731 : 0 : t1 = gen_reg_rtx (V4DImode);
23732 : 0 : t2 = gen_reg_rtx (V4DImode);
23733 : :
23734 : : /* Shuffle the lanes around into { 0 1 4 5 } and { 2 3 6 7 }. */
23735 : 0 : emit_insn (gen_avx2_permv2ti (t1, d->op0, d->op1, GEN_INT (0x20)));
23736 : 0 : emit_insn (gen_avx2_permv2ti (t2, d->op0, d->op1, GEN_INT (0x31)));
23737 : :
23738 : : /* Now an vpunpck[lh]qdq will produce the result required. */
23739 : 0 : if (odd)
23740 : 0 : t3 = gen_avx2_interleave_highv4di (d->target, t1, t2);
23741 : : else
23742 : 0 : t3 = gen_avx2_interleave_lowv4di (d->target, t1, t2);
23743 : 0 : emit_insn (t3);
23744 : 0 : break;
23745 : :
23746 : 243 : case E_V8SImode:
23747 : 243 : if (!TARGET_AVX2)
23748 : : {
23749 : 126 : struct expand_vec_perm_d d_copy = *d;
23750 : 126 : d_copy.vmode = V8SFmode;
23751 : 126 : if (d->testing_p)
23752 : 126 : d_copy.target = gen_raw_REG (V8SFmode, LAST_VIRTUAL_REGISTER + 1);
23753 : : else
23754 : 0 : d_copy.target = gen_reg_rtx (V8SFmode);
23755 : 126 : d_copy.op0 = gen_lowpart (V8SFmode, d->op0);
23756 : 126 : d_copy.op1 = gen_lowpart (V8SFmode, d->op1);
23757 : 126 : if (expand_vec_perm_even_odd_1 (&d_copy, odd))
23758 : : {
23759 : 126 : if (!d->testing_p)
23760 : 0 : emit_move_insn (d->target,
23761 : 0 : gen_lowpart (V8SImode, d_copy.target));
23762 : 126 : return true;
23763 : : }
23764 : : return false;
23765 : : }
23766 : :
23767 : 117 : if (d->testing_p)
23768 : : break;
23769 : :
23770 : 117 : t1 = gen_reg_rtx (V8SImode);
23771 : 117 : t2 = gen_reg_rtx (V8SImode);
23772 : 117 : t3 = gen_reg_rtx (V4DImode);
23773 : 117 : t4 = gen_reg_rtx (V4DImode);
23774 : 117 : t5 = gen_reg_rtx (V4DImode);
23775 : :
23776 : : /* Shuffle the lanes around into
23777 : : { 0 1 2 3 8 9 a b } and { 4 5 6 7 c d e f }. */
23778 : 234 : emit_insn (gen_avx2_permv2ti (t3, gen_lowpart (V4DImode, d->op0),
23779 : 117 : gen_lowpart (V4DImode, d->op1),
23780 : : GEN_INT (0x20)));
23781 : 234 : emit_insn (gen_avx2_permv2ti (t4, gen_lowpart (V4DImode, d->op0),
23782 : 117 : gen_lowpart (V4DImode, d->op1),
23783 : : GEN_INT (0x31)));
23784 : :
23785 : : /* Swap the 2nd and 3rd position in each lane into
23786 : : { 0 2 1 3 8 a 9 b } and { 4 6 5 7 c e d f }. */
23787 : 117 : emit_insn (gen_avx2_pshufdv3 (t1, gen_lowpart (V8SImode, t3),
23788 : : GEN_INT (2 * 4 + 1 * 16 + 3 * 64)));
23789 : 117 : emit_insn (gen_avx2_pshufdv3 (t2, gen_lowpart (V8SImode, t4),
23790 : : GEN_INT (2 * 4 + 1 * 16 + 3 * 64)));
23791 : :
23792 : : /* Now an vpunpck[lh]qdq will produce
23793 : : { 0 2 4 6 8 a c e } resp. { 1 3 5 7 9 b d f }. */
23794 : 117 : if (odd)
23795 : 0 : t3 = gen_avx2_interleave_highv4di (t5, gen_lowpart (V4DImode, t1),
23796 : 0 : gen_lowpart (V4DImode, t2));
23797 : : else
23798 : 117 : t3 = gen_avx2_interleave_lowv4di (t5, gen_lowpart (V4DImode, t1),
23799 : 117 : gen_lowpart (V4DImode, t2));
23800 : 117 : emit_insn (t3);
23801 : 117 : emit_move_insn (d->target, gen_lowpart (V8SImode, t5));
23802 : 117 : break;
23803 : :
23804 : 0 : default:
23805 : 0 : gcc_unreachable ();
23806 : : }
23807 : :
23808 : : return true;
23809 : : }
23810 : :
23811 : : /* A subroutine of ix86_expand_vec_perm_const_1. Pattern match
23812 : : extract-even and extract-odd permutations. */
23813 : :
23814 : : static bool
23815 : 24777 : expand_vec_perm_even_odd (struct expand_vec_perm_d *d)
23816 : : {
23817 : 24777 : unsigned i, odd, nelt = d->nelt;
23818 : :
23819 : 24777 : odd = d->perm[0];
23820 : 24777 : if (odd != 0 && odd != 1)
23821 : : return false;
23822 : :
23823 : 73748 : for (i = 1; i < nelt; ++i)
23824 : 65071 : if (d->perm[i] != 2 * i + odd)
23825 : : return false;
23826 : :
23827 : 8677 : if (d->vmode == E_V32HImode
23828 : 12 : && d->testing_p
23829 : 12 : && !TARGET_AVX512BW)
23830 : : return false;
23831 : :
23832 : 8665 : return expand_vec_perm_even_odd_1 (d, odd);
23833 : : }
23834 : :
23835 : : /* A subroutine of ix86_expand_vec_perm_const_1. Implement broadcast
23836 : : permutations. We assume that expand_vec_perm_1 has already failed. */
23837 : :
23838 : : static bool
23839 : 1031 : expand_vec_perm_broadcast_1 (struct expand_vec_perm_d *d)
23840 : : {
23841 : 1031 : unsigned elt = d->perm[0], nelt2 = d->nelt / 2;
23842 : 1031 : machine_mode vmode = d->vmode;
23843 : 1031 : rtx (*gen) (rtx, rtx, rtx);
23844 : 1031 : unsigned char perm2[4];
23845 : 1031 : rtx op0 = d->op0, dest;
23846 : 1031 : bool ok;
23847 : :
23848 : 1031 : switch (vmode)
23849 : : {
23850 : 0 : case E_V4DFmode:
23851 : 0 : case E_V8SFmode:
23852 : : /* These are special-cased in sse.md so that we can optionally
23853 : : use the vbroadcast instruction. They expand to two insns
23854 : : if the input happens to be in a register. */
23855 : 0 : gcc_unreachable ();
23856 : :
23857 : 0 : case E_V2DFmode:
23858 : 0 : case E_V2SFmode:
23859 : 0 : case E_V4SFmode:
23860 : 0 : case E_V2DImode:
23861 : 0 : case E_V2SImode:
23862 : 0 : case E_V4SImode:
23863 : 0 : case E_V2HImode:
23864 : 0 : case E_V4HImode:
23865 : : /* These are always implementable using standard shuffle patterns. */
23866 : 0 : gcc_unreachable ();
23867 : :
23868 : 16 : case E_V4QImode:
23869 : : /* This can be implemented via interleave and pshuflw. */
23870 : 16 : if (d->testing_p)
23871 : : return true;
23872 : :
23873 : 8 : if (elt >= nelt2)
23874 : : {
23875 : 4 : gen = gen_mmx_punpckhbw_low;
23876 : 4 : elt -= nelt2;
23877 : : }
23878 : : else
23879 : : gen = gen_mmx_punpcklbw_low;
23880 : :
23881 : 8 : dest = gen_reg_rtx (vmode);
23882 : 8 : emit_insn (gen (dest, op0, op0));
23883 : 8 : vmode = get_mode_wider_vector (vmode);
23884 : 8 : op0 = gen_lowpart (vmode, dest);
23885 : :
23886 : 8 : memset (perm2, elt, 2);
23887 : 8 : dest = gen_reg_rtx (vmode);
23888 : 8 : ok = expand_vselect (dest, op0, perm2, 2, d->testing_p);
23889 : 8 : gcc_assert (ok);
23890 : :
23891 : 8 : emit_move_insn (d->target, gen_lowpart (d->vmode, dest));
23892 : 8 : return true;
23893 : :
23894 : 4 : case E_V8QImode:
23895 : : /* This can be implemented via interleave. We save one insn by
23896 : : stopping once we have promoted to V2SImode and then use pshufd. */
23897 : 4 : if (d->testing_p)
23898 : : return true;
23899 : 4 : do
23900 : : {
23901 : 4 : if (elt >= nelt2)
23902 : : {
23903 : 1 : gen = vmode == V8QImode ? gen_mmx_punpckhbw
23904 : : : gen_mmx_punpckhwd;
23905 : 1 : elt -= nelt2;
23906 : : }
23907 : : else
23908 : 3 : gen = vmode == V8QImode ? gen_mmx_punpcklbw
23909 : : : gen_mmx_punpcklwd;
23910 : 4 : nelt2 /= 2;
23911 : :
23912 : 4 : dest = gen_reg_rtx (vmode);
23913 : 4 : emit_insn (gen (dest, op0, op0));
23914 : 4 : vmode = get_mode_wider_vector (vmode);
23915 : 4 : op0 = gen_lowpart (vmode, dest);
23916 : : }
23917 : 4 : while (vmode != V2SImode);
23918 : :
23919 : 2 : memset (perm2, elt, 2);
23920 : 2 : dest = gen_reg_rtx (vmode);
23921 : 2 : ok = expand_vselect (dest, op0, perm2, 2, d->testing_p);
23922 : 2 : gcc_assert (ok);
23923 : :
23924 : 2 : emit_move_insn (d->target, gen_lowpart (d->vmode, dest));
23925 : 2 : return true;
23926 : :
23927 : 981 : case E_V8HImode:
23928 : 981 : case E_V16QImode:
23929 : : /* These can be implemented via interleave. We save one insn by
23930 : : stopping once we have promoted to V4SImode and then use pshufd. */
23931 : 981 : if (d->testing_p)
23932 : : return true;
23933 : 1537 : do
23934 : : {
23935 : 1537 : if (elt >= nelt2)
23936 : : {
23937 : 16 : gen = vmode == V16QImode ? gen_vec_interleave_highv16qi
23938 : : : gen_vec_interleave_highv8hi;
23939 : 16 : elt -= nelt2;
23940 : : }
23941 : : else
23942 : 1521 : gen = vmode == V16QImode ? gen_vec_interleave_lowv16qi
23943 : : : gen_vec_interleave_lowv8hi;
23944 : 1537 : nelt2 /= 2;
23945 : :
23946 : 1537 : dest = gen_reg_rtx (vmode);
23947 : 1537 : emit_insn (gen (dest, op0, op0));
23948 : 1537 : vmode = get_mode_wider_vector (vmode);
23949 : 1537 : op0 = gen_lowpart (vmode, dest);
23950 : : }
23951 : 1537 : while (vmode != V4SImode);
23952 : :
23953 : 917 : memset (perm2, elt, 4);
23954 : 917 : dest = gen_reg_rtx (vmode);
23955 : 917 : ok = expand_vselect (dest, op0, perm2, 4, d->testing_p);
23956 : 917 : gcc_assert (ok);
23957 : :
23958 : 917 : emit_move_insn (d->target, gen_lowpart (d->vmode, dest));
23959 : 917 : return true;
23960 : :
23961 : 1 : case E_V8HFmode:
23962 : 1 : case E_V8BFmode:
23963 : : /* This can be implemented via interleave and pshufd. */
23964 : 1 : if (d->testing_p)
23965 : : return true;
23966 : :
23967 : 1 : rtx (*gen_interleave) (machine_mode, rtx, rtx, rtx);
23968 : 1 : if (elt >= nelt2)
23969 : : {
23970 : 0 : gen_interleave = gen_vec_interleave_high;
23971 : 0 : elt -= nelt2;
23972 : : }
23973 : : else
23974 : : gen_interleave = gen_vec_interleave_low;
23975 : 1 : nelt2 /= 2;
23976 : :
23977 : 1 : dest = gen_reg_rtx (vmode);
23978 : 1 : emit_insn (gen_interleave (vmode, dest, op0, op0));
23979 : :
23980 : 1 : vmode = V4SImode;
23981 : 1 : op0 = gen_lowpart (vmode, dest);
23982 : :
23983 : 1 : memset (perm2, elt, 4);
23984 : 1 : dest = gen_reg_rtx (vmode);
23985 : 1 : ok = expand_vselect (dest, op0, perm2, 4, d->testing_p);
23986 : 1 : gcc_assert (ok);
23987 : :
23988 : 1 : emit_move_insn (d->target, gen_lowpart (d->vmode, dest));
23989 : 1 : return true;
23990 : :
23991 : 21 : case E_V32QImode:
23992 : 21 : case E_V16HImode:
23993 : 21 : case E_V8SImode:
23994 : 21 : case E_V4DImode:
23995 : : /* For AVX2 broadcasts of the first element vpbroadcast* or
23996 : : vpermq should be used by expand_vec_perm_1. */
23997 : 21 : gcc_assert (!TARGET_AVX2 || d->perm[0]);
23998 : : return false;
23999 : :
24000 : 6 : case E_V64QImode:
24001 : 6 : gcc_assert (!TARGET_AVX512BW || d->perm[0]);
24002 : : return false;
24003 : :
24004 : 2 : case E_V32HImode:
24005 : 2 : gcc_assert (!TARGET_AVX512BW);
24006 : : return false;
24007 : :
24008 : 0 : default:
24009 : 0 : gcc_unreachable ();
24010 : : }
24011 : : }
24012 : :
24013 : : /* A subroutine of ix86_expand_vec_perm_const_1. Pattern match
24014 : : broadcast permutations. */
24015 : :
24016 : : static bool
24017 : 103747 : expand_vec_perm_broadcast (struct expand_vec_perm_d *d)
24018 : : {
24019 : 103747 : unsigned i, elt, nelt = d->nelt;
24020 : :
24021 : 103747 : if (!d->one_operand_p)
24022 : : return false;
24023 : :
24024 : 6102 : elt = d->perm[0];
24025 : 8945 : for (i = 1; i < nelt; ++i)
24026 : 8816 : if (d->perm[i] != elt)
24027 : : return false;
24028 : :
24029 : 129 : return expand_vec_perm_broadcast_1 (d);
24030 : : }
24031 : :
24032 : : /* Implement arbitrary permutations of two V64QImode operands
24033 : : with 2 vperm[it]2w, 2 vpshufb and one vpor instruction. */
24034 : : static bool
24035 : 24817 : expand_vec_perm_vpermt2_vpshub2 (struct expand_vec_perm_d *d)
24036 : : {
24037 : 24817 : if (!TARGET_AVX512BW || !(d->vmode == V64QImode))
24038 : : return false;
24039 : :
24040 : 40 : if (d->testing_p)
24041 : : return true;
24042 : :
24043 : 40 : struct expand_vec_perm_d ds[2];
24044 : 40 : rtx rperm[128], vperm, target0, target1;
24045 : 40 : unsigned int i, nelt;
24046 : 40 : machine_mode vmode;
24047 : :
24048 : 40 : nelt = d->nelt;
24049 : 40 : vmode = V64QImode;
24050 : :
24051 : 120 : for (i = 0; i < 2; i++)
24052 : : {
24053 : 80 : ds[i] = *d;
24054 : 80 : ds[i].vmode = V32HImode;
24055 : 80 : ds[i].nelt = 32;
24056 : 80 : ds[i].target = gen_reg_rtx (V32HImode);
24057 : 80 : ds[i].op0 = gen_lowpart (V32HImode, d->op0);
24058 : 80 : ds[i].op1 = gen_lowpart (V32HImode, d->op1);
24059 : : }
24060 : :
24061 : : /* Prepare permutations such that the first one takes care of
24062 : : putting the even bytes into the right positions or one higher
24063 : : positions (ds[0]) and the second one takes care of
24064 : : putting the odd bytes into the right positions or one below
24065 : : (ds[1]). */
24066 : :
24067 : 2600 : for (i = 0; i < nelt; i++)
24068 : : {
24069 : 2560 : ds[i & 1].perm[i / 2] = d->perm[i] / 2;
24070 : 2560 : if (i & 1)
24071 : : {
24072 : 1280 : rperm[i] = constm1_rtx;
24073 : 1280 : rperm[i + 64] = GEN_INT ((i & 14) + (d->perm[i] & 1));
24074 : : }
24075 : : else
24076 : : {
24077 : 1280 : rperm[i] = GEN_INT ((i & 14) + (d->perm[i] & 1));
24078 : 1280 : rperm[i + 64] = constm1_rtx;
24079 : : }
24080 : : }
24081 : :
24082 : 40 : bool ok = expand_vec_perm_1 (&ds[0]);
24083 : 40 : gcc_assert (ok);
24084 : 40 : ds[0].target = gen_lowpart (V64QImode, ds[0].target);
24085 : :
24086 : 40 : ok = expand_vec_perm_1 (&ds[1]);
24087 : 40 : gcc_assert (ok);
24088 : 40 : ds[1].target = gen_lowpart (V64QImode, ds[1].target);
24089 : :
24090 : 40 : vperm = gen_rtx_CONST_VECTOR (V64QImode, gen_rtvec_v (64, rperm));
24091 : 40 : vperm = force_reg (vmode, vperm);
24092 : 40 : target0 = gen_reg_rtx (V64QImode);
24093 : 40 : emit_insn (gen_avx512bw_pshufbv64qi3 (target0, ds[0].target, vperm));
24094 : :
24095 : 40 : vperm = gen_rtx_CONST_VECTOR (V64QImode, gen_rtvec_v (64, rperm + 64));
24096 : 40 : vperm = force_reg (vmode, vperm);
24097 : 40 : target1 = gen_reg_rtx (V64QImode);
24098 : 40 : emit_insn (gen_avx512bw_pshufbv64qi3 (target1, ds[1].target, vperm));
24099 : :
24100 : 40 : emit_insn (gen_iorv64qi3 (d->target, target0, target1));
24101 : 40 : return true;
24102 : : }
24103 : :
24104 : : /* Implement arbitrary permutation of two V32QImode and V16QImode operands
24105 : : with 4 vpshufb insns, 2 vpermq and 3 vpor. We should have already failed
24106 : : all the shorter instruction sequences. */
24107 : :
24108 : : static bool
24109 : 15967 : expand_vec_perm_vpshufb4_vpermq2 (struct expand_vec_perm_d *d)
24110 : : {
24111 : 15967 : rtx rperm[4][32], vperm, l[2], h[2], op, m128;
24112 : 15967 : unsigned int i, nelt, eltsz;
24113 : 15967 : bool used[4];
24114 : :
24115 : 15967 : if (!TARGET_AVX2
24116 : 321 : || d->one_operand_p
24117 : 192 : || (d->vmode != V32QImode && d->vmode != V16HImode))
24118 : : return false;
24119 : :
24120 : 54 : if (d->testing_p)
24121 : : return true;
24122 : :
24123 : 54 : nelt = d->nelt;
24124 : 54 : eltsz = GET_MODE_UNIT_SIZE (d->vmode);
24125 : :
24126 : : /* Generate 4 permutation masks. If the required element is within
24127 : : the same lane, it is shuffled in. If the required element from the
24128 : : other lane, force a zero by setting bit 7 in the permutation mask.
24129 : : In the other mask the mask has non-negative elements if element
24130 : : is requested from the other lane, but also moved to the other lane,
24131 : : so that the result of vpshufb can have the two V2TImode halves
24132 : : swapped. */
24133 : 54 : m128 = GEN_INT (-128);
24134 : 1836 : for (i = 0; i < 32; ++i)
24135 : : {
24136 : 1728 : rperm[0][i] = m128;
24137 : 1728 : rperm[1][i] = m128;
24138 : 1728 : rperm[2][i] = m128;
24139 : 1728 : rperm[3][i] = m128;
24140 : : }
24141 : 54 : used[0] = false;
24142 : 54 : used[1] = false;
24143 : 54 : used[2] = false;
24144 : 54 : used[3] = false;
24145 : 1590 : for (i = 0; i < nelt; ++i)
24146 : : {
24147 : 1536 : unsigned j, e = d->perm[i] & (nelt / 2 - 1);
24148 : 1536 : unsigned xlane = ((d->perm[i] ^ i) & (nelt / 2)) * eltsz;
24149 : 2074 : unsigned int which = ((d->perm[i] & nelt) ? 2 : 0) + (xlane ? 1 : 0);
24150 : :
24151 : 3264 : for (j = 0; j < eltsz; ++j)
24152 : 1728 : rperm[which][(i * eltsz + j) ^ xlane] = GEN_INT (e * eltsz + j);
24153 : 1536 : used[which] = true;
24154 : : }
24155 : :
24156 : 162 : for (i = 0; i < 2; ++i)
24157 : : {
24158 : 108 : if (!used[2 * i + 1])
24159 : : {
24160 : 22 : h[i] = NULL_RTX;
24161 : 22 : continue;
24162 : : }
24163 : 86 : vperm = gen_rtx_CONST_VECTOR (V32QImode,
24164 : 86 : gen_rtvec_v (32, rperm[2 * i + 1]));
24165 : 86 : vperm = force_reg (V32QImode, vperm);
24166 : 86 : h[i] = gen_reg_rtx (V32QImode);
24167 : 86 : op = gen_lowpart (V32QImode, i ? d->op1 : d->op0);
24168 : 86 : emit_insn (gen_avx2_pshufbv32qi3 (h[i], op, vperm));
24169 : : }
24170 : :
24171 : : /* Swap the 128-byte lanes of h[X]. */
24172 : 162 : for (i = 0; i < 2; ++i)
24173 : : {
24174 : 108 : if (h[i] == NULL_RTX)
24175 : 22 : continue;
24176 : 86 : op = gen_reg_rtx (V4DImode);
24177 : 86 : emit_insn (gen_avx2_permv4di_1 (op, gen_lowpart (V4DImode, h[i]),
24178 : : const2_rtx, GEN_INT (3), const0_rtx,
24179 : : const1_rtx));
24180 : 86 : h[i] = gen_lowpart (V32QImode, op);
24181 : : }
24182 : :
24183 : 162 : for (i = 0; i < 2; ++i)
24184 : : {
24185 : 108 : if (!used[2 * i])
24186 : : {
24187 : 0 : l[i] = NULL_RTX;
24188 : 0 : continue;
24189 : : }
24190 : 108 : vperm = gen_rtx_CONST_VECTOR (V32QImode, gen_rtvec_v (32, rperm[2 * i]));
24191 : 108 : vperm = force_reg (V32QImode, vperm);
24192 : 108 : l[i] = gen_reg_rtx (V32QImode);
24193 : 108 : op = gen_lowpart (V32QImode, i ? d->op1 : d->op0);
24194 : 108 : emit_insn (gen_avx2_pshufbv32qi3 (l[i], op, vperm));
24195 : : }
24196 : :
24197 : 162 : for (i = 0; i < 2; ++i)
24198 : : {
24199 : 108 : if (h[i] && l[i])
24200 : : {
24201 : 86 : op = gen_reg_rtx (V32QImode);
24202 : 86 : emit_insn (gen_iorv32qi3 (op, l[i], h[i]));
24203 : 86 : l[i] = op;
24204 : : }
24205 : 22 : else if (h[i])
24206 : 0 : l[i] = h[i];
24207 : : }
24208 : :
24209 : 54 : gcc_assert (l[0] && l[1]);
24210 : 54 : op = d->target;
24211 : 54 : if (d->vmode != V32QImode)
24212 : 12 : op = gen_reg_rtx (V32QImode);
24213 : 54 : emit_insn (gen_iorv32qi3 (op, l[0], l[1]));
24214 : 54 : if (op != d->target)
24215 : 12 : emit_move_insn (d->target, gen_lowpart (d->vmode, op));
24216 : : return true;
24217 : : }
24218 : :
24219 : : /* The guts of ix86_vectorize_vec_perm_const. With all of the interface bits
24220 : : taken care of, perform the expansion in D and return true on success. */
24221 : :
24222 : : static bool
24223 : 317072 : ix86_expand_vec_perm_const_1 (struct expand_vec_perm_d *d)
24224 : : {
24225 : : /* Try a single instruction expansion. */
24226 : 317072 : if (expand_vec_perm_1 (d))
24227 : : return true;
24228 : :
24229 : : /* Try sequences of two instructions. */
24230 : :
24231 : 116593 : if (expand_vec_perm_pshuflw_pshufhw (d))
24232 : : return true;
24233 : :
24234 : 113624 : if (expand_vec_perm_palignr (d, false))
24235 : : return true;
24236 : :
24237 : 110493 : if (expand_vec_perm_interleave2 (d))
24238 : : return true;
24239 : :
24240 : 103747 : if (expand_vec_perm_broadcast (d))
24241 : : return true;
24242 : :
24243 : 103647 : if (expand_vec_perm_vpermq_perm_1 (d))
24244 : : return true;
24245 : :
24246 : 103647 : if (expand_vec_perm_vperm2f128 (d))
24247 : : return true;
24248 : :
24249 : 103598 : if (expand_vec_perm_pblendv (d))
24250 : : return true;
24251 : :
24252 : 101813 : if (expand_vec_perm_2perm_interleave (d, true))
24253 : : return true;
24254 : :
24255 : 101453 : if (expand_vec_perm_2perm_pblendv (d, true))
24256 : : return true;
24257 : :
24258 : 98376 : if (expand_vec_perm_shufps_shufps (d))
24259 : : return true;
24260 : :
24261 : 52496 : if (expand_vec_perm_punpckldq_pshuf (d))
24262 : : return true;
24263 : :
24264 : : /* Try sequences of three instructions. */
24265 : :
24266 : 46710 : if (expand_vec_perm_even_odd_pack (d))
24267 : : return true;
24268 : :
24269 : 32509 : if (expand_vec_perm_2vperm2f128_vshuf (d))
24270 : : return true;
24271 : :
24272 : 30360 : if (expand_vec_perm_pshufb2 (d))
24273 : : return true;
24274 : :
24275 : 29619 : if (expand_vec_perm_pslldq_psrldq_por (d, false))
24276 : : return true;
24277 : :
24278 : 29432 : if (expand_vec_perm_interleave3 (d))
24279 : : return true;
24280 : :
24281 : 29266 : if (expand_vec_perm_vperm2f128_vblend (d))
24282 : : return true;
24283 : :
24284 : 29266 : if (expand_vec_perm_2perm_interleave (d, false))
24285 : : return true;
24286 : :
24287 : 29026 : if (expand_vec_perm_2perm_pblendv (d, false))
24288 : : return true;
24289 : :
24290 : 28198 : if (expand_vec_perm_psrlw_psllw_por (d))
24291 : : return true;
24292 : :
24293 : 26008 : if (expand_vec_perm_pand_pandn_por (d))
24294 : : return true;
24295 : :
24296 : : /* Try sequences of four instructions. */
24297 : :
24298 : 24827 : if (expand_vec_perm_even_odd_trunc (d))
24299 : : return true;
24300 : 24823 : if (expand_vec_perm_vpshufb2_vpermq (d))
24301 : : return true;
24302 : :
24303 : 24817 : if (expand_vec_perm_vpshufb2_vpermq_even_odd (d))
24304 : : return true;
24305 : :
24306 : 24817 : if (expand_vec_perm_vpermt2_vpshub2 (d))
24307 : : return true;
24308 : :
24309 : : /* ??? Look for narrow permutations whose element orderings would
24310 : : allow the promotion to a wider mode. */
24311 : :
24312 : : /* ??? Look for sequences of interleave or a wider permute that place
24313 : : the data into the correct lanes for a half-vector shuffle like
24314 : : pshuf[lh]w or vpermilps. */
24315 : :
24316 : : /* ??? Look for sequences of interleave that produce the desired results.
24317 : : The combinatorics of punpck[lh] get pretty ugly... */
24318 : :
24319 : 24777 : if (expand_vec_perm_even_odd (d))
24320 : : return true;
24321 : :
24322 : : /* Generate four or five instructions. */
24323 : 16192 : if (expand_vec_perm_pslldq_psrldq_por (d, true))
24324 : : return true;
24325 : :
24326 : : /* Even longer sequences. */
24327 : 15967 : if (expand_vec_perm_vpshufb4_vpermq2 (d))
24328 : : return true;
24329 : :
24330 : : /* See if we can get the same permutation in different vector integer
24331 : : mode. */
24332 : 15913 : struct expand_vec_perm_d nd;
24333 : 15913 : if (canonicalize_vector_int_perm (d, &nd) && expand_vec_perm_1 (&nd))
24334 : : {
24335 : 0 : if (!d->testing_p)
24336 : 0 : emit_move_insn (d->target, gen_lowpart (d->vmode, nd.target));
24337 : 0 : return true;
24338 : : }
24339 : :
24340 : : /* Even longer, including recursion to ix86_expand_vec_perm_const_1. */
24341 : 15913 : if (expand_vec_perm2_vperm2f128_vblend (d))
24342 : : return true;
24343 : :
24344 : : return false;
24345 : : }
24346 : :
24347 : : /* If a permutation only uses one operand, make it clear. Returns true
24348 : : if the permutation references both operands. */
24349 : :
24350 : : static bool
24351 : 67912 : canonicalize_perm (struct expand_vec_perm_d *d)
24352 : : {
24353 : 67912 : int i, which, nelt = d->nelt;
24354 : :
24355 : 422522 : for (i = which = 0; i < nelt; ++i)
24356 : 483234 : which |= (d->perm[i] < nelt ? 1 : 2);
24357 : :
24358 : 67912 : d->one_operand_p = true;
24359 : 67912 : switch (which)
24360 : : {
24361 : 0 : default:
24362 : 0 : gcc_unreachable();
24363 : :
24364 : 51817 : case 3:
24365 : 51817 : if (!rtx_equal_p (d->op0, d->op1))
24366 : : {
24367 : 51766 : d->one_operand_p = false;
24368 : 51766 : break;
24369 : : }
24370 : : /* The elements of PERM do not suggest that only the first operand
24371 : : is used, but both operands are identical. Allow easier matching
24372 : : of the permutation by folding the permutation into the single
24373 : : input vector. */
24374 : : /* FALLTHRU */
24375 : :
24376 : : case 2:
24377 : 2913 : for (i = 0; i < nelt; ++i)
24378 : 2576 : d->perm[i] &= nelt - 1;
24379 : 337 : d->op0 = d->op1;
24380 : 337 : break;
24381 : :
24382 : 15809 : case 1:
24383 : 15809 : d->op1 = d->op0;
24384 : 15809 : break;
24385 : : }
24386 : :
24387 : 67912 : return (which == 3);
24388 : : }
24389 : :
24390 : : /* Implement TARGET_VECTORIZE_VEC_PERM_CONST. */
24391 : :
24392 : : bool
24393 : 829818 : ix86_vectorize_vec_perm_const (machine_mode vmode, machine_mode op_mode,
24394 : : rtx target, rtx op0, rtx op1,
24395 : : const vec_perm_indices &sel)
24396 : : {
24397 : 829818 : if (vmode != op_mode)
24398 : : return false;
24399 : :
24400 : 828159 : struct expand_vec_perm_d d;
24401 : 828159 : unsigned char perm[MAX_VECT_LEN];
24402 : 828159 : unsigned int i, nelt, which;
24403 : 828159 : bool two_args;
24404 : :
24405 : : /* For HF and BF mode vector, convert it to HI using subreg. */
24406 : 2484007 : if (GET_MODE_INNER (vmode) == HFmode || GET_MODE_INNER (vmode) == BFmode)
24407 : : {
24408 : 495 : machine_mode orig_mode = vmode;
24409 : 990 : vmode = mode_for_vector (HImode,
24410 : 495 : GET_MODE_NUNITS (vmode)).require ();
24411 : 495 : if (target)
24412 : 431 : target = lowpart_subreg (vmode, target, orig_mode);
24413 : 495 : if (op0)
24414 : 431 : op0 = lowpart_subreg (vmode, op0, orig_mode);
24415 : 495 : if (op1)
24416 : 431 : op1 = lowpart_subreg (vmode, op1, orig_mode);
24417 : : }
24418 : :
24419 : 828159 : d.target = target;
24420 : 828159 : d.op0 = op0;
24421 : 828159 : d.op1 = op1;
24422 : :
24423 : 828159 : d.vmode = vmode;
24424 : 828159 : gcc_assert (VECTOR_MODE_P (d.vmode));
24425 : 828159 : d.nelt = nelt = GET_MODE_NUNITS (d.vmode);
24426 : 828159 : d.testing_p = !target;
24427 : :
24428 : 828159 : gcc_assert (sel.length () == nelt);
24429 : 828159 : gcc_checking_assert (sizeof (d.perm) == sizeof (perm));
24430 : :
24431 : : /* Given sufficient ISA support we can just return true here
24432 : : for selected vector modes. */
24433 : 828159 : switch (d.vmode)
24434 : : {
24435 : 1986 : case E_V16SFmode:
24436 : 1986 : case E_V16SImode:
24437 : 1986 : case E_V8DImode:
24438 : 1986 : case E_V8DFmode:
24439 : 1986 : if (!TARGET_AVX512F)
24440 : : return false;
24441 : : /* All implementable with a single vperm[it]2 insn. */
24442 : 1986 : if (d.testing_p)
24443 : : return true;
24444 : : break;
24445 : 323 : case E_V32HImode:
24446 : 323 : if (!TARGET_AVX512F)
24447 : : return false;
24448 : 323 : if (d.testing_p && TARGET_AVX512BW)
24449 : : /* All implementable with a single vperm[it]2 insn. */
24450 : : return true;
24451 : : break;
24452 : 569 : case E_V64QImode:
24453 : 569 : if (!TARGET_AVX512F)
24454 : : return false;
24455 : 569 : if (d.testing_p && TARGET_AVX512BW)
24456 : : /* Implementable with 2 vperm[it]2, 2 vpshufb and 1 or insn. */
24457 : : return true;
24458 : : break;
24459 : 10511 : case E_V8SImode:
24460 : 10511 : case E_V8SFmode:
24461 : 10511 : case E_V4DFmode:
24462 : 10511 : case E_V4DImode:
24463 : 10511 : if (!TARGET_AVX)
24464 : : return false;
24465 : 10511 : if (d.testing_p && TARGET_AVX512VL)
24466 : : /* All implementable with a single vperm[it]2 insn. */
24467 : : return true;
24468 : : break;
24469 : 601 : case E_V16HImode:
24470 : 601 : if (!TARGET_SSE2)
24471 : : return false;
24472 : 601 : if (d.testing_p && TARGET_AVX2)
24473 : : /* Implementable with 4 vpshufb insns, 2 vpermq and 3 vpor insns. */
24474 : : return true;
24475 : : break;
24476 : 694 : case E_V32QImode:
24477 : 694 : if (!TARGET_SSE2)
24478 : : return false;
24479 : 694 : if (d.testing_p && TARGET_AVX2)
24480 : : /* Implementable with 4 vpshufb insns, 2 vpermq and 3 vpor insns. */
24481 : : return true;
24482 : : break;
24483 : 40580 : case E_V8HImode:
24484 : 40580 : case E_V16QImode:
24485 : 40580 : if (!TARGET_SSE2)
24486 : : return false;
24487 : : /* Fall through. */
24488 : 260689 : case E_V4SImode:
24489 : 260689 : case E_V4SFmode:
24490 : 260689 : if (!TARGET_SSE)
24491 : : return false;
24492 : : /* All implementable with a single vpperm insn. */
24493 : 260689 : if (d.testing_p && TARGET_XOP)
24494 : : return true;
24495 : : /* All implementable with 2 pshufb + 1 ior. */
24496 : 260583 : if (d.testing_p && TARGET_SSSE3)
24497 : : return true;
24498 : : break;
24499 : 135330 : case E_V2SFmode:
24500 : 135330 : case E_V2SImode:
24501 : 135330 : case E_V4HImode:
24502 : 135330 : case E_V8QImode:
24503 : 135330 : if (!TARGET_MMX_WITH_SSE)
24504 : : return false;
24505 : : break;
24506 : 27228 : case E_V2HImode:
24507 : 27228 : if (!TARGET_SSE2)
24508 : : return false;
24509 : : /* All implementable with *punpckwd. */
24510 : 27228 : if (d.testing_p)
24511 : : return true;
24512 : : break;
24513 : 10038 : case E_V4QImode:
24514 : 10038 : if (!TARGET_SSE2)
24515 : : return false;
24516 : : break;
24517 : 376075 : case E_V2DImode:
24518 : 376075 : case E_V2DFmode:
24519 : 376075 : if (!TARGET_SSE)
24520 : : return false;
24521 : : /* All implementable with shufpd or unpck[lh]pd. */
24522 : 376075 : if (d.testing_p)
24523 : : return true;
24524 : : break;
24525 : : default:
24526 : : return false;
24527 : : }
24528 : :
24529 : 2332557 : for (i = which = 0; i < nelt; ++i)
24530 : : {
24531 : 1913284 : unsigned char e = sel[i];
24532 : 1913284 : gcc_assert (e < 2 * nelt);
24533 : 1913284 : d.perm[i] = e;
24534 : 1913284 : perm[i] = e;
24535 : 2601501 : which |= (e < nelt ? 1 : 2);
24536 : : }
24537 : :
24538 : 419273 : if (d.testing_p)
24539 : : {
24540 : : /* For all elements from second vector, fold the elements to first. */
24541 : 353156 : if (which == 2)
24542 : 1345 : for (i = 0; i < nelt; ++i)
24543 : 1240 : d.perm[i] -= nelt;
24544 : :
24545 : : /* Check whether the mask can be applied to the vector type. */
24546 : 353156 : d.one_operand_p = (which != 3);
24547 : :
24548 : : /* Implementable with shufps, pshufd or pshuflw. */
24549 : 353156 : if (d.one_operand_p
24550 : : && (d.vmode == V4SFmode || d.vmode == V2SFmode
24551 : : || d.vmode == V4SImode || d.vmode == V2SImode
24552 : : || d.vmode == V4HImode || d.vmode == V2HImode))
24553 : : return true;
24554 : :
24555 : : /* Otherwise we have to go through the motions and see if we can
24556 : : figure out how to generate the requested permutation. */
24557 : 246396 : d.target = gen_raw_REG (d.vmode, LAST_VIRTUAL_REGISTER + 1);
24558 : 246396 : d.op1 = d.op0 = gen_raw_REG (d.vmode, LAST_VIRTUAL_REGISTER + 2);
24559 : 246396 : if (!d.one_operand_p)
24560 : 234847 : d.op1 = gen_raw_REG (d.vmode, LAST_VIRTUAL_REGISTER + 3);
24561 : :
24562 : 246396 : start_sequence ();
24563 : 246396 : bool ret = ix86_expand_vec_perm_const_1 (&d);
24564 : 246396 : end_sequence ();
24565 : :
24566 : 246396 : return ret;
24567 : : }
24568 : :
24569 : 66117 : two_args = canonicalize_perm (&d);
24570 : :
24571 : : /* If one of the operands is a zero vector, try to match pmovzx. */
24572 : 66117 : if (two_args && (d.op0 == CONST0_RTX (vmode) || d.op1 == CONST0_RTX (vmode)))
24573 : : {
24574 : 565 : struct expand_vec_perm_d dzero = d;
24575 : 565 : if (d.op0 == CONST0_RTX (vmode))
24576 : : {
24577 : 387 : d.op1 = dzero.op1 = force_reg (vmode, d.op1);
24578 : 387 : std::swap (dzero.op0, dzero.op1);
24579 : 7527 : for (i = 0; i < nelt; ++i)
24580 : 7140 : dzero.perm[i] ^= nelt;
24581 : : }
24582 : : else
24583 : 178 : d.op0 = dzero.op0 = force_reg (vmode, d.op0);
24584 : :
24585 : 565 : if (expand_vselect_vconcat (dzero.target, dzero.op0, dzero.op1,
24586 : 565 : dzero.perm, nelt, dzero.testing_p))
24587 : 116 : return true;
24588 : : }
24589 : :
24590 : : /* Force operands into registers. */
24591 : 66001 : rtx nop0 = force_reg (vmode, d.op0);
24592 : 66001 : if (d.op0 == d.op1)
24593 : 15649 : d.op1 = nop0;
24594 : 66001 : d.op0 = nop0;
24595 : 66001 : d.op1 = force_reg (vmode, d.op1);
24596 : :
24597 : 66001 : if (ix86_expand_vec_perm_const_1 (&d))
24598 : : return true;
24599 : :
24600 : : /* If the selector says both arguments are needed, but the operands are the
24601 : : same, the above tried to expand with one_operand_p and flattened selector.
24602 : : If that didn't work, retry without one_operand_p; we succeeded with that
24603 : : during testing. */
24604 : 22 : if (two_args && d.one_operand_p)
24605 : : {
24606 : 22 : d.one_operand_p = false;
24607 : 22 : memcpy (d.perm, perm, sizeof (perm));
24608 : 22 : return ix86_expand_vec_perm_const_1 (&d);
24609 : : }
24610 : :
24611 : : return false;
24612 : : }
24613 : :
24614 : : void
24615 : 7744 : ix86_expand_vec_extract_even_odd (rtx targ, rtx op0, rtx op1, unsigned odd)
24616 : : {
24617 : 7744 : struct expand_vec_perm_d d;
24618 : 7744 : unsigned i, nelt;
24619 : :
24620 : 7744 : d.target = targ;
24621 : 7744 : d.op0 = op0;
24622 : 7744 : d.op1 = op1;
24623 : 7744 : d.vmode = GET_MODE (targ);
24624 : 7744 : d.nelt = nelt = GET_MODE_NUNITS (d.vmode);
24625 : 7744 : d.one_operand_p = false;
24626 : 7744 : d.testing_p = false;
24627 : :
24628 : 74204 : for (i = 0; i < nelt; ++i)
24629 : 66460 : d.perm[i] = i * 2 + odd;
24630 : :
24631 : : /* We'll either be able to implement the permutation directly... */
24632 : 7744 : if (expand_vec_perm_1 (&d))
24633 : 3034 : return;
24634 : :
24635 : : /* ... or we use the special-case patterns. */
24636 : 4710 : expand_vec_perm_even_odd_1 (&d, odd);
24637 : : }
24638 : :
24639 : : static void
24640 : 854 : ix86_expand_vec_interleave (rtx targ, rtx op0, rtx op1, bool high_p)
24641 : : {
24642 : 854 : struct expand_vec_perm_d d;
24643 : 854 : unsigned i, nelt, base;
24644 : 854 : bool ok;
24645 : :
24646 : 854 : d.target = targ;
24647 : 854 : d.op0 = op0;
24648 : 854 : d.op1 = op1;
24649 : 854 : d.vmode = GET_MODE (targ);
24650 : 854 : d.nelt = nelt = GET_MODE_NUNITS (d.vmode);
24651 : 854 : d.one_operand_p = false;
24652 : 854 : d.testing_p = false;
24653 : :
24654 : 854 : base = high_p ? nelt / 2 : 0;
24655 : 3398 : for (i = 0; i < nelt / 2; ++i)
24656 : : {
24657 : 2544 : d.perm[i * 2] = i + base;
24658 : 2544 : d.perm[i * 2 + 1] = i + base + nelt;
24659 : : }
24660 : :
24661 : : /* Note that for AVX this isn't one instruction. */
24662 : 854 : ok = ix86_expand_vec_perm_const_1 (&d);
24663 : 854 : gcc_assert (ok);
24664 : 854 : }
24665 : :
24666 : : /* Expand a vector operation shift by constant for a V*QImode in terms of the
24667 : : same operation on V*HImode. Return true if success. */
24668 : : static bool
24669 : 334 : ix86_expand_vec_shift_qihi_constant (enum rtx_code code,
24670 : : rtx dest, rtx op1, rtx op2)
24671 : : {
24672 : 334 : machine_mode qimode, himode;
24673 : 334 : HOST_WIDE_INT and_constant, xor_constant;
24674 : 334 : HOST_WIDE_INT shift_amount;
24675 : 334 : rtx vec_const_and, vec_const_xor;
24676 : 334 : rtx tmp, op1_subreg;
24677 : 334 : rtx (*gen_shift) (rtx, rtx, rtx);
24678 : 334 : rtx (*gen_and) (rtx, rtx, rtx);
24679 : 334 : rtx (*gen_xor) (rtx, rtx, rtx);
24680 : 334 : rtx (*gen_sub) (rtx, rtx, rtx);
24681 : :
24682 : : /* Only optimize shift by constant. */
24683 : 334 : if (!CONST_INT_P (op2))
24684 : : return false;
24685 : :
24686 : 334 : qimode = GET_MODE (dest);
24687 : 334 : shift_amount = INTVAL (op2);
24688 : : /* Do nothing when shift amount greater equal 8. */
24689 : 334 : if (shift_amount > 7)
24690 : : return false;
24691 : :
24692 : 334 : gcc_assert (code == ASHIFT || code == ASHIFTRT || code == LSHIFTRT);
24693 : :
24694 : :
24695 : 334 : if (shift_amount == 7
24696 : 334 : && code == ASHIFTRT)
24697 : : {
24698 : 26 : if (qimode == V16QImode
24699 : 8 : || qimode == V32QImode)
24700 : : {
24701 : 25 : rtx zero = gen_reg_rtx (qimode);
24702 : 25 : emit_move_insn (zero, CONST0_RTX (qimode));
24703 : 25 : emit_move_insn (dest, gen_rtx_fmt_ee (GT, qimode, zero, op1));
24704 : 25 : }
24705 : : else
24706 : : {
24707 : 1 : gcc_assert (qimode == V64QImode);
24708 : 1 : rtx kmask = gen_reg_rtx (DImode);
24709 : 1 : emit_insn (gen_avx512bw_cvtb2maskv64qi (kmask, op1));
24710 : 1 : emit_insn (gen_avx512bw_cvtmask2bv64qi (dest, kmask));
24711 : : }
24712 : 26 : return true;
24713 : : }
24714 : :
24715 : : /* Record sign bit. */
24716 : 308 : xor_constant = 1 << (8 - shift_amount - 1);
24717 : :
24718 : : /* Zero upper/lower bits shift from left/right element. */
24719 : 308 : and_constant
24720 : 308 : = (code == ASHIFT ? 256 - (1 << shift_amount)
24721 : 290 : : (1 << (8 - shift_amount)) - 1);
24722 : :
24723 : 308 : switch (qimode)
24724 : : {
24725 : 295 : case V16QImode:
24726 : 295 : himode = V8HImode;
24727 : 257 : gen_shift =
24728 : : ((code == ASHIFT)
24729 : 295 : ? gen_ashlv8hi3
24730 : 286 : : (code == ASHIFTRT) ? gen_ashrv8hi3 : gen_lshrv8hi3);
24731 : : gen_and = gen_andv16qi3;
24732 : : gen_xor = gen_xorv16qi3;
24733 : : gen_sub = gen_subv16qi3;
24734 : : break;
24735 : 5 : case V32QImode:
24736 : 5 : himode = V16HImode;
24737 : 1 : gen_shift =
24738 : : ((code == ASHIFT)
24739 : 5 : ? gen_ashlv16hi3
24740 : 2 : : (code == ASHIFTRT) ? gen_ashrv16hi3 : gen_lshrv16hi3);
24741 : : gen_and = gen_andv32qi3;
24742 : : gen_xor = gen_xorv32qi3;
24743 : : gen_sub = gen_subv32qi3;
24744 : : break;
24745 : 8 : case V64QImode:
24746 : 8 : himode = V32HImode;
24747 : 1 : gen_shift =
24748 : : ((code == ASHIFT)
24749 : 8 : ? gen_ashlv32hi3
24750 : 2 : : (code == ASHIFTRT) ? gen_ashrv32hi3 : gen_lshrv32hi3);
24751 : : gen_and = gen_andv64qi3;
24752 : : gen_xor = gen_xorv64qi3;
24753 : : gen_sub = gen_subv64qi3;
24754 : : break;
24755 : 0 : default:
24756 : 0 : gcc_unreachable ();
24757 : : }
24758 : :
24759 : 308 : tmp = gen_reg_rtx (himode);
24760 : 308 : vec_const_and = gen_reg_rtx (qimode);
24761 : 308 : op1_subreg = lowpart_subreg (himode, op1, qimode);
24762 : :
24763 : : /* For ASHIFT and LSHIFTRT, perform operation like
24764 : : vpsllw/vpsrlw $shift_amount, %op1, %dest.
24765 : : vpand %vec_const_and, %dest. */
24766 : 308 : emit_insn (gen_shift (tmp, op1_subreg, op2));
24767 : 308 : emit_move_insn (dest, simplify_gen_subreg (qimode, tmp, himode, 0));
24768 : 308 : emit_move_insn (vec_const_and,
24769 : : ix86_build_const_vector (qimode, true,
24770 : 308 : gen_int_mode (and_constant, QImode)));
24771 : 308 : emit_insn (gen_and (dest, dest, vec_const_and));
24772 : :
24773 : : /* For ASHIFTRT, perform extra operation like
24774 : : vpxor %vec_const_xor, %dest, %dest
24775 : : vpsubb %vec_const_xor, %dest, %dest */
24776 : 308 : if (code == ASHIFTRT)
24777 : : {
24778 : 31 : vec_const_xor = gen_reg_rtx (qimode);
24779 : 31 : emit_move_insn (vec_const_xor,
24780 : : ix86_build_const_vector (qimode, true,
24781 : 31 : gen_int_mode (xor_constant, QImode)));
24782 : 31 : emit_insn (gen_xor (dest, dest, vec_const_xor));
24783 : 31 : emit_insn (gen_sub (dest, dest, vec_const_xor));
24784 : : }
24785 : : return true;
24786 : : }
24787 : :
24788 : : void
24789 : 1374 : ix86_expand_vecop_qihi_partial (enum rtx_code code, rtx dest, rtx op1, rtx op2)
24790 : : {
24791 : 1374 : machine_mode qimode = GET_MODE (dest);
24792 : 1374 : rtx qop1, qop2, hop1, hop2, qdest, hdest;
24793 : 1374 : bool op2vec = GET_MODE_CLASS (GET_MODE (op2)) == MODE_VECTOR_INT;
24794 : 1374 : bool uns_p = code != ASHIFTRT;
24795 : :
24796 : 1374 : switch (qimode)
24797 : : {
24798 : 1374 : case E_V4QImode:
24799 : 1374 : case E_V8QImode:
24800 : 1374 : break;
24801 : 0 : default:
24802 : 0 : gcc_unreachable ();
24803 : : }
24804 : :
24805 : 1374 : qop1 = lowpart_subreg (V16QImode, force_reg (qimode, op1), qimode);
24806 : :
24807 : 1374 : if (op2vec)
24808 : 1320 : qop2 = lowpart_subreg (V16QImode, force_reg (qimode, op2), qimode);
24809 : : else
24810 : : qop2 = op2;
24811 : :
24812 : 1374 : qdest = gen_reg_rtx (V16QImode);
24813 : :
24814 : 1374 : if (CONST_INT_P (op2)
24815 : 42 : && (code == ASHIFT || code == LSHIFTRT || code == ASHIFTRT)
24816 : : /* With AVX512 it's cheaper to do vpmovsxbw/op/vpmovwb.
24817 : : Even with SSE4.1 the alternative is better. */
24818 : 42 : && !TARGET_SSE4_1
24819 : 1404 : && ix86_expand_vec_shift_qihi_constant (code, qdest, qop1, qop2))
24820 : : {
24821 : 30 : emit_move_insn (dest, gen_lowpart (qimode, qdest));
24822 : 30 : return;
24823 : : }
24824 : :
24825 : 1344 : if (CONST_INT_P (op2)
24826 : 12 : && code == ASHIFTRT
24827 : 6 : && INTVAL (op2) == 7)
24828 : : {
24829 : 2 : rtx zero = gen_reg_rtx (qimode);
24830 : 2 : emit_move_insn (zero, CONST0_RTX (qimode));
24831 : 2 : emit_move_insn (dest, gen_rtx_fmt_ee (GT, qimode, zero, op1));
24832 : 2 : return;
24833 : : }
24834 : :
24835 : 1342 : switch (code)
24836 : : {
24837 : 1307 : case MULT:
24838 : 1307 : gcc_assert (op2vec);
24839 : 1307 : if (!TARGET_SSE4_1)
24840 : : {
24841 : : /* Unpack data such that we've got a source byte in each low byte
24842 : : of each word. We don't care what goes into the high byte of
24843 : : each word. Rather than trying to get zero in there, most
24844 : : convenient is to let it be a copy of the low byte. */
24845 : 242 : hop1 = copy_to_reg (qop1);
24846 : 242 : hop2 = copy_to_reg (qop2);
24847 : 242 : emit_insn (gen_vec_interleave_lowv16qi (hop1, hop1, hop1));
24848 : 242 : emit_insn (gen_vec_interleave_lowv16qi (hop2, hop2, hop2));
24849 : 242 : break;
24850 : : }
24851 : : /* FALLTHRU */
24852 : 1100 : case ASHIFT:
24853 : 1100 : case ASHIFTRT:
24854 : 1100 : case LSHIFTRT:
24855 : 1100 : hop1 = gen_reg_rtx (V8HImode);
24856 : 1100 : ix86_expand_sse_unpack (hop1, qop1, uns_p, false);
24857 : : /* mult/vashr/vlshr/vashl */
24858 : 1100 : if (op2vec)
24859 : : {
24860 : 1078 : hop2 = gen_reg_rtx (V8HImode);
24861 : 1078 : ix86_expand_sse_unpack (hop2, qop2, uns_p, false);
24862 : : }
24863 : : else
24864 : : hop2 = qop2;
24865 : :
24866 : : break;
24867 : 0 : default:
24868 : 0 : gcc_unreachable ();
24869 : : }
24870 : :
24871 : 1342 : if (code != MULT && op2vec)
24872 : : {
24873 : : /* Expand vashr/vlshr/vashl. */
24874 : 13 : hdest = gen_reg_rtx (V8HImode);
24875 : 13 : emit_insn (gen_rtx_SET (hdest,
24876 : : simplify_gen_binary (code, V8HImode,
24877 : : hop1, hop2)));
24878 : : }
24879 : : else
24880 : : /* Expand mult/ashr/lshr/ashl. */
24881 : 1329 : hdest = expand_simple_binop (V8HImode, code, hop1, hop2,
24882 : : NULL_RTX, 1, OPTAB_DIRECT);
24883 : :
24884 : 1342 : if (TARGET_AVX512BW && TARGET_AVX512VL)
24885 : : {
24886 : 30 : if (qimode == V8QImode)
24887 : : qdest = dest;
24888 : : else
24889 : 10 : qdest = gen_reg_rtx (V8QImode);
24890 : :
24891 : 30 : emit_insn (gen_truncv8hiv8qi2 (qdest, hdest));
24892 : : }
24893 : : else
24894 : : {
24895 : 1312 : struct expand_vec_perm_d d;
24896 : 1312 : rtx qres = gen_lowpart (V16QImode, hdest);
24897 : 1312 : bool ok;
24898 : 1312 : int i;
24899 : :
24900 : : /* Merge the data back into the right place. */
24901 : 1312 : d.target = qdest;
24902 : 1312 : d.op0 = d.op1 = qres;
24903 : 1312 : d.vmode = V16QImode;
24904 : 1312 : d.nelt = 16;
24905 : 1312 : d.one_operand_p = TARGET_SSSE3;
24906 : 1312 : d.testing_p = false;
24907 : :
24908 : 22304 : for (i = 0; i < d.nelt; ++i)
24909 : 20992 : d.perm[i] = i * 2;
24910 : :
24911 : 1312 : ok = ix86_expand_vec_perm_const_1 (&d);
24912 : 1312 : gcc_assert (ok);
24913 : : }
24914 : :
24915 : 1342 : if (qdest != dest)
24916 : 1322 : emit_move_insn (dest, gen_lowpart (qimode, qdest));
24917 : : }
24918 : :
24919 : : /* Emit instruction in 2x wider mode. For example, optimize
24920 : : vector MUL generation like
24921 : :
24922 : : vpmovzxbw ymm2, xmm0
24923 : : vpmovzxbw ymm3, xmm1
24924 : : vpmullw ymm4, ymm2, ymm3
24925 : : vpmovwb xmm0, ymm4
24926 : :
24927 : : it would take less instructions than ix86_expand_vecop_qihi.
24928 : : Return true if success. */
24929 : :
24930 : : static bool
24931 : 1337 : ix86_expand_vecop_qihi2 (enum rtx_code code, rtx dest, rtx op1, rtx op2)
24932 : : {
24933 : 1337 : machine_mode himode, qimode = GET_MODE (dest);
24934 : 1337 : machine_mode wqimode;
24935 : 1337 : rtx qop1, qop2, hop1, hop2, hdest;
24936 : 1337 : rtx (*gen_truncate)(rtx, rtx) = NULL;
24937 : 1337 : bool op2vec = GET_MODE_CLASS (GET_MODE (op2)) == MODE_VECTOR_INT;
24938 : 1337 : bool uns_p = code != ASHIFTRT;
24939 : :
24940 : : /* Without VPMOVWB (provided by AVX512BW ISA), the expansion uses the
24941 : : generic permutation to merge the data back into the right place. This
24942 : : permutation results in VPERMQ, which is slow, so better fall back to
24943 : : ix86_expand_vecop_qihi. */
24944 : 1337 : if (!TARGET_AVX512BW
24945 : 301 : || (qimode == V16QImode && !TARGET_AVX512VL)
24946 : : /* There are no V64HImode instructions. */
24947 : 301 : || qimode == V64QImode)
24948 : : return false;
24949 : :
24950 : : /* Do not generate ymm/zmm instructions when
24951 : : target prefers 128/256 bit vector width. */
24952 : 267 : if ((qimode == V16QImode && TARGET_PREFER_AVX128)
24953 : 267 : || (qimode == V32QImode && TARGET_PREFER_AVX256))
24954 : : return false;
24955 : :
24956 : 260 : switch (qimode)
24957 : : {
24958 : : case E_V16QImode:
24959 : : himode = V16HImode;
24960 : : gen_truncate = gen_truncv16hiv16qi2;
24961 : : break;
24962 : 17 : case E_V32QImode:
24963 : 17 : himode = V32HImode;
24964 : 17 : gen_truncate = gen_truncv32hiv32qi2;
24965 : 17 : break;
24966 : 0 : default:
24967 : 0 : gcc_unreachable ();
24968 : : }
24969 : :
24970 : 260 : wqimode = GET_MODE_2XWIDER_MODE (qimode).require ();
24971 : 260 : qop1 = lowpart_subreg (wqimode, force_reg (qimode, op1), qimode);
24972 : :
24973 : 260 : if (op2vec)
24974 : 260 : qop2 = lowpart_subreg (wqimode, force_reg (qimode, op2), qimode);
24975 : : else
24976 : : qop2 = op2;
24977 : :
24978 : 260 : hop1 = gen_reg_rtx (himode);
24979 : 260 : ix86_expand_sse_unpack (hop1, qop1, uns_p, false);
24980 : :
24981 : 260 : if (op2vec)
24982 : : {
24983 : 260 : hop2 = gen_reg_rtx (himode);
24984 : 260 : ix86_expand_sse_unpack (hop2, qop2, uns_p, false);
24985 : : }
24986 : : else
24987 : : hop2 = qop2;
24988 : :
24989 : 260 : if (code != MULT && op2vec)
24990 : : {
24991 : : /* Expand vashr/vlshr/vashl. */
24992 : 14 : hdest = gen_reg_rtx (himode);
24993 : 14 : emit_insn (gen_rtx_SET (hdest,
24994 : : simplify_gen_binary (code, himode,
24995 : : hop1, hop2)));
24996 : : }
24997 : : else
24998 : : /* Expand mult/ashr/lshr/ashl. */
24999 : 246 : hdest = expand_simple_binop (himode, code, hop1, hop2,
25000 : : NULL_RTX, 1, OPTAB_DIRECT);
25001 : :
25002 : 260 : emit_insn (gen_truncate (dest, hdest));
25003 : 260 : return true;
25004 : : }
25005 : :
25006 : : /* Expand a vector operation CODE for a V*QImode in terms of the
25007 : : same operation on V*HImode. */
25008 : :
25009 : : void
25010 : 1641 : ix86_expand_vecop_qihi (enum rtx_code code, rtx dest, rtx op1, rtx op2)
25011 : : {
25012 : 1641 : machine_mode qimode = GET_MODE (dest);
25013 : 1641 : machine_mode himode;
25014 : 1641 : rtx (*gen_il) (rtx, rtx, rtx);
25015 : 1641 : rtx (*gen_ih) (rtx, rtx, rtx);
25016 : 1641 : rtx op1_l, op1_h, op2_l, op2_h, res_l, res_h;
25017 : 1641 : bool op2vec = GET_MODE_CLASS (GET_MODE (op2)) == MODE_VECTOR_INT;
25018 : 1641 : struct expand_vec_perm_d d;
25019 : 1641 : bool full_interleave = true;
25020 : 1641 : bool uns_p = code != ASHIFTRT;
25021 : 1641 : bool ok;
25022 : 1641 : int i;
25023 : :
25024 : 1641 : if (CONST_INT_P (op2)
25025 : 304 : && (code == ASHIFT || code == LSHIFTRT || code == ASHIFTRT)
25026 : 1945 : && ix86_expand_vec_shift_qihi_constant (code, dest, op1, op2))
25027 : 564 : return;
25028 : :
25029 : 1337 : if (ix86_expand_vecop_qihi2 (code, dest, op1, op2))
25030 : : return;
25031 : :
25032 : 1077 : switch (qimode)
25033 : : {
25034 : : case E_V16QImode:
25035 : : himode = V8HImode;
25036 : : break;
25037 : 280 : case E_V32QImode:
25038 : 280 : himode = V16HImode;
25039 : 280 : break;
25040 : 34 : case E_V64QImode:
25041 : 34 : himode = V32HImode;
25042 : 34 : break;
25043 : 0 : default:
25044 : 0 : gcc_unreachable ();
25045 : : }
25046 : :
25047 : 1077 : switch (code)
25048 : : {
25049 : 1069 : case MULT:
25050 : 1069 : gcc_assert (op2vec);
25051 : : /* Unpack data such that we've got a source byte in each low byte of
25052 : : each word. We don't care what goes into the high byte of each word.
25053 : : Rather than trying to get zero in there, most convenient is to let
25054 : : it be a copy of the low byte. */
25055 : 1069 : switch (qimode)
25056 : : {
25057 : : case E_V16QImode:
25058 : : gen_il = gen_vec_interleave_lowv16qi;
25059 : : gen_ih = gen_vec_interleave_highv16qi;
25060 : : break;
25061 : 280 : case E_V32QImode:
25062 : 280 : gen_il = gen_avx2_interleave_lowv32qi;
25063 : 280 : gen_ih = gen_avx2_interleave_highv32qi;
25064 : 280 : full_interleave = false;
25065 : 280 : break;
25066 : 32 : case E_V64QImode:
25067 : 32 : gen_il = gen_avx512bw_interleave_lowv64qi;
25068 : 32 : gen_ih = gen_avx512bw_interleave_highv64qi;
25069 : 32 : full_interleave = false;
25070 : 32 : break;
25071 : 0 : default:
25072 : 0 : gcc_unreachable ();
25073 : : }
25074 : :
25075 : 1069 : op2_l = gen_reg_rtx (qimode);
25076 : 1069 : op2_h = gen_reg_rtx (qimode);
25077 : 1069 : emit_insn (gen_il (op2_l, op2, op2));
25078 : 1069 : emit_insn (gen_ih (op2_h, op2, op2));
25079 : :
25080 : 1069 : op1_l = gen_reg_rtx (qimode);
25081 : 1069 : op1_h = gen_reg_rtx (qimode);
25082 : 1069 : emit_insn (gen_il (op1_l, op1, op1));
25083 : 1069 : emit_insn (gen_ih (op1_h, op1, op1));
25084 : 1069 : break;
25085 : :
25086 : 8 : case ASHIFT:
25087 : 8 : case ASHIFTRT:
25088 : 8 : case LSHIFTRT:
25089 : 8 : op1_l = gen_reg_rtx (himode);
25090 : 8 : op1_h = gen_reg_rtx (himode);
25091 : 8 : ix86_expand_sse_unpack (op1_l, op1, uns_p, false);
25092 : 8 : ix86_expand_sse_unpack (op1_h, op1, uns_p, true);
25093 : : /* vashr/vlshr/vashl */
25094 : 8 : if (op2vec)
25095 : : {
25096 : 2 : rtx tmp = force_reg (qimode, op2);
25097 : 2 : op2_l = gen_reg_rtx (himode);
25098 : 2 : op2_h = gen_reg_rtx (himode);
25099 : 2 : ix86_expand_sse_unpack (op2_l, tmp, uns_p, false);
25100 : 2 : ix86_expand_sse_unpack (op2_h, tmp, uns_p, true);
25101 : : }
25102 : : else
25103 : : op2_l = op2_h = op2;
25104 : :
25105 : : break;
25106 : 0 : default:
25107 : 0 : gcc_unreachable ();
25108 : : }
25109 : :
25110 : 1077 : if (code != MULT && op2vec)
25111 : : {
25112 : : /* Expand vashr/vlshr/vashl. */
25113 : 2 : res_l = gen_reg_rtx (himode);
25114 : 2 : res_h = gen_reg_rtx (himode);
25115 : 2 : emit_insn (gen_rtx_SET (res_l,
25116 : : simplify_gen_binary (code, himode,
25117 : : op1_l, op2_l)));
25118 : 2 : emit_insn (gen_rtx_SET (res_h,
25119 : : simplify_gen_binary (code, himode,
25120 : : op1_h, op2_h)));
25121 : : }
25122 : : else
25123 : : {
25124 : : /* Expand mult/ashr/lshr/ashl. */
25125 : 1075 : res_l = expand_simple_binop (himode, code, op1_l, op2_l, NULL_RTX,
25126 : : 1, OPTAB_DIRECT);
25127 : 1075 : res_h = expand_simple_binop (himode, code, op1_h, op2_h, NULL_RTX,
25128 : : 1, OPTAB_DIRECT);
25129 : : }
25130 : :
25131 : 1077 : gcc_assert (res_l && res_h);
25132 : :
25133 : : /* Merge the data back into the right place. */
25134 : 1077 : d.target = dest;
25135 : 1077 : d.op0 = gen_lowpart (qimode, res_l);
25136 : 1077 : d.op1 = gen_lowpart (qimode, res_h);
25137 : 1077 : d.vmode = qimode;
25138 : 1077 : d.nelt = GET_MODE_NUNITS (qimode);
25139 : 1077 : d.one_operand_p = false;
25140 : 1077 : d.testing_p = false;
25141 : :
25142 : 1077 : if (full_interleave)
25143 : : {
25144 : : /* We used the full interleave, the desired
25145 : : results are in the even elements. */
25146 : 13101 : for (i = 0; i < d.nelt; ++i)
25147 : 12336 : d.perm[i] = i * 2;
25148 : : }
25149 : : else
25150 : : {
25151 : : /* For AVX, the interleave used above was not cross-lane. So the
25152 : : extraction is evens but with the second and third quarter swapped.
25153 : : Happily, that is even one insn shorter than even extraction.
25154 : : For AVX512BW we have 4 lanes. We extract evens from within a lane,
25155 : : always first from the first and then from the second source operand,
25156 : : the index bits above the low 4 bits remains the same.
25157 : : Thus, for d.nelt == 32 we want permutation
25158 : : 0,2,4,..14, 32,34,36,..46, 16,18,20,..30, 48,50,52,..62
25159 : : and for d.nelt == 64 we want permutation
25160 : : 0,2,4,..14, 64,66,68,..78, 16,18,20,..30, 80,82,84,..94,
25161 : : 32,34,36,..46, 96,98,100,..110, 48,50,52,..62, 112,114,116,..126. */
25162 : 11320 : for (i = 0; i < d.nelt; ++i)
25163 : 16512 : d.perm[i] = ((i * 2) & 14) + ((i & 8) ? d.nelt : 0) + (i & ~15);
25164 : : }
25165 : :
25166 : 1077 : ok = ix86_expand_vec_perm_const_1 (&d);
25167 : 1077 : gcc_assert (ok);
25168 : : }
25169 : :
25170 : : /* Helper function of ix86_expand_mul_widen_evenodd. Return true
25171 : : if op is CONST_VECTOR with all odd elements equal to their
25172 : : preceding element. */
25173 : :
25174 : : static bool
25175 : 8322 : const_vector_equal_evenodd_p (rtx op)
25176 : : {
25177 : 8322 : machine_mode mode = GET_MODE (op);
25178 : 8322 : int i, nunits = GET_MODE_NUNITS (mode);
25179 : 8322 : if (GET_CODE (op) != CONST_VECTOR
25180 : 8322 : || nunits != CONST_VECTOR_NUNITS (op))
25181 : : return false;
25182 : 3156 : for (i = 0; i < nunits; i += 2)
25183 : 2574 : if (CONST_VECTOR_ELT (op, i) != CONST_VECTOR_ELT (op, i + 1))
25184 : : return false;
25185 : : return true;
25186 : : }
25187 : :
25188 : : void
25189 : 8435 : ix86_expand_mul_widen_evenodd (rtx dest, rtx op1, rtx op2,
25190 : : bool uns_p, bool odd_p)
25191 : : {
25192 : 8435 : machine_mode mode = GET_MODE (op1);
25193 : 8435 : machine_mode wmode = GET_MODE (dest);
25194 : 8435 : rtx x;
25195 : 8435 : rtx orig_op1 = op1, orig_op2 = op2;
25196 : :
25197 : 8435 : if (!nonimmediate_operand (op1, mode))
25198 : 0 : op1 = force_reg (mode, op1);
25199 : 8435 : if (!nonimmediate_operand (op2, mode))
25200 : 3189 : op2 = force_reg (mode, op2);
25201 : :
25202 : : /* We only play even/odd games with vectors of SImode. */
25203 : 8435 : gcc_assert (mode == V4SImode || mode == V8SImode || mode == V16SImode);
25204 : :
25205 : : /* If we're looking for the odd results, shift those members down to
25206 : : the even slots. For some cpus this is faster than a PSHUFD. */
25207 : 8435 : if (odd_p)
25208 : : {
25209 : : /* For XOP use vpmacsdqh, but only for smult, as it is only
25210 : : signed. */
25211 : 4179 : if (TARGET_XOP && mode == V4SImode && !uns_p)
25212 : : {
25213 : 18 : x = force_reg (wmode, CONST0_RTX (wmode));
25214 : 18 : emit_insn (gen_xop_pmacsdqh (dest, op1, op2, x));
25215 : 18 : return;
25216 : : }
25217 : :
25218 : 8322 : x = GEN_INT (GET_MODE_UNIT_BITSIZE (mode));
25219 : 4161 : if (!const_vector_equal_evenodd_p (orig_op1))
25220 : 4161 : op1 = expand_binop (wmode, lshr_optab, gen_lowpart (wmode, op1),
25221 : : x, NULL, 1, OPTAB_DIRECT);
25222 : 4161 : if (!const_vector_equal_evenodd_p (orig_op2))
25223 : 3579 : op2 = expand_binop (wmode, lshr_optab, gen_lowpart (wmode, op2),
25224 : : x, NULL, 1, OPTAB_DIRECT);
25225 : 4161 : op1 = gen_lowpart (mode, op1);
25226 : 4161 : op2 = gen_lowpart (mode, op2);
25227 : : }
25228 : :
25229 : 8417 : if (mode == V16SImode)
25230 : : {
25231 : 4 : if (uns_p)
25232 : 0 : x = gen_vec_widen_umult_even_v16si (dest, op1, op2);
25233 : : else
25234 : 4 : x = gen_vec_widen_smult_even_v16si (dest, op1, op2);
25235 : : }
25236 : 8413 : else if (mode == V8SImode)
25237 : : {
25238 : 89 : if (uns_p)
25239 : 39 : x = gen_vec_widen_umult_even_v8si (dest, op1, op2);
25240 : : else
25241 : 50 : x = gen_vec_widen_smult_even_v8si (dest, op1, op2);
25242 : : }
25243 : 8324 : else if (uns_p)
25244 : 7381 : x = gen_vec_widen_umult_even_v4si (dest, op1, op2);
25245 : 943 : else if (TARGET_SSE4_1)
25246 : 305 : x = gen_sse4_1_mulv2siv2di3 (dest, op1, op2);
25247 : : else
25248 : : {
25249 : 638 : rtx s1, s2, t0, t1, t2;
25250 : :
25251 : : /* The easiest way to implement this without PMULDQ is to go through
25252 : : the motions as if we are performing a full 64-bit multiply. With
25253 : : the exception that we need to do less shuffling of the elements. */
25254 : :
25255 : : /* Compute the sign-extension, aka highparts, of the two operands. */
25256 : 638 : s1 = ix86_expand_sse_cmp (gen_reg_rtx (mode), GT, CONST0_RTX (mode),
25257 : : op1, pc_rtx, pc_rtx);
25258 : 638 : s2 = ix86_expand_sse_cmp (gen_reg_rtx (mode), GT, CONST0_RTX (mode),
25259 : : op2, pc_rtx, pc_rtx);
25260 : :
25261 : : /* Multiply LO(A) * HI(B), and vice-versa. */
25262 : 638 : t1 = gen_reg_rtx (wmode);
25263 : 638 : t2 = gen_reg_rtx (wmode);
25264 : 638 : emit_insn (gen_vec_widen_umult_even_v4si (t1, s1, op2));
25265 : 638 : emit_insn (gen_vec_widen_umult_even_v4si (t2, s2, op1));
25266 : :
25267 : : /* Multiply LO(A) * LO(B). */
25268 : 638 : t0 = gen_reg_rtx (wmode);
25269 : 638 : emit_insn (gen_vec_widen_umult_even_v4si (t0, op1, op2));
25270 : :
25271 : : /* Combine and shift the highparts into place. */
25272 : 638 : t1 = expand_binop (wmode, add_optab, t1, t2, t1, 1, OPTAB_DIRECT);
25273 : 638 : t1 = expand_binop (wmode, ashl_optab, t1, GEN_INT (32), t1,
25274 : : 1, OPTAB_DIRECT);
25275 : :
25276 : : /* Combine high and low parts. */
25277 : 638 : force_expand_binop (wmode, add_optab, t0, t1, dest, 1, OPTAB_DIRECT);
25278 : 638 : return;
25279 : : }
25280 : 7779 : emit_insn (x);
25281 : : }
25282 : :
25283 : : void
25284 : 867 : ix86_expand_mul_widen_hilo (rtx dest, rtx op1, rtx op2,
25285 : : bool uns_p, bool high_p)
25286 : : {
25287 : 867 : machine_mode wmode = GET_MODE (dest);
25288 : 867 : machine_mode mode = GET_MODE (op1);
25289 : 867 : rtx t1, t2, t3, t4, mask;
25290 : :
25291 : 867 : switch (mode)
25292 : : {
25293 : 269 : case E_V4SImode:
25294 : 269 : t1 = gen_reg_rtx (mode);
25295 : 269 : t2 = gen_reg_rtx (mode);
25296 : 269 : if (TARGET_XOP && !uns_p)
25297 : : {
25298 : : /* With XOP, we have pmacsdqh, aka mul_widen_odd. In this case,
25299 : : shuffle the elements once so that all elements are in the right
25300 : : place for immediate use: { A C B D }. */
25301 : 33 : emit_insn (gen_sse2_pshufd_1 (t1, op1, const0_rtx, const2_rtx,
25302 : : const1_rtx, GEN_INT (3)));
25303 : 33 : emit_insn (gen_sse2_pshufd_1 (t2, op2, const0_rtx, const2_rtx,
25304 : : const1_rtx, GEN_INT (3)));
25305 : : }
25306 : : else
25307 : : {
25308 : : /* Put the elements into place for the multiply. */
25309 : 236 : ix86_expand_vec_interleave (t1, op1, op1, high_p);
25310 : 236 : ix86_expand_vec_interleave (t2, op2, op2, high_p);
25311 : 236 : high_p = false;
25312 : : }
25313 : 269 : ix86_expand_mul_widen_evenodd (dest, t1, t2, uns_p, high_p);
25314 : 269 : break;
25315 : :
25316 : 48 : case E_V8SImode:
25317 : : /* Shuffle the elements between the lanes. After this we
25318 : : have { A B E F | C D G H } for each operand. */
25319 : 48 : t1 = gen_reg_rtx (V4DImode);
25320 : 48 : t2 = gen_reg_rtx (V4DImode);
25321 : 48 : emit_insn (gen_avx2_permv4di_1 (t1, gen_lowpart (V4DImode, op1),
25322 : : const0_rtx, const2_rtx,
25323 : : const1_rtx, GEN_INT (3)));
25324 : 48 : emit_insn (gen_avx2_permv4di_1 (t2, gen_lowpart (V4DImode, op2),
25325 : : const0_rtx, const2_rtx,
25326 : : const1_rtx, GEN_INT (3)));
25327 : :
25328 : : /* Shuffle the elements within the lanes. After this we
25329 : : have { A A B B | C C D D } or { E E F F | G G H H }. */
25330 : 48 : t3 = gen_reg_rtx (V8SImode);
25331 : 48 : t4 = gen_reg_rtx (V8SImode);
25332 : 72 : mask = GEN_INT (high_p
25333 : : ? 2 + (2 << 2) + (3 << 4) + (3 << 6)
25334 : : : 0 + (0 << 2) + (1 << 4) + (1 << 6));
25335 : 48 : emit_insn (gen_avx2_pshufdv3 (t3, gen_lowpart (V8SImode, t1), mask));
25336 : 48 : emit_insn (gen_avx2_pshufdv3 (t4, gen_lowpart (V8SImode, t2), mask));
25337 : :
25338 : 48 : ix86_expand_mul_widen_evenodd (dest, t3, t4, uns_p, false);
25339 : 48 : break;
25340 : :
25341 : 382 : case E_V8HImode:
25342 : 382 : case E_V16HImode:
25343 : 382 : t1 = expand_binop (mode, smul_optab, op1, op2, NULL_RTX,
25344 : : uns_p, OPTAB_DIRECT);
25345 : 618 : t2 = expand_binop (mode,
25346 : : uns_p ? umul_highpart_optab : smul_highpart_optab,
25347 : : op1, op2, NULL_RTX, uns_p, OPTAB_DIRECT);
25348 : 382 : gcc_assert (t1 && t2);
25349 : :
25350 : 382 : t3 = gen_reg_rtx (mode);
25351 : 382 : ix86_expand_vec_interleave (t3, t1, t2, high_p);
25352 : 382 : emit_move_insn (dest, gen_lowpart (wmode, t3));
25353 : 382 : break;
25354 : :
25355 : 168 : case E_V16QImode:
25356 : 168 : case E_V32QImode:
25357 : 168 : case E_V32HImode:
25358 : 168 : case E_V16SImode:
25359 : 168 : case E_V64QImode:
25360 : 168 : t1 = gen_reg_rtx (wmode);
25361 : 168 : t2 = gen_reg_rtx (wmode);
25362 : 168 : ix86_expand_sse_unpack (t1, op1, uns_p, high_p);
25363 : 168 : ix86_expand_sse_unpack (t2, op2, uns_p, high_p);
25364 : :
25365 : 168 : emit_insn (gen_rtx_SET (dest, gen_rtx_MULT (wmode, t1, t2)));
25366 : 168 : break;
25367 : :
25368 : 0 : default:
25369 : 0 : gcc_unreachable ();
25370 : : }
25371 : 867 : }
25372 : :
25373 : : void
25374 : 3549 : ix86_expand_sse2_mulv4si3 (rtx op0, rtx op1, rtx op2)
25375 : : {
25376 : 3549 : rtx res_1, res_2, res_3, res_4;
25377 : :
25378 : 3549 : res_1 = gen_reg_rtx (V4SImode);
25379 : 3549 : res_2 = gen_reg_rtx (V4SImode);
25380 : 3549 : res_3 = gen_reg_rtx (V2DImode);
25381 : 3549 : res_4 = gen_reg_rtx (V2DImode);
25382 : 3549 : ix86_expand_mul_widen_evenodd (res_3, op1, op2, true, false);
25383 : 3549 : ix86_expand_mul_widen_evenodd (res_4, op1, op2, true, true);
25384 : :
25385 : : /* Move the results in element 2 down to element 1; we don't care
25386 : : what goes in elements 2 and 3. Then we can merge the parts
25387 : : back together with an interleave.
25388 : :
25389 : : Note that two other sequences were tried:
25390 : : (1) Use interleaves at the start instead of psrldq, which allows
25391 : : us to use a single shufps to merge things back at the end.
25392 : : (2) Use shufps here to combine the two vectors, then pshufd to
25393 : : put the elements in the correct order.
25394 : : In both cases the cost of the reformatting stall was too high
25395 : : and the overall sequence slower. */
25396 : :
25397 : 3549 : emit_insn (gen_sse2_pshufd_1 (res_1, gen_lowpart (V4SImode, res_3),
25398 : : const0_rtx, const2_rtx,
25399 : : const0_rtx, const0_rtx));
25400 : 3549 : emit_insn (gen_sse2_pshufd_1 (res_2, gen_lowpart (V4SImode, res_4),
25401 : : const0_rtx, const2_rtx,
25402 : : const0_rtx, const0_rtx));
25403 : 3549 : res_1 = emit_insn (gen_vec_interleave_lowv4si (op0, res_1, res_2));
25404 : :
25405 : 3549 : set_unique_reg_note (res_1, REG_EQUAL, gen_rtx_MULT (V4SImode, op1, op2));
25406 : 3549 : }
25407 : :
25408 : : void
25409 : 536 : ix86_expand_sse2_mulvxdi3 (rtx op0, rtx op1, rtx op2)
25410 : : {
25411 : 536 : machine_mode mode = GET_MODE (op0);
25412 : 536 : rtx t1, t2, t3, t4, t5, t6;
25413 : :
25414 : 536 : if (TARGET_AVX512DQ && mode == V8DImode)
25415 : 32 : emit_insn (gen_avx512dq_mulv8di3 (op0, op1, op2));
25416 : 504 : else if (TARGET_AVX512DQ && TARGET_AVX512VL && mode == V4DImode)
25417 : 32 : emit_insn (gen_avx512dq_mulv4di3 (op0, op1, op2));
25418 : 472 : else if (TARGET_AVX512DQ && TARGET_AVX512VL && mode == V2DImode)
25419 : 36 : emit_insn (gen_avx512dq_mulv2di3 (op0, op1, op2));
25420 : 436 : else if (TARGET_XOP && mode == V2DImode)
25421 : : {
25422 : : /* op1: A,B,C,D, op2: E,F,G,H */
25423 : 2 : op1 = gen_lowpart (V4SImode, op1);
25424 : 2 : op2 = gen_lowpart (V4SImode, op2);
25425 : :
25426 : 2 : t1 = gen_reg_rtx (V4SImode);
25427 : 2 : t2 = gen_reg_rtx (V4SImode);
25428 : 2 : t3 = gen_reg_rtx (V2DImode);
25429 : 2 : t4 = gen_reg_rtx (V2DImode);
25430 : :
25431 : : /* t1: B,A,D,C */
25432 : 2 : emit_insn (gen_sse2_pshufd_1 (t1, op1,
25433 : : GEN_INT (1),
25434 : : GEN_INT (0),
25435 : : GEN_INT (3),
25436 : : GEN_INT (2)));
25437 : :
25438 : : /* t2: (B*E),(A*F),(D*G),(C*H) */
25439 : 2 : emit_insn (gen_mulv4si3 (t2, t1, op2));
25440 : :
25441 : : /* t3: (B*E)+(A*F), (D*G)+(C*H) */
25442 : 2 : emit_insn (gen_xop_phadddq (t3, t2));
25443 : :
25444 : : /* t4: ((B*E)+(A*F))<<32, ((D*G)+(C*H))<<32 */
25445 : 2 : emit_insn (gen_ashlv2di3 (t4, t3, GEN_INT (32)));
25446 : :
25447 : : /* Multiply lower parts and add all */
25448 : 2 : t5 = gen_reg_rtx (V2DImode);
25449 : 2 : emit_insn (gen_vec_widen_umult_even_v4si (t5,
25450 : 2 : gen_lowpart (V4SImode, op1),
25451 : 2 : gen_lowpart (V4SImode, op2)));
25452 : 2 : force_expand_binop (mode, add_optab, t5, t4, op0, 1, OPTAB_DIRECT);
25453 : : }
25454 : : else
25455 : : {
25456 : 434 : machine_mode nmode;
25457 : 434 : rtx (*umul) (rtx, rtx, rtx);
25458 : :
25459 : 434 : if (mode == V2DImode)
25460 : : {
25461 : : umul = gen_vec_widen_umult_even_v4si;
25462 : : nmode = V4SImode;
25463 : : }
25464 : 329 : else if (mode == V4DImode)
25465 : : {
25466 : : umul = gen_vec_widen_umult_even_v8si;
25467 : : nmode = V8SImode;
25468 : : }
25469 : 118 : else if (mode == V8DImode)
25470 : : {
25471 : : umul = gen_vec_widen_umult_even_v16si;
25472 : : nmode = V16SImode;
25473 : : }
25474 : : else
25475 : 0 : gcc_unreachable ();
25476 : :
25477 : :
25478 : : /* Multiply low parts. */
25479 : 434 : t1 = gen_reg_rtx (mode);
25480 : 434 : emit_insn (umul (t1, gen_lowpart (nmode, op1), gen_lowpart (nmode, op2)));
25481 : :
25482 : : /* Shift input vectors right 32 bits so we can multiply high parts. */
25483 : 434 : t6 = GEN_INT (32);
25484 : 434 : t2 = expand_binop (mode, lshr_optab, op1, t6, NULL, 1, OPTAB_DIRECT);
25485 : 434 : t3 = expand_binop (mode, lshr_optab, op2, t6, NULL, 1, OPTAB_DIRECT);
25486 : :
25487 : : /* Multiply high parts by low parts. */
25488 : 434 : t4 = gen_reg_rtx (mode);
25489 : 434 : t5 = gen_reg_rtx (mode);
25490 : 434 : emit_insn (umul (t4, gen_lowpart (nmode, t2), gen_lowpart (nmode, op2)));
25491 : 434 : emit_insn (umul (t5, gen_lowpart (nmode, t3), gen_lowpart (nmode, op1)));
25492 : :
25493 : : /* Combine and shift the highparts back. */
25494 : 434 : t4 = expand_binop (mode, add_optab, t4, t5, t4, 1, OPTAB_DIRECT);
25495 : 434 : t4 = expand_binop (mode, ashl_optab, t4, t6, t4, 1, OPTAB_DIRECT);
25496 : :
25497 : : /* Combine high and low parts. */
25498 : 434 : force_expand_binop (mode, add_optab, t1, t4, op0, 1, OPTAB_DIRECT);
25499 : : }
25500 : :
25501 : 536 : set_unique_reg_note (get_last_insn (), REG_EQUAL,
25502 : : gen_rtx_MULT (mode, op1, op2));
25503 : 536 : }
25504 : :
25505 : : /* Return 1 if control tansfer instruction INSN
25506 : : should be encoded with notrack prefix. */
25507 : :
25508 : : bool
25509 : 14696903 : ix86_notrack_prefixed_insn_p (rtx_insn *insn)
25510 : : {
25511 : 14696903 : if (!insn || !((flag_cf_protection & CF_BRANCH)))
25512 : : return false;
25513 : :
25514 : 4046035 : if (CALL_P (insn))
25515 : : {
25516 : 1421317 : rtx call = get_call_rtx_from (insn);
25517 : 1421317 : gcc_assert (call != NULL_RTX);
25518 : 1421317 : rtx addr = XEXP (call, 0);
25519 : :
25520 : : /* Do not emit 'notrack' if it's not an indirect call. */
25521 : 1421317 : if (MEM_P (addr)
25522 : 1421317 : && GET_CODE (XEXP (addr, 0)) == SYMBOL_REF)
25523 : : return false;
25524 : : else
25525 : 73204 : return find_reg_note (insn, REG_CALL_NOCF_CHECK, 0);
25526 : : }
25527 : :
25528 : 2624718 : if (JUMP_P (insn) && !flag_cet_switch)
25529 : : {
25530 : 2611699 : rtx target = JUMP_LABEL (insn);
25531 : 2611699 : if (target == NULL_RTX || ANY_RETURN_P (target))
25532 : : return false;
25533 : :
25534 : : /* Check the jump is a switch table. */
25535 : 2611661 : rtx_insn *label = as_a<rtx_insn *> (target);
25536 : 2611661 : rtx_insn *table = next_insn (label);
25537 : 2611661 : if (table == NULL_RTX || !JUMP_TABLE_DATA_P (table))
25538 : : return false;
25539 : : else
25540 : : return true;
25541 : : }
25542 : : return false;
25543 : : }
25544 : :
25545 : : /* Calculate integer abs() using only SSE2 instructions. */
25546 : :
25547 : : void
25548 : 512 : ix86_expand_sse2_abs (rtx target, rtx input)
25549 : : {
25550 : 512 : machine_mode mode = GET_MODE (target);
25551 : 512 : rtx tmp0, tmp1, x;
25552 : :
25553 : 512 : switch (mode)
25554 : : {
25555 : 21 : case E_V2DImode:
25556 : 21 : case E_V4DImode:
25557 : : /* For 64-bit signed integer X, with SSE4.2 use
25558 : : pxor t0, t0; pcmpgtq X, t0; pxor t0, X; psubq t0, X.
25559 : : Otherwise handle it similarly to V4SImode, except use 64 as W instead of
25560 : : 32 and use logical instead of arithmetic right shift (which is
25561 : : unimplemented) and subtract. */
25562 : 21 : if (TARGET_SSE4_2)
25563 : : {
25564 : 9 : tmp0 = gen_reg_rtx (mode);
25565 : 9 : tmp1 = gen_reg_rtx (mode);
25566 : 9 : emit_move_insn (tmp1, CONST0_RTX (mode));
25567 : 9 : if (mode == E_V2DImode)
25568 : 6 : emit_insn (gen_sse4_2_gtv2di3 (tmp0, tmp1, input));
25569 : : else
25570 : 3 : emit_insn (gen_avx2_gtv4di3 (tmp0, tmp1, input));
25571 : : }
25572 : : else
25573 : : {
25574 : 24 : tmp0 = expand_simple_binop (mode, LSHIFTRT, input,
25575 : 12 : GEN_INT (GET_MODE_UNIT_BITSIZE (mode)
25576 : : - 1), NULL, 0, OPTAB_DIRECT);
25577 : 12 : tmp0 = expand_simple_unop (mode, NEG, tmp0, NULL, false);
25578 : : }
25579 : :
25580 : 21 : tmp1 = expand_simple_binop (mode, XOR, tmp0, input,
25581 : : NULL, 0, OPTAB_DIRECT);
25582 : 21 : x = expand_simple_binop (mode, MINUS, tmp1, tmp0,
25583 : : target, 0, OPTAB_DIRECT);
25584 : 21 : break;
25585 : :
25586 : 31 : case E_V4SImode:
25587 : : /* For 32-bit signed integer X, the best way to calculate the absolute
25588 : : value of X is (((signed) X >> (W-1)) ^ X) - ((signed) X >> (W-1)). */
25589 : 31 : tmp0 = expand_simple_binop (mode, ASHIFTRT, input,
25590 : 31 : GEN_INT (GET_MODE_UNIT_BITSIZE (mode) - 1),
25591 : : NULL, 0, OPTAB_DIRECT);
25592 : 31 : tmp1 = expand_simple_binop (mode, XOR, tmp0, input,
25593 : : NULL, 0, OPTAB_DIRECT);
25594 : 31 : x = expand_simple_binop (mode, MINUS, tmp1, tmp0,
25595 : : target, 0, OPTAB_DIRECT);
25596 : 31 : break;
25597 : :
25598 : 69 : case E_V8HImode:
25599 : : /* For 16-bit signed integer X, the best way to calculate the absolute
25600 : : value of X is max (X, -X), as SSE2 provides the PMAXSW insn. */
25601 : 69 : tmp0 = expand_unop (mode, neg_optab, input, NULL_RTX, 0);
25602 : :
25603 : 69 : x = expand_simple_binop (mode, SMAX, tmp0, input,
25604 : : target, 0, OPTAB_DIRECT);
25605 : 69 : break;
25606 : :
25607 : 391 : case E_V16QImode:
25608 : : /* For 8-bit signed integer X, the best way to calculate the absolute
25609 : : value of X is min ((unsigned char) X, (unsigned char) (-X)),
25610 : : as SSE2 provides the PMINUB insn. */
25611 : 391 : tmp0 = expand_unop (mode, neg_optab, input, NULL_RTX, 0);
25612 : :
25613 : 391 : x = expand_simple_binop (V16QImode, UMIN, tmp0, input,
25614 : : target, 0, OPTAB_DIRECT);
25615 : 391 : break;
25616 : :
25617 : 0 : default:
25618 : 0 : gcc_unreachable ();
25619 : : }
25620 : :
25621 : 512 : if (x != target)
25622 : 0 : emit_move_insn (target, x);
25623 : 512 : }
25624 : :
25625 : : /* Expand an extract from a vector register through pextr insn.
25626 : : Return true if successful. */
25627 : :
25628 : : bool
25629 : 107619 : ix86_expand_pextr (rtx *operands)
25630 : : {
25631 : 107619 : rtx dst = operands[0];
25632 : 107619 : rtx src = operands[1];
25633 : :
25634 : 107619 : unsigned int size = INTVAL (operands[2]);
25635 : 107619 : unsigned int pos = INTVAL (operands[3]);
25636 : :
25637 : 107619 : if (SUBREG_P (dst))
25638 : : {
25639 : : /* Reject non-lowpart subregs. */
25640 : 64175 : if (SUBREG_BYTE (dst) > 0)
25641 : : return false;
25642 : 64081 : dst = SUBREG_REG (dst);
25643 : : }
25644 : :
25645 : 107525 : if (SUBREG_P (src))
25646 : : {
25647 : 39751 : pos += SUBREG_BYTE (src) * BITS_PER_UNIT;
25648 : 39751 : src = SUBREG_REG (src);
25649 : : }
25650 : :
25651 : 107525 : switch (GET_MODE (src))
25652 : : {
25653 : 0 : case E_V16QImode:
25654 : 0 : case E_V8HImode:
25655 : 0 : case E_V4SImode:
25656 : 0 : case E_V2DImode:
25657 : 0 : case E_V1TImode:
25658 : 0 : {
25659 : 0 : machine_mode srcmode, dstmode;
25660 : 0 : rtx d, pat;
25661 : :
25662 : 0 : if (!int_mode_for_size (size, 0).exists (&dstmode))
25663 : 0 : return false;
25664 : :
25665 : 0 : switch (dstmode)
25666 : : {
25667 : 0 : case E_QImode:
25668 : 0 : if (!TARGET_SSE4_1)
25669 : : return false;
25670 : : srcmode = V16QImode;
25671 : : break;
25672 : :
25673 : 0 : case E_HImode:
25674 : 0 : if (!TARGET_SSE2)
25675 : : return false;
25676 : : srcmode = V8HImode;
25677 : : break;
25678 : :
25679 : 0 : case E_SImode:
25680 : 0 : if (!TARGET_SSE4_1)
25681 : : return false;
25682 : : srcmode = V4SImode;
25683 : : break;
25684 : :
25685 : 0 : case E_DImode:
25686 : 0 : gcc_assert (TARGET_64BIT);
25687 : 0 : if (!TARGET_SSE4_1)
25688 : : return false;
25689 : : srcmode = V2DImode;
25690 : : break;
25691 : :
25692 : : default:
25693 : : return false;
25694 : : }
25695 : :
25696 : : /* Reject extractions from misaligned positions. */
25697 : 0 : if (pos & (size-1))
25698 : : return false;
25699 : :
25700 : 0 : if (GET_MODE (dst) == dstmode)
25701 : : d = dst;
25702 : : else
25703 : 0 : d = gen_reg_rtx (dstmode);
25704 : :
25705 : : /* Construct insn pattern. */
25706 : 0 : pat = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (1, GEN_INT (pos / size)));
25707 : 0 : pat = gen_rtx_VEC_SELECT (dstmode, gen_lowpart (srcmode, src), pat);
25708 : :
25709 : : /* Let the rtl optimizers know about the zero extension performed. */
25710 : 0 : if (dstmode == QImode || dstmode == HImode)
25711 : : {
25712 : 0 : pat = gen_rtx_ZERO_EXTEND (SImode, pat);
25713 : 0 : d = gen_lowpart (SImode, d);
25714 : : }
25715 : :
25716 : 0 : emit_insn (gen_rtx_SET (d, pat));
25717 : :
25718 : 0 : if (d != dst)
25719 : 0 : emit_move_insn (dst, gen_lowpart (GET_MODE (dst), d));
25720 : : return true;
25721 : : }
25722 : :
25723 : : default:
25724 : : return false;
25725 : : }
25726 : : }
25727 : :
25728 : : /* Expand an insert into a vector register through pinsr insn.
25729 : : Return true if successful. */
25730 : :
25731 : : bool
25732 : 107072 : ix86_expand_pinsr (rtx *operands)
25733 : : {
25734 : 107072 : rtx dst = operands[0];
25735 : 107072 : rtx src = operands[3];
25736 : :
25737 : 107072 : unsigned int size = INTVAL (operands[1]);
25738 : 107072 : unsigned int pos = INTVAL (operands[2]);
25739 : :
25740 : 107072 : if (SUBREG_P (dst))
25741 : : {
25742 : 58347 : pos += SUBREG_BYTE (dst) * BITS_PER_UNIT;
25743 : 58347 : dst = SUBREG_REG (dst);
25744 : : }
25745 : :
25746 : 107072 : switch (GET_MODE (dst))
25747 : : {
25748 : 21 : case E_V16QImode:
25749 : 21 : case E_V8HImode:
25750 : 21 : case E_V4SImode:
25751 : 21 : case E_V2DImode:
25752 : 21 : case E_V1TImode:
25753 : 21 : {
25754 : 21 : machine_mode srcmode, dstmode;
25755 : 21 : rtx (*pinsr)(rtx, rtx, rtx, rtx);
25756 : 21 : rtx d;
25757 : :
25758 : 21 : if (!int_mode_for_size (size, 0).exists (&srcmode))
25759 : 0 : return false;
25760 : :
25761 : 21 : switch (srcmode)
25762 : : {
25763 : 1 : case E_QImode:
25764 : 1 : if (!TARGET_SSE4_1)
25765 : : return false;
25766 : : dstmode = V16QImode;
25767 : : pinsr = gen_sse4_1_pinsrb;
25768 : : break;
25769 : :
25770 : 5 : case E_HImode:
25771 : 5 : if (!TARGET_SSE2)
25772 : : return false;
25773 : : dstmode = V8HImode;
25774 : : pinsr = gen_sse2_pinsrw;
25775 : : break;
25776 : :
25777 : 15 : case E_SImode:
25778 : 15 : if (!TARGET_SSE4_1)
25779 : : return false;
25780 : : dstmode = V4SImode;
25781 : : pinsr = gen_sse4_1_pinsrd;
25782 : : break;
25783 : :
25784 : 0 : case E_DImode:
25785 : 0 : gcc_assert (TARGET_64BIT);
25786 : 0 : if (!TARGET_SSE4_1)
25787 : : return false;
25788 : : dstmode = V2DImode;
25789 : : pinsr = gen_sse4_1_pinsrq;
25790 : : break;
25791 : :
25792 : : default:
25793 : : return false;
25794 : : }
25795 : :
25796 : : /* Reject insertions to misaligned positions. */
25797 : 8 : if (pos & (size-1))
25798 : : return false;
25799 : :
25800 : 8 : if (SUBREG_P (src))
25801 : : {
25802 : 8 : unsigned int srcpos = SUBREG_BYTE (src);
25803 : :
25804 : 8 : if (srcpos > 0)
25805 : : {
25806 : 0 : rtx extr_ops[4];
25807 : :
25808 : 0 : extr_ops[0] = gen_reg_rtx (srcmode);
25809 : 0 : extr_ops[1] = gen_lowpart (srcmode, SUBREG_REG (src));
25810 : 0 : extr_ops[2] = GEN_INT (size);
25811 : 0 : extr_ops[3] = GEN_INT (srcpos * BITS_PER_UNIT);
25812 : :
25813 : 0 : if (!ix86_expand_pextr (extr_ops))
25814 : 0 : return false;
25815 : :
25816 : 0 : src = extr_ops[0];
25817 : : }
25818 : : else
25819 : 8 : src = gen_lowpart (srcmode, SUBREG_REG (src));
25820 : : }
25821 : :
25822 : 8 : if (GET_MODE (dst) == dstmode)
25823 : : d = dst;
25824 : : else
25825 : 8 : d = gen_reg_rtx (dstmode);
25826 : :
25827 : 8 : emit_insn (pinsr (d, gen_lowpart (dstmode, dst),
25828 : 8 : gen_lowpart (srcmode, src),
25829 : 8 : GEN_INT (1 << (pos / size))));
25830 : 8 : if (d != dst)
25831 : 8 : emit_move_insn (dst, gen_lowpart (GET_MODE (dst), d));
25832 : : return true;
25833 : : }
25834 : :
25835 : : default:
25836 : : return false;
25837 : : }
25838 : : }
25839 : :
25840 : : /* All CPUs prefer to avoid cross-lane operations so perform reductions
25841 : : upper against lower halves up to SSE reg size. */
25842 : :
25843 : : machine_mode
25844 : 1725 : ix86_split_reduction (machine_mode mode)
25845 : : {
25846 : : /* Reduce lowpart against highpart until we reach SSE reg width to
25847 : : avoid cross-lane operations. */
25848 : 1725 : switch (mode)
25849 : : {
25850 : : case E_V8DImode:
25851 : : case E_V4DImode:
25852 : : return V2DImode;
25853 : 7 : case E_V16SImode:
25854 : 7 : case E_V8SImode:
25855 : 7 : return V4SImode;
25856 : 6 : case E_V32HImode:
25857 : 6 : case E_V16HImode:
25858 : 6 : return V8HImode;
25859 : 4 : case E_V64QImode:
25860 : 4 : case E_V32QImode:
25861 : 4 : return V16QImode;
25862 : 5 : case E_V16SFmode:
25863 : 5 : case E_V8SFmode:
25864 : 5 : return V4SFmode;
25865 : 14 : case E_V8DFmode:
25866 : 14 : case E_V4DFmode:
25867 : 14 : return V2DFmode;
25868 : 1687 : default:
25869 : 1687 : return mode;
25870 : : }
25871 : : }
25872 : :
25873 : : /* Generate call to __divmoddi4. */
25874 : :
25875 : : void
25876 : 904 : ix86_expand_divmod_libfunc (rtx libfunc, machine_mode mode,
25877 : : rtx op0, rtx op1,
25878 : : rtx *quot_p, rtx *rem_p)
25879 : : {
25880 : 1808 : rtx rem = assign_stack_temp (mode, GET_MODE_SIZE (mode));
25881 : :
25882 : 904 : rtx quot = emit_library_call_value (libfunc, NULL_RTX, LCT_NORMAL,
25883 : : mode, op0, mode, op1, mode,
25884 : 904 : XEXP (rem, 0), Pmode);
25885 : 904 : *quot_p = quot;
25886 : 904 : *rem_p = rem;
25887 : 904 : }
25888 : :
25889 : : void
25890 : 64 : ix86_expand_atomic_fetch_op_loop (rtx target, rtx mem, rtx val,
25891 : : enum rtx_code code, bool after,
25892 : : bool doubleword)
25893 : : {
25894 : 64 : rtx old_reg, new_reg, old_mem, success;
25895 : 64 : machine_mode mode = GET_MODE (target);
25896 : 64 : rtx_code_label *loop_label = NULL;
25897 : :
25898 : 64 : old_reg = gen_reg_rtx (mode);
25899 : 64 : new_reg = old_reg;
25900 : 64 : old_mem = copy_to_reg (mem);
25901 : 64 : loop_label = gen_label_rtx ();
25902 : 64 : emit_label (loop_label);
25903 : 64 : emit_move_insn (old_reg, old_mem);
25904 : :
25905 : : /* return value for atomic_fetch_op. */
25906 : 64 : if (!after)
25907 : 32 : emit_move_insn (target, old_reg);
25908 : :
25909 : 64 : if (code == NOT)
25910 : : {
25911 : 16 : new_reg = expand_simple_binop (mode, AND, new_reg, val, NULL_RTX,
25912 : : true, OPTAB_LIB_WIDEN);
25913 : 16 : new_reg = expand_simple_unop (mode, code, new_reg, NULL_RTX, true);
25914 : : }
25915 : : else
25916 : 48 : new_reg = expand_simple_binop (mode, code, new_reg, val, NULL_RTX,
25917 : : true, OPTAB_LIB_WIDEN);
25918 : :
25919 : : /* return value for atomic_op_fetch. */
25920 : 64 : if (after)
25921 : 32 : emit_move_insn (target, new_reg);
25922 : :
25923 : 64 : success = NULL_RTX;
25924 : :
25925 : 64 : ix86_expand_cmpxchg_loop (&success, old_mem, mem, old_reg, new_reg,
25926 : : gen_int_mode (MEMMODEL_SYNC_SEQ_CST,
25927 : : SImode),
25928 : : doubleword, loop_label);
25929 : 64 : }
25930 : :
25931 : : /* Relax cmpxchg instruction, param loop_label indicates whether
25932 : : the instruction should be relaxed with a pause loop. If not,
25933 : : it will be relaxed to an atomic load + compare, and skip
25934 : : cmpxchg instruction if mem != exp_input. */
25935 : :
25936 : : void
25937 : 72 : ix86_expand_cmpxchg_loop (rtx *ptarget_bool, rtx target_val,
25938 : : rtx mem, rtx exp_input, rtx new_input,
25939 : : rtx mem_model, bool doubleword,
25940 : : rtx_code_label *loop_label)
25941 : : {
25942 : 72 : rtx_code_label *cmp_label = NULL;
25943 : 72 : rtx_code_label *done_label = NULL;
25944 : 72 : rtx target_bool = NULL_RTX, new_mem = NULL_RTX;
25945 : 72 : rtx (*gen) (rtx, rtx, rtx, rtx, rtx) = NULL;
25946 : 72 : rtx (*gendw) (rtx, rtx, rtx, rtx, rtx, rtx) = NULL;
25947 : 72 : machine_mode mode = GET_MODE (target_val), hmode = mode;
25948 : :
25949 : 72 : if (*ptarget_bool == NULL)
25950 : 64 : target_bool = gen_reg_rtx (QImode);
25951 : : else
25952 : : target_bool = *ptarget_bool;
25953 : :
25954 : 72 : cmp_label = gen_label_rtx ();
25955 : 72 : done_label = gen_label_rtx ();
25956 : :
25957 : 72 : new_mem = gen_reg_rtx (mode);
25958 : : /* Load memory first. */
25959 : 72 : expand_atomic_load (new_mem, mem, MEMMODEL_SEQ_CST);
25960 : :
25961 : 72 : switch (mode)
25962 : : {
25963 : : case E_TImode:
25964 : : gendw = gen_atomic_compare_and_swapti_doubleword;
25965 : : hmode = DImode;
25966 : : break;
25967 : 18 : case E_DImode:
25968 : 18 : if (doubleword)
25969 : : {
25970 : : gendw = gen_atomic_compare_and_swapdi_doubleword;
25971 : : hmode = SImode;
25972 : : }
25973 : : else
25974 : : gen = gen_atomic_compare_and_swapdi_1;
25975 : : break;
25976 : 18 : case E_SImode:
25977 : 18 : gen = gen_atomic_compare_and_swapsi_1;
25978 : 18 : break;
25979 : 18 : case E_HImode:
25980 : 18 : gen = gen_atomic_compare_and_swaphi_1;
25981 : 18 : break;
25982 : 18 : case E_QImode:
25983 : 18 : gen = gen_atomic_compare_and_swapqi_1;
25984 : 18 : break;
25985 : 0 : default:
25986 : 0 : gcc_unreachable ();
25987 : : }
25988 : :
25989 : : /* Compare mem value with expected value. */
25990 : 54 : if (doubleword)
25991 : : {
25992 : 0 : rtx low_new_mem = gen_lowpart (hmode, new_mem);
25993 : 0 : rtx low_exp_input = gen_lowpart (hmode, exp_input);
25994 : 0 : rtx high_new_mem = gen_highpart (hmode, new_mem);
25995 : 0 : rtx high_exp_input = gen_highpart (hmode, exp_input);
25996 : 0 : emit_cmp_and_jump_insns (low_new_mem, low_exp_input, NE, NULL_RTX,
25997 : : hmode, 1, cmp_label,
25998 : : profile_probability::guessed_never ());
25999 : 0 : emit_cmp_and_jump_insns (high_new_mem, high_exp_input, NE, NULL_RTX,
26000 : : hmode, 1, cmp_label,
26001 : : profile_probability::guessed_never ());
26002 : : }
26003 : : else
26004 : 72 : emit_cmp_and_jump_insns (new_mem, exp_input, NE, NULL_RTX,
26005 : 72 : GET_MODE (exp_input), 1, cmp_label,
26006 : : profile_probability::guessed_never ());
26007 : :
26008 : : /* Directly emits cmpxchg here. */
26009 : 72 : if (doubleword)
26010 : 0 : emit_insn (gendw (target_val, mem, exp_input,
26011 : 0 : gen_lowpart (hmode, new_input),
26012 : : gen_highpart (hmode, new_input),
26013 : : mem_model));
26014 : : else
26015 : 72 : emit_insn (gen (target_val, mem, exp_input, new_input, mem_model));
26016 : :
26017 : 72 : if (!loop_label)
26018 : : {
26019 : 8 : emit_jump_insn (gen_jump (done_label));
26020 : 8 : emit_barrier ();
26021 : 8 : emit_label (cmp_label);
26022 : 8 : emit_move_insn (target_val, new_mem);
26023 : 8 : emit_label (done_label);
26024 : 8 : ix86_expand_setcc (target_bool, EQ, gen_rtx_REG (CCZmode, FLAGS_REG),
26025 : : const0_rtx);
26026 : : }
26027 : : else
26028 : : {
26029 : 64 : ix86_expand_setcc (target_bool, EQ, gen_rtx_REG (CCZmode, FLAGS_REG),
26030 : : const0_rtx);
26031 : 64 : emit_cmp_and_jump_insns (target_bool, const0_rtx, EQ, const0_rtx,
26032 : 64 : GET_MODE (target_bool), 1, loop_label,
26033 : : profile_probability::guessed_never ());
26034 : 64 : emit_jump_insn (gen_jump (done_label));
26035 : 64 : emit_barrier ();
26036 : :
26037 : : /* If mem is not expected, pause and loop back. */
26038 : 64 : emit_label (cmp_label);
26039 : 64 : emit_move_insn (target_val, new_mem);
26040 : 64 : emit_insn (gen_pause ());
26041 : 64 : emit_jump_insn (gen_jump (loop_label));
26042 : 64 : emit_barrier ();
26043 : 64 : emit_label (done_label);
26044 : : }
26045 : :
26046 : 72 : *ptarget_bool = target_bool;
26047 : 72 : }
26048 : :
26049 : : /* Convert a BFmode VAL to SFmode without signaling sNaNs.
26050 : : This is done by returning SF SUBREG of ((HI SUBREG) (VAL)) << 16. */
26051 : :
26052 : : rtx
26053 : 1910 : ix86_expand_fast_convert_bf_to_sf (rtx val)
26054 : : {
26055 : 1910 : rtx op = gen_lowpart (HImode, val), ret;
26056 : 1910 : if (CONST_INT_P (op))
26057 : : {
26058 : 378 : ret = simplify_const_unary_operation (FLOAT_EXTEND, SFmode,
26059 : : val, BFmode);
26060 : 378 : if (ret)
26061 : : return ret;
26062 : : /* FLOAT_EXTEND simplification will fail if VAL is a sNaN. */
26063 : 1 : ret = gen_reg_rtx (SImode);
26064 : 1 : emit_move_insn (ret, GEN_INT (INTVAL (op) & 0xffff));
26065 : 1 : emit_insn (gen_ashlsi3 (ret, ret, GEN_INT (16)));
26066 : 1 : return gen_lowpart (SFmode, ret);
26067 : : }
26068 : :
26069 : 1532 : ret = gen_reg_rtx (SFmode);
26070 : 1532 : emit_insn (gen_extendbfsf2_1 (ret, force_reg (BFmode, val)));
26071 : 1532 : return ret;
26072 : : }
26073 : :
26074 : : rtx
26075 : 36 : ix86_gen_ccmp_first (rtx_insn **prep_seq, rtx_insn **gen_seq,
26076 : : rtx_code code, tree treeop0, tree treeop1)
26077 : : {
26078 : 36 : if (!TARGET_APX_CCMP)
26079 : : return NULL_RTX;
26080 : :
26081 : 36 : rtx op0, op1, res;
26082 : 36 : machine_mode op_mode;
26083 : :
26084 : 36 : start_sequence ();
26085 : 36 : expand_operands (treeop0, treeop1, NULL_RTX, &op0, &op1, EXPAND_NORMAL);
26086 : :
26087 : 36 : op_mode = GET_MODE (op0);
26088 : 36 : if (op_mode == VOIDmode)
26089 : 0 : op_mode = GET_MODE (op1);
26090 : :
26091 : : /* We only supports following scalar comparisons that use just 1
26092 : : instruction: DI/SI/QI/HI/DF/SF/HF.
26093 : : Unordered/Ordered compare cannot be corretly indentified by
26094 : : ccmp so they are not supported. */
26095 : 38 : if (!(op_mode == DImode || op_mode == SImode || op_mode == HImode
26096 : 36 : || op_mode == QImode || op_mode == DFmode || op_mode == SFmode
26097 : 2 : || op_mode == HFmode)
26098 : 36 : || code == ORDERED
26099 : 36 : || code == UNORDERED)
26100 : : {
26101 : 0 : end_sequence ();
26102 : 0 : return NULL_RTX;
26103 : : }
26104 : :
26105 : : /* Canonicalize the operands according to mode. */
26106 : 36 : if (SCALAR_INT_MODE_P (op_mode))
26107 : : {
26108 : 29 : if (!nonimmediate_operand (op0, op_mode))
26109 : 0 : op0 = force_reg (op_mode, op0);
26110 : 29 : if (!x86_64_general_operand (op1, op_mode))
26111 : 0 : op1 = force_reg (op_mode, op1);
26112 : : }
26113 : : else
26114 : : {
26115 : : /* op0/op1 can be canonicallized from expand_fp_compare, so
26116 : : just adjust the code to make it generate supported fp
26117 : : condition. */
26118 : 7 : if (ix86_fp_compare_code_to_integer (code) == UNKNOWN)
26119 : : {
26120 : : /* First try to split condition if we don't need to honor
26121 : : NaNs, as the ORDERED/UNORDERED check always fall
26122 : : through. */
26123 : 6 : if (!HONOR_NANS (op_mode))
26124 : : {
26125 : 6 : rtx_code first_code;
26126 : 6 : split_comparison (code, op_mode, &first_code, &code);
26127 : : }
26128 : : /* Otherwise try to swap the operand order and check if
26129 : : the comparison is supported. */
26130 : : else
26131 : : {
26132 : 0 : code = swap_condition (code);
26133 : 0 : std::swap (op0, op1);
26134 : : }
26135 : :
26136 : 6 : if (ix86_fp_compare_code_to_integer (code) == UNKNOWN)
26137 : : {
26138 : 0 : end_sequence ();
26139 : 0 : return NULL_RTX;
26140 : : }
26141 : : }
26142 : : }
26143 : :
26144 : 36 : *prep_seq = end_sequence ();
26145 : :
26146 : 36 : start_sequence ();
26147 : :
26148 : 36 : res = ix86_expand_compare (code, op0, op1);
26149 : :
26150 : 36 : if (!res)
26151 : : {
26152 : : end_sequence ();
26153 : : return NULL_RTX;
26154 : : }
26155 : 36 : *gen_seq = end_sequence ();
26156 : :
26157 : 36 : return res;
26158 : : }
26159 : :
26160 : : rtx
26161 : 39 : ix86_gen_ccmp_next (rtx_insn **prep_seq, rtx_insn **gen_seq, rtx prev,
26162 : : rtx_code cmp_code, tree treeop0, tree treeop1,
26163 : : rtx_code bit_code)
26164 : : {
26165 : 39 : if (!TARGET_APX_CCMP)
26166 : : return NULL_RTX;
26167 : :
26168 : 39 : rtx op0, op1, target;
26169 : 39 : machine_mode op_mode, cmp_mode, cc_mode = CCmode;
26170 : 39 : int unsignedp = TYPE_UNSIGNED (TREE_TYPE (treeop0));
26171 : 39 : insn_code icode;
26172 : 39 : rtx_code prev_code;
26173 : 39 : struct expand_operand ops[5];
26174 : 39 : int dfv;
26175 : :
26176 : 39 : push_to_sequence (*prep_seq);
26177 : 39 : expand_operands (treeop0, treeop1, NULL_RTX, &op0, &op1, EXPAND_NORMAL);
26178 : :
26179 : 39 : cmp_mode = op_mode = GET_MODE (op0);
26180 : :
26181 : 39 : if (!(op_mode == DImode || op_mode == SImode || op_mode == HImode
26182 : : || op_mode == QImode))
26183 : : {
26184 : 7 : end_sequence ();
26185 : 7 : return NULL_RTX;
26186 : : }
26187 : :
26188 : 32 : icode = code_for_ccmp (op_mode);
26189 : :
26190 : 32 : op0 = prepare_operand (icode, op0, 2, op_mode, cmp_mode, unsignedp);
26191 : 32 : op1 = prepare_operand (icode, op1, 3, op_mode, cmp_mode, unsignedp);
26192 : 32 : if (!op0 || !op1)
26193 : : {
26194 : 0 : end_sequence ();
26195 : 0 : return NULL_RTX;
26196 : : }
26197 : :
26198 : 32 : *prep_seq = end_sequence ();
26199 : :
26200 : 32 : target = gen_rtx_REG (cc_mode, FLAGS_REG);
26201 : 32 : dfv = ix86_get_flags_cc ((rtx_code) cmp_code);
26202 : :
26203 : 32 : prev_code = GET_CODE (prev);
26204 : : /* Fixup FP compare code here. */
26205 : 32 : if (GET_MODE (XEXP (prev, 0)) == CCFPmode)
26206 : 7 : prev_code = ix86_fp_compare_code_to_integer (prev_code);
26207 : :
26208 : 32 : if (bit_code != AND)
26209 : 17 : prev_code = reverse_condition (prev_code);
26210 : : else
26211 : 15 : dfv = (int)(dfv ^ 1);
26212 : :
26213 : 32 : prev = gen_rtx_fmt_ee (prev_code, VOIDmode, XEXP (prev, 0),
26214 : : const0_rtx);
26215 : :
26216 : 32 : create_fixed_operand (&ops[0], target);
26217 : 32 : create_fixed_operand (&ops[1], prev);
26218 : 32 : create_fixed_operand (&ops[2], op0);
26219 : 32 : create_fixed_operand (&ops[3], op1);
26220 : 32 : create_fixed_operand (&ops[4], GEN_INT (dfv));
26221 : :
26222 : 32 : push_to_sequence (*gen_seq);
26223 : 32 : if (!maybe_expand_insn (icode, 5, ops))
26224 : : {
26225 : 0 : end_sequence ();
26226 : 0 : return NULL_RTX;
26227 : : }
26228 : :
26229 : 32 : *gen_seq = end_sequence ();
26230 : :
26231 : 32 : return gen_rtx_fmt_ee ((rtx_code) cmp_code, VOIDmode, target, const0_rtx);
26232 : : }
26233 : :
26234 : : /* Attempt to convert a CONST_VECTOR into a bcst_mem_operand.
26235 : : Returns NULL_RTX if X is cannot be expressed as a suitable
26236 : : VEC_DUPLICATE in mode MODE. */
26237 : :
26238 : : static rtx
26239 : 49 : ix86_gen_bcst_mem (machine_mode mode, rtx x)
26240 : : {
26241 : 49 : if (!TARGET_AVX512F
26242 : 49 : || !CONST_VECTOR_P (x)
26243 : 65 : || (!TARGET_AVX512VL && GET_MODE_SIZE (mode) != 64)
26244 : 152 : || !VALID_BCST_MODE_P (GET_MODE_INNER (mode))
26245 : : /* Disallow HFmode broadcast. */
26246 : 129 : || GET_MODE_SIZE (GET_MODE_INNER (mode)) < 4)
26247 : : return NULL_RTX;
26248 : :
26249 : 21 : rtx cst = CONST_VECTOR_ELT (x, 0);
26250 : 21 : if (!CONST_SCALAR_INT_P (cst)
26251 : 15 : && !CONST_DOUBLE_P (cst)
26252 : 0 : && !CONST_FIXED_P (cst))
26253 : : return NULL_RTX;
26254 : :
26255 : 21 : int n_elts = GET_MODE_NUNITS (mode);
26256 : 42 : if (CONST_VECTOR_NUNITS (x) != n_elts)
26257 : : return NULL_RTX;
26258 : :
26259 : 150 : for (int i = 1; i < n_elts; i++)
26260 : 129 : if (!rtx_equal_p (cst, CONST_VECTOR_ELT (x, i)))
26261 : : return NULL_RTX;
26262 : :
26263 : 42 : rtx mem = force_const_mem (GET_MODE_INNER (mode), cst);
26264 : 21 : return gen_rtx_VEC_DUPLICATE (mode, validize_mem (mem));
26265 : : }
26266 : :
26267 : : /* Determine the ternlog immediate index that implements 3-operand
26268 : : ternary logic expression OP. This uses and modifies the 3 element
26269 : : array ARGS to record and check the leaves, either 3 REGs, or 2 REGs
26270 : : and MEM. Returns an index between 0 and 255 for a valid ternlog,
26271 : : or -1 if the expression isn't suitable. */
26272 : :
26273 : : int
26274 : 6024499 : ix86_ternlog_idx (rtx op, rtx *args)
26275 : : {
26276 : 6024499 : int idx0, idx1;
26277 : :
26278 : 6024499 : if (!op)
26279 : : return -1;
26280 : :
26281 : 6024499 : switch (GET_CODE (op))
26282 : : {
26283 : 644876 : case SUBREG:
26284 : 644876 : if (!register_operand (op, GET_MODE (op)))
26285 : : return -1;
26286 : : /* FALLTHRU */
26287 : :
26288 : 3006664 : case REG:
26289 : 3006664 : if (!args[0])
26290 : : {
26291 : 1520306 : args[0] = op;
26292 : 1520306 : return 0xf0;
26293 : : }
26294 : 1486358 : if (rtx_equal_p (op, args[0]))
26295 : : return 0xf0;
26296 : 1460328 : if (!args[1])
26297 : : {
26298 : 1256333 : args[1] = op;
26299 : 1256333 : return 0xcc;
26300 : : }
26301 : 203995 : if (rtx_equal_p (op, args[1]))
26302 : : return 0xcc;
26303 : 187595 : if (!args[2])
26304 : : {
26305 : 176704 : args[2] = op;
26306 : 176704 : return 0xaa;
26307 : : }
26308 : 10891 : if (rtx_equal_p (op, args[2]))
26309 : : return 0xaa;
26310 : : return -1;
26311 : :
26312 : 15178 : case VEC_DUPLICATE:
26313 : 15178 : if (!bcst_mem_operand (op, GET_MODE (op)))
26314 : : return -1;
26315 : 302 : goto do_mem_operand;
26316 : :
26317 : 205931 : case MEM:
26318 : 205931 : if (!memory_operand (op, GET_MODE (op)))
26319 : : return -1;
26320 : 205716 : if (MEM_P (op)
26321 : 205716 : && MEM_VOLATILE_P (op)
26322 : 205716 : && !volatile_ok)
26323 : : return -1;
26324 : : /* FALLTHRU */
26325 : :
26326 : 266767 : case CONST_VECTOR:
26327 : 266767 : do_mem_operand:
26328 : 266767 : if (!args[2])
26329 : : {
26330 : 248326 : args[2] = op;
26331 : 248326 : return 0xaa;
26332 : : }
26333 : : /* Maximum of one volatile memory reference per expression. */
26334 : 18441 : if (side_effects_p (op))
26335 : : return -1;
26336 : 18441 : if (rtx_equal_p (op, args[2]))
26337 : : return 0xaa;
26338 : : /* Check if CONST_VECTOR is the ones-complement of args[2]. */
26339 : 18410 : if (GET_CODE (op) == CONST_VECTOR
26340 : 2069 : && GET_CODE (args[2]) == CONST_VECTOR
26341 : 18791 : && rtx_equal_p (simplify_const_unary_operation (NOT, GET_MODE (op),
26342 : 381 : op, GET_MODE (op)),
26343 : : args[2]))
26344 : : return 0x55;
26345 : 18297 : if (!args[0])
26346 : : {
26347 : 16311 : args[0] = op;
26348 : 16311 : return 0xf0;
26349 : : }
26350 : 1986 : if (rtx_equal_p (op, args[0]))
26351 : : return 0xf0;
26352 : : /* Check if CONST_VECTOR is the ones-complement of args[0]. */
26353 : 1986 : if (GET_CODE (op) == CONST_VECTOR
26354 : 338 : && GET_CODE (args[0]) == CONST_VECTOR
26355 : 2028 : && rtx_equal_p (simplify_const_unary_operation (NOT, GET_MODE (op),
26356 : 42 : op, GET_MODE (op)),
26357 : : args[0]))
26358 : : return 0x0f;
26359 : 1944 : if (!args[1])
26360 : : {
26361 : 1932 : args[1] = op;
26362 : 1932 : return 0xcc;
26363 : : }
26364 : 12 : if (rtx_equal_p (op, args[1]))
26365 : : return 0xcc;
26366 : : /* Check if CONST_VECTOR is the ones-complement of args[1]. */
26367 : 12 : if (GET_CODE (op) == CONST_VECTOR
26368 : 0 : && GET_CODE (args[1]) == CONST_VECTOR
26369 : 12 : && rtx_equal_p (simplify_const_unary_operation (NOT, GET_MODE (op),
26370 : 0 : op, GET_MODE (op)),
26371 : : args[1]))
26372 : : return 0x33;
26373 : : return -1;
26374 : :
26375 : 177552 : case NOT:
26376 : 177552 : idx0 = ix86_ternlog_idx (XEXP (op, 0), args);
26377 : 177552 : return (idx0 >= 0) ? idx0 ^ 0xff : -1;
26378 : :
26379 : 1059277 : case AND:
26380 : 1059277 : idx0 = ix86_ternlog_idx (XEXP (op, 0), args);
26381 : 1059277 : if (idx0 < 0)
26382 : : return -1;
26383 : 849531 : idx1 = ix86_ternlog_idx (XEXP (op, 1), args);
26384 : 849531 : return (idx1 >= 0) ? idx0 & idx1 : -1;
26385 : :
26386 : 891031 : case IOR:
26387 : 891031 : idx0 = ix86_ternlog_idx (XEXP (op, 0), args);
26388 : 891031 : if (idx0 < 0)
26389 : : return -1;
26390 : 656799 : idx1 = ix86_ternlog_idx (XEXP (op, 1), args);
26391 : 656799 : return (idx1 >= 0) ? idx0 | idx1 : -1;
26392 : :
26393 : 257533 : case XOR:
26394 : 257533 : idx0 = ix86_ternlog_idx (XEXP (op, 0), args);
26395 : 257533 : if (idx0 < 0)
26396 : : return -1;
26397 : 242064 : if (vector_all_ones_operand (XEXP (op, 1), GET_MODE (op)))
26398 : 6109 : return idx0 ^ 0xff;
26399 : 235955 : idx1 = ix86_ternlog_idx (XEXP (op, 1), args);
26400 : 235955 : return (idx1 >= 0) ? idx0 ^ idx1 : -1;
26401 : :
26402 : 6637 : case UNSPEC:
26403 : 6637 : if (XINT (op, 1) != UNSPEC_VTERNLOG
26404 : 0 : || XVECLEN (op, 0) != 4
26405 : 0 : || !CONST_INT_P (XVECEXP (op, 0, 3)))
26406 : : return -1;
26407 : :
26408 : : /* TODO: Handle permuted operands. */
26409 : 0 : if (ix86_ternlog_idx (XVECEXP (op, 0, 0), args) != 0xf0
26410 : 0 : || ix86_ternlog_idx (XVECEXP (op, 0, 1), args) != 0xcc
26411 : 0 : || ix86_ternlog_idx (XVECEXP (op, 0, 2), args) != 0xaa)
26412 : 0 : return -1;
26413 : 0 : return INTVAL (XVECEXP (op, 0, 3));
26414 : :
26415 : : default:
26416 : : return -1;
26417 : : }
26418 : : }
26419 : :
26420 : : /* Return TRUE if OP (in mode MODE) is the leaf of a ternary logic
26421 : : expression, such as a register or a memory reference. */
26422 : :
26423 : : bool
26424 : 2746106 : ix86_ternlog_leaf_p (rtx op, machine_mode mode)
26425 : : {
26426 : : /* We can't use memory_operand here, as it may return a different
26427 : : value before and after reload (for volatile MEMs) which creates
26428 : : problems splitting instructions. */
26429 : 2746106 : return register_operand (op, mode)
26430 : 492328 : || MEM_P (op)
26431 : 300171 : || CONST_VECTOR_P (op)
26432 : 2992210 : || bcst_mem_operand (op, mode);
26433 : : }
26434 : :
26435 : : /* Test whether OP is a 3-operand ternary logic expression suitable
26436 : : for use in a ternlog instruction. */
26437 : :
26438 : : bool
26439 : 1861839 : ix86_ternlog_operand_p (rtx op)
26440 : : {
26441 : 1861839 : rtx op0, op1;
26442 : 1861839 : rtx args[3];
26443 : :
26444 : 1861839 : args[0] = NULL_RTX;
26445 : 1861839 : args[1] = NULL_RTX;
26446 : 1861839 : args[2] = NULL_RTX;
26447 : 1861839 : int idx = ix86_ternlog_idx (op, args);
26448 : 1861839 : if (idx < 0)
26449 : : return false;
26450 : :
26451 : : /* Don't match simple (binary or unary) expressions. */
26452 : 1486722 : machine_mode mode = GET_MODE (op);
26453 : 1486722 : switch (GET_CODE (op))
26454 : : {
26455 : 684052 : case AND:
26456 : 684052 : op0 = XEXP (op, 0);
26457 : 684052 : op1 = XEXP (op, 1);
26458 : :
26459 : : /* Prefer pand. */
26460 : 684052 : if (ix86_ternlog_leaf_p (op0, mode)
26461 : 684052 : && ix86_ternlog_leaf_p (op1, mode))
26462 : : return false;
26463 : : /* Prefer pandn. */
26464 : 109194 : if (GET_CODE (op0) == NOT
26465 : 79490 : && register_operand (XEXP (op0, 0), mode)
26466 : 185008 : && ix86_ternlog_leaf_p (op1, mode))
26467 : : return false;
26468 : : break;
26469 : :
26470 : 586024 : case IOR:
26471 : : /* Prefer por. */
26472 : 586024 : if (ix86_ternlog_leaf_p (XEXP (op, 0), mode)
26473 : 586024 : && ix86_ternlog_leaf_p (XEXP (op, 1), mode))
26474 : : return false;
26475 : : break;
26476 : :
26477 : 187290 : case XOR:
26478 : 187290 : op1 = XEXP (op, 1);
26479 : : /* Prefer pxor, or one_cmpl<vmode>2. */
26480 : 187290 : if (ix86_ternlog_leaf_p (XEXP (op, 0), mode)
26481 : 187290 : && ix86_ternlog_leaf_p (XEXP (op, 1), mode))
26482 : : return false;
26483 : : break;
26484 : :
26485 : : default:
26486 : : break;
26487 : : }
26488 : : return true;
26489 : : }
26490 : :
26491 : : /* Helper function for ix86_expand_ternlog. */
26492 : : static rtx
26493 : 0 : ix86_expand_ternlog_binop (enum rtx_code code, machine_mode mode,
26494 : : rtx op0, rtx op1, rtx target)
26495 : : {
26496 : 0 : if (GET_MODE (op0) != mode)
26497 : 0 : op0 = gen_lowpart (mode, op0);
26498 : 0 : if (GET_MODE (op1) != mode)
26499 : 0 : op1 = gen_lowpart (mode, op1);
26500 : :
26501 : 0 : if (CONST_VECTOR_P (op0))
26502 : 0 : op0 = validize_mem (force_const_mem (mode, op0));
26503 : 0 : if (CONST_VECTOR_P (op1))
26504 : 0 : op1 = validize_mem (force_const_mem (mode, op1));
26505 : :
26506 : 0 : if (!register_operand (op0, mode))
26507 : : {
26508 : 0 : if (!register_operand (op1, mode))
26509 : : {
26510 : : /* We can't use force_reg (op0, mode). */
26511 : 0 : rtx reg = gen_reg_rtx (mode);
26512 : 0 : emit_move_insn (reg, op0);
26513 : 0 : op0 = reg;
26514 : : }
26515 : : else
26516 : : std::swap (op0, op1);
26517 : : }
26518 : 0 : rtx ops[3] = { target, op0, op1 };
26519 : 0 : ix86_expand_vector_logical_operator (code, mode, ops);
26520 : 0 : return target;
26521 : : }
26522 : :
26523 : :
26524 : : /* Helper function for ix86_expand_ternlog. */
26525 : : static rtx
26526 : 0 : ix86_expand_ternlog_andnot (machine_mode mode, rtx op0, rtx op1, rtx target)
26527 : : {
26528 : 0 : if (GET_MODE (op0) != mode)
26529 : 0 : op0 = gen_lowpart (mode, op0);
26530 : 0 : op0 = gen_rtx_NOT (mode, op0);
26531 : 0 : if (GET_MODE (op1) != mode)
26532 : 0 : op1 = gen_lowpart (mode, op1);
26533 : 0 : if (CONST_VECTOR_P (op1))
26534 : 0 : op1 = validize_mem (force_const_mem (mode, op1));
26535 : 0 : emit_move_insn (target, gen_rtx_AND (mode, op0, op1));
26536 : 0 : return target;
26537 : : }
26538 : :
26539 : : /* Expand a 3-operand ternary logic expression. Return TARGET. */
26540 : : rtx
26541 : 2348 : ix86_expand_ternlog (machine_mode mode, rtx op0, rtx op1, rtx op2, int idx,
26542 : : rtx target)
26543 : : {
26544 : 2348 : rtx tmp0, tmp1, tmp2;
26545 : :
26546 : 2348 : if (!target)
26547 : 3 : target = gen_reg_rtx (mode);
26548 : :
26549 : : /* Canonicalize ternlog index for degenerate (duplicated) operands. */
26550 : 2348 : if (rtx_equal_p (op0, op1) && rtx_equal_p (op0, op2))
26551 : 0 : switch (idx & 0x81)
26552 : : {
26553 : : case 0x00:
26554 : : idx = 0x00;
26555 : : break;
26556 : : case 0x01:
26557 : : idx = 0x0f;
26558 : : break;
26559 : : case 0x80:
26560 : : idx = 0xf0;
26561 : : break;
26562 : : case 0x81:
26563 : : idx = 0xff;
26564 : : break;
26565 : : }
26566 : :
26567 : 2348 : switch (idx & 0xff)
26568 : : {
26569 : 0 : case 0x00:
26570 : 0 : if ((!op0 || !side_effects_p (op0))
26571 : 0 : && (!op1 || !side_effects_p (op1))
26572 : 0 : && (!op2 || !side_effects_p (op2)))
26573 : : {
26574 : 0 : emit_move_insn (target, CONST0_RTX (mode));
26575 : 0 : return target;
26576 : : }
26577 : : break;
26578 : :
26579 : 0 : case 0x0a: /* ~a&c */
26580 : 0 : if ((!op1 || !side_effects_p (op1))
26581 : 0 : && op0 && register_operand (op0, mode)
26582 : 0 : && op2 && ix86_ternlog_leaf_p (op2, mode))
26583 : 0 : return ix86_expand_ternlog_andnot (mode, op0, op2, target);
26584 : : break;
26585 : :
26586 : 0 : case 0x0c: /* ~a&b */
26587 : 0 : if ((!op2 || !side_effects_p (op2))
26588 : 0 : && op0 && register_operand (op0, mode)
26589 : 0 : && op1 && ix86_ternlog_leaf_p (op1, mode))
26590 : 0 : return ix86_expand_ternlog_andnot (mode, op0, op1, target);
26591 : : break;
26592 : :
26593 : 14 : case 0x0f: /* ~a */
26594 : 0 : if ((!op1 || !side_effects_p (op1))
26595 : 14 : && (!op2 || !side_effects_p (op2))
26596 : 28 : && op0)
26597 : : {
26598 : 14 : if (GET_MODE (op0) != mode)
26599 : 0 : op0 = gen_lowpart (mode, op0);
26600 : 14 : if (!TARGET_64BIT && !register_operand (op0, mode))
26601 : : {
26602 : : /* Avoid force_reg (mode, op0). */
26603 : 0 : rtx reg = gen_reg_rtx (mode);
26604 : 0 : emit_move_insn (reg, op0);
26605 : 0 : op0 = reg;
26606 : : }
26607 : 14 : emit_move_insn (target, gen_rtx_XOR (mode, op0, CONSTM1_RTX (mode)));
26608 : 14 : return target;
26609 : : }
26610 : : break;
26611 : :
26612 : 0 : case 0x22: /* ~b&c */
26613 : 0 : if ((!op0 || !side_effects_p (op0))
26614 : 0 : && op1 && register_operand (op1, mode)
26615 : 0 : && op2 && ix86_ternlog_leaf_p (op2, mode))
26616 : 0 : return ix86_expand_ternlog_andnot (mode, op1, op2, target);
26617 : : break;
26618 : :
26619 : 0 : case 0x30: /* ~b&a */
26620 : 0 : if ((!op2 || !side_effects_p (op2))
26621 : 0 : && op0 && ix86_ternlog_leaf_p (op0, mode)
26622 : 0 : && op1 && register_operand (op1, mode))
26623 : 0 : return ix86_expand_ternlog_andnot (mode, op1, op0, target);
26624 : : break;
26625 : :
26626 : 0 : case 0x33: /* ~b */
26627 : 0 : if ((!op0 || !side_effects_p (op0))
26628 : 0 : && (!op2 || !side_effects_p (op2))
26629 : 0 : && op1)
26630 : : {
26631 : 0 : if (GET_MODE (op1) != mode)
26632 : 0 : op1 = gen_lowpart (mode, op1);
26633 : 0 : if (!TARGET_64BIT && !register_operand (op1, mode))
26634 : : {
26635 : : /* Avoid force_reg (mode, op1). */
26636 : 0 : rtx reg = gen_reg_rtx (mode);
26637 : 0 : emit_move_insn (reg, op1);
26638 : 0 : op1 = reg;
26639 : : }
26640 : 0 : emit_move_insn (target, gen_rtx_XOR (mode, op1, CONSTM1_RTX (mode)));
26641 : 0 : return target;
26642 : : }
26643 : : break;
26644 : :
26645 : 0 : case 0x3c: /* a^b */
26646 : 0 : if (op0 && ix86_ternlog_leaf_p (op0, mode)
26647 : 0 : && op1 && ix86_ternlog_leaf_p (op1, mode)
26648 : 0 : && (!op2 || !side_effects_p (op2)))
26649 : 0 : return ix86_expand_ternlog_binop (XOR, mode, op0, op1, target);
26650 : : break;
26651 : :
26652 : 0 : case 0x44: /* ~c&b */
26653 : 0 : if ((!op0 || !side_effects_p (op0))
26654 : 0 : && op1 && ix86_ternlog_leaf_p (op1, mode)
26655 : 0 : && op2 && register_operand (op2, mode))
26656 : 0 : return ix86_expand_ternlog_andnot (mode, op2, op1, target);
26657 : : break;
26658 : :
26659 : 2 : case 0x50: /* ~c&a */
26660 : 0 : if ((!op1 || !side_effects_p (op1))
26661 : 2 : && op0 && ix86_ternlog_leaf_p (op0, mode)
26662 : 4 : && op2 && register_operand (op2, mode))
26663 : 0 : return ix86_expand_ternlog_andnot (mode, op2, op0, target);
26664 : : break;
26665 : :
26666 : 4 : case 0x55: /* ~c */
26667 : 1 : if ((!op0 || !side_effects_p (op0))
26668 : 4 : && (!op1 || !side_effects_p (op1))
26669 : 8 : && op2)
26670 : : {
26671 : 4 : if (GET_MODE (op2) != mode)
26672 : 0 : op2 = gen_lowpart (mode, op2);
26673 : 4 : if (!TARGET_64BIT && !register_operand (op2, mode))
26674 : : {
26675 : : /* Avoid force_reg (mode, op2). */
26676 : 0 : rtx reg = gen_reg_rtx (mode);
26677 : 0 : emit_move_insn (reg, op2);
26678 : 0 : op2 = reg;
26679 : : }
26680 : 4 : emit_move_insn (target, gen_rtx_XOR (mode, op2, CONSTM1_RTX (mode)));
26681 : 4 : return target;
26682 : : }
26683 : : break;
26684 : :
26685 : 0 : case 0x5a: /* a^c */
26686 : 0 : if (op0 && ix86_ternlog_leaf_p (op0, mode)
26687 : 0 : && op2 && ix86_ternlog_leaf_p (op2, mode)
26688 : 0 : && (!op1 || !side_effects_p (op1)))
26689 : 0 : return ix86_expand_ternlog_binop (XOR, mode, op0, op2, target);
26690 : : break;
26691 : :
26692 : 0 : case 0x66: /* b^c */
26693 : 0 : if ((!op0 || !side_effects_p (op0))
26694 : 0 : && op1 && ix86_ternlog_leaf_p (op1, mode)
26695 : 0 : && op2 && ix86_ternlog_leaf_p (op2, mode))
26696 : 0 : return ix86_expand_ternlog_binop (XOR, mode, op1, op2, target);
26697 : : break;
26698 : :
26699 : 0 : case 0x88: /* b&c */
26700 : 0 : if ((!op0 || !side_effects_p (op0))
26701 : 0 : && op1 && ix86_ternlog_leaf_p (op1, mode)
26702 : 0 : && op2 && ix86_ternlog_leaf_p (op2, mode))
26703 : 0 : return ix86_expand_ternlog_binop (AND, mode, op1, op2, target);
26704 : : break;
26705 : :
26706 : 0 : case 0xa0: /* a&c */
26707 : 0 : if ((!op1 || !side_effects_p (op1))
26708 : 0 : && op0 && ix86_ternlog_leaf_p (op0, mode)
26709 : 0 : && op2 && ix86_ternlog_leaf_p (op2, mode))
26710 : 0 : return ix86_expand_ternlog_binop (AND, mode, op0, op2, target);
26711 : : break;
26712 : :
26713 : 0 : case 0xaa: /* c */
26714 : 0 : if ((!op0 || !side_effects_p (op0))
26715 : 0 : && (!op1 || !side_effects_p (op1))
26716 : 0 : && op2)
26717 : : {
26718 : 0 : if (GET_MODE (op2) != mode)
26719 : 0 : op2 = gen_lowpart (mode, op2);
26720 : 0 : emit_move_insn (target, op2);
26721 : 0 : return target;
26722 : : }
26723 : : break;
26724 : :
26725 : 0 : case 0xc0: /* a&b */
26726 : 0 : if (op0 && ix86_ternlog_leaf_p (op0, mode)
26727 : 0 : && op1 && ix86_ternlog_leaf_p (op1, mode)
26728 : 0 : && (!op2 || !side_effects_p (op2)))
26729 : 0 : return ix86_expand_ternlog_binop (AND, mode, op0, op1, target);
26730 : : break;
26731 : :
26732 : 0 : case 0xcc: /* b */
26733 : 0 : if ((!op0 || !side_effects_p (op0))
26734 : 0 : && op1
26735 : 0 : && (!op2 || !side_effects_p (op2)))
26736 : : {
26737 : 0 : if (GET_MODE (op1) != mode)
26738 : 0 : op1 = gen_lowpart (mode, op1);
26739 : 0 : emit_move_insn (target, op1);
26740 : 0 : return target;
26741 : : }
26742 : : break;
26743 : :
26744 : 0 : case 0xee: /* b|c */
26745 : 0 : if ((!op0 || !side_effects_p (op0))
26746 : 0 : && op1 && ix86_ternlog_leaf_p (op1, mode)
26747 : 0 : && op2 && ix86_ternlog_leaf_p (op2, mode))
26748 : 0 : return ix86_expand_ternlog_binop (IOR, mode, op1, op2, target);
26749 : : break;
26750 : :
26751 : 6 : case 0xf0: /* a */
26752 : 6 : if (op0
26753 : 6 : && (!op1 || !side_effects_p (op1))
26754 : 12 : && (!op2 || !side_effects_p (op2)))
26755 : : {
26756 : 6 : if (GET_MODE (op0) != mode)
26757 : 0 : op0 = gen_lowpart (mode, op0);
26758 : 6 : emit_move_insn (target, op0);
26759 : 6 : return target;
26760 : : }
26761 : : break;
26762 : :
26763 : 0 : case 0xfa: /* a|c */
26764 : 0 : if (op0 && ix86_ternlog_leaf_p (op0, mode)
26765 : 0 : && op2 && ix86_ternlog_leaf_p (op2, mode)
26766 : 0 : && (!op1 || !side_effects_p (op1)))
26767 : 0 : return ix86_expand_ternlog_binop (IOR, mode, op0, op2, target);
26768 : : break;
26769 : :
26770 : 0 : case 0xfc: /* a|b */
26771 : 0 : if (op0 && ix86_ternlog_leaf_p (op0, mode)
26772 : 0 : && op1 && ix86_ternlog_leaf_p (op1, mode)
26773 : 0 : && (!op2 || !side_effects_p (op2)))
26774 : 0 : return ix86_expand_ternlog_binop (IOR, mode, op0, op1, target);
26775 : : break;
26776 : :
26777 : 0 : case 0xff:
26778 : 0 : if ((!op0 || !side_effects_p (op0))
26779 : 0 : && (!op1 || !side_effects_p (op1))
26780 : 0 : && (!op2 || !side_effects_p (op2)))
26781 : : {
26782 : 0 : emit_move_insn (target, CONSTM1_RTX (mode));
26783 : 0 : return target;
26784 : : }
26785 : : break;
26786 : : }
26787 : :
26788 : 2324 : if (!register_operand (op0, mode))
26789 : : {
26790 : : /* We can't use force_reg (mode, op0). */
26791 : 12 : tmp0 = gen_reg_rtx (GET_MODE (op0));
26792 : 12 : emit_move_insn (tmp0,op0);
26793 : : }
26794 : : else
26795 : : tmp0 = op0;
26796 : 2324 : if (GET_MODE (tmp0) != mode)
26797 : 0 : tmp0 = gen_lowpart (mode, tmp0);
26798 : :
26799 : 2324 : if (!op1 || rtx_equal_p (op0, op1))
26800 : 6 : tmp1 = copy_rtx (tmp0);
26801 : 2318 : else if (!register_operand (op1, mode))
26802 : : {
26803 : : /* We can't use force_reg (mode, op1). */
26804 : 37 : tmp1 = gen_reg_rtx (GET_MODE (op1));
26805 : 37 : emit_move_insn (tmp1, op1);
26806 : : }
26807 : : else
26808 : : tmp1 = op1;
26809 : 2324 : if (GET_MODE (tmp1) != mode)
26810 : 0 : tmp1 = gen_lowpart (mode, tmp1);
26811 : :
26812 : 2324 : if (!op2 || rtx_equal_p (op0, op2))
26813 : 71 : tmp2 = copy_rtx (tmp0);
26814 : 2253 : else if (rtx_equal_p (op1, op2))
26815 : 0 : tmp2 = copy_rtx (tmp1);
26816 : 2253 : else if (CONST_VECTOR_P (op2))
26817 : : {
26818 : 44 : if (GET_MODE (op2) != mode)
26819 : 0 : op2 = gen_lowpart (mode, op2);
26820 : 44 : tmp2 = ix86_gen_bcst_mem (mode, op2);
26821 : 44 : if (!tmp2)
26822 : : {
26823 : 26 : machine_mode bcst32_mode = mode;
26824 : 26 : machine_mode bcst64_mode = mode;
26825 : 26 : switch (mode)
26826 : : {
26827 : 1 : case V1TImode:
26828 : 1 : case V4SImode:
26829 : 1 : case V4SFmode:
26830 : 1 : case V8HImode:
26831 : 1 : case V16QImode:
26832 : 1 : bcst32_mode = V4SImode;
26833 : 1 : bcst64_mode = V2DImode;
26834 : 1 : break;
26835 : :
26836 : 0 : case V2TImode:
26837 : 0 : case V8SImode:
26838 : 0 : case V8SFmode:
26839 : 0 : case V16HImode:
26840 : 0 : case V32QImode:
26841 : 0 : bcst32_mode = V8SImode;
26842 : 0 : bcst64_mode = V4DImode;
26843 : 0 : break;
26844 : :
26845 : 3 : case V4TImode:
26846 : 3 : case V16SImode:
26847 : 3 : case V16SFmode:
26848 : 3 : case V32HImode:
26849 : 3 : case V64QImode:
26850 : 3 : bcst32_mode = V16SImode;
26851 : 3 : bcst64_mode = V8DImode;
26852 : 3 : break;
26853 : :
26854 : : default:
26855 : : break;
26856 : : }
26857 : :
26858 : 26 : if (bcst32_mode != mode)
26859 : : {
26860 : 4 : tmp2 = gen_lowpart (bcst32_mode, op2);
26861 : 4 : if (ix86_gen_bcst_mem (bcst32_mode, tmp2))
26862 : : {
26863 : 3 : tmp2 = ix86_expand_ternlog (bcst32_mode,
26864 : 3 : gen_lowpart (bcst32_mode, tmp0),
26865 : 3 : gen_lowpart (bcst32_mode, tmp1),
26866 : : tmp2, idx, NULL_RTX);
26867 : 3 : emit_move_insn (target, gen_lowpart (mode, tmp2));
26868 : 3 : return target;
26869 : : }
26870 : : }
26871 : :
26872 : 23 : if (bcst64_mode != mode)
26873 : : {
26874 : 1 : tmp2 = gen_lowpart (bcst64_mode, op2);
26875 : 1 : if (ix86_gen_bcst_mem (bcst64_mode, tmp2))
26876 : : {
26877 : 0 : tmp2 = ix86_expand_ternlog (bcst64_mode,
26878 : 0 : gen_lowpart (bcst64_mode, tmp0),
26879 : 0 : gen_lowpart (bcst64_mode, tmp1),
26880 : : tmp2, idx, NULL_RTX);
26881 : 0 : emit_move_insn (target, gen_lowpart (mode, tmp2));
26882 : 0 : return target;
26883 : : }
26884 : : }
26885 : :
26886 : 23 : tmp2 = force_const_mem (mode, op2);
26887 : 23 : rtx bcast = ix86_broadcast_from_constant (mode, tmp2);
26888 : 23 : tmp2 = validize_mem (tmp2);
26889 : 23 : if (bcast)
26890 : : {
26891 : 12 : rtx reg2 = gen_reg_rtx (mode);
26892 : 12 : bool ok = ix86_expand_vector_init_duplicate (false, mode,
26893 : : reg2, bcast);
26894 : 12 : if (ok)
26895 : 2321 : tmp2 = reg2;
26896 : : }
26897 : : }
26898 : : }
26899 : : else
26900 : : tmp2 = op2;
26901 : 2321 : if (GET_MODE (tmp2) != mode)
26902 : 0 : tmp2 = gen_lowpart (mode, tmp2);
26903 : : /* Some memory_operands are not vector_memory_operands. */
26904 : 2321 : if (!bcst_vector_operand (tmp2, mode))
26905 : 0 : tmp2 = force_reg (mode, tmp2);
26906 : :
26907 : 2321 : rtvec vec = gen_rtvec (4, tmp0, tmp1, tmp2, GEN_INT (idx));
26908 : 2321 : emit_move_insn (target, gen_rtx_UNSPEC (mode, vec, UNSPEC_VTERNLOG));
26909 : 2321 : return target;
26910 : : }
26911 : :
26912 : : /* Trunc a vector to a narrow vector, like v4di -> v4si. */
26913 : :
26914 : : void
26915 : 60 : ix86_expand_trunc_with_avx2_noavx512f (rtx output, rtx input, machine_mode cvt_mode)
26916 : : {
26917 : 60 : machine_mode out_mode = GET_MODE (output);
26918 : 60 : machine_mode in_mode = GET_MODE (input);
26919 : 60 : int len = GET_MODE_SIZE (in_mode);
26920 : 240 : gcc_assert (len == GET_MODE_SIZE (cvt_mode)
26921 : : && GET_MODE_INNER (out_mode) == GET_MODE_INNER (cvt_mode)
26922 : : && (REG_P (input) || SUBREG_P (input)));
26923 : 60 : scalar_mode inner_out_mode = GET_MODE_INNER (out_mode);
26924 : 120 : int in_innersize = GET_MODE_SIZE (GET_MODE_INNER (in_mode));
26925 : 60 : int out_innersize = GET_MODE_SIZE (inner_out_mode);
26926 : :
26927 : 60 : struct expand_vec_perm_d d;
26928 : 60 : d.target = gen_reg_rtx (cvt_mode);
26929 : 60 : d.op0 = lowpart_subreg (cvt_mode, force_reg(in_mode, input), in_mode);
26930 : 60 : d.op1 = d.op0;
26931 : 60 : d.vmode = cvt_mode;
26932 : 60 : d.nelt = GET_MODE_NUNITS (cvt_mode);
26933 : 60 : d.testing_p = false;
26934 : 60 : d.one_operand_p = true;
26935 : :
26936 : : /* Init perm. Put the needed bits of input in order and
26937 : : fill the rest of bits by default. */
26938 : 636 : for (int i = 0; i < d.nelt; ++i)
26939 : : {
26940 : 576 : d.perm[i] = i;
26941 : 1152 : if (i < GET_MODE_NUNITS (out_mode))
26942 : 234 : d.perm[i] = i * (in_innersize / out_innersize);
26943 : : }
26944 : :
26945 : 60 : bool ok = ix86_expand_vec_perm_const_1(&d);
26946 : 60 : gcc_assert (ok);
26947 : 60 : emit_move_insn (output, gen_lowpart (out_mode, d.target));
26948 : 60 : }
26949 : :
26950 : : /* Implement truncv8sfv8bf2 with vector permutation. */
26951 : : void
26952 : 8 : ix86_expand_vector_sf2bf_with_vec_perm (rtx dest, rtx src)
26953 : : {
26954 : 8 : machine_mode vperm_mode, src_mode = GET_MODE (src);
26955 : 8 : switch (src_mode)
26956 : : {
26957 : : case V16SFmode:
26958 : : vperm_mode = V32BFmode;
26959 : : break;
26960 : 2 : case V8SFmode:
26961 : 2 : vperm_mode = V16BFmode;
26962 : 2 : break;
26963 : 4 : case V4SFmode:
26964 : 4 : vperm_mode = V8BFmode;
26965 : 4 : break;
26966 : 0 : default:
26967 : 0 : gcc_unreachable ();
26968 : : }
26969 : :
26970 : 8 : int nelt = GET_MODE_NUNITS (vperm_mode);
26971 : 8 : vec_perm_builder sel (nelt, nelt, 1);
26972 : 8 : sel.quick_grow (nelt);
26973 : 136 : for (int i = 0; i != nelt; i++)
26974 : 128 : sel[i] = (2 * i + 1) % nelt;
26975 : 16 : vec_perm_indices indices (sel, 1, nelt);
26976 : :
26977 : 8 : rtx target = gen_reg_rtx (vperm_mode);
26978 : 8 : rtx op0 = lowpart_subreg (vperm_mode,
26979 : : force_reg (src_mode, src),
26980 : : src_mode);
26981 : 8 : bool ok = targetm.vectorize.vec_perm_const (vperm_mode, vperm_mode,
26982 : : target, op0, op0, indices);
26983 : 8 : gcc_assert (ok);
26984 : 8 : emit_move_insn (dest, lowpart_subreg (GET_MODE (dest), target, vperm_mode));
26985 : 8 : }
26986 : :
26987 : : /* Implement extendv8bf2v8sf2 with vector permutation. */
26988 : : void
26989 : 8 : ix86_expand_vector_bf2sf_with_vec_perm (rtx dest, rtx src)
26990 : : {
26991 : 8 : machine_mode vperm_mode, src_mode = GET_MODE (src);
26992 : 8 : switch (src_mode)
26993 : : {
26994 : : case V16BFmode:
26995 : : vperm_mode = V32BFmode;
26996 : : break;
26997 : 2 : case V8BFmode:
26998 : 2 : vperm_mode = V16BFmode;
26999 : 2 : break;
27000 : 4 : case V4BFmode:
27001 : 4 : vperm_mode = V8BFmode;
27002 : 4 : break;
27003 : 0 : default:
27004 : 0 : gcc_unreachable ();
27005 : : }
27006 : :
27007 : 8 : int nelt = GET_MODE_NUNITS (vperm_mode);
27008 : 8 : vec_perm_builder sel (nelt, nelt, 1);
27009 : 8 : sel.quick_grow (nelt);
27010 : 136 : for (int i = 0, k = 0, j = nelt; i != nelt; i++)
27011 : 128 : sel[i] = i & 1 ? j++ : k++;
27012 : :
27013 : 16 : vec_perm_indices indices (sel, 2, nelt);
27014 : :
27015 : 8 : rtx target = gen_reg_rtx (vperm_mode);
27016 : 8 : rtx op1 = lowpart_subreg (vperm_mode,
27017 : : force_reg (src_mode, src),
27018 : : src_mode);
27019 : 8 : rtx op0 = CONST0_RTX (vperm_mode);
27020 : 8 : bool ok = targetm.vectorize.vec_perm_const (vperm_mode, vperm_mode,
27021 : : target, op0, op1, indices);
27022 : 8 : gcc_assert (ok);
27023 : 8 : emit_move_insn (dest, lowpart_subreg (GET_MODE (dest), target, vperm_mode));
27024 : 8 : }
27025 : :
27026 : :
27027 : : #include "gt-i386-expand.h"
|