Branch data Line data Source code
1 : : /* Copyright (C) 1988-2024 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 : 4014419 : split_double_mode (machine_mode mode, rtx operands[],
106 : : int num, rtx lo_half[], rtx hi_half[])
107 : : {
108 : 4014419 : machine_mode half_mode;
109 : 4014419 : unsigned int byte;
110 : 4014419 : rtx mem_op = NULL_RTX;
111 : 4014419 : int mem_num = 0;
112 : :
113 : 4014419 : switch (mode)
114 : : {
115 : : case E_TImode:
116 : : half_mode = DImode;
117 : : break;
118 : 566877 : case E_DImode:
119 : 566877 : half_mode = SImode;
120 : 566877 : 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 : 4014419 : byte = GET_MODE_SIZE (half_mode);
132 : :
133 : 8217019 : while (num--)
134 : : {
135 : 4202600 : rtx op = operands[num];
136 : :
137 : : /* simplify_subreg refuse to split volatile memory addresses,
138 : : but we still have to handle it. */
139 : 4202600 : if (MEM_P (op))
140 : : {
141 : 1657286 : if (mem_op && rtx_equal_p (op, mem_op))
142 : : {
143 : 2105 : lo_half[num] = lo_half[mem_num];
144 : 2105 : hi_half[num] = hi_half[mem_num];
145 : : }
146 : : else
147 : : {
148 : 1655181 : mem_op = op;
149 : 1655181 : mem_num = num;
150 : 1655181 : lo_half[num] = adjust_address (op, half_mode, 0);
151 : 1655181 : hi_half[num] = adjust_address (op, half_mode, byte);
152 : : }
153 : : }
154 : : else
155 : : {
156 : 2545314 : lo_half[num] = simplify_gen_subreg (half_mode, op,
157 : 2545314 : GET_MODE (op) == VOIDmode
158 : 2545314 : ? mode : GET_MODE (op), 0);
159 : :
160 : 2545314 : rtx tmp = simplify_gen_subreg (half_mode, op,
161 : 2545314 : GET_MODE (op) == VOIDmode
162 : : ? mode : GET_MODE (op), byte);
163 : : /* simplify_gen_subreg will return NULL RTX for the
164 : : high half of the paradoxical subreg. */
165 : 2545314 : hi_half[num] = tmp ? tmp : gen_reg_rtx (half_mode);
166 : : }
167 : : }
168 : 4014419 : }
169 : :
170 : : /* Emit the double word assignment DST = { LO, HI }. */
171 : :
172 : : void
173 : 97209 : split_double_concat (machine_mode mode, rtx dst, rtx lo, rtx hi)
174 : : {
175 : 97209 : rtx dlo, dhi;
176 : 97209 : int deleted_move_count = 0;
177 : 97209 : 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 : 97209 : if (MEM_P (lo)
183 : 5187 : && rtx_equal_p (dlo, hi)
184 : 97653 : && 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 : 2 : emit_move_insn (dhi, lo);
192 : 2 : lo = dhi;
193 : : }
194 : 97207 : else if (MEM_P (hi)
195 : 9537 : && !MEM_P (lo)
196 : 5996 : && !rtx_equal_p (dlo, lo)
197 : 98315 : && 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 : 17 : 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 : 8 : emit_move_insn (dhi, hi);
213 : 8 : hi = dhi;
214 : : }
215 : : }
216 : 97209 : if (!rtx_equal_p (dlo, hi))
217 : : {
218 : 83620 : if (!rtx_equal_p (dlo, lo))
219 : 34710 : emit_move_insn (dlo, lo);
220 : : else
221 : : deleted_move_count++;
222 : 83620 : if (!rtx_equal_p (dhi, hi))
223 : 78758 : emit_move_insn (dhi, hi);
224 : : else
225 : 4862 : deleted_move_count++;
226 : : }
227 : 13589 : else if (!rtx_equal_p (lo, dhi))
228 : : {
229 : 7637 : if (!rtx_equal_p (dhi, hi))
230 : 7637 : emit_move_insn (dhi, hi);
231 : : else
232 : : deleted_move_count++;
233 : 7637 : if (!rtx_equal_p (dlo, lo))
234 : 7551 : emit_move_insn (dlo, lo);
235 : : else
236 : 86 : deleted_move_count++;
237 : : }
238 : 5952 : else if (mode == TImode)
239 : 5930 : emit_insn (gen_swapdi (dlo, dhi));
240 : : else
241 : 22 : emit_insn (gen_swapsi (dlo, dhi));
242 : :
243 : 97209 : if (deleted_move_count == 2)
244 : 2319 : emit_note (NOTE_INSN_DELETED);
245 : 97209 : }
246 : :
247 : :
248 : : /* Generate either "mov $0, reg" or "xor reg, reg", as appropriate
249 : : for the target. */
250 : :
251 : : void
252 : 98169 : ix86_expand_clear (rtx dest)
253 : : {
254 : 98169 : rtx tmp;
255 : :
256 : : /* We play register width games, which are only valid after reload. */
257 : 98169 : gcc_assert (reload_completed);
258 : :
259 : : /* Avoid HImode and its attendant prefix byte. */
260 : 196338 : if (GET_MODE_SIZE (GET_MODE (dest)) < 4)
261 : 865 : dest = gen_rtx_REG (SImode, REGNO (dest));
262 : 98169 : tmp = gen_rtx_SET (dest, const0_rtx);
263 : :
264 : 98169 : if (!TARGET_USE_MOV0 || optimize_insn_for_size_p ())
265 : : {
266 : 98169 : rtx clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
267 : 98169 : tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, tmp, clob));
268 : : }
269 : :
270 : 98169 : emit_insn (tmp);
271 : 98169 : }
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 : 4381 : ix86_broadcast (HOST_WIDE_INT v, unsigned int width,
278 : : HOST_WIDE_INT &val_broadcast)
279 : : {
280 : 4381 : wide_int val = wi::uhwi (v, HOST_BITS_PER_WIDE_INT);
281 : 4381 : val_broadcast = wi::extract_uhwi (val, 0, width);
282 : 5735 : for (unsigned int i = width; i < HOST_BITS_PER_WIDE_INT; i += width)
283 : : {
284 : 4429 : HOST_WIDE_INT each = wi::extract_uhwi (val, i, width);
285 : 4429 : if (val_broadcast != each)
286 : : return false;
287 : : }
288 : 1306 : val_broadcast = sext_hwi (val_broadcast, width);
289 : 1306 : return true;
290 : 4381 : }
291 : :
292 : : /* Convert the CONST_WIDE_INT operand OP to broadcast in MODE. */
293 : :
294 : : rtx
295 : 34602 : 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 : 34602 : if (!TARGET_INTER_UNIT_MOVES_TO_VEC)
300 : : return nullptr;
301 : :
302 : 34602 : unsigned int msize = GET_MODE_SIZE (mode);
303 : :
304 : : /* Only optimized for vpbroadcast[bwsd]/vbroadcastss with xmm/ymm/zmm. */
305 : 34602 : 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 : 34602 : if (!TARGET_AVX
311 : 1347 : || !CONST_WIDE_INT_P (op)
312 : 1341 : || standard_sse_constant_p (op, mode)
313 : 35943 : || (CONST_WIDE_INT_NUNITS (op) * HOST_BITS_PER_WIDE_INT
314 : 1341 : != GET_MODE_BITSIZE (mode)))
315 : 33263 : return nullptr;
316 : :
317 : 1339 : HOST_WIDE_INT val = CONST_WIDE_INT_ELT (op, 0);
318 : 1339 : HOST_WIDE_INT val_broadcast;
319 : 1339 : scalar_int_mode broadcast_mode;
320 : : /* vpbroadcastb zmm requires TARGET_AVX512BW. */
321 : 486 : if ((msize == 64 ? TARGET_AVX512BW : TARGET_AVX2)
322 : 2360 : && ix86_broadcast (val, GET_MODE_BITSIZE (QImode),
323 : : val_broadcast))
324 : : broadcast_mode = QImode;
325 : 460 : else if ((msize == 64 ? TARGET_AVX512BW : TARGET_AVX2)
326 : 2296 : && 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 : 215 : else if ((msize != 32 || TARGET_AVX2)
333 : 2505 : && ix86_broadcast (val, GET_MODE_BITSIZE (SImode),
334 : : val_broadcast))
335 : : broadcast_mode = SImode;
336 : 1168 : else if (TARGET_64BIT && (msize != 32 || TARGET_AVX2)
337 : 2303 : && ix86_broadcast (val, GET_MODE_BITSIZE (DImode),
338 : : val_broadcast))
339 : : broadcast_mode = DImode;
340 : : else
341 : 33 : return nullptr;
342 : :
343 : : /* Check if OP can be broadcasted from VAL. */
344 : 1663 : for (int i = 1; i < CONST_WIDE_INT_NUNITS (op); i++)
345 : 1444 : if (val != CONST_WIDE_INT_ELT (op, i))
346 : : return nullptr;
347 : :
348 : 219 : unsigned int nunits = (GET_MODE_SIZE (mode)
349 : 219 : / GET_MODE_SIZE (broadcast_mode));
350 : 219 : machine_mode vector_mode;
351 : 219 : if (!mode_for_vector (broadcast_mode, nunits).exists (&vector_mode))
352 : 0 : gcc_unreachable ();
353 : 219 : rtx target = gen_reg_rtx (vector_mode);
354 : 219 : bool ok = ix86_expand_vector_init_duplicate (false, vector_mode,
355 : : target,
356 : : GEN_INT (val_broadcast));
357 : 219 : if (!ok)
358 : : return nullptr;
359 : 219 : target = lowpart_subreg (mode, target, vector_mode);
360 : 219 : return target;
361 : : }
362 : :
363 : : void
364 : 69272989 : ix86_expand_move (machine_mode mode, rtx operands[])
365 : : {
366 : 69272989 : rtx op0, op1;
367 : 69272989 : rtx tmp, addend = NULL_RTX;
368 : 69272989 : enum tls_model model;
369 : :
370 : 69272989 : op0 = operands[0];
371 : 69272989 : op1 = operands[1];
372 : :
373 : : /* Avoid complex sets of likely spilled hard registers before reload. */
374 : 69272989 : if (!ix86_hardreg_mov_ok (op0, op1))
375 : : {
376 : 242661 : tmp = gen_reg_rtx (mode);
377 : 242661 : operands[0] = tmp;
378 : 242661 : ix86_expand_move (mode, operands);
379 : 242661 : operands[0] = op0;
380 : 242661 : operands[1] = tmp;
381 : 242661 : op1 = tmp;
382 : : }
383 : :
384 : 69272989 : switch (GET_CODE (op1))
385 : : {
386 : 347821 : case CONST:
387 : 347821 : tmp = XEXP (op1, 0);
388 : :
389 : 347821 : if (GET_CODE (tmp) != PLUS
390 : 336144 : || GET_CODE (XEXP (tmp, 0)) != SYMBOL_REF)
391 : : break;
392 : :
393 : 333553 : op1 = XEXP (tmp, 0);
394 : 333553 : addend = XEXP (tmp, 1);
395 : : /* FALLTHRU */
396 : :
397 : 4708948 : case SYMBOL_REF:
398 : 4708948 : model = SYMBOL_REF_TLS_MODEL (op1);
399 : :
400 : 4708948 : if (model)
401 : 9600 : op1 = legitimize_tls_address (op1, model, true);
402 : 4699348 : else if (ix86_force_load_from_GOT_p (op1))
403 : : {
404 : : /* Load the external function address via GOT slot to avoid PLT. */
405 : 12 : op1 = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op1),
406 : : (TARGET_64BIT
407 : : ? UNSPEC_GOTPCREL
408 : : : UNSPEC_GOT));
409 : 12 : op1 = gen_rtx_CONST (Pmode, op1);
410 : 12 : op1 = gen_const_mem (Pmode, op1);
411 : 12 : set_mem_alias_set (op1, ix86_GOT_alias_set ());
412 : : }
413 : : else
414 : : {
415 : 4699336 : tmp = legitimize_pe_coff_symbol (op1, addend != NULL_RTX);
416 : 4699336 : if (tmp)
417 : : {
418 : 0 : op1 = tmp;
419 : 0 : if (!addend)
420 : : break;
421 : : }
422 : : else
423 : : {
424 : 4699336 : op1 = operands[1];
425 : 4699336 : break;
426 : : }
427 : : }
428 : :
429 : 9612 : if (addend)
430 : : {
431 : 2786 : op1 = force_operand (op1, NULL_RTX);
432 : 2786 : op1 = expand_simple_binop (Pmode, PLUS, op1, addend,
433 : : op0, 1, OPTAB_DIRECT);
434 : : }
435 : : else
436 : 6826 : op1 = force_operand (op1, op0);
437 : :
438 : 9612 : if (op1 == op0)
439 : : return;
440 : :
441 : 4520 : op1 = convert_to_mode (mode, op1, 1);
442 : :
443 : : default:
444 : : break;
445 : :
446 : 1645411 : case SUBREG:
447 : : /* Transform TImode paradoxical SUBREG into zero_extendditi2. */
448 : 1645411 : if (TARGET_64BIT
449 : 1397967 : && mode == TImode
450 : : && SUBREG_P (op1)
451 : 89628 : && GET_MODE (SUBREG_REG (op1)) == DImode
452 : 1688507 : && SUBREG_BYTE (op1) == 0)
453 : 43096 : op1 = gen_rtx_ZERO_EXTEND (TImode, SUBREG_REG (op1));
454 : : /* As not all values in XFmode are representable in real_value,
455 : : we might be called with unfoldable SUBREGs of constants. */
456 : 1645411 : if (mode == XFmode
457 : 2535 : && CONSTANT_P (SUBREG_REG (op1))
458 : 2 : && can_create_pseudo_p ())
459 : : {
460 : 2 : machine_mode imode = GET_MODE (SUBREG_REG (op1));
461 : 2 : rtx r = force_const_mem (imode, SUBREG_REG (op1));
462 : 2 : if (r)
463 : 2 : r = validize_mem (r);
464 : : else
465 : 0 : r = force_reg (imode, SUBREG_REG (op1));
466 : 2 : op1 = simplify_gen_subreg (mode, r, imode, SUBREG_BYTE (op1));
467 : : }
468 : : break;
469 : : }
470 : :
471 : 69267897 : if ((flag_pic || MACHOPIC_INDIRECT)
472 : 69267897 : && symbolic_operand (op1, mode))
473 : : {
474 : : #if TARGET_MACHO
475 : : if (TARGET_MACHO && !TARGET_64BIT)
476 : : {
477 : : /* dynamic-no-pic */
478 : : if (MACHOPIC_INDIRECT)
479 : : {
480 : : rtx temp = (op0 && REG_P (op0) && mode == Pmode)
481 : : ? op0 : gen_reg_rtx (Pmode);
482 : : op1 = machopic_indirect_data_reference (op1, temp);
483 : : if (MACHOPIC_PURE)
484 : : op1 = machopic_legitimize_pic_address (op1, mode,
485 : : temp == op1 ? 0 : temp);
486 : : }
487 : : if (op0 != op1 && GET_CODE (op0) != MEM)
488 : : {
489 : : rtx insn = gen_rtx_SET (op0, op1);
490 : : emit_insn (insn);
491 : : return;
492 : : }
493 : : }
494 : : #endif
495 : :
496 : 329887 : if (MEM_P (op0))
497 : 87114 : op1 = force_reg (mode, op1);
498 : 242773 : else if (!(TARGET_64BIT && x86_64_movabs_operand (op1, DImode)))
499 : : {
500 : 242730 : rtx reg = can_create_pseudo_p () ? NULL_RTX : op0;
501 : 242730 : op1 = legitimize_pic_address (op1, reg);
502 : 242730 : if (op0 == op1)
503 : : return;
504 : 242730 : op1 = convert_to_mode (mode, op1, 1);
505 : : }
506 : : }
507 : : else
508 : : {
509 : 68938010 : if (MEM_P (op0)
510 : 93592322 : && (PUSH_ROUNDING (GET_MODE_SIZE (mode)) != GET_MODE_SIZE (mode)
511 : 10062573 : || !push_operand (op0, mode))
512 : 80325448 : && MEM_P (op1))
513 : 2185098 : op1 = force_reg (mode, op1);
514 : :
515 : 68938010 : if (push_operand (op0, mode)
516 : 68938010 : && ! general_no_elim_operand (op1, mode))
517 : 1018 : op1 = copy_to_mode_reg (mode, op1);
518 : :
519 : : /* Force large constants in 64bit compilation into register
520 : : to get them CSEed. */
521 : 68938010 : if (can_create_pseudo_p ()
522 : 63737220 : && (mode == DImode) && TARGET_64BIT
523 : 32061997 : && immediate_operand (op1, mode)
524 : 7869054 : && !x86_64_zext_immediate_operand (op1, VOIDmode)
525 : 765454 : && !register_operand (op0, mode)
526 : 69092853 : && optimize)
527 : 105892 : op1 = copy_to_mode_reg (mode, op1);
528 : :
529 : 68938010 : if (can_create_pseudo_p ())
530 : : {
531 : 63737220 : if (CONST_DOUBLE_P (op1))
532 : : {
533 : : /* If we are loading a floating point constant to a
534 : : register, force the value to memory now, since we'll
535 : : get better code out the back end. */
536 : :
537 : 880469 : op1 = validize_mem (force_const_mem (mode, op1));
538 : 880469 : if (!register_operand (op0, mode))
539 : : {
540 : 122861 : rtx temp = gen_reg_rtx (mode);
541 : 122861 : emit_insn (gen_rtx_SET (temp, op1));
542 : 122861 : emit_move_insn (op0, temp);
543 : 122861 : return;
544 : : }
545 : : }
546 : : }
547 : : }
548 : :
549 : : /* Special case inserting 64-bit values into a TImode register. */
550 : 69145036 : if (TARGET_64BIT
551 : : /* Disable for -O0 (see PR110587) unless naked (PR110533). */
552 : 59570159 : && (optimize || ix86_function_naked (current_function_decl))
553 : 39947774 : && (mode == DImode || mode == DFmode)
554 : 26521041 : && SUBREG_P (op0)
555 : 421512 : && GET_MODE (SUBREG_REG (op0)) == TImode
556 : 421512 : && REG_P (SUBREG_REG (op0))
557 : 69484240 : && REG_P (op1))
558 : : {
559 : : /* Use *insvti_lowpart_1 to set lowpart. */
560 : 162522 : if (SUBREG_BYTE (op0) == 0)
561 : : {
562 : 41439 : wide_int mask = wi::mask (64, true, 128);
563 : 41439 : rtx tmp = immed_wide_int_const (mask, TImode);
564 : 41439 : op0 = SUBREG_REG (op0);
565 : 41439 : tmp = gen_rtx_AND (TImode, copy_rtx (op0), tmp);
566 : 41439 : if (mode == DFmode)
567 : 346 : op1 = gen_lowpart (DImode, op1);
568 : 41439 : op1 = gen_rtx_ZERO_EXTEND (TImode, op1);
569 : 41439 : op1 = gen_rtx_IOR (TImode, tmp, op1);
570 : 41439 : }
571 : : /* Use *insvti_highpart_1 to set highpart. */
572 : 121083 : else if (SUBREG_BYTE (op0) == 8)
573 : : {
574 : 121083 : wide_int mask = wi::mask (64, false, 128);
575 : 121083 : rtx tmp = immed_wide_int_const (mask, TImode);
576 : 121083 : op0 = SUBREG_REG (op0);
577 : 121083 : tmp = gen_rtx_AND (TImode, copy_rtx (op0), tmp);
578 : 121083 : if (mode == DFmode)
579 : 193 : op1 = gen_lowpart (DImode, op1);
580 : 121083 : op1 = gen_rtx_ZERO_EXTEND (TImode, op1);
581 : 121083 : op1 = gen_rtx_ASHIFT (TImode, op1, GEN_INT (64));
582 : 121083 : op1 = gen_rtx_IOR (TImode, tmp, op1);
583 : 121083 : }
584 : : }
585 : :
586 : 69145036 : emit_insn (gen_rtx_SET (op0, op1));
587 : : }
588 : :
589 : : /* OP is a memref of CONST_VECTOR, return scalar constant mem
590 : : if CONST_VECTOR is a vec_duplicate, else return NULL. */
591 : : static rtx
592 : 424055 : ix86_broadcast_from_constant (machine_mode mode, rtx op)
593 : : {
594 : 424055 : int nunits = GET_MODE_NUNITS (mode);
595 : 424055 : if (nunits < 2)
596 : : return nullptr;
597 : :
598 : : /* Don't use integer vector broadcast if we can't move from GPR to SSE
599 : : register directly. */
600 : 423695 : if (!TARGET_INTER_UNIT_MOVES_TO_VEC
601 : 2244 : && INTEGRAL_MODE_P (mode))
602 : : return nullptr;
603 : :
604 : : /* Convert CONST_VECTOR to a non-standard SSE constant integer
605 : : broadcast only if vector broadcast is available. */
606 : 422648 : if (standard_sse_constant_p (op, mode))
607 : : return nullptr;
608 : :
609 : 845288 : if (GET_MODE_INNER (mode) == TImode)
610 : : return nullptr;
611 : :
612 : 422623 : rtx constant = get_pool_constant (XEXP (op, 0));
613 : 422623 : if (GET_CODE (constant) != CONST_VECTOR)
614 : : return nullptr;
615 : :
616 : : /* There could be some rtx like
617 : : (mem/u/c:V16QI (symbol_ref/u:DI ("*.LC1")))
618 : : but with "*.LC1" refer to V2DI constant vector. */
619 : 422623 : if (GET_MODE (constant) != mode)
620 : : {
621 : 696 : constant = simplify_subreg (mode, constant, GET_MODE (constant),
622 : 348 : 0);
623 : 348 : if (constant == nullptr || GET_CODE (constant) != CONST_VECTOR)
624 : : return nullptr;
625 : : }
626 : :
627 : 422623 : rtx first = XVECEXP (constant, 0, 0);
628 : :
629 : 776321 : for (int i = 1; i < nunits; ++i)
630 : : {
631 : 667750 : rtx tmp = XVECEXP (constant, 0, i);
632 : : /* Vector duplicate value. */
633 : 667750 : if (!rtx_equal_p (tmp, first))
634 : : return nullptr;
635 : : }
636 : :
637 : : return first;
638 : : }
639 : :
640 : : void
641 : 4016686 : ix86_expand_vector_move (machine_mode mode, rtx operands[])
642 : : {
643 : 4016686 : rtx op0 = operands[0], op1 = operands[1];
644 : : /* Use GET_MODE_BITSIZE instead of GET_MODE_ALIGNMENT for IA MCU
645 : : psABI since the biggest alignment is 4 byte for IA MCU psABI. */
646 : 4016686 : unsigned int align = (TARGET_IAMCU
647 : 4016686 : ? GET_MODE_BITSIZE (mode)
648 : 4016686 : : GET_MODE_ALIGNMENT (mode));
649 : :
650 : 4016686 : if (push_operand (op0, VOIDmode))
651 : 2875 : op0 = emit_move_resolve_push (mode, op0);
652 : :
653 : : /* Force constants other than zero into memory. We do not know how
654 : : the instructions used to build constants modify the upper 64 bits
655 : : of the register, once we have that information we may be able
656 : : to handle some of them more efficiently. */
657 : 4016686 : if (can_create_pseudo_p ()
658 : 3827530 : && (CONSTANT_P (op1)
659 : 3580904 : || (SUBREG_P (op1)
660 : 279775 : && CONSTANT_P (SUBREG_REG (op1))))
661 : 4263358 : && ((register_operand (op0, mode)
662 : 199891 : && !standard_sse_constant_p (op1, mode))
663 : : /* ix86_expand_vector_move_misalign() does not like constants. */
664 : : || (SSE_REG_MODE_P (mode)
665 : 195124 : && MEM_P (op0)
666 : 34719 : && MEM_ALIGN (op0) < align)))
667 : : {
668 : 1987 : if (SUBREG_P (op1))
669 : : {
670 : 46 : machine_mode imode = GET_MODE (SUBREG_REG (op1));
671 : 46 : rtx r = force_const_mem (imode, SUBREG_REG (op1));
672 : 46 : if (r)
673 : 46 : r = validize_mem (r);
674 : : else
675 : 0 : r = force_reg (imode, SUBREG_REG (op1));
676 : 46 : op1 = simplify_gen_subreg (mode, r, imode, SUBREG_BYTE (op1));
677 : : }
678 : : else
679 : : {
680 : 1941 : machine_mode mode = GET_MODE (op0);
681 : 1941 : rtx tmp = ix86_convert_const_wide_int_to_broadcast
682 : 1941 : (mode, op1);
683 : 1941 : if (tmp == nullptr)
684 : 1915 : op1 = validize_mem (force_const_mem (mode, op1));
685 : : else
686 : : op1 = tmp;
687 : : }
688 : : }
689 : :
690 : 4016686 : if (can_create_pseudo_p ()
691 : 3827530 : && GET_MODE_SIZE (mode) >= 16
692 : 3107277 : && VECTOR_MODE_P (mode)
693 : 6891623 : && (MEM_P (op1)
694 : 611147 : && SYMBOL_REF_P (XEXP (op1, 0))
695 : 438307 : && CONSTANT_POOL_ADDRESS_P (XEXP (op1, 0))))
696 : : {
697 : 424055 : rtx first = ix86_broadcast_from_constant (mode, op1);
698 : 424055 : if (first != nullptr)
699 : : {
700 : : /* Broadcast to XMM/YMM/ZMM register from an integer
701 : : constant or scalar mem. */
702 : 108571 : rtx tmp = gen_reg_rtx (mode);
703 : 108571 : if (FLOAT_MODE_P (mode))
704 : 24678 : first = force_const_mem (GET_MODE_INNER (mode), first);
705 : 108571 : bool ok = ix86_expand_vector_init_duplicate (false, mode,
706 : : tmp, first);
707 : 108571 : if (!ok && !TARGET_64BIT && GET_MODE_INNER (mode) == DImode)
708 : : {
709 : 0 : first = force_const_mem (GET_MODE_INNER (mode), first);
710 : 0 : ok = ix86_expand_vector_init_duplicate (false, mode,
711 : : tmp, first);
712 : : }
713 : 108571 : if (ok)
714 : : {
715 : 108571 : emit_move_insn (op0, tmp);
716 : 108571 : return;
717 : : }
718 : : }
719 : : }
720 : :
721 : : /* We need to check memory alignment for SSE mode since attribute
722 : : can make operands unaligned. */
723 : 3908115 : if (can_create_pseudo_p ()
724 : : && SSE_REG_MODE_P (mode)
725 : 6877329 : && ((MEM_P (op0) && (MEM_ALIGN (op0) < align))
726 : 2817749 : || (MEM_P (op1) && (MEM_ALIGN (op1) < align))))
727 : : {
728 : 256221 : rtx tmp[2];
729 : :
730 : : /* ix86_expand_vector_move_misalign() does not like both
731 : : arguments in memory. */
732 : 256221 : if (!register_operand (op0, mode)
733 : 256221 : && !register_operand (op1, mode))
734 : : {
735 : 95838 : rtx scratch = gen_reg_rtx (mode);
736 : 95838 : emit_move_insn (scratch, op1);
737 : 95838 : op1 = scratch;
738 : : }
739 : :
740 : 256221 : tmp[0] = op0; tmp[1] = op1;
741 : 256221 : ix86_expand_vector_move_misalign (mode, tmp);
742 : 256221 : return;
743 : : }
744 : :
745 : : /* Special case TImode to 128-bit vector conversions via V2DI. */
746 : 1063489 : if (VECTOR_MODE_P (mode)
747 : 3603141 : && GET_MODE_SIZE (mode) == 16
748 : 2412748 : && SUBREG_P (op1)
749 : 196378 : && GET_MODE (SUBREG_REG (op1)) == TImode
750 : 6250 : && TARGET_64BIT && TARGET_SSE
751 : 3657547 : && can_create_pseudo_p ())
752 : : {
753 : 5653 : rtx tmp = gen_reg_rtx (V2DImode);
754 : 5653 : rtx lo = gen_reg_rtx (DImode);
755 : 5653 : rtx hi = gen_reg_rtx (DImode);
756 : 5653 : emit_move_insn (lo, gen_lowpart (DImode, SUBREG_REG (op1)));
757 : 5653 : emit_move_insn (hi, gen_highpart (DImode, SUBREG_REG (op1)));
758 : 5653 : emit_insn (gen_vec_concatv2di (tmp, lo, hi));
759 : 5653 : emit_move_insn (op0, gen_lowpart (mode, tmp));
760 : 5653 : return;
761 : : }
762 : :
763 : : /* If operand0 is a hard register, make operand1 a pseudo. */
764 : 3646241 : if (can_create_pseudo_p ()
765 : 7103326 : && !ix86_hardreg_mov_ok (op0, op1))
766 : : {
767 : 41 : rtx tmp = gen_reg_rtx (GET_MODE (op0));
768 : 41 : emit_move_insn (tmp, op1);
769 : 41 : emit_move_insn (op0, tmp);
770 : 41 : return;
771 : : }
772 : :
773 : : /* Make operand1 a register if it isn't already. */
774 : 3646200 : if (can_create_pseudo_p ()
775 : 3457044 : && !register_operand (op0, mode)
776 : 4622823 : && !register_operand (op1, mode))
777 : : {
778 : 188140 : rtx tmp = gen_reg_rtx (GET_MODE (op0));
779 : 188140 : emit_move_insn (tmp, op1);
780 : 188140 : emit_move_insn (op0, tmp);
781 : 188140 : return;
782 : : }
783 : :
784 : 3458060 : emit_insn (gen_rtx_SET (op0, op1));
785 : : }
786 : :
787 : : /* Split 32-byte AVX unaligned load and store if needed. */
788 : :
789 : : static void
790 : 9910 : ix86_avx256_split_vector_move_misalign (rtx op0, rtx op1)
791 : : {
792 : 9910 : rtx m;
793 : 9910 : rtx (*extract) (rtx, rtx, rtx);
794 : 9910 : machine_mode mode;
795 : :
796 : 9910 : if ((MEM_P (op1) && !TARGET_AVX256_SPLIT_UNALIGNED_LOAD)
797 : 3438 : || (MEM_P (op0) && !TARGET_AVX256_SPLIT_UNALIGNED_STORE))
798 : : {
799 : 9860 : emit_insn (gen_rtx_SET (op0, op1));
800 : 9860 : return;
801 : : }
802 : :
803 : 50 : rtx orig_op0 = NULL_RTX;
804 : 50 : mode = GET_MODE (op0);
805 : 50 : switch (GET_MODE_CLASS (mode))
806 : : {
807 : 33 : case MODE_VECTOR_INT:
808 : 33 : case MODE_INT:
809 : 33 : if (mode != V32QImode)
810 : : {
811 : 7 : if (!MEM_P (op0))
812 : : {
813 : 3 : orig_op0 = op0;
814 : 3 : op0 = gen_reg_rtx (V32QImode);
815 : : }
816 : : else
817 : 4 : op0 = gen_lowpart (V32QImode, op0);
818 : 7 : op1 = gen_lowpart (V32QImode, op1);
819 : 7 : mode = V32QImode;
820 : : }
821 : : break;
822 : : case MODE_VECTOR_FLOAT:
823 : : break;
824 : 0 : default:
825 : 0 : gcc_unreachable ();
826 : : }
827 : :
828 : 50 : switch (mode)
829 : : {
830 : 0 : default:
831 : 0 : gcc_unreachable ();
832 : : case E_V32QImode:
833 : : extract = gen_avx_vextractf128v32qi;
834 : : mode = V16QImode;
835 : : break;
836 : 1 : case E_V16BFmode:
837 : 1 : extract = gen_avx_vextractf128v16bf;
838 : 1 : mode = V8BFmode;
839 : 1 : break;
840 : 0 : case E_V16HFmode:
841 : 0 : extract = gen_avx_vextractf128v16hf;
842 : 0 : mode = V8HFmode;
843 : 0 : break;
844 : 8 : case E_V8SFmode:
845 : 8 : extract = gen_avx_vextractf128v8sf;
846 : 8 : mode = V4SFmode;
847 : 8 : break;
848 : 8 : case E_V4DFmode:
849 : 8 : extract = gen_avx_vextractf128v4df;
850 : 8 : mode = V2DFmode;
851 : 8 : break;
852 : : }
853 : :
854 : 50 : if (MEM_P (op1))
855 : : {
856 : 9 : rtx r = gen_reg_rtx (mode);
857 : 9 : m = adjust_address (op1, mode, 0);
858 : 9 : emit_move_insn (r, m);
859 : 9 : m = adjust_address (op1, mode, 16);
860 : 9 : r = gen_rtx_VEC_CONCAT (GET_MODE (op0), r, m);
861 : 9 : emit_move_insn (op0, r);
862 : : }
863 : 41 : else if (MEM_P (op0))
864 : : {
865 : 41 : m = adjust_address (op0, mode, 0);
866 : 41 : emit_insn (extract (m, op1, const0_rtx));
867 : 41 : m = adjust_address (op0, mode, 16);
868 : 41 : emit_insn (extract (m, copy_rtx (op1), const1_rtx));
869 : : }
870 : : else
871 : 0 : gcc_unreachable ();
872 : :
873 : 50 : if (orig_op0)
874 : 3 : emit_move_insn (orig_op0, gen_lowpart (GET_MODE (orig_op0), op0));
875 : : }
876 : :
877 : : /* Implement the movmisalign patterns for SSE. Non-SSE modes go
878 : : straight to ix86_expand_vector_move. */
879 : : /* Code generation for scalar reg-reg moves of single and double precision data:
880 : : if (x86_sse_partial_reg_dependency == true | x86_sse_split_regs == true)
881 : : movaps reg, reg
882 : : else
883 : : movss reg, reg
884 : : if (x86_sse_partial_reg_dependency == true)
885 : : movapd reg, reg
886 : : else
887 : : movsd reg, reg
888 : :
889 : : Code generation for scalar loads of double precision data:
890 : : if (x86_sse_split_regs == true)
891 : : movlpd mem, reg (gas syntax)
892 : : else
893 : : movsd mem, reg
894 : :
895 : : Code generation for unaligned packed loads of single precision data
896 : : (x86_sse_unaligned_move_optimal overrides x86_sse_partial_reg_dependency):
897 : : if (x86_sse_unaligned_move_optimal)
898 : : movups mem, reg
899 : :
900 : : if (x86_sse_partial_reg_dependency == true)
901 : : {
902 : : xorps reg, reg
903 : : movlps mem, reg
904 : : movhps mem+8, reg
905 : : }
906 : : else
907 : : {
908 : : movlps mem, reg
909 : : movhps mem+8, reg
910 : : }
911 : :
912 : : Code generation for unaligned packed loads of double precision data
913 : : (x86_sse_unaligned_move_optimal overrides x86_sse_split_regs):
914 : : if (x86_sse_unaligned_move_optimal)
915 : : movupd mem, reg
916 : :
917 : : if (x86_sse_split_regs == true)
918 : : {
919 : : movlpd mem, reg
920 : : movhpd mem+8, reg
921 : : }
922 : : else
923 : : {
924 : : movsd mem, reg
925 : : movhpd mem+8, reg
926 : : }
927 : : */
928 : :
929 : : void
930 : 550535 : ix86_expand_vector_move_misalign (machine_mode mode, rtx operands[])
931 : : {
932 : 550535 : rtx op0, op1, m;
933 : :
934 : 550535 : op0 = operands[0];
935 : 550535 : op1 = operands[1];
936 : :
937 : : /* Use unaligned load/store for AVX512 or when optimizing for size. */
938 : 1101070 : if (GET_MODE_SIZE (mode) == 64 || optimize_insn_for_size_p ())
939 : : {
940 : 13771 : emit_insn (gen_rtx_SET (op0, op1));
941 : 13771 : return;
942 : : }
943 : :
944 : 536764 : if (TARGET_AVX)
945 : : {
946 : 46278 : if (GET_MODE_SIZE (mode) == 32)
947 : 9910 : ix86_avx256_split_vector_move_misalign (op0, op1);
948 : : else
949 : : /* Always use 128-bit mov<mode>_internal pattern for AVX. */
950 : 13229 : emit_insn (gen_rtx_SET (op0, op1));
951 : 23139 : return;
952 : : }
953 : :
954 : 513625 : if (TARGET_SSE_UNALIGNED_LOAD_OPTIMAL
955 : 99 : || TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL)
956 : : {
957 : 513526 : emit_insn (gen_rtx_SET (op0, op1));
958 : 513526 : return;
959 : : }
960 : :
961 : : /* ??? If we have typed data, then it would appear that using
962 : : movdqu is the only way to get unaligned data loaded with
963 : : integer type. */
964 : 99 : if (TARGET_SSE2 && GET_MODE_CLASS (mode) == MODE_VECTOR_INT)
965 : : {
966 : 85 : emit_insn (gen_rtx_SET (op0, op1));
967 : 85 : return;
968 : : }
969 : :
970 : 14 : if (MEM_P (op1))
971 : : {
972 : 6 : if (TARGET_SSE2 && mode == V2DFmode)
973 : : {
974 : 2 : rtx zero;
975 : :
976 : : /* When SSE registers are split into halves, we can avoid
977 : : writing to the top half twice. */
978 : 2 : if (TARGET_SSE_SPLIT_REGS)
979 : : {
980 : 2 : emit_clobber (op0);
981 : 2 : zero = op0;
982 : : }
983 : : else
984 : : {
985 : : /* ??? Not sure about the best option for the Intel chips.
986 : : The following would seem to satisfy; the register is
987 : : entirely cleared, breaking the dependency chain. We
988 : : then store to the upper half, with a dependency depth
989 : : of one. A rumor has it that Intel recommends two movsd
990 : : followed by an unpacklpd, but this is unconfirmed. And
991 : : given that the dependency depth of the unpacklpd would
992 : : still be one, I'm not sure why this would be better. */
993 : 0 : zero = CONST0_RTX (V2DFmode);
994 : : }
995 : :
996 : 2 : m = adjust_address (op1, DFmode, 0);
997 : 2 : emit_insn (gen_sse2_loadlpd (op0, zero, m));
998 : 2 : m = adjust_address (op1, DFmode, 8);
999 : 2 : emit_insn (gen_sse2_loadhpd (op0, op0, m));
1000 : 2 : }
1001 : : else
1002 : : {
1003 : 4 : rtx t;
1004 : :
1005 : 4 : if (mode != V4SFmode)
1006 : 0 : t = gen_reg_rtx (V4SFmode);
1007 : : else
1008 : : t = op0;
1009 : :
1010 : 4 : if (TARGET_SSE_PARTIAL_REG_DEPENDENCY)
1011 : 2 : emit_move_insn (t, CONST0_RTX (V4SFmode));
1012 : : else
1013 : 2 : emit_clobber (t);
1014 : :
1015 : 4 : m = adjust_address (op1, V2SFmode, 0);
1016 : 4 : emit_insn (gen_sse_loadlps (t, t, m));
1017 : 4 : m = adjust_address (op1, V2SFmode, 8);
1018 : 4 : emit_insn (gen_sse_loadhps (t, t, m));
1019 : 4 : if (mode != V4SFmode)
1020 : 0 : emit_move_insn (op0, gen_lowpart (mode, t));
1021 : : }
1022 : : }
1023 : 8 : else if (MEM_P (op0))
1024 : : {
1025 : 8 : if (TARGET_SSE2 && mode == V2DFmode)
1026 : : {
1027 : 2 : m = adjust_address (op0, DFmode, 0);
1028 : 2 : emit_insn (gen_sse2_storelpd (m, op1));
1029 : 2 : m = adjust_address (op0, DFmode, 8);
1030 : 2 : emit_insn (gen_sse2_storehpd (m, op1));
1031 : : }
1032 : : else
1033 : : {
1034 : 6 : if (mode != V4SFmode)
1035 : 0 : op1 = gen_lowpart (V4SFmode, op1);
1036 : :
1037 : 6 : m = adjust_address (op0, V2SFmode, 0);
1038 : 6 : emit_insn (gen_sse_storelps (m, op1));
1039 : 6 : m = adjust_address (op0, V2SFmode, 8);
1040 : 6 : emit_insn (gen_sse_storehps (m, copy_rtx (op1)));
1041 : : }
1042 : : }
1043 : : else
1044 : 0 : gcc_unreachable ();
1045 : : }
1046 : :
1047 : : /* Move bits 64:95 to bits 32:63. */
1048 : :
1049 : : void
1050 : 969 : ix86_move_vector_high_sse_to_mmx (rtx op)
1051 : : {
1052 : 969 : rtx mask = gen_rtx_PARALLEL (VOIDmode,
1053 : : gen_rtvec (4, GEN_INT (0), GEN_INT (2),
1054 : : GEN_INT (0), GEN_INT (0)));
1055 : 969 : rtx dest = lowpart_subreg (V4SImode, op, GET_MODE (op));
1056 : 969 : op = gen_rtx_VEC_SELECT (V4SImode, dest, mask);
1057 : 969 : rtx insn = gen_rtx_SET (dest, op);
1058 : 969 : emit_insn (insn);
1059 : 969 : }
1060 : :
1061 : : /* Split MMX pack with signed/unsigned saturation with SSE/SSE2. */
1062 : :
1063 : : void
1064 : 879 : ix86_split_mmx_pack (rtx operands[], enum rtx_code code)
1065 : : {
1066 : 879 : rtx op0 = operands[0];
1067 : 879 : rtx op1 = operands[1];
1068 : 879 : rtx op2 = operands[2];
1069 : 879 : rtx src;
1070 : :
1071 : 879 : machine_mode dmode = GET_MODE (op0);
1072 : 879 : machine_mode smode = GET_MODE (op1);
1073 : 879 : machine_mode inner_dmode = GET_MODE_INNER (dmode);
1074 : 879 : machine_mode inner_smode = GET_MODE_INNER (smode);
1075 : :
1076 : : /* Get the corresponding SSE mode for destination. */
1077 : 879 : int nunits = 16 / GET_MODE_SIZE (inner_dmode);
1078 : 1758 : machine_mode sse_dmode = mode_for_vector (GET_MODE_INNER (dmode),
1079 : 879 : nunits).require ();
1080 : 879 : machine_mode sse_half_dmode = mode_for_vector (GET_MODE_INNER (dmode),
1081 : 1758 : nunits / 2).require ();
1082 : :
1083 : : /* Get the corresponding SSE mode for source. */
1084 : 879 : nunits = 16 / GET_MODE_SIZE (inner_smode);
1085 : 1758 : machine_mode sse_smode = mode_for_vector (GET_MODE_INNER (smode),
1086 : 879 : nunits).require ();
1087 : :
1088 : : /* Generate SSE pack with signed/unsigned saturation. */
1089 : 879 : rtx dest = lowpart_subreg (sse_dmode, op0, GET_MODE (op0));
1090 : 879 : op1 = lowpart_subreg (sse_smode, op1, GET_MODE (op1));
1091 : 879 : op2 = lowpart_subreg (sse_smode, op2, GET_MODE (op2));
1092 : :
1093 : : /* paskusdw/packuswb does unsigned saturation of a signed source
1094 : : which is different from generic us_truncate RTX. */
1095 : 879 : if (code == US_TRUNCATE)
1096 : 776 : src = gen_rtx_UNSPEC (sse_dmode,
1097 : : gen_rtvec (2, op1, op2),
1098 : : UNSPEC_US_TRUNCATE);
1099 : : else
1100 : : {
1101 : 103 : op1 = gen_rtx_fmt_e (code, sse_half_dmode, op1);
1102 : 103 : op2 = gen_rtx_fmt_e (code, sse_half_dmode, op2);
1103 : 103 : src = gen_rtx_VEC_CONCAT (sse_dmode, op1, op2);
1104 : : }
1105 : :
1106 : 879 : emit_move_insn (dest, src);
1107 : :
1108 : 879 : ix86_move_vector_high_sse_to_mmx (op0);
1109 : 879 : }
1110 : :
1111 : : /* Split MMX punpcklXX/punpckhXX with SSE punpcklXX. This is also used
1112 : : for a full unpack of OPERANDS[1] and OPERANDS[2] into a wider
1113 : : OPERANDS[0]. */
1114 : :
1115 : : void
1116 : 5188 : ix86_split_mmx_punpck (rtx operands[], bool high_p)
1117 : : {
1118 : 5188 : rtx op0 = operands[0];
1119 : 5188 : rtx op1 = operands[1];
1120 : 5188 : rtx op2 = operands[2];
1121 : 5188 : machine_mode mode = GET_MODE (op1);
1122 : 5188 : rtx mask;
1123 : : /* The corresponding SSE mode. */
1124 : 5188 : machine_mode sse_mode, double_sse_mode;
1125 : :
1126 : 5188 : switch (mode)
1127 : : {
1128 : 1595 : case E_V8QImode:
1129 : 1595 : case E_V4QImode:
1130 : 1595 : case E_V2QImode:
1131 : 1595 : sse_mode = V16QImode;
1132 : 1595 : double_sse_mode = V32QImode;
1133 : 1595 : mask = gen_rtx_PARALLEL (VOIDmode,
1134 : : gen_rtvec (16,
1135 : : GEN_INT (0), GEN_INT (16),
1136 : : GEN_INT (1), GEN_INT (17),
1137 : : GEN_INT (2), GEN_INT (18),
1138 : : GEN_INT (3), GEN_INT (19),
1139 : : GEN_INT (4), GEN_INT (20),
1140 : : GEN_INT (5), GEN_INT (21),
1141 : : GEN_INT (6), GEN_INT (22),
1142 : : GEN_INT (7), GEN_INT (23)));
1143 : 1595 : break;
1144 : :
1145 : 2798 : case E_V4HImode:
1146 : 2798 : case E_V2HImode:
1147 : 2798 : sse_mode = V8HImode;
1148 : 2798 : double_sse_mode = V16HImode;
1149 : 2798 : mask = gen_rtx_PARALLEL (VOIDmode,
1150 : : gen_rtvec (8,
1151 : : GEN_INT (0), GEN_INT (8),
1152 : : GEN_INT (1), GEN_INT (9),
1153 : : GEN_INT (2), GEN_INT (10),
1154 : : GEN_INT (3), GEN_INT (11)));
1155 : 2798 : break;
1156 : :
1157 : 688 : case E_V2SImode:
1158 : 688 : sse_mode = V4SImode;
1159 : 688 : double_sse_mode = V8SImode;
1160 : 688 : mask = gen_rtx_PARALLEL (VOIDmode,
1161 : : gen_rtvec (4,
1162 : : GEN_INT (0), GEN_INT (4),
1163 : : GEN_INT (1), GEN_INT (5)));
1164 : 688 : break;
1165 : :
1166 : 107 : case E_V2SFmode:
1167 : 107 : sse_mode = V4SFmode;
1168 : 107 : double_sse_mode = V8SFmode;
1169 : 107 : mask = gen_rtx_PARALLEL (VOIDmode,
1170 : : gen_rtvec (4,
1171 : : GEN_INT (0), GEN_INT (4),
1172 : : GEN_INT (1), GEN_INT (5)));
1173 : 107 : break;
1174 : :
1175 : 0 : default:
1176 : 0 : gcc_unreachable ();
1177 : : }
1178 : :
1179 : : /* Generate SSE punpcklXX. */
1180 : 5188 : rtx dest = lowpart_subreg (sse_mode, op0, GET_MODE (op0));
1181 : 5188 : op1 = lowpart_subreg (sse_mode, op1, GET_MODE (op1));
1182 : 5188 : op2 = lowpart_subreg (sse_mode, op2, GET_MODE (op2));
1183 : :
1184 : 5188 : op1 = gen_rtx_VEC_CONCAT (double_sse_mode, op1, op2);
1185 : 5188 : op2 = gen_rtx_VEC_SELECT (sse_mode, op1, mask);
1186 : 5188 : rtx insn = gen_rtx_SET (dest, op2);
1187 : 5188 : emit_insn (insn);
1188 : :
1189 : : /* Move high bits to low bits. */
1190 : 5188 : if (high_p)
1191 : : {
1192 : 2000 : if (sse_mode == V4SFmode)
1193 : : {
1194 : 47 : mask = gen_rtx_PARALLEL (VOIDmode,
1195 : : gen_rtvec (4, GEN_INT (2), GEN_INT (3),
1196 : : GEN_INT (4), GEN_INT (5)));
1197 : 47 : op2 = gen_rtx_VEC_CONCAT (V8SFmode, dest, dest);
1198 : 47 : op1 = gen_rtx_VEC_SELECT (V4SFmode, op2, mask);
1199 : : }
1200 : : else
1201 : : {
1202 : 1953 : int sz = GET_MODE_SIZE (mode);
1203 : :
1204 : 1953 : if (sz == 4)
1205 : 300 : mask = gen_rtx_PARALLEL (VOIDmode,
1206 : : gen_rtvec (4, GEN_INT (1), GEN_INT (0),
1207 : : GEN_INT (0), GEN_INT (1)));
1208 : 1653 : else if (sz == 8)
1209 : 1653 : mask = gen_rtx_PARALLEL (VOIDmode,
1210 : : gen_rtvec (4, GEN_INT (2), GEN_INT (3),
1211 : : GEN_INT (0), GEN_INT (1)));
1212 : : else
1213 : 0 : gcc_unreachable ();
1214 : :
1215 : 1953 : dest = lowpart_subreg (V4SImode, dest, GET_MODE (dest));
1216 : 1953 : op1 = gen_rtx_VEC_SELECT (V4SImode, dest, mask);
1217 : : }
1218 : :
1219 : 2000 : insn = gen_rtx_SET (dest, op1);
1220 : 2000 : emit_insn (insn);
1221 : : }
1222 : 5188 : }
1223 : :
1224 : : /* Helper function of ix86_fixup_binary_operands to canonicalize
1225 : : operand order. Returns true if the operands should be swapped. */
1226 : :
1227 : : static bool
1228 : 71295725 : ix86_swap_binary_operands_p (enum rtx_code code, machine_mode mode,
1229 : : rtx operands[])
1230 : : {
1231 : 71295725 : rtx dst = operands[0];
1232 : 71295725 : rtx src1 = operands[1];
1233 : 71295725 : rtx src2 = operands[2];
1234 : :
1235 : : /* If the operation is not commutative, we can't do anything. */
1236 : 71295725 : if (GET_RTX_CLASS (code) != RTX_COMM_ARITH
1237 : 8871457 : && GET_RTX_CLASS (code) != RTX_COMM_COMPARE)
1238 : : return false;
1239 : :
1240 : : /* Highest priority is that src1 should match dst. */
1241 : 62428436 : if (rtx_equal_p (dst, src1))
1242 : : return false;
1243 : 46919540 : if (rtx_equal_p (dst, src2))
1244 : : return true;
1245 : :
1246 : : /* Next highest priority is that immediate constants come second. */
1247 : 46863873 : if (immediate_operand (src2, mode))
1248 : : return false;
1249 : 8451228 : if (immediate_operand (src1, mode))
1250 : : return true;
1251 : :
1252 : : /* Lowest priority is that memory references should come second. */
1253 : 8451228 : if (MEM_P (src2))
1254 : : return false;
1255 : 7688402 : if (MEM_P (src1))
1256 : : return true;
1257 : :
1258 : : return false;
1259 : : }
1260 : :
1261 : : /* Fix up OPERANDS to satisfy ix86_binary_operator_ok. Return the
1262 : : destination to use for the operation. If different from the true
1263 : : destination in operands[0], a copy operation will be required except
1264 : : under TARGET_APX_NDD. */
1265 : :
1266 : : rtx
1267 : 12231836 : ix86_fixup_binary_operands (enum rtx_code code, machine_mode mode,
1268 : : rtx operands[], bool use_ndd)
1269 : : {
1270 : 12231836 : rtx dst = operands[0];
1271 : 12231836 : rtx src1 = operands[1];
1272 : 12231836 : rtx src2 = operands[2];
1273 : :
1274 : : /* Canonicalize operand order. */
1275 : 12231836 : if (ix86_swap_binary_operands_p (code, mode, operands))
1276 : : {
1277 : : /* It is invalid to swap operands of different modes. */
1278 : 77908 : gcc_assert (GET_MODE (src1) == GET_MODE (src2));
1279 : :
1280 : : std::swap (src1, src2);
1281 : : }
1282 : :
1283 : : /* Both source operands cannot be in memory. */
1284 : 12231836 : if (MEM_P (src1) && MEM_P (src2))
1285 : : {
1286 : : /* Optimization: Only read from memory once. */
1287 : 75449 : if (rtx_equal_p (src1, src2))
1288 : : {
1289 : 9 : src2 = force_reg (mode, src2);
1290 : 9 : src1 = src2;
1291 : : }
1292 : 75440 : else if (rtx_equal_p (dst, src1))
1293 : 2879 : src2 = force_reg (mode, src2);
1294 : : else
1295 : 72561 : src1 = force_reg (mode, src1);
1296 : : }
1297 : :
1298 : : /* If the destination is memory, and we do not have matching source
1299 : : operands, do things in registers. */
1300 : 12231836 : if (MEM_P (dst) && !rtx_equal_p (dst, src1))
1301 : 460687 : dst = gen_reg_rtx (mode);
1302 : :
1303 : : /* Source 1 cannot be a constant. */
1304 : 12231836 : if (CONSTANT_P (src1))
1305 : 616 : src1 = force_reg (mode, src1);
1306 : :
1307 : : /* Source 1 cannot be a non-matching memory. */
1308 : 12231836 : if (!use_ndd && MEM_P (src1) && !rtx_equal_p (dst, src1))
1309 : 425979 : src1 = force_reg (mode, src1);
1310 : :
1311 : : /* Improve address combine. */
1312 : 12231836 : if (code == PLUS
1313 : 9024285 : && GET_MODE_CLASS (mode) == MODE_INT
1314 : 8930058 : && MEM_P (src2))
1315 : 180035 : src2 = force_reg (mode, src2);
1316 : :
1317 : 12231836 : operands[1] = src1;
1318 : 12231836 : operands[2] = src2;
1319 : 12231836 : return dst;
1320 : : }
1321 : :
1322 : : /* Similarly, but assume that the destination has already been
1323 : : set up properly. */
1324 : :
1325 : : void
1326 : 218075 : ix86_fixup_binary_operands_no_copy (enum rtx_code code,
1327 : : machine_mode mode, rtx operands[],
1328 : : bool use_ndd)
1329 : : {
1330 : 218075 : rtx dst = ix86_fixup_binary_operands (code, mode, operands, use_ndd);
1331 : 218075 : gcc_assert (dst == operands[0]);
1332 : 218075 : }
1333 : :
1334 : : /* Attempt to expand a binary operator. Make the expansion closer to the
1335 : : actual machine, then just general_operand, which will allow 3 separate
1336 : : memory references (one output, two input) in a single insn. */
1337 : :
1338 : : void
1339 : 12013605 : ix86_expand_binary_operator (enum rtx_code code, machine_mode mode,
1340 : : rtx operands[], bool use_ndd)
1341 : : {
1342 : 12013605 : rtx src1, src2, dst, op, clob;
1343 : :
1344 : 12013605 : dst = ix86_fixup_binary_operands (code, mode, operands, use_ndd);
1345 : 12013605 : src1 = operands[1];
1346 : 12013605 : src2 = operands[2];
1347 : :
1348 : : /* Emit the instruction. */
1349 : :
1350 : 12013605 : op = gen_rtx_SET (dst, gen_rtx_fmt_ee (code, mode, src1, src2));
1351 : :
1352 : 12013605 : if (reload_completed
1353 : 77813 : && code == PLUS
1354 : 821 : && !rtx_equal_p (dst, src1)
1355 : 12013605 : && !use_ndd)
1356 : : {
1357 : : /* This is going to be an LEA; avoid splitting it later. */
1358 : 0 : emit_insn (op);
1359 : : }
1360 : : else
1361 : : {
1362 : 12013605 : clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
1363 : 12013605 : emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, op, clob)));
1364 : : }
1365 : :
1366 : : /* Fix up the destination if needed. */
1367 : 12013605 : if (dst != operands[0])
1368 : 460678 : emit_move_insn (operands[0], dst);
1369 : 12013605 : }
1370 : :
1371 : : /* Expand vector logical operation CODE (AND, IOR, XOR) in MODE with
1372 : : the given OPERANDS. */
1373 : :
1374 : : void
1375 : 37594 : ix86_expand_vector_logical_operator (enum rtx_code code, machine_mode mode,
1376 : : rtx operands[])
1377 : : {
1378 : 37594 : rtx op1 = NULL_RTX, op2 = NULL_RTX;
1379 : 37594 : if (SUBREG_P (operands[1]))
1380 : : {
1381 : 693 : op1 = operands[1];
1382 : 693 : op2 = operands[2];
1383 : : }
1384 : 36901 : else if (SUBREG_P (operands[2]))
1385 : : {
1386 : : op1 = operands[2];
1387 : : op2 = operands[1];
1388 : : }
1389 : : /* Optimize (__m128i) d | (__m128i) e and similar code
1390 : : when d and e are float vectors into float vector logical
1391 : : insn. In C/C++ without using intrinsics there is no other way
1392 : : to express vector logical operation on float vectors than
1393 : : to cast them temporarily to integer vectors. */
1394 : 2999 : if (op1
1395 : 2999 : && !TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL
1396 : 2999 : && (SUBREG_P (op2) || GET_CODE (op2) == CONST_VECTOR)
1397 : 295 : && GET_MODE_CLASS (GET_MODE (SUBREG_REG (op1))) == MODE_VECTOR_FLOAT
1398 : 303 : && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op1))) == GET_MODE_SIZE (mode)
1399 : 101 : && SUBREG_BYTE (op1) == 0
1400 : 101 : && (GET_CODE (op2) == CONST_VECTOR
1401 : 1 : || (GET_MODE (SUBREG_REG (op1)) == GET_MODE (SUBREG_REG (op2))
1402 : 1 : && SUBREG_BYTE (op2) == 0))
1403 : 101 : && can_create_pseudo_p ())
1404 : : {
1405 : 101 : rtx dst;
1406 : 101 : switch (GET_MODE (SUBREG_REG (op1)))
1407 : : {
1408 : 17 : case E_V4SFmode:
1409 : 17 : case E_V8SFmode:
1410 : 17 : case E_V16SFmode:
1411 : 17 : case E_V2DFmode:
1412 : 17 : case E_V4DFmode:
1413 : 17 : case E_V8DFmode:
1414 : 17 : dst = gen_reg_rtx (GET_MODE (SUBREG_REG (op1)));
1415 : 17 : if (GET_CODE (op2) == CONST_VECTOR)
1416 : : {
1417 : 16 : op2 = gen_lowpart (GET_MODE (dst), op2);
1418 : 16 : op2 = force_reg (GET_MODE (dst), op2);
1419 : : }
1420 : : else
1421 : : {
1422 : 1 : op1 = operands[1];
1423 : 1 : op2 = SUBREG_REG (operands[2]);
1424 : 1 : if (!vector_operand (op2, GET_MODE (dst)))
1425 : 0 : op2 = force_reg (GET_MODE (dst), op2);
1426 : : }
1427 : 17 : op1 = SUBREG_REG (op1);
1428 : 17 : if (!vector_operand (op1, GET_MODE (dst)))
1429 : 0 : op1 = force_reg (GET_MODE (dst), op1);
1430 : 17 : emit_insn (gen_rtx_SET (dst,
1431 : : gen_rtx_fmt_ee (code, GET_MODE (dst),
1432 : : op1, op2)));
1433 : 17 : emit_move_insn (operands[0], gen_lowpart (mode, dst));
1434 : 17 : return;
1435 : : default:
1436 : : break;
1437 : : }
1438 : : }
1439 : 37577 : if (!vector_operand (operands[1], mode))
1440 : 0 : operands[1] = force_reg (mode, operands[1]);
1441 : 37577 : if (!vector_operand (operands[2], mode))
1442 : 3053 : operands[2] = force_reg (mode, operands[2]);
1443 : 37577 : ix86_fixup_binary_operands_no_copy (code, mode, operands);
1444 : 37577 : emit_insn (gen_rtx_SET (operands[0],
1445 : : gen_rtx_fmt_ee (code, mode, operands[1],
1446 : : operands[2])));
1447 : : }
1448 : :
1449 : : /* Return TRUE or FALSE depending on whether the binary operator meets the
1450 : : appropriate constraints. */
1451 : :
1452 : : bool
1453 : 59549204 : ix86_binary_operator_ok (enum rtx_code code, machine_mode mode,
1454 : : rtx operands[3], bool use_ndd)
1455 : : {
1456 : 59549204 : rtx dst = operands[0];
1457 : 59549204 : rtx src1 = operands[1];
1458 : 59549204 : rtx src2 = operands[2];
1459 : :
1460 : : /* Both source operands cannot be in memory. */
1461 : 56037472 : if ((MEM_P (src1) || bcst_mem_operand (src1, mode))
1462 : 59549378 : && (MEM_P (src2) || bcst_mem_operand (src2, mode)))
1463 : 485315 : return false;
1464 : :
1465 : : /* Canonicalize operand order for commutative operators. */
1466 : 59063889 : if (ix86_swap_binary_operands_p (code, mode, operands))
1467 : 217569 : std::swap (src1, src2);
1468 : :
1469 : : /* If the destination is memory, we must have a matching source operand. */
1470 : 59063889 : if (MEM_P (dst) && !rtx_equal_p (dst, src1))
1471 : : return false;
1472 : :
1473 : : /* Source 1 cannot be a constant. */
1474 : 57235222 : if (CONSTANT_P (src1))
1475 : : return false;
1476 : :
1477 : : /* Source 1 cannot be a non-matching memory. */
1478 : 57233680 : if (!use_ndd && MEM_P (src1) && !rtx_equal_p (dst, src1))
1479 : : /* Support "andhi/andsi/anddi" as a zero-extending move. */
1480 : 1996146 : return (code == AND
1481 : 230971 : && (mode == HImode
1482 : 230971 : || mode == SImode
1483 : 137251 : || (TARGET_64BIT && mode == DImode))
1484 : 2142456 : && satisfies_constraint_L (src2));
1485 : :
1486 : : return true;
1487 : : }
1488 : :
1489 : : /* Attempt to expand a unary operator. Make the expansion closer to the
1490 : : actual machine, then just general_operand, which will allow 2 separate
1491 : : memory references (one output, one input) in a single insn. */
1492 : :
1493 : : void
1494 : 108950 : ix86_expand_unary_operator (enum rtx_code code, machine_mode mode,
1495 : : rtx operands[], bool use_ndd)
1496 : : {
1497 : 108950 : bool matching_memory = false;
1498 : 108950 : rtx src, dst, op, clob;
1499 : :
1500 : 108950 : dst = operands[0];
1501 : 108950 : src = operands[1];
1502 : :
1503 : : /* If the destination is memory, and we do not have matching source
1504 : : operands, do things in registers. */
1505 : 108950 : if (MEM_P (dst))
1506 : : {
1507 : 3588 : if (rtx_equal_p (dst, src))
1508 : : matching_memory = true;
1509 : : else
1510 : 3351 : dst = gen_reg_rtx (mode);
1511 : : }
1512 : :
1513 : : /* When source operand is memory, destination must match. */
1514 : 108950 : if (!use_ndd && MEM_P (src) && !matching_memory)
1515 : 3767 : src = force_reg (mode, src);
1516 : :
1517 : : /* Emit the instruction. */
1518 : :
1519 : 108950 : op = gen_rtx_SET (dst, gen_rtx_fmt_e (code, mode, src));
1520 : :
1521 : 108950 : if (code == NOT)
1522 : 61181 : emit_insn (op);
1523 : : else
1524 : : {
1525 : 47769 : clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
1526 : 47769 : emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, op, clob)));
1527 : : }
1528 : :
1529 : : /* Fix up the destination if needed. */
1530 : 108950 : if (dst != operands[0])
1531 : 3351 : emit_move_insn (operands[0], dst);
1532 : 108950 : }
1533 : :
1534 : : /* Return TRUE or FALSE depending on whether the unary operator meets the
1535 : : appropriate constraints. */
1536 : :
1537 : : bool
1538 : 583301 : ix86_unary_operator_ok (enum rtx_code,
1539 : : machine_mode,
1540 : : rtx operands[2],
1541 : : bool use_ndd)
1542 : : {
1543 : : /* If one of operands is memory, source and destination must match. */
1544 : 583301 : if ((MEM_P (operands[0])
1545 : 567547 : || (!use_ndd && MEM_P (operands[1])))
1546 : 596267 : && ! rtx_equal_p (operands[0], operands[1]))
1547 : : return false;
1548 : : return true;
1549 : : }
1550 : :
1551 : : /* Predict just emitted jump instruction to be taken with probability PROB. */
1552 : :
1553 : : static void
1554 : 34375 : predict_jump (int prob)
1555 : : {
1556 : 34375 : rtx_insn *insn = get_last_insn ();
1557 : 34375 : gcc_assert (JUMP_P (insn));
1558 : 34375 : add_reg_br_prob_note (insn, profile_probability::from_reg_br_prob_base (prob));
1559 : 34375 : }
1560 : :
1561 : : /* Split 32bit/64bit divmod with 8bit unsigned divmod if dividend and
1562 : : divisor are within the range [0-255]. */
1563 : :
1564 : : void
1565 : 27 : ix86_split_idivmod (machine_mode mode, rtx operands[],
1566 : : bool unsigned_p)
1567 : : {
1568 : 27 : rtx_code_label *end_label, *qimode_label;
1569 : 27 : rtx div, mod;
1570 : 27 : rtx_insn *insn;
1571 : 27 : rtx scratch, tmp0, tmp1, tmp2;
1572 : 27 : rtx (*gen_divmod4_1) (rtx, rtx, rtx, rtx);
1573 : :
1574 : 27 : operands[2] = force_reg (mode, operands[2]);
1575 : 27 : operands[3] = force_reg (mode, operands[3]);
1576 : :
1577 : 27 : switch (mode)
1578 : : {
1579 : 20 : case E_SImode:
1580 : 20 : if (GET_MODE (operands[0]) == SImode)
1581 : : {
1582 : 16 : if (GET_MODE (operands[1]) == SImode)
1583 : 14 : gen_divmod4_1 = unsigned_p ? gen_udivmodsi4_1 : gen_divmodsi4_1;
1584 : : else
1585 : 2 : gen_divmod4_1
1586 : 2 : = unsigned_p ? gen_udivmodsi4_zext_2 : gen_divmodsi4_zext_2;
1587 : : }
1588 : : else
1589 : 4 : gen_divmod4_1
1590 : 4 : = unsigned_p ? gen_udivmodsi4_zext_1 : gen_divmodsi4_zext_1;
1591 : : break;
1592 : :
1593 : 7 : case E_DImode:
1594 : 7 : gen_divmod4_1 = unsigned_p ? gen_udivmoddi4_1 : gen_divmoddi4_1;
1595 : : break;
1596 : :
1597 : 0 : default:
1598 : 0 : gcc_unreachable ();
1599 : : }
1600 : :
1601 : 27 : end_label = gen_label_rtx ();
1602 : 27 : qimode_label = gen_label_rtx ();
1603 : :
1604 : 27 : scratch = gen_reg_rtx (mode);
1605 : :
1606 : : /* Use 8bit unsigned divimod if dividend and divisor are within
1607 : : the range [0-255]. */
1608 : 27 : emit_move_insn (scratch, operands[2]);
1609 : 27 : scratch = expand_simple_binop (mode, IOR, scratch, operands[3],
1610 : : scratch, 1, OPTAB_DIRECT);
1611 : 27 : emit_insn (gen_test_ccno_1 (mode, scratch, GEN_INT (-0x100)));
1612 : 27 : tmp0 = gen_rtx_REG (CCNOmode, FLAGS_REG);
1613 : 27 : tmp0 = gen_rtx_EQ (VOIDmode, tmp0, const0_rtx);
1614 : 27 : tmp0 = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp0,
1615 : : gen_rtx_LABEL_REF (VOIDmode, qimode_label),
1616 : : pc_rtx);
1617 : 27 : insn = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp0));
1618 : 27 : predict_jump (REG_BR_PROB_BASE * 50 / 100);
1619 : 27 : JUMP_LABEL (insn) = qimode_label;
1620 : :
1621 : : /* Generate original signed/unsigned divimod. */
1622 : 27 : emit_insn (gen_divmod4_1 (operands[0], operands[1],
1623 : : operands[2], operands[3]));
1624 : :
1625 : : /* Branch to the end. */
1626 : 27 : emit_jump_insn (gen_jump (end_label));
1627 : 27 : emit_barrier ();
1628 : :
1629 : : /* Generate 8bit unsigned divide. */
1630 : 27 : emit_label (qimode_label);
1631 : : /* Don't use operands[0] for result of 8bit divide since not all
1632 : : registers support QImode ZERO_EXTRACT. */
1633 : 27 : tmp0 = lowpart_subreg (HImode, scratch, mode);
1634 : 27 : tmp1 = lowpart_subreg (HImode, operands[2], mode);
1635 : 27 : tmp2 = lowpart_subreg (QImode, operands[3], mode);
1636 : 27 : emit_insn (gen_udivmodhiqi3 (tmp0, tmp1, tmp2));
1637 : :
1638 : 27 : if (unsigned_p)
1639 : : {
1640 : 12 : div = gen_rtx_UDIV (mode, operands[2], operands[3]);
1641 : 12 : mod = gen_rtx_UMOD (mode, operands[2], operands[3]);
1642 : : }
1643 : : else
1644 : : {
1645 : 15 : div = gen_rtx_DIV (mode, operands[2], operands[3]);
1646 : 15 : mod = gen_rtx_MOD (mode, operands[2], operands[3]);
1647 : : }
1648 : 27 : if (mode == SImode)
1649 : : {
1650 : 20 : if (GET_MODE (operands[0]) != SImode)
1651 : 4 : div = gen_rtx_ZERO_EXTEND (DImode, div);
1652 : 20 : if (GET_MODE (operands[1]) != SImode)
1653 : 2 : mod = gen_rtx_ZERO_EXTEND (DImode, mod);
1654 : : }
1655 : :
1656 : : /* Extract remainder from AH. */
1657 : 27 : scratch = gen_lowpart (GET_MODE (operands[1]), scratch);
1658 : 27 : tmp1 = gen_rtx_ZERO_EXTRACT (GET_MODE (operands[1]), scratch,
1659 : : GEN_INT (8), GEN_INT (8));
1660 : 27 : insn = emit_move_insn (operands[1], tmp1);
1661 : 27 : set_unique_reg_note (insn, REG_EQUAL, mod);
1662 : :
1663 : : /* Zero extend quotient from AL. */
1664 : 27 : tmp1 = gen_lowpart (QImode, tmp0);
1665 : 27 : insn = emit_insn (gen_extend_insn
1666 : 27 : (operands[0], tmp1,
1667 : 27 : GET_MODE (operands[0]), QImode, 1));
1668 : 27 : set_unique_reg_note (insn, REG_EQUAL, div);
1669 : :
1670 : 27 : emit_label (end_label);
1671 : 27 : }
1672 : :
1673 : : /* Emit x86 binary operand CODE in mode MODE, where the first operand
1674 : : matches destination. RTX includes clobber of FLAGS_REG. */
1675 : :
1676 : : void
1677 : 4362 : ix86_emit_binop (enum rtx_code code, machine_mode mode,
1678 : : rtx dst, rtx src)
1679 : : {
1680 : 4362 : rtx op, clob;
1681 : :
1682 : 4362 : op = gen_rtx_SET (dst, gen_rtx_fmt_ee (code, mode, dst, src));
1683 : 4362 : clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
1684 : :
1685 : 4362 : emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, op, clob)));
1686 : 4362 : }
1687 : :
1688 : : /* Return true if regno1 def is nearest to the insn. */
1689 : :
1690 : : static bool
1691 : 15 : find_nearest_reg_def (rtx_insn *insn, int regno1, int regno2)
1692 : : {
1693 : 15 : rtx_insn *prev = insn;
1694 : 15 : rtx_insn *start = BB_HEAD (BLOCK_FOR_INSN (insn));
1695 : :
1696 : 15 : if (insn == start)
1697 : : return false;
1698 : 40 : while (prev && prev != start)
1699 : : {
1700 : 30 : if (!INSN_P (prev) || !NONDEBUG_INSN_P (prev))
1701 : : {
1702 : 10 : prev = PREV_INSN (prev);
1703 : 10 : continue;
1704 : : }
1705 : 20 : if (insn_defines_reg (regno1, INVALID_REGNUM, prev))
1706 : : return true;
1707 : 15 : else if (insn_defines_reg (regno2, INVALID_REGNUM, prev))
1708 : : return false;
1709 : 15 : prev = PREV_INSN (prev);
1710 : : }
1711 : :
1712 : : /* None of the regs is defined in the bb. */
1713 : : return false;
1714 : : }
1715 : :
1716 : : /* INSN_UID of the last insn emitted by zero store peephole2s. */
1717 : : int ix86_last_zero_store_uid;
1718 : :
1719 : : /* Split lea instructions into a sequence of instructions
1720 : : which are executed on ALU to avoid AGU stalls.
1721 : : It is assumed that it is allowed to clobber flags register
1722 : : at lea position. */
1723 : :
1724 : : void
1725 : 2018 : ix86_split_lea_for_addr (rtx_insn *insn, rtx operands[], machine_mode mode)
1726 : : {
1727 : 2018 : unsigned int regno0, regno1, regno2;
1728 : 2018 : struct ix86_address parts;
1729 : 2018 : rtx target, tmp;
1730 : 2018 : int ok, adds;
1731 : :
1732 : 2018 : ok = ix86_decompose_address (operands[1], &parts);
1733 : 2018 : gcc_assert (ok);
1734 : :
1735 : 2018 : target = gen_lowpart (mode, operands[0]);
1736 : :
1737 : 2018 : regno0 = true_regnum (target);
1738 : 2018 : regno1 = INVALID_REGNUM;
1739 : 2018 : regno2 = INVALID_REGNUM;
1740 : :
1741 : 2018 : if (parts.base)
1742 : : {
1743 : 2009 : parts.base = gen_lowpart (mode, parts.base);
1744 : 2009 : regno1 = true_regnum (parts.base);
1745 : : }
1746 : :
1747 : 2018 : if (parts.index)
1748 : : {
1749 : 2013 : parts.index = gen_lowpart (mode, parts.index);
1750 : 2013 : regno2 = true_regnum (parts.index);
1751 : : }
1752 : :
1753 : 2018 : if (parts.disp)
1754 : 80 : parts.disp = gen_lowpart (mode, parts.disp);
1755 : :
1756 : 2018 : if (parts.scale > 1)
1757 : : {
1758 : : /* Case r1 = r1 + ... */
1759 : 13 : if (regno1 == regno0)
1760 : : {
1761 : : /* If we have a case r1 = r1 + C * r2 then we
1762 : : should use multiplication which is very
1763 : : expensive. Assume cost model is wrong if we
1764 : : have such case here. */
1765 : 0 : gcc_assert (regno2 != regno0);
1766 : :
1767 : 0 : for (adds = parts.scale; adds > 0; adds--)
1768 : 0 : ix86_emit_binop (PLUS, mode, target, parts.index);
1769 : : }
1770 : : else
1771 : : {
1772 : : /* r1 = r2 + r3 * C case. Need to move r3 into r1. */
1773 : 13 : if (regno0 != regno2)
1774 : 9 : emit_insn (gen_rtx_SET (target, parts.index));
1775 : :
1776 : : /* Use shift for scaling, but emit it as MULT instead
1777 : : to avoid it being immediately peephole2 optimized back
1778 : : into lea. */
1779 : 13 : ix86_emit_binop (MULT, mode, target, GEN_INT (parts.scale));
1780 : :
1781 : 13 : if (parts.base)
1782 : 4 : ix86_emit_binop (PLUS, mode, target, parts.base);
1783 : :
1784 : 13 : if (parts.disp && parts.disp != const0_rtx)
1785 : 3 : ix86_emit_binop (PLUS, mode, target, parts.disp);
1786 : : }
1787 : : }
1788 : 2005 : else if (!parts.base && !parts.index)
1789 : : {
1790 : 0 : gcc_assert(parts.disp);
1791 : 0 : emit_insn (gen_rtx_SET (target, parts.disp));
1792 : : }
1793 : : else
1794 : : {
1795 : 2005 : if (!parts.base)
1796 : : {
1797 : 0 : if (regno0 != regno2)
1798 : 0 : emit_insn (gen_rtx_SET (target, parts.index));
1799 : : }
1800 : 2005 : else if (!parts.index)
1801 : : {
1802 : 5 : if (regno0 != regno1)
1803 : 3 : emit_insn (gen_rtx_SET (target, parts.base));
1804 : : }
1805 : : else
1806 : : {
1807 : 2000 : if (regno0 == regno1)
1808 : : tmp = parts.index;
1809 : 846 : else if (regno0 == regno2)
1810 : : tmp = parts.base;
1811 : : else
1812 : : {
1813 : 15 : rtx tmp1;
1814 : :
1815 : : /* Find better operand for SET instruction, depending
1816 : : on which definition is farther from the insn. */
1817 : 15 : if (find_nearest_reg_def (insn, regno1, regno2))
1818 : 5 : tmp = parts.index, tmp1 = parts.base;
1819 : : else
1820 : 10 : tmp = parts.base, tmp1 = parts.index;
1821 : :
1822 : 15 : emit_insn (gen_rtx_SET (target, tmp));
1823 : :
1824 : 15 : if (parts.disp && parts.disp != const0_rtx)
1825 : 0 : ix86_emit_binop (PLUS, mode, target, parts.disp);
1826 : :
1827 : 15 : ix86_emit_binop (PLUS, mode, target, tmp1);
1828 : 15 : return;
1829 : : }
1830 : :
1831 : 1985 : ix86_emit_binop (PLUS, mode, target, tmp);
1832 : : }
1833 : :
1834 : 1990 : if (parts.disp && parts.disp != const0_rtx)
1835 : 6 : ix86_emit_binop (PLUS, mode, target, parts.disp);
1836 : : }
1837 : : }
1838 : :
1839 : : /* Post-reload splitter for converting an SF or DFmode value in an
1840 : : SSE register into an unsigned SImode. */
1841 : :
1842 : : void
1843 : 0 : ix86_split_convert_uns_si_sse (rtx operands[])
1844 : : {
1845 : 0 : machine_mode vecmode;
1846 : 0 : rtx value, large, zero_or_two31, input, two31, x;
1847 : :
1848 : 0 : large = operands[1];
1849 : 0 : zero_or_two31 = operands[2];
1850 : 0 : input = operands[3];
1851 : 0 : two31 = operands[4];
1852 : 0 : vecmode = GET_MODE (large);
1853 : 0 : value = gen_rtx_REG (vecmode, REGNO (operands[0]));
1854 : :
1855 : : /* Load up the value into the low element. We must ensure that the other
1856 : : elements are valid floats -- zero is the easiest such value. */
1857 : 0 : if (MEM_P (input))
1858 : : {
1859 : 0 : if (vecmode == V4SFmode)
1860 : 0 : emit_insn (gen_vec_setv4sf_0 (value, CONST0_RTX (V4SFmode), input));
1861 : : else
1862 : 0 : emit_insn (gen_sse2_loadlpd (value, CONST0_RTX (V2DFmode), input));
1863 : : }
1864 : : else
1865 : : {
1866 : 0 : input = gen_rtx_REG (vecmode, REGNO (input));
1867 : 0 : emit_move_insn (value, CONST0_RTX (vecmode));
1868 : 0 : if (vecmode == V4SFmode)
1869 : 0 : emit_insn (gen_sse_movss_v4sf (value, value, input));
1870 : : else
1871 : 0 : emit_insn (gen_sse2_movsd_v2df (value, value, input));
1872 : : }
1873 : :
1874 : 0 : emit_move_insn (large, two31);
1875 : 0 : emit_move_insn (zero_or_two31, MEM_P (two31) ? large : two31);
1876 : :
1877 : 0 : x = gen_rtx_fmt_ee (LE, vecmode, large, value);
1878 : 0 : emit_insn (gen_rtx_SET (large, x));
1879 : :
1880 : 0 : x = gen_rtx_AND (vecmode, zero_or_two31, large);
1881 : 0 : emit_insn (gen_rtx_SET (zero_or_two31, x));
1882 : :
1883 : 0 : x = gen_rtx_MINUS (vecmode, value, zero_or_two31);
1884 : 0 : emit_insn (gen_rtx_SET (value, x));
1885 : :
1886 : 0 : large = gen_rtx_REG (V4SImode, REGNO (large));
1887 : 0 : emit_insn (gen_ashlv4si3 (large, large, GEN_INT (31)));
1888 : :
1889 : 0 : x = gen_rtx_REG (V4SImode, REGNO (value));
1890 : 0 : if (vecmode == V4SFmode)
1891 : 0 : emit_insn (gen_fix_truncv4sfv4si2 (x, value));
1892 : : else
1893 : 0 : emit_insn (gen_sse2_cvttpd2dq (x, value));
1894 : 0 : value = x;
1895 : :
1896 : 0 : emit_insn (gen_xorv4si3 (value, value, large));
1897 : 0 : }
1898 : :
1899 : : static bool ix86_expand_vector_init_one_nonzero (bool mmx_ok,
1900 : : machine_mode mode, rtx target,
1901 : : rtx var, int one_var);
1902 : :
1903 : : /* Convert an unsigned DImode value into a DFmode, using only SSE.
1904 : : Expects the 64-bit DImode to be supplied in a pair of integral
1905 : : registers. Requires SSE2; will use SSE3 if available. For x86_32,
1906 : : -mfpmath=sse, !optimize_size only. */
1907 : :
1908 : : void
1909 : 0 : ix86_expand_convert_uns_didf_sse (rtx target, rtx input)
1910 : : {
1911 : 0 : REAL_VALUE_TYPE bias_lo_rvt, bias_hi_rvt;
1912 : 0 : rtx int_xmm, fp_xmm;
1913 : 0 : rtx biases, exponents;
1914 : 0 : rtx x;
1915 : :
1916 : 0 : int_xmm = gen_reg_rtx (V4SImode);
1917 : 0 : if (TARGET_INTER_UNIT_MOVES_TO_VEC)
1918 : 0 : emit_insn (gen_movdi_to_sse (int_xmm, input));
1919 : 0 : else if (TARGET_SSE_SPLIT_REGS)
1920 : : {
1921 : 0 : emit_clobber (int_xmm);
1922 : 0 : emit_move_insn (gen_lowpart (DImode, int_xmm), input);
1923 : : }
1924 : : else
1925 : : {
1926 : 0 : x = gen_reg_rtx (V2DImode);
1927 : 0 : ix86_expand_vector_init_one_nonzero (false, V2DImode, x, input, 0);
1928 : 0 : emit_move_insn (int_xmm, gen_lowpart (V4SImode, x));
1929 : : }
1930 : :
1931 : 0 : x = gen_rtx_CONST_VECTOR (V4SImode,
1932 : : gen_rtvec (4, GEN_INT (0x43300000UL),
1933 : : GEN_INT (0x45300000UL),
1934 : : const0_rtx, const0_rtx));
1935 : 0 : exponents = validize_mem (force_const_mem (V4SImode, x));
1936 : :
1937 : : /* int_xmm = {0x45300000UL, fp_xmm/hi, 0x43300000, fp_xmm/lo } */
1938 : 0 : emit_insn (gen_vec_interleave_lowv4si (int_xmm, int_xmm, exponents));
1939 : :
1940 : : /* Concatenating (juxtaposing) (0x43300000UL ## fp_value_low_xmm)
1941 : : yields a valid DF value equal to (0x1.0p52 + double(fp_value_lo_xmm)).
1942 : : Similarly (0x45300000UL ## fp_value_hi_xmm) yields
1943 : : (0x1.0p84 + double(fp_value_hi_xmm)).
1944 : : Note these exponents differ by 32. */
1945 : :
1946 : 0 : fp_xmm = copy_to_mode_reg (V2DFmode, gen_lowpart (V2DFmode, int_xmm));
1947 : :
1948 : : /* Subtract off those 0x1.0p52 and 0x1.0p84 biases, to produce values
1949 : : in [0,2**32-1] and [0]+[2**32,2**64-1] respectively. */
1950 : 0 : real_ldexp (&bias_lo_rvt, &dconst1, 52);
1951 : 0 : real_ldexp (&bias_hi_rvt, &dconst1, 84);
1952 : 0 : biases = const_double_from_real_value (bias_lo_rvt, DFmode);
1953 : 0 : x = const_double_from_real_value (bias_hi_rvt, DFmode);
1954 : 0 : biases = gen_rtx_CONST_VECTOR (V2DFmode, gen_rtvec (2, biases, x));
1955 : 0 : biases = validize_mem (force_const_mem (V2DFmode, biases));
1956 : 0 : emit_insn (gen_subv2df3 (fp_xmm, fp_xmm, biases));
1957 : :
1958 : : /* Add the upper and lower DFmode values together. */
1959 : 0 : if (TARGET_SSE3)
1960 : 0 : emit_insn (gen_sse3_haddv2df3 (fp_xmm, fp_xmm, fp_xmm));
1961 : : else
1962 : : {
1963 : 0 : x = copy_to_mode_reg (V2DFmode, fp_xmm);
1964 : 0 : emit_insn (gen_vec_interleave_highv2df (fp_xmm, fp_xmm, fp_xmm));
1965 : 0 : emit_insn (gen_addv2df3 (fp_xmm, fp_xmm, x));
1966 : : }
1967 : :
1968 : 0 : ix86_expand_vector_extract (false, target, fp_xmm, 0);
1969 : 0 : }
1970 : :
1971 : : /* Not used, but eases macroization of patterns. */
1972 : : void
1973 : 0 : ix86_expand_convert_uns_sixf_sse (rtx, rtx)
1974 : : {
1975 : 0 : gcc_unreachable ();
1976 : : }
1977 : :
1978 : : static rtx ix86_expand_sse_fabs (rtx op0, rtx *smask);
1979 : :
1980 : : /* Convert an unsigned SImode value into a DFmode. Only currently used
1981 : : for SSE, but applicable anywhere. */
1982 : :
1983 : : void
1984 : 0 : ix86_expand_convert_uns_sidf_sse (rtx target, rtx input)
1985 : : {
1986 : 0 : REAL_VALUE_TYPE TWO31r;
1987 : 0 : rtx x, fp;
1988 : :
1989 : 0 : x = expand_simple_binop (SImode, PLUS, input, GEN_INT (-2147483647 - 1),
1990 : : NULL, 1, OPTAB_DIRECT);
1991 : :
1992 : 0 : fp = gen_reg_rtx (DFmode);
1993 : 0 : emit_insn (gen_floatsidf2 (fp, x));
1994 : :
1995 : 0 : real_ldexp (&TWO31r, &dconst1, 31);
1996 : 0 : x = const_double_from_real_value (TWO31r, DFmode);
1997 : :
1998 : 0 : x = expand_simple_binop (DFmode, PLUS, fp, x, target, 0, OPTAB_DIRECT);
1999 : :
2000 : : /* Remove the sign with FE_DOWNWARD, where x - x = -0.0. */
2001 : 0 : if (HONOR_SIGNED_ZEROS (DFmode) && flag_rounding_math)
2002 : 0 : x = ix86_expand_sse_fabs (x, NULL);
2003 : :
2004 : 0 : if (x != target)
2005 : 0 : emit_move_insn (target, x);
2006 : 0 : }
2007 : :
2008 : : /* Convert a signed DImode value into a DFmode. Only used for SSE in
2009 : : 32-bit mode; otherwise we have a direct convert instruction. */
2010 : :
2011 : : void
2012 : 0 : ix86_expand_convert_sign_didf_sse (rtx target, rtx input)
2013 : : {
2014 : 0 : REAL_VALUE_TYPE TWO32r;
2015 : 0 : rtx fp_lo, fp_hi, x;
2016 : :
2017 : 0 : fp_lo = gen_reg_rtx (DFmode);
2018 : 0 : fp_hi = gen_reg_rtx (DFmode);
2019 : :
2020 : 0 : emit_insn (gen_floatsidf2 (fp_hi, gen_highpart (SImode, input)));
2021 : :
2022 : 0 : real_ldexp (&TWO32r, &dconst1, 32);
2023 : 0 : x = const_double_from_real_value (TWO32r, DFmode);
2024 : 0 : fp_hi = expand_simple_binop (DFmode, MULT, fp_hi, x, fp_hi, 0, OPTAB_DIRECT);
2025 : :
2026 : 0 : ix86_expand_convert_uns_sidf_sse (fp_lo, gen_lowpart (SImode, input));
2027 : :
2028 : 0 : x = expand_simple_binop (DFmode, PLUS, fp_hi, fp_lo, target,
2029 : : 0, OPTAB_DIRECT);
2030 : 0 : if (x != target)
2031 : 0 : emit_move_insn (target, x);
2032 : 0 : }
2033 : :
2034 : : /* Convert an unsigned SImode value into a SFmode, using only SSE.
2035 : : For x86_32, -mfpmath=sse, !optimize_size only. */
2036 : : void
2037 : 0 : ix86_expand_convert_uns_sisf_sse (rtx target, rtx input)
2038 : : {
2039 : 0 : REAL_VALUE_TYPE ONE16r;
2040 : 0 : rtx fp_hi, fp_lo, int_hi, int_lo, x;
2041 : :
2042 : 0 : real_ldexp (&ONE16r, &dconst1, 16);
2043 : 0 : x = const_double_from_real_value (ONE16r, SFmode);
2044 : 0 : int_lo = expand_simple_binop (SImode, AND, input, GEN_INT(0xffff),
2045 : : NULL, 0, OPTAB_DIRECT);
2046 : 0 : int_hi = expand_simple_binop (SImode, LSHIFTRT, input, GEN_INT(16),
2047 : : NULL, 0, OPTAB_DIRECT);
2048 : 0 : fp_hi = gen_reg_rtx (SFmode);
2049 : 0 : fp_lo = gen_reg_rtx (SFmode);
2050 : 0 : emit_insn (gen_floatsisf2 (fp_hi, int_hi));
2051 : 0 : emit_insn (gen_floatsisf2 (fp_lo, int_lo));
2052 : 0 : if (TARGET_FMA)
2053 : : {
2054 : 0 : x = validize_mem (force_const_mem (SFmode, x));
2055 : 0 : fp_hi = gen_rtx_FMA (SFmode, fp_hi, x, fp_lo);
2056 : 0 : emit_move_insn (target, fp_hi);
2057 : : }
2058 : : else
2059 : : {
2060 : 0 : fp_hi = expand_simple_binop (SFmode, MULT, fp_hi, x, fp_hi,
2061 : : 0, OPTAB_DIRECT);
2062 : 0 : fp_hi = expand_simple_binop (SFmode, PLUS, fp_hi, fp_lo, target,
2063 : : 0, OPTAB_DIRECT);
2064 : 0 : if (!rtx_equal_p (target, fp_hi))
2065 : 0 : emit_move_insn (target, fp_hi);
2066 : : }
2067 : 0 : }
2068 : :
2069 : : /* floatunsv{4,8}siv{4,8}sf2 expander. Expand code to convert
2070 : : a vector of unsigned ints VAL to vector of floats TARGET. */
2071 : :
2072 : : void
2073 : 46 : ix86_expand_vector_convert_uns_vsivsf (rtx target, rtx val)
2074 : : {
2075 : 46 : rtx tmp[8];
2076 : 46 : REAL_VALUE_TYPE TWO16r;
2077 : 46 : machine_mode intmode = GET_MODE (val);
2078 : 46 : machine_mode fltmode = GET_MODE (target);
2079 : 46 : rtx (*cvt) (rtx, rtx);
2080 : :
2081 : 46 : if (intmode == V4SImode)
2082 : : cvt = gen_floatv4siv4sf2;
2083 : : else
2084 : 2 : cvt = gen_floatv8siv8sf2;
2085 : 46 : tmp[0] = ix86_build_const_vector (intmode, 1, GEN_INT (0xffff));
2086 : 46 : tmp[0] = force_reg (intmode, tmp[0]);
2087 : 46 : tmp[1] = expand_simple_binop (intmode, AND, val, tmp[0], NULL_RTX, 1,
2088 : : OPTAB_DIRECT);
2089 : 46 : tmp[2] = expand_simple_binop (intmode, LSHIFTRT, val, GEN_INT (16),
2090 : : NULL_RTX, 1, OPTAB_DIRECT);
2091 : 46 : tmp[3] = gen_reg_rtx (fltmode);
2092 : 46 : emit_insn (cvt (tmp[3], tmp[1]));
2093 : 46 : tmp[4] = gen_reg_rtx (fltmode);
2094 : 46 : emit_insn (cvt (tmp[4], tmp[2]));
2095 : 46 : real_ldexp (&TWO16r, &dconst1, 16);
2096 : 46 : tmp[5] = const_double_from_real_value (TWO16r, SFmode);
2097 : 46 : tmp[5] = force_reg (fltmode, ix86_build_const_vector (fltmode, 1, tmp[5]));
2098 : 46 : if (TARGET_FMA)
2099 : : {
2100 : 1 : tmp[6] = gen_rtx_FMA (fltmode, tmp[4], tmp[5], tmp[3]);
2101 : 1 : emit_move_insn (target, tmp[6]);
2102 : : }
2103 : : else
2104 : : {
2105 : 45 : tmp[6] = expand_simple_binop (fltmode, MULT, tmp[4], tmp[5],
2106 : : NULL_RTX, 1, OPTAB_DIRECT);
2107 : 45 : tmp[7] = expand_simple_binop (fltmode, PLUS, tmp[3], tmp[6],
2108 : : target, 1, OPTAB_DIRECT);
2109 : 45 : if (tmp[7] != target)
2110 : 0 : emit_move_insn (target, tmp[7]);
2111 : : }
2112 : 46 : }
2113 : :
2114 : : /* Adjust a V*SFmode/V*DFmode value VAL so that *sfix_trunc* resp. fix_trunc*
2115 : : pattern can be used on it instead of fixuns_trunc*.
2116 : : This is done by doing just signed conversion if < 0x1p31, and otherwise by
2117 : : subtracting 0x1p31 first and xoring in 0x80000000 from *XORP afterwards. */
2118 : :
2119 : : rtx
2120 : 26 : ix86_expand_adjust_ufix_to_sfix_si (rtx val, rtx *xorp)
2121 : : {
2122 : 26 : REAL_VALUE_TYPE TWO31r;
2123 : 26 : rtx two31r, tmp[4];
2124 : 26 : machine_mode mode = GET_MODE (val);
2125 : 26 : machine_mode scalarmode = GET_MODE_INNER (mode);
2126 : 52 : machine_mode intmode = GET_MODE_SIZE (mode) == 32 ? V8SImode : V4SImode;
2127 : 26 : rtx (*cmp) (rtx, rtx, rtx, rtx);
2128 : 26 : int i;
2129 : :
2130 : 104 : for (i = 0; i < 3; i++)
2131 : 78 : tmp[i] = gen_reg_rtx (mode);
2132 : 26 : real_ldexp (&TWO31r, &dconst1, 31);
2133 : 26 : two31r = const_double_from_real_value (TWO31r, scalarmode);
2134 : 26 : two31r = ix86_build_const_vector (mode, 1, two31r);
2135 : 26 : two31r = force_reg (mode, two31r);
2136 : 26 : switch (mode)
2137 : : {
2138 : : case E_V8SFmode: cmp = gen_avx_maskcmpv8sf3; break;
2139 : 8 : case E_V4SFmode: cmp = gen_sse_maskcmpv4sf3; break;
2140 : 0 : case E_V4DFmode: cmp = gen_avx_maskcmpv4df3; break;
2141 : 18 : case E_V2DFmode: cmp = gen_sse2_maskcmpv2df3; break;
2142 : 0 : default: gcc_unreachable ();
2143 : : }
2144 : 26 : tmp[3] = gen_rtx_LE (mode, two31r, val);
2145 : 26 : emit_insn (cmp (tmp[0], two31r, val, tmp[3]));
2146 : 26 : tmp[1] = expand_simple_binop (mode, AND, tmp[0], two31r, tmp[1],
2147 : : 0, OPTAB_DIRECT);
2148 : 26 : if (intmode == V4SImode || TARGET_AVX2)
2149 : 52 : *xorp = expand_simple_binop (intmode, ASHIFT,
2150 : 26 : gen_lowpart (intmode, tmp[0]),
2151 : : GEN_INT (31), NULL_RTX, 0,
2152 : : OPTAB_DIRECT);
2153 : : else
2154 : : {
2155 : 0 : rtx two31 = gen_int_mode (HOST_WIDE_INT_1U << 31, SImode);
2156 : 0 : two31 = ix86_build_const_vector (intmode, 1, two31);
2157 : 0 : *xorp = expand_simple_binop (intmode, AND,
2158 : 0 : gen_lowpart (intmode, tmp[0]),
2159 : : two31, NULL_RTX, 0,
2160 : : OPTAB_DIRECT);
2161 : : }
2162 : 26 : return expand_simple_binop (mode, MINUS, val, tmp[1], tmp[2],
2163 : 26 : 0, OPTAB_DIRECT);
2164 : : }
2165 : :
2166 : : /* Generate code for floating point ABS or NEG. */
2167 : :
2168 : : void
2169 : 32255 : ix86_expand_fp_absneg_operator (enum rtx_code code, machine_mode mode,
2170 : : rtx operands[])
2171 : : {
2172 : 32255 : rtx set, dst, src;
2173 : 32255 : bool use_sse = false;
2174 : 32255 : bool vector_mode = VECTOR_MODE_P (mode);
2175 : 32255 : machine_mode vmode = mode;
2176 : 32255 : rtvec par;
2177 : :
2178 : 32255 : if (vector_mode || mode == TFmode || mode == HFmode)
2179 : : {
2180 : 4555 : use_sse = true;
2181 : 4464 : if (mode == HFmode)
2182 : 91 : vmode = V8HFmode;
2183 : : }
2184 : 27700 : else if (TARGET_SSE_MATH)
2185 : : {
2186 : 26346 : use_sse = SSE_FLOAT_MODE_P (mode);
2187 : 3786 : if (mode == SFmode)
2188 : : vmode = V4SFmode;
2189 : 17456 : else if (mode == DFmode)
2190 : 13674 : vmode = V2DFmode;
2191 : : }
2192 : :
2193 : 32255 : dst = operands[0];
2194 : 32255 : src = operands[1];
2195 : :
2196 : 32255 : set = gen_rtx_fmt_e (code, mode, src);
2197 : 32255 : set = gen_rtx_SET (dst, set);
2198 : :
2199 : 32255 : if (use_sse)
2200 : : {
2201 : 27115 : rtx mask, use, clob;
2202 : :
2203 : : /* NEG and ABS performed with SSE use bitwise mask operations.
2204 : : Create the appropriate mask now. */
2205 : 27115 : mask = ix86_build_signbit_mask (vmode, vector_mode, code == ABS);
2206 : 27115 : use = gen_rtx_USE (VOIDmode, mask);
2207 : 27115 : if (vector_mode || mode == TFmode)
2208 : 4464 : par = gen_rtvec (2, set, use);
2209 : : else
2210 : : {
2211 : 22651 : clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
2212 : 22651 : par = gen_rtvec (3, set, use, clob);
2213 : : }
2214 : : }
2215 : : else
2216 : : {
2217 : 5140 : rtx clob;
2218 : :
2219 : : /* Changing of sign for FP values is doable using integer unit too. */
2220 : 5140 : clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
2221 : 5140 : par = gen_rtvec (2, set, clob);
2222 : : }
2223 : :
2224 : 32255 : emit_insn (gen_rtx_PARALLEL (VOIDmode, par));
2225 : 32255 : }
2226 : :
2227 : : /* Deconstruct a floating point ABS or NEG operation
2228 : : with integer registers into integer operations. */
2229 : :
2230 : : void
2231 : 31 : ix86_split_fp_absneg_operator (enum rtx_code code, machine_mode mode,
2232 : : rtx operands[])
2233 : : {
2234 : 31 : enum rtx_code absneg_op;
2235 : 31 : rtx dst, set;
2236 : :
2237 : 31 : gcc_assert (operands_match_p (operands[0], operands[1]));
2238 : :
2239 : 31 : switch (mode)
2240 : : {
2241 : 0 : case E_SFmode:
2242 : 0 : dst = gen_lowpart (SImode, operands[0]);
2243 : :
2244 : 0 : if (code == ABS)
2245 : : {
2246 : 0 : set = gen_int_mode (0x7fffffff, SImode);
2247 : 0 : absneg_op = AND;
2248 : : }
2249 : : else
2250 : : {
2251 : 0 : set = gen_int_mode (0x80000000, SImode);
2252 : 0 : absneg_op = XOR;
2253 : : }
2254 : 0 : set = gen_rtx_fmt_ee (absneg_op, SImode, dst, set);
2255 : 0 : break;
2256 : :
2257 : 1 : case E_DFmode:
2258 : 1 : if (TARGET_64BIT)
2259 : : {
2260 : 1 : dst = gen_lowpart (DImode, operands[0]);
2261 : 1 : dst = gen_rtx_ZERO_EXTRACT (DImode, dst, const1_rtx, GEN_INT (63));
2262 : :
2263 : 1 : if (code == ABS)
2264 : 0 : set = const0_rtx;
2265 : : else
2266 : 1 : set = gen_rtx_NOT (DImode, dst);
2267 : : }
2268 : : else
2269 : : {
2270 : 0 : dst = gen_highpart (SImode, operands[0]);
2271 : :
2272 : 0 : if (code == ABS)
2273 : : {
2274 : 0 : set = gen_int_mode (0x7fffffff, SImode);
2275 : 0 : absneg_op = AND;
2276 : : }
2277 : : else
2278 : : {
2279 : 0 : set = gen_int_mode (0x80000000, SImode);
2280 : 0 : absneg_op = XOR;
2281 : : }
2282 : 0 : set = gen_rtx_fmt_ee (absneg_op, SImode, dst, set);
2283 : : }
2284 : : break;
2285 : :
2286 : 30 : case E_XFmode:
2287 : 30 : dst = gen_rtx_REG (SImode,
2288 : 30 : REGNO (operands[0]) + (TARGET_64BIT ? 1 : 2));
2289 : 30 : if (code == ABS)
2290 : : {
2291 : 4 : set = GEN_INT (0x7fff);
2292 : 4 : absneg_op = AND;
2293 : : }
2294 : : else
2295 : : {
2296 : 26 : set = GEN_INT (0x8000);
2297 : 26 : absneg_op = XOR;
2298 : : }
2299 : 30 : set = gen_rtx_fmt_ee (absneg_op, SImode, dst, set);
2300 : 30 : break;
2301 : :
2302 : 0 : default:
2303 : 0 : gcc_unreachable ();
2304 : : }
2305 : :
2306 : 31 : set = gen_rtx_SET (dst, set);
2307 : :
2308 : 31 : rtx clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
2309 : 31 : rtvec par = gen_rtvec (2, set, clob);
2310 : :
2311 : 31 : emit_insn (gen_rtx_PARALLEL (VOIDmode, par));
2312 : 31 : }
2313 : :
2314 : : /* Expand a copysign operation. Special case operand 0 being a constant. */
2315 : :
2316 : : void
2317 : 23192 : ix86_expand_copysign (rtx operands[])
2318 : : {
2319 : 23192 : machine_mode mode, vmode;
2320 : 23192 : rtx dest, vdest, op0, op1, mask, op2, op3;
2321 : :
2322 : 23192 : mode = GET_MODE (operands[0]);
2323 : :
2324 : 23192 : if (mode == HFmode)
2325 : : vmode = V8HFmode;
2326 : : else if (mode == SFmode)
2327 : : vmode = V4SFmode;
2328 : : else if (mode == DFmode)
2329 : : vmode = V2DFmode;
2330 : : else if (mode == TFmode)
2331 : : vmode = mode;
2332 : : else
2333 : 0 : gcc_unreachable ();
2334 : :
2335 : 23192 : if (rtx_equal_p (operands[1], operands[2]))
2336 : : {
2337 : 0 : emit_move_insn (operands[0], operands[1]);
2338 : 0 : return;
2339 : : }
2340 : :
2341 : 23192 : dest = operands[0];
2342 : 23192 : vdest = lowpart_subreg (vmode, dest, mode);
2343 : 23192 : if (vdest == NULL_RTX)
2344 : 0 : vdest = gen_reg_rtx (vmode);
2345 : : else
2346 : : dest = NULL_RTX;
2347 : 23192 : op1 = lowpart_subreg (vmode, force_reg (mode, operands[2]), mode);
2348 : 46369 : mask = ix86_build_signbit_mask (vmode, TARGET_AVX512F && mode != HFmode, 0);
2349 : :
2350 : 23192 : if (CONST_DOUBLE_P (operands[1]))
2351 : : {
2352 : 22741 : op0 = simplify_unary_operation (ABS, mode, operands[1], mode);
2353 : : /* Optimize for 0, simplify b = copy_signf (0.0f, a) to b = mask & a. */
2354 : 22741 : if (op0 == CONST0_RTX (mode))
2355 : : {
2356 : 109 : emit_move_insn (vdest, gen_rtx_AND (vmode, mask, op1));
2357 : 109 : if (dest)
2358 : 0 : emit_move_insn (dest, lowpart_subreg (mode, vdest, vmode));
2359 : 109 : return;
2360 : : }
2361 : :
2362 : 45264 : if (GET_MODE_SIZE (mode) < 16)
2363 : 22620 : op0 = ix86_build_const_vector (vmode, false, op0);
2364 : 22632 : op0 = force_reg (vmode, op0);
2365 : : }
2366 : : else
2367 : 451 : op0 = lowpart_subreg (vmode, force_reg (mode, operands[1]), mode);
2368 : :
2369 : 23083 : op2 = gen_reg_rtx (vmode);
2370 : 23083 : op3 = gen_reg_rtx (vmode);
2371 : 23083 : emit_move_insn (op2, gen_rtx_AND (vmode,
2372 : : gen_rtx_NOT (vmode, mask),
2373 : : op0));
2374 : 23083 : emit_move_insn (op3, gen_rtx_AND (vmode, mask, op1));
2375 : 23083 : emit_move_insn (vdest, gen_rtx_IOR (vmode, op2, op3));
2376 : 23083 : if (dest)
2377 : 0 : emit_move_insn (dest, lowpart_subreg (mode, vdest, vmode));
2378 : : }
2379 : :
2380 : : /* Expand an xorsign operation. */
2381 : :
2382 : : void
2383 : 16 : ix86_expand_xorsign (rtx operands[])
2384 : : {
2385 : 16 : machine_mode mode, vmode;
2386 : 16 : rtx dest, vdest, op0, op1, mask, x, temp;
2387 : :
2388 : 16 : dest = operands[0];
2389 : 16 : op0 = operands[1];
2390 : 16 : op1 = operands[2];
2391 : :
2392 : 16 : mode = GET_MODE (dest);
2393 : :
2394 : 16 : if (mode == HFmode)
2395 : : vmode = V8HFmode;
2396 : : else if (mode == SFmode)
2397 : : vmode = V4SFmode;
2398 : : else if (mode == DFmode)
2399 : : vmode = V2DFmode;
2400 : : else
2401 : 0 : gcc_unreachable ();
2402 : :
2403 : 16 : temp = gen_reg_rtx (vmode);
2404 : 16 : mask = ix86_build_signbit_mask (vmode, 0, 0);
2405 : :
2406 : 16 : op1 = lowpart_subreg (vmode, force_reg (mode, op1), mode);
2407 : 16 : x = gen_rtx_AND (vmode, op1, mask);
2408 : 16 : emit_insn (gen_rtx_SET (temp, x));
2409 : :
2410 : 16 : op0 = lowpart_subreg (vmode, force_reg (mode, op0), mode);
2411 : 16 : x = gen_rtx_XOR (vmode, temp, op0);
2412 : :
2413 : 16 : vdest = lowpart_subreg (vmode, dest, mode);
2414 : 16 : if (vdest == NULL_RTX)
2415 : 0 : vdest = gen_reg_rtx (vmode);
2416 : : else
2417 : : dest = NULL_RTX;
2418 : 16 : emit_insn (gen_rtx_SET (vdest, x));
2419 : :
2420 : 16 : if (dest)
2421 : 0 : emit_move_insn (dest, lowpart_subreg (mode, vdest, vmode));
2422 : 16 : }
2423 : :
2424 : : static rtx ix86_expand_compare (enum rtx_code code, rtx op0, rtx op1);
2425 : :
2426 : : void
2427 : 5859059 : ix86_expand_branch (enum rtx_code code, rtx op0, rtx op1, rtx label)
2428 : : {
2429 : 5859059 : machine_mode mode = GET_MODE (op0);
2430 : 5859059 : rtx tmp;
2431 : :
2432 : : /* Handle special case - vector comparsion with boolean result, transform
2433 : : it using ptest instruction or vpcmpeq + kortest. */
2434 : 5859059 : if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT
2435 : 5853649 : || (mode == TImode && !TARGET_64BIT)
2436 : 5853649 : || mode == OImode
2437 : 11712708 : || GET_MODE_SIZE (mode) == 64)
2438 : : {
2439 : 5410 : unsigned msize = GET_MODE_SIZE (mode);
2440 : 13771 : machine_mode p_mode
2441 : 5410 : = msize == 64 ? V16SImode : msize == 32 ? V4DImode : V2DImode;
2442 : : /* kortest set CF when result is 0xFFFF (op0 == op1). */
2443 : 5410 : rtx flag = gen_rtx_REG (msize == 64 ? CCCmode : CCZmode, FLAGS_REG);
2444 : :
2445 : 5410 : gcc_assert (code == EQ || code == NE);
2446 : :
2447 : : /* Using vpcmpeq zmm zmm k + kortest for 512-bit vectors. */
2448 : 5410 : if (msize == 64)
2449 : : {
2450 : 1344 : if (mode != V16SImode)
2451 : : {
2452 : 1344 : op0 = lowpart_subreg (p_mode, force_reg (mode, op0), mode);
2453 : 1344 : op1 = lowpart_subreg (p_mode, force_reg (mode, op1), mode);
2454 : : }
2455 : :
2456 : 1344 : tmp = gen_reg_rtx (HImode);
2457 : 1344 : emit_insn (gen_avx512f_cmpv16si3 (tmp, op0, op1, GEN_INT (0)));
2458 : 1344 : emit_insn (gen_kortesthi_ccc (tmp, tmp));
2459 : : }
2460 : : /* Using ptest for 128/256-bit vectors. */
2461 : : else
2462 : : {
2463 : 4066 : if (GET_MODE_CLASS (mode) != MODE_VECTOR_INT)
2464 : : {
2465 : 0 : op0 = lowpart_subreg (p_mode, force_reg (mode, op0), mode);
2466 : 0 : op1 = lowpart_subreg (p_mode, force_reg (mode, op1), mode);
2467 : 0 : mode = p_mode;
2468 : : }
2469 : :
2470 : : /* Generate XOR since we can't check that one operand is zero
2471 : : vector. */
2472 : 4066 : tmp = gen_reg_rtx (mode);
2473 : 4066 : rtx ops[3] = { tmp, op0, op1 };
2474 : 4066 : ix86_expand_vector_logical_operator (XOR, mode, ops);
2475 : 4066 : tmp = gen_lowpart (p_mode, tmp);
2476 : 4066 : emit_insn (gen_rtx_SET (gen_rtx_REG (CCZmode, FLAGS_REG),
2477 : : gen_rtx_UNSPEC (CCZmode,
2478 : : gen_rtvec (2, tmp, tmp),
2479 : : UNSPEC_PTEST)));
2480 : : }
2481 : 5410 : tmp = gen_rtx_fmt_ee (code, VOIDmode, flag, const0_rtx);
2482 : 5410 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
2483 : : gen_rtx_LABEL_REF (VOIDmode, label),
2484 : : pc_rtx);
2485 : 5410 : emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
2486 : 5410 : return;
2487 : : }
2488 : :
2489 : 5853649 : switch (mode)
2490 : : {
2491 : 5821481 : case E_HFmode:
2492 : 5821481 : case E_SFmode:
2493 : 5821481 : case E_DFmode:
2494 : 5821481 : case E_XFmode:
2495 : 5821481 : case E_QImode:
2496 : 5821481 : case E_HImode:
2497 : 5821481 : case E_SImode:
2498 : 5821481 : simple:
2499 : 5821481 : tmp = ix86_expand_compare (code, op0, op1);
2500 : 5821481 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
2501 : : gen_rtx_LABEL_REF (VOIDmode, label),
2502 : : pc_rtx);
2503 : 5821481 : emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
2504 : 5821481 : return;
2505 : :
2506 : 2309202 : case E_DImode:
2507 : 2309202 : if (TARGET_64BIT)
2508 : 2282010 : goto simple;
2509 : : /* FALLTHRU */
2510 : 75787 : case E_TImode:
2511 : : /* DI and TI mode equality/inequality comparisons may be performed
2512 : : on SSE registers. Avoid splitting them, except when optimizing
2513 : : for size. */
2514 : 75787 : if ((code == EQ || code == NE)
2515 : 75787 : && !optimize_insn_for_size_p ())
2516 : 43619 : goto simple;
2517 : :
2518 : : /* Expand DImode branch into multiple compare+branch. */
2519 : 32168 : {
2520 : 32168 : rtx lo[2], hi[2];
2521 : 32168 : rtx_code_label *label2;
2522 : 32168 : enum rtx_code code1, code2, code3;
2523 : 32168 : machine_mode submode;
2524 : :
2525 : 32168 : if (CONSTANT_P (op0) && !CONSTANT_P (op1))
2526 : : {
2527 : 0 : std::swap (op0, op1);
2528 : 0 : code = swap_condition (code);
2529 : : }
2530 : :
2531 : 32168 : split_double_mode (mode, &op0, 1, lo+0, hi+0);
2532 : 32168 : split_double_mode (mode, &op1, 1, lo+1, hi+1);
2533 : :
2534 : 32168 : submode = mode == DImode ? SImode : DImode;
2535 : :
2536 : : /* If we are doing less-than or greater-or-equal-than,
2537 : : op1 is a constant and the low word is zero, then we can just
2538 : : examine the high word. Similarly for low word -1 and
2539 : : less-or-equal-than or greater-than. */
2540 : :
2541 : 32168 : if (CONST_INT_P (hi[1]))
2542 : 22310 : switch (code)
2543 : : {
2544 : 11494 : case LT: case LTU: case GE: case GEU:
2545 : 11494 : if (lo[1] == const0_rtx)
2546 : : {
2547 : 11103 : ix86_expand_branch (code, hi[0], hi[1], label);
2548 : 11103 : return;
2549 : : }
2550 : : break;
2551 : 9586 : case LE: case LEU: case GT: case GTU:
2552 : 9586 : if (lo[1] == constm1_rtx)
2553 : : {
2554 : 531 : ix86_expand_branch (code, hi[0], hi[1], label);
2555 : 531 : return;
2556 : : }
2557 : : break;
2558 : : default:
2559 : : break;
2560 : : }
2561 : :
2562 : : /* Emulate comparisons that do not depend on Zero flag with
2563 : : double-word subtraction. Note that only Overflow, Sign
2564 : : and Carry flags are valid, so swap arguments and condition
2565 : : of comparisons that would otherwise test Zero flag. */
2566 : :
2567 : 20534 : switch (code)
2568 : : {
2569 : 13982 : case LE: case LEU: case GT: case GTU:
2570 : 13982 : std::swap (lo[0], lo[1]);
2571 : 13982 : std::swap (hi[0], hi[1]);
2572 : 13982 : code = swap_condition (code);
2573 : : /* FALLTHRU */
2574 : :
2575 : 18153 : case LT: case LTU: case GE: case GEU:
2576 : 18153 : {
2577 : 18153 : bool uns = (code == LTU || code == GEU);
2578 : 36306 : rtx (*sbb_insn) (machine_mode, rtx, rtx, rtx)
2579 : 18153 : = uns ? gen_sub3_carry_ccc : gen_sub3_carry_ccgz;
2580 : :
2581 : 18153 : if (!nonimmediate_operand (lo[0], submode))
2582 : 9055 : lo[0] = force_reg (submode, lo[0]);
2583 : 18153 : if (!x86_64_general_operand (lo[1], submode))
2584 : 0 : lo[1] = force_reg (submode, lo[1]);
2585 : :
2586 : 18153 : if (!register_operand (hi[0], submode))
2587 : 9800 : hi[0] = force_reg (submode, hi[0]);
2588 : 14129 : if ((uns && !nonimmediate_operand (hi[1], submode))
2589 : 18153 : || (!uns && !x86_64_general_operand (hi[1], submode)))
2590 : 315 : hi[1] = force_reg (submode, hi[1]);
2591 : :
2592 : 18153 : emit_insn (gen_cmp_1 (submode, lo[0], lo[1]));
2593 : :
2594 : 18153 : tmp = gen_rtx_SCRATCH (submode);
2595 : 18153 : emit_insn (sbb_insn (submode, tmp, hi[0], hi[1]));
2596 : :
2597 : 22177 : tmp = gen_rtx_REG (uns ? CCCmode : CCGZmode, FLAGS_REG);
2598 : 18153 : ix86_expand_branch (code, tmp, const0_rtx, label);
2599 : 18153 : return;
2600 : : }
2601 : :
2602 : 2381 : default:
2603 : 2381 : break;
2604 : : }
2605 : :
2606 : : /* Otherwise, we need two or three jumps. */
2607 : :
2608 : 2381 : label2 = gen_label_rtx ();
2609 : :
2610 : 2381 : code1 = code;
2611 : 2381 : code2 = swap_condition (code);
2612 : 2381 : code3 = unsigned_condition (code);
2613 : :
2614 : 2381 : switch (code)
2615 : : {
2616 : : case LT: case GT: case LTU: case GTU:
2617 : : break;
2618 : :
2619 : : case LE: code1 = LT; code2 = GT; break;
2620 : : case GE: code1 = GT; code2 = LT; break;
2621 : 0 : case LEU: code1 = LTU; code2 = GTU; break;
2622 : 0 : case GEU: code1 = GTU; code2 = LTU; break;
2623 : :
2624 : : case EQ: code1 = UNKNOWN; code2 = NE; break;
2625 : : case NE: code2 = UNKNOWN; break;
2626 : :
2627 : 0 : default:
2628 : 0 : gcc_unreachable ();
2629 : : }
2630 : :
2631 : : /*
2632 : : * a < b =>
2633 : : * if (hi(a) < hi(b)) goto true;
2634 : : * if (hi(a) > hi(b)) goto false;
2635 : : * if (lo(a) < lo(b)) goto true;
2636 : : * false:
2637 : : */
2638 : :
2639 : 0 : if (code1 != UNKNOWN)
2640 : 1729 : ix86_expand_branch (code1, hi[0], hi[1], label);
2641 : 2381 : if (code2 != UNKNOWN)
2642 : 652 : ix86_expand_branch (code2, hi[0], hi[1], label2);
2643 : :
2644 : 2381 : ix86_expand_branch (code3, lo[0], lo[1], label);
2645 : :
2646 : 2381 : if (code2 != UNKNOWN)
2647 : 652 : emit_label (label2);
2648 : : return;
2649 : : }
2650 : :
2651 : 18459 : default:
2652 : 18459 : gcc_assert (GET_MODE_CLASS (GET_MODE (op0)) == MODE_CC);
2653 : 18459 : goto simple;
2654 : : }
2655 : : }
2656 : :
2657 : : /* Figure out whether to use unordered fp comparisons. */
2658 : :
2659 : : static bool
2660 : 1082071 : ix86_unordered_fp_compare (enum rtx_code code)
2661 : : {
2662 : 1082071 : if (!TARGET_IEEE_FP)
2663 : : return false;
2664 : :
2665 : 1077897 : switch (code)
2666 : : {
2667 : : case LT:
2668 : : case LE:
2669 : : case GT:
2670 : : case GE:
2671 : : case LTGT:
2672 : : return false;
2673 : :
2674 : : case EQ:
2675 : : case NE:
2676 : :
2677 : : case UNORDERED:
2678 : : case ORDERED:
2679 : : case UNLT:
2680 : : case UNLE:
2681 : : case UNGT:
2682 : : case UNGE:
2683 : : case UNEQ:
2684 : : return true;
2685 : :
2686 : 0 : default:
2687 : 0 : gcc_unreachable ();
2688 : : }
2689 : : }
2690 : :
2691 : : /* Return a comparison we can do and that it is equivalent to
2692 : : swap_condition (code) apart possibly from orderedness.
2693 : : But, never change orderedness if TARGET_IEEE_FP, returning
2694 : : UNKNOWN in that case if necessary. */
2695 : :
2696 : : static enum rtx_code
2697 : 36043 : ix86_fp_swap_condition (enum rtx_code code)
2698 : : {
2699 : 36043 : switch (code)
2700 : : {
2701 : 1432 : case GT: /* GTU - CF=0 & ZF=0 */
2702 : 1432 : return TARGET_IEEE_FP ? UNKNOWN : UNLT;
2703 : 490 : case GE: /* GEU - CF=0 */
2704 : 490 : return TARGET_IEEE_FP ? UNKNOWN : UNLE;
2705 : 380 : case UNLT: /* LTU - CF=1 */
2706 : 380 : return TARGET_IEEE_FP ? UNKNOWN : GT;
2707 : 7209 : case UNLE: /* LEU - CF=1 | ZF=1 */
2708 : 7209 : return TARGET_IEEE_FP ? UNKNOWN : GE;
2709 : 26532 : default:
2710 : 26532 : return swap_condition (code);
2711 : : }
2712 : : }
2713 : :
2714 : : /* Return cost of comparison CODE using the best strategy for performance.
2715 : : All following functions do use number of instructions as a cost metrics.
2716 : : In future this should be tweaked to compute bytes for optimize_size and
2717 : : take into account performance of various instructions on various CPUs. */
2718 : :
2719 : : static int
2720 : 1081100 : ix86_fp_comparison_cost (enum rtx_code code)
2721 : : {
2722 : 1081100 : int arith_cost;
2723 : :
2724 : : /* The cost of code using bit-twiddling on %ah. */
2725 : 1081100 : switch (code)
2726 : : {
2727 : : case UNLE:
2728 : : case UNLT:
2729 : : case LTGT:
2730 : : case GT:
2731 : : case GE:
2732 : : case UNORDERED:
2733 : : case ORDERED:
2734 : : case UNEQ:
2735 : : arith_cost = 4;
2736 : : break;
2737 : 62683 : case LT:
2738 : 62683 : case NE:
2739 : 62683 : case EQ:
2740 : 62683 : case UNGE:
2741 : 62683 : arith_cost = TARGET_IEEE_FP ? 5 : 4;
2742 : : break;
2743 : 20627 : case LE:
2744 : 20627 : case UNGT:
2745 : 20627 : arith_cost = TARGET_IEEE_FP ? 6 : 4;
2746 : : break;
2747 : 0 : default:
2748 : 0 : gcc_unreachable ();
2749 : : }
2750 : :
2751 : 1081100 : switch (ix86_fp_comparison_strategy (code))
2752 : : {
2753 : 1081100 : case IX86_FPCMP_COMI:
2754 : 1081100 : return arith_cost > 4 ? 3 : 2;
2755 : 0 : case IX86_FPCMP_SAHF:
2756 : 0 : return arith_cost > 4 ? 4 : 3;
2757 : : default:
2758 : : return arith_cost;
2759 : : }
2760 : : }
2761 : :
2762 : : /* Swap, force into registers, or otherwise massage the two operands
2763 : : to a fp comparison. The operands are updated in place; the new
2764 : : comparison code is returned. */
2765 : :
2766 : : static enum rtx_code
2767 : 540550 : ix86_prepare_fp_compare_args (enum rtx_code code, rtx *pop0, rtx *pop1)
2768 : : {
2769 : 540552 : bool unordered_compare = ix86_unordered_fp_compare (code);
2770 : 540552 : rtx op0 = *pop0, op1 = *pop1;
2771 : 540552 : machine_mode op_mode = GET_MODE (op0);
2772 : 540552 : bool is_sse = SSE_FLOAT_MODE_SSEMATH_OR_HF_P (op_mode);
2773 : :
2774 : 538638 : if (op_mode == BFmode)
2775 : : {
2776 : 2 : rtx op = gen_lowpart (HImode, op0);
2777 : 2 : if (CONST_INT_P (op))
2778 : 0 : op = simplify_const_unary_operation (FLOAT_EXTEND, SFmode,
2779 : : op0, BFmode);
2780 : : else
2781 : : {
2782 : 2 : rtx t1 = gen_reg_rtx (SImode);
2783 : 2 : emit_insn (gen_zero_extendhisi2 (t1, op));
2784 : 2 : emit_insn (gen_ashlsi3 (t1, t1, GEN_INT (16)));
2785 : 2 : op = gen_lowpart (SFmode, t1);
2786 : : }
2787 : 2 : *pop0 = op;
2788 : 2 : op = gen_lowpart (HImode, op1);
2789 : 2 : if (CONST_INT_P (op))
2790 : 2 : op = simplify_const_unary_operation (FLOAT_EXTEND, SFmode,
2791 : : op1, BFmode);
2792 : : else
2793 : : {
2794 : 0 : rtx t1 = gen_reg_rtx (SImode);
2795 : 0 : emit_insn (gen_zero_extendhisi2 (t1, op));
2796 : 0 : emit_insn (gen_ashlsi3 (t1, t1, GEN_INT (16)));
2797 : 0 : op = gen_lowpart (SFmode, t1);
2798 : : }
2799 : 2 : *pop1 = op;
2800 : 2 : return ix86_prepare_fp_compare_args (code, pop0, pop1);
2801 : : }
2802 : :
2803 : : /* All of the unordered compare instructions only work on registers.
2804 : : The same is true of the fcomi compare instructions. The XFmode
2805 : : compare instructions require registers except when comparing
2806 : : against zero or when converting operand 1 from fixed point to
2807 : : floating point. */
2808 : :
2809 : 540550 : if (!is_sse
2810 : 540550 : && (unordered_compare
2811 : 9448 : || (op_mode == XFmode
2812 : 10865 : && ! (standard_80387_constant_p (op0) == 1
2813 : 5430 : || standard_80387_constant_p (op1) == 1)
2814 : 5073 : && GET_CODE (op1) != FLOAT)
2815 : 4375 : || ix86_fp_comparison_strategy (code) == IX86_FPCMP_COMI))
2816 : : {
2817 : 149053 : op0 = force_reg (op_mode, op0);
2818 : 149053 : op1 = force_reg (op_mode, op1);
2819 : : }
2820 : : else
2821 : : {
2822 : : /* %%% We only allow op1 in memory; op0 must be st(0). So swap
2823 : : things around if they appear profitable, otherwise force op0
2824 : : into a register. */
2825 : :
2826 : 391497 : if (standard_80387_constant_p (op0) == 0
2827 : 391497 : || (MEM_P (op0)
2828 : 50719 : && ! (standard_80387_constant_p (op1) == 0
2829 : 36079 : || MEM_P (op1))))
2830 : : {
2831 : 36043 : enum rtx_code new_code = ix86_fp_swap_condition (code);
2832 : 36043 : if (new_code != UNKNOWN)
2833 : : {
2834 : : std::swap (op0, op1);
2835 : 391497 : code = new_code;
2836 : : }
2837 : : }
2838 : :
2839 : 391497 : if (!REG_P (op0))
2840 : 49598 : op0 = force_reg (op_mode, op0);
2841 : :
2842 : 391497 : if (CONSTANT_P (op1))
2843 : : {
2844 : 189692 : int tmp = standard_80387_constant_p (op1);
2845 : 189692 : if (tmp == 0)
2846 : 71481 : op1 = validize_mem (force_const_mem (op_mode, op1));
2847 : 118211 : else if (tmp == 1)
2848 : : {
2849 : 64429 : if (TARGET_CMOVE)
2850 : 64429 : op1 = force_reg (op_mode, op1);
2851 : : }
2852 : : else
2853 : 53782 : op1 = force_reg (op_mode, op1);
2854 : : }
2855 : : }
2856 : :
2857 : : /* Try to rearrange the comparison to make it cheaper. */
2858 : 540550 : if (ix86_fp_comparison_cost (code)
2859 : 540550 : > ix86_fp_comparison_cost (swap_condition (code))
2860 : 540550 : && (REG_P (op1) || can_create_pseudo_p ()))
2861 : : {
2862 : 0 : std::swap (op0, op1);
2863 : 0 : code = swap_condition (code);
2864 : 0 : if (!REG_P (op0))
2865 : 0 : op0 = force_reg (op_mode, op0);
2866 : : }
2867 : :
2868 : 540550 : *pop0 = op0;
2869 : 540550 : *pop1 = op1;
2870 : 540550 : return code;
2871 : : }
2872 : :
2873 : : /* Generate insn patterns to do a floating point compare of OPERANDS. */
2874 : :
2875 : : static rtx
2876 : 540550 : ix86_expand_fp_compare (enum rtx_code code, rtx op0, rtx op1)
2877 : : {
2878 : 540550 : bool unordered_compare = ix86_unordered_fp_compare (code);
2879 : 540550 : machine_mode cmp_mode;
2880 : 540550 : rtx tmp, scratch;
2881 : :
2882 : 540550 : code = ix86_prepare_fp_compare_args (code, &op0, &op1);
2883 : :
2884 : 540550 : tmp = gen_rtx_COMPARE (CCFPmode, op0, op1);
2885 : 540550 : if (unordered_compare)
2886 : 488348 : tmp = gen_rtx_UNSPEC (CCFPmode, gen_rtvec (1, tmp), UNSPEC_NOTRAP);
2887 : :
2888 : : /* Do fcomi/sahf based test when profitable. */
2889 : 540550 : switch (ix86_fp_comparison_strategy (code))
2890 : : {
2891 : 540550 : case IX86_FPCMP_COMI:
2892 : 540550 : cmp_mode = CCFPmode;
2893 : 540550 : emit_insn (gen_rtx_SET (gen_rtx_REG (CCFPmode, FLAGS_REG), tmp));
2894 : 540550 : break;
2895 : :
2896 : 0 : case IX86_FPCMP_SAHF:
2897 : 0 : cmp_mode = CCFPmode;
2898 : 0 : tmp = gen_rtx_UNSPEC (HImode, gen_rtvec (1, tmp), UNSPEC_FNSTSW);
2899 : 0 : scratch = gen_reg_rtx (HImode);
2900 : 0 : emit_insn (gen_rtx_SET (scratch, tmp));
2901 : 0 : emit_insn (gen_x86_sahf_1 (scratch));
2902 : 0 : break;
2903 : :
2904 : 0 : case IX86_FPCMP_ARITH:
2905 : 0 : cmp_mode = CCNOmode;
2906 : 0 : tmp = gen_rtx_UNSPEC (HImode, gen_rtvec (1, tmp), UNSPEC_FNSTSW);
2907 : 0 : scratch = gen_reg_rtx (HImode);
2908 : 0 : emit_insn (gen_rtx_SET (scratch, tmp));
2909 : :
2910 : : /* In the unordered case, we have to check C2 for NaN's, which
2911 : : doesn't happen to work out to anything nice combination-wise.
2912 : : So do some bit twiddling on the value we've got in AH to come
2913 : : up with an appropriate set of condition codes. */
2914 : :
2915 : 0 : switch (code)
2916 : : {
2917 : 0 : case GT:
2918 : 0 : case UNGT:
2919 : 0 : if (code == GT || !TARGET_IEEE_FP)
2920 : : {
2921 : 0 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x45)));
2922 : 0 : code = EQ;
2923 : : }
2924 : : else
2925 : : {
2926 : 0 : emit_insn (gen_andqi_ext_1 (scratch, scratch, GEN_INT (0x45)));
2927 : 0 : emit_insn (gen_addqi_ext_1 (scratch, scratch, constm1_rtx));
2928 : 0 : emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x44)));
2929 : 0 : cmp_mode = CCmode;
2930 : 0 : code = GEU;
2931 : : }
2932 : : break;
2933 : 0 : case LT:
2934 : 0 : case UNLT:
2935 : 0 : if (code == LT && TARGET_IEEE_FP)
2936 : : {
2937 : 0 : emit_insn (gen_andqi_ext_1 (scratch, scratch, GEN_INT (0x45)));
2938 : 0 : emit_insn (gen_cmpqi_ext_3 (scratch, const1_rtx));
2939 : 0 : cmp_mode = CCmode;
2940 : 0 : code = EQ;
2941 : : }
2942 : : else
2943 : : {
2944 : 0 : emit_insn (gen_testqi_ext_1_ccno (scratch, const1_rtx));
2945 : 0 : code = NE;
2946 : : }
2947 : : break;
2948 : 0 : case GE:
2949 : 0 : case UNGE:
2950 : 0 : if (code == GE || !TARGET_IEEE_FP)
2951 : : {
2952 : 0 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x05)));
2953 : 0 : code = EQ;
2954 : : }
2955 : : else
2956 : : {
2957 : 0 : emit_insn (gen_andqi_ext_1 (scratch, scratch, GEN_INT (0x45)));
2958 : 0 : emit_insn (gen_xorqi_ext_1_cc (scratch, scratch, const1_rtx));
2959 : 0 : code = NE;
2960 : : }
2961 : : break;
2962 : 0 : case LE:
2963 : 0 : case UNLE:
2964 : 0 : if (code == LE && TARGET_IEEE_FP)
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 (0x40)));
2969 : 0 : cmp_mode = CCmode;
2970 : 0 : code = LTU;
2971 : : }
2972 : : else
2973 : : {
2974 : 0 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x45)));
2975 : 0 : code = NE;
2976 : : }
2977 : : break;
2978 : 0 : case EQ:
2979 : 0 : case UNEQ:
2980 : 0 : if (code == EQ && TARGET_IEEE_FP)
2981 : : {
2982 : 0 : emit_insn (gen_andqi_ext_1 (scratch, scratch, GEN_INT (0x45)));
2983 : 0 : emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x40)));
2984 : 0 : cmp_mode = CCmode;
2985 : 0 : code = EQ;
2986 : : }
2987 : : else
2988 : : {
2989 : 0 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x40)));
2990 : 0 : code = NE;
2991 : : }
2992 : : break;
2993 : 0 : case NE:
2994 : 0 : case LTGT:
2995 : 0 : if (code == NE && TARGET_IEEE_FP)
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,
2999 : : GEN_INT (0x40)));
3000 : 0 : code = NE;
3001 : : }
3002 : : else
3003 : : {
3004 : 0 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x40)));
3005 : 0 : code = EQ;
3006 : : }
3007 : : break;
3008 : :
3009 : 0 : case UNORDERED:
3010 : 0 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x04)));
3011 : 0 : code = NE;
3012 : 0 : break;
3013 : 0 : case ORDERED:
3014 : 0 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x04)));
3015 : 0 : code = EQ;
3016 : 0 : break;
3017 : :
3018 : 0 : default:
3019 : 0 : gcc_unreachable ();
3020 : : }
3021 : : break;
3022 : :
3023 : 0 : default:
3024 : 0 : gcc_unreachable();
3025 : : }
3026 : :
3027 : : /* Return the test that should be put into the flags user, i.e.
3028 : : the bcc, scc, or cmov instruction. */
3029 : 540550 : return gen_rtx_fmt_ee (code, VOIDmode,
3030 : : gen_rtx_REG (cmp_mode, FLAGS_REG),
3031 : : const0_rtx);
3032 : : }
3033 : :
3034 : : /* Generate insn patterns to do an integer compare of OPERANDS. */
3035 : :
3036 : : static rtx
3037 : 6088980 : ix86_expand_int_compare (enum rtx_code code, rtx op0, rtx op1)
3038 : : {
3039 : 6088980 : machine_mode cmpmode;
3040 : 6088980 : rtx tmp, flags;
3041 : :
3042 : : /* Swap operands to emit carry flag comparison. */
3043 : 6088980 : if ((code == GTU || code == LEU)
3044 : 6088980 : && nonimmediate_operand (op1, VOIDmode))
3045 : : {
3046 : 111249 : std::swap (op0, op1);
3047 : 111249 : code = swap_condition (code);
3048 : : }
3049 : :
3050 : 6088980 : cmpmode = SELECT_CC_MODE (code, op0, op1);
3051 : 6088980 : flags = gen_rtx_REG (cmpmode, FLAGS_REG);
3052 : :
3053 : : /* Attempt to use PTEST, if available, when testing vector modes for
3054 : : equality/inequality against zero. */
3055 : 6088980 : if (op1 == const0_rtx
3056 : 2695473 : && SUBREG_P (op0)
3057 : 26370 : && cmpmode == CCZmode
3058 : 12986 : && SUBREG_BYTE (op0) == 0
3059 : 11216 : && REG_P (SUBREG_REG (op0))
3060 : 11216 : && VECTOR_MODE_P (GET_MODE (SUBREG_REG (op0)))
3061 : 6 : && TARGET_SSE4_1
3062 : 0 : && GET_MODE (op0) == TImode
3063 : 6088980 : && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op0))) == 16)
3064 : : {
3065 : 0 : tmp = SUBREG_REG (op0);
3066 : 0 : tmp = gen_rtx_UNSPEC (CCZmode, gen_rtvec (2, tmp, tmp), UNSPEC_PTEST);
3067 : : }
3068 : : else
3069 : 6088980 : tmp = gen_rtx_COMPARE (cmpmode, op0, op1);
3070 : :
3071 : : /* This is very simple, but making the interface the same as in the
3072 : : FP case makes the rest of the code easier. */
3073 : 6088980 : emit_insn (gen_rtx_SET (flags, tmp));
3074 : :
3075 : : /* Return the test that should be put into the flags user, i.e.
3076 : : the bcc, scc, or cmov instruction. */
3077 : 6088980 : return gen_rtx_fmt_ee (code, VOIDmode, flags, const0_rtx);
3078 : : }
3079 : :
3080 : : static rtx
3081 : 6722113 : ix86_expand_compare (enum rtx_code code, rtx op0, rtx op1)
3082 : : {
3083 : 6722113 : rtx ret;
3084 : :
3085 : 6722113 : if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_CC)
3086 : 93234 : ret = gen_rtx_fmt_ee (code, VOIDmode, op0, op1);
3087 : :
3088 : 6628879 : else if (SCALAR_FLOAT_MODE_P (GET_MODE (op0)))
3089 : : {
3090 : 539899 : gcc_assert (!DECIMAL_FLOAT_MODE_P (GET_MODE (op0)));
3091 : 539899 : ret = ix86_expand_fp_compare (code, op0, op1);
3092 : : }
3093 : : else
3094 : 6088980 : ret = ix86_expand_int_compare (code, op0, op1);
3095 : :
3096 : 6722113 : return ret;
3097 : : }
3098 : :
3099 : : void
3100 : 480889 : ix86_expand_setcc (rtx dest, enum rtx_code code, rtx op0, rtx op1)
3101 : : {
3102 : 480889 : rtx ret;
3103 : :
3104 : 480889 : gcc_assert (GET_MODE (dest) == QImode);
3105 : :
3106 : 480889 : ret = ix86_expand_compare (code, op0, op1);
3107 : 480889 : PUT_MODE (ret, QImode);
3108 : 480889 : emit_insn (gen_rtx_SET (dest, ret));
3109 : 480889 : }
3110 : :
3111 : : /* Expand floating point op0 <=> op1, i.e.
3112 : : dest = op0 == op1 ? 0 : op0 < op1 ? -1 : op0 > op1 ? 1 : 2. */
3113 : :
3114 : : void
3115 : 306 : ix86_expand_fp_spaceship (rtx dest, rtx op0, rtx op1)
3116 : : {
3117 : 306 : gcc_checking_assert (ix86_fp_comparison_strategy (GT) != IX86_FPCMP_ARITH);
3118 : 306 : rtx gt = ix86_expand_fp_compare (GT, op0, op1);
3119 : 306 : rtx l0 = gen_label_rtx ();
3120 : 306 : rtx l1 = gen_label_rtx ();
3121 : 306 : rtx l2 = TARGET_IEEE_FP ? gen_label_rtx () : NULL_RTX;
3122 : 306 : rtx lend = gen_label_rtx ();
3123 : 306 : rtx tmp;
3124 : 306 : rtx_insn *jmp;
3125 : 306 : if (l2)
3126 : : {
3127 : 269 : rtx un = gen_rtx_fmt_ee (UNORDERED, VOIDmode,
3128 : : gen_rtx_REG (CCFPmode, FLAGS_REG), const0_rtx);
3129 : 269 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, un,
3130 : : gen_rtx_LABEL_REF (VOIDmode, l2), pc_rtx);
3131 : 269 : jmp = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
3132 : 269 : add_reg_br_prob_note (jmp, profile_probability:: very_unlikely ());
3133 : : }
3134 : 306 : rtx eq = gen_rtx_fmt_ee (UNEQ, VOIDmode,
3135 : : gen_rtx_REG (CCFPmode, FLAGS_REG), const0_rtx);
3136 : 306 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, eq,
3137 : : gen_rtx_LABEL_REF (VOIDmode, l0), pc_rtx);
3138 : 306 : jmp = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
3139 : 306 : add_reg_br_prob_note (jmp, profile_probability::unlikely ());
3140 : 306 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, gt,
3141 : : gen_rtx_LABEL_REF (VOIDmode, l1), pc_rtx);
3142 : 306 : jmp = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
3143 : 306 : add_reg_br_prob_note (jmp, profile_probability::even ());
3144 : 306 : emit_move_insn (dest, constm1_rtx);
3145 : 306 : emit_jump (lend);
3146 : 306 : emit_label (l0);
3147 : 306 : emit_move_insn (dest, const0_rtx);
3148 : 306 : emit_jump (lend);
3149 : 306 : emit_label (l1);
3150 : 306 : emit_move_insn (dest, const1_rtx);
3151 : 306 : emit_jump (lend);
3152 : 306 : if (l2)
3153 : : {
3154 : 269 : emit_label (l2);
3155 : 269 : emit_move_insn (dest, const2_rtx);
3156 : : }
3157 : 306 : emit_label (lend);
3158 : 306 : }
3159 : :
3160 : : /* Expand comparison setting or clearing carry flag. Return true when
3161 : : successful and set pop for the operation. */
3162 : : static bool
3163 : 35683 : ix86_expand_carry_flag_compare (enum rtx_code code, rtx op0, rtx op1, rtx *pop)
3164 : : {
3165 : 71366 : machine_mode mode
3166 : 35683 : = GET_MODE (op0) != VOIDmode ? GET_MODE (op0) : GET_MODE (op1);
3167 : :
3168 : : /* Do not handle double-mode compares that go through special path. */
3169 : 35683 : if (mode == (TARGET_64BIT ? TImode : DImode))
3170 : : return false;
3171 : :
3172 : 35681 : if (SCALAR_FLOAT_MODE_P (mode))
3173 : : {
3174 : 353 : rtx compare_op;
3175 : 353 : rtx_insn *compare_seq;
3176 : :
3177 : 353 : gcc_assert (!DECIMAL_FLOAT_MODE_P (mode));
3178 : :
3179 : : /* Shortcut: following common codes never translate
3180 : : into carry flag compares. */
3181 : 353 : if (code == EQ || code == NE || code == UNEQ || code == LTGT
3182 : : || code == ORDERED || code == UNORDERED)
3183 : : return false;
3184 : :
3185 : : /* These comparisons require zero flag; swap operands so they won't. */
3186 : : if ((code == GT || code == UNLE || code == LE || code == UNGT)
3187 : 285 : && !TARGET_IEEE_FP)
3188 : : {
3189 : 8 : std::swap (op0, op1);
3190 : 8 : code = swap_condition (code);
3191 : : }
3192 : :
3193 : : /* Try to expand the comparison and verify that we end up with
3194 : : carry flag based comparison. This fails to be true only when
3195 : : we decide to expand comparison using arithmetic that is not
3196 : : too common scenario. */
3197 : 345 : start_sequence ();
3198 : 345 : compare_op = ix86_expand_fp_compare (code, op0, op1);
3199 : 345 : compare_seq = get_insns ();
3200 : 345 : end_sequence ();
3201 : :
3202 : 345 : if (GET_MODE (XEXP (compare_op, 0)) == CCFPmode)
3203 : 345 : code = ix86_fp_compare_code_to_integer (GET_CODE (compare_op));
3204 : : else
3205 : 0 : code = GET_CODE (compare_op);
3206 : :
3207 : 345 : if (code != LTU && code != GEU)
3208 : : return false;
3209 : :
3210 : 60 : emit_insn (compare_seq);
3211 : 60 : *pop = compare_op;
3212 : 60 : return true;
3213 : : }
3214 : :
3215 : 35328 : if (!INTEGRAL_MODE_P (mode))
3216 : : return false;
3217 : :
3218 : 35207 : switch (code)
3219 : : {
3220 : : case LTU:
3221 : : case GEU:
3222 : : break;
3223 : :
3224 : : /* Convert a==0 into (unsigned)a<1. */
3225 : 30986 : case EQ:
3226 : 30986 : case NE:
3227 : 30986 : if (op1 != const0_rtx)
3228 : : return false;
3229 : 12311 : op1 = const1_rtx;
3230 : 12311 : code = (code == EQ ? LTU : GEU);
3231 : : break;
3232 : :
3233 : : /* Convert a>b into b<a or a>=b-1. */
3234 : 712 : case GTU:
3235 : 712 : case LEU:
3236 : 712 : if (CONST_INT_P (op1))
3237 : : {
3238 : 710 : op1 = gen_int_mode (INTVAL (op1) + 1, GET_MODE (op0));
3239 : : /* Bail out on overflow. We still can swap operands but that
3240 : : would force loading of the constant into register. */
3241 : 710 : if (op1 == const0_rtx
3242 : 710 : || !x86_64_immediate_operand (op1, GET_MODE (op1)))
3243 : 0 : return false;
3244 : 710 : code = (code == GTU ? GEU : LTU);
3245 : : }
3246 : : else
3247 : : {
3248 : 2 : std::swap (op0, op1);
3249 : 2 : code = (code == GTU ? LTU : GEU);
3250 : : }
3251 : : break;
3252 : :
3253 : : /* Convert a>=0 into (unsigned)a<0x80000000. */
3254 : 1879 : case LT:
3255 : 1879 : case GE:
3256 : 1879 : if (mode == DImode || op1 != const0_rtx)
3257 : : return false;
3258 : 260 : op1 = gen_int_mode (1 << (GET_MODE_BITSIZE (mode) - 1), mode);
3259 : 130 : code = (code == LT ? GEU : LTU);
3260 : : break;
3261 : 717 : case LE:
3262 : 717 : case GT:
3263 : 717 : if (mode == DImode || op1 != constm1_rtx)
3264 : : return false;
3265 : 0 : op1 = gen_int_mode (1 << (GET_MODE_BITSIZE (mode) - 1), mode);
3266 : 0 : code = (code == LE ? GEU : LTU);
3267 : : break;
3268 : :
3269 : : default:
3270 : : return false;
3271 : : }
3272 : : /* Swapping operands may cause constant to appear as first operand. */
3273 : 14066 : if (!nonimmediate_operand (op0, VOIDmode))
3274 : : {
3275 : 0 : if (!can_create_pseudo_p ())
3276 : : return false;
3277 : 0 : op0 = force_reg (mode, op0);
3278 : : }
3279 : 14066 : *pop = ix86_expand_compare (code, op0, op1);
3280 : 14066 : gcc_assert (GET_CODE (*pop) == LTU || GET_CODE (*pop) == GEU);
3281 : : return true;
3282 : : }
3283 : :
3284 : : /* Expand conditional increment or decrement using adb/sbb instructions.
3285 : : The default case using setcc followed by the conditional move can be
3286 : : done by generic code. */
3287 : : bool
3288 : 8539 : ix86_expand_int_addcc (rtx operands[])
3289 : : {
3290 : 8539 : enum rtx_code code = GET_CODE (operands[1]);
3291 : 8539 : rtx flags;
3292 : 8539 : rtx (*insn) (machine_mode, rtx, rtx, rtx, rtx, rtx);
3293 : 8539 : rtx compare_op;
3294 : 8539 : rtx val = const0_rtx;
3295 : 8539 : bool fpcmp = false;
3296 : 8539 : machine_mode mode;
3297 : 8539 : rtx op0 = XEXP (operands[1], 0);
3298 : 8539 : rtx op1 = XEXP (operands[1], 1);
3299 : :
3300 : 8539 : if (operands[3] != const1_rtx
3301 : 4838 : && operands[3] != constm1_rtx)
3302 : : return false;
3303 : 5059 : if (!ix86_expand_carry_flag_compare (code, op0, op1, &compare_op))
3304 : : return false;
3305 : 927 : code = GET_CODE (compare_op);
3306 : :
3307 : 927 : flags = XEXP (compare_op, 0);
3308 : :
3309 : 927 : if (GET_MODE (flags) == CCFPmode)
3310 : : {
3311 : 4 : fpcmp = true;
3312 : 4 : code = ix86_fp_compare_code_to_integer (code);
3313 : : }
3314 : :
3315 : 927 : if (code != LTU)
3316 : : {
3317 : 518 : val = constm1_rtx;
3318 : 518 : if (fpcmp)
3319 : 4 : PUT_CODE (compare_op,
3320 : : reverse_condition_maybe_unordered
3321 : : (GET_CODE (compare_op)));
3322 : : else
3323 : 514 : PUT_CODE (compare_op, reverse_condition (GET_CODE (compare_op)));
3324 : : }
3325 : :
3326 : 927 : mode = GET_MODE (operands[0]);
3327 : :
3328 : : /* Construct either adc or sbb insn. */
3329 : 927 : if ((code == LTU) == (operands[3] == constm1_rtx))
3330 : : insn = gen_sub3_carry;
3331 : : else
3332 : 412 : insn = gen_add3_carry;
3333 : :
3334 : 927 : emit_insn (insn (mode, operands[0], operands[2], val, flags, compare_op));
3335 : :
3336 : 927 : return true;
3337 : : }
3338 : :
3339 : : bool
3340 : 391279 : ix86_expand_int_movcc (rtx operands[])
3341 : : {
3342 : 391279 : enum rtx_code code = GET_CODE (operands[1]), compare_code;
3343 : 391279 : rtx_insn *compare_seq;
3344 : 391279 : rtx compare_op;
3345 : 391279 : machine_mode mode = GET_MODE (operands[0]);
3346 : 391279 : bool sign_bit_compare_p = false;
3347 : 391279 : bool negate_cc_compare_p = false;
3348 : 391279 : rtx op0 = XEXP (operands[1], 0);
3349 : 391279 : rtx op1 = XEXP (operands[1], 1);
3350 : 391279 : rtx op2 = operands[2];
3351 : 391279 : rtx op3 = operands[3];
3352 : :
3353 : 391279 : if (GET_MODE (op0) == TImode
3354 : 375879 : || (GET_MODE (op0) == DImode
3355 : 123805 : && !TARGET_64BIT))
3356 : : return false;
3357 : :
3358 : 374527 : if (GET_MODE (op0) == BFmode
3359 : 374527 : && !ix86_fp_comparison_operator (operands[1], VOIDmode))
3360 : : return false;
3361 : :
3362 : 374526 : start_sequence ();
3363 : 374526 : compare_op = ix86_expand_compare (code, op0, op1);
3364 : 374526 : compare_seq = get_insns ();
3365 : 374526 : end_sequence ();
3366 : :
3367 : 374526 : compare_code = GET_CODE (compare_op);
3368 : :
3369 : 374526 : if ((op1 == const0_rtx && (code == GE || code == LT))
3370 : 350508 : || (op1 == constm1_rtx && (code == GT || code == LE)))
3371 : : sign_bit_compare_p = true;
3372 : :
3373 : : /* op0 == op1 ? op0 : op3 is equivalent to op0 == op1 ? op1 : op3,
3374 : : but if op1 is a constant, the latter form allows more optimizations,
3375 : : either through the last 2 ops being constant handling, or the one
3376 : : constant and one variable cases. On the other side, for cmov the
3377 : : former might be better as we don't need to load the constant into
3378 : : another register. */
3379 : 350508 : if (code == EQ && CONST_INT_P (op1) && rtx_equal_p (op0, op2))
3380 : : op2 = op1;
3381 : : /* Similarly for op0 != op1 ? op2 : op0 and op0 != op1 ? op2 : op1. */
3382 : 374202 : else if (code == NE && CONST_INT_P (op1) && rtx_equal_p (op0, op3))
3383 : : op3 = op1;
3384 : :
3385 : : /* Don't attempt mode expansion here -- if we had to expand 5 or 6
3386 : : HImode insns, we'd be swallowed in word prefix ops. */
3387 : :
3388 : 3927 : if ((mode != HImode || TARGET_FAST_PREFIX)
3389 : 374526 : && (mode != (TARGET_64BIT ? TImode : DImode))
3390 : 374526 : && CONST_INT_P (op2)
3391 : 411112 : && CONST_INT_P (op3))
3392 : : {
3393 : 32124 : rtx out = operands[0];
3394 : 32124 : HOST_WIDE_INT ct = INTVAL (op2);
3395 : 32124 : HOST_WIDE_INT cf = INTVAL (op3);
3396 : 32124 : HOST_WIDE_INT diff;
3397 : :
3398 : 32124 : if ((mode == SImode
3399 : 10916 : || (TARGET_64BIT && mode == DImode))
3400 : 24941 : && (GET_MODE (op0) == SImode
3401 : 19337 : || (TARGET_64BIT && GET_MODE (op0) == DImode)))
3402 : : {
3403 : : /* Special case x != 0 ? -1 : y. */
3404 : 20517 : if (code == NE && op1 == const0_rtx && ct == -1)
3405 : : {
3406 : : negate_cc_compare_p = true;
3407 : : std::swap (ct, cf);
3408 : : code = EQ;
3409 : : }
3410 : 20240 : else if (code == EQ && op1 == const0_rtx && cf == -1)
3411 : 32124 : negate_cc_compare_p = true;
3412 : : }
3413 : :
3414 : 32124 : diff = ct - cf;
3415 : : /* Sign bit compares are better done using shifts than we do by using
3416 : : sbb. */
3417 : 32124 : if (sign_bit_compare_p
3418 : 32124 : || negate_cc_compare_p
3419 : 32124 : || ix86_expand_carry_flag_compare (code, op0, op1, &compare_op))
3420 : : {
3421 : : /* Detect overlap between destination and compare sources. */
3422 : 14699 : rtx tmp = out;
3423 : :
3424 : 14699 : if (negate_cc_compare_p)
3425 : : {
3426 : 478 : if (GET_MODE (op0) == DImode)
3427 : 232 : emit_insn (gen_x86_negdi_ccc (gen_reg_rtx (DImode), op0));
3428 : : else
3429 : 246 : emit_insn (gen_x86_negsi_ccc (gen_reg_rtx (SImode),
3430 : 246 : gen_lowpart (SImode, op0)));
3431 : :
3432 : 478 : tmp = gen_reg_rtx (mode);
3433 : 478 : if (mode == DImode)
3434 : 236 : emit_insn (gen_x86_movdicc_0_m1_neg (tmp));
3435 : : else
3436 : 242 : emit_insn (gen_x86_movsicc_0_m1_neg (gen_lowpart (SImode,
3437 : : tmp)));
3438 : : }
3439 : 14221 : else if (!sign_bit_compare_p)
3440 : : {
3441 : 13199 : rtx flags;
3442 : 13199 : bool fpcmp = false;
3443 : :
3444 : 13199 : compare_code = GET_CODE (compare_op);
3445 : :
3446 : 13199 : flags = XEXP (compare_op, 0);
3447 : :
3448 : 13199 : if (GET_MODE (flags) == CCFPmode)
3449 : : {
3450 : 56 : fpcmp = true;
3451 : 56 : compare_code
3452 : 56 : = ix86_fp_compare_code_to_integer (compare_code);
3453 : : }
3454 : :
3455 : : /* To simplify rest of code, restrict to the GEU case. */
3456 : 13199 : if (compare_code == LTU)
3457 : : {
3458 : 8006 : std::swap (ct, cf);
3459 : 8006 : compare_code = reverse_condition (compare_code);
3460 : 8006 : code = reverse_condition (code);
3461 : : }
3462 : : else
3463 : : {
3464 : 5193 : if (fpcmp)
3465 : 52 : PUT_CODE (compare_op,
3466 : : reverse_condition_maybe_unordered
3467 : : (GET_CODE (compare_op)));
3468 : : else
3469 : 5141 : PUT_CODE (compare_op,
3470 : : reverse_condition (GET_CODE (compare_op)));
3471 : : }
3472 : 13199 : diff = ct - cf;
3473 : :
3474 : 13199 : if (reg_overlap_mentioned_p (out, compare_op))
3475 : 0 : tmp = gen_reg_rtx (mode);
3476 : :
3477 : 13199 : if (mode == DImode)
3478 : 1908 : emit_insn (gen_x86_movdicc_0_m1 (tmp, flags, compare_op));
3479 : : else
3480 : 11291 : emit_insn (gen_x86_movsicc_0_m1 (gen_lowpart (SImode, tmp),
3481 : : flags, compare_op));
3482 : : }
3483 : : else
3484 : : {
3485 : 1022 : if (code == GT || code == GE)
3486 : 173 : code = reverse_condition (code);
3487 : : else
3488 : : {
3489 : 849 : std::swap (ct, cf);
3490 : 849 : diff = ct - cf;
3491 : : }
3492 : 1022 : tmp = emit_store_flag (tmp, code, op0, op1, VOIDmode, 0, -1);
3493 : : }
3494 : :
3495 : 14699 : if (diff == 1)
3496 : : {
3497 : : /*
3498 : : * cmpl op0,op1
3499 : : * sbbl dest,dest
3500 : : * [addl dest, ct]
3501 : : *
3502 : : * Size 5 - 8.
3503 : : */
3504 : 1554 : if (ct)
3505 : 1412 : tmp = expand_simple_binop (mode, PLUS,
3506 : : tmp, GEN_INT (ct),
3507 : : copy_rtx (tmp), 1, OPTAB_DIRECT);
3508 : : }
3509 : 13145 : else if (cf == -1)
3510 : : {
3511 : : /*
3512 : : * cmpl op0,op1
3513 : : * sbbl dest,dest
3514 : : * orl $ct, dest
3515 : : *
3516 : : * Size 8.
3517 : : */
3518 : 925 : tmp = expand_simple_binop (mode, IOR,
3519 : : tmp, GEN_INT (ct),
3520 : : copy_rtx (tmp), 1, OPTAB_DIRECT);
3521 : : }
3522 : 12220 : else if (diff == -1 && ct)
3523 : : {
3524 : : /*
3525 : : * cmpl op0,op1
3526 : : * sbbl dest,dest
3527 : : * notl dest
3528 : : * [addl dest, cf]
3529 : : *
3530 : : * Size 8 - 11.
3531 : : */
3532 : 1370 : tmp = expand_simple_unop (mode, NOT, tmp, copy_rtx (tmp), 1);
3533 : 1370 : if (cf)
3534 : 1352 : tmp = expand_simple_binop (mode, PLUS,
3535 : : copy_rtx (tmp), GEN_INT (cf),
3536 : : copy_rtx (tmp), 1, OPTAB_DIRECT);
3537 : : }
3538 : : else
3539 : : {
3540 : : /*
3541 : : * cmpl op0,op1
3542 : : * sbbl dest,dest
3543 : : * [notl dest]
3544 : : * andl cf - ct, dest
3545 : : * [addl dest, ct]
3546 : : *
3547 : : * Size 8 - 11.
3548 : : */
3549 : :
3550 : 10850 : if (cf == 0)
3551 : : {
3552 : 789 : cf = ct;
3553 : 789 : ct = 0;
3554 : 789 : tmp = expand_simple_unop (mode, NOT, tmp, copy_rtx (tmp), 1);
3555 : : }
3556 : :
3557 : 10850 : tmp = expand_simple_binop (mode, AND,
3558 : : copy_rtx (tmp),
3559 : 10850 : gen_int_mode (cf - ct, mode),
3560 : : copy_rtx (tmp), 1, OPTAB_DIRECT);
3561 : 10850 : if (ct)
3562 : 8796 : tmp = expand_simple_binop (mode, PLUS,
3563 : : copy_rtx (tmp), GEN_INT (ct),
3564 : : copy_rtx (tmp), 1, OPTAB_DIRECT);
3565 : : }
3566 : :
3567 : 14699 : if (!rtx_equal_p (tmp, out))
3568 : 585 : emit_move_insn (copy_rtx (out), copy_rtx (tmp));
3569 : :
3570 : 14699 : return true;
3571 : : }
3572 : :
3573 : 17425 : if (diff < 0)
3574 : : {
3575 : 5605 : machine_mode cmp_mode = GET_MODE (op0);
3576 : 5605 : enum rtx_code new_code;
3577 : :
3578 : 5605 : if (SCALAR_FLOAT_MODE_P (cmp_mode))
3579 : : {
3580 : 69 : gcc_assert (!DECIMAL_FLOAT_MODE_P (cmp_mode));
3581 : :
3582 : : /* We may be reversing a non-trapping
3583 : : comparison to a trapping comparison. */
3584 : 122 : if (HONOR_NANS (cmp_mode) && flag_trapping_math
3585 : 45 : && code != EQ && code != NE
3586 : 114 : && code != ORDERED && code != UNORDERED)
3587 : : new_code = UNKNOWN;
3588 : : else
3589 : 24 : new_code = reverse_condition_maybe_unordered (code);
3590 : : }
3591 : : else
3592 : 5536 : new_code = ix86_reverse_condition (code, cmp_mode);
3593 : 5560 : if (new_code != UNKNOWN)
3594 : : {
3595 : 5560 : std::swap (ct, cf);
3596 : 5560 : diff = -diff;
3597 : 5560 : code = new_code;
3598 : : }
3599 : : }
3600 : :
3601 : 17425 : compare_code = UNKNOWN;
3602 : 17425 : if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT
3603 : 17204 : && CONST_INT_P (op1))
3604 : : {
3605 : 7950 : if (op1 == const0_rtx
3606 : 119 : && (code == LT || code == GE))
3607 : : compare_code = code;
3608 : 7950 : else if (op1 == constm1_rtx)
3609 : : {
3610 : 553 : if (code == LE)
3611 : : compare_code = LT;
3612 : 553 : else if (code == GT)
3613 : : compare_code = GE;
3614 : : }
3615 : : }
3616 : :
3617 : : /* Optimize dest = (op0 < 0) ? -1 : cf. */
3618 : : if (compare_code != UNKNOWN
3619 : 0 : && GET_MODE (op0) == GET_MODE (out)
3620 : 0 : && (cf == -1 || ct == -1))
3621 : : {
3622 : : /* If lea code below could be used, only optimize
3623 : : if it results in a 2 insn sequence. */
3624 : :
3625 : 0 : if (! (diff == 1 || diff == 2 || diff == 4 || diff == 8
3626 : 0 : || diff == 3 || diff == 5 || diff == 9)
3627 : 0 : || (compare_code == LT && ct == -1)
3628 : 0 : || (compare_code == GE && cf == -1))
3629 : : {
3630 : : /*
3631 : : * notl op1 (if necessary)
3632 : : * sarl $31, op1
3633 : : * orl cf, op1
3634 : : */
3635 : 0 : if (ct != -1)
3636 : : {
3637 : 0 : cf = ct;
3638 : 0 : ct = -1;
3639 : 0 : code = reverse_condition (code);
3640 : : }
3641 : :
3642 : 0 : out = emit_store_flag (out, code, op0, op1, VOIDmode, 0, -1);
3643 : :
3644 : 0 : out = expand_simple_binop (mode, IOR,
3645 : : out, GEN_INT (cf),
3646 : : out, 1, OPTAB_DIRECT);
3647 : 0 : if (out != operands[0])
3648 : 0 : emit_move_insn (operands[0], out);
3649 : :
3650 : 0 : return true;
3651 : : }
3652 : : }
3653 : :
3654 : :
3655 : 28396 : if ((diff == 1 || diff == 2 || diff == 4 || diff == 8
3656 : 10971 : || diff == 3 || diff == 5 || diff == 9)
3657 : 6833 : && ((mode != QImode && mode != HImode) || !TARGET_PARTIAL_REG_STALL)
3658 : 24258 : && (mode != DImode
3659 : 483 : || x86_64_immediate_operand (GEN_INT (cf), VOIDmode)))
3660 : : {
3661 : : /*
3662 : : * xorl dest,dest
3663 : : * cmpl op1,op2
3664 : : * setcc dest
3665 : : * lea cf(dest*(ct-cf)),dest
3666 : : *
3667 : : * Size 14.
3668 : : *
3669 : : * This also catches the degenerate setcc-only case.
3670 : : */
3671 : :
3672 : 6833 : rtx tmp;
3673 : 6833 : int nops;
3674 : :
3675 : 6833 : out = emit_store_flag (out, code, op0, op1, VOIDmode, 0, 1);
3676 : :
3677 : 6833 : nops = 0;
3678 : : /* On x86_64 the lea instruction operates on Pmode, so we need
3679 : : to get arithmetics done in proper mode to match. */
3680 : 6833 : if (diff == 1)
3681 : 5568 : tmp = copy_rtx (out);
3682 : : else
3683 : : {
3684 : 1265 : rtx out1;
3685 : 1265 : out1 = copy_rtx (out);
3686 : 1265 : tmp = gen_rtx_MULT (mode, out1, GEN_INT (diff & ~1));
3687 : 1265 : nops++;
3688 : 1265 : if (diff & 1)
3689 : : {
3690 : 337 : tmp = gen_rtx_PLUS (mode, tmp, out1);
3691 : 337 : nops++;
3692 : : }
3693 : : }
3694 : 6833 : if (cf != 0)
3695 : : {
3696 : 5721 : tmp = plus_constant (mode, tmp, cf);
3697 : 5721 : nops++;
3698 : : }
3699 : 6833 : if (!rtx_equal_p (tmp, out))
3700 : : {
3701 : 5952 : if (nops == 1)
3702 : 4715 : out = force_operand (tmp, copy_rtx (out));
3703 : : else
3704 : 1237 : emit_insn (gen_rtx_SET (copy_rtx (out), copy_rtx (tmp)));
3705 : : }
3706 : 6833 : if (!rtx_equal_p (out, operands[0]))
3707 : 1008 : emit_move_insn (operands[0], copy_rtx (out));
3708 : :
3709 : 6833 : return true;
3710 : : }
3711 : :
3712 : : /*
3713 : : * General case: Jumpful:
3714 : : * xorl dest,dest cmpl op1, op2
3715 : : * cmpl op1, op2 movl ct, dest
3716 : : * setcc dest jcc 1f
3717 : : * decl dest movl cf, dest
3718 : : * andl (cf-ct),dest 1:
3719 : : * addl ct,dest
3720 : : *
3721 : : * Size 20. Size 14.
3722 : : *
3723 : : * This is reasonably steep, but branch mispredict costs are
3724 : : * high on modern cpus, so consider failing only if optimizing
3725 : : * for space.
3726 : : */
3727 : :
3728 : 10592 : if ((!TARGET_CMOVE || (mode == QImode && TARGET_PARTIAL_REG_STALL))
3729 : 10592 : && BRANCH_COST (optimize_insn_for_speed_p (),
3730 : : false) >= 2)
3731 : : {
3732 : 0 : if (cf == 0)
3733 : : {
3734 : 0 : machine_mode cmp_mode = GET_MODE (op0);
3735 : 0 : enum rtx_code new_code;
3736 : :
3737 : 0 : if (SCALAR_FLOAT_MODE_P (cmp_mode))
3738 : : {
3739 : 0 : gcc_assert (!DECIMAL_FLOAT_MODE_P (cmp_mode));
3740 : :
3741 : : /* We may be reversing a non-trapping
3742 : : comparison to a trapping comparison. */
3743 : 0 : if (HONOR_NANS (cmp_mode) && flag_trapping_math
3744 : 0 : && code != EQ && code != NE
3745 : 0 : && code != ORDERED && code != UNORDERED)
3746 : : new_code = UNKNOWN;
3747 : : else
3748 : 0 : new_code = reverse_condition_maybe_unordered (code);
3749 : :
3750 : : }
3751 : : else
3752 : : {
3753 : 0 : new_code = ix86_reverse_condition (code, cmp_mode);
3754 : 0 : if (compare_code != UNKNOWN && new_code != UNKNOWN)
3755 : 0 : compare_code = reverse_condition (compare_code);
3756 : : }
3757 : :
3758 : 0 : if (new_code != UNKNOWN)
3759 : : {
3760 : 0 : cf = ct;
3761 : 0 : ct = 0;
3762 : 0 : code = new_code;
3763 : : }
3764 : : }
3765 : :
3766 : 0 : if (compare_code != UNKNOWN)
3767 : : {
3768 : : /* notl op1 (if needed)
3769 : : sarl $31, op1
3770 : : andl (cf-ct), op1
3771 : : addl ct, op1
3772 : :
3773 : : For x < 0 (resp. x <= -1) there will be no notl,
3774 : : so if possible swap the constants to get rid of the
3775 : : complement.
3776 : : True/false will be -1/0 while code below (store flag
3777 : : followed by decrement) is 0/-1, so the constants need
3778 : : to be exchanged once more. */
3779 : :
3780 : 0 : if (compare_code == GE || !cf)
3781 : : {
3782 : 0 : code = reverse_condition (code);
3783 : 0 : compare_code = LT;
3784 : : }
3785 : : else
3786 : : std::swap (ct, cf);
3787 : :
3788 : 0 : out = emit_store_flag (out, code, op0, op1, VOIDmode, 0, -1);
3789 : : }
3790 : : else
3791 : : {
3792 : 0 : out = emit_store_flag (out, code, op0, op1, VOIDmode, 0, 1);
3793 : :
3794 : 0 : out = expand_simple_binop (mode, PLUS, copy_rtx (out),
3795 : : constm1_rtx,
3796 : : copy_rtx (out), 1, OPTAB_DIRECT);
3797 : : }
3798 : :
3799 : 0 : out = expand_simple_binop (mode, AND, copy_rtx (out),
3800 : 0 : gen_int_mode (cf - ct, mode),
3801 : : copy_rtx (out), 1, OPTAB_DIRECT);
3802 : 0 : if (ct)
3803 : 0 : out = expand_simple_binop (mode, PLUS, copy_rtx (out), GEN_INT (ct),
3804 : : copy_rtx (out), 1, OPTAB_DIRECT);
3805 : 0 : if (!rtx_equal_p (out, operands[0]))
3806 : 0 : emit_move_insn (operands[0], copy_rtx (out));
3807 : :
3808 : 0 : return true;
3809 : : }
3810 : : }
3811 : :
3812 : 352994 : if (!TARGET_CMOVE || (mode == QImode && TARGET_PARTIAL_REG_STALL))
3813 : : {
3814 : : /* Try a few things more with specific constants and a variable. */
3815 : :
3816 : 0 : optab op;
3817 : 0 : rtx var, orig_out, out, tmp;
3818 : :
3819 : 0 : if (BRANCH_COST (optimize_insn_for_speed_p (), false) <= 2)
3820 : : return false;
3821 : :
3822 : 0 : operands[2] = op2;
3823 : 0 : operands[3] = op3;
3824 : :
3825 : : /* If one of the two operands is an interesting constant, load a
3826 : : constant with the above and mask it in with a logical operation. */
3827 : :
3828 : 0 : if (CONST_INT_P (operands[2]))
3829 : : {
3830 : 0 : var = operands[3];
3831 : 0 : if (INTVAL (operands[2]) == 0 && operands[3] != constm1_rtx)
3832 : 0 : operands[3] = constm1_rtx, op = and_optab;
3833 : 0 : else if (INTVAL (operands[2]) == -1 && operands[3] != const0_rtx)
3834 : 0 : operands[3] = const0_rtx, op = ior_optab;
3835 : : else
3836 : : return false;
3837 : : }
3838 : 0 : else if (CONST_INT_P (operands[3]))
3839 : : {
3840 : 0 : var = operands[2];
3841 : 0 : if (INTVAL (operands[3]) == 0 && operands[2] != constm1_rtx)
3842 : : {
3843 : : /* For smin (x, 0), expand as "x < 0 ? x : 0" instead of
3844 : : "x <= 0 ? x : 0" to enable sign_bit_compare_p. */
3845 : 0 : if (code == LE && op1 == const0_rtx && rtx_equal_p (op0, var))
3846 : 0 : operands[1] = simplify_gen_relational (LT, VOIDmode,
3847 : 0 : GET_MODE (op0),
3848 : : op0, const0_rtx);
3849 : :
3850 : 0 : operands[2] = constm1_rtx;
3851 : 0 : op = and_optab;
3852 : : }
3853 : 0 : else if (INTVAL (operands[3]) == -1 && operands[3] != const0_rtx)
3854 : 0 : operands[2] = const0_rtx, op = ior_optab;
3855 : : else
3856 : : return false;
3857 : : }
3858 : : else
3859 : : return false;
3860 : :
3861 : 0 : orig_out = operands[0];
3862 : 0 : tmp = gen_reg_rtx (mode);
3863 : 0 : operands[0] = tmp;
3864 : :
3865 : : /* Recurse to get the constant loaded. */
3866 : 0 : if (!ix86_expand_int_movcc (operands))
3867 : : return false;
3868 : :
3869 : : /* Mask in the interesting variable. */
3870 : 0 : out = expand_binop (mode, op, var, tmp, orig_out, 0,
3871 : : OPTAB_WIDEN);
3872 : 0 : if (!rtx_equal_p (out, orig_out))
3873 : 0 : emit_move_insn (copy_rtx (orig_out), copy_rtx (out));
3874 : :
3875 : 0 : return true;
3876 : : }
3877 : :
3878 : : /*
3879 : : * For comparison with above,
3880 : : *
3881 : : * movl cf,dest
3882 : : * movl ct,tmp
3883 : : * cmpl op1,op2
3884 : : * cmovcc tmp,dest
3885 : : *
3886 : : * Size 15.
3887 : : */
3888 : :
3889 : 352994 : if (! nonimmediate_operand (operands[2], mode))
3890 : 25623 : operands[2] = force_reg (mode, operands[2]);
3891 : 352994 : if (! nonimmediate_operand (operands[3], mode))
3892 : 159614 : operands[3] = force_reg (mode, operands[3]);
3893 : :
3894 : 352994 : if (! register_operand (operands[2], VOIDmode)
3895 : 352994 : && (mode == QImode
3896 : 1062 : || ! register_operand (operands[3], VOIDmode)))
3897 : 1543 : operands[2] = force_reg (mode, operands[2]);
3898 : :
3899 : 352994 : if (mode == QImode
3900 : 352994 : && ! register_operand (operands[3], VOIDmode))
3901 : 592 : operands[3] = force_reg (mode, operands[3]);
3902 : :
3903 : 352994 : emit_insn (compare_seq);
3904 : 352994 : emit_insn (gen_rtx_SET (operands[0],
3905 : : gen_rtx_IF_THEN_ELSE (mode,
3906 : : compare_op, operands[2],
3907 : : operands[3])));
3908 : 352994 : return true;
3909 : : }
3910 : :
3911 : : /* Detect conditional moves that exactly match min/max operational
3912 : : semantics. Note that this is IEEE safe, as long as we don't
3913 : : interchange the operands.
3914 : :
3915 : : Returns FALSE if this conditional move doesn't match a MIN/MAX,
3916 : : and TRUE if the operation is successful and instructions are emitted. */
3917 : :
3918 : : static bool
3919 : 10003 : ix86_expand_sse_fp_minmax (rtx dest, enum rtx_code code, rtx cmp_op0,
3920 : : rtx cmp_op1, rtx if_true, rtx if_false)
3921 : : {
3922 : 10003 : machine_mode mode;
3923 : 10003 : bool is_min;
3924 : 10003 : rtx tmp;
3925 : :
3926 : 10003 : if (code == LT)
3927 : : ;
3928 : 6938 : else if (code == UNGE)
3929 : : std::swap (if_true, if_false);
3930 : : else
3931 : : return false;
3932 : :
3933 : 4488 : if (rtx_equal_p (cmp_op0, if_true) && rtx_equal_p (cmp_op1, if_false))
3934 : : is_min = true;
3935 : 3117 : else if (rtx_equal_p (cmp_op1, if_true) && rtx_equal_p (cmp_op0, if_false))
3936 : : is_min = false;
3937 : : else
3938 : 1511 : return false;
3939 : :
3940 : 2977 : mode = GET_MODE (dest);
3941 : :
3942 : : /* We want to check HONOR_NANS and HONOR_SIGNED_ZEROS here,
3943 : : but MODE may be a vector mode and thus not appropriate. */
3944 : 2977 : if (!flag_finite_math_only || flag_signed_zeros)
3945 : : {
3946 : 2977 : int u = is_min ? UNSPEC_IEEE_MIN : UNSPEC_IEEE_MAX;
3947 : 2977 : rtvec v;
3948 : :
3949 : 2977 : if_true = force_reg (mode, if_true);
3950 : 2977 : v = gen_rtvec (2, if_true, if_false);
3951 : 2977 : tmp = gen_rtx_UNSPEC (mode, v, u);
3952 : 2977 : }
3953 : : else
3954 : : {
3955 : 0 : code = is_min ? SMIN : SMAX;
3956 : 0 : if (MEM_P (if_true) && MEM_P (if_false))
3957 : 0 : if_true = force_reg (mode, if_true);
3958 : 0 : tmp = gen_rtx_fmt_ee (code, mode, if_true, if_false);
3959 : : }
3960 : :
3961 : 2977 : emit_insn (gen_rtx_SET (dest, tmp));
3962 : 2977 : return true;
3963 : : }
3964 : :
3965 : : /* Return true if MODE is valid for vector compare to mask register,
3966 : : Same result for conditionl vector move with mask register. */
3967 : : static bool
3968 : 17674 : ix86_valid_mask_cmp_mode (machine_mode mode)
3969 : : {
3970 : : /* XOP has its own vector conditional movement. */
3971 : 17674 : if (TARGET_XOP && !TARGET_AVX512F)
3972 : : return false;
3973 : :
3974 : : /* HFmode only supports vcmpsh whose dest is mask register. */
3975 : 17596 : if (TARGET_AVX512FP16 && mode == HFmode)
3976 : : return true;
3977 : :
3978 : : /* AVX512F is needed for mask operation. */
3979 : 17586 : if (!(TARGET_AVX512F && VECTOR_MODE_P (mode)))
3980 : : return false;
3981 : :
3982 : : /* AVX512BW is needed for vector QI/HImode,
3983 : : AVX512VL is needed for 128/256-bit vector. */
3984 : 2976 : machine_mode inner_mode = GET_MODE_INNER (mode);
3985 : 2976 : int vector_size = GET_MODE_SIZE (mode);
3986 : 2976 : if ((inner_mode == QImode || inner_mode == HImode) && !TARGET_AVX512BW)
3987 : : return false;
3988 : :
3989 : 2936 : return (vector_size == 64 && TARGET_EVEX512) || TARGET_AVX512VL;
3990 : : }
3991 : :
3992 : : /* Return true if integer mask comparison should be used. */
3993 : : static bool
3994 : 37969 : ix86_use_mask_cmp_p (machine_mode mode, machine_mode cmp_mode,
3995 : : rtx op_true, rtx op_false)
3996 : : {
3997 : 37969 : int vector_size = GET_MODE_SIZE (mode);
3998 : :
3999 : 37969 : if (cmp_mode == HFmode)
4000 : : return true;
4001 : 37959 : else if (vector_size < 16)
4002 : : return false;
4003 : 32347 : else if (vector_size == 64)
4004 : : return true;
4005 : 62724 : else if (GET_MODE_INNER (cmp_mode) == HFmode)
4006 : : return true;
4007 : :
4008 : : /* When op_true is NULL, op_false must be NULL, or vice versa. */
4009 : 31231 : gcc_assert (!op_true == !op_false);
4010 : :
4011 : : /* When op_true/op_false is NULL or cmp_mode is not valid mask cmp mode,
4012 : : vector dest is required. */
4013 : 31231 : if (!op_true || !ix86_valid_mask_cmp_mode (cmp_mode))
4014 : 29460 : return false;
4015 : :
4016 : : /* Exclude those that could be optimized in ix86_expand_sse_movcc. */
4017 : 1771 : if (op_false == CONST0_RTX (mode)
4018 : 961 : || op_true == CONST0_RTX (mode)
4019 : 672 : || (INTEGRAL_MODE_P (mode)
4020 : 508 : && (op_true == CONSTM1_RTX (mode)
4021 : 508 : || op_false == CONSTM1_RTX (mode))))
4022 : : return false;
4023 : :
4024 : : return true;
4025 : : }
4026 : :
4027 : : /* Expand an SSE comparison. Return the register with the result. */
4028 : :
4029 : : static rtx
4030 : 26305 : ix86_expand_sse_cmp (rtx dest, enum rtx_code code, rtx cmp_op0, rtx cmp_op1,
4031 : : rtx op_true, rtx op_false)
4032 : : {
4033 : 26305 : machine_mode mode = GET_MODE (dest);
4034 : 26305 : machine_mode cmp_ops_mode = GET_MODE (cmp_op0);
4035 : :
4036 : : /* In general case result of comparison can differ from operands' type. */
4037 : 26305 : machine_mode cmp_mode;
4038 : :
4039 : : /* In AVX512F the result of comparison is an integer mask. */
4040 : 26305 : bool maskcmp = false;
4041 : 26305 : rtx x;
4042 : :
4043 : 26305 : if (ix86_use_mask_cmp_p (mode, cmp_ops_mode, op_true, op_false))
4044 : : {
4045 : 1054 : unsigned int nbits = GET_MODE_NUNITS (cmp_ops_mode);
4046 : 1054 : maskcmp = true;
4047 : 1054 : cmp_mode = nbits > 8 ? int_mode_for_size (nbits, 0).require () : E_QImode;
4048 : : }
4049 : : else
4050 : : cmp_mode = cmp_ops_mode;
4051 : :
4052 : 26305 : cmp_op0 = force_reg (cmp_ops_mode, cmp_op0);
4053 : :
4054 : 52610 : bool (*op1_predicate)(rtx, machine_mode)
4055 : 26305 : = VECTOR_MODE_P (cmp_ops_mode) ? vector_operand : nonimmediate_operand;
4056 : :
4057 : 26305 : if (!op1_predicate (cmp_op1, cmp_ops_mode))
4058 : 0 : cmp_op1 = force_reg (cmp_ops_mode, cmp_op1);
4059 : :
4060 : 26305 : if (optimize
4061 : 638 : || (maskcmp && cmp_mode != mode)
4062 : 605 : || (op_true && reg_overlap_mentioned_p (dest, op_true))
4063 : 26910 : || (op_false && reg_overlap_mentioned_p (dest, op_false)))
4064 : 50346 : dest = gen_reg_rtx (maskcmp ? cmp_mode : mode);
4065 : :
4066 : 26305 : if (maskcmp)
4067 : : {
4068 : 1054 : bool ok = ix86_expand_mask_vec_cmp (dest, code, cmp_op0, cmp_op1);
4069 : 1054 : gcc_assert (ok);
4070 : : return dest;
4071 : : }
4072 : :
4073 : 25251 : x = gen_rtx_fmt_ee (code, cmp_mode, cmp_op0, cmp_op1);
4074 : :
4075 : 25251 : if (cmp_mode != mode)
4076 : : {
4077 : 6244 : x = force_reg (cmp_ops_mode, x);
4078 : 6244 : convert_move (dest, x, false);
4079 : : }
4080 : : else
4081 : 19007 : emit_insn (gen_rtx_SET (dest, x));
4082 : :
4083 : : return dest;
4084 : : }
4085 : :
4086 : : /* Emit x86 binary operand CODE in mode MODE for SSE vector
4087 : : instructions that can be performed using GP registers. */
4088 : :
4089 : : static void
4090 : 6039 : ix86_emit_vec_binop (enum rtx_code code, machine_mode mode,
4091 : : rtx dst, rtx src1, rtx src2)
4092 : : {
4093 : 6039 : rtx tmp;
4094 : :
4095 : 6039 : tmp = gen_rtx_SET (dst, gen_rtx_fmt_ee (code, mode, src1, src2));
4096 : :
4097 : 12078 : if (GET_MODE_SIZE (mode) <= GET_MODE_SIZE (SImode)
4098 : 6039 : && GET_MODE_CLASS (mode) == MODE_VECTOR_INT)
4099 : : {
4100 : 69 : rtx clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
4101 : 69 : tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, tmp, clob));
4102 : : }
4103 : :
4104 : 6039 : emit_insn (tmp);
4105 : 6039 : }
4106 : :
4107 : : /* Expand DEST = CMP ? OP_TRUE : OP_FALSE into a sequence of logical
4108 : : operations. This is used for both scalar and vector conditional moves. */
4109 : :
4110 : : void
4111 : 13437 : ix86_expand_sse_movcc (rtx dest, rtx cmp, rtx op_true, rtx op_false)
4112 : : {
4113 : 13437 : machine_mode mode = GET_MODE (dest);
4114 : 13437 : machine_mode cmpmode = GET_MODE (cmp);
4115 : 13437 : rtx x;
4116 : :
4117 : : /* Simplify trivial VEC_COND_EXPR to avoid ICE in pr97506. */
4118 : 13437 : if (rtx_equal_p (op_true, op_false))
4119 : : {
4120 : 1 : emit_move_insn (dest, op_true);
4121 : 1 : return;
4122 : : }
4123 : :
4124 : : /* If we have an integer mask and FP value then we need
4125 : : to cast mask to FP mode. */
4126 : 13436 : if (mode != cmpmode && VECTOR_MODE_P (cmpmode))
4127 : : {
4128 : 331 : cmp = force_reg (cmpmode, cmp);
4129 : 331 : cmp = gen_rtx_SUBREG (mode, cmp, 0);
4130 : : }
4131 : :
4132 : : /* In AVX512F the result of comparison is an integer mask. */
4133 : 13436 : if (mode != cmpmode
4134 : 1385 : && GET_MODE_CLASS (cmpmode) == MODE_INT)
4135 : : {
4136 : 1054 : gcc_assert (ix86_valid_mask_cmp_mode (mode));
4137 : : /* Using scalar/vector move with mask register. */
4138 : 1054 : cmp = force_reg (cmpmode, cmp);
4139 : : /* Optimize for mask zero. */
4140 : 2108 : op_true = (op_true != CONST0_RTX (mode)
4141 : 1054 : ? force_reg (mode, op_true) : op_true);
4142 : 2108 : op_false = (op_false != CONST0_RTX (mode)
4143 : 1054 : ? force_reg (mode, op_false) : op_false);
4144 : 1054 : if (op_true == CONST0_RTX (mode))
4145 : : {
4146 : 3 : if (cmpmode == E_DImode && !TARGET_64BIT)
4147 : : {
4148 : 0 : x = gen_reg_rtx (cmpmode);
4149 : 0 : emit_insn (gen_knotdi (x, cmp));
4150 : : }
4151 : : else
4152 : 3 : x = expand_simple_unop (cmpmode, NOT, cmp, NULL, 1);
4153 : : cmp = x;
4154 : : /* Reverse op_true op_false. */
4155 : : std::swap (op_true, op_false);
4156 : : }
4157 : :
4158 : 1054 : if (mode == HFmode)
4159 : 10 : emit_insn (gen_movhf_mask (dest, op_true, op_false, cmp));
4160 : : else
4161 : 1044 : emit_insn (gen_rtx_SET (dest,
4162 : : gen_rtx_VEC_MERGE (mode,
4163 : : op_true, op_false, cmp)));
4164 : 1054 : return;
4165 : : }
4166 : :
4167 : 12382 : if (vector_all_ones_operand (op_true, mode)
4168 : 12382 : && op_false == CONST0_RTX (mode))
4169 : : {
4170 : 275 : emit_move_insn (dest, cmp);
4171 : 275 : return;
4172 : : }
4173 : 12107 : else if (op_false == CONST0_RTX (mode))
4174 : : {
4175 : 5875 : x = expand_simple_binop (mode, AND, cmp, op_true,
4176 : : dest, 1, OPTAB_DIRECT);
4177 : 5875 : if (x != dest)
4178 : 0 : emit_move_insn (dest, x);
4179 : 5875 : return;
4180 : : }
4181 : 6232 : else if (op_true == CONST0_RTX (mode))
4182 : : {
4183 : 932 : op_false = force_reg (mode, op_false);
4184 : 932 : x = gen_rtx_NOT (mode, cmp);
4185 : 932 : ix86_emit_vec_binop (AND, mode, dest, x, op_false);
4186 : 932 : return;
4187 : : }
4188 : 5300 : else if (vector_all_ones_operand (op_true, mode))
4189 : : {
4190 : 21 : x = expand_simple_binop (mode, IOR, cmp, op_false,
4191 : : dest, 1, OPTAB_DIRECT);
4192 : 21 : if (x != dest)
4193 : 0 : emit_move_insn (dest, x);
4194 : 21 : return;
4195 : : }
4196 : :
4197 : 5279 : if (TARGET_XOP)
4198 : : {
4199 : 88 : op_true = force_reg (mode, op_true);
4200 : :
4201 : 88 : if (GET_MODE_SIZE (mode) < 16
4202 : 88 : || !nonimmediate_operand (op_false, mode))
4203 : 64 : op_false = force_reg (mode, op_false);
4204 : :
4205 : 88 : emit_insn (gen_rtx_SET (dest,
4206 : : gen_rtx_IF_THEN_ELSE (mode, cmp,
4207 : : op_true, op_false)));
4208 : 88 : return;
4209 : : }
4210 : :
4211 : 5191 : rtx (*gen) (rtx, rtx, rtx, rtx) = NULL;
4212 : 5191 : machine_mode blend_mode = mode;
4213 : :
4214 : 5191 : if (GET_MODE_SIZE (mode) < 16
4215 : 5191 : || !vector_operand (op_true, mode))
4216 : 2549 : op_true = force_reg (mode, op_true);
4217 : :
4218 : 5191 : op_false = force_reg (mode, op_false);
4219 : :
4220 : 5191 : switch (mode)
4221 : : {
4222 : 23 : case E_V2SFmode:
4223 : 23 : if (TARGET_SSE4_1)
4224 : : gen = gen_mmx_blendvps;
4225 : : break;
4226 : 105 : case E_V4SFmode:
4227 : 105 : if (TARGET_SSE4_1)
4228 : : gen = gen_sse4_1_blendvps;
4229 : : break;
4230 : 136 : case E_V2DFmode:
4231 : 136 : if (TARGET_SSE4_1)
4232 : : gen = gen_sse4_1_blendvpd;
4233 : : break;
4234 : 871 : case E_SFmode:
4235 : 871 : if (TARGET_SSE4_1)
4236 : : gen = gen_sse4_1_blendvss;
4237 : : break;
4238 : 1161 : case E_DFmode:
4239 : 1161 : if (TARGET_SSE4_1)
4240 : : gen = gen_sse4_1_blendvsd;
4241 : : break;
4242 : 403 : case E_V8QImode:
4243 : 403 : case E_V4HImode:
4244 : 403 : case E_V4HFmode:
4245 : 403 : case E_V4BFmode:
4246 : 403 : case E_V2SImode:
4247 : 403 : if (TARGET_SSE4_1)
4248 : : {
4249 : : gen = gen_mmx_pblendvb_v8qi;
4250 : : blend_mode = V8QImode;
4251 : : }
4252 : : break;
4253 : 59 : case E_V4QImode:
4254 : 59 : case E_V2HImode:
4255 : 59 : case E_V2HFmode:
4256 : 59 : case E_V2BFmode:
4257 : 59 : if (TARGET_SSE4_1)
4258 : : {
4259 : : gen = gen_mmx_pblendvb_v4qi;
4260 : : blend_mode = V4QImode;
4261 : : }
4262 : : break;
4263 : 32 : case E_V2QImode:
4264 : 32 : if (TARGET_SSE4_1)
4265 : : gen = gen_mmx_pblendvb_v2qi;
4266 : : break;
4267 : 2168 : case E_V16QImode:
4268 : 2168 : case E_V8HImode:
4269 : 2168 : case E_V8HFmode:
4270 : 2168 : case E_V8BFmode:
4271 : 2168 : case E_V4SImode:
4272 : 2168 : case E_V2DImode:
4273 : 2168 : case E_V1TImode:
4274 : 2168 : if (TARGET_SSE4_1)
4275 : : {
4276 : : gen = gen_sse4_1_pblendvb;
4277 : : blend_mode = V16QImode;
4278 : : }
4279 : : break;
4280 : 38 : case E_V8SFmode:
4281 : 38 : if (TARGET_AVX)
4282 : : gen = gen_avx_blendvps256;
4283 : : break;
4284 : 54 : case E_V4DFmode:
4285 : 54 : if (TARGET_AVX)
4286 : : gen = gen_avx_blendvpd256;
4287 : : break;
4288 : 141 : case E_V32QImode:
4289 : 141 : case E_V16HImode:
4290 : 141 : case E_V16HFmode:
4291 : 141 : case E_V16BFmode:
4292 : 141 : case E_V8SImode:
4293 : 141 : case E_V4DImode:
4294 : 141 : if (TARGET_AVX2)
4295 : : {
4296 : : gen = gen_avx2_pblendvb;
4297 : : blend_mode = V32QImode;
4298 : : }
4299 : : break;
4300 : :
4301 : 0 : case E_V64QImode:
4302 : 0 : gen = gen_avx512bw_blendmv64qi;
4303 : 0 : break;
4304 : 0 : case E_V32HImode:
4305 : 0 : gen = gen_avx512bw_blendmv32hi;
4306 : 0 : break;
4307 : 0 : case E_V32HFmode:
4308 : 0 : gen = gen_avx512bw_blendmv32hf;
4309 : 0 : break;
4310 : 0 : case E_V32BFmode:
4311 : 0 : gen = gen_avx512bw_blendmv32bf;
4312 : 0 : break;
4313 : 0 : case E_V16SImode:
4314 : 0 : gen = gen_avx512f_blendmv16si;
4315 : 0 : break;
4316 : 0 : case E_V8DImode:
4317 : 0 : gen = gen_avx512f_blendmv8di;
4318 : 0 : break;
4319 : 0 : case E_V8DFmode:
4320 : 0 : gen = gen_avx512f_blendmv8df;
4321 : 0 : break;
4322 : : case E_V16SFmode:
4323 : : gen = gen_avx512f_blendmv16sf;
4324 : : break;
4325 : :
4326 : : default:
4327 : : break;
4328 : : }
4329 : :
4330 : 0 : if (gen != NULL)
4331 : : {
4332 : 1109 : if (blend_mode == mode)
4333 : : x = dest;
4334 : : else
4335 : : {
4336 : 684 : x = gen_reg_rtx (blend_mode);
4337 : 684 : op_false = gen_lowpart (blend_mode, op_false);
4338 : 684 : op_true = gen_lowpart (blend_mode, op_true);
4339 : 684 : cmp = gen_lowpart (blend_mode, cmp);
4340 : : }
4341 : :
4342 : 1109 : emit_insn (gen (x, op_false, op_true, cmp));
4343 : :
4344 : 1109 : if (x != dest)
4345 : 684 : emit_move_insn (dest, gen_lowpart (mode, x));
4346 : : }
4347 : : else
4348 : : {
4349 : 4082 : rtx t2, t3;
4350 : :
4351 : 4082 : t2 = expand_simple_binop (mode, AND, op_true, cmp,
4352 : : NULL, 1, OPTAB_DIRECT);
4353 : :
4354 : 4082 : t3 = gen_reg_rtx (mode);
4355 : 4082 : x = gen_rtx_NOT (mode, cmp);
4356 : 4082 : ix86_emit_vec_binop (AND, mode, t3, x, op_false);
4357 : :
4358 : 4082 : x = expand_simple_binop (mode, IOR, t3, t2,
4359 : : dest, 1, OPTAB_DIRECT);
4360 : 4082 : if (x != dest)
4361 : 0 : emit_move_insn (dest, x);
4362 : : }
4363 : : }
4364 : :
4365 : : /* Swap, force into registers, or otherwise massage the two operands
4366 : : to an sse comparison with a mask result. Thus we differ a bit from
4367 : : ix86_prepare_fp_compare_args which expects to produce a flags result.
4368 : :
4369 : : The DEST operand exists to help determine whether to commute commutative
4370 : : operators. The POP0/POP1 operands are updated in place. The new
4371 : : comparison code is returned, or UNKNOWN if not implementable. */
4372 : :
4373 : : static enum rtx_code
4374 : 11811 : ix86_prepare_sse_fp_compare_args (rtx dest, enum rtx_code code,
4375 : : rtx *pop0, rtx *pop1)
4376 : : {
4377 : 11811 : switch (code)
4378 : : {
4379 : 49 : case LTGT:
4380 : 49 : case UNEQ:
4381 : : /* AVX supports all the needed comparisons. */
4382 : 49 : if (TARGET_AVX)
4383 : : break;
4384 : : /* We have no LTGT as an operator. We could implement it with
4385 : : NE & ORDERED, but this requires an extra temporary. It's
4386 : : not clear that it's worth it. */
4387 : : return UNKNOWN;
4388 : :
4389 : : case LT:
4390 : : case LE:
4391 : : case UNGT:
4392 : : case UNGE:
4393 : : /* These are supported directly. */
4394 : : break;
4395 : :
4396 : 5331 : case EQ:
4397 : 5331 : case NE:
4398 : 5331 : case UNORDERED:
4399 : 5331 : case ORDERED:
4400 : : /* AVX has 3 operand comparisons, no need to swap anything. */
4401 : 5331 : if (TARGET_AVX)
4402 : : break;
4403 : : /* For commutative operators, try to canonicalize the destination
4404 : : operand to be first in the comparison - this helps reload to
4405 : : avoid extra moves. */
4406 : 335 : if (!dest || !rtx_equal_p (dest, *pop1))
4407 : : break;
4408 : : /* FALLTHRU */
4409 : :
4410 : 5468 : case GE:
4411 : 5468 : case GT:
4412 : 5468 : case UNLE:
4413 : 5468 : case UNLT:
4414 : : /* These are not supported directly before AVX, and furthermore
4415 : : ix86_expand_sse_fp_minmax only optimizes LT/UNGE. Swap the
4416 : : comparison operands to transform into something that is
4417 : : supported. */
4418 : 5468 : std::swap (*pop0, *pop1);
4419 : 5468 : code = swap_condition (code);
4420 : 5468 : break;
4421 : :
4422 : 0 : default:
4423 : 0 : gcc_unreachable ();
4424 : : }
4425 : :
4426 : : return code;
4427 : : }
4428 : :
4429 : : /* Expand a floating-point conditional move. Return true if successful. */
4430 : :
4431 : : bool
4432 : 62467 : ix86_expand_fp_movcc (rtx operands[])
4433 : : {
4434 : 62467 : machine_mode mode = GET_MODE (operands[0]);
4435 : 62467 : enum rtx_code code = GET_CODE (operands[1]);
4436 : 62467 : rtx tmp, compare_op;
4437 : 62467 : rtx op0 = XEXP (operands[1], 0);
4438 : 62467 : rtx op1 = XEXP (operands[1], 1);
4439 : :
4440 : 62467 : if (GET_MODE (op0) == BFmode
4441 : 62467 : && !ix86_fp_comparison_operator (operands[1], VOIDmode))
4442 : : return false;
4443 : :
4444 : 62467 : if (SSE_FLOAT_MODE_SSEMATH_OR_HF_P (mode))
4445 : : {
4446 : 31379 : machine_mode cmode;
4447 : :
4448 : : /* Since we've no cmove for sse registers, don't force bad register
4449 : : allocation just to gain access to it. Deny movcc when the
4450 : : comparison mode doesn't match the move mode. */
4451 : 31379 : cmode = GET_MODE (op0);
4452 : 31379 : if (cmode == VOIDmode)
4453 : 0 : cmode = GET_MODE (op1);
4454 : 31379 : if (cmode != mode)
4455 : : return false;
4456 : :
4457 : 4891 : code = ix86_prepare_sse_fp_compare_args (operands[0], code, &op0, &op1);
4458 : 4891 : if (code == UNKNOWN)
4459 : : return false;
4460 : :
4461 : 4875 : if (ix86_expand_sse_fp_minmax (operands[0], code, op0, op1,
4462 : : operands[2], operands[3]))
4463 : : return true;
4464 : :
4465 : 2046 : tmp = ix86_expand_sse_cmp (operands[0], code, op0, op1,
4466 : : operands[2], operands[3]);
4467 : 2046 : ix86_expand_sse_movcc (operands[0], tmp, operands[2], operands[3]);
4468 : 2046 : return true;
4469 : : }
4470 : :
4471 : 31088 : if (GET_MODE (op0) == TImode
4472 : 31088 : || (GET_MODE (op0) == DImode
4473 : 56 : && !TARGET_64BIT))
4474 : : return false;
4475 : :
4476 : : /* The floating point conditional move instructions don't directly
4477 : : support conditions resulting from a signed integer comparison. */
4478 : :
4479 : 31032 : compare_op = ix86_expand_compare (code, op0, op1);
4480 : 31032 : if (!fcmov_comparison_operator (compare_op, VOIDmode))
4481 : : {
4482 : 119 : tmp = gen_reg_rtx (QImode);
4483 : 119 : ix86_expand_setcc (tmp, code, op0, op1);
4484 : :
4485 : 119 : compare_op = ix86_expand_compare (NE, tmp, const0_rtx);
4486 : : }
4487 : :
4488 : 31032 : emit_insn (gen_rtx_SET (operands[0],
4489 : : gen_rtx_IF_THEN_ELSE (mode, compare_op,
4490 : : operands[2], operands[3])));
4491 : :
4492 : 31032 : return true;
4493 : : }
4494 : :
4495 : : /* Helper for ix86_cmp_code_to_pcmp_immediate for int modes. */
4496 : :
4497 : : static int
4498 : 2613 : ix86_int_cmp_code_to_pcmp_immediate (enum rtx_code code)
4499 : : {
4500 : 2613 : switch (code)
4501 : : {
4502 : : case EQ:
4503 : : return 0;
4504 : 335 : case LT:
4505 : 335 : case LTU:
4506 : 335 : return 1;
4507 : 170 : case LE:
4508 : 170 : case LEU:
4509 : 170 : return 2;
4510 : 1129 : case NE:
4511 : 1129 : return 4;
4512 : 259 : case GE:
4513 : 259 : case GEU:
4514 : 259 : return 5;
4515 : 349 : case GT:
4516 : 349 : case GTU:
4517 : 349 : return 6;
4518 : 0 : default:
4519 : 0 : gcc_unreachable ();
4520 : : }
4521 : : }
4522 : :
4523 : : /* Helper for ix86_cmp_code_to_pcmp_immediate for fp modes. */
4524 : :
4525 : : static int
4526 : 1084 : ix86_fp_cmp_code_to_pcmp_immediate (enum rtx_code code)
4527 : : {
4528 : 1084 : switch (code)
4529 : : {
4530 : : case EQ:
4531 : : return 0x00;
4532 : 296 : case NE:
4533 : 296 : return 0x04;
4534 : 212 : case GT:
4535 : 212 : return 0x0e;
4536 : 86 : case LE:
4537 : 86 : return 0x02;
4538 : 13 : case GE:
4539 : 13 : return 0x0d;
4540 : 389 : case LT:
4541 : 389 : return 0x01;
4542 : 1 : case UNLE:
4543 : 1 : return 0x0a;
4544 : 1 : case UNLT:
4545 : 1 : return 0x09;
4546 : 7 : case UNGE:
4547 : 7 : return 0x05;
4548 : 1 : case UNGT:
4549 : 1 : return 0x06;
4550 : 1 : case UNEQ:
4551 : 1 : return 0x18;
4552 : 0 : case LTGT:
4553 : 0 : return 0x0c;
4554 : 1 : case ORDERED:
4555 : 1 : return 0x07;
4556 : 1 : case UNORDERED:
4557 : 1 : return 0x03;
4558 : 0 : default:
4559 : 0 : gcc_unreachable ();
4560 : : }
4561 : : }
4562 : :
4563 : : /* Return immediate value to be used in UNSPEC_PCMP
4564 : : for comparison CODE in MODE. */
4565 : :
4566 : : static int
4567 : 3697 : ix86_cmp_code_to_pcmp_immediate (enum rtx_code code, machine_mode mode)
4568 : : {
4569 : 3697 : if (FLOAT_MODE_P (mode))
4570 : 1084 : return ix86_fp_cmp_code_to_pcmp_immediate (code);
4571 : 2613 : return ix86_int_cmp_code_to_pcmp_immediate (code);
4572 : : }
4573 : :
4574 : : /* Expand AVX-512 vector comparison. */
4575 : :
4576 : : bool
4577 : 3697 : ix86_expand_mask_vec_cmp (rtx dest, enum rtx_code code, rtx cmp_op0, rtx cmp_op1)
4578 : : {
4579 : 3697 : machine_mode mask_mode = GET_MODE (dest);
4580 : 3697 : machine_mode cmp_mode = GET_MODE (cmp_op0);
4581 : 3697 : rtx imm = GEN_INT (ix86_cmp_code_to_pcmp_immediate (code, cmp_mode));
4582 : 3697 : int unspec_code;
4583 : 3697 : rtx unspec;
4584 : :
4585 : 3697 : switch (code)
4586 : : {
4587 : : case LEU:
4588 : : case GTU:
4589 : : case GEU:
4590 : : case LTU:
4591 : : unspec_code = UNSPEC_UNSIGNED_PCMP;
4592 : : break;
4593 : :
4594 : 3393 : default:
4595 : 3393 : unspec_code = UNSPEC_PCMP;
4596 : : }
4597 : :
4598 : 3697 : unspec = gen_rtx_UNSPEC (mask_mode, gen_rtvec (3, cmp_op0, cmp_op1, imm),
4599 : : unspec_code);
4600 : 3697 : emit_insn (gen_rtx_SET (dest, unspec));
4601 : :
4602 : 3697 : return true;
4603 : : }
4604 : :
4605 : : /* Expand fp vector comparison. */
4606 : :
4607 : : bool
4608 : 1786 : ix86_expand_fp_vec_cmp (rtx operands[])
4609 : : {
4610 : 1786 : enum rtx_code code = GET_CODE (operands[1]);
4611 : 1786 : rtx cmp;
4612 : :
4613 : 1786 : code = ix86_prepare_sse_fp_compare_args (operands[0], code,
4614 : : &operands[2], &operands[3]);
4615 : 1786 : if (code == UNKNOWN)
4616 : : {
4617 : 13 : rtx temp;
4618 : 13 : switch (GET_CODE (operands[1]))
4619 : : {
4620 : 0 : case LTGT:
4621 : 0 : temp = ix86_expand_sse_cmp (operands[0], ORDERED, operands[2],
4622 : : operands[3], NULL, NULL);
4623 : 0 : cmp = ix86_expand_sse_cmp (operands[0], NE, operands[2],
4624 : : operands[3], NULL, NULL);
4625 : 0 : code = AND;
4626 : 0 : break;
4627 : 13 : case UNEQ:
4628 : 13 : temp = ix86_expand_sse_cmp (operands[0], UNORDERED, operands[2],
4629 : : operands[3], NULL, NULL);
4630 : 13 : cmp = ix86_expand_sse_cmp (operands[0], EQ, operands[2],
4631 : : operands[3], NULL, NULL);
4632 : 13 : code = IOR;
4633 : 13 : break;
4634 : 0 : default:
4635 : 0 : gcc_unreachable ();
4636 : : }
4637 : 13 : cmp = expand_simple_binop (GET_MODE (cmp), code, temp, cmp, cmp, 1,
4638 : : OPTAB_DIRECT);
4639 : : }
4640 : : else
4641 : 1773 : cmp = ix86_expand_sse_cmp (operands[0], code, operands[2], operands[3],
4642 : : NULL, NULL);
4643 : :
4644 : 1786 : if (operands[0] != cmp)
4645 : 1691 : emit_move_insn (operands[0], cmp);
4646 : :
4647 : 1786 : return true;
4648 : : }
4649 : :
4650 : : static rtx
4651 : 11957 : ix86_expand_int_sse_cmp (rtx dest, enum rtx_code code, rtx cop0, rtx cop1,
4652 : : rtx op_true, rtx op_false, bool *negate)
4653 : : {
4654 : 11957 : machine_mode data_mode = GET_MODE (dest);
4655 : 11957 : machine_mode mode = GET_MODE (cop0);
4656 : 11957 : rtx x;
4657 : :
4658 : 11957 : *negate = false;
4659 : :
4660 : : /* XOP supports all of the comparisons on all 128-bit vector int types. */
4661 : 11957 : if (TARGET_XOP
4662 : 370 : && GET_MODE_CLASS (mode) == MODE_VECTOR_INT
4663 : 12327 : && GET_MODE_SIZE (mode) <= 16)
4664 : : ;
4665 : : /* AVX512F supports all of the comparsions
4666 : : on all 128/256/512-bit vector int types. */
4667 : 11664 : else if (ix86_use_mask_cmp_p (data_mode, mode, op_true, op_false))
4668 : : ;
4669 : : else
4670 : : {
4671 : : /* Canonicalize the comparison to EQ, GT, GTU. */
4672 : 10920 : switch (code)
4673 : : {
4674 : : case EQ:
4675 : : case GT:
4676 : : case GTU:
4677 : : break;
4678 : :
4679 : 649 : case LE:
4680 : 649 : case LEU:
4681 : : /* x <= cst can be handled as x < cst + 1 unless there is
4682 : : wrap around in cst + 1. */
4683 : 649 : if (GET_CODE (cop1) == CONST_VECTOR
4684 : 927 : && GET_MODE_INNER (mode) != TImode)
4685 : : {
4686 : 278 : unsigned int n_elts = GET_MODE_NUNITS (mode), i;
4687 : 278 : machine_mode eltmode = GET_MODE_INNER (mode);
4688 : 1883 : for (i = 0; i < n_elts; ++i)
4689 : : {
4690 : 1606 : rtx elt = CONST_VECTOR_ELT (cop1, i);
4691 : 1606 : if (!CONST_INT_P (elt))
4692 : : break;
4693 : 1606 : if (code == LE)
4694 : : {
4695 : : /* For LE punt if some element is signed maximum. */
4696 : 942 : if ((INTVAL (elt) & (GET_MODE_MASK (eltmode) >> 1))
4697 : : == (GET_MODE_MASK (eltmode) >> 1))
4698 : : break;
4699 : : }
4700 : : /* For LEU punt if some element is unsigned maximum. */
4701 : 664 : else if (elt == constm1_rtx)
4702 : : break;
4703 : : }
4704 : 278 : if (i == n_elts)
4705 : : {
4706 : 277 : rtvec v = rtvec_alloc (n_elts);
4707 : 2158 : for (i = 0; i < n_elts; ++i)
4708 : 1604 : RTVEC_ELT (v, i)
4709 : 1604 : = gen_int_mode (INTVAL (CONST_VECTOR_ELT (cop1, i)) + 1,
4710 : : eltmode);
4711 : 277 : cop1 = gen_rtx_CONST_VECTOR (mode, v);
4712 : 277 : std::swap (cop0, cop1);
4713 : 277 : code = code == LE ? GT : GTU;
4714 : : break;
4715 : : }
4716 : : }
4717 : : /* FALLTHRU */
4718 : 3449 : case NE:
4719 : 3449 : code = reverse_condition (code);
4720 : 3449 : *negate = true;
4721 : 3449 : break;
4722 : :
4723 : 389 : case GE:
4724 : 389 : case GEU:
4725 : : /* x >= cst can be handled as x > cst - 1 unless there is
4726 : : wrap around in cst - 1. */
4727 : 389 : if (GET_CODE (cop1) == CONST_VECTOR
4728 : 500 : && GET_MODE_INNER (mode) != TImode)
4729 : : {
4730 : 111 : unsigned int n_elts = GET_MODE_NUNITS (mode), i;
4731 : 111 : machine_mode eltmode = GET_MODE_INNER (mode);
4732 : 659 : for (i = 0; i < n_elts; ++i)
4733 : : {
4734 : 596 : rtx elt = CONST_VECTOR_ELT (cop1, i);
4735 : 596 : if (!CONST_INT_P (elt))
4736 : : break;
4737 : 596 : if (code == GE)
4738 : : {
4739 : : /* For GE punt if some element is signed minimum. */
4740 : 548 : if (INTVAL (elt) < 0
4741 : 136 : && ((INTVAL (elt) & (GET_MODE_MASK (eltmode) >> 1))
4742 : : == 0))
4743 : : break;
4744 : : }
4745 : : /* For GEU punt if some element is zero. */
4746 : 48 : else if (elt == const0_rtx)
4747 : : break;
4748 : : }
4749 : 111 : if (i == n_elts)
4750 : : {
4751 : 63 : rtvec v = rtvec_alloc (n_elts);
4752 : 674 : for (i = 0; i < n_elts; ++i)
4753 : 548 : RTVEC_ELT (v, i)
4754 : 548 : = gen_int_mode (INTVAL (CONST_VECTOR_ELT (cop1, i)) - 1,
4755 : : eltmode);
4756 : 63 : cop1 = gen_rtx_CONST_VECTOR (mode, v);
4757 : 63 : code = code == GE ? GT : GTU;
4758 : : break;
4759 : : }
4760 : : }
4761 : 326 : code = reverse_condition (code);
4762 : 326 : *negate = true;
4763 : : /* FALLTHRU */
4764 : :
4765 : 1448 : case LT:
4766 : 1448 : case LTU:
4767 : 1448 : std::swap (cop0, cop1);
4768 : 1448 : code = swap_condition (code);
4769 : 1448 : break;
4770 : :
4771 : 0 : default:
4772 : 0 : gcc_unreachable ();
4773 : : }
4774 : :
4775 : : /* Only SSE4.1/SSE4.2 supports V2DImode. */
4776 : 10920 : if (mode == V2DImode)
4777 : : {
4778 : 697 : switch (code)
4779 : : {
4780 : 491 : case EQ:
4781 : : /* SSE4.1 supports EQ. */
4782 : 491 : if (!TARGET_SSE4_1)
4783 : 0 : return NULL;
4784 : : break;
4785 : :
4786 : 206 : case GT:
4787 : 206 : case GTU:
4788 : : /* SSE4.2 supports GT/GTU. */
4789 : 206 : if (!TARGET_SSE4_2)
4790 : : return NULL;
4791 : : break;
4792 : :
4793 : 0 : default:
4794 : 0 : gcc_unreachable ();
4795 : : }
4796 : : }
4797 : :
4798 : 10920 : if (GET_CODE (cop0) == CONST_VECTOR)
4799 : 607 : cop0 = force_reg (mode, cop0);
4800 : 10313 : else if (GET_CODE (cop1) == CONST_VECTOR)
4801 : 4202 : cop1 = force_reg (mode, cop1);
4802 : :
4803 : 10920 : rtx optrue = op_true ? op_true : CONSTM1_RTX (data_mode);
4804 : 10920 : rtx opfalse = op_false ? op_false : CONST0_RTX (data_mode);
4805 : 10920 : if (*negate)
4806 : 3775 : std::swap (optrue, opfalse);
4807 : :
4808 : : /* Transform x > y ? 0 : -1 (i.e. x <= y ? -1 : 0 or x <= y) when
4809 : : not using integer masks into min (x, y) == x ? -1 : 0 (i.e.
4810 : : min (x, y) == x). While we add one instruction (the minimum),
4811 : : we remove the need for two instructions in the negation, as the
4812 : : result is done this way.
4813 : : When using masks, do it for SI/DImode element types, as it is shorter
4814 : : than the two subtractions. */
4815 : 10920 : if ((code != EQ
4816 : 3980 : && GET_MODE_SIZE (mode) != 64
4817 : 3980 : && vector_all_ones_operand (opfalse, data_mode)
4818 : 398 : && optrue == CONST0_RTX (data_mode))
4819 : 14502 : || (code == GTU
4820 : 1604 : && GET_MODE_SIZE (GET_MODE_INNER (mode)) >= 4
4821 : : /* Don't do it if not using integer masks and we'd end up with
4822 : : the right values in the registers though. */
4823 : 497 : && ((GET_MODE_SIZE (mode) == 64 && TARGET_EVEX512)
4824 : 497 : || !vector_all_ones_operand (optrue, data_mode)
4825 : 259 : || opfalse != CONST0_RTX (data_mode))))
4826 : : {
4827 : 636 : rtx (*gen) (rtx, rtx, rtx) = NULL;
4828 : :
4829 : 636 : switch (mode)
4830 : : {
4831 : 0 : case E_V16SImode:
4832 : 0 : gen = (code == GTU) ? gen_uminv16si3 : gen_sminv16si3;
4833 : : break;
4834 : 0 : case E_V8DImode:
4835 : 0 : gen = (code == GTU) ? gen_uminv8di3 : gen_sminv8di3;
4836 : 0 : cop0 = force_reg (mode, cop0);
4837 : 0 : cop1 = force_reg (mode, cop1);
4838 : 0 : break;
4839 : 24 : case E_V32QImode:
4840 : 24 : if (TARGET_AVX2)
4841 : 24 : gen = (code == GTU) ? gen_uminv32qi3 : gen_sminv32qi3;
4842 : : break;
4843 : 24 : case E_V16HImode:
4844 : 24 : if (TARGET_AVX2)
4845 : 24 : gen = (code == GTU) ? gen_uminv16hi3 : gen_sminv16hi3;
4846 : : break;
4847 : 27 : case E_V8SImode:
4848 : 27 : if (TARGET_AVX2)
4849 : 27 : gen = (code == GTU) ? gen_uminv8si3 : gen_sminv8si3;
4850 : : break;
4851 : 28 : case E_V4DImode:
4852 : 28 : if (TARGET_AVX512VL)
4853 : : {
4854 : 8 : gen = (code == GTU) ? gen_uminv4di3 : gen_sminv4di3;
4855 : 8 : cop0 = force_reg (mode, cop0);
4856 : 8 : cop1 = force_reg (mode, cop1);
4857 : : }
4858 : : break;
4859 : 55 : case E_V16QImode:
4860 : 55 : if (code == GTU && TARGET_SSE2)
4861 : : gen = gen_uminv16qi3;
4862 : 18 : else if (code == GT && TARGET_SSE4_1)
4863 : : gen = gen_sminv16qi3;
4864 : : break;
4865 : 8 : case E_V8QImode:
4866 : 8 : if (code == GTU && TARGET_SSE2)
4867 : : gen = gen_uminv8qi3;
4868 : 6 : else if (code == GT && TARGET_SSE4_1)
4869 : : gen = gen_sminv8qi3;
4870 : : break;
4871 : 15 : case E_V4QImode:
4872 : 15 : if (code == GTU && TARGET_SSE2)
4873 : : gen = gen_uminv4qi3;
4874 : 2 : else if (code == GT && TARGET_SSE4_1)
4875 : : gen = gen_sminv4qi3;
4876 : : break;
4877 : 8 : case E_V2QImode:
4878 : 8 : if (code == GTU && TARGET_SSE2)
4879 : : gen = gen_uminv2qi3;
4880 : 6 : else if (code == GT && TARGET_SSE4_1)
4881 : : gen = gen_sminv2qi3;
4882 : : break;
4883 : 55 : case E_V8HImode:
4884 : 55 : if (code == GTU && TARGET_SSE4_1)
4885 : : gen = gen_uminv8hi3;
4886 : 47 : else if (code == GT && TARGET_SSE2)
4887 : : gen = gen_sminv8hi3;
4888 : : break;
4889 : 4 : case E_V4HImode:
4890 : 4 : if (code == GTU && TARGET_SSE4_1)
4891 : : gen = gen_uminv4hi3;
4892 : 4 : else if (code == GT && TARGET_SSE2)
4893 : : gen = gen_sminv4hi3;
4894 : : break;
4895 : 10 : case E_V2HImode:
4896 : 10 : if (code == GTU && TARGET_SSE4_1)
4897 : : gen = gen_uminv2hi3;
4898 : 10 : else if (code == GT && TARGET_SSE2)
4899 : : gen = gen_sminv2hi3;
4900 : : break;
4901 : 266 : case E_V4SImode:
4902 : 266 : if (TARGET_SSE4_1)
4903 : 62 : gen = (code == GTU) ? gen_uminv4si3 : gen_sminv4si3;
4904 : : break;
4905 : 59 : case E_V2SImode:
4906 : 59 : if (TARGET_SSE4_1)
4907 : 4 : gen = (code == GTU) ? gen_uminv2si3 : gen_sminv2si3;
4908 : : break;
4909 : 53 : case E_V2DImode:
4910 : 53 : if (TARGET_AVX512VL)
4911 : : {
4912 : 0 : gen = (code == GTU) ? gen_uminv2di3 : gen_sminv2di3;
4913 : 0 : cop0 = force_reg (mode, cop0);
4914 : 0 : cop1 = force_reg (mode, cop1);
4915 : : }
4916 : : break;
4917 : : default:
4918 : : break;
4919 : : }
4920 : :
4921 : 8 : if (gen)
4922 : : {
4923 : 249 : rtx tem = gen_reg_rtx (mode);
4924 : 249 : if (!vector_operand (cop0, mode))
4925 : 0 : cop0 = force_reg (mode, cop0);
4926 : 249 : if (!vector_operand (cop1, mode))
4927 : 0 : cop1 = force_reg (mode, cop1);
4928 : 249 : *negate = !*negate;
4929 : 249 : emit_insn (gen (tem, cop0, cop1));
4930 : 249 : cop1 = tem;
4931 : 249 : code = EQ;
4932 : : }
4933 : : }
4934 : :
4935 : : /* Unsigned parallel compare is not supported by the hardware.
4936 : : Play some tricks to turn this into a signed comparison
4937 : : against 0. */
4938 : 10920 : if (code == GTU)
4939 : : {
4940 : 839 : cop0 = force_reg (mode, cop0);
4941 : :
4942 : 839 : switch (mode)
4943 : : {
4944 : 503 : case E_V16SImode:
4945 : 503 : case E_V8DImode:
4946 : 503 : case E_V8SImode:
4947 : 503 : case E_V4DImode:
4948 : 503 : case E_V4SImode:
4949 : 503 : case E_V2SImode:
4950 : 503 : case E_V2DImode:
4951 : 503 : {
4952 : 503 : rtx t1, t2, mask;
4953 : :
4954 : : /* Subtract (-(INT MAX) - 1) from both operands to make
4955 : : them signed. */
4956 : 503 : mask = ix86_build_signbit_mask (mode, true, false);
4957 : 503 : t1 = gen_reg_rtx (mode);
4958 : 503 : emit_insn (gen_sub3_insn (t1, cop0, mask));
4959 : :
4960 : 503 : t2 = gen_reg_rtx (mode);
4961 : 503 : emit_insn (gen_sub3_insn (t2, cop1, mask));
4962 : :
4963 : 503 : cop0 = t1;
4964 : 503 : cop1 = t2;
4965 : 503 : code = GT;
4966 : : }
4967 : 503 : break;
4968 : :
4969 : 336 : case E_V64QImode:
4970 : 336 : case E_V32HImode:
4971 : 336 : case E_V32QImode:
4972 : 336 : case E_V16HImode:
4973 : 336 : case E_V16QImode:
4974 : 336 : case E_V8QImode:
4975 : 336 : case E_V4QImode:
4976 : 336 : case E_V2QImode:
4977 : 336 : case E_V8HImode:
4978 : 336 : case E_V4HImode:
4979 : 336 : case E_V2HImode:
4980 : : /* Perform a parallel unsigned saturating subtraction. */
4981 : 336 : x = gen_reg_rtx (mode);
4982 : 336 : emit_insn (gen_rtx_SET
4983 : : (x, gen_rtx_US_MINUS (mode, cop0, cop1)));
4984 : 336 : cop0 = x;
4985 : 336 : cop1 = CONST0_RTX (mode);
4986 : 336 : code = EQ;
4987 : 336 : *negate = !*negate;
4988 : 336 : break;
4989 : :
4990 : 0 : default:
4991 : 0 : gcc_unreachable ();
4992 : : }
4993 : : }
4994 : : }
4995 : :
4996 : 11957 : if (*negate)
4997 : 3890 : std::swap (op_true, op_false);
4998 : :
4999 : 11957 : if (GET_CODE (cop1) == CONST_VECTOR)
5000 : 356 : cop1 = force_reg (mode, cop1);
5001 : :
5002 : : /* Allow the comparison to be done in one mode, but the movcc to
5003 : : happen in another mode. */
5004 : 11957 : if (data_mode == mode)
5005 : 11666 : x = ix86_expand_sse_cmp (dest, code, cop0, cop1, op_true, op_false);
5006 : : else
5007 : : {
5008 : 873 : gcc_assert (GET_MODE_SIZE (data_mode) == GET_MODE_SIZE (mode));
5009 : 291 : x = ix86_expand_sse_cmp (gen_reg_rtx (mode), code, cop0, cop1,
5010 : : op_true, op_false);
5011 : 291 : if (GET_MODE (x) == mode)
5012 : 92 : x = gen_lowpart (data_mode, x);
5013 : : }
5014 : :
5015 : : return x;
5016 : : }
5017 : :
5018 : : /* Expand integer vector comparison. */
5019 : :
5020 : : bool
5021 : 4919 : ix86_expand_int_vec_cmp (rtx operands[])
5022 : : {
5023 : 4919 : rtx_code code = GET_CODE (operands[1]);
5024 : 4919 : bool negate = false;
5025 : 4919 : rtx cmp = ix86_expand_int_sse_cmp (operands[0], code, operands[2],
5026 : : operands[3], NULL, NULL, &negate);
5027 : :
5028 : 4919 : if (!cmp)
5029 : : return false;
5030 : :
5031 : 4919 : if (negate)
5032 : 2423 : cmp = ix86_expand_int_sse_cmp (operands[0], EQ, cmp,
5033 : 2423 : CONST0_RTX (GET_MODE (cmp)),
5034 : : NULL, NULL, &negate);
5035 : :
5036 : 4919 : gcc_assert (!negate);
5037 : :
5038 : 4919 : if (operands[0] != cmp)
5039 : 4641 : emit_move_insn (operands[0], cmp);
5040 : :
5041 : : return true;
5042 : : }
5043 : :
5044 : : /* Expand a floating-point vector conditional move; a vcond operation
5045 : : rather than a movcc operation. */
5046 : :
5047 : : bool
5048 : 5134 : ix86_expand_fp_vcond (rtx operands[])
5049 : : {
5050 : 5134 : enum rtx_code code = GET_CODE (operands[3]);
5051 : 5134 : rtx cmp;
5052 : :
5053 : 5134 : code = ix86_prepare_sse_fp_compare_args (operands[0], code,
5054 : : &operands[4], &operands[5]);
5055 : 5134 : if (code == UNKNOWN)
5056 : : {
5057 : 6 : rtx temp;
5058 : 6 : switch (GET_CODE (operands[3]))
5059 : : {
5060 : 2 : case LTGT:
5061 : 2 : temp = ix86_expand_sse_cmp (operands[0], ORDERED, operands[4],
5062 : : operands[5], operands[0], operands[0]);
5063 : 2 : cmp = ix86_expand_sse_cmp (operands[0], NE, operands[4],
5064 : : operands[5], operands[1], operands[2]);
5065 : 2 : code = AND;
5066 : 2 : break;
5067 : 4 : case UNEQ:
5068 : 4 : temp = ix86_expand_sse_cmp (operands[0], UNORDERED, operands[4],
5069 : : operands[5], operands[0], operands[0]);
5070 : 4 : cmp = ix86_expand_sse_cmp (operands[0], EQ, operands[4],
5071 : : operands[5], operands[1], operands[2]);
5072 : 4 : code = IOR;
5073 : 4 : break;
5074 : 0 : default:
5075 : 0 : gcc_unreachable ();
5076 : : }
5077 : 6 : cmp = expand_simple_binop (GET_MODE (cmp), code, temp, cmp, cmp, 1,
5078 : : OPTAB_DIRECT);
5079 : 6 : ix86_expand_sse_movcc (operands[0], cmp, operands[1], operands[2]);
5080 : 6 : return true;
5081 : : }
5082 : :
5083 : 5128 : if (ix86_expand_sse_fp_minmax (operands[0], code, operands[4],
5084 : : operands[5], operands[1], operands[2]))
5085 : : return true;
5086 : :
5087 : 4980 : cmp = ix86_expand_sse_cmp (operands[0], code, operands[4], operands[5],
5088 : : operands[1], operands[2]);
5089 : 4980 : ix86_expand_sse_movcc (operands[0], cmp, operands[1], operands[2]);
5090 : 4980 : return true;
5091 : : }
5092 : :
5093 : : /* Expand a signed/unsigned integral vector conditional move. */
5094 : :
5095 : : bool
5096 : 4634 : ix86_expand_int_vcond (rtx operands[])
5097 : : {
5098 : 4634 : machine_mode data_mode = GET_MODE (operands[0]);
5099 : 4634 : machine_mode mode = GET_MODE (operands[4]);
5100 : 4634 : enum rtx_code code = GET_CODE (operands[3]);
5101 : 4634 : bool negate = false;
5102 : 4634 : rtx x, cop0, cop1;
5103 : :
5104 : 4634 : cop0 = operands[4];
5105 : 4634 : cop1 = operands[5];
5106 : :
5107 : : /* Try to optimize x < 0 ? -1 : 0 into (signed) x >> 31
5108 : : and x < 0 ? 1 : 0 into (unsigned) x >> 31. */
5109 : 4634 : if ((code == LT || code == GE)
5110 : 885 : && data_mode == mode
5111 : 761 : && cop1 == CONST0_RTX (mode)
5112 : 515 : && operands[1 + (code == LT)] == CONST0_RTX (data_mode)
5113 : 236 : && GET_MODE_UNIT_SIZE (data_mode) > 1
5114 : 236 : && GET_MODE_UNIT_SIZE (data_mode) <= 8
5115 : 4870 : && (GET_MODE_SIZE (data_mode) == 16
5116 : 38 : || (TARGET_AVX2 && GET_MODE_SIZE (data_mode) == 32)))
5117 : : {
5118 : 235 : rtx negop = operands[2 - (code == LT)];
5119 : 235 : int shift = GET_MODE_UNIT_BITSIZE (data_mode) - 1;
5120 : 235 : if (negop == CONST1_RTX (data_mode))
5121 : : {
5122 : 15 : rtx res = expand_simple_binop (mode, LSHIFTRT, cop0, GEN_INT (shift),
5123 : : operands[0], 1, OPTAB_DIRECT);
5124 : 15 : if (res != operands[0])
5125 : 0 : emit_move_insn (operands[0], res);
5126 : 15 : return true;
5127 : : }
5128 : 220 : else if (GET_MODE_INNER (data_mode) != DImode
5129 : 220 : && vector_all_ones_operand (negop, data_mode))
5130 : : {
5131 : 4 : rtx res = expand_simple_binop (mode, ASHIFTRT, cop0, GEN_INT (shift),
5132 : : operands[0], 0, OPTAB_DIRECT);
5133 : 4 : if (res != operands[0])
5134 : 0 : emit_move_insn (operands[0], res);
5135 : 4 : return true;
5136 : : }
5137 : : }
5138 : :
5139 : 4615 : if (!nonimmediate_operand (cop1, mode))
5140 : 1217 : cop1 = force_reg (mode, cop1);
5141 : 4615 : if (!general_operand (operands[1], data_mode))
5142 : 1781 : operands[1] = force_reg (data_mode, operands[1]);
5143 : 4615 : if (!general_operand (operands[2], data_mode))
5144 : 105 : operands[2] = force_reg (data_mode, operands[2]);
5145 : :
5146 : 4615 : x = ix86_expand_int_sse_cmp (operands[0], code, cop0, cop1,
5147 : : operands[1], operands[2], &negate);
5148 : :
5149 : 4615 : if (!x)
5150 : : return false;
5151 : :
5152 : 4615 : ix86_expand_sse_movcc (operands[0], x, operands[1+negate],
5153 : 4615 : operands[2-negate]);
5154 : 4615 : return true;
5155 : : }
5156 : :
5157 : : static bool
5158 : 129113 : ix86_expand_vec_perm_vpermt2 (rtx target, rtx mask, rtx op0, rtx op1,
5159 : : struct expand_vec_perm_d *d)
5160 : : {
5161 : : /* ix86_expand_vec_perm_vpermt2 is called from both const and non-const
5162 : : expander, so args are either in d, or in op0, op1 etc. */
5163 : 129113 : machine_mode mode = GET_MODE (d ? d->op0 : op0);
5164 : 129113 : machine_mode maskmode = mode;
5165 : 129113 : rtx (*gen) (rtx, rtx, rtx, rtx) = NULL;
5166 : :
5167 : 129113 : switch (mode)
5168 : : {
5169 : 15269 : case E_V16QImode:
5170 : 15269 : if (TARGET_AVX512VL && TARGET_AVX512VBMI)
5171 : : gen = gen_avx512vl_vpermt2varv16qi3;
5172 : : break;
5173 : 1991 : case E_V32QImode:
5174 : 1991 : if (TARGET_AVX512VL && TARGET_AVX512VBMI)
5175 : : gen = gen_avx512vl_vpermt2varv32qi3;
5176 : : break;
5177 : 178 : case E_V64QImode:
5178 : 178 : if (TARGET_AVX512VBMI)
5179 : : gen = gen_avx512bw_vpermt2varv64qi3;
5180 : : break;
5181 : 13326 : case E_V8HImode:
5182 : 13326 : if (TARGET_AVX512VL && TARGET_AVX512BW)
5183 : : gen = gen_avx512vl_vpermt2varv8hi3;
5184 : : break;
5185 : 1117 : case E_V16HImode:
5186 : 1117 : if (TARGET_AVX512VL && TARGET_AVX512BW)
5187 : : gen = gen_avx512vl_vpermt2varv16hi3;
5188 : : break;
5189 : 368 : case E_V32HImode:
5190 : 368 : if (TARGET_AVX512BW)
5191 : : gen = gen_avx512bw_vpermt2varv32hi3;
5192 : : break;
5193 : 56226 : case E_V4SImode:
5194 : 56226 : if (TARGET_AVX512VL)
5195 : : gen = gen_avx512vl_vpermt2varv4si3;
5196 : : break;
5197 : 812 : case E_V8SImode:
5198 : 812 : if (TARGET_AVX512VL)
5199 : : gen = gen_avx512vl_vpermt2varv8si3;
5200 : : break;
5201 : 230 : case E_V16SImode:
5202 : 230 : if (TARGET_AVX512F)
5203 : : gen = gen_avx512f_vpermt2varv16si3;
5204 : : break;
5205 : 9439 : case E_V4SFmode:
5206 : 9439 : if (TARGET_AVX512VL)
5207 : : {
5208 : : gen = gen_avx512vl_vpermt2varv4sf3;
5209 : : maskmode = V4SImode;
5210 : : }
5211 : : break;
5212 : 6529 : case E_V8SFmode:
5213 : 6529 : if (TARGET_AVX512VL)
5214 : : {
5215 : : gen = gen_avx512vl_vpermt2varv8sf3;
5216 : : maskmode = V8SImode;
5217 : : }
5218 : : break;
5219 : 223 : case E_V16SFmode:
5220 : 223 : if (TARGET_AVX512F)
5221 : : {
5222 : : gen = gen_avx512f_vpermt2varv16sf3;
5223 : : maskmode = V16SImode;
5224 : : }
5225 : : break;
5226 : 0 : case E_V2DImode:
5227 : 0 : if (TARGET_AVX512VL)
5228 : : gen = gen_avx512vl_vpermt2varv2di3;
5229 : : break;
5230 : 438 : case E_V4DImode:
5231 : 438 : if (TARGET_AVX512VL)
5232 : : gen = gen_avx512vl_vpermt2varv4di3;
5233 : : break;
5234 : 74 : case E_V8DImode:
5235 : 74 : if (TARGET_AVX512F)
5236 : : gen = gen_avx512f_vpermt2varv8di3;
5237 : : break;
5238 : 0 : case E_V2DFmode:
5239 : 0 : if (TARGET_AVX512VL)
5240 : : {
5241 : : gen = gen_avx512vl_vpermt2varv2df3;
5242 : : maskmode = V2DImode;
5243 : : }
5244 : : break;
5245 : 2176 : case E_V4DFmode:
5246 : 2176 : if (TARGET_AVX512VL)
5247 : : {
5248 : : gen = gen_avx512vl_vpermt2varv4df3;
5249 : : maskmode = V4DImode;
5250 : : }
5251 : : break;
5252 : 210 : case E_V8DFmode:
5253 : 210 : if (TARGET_AVX512F)
5254 : : {
5255 : : gen = gen_avx512f_vpermt2varv8df3;
5256 : : maskmode = V8DImode;
5257 : : }
5258 : : break;
5259 : : default:
5260 : : break;
5261 : : }
5262 : :
5263 : : if (gen == NULL)
5264 : : return false;
5265 : :
5266 : 1075 : if (d && d->testing_p)
5267 : : return true;
5268 : :
5269 : : /* ix86_expand_vec_perm_vpermt2 is called from both const and non-const
5270 : : expander, so args are either in d, or in op0, op1 etc. */
5271 : 1064 : if (d)
5272 : : {
5273 : 1064 : rtx vec[64];
5274 : 1064 : target = d->target;
5275 : 1064 : op0 = d->op0;
5276 : 1064 : op1 = d->op1;
5277 : 18572 : for (int i = 0; i < d->nelt; ++i)
5278 : 17508 : vec[i] = GEN_INT (d->perm[i]);
5279 : 1064 : mask = gen_rtx_CONST_VECTOR (maskmode, gen_rtvec_v (d->nelt, vec));
5280 : : }
5281 : :
5282 : 1072 : emit_insn (gen (target, force_reg (maskmode, mask), op0, op1));
5283 : 1072 : return true;
5284 : : }
5285 : :
5286 : : /* Expand a variable vector permutation. */
5287 : :
5288 : : void
5289 : 10 : ix86_expand_vec_perm (rtx operands[])
5290 : : {
5291 : 10 : rtx target = operands[0];
5292 : 10 : rtx op0 = operands[1];
5293 : 10 : rtx op1 = operands[2];
5294 : 10 : rtx mask = operands[3];
5295 : 10 : rtx t1, t2, t3, t4, t5, t6, t7, t8, vt, vt2, vec[32];
5296 : 10 : machine_mode mode = GET_MODE (op0);
5297 : 10 : machine_mode maskmode = GET_MODE (mask);
5298 : 10 : int w, e, i;
5299 : 10 : bool one_operand_shuffle = rtx_equal_p (op0, op1);
5300 : :
5301 : : /* Number of elements in the vector. */
5302 : 10 : w = GET_MODE_NUNITS (mode);
5303 : 10 : e = GET_MODE_UNIT_SIZE (mode);
5304 : 10 : gcc_assert (w <= 64);
5305 : :
5306 : : /* For HF mode vector, convert it to HI using subreg. */
5307 : 20 : if (GET_MODE_INNER (mode) == HFmode)
5308 : : {
5309 : 6 : machine_mode orig_mode = mode;
5310 : 6 : mode = mode_for_vector (HImode, w).require ();
5311 : 6 : target = lowpart_subreg (mode, target, orig_mode);
5312 : 6 : op0 = lowpart_subreg (mode, op0, orig_mode);
5313 : 6 : op1 = lowpart_subreg (mode, op1, orig_mode);
5314 : : }
5315 : :
5316 : 10 : if (TARGET_AVX512F && one_operand_shuffle)
5317 : : {
5318 : 5 : rtx (*gen) (rtx, rtx, rtx) = NULL;
5319 : 5 : switch (mode)
5320 : : {
5321 : : case E_V16SImode:
5322 : : gen =gen_avx512f_permvarv16si;
5323 : : break;
5324 : 0 : case E_V16SFmode:
5325 : 0 : gen = gen_avx512f_permvarv16sf;
5326 : 0 : break;
5327 : 0 : case E_V8DImode:
5328 : 0 : gen = gen_avx512f_permvarv8di;
5329 : 0 : break;
5330 : 0 : case E_V8DFmode:
5331 : 0 : gen = gen_avx512f_permvarv8df;
5332 : 0 : break;
5333 : : default:
5334 : : break;
5335 : : }
5336 : 0 : if (gen != NULL)
5337 : : {
5338 : 0 : emit_insn (gen (target, op0, mask));
5339 : 8 : return;
5340 : : }
5341 : : }
5342 : :
5343 : 10 : if (ix86_expand_vec_perm_vpermt2 (target, mask, op0, op1, NULL))
5344 : : return;
5345 : :
5346 : 2 : if (TARGET_AVX2)
5347 : : {
5348 : 1 : if (mode == V4DImode || mode == V4DFmode || mode == V16HImode)
5349 : : {
5350 : : /* Unfortunately, the VPERMQ and VPERMPD instructions only support
5351 : : an constant shuffle operand. With a tiny bit of effort we can
5352 : : use VPERMD instead. A re-interpretation stall for V4DFmode is
5353 : : unfortunate but there's no avoiding it.
5354 : : Similarly for V16HImode we don't have instructions for variable
5355 : : shuffling, while for V32QImode we can use after preparing suitable
5356 : : masks vpshufb; vpshufb; vpermq; vpor. */
5357 : :
5358 : 0 : if (mode == V16HImode)
5359 : : {
5360 : 0 : maskmode = mode = V32QImode;
5361 : 0 : w = 32;
5362 : 0 : e = 1;
5363 : : }
5364 : : else
5365 : : {
5366 : 0 : maskmode = mode = V8SImode;
5367 : 0 : w = 8;
5368 : 0 : e = 4;
5369 : : }
5370 : 0 : t1 = gen_reg_rtx (maskmode);
5371 : :
5372 : : /* Replicate the low bits of the V4DImode mask into V8SImode:
5373 : : mask = { A B C D }
5374 : : t1 = { A A B B C C D D }. */
5375 : 0 : for (i = 0; i < w / 2; ++i)
5376 : 0 : vec[i*2 + 1] = vec[i*2] = GEN_INT (i * 2);
5377 : 0 : vt = gen_rtx_CONST_VECTOR (maskmode, gen_rtvec_v (w, vec));
5378 : 0 : vt = force_reg (maskmode, vt);
5379 : 0 : mask = gen_lowpart (maskmode, mask);
5380 : 0 : if (maskmode == V8SImode)
5381 : 0 : emit_insn (gen_avx2_permvarv8si (t1, mask, vt));
5382 : : else
5383 : 0 : emit_insn (gen_avx2_pshufbv32qi3 (t1, mask, vt));
5384 : :
5385 : : /* Multiply the shuffle indicies by two. */
5386 : 0 : t1 = expand_simple_binop (maskmode, PLUS, t1, t1, t1, 1,
5387 : : OPTAB_DIRECT);
5388 : :
5389 : : /* Add one to the odd shuffle indicies:
5390 : : t1 = { A*2, A*2+1, B*2, B*2+1, ... }. */
5391 : 0 : for (i = 0; i < w / 2; ++i)
5392 : : {
5393 : 0 : vec[i * 2] = const0_rtx;
5394 : 0 : vec[i * 2 + 1] = const1_rtx;
5395 : : }
5396 : 0 : vt = gen_rtx_CONST_VECTOR (maskmode, gen_rtvec_v (w, vec));
5397 : 0 : vt = validize_mem (force_const_mem (maskmode, vt));
5398 : 0 : t1 = expand_simple_binop (maskmode, PLUS, t1, vt, t1, 1,
5399 : : OPTAB_DIRECT);
5400 : :
5401 : : /* Continue as if V8SImode (resp. V32QImode) was used initially. */
5402 : 0 : operands[3] = mask = t1;
5403 : 0 : target = gen_reg_rtx (mode);
5404 : 0 : op0 = gen_lowpart (mode, op0);
5405 : 0 : op1 = gen_lowpart (mode, op1);
5406 : : }
5407 : :
5408 : 1 : switch (mode)
5409 : : {
5410 : 1 : case E_V8SImode:
5411 : : /* The VPERMD and VPERMPS instructions already properly ignore
5412 : : the high bits of the shuffle elements. No need for us to
5413 : : perform an AND ourselves. */
5414 : 1 : if (one_operand_shuffle)
5415 : : {
5416 : 0 : emit_insn (gen_avx2_permvarv8si (target, op0, mask));
5417 : 0 : if (target != operands[0])
5418 : 0 : emit_move_insn (operands[0],
5419 : 0 : gen_lowpart (GET_MODE (operands[0]), target));
5420 : : }
5421 : : else
5422 : : {
5423 : 1 : t1 = gen_reg_rtx (V8SImode);
5424 : 1 : t2 = gen_reg_rtx (V8SImode);
5425 : 1 : emit_insn (gen_avx2_permvarv8si (t1, op0, mask));
5426 : 1 : emit_insn (gen_avx2_permvarv8si (t2, op1, mask));
5427 : 1 : goto merge_two;
5428 : : }
5429 : 0 : return;
5430 : :
5431 : 0 : case E_V8SFmode:
5432 : 0 : mask = gen_lowpart (V8SImode, mask);
5433 : 0 : if (one_operand_shuffle)
5434 : 0 : emit_insn (gen_avx2_permvarv8sf (target, op0, mask));
5435 : : else
5436 : : {
5437 : 0 : t1 = gen_reg_rtx (V8SFmode);
5438 : 0 : t2 = gen_reg_rtx (V8SFmode);
5439 : 0 : emit_insn (gen_avx2_permvarv8sf (t1, op0, mask));
5440 : 0 : emit_insn (gen_avx2_permvarv8sf (t2, op1, mask));
5441 : 0 : goto merge_two;
5442 : : }
5443 : 0 : return;
5444 : :
5445 : 0 : case E_V4SImode:
5446 : : /* By combining the two 128-bit input vectors into one 256-bit
5447 : : input vector, we can use VPERMD and VPERMPS for the full
5448 : : two-operand shuffle. */
5449 : 0 : t1 = gen_reg_rtx (V8SImode);
5450 : 0 : t2 = gen_reg_rtx (V8SImode);
5451 : 0 : emit_insn (gen_avx_vec_concatv8si (t1, op0, op1));
5452 : 0 : emit_insn (gen_avx_vec_concatv8si (t2, mask, mask));
5453 : 0 : emit_insn (gen_avx2_permvarv8si (t1, t1, t2));
5454 : 0 : emit_insn (gen_avx_vextractf128v8si (target, t1, const0_rtx));
5455 : 0 : return;
5456 : :
5457 : 0 : case E_V4SFmode:
5458 : 0 : t1 = gen_reg_rtx (V8SFmode);
5459 : 0 : t2 = gen_reg_rtx (V8SImode);
5460 : 0 : mask = gen_lowpart (V4SImode, mask);
5461 : 0 : emit_insn (gen_avx_vec_concatv8sf (t1, op0, op1));
5462 : 0 : emit_insn (gen_avx_vec_concatv8si (t2, mask, mask));
5463 : 0 : emit_insn (gen_avx2_permvarv8sf (t1, t1, t2));
5464 : 0 : emit_insn (gen_avx_vextractf128v8sf (target, t1, const0_rtx));
5465 : 0 : return;
5466 : :
5467 : 0 : case E_V32QImode:
5468 : 0 : t1 = gen_reg_rtx (V32QImode);
5469 : 0 : t2 = gen_reg_rtx (V32QImode);
5470 : 0 : t3 = gen_reg_rtx (V32QImode);
5471 : 0 : vt2 = GEN_INT (-128);
5472 : 0 : vt = gen_const_vec_duplicate (V32QImode, vt2);
5473 : 0 : vt = force_reg (V32QImode, vt);
5474 : 0 : for (i = 0; i < 32; i++)
5475 : 0 : vec[i] = i < 16 ? vt2 : const0_rtx;
5476 : 0 : vt2 = gen_rtx_CONST_VECTOR (V32QImode, gen_rtvec_v (32, vec));
5477 : 0 : vt2 = force_reg (V32QImode, vt2);
5478 : : /* From mask create two adjusted masks, which contain the same
5479 : : bits as mask in the low 7 bits of each vector element.
5480 : : The first mask will have the most significant bit clear
5481 : : if it requests element from the same 128-bit lane
5482 : : and MSB set if it requests element from the other 128-bit lane.
5483 : : The second mask will have the opposite values of the MSB,
5484 : : and additionally will have its 128-bit lanes swapped.
5485 : : E.g. { 07 12 1e 09 ... | 17 19 05 1f ... } mask vector will have
5486 : : t1 { 07 92 9e 09 ... | 17 19 85 1f ... } and
5487 : : t3 { 97 99 05 9f ... | 87 12 1e 89 ... } where each ...
5488 : : stands for other 12 bytes. */
5489 : : /* The bit whether element is from the same lane or the other
5490 : : lane is bit 4, so shift it up by 3 to the MSB position. */
5491 : 0 : t5 = gen_reg_rtx (V4DImode);
5492 : 0 : emit_insn (gen_ashlv4di3 (t5, gen_lowpart (V4DImode, mask),
5493 : : GEN_INT (3)));
5494 : : /* Clear MSB bits from the mask just in case it had them set. */
5495 : 0 : emit_insn (gen_avx2_andnotv32qi3 (t2, vt, mask));
5496 : : /* After this t1 will have MSB set for elements from other lane. */
5497 : 0 : emit_insn (gen_xorv32qi3 (t1, gen_lowpart (V32QImode, t5), vt2));
5498 : : /* Clear bits other than MSB. */
5499 : 0 : emit_insn (gen_andv32qi3 (t1, t1, vt));
5500 : : /* Or in the lower bits from mask into t3. */
5501 : 0 : emit_insn (gen_iorv32qi3 (t3, t1, t2));
5502 : : /* And invert MSB bits in t1, so MSB is set for elements from the same
5503 : : lane. */
5504 : 0 : emit_insn (gen_xorv32qi3 (t1, t1, vt));
5505 : : /* Swap 128-bit lanes in t3. */
5506 : 0 : t6 = gen_reg_rtx (V4DImode);
5507 : 0 : emit_insn (gen_avx2_permv4di_1 (t6, gen_lowpart (V4DImode, t3),
5508 : : const2_rtx, GEN_INT (3),
5509 : : const0_rtx, const1_rtx));
5510 : : /* And or in the lower bits from mask into t1. */
5511 : 0 : emit_insn (gen_iorv32qi3 (t1, t1, t2));
5512 : 0 : if (one_operand_shuffle)
5513 : : {
5514 : : /* Each of these shuffles will put 0s in places where
5515 : : element from the other 128-bit lane is needed, otherwise
5516 : : will shuffle in the requested value. */
5517 : 0 : emit_insn (gen_avx2_pshufbv32qi3 (t3, op0,
5518 : 0 : gen_lowpart (V32QImode, t6)));
5519 : 0 : emit_insn (gen_avx2_pshufbv32qi3 (t1, op0, t1));
5520 : : /* For t3 the 128-bit lanes are swapped again. */
5521 : 0 : t7 = gen_reg_rtx (V4DImode);
5522 : 0 : emit_insn (gen_avx2_permv4di_1 (t7, gen_lowpart (V4DImode, t3),
5523 : : const2_rtx, GEN_INT (3),
5524 : : const0_rtx, const1_rtx));
5525 : : /* And oring both together leads to the result. */
5526 : 0 : emit_insn (gen_iorv32qi3 (target, t1,
5527 : 0 : gen_lowpart (V32QImode, t7)));
5528 : 0 : if (target != operands[0])
5529 : 0 : emit_move_insn (operands[0],
5530 : 0 : gen_lowpart (GET_MODE (operands[0]), target));
5531 : 0 : return;
5532 : : }
5533 : :
5534 : 0 : t4 = gen_reg_rtx (V32QImode);
5535 : : /* Similarly to the above one_operand_shuffle code,
5536 : : just for repeated twice for each operand. merge_two:
5537 : : code will merge the two results together. */
5538 : 0 : emit_insn (gen_avx2_pshufbv32qi3 (t4, op0,
5539 : 0 : gen_lowpart (V32QImode, t6)));
5540 : 0 : emit_insn (gen_avx2_pshufbv32qi3 (t3, op1,
5541 : 0 : gen_lowpart (V32QImode, t6)));
5542 : 0 : emit_insn (gen_avx2_pshufbv32qi3 (t2, op0, t1));
5543 : 0 : emit_insn (gen_avx2_pshufbv32qi3 (t1, op1, t1));
5544 : 0 : t7 = gen_reg_rtx (V4DImode);
5545 : 0 : emit_insn (gen_avx2_permv4di_1 (t7, gen_lowpart (V4DImode, t4),
5546 : : const2_rtx, GEN_INT (3),
5547 : : const0_rtx, const1_rtx));
5548 : 0 : t8 = gen_reg_rtx (V4DImode);
5549 : 0 : emit_insn (gen_avx2_permv4di_1 (t8, gen_lowpart (V4DImode, t3),
5550 : : const2_rtx, GEN_INT (3),
5551 : : const0_rtx, const1_rtx));
5552 : 0 : emit_insn (gen_iorv32qi3 (t4, t2, gen_lowpart (V32QImode, t7)));
5553 : 0 : emit_insn (gen_iorv32qi3 (t3, t1, gen_lowpart (V32QImode, t8)));
5554 : 0 : t1 = t4;
5555 : 0 : t2 = t3;
5556 : 0 : goto merge_two;
5557 : :
5558 : 0 : default:
5559 : 0 : gcc_assert (GET_MODE_SIZE (mode) <= 16);
5560 : : break;
5561 : : }
5562 : : }
5563 : :
5564 : 1 : if (TARGET_XOP)
5565 : : {
5566 : : /* The XOP VPPERM insn supports three inputs. By ignoring the
5567 : : one_operand_shuffle special case, we avoid creating another
5568 : : set of constant vectors in memory. */
5569 : 0 : one_operand_shuffle = false;
5570 : :
5571 : : /* mask = mask & {2*w-1, ...} */
5572 : 0 : vt = GEN_INT (2*w - 1);
5573 : : }
5574 : : else
5575 : : {
5576 : : /* mask = mask & {w-1, ...} */
5577 : 1 : vt = GEN_INT (w - 1);
5578 : : }
5579 : :
5580 : 1 : vt = gen_const_vec_duplicate (maskmode, vt);
5581 : 1 : mask = expand_simple_binop (maskmode, AND, mask, vt,
5582 : : NULL_RTX, 0, OPTAB_DIRECT);
5583 : :
5584 : : /* For non-QImode operations, convert the word permutation control
5585 : : into a byte permutation control. */
5586 : 1 : if (mode != V16QImode)
5587 : : {
5588 : 1 : mask = expand_simple_binop (maskmode, ASHIFT, mask,
5589 : 1 : GEN_INT (exact_log2 (e)),
5590 : : NULL_RTX, 0, OPTAB_DIRECT);
5591 : :
5592 : : /* Convert mask to vector of chars. */
5593 : 1 : mask = force_reg (V16QImode, gen_lowpart (V16QImode, mask));
5594 : :
5595 : : /* Replicate each of the input bytes into byte positions:
5596 : : (v2di) --> {0,0,0,0,0,0,0,0, 8,8,8,8,8,8,8,8}
5597 : : (v4si) --> {0,0,0,0, 4,4,4,4, 8,8,8,8, 12,12,12,12}
5598 : : (v8hi) --> {0,0, 2,2, 4,4, 6,6, ...}. */
5599 : 18 : for (i = 0; i < 16; ++i)
5600 : 16 : vec[i] = GEN_INT (i/e * e);
5601 : 1 : vt = gen_rtx_CONST_VECTOR (V16QImode, gen_rtvec_v (16, vec));
5602 : 1 : vt = validize_mem (force_const_mem (V16QImode, vt));
5603 : 1 : if (TARGET_XOP)
5604 : 0 : emit_insn (gen_xop_pperm (mask, mask, mask, vt));
5605 : : else
5606 : 1 : emit_insn (gen_ssse3_pshufbv16qi3 (mask, mask, vt));
5607 : :
5608 : : /* Convert it into the byte positions by doing
5609 : : mask = mask + {0,1,..,16/w, 0,1,..,16/w, ...} */
5610 : 17 : for (i = 0; i < 16; ++i)
5611 : 16 : vec[i] = GEN_INT (i % e);
5612 : 1 : vt = gen_rtx_CONST_VECTOR (V16QImode, gen_rtvec_v (16, vec));
5613 : 1 : vt = validize_mem (force_const_mem (V16QImode, vt));
5614 : 1 : emit_insn (gen_addv16qi3 (mask, mask, vt));
5615 : : }
5616 : :
5617 : : /* The actual shuffle operations all operate on V16QImode. */
5618 : 1 : op0 = gen_lowpart (V16QImode, op0);
5619 : 1 : op1 = gen_lowpart (V16QImode, op1);
5620 : :
5621 : 1 : if (TARGET_XOP)
5622 : : {
5623 : 0 : if (GET_MODE (target) != V16QImode)
5624 : 0 : target = gen_reg_rtx (V16QImode);
5625 : 0 : emit_insn (gen_xop_pperm (target, op0, op1, mask));
5626 : 0 : if (target != operands[0])
5627 : 0 : emit_move_insn (operands[0],
5628 : 0 : gen_lowpart (GET_MODE (operands[0]), target));
5629 : : }
5630 : 1 : else if (one_operand_shuffle)
5631 : : {
5632 : 1 : if (GET_MODE (target) != V16QImode)
5633 : 1 : target = gen_reg_rtx (V16QImode);
5634 : 1 : emit_insn (gen_ssse3_pshufbv16qi3 (target, op0, mask));
5635 : 1 : if (target != operands[0])
5636 : 1 : emit_move_insn (operands[0],
5637 : 1 : gen_lowpart (GET_MODE (operands[0]), target));
5638 : : }
5639 : : else
5640 : : {
5641 : 0 : rtx xops[6];
5642 : 0 : bool ok;
5643 : :
5644 : : /* Shuffle the two input vectors independently. */
5645 : 0 : t1 = gen_reg_rtx (V16QImode);
5646 : 0 : t2 = gen_reg_rtx (V16QImode);
5647 : 0 : emit_insn (gen_ssse3_pshufbv16qi3 (t1, op0, mask));
5648 : 0 : emit_insn (gen_ssse3_pshufbv16qi3 (t2, op1, mask));
5649 : :
5650 : 1 : merge_two:
5651 : : /* Then merge them together. The key is whether any given control
5652 : : element contained a bit set that indicates the second word. */
5653 : 1 : mask = operands[3];
5654 : 1 : vt = GEN_INT (w);
5655 : 1 : if (maskmode == V2DImode && !TARGET_SSE4_1)
5656 : : {
5657 : : /* Without SSE4.1, we don't have V2DImode EQ. Perform one
5658 : : more shuffle to convert the V2DI input mask into a V4SI
5659 : : input mask. At which point the masking that expand_int_vcond
5660 : : will work as desired. */
5661 : 0 : rtx t3 = gen_reg_rtx (V4SImode);
5662 : 0 : emit_insn (gen_sse2_pshufd_1 (t3, gen_lowpart (V4SImode, mask),
5663 : : const0_rtx, const0_rtx,
5664 : : const2_rtx, const2_rtx));
5665 : 0 : mask = t3;
5666 : 0 : maskmode = V4SImode;
5667 : 0 : e = w = 4;
5668 : : }
5669 : :
5670 : 1 : vt = gen_const_vec_duplicate (maskmode, vt);
5671 : 1 : vt = force_reg (maskmode, vt);
5672 : 1 : mask = expand_simple_binop (maskmode, AND, mask, vt,
5673 : : NULL_RTX, 0, OPTAB_DIRECT);
5674 : :
5675 : 1 : if (GET_MODE (target) != mode)
5676 : 0 : target = gen_reg_rtx (mode);
5677 : 1 : xops[0] = target;
5678 : 1 : xops[1] = gen_lowpart (mode, t2);
5679 : 1 : xops[2] = gen_lowpart (mode, t1);
5680 : 1 : xops[3] = gen_rtx_EQ (maskmode, mask, vt);
5681 : 1 : xops[4] = mask;
5682 : 1 : xops[5] = vt;
5683 : 1 : ok = ix86_expand_int_vcond (xops);
5684 : 1 : gcc_assert (ok);
5685 : 1 : if (target != operands[0])
5686 : 0 : emit_move_insn (operands[0],
5687 : 0 : gen_lowpart (GET_MODE (operands[0]), target));
5688 : : }
5689 : : }
5690 : :
5691 : : /* Extend SRC into next wider integer vector type. UNSIGNED_P is
5692 : : true if we should do zero extension, else sign extension. */
5693 : :
5694 : : void
5695 : 603 : ix86_expand_sse_extend (rtx dest, rtx src, bool unsigned_p)
5696 : : {
5697 : 603 : machine_mode imode = GET_MODE (src);
5698 : 603 : rtx ops[3];
5699 : :
5700 : 603 : switch (imode)
5701 : : {
5702 : 603 : case E_V8QImode:
5703 : 603 : case E_V4QImode:
5704 : 603 : case E_V2QImode:
5705 : 603 : case E_V4HImode:
5706 : 603 : case E_V2HImode:
5707 : 603 : case E_V2SImode:
5708 : 603 : break;
5709 : 0 : default:
5710 : 0 : gcc_unreachable ();
5711 : : }
5712 : :
5713 : 603 : ops[0] = dest;
5714 : :
5715 : 603 : ops[1] = force_reg (imode, src);
5716 : :
5717 : 603 : if (unsigned_p)
5718 : 124 : ops[2] = force_reg (imode, CONST0_RTX (imode));
5719 : : else
5720 : 479 : ops[2] = ix86_expand_sse_cmp (gen_reg_rtx (imode), GT, CONST0_RTX (imode),
5721 : : ops[1], pc_rtx, pc_rtx);
5722 : :
5723 : 603 : ix86_split_mmx_punpck (ops, false);
5724 : 603 : }
5725 : :
5726 : : /* Unpack SRC into the next wider integer vector type. UNSIGNED_P is
5727 : : true if we should do zero extension, else sign extension. HIGH_P is
5728 : : true if we want the N/2 high elements, else the low elements. */
5729 : :
5730 : : void
5731 : 13406 : ix86_expand_sse_unpack (rtx dest, rtx src, bool unsigned_p, bool high_p)
5732 : : {
5733 : 13406 : machine_mode imode = GET_MODE (src);
5734 : 13406 : rtx tmp;
5735 : :
5736 : 13406 : if (TARGET_SSE4_1)
5737 : : {
5738 : 5586 : rtx (*unpack)(rtx, rtx);
5739 : 5586 : rtx (*extract)(rtx, rtx) = NULL;
5740 : 5586 : machine_mode halfmode = BLKmode;
5741 : :
5742 : 5586 : switch (imode)
5743 : : {
5744 : 48 : case E_V64QImode:
5745 : 48 : if (unsigned_p)
5746 : : unpack = gen_avx512bw_zero_extendv32qiv32hi2;
5747 : : else
5748 : 10 : unpack = gen_avx512bw_sign_extendv32qiv32hi2;
5749 : 48 : halfmode = V32QImode;
5750 : 48 : extract
5751 : 48 : = high_p ? gen_vec_extract_hi_v64qi : gen_vec_extract_lo_v64qi;
5752 : : break;
5753 : 1053 : case E_V32QImode:
5754 : 1053 : if (unsigned_p)
5755 : : unpack = gen_avx2_zero_extendv16qiv16hi2;
5756 : : else
5757 : 88 : unpack = gen_avx2_sign_extendv16qiv16hi2;
5758 : 1053 : halfmode = V16QImode;
5759 : 1053 : extract
5760 : 1053 : = high_p ? gen_vec_extract_hi_v32qi : gen_vec_extract_lo_v32qi;
5761 : : break;
5762 : 28 : case E_V32HImode:
5763 : 28 : if (unsigned_p)
5764 : : unpack = gen_avx512f_zero_extendv16hiv16si2;
5765 : : else
5766 : 16 : unpack = gen_avx512f_sign_extendv16hiv16si2;
5767 : 28 : halfmode = V16HImode;
5768 : 28 : extract
5769 : 28 : = high_p ? gen_vec_extract_hi_v32hi : gen_vec_extract_lo_v32hi;
5770 : : break;
5771 : 391 : case E_V16HImode:
5772 : 391 : if (unsigned_p)
5773 : : unpack = gen_avx2_zero_extendv8hiv8si2;
5774 : : else
5775 : 306 : unpack = gen_avx2_sign_extendv8hiv8si2;
5776 : 391 : halfmode = V8HImode;
5777 : 391 : extract
5778 : 391 : = high_p ? gen_vec_extract_hi_v16hi : gen_vec_extract_lo_v16hi;
5779 : : break;
5780 : 110 : case E_V16SImode:
5781 : 110 : if (unsigned_p)
5782 : : unpack = gen_avx512f_zero_extendv8siv8di2;
5783 : : else
5784 : 106 : unpack = gen_avx512f_sign_extendv8siv8di2;
5785 : 110 : halfmode = V8SImode;
5786 : 110 : extract
5787 : 110 : = high_p ? gen_vec_extract_hi_v16si : gen_vec_extract_lo_v16si;
5788 : : break;
5789 : 344 : case E_V8SImode:
5790 : 344 : if (unsigned_p)
5791 : : unpack = gen_avx2_zero_extendv4siv4di2;
5792 : : else
5793 : 326 : unpack = gen_avx2_sign_extendv4siv4di2;
5794 : 344 : halfmode = V4SImode;
5795 : 344 : extract
5796 : 344 : = high_p ? gen_vec_extract_hi_v8si : gen_vec_extract_lo_v8si;
5797 : : break;
5798 : 1753 : case E_V16QImode:
5799 : 1753 : if (unsigned_p)
5800 : : unpack = gen_sse4_1_zero_extendv8qiv8hi2;
5801 : : else
5802 : 218 : unpack = gen_sse4_1_sign_extendv8qiv8hi2;
5803 : : break;
5804 : 1015 : case E_V8HImode:
5805 : 1015 : if (unsigned_p)
5806 : : unpack = gen_sse4_1_zero_extendv4hiv4si2;
5807 : : else
5808 : 700 : unpack = gen_sse4_1_sign_extendv4hiv4si2;
5809 : : break;
5810 : 518 : case E_V4SImode:
5811 : 518 : if (unsigned_p)
5812 : : unpack = gen_sse4_1_zero_extendv2siv2di2;
5813 : : else
5814 : 496 : unpack = gen_sse4_1_sign_extendv2siv2di2;
5815 : : break;
5816 : 100 : case E_V8QImode:
5817 : 100 : if (unsigned_p)
5818 : : unpack = gen_sse4_1_zero_extendv4qiv4hi2;
5819 : : else
5820 : 60 : unpack = gen_sse4_1_sign_extendv4qiv4hi2;
5821 : : break;
5822 : 226 : case E_V4HImode:
5823 : 226 : if (unsigned_p)
5824 : : unpack = gen_sse4_1_zero_extendv2hiv2si2;
5825 : : else
5826 : 188 : unpack = gen_sse4_1_sign_extendv2hiv2si2;
5827 : : break;
5828 : 0 : case E_V4QImode:
5829 : 0 : if (unsigned_p)
5830 : : unpack = gen_sse4_1_zero_extendv2qiv2hi2;
5831 : : else
5832 : 0 : unpack = gen_sse4_1_sign_extendv2qiv2hi2;
5833 : : break;
5834 : 0 : default:
5835 : 0 : gcc_unreachable ();
5836 : : }
5837 : :
5838 : 11172 : if (GET_MODE_SIZE (imode) >= 32)
5839 : : {
5840 : 1974 : tmp = gen_reg_rtx (halfmode);
5841 : 1974 : emit_insn (extract (tmp, src));
5842 : : }
5843 : 3612 : else if (high_p)
5844 : : {
5845 : 2182 : switch (GET_MODE_SIZE (imode))
5846 : : {
5847 : 928 : case 16:
5848 : : /* Shift higher 8 bytes to lower 8 bytes. */
5849 : 928 : tmp = gen_reg_rtx (V1TImode);
5850 : 928 : emit_insn (gen_sse2_lshrv1ti3 (tmp, gen_lowpart (V1TImode, src),
5851 : : GEN_INT (64)));
5852 : 928 : break;
5853 : 163 : case 8:
5854 : : /* Shift higher 4 bytes to lower 4 bytes. */
5855 : 163 : tmp = gen_reg_rtx (V1DImode);
5856 : 163 : emit_insn (gen_mmx_lshrv1di3 (tmp, gen_lowpart (V1DImode, src),
5857 : : GEN_INT (32)));
5858 : 163 : break;
5859 : 0 : case 4:
5860 : : /* Shift higher 2 bytes to lower 2 bytes. */
5861 : 0 : tmp = gen_reg_rtx (V1SImode);
5862 : 0 : emit_insn (gen_mmx_lshrv1si3 (tmp, gen_lowpart (V1SImode, src),
5863 : : GEN_INT (16)));
5864 : 0 : break;
5865 : 0 : default:
5866 : 0 : gcc_unreachable ();
5867 : : }
5868 : :
5869 : 1091 : tmp = gen_lowpart (imode, tmp);
5870 : : }
5871 : : else
5872 : : tmp = src;
5873 : :
5874 : 5586 : emit_insn (unpack (dest, tmp));
5875 : : }
5876 : : else
5877 : : {
5878 : 7820 : rtx (*unpack)(rtx, rtx, rtx);
5879 : :
5880 : 7820 : switch (imode)
5881 : : {
5882 : 2346 : case E_V16QImode:
5883 : 2346 : if (high_p)
5884 : : unpack = gen_vec_interleave_highv16qi;
5885 : : else
5886 : 1176 : unpack = gen_vec_interleave_lowv16qi;
5887 : : break;
5888 : 3050 : case E_V8HImode:
5889 : 3050 : if (high_p)
5890 : : unpack = gen_vec_interleave_highv8hi;
5891 : : else
5892 : 1525 : unpack = gen_vec_interleave_lowv8hi;
5893 : : break;
5894 : 1426 : case E_V4SImode:
5895 : 1426 : if (high_p)
5896 : : unpack = gen_vec_interleave_highv4si;
5897 : : else
5898 : 713 : unpack = gen_vec_interleave_lowv4si;
5899 : : break;
5900 : 320 : case E_V8QImode:
5901 : 320 : if (high_p)
5902 : : unpack = gen_mmx_punpckhbw;
5903 : : else
5904 : 160 : unpack = gen_mmx_punpcklbw;
5905 : : break;
5906 : 674 : case E_V4HImode:
5907 : 674 : if (high_p)
5908 : : unpack = gen_mmx_punpckhwd;
5909 : : else
5910 : 337 : unpack = gen_mmx_punpcklwd;
5911 : : break;
5912 : 4 : case E_V4QImode:
5913 : 4 : if (high_p)
5914 : : unpack = gen_mmx_punpckhbw_low;
5915 : : else
5916 : 2 : unpack = gen_mmx_punpcklbw_low;
5917 : : break;
5918 : 0 : default:
5919 : 0 : gcc_unreachable ();
5920 : : }
5921 : :
5922 : 7820 : if (unsigned_p)
5923 : 4044 : tmp = force_reg (imode, CONST0_RTX (imode));
5924 : : else
5925 : 3776 : tmp = ix86_expand_sse_cmp (gen_reg_rtx (imode), GT, CONST0_RTX (imode),
5926 : : src, pc_rtx, pc_rtx);
5927 : :
5928 : 7820 : rtx tmp2 = gen_reg_rtx (imode);
5929 : 7820 : emit_insn (unpack (tmp2, src, tmp));
5930 : 7820 : emit_move_insn (dest, gen_lowpart (GET_MODE (dest), tmp2));
5931 : : }
5932 : 13406 : }
5933 : :
5934 : : /* Return true if mem is pool constant which contains a const_vector
5935 : : perm index, assign the index to PERM. */
5936 : : bool
5937 : 35 : ix86_extract_perm_from_pool_constant (int* perm, rtx mem)
5938 : : {
5939 : 35 : machine_mode mode = GET_MODE (mem);
5940 : 35 : int nelt = GET_MODE_NUNITS (mode);
5941 : :
5942 : 35 : if (!INTEGRAL_MODE_P (mode))
5943 : : return false;
5944 : :
5945 : : /* Needs to be constant pool. */
5946 : 35 : if (!(MEM_P (mem))
5947 : 35 : || !SYMBOL_REF_P (XEXP (mem, 0))
5948 : 70 : || !CONSTANT_POOL_ADDRESS_P (XEXP (mem, 0)))
5949 : : return false;
5950 : :
5951 : 35 : rtx constant = get_pool_constant (XEXP (mem, 0));
5952 : :
5953 : 35 : if (GET_CODE (constant) != CONST_VECTOR)
5954 : : return false;
5955 : :
5956 : : /* There could be some rtx like
5957 : : (mem/u/c:V16QI (symbol_ref/u:DI ("*.LC1")))
5958 : : but with "*.LC1" refer to V2DI constant vector. */
5959 : 35 : if (GET_MODE (constant) != mode)
5960 : : {
5961 : 0 : constant = simplify_subreg (mode, constant, GET_MODE (constant), 0);
5962 : :
5963 : 0 : if (constant == nullptr || GET_CODE (constant) != CONST_VECTOR)
5964 : : return false;
5965 : : }
5966 : :
5967 : 771 : for (int i = 0; i != nelt; i++)
5968 : 736 : perm[i] = UINTVAL (XVECEXP (constant, 0, i));
5969 : :
5970 : : return true;
5971 : : }
5972 : :
5973 : : /* Split operands 0 and 1 into half-mode parts. Similar to split_double_mode,
5974 : : but works for floating pointer parameters and nonoffsetable memories.
5975 : : For pushes, it returns just stack offsets; the values will be saved
5976 : : in the right order. Maximally three parts are generated. */
5977 : :
5978 : : static int
5979 : 4015104 : ix86_split_to_parts (rtx operand, rtx *parts, machine_mode mode)
5980 : : {
5981 : 4015104 : int size;
5982 : :
5983 : 4015104 : if (!TARGET_64BIT)
5984 : 1546028 : size = mode==XFmode ? 3 : GET_MODE_SIZE (mode) / 4;
5985 : : else
5986 : 6483108 : size = (GET_MODE_SIZE (mode) + 4) / 8;
5987 : :
5988 : 4015104 : gcc_assert (!REG_P (operand) || !MMX_REGNO_P (REGNO (operand)));
5989 : 4015104 : gcc_assert (size >= 2 && size <= 4);
5990 : :
5991 : : /* Optimize constant pool reference to immediates. This is used by fp
5992 : : moves, that force all constants to memory to allow combining. */
5993 : 4015104 : if (MEM_P (operand) && MEM_READONLY_P (operand))
5994 : 34510 : operand = avoid_constant_pool_reference (operand);
5995 : :
5996 : 4015104 : if (MEM_P (operand) && !offsettable_memref_p (operand))
5997 : : {
5998 : : /* The only non-offsetable memories we handle are pushes. */
5999 : 183468 : int ok = push_operand (operand, VOIDmode);
6000 : :
6001 : 183468 : gcc_assert (ok);
6002 : :
6003 : 183468 : operand = copy_rtx (operand);
6004 : 183468 : PUT_MODE (operand, word_mode);
6005 : 183468 : parts[0] = parts[1] = parts[2] = parts[3] = operand;
6006 : 183468 : return size;
6007 : : }
6008 : :
6009 : 3831636 : if (GET_CODE (operand) == CONST_VECTOR)
6010 : : {
6011 : 45204 : scalar_int_mode imode = int_mode_for_mode (mode).require ();
6012 : : /* Caution: if we looked through a constant pool memory above,
6013 : : the operand may actually have a different mode now. That's
6014 : : ok, since we want to pun this all the way back to an integer. */
6015 : 45204 : operand = simplify_subreg (imode, operand, GET_MODE (operand), 0);
6016 : 45204 : gcc_assert (operand != NULL);
6017 : 45204 : mode = imode;
6018 : : }
6019 : :
6020 : 3831636 : if (!TARGET_64BIT)
6021 : : {
6022 : 614217 : if (mode == DImode)
6023 : 463097 : split_double_mode (mode, &operand, 1, &parts[0], &parts[1]);
6024 : : else
6025 : : {
6026 : 151120 : int i;
6027 : :
6028 : 151120 : if (REG_P (operand))
6029 : : {
6030 : 79124 : gcc_assert (reload_completed);
6031 : 237372 : for (i = 0; i < size; i++)
6032 : 158248 : parts[i] = gen_rtx_REG (SImode, REGNO (operand) + i);
6033 : : }
6034 : 71996 : else if (offsettable_memref_p (operand))
6035 : : {
6036 : 71200 : operand = adjust_address (operand, SImode, 0);
6037 : 71200 : parts[0] = operand;
6038 : 142823 : for (i = 1; i < size; i++)
6039 : 71623 : parts[i] = adjust_address (operand, SImode, 4 * i);
6040 : : }
6041 : 796 : else if (CONST_DOUBLE_P (operand))
6042 : : {
6043 : 796 : const REAL_VALUE_TYPE *r;
6044 : 796 : long l[4];
6045 : :
6046 : 796 : r = CONST_DOUBLE_REAL_VALUE (operand);
6047 : 796 : switch (mode)
6048 : : {
6049 : 0 : case E_TFmode:
6050 : 0 : real_to_target (l, r, mode);
6051 : 0 : parts[3] = gen_int_mode (l[3], SImode);
6052 : 0 : parts[2] = gen_int_mode (l[2], SImode);
6053 : 0 : break;
6054 : 127 : case E_XFmode:
6055 : : /* We can't use REAL_VALUE_TO_TARGET_LONG_DOUBLE since
6056 : : long double may not be 80-bit. */
6057 : 127 : real_to_target (l, r, mode);
6058 : 127 : parts[2] = gen_int_mode (l[2], SImode);
6059 : 127 : break;
6060 : 669 : case E_DFmode:
6061 : 669 : REAL_VALUE_TO_TARGET_DOUBLE (*r, l);
6062 : 669 : break;
6063 : 0 : default:
6064 : 0 : gcc_unreachable ();
6065 : : }
6066 : 796 : parts[1] = gen_int_mode (l[1], SImode);
6067 : 796 : parts[0] = gen_int_mode (l[0], SImode);
6068 : : }
6069 : : else
6070 : 0 : gcc_unreachable ();
6071 : : }
6072 : : }
6073 : : else
6074 : : {
6075 : 3217419 : if (mode == TImode)
6076 : 3203627 : split_double_mode (mode, &operand, 1, &parts[0], &parts[1]);
6077 : 3217419 : if (mode == XFmode || mode == TFmode)
6078 : : {
6079 : 13792 : machine_mode upper_mode = mode==XFmode ? SImode : DImode;
6080 : 13792 : if (REG_P (operand))
6081 : : {
6082 : 1596 : gcc_assert (reload_completed);
6083 : 1596 : parts[0] = gen_rtx_REG (DImode, REGNO (operand) + 0);
6084 : 1596 : parts[1] = gen_rtx_REG (upper_mode, REGNO (operand) + 1);
6085 : : }
6086 : 12196 : else if (offsettable_memref_p (operand))
6087 : : {
6088 : 10343 : operand = adjust_address (operand, DImode, 0);
6089 : 10343 : parts[0] = operand;
6090 : 10343 : parts[1] = adjust_address (operand, upper_mode, 8);
6091 : : }
6092 : 1853 : else if (CONST_DOUBLE_P (operand))
6093 : : {
6094 : 1853 : long l[4];
6095 : :
6096 : 1853 : real_to_target (l, CONST_DOUBLE_REAL_VALUE (operand), mode);
6097 : :
6098 : : /* real_to_target puts 32-bit pieces in each long. */
6099 : 3706 : parts[0] = gen_int_mode ((l[0] & HOST_WIDE_INT_C (0xffffffff))
6100 : 1853 : | ((l[1] & HOST_WIDE_INT_C (0xffffffff))
6101 : 1853 : << 32), DImode);
6102 : :
6103 : 1853 : if (upper_mode == SImode)
6104 : 1324 : parts[1] = gen_int_mode (l[2], SImode);
6105 : : else
6106 : 529 : parts[1]
6107 : 529 : = gen_int_mode ((l[2] & HOST_WIDE_INT_C (0xffffffff))
6108 : 529 : | ((l[3] & HOST_WIDE_INT_C (0xffffffff))
6109 : 529 : << 32), DImode);
6110 : : }
6111 : : else
6112 : 0 : gcc_unreachable ();
6113 : : }
6114 : : }
6115 : :
6116 : : return size;
6117 : : }
6118 : :
6119 : : /* Emit insns to perform a move or push of DI, DF, XF, and TF values.
6120 : : Return false when normal moves are needed; true when all required
6121 : : insns have been emitted. Operands 2-4 contain the input values
6122 : : int the correct order; operands 5-7 contain the output values. */
6123 : :
6124 : : void
6125 : 2020528 : ix86_split_long_move (rtx operands[])
6126 : : {
6127 : 2020528 : rtx part[2][4];
6128 : 2020528 : int nparts, i, j;
6129 : 2020528 : int push = 0;
6130 : 2020528 : int collisions = 0;
6131 : 2020528 : machine_mode mode = GET_MODE (operands[0]);
6132 : 2020528 : bool collisionparts[4];
6133 : :
6134 : : /* The DFmode expanders may ask us to move double.
6135 : : For 64bit target this is single move. By hiding the fact
6136 : : here we simplify i386.md splitters. */
6137 : 3654281 : if (TARGET_64BIT && GET_MODE_SIZE (GET_MODE (operands[0])) == 8)
6138 : : {
6139 : : /* Optimize constant pool reference to immediates. This is used by
6140 : : fp moves, that force all constants to memory to allow combining. */
6141 : :
6142 : 12976 : if (MEM_P (operands[1])
6143 : 12487 : && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
6144 : 13553 : && CONSTANT_POOL_ADDRESS_P (XEXP (operands[1], 0)))
6145 : 77 : operands[1] = get_pool_constant (XEXP (operands[1], 0));
6146 : 12976 : if (push_operand (operands[0], VOIDmode))
6147 : : {
6148 : 12976 : operands[0] = copy_rtx (operands[0]);
6149 : 12976 : PUT_MODE (operands[0], word_mode);
6150 : : }
6151 : : else
6152 : 0 : operands[0] = gen_lowpart (DImode, operands[0]);
6153 : 12976 : operands[1] = gen_lowpart (DImode, operands[1]);
6154 : 12976 : emit_move_insn (operands[0], operands[1]);
6155 : 12976 : return;
6156 : : }
6157 : :
6158 : : /* The only non-offsettable memory we handle is push. */
6159 : 2007552 : if (push_operand (operands[0], VOIDmode))
6160 : : push = 1;
6161 : : else
6162 : 1824084 : gcc_assert (!MEM_P (operands[0])
6163 : : || offsettable_memref_p (operands[0]));
6164 : :
6165 : 2007552 : nparts = ix86_split_to_parts (operands[1], part[1], GET_MODE (operands[0]));
6166 : 2007552 : ix86_split_to_parts (operands[0], part[0], GET_MODE (operands[0]));
6167 : :
6168 : : /* When emitting push, take care for source operands on the stack. */
6169 : 183468 : if (push && MEM_P (operands[1])
6170 : 2108434 : && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
6171 : : {
6172 : 60694 : rtx src_base = XEXP (part[1][nparts - 1], 0);
6173 : :
6174 : : /* Compensate for the stack decrement by 4. */
6175 : 60694 : if (!TARGET_64BIT && nparts == 3
6176 : 56225 : && mode == XFmode && TARGET_128BIT_LONG_DOUBLE)
6177 : 0 : src_base = plus_constant (Pmode, src_base, 4);
6178 : :
6179 : : /* src_base refers to the stack pointer and is
6180 : : automatically decreased by emitted push. */
6181 : 182359 : for (i = 0; i < nparts; i++)
6182 : 121665 : part[1][i] = change_address (part[1][i],
6183 : 121665 : GET_MODE (part[1][i]), src_base);
6184 : : }
6185 : :
6186 : : /* We need to do copy in the right order in case an address register
6187 : : of the source overlaps the destination. */
6188 : 2007552 : if (REG_P (part[0][0]) && MEM_P (part[1][0]))
6189 : : {
6190 : : rtx tmp;
6191 : :
6192 : 2315166 : for (i = 0; i < nparts; i++)
6193 : : {
6194 : 1543444 : collisionparts[i]
6195 : 1543444 : = reg_overlap_mentioned_p (part[0][i], XEXP (part[1][0], 0));
6196 : 1543444 : if (collisionparts[i])
6197 : 16099 : collisions++;
6198 : : }
6199 : :
6200 : : /* Collision in the middle part can be handled by reordering. */
6201 : 771722 : if (collisions == 1 && nparts == 3 && collisionparts [1])
6202 : : {
6203 : 0 : std::swap (part[0][1], part[0][2]);
6204 : 0 : std::swap (part[1][1], part[1][2]);
6205 : : }
6206 : 771722 : else if (collisions == 1
6207 : 771722 : && nparts == 4
6208 : 0 : && (collisionparts [1] || collisionparts [2]))
6209 : : {
6210 : 0 : if (collisionparts [1])
6211 : : {
6212 : 0 : std::swap (part[0][1], part[0][2]);
6213 : 0 : std::swap (part[1][1], part[1][2]);
6214 : : }
6215 : : else
6216 : : {
6217 : 0 : std::swap (part[0][2], part[0][3]);
6218 : 0 : std::swap (part[1][2], part[1][3]);
6219 : : }
6220 : : }
6221 : :
6222 : : /* If there are more collisions, we can't handle it by reordering.
6223 : : Do an lea to the last part and use only one colliding move. */
6224 : 771722 : else if (collisions > 1)
6225 : : {
6226 : 32 : rtx base, addr;
6227 : :
6228 : 32 : collisions = 1;
6229 : :
6230 : 32 : base = part[0][nparts - 1];
6231 : :
6232 : : /* Handle the case when the last part isn't valid for lea.
6233 : : Happens in 64-bit mode storing the 12-byte XFmode. */
6234 : 32 : if (GET_MODE (base) != Pmode)
6235 : 0 : base = gen_rtx_REG (Pmode, REGNO (base));
6236 : :
6237 : 32 : addr = XEXP (part[1][0], 0);
6238 : 32 : if (TARGET_TLS_DIRECT_SEG_REFS)
6239 : : {
6240 : 32 : struct ix86_address parts;
6241 : 32 : int ok = ix86_decompose_address (addr, &parts);
6242 : 32 : gcc_assert (ok);
6243 : : /* It is not valid to use %gs: or %fs: in lea. */
6244 : 32 : gcc_assert (parts.seg == ADDR_SPACE_GENERIC);
6245 : : }
6246 : 32 : emit_insn (gen_rtx_SET (base, addr));
6247 : 32 : part[1][0] = replace_equiv_address (part[1][0], base);
6248 : 64 : for (i = 1; i < nparts; i++)
6249 : : {
6250 : 57 : tmp = plus_constant (Pmode, base, UNITS_PER_WORD * i);
6251 : 32 : part[1][i] = replace_equiv_address (part[1][i], tmp);
6252 : : }
6253 : : }
6254 : : }
6255 : :
6256 : 2007552 : if (push)
6257 : : {
6258 : 183468 : if (!TARGET_64BIT)
6259 : : {
6260 : 159333 : if (nparts == 3)
6261 : : {
6262 : 522 : if (TARGET_128BIT_LONG_DOUBLE && mode == XFmode)
6263 : 0 : emit_insn (gen_add2_insn (stack_pointer_rtx, GEN_INT (-4)));
6264 : 522 : emit_move_insn (part[0][2], part[1][2]);
6265 : : }
6266 : 158811 : else if (nparts == 4)
6267 : : {
6268 : 0 : emit_move_insn (part[0][3], part[1][3]);
6269 : 0 : emit_move_insn (part[0][2], part[1][2]);
6270 : : }
6271 : : }
6272 : : else
6273 : : {
6274 : : /* In 64bit mode we don't have 32bit push available. In case this is
6275 : : register, it is OK - we will just use larger counterpart. We also
6276 : : retype memory - these comes from attempt to avoid REX prefix on
6277 : : moving of second half of TFmode value. */
6278 : 24135 : if (GET_MODE (part[1][1]) == SImode)
6279 : : {
6280 : 9705 : switch (GET_CODE (part[1][1]))
6281 : : {
6282 : 9212 : case MEM:
6283 : 9212 : part[1][1] = adjust_address (part[1][1], DImode, 0);
6284 : 9212 : break;
6285 : :
6286 : 493 : case REG:
6287 : 493 : part[1][1] = gen_rtx_REG (DImode, REGNO (part[1][1]));
6288 : 493 : break;
6289 : :
6290 : 0 : default:
6291 : 0 : gcc_unreachable ();
6292 : : }
6293 : :
6294 : 9705 : if (GET_MODE (part[1][0]) == SImode)
6295 : 0 : part[1][0] = part[1][1];
6296 : : }
6297 : : }
6298 : 183468 : emit_move_insn (part[0][1], part[1][1]);
6299 : 183468 : emit_move_insn (part[0][0], part[1][0]);
6300 : 183468 : return;
6301 : : }
6302 : :
6303 : : /* Choose correct order to not overwrite the source before it is copied. */
6304 : 1824084 : if ((REG_P (part[0][0])
6305 : 1001974 : && REG_P (part[1][1])
6306 : 79337 : && (REGNO (part[0][0]) == REGNO (part[1][1])
6307 : 66610 : || (nparts == 3
6308 : 0 : && REGNO (part[0][0]) == REGNO (part[1][2]))
6309 : 66610 : || (nparts == 4
6310 : 0 : && REGNO (part[0][0]) == REGNO (part[1][3]))))
6311 : 2813331 : || (collisions > 0
6312 : 16067 : && reg_overlap_mentioned_p (part[0][0], XEXP (part[1][0], 0))))
6313 : : {
6314 : 85389 : for (i = 0, j = nparts - 1; i < nparts; i++, j--)
6315 : : {
6316 : 56926 : operands[2 + i] = part[0][j];
6317 : 56926 : operands[6 + i] = part[1][j];
6318 : : }
6319 : : }
6320 : : else
6321 : : {
6322 : 5386877 : for (i = 0; i < nparts; i++)
6323 : : {
6324 : 3591256 : operands[2 + i] = part[0][i];
6325 : 3591256 : operands[6 + i] = part[1][i];
6326 : : }
6327 : : }
6328 : :
6329 : : /* Attempt to locally unCSE nonzero constants. */
6330 : 3648182 : for (j = 0; j < nparts - 1; j++)
6331 : 1824098 : if (CONST_INT_P (operands[6 + j])
6332 : 206009 : && operands[6 + j] != const0_rtx
6333 : 57665 : && REG_P (operands[2 + j]))
6334 : 105584 : for (i = j; i < nparts - 1; i++)
6335 : 52792 : if (CONST_INT_P (operands[7 + i])
6336 : 52792 : && INTVAL (operands[7 + i]) == INTVAL (operands[6 + j]))
6337 : 23528 : operands[7 + i] = operands[2 + j];
6338 : :
6339 : 5472266 : for (i = 0; i < nparts; i++)
6340 : 3648182 : emit_move_insn (operands[2 + i], operands[6 + i]);
6341 : :
6342 : : return;
6343 : : }
6344 : :
6345 : : /* Helper function of ix86_split_ashl used to generate an SImode/DImode
6346 : : left shift by a constant, either using a single shift or
6347 : : a sequence of add instructions. */
6348 : :
6349 : : static void
6350 : 4094 : ix86_expand_ashl_const (rtx operand, int count, machine_mode mode)
6351 : : {
6352 : 4094 : if (count == 1
6353 : 4094 : || (count * ix86_cost->add <= ix86_cost->shift_const
6354 : 0 : && !optimize_insn_for_size_p ()))
6355 : : {
6356 : 4 : while (count-- > 0)
6357 : 2 : emit_insn (gen_add2_insn (operand, operand));
6358 : : }
6359 : : else
6360 : : {
6361 : 4092 : rtx (*insn)(rtx, rtx, rtx);
6362 : :
6363 : 4092 : insn = mode == DImode ? gen_ashlsi3 : gen_ashldi3;
6364 : 4092 : emit_insn (insn (operand, operand, GEN_INT (count)));
6365 : : }
6366 : 4094 : }
6367 : :
6368 : : void
6369 : 9895 : ix86_split_ashl (rtx *operands, rtx scratch, machine_mode mode)
6370 : : {
6371 : 9895 : rtx (*gen_ashl3)(rtx, rtx, rtx);
6372 : 9895 : rtx (*gen_shld)(rtx, rtx, rtx);
6373 : 9895 : int half_width = GET_MODE_BITSIZE (mode) >> 1;
6374 : 9895 : machine_mode half_mode;
6375 : :
6376 : 9895 : rtx low[2], high[2];
6377 : 9895 : int count;
6378 : :
6379 : 9895 : if (CONST_INT_P (operands[2]))
6380 : : {
6381 : 8309 : split_double_mode (mode, operands, 2, low, high);
6382 : 8309 : count = INTVAL (operands[2]) & (GET_MODE_BITSIZE (mode) - 1);
6383 : :
6384 : 8309 : if (count >= half_width)
6385 : : {
6386 : 2497 : emit_move_insn (high[0], low[1]);
6387 : 2497 : ix86_expand_clear (low[0]);
6388 : :
6389 : 2497 : if (count > half_width)
6390 : 110 : ix86_expand_ashl_const (high[0], count - half_width, mode);
6391 : : }
6392 : 5812 : else if (count == 1)
6393 : : {
6394 : 1828 : if (!rtx_equal_p (operands[0], operands[1]))
6395 : 0 : emit_move_insn (operands[0], operands[1]);
6396 : 1828 : rtx x3 = gen_rtx_REG (CCCmode, FLAGS_REG);
6397 : 1828 : rtx x4 = gen_rtx_LTU (mode, x3, const0_rtx);
6398 : 1828 : half_mode = mode == DImode ? SImode : DImode;
6399 : 1828 : emit_insn (gen_add3_cc_overflow_1 (half_mode, low[0],
6400 : : low[0], low[0]));
6401 : 1828 : emit_insn (gen_add3_carry (half_mode, high[0], high[0], high[0],
6402 : : x3, x4));
6403 : : }
6404 : : else
6405 : : {
6406 : 3984 : gen_shld = mode == DImode ? gen_x86_shld : gen_x86_64_shld;
6407 : :
6408 : 3984 : if (!rtx_equal_p (operands[0], operands[1]))
6409 : 0 : emit_move_insn (operands[0], operands[1]);
6410 : :
6411 : 3984 : emit_insn (gen_shld (high[0], low[0], GEN_INT (count)));
6412 : 3984 : ix86_expand_ashl_const (low[0], count, mode);
6413 : : }
6414 : 8558 : return;
6415 : : }
6416 : :
6417 : 1586 : split_double_mode (mode, operands, 1, low, high);
6418 : 1586 : half_mode = mode == DImode ? SImode : DImode;
6419 : :
6420 : 1586 : gen_ashl3 = mode == DImode ? gen_ashlsi3 : gen_ashldi3;
6421 : :
6422 : 1586 : if (operands[1] == const1_rtx)
6423 : : {
6424 : : /* Assuming we've chosen a QImode capable registers, then 1 << N
6425 : : can be done with two 32/64-bit shifts, no branches, no cmoves. */
6426 : 249 : if (ANY_QI_REG_P (low[0]) && ANY_QI_REG_P (high[0]))
6427 : : {
6428 : 141 : rtx s, d, flags = gen_rtx_REG (CCZmode, FLAGS_REG);
6429 : :
6430 : 141 : ix86_expand_clear (low[0]);
6431 : 141 : ix86_expand_clear (high[0]);
6432 : 141 : emit_insn (gen_testqi_ccz_1 (operands[2], GEN_INT (half_width)));
6433 : :
6434 : 141 : d = gen_lowpart (QImode, low[0]);
6435 : 141 : d = gen_rtx_STRICT_LOW_PART (VOIDmode, d);
6436 : 141 : s = gen_rtx_EQ (QImode, flags, const0_rtx);
6437 : 141 : emit_insn (gen_rtx_SET (d, s));
6438 : :
6439 : 141 : d = gen_lowpart (QImode, high[0]);
6440 : 141 : d = gen_rtx_STRICT_LOW_PART (VOIDmode, d);
6441 : 141 : s = gen_rtx_NE (QImode, flags, const0_rtx);
6442 : 141 : emit_insn (gen_rtx_SET (d, s));
6443 : : }
6444 : :
6445 : : /* Otherwise, we can get the same results by manually performing
6446 : : a bit extract operation on bit 5/6, and then performing the two
6447 : : shifts. The two methods of getting 0/1 into low/high are exactly
6448 : : the same size. Avoiding the shift in the bit extract case helps
6449 : : pentium4 a bit; no one else seems to care much either way. */
6450 : : else
6451 : : {
6452 : 108 : rtx (*gen_lshr3)(rtx, rtx, rtx);
6453 : 108 : rtx (*gen_and3)(rtx, rtx, rtx);
6454 : 108 : rtx (*gen_xor3)(rtx, rtx, rtx);
6455 : 108 : HOST_WIDE_INT bits;
6456 : 108 : rtx x;
6457 : :
6458 : 108 : if (mode == DImode)
6459 : : {
6460 : : gen_lshr3 = gen_lshrsi3;
6461 : : gen_and3 = gen_andsi3;
6462 : : gen_xor3 = gen_xorsi3;
6463 : : bits = 5;
6464 : : }
6465 : : else
6466 : : {
6467 : 0 : gen_lshr3 = gen_lshrdi3;
6468 : 0 : gen_and3 = gen_anddi3;
6469 : 0 : gen_xor3 = gen_xordi3;
6470 : 0 : bits = 6;
6471 : : }
6472 : :
6473 : 108 : if (TARGET_PARTIAL_REG_STALL && !optimize_insn_for_size_p ())
6474 : 0 : x = gen_rtx_ZERO_EXTEND (half_mode, operands[2]);
6475 : : else
6476 : 108 : x = gen_lowpart (half_mode, operands[2]);
6477 : 108 : emit_insn (gen_rtx_SET (high[0], x));
6478 : :
6479 : 108 : emit_insn (gen_lshr3 (high[0], high[0], GEN_INT (bits)));
6480 : 108 : emit_insn (gen_and3 (high[0], high[0], const1_rtx));
6481 : 108 : emit_move_insn (low[0], high[0]);
6482 : 108 : emit_insn (gen_xor3 (low[0], low[0], const1_rtx));
6483 : : }
6484 : :
6485 : 249 : emit_insn (gen_ashl3 (low[0], low[0], operands[2]));
6486 : 249 : emit_insn (gen_ashl3 (high[0], high[0], operands[2]));
6487 : 249 : return;
6488 : : }
6489 : :
6490 : 1337 : if (operands[1] == constm1_rtx)
6491 : : {
6492 : : /* For -1 << N, we can avoid the shld instruction, because we
6493 : : know that we're shifting 0...31/63 ones into a -1. */
6494 : 120 : emit_move_insn (low[0], constm1_rtx);
6495 : 120 : if (optimize_insn_for_size_p ())
6496 : 6 : emit_move_insn (high[0], low[0]);
6497 : : else
6498 : 114 : emit_move_insn (high[0], constm1_rtx);
6499 : : }
6500 : : else
6501 : : {
6502 : 1217 : gen_shld = mode == DImode ? gen_x86_shld : gen_x86_64_shld;
6503 : :
6504 : 1217 : if (!rtx_equal_p (operands[0], operands[1]))
6505 : 5 : emit_move_insn (operands[0], operands[1]);
6506 : :
6507 : 1217 : split_double_mode (mode, operands, 1, low, high);
6508 : 1217 : emit_insn (gen_shld (high[0], low[0], operands[2]));
6509 : : }
6510 : :
6511 : 1337 : emit_insn (gen_ashl3 (low[0], low[0], operands[2]));
6512 : :
6513 : 1337 : if (TARGET_CMOVE && scratch)
6514 : : {
6515 : 979 : ix86_expand_clear (scratch);
6516 : 979 : emit_insn (gen_x86_shift_adj_1
6517 : : (half_mode, high[0], low[0], operands[2], scratch));
6518 : : }
6519 : : else
6520 : 358 : emit_insn (gen_x86_shift_adj_2 (half_mode, high[0], low[0], operands[2]));
6521 : : }
6522 : :
6523 : : void
6524 : 6617 : ix86_split_ashr (rtx *operands, rtx scratch, machine_mode mode)
6525 : : {
6526 : 13234 : rtx (*gen_ashr3)(rtx, rtx, rtx)
6527 : 6617 : = mode == DImode ? gen_ashrsi3 : gen_ashrdi3;
6528 : 6617 : rtx (*gen_shrd)(rtx, rtx, rtx);
6529 : 6617 : int half_width = GET_MODE_BITSIZE (mode) >> 1;
6530 : :
6531 : 6617 : rtx low[2], high[2];
6532 : 6617 : int count;
6533 : :
6534 : 6617 : if (CONST_INT_P (operands[2]))
6535 : : {
6536 : 6445 : split_double_mode (mode, operands, 2, low, high);
6537 : 6445 : count = INTVAL (operands[2]) & (GET_MODE_BITSIZE (mode) - 1);
6538 : :
6539 : 12890 : if (count == GET_MODE_BITSIZE (mode) - 1)
6540 : : {
6541 : 82 : emit_move_insn (high[0], high[1]);
6542 : 82 : emit_insn (gen_ashr3 (high[0], high[0],
6543 : 82 : GEN_INT (half_width - 1)));
6544 : 82 : emit_move_insn (low[0], high[0]);
6545 : :
6546 : : }
6547 : 6363 : else if (count >= half_width)
6548 : : {
6549 : 2087 : emit_move_insn (low[0], high[1]);
6550 : 2087 : emit_move_insn (high[0], low[0]);
6551 : 2087 : emit_insn (gen_ashr3 (high[0], high[0],
6552 : 2087 : GEN_INT (half_width - 1)));
6553 : :
6554 : 2087 : if (count > half_width)
6555 : 30 : emit_insn (gen_ashr3 (low[0], low[0],
6556 : 30 : GEN_INT (count - half_width)));
6557 : : }
6558 : 4276 : else if (count == 1
6559 : 829 : && (TARGET_USE_RCR || optimize_size > 1))
6560 : : {
6561 : 1 : if (!rtx_equal_p (operands[0], operands[1]))
6562 : 0 : emit_move_insn (operands[0], operands[1]);
6563 : 1 : if (mode == DImode)
6564 : : {
6565 : 0 : emit_insn (gen_ashrsi3_carry (high[0], high[0]));
6566 : 0 : emit_insn (gen_rcrsi2 (low[0], low[0]));
6567 : : }
6568 : : else
6569 : : {
6570 : 1 : emit_insn (gen_ashrdi3_carry (high[0], high[0]));
6571 : 1 : emit_insn (gen_rcrdi2 (low[0], low[0]));
6572 : : }
6573 : : }
6574 : : else
6575 : : {
6576 : 4275 : gen_shrd = mode == DImode ? gen_x86_shrd : gen_x86_64_shrd;
6577 : :
6578 : 4275 : if (!rtx_equal_p (operands[0], operands[1]))
6579 : 0 : emit_move_insn (operands[0], operands[1]);
6580 : :
6581 : 4275 : emit_insn (gen_shrd (low[0], high[0], GEN_INT (count)));
6582 : 4275 : emit_insn (gen_ashr3 (high[0], high[0], GEN_INT (count)));
6583 : : }
6584 : : }
6585 : : else
6586 : : {
6587 : 172 : machine_mode half_mode;
6588 : :
6589 : 172 : gen_shrd = mode == DImode ? gen_x86_shrd : gen_x86_64_shrd;
6590 : :
6591 : 172 : if (!rtx_equal_p (operands[0], operands[1]))
6592 : 0 : emit_move_insn (operands[0], operands[1]);
6593 : :
6594 : 172 : split_double_mode (mode, operands, 1, low, high);
6595 : 172 : half_mode = mode == DImode ? SImode : DImode;
6596 : :
6597 : 172 : emit_insn (gen_shrd (low[0], high[0], operands[2]));
6598 : 172 : emit_insn (gen_ashr3 (high[0], high[0], operands[2]));
6599 : :
6600 : 172 : if (TARGET_CMOVE && scratch)
6601 : : {
6602 : 135 : emit_move_insn (scratch, high[0]);
6603 : 135 : emit_insn (gen_ashr3 (scratch, scratch,
6604 : 135 : GEN_INT (half_width - 1)));
6605 : 135 : emit_insn (gen_x86_shift_adj_1
6606 : : (half_mode, low[0], high[0], operands[2], scratch));
6607 : : }
6608 : : else
6609 : 37 : emit_insn (gen_x86_shift_adj_3
6610 : : (half_mode, low[0], high[0], operands[2]));
6611 : : }
6612 : 6617 : }
6613 : :
6614 : : void
6615 : 13544 : ix86_split_lshr (rtx *operands, rtx scratch, machine_mode mode)
6616 : : {
6617 : 27088 : rtx (*gen_lshr3)(rtx, rtx, rtx)
6618 : 13544 : = mode == DImode ? gen_lshrsi3 : gen_lshrdi3;
6619 : 13544 : rtx (*gen_shrd)(rtx, rtx, rtx);
6620 : 13544 : int half_width = GET_MODE_BITSIZE (mode) >> 1;
6621 : :
6622 : 13544 : rtx low[2], high[2];
6623 : 13544 : int count;
6624 : :
6625 : 13544 : if (CONST_INT_P (operands[2]))
6626 : : {
6627 : 12168 : split_double_mode (mode, operands, 2, low, high);
6628 : 12168 : count = INTVAL (operands[2]) & (GET_MODE_BITSIZE (mode) - 1);
6629 : :
6630 : 12168 : if (count >= half_width)
6631 : : {
6632 : 8357 : emit_move_insn (low[0], high[1]);
6633 : 8357 : ix86_expand_clear (high[0]);
6634 : :
6635 : 8357 : if (count > half_width)
6636 : 577 : emit_insn (gen_lshr3 (low[0], low[0],
6637 : 577 : GEN_INT (count - half_width)));
6638 : : }
6639 : 3811 : else if (count == 1
6640 : 654 : && (TARGET_USE_RCR || optimize_size > 1))
6641 : : {
6642 : 1 : if (!rtx_equal_p (operands[0], operands[1]))
6643 : 0 : emit_move_insn (operands[0], operands[1]);
6644 : 1 : if (mode == DImode)
6645 : : {
6646 : 0 : emit_insn (gen_lshrsi3_carry (high[0], high[0]));
6647 : 0 : emit_insn (gen_rcrsi2 (low[0], low[0]));
6648 : : }
6649 : : else
6650 : : {
6651 : 1 : emit_insn (gen_lshrdi3_carry (high[0], high[0]));
6652 : 1 : emit_insn (gen_rcrdi2 (low[0], low[0]));
6653 : : }
6654 : : }
6655 : : else
6656 : : {
6657 : 3810 : gen_shrd = mode == DImode ? gen_x86_shrd : gen_x86_64_shrd;
6658 : :
6659 : 3810 : if (!rtx_equal_p (operands[0], operands[1]))
6660 : 0 : emit_move_insn (operands[0], operands[1]);
6661 : :
6662 : 3810 : emit_insn (gen_shrd (low[0], high[0], GEN_INT (count)));
6663 : 3810 : emit_insn (gen_lshr3 (high[0], high[0], GEN_INT (count)));
6664 : : }
6665 : : }
6666 : : else
6667 : : {
6668 : 1376 : machine_mode half_mode;
6669 : :
6670 : 1376 : gen_shrd = mode == DImode ? gen_x86_shrd : gen_x86_64_shrd;
6671 : :
6672 : 1376 : if (!rtx_equal_p (operands[0], operands[1]))
6673 : 0 : emit_move_insn (operands[0], operands[1]);
6674 : :
6675 : 1376 : split_double_mode (mode, operands, 1, low, high);
6676 : 1376 : half_mode = mode == DImode ? SImode : DImode;
6677 : :
6678 : 1376 : emit_insn (gen_shrd (low[0], high[0], operands[2]));
6679 : 1376 : emit_insn (gen_lshr3 (high[0], high[0], operands[2]));
6680 : :
6681 : 1376 : if (TARGET_CMOVE && scratch)
6682 : : {
6683 : 1092 : ix86_expand_clear (scratch);
6684 : 1092 : emit_insn (gen_x86_shift_adj_1
6685 : : (half_mode, low[0], high[0], operands[2], scratch));
6686 : : }
6687 : : else
6688 : 284 : emit_insn (gen_x86_shift_adj_2
6689 : : (half_mode, low[0], high[0], operands[2]));
6690 : : }
6691 : 13544 : }
6692 : :
6693 : : /* Helper function to split TImode ashl under NDD. */
6694 : : void
6695 : 1 : ix86_split_ashl_ndd (rtx *operands, rtx scratch)
6696 : : {
6697 : 1 : gcc_assert (TARGET_APX_NDD);
6698 : 1 : int half_width = GET_MODE_BITSIZE (TImode) >> 1;
6699 : :
6700 : 1 : rtx low[2], high[2];
6701 : 1 : int count;
6702 : :
6703 : 1 : split_double_mode (TImode, operands, 2, low, high);
6704 : 1 : if (CONST_INT_P (operands[2]))
6705 : : {
6706 : 0 : count = INTVAL (operands[2]) & (GET_MODE_BITSIZE (TImode) - 1);
6707 : :
6708 : 0 : if (count >= half_width)
6709 : : {
6710 : 0 : count = count - half_width;
6711 : 0 : if (count == 0)
6712 : : {
6713 : 0 : if (!rtx_equal_p (high[0], low[1]))
6714 : 0 : emit_move_insn (high[0], low[1]);
6715 : : }
6716 : 0 : else if (count == 1)
6717 : 0 : emit_insn (gen_adddi3 (high[0], low[1], low[1]));
6718 : : else
6719 : 0 : emit_insn (gen_ashldi3 (high[0], low[1], GEN_INT (count)));
6720 : :
6721 : 0 : ix86_expand_clear (low[0]);
6722 : : }
6723 : 0 : else if (count == 1)
6724 : : {
6725 : 0 : rtx x3 = gen_rtx_REG (CCCmode, FLAGS_REG);
6726 : 0 : rtx x4 = gen_rtx_LTU (TImode, x3, const0_rtx);
6727 : 0 : emit_insn (gen_add3_cc_overflow_1 (DImode, low[0],
6728 : : low[1], low[1]));
6729 : 0 : emit_insn (gen_add3_carry (DImode, high[0], high[1], high[1],
6730 : : x3, x4));
6731 : : }
6732 : : else
6733 : : {
6734 : 0 : emit_insn (gen_x86_64_shld_ndd (high[0], high[1], low[1],
6735 : : GEN_INT (count)));
6736 : 0 : emit_insn (gen_ashldi3 (low[0], low[1], GEN_INT (count)));
6737 : : }
6738 : : }
6739 : : else
6740 : : {
6741 : 1 : emit_insn (gen_x86_64_shld_ndd (high[0], high[1], low[1],
6742 : : operands[2]));
6743 : 1 : emit_insn (gen_ashldi3 (low[0], low[1], operands[2]));
6744 : 1 : if (TARGET_CMOVE && scratch)
6745 : : {
6746 : 1 : ix86_expand_clear (scratch);
6747 : 1 : emit_insn (gen_x86_shift_adj_1
6748 : : (DImode, high[0], low[0], operands[2], scratch));
6749 : : }
6750 : : else
6751 : 0 : emit_insn (gen_x86_shift_adj_2 (DImode, high[0], low[0], operands[2]));
6752 : : }
6753 : 1 : }
6754 : :
6755 : : /* Helper function to split TImode l/ashr under NDD. */
6756 : : void
6757 : 2 : ix86_split_rshift_ndd (enum rtx_code code, rtx *operands, rtx scratch)
6758 : : {
6759 : 2 : gcc_assert (TARGET_APX_NDD);
6760 : 2 : int half_width = GET_MODE_BITSIZE (TImode) >> 1;
6761 : 2 : bool ashr_p = code == ASHIFTRT;
6762 : 2 : rtx (*gen_shr)(rtx, rtx, rtx) = ashr_p ? gen_ashrdi3
6763 : : : gen_lshrdi3;
6764 : :
6765 : 2 : rtx low[2], high[2];
6766 : 2 : int count;
6767 : :
6768 : 2 : split_double_mode (TImode, operands, 2, low, high);
6769 : 2 : if (CONST_INT_P (operands[2]))
6770 : : {
6771 : 0 : count = INTVAL (operands[2]) & (GET_MODE_BITSIZE (TImode) - 1);
6772 : :
6773 : 0 : if (ashr_p && (count == GET_MODE_BITSIZE (TImode) - 1))
6774 : : {
6775 : 0 : emit_insn (gen_shr (high[0], high[1],
6776 : : GEN_INT (half_width - 1)));
6777 : 0 : emit_move_insn (low[0], high[0]);
6778 : : }
6779 : 0 : else if (count >= half_width)
6780 : : {
6781 : 0 : if (ashr_p)
6782 : 0 : emit_insn (gen_shr (high[0], high[1],
6783 : : GEN_INT (half_width - 1)));
6784 : : else
6785 : 0 : ix86_expand_clear (high[0]);
6786 : :
6787 : 0 : if (count > half_width)
6788 : 0 : emit_insn (gen_shr (low[0], high[1],
6789 : 0 : GEN_INT (count - half_width)));
6790 : : else
6791 : 0 : emit_move_insn (low[0], high[1]);
6792 : : }
6793 : : else
6794 : : {
6795 : 0 : emit_insn (gen_x86_64_shrd_ndd (low[0], low[1], high[1],
6796 : : GEN_INT (count)));
6797 : 0 : emit_insn (gen_shr (high[0], high[1], GEN_INT (count)));
6798 : : }
6799 : : }
6800 : : else
6801 : : {
6802 : 2 : emit_insn (gen_x86_64_shrd_ndd (low[0], low[1], high[1],
6803 : : operands[2]));
6804 : 2 : emit_insn (gen_shr (high[0], high[1], operands[2]));
6805 : :
6806 : 2 : if (TARGET_CMOVE && scratch)
6807 : : {
6808 : 2 : if (ashr_p)
6809 : : {
6810 : 1 : emit_move_insn (scratch, high[0]);
6811 : 1 : emit_insn (gen_shr (scratch, scratch,
6812 : : GEN_INT (half_width - 1)));
6813 : : }
6814 : : else
6815 : 1 : ix86_expand_clear (scratch);
6816 : :
6817 : 2 : emit_insn (gen_x86_shift_adj_1
6818 : : (DImode, low[0], high[0], operands[2], scratch));
6819 : : }
6820 : 0 : else if (ashr_p)
6821 : 0 : emit_insn (gen_x86_shift_adj_3
6822 : : (DImode, low[0], high[0], operands[2]));
6823 : : else
6824 : 0 : emit_insn (gen_x86_shift_adj_2
6825 : : (DImode, low[0], high[0], operands[2]));
6826 : : }
6827 : 2 : }
6828 : :
6829 : : /* Expand move of V1TI mode register X to a new TI mode register. */
6830 : : static rtx
6831 : 17 : ix86_expand_v1ti_to_ti (rtx x)
6832 : : {
6833 : 17 : rtx result = gen_reg_rtx (TImode);
6834 : 17 : if (TARGET_SSE2)
6835 : : {
6836 : 17 : rtx temp = force_reg (V2DImode, gen_lowpart (V2DImode, x));
6837 : 17 : rtx lo = gen_lowpart (DImode, result);
6838 : 17 : emit_insn (gen_vec_extractv2didi (lo, temp, const0_rtx));
6839 : 17 : rtx hi = gen_highpart (DImode, result);
6840 : 17 : emit_insn (gen_vec_extractv2didi (hi, temp, const1_rtx));
6841 : : }
6842 : : else
6843 : 0 : emit_move_insn (result, gen_lowpart (TImode, x));
6844 : 17 : return result;
6845 : : }
6846 : :
6847 : : /* Expand move of TI mode register X to a new V1TI mode register. */
6848 : : static rtx
6849 : 17 : ix86_expand_ti_to_v1ti (rtx x)
6850 : : {
6851 : 17 : if (TARGET_SSE2)
6852 : : {
6853 : 17 : rtx lo = gen_lowpart (DImode, x);
6854 : 17 : rtx hi = gen_highpart (DImode, x);
6855 : 17 : rtx tmp = gen_reg_rtx (V2DImode);
6856 : 17 : emit_insn (gen_vec_concatv2di (tmp, lo, hi));
6857 : 17 : return force_reg (V1TImode, gen_lowpart (V1TImode, tmp));
6858 : : }
6859 : :
6860 : 0 : return force_reg (V1TImode, gen_lowpart (V1TImode, x));
6861 : : }
6862 : :
6863 : : /* Expand V1TI mode shift (of rtx_code CODE) by constant. */
6864 : : void
6865 : 42 : ix86_expand_v1ti_shift (enum rtx_code code, rtx operands[])
6866 : : {
6867 : 42 : rtx op1 = force_reg (V1TImode, operands[1]);
6868 : :
6869 : 42 : if (!CONST_INT_P (operands[2]))
6870 : : {
6871 : 6 : rtx tmp1 = ix86_expand_v1ti_to_ti (op1);
6872 : 6 : rtx tmp2 = gen_reg_rtx (TImode);
6873 : 12 : rtx (*shift) (rtx, rtx, rtx)
6874 : 6 : = (code == ASHIFT) ? gen_ashlti3 : gen_lshrti3;
6875 : 6 : emit_insn (shift (tmp2, tmp1, operands[2]));
6876 : 6 : rtx tmp3 = ix86_expand_ti_to_v1ti (tmp2);
6877 : 6 : emit_move_insn (operands[0], tmp3);
6878 : 6 : return;
6879 : : }
6880 : :
6881 : 36 : HOST_WIDE_INT bits = INTVAL (operands[2]) & 127;
6882 : :
6883 : 36 : if (bits == 0)
6884 : : {
6885 : 0 : emit_move_insn (operands[0], op1);
6886 : 0 : return;
6887 : : }
6888 : :
6889 : 36 : if ((bits & 7) == 0)
6890 : : {
6891 : 0 : rtx tmp = gen_reg_rtx (V1TImode);
6892 : 0 : if (code == ASHIFT)
6893 : 0 : emit_insn (gen_sse2_ashlv1ti3 (tmp, op1, GEN_INT (bits)));
6894 : : else
6895 : 0 : emit_insn (gen_sse2_lshrv1ti3 (tmp, op1, GEN_INT (bits)));
6896 : 0 : emit_move_insn (operands[0], tmp);
6897 : 0 : return;
6898 : : }
6899 : :
6900 : 36 : rtx tmp1 = gen_reg_rtx (V1TImode);
6901 : 36 : if (code == ASHIFT)
6902 : 18 : emit_insn (gen_sse2_ashlv1ti3 (tmp1, op1, GEN_INT (64)));
6903 : : else
6904 : 18 : emit_insn (gen_sse2_lshrv1ti3 (tmp1, op1, GEN_INT (64)));
6905 : :
6906 : : /* tmp2 is operands[1] shifted by 64, in V2DImode. */
6907 : 36 : rtx tmp2 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp1));
6908 : :
6909 : : /* tmp3 will be the V2DImode result. */
6910 : 36 : rtx tmp3 = gen_reg_rtx (V2DImode);
6911 : :
6912 : 36 : if (bits > 64)
6913 : : {
6914 : 18 : if (code == ASHIFT)
6915 : 9 : emit_insn (gen_ashlv2di3 (tmp3, tmp2, GEN_INT (bits - 64)));
6916 : : else
6917 : 9 : emit_insn (gen_lshrv2di3 (tmp3, tmp2, GEN_INT (bits - 64)));
6918 : : }
6919 : : else
6920 : : {
6921 : : /* tmp4 is operands[1], in V2DImode. */
6922 : 18 : rtx tmp4 = force_reg (V2DImode, gen_lowpart (V2DImode, op1));
6923 : :
6924 : 18 : rtx tmp5 = gen_reg_rtx (V2DImode);
6925 : 18 : if (code == ASHIFT)
6926 : 9 : emit_insn (gen_ashlv2di3 (tmp5, tmp4, GEN_INT (bits)));
6927 : : else
6928 : 9 : emit_insn (gen_lshrv2di3 (tmp5, tmp4, GEN_INT (bits)));
6929 : :
6930 : 18 : rtx tmp6 = gen_reg_rtx (V2DImode);
6931 : 18 : if (code == ASHIFT)
6932 : 9 : emit_insn (gen_lshrv2di3 (tmp6, tmp2, GEN_INT (64 - bits)));
6933 : : else
6934 : 9 : emit_insn (gen_ashlv2di3 (tmp6, tmp2, GEN_INT (64 - bits)));
6935 : :
6936 : 18 : emit_insn (gen_iorv2di3 (tmp3, tmp5, tmp6));
6937 : : }
6938 : :
6939 : : /* Convert the result back to V1TImode and store in operands[0]. */
6940 : 36 : rtx tmp7 = force_reg (V1TImode, gen_lowpart (V1TImode, tmp3));
6941 : 36 : emit_move_insn (operands[0], tmp7);
6942 : : }
6943 : :
6944 : : /* Expand V1TI mode rotate (of rtx_code CODE) by constant. */
6945 : : void
6946 : 39 : ix86_expand_v1ti_rotate (enum rtx_code code, rtx operands[])
6947 : : {
6948 : 39 : rtx op1 = force_reg (V1TImode, operands[1]);
6949 : :
6950 : 39 : if (!CONST_INT_P (operands[2]))
6951 : : {
6952 : 8 : rtx tmp1 = ix86_expand_v1ti_to_ti (op1);
6953 : 8 : rtx tmp2 = gen_reg_rtx (TImode);
6954 : 16 : rtx (*rotate) (rtx, rtx, rtx)
6955 : 8 : = (code == ROTATE) ? gen_rotlti3 : gen_rotrti3;
6956 : 8 : emit_insn (rotate (tmp2, tmp1, operands[2]));
6957 : 8 : rtx tmp3 = ix86_expand_ti_to_v1ti (tmp2);
6958 : 8 : emit_move_insn (operands[0], tmp3);
6959 : 8 : return;
6960 : : }
6961 : :
6962 : 31 : HOST_WIDE_INT bits = INTVAL (operands[2]) & 127;
6963 : :
6964 : 31 : if (bits == 0)
6965 : : {
6966 : 0 : emit_move_insn (operands[0], op1);
6967 : 0 : return;
6968 : : }
6969 : :
6970 : 31 : if (code == ROTATERT)
6971 : 16 : bits = 128 - bits;
6972 : :
6973 : 31 : if ((bits & 31) == 0)
6974 : : {
6975 : 5 : rtx tmp2 = gen_reg_rtx (V4SImode);
6976 : 5 : rtx tmp1 = force_reg (V4SImode, gen_lowpart (V4SImode, op1));
6977 : 5 : if (bits == 32)
6978 : 1 : emit_insn (gen_sse2_pshufd (tmp2, tmp1, GEN_INT (0x93)));
6979 : 4 : else if (bits == 64)
6980 : 2 : emit_insn (gen_sse2_pshufd (tmp2, tmp1, GEN_INT (0x4e)));
6981 : : else
6982 : 2 : emit_insn (gen_sse2_pshufd (tmp2, tmp1, GEN_INT (0x39)));
6983 : 5 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp2));
6984 : 5 : return;
6985 : : }
6986 : :
6987 : 26 : if ((bits & 7) == 0)
6988 : : {
6989 : 6 : rtx tmp1 = gen_reg_rtx (V1TImode);
6990 : 6 : rtx tmp2 = gen_reg_rtx (V1TImode);
6991 : 6 : rtx tmp3 = gen_reg_rtx (V1TImode);
6992 : :
6993 : 6 : emit_insn (gen_sse2_ashlv1ti3 (tmp1, op1, GEN_INT (bits)));
6994 : 6 : emit_insn (gen_sse2_lshrv1ti3 (tmp2, op1, GEN_INT (128 - bits)));
6995 : 6 : emit_insn (gen_iorv1ti3 (tmp3, tmp1, tmp2));
6996 : 6 : emit_move_insn (operands[0], tmp3);
6997 : 6 : return;
6998 : : }
6999 : :
7000 : 20 : rtx op1_v4si = force_reg (V4SImode, gen_lowpart (V4SImode, op1));
7001 : :
7002 : 20 : rtx lobits;
7003 : 20 : rtx hibits;
7004 : :
7005 : 20 : switch (bits >> 5)
7006 : : {
7007 : 7 : case 0:
7008 : 7 : lobits = op1_v4si;
7009 : 7 : hibits = gen_reg_rtx (V4SImode);
7010 : 7 : emit_insn (gen_sse2_pshufd (hibits, op1_v4si, GEN_INT (0x93)));
7011 : 7 : break;
7012 : :
7013 : 2 : case 1:
7014 : 2 : lobits = gen_reg_rtx (V4SImode);
7015 : 2 : hibits = gen_reg_rtx (V4SImode);
7016 : 2 : emit_insn (gen_sse2_pshufd (lobits, op1_v4si, GEN_INT (0x93)));
7017 : 2 : emit_insn (gen_sse2_pshufd (hibits, op1_v4si, GEN_INT (0x4e)));
7018 : 2 : break;
7019 : :
7020 : 2 : case 2:
7021 : 2 : lobits = gen_reg_rtx (V4SImode);
7022 : 2 : hibits = gen_reg_rtx (V4SImode);
7023 : 2 : emit_insn (gen_sse2_pshufd (lobits, op1_v4si, GEN_INT (0x4e)));
7024 : 2 : emit_insn (gen_sse2_pshufd (hibits, op1_v4si, GEN_INT (0x39)));
7025 : 2 : break;
7026 : :
7027 : 9 : default:
7028 : 9 : lobits = gen_reg_rtx (V4SImode);
7029 : 9 : emit_insn (gen_sse2_pshufd (lobits, op1_v4si, GEN_INT (0x39)));
7030 : 9 : hibits = op1_v4si;
7031 : 9 : break;
7032 : : }
7033 : :
7034 : 20 : rtx tmp1 = gen_reg_rtx (V4SImode);
7035 : 20 : rtx tmp2 = gen_reg_rtx (V4SImode);
7036 : 20 : rtx tmp3 = gen_reg_rtx (V4SImode);
7037 : :
7038 : 20 : emit_insn (gen_ashlv4si3 (tmp1, lobits, GEN_INT (bits & 31)));
7039 : 20 : emit_insn (gen_lshrv4si3 (tmp2, hibits, GEN_INT (32 - (bits & 31))));
7040 : 20 : emit_insn (gen_iorv4si3 (tmp3, tmp1, tmp2));
7041 : :
7042 : 20 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp3));
7043 : : }
7044 : :
7045 : : /* Expand V1TI mode ashiftrt by constant. */
7046 : : void
7047 : 108 : ix86_expand_v1ti_ashiftrt (rtx operands[])
7048 : : {
7049 : 108 : rtx op1 = force_reg (V1TImode, operands[1]);
7050 : :
7051 : 108 : if (!CONST_INT_P (operands[2]))
7052 : : {
7053 : 3 : rtx tmp1 = ix86_expand_v1ti_to_ti (op1);
7054 : 3 : rtx tmp2 = gen_reg_rtx (TImode);
7055 : 3 : emit_insn (gen_ashrti3 (tmp2, tmp1, operands[2]));
7056 : 3 : rtx tmp3 = ix86_expand_ti_to_v1ti (tmp2);
7057 : 3 : emit_move_insn (operands[0], tmp3);
7058 : 3 : return;
7059 : : }
7060 : :
7061 : 105 : HOST_WIDE_INT bits = INTVAL (operands[2]) & 127;
7062 : :
7063 : 105 : if (bits == 0)
7064 : : {
7065 : 0 : emit_move_insn (operands[0], op1);
7066 : 0 : return;
7067 : : }
7068 : :
7069 : 105 : if (bits == 127)
7070 : : {
7071 : : /* Two operations. */
7072 : 3 : rtx tmp1 = force_reg(V4SImode, gen_lowpart (V4SImode, op1));
7073 : 3 : rtx tmp2 = gen_reg_rtx (V4SImode);
7074 : 3 : emit_insn (gen_sse2_pshufd (tmp2, tmp1, GEN_INT (0xff)));
7075 : :
7076 : 3 : rtx tmp3 = gen_reg_rtx (V4SImode);
7077 : 3 : emit_insn (gen_ashrv4si3 (tmp3, tmp2, GEN_INT (31)));
7078 : :
7079 : 3 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp3));
7080 : 3 : return;
7081 : : }
7082 : :
7083 : 102 : if (bits == 64)
7084 : : {
7085 : : /* Three operations. */
7086 : 3 : rtx tmp1 = force_reg(V4SImode, gen_lowpart (V4SImode, op1));
7087 : 3 : rtx tmp2 = gen_reg_rtx (V4SImode);
7088 : 3 : emit_insn (gen_sse2_pshufd (tmp2, tmp1, GEN_INT (0xff)));
7089 : :
7090 : 3 : rtx tmp3 = gen_reg_rtx (V4SImode);
7091 : 3 : emit_insn (gen_ashrv4si3 (tmp3, tmp2, GEN_INT (31)));
7092 : :
7093 : 3 : rtx tmp4 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp1));
7094 : 3 : rtx tmp5 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp3));
7095 : 3 : rtx tmp6 = gen_reg_rtx (V2DImode);
7096 : 3 : emit_insn (gen_vec_interleave_highv2di (tmp6, tmp4, tmp5));
7097 : :
7098 : 3 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp6));
7099 : 3 : return;
7100 : : }
7101 : :
7102 : 99 : if (bits == 96)
7103 : : {
7104 : : /* Three operations. */
7105 : 3 : rtx tmp1 = force_reg(V4SImode, gen_lowpart (V4SImode, op1));
7106 : 3 : rtx tmp2 = gen_reg_rtx (V4SImode);
7107 : 3 : emit_insn (gen_ashrv4si3 (tmp2, tmp1, GEN_INT (31)));
7108 : :
7109 : 3 : rtx tmp3 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp1));
7110 : 3 : rtx tmp4 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp2));
7111 : 3 : rtx tmp5 = gen_reg_rtx (V2DImode);
7112 : 3 : emit_insn (gen_vec_interleave_highv2di (tmp5, tmp3, tmp4));
7113 : :
7114 : 3 : rtx tmp6 = force_reg(V4SImode, gen_lowpart (V4SImode, tmp5));
7115 : 3 : rtx tmp7 = gen_reg_rtx (V4SImode);
7116 : 3 : emit_insn (gen_sse2_pshufd (tmp7, tmp6, GEN_INT (0xfd)));
7117 : :
7118 : 3 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp7));
7119 : 3 : return;
7120 : : }
7121 : :
7122 : 96 : if (bits >= 111)
7123 : : {
7124 : : /* Three operations. */
7125 : 21 : rtx tmp1 = force_reg (V4SImode, gen_lowpart (V4SImode, op1));
7126 : 21 : rtx tmp2 = gen_reg_rtx (V4SImode);
7127 : 21 : emit_insn (gen_ashrv4si3 (tmp2, tmp1, GEN_INT (bits - 96)));
7128 : :
7129 : 21 : rtx tmp3 = force_reg (V8HImode, gen_lowpart (V8HImode, tmp2));
7130 : 21 : rtx tmp4 = gen_reg_rtx (V8HImode);
7131 : 21 : emit_insn (gen_sse2_pshufhw (tmp4, tmp3, GEN_INT (0xfe)));
7132 : :
7133 : 21 : rtx tmp5 = force_reg (V4SImode, gen_lowpart (V4SImode, tmp4));
7134 : 21 : rtx tmp6 = gen_reg_rtx (V4SImode);
7135 : 21 : emit_insn (gen_sse2_pshufd (tmp6, tmp5, GEN_INT (0xfe)));
7136 : :
7137 : 21 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp6));
7138 : 21 : return;
7139 : : }
7140 : :
7141 : 75 : if (TARGET_AVX2 || TARGET_SSE4_1)
7142 : : {
7143 : : /* Three operations. */
7144 : 50 : if (bits == 32)
7145 : : {
7146 : 2 : rtx tmp1 = force_reg (V4SImode, gen_lowpart (V4SImode, op1));
7147 : 2 : rtx tmp2 = gen_reg_rtx (V4SImode);
7148 : 2 : emit_insn (gen_ashrv4si3 (tmp2, tmp1, GEN_INT (31)));
7149 : :
7150 : 2 : rtx tmp3 = gen_reg_rtx (V1TImode);
7151 : 2 : emit_insn (gen_sse2_lshrv1ti3 (tmp3, op1, GEN_INT (32)));
7152 : :
7153 : 2 : if (TARGET_AVX2)
7154 : : {
7155 : 1 : rtx tmp4 = force_reg (V4SImode, gen_lowpart (V4SImode, tmp3));
7156 : 1 : rtx tmp5 = gen_reg_rtx (V4SImode);
7157 : 1 : emit_insn (gen_avx2_pblenddv4si (tmp5, tmp2, tmp4,
7158 : : GEN_INT (7)));
7159 : :
7160 : 1 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp5));
7161 : : }
7162 : : else
7163 : : {
7164 : 1 : rtx tmp4 = force_reg (V8HImode, gen_lowpart (V8HImode, tmp2));
7165 : 1 : rtx tmp5 = force_reg (V8HImode, gen_lowpart (V8HImode, tmp3));
7166 : 1 : rtx tmp6 = gen_reg_rtx (V8HImode);
7167 : 1 : emit_insn (gen_sse4_1_pblendw (tmp6, tmp4, tmp5,
7168 : : GEN_INT (0x3f)));
7169 : :
7170 : 1 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp6));
7171 : : }
7172 : 2 : return;
7173 : : }
7174 : :
7175 : : /* Three operations. */
7176 : 48 : if (bits == 8 || bits == 16 || bits == 24)
7177 : : {
7178 : 6 : rtx tmp1 = force_reg (V4SImode, gen_lowpart (V4SImode, op1));
7179 : 6 : rtx tmp2 = gen_reg_rtx (V4SImode);
7180 : 6 : emit_insn (gen_ashrv4si3 (tmp2, tmp1, GEN_INT (bits)));
7181 : :
7182 : 6 : rtx tmp3 = gen_reg_rtx (V1TImode);
7183 : 6 : emit_insn (gen_sse2_lshrv1ti3 (tmp3, op1, GEN_INT (bits)));
7184 : :
7185 : 6 : if (TARGET_AVX2)
7186 : : {
7187 : 3 : rtx tmp4 = force_reg (V4SImode, gen_lowpart (V4SImode, tmp3));
7188 : 3 : rtx tmp5 = gen_reg_rtx (V4SImode);
7189 : 3 : emit_insn (gen_avx2_pblenddv4si (tmp5, tmp2, tmp4,
7190 : : GEN_INT (7)));
7191 : :
7192 : 3 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp5));
7193 : : }
7194 : : else
7195 : : {
7196 : 3 : rtx tmp4 = force_reg (V8HImode, gen_lowpart (V8HImode, tmp2));
7197 : 3 : rtx tmp5 = force_reg (V8HImode, gen_lowpart (V8HImode, tmp3));
7198 : 3 : rtx tmp6 = gen_reg_rtx (V8HImode);
7199 : 3 : emit_insn (gen_sse4_1_pblendw (tmp6, tmp4, tmp5,
7200 : : GEN_INT (0x3f)));
7201 : :
7202 : 3 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp6));
7203 : : }
7204 : 6 : return;
7205 : : }
7206 : : }
7207 : :
7208 : 67 : if (bits > 96)
7209 : : {
7210 : : /* Four operations. */
7211 : 3 : rtx tmp1 = force_reg (V4SImode, gen_lowpart (V4SImode, op1));
7212 : 3 : rtx tmp2 = gen_reg_rtx (V4SImode);
7213 : 3 : emit_insn (gen_ashrv4si3 (tmp2, tmp1, GEN_INT (bits - 96)));
7214 : :
7215 : 3 : rtx tmp3 = gen_reg_rtx (V4SImode);
7216 : 3 : emit_insn (gen_ashrv4si3 (tmp3, tmp1, GEN_INT (31)));
7217 : :
7218 : 3 : rtx tmp4 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp2));
7219 : 3 : rtx tmp5 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp3));
7220 : 3 : rtx tmp6 = gen_reg_rtx (V2DImode);
7221 : 3 : emit_insn (gen_vec_interleave_highv2di (tmp6, tmp4, tmp5));
7222 : :
7223 : 3 : rtx tmp7 = force_reg (V4SImode, gen_lowpart (V4SImode, tmp6));
7224 : 3 : rtx tmp8 = gen_reg_rtx (V4SImode);
7225 : 3 : emit_insn (gen_sse2_pshufd (tmp8, tmp7, GEN_INT (0xfd)));
7226 : :
7227 : 3 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp8));
7228 : 3 : return;
7229 : : }
7230 : :
7231 : 64 : if (TARGET_SSE4_1 && (bits == 48 || bits == 80))
7232 : : {
7233 : : /* Four operations. */
7234 : 4 : rtx tmp1 = force_reg (V4SImode, gen_lowpart (V4SImode, op1));
7235 : 4 : rtx tmp2 = gen_reg_rtx (V4SImode);
7236 : 4 : emit_insn (gen_sse2_pshufd (tmp2, tmp1, GEN_INT (0xff)));
7237 : :
7238 : 4 : rtx tmp3 = gen_reg_rtx (V4SImode);
7239 : 4 : emit_insn (gen_ashrv4si3 (tmp3, tmp2, GEN_INT (31)));
7240 : :
7241 : 4 : rtx tmp4 = gen_reg_rtx (V1TImode);
7242 : 4 : emit_insn (gen_sse2_lshrv1ti3 (tmp4, op1, GEN_INT (bits)));
7243 : :
7244 : 4 : rtx tmp5 = force_reg (V8HImode, gen_lowpart (V8HImode, tmp3));
7245 : 4 : rtx tmp6 = force_reg (V8HImode, gen_lowpart (V8HImode, tmp4));
7246 : 4 : rtx tmp7 = gen_reg_rtx (V8HImode);
7247 : 6 : emit_insn (gen_sse4_1_pblendw (tmp7, tmp5, tmp6,
7248 : : GEN_INT (bits == 48 ? 0x1f : 0x07)));
7249 : :
7250 : 4 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp7));
7251 : 4 : return;
7252 : : }
7253 : :
7254 : 60 : if ((bits & 7) == 0)
7255 : : {
7256 : : /* Five operations. */
7257 : 9 : rtx tmp1 = force_reg (V4SImode, gen_lowpart (V4SImode, op1));
7258 : 9 : rtx tmp2 = gen_reg_rtx (V4SImode);
7259 : 9 : emit_insn (gen_sse2_pshufd (tmp2, tmp1, GEN_INT (0xff)));
7260 : :
7261 : 9 : rtx tmp3 = gen_reg_rtx (V4SImode);
7262 : 9 : emit_insn (gen_ashrv4si3 (tmp3, tmp2, GEN_INT (31)));
7263 : :
7264 : 9 : rtx tmp4 = gen_reg_rtx (V1TImode);
7265 : 9 : emit_insn (gen_sse2_lshrv1ti3 (tmp4, op1, GEN_INT (bits)));
7266 : :
7267 : 9 : rtx tmp5 = force_reg (V1TImode, gen_lowpart (V1TImode, tmp3));
7268 : 9 : rtx tmp6 = gen_reg_rtx (V1TImode);
7269 : 9 : emit_insn (gen_sse2_ashlv1ti3 (tmp6, tmp5, GEN_INT (128 - bits)));
7270 : :
7271 : 9 : rtx tmp7 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp4));
7272 : 9 : rtx tmp8 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp6));
7273 : 9 : rtx tmp9 = gen_reg_rtx (V2DImode);
7274 : 9 : emit_insn (gen_iorv2di3 (tmp9, tmp7, tmp8));
7275 : :
7276 : 9 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp9));
7277 : 9 : return;
7278 : : }
7279 : :
7280 : 51 : if (TARGET_AVX2 && bits < 32)
7281 : : {
7282 : : /* Six operations. */
7283 : 9 : rtx tmp1 = force_reg (V4SImode, gen_lowpart (V4SImode, op1));
7284 : 9 : rtx tmp2 = gen_reg_rtx (V4SImode);
7285 : 9 : emit_insn (gen_ashrv4si3 (tmp2, tmp1, GEN_INT (bits)));
7286 : :
7287 : 9 : rtx tmp3 = gen_reg_rtx (V1TImode);
7288 : 9 : emit_insn (gen_sse2_lshrv1ti3 (tmp3, op1, GEN_INT (64)));
7289 : :
7290 : 9 : rtx tmp4 = force_reg (V2DImode, gen_lowpart (V2DImode, op1));
7291 : 9 : rtx tmp5 = gen_reg_rtx (V2DImode);
7292 : 9 : emit_insn (gen_lshrv2di3 (tmp5, tmp4, GEN_INT (bits)));
7293 : :
7294 : 9 : rtx tmp6 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp3));
7295 : 9 : rtx tmp7 = gen_reg_rtx (V2DImode);
7296 : 9 : emit_insn (gen_ashlv2di3 (tmp7, tmp6, GEN_INT (64 - bits)));
7297 : :
7298 : 9 : rtx tmp8 = gen_reg_rtx (V2DImode);
7299 : 9 : emit_insn (gen_iorv2di3 (tmp8, tmp5, tmp7));
7300 : :
7301 : 9 : rtx tmp9 = force_reg (V4SImode, gen_lowpart (V4SImode, tmp8));
7302 : 9 : rtx tmp10 = gen_reg_rtx (V4SImode);
7303 : 9 : emit_insn (gen_avx2_pblenddv4si (tmp10, tmp2, tmp9, GEN_INT (7)));
7304 : :
7305 : 9 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp10));
7306 : 9 : return;
7307 : : }
7308 : :
7309 : 42 : if (TARGET_SSE4_1 && bits < 15)
7310 : : {
7311 : : /* Six operations. */
7312 : 4 : rtx tmp1 = force_reg (V4SImode, gen_lowpart (V4SImode, op1));
7313 : 4 : rtx tmp2 = gen_reg_rtx (V4SImode);
7314 : 4 : emit_insn (gen_ashrv4si3 (tmp2, tmp1, GEN_INT (bits)));
7315 : :
7316 : 4 : rtx tmp3 = gen_reg_rtx (V1TImode);
7317 : 4 : emit_insn (gen_sse2_lshrv1ti3 (tmp3, op1, GEN_INT (64)));
7318 : :
7319 : 4 : rtx tmp4 = force_reg (V2DImode, gen_lowpart (V2DImode, op1));
7320 : 4 : rtx tmp5 = gen_reg_rtx (V2DImode);
7321 : 4 : emit_insn (gen_lshrv2di3 (tmp5, tmp4, GEN_INT (bits)));
7322 : :
7323 : 4 : rtx tmp6 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp3));
7324 : 4 : rtx tmp7 = gen_reg_rtx (V2DImode);
7325 : 4 : emit_insn (gen_ashlv2di3 (tmp7, tmp6, GEN_INT (64 - bits)));
7326 : :
7327 : 4 : rtx tmp8 = gen_reg_rtx (V2DImode);
7328 : 4 : emit_insn (gen_iorv2di3 (tmp8, tmp5, tmp7));
7329 : :
7330 : 4 : rtx tmp9 = force_reg (V8HImode, gen_lowpart (V8HImode, tmp2));
7331 : 4 : rtx tmp10 = force_reg (V8HImode, gen_lowpart (V8HImode, tmp8));
7332 : 4 : rtx tmp11 = gen_reg_rtx (V8HImode);
7333 : 4 : emit_insn (gen_sse4_1_pblendw (tmp11, tmp9, tmp10, GEN_INT (0x3f)));
7334 : :
7335 : 4 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp11));
7336 : 4 : return;
7337 : : }
7338 : :
7339 : 17 : if (bits == 1)
7340 : : {
7341 : : /* Eight operations. */
7342 : 1 : rtx tmp1 = gen_reg_rtx (V1TImode);
7343 : 1 : emit_insn (gen_sse2_lshrv1ti3 (tmp1, op1, GEN_INT (64)));
7344 : :
7345 : 1 : rtx tmp2 = force_reg (V2DImode, gen_lowpart (V2DImode, op1));
7346 : 1 : rtx tmp3 = gen_reg_rtx (V2DImode);
7347 : 1 : emit_insn (gen_lshrv2di3 (tmp3, tmp2, GEN_INT (1)));
7348 : :
7349 : 1 : rtx tmp4 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp1));
7350 : 1 : rtx tmp5 = gen_reg_rtx (V2DImode);
7351 : 1 : emit_insn (gen_ashlv2di3 (tmp5, tmp4, GEN_INT (63)));
7352 : :
7353 : 1 : rtx tmp6 = gen_reg_rtx (V2DImode);
7354 : 1 : emit_insn (gen_iorv2di3 (tmp6, tmp3, tmp5));
7355 : :
7356 : 1 : rtx tmp7 = gen_reg_rtx (V2DImode);
7357 : 1 : emit_insn (gen_lshrv2di3 (tmp7, tmp2, GEN_INT (63)));
7358 : :
7359 : 1 : rtx tmp8 = force_reg (V4SImode, gen_lowpart (V4SImode, tmp7));
7360 : 1 : rtx tmp9 = gen_reg_rtx (V4SImode);
7361 : 1 : emit_insn (gen_sse2_pshufd (tmp9, tmp8, GEN_INT (0xbf)));
7362 : :
7363 : 1 : rtx tmp10 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp9));
7364 : 1 : rtx tmp11 = gen_reg_rtx (V2DImode);
7365 : 1 : emit_insn (gen_ashlv2di3 (tmp11, tmp10, GEN_INT (31)));
7366 : :
7367 : 1 : rtx tmp12 = gen_reg_rtx (V2DImode);
7368 : 1 : emit_insn (gen_iorv2di3 (tmp12, tmp6, tmp11));
7369 : :
7370 : 1 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp12));
7371 : 1 : return;
7372 : : }
7373 : :
7374 : 37 : if (bits > 64)
7375 : : {
7376 : : /* Eight operations. */
7377 : 12 : rtx tmp1 = force_reg (V4SImode, gen_lowpart (V4SImode, op1));
7378 : 12 : rtx tmp2 = gen_reg_rtx (V4SImode);
7379 : 12 : emit_insn (gen_sse2_pshufd (tmp2, tmp1, GEN_INT (0xff)));
7380 : :
7381 : 12 : rtx tmp3 = gen_reg_rtx (V4SImode);
7382 : 12 : emit_insn (gen_ashrv4si3 (tmp3, tmp2, GEN_INT (31)));
7383 : :
7384 : 12 : rtx tmp4 = gen_reg_rtx (V1TImode);
7385 : 12 : emit_insn (gen_sse2_lshrv1ti3 (tmp4, op1, GEN_INT (64)));
7386 : :
7387 : 12 : rtx tmp5 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp4));
7388 : 12 : rtx tmp6 = gen_reg_rtx (V2DImode);
7389 : 12 : emit_insn (gen_lshrv2di3 (tmp6, tmp5, GEN_INT (bits - 64)));
7390 : :
7391 : 12 : rtx tmp7 = force_reg (V1TImode, gen_lowpart (V1TImode, tmp3));
7392 : 12 : rtx tmp8 = gen_reg_rtx (V1TImode);
7393 : 12 : emit_insn (gen_sse2_ashlv1ti3 (tmp8, tmp7, GEN_INT (64)));
7394 : :
7395 : 12 : rtx tmp9 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp3));
7396 : 12 : rtx tmp10 = gen_reg_rtx (V2DImode);
7397 : 12 : emit_insn (gen_ashlv2di3 (tmp10, tmp9, GEN_INT (128 - bits)));
7398 : :
7399 : 12 : rtx tmp11 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp8));
7400 : 12 : rtx tmp12 = gen_reg_rtx (V2DImode);
7401 : 12 : emit_insn (gen_iorv2di3 (tmp12, tmp10, tmp11));
7402 : :
7403 : 12 : rtx tmp13 = gen_reg_rtx (V2DImode);
7404 : 12 : emit_insn (gen_iorv2di3 (tmp13, tmp6, tmp12));
7405 : :
7406 : 12 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp13));
7407 : : }
7408 : : else
7409 : : {
7410 : : /* Nine operations. */
7411 : 25 : rtx tmp1 = force_reg (V4SImode, gen_lowpart (V4SImode, op1));
7412 : 25 : rtx tmp2 = gen_reg_rtx (V4SImode);
7413 : 25 : emit_insn (gen_sse2_pshufd (tmp2, tmp1, GEN_INT (0xff)));
7414 : :
7415 : 25 : rtx tmp3 = gen_reg_rtx (V4SImode);
7416 : 25 : emit_insn (gen_ashrv4si3 (tmp3, tmp2, GEN_INT (31)));
7417 : :
7418 : 25 : rtx tmp4 = gen_reg_rtx (V1TImode);
7419 : 25 : emit_insn (gen_sse2_lshrv1ti3 (tmp4, op1, GEN_INT (64)));
7420 : :
7421 : 25 : rtx tmp5 = force_reg (V2DImode, gen_lowpart (V2DImode, op1));
7422 : 25 : rtx tmp6 = gen_reg_rtx (V2DImode);
7423 : 25 : emit_insn (gen_lshrv2di3 (tmp6, tmp5, GEN_INT (bits)));
7424 : :
7425 : 25 : rtx tmp7 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp4));
7426 : 25 : rtx tmp8 = gen_reg_rtx (V2DImode);
7427 : 25 : emit_insn (gen_ashlv2di3 (tmp8, tmp7, GEN_INT (64 - bits)));
7428 : :
7429 : 25 : rtx tmp9 = gen_reg_rtx (V2DImode);
7430 : 25 : emit_insn (gen_iorv2di3 (tmp9, tmp6, tmp8));
7431 : :
7432 : 25 : rtx tmp10 = force_reg (V1TImode, gen_lowpart (V1TImode, tmp3));
7433 : 25 : rtx tmp11 = gen_reg_rtx (V1TImode);
7434 : 25 : emit_insn (gen_sse2_ashlv1ti3 (tmp11, tmp10, GEN_INT (64)));
7435 : :
7436 : 25 : rtx tmp12 = force_reg (V2DImode, gen_lowpart (V2DImode, tmp11));
7437 : 25 : rtx tmp13 = gen_reg_rtx (V2DImode);
7438 : 25 : emit_insn (gen_ashlv2di3 (tmp13, tmp12, GEN_INT (64 - bits)));
7439 : :
7440 : 25 : rtx tmp14 = gen_reg_rtx (V2DImode);
7441 : 25 : emit_insn (gen_iorv2di3 (tmp14, tmp9, tmp13));
7442 : :
7443 : 25 : emit_move_insn (operands[0], gen_lowpart (V1TImode, tmp14));
7444 : : }
7445 : : }
7446 : :
7447 : : /* Replace all occurrences of REG FROM with REG TO in X, including
7448 : : occurrences with different modes. */
7449 : :
7450 : : rtx
7451 : 46698 : ix86_replace_reg_with_reg (rtx x, rtx from, rtx to)
7452 : : {
7453 : 46698 : gcc_checking_assert (REG_P (from)
7454 : : && REG_P (to)
7455 : : && GET_MODE (from) == GET_MODE (to));
7456 : 46698 : if (!reg_overlap_mentioned_p (from, x))
7457 : : return x;
7458 : 138 : rtx ret = copy_rtx (x);
7459 : 138 : subrtx_ptr_iterator::array_type array;
7460 : 672 : FOR_EACH_SUBRTX_PTR (iter, array, &ret, NONCONST)
7461 : : {
7462 : 534 : rtx *loc = *iter;
7463 : 534 : x = *loc;
7464 : 534 : if (REG_P (x) && REGNO (x) == REGNO (from))
7465 : : {
7466 : 138 : if (x == from)
7467 : 138 : *loc = to;
7468 : : else
7469 : : {
7470 : 0 : gcc_checking_assert (REG_NREGS (x) == 1);
7471 : 0 : *loc = gen_rtx_REG (GET_MODE (x), REGNO (to));
7472 : : }
7473 : : }
7474 : : }
7475 : 138 : return ret;
7476 : 138 : }
7477 : :
7478 : : /* Return mode for the memcpy/memset loop counter. Prefer SImode over
7479 : : DImode for constant loop counts. */
7480 : :
7481 : : static machine_mode
7482 : 16667 : counter_mode (rtx count_exp)
7483 : : {
7484 : 16559 : if (GET_MODE (count_exp) != VOIDmode)
7485 : 14879 : return GET_MODE (count_exp);
7486 : 1788 : if (!CONST_INT_P (count_exp))
7487 : 0 : return Pmode;
7488 : : if (TARGET_64BIT && (INTVAL (count_exp) & ~0xffffffff))
7489 : : return DImode;
7490 : : return SImode;
7491 : : }
7492 : :
7493 : : /* When ISSETMEM is FALSE, output simple loop to move memory pointer to SRCPTR
7494 : : to DESTPTR via chunks of MODE unrolled UNROLL times, overall size is COUNT
7495 : : specified in bytes. When ISSETMEM is TRUE, output the equivalent loop to set
7496 : : memory by VALUE (supposed to be in MODE).
7497 : :
7498 : : The size is rounded down to whole number of chunk size moved at once.
7499 : : SRCMEM and DESTMEM provide MEMrtx to feed proper aliasing info. */
7500 : :
7501 : :
7502 : : static void
7503 : 8365 : expand_set_or_cpymem_via_loop (rtx destmem, rtx srcmem,
7504 : : rtx destptr, rtx srcptr, rtx value,
7505 : : rtx count, machine_mode mode, int unroll,
7506 : : int expected_size, bool issetmem)
7507 : : {
7508 : 8365 : rtx_code_label *out_label, *top_label;
7509 : 8365 : rtx iter, tmp;
7510 : 8365 : machine_mode iter_mode = counter_mode (count);
7511 : 8365 : int piece_size_n = GET_MODE_SIZE (mode) * unroll;
7512 : 8365 : rtx piece_size = GEN_INT (piece_size_n);
7513 : 16730 : rtx piece_size_mask = GEN_INT (~((GET_MODE_SIZE (mode) * unroll) - 1));
7514 : 8365 : rtx size;
7515 : 8365 : int i;
7516 : :
7517 : 8365 : top_label = gen_label_rtx ();
7518 : 8365 : out_label = gen_label_rtx ();
7519 : 8365 : iter = gen_reg_rtx (iter_mode);
7520 : :
7521 : 8365 : size = expand_simple_binop (iter_mode, AND, count, piece_size_mask,
7522 : : NULL, 1, OPTAB_DIRECT);
7523 : : /* Those two should combine. */
7524 : 8365 : if (piece_size == const1_rtx)
7525 : : {
7526 : 1795 : emit_cmp_and_jump_insns (size, const0_rtx, EQ, NULL_RTX, iter_mode,
7527 : : true, out_label);
7528 : 1795 : predict_jump (REG_BR_PROB_BASE * 10 / 100);
7529 : : }
7530 : 8365 : emit_move_insn (iter, const0_rtx);
7531 : :
7532 : 8365 : emit_label (top_label);
7533 : :
7534 : 8365 : tmp = convert_modes (Pmode, iter_mode, iter, true);
7535 : :
7536 : : /* This assert could be relaxed - in this case we'll need to compute
7537 : : smallest power of two, containing in PIECE_SIZE_N and pass it to
7538 : : offset_address. */
7539 : 8365 : gcc_assert ((piece_size_n & (piece_size_n - 1)) == 0);
7540 : 8365 : destmem = offset_address (destmem, tmp, piece_size_n);
7541 : 8365 : destmem = adjust_address (destmem, mode, 0);
7542 : :
7543 : 8365 : if (!issetmem)
7544 : : {
7545 : 7382 : srcmem = offset_address (srcmem, copy_rtx (tmp), piece_size_n);
7546 : 7382 : srcmem = adjust_address (srcmem, mode, 0);
7547 : :
7548 : : /* When unrolling for chips that reorder memory reads and writes,
7549 : : we can save registers by using single temporary.
7550 : : Also using 4 temporaries is overkill in 32bit mode. */
7551 : 7382 : if (!TARGET_64BIT && 0)
7552 : : {
7553 : : for (i = 0; i < unroll; i++)
7554 : : {
7555 : : if (i)
7556 : : {
7557 : : destmem = adjust_address (copy_rtx (destmem), mode,
7558 : : GET_MODE_SIZE (mode));
7559 : : srcmem = adjust_address (copy_rtx (srcmem), mode,
7560 : : GET_MODE_SIZE (mode));
7561 : : }
7562 : : emit_move_insn (destmem, srcmem);
7563 : : }
7564 : : }
7565 : : else
7566 : : {
7567 : 7382 : rtx tmpreg[4];
7568 : 7382 : gcc_assert (unroll <= 4);
7569 : 14785 : for (i = 0; i < unroll; i++)
7570 : : {
7571 : 7403 : tmpreg[i] = gen_reg_rtx (mode);
7572 : 7403 : if (i)
7573 : 42 : srcmem = adjust_address (copy_rtx (srcmem), mode,
7574 : : GET_MODE_SIZE (mode));
7575 : 7403 : emit_move_insn (tmpreg[i], srcmem);
7576 : : }
7577 : 14785 : for (i = 0; i < unroll; i++)
7578 : : {
7579 : 7403 : if (i)
7580 : 42 : destmem = adjust_address (copy_rtx (destmem), mode,
7581 : : GET_MODE_SIZE (mode));
7582 : 7403 : emit_move_insn (destmem, tmpreg[i]);
7583 : : }
7584 : : }
7585 : : }
7586 : : else
7587 : 1981 : for (i = 0; i < unroll; i++)
7588 : : {
7589 : 998 : if (i)
7590 : 30 : destmem = adjust_address (copy_rtx (destmem), mode,
7591 : : GET_MODE_SIZE (mode));
7592 : 998 : emit_move_insn (destmem, value);
7593 : : }
7594 : :
7595 : 8365 : tmp = expand_simple_binop (iter_mode, PLUS, iter, piece_size, iter,
7596 : : true, OPTAB_LIB_WIDEN);
7597 : 8365 : if (tmp != iter)
7598 : 0 : emit_move_insn (iter, tmp);
7599 : :
7600 : 8365 : emit_cmp_and_jump_insns (iter, size, LT, NULL_RTX, iter_mode,
7601 : : true, top_label);
7602 : 8365 : if (expected_size != -1)
7603 : : {
7604 : 191 : expected_size /= GET_MODE_SIZE (mode) * unroll;
7605 : 191 : if (expected_size == 0)
7606 : 1 : predict_jump (0);
7607 : 190 : else if (expected_size > REG_BR_PROB_BASE)
7608 : 0 : predict_jump (REG_BR_PROB_BASE - 1);
7609 : : else
7610 : 190 : predict_jump (REG_BR_PROB_BASE - (REG_BR_PROB_BASE + expected_size / 2)
7611 : 190 : / expected_size);
7612 : : }
7613 : : else
7614 : 8174 : predict_jump (REG_BR_PROB_BASE * 80 / 100);
7615 : 8365 : iter = ix86_zero_extend_to_Pmode (iter);
7616 : 8365 : tmp = expand_simple_binop (Pmode, PLUS, destptr, iter, destptr,
7617 : : true, OPTAB_LIB_WIDEN);
7618 : 8365 : if (tmp != destptr)
7619 : 0 : emit_move_insn (destptr, tmp);
7620 : 8365 : if (!issetmem)
7621 : : {
7622 : 7382 : tmp = expand_simple_binop (Pmode, PLUS, srcptr, iter, srcptr,
7623 : : true, OPTAB_LIB_WIDEN);
7624 : 7382 : if (tmp != srcptr)
7625 : 0 : emit_move_insn (srcptr, tmp);
7626 : : }
7627 : 8365 : emit_label (out_label);
7628 : 8365 : }
7629 : :
7630 : : /* Divide COUNTREG by SCALE. */
7631 : : static rtx
7632 : 44227 : scale_counter (rtx countreg, int scale)
7633 : : {
7634 : 44227 : rtx sc;
7635 : :
7636 : 44227 : if (scale == 1)
7637 : : return countreg;
7638 : 40109 : if (CONST_INT_P (countreg))
7639 : 36763 : return GEN_INT (INTVAL (countreg) / scale);
7640 : 3346 : gcc_assert (REG_P (countreg));
7641 : :
7642 : 10038 : sc = expand_simple_binop (GET_MODE (countreg), LSHIFTRT, countreg,
7643 : 6692 : GEN_INT (exact_log2 (scale)),
7644 : : NULL, 1, OPTAB_DIRECT);
7645 : 3346 : return sc;
7646 : : }
7647 : :
7648 : : /* Output "rep; mov" or "rep; stos" instruction depending on ISSETMEM argument.
7649 : : When ISSETMEM is true, arguments SRCMEM and SRCPTR are ignored.
7650 : : When ISSETMEM is false, arguments VALUE and ORIG_VALUE are ignored.
7651 : : For setmem case, VALUE is a promoted to a wider size ORIG_VALUE.
7652 : : ORIG_VALUE is the original value passed to memset to fill the memory with.
7653 : : Other arguments have same meaning as for previous function. */
7654 : :
7655 : : static void
7656 : 44227 : expand_set_or_cpymem_via_rep (rtx destmem, rtx srcmem,
7657 : : rtx destptr, rtx srcptr, rtx value, rtx orig_value,
7658 : : rtx count,
7659 : : machine_mode mode, bool issetmem)
7660 : : {
7661 : 44227 : rtx destexp;
7662 : 44227 : rtx srcexp;
7663 : 44227 : rtx countreg;
7664 : 44227 : HOST_WIDE_INT rounded_count;
7665 : :
7666 : : /* If possible, it is shorter to use rep movs.
7667 : : TODO: Maybe it is better to move this logic to decide_alg. */
7668 : 44227 : if (mode == QImode && CONST_INT_P (count) && !(INTVAL (count) & 3)
7669 : 243 : && !TARGET_PREFER_KNOWN_REP_MOVSB_STOSB
7670 : 239 : && (!issetmem || orig_value == const0_rtx))
7671 : 44227 : mode = SImode;
7672 : :
7673 : 44227 : if (destptr != XEXP (destmem, 0) || GET_MODE (destmem) != BLKmode)
7674 : 41631 : destmem = adjust_automodify_address_nv (destmem, BLKmode, destptr, 0);
7675 : :
7676 : 88454 : countreg = ix86_zero_extend_to_Pmode (scale_counter (count,
7677 : 44227 : GET_MODE_SIZE (mode)));
7678 : 44227 : if (mode != QImode)
7679 : : {
7680 : 80218 : destexp = gen_rtx_ASHIFT (Pmode, countreg,
7681 : : GEN_INT (exact_log2 (GET_MODE_SIZE (mode))));
7682 : 40109 : destexp = gen_rtx_PLUS (Pmode, destexp, destptr);
7683 : : }
7684 : : else
7685 : 4118 : destexp = gen_rtx_PLUS (Pmode, destptr, countreg);
7686 : 44227 : if ((!issetmem || orig_value == const0_rtx) && CONST_INT_P (count))
7687 : : {
7688 : 37197 : rounded_count
7689 : 37197 : = ROUND_DOWN (INTVAL (count), (HOST_WIDE_INT) GET_MODE_SIZE (mode));
7690 : 37197 : destmem = shallow_copy_rtx (destmem);
7691 : 37197 : set_mem_size (destmem, rounded_count);
7692 : : }
7693 : 7030 : else if (MEM_SIZE_KNOWN_P (destmem))
7694 : 543 : clear_mem_size (destmem);
7695 : :
7696 : 44227 : if (issetmem)
7697 : : {
7698 : 19561 : value = force_reg (mode, gen_lowpart (mode, value));
7699 : 19561 : emit_insn (gen_rep_stos (destptr, countreg, destmem, value, destexp));
7700 : : }
7701 : : else
7702 : : {
7703 : 24666 : if (srcptr != XEXP (srcmem, 0) || GET_MODE (srcmem) != BLKmode)
7704 : 23664 : srcmem = adjust_automodify_address_nv (srcmem, BLKmode, srcptr, 0);
7705 : 24666 : if (mode != QImode)
7706 : : {
7707 : 43458 : srcexp = gen_rtx_ASHIFT (Pmode, countreg,
7708 : : GEN_INT (exact_log2 (GET_MODE_SIZE (mode))));
7709 : 21729 : srcexp = gen_rtx_PLUS (Pmode, srcexp, srcptr);
7710 : : }
7711 : : else
7712 : 2937 : srcexp = gen_rtx_PLUS (Pmode, srcptr, countreg);
7713 : 24666 : if (CONST_INT_P (count))
7714 : : {
7715 : 21097 : rounded_count
7716 : 21097 : = ROUND_DOWN (INTVAL (count), (HOST_WIDE_INT) GET_MODE_SIZE (mode));
7717 : 21097 : srcmem = shallow_copy_rtx (srcmem);
7718 : 21097 : set_mem_size (srcmem, rounded_count);
7719 : : }
7720 : : else
7721 : : {
7722 : 3569 : if (MEM_SIZE_KNOWN_P (srcmem))
7723 : 0 : clear_mem_size (srcmem);
7724 : : }
7725 : 24666 : emit_insn (gen_rep_mov (destptr, destmem, srcptr, srcmem, countreg,
7726 : : destexp, srcexp));
7727 : : }
7728 : 44227 : }
7729 : :
7730 : : /* This function emits moves to copy SIZE_TO_MOVE bytes from SRCMEM to
7731 : : DESTMEM.
7732 : : SRC is passed by pointer to be updated on return.
7733 : : Return value is updated DST. */
7734 : : static rtx
7735 : 3701 : emit_memmov (rtx destmem, rtx *srcmem, rtx destptr, rtx srcptr,
7736 : : HOST_WIDE_INT size_to_move)
7737 : : {
7738 : 3701 : rtx dst = destmem, src = *srcmem, tempreg;
7739 : 3701 : enum insn_code code;
7740 : 3701 : machine_mode move_mode;
7741 : 3701 : int piece_size, i;
7742 : :
7743 : : /* Find the widest mode in which we could perform moves.
7744 : : Start with the biggest power of 2 less than SIZE_TO_MOVE and half
7745 : : it until move of such size is supported. */
7746 : 3701 : piece_size = 1 << floor_log2 (size_to_move);
7747 : 7402 : while (!int_mode_for_size (piece_size * BITS_PER_UNIT, 0).exists (&move_mode)
7748 : 7402 : || (code = optab_handler (mov_optab, move_mode)) == CODE_FOR_nothing)
7749 : : {
7750 : 0 : gcc_assert (piece_size > 1);
7751 : 0 : piece_size >>= 1;
7752 : : }
7753 : :
7754 : : /* Find the corresponding vector mode with the same size as MOVE_MODE.
7755 : : MOVE_MODE is an integer mode at the moment (SI, DI, TI, etc.). */
7756 : 11103 : if (GET_MODE_SIZE (move_mode) > GET_MODE_SIZE (word_mode))
7757 : : {
7758 : 0 : int nunits = GET_MODE_SIZE (move_mode) / GET_MODE_SIZE (word_mode);
7759 : 0 : if (!mode_for_vector (word_mode, nunits).exists (&move_mode)
7760 : 0 : || (code = optab_handler (mov_optab, move_mode)) == CODE_FOR_nothing)
7761 : : {
7762 : 0 : move_mode = word_mode;
7763 : 0 : piece_size = GET_MODE_SIZE (move_mode);
7764 : 0 : code = optab_handler (mov_optab, move_mode);
7765 : : }
7766 : : }
7767 : 3701 : gcc_assert (code != CODE_FOR_nothing);
7768 : :
7769 : 3701 : dst = adjust_automodify_address_nv (dst, move_mode, destptr, 0);
7770 : 3701 : src = adjust_automodify_address_nv (src, move_mode, srcptr, 0);
7771 : :
7772 : : /* Emit moves. We'll need SIZE_TO_MOVE/PIECE_SIZES moves. */
7773 : 3701 : gcc_assert (size_to_move % piece_size == 0);
7774 : :
7775 : 7402 : for (i = 0; i < size_to_move; i += piece_size)
7776 : : {
7777 : : /* We move from memory to memory, so we'll need to do it via
7778 : : a temporary register. */
7779 : 3701 : tempreg = gen_reg_rtx (move_mode);
7780 : 3701 : emit_insn (GEN_FCN (code) (tempreg, src));
7781 : 3701 : emit_insn (GEN_FCN (code) (dst, tempreg));
7782 : :
7783 : 7402 : emit_move_insn (destptr,
7784 : 3701 : plus_constant (Pmode, copy_rtx (destptr), piece_size));
7785 : 7402 : emit_move_insn (srcptr,
7786 : 3701 : plus_constant (Pmode, copy_rtx (srcptr), piece_size));
7787 : :
7788 : 3701 : dst = adjust_automodify_address_nv (dst, move_mode, destptr,
7789 : : piece_size);
7790 : 3701 : src = adjust_automodify_address_nv (src, move_mode, srcptr,
7791 : : piece_size);
7792 : : }
7793 : :
7794 : : /* Update DST and SRC rtx. */
7795 : 3701 : *srcmem = src;
7796 : 3701 : return dst;
7797 : : }
7798 : :
7799 : : /* Helper function for the string operations below. Dest VARIABLE whether
7800 : : it is aligned to VALUE bytes. If true, jump to the label. */
7801 : :
7802 : : static rtx_code_label *
7803 : 17263 : ix86_expand_aligntest (rtx variable, int value, bool epilogue)
7804 : : {
7805 : 17263 : rtx_code_label *label = gen_label_rtx ();
7806 : 17263 : rtx tmpcount = gen_reg_rtx (GET_MODE (variable));
7807 : 17263 : if (GET_MODE (variable) == DImode)
7808 : 408 : emit_insn (gen_anddi3 (tmpcount, variable, GEN_INT (value)));
7809 : : else
7810 : 16855 : emit_insn (gen_andsi3 (tmpcount, variable, GEN_INT (value)));
7811 : 17263 : emit_cmp_and_jump_insns (tmpcount, const0_rtx, EQ, 0, GET_MODE (variable),
7812 : : 1, label);
7813 : 17263 : if (epilogue)
7814 : 8224 : predict_jump (REG_BR_PROB_BASE * 50 / 100);
7815 : : else
7816 : 9039 : predict_jump (REG_BR_PROB_BASE * 90 / 100);
7817 : 17263 : return label;
7818 : : }
7819 : :
7820 : :
7821 : : /* Output code to copy at most count & (max_size - 1) bytes from SRC to DEST. */
7822 : :
7823 : : static void
7824 : 22736 : expand_cpymem_epilogue (rtx destmem, rtx srcmem,
7825 : : rtx destptr, rtx srcptr, rtx count, int max_size)
7826 : : {
7827 : 22736 : rtx src, dest;
7828 : 22736 : if (CONST_INT_P (count))
7829 : : {
7830 : 20675 : HOST_WIDE_INT countval = INTVAL (count);
7831 : 20675 : HOST_WIDE_INT epilogue_size = countval % max_size;
7832 : 20675 : int i;
7833 : :
7834 : : /* For now MAX_SIZE should be a power of 2. This assert could be
7835 : : relaxed, but it'll require a bit more complicated epilogue
7836 : : expanding. */
7837 : 20675 : gcc_assert ((max_size & (max_size - 1)) == 0);
7838 : 97161 : for (i = max_size; i >= 1; i >>= 1)
7839 : : {
7840 : 76486 : if (epilogue_size & i)
7841 : 3685 : destmem = emit_memmov (destmem, &srcmem, destptr, srcptr, i);
7842 : : }
7843 : : return;
7844 : : }
7845 : 2061 : if (max_size > 8)
7846 : : {
7847 : 4 : count = expand_simple_binop (GET_MODE (count), AND, count, GEN_INT (max_size - 1),
7848 : : count, 1, OPTAB_DIRECT);
7849 : 4 : expand_set_or_cpymem_via_loop (destmem, srcmem, destptr, srcptr, NULL,
7850 : : count, QImode, 1, 4, false);
7851 : 4 : return;
7852 : : }
7853 : :
7854 : : /* When there are stringops, we can cheaply increase dest and src pointers.
7855 : : Otherwise we save code size by maintaining offset (zero is readily
7856 : : available from preceding rep operation) and using x86 addressing modes.
7857 : : */
7858 : 2057 : if (TARGET_SINGLE_STRINGOP)
7859 : : {
7860 : 0 : if (max_size > 4)
7861 : : {
7862 : 0 : rtx_code_label *label = ix86_expand_aligntest (count, 4, true);
7863 : 0 : src = change_address (srcmem, SImode, srcptr);
7864 : 0 : dest = change_address (destmem, SImode, destptr);
7865 : 0 : emit_insn (gen_strmov (destptr, dest, srcptr, src));
7866 : 0 : emit_label (label);
7867 : 0 : LABEL_NUSES (label) = 1;
7868 : : }
7869 : 0 : if (max_size > 2)
7870 : : {
7871 : 0 : rtx_code_label *label = ix86_expand_aligntest (count, 2, true);
7872 : 0 : src = change_address (srcmem, HImode, srcptr);
7873 : 0 : dest = change_address (destmem, HImode, destptr);
7874 : 0 : emit_insn (gen_strmov (destptr, dest, srcptr, src));
7875 : 0 : emit_label (label);
7876 : 0 : LABEL_NUSES (label) = 1;
7877 : : }
7878 : 0 : if (max_size > 1)
7879 : : {
7880 : 0 : rtx_code_label *label = ix86_expand_aligntest (count, 1, true);
7881 : 0 : src = change_address (srcmem, QImode, srcptr);
7882 : 0 : dest = change_address (destmem, QImode, destptr);
7883 : 0 : emit_insn (gen_strmov (destptr, dest, srcptr, src));
7884 : 0 : emit_label (label);
7885 : 0 : LABEL_NUSES (label) = 1;
7886 : : }
7887 : : }
7888 : : else
7889 : : {
7890 : 2057 : rtx offset = force_reg (Pmode, const0_rtx);
7891 : 2057 : rtx tmp;
7892 : :
7893 : 2057 : if (max_size > 4)
7894 : : {
7895 : 2000 : rtx_code_label *label = ix86_expand_aligntest (count, 4, true);
7896 : 2000 : src = change_address (srcmem, SImode, srcptr);
7897 : 2000 : dest = change_address (destmem, SImode, destptr);
7898 : 2000 : emit_move_insn (dest, src);
7899 : 2000 : tmp = expand_simple_binop (Pmode, PLUS, offset, GEN_INT (4), NULL,
7900 : : true, OPTAB_LIB_WIDEN);
7901 : 2000 : if (tmp != offset)
7902 : 2000 : emit_move_insn (offset, tmp);
7903 : 2000 : emit_label (label);
7904 : 2000 : LABEL_NUSES (label) = 1;
7905 : : }
7906 : 2057 : if (max_size > 2)
7907 : : {
7908 : 2057 : rtx_code_label *label = ix86_expand_aligntest (count, 2, true);
7909 : 2057 : tmp = gen_rtx_PLUS (Pmode, srcptr, offset);
7910 : 2057 : src = change_address (srcmem, HImode, tmp);
7911 : 2057 : tmp = gen_rtx_PLUS (Pmode, destptr, offset);
7912 : 2057 : dest = change_address (destmem, HImode, tmp);
7913 : 2057 : emit_move_insn (dest, src);
7914 : 2057 : tmp = expand_simple_binop (Pmode, PLUS, offset, GEN_INT (2), tmp,
7915 : : true, OPTAB_LIB_WIDEN);
7916 : 2057 : if (tmp != offset)
7917 : 2057 : emit_move_insn (offset, tmp);
7918 : 2057 : emit_label (label);
7919 : 2057 : LABEL_NUSES (label) = 1;
7920 : : }
7921 : 2057 : if (max_size > 1)
7922 : : {
7923 : 2057 : rtx_code_label *label = ix86_expand_aligntest (count, 1, true);
7924 : 2057 : tmp = gen_rtx_PLUS (Pmode, srcptr, offset);
7925 : 2057 : src = change_address (srcmem, QImode, tmp);
7926 : 2057 : tmp = gen_rtx_PLUS (Pmode, destptr, offset);
7927 : 2057 : dest = change_address (destmem, QImode, tmp);
7928 : 2057 : emit_move_insn (dest, src);
7929 : 2057 : emit_label (label);
7930 : 2057 : LABEL_NUSES (label) = 1;
7931 : : }
7932 : : }
7933 : : }
7934 : :
7935 : : /* This function emits moves to fill SIZE_TO_MOVE bytes starting from DESTMEM
7936 : : with value PROMOTED_VAL.
7937 : : SRC is passed by pointer to be updated on return.
7938 : : Return value is updated DST. */
7939 : : static rtx
7940 : 4858 : emit_memset (rtx destmem, rtx destptr, rtx promoted_val,
7941 : : HOST_WIDE_INT size_to_move)
7942 : : {
7943 : 4858 : rtx dst = destmem;
7944 : 4858 : enum insn_code code;
7945 : 4858 : machine_mode move_mode;
7946 : 4858 : int piece_size, i;
7947 : :
7948 : : /* Find the widest mode in which we could perform moves.
7949 : : Start with the biggest power of 2 less than SIZE_TO_MOVE and half
7950 : : it until move of such size is supported. */
7951 : 4858 : move_mode = GET_MODE (promoted_val);
7952 : 4858 : if (move_mode == VOIDmode)
7953 : 0 : move_mode = QImode;
7954 : 9716 : if (size_to_move < GET_MODE_SIZE (move_mode))
7955 : : {
7956 : 4856 : unsigned int move_bits = size_to_move * BITS_PER_UNIT;
7957 : 4856 : move_mode = int_mode_for_size (move_bits, 0).require ();
7958 : 4856 : promoted_val = gen_lowpart (move_mode, promoted_val);
7959 : : }
7960 : 4858 : piece_size = GET_MODE_SIZE (move_mode);
7961 : 4858 : code = optab_handler (mov_optab, move_mode);
7962 : 4858 : gcc_assert (code != CODE_FOR_nothing && promoted_val != NULL_RTX);
7963 : :
7964 : 4858 : dst = adjust_automodify_address_nv (dst, move_mode, destptr, 0);
7965 : :
7966 : : /* Emit moves. We'll need SIZE_TO_MOVE/PIECE_SIZES moves. */
7967 : 4858 : gcc_assert (size_to_move % piece_size == 0);
7968 : :
7969 : 9717 : for (i = 0; i < size_to_move; i += piece_size)
7970 : : {
7971 : 9718 : if (piece_size <= GET_MODE_SIZE (word_mode))
7972 : : {
7973 : 4857 : emit_insn (gen_strset (destptr, dst, promoted_val));
7974 : 4857 : dst = adjust_automodify_address_nv (dst, move_mode, destptr,
7975 : : piece_size);
7976 : 4857 : continue;
7977 : : }
7978 : :
7979 : 2 : emit_insn (GEN_FCN (code) (dst, promoted_val));
7980 : :
7981 : 4 : emit_move_insn (destptr,
7982 : 2 : plus_constant (Pmode, copy_rtx (destptr), piece_size));
7983 : :
7984 : 2 : dst = adjust_automodify_address_nv (dst, move_mode, destptr,
7985 : : piece_size);
7986 : : }
7987 : :
7988 : : /* Update DST rtx. */
7989 : 4858 : return dst;
7990 : : }
7991 : : /* Output code to set at most count & (max_size - 1) bytes starting by DEST. */
7992 : : static void
7993 : 108 : expand_setmem_epilogue_via_loop (rtx destmem, rtx destptr, rtx value,
7994 : : rtx count, int max_size)
7995 : : {
7996 : 216 : count = expand_simple_binop (counter_mode (count), AND, count,
7997 : 108 : GEN_INT (max_size - 1), count, 1, OPTAB_DIRECT);
7998 : 108 : expand_set_or_cpymem_via_loop (destmem, NULL, destptr, NULL,
7999 : 108 : gen_lowpart (QImode, value), count, QImode,
8000 : : 1, max_size / 2, true);
8001 : 108 : }
8002 : :
8003 : : /* Output code to set at most count & (max_size - 1) bytes starting by DEST. */
8004 : : static void
8005 : 16913 : expand_setmem_epilogue (rtx destmem, rtx destptr, rtx value, rtx vec_value,
8006 : : rtx count, int max_size)
8007 : : {
8008 : 16913 : rtx dest;
8009 : :
8010 : 16913 : if (CONST_INT_P (count))
8011 : : {
8012 : 16153 : HOST_WIDE_INT countval = INTVAL (count);
8013 : 16153 : HOST_WIDE_INT epilogue_size = countval % max_size;
8014 : 16153 : int i;
8015 : :
8016 : : /* For now MAX_SIZE should be a power of 2. This assert could be
8017 : : relaxed, but it'll require a bit more complicated epilogue
8018 : : expanding. */
8019 : 16153 : gcc_assert ((max_size & (max_size - 1)) == 0);
8020 : 76546 : for (i = max_size; i >= 1; i >>= 1)
8021 : : {
8022 : 60393 : if (epilogue_size & i)
8023 : : {
8024 : 4852 : if (vec_value && i > GET_MODE_SIZE (GET_MODE (value)))
8025 : 0 : destmem = emit_memset (destmem, destptr, vec_value, i);
8026 : : else
8027 : 4852 : destmem = emit_memset (destmem, destptr, value, i);
8028 : : }
8029 : : }
8030 : : return;
8031 : : }
8032 : 760 : if (max_size > 32)
8033 : : {
8034 : 2 : expand_setmem_epilogue_via_loop (destmem, destptr, value, count, max_size);
8035 : 2 : return;
8036 : : }
8037 : 758 : if (max_size > 16)
8038 : : {
8039 : 0 : rtx_code_label *label = ix86_expand_aligntest (count, 16, true);
8040 : 0 : if (TARGET_64BIT)
8041 : : {
8042 : 0 : dest = change_address (destmem, DImode, destptr);
8043 : 0 : emit_insn (gen_strset (destptr, dest, value));
8044 : 0 : dest = adjust_automodify_address_nv (dest, DImode, destptr, 8);
8045 : 0 : emit_insn (gen_strset (destptr, dest, value));
8046 : : }
8047 : : else
8048 : : {
8049 : 0 : dest = change_address (destmem, SImode, destptr);
8050 : 0 : emit_insn (gen_strset (destptr, dest, value));
8051 : 0 : dest = adjust_automodify_address_nv (dest, SImode, destptr, 4);
8052 : 0 : emit_insn (gen_strset (destptr, dest, value));
8053 : 0 : dest = adjust_automodify_address_nv (dest, SImode, destptr, 8);
8054 : 0 : emit_insn (gen_strset (destptr, dest, value));
8055 : 0 : dest = adjust_automodify_address_nv (dest, SImode, destptr, 12);
8056 : 0 : emit_insn (gen_strset (destptr, dest, value));
8057 : : }
8058 : 0 : emit_label (label);
8059 : 0 : LABEL_NUSES (label) = 1;
8060 : : }
8061 : 758 : if (max_size > 8)
8062 : : {
8063 : 0 : rtx_code_label *label = ix86_expand_aligntest (count, 8, true);
8064 : 0 : if (TARGET_64BIT)
8065 : : {
8066 : 0 : dest = change_address (destmem, DImode, destptr);
8067 : 0 : emit_insn (gen_strset (destptr, dest, value));
8068 : : }
8069 : : else
8070 : : {
8071 : 0 : dest = change_address (destmem, SImode, destptr);
8072 : 0 : emit_insn (gen_strset (destptr, dest, value));
8073 : 0 : dest = adjust_automodify_address_nv (dest, SImode, destptr, 4);
8074 : 0 : emit_insn (gen_strset (destptr, dest, value));
8075 : : }
8076 : 0 : emit_label (label);
8077 : 0 : LABEL_NUSES (label) = 1;
8078 : : }
8079 : 758 : if (max_size > 4)
8080 : : {
8081 : 594 : rtx_code_label *label = ix86_expand_aligntest (count, 4, true);
8082 : 594 : dest = change_address (destmem, SImode, destptr);
8083 : 594 : emit_insn (gen_strset (destptr, dest, gen_lowpart (SImode, value)));
8084 : 594 : emit_label (label);
8085 : 594 : LABEL_NUSES (label) = 1;
8086 : : }
8087 : 758 : if (max_size > 2)
8088 : : {
8089 : 758 : rtx_code_label *label = ix86_expand_aligntest (count, 2, true);
8090 : 758 : dest = change_address (destmem, HImode, destptr);
8091 : 758 : emit_insn (gen_strset (destptr, dest, gen_lowpart (HImode, value)));
8092 : 758 : emit_label (label);
8093 : 758 : LABEL_NUSES (label) = 1;
8094 : : }
8095 : 758 : if (max_size > 1)
8096 : : {
8097 : 758 : rtx_code_label *label = ix86_expand_aligntest (count, 1, true);
8098 : 758 : dest = change_address (destmem, QImode, destptr);
8099 : 758 : emit_insn (gen_strset (destptr, dest, gen_lowpart (QImode, value)));
8100 : 758 : emit_label (label);
8101 : 758 : LABEL_NUSES (label) = 1;
8102 : : }
8103 : : }
8104 : :
8105 : : /* Adjust COUNTER by the VALUE. */
8106 : : static void
8107 : 16 : ix86_adjust_counter (rtx countreg, HOST_WIDE_INT value)
8108 : : {
8109 : 16 : emit_insn (gen_add2_insn (countreg, GEN_INT (-value)));
8110 : 16 : }
8111 : :
8112 : : /* Depending on ISSETMEM, copy enough from SRCMEM to DESTMEM or set enough to
8113 : : DESTMEM to align it to DESIRED_ALIGNMENT. Original alignment is ALIGN.
8114 : : Depending on ISSETMEM, either arguments SRCMEM/SRCPTR or VALUE/VEC_VALUE are
8115 : : ignored.
8116 : : Return value is updated DESTMEM. */
8117 : :
8118 : : static rtx
8119 : 6 : expand_set_or_cpymem_prologue (rtx destmem, rtx srcmem,
8120 : : rtx destptr, rtx srcptr, rtx value,
8121 : : rtx vec_value, rtx count, int align,
8122 : : int desired_alignment, bool issetmem)
8123 : : {
8124 : 6 : int i;
8125 : 31 : for (i = 1; i < desired_alignment; i <<= 1)
8126 : : {
8127 : 25 : if (align <= i)
8128 : : {
8129 : 16 : rtx_code_label *label = ix86_expand_aligntest (destptr, i, false);
8130 : 16 : if (issetmem)
8131 : : {
8132 : 12 : if (vec_value && i > GET_MODE_SIZE (GET_MODE (value)))
8133 : 2 : destmem = emit_memset (destmem, destptr, vec_value, i);
8134 : : else
8135 : 4 : destmem = emit_memset (destmem, destptr, value, i);
8136 : : }
8137 : : else
8138 : 10 : destmem = emit_memmov (destmem, &srcmem, destptr, srcptr, i);
8139 : 16 : ix86_adjust_counter (count, i);
8140 : 16 : emit_label (label);
8141 : 16 : LABEL_NUSES (label) = 1;
8142 : 16 : set_mem_align (destmem, i * 2 * BITS_PER_UNIT);
8143 : : }
8144 : : }
8145 : 6 : return destmem;
8146 : : }
8147 : :
8148 : : /* Test if COUNT&SIZE is nonzero and if so, expand movme
8149 : : or setmem sequence that is valid for SIZE..2*SIZE-1 bytes
8150 : : and jump to DONE_LABEL. */
8151 : : static void
8152 : 4381 : expand_small_cpymem_or_setmem (rtx destmem, rtx srcmem,
8153 : : rtx destptr, rtx srcptr,
8154 : : rtx value, rtx vec_value,
8155 : : rtx count, int size,
8156 : : rtx done_label, bool issetmem)
8157 : : {
8158 : 4381 : rtx_code_label *label = ix86_expand_aligntest (count, size, false);
8159 : 4381 : machine_mode mode = int_mode_for_size (size * BITS_PER_UNIT, 1).else_blk ();
8160 : 4381 : rtx modesize;
8161 : 4381 : int n;
8162 : :
8163 : : /* If we do not have vector value to copy, we must reduce size. */
8164 : 4381 : if (issetmem)
8165 : : {
8166 : 598 : if (!vec_value)
8167 : : {
8168 : 598 : if (GET_MODE (value) == VOIDmode && size > 8)
8169 : 0 : mode = Pmode;
8170 : 1794 : else if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (value)))
8171 : 1 : mode = GET_MODE (value);
8172 : : }
8173 : : else
8174 : 0 : mode = GET_MODE (vec_value), value = vec_value;
8175 : : }
8176 : : else
8177 : : {
8178 : : /* Choose appropriate vector mode. */
8179 : 3783 : if (size >= 32)
8180 : 0 : mode = TARGET_AVX ? V32QImode : TARGET_SSE ? V16QImode : DImode;
8181 : 3783 : else if (size >= 16)
8182 : 0 : mode = TARGET_SSE ? V16QImode : DImode;
8183 : 3783 : srcmem = change_address (srcmem, mode, srcptr);
8184 : : }
8185 : 4381 : destmem = change_address (destmem, mode, destptr);
8186 : 8762 : modesize = GEN_INT (GET_MODE_SIZE (mode));
8187 : 8762 : gcc_assert (GET_MODE_SIZE (mode) <= size);
8188 : 17526 : for (n = 0; n * GET_MODE_SIZE (mode) < size; n++)
8189 : : {
8190 : 4382 : if (issetmem)
8191 : 599 : emit_move_insn (destmem, gen_lowpart (mode, value));
8192 : : else
8193 : : {
8194 : 3783 : emit_move_insn (destmem, srcmem);
8195 : 7566 : srcmem = offset_address (srcmem, modesize, GET_MODE_SIZE (mode));
8196 : : }
8197 : 8764 : destmem = offset_address (destmem, modesize, GET_MODE_SIZE (mode));
8198 : : }
8199 : :
8200 : 4381 : destmem = offset_address (destmem, count, 1);
8201 : 8762 : destmem = offset_address (destmem, GEN_INT (-2 * size),
8202 : 4381 : GET_MODE_SIZE (mode));
8203 : 4381 : if (!issetmem)
8204 : : {
8205 : 3783 : srcmem = offset_address (srcmem, count, 1);
8206 : 7566 : srcmem = offset_address (srcmem, GEN_INT (-2 * size),
8207 : 3783 : GET_MODE_SIZE (mode));
8208 : : }
8209 : 17526 : for (n = 0; n * GET_MODE_SIZE (mode) < size; n++)
8210 : : {
8211 : 4382 : if (issetmem)
8212 : 599 : emit_move_insn (destmem, gen_lowpart (mode, value));
8213 : : else
8214 : : {
8215 : 3783 : emit_move_insn (destmem, srcmem);
8216 : 7566 : srcmem = offset_address (srcmem, modesize, GET_MODE_SIZE (mode));
8217 : : }
8218 : 8764 : destmem = offset_address (destmem, modesize, GET_MODE_SIZE (mode));
8219 : : }
8220 : 4381 : emit_jump_insn (gen_jump (done_label));
8221 : 4381 : emit_barrier ();
8222 : :
8223 : 4381 : emit_label (label);
8224 : 4381 : LABEL_NUSES (label) = 1;
8225 : 4381 : }
8226 : :
8227 : : /* Handle small memcpy (up to SIZE that is supposed to be small power of 2.
8228 : : and get ready for the main memcpy loop by copying iniital DESIRED_ALIGN-ALIGN
8229 : : bytes and last SIZE bytes adjusitng DESTPTR/SRCPTR/COUNT in a way we can
8230 : : proceed with an loop copying SIZE bytes at once. Do moves in MODE.
8231 : : DONE_LABEL is a label after the whole copying sequence. The label is created
8232 : : on demand if *DONE_LABEL is NULL.
8233 : : MIN_SIZE is minimal size of block copied. This value gets adjusted for new
8234 : : bounds after the initial copies.
8235 : :
8236 : : DESTMEM/SRCMEM are memory expressions pointing to the copies block,
8237 : : DESTPTR/SRCPTR are pointers to the block. DYNAMIC_CHECK indicate whether
8238 : : we will dispatch to a library call for large blocks.
8239 : :
8240 : : In pseudocode we do:
8241 : :
8242 : : if (COUNT < SIZE)
8243 : : {
8244 : : Assume that SIZE is 4. Bigger sizes are handled analogously
8245 : : if (COUNT & 4)
8246 : : {
8247 : : copy 4 bytes from SRCPTR to DESTPTR
8248 : : copy 4 bytes from SRCPTR + COUNT - 4 to DESTPTR + COUNT - 4
8249 : : goto done_label
8250 : : }
8251 : : if (!COUNT)
8252 : : goto done_label;
8253 : : copy 1 byte from SRCPTR to DESTPTR
8254 : : if (COUNT & 2)
8255 : : {
8256 : : copy 2 bytes from SRCPTR to DESTPTR
8257 : : copy 2 bytes from SRCPTR + COUNT - 2 to DESTPTR + COUNT - 2
8258 : : }
8259 : : }
8260 : : else
8261 : : {
8262 : : copy at least DESIRED_ALIGN-ALIGN bytes from SRCPTR to DESTPTR
8263 : : copy SIZE bytes from SRCPTR + COUNT - SIZE to DESTPTR + COUNT -SIZE
8264 : :
8265 : : OLD_DESPTR = DESTPTR;
8266 : : Align DESTPTR up to DESIRED_ALIGN
8267 : : SRCPTR += DESTPTR - OLD_DESTPTR
8268 : : COUNT -= DEST_PTR - OLD_DESTPTR
8269 : : if (DYNAMIC_CHECK)
8270 : : Round COUNT down to multiple of SIZE
8271 : : << optional caller supplied zero size guard is here >>
8272 : : << optional caller supplied dynamic check is here >>
8273 : : << caller supplied main copy loop is here >>
8274 : : }
8275 : : done_label:
8276 : : */
8277 : : static void
8278 : 7008 : expand_set_or_cpymem_prologue_epilogue_by_misaligned_moves (rtx destmem, rtx srcmem,
8279 : : rtx *destptr, rtx *srcptr,
8280 : : machine_mode mode,
8281 : : rtx value, rtx vec_value,
8282 : : rtx *count,
8283 : : rtx_code_label **done_label,
8284 : : int size,
8285 : : int desired_align,
8286 : : int align,
8287 : : unsigned HOST_WIDE_INT *min_size,
8288 : : bool dynamic_check,
8289 : : bool issetmem)
8290 : : {
8291 : 7008 : rtx_code_label *loop_label = NULL, *label;
8292 : 7008 : int n;
8293 : 7008 : rtx modesize;
8294 : 7008 : int prolog_size = 0;
8295 : 7008 : rtx mode_value;
8296 : :
8297 : : /* Chose proper value to copy. */
8298 : 7008 : if (issetmem && VECTOR_MODE_P (mode))
8299 : : mode_value = vec_value;
8300 : : else
8301 : 7008 : mode_value = value;
8302 : 14016 : gcc_assert (GET_MODE_SIZE (mode) <= size);
8303 : :
8304 : : /* See if block is big or small, handle small blocks. */
8305 : 7008 : if (!CONST_INT_P (*count) && *min_size < (unsigned HOST_WIDE_INT)size)
8306 : : {
8307 : 4642 : int size2 = size;
8308 : 4642 : loop_label = gen_label_rtx ();
8309 : :
8310 : 4642 : if (!*done_label)
8311 : 4642 : *done_label = gen_label_rtx ();
8312 : :
8313 : 4642 : emit_cmp_and_jump_insns (*count, GEN_INT (size2), GE, 0, GET_MODE (*count),
8314 : : 1, loop_label);
8315 : 4642 : size2 >>= 1;
8316 : :
8317 : : /* Handle sizes > 3. */
8318 : 9023 : for (;size2 > 2; size2 >>= 1)
8319 : 4381 : expand_small_cpymem_or_setmem (destmem, srcmem,
8320 : : *destptr, *srcptr,
8321 : : value, vec_value,
8322 : : *count,
8323 : : size2, *done_label, issetmem);
8324 : : /* Nothing to copy? Jump to DONE_LABEL if so */
8325 : 4642 : emit_cmp_and_jump_insns (*count, const0_rtx, EQ, 0, GET_MODE (*count),
8326 : : 1, *done_label);
8327 : :
8328 : : /* Do a byte copy. */
8329 : 4642 : destmem = change_address (destmem, QImode, *destptr);
8330 : 4642 : if (issetmem)
8331 : 685 : emit_move_insn (destmem, gen_lowpart (QImode, value));
8332 : : else
8333 : : {
8334 : 3957 : srcmem = change_address (srcmem, QImode, *srcptr);
8335 : 3957 : emit_move_insn (destmem, srcmem);
8336 : : }
8337 : :
8338 : : /* Handle sizes 2 and 3. */
8339 : 4642 : label = ix86_expand_aligntest (*count, 2, false);
8340 : 4642 : destmem = change_address (destmem, HImode, *destptr);
8341 : 4642 : destmem = offset_address (destmem, *count, 1);
8342 : 4642 : destmem = offset_address (destmem, GEN_INT (-2), 2);
8343 : 4642 : if (issetmem)
8344 : 685 : emit_move_insn (destmem, gen_lowpart (HImode, value));
8345 : : else
8346 : : {
8347 : 3957 : srcmem = change_address (srcmem, HImode, *srcptr);
8348 : 3957 : srcmem = offset_address (srcmem, *count, 1);
8349 : 3957 : srcmem = offset_address (srcmem, GEN_INT (-2), 2);
8350 : 3957 : emit_move_insn (destmem, srcmem);
8351 : : }
8352 : :
8353 : 4642 : emit_label (label);
8354 : 4642 : LABEL_NUSES (label) = 1;
8355 : 4642 : emit_jump_insn (gen_jump (*done_label));
8356 : 4642 : emit_barrier ();
8357 : 4642 : }
8358 : : else
8359 : 2366 : gcc_assert (*min_size >= (unsigned HOST_WIDE_INT)size
8360 : : || UINTVAL (*count) >= (unsigned HOST_WIDE_INT)size);
8361 : :
8362 : : /* Start memcpy for COUNT >= SIZE. */
8363 : 7008 : if (loop_label)
8364 : : {
8365 : 4642 : emit_label (loop_label);
8366 : 4642 : LABEL_NUSES (loop_label) = 1;
8367 : : }
8368 : :
8369 : : /* Copy first desired_align bytes. */
8370 : 7008 : if (!issetmem)
8371 : 4905 : srcmem = change_address (srcmem, mode, *srcptr);
8372 : 7008 : destmem = change_address (destmem, mode, *destptr);
8373 : 7008 : modesize = GEN_INT (GET_MODE_SIZE (mode));
8374 : 20285 : for (n = 0; prolog_size < desired_align - align; n++)
8375 : : {
8376 : 6269 : if (issetmem)
8377 : 1715 : emit_move_insn (destmem, mode_value);
8378 : : else
8379 : : {
8380 : 4554 : emit_move_insn (destmem, srcmem);
8381 : 9108 : srcmem = offset_address (srcmem, modesize, GET_MODE_SIZE (mode));
8382 : : }
8383 : 12538 : destmem = offset_address (destmem, modesize, GET_MODE_SIZE (mode));
8384 : 12538 : prolog_size += GET_MODE_SIZE (mode);
8385 : : }
8386 : :
8387 : :
8388 : : /* Copy last SIZE bytes. */
8389 : 7008 : destmem = offset_address (destmem, *count, 1);
8390 : 7008 : destmem = offset_address (destmem,
8391 : 7008 : GEN_INT (-size - prolog_size),
8392 : : 1);
8393 : 7008 : if (issetmem)
8394 : 2103 : emit_move_insn (destmem, mode_value);
8395 : : else
8396 : : {
8397 : 4905 : srcmem = offset_address (srcmem, *count, 1);
8398 : 4905 : srcmem = offset_address (srcmem,
8399 : : GEN_INT (-size - prolog_size),
8400 : : 1);
8401 : 4905 : emit_move_insn (destmem, srcmem);
8402 : : }
8403 : 14022 : for (n = 1; n * GET_MODE_SIZE (mode) < size; n++)
8404 : : {
8405 : 3 : destmem = offset_address (destmem, modesize, 1);
8406 : 3 : if (issetmem)
8407 : 3 : emit_move_insn (destmem, mode_value);
8408 : : else
8409 : : {
8410 : 0 : srcmem = offset_address (srcmem, modesize, 1);
8411 : 0 : emit_move_insn (destmem, srcmem);
8412 : : }
8413 : : }
8414 : :
8415 : : /* Align destination. */
8416 : 7008 : if (desired_align > 1 && desired_align > align)
8417 : : {
8418 : 6269 : rtx saveddest = *destptr;
8419 : :
8420 : 6269 : gcc_assert (desired_align <= size);
8421 : : /* Align destptr up, place it to new register. */
8422 : 6269 : *destptr = expand_simple_binop (GET_MODE (*destptr), PLUS, *destptr,
8423 : : GEN_INT (prolog_size),
8424 : : NULL_RTX, 1, OPTAB_DIRECT);
8425 : 6269 : if (REG_P (*destptr) && REG_P (saveddest) && REG_POINTER (saveddest))
8426 : 6269 : REG_POINTER (*destptr) = 1;
8427 : 6269 : *destptr = expand_simple_binop (GET_MODE (*destptr), AND, *destptr,
8428 : 6269 : GEN_INT (-desired_align),
8429 : : *destptr, 1, OPTAB_DIRECT);
8430 : : /* See how many bytes we skipped. */
8431 : 6269 : saveddest = expand_simple_binop (GET_MODE (*destptr), MINUS, saveddest,
8432 : : *destptr,
8433 : : NULL_RTX, 1, OPTAB_DIRECT);
8434 : : /* Adjust srcptr and count. */
8435 : 6269 : if (!issetmem)
8436 : 4554 : *srcptr = expand_simple_binop (GET_MODE (*srcptr), MINUS, *srcptr,
8437 : : saveddest, *srcptr, 1, OPTAB_DIRECT);
8438 : 6269 : *count = expand_simple_binop (GET_MODE (*count), PLUS, *count,
8439 : : saveddest, *count, 1, OPTAB_DIRECT);
8440 : : /* We copied at most size + prolog_size. */
8441 : 6269 : if (*min_size > (unsigned HOST_WIDE_INT)(size + prolog_size))
8442 : 1757 : *min_size
8443 : 1757 : = ROUND_DOWN (*min_size - size, (unsigned HOST_WIDE_INT)size);
8444 : : else
8445 : 4512 : *min_size = 0;
8446 : :
8447 : : /* Our loops always round down the block size, but for dispatch to
8448 : : library we need precise value. */
8449 : 6269 : if (dynamic_check)
8450 : 6269 : *count = expand_simple_binop (GET_MODE (*count), AND, *count,
8451 : : GEN_INT (-size), *count, 1, OPTAB_DIRECT);
8452 : : }
8453 : : else
8454 : : {
8455 : 739 : gcc_assert (prolog_size == 0);
8456 : : /* Decrease count, so we won't end up copying last word twice. */
8457 : 739 : if (!CONST_INT_P (*count))
8458 : 739 : *count = expand_simple_binop (GET_MODE (*count), PLUS, *count,
8459 : : constm1_rtx, *count, 1, OPTAB_DIRECT);
8460 : : else
8461 : 0 : *count = GEN_INT (ROUND_DOWN (UINTVAL (*count) - 1,
8462 : : (unsigned HOST_WIDE_INT)size));
8463 : 739 : if (*min_size)
8464 : 688 : *min_size = ROUND_DOWN (*min_size - 1, (unsigned HOST_WIDE_INT)size);
8465 : : }
8466 : 7008 : }
8467 : :
8468 : :
8469 : : /* This function is like the previous one, except here we know how many bytes
8470 : : need to be copied. That allows us to update alignment not only of DST, which
8471 : : is returned, but also of SRC, which is passed as a pointer for that
8472 : : reason. */
8473 : : static rtx
8474 : 6 : expand_set_or_cpymem_constant_prologue (rtx dst, rtx *srcp, rtx destreg,
8475 : : rtx srcreg, rtx value, rtx vec_value,
8476 : : int desired_align, int align_bytes,
8477 : : bool issetmem)
8478 : : {
8479 : 6 : rtx src = NULL;
8480 : 6 : rtx orig_dst = dst;
8481 : 6 : rtx orig_src = NULL;
8482 : 6 : int piece_size = 1;
8483 : 6 : int copied_bytes = 0;
8484 : :
8485 : 6 : if (!issetmem)
8486 : : {
8487 : 6 : gcc_assert (srcp != NULL);
8488 : 6 : src = *srcp;
8489 : 6 : orig_src = src;
8490 : : }
8491 : :
8492 : 6 : for (piece_size = 1;
8493 : 24 : piece_size <= desired_align && copied_bytes < align_bytes;
8494 : 18 : piece_size <<= 1)
8495 : : {
8496 : 18 : if (align_bytes & piece_size)
8497 : : {
8498 : 6 : if (issetmem)
8499 : : {
8500 : 0 : if (vec_value && piece_size > GET_MODE_SIZE (GET_MODE (value)))
8501 : 0 : dst = emit_memset (dst, destreg, vec_value, piece_size);
8502 : : else
8503 : 0 : dst = emit_memset (dst, destreg, value, piece_size);
8504 : : }
8505 : : else
8506 : 6 : dst = emit_memmov (dst, &src, destreg, srcreg, piece_size);
8507 : 6 : copied_bytes += piece_size;
8508 : : }
8509 : : }
8510 : 6 : if (MEM_ALIGN (dst) < (unsigned int) desired_align * BITS_PER_UNIT)
8511 : 6 : set_mem_align (dst, desired_align * BITS_PER_UNIT);
8512 : 6 : if (MEM_SIZE_KNOWN_P (orig_dst))
8513 : 6 : set_mem_size (dst, MEM_SIZE (orig_dst) - align_bytes);
8514 : :
8515 : 6 : if (!issetmem)
8516 : : {
8517 : 6 : int src_align_bytes = get_mem_align_offset (src, desired_align
8518 : : * BITS_PER_UNIT);
8519 : 6 : if (src_align_bytes >= 0)
8520 : 0 : src_align_bytes = desired_align - src_align_bytes;
8521 : 0 : if (src_align_bytes >= 0)
8522 : : {
8523 : : unsigned int src_align;
8524 : 0 : for (src_align = desired_align; src_align >= 2; src_align >>= 1)
8525 : : {
8526 : 0 : if ((src_align_bytes & (src_align - 1))
8527 : 0 : == (align_bytes & (src_align - 1)))
8528 : : break;
8529 : : }
8530 : 0 : if (src_align > (unsigned int) desired_align)
8531 : : src_align = desired_align;
8532 : 0 : if (MEM_ALIGN (src) < src_align * BITS_PER_UNIT)
8533 : 0 : set_mem_align (src, src_align * BITS_PER_UNIT);
8534 : : }
8535 : 6 : if (MEM_SIZE_KNOWN_P (orig_src))
8536 : 6 : set_mem_size (src, MEM_SIZE (orig_src) - align_bytes);
8537 : 6 : *srcp = src;
8538 : : }
8539 : :
8540 : 6 : return dst;
8541 : : }
8542 : :
8543 : : /* Return true if ALG can be used in current context.
8544 : : Assume we expand memset if MEMSET is true. */
8545 : : static bool
8546 : 535681 : alg_usable_p (enum stringop_alg alg, bool memset, bool have_as)
8547 : : {
8548 : 535681 : if (alg == no_stringop)
8549 : : return false;
8550 : : /* It is not possible to use a library call if we have non-default
8551 : : address space. We can do better than the generic byte-at-a-time
8552 : : loop, used as a fallback. */
8553 : 535681 : if (alg == libcall && have_as)
8554 : : return false;
8555 : 535673 : if (alg == vector_loop)
8556 : 15 : return TARGET_SSE || TARGET_AVX;
8557 : : /* Algorithms using the rep prefix want at least edi and ecx;
8558 : : additionally, memset wants eax and memcpy wants esi. Don't
8559 : : consider such algorithms if the user has appropriated those
8560 : : registers for their own purposes, or if we have a non-default
8561 : : address space, since some string insns cannot override the segment. */
8562 : 535658 : if (alg == rep_prefix_1_byte
8563 : : || alg == rep_prefix_4_byte
8564 : 535658 : || alg == rep_prefix_8_byte)
8565 : : {
8566 : 173614 : if (have_as)
8567 : : return false;
8568 : 173610 : if (fixed_regs[CX_REG]
8569 : 173610 : || fixed_regs[DI_REG]
8570 : 173602 : || (memset ? fixed_regs[AX_REG] : fixed_regs[SI_REG]))
8571 : 12 : return false;
8572 : : }
8573 : : return true;
8574 : : }
8575 : :
8576 : : /* Given COUNT and EXPECTED_SIZE, decide on codegen of string operation. */
8577 : : static enum stringop_alg
8578 : 100482 : decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size,
8579 : : unsigned HOST_WIDE_INT min_size, unsigned HOST_WIDE_INT max_size,
8580 : : bool memset, bool zero_memset, bool have_as,
8581 : : int *dynamic_check, bool *noalign, bool recur)
8582 : : {
8583 : 100482 : const struct stringop_algs *algs;
8584 : 100482 : bool optimize_for_speed;
8585 : 100482 : int max = 0;
8586 : 100482 : const struct processor_costs *cost;
8587 : 100482 : int i;
8588 : 100482 : bool any_alg_usable_p = false;
8589 : :
8590 : 100482 : *noalign = false;
8591 : 100482 : *dynamic_check = -1;
8592 : :
8593 : : /* Even if the string operation call is cold, we still might spend a lot
8594 : : of time processing large blocks. */
8595 : 100482 : if (optimize_function_for_size_p (cfun)
8596 : 100482 : || (optimize_insn_for_size_p ()
8597 : 4161 : && (max_size < 256
8598 : 1835 : || (expected_size != -1 && expected_size < 256))))
8599 : : optimize_for_speed = false;
8600 : : else
8601 : 90306 : optimize_for_speed = true;
8602 : :
8603 : 90306 : cost = optimize_for_speed ? ix86_cost : &ix86_size_cost;
8604 : 100482 : if (memset)
8605 : 36607 : algs = &cost->memset[TARGET_64BIT != 0];
8606 : : else
8607 : 72698 : algs = &cost->memcpy[TARGET_64BIT != 0];
8608 : :
8609 : : /* See maximal size for user defined algorithm. */
8610 : 502410 : for (i = 0; i < MAX_STRINGOP_ALGS; i++)
8611 : : {
8612 : 401928 : enum stringop_alg candidate = algs->size[i].alg;
8613 : 401928 : bool usable = alg_usable_p (candidate, memset, have_as);
8614 : 401928 : any_alg_usable_p |= usable;
8615 : :
8616 : 401928 : if (candidate != libcall && candidate && usable)
8617 : 190790 : max = algs->size[i].max;
8618 : : }
8619 : :
8620 : : /* If expected size is not known but max size is small enough
8621 : : so inline version is a win, set expected size into
8622 : : the range. */
8623 : 100482 : if (((max > 1 && (unsigned HOST_WIDE_INT) max >= max_size) || max == -1)
8624 : 52114 : && expected_size == -1)
8625 : 12808 : expected_size = min_size / 2 + max_size / 2;
8626 : :
8627 : : /* If user specified the algorithm, honor it if possible. */
8628 : 100482 : if (ix86_stringop_alg != no_stringop
8629 : 100482 : && alg_usable_p (ix86_stringop_alg, memset, have_as))
8630 : : return ix86_stringop_alg;
8631 : : /* rep; movq or rep; movl is the smallest variant. */
8632 : 100361 : else if (!optimize_for_speed)
8633 : : {
8634 : 10079 : *noalign = true;
8635 : 10079 : if (!count || (count & 3) || (memset && !zero_memset))
8636 : 4114 : return alg_usable_p (rep_prefix_1_byte, memset, have_as)
8637 : 4114 : ? rep_prefix_1_byte : loop_1_byte;
8638 : : else
8639 : 5965 : return alg_usable_p (rep_prefix_4_byte, memset, have_as)
8640 : 5965 : ? rep_prefix_4_byte : loop;
8641 : : }
8642 : : /* Very tiny blocks are best handled via the loop, REP is expensive to
8643 : : setup. */
8644 : 90282 : else if (expected_size != -1 && expected_size < 4)
8645 : : return loop_1_byte;
8646 : 88603 : else if (expected_size != -1)
8647 : : {
8648 : : enum stringop_alg alg = libcall;
8649 : : bool alg_noalign = false;
8650 : 82477 : for (i = 0; i < MAX_STRINGOP_ALGS; i++)
8651 : : {
8652 : : /* We get here if the algorithms that were not libcall-based
8653 : : were rep-prefix based and we are unable to use rep prefixes
8654 : : based on global register usage. Break out of the loop and
8655 : : use the heuristic below. */
8656 : 82212 : if (algs->size[i].max == 0)
8657 : : break;
8658 : 82212 : if (algs->size[i].max >= expected_size || algs->size[i].max == -1)
8659 : : {
8660 : 43357 : enum stringop_alg candidate = algs->size[i].alg;
8661 : :
8662 : 43357 : if (candidate != libcall
8663 : 43357 : && alg_usable_p (candidate, memset, have_as))
8664 : : {
8665 : 40726 : alg = candidate;
8666 : 40726 : alg_noalign = algs->size[i].noalign;
8667 : : }
8668 : : /* Honor TARGET_INLINE_ALL_STRINGOPS by picking
8669 : : last non-libcall inline algorithm. */
8670 : 43357 : if (TARGET_INLINE_ALL_STRINGOPS)
8671 : : {
8672 : : /* When the current size is best to be copied by a libcall,
8673 : : but we are still forced to inline, run the heuristic below
8674 : : that will pick code for medium sized blocks. */
8675 : 5836 : if (alg != libcall)
8676 : : {
8677 : 5307 : *noalign = alg_noalign;
8678 : 5307 : return alg;
8679 : : }
8680 : 529 : else if (!any_alg_usable_p)
8681 : : break;
8682 : : }
8683 : 37521 : else if (alg_usable_p (candidate, memset, have_as)
8684 : 37521 : && !(TARGET_PREFER_KNOWN_REP_MOVSB_STOSB
8685 : 22 : && candidate == rep_prefix_1_byte
8686 : : /* NB: If min_size != max_size, size is
8687 : : unknown. */
8688 : 22 : && min_size != max_size))
8689 : : {
8690 : 37513 : *noalign = algs->size[i].noalign;
8691 : 37513 : return candidate;
8692 : : }
8693 : : }
8694 : : }
8695 : : }
8696 : : /* When asked to inline the call anyway, try to pick meaningful choice.
8697 : : We look for maximal size of block that is faster to copy by hand and
8698 : : take blocks of at most of that size guessing that average size will
8699 : : be roughly half of the block.
8700 : :
8701 : : If this turns out to be bad, we might simply specify the preferred
8702 : : choice in ix86_costs. */
8703 : 45783 : if ((TARGET_INLINE_ALL_STRINGOPS || TARGET_INLINE_STRINGOPS_DYNAMICALLY)
8704 : 45783 : && (algs->unknown_size == libcall
8705 : 0 : || !alg_usable_p (algs->unknown_size, memset, have_as)))
8706 : : {
8707 : 478 : enum stringop_alg alg;
8708 : 478 : HOST_WIDE_INT new_expected_size = (max > 0 ? max : 4096) / 2;
8709 : :
8710 : : /* If there aren't any usable algorithms or if recursing already,
8711 : : then recursing on smaller sizes or same size isn't going to
8712 : : find anything. Just return the simple byte-at-a-time copy loop. */
8713 : 478 : if (!any_alg_usable_p || recur)
8714 : : {
8715 : : /* Pick something reasonable. */
8716 : 0 : if (TARGET_INLINE_STRINGOPS_DYNAMICALLY && !recur)
8717 : 0 : *dynamic_check = 128;
8718 : 0 : return loop_1_byte;
8719 : : }
8720 : 478 : alg = decide_alg (count, new_expected_size, min_size, max_size, memset,
8721 : : zero_memset, have_as, dynamic_check, noalign, true);
8722 : 478 : gcc_assert (*dynamic_check == -1);
8723 : 478 : if (TARGET_INLINE_STRINGOPS_DYNAMICALLY)
8724 : 9 : *dynamic_check = max;
8725 : : else
8726 : 469 : gcc_assert (alg != libcall);
8727 : 478 : return alg;
8728 : : }
8729 : :
8730 : : /* Try to use some reasonable fallback algorithm. Note that for
8731 : : non-default address spaces we default to a loop instead of
8732 : : a libcall. */
8733 : 45305 : return (alg_usable_p (algs->unknown_size, memset, have_as)
8734 : 45305 : ? algs->unknown_size : have_as ? loop : libcall);
8735 : : }
8736 : :
8737 : : /* Decide on alignment. We know that the operand is already aligned to ALIGN
8738 : : (ALIGN can be based on profile feedback and thus it is not 100% guaranteed). */
8739 : : static int
8740 : 52564 : decide_alignment (int align,
8741 : : enum stringop_alg alg,
8742 : : int expected_size,
8743 : : machine_mode move_mode)
8744 : : {
8745 : 52564 : int desired_align = 0;
8746 : :
8747 : 52564 : gcc_assert (alg != no_stringop);
8748 : :
8749 : 52564 : if (alg == libcall)
8750 : : return 0;
8751 : 52564 : if (move_mode == VOIDmode)
8752 : : return 0;
8753 : :
8754 : 52564 : desired_align = GET_MODE_SIZE (move_mode);
8755 : : /* PentiumPro has special logic triggering for 8 byte aligned blocks.
8756 : : copying whole cacheline at once. */
8757 : 52564 : if (TARGET_CPU_P (PENTIUMPRO)
8758 : 0 : && (alg == rep_prefix_4_byte || alg == rep_prefix_1_byte))
8759 : 52564 : desired_align = 8;
8760 : :
8761 : 52564 : if (optimize_size)
8762 : 7634 : desired_align = 1;
8763 : 52564 : if (desired_align < align)
8764 : : desired_align = align;
8765 : 52564 : if (expected_size != -1 && expected_size < 4)
8766 : 0 : desired_align = align;
8767 : :
8768 : : return desired_align;
8769 : : }
8770 : :
8771 : :
8772 : : /* Helper function for memcpy. For QImode value 0xXY produce
8773 : : 0xXYXYXYXY of wide specified by MODE. This is essentially
8774 : : a * 0x10101010, but we can do slightly better than
8775 : : synth_mult by unwinding the sequence by hand on CPUs with
8776 : : slow multiply. */
8777 : : static rtx
8778 : 19361 : promote_duplicated_reg (machine_mode mode, rtx val)
8779 : : {
8780 : 19361 : machine_mode valmode = GET_MODE (val);
8781 : 19361 : rtx tmp;
8782 : 19361 : int nops = mode == DImode ? 3 : 2;
8783 : :
8784 : 19361 : gcc_assert (mode == SImode || mode == DImode || val == const0_rtx);
8785 : 19361 : if (val == const0_rtx)
8786 : 18255 : return copy_to_mode_reg (mode, CONST0_RTX (mode));
8787 : 1106 : if (CONST_INT_P (val))
8788 : : {
8789 : 870 : HOST_WIDE_INT v = INTVAL (val) & 255;
8790 : :
8791 : 870 : v |= v << 8;
8792 : 870 : v |= v << 16;
8793 : 870 : if (mode == DImode)
8794 : 835 : v |= (v << 16) << 16;
8795 : 870 : return copy_to_mode_reg (mode, gen_int_mode (v, mode));
8796 : : }
8797 : :
8798 : 236 : if (valmode == VOIDmode)
8799 : : valmode = QImode;
8800 : 236 : if (valmode != QImode)
8801 : 0 : val = gen_lowpart (QImode, val);
8802 : 236 : if (mode == QImode)
8803 : : return val;
8804 : 236 : if (!TARGET_PARTIAL_REG_STALL)
8805 : 236 : nops--;
8806 : 472 : if (ix86_cost->mult_init[mode == DImode ? 3 : 2]
8807 : 236 : + ix86_cost->mult_bit * (mode == DImode ? 8 : 4)
8808 : 236 : <= (ix86_cost->shift_const + ix86_cost->add) * nops
8809 : 236 : + (COSTS_N_INSNS (TARGET_PARTIAL_REG_STALL == 0)))
8810 : : {
8811 : 236 : rtx reg = convert_modes (mode, QImode, val, true);
8812 : 236 : tmp = promote_duplicated_reg (mode, const1_rtx);
8813 : 236 : return expand_simple_binop (mode, MULT, reg, tmp, NULL, 1,
8814 : 236 : OPTAB_DIRECT);
8815 : : }
8816 : : else
8817 : : {
8818 : 0 : rtx reg = convert_modes (mode, QImode, val, true);
8819 : :
8820 : 0 : if (!TARGET_PARTIAL_REG_STALL)
8821 : 0 : emit_insn (gen_insv_1 (mode, reg, reg));
8822 : : else
8823 : : {
8824 : 0 : tmp = expand_simple_binop (mode, ASHIFT, reg, GEN_INT (8),
8825 : : NULL, 1, OPTAB_DIRECT);
8826 : 0 : reg = expand_simple_binop (mode, IOR, reg, tmp, reg, 1,
8827 : : OPTAB_DIRECT);
8828 : : }
8829 : 0 : tmp = expand_simple_binop (mode, ASHIFT, reg, GEN_INT (16),
8830 : : NULL, 1, OPTAB_DIRECT);
8831 : 0 : reg = expand_simple_binop (mode, IOR, reg, tmp, reg, 1, OPTAB_DIRECT);
8832 : 0 : if (mode == SImode)
8833 : : return reg;
8834 : 0 : tmp = expand_simple_binop (mode, ASHIFT, reg, GEN_INT (32),
8835 : : NULL, 1, OPTAB_DIRECT);
8836 : 0 : reg = expand_simple_binop (mode, IOR, reg, tmp, reg, 1, OPTAB_DIRECT);
8837 : 0 : return reg;
8838 : : }
8839 : : }
8840 : :
8841 : : /* Duplicate value VAL using promote_duplicated_reg into maximal size that will
8842 : : be needed by main loop copying SIZE_NEEDED chunks and prologue getting
8843 : : alignment from ALIGN to DESIRED_ALIGN. */
8844 : : static rtx
8845 : 20436 : promote_duplicated_reg_to_size (rtx val, int size_needed, int desired_align,
8846 : : int align)
8847 : : {
8848 : 20436 : rtx promoted_val;
8849 : :
8850 : 20436 : if (TARGET_64BIT
8851 : 17186 : && (size_needed > 4 || (desired_align > align && desired_align > 4)))
8852 : 14155 : promoted_val = promote_duplicated_reg (DImode, val);
8853 : 6281 : else if (size_needed > 2 || (desired_align > align && desired_align > 2))
8854 : 4967 : promoted_val = promote_duplicated_reg (SImode, val);
8855 : 1314 : else if (size_needed > 1 || (desired_align > align && desired_align > 1))
8856 : 0 : promoted_val = promote_duplicated_reg (HImode, val);
8857 : : else
8858 : : promoted_val = val;
8859 : :
8860 : 20436 : return promoted_val;
8861 : : }
8862 : :
8863 : : /* Copy the address to a Pmode register. This is used for x32 to
8864 : : truncate DImode TLS address to a SImode register. */
8865 : :
8866 : : static rtx
8867 : 84692 : ix86_copy_addr_to_reg (rtx addr)
8868 : : {
8869 : 84692 : rtx reg;
8870 : 84692 : if (GET_MODE (addr) == Pmode || GET_MODE (addr) == VOIDmode)
8871 : : {
8872 : 84692 : reg = copy_addr_to_reg (addr);
8873 : 84692 : REG_POINTER (reg) = 1;
8874 : 84692 : return reg;
8875 : : }
8876 : : else
8877 : : {
8878 : 0 : gcc_assert (GET_MODE (addr) == DImode && Pmode == SImode);
8879 : 0 : reg = copy_to_mode_reg (DImode, addr);
8880 : 0 : REG_POINTER (reg) = 1;
8881 : 0 : return gen_rtx_SUBREG (SImode, reg, 0);
8882 : : }
8883 : : }
8884 : :
8885 : : /* Expand string move (memcpy) ot store (memset) operation. Use i386 string
8886 : : operations when profitable. The code depends upon architecture, block size
8887 : : and alignment, but always has one of the following overall structures:
8888 : :
8889 : : Aligned move sequence:
8890 : :
8891 : : 1) Prologue guard: Conditional that jumps up to epilogues for small
8892 : : blocks that can be handled by epilogue alone. This is faster
8893 : : but also needed for correctness, since prologue assume the block
8894 : : is larger than the desired alignment.
8895 : :
8896 : : Optional dynamic check for size and libcall for large
8897 : : blocks is emitted here too, with -minline-stringops-dynamically.
8898 : :
8899 : : 2) Prologue: copy first few bytes in order to get destination
8900 : : aligned to DESIRED_ALIGN. It is emitted only when ALIGN is less
8901 : : than DESIRED_ALIGN and up to DESIRED_ALIGN - ALIGN bytes can be
8902 : : copied. We emit either a jump tree on power of two sized
8903 : : blocks, or a byte loop.
8904 : :
8905 : : 3) Main body: the copying loop itself, copying in SIZE_NEEDED chunks
8906 : : with specified algorithm.
8907 : :
8908 : : 4) Epilogue: code copying tail of the block that is too small to be
8909 : : handled by main body (or up to size guarded by prologue guard).
8910 : :
8911 : : Misaligned move sequence
8912 : :
8913 : : 1) missaligned move prologue/epilogue containing:
8914 : : a) Prologue handling small memory blocks and jumping to done_label
8915 : : (skipped if blocks are known to be large enough)
8916 : : b) Signle move copying first DESIRED_ALIGN-ALIGN bytes if alignment is
8917 : : needed by single possibly misaligned move
8918 : : (skipped if alignment is not needed)
8919 : : c) Copy of last SIZE_NEEDED bytes by possibly misaligned moves
8920 : :
8921 : : 2) Zero size guard dispatching to done_label, if needed
8922 : :
8923 : : 3) dispatch to library call, if needed,
8924 : :
8925 : : 3) Main body: the copying loop itself, copying in SIZE_NEEDED chunks
8926 : : with specified algorithm. */
8927 : : bool
8928 : 100185 : ix86_expand_set_or_cpymem (rtx dst, rtx src, rtx count_exp, rtx val_exp,
8929 : : rtx align_exp, rtx expected_align_exp,
8930 : : rtx expected_size_exp, rtx min_size_exp,
8931 : : rtx max_size_exp, rtx probable_max_size_exp,
8932 : : bool issetmem)
8933 : : {
8934 : 100185 : rtx destreg;
8935 : 100185 : rtx srcreg = NULL;
8936 : 100185 : rtx_code_label *label = NULL;
8937 : 100185 : rtx tmp;
8938 : 100185 : rtx_code_label *jump_around_label = NULL;
8939 : 100185 : HOST_WIDE_INT align = 1;
8940 : 100185 : unsigned HOST_WIDE_INT count = 0;
8941 : 100185 : HOST_WIDE_INT expected_size = -1;
8942 : 100185 : int size_needed = 0, epilogue_size_needed;
8943 : 100185 : int desired_align = 0, align_bytes = 0;
8944 : 100185 : enum stringop_alg alg;
8945 : 100185 : rtx promoted_val = NULL;
8946 : 100185 : rtx vec_promoted_val = NULL;
8947 : 100185 : bool force_loopy_epilogue = false;
8948 : 100185 : int dynamic_check;
8949 : 100185 : bool need_zero_guard = false;
8950 : 100185 : bool noalign;
8951 : 100185 : machine_mode move_mode = VOIDmode;
8952 : 100185 : machine_mode wider_mode;
8953 : 100185 : int unroll_factor = 1;
8954 : : /* TODO: Once value ranges are available, fill in proper data. */
8955 : 100185 : unsigned HOST_WIDE_INT min_size = 0;
8956 : 100185 : unsigned HOST_WIDE_INT max_size = -1;
8957 : 100185 : unsigned HOST_WIDE_INT probable_max_size = -1;
8958 : 100185 : bool misaligned_prologue_used = false;
8959 : 100185 : bool have_as;
8960 : :
8961 : 100185 : if (CONST_INT_P (align_exp))
8962 : 100185 : align = INTVAL (align_exp);
8963 : : /* i386 can do misaligned access on reasonably increased cost. */
8964 : 100185 : if (CONST_INT_P (expected_align_exp)
8965 : 100185 : && INTVAL (expected_align_exp) > align)
8966 : : align = INTVAL (expected_align_exp);
8967 : : /* ALIGN is the minimum of destination and source alignment, but we care here
8968 : : just about destination alignment. */
8969 : 94738 : else if (!issetmem
8970 : 94738 : && MEM_ALIGN (dst) > (unsigned HOST_WIDE_INT) align * BITS_PER_UNIT)
8971 : 2322 : align = MEM_ALIGN (dst) / BITS_PER_UNIT;
8972 : :
8973 : 100185 : if (CONST_INT_P (count_exp))
8974 : : {
8975 : 41844 : min_size = max_size = probable_max_size = count = expected_size
8976 : 41844 : = INTVAL (count_exp);
8977 : : /* When COUNT is 0, there is nothing to do. */
8978 : 41844 : if (!count)
8979 : : return true;
8980 : : }
8981 : : else
8982 : : {
8983 : 58341 : if (min_size_exp)
8984 : 58341 : min_size = INTVAL (min_size_exp);
8985 : 58341 : if (max_size_exp)
8986 : 32937 : max_size = INTVAL (max_size_exp);
8987 : 58341 : if (probable_max_size_exp)
8988 : 34992 : probable_max_size = INTVAL (probable_max_size_exp);
8989 : 58341 : if (CONST_INT_P (expected_size_exp))
8990 : 58341 : expected_size = INTVAL (expected_size_exp);
8991 : : }
8992 : :
8993 : : /* Make sure we don't need to care about overflow later on. */
8994 : 100183 : if (count > (HOST_WIDE_INT_1U << 30))
8995 : : return false;
8996 : :
8997 : 100004 : have_as = !ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (dst));
8998 : 100004 : if (!issetmem)
8999 : 67732 : have_as |= !ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (src));
9000 : :
9001 : : /* Step 0: Decide on preferred algorithm, desired alignment and
9002 : : size of chunks to be copied by main loop. */
9003 : 100004 : alg = decide_alg (count, expected_size, min_size, probable_max_size,
9004 : : issetmem,
9005 : 32272 : issetmem && val_exp == const0_rtx, have_as,
9006 : : &dynamic_check, &noalign, false);
9007 : :
9008 : 100004 : if (dump_file)
9009 : 7 : fprintf (dump_file, "Selected stringop expansion strategy: %s\n",
9010 : 7 : stringop_alg_names[alg]);
9011 : :
9012 : 100004 : if (alg == libcall)
9013 : : return false;
9014 : 52564 : gcc_assert (alg != no_stringop);
9015 : :
9016 : : /* For now vector-version of memset is generated only for memory zeroing, as
9017 : : creating of promoted vector value is very cheap in this case. */
9018 : 52564 : if (issetmem && alg == vector_loop && val_exp != const0_rtx)
9019 : 0 : alg = unrolled_loop;
9020 : :
9021 : 52564 : if (!count)
9022 : 13033 : count_exp = copy_to_mode_reg (GET_MODE (count_exp), count_exp);
9023 : 52564 : destreg = ix86_copy_addr_to_reg (XEXP (dst, 0));
9024 : 52564 : if (!issetmem)
9025 : 32128 : srcreg = ix86_copy_addr_to_reg (XEXP (src, 0));
9026 : :
9027 : 52564 : unroll_factor = 1;
9028 : 52564 : move_mode = word_mode;
9029 : 52564 : switch (alg)
9030 : : {
9031 : 0 : case libcall:
9032 : 0 : case no_stringop:
9033 : 0 : case last_alg:
9034 : 0 : gcc_unreachable ();
9035 : 1683 : case loop_1_byte:
9036 : 1683 : need_zero_guard = true;
9037 : 1683 : move_mode = QImode;
9038 : 1683 : break;
9039 : : case loop:
9040 : 8325 : need_zero_guard = true;
9041 : : break;
9042 : 3 : case unrolled_loop:
9043 : 3 : need_zero_guard = true;
9044 : 3 : unroll_factor = (TARGET_64BIT ? 4 : 2);
9045 : : break;
9046 : : case vector_loop:
9047 : 20 : need_zero_guard = true;
9048 : 20 : unroll_factor = 4;
9049 : : /* Find the widest supported mode. */
9050 : : move_mode = word_mode;
9051 : 20 : while (GET_MODE_WIDER_MODE (move_mode).exists (&wider_mode)
9052 : 20 : && optab_handler (mov_optab, wider_mode) != CODE_FOR_nothing)
9053 : 11 : move_mode = wider_mode;
9054 : :
9055 : 9 : if (TARGET_AVX256_SPLIT_REGS && GET_MODE_BITSIZE (move_mode) > 128)
9056 : 0 : move_mode = TImode;
9057 : 9 : if (TARGET_AVX512_SPLIT_REGS && GET_MODE_BITSIZE (move_mode) > 256)
9058 : 0 : move_mode = OImode;
9059 : :
9060 : : /* Find the corresponding vector mode with the same size as MOVE_MODE.
9061 : : MOVE_MODE is an integer mode at the moment (SI, DI, TI, etc.). */
9062 : 27 : if (GET_MODE_SIZE (move_mode) > GET_MODE_SIZE (word_mode))
9063 : : {
9064 : 18 : int nunits = GET_MODE_SIZE (move_mode) / GET_MODE_SIZE (word_mode);
9065 : 18 : if (!mode_for_vector (word_mode, nunits).exists (&move_mode)
9066 : 9 : || optab_handler (mov_optab, move_mode) == CODE_FOR_nothing)
9067 : 0 : move_mode = word_mode;
9068 : : }
9069 : 9 : gcc_assert (optab_handler (mov_optab, move_mode) != CODE_FOR_nothing);
9070 : : break;
9071 : 28791 : case rep_prefix_8_byte:
9072 : 28791 : move_mode = DImode;
9073 : 28791 : break;
9074 : 11318 : case rep_prefix_4_byte:
9075 : 11318 : move_mode = SImode;
9076 : 11318 : break;
9077 : 4118 : case rep_prefix_1_byte:
9078 : 4118 : move_mode = QImode;
9079 : 4118 : break;
9080 : : }
9081 : 52564 : size_needed = GET_MODE_SIZE (move_mode) * unroll_factor;
9082 : 52564 : epilogue_size_needed = size_needed;
9083 : :
9084 : : /* If we are going to call any library calls conditionally, make sure any
9085 : : pending stack adjustment happen before the first conditional branch,
9086 : : otherwise they will be emitted before the library call only and won't
9087 : : happen from the other branches. */
9088 : 52564 : if (dynamic_check != -1)
9089 : 8 : do_pending_stack_adjust ();
9090 : :
9091 : 52564 : desired_align = decide_alignment (align, alg, expected_size, move_mode);
9092 : 52564 : if (!TARGET_ALIGN_STRINGOPS || noalign)
9093 : 10088 : align = desired_align;
9094 : :
9095 : : /* Step 1: Prologue guard. */
9096 : :
9097 : : /* Alignment code needs count to be in register. */
9098 : 52564 : if (CONST_INT_P (count_exp) && desired_align > align)
9099 : : {
9100 : 1716 : if (INTVAL (count_exp) > desired_align
9101 : 1716 : && INTVAL (count_exp) > size_needed)
9102 : : {
9103 : 1716 : align_bytes
9104 : 1716 : = get_mem_align_offset (dst, desired_align * BITS_PER_UNIT);
9105 : 1716 : if (align_bytes <= 0)
9106 : : align_bytes = 0;
9107 : : else
9108 : 6 : align_bytes = desired_align - align_bytes;
9109 : : }
9110 : 6 : if (align_bytes == 0)
9111 : 1710 : count_exp = force_reg (counter_mode (count_exp), count_exp);
9112 : : }
9113 : 52564 : gcc_assert (desired_align >= 1 && align >= 1);
9114 : :
9115 : : /* Misaligned move sequences handle both prologue and epilogue at once.
9116 : : Default code generation results in a smaller code for large alignments
9117 : : and also avoids redundant job when sizes are known precisely. */
9118 : 52564 : misaligned_prologue_used
9119 : 105128 : = (TARGET_MISALIGNED_MOVE_STRING_PRO_EPILOGUES
9120 : 52553 : && MAX (desired_align, epilogue_size_needed) <= 32
9121 : 51398 : && desired_align <= epilogue_size_needed
9122 : 70424 : && ((desired_align > align && !align_bytes)
9123 : 11591 : || (!count && epilogue_size_needed > 1)));
9124 : :
9125 : : /* Do the cheap promotion to allow better CSE across the
9126 : : main loop and epilogue (ie one load of the big constant in the
9127 : : front of all code.
9128 : : For now the misaligned move sequences do not have fast path
9129 : : without broadcasting. */
9130 : 52564 : if (issetmem && ((CONST_INT_P (val_exp) || misaligned_prologue_used)))
9131 : : {
9132 : 20288 : if (alg == vector_loop)
9133 : : {
9134 : 3 : gcc_assert (val_exp == const0_rtx);
9135 : 3 : vec_promoted_val = promote_duplicated_reg (move_mode, val_exp);
9136 : 3 : promoted_val = promote_duplicated_reg_to_size (val_exp,
9137 : 6 : GET_MODE_SIZE (word_mode),
9138 : : desired_align, align);
9139 : : }
9140 : : else
9141 : : {
9142 : 20285 : promoted_val = promote_duplicated_reg_to_size (val_exp, size_needed,
9143 : : desired_align, align);
9144 : : }
9145 : : }
9146 : : /* Misaligned move sequences handles both prologues and epilogues at once.
9147 : : Default code generation results in smaller code for large alignments and
9148 : : also avoids redundant job when sizes are known precisely. */
9149 : 52564 : if (misaligned_prologue_used)
9150 : : {
9151 : : /* Misaligned move prologue handled small blocks by itself. */
9152 : 7008 : expand_set_or_cpymem_prologue_epilogue_by_misaligned_moves
9153 : 7008 : (dst, src, &destreg, &srcreg,
9154 : : move_mode, promoted_val, vec_promoted_val,
9155 : : &count_exp,
9156 : : &jump_around_label,
9157 : 7008 : desired_align < align
9158 : 0 : ? MAX (desired_align, epilogue_size_needed) : epilogue_size_needed,
9159 : : desired_align, align, &min_size, dynamic_check, issetmem);
9160 : 7008 : if (!issetmem)
9161 : 4905 : src = change_address (src, BLKmode, srcreg);
9162 : 7008 : dst = change_address (dst, BLKmode, destreg);
9163 : 7008 : set_mem_align (dst, desired_align * BITS_PER_UNIT);
9164 : 7008 : epilogue_size_needed = 0;
9165 : 7008 : if (need_zero_guard
9166 : 4412 : && min_size < (unsigned HOST_WIDE_INT) size_needed)
9167 : : {
9168 : : /* It is possible that we copied enough so the main loop will not
9169 : : execute. */
9170 : 4404 : gcc_assert (size_needed > 1);
9171 : 4404 : if (jump_around_label == NULL_RTX)
9172 : 192 : jump_around_label = gen_label_rtx ();
9173 : 4404 : emit_cmp_and_jump_insns (count_exp,
9174 : : GEN_INT (size_needed),
9175 : : LTU, 0, counter_mode (count_exp), 1, jump_around_label);
9176 : 4404 : if (expected_size == -1
9177 : 1 : || expected_size < (desired_align - align) / 2 + size_needed)
9178 : 4404 : predict_jump (REG_BR_PROB_BASE * 20 / 100);
9179 : : else
9180 : 0 : predict_jump (REG_BR_PROB_BASE * 60 / 100);
9181 : : }
9182 : : }
9183 : : /* Ensure that alignment prologue won't copy past end of block. */
9184 : 45556 : else if (size_needed > 1 || (desired_align > 1 && desired_align > align))
9185 : : {
9186 : 39755 : epilogue_size_needed = MAX (size_needed - 1, desired_align - align);
9187 : : /* Epilogue always copies COUNT_EXP & EPILOGUE_SIZE_NEEDED bytes.
9188 : : Make sure it is power of 2. */
9189 : 39755 : epilogue_size_needed = 1 << (floor_log2 (epilogue_size_needed) + 1);
9190 : :
9191 : : /* To improve performance of small blocks, we jump around the VAL
9192 : : promoting mode. This mean that if the promoted VAL is not constant,
9193 : : we might not use it in the epilogue and have to use byte
9194 : : loop variant. */
9195 : 39755 : if (issetmem && epilogue_size_needed > 2 && !promoted_val)
9196 : 39755 : force_loopy_epilogue = true;
9197 : 39755 : if ((count && count < (unsigned HOST_WIDE_INT) epilogue_size_needed)
9198 : 39755 : || max_size < (unsigned HOST_WIDE_INT) epilogue_size_needed)
9199 : : {
9200 : : /* If main algorithm works on QImode, no epilogue is needed.
9201 : : For small sizes just don't align anything. */
9202 : 84 : if (size_needed == 1)
9203 : 0 : desired_align = align;
9204 : : else
9205 : 84 : goto epilogue;
9206 : : }
9207 : 39671 : else if (!count
9208 : 2837 : && min_size < (unsigned HOST_WIDE_INT) epilogue_size_needed)
9209 : : {
9210 : 2065 : label = gen_label_rtx ();
9211 : 2065 : emit_cmp_and_jump_insns (count_exp,
9212 : : GEN_INT (epilogue_size_needed),
9213 : : LTU, 0, counter_mode (count_exp), 1, label);
9214 : 2065 : if (expected_size == -1 || expected_size < epilogue_size_needed)
9215 : 2060 : predict_jump (REG_BR_PROB_BASE * 60 / 100);
9216 : : else
9217 : 5 : predict_jump (REG_BR_PROB_BASE * 20 / 100);
9218 : : }
9219 : : }
9220 : :
9221 : : /* Emit code to decide on runtime whether library call or inline should be
9222 : : used. */
9223 : 52480 : if (dynamic_check != -1)
9224 : : {
9225 : 8 : if (!issetmem && CONST_INT_P (count_exp))
9226 : : {
9227 : 0 : if (UINTVAL (count_exp) >= (unsigned HOST_WIDE_INT)dynamic_check)
9228 : : {
9229 : 0 : emit_block_copy_via_libcall (dst, src, count_exp);
9230 : 0 : count_exp = const0_rtx;
9231 : 0 : goto epilogue;
9232 : : }
9233 : : }
9234 : : else
9235 : : {
9236 : 8 : rtx_code_label *hot_label = gen_label_rtx ();
9237 : 8 : if (jump_around_label == NULL_RTX)
9238 : 2 : jump_around_label = gen_label_rtx ();
9239 : 8 : emit_cmp_and_jump_insns (count_exp, GEN_INT (dynamic_check - 1),
9240 : : LEU, 0, counter_mode (count_exp),
9241 : : 1, hot_label);
9242 : 8 : predict_jump (REG_BR_PROB_BASE * 90 / 100);
9243 : 8 : if (issetmem)
9244 : 5 : set_storage_via_libcall (dst, count_exp, val_exp);
9245 : : else
9246 : 3 : emit_block_copy_via_libcall (dst, src, count_exp);
9247 : 8 : emit_jump (jump_around_label);
9248 : 8 : emit_label (hot_label);
9249 : : }
9250 : : }
9251 : :
9252 : : /* Step 2: Alignment prologue. */
9253 : : /* Do the expensive promotion once we branched off the small blocks. */
9254 : 52480 : if (issetmem && !promoted_val)
9255 : 148 : promoted_val = promote_duplicated_reg_to_size (val_exp, size_needed,
9256 : : desired_align, align);
9257 : :
9258 : 52480 : if (desired_align > align && !misaligned_prologue_used)
9259 : : {
9260 : 12 : if (align_bytes == 0)
9261 : : {
9262 : : /* Except for the first move in prologue, we no longer know
9263 : : constant offset in aliasing info. It don't seems to worth
9264 : : the pain to maintain it for the first move, so throw away
9265 : : the info early. */
9266 : 6 : dst = change_address (dst, BLKmode, destreg);
9267 : 6 : if (!issetmem)
9268 : 4 : src = change_address (src, BLKmode, srcreg);
9269 : 6 : dst = expand_set_or_cpymem_prologue (dst, src, destreg, srcreg,
9270 : : promoted_val, vec_promoted_val,
9271 : : count_exp, align, desired_align,
9272 : : issetmem);
9273 : : /* At most desired_align - align bytes are copied. */
9274 : 6 : if (min_size < (unsigned)(desired_align - align))
9275 : 0 : min_size = 0;
9276 : : else
9277 : 6 : min_size -= desired_align - align;
9278 : : }
9279 : : else
9280 : : {
9281 : : /* If we know how many bytes need to be stored before dst is
9282 : : sufficiently aligned, maintain aliasing info accurately. */
9283 : 6 : dst = expand_set_or_cpymem_constant_prologue (dst, &src, destreg,
9284 : : srcreg,
9285 : : promoted_val,
9286 : : vec_promoted_val,
9287 : : desired_align,
9288 : : align_bytes,
9289 : : issetmem);
9290 : :
9291 : 6 : count_exp = plus_constant (counter_mode (count_exp),
9292 : 6 : count_exp, -align_bytes);
9293 : 6 : count -= align_bytes;
9294 : 6 : min_size -= align_bytes;
9295 : 6 : max_size -= align_bytes;
9296 : : }
9297 : 12 : if (need_zero_guard
9298 : 6 : && min_size < (unsigned HOST_WIDE_INT) size_needed
9299 : 1 : && (count < (unsigned HOST_WIDE_INT) size_needed
9300 : 0 : || (align_bytes == 0
9301 : 0 : && count < ((unsigned HOST_WIDE_INT) size_needed
9302 : 0 : + desired_align - align))))
9303 : : {
9304 : : /* It is possible that we copied enough so the main loop will not
9305 : : execute. */
9306 : 1 : gcc_assert (size_needed > 1);
9307 : 1 : if (label == NULL_RTX)
9308 : 0 : label = gen_label_rtx ();
9309 : 1 : emit_cmp_and_jump_insns (count_exp,
9310 : : GEN_INT (size_needed),
9311 : : LTU, 0, counter_mode (count_exp), 1, label);
9312 : 1 : if (expected_size == -1
9313 : 0 : || expected_size < (desired_align - align) / 2 + size_needed)
9314 : 1 : predict_jump (REG_BR_PROB_BASE * 20 / 100);
9315 : : else
9316 : 0 : predict_jump (REG_BR_PROB_BASE * 60 / 100);
9317 : : }
9318 : : }
9319 : 52480 : if (label && size_needed == 1)
9320 : : {
9321 : 0 : emit_label (label);
9322 : 0 : LABEL_NUSES (label) = 1;
9323 : 0 : label = NULL;
9324 : 0 : epilogue_size_needed = 1;
9325 : 0 : if (issetmem)
9326 : 0 : promoted_val = val_exp;
9327 : : }
9328 : 52480 : else if (label == NULL_RTX && !misaligned_prologue_used)
9329 : 43407 : epilogue_size_needed = size_needed;
9330 : :
9331 : : /* Step 3: Main loop. */
9332 : :
9333 : 52480 : switch (alg)
9334 : : {
9335 : 0 : case libcall:
9336 : 0 : case no_stringop:
9337 : 0 : case last_alg:
9338 : 0 : gcc_unreachable ();
9339 : 8244 : case loop_1_byte:
9340 : 8244 : case loop:
9341 : 8244 : case unrolled_loop:
9342 : 8244 : expand_set_or_cpymem_via_loop (dst, src, destreg, srcreg, promoted_val,
9343 : : count_exp, move_mode, unroll_factor,
9344 : : expected_size, issetmem);
9345 : 8244 : break;
9346 : 9 : case vector_loop:
9347 : 9 : expand_set_or_cpymem_via_loop (dst, src, destreg, srcreg,
9348 : : vec_promoted_val, count_exp, move_mode,
9349 : : unroll_factor, expected_size, issetmem);
9350 : 9 : break;
9351 : 44227 : case rep_prefix_8_byte:
9352 : 44227 : case rep_prefix_4_byte:
9353 : 44227 : case rep_prefix_1_byte:
9354 : 44227 : expand_set_or_cpymem_via_rep (dst, src, destreg, srcreg, promoted_val,
9355 : : val_exp, count_exp, move_mode, issetmem);
9356 : 44227 : break;
9357 : : }
9358 : : /* Adjust properly the offset of src and dest memory for aliasing. */
9359 : 52480 : if (CONST_INT_P (count_exp))
9360 : : {
9361 : 37821 : if (!issetmem)
9362 : 21144 : src = adjust_automodify_address_nv (src, BLKmode, srcreg,
9363 : : (count / size_needed) * size_needed);
9364 : 37821 : dst = adjust_automodify_address_nv (dst, BLKmode, destreg,
9365 : : (count / size_needed) * size_needed);
9366 : : }
9367 : : else
9368 : : {
9369 : 14659 : if (!issetmem)
9370 : 10900 : src = change_address (src, BLKmode, srcreg);
9371 : 14659 : dst = change_address (dst, BLKmode, destreg);
9372 : : }
9373 : :
9374 : : /* Step 4: Epilogue to copy the remaining bytes. */
9375 : 52564 : epilogue:
9376 : 52564 : if (label)
9377 : : {
9378 : : /* When the main loop is done, COUNT_EXP might hold original count,
9379 : : while we want to copy only COUNT_EXP & SIZE_NEEDED bytes.
9380 : : Epilogue code will actually copy COUNT_EXP & EPILOGUE_SIZE_NEEDED
9381 : : bytes. Compensate if needed. */
9382 : :
9383 : 2065 : if (size_needed < epilogue_size_needed)
9384 : : {
9385 : 0 : tmp = expand_simple_binop (counter_mode (count_exp), AND, count_exp,
9386 : 0 : GEN_INT (size_needed - 1), count_exp, 1,
9387 : : OPTAB_DIRECT);
9388 : 0 : if (tmp != count_exp)
9389 : 0 : emit_move_insn (count_exp, tmp);
9390 : : }
9391 : 2065 : emit_label (label);
9392 : 2065 : LABEL_NUSES (label) = 1;
9393 : : }
9394 : :
9395 : 52564 : if (count_exp != const0_rtx && epilogue_size_needed > 1)
9396 : : {
9397 : 39755 : if (force_loopy_epilogue)
9398 : 106 : expand_setmem_epilogue_via_loop (dst, destreg, val_exp, count_exp,
9399 : : epilogue_size_needed);
9400 : : else
9401 : : {
9402 : 39649 : if (issetmem)
9403 : 16913 : expand_setmem_epilogue (dst, destreg, promoted_val,
9404 : : vec_promoted_val, count_exp,
9405 : : epilogue_size_needed);
9406 : : else
9407 : 22736 : expand_cpymem_epilogue (dst, src, destreg, srcreg, count_exp,
9408 : : epilogue_size_needed);
9409 : : }
9410 : : }
9411 : 52564 : if (jump_around_label)
9412 : 4836 : emit_label (jump_around_label);
9413 : : return true;
9414 : : }
9415 : :
9416 : : /* Expand cmpstrn or memcmp. */
9417 : :
9418 : : bool
9419 : 208150 : ix86_expand_cmpstrn_or_cmpmem (rtx result, rtx src1, rtx src2,
9420 : : rtx length, rtx align, bool is_cmpstrn)
9421 : : {
9422 : : /* Expand strncmp and memcmp only with -minline-all-stringops since
9423 : : "repz cmpsb" can be much slower than strncmp and memcmp functions
9424 : : implemented with vector instructions, see
9425 : :
9426 : : https://gcc.gnu.org/bugzilla/show_bug.cgi?id=43052
9427 : : */
9428 : 208150 : if (!TARGET_INLINE_ALL_STRINGOPS)
9429 : : return false;
9430 : :
9431 : : /* Can't use this if the user has appropriated ecx, esi or edi. */
9432 : 5704 : if (fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG])
9433 : : return false;
9434 : :
9435 : 5704 : if (is_cmpstrn)
9436 : : {
9437 : : /* For strncmp, length is the maximum length, which can be larger
9438 : : than actual string lengths. We can expand the cmpstrn pattern
9439 : : to "repz cmpsb" only if one of the strings is a constant so
9440 : : that expand_builtin_strncmp() can write the length argument to
9441 : : be the minimum of the const string length and the actual length
9442 : : argument. Otherwise, "repz cmpsb" may pass the 0 byte. */
9443 : 73 : tree t1 = MEM_EXPR (src1);
9444 : 73 : tree t2 = MEM_EXPR (src2);
9445 : 146 : if (!((t1 && TREE_CODE (t1) == MEM_REF
9446 : 73 : && TREE_CODE (TREE_OPERAND (t1, 0)) == ADDR_EXPR
9447 : 0 : && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (t1, 0), 0))
9448 : : == STRING_CST))
9449 : 73 : || (t2 && TREE_CODE (t2) == MEM_REF
9450 : 73 : && TREE_CODE (TREE_OPERAND (t2, 0)) == ADDR_EXPR
9451 : 73 : && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (t2, 0), 0))
9452 : : == STRING_CST))))
9453 : : return false;
9454 : : }
9455 : :
9456 : 5704 : rtx addr1 = copy_addr_to_reg (XEXP (src1, 0));
9457 : 5704 : rtx addr2 = copy_addr_to_reg (XEXP (src2, 0));
9458 : 5704 : if (addr1 != XEXP (src1, 0))
9459 : 5704 : src1 = replace_equiv_address_nv (src1, addr1);
9460 : 5704 : if (addr2 != XEXP (src2, 0))
9461 : 5704 : src2 = replace_equiv_address_nv (src2, addr2);
9462 : :
9463 : : /* NB: Make a copy of the data length to avoid changing the original
9464 : : data length by cmpstrnqi patterns. */
9465 : 5704 : length = ix86_zero_extend_to_Pmode (length);
9466 : 5704 : rtx lengthreg = gen_reg_rtx (Pmode);
9467 : 5704 : emit_move_insn (lengthreg, length);
9468 : :
9469 : : /* If we are testing strict equality, we can use known alignment to
9470 : : good advantage. This may be possible with combine, particularly
9471 : : once cc0 is dead. */
9472 : 5704 : if (CONST_INT_P (length))
9473 : : {
9474 : 0 : if (length == const0_rtx)
9475 : : {
9476 : 0 : emit_move_insn (result, const0_rtx);
9477 : 0 : return true;
9478 : : }
9479 : 0 : emit_insn (gen_cmpstrnqi_nz_1 (addr1, addr2, lengthreg, align,
9480 : : src1, src2));
9481 : : }
9482 : : else
9483 : : {
9484 : 5704 : emit_insn (gen_cmp_1 (Pmode, lengthreg, lengthreg));
9485 : 5704 : emit_insn (gen_cmpstrnqi_1 (addr1, addr2, lengthreg, align,
9486 : : src1, src2));
9487 : : }
9488 : :
9489 : 5704 : rtx out = gen_lowpart (QImode, result);
9490 : 5704 : emit_insn (gen_cmpintqi (out));
9491 : 5704 : emit_move_insn (result, gen_rtx_SIGN_EXTEND (SImode, out));
9492 : :
9493 : 5704 : return true;
9494 : : }
9495 : :
9496 : : /* Expand the appropriate insns for doing strlen if not just doing
9497 : : repnz; scasb
9498 : :
9499 : : out = result, initialized with the start address
9500 : : align_rtx = alignment of the address.
9501 : : scratch = scratch register, initialized with the startaddress when
9502 : : not aligned, otherwise undefined
9503 : :
9504 : : This is just the body. It needs the initializations mentioned above and
9505 : : some address computing at the end. These things are done in i386.md. */
9506 : :
9507 : : static void
9508 : 11 : ix86_expand_strlensi_unroll_1 (rtx out, rtx src, rtx align_rtx)
9509 : : {
9510 : 11 : int align;
9511 : 11 : rtx tmp;
9512 : 11 : rtx_code_label *align_2_label = NULL;
9513 : 11 : rtx_code_label *align_3_label = NULL;
9514 : 11 : rtx_code_label *align_4_label = gen_label_rtx ();
9515 : 11 : rtx_code_label *end_0_label = gen_label_rtx ();
9516 : 11 : rtx mem;
9517 : 11 : rtx tmpreg = gen_reg_rtx (SImode);
9518 : 11 : rtx scratch = gen_reg_rtx (SImode);
9519 : 11 : rtx cmp;
9520 : :
9521 : 11 : align = 0;
9522 : 11 : if (CONST_INT_P (align_rtx))
9523 : 11 : align = INTVAL (align_rtx);
9524 : :
9525 : : /* Loop to check 1..3 bytes for null to get an aligned pointer. */
9526 : :
9527 : : /* Is there a known alignment and is it less than 4? */
9528 : 11 : if (align < 4)
9529 : : {
9530 : 11 : rtx scratch1 = gen_reg_rtx (Pmode);
9531 : 11 : emit_move_insn (scratch1, out);
9532 : : /* Is there a known alignment and is it not 2? */
9533 : 11 : if (align != 2)
9534 : : {
9535 : 11 : align_3_label = gen_label_rtx (); /* Label when aligned to 3-byte */
9536 : 11 : align_2_label = gen_label_rtx (); /* Label when aligned to 2-byte */
9537 : :
9538 : : /* Leave just the 3 lower bits. */
9539 : 11 : align_rtx = expand_binop (Pmode, and_optab, scratch1, GEN_INT (3),
9540 : : NULL_RTX, 0, OPTAB_WIDEN);
9541 : :
9542 : 15 : emit_cmp_and_jump_insns (align_rtx, const0_rtx, EQ, NULL,
9543 : 11 : Pmode, 1, align_4_label);
9544 : 15 : emit_cmp_and_jump_insns (align_rtx, const2_rtx, EQ, NULL,
9545 : 11 : Pmode, 1, align_2_label);
9546 : 15 : emit_cmp_and_jump_insns (align_rtx, const2_rtx, GTU, NULL,
9547 : 11 : Pmode, 1, align_3_label);
9548 : : }
9549 : : else
9550 : : {
9551 : : /* Since the alignment is 2, we have to check 2 or 0 bytes;
9552 : : check if is aligned to 4 - byte. */
9553 : :
9554 : 0 : align_rtx = expand_binop (Pmode, and_optab, scratch1, const2_rtx,
9555 : : NULL_RTX, 0, OPTAB_WIDEN);
9556 : :
9557 : 0 : emit_cmp_and_jump_insns (align_rtx, const0_rtx, EQ, NULL,
9558 : 0 : Pmode, 1, align_4_label);
9559 : : }
9560 : :
9561 : 11 : mem = change_address (src, QImode, out);
9562 : :
9563 : : /* Now compare the bytes. */
9564 : :
9565 : : /* Compare the first n unaligned byte on a byte per byte basis. */
9566 : 11 : emit_cmp_and_jump_insns (mem, const0_rtx, EQ, NULL,
9567 : : QImode, 1, end_0_label);
9568 : :
9569 : : /* Increment the address. */
9570 : 11 : emit_insn (gen_add2_insn (out, const1_rtx));
9571 : :
9572 : : /* Not needed with an alignment of 2 */
9573 : 11 : if (align != 2)
9574 : : {
9575 : 11 : emit_label (align_2_label);
9576 : :
9577 : 11 : emit_cmp_and_jump_insns (mem, const0_rtx, EQ, NULL, QImode, 1,
9578 : : end_0_label);
9579 : :
9580 : 11 : emit_insn (gen_add2_insn (out, const1_rtx));
9581 : :
9582 : 11 : emit_label (align_3_label);
9583 : : }
9584 : :
9585 : 11 : emit_cmp_and_jump_insns (mem, const0_rtx, EQ, NULL, QImode, 1,
9586 : : end_0_label);
9587 : :
9588 : 11 : emit_insn (gen_add2_insn (out, const1_rtx));
9589 : : }
9590 : :
9591 : : /* Generate loop to check 4 bytes at a time. It is not a good idea to
9592 : : align this loop. It gives only huge programs, but does not help to
9593 : : speed up. */
9594 : 11 : emit_label (align_4_label);
9595 : :
9596 : 11 : mem = change_address (src, SImode, out);
9597 : 11 : emit_move_insn (scratch, mem);
9598 : 11 : emit_insn (gen_add2_insn (out, GEN_INT (4)));
9599 : :
9600 : : /* This formula yields a nonzero result iff one of the bytes is zero.
9601 : : This saves three branches inside loop and many cycles. */
9602 : :
9603 : 11 : emit_insn (gen_addsi3 (tmpreg, scratch, GEN_INT (-0x01010101)));
9604 : 11 : emit_insn (gen_one_cmplsi2 (scratch, scratch));
9605 : 11 : emit_insn (gen_andsi3 (tmpreg, tmpreg, scratch));
9606 : 11 : emit_insn (gen_andsi3 (tmpreg, tmpreg,
9607 : 11 : gen_int_mode (0x80808080, SImode)));
9608 : 11 : emit_cmp_and_jump_insns (tmpreg, const0_rtx, EQ, 0, SImode, 1,
9609 : : align_4_label);
9610 : :
9611 : 11 : if (TARGET_CMOVE)
9612 : : {
9613 : 11 : rtx reg = gen_reg_rtx (SImode);
9614 : 11 : rtx reg2 = gen_reg_rtx (Pmode);
9615 : 11 : emit_move_insn (reg, tmpreg);
9616 : 11 : emit_insn (gen_lshrsi3 (reg, reg, GEN_INT (16)));
9617 : :
9618 : : /* If zero is not in the first two bytes, move two bytes forward. */
9619 : 11 : emit_insn (gen_testsi_ccno_1 (tmpreg, GEN_INT (0x8080)));
9620 : 11 : tmp = gen_rtx_REG (CCNOmode, FLAGS_REG);
9621 : 11 : tmp = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
9622 : 11 : emit_insn (gen_rtx_SET (tmpreg,
9623 : : gen_rtx_IF_THEN_ELSE (SImode, tmp,
9624 : : reg,
9625 : : tmpreg)));
9626 : : /* Emit lea manually to avoid clobbering of flags. */
9627 : 11 : emit_insn (gen_rtx_SET (reg2, plus_constant (Pmode, out, 2)));
9628 : :
9629 : 11 : tmp = gen_rtx_REG (CCNOmode, FLAGS_REG);
9630 : 11 : tmp = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
9631 : 11 : emit_insn (gen_rtx_SET (out,
9632 : : gen_rtx_IF_THEN_ELSE (Pmode, tmp,
9633 : : reg2,
9634 : : out)));
9635 : 11 : }
9636 : : else
9637 : : {
9638 : 0 : rtx_code_label *end_2_label = gen_label_rtx ();
9639 : : /* Is zero in the first two bytes? */
9640 : :
9641 : 0 : emit_insn (gen_testsi_ccno_1 (tmpreg, GEN_INT (0x8080)));
9642 : 0 : tmp = gen_rtx_REG (CCNOmode, FLAGS_REG);
9643 : 0 : tmp = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
9644 : 0 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
9645 : : gen_rtx_LABEL_REF (VOIDmode, end_2_label),
9646 : : pc_rtx);
9647 : 0 : tmp = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
9648 : 0 : JUMP_LABEL (tmp) = end_2_label;
9649 : :
9650 : : /* Not in the first two. Move two bytes forward. */
9651 : 0 : emit_insn (gen_lshrsi3 (tmpreg, tmpreg, GEN_INT (16)));
9652 : 0 : emit_insn (gen_add2_insn (out, const2_rtx));
9653 : :
9654 : 0 : emit_label (end_2_label);
9655 : :
9656 : : }
9657 : :
9658 : : /* Avoid branch in fixing the byte. */
9659 : 11 : tmpreg = gen_lowpart (QImode, tmpreg);
9660 : 11 : emit_insn (gen_addqi3_cconly_overflow (tmpreg, tmpreg));
9661 : 11 : tmp = gen_rtx_REG (CCmode, FLAGS_REG);
9662 : 11 : cmp = gen_rtx_LTU (VOIDmode, tmp, const0_rtx);
9663 : 11 : emit_insn (gen_sub3_carry (Pmode, out, out, GEN_INT (3), tmp, cmp));
9664 : :
9665 : 11 : emit_label (end_0_label);
9666 : 11 : }
9667 : :
9668 : : /* Expand strlen. */
9669 : :
9670 : : bool
9671 : 13632 : ix86_expand_strlen (rtx out, rtx src, rtx eoschar, rtx align)
9672 : : {
9673 : 13632 : if (TARGET_UNROLL_STRLEN
9674 : 13632 : && TARGET_INLINE_ALL_STRINGOPS
9675 : 11 : && eoschar == const0_rtx
9676 : 11 : && optimize > 1)
9677 : : {
9678 : : /* The generic case of strlen expander is long. Avoid it's
9679 : : expanding unless TARGET_INLINE_ALL_STRINGOPS. */
9680 : 11 : rtx addr = force_reg (Pmode, XEXP (src, 0));
9681 : : /* Well it seems that some optimizer does not combine a call like
9682 : : foo(strlen(bar), strlen(bar));
9683 : : when the move and the subtraction is done here. It does calculate
9684 : : the length just once when these instructions are done inside of
9685 : : output_strlen_unroll(). But I think since &bar[strlen(bar)] is
9686 : : often used and I use one fewer register for the lifetime of
9687 : : output_strlen_unroll() this is better. */
9688 : :
9689 : 11 : emit_move_insn (out, addr);
9690 : :
9691 : 11 : ix86_expand_strlensi_unroll_1 (out, src, align);
9692 : :
9693 : : /* strlensi_unroll_1 returns the address of the zero at the end of
9694 : : the string, like memchr(), so compute the length by subtracting
9695 : : the start address. */
9696 : 11 : emit_insn (gen_sub2_insn (out, addr));
9697 : 11 : return true;
9698 : : }
9699 : : else
9700 : : return false;
9701 : : }
9702 : :
9703 : : /* For given symbol (function) construct code to compute address of it's PLT
9704 : : entry in large x86-64 PIC model. */
9705 : :
9706 : : static rtx
9707 : 34 : construct_plt_address (rtx symbol)
9708 : : {
9709 : 34 : rtx tmp, unspec;
9710 : :
9711 : 34 : gcc_assert (GET_CODE (symbol) == SYMBOL_REF);
9712 : 34 : gcc_assert (ix86_cmodel == CM_LARGE_PIC && !TARGET_PECOFF);
9713 : 34 : gcc_assert (Pmode == DImode);
9714 : :
9715 : 34 : tmp = gen_reg_rtx (Pmode);
9716 : 34 : unspec = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, symbol), UNSPEC_PLTOFF);
9717 : :
9718 : 34 : emit_move_insn (tmp, gen_rtx_CONST (Pmode, unspec));
9719 : 34 : emit_insn (gen_add2_insn (tmp, pic_offset_table_rtx));
9720 : 34 : return tmp;
9721 : : }
9722 : :
9723 : : /* Additional registers that are clobbered by SYSV calls. */
9724 : :
9725 : : static int const x86_64_ms_sysv_extra_clobbered_registers
9726 : : [NUM_X86_64_MS_CLOBBERED_REGS] =
9727 : : {
9728 : : SI_REG, DI_REG,
9729 : : XMM6_REG, XMM7_REG,
9730 : : XMM8_REG, XMM9_REG, XMM10_REG, XMM11_REG,
9731 : : XMM12_REG, XMM13_REG, XMM14_REG, XMM15_REG
9732 : : };
9733 : :
9734 : : rtx_insn *
9735 : 5938586 : ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1,
9736 : : rtx callarg2,
9737 : : rtx pop, bool sibcall)
9738 : : {
9739 : 5938586 : rtx vec[3];
9740 : 5938586 : rtx use = NULL, call;
9741 : 5938586 : unsigned int vec_len = 0;
9742 : 5938586 : tree fndecl;
9743 : 5938586 : bool call_no_callee_saved_registers = false;
9744 : :
9745 : 5938586 : if (GET_CODE (XEXP (fnaddr, 0)) == SYMBOL_REF)
9746 : : {
9747 : 5758426 : fndecl = SYMBOL_REF_DECL (XEXP (fnaddr, 0));
9748 : 5758426 : if (fndecl)
9749 : : {
9750 : 5498641 : if (lookup_attribute ("interrupt",
9751 : 5498641 : TYPE_ATTRIBUTES (TREE_TYPE (fndecl))))
9752 : 1 : error ("interrupt service routine cannot be called directly");
9753 : 5498640 : else if (lookup_attribute ("no_callee_saved_registers",
9754 : 5498640 : TYPE_ATTRIBUTES (TREE_TYPE (fndecl))))
9755 : 10 : call_no_callee_saved_registers = true;
9756 : : }
9757 : : }
9758 : : else
9759 : : {
9760 : 180160 : if (MEM_P (fnaddr))
9761 : : {
9762 : 180160 : tree mem_expr = MEM_EXPR (fnaddr);
9763 : 180160 : if (mem_expr != nullptr
9764 : 180112 : && TREE_CODE (mem_expr) == MEM_REF
9765 : 360272 : && lookup_attribute ("no_callee_saved_registers",
9766 : 180112 : TYPE_ATTRIBUTES (TREE_TYPE (mem_expr))))
9767 : : call_no_callee_saved_registers = true;
9768 : : }
9769 : :
9770 : : fndecl = NULL_TREE;
9771 : : }
9772 : :
9773 : 5938586 : if (pop == const0_rtx)
9774 : 0 : pop = NULL;
9775 : 5938586 : gcc_assert (!TARGET_64BIT || !pop);
9776 : :
9777 : 5938586 : rtx addr = XEXP (fnaddr, 0);
9778 : 5938586 : if (TARGET_MACHO && !TARGET_64BIT)
9779 : : {
9780 : : #if TARGET_MACHO
9781 : : if (flag_pic && GET_CODE (XEXP (fnaddr, 0)) == SYMBOL_REF)
9782 : : fnaddr = machopic_indirect_call_target (fnaddr);
9783 : : #endif
9784 : : }
9785 : : else
9786 : : {
9787 : : /* Static functions and indirect calls don't need the pic register. Also,
9788 : : check if PLT was explicitly avoided via no-plt or "noplt" attribute, making
9789 : : it an indirect call. */
9790 : 5938586 : if (flag_pic
9791 : 515416 : && GET_CODE (addr) == SYMBOL_REF
9792 : 6428068 : && ix86_call_use_plt_p (addr))
9793 : : {
9794 : 393916 : if (flag_plt
9795 : 393916 : && (SYMBOL_REF_DECL (addr) == NULL_TREE
9796 : 393890 : || !lookup_attribute ("noplt",
9797 : 393890 : DECL_ATTRIBUTES (SYMBOL_REF_DECL (addr)))))
9798 : : {
9799 : 393889 : if (!TARGET_64BIT
9800 : 216236 : || (ix86_cmodel == CM_LARGE_PIC
9801 : : && DEFAULT_ABI != MS_ABI))
9802 : : {
9803 : 355340 : use_reg (&use, gen_rtx_REG (Pmode,
9804 : : REAL_PIC_OFFSET_TABLE_REGNUM));
9805 : 177687 : if (ix86_use_pseudo_pic_reg ())
9806 : 177687 : emit_move_insn (gen_rtx_REG (Pmode,
9807 : 177687 : REAL_PIC_OFFSET_TABLE_REGNUM),
9808 : : pic_offset_table_rtx);
9809 : : }
9810 : : }
9811 : 27 : else if (!TARGET_PECOFF && !TARGET_MACHO)
9812 : : {
9813 : 27 : if (TARGET_64BIT
9814 : 27 : && ix86_cmodel == CM_LARGE_PIC
9815 : : && DEFAULT_ABI != MS_ABI)
9816 : : {
9817 : 1 : fnaddr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr),
9818 : : UNSPEC_GOT);
9819 : 1 : fnaddr = gen_rtx_CONST (Pmode, fnaddr);
9820 : 1 : fnaddr = force_reg (Pmode, fnaddr);
9821 : 1 : fnaddr = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, fnaddr);
9822 : : }
9823 : 26 : else if (TARGET_64BIT)
9824 : : {
9825 : 26 : fnaddr = gen_rtx_UNSPEC (Pmode,
9826 : : gen_rtvec (1, addr),
9827 : : UNSPEC_GOTPCREL);
9828 : 26 : fnaddr = gen_rtx_CONST (Pmode, fnaddr);
9829 : : }
9830 : : else
9831 : : {
9832 : 0 : fnaddr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr),
9833 : : UNSPEC_GOT);
9834 : 0 : fnaddr = gen_rtx_CONST (Pmode, fnaddr);
9835 : 0 : fnaddr = gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
9836 : : fnaddr);
9837 : : }
9838 : 27 : fnaddr = gen_const_mem (Pmode, fnaddr);
9839 : : /* Pmode may not be the same as word_mode for x32, which
9840 : : doesn't support indirect branch via 32-bit memory slot.
9841 : : Since x32 GOT slot is 64 bit with zero upper 32 bits,
9842 : : indirect branch via x32 GOT slot is OK. */
9843 : 27 : if (GET_MODE (fnaddr) != word_mode)
9844 : 0 : fnaddr = gen_rtx_ZERO_EXTEND (word_mode, fnaddr);
9845 : 27 : fnaddr = gen_rtx_MEM (QImode, fnaddr);
9846 : : }
9847 : : }
9848 : : }
9849 : :
9850 : : /* Skip setting up RAX register for -mskip-rax-setup when there are no
9851 : : parameters passed in vector registers. */
9852 : 5938586 : if (TARGET_64BIT
9853 : 5106299 : && (INTVAL (callarg2) > 0
9854 : 5045997 : || (INTVAL (callarg2) == 0
9855 : 291256 : && (TARGET_SSE || !flag_skip_rax_setup))))
9856 : : {
9857 : 351556 : rtx al = gen_rtx_REG (QImode, AX_REG);
9858 : 351556 : emit_move_insn (al, callarg2);
9859 : 351556 : use_reg (&use, al);
9860 : : }
9861 : :
9862 : 5938586 : if (ix86_cmodel == CM_LARGE_PIC
9863 : : && !TARGET_PECOFF
9864 : 45 : && MEM_P (fnaddr)
9865 : 45 : && GET_CODE (XEXP (fnaddr, 0)) == SYMBOL_REF
9866 : 5938622 : && !local_symbolic_operand (XEXP (fnaddr, 0), VOIDmode))
9867 : 34 : fnaddr = gen_rtx_MEM (QImode, construct_plt_address (XEXP (fnaddr, 0)));
9868 : : /* Since x32 GOT slot is 64 bit with zero upper 32 bits, indirect
9869 : : branch via x32 GOT slot is OK. */
9870 : 0 : else if (!(TARGET_X32
9871 : 48 : && MEM_P (fnaddr)
9872 : 48 : && GET_CODE (XEXP (fnaddr, 0)) == ZERO_EXTEND
9873 : 0 : && GOT_memory_operand (XEXP (XEXP (fnaddr, 0), 0), Pmode))
9874 : 6054988 : && (sibcall
9875 : 5938552 : ? !sibcall_insn_operand (XEXP (fnaddr, 0), word_mode)
9876 : 5822164 : : !call_insn_operand (XEXP (fnaddr, 0), word_mode)))
9877 : : {
9878 : 518 : fnaddr = convert_to_mode (word_mode, XEXP (fnaddr, 0), 1);
9879 : 518 : fnaddr = gen_rtx_MEM (QImode, copy_to_mode_reg (word_mode, fnaddr));
9880 : : }
9881 : :
9882 : : /* PR100665: Hwasan may tag code pointer which is not supported by LAM,
9883 : : mask off code pointers here.
9884 : : TODO: also need to handle indirect jump. */
9885 : 5939642 : if (ix86_memtag_can_tag_addresses () && !fndecl
9886 : 5938610 : && sanitize_flags_p (SANITIZE_HWADDRESS))
9887 : : {
9888 : 24 : rtx untagged_addr = ix86_memtag_untagged_pointer (XEXP (fnaddr, 0),
9889 : : NULL_RTX);
9890 : 24 : fnaddr = gen_rtx_MEM (QImode, untagged_addr);
9891 : : }
9892 : :
9893 : 5938586 : call = gen_rtx_CALL (VOIDmode, fnaddr, callarg1);
9894 : :
9895 : 5938586 : if (retval)
9896 : 2319802 : call = gen_rtx_SET (retval, call);
9897 : 5938586 : vec[vec_len++] = call;
9898 : :
9899 : 5938586 : if (pop)
9900 : : {
9901 : 224378 : pop = gen_rtx_PLUS (Pmode, stack_pointer_rtx, pop);
9902 : 224378 : pop = gen_rtx_SET (stack_pointer_rtx, pop);
9903 : 224378 : vec[vec_len++] = pop;
9904 : : }
9905 : :
9906 : 5938586 : static const char ix86_call_used_regs[] = CALL_USED_REGISTERS;
9907 : :
9908 : 5938586 : if ((cfun->machine->call_saved_registers
9909 : 5938586 : == TYPE_NO_CALLER_SAVED_REGISTERS)
9910 : 5938586 : && (!fndecl
9911 : 464 : || (!TREE_THIS_VOLATILE (fndecl)
9912 : 182 : && !lookup_attribute ("no_caller_saved_registers",
9913 : 182 : TYPE_ATTRIBUTES (TREE_TYPE (fndecl))))))
9914 : : {
9915 : 173 : bool is_64bit_ms_abi = (TARGET_64BIT
9916 : 173 : && ix86_function_abi (fndecl) == MS_ABI);
9917 : 173 : char c_mask = CALL_USED_REGISTERS_MASK (is_64bit_ms_abi);
9918 : :
9919 : : /* If there are no caller-saved registers, add all registers
9920 : : that are clobbered by the call which returns. */
9921 : 16089 : for (int i = 0; i < FIRST_PSEUDO_REGISTER; i++)
9922 : 15916 : if (!fixed_regs[i]
9923 : 2979 : && (ix86_call_used_regs[i] == 1
9924 : 1384 : || (ix86_call_used_regs[i] & c_mask))
9925 : 1941 : && !STACK_REGNO_P (i)
9926 : 1941 : && !MMX_REGNO_P (i))
9927 : 1941 : clobber_reg (&use,
9928 : 1941 : gen_rtx_REG (GET_MODE (regno_reg_rtx[i]), i));
9929 : : }
9930 : 5106126 : else if (TARGET_64BIT_MS_ABI
9931 : 6011816 : && (!callarg2 || INTVAL (callarg2) != -2))
9932 : : {
9933 : : unsigned i;
9934 : :
9935 : 861705 : for (i = 0; i < NUM_X86_64_MS_CLOBBERED_REGS; i++)
9936 : : {
9937 : 795420 : int regno = x86_64_ms_sysv_extra_clobbered_registers[i];
9938 : 795420 : machine_mode mode = SSE_REGNO_P (regno) ? TImode : DImode;
9939 : :
9940 : 795420 : clobber_reg (&use, gen_rtx_REG (mode, regno));
9941 : : }
9942 : :
9943 : : /* Set here, but it may get cleared later. */
9944 : 66285 : if (TARGET_CALL_MS2SYSV_XLOGUES)
9945 : : {
9946 : 7046 : if (!TARGET_SSE)
9947 : : ;
9948 : :
9949 : : /* Don't break hot-patched functions. */
9950 : 7046 : else if (ix86_function_ms_hook_prologue (current_function_decl))
9951 : : ;
9952 : :
9953 : : /* TODO: Cases not yet examined. */
9954 : 7046 : else if (flag_split_stack)
9955 : 0 : warn_once_call_ms2sysv_xlogues ("-fsplit-stack");
9956 : :
9957 : : else
9958 : : {
9959 : 7046 : gcc_assert (!reload_completed);
9960 : 7046 : cfun->machine->call_ms2sysv = true;
9961 : : }
9962 : : }
9963 : : }
9964 : :
9965 : 5938586 : if (TARGET_MACHO && TARGET_64BIT && !sibcall
9966 : : && ((GET_CODE (addr) == SYMBOL_REF && !SYMBOL_REF_LOCAL_P (addr))
9967 : : || !fndecl || TREE_PUBLIC (fndecl)))
9968 : : {
9969 : : /* We allow public functions defined in a TU to bind locally for PIC
9970 : : code (the default) on 64bit Mach-O.
9971 : : If such functions are not inlined, we cannot tell at compile-time if
9972 : : they will be called via the lazy symbol resolver (this can depend on
9973 : : options given at link-time). Therefore, we must assume that the lazy
9974 : : resolver could be used which clobbers R11 and R10. */
9975 : : clobber_reg (&use, gen_rtx_REG (DImode, R11_REG));
9976 : : clobber_reg (&use, gen_rtx_REG (DImode, R10_REG));
9977 : : }
9978 : :
9979 : 5938586 : if (call_no_callee_saved_registers)
9980 : : {
9981 : : /* After calling a no_callee_saved_registers function, all
9982 : : registers may be clobbered. Clobber all registers that are
9983 : : not used by the callee. */
9984 : 17 : bool is_64bit_ms_abi = (TARGET_64BIT
9985 : 17 : && ix86_function_abi (fndecl) == MS_ABI);
9986 : 17 : char c_mask = CALL_USED_REGISTERS_MASK (is_64bit_ms_abi);
9987 : 1581 : for (int i = 0; i < FIRST_PSEUDO_REGISTER; i++)
9988 : 1564 : if (!fixed_regs[i]
9989 : 767 : && !(ix86_call_used_regs[i] == 1
9990 : 296 : || (ix86_call_used_regs[i] & c_mask))
9991 : 102 : && !STACK_REGNO_P (i)
9992 : 102 : && !MMX_REGNO_P (i))
9993 : 102 : clobber_reg (&use,
9994 : 102 : gen_rtx_REG (GET_MODE (regno_reg_rtx[i]), i));
9995 : : }
9996 : :
9997 : 5938586 : if (vec_len > 1)
9998 : 224378 : call = gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (vec_len, vec));
9999 : 5938586 : rtx_insn *call_insn = emit_call_insn (call);
10000 : 5938586 : if (use)
10001 : 568087 : CALL_INSN_FUNCTION_USAGE (call_insn) = use;
10002 : :
10003 : 5938586 : return call_insn;
10004 : : }
10005 : :
10006 : : /* Split simple return with popping POPC bytes from stack to indirect
10007 : : branch with stack adjustment . */
10008 : :
10009 : : void
10010 : 0 : ix86_split_simple_return_pop_internal (rtx popc)
10011 : : {
10012 : 0 : struct machine_function *m = cfun->machine;
10013 : 0 : rtx ecx = gen_rtx_REG (SImode, CX_REG);
10014 : 0 : rtx_insn *insn;
10015 : :
10016 : : /* There is no "pascal" calling convention in any 64bit ABI. */
10017 : 0 : gcc_assert (!TARGET_64BIT);
10018 : :
10019 : 0 : insn = emit_insn (gen_pop (ecx));
10020 : 0 : m->fs.cfa_offset -= UNITS_PER_WORD;
10021 : 0 : m->fs.sp_offset -= UNITS_PER_WORD;
10022 : :
10023 : 0 : rtx x = plus_constant (Pmode, stack_pointer_rtx, UNITS_PER_WORD);
10024 : 0 : x = gen_rtx_SET (stack_pointer_rtx, x);
10025 : 0 : add_reg_note (insn, REG_CFA_ADJUST_CFA, x);
10026 : 0 : add_reg_note (insn, REG_CFA_REGISTER, gen_rtx_SET (ecx, pc_rtx));
10027 : 0 : RTX_FRAME_RELATED_P (insn) = 1;
10028 : :
10029 : 0 : x = gen_rtx_PLUS (Pmode, stack_pointer_rtx, popc);
10030 : 0 : x = gen_rtx_SET (stack_pointer_rtx, x);
10031 : 0 : insn = emit_insn (x);
10032 : 0 : add_reg_note (insn, REG_CFA_ADJUST_CFA, x);
10033 : 0 : RTX_FRAME_RELATED_P (insn) = 1;
10034 : :
10035 : : /* Now return address is in ECX. */
10036 : 0 : emit_jump_insn (gen_simple_return_indirect_internal (ecx));
10037 : 0 : }
10038 : :
10039 : : /* Errors in the source file can cause expand_expr to return const0_rtx
10040 : : where we expect a vector. To avoid crashing, use one of the vector
10041 : : clear instructions. */
10042 : :
10043 : : static rtx
10044 : 174304 : safe_vector_operand (rtx x, machine_mode mode)
10045 : : {
10046 : 0 : if (x == const0_rtx)
10047 : 0 : x = CONST0_RTX (mode);
10048 : 24 : return x;
10049 : : }
10050 : :
10051 : : /* Subroutine of ix86_expand_builtin to take care of binop insns. */
10052 : :
10053 : : static rtx
10054 : 8941 : ix86_expand_binop_builtin (enum insn_code icode, tree exp, rtx target)
10055 : : {
10056 : 8941 : rtx pat;
10057 : 8941 : tree arg0 = CALL_EXPR_ARG (exp, 0);
10058 : 8941 : tree arg1 = CALL_EXPR_ARG (exp, 1);
10059 : 8941 : rtx op0 = expand_normal (arg0);
10060 : 8941 : rtx op1 = expand_normal (arg1);
10061 : 8941 : machine_mode tmode = insn_data[icode].operand[0].mode;
10062 : 8941 : machine_mode mode0 = insn_data[icode].operand[1].mode;
10063 : 8941 : machine_mode mode1 = insn_data[icode].operand[2].mode;
10064 : :
10065 : 8941 : if (VECTOR_MODE_P (mode0))
10066 : 8936 : op0 = safe_vector_operand (op0, mode0);
10067 : 8941 : if (VECTOR_MODE_P (mode1))
10068 : 8800 : op1 = safe_vector_operand (op1, mode1);
10069 : :
10070 : 2736 : if (optimize || !target
10071 : 2736 : || GET_MODE (target) != tmode
10072 : 11677 : || !insn_data[icode].operand[0].predicate (target, tmode))
10073 : 6258 : target = gen_reg_rtx (tmode);
10074 : :
10075 : 8941 : if (GET_MODE (op1) == SImode && mode1 == TImode)
10076 : : {
10077 : 0 : rtx x = gen_reg_rtx (V4SImode);
10078 : 0 : emit_insn (gen_sse2_loadd (x, op1));
10079 : 0 : op1 = gen_lowpart (TImode, x);
10080 : : }
10081 : :
10082 : 8941 : if (!insn_data[icode].operand[1].predicate (op0, mode0))
10083 : 1313 : op0 = copy_to_mode_reg (mode0, op0);
10084 : 8941 : if (!insn_data[icode].operand[2].predicate (op1, mode1))
10085 : 828 : op1 = copy_to_mode_reg (mode1, op1);
10086 : :
10087 : 8941 : pat = GEN_FCN (icode) (target, op0, op1);
10088 : 8941 : if (! pat)
10089 : : return 0;
10090 : :
10091 : 8941 : emit_insn (pat);
10092 : :
10093 : 8941 : return target;
10094 : : }
10095 : :
10096 : : /* Subroutine of ix86_expand_builtin to take care of 2-4 argument insns. */
10097 : :
10098 : : static rtx
10099 : 1793 : ix86_expand_multi_arg_builtin (enum insn_code icode, tree exp, rtx target,
10100 : : enum ix86_builtin_func_type m_type,
10101 : : enum rtx_code sub_code)
10102 : : {
10103 : 1793 : rtx pat;
10104 : 1793 : unsigned int i, nargs;
10105 : 1793 : bool comparison_p = false;
10106 : 1793 : bool tf_p = false;
10107 : 1793 : bool last_arg_constant = false;
10108 : 1793 : int num_memory = 0;
10109 : 1793 : rtx xops[4];
10110 : :
10111 : 1793 : machine_mode tmode = insn_data[icode].operand[0].mode;
10112 : :
10113 : 1793 : switch (m_type)
10114 : : {
10115 : : case MULTI_ARG_4_DF2_DI_I:
10116 : : case MULTI_ARG_4_DF2_DI_I1:
10117 : : case MULTI_ARG_4_SF2_SI_I:
10118 : : case MULTI_ARG_4_SF2_SI_I1:
10119 : : nargs = 4;
10120 : : last_arg_constant = true;
10121 : : break;
10122 : :
10123 : 816 : case MULTI_ARG_3_SF:
10124 : 816 : case MULTI_ARG_3_DF:
10125 : 816 : case MULTI_ARG_3_SF2:
10126 : 816 : case MULTI_ARG_3_DF2:
10127 : 816 : case MULTI_ARG_3_DI:
10128 : 816 : case MULTI_ARG_3_SI:
10129 : 816 : case MULTI_ARG_3_SI_DI:
10130 : 816 : case MULTI_ARG_3_HI:
10131 : 816 : case MULTI_ARG_3_HI_SI:
10132 : 816 : case MULTI_ARG_3_QI:
10133 : 816 : case MULTI_ARG_3_DI2:
10134 : 816 : case MULTI_ARG_3_SI2:
10135 : 816 : case MULTI_ARG_3_HI2:
10136 : 816 : case MULTI_ARG_3_QI2:
10137 : 816 : nargs = 3;
10138 : 816 : break;
10139 : :
10140 : 128 : case MULTI_ARG_2_SF:
10141 : 128 : case MULTI_ARG_2_DF:
10142 : 128 : case MULTI_ARG_2_DI:
10143 : 128 : case MULTI_ARG_2_SI:
10144 : 128 : case MULTI_ARG_2_HI:
10145 : 128 : case MULTI_ARG_2_QI:
10146 : 128 : nargs = 2;
10147 : 128 : break;
10148 : :
10149 : 64 : case MULTI_ARG_2_DI_IMM:
10150 : 64 : case MULTI_ARG_2_SI_IMM:
10151 : 64 : case MULTI_ARG_2_HI_IMM:
10152 : 64 : case MULTI_ARG_2_QI_IMM:
10153 : 64 : nargs = 2;
10154 : 64 : last_arg_constant = true;
10155 : 64 : break;
10156 : :
10157 : 185 : case MULTI_ARG_1_SF:
10158 : 185 : case MULTI_ARG_1_DF:
10159 : 185 : case MULTI_ARG_1_SF2:
10160 : 185 : case MULTI_ARG_1_DF2:
10161 : 185 : case MULTI_ARG_1_DI:
10162 : 185 : case MULTI_ARG_1_SI:
10163 : 185 : case MULTI_ARG_1_HI:
10164 : 185 : case MULTI_ARG_1_QI:
10165 : 185 : case MULTI_ARG_1_SI_DI:
10166 : 185 : case MULTI_ARG_1_HI_DI:
10167 : 185 : case MULTI_ARG_1_HI_SI:
10168 : 185 : case MULTI_ARG_1_QI_DI:
10169 : 185 : case MULTI_ARG_1_QI_SI:
10170 : 185 : case MULTI_ARG_1_QI_HI:
10171 : 185 : nargs = 1;
10172 : 185 : break;
10173 : :
10174 : 384 : case MULTI_ARG_2_DI_CMP:
10175 : 384 : case MULTI_ARG_2_SI_CMP:
10176 : 384 : case MULTI_ARG_2_HI_CMP:
10177 : 384 : case MULTI_ARG_2_QI_CMP:
10178 : 384 : nargs = 2;
10179 : 384 : comparison_p = true;
10180 : 384 : break;
10181 : :
10182 : 128 : case MULTI_ARG_2_SF_TF:
10183 : 128 : case MULTI_ARG_2_DF_TF:
10184 : 128 : case MULTI_ARG_2_DI_TF:
10185 : 128 : case MULTI_ARG_2_SI_TF:
10186 : 128 : case MULTI_ARG_2_HI_TF:
10187 : 128 : case MULTI_ARG_2_QI_TF:
10188 : 128 : nargs = 2;
10189 : 128 : tf_p = true;
10190 : 128 : break;
10191 : :
10192 : 0 : default:
10193 : 0 : gcc_unreachable ();
10194 : : }
10195 : :
10196 : 632 : if (optimize || !target
10197 : 632 : || GET_MODE (target) != tmode
10198 : 2401 : || !insn_data[icode].operand[0].predicate (target, tmode))
10199 : 1185 : target = gen_reg_rtx (tmode);
10200 : 608 : else if (memory_operand (target, tmode))
10201 : 0 : num_memory++;
10202 : :
10203 : 1793 : gcc_assert (nargs <= ARRAY_SIZE (xops));
10204 : :
10205 : 6178 : for (i = 0; i < nargs; i++)
10206 : : {
10207 : 4393 : tree arg = CALL_EXPR_ARG (exp, i);
10208 : 4393 : rtx op = expand_normal (arg);
10209 : 4393 : int adjust = (comparison_p) ? 1 : 0;
10210 : 4393 : machine_mode mode = insn_data[icode].operand[i+adjust+1].mode;
10211 : :
10212 : 4393 : if (last_arg_constant && i == nargs - 1)
10213 : : {
10214 : 152 : if (!insn_data[icode].operand[i + 1].predicate (op, mode))
10215 : : {
10216 : 30 : enum insn_code new_icode = icode;
10217 : 30 : switch (icode)
10218 : : {
10219 : 8 : case CODE_FOR_xop_vpermil2v2df3:
10220 : 8 : case CODE_FOR_xop_vpermil2v4sf3:
10221 : 8 : case CODE_FOR_xop_vpermil2v4df3:
10222 : 8 : case CODE_FOR_xop_vpermil2v8sf3:
10223 : 8 : error ("the last argument must be a 2-bit immediate");
10224 : 8 : return gen_reg_rtx (tmode);
10225 : 5 : case CODE_FOR_xop_rotlv2di3:
10226 : 5 : new_icode = CODE_FOR_rotlv2di3;
10227 : 5 : goto xop_rotl;
10228 : 5 : case CODE_FOR_xop_rotlv4si3:
10229 : 5 : new_icode = CODE_FOR_rotlv4si3;
10230 : 5 : goto xop_rotl;
10231 : 6 : case CODE_FOR_xop_rotlv8hi3:
10232 : 6 : new_icode = CODE_FOR_rotlv8hi3;
10233 : 6 : goto xop_rotl;
10234 : : case CODE_FOR_xop_rotlv16qi3:
10235 : : new_icode = CODE_FOR_rotlv16qi3;
10236 : 22 : xop_rotl:
10237 : 22 : if (CONST_INT_P (op))
10238 : : {
10239 : 6 : int mask = GET_MODE_UNIT_BITSIZE (tmode) - 1;
10240 : 6 : op = GEN_INT (INTVAL (op) & mask);
10241 : 6 : gcc_checking_assert
10242 : : (insn_data[icode].operand[i + 1].predicate (op, mode));
10243 : : }
10244 : : else
10245 : : {
10246 : 16 : gcc_checking_assert
10247 : : (nargs == 2
10248 : : && insn_data[new_icode].operand[0].mode == tmode
10249 : : && insn_data[new_icode].operand[1].mode == tmode
10250 : : && insn_data[new_icode].operand[2].mode == mode
10251 : : && insn_data[new_icode].operand[0].predicate
10252 : : == insn_data[icode].operand[0].predicate
10253 : : && insn_data[new_icode].operand[1].predicate
10254 : : == insn_data[icode].operand[1].predicate);
10255 : 16 : icode = new_icode;
10256 : 16 : goto non_constant;
10257 : : }
10258 : : break;
10259 : 0 : default:
10260 : 0 : gcc_unreachable ();
10261 : : }
10262 : : }
10263 : : }
10264 : : else
10265 : : {
10266 : 4241 : non_constant:
10267 : 4257 : if (VECTOR_MODE_P (mode))
10268 : 4241 : op = safe_vector_operand (op, mode);
10269 : :
10270 : : /* If we aren't optimizing, only allow one memory operand to be
10271 : : generated. */
10272 : 4257 : if (memory_operand (op, mode))
10273 : 826 : num_memory++;
10274 : :
10275 : 4257 : gcc_assert (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode);
10276 : :
10277 : 4257 : if (optimize
10278 : 1518 : || !insn_data[icode].operand[i+adjust+1].predicate (op, mode)
10279 : 5665 : || num_memory > 1)
10280 : 3356 : op = force_reg (mode, op);
10281 : : }
10282 : :
10283 : 4385 : xops[i] = op;
10284 : : }
10285 : :
10286 : 1785 : switch (nargs)
10287 : : {
10288 : 185 : case 1:
10289 : 185 : pat = GEN_FCN (icode) (target, xops[0]);
10290 : 185 : break;
10291 : :
10292 : 704 : case 2:
10293 : 704 : if (tf_p)
10294 : 128 : pat = GEN_FCN (icode) (target, xops[0], xops[1],
10295 : 128 : GEN_INT ((int)sub_code));
10296 : 576 : else if (! comparison_p)
10297 : 192 : pat = GEN_FCN (icode) (target, xops[0], xops[1]);
10298 : : else
10299 : : {
10300 : 384 : rtx cmp_op = gen_rtx_fmt_ee (sub_code, GET_MODE (target),
10301 : : xops[0], xops[1]);
10302 : :
10303 : 384 : pat = GEN_FCN (icode) (target, cmp_op, xops[0], xops[1]);
10304 : : }
10305 : : break;
10306 : :
10307 : 816 : case 3:
10308 : 816 : pat = GEN_FCN (icode) (target, xops[0], xops[1], xops[2]);
10309 : 816 : break;
10310 : :
10311 : 80 : case 4:
10312 : 80 : pat = GEN_FCN (icode) (target, xops[0], xops[1], xops[2], xops[3]);
10313 : 80 : break;
10314 : :
10315 : : default:
10316 : : gcc_unreachable ();
10317 : : }
10318 : :
10319 : 1785 : if (! pat)
10320 : : return 0;
10321 : :
10322 : 1785 : emit_insn (pat);
10323 : 1785 : return target;
10324 : : }
10325 : :
10326 : : /* Subroutine of ix86_expand_args_builtin to take care of scalar unop
10327 : : insns with vec_merge. */
10328 : :
10329 : : static rtx
10330 : 52 : ix86_expand_unop_vec_merge_builtin (enum insn_code icode, tree exp,
10331 : : rtx target)
10332 : : {
10333 : 52 : rtx pat;
10334 : 52 : tree arg0 = CALL_EXPR_ARG (exp, 0);
10335 : 52 : rtx op1, op0 = expand_normal (arg0);
10336 : 52 : machine_mode tmode = insn_data[icode].operand[0].mode;
10337 : 52 : machine_mode mode0 = insn_data[icode].operand[1].mode;
10338 : :
10339 : 16 : if (optimize || !target
10340 : 16 : || GET_MODE (target) != tmode
10341 : 68 : || !insn_data[icode].operand[0].predicate (target, tmode))
10342 : 36 : target = gen_reg_rtx (tmode);
10343 : :
10344 : 52 : if (VECTOR_MODE_P (mode0))
10345 : 52 : op0 = safe_vector_operand (op0, mode0);
10346 : :
10347 : 36 : if ((optimize && !register_operand (op0, mode0))
10348 : 88 : || !insn_data[icode].operand[1].predicate (op0, mode0))
10349 : 0 : op0 = copy_to_mode_reg (mode0, op0);
10350 : :
10351 : 52 : op1 = op0;
10352 : 52 : if (!insn_data[icode].operand[2].predicate (op1, mode0))
10353 : 16 : op1 = copy_to_mode_reg (mode0, op1);
10354 : :
10355 : 52 : pat = GEN_FCN (icode) (target, op0, op1);
10356 : 52 : if (! pat)
10357 : : return 0;
10358 : 52 : emit_insn (pat);
10359 : 52 : return target;
10360 : : }
10361 : :
10362 : : /* Subroutine of ix86_expand_builtin to take care of comparison insns. */
10363 : :
10364 : : static rtx
10365 : 609 : ix86_expand_sse_compare (const struct builtin_description *d,
10366 : : tree exp, rtx target, bool swap)
10367 : : {
10368 : 609 : rtx pat;
10369 : 609 : tree arg0 = CALL_EXPR_ARG (exp, 0);
10370 : 609 : tree arg1 = CALL_EXPR_ARG (exp, 1);
10371 : 609 : rtx op0 = expand_normal (arg0);
10372 : 609 : rtx op1 = expand_normal (arg1);
10373 : 609 : rtx op2;
10374 : 609 : machine_mode tmode = insn_data[d->icode].operand[0].mode;
10375 : 609 : machine_mode mode0 = insn_data[d->icode].operand[1].mode;
10376 : 609 : machine_mode mode1 = insn_data[d->icode].operand[2].mode;
10377 : 609 : enum rtx_code comparison = d->comparison;
10378 : :
10379 : 609 : if (VECTOR_MODE_P (mode0))
10380 : 609 : op0 = safe_vector_operand (op0, mode0);
10381 : 609 : if (VECTOR_MODE_P (mode1))
10382 : 609 : op1 = safe_vector_operand (op1, mode1);
10383 : :
10384 : : /* Swap operands if we have a comparison that isn't available in
10385 : : hardware. */
10386 : 609 : if (swap)
10387 : 80 : std::swap (op0, op1);
10388 : :
10389 : 202 : if (optimize || !target
10390 : 202 : || GET_MODE (target) != tmode
10391 : 811 : || !insn_data[d->icode].operand[0].predicate (target, tmode))
10392 : 407 : target = gen_reg_rtx (tmode);
10393 : :
10394 : 407 : if ((optimize && !register_operand (op0, mode0))
10395 : 917 : || !insn_data[d->icode].operand[1].predicate (op0, mode0))
10396 : 301 : op0 = copy_to_mode_reg (mode0, op0);
10397 : 407 : if ((optimize && !register_operand (op1, mode1))
10398 : 928 : || !insn_data[d->icode].operand[2].predicate (op1, mode1))
10399 : 88 : op1 = copy_to_mode_reg (mode1, op1);
10400 : :
10401 : 609 : op2 = gen_rtx_fmt_ee (comparison, mode0, op0, op1);
10402 : 609 : pat = GEN_FCN (d->icode) (target, op0, op1, op2);
10403 : 609 : if (! pat)
10404 : : return 0;
10405 : 609 : emit_insn (pat);
10406 : 609 : return target;
10407 : : }
10408 : :
10409 : : /* Subroutine of ix86_sse_comi and ix86_sse_comi_round to take care of
10410 : : * ordered EQ or unordered NE, generate PF jump. */
10411 : :
10412 : : static rtx
10413 : 560 : ix86_ssecom_setcc (const enum rtx_code comparison,
10414 : : bool check_unordered, machine_mode mode,
10415 : : rtx set_dst, rtx target)
10416 : : {
10417 : :
10418 : 560 : rtx_code_label *label = NULL;
10419 : :
10420 : : /* NB: For ordered EQ or unordered NE, check ZF alone isn't sufficient
10421 : : with NAN operands. */
10422 : 560 : if (check_unordered)
10423 : : {
10424 : 154 : gcc_assert (comparison == EQ || comparison == NE);
10425 : :
10426 : 154 : rtx flag = gen_rtx_REG (CCFPmode, FLAGS_REG);
10427 : 154 : label = gen_label_rtx ();
10428 : 154 : rtx tmp = gen_rtx_fmt_ee (UNORDERED, VOIDmode, flag, const0_rtx);
10429 : 154 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
10430 : : gen_rtx_LABEL_REF (VOIDmode, label),
10431 : : pc_rtx);
10432 : 154 : emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
10433 : : }
10434 : :
10435 : : /* NB: Set CCFPmode and check a different CCmode which is in subset
10436 : : of CCFPmode. */
10437 : 560 : if (GET_MODE (set_dst) != mode)
10438 : : {
10439 : 170 : gcc_assert (mode == CCAmode || mode == CCCmode
10440 : : || mode == CCOmode || mode == CCPmode
10441 : : || mode == CCSmode || mode == CCZmode);
10442 : 170 : set_dst = gen_rtx_REG (mode, FLAGS_REG);
10443 : : }
10444 : :
10445 : 560 : emit_insn (gen_rtx_SET (gen_rtx_STRICT_LOW_PART (VOIDmode, target),
10446 : : gen_rtx_fmt_ee (comparison, QImode,
10447 : : set_dst,
10448 : : const0_rtx)));
10449 : :
10450 : 560 : if (label)
10451 : 154 : emit_label (label);
10452 : :
10453 : 560 : return SUBREG_REG (target);
10454 : : }
10455 : :
10456 : : /* Subroutine of ix86_expand_builtin to take care of comi insns. */
10457 : :
10458 : : static rtx
10459 : 473 : ix86_expand_sse_comi (const struct builtin_description *d, tree exp,
10460 : : rtx target)
10461 : : {
10462 : 473 : rtx pat, set_dst;
10463 : 473 : tree arg0 = CALL_EXPR_ARG (exp, 0);
10464 : 473 : tree arg1 = CALL_EXPR_ARG (exp, 1);
10465 : 473 : rtx op0 = expand_normal (arg0);
10466 : 473 : rtx op1 = expand_normal (arg1);
10467 : 473 : enum insn_code icode = d->icode;
10468 : 473 : const struct insn_data_d *insn_p = &insn_data[icode];
10469 : 473 : machine_mode mode0 = insn_p->operand[0].mode;
10470 : 473 : machine_mode mode1 = insn_p->operand[1].mode;
10471 : :
10472 : 473 : if (VECTOR_MODE_P (mode0))
10473 : 473 : op0 = safe_vector_operand (op0, mode0);
10474 : 473 : if (VECTOR_MODE_P (mode1))
10475 : 473 : op1 = safe_vector_operand (op1, mode1);
10476 : :
10477 : 473 : enum rtx_code comparison = d->comparison;
10478 : 473 : rtx const_val = const0_rtx;
10479 : :
10480 : 473 : bool check_unordered = false;
10481 : 473 : machine_mode mode = CCFPmode;
10482 : 473 : switch (comparison)
10483 : : {
10484 : 168 : case LE: /* -> GE */
10485 : 168 : case LT: /* -> GT */
10486 : 168 : std::swap (op0, op1);
10487 : 168 : comparison = swap_condition (comparison);
10488 : : /* FALLTHRU */
10489 : : case GT:
10490 : : case GE:
10491 : : break;
10492 : 61 : case EQ:
10493 : 61 : check_unordered = true;
10494 : 61 : mode = CCZmode;
10495 : 61 : break;
10496 : 84 : case NE:
10497 : 84 : check_unordered = true;
10498 : 84 : mode = CCZmode;
10499 : 84 : const_val = const1_rtx;
10500 : 84 : break;
10501 : 0 : default:
10502 : 0 : gcc_unreachable ();
10503 : : }
10504 : :
10505 : 473 : target = gen_reg_rtx (SImode);
10506 : 473 : emit_move_insn (target, const_val);
10507 : 473 : target = gen_rtx_SUBREG (QImode, target, 0);
10508 : :
10509 : 376 : if ((optimize && !register_operand (op0, mode0))
10510 : 801 : || !insn_p->operand[0].predicate (op0, mode0))
10511 : 145 : op0 = copy_to_mode_reg (mode0, op0);
10512 : 376 : if ((optimize && !register_operand (op1, mode1))
10513 : 801 : || !insn_p->operand[1].predicate (op1, mode1))
10514 : 48 : op1 = copy_to_mode_reg (mode1, op1);
10515 : :
10516 : 473 : pat = GEN_FCN (icode) (op0, op1);
10517 : 473 : if (! pat)
10518 : : return 0;
10519 : :
10520 : 473 : set_dst = SET_DEST (pat);
10521 : 473 : emit_insn (pat);
10522 : 473 : return ix86_ssecom_setcc (comparison, check_unordered, mode,
10523 : 473 : set_dst, target);
10524 : : }
10525 : :
10526 : : /* Subroutines of ix86_expand_args_builtin to take care of round insns. */
10527 : :
10528 : : static rtx
10529 : 0 : ix86_expand_sse_round (const struct builtin_description *d, tree exp,
10530 : : rtx target)
10531 : : {
10532 : 0 : rtx pat;
10533 : 0 : tree arg0 = CALL_EXPR_ARG (exp, 0);
10534 : 0 : rtx op1, op0 = expand_normal (arg0);
10535 : 0 : machine_mode tmode = insn_data[d->icode].operand[0].mode;
10536 : 0 : machine_mode mode0 = insn_data[d->icode].operand[1].mode;
10537 : :
10538 : 0 : if (optimize || target == 0
10539 : 0 : || GET_MODE (target) != tmode
10540 : 0 : || !insn_data[d->icode].operand[0].predicate (target, tmode))
10541 : 0 : target = gen_reg_rtx (tmode);
10542 : :
10543 : 0 : if (VECTOR_MODE_P (mode0))
10544 : 0 : op0 = safe_vector_operand (op0, mode0);
10545 : :
10546 : 0 : if ((optimize && !register_operand (op0, mode0))
10547 : 0 : || !insn_data[d->icode].operand[0].predicate (op0, mode0))
10548 : 0 : op0 = copy_to_mode_reg (mode0, op0);
10549 : :
10550 : 0 : op1 = GEN_INT (d->comparison);
10551 : :
10552 : 0 : pat = GEN_FCN (d->icode) (target, op0, op1);
10553 : 0 : if (! pat)
10554 : : return 0;
10555 : 0 : emit_insn (pat);
10556 : 0 : return target;
10557 : : }
10558 : :
10559 : : static rtx
10560 : 12 : ix86_expand_sse_round_vec_pack_sfix (const struct builtin_description *d,
10561 : : tree exp, rtx target)
10562 : : {
10563 : 12 : rtx pat;
10564 : 12 : tree arg0 = CALL_EXPR_ARG (exp, 0);
10565 : 12 : tree arg1 = CALL_EXPR_ARG (exp, 1);
10566 : 12 : rtx op0 = expand_normal (arg0);
10567 : 12 : rtx op1 = expand_normal (arg1);
10568 : 12 : rtx op2;
10569 : 12 : machine_mode tmode = insn_data[d->icode].operand[0].mode;
10570 : 12 : machine_mode mode0 = insn_data[d->icode].operand[1].mode;
10571 : 12 : machine_mode mode1 = insn_data[d->icode].operand[2].mode;
10572 : :
10573 : 0 : if (optimize || target == 0
10574 : 0 : || GET_MODE (target) != tmode
10575 : 12 : || !insn_data[d->icode].operand[0].predicate (target, tmode))
10576 : 12 : target = gen_reg_rtx (tmode);
10577 : :
10578 : 12 : op0 = safe_vector_operand (op0, mode0);
10579 : 12 : op1 = safe_vector_operand (op1, mode1);
10580 : :
10581 : 12 : if ((optimize && !register_operand (op0, mode0))
10582 : 12 : || !insn_data[d->icode].operand[0].predicate (op0, mode0))
10583 : 12 : op0 = copy_to_mode_reg (mode0, op0);
10584 : 12 : if ((optimize && !register_operand (op1, mode1))
10585 : 12 : || !insn_data[d->icode].operand[1].predicate (op1, mode1))
10586 : 12 : op1 = copy_to_mode_reg (mode1, op1);
10587 : :
10588 : 12 : op2 = GEN_INT (d->comparison);
10589 : :
10590 : 12 : pat = GEN_FCN (d->icode) (target, op0, op1, op2);
10591 : 12 : if (! pat)
10592 : : return 0;
10593 : 12 : emit_insn (pat);
10594 : 12 : return target;
10595 : : }
10596 : :
10597 : : /* Subroutine of ix86_expand_builtin to take care of ptest insns. */
10598 : :
10599 : : static rtx
10600 : 235 : ix86_expand_sse_ptest (const struct builtin_description *d, tree exp,
10601 : : rtx target)
10602 : : {
10603 : 235 : rtx pat;
10604 : 235 : tree arg0 = CALL_EXPR_ARG (exp, 0);
10605 : 235 : tree arg1 = CALL_EXPR_ARG (exp, 1);
10606 : 235 : rtx op0 = expand_normal (arg0);
10607 : 235 : rtx op1 = expand_normal (arg1);
10608 : 235 : machine_mode mode0 = insn_data[d->icode].operand[0].mode;
10609 : 235 : machine_mode mode1 = insn_data[d->icode].operand[1].mode;
10610 : 235 : enum rtx_code comparison = d->comparison;
10611 : :
10612 : : /* ptest reg, reg sets the carry flag. */
10613 : 235 : if (comparison == LTU
10614 : 75 : && (d->code == IX86_BUILTIN_PTESTC
10615 : 57 : || d->code == IX86_BUILTIN_PTESTC256)
10616 : 266 : && rtx_equal_p (op0, op1))
10617 : : {
10618 : 2 : if (!target)
10619 : 0 : target = gen_reg_rtx (SImode);
10620 : 2 : emit_move_insn (target, const1_rtx);
10621 : 2 : return target;
10622 : : }
10623 : :
10624 : 233 : if (VECTOR_MODE_P (mode0))
10625 : 233 : op0 = safe_vector_operand (op0, mode0);
10626 : 233 : if (VECTOR_MODE_P (mode1))
10627 : 233 : op1 = safe_vector_operand (op1, mode1);
10628 : :
10629 : 233 : target = gen_reg_rtx (SImode);
10630 : 233 : emit_move_insn (target, const0_rtx);
10631 : 233 : target = gen_rtx_SUBREG (QImode, target, 0);
10632 : :
10633 : 161 : if ((optimize && !register_operand (op0, mode0))
10634 : 366 : || !insn_data[d->icode].operand[0].predicate (op0, mode0))
10635 : 100 : op0 = copy_to_mode_reg (mode0, op0);
10636 : 161 : if ((optimize && !register_operand (op1, mode1))
10637 : 367 : || !insn_data[d->icode].operand[1].predicate (op1, mode1))
10638 : 27 : op1 = copy_to_mode_reg (mode1, op1);
10639 : :
10640 : 233 : pat = GEN_FCN (d->icode) (op0, op1);
10641 : 233 : if (! pat)
10642 : : return 0;
10643 : 233 : emit_insn (pat);
10644 : 233 : emit_insn (gen_rtx_SET (gen_rtx_STRICT_LOW_PART (VOIDmode, target),
10645 : : gen_rtx_fmt_ee (comparison, QImode,
10646 : : SET_DEST (pat),
10647 : : const0_rtx)));
10648 : :
10649 : 233 : return SUBREG_REG (target);
10650 : : }
10651 : :
10652 : : /* Subroutine of ix86_expand_builtin to take care of pcmpestr[im] insns. */
10653 : :
10654 : : static rtx
10655 : 216 : ix86_expand_sse_pcmpestr (const struct builtin_description *d,
10656 : : tree exp, rtx target)
10657 : : {
10658 : 216 : rtx pat;
10659 : 216 : tree arg0 = CALL_EXPR_ARG (exp, 0);
10660 : 216 : tree arg1 = CALL_EXPR_ARG (exp, 1);
10661 : 216 : tree arg2 = CALL_EXPR_ARG (exp, 2);
10662 : 216 : tree arg3 = CALL_EXPR_ARG (exp, 3);
10663 : 216 : tree arg4 = CALL_EXPR_ARG (exp, 4);
10664 : 216 : rtx scratch0, scratch1;
10665 : 216 : rtx op0 = expand_normal (arg0);
10666 : 216 : rtx op1 = expand_normal (arg1);
10667 : 216 : rtx op2 = expand_normal (arg2);
10668 : 216 : rtx op3 = expand_normal (arg3);
10669 : 216 : rtx op4 = expand_normal (arg4);
10670 : 216 : machine_mode tmode0, tmode1, modev2, modei3, modev4, modei5, modeimm;
10671 : :
10672 : 216 : tmode0 = insn_data[d->icode].operand[0].mode;
10673 : 216 : tmode1 = insn_data[d->icode].operand[1].mode;
10674 : 216 : modev2 = insn_data[d->icode].operand[2].mode;
10675 : 216 : modei3 = insn_data[d->icode].operand[3].mode;
10676 : 216 : modev4 = insn_data[d->icode].operand[4].mode;
10677 : 216 : modei5 = insn_data[d->icode].operand[5].mode;
10678 : 216 : modeimm = insn_data[d->icode].operand[6].mode;
10679 : :
10680 : 216 : if (VECTOR_MODE_P (modev2))
10681 : 216 : op0 = safe_vector_operand (op0, modev2);
10682 : 216 : if (VECTOR_MODE_P (modev4))
10683 : 216 : op2 = safe_vector_operand (op2, modev4);
10684 : :
10685 : 216 : if (!insn_data[d->icode].operand[2].predicate (op0, modev2))
10686 : 6 : op0 = copy_to_mode_reg (modev2, op0);
10687 : 216 : if (!insn_data[d->icode].operand[3].predicate (op1, modei3))
10688 : 34 : op1 = copy_to_mode_reg (modei3, op1);
10689 : 160 : if ((optimize && !register_operand (op2, modev4))
10690 : 371 : || !insn_data[d->icode].operand[4].predicate (op2, modev4))
10691 : 5 : op2 = copy_to_mode_reg (modev4, op2);
10692 : 216 : if (!insn_data[d->icode].operand[5].predicate (op3, modei5))
10693 : 34 : op3 = copy_to_mode_reg (modei5, op3);
10694 : :
10695 : 216 : if (!insn_data[d->icode].operand[6].predicate (op4, modeimm))
10696 : : {
10697 : 21 : error ("the fifth argument must be an 8-bit immediate");
10698 : 21 : return const0_rtx;
10699 : : }
10700 : :
10701 : 195 : if (d->code == IX86_BUILTIN_PCMPESTRI128)
10702 : : {
10703 : 5 : if (optimize || !target
10704 : 5 : || GET_MODE (target) != tmode0
10705 : 34 : || !insn_data[d->icode].operand[0].predicate (target, tmode0))
10706 : 24 : target = gen_reg_rtx (tmode0);
10707 : :
10708 : 29 : scratch1 = gen_reg_rtx (tmode1);
10709 : :
10710 : 29 : pat = GEN_FCN (d->icode) (target, scratch1, op0, op1, op2, op3, op4);
10711 : : }
10712 : 166 : else if (d->code == IX86_BUILTIN_PCMPESTRM128)
10713 : : {
10714 : 5 : if (optimize || !target
10715 : 5 : || GET_MODE (target) != tmode1
10716 : 36 : || !insn_data[d->icode].operand[1].predicate (target, tmode1))
10717 : 26 : target = gen_reg_rtx (tmode1);
10718 : :
10719 : 31 : scratch0 = gen_reg_rtx (tmode0);
10720 : :
10721 : 31 : pat = GEN_FCN (d->icode) (scratch0, target, op0, op1, op2, op3, op4);
10722 : : }
10723 : : else
10724 : : {
10725 : 135 : gcc_assert (d->flag);
10726 : :
10727 : 135 : scratch0 = gen_reg_rtx (tmode0);
10728 : 135 : scratch1 = gen_reg_rtx (tmode1);
10729 : :
10730 : 135 : pat = GEN_FCN (d->icode) (scratch0, scratch1, op0, op1, op2, op3, op4);
10731 : : }
10732 : :
10733 : 195 : if (! pat)
10734 : : return 0;
10735 : :
10736 : 195 : emit_insn (pat);
10737 : :
10738 : 195 : if (d->flag)
10739 : : {
10740 : 135 : target = gen_reg_rtx (SImode);
10741 : 135 : emit_move_insn (target, const0_rtx);
10742 : 135 : target = gen_rtx_SUBREG (QImode, target, 0);
10743 : :
10744 : 135 : emit_insn
10745 : 135 : (gen_rtx_SET (gen_rtx_STRICT_LOW_PART (VOIDmode, target),
10746 : : gen_rtx_fmt_ee (EQ, QImode,
10747 : : gen_rtx_REG ((machine_mode) d->flag,
10748 : : FLAGS_REG),
10749 : : const0_rtx)));
10750 : 135 : return SUBREG_REG (target);
10751 : : }
10752 : : else
10753 : : return target;
10754 : : }
10755 : :
10756 : :
10757 : : /* Subroutine of ix86_expand_builtin to take care of pcmpistr[im] insns. */
10758 : :
10759 : : static rtx
10760 : 275 : ix86_expand_sse_pcmpistr (const struct builtin_description *d,
10761 : : tree exp, rtx target)
10762 : : {
10763 : 275 : rtx pat;
10764 : 275 : tree arg0 = CALL_EXPR_ARG (exp, 0);
10765 : 275 : tree arg1 = CALL_EXPR_ARG (exp, 1);
10766 : 275 : tree arg2 = CALL_EXPR_ARG (exp, 2);
10767 : 275 : rtx scratch0, scratch1;
10768 : 275 : rtx op0 = expand_normal (arg0);
10769 : 275 : rtx op1 = expand_normal (arg1);
10770 : 275 : rtx op2 = expand_normal (arg2);
10771 : 275 : machine_mode tmode0, tmode1, modev2, modev3, modeimm;
10772 : :
10773 : 275 : tmode0 = insn_data[d->icode].operand[0].mode;
10774 : 275 : tmode1 = insn_data[d->icode].operand[1].mode;
10775 : 275 : modev2 = insn_data[d->icode].operand[2].mode;
10776 : 275 : modev3 = insn_data[d->icode].operand[3].mode;
10777 : 275 : modeimm = insn_data[d->icode].operand[4].mode;
10778 : :
10779 : 275 : if (VECTOR_MODE_P (modev2))
10780 : 275 : op0 = safe_vector_operand (op0, modev2);
10781 : 275 : if (VECTOR_MODE_P (modev3))
10782 : 275 : op1 = safe_vector_operand (op1, modev3);
10783 : :
10784 : 275 : if (!insn_data[d->icode].operand[2].predicate (op0, modev2))
10785 : 4 : op0 = copy_to_mode_reg (modev2, op0);
10786 : 210 : if ((optimize && !register_operand (op1, modev3))
10787 : 481 : || !insn_data[d->icode].operand[3].predicate (op1, modev3))
10788 : 4 : op1 = copy_to_mode_reg (modev3, op1);
10789 : :
10790 : 275 : if (!insn_data[d->icode].operand[4].predicate (op2, modeimm))
10791 : : {
10792 : 21 : error ("the third argument must be an 8-bit immediate");
10793 : 21 : return const0_rtx;
10794 : : }
10795 : :
10796 : 254 : if (d->code == IX86_BUILTIN_PCMPISTRI128)
10797 : : {
10798 : 5 : if (optimize || !target
10799 : 5 : || GET_MODE (target) != tmode0
10800 : 38 : || !insn_data[d->icode].operand[0].predicate (target, tmode0))
10801 : 28 : target = gen_reg_rtx (tmode0);
10802 : :
10803 : 33 : scratch1 = gen_reg_rtx (tmode1);
10804 : :
10805 : 33 : pat = GEN_FCN (d->icode) (target, scratch1, op0, op1, op2);
10806 : : }
10807 : 221 : else if (d->code == IX86_BUILTIN_PCMPISTRM128)
10808 : : {
10809 : 8 : if (optimize || !target
10810 : 8 : || GET_MODE (target) != tmode1
10811 : 58 : || !insn_data[d->icode].operand[1].predicate (target, tmode1))
10812 : 42 : target = gen_reg_rtx (tmode1);
10813 : :
10814 : 50 : scratch0 = gen_reg_rtx (tmode0);
10815 : :
10816 : 50 : pat = GEN_FCN (d->icode) (scratch0, target, op0, op1, op2);
10817 : : }
10818 : : else
10819 : : {
10820 : 171 : gcc_assert (d->flag);
10821 : :
10822 : 171 : scratch0 = gen_reg_rtx (tmode0);
10823 : 171 : scratch1 = gen_reg_rtx (tmode1);
10824 : :
10825 : 171 : pat = GEN_FCN (d->icode) (scratch0, scratch1, op0, op1, op2);
10826 : : }
10827 : :
10828 : 254 : if (! pat)
10829 : : return 0;
10830 : :
10831 : 254 : emit_insn (pat);
10832 : :
10833 : 254 : if (d->flag)
10834 : : {
10835 : 171 : target = gen_reg_rtx (SImode);
10836 : 171 : emit_move_insn (target, const0_rtx);
10837 : 171 : target = gen_rtx_SUBREG (QImode, target, 0);
10838 : :
10839 : 171 : emit_insn
10840 : 171 : (gen_rtx_SET (gen_rtx_STRICT_LOW_PART (VOIDmode, target),
10841 : : gen_rtx_fmt_ee (EQ, QImode,
10842 : : gen_rtx_REG ((machine_mode) d->flag,
10843 : : FLAGS_REG),
10844 : : const0_rtx)));
10845 : 171 : return SUBREG_REG (target);
10846 : : }
10847 : : else
10848 : : return target;
10849 : : }
10850 : :
10851 : : /* Fixup modeless constants to fit required mode. */
10852 : :
10853 : : static rtx
10854 : 209737 : fixup_modeless_constant (rtx x, machine_mode mode)
10855 : : {
10856 : 209737 : if (GET_MODE (x) == VOIDmode)
10857 : 20994 : x = convert_to_mode (mode, x, 1);
10858 : 209737 : return x;
10859 : : }
10860 : :
10861 : : /* Subroutine of ix86_expand_builtin to take care of insns with
10862 : : variable number of operands. */
10863 : :
10864 : : static rtx
10865 : 61362 : ix86_expand_args_builtin (const struct builtin_description *d,
10866 : : tree exp, rtx target)
10867 : : {
10868 : 61362 : rtx pat, real_target;
10869 : 61362 : unsigned int i, nargs;
10870 : 61362 : unsigned int nargs_constant = 0;
10871 : 61362 : unsigned int mask_pos = 0;
10872 : 61362 : int num_memory = 0;
10873 : 61362 : rtx xops[6];
10874 : 61362 : bool second_arg_count = false;
10875 : 61362 : enum insn_code icode = d->icode;
10876 : 61362 : const struct insn_data_d *insn_p = &insn_data[icode];
10877 : 61362 : machine_mode tmode = insn_p->operand[0].mode;
10878 : 61362 : machine_mode rmode = VOIDmode;
10879 : 61362 : bool swap = false;
10880 : 61362 : enum rtx_code comparison = d->comparison;
10881 : :
10882 : 61362 : switch ((enum ix86_builtin_func_type) d->flag)
10883 : : {
10884 : 0 : case V2DF_FTYPE_V2DF_ROUND:
10885 : 0 : case V4DF_FTYPE_V4DF_ROUND:
10886 : 0 : case V8DF_FTYPE_V8DF_ROUND:
10887 : 0 : case V4SF_FTYPE_V4SF_ROUND:
10888 : 0 : case V8SF_FTYPE_V8SF_ROUND:
10889 : 0 : case V16SF_FTYPE_V16SF_ROUND:
10890 : 0 : case V8HF_FTYPE_V8HF_ROUND:
10891 : 0 : case V16HF_FTYPE_V16HF_ROUND:
10892 : 0 : case V32HF_FTYPE_V32HF_ROUND:
10893 : 0 : case V4SI_FTYPE_V4SF_ROUND:
10894 : 0 : case V8SI_FTYPE_V8SF_ROUND:
10895 : 0 : case V16SI_FTYPE_V16SF_ROUND:
10896 : 0 : return ix86_expand_sse_round (d, exp, target);
10897 : 12 : case V4SI_FTYPE_V2DF_V2DF_ROUND:
10898 : 12 : case V8SI_FTYPE_V4DF_V4DF_ROUND:
10899 : 12 : case V16SI_FTYPE_V8DF_V8DF_ROUND:
10900 : 12 : return ix86_expand_sse_round_vec_pack_sfix (d, exp, target);
10901 : 235 : case INT_FTYPE_V8SF_V8SF_PTEST:
10902 : 235 : case INT_FTYPE_V4DI_V4DI_PTEST:
10903 : 235 : case INT_FTYPE_V4DF_V4DF_PTEST:
10904 : 235 : case INT_FTYPE_V4SF_V4SF_PTEST:
10905 : 235 : case INT_FTYPE_V2DI_V2DI_PTEST:
10906 : 235 : case INT_FTYPE_V2DF_V2DF_PTEST:
10907 : 235 : return ix86_expand_sse_ptest (d, exp, target);
10908 : : case FLOAT128_FTYPE_FLOAT128:
10909 : : case FLOAT_FTYPE_FLOAT:
10910 : : case FLOAT_FTYPE_BFLOAT16:
10911 : : case INT_FTYPE_INT:
10912 : : case UINT_FTYPE_UINT:
10913 : : case UINT16_FTYPE_UINT16:
10914 : : case UINT64_FTYPE_INT:
10915 : : case UINT64_FTYPE_UINT64:
10916 : : case INT64_FTYPE_INT64:
10917 : : case INT64_FTYPE_V4SF:
10918 : : case INT64_FTYPE_V2DF:
10919 : : case INT_FTYPE_V16QI:
10920 : : case INT_FTYPE_V8QI:
10921 : : case INT_FTYPE_V8SF:
10922 : : case INT_FTYPE_V4DF:
10923 : : case INT_FTYPE_V4SF:
10924 : : case INT_FTYPE_V2DF:
10925 : : case INT_FTYPE_V32QI:
10926 : : case V16QI_FTYPE_V16QI:
10927 : : case V8SI_FTYPE_V8SF:
10928 : : case V8SI_FTYPE_V4SI:
10929 : : case V8HI_FTYPE_V8HI:
10930 : : case V8HI_FTYPE_V16QI:
10931 : : case V8QI_FTYPE_V8QI:
10932 : : case V8SF_FTYPE_V8SF:
10933 : : case V8SF_FTYPE_V8SI:
10934 : : case V8SF_FTYPE_V4SF:
10935 : : case V8SF_FTYPE_V8HI:
10936 : : case V4SI_FTYPE_V4SI:
10937 : : case V4SI_FTYPE_V16QI:
10938 : : case V4SI_FTYPE_V4SF:
10939 : : case V4SI_FTYPE_V8SI:
10940 : : case V4SI_FTYPE_V8HI:
10941 : : case V4SI_FTYPE_V4DF:
10942 : : case V4SI_FTYPE_V2DF:
10943 : : case V4HI_FTYPE_V4HI:
10944 : : case V4DF_FTYPE_V4DF:
10945 : : case V4DF_FTYPE_V4SI:
10946 : : case V4DF_FTYPE_V4SF:
10947 : : case V4DF_FTYPE_V2DF:
10948 : : case V4SF_FTYPE_V4SF:
10949 : : case V4SF_FTYPE_V4SI:
10950 : : case V4SF_FTYPE_V8SF:
10951 : : case V4SF_FTYPE_V4DF:
10952 : : case V4SF_FTYPE_V8HI:
10953 : : case V4SF_FTYPE_V2DF:
10954 : : case V2DI_FTYPE_V2DI:
10955 : : case V2DI_FTYPE_V16QI:
10956 : : case V2DI_FTYPE_V8HI:
10957 : : case V2DI_FTYPE_V4SI:
10958 : : case V2DF_FTYPE_V2DF:
10959 : : case V2DF_FTYPE_V4SI:
10960 : : case V2DF_FTYPE_V4DF:
10961 : : case V2DF_FTYPE_V4SF:
10962 : : case V2DF_FTYPE_V2SI:
10963 : : case V2SI_FTYPE_V2SI:
10964 : : case V2SI_FTYPE_V4SF:
10965 : : case V2SI_FTYPE_V2SF:
10966 : : case V2SI_FTYPE_V2DF:
10967 : : case V2SF_FTYPE_V2SF:
10968 : : case V2SF_FTYPE_V2SI:
10969 : : case V32QI_FTYPE_V32QI:
10970 : : case V32QI_FTYPE_V16QI:
10971 : : case V16HI_FTYPE_V16HI:
10972 : : case V16HI_FTYPE_V8HI:
10973 : : case V8SI_FTYPE_V8SI:
10974 : : case V16HI_FTYPE_V16QI:
10975 : : case V8SI_FTYPE_V16QI:
10976 : : case V4DI_FTYPE_V16QI:
10977 : : case V8SI_FTYPE_V8HI:
10978 : : case V4DI_FTYPE_V8HI:
10979 : : case V4DI_FTYPE_V4SI:
10980 : : case V4DI_FTYPE_V2DI:
10981 : : case UQI_FTYPE_UQI:
10982 : : case UHI_FTYPE_UHI:
10983 : : case USI_FTYPE_USI:
10984 : : case USI_FTYPE_UQI:
10985 : : case USI_FTYPE_UHI:
10986 : : case UDI_FTYPE_UDI:
10987 : : case UHI_FTYPE_V16QI:
10988 : : case USI_FTYPE_V32QI:
10989 : : case UDI_FTYPE_V64QI:
10990 : : case V16QI_FTYPE_UHI:
10991 : : case V32QI_FTYPE_USI:
10992 : : case V64QI_FTYPE_UDI:
10993 : : case V8HI_FTYPE_UQI:
10994 : : case V16HI_FTYPE_UHI:
10995 : : case V32HI_FTYPE_USI:
10996 : : case V4SI_FTYPE_UQI:
10997 : : case V8SI_FTYPE_UQI:
10998 : : case V4SI_FTYPE_UHI:
10999 : : case V8SI_FTYPE_UHI:
11000 : : case UQI_FTYPE_V8HI:
11001 : : case UHI_FTYPE_V16HI:
11002 : : case USI_FTYPE_V32HI:
11003 : : case UQI_FTYPE_V4SI:
11004 : : case UQI_FTYPE_V8SI:
11005 : : case UHI_FTYPE_V16SI:
11006 : : case UQI_FTYPE_V2DI:
11007 : : case UQI_FTYPE_V4DI:
11008 : : case UQI_FTYPE_V8DI:
11009 : : case V16SI_FTYPE_UHI:
11010 : : case V2DI_FTYPE_UQI:
11011 : : case V4DI_FTYPE_UQI:
11012 : : case V16SI_FTYPE_INT:
11013 : : case V16SF_FTYPE_V8SF:
11014 : : case V16SI_FTYPE_V8SI:
11015 : : case V16SF_FTYPE_V4SF:
11016 : : case V16SI_FTYPE_V4SI:
11017 : : case V16SI_FTYPE_V16SF:
11018 : : case V16SI_FTYPE_V16SI:
11019 : : case V64QI_FTYPE_V64QI:
11020 : : case V32HI_FTYPE_V32HI:
11021 : : case V16SF_FTYPE_V16SF:
11022 : : case V8DI_FTYPE_UQI:
11023 : : case V8DI_FTYPE_V8DI:
11024 : : case V8DF_FTYPE_V4DF:
11025 : : case V8DF_FTYPE_V2DF:
11026 : : case V8DF_FTYPE_V8DF:
11027 : : case V4DI_FTYPE_V4DI:
11028 : : case V16BF_FTYPE_V16SF:
11029 : : case V8BF_FTYPE_V8SF:
11030 : : case V8BF_FTYPE_V4SF:
11031 : : nargs = 1;
11032 : : break;
11033 : 52 : case V4SF_FTYPE_V4SF_VEC_MERGE:
11034 : 52 : case V2DF_FTYPE_V2DF_VEC_MERGE:
11035 : 52 : return ix86_expand_unop_vec_merge_builtin (icode, exp, target);
11036 : 9470 : case FLOAT128_FTYPE_FLOAT128_FLOAT128:
11037 : 9470 : case V16QI_FTYPE_V16QI_V16QI:
11038 : 9470 : case V16QI_FTYPE_V8HI_V8HI:
11039 : 9470 : case V16HF_FTYPE_V16HF_V16HF:
11040 : 9470 : case V16SF_FTYPE_V16SF_V16SF:
11041 : 9470 : case V8QI_FTYPE_V8QI_V8QI:
11042 : 9470 : case V8QI_FTYPE_V4HI_V4HI:
11043 : 9470 : case V8HI_FTYPE_V8HI_V8HI:
11044 : 9470 : case V8HI_FTYPE_V16QI_V16QI:
11045 : 9470 : case V8HI_FTYPE_V4SI_V4SI:
11046 : 9470 : case V8HF_FTYPE_V8HF_V8HF:
11047 : 9470 : case V8SF_FTYPE_V8SF_V8SF:
11048 : 9470 : case V8SF_FTYPE_V8SF_V8SI:
11049 : 9470 : case V8DF_FTYPE_V8DF_V8DF:
11050 : 9470 : case V4SI_FTYPE_V4SI_V4SI:
11051 : 9470 : case V4SI_FTYPE_V8HI_V8HI:
11052 : 9470 : case V4SI_FTYPE_V2DF_V2DF:
11053 : 9470 : case V4HI_FTYPE_V4HI_V4HI:
11054 : 9470 : case V4HI_FTYPE_V8QI_V8QI:
11055 : 9470 : case V4HI_FTYPE_V2SI_V2SI:
11056 : 9470 : case V4DF_FTYPE_V4DF_V4DF:
11057 : 9470 : case V4DF_FTYPE_V4DF_V4DI:
11058 : 9470 : case V4SF_FTYPE_V4SF_V4SF:
11059 : 9470 : case V4SF_FTYPE_V4SF_V4SI:
11060 : 9470 : case V4SF_FTYPE_V4SF_V2SI:
11061 : 9470 : case V4SF_FTYPE_V4SF_V2DF:
11062 : 9470 : case V4SF_FTYPE_V4SF_UINT:
11063 : 9470 : case V4SF_FTYPE_V4SF_DI:
11064 : 9470 : case V4SF_FTYPE_V4SF_SI:
11065 : 9470 : case V4DI_FTYPE_V4DI_V2DI:
11066 : 9470 : case V2DI_FTYPE_V2DI_V2DI:
11067 : 9470 : case V2DI_FTYPE_V16QI_V16QI:
11068 : 9470 : case V2DI_FTYPE_V4SI_V4SI:
11069 : 9470 : case V2DI_FTYPE_V2DI_V16QI:
11070 : 9470 : case V2SI_FTYPE_V2SI_V2SI:
11071 : 9470 : case V2SI_FTYPE_V4HI_V4HI:
11072 : 9470 : case V2SI_FTYPE_V2SF_V2SF:
11073 : 9470 : case V2DF_FTYPE_V2DF_V2DF:
11074 : 9470 : case V2DF_FTYPE_V2DF_V4SF:
11075 : 9470 : case V2DF_FTYPE_V2DF_V2DI:
11076 : 9470 : case V2DF_FTYPE_V2DF_DI:
11077 : 9470 : case V2DF_FTYPE_V2DF_SI:
11078 : 9470 : case V2DF_FTYPE_V2DF_UINT:
11079 : 9470 : case V2SF_FTYPE_V2SF_V2SF:
11080 : 9470 : case V1DI_FTYPE_V1DI_V1DI:
11081 : 9470 : case V1DI_FTYPE_V8QI_V8QI:
11082 : 9470 : case V1DI_FTYPE_V2SI_V2SI:
11083 : 9470 : case V32QI_FTYPE_V16HI_V16HI:
11084 : 9470 : case V16HI_FTYPE_V8SI_V8SI:
11085 : 9470 : case V64QI_FTYPE_V64QI_V64QI:
11086 : 9470 : case V32QI_FTYPE_V32QI_V32QI:
11087 : 9470 : case V16HI_FTYPE_V32QI_V32QI:
11088 : 9470 : case V16HI_FTYPE_V16HI_V16HI:
11089 : 9470 : case V8SI_FTYPE_V4DF_V4DF:
11090 : 9470 : case V8SI_FTYPE_V8SI_V8SI:
11091 : 9470 : case V8SI_FTYPE_V16HI_V16HI:
11092 : 9470 : case V4DI_FTYPE_V4DI_V4DI:
11093 : 9470 : case V4DI_FTYPE_V8SI_V8SI:
11094 : 9470 : case V4DI_FTYPE_V32QI_V32QI:
11095 : 9470 : case V8DI_FTYPE_V64QI_V64QI:
11096 : 9470 : if (comparison == UNKNOWN)
11097 : 8941 : return ix86_expand_binop_builtin (icode, exp, target);
11098 : : nargs = 2;
11099 : : break;
11100 : 80 : case V4SF_FTYPE_V4SF_V4SF_SWAP:
11101 : 80 : case V2DF_FTYPE_V2DF_V2DF_SWAP:
11102 : 80 : gcc_assert (comparison != UNKNOWN);
11103 : : nargs = 2;
11104 : : swap = true;
11105 : : break;
11106 : 1423 : case V16HI_FTYPE_V16HI_V8HI_COUNT:
11107 : 1423 : case V16HI_FTYPE_V16HI_SI_COUNT:
11108 : 1423 : case V8SI_FTYPE_V8SI_V4SI_COUNT:
11109 : 1423 : case V8SI_FTYPE_V8SI_SI_COUNT:
11110 : 1423 : case V4DI_FTYPE_V4DI_V2DI_COUNT:
11111 : 1423 : case V4DI_FTYPE_V4DI_INT_COUNT:
11112 : 1423 : case V8HI_FTYPE_V8HI_V8HI_COUNT:
11113 : 1423 : case V8HI_FTYPE_V8HI_SI_COUNT:
11114 : 1423 : case V4SI_FTYPE_V4SI_V4SI_COUNT:
11115 : 1423 : case V4SI_FTYPE_V4SI_SI_COUNT:
11116 : 1423 : case V4HI_FTYPE_V4HI_V4HI_COUNT:
11117 : 1423 : case V4HI_FTYPE_V4HI_SI_COUNT:
11118 : 1423 : case V2DI_FTYPE_V2DI_V2DI_COUNT:
11119 : 1423 : case V2DI_FTYPE_V2DI_SI_COUNT:
11120 : 1423 : case V2SI_FTYPE_V2SI_V2SI_COUNT:
11121 : 1423 : case V2SI_FTYPE_V2SI_SI_COUNT:
11122 : 1423 : case V1DI_FTYPE_V1DI_V1DI_COUNT:
11123 : 1423 : case V1DI_FTYPE_V1DI_SI_COUNT:
11124 : 1423 : nargs = 2;
11125 : 1423 : second_arg_count = true;
11126 : 1423 : break;
11127 : 1351 : case V16HI_FTYPE_V16HI_INT_V16HI_UHI_COUNT:
11128 : 1351 : case V16HI_FTYPE_V16HI_V8HI_V16HI_UHI_COUNT:
11129 : 1351 : case V16SI_FTYPE_V16SI_INT_V16SI_UHI_COUNT:
11130 : 1351 : case V16SI_FTYPE_V16SI_V4SI_V16SI_UHI_COUNT:
11131 : 1351 : case V2DI_FTYPE_V2DI_INT_V2DI_UQI_COUNT:
11132 : 1351 : case V2DI_FTYPE_V2DI_V2DI_V2DI_UQI_COUNT:
11133 : 1351 : case V32HI_FTYPE_V32HI_INT_V32HI_USI_COUNT:
11134 : 1351 : case V32HI_FTYPE_V32HI_V8HI_V32HI_USI_COUNT:
11135 : 1351 : case V4DI_FTYPE_V4DI_INT_V4DI_UQI_COUNT:
11136 : 1351 : case V4DI_FTYPE_V4DI_V2DI_V4DI_UQI_COUNT:
11137 : 1351 : case V4SI_FTYPE_V4SI_INT_V4SI_UQI_COUNT:
11138 : 1351 : case V4SI_FTYPE_V4SI_V4SI_V4SI_UQI_COUNT:
11139 : 1351 : case V8DI_FTYPE_V8DI_INT_V8DI_UQI_COUNT:
11140 : 1351 : case V8DI_FTYPE_V8DI_V2DI_V8DI_UQI_COUNT:
11141 : 1351 : case V8HI_FTYPE_V8HI_INT_V8HI_UQI_COUNT:
11142 : 1351 : case V8HI_FTYPE_V8HI_V8HI_V8HI_UQI_COUNT:
11143 : 1351 : case V8SI_FTYPE_V8SI_INT_V8SI_UQI_COUNT:
11144 : 1351 : case V8SI_FTYPE_V8SI_V4SI_V8SI_UQI_COUNT:
11145 : 1351 : nargs = 4;
11146 : 1351 : second_arg_count = true;
11147 : 1351 : break;
11148 : 912 : case UINT64_FTYPE_UINT64_UINT64:
11149 : 912 : case UINT_FTYPE_UINT_UINT:
11150 : 912 : case UINT_FTYPE_UINT_USHORT:
11151 : 912 : case UINT_FTYPE_UINT_UCHAR:
11152 : 912 : case UINT16_FTYPE_UINT16_INT:
11153 : 912 : case UINT8_FTYPE_UINT8_INT:
11154 : 912 : case UQI_FTYPE_UQI_UQI:
11155 : 912 : case UHI_FTYPE_UHI_UHI:
11156 : 912 : case USI_FTYPE_USI_USI:
11157 : 912 : case UDI_FTYPE_UDI_UDI:
11158 : 912 : case V16SI_FTYPE_V8DF_V8DF:
11159 : 912 : case V32BF_FTYPE_V16SF_V16SF:
11160 : 912 : case V16BF_FTYPE_V8SF_V8SF:
11161 : 912 : case V8BF_FTYPE_V4SF_V4SF:
11162 : 912 : case V16BF_FTYPE_V16SF_UHI:
11163 : 912 : case V8BF_FTYPE_V8SF_UQI:
11164 : 912 : case V8BF_FTYPE_V4SF_UQI:
11165 : 912 : nargs = 2;
11166 : 912 : break;
11167 : 679 : case V2DI_FTYPE_V2DI_INT_CONVERT:
11168 : 679 : nargs = 2;
11169 : 679 : rmode = V1TImode;
11170 : 679 : nargs_constant = 1;
11171 : 679 : break;
11172 : 42 : case V4DI_FTYPE_V4DI_INT_CONVERT:
11173 : 42 : nargs = 2;
11174 : 42 : rmode = V2TImode;
11175 : 42 : nargs_constant = 1;
11176 : 42 : break;
11177 : 16 : case V8DI_FTYPE_V8DI_INT_CONVERT:
11178 : 16 : nargs = 2;
11179 : 16 : rmode = V4TImode;
11180 : 16 : nargs_constant = 1;
11181 : 16 : break;
11182 : 2382 : case V8HI_FTYPE_V8HI_INT:
11183 : 2382 : case V8HI_FTYPE_V8SF_INT:
11184 : 2382 : case V16HI_FTYPE_V16SF_INT:
11185 : 2382 : case V8HI_FTYPE_V4SF_INT:
11186 : 2382 : case V8SF_FTYPE_V8SF_INT:
11187 : 2382 : case V4SF_FTYPE_V16SF_INT:
11188 : 2382 : case V16SF_FTYPE_V16SF_INT:
11189 : 2382 : case V4SI_FTYPE_V4SI_INT:
11190 : 2382 : case V4SI_FTYPE_V8SI_INT:
11191 : 2382 : case V4HI_FTYPE_V4HI_INT:
11192 : 2382 : case V4DF_FTYPE_V4DF_INT:
11193 : 2382 : case V4DF_FTYPE_V8DF_INT:
11194 : 2382 : case V4SF_FTYPE_V4SF_INT:
11195 : 2382 : case V4SF_FTYPE_V8SF_INT:
11196 : 2382 : case V2DI_FTYPE_V2DI_INT:
11197 : 2382 : case V2DF_FTYPE_V2DF_INT:
11198 : 2382 : case V2DF_FTYPE_V4DF_INT:
11199 : 2382 : case V16HI_FTYPE_V16HI_INT:
11200 : 2382 : case V8SI_FTYPE_V8SI_INT:
11201 : 2382 : case V16SI_FTYPE_V16SI_INT:
11202 : 2382 : case V4SI_FTYPE_V16SI_INT:
11203 : 2382 : case V4DI_FTYPE_V4DI_INT:
11204 : 2382 : case V2DI_FTYPE_V4DI_INT:
11205 : 2382 : case V4DI_FTYPE_V8DI_INT:
11206 : 2382 : case UQI_FTYPE_UQI_UQI_CONST:
11207 : 2382 : case UHI_FTYPE_UHI_UQI:
11208 : 2382 : case USI_FTYPE_USI_UQI:
11209 : 2382 : case UDI_FTYPE_UDI_UQI:
11210 : 2382 : nargs = 2;
11211 : 2382 : nargs_constant = 1;
11212 : 2382 : break;
11213 : 15029 : case V16QI_FTYPE_V16QI_V16QI_V16QI:
11214 : 15029 : case V8SF_FTYPE_V8SF_V8SF_V8SF:
11215 : 15029 : case V4DF_FTYPE_V4DF_V4DF_V4DF:
11216 : 15029 : case V4SF_FTYPE_V4SF_V4SF_V4SF:
11217 : 15029 : case V2DF_FTYPE_V2DF_V2DF_V2DF:
11218 : 15029 : case V32QI_FTYPE_V32QI_V32QI_V32QI:
11219 : 15029 : case UHI_FTYPE_V16SI_V16SI_UHI:
11220 : 15029 : case UQI_FTYPE_V8DI_V8DI_UQI:
11221 : 15029 : case V16HI_FTYPE_V16SI_V16HI_UHI:
11222 : 15029 : case V16QI_FTYPE_V16SI_V16QI_UHI:
11223 : 15029 : case V16QI_FTYPE_V8DI_V16QI_UQI:
11224 : 15029 : case V32HF_FTYPE_V32HF_V32HF_USI:
11225 : 15029 : case V16SF_FTYPE_V16SF_V16SF_UHI:
11226 : 15029 : case V16SF_FTYPE_V4SF_V16SF_UHI:
11227 : 15029 : case V16SI_FTYPE_SI_V16SI_UHI:
11228 : 15029 : case V16SI_FTYPE_V16HI_V16SI_UHI:
11229 : 15029 : case V16SI_FTYPE_V16QI_V16SI_UHI:
11230 : 15029 : case V8SF_FTYPE_V4SF_V8SF_UQI:
11231 : 15029 : case V4DF_FTYPE_V2DF_V4DF_UQI:
11232 : 15029 : case V8SI_FTYPE_V4SI_V8SI_UQI:
11233 : 15029 : case V8SI_FTYPE_SI_V8SI_UQI:
11234 : 15029 : case V4SI_FTYPE_V4SI_V4SI_UQI:
11235 : 15029 : case V4SI_FTYPE_SI_V4SI_UQI:
11236 : 15029 : case V4DI_FTYPE_V2DI_V4DI_UQI:
11237 : 15029 : case V4DI_FTYPE_DI_V4DI_UQI:
11238 : 15029 : case V2DI_FTYPE_V2DI_V2DI_UQI:
11239 : 15029 : case V2DI_FTYPE_DI_V2DI_UQI:
11240 : 15029 : case V64QI_FTYPE_V64QI_V64QI_UDI:
11241 : 15029 : case V64QI_FTYPE_V16QI_V64QI_UDI:
11242 : 15029 : case V64QI_FTYPE_QI_V64QI_UDI:
11243 : 15029 : case V32QI_FTYPE_V32QI_V32QI_USI:
11244 : 15029 : case V32QI_FTYPE_V16QI_V32QI_USI:
11245 : 15029 : case V32QI_FTYPE_QI_V32QI_USI:
11246 : 15029 : case V16QI_FTYPE_V16QI_V16QI_UHI:
11247 : 15029 : case V16QI_FTYPE_QI_V16QI_UHI:
11248 : 15029 : case V32HI_FTYPE_V8HI_V32HI_USI:
11249 : 15029 : case V32HI_FTYPE_HI_V32HI_USI:
11250 : 15029 : case V16HI_FTYPE_V8HI_V16HI_UHI:
11251 : 15029 : case V16HI_FTYPE_HI_V16HI_UHI:
11252 : 15029 : case V8HI_FTYPE_V8HI_V8HI_UQI:
11253 : 15029 : case V8HI_FTYPE_HI_V8HI_UQI:
11254 : 15029 : case V16HF_FTYPE_V16HF_V16HF_UHI:
11255 : 15029 : case V8SF_FTYPE_V8HI_V8SF_UQI:
11256 : 15029 : case V4SF_FTYPE_V8HI_V4SF_UQI:
11257 : 15029 : case V8SI_FTYPE_V8HF_V8SI_UQI:
11258 : 15029 : case V8SF_FTYPE_V8HF_V8SF_UQI:
11259 : 15029 : case V8SI_FTYPE_V8SF_V8SI_UQI:
11260 : 15029 : case V4SI_FTYPE_V4SF_V4SI_UQI:
11261 : 15029 : case V4SI_FTYPE_V8HF_V4SI_UQI:
11262 : 15029 : case V4SF_FTYPE_V8HF_V4SF_UQI:
11263 : 15029 : case V4DI_FTYPE_V8HF_V4DI_UQI:
11264 : 15029 : case V4DI_FTYPE_V4SF_V4DI_UQI:
11265 : 15029 : case V2DI_FTYPE_V8HF_V2DI_UQI:
11266 : 15029 : case V2DI_FTYPE_V4SF_V2DI_UQI:
11267 : 15029 : case V8HF_FTYPE_V8HF_V8HF_UQI:
11268 : 15029 : case V8HF_FTYPE_V8HF_V8HF_V8HF:
11269 : 15029 : case V8HF_FTYPE_V8HI_V8HF_UQI:
11270 : 15029 : case V8HF_FTYPE_V8SI_V8HF_UQI:
11271 : 15029 : case V8HF_FTYPE_V8SF_V8HF_UQI:
11272 : 15029 : case V8HF_FTYPE_V4SI_V8HF_UQI:
11273 : 15029 : case V8HF_FTYPE_V4SF_V8HF_UQI:
11274 : 15029 : case V8HF_FTYPE_V4DI_V8HF_UQI:
11275 : 15029 : case V8HF_FTYPE_V4DF_V8HF_UQI:
11276 : 15029 : case V8HF_FTYPE_V2DI_V8HF_UQI:
11277 : 15029 : case V8HF_FTYPE_V2DF_V8HF_UQI:
11278 : 15029 : case V4SF_FTYPE_V4DI_V4SF_UQI:
11279 : 15029 : case V4SF_FTYPE_V2DI_V4SF_UQI:
11280 : 15029 : case V4DF_FTYPE_V4DI_V4DF_UQI:
11281 : 15029 : case V4DF_FTYPE_V8HF_V4DF_UQI:
11282 : 15029 : case V2DF_FTYPE_V8HF_V2DF_UQI:
11283 : 15029 : case V2DF_FTYPE_V2DI_V2DF_UQI:
11284 : 15029 : case V16QI_FTYPE_V8HI_V16QI_UQI:
11285 : 15029 : case V16QI_FTYPE_V16HI_V16QI_UHI:
11286 : 15029 : case V16QI_FTYPE_V4SI_V16QI_UQI:
11287 : 15029 : case V16QI_FTYPE_V8SI_V16QI_UQI:
11288 : 15029 : case V8HI_FTYPE_V8HF_V8HI_UQI:
11289 : 15029 : case V8HI_FTYPE_V4SI_V8HI_UQI:
11290 : 15029 : case V8HI_FTYPE_V8SI_V8HI_UQI:
11291 : 15029 : case V16QI_FTYPE_V2DI_V16QI_UQI:
11292 : 15029 : case V16QI_FTYPE_V4DI_V16QI_UQI:
11293 : 15029 : case V8HI_FTYPE_V2DI_V8HI_UQI:
11294 : 15029 : case V8HI_FTYPE_V4DI_V8HI_UQI:
11295 : 15029 : case V4SI_FTYPE_V2DI_V4SI_UQI:
11296 : 15029 : case V4SI_FTYPE_V4DI_V4SI_UQI:
11297 : 15029 : case V32QI_FTYPE_V32HI_V32QI_USI:
11298 : 15029 : case UHI_FTYPE_V16QI_V16QI_UHI:
11299 : 15029 : case USI_FTYPE_V32QI_V32QI_USI:
11300 : 15029 : case UDI_FTYPE_V64QI_V64QI_UDI:
11301 : 15029 : case UQI_FTYPE_V8HI_V8HI_UQI:
11302 : 15029 : case UHI_FTYPE_V16HI_V16HI_UHI:
11303 : 15029 : case USI_FTYPE_V32HI_V32HI_USI:
11304 : 15029 : case UQI_FTYPE_V4SI_V4SI_UQI:
11305 : 15029 : case UQI_FTYPE_V8SI_V8SI_UQI:
11306 : 15029 : case UQI_FTYPE_V2DI_V2DI_UQI:
11307 : 15029 : case UQI_FTYPE_V4DI_V4DI_UQI:
11308 : 15029 : case V4SF_FTYPE_V2DF_V4SF_UQI:
11309 : 15029 : case V4SF_FTYPE_V4DF_V4SF_UQI:
11310 : 15029 : case V16SI_FTYPE_V16SI_V16SI_UHI:
11311 : 15029 : case V16SI_FTYPE_V4SI_V16SI_UHI:
11312 : 15029 : case V2DI_FTYPE_V4SI_V2DI_UQI:
11313 : 15029 : case V2DI_FTYPE_V8HI_V2DI_UQI:
11314 : 15029 : case V2DI_FTYPE_V16QI_V2DI_UQI:
11315 : 15029 : case V4DI_FTYPE_V4DI_V4DI_UQI:
11316 : 15029 : case V4DI_FTYPE_V4SI_V4DI_UQI:
11317 : 15029 : case V4DI_FTYPE_V8HI_V4DI_UQI:
11318 : 15029 : case V4DI_FTYPE_V16QI_V4DI_UQI:
11319 : 15029 : case V4DI_FTYPE_V4DF_V4DI_UQI:
11320 : 15029 : case V2DI_FTYPE_V2DF_V2DI_UQI:
11321 : 15029 : case V4SI_FTYPE_V4DF_V4SI_UQI:
11322 : 15029 : case V4SI_FTYPE_V2DF_V4SI_UQI:
11323 : 15029 : case V4SI_FTYPE_V8HI_V4SI_UQI:
11324 : 15029 : case V4SI_FTYPE_V16QI_V4SI_UQI:
11325 : 15029 : case V4DI_FTYPE_V4DI_V4DI_V4DI:
11326 : 15029 : case V8DF_FTYPE_V2DF_V8DF_UQI:
11327 : 15029 : case V8DF_FTYPE_V4DF_V8DF_UQI:
11328 : 15029 : case V8DF_FTYPE_V8DF_V8DF_UQI:
11329 : 15029 : case V8SF_FTYPE_V8SF_V8SF_UQI:
11330 : 15029 : case V8SF_FTYPE_V8SI_V8SF_UQI:
11331 : 15029 : case V4DF_FTYPE_V4DF_V4DF_UQI:
11332 : 15029 : case V4SF_FTYPE_V4SF_V4SF_UQI:
11333 : 15029 : case V2DF_FTYPE_V2DF_V2DF_UQI:
11334 : 15029 : case V2DF_FTYPE_V4SF_V2DF_UQI:
11335 : 15029 : case V2DF_FTYPE_V4SI_V2DF_UQI:
11336 : 15029 : case V4SF_FTYPE_V4SI_V4SF_UQI:
11337 : 15029 : case V4DF_FTYPE_V4SF_V4DF_UQI:
11338 : 15029 : case V4DF_FTYPE_V4SI_V4DF_UQI:
11339 : 15029 : case V8SI_FTYPE_V8SI_V8SI_UQI:
11340 : 15029 : case V8SI_FTYPE_V8HI_V8SI_UQI:
11341 : 15029 : case V8SI_FTYPE_V16QI_V8SI_UQI:
11342 : 15029 : case V8DF_FTYPE_V8SI_V8DF_UQI:
11343 : 15029 : case V8DI_FTYPE_DI_V8DI_UQI:
11344 : 15029 : case V16SF_FTYPE_V8SF_V16SF_UHI:
11345 : 15029 : case V16SI_FTYPE_V8SI_V16SI_UHI:
11346 : 15029 : case V16HF_FTYPE_V16HI_V16HF_UHI:
11347 : 15029 : case V16HF_FTYPE_V16HF_V16HF_V16HF:
11348 : 15029 : case V16HI_FTYPE_V16HF_V16HI_UHI:
11349 : 15029 : case V16HI_FTYPE_V16HI_V16HI_UHI:
11350 : 15029 : case V8HI_FTYPE_V16QI_V8HI_UQI:
11351 : 15029 : case V16HI_FTYPE_V16QI_V16HI_UHI:
11352 : 15029 : case V32HI_FTYPE_V32HI_V32HI_USI:
11353 : 15029 : case V32HI_FTYPE_V32QI_V32HI_USI:
11354 : 15029 : case V8DI_FTYPE_V16QI_V8DI_UQI:
11355 : 15029 : case V8DI_FTYPE_V2DI_V8DI_UQI:
11356 : 15029 : case V8DI_FTYPE_V4DI_V8DI_UQI:
11357 : 15029 : case V8DI_FTYPE_V8DI_V8DI_UQI:
11358 : 15029 : case V8DI_FTYPE_V8HI_V8DI_UQI:
11359 : 15029 : case V8DI_FTYPE_V8SI_V8DI_UQI:
11360 : 15029 : case V8HI_FTYPE_V8DI_V8HI_UQI:
11361 : 15029 : case V8SI_FTYPE_V8DI_V8SI_UQI:
11362 : 15029 : case V4SI_FTYPE_V4SI_V4SI_V4SI:
11363 : 15029 : case V4DI_FTYPE_V4DI_V4DI_V2DI:
11364 : 15029 : case V16SI_FTYPE_V16SI_V16SI_V16SI:
11365 : 15029 : case V8DI_FTYPE_V8DI_V8DI_V8DI:
11366 : 15029 : case V32HI_FTYPE_V32HI_V32HI_V32HI:
11367 : 15029 : case V2DI_FTYPE_V2DI_V2DI_V2DI:
11368 : 15029 : case V16HI_FTYPE_V16HI_V16HI_V16HI:
11369 : 15029 : case V8SI_FTYPE_V8SI_V8SI_V8SI:
11370 : 15029 : case V8HI_FTYPE_V8HI_V8HI_V8HI:
11371 : 15029 : case V32BF_FTYPE_V16SF_V16SF_USI:
11372 : 15029 : case V16BF_FTYPE_V8SF_V8SF_UHI:
11373 : 15029 : case V8BF_FTYPE_V4SF_V4SF_UQI:
11374 : 15029 : case V16BF_FTYPE_V16SF_V16BF_UHI:
11375 : 15029 : case V8BF_FTYPE_V8SF_V8BF_UQI:
11376 : 15029 : case V8BF_FTYPE_V4SF_V8BF_UQI:
11377 : 15029 : case V16SF_FTYPE_V16SF_V32BF_V32BF:
11378 : 15029 : case V8SF_FTYPE_V8SF_V16BF_V16BF:
11379 : 15029 : case V4SF_FTYPE_V4SF_V8BF_V8BF:
11380 : 15029 : nargs = 3;
11381 : 15029 : break;
11382 : 1404 : case V32QI_FTYPE_V32QI_V32QI_INT:
11383 : 1404 : case V16HI_FTYPE_V16HI_V16HI_INT:
11384 : 1404 : case V16QI_FTYPE_V16QI_V16QI_INT:
11385 : 1404 : case V4DI_FTYPE_V4DI_V4DI_INT:
11386 : 1404 : case V8HI_FTYPE_V8HI_V8HI_INT:
11387 : 1404 : case V8SI_FTYPE_V8SI_V8SI_INT:
11388 : 1404 : case V8SI_FTYPE_V8SI_V4SI_INT:
11389 : 1404 : case V8SF_FTYPE_V8SF_V8SF_INT:
11390 : 1404 : case V8SF_FTYPE_V8SF_V4SF_INT:
11391 : 1404 : case V4SI_FTYPE_V4SI_V4SI_INT:
11392 : 1404 : case V4DF_FTYPE_V4DF_V4DF_INT:
11393 : 1404 : case V16SF_FTYPE_V16SF_V16SF_INT:
11394 : 1404 : case V16SF_FTYPE_V16SF_V4SF_INT:
11395 : 1404 : case V16SI_FTYPE_V16SI_V4SI_INT:
11396 : 1404 : case V4DF_FTYPE_V4DF_V2DF_INT:
11397 : 1404 : case V4SF_FTYPE_V4SF_V4SF_INT:
11398 : 1404 : case V2DI_FTYPE_V2DI_V2DI_INT:
11399 : 1404 : case V4DI_FTYPE_V4DI_V2DI_INT:
11400 : 1404 : case V2DF_FTYPE_V2DF_V2DF_INT:
11401 : 1404 : case UQI_FTYPE_V8DI_V8UDI_INT:
11402 : 1404 : case UQI_FTYPE_V8DF_V8DF_INT:
11403 : 1404 : case UQI_FTYPE_V2DF_V2DF_INT:
11404 : 1404 : case UQI_FTYPE_V4SF_V4SF_INT:
11405 : 1404 : case UHI_FTYPE_V16SI_V16SI_INT:
11406 : 1404 : case UHI_FTYPE_V16SF_V16SF_INT:
11407 : 1404 : case V64QI_FTYPE_V64QI_V64QI_INT:
11408 : 1404 : case V32HI_FTYPE_V32HI_V32HI_INT:
11409 : 1404 : case V16SI_FTYPE_V16SI_V16SI_INT:
11410 : 1404 : case V8DI_FTYPE_V8DI_V8DI_INT:
11411 : 1404 : nargs = 3;
11412 : 1404 : nargs_constant = 1;
11413 : 1404 : break;
11414 : 47 : case V4DI_FTYPE_V4DI_V4DI_INT_CONVERT:
11415 : 47 : nargs = 3;
11416 : 47 : rmode = V4DImode;
11417 : 47 : nargs_constant = 1;
11418 : 47 : break;
11419 : 80 : case V2DI_FTYPE_V2DI_V2DI_INT_CONVERT:
11420 : 80 : nargs = 3;
11421 : 80 : rmode = V2DImode;
11422 : 80 : nargs_constant = 1;
11423 : 80 : break;
11424 : 48 : case V1DI_FTYPE_V1DI_V1DI_INT_CONVERT:
11425 : 48 : nargs = 3;
11426 : 48 : rmode = DImode;
11427 : 48 : nargs_constant = 1;
11428 : 48 : break;
11429 : 20 : case V2DI_FTYPE_V2DI_UINT_UINT:
11430 : 20 : nargs = 3;
11431 : 20 : nargs_constant = 2;
11432 : 20 : break;
11433 : 8 : case V8DI_FTYPE_V8DI_V8DI_INT_CONVERT:
11434 : 8 : nargs = 3;
11435 : 8 : rmode = V8DImode;
11436 : 8 : nargs_constant = 1;
11437 : 8 : break;
11438 : 16 : case V8DI_FTYPE_V8DI_V8DI_INT_V8DI_UDI_CONVERT:
11439 : 16 : nargs = 5;
11440 : 16 : rmode = V8DImode;
11441 : 16 : mask_pos = 2;
11442 : 16 : nargs_constant = 1;
11443 : 16 : break;
11444 : 245 : case QI_FTYPE_V8DF_INT_UQI:
11445 : 245 : case QI_FTYPE_V4DF_INT_UQI:
11446 : 245 : case QI_FTYPE_V2DF_INT_UQI:
11447 : 245 : case HI_FTYPE_V16SF_INT_UHI:
11448 : 245 : case QI_FTYPE_V8SF_INT_UQI:
11449 : 245 : case QI_FTYPE_V4SF_INT_UQI:
11450 : 245 : case QI_FTYPE_V8HF_INT_UQI:
11451 : 245 : case HI_FTYPE_V16HF_INT_UHI:
11452 : 245 : case SI_FTYPE_V32HF_INT_USI:
11453 : 245 : case V4SI_FTYPE_V4SI_V4SI_UHI:
11454 : 245 : case V8SI_FTYPE_V8SI_V8SI_UHI:
11455 : 245 : nargs = 3;
11456 : 245 : mask_pos = 1;
11457 : 245 : nargs_constant = 1;
11458 : 245 : break;
11459 : 16 : case V4DI_FTYPE_V4DI_V4DI_INT_V4DI_USI_CONVERT:
11460 : 16 : nargs = 5;
11461 : 16 : rmode = V4DImode;
11462 : 16 : mask_pos = 2;
11463 : 16 : nargs_constant = 1;
11464 : 16 : break;
11465 : 16 : case V2DI_FTYPE_V2DI_V2DI_INT_V2DI_UHI_CONVERT:
11466 : 16 : nargs = 5;
11467 : 16 : rmode = V2DImode;
11468 : 16 : mask_pos = 2;
11469 : 16 : nargs_constant = 1;
11470 : 16 : break;
11471 : 14618 : case V32QI_FTYPE_V32QI_V32QI_V32QI_USI:
11472 : 14618 : case V32HI_FTYPE_V32HI_V32HI_V32HI_USI:
11473 : 14618 : case V32HI_FTYPE_V64QI_V64QI_V32HI_USI:
11474 : 14618 : case V16SI_FTYPE_V32HI_V32HI_V16SI_UHI:
11475 : 14618 : case V64QI_FTYPE_V64QI_V64QI_V64QI_UDI:
11476 : 14618 : case V32HI_FTYPE_V32HI_V8HI_V32HI_USI:
11477 : 14618 : case V16HI_FTYPE_V16HI_V8HI_V16HI_UHI:
11478 : 14618 : case V8SI_FTYPE_V8SI_V4SI_V8SI_UQI:
11479 : 14618 : case V4DI_FTYPE_V4DI_V2DI_V4DI_UQI:
11480 : 14618 : case V64QI_FTYPE_V32HI_V32HI_V64QI_UDI:
11481 : 14618 : case V32QI_FTYPE_V16HI_V16HI_V32QI_USI:
11482 : 14618 : case V16QI_FTYPE_V8HI_V8HI_V16QI_UHI:
11483 : 14618 : case V32HI_FTYPE_V16SI_V16SI_V32HI_USI:
11484 : 14618 : case V16HI_FTYPE_V8SI_V8SI_V16HI_UHI:
11485 : 14618 : case V8HI_FTYPE_V4SI_V4SI_V8HI_UQI:
11486 : 14618 : case V4DF_FTYPE_V4DF_V4DI_V4DF_UQI:
11487 : 14618 : case V32HF_FTYPE_V32HF_V32HF_V32HF_USI:
11488 : 14618 : case V8SF_FTYPE_V8SF_V8SI_V8SF_UQI:
11489 : 14618 : case V4SF_FTYPE_V4SF_V4SI_V4SF_UQI:
11490 : 14618 : case V2DF_FTYPE_V2DF_V2DI_V2DF_UQI:
11491 : 14618 : case V2DI_FTYPE_V4SI_V4SI_V2DI_UQI:
11492 : 14618 : case V4DI_FTYPE_V8SI_V8SI_V4DI_UQI:
11493 : 14618 : case V4DF_FTYPE_V4DI_V4DF_V4DF_UQI:
11494 : 14618 : case V8SF_FTYPE_V8SI_V8SF_V8SF_UQI:
11495 : 14618 : case V2DF_FTYPE_V2DI_V2DF_V2DF_UQI:
11496 : 14618 : case V4SF_FTYPE_V4SI_V4SF_V4SF_UQI:
11497 : 14618 : case V16SF_FTYPE_V16SF_V16SF_V16SF_UHI:
11498 : 14618 : case V16SF_FTYPE_V16SF_V16SI_V16SF_UHI:
11499 : 14618 : case V16SF_FTYPE_V16SI_V16SF_V16SF_UHI:
11500 : 14618 : case V16SI_FTYPE_V16SI_V16SI_V16SI_UHI:
11501 : 14618 : case V16SI_FTYPE_V16SI_V4SI_V16SI_UHI:
11502 : 14618 : case V8HI_FTYPE_V8HI_V8HI_V8HI_UQI:
11503 : 14618 : case V8SI_FTYPE_V8SI_V8SI_V8SI_UQI:
11504 : 14618 : case V4SI_FTYPE_V4SI_V4SI_V4SI_UQI:
11505 : 14618 : case V16HF_FTYPE_V16HF_V16HF_V16HF_UQI:
11506 : 14618 : case V16HF_FTYPE_V16HF_V16HF_V16HF_UHI:
11507 : 14618 : case V8SF_FTYPE_V8SF_V8SF_V8SF_UQI:
11508 : 14618 : case V16QI_FTYPE_V16QI_V16QI_V16QI_UHI:
11509 : 14618 : case V16HI_FTYPE_V16HI_V16HI_V16HI_UHI:
11510 : 14618 : case V2DI_FTYPE_V2DI_V2DI_V2DI_UQI:
11511 : 14618 : case V2DF_FTYPE_V2DF_V2DF_V2DF_UQI:
11512 : 14618 : case V4DI_FTYPE_V4DI_V4DI_V4DI_UQI:
11513 : 14618 : case V4DF_FTYPE_V4DF_V4DF_V4DF_UQI:
11514 : 14618 : case V8HF_FTYPE_V8HF_V8HF_V8HF_UQI:
11515 : 14618 : case V4SF_FTYPE_V4SF_V4SF_V4SF_UQI:
11516 : 14618 : case V8DF_FTYPE_V8DF_V8DF_V8DF_UQI:
11517 : 14618 : case V8DF_FTYPE_V8DF_V8DI_V8DF_UQI:
11518 : 14618 : case V8DF_FTYPE_V8DI_V8DF_V8DF_UQI:
11519 : 14618 : case V8DI_FTYPE_V16SI_V16SI_V8DI_UQI:
11520 : 14618 : case V8DI_FTYPE_V8DI_V2DI_V8DI_UQI:
11521 : 14618 : case V8DI_FTYPE_V8DI_V8DI_V8DI_UQI:
11522 : 14618 : case V8HI_FTYPE_V16QI_V16QI_V8HI_UQI:
11523 : 14618 : case V16HI_FTYPE_V32QI_V32QI_V16HI_UHI:
11524 : 14618 : case V8SI_FTYPE_V16HI_V16HI_V8SI_UQI:
11525 : 14618 : case V4SI_FTYPE_V8HI_V8HI_V4SI_UQI:
11526 : 14618 : case V32BF_FTYPE_V16SF_V16SF_V32BF_USI:
11527 : 14618 : case V16BF_FTYPE_V8SF_V8SF_V16BF_UHI:
11528 : 14618 : case V8BF_FTYPE_V4SF_V4SF_V8BF_UQI:
11529 : 14618 : nargs = 4;
11530 : 14618 : break;
11531 : 11 : case V2DF_FTYPE_V2DF_V2DF_V2DI_INT:
11532 : 11 : case V4DF_FTYPE_V4DF_V4DF_V4DI_INT:
11533 : 11 : case V4SF_FTYPE_V4SF_V4SF_V4SI_INT:
11534 : 11 : case V8SF_FTYPE_V8SF_V8SF_V8SI_INT:
11535 : 11 : case V16SF_FTYPE_V16SF_V16SF_V16SI_INT:
11536 : 11 : case V4SI_FTYPE_V4SI_V4SI_V4SI_INT:
11537 : 11 : nargs = 4;
11538 : 11 : nargs_constant = 1;
11539 : 11 : break;
11540 : 3625 : case UQI_FTYPE_V4DI_V4DI_INT_UQI:
11541 : 3625 : case UQI_FTYPE_V8SI_V8SI_INT_UQI:
11542 : 3625 : case QI_FTYPE_V4DF_V4DF_INT_UQI:
11543 : 3625 : case QI_FTYPE_V8SF_V8SF_INT_UQI:
11544 : 3625 : case UHI_FTYPE_V16HF_V16HF_INT_UHI:
11545 : 3625 : case UQI_FTYPE_V2DI_V2DI_INT_UQI:
11546 : 3625 : case UQI_FTYPE_V4SI_V4SI_INT_UQI:
11547 : 3625 : case UQI_FTYPE_V2DF_V2DF_INT_UQI:
11548 : 3625 : case UQI_FTYPE_V4SF_V4SF_INT_UQI:
11549 : 3625 : case UQI_FTYPE_V8HF_V8HF_INT_UQI:
11550 : 3625 : case UDI_FTYPE_V64QI_V64QI_INT_UDI:
11551 : 3625 : case USI_FTYPE_V32QI_V32QI_INT_USI:
11552 : 3625 : case UHI_FTYPE_V16QI_V16QI_INT_UHI:
11553 : 3625 : case USI_FTYPE_V32HI_V32HI_INT_USI:
11554 : 3625 : case USI_FTYPE_V32HF_V32HF_INT_USI:
11555 : 3625 : case UHI_FTYPE_V16HI_V16HI_INT_UHI:
11556 : 3625 : case UQI_FTYPE_V8HI_V8HI_INT_UQI:
11557 : 3625 : nargs = 4;
11558 : 3625 : mask_pos = 1;
11559 : 3625 : nargs_constant = 1;
11560 : 3625 : break;
11561 : 23 : case V2DI_FTYPE_V2DI_V2DI_UINT_UINT:
11562 : 23 : nargs = 4;
11563 : 23 : nargs_constant = 2;
11564 : 23 : break;
11565 : 67 : case UCHAR_FTYPE_UCHAR_UINT_UINT_PUNSIGNED:
11566 : 67 : case UCHAR_FTYPE_UCHAR_ULONGLONG_ULONGLONG_PULONGLONG:
11567 : 67 : case V16SF_FTYPE_V16SF_V32BF_V32BF_UHI:
11568 : 67 : case V8SF_FTYPE_V8SF_V16BF_V16BF_UQI:
11569 : 67 : case V4SF_FTYPE_V4SF_V8BF_V8BF_UQI:
11570 : 67 : nargs = 4;
11571 : 67 : break;
11572 : 667 : case UQI_FTYPE_V8DI_V8DI_INT_UQI:
11573 : 667 : case UHI_FTYPE_V16SI_V16SI_INT_UHI:
11574 : 667 : mask_pos = 1;
11575 : 667 : nargs = 4;
11576 : 667 : nargs_constant = 1;
11577 : 667 : break;
11578 : 3488 : case V8SF_FTYPE_V8SF_INT_V8SF_UQI:
11579 : 3488 : case V4SF_FTYPE_V4SF_INT_V4SF_UQI:
11580 : 3488 : case V2DF_FTYPE_V4DF_INT_V2DF_UQI:
11581 : 3488 : case V2DI_FTYPE_V4DI_INT_V2DI_UQI:
11582 : 3488 : case V8SF_FTYPE_V16SF_INT_V8SF_UQI:
11583 : 3488 : case V8SI_FTYPE_V16SI_INT_V8SI_UQI:
11584 : 3488 : case V2DF_FTYPE_V8DF_INT_V2DF_UQI:
11585 : 3488 : case V2DI_FTYPE_V8DI_INT_V2DI_UQI:
11586 : 3488 : case V4SF_FTYPE_V8SF_INT_V4SF_UQI:
11587 : 3488 : case V4SI_FTYPE_V8SI_INT_V4SI_UQI:
11588 : 3488 : case V8HI_FTYPE_V8SF_INT_V8HI_UQI:
11589 : 3488 : case V8HI_FTYPE_V4SF_INT_V8HI_UQI:
11590 : 3488 : case V32HI_FTYPE_V32HI_INT_V32HI_USI:
11591 : 3488 : case V16HI_FTYPE_V16HI_INT_V16HI_UHI:
11592 : 3488 : case V8HI_FTYPE_V8HI_INT_V8HI_UQI:
11593 : 3488 : case V4DI_FTYPE_V4DI_INT_V4DI_UQI:
11594 : 3488 : case V2DI_FTYPE_V2DI_INT_V2DI_UQI:
11595 : 3488 : case V8SI_FTYPE_V8SI_INT_V8SI_UQI:
11596 : 3488 : case V4SI_FTYPE_V4SI_INT_V4SI_UQI:
11597 : 3488 : case V4DF_FTYPE_V4DF_INT_V4DF_UQI:
11598 : 3488 : case V2DF_FTYPE_V2DF_INT_V2DF_UQI:
11599 : 3488 : case V8DF_FTYPE_V8DF_INT_V8DF_UQI:
11600 : 3488 : case V16SF_FTYPE_V16SF_INT_V16SF_UHI:
11601 : 3488 : case V16HI_FTYPE_V16SF_INT_V16HI_UHI:
11602 : 3488 : case V16SI_FTYPE_V16SI_INT_V16SI_UHI:
11603 : 3488 : case V16HF_FTYPE_V16HF_INT_V16HF_UHI:
11604 : 3488 : case V8HF_FTYPE_V8HF_INT_V8HF_UQI:
11605 : 3488 : case V4SI_FTYPE_V16SI_INT_V4SI_UQI:
11606 : 3488 : case V4DI_FTYPE_V8DI_INT_V4DI_UQI:
11607 : 3488 : case V4DF_FTYPE_V8DF_INT_V4DF_UQI:
11608 : 3488 : case V4SF_FTYPE_V16SF_INT_V4SF_UQI:
11609 : 3488 : case V8DI_FTYPE_V8DI_INT_V8DI_UQI:
11610 : 3488 : nargs = 4;
11611 : 3488 : mask_pos = 2;
11612 : 3488 : nargs_constant = 1;
11613 : 3488 : break;
11614 : 1467 : case V16SF_FTYPE_V16SF_V4SF_INT_V16SF_UHI:
11615 : 1467 : case V16SI_FTYPE_V16SI_V4SI_INT_V16SI_UHI:
11616 : 1467 : case V8DF_FTYPE_V8DF_V8DF_INT_V8DF_UQI:
11617 : 1467 : case V8DI_FTYPE_V8DI_V8DI_INT_V8DI_UQI:
11618 : 1467 : case V16SF_FTYPE_V16SF_V16SF_INT_V16SF_UHI:
11619 : 1467 : case V16SI_FTYPE_V16SI_V16SI_INT_V16SI_UHI:
11620 : 1467 : case V4SF_FTYPE_V4SF_V4SF_INT_V4SF_UQI:
11621 : 1467 : case V2DF_FTYPE_V2DF_V2DF_INT_V2DF_UQI:
11622 : 1467 : case V8DF_FTYPE_V8DF_V4DF_INT_V8DF_UQI:
11623 : 1467 : case V8DI_FTYPE_V8DI_V4DI_INT_V8DI_UQI:
11624 : 1467 : case V4DF_FTYPE_V4DF_V4DF_INT_V4DF_UQI:
11625 : 1467 : case V8SF_FTYPE_V8SF_V8SF_INT_V8SF_UQI:
11626 : 1467 : case V8DF_FTYPE_V8DF_V2DF_INT_V8DF_UQI:
11627 : 1467 : case V8DI_FTYPE_V8DI_V2DI_INT_V8DI_UQI:
11628 : 1467 : case V8SI_FTYPE_V8SI_V8SI_INT_V8SI_UQI:
11629 : 1467 : case V4DI_FTYPE_V4DI_V4DI_INT_V4DI_UQI:
11630 : 1467 : case V4SI_FTYPE_V4SI_V4SI_INT_V4SI_UQI:
11631 : 1467 : case V2DI_FTYPE_V2DI_V2DI_INT_V2DI_UQI:
11632 : 1467 : case V32HI_FTYPE_V64QI_V64QI_INT_V32HI_USI:
11633 : 1467 : case V16HI_FTYPE_V32QI_V32QI_INT_V16HI_UHI:
11634 : 1467 : case V8HI_FTYPE_V16QI_V16QI_INT_V8HI_UQI:
11635 : 1467 : case V16SF_FTYPE_V16SF_V8SF_INT_V16SF_UHI:
11636 : 1467 : case V16SI_FTYPE_V16SI_V8SI_INT_V16SI_UHI:
11637 : 1467 : case V8SF_FTYPE_V8SF_V4SF_INT_V8SF_UQI:
11638 : 1467 : case V8SI_FTYPE_V8SI_V4SI_INT_V8SI_UQI:
11639 : 1467 : case V4DI_FTYPE_V4DI_V2DI_INT_V4DI_UQI:
11640 : 1467 : case V4DF_FTYPE_V4DF_V2DF_INT_V4DF_UQI:
11641 : 1467 : nargs = 5;
11642 : 1467 : mask_pos = 2;
11643 : 1467 : nargs_constant = 1;
11644 : 1467 : break;
11645 : 268 : case V8DI_FTYPE_V8DI_V8DI_V8DI_INT_UQI:
11646 : 268 : case V16SI_FTYPE_V16SI_V16SI_V16SI_INT_UHI:
11647 : 268 : case V2DF_FTYPE_V2DF_V2DF_V2DI_INT_UQI:
11648 : 268 : case V4SF_FTYPE_V4SF_V4SF_V4SI_INT_UQI:
11649 : 268 : case V8SF_FTYPE_V8SF_V8SF_V8SI_INT_UQI:
11650 : 268 : case V8SI_FTYPE_V8SI_V8SI_V8SI_INT_UQI:
11651 : 268 : case V4DF_FTYPE_V4DF_V4DF_V4DI_INT_UQI:
11652 : 268 : case V4DI_FTYPE_V4DI_V4DI_V4DI_INT_UQI:
11653 : 268 : case V4SI_FTYPE_V4SI_V4SI_V4SI_INT_UQI:
11654 : 268 : case V2DI_FTYPE_V2DI_V2DI_V2DI_INT_UQI:
11655 : 268 : nargs = 5;
11656 : 268 : mask_pos = 1;
11657 : 268 : nargs_constant = 1;
11658 : 268 : break;
11659 : 492 : case V64QI_FTYPE_V64QI_V64QI_INT_V64QI_UDI:
11660 : 492 : case V32QI_FTYPE_V32QI_V32QI_INT_V32QI_USI:
11661 : 492 : case V16QI_FTYPE_V16QI_V16QI_INT_V16QI_UHI:
11662 : 492 : case V32HI_FTYPE_V32HI_V32HI_INT_V32HI_INT:
11663 : 492 : case V16SI_FTYPE_V16SI_V16SI_INT_V16SI_INT:
11664 : 492 : case V8DI_FTYPE_V8DI_V8DI_INT_V8DI_INT:
11665 : 492 : case V16HI_FTYPE_V16HI_V16HI_INT_V16HI_INT:
11666 : 492 : case V8SI_FTYPE_V8SI_V8SI_INT_V8SI_INT:
11667 : 492 : case V4DI_FTYPE_V4DI_V4DI_INT_V4DI_INT:
11668 : 492 : case V8HI_FTYPE_V8HI_V8HI_INT_V8HI_INT:
11669 : 492 : case V4SI_FTYPE_V4SI_V4SI_INT_V4SI_INT:
11670 : 492 : case V2DI_FTYPE_V2DI_V2DI_INT_V2DI_INT:
11671 : 492 : nargs = 5;
11672 : 492 : mask_pos = 1;
11673 : 492 : nargs_constant = 2;
11674 : 492 : break;
11675 : :
11676 : 0 : default:
11677 : 0 : gcc_unreachable ();
11678 : : }
11679 : :
11680 : 52122 : gcc_assert (nargs <= ARRAY_SIZE (xops));
11681 : :
11682 : 52122 : if (comparison != UNKNOWN)
11683 : : {
11684 : 609 : gcc_assert (nargs == 2);
11685 : 609 : return ix86_expand_sse_compare (d, exp, target, swap);
11686 : : }
11687 : :
11688 : 51513 : if (rmode == VOIDmode || rmode == tmode)
11689 : : {
11690 : 51330 : if (optimize
11691 : 15248 : || target == 0
11692 : 15248 : || GET_MODE (target) != tmode
11693 : 66393 : || !insn_p->operand[0].predicate (target, tmode))
11694 : 36362 : target = gen_reg_rtx (tmode);
11695 : 14968 : else if (memory_operand (target, tmode))
11696 : 578 : num_memory++;
11697 : : real_target = target;
11698 : : }
11699 : : else
11700 : : {
11701 : 183 : real_target = gen_reg_rtx (tmode);
11702 : 183 : target = lowpart_subreg (rmode, real_target, tmode);
11703 : : }
11704 : :
11705 : 222495 : for (i = 0; i < nargs; i++)
11706 : : {
11707 : 171211 : tree arg = CALL_EXPR_ARG (exp, i);
11708 : 171211 : rtx op = expand_normal (arg);
11709 : 171211 : machine_mode mode = insn_p->operand[i + 1].mode;
11710 : 171211 : bool match = insn_p->operand[i + 1].predicate (op, mode);
11711 : :
11712 : 171211 : if (second_arg_count && i == 1)
11713 : : {
11714 : : /* SIMD shift insns take either an 8-bit immediate or
11715 : : register as count. But builtin functions take int as
11716 : : count. If count doesn't match, we put it in register.
11717 : : The instructions are using 64-bit count, if op is just
11718 : : 32-bit, zero-extend it, as negative shift counts
11719 : : are undefined behavior and zero-extension is more
11720 : : efficient. */
11721 : 2774 : if (!match)
11722 : : {
11723 : 1732 : if (SCALAR_INT_MODE_P (GET_MODE (op)))
11724 : 473 : op = convert_modes (mode, GET_MODE (op), op, 1);
11725 : : else
11726 : 1259 : op = lowpart_subreg (mode, op, GET_MODE (op));
11727 : 1732 : if (!insn_p->operand[i + 1].predicate (op, mode))
11728 : 190 : op = copy_to_reg (op);
11729 : : }
11730 : : }
11731 : 168437 : else if ((mask_pos && (nargs - i - mask_pos) == nargs_constant) ||
11732 : 125371 : (!mask_pos && (nargs - i) <= nargs_constant))
11733 : : {
11734 : 15099 : if (!match)
11735 : 229 : switch (icode)
11736 : : {
11737 : 2 : case CODE_FOR_avx_vinsertf128v4di:
11738 : 2 : case CODE_FOR_avx_vextractf128v4di:
11739 : 2 : error ("the last argument must be an 1-bit immediate");
11740 : 2 : return const0_rtx;
11741 : :
11742 : 8 : case CODE_FOR_avx512f_cmpv8di3_mask:
11743 : 8 : case CODE_FOR_avx512f_cmpv16si3_mask:
11744 : 8 : case CODE_FOR_avx512f_ucmpv8di3_mask:
11745 : 8 : case CODE_FOR_avx512f_ucmpv16si3_mask:
11746 : 8 : case CODE_FOR_avx512vl_cmpv4di3_mask:
11747 : 8 : case CODE_FOR_avx512vl_cmpv8si3_mask:
11748 : 8 : case CODE_FOR_avx512vl_ucmpv4di3_mask:
11749 : 8 : case CODE_FOR_avx512vl_ucmpv8si3_mask:
11750 : 8 : case CODE_FOR_avx512vl_cmpv2di3_mask:
11751 : 8 : case CODE_FOR_avx512vl_cmpv4si3_mask:
11752 : 8 : case CODE_FOR_avx512vl_ucmpv2di3_mask:
11753 : 8 : case CODE_FOR_avx512vl_ucmpv4si3_mask:
11754 : 8 : error ("the last argument must be a 3-bit immediate");
11755 : 8 : return const0_rtx;
11756 : :
11757 : 24 : case CODE_FOR_sse4_1_roundsd:
11758 : 24 : case CODE_FOR_sse4_1_roundss:
11759 : :
11760 : 24 : case CODE_FOR_sse4_1_roundpd:
11761 : 24 : case CODE_FOR_sse4_1_roundps:
11762 : 24 : case CODE_FOR_avx_roundpd256:
11763 : 24 : case CODE_FOR_avx_roundps256:
11764 : :
11765 : 24 : case CODE_FOR_sse4_1_roundpd_vec_pack_sfix:
11766 : 24 : case CODE_FOR_sse4_1_roundps_sfix:
11767 : 24 : case CODE_FOR_avx_roundpd_vec_pack_sfix256:
11768 : 24 : case CODE_FOR_avx_roundps_sfix256:
11769 : :
11770 : 24 : case CODE_FOR_sse4_1_blendps:
11771 : 24 : case CODE_FOR_avx_blendpd256:
11772 : 24 : case CODE_FOR_avx_vpermilv4df:
11773 : 24 : case CODE_FOR_avx_vpermilv4df_mask:
11774 : 24 : case CODE_FOR_avx512f_getmantv8df_mask:
11775 : 24 : case CODE_FOR_avx512f_getmantv16sf_mask:
11776 : 24 : case CODE_FOR_avx512vl_getmantv16hf_mask:
11777 : 24 : case CODE_FOR_avx512vl_getmantv8sf_mask:
11778 : 24 : case CODE_FOR_avx512vl_getmantv4df_mask:
11779 : 24 : case CODE_FOR_avx512fp16_getmantv8hf_mask:
11780 : 24 : case CODE_FOR_avx512vl_getmantv4sf_mask:
11781 : 24 : case CODE_FOR_avx512vl_getmantv2df_mask:
11782 : 24 : case CODE_FOR_avx512dq_rangepv8df_mask_round:
11783 : 24 : case CODE_FOR_avx512dq_rangepv16sf_mask_round:
11784 : 24 : case CODE_FOR_avx512dq_rangepv4df_mask:
11785 : 24 : case CODE_FOR_avx512dq_rangepv8sf_mask:
11786 : 24 : case CODE_FOR_avx512dq_rangepv2df_mask:
11787 : 24 : case CODE_FOR_avx512dq_rangepv4sf_mask:
11788 : 24 : case CODE_FOR_avx_shufpd256_mask:
11789 : 24 : error ("the last argument must be a 4-bit immediate");
11790 : 24 : return const0_rtx;
11791 : :
11792 : 15 : case CODE_FOR_sha1rnds4:
11793 : 15 : case CODE_FOR_sse4_1_blendpd:
11794 : 15 : case CODE_FOR_avx_vpermilv2df:
11795 : 15 : case CODE_FOR_avx_vpermilv2df_mask:
11796 : 15 : case CODE_FOR_xop_vpermil2v2df3:
11797 : 15 : case CODE_FOR_xop_vpermil2v4sf3:
11798 : 15 : case CODE_FOR_xop_vpermil2v4df3:
11799 : 15 : case CODE_FOR_xop_vpermil2v8sf3:
11800 : 15 : case CODE_FOR_avx512f_vinsertf32x4_mask:
11801 : 15 : case CODE_FOR_avx512f_vinserti32x4_mask:
11802 : 15 : case CODE_FOR_avx512f_vextractf32x4_mask:
11803 : 15 : case CODE_FOR_avx512f_vextracti32x4_mask:
11804 : 15 : case CODE_FOR_sse2_shufpd:
11805 : 15 : case CODE_FOR_sse2_shufpd_mask:
11806 : 15 : case CODE_FOR_avx512dq_shuf_f64x2_mask:
11807 : 15 : case CODE_FOR_avx512dq_shuf_i64x2_mask:
11808 : 15 : case CODE_FOR_avx512vl_shuf_i32x4_mask:
11809 : 15 : case CODE_FOR_avx512vl_shuf_f32x4_mask:
11810 : 15 : error ("the last argument must be a 2-bit immediate");
11811 : 15 : return const0_rtx;
11812 : :
11813 : 30 : case CODE_FOR_avx_vextractf128v4df:
11814 : 30 : case CODE_FOR_avx_vextractf128v8sf:
11815 : 30 : case CODE_FOR_avx_vextractf128v8si:
11816 : 30 : case CODE_FOR_avx_vinsertf128v4df:
11817 : 30 : case CODE_FOR_avx_vinsertf128v8sf:
11818 : 30 : case CODE_FOR_avx_vinsertf128v8si:
11819 : 30 : case CODE_FOR_avx512f_vinsertf64x4_mask:
11820 : 30 : case CODE_FOR_avx512f_vinserti64x4_mask:
11821 : 30 : case CODE_FOR_avx512f_vextractf64x4_mask:
11822 : 30 : case CODE_FOR_avx512f_vextracti64x4_mask:
11823 : 30 : case CODE_FOR_avx512dq_vinsertf32x8_mask:
11824 : 30 : case CODE_FOR_avx512dq_vinserti32x8_mask:
11825 : 30 : case CODE_FOR_avx512vl_vinsertv4df:
11826 : 30 : case CODE_FOR_avx512vl_vinsertv4di:
11827 : 30 : case CODE_FOR_avx512vl_vinsertv8sf:
11828 : 30 : case CODE_FOR_avx512vl_vinsertv8si:
11829 : 30 : error ("the last argument must be a 1-bit immediate");
11830 : 30 : return const0_rtx;
11831 : :
11832 : 18 : case CODE_FOR_avx_vmcmpv2df3:
11833 : 18 : case CODE_FOR_avx_vmcmpv4sf3:
11834 : 18 : case CODE_FOR_avx_cmpv2df3:
11835 : 18 : case CODE_FOR_avx_cmpv4sf3:
11836 : 18 : case CODE_FOR_avx_cmpv4df3:
11837 : 18 : case CODE_FOR_avx_cmpv8sf3:
11838 : 18 : case CODE_FOR_avx512f_cmpv8df3_mask:
11839 : 18 : case CODE_FOR_avx512f_cmpv16sf3_mask:
11840 : 18 : case CODE_FOR_avx512f_vmcmpv2df3_mask:
11841 : 18 : case CODE_FOR_avx512f_vmcmpv4sf3_mask:
11842 : 18 : case CODE_FOR_avx512bw_cmpv32hf3_mask:
11843 : 18 : case CODE_FOR_avx512vl_cmpv16hf3_mask:
11844 : 18 : case CODE_FOR_avx512fp16_cmpv8hf3_mask:
11845 : 18 : error ("the last argument must be a 5-bit immediate");
11846 : 18 : return const0_rtx;
11847 : :
11848 : 132 : default:
11849 : 132 : switch (nargs_constant)
11850 : : {
11851 : 8 : case 2:
11852 : 8 : if ((mask_pos && (nargs - i - mask_pos) == nargs_constant) ||
11853 : 8 : (!mask_pos && (nargs - i) == nargs_constant))
11854 : : {
11855 : 4 : error ("the next to last argument must be an 8-bit immediate");
11856 : 4 : break;
11857 : : }
11858 : : /* FALLTHRU */
11859 : 128 : case 1:
11860 : 128 : error ("the last argument must be an 8-bit immediate");
11861 : 128 : break;
11862 : 0 : default:
11863 : 0 : gcc_unreachable ();
11864 : : }
11865 : 132 : return const0_rtx;
11866 : : }
11867 : : }
11868 : : else
11869 : : {
11870 : 153338 : if (VECTOR_MODE_P (mode))
11871 : 110023 : op = safe_vector_operand (op, mode);
11872 : :
11873 : : /* If we aren't optimizing, only allow one memory operand to
11874 : : be generated. */
11875 : 153338 : if (memory_operand (op, mode))
11876 : 17577 : num_memory++;
11877 : :
11878 : 153338 : op = fixup_modeless_constant (op, mode);
11879 : :
11880 : 153338 : if (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)
11881 : : {
11882 : 128535 : if (optimize || !match || num_memory > 1)
11883 : 106758 : op = copy_to_mode_reg (mode, op);
11884 : : }
11885 : : else
11886 : : {
11887 : 24803 : op = copy_to_reg (op);
11888 : 24803 : op = lowpart_subreg (mode, op, GET_MODE (op));
11889 : : }
11890 : : }
11891 : :
11892 : 170982 : xops[i] = op;
11893 : : }
11894 : :
11895 : 51284 : switch (nargs)
11896 : : {
11897 : 3053 : case 1:
11898 : 3053 : pat = GEN_FCN (icode) (real_target, xops[0]);
11899 : 3053 : break;
11900 : 5401 : case 2:
11901 : 5401 : pat = GEN_FCN (icode) (real_target, xops[0], xops[1]);
11902 : 5401 : break;
11903 : 16795 : case 3:
11904 : 16795 : pat = GEN_FCN (icode) (real_target, xops[0], xops[1], xops[2]);
11905 : 16795 : break;
11906 : 23796 : case 4:
11907 : 23796 : pat = GEN_FCN (icode) (real_target, xops[0], xops[1],
11908 : : xops[2], xops[3]);
11909 : 23796 : break;
11910 : 2239 : case 5:
11911 : 2239 : pat = GEN_FCN (icode) (real_target, xops[0], xops[1],
11912 : : xops[2], xops[3], xops[4]);
11913 : 2239 : break;
11914 : : case 6:
11915 : : pat = GEN_FCN (icode) (real_target, xops[0], xops[1],
11916 : : xops[2], xops[3], xops[4], xops[5]);
11917 : : break;
11918 : : default:
11919 : : gcc_unreachable ();
11920 : : }
11921 : :
11922 : 51284 : if (! pat)
11923 : : return 0;
11924 : :
11925 : 51284 : emit_insn (pat);
11926 : 51284 : return target;
11927 : : }
11928 : :
11929 : : /* Transform pattern of following layout:
11930 : : (set A
11931 : : (unspec [B C] UNSPEC_EMBEDDED_ROUNDING))
11932 : : )
11933 : : into:
11934 : : (set (A B)) */
11935 : :
11936 : : static rtx
11937 : 4375 : ix86_erase_embedded_rounding (rtx pat)
11938 : : {
11939 : 4375 : if (GET_CODE (pat) == INSN)
11940 : 529 : pat = PATTERN (pat);
11941 : :
11942 : 4375 : gcc_assert (GET_CODE (pat) == SET);
11943 : 4375 : rtx src = SET_SRC (pat);
11944 : 4375 : gcc_assert (XVECLEN (src, 0) == 2);
11945 : 4375 : rtx p0 = XVECEXP (src, 0, 0);
11946 : 4375 : gcc_assert (GET_CODE (src) == UNSPEC
11947 : : && XINT (src, 1) == UNSPEC_EMBEDDED_ROUNDING);
11948 : 4375 : rtx res = gen_rtx_SET (SET_DEST (pat), p0);
11949 : 4375 : return res;
11950 : : }
11951 : :
11952 : : /* Subroutine of ix86_expand_round_builtin to take care of comi insns
11953 : : with rounding. */
11954 : : static rtx
11955 : 91 : ix86_expand_sse_comi_round (const struct builtin_description *d,
11956 : : tree exp, rtx target)
11957 : : {
11958 : 91 : rtx pat, set_dst;
11959 : 91 : tree arg0 = CALL_EXPR_ARG (exp, 0);
11960 : 91 : tree arg1 = CALL_EXPR_ARG (exp, 1);
11961 : 91 : tree arg2 = CALL_EXPR_ARG (exp, 2);
11962 : 91 : tree arg3 = CALL_EXPR_ARG (exp, 3);
11963 : 91 : rtx op0 = expand_normal (arg0);
11964 : 91 : rtx op1 = expand_normal (arg1);
11965 : 91 : rtx op2 = expand_normal (arg2);
11966 : 91 : rtx op3 = expand_normal (arg3);
11967 : 91 : enum insn_code icode = d->icode;
11968 : 91 : const struct insn_data_d *insn_p = &insn_data[icode];
11969 : 91 : machine_mode mode0 = insn_p->operand[0].mode;
11970 : 91 : machine_mode mode1 = insn_p->operand[1].mode;
11971 : :
11972 : : /* See avxintrin.h for values. */
11973 : 91 : static const enum rtx_code comparisons[32] =
11974 : : {
11975 : : EQ, LT, LE, UNORDERED, NE, UNGE, UNGT, ORDERED,
11976 : : UNEQ, UNLT, UNLE, UNORDERED, LTGT, GE, GT, ORDERED,
11977 : : EQ, LT, LE, UNORDERED, NE, UNGE, UNGT, ORDERED,
11978 : : UNEQ, UNLT, UNLE, UNORDERED, LTGT, GE, GT, ORDERED
11979 : : };
11980 : 91 : static const bool ordereds[32] =
11981 : : {
11982 : : true, true, true, false, false, false, false, true,
11983 : : false, false, false, true, true, true, true, false,
11984 : : true, true, true, false, false, false, false, true,
11985 : : false, false, false, true, true, true, true, false
11986 : : };
11987 : 91 : static const bool non_signalings[32] =
11988 : : {
11989 : : true, false, false, true, true, false, false, true,
11990 : : true, false, false, true, true, false, false, true,
11991 : : false, true, true, false, false, true, true, false,
11992 : : false, true, true, false, false, true, true, false
11993 : : };
11994 : :
11995 : 91 : if (!CONST_INT_P (op2))
11996 : : {
11997 : 0 : error ("the third argument must be comparison constant");
11998 : 0 : return const0_rtx;
11999 : : }
12000 : 91 : if (INTVAL (op2) < 0 || INTVAL (op2) >= 32)
12001 : : {
12002 : 0 : error ("incorrect comparison mode");
12003 : 0 : return const0_rtx;
12004 : : }
12005 : :
12006 : 91 : if (!insn_p->operand[2].predicate (op3, SImode))
12007 : : {
12008 : 4 : error ("incorrect rounding operand");
12009 : 4 : return const0_rtx;
12010 : : }
12011 : :
12012 : 87 : if (VECTOR_MODE_P (mode0))
12013 : 87 : op0 = safe_vector_operand (op0, mode0);
12014 : 87 : if (VECTOR_MODE_P (mode1))
12015 : 87 : op1 = safe_vector_operand (op1, mode1);
12016 : :
12017 : 87 : enum rtx_code comparison = comparisons[INTVAL (op2)];
12018 : 87 : bool ordered = ordereds[INTVAL (op2)];
12019 : 87 : bool non_signaling = non_signalings[INTVAL (op2)];
12020 : 87 : rtx const_val = const0_rtx;
12021 : :
12022 : 87 : bool check_unordered = false;
12023 : 87 : machine_mode mode = CCFPmode;
12024 : 87 : switch (comparison)
12025 : : {
12026 : 8 : case ORDERED:
12027 : 8 : if (!ordered)
12028 : : {
12029 : : /* NB: Use CCSmode/NE for _CMP_TRUE_UQ/_CMP_TRUE_US. */
12030 : 4 : if (!non_signaling)
12031 : 4 : ordered = true;
12032 : 4 : mode = CCSmode;
12033 : : }
12034 : : else
12035 : : {
12036 : : /* NB: Use CCPmode/NE for _CMP_ORD_Q/_CMP_ORD_S. */
12037 : : if (non_signaling)
12038 : : ordered = false;
12039 : : mode = CCPmode;
12040 : : }
12041 : : comparison = NE;
12042 : : break;
12043 : 8 : case UNORDERED:
12044 : 8 : if (ordered)
12045 : : {
12046 : : /* NB: Use CCSmode/EQ for _CMP_FALSE_OQ/_CMP_FALSE_OS. */
12047 : : if (non_signaling)
12048 : 87 : ordered = false;
12049 : : mode = CCSmode;
12050 : : }
12051 : : else
12052 : : {
12053 : : /* NB: Use CCPmode/NE for _CMP_UNORD_Q/_CMP_UNORD_S. */
12054 : 4 : if (!non_signaling)
12055 : 4 : ordered = true;
12056 : 4 : mode = CCPmode;
12057 : : }
12058 : : comparison = EQ;
12059 : : break;
12060 : :
12061 : 38 : case LE: /* -> GE */
12062 : 38 : case LT: /* -> GT */
12063 : 38 : case UNGE: /* -> UNLE */
12064 : 38 : case UNGT: /* -> UNLT */
12065 : 38 : std::swap (op0, op1);
12066 : 38 : comparison = swap_condition (comparison);
12067 : : /* FALLTHRU */
12068 : 62 : case GT:
12069 : 62 : case GE:
12070 : 62 : case UNEQ:
12071 : 62 : case UNLT:
12072 : 62 : case UNLE:
12073 : 62 : case LTGT:
12074 : : /* These are supported by CCFPmode. NB: Use ordered/signaling
12075 : : COMI or unordered/non-signaling UCOMI. Both set ZF, PF, CF
12076 : : with NAN operands. */
12077 : 62 : if (ordered == non_signaling)
12078 : : ordered = !ordered;
12079 : : break;
12080 : : case EQ:
12081 : : /* NB: COMI/UCOMI will set ZF with NAN operands. Use CCZmode for
12082 : : _CMP_EQ_OQ/_CMP_EQ_OS. */
12083 : : check_unordered = true;
12084 : : mode = CCZmode;
12085 : : break;
12086 : 4 : case NE:
12087 : : /* NB: COMI/UCOMI will set ZF with NAN operands. Use CCZmode for
12088 : : _CMP_NEQ_UQ/_CMP_NEQ_US. */
12089 : 4 : gcc_assert (!ordered);
12090 : 4 : check_unordered = true;
12091 : 4 : mode = CCZmode;
12092 : 4 : const_val = const1_rtx;
12093 : 4 : break;
12094 : 0 : default:
12095 : 0 : gcc_unreachable ();
12096 : : }
12097 : :
12098 : 87 : target = gen_reg_rtx (SImode);
12099 : 87 : emit_move_insn (target, const_val);
12100 : 87 : target = gen_rtx_SUBREG (QImode, target, 0);
12101 : :
12102 : 81 : if ((optimize && !register_operand (op0, mode0))
12103 : 168 : || !insn_p->operand[0].predicate (op0, mode0))
12104 : 6 : op0 = copy_to_mode_reg (mode0, op0);
12105 : 81 : if ((optimize && !register_operand (op1, mode1))
12106 : 168 : || !insn_p->operand[1].predicate (op1, mode1))
12107 : 6 : op1 = copy_to_mode_reg (mode1, op1);
12108 : :
12109 : : /*
12110 : : 1. COMI: ordered and signaling.
12111 : : 2. UCOMI: unordered and non-signaling.
12112 : : */
12113 : 87 : if (non_signaling)
12114 : 34 : icode = (icode == CODE_FOR_sse_comi_round
12115 : 34 : ? CODE_FOR_sse_ucomi_round
12116 : : : CODE_FOR_sse2_ucomi_round);
12117 : :
12118 : 87 : pat = GEN_FCN (icode) (op0, op1, op3);
12119 : 87 : if (! pat)
12120 : : return 0;
12121 : :
12122 : : /* Rounding operand can be either NO_ROUND or ROUND_SAE at this point. */
12123 : 87 : if (INTVAL (op3) == NO_ROUND)
12124 : : {
12125 : 1 : pat = ix86_erase_embedded_rounding (pat);
12126 : 1 : if (! pat)
12127 : : return 0;
12128 : :
12129 : 1 : set_dst = SET_DEST (pat);
12130 : : }
12131 : : else
12132 : : {
12133 : 86 : gcc_assert (GET_CODE (pat) == SET);
12134 : 86 : set_dst = SET_DEST (pat);
12135 : : }
12136 : :
12137 : 87 : emit_insn (pat);
12138 : :
12139 : 87 : return ix86_ssecom_setcc (comparison, check_unordered, mode,
12140 : 87 : set_dst, target);
12141 : : }
12142 : :
12143 : : static rtx
12144 : 14540 : ix86_expand_round_builtin (const struct builtin_description *d,
12145 : : tree exp, rtx target)
12146 : : {
12147 : 14540 : rtx pat;
12148 : 14540 : unsigned int i, nargs;
12149 : 14540 : rtx xops[6];
12150 : 14540 : enum insn_code icode = d->icode;
12151 : 14540 : const struct insn_data_d *insn_p = &insn_data[icode];
12152 : 14540 : machine_mode tmode = insn_p->operand[0].mode;
12153 : 14540 : unsigned int nargs_constant = 0;
12154 : 14540 : unsigned int redundant_embed_rnd = 0;
12155 : :
12156 : 14540 : switch ((enum ix86_builtin_func_type) d->flag)
12157 : : {
12158 : : case UINT64_FTYPE_V2DF_INT:
12159 : : case UINT64_FTYPE_V4SF_INT:
12160 : : case UINT64_FTYPE_V8HF_INT:
12161 : : case UINT_FTYPE_V2DF_INT:
12162 : : case UINT_FTYPE_V4SF_INT:
12163 : : case UINT_FTYPE_V8HF_INT:
12164 : : case INT64_FTYPE_V2DF_INT:
12165 : : case INT64_FTYPE_V4SF_INT:
12166 : : case INT64_FTYPE_V8HF_INT:
12167 : : case INT_FTYPE_V2DF_INT:
12168 : : case INT_FTYPE_V4SF_INT:
12169 : : case INT_FTYPE_V8HF_INT:
12170 : : nargs = 2;
12171 : : break;
12172 : 678 : case V32HF_FTYPE_V32HF_V32HF_INT:
12173 : 678 : case V8HF_FTYPE_V8HF_V8HF_INT:
12174 : 678 : case V8HF_FTYPE_V8HF_INT_INT:
12175 : 678 : case V8HF_FTYPE_V8HF_UINT_INT:
12176 : 678 : case V8HF_FTYPE_V8HF_INT64_INT:
12177 : 678 : case V8HF_FTYPE_V8HF_UINT64_INT:
12178 : 678 : case V4SF_FTYPE_V4SF_UINT_INT:
12179 : 678 : case V4SF_FTYPE_V4SF_UINT64_INT:
12180 : 678 : case V2DF_FTYPE_V2DF_UINT64_INT:
12181 : 678 : case V4SF_FTYPE_V4SF_INT_INT:
12182 : 678 : case V4SF_FTYPE_V4SF_INT64_INT:
12183 : 678 : case V2DF_FTYPE_V2DF_INT64_INT:
12184 : 678 : case V4SF_FTYPE_V4SF_V4SF_INT:
12185 : 678 : case V2DF_FTYPE_V2DF_V2DF_INT:
12186 : 678 : case V4SF_FTYPE_V4SF_V2DF_INT:
12187 : 678 : case V2DF_FTYPE_V2DF_V4SF_INT:
12188 : 678 : nargs = 3;
12189 : 678 : break;
12190 : 4226 : case V8SF_FTYPE_V8DF_V8SF_QI_INT:
12191 : 4226 : case V8DF_FTYPE_V8DF_V8DF_QI_INT:
12192 : 4226 : case V32HI_FTYPE_V32HF_V32HI_USI_INT:
12193 : 4226 : case V8SI_FTYPE_V8DF_V8SI_QI_INT:
12194 : 4226 : case V8DI_FTYPE_V8HF_V8DI_UQI_INT:
12195 : 4226 : case V8DI_FTYPE_V8DF_V8DI_QI_INT:
12196 : 4226 : case V8SF_FTYPE_V8DI_V8SF_QI_INT:
12197 : 4226 : case V8DF_FTYPE_V8DI_V8DF_QI_INT:
12198 : 4226 : case V8DF_FTYPE_V8HF_V8DF_UQI_INT:
12199 : 4226 : case V16SF_FTYPE_V16HF_V16SF_UHI_INT:
12200 : 4226 : case V32HF_FTYPE_V32HI_V32HF_USI_INT:
12201 : 4226 : case V32HF_FTYPE_V32HF_V32HF_USI_INT:
12202 : 4226 : case V32HF_FTYPE_V32HF_V32HF_V32HF_INT:
12203 : 4226 : case V16SF_FTYPE_V16SF_V16SF_HI_INT:
12204 : 4226 : case V8DI_FTYPE_V8SF_V8DI_QI_INT:
12205 : 4226 : case V16SF_FTYPE_V16SI_V16SF_HI_INT:
12206 : 4226 : case V16SI_FTYPE_V16SF_V16SI_HI_INT:
12207 : 4226 : case V16SI_FTYPE_V16HF_V16SI_UHI_INT:
12208 : 4226 : case V16HF_FTYPE_V16SI_V16HF_UHI_INT:
12209 : 4226 : case V8DF_FTYPE_V8SF_V8DF_QI_INT:
12210 : 4226 : case V16SF_FTYPE_V16HI_V16SF_HI_INT:
12211 : 4226 : case V2DF_FTYPE_V2DF_V2DF_V2DF_INT:
12212 : 4226 : case V4SF_FTYPE_V4SF_V4SF_V4SF_INT:
12213 : 4226 : case V8HF_FTYPE_V8DI_V8HF_UQI_INT:
12214 : 4226 : case V8HF_FTYPE_V8DF_V8HF_UQI_INT:
12215 : 4226 : case V16HF_FTYPE_V16SF_V16HF_UHI_INT:
12216 : 4226 : case V8HF_FTYPE_V8HF_V8HF_V8HF_INT:
12217 : 4226 : nargs = 4;
12218 : 4226 : break;
12219 : 167 : case V4SF_FTYPE_V4SF_V4SF_INT_INT:
12220 : 167 : case V2DF_FTYPE_V2DF_V2DF_INT_INT:
12221 : 167 : nargs_constant = 2;
12222 : 167 : nargs = 4;
12223 : 167 : break;
12224 : 91 : case INT_FTYPE_V4SF_V4SF_INT_INT:
12225 : 91 : case INT_FTYPE_V2DF_V2DF_INT_INT:
12226 : 91 : return ix86_expand_sse_comi_round (d, exp, target);
12227 : 6145 : case V8DF_FTYPE_V8DF_V8DF_V8DF_UQI_INT:
12228 : 6145 : case V2DF_FTYPE_V2DF_V2DF_V2DF_UQI_INT:
12229 : 6145 : case V4SF_FTYPE_V4SF_V4SF_V4SF_UQI_INT:
12230 : 6145 : case V4SF_FTYPE_V8HF_V4SF_V4SF_UQI_INT:
12231 : 6145 : case V16SF_FTYPE_V16SF_V16SF_V16SF_HI_INT:
12232 : 6145 : case V32HF_FTYPE_V32HF_V32HF_V32HF_UHI_INT:
12233 : 6145 : case V32HF_FTYPE_V32HF_V32HF_V32HF_USI_INT:
12234 : 6145 : case V2DF_FTYPE_V8HF_V2DF_V2DF_UQI_INT:
12235 : 6145 : case V2DF_FTYPE_V2DF_V2DF_V2DF_QI_INT:
12236 : 6145 : case V2DF_FTYPE_V2DF_V4SF_V2DF_QI_INT:
12237 : 6145 : case V2DF_FTYPE_V2DF_V4SF_V2DF_UQI_INT:
12238 : 6145 : case V4SF_FTYPE_V4SF_V4SF_V4SF_QI_INT:
12239 : 6145 : case V4SF_FTYPE_V4SF_V2DF_V4SF_QI_INT:
12240 : 6145 : case V4SF_FTYPE_V4SF_V2DF_V4SF_UQI_INT:
12241 : 6145 : case V8HF_FTYPE_V8HF_V8HF_V8HF_UQI_INT:
12242 : 6145 : case V8HF_FTYPE_V2DF_V8HF_V8HF_UQI_INT:
12243 : 6145 : case V8HF_FTYPE_V4SF_V8HF_V8HF_UQI_INT:
12244 : 6145 : nargs = 5;
12245 : 6145 : break;
12246 : 635 : case V32HF_FTYPE_V32HF_INT_V32HF_USI_INT:
12247 : 635 : case V16SF_FTYPE_V16SF_INT_V16SF_HI_INT:
12248 : 635 : case V8DF_FTYPE_V8DF_INT_V8DF_QI_INT:
12249 : 635 : case V8DF_FTYPE_V8DF_INT_V8DF_UQI_INT:
12250 : 635 : case V16SF_FTYPE_V16SF_INT_V16SF_UHI_INT:
12251 : 635 : nargs_constant = 4;
12252 : 635 : nargs = 5;
12253 : 635 : break;
12254 : 1181 : case UQI_FTYPE_V8DF_V8DF_INT_UQI_INT:
12255 : 1181 : case UQI_FTYPE_V2DF_V2DF_INT_UQI_INT:
12256 : 1181 : case UHI_FTYPE_V16SF_V16SF_INT_UHI_INT:
12257 : 1181 : case UQI_FTYPE_V4SF_V4SF_INT_UQI_INT:
12258 : 1181 : case USI_FTYPE_V32HF_V32HF_INT_USI_INT:
12259 : 1181 : case UQI_FTYPE_V8HF_V8HF_INT_UQI_INT:
12260 : 1181 : nargs_constant = 3;
12261 : 1181 : nargs = 5;
12262 : 1181 : break;
12263 : 628 : case V16SF_FTYPE_V16SF_V16SF_INT_V16SF_HI_INT:
12264 : 628 : case V8DF_FTYPE_V8DF_V8DF_INT_V8DF_QI_INT:
12265 : 628 : case V4SF_FTYPE_V4SF_V4SF_INT_V4SF_QI_INT:
12266 : 628 : case V2DF_FTYPE_V2DF_V2DF_INT_V2DF_QI_INT:
12267 : 628 : case V2DF_FTYPE_V2DF_V2DF_INT_V2DF_UQI_INT:
12268 : 628 : case V4SF_FTYPE_V4SF_V4SF_INT_V4SF_UQI_INT:
12269 : 628 : case V8HF_FTYPE_V8HF_V8HF_INT_V8HF_UQI_INT:
12270 : 628 : nargs = 6;
12271 : 628 : nargs_constant = 4;
12272 : 628 : break;
12273 : 252 : case V8DF_FTYPE_V8DF_V8DF_V8DI_INT_QI_INT:
12274 : 252 : case V16SF_FTYPE_V16SF_V16SF_V16SI_INT_HI_INT:
12275 : 252 : case V2DF_FTYPE_V2DF_V2DF_V2DI_INT_QI_INT:
12276 : 252 : case V4SF_FTYPE_V4SF_V4SF_V4SI_INT_QI_INT:
12277 : 252 : nargs = 6;
12278 : 252 : nargs_constant = 3;
12279 : 252 : break;
12280 : 0 : default:
12281 : 0 : gcc_unreachable ();
12282 : : }
12283 : 13912 : gcc_assert (nargs <= ARRAY_SIZE (xops));
12284 : :
12285 : 14449 : if (optimize
12286 : 4030 : || target == 0
12287 : 4030 : || GET_MODE (target) != tmode
12288 : 18479 : || !insn_p->operand[0].predicate (target, tmode))
12289 : 10419 : target = gen_reg_rtx (tmode);
12290 : :
12291 : 79563 : for (i = 0; i < nargs; i++)
12292 : : {
12293 : 65669 : tree arg = CALL_EXPR_ARG (exp, i);
12294 : 65669 : rtx op = expand_normal (arg);
12295 : 65669 : machine_mode mode = insn_p->operand[i + 1].mode;
12296 : 65669 : bool match = insn_p->operand[i + 1].predicate (op, mode);
12297 : :
12298 : 65669 : if (i == nargs - nargs_constant)
12299 : : {
12300 : 2863 : if (!match)
12301 : : {
12302 : 40 : switch (icode)
12303 : : {
12304 : 12 : case CODE_FOR_avx512f_getmantv8df_mask_round:
12305 : 12 : case CODE_FOR_avx512f_getmantv16sf_mask_round:
12306 : 12 : case CODE_FOR_avx512bw_getmantv32hf_mask_round:
12307 : 12 : case CODE_FOR_avx512f_vgetmantv2df_round:
12308 : 12 : case CODE_FOR_avx512f_vgetmantv2df_mask_round:
12309 : 12 : case CODE_FOR_avx512f_vgetmantv4sf_round:
12310 : 12 : case CODE_FOR_avx512f_vgetmantv4sf_mask_round:
12311 : 12 : case CODE_FOR_avx512f_vgetmantv8hf_mask_round:
12312 : 12 : error ("the immediate argument must be a 4-bit immediate");
12313 : 12 : return const0_rtx;
12314 : 8 : case CODE_FOR_avx512f_cmpv8df3_mask_round:
12315 : 8 : case CODE_FOR_avx512f_cmpv16sf3_mask_round:
12316 : 8 : case CODE_FOR_avx512f_vmcmpv2df3_mask_round:
12317 : 8 : case CODE_FOR_avx512f_vmcmpv4sf3_mask_round:
12318 : 8 : case CODE_FOR_avx512f_vmcmpv8hf3_mask_round:
12319 : 8 : case CODE_FOR_avx512bw_cmpv32hf3_mask_round:
12320 : 8 : error ("the immediate argument must be a 5-bit immediate");
12321 : 8 : return const0_rtx;
12322 : 20 : default:
12323 : 20 : error ("the immediate argument must be an 8-bit immediate");
12324 : 20 : return const0_rtx;
12325 : : }
12326 : : }
12327 : : }
12328 : 62806 : else if (i == nargs-1)
12329 : : {
12330 : 14409 : if (!insn_p->operand[nargs].predicate (op, SImode))
12331 : : {
12332 : 515 : error ("incorrect rounding operand");
12333 : 515 : return const0_rtx;
12334 : : }
12335 : :
12336 : : /* If there is no rounding use normal version of the pattern. */
12337 : 13894 : if (INTVAL (op) == NO_ROUND)
12338 : : {
12339 : : /* Skip erasing embedded rounding for below expanders who
12340 : : generates multiple insns. In ix86_erase_embedded_rounding
12341 : : the pattern will be transformed to a single set, and emit_insn
12342 : : appends the set insead of insert it to chain. So the insns
12343 : : emitted inside define_expander would be ignored. */
12344 : 4406 : switch (icode)
12345 : : {
12346 : : case CODE_FOR_avx512bw_fmaddc_v32hf_mask1_round:
12347 : : case CODE_FOR_avx512bw_fcmaddc_v32hf_mask1_round:
12348 : : case CODE_FOR_avx512fp16_fmaddcsh_v8hf_mask1_round:
12349 : : case CODE_FOR_avx512fp16_fcmaddcsh_v8hf_mask1_round:
12350 : : case CODE_FOR_avx512fp16_fmaddcsh_v8hf_mask3_round:
12351 : : case CODE_FOR_avx512fp16_fcmaddcsh_v8hf_mask3_round:
12352 : : redundant_embed_rnd = 0;
12353 : : break;
12354 : 4374 : default:
12355 : 4374 : redundant_embed_rnd = 1;
12356 : 4374 : break;
12357 : : }
12358 : : }
12359 : : }
12360 : : else
12361 : : {
12362 : 48397 : if (VECTOR_MODE_P (mode))
12363 : 35339 : op = safe_vector_operand (op, mode);
12364 : :
12365 : 48397 : op = fixup_modeless_constant (op, mode);
12366 : :
12367 : 48397 : if (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)
12368 : : {
12369 : 41402 : if (optimize || !match)
12370 : 36681 : op = copy_to_mode_reg (mode, op);
12371 : : }
12372 : : else
12373 : : {
12374 : 6995 : op = copy_to_reg (op);
12375 : 6995 : op = lowpart_subreg (mode, op, GET_MODE (op));
12376 : : }
12377 : : }
12378 : :
12379 : 65114 : xops[i] = op;
12380 : : }
12381 : :
12382 : 13894 : switch (nargs)
12383 : : {
12384 : : case 1:
12385 : : pat = GEN_FCN (icode) (target, xops[0]);
12386 : : break;
12387 : 504 : case 2:
12388 : 504 : pat = GEN_FCN (icode) (target, xops[0], xops[1]);
12389 : 504 : break;
12390 : 634 : case 3:
12391 : 634 : pat = GEN_FCN (icode) (target, xops[0], xops[1], xops[2]);
12392 : 634 : break;
12393 : 4269 : case 4:
12394 : 4269 : pat = GEN_FCN (icode) (target, xops[0], xops[1],
12395 : : xops[2], xops[3]);
12396 : 4269 : break;
12397 : 7657 : case 5:
12398 : 7657 : pat = GEN_FCN (icode) (target, xops[0], xops[1],
12399 : : xops[2], xops[3], xops[4]);
12400 : 7657 : break;
12401 : 830 : case 6:
12402 : 830 : pat = GEN_FCN (icode) (target, xops[0], xops[1],
12403 : : xops[2], xops[3], xops[4], xops[5]);
12404 : 830 : break;
12405 : : default:
12406 : : gcc_unreachable ();
12407 : : }
12408 : :
12409 : 13894 : if (!pat)
12410 : : return 0;
12411 : :
12412 : 13894 : if (redundant_embed_rnd)
12413 : 4374 : pat = ix86_erase_embedded_rounding (pat);
12414 : :
12415 : 13894 : emit_insn (pat);
12416 : 13894 : return target;
12417 : : }
12418 : :
12419 : : /* Subroutine of ix86_expand_builtin to take care of special insns
12420 : : with variable number of operands. */
12421 : :
12422 : : static rtx
12423 : 27009 : ix86_expand_special_args_builtin (const struct builtin_description *d,
12424 : : tree exp, rtx target)
12425 : : {
12426 : 27009 : tree arg;
12427 : 27009 : rtx pat, op;
12428 : 27009 : unsigned int i, nargs, arg_adjust, memory;
12429 : 27009 : unsigned int constant = 100;
12430 : 27009 : bool aligned_mem = false;
12431 : 27009 : rtx xops[4];
12432 : 27009 : enum insn_code icode = d->icode;
12433 : 27009 : const struct insn_data_d *insn_p = &insn_data[icode];
12434 : 27009 : machine_mode tmode = insn_p->operand[0].mode;
12435 : 27009 : enum { load, store } klass;
12436 : :
12437 : 27009 : switch ((enum ix86_builtin_func_type) d->flag)
12438 : : {
12439 : 15624 : case VOID_FTYPE_VOID:
12440 : 15624 : emit_insn (GEN_FCN (icode) (target));
12441 : 15624 : return 0;
12442 : : case VOID_FTYPE_UINT64:
12443 : : case VOID_FTYPE_UNSIGNED:
12444 : : nargs = 0;
12445 : : klass = store;
12446 : : memory = 0;
12447 : : break;
12448 : :
12449 : 7573 : case INT_FTYPE_VOID:
12450 : 7573 : case USHORT_FTYPE_VOID:
12451 : 7573 : case UINT64_FTYPE_VOID:
12452 : 7573 : case UINT_FTYPE_VOID:
12453 : 7573 : case UINT8_FTYPE_VOID:
12454 : 7573 : case UNSIGNED_FTYPE_VOID:
12455 : 7573 : nargs = 0;
12456 : 7573 : klass = load;
12457 : 7573 : memory = 0;
12458 : 7573 : break;
12459 : 314 : case UINT64_FTYPE_PUNSIGNED:
12460 : 314 : case V2DI_FTYPE_PV2DI:
12461 : 314 : case V4DI_FTYPE_PV4DI:
12462 : 314 : case V32QI_FTYPE_PCCHAR:
12463 : 314 : case V16QI_FTYPE_PCCHAR:
12464 : 314 : case V8SF_FTYPE_PCV4SF:
12465 : 314 : case V8SF_FTYPE_PCFLOAT:
12466 : 314 : case V4SF_FTYPE_PCFLOAT:
12467 : 314 : case V4SF_FTYPE_PCFLOAT16:
12468 : 314 : case V4SF_FTYPE_PCBFLOAT16:
12469 : 314 : case V4SF_FTYPE_PCV8BF:
12470 : 314 : case V4SF_FTYPE_PCV8HF:
12471 : 314 : case V8SF_FTYPE_PCFLOAT16:
12472 : 314 : case V8SF_FTYPE_PCBFLOAT16:
12473 : 314 : case V8SF_FTYPE_PCV16HF:
12474 : 314 : case V8SF_FTYPE_PCV16BF:
12475 : 314 : case V4DF_FTYPE_PCV2DF:
12476 : 314 : case V4DF_FTYPE_PCDOUBLE:
12477 : 314 : case V2DF_FTYPE_PCDOUBLE:
12478 : 314 : case VOID_FTYPE_PVOID:
12479 : 314 : case V8DI_FTYPE_PV8DI:
12480 : 314 : nargs = 1;
12481 : 314 : klass = load;
12482 : 314 : memory = 0;
12483 : 314 : switch (icode)
12484 : : {
12485 : 39 : case CODE_FOR_sse4_1_movntdqa:
12486 : 39 : case CODE_FOR_avx2_movntdqa:
12487 : 39 : case CODE_FOR_avx512f_movntdqa:
12488 : 39 : aligned_mem = true;
12489 : 39 : break;
12490 : : default:
12491 : : break;
12492 : : }
12493 : : break;
12494 : 372 : case VOID_FTYPE_PV2SF_V4SF:
12495 : 372 : case VOID_FTYPE_PV8DI_V8DI:
12496 : 372 : case VOID_FTYPE_PV4DI_V4DI:
12497 : 372 : case VOID_FTYPE_PV2DI_V2DI:
12498 : 372 : case VOID_FTYPE_PCHAR_V32QI:
12499 : 372 : case VOID_FTYPE_PCHAR_V16QI:
12500 : 372 : case VOID_FTYPE_PFLOAT_V16SF:
12501 : 372 : case VOID_FTYPE_PFLOAT_V8SF:
12502 : 372 : case VOID_FTYPE_PFLOAT_V4SF:
12503 : 372 : case VOID_FTYPE_PDOUBLE_V8DF:
12504 : 372 : case VOID_FTYPE_PDOUBLE_V4DF:
12505 : 372 : case VOID_FTYPE_PDOUBLE_V2DF:
12506 : 372 : case VOID_FTYPE_PLONGLONG_LONGLONG:
12507 : 372 : case VOID_FTYPE_PULONGLONG_ULONGLONG:
12508 : 372 : case VOID_FTYPE_PUNSIGNED_UNSIGNED:
12509 : 372 : case VOID_FTYPE_PINT_INT:
12510 : 372 : nargs = 1;
12511 : 372 : klass = store;
12512 : : /* Reserve memory operand for target. */
12513 : 372 : memory = ARRAY_SIZE (xops);
12514 : 372 : switch (icode)
12515 : : {
12516 : : /* These builtins and instructions require the memory
12517 : : to be properly aligned. */
12518 : 157 : case CODE_FOR_avx_movntv4di:
12519 : 157 : case CODE_FOR_sse2_movntv2di:
12520 : 157 : case CODE_FOR_avx_movntv8sf:
12521 : 157 : case CODE_FOR_sse_movntv4sf:
12522 : 157 : case CODE_FOR_sse4a_vmmovntv4sf:
12523 : 157 : case CODE_FOR_avx_movntv4df:
12524 : 157 : case CODE_FOR_sse2_movntv2df:
12525 : 157 : case CODE_FOR_sse4a_vmmovntv2df:
12526 : 157 : case CODE_FOR_sse2_movntidi:
12527 : 157 : case CODE_FOR_sse_movntq:
12528 : 157 : case CODE_FOR_sse2_movntisi:
12529 : 157 : case CODE_FOR_avx512f_movntv16sf:
12530 : 157 : case CODE_FOR_avx512f_movntv8df:
12531 : 157 : case CODE_FOR_avx512f_movntv8di:
12532 : 157 : aligned_mem = true;
12533 : 157 : break;
12534 : : default:
12535 : : break;
12536 : : }
12537 : : break;
12538 : 0 : case VOID_FTYPE_PVOID_PCVOID:
12539 : 0 : nargs = 1;
12540 : 0 : klass = store;
12541 : 0 : memory = 0;
12542 : :
12543 : 0 : break;
12544 : 52 : case V4SF_FTYPE_V4SF_PCV2SF:
12545 : 52 : case V2DF_FTYPE_V2DF_PCDOUBLE:
12546 : 52 : nargs = 2;
12547 : 52 : klass = load;
12548 : 52 : memory = 1;
12549 : 52 : break;
12550 : 93 : case V8SF_FTYPE_PCV8SF_V8SI:
12551 : 93 : case V4DF_FTYPE_PCV4DF_V4DI:
12552 : 93 : case V4SF_FTYPE_PCV4SF_V4SI:
12553 : 93 : case V2DF_FTYPE_PCV2DF_V2DI:
12554 : 93 : case V8SI_FTYPE_PCV8SI_V8SI:
12555 : 93 : case V4DI_FTYPE_PCV4DI_V4DI:
12556 : 93 : case V4SI_FTYPE_PCV4SI_V4SI:
12557 : 93 : case V2DI_FTYPE_PCV2DI_V2DI:
12558 : 93 : case VOID_FTYPE_INT_INT64:
12559 : 93 : nargs = 2;
12560 : 93 : klass = load;
12561 : 93 : memory = 0;
12562 : 93 : break;
12563 : 360 : case VOID_FTYPE_PV8DF_V8DF_UQI:
12564 : 360 : case VOID_FTYPE_PV4DF_V4DF_UQI:
12565 : 360 : case VOID_FTYPE_PV2DF_V2DF_UQI:
12566 : 360 : case VOID_FTYPE_PV16SF_V16SF_UHI:
12567 : 360 : case VOID_FTYPE_PV8SF_V8SF_UQI:
12568 : 360 : case VOID_FTYPE_PV4SF_V4SF_UQI:
12569 : 360 : case VOID_FTYPE_PV8DI_V8DI_UQI:
12570 : 360 : case VOID_FTYPE_PV4DI_V4DI_UQI:
12571 : 360 : case VOID_FTYPE_PV2DI_V2DI_UQI:
12572 : 360 : case VOID_FTYPE_PV16SI_V16SI_UHI:
12573 : 360 : case VOID_FTYPE_PV8SI_V8SI_UQI:
12574 : 360 : case VOID_FTYPE_PV4SI_V4SI_UQI:
12575 : 360 : case VOID_FTYPE_PV64QI_V64QI_UDI:
12576 : 360 : case VOID_FTYPE_PV32HI_V32HI_USI:
12577 : 360 : case VOID_FTYPE_PV32QI_V32QI_USI:
12578 : 360 : case VOID_FTYPE_PV16QI_V16QI_UHI:
12579 : 360 : case VOID_FTYPE_PV16HI_V16HI_UHI:
12580 : 360 : case VOID_FTYPE_PV8HI_V8HI_UQI:
12581 : 360 : switch (icode)
12582 : : {
12583 : : /* These builtins and instructions require the memory
12584 : : to be properly aligned. */
12585 : : case CODE_FOR_avx512f_storev16sf_mask:
12586 : : case CODE_FOR_avx512f_storev16si_mask:
12587 : : case CODE_FOR_avx512f_storev8df_mask:
12588 : : case CODE_FOR_avx512f_storev8di_mask:
12589 : : case CODE_FOR_avx512vl_storev8sf_mask:
12590 : : case CODE_FOR_avx512vl_storev8si_mask:
12591 : : case CODE_FOR_avx512vl_storev4df_mask:
12592 : : case CODE_FOR_avx512vl_storev4di_mask:
12593 : : case CODE_FOR_avx512vl_storev4sf_mask:
12594 : : case CODE_FOR_avx512vl_storev4si_mask:
12595 : : case CODE_FOR_avx512vl_storev2df_mask:
12596 : : case CODE_FOR_avx512vl_storev2di_mask:
12597 : 11385 : aligned_mem = true;
12598 : : break;
12599 : : default:
12600 : : break;
12601 : : }
12602 : : /* FALLTHRU */
12603 : : case VOID_FTYPE_PV8SF_V8SI_V8SF:
12604 : : case VOID_FTYPE_PV4DF_V4DI_V4DF:
12605 : : case VOID_FTYPE_PV4SF_V4SI_V4SF:
12606 : : case VOID_FTYPE_PV2DF_V2DI_V2DF:
12607 : : case VOID_FTYPE_PV8SI_V8SI_V8SI:
12608 : : case VOID_FTYPE_PV4DI_V4DI_V4DI:
12609 : : case VOID_FTYPE_PV4SI_V4SI_V4SI:
12610 : : case VOID_FTYPE_PV2DI_V2DI_V2DI:
12611 : : case VOID_FTYPE_PV8SI_V8DI_UQI:
12612 : : case VOID_FTYPE_PV8HI_V8DI_UQI:
12613 : : case VOID_FTYPE_PV16HI_V16SI_UHI:
12614 : : case VOID_FTYPE_PUDI_V8DI_UQI:
12615 : : case VOID_FTYPE_PV16QI_V16SI_UHI:
12616 : : case VOID_FTYPE_PV4SI_V4DI_UQI:
12617 : : case VOID_FTYPE_PUDI_V2DI_UQI:
12618 : : case VOID_FTYPE_PUDI_V4DI_UQI:
12619 : : case VOID_FTYPE_PUSI_V2DI_UQI:
12620 : : case VOID_FTYPE_PV8HI_V8SI_UQI:
12621 : : case VOID_FTYPE_PUDI_V4SI_UQI:
12622 : : case VOID_FTYPE_PUSI_V4DI_UQI:
12623 : : case VOID_FTYPE_PUHI_V2DI_UQI:
12624 : : case VOID_FTYPE_PUDI_V8SI_UQI:
12625 : : case VOID_FTYPE_PUSI_V4SI_UQI:
12626 : : case VOID_FTYPE_PCHAR_V64QI_UDI:
12627 : : case VOID_FTYPE_PCHAR_V32QI_USI:
12628 : : case VOID_FTYPE_PCHAR_V16QI_UHI:
12629 : : case VOID_FTYPE_PSHORT_V32HI_USI:
12630 : : case VOID_FTYPE_PSHORT_V16HI_UHI:
12631 : : case VOID_FTYPE_PSHORT_V8HI_UQI:
12632 : : case VOID_FTYPE_PINT_V16SI_UHI:
12633 : : case VOID_FTYPE_PINT_V8SI_UQI:
12634 : : case VOID_FTYPE_PINT_V4SI_UQI:
12635 : : case VOID_FTYPE_PINT64_V8DI_UQI:
12636 : : case VOID_FTYPE_PINT64_V4DI_UQI:
12637 : : case VOID_FTYPE_PINT64_V2DI_UQI:
12638 : : case VOID_FTYPE_PDOUBLE_V8DF_UQI:
12639 : : case VOID_FTYPE_PDOUBLE_V4DF_UQI:
12640 : : case VOID_FTYPE_PDOUBLE_V2DF_UQI:
12641 : : case VOID_FTYPE_PFLOAT_V16SF_UHI:
12642 : : case VOID_FTYPE_PFLOAT_V8SF_UQI:
12643 : : case VOID_FTYPE_PFLOAT_V4SF_UQI:
12644 : : case VOID_FTYPE_PCFLOAT16_V8HF_UQI:
12645 : : case VOID_FTYPE_PV32QI_V32HI_USI:
12646 : : case VOID_FTYPE_PV16QI_V16HI_UHI:
12647 : : case VOID_FTYPE_PUDI_V8HI_UQI:
12648 : : nargs = 2;
12649 : : klass = store;
12650 : : /* Reserve memory operand for target. */
12651 : : memory = ARRAY_SIZE (xops);
12652 : : break;
12653 : 847 : case V4SF_FTYPE_PCV4SF_V4SF_UQI:
12654 : 847 : case V8SF_FTYPE_PCV8SF_V8SF_UQI:
12655 : 847 : case V16SF_FTYPE_PCV16SF_V16SF_UHI:
12656 : 847 : case V4SI_FTYPE_PCV4SI_V4SI_UQI:
12657 : 847 : case V8SI_FTYPE_PCV8SI_V8SI_UQI:
12658 : 847 : case V16SI_FTYPE_PCV16SI_V16SI_UHI:
12659 : 847 : case V2DF_FTYPE_PCV2DF_V2DF_UQI:
12660 : 847 : case V4DF_FTYPE_PCV4DF_V4DF_UQI:
12661 : 847 : case V8DF_FTYPE_PCV8DF_V8DF_UQI:
12662 : 847 : case V2DI_FTYPE_PCV2DI_V2DI_UQI:
12663 : 847 : case V4DI_FTYPE_PCV4DI_V4DI_UQI:
12664 : 847 : case V8DI_FTYPE_PCV8DI_V8DI_UQI:
12665 : 847 : case V64QI_FTYPE_PCV64QI_V64QI_UDI:
12666 : 847 : case V32HI_FTYPE_PCV32HI_V32HI_USI:
12667 : 847 : case V32QI_FTYPE_PCV32QI_V32QI_USI:
12668 : 847 : case V16QI_FTYPE_PCV16QI_V16QI_UHI:
12669 : 847 : case V16HI_FTYPE_PCV16HI_V16HI_UHI:
12670 : 847 : case V8HI_FTYPE_PCV8HI_V8HI_UQI:
12671 : 847 : switch (icode)
12672 : : {
12673 : : /* These builtins and instructions require the memory
12674 : : to be properly aligned. */
12675 : : case CODE_FOR_avx512f_loadv16sf_mask:
12676 : : case CODE_FOR_avx512f_loadv16si_mask:
12677 : : case CODE_FOR_avx512f_loadv8df_mask:
12678 : : case CODE_FOR_avx512f_loadv8di_mask:
12679 : : case CODE_FOR_avx512vl_loadv8sf_mask:
12680 : : case CODE_FOR_avx512vl_loadv8si_mask:
12681 : : case CODE_FOR_avx512vl_loadv4df_mask:
12682 : : case CODE_FOR_avx512vl_loadv4di_mask:
12683 : : case CODE_FOR_avx512vl_loadv4sf_mask:
12684 : : case CODE_FOR_avx512vl_loadv4si_mask:
12685 : : case CODE_FOR_avx512vl_loadv2df_mask:
12686 : : case CODE_FOR_avx512vl_loadv2di_mask:
12687 : : case CODE_FOR_avx512bw_loadv64qi_mask:
12688 : : case CODE_FOR_avx512vl_loadv32qi_mask:
12689 : : case CODE_FOR_avx512vl_loadv16qi_mask:
12690 : : case CODE_FOR_avx512bw_loadv32hi_mask:
12691 : : case CODE_FOR_avx512vl_loadv16hi_mask:
12692 : : case CODE_FOR_avx512vl_loadv8hi_mask:
12693 : 11385 : aligned_mem = true;
12694 : : break;
12695 : : default:
12696 : : break;
12697 : : }
12698 : : /* FALLTHRU */
12699 : : case V64QI_FTYPE_PCCHAR_V64QI_UDI:
12700 : : case V32QI_FTYPE_PCCHAR_V32QI_USI:
12701 : : case V16QI_FTYPE_PCCHAR_V16QI_UHI:
12702 : : case V32HI_FTYPE_PCSHORT_V32HI_USI:
12703 : : case V16HI_FTYPE_PCSHORT_V16HI_UHI:
12704 : : case V8HI_FTYPE_PCSHORT_V8HI_UQI:
12705 : : case V16SI_FTYPE_PCINT_V16SI_UHI:
12706 : : case V8SI_FTYPE_PCINT_V8SI_UQI:
12707 : : case V4SI_FTYPE_PCINT_V4SI_UQI:
12708 : : case V8DI_FTYPE_PCINT64_V8DI_UQI:
12709 : : case V4DI_FTYPE_PCINT64_V4DI_UQI:
12710 : : case V2DI_FTYPE_PCINT64_V2DI_UQI:
12711 : : case V8DF_FTYPE_PCDOUBLE_V8DF_UQI:
12712 : : case V4DF_FTYPE_PCDOUBLE_V4DF_UQI:
12713 : : case V2DF_FTYPE_PCDOUBLE_V2DF_UQI:
12714 : : case V16SF_FTYPE_PCFLOAT_V16SF_UHI:
12715 : : case V8SF_FTYPE_PCFLOAT_V8SF_UQI:
12716 : : case V4SF_FTYPE_PCFLOAT_V4SF_UQI:
12717 : : case V8HF_FTYPE_PCFLOAT16_V8HF_UQI:
12718 : : nargs = 3;
12719 : : klass = load;
12720 : : memory = 0;
12721 : : break;
12722 : 105 : case INT_FTYPE_PINT_INT_INT_INT:
12723 : 105 : case LONGLONG_FTYPE_PLONGLONG_LONGLONG_LONGLONG_INT:
12724 : 105 : nargs = 4;
12725 : 105 : klass = load;
12726 : 105 : memory = 0;
12727 : 105 : constant = 3;
12728 : 105 : break;
12729 : 0 : default:
12730 : 0 : gcc_unreachable ();
12731 : : }
12732 : :
12733 : 11385 : gcc_assert (nargs <= ARRAY_SIZE (xops));
12734 : :
12735 : 11385 : if (klass == store)
12736 : : {
12737 : 1874 : arg = CALL_EXPR_ARG (exp, 0);
12738 : 1874 : op = expand_normal (arg);
12739 : 1874 : gcc_assert (target == 0);
12740 : 1874 : if (memory)
12741 : : {
12742 : 1715 : op = ix86_zero_extend_to_Pmode (op);
12743 : 1715 : target = gen_rtx_MEM (tmode, op);
12744 : : /* target at this point has just BITS_PER_UNIT MEM_ALIGN
12745 : : on it. Try to improve it using get_pointer_alignment,
12746 : : and if the special builtin is one that requires strict
12747 : : mode alignment, also from it's GET_MODE_ALIGNMENT.
12748 : : Failure to do so could lead to ix86_legitimate_combined_insn
12749 : : rejecting all changes to such insns. */
12750 : 1715 : unsigned int align = get_pointer_alignment (arg);
12751 : 1715 : if (aligned_mem && align < GET_MODE_ALIGNMENT (tmode))
12752 : 275 : align = GET_MODE_ALIGNMENT (tmode);
12753 : 3430 : if (MEM_ALIGN (target) < align)
12754 : 421 : set_mem_align (target, align);
12755 : : }
12756 : : else
12757 : 159 : target = force_reg (tmode, op);
12758 : : arg_adjust = 1;
12759 : : }
12760 : : else
12761 : : {
12762 : 9511 : arg_adjust = 0;
12763 : 9511 : if (optimize
12764 : 2766 : || target == 0
12765 : 2766 : || !register_operand (target, tmode)
12766 : 12266 : || GET_MODE (target) != tmode)
12767 : 6756 : target = gen_reg_rtx (tmode);
12768 : : }
12769 : :
12770 : 19589 : for (i = 0; i < nargs; i++)
12771 : : {
12772 : 8204 : machine_mode mode = insn_p->operand[i + 1].mode;
12773 : :
12774 : 8204 : arg = CALL_EXPR_ARG (exp, i + arg_adjust);
12775 : 8204 : op = expand_normal (arg);
12776 : :
12777 : 8204 : if (i == memory)
12778 : : {
12779 : : /* This must be the memory operand. */
12780 : 1938 : op = ix86_zero_extend_to_Pmode (op);
12781 : 1938 : op = gen_rtx_MEM (mode, op);
12782 : : /* op at this point has just BITS_PER_UNIT MEM_ALIGN
12783 : : on it. Try to improve it using get_pointer_alignment,
12784 : : and if the special builtin is one that requires strict
12785 : : mode alignment, also from it's GET_MODE_ALIGNMENT.
12786 : : Failure to do so could lead to ix86_legitimate_combined_insn
12787 : : rejecting all changes to such insns. */
12788 : 1938 : unsigned int align = get_pointer_alignment (arg);
12789 : 1938 : if (aligned_mem && align < GET_MODE_ALIGNMENT (mode))
12790 : 299 : align = GET_MODE_ALIGNMENT (mode);
12791 : 3876 : if (MEM_ALIGN (op) < align)
12792 : 528 : set_mem_align (op, align);
12793 : : }
12794 : 6266 : else if (i == constant)
12795 : : {
12796 : : /* This must be the constant. */
12797 : 105 : if (!insn_p->operand[nargs].predicate(op, SImode))
12798 : : {
12799 : 0 : error ("the fourth argument must be one of enum %qs", "_CMPCCX_ENUM");
12800 : 0 : return const0_rtx;
12801 : : }
12802 : : }
12803 : : else
12804 : : {
12805 : : /* This must be register. */
12806 : 6161 : if (VECTOR_MODE_P (mode))
12807 : 3103 : op = safe_vector_operand (op, mode);
12808 : :
12809 : 6161 : op = fixup_modeless_constant (op, mode);
12810 : :
12811 : : /* NB: 3-operands load implied it's a mask load or v{p}expand*,
12812 : : and that mask operand shoud be at the end.
12813 : : Keep all-ones mask which would be simplified by the expander. */
12814 : 1374 : if (nargs == 3 && i == 2 && klass == load
12815 : 1374 : && constm1_operand (op, mode)
12816 : 6202 : && insn_p->operand[i].predicate (op, mode))
12817 : : ;
12818 : 6161 : else if (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)
12819 : 4126 : op = copy_to_mode_reg (mode, op);
12820 : : else
12821 : : {
12822 : 2035 : op = copy_to_reg (op);
12823 : 2035 : op = lowpart_subreg (mode, op, GET_MODE (op));
12824 : : }
12825 : : }
12826 : :
12827 : 8204 : xops[i]= op;
12828 : : }
12829 : :
12830 : 11385 : switch (nargs)
12831 : : {
12832 : 7732 : case 0:
12833 : 7732 : pat = GEN_FCN (icode) (target);
12834 : 7732 : break;
12835 : 686 : case 1:
12836 : 686 : pat = GEN_FCN (icode) (target, xops[0]);
12837 : 686 : break;
12838 : 1488 : case 2:
12839 : 1488 : pat = GEN_FCN (icode) (target, xops[0], xops[1]);
12840 : 1488 : break;
12841 : 1374 : case 3:
12842 : 1374 : pat = GEN_FCN (icode) (target, xops[0], xops[1], xops[2]);
12843 : 1374 : break;
12844 : 105 : case 4:
12845 : 105 : pat = GEN_FCN (icode) (target, xops[0], xops[1], xops[2], xops[3]);
12846 : 105 : break;
12847 : : default:
12848 : : gcc_unreachable ();
12849 : : }
12850 : :
12851 : 11385 : if (! pat)
12852 : : return 0;
12853 : :
12854 : 11385 : emit_insn (pat);
12855 : 11385 : return klass == store ? 0 : target;
12856 : : }
12857 : :
12858 : : /* Return the integer constant in ARG. Constrain it to be in the range
12859 : : of the subparts of VEC_TYPE; issue an error if not. */
12860 : :
12861 : : static int
12862 : 591 : get_element_number (tree vec_type, tree arg)
12863 : : {
12864 : 591 : unsigned HOST_WIDE_INT elt, max = TYPE_VECTOR_SUBPARTS (vec_type) - 1;
12865 : :
12866 : 591 : if (!tree_fits_uhwi_p (arg)
12867 : 591 : || (elt = tree_to_uhwi (arg), elt > max))
12868 : : {
12869 : 0 : error ("selector must be an integer constant in the range "
12870 : : "[0, %wi]", max);
12871 : 0 : return 0;
12872 : : }
12873 : :
12874 : 591 : return elt;
12875 : : }
12876 : :
12877 : : /* A subroutine of ix86_expand_builtin. These builtins are a wrapper around
12878 : : ix86_expand_vector_init. We DO have language-level syntax for this, in
12879 : : the form of (type){ init-list }. Except that since we can't place emms
12880 : : instructions from inside the compiler, we can't allow the use of MMX
12881 : : registers unless the user explicitly asks for it. So we do *not* define
12882 : : vec_set/vec_extract/vec_init patterns for MMX modes in mmx.md. Instead
12883 : : we have builtins invoked by mmintrin.h that gives us license to emit
12884 : : these sorts of instructions. */
12885 : :
12886 : : static rtx
12887 : 230 : ix86_expand_vec_init_builtin (tree type, tree exp, rtx target)
12888 : : {
12889 : 230 : machine_mode tmode = TYPE_MODE (type);
12890 : 230 : machine_mode inner_mode = GET_MODE_INNER (tmode);
12891 : 230 : int i, n_elt = GET_MODE_NUNITS (tmode);
12892 : 230 : rtvec v = rtvec_alloc (n_elt);
12893 : :
12894 : 230 : gcc_assert (VECTOR_MODE_P (tmode));
12895 : 230 : gcc_assert (call_expr_nargs (exp) == n_elt);
12896 : :
12897 : 1206 : for (i = 0; i < n_elt; ++i)
12898 : : {
12899 : 976 : rtx x = expand_normal (CALL_EXPR_ARG (exp, i));
12900 : 976 : RTVEC_ELT (v, i) = gen_lowpart (inner_mode, x);
12901 : : }
12902 : :
12903 : 230 : if (!target || !register_operand (target, tmode))
12904 : 0 : target = gen_reg_rtx (tmode);
12905 : :
12906 : 230 : ix86_expand_vector_init (true, target, gen_rtx_PARALLEL (tmode, v));
12907 : 230 : return target;
12908 : : }
12909 : :
12910 : : /* A subroutine of ix86_expand_builtin. These builtins are a wrapper around
12911 : : ix86_expand_vector_extract. They would be redundant (for non-MMX) if we
12912 : : had a language-level syntax for referencing vector elements. */
12913 : :
12914 : : static rtx
12915 : 387 : ix86_expand_vec_ext_builtin (tree exp, rtx target)
12916 : : {
12917 : 387 : machine_mode tmode, mode0;
12918 : 387 : tree arg0, arg1;
12919 : 387 : int elt;
12920 : 387 : rtx op0;
12921 : :
12922 : 387 : arg0 = CALL_EXPR_ARG (exp, 0);
12923 : 387 : arg1 = CALL_EXPR_ARG (exp, 1);
12924 : :
12925 : 387 : op0 = expand_normal (arg0);
12926 : 387 : elt = get_element_number (TREE_TYPE (arg0), arg1);
12927 : :
12928 : 387 : tmode = TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0)));
12929 : 387 : mode0 = TYPE_MODE (TREE_TYPE (arg0));
12930 : 387 : gcc_assert (VECTOR_MODE_P (mode0));
12931 : :
12932 : 387 : op0 = force_reg (mode0, op0);
12933 : :
12934 : 387 : if (optimize || !target || !register_operand (target, tmode))
12935 : 308 : target = gen_reg_rtx (tmode);
12936 : :
12937 : 387 : ix86_expand_vector_extract (true, target, op0, elt);
12938 : :
12939 : 387 : return target;
12940 : : }
12941 : :
12942 : : /* A subroutine of ix86_expand_builtin. These builtins are a wrapper around
12943 : : ix86_expand_vector_set. They would be redundant (for non-MMX) if we had
12944 : : a language-level syntax for referencing vector elements. */
12945 : :
12946 : : static rtx
12947 : 204 : ix86_expand_vec_set_builtin (tree exp)
12948 : : {
12949 : 204 : machine_mode tmode, mode1;
12950 : 204 : tree arg0, arg1, arg2;
12951 : 204 : int elt;
12952 : 204 : rtx op0, op1, target;
12953 : :
12954 : 204 : arg0 = CALL_EXPR_ARG (exp, 0);
12955 : 204 : arg1 = CALL_EXPR_ARG (exp, 1);
12956 : 204 : arg2 = CALL_EXPR_ARG (exp, 2);
12957 : :
12958 : 204 : tmode = TYPE_MODE (TREE_TYPE (arg0));
12959 : 204 : mode1 = TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0)));
12960 : 204 : gcc_assert (VECTOR_MODE_P (tmode));
12961 : :
12962 : 204 : op0 = expand_expr (arg0, NULL_RTX, tmode, EXPAND_NORMAL);
12963 : 204 : op1 = expand_expr (arg1, NULL_RTX, mode1, EXPAND_NORMAL);
12964 : 204 : elt = get_element_number (TREE_TYPE (arg0), arg2);
12965 : :
12966 : 204 : if (GET_MODE (op1) != mode1)
12967 : 156 : op1 = convert_modes (mode1, GET_MODE (op1), op1, true);
12968 : :
12969 : 204 : op0 = force_reg (tmode, op0);
12970 : 204 : op1 = force_reg (mode1, op1);
12971 : :
12972 : : /* OP0 is the source of these builtin functions and shouldn't be
12973 : : modified. Create a copy, use it and return it as target. */
12974 : 204 : target = gen_reg_rtx (tmode);
12975 : 204 : emit_move_insn (target, op0);
12976 : 204 : ix86_expand_vector_set (true, target, op1, elt);
12977 : :
12978 : 204 : return target;
12979 : : }
12980 : :
12981 : : /* Return true if the necessary isa options for this builtin exist,
12982 : : else false.
12983 : : fcode = DECL_MD_FUNCTION_CODE (fndecl); */
12984 : : bool
12985 : 1196215 : ix86_check_builtin_isa_match (unsigned int fcode,
12986 : : HOST_WIDE_INT* pbisa,
12987 : : HOST_WIDE_INT* pbisa2)
12988 : : {
12989 : 1196215 : HOST_WIDE_INT isa = ix86_isa_flags;
12990 : 1196215 : HOST_WIDE_INT isa2 = ix86_isa_flags2;
12991 : 1196215 : HOST_WIDE_INT bisa = ix86_builtins_isa[fcode].isa;
12992 : 1196215 : HOST_WIDE_INT bisa2 = ix86_builtins_isa[fcode].isa2;
12993 : 1196215 : HOST_WIDE_INT tmp_isa = isa, tmp_isa2 = isa2;
12994 : : /* The general case is we require all the ISAs specified in bisa{,2}
12995 : : to be enabled.
12996 : : The exceptions are:
12997 : : OPTION_MASK_ISA_SSE | OPTION_MASK_ISA_3DNOW_A
12998 : : OPTION_MASK_ISA_SSE4_2 | OPTION_MASK_ISA_CRC32
12999 : : OPTION_MASK_ISA_FMA | OPTION_MASK_ISA_FMA4
13000 : : (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL) or
13001 : : OPTION_MASK_ISA2_AVXVNNI
13002 : : (OPTION_MASK_ISA_AVX512IFMA | OPTION_MASK_ISA_AVX512VL) or
13003 : : OPTION_MASK_ISA2_AVXIFMA
13004 : : (OPTION_MASK_ISA_AVX512VL | OPTION_MASK_ISA2_AVX512BF16) or
13005 : : OPTION_MASK_ISA2_AVXNECONVERT
13006 : : OPTION_MASK_ISA_AES or (OPTION_MASK_ISA_AVX512VL | OPTION_MASK_ISA2_VAES)
13007 : : where for each such pair it is sufficient if either of the ISAs is
13008 : : enabled, plus if it is ored with other options also those others.
13009 : : OPTION_MASK_ISA_MMX in bisa is satisfied also if TARGET_MMX_WITH_SSE. */
13010 : :
13011 : : #define SHARE_BUILTIN(A1, A2, B1, B2) \
13012 : : if ((((bisa & (A1)) == (A1) && (bisa2 & (A2)) == (A2)) \
13013 : : && ((bisa & (B1)) == (B1) && (bisa2 & (B2)) == (B2))) \
13014 : : && (((isa & (A1)) == (A1) && (isa2 & (A2)) == (A2)) \
13015 : : || ((isa & (B1)) == (B1) && (isa2 & (B2)) == (B2)))) \
13016 : : { \
13017 : : tmp_isa |= (A1) | (B1); \
13018 : : tmp_isa2 |= (A2) | (B2); \
13019 : : }
13020 : :
13021 : 1196215 : SHARE_BUILTIN (OPTION_MASK_ISA_SSE, 0, OPTION_MASK_ISA_3DNOW_A, 0);
13022 : 1196215 : SHARE_BUILTIN (OPTION_MASK_ISA_SSE4_2, 0, OPTION_MASK_ISA_CRC32, 0);
13023 : 1196215 : SHARE_BUILTIN (OPTION_MASK_ISA_FMA, 0, OPTION_MASK_ISA_FMA4, 0);
13024 : 1196215 : SHARE_BUILTIN (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, 0,
13025 : 1196215 : OPTION_MASK_ISA2_AVXVNNI);
13026 : 1196215 : SHARE_BUILTIN (OPTION_MASK_ISA_AVX512IFMA | OPTION_MASK_ISA_AVX512VL, 0, 0,
13027 : 1196215 : OPTION_MASK_ISA2_AVXIFMA);
13028 : 1196215 : SHARE_BUILTIN (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512BF16, 0,
13029 : 1196215 : OPTION_MASK_ISA2_AVXNECONVERT);
13030 : 1196215 : SHARE_BUILTIN (OPTION_MASK_ISA_AES, 0, OPTION_MASK_ISA_AVX512VL,
13031 : 1196215 : OPTION_MASK_ISA2_VAES);
13032 : 1196215 : isa = tmp_isa;
13033 : 1196215 : isa2 = tmp_isa2;
13034 : :
13035 : 1196215 : if ((bisa & OPTION_MASK_ISA_MMX) && !TARGET_MMX && TARGET_MMX_WITH_SSE
13036 : : /* __builtin_ia32_maskmovq requires MMX registers. */
13037 : 4515 : && fcode != IX86_BUILTIN_MASKMOVQ)
13038 : : {
13039 : 4506 : bisa &= ~OPTION_MASK_ISA_MMX;
13040 : 4506 : bisa |= OPTION_MASK_ISA_SSE2;
13041 : : }
13042 : :
13043 : 1196215 : if (pbisa)
13044 : 162566 : *pbisa = bisa;
13045 : 1196215 : if (pbisa2)
13046 : 162566 : *pbisa2 = bisa2;
13047 : :
13048 : 1196215 : return (bisa & isa) == bisa && (bisa2 & isa2) == bisa2;
13049 : : }
13050 : :
13051 : : /* Emit instructions to set the carry flag from ARG. */
13052 : :
13053 : : void
13054 : 12760 : ix86_expand_carry (rtx arg)
13055 : : {
13056 : 12760 : if (!CONST_INT_P (arg) || arg == const0_rtx)
13057 : : {
13058 : 12754 : arg = convert_to_mode (QImode, arg, 1);
13059 : 12754 : arg = copy_to_mode_reg (QImode, arg);
13060 : 12754 : emit_insn (gen_addqi3_cconly_overflow (arg, constm1_rtx));
13061 : : }
13062 : : else
13063 : 6 : emit_insn (gen_x86_stc ());
13064 : 12760 : }
13065 : :
13066 : : /* Expand an expression EXP that calls a built-in function,
13067 : : with result going to TARGET if that's convenient
13068 : : (and in mode MODE if that's convenient).
13069 : : SUBTARGET may be used as the target for computing one of EXP's operands.
13070 : : IGNORE is nonzero if the value is to be ignored. */
13071 : :
13072 : : rtx
13073 : 163383 : ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
13074 : : machine_mode mode, int ignore)
13075 : : {
13076 : 163383 : size_t i;
13077 : 163383 : enum insn_code icode, icode2;
13078 : 163383 : tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
13079 : 163383 : tree arg0, arg1, arg2, arg3, arg4;
13080 : 163383 : rtx op0, op1, op2, op3, op4, pat, pat2, insn;
13081 : 163383 : machine_mode mode0, mode1, mode2, mode3, mode4;
13082 : 163383 : unsigned int fcode = DECL_MD_FUNCTION_CODE (fndecl);
13083 : 163383 : HOST_WIDE_INT bisa, bisa2;
13084 : :
13085 : : /* For CPU builtins that can be folded, fold first and expand the fold. */
13086 : 163383 : switch (fcode)
13087 : : {
13088 : 183 : case IX86_BUILTIN_CPU_INIT:
13089 : 183 : {
13090 : : /* Make it call __cpu_indicator_init in libgcc. */
13091 : 183 : tree call_expr, fndecl, type;
13092 : 183 : type = build_function_type_list (integer_type_node, NULL_TREE);
13093 : 183 : fndecl = build_fn_decl ("__cpu_indicator_init", type);
13094 : 183 : call_expr = build_call_expr (fndecl, 0);
13095 : 183 : return expand_expr (call_expr, target, mode, EXPAND_NORMAL);
13096 : : }
13097 : 634 : case IX86_BUILTIN_CPU_IS:
13098 : 634 : case IX86_BUILTIN_CPU_SUPPORTS:
13099 : 634 : {
13100 : 634 : tree arg0 = CALL_EXPR_ARG (exp, 0);
13101 : 634 : tree fold_expr = fold_builtin_cpu (fndecl, &arg0);
13102 : 634 : gcc_assert (fold_expr != NULL_TREE);
13103 : 634 : return expand_expr (fold_expr, target, mode, EXPAND_NORMAL);
13104 : : }
13105 : : }
13106 : :
13107 : 162566 : if (!ix86_check_builtin_isa_match (fcode, &bisa, &bisa2))
13108 : : {
13109 : 21 : bool add_abi_p = bisa & OPTION_MASK_ISA_64BIT;
13110 : 21 : if (TARGET_ABI_X32)
13111 : 0 : bisa |= OPTION_MASK_ABI_X32;
13112 : : else
13113 : 21 : bisa |= OPTION_MASK_ABI_64;
13114 : 21 : char *opts = ix86_target_string (bisa, bisa2, 0, 0, NULL, NULL,
13115 : : (enum fpmath_unit) 0,
13116 : : (enum prefer_vector_width) 0,
13117 : : PVW_NONE, PVW_NONE,
13118 : : false, add_abi_p);
13119 : 21 : if (!opts)
13120 : 0 : error ("%qE needs unknown isa option", fndecl);
13121 : : else
13122 : : {
13123 : 21 : gcc_assert (opts != NULL);
13124 : 21 : error ("%qE needs isa option %s", fndecl, opts);
13125 : 21 : free (opts);
13126 : : }
13127 : 21 : return expand_call (exp, target, ignore);
13128 : : }
13129 : :
13130 : 162545 : switch (fcode)
13131 : : {
13132 : 35 : case IX86_BUILTIN_MASKMOVQ:
13133 : 35 : case IX86_BUILTIN_MASKMOVDQU:
13134 : 70 : icode = (fcode == IX86_BUILTIN_MASKMOVQ
13135 : 35 : ? CODE_FOR_mmx_maskmovq
13136 : : : CODE_FOR_sse2_maskmovdqu);
13137 : : /* Note the arg order is different from the operand order. */
13138 : 35 : arg1 = CALL_EXPR_ARG (exp, 0);
13139 : 35 : arg2 = CALL_EXPR_ARG (exp, 1);
13140 : 35 : arg0 = CALL_EXPR_ARG (exp, 2);
13141 : 35 : op0 = expand_normal (arg0);
13142 : 35 : op1 = expand_normal (arg1);
13143 : 35 : op2 = expand_normal (arg2);
13144 : 35 : mode0 = insn_data[icode].operand[0].mode;
13145 : 35 : mode1 = insn_data[icode].operand[1].mode;
13146 : 35 : mode2 = insn_data[icode].operand[2].mode;
13147 : :
13148 : 35 : op0 = ix86_zero_extend_to_Pmode (op0);
13149 : 35 : op0 = gen_rtx_MEM (mode1, op0);
13150 : :
13151 : 35 : if (!insn_data[icode].operand[0].predicate (op0, mode0))
13152 : 0 : op0 = copy_to_mode_reg (mode0, op0);
13153 : 35 : if (!insn_data[icode].operand[1].predicate (op1, mode1))
13154 : 2 : op1 = copy_to_mode_reg (mode1, op1);
13155 : 35 : if (!insn_data[icode].operand[2].predicate (op2, mode2))
13156 : 2 : op2 = copy_to_mode_reg (mode2, op2);
13157 : 35 : pat = GEN_FCN (icode) (op0, op1, op2);
13158 : 35 : if (! pat)
13159 : 56676 : return 0;
13160 : 35 : emit_insn (pat);
13161 : 35 : return 0;
13162 : :
13163 : 21978 : case IX86_BUILTIN_LDMXCSR:
13164 : 21978 : op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
13165 : 21978 : target = assign_386_stack_local (SImode, SLOT_TEMP);
13166 : 21978 : emit_move_insn (target, op0);
13167 : 21978 : emit_insn (gen_sse_ldmxcsr (target));
13168 : 21978 : return 0;
13169 : :
13170 : 14769 : case IX86_BUILTIN_STMXCSR:
13171 : 14769 : target = assign_386_stack_local (SImode, SLOT_TEMP);
13172 : 14769 : emit_insn (gen_sse_stmxcsr (target));
13173 : 14769 : return copy_to_mode_reg (SImode, target);
13174 : :
13175 : 11 : case IX86_BUILTIN_CLFLUSH:
13176 : 11 : arg0 = CALL_EXPR_ARG (exp, 0);
13177 : 11 : op0 = expand_normal (arg0);
13178 : 11 : icode = CODE_FOR_sse2_clflush;
13179 : 11 : if (!insn_data[icode].operand[0].predicate (op0, Pmode))
13180 : 5 : op0 = ix86_zero_extend_to_Pmode (op0);
13181 : :
13182 : 11 : emit_insn (gen_sse2_clflush (op0));
13183 : 11 : return 0;
13184 : :
13185 : 19 : case IX86_BUILTIN_CLWB:
13186 : 19 : arg0 = CALL_EXPR_ARG (exp, 0);
13187 : 19 : op0 = expand_normal (arg0);
13188 : 19 : icode = CODE_FOR_clwb;
13189 : 19 : if (!insn_data[icode].operand[0].predicate (op0, Pmode))
13190 : 9 : op0 = ix86_zero_extend_to_Pmode (op0);
13191 : :
13192 : 19 : emit_insn (gen_clwb (op0));
13193 : 19 : return 0;
13194 : :
13195 : 19 : case IX86_BUILTIN_CLFLUSHOPT:
13196 : 19 : arg0 = CALL_EXPR_ARG (exp, 0);
13197 : 19 : op0 = expand_normal (arg0);
13198 : 19 : icode = CODE_FOR_clflushopt;
13199 : 19 : if (!insn_data[icode].operand[0].predicate (op0, Pmode))
13200 : 9 : op0 = ix86_zero_extend_to_Pmode (op0);
13201 : :
13202 : 19 : emit_insn (gen_clflushopt (op0));
13203 : 19 : return 0;
13204 : :
13205 : 47 : case IX86_BUILTIN_MONITOR:
13206 : 47 : case IX86_BUILTIN_MONITORX:
13207 : 47 : arg0 = CALL_EXPR_ARG (exp, 0);
13208 : 47 : arg1 = CALL_EXPR_ARG (exp, 1);
13209 : 47 : arg2 = CALL_EXPR_ARG (exp, 2);
13210 : 47 : op0 = expand_normal (arg0);
13211 : 47 : op1 = expand_normal (arg1);
13212 : 47 : op2 = expand_normal (arg2);
13213 : 47 : if (!REG_P (op0))
13214 : 19 : op0 = ix86_zero_extend_to_Pmode (op0);
13215 : 47 : if (!REG_P (op1))
13216 : 22 : op1 = copy_to_mode_reg (SImode, op1);
13217 : 47 : if (!REG_P (op2))
13218 : 25 : op2 = copy_to_mode_reg (SImode, op2);
13219 : :
13220 : 47 : emit_insn (fcode == IX86_BUILTIN_MONITOR
13221 : 26 : ? gen_sse3_monitor (Pmode, op0, op1, op2)
13222 : 21 : : gen_monitorx (Pmode, op0, op1, op2));
13223 : 47 : return 0;
13224 : :
13225 : 25 : case IX86_BUILTIN_MWAIT:
13226 : 25 : arg0 = CALL_EXPR_ARG (exp, 0);
13227 : 25 : arg1 = CALL_EXPR_ARG (exp, 1);
13228 : 25 : op0 = expand_normal (arg0);
13229 : 25 : op1 = expand_normal (arg1);
13230 : 25 : if (!REG_P (op0))
13231 : 13 : op0 = copy_to_mode_reg (SImode, op0);
13232 : 25 : if (!REG_P (op1))
13233 : 11 : op1 = copy_to_mode_reg (SImode, op1);
13234 : 25 : emit_insn (gen_sse3_mwait (op0, op1));
13235 : 25 : return 0;
13236 : :
13237 : 21 : case IX86_BUILTIN_MWAITX:
13238 : 21 : arg0 = CALL_EXPR_ARG (exp, 0);
13239 : 21 : arg1 = CALL_EXPR_ARG (exp, 1);
13240 : 21 : arg2 = CALL_EXPR_ARG (exp, 2);
13241 : 21 : op0 = expand_normal (arg0);
13242 : 21 : op1 = expand_normal (arg1);
13243 : 21 : op2 = expand_normal (arg2);
13244 : 21 : if (!REG_P (op0))
13245 : 11 : op0 = copy_to_mode_reg (SImode, op0);
13246 : 21 : if (!REG_P (op1))
13247 : 10 : op1 = copy_to_mode_reg (SImode, op1);
13248 : 21 : if (!REG_P (op2))
13249 : 11 : op2 = copy_to_mode_reg (SImode, op2);
13250 : 21 : emit_insn (gen_mwaitx (op0, op1, op2));
13251 : 21 : return 0;
13252 : :
13253 : 21 : case IX86_BUILTIN_UMONITOR:
13254 : 21 : arg0 = CALL_EXPR_ARG (exp, 0);
13255 : 21 : op0 = expand_normal (arg0);
13256 : :
13257 : 21 : op0 = ix86_zero_extend_to_Pmode (op0);
13258 : 21 : emit_insn (gen_umonitor (Pmode, op0));
13259 : 21 : return 0;
13260 : :
13261 : 42 : case IX86_BUILTIN_UMWAIT:
13262 : 42 : case IX86_BUILTIN_TPAUSE:
13263 : 42 : arg0 = CALL_EXPR_ARG (exp, 0);
13264 : 42 : arg1 = CALL_EXPR_ARG (exp, 1);
13265 : 42 : op0 = expand_normal (arg0);
13266 : 42 : op1 = expand_normal (arg1);
13267 : :
13268 : 42 : if (!REG_P (op0))
13269 : 20 : op0 = copy_to_mode_reg (SImode, op0);
13270 : :
13271 : 42 : op1 = force_reg (DImode, op1);
13272 : :
13273 : 42 : if (TARGET_64BIT)
13274 : : {
13275 : 42 : op2 = expand_simple_binop (DImode, LSHIFTRT, op1, GEN_INT (32),
13276 : : NULL, 1, OPTAB_DIRECT);
13277 : 42 : switch (fcode)
13278 : : {
13279 : : case IX86_BUILTIN_UMWAIT:
13280 : : icode = CODE_FOR_umwait_rex64;
13281 : : break;
13282 : 21 : case IX86_BUILTIN_TPAUSE:
13283 : 21 : icode = CODE_FOR_tpause_rex64;
13284 : 21 : break;
13285 : 0 : default:
13286 : 0 : gcc_unreachable ();
13287 : : }
13288 : :
13289 : 42 : op2 = gen_lowpart (SImode, op2);
13290 : 42 : op1 = gen_lowpart (SImode, op1);
13291 : 42 : pat = GEN_FCN (icode) (op0, op1, op2);
13292 : : }
13293 : : else
13294 : : {
13295 : 0 : switch (fcode)
13296 : : {
13297 : : case IX86_BUILTIN_UMWAIT:
13298 : : icode = CODE_FOR_umwait;
13299 : : break;
13300 : 0 : case IX86_BUILTIN_TPAUSE:
13301 : 0 : icode = CODE_FOR_tpause;
13302 : 0 : break;
13303 : 0 : default:
13304 : 0 : gcc_unreachable ();
13305 : : }
13306 : 0 : pat = GEN_FCN (icode) (op0, op1);
13307 : : }
13308 : :
13309 : 42 : if (!pat)
13310 : : return 0;
13311 : :
13312 : 42 : emit_insn (pat);
13313 : :
13314 : 42 : if (target == 0
13315 : 42 : || !register_operand (target, QImode))
13316 : 0 : target = gen_reg_rtx (QImode);
13317 : :
13318 : 42 : pat = gen_rtx_EQ (QImode, gen_rtx_REG (CCCmode, FLAGS_REG),
13319 : : const0_rtx);
13320 : 42 : emit_insn (gen_rtx_SET (target, pat));
13321 : :
13322 : 42 : return target;
13323 : :
13324 : 20 : case IX86_BUILTIN_TESTUI:
13325 : 20 : emit_insn (gen_testui ());
13326 : :
13327 : 20 : if (target == 0
13328 : 20 : || !register_operand (target, QImode))
13329 : 0 : target = gen_reg_rtx (QImode);
13330 : :
13331 : 20 : pat = gen_rtx_LTU (QImode, gen_rtx_REG (CCCmode, FLAGS_REG),
13332 : : const0_rtx);
13333 : 20 : emit_insn (gen_rtx_SET (target, pat));
13334 : :
13335 : 20 : return target;
13336 : :
13337 : 19 : case IX86_BUILTIN_CLZERO:
13338 : 19 : arg0 = CALL_EXPR_ARG (exp, 0);
13339 : 19 : op0 = expand_normal (arg0);
13340 : 19 : if (!REG_P (op0))
13341 : 9 : op0 = ix86_zero_extend_to_Pmode (op0);
13342 : 19 : emit_insn (gen_clzero (Pmode, op0));
13343 : 19 : return 0;
13344 : :
13345 : 19 : case IX86_BUILTIN_CLDEMOTE:
13346 : 19 : arg0 = CALL_EXPR_ARG (exp, 0);
13347 : 19 : op0 = expand_normal (arg0);
13348 : 19 : icode = CODE_FOR_cldemote;
13349 : 19 : if (!insn_data[icode].operand[0].predicate (op0, Pmode))
13350 : 9 : op0 = ix86_zero_extend_to_Pmode (op0);
13351 : :
13352 : 19 : emit_insn (gen_cldemote (op0));
13353 : 19 : return 0;
13354 : :
13355 : 11 : case IX86_BUILTIN_LOADIWKEY:
13356 : 11 : {
13357 : 11 : arg0 = CALL_EXPR_ARG (exp, 0);
13358 : 11 : arg1 = CALL_EXPR_ARG (exp, 1);
13359 : 11 : arg2 = CALL_EXPR_ARG (exp, 2);
13360 : 11 : arg3 = CALL_EXPR_ARG (exp, 3);
13361 : :
13362 : 11 : op0 = expand_normal (arg0);
13363 : 11 : op1 = expand_normal (arg1);
13364 : 11 : op2 = expand_normal (arg2);
13365 : 11 : op3 = expand_normal (arg3);
13366 : :
13367 : 11 : if (!REG_P (op0))
13368 : 5 : op0 = copy_to_mode_reg (V2DImode, op0);
13369 : 11 : if (!REG_P (op1))
13370 : 5 : op1 = copy_to_mode_reg (V2DImode, op1);
13371 : 11 : if (!REG_P (op2))
13372 : 5 : op2 = copy_to_mode_reg (V2DImode, op2);
13373 : 11 : if (!REG_P (op3))
13374 : 5 : op3 = copy_to_mode_reg (SImode, op3);
13375 : :
13376 : 11 : emit_insn (gen_loadiwkey (op0, op1, op2, op3));
13377 : :
13378 : 11 : return 0;
13379 : : }
13380 : :
13381 : 11 : case IX86_BUILTIN_AESDEC128KLU8:
13382 : 11 : icode = CODE_FOR_aesdec128klu8;
13383 : 11 : goto aesdecenc_expand;
13384 : :
13385 : 11 : case IX86_BUILTIN_AESDEC256KLU8:
13386 : 11 : icode = CODE_FOR_aesdec256klu8;
13387 : 11 : goto aesdecenc_expand;
13388 : :
13389 : 11 : case IX86_BUILTIN_AESENC128KLU8:
13390 : 11 : icode = CODE_FOR_aesenc128klu8;
13391 : 11 : goto aesdecenc_expand;
13392 : :
13393 : : case IX86_BUILTIN_AESENC256KLU8:
13394 : : icode = CODE_FOR_aesenc256klu8;
13395 : :
13396 : 44 : aesdecenc_expand:
13397 : :
13398 : 44 : arg0 = CALL_EXPR_ARG (exp, 0); // __m128i *odata
13399 : 44 : arg1 = CALL_EXPR_ARG (exp, 1); // __m128i idata
13400 : 44 : arg2 = CALL_EXPR_ARG (exp, 2); // const void *p
13401 : :
13402 : 44 : op0 = expand_normal (arg0);
13403 : 44 : op1 = expand_normal (arg1);
13404 : 44 : op2 = expand_normal (arg2);
13405 : :
13406 : 44 : if (!address_operand (op0, V2DImode))
13407 : : {
13408 : 16 : op0 = convert_memory_address (Pmode, op0);
13409 : 16 : op0 = copy_addr_to_reg (op0);
13410 : : }
13411 : 44 : op0 = gen_rtx_MEM (V2DImode, op0);
13412 : :
13413 : 44 : if (!REG_P (op1))
13414 : 20 : op1 = copy_to_mode_reg (V2DImode, op1);
13415 : :
13416 : 44 : if (!address_operand (op2, VOIDmode))
13417 : : {
13418 : 16 : op2 = convert_memory_address (Pmode, op2);
13419 : 16 : op2 = copy_addr_to_reg (op2);
13420 : : }
13421 : 44 : op2 = gen_rtx_MEM (BLKmode, op2);
13422 : :
13423 : 44 : emit_insn (GEN_FCN (icode) (op1, op1, op2));
13424 : :
13425 : 44 : if (target == 0)
13426 : 0 : target = gen_reg_rtx (QImode);
13427 : :
13428 : : /* NB: For aesenc/aesdec keylocker insn, ZF will be set when runtime
13429 : : error occurs. Then the output should be cleared for safety. */
13430 : 44 : rtx_code_label *ok_label;
13431 : 44 : rtx tmp;
13432 : :
13433 : 44 : tmp = gen_rtx_REG (CCZmode, FLAGS_REG);
13434 : 44 : pat = gen_rtx_EQ (QImode, tmp, const0_rtx);
13435 : 44 : ok_label = gen_label_rtx ();
13436 : 44 : emit_cmp_and_jump_insns (tmp, const0_rtx, NE, 0, GET_MODE (tmp),
13437 : : true, ok_label);
13438 : : /* Usually the runtime error seldom occur, so predict OK path as
13439 : : hotspot to optimize it as fallthrough block. */
13440 : 44 : predict_jump (REG_BR_PROB_BASE * 90 / 100);
13441 : :
13442 : 44 : emit_insn (gen_rtx_SET (op1, const0_rtx));
13443 : :
13444 : 44 : emit_label (ok_label);
13445 : 44 : emit_insn (gen_rtx_SET (target, pat));
13446 : 44 : emit_insn (gen_rtx_SET (op0, op1));
13447 : :
13448 : 44 : return target;
13449 : :
13450 : 11 : case IX86_BUILTIN_AESDECWIDE128KLU8:
13451 : 11 : icode = CODE_FOR_aesdecwide128klu8;
13452 : 11 : goto wideaesdecenc_expand;
13453 : :
13454 : 11 : case IX86_BUILTIN_AESDECWIDE256KLU8:
13455 : 11 : icode = CODE_FOR_aesdecwide256klu8;
13456 : 11 : goto wideaesdecenc_expand;
13457 : :
13458 : 11 : case IX86_BUILTIN_AESENCWIDE128KLU8:
13459 : 11 : icode = CODE_FOR_aesencwide128klu8;
13460 : 11 : goto wideaesdecenc_expand;
13461 : :
13462 : : case IX86_BUILTIN_AESENCWIDE256KLU8:
13463 : : icode = CODE_FOR_aesencwide256klu8;
13464 : :
13465 : 44 : wideaesdecenc_expand:
13466 : :
13467 : 44 : rtx xmm_regs[8];
13468 : 44 : rtx op;
13469 : :
13470 : 44 : arg0 = CALL_EXPR_ARG (exp, 0); // __m128i * odata
13471 : 44 : arg1 = CALL_EXPR_ARG (exp, 1); // const __m128i * idata
13472 : 44 : arg2 = CALL_EXPR_ARG (exp, 2); // const void *p
13473 : :
13474 : 44 : op0 = expand_normal (arg0);
13475 : 44 : op1 = expand_normal (arg1);
13476 : 44 : op2 = expand_normal (arg2);
13477 : :
13478 : 44 : if (!address_operand (op2, VOIDmode))
13479 : : {
13480 : 16 : op2 = convert_memory_address (Pmode, op2);
13481 : 16 : op2 = copy_addr_to_reg (op2);
13482 : : }
13483 : 44 : op2 = gen_rtx_MEM (BLKmode, op2);
13484 : :
13485 : 440 : for (i = 0; i < 8; i++)
13486 : : {
13487 : 352 : xmm_regs[i] = gen_rtx_REG (V2DImode, GET_SSE_REGNO (i));
13488 : :
13489 : 352 : op = gen_rtx_MEM (V2DImode,
13490 : 352 : plus_constant (Pmode, op1, (i * 16)));
13491 : :
13492 : 352 : emit_move_insn (xmm_regs[i], op);
13493 : : }
13494 : :
13495 : 44 : emit_insn (GEN_FCN (icode) (op2));
13496 : :
13497 : 44 : if (target == 0)
13498 : 0 : target = gen_reg_rtx (QImode);
13499 : :
13500 : 44 : tmp = gen_rtx_REG (CCZmode, FLAGS_REG);
13501 : 44 : pat = gen_rtx_EQ (QImode, tmp, const0_rtx);
13502 : 44 : ok_label = gen_label_rtx ();
13503 : 44 : emit_cmp_and_jump_insns (tmp, const0_rtx, NE, 0, GET_MODE (tmp),
13504 : : true, ok_label);
13505 : 44 : predict_jump (REG_BR_PROB_BASE * 90 / 100);
13506 : :
13507 : 440 : for (i = 0; i < 8; i++)
13508 : 352 : emit_insn (gen_rtx_SET (xmm_regs[i], const0_rtx));
13509 : :
13510 : 44 : emit_label (ok_label);
13511 : 44 : emit_insn (gen_rtx_SET (target, pat));
13512 : :
13513 : 440 : for (i = 0; i < 8; i++)
13514 : : {
13515 : 352 : op = gen_rtx_MEM (V2DImode,
13516 : 352 : plus_constant (Pmode, op0, (i * 16)));
13517 : 352 : emit_move_insn (op, xmm_regs[i]);
13518 : : }
13519 : :
13520 : : return target;
13521 : :
13522 : 11 : case IX86_BUILTIN_ENCODEKEY128U32:
13523 : 11 : {
13524 : 11 : rtx op, xmm_regs[7];
13525 : :
13526 : 11 : arg0 = CALL_EXPR_ARG (exp, 0); // unsigned int htype
13527 : 11 : arg1 = CALL_EXPR_ARG (exp, 1); // __m128i key
13528 : 11 : arg2 = CALL_EXPR_ARG (exp, 2); // void *h
13529 : :
13530 : 11 : op0 = expand_normal (arg0);
13531 : 11 : op1 = expand_normal (arg1);
13532 : 11 : op2 = expand_normal (arg2);
13533 : :
13534 : 11 : if (!REG_P (op0))
13535 : 5 : op0 = copy_to_mode_reg (SImode, op0);
13536 : :
13537 : 11 : op = gen_rtx_REG (V2DImode, GET_SSE_REGNO (0));
13538 : 11 : emit_move_insn (op, op1);
13539 : :
13540 : 55 : for (i = 0; i < 3; i++)
13541 : 33 : xmm_regs[i] = gen_rtx_REG (V2DImode, GET_SSE_REGNO (i));
13542 : :
13543 : 11 : if (target == 0)
13544 : 0 : target = gen_reg_rtx (SImode);
13545 : :
13546 : 11 : emit_insn (gen_encodekey128u32 (target, op0));
13547 : :
13548 : 55 : for (i = 0; i < 3; i++)
13549 : : {
13550 : 33 : op = gen_rtx_MEM (V2DImode,
13551 : 33 : plus_constant (Pmode, op2, (i * 16)));
13552 : 33 : emit_move_insn (op, xmm_regs[i]);
13553 : : }
13554 : :
13555 : 11 : return target;
13556 : : }
13557 : 11 : case IX86_BUILTIN_ENCODEKEY256U32:
13558 : 11 : {
13559 : 11 : rtx op, xmm_regs[7];
13560 : :
13561 : 11 : arg0 = CALL_EXPR_ARG (exp, 0); // unsigned int htype
13562 : 11 : arg1 = CALL_EXPR_ARG (exp, 1); // __m128i keylow
13563 : 11 : arg2 = CALL_EXPR_ARG (exp, 2); // __m128i keyhi
13564 : 11 : arg3 = CALL_EXPR_ARG (exp, 3); // void *h
13565 : :
13566 : 11 : op0 = expand_normal (arg0);
13567 : 11 : op1 = expand_normal (arg1);
13568 : 11 : op2 = expand_normal (arg2);
13569 : 11 : op3 = expand_normal (arg3);
13570 : :
13571 : 11 : if (!REG_P (op0))
13572 : 5 : op0 = copy_to_mode_reg (SImode, op0);
13573 : :
13574 : : /* Force to use xmm0, xmm1 for keylow, keyhi*/
13575 : 11 : op = gen_rtx_REG (V2DImode, GET_SSE_REGNO (0));
13576 : 11 : emit_move_insn (op, op1);
13577 : 11 : op = gen_rtx_REG (V2DImode, GET_SSE_REGNO (1));
13578 : 11 : emit_move_insn (op, op2);
13579 : :
13580 : 66 : for (i = 0; i < 4; i++)
13581 : 44 : xmm_regs[i] = gen_rtx_REG (V2DImode, GET_SSE_REGNO (i));
13582 : :
13583 : 11 : if (target == 0)
13584 : 0 : target = gen_reg_rtx (SImode);
13585 : :
13586 : 11 : emit_insn (gen_encodekey256u32 (target, op0));
13587 : :
13588 : 66 : for (i = 0; i < 4; i++)
13589 : : {
13590 : 44 : op = gen_rtx_MEM (V2DImode,
13591 : 44 : plus_constant (Pmode, op3, (i * 16)));
13592 : 44 : emit_move_insn (op, xmm_regs[i]);
13593 : : }
13594 : :
13595 : 11 : return target;
13596 : : }
13597 : :
13598 : 28 : case IX86_BUILTIN_PREFETCH:
13599 : 28 : {
13600 : 28 : arg0 = CALL_EXPR_ARG (exp, 0); // const void *
13601 : 28 : arg1 = CALL_EXPR_ARG (exp, 1); // const int
13602 : 28 : arg2 = CALL_EXPR_ARG (exp, 2); // const int
13603 : 28 : arg3 = CALL_EXPR_ARG (exp, 3); // const int
13604 : :
13605 : 28 : op0 = expand_normal (arg0);
13606 : 28 : op1 = expand_normal (arg1);
13607 : 28 : op2 = expand_normal (arg2);
13608 : 28 : op3 = expand_normal (arg3);
13609 : :
13610 : 28 : if (!CONST_INT_P (op1) || !CONST_INT_P (op2) || !CONST_INT_P (op3))
13611 : : {
13612 : 0 : error ("second, third and fourth argument must be a const");
13613 : 0 : return const0_rtx;
13614 : : }
13615 : :
13616 : 28 : if (INTVAL (op3) == 1)
13617 : : {
13618 : 4 : if (INTVAL (op2) < 2 || INTVAL (op2) > 3)
13619 : : {
13620 : 1 : error ("invalid third argument");
13621 : 1 : return const0_rtx;
13622 : : }
13623 : :
13624 : 3 : if (TARGET_64BIT && TARGET_PREFETCHI
13625 : 6 : && local_func_symbolic_operand (op0, GET_MODE (op0)))
13626 : 2 : emit_insn (gen_prefetchi (op0, op2));
13627 : : else
13628 : : {
13629 : 1 : warning (0, "instruction prefetch applies when in 64-bit mode"
13630 : : " with RIP-relative addressing and"
13631 : : " option %<-mprefetchi%>;"
13632 : : " they stay NOPs otherwise");
13633 : 1 : emit_insn (gen_nop ());
13634 : : }
13635 : : }
13636 : : else
13637 : : {
13638 : 24 : if (!address_operand (op0, VOIDmode))
13639 : : {
13640 : 6 : op0 = convert_memory_address (Pmode, op0);
13641 : 6 : op0 = copy_addr_to_reg (op0);
13642 : : }
13643 : :
13644 : 24 : if (INTVAL (op2) < 0 || INTVAL (op2) > 3)
13645 : : {
13646 : 1 : warning (0, "invalid third argument to %<__builtin_ia32_prefetch%>; using zero");
13647 : 1 : op2 = const0_rtx;
13648 : : }
13649 : :
13650 : 24 : if (TARGET_3DNOW || TARGET_PREFETCH_SSE
13651 : 0 : || TARGET_PRFCHW || TARGET_PREFETCHWT1)
13652 : 24 : emit_insn (gen_prefetch (op0, op1, op2));
13653 : 0 : else if (!MEM_P (op0) && side_effects_p (op0))
13654 : : /* Don't do anything with direct references to volatile memory,
13655 : : but generate code to handle other side effects. */
13656 : 0 : emit_insn (op0);
13657 : : }
13658 : :
13659 : : return 0;
13660 : : }
13661 : :
13662 : 37 : case IX86_BUILTIN_PREFETCHI:
13663 : 37 : {
13664 : 37 : arg0 = CALL_EXPR_ARG (exp, 0); // const void *
13665 : 37 : arg1 = CALL_EXPR_ARG (exp, 1); // const int
13666 : :
13667 : 37 : op0 = expand_normal (arg0);
13668 : 37 : op1 = expand_normal (arg1);
13669 : :
13670 : 37 : if (!CONST_INT_P (op1))
13671 : : {
13672 : 0 : error ("second argument must be a const");
13673 : 0 : return const0_rtx;
13674 : : }
13675 : :
13676 : : /* GOT/PLT_PIC should not be available for instruction prefetch.
13677 : : It must be real instruction address. */
13678 : 37 : if (TARGET_64BIT
13679 : 37 : && local_func_symbolic_operand (op0, GET_MODE (op0)))
13680 : 2 : emit_insn (gen_prefetchi (op0, op1));
13681 : : else
13682 : : {
13683 : : /* Ignore the hint. */
13684 : 35 : warning (0, "instruction prefetch applies when in 64-bit mode"
13685 : : " with RIP-relative addressing and"
13686 : : " option %<-mprefetchi%>;"
13687 : : " they stay NOPs otherwise");
13688 : 35 : emit_insn (gen_nop ());
13689 : : }
13690 : :
13691 : : return 0;
13692 : : }
13693 : :
13694 : 52 : case IX86_BUILTIN_URDMSR:
13695 : 52 : case IX86_BUILTIN_UWRMSR:
13696 : 52 : {
13697 : 52 : arg0 = CALL_EXPR_ARG (exp, 0);
13698 : 52 : op0 = expand_normal (arg0);
13699 : :
13700 : 52 : if (CONST_INT_P (op0))
13701 : : {
13702 : 12 : unsigned HOST_WIDE_INT val = UINTVAL (op0);
13703 : 12 : if (val > 0xffffffff)
13704 : 2 : op0 = force_reg (DImode, op0);
13705 : : }
13706 : : else
13707 : 40 : op0 = force_reg (DImode, op0);
13708 : :
13709 : 52 : if (fcode == IX86_BUILTIN_UWRMSR)
13710 : : {
13711 : 26 : arg1 = CALL_EXPR_ARG (exp, 1);
13712 : 26 : op1 = expand_normal (arg1);
13713 : 26 : op1 = force_reg (DImode, op1);
13714 : 26 : icode = CODE_FOR_uwrmsr;
13715 : 26 : target = 0;
13716 : : }
13717 : : else
13718 : : {
13719 : 26 : if (target == 0)
13720 : 0 : target = gen_reg_rtx (DImode);
13721 : : icode = CODE_FOR_urdmsr;
13722 : : op1 = op0;
13723 : : op0 = target;
13724 : : }
13725 : 52 : emit_insn (GEN_FCN (icode) (op0, op1));
13726 : 52 : return target;
13727 : : }
13728 : :
13729 : 230 : case IX86_BUILTIN_VEC_INIT_V2SI:
13730 : 230 : case IX86_BUILTIN_VEC_INIT_V4HI:
13731 : 230 : case IX86_BUILTIN_VEC_INIT_V8QI:
13732 : 230 : return ix86_expand_vec_init_builtin (TREE_TYPE (exp), exp, target);
13733 : :
13734 : 387 : case IX86_BUILTIN_VEC_EXT_V2DF:
13735 : 387 : case IX86_BUILTIN_VEC_EXT_V2DI:
13736 : 387 : case IX86_BUILTIN_VEC_EXT_V4SF:
13737 : 387 : case IX86_BUILTIN_VEC_EXT_V4SI:
13738 : 387 : case IX86_BUILTIN_VEC_EXT_V8HI:
13739 : 387 : case IX86_BUILTIN_VEC_EXT_V2SI:
13740 : 387 : case IX86_BUILTIN_VEC_EXT_V4HI:
13741 : 387 : case IX86_BUILTIN_VEC_EXT_V16QI:
13742 : 387 : return ix86_expand_vec_ext_builtin (exp, target);
13743 : :
13744 : 204 : case IX86_BUILTIN_VEC_SET_V2DI:
13745 : 204 : case IX86_BUILTIN_VEC_SET_V4SF:
13746 : 204 : case IX86_BUILTIN_VEC_SET_V4SI:
13747 : 204 : case IX86_BUILTIN_VEC_SET_V8HI:
13748 : 204 : case IX86_BUILTIN_VEC_SET_V4HI:
13749 : 204 : case IX86_BUILTIN_VEC_SET_V16QI:
13750 : 204 : return ix86_expand_vec_set_builtin (exp);
13751 : :
13752 : 0 : case IX86_BUILTIN_NANQ:
13753 : 0 : case IX86_BUILTIN_NANSQ:
13754 : 0 : return expand_call (exp, target, ignore);
13755 : :
13756 : 18 : case IX86_BUILTIN_RDPID:
13757 : :
13758 : 18 : op0 = gen_reg_rtx (word_mode);
13759 : :
13760 : 18 : if (TARGET_64BIT)
13761 : : {
13762 : 18 : insn = gen_rdpid_rex64 (op0);
13763 : 18 : op0 = convert_to_mode (SImode, op0, 1);
13764 : : }
13765 : : else
13766 : 0 : insn = gen_rdpid (op0);
13767 : :
13768 : 18 : emit_insn (insn);
13769 : :
13770 : 18 : if (target == 0
13771 : 18 : || !register_operand (target, SImode))
13772 : 0 : target = gen_reg_rtx (SImode);
13773 : :
13774 : 18 : emit_move_insn (target, op0);
13775 : 18 : return target;
13776 : :
13777 : 75 : case IX86_BUILTIN_2INTERSECTD512:
13778 : 75 : case IX86_BUILTIN_2INTERSECTQ512:
13779 : 75 : case IX86_BUILTIN_2INTERSECTD256:
13780 : 75 : case IX86_BUILTIN_2INTERSECTQ256:
13781 : 75 : case IX86_BUILTIN_2INTERSECTD128:
13782 : 75 : case IX86_BUILTIN_2INTERSECTQ128:
13783 : 75 : arg0 = CALL_EXPR_ARG (exp, 0);
13784 : 75 : arg1 = CALL_EXPR_ARG (exp, 1);
13785 : 75 : arg2 = CALL_EXPR_ARG (exp, 2);
13786 : 75 : arg3 = CALL_EXPR_ARG (exp, 3);
13787 : 75 : op0 = expand_normal (arg0);
13788 : 75 : op1 = expand_normal (arg1);
13789 : 75 : op2 = expand_normal (arg2);
13790 : 75 : op3 = expand_normal (arg3);
13791 : :
13792 : 75 : if (!address_operand (op0, VOIDmode))
13793 : : {
13794 : 25 : op0 = convert_memory_address (Pmode, op0);
13795 : 25 : op0 = copy_addr_to_reg (op0);
13796 : : }
13797 : 75 : if (!address_operand (op1, VOIDmode))
13798 : : {
13799 : 25 : op1 = convert_memory_address (Pmode, op1);
13800 : 25 : op1 = copy_addr_to_reg (op1);
13801 : : }
13802 : :
13803 : 75 : switch (fcode)
13804 : : {
13805 : : case IX86_BUILTIN_2INTERSECTD512:
13806 : : mode4 = P2HImode;
13807 : : icode = CODE_FOR_avx512vp2intersect_2intersectv16si;
13808 : : break;
13809 : : case IX86_BUILTIN_2INTERSECTQ512:
13810 : : mode4 = P2QImode;
13811 : : icode = CODE_FOR_avx512vp2intersect_2intersectv8di;
13812 : : break;
13813 : : case IX86_BUILTIN_2INTERSECTD256:
13814 : : mode4 = P2QImode;
13815 : : icode = CODE_FOR_avx512vp2intersect_2intersectv8si;
13816 : : break;
13817 : : case IX86_BUILTIN_2INTERSECTQ256:
13818 : : mode4 = P2QImode;
13819 : : icode = CODE_FOR_avx512vp2intersect_2intersectv4di;
13820 : : break;
13821 : : case IX86_BUILTIN_2INTERSECTD128:
13822 : : mode4 = P2QImode;
13823 : : icode = CODE_FOR_avx512vp2intersect_2intersectv4si;
13824 : : break;
13825 : : case IX86_BUILTIN_2INTERSECTQ128:
13826 : : mode4 = P2QImode;
13827 : : icode = CODE_FOR_avx512vp2intersect_2intersectv2di;
13828 : : break;
13829 : 0 : default:
13830 : 0 : gcc_unreachable ();
13831 : : }
13832 : :
13833 : 75 : mode2 = insn_data[icode].operand[1].mode;
13834 : 75 : mode3 = insn_data[icode].operand[2].mode;
13835 : 75 : if (!insn_data[icode].operand[1].predicate (op2, mode2))
13836 : 25 : op2 = copy_to_mode_reg (mode2, op2);
13837 : 75 : if (!insn_data[icode].operand[2].predicate (op3, mode3))
13838 : 6 : op3 = copy_to_mode_reg (mode3, op3);
13839 : :
13840 : 75 : op4 = gen_reg_rtx (mode4);
13841 : 75 : emit_insn (GEN_FCN (icode) (op4, op2, op3));
13842 : 75 : mode0 = mode4 == P2HImode ? HImode : QImode;
13843 : 75 : emit_move_insn (gen_rtx_MEM (mode0, op0),
13844 : 75 : gen_lowpart (mode0, op4));
13845 : 75 : emit_move_insn (gen_rtx_MEM (mode0, op1),
13846 : : gen_highpart (mode0, op4));
13847 : :
13848 : 75 : return 0;
13849 : :
13850 : 102 : case IX86_BUILTIN_RDPMC:
13851 : 102 : case IX86_BUILTIN_RDTSC:
13852 : 102 : case IX86_BUILTIN_RDTSCP:
13853 : 102 : case IX86_BUILTIN_XGETBV:
13854 : :
13855 : 102 : op0 = gen_reg_rtx (DImode);
13856 : 102 : op1 = gen_reg_rtx (DImode);
13857 : :
13858 : 102 : if (fcode == IX86_BUILTIN_RDPMC)
13859 : : {
13860 : 22 : arg0 = CALL_EXPR_ARG (exp, 0);
13861 : 22 : op2 = expand_normal (arg0);
13862 : 22 : if (!register_operand (op2, SImode))
13863 : 11 : op2 = copy_to_mode_reg (SImode, op2);
13864 : :
13865 : 44 : insn = (TARGET_64BIT
13866 : 22 : ? gen_rdpmc_rex64 (op0, op1, op2)
13867 : 0 : : gen_rdpmc (op0, op2));
13868 : 22 : emit_insn (insn);
13869 : : }
13870 : 80 : else if (fcode == IX86_BUILTIN_XGETBV)
13871 : : {
13872 : 22 : arg0 = CALL_EXPR_ARG (exp, 0);
13873 : 22 : op2 = expand_normal (arg0);
13874 : 22 : if (!register_operand (op2, SImode))
13875 : 1 : op2 = copy_to_mode_reg (SImode, op2);
13876 : :
13877 : 44 : insn = (TARGET_64BIT
13878 : 22 : ? gen_xgetbv_rex64 (op0, op1, op2)
13879 : 0 : : gen_xgetbv (op0, op2));
13880 : 22 : emit_insn (insn);
13881 : : }
13882 : 58 : else if (fcode == IX86_BUILTIN_RDTSC)
13883 : : {
13884 : 72 : insn = (TARGET_64BIT
13885 : 36 : ? gen_rdtsc_rex64 (op0, op1)
13886 : 2 : : gen_rdtsc (op0));
13887 : 36 : emit_insn (insn);
13888 : : }
13889 : : else
13890 : : {
13891 : 22 : op2 = gen_reg_rtx (SImode);
13892 : :
13893 : 44 : insn = (TARGET_64BIT
13894 : 22 : ? gen_rdtscp_rex64 (op0, op1, op2)
13895 : 0 : : gen_rdtscp (op0, op2));
13896 : 22 : emit_insn (insn);
13897 : :
13898 : 22 : arg0 = CALL_EXPR_ARG (exp, 0);
13899 : 22 : op4 = expand_normal (arg0);
13900 : 22 : if (!address_operand (op4, VOIDmode))
13901 : : {
13902 : 10 : op4 = convert_memory_address (Pmode, op4);
13903 : 10 : op4 = copy_addr_to_reg (op4);
13904 : : }
13905 : 22 : emit_move_insn (gen_rtx_MEM (SImode, op4), op2);
13906 : : }
13907 : :
13908 : 102 : if (target == 0
13909 : 102 : || !register_operand (target, DImode))
13910 : 10 : target = gen_reg_rtx (DImode);
13911 : :
13912 : 102 : if (TARGET_64BIT)
13913 : : {
13914 : 100 : op1 = expand_simple_binop (DImode, ASHIFT, op1, GEN_INT (32),
13915 : : op1, 1, OPTAB_DIRECT);
13916 : 100 : op0 = expand_simple_binop (DImode, IOR, op0, op1,
13917 : : op0, 1, OPTAB_DIRECT);
13918 : : }
13919 : :
13920 : 102 : emit_move_insn (target, op0);
13921 : 102 : return target;
13922 : :
13923 : 61 : case IX86_BUILTIN_ENQCMD:
13924 : 61 : case IX86_BUILTIN_ENQCMDS:
13925 : 61 : case IX86_BUILTIN_MOVDIR64B:
13926 : :
13927 : 61 : arg0 = CALL_EXPR_ARG (exp, 0);
13928 : 61 : arg1 = CALL_EXPR_ARG (exp, 1);
13929 : 61 : op0 = expand_normal (arg0);
13930 : 61 : op1 = expand_normal (arg1);
13931 : :
13932 : 61 : op0 = ix86_zero_extend_to_Pmode (op0);
13933 : 61 : if (!address_operand (op1, VOIDmode))
13934 : : {
13935 : 28 : op1 = convert_memory_address (Pmode, op1);
13936 : 28 : op1 = copy_addr_to_reg (op1);
13937 : : }
13938 : 61 : op1 = gen_rtx_MEM (XImode, op1);
13939 : :
13940 : 61 : if (fcode == IX86_BUILTIN_MOVDIR64B)
13941 : : {
13942 : 23 : emit_insn (gen_movdir64b (Pmode, op0, op1));
13943 : 23 : return 0;
13944 : : }
13945 : : else
13946 : : {
13947 : 38 : if (target == 0
13948 : 38 : || !register_operand (target, SImode))
13949 : 0 : target = gen_reg_rtx (SImode);
13950 : :
13951 : 38 : emit_move_insn (target, const0_rtx);
13952 : 38 : target = gen_rtx_SUBREG (QImode, target, 0);
13953 : :
13954 : 76 : int unspecv = (fcode == IX86_BUILTIN_ENQCMD
13955 : 38 : ? UNSPECV_ENQCMD
13956 : : : UNSPECV_ENQCMDS);
13957 : 38 : icode = code_for_enqcmd (unspecv, Pmode);
13958 : 38 : emit_insn (GEN_FCN (icode) (op0, op1));
13959 : :
13960 : 38 : emit_insn
13961 : 38 : (gen_rtx_SET (gen_rtx_STRICT_LOW_PART (VOIDmode, target),
13962 : : gen_rtx_fmt_ee (EQ, QImode,
13963 : : gen_rtx_REG (CCZmode, FLAGS_REG),
13964 : : const0_rtx)));
13965 : 38 : return SUBREG_REG (target);
13966 : : }
13967 : :
13968 : 14759 : case IX86_BUILTIN_FXSAVE:
13969 : 14759 : case IX86_BUILTIN_FXRSTOR:
13970 : 14759 : case IX86_BUILTIN_FXSAVE64:
13971 : 14759 : case IX86_BUILTIN_FXRSTOR64:
13972 : 14759 : case IX86_BUILTIN_FNSTENV:
13973 : 14759 : case IX86_BUILTIN_FLDENV:
13974 : 14759 : mode0 = BLKmode;
13975 : 14759 : switch (fcode)
13976 : : {
13977 : : case IX86_BUILTIN_FXSAVE:
13978 : : icode = CODE_FOR_fxsave;
13979 : : break;
13980 : 19 : case IX86_BUILTIN_FXRSTOR:
13981 : 19 : icode = CODE_FOR_fxrstor;
13982 : 19 : break;
13983 : 23 : case IX86_BUILTIN_FXSAVE64:
13984 : 23 : icode = CODE_FOR_fxsave64;
13985 : 23 : break;
13986 : 21 : case IX86_BUILTIN_FXRSTOR64:
13987 : 21 : icode = CODE_FOR_fxrstor64;
13988 : 21 : break;
13989 : 7249 : case IX86_BUILTIN_FNSTENV:
13990 : 7249 : icode = CODE_FOR_fnstenv;
13991 : 7249 : break;
13992 : 7427 : case IX86_BUILTIN_FLDENV:
13993 : 7427 : icode = CODE_FOR_fldenv;
13994 : 7427 : break;
13995 : 0 : default:
13996 : 0 : gcc_unreachable ();
13997 : : }
13998 : :
13999 : 14759 : arg0 = CALL_EXPR_ARG (exp, 0);
14000 : 14759 : op0 = expand_normal (arg0);
14001 : :
14002 : 14759 : if (!address_operand (op0, VOIDmode))
14003 : : {
14004 : 36 : op0 = convert_memory_address (Pmode, op0);
14005 : 36 : op0 = copy_addr_to_reg (op0);
14006 : : }
14007 : 14759 : op0 = gen_rtx_MEM (mode0, op0);
14008 : :
14009 : 14759 : pat = GEN_FCN (icode) (op0);
14010 : 14759 : if (pat)
14011 : 14759 : emit_insn (pat);
14012 : : return 0;
14013 : :
14014 : 21 : case IX86_BUILTIN_XSETBV:
14015 : 21 : arg0 = CALL_EXPR_ARG (exp, 0);
14016 : 21 : arg1 = CALL_EXPR_ARG (exp, 1);
14017 : 21 : op0 = expand_normal (arg0);
14018 : 21 : op1 = expand_normal (arg1);
14019 : :
14020 : 21 : if (!REG_P (op0))
14021 : 1 : op0 = copy_to_mode_reg (SImode, op0);
14022 : :
14023 : 21 : op1 = force_reg (DImode, op1);
14024 : :
14025 : 21 : if (TARGET_64BIT)
14026 : : {
14027 : 21 : op2 = expand_simple_binop (DImode, LSHIFTRT, op1, GEN_INT (32),
14028 : : NULL, 1, OPTAB_DIRECT);
14029 : :
14030 : 21 : icode = CODE_FOR_xsetbv_rex64;
14031 : :
14032 : 21 : op2 = gen_lowpart (SImode, op2);
14033 : 21 : op1 = gen_lowpart (SImode, op1);
14034 : 21 : pat = GEN_FCN (icode) (op0, op1, op2);
14035 : : }
14036 : : else
14037 : : {
14038 : 0 : icode = CODE_FOR_xsetbv;
14039 : :
14040 : 0 : pat = GEN_FCN (icode) (op0, op1);
14041 : : }
14042 : 21 : if (pat)
14043 : 21 : emit_insn (pat);
14044 : : return 0;
14045 : :
14046 : 232 : case IX86_BUILTIN_XSAVE:
14047 : 232 : case IX86_BUILTIN_XRSTOR:
14048 : 232 : case IX86_BUILTIN_XSAVE64:
14049 : 232 : case IX86_BUILTIN_XRSTOR64:
14050 : 232 : case IX86_BUILTIN_XSAVEOPT:
14051 : 232 : case IX86_BUILTIN_XSAVEOPT64:
14052 : 232 : case IX86_BUILTIN_XSAVES:
14053 : 232 : case IX86_BUILTIN_XRSTORS:
14054 : 232 : case IX86_BUILTIN_XSAVES64:
14055 : 232 : case IX86_BUILTIN_XRSTORS64:
14056 : 232 : case IX86_BUILTIN_XSAVEC:
14057 : 232 : case IX86_BUILTIN_XSAVEC64:
14058 : 232 : arg0 = CALL_EXPR_ARG (exp, 0);
14059 : 232 : arg1 = CALL_EXPR_ARG (exp, 1);
14060 : 232 : op0 = expand_normal (arg0);
14061 : 232 : op1 = expand_normal (arg1);
14062 : :
14063 : 232 : if (!address_operand (op0, VOIDmode))
14064 : : {
14065 : 108 : op0 = convert_memory_address (Pmode, op0);
14066 : 108 : op0 = copy_addr_to_reg (op0);
14067 : : }
14068 : 232 : op0 = gen_rtx_MEM (BLKmode, op0);
14069 : :
14070 : 232 : op1 = force_reg (DImode, op1);
14071 : :
14072 : 232 : if (TARGET_64BIT)
14073 : : {
14074 : 232 : op2 = expand_simple_binop (DImode, LSHIFTRT, op1, GEN_INT (32),
14075 : : NULL, 1, OPTAB_DIRECT);
14076 : 232 : switch (fcode)
14077 : : {
14078 : : case IX86_BUILTIN_XSAVE:
14079 : : icode = CODE_FOR_xsave_rex64;
14080 : : break;
14081 : 19 : case IX86_BUILTIN_XRSTOR:
14082 : 19 : icode = CODE_FOR_xrstor_rex64;
14083 : 19 : break;
14084 : 21 : case IX86_BUILTIN_XSAVE64:
14085 : 21 : icode = CODE_FOR_xsave64;
14086 : 21 : break;
14087 : 21 : case IX86_BUILTIN_XRSTOR64:
14088 : 21 : icode = CODE_FOR_xrstor64;
14089 : 21 : break;
14090 : 19 : case IX86_BUILTIN_XSAVEOPT:
14091 : 19 : icode = CODE_FOR_xsaveopt_rex64;
14092 : 19 : break;
14093 : 19 : case IX86_BUILTIN_XSAVEOPT64:
14094 : 19 : icode = CODE_FOR_xsaveopt64;
14095 : 19 : break;
14096 : 19 : case IX86_BUILTIN_XSAVES:
14097 : 19 : icode = CODE_FOR_xsaves_rex64;
14098 : 19 : break;
14099 : 19 : case IX86_BUILTIN_XRSTORS:
14100 : 19 : icode = CODE_FOR_xrstors_rex64;
14101 : 19 : break;
14102 : 19 : case IX86_BUILTIN_XSAVES64:
14103 : 19 : icode = CODE_FOR_xsaves64;
14104 : 19 : break;
14105 : 19 : case IX86_BUILTIN_XRSTORS64:
14106 : 19 : icode = CODE_FOR_xrstors64;
14107 : 19 : break;
14108 : 19 : case IX86_BUILTIN_XSAVEC:
14109 : 19 : icode = CODE_FOR_xsavec_rex64;
14110 : 19 : break;
14111 : 19 : case IX86_BUILTIN_XSAVEC64:
14112 : 19 : icode = CODE_FOR_xsavec64;
14113 : 19 : break;
14114 : 0 : default:
14115 : 0 : gcc_unreachable ();
14116 : : }
14117 : :
14118 : 232 : op2 = gen_lowpart (SImode, op2);
14119 : 232 : op1 = gen_lowpart (SImode, op1);
14120 : 232 : pat = GEN_FCN (icode) (op0, op1, op2);
14121 : : }
14122 : : else
14123 : : {
14124 : 0 : switch (fcode)
14125 : : {
14126 : : case IX86_BUILTIN_XSAVE:
14127 : : icode = CODE_FOR_xsave;
14128 : : break;
14129 : : case IX86_BUILTIN_XRSTOR:
14130 : : icode = CODE_FOR_xrstor;
14131 : : break;
14132 : : case IX86_BUILTIN_XSAVEOPT:
14133 : : icode = CODE_FOR_xsaveopt;
14134 : : break;
14135 : : case IX86_BUILTIN_XSAVES:
14136 : : icode = CODE_FOR_xsaves;
14137 : : break;
14138 : : case IX86_BUILTIN_XRSTORS:
14139 : : icode = CODE_FOR_xrstors;
14140 : : break;
14141 : : case IX86_BUILTIN_XSAVEC:
14142 : : icode = CODE_FOR_xsavec;
14143 : : break;
14144 : 0 : default:
14145 : 0 : gcc_unreachable ();
14146 : : }
14147 : 0 : pat = GEN_FCN (icode) (op0, op1);
14148 : : }
14149 : :
14150 : 232 : if (pat)
14151 : 232 : emit_insn (pat);
14152 : : return 0;
14153 : :
14154 : 80 : case IX86_BUILTIN_LDTILECFG:
14155 : 80 : case IX86_BUILTIN_STTILECFG:
14156 : 80 : arg0 = CALL_EXPR_ARG (exp, 0);
14157 : 80 : op0 = expand_normal (arg0);
14158 : :
14159 : 80 : if (!address_operand (op0, VOIDmode))
14160 : : {
14161 : 8 : op0 = convert_memory_address (Pmode, op0);
14162 : 8 : op0 = copy_addr_to_reg (op0);
14163 : : }
14164 : 80 : op0 = gen_rtx_MEM (XImode, op0);
14165 : 80 : if (fcode == IX86_BUILTIN_LDTILECFG)
14166 : : icode = CODE_FOR_ldtilecfg;
14167 : : else
14168 : 49 : icode = CODE_FOR_sttilecfg;
14169 : 80 : pat = GEN_FCN (icode) (op0);
14170 : 80 : emit_insn (pat);
14171 : 80 : return 0;
14172 : :
14173 : 18 : case IX86_BUILTIN_LLWPCB:
14174 : 18 : arg0 = CALL_EXPR_ARG (exp, 0);
14175 : 18 : op0 = expand_normal (arg0);
14176 : :
14177 : 18 : if (!register_operand (op0, Pmode))
14178 : 9 : op0 = ix86_zero_extend_to_Pmode (op0);
14179 : 18 : emit_insn (gen_lwp_llwpcb (Pmode, op0));
14180 : 18 : return 0;
14181 : :
14182 : 18 : case IX86_BUILTIN_SLWPCB:
14183 : 18 : if (!target
14184 : 18 : || !register_operand (target, Pmode))
14185 : 0 : target = gen_reg_rtx (Pmode);
14186 : 18 : emit_insn (gen_lwp_slwpcb (Pmode, target));
14187 : 18 : return target;
14188 : :
14189 : 51 : case IX86_BUILTIN_LWPVAL32:
14190 : 51 : case IX86_BUILTIN_LWPVAL64:
14191 : 51 : case IX86_BUILTIN_LWPINS32:
14192 : 51 : case IX86_BUILTIN_LWPINS64:
14193 : 51 : mode = ((fcode == IX86_BUILTIN_LWPVAL32
14194 : 51 : || fcode == IX86_BUILTIN_LWPINS32)
14195 : 51 : ? SImode : DImode);
14196 : :
14197 : 51 : if (fcode == IX86_BUILTIN_LWPVAL32
14198 : 51 : || fcode == IX86_BUILTIN_LWPVAL64)
14199 : 26 : icode = code_for_lwp_lwpval (mode);
14200 : : else
14201 : 25 : icode = code_for_lwp_lwpins (mode);
14202 : :
14203 : 51 : arg0 = CALL_EXPR_ARG (exp, 0);
14204 : 51 : arg1 = CALL_EXPR_ARG (exp, 1);
14205 : 51 : arg2 = CALL_EXPR_ARG (exp, 2);
14206 : 51 : op0 = expand_normal (arg0);
14207 : 51 : op1 = expand_normal (arg1);
14208 : 51 : op2 = expand_normal (arg2);
14209 : 51 : mode0 = insn_data[icode].operand[0].mode;
14210 : :
14211 : 51 : if (!insn_data[icode].operand[0].predicate (op0, mode0))
14212 : 13 : op0 = copy_to_mode_reg (mode0, op0);
14213 : 51 : if (!insn_data[icode].operand[1].predicate (op1, SImode))
14214 : 0 : op1 = copy_to_mode_reg (SImode, op1);
14215 : :
14216 : 51 : if (!CONST_INT_P (op2))
14217 : : {
14218 : 0 : error ("the last argument must be a 32-bit immediate");
14219 : 0 : return const0_rtx;
14220 : : }
14221 : :
14222 : 51 : emit_insn (GEN_FCN (icode) (op0, op1, op2));
14223 : :
14224 : 51 : if (fcode == IX86_BUILTIN_LWPINS32
14225 : 51 : || fcode == IX86_BUILTIN_LWPINS64)
14226 : : {
14227 : 25 : if (target == 0
14228 : 25 : || !nonimmediate_operand (target, QImode))
14229 : 0 : target = gen_reg_rtx (QImode);
14230 : :
14231 : 25 : pat = gen_rtx_EQ (QImode, gen_rtx_REG (CCCmode, FLAGS_REG),
14232 : : const0_rtx);
14233 : 25 : emit_insn (gen_rtx_SET (target, pat));
14234 : :
14235 : 25 : return target;
14236 : : }
14237 : : else
14238 : : return 0;
14239 : :
14240 : 18 : case IX86_BUILTIN_BEXTRI32:
14241 : 18 : case IX86_BUILTIN_BEXTRI64:
14242 : 18 : mode = (fcode == IX86_BUILTIN_BEXTRI32 ? SImode : DImode);
14243 : :
14244 : 18 : arg0 = CALL_EXPR_ARG (exp, 0);
14245 : 18 : arg1 = CALL_EXPR_ARG (exp, 1);
14246 : 18 : op0 = expand_normal (arg0);
14247 : 18 : op1 = expand_normal (arg1);
14248 : :
14249 : 18 : if (!CONST_INT_P (op1))
14250 : : {
14251 : 0 : error ("last argument must be an immediate");
14252 : 0 : return const0_rtx;
14253 : : }
14254 : : else
14255 : : {
14256 : 18 : unsigned char lsb_index = UINTVAL (op1);
14257 : 18 : unsigned char length = UINTVAL (op1) >> 8;
14258 : :
14259 : 18 : unsigned char bitsize = GET_MODE_BITSIZE (mode);
14260 : :
14261 : 18 : icode = code_for_tbm_bextri (mode);
14262 : :
14263 : 18 : mode1 = insn_data[icode].operand[1].mode;
14264 : 18 : if (!insn_data[icode].operand[1].predicate (op0, mode1))
14265 : 12 : op0 = copy_to_mode_reg (mode1, op0);
14266 : :
14267 : 18 : mode0 = insn_data[icode].operand[0].mode;
14268 : 18 : if (target == 0
14269 : 18 : || !register_operand (target, mode0))
14270 : 0 : target = gen_reg_rtx (mode0);
14271 : :
14272 : 18 : if (length == 0 || lsb_index >= bitsize)
14273 : : {
14274 : 8 : emit_move_insn (target, const0_rtx);
14275 : 8 : return target;
14276 : : }
14277 : :
14278 : 10 : if (length + lsb_index > bitsize)
14279 : 5 : length = bitsize - lsb_index;
14280 : :
14281 : 10 : op1 = GEN_INT (length);
14282 : 10 : op2 = GEN_INT (lsb_index);
14283 : :
14284 : 10 : emit_insn (GEN_FCN (icode) (target, op0, op1, op2));
14285 : 10 : return target;
14286 : : }
14287 : :
14288 : 21 : case IX86_BUILTIN_RDRAND16_STEP:
14289 : 21 : mode = HImode;
14290 : 21 : goto rdrand_step;
14291 : :
14292 : 44 : case IX86_BUILTIN_RDRAND32_STEP:
14293 : 44 : mode = SImode;
14294 : 44 : goto rdrand_step;
14295 : :
14296 : : case IX86_BUILTIN_RDRAND64_STEP:
14297 : : mode = DImode;
14298 : :
14299 : 85 : rdrand_step:
14300 : 85 : arg0 = CALL_EXPR_ARG (exp, 0);
14301 : 85 : op1 = expand_normal (arg0);
14302 : 85 : if (!address_operand (op1, VOIDmode))
14303 : : {
14304 : 29 : op1 = convert_memory_address (Pmode, op1);
14305 : 29 : op1 = copy_addr_to_reg (op1);
14306 : : }
14307 : :
14308 : 85 : op0 = gen_reg_rtx (mode);
14309 : 85 : emit_insn (gen_rdrand (mode, op0));
14310 : :
14311 : 85 : emit_move_insn (gen_rtx_MEM (mode, op1), op0);
14312 : :
14313 : 85 : op1 = force_reg (SImode, const1_rtx);
14314 : :
14315 : : /* Emit SImode conditional move. */
14316 : 85 : if (mode == HImode)
14317 : : {
14318 : 21 : if (TARGET_ZERO_EXTEND_WITH_AND
14319 : 21 : && optimize_function_for_speed_p (cfun))
14320 : : {
14321 : 0 : op2 = force_reg (SImode, const0_rtx);
14322 : :
14323 : 0 : emit_insn (gen_movstricthi
14324 : 0 : (gen_lowpart (HImode, op2), op0));
14325 : : }
14326 : : else
14327 : : {
14328 : 21 : op2 = gen_reg_rtx (SImode);
14329 : :
14330 : 21 : emit_insn (gen_zero_extendhisi2 (op2, op0));
14331 : : }
14332 : : }
14333 : 64 : else if (mode == SImode)
14334 : : op2 = op0;
14335 : : else
14336 : 20 : op2 = gen_rtx_SUBREG (SImode, op0, 0);
14337 : :
14338 : 85 : if (target == 0
14339 : 85 : || !register_operand (target, SImode))
14340 : 8 : target = gen_reg_rtx (SImode);
14341 : :
14342 : 85 : pat = gen_rtx_GEU (VOIDmode, gen_rtx_REG (CCCmode, FLAGS_REG),
14343 : : const0_rtx);
14344 : 85 : emit_insn (gen_rtx_SET (target,
14345 : : gen_rtx_IF_THEN_ELSE (SImode, pat, op2, op1)));
14346 : 85 : return target;
14347 : :
14348 : 19 : case IX86_BUILTIN_RDSEED16_STEP:
14349 : 19 : mode = HImode;
14350 : 19 : goto rdseed_step;
14351 : :
14352 : 28 : case IX86_BUILTIN_RDSEED32_STEP:
14353 : 28 : mode = SImode;
14354 : 28 : goto rdseed_step;
14355 : :
14356 : : case IX86_BUILTIN_RDSEED64_STEP:
14357 : : mode = DImode;
14358 : :
14359 : 66 : rdseed_step:
14360 : 66 : arg0 = CALL_EXPR_ARG (exp, 0);
14361 : 66 : op1 = expand_normal (arg0);
14362 : 66 : if (!address_operand (op1, VOIDmode))
14363 : : {
14364 : 28 : op1 = convert_memory_address (Pmode, op1);
14365 : 28 : op1 = copy_addr_to_reg (op1);
14366 : : }
14367 : :
14368 : 66 : op0 = gen_reg_rtx (mode);
14369 : 66 : emit_insn (gen_rdseed (mode, op0));
14370 : :
14371 : 66 : emit_move_insn (gen_rtx_MEM (mode, op1), op0);
14372 : :
14373 : 66 : op2 = gen_reg_rtx (QImode);
14374 : :
14375 : 66 : pat = gen_rtx_LTU (QImode, gen_rtx_REG (CCCmode, FLAGS_REG),
14376 : : const0_rtx);
14377 : 66 : emit_insn (gen_rtx_SET (op2, pat));
14378 : :
14379 : 66 : if (target == 0
14380 : 66 : || !register_operand (target, SImode))
14381 : 1 : target = gen_reg_rtx (SImode);
14382 : :
14383 : 66 : emit_insn (gen_zero_extendqisi2 (target, op2));
14384 : 66 : return target;
14385 : :
14386 : 38 : case IX86_BUILTIN_SBB32:
14387 : 38 : icode = CODE_FOR_subborrowsi;
14388 : 38 : icode2 = CODE_FOR_subborrowsi_0;
14389 : 38 : mode0 = SImode;
14390 : 38 : mode1 = DImode;
14391 : 38 : mode2 = CCmode;
14392 : 38 : goto handlecarry;
14393 : :
14394 : 41 : case IX86_BUILTIN_SBB64:
14395 : 41 : icode = CODE_FOR_subborrowdi;
14396 : 41 : icode2 = CODE_FOR_subborrowdi_0;
14397 : 41 : mode0 = DImode;
14398 : 41 : mode1 = TImode;
14399 : 41 : mode2 = CCmode;
14400 : 41 : goto handlecarry;
14401 : :
14402 : 68 : case IX86_BUILTIN_ADDCARRYX32:
14403 : 68 : icode = CODE_FOR_addcarrysi;
14404 : 68 : icode2 = CODE_FOR_addcarrysi_0;
14405 : 68 : mode0 = SImode;
14406 : 68 : mode1 = DImode;
14407 : 68 : mode2 = CCCmode;
14408 : 68 : goto handlecarry;
14409 : :
14410 : : case IX86_BUILTIN_ADDCARRYX64:
14411 : : icode = CODE_FOR_addcarrydi;
14412 : : icode2 = CODE_FOR_addcarrydi_0;
14413 : : mode0 = DImode;
14414 : : mode1 = TImode;
14415 : : mode2 = CCCmode;
14416 : :
14417 : 207 : handlecarry:
14418 : 207 : arg0 = CALL_EXPR_ARG (exp, 0); /* unsigned char c_in. */
14419 : 207 : arg1 = CALL_EXPR_ARG (exp, 1); /* unsigned int src1. */
14420 : 207 : arg2 = CALL_EXPR_ARG (exp, 2); /* unsigned int src2. */
14421 : 207 : arg3 = CALL_EXPR_ARG (exp, 3); /* unsigned int *sum_out. */
14422 : :
14423 : 207 : op1 = expand_normal (arg0);
14424 : :
14425 : 207 : op2 = expand_normal (arg1);
14426 : 207 : if (!register_operand (op2, mode0))
14427 : 116 : op2 = copy_to_mode_reg (mode0, op2);
14428 : :
14429 : 207 : op3 = expand_normal (arg2);
14430 : 207 : if (!register_operand (op3, mode0))
14431 : 117 : op3 = copy_to_mode_reg (mode0, op3);
14432 : :
14433 : 207 : op4 = expand_normal (arg3);
14434 : 207 : if (!address_operand (op4, VOIDmode))
14435 : : {
14436 : 67 : op4 = convert_memory_address (Pmode, op4);
14437 : 67 : op4 = copy_addr_to_reg (op4);
14438 : : }
14439 : :
14440 : 207 : op0 = gen_reg_rtx (mode0);
14441 : 207 : if (op1 == const0_rtx)
14442 : : {
14443 : : /* If arg0 is 0, optimize right away into add or sub
14444 : : instruction that sets CCCmode flags. */
14445 : 19 : op1 = gen_rtx_REG (mode2, FLAGS_REG);
14446 : 19 : emit_insn (GEN_FCN (icode2) (op0, op2, op3));
14447 : : }
14448 : : else
14449 : : {
14450 : : /* Generate CF from input operand. */
14451 : 188 : ix86_expand_carry (op1);
14452 : :
14453 : : /* Generate instruction that consumes CF. */
14454 : 188 : op1 = gen_rtx_REG (CCCmode, FLAGS_REG);
14455 : 188 : pat = gen_rtx_LTU (mode1, op1, const0_rtx);
14456 : 188 : pat2 = gen_rtx_LTU (mode0, op1, const0_rtx);
14457 : 188 : emit_insn (GEN_FCN (icode) (op0, op2, op3, op1, pat, pat2));
14458 : : }
14459 : :
14460 : : /* Return current CF value. */
14461 : 207 : if (target == 0)
14462 : 13 : target = gen_reg_rtx (QImode);
14463 : :
14464 : 207 : pat = gen_rtx_LTU (QImode, op1, const0_rtx);
14465 : 207 : emit_insn (gen_rtx_SET (target, pat));
14466 : :
14467 : : /* Store the result. */
14468 : 207 : emit_move_insn (gen_rtx_MEM (mode0, op4), op0);
14469 : :
14470 : 207 : return target;
14471 : :
14472 : 24 : case IX86_BUILTIN_READ_FLAGS:
14473 : 24 : if (ignore)
14474 : 1 : return const0_rtx;
14475 : :
14476 : 23 : emit_insn (gen_pushfl ());
14477 : :
14478 : 23 : if (optimize
14479 : 11 : || target == NULL_RTX
14480 : 11 : || !nonimmediate_operand (target, word_mode)
14481 : 34 : || GET_MODE (target) != word_mode)
14482 : 12 : target = gen_reg_rtx (word_mode);
14483 : :
14484 : 23 : emit_insn (gen_pop (target));
14485 : 23 : return target;
14486 : :
14487 : 21 : case IX86_BUILTIN_WRITE_FLAGS:
14488 : :
14489 : 21 : arg0 = CALL_EXPR_ARG (exp, 0);
14490 : 21 : op0 = expand_normal (arg0);
14491 : 21 : if (!general_no_elim_operand (op0, word_mode))
14492 : 0 : op0 = copy_to_mode_reg (word_mode, op0);
14493 : :
14494 : 21 : emit_insn (gen_push (op0));
14495 : 21 : emit_insn (gen_popfl ());
14496 : 21 : return 0;
14497 : :
14498 : 22 : case IX86_BUILTIN_KTESTC8:
14499 : 22 : icode = CODE_FOR_ktestqi;
14500 : 22 : mode3 = CCCmode;
14501 : 22 : goto kortest;
14502 : :
14503 : 22 : case IX86_BUILTIN_KTESTZ8:
14504 : 22 : icode = CODE_FOR_ktestqi;
14505 : 22 : mode3 = CCZmode;
14506 : 22 : goto kortest;
14507 : :
14508 : 22 : case IX86_BUILTIN_KTESTC16:
14509 : 22 : icode = CODE_FOR_ktesthi;
14510 : 22 : mode3 = CCCmode;
14511 : 22 : goto kortest;
14512 : :
14513 : 22 : case IX86_BUILTIN_KTESTZ16:
14514 : 22 : icode = CODE_FOR_ktesthi;
14515 : 22 : mode3 = CCZmode;
14516 : 22 : goto kortest;
14517 : :
14518 : 22 : case IX86_BUILTIN_KTESTC32:
14519 : 22 : icode = CODE_FOR_ktestsi;
14520 : 22 : mode3 = CCCmode;
14521 : 22 : goto kortest;
14522 : :
14523 : 22 : case IX86_BUILTIN_KTESTZ32:
14524 : 22 : icode = CODE_FOR_ktestsi;
14525 : 22 : mode3 = CCZmode;
14526 : 22 : goto kortest;
14527 : :
14528 : 22 : case IX86_BUILTIN_KTESTC64:
14529 : 22 : icode = CODE_FOR_ktestdi;
14530 : 22 : mode3 = CCCmode;
14531 : 22 : goto kortest;
14532 : :
14533 : 22 : case IX86_BUILTIN_KTESTZ64:
14534 : 22 : icode = CODE_FOR_ktestdi;
14535 : 22 : mode3 = CCZmode;
14536 : 22 : goto kortest;
14537 : :
14538 : 22 : case IX86_BUILTIN_KORTESTC8:
14539 : 22 : icode = CODE_FOR_kortestqi;
14540 : 22 : mode3 = CCCmode;
14541 : 22 : goto kortest;
14542 : :
14543 : 76 : case IX86_BUILTIN_KORTESTZ8:
14544 : 76 : icode = CODE_FOR_kortestqi;
14545 : 76 : mode3 = CCZmode;
14546 : 76 : goto kortest;
14547 : :
14548 : 38 : case IX86_BUILTIN_KORTESTC16:
14549 : 38 : icode = CODE_FOR_kortesthi;
14550 : 38 : mode3 = CCCmode;
14551 : 38 : goto kortest;
14552 : :
14553 : 90 : case IX86_BUILTIN_KORTESTZ16:
14554 : 90 : icode = CODE_FOR_kortesthi;
14555 : 90 : mode3 = CCZmode;
14556 : 90 : goto kortest;
14557 : :
14558 : 22 : case IX86_BUILTIN_KORTESTC32:
14559 : 22 : icode = CODE_FOR_kortestsi;
14560 : 22 : mode3 = CCCmode;
14561 : 22 : goto kortest;
14562 : :
14563 : 79 : case IX86_BUILTIN_KORTESTZ32:
14564 : 79 : icode = CODE_FOR_kortestsi;
14565 : 79 : mode3 = CCZmode;
14566 : 79 : goto kortest;
14567 : :
14568 : 22 : case IX86_BUILTIN_KORTESTC64:
14569 : 22 : icode = CODE_FOR_kortestdi;
14570 : 22 : mode3 = CCCmode;
14571 : 22 : goto kortest;
14572 : :
14573 : : case IX86_BUILTIN_KORTESTZ64:
14574 : : icode = CODE_FOR_kortestdi;
14575 : : mode3 = CCZmode;
14576 : :
14577 : 609 : kortest:
14578 : 609 : arg0 = CALL_EXPR_ARG (exp, 0); /* Mask reg src1. */
14579 : 609 : arg1 = CALL_EXPR_ARG (exp, 1); /* Mask reg src2. */
14580 : 609 : op0 = expand_normal (arg0);
14581 : 609 : op1 = expand_normal (arg1);
14582 : :
14583 : 609 : mode0 = insn_data[icode].operand[0].mode;
14584 : 609 : mode1 = insn_data[icode].operand[1].mode;
14585 : :
14586 : 609 : if (GET_MODE (op0) != VOIDmode)
14587 : 609 : op0 = force_reg (GET_MODE (op0), op0);
14588 : :
14589 : 609 : op0 = gen_lowpart (mode0, op0);
14590 : :
14591 : 609 : if (!insn_data[icode].operand[0].predicate (op0, mode0))
14592 : 0 : op0 = copy_to_mode_reg (mode0, op0);
14593 : :
14594 : 609 : if (GET_MODE (op1) != VOIDmode)
14595 : 608 : op1 = force_reg (GET_MODE (op1), op1);
14596 : :
14597 : 609 : op1 = gen_lowpart (mode1, op1);
14598 : :
14599 : 609 : if (!insn_data[icode].operand[1].predicate (op1, mode1))
14600 : 1 : op1 = copy_to_mode_reg (mode1, op1);
14601 : :
14602 : 609 : target = gen_reg_rtx (QImode);
14603 : :
14604 : : /* Emit kortest. */
14605 : 609 : emit_insn (GEN_FCN (icode) (op0, op1));
14606 : : /* And use setcc to return result from flags. */
14607 : 609 : ix86_expand_setcc (target, EQ,
14608 : : gen_rtx_REG (mode3, FLAGS_REG), const0_rtx);
14609 : 609 : return target;
14610 : :
14611 : 24 : case IX86_BUILTIN_GATHERSIV2DF:
14612 : 24 : icode = CODE_FOR_avx2_gathersiv2df;
14613 : 24 : goto gather_gen;
14614 : 18 : case IX86_BUILTIN_GATHERSIV4DF:
14615 : 18 : icode = CODE_FOR_avx2_gathersiv4df;
14616 : 18 : goto gather_gen;
14617 : 21 : case IX86_BUILTIN_GATHERDIV2DF:
14618 : 21 : icode = CODE_FOR_avx2_gatherdiv2df;
14619 : 21 : goto gather_gen;
14620 : 32 : case IX86_BUILTIN_GATHERDIV4DF:
14621 : 32 : icode = CODE_FOR_avx2_gatherdiv4df;
14622 : 32 : goto gather_gen;
14623 : 32 : case IX86_BUILTIN_GATHERSIV4SF:
14624 : 32 : icode = CODE_FOR_avx2_gathersiv4sf;
14625 : 32 : goto gather_gen;
14626 : 38 : case IX86_BUILTIN_GATHERSIV8SF:
14627 : 38 : icode = CODE_FOR_avx2_gathersiv8sf;
14628 : 38 : goto gather_gen;
14629 : 26 : case IX86_BUILTIN_GATHERDIV4SF:
14630 : 26 : icode = CODE_FOR_avx2_gatherdiv4sf;
14631 : 26 : goto gather_gen;
14632 : 18 : case IX86_BUILTIN_GATHERDIV8SF:
14633 : 18 : icode = CODE_FOR_avx2_gatherdiv8sf;
14634 : 18 : goto gather_gen;
14635 : 18 : case IX86_BUILTIN_GATHERSIV2DI:
14636 : 18 : icode = CODE_FOR_avx2_gathersiv2di;
14637 : 18 : goto gather_gen;
14638 : 18 : case IX86_BUILTIN_GATHERSIV4DI:
14639 : 18 : icode = CODE_FOR_avx2_gathersiv4di;
14640 : 18 : goto gather_gen;
14641 : 27 : case IX86_BUILTIN_GATHERDIV2DI:
14642 : 27 : icode = CODE_FOR_avx2_gatherdiv2di;
14643 : 27 : goto gather_gen;
14644 : 29 : case IX86_BUILTIN_GATHERDIV4DI:
14645 : 29 : icode = CODE_FOR_avx2_gatherdiv4di;
14646 : 29 : goto gather_gen;
14647 : 21 : case IX86_BUILTIN_GATHERSIV4SI:
14648 : 21 : icode = CODE_FOR_avx2_gathersiv4si;
14649 : 21 : goto gather_gen;
14650 : 22 : case IX86_BUILTIN_GATHERSIV8SI:
14651 : 22 : icode = CODE_FOR_avx2_gathersiv8si;
14652 : 22 : goto gather_gen;
14653 : 28 : case IX86_BUILTIN_GATHERDIV4SI:
14654 : 28 : icode = CODE_FOR_avx2_gatherdiv4si;
14655 : 28 : goto gather_gen;
14656 : 18 : case IX86_BUILTIN_GATHERDIV8SI:
14657 : 18 : icode = CODE_FOR_avx2_gatherdiv8si;
14658 : 18 : goto gather_gen;
14659 : 20 : case IX86_BUILTIN_GATHERALTSIV4DF:
14660 : 20 : icode = CODE_FOR_avx2_gathersiv4df;
14661 : 20 : goto gather_gen;
14662 : 16 : case IX86_BUILTIN_GATHERALTDIV8SF:
14663 : 16 : icode = CODE_FOR_avx2_gatherdiv8sf;
14664 : 16 : goto gather_gen;
14665 : 4 : case IX86_BUILTIN_GATHERALTSIV4DI:
14666 : 4 : icode = CODE_FOR_avx2_gathersiv4di;
14667 : 4 : goto gather_gen;
14668 : 10 : case IX86_BUILTIN_GATHERALTDIV8SI:
14669 : 10 : icode = CODE_FOR_avx2_gatherdiv8si;
14670 : 10 : goto gather_gen;
14671 : 36 : case IX86_BUILTIN_GATHER3SIV16SF:
14672 : 36 : icode = CODE_FOR_avx512f_gathersiv16sf;
14673 : 36 : goto gather_gen;
14674 : 24 : case IX86_BUILTIN_GATHER3SIV8DF:
14675 : 24 : icode = CODE_FOR_avx512f_gathersiv8df;
14676 : 24 : goto gather_gen;
14677 : 24 : case IX86_BUILTIN_GATHER3DIV16SF:
14678 : 24 : icode = CODE_FOR_avx512f_gatherdiv16sf;
14679 : 24 : goto gather_gen;
14680 : 37 : case IX86_BUILTIN_GATHER3DIV8DF:
14681 : 37 : icode = CODE_FOR_avx512f_gatherdiv8df;
14682 : 37 : goto gather_gen;
14683 : 30 : case IX86_BUILTIN_GATHER3SIV16SI:
14684 : 30 : icode = CODE_FOR_avx512f_gathersiv16si;
14685 : 30 : goto gather_gen;
14686 : 24 : case IX86_BUILTIN_GATHER3SIV8DI:
14687 : 24 : icode = CODE_FOR_avx512f_gathersiv8di;
14688 : 24 : goto gather_gen;
14689 : 24 : case IX86_BUILTIN_GATHER3DIV16SI:
14690 : 24 : icode = CODE_FOR_avx512f_gatherdiv16si;
14691 : 24 : goto gather_gen;
14692 : 37 : case IX86_BUILTIN_GATHER3DIV8DI:
14693 : 37 : icode = CODE_FOR_avx512f_gatherdiv8di;
14694 : 37 : goto gather_gen;
14695 : 16 : case IX86_BUILTIN_GATHER3ALTSIV8DF:
14696 : 16 : icode = CODE_FOR_avx512f_gathersiv8df;
14697 : 16 : goto gather_gen;
14698 : 22 : case IX86_BUILTIN_GATHER3ALTDIV16SF:
14699 : 22 : icode = CODE_FOR_avx512f_gatherdiv16sf;
14700 : 22 : goto gather_gen;
14701 : 14 : case IX86_BUILTIN_GATHER3ALTSIV8DI:
14702 : 14 : icode = CODE_FOR_avx512f_gathersiv8di;
14703 : 14 : goto gather_gen;
14704 : 20 : case IX86_BUILTIN_GATHER3ALTDIV16SI:
14705 : 20 : icode = CODE_FOR_avx512f_gatherdiv16si;
14706 : 20 : goto gather_gen;
14707 : 18 : case IX86_BUILTIN_GATHER3SIV2DF:
14708 : 18 : icode = CODE_FOR_avx512vl_gathersiv2df;
14709 : 18 : goto gather_gen;
14710 : 10 : case IX86_BUILTIN_GATHER3SIV4DF:
14711 : 10 : icode = CODE_FOR_avx512vl_gathersiv4df;
14712 : 10 : goto gather_gen;
14713 : 16 : case IX86_BUILTIN_GATHER3DIV2DF:
14714 : 16 : icode = CODE_FOR_avx512vl_gatherdiv2df;
14715 : 16 : goto gather_gen;
14716 : 16 : case IX86_BUILTIN_GATHER3DIV4DF:
14717 : 16 : icode = CODE_FOR_avx512vl_gatherdiv4df;
14718 : 16 : goto gather_gen;
14719 : 14 : case IX86_BUILTIN_GATHER3SIV4SF:
14720 : 14 : icode = CODE_FOR_avx512vl_gathersiv4sf;
14721 : 14 : goto gather_gen;
14722 : 12 : case IX86_BUILTIN_GATHER3SIV8SF:
14723 : 12 : icode = CODE_FOR_avx512vl_gathersiv8sf;
14724 : 12 : goto gather_gen;
14725 : 22 : case IX86_BUILTIN_GATHER3DIV4SF:
14726 : 22 : icode = CODE_FOR_avx512vl_gatherdiv4sf;
14727 : 22 : goto gather_gen;
14728 : 10 : case IX86_BUILTIN_GATHER3DIV8SF:
14729 : 10 : icode = CODE_FOR_avx512vl_gatherdiv8sf;
14730 : 10 : goto gather_gen;
14731 : 20 : case IX86_BUILTIN_GATHER3SIV2DI:
14732 : 20 : icode = CODE_FOR_avx512vl_gathersiv2di;
14733 : 20 : goto gather_gen;
14734 : 10 : case IX86_BUILTIN_GATHER3SIV4DI:
14735 : 10 : icode = CODE_FOR_avx512vl_gathersiv4di;
14736 : 10 : goto gather_gen;
14737 : 14 : case IX86_BUILTIN_GATHER3DIV2DI:
14738 : 14 : icode = CODE_FOR_avx512vl_gatherdiv2di;
14739 : 14 : goto gather_gen;
14740 : 13 : case IX86_BUILTIN_GATHER3DIV4DI:
14741 : 13 : icode = CODE_FOR_avx512vl_gatherdiv4di;
14742 : 13 : goto gather_gen;
14743 : 14 : case IX86_BUILTIN_GATHER3SIV4SI:
14744 : 14 : icode = CODE_FOR_avx512vl_gathersiv4si;
14745 : 14 : goto gather_gen;
14746 : 12 : case IX86_BUILTIN_GATHER3SIV8SI:
14747 : 12 : icode = CODE_FOR_avx512vl_gathersiv8si;
14748 : 12 : goto gather_gen;
14749 : 24 : case IX86_BUILTIN_GATHER3DIV4SI:
14750 : 24 : icode = CODE_FOR_avx512vl_gatherdiv4si;
14751 : 24 : goto gather_gen;
14752 : 10 : case IX86_BUILTIN_GATHER3DIV8SI:
14753 : 10 : icode = CODE_FOR_avx512vl_gatherdiv8si;
14754 : 10 : goto gather_gen;
14755 : 4 : case IX86_BUILTIN_GATHER3ALTSIV4DF:
14756 : 4 : icode = CODE_FOR_avx512vl_gathersiv4df;
14757 : 4 : goto gather_gen;
14758 : 8 : case IX86_BUILTIN_GATHER3ALTDIV8SF:
14759 : 8 : icode = CODE_FOR_avx512vl_gatherdiv8sf;
14760 : 8 : goto gather_gen;
14761 : 6 : case IX86_BUILTIN_GATHER3ALTSIV4DI:
14762 : 6 : icode = CODE_FOR_avx512vl_gathersiv4di;
14763 : 6 : goto gather_gen;
14764 : 10 : case IX86_BUILTIN_GATHER3ALTDIV8SI:
14765 : 10 : icode = CODE_FOR_avx512vl_gatherdiv8si;
14766 : 10 : goto gather_gen;
14767 : 40 : case IX86_BUILTIN_SCATTERSIV16SF:
14768 : 40 : icode = CODE_FOR_avx512f_scattersiv16sf;
14769 : 40 : goto scatter_gen;
14770 : 27 : case IX86_BUILTIN_SCATTERSIV8DF:
14771 : 27 : icode = CODE_FOR_avx512f_scattersiv8df;
14772 : 27 : goto scatter_gen;
14773 : 24 : case IX86_BUILTIN_SCATTERDIV16SF:
14774 : 24 : icode = CODE_FOR_avx512f_scatterdiv16sf;
14775 : 24 : goto scatter_gen;
14776 : 37 : case IX86_BUILTIN_SCATTERDIV8DF:
14777 : 37 : icode = CODE_FOR_avx512f_scatterdiv8df;
14778 : 37 : goto scatter_gen;
14779 : 30 : case IX86_BUILTIN_SCATTERSIV16SI:
14780 : 30 : icode = CODE_FOR_avx512f_scattersiv16si;
14781 : 30 : goto scatter_gen;
14782 : 24 : case IX86_BUILTIN_SCATTERSIV8DI:
14783 : 24 : icode = CODE_FOR_avx512f_scattersiv8di;
14784 : 24 : goto scatter_gen;
14785 : 24 : case IX86_BUILTIN_SCATTERDIV16SI:
14786 : 24 : icode = CODE_FOR_avx512f_scatterdiv16si;
14787 : 24 : goto scatter_gen;
14788 : 29 : case IX86_BUILTIN_SCATTERDIV8DI:
14789 : 29 : icode = CODE_FOR_avx512f_scatterdiv8di;
14790 : 29 : goto scatter_gen;
14791 : 18 : case IX86_BUILTIN_SCATTERSIV8SF:
14792 : 18 : icode = CODE_FOR_avx512vl_scattersiv8sf;
14793 : 18 : goto scatter_gen;
14794 : 20 : case IX86_BUILTIN_SCATTERSIV4SF:
14795 : 20 : icode = CODE_FOR_avx512vl_scattersiv4sf;
14796 : 20 : goto scatter_gen;
14797 : 16 : case IX86_BUILTIN_SCATTERSIV4DF:
14798 : 16 : icode = CODE_FOR_avx512vl_scattersiv4df;
14799 : 16 : goto scatter_gen;
14800 : 16 : case IX86_BUILTIN_SCATTERSIV2DF:
14801 : 16 : icode = CODE_FOR_avx512vl_scattersiv2df;
14802 : 16 : goto scatter_gen;
14803 : 16 : case IX86_BUILTIN_SCATTERDIV8SF:
14804 : 16 : icode = CODE_FOR_avx512vl_scatterdiv8sf;
14805 : 16 : goto scatter_gen;
14806 : 16 : case IX86_BUILTIN_SCATTERDIV4SF:
14807 : 16 : icode = CODE_FOR_avx512vl_scatterdiv4sf;
14808 : 16 : goto scatter_gen;
14809 : 18 : case IX86_BUILTIN_SCATTERDIV4DF:
14810 : 18 : icode = CODE_FOR_avx512vl_scatterdiv4df;
14811 : 18 : goto scatter_gen;
14812 : 20 : case IX86_BUILTIN_SCATTERDIV2DF:
14813 : 20 : icode = CODE_FOR_avx512vl_scatterdiv2df;
14814 : 20 : goto scatter_gen;
14815 : 32 : case IX86_BUILTIN_SCATTERSIV8SI:
14816 : 32 : icode = CODE_FOR_avx512vl_scattersiv8si;
14817 : 32 : goto scatter_gen;
14818 : 34 : case IX86_BUILTIN_SCATTERSIV4SI:
14819 : 34 : icode = CODE_FOR_avx512vl_scattersiv4si;
14820 : 34 : goto scatter_gen;
14821 : 16 : case IX86_BUILTIN_SCATTERSIV4DI:
14822 : 16 : icode = CODE_FOR_avx512vl_scattersiv4di;
14823 : 16 : goto scatter_gen;
14824 : 16 : case IX86_BUILTIN_SCATTERSIV2DI:
14825 : 16 : icode = CODE_FOR_avx512vl_scattersiv2di;
14826 : 16 : goto scatter_gen;
14827 : 16 : case IX86_BUILTIN_SCATTERDIV8SI:
14828 : 16 : icode = CODE_FOR_avx512vl_scatterdiv8si;
14829 : 16 : goto scatter_gen;
14830 : 16 : case IX86_BUILTIN_SCATTERDIV4SI:
14831 : 16 : icode = CODE_FOR_avx512vl_scatterdiv4si;
14832 : 16 : goto scatter_gen;
14833 : 18 : case IX86_BUILTIN_SCATTERDIV4DI:
14834 : 18 : icode = CODE_FOR_avx512vl_scatterdiv4di;
14835 : 18 : goto scatter_gen;
14836 : 18 : case IX86_BUILTIN_SCATTERDIV2DI:
14837 : 18 : icode = CODE_FOR_avx512vl_scatterdiv2di;
14838 : 18 : goto scatter_gen;
14839 : 26 : case IX86_BUILTIN_GATHERPFDPD:
14840 : 26 : icode = CODE_FOR_avx512pf_gatherpfv8sidf;
14841 : 26 : goto vec_prefetch_gen;
14842 : 16 : case IX86_BUILTIN_SCATTERALTSIV8DF:
14843 : 16 : icode = CODE_FOR_avx512f_scattersiv8df;
14844 : 16 : goto scatter_gen;
14845 : 12 : case IX86_BUILTIN_SCATTERALTDIV16SF:
14846 : 12 : icode = CODE_FOR_avx512f_scatterdiv16sf;
14847 : 12 : goto scatter_gen;
14848 : 8 : case IX86_BUILTIN_SCATTERALTSIV8DI:
14849 : 8 : icode = CODE_FOR_avx512f_scattersiv8di;
14850 : 8 : goto scatter_gen;
14851 : 24 : case IX86_BUILTIN_SCATTERALTDIV16SI:
14852 : 24 : icode = CODE_FOR_avx512f_scatterdiv16si;
14853 : 24 : goto scatter_gen;
14854 : 4 : case IX86_BUILTIN_SCATTERALTSIV4DF:
14855 : 4 : icode = CODE_FOR_avx512vl_scattersiv4df;
14856 : 4 : goto scatter_gen;
14857 : 4 : case IX86_BUILTIN_SCATTERALTDIV8SF:
14858 : 4 : icode = CODE_FOR_avx512vl_scatterdiv8sf;
14859 : 4 : goto scatter_gen;
14860 : 4 : case IX86_BUILTIN_SCATTERALTSIV4DI:
14861 : 4 : icode = CODE_FOR_avx512vl_scattersiv4di;
14862 : 4 : goto scatter_gen;
14863 : 4 : case IX86_BUILTIN_SCATTERALTDIV8SI:
14864 : 4 : icode = CODE_FOR_avx512vl_scatterdiv8si;
14865 : 4 : goto scatter_gen;
14866 : 8 : case IX86_BUILTIN_SCATTERALTSIV2DF:
14867 : 8 : icode = CODE_FOR_avx512vl_scattersiv2df;
14868 : 8 : goto scatter_gen;
14869 : 8 : case IX86_BUILTIN_SCATTERALTDIV4SF:
14870 : 8 : icode = CODE_FOR_avx512vl_scatterdiv4sf;
14871 : 8 : goto scatter_gen;
14872 : 8 : case IX86_BUILTIN_SCATTERALTSIV2DI:
14873 : 8 : icode = CODE_FOR_avx512vl_scattersiv2di;
14874 : 8 : goto scatter_gen;
14875 : 8 : case IX86_BUILTIN_SCATTERALTDIV4SI:
14876 : 8 : icode = CODE_FOR_avx512vl_scatterdiv4si;
14877 : 8 : goto scatter_gen;
14878 : 22 : case IX86_BUILTIN_GATHERPFDPS:
14879 : 22 : icode = CODE_FOR_avx512pf_gatherpfv16sisf;
14880 : 22 : goto vec_prefetch_gen;
14881 : 22 : case IX86_BUILTIN_GATHERPFQPD:
14882 : 22 : icode = CODE_FOR_avx512pf_gatherpfv8didf;
14883 : 22 : goto vec_prefetch_gen;
14884 : 22 : case IX86_BUILTIN_GATHERPFQPS:
14885 : 22 : icode = CODE_FOR_avx512pf_gatherpfv8disf;
14886 : 22 : goto vec_prefetch_gen;
14887 : 22 : case IX86_BUILTIN_SCATTERPFDPD:
14888 : 22 : icode = CODE_FOR_avx512pf_scatterpfv8sidf;
14889 : 22 : goto vec_prefetch_gen;
14890 : 22 : case IX86_BUILTIN_SCATTERPFDPS:
14891 : 22 : icode = CODE_FOR_avx512pf_scatterpfv16sisf;
14892 : 22 : goto vec_prefetch_gen;
14893 : 22 : case IX86_BUILTIN_SCATTERPFQPD:
14894 : 22 : icode = CODE_FOR_avx512pf_scatterpfv8didf;
14895 : 22 : goto vec_prefetch_gen;
14896 : 22 : case IX86_BUILTIN_SCATTERPFQPS:
14897 : 22 : icode = CODE_FOR_avx512pf_scatterpfv8disf;
14898 : 22 : goto vec_prefetch_gen;
14899 : :
14900 : 1011 : gather_gen:
14901 : 1011 : rtx half;
14902 : 1011 : rtx (*gen) (rtx, rtx);
14903 : :
14904 : 1011 : arg0 = CALL_EXPR_ARG (exp, 0);
14905 : 1011 : arg1 = CALL_EXPR_ARG (exp, 1);
14906 : 1011 : arg2 = CALL_EXPR_ARG (exp, 2);
14907 : 1011 : arg3 = CALL_EXPR_ARG (exp, 3);
14908 : 1011 : arg4 = CALL_EXPR_ARG (exp, 4);
14909 : 1011 : op0 = expand_normal (arg0);
14910 : 1011 : op1 = expand_normal (arg1);
14911 : 1011 : op2 = expand_normal (arg2);
14912 : 1011 : op3 = expand_normal (arg3);
14913 : 1011 : op4 = expand_normal (arg4);
14914 : : /* Note the arg order is different from the operand order. */
14915 : 1011 : mode0 = insn_data[icode].operand[1].mode;
14916 : 1011 : mode2 = insn_data[icode].operand[3].mode;
14917 : 1011 : mode3 = insn_data[icode].operand[4].mode;
14918 : 1011 : mode4 = insn_data[icode].operand[5].mode;
14919 : :
14920 : 1011 : if (target == NULL_RTX
14921 : 1011 : || GET_MODE (target) != insn_data[icode].operand[0].mode
14922 : 1918 : || !insn_data[icode].operand[0].predicate (target,
14923 : : GET_MODE (target)))
14924 : 105 : subtarget = gen_reg_rtx (insn_data[icode].operand[0].mode);
14925 : : else
14926 : : subtarget = target;
14927 : :
14928 : 1011 : switch (fcode)
14929 : : {
14930 : 30 : case IX86_BUILTIN_GATHER3ALTSIV8DF:
14931 : 30 : case IX86_BUILTIN_GATHER3ALTSIV8DI:
14932 : 30 : half = gen_reg_rtx (V8SImode);
14933 : 30 : if (!nonimmediate_operand (op2, V16SImode))
14934 : 0 : op2 = copy_to_mode_reg (V16SImode, op2);
14935 : 30 : emit_insn (gen_vec_extract_lo_v16si (half, op2));
14936 : 30 : op2 = half;
14937 : 30 : break;
14938 : 34 : case IX86_BUILTIN_GATHER3ALTSIV4DF:
14939 : 34 : case IX86_BUILTIN_GATHER3ALTSIV4DI:
14940 : 34 : case IX86_BUILTIN_GATHERALTSIV4DF:
14941 : 34 : case IX86_BUILTIN_GATHERALTSIV4DI:
14942 : 34 : half = gen_reg_rtx (V4SImode);
14943 : 34 : if (!nonimmediate_operand (op2, V8SImode))
14944 : 0 : op2 = copy_to_mode_reg (V8SImode, op2);
14945 : 34 : emit_insn (gen_vec_extract_lo_v8si (half, op2));
14946 : 34 : op2 = half;
14947 : 34 : break;
14948 : 42 : case IX86_BUILTIN_GATHER3ALTDIV16SF:
14949 : 42 : case IX86_BUILTIN_GATHER3ALTDIV16SI:
14950 : 42 : half = gen_reg_rtx (mode0);
14951 : 42 : if (mode0 == V8SFmode)
14952 : : gen = gen_vec_extract_lo_v16sf;
14953 : : else
14954 : 20 : gen = gen_vec_extract_lo_v16si;
14955 : 42 : if (!nonimmediate_operand (op0, GET_MODE (op0)))
14956 : 42 : op0 = copy_to_mode_reg (GET_MODE (op0), op0);
14957 : 42 : emit_insn (gen (half, op0));
14958 : 42 : op0 = half;
14959 : 42 : op3 = lowpart_subreg (QImode, op3, HImode);
14960 : 42 : break;
14961 : 44 : case IX86_BUILTIN_GATHER3ALTDIV8SF:
14962 : 44 : case IX86_BUILTIN_GATHER3ALTDIV8SI:
14963 : 44 : case IX86_BUILTIN_GATHERALTDIV8SF:
14964 : 44 : case IX86_BUILTIN_GATHERALTDIV8SI:
14965 : 44 : half = gen_reg_rtx (mode0);
14966 : 44 : if (mode0 == V4SFmode)
14967 : : gen = gen_vec_extract_lo_v8sf;
14968 : : else
14969 : 20 : gen = gen_vec_extract_lo_v8si;
14970 : 44 : if (!nonimmediate_operand (op0, GET_MODE (op0)))
14971 : 44 : op0 = copy_to_mode_reg (GET_MODE (op0), op0);
14972 : 44 : emit_insn (gen (half, op0));
14973 : 44 : op0 = half;
14974 : 44 : if (VECTOR_MODE_P (GET_MODE (op3)))
14975 : : {
14976 : 26 : half = gen_reg_rtx (mode0);
14977 : 26 : if (!nonimmediate_operand (op3, GET_MODE (op3)))
14978 : 12 : op3 = copy_to_mode_reg (GET_MODE (op3), op3);
14979 : 26 : emit_insn (gen (half, op3));
14980 : 26 : op3 = half;
14981 : : }
14982 : : break;
14983 : : default:
14984 : : break;
14985 : : }
14986 : :
14987 : : /* Force memory operand only with base register here. But we
14988 : : don't want to do it on memory operand for other builtin
14989 : : functions. */
14990 : 1011 : op1 = ix86_zero_extend_to_Pmode (op1);
14991 : :
14992 : 1011 : if (!insn_data[icode].operand[1].predicate (op0, mode0))
14993 : 406 : op0 = copy_to_mode_reg (mode0, op0);
14994 : 1011 : if (!insn_data[icode].operand[2].predicate (op1, Pmode))
14995 : 0 : op1 = copy_to_mode_reg (Pmode, op1);
14996 : 1011 : if (!insn_data[icode].operand[3].predicate (op2, mode2))
14997 : 221 : op2 = copy_to_mode_reg (mode2, op2);
14998 : :
14999 : 1011 : op3 = fixup_modeless_constant (op3, mode3);
15000 : :
15001 : 1011 : if (GET_MODE (op3) == mode3 || GET_MODE (op3) == VOIDmode)
15002 : : {
15003 : 795 : if (!insn_data[icode].operand[4].predicate (op3, mode3))
15004 : 356 : op3 = copy_to_mode_reg (mode3, op3);
15005 : : }
15006 : : else
15007 : : {
15008 : 216 : op3 = copy_to_reg (op3);
15009 : 216 : op3 = lowpart_subreg (mode3, op3, GET_MODE (op3));
15010 : : }
15011 : 1011 : if (!insn_data[icode].operand[5].predicate (op4, mode4))
15012 : : {
15013 : 0 : error ("the last argument must be scale 1, 2, 4, 8");
15014 : 0 : return const0_rtx;
15015 : : }
15016 : :
15017 : : /* Optimize. If mask is known to have all high bits set,
15018 : : replace op0 with pc_rtx to signal that the instruction
15019 : : overwrites the whole destination and doesn't use its
15020 : : previous contents. */
15021 : 1011 : if (optimize)
15022 : : {
15023 : 918 : if (TREE_CODE (arg3) == INTEGER_CST)
15024 : : {
15025 : 209 : if (integer_all_onesp (arg3))
15026 : 195 : op0 = pc_rtx;
15027 : : }
15028 : 709 : else if (TREE_CODE (arg3) == VECTOR_CST)
15029 : : {
15030 : : unsigned int negative = 0;
15031 : 751 : for (i = 0; i < VECTOR_CST_NELTS (arg3); ++i)
15032 : : {
15033 : 616 : tree cst = VECTOR_CST_ELT (arg3, i);
15034 : 616 : if (TREE_CODE (cst) == INTEGER_CST
15035 : 616 : && tree_int_cst_sign_bit (cst))
15036 : 290 : negative++;
15037 : 326 : else if (TREE_CODE (cst) == REAL_CST
15038 : 326 : && REAL_VALUE_NEGATIVE (TREE_REAL_CST (cst)))
15039 : 298 : negative++;
15040 : : }
15041 : 135 : if (negative == TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg3)))
15042 : 121 : op0 = pc_rtx;
15043 : : }
15044 : 574 : else if (TREE_CODE (arg3) == SSA_NAME
15045 : 574 : && VECTOR_TYPE_P (TREE_TYPE (arg3)))
15046 : : {
15047 : : /* Recognize also when mask is like:
15048 : : __v2df src = _mm_setzero_pd ();
15049 : : __v2df mask = _mm_cmpeq_pd (src, src);
15050 : : or
15051 : : __v8sf src = _mm256_setzero_ps ();
15052 : : __v8sf mask = _mm256_cmp_ps (src, src, _CMP_EQ_OQ);
15053 : : as that is a cheaper way to load all ones into
15054 : : a register than having to load a constant from
15055 : : memory. */
15056 : 260 : gimple *def_stmt = SSA_NAME_DEF_STMT (arg3);
15057 : 260 : if (is_gimple_call (def_stmt))
15058 : : {
15059 : 79 : tree fndecl = gimple_call_fndecl (def_stmt);
15060 : 79 : if (fndecl
15061 : 79 : && fndecl_built_in_p (fndecl, BUILT_IN_MD))
15062 : 67 : switch (DECL_MD_FUNCTION_CODE (fndecl))
15063 : : {
15064 : 24 : case IX86_BUILTIN_CMPPD:
15065 : 24 : case IX86_BUILTIN_CMPPS:
15066 : 24 : case IX86_BUILTIN_CMPPD256:
15067 : 24 : case IX86_BUILTIN_CMPPS256:
15068 : 24 : if (!integer_zerop (gimple_call_arg (def_stmt, 2)))
15069 : : break;
15070 : : /* FALLTHRU */
15071 : 49 : case IX86_BUILTIN_CMPEQPD:
15072 : 49 : case IX86_BUILTIN_CMPEQPS:
15073 : 49 : if (initializer_zerop (gimple_call_arg (def_stmt, 0))
15074 : 49 : && initializer_zerop (gimple_call_arg (def_stmt,
15075 : : 1)))
15076 : 49 : op0 = pc_rtx;
15077 : : break;
15078 : : default:
15079 : : break;
15080 : : }
15081 : : }
15082 : : }
15083 : : }
15084 : :
15085 : 1011 : pat = GEN_FCN (icode) (subtarget, op0, op1, op2, op3, op4);
15086 : 1011 : if (! pat)
15087 : 0 : return const0_rtx;
15088 : 1011 : emit_insn (pat);
15089 : :
15090 : 1011 : switch (fcode)
15091 : : {
15092 : 24 : case IX86_BUILTIN_GATHER3DIV16SF:
15093 : 24 : if (target == NULL_RTX)
15094 : 0 : target = gen_reg_rtx (V8SFmode);
15095 : 24 : emit_insn (gen_vec_extract_lo_v16sf (target, subtarget));
15096 : 24 : break;
15097 : 24 : case IX86_BUILTIN_GATHER3DIV16SI:
15098 : 24 : if (target == NULL_RTX)
15099 : 0 : target = gen_reg_rtx (V8SImode);
15100 : 24 : emit_insn (gen_vec_extract_lo_v16si (target, subtarget));
15101 : 24 : break;
15102 : 28 : case IX86_BUILTIN_GATHER3DIV8SF:
15103 : 28 : case IX86_BUILTIN_GATHERDIV8SF:
15104 : 28 : if (target == NULL_RTX)
15105 : 0 : target = gen_reg_rtx (V4SFmode);
15106 : 28 : emit_insn (gen_vec_extract_lo_v8sf (target, subtarget));
15107 : 28 : break;
15108 : 28 : case IX86_BUILTIN_GATHER3DIV8SI:
15109 : 28 : case IX86_BUILTIN_GATHERDIV8SI:
15110 : 28 : if (target == NULL_RTX)
15111 : 0 : target = gen_reg_rtx (V4SImode);
15112 : 28 : emit_insn (gen_vec_extract_lo_v8si (target, subtarget));
15113 : 28 : break;
15114 : : default:
15115 : : target = subtarget;
15116 : : break;
15117 : : }
15118 : : return target;
15119 : :
15120 : 649 : scatter_gen:
15121 : 649 : arg0 = CALL_EXPR_ARG (exp, 0);
15122 : 649 : arg1 = CALL_EXPR_ARG (exp, 1);
15123 : 649 : arg2 = CALL_EXPR_ARG (exp, 2);
15124 : 649 : arg3 = CALL_EXPR_ARG (exp, 3);
15125 : 649 : arg4 = CALL_EXPR_ARG (exp, 4);
15126 : 649 : op0 = expand_normal (arg0);
15127 : 649 : op1 = expand_normal (arg1);
15128 : 649 : op2 = expand_normal (arg2);
15129 : 649 : op3 = expand_normal (arg3);
15130 : 649 : op4 = expand_normal (arg4);
15131 : 649 : mode1 = insn_data[icode].operand[1].mode;
15132 : 649 : mode2 = insn_data[icode].operand[2].mode;
15133 : 649 : mode3 = insn_data[icode].operand[3].mode;
15134 : 649 : mode4 = insn_data[icode].operand[4].mode;
15135 : :
15136 : : /* Scatter instruction stores operand op3 to memory with
15137 : : indices from op2 and scale from op4 under writemask op1.
15138 : : If index operand op2 has more elements then source operand
15139 : : op3 one need to use only its low half. And vice versa. */
15140 : 649 : switch (fcode)
15141 : : {
15142 : 24 : case IX86_BUILTIN_SCATTERALTSIV8DF:
15143 : 24 : case IX86_BUILTIN_SCATTERALTSIV8DI:
15144 : 24 : half = gen_reg_rtx (V8SImode);
15145 : 24 : if (!nonimmediate_operand (op2, V16SImode))
15146 : 0 : op2 = copy_to_mode_reg (V16SImode, op2);
15147 : 24 : emit_insn (gen_vec_extract_lo_v16si (half, op2));
15148 : 24 : op2 = half;
15149 : 24 : break;
15150 : 36 : case IX86_BUILTIN_SCATTERALTDIV16SF:
15151 : 36 : case IX86_BUILTIN_SCATTERALTDIV16SI:
15152 : 36 : half = gen_reg_rtx (mode3);
15153 : 36 : if (mode3 == V8SFmode)
15154 : : gen = gen_vec_extract_lo_v16sf;
15155 : : else
15156 : 24 : gen = gen_vec_extract_lo_v16si;
15157 : 36 : if (!nonimmediate_operand (op3, GET_MODE (op3)))
15158 : 0 : op3 = copy_to_mode_reg (GET_MODE (op3), op3);
15159 : 36 : emit_insn (gen (half, op3));
15160 : 36 : op3 = half;
15161 : 36 : break;
15162 : 8 : case IX86_BUILTIN_SCATTERALTSIV4DF:
15163 : 8 : case IX86_BUILTIN_SCATTERALTSIV4DI:
15164 : 8 : half = gen_reg_rtx (V4SImode);
15165 : 8 : if (!nonimmediate_operand (op2, V8SImode))
15166 : 0 : op2 = copy_to_mode_reg (V8SImode, op2);
15167 : 8 : emit_insn (gen_vec_extract_lo_v8si (half, op2));
15168 : 8 : op2 = half;
15169 : 8 : break;
15170 : 8 : case IX86_BUILTIN_SCATTERALTDIV8SF:
15171 : 8 : case IX86_BUILTIN_SCATTERALTDIV8SI:
15172 : 8 : half = gen_reg_rtx (mode3);
15173 : 8 : if (mode3 == V4SFmode)
15174 : : gen = gen_vec_extract_lo_v8sf;
15175 : : else
15176 : 4 : gen = gen_vec_extract_lo_v8si;
15177 : 8 : if (!nonimmediate_operand (op3, GET_MODE (op3)))
15178 : 0 : op3 = copy_to_mode_reg (GET_MODE (op3), op3);
15179 : 8 : emit_insn (gen (half, op3));
15180 : 8 : op3 = half;
15181 : 8 : break;
15182 : 16 : case IX86_BUILTIN_SCATTERALTSIV2DF:
15183 : 16 : case IX86_BUILTIN_SCATTERALTSIV2DI:
15184 : 16 : if (!nonimmediate_operand (op2, V4SImode))
15185 : 0 : op2 = copy_to_mode_reg (V4SImode, op2);
15186 : : break;
15187 : 16 : case IX86_BUILTIN_SCATTERALTDIV4SF:
15188 : 16 : case IX86_BUILTIN_SCATTERALTDIV4SI:
15189 : 16 : if (!nonimmediate_operand (op3, GET_MODE (op3)))
15190 : 0 : op3 = copy_to_mode_reg (GET_MODE (op3), op3);
15191 : : break;
15192 : : default:
15193 : : break;
15194 : : }
15195 : :
15196 : : /* Force memory operand only with base register here. But we
15197 : : don't want to do it on memory operand for other builtin
15198 : : functions. */
15199 : 649 : op0 = force_reg (Pmode, convert_to_mode (Pmode, op0, 1));
15200 : :
15201 : 649 : if (!insn_data[icode].operand[0].predicate (op0, Pmode))
15202 : 0 : op0 = copy_to_mode_reg (Pmode, op0);
15203 : :
15204 : 649 : op1 = fixup_modeless_constant (op1, mode1);
15205 : :
15206 : 649 : if (GET_MODE (op1) == mode1 || GET_MODE (op1) == VOIDmode)
15207 : : {
15208 : 391 : if (!insn_data[icode].operand[1].predicate (op1, mode1))
15209 : 293 : op1 = copy_to_mode_reg (mode1, op1);
15210 : : }
15211 : : else
15212 : : {
15213 : 258 : op1 = copy_to_reg (op1);
15214 : 258 : op1 = lowpart_subreg (mode1, op1, GET_MODE (op1));
15215 : : }
15216 : :
15217 : 649 : if (!insn_data[icode].operand[2].predicate (op2, mode2))
15218 : 57 : op2 = copy_to_mode_reg (mode2, op2);
15219 : :
15220 : 649 : if (!insn_data[icode].operand[3].predicate (op3, mode3))
15221 : 98 : op3 = copy_to_mode_reg (mode3, op3);
15222 : :
15223 : 649 : if (!insn_data[icode].operand[4].predicate (op4, mode4))
15224 : : {
15225 : 0 : error ("the last argument must be scale 1, 2, 4, 8");
15226 : 0 : return const0_rtx;
15227 : : }
15228 : :
15229 : 649 : pat = GEN_FCN (icode) (op0, op1, op2, op3, op4);
15230 : 649 : if (! pat)
15231 : 0 : return const0_rtx;
15232 : :
15233 : 649 : emit_insn (pat);
15234 : 649 : return 0;
15235 : :
15236 : 180 : vec_prefetch_gen:
15237 : 180 : arg0 = CALL_EXPR_ARG (exp, 0);
15238 : 180 : arg1 = CALL_EXPR_ARG (exp, 1);
15239 : 180 : arg2 = CALL_EXPR_ARG (exp, 2);
15240 : 180 : arg3 = CALL_EXPR_ARG (exp, 3);
15241 : 180 : arg4 = CALL_EXPR_ARG (exp, 4);
15242 : 180 : op0 = expand_normal (arg0);
15243 : 180 : op1 = expand_normal (arg1);
15244 : 180 : op2 = expand_normal (arg2);
15245 : 180 : op3 = expand_normal (arg3);
15246 : 180 : op4 = expand_normal (arg4);
15247 : 180 : mode0 = insn_data[icode].operand[0].mode;
15248 : 180 : mode1 = insn_data[icode].operand[1].mode;
15249 : 180 : mode3 = insn_data[icode].operand[3].mode;
15250 : 180 : mode4 = insn_data[icode].operand[4].mode;
15251 : :
15252 : 180 : op0 = fixup_modeless_constant (op0, mode0);
15253 : :
15254 : 180 : if (GET_MODE (op0) == mode0 || GET_MODE (op0) == VOIDmode)
15255 : : {
15256 : 90 : if (!insn_data[icode].operand[0].predicate (op0, mode0))
15257 : 90 : op0 = copy_to_mode_reg (mode0, op0);
15258 : : }
15259 : : else
15260 : : {
15261 : 90 : op0 = copy_to_reg (op0);
15262 : 90 : op0 = lowpart_subreg (mode0, op0, GET_MODE (op0));
15263 : : }
15264 : :
15265 : 180 : if (!insn_data[icode].operand[1].predicate (op1, mode1))
15266 : 24 : op1 = copy_to_mode_reg (mode1, op1);
15267 : :
15268 : : /* Force memory operand only with base register here. But we
15269 : : don't want to do it on memory operand for other builtin
15270 : : functions. */
15271 : 180 : op2 = force_reg (Pmode, convert_to_mode (Pmode, op2, 1));
15272 : :
15273 : 180 : if (!insn_data[icode].operand[2].predicate (op2, Pmode))
15274 : 0 : op2 = copy_to_mode_reg (Pmode, op2);
15275 : :
15276 : 180 : if (!insn_data[icode].operand[3].predicate (op3, mode3))
15277 : : {
15278 : 0 : error ("the forth argument must be scale 1, 2, 4, 8");
15279 : 0 : return const0_rtx;
15280 : : }
15281 : :
15282 : 180 : if (!insn_data[icode].operand[4].predicate (op4, mode4))
15283 : : {
15284 : 0 : error ("incorrect hint operand");
15285 : 0 : return const0_rtx;
15286 : : }
15287 : :
15288 : 180 : pat = GEN_FCN (icode) (op0, op1, op2, op3, op4);
15289 : 180 : if (! pat)
15290 : 0 : return const0_rtx;
15291 : :
15292 : 180 : emit_insn (pat);
15293 : :
15294 : 180 : return 0;
15295 : :
15296 : 23 : case IX86_BUILTIN_XABORT:
15297 : 23 : icode = CODE_FOR_xabort;
15298 : 23 : arg0 = CALL_EXPR_ARG (exp, 0);
15299 : 23 : op0 = expand_normal (arg0);
15300 : 23 : mode0 = insn_data[icode].operand[0].mode;
15301 : 23 : if (!insn_data[icode].operand[0].predicate (op0, mode0))
15302 : : {
15303 : 0 : error ("the argument to %<xabort%> intrinsic must "
15304 : : "be an 8-bit immediate");
15305 : 0 : return const0_rtx;
15306 : : }
15307 : 23 : emit_insn (gen_xabort (op0));
15308 : 23 : return 0;
15309 : :
15310 : 55 : case IX86_BUILTIN_RDSSPD:
15311 : 55 : case IX86_BUILTIN_RDSSPQ:
15312 : 55 : mode = (fcode == IX86_BUILTIN_RDSSPD ? SImode : DImode);
15313 : :
15314 : 55 : if (target == 0
15315 : 55 : || !register_operand (target, mode))
15316 : 0 : target = gen_reg_rtx (mode);
15317 : :
15318 : 55 : op0 = force_reg (mode, const0_rtx);
15319 : :
15320 : 55 : emit_insn (gen_rdssp (mode, target, op0));
15321 : 55 : return target;
15322 : :
15323 : 55 : case IX86_BUILTIN_INCSSPD:
15324 : 55 : case IX86_BUILTIN_INCSSPQ:
15325 : 55 : mode = (fcode == IX86_BUILTIN_INCSSPD ? SImode : DImode);
15326 : :
15327 : 55 : arg0 = CALL_EXPR_ARG (exp, 0);
15328 : 55 : op0 = expand_normal (arg0);
15329 : :
15330 : 55 : op0 = force_reg (mode, op0);
15331 : :
15332 : 55 : emit_insn (gen_incssp (mode, op0));
15333 : 55 : return 0;
15334 : :
15335 : 20 : case IX86_BUILTIN_HRESET:
15336 : 20 : icode = CODE_FOR_hreset;
15337 : 20 : arg0 = CALL_EXPR_ARG (exp, 0);
15338 : 20 : op0 = expand_normal (arg0);
15339 : 20 : op0 = force_reg (SImode, op0);
15340 : 20 : emit_insn (gen_hreset (op0));
15341 : 20 : return 0;
15342 : :
15343 : 38 : case IX86_BUILTIN_RSTORSSP:
15344 : 38 : case IX86_BUILTIN_CLRSSBSY:
15345 : 38 : arg0 = CALL_EXPR_ARG (exp, 0);
15346 : 38 : op0 = expand_normal (arg0);
15347 : 76 : icode = (fcode == IX86_BUILTIN_RSTORSSP
15348 : 38 : ? CODE_FOR_rstorssp
15349 : : : CODE_FOR_clrssbsy);
15350 : :
15351 : 38 : if (!address_operand (op0, VOIDmode))
15352 : : {
15353 : 18 : op0 = convert_memory_address (Pmode, op0);
15354 : 18 : op0 = copy_addr_to_reg (op0);
15355 : : }
15356 : 38 : emit_insn (GEN_FCN (icode) (gen_rtx_MEM (DImode, op0)));
15357 : 38 : return 0;
15358 : :
15359 : 76 : case IX86_BUILTIN_WRSSD:
15360 : 76 : case IX86_BUILTIN_WRSSQ:
15361 : 76 : case IX86_BUILTIN_WRUSSD:
15362 : 76 : case IX86_BUILTIN_WRUSSQ:
15363 : 76 : mode = ((fcode == IX86_BUILTIN_WRSSD
15364 : 76 : || fcode == IX86_BUILTIN_WRUSSD)
15365 : 76 : ? SImode : DImode);
15366 : :
15367 : 76 : arg0 = CALL_EXPR_ARG (exp, 0);
15368 : 76 : op0 = expand_normal (arg0);
15369 : 76 : arg1 = CALL_EXPR_ARG (exp, 1);
15370 : 76 : op1 = expand_normal (arg1);
15371 : :
15372 : 76 : op0 = force_reg (mode, op0);
15373 : :
15374 : 76 : if (!address_operand (op1, VOIDmode))
15375 : : {
15376 : 36 : op1 = convert_memory_address (Pmode, op1);
15377 : 36 : op1 = copy_addr_to_reg (op1);
15378 : : }
15379 : 76 : op1 = gen_rtx_MEM (mode, op1);
15380 : :
15381 : 152 : icode = ((fcode == IX86_BUILTIN_WRSSD
15382 : 76 : || fcode == IX86_BUILTIN_WRSSQ)
15383 : 76 : ? code_for_wrss (mode)
15384 : 38 : : code_for_wruss (mode));
15385 : 76 : emit_insn (GEN_FCN (icode) (op0, op1));
15386 : :
15387 : 76 : return 0;
15388 : :
15389 : 105869 : default:
15390 : 105869 : break;
15391 : : }
15392 : :
15393 : 105869 : if (fcode >= IX86_BUILTIN__BDESC_SPECIAL_ARGS_FIRST
15394 : 105869 : && fcode <= IX86_BUILTIN__BDESC_SPECIAL_ARGS_LAST)
15395 : : {
15396 : 26878 : i = fcode - IX86_BUILTIN__BDESC_SPECIAL_ARGS_FIRST;
15397 : 26878 : return ix86_expand_special_args_builtin (bdesc_special_args + i, exp,
15398 : 26878 : target);
15399 : : }
15400 : :
15401 : 78991 : if (fcode >= IX86_BUILTIN__BDESC_PURE_ARGS_FIRST
15402 : 78991 : && fcode <= IX86_BUILTIN__BDESC_PURE_ARGS_LAST)
15403 : : {
15404 : 93 : i = fcode - IX86_BUILTIN__BDESC_PURE_ARGS_FIRST;
15405 : 93 : return ix86_expand_special_args_builtin (bdesc_pure_args + i, exp,
15406 : 93 : target);
15407 : : }
15408 : :
15409 : 78898 : if (fcode >= IX86_BUILTIN__BDESC_ARGS_FIRST
15410 : 78898 : && fcode <= IX86_BUILTIN__BDESC_ARGS_LAST)
15411 : : {
15412 : 61563 : i = fcode - IX86_BUILTIN__BDESC_ARGS_FIRST;
15413 : 61563 : rtx (*fcn) (rtx, rtx, rtx, rtx) = NULL;
15414 : 61563 : rtx (*fcn_mask) (rtx, rtx, rtx, rtx, rtx);
15415 : 61563 : rtx (*fcn_maskz) (rtx, rtx, rtx, rtx, rtx, rtx);
15416 : 61563 : int masked = 1;
15417 : 61563 : machine_mode mode, wide_mode, nar_mode;
15418 : :
15419 : 61563 : nar_mode = V4SFmode;
15420 : 61563 : mode = V16SFmode;
15421 : 61563 : wide_mode = V64SFmode;
15422 : 61563 : fcn_mask = gen_avx5124fmaddps_4fmaddps_mask;
15423 : 61563 : fcn_maskz = gen_avx5124fmaddps_4fmaddps_maskz;
15424 : :
15425 : 61563 : switch (fcode)
15426 : : {
15427 : 11 : case IX86_BUILTIN_4FMAPS:
15428 : 11 : fcn = gen_avx5124fmaddps_4fmaddps;
15429 : 11 : masked = 0;
15430 : 11 : goto v4fma_expand;
15431 : :
15432 : 13 : case IX86_BUILTIN_4DPWSSD:
15433 : 13 : nar_mode = V4SImode;
15434 : 13 : mode = V16SImode;
15435 : 13 : wide_mode = V64SImode;
15436 : 13 : fcn = gen_avx5124vnniw_vp4dpwssd;
15437 : 13 : masked = 0;
15438 : 13 : goto v4fma_expand;
15439 : :
15440 : 11 : case IX86_BUILTIN_4DPWSSDS:
15441 : 11 : nar_mode = V4SImode;
15442 : 11 : mode = V16SImode;
15443 : 11 : wide_mode = V64SImode;
15444 : 11 : fcn = gen_avx5124vnniw_vp4dpwssds;
15445 : 11 : masked = 0;
15446 : 11 : goto v4fma_expand;
15447 : :
15448 : 11 : case IX86_BUILTIN_4FNMAPS:
15449 : 11 : fcn = gen_avx5124fmaddps_4fnmaddps;
15450 : 11 : masked = 0;
15451 : 11 : goto v4fma_expand;
15452 : :
15453 : 22 : case IX86_BUILTIN_4FNMAPS_MASK:
15454 : 22 : fcn_mask = gen_avx5124fmaddps_4fnmaddps_mask;
15455 : 22 : fcn_maskz = gen_avx5124fmaddps_4fnmaddps_maskz;
15456 : 22 : goto v4fma_expand;
15457 : :
15458 : 22 : case IX86_BUILTIN_4DPWSSD_MASK:
15459 : 22 : nar_mode = V4SImode;
15460 : 22 : mode = V16SImode;
15461 : 22 : wide_mode = V64SImode;
15462 : 22 : fcn_mask = gen_avx5124vnniw_vp4dpwssd_mask;
15463 : 22 : fcn_maskz = gen_avx5124vnniw_vp4dpwssd_maskz;
15464 : 22 : goto v4fma_expand;
15465 : :
15466 : 22 : case IX86_BUILTIN_4DPWSSDS_MASK:
15467 : 22 : nar_mode = V4SImode;
15468 : 22 : mode = V16SImode;
15469 : 22 : wide_mode = V64SImode;
15470 : 22 : fcn_mask = gen_avx5124vnniw_vp4dpwssds_mask;
15471 : 22 : fcn_maskz = gen_avx5124vnniw_vp4dpwssds_maskz;
15472 : 22 : goto v4fma_expand;
15473 : :
15474 : 135 : case IX86_BUILTIN_4FMAPS_MASK:
15475 : 135 : {
15476 : 135 : tree args[4];
15477 : 135 : rtx ops[4];
15478 : 135 : rtx wide_reg;
15479 : 135 : rtx accum;
15480 : 135 : rtx addr;
15481 : 135 : rtx mem;
15482 : :
15483 : 135 : v4fma_expand:
15484 : 135 : wide_reg = gen_reg_rtx (wide_mode);
15485 : 810 : for (i = 0; i < 4; i++)
15486 : : {
15487 : 540 : args[i] = CALL_EXPR_ARG (exp, i);
15488 : 540 : ops[i] = expand_normal (args[i]);
15489 : :
15490 : 540 : emit_move_insn (gen_rtx_SUBREG (mode, wide_reg, i * 64),
15491 : : ops[i]);
15492 : : }
15493 : :
15494 : 135 : accum = expand_normal (CALL_EXPR_ARG (exp, 4));
15495 : 135 : accum = force_reg (mode, accum);
15496 : :
15497 : 135 : addr = expand_normal (CALL_EXPR_ARG (exp, 5));
15498 : 135 : addr = force_reg (Pmode, addr);
15499 : :
15500 : 135 : mem = gen_rtx_MEM (nar_mode, addr);
15501 : :
15502 : 135 : target = gen_reg_rtx (mode);
15503 : :
15504 : 135 : emit_move_insn (target, accum);
15505 : :
15506 : 135 : if (! masked)
15507 : 46 : emit_insn (fcn (target, accum, wide_reg, mem));
15508 : : else
15509 : : {
15510 : 89 : rtx merge, mask;
15511 : 89 : merge = expand_normal (CALL_EXPR_ARG (exp, 6));
15512 : :
15513 : 89 : mask = expand_normal (CALL_EXPR_ARG (exp, 7));
15514 : :
15515 : 89 : if (CONST_INT_P (mask))
15516 : 1 : mask = fixup_modeless_constant (mask, HImode);
15517 : :
15518 : 89 : mask = force_reg (HImode, mask);
15519 : :
15520 : 89 : if (GET_MODE (mask) != HImode)
15521 : 88 : mask = gen_rtx_SUBREG (HImode, mask, 0);
15522 : :
15523 : : /* If merge is 0 then we're about to emit z-masked variant. */
15524 : 89 : if (const0_operand (merge, mode))
15525 : 28 : emit_insn (fcn_maskz (target, accum, wide_reg, mem, merge, mask));
15526 : : /* If merge is the same as accum then emit merge-masked variant. */
15527 : 61 : else if (CALL_EXPR_ARG (exp, 6) == CALL_EXPR_ARG (exp, 4))
15528 : : {
15529 : 36 : merge = force_reg (mode, merge);
15530 : 36 : emit_insn (fcn_mask (target, wide_reg, mem, merge, mask));
15531 : : }
15532 : : /* Merge with something unknown might happen if we z-mask w/ -O0. */
15533 : : else
15534 : : {
15535 : 25 : target = gen_reg_rtx (mode);
15536 : 25 : emit_move_insn (target, merge);
15537 : 25 : emit_insn (fcn_mask (target, wide_reg, mem, target, mask));
15538 : : }
15539 : : }
15540 : 135 : return target;
15541 : : }
15542 : :
15543 : 11 : case IX86_BUILTIN_4FNMASS:
15544 : 11 : fcn = gen_avx5124fmaddps_4fnmaddss;
15545 : 11 : masked = 0;
15546 : 11 : goto s4fma_expand;
15547 : :
15548 : 11 : case IX86_BUILTIN_4FMASS:
15549 : 11 : fcn = gen_avx5124fmaddps_4fmaddss;
15550 : 11 : masked = 0;
15551 : 11 : goto s4fma_expand;
15552 : :
15553 : 22 : case IX86_BUILTIN_4FNMASS_MASK:
15554 : 22 : fcn_mask = gen_avx5124fmaddps_4fnmaddss_mask;
15555 : 22 : fcn_maskz = gen_avx5124fmaddps_4fnmaddss_maskz;
15556 : 22 : goto s4fma_expand;
15557 : :
15558 : : case IX86_BUILTIN_4FMASS_MASK:
15559 : : {
15560 : : tree args[4];
15561 : : rtx ops[4];
15562 : : rtx wide_reg;
15563 : : rtx accum;
15564 : : rtx addr;
15565 : : rtx mem;
15566 : :
15567 : : fcn_mask = gen_avx5124fmaddps_4fmaddss_mask;
15568 : : fcn_maskz = gen_avx5124fmaddps_4fmaddss_maskz;
15569 : :
15570 : 66 : s4fma_expand:
15571 : 66 : mode = V4SFmode;
15572 : 66 : wide_reg = gen_reg_rtx (V64SFmode);
15573 : 330 : for (i = 0; i < 4; i++)
15574 : : {
15575 : 264 : rtx tmp;
15576 : 264 : args[i] = CALL_EXPR_ARG (exp, i);
15577 : 264 : ops[i] = expand_normal (args[i]);
15578 : :
15579 : 264 : tmp = gen_reg_rtx (SFmode);
15580 : 264 : emit_move_insn (tmp, gen_rtx_SUBREG (SFmode, ops[i], 0));
15581 : :
15582 : 264 : emit_move_insn (gen_rtx_SUBREG (V16SFmode, wide_reg, i * 64),
15583 : 264 : gen_rtx_SUBREG (V16SFmode, tmp, 0));
15584 : : }
15585 : :
15586 : 66 : accum = expand_normal (CALL_EXPR_ARG (exp, 4));
15587 : 66 : accum = force_reg (V4SFmode, accum);
15588 : :
15589 : 66 : addr = expand_normal (CALL_EXPR_ARG (exp, 5));
15590 : 66 : addr = force_reg (Pmode, addr);
15591 : :
15592 : 66 : mem = gen_rtx_MEM (V4SFmode, addr);
15593 : :
15594 : 66 : target = gen_reg_rtx (V4SFmode);
15595 : :
15596 : 66 : emit_move_insn (target, accum);
15597 : :
15598 : 66 : if (! masked)
15599 : 22 : emit_insn (fcn (target, accum, wide_reg, mem));
15600 : : else
15601 : : {
15602 : 44 : rtx merge, mask;
15603 : 44 : merge = expand_normal (CALL_EXPR_ARG (exp, 6));
15604 : :
15605 : 44 : mask = expand_normal (CALL_EXPR_ARG (exp, 7));
15606 : :
15607 : 44 : if (CONST_INT_P (mask))
15608 : 0 : mask = fixup_modeless_constant (mask, QImode);
15609 : :
15610 : 44 : mask = force_reg (QImode, mask);
15611 : :
15612 : 44 : if (GET_MODE (mask) != QImode)
15613 : 44 : mask = gen_rtx_SUBREG (QImode, mask, 0);
15614 : :
15615 : : /* If merge is 0 then we're about to emit z-masked variant. */
15616 : 44 : if (const0_operand (merge, mode))
15617 : 14 : emit_insn (fcn_maskz (target, accum, wide_reg, mem, merge, mask));
15618 : : /* If merge is the same as accum then emit merge-masked
15619 : : variant. */
15620 : 30 : else if (CALL_EXPR_ARG (exp, 6) == CALL_EXPR_ARG (exp, 4))
15621 : : {
15622 : 22 : merge = force_reg (mode, merge);
15623 : 22 : emit_insn (fcn_mask (target, wide_reg, mem, merge, mask));
15624 : : }
15625 : : /* Merge with something unknown might happen if we z-mask
15626 : : w/ -O0. */
15627 : : else
15628 : : {
15629 : 8 : target = gen_reg_rtx (mode);
15630 : 8 : emit_move_insn (target, merge);
15631 : 8 : emit_insn (fcn_mask (target, wide_reg, mem, target, mask));
15632 : : }
15633 : : }
15634 : 66 : return target;
15635 : : }
15636 : 0 : case IX86_BUILTIN_RDPID:
15637 : 0 : return ix86_expand_special_args_builtin (bdesc_args + i, exp,
15638 : 0 : target);
15639 : 9 : case IX86_BUILTIN_FABSQ:
15640 : 9 : case IX86_BUILTIN_COPYSIGNQ:
15641 : 9 : if (!TARGET_SSE)
15642 : : /* Emit a normal call if SSE isn't available. */
15643 : 0 : return expand_call (exp, target, ignore);
15644 : : /* FALLTHRU */
15645 : 61362 : default:
15646 : 61362 : return ix86_expand_args_builtin (bdesc_args + i, exp, target);
15647 : : }
15648 : : }
15649 : :
15650 : 17335 : if (fcode >= IX86_BUILTIN__BDESC_COMI_FIRST
15651 : 17335 : && fcode <= IX86_BUILTIN__BDESC_COMI_LAST)
15652 : : {
15653 : 473 : i = fcode - IX86_BUILTIN__BDESC_COMI_FIRST;
15654 : 473 : return ix86_expand_sse_comi (bdesc_comi + i, exp, target);
15655 : : }
15656 : :
15657 : 16862 : if (fcode >= IX86_BUILTIN__BDESC_ROUND_ARGS_FIRST
15658 : 16862 : && fcode <= IX86_BUILTIN__BDESC_ROUND_ARGS_LAST)
15659 : : {
15660 : 14540 : i = fcode - IX86_BUILTIN__BDESC_ROUND_ARGS_FIRST;
15661 : 14540 : return ix86_expand_round_builtin (bdesc_round_args + i, exp, target);
15662 : : }
15663 : :
15664 : 2322 : if (fcode >= IX86_BUILTIN__BDESC_PCMPESTR_FIRST
15665 : 2322 : && fcode <= IX86_BUILTIN__BDESC_PCMPESTR_LAST)
15666 : : {
15667 : 216 : i = fcode - IX86_BUILTIN__BDESC_PCMPESTR_FIRST;
15668 : 216 : return ix86_expand_sse_pcmpestr (bdesc_pcmpestr + i, exp, target);
15669 : : }
15670 : :
15671 : 2106 : if (fcode >= IX86_BUILTIN__BDESC_PCMPISTR_FIRST
15672 : 2106 : && fcode <= IX86_BUILTIN__BDESC_PCMPISTR_LAST)
15673 : : {
15674 : 275 : i = fcode - IX86_BUILTIN__BDESC_PCMPISTR_FIRST;
15675 : 275 : return ix86_expand_sse_pcmpistr (bdesc_pcmpistr + i, exp, target);
15676 : : }
15677 : :
15678 : 1831 : if (fcode >= IX86_BUILTIN__BDESC_MULTI_ARG_FIRST
15679 : 1831 : && fcode <= IX86_BUILTIN__BDESC_MULTI_ARG_LAST)
15680 : : {
15681 : 1793 : i = fcode - IX86_BUILTIN__BDESC_MULTI_ARG_FIRST;
15682 : 1793 : const struct builtin_description *d = bdesc_multi_arg + i;
15683 : 1793 : return ix86_expand_multi_arg_builtin (d->icode, exp, target,
15684 : : (enum ix86_builtin_func_type)
15685 : 1793 : d->flag, d->comparison);
15686 : : }
15687 : :
15688 : 38 : if (fcode >= IX86_BUILTIN__BDESC_CET_FIRST
15689 : 38 : && fcode <= IX86_BUILTIN__BDESC_CET_LAST)
15690 : : {
15691 : 38 : i = fcode - IX86_BUILTIN__BDESC_CET_FIRST;
15692 : 38 : return ix86_expand_special_args_builtin (bdesc_cet + i, exp,
15693 : 38 : target);
15694 : : }
15695 : :
15696 : 0 : gcc_unreachable ();
15697 : : }
15698 : :
15699 : : /* A subroutine of ix86_expand_vector_init_duplicate. Tries to
15700 : : fill target with val via vec_duplicate. */
15701 : :
15702 : : static bool
15703 : 133632 : ix86_vector_duplicate_value (machine_mode mode, rtx target, rtx val)
15704 : : {
15705 : 133632 : bool ok;
15706 : 133632 : rtx_insn *insn;
15707 : 133632 : rtx dup;
15708 : : /* Save/restore recog_data in case this is called from splitters
15709 : : or other routines where recog_data needs to stay valid across
15710 : : force_reg. See PR106577. */
15711 : 133632 : recog_data_d recog_data_save = recog_data;
15712 : :
15713 : : /* First attempt to recognize VAL as-is. */
15714 : 133632 : dup = gen_vec_duplicate (mode, val);
15715 : 133632 : insn = emit_insn (gen_rtx_SET (target, dup));
15716 : 133632 : if (recog_memoized (insn) < 0)
15717 : : {
15718 : 96514 : rtx_insn *seq;
15719 : 96514 : machine_mode innermode = GET_MODE_INNER (mode);
15720 : 96514 : rtx reg;
15721 : :
15722 : : /* If that fails, force VAL into a register. */
15723 : :
15724 : 96514 : start_sequence ();
15725 : 96514 : reg = force_reg (innermode, val);
15726 : 96514 : if (GET_MODE (reg) != innermode)
15727 : 0 : reg = gen_lowpart (innermode, reg);
15728 : 96514 : SET_SRC (PATTERN (insn)) = gen_vec_duplicate (mode, reg);
15729 : 96514 : seq = get_insns ();
15730 : 96514 : end_sequence ();
15731 : 96514 : if (seq)
15732 : 96514 : emit_insn_before (seq, insn);
15733 : :
15734 : 96514 : ok = recog_memoized (insn) >= 0;
15735 : 96514 : gcc_assert (ok);
15736 : : }
15737 : 133632 : recog_data = recog_data_save;
15738 : 133632 : return true;
15739 : : }
15740 : :
15741 : : /* Get a vector mode of the same size as the original but with elements
15742 : : twice as wide. This is only guaranteed to apply to integral vectors. */
15743 : :
15744 : : static machine_mode
15745 : 13767 : get_mode_wider_vector (machine_mode o)
15746 : : {
15747 : : /* ??? Rely on the ordering that genmodes.cc gives to vectors. */
15748 : 13767 : machine_mode n = GET_MODE_NEXT_MODE (o).require ();
15749 : 41301 : gcc_assert (GET_MODE_NUNITS (o) == GET_MODE_NUNITS (n) * 2);
15750 : 41301 : gcc_assert (GET_MODE_SIZE (o) == GET_MODE_SIZE (n));
15751 : 13767 : return n;
15752 : : }
15753 : :
15754 : : static bool expand_vec_perm_broadcast_1 (struct expand_vec_perm_d *d);
15755 : : static bool expand_vec_perm_1 (struct expand_vec_perm_d *d);
15756 : :
15757 : : /* A subroutine of ix86_expand_vector_init. Store into TARGET a vector
15758 : : with all elements equal to VAR. Return true if successful. */
15759 : :
15760 : : bool
15761 : 150407 : ix86_expand_vector_init_duplicate (bool mmx_ok, machine_mode mode,
15762 : : rtx target, rtx val)
15763 : : {
15764 : 150407 : bool ok;
15765 : :
15766 : 150407 : switch (mode)
15767 : : {
15768 : 74066 : case E_V2DImode:
15769 : 74066 : if (CONST_INT_P (val))
15770 : : {
15771 : 59656 : int tmp = (int)INTVAL (val);
15772 : 59656 : if (tmp == (int)(INTVAL (val) >> 32))
15773 : : {
15774 : 66 : rtx reg = gen_reg_rtx (V4SImode);
15775 : 66 : ok = ix86_vector_duplicate_value (V4SImode, reg,
15776 : : GEN_INT (tmp));
15777 : 66 : if (ok)
15778 : : {
15779 : 66 : emit_move_insn (target, gen_lowpart (V2DImode, reg));
15780 : 66 : return true;
15781 : : }
15782 : : }
15783 : : }
15784 : 74000 : return ix86_vector_duplicate_value (mode, target, val);
15785 : :
15786 : 700 : case E_V4DImode:
15787 : 700 : if (CONST_INT_P (val))
15788 : : {
15789 : 601 : int tmp = (int)INTVAL (val);
15790 : 601 : if (tmp == (int)(INTVAL (val) >> 32))
15791 : : {
15792 : 43 : rtx reg = gen_reg_rtx (V8SImode);
15793 : 43 : ok = ix86_vector_duplicate_value (V8SImode, reg,
15794 : : GEN_INT (tmp));
15795 : 43 : if (ok)
15796 : : {
15797 : 43 : emit_move_insn (target, gen_lowpart (V4DImode, reg));
15798 : 43 : return true;
15799 : : }
15800 : : }
15801 : : }
15802 : 657 : return ix86_vector_duplicate_value (mode, target, val);
15803 : :
15804 : 3858 : case E_V2SImode:
15805 : 3858 : case E_V2SFmode:
15806 : 3858 : if (!mmx_ok)
15807 : : return false;
15808 : : /* FALLTHRU */
15809 : :
15810 : 57776 : case E_V4DFmode:
15811 : 57776 : case E_V8SFmode:
15812 : 57776 : case E_V8SImode:
15813 : 57776 : case E_V2DFmode:
15814 : 57776 : case E_V4SFmode:
15815 : 57776 : case E_V4SImode:
15816 : 57776 : case E_V16SImode:
15817 : 57776 : case E_V8DImode:
15818 : 57776 : case E_V16SFmode:
15819 : 57776 : case E_V8DFmode:
15820 : 57776 : return ix86_vector_duplicate_value (mode, target, val);
15821 : :
15822 : 397 : case E_V4HImode:
15823 : 397 : if (!mmx_ok)
15824 : : return false;
15825 : 388 : if (TARGET_SSE || TARGET_3DNOW_A)
15826 : : {
15827 : 388 : rtx x;
15828 : :
15829 : 388 : val = gen_lowpart (SImode, val);
15830 : 388 : if (CONST_INT_P (val))
15831 : : return false;
15832 : 386 : x = gen_rtx_TRUNCATE (HImode, val);
15833 : 386 : x = gen_rtx_VEC_DUPLICATE (mode, x);
15834 : 386 : emit_insn (gen_rtx_SET (target, x));
15835 : 386 : return true;
15836 : : }
15837 : 0 : goto widen;
15838 : :
15839 : 5 : case E_V4HFmode:
15840 : 5 : case E_V4BFmode:
15841 : 5 : if (TARGET_MMX_WITH_SSE)
15842 : : {
15843 : 10 : val = force_reg (GET_MODE_INNER (mode), val);
15844 : 5 : rtx x = gen_rtx_VEC_DUPLICATE (mode, val);
15845 : 5 : emit_insn (gen_rtx_SET (target, x));
15846 : 5 : return true;
15847 : : }
15848 : : return false;
15849 : :
15850 : 171 : case E_V2HImode:
15851 : 171 : if (TARGET_SSE2)
15852 : : {
15853 : 171 : rtx x;
15854 : :
15855 : 171 : val = gen_lowpart (SImode, val);
15856 : 171 : if (CONST_INT_P (val))
15857 : : return false;
15858 : 171 : x = gen_rtx_TRUNCATE (HImode, val);
15859 : 171 : x = gen_rtx_VEC_DUPLICATE (mode, x);
15860 : 171 : emit_insn (gen_rtx_SET (target, x));
15861 : 171 : return true;
15862 : : }
15863 : : return false;
15864 : :
15865 : 3 : case E_V2HFmode:
15866 : 3 : case E_V2BFmode:
15867 : 3 : if (TARGET_SSE2)
15868 : : {
15869 : 6 : val = force_reg (GET_MODE_INNER (mode), val);
15870 : 3 : rtx x = gen_rtx_VEC_DUPLICATE (mode, val);
15871 : 3 : emit_insn (gen_rtx_SET (target, x));
15872 : 3 : return true;
15873 : : }
15874 : : return false;
15875 : :
15876 : 278 : case E_V8QImode:
15877 : 278 : case E_V4QImode:
15878 : 278 : if (!mmx_ok)
15879 : : return false;
15880 : 277 : goto widen;
15881 : :
15882 : 8193 : case E_V8HImode:
15883 : 8193 : if (CONST_INT_P (val))
15884 : 7816 : goto widen;
15885 : : /* FALLTHRU */
15886 : :
15887 : 656 : case E_V8HFmode:
15888 : 656 : case E_V8BFmode:
15889 : 656 : if (TARGET_AVX2)
15890 : 326 : return ix86_vector_duplicate_value (mode, target, val);
15891 : :
15892 : 330 : if (TARGET_SSE2)
15893 : : {
15894 : 751 : struct expand_vec_perm_d dperm;
15895 : 751 : rtx tmp1, tmp2;
15896 : :
15897 : 330 : permute:
15898 : 751 : memset (&dperm, 0, sizeof (dperm));
15899 : 751 : dperm.target = target;
15900 : 751 : dperm.vmode = mode;
15901 : 751 : dperm.nelt = GET_MODE_NUNITS (mode);
15902 : 751 : dperm.op0 = dperm.op1 = gen_reg_rtx (mode);
15903 : 751 : dperm.one_operand_p = true;
15904 : :
15905 : 751 : if (mode == V8HFmode || mode == V8BFmode)
15906 : : {
15907 : 3 : tmp1 = force_reg (GET_MODE_INNER (mode), val);
15908 : 3 : tmp2 = gen_reg_rtx (mode);
15909 : 3 : emit_insn (gen_vec_set_0 (mode, tmp2, CONST0_RTX (mode), tmp1));
15910 : 3 : tmp1 = gen_lowpart (mode, tmp2);
15911 : : }
15912 : : else
15913 : : {
15914 : : /* Extend to SImode using a paradoxical SUBREG. */
15915 : 748 : tmp1 = gen_reg_rtx (SImode);
15916 : 748 : emit_move_insn (tmp1, gen_lowpart (SImode, val));
15917 : :
15918 : : /* Insert the SImode value as
15919 : : low element of a V4SImode vector. */
15920 : 748 : tmp2 = gen_reg_rtx (V4SImode);
15921 : 748 : emit_insn (gen_vec_setv4si_0 (tmp2, CONST0_RTX (V4SImode), tmp1));
15922 : 748 : tmp1 = gen_lowpart (mode, tmp2);
15923 : : }
15924 : :
15925 : 751 : emit_move_insn (dperm.op0, tmp1);
15926 : 751 : ok = (expand_vec_perm_1 (&dperm)
15927 : 751 : || expand_vec_perm_broadcast_1 (&dperm));
15928 : 0 : gcc_assert (ok);
15929 : 751 : return ok;
15930 : : }
15931 : 0 : goto widen;
15932 : :
15933 : 4222 : case E_V16QImode:
15934 : 4222 : if (CONST_INT_P (val))
15935 : 3743 : goto widen;
15936 : 479 : if (TARGET_AVX2)
15937 : 58 : return ix86_vector_duplicate_value (mode, target, val);
15938 : :
15939 : 421 : if (TARGET_SSE2)
15940 : 421 : goto permute;
15941 : 0 : goto widen;
15942 : :
15943 : 12770 : widen:
15944 : : /* Replicate the value once into the next wider mode and recurse. */
15945 : 12770 : {
15946 : 12770 : machine_mode smode, wsmode, wvmode;
15947 : 12770 : rtx x;
15948 : :
15949 : 12770 : smode = GET_MODE_INNER (mode);
15950 : 12770 : wvmode = get_mode_wider_vector (mode);
15951 : 12770 : wsmode = GET_MODE_INNER (wvmode);
15952 : :
15953 : 12770 : val = convert_modes (wsmode, smode, val, true);
15954 : :
15955 : 12770 : if (CONST_INT_P (val))
15956 : : {
15957 : 24988 : x = simplify_binary_operation (ASHIFT, wsmode, val,
15958 : 12494 : GEN_INT (GET_MODE_BITSIZE (smode)));
15959 : 12494 : val = simplify_binary_operation (IOR, wsmode, val, x);
15960 : : }
15961 : 276 : else if (smode == QImode && !TARGET_PARTIAL_REG_STALL)
15962 : 276 : emit_insn (gen_insv_1 (wsmode, val, val));
15963 : : else
15964 : : {
15965 : 0 : x = expand_simple_binop (wsmode, ASHIFT, val,
15966 : 0 : GEN_INT (GET_MODE_BITSIZE (smode)),
15967 : : NULL_RTX, 1, OPTAB_LIB_WIDEN);
15968 : 0 : val = expand_simple_binop (wsmode, IOR, val, x, x, 1,
15969 : : OPTAB_LIB_WIDEN);
15970 : : }
15971 : :
15972 : 12770 : x = gen_reg_rtx (wvmode);
15973 : 12770 : ok = ix86_expand_vector_init_duplicate (mmx_ok, wvmode, x, val);
15974 : 12770 : if (!ok)
15975 : : return false;
15976 : 12769 : emit_move_insn (target, gen_lowpart (GET_MODE (target), x));
15977 : 12769 : return true;
15978 : : }
15979 : :
15980 : 1141 : case E_V16HImode:
15981 : 1141 : case E_V32QImode:
15982 : 1141 : if (CONST_INT_P (val))
15983 : 934 : goto widen;
15984 : : /* FALLTHRU */
15985 : :
15986 : 248 : case E_V16HFmode:
15987 : 248 : case E_V16BFmode:
15988 : 248 : if (TARGET_AVX2)
15989 : 225 : return ix86_vector_duplicate_value (mode, target, val);
15990 : : else
15991 : : {
15992 : 23 : machine_mode hvmode;
15993 : 23 : switch (mode)
15994 : : {
15995 : : case V16HImode:
15996 : : hvmode = V8HImode;
15997 : : break;
15998 : 0 : case V16HFmode:
15999 : 0 : hvmode = V8HFmode;
16000 : 0 : break;
16001 : 1 : case V16BFmode:
16002 : 1 : hvmode = V8BFmode;
16003 : 1 : break;
16004 : 13 : case V32QImode:
16005 : 13 : hvmode = V16QImode;
16006 : 13 : break;
16007 : 0 : default:
16008 : 0 : gcc_unreachable ();
16009 : : }
16010 : 23 : rtx x = gen_reg_rtx (hvmode);
16011 : :
16012 : 23 : ok = ix86_expand_vector_init_duplicate (false, hvmode, x, val);
16013 : 23 : if (!ok)
16014 : : return false;
16015 : :
16016 : 23 : x = gen_rtx_VEC_CONCAT (mode, x, x);
16017 : 23 : emit_insn (gen_rtx_SET (target, x));
16018 : : }
16019 : 23 : return true;
16020 : :
16021 : 505 : case E_V32HImode:
16022 : 505 : case E_V32HFmode:
16023 : 505 : case E_V32BFmode:
16024 : 505 : case E_V64QImode:
16025 : 505 : gcc_assert (TARGET_EVEX512);
16026 : 505 : if (TARGET_AVX512BW)
16027 : 481 : return ix86_vector_duplicate_value (mode, target, val);
16028 : : else
16029 : : {
16030 : 24 : machine_mode hvmode;
16031 : 24 : switch (mode)
16032 : : {
16033 : : case V32HImode:
16034 : : hvmode = V16HImode;
16035 : : break;
16036 : 0 : case V32HFmode:
16037 : 0 : hvmode = V16HFmode;
16038 : 0 : break;
16039 : 1 : case V32BFmode:
16040 : 1 : hvmode = V16BFmode;
16041 : 1 : break;
16042 : 14 : case V64QImode:
16043 : 14 : hvmode = V32QImode;
16044 : 14 : break;
16045 : 0 : default:
16046 : 0 : gcc_unreachable ();
16047 : : }
16048 : 24 : rtx x = gen_reg_rtx (hvmode);
16049 : :
16050 : 24 : ok = ix86_expand_vector_init_duplicate (false, hvmode, x, val);
16051 : 24 : if (!ok)
16052 : : return false;
16053 : :
16054 : 24 : x = gen_rtx_VEC_CONCAT (mode, x, x);
16055 : 24 : emit_insn (gen_rtx_SET (target, x));
16056 : : }
16057 : 24 : return true;
16058 : :
16059 : : default:
16060 : : return false;
16061 : : }
16062 : : }
16063 : :
16064 : : /* A subroutine of ix86_expand_vector_init. Store into TARGET a vector
16065 : : whose ONE_VAR element is VAR, and other elements are zero. Return true
16066 : : if successful. */
16067 : :
16068 : : static bool
16069 : 1522 : ix86_expand_vector_init_one_nonzero (bool mmx_ok, machine_mode mode,
16070 : : rtx target, rtx var, int one_var)
16071 : : {
16072 : 1522 : machine_mode vsimode;
16073 : 1522 : rtx new_target;
16074 : 1522 : rtx x, tmp;
16075 : 1522 : bool use_vector_set = false;
16076 : 1522 : rtx (*gen_vec_set_0) (rtx, rtx, rtx) = NULL;
16077 : :
16078 : 3044 : if (GET_MODE_SIZE (mode) == 64 && !TARGET_EVEX512)
16079 : : return false;
16080 : :
16081 : 1522 : switch (mode)
16082 : : {
16083 : 391 : case E_V2DImode:
16084 : : /* For SSE4.1, we normally use vector set. But if the second
16085 : : element is zero and inter-unit moves are OK, we use movq
16086 : : instead. */
16087 : 391 : use_vector_set = (TARGET_64BIT && TARGET_SSE4_1
16088 : 391 : && !(TARGET_INTER_UNIT_MOVES_TO_VEC
16089 : : && one_var == 0));
16090 : : break;
16091 : 263 : case E_V16QImode:
16092 : 263 : case E_V4SImode:
16093 : 263 : case E_V4SFmode:
16094 : 263 : use_vector_set = TARGET_SSE4_1;
16095 : 263 : break;
16096 : 74 : case E_V8HImode:
16097 : 74 : use_vector_set = TARGET_SSE2;
16098 : 25 : gen_vec_set_0 = TARGET_AVX512FP16 && one_var == 0
16099 : 74 : ? gen_vec_setv8hi_0 : NULL;
16100 : : break;
16101 : 4 : case E_V8QImode:
16102 : 4 : use_vector_set = TARGET_MMX_WITH_SSE && TARGET_SSE4_1;
16103 : 4 : break;
16104 : 16 : case E_V4HImode:
16105 : 16 : case E_V4HFmode:
16106 : 16 : case E_V4BFmode:
16107 : 16 : use_vector_set = TARGET_SSE || TARGET_3DNOW_A;
16108 : 16 : break;
16109 : 7 : case E_V4QImode:
16110 : 7 : use_vector_set = TARGET_SSE4_1;
16111 : 7 : break;
16112 : 0 : case E_V32QImode:
16113 : 0 : use_vector_set = TARGET_AVX;
16114 : 0 : break;
16115 : 5 : case E_V16HImode:
16116 : 5 : use_vector_set = TARGET_AVX;
16117 : 4 : gen_vec_set_0 = TARGET_AVX512FP16 && one_var == 0
16118 : 5 : ? gen_vec_setv16hi_0 : NULL;
16119 : : break;
16120 : 5 : case E_V8SImode:
16121 : 5 : use_vector_set = TARGET_AVX;
16122 : 5 : gen_vec_set_0 = gen_vec_setv8si_0;
16123 : 5 : break;
16124 : 22 : case E_V8SFmode:
16125 : 22 : use_vector_set = TARGET_AVX;
16126 : 22 : gen_vec_set_0 = gen_vec_setv8sf_0;
16127 : 22 : break;
16128 : 13 : case E_V4DFmode:
16129 : 13 : use_vector_set = TARGET_AVX;
16130 : 13 : gen_vec_set_0 = gen_vec_setv4df_0;
16131 : 13 : break;
16132 : 3 : case E_V4DImode:
16133 : : /* Use ix86_expand_vector_set in 64bit mode only. */
16134 : 3 : use_vector_set = TARGET_AVX && TARGET_64BIT;
16135 : 3 : gen_vec_set_0 = gen_vec_setv4di_0;
16136 : 3 : break;
16137 : 16 : case E_V16SImode:
16138 : 16 : use_vector_set = TARGET_AVX512F && one_var == 0;
16139 : : gen_vec_set_0 = gen_vec_setv16si_0;
16140 : : break;
16141 : 22 : case E_V16SFmode:
16142 : 22 : use_vector_set = TARGET_AVX512F && one_var == 0;
16143 : : gen_vec_set_0 = gen_vec_setv16sf_0;
16144 : : break;
16145 : 0 : case E_V8DFmode:
16146 : 0 : use_vector_set = TARGET_AVX512F && one_var == 0;
16147 : : gen_vec_set_0 = gen_vec_setv8df_0;
16148 : : break;
16149 : 2 : case E_V8DImode:
16150 : : /* Use ix86_expand_vector_set in 64bit mode only. */
16151 : 2 : use_vector_set = TARGET_AVX512F && TARGET_64BIT && one_var == 0;
16152 : : gen_vec_set_0 = gen_vec_setv8di_0;
16153 : : break;
16154 : 36 : case E_V8HFmode:
16155 : 36 : use_vector_set = TARGET_AVX512FP16 && one_var == 0;
16156 : : gen_vec_set_0 = gen_vec_setv8hf_0;
16157 : : break;
16158 : 7 : case E_V16HFmode:
16159 : 7 : use_vector_set = TARGET_AVX512FP16 && one_var == 0;
16160 : : gen_vec_set_0 = gen_vec_setv16hf_0;
16161 : : break;
16162 : 6 : case E_V32HFmode:
16163 : 6 : use_vector_set = TARGET_AVX512FP16 && one_var == 0;
16164 : : gen_vec_set_0 = gen_vec_setv32hf_0;
16165 : : break;
16166 : 0 : case E_V8BFmode:
16167 : 0 : use_vector_set = TARGET_AVX512FP16 && one_var == 0;
16168 : : gen_vec_set_0 = gen_vec_setv8bf_0;
16169 : : break;
16170 : 0 : case E_V16BFmode:
16171 : 0 : use_vector_set = TARGET_AVX512FP16 && one_var == 0;
16172 : : gen_vec_set_0 = gen_vec_setv16bf_0;
16173 : : break;
16174 : 0 : case E_V32BFmode:
16175 : 0 : use_vector_set = TARGET_AVX512FP16 && one_var == 0;
16176 : : gen_vec_set_0 = gen_vec_setv32bf_0;
16177 : : break;
16178 : 4 : case E_V32HImode:
16179 : 4 : use_vector_set = TARGET_AVX512FP16 && one_var == 0;
16180 : : gen_vec_set_0 = gen_vec_setv32hi_0;
16181 : : default:
16182 : : break;
16183 : : }
16184 : :
16185 : 803 : if (use_vector_set)
16186 : : {
16187 : 393 : if (gen_vec_set_0 && one_var == 0)
16188 : : {
16189 : 320 : var = force_reg (GET_MODE_INNER (mode), var);
16190 : 160 : emit_insn (gen_vec_set_0 (target, CONST0_RTX (mode), var));
16191 : 160 : return true;
16192 : : }
16193 : 233 : emit_insn (gen_rtx_SET (target, CONST0_RTX (mode)));
16194 : 466 : var = force_reg (GET_MODE_INNER (mode), var);
16195 : 233 : ix86_expand_vector_set (mmx_ok, target, var, one_var);
16196 : 233 : return true;
16197 : : }
16198 : :
16199 : 1129 : switch (mode)
16200 : : {
16201 : 556 : case E_V2SFmode:
16202 : 556 : case E_V2SImode:
16203 : 556 : if (!mmx_ok)
16204 : : return false;
16205 : : /* FALLTHRU */
16206 : :
16207 : 515 : case E_V2DFmode:
16208 : 515 : case E_V2DImode:
16209 : 515 : if (one_var != 0)
16210 : : return false;
16211 : 528 : var = force_reg (GET_MODE_INNER (mode), var);
16212 : 528 : x = gen_rtx_VEC_CONCAT (mode, var, CONST0_RTX (GET_MODE_INNER (mode)));
16213 : 264 : emit_insn (gen_rtx_SET (target, x));
16214 : 264 : return true;
16215 : :
16216 : 145 : case E_V4SFmode:
16217 : 145 : case E_V4SImode:
16218 : 145 : if (!REG_P (target) || REGNO (target) < FIRST_PSEUDO_REGISTER)
16219 : 0 : new_target = gen_reg_rtx (mode);
16220 : : else
16221 : : new_target = target;
16222 : 290 : var = force_reg (GET_MODE_INNER (mode), var);
16223 : 145 : x = gen_rtx_VEC_DUPLICATE (mode, var);
16224 : 145 : x = gen_rtx_VEC_MERGE (mode, x, CONST0_RTX (mode), const1_rtx);
16225 : 145 : emit_insn (gen_rtx_SET (new_target, x));
16226 : 145 : if (one_var != 0)
16227 : : {
16228 : : /* We need to shuffle the value to the correct position, so
16229 : : create a new pseudo to store the intermediate result. */
16230 : :
16231 : : /* With SSE2, we can use the integer shuffle insns. */
16232 : 24 : if (mode != V4SFmode && TARGET_SSE2)
16233 : : {
16234 : 14 : emit_insn (gen_sse2_pshufd_1 (new_target, new_target,
16235 : : const1_rtx,
16236 : 14 : GEN_INT (one_var == 1 ? 0 : 1),
16237 : 14 : GEN_INT (one_var == 2 ? 0 : 1),
16238 : 14 : GEN_INT (one_var == 3 ? 0 : 1)));
16239 : 14 : if (target != new_target)
16240 : 0 : emit_move_insn (target, new_target);
16241 : 14 : return true;
16242 : : }
16243 : :
16244 : : /* Otherwise convert the intermediate result to V4SFmode and
16245 : : use the SSE1 shuffle instructions. */
16246 : 0 : if (mode != V4SFmode)
16247 : : {
16248 : 0 : tmp = gen_reg_rtx (V4SFmode);
16249 : 0 : emit_move_insn (tmp, gen_lowpart (V4SFmode, new_target));
16250 : : }
16251 : : else
16252 : : tmp = new_target;
16253 : :
16254 : 33 : emit_insn (gen_sse_shufps_v4sf (tmp, tmp, tmp,
16255 : : const1_rtx,
16256 : 10 : GEN_INT (one_var == 1 ? 0 : 1),
16257 : : GEN_INT (one_var == 2 ? 0+4 : 1+4),
16258 : : GEN_INT (one_var == 3 ? 0+4 : 1+4)));
16259 : :
16260 : 10 : if (mode != V4SFmode)
16261 : 0 : emit_move_insn (target, gen_lowpart (V4SImode, tmp));
16262 : 10 : else if (tmp != target)
16263 : 0 : emit_move_insn (target, tmp);
16264 : : }
16265 : 121 : else if (target != new_target)
16266 : 0 : emit_move_insn (target, new_target);
16267 : : return true;
16268 : :
16269 : 10 : case E_V8HImode:
16270 : 10 : case E_V16QImode:
16271 : 10 : vsimode = V4SImode;
16272 : 10 : goto widen;
16273 : 4 : case E_V4HImode:
16274 : 4 : case E_V8QImode:
16275 : 4 : if (!mmx_ok)
16276 : : return false;
16277 : 4 : vsimode = V2SImode;
16278 : 4 : goto widen;
16279 : 14 : widen:
16280 : 14 : if (one_var != 0)
16281 : : return false;
16282 : :
16283 : : /* Zero extend the variable element to SImode and recurse. */
16284 : 14 : var = convert_modes (SImode, GET_MODE_INNER (mode), var, true);
16285 : :
16286 : 7 : x = gen_reg_rtx (vsimode);
16287 : 7 : if (!ix86_expand_vector_init_one_nonzero (mmx_ok, vsimode, x,
16288 : : var, one_var))
16289 : 0 : gcc_unreachable ();
16290 : :
16291 : 7 : emit_move_insn (target, gen_lowpart (mode, x));
16292 : 7 : return true;
16293 : :
16294 : : default:
16295 : : return false;
16296 : : }
16297 : : }
16298 : :
16299 : : /* A subroutine of ix86_expand_vector_init. Store into TARGET a vector
16300 : : consisting of the values in VALS. It is known that all elements
16301 : : except ONE_VAR are constants. Return true if successful. */
16302 : :
16303 : : static bool
16304 : 1389 : ix86_expand_vector_init_one_var (bool mmx_ok, machine_mode mode,
16305 : : rtx target, rtx vals, int one_var)
16306 : : {
16307 : 1389 : rtx var = XVECEXP (vals, 0, one_var);
16308 : 1389 : machine_mode wmode;
16309 : 1389 : rtx const_vec, x;
16310 : :
16311 : 1389 : const_vec = copy_rtx (vals);
16312 : 1389 : XVECEXP (const_vec, 0, one_var) = CONST0_RTX (GET_MODE_INNER (mode));
16313 : 1389 : const_vec = gen_rtx_CONST_VECTOR (mode, XVEC (const_vec, 0));
16314 : :
16315 : 1389 : switch (mode)
16316 : : {
16317 : : case E_V2DFmode:
16318 : : case E_V2DImode:
16319 : : case E_V2SFmode:
16320 : : case E_V2SImode:
16321 : : /* For the two element vectors, it's just as easy to use
16322 : : the general case. */
16323 : : return false;
16324 : :
16325 : 2 : case E_V4DImode:
16326 : : /* Use ix86_expand_vector_set in 64bit mode only. */
16327 : 2 : if (!TARGET_64BIT)
16328 : : return false;
16329 : : /* FALLTHRU */
16330 : : case E_V8HFmode:
16331 : : case E_V16HFmode:
16332 : : case E_V8BFmode:
16333 : : case E_V16BFmode:
16334 : : case E_V4DFmode:
16335 : : case E_V8SFmode:
16336 : : case E_V8SImode:
16337 : : case E_V16HImode:
16338 : : case E_V32QImode:
16339 : : case E_V4SFmode:
16340 : : case E_V4SImode:
16341 : : case E_V8HImode:
16342 : : case E_V4HImode:
16343 : : case E_V4HFmode:
16344 : : case E_V4BFmode:
16345 : : break;
16346 : :
16347 : 8 : case E_V16QImode:
16348 : 8 : if (TARGET_SSE4_1)
16349 : : break;
16350 : 8 : wmode = V8HImode;
16351 : 8 : goto widen;
16352 : 0 : case E_V8QImode:
16353 : 0 : if (TARGET_MMX_WITH_SSE && TARGET_SSE4_1)
16354 : : break;
16355 : 0 : wmode = V4HImode;
16356 : 0 : goto widen;
16357 : 13 : case E_V4QImode:
16358 : 13 : if (TARGET_SSE4_1)
16359 : : break;
16360 : : wmode = V2HImode;
16361 : 21 : widen:
16362 : : /* There's no way to set one QImode entry easily. Combine
16363 : : the variable value with its adjacent constant value, and
16364 : : promote to an HImode set. */
16365 : 21 : x = XVECEXP (vals, 0, one_var ^ 1);
16366 : 21 : if (one_var & 1)
16367 : : {
16368 : 6 : var = convert_modes (HImode, QImode, var, true);
16369 : 6 : var = expand_simple_binop (HImode, ASHIFT, var, GEN_INT (8),
16370 : : NULL_RTX, 1, OPTAB_LIB_WIDEN);
16371 : 6 : x = GEN_INT (INTVAL (x) & 0xff);
16372 : : }
16373 : : else
16374 : : {
16375 : 15 : var = convert_modes (HImode, QImode, var, true);
16376 : 15 : x = gen_int_mode (UINTVAL (x) << 8, HImode);
16377 : : }
16378 : 21 : if (x != const0_rtx)
16379 : 7 : var = expand_simple_binop (HImode, IOR, var, x, var,
16380 : : 1, OPTAB_LIB_WIDEN);
16381 : :
16382 : 21 : x = gen_reg_rtx (wmode);
16383 : 21 : emit_move_insn (x, gen_lowpart (wmode, const_vec));
16384 : 21 : ix86_expand_vector_set (mmx_ok, x, var, one_var >> 1);
16385 : :
16386 : 21 : emit_move_insn (target, gen_lowpart (mode, x));
16387 : 21 : return true;
16388 : :
16389 : : default:
16390 : : return false;
16391 : : }
16392 : :
16393 : 177 : emit_move_insn (target, const_vec);
16394 : 177 : ix86_expand_vector_set (mmx_ok, target, var, one_var);
16395 : 177 : return true;
16396 : : }
16397 : :
16398 : : /* A subroutine of ix86_expand_vector_init_general. Use vector
16399 : : concatenate to handle the most general case: all values variable,
16400 : : and none identical. */
16401 : :
16402 : : static void
16403 : 150787 : ix86_expand_vector_init_concat (machine_mode mode,
16404 : : rtx target, rtx *ops, int n)
16405 : : {
16406 : 150787 : machine_mode half_mode = VOIDmode;
16407 : 150787 : rtx half[2];
16408 : 150787 : rtvec v;
16409 : 150787 : int i, j;
16410 : :
16411 : 150787 : switch (n)
16412 : : {
16413 : 141040 : case 2:
16414 : 141040 : switch (mode)
16415 : : {
16416 : : case E_V32HFmode:
16417 : : half_mode = V16HFmode;
16418 : : break;
16419 : 0 : case E_V32BFmode:
16420 : 0 : half_mode = V16BFmode;
16421 : 0 : break;
16422 : 77 : case E_V16SImode:
16423 : 77 : half_mode = V8SImode;
16424 : 77 : break;
16425 : 41 : case E_V16SFmode:
16426 : 41 : half_mode = V8SFmode;
16427 : 41 : break;
16428 : 112 : case E_V8DImode:
16429 : 112 : half_mode = V4DImode;
16430 : 112 : break;
16431 : 83 : case E_V8DFmode:
16432 : 83 : half_mode = V4DFmode;
16433 : 83 : break;
16434 : 0 : case E_V16HFmode:
16435 : 0 : half_mode = V8HFmode;
16436 : 0 : break;
16437 : 0 : case E_V16BFmode:
16438 : 0 : half_mode = V8BFmode;
16439 : 0 : break;
16440 : 176 : case E_V8SImode:
16441 : 176 : half_mode = V4SImode;
16442 : 176 : break;
16443 : 241 : case E_V8SFmode:
16444 : 241 : half_mode = V4SFmode;
16445 : 241 : break;
16446 : 406 : case E_V4DImode:
16447 : 406 : half_mode = V2DImode;
16448 : 406 : break;
16449 : 624 : case E_V4DFmode:
16450 : 624 : half_mode = V2DFmode;
16451 : 624 : break;
16452 : 6584 : case E_V4SImode:
16453 : 6584 : half_mode = V2SImode;
16454 : 6584 : break;
16455 : 1965 : case E_V4SFmode:
16456 : 1965 : half_mode = V2SFmode;
16457 : 1965 : break;
16458 : 74900 : case E_V2DImode:
16459 : 74900 : half_mode = DImode;
16460 : 74900 : break;
16461 : 47087 : case E_V2SImode:
16462 : 47087 : half_mode = SImode;
16463 : 47087 : break;
16464 : 3796 : case E_V2DFmode:
16465 : 3796 : half_mode = DFmode;
16466 : 3796 : break;
16467 : 4948 : case E_V2SFmode:
16468 : 4948 : half_mode = SFmode;
16469 : 4948 : break;
16470 : 0 : default:
16471 : 0 : gcc_unreachable ();
16472 : : }
16473 : :
16474 : 141040 : if (!register_operand (ops[1], half_mode))
16475 : 58543 : ops[1] = force_reg (half_mode, ops[1]);
16476 : 141040 : if (!register_operand (ops[0], half_mode))
16477 : 38051 : ops[0] = force_reg (half_mode, ops[0]);
16478 : 141040 : emit_insn (gen_rtx_SET (target, gen_rtx_VEC_CONCAT (mode, ops[0],
16479 : : ops[1])));
16480 : 141040 : break;
16481 : :
16482 : 9117 : case 4:
16483 : 9117 : switch (mode)
16484 : : {
16485 : : case E_V4DImode:
16486 : : half_mode = V2DImode;
16487 : : break;
16488 : 530 : case E_V4DFmode:
16489 : 530 : half_mode = V2DFmode;
16490 : 530 : break;
16491 : 6426 : case E_V4SImode:
16492 : 6426 : half_mode = V2SImode;
16493 : 6426 : break;
16494 : 1875 : case E_V4SFmode:
16495 : 1875 : half_mode = V2SFmode;
16496 : 1875 : break;
16497 : 0 : default:
16498 : 0 : gcc_unreachable ();
16499 : : }
16500 : 9117 : goto half;
16501 : :
16502 : 531 : case 8:
16503 : 531 : switch (mode)
16504 : : {
16505 : : case E_V8DImode:
16506 : : half_mode = V4DImode;
16507 : : break;
16508 : 82 : case E_V8DFmode:
16509 : 82 : half_mode = V4DFmode;
16510 : 82 : break;
16511 : 149 : case E_V8SImode:
16512 : 149 : half_mode = V4SImode;
16513 : 149 : break;
16514 : 235 : case E_V8SFmode:
16515 : 235 : half_mode = V4SFmode;
16516 : 235 : break;
16517 : 0 : default:
16518 : 0 : gcc_unreachable ();
16519 : : }
16520 : 531 : goto half;
16521 : :
16522 : 99 : case 16:
16523 : 99 : switch (mode)
16524 : : {
16525 : : case E_V16SImode:
16526 : : half_mode = V8SImode;
16527 : : break;
16528 : 41 : case E_V16SFmode:
16529 : 41 : half_mode = V8SFmode;
16530 : 41 : break;
16531 : 0 : default:
16532 : 0 : gcc_unreachable ();
16533 : : }
16534 : 99 : goto half;
16535 : :
16536 : 9747 : half:
16537 : : /* FIXME: We process inputs backward to help RA. PR 36222. */
16538 : 9747 : i = n - 1;
16539 : 29241 : for (j = 1; j != -1; j--)
16540 : : {
16541 : 19494 : half[j] = gen_reg_rtx (half_mode);
16542 : 19494 : switch (n >> 1)
16543 : : {
16544 : 18234 : case 2:
16545 : 18234 : v = gen_rtvec (2, ops[i-1], ops[i]);
16546 : 18234 : i -= 2;
16547 : 18234 : break;
16548 : 1062 : case 4:
16549 : 1062 : v = gen_rtvec (4, ops[i-3], ops[i-2], ops[i-1], ops[i]);
16550 : 1062 : i -= 4;
16551 : 1062 : break;
16552 : 198 : case 8:
16553 : 396 : v = gen_rtvec (8, ops[i-7], ops[i-6], ops[i-5], ops[i-4],
16554 : 198 : ops[i-3], ops[i-2], ops[i-1], ops[i]);
16555 : 198 : i -= 8;
16556 : 198 : break;
16557 : 0 : default:
16558 : 0 : gcc_unreachable ();
16559 : : }
16560 : 19494 : ix86_expand_vector_init (false, half[j],
16561 : : gen_rtx_PARALLEL (half_mode, v));
16562 : : }
16563 : :
16564 : 9747 : ix86_expand_vector_init_concat (mode, target, half, 2);
16565 : 9747 : break;
16566 : :
16567 : 0 : default:
16568 : 0 : gcc_unreachable ();
16569 : : }
16570 : 150787 : }
16571 : :
16572 : : /* A subroutine of ix86_expand_vector_init_general. Use vector
16573 : : interleave to handle the most general case: all values variable,
16574 : : and none identical. */
16575 : :
16576 : : static void
16577 : 3691 : ix86_expand_vector_init_interleave (machine_mode mode,
16578 : : rtx target, rtx *ops, int n)
16579 : : {
16580 : 3691 : machine_mode first_imode, second_imode, third_imode, inner_mode;
16581 : 3691 : int i, j;
16582 : 3691 : rtx op, op0, op1;
16583 : 3691 : rtx (*gen_load_even) (rtx, rtx, rtx);
16584 : 3691 : rtx (*gen_interleave_first_low) (rtx, rtx, rtx);
16585 : 3691 : rtx (*gen_interleave_second_low) (rtx, rtx, rtx);
16586 : :
16587 : 3691 : switch (mode)
16588 : : {
16589 : : case E_V8HFmode:
16590 : : gen_load_even = gen_vec_interleave_lowv8hf;
16591 : : gen_interleave_first_low = gen_vec_interleave_lowv4si;
16592 : : gen_interleave_second_low = gen_vec_interleave_lowv2di;
16593 : : inner_mode = HFmode;
16594 : : first_imode = V4SImode;
16595 : : second_imode = V2DImode;
16596 : : third_imode = VOIDmode;
16597 : : break;
16598 : 487 : case E_V8BFmode:
16599 : 487 : gen_load_even = gen_vec_interleave_lowv8bf;
16600 : 487 : gen_interleave_first_low = gen_vec_interleave_lowv4si;
16601 : 487 : gen_interleave_second_low = gen_vec_interleave_lowv2di;
16602 : 487 : inner_mode = BFmode;
16603 : 487 : first_imode = V4SImode;
16604 : 487 : second_imode = V2DImode;
16605 : 487 : third_imode = VOIDmode;
16606 : 487 : break;
16607 : 787 : case E_V8HImode:
16608 : 787 : gen_load_even = gen_vec_setv8hi;
16609 : 787 : gen_interleave_first_low = gen_vec_interleave_lowv4si;
16610 : 787 : gen_interleave_second_low = gen_vec_interleave_lowv2di;
16611 : 787 : inner_mode = HImode;
16612 : 787 : first_imode = V4SImode;
16613 : 787 : second_imode = V2DImode;
16614 : 787 : third_imode = VOIDmode;
16615 : 787 : break;
16616 : 363 : case E_V16QImode:
16617 : 363 : gen_load_even = gen_vec_setv16qi;
16618 : 363 : gen_interleave_first_low = gen_vec_interleave_lowv8hi;
16619 : 363 : gen_interleave_second_low = gen_vec_interleave_lowv4si;
16620 : 363 : inner_mode = QImode;
16621 : 363 : first_imode = V8HImode;
16622 : 363 : second_imode = V4SImode;
16623 : 363 : third_imode = V2DImode;
16624 : 363 : break;
16625 : 0 : default:
16626 : 0 : gcc_unreachable ();
16627 : : }
16628 : :
16629 : 19907 : for (i = 0; i < n; i++)
16630 : : {
16631 : 16216 : op = ops [i + i];
16632 : 16216 : if (inner_mode == HFmode || inner_mode == BFmode)
16633 : : {
16634 : 10164 : rtx even, odd;
16635 : : /* Use vpuncklwd to pack 2 HFmode or BFmode. */
16636 : 20328 : machine_mode vec_mode =
16637 : 10164 : (inner_mode == HFmode) ? V8HFmode : V8BFmode;
16638 : 10164 : op0 = gen_reg_rtx (vec_mode);
16639 : 10164 : even = lowpart_subreg (vec_mode,
16640 : : force_reg (inner_mode, op), inner_mode);
16641 : 10164 : odd = lowpart_subreg (vec_mode,
16642 : 10164 : force_reg (inner_mode, ops[i + i + 1]),
16643 : : inner_mode);
16644 : 10164 : emit_insn (gen_load_even (op0, even, odd));
16645 : : }
16646 : : else
16647 : : {
16648 : : /* Extend the odd elment to SImode using a paradoxical SUBREG. */
16649 : 6052 : op0 = gen_reg_rtx (SImode);
16650 : 6052 : emit_move_insn (op0, gen_lowpart (SImode, op));
16651 : :
16652 : : /* Insert the SImode value as low element of V4SImode vector. */
16653 : 6052 : op1 = gen_reg_rtx (V4SImode);
16654 : 6052 : op0 = gen_rtx_VEC_MERGE (V4SImode,
16655 : : gen_rtx_VEC_DUPLICATE (V4SImode,
16656 : : op0),
16657 : : CONST0_RTX (V4SImode),
16658 : : const1_rtx);
16659 : 6052 : emit_insn (gen_rtx_SET (op1, op0));
16660 : :
16661 : : /* Cast the V4SImode vector back to a vector in orignal mode. */
16662 : 6052 : op0 = gen_reg_rtx (mode);
16663 : 6052 : emit_move_insn (op0, gen_lowpart (mode, op1));
16664 : :
16665 : : /* Load even elements into the second position. */
16666 : 6052 : emit_insn (gen_load_even (op0,
16667 : : force_reg (inner_mode,
16668 : 6052 : ops[i + i + 1]),
16669 : : const1_rtx));
16670 : : }
16671 : :
16672 : : /* Cast vector to FIRST_IMODE vector. */
16673 : 16216 : ops[i] = gen_reg_rtx (first_imode);
16674 : 16216 : emit_move_insn (ops[i], gen_lowpart (first_imode, op0));
16675 : : }
16676 : :
16677 : : /* Interleave low FIRST_IMODE vectors. */
16678 : 11799 : for (i = j = 0; i < n; i += 2, j++)
16679 : : {
16680 : 8108 : op0 = gen_reg_rtx (first_imode);
16681 : 8108 : emit_insn (gen_interleave_first_low (op0, ops[i], ops[i + 1]));
16682 : :
16683 : : /* Cast FIRST_IMODE vector to SECOND_IMODE vector. */
16684 : 8108 : ops[j] = gen_reg_rtx (second_imode);
16685 : 8108 : emit_move_insn (ops[j], gen_lowpart (second_imode, op0));
16686 : : }
16687 : :
16688 : : /* Interleave low SECOND_IMODE vectors. */
16689 : 3691 : switch (second_imode)
16690 : : {
16691 : : case E_V4SImode:
16692 : 1089 : for (i = j = 0; i < n / 2; i += 2, j++)
16693 : : {
16694 : 726 : op0 = gen_reg_rtx (second_imode);
16695 : 726 : emit_insn (gen_interleave_second_low (op0, ops[i],
16696 : 726 : ops[i + 1]));
16697 : :
16698 : : /* Cast the SECOND_IMODE vector to the THIRD_IMODE
16699 : : vector. */
16700 : 726 : ops[j] = gen_reg_rtx (third_imode);
16701 : 726 : emit_move_insn (ops[j], gen_lowpart (third_imode, op0));
16702 : : }
16703 : : second_imode = V2DImode;
16704 : : gen_interleave_second_low = gen_vec_interleave_lowv2di;
16705 : : /* FALLTHRU */
16706 : :
16707 : 3691 : case E_V2DImode:
16708 : 3691 : op0 = gen_reg_rtx (second_imode);
16709 : 3691 : emit_insn (gen_interleave_second_low (op0, ops[0],
16710 : : ops[1]));
16711 : :
16712 : : /* Cast the SECOND_IMODE vector back to a vector on original
16713 : : mode. */
16714 : 3691 : emit_insn (gen_rtx_SET (target, gen_lowpart (mode, op0)));
16715 : 3691 : break;
16716 : :
16717 : : default:
16718 : : gcc_unreachable ();
16719 : : }
16720 : 3691 : }
16721 : :
16722 : : /* A subroutine of ix86_expand_vector_init. Handle the most general case:
16723 : : all values variable, and none identical. */
16724 : :
16725 : : static void
16726 : 152397 : ix86_expand_vector_init_general (bool mmx_ok, machine_mode mode,
16727 : : rtx target, rtx vals)
16728 : : {
16729 : 152397 : rtx ops[64], op0, op1, op2, op3, op4, op5;
16730 : 152397 : machine_mode half_mode = VOIDmode;
16731 : 152397 : machine_mode quarter_mode = VOIDmode;
16732 : 152397 : machine_mode int_inner_mode = VOIDmode;
16733 : 152397 : int n, i;
16734 : :
16735 : 152397 : switch (mode)
16736 : : {
16737 : 52035 : case E_V2SFmode:
16738 : 52035 : case E_V2SImode:
16739 : 52035 : if (!mmx_ok && !TARGET_SSE)
16740 : : break;
16741 : : /* FALLTHRU */
16742 : :
16743 : 140478 : case E_V16SImode:
16744 : 140478 : case E_V16SFmode:
16745 : 140478 : case E_V8DFmode:
16746 : 140478 : case E_V8DImode:
16747 : 140478 : case E_V8SFmode:
16748 : 140478 : case E_V8SImode:
16749 : 140478 : case E_V4DFmode:
16750 : 140478 : case E_V4DImode:
16751 : 140478 : case E_V4SFmode:
16752 : 140478 : case E_V4SImode:
16753 : 140478 : case E_V2DFmode:
16754 : 140478 : case E_V2DImode:
16755 : 140478 : n = GET_MODE_NUNITS (mode);
16756 : 444240 : for (i = 0; i < n; i++)
16757 : 303762 : ops[i] = XVECEXP (vals, 0, i);
16758 : 140478 : ix86_expand_vector_init_concat (mode, target, ops, n);
16759 : 282968 : return;
16760 : :
16761 : : case E_V2TImode:
16762 : 72 : for (i = 0; i < 2; i++)
16763 : 48 : ops[i] = gen_lowpart (V2DImode, XVECEXP (vals, 0, i));
16764 : 24 : op0 = gen_reg_rtx (V4DImode);
16765 : 24 : ix86_expand_vector_init_concat (V4DImode, op0, ops, 2);
16766 : 24 : emit_move_insn (target, gen_lowpart (GET_MODE (target), op0));
16767 : 24 : return;
16768 : :
16769 : : case E_V4TImode:
16770 : 225 : for (i = 0; i < 4; i++)
16771 : 180 : ops[i] = gen_lowpart (V2DImode, XVECEXP (vals, 0, i));
16772 : 45 : ops[4] = gen_reg_rtx (V4DImode);
16773 : 45 : ix86_expand_vector_init_concat (V4DImode, ops[4], ops, 2);
16774 : 45 : ops[5] = gen_reg_rtx (V4DImode);
16775 : 45 : ix86_expand_vector_init_concat (V4DImode, ops[5], ops + 2, 2);
16776 : 45 : op0 = gen_reg_rtx (V8DImode);
16777 : 45 : ix86_expand_vector_init_concat (V8DImode, op0, ops + 4, 2);
16778 : 45 : emit_move_insn (target, gen_lowpart (GET_MODE (target), op0));
16779 : 45 : return;
16780 : :
16781 : 68 : case E_V32QImode:
16782 : 68 : half_mode = V16QImode;
16783 : 68 : goto half;
16784 : :
16785 : 64 : case E_V16HImode:
16786 : 64 : half_mode = V8HImode;
16787 : 64 : goto half;
16788 : :
16789 : 222 : case E_V16HFmode:
16790 : 222 : half_mode = V8HFmode;
16791 : 222 : goto half;
16792 : :
16793 : 95 : case E_V16BFmode:
16794 : 95 : half_mode = V8BFmode;
16795 : 95 : goto half;
16796 : :
16797 : 449 : half:
16798 : 449 : n = GET_MODE_NUNITS (mode);
16799 : 8721 : for (i = 0; i < n; i++)
16800 : 8272 : ops[i] = XVECEXP (vals, 0, i);
16801 : 449 : op0 = gen_reg_rtx (half_mode);
16802 : 449 : op1 = gen_reg_rtx (half_mode);
16803 : 449 : ix86_expand_vector_init_interleave (half_mode, op0, ops,
16804 : : n >> 2);
16805 : 449 : ix86_expand_vector_init_interleave (half_mode, op1,
16806 : 449 : &ops [n >> 1], n >> 2);
16807 : 449 : emit_insn (gen_rtx_SET (target, gen_rtx_VEC_CONCAT (mode, op0, op1)));
16808 : 449 : return;
16809 : :
16810 : 55 : case E_V64QImode:
16811 : 55 : quarter_mode = V16QImode;
16812 : 55 : half_mode = V32QImode;
16813 : 55 : goto quarter;
16814 : :
16815 : 71 : case E_V32HImode:
16816 : 71 : quarter_mode = V8HImode;
16817 : 71 : half_mode = V16HImode;
16818 : 71 : goto quarter;
16819 : :
16820 : 256 : case E_V32HFmode:
16821 : 256 : quarter_mode = V8HFmode;
16822 : 256 : half_mode = V16HFmode;
16823 : 256 : goto quarter;
16824 : :
16825 : 51 : case E_V32BFmode:
16826 : 51 : quarter_mode = V8BFmode;
16827 : 51 : half_mode = V16BFmode;
16828 : 51 : goto quarter;
16829 : :
16830 : 433 : quarter:
16831 : 433 : n = GET_MODE_NUNITS (mode);
16832 : 16049 : for (i = 0; i < n; i++)
16833 : 15616 : ops[i] = XVECEXP (vals, 0, i);
16834 : 433 : op0 = gen_reg_rtx (quarter_mode);
16835 : 433 : op1 = gen_reg_rtx (quarter_mode);
16836 : 433 : op2 = gen_reg_rtx (quarter_mode);
16837 : 433 : op3 = gen_reg_rtx (quarter_mode);
16838 : 433 : op4 = gen_reg_rtx (half_mode);
16839 : 433 : op5 = gen_reg_rtx (half_mode);
16840 : 433 : ix86_expand_vector_init_interleave (quarter_mode, op0, ops,
16841 : : n >> 3);
16842 : 433 : ix86_expand_vector_init_interleave (quarter_mode, op1,
16843 : 433 : &ops [n >> 2], n >> 3);
16844 : 433 : ix86_expand_vector_init_interleave (quarter_mode, op2,
16845 : 433 : &ops [n >> 1], n >> 3);
16846 : 433 : ix86_expand_vector_init_interleave (quarter_mode, op3,
16847 : 433 : &ops [(n >> 1) | (n >> 2)], n >> 3);
16848 : 433 : emit_insn (gen_rtx_SET (op4, gen_rtx_VEC_CONCAT (half_mode, op0, op1)));
16849 : 433 : emit_insn (gen_rtx_SET (op5, gen_rtx_VEC_CONCAT (half_mode, op2, op3)));
16850 : 433 : emit_insn (gen_rtx_SET (target, gen_rtx_VEC_CONCAT (mode, op4, op5)));
16851 : 433 : return;
16852 : :
16853 : 374 : case E_V16QImode:
16854 : 374 : if (!TARGET_SSE4_1)
16855 : : break;
16856 : : /* FALLTHRU */
16857 : :
16858 : 502 : case E_V8HImode:
16859 : 502 : if (!TARGET_SSE2)
16860 : : break;
16861 : :
16862 : : /* Don't use ix86_expand_vector_init_interleave if we can't
16863 : : move from GPR to SSE register directly. */
16864 : 502 : if (!TARGET_INTER_UNIT_MOVES_TO_VEC)
16865 : : break;
16866 : : /* FALLTHRU */
16867 : :
16868 : 1061 : case E_V8HFmode:
16869 : 1061 : case E_V8BFmode:
16870 : :
16871 : 1061 : n = GET_MODE_NUNITS (mode);
16872 : 9605 : for (i = 0; i < n; i++)
16873 : 8544 : ops[i] = XVECEXP (vals, 0, i);
16874 : 1061 : ix86_expand_vector_init_interleave (mode, target, ops, n >> 1);
16875 : 1061 : return;
16876 : :
16877 : : case E_V4HFmode:
16878 : : case E_V4BFmode:
16879 : : case E_V2HFmode:
16880 : : case E_V2BFmode:
16881 : 9907 : int_inner_mode = HImode;
16882 : : break;
16883 : :
16884 : : case E_V4HImode:
16885 : : case E_V8QImode:
16886 : :
16887 : : case E_V2HImode:
16888 : : case E_V4QImode:
16889 : : break;
16890 : :
16891 : 0 : default:
16892 : 0 : gcc_unreachable ();
16893 : : }
16894 : :
16895 : 9907 : {
16896 : 9907 : int i, j, n_elts, n_words, n_elt_per_word;
16897 : 9907 : machine_mode tmp_mode, inner_mode;
16898 : 9907 : rtx words[4], shift;
16899 : :
16900 : 20291 : tmp_mode = (GET_MODE_SIZE (mode) < UNITS_PER_WORD) ? SImode : word_mode;
16901 : :
16902 : 9907 : inner_mode = GET_MODE_INNER (mode);
16903 : 9907 : n_elts = GET_MODE_NUNITS (mode);
16904 : 19814 : n_words = GET_MODE_SIZE (mode) / GET_MODE_SIZE (tmp_mode);
16905 : 9907 : n_elt_per_word = n_elts / n_words;
16906 : 9907 : shift = GEN_INT (GET_MODE_BITSIZE (inner_mode));
16907 : :
16908 : 20323 : for (i = 0; i < n_words; ++i)
16909 : : {
16910 : : rtx word = NULL_RTX;
16911 : :
16912 : 54672 : for (j = 0; j < n_elt_per_word; ++j)
16913 : : {
16914 : 44256 : rtx elt = XVECEXP (vals, 0, (i+1)*n_elt_per_word - j - 1);
16915 : 44256 : if (int_inner_mode != E_VOIDmode)
16916 : : {
16917 : 130 : gcc_assert (TARGET_SSE2 && int_inner_mode == HImode);
16918 : 130 : rtx tmp = gen_reg_rtx (int_inner_mode);
16919 : 130 : elt = lowpart_subreg (int_inner_mode,
16920 : : force_reg (inner_mode, elt),
16921 : : inner_mode);
16922 : 130 : emit_move_insn (tmp, elt);
16923 : 130 : elt = tmp;
16924 : : }
16925 : 44256 : elt = convert_modes (tmp_mode, inner_mode, elt, true);
16926 : :
16927 : 44256 : if (j == 0)
16928 : : word = elt;
16929 : : else
16930 : : {
16931 : 33840 : word = expand_simple_binop (tmp_mode, ASHIFT, word, shift,
16932 : : NULL_RTX, 1, OPTAB_LIB_WIDEN);
16933 : 33840 : word = expand_simple_binop (tmp_mode, IOR, word, elt,
16934 : : NULL_RTX, 1, OPTAB_LIB_WIDEN);
16935 : : }
16936 : : }
16937 : :
16938 : 10416 : words[i] = word;
16939 : : }
16940 : :
16941 : 9907 : if (n_words == 1)
16942 : 9398 : emit_move_insn (target, gen_lowpart (mode, words[0]));
16943 : 509 : else if (n_words == 2)
16944 : : {
16945 : 509 : gcc_assert (tmp_mode == DImode || tmp_mode == SImode);
16946 : 509 : machine_mode concat_mode = tmp_mode == DImode ? V2DImode : V2SImode;
16947 : 509 : rtx tmp = gen_reg_rtx (concat_mode);
16948 : 509 : vals = gen_rtx_PARALLEL (concat_mode, gen_rtvec_v (2, words));
16949 : 509 : ix86_expand_vector_init_general (mmx_ok, concat_mode, tmp, vals);
16950 : 509 : emit_move_insn (target, gen_lowpart (mode, tmp));
16951 : : }
16952 : 0 : else if (n_words == 4)
16953 : : {
16954 : 0 : rtx tmp = gen_reg_rtx (V4SImode);
16955 : 0 : gcc_assert (tmp_mode == SImode);
16956 : 0 : vals = gen_rtx_PARALLEL (V4SImode, gen_rtvec_v (4, words));
16957 : 0 : ix86_expand_vector_init_general (false, V4SImode, tmp, vals);
16958 : 0 : emit_move_insn (target, gen_lowpart (mode, tmp));
16959 : : }
16960 : : else
16961 : 0 : gcc_unreachable ();
16962 : : }
16963 : : }
16964 : :
16965 : : /* Initialize vector TARGET via VALS. Suppress the use of MMX
16966 : : instructions unless MMX_OK is true. */
16967 : :
16968 : : void
16969 : 158474 : ix86_expand_vector_init (bool mmx_ok, rtx target, rtx vals)
16970 : : {
16971 : 158474 : machine_mode mode = GET_MODE (target);
16972 : 158474 : machine_mode inner_mode = GET_MODE_INNER (mode);
16973 : 158474 : int n_elts = GET_MODE_NUNITS (mode);
16974 : 158474 : int n_var = 0, one_var = -1;
16975 : 158474 : bool all_same = true, all_const_zero = true;
16976 : 158474 : int i;
16977 : 158474 : rtx x;
16978 : :
16979 : : /* Handle first initialization from vector elts. */
16980 : 158474 : if (n_elts != XVECLEN (vals, 0))
16981 : : {
16982 : 403 : rtx subtarget = target;
16983 : 403 : x = XVECEXP (vals, 0, 0);
16984 : 806 : gcc_assert (GET_MODE_INNER (GET_MODE (x)) == inner_mode);
16985 : 806 : if (GET_MODE_NUNITS (GET_MODE (x)) * 2 == n_elts)
16986 : : {
16987 : 403 : rtx ops[2] = { XVECEXP (vals, 0, 0), XVECEXP (vals, 0, 1) };
16988 : 403 : if (inner_mode == QImode
16989 : 403 : || inner_mode == HImode
16990 : 403 : || inner_mode == TImode
16991 : : || inner_mode == HFmode
16992 : : || inner_mode == BFmode)
16993 : : {
16994 : 107 : unsigned int n_bits = n_elts * GET_MODE_SIZE (inner_mode);
16995 : 107 : scalar_mode elt_mode = inner_mode == TImode ? DImode : SImode;
16996 : 107 : n_bits /= GET_MODE_SIZE (elt_mode);
16997 : 107 : mode = mode_for_vector (elt_mode, n_bits).require ();
16998 : 107 : inner_mode = mode_for_vector (elt_mode, n_bits / 2).require ();
16999 : 107 : ops[0] = gen_lowpart (inner_mode, ops[0]);
17000 : 107 : ops[1] = gen_lowpart (inner_mode, ops[1]);
17001 : 107 : subtarget = gen_reg_rtx (mode);
17002 : : }
17003 : 403 : ix86_expand_vector_init_concat (mode, subtarget, ops, 2);
17004 : 403 : if (subtarget != target)
17005 : 107 : emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
17006 : 403 : return;
17007 : : }
17008 : 0 : gcc_unreachable ();
17009 : : }
17010 : :
17011 : 564889 : for (i = 0; i < n_elts; ++i)
17012 : : {
17013 : 406818 : x = XVECEXP (vals, 0, i);
17014 : 805098 : if (!(CONST_SCALAR_INT_P (x)
17015 : 401175 : || CONST_DOUBLE_P (x)
17016 : : || CONST_FIXED_P (x)))
17017 : 398280 : n_var++, one_var = i;
17018 : 8538 : else if (x != CONST0_RTX (inner_mode))
17019 : 2359 : all_const_zero = false;
17020 : 406818 : if (i > 0 && !rtx_equal_p (x, XVECEXP (vals, 0, 0)))
17021 : : all_same = false;
17022 : : }
17023 : :
17024 : : /* If all values are identical, broadcast the value. */
17025 : 158071 : if (all_same
17026 : 165730 : && ix86_expand_vector_init_duplicate (mmx_ok, mode, target,
17027 : 7659 : XVECEXP (vals, 0, 0)))
17028 : : return;
17029 : :
17030 : : /* Constants are best loaded from the constant pool. */
17031 : 153054 : if (n_var == 0)
17032 : : {
17033 : 166 : emit_move_insn (target, gen_rtx_CONST_VECTOR (mode, XVEC (vals, 0)));
17034 : 166 : return;
17035 : : }
17036 : :
17037 : : /* Values where only one field is non-constant are best loaded from
17038 : : the pool and overwritten via move later. */
17039 : 152888 : if (n_var == 1)
17040 : : {
17041 : 2191 : if (all_const_zero
17042 : 3706 : && ix86_expand_vector_init_one_nonzero (mmx_ok, mode, target,
17043 : 1515 : XVECEXP (vals, 0, one_var),
17044 : : one_var))
17045 : : return;
17046 : :
17047 : 1389 : if (ix86_expand_vector_init_one_var (mmx_ok, mode, target, vals, one_var))
17048 : : return;
17049 : : }
17050 : :
17051 : 151888 : ix86_expand_vector_init_general (mmx_ok, mode, target, vals);
17052 : : }
17053 : :
17054 : : /* Implemented as
17055 : : V setg (V v, int idx, T val)
17056 : : {
17057 : : V idxv = (V){idx, idx, idx, idx, idx, idx, idx, idx};
17058 : : V valv = (V){val, val, val, val, val, val, val, val};
17059 : : V mask = ((V){0, 1, 2, 3, 4, 5, 6, 7} == idxv);
17060 : : v = (v & ~mask) | (valv & mask);
17061 : : return v;
17062 : : }. */
17063 : : void
17064 : 133 : ix86_expand_vector_set_var (rtx target, rtx val, rtx idx)
17065 : : {
17066 : 133 : rtx vec[64];
17067 : 133 : machine_mode mode = GET_MODE (target);
17068 : 133 : machine_mode cmp_mode = mode;
17069 : 133 : int n_elts = GET_MODE_NUNITS (mode);
17070 : 133 : rtx valv,idxv,constv,idx_tmp;
17071 : 133 : bool ok = false;
17072 : :
17073 : : /* 512-bits vector byte/word broadcast and comparison only available
17074 : : under TARGET_AVX512BW, break 512-bits vector into two 256-bits vector
17075 : : when without TARGET_AVX512BW. */
17076 : 133 : if ((mode == V32HImode || mode == V32HFmode || mode == V32BFmode
17077 : 127 : || mode == V64QImode)
17078 : 10 : && !TARGET_AVX512BW)
17079 : : {
17080 : 3 : gcc_assert (TARGET_AVX512F);
17081 : 3 : rtx vhi, vlo, idx_hi;
17082 : 3 : machine_mode half_mode;
17083 : 3 : rtx (*extract_hi)(rtx, rtx);
17084 : 3 : rtx (*extract_lo)(rtx, rtx);
17085 : :
17086 : 3 : if (mode == V32HImode)
17087 : : {
17088 : : half_mode = V16HImode;
17089 : : extract_hi = gen_vec_extract_hi_v32hi;
17090 : : extract_lo = gen_vec_extract_lo_v32hi;
17091 : : }
17092 : : else if (mode == V32HFmode)
17093 : : {
17094 : : half_mode = V16HFmode;
17095 : : extract_hi = gen_vec_extract_hi_v32hf;
17096 : : extract_lo = gen_vec_extract_lo_v32hf;
17097 : : }
17098 : : else if (mode == V32BFmode)
17099 : : {
17100 : : half_mode = V16BFmode;
17101 : : extract_hi = gen_vec_extract_hi_v32bf;
17102 : : extract_lo = gen_vec_extract_lo_v32bf;
17103 : : }
17104 : : else
17105 : : {
17106 : 3 : half_mode = V32QImode;
17107 : 3 : extract_hi = gen_vec_extract_hi_v64qi;
17108 : 3 : extract_lo = gen_vec_extract_lo_v64qi;
17109 : : }
17110 : :
17111 : 3 : vhi = gen_reg_rtx (half_mode);
17112 : 3 : vlo = gen_reg_rtx (half_mode);
17113 : 3 : idx_hi = gen_reg_rtx (GET_MODE (idx));
17114 : 3 : emit_insn (extract_hi (vhi, target));
17115 : 3 : emit_insn (extract_lo (vlo, target));
17116 : 3 : vec[0] = idx_hi;
17117 : 3 : vec[1] = idx;
17118 : 3 : vec[2] = GEN_INT (n_elts/2);
17119 : 3 : ix86_expand_binary_operator (MINUS, GET_MODE (idx), vec);
17120 : 3 : ix86_expand_vector_set_var (vhi, val, idx_hi);
17121 : 3 : ix86_expand_vector_set_var (vlo, val, idx);
17122 : 3 : emit_insn (gen_rtx_SET (target, gen_rtx_VEC_CONCAT (mode, vlo, vhi)));
17123 : 3 : return;
17124 : : }
17125 : :
17126 : 524 : if (FLOAT_MODE_P (GET_MODE_INNER (mode)))
17127 : : {
17128 : 42 : switch (mode)
17129 : : {
17130 : : case E_V2DFmode:
17131 : : cmp_mode = V2DImode;
17132 : : break;
17133 : 6 : case E_V4DFmode:
17134 : 6 : cmp_mode = V4DImode;
17135 : 6 : break;
17136 : 4 : case E_V8DFmode:
17137 : 4 : cmp_mode = V8DImode;
17138 : 4 : break;
17139 : 2 : case E_V2SFmode:
17140 : 2 : cmp_mode = V2SImode;
17141 : 2 : break;
17142 : 6 : case E_V4SFmode:
17143 : 6 : cmp_mode = V4SImode;
17144 : 6 : break;
17145 : 6 : case E_V8SFmode:
17146 : 6 : cmp_mode = V8SImode;
17147 : 6 : break;
17148 : 5 : case E_V16SFmode:
17149 : 5 : cmp_mode = V16SImode;
17150 : 5 : break;
17151 : 1 : case E_V2HFmode:
17152 : 1 : case E_V2BFmode:
17153 : 1 : cmp_mode = V2HImode;
17154 : 1 : break;
17155 : 1 : case E_V4HFmode:
17156 : 1 : case E_V4BFmode:
17157 : 1 : cmp_mode = V4HImode;
17158 : 1 : break;
17159 : : case E_V8HFmode:
17160 : 2 : cmp_mode = V8HImode;
17161 : : break;
17162 : : case E_V16HFmode:
17163 : 2 : cmp_mode = V16HImode;
17164 : : break;
17165 : : case E_V32HFmode:
17166 : 1 : cmp_mode = V32HImode;
17167 : : break;
17168 : : case E_V8BFmode:
17169 : 2 : cmp_mode = V8HImode;
17170 : : break;
17171 : : case E_V16BFmode:
17172 : 2 : cmp_mode = V16HImode;
17173 : : break;
17174 : : case E_V32BFmode:
17175 : 1 : cmp_mode = V32HImode;
17176 : : break;
17177 : 0 : default:
17178 : 0 : gcc_unreachable ();
17179 : : }
17180 : : }
17181 : :
17182 : 1624 : for (int i = 0; i != n_elts; i++)
17183 : 1494 : vec[i] = GEN_INT (i);
17184 : 130 : constv = gen_rtx_CONST_VECTOR (cmp_mode, gen_rtvec_v (n_elts, vec));
17185 : 130 : valv = gen_reg_rtx (mode);
17186 : 130 : idxv = gen_reg_rtx (cmp_mode);
17187 : 260 : idx_tmp = convert_to_mode (GET_MODE_INNER (cmp_mode), idx, 1);
17188 : :
17189 : 130 : ok = ix86_expand_vector_init_duplicate (TARGET_MMX_WITH_SSE,
17190 : : mode, valv, val);
17191 : 130 : gcc_assert (ok);
17192 : 130 : ok = ix86_expand_vector_init_duplicate (TARGET_MMX_WITH_SSE,
17193 : : cmp_mode, idxv, idx_tmp);
17194 : 130 : gcc_assert (ok);
17195 : 130 : vec[0] = target;
17196 : 130 : vec[1] = valv;
17197 : 130 : vec[2] = target;
17198 : 130 : vec[3] = gen_rtx_EQ (mode, idxv, constv);
17199 : 130 : vec[4] = idxv;
17200 : 130 : vec[5] = constv;
17201 : 130 : ok = ix86_expand_int_vcond (vec);
17202 : 130 : gcc_assert (ok);
17203 : : }
17204 : :
17205 : : void
17206 : 7782 : ix86_expand_vector_set (bool mmx_ok, rtx target, rtx val, int elt)
17207 : : {
17208 : 7782 : machine_mode mode = GET_MODE (target);
17209 : 7782 : machine_mode inner_mode = GET_MODE_INNER (mode);
17210 : 7782 : machine_mode half_mode;
17211 : 7782 : bool use_vec_merge = false;
17212 : 7782 : bool blendm_const = false;
17213 : 7782 : rtx tmp;
17214 : 7782 : static rtx (*gen_extract[8][2]) (rtx, rtx)
17215 : : = {
17216 : : { gen_vec_extract_lo_v32qi, gen_vec_extract_hi_v32qi },
17217 : : { gen_vec_extract_lo_v16hi, gen_vec_extract_hi_v16hi },
17218 : : { gen_vec_extract_lo_v8si, gen_vec_extract_hi_v8si },
17219 : : { gen_vec_extract_lo_v4di, gen_vec_extract_hi_v4di },
17220 : : { gen_vec_extract_lo_v8sf, gen_vec_extract_hi_v8sf },
17221 : : { gen_vec_extract_lo_v4df, gen_vec_extract_hi_v4df },
17222 : : { gen_vec_extract_lo_v16hf, gen_vec_extract_hi_v16hf },
17223 : : { gen_vec_extract_lo_v16bf, gen_vec_extract_hi_v16bf }
17224 : : };
17225 : 7782 : static rtx (*gen_insert[8][2]) (rtx, rtx, rtx)
17226 : : = {
17227 : : { gen_vec_set_lo_v32qi, gen_vec_set_hi_v32qi },
17228 : : { gen_vec_set_lo_v16hi, gen_vec_set_hi_v16hi },
17229 : : { gen_vec_set_lo_v8si, gen_vec_set_hi_v8si },
17230 : : { gen_vec_set_lo_v4di, gen_vec_set_hi_v4di },
17231 : : { gen_vec_set_lo_v8sf, gen_vec_set_hi_v8sf },
17232 : : { gen_vec_set_lo_v4df, gen_vec_set_hi_v4df },
17233 : : { gen_vec_set_lo_v16hf, gen_vec_set_hi_v16hf },
17234 : : { gen_vec_set_lo_v16bf, gen_vec_set_hi_v16bf },
17235 : : };
17236 : 7782 : int i, j, n;
17237 : 7782 : machine_mode mmode = VOIDmode;
17238 : 7782 : rtx (*gen_blendm) (rtx, rtx, rtx, rtx);
17239 : :
17240 : 7782 : switch (mode)
17241 : : {
17242 : 124 : case E_V2SImode:
17243 : 124 : use_vec_merge = TARGET_MMX_WITH_SSE && TARGET_SSE4_1;
17244 : 124 : if (use_vec_merge)
17245 : : break;
17246 : : /* FALLTHRU */
17247 : :
17248 : 105 : case E_V2SFmode:
17249 : 105 : if (mmx_ok)
17250 : : {
17251 : 105 : tmp = gen_reg_rtx (GET_MODE_INNER (mode));
17252 : 105 : ix86_expand_vector_extract (true, tmp, target, 1 - elt);
17253 : 105 : if (elt == 0)
17254 : 0 : tmp = gen_rtx_VEC_CONCAT (mode, val, tmp);
17255 : : else
17256 : 105 : tmp = gen_rtx_VEC_CONCAT (mode, tmp, val);
17257 : 105 : emit_insn (gen_rtx_SET (target, tmp));
17258 : 105 : return;
17259 : : }
17260 : : break;
17261 : :
17262 : 345 : case E_V2DImode:
17263 : 345 : use_vec_merge = TARGET_SSE4_1 && TARGET_64BIT;
17264 : 345 : if (use_vec_merge)
17265 : : break;
17266 : :
17267 : 239 : tmp = gen_reg_rtx (GET_MODE_INNER (mode));
17268 : 239 : ix86_expand_vector_extract (false, tmp, target, 1 - elt);
17269 : 239 : if (elt == 0)
17270 : 187 : tmp = gen_rtx_VEC_CONCAT (mode, val, tmp);
17271 : : else
17272 : 52 : tmp = gen_rtx_VEC_CONCAT (mode, tmp, val);
17273 : 239 : emit_insn (gen_rtx_SET (target, tmp));
17274 : 239 : return;
17275 : :
17276 : 123 : case E_V2DFmode:
17277 : : /* NB: For ELT == 0, use standard scalar operation patterns which
17278 : : preserve the rest of the vector for combiner:
17279 : :
17280 : : (vec_merge:V2DF
17281 : : (vec_duplicate:V2DF (reg:DF))
17282 : : (reg:V2DF)
17283 : : (const_int 1))
17284 : : */
17285 : 123 : if (elt == 0)
17286 : 47 : goto do_vec_merge;
17287 : :
17288 : 76 : {
17289 : 76 : rtx op0, op1;
17290 : :
17291 : : /* For the two element vectors, we implement a VEC_CONCAT with
17292 : : the extraction of the other element. */
17293 : :
17294 : 76 : tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (1, GEN_INT (1 - elt)));
17295 : 76 : tmp = gen_rtx_VEC_SELECT (inner_mode, target, tmp);
17296 : :
17297 : 76 : if (elt == 0)
17298 : : op0 = val, op1 = tmp;
17299 : : else
17300 : 76 : op0 = tmp, op1 = val;
17301 : :
17302 : 76 : tmp = gen_rtx_VEC_CONCAT (mode, op0, op1);
17303 : 76 : emit_insn (gen_rtx_SET (target, tmp));
17304 : : }
17305 : 76 : return;
17306 : :
17307 : 153 : case E_V4SFmode:
17308 : 153 : use_vec_merge = TARGET_SSE4_1;
17309 : 153 : if (use_vec_merge)
17310 : : break;
17311 : :
17312 : 63 : switch (elt)
17313 : : {
17314 : : case 0:
17315 : : use_vec_merge = true;
17316 : : break;
17317 : :
17318 : 1 : case 1:
17319 : : /* tmp = target = A B C D */
17320 : 1 : tmp = copy_to_reg (target);
17321 : : /* target = A A B B */
17322 : 1 : emit_insn (gen_vec_interleave_lowv4sf (target, target, target));
17323 : : /* target = X A B B */
17324 : 1 : ix86_expand_vector_set (false, target, val, 0);
17325 : : /* target = A X C D */
17326 : 1 : emit_insn (gen_sse_shufps_v4sf (target, target, tmp,
17327 : : const1_rtx, const0_rtx,
17328 : : GEN_INT (2+4), GEN_INT (3+4)));
17329 : 1 : return;
17330 : :
17331 : 0 : case 2:
17332 : : /* tmp = target = A B C D */
17333 : 0 : tmp = copy_to_reg (target);
17334 : : /* tmp = X B C D */
17335 : 0 : ix86_expand_vector_set (false, tmp, val, 0);
17336 : : /* target = A B X D */
17337 : 0 : emit_insn (gen_sse_shufps_v4sf (target, target, tmp,
17338 : : const0_rtx, const1_rtx,
17339 : : GEN_INT (0+4), GEN_INT (3+4)));
17340 : 0 : return;
17341 : :
17342 : 5 : case 3:
17343 : : /* tmp = target = A B C D */
17344 : 5 : tmp = copy_to_reg (target);
17345 : : /* tmp = X B C D */
17346 : 5 : ix86_expand_vector_set (false, tmp, val, 0);
17347 : : /* target = A B X D */
17348 : 5 : emit_insn (gen_sse_shufps_v4sf (target, target, tmp,
17349 : : const0_rtx, const1_rtx,
17350 : : GEN_INT (2+4), GEN_INT (0+4)));
17351 : 5 : return;
17352 : :
17353 : 0 : default:
17354 : 0 : gcc_unreachable ();
17355 : : }
17356 : : break;
17357 : :
17358 : 447 : case E_V4SImode:
17359 : 447 : use_vec_merge = TARGET_SSE4_1;
17360 : 447 : if (use_vec_merge)
17361 : : break;
17362 : :
17363 : : /* Element 0 handled by vec_merge below. */
17364 : 223 : if (elt == 0)
17365 : : {
17366 : : use_vec_merge = true;
17367 : : break;
17368 : : }
17369 : :
17370 : 70 : if (TARGET_SSE2)
17371 : : {
17372 : : /* With SSE2, use integer shuffles to swap element 0 and ELT,
17373 : : store into element 0, then shuffle them back. */
17374 : :
17375 : 70 : rtx order[4];
17376 : :
17377 : 70 : order[0] = GEN_INT (elt);
17378 : 70 : order[1] = const1_rtx;
17379 : 70 : order[2] = const2_rtx;
17380 : 70 : order[3] = GEN_INT (3);
17381 : 70 : order[elt] = const0_rtx;
17382 : :
17383 : 70 : emit_insn (gen_sse2_pshufd_1 (target, target, order[0],
17384 : : order[1], order[2], order[3]));
17385 : :
17386 : 70 : ix86_expand_vector_set (false, target, val, 0);
17387 : :
17388 : 70 : emit_insn (gen_sse2_pshufd_1 (target, target, order[0],
17389 : : order[1], order[2], order[3]));
17390 : : }
17391 : : else
17392 : : {
17393 : : /* For SSE1, we have to reuse the V4SF code. */
17394 : 0 : rtx t = gen_reg_rtx (V4SFmode);
17395 : 0 : emit_move_insn (t, gen_lowpart (V4SFmode, target));
17396 : 0 : ix86_expand_vector_set (false, t, gen_lowpart (SFmode, val), elt);
17397 : 0 : emit_move_insn (target, gen_lowpart (mode, t));
17398 : : }
17399 : : return;
17400 : :
17401 : 3439 : case E_V8HImode:
17402 : 3439 : case E_V8HFmode:
17403 : 3439 : case E_V8BFmode:
17404 : 3439 : case E_V2HImode:
17405 : 3439 : case E_V2HFmode:
17406 : 3439 : case E_V2BFmode:
17407 : 3439 : use_vec_merge = TARGET_SSE2;
17408 : 3439 : break;
17409 : 51 : case E_V4HImode:
17410 : 51 : case E_V4HFmode:
17411 : 51 : case E_V4BFmode:
17412 : 51 : use_vec_merge = mmx_ok && (TARGET_SSE || TARGET_3DNOW_A);
17413 : : break;
17414 : :
17415 : 2982 : case E_V16QImode:
17416 : 2982 : case E_V4QImode:
17417 : 2982 : use_vec_merge = TARGET_SSE4_1;
17418 : 2982 : break;
17419 : :
17420 : 0 : case E_V8QImode:
17421 : 0 : use_vec_merge = TARGET_MMX_WITH_SSE && TARGET_SSE4_1;
17422 : 0 : break;
17423 : :
17424 : 3 : case E_V32QImode:
17425 : 3 : half_mode = V16QImode;
17426 : 3 : j = 0;
17427 : 3 : n = 16;
17428 : 3 : goto half;
17429 : :
17430 : 17 : case E_V16HFmode:
17431 : 17 : case E_V16BFmode:
17432 : : /* For ELT == 0, vec_setv8hf_0 can save 1 vpbroadcastw. */
17433 : 17 : if (TARGET_AVX2 && elt != 0)
17434 : : {
17435 : 12 : mmode = SImode;
17436 : 12 : gen_blendm = ((mode == E_V16HFmode) ? gen_avx2_pblendph_1
17437 : : : gen_avx2_pblendbf_1);
17438 : : blendm_const = true;
17439 : : break;
17440 : : }
17441 : : else
17442 : : {
17443 : 5 : half_mode = ((mode == E_V16HFmode) ? V8HFmode : V8BFmode);
17444 : 3 : j = ((mode == E_V16HFmode) ? 6 : 7);
17445 : 5 : n = 8;
17446 : 5 : goto half;
17447 : : }
17448 : :
17449 : 5 : case E_V16HImode:
17450 : 5 : half_mode = V8HImode;
17451 : 5 : j = 1;
17452 : 5 : n = 8;
17453 : 5 : goto half;
17454 : :
17455 : 13 : case E_V8SImode:
17456 : 13 : half_mode = V4SImode;
17457 : 13 : j = 2;
17458 : 13 : n = 4;
17459 : 13 : goto half;
17460 : :
17461 : 10 : case E_V4DImode:
17462 : 10 : half_mode = V2DImode;
17463 : 10 : j = 3;
17464 : 10 : n = 2;
17465 : 10 : goto half;
17466 : :
17467 : 4 : case E_V8SFmode:
17468 : 4 : half_mode = V4SFmode;
17469 : 4 : j = 4;
17470 : 4 : n = 4;
17471 : 4 : goto half;
17472 : :
17473 : 6 : case E_V4DFmode:
17474 : 6 : half_mode = V2DFmode;
17475 : 6 : j = 5;
17476 : 6 : n = 2;
17477 : 6 : goto half;
17478 : :
17479 : 46 : half:
17480 : : /* Compute offset. */
17481 : 46 : i = elt / n;
17482 : 46 : elt %= n;
17483 : :
17484 : 46 : gcc_assert (i <= 1);
17485 : :
17486 : : /* Extract the half. */
17487 : 46 : tmp = gen_reg_rtx (half_mode);
17488 : 46 : emit_insn (gen_extract[j][i] (tmp, target));
17489 : :
17490 : : /* Put val in tmp at elt. */
17491 : 46 : ix86_expand_vector_set (false, tmp, val, elt);
17492 : :
17493 : : /* Put it back. */
17494 : 46 : emit_insn (gen_insert[j][i] (target, target, tmp));
17495 : 46 : return;
17496 : :
17497 : 8 : case E_V8DFmode:
17498 : 8 : if (TARGET_AVX512F)
17499 : : {
17500 : 7182 : mmode = QImode;
17501 : 7182 : gen_blendm = gen_avx512f_blendmv8df;
17502 : : }
17503 : : break;
17504 : :
17505 : 0 : case E_V8DImode:
17506 : 0 : if (TARGET_AVX512F)
17507 : : {
17508 : 7182 : mmode = QImode;
17509 : 7182 : gen_blendm = gen_avx512f_blendmv8di;
17510 : : }
17511 : : break;
17512 : :
17513 : 0 : case E_V16SFmode:
17514 : 0 : if (TARGET_AVX512F)
17515 : : {
17516 : 7182 : mmode = HImode;
17517 : 7182 : gen_blendm = gen_avx512f_blendmv16sf;
17518 : : }
17519 : : break;
17520 : :
17521 : 0 : case E_V16SImode:
17522 : 0 : if (TARGET_AVX512F)
17523 : : {
17524 : 7182 : mmode = HImode;
17525 : 7182 : gen_blendm = gen_avx512f_blendmv16si;
17526 : : }
17527 : : break;
17528 : :
17529 : 12 : case E_V32HFmode:
17530 : 12 : if (TARGET_AVX512BW)
17531 : : {
17532 : 7182 : mmode = SImode;
17533 : 7182 : gen_blendm = gen_avx512bw_blendmv32hf;
17534 : : }
17535 : : break;
17536 : 12 : case E_V32BFmode:
17537 : 12 : if (TARGET_AVX512BW)
17538 : : {
17539 : 7182 : mmode = SImode;
17540 : 7182 : gen_blendm = gen_avx512bw_blendmv32bf;
17541 : : }
17542 : : break;
17543 : 9 : case E_V32HImode:
17544 : 9 : if (TARGET_AVX512BW)
17545 : : {
17546 : : mmode = SImode;
17547 : : gen_blendm = gen_avx512bw_blendmv32hi;
17548 : : }
17549 : 5 : else if (TARGET_AVX512F)
17550 : : {
17551 : 5 : half_mode = E_V8HImode;
17552 : 5 : n = 8;
17553 : 5 : goto quarter;
17554 : : }
17555 : : break;
17556 : :
17557 : 12 : case E_V64QImode:
17558 : 12 : if (TARGET_AVX512BW)
17559 : : {
17560 : : mmode = DImode;
17561 : : gen_blendm = gen_avx512bw_blendmv64qi;
17562 : : }
17563 : 6 : else if (TARGET_AVX512F)
17564 : : {
17565 : 6 : half_mode = E_V16QImode;
17566 : 6 : n = 16;
17567 : 6 : goto quarter;
17568 : : }
17569 : : break;
17570 : :
17571 : 11 : quarter:
17572 : : /* Compute offset. */
17573 : 11 : i = elt / n;
17574 : 11 : elt %= n;
17575 : :
17576 : 11 : gcc_assert (i <= 3);
17577 : :
17578 : 11 : {
17579 : : /* Extract the quarter. */
17580 : 11 : tmp = gen_reg_rtx (V4SImode);
17581 : 11 : rtx tmp2 = gen_lowpart (V16SImode, target);
17582 : 11 : rtx mask = gen_reg_rtx (QImode);
17583 : :
17584 : 11 : emit_move_insn (mask, constm1_rtx);
17585 : 11 : emit_insn (gen_avx512f_vextracti32x4_mask (tmp, tmp2, GEN_INT (i),
17586 : : tmp, mask));
17587 : :
17588 : 11 : tmp2 = gen_reg_rtx (half_mode);
17589 : 11 : emit_move_insn (tmp2, gen_lowpart (half_mode, tmp));
17590 : 11 : tmp = tmp2;
17591 : :
17592 : : /* Put val in tmp at elt. */
17593 : 11 : ix86_expand_vector_set (false, tmp, val, elt);
17594 : :
17595 : : /* Put it back. */
17596 : 11 : tmp2 = gen_reg_rtx (V16SImode);
17597 : 11 : rtx tmp3 = gen_lowpart (V16SImode, target);
17598 : 11 : mask = gen_reg_rtx (HImode);
17599 : 11 : emit_move_insn (mask, constm1_rtx);
17600 : 11 : tmp = gen_lowpart (V4SImode, tmp);
17601 : 11 : emit_insn (gen_avx512f_vinserti32x4_mask (tmp2, tmp3, tmp, GEN_INT (i),
17602 : : tmp3, mask));
17603 : 11 : emit_move_insn (target, gen_lowpart (mode, tmp2));
17604 : : }
17605 : 11 : return;
17606 : :
17607 : : default:
17608 : : break;
17609 : : }
17610 : :
17611 : 7182 : if (mmode != VOIDmode)
17612 : : {
17613 : 48 : tmp = gen_reg_rtx (mode);
17614 : 48 : emit_insn (gen_rtx_SET (tmp, gen_rtx_VEC_DUPLICATE (mode, val)));
17615 : 48 : rtx merge_mask = gen_int_mode (HOST_WIDE_INT_1U << elt, mmode);
17616 : : /* The avx512*_blendm<mode> expanders have different operand order
17617 : : from VEC_MERGE. In VEC_MERGE, the first input operand is used for
17618 : : elements where the mask is set and second input operand otherwise,
17619 : : in {sse,avx}*_*blend* the first input operand is used for elements
17620 : : where the mask is clear and second input operand otherwise. */
17621 : 48 : if (!blendm_const)
17622 : 36 : merge_mask = force_reg (mmode, merge_mask);
17623 : 48 : emit_insn (gen_blendm (target, target, tmp, merge_mask));
17624 : : }
17625 : 7134 : else if (use_vec_merge)
17626 : : {
17627 : 7121 : do_vec_merge:
17628 : 7168 : tmp = gen_rtx_VEC_DUPLICATE (mode, val);
17629 : 7168 : tmp = gen_rtx_VEC_MERGE (mode, tmp, target,
17630 : : GEN_INT (HOST_WIDE_INT_1U << elt));
17631 : 7168 : emit_insn (gen_rtx_SET (target, tmp));
17632 : : }
17633 : : else
17634 : : {
17635 : 26 : rtx mem = assign_stack_temp (mode, GET_MODE_SIZE (mode));
17636 : :
17637 : 13 : emit_move_insn (mem, target);
17638 : :
17639 : 26 : tmp = adjust_address (mem, inner_mode, elt * GET_MODE_SIZE (inner_mode));
17640 : 13 : emit_move_insn (tmp, val);
17641 : :
17642 : 13 : emit_move_insn (target, mem);
17643 : : }
17644 : : }
17645 : :
17646 : : void
17647 : 97774 : ix86_expand_vector_extract (bool mmx_ok, rtx target, rtx vec, int elt)
17648 : : {
17649 : 97774 : machine_mode mode = GET_MODE (vec);
17650 : 97774 : machine_mode inner_mode = GET_MODE_INNER (mode);
17651 : 97774 : bool use_vec_extr = false;
17652 : 97774 : rtx tmp;
17653 : :
17654 : 97774 : switch (mode)
17655 : : {
17656 : 10426 : case E_V2SImode:
17657 : 10426 : use_vec_extr = TARGET_MMX_WITH_SSE && TARGET_SSE4_1;
17658 : 10426 : if (use_vec_extr)
17659 : : break;
17660 : : /* FALLTHRU */
17661 : :
17662 : 11091 : case E_V2SFmode:
17663 : 11091 : if (!mmx_ok)
17664 : : break;
17665 : : /* FALLTHRU */
17666 : :
17667 : : case E_V2DFmode:
17668 : : case E_V2DImode:
17669 : : case E_V2TImode:
17670 : : case E_V4TImode:
17671 : 50884 : use_vec_extr = true;
17672 : : break;
17673 : :
17674 : 7901 : case E_V4SFmode:
17675 : 7901 : use_vec_extr = TARGET_SSE4_1;
17676 : 7901 : if (use_vec_extr)
17677 : : break;
17678 : :
17679 : 4035 : switch (elt)
17680 : : {
17681 : : case 0:
17682 : : tmp = vec;
17683 : : break;
17684 : :
17685 : 1650 : case 1:
17686 : 1650 : case 3:
17687 : 1650 : tmp = gen_reg_rtx (mode);
17688 : 1650 : emit_insn (gen_sse_shufps_v4sf (tmp, vec, vec,
17689 : : GEN_INT (elt), GEN_INT (elt),
17690 : 1650 : GEN_INT (elt+4), GEN_INT (elt+4)));
17691 : 1650 : break;
17692 : :
17693 : 965 : case 2:
17694 : 965 : tmp = gen_reg_rtx (mode);
17695 : 965 : emit_insn (gen_vec_interleave_highv4sf (tmp, vec, vec));
17696 : 965 : break;
17697 : :
17698 : 0 : default:
17699 : 0 : gcc_unreachable ();
17700 : : }
17701 : : vec = tmp;
17702 : : use_vec_extr = true;
17703 : : elt = 0;
17704 : : break;
17705 : :
17706 : 19102 : case E_V4SImode:
17707 : 19102 : use_vec_extr = TARGET_SSE4_1;
17708 : 19102 : if (use_vec_extr)
17709 : : break;
17710 : :
17711 : 12156 : if (TARGET_SSE2)
17712 : : {
17713 : 12152 : switch (elt)
17714 : : {
17715 : : case 0:
17716 : : tmp = vec;
17717 : : break;
17718 : :
17719 : 4964 : case 1:
17720 : 4964 : case 3:
17721 : 4964 : tmp = gen_reg_rtx (mode);
17722 : 4964 : emit_insn (gen_sse2_pshufd_1 (tmp, vec,
17723 : : GEN_INT (elt), GEN_INT (elt),
17724 : : GEN_INT (elt), GEN_INT (elt)));
17725 : 4964 : break;
17726 : :
17727 : 2439 : case 2:
17728 : 2439 : tmp = gen_reg_rtx (mode);
17729 : 2439 : emit_insn (gen_vec_interleave_highv4si (tmp, vec, vec));
17730 : 2439 : break;
17731 : :
17732 : 0 : default:
17733 : 0 : gcc_unreachable ();
17734 : : }
17735 : : vec = tmp;
17736 : : use_vec_extr = true;
17737 : : elt = 0;
17738 : : }
17739 : : else
17740 : : {
17741 : : /* For SSE1, we have to reuse the V4SF code. */
17742 : 4 : ix86_expand_vector_extract (false, gen_lowpart (SFmode, target),
17743 : 4 : gen_lowpart (V4SFmode, vec), elt);
17744 : 4 : return;
17745 : : }
17746 : : break;
17747 : :
17748 : 6087 : case E_V8HImode:
17749 : 6087 : case E_V8HFmode:
17750 : 6087 : case E_V8BFmode:
17751 : 6087 : case E_V2HImode:
17752 : 6087 : case E_V2HFmode:
17753 : 6087 : case E_V2BFmode:
17754 : 6087 : use_vec_extr = TARGET_SSE2;
17755 : 6087 : break;
17756 : 623 : case E_V4HImode:
17757 : 623 : case E_V4HFmode:
17758 : 623 : case E_V4BFmode:
17759 : 623 : use_vec_extr = mmx_ok && (TARGET_SSE || TARGET_3DNOW_A);
17760 : : break;
17761 : :
17762 : 5230 : case E_V16QImode:
17763 : 5230 : use_vec_extr = TARGET_SSE4_1;
17764 : 5230 : if (!use_vec_extr
17765 : 3605 : && TARGET_SSE2
17766 : 3605 : && elt == 0
17767 : 5771 : && (optimize_insn_for_size_p () || TARGET_INTER_UNIT_MOVES_FROM_VEC))
17768 : : {
17769 : 540 : tmp = gen_reg_rtx (SImode);
17770 : 540 : ix86_expand_vector_extract (false, tmp, gen_lowpart (V4SImode, vec),
17771 : : 0);
17772 : 540 : emit_insn (gen_rtx_SET (target, gen_lowpart (QImode, tmp)));
17773 : 540 : return;
17774 : : }
17775 : : break;
17776 : 28 : case E_V4QImode:
17777 : 28 : use_vec_extr = TARGET_SSE4_1;
17778 : 28 : break;
17779 : :
17780 : 643 : case E_V8SFmode:
17781 : 643 : if (TARGET_AVX)
17782 : : {
17783 : 643 : tmp = gen_reg_rtx (V4SFmode);
17784 : 643 : if (elt < 4)
17785 : 317 : emit_insn (gen_vec_extract_lo_v8sf (tmp, vec));
17786 : : else
17787 : 326 : emit_insn (gen_vec_extract_hi_v8sf (tmp, vec));
17788 : 643 : ix86_expand_vector_extract (false, target, tmp, elt & 3);
17789 : 643 : return;
17790 : : }
17791 : : break;
17792 : :
17793 : 185 : case E_V4DFmode:
17794 : 185 : if (TARGET_AVX)
17795 : : {
17796 : 185 : tmp = gen_reg_rtx (V2DFmode);
17797 : 185 : if (elt < 2)
17798 : 101 : emit_insn (gen_vec_extract_lo_v4df (tmp, vec));
17799 : : else
17800 : 84 : emit_insn (gen_vec_extract_hi_v4df (tmp, vec));
17801 : 185 : ix86_expand_vector_extract (false, target, tmp, elt & 1);
17802 : 185 : return;
17803 : : }
17804 : : break;
17805 : :
17806 : 190 : case E_V32QImode:
17807 : 190 : if (TARGET_AVX)
17808 : : {
17809 : 190 : tmp = gen_reg_rtx (V16QImode);
17810 : 190 : if (elt < 16)
17811 : 99 : emit_insn (gen_vec_extract_lo_v32qi (tmp, vec));
17812 : : else
17813 : 91 : emit_insn (gen_vec_extract_hi_v32qi (tmp, vec));
17814 : 190 : ix86_expand_vector_extract (false, target, tmp, elt & 15);
17815 : 190 : return;
17816 : : }
17817 : : break;
17818 : :
17819 : 586 : case E_V16HImode:
17820 : 586 : if (TARGET_AVX)
17821 : : {
17822 : 586 : tmp = gen_reg_rtx (V8HImode);
17823 : 586 : if (elt < 8)
17824 : 546 : emit_insn (gen_vec_extract_lo_v16hi (tmp, vec));
17825 : : else
17826 : 40 : emit_insn (gen_vec_extract_hi_v16hi (tmp, vec));
17827 : 586 : ix86_expand_vector_extract (false, target, tmp, elt & 7);
17828 : 586 : return;
17829 : : }
17830 : : break;
17831 : :
17832 : 1648 : case E_V8SImode:
17833 : 1648 : if (TARGET_AVX)
17834 : : {
17835 : 1648 : tmp = gen_reg_rtx (V4SImode);
17836 : 1648 : if (elt < 4)
17837 : 1184 : emit_insn (gen_vec_extract_lo_v8si (tmp, vec));
17838 : : else
17839 : 464 : emit_insn (gen_vec_extract_hi_v8si (tmp, vec));
17840 : 1648 : ix86_expand_vector_extract (false, target, tmp, elt & 3);
17841 : 1648 : return;
17842 : : }
17843 : : break;
17844 : :
17845 : 1669 : case E_V4DImode:
17846 : 1669 : if (TARGET_AVX)
17847 : : {
17848 : 1669 : tmp = gen_reg_rtx (V2DImode);
17849 : 1669 : if (elt < 2)
17850 : 1064 : emit_insn (gen_vec_extract_lo_v4di (tmp, vec));
17851 : : else
17852 : 605 : emit_insn (gen_vec_extract_hi_v4di (tmp, vec));
17853 : 1669 : ix86_expand_vector_extract (false, target, tmp, elt & 1);
17854 : 1669 : return;
17855 : : }
17856 : : break;
17857 : :
17858 : 10 : case E_V32HImode:
17859 : 10 : if (TARGET_AVX512BW)
17860 : : {
17861 : 10 : tmp = gen_reg_rtx (V16HImode);
17862 : 10 : if (elt < 16)
17863 : 5 : emit_insn (gen_vec_extract_lo_v32hi (tmp, vec));
17864 : : else
17865 : 5 : emit_insn (gen_vec_extract_hi_v32hi (tmp, vec));
17866 : 10 : ix86_expand_vector_extract (false, target, tmp, elt & 15);
17867 : 10 : return;
17868 : : }
17869 : : break;
17870 : :
17871 : 12 : case E_V64QImode:
17872 : 12 : if (TARGET_AVX512BW)
17873 : : {
17874 : 12 : tmp = gen_reg_rtx (V32QImode);
17875 : 12 : if (elt < 32)
17876 : 6 : emit_insn (gen_vec_extract_lo_v64qi (tmp, vec));
17877 : : else
17878 : 6 : emit_insn (gen_vec_extract_hi_v64qi (tmp, vec));
17879 : 12 : ix86_expand_vector_extract (false, target, tmp, elt & 31);
17880 : 12 : return;
17881 : : }
17882 : : break;
17883 : :
17884 : 183 : case E_V16SFmode:
17885 : 183 : tmp = gen_reg_rtx (V8SFmode);
17886 : 183 : if (elt < 8)
17887 : 93 : emit_insn (gen_vec_extract_lo_v16sf (tmp, vec));
17888 : : else
17889 : 90 : emit_insn (gen_vec_extract_hi_v16sf (tmp, vec));
17890 : 183 : ix86_expand_vector_extract (false, target, tmp, elt & 7);
17891 : 183 : return;
17892 : :
17893 : 22 : case E_V8DFmode:
17894 : 22 : tmp = gen_reg_rtx (V4DFmode);
17895 : 22 : if (elt < 4)
17896 : 18 : emit_insn (gen_vec_extract_lo_v8df (tmp, vec));
17897 : : else
17898 : 4 : emit_insn (gen_vec_extract_hi_v8df (tmp, vec));
17899 : 22 : ix86_expand_vector_extract (false, target, tmp, elt & 3);
17900 : 22 : return;
17901 : :
17902 : 421 : case E_V16SImode:
17903 : 421 : tmp = gen_reg_rtx (V8SImode);
17904 : 421 : if (elt < 8)
17905 : 285 : emit_insn (gen_vec_extract_lo_v16si (tmp, vec));
17906 : : else
17907 : 136 : emit_insn (gen_vec_extract_hi_v16si (tmp, vec));
17908 : 421 : ix86_expand_vector_extract (false, target, tmp, elt & 7);
17909 : 421 : return;
17910 : :
17911 : 772 : case E_V8DImode:
17912 : 772 : tmp = gen_reg_rtx (V4DImode);
17913 : 772 : if (elt < 4)
17914 : 531 : emit_insn (gen_vec_extract_lo_v8di (tmp, vec));
17915 : : else
17916 : 241 : emit_insn (gen_vec_extract_hi_v8di (tmp, vec));
17917 : 772 : ix86_expand_vector_extract (false, target, tmp, elt & 3);
17918 : 772 : return;
17919 : :
17920 : 45 : case E_V32HFmode:
17921 : 45 : case E_V32BFmode:
17922 : 45 : if (TARGET_AVX512BW)
17923 : : {
17924 : 90 : tmp = (mode == E_V32HFmode
17925 : 45 : ? gen_reg_rtx (V16HFmode)
17926 : 7 : : gen_reg_rtx (V16BFmode));
17927 : 45 : if (elt < 16)
17928 : 31 : emit_insn (gen_vec_extract_lo (mode, tmp, vec));
17929 : : else
17930 : 14 : emit_insn (gen_vec_extract_hi (mode, tmp, vec));
17931 : 45 : ix86_expand_vector_extract (false, target, tmp, elt & 15);
17932 : 45 : return;
17933 : : }
17934 : : break;
17935 : :
17936 : 394 : case E_V16HFmode:
17937 : 394 : case E_V16BFmode:
17938 : 394 : if (TARGET_AVX)
17939 : : {
17940 : 788 : tmp = (mode == E_V16HFmode
17941 : 394 : ? gen_reg_rtx (V8HFmode)
17942 : 291 : : gen_reg_rtx (V8BFmode));
17943 : 394 : if (elt < 8)
17944 : 209 : emit_insn (gen_vec_extract_lo (mode, tmp, vec));
17945 : : else
17946 : 185 : emit_insn (gen_vec_extract_hi (mode, tmp, vec));
17947 : 394 : ix86_expand_vector_extract (false, target, tmp, elt & 7);
17948 : 394 : return;
17949 : : }
17950 : : break;
17951 : :
17952 : 494 : case E_V8QImode:
17953 : 494 : use_vec_extr = TARGET_MMX_WITH_SSE && TARGET_SSE4_1;
17954 : : /* ??? Could extract the appropriate HImode element and shift. */
17955 : 494 : break;
17956 : :
17957 : : default:
17958 : : break;
17959 : : }
17960 : :
17961 : 90450 : if (use_vec_extr)
17962 : : {
17963 : 79562 : tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (1, GEN_INT (elt)));
17964 : 79562 : tmp = gen_rtx_VEC_SELECT (inner_mode, vec, tmp);
17965 : :
17966 : : /* Let the rtl optimizers know about the zero extension performed. */
17967 : 79562 : if (inner_mode == QImode || inner_mode == HImode)
17968 : : {
17969 : 7909 : rtx reg = gen_reg_rtx (SImode);
17970 : 7909 : tmp = gen_rtx_ZERO_EXTEND (SImode, tmp);
17971 : 7909 : emit_move_insn (reg, tmp);
17972 : 7909 : tmp = gen_lowpart (inner_mode, reg);
17973 : 7909 : SUBREG_PROMOTED_VAR_P (tmp) = 1;
17974 : 7909 : SUBREG_PROMOTED_SET (tmp, 1);
17975 : : }
17976 : :
17977 : 79562 : emit_move_insn (target, tmp);
17978 : : }
17979 : : else
17980 : : {
17981 : 21776 : rtx mem = assign_stack_temp (mode, GET_MODE_SIZE (mode));
17982 : :
17983 : 10888 : emit_move_insn (mem, vec);
17984 : :
17985 : 21776 : tmp = adjust_address (mem, inner_mode, elt*GET_MODE_SIZE (inner_mode));
17986 : 10888 : emit_move_insn (target, tmp);
17987 : : }
17988 : : }
17989 : :
17990 : : /* Generate code to copy vector bits i / 2 ... i - 1 from vector SRC
17991 : : to bits 0 ... i / 2 - 1 of vector DEST, which has the same mode.
17992 : : The upper bits of DEST are undefined, though they shouldn't cause
17993 : : exceptions (some bits from src or all zeros are ok). */
17994 : :
17995 : : static void
17996 : 25272 : emit_reduc_half (rtx dest, rtx src, int i)
17997 : : {
17998 : 25272 : rtx tem, d = dest;
17999 : 25272 : switch (GET_MODE (src))
18000 : : {
18001 : 5556 : case E_V4SFmode:
18002 : 5556 : if (i == 128)
18003 : 2778 : tem = gen_sse_movhlps (dest, src, src);
18004 : : else
18005 : 2778 : tem = gen_sse_shufps_v4sf (dest, src, src, const1_rtx, const1_rtx,
18006 : : GEN_INT (1 + 4), GEN_INT (1 + 4));
18007 : : break;
18008 : 2924 : case E_V2DFmode:
18009 : 2924 : tem = gen_vec_interleave_highv2df (dest, src, src);
18010 : 2924 : break;
18011 : 54 : case E_V4QImode:
18012 : 54 : d = gen_reg_rtx (V1SImode);
18013 : 54 : tem = gen_mmx_lshrv1si3 (d, gen_lowpart (V1SImode, src),
18014 : 54 : GEN_INT (i / 2));
18015 : 54 : break;
18016 : 519 : case E_V8QImode:
18017 : 519 : case E_V4HImode:
18018 : 519 : d = gen_reg_rtx (V1DImode);
18019 : 519 : tem = gen_mmx_lshrv1di3 (d, gen_lowpart (V1DImode, src),
18020 : 519 : GEN_INT (i / 2));
18021 : 519 : break;
18022 : 16219 : case E_V16QImode:
18023 : 16219 : case E_V8HImode:
18024 : 16219 : case E_V8HFmode:
18025 : 16219 : case E_V4SImode:
18026 : 16219 : case E_V2DImode:
18027 : 16219 : d = gen_reg_rtx (V1TImode);
18028 : 16219 : tem = gen_sse2_lshrv1ti3 (d, gen_lowpart (V1TImode, src),
18029 : 16219 : GEN_INT (i / 2));
18030 : 16219 : break;
18031 : 0 : case E_V8SFmode:
18032 : 0 : if (i == 256)
18033 : 0 : tem = gen_avx_vperm2f128v8sf3 (dest, src, src, const1_rtx);
18034 : : else
18035 : 0 : tem = gen_avx_shufps256 (dest, src, src,
18036 : : GEN_INT (i == 128 ? 2 + (3 << 2) : 1));
18037 : : break;
18038 : 0 : case E_V4DFmode:
18039 : 0 : if (i == 256)
18040 : 0 : tem = gen_avx_vperm2f128v4df3 (dest, src, src, const1_rtx);
18041 : : else
18042 : 0 : tem = gen_avx_shufpd256 (dest, src, src, const1_rtx);
18043 : : break;
18044 : 0 : case E_V32QImode:
18045 : 0 : case E_V16HImode:
18046 : 0 : case E_V16HFmode:
18047 : 0 : case E_V8SImode:
18048 : 0 : case E_V4DImode:
18049 : 0 : if (i == 256)
18050 : : {
18051 : 0 : if (GET_MODE (dest) != V4DImode)
18052 : 0 : d = gen_reg_rtx (V4DImode);
18053 : 0 : tem = gen_avx2_permv2ti (d, gen_lowpart (V4DImode, src),
18054 : 0 : gen_lowpart (V4DImode, src),
18055 : : const1_rtx);
18056 : : }
18057 : : else
18058 : : {
18059 : 0 : d = gen_reg_rtx (V2TImode);
18060 : 0 : tem = gen_avx2_lshrv2ti3 (d, gen_lowpart (V2TImode, src),
18061 : 0 : GEN_INT (i / 2));
18062 : : }
18063 : : break;
18064 : 0 : case E_V64QImode:
18065 : 0 : case E_V32HImode:
18066 : 0 : case E_V32HFmode:
18067 : 0 : if (i < 64)
18068 : : {
18069 : 0 : d = gen_reg_rtx (V4TImode);
18070 : 0 : tem = gen_avx512bw_lshrv4ti3 (d, gen_lowpart (V4TImode, src),
18071 : 0 : GEN_INT (i / 2));
18072 : 0 : break;
18073 : : }
18074 : : /* FALLTHRU */
18075 : 0 : case E_V16SImode:
18076 : 0 : case E_V16SFmode:
18077 : 0 : case E_V8DImode:
18078 : 0 : case E_V8DFmode:
18079 : 0 : if (i > 128)
18080 : 0 : tem = gen_avx512f_shuf_i32x4_1 (gen_lowpart (V16SImode, dest),
18081 : 0 : gen_lowpart (V16SImode, src),
18082 : 0 : gen_lowpart (V16SImode, src),
18083 : : GEN_INT (0x4 + (i == 512 ? 4 : 0)),
18084 : : GEN_INT (0x5 + (i == 512 ? 4 : 0)),
18085 : : GEN_INT (0x6 + (i == 512 ? 4 : 0)),
18086 : : GEN_INT (0x7 + (i == 512 ? 4 : 0)),
18087 : : GEN_INT (0xC), GEN_INT (0xD),
18088 : : GEN_INT (0xE), GEN_INT (0xF),
18089 : : GEN_INT (0x10), GEN_INT (0x11),
18090 : : GEN_INT (0x12), GEN_INT (0x13),
18091 : : GEN_INT (0x14), GEN_INT (0x15),
18092 : : GEN_INT (0x16), GEN_INT (0x17));
18093 : : else
18094 : 0 : tem = gen_avx512f_pshufd_1 (gen_lowpart (V16SImode, dest),
18095 : 0 : gen_lowpart (V16SImode, src),
18096 : : GEN_INT (i == 128 ? 0x2 : 0x1),
18097 : : GEN_INT (0x3),
18098 : : GEN_INT (0x3),
18099 : : GEN_INT (0x3),
18100 : : GEN_INT (i == 128 ? 0x6 : 0x5),
18101 : : GEN_INT (0x7),
18102 : : GEN_INT (0x7),
18103 : : GEN_INT (0x7),
18104 : : GEN_INT (i == 128 ? 0xA : 0x9),
18105 : : GEN_INT (0xB),
18106 : : GEN_INT (0xB),
18107 : : GEN_INT (0xB),
18108 : : GEN_INT (i == 128 ? 0xE : 0xD),
18109 : : GEN_INT (0xF),
18110 : : GEN_INT (0xF),
18111 : : GEN_INT (0xF));
18112 : : break;
18113 : 0 : default:
18114 : 0 : gcc_unreachable ();
18115 : : }
18116 : 25272 : emit_insn (tem);
18117 : 25272 : if (d != dest)
18118 : 16792 : emit_move_insn (dest, gen_lowpart (GET_MODE (dest), d));
18119 : 25272 : }
18120 : :
18121 : : /* Expand a vector reduction. FN is the binary pattern to reduce;
18122 : : DEST is the destination; IN is the input vector. */
18123 : :
18124 : : void
18125 : 15687 : ix86_expand_reduc (rtx (*fn) (rtx, rtx, rtx), rtx dest, rtx in)
18126 : : {
18127 : 15687 : rtx half, dst, vec = in;
18128 : 15687 : machine_mode mode = GET_MODE (in);
18129 : 15687 : int i;
18130 : :
18131 : : /* SSE4 has a special instruction for V8HImode UMIN reduction. */
18132 : 15687 : if (TARGET_SSE4_1
18133 : 8990 : && mode == V8HImode
18134 : 756 : && fn == gen_uminv8hi3)
18135 : : {
18136 : 4 : emit_insn (gen_sse4_1_phminposuw (dest, in));
18137 : 4 : return;
18138 : : }
18139 : :
18140 : 31366 : for (i = GET_MODE_BITSIZE (mode);
18141 : 81910 : i > GET_MODE_UNIT_BITSIZE (mode);
18142 : 25272 : i >>= 1)
18143 : : {
18144 : 25272 : half = gen_reg_rtx (mode);
18145 : 25272 : emit_reduc_half (half, vec, i);
18146 : 50544 : if (i == GET_MODE_UNIT_BITSIZE (mode) * 2)
18147 : : dst = dest;
18148 : : else
18149 : 9589 : dst = gen_reg_rtx (mode);
18150 : 25272 : emit_insn (fn (dst, half, vec));
18151 : 25272 : vec = dst;
18152 : : }
18153 : : }
18154 : :
18155 : : /* Output code to perform a conditional jump to LABEL, if C2 flag in
18156 : : FP status register is set. */
18157 : :
18158 : : void
18159 : 279 : ix86_emit_fp_unordered_jump (rtx label)
18160 : : {
18161 : 279 : rtx reg = gen_reg_rtx (HImode);
18162 : 279 : rtx_insn *insn;
18163 : 279 : rtx temp;
18164 : :
18165 : 279 : emit_insn (gen_x86_fnstsw_1 (reg));
18166 : :
18167 : 279 : if (TARGET_SAHF && (TARGET_USE_SAHF || optimize_insn_for_size_p ()))
18168 : : {
18169 : 37 : emit_insn (gen_x86_sahf_1 (reg));
18170 : :
18171 : 37 : temp = gen_rtx_REG (CCmode, FLAGS_REG);
18172 : 37 : temp = gen_rtx_UNORDERED (VOIDmode, temp, const0_rtx);
18173 : : }
18174 : : else
18175 : : {
18176 : 242 : emit_insn (gen_testqi_ext_1_ccno (reg, GEN_INT (0x04)));
18177 : :
18178 : 242 : temp = gen_rtx_REG (CCNOmode, FLAGS_REG);
18179 : 242 : temp = gen_rtx_NE (VOIDmode, temp, const0_rtx);
18180 : : }
18181 : :
18182 : 279 : temp = gen_rtx_IF_THEN_ELSE (VOIDmode, temp,
18183 : : gen_rtx_LABEL_REF (VOIDmode, label),
18184 : : pc_rtx);
18185 : 279 : insn = emit_jump_insn (gen_rtx_SET (pc_rtx, temp));
18186 : 279 : predict_jump (REG_BR_PROB_BASE * 10 / 100);
18187 : 279 : JUMP_LABEL (insn) = label;
18188 : 279 : }
18189 : :
18190 : : /* Output code to perform an sinh XFmode calculation. */
18191 : :
18192 : : void
18193 : 2 : ix86_emit_i387_sinh (rtx op0, rtx op1)
18194 : : {
18195 : 2 : rtx e1 = gen_reg_rtx (XFmode);
18196 : 2 : rtx e2 = gen_reg_rtx (XFmode);
18197 : 2 : rtx scratch = gen_reg_rtx (HImode);
18198 : 2 : rtx flags = gen_rtx_REG (CCNOmode, FLAGS_REG);
18199 : 2 : rtx half = const_double_from_real_value (dconsthalf, XFmode);
18200 : 2 : rtx cst1, tmp;
18201 : 2 : rtx_code_label *jump_label = gen_label_rtx ();
18202 : 2 : rtx_insn *insn;
18203 : :
18204 : : /* scratch = fxam (op1) */
18205 : 2 : emit_insn (gen_fxamxf2_i387 (scratch, op1));
18206 : :
18207 : : /* e1 = expm1 (|op1|) */
18208 : 2 : emit_insn (gen_absxf2 (e2, op1));
18209 : 2 : emit_insn (gen_expm1xf2 (e1, e2));
18210 : :
18211 : : /* e2 = e1 / (e1 + 1.0) + e1 */
18212 : 2 : cst1 = force_reg (XFmode, CONST1_RTX (XFmode));
18213 : 2 : emit_insn (gen_addxf3 (e2, e1, cst1));
18214 : 2 : emit_insn (gen_divxf3 (e2, e1, e2));
18215 : 2 : emit_insn (gen_addxf3 (e2, e2, e1));
18216 : :
18217 : : /* flags = signbit (op1) */
18218 : 2 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x02)));
18219 : :
18220 : : /* if (flags) then e2 = -e2 */
18221 : 2 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode,
18222 : : gen_rtx_EQ (VOIDmode, flags, const0_rtx),
18223 : : gen_rtx_LABEL_REF (VOIDmode, jump_label),
18224 : : pc_rtx);
18225 : 2 : insn = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
18226 : 2 : predict_jump (REG_BR_PROB_BASE * 50 / 100);
18227 : 2 : JUMP_LABEL (insn) = jump_label;
18228 : :
18229 : 2 : emit_insn (gen_negxf2 (e2, e2));
18230 : :
18231 : 2 : emit_label (jump_label);
18232 : 2 : LABEL_NUSES (jump_label) = 1;
18233 : :
18234 : : /* op0 = 0.5 * e2 */
18235 : 2 : half = force_reg (XFmode, half);
18236 : 2 : emit_insn (gen_mulxf3 (op0, e2, half));
18237 : 2 : }
18238 : :
18239 : : /* Output code to perform an cosh XFmode calculation. */
18240 : :
18241 : : void
18242 : 3 : ix86_emit_i387_cosh (rtx op0, rtx op1)
18243 : : {
18244 : 3 : rtx e1 = gen_reg_rtx (XFmode);
18245 : 3 : rtx e2 = gen_reg_rtx (XFmode);
18246 : 3 : rtx half = const_double_from_real_value (dconsthalf, XFmode);
18247 : 3 : rtx cst1;
18248 : :
18249 : : /* e1 = exp (op1) */
18250 : 3 : emit_insn (gen_expxf2 (e1, op1));
18251 : :
18252 : : /* e2 = e1 + 1.0 / e1 */
18253 : 3 : cst1 = force_reg (XFmode, CONST1_RTX (XFmode));
18254 : 3 : emit_insn (gen_divxf3 (e2, cst1, e1));
18255 : 3 : emit_insn (gen_addxf3 (e2, e1, e2));
18256 : :
18257 : : /* op0 = 0.5 * e2 */
18258 : 3 : half = force_reg (XFmode, half);
18259 : 3 : emit_insn (gen_mulxf3 (op0, e2, half));
18260 : 3 : }
18261 : :
18262 : : /* Output code to perform an tanh XFmode calculation. */
18263 : :
18264 : : void
18265 : 1 : ix86_emit_i387_tanh (rtx op0, rtx op1)
18266 : : {
18267 : 1 : rtx e1 = gen_reg_rtx (XFmode);
18268 : 1 : rtx e2 = gen_reg_rtx (XFmode);
18269 : 1 : rtx scratch = gen_reg_rtx (HImode);
18270 : 1 : rtx flags = gen_rtx_REG (CCNOmode, FLAGS_REG);
18271 : 1 : rtx cst2, tmp;
18272 : 1 : rtx_code_label *jump_label = gen_label_rtx ();
18273 : 1 : rtx_insn *insn;
18274 : :
18275 : : /* scratch = fxam (op1) */
18276 : 1 : emit_insn (gen_fxamxf2_i387 (scratch, op1));
18277 : :
18278 : : /* e1 = expm1 (-|2 * op1|) */
18279 : 1 : emit_insn (gen_addxf3 (e2, op1, op1));
18280 : 1 : emit_insn (gen_absxf2 (e2, e2));
18281 : 1 : emit_insn (gen_negxf2 (e2, e2));
18282 : 1 : emit_insn (gen_expm1xf2 (e1, e2));
18283 : :
18284 : : /* e2 = e1 / (e1 + 2.0) */
18285 : 1 : cst2 = force_reg (XFmode, CONST2_RTX (XFmode));
18286 : 1 : emit_insn (gen_addxf3 (e2, e1, cst2));
18287 : 1 : emit_insn (gen_divxf3 (e2, e1, e2));
18288 : :
18289 : : /* flags = signbit (op1) */
18290 : 1 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x02)));
18291 : :
18292 : : /* if (!flags) then e2 = -e2 */
18293 : 1 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode,
18294 : : gen_rtx_NE (VOIDmode, flags, const0_rtx),
18295 : : gen_rtx_LABEL_REF (VOIDmode, jump_label),
18296 : : pc_rtx);
18297 : 1 : insn = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
18298 : 1 : predict_jump (REG_BR_PROB_BASE * 50 / 100);
18299 : 1 : JUMP_LABEL (insn) = jump_label;
18300 : :
18301 : 1 : emit_insn (gen_negxf2 (e2, e2));
18302 : :
18303 : 1 : emit_label (jump_label);
18304 : 1 : LABEL_NUSES (jump_label) = 1;
18305 : :
18306 : 1 : emit_move_insn (op0, e2);
18307 : 1 : }
18308 : :
18309 : : /* Output code to perform an asinh XFmode calculation. */
18310 : :
18311 : : void
18312 : 0 : ix86_emit_i387_asinh (rtx op0, rtx op1)
18313 : : {
18314 : 0 : rtx e1 = gen_reg_rtx (XFmode);
18315 : 0 : rtx e2 = gen_reg_rtx (XFmode);
18316 : 0 : rtx scratch = gen_reg_rtx (HImode);
18317 : 0 : rtx flags = gen_rtx_REG (CCNOmode, FLAGS_REG);
18318 : 0 : rtx cst1, tmp;
18319 : 0 : rtx_code_label *jump_label = gen_label_rtx ();
18320 : 0 : rtx_insn *insn;
18321 : :
18322 : : /* e2 = sqrt (op1^2 + 1.0) + 1.0 */
18323 : 0 : emit_insn (gen_mulxf3 (e1, op1, op1));
18324 : 0 : cst1 = force_reg (XFmode, CONST1_RTX (XFmode));
18325 : 0 : emit_insn (gen_addxf3 (e2, e1, cst1));
18326 : 0 : emit_insn (gen_sqrtxf2 (e2, e2));
18327 : 0 : emit_insn (gen_addxf3 (e2, e2, cst1));
18328 : :
18329 : : /* e1 = e1 / e2 */
18330 : 0 : emit_insn (gen_divxf3 (e1, e1, e2));
18331 : :
18332 : : /* scratch = fxam (op1) */
18333 : 0 : emit_insn (gen_fxamxf2_i387 (scratch, op1));
18334 : :
18335 : : /* e1 = e1 + |op1| */
18336 : 0 : emit_insn (gen_absxf2 (e2, op1));
18337 : 0 : emit_insn (gen_addxf3 (e1, e1, e2));
18338 : :
18339 : : /* e2 = log1p (e1) */
18340 : 0 : ix86_emit_i387_log1p (e2, e1);
18341 : :
18342 : : /* flags = signbit (op1) */
18343 : 0 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x02)));
18344 : :
18345 : : /* if (flags) then e2 = -e2 */
18346 : 0 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode,
18347 : : gen_rtx_EQ (VOIDmode, flags, const0_rtx),
18348 : : gen_rtx_LABEL_REF (VOIDmode, jump_label),
18349 : : pc_rtx);
18350 : 0 : insn = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
18351 : 0 : predict_jump (REG_BR_PROB_BASE * 50 / 100);
18352 : 0 : JUMP_LABEL (insn) = jump_label;
18353 : :
18354 : 0 : emit_insn (gen_negxf2 (e2, e2));
18355 : :
18356 : 0 : emit_label (jump_label);
18357 : 0 : LABEL_NUSES (jump_label) = 1;
18358 : :
18359 : 0 : emit_move_insn (op0, e2);
18360 : 0 : }
18361 : :
18362 : : /* Output code to perform an acosh XFmode calculation. */
18363 : :
18364 : : void
18365 : 0 : ix86_emit_i387_acosh (rtx op0, rtx op1)
18366 : : {
18367 : 0 : rtx e1 = gen_reg_rtx (XFmode);
18368 : 0 : rtx e2 = gen_reg_rtx (XFmode);
18369 : 0 : rtx cst1 = force_reg (XFmode, CONST1_RTX (XFmode));
18370 : :
18371 : : /* e2 = sqrt (op1 + 1.0) */
18372 : 0 : emit_insn (gen_addxf3 (e2, op1, cst1));
18373 : 0 : emit_insn (gen_sqrtxf2 (e2, e2));
18374 : :
18375 : : /* e1 = sqrt (op1 - 1.0) */
18376 : 0 : emit_insn (gen_subxf3 (e1, op1, cst1));
18377 : 0 : emit_insn (gen_sqrtxf2 (e1, e1));
18378 : :
18379 : : /* e1 = e1 * e2 */
18380 : 0 : emit_insn (gen_mulxf3 (e1, e1, e2));
18381 : :
18382 : : /* e1 = e1 + op1 */
18383 : 0 : emit_insn (gen_addxf3 (e1, e1, op1));
18384 : :
18385 : : /* op0 = log (e1) */
18386 : 0 : emit_insn (gen_logxf2 (op0, e1));
18387 : 0 : }
18388 : :
18389 : : /* Output code to perform an atanh XFmode calculation. */
18390 : :
18391 : : void
18392 : 4 : ix86_emit_i387_atanh (rtx op0, rtx op1)
18393 : : {
18394 : 4 : rtx e1 = gen_reg_rtx (XFmode);
18395 : 4 : rtx e2 = gen_reg_rtx (XFmode);
18396 : 4 : rtx scratch = gen_reg_rtx (HImode);
18397 : 4 : rtx flags = gen_rtx_REG (CCNOmode, FLAGS_REG);
18398 : 4 : rtx half = const_double_from_real_value (dconsthalf, XFmode);
18399 : 4 : rtx cst1, tmp;
18400 : 4 : rtx_code_label *jump_label = gen_label_rtx ();
18401 : 4 : rtx_insn *insn;
18402 : :
18403 : : /* scratch = fxam (op1) */
18404 : 4 : emit_insn (gen_fxamxf2_i387 (scratch, op1));
18405 : :
18406 : : /* e2 = |op1| */
18407 : 4 : emit_insn (gen_absxf2 (e2, op1));
18408 : :
18409 : : /* e1 = -(e2 + e2) / (e2 + 1.0) */
18410 : 4 : cst1 = force_reg (XFmode, CONST1_RTX (XFmode));
18411 : 4 : emit_insn (gen_addxf3 (e1, e2, cst1));
18412 : 4 : emit_insn (gen_addxf3 (e2, e2, e2));
18413 : 4 : emit_insn (gen_negxf2 (e2, e2));
18414 : 4 : emit_insn (gen_divxf3 (e1, e2, e1));
18415 : :
18416 : : /* e2 = log1p (e1) */
18417 : 4 : ix86_emit_i387_log1p (e2, e1);
18418 : :
18419 : : /* flags = signbit (op1) */
18420 : 4 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x02)));
18421 : :
18422 : : /* if (!flags) then e2 = -e2 */
18423 : 4 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode,
18424 : : gen_rtx_NE (VOIDmode, flags, const0_rtx),
18425 : : gen_rtx_LABEL_REF (VOIDmode, jump_label),
18426 : : pc_rtx);
18427 : 4 : insn = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
18428 : 4 : predict_jump (REG_BR_PROB_BASE * 50 / 100);
18429 : 4 : JUMP_LABEL (insn) = jump_label;
18430 : :
18431 : 4 : emit_insn (gen_negxf2 (e2, e2));
18432 : :
18433 : 4 : emit_label (jump_label);
18434 : 4 : LABEL_NUSES (jump_label) = 1;
18435 : :
18436 : : /* op0 = 0.5 * e2 */
18437 : 4 : half = force_reg (XFmode, half);
18438 : 4 : emit_insn (gen_mulxf3 (op0, e2, half));
18439 : 4 : }
18440 : :
18441 : : /* Output code to perform a log1p XFmode calculation. */
18442 : :
18443 : : void
18444 : 5 : ix86_emit_i387_log1p (rtx op0, rtx op1)
18445 : : {
18446 : 5 : rtx_code_label *label1 = gen_label_rtx ();
18447 : 5 : rtx_code_label *label2 = gen_label_rtx ();
18448 : :
18449 : 5 : rtx tmp = gen_reg_rtx (XFmode);
18450 : 5 : rtx res = gen_reg_rtx (XFmode);
18451 : 5 : rtx cst, cstln2, cst1;
18452 : 5 : rtx_insn *insn;
18453 : :
18454 : : /* The emit_jump call emits pending stack adjust, make sure it is emitted
18455 : : before the conditional jump, otherwise the stack adjustment will be
18456 : : only conditional. */
18457 : 5 : do_pending_stack_adjust ();
18458 : :
18459 : 5 : cst = const_double_from_real_value
18460 : 5 : (REAL_VALUE_ATOF ("0.29289321881345247561810596348408353", XFmode), XFmode);
18461 : 5 : cstln2 = force_reg (XFmode, standard_80387_constant_rtx (4)); /* fldln2 */
18462 : :
18463 : 5 : emit_insn (gen_absxf2 (tmp, op1));
18464 : :
18465 : 5 : cst = force_reg (XFmode, cst);
18466 : 5 : ix86_expand_branch (GE, tmp, cst, label1);
18467 : 5 : predict_jump (REG_BR_PROB_BASE * 10 / 100);
18468 : 5 : insn = get_last_insn ();
18469 : 5 : JUMP_LABEL (insn) = label1;
18470 : :
18471 : 5 : emit_insn (gen_fyl2xp1xf3_i387 (res, op1, cstln2));
18472 : 5 : emit_jump (label2);
18473 : :
18474 : 5 : emit_label (label1);
18475 : 5 : LABEL_NUSES (label1) = 1;
18476 : :
18477 : 5 : cst1 = force_reg (XFmode, CONST1_RTX (XFmode));
18478 : 5 : emit_insn (gen_rtx_SET (tmp, gen_rtx_PLUS (XFmode, op1, cst1)));
18479 : 5 : emit_insn (gen_fyl2xxf3_i387 (res, tmp, cstln2));
18480 : :
18481 : 5 : emit_label (label2);
18482 : 5 : LABEL_NUSES (label2) = 1;
18483 : :
18484 : 5 : emit_move_insn (op0, res);
18485 : 5 : }
18486 : :
18487 : : /* Emit code for round calculation. */
18488 : : void
18489 : 68 : ix86_emit_i387_round (rtx op0, rtx op1)
18490 : : {
18491 : 68 : machine_mode inmode = GET_MODE (op1);
18492 : 68 : machine_mode outmode = GET_MODE (op0);
18493 : 68 : rtx e1 = gen_reg_rtx (XFmode);
18494 : 68 : rtx e2 = gen_reg_rtx (XFmode);
18495 : 68 : rtx scratch = gen_reg_rtx (HImode);
18496 : 68 : rtx flags = gen_rtx_REG (CCNOmode, FLAGS_REG);
18497 : 68 : rtx half = const_double_from_real_value (dconsthalf, XFmode);
18498 : 68 : rtx res = gen_reg_rtx (outmode);
18499 : 68 : rtx_code_label *jump_label = gen_label_rtx ();
18500 : 68 : rtx (*floor_insn) (rtx, rtx);
18501 : 68 : rtx (*neg_insn) (rtx, rtx);
18502 : 68 : rtx_insn *insn;
18503 : 68 : rtx tmp;
18504 : :
18505 : 68 : switch (inmode)
18506 : : {
18507 : 37 : case E_SFmode:
18508 : 37 : case E_DFmode:
18509 : 37 : tmp = gen_reg_rtx (XFmode);
18510 : :
18511 : 37 : emit_insn (gen_rtx_SET (tmp, gen_rtx_FLOAT_EXTEND (XFmode, op1)));
18512 : 37 : op1 = tmp;
18513 : 37 : break;
18514 : : case E_XFmode:
18515 : : break;
18516 : 0 : default:
18517 : 0 : gcc_unreachable ();
18518 : : }
18519 : :
18520 : 68 : switch (outmode)
18521 : : {
18522 : : case E_SFmode:
18523 : : floor_insn = gen_frndintxf2_floor;
18524 : : neg_insn = gen_negsf2;
18525 : : break;
18526 : 8 : case E_DFmode:
18527 : 8 : floor_insn = gen_frndintxf2_floor;
18528 : 8 : neg_insn = gen_negdf2;
18529 : 8 : break;
18530 : 10 : case E_XFmode:
18531 : 10 : floor_insn = gen_frndintxf2_floor;
18532 : 10 : neg_insn = gen_negxf2;
18533 : 10 : break;
18534 : 0 : case E_HImode:
18535 : 0 : floor_insn = gen_lfloorxfhi2;
18536 : 0 : neg_insn = gen_neghi2;
18537 : 0 : break;
18538 : 10 : case E_SImode:
18539 : 10 : floor_insn = gen_lfloorxfsi2;
18540 : 10 : neg_insn = gen_negsi2;
18541 : 10 : break;
18542 : 36 : case E_DImode:
18543 : 36 : floor_insn = gen_lfloorxfdi2;
18544 : 36 : neg_insn = gen_negdi2;
18545 : 36 : break;
18546 : 0 : default:
18547 : 0 : gcc_unreachable ();
18548 : : }
18549 : :
18550 : : /* round(a) = sgn(a) * floor(fabs(a) + 0.5) */
18551 : :
18552 : : /* scratch = fxam(op1) */
18553 : 68 : emit_insn (gen_fxamxf2_i387 (scratch, op1));
18554 : :
18555 : : /* e1 = fabs(op1) */
18556 : 68 : emit_insn (gen_absxf2 (e1, op1));
18557 : :
18558 : : /* e2 = e1 + 0.5 */
18559 : 68 : half = force_reg (XFmode, half);
18560 : 68 : emit_insn (gen_rtx_SET (e2, gen_rtx_PLUS (XFmode, e1, half)));
18561 : :
18562 : : /* res = floor(e2) */
18563 : 68 : switch (outmode)
18564 : : {
18565 : 12 : case E_SFmode:
18566 : 12 : case E_DFmode:
18567 : 12 : {
18568 : 12 : tmp = gen_reg_rtx (XFmode);
18569 : :
18570 : 12 : emit_insn (floor_insn (tmp, e2));
18571 : 12 : emit_insn (gen_rtx_SET (res,
18572 : : gen_rtx_UNSPEC (outmode, gen_rtvec (1, tmp),
18573 : : UNSPEC_TRUNC_NOOP)));
18574 : : }
18575 : 12 : break;
18576 : 56 : default:
18577 : 56 : emit_insn (floor_insn (res, e2));
18578 : : }
18579 : :
18580 : : /* flags = signbit(a) */
18581 : 68 : emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x02)));
18582 : :
18583 : : /* if (flags) then res = -res */
18584 : 68 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode,
18585 : : gen_rtx_EQ (VOIDmode, flags, const0_rtx),
18586 : : gen_rtx_LABEL_REF (VOIDmode, jump_label),
18587 : : pc_rtx);
18588 : 68 : insn = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
18589 : 68 : predict_jump (REG_BR_PROB_BASE * 50 / 100);
18590 : 68 : JUMP_LABEL (insn) = jump_label;
18591 : :
18592 : 68 : emit_insn (neg_insn (res, res));
18593 : :
18594 : 68 : emit_label (jump_label);
18595 : 68 : LABEL_NUSES (jump_label) = 1;
18596 : :
18597 : 68 : emit_move_insn (op0, res);
18598 : 68 : }
18599 : :
18600 : : /* Output code to perform a Newton-Rhapson approximation of a single precision
18601 : : floating point divide [http://en.wikipedia.org/wiki/N-th_root_algorithm]. */
18602 : :
18603 : : void
18604 : 50 : ix86_emit_swdivsf (rtx res, rtx a, rtx b, machine_mode mode)
18605 : : {
18606 : 50 : rtx x0, x1, e0, e1;
18607 : :
18608 : 50 : x0 = gen_reg_rtx (mode);
18609 : 50 : e0 = gen_reg_rtx (mode);
18610 : 50 : e1 = gen_reg_rtx (mode);
18611 : 50 : x1 = gen_reg_rtx (mode);
18612 : :
18613 : : /* a / b = a * ((rcp(b) + rcp(b)) - (b * rcp(b) * rcp (b))) */
18614 : :
18615 : 50 : b = force_reg (mode, b);
18616 : :
18617 : : /* x0 = rcp(b) estimate */
18618 : 50 : if (mode == V16SFmode || mode == V8DFmode)
18619 : : {
18620 : 1 : if (TARGET_AVX512ER)
18621 : : {
18622 : 1 : emit_insn (gen_rtx_SET (x0, gen_rtx_UNSPEC (mode, gen_rtvec (1, b),
18623 : : UNSPEC_RCP28)));
18624 : : /* res = a * x0 */
18625 : 1 : emit_insn (gen_rtx_SET (res, gen_rtx_MULT (mode, a, x0)));
18626 : 1 : return;
18627 : : }
18628 : : else
18629 : 0 : emit_insn (gen_rtx_SET (x0, gen_rtx_UNSPEC (mode, gen_rtvec (1, b),
18630 : : UNSPEC_RCP14)));
18631 : : }
18632 : : else
18633 : 49 : emit_insn (gen_rtx_SET (x0, gen_rtx_UNSPEC (mode, gen_rtvec (1, b),
18634 : : UNSPEC_RCP)));
18635 : :
18636 : : /* e0 = x0 * b */
18637 : 49 : emit_insn (gen_rtx_SET (e0, gen_rtx_MULT (mode, x0, b)));
18638 : :
18639 : : /* e0 = x0 * e0 */
18640 : 49 : emit_insn (gen_rtx_SET (e0, gen_rtx_MULT (mode, x0, e0)));
18641 : :
18642 : : /* e1 = x0 + x0 */
18643 : 49 : emit_insn (gen_rtx_SET (e1, gen_rtx_PLUS (mode, x0, x0)));
18644 : :
18645 : : /* x1 = e1 - e0 */
18646 : 49 : emit_insn (gen_rtx_SET (x1, gen_rtx_MINUS (mode, e1, e0)));
18647 : :
18648 : : /* res = a * x1 */
18649 : 49 : emit_insn (gen_rtx_SET (res, gen_rtx_MULT (mode, a, x1)));
18650 : : }
18651 : :
18652 : : /* Output code to perform a Newton-Rhapson approximation of a
18653 : : single precision floating point [reciprocal] square root. */
18654 : :
18655 : : void
18656 : 70 : ix86_emit_swsqrtsf (rtx res, rtx a, machine_mode mode, bool recip)
18657 : : {
18658 : 70 : rtx x0, e0, e1, e2, e3, mthree, mhalf;
18659 : 70 : REAL_VALUE_TYPE r;
18660 : 70 : int unspec;
18661 : :
18662 : 70 : x0 = gen_reg_rtx (mode);
18663 : 70 : e0 = gen_reg_rtx (mode);
18664 : 70 : e1 = gen_reg_rtx (mode);
18665 : 70 : e2 = gen_reg_rtx (mode);
18666 : 70 : e3 = gen_reg_rtx (mode);
18667 : :
18668 : 70 : if (TARGET_AVX512ER && mode == V16SFmode)
18669 : : {
18670 : 2 : if (recip)
18671 : : /* res = rsqrt28(a) estimate */
18672 : 1 : emit_insn (gen_rtx_SET (res, gen_rtx_UNSPEC (mode, gen_rtvec (1, a),
18673 : : UNSPEC_RSQRT28)));
18674 : : else
18675 : : {
18676 : : /* x0 = rsqrt28(a) estimate */
18677 : 1 : emit_insn (gen_rtx_SET (x0, gen_rtx_UNSPEC (mode, gen_rtvec (1, a),
18678 : : UNSPEC_RSQRT28)));
18679 : : /* res = rcp28(x0) estimate */
18680 : 1 : emit_insn (gen_rtx_SET (res, gen_rtx_UNSPEC (mode, gen_rtvec (1, x0),
18681 : : UNSPEC_RCP28)));
18682 : : }
18683 : 2 : return;
18684 : : }
18685 : :
18686 : 68 : real_from_integer (&r, VOIDmode, -3, SIGNED);
18687 : 68 : mthree = const_double_from_real_value (r, SFmode);
18688 : :
18689 : 68 : real_arithmetic (&r, NEGATE_EXPR, &dconsthalf, NULL);
18690 : 68 : mhalf = const_double_from_real_value (r, SFmode);
18691 : 68 : unspec = UNSPEC_RSQRT;
18692 : :
18693 : 68 : if (VECTOR_MODE_P (mode))
18694 : : {
18695 : 50 : mthree = ix86_build_const_vector (mode, true, mthree);
18696 : 50 : mhalf = ix86_build_const_vector (mode, true, mhalf);
18697 : : /* There is no 512-bit rsqrt. There is however rsqrt14. */
18698 : 100 : if (GET_MODE_SIZE (mode) == 64)
18699 : 0 : unspec = UNSPEC_RSQRT14;
18700 : : }
18701 : :
18702 : : /* sqrt(a) = -0.5 * a * rsqrtss(a) * (a * rsqrtss(a) * rsqrtss(a) - 3.0)
18703 : : rsqrt(a) = -0.5 * rsqrtss(a) * (a * rsqrtss(a) * rsqrtss(a) - 3.0) */
18704 : :
18705 : 68 : a = force_reg (mode, a);
18706 : :
18707 : : /* x0 = rsqrt(a) estimate */
18708 : 68 : emit_insn (gen_rtx_SET (x0, gen_rtx_UNSPEC (mode, gen_rtvec (1, a),
18709 : : unspec)));
18710 : :
18711 : : /* If (a == 0.0) Filter out infinity to prevent NaN for sqrt(0.0). */
18712 : 68 : if (!recip)
18713 : : {
18714 : 40 : rtx zero = force_reg (mode, CONST0_RTX(mode));
18715 : 40 : rtx mask;
18716 : :
18717 : : /* Handle masked compare. */
18718 : 76 : if (VECTOR_MODE_P (mode) && GET_MODE_SIZE (mode) == 64)
18719 : : {
18720 : 0 : mask = gen_reg_rtx (HImode);
18721 : : /* Imm value 0x4 corresponds to not-equal comparison. */
18722 : 0 : emit_insn (gen_avx512f_cmpv16sf3 (mask, zero, a, GEN_INT (0x4)));
18723 : 0 : emit_insn (gen_avx512f_blendmv16sf (x0, zero, x0, mask));
18724 : : }
18725 : : else
18726 : : {
18727 : 40 : mask = gen_reg_rtx (mode);
18728 : 40 : emit_insn (gen_rtx_SET (mask, gen_rtx_NE (mode, zero, a)));
18729 : 40 : emit_insn (gen_rtx_SET (x0, gen_rtx_AND (mode, x0, mask)));
18730 : : }
18731 : : }
18732 : :
18733 : 68 : mthree = force_reg (mode, mthree);
18734 : :
18735 : : /* e0 = x0 * a */
18736 : 68 : emit_insn (gen_rtx_SET (e0, gen_rtx_MULT (mode, x0, a)));
18737 : :
18738 : 68 : unsigned vector_size = GET_MODE_SIZE (mode);
18739 : 68 : if (TARGET_FMA
18740 : 60 : || (TARGET_AVX512F && TARGET_EVEX512 && vector_size == 64)
18741 : 60 : || (TARGET_AVX512VL && (vector_size == 32 || vector_size == 16)))
18742 : 16 : emit_insn (gen_rtx_SET (e2,
18743 : : gen_rtx_FMA (mode, e0, x0, mthree)));
18744 : : else
18745 : : {
18746 : : /* e1 = e0 * x0 */
18747 : 52 : emit_insn (gen_rtx_SET (e1, gen_rtx_MULT (mode, e0, x0)));
18748 : :
18749 : : /* e2 = e1 - 3. */
18750 : 52 : emit_insn (gen_rtx_SET (e2, gen_rtx_PLUS (mode, e1, mthree)));
18751 : : }
18752 : :
18753 : 68 : mhalf = force_reg (mode, mhalf);
18754 : 68 : if (recip)
18755 : : /* e3 = -.5 * x0 */
18756 : 28 : emit_insn (gen_rtx_SET (e3, gen_rtx_MULT (mode, x0, mhalf)));
18757 : : else
18758 : : /* e3 = -.5 * e0 */
18759 : 40 : emit_insn (gen_rtx_SET (e3, gen_rtx_MULT (mode, e0, mhalf)));
18760 : : /* ret = e2 * e3 */
18761 : 68 : emit_insn (gen_rtx_SET (res, gen_rtx_MULT (mode, e2, e3)));
18762 : : }
18763 : :
18764 : : /* Expand fabs (OP0) and return a new rtx that holds the result. The
18765 : : mask for masking out the sign-bit is stored in *SMASK, if that is
18766 : : non-null. */
18767 : :
18768 : : static rtx
18769 : 955 : ix86_expand_sse_fabs (rtx op0, rtx *smask)
18770 : : {
18771 : 955 : machine_mode vmode, mode = GET_MODE (op0);
18772 : 955 : rtx xa, mask;
18773 : :
18774 : 955 : xa = gen_reg_rtx (mode);
18775 : 955 : if (mode == SFmode)
18776 : : vmode = V4SFmode;
18777 : 510 : else if (mode == DFmode)
18778 : : vmode = V2DFmode;
18779 : : else
18780 : 0 : vmode = mode;
18781 : 955 : mask = ix86_build_signbit_mask (vmode, VECTOR_MODE_P (mode), true);
18782 : 955 : if (!VECTOR_MODE_P (mode))
18783 : : {
18784 : : /* We need to generate a scalar mode mask in this case. */
18785 : 955 : rtx tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (1, const0_rtx));
18786 : 955 : tmp = gen_rtx_VEC_SELECT (mode, mask, tmp);
18787 : 955 : mask = gen_reg_rtx (mode);
18788 : 955 : emit_insn (gen_rtx_SET (mask, tmp));
18789 : : }
18790 : 955 : emit_insn (gen_rtx_SET (xa, gen_rtx_AND (mode, op0, mask)));
18791 : :
18792 : 955 : if (smask)
18793 : 901 : *smask = mask;
18794 : :
18795 : 955 : return xa;
18796 : : }
18797 : :
18798 : : /* Expands a comparison of OP0 with OP1 using comparison code CODE,
18799 : : swapping the operands if SWAP_OPERANDS is true. The expanded
18800 : : code is a forward jump to a newly created label in case the
18801 : : comparison is true. The generated label rtx is returned. */
18802 : : static rtx_code_label *
18803 : 969 : ix86_expand_sse_compare_and_jump (enum rtx_code code, rtx op0, rtx op1,
18804 : : bool swap_operands)
18805 : : {
18806 : 969 : bool unordered_compare = ix86_unordered_fp_compare (code);
18807 : 969 : rtx_code_label *label;
18808 : 969 : rtx tmp, reg;
18809 : :
18810 : 969 : if (swap_operands)
18811 : 34 : std::swap (op0, op1);
18812 : :
18813 : 969 : label = gen_label_rtx ();
18814 : 969 : tmp = gen_rtx_COMPARE (CCFPmode, op0, op1);
18815 : 969 : if (unordered_compare)
18816 : 821 : tmp = gen_rtx_UNSPEC (CCFPmode, gen_rtvec (1, tmp), UNSPEC_NOTRAP);
18817 : 969 : reg = gen_rtx_REG (CCFPmode, FLAGS_REG);
18818 : 969 : emit_insn (gen_rtx_SET (reg, tmp));
18819 : 969 : tmp = gen_rtx_fmt_ee (code, VOIDmode, reg, const0_rtx);
18820 : 969 : tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
18821 : : gen_rtx_LABEL_REF (VOIDmode, label), pc_rtx);
18822 : 969 : tmp = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
18823 : 969 : JUMP_LABEL (tmp) = label;
18824 : :
18825 : 969 : return label;
18826 : : }
18827 : :
18828 : : /* Expand a mask generating SSE comparison instruction comparing OP0 with OP1
18829 : : using comparison code CODE. Operands are swapped for the comparison if
18830 : : SWAP_OPERANDS is true. Returns a rtx for the generated mask. */
18831 : : static rtx
18832 : 620 : ix86_expand_sse_compare_mask (enum rtx_code code, rtx op0, rtx op1,
18833 : : bool swap_operands)
18834 : : {
18835 : 620 : rtx (*insn)(rtx, rtx, rtx, rtx);
18836 : 620 : machine_mode mode = GET_MODE (op0);
18837 : 620 : rtx mask = gen_reg_rtx (mode);
18838 : :
18839 : 620 : if (swap_operands)
18840 : 404 : std::swap (op0, op1);
18841 : :
18842 : 620 : insn = mode == DFmode ? gen_setcc_df_sse : gen_setcc_sf_sse;
18843 : :
18844 : 620 : emit_insn (insn (mask, op0, op1,
18845 : : gen_rtx_fmt_ee (code, mode, op0, op1)));
18846 : 620 : return mask;
18847 : : }
18848 : :
18849 : : /* Expand copysign from SIGN to the positive value ABS_VALUE
18850 : : storing in RESULT. If MASK is non-null, it shall be a mask to mask out
18851 : : the sign-bit. */
18852 : :
18853 : : static void
18854 : 936 : ix86_sse_copysign_to_positive (rtx result, rtx abs_value, rtx sign, rtx mask)
18855 : : {
18856 : 936 : machine_mode mode = GET_MODE (sign);
18857 : 936 : rtx sgn = gen_reg_rtx (mode);
18858 : 936 : if (mask == NULL_RTX)
18859 : : {
18860 : 35 : machine_mode vmode;
18861 : :
18862 : 35 : if (mode == SFmode)
18863 : : vmode = V4SFmode;
18864 : : else if (mode == DFmode)
18865 : : vmode = V2DFmode;
18866 : : else if (mode == HFmode)
18867 : : vmode = V8HFmode;
18868 : : else
18869 : 35 : vmode = mode;
18870 : :
18871 : 35 : mask = ix86_build_signbit_mask (vmode, VECTOR_MODE_P (mode), false);
18872 : 35 : if (!VECTOR_MODE_P (mode))
18873 : : {
18874 : : /* We need to generate a scalar mode mask in this case. */
18875 : 35 : rtx tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (1, const0_rtx));
18876 : 35 : tmp = gen_rtx_VEC_SELECT (mode, mask, tmp);
18877 : 35 : mask = gen_reg_rtx (mode);
18878 : 35 : emit_insn (gen_rtx_SET (mask, tmp));
18879 : : }
18880 : : }
18881 : : else
18882 : 901 : mask = gen_rtx_NOT (mode, mask);
18883 : 936 : emit_insn (gen_rtx_SET (sgn, gen_rtx_AND (mode, mask, sign)));
18884 : 936 : emit_insn (gen_rtx_SET (result, gen_rtx_IOR (mode, abs_value, sgn)));
18885 : 936 : }
18886 : :
18887 : : /* Expand SSE sequence for computing lround from OP1 storing
18888 : : into OP0. */
18889 : :
18890 : : void
18891 : 35 : ix86_expand_lround (rtx op0, rtx op1)
18892 : : {
18893 : : /* C code for the stuff we're doing below:
18894 : : tmp = op1 + copysign (nextafter (0.5, 0.0), op1)
18895 : : return (long)tmp;
18896 : : */
18897 : 35 : machine_mode mode = GET_MODE (op1);
18898 : 35 : const struct real_format *fmt;
18899 : 35 : REAL_VALUE_TYPE pred_half, half_minus_pred_half;
18900 : 35 : rtx adj;
18901 : :
18902 : : /* load nextafter (0.5, 0.0) */
18903 : 35 : fmt = REAL_MODE_FORMAT (mode);
18904 : 35 : real_2expN (&half_minus_pred_half, -(fmt->p) - 1, mode);
18905 : 35 : real_arithmetic (&pred_half, MINUS_EXPR, &dconsthalf, &half_minus_pred_half);
18906 : :
18907 : : /* adj = copysign (0.5, op1) */
18908 : 35 : adj = force_reg (mode, const_double_from_real_value (pred_half, mode));
18909 : 35 : ix86_sse_copysign_to_positive (adj, adj, force_reg (mode, op1), NULL_RTX);
18910 : :
18911 : : /* adj = op1 + adj */
18912 : 35 : adj = expand_simple_binop (mode, PLUS, adj, op1, NULL_RTX, 0, OPTAB_DIRECT);
18913 : :
18914 : : /* op0 = (imode)adj */
18915 : 35 : expand_fix (op0, adj, 0);
18916 : 35 : }
18917 : :
18918 : : /* Expand SSE2 sequence for computing lround from OPERAND1 storing
18919 : : into OPERAND0. */
18920 : :
18921 : : void
18922 : 68 : ix86_expand_lfloorceil (rtx op0, rtx op1, bool do_floor)
18923 : : {
18924 : : /* C code for the stuff we're doing below (for do_floor):
18925 : : xi = (long)op1;
18926 : : xi -= (double)xi > op1 ? 1 : 0;
18927 : : return xi;
18928 : : */
18929 : 68 : machine_mode fmode = GET_MODE (op1);
18930 : 68 : machine_mode imode = GET_MODE (op0);
18931 : 68 : rtx ireg, freg, tmp;
18932 : 68 : rtx_code_label *label;
18933 : :
18934 : : /* reg = (long)op1 */
18935 : 68 : ireg = gen_reg_rtx (imode);
18936 : 68 : expand_fix (ireg, op1, 0);
18937 : :
18938 : : /* freg = (double)reg */
18939 : 68 : freg = gen_reg_rtx (fmode);
18940 : 68 : expand_float (freg, ireg, 0);
18941 : :
18942 : : /* ireg = (freg > op1) ? ireg - 1 : ireg */
18943 : 136 : label = ix86_expand_sse_compare_and_jump (UNLE,
18944 : 68 : freg, op1, !do_floor);
18945 : 102 : tmp = expand_simple_binop (imode, do_floor ? MINUS : PLUS,
18946 : : ireg, const1_rtx, NULL_RTX, 0, OPTAB_DIRECT);
18947 : 68 : emit_move_insn (ireg, tmp);
18948 : :
18949 : 68 : emit_label (label);
18950 : 68 : LABEL_NUSES (label) = 1;
18951 : :
18952 : 68 : emit_move_insn (op0, ireg);
18953 : 68 : }
18954 : :
18955 : : /* Generate and return a rtx of mode MODE for 2**n where n is the number
18956 : : of bits of the mantissa of MODE, which must be one of DFmode or SFmode. */
18957 : :
18958 : : static rtx
18959 : 901 : ix86_gen_TWO52 (machine_mode mode)
18960 : : {
18961 : 901 : const struct real_format *fmt;
18962 : 901 : REAL_VALUE_TYPE TWO52r;
18963 : 901 : rtx TWO52;
18964 : :
18965 : 901 : fmt = REAL_MODE_FORMAT (mode);
18966 : 901 : real_2expN (&TWO52r, fmt->p - 1, mode);
18967 : 901 : TWO52 = const_double_from_real_value (TWO52r, mode);
18968 : 901 : TWO52 = force_reg (mode, TWO52);
18969 : :
18970 : 901 : return TWO52;
18971 : : }
18972 : :
18973 : : /* Expand rint rounding OPERAND1 and storing the result in OPERAND0. */
18974 : :
18975 : : void
18976 : 123 : ix86_expand_rint (rtx operand0, rtx operand1)
18977 : : {
18978 : : /* C code for the stuff we're doing below:
18979 : : xa = fabs (operand1);
18980 : : if (!isless (xa, 2**52))
18981 : : return operand1;
18982 : : two52 = 2**52;
18983 : : if (flag_rounding_math)
18984 : : {
18985 : : two52 = copysign (two52, operand1);
18986 : : xa = operand1;
18987 : : }
18988 : : xa = xa + two52 - two52;
18989 : : return copysign (xa, operand1);
18990 : : */
18991 : 123 : machine_mode mode = GET_MODE (operand0);
18992 : 123 : rtx res, xa, TWO52, mask;
18993 : 123 : rtx_code_label *label;
18994 : :
18995 : 123 : TWO52 = ix86_gen_TWO52 (mode);
18996 : :
18997 : : /* Temporary for holding the result, initialized to the input
18998 : : operand to ease control flow. */
18999 : 123 : res = copy_to_reg (operand1);
19000 : :
19001 : : /* xa = abs (operand1) */
19002 : 123 : xa = ix86_expand_sse_fabs (res, &mask);
19003 : :
19004 : : /* if (!isless (xa, TWO52)) goto label; */
19005 : 123 : label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
19006 : :
19007 : 123 : if (flag_rounding_math)
19008 : : {
19009 : 53 : ix86_sse_copysign_to_positive (TWO52, TWO52, res, mask);
19010 : 53 : xa = res;
19011 : : }
19012 : :
19013 : 123 : xa = expand_simple_binop (mode, PLUS, xa, TWO52, NULL_RTX, 0, OPTAB_DIRECT);
19014 : 123 : xa = expand_simple_binop (mode, MINUS, xa, TWO52, xa, 0, OPTAB_DIRECT);
19015 : :
19016 : : /* Remove the sign with FE_DOWNWARD, where x - x = -0.0. */
19017 : 123 : if (HONOR_SIGNED_ZEROS (mode) && flag_rounding_math)
19018 : 53 : xa = ix86_expand_sse_fabs (xa, NULL);
19019 : :
19020 : 123 : ix86_sse_copysign_to_positive (res, xa, res, mask);
19021 : :
19022 : 123 : emit_label (label);
19023 : 123 : LABEL_NUSES (label) = 1;
19024 : :
19025 : 123 : emit_move_insn (operand0, res);
19026 : 123 : }
19027 : :
19028 : : /* Expand SSE2 sequence for computing floor or ceil
19029 : : from OPERAND1 storing into OPERAND0. */
19030 : : void
19031 : 620 : ix86_expand_floorceil (rtx operand0, rtx operand1, bool do_floor)
19032 : : {
19033 : : /* C code for the stuff we expand below.
19034 : : double xa = fabs (x), x2;
19035 : : if (!isless (xa, TWO52))
19036 : : return x;
19037 : : x2 = (double)(long)x;
19038 : :
19039 : : Compensate. Floor:
19040 : : if (x2 > x)
19041 : : x2 -= 1;
19042 : : Compensate. Ceil:
19043 : : if (x2 < x)
19044 : : x2 += 1;
19045 : :
19046 : : if (HONOR_SIGNED_ZEROS (mode))
19047 : : return copysign (x2, x);
19048 : : return x2;
19049 : : */
19050 : 620 : machine_mode mode = GET_MODE (operand0);
19051 : 620 : rtx xa, xi, TWO52, tmp, one, res, mask;
19052 : 620 : rtx_code_label *label;
19053 : :
19054 : 620 : TWO52 = ix86_gen_TWO52 (mode);
19055 : :
19056 : : /* Temporary for holding the result, initialized to the input
19057 : : operand to ease control flow. */
19058 : 620 : res = copy_to_reg (operand1);
19059 : :
19060 : : /* xa = abs (operand1) */
19061 : 620 : xa = ix86_expand_sse_fabs (res, &mask);
19062 : :
19063 : : /* if (!isless (xa, TWO52)) goto label; */
19064 : 620 : label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
19065 : :
19066 : : /* xa = (double)(long)x */
19067 : 620 : xi = gen_reg_rtx (int_mode_for_mode (mode).require ());
19068 : 620 : expand_fix (xi, res, 0);
19069 : 620 : expand_float (xa, xi, 0);
19070 : :
19071 : : /* generate 1.0 */
19072 : 620 : one = force_reg (mode, const_double_from_real_value (dconst1, mode));
19073 : :
19074 : : /* Compensate: xa = xa - (xa > operand1 ? 1 : 0) */
19075 : 620 : tmp = ix86_expand_sse_compare_mask (UNGT, xa, res, !do_floor);
19076 : 620 : emit_insn (gen_rtx_SET (tmp, gen_rtx_AND (mode, one, tmp)));
19077 : 1024 : tmp = expand_simple_binop (mode, do_floor ? MINUS : PLUS,
19078 : : xa, tmp, NULL_RTX, 0, OPTAB_DIRECT);
19079 : 620 : if (HONOR_SIGNED_ZEROS (mode))
19080 : : {
19081 : : /* Remove the sign with FE_DOWNWARD, where x - x = -0.0. */
19082 : 581 : if (do_floor && flag_rounding_math)
19083 : 1 : tmp = ix86_expand_sse_fabs (tmp, NULL);
19084 : :
19085 : 581 : ix86_sse_copysign_to_positive (tmp, tmp, res, mask);
19086 : : }
19087 : 620 : emit_move_insn (res, tmp);
19088 : :
19089 : 620 : emit_label (label);
19090 : 620 : LABEL_NUSES (label) = 1;
19091 : :
19092 : 620 : emit_move_insn (operand0, res);
19093 : 620 : }
19094 : :
19095 : : /* Expand SSE2 sequence for computing floor or ceil from OPERAND1 storing
19096 : : into OPERAND0 without relying on DImode truncation via cvttsd2siq
19097 : : that is only available on 64bit targets. */
19098 : : void
19099 : 0 : ix86_expand_floorceildf_32 (rtx operand0, rtx operand1, bool do_floor)
19100 : : {
19101 : : /* C code for the stuff we expand below.
19102 : : double xa = fabs (x), x2;
19103 : : if (!isless (xa, TWO52))
19104 : : return x;
19105 : : xa = xa + TWO52 - TWO52;
19106 : : x2 = copysign (xa, x);
19107 : :
19108 : : Compensate. Floor:
19109 : : if (x2 > x)
19110 : : x2 -= 1;
19111 : : Compensate. Ceil:
19112 : : if (x2 < x)
19113 : : x2 += 1;
19114 : :
19115 : : if (HONOR_SIGNED_ZEROS (mode))
19116 : : x2 = copysign (x2, x);
19117 : : return x2;
19118 : : */
19119 : 0 : machine_mode mode = GET_MODE (operand0);
19120 : 0 : rtx xa, TWO52, tmp, one, res, mask;
19121 : 0 : rtx_code_label *label;
19122 : :
19123 : 0 : TWO52 = ix86_gen_TWO52 (mode);
19124 : :
19125 : : /* Temporary for holding the result, initialized to the input
19126 : : operand to ease control flow. */
19127 : 0 : res = copy_to_reg (operand1);
19128 : :
19129 : : /* xa = abs (operand1) */
19130 : 0 : xa = ix86_expand_sse_fabs (res, &mask);
19131 : :
19132 : : /* if (!isless (xa, TWO52)) goto label; */
19133 : 0 : label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
19134 : :
19135 : : /* xa = xa + TWO52 - TWO52; */
19136 : 0 : xa = expand_simple_binop (mode, PLUS, xa, TWO52, NULL_RTX, 0, OPTAB_DIRECT);
19137 : 0 : xa = expand_simple_binop (mode, MINUS, xa, TWO52, xa, 0, OPTAB_DIRECT);
19138 : :
19139 : : /* xa = copysign (xa, operand1) */
19140 : 0 : ix86_sse_copysign_to_positive (xa, xa, res, mask);
19141 : :
19142 : : /* generate 1.0 */
19143 : 0 : one = force_reg (mode, const_double_from_real_value (dconst1, mode));
19144 : :
19145 : : /* Compensate: xa = xa - (xa > operand1 ? 1 : 0) */
19146 : 0 : tmp = ix86_expand_sse_compare_mask (UNGT, xa, res, !do_floor);
19147 : 0 : emit_insn (gen_rtx_SET (tmp, gen_rtx_AND (mode, one, tmp)));
19148 : 0 : tmp = expand_simple_binop (mode, do_floor ? MINUS : PLUS,
19149 : : xa, tmp, NULL_RTX, 0, OPTAB_DIRECT);
19150 : 0 : if (HONOR_SIGNED_ZEROS (mode))
19151 : : {
19152 : : /* Remove the sign with FE_DOWNWARD, where x - x = -0.0. */
19153 : 0 : if (do_floor && flag_rounding_math)
19154 : 0 : tmp = ix86_expand_sse_fabs (tmp, NULL);
19155 : :
19156 : 0 : ix86_sse_copysign_to_positive (tmp, tmp, res, mask);
19157 : : }
19158 : 0 : emit_move_insn (res, tmp);
19159 : :
19160 : 0 : emit_label (label);
19161 : 0 : LABEL_NUSES (label) = 1;
19162 : :
19163 : 0 : emit_move_insn (operand0, res);
19164 : 0 : }
19165 : :
19166 : : /* Expand SSE sequence for computing trunc
19167 : : from OPERAND1 storing into OPERAND0. */
19168 : : void
19169 : 144 : ix86_expand_trunc (rtx operand0, rtx operand1)
19170 : : {
19171 : : /* C code for SSE variant we expand below.
19172 : : double xa = fabs (x), x2;
19173 : : if (!isless (xa, TWO52))
19174 : : return x;
19175 : : x2 = (double)(long)x;
19176 : : if (HONOR_SIGNED_ZEROS (mode))
19177 : : return copysign (x2, x);
19178 : : return x2;
19179 : : */
19180 : 144 : machine_mode mode = GET_MODE (operand0);
19181 : 144 : rtx xa, xi, TWO52, res, mask;
19182 : 144 : rtx_code_label *label;
19183 : :
19184 : 144 : TWO52 = ix86_gen_TWO52 (mode);
19185 : :
19186 : : /* Temporary for holding the result, initialized to the input
19187 : : operand to ease control flow. */
19188 : 144 : res = copy_to_reg (operand1);
19189 : :
19190 : : /* xa = abs (operand1) */
19191 : 144 : xa = ix86_expand_sse_fabs (res, &mask);
19192 : :
19193 : : /* if (!isless (xa, TWO52)) goto label; */
19194 : 144 : label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
19195 : :
19196 : : /* xa = (double)(long)x */
19197 : 144 : xi = gen_reg_rtx (int_mode_for_mode (mode).require ());
19198 : 144 : expand_fix (xi, res, 0);
19199 : 144 : expand_float (xa, xi, 0);
19200 : :
19201 : 144 : if (HONOR_SIGNED_ZEROS (mode))
19202 : 130 : ix86_sse_copysign_to_positive (xa, xa, res, mask);
19203 : :
19204 : 144 : emit_move_insn (res, xa);
19205 : :
19206 : 144 : emit_label (label);
19207 : 144 : LABEL_NUSES (label) = 1;
19208 : :
19209 : 144 : emit_move_insn (operand0, res);
19210 : 144 : }
19211 : :
19212 : : /* Expand SSE sequence for computing trunc from OPERAND1 storing
19213 : : into OPERAND0 without relying on DImode truncation via cvttsd2siq
19214 : : that is only available on 64bit targets. */
19215 : : void
19216 : 0 : ix86_expand_truncdf_32 (rtx operand0, rtx operand1)
19217 : : {
19218 : 0 : machine_mode mode = GET_MODE (operand0);
19219 : 0 : rtx xa, xa2, TWO52, tmp, one, res, mask;
19220 : 0 : rtx_code_label *label;
19221 : :
19222 : : /* C code for SSE variant we expand below.
19223 : : double xa = fabs (x), x2;
19224 : : if (!isless (xa, TWO52))
19225 : : return x;
19226 : : xa2 = xa + TWO52 - TWO52;
19227 : : Compensate:
19228 : : if (xa2 > xa)
19229 : : xa2 -= 1.0;
19230 : : x2 = copysign (xa2, x);
19231 : : return x2;
19232 : : */
19233 : :
19234 : 0 : TWO52 = ix86_gen_TWO52 (mode);
19235 : :
19236 : : /* Temporary for holding the result, initialized to the input
19237 : : operand to ease control flow. */
19238 : 0 : res =copy_to_reg (operand1);
19239 : :
19240 : : /* xa = abs (operand1) */
19241 : 0 : xa = ix86_expand_sse_fabs (res, &mask);
19242 : :
19243 : : /* if (!isless (xa, TWO52)) goto label; */
19244 : 0 : label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
19245 : :
19246 : : /* xa2 = xa + TWO52 - TWO52; */
19247 : 0 : xa2 = expand_simple_binop (mode, PLUS, xa, TWO52, NULL_RTX, 0, OPTAB_DIRECT);
19248 : 0 : xa2 = expand_simple_binop (mode, MINUS, xa2, TWO52, xa2, 0, OPTAB_DIRECT);
19249 : :
19250 : : /* generate 1.0 */
19251 : 0 : one = force_reg (mode, const_double_from_real_value (dconst1, mode));
19252 : :
19253 : : /* Compensate: xa2 = xa2 - (xa2 > xa ? 1 : 0) */
19254 : 0 : tmp = ix86_expand_sse_compare_mask (UNGT, xa2, xa, false);
19255 : 0 : emit_insn (gen_rtx_SET (tmp, gen_rtx_AND (mode, one, tmp)));
19256 : 0 : tmp = expand_simple_binop (mode, MINUS,
19257 : : xa2, tmp, NULL_RTX, 0, OPTAB_DIRECT);
19258 : : /* Remove the sign with FE_DOWNWARD, where x - x = -0.0. */
19259 : 0 : if (HONOR_SIGNED_ZEROS (mode) && flag_rounding_math)
19260 : 0 : tmp = ix86_expand_sse_fabs (tmp, NULL);
19261 : :
19262 : : /* res = copysign (xa2, operand1) */
19263 : 0 : ix86_sse_copysign_to_positive (res, tmp, res, mask);
19264 : :
19265 : 0 : emit_label (label);
19266 : 0 : LABEL_NUSES (label) = 1;
19267 : :
19268 : 0 : emit_move_insn (operand0, res);
19269 : 0 : }
19270 : :
19271 : : /* Expand SSE sequence for computing round
19272 : : from OPERAND1 storing into OPERAND0. */
19273 : : void
19274 : 14 : ix86_expand_round (rtx operand0, rtx operand1)
19275 : : {
19276 : : /* C code for the stuff we're doing below:
19277 : : double xa = fabs (x);
19278 : : if (!isless (xa, TWO52))
19279 : : return x;
19280 : : xa = (double)(long)(xa + nextafter (0.5, 0.0));
19281 : : return copysign (xa, x);
19282 : : */
19283 : 14 : machine_mode mode = GET_MODE (operand0);
19284 : 14 : rtx res, TWO52, xa, xi, half, mask;
19285 : 14 : rtx_code_label *label;
19286 : 14 : const struct real_format *fmt;
19287 : 14 : REAL_VALUE_TYPE pred_half, half_minus_pred_half;
19288 : :
19289 : : /* Temporary for holding the result, initialized to the input
19290 : : operand to ease control flow. */
19291 : 14 : res = copy_to_reg (operand1);
19292 : :
19293 : 14 : TWO52 = ix86_gen_TWO52 (mode);
19294 : 14 : xa = ix86_expand_sse_fabs (res, &mask);
19295 : 14 : label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
19296 : :
19297 : : /* load nextafter (0.5, 0.0) */
19298 : 14 : fmt = REAL_MODE_FORMAT (mode);
19299 : 14 : real_2expN (&half_minus_pred_half, -(fmt->p) - 1, mode);
19300 : 14 : real_arithmetic (&pred_half, MINUS_EXPR, &dconsthalf, &half_minus_pred_half);
19301 : :
19302 : : /* xa = xa + 0.5 */
19303 : 14 : half = force_reg (mode, const_double_from_real_value (pred_half, mode));
19304 : 14 : xa = expand_simple_binop (mode, PLUS, xa, half, NULL_RTX, 0, OPTAB_DIRECT);
19305 : :
19306 : : /* xa = (double)(int64_t)xa */
19307 : 14 : xi = gen_reg_rtx (int_mode_for_mode (mode).require ());
19308 : 14 : expand_fix (xi, xa, 0);
19309 : 14 : expand_float (xa, xi, 0);
19310 : :
19311 : : /* res = copysign (xa, operand1) */
19312 : 14 : ix86_sse_copysign_to_positive (res, xa, res, mask);
19313 : :
19314 : 14 : emit_label (label);
19315 : 14 : LABEL_NUSES (label) = 1;
19316 : :
19317 : 14 : emit_move_insn (operand0, res);
19318 : 14 : }
19319 : :
19320 : : /* Expand SSE sequence for computing round from OPERAND1 storing
19321 : : into OPERAND0 without relying on DImode truncation via cvttsd2siq
19322 : : that is only available on 64bit targets. */
19323 : : void
19324 : 0 : ix86_expand_rounddf_32 (rtx operand0, rtx operand1)
19325 : : {
19326 : : /* C code for the stuff we expand below.
19327 : : double xa = fabs (x), xa2, x2;
19328 : : if (!isless (xa, TWO52))
19329 : : return x;
19330 : : Using the absolute value and copying back sign makes
19331 : : -0.0 -> -0.0 correct.
19332 : : xa2 = xa + TWO52 - TWO52;
19333 : : Compensate.
19334 : : dxa = xa2 - xa;
19335 : : if (dxa <= -0.5)
19336 : : xa2 += 1;
19337 : : else if (dxa > 0.5)
19338 : : xa2 -= 1;
19339 : : x2 = copysign (xa2, x);
19340 : : return x2;
19341 : : */
19342 : 0 : machine_mode mode = GET_MODE (operand0);
19343 : 0 : rtx xa, xa2, dxa, TWO52, tmp, half, mhalf, one, res, mask;
19344 : 0 : rtx_code_label *label;
19345 : :
19346 : 0 : TWO52 = ix86_gen_TWO52 (mode);
19347 : :
19348 : : /* Temporary for holding the result, initialized to the input
19349 : : operand to ease control flow. */
19350 : 0 : res = copy_to_reg (operand1);
19351 : :
19352 : : /* xa = abs (operand1) */
19353 : 0 : xa = ix86_expand_sse_fabs (res, &mask);
19354 : :
19355 : : /* if (!isless (xa, TWO52)) goto label; */
19356 : 0 : label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
19357 : :
19358 : : /* xa2 = xa + TWO52 - TWO52; */
19359 : 0 : xa2 = expand_simple_binop (mode, PLUS, xa, TWO52, NULL_RTX, 0, OPTAB_DIRECT);
19360 : 0 : xa2 = expand_simple_binop (mode, MINUS, xa2, TWO52, xa2, 0, OPTAB_DIRECT);
19361 : :
19362 : : /* dxa = xa2 - xa; */
19363 : 0 : dxa = expand_simple_binop (mode, MINUS, xa2, xa, NULL_RTX, 0, OPTAB_DIRECT);
19364 : :
19365 : : /* generate 0.5, 1.0 and -0.5 */
19366 : 0 : half = force_reg (mode, const_double_from_real_value (dconsthalf, mode));
19367 : 0 : one = expand_simple_binop (mode, PLUS, half, half, NULL_RTX, 0, OPTAB_DIRECT);
19368 : 0 : mhalf = expand_simple_binop (mode, MINUS, half, one, NULL_RTX,
19369 : : 0, OPTAB_DIRECT);
19370 : :
19371 : : /* Compensate. */
19372 : : /* xa2 = xa2 - (dxa > 0.5 ? 1 : 0) */
19373 : 0 : tmp = ix86_expand_sse_compare_mask (UNGT, dxa, half, false);
19374 : 0 : emit_insn (gen_rtx_SET (tmp, gen_rtx_AND (mode, tmp, one)));
19375 : 0 : xa2 = expand_simple_binop (mode, MINUS, xa2, tmp, NULL_RTX, 0, OPTAB_DIRECT);
19376 : : /* xa2 = xa2 + (dxa <= -0.5 ? 1 : 0) */
19377 : 0 : tmp = ix86_expand_sse_compare_mask (UNGE, mhalf, dxa, false);
19378 : 0 : emit_insn (gen_rtx_SET (tmp, gen_rtx_AND (mode, tmp, one)));
19379 : 0 : xa2 = expand_simple_binop (mode, PLUS, xa2, tmp, NULL_RTX, 0, OPTAB_DIRECT);
19380 : :
19381 : : /* res = copysign (xa2, operand1) */
19382 : 0 : ix86_sse_copysign_to_positive (res, xa2, res, mask);
19383 : :
19384 : 0 : emit_label (label);
19385 : 0 : LABEL_NUSES (label) = 1;
19386 : :
19387 : 0 : emit_move_insn (operand0, res);
19388 : 0 : }
19389 : :
19390 : : /* Expand SSE sequence for computing round
19391 : : from OP1 storing into OP0 using sse4 round insn. */
19392 : : void
19393 : 9 : ix86_expand_round_sse4 (rtx op0, rtx op1)
19394 : : {
19395 : 9 : machine_mode mode = GET_MODE (op0);
19396 : 9 : rtx e1, e2, res, half;
19397 : 9 : const struct real_format *fmt;
19398 : 9 : REAL_VALUE_TYPE pred_half, half_minus_pred_half;
19399 : 9 : rtx (*gen_copysign) (rtx, rtx, rtx);
19400 : 9 : rtx (*gen_round) (rtx, rtx, rtx);
19401 : :
19402 : 9 : switch (mode)
19403 : : {
19404 : : case E_HFmode:
19405 : : gen_copysign = gen_copysignhf3;
19406 : : gen_round = gen_sse4_1_roundhf2;
19407 : : break;
19408 : 4 : case E_SFmode:
19409 : 4 : gen_copysign = gen_copysignsf3;
19410 : 4 : gen_round = gen_sse4_1_roundsf2;
19411 : 4 : break;
19412 : 4 : case E_DFmode:
19413 : 4 : gen_copysign = gen_copysigndf3;
19414 : 4 : gen_round = gen_sse4_1_rounddf2;
19415 : 4 : break;
19416 : 0 : default:
19417 : 0 : gcc_unreachable ();
19418 : : }
19419 : :
19420 : : /* round (a) = trunc (a + copysign (0.5, a)) */
19421 : :
19422 : : /* load nextafter (0.5, 0.0) */
19423 : 9 : fmt = REAL_MODE_FORMAT (mode);
19424 : 9 : real_2expN (&half_minus_pred_half, -(fmt->p) - 1, mode);
19425 : 9 : real_arithmetic (&pred_half, MINUS_EXPR, &dconsthalf, &half_minus_pred_half);
19426 : 9 : half = const_double_from_real_value (pred_half, mode);
19427 : :
19428 : : /* e1 = copysign (0.5, op1) */
19429 : 9 : e1 = gen_reg_rtx (mode);
19430 : 9 : emit_insn (gen_copysign (e1, half, op1));
19431 : :
19432 : : /* e2 = op1 + e1 */
19433 : 9 : e2 = expand_simple_binop (mode, PLUS, op1, e1, NULL_RTX, 0, OPTAB_DIRECT);
19434 : :
19435 : : /* res = trunc (e2) */
19436 : 9 : res = gen_reg_rtx (mode);
19437 : 9 : emit_insn (gen_round (res, e2, GEN_INT (ROUND_TRUNC)));
19438 : :
19439 : 9 : emit_move_insn (op0, res);
19440 : 9 : }
19441 : :
19442 : : /* A cached (set (nil) (vselect (vconcat (nil) (nil)) (parallel [])))
19443 : : insn, so that expand_vselect{,_vconcat} doesn't have to create a fresh
19444 : : insn every time. */
19445 : :
19446 : : static GTY(()) rtx_insn *vselect_insn;
19447 : :
19448 : : /* Initialize vselect_insn. */
19449 : :
19450 : : static void
19451 : 5931 : init_vselect_insn (void)
19452 : : {
19453 : 5931 : unsigned i;
19454 : 5931 : rtx x;
19455 : :
19456 : 5931 : x = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (MAX_VECT_LEN));
19457 : 385515 : for (i = 0; i < MAX_VECT_LEN; ++i)
19458 : 379584 : XVECEXP (x, 0, i) = const0_rtx;
19459 : 5931 : x = gen_rtx_VEC_SELECT (V2DFmode, gen_rtx_VEC_CONCAT (V4DFmode, const0_rtx,
19460 : : const0_rtx), x);
19461 : 5931 : x = gen_rtx_SET (const0_rtx, x);
19462 : 5931 : start_sequence ();
19463 : 5931 : vselect_insn = emit_insn (x);
19464 : 5931 : end_sequence ();
19465 : 5931 : }
19466 : :
19467 : : /* Construct (set target (vec_select op0 (parallel perm))) and
19468 : : return true if that's a valid instruction in the active ISA. */
19469 : :
19470 : : static bool
19471 : 439150 : expand_vselect (rtx target, rtx op0, const unsigned char *perm,
19472 : : unsigned nelt, bool testing_p)
19473 : : {
19474 : 439150 : unsigned int i;
19475 : 439150 : rtx x, save_vconcat;
19476 : 439150 : int icode;
19477 : :
19478 : 439150 : if (vselect_insn == NULL_RTX)
19479 : 1334 : init_vselect_insn ();
19480 : :
19481 : 439150 : x = XEXP (SET_SRC (PATTERN (vselect_insn)), 1);
19482 : 439150 : PUT_NUM_ELEM (XVEC (x, 0), nelt);
19483 : 3519904 : for (i = 0; i < nelt; ++i)
19484 : 3080754 : XVECEXP (x, 0, i) = GEN_INT (perm[i]);
19485 : 439150 : save_vconcat = XEXP (SET_SRC (PATTERN (vselect_insn)), 0);
19486 : 439150 : XEXP (SET_SRC (PATTERN (vselect_insn)), 0) = op0;
19487 : 439150 : PUT_MODE (SET_SRC (PATTERN (vselect_insn)), GET_MODE (target));
19488 : 439150 : SET_DEST (PATTERN (vselect_insn)) = target;
19489 : 439150 : icode = recog_memoized (vselect_insn);
19490 : :
19491 : 439150 : if (icode >= 0 && !testing_p)
19492 : 55963 : emit_insn (copy_rtx (PATTERN (vselect_insn)));
19493 : :
19494 : 439150 : SET_DEST (PATTERN (vselect_insn)) = const0_rtx;
19495 : 439150 : XEXP (SET_SRC (PATTERN (vselect_insn)), 0) = save_vconcat;
19496 : 439150 : INSN_CODE (vselect_insn) = -1;
19497 : :
19498 : 439150 : return icode >= 0;
19499 : : }
19500 : :
19501 : : /* Similar, but generate a vec_concat from op0 and op1 as well. */
19502 : :
19503 : : static bool
19504 : 382000 : expand_vselect_vconcat (rtx target, rtx op0, rtx op1,
19505 : : const unsigned char *perm, unsigned nelt,
19506 : : bool testing_p)
19507 : : {
19508 : 382000 : machine_mode v2mode;
19509 : 382000 : rtx x;
19510 : 382000 : bool ok;
19511 : :
19512 : 382000 : if (vselect_insn == NULL_RTX)
19513 : 4597 : init_vselect_insn ();
19514 : :
19515 : 764000 : if (!GET_MODE_2XWIDER_MODE (GET_MODE (op0)).exists (&v2mode))
19516 : : return false;
19517 : 382000 : x = XEXP (SET_SRC (PATTERN (vselect_insn)), 0);
19518 : 382000 : PUT_MODE (x, v2mode);
19519 : 382000 : XEXP (x, 0) = op0;
19520 : 382000 : XEXP (x, 1) = op1;
19521 : 382000 : ok = expand_vselect (target, x, perm, nelt, testing_p);
19522 : 382000 : XEXP (x, 0) = const0_rtx;
19523 : 382000 : XEXP (x, 1) = const0_rtx;
19524 : 382000 : return ok;
19525 : : }
19526 : :
19527 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement D
19528 : : using movss or movsd. */
19529 : : static bool
19530 : 222842 : expand_vec_perm_movs (struct expand_vec_perm_d *d)
19531 : : {
19532 : 222842 : machine_mode vmode = d->vmode;
19533 : 222842 : unsigned i, nelt = d->nelt;
19534 : 222842 : rtx x;
19535 : :
19536 : 222842 : if (d->one_operand_p)
19537 : : return false;
19538 : :
19539 : 201296 : if (!(TARGET_SSE && (vmode == V4SFmode || vmode == V4SImode))
19540 : 104368 : && !(TARGET_MMX_WITH_SSE && (vmode == V2SFmode || vmode == V2SImode))
19541 : 66329 : && !(TARGET_SSE2 && (vmode == V2DFmode || vmode == V2DImode)))
19542 : : return false;
19543 : :
19544 : : /* Only the first element is changed. */
19545 : 141139 : if (d->perm[0] != nelt && d->perm[0] != 0)
19546 : : return false;
19547 : 112327 : for (i = 1; i < nelt; ++i)
19548 : 82398 : if (d->perm[i] != i + nelt - d->perm[0])
19549 : : return false;
19550 : :
19551 : 29929 : if (d->testing_p)
19552 : : return true;
19553 : :
19554 : 4255 : if (d->perm[0] == nelt)
19555 : 0 : x = gen_rtx_VEC_MERGE (vmode, d->op1, d->op0, GEN_INT (1));
19556 : : else
19557 : 4255 : x = gen_rtx_VEC_MERGE (vmode, d->op0, d->op1, GEN_INT (1));
19558 : :
19559 : 4255 : emit_insn (gen_rtx_SET (d->target, x));
19560 : :
19561 : 4255 : return true;
19562 : : }
19563 : :
19564 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement D
19565 : : using insertps. */
19566 : : static bool
19567 : 192913 : expand_vec_perm_insertps (struct expand_vec_perm_d *d)
19568 : : {
19569 : 192913 : machine_mode vmode = d->vmode;
19570 : 192913 : unsigned i, cnt_s, nelt = d->nelt;
19571 : 192913 : int cnt_d = -1;
19572 : 192913 : rtx src, dst;
19573 : :
19574 : 192913 : if (d->one_operand_p)
19575 : : return false;
19576 : :
19577 : 171367 : if (!(TARGET_SSE4_1
19578 : 34003 : && (vmode == V4SFmode || vmode == V4SImode
19579 : 23576 : || (TARGET_MMX_WITH_SSE
19580 : 17178 : && (vmode == V2SFmode || vmode == V2SImode)))))
19581 : : return false;
19582 : :
19583 : 48710 : for (i = 0; i < nelt; ++i)
19584 : : {
19585 : 46919 : if (d->perm[i] == i)
19586 : 9076 : continue;
19587 : 37843 : if (cnt_d != -1)
19588 : : {
19589 : : cnt_d = -1;
19590 : : break;
19591 : : }
19592 : 19817 : cnt_d = i;
19593 : : }
19594 : :
19595 : 19817 : if (cnt_d == -1)
19596 : : {
19597 : 39834 : for (i = 0; i < nelt; ++i)
19598 : : {
19599 : 38132 : if (d->perm[i] == i + nelt)
19600 : 3782 : continue;
19601 : 34350 : if (cnt_d != -1)
19602 : : return false;
19603 : 18026 : cnt_d = i;
19604 : : }
19605 : :
19606 : 1702 : if (cnt_d == -1)
19607 : : return false;
19608 : : }
19609 : :
19610 : 3493 : if (d->testing_p)
19611 : : return true;
19612 : :
19613 : 397 : gcc_assert (cnt_d != -1);
19614 : :
19615 : 397 : cnt_s = d->perm[cnt_d];
19616 : 397 : if (cnt_s < nelt)
19617 : : {
19618 : 173 : src = d->op0;
19619 : 173 : dst = d->op1;
19620 : : }
19621 : : else
19622 : : {
19623 : 224 : cnt_s -= nelt;
19624 : 224 : src = d->op1;
19625 : 224 : dst = d->op0;
19626 : : }
19627 : 397 : gcc_assert (cnt_s < nelt);
19628 : :
19629 : 397 : rtx x = gen_sse4_1_insertps (vmode, d->target, dst, src,
19630 : 397 : GEN_INT (cnt_s << 6 | cnt_d << 4));
19631 : 397 : emit_insn (x);
19632 : :
19633 : 397 : return true;
19634 : : }
19635 : :
19636 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement D
19637 : : in terms of blendp[sd] / pblendw / pblendvb / vpblendd. */
19638 : :
19639 : : static bool
19640 : 227206 : expand_vec_perm_blend (struct expand_vec_perm_d *d)
19641 : : {
19642 : 227206 : machine_mode mmode, vmode = d->vmode;
19643 : 227206 : unsigned i, nelt = d->nelt;
19644 : 227206 : unsigned HOST_WIDE_INT mask;
19645 : 227206 : rtx target, op0, op1, maskop, x;
19646 : 227206 : rtx rperm[32], vperm;
19647 : :
19648 : 227206 : if (d->one_operand_p)
19649 : : return false;
19650 : 5005 : if (TARGET_AVX512F && GET_MODE_SIZE (vmode) == 64
19651 : 206882 : && (TARGET_AVX512BW
19652 : 833 : || GET_MODE_UNIT_SIZE (vmode) >= 4))
19653 : : ;
19654 : 213468 : else if (TARGET_AVX2 && GET_MODE_SIZE (vmode) == 32)
19655 : : ;
19656 : 198393 : else if (TARGET_AVX && (vmode == V4DFmode || vmode == V8SFmode))
19657 : : ;
19658 : 191517 : else if (TARGET_SSE4_1
19659 : 220444 : && (GET_MODE_SIZE (vmode) == 16
19660 : 16896 : || (TARGET_MMX_WITH_SSE && GET_MODE_SIZE (vmode) == 8)
19661 : 1270 : || GET_MODE_SIZE (vmode) == 4))
19662 : : ;
19663 : : else
19664 : 163199 : return false;
19665 : :
19666 : : /* This is a blend, not a permute. Elements must stay in their
19667 : : respective lanes. */
19668 : 104854 : for (i = 0; i < nelt; ++i)
19669 : : {
19670 : 100490 : unsigned e = d->perm[i];
19671 : 100490 : if (!(e == i || e == i + nelt))
19672 : : return false;
19673 : : }
19674 : :
19675 : 4364 : if (d->testing_p)
19676 : : return true;
19677 : :
19678 : : /* ??? Without SSE4.1, we could implement this with and/andn/or. This
19679 : : decision should be extracted elsewhere, so that we only try that
19680 : : sequence once all budget==3 options have been tried. */
19681 : 3125 : target = d->target;
19682 : 3125 : op0 = d->op0;
19683 : 3125 : op1 = d->op1;
19684 : 3125 : mask = 0;
19685 : :
19686 : 3125 : switch (vmode)
19687 : : {
19688 : : case E_V8DFmode:
19689 : : case E_V16SFmode:
19690 : : case E_V4DFmode:
19691 : : case E_V8SFmode:
19692 : : case E_V2DFmode:
19693 : : case E_V4SFmode:
19694 : : case E_V2SFmode:
19695 : : case E_V2HImode:
19696 : : case E_V4HImode:
19697 : : case E_V8HImode:
19698 : : case E_V8SImode:
19699 : : case E_V32HImode:
19700 : : case E_V64QImode:
19701 : : case E_V16SImode:
19702 : : case E_V8DImode:
19703 : 11004 : for (i = 0; i < nelt; ++i)
19704 : 9496 : mask |= ((unsigned HOST_WIDE_INT) (d->perm[i] >= nelt)) << i;
19705 : : break;
19706 : :
19707 : : case E_V2DImode:
19708 : 0 : for (i = 0; i < 2; ++i)
19709 : 0 : mask |= (d->perm[i] >= 2 ? 15 : 0) << (i * 4);
19710 : 0 : vmode = V8HImode;
19711 : 0 : goto do_subreg;
19712 : :
19713 : : case E_V2SImode:
19714 : 24 : for (i = 0; i < 2; ++i)
19715 : 24 : mask |= (d->perm[i] >= 2 ? 3 : 0) << (i * 2);
19716 : 8 : vmode = V4HImode;
19717 : 8 : goto do_subreg;
19718 : :
19719 : 701 : case E_V4SImode:
19720 : 701 : if (TARGET_AVX2)
19721 : : {
19722 : : /* Use vpblendd instead of vpblendw. */
19723 : 125 : for (i = 0; i < nelt; ++i)
19724 : 100 : mask |= ((unsigned HOST_WIDE_INT) (d->perm[i] >= nelt)) << i;
19725 : : break;
19726 : : }
19727 : : else
19728 : : {
19729 : 3380 : for (i = 0; i < 4; ++i)
19730 : 4256 : mask |= (d->perm[i] >= 4 ? 3 : 0) << (i * 2);
19731 : 676 : vmode = V8HImode;
19732 : 676 : goto do_subreg;
19733 : : }
19734 : :
19735 : : case E_V16QImode:
19736 : : /* See if bytes move in pairs so we can use pblendw with
19737 : : an immediate argument, rather than pblendvb with a vector
19738 : : argument. */
19739 : 105 : for (i = 0; i < 16; i += 2)
19740 : 104 : if (d->perm[i] + 1 != d->perm[i + 1])
19741 : : {
19742 : 85 : use_pblendvb:
19743 : 10514 : for (i = 0; i < nelt; ++i)
19744 : 10072 : rperm[i] = (d->perm[i] < nelt ? const0_rtx : constm1_rtx);
19745 : :
19746 : 442 : finish_pblendvb:
19747 : 571 : vperm = gen_rtx_CONST_VECTOR (vmode, gen_rtvec_v (nelt, rperm));
19748 : 571 : vperm = force_reg (vmode, vperm);
19749 : :
19750 : 1142 : if (GET_MODE_SIZE (vmode) == 4)
19751 : 72 : emit_insn (gen_mmx_pblendvb_v4qi (target, op0, op1, vperm));
19752 : 998 : else if (GET_MODE_SIZE (vmode) == 8)
19753 : 29 : emit_insn (gen_mmx_pblendvb_v8qi (target, op0, op1, vperm));
19754 : 940 : else if (GET_MODE_SIZE (vmode) == 16)
19755 : 85 : emit_insn (gen_sse4_1_pblendvb (target, op0, op1, vperm));
19756 : : else
19757 : 385 : emit_insn (gen_avx2_pblendvb (target, op0, op1, vperm));
19758 : 571 : if (target != d->target)
19759 : 129 : emit_move_insn (d->target, gen_lowpart (d->vmode, target));
19760 : 571 : return true;
19761 : : }
19762 : :
19763 : 9 : for (i = 0; i < 8; ++i)
19764 : 8 : mask |= (d->perm[i * 2] >= 16) << i;
19765 : : vmode = V8HImode;
19766 : : /* FALLTHRU */
19767 : :
19768 : 1021 : do_subreg:
19769 : 1021 : target = gen_reg_rtx (vmode);
19770 : 1021 : op0 = gen_lowpart (vmode, op0);
19771 : 1021 : op1 = gen_lowpart (vmode, op1);
19772 : 1021 : break;
19773 : :
19774 : : case E_V8QImode:
19775 : 39 : for (i = 0; i < 8; i += 2)
19776 : 38 : if (d->perm[i] + 1 != d->perm[i + 1])
19777 : 29 : goto use_pblendvb;
19778 : :
19779 : 5 : for (i = 0; i < 4; ++i)
19780 : 4 : mask |= (d->perm[i * 2] >= 8) << i;
19781 : 1 : vmode = V4HImode;
19782 : 1 : goto do_subreg;
19783 : :
19784 : : case E_V4QImode:
19785 : 72 : for (i = 0; i < 4; i += 2)
19786 : 72 : if (d->perm[i] + 1 != d->perm[i + 1])
19787 : 72 : goto use_pblendvb;
19788 : :
19789 : 0 : for (i = 0; i < 2; ++i)
19790 : 0 : mask |= (d->perm[i * 2] >= 4) << i;
19791 : 0 : vmode = V2HImode;
19792 : 0 : goto do_subreg;
19793 : :
19794 : : case E_V32QImode:
19795 : : /* See if bytes move in pairs. If not, vpblendvb must be used. */
19796 : 5305 : for (i = 0; i < 32; i += 2)
19797 : 5008 : if (d->perm[i] + 1 != d->perm[i + 1])
19798 : 256 : goto use_pblendvb;
19799 : : /* See if bytes move in quadruplets. If yes, vpblendd
19800 : : with immediate can be used. */
19801 : 2673 : for (i = 0; i < 32; i += 4)
19802 : 2376 : if (d->perm[i] + 2 != d->perm[i + 2])
19803 : : break;
19804 : 297 : if (i < 32)
19805 : : {
19806 : : /* See if bytes move the same in both lanes. If yes,
19807 : : vpblendw with immediate can be used. */
19808 : 0 : for (i = 0; i < 16; i += 2)
19809 : 0 : if (d->perm[i] + 16 != d->perm[i + 16])
19810 : 0 : goto use_pblendvb;
19811 : :
19812 : : /* Use vpblendw. */
19813 : 0 : for (i = 0; i < 16; ++i)
19814 : 0 : mask |= (d->perm[i * 2] >= 32) << i;
19815 : 0 : vmode = V16HImode;
19816 : 0 : goto do_subreg;
19817 : : }
19818 : :
19819 : : /* Use vpblendd. */
19820 : 2673 : for (i = 0; i < 8; ++i)
19821 : 2376 : mask |= (d->perm[i * 4] >= 32) << i;
19822 : 297 : vmode = V8SImode;
19823 : 297 : goto do_subreg;
19824 : :
19825 : : case E_V16HImode:
19826 : : /* See if words move in pairs. If yes, vpblendd can be used. */
19827 : 273 : for (i = 0; i < 16; i += 2)
19828 : 257 : if (d->perm[i] + 1 != d->perm[i + 1])
19829 : : break;
19830 : 145 : if (i < 16)
19831 : : {
19832 : : /* See if words move the same in both lanes. If not,
19833 : : vpblendvb must be used. */
19834 : 146 : for (i = 0; i < 8; i++)
19835 : 146 : if (d->perm[i] + 8 != d->perm[i + 8])
19836 : : {
19837 : : /* Use vpblendvb. */
19838 : 4257 : for (i = 0; i < 32; ++i)
19839 : 4128 : rperm[i] = (d->perm[i / 2] < 16 ? const0_rtx : constm1_rtx);
19840 : :
19841 : 129 : vmode = V32QImode;
19842 : 129 : nelt = 32;
19843 : 129 : target = gen_reg_rtx (vmode);
19844 : 129 : op0 = gen_lowpart (vmode, op0);
19845 : 129 : op1 = gen_lowpart (vmode, op1);
19846 : 129 : goto finish_pblendvb;
19847 : : }
19848 : :
19849 : : /* Use vpblendw. */
19850 : 0 : for (i = 0; i < 16; ++i)
19851 : 0 : mask |= (d->perm[i] >= 16) << i;
19852 : : break;
19853 : : }
19854 : :
19855 : : /* Use vpblendd. */
19856 : 144 : for (i = 0; i < 8; ++i)
19857 : 128 : mask |= (d->perm[i * 2] >= 16) << i;
19858 : 16 : vmode = V8SImode;
19859 : 16 : goto do_subreg;
19860 : :
19861 : : case E_V4DImode:
19862 : : /* Use vpblendd. */
19863 : 110 : for (i = 0; i < 4; ++i)
19864 : 135 : mask |= (d->perm[i] >= 4 ? 3 : 0) << (i * 2);
19865 : 22 : vmode = V8SImode;
19866 : 22 : goto do_subreg;
19867 : :
19868 : 0 : default:
19869 : 0 : gcc_unreachable ();
19870 : : }
19871 : :
19872 : 2554 : switch (vmode)
19873 : : {
19874 : : case E_V8DFmode:
19875 : : case E_V8DImode:
19876 : : mmode = QImode;
19877 : : break;
19878 : 5 : case E_V16SFmode:
19879 : 5 : case E_V16SImode:
19880 : 5 : mmode = HImode;
19881 : 5 : break;
19882 : 6 : case E_V32HImode:
19883 : 6 : mmode = SImode;
19884 : 6 : break;
19885 : 1 : case E_V64QImode:
19886 : 1 : mmode = DImode;
19887 : 1 : break;
19888 : : default:
19889 : : mmode = VOIDmode;
19890 : : }
19891 : :
19892 : : /* Canonicalize vec_merge. */
19893 : 2554 : if (swap_commutative_operands_p (op1, op0)
19894 : : /* Two operands have same precedence, then
19895 : : first bit of mask select first operand. */
19896 : 2554 : || (!swap_commutative_operands_p (op0, op1)
19897 : 2554 : && !(mask & 1)))
19898 : : {
19899 : 2547 : unsigned n_elts = GET_MODE_NUNITS (vmode);
19900 : 2547 : std::swap (op0, op1);
19901 : 2547 : unsigned HOST_WIDE_INT mask_all = HOST_WIDE_INT_1U;
19902 : 2547 : if (n_elts == HOST_BITS_PER_WIDE_INT)
19903 : : mask_all = -1;
19904 : : else
19905 : 2546 : mask_all = (HOST_WIDE_INT_1U << n_elts) - 1;
19906 : 2547 : mask = ~mask & mask_all;
19907 : : }
19908 : :
19909 : 2554 : if (mmode != VOIDmode)
19910 : 16 : maskop = force_reg (mmode, gen_int_mode (mask, mmode));
19911 : : else
19912 : 2538 : maskop = GEN_INT (mask);
19913 : :
19914 : : /* This matches five different patterns with the different modes. */
19915 : 2554 : x = gen_rtx_VEC_MERGE (vmode, op1, op0, maskop);
19916 : 2554 : x = gen_rtx_SET (target, x);
19917 : 2554 : emit_insn (x);
19918 : 2554 : if (target != d->target)
19919 : 1021 : emit_move_insn (d->target, gen_lowpart (d->vmode, target));
19920 : :
19921 : : return true;
19922 : : }
19923 : :
19924 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement D
19925 : : in terms of the variable form of vpermilps.
19926 : :
19927 : : Note that we will have already failed the immediate input vpermilps,
19928 : : which requires that the high and low part shuffle be identical; the
19929 : : variable form doesn't require that. */
19930 : :
19931 : : static bool
19932 : 140026 : expand_vec_perm_vpermil (struct expand_vec_perm_d *d)
19933 : : {
19934 : 140026 : rtx rperm[8], vperm;
19935 : 140026 : unsigned i;
19936 : :
19937 : 140026 : if (!TARGET_AVX || d->vmode != V8SFmode || !d->one_operand_p)
19938 : : return false;
19939 : :
19940 : : /* We can only permute within the 128-bit lane. */
19941 : 15174 : for (i = 0; i < 8; ++i)
19942 : : {
19943 : 14454 : unsigned e = d->perm[i];
19944 : 14454 : if (i < 4 ? e >= 4 : e < 4)
19945 : : return false;
19946 : : }
19947 : :
19948 : 720 : if (d->testing_p)
19949 : : return true;
19950 : :
19951 : 900 : for (i = 0; i < 8; ++i)
19952 : : {
19953 : 800 : unsigned e = d->perm[i];
19954 : :
19955 : : /* Within each 128-bit lane, the elements of op0 are numbered
19956 : : from 0 and the elements of op1 are numbered from 4. */
19957 : 800 : if (e >= 8 + 4)
19958 : 0 : e -= 8;
19959 : 800 : else if (e >= 4)
19960 : 400 : e -= 4;
19961 : :
19962 : 800 : rperm[i] = GEN_INT (e);
19963 : : }
19964 : :
19965 : 100 : vperm = gen_rtx_CONST_VECTOR (V8SImode, gen_rtvec_v (8, rperm));
19966 : 100 : vperm = force_reg (V8SImode, vperm);
19967 : 100 : emit_insn (gen_avx_vpermilvarv8sf3 (d->target, d->op0, vperm));
19968 : :
19969 : 100 : return true;
19970 : : }
19971 : :
19972 : : /* For V*[QHS]Imode permutations, check if the same permutation
19973 : : can't be performed in a 2x, 4x or 8x wider inner mode. */
19974 : :
19975 : : static bool
19976 : 157223 : canonicalize_vector_int_perm (const struct expand_vec_perm_d *d,
19977 : : struct expand_vec_perm_d *nd)
19978 : : {
19979 : 157223 : int i;
19980 : 157223 : machine_mode mode = VOIDmode;
19981 : :
19982 : 157223 : switch (d->vmode)
19983 : : {
19984 : : case E_V8QImode: mode = V4HImode; break;
19985 : 20017 : case E_V16QImode: mode = V8HImode; break;
19986 : 3090 : case E_V32QImode: mode = V16HImode; break;
19987 : 252 : case E_V64QImode: mode = V32HImode; break;
19988 : 9871 : case E_V4HImode: mode = V2SImode; break;
19989 : 17587 : case E_V8HImode: mode = V4SImode; break;
19990 : 1304 : case E_V16HImode: mode = V8SImode; break;
19991 : 389 : case E_V32HImode: mode = V16SImode; break;
19992 : 61189 : case E_V4SImode: mode = V2DImode; break;
19993 : 1243 : case E_V8SImode: mode = V4DImode; break;
19994 : 58 : case E_V16SImode: mode = V8DImode; break;
19995 : : default: return false;
19996 : : }
19997 : 163259 : for (i = 0; i < d->nelt; i += 2)
19998 : 157915 : if ((d->perm[i] & 1) || d->perm[i + 1] != d->perm[i] + 1)
19999 : : return false;
20000 : 5344 : nd->vmode = mode;
20001 : 5344 : nd->nelt = d->nelt / 2;
20002 : 33492 : for (i = 0; i < nd->nelt; i++)
20003 : 28148 : nd->perm[i] = d->perm[2 * i] / 2;
20004 : 10688 : if (GET_MODE_INNER (mode) != DImode)
20005 : 4011 : canonicalize_vector_int_perm (nd, nd);
20006 : 5344 : if (nd != d)
20007 : : {
20008 : 2785 : nd->one_operand_p = d->one_operand_p;
20009 : 2785 : nd->testing_p = d->testing_p;
20010 : 2785 : if (d->op0 == d->op1)
20011 : 2213 : nd->op0 = nd->op1 = gen_lowpart (nd->vmode, d->op0);
20012 : : else
20013 : : {
20014 : 572 : nd->op0 = gen_lowpart (nd->vmode, d->op0);
20015 : 572 : nd->op1 = gen_lowpart (nd->vmode, d->op1);
20016 : : }
20017 : 2785 : if (d->testing_p)
20018 : 830 : nd->target = gen_raw_REG (nd->vmode, LAST_VIRTUAL_REGISTER + 1);
20019 : : else
20020 : 1955 : nd->target = gen_reg_rtx (nd->vmode);
20021 : : }
20022 : : return true;
20023 : : }
20024 : :
20025 : : /* Return true if permutation D can be performed as VMODE permutation
20026 : : instead. */
20027 : :
20028 : : static bool
20029 : 8615 : valid_perm_using_mode_p (machine_mode vmode, struct expand_vec_perm_d *d)
20030 : : {
20031 : 8615 : unsigned int i, j, chunk;
20032 : :
20033 : 8615 : if (GET_MODE_CLASS (vmode) != MODE_VECTOR_INT
20034 : 8615 : || GET_MODE_CLASS (d->vmode) != MODE_VECTOR_INT
20035 : 24125 : || GET_MODE_SIZE (vmode) != GET_MODE_SIZE (d->vmode))
20036 : 860 : return false;
20037 : :
20038 : 15510 : if (GET_MODE_NUNITS (vmode) >= d->nelt)
20039 : : return true;
20040 : :
20041 : 7454 : chunk = d->nelt / GET_MODE_NUNITS (vmode);
20042 : 8780 : for (i = 0; i < d->nelt; i += chunk)
20043 : 8663 : if (d->perm[i] & (chunk - 1))
20044 : : return false;
20045 : : else
20046 : 10342 : for (j = 1; j < chunk; ++j)
20047 : 9016 : if (d->perm[i] + j != d->perm[i + j])
20048 : : return false;
20049 : :
20050 : : return true;
20051 : : }
20052 : :
20053 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement D
20054 : : in terms of pshufb, vpperm, vpermq, vpermd, vpermps or vperm2i128. */
20055 : :
20056 : : static bool
20057 : 139306 : expand_vec_perm_pshufb (struct expand_vec_perm_d *d)
20058 : : {
20059 : 139306 : unsigned i, nelt, eltsz, mask;
20060 : 139306 : unsigned char perm[64];
20061 : 139306 : machine_mode vmode;
20062 : 139306 : struct expand_vec_perm_d nd;
20063 : 139306 : rtx rperm[64], vperm, target, op0, op1;
20064 : :
20065 : 139306 : nelt = d->nelt;
20066 : :
20067 : 139306 : if (!d->one_operand_p)
20068 : 237186 : switch (GET_MODE_SIZE (d->vmode))
20069 : : {
20070 : 5438 : case 4:
20071 : 5438 : if (!TARGET_XOP)
20072 : : return false;
20073 : : vmode = V4QImode;
20074 : : break;
20075 : :
20076 : 13378 : case 8:
20077 : 13378 : if (!TARGET_XOP)
20078 : : return false;
20079 : : vmode = V8QImode;
20080 : : break;
20081 : :
20082 : 88793 : case 16:
20083 : 88793 : if (!TARGET_XOP)
20084 : : return false;
20085 : : vmode = V16QImode;
20086 : : break;
20087 : :
20088 : 9851 : case 32:
20089 : 9851 : if (!TARGET_AVX2)
20090 : : return false;
20091 : :
20092 : 4312 : if (valid_perm_using_mode_p (V2TImode, d))
20093 : : {
20094 : 53 : if (d->testing_p)
20095 : : return true;
20096 : :
20097 : : /* Use vperm2i128 insn. The pattern uses
20098 : : V4DImode instead of V2TImode. */
20099 : 49 : target = d->target;
20100 : 49 : if (d->vmode != V4DImode)
20101 : 12 : target = gen_reg_rtx (V4DImode);
20102 : 49 : op0 = gen_lowpart (V4DImode, d->op0);
20103 : 49 : op1 = gen_lowpart (V4DImode, d->op1);
20104 : 49 : rperm[0]
20105 : 49 : = GEN_INT ((d->perm[0] / (nelt / 2))
20106 : : | ((d->perm[nelt / 2] / (nelt / 2)) * 16));
20107 : 49 : emit_insn (gen_avx2_permv2ti (target, op0, op1, rperm[0]));
20108 : 49 : if (target != d->target)
20109 : 12 : emit_move_insn (d->target, gen_lowpart (d->vmode, target));
20110 : 49 : return true;
20111 : : }
20112 : : /* FALLTHRU */
20113 : :
20114 : 5392 : default:
20115 : 5392 : return false;
20116 : : }
20117 : : else
20118 : 41426 : switch (GET_MODE_SIZE (d->vmode))
20119 : : {
20120 : 2156 : case 4:
20121 : 2156 : if (!TARGET_SSSE3)
20122 : : return false;
20123 : : vmode = V4QImode;
20124 : : break;
20125 : :
20126 : 1174 : case 8:
20127 : 1174 : if (!TARGET_SSSE3)
20128 : : return false;
20129 : : vmode = V8QImode;
20130 : : break;
20131 : :
20132 : 11451 : case 16:
20133 : 11451 : if (!TARGET_SSSE3)
20134 : : return false;
20135 : : vmode = V16QImode;
20136 : : break;
20137 : :
20138 : 5662 : case 32:
20139 : 5662 : if (!TARGET_AVX2)
20140 : : return false;
20141 : :
20142 : : /* V4DImode should be already handled through
20143 : : expand_vselect by vpermq instruction. */
20144 : 2814 : gcc_assert (d->vmode != V4DImode);
20145 : :
20146 : 2814 : vmode = V32QImode;
20147 : 2814 : if (d->vmode == V8SImode
20148 : 2501 : || d->vmode == V16HImode
20149 : 2083 : || d->vmode == V32QImode)
20150 : : {
20151 : : /* First see if vpermq can be used for
20152 : : V8SImode/V16HImode/V32QImode. */
20153 : 2116 : if (valid_perm_using_mode_p (V4DImode, d))
20154 : : {
20155 : 215 : for (i = 0; i < 4; i++)
20156 : 172 : perm[i] = (d->perm[i * nelt / 4] * 4 / nelt) & 3;
20157 : 43 : if (d->testing_p)
20158 : : return true;
20159 : 43 : target = gen_reg_rtx (V4DImode);
20160 : 43 : if (expand_vselect (target, gen_lowpart (V4DImode, d->op0),
20161 : : perm, 4, false))
20162 : : {
20163 : 86 : emit_move_insn (d->target,
20164 : 43 : gen_lowpart (d->vmode, target));
20165 : 43 : return true;
20166 : : }
20167 : : return false;
20168 : : }
20169 : :
20170 : : /* Next see if vpermd can be used. */
20171 : 2073 : if (valid_perm_using_mode_p (V8SImode, d))
20172 : : vmode = V8SImode;
20173 : : }
20174 : : /* Or if vpermps can be used. */
20175 : 698 : else if (d->vmode == V8SFmode)
20176 : : vmode = V8SImode;
20177 : :
20178 : 1769 : if (vmode == V32QImode)
20179 : : {
20180 : : /* vpshufb only works intra lanes, it is not
20181 : : possible to shuffle bytes in between the lanes. */
20182 : 39481 : for (i = 0; i < nelt; ++i)
20183 : 38218 : if ((d->perm[i] ^ i) & (nelt / 2))
20184 : : return false;
20185 : : }
20186 : : break;
20187 : :
20188 : 270 : case 64:
20189 : 270 : if (!TARGET_AVX512BW)
20190 : : return false;
20191 : :
20192 : : /* If vpermq didn't work, vpshufb won't work either. */
20193 : 89 : if (d->vmode == V8DFmode || d->vmode == V8DImode)
20194 : : return false;
20195 : :
20196 : 66 : vmode = V64QImode;
20197 : 66 : if (d->vmode == V16SImode
20198 : 48 : || d->vmode == V32HImode
20199 : 16 : || d->vmode == V64QImode)
20200 : : {
20201 : : /* First see if vpermq can be used for
20202 : : V16SImode/V32HImode/V64QImode. */
20203 : 57 : if (valid_perm_using_mode_p (V8DImode, d))
20204 : : {
20205 : 0 : for (i = 0; i < 8; i++)
20206 : 0 : perm[i] = (d->perm[i * nelt / 8] * 8 / nelt) & 7;
20207 : 0 : if (d->testing_p)
20208 : : return true;
20209 : 0 : target = gen_reg_rtx (V8DImode);
20210 : 0 : if (expand_vselect (target, gen_lowpart (V8DImode, d->op0),
20211 : : perm, 8, false))
20212 : : {
20213 : 0 : emit_move_insn (d->target,
20214 : 0 : gen_lowpart (d->vmode, target));
20215 : 0 : return true;
20216 : : }
20217 : : return false;
20218 : : }
20219 : :
20220 : : /* Next see if vpermd can be used. */
20221 : 57 : if (valid_perm_using_mode_p (V16SImode, d))
20222 : : vmode = V16SImode;
20223 : : }
20224 : : /* Or if vpermps can be used. */
20225 : 9 : else if (d->vmode == V16SFmode)
20226 : : vmode = V16SImode;
20227 : :
20228 : 39 : if (vmode == V64QImode)
20229 : : {
20230 : : /* vpshufb only works intra lanes, it is not
20231 : : possible to shuffle bytes in between the lanes. */
20232 : 198 : for (i = 0; i < nelt; ++i)
20233 : 198 : if ((d->perm[i] ^ i) & (3 * nelt / 4))
20234 : : return false;
20235 : : }
20236 : : break;
20237 : :
20238 : : default:
20239 : : return false;
20240 : : }
20241 : :
20242 : 9887 : if (d->testing_p)
20243 : : return true;
20244 : :
20245 : : /* Try to avoid variable permutation instruction. */
20246 : 8468 : if (canonicalize_vector_int_perm (d, &nd) && expand_vec_perm_1 (&nd))
20247 : : {
20248 : 1822 : emit_move_insn (d->target, gen_lowpart (d->vmode, nd.target));
20249 : 1822 : return true;
20250 : : }
20251 : :
20252 : 6646 : if (vmode == V8SImode)
20253 : 8829 : for (i = 0; i < 8; ++i)
20254 : 7848 : rperm[i] = GEN_INT ((d->perm[i * nelt / 8] * 8 / nelt) & 7);
20255 : 5665 : else if (vmode == V16SImode)
20256 : 459 : for (i = 0; i < 16; ++i)
20257 : 432 : rperm[i] = GEN_INT ((d->perm[i * nelt / 16] * 16 / nelt) & 15);
20258 : : else
20259 : : {
20260 : 5638 : eltsz = GET_MODE_UNIT_SIZE (d->vmode);
20261 : 5638 : if (!d->one_operand_p)
20262 : 3249 : mask = 2 * nelt - 1;
20263 : 2389 : else if (vmode == V64QImode)
20264 : 0 : mask = nelt / 4 - 1;
20265 : 2389 : else if (vmode == V32QImode)
20266 : 1257 : mask = nelt / 2 - 1;
20267 : : else
20268 : 1132 : mask = nelt - 1;
20269 : :
20270 : 70274 : for (i = 0; i < nelt; ++i)
20271 : : {
20272 : 64636 : unsigned j, e = d->perm[i] & mask;
20273 : 172624 : for (j = 0; j < eltsz; ++j)
20274 : 107988 : rperm[i * eltsz + j] = GEN_INT (e * eltsz + j);
20275 : : }
20276 : : }
20277 : :
20278 : 6646 : machine_mode vpmode = vmode;
20279 : :
20280 : 6646 : nelt = GET_MODE_SIZE (vmode);
20281 : :
20282 : : /* Emulate narrow modes with V16QI instructions. */
20283 : 6646 : if (nelt < 16)
20284 : : {
20285 : 219 : rtx m128 = GEN_INT (-128);
20286 : :
20287 : : /* Remap elements from the second operand, as we have to
20288 : : account for inactive top elements from the first operand. */
20289 : 219 : if (!d->one_operand_p)
20290 : : {
20291 : 279 : for (i = 0; i < nelt; ++i)
20292 : : {
20293 : 248 : unsigned ival = UINTVAL (rperm[i]);
20294 : 248 : if (ival >= nelt)
20295 : 124 : rperm[i] = GEN_INT (ival + 16 - nelt);
20296 : : }
20297 : : }
20298 : :
20299 : : /* Fill inactive elements in the top positions with zeros. */
20300 : 2551 : for (i = nelt; i < 16; ++i)
20301 : 2332 : rperm[i] = m128;
20302 : :
20303 : : vpmode = V16QImode;
20304 : : }
20305 : :
20306 : 13292 : vperm = gen_rtx_CONST_VECTOR (vpmode,
20307 : 6646 : gen_rtvec_v (GET_MODE_NUNITS (vpmode), rperm));
20308 : 6646 : vperm = force_reg (vpmode, vperm);
20309 : :
20310 : 6646 : if (vmode == d->vmode)
20311 : 2247 : target = d->target;
20312 : : else
20313 : 4399 : target = gen_reg_rtx (vmode);
20314 : :
20315 : 6646 : op0 = gen_lowpart (vmode, d->op0);
20316 : :
20317 : 6646 : if (d->one_operand_p)
20318 : : {
20319 : 3397 : rtx (*gen) (rtx, rtx, rtx);
20320 : :
20321 : 3397 : if (vmode == V4QImode)
20322 : : gen = gen_mmx_pshufbv4qi3;
20323 : : else if (vmode == V8QImode)
20324 : : gen = gen_mmx_pshufbv8qi3;
20325 : : else if (vmode == V16QImode)
20326 : : gen = gen_ssse3_pshufbv16qi3;
20327 : : else if (vmode == V32QImode)
20328 : : gen = gen_avx2_pshufbv32qi3;
20329 : : else if (vmode == V64QImode)
20330 : : gen = gen_avx512bw_pshufbv64qi3;
20331 : : else if (vmode == V8SFmode)
20332 : : gen = gen_avx2_permvarv8sf;
20333 : : else if (vmode == V8SImode)
20334 : : gen = gen_avx2_permvarv8si;
20335 : : else if (vmode == V16SFmode)
20336 : : gen = gen_avx512f_permvarv16sf;
20337 : : else if (vmode == V16SImode)
20338 : : gen = gen_avx512f_permvarv16si;
20339 : : else
20340 : : gcc_unreachable ();
20341 : :
20342 : 3397 : emit_insn (gen (target, op0, vperm));
20343 : : }
20344 : : else
20345 : : {
20346 : 3249 : rtx (*gen) (rtx, rtx, rtx, rtx);
20347 : :
20348 : 3249 : op1 = gen_lowpart (vmode, d->op1);
20349 : :
20350 : 3249 : if (vmode == V4QImode)
20351 : : gen = gen_mmx_ppermv32;
20352 : : else if (vmode == V8QImode)
20353 : : gen = gen_mmx_ppermv64;
20354 : : else if (vmode == V16QImode)
20355 : : gen = gen_xop_pperm;
20356 : : else
20357 : 0 : gcc_unreachable ();
20358 : :
20359 : 3249 : emit_insn (gen (target, op0, op1, vperm));
20360 : : }
20361 : :
20362 : 6646 : if (target != d->target)
20363 : 4399 : emit_move_insn (d->target, gen_lowpart (d->vmode, target));
20364 : :
20365 : : return true;
20366 : : }
20367 : :
20368 : : /* Try to expand one-operand permutation with constant mask. */
20369 : :
20370 : : static bool
20371 : 129220 : ix86_expand_vec_one_operand_perm_avx512 (struct expand_vec_perm_d *d)
20372 : : {
20373 : 129220 : machine_mode mode = GET_MODE (d->op0);
20374 : 129220 : machine_mode maskmode = mode;
20375 : 258440 : unsigned inner_size = GET_MODE_SIZE (GET_MODE_INNER (mode));
20376 : 129220 : rtx (*gen) (rtx, rtx, rtx) = NULL;
20377 : 129220 : rtx target, op0, mask;
20378 : 129220 : rtx vec[64];
20379 : :
20380 : 129220 : if (!rtx_equal_p (d->op0, d->op1))
20381 : : return false;
20382 : :
20383 : 16248 : if (!TARGET_AVX512F)
20384 : : return false;
20385 : :
20386 : : /* Accept VNxHImode and VNxQImode now. */
20387 : 1127 : if (!TARGET_AVX512VL && GET_MODE_SIZE (mode) < 64)
20388 : : return false;
20389 : :
20390 : : /* vpermw. */
20391 : 285 : if (!TARGET_AVX512BW && inner_size == 2)
20392 : : return false;
20393 : :
20394 : : /* vpermb. */
20395 : 183 : if (!TARGET_AVX512VBMI && inner_size == 1)
20396 : : return false;
20397 : :
20398 : 118 : switch (mode)
20399 : : {
20400 : : case E_V16SImode:
20401 : : gen = gen_avx512f_permvarv16si;
20402 : : break;
20403 : 4 : case E_V16SFmode:
20404 : 4 : gen = gen_avx512f_permvarv16sf;
20405 : 4 : maskmode = V16SImode;
20406 : 4 : break;
20407 : 0 : case E_V8DImode:
20408 : 0 : gen = gen_avx512f_permvarv8di;
20409 : 0 : break;
20410 : 23 : case E_V8DFmode:
20411 : 23 : gen = gen_avx512f_permvarv8df;
20412 : 23 : maskmode = V8DImode;
20413 : 23 : break;
20414 : 38 : case E_V32HImode:
20415 : 38 : gen = gen_avx512bw_permvarv32hi;
20416 : 38 : break;
20417 : 12 : case E_V16HImode:
20418 : 12 : gen = gen_avx512vl_permvarv16hi;
20419 : 12 : break;
20420 : 6 : case E_V8HImode:
20421 : 6 : gen = gen_avx512vl_permvarv8hi;
20422 : 6 : break;
20423 : 2 : case E_V64QImode:
20424 : 2 : gen = gen_avx512bw_permvarv64qi;
20425 : 2 : break;
20426 : 2 : case E_V32QImode:
20427 : 2 : gen = gen_avx512vl_permvarv32qi;
20428 : 2 : break;
20429 : 0 : case E_V16QImode:
20430 : 0 : gen = gen_avx512vl_permvarv16qi;
20431 : 0 : break;
20432 : :
20433 : : default:
20434 : : return false;
20435 : : }
20436 : :
20437 : 117 : if (d->testing_p)
20438 : : return true;
20439 : :
20440 : 108 : target = d->target;
20441 : 108 : op0 = d->op0;
20442 : 2340 : for (int i = 0; i < d->nelt; ++i)
20443 : 2232 : vec[i] = GEN_INT (d->perm[i]);
20444 : 108 : mask = gen_rtx_CONST_VECTOR (maskmode, gen_rtvec_v (d->nelt, vec));
20445 : 108 : emit_insn (gen (target, op0, force_reg (maskmode, mask)));
20446 : 108 : return true;
20447 : : }
20448 : :
20449 : : static bool expand_vec_perm_palignr (struct expand_vec_perm_d *d, bool);
20450 : :
20451 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to instantiate D
20452 : : in a single instruction. */
20453 : :
20454 : : static bool
20455 : 257467 : expand_vec_perm_1 (struct expand_vec_perm_d *d)
20456 : : {
20457 : 257467 : unsigned i, nelt = d->nelt;
20458 : 257467 : struct expand_vec_perm_d nd;
20459 : :
20460 : : /* Check plain VEC_SELECT first, because AVX has instructions that could
20461 : : match both SEL and SEL+CONCAT, but the plain SEL will allow a memory
20462 : : input where SEL+CONCAT may not. */
20463 : 257467 : if (d->one_operand_p)
20464 : : {
20465 : 463893 : int mask = nelt - 1;
20466 : 463893 : bool identity_perm = true;
20467 : 463893 : bool broadcast_perm = true;
20468 : :
20469 : 463893 : for (i = 0; i < nelt; i++)
20470 : : {
20471 : 409314 : nd.perm[i] = d->perm[i] & mask;
20472 : 409314 : if (nd.perm[i] != i)
20473 : 281924 : identity_perm = false;
20474 : 409314 : if (nd.perm[i])
20475 : 346723 : broadcast_perm = false;
20476 : : }
20477 : :
20478 : 54579 : if (identity_perm)
20479 : : {
20480 : 44 : if (!d->testing_p)
20481 : 22 : emit_move_insn (d->target, d->op0);
20482 : 44 : return true;
20483 : : }
20484 : 54535 : else if (broadcast_perm && TARGET_AVX2)
20485 : : {
20486 : : /* Use vpbroadcast{b,w,d}. */
20487 : 274 : rtx (*gen) (rtx, rtx) = NULL;
20488 : 274 : switch (d->vmode)
20489 : : {
20490 : 1 : case E_V64QImode:
20491 : 1 : if (TARGET_AVX512BW)
20492 : : gen = gen_avx512bw_vec_dupv64qi_1;
20493 : : break;
20494 : 4 : case E_V32QImode:
20495 : 4 : gen = gen_avx2_pbroadcastv32qi_1;
20496 : 4 : break;
20497 : 1 : case E_V32HImode:
20498 : 1 : if (TARGET_AVX512BW)
20499 : : gen = gen_avx512bw_vec_dupv32hi_1;
20500 : : break;
20501 : 4 : case E_V16HImode:
20502 : 4 : gen = gen_avx2_pbroadcastv16hi_1;
20503 : 4 : break;
20504 : 0 : case E_V16SImode:
20505 : 0 : if (TARGET_AVX512F)
20506 : : gen = gen_avx512f_vec_dupv16si_1;
20507 : : break;
20508 : 4 : case E_V8SImode:
20509 : 4 : gen = gen_avx2_pbroadcastv8si_1;
20510 : 4 : break;
20511 : 4 : case E_V16QImode:
20512 : 4 : gen = gen_avx2_pbroadcastv16qi;
20513 : 4 : break;
20514 : 6 : case E_V8HImode:
20515 : 6 : gen = gen_avx2_pbroadcastv8hi;
20516 : 6 : break;
20517 : 0 : case E_V16SFmode:
20518 : 0 : if (TARGET_AVX512F)
20519 : : gen = gen_avx512f_vec_dupv16sf_1;
20520 : : break;
20521 : : case E_V8SFmode:
20522 : : gen = gen_avx2_vec_dupv8sf_1;
20523 : : break;
20524 : 0 : case E_V8DFmode:
20525 : 0 : if (TARGET_AVX512F)
20526 : : gen = gen_avx512f_vec_dupv8df_1;
20527 : : break;
20528 : 0 : case E_V8DImode:
20529 : 0 : if (TARGET_AVX512F)
20530 : : gen = gen_avx512f_vec_dupv8di_1;
20531 : : break;
20532 : : /* For other modes prefer other shuffles this function creates. */
20533 : : default: break;
20534 : : }
20535 : 22 : if (gen != NULL)
20536 : : {
20537 : 24 : if (!d->testing_p)
20538 : 24 : emit_insn (gen (d->target, d->op0));
20539 : 24 : return true;
20540 : : }
20541 : : }
20542 : :
20543 : 54511 : if (expand_vselect (d->target, d->op0, nd.perm, nelt, d->testing_p))
20544 : : return true;
20545 : :
20546 : : /* There are plenty of patterns in sse.md that are written for
20547 : : SEL+CONCAT and are not replicated for a single op. Perhaps
20548 : : that should be changed, to avoid the nastiness here. */
20549 : :
20550 : : /* Recognize interleave style patterns, which means incrementing
20551 : : every other permutation operand. */
20552 : 181763 : for (i = 0; i < nelt; i += 2)
20553 : : {
20554 : 149795 : nd.perm[i] = d->perm[i] & mask;
20555 : 149795 : nd.perm[i + 1] = (d->perm[i + 1] & mask) + nelt;
20556 : : }
20557 : 31968 : if (expand_vselect_vconcat (d->target, d->op0, d->op0, nd.perm, nelt,
20558 : 31968 : d->testing_p))
20559 : : return true;
20560 : :
20561 : : /* Recognize shufps, which means adding {0, 0, nelt, nelt}. */
20562 : 27033 : if (nelt >= 4)
20563 : : {
20564 : 95365 : for (i = 0; i < nelt; i += 4)
20565 : : {
20566 : 68332 : nd.perm[i + 0] = d->perm[i + 0] & mask;
20567 : 68332 : nd.perm[i + 1] = d->perm[i + 1] & mask;
20568 : 68332 : nd.perm[i + 2] = (d->perm[i + 2] & mask) + nelt;
20569 : 68332 : nd.perm[i + 3] = (d->perm[i + 3] & mask) + nelt;
20570 : : }
20571 : :
20572 : 27033 : if (expand_vselect_vconcat (d->target, d->op0, d->op0, nd.perm, nelt,
20573 : 27033 : d->testing_p))
20574 : : return true;
20575 : : }
20576 : : }
20577 : :
20578 : : /* Try the SSE4.1 blend variable merge instructions. */
20579 : 224434 : if (expand_vec_perm_blend (d))
20580 : : return true;
20581 : :
20582 : : /* Try movss/movsd instructions. */
20583 : 222842 : if (expand_vec_perm_movs (d))
20584 : : return true;
20585 : :
20586 : : /* Try the SSE4.1 insertps instruction. */
20587 : 192913 : if (expand_vec_perm_insertps (d))
20588 : : return true;
20589 : :
20590 : : /* Try the fully general two operand permute. */
20591 : 189420 : if (expand_vselect_vconcat (d->target, d->op0, d->op1, d->perm, nelt,
20592 : 189420 : d->testing_p))
20593 : : return true;
20594 : :
20595 : : /* Recognize interleave style patterns with reversed operands. */
20596 : 140128 : if (!d->one_operand_p)
20597 : : {
20598 : 877603 : for (i = 0; i < nelt; ++i)
20599 : : {
20600 : 758908 : unsigned e = d->perm[i];
20601 : 758908 : if (e >= nelt)
20602 : 358111 : e -= nelt;
20603 : : else
20604 : 400797 : e += nelt;
20605 : 758908 : nd.perm[i] = e;
20606 : : }
20607 : :
20608 : 118695 : if (expand_vselect_vconcat (d->target, d->op1, d->op0, nd.perm, nelt,
20609 : 118695 : d->testing_p))
20610 : : return true;
20611 : : }
20612 : :
20613 : : /* Try one of the AVX vpermil variable permutations. */
20614 : 140026 : if (expand_vec_perm_vpermil (d))
20615 : : return true;
20616 : :
20617 : : /* Try the SSSE3 pshufb or XOP vpperm or AVX2 vperm2i128,
20618 : : vpshufb, vpermd, vpermps or vpermq variable permutation. */
20619 : 139306 : if (expand_vec_perm_pshufb (d))
20620 : : return true;
20621 : :
20622 : : /* Try the AVX2 vpalignr instruction. */
20623 : 129323 : if (expand_vec_perm_palignr (d, true))
20624 : : return true;
20625 : :
20626 : : /* Try the AVX512F vperm{w,b,s,d} instructions */
20627 : 129220 : if (ix86_expand_vec_one_operand_perm_avx512 (d))
20628 : : return true;
20629 : :
20630 : : /* Try the AVX512F vpermt2/vpermi2 instructions. */
20631 : 129103 : if (ix86_expand_vec_perm_vpermt2 (NULL_RTX, NULL_RTX, NULL_RTX, NULL_RTX, d))
20632 : : return true;
20633 : :
20634 : : /* See if we can get the same permutation in different vector integer
20635 : : mode. */
20636 : 128036 : if (canonicalize_vector_int_perm (d, &nd) && expand_vec_perm_1 (&nd))
20637 : : {
20638 : 552 : if (!d->testing_p)
20639 : 60 : emit_move_insn (d->target, gen_lowpart (d->vmode, nd.target));
20640 : 552 : return true;
20641 : : }
20642 : : return false;
20643 : : }
20644 : :
20645 : : /* Canonicalize vec_perm index to make the first index
20646 : : always comes from the first vector. */
20647 : : static void
20648 : 7989 : ix86_vec_perm_index_canon (struct expand_vec_perm_d *d)
20649 : : {
20650 : 7989 : unsigned nelt = d->nelt;
20651 : 7989 : if (d->perm[0] < nelt)
20652 : : return;
20653 : :
20654 : 5 : for (unsigned i = 0; i != nelt; i++)
20655 : 4 : d->perm[i] = (d->perm[i] + nelt) % (2 * nelt);
20656 : :
20657 : 1 : std::swap (d->op0, d->op1);
20658 : 1 : return;
20659 : : }
20660 : :
20661 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement D
20662 : : in terms of a pair of shufps+ shufps/pshufd instructions. */
20663 : : static bool
20664 : 100167 : expand_vec_perm_shufps_shufps (struct expand_vec_perm_d *d)
20665 : : {
20666 : 100167 : unsigned char perm1[4];
20667 : 100167 : machine_mode vmode = d->vmode;
20668 : 100167 : bool ok;
20669 : 100167 : unsigned i, j, k, count = 0;
20670 : :
20671 : 100167 : if (d->one_operand_p
20672 : 95837 : || (vmode != V4SImode && vmode != V4SFmode))
20673 : : return false;
20674 : :
20675 : 58116 : if (d->testing_p)
20676 : : return true;
20677 : :
20678 : 7989 : ix86_vec_perm_index_canon (d);
20679 : 47934 : for (i = 0; i < 4; ++i)
20680 : 50171 : count += d->perm[i] > 3 ? 1 : 0;
20681 : :
20682 : 7989 : gcc_assert (count & 3);
20683 : :
20684 : 7989 : rtx tmp = gen_reg_rtx (vmode);
20685 : : /* 2 from op0 and 2 from op1. */
20686 : 7989 : if (count == 2)
20687 : : {
20688 : : unsigned char perm2[4];
20689 : 16700 : for (i = 0, j = 0, k = 2; i < 4; ++i)
20690 : 13360 : if (d->perm[i] & 4)
20691 : : {
20692 : 6680 : perm1[k++] = d->perm[i];
20693 : 6680 : perm2[i] = k - 1;
20694 : : }
20695 : : else
20696 : : {
20697 : 6680 : perm1[j++] = d->perm[i];
20698 : 6680 : perm2[i] = j - 1;
20699 : : }
20700 : :
20701 : : /* shufps. */
20702 : 6680 : ok = expand_vselect_vconcat (tmp, d->op0, d->op1,
20703 : 3340 : perm1, d->nelt, false);
20704 : 3340 : gcc_assert (ok);
20705 : 3340 : if (vmode == V4SImode && TARGET_SSE2)
20706 : : /* pshufd. */
20707 : 1897 : ok = expand_vselect (d->target, tmp,
20708 : 1897 : perm2, d->nelt, false);
20709 : : else
20710 : : {
20711 : : /* shufps. */
20712 : 1443 : perm2[2] += 4;
20713 : 1443 : perm2[3] += 4;
20714 : 1443 : ok = expand_vselect_vconcat (d->target, tmp, tmp,
20715 : 1443 : perm2, d->nelt, false);
20716 : : }
20717 : 3340 : gcc_assert (ok);
20718 : : }
20719 : : /* 3 from one op and 1 from another. */
20720 : : else
20721 : : {
20722 : 23245 : unsigned pair_idx = 8, lone_idx = 8, shift;
20723 : :
20724 : : /* Find the lone index. */
20725 : 23245 : for (i = 0; i < 4; ++i)
20726 : 18596 : if ((d->perm[i] > 3 && count == 1)
20727 : 15153 : || (d->perm[i] < 4 && count == 3))
20728 : 18596 : lone_idx = i;
20729 : :
20730 : : /* When lone_idx is not 0, it must from second op(count == 1). */
20731 : 5855 : gcc_assert (count == (lone_idx ? 1 : 3));
20732 : :
20733 : : /* Find the pair index that sits in the same half as the lone index. */
20734 : 4649 : shift = lone_idx & 2;
20735 : 4649 : pair_idx = 1 - lone_idx + 2 * shift;
20736 : :
20737 : : /* First permutate lone index and pair index into the same vector as
20738 : : [ lone, lone, pair, pair ]. */
20739 : 9298 : perm1[1] = perm1[0]
20740 : 4649 : = (count == 3) ? d->perm[lone_idx] : d->perm[lone_idx] - 4;
20741 : 9298 : perm1[3] = perm1[2]
20742 : 4649 : = (count == 3) ? d->perm[pair_idx] : d->perm[pair_idx] + 4;
20743 : :
20744 : : /* Alway put the vector contains lone indx at the first. */
20745 : 4649 : if (count == 1)
20746 : 3443 : std::swap (d->op0, d->op1);
20747 : :
20748 : : /* shufps. */
20749 : 9298 : ok = expand_vselect_vconcat (tmp, d->op0, d->op1,
20750 : 4649 : perm1, d->nelt, false);
20751 : 4649 : gcc_assert (ok);
20752 : :
20753 : : /* Refine lone and pair index to original order. */
20754 : 4649 : perm1[shift] = lone_idx << 1;
20755 : 4649 : perm1[shift + 1] = pair_idx << 1;
20756 : :
20757 : : /* Select the remaining 2 elements in another vector. */
20758 : 13947 : for (i = 2 - shift; i < 4 - shift; ++i)
20759 : 9298 : perm1[i] = lone_idx == 1 ? d->perm[i] + 4 : d->perm[i];
20760 : :
20761 : : /* Adjust to original selector. */
20762 : 4649 : if (lone_idx > 1)
20763 : 2349 : std::swap (tmp, d->op1);
20764 : :
20765 : : /* shufps. */
20766 : 9298 : ok = expand_vselect_vconcat (d->target, tmp, d->op1,
20767 : 4649 : perm1, d->nelt, false);
20768 : :
20769 : 4649 : gcc_assert (ok);
20770 : : }
20771 : :
20772 : : return true;
20773 : : }
20774 : :
20775 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement D
20776 : : in terms of a pair of pshuflw + pshufhw instructions. */
20777 : :
20778 : : static bool
20779 : 114337 : expand_vec_perm_pshuflw_pshufhw (struct expand_vec_perm_d *d)
20780 : : {
20781 : 114337 : unsigned char perm2[MAX_VECT_LEN];
20782 : 114337 : unsigned i;
20783 : 114337 : bool ok;
20784 : :
20785 : 114337 : if (d->vmode != V8HImode || !d->one_operand_p)
20786 : : return false;
20787 : :
20788 : : /* The two permutations only operate in 64-bit lanes. */
20789 : 17809 : for (i = 0; i < 4; ++i)
20790 : 14367 : if (d->perm[i] >= 4)
20791 : : return false;
20792 : 16114 : for (i = 4; i < 8; ++i)
20793 : 12946 : if (d->perm[i] < 4)
20794 : : return false;
20795 : :
20796 : 3168 : if (d->testing_p)
20797 : : return true;
20798 : :
20799 : : /* Emit the pshuflw. */
20800 : 32 : memcpy (perm2, d->perm, 4);
20801 : 160 : for (i = 4; i < 8; ++i)
20802 : 128 : perm2[i] = i;
20803 : 32 : ok = expand_vselect (d->target, d->op0, perm2, 8, d->testing_p);
20804 : 32 : gcc_assert (ok);
20805 : :
20806 : : /* Emit the pshufhw. */
20807 : 32 : memcpy (perm2 + 4, d->perm + 4, 4);
20808 : 160 : for (i = 0; i < 4; ++i)
20809 : 128 : perm2[i] = i;
20810 : 32 : ok = expand_vselect (d->target, d->target, perm2, 8, d->testing_p);
20811 : 32 : gcc_assert (ok);
20812 : :
20813 : : return true;
20814 : : }
20815 : :
20816 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to simplify
20817 : : the permutation using the SSSE3 palignr instruction. This succeeds
20818 : : when all of the elements in PERM fit within one vector and we merely
20819 : : need to shift them down so that a single vector permutation has a
20820 : : chance to succeed. If SINGLE_INSN_ONLY_P, succeed if only
20821 : : the vpalignr instruction itself can perform the requested permutation. */
20822 : :
20823 : : static bool
20824 : 240492 : expand_vec_perm_palignr (struct expand_vec_perm_d *d, bool single_insn_only_p)
20825 : : {
20826 : 240492 : unsigned i, nelt = d->nelt;
20827 : 240492 : unsigned min, max, minswap, maxswap;
20828 : 240492 : bool in_order, ok, swap = false;
20829 : 240492 : rtx shift, target;
20830 : 240492 : struct expand_vec_perm_d dcopy;
20831 : :
20832 : : /* Even with AVX, palignr only operates on 128-bit vectors,
20833 : : in AVX2 palignr operates on both 128-bit lanes. */
20834 : 118610 : if ((!TARGET_SSSE3 || GET_MODE_SIZE (d->vmode) != 16)
20835 : 279228 : && (!TARGET_AVX2 || GET_MODE_SIZE (d->vmode) != 32))
20836 : 202962 : return false;
20837 : :
20838 : 37530 : min = 2 * nelt;
20839 : 37530 : max = 0;
20840 : 37530 : minswap = 2 * nelt;
20841 : 37530 : maxswap = 0;
20842 : 344754 : for (i = 0; i < nelt; ++i)
20843 : : {
20844 : 307224 : unsigned e = d->perm[i];
20845 : 307224 : unsigned eswap = d->perm[i] ^ nelt;
20846 : 614448 : if (GET_MODE_SIZE (d->vmode) == 32)
20847 : : {
20848 : 136812 : e = (e & ((nelt / 2) - 1)) | ((e & nelt) >> 1);
20849 : 136812 : eswap = e ^ (nelt / 2);
20850 : : }
20851 : 307224 : if (e < min)
20852 : : min = e;
20853 : 307224 : if (e > max)
20854 : : max = e;
20855 : 307224 : if (eswap < minswap)
20856 : : minswap = eswap;
20857 : 307224 : if (eswap > maxswap)
20858 : : maxswap = eswap;
20859 : : }
20860 : 37530 : if (min == 0
20861 : 55899 : || max - min >= (GET_MODE_SIZE (d->vmode) == 32 ? nelt / 2 : nelt))
20862 : : {
20863 : 33963 : if (d->one_operand_p
20864 : 33813 : || minswap == 0
20865 : 71771 : || maxswap - minswap >= (GET_MODE_SIZE (d->vmode) == 32
20866 : 18904 : ? nelt / 2 : nelt))
20867 : 30775 : return false;
20868 : : swap = true;
20869 : : min = minswap;
20870 : 6755 : max = maxswap;
20871 : : }
20872 : :
20873 : : /* Given that we have SSSE3, we know we'll be able to implement the
20874 : : single operand permutation after the palignr with pshufb for
20875 : : 128-bit vectors. If SINGLE_INSN_ONLY_P, in_order has to be computed
20876 : : first. */
20877 : 6797 : if (d->testing_p && GET_MODE_SIZE (d->vmode) == 16 && !single_insn_only_p)
20878 : : return true;
20879 : :
20880 : 6755 : dcopy = *d;
20881 : 6755 : if (swap)
20882 : : {
20883 : 3188 : dcopy.op0 = d->op1;
20884 : 3188 : dcopy.op1 = d->op0;
20885 : 15940 : for (i = 0; i < nelt; ++i)
20886 : 12752 : dcopy.perm[i] ^= nelt;
20887 : : }
20888 : :
20889 : : in_order = true;
20890 : 42683 : for (i = 0; i < nelt; ++i)
20891 : : {
20892 : 35928 : unsigned e = dcopy.perm[i];
20893 : 35928 : if (GET_MODE_SIZE (d->vmode) == 32
20894 : 10352 : && e >= nelt
20895 : 36108 : && (e & (nelt / 2 - 1)) < min)
20896 : 180 : e = e - min - (nelt / 2);
20897 : : else
20898 : 35748 : e = e - min;
20899 : 35928 : if (e != i)
20900 : 28912 : in_order = false;
20901 : 35928 : dcopy.perm[i] = e;
20902 : : }
20903 : 6755 : dcopy.one_operand_p = true;
20904 : :
20905 : 6755 : if (single_insn_only_p && !in_order)
20906 : : return false;
20907 : :
20908 : : /* For AVX2, test whether we can permute the result in one instruction. */
20909 : 3253 : if (d->testing_p)
20910 : : {
20911 : 42 : if (in_order)
20912 : : return true;
20913 : 0 : dcopy.op1 = dcopy.op0;
20914 : 0 : return expand_vec_perm_1 (&dcopy);
20915 : : }
20916 : :
20917 : 6422 : shift = GEN_INT (min * GET_MODE_UNIT_BITSIZE (d->vmode));
20918 : 6422 : if (GET_MODE_SIZE (d->vmode) == 16)
20919 : : {
20920 : 3157 : target = gen_reg_rtx (V1TImode);
20921 : 3157 : emit_insn (gen_ssse3_palignrv1ti (target,
20922 : 3157 : gen_lowpart (V1TImode, dcopy.op1),
20923 : 3157 : gen_lowpart (V1TImode, dcopy.op0),
20924 : : shift));
20925 : : }
20926 : : else
20927 : : {
20928 : 54 : target = gen_reg_rtx (V2TImode);
20929 : 54 : emit_insn (gen_avx2_palignrv2ti (target,
20930 : 54 : gen_lowpart (V2TImode, dcopy.op1),
20931 : 54 : gen_lowpart (V2TImode, dcopy.op0),
20932 : : shift));
20933 : : }
20934 : :
20935 : 3211 : dcopy.op0 = dcopy.op1 = gen_lowpart (d->vmode, target);
20936 : :
20937 : : /* Test for the degenerate case where the alignment by itself
20938 : : produces the desired permutation. */
20939 : 3211 : if (in_order)
20940 : : {
20941 : 61 : emit_move_insn (d->target, dcopy.op0);
20942 : 61 : return true;
20943 : : }
20944 : :
20945 : 3150 : ok = expand_vec_perm_1 (&dcopy);
20946 : 3162 : gcc_assert (ok || GET_MODE_SIZE (d->vmode) == 32);
20947 : :
20948 : : return ok;
20949 : : }
20950 : :
20951 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to simplify
20952 : : the permutation using the SSE4_1 pblendv instruction. Potentially
20953 : : reduces permutation from 2 pshufb and or to 1 pshufb and pblendv. */
20954 : :
20955 : : static bool
20956 : 102690 : expand_vec_perm_pblendv (struct expand_vec_perm_d *d)
20957 : : {
20958 : 102690 : unsigned i, which, nelt = d->nelt;
20959 : 102690 : struct expand_vec_perm_d dcopy, dcopy1;
20960 : 102690 : machine_mode vmode = d->vmode;
20961 : 102690 : bool ok;
20962 : :
20963 : : /* Use the same checks as in expand_vec_perm_blend. */
20964 : 102690 : if (d->one_operand_p)
20965 : : return false;
20966 : 101284 : if (TARGET_AVX2 && GET_MODE_SIZE (vmode) == 32)
20967 : : ;
20968 : 96345 : else if (TARGET_AVX && (vmode == V4DFmode || vmode == V8SFmode))
20969 : : ;
20970 : 92286 : else if (TARGET_SSE4_1
20971 : 101487 : && (GET_MODE_SIZE (vmode) == 16
20972 : 5302 : || (TARGET_MMX_WITH_SSE && GET_MODE_SIZE (vmode) == 8)
20973 : 971 : || GET_MODE_SIZE (vmode) == 4))
20974 : : ;
20975 : : else
20976 : 83716 : return false;
20977 : :
20978 : : /* Figure out where permutation elements stay not in their
20979 : : respective lanes. */
20980 : 142726 : for (i = 0, which = 0; i < nelt; ++i)
20981 : : {
20982 : 128082 : unsigned e = d->perm[i];
20983 : 128082 : if (e != i)
20984 : 194114 : which |= (e < nelt ? 1 : 2);
20985 : : }
20986 : : /* We can pblend the part where elements stay not in their
20987 : : respective lanes only when these elements are all in one
20988 : : half of a permutation.
20989 : : {0 1 8 3 4 5 9 7} is ok as 8, 9 are at not at their respective
20990 : : lanes, but both 8 and 9 >= 8
20991 : : {0 1 8 3 4 5 2 7} is not ok as 2 and 8 are not at their
20992 : : respective lanes and 8 >= 8, but 2 not. */
20993 : 14644 : if (which != 1 && which != 2)
20994 : : return false;
20995 : 1947 : if (d->testing_p && GET_MODE_SIZE (vmode) == 16)
20996 : : return true;
20997 : :
20998 : : /* First we apply one operand permutation to the part where
20999 : : elements stay not in their respective lanes. */
21000 : 1308 : dcopy = *d;
21001 : 1308 : if (which == 2)
21002 : 1308 : dcopy.op0 = dcopy.op1 = d->op1;
21003 : : else
21004 : 0 : dcopy.op0 = dcopy.op1 = d->op0;
21005 : 1308 : if (!d->testing_p)
21006 : 669 : dcopy.target = gen_reg_rtx (vmode);
21007 : 1308 : dcopy.one_operand_p = true;
21008 : :
21009 : 11824 : for (i = 0; i < nelt; ++i)
21010 : 10516 : dcopy.perm[i] = d->perm[i] & (nelt - 1);
21011 : :
21012 : 1308 : ok = expand_vec_perm_1 (&dcopy);
21013 : 2616 : if (GET_MODE_SIZE (vmode) != 16 && !ok)
21014 : : return false;
21015 : : else
21016 : 1013 : gcc_assert (ok);
21017 : 1013 : if (d->testing_p)
21018 : : return true;
21019 : :
21020 : : /* Next we put permuted elements into their positions. */
21021 : 607 : dcopy1 = *d;
21022 : 607 : if (which == 2)
21023 : 607 : dcopy1.op1 = dcopy.target;
21024 : : else
21025 : 0 : dcopy1.op0 = dcopy.target;
21026 : :
21027 : 5407 : for (i = 0; i < nelt; ++i)
21028 : 4800 : dcopy1.perm[i] = ((d->perm[i] >= nelt) ? (nelt + i) : i);
21029 : :
21030 : 607 : ok = expand_vec_perm_blend (&dcopy1);
21031 : 607 : gcc_assert (ok);
21032 : :
21033 : : return true;
21034 : : }
21035 : :
21036 : : static bool expand_vec_perm_interleave3 (struct expand_vec_perm_d *d);
21037 : :
21038 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to simplify
21039 : : a two vector permutation into a single vector permutation by using
21040 : : an interleave operation to merge the vectors. */
21041 : :
21042 : : static bool
21043 : 108031 : expand_vec_perm_interleave2 (struct expand_vec_perm_d *d)
21044 : : {
21045 : 108031 : struct expand_vec_perm_d dremap, dfinal;
21046 : 108031 : unsigned i, nelt = d->nelt, nelt2 = nelt / 2;
21047 : 108031 : unsigned HOST_WIDE_INT contents;
21048 : 108031 : unsigned char remap[2 * MAX_VECT_LEN];
21049 : 108031 : rtx_insn *seq;
21050 : 108031 : bool ok, same_halves = false;
21051 : :
21052 : 108031 : if (GET_MODE_SIZE (d->vmode) == 4
21053 : 202664 : || GET_MODE_SIZE (d->vmode) == 8
21054 : 285913 : || GET_MODE_SIZE (d->vmode) == 16)
21055 : : {
21056 : 100454 : if (d->one_operand_p)
21057 : : return false;
21058 : : }
21059 : 15154 : else if (GET_MODE_SIZE (d->vmode) == 32)
21060 : : {
21061 : 7280 : if (!TARGET_AVX)
21062 : : return false;
21063 : : /* For 32-byte modes allow even d->one_operand_p.
21064 : : The lack of cross-lane shuffling in some instructions
21065 : : might prevent a single insn shuffle. */
21066 : 7280 : dfinal = *d;
21067 : 7280 : dfinal.testing_p = true;
21068 : : /* If expand_vec_perm_interleave3 can expand this into
21069 : : a 3 insn sequence, give up and let it be expanded as
21070 : : 3 insn sequence. While that is one insn longer,
21071 : : it doesn't need a memory operand and in the common
21072 : : case that both interleave low and high permutations
21073 : : with the same operands are adjacent needs 4 insns
21074 : : for both after CSE. */
21075 : 7280 : if (expand_vec_perm_interleave3 (&dfinal))
21076 : : return false;
21077 : : }
21078 : : else
21079 : : return false;
21080 : :
21081 : : /* Examine from whence the elements come. */
21082 : 103404 : contents = 0;
21083 : 729636 : for (i = 0; i < nelt; ++i)
21084 : 626232 : contents |= HOST_WIDE_INT_1U << d->perm[i];
21085 : :
21086 : 103404 : memset (remap, 0xff, sizeof (remap));
21087 : 103404 : dremap = *d;
21088 : :
21089 : 103404 : if (GET_MODE_SIZE (d->vmode) == 4
21090 : 201418 : || GET_MODE_SIZE (d->vmode) == 8)
21091 : : {
21092 : 17011 : unsigned HOST_WIDE_INT h1, h2, h3, h4;
21093 : :
21094 : : /* Split the two input vectors into 4 halves. */
21095 : 17011 : h1 = (HOST_WIDE_INT_1U << nelt2) - 1;
21096 : 17011 : h2 = h1 << nelt2;
21097 : 17011 : h3 = h2 << nelt2;
21098 : 17011 : h4 = h3 << nelt2;
21099 : :
21100 : : /* If the elements from the low halves use interleave low,
21101 : : and similarly for interleave high. */
21102 : 17011 : if ((contents & (h1 | h3)) == contents)
21103 : : {
21104 : : /* punpckl* */
21105 : 2613 : for (i = 0; i < nelt2; ++i)
21106 : : {
21107 : 1796 : remap[i] = i * 2;
21108 : 1796 : remap[i + nelt] = i * 2 + 1;
21109 : 1796 : dremap.perm[i * 2] = i;
21110 : 1796 : dremap.perm[i * 2 + 1] = i + nelt;
21111 : : }
21112 : : }
21113 : 16194 : else if ((contents & (h2 | h4)) == contents)
21114 : : {
21115 : : /* punpckh* */
21116 : 2938 : for (i = 0; i < nelt2; ++i)
21117 : : {
21118 : 1988 : remap[i + nelt2] = i * 2;
21119 : 1988 : remap[i + nelt + nelt2] = i * 2 + 1;
21120 : 1988 : dremap.perm[i * 2] = i + nelt2;
21121 : 1988 : dremap.perm[i * 2 + 1] = i + nelt + nelt2;
21122 : : }
21123 : : }
21124 : : else
21125 : : return false;
21126 : : }
21127 : 172786 : else if (GET_MODE_SIZE (d->vmode) == 16)
21128 : : {
21129 : 79167 : unsigned HOST_WIDE_INT h1, h2, h3, h4;
21130 : :
21131 : : /* Split the two input vectors into 4 halves. */
21132 : 79167 : h1 = (HOST_WIDE_INT_1U << nelt2) - 1;
21133 : 79167 : h2 = h1 << nelt2;
21134 : 79167 : h3 = h2 << nelt2;
21135 : 79167 : h4 = h3 << nelt2;
21136 : :
21137 : : /* If the elements from the low halves use interleave low, and similarly
21138 : : for interleave high. If the elements are from mis-matched halves, we
21139 : : can use shufps for V4SF/V4SI or do a DImode shuffle. */
21140 : 79167 : if ((contents & (h1 | h3)) == contents)
21141 : : {
21142 : : /* punpckl* */
21143 : 5019 : for (i = 0; i < nelt2; ++i)
21144 : : {
21145 : 3586 : remap[i] = i * 2;
21146 : 3586 : remap[i + nelt] = i * 2 + 1;
21147 : 3586 : dremap.perm[i * 2] = i;
21148 : 3586 : dremap.perm[i * 2 + 1] = i + nelt;
21149 : : }
21150 : 1433 : if (!TARGET_SSE2 && d->vmode == V4SImode)
21151 : 0 : dremap.vmode = V4SFmode;
21152 : : }
21153 : 77734 : else if ((contents & (h2 | h4)) == contents)
21154 : : {
21155 : : /* punpckh* */
21156 : 4712 : for (i = 0; i < nelt2; ++i)
21157 : : {
21158 : 3320 : remap[i + nelt2] = i * 2;
21159 : 3320 : remap[i + nelt + nelt2] = i * 2 + 1;
21160 : 3320 : dremap.perm[i * 2] = i + nelt2;
21161 : 3320 : dremap.perm[i * 2 + 1] = i + nelt + nelt2;
21162 : : }
21163 : 1392 : if (!TARGET_SSE2 && d->vmode == V4SImode)
21164 : 0 : dremap.vmode = V4SFmode;
21165 : : }
21166 : 76342 : else if ((contents & (h1 | h4)) == contents)
21167 : : {
21168 : : /* shufps */
21169 : 1157 : for (i = 0; i < nelt2; ++i)
21170 : : {
21171 : 856 : remap[i] = i;
21172 : 856 : remap[i + nelt + nelt2] = i + nelt2;
21173 : 856 : dremap.perm[i] = i;
21174 : 856 : dremap.perm[i + nelt2] = i + nelt + nelt2;
21175 : : }
21176 : 301 : if (nelt != 4)
21177 : : {
21178 : : /* shufpd */
21179 : 53 : dremap.vmode = V2DImode;
21180 : 53 : dremap.nelt = 2;
21181 : 53 : dremap.perm[0] = 0;
21182 : 53 : dremap.perm[1] = 3;
21183 : : }
21184 : : }
21185 : 76041 : else if ((contents & (h2 | h3)) == contents)
21186 : : {
21187 : : /* shufps */
21188 : 1746 : for (i = 0; i < nelt2; ++i)
21189 : : {
21190 : 1240 : remap[i + nelt2] = i;
21191 : 1240 : remap[i + nelt] = i + nelt2;
21192 : 1240 : dremap.perm[i] = i + nelt2;
21193 : 1240 : dremap.perm[i + nelt2] = i + nelt;
21194 : : }
21195 : 506 : if (nelt != 4)
21196 : : {
21197 : : /* shufpd */
21198 : 48 : dremap.vmode = V2DImode;
21199 : 48 : dremap.nelt = 2;
21200 : 48 : dremap.perm[0] = 1;
21201 : 48 : dremap.perm[1] = 2;
21202 : : }
21203 : : }
21204 : : else
21205 : : return false;
21206 : : }
21207 : : else
21208 : : {
21209 : 7226 : unsigned int nelt4 = nelt / 4, nzcnt = 0;
21210 : 7226 : unsigned HOST_WIDE_INT q[8];
21211 : 7226 : unsigned int nonzero_halves[4];
21212 : :
21213 : : /* Split the two input vectors into 8 quarters. */
21214 : 7226 : q[0] = (HOST_WIDE_INT_1U << nelt4) - 1;
21215 : 57808 : for (i = 1; i < 8; ++i)
21216 : 50582 : q[i] = q[0] << (nelt4 * i);
21217 : 36130 : for (i = 0; i < 4; ++i)
21218 : 28904 : if (((q[2 * i] | q[2 * i + 1]) & contents) != 0)
21219 : : {
21220 : 25810 : nonzero_halves[nzcnt] = i;
21221 : 25810 : ++nzcnt;
21222 : : }
21223 : :
21224 : 7226 : if (nzcnt == 1)
21225 : : {
21226 : 301 : gcc_assert (d->one_operand_p);
21227 : 301 : nonzero_halves[1] = nonzero_halves[0];
21228 : 301 : same_halves = true;
21229 : : }
21230 : 6925 : else if (d->one_operand_p)
21231 : : {
21232 : 4 : gcc_assert (nonzero_halves[0] == 0);
21233 : 4 : gcc_assert (nonzero_halves[1] == 1);
21234 : : }
21235 : :
21236 : 7226 : if (nzcnt <= 2)
21237 : : {
21238 : 427 : if (d->perm[0] / nelt2 == nonzero_halves[1])
21239 : : {
21240 : : /* Attempt to increase the likelihood that dfinal
21241 : : shuffle will be intra-lane. */
21242 : 305 : std::swap (nonzero_halves[0], nonzero_halves[1]);
21243 : : }
21244 : :
21245 : : /* vperm2f128 or vperm2i128. */
21246 : 1811 : for (i = 0; i < nelt2; ++i)
21247 : : {
21248 : 1384 : remap[i + nonzero_halves[1] * nelt2] = i + nelt2;
21249 : 1384 : remap[i + nonzero_halves[0] * nelt2] = i;
21250 : 1384 : dremap.perm[i + nelt2] = i + nonzero_halves[1] * nelt2;
21251 : 1384 : dremap.perm[i] = i + nonzero_halves[0] * nelt2;
21252 : : }
21253 : :
21254 : 427 : if (d->vmode != V8SFmode
21255 : : && d->vmode != V4DFmode
21256 : : && d->vmode != V8SImode)
21257 : : {
21258 : 64 : dremap.vmode = V8SImode;
21259 : 64 : dremap.nelt = 8;
21260 : 320 : for (i = 0; i < 4; ++i)
21261 : : {
21262 : 256 : dremap.perm[i] = i + nonzero_halves[0] * 4;
21263 : 256 : dremap.perm[i + 4] = i + nonzero_halves[1] * 4;
21264 : : }
21265 : : }
21266 : : }
21267 : 6799 : else if (d->one_operand_p)
21268 : 6488 : return false;
21269 : 6799 : else if (TARGET_AVX2
21270 : 2360 : && (contents & (q[0] | q[2] | q[4] | q[6])) == contents)
21271 : : {
21272 : : /* vpunpckl* */
21273 : 330 : for (i = 0; i < nelt4; ++i)
21274 : : {
21275 : 165 : remap[i] = i * 2;
21276 : 165 : remap[i + nelt] = i * 2 + 1;
21277 : 165 : remap[i + nelt2] = i * 2 + nelt2;
21278 : 165 : remap[i + nelt + nelt2] = i * 2 + nelt2 + 1;
21279 : 165 : dremap.perm[i * 2] = i;
21280 : 165 : dremap.perm[i * 2 + 1] = i + nelt;
21281 : 165 : dremap.perm[i * 2 + nelt2] = i + nelt2;
21282 : 165 : dremap.perm[i * 2 + nelt2 + 1] = i + nelt + nelt2;
21283 : : }
21284 : : }
21285 : 6634 : else if (TARGET_AVX2
21286 : 2195 : && (contents & (q[1] | q[3] | q[5] | q[7])) == contents)
21287 : : {
21288 : : /* vpunpckh* */
21289 : 292 : for (i = 0; i < nelt4; ++i)
21290 : : {
21291 : 146 : remap[i + nelt4] = i * 2;
21292 : 146 : remap[i + nelt + nelt4] = i * 2 + 1;
21293 : 146 : remap[i + nelt2 + nelt4] = i * 2 + nelt2;
21294 : 146 : remap[i + nelt + nelt2 + nelt4] = i * 2 + nelt2 + 1;
21295 : 146 : dremap.perm[i * 2] = i + nelt4;
21296 : 146 : dremap.perm[i * 2 + 1] = i + nelt + nelt4;
21297 : 146 : dremap.perm[i * 2 + nelt2] = i + nelt2 + nelt4;
21298 : 146 : dremap.perm[i * 2 + nelt2 + 1] = i + nelt + nelt2 + nelt4;
21299 : : }
21300 : : }
21301 : : else
21302 : : return false;
21303 : : }
21304 : :
21305 : : /* Use the remapping array set up above to move the elements from their
21306 : : swizzled locations into their final destinations. */
21307 : 6137 : dfinal = *d;
21308 : 35721 : for (i = 0; i < nelt; ++i)
21309 : : {
21310 : 29584 : unsigned e = remap[d->perm[i]];
21311 : 29584 : gcc_assert (e < nelt);
21312 : : /* If same_halves is true, both halves of the remapped vector are the
21313 : : same. Avoid cross-lane accesses if possible. */
21314 : 29584 : if (same_halves && i >= nelt2)
21315 : : {
21316 : 996 : gcc_assert (e < nelt2);
21317 : 996 : dfinal.perm[i] = e + nelt2;
21318 : : }
21319 : : else
21320 : 28588 : dfinal.perm[i] = e;
21321 : : }
21322 : 6137 : if (!d->testing_p)
21323 : : {
21324 : 2730 : dremap.target = gen_reg_rtx (dremap.vmode);
21325 : 2730 : dfinal.op0 = gen_lowpart (dfinal.vmode, dremap.target);
21326 : : }
21327 : 6137 : dfinal.op1 = dfinal.op0;
21328 : 6137 : dfinal.one_operand_p = true;
21329 : :
21330 : : /* Test if the final remap can be done with a single insn. For V4SFmode or
21331 : : V4SImode this *will* succeed. For V8HImode or V16QImode it may not. */
21332 : 6137 : start_sequence ();
21333 : 6137 : ok = expand_vec_perm_1 (&dfinal);
21334 : 6137 : seq = get_insns ();
21335 : 6137 : end_sequence ();
21336 : :
21337 : 6137 : if (!ok)
21338 : : return false;
21339 : :
21340 : 5187 : if (d->testing_p)
21341 : : return true;
21342 : :
21343 : 2714 : if (dremap.vmode != dfinal.vmode)
21344 : : {
21345 : 38 : dremap.op0 = gen_lowpart (dremap.vmode, dremap.op0);
21346 : 38 : dremap.op1 = gen_lowpart (dremap.vmode, dremap.op1);
21347 : : }
21348 : :
21349 : 2714 : ok = expand_vec_perm_1 (&dremap);
21350 : 2714 : gcc_assert (ok);
21351 : :
21352 : 2714 : emit_insn (seq);
21353 : 2714 : return true;
21354 : : }
21355 : :
21356 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to simplify
21357 : : a single vector cross-lane permutation into vpermq followed
21358 : : by any of the single insn permutations. */
21359 : :
21360 : : static bool
21361 : 102744 : expand_vec_perm_vpermq_perm_1 (struct expand_vec_perm_d *d)
21362 : : {
21363 : 102744 : struct expand_vec_perm_d dremap, dfinal;
21364 : 102744 : unsigned i, j, nelt = d->nelt, nelt2 = nelt / 2, nelt4 = nelt / 4;
21365 : 102744 : unsigned contents[2];
21366 : 102744 : bool ok;
21367 : :
21368 : 102744 : if (!(TARGET_AVX2
21369 : 3105 : && (d->vmode == V32QImode || d->vmode == V16HImode)
21370 : 1346 : && d->one_operand_p))
21371 : : return false;
21372 : :
21373 : 0 : contents[0] = 0;
21374 : 0 : contents[1] = 0;
21375 : 0 : for (i = 0; i < nelt2; ++i)
21376 : : {
21377 : 0 : contents[0] |= 1u << (d->perm[i] / nelt4);
21378 : 0 : contents[1] |= 1u << (d->perm[i + nelt2] / nelt4);
21379 : : }
21380 : :
21381 : 0 : for (i = 0; i < 2; ++i)
21382 : : {
21383 : : unsigned int cnt = 0;
21384 : 0 : for (j = 0; j < 4; ++j)
21385 : 0 : if ((contents[i] & (1u << j)) != 0 && ++cnt > 2)
21386 : : return false;
21387 : : }
21388 : :
21389 : 0 : if (d->testing_p)
21390 : : return true;
21391 : :
21392 : 0 : dremap = *d;
21393 : 0 : dremap.vmode = V4DImode;
21394 : 0 : dremap.nelt = 4;
21395 : 0 : dremap.target = gen_reg_rtx (V4DImode);
21396 : 0 : dremap.op0 = gen_lowpart (V4DImode, d->op0);
21397 : 0 : dremap.op1 = dremap.op0;
21398 : 0 : dremap.one_operand_p = true;
21399 : 0 : for (i = 0; i < 2; ++i)
21400 : : {
21401 : : unsigned int cnt = 0;
21402 : 0 : for (j = 0; j < 4; ++j)
21403 : 0 : if ((contents[i] & (1u << j)) != 0)
21404 : 0 : dremap.perm[2 * i + cnt++] = j;
21405 : 0 : for (; cnt < 2; ++cnt)
21406 : 0 : dremap.perm[2 * i + cnt] = 0;
21407 : : }
21408 : :
21409 : 0 : dfinal = *d;
21410 : 0 : dfinal.op0 = gen_lowpart (dfinal.vmode, dremap.target);
21411 : 0 : dfinal.op1 = dfinal.op0;
21412 : 0 : dfinal.one_operand_p = true;
21413 : 0 : for (i = 0, j = 0; i < nelt; ++i)
21414 : : {
21415 : 0 : if (i == nelt2)
21416 : 0 : j = 2;
21417 : 0 : dfinal.perm[i] = (d->perm[i] & (nelt4 - 1)) | (j ? nelt2 : 0);
21418 : 0 : if ((d->perm[i] / nelt4) == dremap.perm[j])
21419 : : ;
21420 : 0 : else if ((d->perm[i] / nelt4) == dremap.perm[j + 1])
21421 : 0 : dfinal.perm[i] |= nelt4;
21422 : : else
21423 : 0 : gcc_unreachable ();
21424 : : }
21425 : :
21426 : 0 : ok = expand_vec_perm_1 (&dremap);
21427 : 0 : gcc_assert (ok);
21428 : :
21429 : 0 : ok = expand_vec_perm_1 (&dfinal);
21430 : 0 : gcc_assert (ok);
21431 : :
21432 : : return true;
21433 : : }
21434 : :
21435 : : static bool canonicalize_perm (struct expand_vec_perm_d *d);
21436 : :
21437 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to expand
21438 : : a vector permutation using two instructions, vperm2f128 resp.
21439 : : vperm2i128 followed by any single in-lane permutation. */
21440 : :
21441 : : static bool
21442 : 102744 : expand_vec_perm_vperm2f128 (struct expand_vec_perm_d *d)
21443 : : {
21444 : 102744 : struct expand_vec_perm_d dfirst, dsecond;
21445 : 102744 : unsigned i, j, nelt = d->nelt, nelt2 = nelt / 2, perm;
21446 : 102744 : bool ok;
21447 : :
21448 : 102744 : if (!TARGET_AVX
21449 : 22512 : || GET_MODE_SIZE (d->vmode) != 32
21450 : 109360 : || (d->vmode != V8SFmode && d->vmode != V4DFmode && !TARGET_AVX2))
21451 : : return false;
21452 : :
21453 : 6128 : dsecond = *d;
21454 : 6128 : dsecond.one_operand_p = false;
21455 : 6128 : dsecond.testing_p = true;
21456 : :
21457 : : /* ((perm << 2)|perm) & 0x33 is the vperm2[fi]128
21458 : : immediate. For perm < 16 the second permutation uses
21459 : : d->op0 as first operand, for perm >= 16 it uses d->op1
21460 : : as first operand. The second operand is the result of
21461 : : vperm2[fi]128. */
21462 : 201585 : for (perm = 0; perm < 32; perm++)
21463 : : {
21464 : : /* Ignore permutations which do not move anything cross-lane. */
21465 : 195511 : if (perm < 16)
21466 : : {
21467 : : /* The second shuffle for e.g. V4DFmode has
21468 : : 0123 and ABCD operands.
21469 : : Ignore AB23, as 23 is already in the second lane
21470 : : of the first operand. */
21471 : 97958 : if ((perm & 0xc) == (1 << 2)) continue;
21472 : : /* And 01CD, as 01 is in the first lane of the first
21473 : : operand. */
21474 : 73446 : if ((perm & 3) == 0) continue;
21475 : : /* And 4567, as then the vperm2[fi]128 doesn't change
21476 : : anything on the original 4567 second operand. */
21477 : 55077 : if ((perm & 0xf) == ((3 << 2) | 2)) continue;
21478 : : }
21479 : : else
21480 : : {
21481 : : /* The second shuffle for e.g. V4DFmode has
21482 : : 4567 and ABCD operands.
21483 : : Ignore AB67, as 67 is already in the second lane
21484 : : of the first operand. */
21485 : 97553 : if ((perm & 0xc) == (3 << 2)) continue;
21486 : : /* And 45CD, as 45 is in the first lane of the first
21487 : : operand. */
21488 : 73257 : if ((perm & 3) == 2) continue;
21489 : : /* And 0123, as then the vperm2[fi]128 doesn't change
21490 : : anything on the original 0123 first operand. */
21491 : 54962 : if ((perm & 0xf) == (1 << 2)) continue;
21492 : : }
21493 : :
21494 : 313251 : for (i = 0; i < nelt; i++)
21495 : : {
21496 : 311047 : j = d->perm[i] / nelt2;
21497 : 573929 : if (j == ((perm >> (2 * (i >= nelt2))) & 3))
21498 : 78064 : dsecond.perm[i] = nelt + (i & nelt2) + (d->perm[i] & (nelt2 - 1));
21499 : 386222 : else if (j == (unsigned) (i >= nelt2) + 2 * (perm >= 16))
21500 : 137372 : dsecond.perm[i] = d->perm[i] & (nelt - 1);
21501 : : else
21502 : : break;
21503 : : }
21504 : :
21505 : 97815 : if (i == nelt)
21506 : : {
21507 : 2204 : start_sequence ();
21508 : 2204 : ok = expand_vec_perm_1 (&dsecond);
21509 : 2204 : end_sequence ();
21510 : : }
21511 : : else
21512 : : ok = false;
21513 : :
21514 : 2204 : if (ok)
21515 : : {
21516 : 54 : if (d->testing_p)
21517 : : return true;
21518 : :
21519 : : /* Found a usable second shuffle. dfirst will be
21520 : : vperm2f128 on d->op0 and d->op1. */
21521 : 38 : dsecond.testing_p = false;
21522 : 38 : dfirst = *d;
21523 : 38 : dfirst.target = gen_reg_rtx (d->vmode);
21524 : 194 : for (i = 0; i < nelt; i++)
21525 : 312 : dfirst.perm[i] = (i & (nelt2 - 1))
21526 : 234 : + ((perm >> (2 * (i >= nelt2))) & 3) * nelt2;
21527 : :
21528 : 38 : canonicalize_perm (&dfirst);
21529 : 38 : ok = expand_vec_perm_1 (&dfirst);
21530 : 38 : gcc_assert (ok);
21531 : :
21532 : : /* And dsecond is some single insn shuffle, taking
21533 : : d->op0 and result of vperm2f128 (if perm < 16) or
21534 : : d->op1 and result of vperm2f128 (otherwise). */
21535 : 38 : if (perm >= 16)
21536 : 37 : dsecond.op0 = dsecond.op1;
21537 : 38 : dsecond.op1 = dfirst.target;
21538 : :
21539 : 38 : ok = expand_vec_perm_1 (&dsecond);
21540 : 38 : gcc_assert (ok);
21541 : :
21542 : : return true;
21543 : : }
21544 : :
21545 : : /* For one operand, the only useful vperm2f128 permutation is 0x01
21546 : : aka lanes swap. */
21547 : 97761 : if (d->one_operand_p)
21548 : : return false;
21549 : : }
21550 : :
21551 : : return false;
21552 : : }
21553 : :
21554 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to simplify
21555 : : a two vector permutation using 2 intra-lane interleave insns
21556 : : and cross-lane shuffle for 32-byte vectors. */
21557 : :
21558 : : static bool
21559 : 33853 : expand_vec_perm_interleave3 (struct expand_vec_perm_d *d)
21560 : : {
21561 : 33853 : unsigned i, nelt;
21562 : 33853 : rtx (*gen) (rtx, rtx, rtx);
21563 : :
21564 : 33853 : if (d->one_operand_p)
21565 : : return false;
21566 : 33324 : if (TARGET_AVX2 && GET_MODE_SIZE (d->vmode) == 32)
21567 : : ;
21568 : 25340 : else if (TARGET_AVX && (d->vmode == V8SFmode || d->vmode == V4DFmode))
21569 : : ;
21570 : : else
21571 : : return false;
21572 : :
21573 : 10020 : nelt = d->nelt;
21574 : 10020 : if (d->perm[0] != 0 && d->perm[0] != nelt / 2)
21575 : : return false;
21576 : 6209 : for (i = 0; i < nelt; i += 2)
21577 : 6125 : if (d->perm[i] != d->perm[0] + i / 2
21578 : 5315 : || d->perm[i + 1] != d->perm[0] + i / 2 + nelt)
21579 : : return false;
21580 : :
21581 : 84 : if (d->testing_p)
21582 : : return true;
21583 : :
21584 : 16 : switch (d->vmode)
21585 : : {
21586 : 0 : case E_V32QImode:
21587 : 0 : if (d->perm[0])
21588 : : gen = gen_vec_interleave_highv32qi;
21589 : : else
21590 : 0 : gen = gen_vec_interleave_lowv32qi;
21591 : : break;
21592 : 14 : case E_V16HImode:
21593 : 14 : if (d->perm[0])
21594 : : gen = gen_vec_interleave_highv16hi;
21595 : : else
21596 : 7 : gen = gen_vec_interleave_lowv16hi;
21597 : : break;
21598 : 0 : case E_V8SImode:
21599 : 0 : if (d->perm[0])
21600 : : gen = gen_vec_interleave_highv8si;
21601 : : else
21602 : 0 : gen = gen_vec_interleave_lowv8si;
21603 : : break;
21604 : 0 : case E_V4DImode:
21605 : 0 : if (d->perm[0])
21606 : : gen = gen_vec_interleave_highv4di;
21607 : : else
21608 : 0 : gen = gen_vec_interleave_lowv4di;
21609 : : break;
21610 : 2 : case E_V8SFmode:
21611 : 2 : if (d->perm[0])
21612 : : gen = gen_vec_interleave_highv8sf;
21613 : : else
21614 : 1 : gen = gen_vec_interleave_lowv8sf;
21615 : : break;
21616 : 0 : case E_V4DFmode:
21617 : 0 : if (d->perm[0])
21618 : : gen = gen_vec_interleave_highv4df;
21619 : : else
21620 : 0 : gen = gen_vec_interleave_lowv4df;
21621 : : break;
21622 : 0 : default:
21623 : 0 : gcc_unreachable ();
21624 : : }
21625 : :
21626 : 16 : emit_insn (gen (d->target, d->op0, d->op1));
21627 : 16 : return true;
21628 : : }
21629 : :
21630 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement
21631 : : a single vector permutation using a single intra-lane vector
21632 : : permutation, vperm2f128 swapping the lanes and vblend* insn blending
21633 : : the non-swapped and swapped vectors together. */
21634 : :
21635 : : static bool
21636 : 26543 : expand_vec_perm_vperm2f128_vblend (struct expand_vec_perm_d *d)
21637 : : {
21638 : 26543 : struct expand_vec_perm_d dfirst, dsecond;
21639 : 26543 : unsigned i, j, msk, nelt = d->nelt, nelt2 = nelt / 2;
21640 : 26543 : rtx_insn *seq;
21641 : 26543 : bool ok;
21642 : 26543 : rtx (*blend) (rtx, rtx, rtx, rtx) = NULL;
21643 : :
21644 : 26543 : if (!TARGET_AVX
21645 : 26543 : || TARGET_AVX2
21646 : 2506 : || (d->vmode != V8SFmode && d->vmode != V4DFmode)
21647 : 2018 : || !d->one_operand_p)
21648 : : return false;
21649 : :
21650 : 0 : dfirst = *d;
21651 : 0 : for (i = 0; i < nelt; i++)
21652 : 0 : dfirst.perm[i] = 0xff;
21653 : 0 : for (i = 0, msk = 0; i < nelt; i++)
21654 : : {
21655 : 0 : j = (d->perm[i] & nelt2) ? i | nelt2 : i & ~nelt2;
21656 : 0 : if (dfirst.perm[j] != 0xff && dfirst.perm[j] != d->perm[i])
21657 : : return false;
21658 : 0 : dfirst.perm[j] = d->perm[i];
21659 : 0 : if (j != i)
21660 : 0 : msk |= (1 << i);
21661 : : }
21662 : 0 : for (i = 0; i < nelt; i++)
21663 : 0 : if (dfirst.perm[i] == 0xff)
21664 : 0 : dfirst.perm[i] = i;
21665 : :
21666 : 0 : if (!d->testing_p)
21667 : 0 : dfirst.target = gen_reg_rtx (dfirst.vmode);
21668 : :
21669 : 0 : start_sequence ();
21670 : 0 : ok = expand_vec_perm_1 (&dfirst);
21671 : 0 : seq = get_insns ();
21672 : 0 : end_sequence ();
21673 : :
21674 : 0 : if (!ok)
21675 : : return false;
21676 : :
21677 : 0 : if (d->testing_p)
21678 : : return true;
21679 : :
21680 : 0 : emit_insn (seq);
21681 : :
21682 : 0 : dsecond = *d;
21683 : 0 : dsecond.op0 = dfirst.target;
21684 : 0 : dsecond.op1 = dfirst.target;
21685 : 0 : dsecond.one_operand_p = true;
21686 : 0 : dsecond.target = gen_reg_rtx (dsecond.vmode);
21687 : 0 : for (i = 0; i < nelt; i++)
21688 : 0 : dsecond.perm[i] = i ^ nelt2;
21689 : :
21690 : 0 : ok = expand_vec_perm_1 (&dsecond);
21691 : 0 : gcc_assert (ok);
21692 : :
21693 : 0 : blend = d->vmode == V8SFmode ? gen_avx_blendps256 : gen_avx_blendpd256;
21694 : 0 : emit_insn (blend (d->target, dfirst.target, dsecond.target, GEN_INT (msk)));
21695 : 0 : return true;
21696 : : }
21697 : :
21698 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement
21699 : : a two vector permutation using two single vector permutations and
21700 : : {,v}{,p}unpckl{ps,pd,bw,wd,dq}. If two_insn, succeed only if one
21701 : : of dfirst or dsecond is identity permutation. */
21702 : :
21703 : : static bool
21704 : 128220 : expand_vec_perm_2perm_interleave (struct expand_vec_perm_d *d, bool two_insn)
21705 : : {
21706 : 128220 : unsigned i, nelt = d->nelt, nelt2 = nelt / 2, lane = nelt;
21707 : 128220 : struct expand_vec_perm_d dfirst, dsecond, dfinal;
21708 : 128220 : bool ident1 = true, ident2 = true;
21709 : :
21710 : 128220 : if (d->one_operand_p)
21711 : : return false;
21712 : :
21713 : 239184 : if (GET_MODE_SIZE (d->vmode) == 16)
21714 : : {
21715 : 82662 : if (!TARGET_SSE)
21716 : : return false;
21717 : 82662 : if (d->vmode != V4SFmode && d->vmode != V2DFmode && !TARGET_SSE2)
21718 : : return false;
21719 : : }
21720 : 73860 : else if (GET_MODE_SIZE (d->vmode) == 32)
21721 : : {
21722 : 9973 : if (!TARGET_AVX)
21723 : : return false;
21724 : 9973 : if (d->vmode != V8SFmode && d->vmode != V4DFmode && !TARGET_AVX2)
21725 : : return false;
21726 : : lane = nelt2;
21727 : : }
21728 : : else
21729 : : return false;
21730 : :
21731 : 231777 : for (i = 1; i < nelt; i++)
21732 : 204359 : if ((d->perm[i] >= nelt) != ((d->perm[0] >= nelt) ^ (i & 1)))
21733 : : return false;
21734 : :
21735 : 27418 : dfirst = *d;
21736 : 27418 : dsecond = *d;
21737 : 27418 : dfinal = *d;
21738 : 27418 : dfirst.op1 = dfirst.op0;
21739 : 27418 : dfirst.one_operand_p = true;
21740 : 27418 : dsecond.op0 = dsecond.op1;
21741 : 27418 : dsecond.one_operand_p = true;
21742 : :
21743 : 167570 : for (i = 0; i < nelt; i++)
21744 : 140152 : if (d->perm[i] >= nelt)
21745 : : {
21746 : 70076 : dsecond.perm[i / 2 + (i >= lane ? lane / 2 : 0)] = d->perm[i] - nelt;
21747 : 70076 : if (d->perm[i] - nelt != i / 2 + (i >= lane ? lane / 2 : 0))
21748 : 64376 : ident2 = false;
21749 : 70076 : dsecond.perm[i / 2 + (i >= lane ? lane : lane / 2)]
21750 : 70076 : = d->perm[i] - nelt;
21751 : : }
21752 : : else
21753 : : {
21754 : 70076 : dfirst.perm[i / 2 + (i >= lane ? lane / 2 : 0)] = d->perm[i];
21755 : 70076 : if (d->perm[i] != i / 2 + (i >= lane ? lane / 2 : 0))
21756 : 60745 : ident1 = false;
21757 : 70076 : dfirst.perm[i / 2 + (i >= lane ? lane : lane / 2)] = d->perm[i];
21758 : : }
21759 : :
21760 : 27418 : if (two_insn && !ident1 && !ident2)
21761 : : return false;
21762 : :
21763 : 2265 : if (!d->testing_p)
21764 : : {
21765 : 126 : if (!ident1)
21766 : 62 : dfinal.op0 = dfirst.target = gen_reg_rtx (d->vmode);
21767 : 126 : if (!ident2)
21768 : 64 : dfinal.op1 = dsecond.target = gen_reg_rtx (d->vmode);
21769 : 126 : if (d->perm[0] >= nelt)
21770 : 0 : std::swap (dfinal.op0, dfinal.op1);
21771 : : }
21772 : :
21773 : 2265 : bool ok;
21774 : 2265 : rtx_insn *seq1 = NULL, *seq2 = NULL;
21775 : :
21776 : 2265 : if (!ident1)
21777 : : {
21778 : 1627 : start_sequence ();
21779 : 1627 : ok = expand_vec_perm_1 (&dfirst);
21780 : 1627 : seq1 = get_insns ();
21781 : 1627 : end_sequence ();
21782 : :
21783 : 1627 : if (!ok)
21784 : : return false;
21785 : : }
21786 : :
21787 : 1009 : if (!ident2)
21788 : : {
21789 : 941 : start_sequence ();
21790 : 941 : ok = expand_vec_perm_1 (&dsecond);
21791 : 941 : seq2 = get_insns ();
21792 : 941 : end_sequence ();
21793 : :
21794 : 941 : if (!ok)
21795 : : return false;
21796 : : }
21797 : :
21798 : 220 : if (d->testing_p)
21799 : : return true;
21800 : :
21801 : 630 : for (i = 0; i < nelt; i++)
21802 : : {
21803 : 504 : dfinal.perm[i] = i / 2;
21804 : 504 : if (i >= lane)
21805 : 4 : dfinal.perm[i] += lane / 2;
21806 : 504 : if ((i & 1) != 0)
21807 : 252 : dfinal.perm[i] += nelt;
21808 : : }
21809 : 126 : emit_insn (seq1);
21810 : 126 : emit_insn (seq2);
21811 : 126 : ok = expand_vselect_vconcat (dfinal.target, dfinal.op0, dfinal.op1,
21812 : : dfinal.perm, dfinal.nelt, false);
21813 : 126 : gcc_assert (ok);
21814 : : return true;
21815 : : }
21816 : :
21817 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to simplify
21818 : : the permutation using two single vector permutations and the SSE4_1 pblendv
21819 : : instruction. If two_insn, succeed only if one of dfirst or dsecond is
21820 : : identity permutation. */
21821 : :
21822 : : static bool
21823 : 128000 : expand_vec_perm_2perm_pblendv (struct expand_vec_perm_d *d, bool two_insn)
21824 : : {
21825 : 128000 : unsigned i, nelt = d->nelt;
21826 : 128000 : struct expand_vec_perm_d dfirst, dsecond, dfinal;
21827 : 128000 : machine_mode vmode = d->vmode;
21828 : 128000 : bool ident1 = true, ident2 = true;
21829 : :
21830 : : /* Use the same checks as in expand_vec_perm_blend. */
21831 : 128000 : if (d->one_operand_p)
21832 : : return false;
21833 : 123709 : if (TARGET_AVX2 && GET_MODE_SIZE (vmode) == 32)
21834 : : ;
21835 : 116074 : else if (TARGET_AVX && (vmode == V4DFmode || vmode == V8SFmode))
21836 : : ;
21837 : 110381 : else if (TARGET_SSE4_1
21838 : 119663 : && (GET_MODE_SIZE (vmode) == 16
21839 : 6114 : || (TARGET_MMX_WITH_SSE && GET_MODE_SIZE (vmode) == 8)
21840 : 1530 : || GET_MODE_SIZE (vmode) == 4))
21841 : : ;
21842 : : else
21843 : 102361 : return false;
21844 : :
21845 : 17011 : dfirst = *d;
21846 : 17011 : dsecond = *d;
21847 : 17011 : dfinal = *d;
21848 : 17011 : dfirst.op1 = dfirst.op0;
21849 : 17011 : dfirst.one_operand_p = true;
21850 : 17011 : dsecond.op0 = dsecond.op1;
21851 : 17011 : dsecond.one_operand_p = true;
21852 : :
21853 : 185169 : for (i = 0; i < nelt; ++i)
21854 : 168158 : if (d->perm[i] >= nelt)
21855 : : {
21856 : 108826 : dfirst.perm[i] = 0xff;
21857 : 108826 : dsecond.perm[i] = d->perm[i] - nelt;
21858 : 108826 : if (d->perm[i] != i + nelt)
21859 : 168158 : ident2 = false;
21860 : : }
21861 : : else
21862 : : {
21863 : 59332 : dsecond.perm[i] = 0xff;
21864 : 59332 : dfirst.perm[i] = d->perm[i];
21865 : 59332 : if (d->perm[i] != i)
21866 : 168158 : ident1 = false;
21867 : : }
21868 : :
21869 : 17011 : if (two_insn && !ident1 && !ident2)
21870 : : return false;
21871 : :
21872 : : /* For now. Ideally treat 0xff as a wildcard. */
21873 : 63649 : for (i = 0; i < nelt; ++i)
21874 : 58576 : if (dfirst.perm[i] == 0xff)
21875 : : {
21876 : 40650 : if (GET_MODE_SIZE (vmode) == 32
21877 : 40650 : && dfirst.perm[i ^ (nelt / 2)] != 0xff)
21878 : 24042 : dfirst.perm[i] = dfirst.perm[i ^ (nelt / 2)] ^ (nelt / 2);
21879 : : else
21880 : 16608 : dfirst.perm[i] = i;
21881 : : }
21882 : : else
21883 : : {
21884 : 17926 : if (GET_MODE_SIZE (vmode) == 32
21885 : 17926 : && dsecond.perm[i ^ (nelt / 2)] != 0xff)
21886 : 12743 : dsecond.perm[i] = dsecond.perm[i ^ (nelt / 2)] ^ (nelt / 2);
21887 : : else
21888 : 5183 : dsecond.perm[i] = i;
21889 : : }
21890 : :
21891 : 5073 : if (!d->testing_p)
21892 : : {
21893 : 2843 : if (!ident1)
21894 : 2719 : dfinal.op0 = dfirst.target = gen_reg_rtx (d->vmode);
21895 : 2843 : if (!ident2)
21896 : 1758 : dfinal.op1 = dsecond.target = gen_reg_rtx (d->vmode);
21897 : : }
21898 : :
21899 : 5073 : bool ok;
21900 : 5073 : rtx_insn *seq1 = NULL, *seq2 = NULL;
21901 : :
21902 : 5073 : if (!ident1)
21903 : : {
21904 : 4484 : start_sequence ();
21905 : 4484 : ok = expand_vec_perm_1 (&dfirst);
21906 : 4484 : seq1 = get_insns ();
21907 : 4484 : end_sequence ();
21908 : :
21909 : 4484 : if (!ok)
21910 : : return false;
21911 : : }
21912 : :
21913 : 3018 : if (!ident2)
21914 : : {
21915 : 1688 : start_sequence ();
21916 : 1688 : ok = expand_vec_perm_1 (&dsecond);
21917 : 1688 : seq2 = get_insns ();
21918 : 1688 : end_sequence ();
21919 : :
21920 : 1688 : if (!ok)
21921 : : return false;
21922 : : }
21923 : :
21924 : 2429 : if (d->testing_p)
21925 : : return true;
21926 : :
21927 : 29869 : for (i = 0; i < nelt; ++i)
21928 : 27704 : dfinal.perm[i] = (d->perm[i] >= nelt ? i + nelt : i);
21929 : :
21930 : 2165 : emit_insn (seq1);
21931 : 2165 : emit_insn (seq2);
21932 : 2165 : ok = expand_vec_perm_blend (&dfinal);
21933 : 2165 : gcc_assert (ok);
21934 : : return true;
21935 : : }
21936 : :
21937 : : /* A subroutine of ix86_expand_vec_perm_const_1. Implement a V4DF
21938 : : permutation using two vperm2f128, followed by a vshufpd insn blending
21939 : : the two vectors together. */
21940 : :
21941 : : static bool
21942 : 30747 : expand_vec_perm_2vperm2f128_vshuf (struct expand_vec_perm_d *d)
21943 : : {
21944 : 30747 : struct expand_vec_perm_d dfirst, dsecond, dthird;
21945 : 30747 : bool ok;
21946 : :
21947 : 30747 : if (!TARGET_AVX || (d->vmode != V4DFmode))
21948 : : return false;
21949 : :
21950 : 1481 : if (d->testing_p)
21951 : : return true;
21952 : :
21953 : 162 : dfirst = *d;
21954 : 162 : dsecond = *d;
21955 : 162 : dthird = *d;
21956 : :
21957 : 162 : dfirst.perm[0] = (d->perm[0] & ~1);
21958 : 162 : dfirst.perm[1] = (d->perm[0] & ~1) + 1;
21959 : 162 : dfirst.perm[2] = (d->perm[2] & ~1);
21960 : 162 : dfirst.perm[3] = (d->perm[2] & ~1) + 1;
21961 : 162 : dsecond.perm[0] = (d->perm[1] & ~1);
21962 : 162 : dsecond.perm[1] = (d->perm[1] & ~1) + 1;
21963 : 162 : dsecond.perm[2] = (d->perm[3] & ~1);
21964 : 162 : dsecond.perm[3] = (d->perm[3] & ~1) + 1;
21965 : 162 : dthird.perm[0] = (d->perm[0] % 2);
21966 : 162 : dthird.perm[1] = (d->perm[1] % 2) + 4;
21967 : 162 : dthird.perm[2] = (d->perm[2] % 2) + 2;
21968 : 162 : dthird.perm[3] = (d->perm[3] % 2) + 6;
21969 : :
21970 : 162 : dfirst.target = gen_reg_rtx (dfirst.vmode);
21971 : 162 : dsecond.target = gen_reg_rtx (dsecond.vmode);
21972 : 162 : dthird.op0 = dfirst.target;
21973 : 162 : dthird.op1 = dsecond.target;
21974 : 162 : dthird.one_operand_p = false;
21975 : :
21976 : 162 : canonicalize_perm (&dfirst);
21977 : 162 : canonicalize_perm (&dsecond);
21978 : :
21979 : 162 : ok = expand_vec_perm_1 (&dfirst)
21980 : 162 : && expand_vec_perm_1 (&dsecond)
21981 : 324 : && expand_vec_perm_1 (&dthird);
21982 : :
21983 : 0 : gcc_assert (ok);
21984 : :
21985 : : return true;
21986 : : }
21987 : :
21988 : : static bool ix86_expand_vec_perm_const_1 (struct expand_vec_perm_d *);
21989 : :
21990 : : /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement
21991 : : a two vector permutation using two intra-lane vector
21992 : : permutations, vperm2f128 swapping the lanes and vblend* insn blending
21993 : : the non-swapped and swapped vectors together. */
21994 : :
21995 : : static bool
21996 : 16708 : expand_vec_perm2_vperm2f128_vblend (struct expand_vec_perm_d *d)
21997 : : {
21998 : 16708 : struct expand_vec_perm_d dfirst, dsecond, dthird;
21999 : 16708 : unsigned i, j, msk, nelt = d->nelt, nelt2 = nelt / 2, which1 = 0, which2 = 0;
22000 : 16708 : rtx_insn *seq1, *seq2;
22001 : 16708 : bool ok;
22002 : 16708 : rtx (*blend) (rtx, rtx, rtx, rtx) = NULL;
22003 : :
22004 : 16708 : if (!TARGET_AVX
22005 : 16708 : || TARGET_AVX2
22006 : 611 : || (d->vmode != V8SFmode && d->vmode != V4DFmode)
22007 : 435 : || d->one_operand_p)
22008 : : return false;
22009 : :
22010 : 435 : dfirst = *d;
22011 : 435 : dsecond = *d;
22012 : 3915 : for (i = 0; i < nelt; i++)
22013 : : {
22014 : 3480 : dfirst.perm[i] = 0xff;
22015 : 3480 : dsecond.perm[i] = 0xff;
22016 : : }
22017 : 3915 : for (i = 0, msk = 0; i < nelt; i++)
22018 : : {
22019 : 3480 : j = (d->perm[i] & nelt2) ? i | nelt2 : i & ~nelt2;
22020 : 3480 : if (j == i)
22021 : : {
22022 : 2498 : dfirst.perm[j] = d->perm[i];
22023 : 4322 : which1 |= (d->perm[i] < nelt ? 1 : 2);
22024 : : }
22025 : : else
22026 : : {
22027 : 982 : dsecond.perm[j] = d->perm[i];
22028 : 982 : which2 |= (d->perm[i] < nelt ? 1 : 2);
22029 : 982 : msk |= (1U << i);
22030 : : }
22031 : : }
22032 : 435 : if (msk == 0 || msk == (1U << nelt) - 1)
22033 : : return false;
22034 : :
22035 : 435 : if (!d->testing_p)
22036 : : {
22037 : 56 : dfirst.target = gen_reg_rtx (dfirst.vmode);
22038 : 56 : dsecond.target = gen_reg_rtx (dsecond.vmode);
22039 : : }
22040 : :
22041 : 3915 : for (i = 0; i < nelt; i++)
22042 : : {
22043 : 3480 : if (dfirst.perm[i] == 0xff)
22044 : 982 : dfirst.perm[i] = (which1 == 2 ? i + nelt : i);
22045 : 3480 : if (dsecond.perm[i] == 0xff)
22046 : 2498 : dsecond.perm[i] = (which2 == 2 ? i + nelt : i);
22047 : : }
22048 : 435 : canonicalize_perm (&dfirst);
22049 : 435 : start_sequence ();
22050 : 435 : ok = ix86_expand_vec_perm_const_1 (&dfirst);
22051 : 435 : seq1 = get_insns ();
22052 : 435 : end_sequence ();
22053 : :
22054 : 435 : if (!ok)
22055 : : return false;
22056 : :
22057 : 435 : canonicalize_perm (&dsecond);
22058 : 435 : start_sequence ();
22059 : 435 : ok = ix86_expand_vec_perm_const_1 (&dsecond);
22060 : 435 : seq2 = get_insns ();
22061 : 435 : end_sequence ();
22062 : :
22063 : 435 : if (!ok)
22064 : : return false;
22065 : :
22066 : 435 : if (d->testing_p)
22067 : : return true;
22068 : :
22069 : 56 : emit_insn (seq1);
22070 : 56 : emit_insn (seq2);
22071 : :
22072 : 56 : dthird = *d;
22073 : 56 : dthird.op0 = dsecond.target;
22074 : 56 : dthird.op1 = dsecond.target;
22075 : 56 : dthird.one_operand_p = true;
22076 : 56 : dthird.target = gen_reg_rtx (dthird.vmode);
22077 : 504 : for (i = 0; i < nelt; i++)
22078 : 448 : dthird.perm[i] = i ^ nelt2;
22079 : :
22080 : 56 : ok = expand_vec_perm_1 (&dthird);
22081 : 56 : gcc_assert (ok);
22082 : :
22083 : 56 : blend = d->vmode == V8SFmode ? gen_avx_blendps256 : gen_avx_blendpd256;
22084 : 56 : emit_insn (blend (d->target, dfirst.target, dthird.target, GEN_INT (msk)));
22085 : 56 : return true;
22086 : : }
22087 : :
22088 : : /* A subroutine of expand_vec_perm_even_odd_1. Implement the double-word
22089 : : permutation with two pshufb insns and an ior. We should have already
22090 : : failed all two instruction sequences. */
22091 : :
22092 : : static bool
22093 : 29293 : expand_vec_perm_pshufb2 (struct expand_vec_perm_d *d)
22094 : : {
22095 : 29293 : rtx rperm[2][16], vperm, l, h, op, m128;
22096 : 29293 : unsigned int i, nelt, eltsz;
22097 : 29293 : machine_mode mode;
22098 : 29293 : rtx (*gen) (rtx, rtx, rtx);
22099 : :
22100 : 36136 : if (!TARGET_SSSE3 || (GET_MODE_SIZE (d->vmode) != 16
22101 : 11978 : && GET_MODE_SIZE (d->vmode) != 8
22102 : 9010 : && GET_MODE_SIZE (d->vmode) != 4))
22103 : 26753 : return false;
22104 : 2540 : gcc_assert (!d->one_operand_p);
22105 : :
22106 : 2540 : if (d->testing_p)
22107 : : return true;
22108 : :
22109 : 2050 : switch (GET_MODE_SIZE (d->vmode))
22110 : : {
22111 : : case 4:
22112 : : mode = V4QImode;
22113 : : gen = gen_mmx_pshufbv4qi3;
22114 : : break;
22115 : 165 : case 8:
22116 : 165 : mode = V8QImode;
22117 : 165 : gen = gen_mmx_pshufbv8qi3;
22118 : 165 : break;
22119 : 854 : case 16:
22120 : 854 : mode = V16QImode;
22121 : 854 : gen = gen_ssse3_pshufbv16qi3;
22122 : 854 : break;
22123 : 0 : default:
22124 : 0 : gcc_unreachable ();
22125 : : }
22126 : :
22127 : 1025 : nelt = d->nelt;
22128 : 1025 : eltsz = GET_MODE_UNIT_SIZE (d->vmode);
22129 : :
22130 : : /* Generate two permutation masks. If the required element is within
22131 : : the given vector it is shuffled into the proper lane. If the required
22132 : : element is in the other vector, force a zero into the lane by setting
22133 : : bit 7 in the permutation mask. */
22134 : 1025 : m128 = GEN_INT (-128);
22135 : 13899 : for (i = 0; i < nelt; ++i)
22136 : : {
22137 : 12874 : unsigned j, k, e = d->perm[i];
22138 : 12874 : unsigned which = (e >= nelt);
22139 : 12874 : if (e >= nelt)
22140 : 11225 : e -= nelt;
22141 : :
22142 : 27882 : for (j = 0; j < eltsz; ++j)
22143 : : {
22144 : 15008 : rperm[which][i*eltsz + j] = GEN_INT (e*eltsz + j);
22145 : 15008 : rperm[1-which][i*eltsz + j] = m128;
22146 : : }
22147 : :
22148 : 113186 : for (k = i*eltsz + j; k < 16; ++k)
22149 : 100312 : rperm[0][k] = rperm[1][k] = m128;
22150 : : }
22151 : :
22152 : 1025 : vperm = gen_rtx_CONST_VECTOR (V16QImode, gen_rtvec_v (16, rperm[0]));
22153 : 1025 : vperm = force_reg (V16QImode, vperm);
22154 : :
22155 : 1025 : l = gen_reg_rtx (mode);
22156 : 1025 : op = gen_lowpart (mode, d->op0);
22157 : 1025 : emit_insn (gen (l, op, vperm));
22158 : :
22159 : 1025 : vperm = gen_rtx_CONST_VECTOR (V16QImode, gen_rtvec_v (16, rperm[1]));
22160 : 1025 : vperm = force_reg (V16QImode, vperm);
22161 : :
22162 : 1025 : h = gen_reg_rtx (mode);
22163 : 1025 : op = gen_lowpart (mode, d->op1);
22164 : 1025 : emit_insn (gen (h, op, vperm));
22165 : :
22166 : 1025 : op = d->target;
22167 : 1025 : if (d->vmode != mode)
22168 : 285 : op = gen_reg_rtx (mode);
22169 : 1025 : ix86_emit_vec_binop (IOR, mode, op, l, h);
22170 : 1025 : if (op != d->target)
22171 : 285 : emit_move_insn (d->target, gen_lowpart (d->vmode, op));
22172 : :
22173 : : return true;
22174 : : }
22175 : :
22176 : : /* Implement arbitrary permutation of one V32QImode and V16QImode operand
22177 : : with two vpshufb insns, vpermq and vpor. We should have already failed
22178 : : all two or three instruction sequences. */
22179 : :
22180 : : static bool
22181 : 25401 : expand_vec_perm_vpshufb2_vpermq (struct expand_vec_perm_d *d)
22182 : : {
22183 : 25401 : rtx rperm[2][32], vperm, l, h, hp, op, m128;
22184 : 25401 : unsigned int i, nelt, eltsz;
22185 : :
22186 : 25401 : if (!TARGET_AVX2
22187 : 700 : || !d->one_operand_p
22188 : 133 : || (d->vmode != V32QImode && d->vmode != V16HImode))
22189 : : return false;
22190 : :
22191 : 0 : if (d->testing_p)
22192 : : return true;
22193 : :
22194 : 0 : nelt = d->nelt;
22195 : 0 : eltsz = GET_MODE_UNIT_SIZE (d->vmode);
22196 : :
22197 : : /* Generate two permutation masks. If the required element is within
22198 : : the same lane, it is shuffled in. If the required element from the
22199 : : other lane, force a zero by setting bit 7 in the permutation mask.
22200 : : In the other mask the mask has non-negative elements if element
22201 : : is requested from the other lane, but also moved to the other lane,
22202 : : so that the result of vpshufb can have the two V2TImode halves
22203 : : swapped. */
22204 : 0 : m128 = GEN_INT (-128);
22205 : 0 : for (i = 0; i < nelt; ++i)
22206 : : {
22207 : 0 : unsigned j, e = d->perm[i] & (nelt / 2 - 1);
22208 : 0 : unsigned which = ((d->perm[i] ^ i) & (nelt / 2)) * eltsz;
22209 : :
22210 : 0 : for (j = 0; j < eltsz; ++j)
22211 : : {
22212 : 0 : rperm[!!which][(i * eltsz + j) ^ which] = GEN_INT (e * eltsz + j);
22213 : 0 : rperm[!which][(i * eltsz + j) ^ (which ^ 16)] = m128;
22214 : : }
22215 : : }
22216 : :
22217 : 0 : vperm = gen_rtx_CONST_VECTOR (V32QImode, gen_rtvec_v (32, rperm[1]));
22218 : 0 : vperm = force_reg (V32QImode, vperm);
22219 : :
22220 : 0 : h = gen_reg_rtx (V32QImode);
22221 : 0 : op = gen_lowpart (V32QImode, d->op0);
22222 : 0 : emit_insn (gen_avx2_pshufbv32qi3 (h, op, vperm));
22223 : :
22224 : : /* Swap the 128-byte lanes of h into hp. */
22225 : 0 : hp = gen_reg_rtx (V4DImode);
22226 : 0 : op = gen_lowpart (V4DImode, h);
22227 : 0 : emit_insn (gen_avx2_permv4di_1 (hp, op, const2_rtx, GEN_INT (3), const0_rtx,
22228 : : const1_rtx));
22229 : :
22230 : 0 : vperm = gen_rtx_CONST_VECTOR (V32QImode, gen_rtvec_v (32, rperm[0]));
22231 : 0 : vperm = force_reg (V32QImode, vperm);
22232 : :
22233 : 0 : l = gen_reg_rtx (V32QImode);
22234 : 0 : op = gen_lowpart (V32QImode, d->op0);
22235 : 0 : emit_insn (gen_avx2_pshufbv32qi3 (l, op, vperm));
22236 : :
22237 : 0 : op = d->target;
22238 : 0 : if (d->vmode != V32QImode)
22239 : 0 : op = gen_reg_rtx (V32QImode);
22240 : 0 : emit_insn (gen_iorv32qi3 (op, l, gen_lowpart (V32QImode, hp)));
22241 : 0 : if (op != d->target)
22242 : 0 : emit_move_insn (d->target, gen_lowpart (d->vmode, op));
22243 : :
22244 : : return true;
22245 : : }
22246 : :
22247 : : /* A subroutine of expand_vec_perm_even_odd_1. Implement extract-even
22248 : : and extract-odd permutations of two V32QImode and V16QImode operand
22249 : : with two vpshufb insns, vpor and vpermq. We should have already
22250 : : failed all two or three instruction sequences. */
22251 : :
22252 : : static bool
22253 : 25401 : expand_vec_perm_vpshufb2_vpermq_even_odd (struct expand_vec_perm_d *d)
22254 : : {
22255 : 25401 : rtx rperm[2][32], vperm, l, h, ior, op, m128;
22256 : 25401 : unsigned int i, nelt, eltsz;
22257 : :
22258 : 25401 : if (!TARGET_AVX2
22259 : 700 : || d->one_operand_p
22260 : 567 : || (d->vmode != V32QImode && d->vmode != V16HImode))
22261 : : return false;
22262 : :
22263 : 432 : for (i = 0; i < d->nelt; ++i)
22264 : 432 : if ((d->perm[i] ^ (i * 2)) & (3 * d->nelt / 2))
22265 : : return false;
22266 : :
22267 : 0 : if (d->testing_p)
22268 : : return true;
22269 : :
22270 : 0 : nelt = d->nelt;
22271 : 0 : eltsz = GET_MODE_UNIT_SIZE (d->vmode);
22272 : :
22273 : : /* Generate two permutation masks. In the first permutation mask
22274 : : the first quarter will contain indexes for the first half
22275 : : of the op0, the second quarter will contain bit 7 set, third quarter
22276 : : will contain indexes for the second half of the op0 and the
22277 : : last quarter bit 7 set. In the second permutation mask
22278 : : the first quarter will contain bit 7 set, the second quarter
22279 : : indexes for the first half of the op1, the third quarter bit 7 set
22280 : : and last quarter indexes for the second half of the op1.
22281 : : I.e. the first mask e.g. for V32QImode extract even will be:
22282 : : 0, 2, ..., 0xe, -128, ..., -128, 0, 2, ..., 0xe, -128, ..., -128
22283 : : (all values masked with 0xf except for -128) and second mask
22284 : : for extract even will be
22285 : : -128, ..., -128, 0, 2, ..., 0xe, -128, ..., -128, 0, 2, ..., 0xe. */
22286 : 0 : m128 = GEN_INT (-128);
22287 : 0 : for (i = 0; i < nelt; ++i)
22288 : : {
22289 : 0 : unsigned j, e = d->perm[i] & (nelt / 2 - 1);
22290 : 0 : unsigned which = d->perm[i] >= nelt;
22291 : 0 : unsigned xorv = (i >= nelt / 4 && i < 3 * nelt / 4) ? 24 : 0;
22292 : :
22293 : 0 : for (j = 0; j < eltsz; ++j)
22294 : : {
22295 : 0 : rperm[which][(i * eltsz + j) ^ xorv] = GEN_INT (e * eltsz + j);
22296 : 0 : rperm[1 - which][(i * eltsz + j) ^ xorv] = m128;
22297 : : }
22298 : : }
22299 : :
22300 : 0 : vperm = gen_rtx_CONST_VECTOR (V32QImode, gen_rtvec_v (32, rperm[0]));
22301 : 0 : vperm = force_reg (V32QImode, vperm);
22302 : :
22303 : 0 : l = gen_reg_rtx (V32QImode);
22304 : 0 : op = gen_lowpart (V32QImode, d->op0);
22305 : 0 : emit_insn (gen_avx2_pshufbv32qi3 (l, op, vperm));
22306 : :
22307 : 0 : vperm = gen_rtx_CONST_VECTOR (V32QImode, gen_rtvec_v (32, rperm[1]));
22308 : 0 : vperm = force_reg (V32QImode, vperm);
22309 : :
22310 : 0 : h = gen_reg_rtx (V32QImode);
22311 : 0 : op = gen_lowpart (V32QImode, d->op1);
22312 : 0 : emit_insn (gen_avx2_pshufbv32qi3 (h, op, vperm));
22313 : :
22314 : 0 : ior = gen_reg_rtx (V32QImode);
22315 : 0 : emit_insn (gen_iorv32qi3 (ior, l, h));
22316 : :
22317 : : /* Permute the V4DImode quarters using { 0, 2, 1, 3 } permutation. */
22318 : 0 : op = gen_reg_rtx (V4DImode);
22319 : 0 : ior = gen_lowpart (V4DImode, ior);
22320 : 0 : emit_insn (gen_avx2_permv4di_1 (op, ior, const0_rtx, const2_rtx,
22321 : : const1_rtx, GEN_INT (3)));
22322 : 0 : emit_move_insn (d->target, gen_lowpart (d->vmode, op));
22323 : :
22324 : 0 : return true;
22325 : : }
22326 : :
22327 : : /* Implement permutation with pslldq + psrldq + por when pshufb is not
22328 : : available. */
22329 : : static bool
22330 : 44203 : expand_vec_perm_pslldq_psrldq_por (struct expand_vec_perm_d *d, bool pandn)
22331 : : {
22332 : 44203 : unsigned i, nelt = d->nelt;
22333 : 44203 : unsigned start1, end1 = -1;
22334 : 44203 : machine_mode vmode = d->vmode, imode;
22335 : 44203 : int start2 = -1;
22336 : 44203 : bool clear_op0, clear_op1;
22337 : 44203 : unsigned inner_size;
22338 : 44203 : rtx op0, op1, dop1;
22339 : 44203 : rtx (*gen_vec_shr) (rtx, rtx, rtx);
22340 : 44203 : rtx (*gen_vec_shl) (rtx, rtx, rtx);
22341 : :
22342 : : /* pshufd can be used for V4SI/V2DI under TARGET_SSE2. */
22343 : 44203 : if (!TARGET_SSE2 || (vmode != E_V16QImode && vmode != E_V8HImode))
22344 : : return false;
22345 : :
22346 : 14076 : start1 = d->perm[0];
22347 : 38096 : for (i = 1; i < nelt; i++)
22348 : : {
22349 : 37244 : if (d->perm[i] != d->perm[i-1] + 1
22350 : 10094 : || d->perm[i] == nelt)
22351 : : {
22352 : 27300 : if (start2 == -1)
22353 : : {
22354 : 14076 : start2 = d->perm[i];
22355 : 14076 : end1 = d->perm[i-1];
22356 : : }
22357 : : else
22358 : : return false;
22359 : : }
22360 : : }
22361 : :
22362 : 852 : clear_op0 = end1 != nelt - 1;
22363 : 852 : clear_op1 = start2 % nelt != 0;
22364 : : /* pandn/pand is needed to clear upper/lower bits of op0/op1. */
22365 : 852 : if (!pandn && (clear_op0 || clear_op1))
22366 : : return false;
22367 : :
22368 : 516 : if (d->testing_p)
22369 : : return true;
22370 : :
22371 : 74 : gen_vec_shr = vmode == E_V16QImode ? gen_vec_shr_v16qi : gen_vec_shr_v8hi;
22372 : 34 : gen_vec_shl = vmode == E_V16QImode ? gen_vec_shl_v16qi : gen_vec_shl_v8hi;
22373 : 74 : imode = GET_MODE_INNER (vmode);
22374 : 74 : inner_size = GET_MODE_BITSIZE (imode);
22375 : 74 : op0 = gen_reg_rtx (vmode);
22376 : 74 : op1 = gen_reg_rtx (vmode);
22377 : :
22378 : 74 : if (start1)
22379 : 68 : emit_insn (gen_vec_shr (op0, d->op0, GEN_INT (start1 * inner_size)));
22380 : : else
22381 : 6 : emit_move_insn (op0, d->op0);
22382 : :
22383 : 74 : dop1 = d->op1;
22384 : 74 : if (d->one_operand_p)
22385 : 23 : dop1 = d->op0;
22386 : :
22387 : 74 : int shl_offset = end1 - start1 + 1 - start2 % nelt;
22388 : 74 : if (shl_offset)
22389 : 43 : emit_insn (gen_vec_shl (op1, dop1, GEN_INT (shl_offset * inner_size)));
22390 : : else
22391 : 31 : emit_move_insn (op1, dop1);
22392 : :
22393 : : /* Clear lower/upper bits for op0/op1. */
22394 : 74 : if (clear_op0 || clear_op1)
22395 : : {
22396 : : rtx vec[16];
22397 : : rtx const_vec;
22398 : : rtx clear;
22399 : 754 : for (i = 0; i != nelt; i++)
22400 : : {
22401 : 696 : if (i < (end1 - start1 + 1))
22402 : 187 : vec[i] = gen_int_mode ((HOST_WIDE_INT_1U << inner_size) - 1, imode);
22403 : : else
22404 : 509 : vec[i] = CONST0_RTX (imode);
22405 : : }
22406 : 58 : const_vec = gen_rtx_CONST_VECTOR (vmode, gen_rtvec_v (nelt, vec));
22407 : 58 : const_vec = validize_mem (force_const_mem (vmode, const_vec));
22408 : 58 : clear = force_reg (vmode, const_vec);
22409 : :
22410 : 58 : if (clear_op0)
22411 : 50 : emit_move_insn (op0, gen_rtx_AND (vmode, op0, clear));
22412 : 58 : if (clear_op1)
22413 : 47 : emit_move_insn (op1, gen_rtx_AND (vmode,
22414 : : gen_rtx_NOT (vmode, clear),
22415 : : op1));
22416 : : }
22417 : :
22418 : 74 : emit_move_insn (d->target, gen_rtx_IOR (vmode, op0, op1));
22419 : 74 : return true;
22420 : : }
22421 : :
22422 : : /* A subroutine of expand_vec_perm_even_odd_1. Implement extract-even
22423 : : and extract-odd permutations of two V8QI, V8HI, V16QI, V16HI or V32QI
22424 : : operands with two "and" and "pack" or two "shift" and "pack" insns.
22425 : : We should have already failed all two instruction sequences. */
22426 : :
22427 : : static bool
22428 : 43949 : expand_vec_perm_even_odd_pack (struct expand_vec_perm_d *d)
22429 : : {
22430 : 43949 : rtx op, dop0, dop1, t;
22431 : 43949 : unsigned i, odd, c, s, nelt = d->nelt;
22432 : 43949 : bool end_perm = false;
22433 : 43949 : machine_mode half_mode;
22434 : 43949 : rtx (*gen_and) (rtx, rtx, rtx);
22435 : 43949 : rtx (*gen_pack) (rtx, rtx, rtx);
22436 : 43949 : rtx (*gen_shift) (rtx, rtx, rtx);
22437 : :
22438 : 43949 : if (d->one_operand_p)
22439 : : return false;
22440 : :
22441 : 39619 : switch (d->vmode)
22442 : : {
22443 : 4875 : case E_V4HImode:
22444 : : /* Required for "pack". */
22445 : 4875 : if (!TARGET_SSE4_1)
22446 : : return false;
22447 : : c = 0xffff;
22448 : : s = 16;
22449 : : half_mode = V2SImode;
22450 : : gen_and = gen_andv2si3;
22451 : : gen_pack = gen_mmx_packusdw;
22452 : : gen_shift = gen_lshrv2si3;
22453 : : break;
22454 : 6214 : case E_V8HImode:
22455 : : /* Required for "pack". */
22456 : 6214 : if (!TARGET_SSE4_1)
22457 : : return false;
22458 : : c = 0xffff;
22459 : : s = 16;
22460 : : half_mode = V4SImode;
22461 : : gen_and = gen_andv4si3;
22462 : : gen_pack = gen_sse4_1_packusdw;
22463 : : gen_shift = gen_lshrv4si3;
22464 : : break;
22465 : : case E_V8QImode:
22466 : : /* No check as all instructions are SSE2. */
22467 : : c = 0xff;
22468 : : s = 8;
22469 : : half_mode = V4HImode;
22470 : : gen_and = gen_andv4hi3;
22471 : : gen_pack = gen_mmx_packuswb;
22472 : : gen_shift = gen_lshrv4hi3;
22473 : : break;
22474 : 11407 : case E_V16QImode:
22475 : : /* No check as all instructions are SSE2. */
22476 : 11407 : c = 0xff;
22477 : 11407 : s = 8;
22478 : 11407 : half_mode = V8HImode;
22479 : 11407 : gen_and = gen_andv8hi3;
22480 : 11407 : gen_pack = gen_sse2_packuswb;
22481 : 11407 : gen_shift = gen_lshrv8hi3;
22482 : 11407 : break;
22483 : 498 : case E_V16HImode:
22484 : 498 : if (!TARGET_AVX2)
22485 : : return false;
22486 : : c = 0xffff;
22487 : : s = 16;
22488 : : half_mode = V8SImode;
22489 : : gen_and = gen_andv8si3;
22490 : : gen_pack = gen_avx2_packusdw;
22491 : : gen_shift = gen_lshrv8si3;
22492 : : end_perm = true;
22493 : : break;
22494 : 1134 : case E_V32QImode:
22495 : 1134 : if (!TARGET_AVX2)
22496 : : return false;
22497 : : c = 0xff;
22498 : : s = 8;
22499 : : half_mode = V16HImode;
22500 : : gen_and = gen_andv16hi3;
22501 : : gen_pack = gen_avx2_packuswb;
22502 : : gen_shift = gen_lshrv16hi3;
22503 : : end_perm = true;
22504 : : break;
22505 : : default:
22506 : : /* Only V4HI, V8QI, V8HI, V16QI, V16HI and V32QI modes
22507 : : are more profitable than general shuffles. */
22508 : : return false;
22509 : : }
22510 : :
22511 : : /* Check that permutation is even or odd. */
22512 : 18215 : odd = d->perm[0];
22513 : 18215 : if (odd > 1)
22514 : : return false;
22515 : :
22516 : 189330 : for (i = 1; i < nelt; ++i)
22517 : 176173 : if (d->perm[i] != 2 * i + odd)
22518 : : return false;
22519 : :
22520 : 13157 : if (d->testing_p)
22521 : : return true;
22522 : :
22523 : 5491 : dop0 = gen_reg_rtx (half_mode);
22524 : 5491 : dop1 = gen_reg_rtx (half_mode);
22525 : 5491 : if (odd == 0)
22526 : : {
22527 : 4668 : t = gen_const_vec_duplicate (half_mode, GEN_INT (c));
22528 : 4668 : t = force_reg (half_mode, t);
22529 : 4668 : emit_insn (gen_and (dop0, t, gen_lowpart (half_mode, d->op0)));
22530 : 4668 : emit_insn (gen_and (dop1, t, gen_lowpart (half_mode, d->op1)));
22531 : : }
22532 : : else
22533 : : {
22534 : 1646 : emit_insn (gen_shift (dop0,
22535 : 823 : gen_lowpart (half_mode, d->op0),
22536 : : GEN_INT (s)));
22537 : 1646 : emit_insn (gen_shift (dop1,
22538 : 823 : gen_lowpart (half_mode, d->op1),
22539 : : GEN_INT (s)));
22540 : : }
22541 : : /* In AVX2 for 256 bit case we need to permute pack result. */
22542 : 5491 : if (TARGET_AVX2 && end_perm)
22543 : : {
22544 : 503 : op = gen_reg_rtx (d->vmode);
22545 : 503 : t = gen_reg_rtx (V4DImode);
22546 : 503 : emit_insn (gen_pack (op, dop0, dop1));
22547 : 1006 : emit_insn (gen_avx2_permv4di_1 (t,
22548 : 503 : gen_lowpart (V4DImode, op),
22549 : : const0_rtx,
22550 : : const2_rtx,
22551 : : const1_rtx,
22552 : : GEN_INT (3)));
22553 : 503 : emit_move_insn (d->target, gen_lowpart (d->vmode, t));
22554 : : }
22555 : : else
22556 : 4988 : emit_insn (gen_pack (d->target, dop0, dop1));
22557 : :
22558 : : return true;
22559 : : }
22560 : :
22561 : : /* A subroutine of expand_vec_perm_even_odd_1. Implement extract-even
22562 : : and extract-odd permutations of two V64QI operands
22563 : : with two "shifts", two "truncs" and one "concat" insns for "odd"
22564 : : and two "truncs" and one concat insn for "even."
22565 : : Have already failed all two instruction sequences. */
22566 : :
22567 : : static bool
22568 : 25436 : expand_vec_perm_even_odd_trunc (struct expand_vec_perm_d *d)
22569 : : {
22570 : 25436 : rtx t1, t2, t3, t4;
22571 : 25436 : unsigned i, odd, nelt = d->nelt;
22572 : :
22573 : 25436 : if (!TARGET_AVX512BW
22574 : 63 : || d->one_operand_p
22575 : 59 : || d->vmode != V64QImode)
22576 : : return false;
22577 : :
22578 : : /* Check that permutation is even or odd. */
22579 : 59 : odd = d->perm[0];
22580 : 59 : if (odd > 1)
22581 : : return false;
22582 : :
22583 : 1718 : for (i = 1; i < nelt; ++i)
22584 : 1695 : if (d->perm[i] != 2 * i + odd)
22585 : : return false;
22586 : :
22587 : 23 : if (d->testing_p)
22588 : : return true;
22589 : :
22590 : :
22591 : 23 : if (odd)
22592 : : {
22593 : 1 : t1 = gen_reg_rtx (V32HImode);
22594 : 1 : t2 = gen_reg_rtx (V32HImode);
22595 : 2 : emit_insn (gen_lshrv32hi3 (t1,
22596 : 1 : gen_lowpart (V32HImode, d->op0),
22597 : : GEN_INT (8)));
22598 : 2 : emit_insn (gen_lshrv32hi3 (t2,
22599 : 1 : gen_lowpart (V32HImode, d->op1),
22600 : : GEN_INT (8)));
22601 : : }
22602 : : else
22603 : : {
22604 : 22 : t1 = gen_lowpart (V32HImode, d->op0);
22605 : 22 : t2 = gen_lowpart (V32HImode, d->op1);
22606 : : }
22607 : :
22608 : 23 : t3 = gen_reg_rtx (V32QImode);
22609 : 23 : t4 = gen_reg_rtx (V32QImode);
22610 : 23 : emit_insn (gen_avx512bw_truncatev32hiv32qi2 (t3, t1));
22611 : 23 : emit_insn (gen_avx512bw_truncatev32hiv32qi2 (t4, t2));
22612 : 23 : emit_insn (gen_avx_vec_concatv64qi (d->target, t3, t4));
22613 : :
22614 : 23 : return true;
22615 : : }
22616 : :
22617 : : /* A subroutine of ix86_expand_vec_perm_const_1. Implement extract-even
22618 : : and extract-odd permutations. */
22619 : :
22620 : : static bool
22621 : 12311 : expand_vec_perm_even_odd_1 (struct expand_vec_perm_d *d, unsigned odd)
22622 : : {
22623 : 12311 : rtx t1, t2, t3, t4, t5;
22624 : :
22625 : 12311 : switch (d->vmode)
22626 : : {
22627 : 148 : case E_V4DFmode:
22628 : 148 : if (d->testing_p)
22629 : : break;
22630 : 1 : t1 = gen_reg_rtx (V4DFmode);
22631 : 1 : t2 = gen_reg_rtx (V4DFmode);
22632 : :
22633 : : /* Shuffle the lanes around into { 0 1 4 5 } and { 2 3 6 7 }. */
22634 : 1 : emit_insn (gen_avx_vperm2f128v4df3 (t1, d->op0, d->op1, GEN_INT (0x20)));
22635 : 1 : emit_insn (gen_avx_vperm2f128v4df3 (t2, d->op0, d->op1, GEN_INT (0x31)));
22636 : :
22637 : : /* Now an unpck[lh]pd will produce the result required. */
22638 : 1 : if (odd)
22639 : 0 : t3 = gen_avx_unpckhpd256 (d->target, t1, t2);
22640 : : else
22641 : 1 : t3 = gen_avx_unpcklpd256 (d->target, t1, t2);
22642 : 1 : emit_insn (t3);
22643 : 1 : break;
22644 : :
22645 : 1672 : case E_V8SFmode:
22646 : 1672 : {
22647 : 1672 : int mask = odd ? 0xdd : 0x88;
22648 : :
22649 : 1672 : if (d->testing_p)
22650 : : break;
22651 : 154 : t1 = gen_reg_rtx (V8SFmode);
22652 : 154 : t2 = gen_reg_rtx (V8SFmode);
22653 : 154 : t3 = gen_reg_rtx (V8SFmode);
22654 : :
22655 : : /* Shuffle within the 128-bit lanes to produce:
22656 : : { 0 2 8 a 4 6 c e } | { 1 3 9 b 5 7 d f }. */
22657 : 154 : emit_insn (gen_avx_shufps256 (t1, d->op0, d->op1,
22658 : : GEN_INT (mask)));
22659 : :
22660 : : /* Shuffle the lanes around to produce:
22661 : : { 4 6 c e 0 2 8 a } and { 5 7 d f 1 3 9 b }. */
22662 : 154 : emit_insn (gen_avx_vperm2f128v8sf3 (t2, t1, t1,
22663 : : GEN_INT (0x3)));
22664 : :
22665 : : /* Shuffle within the 128-bit lanes to produce:
22666 : : { 0 2 4 6 4 6 0 2 } | { 1 3 5 7 5 7 1 3 }. */
22667 : 154 : emit_insn (gen_avx_shufps256 (t3, t1, t2, GEN_INT (0x44)));
22668 : :
22669 : : /* Shuffle within the 128-bit lanes to produce:
22670 : : { 8 a c e c e 8 a } | { 9 b d f d f 9 b }. */
22671 : 154 : emit_insn (gen_avx_shufps256 (t2, t1, t2, GEN_INT (0xee)));
22672 : :
22673 : : /* Shuffle the lanes around to produce:
22674 : : { 0 2 4 6 8 a c e } | { 1 3 5 7 9 b d f }. */
22675 : 154 : emit_insn (gen_avx_vperm2f128v8sf3 (d->target, t3, t2,
22676 : : GEN_INT (0x20)));
22677 : : }
22678 : 154 : break;
22679 : :
22680 : 0 : case E_V2DFmode:
22681 : 0 : case E_V4SFmode:
22682 : 0 : case E_V2DImode:
22683 : 0 : case E_V2SImode:
22684 : 0 : case E_V4SImode:
22685 : 0 : case E_V2HImode:
22686 : : /* These are always directly implementable by expand_vec_perm_1. */
22687 : 0 : gcc_unreachable ();
22688 : :
22689 : 0 : case E_V2SFmode:
22690 : 0 : gcc_assert (TARGET_MMX_WITH_SSE);
22691 : : /* We have no suitable instructions. */
22692 : 0 : if (d->testing_p)
22693 : : return false;
22694 : : break;
22695 : :
22696 : 856 : case E_V4QImode:
22697 : 856 : if (TARGET_SSSE3 && !TARGET_SLOW_PSHUFB)
22698 : 6 : return expand_vec_perm_pshufb2 (d);
22699 : : else
22700 : : {
22701 : 850 : if (d->testing_p)
22702 : : break;
22703 : : /* We need 2*log2(N)-1 operations to achieve odd/even
22704 : : with interleave. */
22705 : 156 : t1 = gen_reg_rtx (V4QImode);
22706 : 156 : emit_insn (gen_mmx_punpckhbw_low (t1, d->op0, d->op1));
22707 : 156 : emit_insn (gen_mmx_punpcklbw_low (d->target, d->op0, d->op1));
22708 : 156 : if (odd)
22709 : 50 : t2 = gen_mmx_punpckhbw_low (d->target, d->target, t1);
22710 : : else
22711 : 106 : t2 = gen_mmx_punpcklbw_low (d->target, d->target, t1);
22712 : 156 : emit_insn (t2);
22713 : : }
22714 : 156 : break;
22715 : :
22716 : 1331 : case E_V4HImode:
22717 : 1331 : if (TARGET_SSE4_1)
22718 : 96 : return expand_vec_perm_even_odd_pack (d);
22719 : 1235 : else if (TARGET_SSSE3 && !TARGET_SLOW_PSHUFB)
22720 : 20 : return expand_vec_perm_pshufb2 (d);
22721 : : else
22722 : : {
22723 : 1215 : if (d->testing_p)
22724 : : break;
22725 : : /* We need 2*log2(N)-1 operations to achieve odd/even
22726 : : with interleave. */
22727 : 483 : t1 = gen_reg_rtx (V4HImode);
22728 : 483 : emit_insn (gen_mmx_punpckhwd (t1, d->op0, d->op1));
22729 : 483 : emit_insn (gen_mmx_punpcklwd (d->target, d->op0, d->op1));
22730 : 483 : if (odd)
22731 : 28 : t2 = gen_mmx_punpckhwd (d->target, d->target, t1);
22732 : : else
22733 : 455 : t2 = gen_mmx_punpcklwd (d->target, d->target, t1);
22734 : 483 : emit_insn (t2);
22735 : : }
22736 : 483 : break;
22737 : :
22738 : 6424 : case E_V8HImode:
22739 : 6424 : if (TARGET_SSE4_1)
22740 : 342 : return expand_vec_perm_even_odd_pack (d);
22741 : 6082 : else if (TARGET_SSSE3 && !TARGET_SLOW_PSHUFB)
22742 : 1 : return expand_vec_perm_pshufb2 (d);
22743 : : else
22744 : : {
22745 : 6081 : if (d->testing_p)
22746 : : break;
22747 : : /* We need 2*log2(N)-1 operations to achieve odd/even
22748 : : with interleave. */
22749 : 2358 : t1 = gen_reg_rtx (V8HImode);
22750 : 2358 : t2 = gen_reg_rtx (V8HImode);
22751 : 2358 : emit_insn (gen_vec_interleave_highv8hi (t1, d->op0, d->op1));
22752 : 2358 : emit_insn (gen_vec_interleave_lowv8hi (d->target, d->op0, d->op1));
22753 : 2358 : emit_insn (gen_vec_interleave_highv8hi (t2, d->target, t1));
22754 : 2358 : emit_insn (gen_vec_interleave_lowv8hi (d->target, d->target, t1));
22755 : 2358 : if (odd)
22756 : 195 : t3 = gen_vec_interleave_highv8hi (d->target, d->target, t2);
22757 : : else
22758 : 2163 : t3 = gen_vec_interleave_lowv8hi (d->target, d->target, t2);
22759 : 2358 : emit_insn (t3);
22760 : : }
22761 : 2358 : break;
22762 : :
22763 : 1140 : case E_V8QImode:
22764 : 1140 : case E_V16QImode:
22765 : 1140 : return expand_vec_perm_even_odd_pack (d);
22766 : :
22767 : 320 : case E_V16HImode:
22768 : 320 : case E_V32QImode:
22769 : 320 : return expand_vec_perm_even_odd_pack (d);
22770 : :
22771 : 32 : case E_V64QImode:
22772 : 32 : return expand_vec_perm_even_odd_trunc (d);
22773 : :
22774 : 148 : case E_V4DImode:
22775 : 148 : if (!TARGET_AVX2)
22776 : : {
22777 : 148 : struct expand_vec_perm_d d_copy = *d;
22778 : 148 : d_copy.vmode = V4DFmode;
22779 : 148 : if (d->testing_p)
22780 : 147 : d_copy.target = gen_raw_REG (V4DFmode, LAST_VIRTUAL_REGISTER + 1);
22781 : : else
22782 : 1 : d_copy.target = gen_reg_rtx (V4DFmode);
22783 : 148 : d_copy.op0 = gen_lowpart (V4DFmode, d->op0);
22784 : 148 : d_copy.op1 = gen_lowpart (V4DFmode, d->op1);
22785 : 148 : if (expand_vec_perm_even_odd_1 (&d_copy, odd))
22786 : : {
22787 : 148 : if (!d->testing_p)
22788 : 1 : emit_move_insn (d->target,
22789 : 1 : gen_lowpart (V4DImode, d_copy.target));
22790 : 148 : return true;
22791 : : }
22792 : : return false;
22793 : : }
22794 : :
22795 : 0 : if (d->testing_p)
22796 : : break;
22797 : :
22798 : 0 : t1 = gen_reg_rtx (V4DImode);
22799 : 0 : t2 = gen_reg_rtx (V4DImode);
22800 : :
22801 : : /* Shuffle the lanes around into { 0 1 4 5 } and { 2 3 6 7 }. */
22802 : 0 : emit_insn (gen_avx2_permv2ti (t1, d->op0, d->op1, GEN_INT (0x20)));
22803 : 0 : emit_insn (gen_avx2_permv2ti (t2, d->op0, d->op1, GEN_INT (0x31)));
22804 : :
22805 : : /* Now an vpunpck[lh]qdq will produce the result required. */
22806 : 0 : if (odd)
22807 : 0 : t3 = gen_avx2_interleave_highv4di (d->target, t1, t2);
22808 : : else
22809 : 0 : t3 = gen_avx2_interleave_lowv4di (d->target, t1, t2);
22810 : 0 : emit_insn (t3);
22811 : 0 : break;
22812 : :
22813 : 240 : case E_V8SImode:
22814 : 240 : if (!TARGET_AVX2)
22815 : : {
22816 : 164 : struct expand_vec_perm_d d_copy = *d;
22817 : 164 : d_copy.vmode = V8SFmode;
22818 : 164 : if (d->testing_p)
22819 : 164 : d_copy.target = gen_raw_REG (V8SFmode, LAST_VIRTUAL_REGISTER + 1);
22820 : : else
22821 : 0 : d_copy.target = gen_reg_rtx (V8SFmode);
22822 : 164 : d_copy.op0 = gen_lowpart (V8SFmode, d->op0);
22823 : 164 : d_copy.op1 = gen_lowpart (V8SFmode, d->op1);
22824 : 164 : if (expand_vec_perm_even_odd_1 (&d_copy, odd))
22825 : : {
22826 : 164 : if (!d->testing_p)
22827 : 0 : emit_move_insn (d->target,
22828 : 0 : gen_lowpart (V8SImode, d_copy.target));
22829 : 164 : return true;
22830 : : }
22831 : : return false;
22832 : : }
22833 : :
22834 : 76 : if (d->testing_p)
22835 : : break;
22836 : :
22837 : 76 : t1 = gen_reg_rtx (V8SImode);
22838 : 76 : t2 = gen_reg_rtx (V8SImode);
22839 : 76 : t3 = gen_reg_rtx (V4DImode);
22840 : 76 : t4 = gen_reg_rtx (V4DImode);
22841 : 76 : t5 = gen_reg_rtx (V4DImode);
22842 : :
22843 : : /* Shuffle the lanes around into
22844 : : { 0 1 2 3 8 9 a b } and { 4 5 6 7 c d e f }. */
22845 : 152 : emit_insn (gen_avx2_permv2ti (t3, gen_lowpart (V4DImode, d->op0),
22846 : 76 : gen_lowpart (V4DImode, d->op1),
22847 : : GEN_INT (0x20)));
22848 : 152 : emit_insn (gen_avx2_permv2ti (t4, gen_lowpart (V4DImode, d->op0),
22849 : 76 : gen_lowpart (V4DImode, d->op1),
22850 : : GEN_INT (0x31)));
22851 : :
22852 : : /* Swap the 2nd and 3rd position in each lane into
22853 : : { 0 2 1 3 8 a 9 b } and { 4 6 5 7 c e d f }. */
22854 : 76 : emit_insn (gen_avx2_pshufdv3 (t1, gen_lowpart (V8SImode, t3),
22855 : : GEN_INT (2 * 4 + 1 * 16 + 3 * 64)));
22856 : 76 : emit_insn (gen_avx2_pshufdv3 (t2, gen_lowpart (V8SImode, t4),
22857 : : GEN_INT (2 * 4 + 1 * 16 + 3 * 64)));
22858 : :
22859 : : /* Now an vpunpck[lh]qdq will produce
22860 : : { 0 2 4 6 8 a c e } resp. { 1 3 5 7 9 b d f }. */
22861 : 76 : if (odd)
22862 : 0 : t3 = gen_avx2_interleave_highv4di (t5, gen_lowpart (V4DImode, t1),
22863 : 0 : gen_lowpart (V4DImode, t2));
22864 : : else
22865 : 76 : t3 = gen_avx2_interleave_lowv4di (t5, gen_lowpart (V4DImode, t1),
22866 : 76 : gen_lowpart (V4DImode, t2));
22867 : 76 : emit_insn (t3);
22868 : 76 : emit_move_insn (d->target, gen_lowpart (V8SImode, t5));
22869 : 76 : break;
22870 : :
22871 : 0 : default:
22872 : 0 : gcc_unreachable ();
22873 : : }
22874 : :
22875 : : return true;
22876 : : }
22877 : :
22878 : : /* A subroutine of ix86_expand_vec_perm_const_1. Pattern match
22879 : : extract-even and extract-odd permutations. */
22880 : :
22881 : : static bool
22882 : 25361 : expand_vec_perm_even_odd (struct expand_vec_perm_d *d)
22883 : : {
22884 : 25361 : unsigned i, odd, nelt = d->nelt;
22885 : :
22886 : 25361 : odd = d->perm[0];
22887 : 25361 : if (odd != 0 && odd != 1)
22888 : : return false;
22889 : :
22890 : 70805 : for (i = 1; i < nelt; ++i)
22891 : 62825 : if (d->perm[i] != 2 * i + odd)
22892 : : return false;
22893 : :
22894 : 7980 : if (d->vmode == E_V32HImode
22895 : 12 : && d->testing_p
22896 : 12 : && !TARGET_AVX512BW)
22897 : : return false;
22898 : :
22899 : 7968 : return expand_vec_perm_even_odd_1 (d, odd);
22900 : : }
22901 : :
22902 : : /* A subroutine of ix86_expand_vec_perm_const_1. Implement broadcast
22903 : : permutations. We assume that expand_vec_perm_1 has already failed. */
22904 : :
22905 : : static bool
22906 : 738 : expand_vec_perm_broadcast_1 (struct expand_vec_perm_d *d)
22907 : : {
22908 : 738 : unsigned elt = d->perm[0], nelt2 = d->nelt / 2;
22909 : 738 : machine_mode vmode = d->vmode;
22910 : 738 : rtx (*gen) (rtx, rtx, rtx);
22911 : 738 : unsigned char perm2[4];
22912 : 738 : rtx op0 = d->op0, dest;
22913 : 738 : bool ok;
22914 : :
22915 : 738 : switch (vmode)
22916 : : {
22917 : 0 : case E_V4DFmode:
22918 : 0 : case E_V8SFmode:
22919 : : /* These are special-cased in sse.md so that we can optionally
22920 : : use the vbroadcast instruction. They expand to two insns
22921 : : if the input happens to be in a register. */
22922 : 0 : gcc_unreachable ();
22923 : :
22924 : 0 : case E_V2DFmode:
22925 : 0 : case E_V2SFmode:
22926 : 0 : case E_V4SFmode:
22927 : 0 : case E_V2DImode:
22928 : 0 : case E_V2SImode:
22929 : 0 : case E_V4SImode:
22930 : 0 : case E_V2HImode:
22931 : 0 : case E_V4HImode:
22932 : : /* These are always implementable using standard shuffle patterns. */
22933 : 0 : gcc_unreachable ();
22934 : :
22935 : 16 : case E_V4QImode:
22936 : : /* This can be implemented via interleave and pshuflw. */
22937 : 16 : if (d->testing_p)
22938 : : return true;
22939 : :
22940 : 8 : if (elt >= nelt2)
22941 : : {
22942 : 4 : gen = gen_mmx_punpckhbw_low;
22943 : 4 : elt -= nelt2;
22944 : : }
22945 : : else
22946 : : gen = gen_mmx_punpcklbw_low;
22947 : :
22948 : 8 : dest = gen_reg_rtx (vmode);
22949 : 8 : emit_insn (gen (dest, op0, op0));
22950 : 8 : vmode = get_mode_wider_vector (vmode);
22951 : 8 : op0 = gen_lowpart (vmode, dest);
22952 : :
22953 : 8 : memset (perm2, elt, 2);
22954 : 8 : dest = gen_reg_rtx (vmode);
22955 : 8 : ok = expand_vselect (dest, op0, perm2, 2, d->testing_p);
22956 : 8 : gcc_assert (ok);
22957 : :
22958 : 8 : emit_move_insn (d->target, gen_lowpart (d->vmode, dest));
22959 : 8 : return true;
22960 : :
22961 : 4 : case E_V8QImode:
22962 : : /* This can be implemented via interleave. We save one insn by
22963 : : stopping once we have promoted to V2SImode and then use pshufd. */
22964 : 4 : if (d->testing_p)
22965 : : return true;
22966 : 4 : do
22967 : : {
22968 : 4 : if (elt >= nelt2)
22969 : : {
22970 : 1 : gen = vmode == V8QImode ? gen_mmx_punpckhbw
22971 : : : gen_mmx_punpckhwd;
22972 : 1 : elt -= nelt2;
22973 : : }
22974 : : else
22975 : 3 : gen = vmode == V8QImode ? gen_mmx_punpcklbw
22976 : : : gen_mmx_punpcklwd;
22977 : 4 : nelt2 /= 2;
22978 : :
22979 : 4 : dest = gen_reg_rtx (vmode);
22980 : 4 : emit_insn (gen (dest, op0, op0));
22981 : 4 : vmode = get_mode_wider_vector (vmode);
22982 : 4 : op0 = gen_lowpart (vmode, dest);
22983 : : }
22984 : 4 : while (vmode != V2SImode);
22985 : :
22986 : 2 : memset (perm2, elt, 2);
22987 : 2 : dest = gen_reg_rtx (vmode);
22988 : 2 : ok = expand_vselect (dest, op0, perm2, 2, d->testing_p);
22989 : 2 : gcc_assert (ok);
22990 : :
22991 : 2 : emit_move_insn (d->target, gen_lowpart (d->vmode, dest));
22992 : 2 : return true;
22993 : :
22994 : 688 : case E_V8HImode:
22995 : 688 : case E_V16QImode:
22996 : : /* These can be implemented via interleave. We save one insn by
22997 : : stopping once we have promoted to V4SImode and then use pshufd. */
22998 : 688 : if (d->testing_p)
22999 : : return true;
23000 : 985 : do
23001 : : {
23002 : 985 : if (elt >= nelt2)
23003 : : {
23004 : 16 : gen = vmode == V16QImode ? gen_vec_interleave_highv16qi
23005 : : : gen_vec_interleave_highv8hi;
23006 : 16 : elt -= nelt2;
23007 : : }
23008 : : else
23009 : 969 : gen = vmode == V16QImode ? gen_vec_interleave_lowv16qi
23010 : : : gen_vec_interleave_lowv8hi;
23011 : 985 : nelt2 /= 2;
23012 : :
23013 : 985 : dest = gen_reg_rtx (vmode);
23014 : 985 : emit_insn (gen (dest, op0, op0));
23015 : 985 : vmode = get_mode_wider_vector (vmode);
23016 : 985 : op0 = gen_lowpart (vmode, dest);
23017 : : }
23018 : 985 : while (vmode != V4SImode);
23019 : :
23020 : 624 : memset (perm2, elt, 4);
23021 : 624 : dest = gen_reg_rtx (vmode);
23022 : 624 : ok = expand_vselect (dest, op0, perm2, 4, d->testing_p);
23023 : 624 : gcc_assert (ok);
23024 : :
23025 : 624 : emit_move_insn (d->target, gen_lowpart (d->vmode, dest));
23026 : 624 : return true;
23027 : :
23028 : 1 : case E_V8HFmode:
23029 : 1 : case E_V8BFmode:
23030 : : /* This can be implemented via interleave and pshufd. */
23031 : 1 : if (d->testing_p)
23032 : : return true;
23033 : :
23034 : 1 : rtx (*gen_interleave) (machine_mode, int, rtx, rtx, rtx);
23035 : 1 : if (elt >= nelt2)
23036 : : {
23037 : 0 : gen_interleave = gen_vec_interleave_high;
23038 : 0 : elt -= nelt2;
23039 : : }
23040 : : else
23041 : : gen_interleave = gen_vec_interleave_low;
23042 : 1 : nelt2 /= 2;
23043 : :
23044 : 1 : dest = gen_reg_rtx (vmode);
23045 : 1 : emit_insn (gen_interleave (vmode, 1, dest, op0, op0));
23046 : :
23047 : 1 : vmode = V4SImode;
23048 : 1 : op0 = gen_lowpart (vmode, dest);
23049 : :
23050 : 1 : memset (perm2, elt, 4);
23051 : 1 : dest = gen_reg_rtx (vmode);
23052 : 1 : ok = expand_vselect (dest, op0, perm2, 4, d->testing_p);
23053 : 1 : gcc_assert (ok);
23054 : :
23055 : 1 : emit_move_insn (d->target, gen_lowpart (d->vmode, dest));
23056 : 1 : return true;
23057 : :
23058 : 21 : case E_V32QImode:
23059 : 21 : case E_V16HImode:
23060 : 21 : case E_V8SImode:
23061 : 21 : case E_V4DImode:
23062 : : /* For AVX2 broadcasts of the first element vpbroadcast* or
23063 : : vpermq should be used by expand_vec_perm_1. */
23064 : 21 : gcc_assert (!TARGET_AVX2 || d->perm[0]);
23065 : : return false;
23066 : :
23067 : 6 : case E_V64QImode:
23068 : 6 : gcc_assert (!TARGET_AVX512BW || d->perm[0]);
23069 : : return false;
23070 : :
23071 : 2 : case E_V32HImode:
23072 : 2 : gcc_assert (!TARGET_AVX512BW);
23073 : : return false;
23074 : :
23075 : 0 : default:
23076 : 0 : gcc_unreachable ();
23077 : : }
23078 : : }
23079 : :
23080 : : /* A subroutine of ix86_expand_vec_perm_const_1. Pattern match
23081 : : broadcast permutations. */
23082 : :
23083 : : static bool
23084 : 102844 : expand_vec_perm_broadcast (struct expand_vec_perm_d *d)
23085 : : {
23086 : 102844 : unsigned i, elt, nelt = d->nelt;
23087 : :
23088 : 102844 : if (!d->one_operand_p)
23089 : : return false;
23090 : :
23091 : 4430 : elt = d->perm[0];
23092 : 7923 : for (i = 1; i < nelt; ++i)
23093 : 7794 : if (d->perm[i] != elt)
23094 : : return false;
23095 : :
23096 : 129 : return expand_vec_perm_broadcast_1 (d);
23097 : : }
23098 : :
23099 : : /* Implement arbitrary permutations of two V64QImode operands
23100 : : with 2 vperm[it]2w, 2 vpshufb and one vpor instruction. */
23101 : : static bool
23102 : 25401 : expand_vec_perm_vpermt2_vpshub2 (struct expand_vec_perm_d *d)
23103 : : {
23104 : 25401 : if (!TARGET_AVX512BW || !(d->vmode == V64QImode))
23105 : : return false;
23106 : :
23107 : 40 : if (d->testing_p)
23108 : : return true;
23109 : :
23110 : 40 : struct expand_vec_perm_d ds[2];
23111 : 40 : rtx rperm[128], vperm, target0, target1;
23112 : 40 : unsigned int i, nelt;
23113 : 40 : machine_mode vmode;
23114 : :
23115 : 40 : nelt = d->nelt;
23116 : 40 : vmode = V64QImode;
23117 : :
23118 : 120 : for (i = 0; i < 2; i++)
23119 : : {
23120 : 80 : ds[i] = *d;
23121 : 80 : ds[i].vmode = V32HImode;
23122 : 80 : ds[i].nelt = 32;
23123 : 80 : ds[i].target = gen_reg_rtx (V32HImode);
23124 : 80 : ds[i].op0 = gen_lowpart (V32HImode, d->op0);
23125 : 80 : ds[i].op1 = gen_lowpart (V32HImode, d->op1);
23126 : : }
23127 : :
23128 : : /* Prepare permutations such that the first one takes care of
23129 : : putting the even bytes into the right positions or one higher
23130 : : positions (ds[0]) and the second one takes care of
23131 : : putting the odd bytes into the right positions or one below
23132 : : (ds[1]). */
23133 : :
23134 : 2600 : for (i = 0; i < nelt; i++)
23135 : : {
23136 : 2560 : ds[i & 1].perm[i / 2] = d->perm[i] / 2;
23137 : 2560 : if (i & 1)
23138 : : {
23139 : 1280 : rperm[i] = constm1_rtx;
23140 : 1280 : rperm[i + 64] = GEN_INT ((i & 14) + (d->perm[i] & 1));
23141 : : }
23142 : : else
23143 : : {
23144 : 1280 : rperm[i] = GEN_INT ((i & 14) + (d->perm[i] & 1));
23145 : 1280 : rperm[i + 64] = constm1_rtx;
23146 : : }
23147 : : }
23148 : :
23149 : 40 : bool ok = expand_vec_perm_1 (&ds[0]);
23150 : 40 : gcc_assert (ok);
23151 : 40 : ds[0].target = gen_lowpart (V64QImode, ds[0].target);
23152 : :
23153 : 40 : ok = expand_vec_perm_1 (&ds[1]);
23154 : 40 : gcc_assert (ok);
23155 : 40 : ds[1].target = gen_lowpart (V64QImode, ds[1].target);
23156 : :
23157 : 40 : vperm = gen_rtx_CONST_VECTOR (V64QImode, gen_rtvec_v (64, rperm));
23158 : 40 : vperm = force_reg (vmode, vperm);
23159 : 40 : target0 = gen_reg_rtx (V64QImode);
23160 : 40 : emit_insn (gen_avx512bw_pshufbv64qi3 (target0, ds[0].target, vperm));
23161 : :
23162 : 40 : vperm = gen_rtx_CONST_VECTOR (V64QImode, gen_rtvec_v (64, rperm + 64));
23163 : 40 : vperm = force_reg (vmode, vperm);
23164 : 40 : target1 = gen_reg_rtx (V64QImode);
23165 : 40 : emit_insn (gen_avx512bw_pshufbv64qi3 (target1, ds[1].target, vperm));
23166 : :
23167 : 40 : emit_insn (gen_iorv64qi3 (d->target, target0, target1));
23168 : 40 : return true;
23169 : : }
23170 : :
23171 : : /* Implement arbitrary permutation of two V32QImode and V16QImode operands
23172 : : with 4 vpshufb insns, 2 vpermq and 3 vpor. We should have already failed
23173 : : all the shorter instruction sequences. */
23174 : :
23175 : : static bool
23176 : 17114 : expand_vec_perm_vpshufb4_vpermq2 (struct expand_vec_perm_d *d)
23177 : : {
23178 : 17114 : rtx rperm[4][32], vperm, l[2], h[2], op, m128;
23179 : 17114 : unsigned int i, nelt, eltsz;
23180 : 17114 : bool used[4];
23181 : :
23182 : 17114 : if (!TARGET_AVX2
23183 : 660 : || d->one_operand_p
23184 : 531 : || (d->vmode != V32QImode && d->vmode != V16HImode))
23185 : : return false;
23186 : :
23187 : 406 : if (d->testing_p)
23188 : : return true;
23189 : :
23190 : 406 : nelt = d->nelt;
23191 : 406 : eltsz = GET_MODE_UNIT_SIZE (d->vmode);
23192 : :
23193 : : /* Generate 4 permutation masks. If the required element is within
23194 : : the same lane, it is shuffled in. If the required element from the
23195 : : other lane, force a zero by setting bit 7 in the permutation mask.
23196 : : In the other mask the mask has non-negative elements if element
23197 : : is requested from the other lane, but also moved to the other lane,
23198 : : so that the result of vpshufb can have the two V2TImode halves
23199 : : swapped. */
23200 : 406 : m128 = GEN_INT (-128);
23201 : 13804 : for (i = 0; i < 32; ++i)
23202 : : {
23203 : 12992 : rperm[0][i] = m128;
23204 : 12992 : rperm[1][i] = m128;
23205 : 12992 : rperm[2][i] = m128;
23206 : 12992 : rperm[3][i] = m128;
23207 : : }
23208 : 406 : used[0] = false;
23209 : 406 : used[1] = false;
23210 : 406 : used[2] = false;
23211 : 406 : used[3] = false;
23212 : 11158 : for (i = 0; i < nelt; ++i)
23213 : : {
23214 : 10752 : unsigned j, e = d->perm[i] & (nelt / 2 - 1);
23215 : 10752 : unsigned xlane = ((d->perm[i] ^ i) & (nelt / 2)) * eltsz;
23216 : 11162 : unsigned int which = ((d->perm[i] & nelt) ? 2 : 0) + (xlane ? 1 : 0);
23217 : :
23218 : 23744 : for (j = 0; j < eltsz; ++j)
23219 : 12992 : rperm[which][(i * eltsz + j) ^ xlane] = GEN_INT (e * eltsz + j);
23220 : 10752 : used[which] = true;
23221 : : }
23222 : :
23223 : 1218 : for (i = 0; i < 2; ++i)
23224 : : {
23225 : 812 : if (!used[2 * i + 1])
23226 : : {
23227 : 22 : h[i] = NULL_RTX;
23228 : 22 : continue;
23229 : : }
23230 : 790 : vperm = gen_rtx_CONST_VECTOR (V32QImode,
23231 : 790 : gen_rtvec_v (32, rperm[2 * i + 1]));
23232 : 790 : vperm = force_reg (V32QImode, vperm);
23233 : 790 : h[i] = gen_reg_rtx (V32QImode);
23234 : 790 : op = gen_lowpart (V32QImode, i ? d->op1 : d->op0);
23235 : 790 : emit_insn (gen_avx2_pshufbv32qi3 (h[i], op, vperm));
23236 : : }
23237 : :
23238 : : /* Swap the 128-byte lanes of h[X]. */
23239 : 1218 : for (i = 0; i < 2; ++i)
23240 : : {
23241 : 812 : if (h[i] == NULL_RTX)
23242 : 22 : continue;
23243 : 790 : op = gen_reg_rtx (V4DImode);
23244 : 790 : emit_insn (gen_avx2_permv4di_1 (op, gen_lowpart (V4DImode, h[i]),
23245 : : const2_rtx, GEN_INT (3), const0_rtx,
23246 : : const1_rtx));
23247 : 790 : h[i] = gen_lowpart (V32QImode, op);
23248 : : }
23249 : :
23250 : 1218 : for (i = 0; i < 2; ++i)
23251 : : {
23252 : 812 : if (!used[2 * i])
23253 : : {
23254 : 384 : l[i] = NULL_RTX;
23255 : 384 : continue;
23256 : : }
23257 : 428 : vperm = gen_rtx_CONST_VECTOR (V32QImode, gen_rtvec_v (32, rperm[2 * i]));
23258 : 428 : vperm = force_reg (V32QImode, vperm);
23259 : 428 : l[i] = gen_reg_rtx (V32QImode);
23260 : 428 : op = gen_lowpart (V32QImode, i ? d->op1 : d->op0);
23261 : 428 : emit_insn (gen_avx2_pshufbv32qi3 (l[i], op, vperm));
23262 : : }
23263 : :
23264 : 1218 : for (i = 0; i < 2; ++i)
23265 : : {
23266 : 812 : if (h[i] && l[i])
23267 : : {
23268 : 406 : op = gen_reg_rtx (V32QImode);
23269 : 406 : emit_insn (gen_iorv32qi3 (op, l[i], h[i]));
23270 : 406 : l[i] = op;
23271 : : }
23272 : 406 : else if (h[i])
23273 : 384 : l[i] = h[i];
23274 : : }
23275 : :
23276 : 406 : gcc_assert (l[0] && l[1]);
23277 : 406 : op = d->target;
23278 : 406 : if (d->vmode != V32QImode)
23279 : 140 : op = gen_reg_rtx (V32QImode);
23280 : 406 : emit_insn (gen_iorv32qi3 (op, l[0], l[1]));
23281 : 406 : if (op != d->target)
23282 : 140 : emit_move_insn (d->target, gen_lowpart (d->vmode, op));
23283 : : return true;
23284 : : }
23285 : :
23286 : : /* The guts of ix86_vectorize_vec_perm_const. With all of the interface bits
23287 : : taken care of, perform the expansion in D and return true on success. */
23288 : :
23289 : : static bool
23290 : 222015 : ix86_expand_vec_perm_const_1 (struct expand_vec_perm_d *d)
23291 : : {
23292 : : /* Try a single instruction expansion. */
23293 : 222015 : if (expand_vec_perm_1 (d))
23294 : : return true;
23295 : :
23296 : : /* Try sequences of two instructions. */
23297 : :
23298 : 114337 : if (expand_vec_perm_pshuflw_pshufhw (d))
23299 : : return true;
23300 : :
23301 : 111169 : if (expand_vec_perm_palignr (d, false))
23302 : : return true;
23303 : :
23304 : 108031 : if (expand_vec_perm_interleave2 (d))
23305 : : return true;
23306 : :
23307 : 102844 : if (expand_vec_perm_broadcast (d))
23308 : : return true;
23309 : :
23310 : 102744 : if (expand_vec_perm_vpermq_perm_1 (d))
23311 : : return true;
23312 : :
23313 : 102744 : if (expand_vec_perm_vperm2f128 (d))
23314 : : return true;
23315 : :
23316 : 102690 : if (expand_vec_perm_pblendv (d))
23317 : : return true;
23318 : :
23319 : 101677 : if (expand_vec_perm_2perm_interleave (d, true))
23320 : : return true;
23321 : :
23322 : 101497 : if (expand_vec_perm_2perm_pblendv (d, true))
23323 : : return true;
23324 : :
23325 : 100167 : if (expand_vec_perm_shufps_shufps (d))
23326 : : return true;
23327 : :
23328 : : /* Try sequences of three instructions. */
23329 : :
23330 : 42051 : if (expand_vec_perm_even_odd_pack (d))
23331 : : return true;
23332 : :
23333 : 30747 : if (expand_vec_perm_2vperm2f128_vshuf (d))
23334 : : return true;
23335 : :
23336 : 29266 : if (expand_vec_perm_pshufb2 (d))
23337 : : return true;
23338 : :
23339 : 26753 : if (expand_vec_perm_pslldq_psrldq_por (d, false))
23340 : : return true;
23341 : :
23342 : 26573 : if (expand_vec_perm_interleave3 (d))
23343 : : return true;
23344 : :
23345 : 26543 : if (expand_vec_perm_vperm2f128_vblend (d))
23346 : : return true;
23347 : :
23348 : 26543 : if (expand_vec_perm_2perm_interleave (d, false))
23349 : : return true;
23350 : :
23351 : 26503 : if (expand_vec_perm_2perm_pblendv (d, false))
23352 : : return true;
23353 : :
23354 : : /* Try sequences of four instructions. */
23355 : :
23356 : 25404 : if (expand_vec_perm_even_odd_trunc (d))
23357 : : return true;
23358 : 25401 : if (expand_vec_perm_vpshufb2_vpermq (d))
23359 : : return true;
23360 : :
23361 : 25401 : if (expand_vec_perm_vpshufb2_vpermq_even_odd (d))
23362 : : return true;
23363 : :
23364 : 25401 : if (expand_vec_perm_vpermt2_vpshub2 (d))
23365 : : return true;
23366 : :
23367 : : /* ??? Look for narrow permutations whose element orderings would
23368 : : allow the promotion to a wider mode. */
23369 : :
23370 : : /* ??? Look for sequences of interleave or a wider permute that place
23371 : : the data into the correct lanes for a half-vector shuffle like
23372 : : pshuf[lh]w or vpermilps. */
23373 : :
23374 : : /* ??? Look for sequences of interleave that produce the desired results.
23375 : : The combinatorics of punpck[lh] get pretty ugly... */
23376 : :
23377 : 25361 : if (expand_vec_perm_even_odd (d))
23378 : : return true;
23379 : :
23380 : : /* Generate four or five instructions. */
23381 : 17450 : if (expand_vec_perm_pslldq_psrldq_por (d, true))
23382 : : return true;
23383 : :
23384 : : /* Even longer sequences. */
23385 : 17114 : if (expand_vec_perm_vpshufb4_vpermq2 (d))
23386 : : return true;
23387 : :
23388 : : /* See if we can get the same permutation in different vector integer
23389 : : mode. */
23390 : 16708 : struct expand_vec_perm_d nd;
23391 : 16708 : if (canonicalize_vector_int_perm (d, &nd) && expand_vec_perm_1 (&nd))
23392 : : {
23393 : 0 : if (!d->testing_p)
23394 : 0 : emit_move_insn (d->target, gen_lowpart (d->vmode, nd.target));
23395 : 0 : return true;
23396 : : }
23397 : :
23398 : : /* Even longer, including recursion to ix86_expand_vec_perm_const_1. */
23399 : 16708 : if (expand_vec_perm2_vperm2f128_vblend (d))
23400 : : return true;
23401 : :
23402 : : return false;
23403 : : }
23404 : :
23405 : : /* If a permutation only uses one operand, make it clear. Returns true
23406 : : if the permutation references both operands. */
23407 : :
23408 : : static bool
23409 : 57425 : canonicalize_perm (struct expand_vec_perm_d *d)
23410 : : {
23411 : 57425 : int i, which, nelt = d->nelt;
23412 : :
23413 : 385927 : for (i = which = 0; i < nelt; ++i)
23414 : 459040 : which |= (d->perm[i] < nelt ? 1 : 2);
23415 : :
23416 : 57425 : d->one_operand_p = true;
23417 : 57425 : switch (which)
23418 : : {
23419 : 0 : default:
23420 : 0 : gcc_unreachable();
23421 : :
23422 : 40537 : case 3:
23423 : 40537 : if (!rtx_equal_p (d->op0, d->op1))
23424 : : {
23425 : 40494 : d->one_operand_p = false;
23426 : 40494 : break;
23427 : : }
23428 : : /* The elements of PERM do not suggest that only the first operand
23429 : : is used, but both operands are identical. Allow easier matching
23430 : : of the permutation by folding the permutation into the single
23431 : : input vector. */
23432 : : /* FALLTHRU */
23433 : :
23434 : : case 2:
23435 : 3085 : for (i = 0; i < nelt; ++i)
23436 : 2720 : d->perm[i] &= nelt - 1;
23437 : 365 : d->op0 = d->op1;
23438 : 365 : break;
23439 : :
23440 : 16566 : case 1:
23441 : 16566 : d->op1 = d->op0;
23442 : 16566 : break;
23443 : : }
23444 : :
23445 : 57425 : return (which == 3);
23446 : : }
23447 : :
23448 : : /* Implement TARGET_VECTORIZE_VEC_PERM_CONST. */
23449 : :
23450 : : bool
23451 : 649409 : ix86_vectorize_vec_perm_const (machine_mode vmode, machine_mode op_mode,
23452 : : rtx target, rtx op0, rtx op1,
23453 : : const vec_perm_indices &sel)
23454 : : {
23455 : 649409 : if (vmode != op_mode)
23456 : : return false;
23457 : :
23458 : 646114 : struct expand_vec_perm_d d;
23459 : 646114 : unsigned char perm[MAX_VECT_LEN];
23460 : 646114 : unsigned int i, nelt, which;
23461 : 646114 : bool two_args;
23462 : :
23463 : 1292228 : if (GET_MODE_SIZE (vmode) == 64 && !TARGET_EVEX512)
23464 : : return false;
23465 : :
23466 : : /* For HF mode vector, convert it to HI using subreg. */
23467 : 1292228 : if (GET_MODE_INNER (vmode) == HFmode)
23468 : : {
23469 : 454 : machine_mode orig_mode = vmode;
23470 : 908 : vmode = mode_for_vector (HImode,
23471 : 908 : GET_MODE_NUNITS (vmode)).require ();
23472 : 454 : if (target)
23473 : 408 : target = lowpart_subreg (vmode, target, orig_mode);
23474 : 454 : if (op0)
23475 : 408 : op0 = lowpart_subreg (vmode, op0, orig_mode);
23476 : 454 : if (op1)
23477 : 408 : op1 = lowpart_subreg (vmode, op1, orig_mode);
23478 : : }
23479 : :
23480 : 646114 : d.target = target;
23481 : 646114 : d.op0 = op0;
23482 : 646114 : d.op1 = op1;
23483 : :
23484 : 646114 : d.vmode = vmode;
23485 : 646114 : gcc_assert (VECTOR_MODE_P (d.vmode));
23486 : 646114 : d.nelt = nelt = GET_MODE_NUNITS (d.vmode);
23487 : 646114 : d.testing_p = !target;
23488 : :
23489 : 646114 : gcc_assert (sel.length () == nelt);
23490 : 646114 : gcc_checking_assert (sizeof (d.perm) == sizeof (perm));
23491 : :
23492 : : /* Given sufficient ISA support we can just return true here
23493 : : for selected vector modes. */
23494 : 646114 : switch (d.vmode)
23495 : : {
23496 : 1294 : case E_V16SFmode:
23497 : 1294 : case E_V16SImode:
23498 : 1294 : case E_V8DImode:
23499 : 1294 : case E_V8DFmode:
23500 : 1294 : if (!TARGET_AVX512F)
23501 : : return false;
23502 : : /* All implementable with a single vperm[it]2 insn. */
23503 : 1294 : if (d.testing_p)
23504 : : return true;
23505 : : break;
23506 : 311 : case E_V32HImode:
23507 : 311 : if (!TARGET_AVX512F)
23508 : : return false;
23509 : 311 : if (d.testing_p && TARGET_AVX512BW)
23510 : : /* All implementable with a single vperm[it]2 insn. */
23511 : : return true;
23512 : : break;
23513 : 702 : case E_V64QImode:
23514 : 702 : if (!TARGET_AVX512F)
23515 : : return false;
23516 : 702 : if (d.testing_p && TARGET_AVX512BW)
23517 : : /* Implementable with 2 vperm[it]2, 2 vpshufb and 1 or insn. */
23518 : : return true;
23519 : : break;
23520 : 12821 : case E_V8SImode:
23521 : 12821 : case E_V8SFmode:
23522 : 12821 : case E_V4DFmode:
23523 : 12821 : case E_V4DImode:
23524 : 12821 : if (!TARGET_AVX)
23525 : : return false;
23526 : 12821 : if (d.testing_p && TARGET_AVX512VL)
23527 : : /* All implementable with a single vperm[it]2 insn. */
23528 : : return true;
23529 : : break;
23530 : 431 : case E_V16HImode:
23531 : 431 : if (!TARGET_SSE2)
23532 : : return false;
23533 : 431 : if (d.testing_p && TARGET_AVX2)
23534 : : /* Implementable with 4 vpshufb insns, 2 vpermq and 3 vpor insns. */
23535 : : return true;
23536 : : break;
23537 : 672 : case E_V32QImode:
23538 : 672 : if (!TARGET_SSE2)
23539 : : return false;
23540 : 672 : if (d.testing_p && TARGET_AVX2)
23541 : : /* Implementable with 4 vpshufb insns, 2 vpermq and 3 vpor insns. */
23542 : : return true;
23543 : : break;
23544 : 32805 : case E_V8HImode:
23545 : 32805 : case E_V16QImode:
23546 : 32805 : if (!TARGET_SSE2)
23547 : : return false;
23548 : : /* Fall through. */
23549 : 169669 : case E_V4SImode:
23550 : 169669 : case E_V4SFmode:
23551 : 169669 : if (!TARGET_SSE)
23552 : : return false;
23553 : : /* All implementable with a single vpperm insn. */
23554 : 169669 : if (d.testing_p && TARGET_XOP)
23555 : : return true;
23556 : : /* All implementable with 2 pshufb + 1 ior. */
23557 : 168819 : if (d.testing_p && TARGET_SSSE3)
23558 : : return true;
23559 : : break;
23560 : 111993 : case E_V2SFmode:
23561 : 111993 : case E_V2SImode:
23562 : 111993 : case E_V4HImode:
23563 : 111993 : case E_V8QImode:
23564 : 111993 : if (!TARGET_MMX_WITH_SSE)
23565 : : return false;
23566 : : break;
23567 : 9028 : case E_V2HImode:
23568 : 9028 : if (!TARGET_SSE2)
23569 : : return false;
23570 : : /* All implementable with *punpckwd. */
23571 : 9028 : if (d.testing_p)
23572 : : return true;
23573 : : break;
23574 : 7903 : case E_V4QImode:
23575 : 7903 : if (!TARGET_SSE2)
23576 : : return false;
23577 : : break;
23578 : 329490 : case E_V2DImode:
23579 : 329490 : case E_V2DFmode:
23580 : 329490 : if (!TARGET_SSE)
23581 : : return false;
23582 : : /* All implementable with shufpd or unpck[lh]pd. */
23583 : 329490 : if (d.testing_p)
23584 : : return true;
23585 : : break;
23586 : : default:
23587 : : return false;
23588 : : }
23589 : :
23590 : 1710457 : for (i = which = 0; i < nelt; ++i)
23591 : : {
23592 : 1403832 : unsigned char e = sel[i];
23593 : 1403832 : gcc_assert (e < 2 * nelt);
23594 : 1403832 : d.perm[i] = e;
23595 : 1403832 : perm[i] = e;
23596 : 1860020 : which |= (e < nelt ? 1 : 2);
23597 : : }
23598 : :
23599 : 306625 : if (d.testing_p)
23600 : : {
23601 : : /* For all elements from second vector, fold the elements to first. */
23602 : 250432 : if (which == 2)
23603 : 753 : for (i = 0; i < nelt; ++i)
23604 : 696 : d.perm[i] -= nelt;
23605 : :
23606 : : /* Check whether the mask can be applied to the vector type. */
23607 : 250432 : d.one_operand_p = (which != 3);
23608 : :
23609 : : /* Implementable with shufps, pshufd or pshuflw. */
23610 : 250432 : if (d.one_operand_p
23611 : : && (d.vmode == V4SFmode || d.vmode == V2SFmode
23612 : : || d.vmode == V4SImode || d.vmode == V2SImode
23613 : : || d.vmode == V4HImode || d.vmode == V2HImode))
23614 : : return true;
23615 : :
23616 : : /* Otherwise we have to go through the motions and see if we can
23617 : : figure out how to generate the requested permutation. */
23618 : 162107 : d.target = gen_raw_REG (d.vmode, LAST_VIRTUAL_REGISTER + 1);
23619 : 162107 : d.op1 = d.op0 = gen_raw_REG (d.vmode, LAST_VIRTUAL_REGISTER + 2);
23620 : 162107 : if (!d.one_operand_p)
23621 : 146862 : d.op1 = gen_raw_REG (d.vmode, LAST_VIRTUAL_REGISTER + 3);
23622 : :
23623 : 162107 : start_sequence ();
23624 : 162107 : bool ret = ix86_expand_vec_perm_const_1 (&d);
23625 : 162107 : end_sequence ();
23626 : :
23627 : 162107 : return ret;
23628 : : }
23629 : :
23630 : 56193 : two_args = canonicalize_perm (&d);
23631 : :
23632 : : /* If one of the operands is a zero vector, try to match pmovzx. */
23633 : 56193 : if (two_args && (d.op0 == CONST0_RTX (vmode) || d.op1 == CONST0_RTX (vmode)))
23634 : : {
23635 : 677 : struct expand_vec_perm_d dzero = d;
23636 : 677 : if (d.op0 == CONST0_RTX (vmode))
23637 : : {
23638 : 468 : d.op1 = dzero.op1 = force_reg (vmode, d.op1);
23639 : 468 : std::swap (dzero.op0, dzero.op1);
23640 : 8304 : for (i = 0; i < nelt; ++i)
23641 : 7368 : dzero.perm[i] ^= nelt;
23642 : : }
23643 : : else
23644 : 209 : d.op0 = dzero.op0 = force_reg (vmode, d.op0);
23645 : :
23646 : 677 : if (expand_vselect_vconcat (dzero.target, dzero.op0, dzero.op1,
23647 : 677 : dzero.perm, nelt, dzero.testing_p))
23648 : 110 : return true;
23649 : : }
23650 : :
23651 : : /* Force operands into registers. */
23652 : 56083 : rtx nop0 = force_reg (vmode, d.op0);
23653 : 56083 : if (d.op0 == d.op1)
23654 : 16602 : d.op1 = nop0;
23655 : 56083 : d.op0 = nop0;
23656 : 56083 : d.op1 = force_reg (vmode, d.op1);
23657 : :
23658 : 56083 : if (ix86_expand_vec_perm_const_1 (&d))
23659 : : return true;
23660 : :
23661 : : /* If the selector says both arguments are needed, but the operands are the
23662 : : same, the above tried to expand with one_operand_p and flattened selector.
23663 : : If that didn't work, retry without one_operand_p; we succeeded with that
23664 : : during testing. */
23665 : 14 : if (two_args && d.one_operand_p)
23666 : : {
23667 : 14 : d.one_operand_p = false;
23668 : 14 : memcpy (d.perm, perm, sizeof (perm));
23669 : 14 : return ix86_expand_vec_perm_const_1 (&d);
23670 : : }
23671 : :
23672 : : return false;
23673 : : }
23674 : :
23675 : : void
23676 : 6965 : ix86_expand_vec_extract_even_odd (rtx targ, rtx op0, rtx op1, unsigned odd)
23677 : : {
23678 : 6965 : struct expand_vec_perm_d d;
23679 : 6965 : unsigned i, nelt;
23680 : :
23681 : 6965 : d.target = targ;
23682 : 6965 : d.op0 = op0;
23683 : 6965 : d.op1 = op1;
23684 : 6965 : d.vmode = GET_MODE (targ);
23685 : 6965 : d.nelt = nelt = GET_MODE_NUNITS (d.vmode);
23686 : 6965 : d.one_operand_p = false;
23687 : 6965 : d.testing_p = false;
23688 : :
23689 : 64549 : for (i = 0; i < nelt; ++i)
23690 : 57584 : d.perm[i] = i * 2 + odd;
23691 : :
23692 : : /* We'll either be able to implement the permutation directly... */
23693 : 6965 : if (expand_vec_perm_1 (&d))
23694 : 2934 : return;
23695 : :
23696 : : /* ... or we use the special-case patterns. */
23697 : 4031 : expand_vec_perm_even_odd_1 (&d, odd);
23698 : : }
23699 : :
23700 : : static void
23701 : 932 : ix86_expand_vec_interleave (rtx targ, rtx op0, rtx op1, bool high_p)
23702 : : {
23703 : 932 : struct expand_vec_perm_d d;
23704 : 932 : unsigned i, nelt, base;
23705 : 932 : bool ok;
23706 : :
23707 : 932 : d.target = targ;
23708 : 932 : d.op0 = op0;
23709 : 932 : d.op1 = op1;
23710 : 932 : d.vmode = GET_MODE (targ);
23711 : 932 : d.nelt = nelt = GET_MODE_NUNITS (d.vmode);
23712 : 932 : d.one_operand_p = false;
23713 : 932 : d.testing_p = false;
23714 : :
23715 : 932 : base = high_p ? nelt / 2 : 0;
23716 : 3564 : for (i = 0; i < nelt / 2; ++i)
23717 : : {
23718 : 2632 : d.perm[i * 2] = i + base;
23719 : 2632 : d.perm[i * 2 + 1] = i + base + nelt;
23720 : : }
23721 : :
23722 : : /* Note that for AVX this isn't one instruction. */
23723 : 932 : ok = ix86_expand_vec_perm_const_1 (&d);
23724 : 932 : gcc_assert (ok);
23725 : 932 : }
23726 : :
23727 : : /* Expand a vector operation shift by constant for a V*QImode in terms of the
23728 : : same operation on V*HImode. Return true if success. */
23729 : : static bool
23730 : 304 : ix86_expand_vec_shift_qihi_constant (enum rtx_code code,
23731 : : rtx dest, rtx op1, rtx op2)
23732 : : {
23733 : 304 : machine_mode qimode, himode;
23734 : 304 : HOST_WIDE_INT and_constant, xor_constant;
23735 : 304 : HOST_WIDE_INT shift_amount;
23736 : 304 : rtx vec_const_and, vec_const_xor;
23737 : 304 : rtx tmp, op1_subreg;
23738 : 304 : rtx (*gen_shift) (rtx, rtx, rtx);
23739 : 304 : rtx (*gen_and) (rtx, rtx, rtx);
23740 : 304 : rtx (*gen_xor) (rtx, rtx, rtx);
23741 : 304 : rtx (*gen_sub) (rtx, rtx, rtx);
23742 : :
23743 : : /* Only optimize shift by constant. */
23744 : 304 : if (!CONST_INT_P (op2))
23745 : : return false;
23746 : :
23747 : 304 : qimode = GET_MODE (dest);
23748 : 304 : shift_amount = INTVAL (op2);
23749 : : /* Do nothing when shift amount greater equal 8. */
23750 : 304 : if (shift_amount > 7)
23751 : : return false;
23752 : :
23753 : 304 : gcc_assert (code == ASHIFT || code == ASHIFTRT || code == LSHIFTRT);
23754 : : /* Record sign bit. */
23755 : 304 : xor_constant = 1 << (8 - shift_amount - 1);
23756 : :
23757 : : /* Zero upper/lower bits shift from left/right element. */
23758 : 304 : and_constant
23759 : 304 : = (code == ASHIFT ? 256 - (1 << shift_amount)
23760 : 289 : : (1 << (8 - shift_amount)) - 1);
23761 : :
23762 : 304 : switch (qimode)
23763 : : {
23764 : 294 : case V16QImode:
23765 : 294 : himode = V8HImode;
23766 : 294 : gen_shift =
23767 : : ((code == ASHIFT)
23768 : 294 : ? gen_ashlv8hi3
23769 : 285 : : (code == ASHIFTRT) ? gen_ashrv8hi3 : gen_lshrv8hi3);
23770 : : gen_and = gen_andv16qi3;
23771 : : gen_xor = gen_xorv16qi3;
23772 : : gen_sub = gen_subv16qi3;
23773 : : break;
23774 : 3 : case V32QImode:
23775 : 3 : himode = V16HImode;
23776 : 3 : gen_shift =
23777 : : ((code == ASHIFT)
23778 : 3 : ? gen_ashlv16hi3
23779 : 2 : : (code == ASHIFTRT) ? gen_ashrv16hi3 : gen_lshrv16hi3);
23780 : : gen_and = gen_andv32qi3;
23781 : : gen_xor = gen_xorv32qi3;
23782 : : gen_sub = gen_subv32qi3;
23783 : : break;
23784 : 7 : case V64QImode:
23785 : 7 : himode = V32HImode;
23786 : 7 : gen_shift =
23787 : : ((code == ASHIFT)
23788 : 7 : ? gen_ashlv32hi3
23789 : 2 : : (code == ASHIFTRT) ? gen_ashrv32hi3 : gen_lshrv32hi3);
23790 : : gen_and = gen_andv64qi3;
23791 : : gen_xor = gen_xorv64qi3;
23792 : : gen_sub = gen_subv64qi3;
23793 : : break;
23794 : 0 : default:
23795 : 0 : gcc_unreachable ();
23796 : : }
23797 : :
23798 : 304 : tmp = gen_reg_rtx (himode);
23799 : 304 : vec_const_and = gen_reg_rtx (qimode);
23800 : 304 : op1_subreg = lowpart_subreg (himode, op1, qimode);
23801 : :
23802 : : /* For ASHIFT and LSHIFTRT, perform operation like
23803 : : vpsllw/vpsrlw $shift_amount, %op1, %dest.
23804 : : vpand %vec_const_and, %dest. */
23805 : 304 : emit_insn (gen_shift (tmp, op1_subreg, op2));
23806 : 304 : emit_move_insn (dest, simplify_gen_subreg (qimode, tmp, himode, 0));
23807 : 304 : emit_move_insn (vec_const_and,
23808 : : ix86_build_const_vector (qimode, true,
23809 : : gen_int_mode (and_constant, QImode)));
23810 : 304 : emit_insn (gen_and (dest, dest, vec_const_and));
23811 : :
23812 : : /* For ASHIFTRT, perform extra operation like
23813 : : vpxor %vec_const_xor, %dest, %dest
23814 : : vpsubb %vec_const_xor, %dest, %dest */
23815 : 304 : if (code == ASHIFTRT)
23816 : : {
23817 : 36 : vec_const_xor = gen_reg_rtx (qimode);
23818 : 36 : emit_move_insn (vec_const_xor,
23819 : : ix86_build_const_vector (qimode, true,
23820 : : gen_int_mode (xor_constant, QImode)));
23821 : 36 : emit_insn (gen_xor (dest, dest, vec_const_xor));
23822 : 36 : emit_insn (gen_sub (dest, dest, vec_const_xor));
23823 : : }
23824 : : return true;
23825 : : }
23826 : :
23827 : : void
23828 : 996 : ix86_expand_vecop_qihi_partial (enum rtx_code code, rtx dest, rtx op1, rtx op2)
23829 : : {
23830 : 996 : machine_mode qimode = GET_MODE (dest);
23831 : 996 : rtx qop1, qop2, hop1, hop2, qdest, hdest;
23832 : 996 : bool op2vec = GET_MODE_CLASS (GET_MODE (op2)) == MODE_VECTOR_INT;
23833 : 996 : bool uns_p = code != ASHIFTRT;
23834 : :
23835 : 996 : switch (qimode)
23836 : : {
23837 : 996 : case E_V4QImode:
23838 : 996 : case E_V8QImode:
23839 : 996 : break;
23840 : 0 : default:
23841 : 0 : gcc_unreachable ();
23842 : : }
23843 : :
23844 : 996 : qop1 = lowpart_subreg (V16QImode, force_reg (qimode, op1), qimode);
23845 : :
23846 : 996 : if (op2vec)
23847 : 964 : qop2 = lowpart_subreg (V16QImode, force_reg (qimode, op2), qimode);
23848 : : else
23849 : : qop2 = op2;
23850 : :
23851 : 996 : qdest = gen_reg_rtx (V16QImode);
23852 : :
23853 : 996 : if (CONST_INT_P (op2)
23854 : 26 : && (code == ASHIFT || code == LSHIFTRT || code == ASHIFTRT)
23855 : 1022 : && ix86_expand_vec_shift_qihi_constant (code, qdest, qop1, qop2))
23856 : : {
23857 : 26 : emit_move_insn (dest, gen_lowpart (qimode, qdest));
23858 : 26 : return;
23859 : : }
23860 : :
23861 : 970 : switch (code)
23862 : : {
23863 : 951 : case MULT:
23864 : 951 : gcc_assert (op2vec);
23865 : 951 : if (!TARGET_SSE4_1)
23866 : : {
23867 : : /* Unpack data such that we've got a source byte in each low byte
23868 : : of each word. We don't care what goes into the high byte of
23869 : : each word. Rather than trying to get zero in there, most
23870 : : convenient is to let it be a copy of the low byte. */
23871 : 246 : hop1 = copy_to_reg (qop1);
23872 : 246 : hop2 = copy_to_reg (qop2);
23873 : 246 : emit_insn (gen_vec_interleave_lowv16qi (hop1, hop1, hop1));
23874 : 246 : emit_insn (gen_vec_interleave_lowv16qi (hop2, hop2, hop2));
23875 : 246 : break;
23876 : : }
23877 : : /* FALLTHRU */
23878 : 724 : case ASHIFT:
23879 : 724 : case ASHIFTRT:
23880 : 724 : case LSHIFTRT:
23881 : 724 : hop1 = gen_reg_rtx (V8HImode);
23882 : 724 : ix86_expand_sse_unpack (hop1, qop1, uns_p, false);
23883 : : /* mult/vashr/vlshr/vashl */
23884 : 724 : if (op2vec)
23885 : : {
23886 : 718 : hop2 = gen_reg_rtx (V8HImode);
23887 : 718 : ix86_expand_sse_unpack (hop2, qop2, uns_p, false);
23888 : : }
23889 : : else
23890 : : hop2 = qop2;
23891 : :
23892 : : break;
23893 : 0 : default:
23894 : 0 : gcc_unreachable ();
23895 : : }
23896 : :
23897 : 970 : if (code != MULT && op2vec)
23898 : : {
23899 : : /* Expand vashr/vlshr/vashl. */
23900 : 13 : hdest = gen_reg_rtx (V8HImode);
23901 : 13 : emit_insn (gen_rtx_SET (hdest,
23902 : : simplify_gen_binary (code, V8HImode,
23903 : : hop1, hop2)));
23904 : : }
23905 : : else
23906 : : /* Expand mult/ashr/lshr/ashl. */
23907 : 957 : hdest = expand_simple_binop (V8HImode, code, hop1, hop2,
23908 : : NULL_RTX, 1, OPTAB_DIRECT);
23909 : :
23910 : 970 : if (TARGET_AVX512BW && TARGET_AVX512VL)
23911 : : {
23912 : 18 : if (qimode == V8QImode)
23913 : : qdest = dest;
23914 : : else
23915 : 4 : qdest = gen_reg_rtx (V8QImode);
23916 : :
23917 : 18 : emit_insn (gen_truncv8hiv8qi2 (qdest, hdest));
23918 : : }
23919 : : else
23920 : : {
23921 : 952 : struct expand_vec_perm_d d;
23922 : 952 : rtx qres = gen_lowpart (V16QImode, hdest);
23923 : 952 : bool ok;
23924 : 952 : int i;
23925 : :
23926 : : /* Merge the data back into the right place. */
23927 : 952 : d.target = qdest;
23928 : 952 : d.op0 = d.op1 = qres;
23929 : 952 : d.vmode = V16QImode;
23930 : 952 : d.nelt = 16;
23931 : 952 : d.one_operand_p = false;
23932 : 952 : d.testing_p = false;
23933 : :
23934 : 16184 : for (i = 0; i < d.nelt; ++i)
23935 : 15232 : d.perm[i] = i * 2;
23936 : :
23937 : 952 : ok = ix86_expand_vec_perm_const_1 (&d);
23938 : 952 : gcc_assert (ok);
23939 : : }
23940 : :
23941 : 970 : if (qdest != dest)
23942 : 956 : emit_move_insn (dest, gen_lowpart (qimode, qdest));
23943 : : }
23944 : :
23945 : : /* Emit instruction in 2x wider mode. For example, optimize
23946 : : vector MUL generation like
23947 : :
23948 : : vpmovzxbw ymm2, xmm0
23949 : : vpmovzxbw ymm3, xmm1
23950 : : vpmullw ymm4, ymm2, ymm3
23951 : : vpmovwb xmm0, ymm4
23952 : :
23953 : : it would take less instructions than ix86_expand_vecop_qihi.
23954 : : Return true if success. */
23955 : :
23956 : : static bool
23957 : 1324 : ix86_expand_vecop_qihi2 (enum rtx_code code, rtx dest, rtx op1, rtx op2)
23958 : : {
23959 : 1324 : machine_mode himode, qimode = GET_MODE (dest);
23960 : 1324 : machine_mode wqimode;
23961 : 1324 : rtx qop1, qop2, hop1, hop2, hdest;
23962 : 1324 : rtx (*gen_truncate)(rtx, rtx) = NULL;
23963 : 1324 : bool op2vec = GET_MODE_CLASS (GET_MODE (op2)) == MODE_VECTOR_INT;
23964 : 1324 : bool uns_p = code != ASHIFTRT;
23965 : :
23966 : 1324 : if ((qimode == V16QImode && !TARGET_AVX2)
23967 : 810 : || (qimode == V32QImode && (!TARGET_AVX512BW || !TARGET_EVEX512))
23968 : : /* There are no V64HImode instructions. */
23969 : 536 : || qimode == V64QImode)
23970 : : return false;
23971 : :
23972 : : /* Do not generate ymm/zmm instructions when
23973 : : target prefers 128/256 bit vector width. */
23974 : 503 : if ((qimode == V16QImode && TARGET_PREFER_AVX128)
23975 : 503 : || (qimode == V32QImode && TARGET_PREFER_AVX256))
23976 : : return false;
23977 : :
23978 : 488 : switch (qimode)
23979 : : {
23980 : 472 : case E_V16QImode:
23981 : 472 : himode = V16HImode;
23982 : 472 : if (TARGET_AVX512VL && TARGET_AVX512BW)
23983 : 251 : gen_truncate = gen_truncv16hiv16qi2;
23984 : : break;
23985 : : case E_V32QImode:
23986 : : himode = V32HImode;
23987 : : gen_truncate = gen_truncv32hiv32qi2;
23988 : : break;
23989 : 0 : default:
23990 : 0 : gcc_unreachable ();
23991 : : }
23992 : :
23993 : 488 : wqimode = GET_MODE_2XWIDER_MODE (qimode).require ();
23994 : 488 : qop1 = lowpart_subreg (wqimode, force_reg (qimode, op1), qimode);
23995 : :
23996 : 488 : if (op2vec)
23997 : 488 : qop2 = lowpart_subreg (wqimode, force_reg (qimode, op2), qimode);
23998 : : else
23999 : : qop2 = op2;
24000 : :
24001 : 488 : hop1 = gen_reg_rtx (himode);
24002 : 488 : ix86_expand_sse_unpack (hop1, qop1, uns_p, false);
24003 : :
24004 : 488 : if (op2vec)
24005 : : {
24006 : 488 : hop2 = gen_reg_rtx (himode);
24007 : 488 : ix86_expand_sse_unpack (hop2, qop2, uns_p, false);
24008 : : }
24009 : : else
24010 : : hop2 = qop2;
24011 : :
24012 : 488 : if (code != MULT && op2vec)
24013 : : {
24014 : : /* Expand vashr/vlshr/vashl. */
24015 : 12 : hdest = gen_reg_rtx (himode);
24016 : 12 : emit_insn (gen_rtx_SET (hdest,
24017 : : simplify_gen_binary (code, himode,
24018 : : hop1, hop2)));
24019 : : }
24020 : : else
24021 : : /* Expand mult/ashr/lshr/ashl. */
24022 : 476 : hdest = expand_simple_binop (himode, code, hop1, hop2,
24023 : : NULL_RTX, 1, OPTAB_DIRECT);
24024 : :
24025 : 488 : if (gen_truncate)
24026 : 267 : emit_insn (gen_truncate (dest, hdest));
24027 : : else
24028 : : {
24029 : 221 : struct expand_vec_perm_d d;
24030 : 221 : rtx wqdest = gen_reg_rtx (wqimode);
24031 : 221 : rtx wqres = gen_lowpart (wqimode, hdest);
24032 : 221 : bool ok;
24033 : 221 : int i;
24034 : :
24035 : : /* Merge the data back into the right place. */
24036 : 221 : d.target = wqdest;
24037 : 221 : d.op0 = d.op1 = wqres;
24038 : 221 : d.vmode = wqimode;
24039 : 221 : d.nelt = GET_MODE_NUNITS (wqimode);
24040 : 221 : d.one_operand_p = false;
24041 : 221 : d.testing_p = false;
24042 : :
24043 : 7293 : for (i = 0; i < d.nelt; ++i)
24044 : 7072 : d.perm[i] = i * 2;
24045 : :
24046 : 221 : ok = ix86_expand_vec_perm_const_1 (&d);
24047 : 221 : gcc_assert (ok);
24048 : :
24049 : 221 : emit_move_insn (dest, gen_lowpart (qimode, wqdest));
24050 : : }
24051 : :
24052 : : return true;
24053 : : }
24054 : :
24055 : : /* Expand a vector operation CODE for a V*QImode in terms of the
24056 : : same operation on V*HImode. */
24057 : :
24058 : : void
24059 : 1602 : ix86_expand_vecop_qihi (enum rtx_code code, rtx dest, rtx op1, rtx op2)
24060 : : {
24061 : 1602 : machine_mode qimode = GET_MODE (dest);
24062 : 1602 : machine_mode himode;
24063 : 1602 : rtx (*gen_il) (rtx, rtx, rtx);
24064 : 1602 : rtx (*gen_ih) (rtx, rtx, rtx);
24065 : 1602 : rtx op1_l, op1_h, op2_l, op2_h, res_l, res_h;
24066 : 1602 : bool op2vec = GET_MODE_CLASS (GET_MODE (op2)) == MODE_VECTOR_INT;
24067 : 1602 : struct expand_vec_perm_d d;
24068 : 1602 : bool full_interleave = true;
24069 : 1602 : bool uns_p = code != ASHIFTRT;
24070 : 1602 : bool ok;
24071 : 1602 : int i;
24072 : :
24073 : 1602 : if (CONST_INT_P (op2)
24074 : 278 : && (code == ASHIFT || code == LSHIFTRT || code == ASHIFTRT)
24075 : 1880 : && ix86_expand_vec_shift_qihi_constant (code, dest, op1, op2))
24076 : 766 : return;
24077 : :
24078 : 1324 : if (ix86_expand_vecop_qihi2 (code, dest, op1, op2))
24079 : : return;
24080 : :
24081 : 836 : switch (qimode)
24082 : : {
24083 : : case E_V16QImode:
24084 : : himode = V8HImode;
24085 : : break;
24086 : 289 : case E_V32QImode:
24087 : 289 : himode = V16HImode;
24088 : 289 : break;
24089 : 33 : case E_V64QImode:
24090 : 33 : himode = V32HImode;
24091 : 33 : break;
24092 : 0 : default:
24093 : 0 : gcc_unreachable ();
24094 : : }
24095 : :
24096 : 836 : switch (code)
24097 : : {
24098 : 829 : case MULT:
24099 : 829 : gcc_assert (op2vec);
24100 : : /* Unpack data such that we've got a source byte in each low byte of
24101 : : each word. We don't care what goes into the high byte of each word.
24102 : : Rather than trying to get zero in there, most convenient is to let
24103 : : it be a copy of the low byte. */
24104 : 829 : switch (qimode)
24105 : : {
24106 : : case E_V16QImode:
24107 : : gen_il = gen_vec_interleave_lowv16qi;
24108 : : gen_ih = gen_vec_interleave_highv16qi;
24109 : : break;
24110 : 289 : case E_V32QImode:
24111 : 289 : gen_il = gen_avx2_interleave_lowv32qi;
24112 : 289 : gen_ih = gen_avx2_interleave_highv32qi;
24113 : 289 : full_interleave = false;
24114 : 289 : break;
24115 : 32 : case E_V64QImode:
24116 : 32 : gen_il = gen_avx512bw_interleave_lowv64qi;
24117 : 32 : gen_ih = gen_avx512bw_interleave_highv64qi;
24118 : 32 : full_interleave = false;
24119 : 32 : break;
24120 : 0 : default:
24121 : 0 : gcc_unreachable ();
24122 : : }
24123 : :
24124 : 829 : op2_l = gen_reg_rtx (qimode);
24125 : 829 : op2_h = gen_reg_rtx (qimode);
24126 : 829 : emit_insn (gen_il (op2_l, op2, op2));
24127 : 829 : emit_insn (gen_ih (op2_h, op2, op2));
24128 : :
24129 : 829 : op1_l = gen_reg_rtx (qimode);
24130 : 829 : op1_h = gen_reg_rtx (qimode);
24131 : 829 : emit_insn (gen_il (op1_l, op1, op1));
24132 : 829 : emit_insn (gen_ih (op1_h, op1, op1));
24133 : 829 : break;
24134 : :
24135 : 7 : case ASHIFT:
24136 : 7 : case ASHIFTRT:
24137 : 7 : case LSHIFTRT:
24138 : 7 : op1_l = gen_reg_rtx (himode);
24139 : 7 : op1_h = gen_reg_rtx (himode);
24140 : 7 : ix86_expand_sse_unpack (op1_l, op1, uns_p, false);
24141 : 7 : ix86_expand_sse_unpack (op1_h, op1, uns_p, true);
24142 : : /* vashr/vlshr/vashl */
24143 : 7 : if (op2vec)
24144 : : {
24145 : 1 : rtx tmp = force_reg (qimode, op2);
24146 : 1 : op2_l = gen_reg_rtx (himode);
24147 : 1 : op2_h = gen_reg_rtx (himode);
24148 : 1 : ix86_expand_sse_unpack (op2_l, tmp, uns_p, false);
24149 : 1 : ix86_expand_sse_unpack (op2_h, tmp, uns_p, true);
24150 : : }
24151 : : else
24152 : : op2_l = op2_h = op2;
24153 : :
24154 : : break;
24155 : 0 : default:
24156 : 0 : gcc_unreachable ();
24157 : : }
24158 : :
24159 : 836 : if (code != MULT && op2vec)
24160 : : {
24161 : : /* Expand vashr/vlshr/vashl. */
24162 : 1 : res_l = gen_reg_rtx (himode);
24163 : 1 : res_h = gen_reg_rtx (himode);
24164 : 1 : emit_insn (gen_rtx_SET (res_l,
24165 : : simplify_gen_binary (code, himode,
24166 : : op1_l, op2_l)));
24167 : 1 : emit_insn (gen_rtx_SET (res_h,
24168 : : simplify_gen_binary (code, himode,
24169 : : op1_h, op2_h)));
24170 : : }
24171 : : else
24172 : : {
24173 : : /* Expand mult/ashr/lshr/ashl. */
24174 : 835 : res_l = expand_simple_binop (himode, code, op1_l, op2_l, NULL_RTX,
24175 : : 1, OPTAB_DIRECT);
24176 : 835 : res_h = expand_simple_binop (himode, code, op1_h, op2_h, NULL_RTX,
24177 : : 1, OPTAB_DIRECT);
24178 : : }
24179 : :
24180 : 836 : gcc_assert (res_l && res_h);
24181 : :
24182 : : /* Merge the data back into the right place. */
24183 : 836 : d.target = dest;
24184 : 836 : d.op0 = gen_lowpart (qimode, res_l);
24185 : 836 : d.op1 = gen_lowpart (qimode, res_h);
24186 : 836 : d.vmode = qimode;
24187 : 836 : d.nelt = GET_MODE_NUNITS (qimode);
24188 : 836 : d.one_operand_p = false;
24189 : 836 : d.testing_p = false;
24190 : :
24191 : 836 : if (full_interleave)
24192 : : {
24193 : : /* We used the full interleave, the desired
24194 : : results are in the even elements. */
24195 : 8803 : for (i = 0; i < d.nelt; ++i)
24196 : 8288 : d.perm[i] = i * 2;
24197 : : }
24198 : : else
24199 : : {
24200 : : /* For AVX, the interleave used above was not cross-lane. So the
24201 : : extraction is evens but with the second and third quarter swapped.
24202 : : Happily, that is even one insn shorter than even extraction.
24203 : : For AVX512BW we have 4 lanes. We extract evens from within a lane,
24204 : : always first from the first and then from the second source operand,
24205 : : the index bits above the low 4 bits remains the same.
24206 : : Thus, for d.nelt == 32 we want permutation
24207 : : 0,2,4,..14, 32,34,36,..46, 16,18,20,..30, 48,50,52,..62
24208 : : and for d.nelt == 64 we want permutation
24209 : : 0,2,4,..14, 64,66,68,..78, 16,18,20,..30, 80,82,84,..94,
24210 : : 32,34,36,..46, 96,98,100,..110, 48,50,52,..62, 112,114,116,..126. */
24211 : 11617 : for (i = 0; i < d.nelt; ++i)
24212 : 16944 : d.perm[i] = ((i * 2) & 14) + ((i & 8) ? d.nelt : 0) + (i & ~15);
24213 : : }
24214 : :
24215 : 836 : ok = ix86_expand_vec_perm_const_1 (&d);
24216 : 836 : gcc_assert (ok);
24217 : : }
24218 : :
24219 : : /* Helper function of ix86_expand_mul_widen_evenodd. Return true
24220 : : if op is CONST_VECTOR with all odd elements equal to their
24221 : : preceding element. */
24222 : :
24223 : : static bool
24224 : 6482 : const_vector_equal_evenodd_p (rtx op)
24225 : : {
24226 : 6482 : machine_mode mode = GET_MODE (op);
24227 : 6482 : int i, nunits = GET_MODE_NUNITS (mode);
24228 : 6482 : if (GET_CODE (op) != CONST_VECTOR
24229 : 8168 : || nunits != CONST_VECTOR_NUNITS (op))
24230 : 4796 : return false;
24231 : 2922 : for (i = 0; i < nunits; i += 2)
24232 : 2353 : if (CONST_VECTOR_ELT (op, i) != CONST_VECTOR_ELT (op, i + 1))
24233 : : return false;
24234 : : return true;
24235 : : }
24236 : :
24237 : : void
24238 : 6683 : ix86_expand_mul_widen_evenodd (rtx dest, rtx op1, rtx op2,
24239 : : bool uns_p, bool odd_p)
24240 : : {
24241 : 6683 : machine_mode mode = GET_MODE (op1);
24242 : 6683 : machine_mode wmode = GET_MODE (dest);
24243 : 6683 : rtx x;
24244 : 6683 : rtx orig_op1 = op1, orig_op2 = op2;
24245 : :
24246 : 6683 : if (!nonimmediate_operand (op1, mode))
24247 : 0 : op1 = force_reg (mode, op1);
24248 : 6683 : if (!nonimmediate_operand (op2, mode))
24249 : 2800 : op2 = force_reg (mode, op2);
24250 : :
24251 : : /* We only play even/odd games with vectors of SImode. */
24252 : 6683 : gcc_assert (mode == V4SImode || mode == V8SImode || mode == V16SImode);
24253 : :
24254 : : /* If we're looking for the odd results, shift those members down to
24255 : : the even slots. For some cpus this is faster than a PSHUFD. */
24256 : 6683 : if (odd_p)
24257 : : {
24258 : : /* For XOP use vpmacsdqh, but only for smult, as it is only
24259 : : signed. */
24260 : 3262 : if (TARGET_XOP && mode == V4SImode && !uns_p)
24261 : : {
24262 : 21 : x = force_reg (wmode, CONST0_RTX (wmode));
24263 : 21 : emit_insn (gen_xop_pmacsdqh (dest, op1, op2, x));
24264 : 21 : return;
24265 : : }
24266 : :
24267 : 6482 : x = GEN_INT (GET_MODE_UNIT_BITSIZE (mode));
24268 : 3241 : if (!const_vector_equal_evenodd_p (orig_op1))
24269 : 3241 : op1 = expand_binop (wmode, lshr_optab, gen_lowpart (wmode, op1),
24270 : : x, NULL, 1, OPTAB_DIRECT);
24271 : 3241 : if (!const_vector_equal_evenodd_p (orig_op2))
24272 : 2672 : op2 = expand_binop (wmode, lshr_optab, gen_lowpart (wmode, op2),
24273 : : x, NULL, 1, OPTAB_DIRECT);
24274 : 3241 : op1 = gen_lowpart (mode, op1);
24275 : 3241 : op2 = gen_lowpart (mode, op2);
24276 : : }
24277 : :
24278 : 6662 : if (mode == V16SImode)
24279 : : {
24280 : 1 : if (uns_p)
24281 : 0 : x = gen_vec_widen_umult_even_v16si (dest, op1, op2);
24282 : : else
24283 : 1 : x = gen_vec_widen_smult_even_v16si (dest, op1, op2);
24284 : : }
24285 : 6661 : else if (mode == V8SImode)
24286 : : {
24287 : 99 : if (uns_p)
24288 : 40 : x = gen_vec_widen_umult_even_v8si (dest, op1, op2);
24289 : : else
24290 : 59 : x = gen_vec_widen_smult_even_v8si (dest, op1, op2);
24291 : : }
24292 : 6562 : else if (uns_p)
24293 : 5647 : x = gen_vec_widen_umult_even_v4si (dest, op1, op2);
24294 : 915 : else if (TARGET_SSE4_1)
24295 : 287 : x = gen_sse4_1_mulv2siv2di3 (dest, op1, op2);
24296 : : else
24297 : : {
24298 : 628 : rtx s1, s2, t0, t1, t2;
24299 : :
24300 : : /* The easiest way to implement this without PMULDQ is to go through
24301 : : the motions as if we are performing a full 64-bit multiply. With
24302 : : the exception that we need to do less shuffling of the elements. */
24303 : :
24304 : : /* Compute the sign-extension, aka highparts, of the two operands. */
24305 : 628 : s1 = ix86_expand_sse_cmp (gen_reg_rtx (mode), GT, CONST0_RTX (mode),
24306 : : op1, pc_rtx, pc_rtx);
24307 : 628 : s2 = ix86_expand_sse_cmp (gen_reg_rtx (mode), GT, CONST0_RTX (mode),
24308 : : op2, pc_rtx, pc_rtx);
24309 : :
24310 : : /* Multiply LO(A) * HI(B), and vice-versa. */
24311 : 628 : t1 = gen_reg_rtx (wmode);
24312 : 628 : t2 = gen_reg_rtx (wmode);
24313 : 628 : emit_insn (gen_vec_widen_umult_even_v4si (t1, s1, op2));
24314 : 628 : emit_insn (gen_vec_widen_umult_even_v4si (t2, s2, op1));
24315 : :
24316 : : /* Multiply LO(A) * LO(B). */
24317 : 628 : t0 = gen_reg_rtx (wmode);
24318 : 628 : emit_insn (gen_vec_widen_umult_even_v4si (t0, op1, op2));
24319 : :
24320 : : /* Combine and shift the highparts into place. */
24321 : 628 : t1 = expand_binop (wmode, add_optab, t1, t2, t1, 1, OPTAB_DIRECT);
24322 : 628 : t1 = expand_binop (wmode, ashl_optab, t1, GEN_INT (32), t1,
24323 : : 1, OPTAB_DIRECT);
24324 : :
24325 : : /* Combine high and low parts. */
24326 : 628 : force_expand_binop (wmode, add_optab, t0, t1, dest, 1, OPTAB_DIRECT);
24327 : 628 : return;
24328 : : }
24329 : 6034 : emit_insn (x);
24330 : : }
24331 : :
24332 : : void
24333 : 918 : ix86_expand_mul_widen_hilo (rtx dest, rtx op1, rtx op2,
24334 : : bool uns_p, bool high_p)
24335 : : {
24336 : 918 : machine_mode wmode = GET_MODE (dest);
24337 : 918 : machine_mode mode = GET_MODE (op1);
24338 : 918 : rtx t1, t2, t3, t4, mask;
24339 : :
24340 : 918 : switch (mode)
24341 : : {
24342 : 326 : case E_V4SImode:
24343 : 326 : t1 = gen_reg_rtx (mode);
24344 : 326 : t2 = gen_reg_rtx (mode);
24345 : 326 : if (TARGET_XOP && !uns_p)
24346 : : {
24347 : : /* With XOP, we have pmacsdqh, aka mul_widen_odd. In this case,
24348 : : shuffle the elements once so that all elements are in the right
24349 : : place for immediate use: { A C B D }. */
24350 : 38 : emit_insn (gen_sse2_pshufd_1 (t1, op1, const0_rtx, const2_rtx,
24351 : : const1_rtx, GEN_INT (3)));
24352 : 38 : emit_insn (gen_sse2_pshufd_1 (t2, op2, const0_rtx, const2_rtx,
24353 : : const1_rtx, GEN_INT (3)));
24354 : : }
24355 : : else
24356 : : {
24357 : : /* Put the elements into place for the multiply. */
24358 : 288 : ix86_expand_vec_interleave (t1, op1, op1, high_p);
24359 : 288 : ix86_expand_vec_interleave (t2, op2, op2, high_p);
24360 : 288 : high_p = false;
24361 : : }
24362 : 326 : ix86_expand_mul_widen_evenodd (dest, t1, t2, uns_p, high_p);
24363 : 326 : break;
24364 : :
24365 : 60 : case E_V8SImode:
24366 : : /* Shuffle the elements between the lanes. After this we
24367 : : have { A B E F | C D G H } for each operand. */
24368 : 60 : t1 = gen_reg_rtx (V4DImode);
24369 : 60 : t2 = gen_reg_rtx (V4DImode);
24370 : 60 : emit_insn (gen_avx2_permv4di_1 (t1, gen_lowpart (V4DImode, op1),
24371 : : const0_rtx, const2_rtx,
24372 : : const1_rtx, GEN_INT (3)));
24373 : 60 : emit_insn (gen_avx2_permv4di_1 (t2, gen_lowpart (V4DImode, op2),
24374 : : const0_rtx, const2_rtx,
24375 : : const1_rtx, GEN_INT (3)));
24376 : :
24377 : : /* Shuffle the elements within the lanes. After this we
24378 : : have { A A B B | C C D D } or { E E F F | G G H H }. */
24379 : 60 : t3 = gen_reg_rtx (V8SImode);
24380 : 60 : t4 = gen_reg_rtx (V8SImode);
24381 : 90 : mask = GEN_INT (high_p
24382 : : ? 2 + (2 << 2) + (3 << 4) + (3 << 6)
24383 : : : 0 + (0 << 2) + (1 << 4) + (1 << 6));
24384 : 60 : emit_insn (gen_avx2_pshufdv3 (t3, gen_lowpart (V8SImode, t1), mask));
24385 : 60 : emit_insn (gen_avx2_pshufdv3 (t4, gen_lowpart (V8SImode, t2), mask));
24386 : :
24387 : 60 : ix86_expand_mul_widen_evenodd (dest, t3, t4, uns_p, false);
24388 : 60 : break;
24389 : :
24390 : 356 : case E_V8HImode:
24391 : 356 : case E_V16HImode:
24392 : 356 : t1 = expand_binop (mode, smul_optab, op1, op2, NULL_RTX,
24393 : : uns_p, OPTAB_DIRECT);
24394 : 566 : t2 = expand_binop (mode,
24395 : : uns_p ? umul_highpart_optab : smul_highpart_optab,
24396 : : op1, op2, NULL_RTX, uns_p, OPTAB_DIRECT);
24397 : 356 : gcc_assert (t1 && t2);
24398 : :
24399 : 356 : t3 = gen_reg_rtx (mode);
24400 : 356 : ix86_expand_vec_interleave (t3, t1, t2, high_p);
24401 : 356 : emit_move_insn (dest, gen_lowpart (wmode, t3));
24402 : 356 : break;
24403 : :
24404 : 176 : case E_V16QImode:
24405 : 176 : case E_V32QImode:
24406 : 176 : case E_V32HImode:
24407 : 176 : case E_V16SImode:
24408 : 176 : case E_V64QImode:
24409 : 176 : t1 = gen_reg_rtx (wmode);
24410 : 176 : t2 = gen_reg_rtx (wmode);
24411 : 176 : ix86_expand_sse_unpack (t1, op1, uns_p, high_p);
24412 : 176 : ix86_expand_sse_unpack (t2, op2, uns_p, high_p);
24413 : :
24414 : 176 : emit_insn (gen_rtx_SET (dest, gen_rtx_MULT (wmode, t1, t2)));
24415 : 176 : break;
24416 : :
24417 : 0 : default:
24418 : 0 : gcc_unreachable ();
24419 : : }
24420 : 918 : }
24421 : :
24422 : : void
24423 : 2669 : ix86_expand_sse2_mulv4si3 (rtx op0, rtx op1, rtx op2)
24424 : : {
24425 : 2669 : rtx res_1, res_2, res_3, res_4;
24426 : :
24427 : 2669 : res_1 = gen_reg_rtx (V4SImode);
24428 : 2669 : res_2 = gen_reg_rtx (V4SImode);
24429 : 2669 : res_3 = gen_reg_rtx (V2DImode);
24430 : 2669 : res_4 = gen_reg_rtx (V2DImode);
24431 : 2669 : ix86_expand_mul_widen_evenodd (res_3, op1, op2, true, false);
24432 : 2669 : ix86_expand_mul_widen_evenodd (res_4, op1, op2, true, true);
24433 : :
24434 : : /* Move the results in element 2 down to element 1; we don't care
24435 : : what goes in elements 2 and 3. Then we can merge the parts
24436 : : back together with an interleave.
24437 : :
24438 : : Note that two other sequences were tried:
24439 : : (1) Use interleaves at the start instead of psrldq, which allows
24440 : : us to use a single shufps to merge things back at the end.
24441 : : (2) Use shufps here to combine the two vectors, then pshufd to
24442 : : put the elements in the correct order.
24443 : : In both cases the cost of the reformatting stall was too high
24444 : : and the overall sequence slower. */
24445 : :
24446 : 2669 : emit_insn (gen_sse2_pshufd_1 (res_1, gen_lowpart (V4SImode, res_3),
24447 : : const0_rtx, const2_rtx,
24448 : : const0_rtx, const0_rtx));
24449 : 2669 : emit_insn (gen_sse2_pshufd_1 (res_2, gen_lowpart (V4SImode, res_4),
24450 : : const0_rtx, const2_rtx,
24451 : : const0_rtx, const0_rtx));
24452 : 2669 : res_1 = emit_insn (gen_vec_interleave_lowv4si (op0, res_1, res_2));
24453 : :
24454 : 2669 : set_unique_reg_note (res_1, REG_EQUAL, gen_rtx_MULT (V4SImode, op1, op2));
24455 : 2669 : }
24456 : :
24457 : : void
24458 : 611 : ix86_expand_sse2_mulvxdi3 (rtx op0, rtx op1, rtx op2)
24459 : : {
24460 : 611 : machine_mode mode = GET_MODE (op0);
24461 : 611 : rtx t1, t2, t3, t4, t5, t6;
24462 : :
24463 : 611 : if (TARGET_AVX512DQ && TARGET_EVEX512 && mode == V8DImode)
24464 : 30 : emit_insn (gen_avx512dq_mulv8di3 (op0, op1, op2));
24465 : 581 : else if (TARGET_AVX512DQ && TARGET_AVX512VL && mode == V4DImode)
24466 : 30 : emit_insn (gen_avx512dq_mulv4di3 (op0, op1, op2));
24467 : 551 : else if (TARGET_AVX512DQ && TARGET_AVX512VL && mode == V2DImode)
24468 : 34 : emit_insn (gen_avx512dq_mulv2di3 (op0, op1, op2));
24469 : 517 : else if (TARGET_XOP && mode == V2DImode)
24470 : : {
24471 : : /* op1: A,B,C,D, op2: E,F,G,H */
24472 : 1 : op1 = gen_lowpart (V4SImode, op1);
24473 : 1 : op2 = gen_lowpart (V4SImode, op2);
24474 : :
24475 : 1 : t1 = gen_reg_rtx (V4SImode);
24476 : 1 : t2 = gen_reg_rtx (V4SImode);
24477 : 1 : t3 = gen_reg_rtx (V2DImode);
24478 : 1 : t4 = gen_reg_rtx (V2DImode);
24479 : :
24480 : : /* t1: B,A,D,C */
24481 : 1 : emit_insn (gen_sse2_pshufd_1 (t1, op1,
24482 : : GEN_INT (1),
24483 : : GEN_INT (0),
24484 : : GEN_INT (3),
24485 : : GEN_INT (2)));
24486 : :
24487 : : /* t2: (B*E),(A*F),(D*G),(C*H) */
24488 : 1 : emit_insn (gen_mulv4si3 (t2, t1, op2));
24489 : :
24490 : : /* t3: (B*E)+(A*F), (D*G)+(C*H) */
24491 : 1 : emit_insn (gen_xop_phadddq (t3, t2));
24492 : :
24493 : : /* t4: ((B*E)+(A*F))<<32, ((D*G)+(C*H))<<32 */
24494 : 1 : emit_insn (gen_ashlv2di3 (t4, t3, GEN_INT (32)));
24495 : :
24496 : : /* Multiply lower parts and add all */
24497 : 1 : t5 = gen_reg_rtx (V2DImode);
24498 : 1 : emit_insn (gen_vec_widen_umult_even_v4si (t5,
24499 : 1 : gen_lowpart (V4SImode, op1),
24500 : 1 : gen_lowpart (V4SImode, op2)));
24501 : 1 : force_expand_binop (mode, add_optab, t5, t4, op0, 1, OPTAB_DIRECT);
24502 : : }
24503 : : else
24504 : : {
24505 : 516 : machine_mode nmode;
24506 : 516 : rtx (*umul) (rtx, rtx, rtx);
24507 : :
24508 : 516 : if (mode == V2DImode)
24509 : : {
24510 : : umul = gen_vec_widen_umult_even_v4si;
24511 : : nmode = V4SImode;
24512 : : }
24513 : 397 : else if (mode == V4DImode)
24514 : : {
24515 : : umul = gen_vec_widen_umult_even_v8si;
24516 : : nmode = V8SImode;
24517 : : }
24518 : 120 : else if (mode == V8DImode)
24519 : : {
24520 : : umul = gen_vec_widen_umult_even_v16si;
24521 : : nmode = V16SImode;
24522 : : }
24523 : : else
24524 : 0 : gcc_unreachable ();
24525 : :
24526 : :
24527 : : /* Multiply low parts. */
24528 : 516 : t1 = gen_reg_rtx (mode);
24529 : 516 : emit_insn (umul (t1, gen_lowpart (nmode, op1), gen_lowpart (nmode, op2)));
24530 : :
24531 : : /* Shift input vectors right 32 bits so we can multiply high parts. */
24532 : 516 : t6 = GEN_INT (32);
24533 : 516 : t2 = expand_binop (mode, lshr_optab, op1, t6, NULL, 1, OPTAB_DIRECT);
24534 : 516 : t3 = expand_binop (mode, lshr_optab, op2, t6, NULL, 1, OPTAB_DIRECT);
24535 : :
24536 : : /* Multiply high parts by low parts. */
24537 : 516 : t4 = gen_reg_rtx (mode);
24538 : 516 : t5 = gen_reg_rtx (mode);
24539 : 516 : emit_insn (umul (t4, gen_lowpart (nmode, t2), gen_lowpart (nmode, op2)));
24540 : 516 : emit_insn (umul (t5, gen_lowpart (nmode, t3), gen_lowpart (nmode, op1)));
24541 : :
24542 : : /* Combine and shift the highparts back. */
24543 : 516 : t4 = expand_binop (mode, add_optab, t4, t5, t4, 1, OPTAB_DIRECT);
24544 : 516 : t4 = expand_binop (mode, ashl_optab, t4, t6, t4, 1, OPTAB_DIRECT);
24545 : :
24546 : : /* Combine high and low parts. */
24547 : 516 : force_expand_binop (mode, add_optab, t1, t4, op0, 1, OPTAB_DIRECT);
24548 : : }
24549 : :
24550 : 611 : set_unique_reg_note (get_last_insn (), REG_EQUAL,
24551 : : gen_rtx_MULT (mode, op1, op2));
24552 : 611 : }
24553 : :
24554 : : /* Return 1 if control tansfer instruction INSN
24555 : : should be encoded with notrack prefix. */
24556 : :
24557 : : bool
24558 : 13606377 : ix86_notrack_prefixed_insn_p (rtx_insn *insn)
24559 : : {
24560 : 13606377 : if (!insn || !((flag_cf_protection & CF_BRANCH)))
24561 : : return false;
24562 : :
24563 : 3331598 : if (CALL_P (insn))
24564 : : {
24565 : 1227657 : rtx call = get_call_rtx_from (insn);
24566 : 1227657 : gcc_assert (call != NULL_RTX);
24567 : 1227657 : rtx addr = XEXP (call, 0);
24568 : :
24569 : : /* Do not emit 'notrack' if it's not an indirect call. */
24570 : 1227657 : if (MEM_P (addr)
24571 : 1227657 : && GET_CODE (XEXP (addr, 0)) == SYMBOL_REF)
24572 : : return false;
24573 : : else
24574 : 65020 : return find_reg_note (insn, REG_CALL_NOCF_CHECK, 0);
24575 : : }
24576 : :
24577 : 2103941 : if (JUMP_P (insn) && !flag_cet_switch)
24578 : : {
24579 : 2091868 : rtx target = JUMP_LABEL (insn);
24580 : 2091868 : if (target == NULL_RTX || ANY_RETURN_P (target))
24581 : : return false;
24582 : :
24583 : : /* Check the jump is a switch table. */
24584 : 2091830 : rtx_insn *label = as_a<rtx_insn *> (target);
24585 : 2091830 : rtx_insn *table = next_insn (label);
24586 : 2091830 : if (table == NULL_RTX || !JUMP_TABLE_DATA_P (table))
24587 : : return false;
24588 : : else
24589 : : return true;
24590 : : }
24591 : : return false;
24592 : : }
24593 : :
24594 : : /* Calculate integer abs() using only SSE2 instructions. */
24595 : :
24596 : : void
24597 : 112 : ix86_expand_sse2_abs (rtx target, rtx input)
24598 : : {
24599 : 112 : machine_mode mode = GET_MODE (target);
24600 : 112 : rtx tmp0, tmp1, x;
24601 : :
24602 : 112 : switch (mode)
24603 : : {
24604 : 28 : case E_V2DImode:
24605 : 28 : case E_V4DImode:
24606 : : /* For 64-bit signed integer X, with SSE4.2 use
24607 : : pxor t0, t0; pcmpgtq X, t0; pxor t0, X; psubq t0, X.
24608 : : Otherwise handle it similarly to V4SImode, except use 64 as W instead of
24609 : : 32 and use logical instead of arithmetic right shift (which is
24610 : : unimplemented) and subtract. */
24611 : 28 : if (TARGET_SSE4_2)
24612 : : {
24613 : 12 : tmp0 = gen_reg_rtx (mode);
24614 : 12 : tmp1 = gen_reg_rtx (mode);
24615 : 12 : emit_move_insn (tmp1, CONST0_RTX (mode));
24616 : 12 : if (mode == E_V2DImode)
24617 : 8 : emit_insn (gen_sse4_2_gtv2di3 (tmp0, tmp1, input));
24618 : : else
24619 : 4 : emit_insn (gen_avx2_gtv4di3 (tmp0, tmp1, input));
24620 : : }
24621 : : else
24622 : : {
24623 : 32 : tmp0 = expand_simple_binop (mode, LSHIFTRT, input,
24624 : 16 : GEN_INT (GET_MODE_UNIT_BITSIZE (mode)
24625 : : - 1), NULL, 0, OPTAB_DIRECT);
24626 : 16 : tmp0 = expand_simple_unop (mode, NEG, tmp0, NULL, false);
24627 : : }
24628 : :
24629 : 28 : tmp1 = expand_simple_binop (mode, XOR, tmp0, input,
24630 : : NULL, 0, OPTAB_DIRECT);
24631 : 28 : x = expand_simple_binop (mode, MINUS, tmp1, tmp0,
24632 : : target, 0, OPTAB_DIRECT);
24633 : 28 : break;
24634 : :
24635 : 29 : case E_V4SImode:
24636 : : /* For 32-bit signed integer X, the best way to calculate the absolute
24637 : : value of X is (((signed) X >> (W-1)) ^ X) - ((signed) X >> (W-1)). */
24638 : 29 : tmp0 = expand_simple_binop (mode, ASHIFTRT, input,
24639 : 29 : GEN_INT (GET_MODE_UNIT_BITSIZE (mode) - 1),
24640 : : NULL, 0, OPTAB_DIRECT);
24641 : 29 : tmp1 = expand_simple_binop (mode, XOR, tmp0, input,
24642 : : NULL, 0, OPTAB_DIRECT);
24643 : 29 : x = expand_simple_binop (mode, MINUS, tmp1, tmp0,
24644 : : target, 0, OPTAB_DIRECT);
24645 : 29 : break;
24646 : :
24647 : 53 : case E_V8HImode:
24648 : : /* For 16-bit signed integer X, the best way to calculate the absolute
24649 : : value of X is max (X, -X), as SSE2 provides the PMAXSW insn. */
24650 : 53 : tmp0 = expand_unop (mode, neg_optab, input, NULL_RTX, 0);
24651 : :
24652 : 53 : x = expand_simple_binop (mode, SMAX, tmp0, input,
24653 : : target, 0, OPTAB_DIRECT);
24654 : 53 : break;
24655 : :
24656 : 2 : case E_V16QImode:
24657 : : /* For 8-bit signed integer X, the best way to calculate the absolute
24658 : : value of X is min ((unsigned char) X, (unsigned char) (-X)),
24659 : : as SSE2 provides the PMINUB insn. */
24660 : 2 : tmp0 = expand_unop (mode, neg_optab, input, NULL_RTX, 0);
24661 : :
24662 : 2 : x = expand_simple_binop (V16QImode, UMIN, tmp0, input,
24663 : : target, 0, OPTAB_DIRECT);
24664 : 2 : break;
24665 : :
24666 : 0 : default:
24667 : 0 : gcc_unreachable ();
24668 : : }
24669 : :
24670 : 112 : if (x != target)
24671 : 0 : emit_move_insn (target, x);
24672 : 112 : }
24673 : :
24674 : : /* Expand an extract from a vector register through pextr insn.
24675 : : Return true if successful. */
24676 : :
24677 : : bool
24678 : 97745 : ix86_expand_pextr (rtx *operands)
24679 : : {
24680 : 97745 : rtx dst = operands[0];
24681 : 97745 : rtx src = operands[1];
24682 : :
24683 : 97745 : unsigned int size = INTVAL (operands[2]);
24684 : 97745 : unsigned int pos = INTVAL (operands[3]);
24685 : :
24686 : 97745 : if (SUBREG_P (dst))
24687 : : {
24688 : : /* Reject non-lowpart subregs. */
24689 : 55108 : if (SUBREG_BYTE (dst) > 0)
24690 : : return false;
24691 : 55026 : dst = SUBREG_REG (dst);
24692 : : }
24693 : :
24694 : 97663 : if (SUBREG_P (src))
24695 : : {
24696 : 33086 : pos += SUBREG_BYTE (src) * BITS_PER_UNIT;
24697 : 33086 : src = SUBREG_REG (src);
24698 : : }
24699 : :
24700 : 97663 : switch (GET_MODE (src))
24701 : : {
24702 : 0 : case E_V16QImode:
24703 : 0 : case E_V8HImode:
24704 : 0 : case E_V4SImode:
24705 : 0 : case E_V2DImode:
24706 : 0 : case E_V1TImode:
24707 : 0 : {
24708 : 0 : machine_mode srcmode, dstmode;
24709 : 0 : rtx d, pat;
24710 : :
24711 : 0 : if (!int_mode_for_size (size, 0).exists (&dstmode))
24712 : : return false;
24713 : :
24714 : 0 : switch (dstmode)
24715 : : {
24716 : 0 : case E_QImode:
24717 : 0 : if (!TARGET_SSE4_1)
24718 : : return false;
24719 : : srcmode = V16QImode;
24720 : : break;
24721 : :
24722 : 0 : case E_HImode:
24723 : 0 : if (!TARGET_SSE2)
24724 : : return false;
24725 : : srcmode = V8HImode;
24726 : : break;
24727 : :
24728 : 0 : case E_SImode:
24729 : 0 : if (!TARGET_SSE4_1)
24730 : : return false;
24731 : : srcmode = V4SImode;
24732 : : break;
24733 : :
24734 : 0 : case E_DImode:
24735 : 0 : gcc_assert (TARGET_64BIT);
24736 : 0 : if (!TARGET_SSE4_1)
24737 : : return false;
24738 : : srcmode = V2DImode;
24739 : : break;
24740 : :
24741 : : default:
24742 : : return false;
24743 : : }
24744 : :
24745 : : /* Reject extractions from misaligned positions. */
24746 : 0 : if (pos & (size-1))
24747 : : return false;
24748 : :
24749 : 0 : if (GET_MODE (dst) == dstmode)
24750 : : d = dst;
24751 : : else
24752 : 0 : d = gen_reg_rtx (dstmode);
24753 : :
24754 : : /* Construct insn pattern. */
24755 : 0 : pat = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (1, GEN_INT (pos / size)));
24756 : 0 : pat = gen_rtx_VEC_SELECT (dstmode, gen_lowpart (srcmode, src), pat);
24757 : :
24758 : : /* Let the rtl optimizers know about the zero extension performed. */
24759 : 0 : if (dstmode == QImode || dstmode == HImode)
24760 : : {
24761 : 0 : pat = gen_rtx_ZERO_EXTEND (SImode, pat);
24762 : 0 : d = gen_lowpart (SImode, d);
24763 : : }
24764 : :
24765 : 0 : emit_insn (gen_rtx_SET (d, pat));
24766 : :
24767 : 0 : if (d != dst)
24768 : 0 : emit_move_insn (dst, gen_lowpart (GET_MODE (dst), d));
24769 : : return true;
24770 : : }
24771 : :
24772 : : default:
24773 : : return false;
24774 : : }
24775 : : }
24776 : :
24777 : : /* Expand an insert into a vector register through pinsr insn.
24778 : : Return true if successful. */
24779 : :
24780 : : bool
24781 : 104015 : ix86_expand_pinsr (rtx *operands)
24782 : : {
24783 : 104015 : rtx dst = operands[0];
24784 : 104015 : rtx src = operands[3];
24785 : :
24786 : 104015 : unsigned int size = INTVAL (operands[1]);
24787 : 104015 : unsigned int pos = INTVAL (operands[2]);
24788 : :
24789 : 104015 : if (SUBREG_P (dst))
24790 : : {
24791 : 57923 : pos += SUBREG_BYTE (dst) * BITS_PER_UNIT;
24792 : 57923 : dst = SUBREG_REG (dst);
24793 : : }
24794 : :
24795 : 104015 : switch (GET_MODE (dst))
24796 : : {
24797 : 94 : case E_V16QImode:
24798 : 94 : case E_V8HImode:
24799 : 94 : case E_V4SImode:
24800 : 94 : case E_V2DImode:
24801 : 94 : case E_V1TImode:
24802 : 94 : {
24803 : 94 : machine_mode srcmode, dstmode;
24804 : 94 : rtx (*pinsr)(rtx, rtx, rtx, rtx);
24805 : 94 : rtx d;
24806 : :
24807 : 188 : if (!int_mode_for_size (size, 0).exists (&srcmode))
24808 : : return false;
24809 : :
24810 : 94 : switch (srcmode)
24811 : : {
24812 : 1 : case E_QImode:
24813 : 1 : if (!TARGET_SSE4_1)
24814 : : return false;
24815 : : dstmode = V16QImode;
24816 : : pinsr = gen_sse4_1_pinsrb;
24817 : : break;
24818 : :
24819 : 6 : case E_HImode:
24820 : 6 : if (!TARGET_SSE2)
24821 : : return false;
24822 : : dstmode = V8HImode;
24823 : : pinsr = gen_sse2_pinsrw;
24824 : : break;
24825 : :
24826 : 87 : case E_SImode:
24827 : 87 : if (!TARGET_SSE4_1)
24828 : : return false;
24829 : : dstmode = V4SImode;
24830 : : pinsr = gen_sse4_1_pinsrd;
24831 : : break;
24832 : :
24833 : 0 : case E_DImode:
24834 : 0 : gcc_assert (TARGET_64BIT);
24835 : 0 : if (!TARGET_SSE4_1)
24836 : : return false;
24837 : : dstmode = V2DImode;
24838 : : pinsr = gen_sse4_1_pinsrq;
24839 : : break;
24840 : :
24841 : : default:
24842 : : return false;
24843 : : }
24844 : :
24845 : : /* Reject insertions to misaligned positions. */
24846 : 17 : if (pos & (size-1))
24847 : : return false;
24848 : :
24849 : 17 : if (SUBREG_P (src))
24850 : : {
24851 : 17 : unsigned int srcpos = SUBREG_BYTE (src);
24852 : :
24853 : 17 : if (srcpos > 0)
24854 : : {
24855 : 0 : rtx extr_ops[4];
24856 : :
24857 : 0 : extr_ops[0] = gen_reg_rtx (srcmode);
24858 : 0 : extr_ops[1] = gen_lowpart (srcmode, SUBREG_REG (src));
24859 : 0 : extr_ops[2] = GEN_INT (size);
24860 : 0 : extr_ops[3] = GEN_INT (srcpos * BITS_PER_UNIT);
24861 : :
24862 : 0 : if (!ix86_expand_pextr (extr_ops))
24863 : 0 : return false;
24864 : :
24865 : 0 : src = extr_ops[0];
24866 : : }
24867 : : else
24868 : 17 : src = gen_lowpart (srcmode, SUBREG_REG (src));
24869 : : }
24870 : :
24871 : 17 : if (GET_MODE (dst) == dstmode)
24872 : : d = dst;
24873 : : else
24874 : 17 : d = gen_reg_rtx (dstmode);
24875 : :
24876 : 17 : emit_insn (pinsr (d, gen_lowpart (dstmode, dst),
24877 : 17 : gen_lowpart (srcmode, src),
24878 : 17 : GEN_INT (1 << (pos / size))));
24879 : 17 : if (d != dst)
24880 : 17 : emit_move_insn (dst, gen_lowpart (GET_MODE (dst), d));
24881 : : return true;
24882 : : }
24883 : :
24884 : : default:
24885 : : return false;
24886 : : }
24887 : : }
24888 : :
24889 : : /* All CPUs prefer to avoid cross-lane operations so perform reductions
24890 : : upper against lower halves up to SSE reg size. */
24891 : :
24892 : : machine_mode
24893 : 3283 : ix86_split_reduction (machine_mode mode)
24894 : : {
24895 : : /* Reduce lowpart against highpart until we reach SSE reg width to
24896 : : avoid cross-lane operations. */
24897 : 3283 : switch (mode)
24898 : : {
24899 : : case E_V8DImode:
24900 : : case E_V4DImode:
24901 : : return V2DImode;
24902 : 11 : case E_V16SImode:
24903 : 11 : case E_V8SImode:
24904 : 11 : return V4SImode;
24905 : 12 : case E_V32HImode:
24906 : 12 : case E_V16HImode:
24907 : 12 : return V8HImode;
24908 : 8 : case E_V64QImode:
24909 : 8 : case E_V32QImode:
24910 : 8 : return V16QImode;
24911 : 89 : case E_V16SFmode:
24912 : 89 : case E_V8SFmode:
24913 : 89 : return V4SFmode;
24914 : 89 : case E_V8DFmode:
24915 : 89 : case E_V4DFmode:
24916 : 89 : return V2DFmode;
24917 : 3074 : default:
24918 : 3074 : return mode;
24919 : : }
24920 : : }
24921 : :
24922 : : /* Generate call to __divmoddi4. */
24923 : :
24924 : : void
24925 : 894 : ix86_expand_divmod_libfunc (rtx libfunc, machine_mode mode,
24926 : : rtx op0, rtx op1,
24927 : : rtx *quot_p, rtx *rem_p)
24928 : : {
24929 : 894 : rtx rem = assign_386_stack_local (mode, SLOT_TEMP);
24930 : :
24931 : 894 : rtx quot = emit_library_call_value (libfunc, NULL_RTX, LCT_NORMAL,
24932 : : mode, op0, mode, op1, mode,
24933 : 894 : XEXP (rem, 0), Pmode);
24934 : 894 : *quot_p = quot;
24935 : 894 : *rem_p = rem;
24936 : 894 : }
24937 : :
24938 : : void
24939 : 64 : ix86_expand_atomic_fetch_op_loop (rtx target, rtx mem, rtx val,
24940 : : enum rtx_code code, bool after,
24941 : : bool doubleword)
24942 : : {
24943 : 64 : rtx old_reg, new_reg, old_mem, success;
24944 : 64 : machine_mode mode = GET_MODE (target);
24945 : 64 : rtx_code_label *loop_label = NULL;
24946 : :
24947 : 64 : old_reg = gen_reg_rtx (mode);
24948 : 64 : new_reg = old_reg;
24949 : 64 : old_mem = copy_to_reg (mem);
24950 : 64 : loop_label = gen_label_rtx ();
24951 : 64 : emit_label (loop_label);
24952 : 64 : emit_move_insn (old_reg, old_mem);
24953 : :
24954 : : /* return value for atomic_fetch_op. */
24955 : 64 : if (!after)
24956 : 32 : emit_move_insn (target, old_reg);
24957 : :
24958 : 64 : if (code == NOT)
24959 : : {
24960 : 16 : new_reg = expand_simple_binop (mode, AND, new_reg, val, NULL_RTX,
24961 : : true, OPTAB_LIB_WIDEN);
24962 : 16 : new_reg = expand_simple_unop (mode, code, new_reg, NULL_RTX, true);
24963 : : }
24964 : : else
24965 : 48 : new_reg = expand_simple_binop (mode, code, new_reg, val, NULL_RTX,
24966 : : true, OPTAB_LIB_WIDEN);
24967 : :
24968 : : /* return value for atomic_op_fetch. */
24969 : 64 : if (after)
24970 : 32 : emit_move_insn (target, new_reg);
24971 : :
24972 : 64 : success = NULL_RTX;
24973 : :
24974 : 64 : ix86_expand_cmpxchg_loop (&success, old_mem, mem, old_reg, new_reg,
24975 : 64 : gen_int_mode (MEMMODEL_SYNC_SEQ_CST,
24976 : : SImode),
24977 : : doubleword, loop_label);
24978 : 64 : }
24979 : :
24980 : : /* Relax cmpxchg instruction, param loop_label indicates whether
24981 : : the instruction should be relaxed with a pause loop. If not,
24982 : : it will be relaxed to an atomic load + compare, and skip
24983 : : cmpxchg instruction if mem != exp_input. */
24984 : :
24985 : : void
24986 : 72 : ix86_expand_cmpxchg_loop (rtx *ptarget_bool, rtx target_val,
24987 : : rtx mem, rtx exp_input, rtx new_input,
24988 : : rtx mem_model, bool doubleword,
24989 : : rtx_code_label *loop_label)
24990 : : {
24991 : 72 : rtx_code_label *cmp_label = NULL;
24992 : 72 : rtx_code_label *done_label = NULL;
24993 : 72 : rtx target_bool = NULL_RTX, new_mem = NULL_RTX;
24994 : 72 : rtx (*gen) (rtx, rtx, rtx, rtx, rtx) = NULL;
24995 : 72 : rtx (*gendw) (rtx, rtx, rtx, rtx, rtx, rtx) = NULL;
24996 : 72 : machine_mode mode = GET_MODE (target_val), hmode = mode;
24997 : :
24998 : 72 : if (*ptarget_bool == NULL)
24999 : 64 : target_bool = gen_reg_rtx (QImode);
25000 : : else
25001 : : target_bool = *ptarget_bool;
25002 : :
25003 : 72 : cmp_label = gen_label_rtx ();
25004 : 72 : done_label = gen_label_rtx ();
25005 : :
25006 : 72 : new_mem = gen_reg_rtx (mode);
25007 : : /* Load memory first. */
25008 : 72 : expand_atomic_load (new_mem, mem, MEMMODEL_SEQ_CST);
25009 : :
25010 : 72 : switch (mode)
25011 : : {
25012 : : case E_TImode:
25013 : : gendw = gen_atomic_compare_and_swapti_doubleword;
25014 : : hmode = DImode;
25015 : : break;
25016 : 18 : case E_DImode:
25017 : 18 : if (doubleword)
25018 : : {
25019 : : gendw = gen_atomic_compare_and_swapdi_doubleword;
25020 : : hmode = SImode;
25021 : : }
25022 : : else
25023 : 18 : gen = gen_atomic_compare_and_swapdi_1;
25024 : : break;
25025 : 18 : case E_SImode:
25026 : 18 : gen = gen_atomic_compare_and_swapsi_1;
25027 : 18 : break;
25028 : 18 : case E_HImode:
25029 : 18 : gen = gen_atomic_compare_and_swaphi_1;
25030 : 18 : break;
25031 : 18 : case E_QImode:
25032 : 18 : gen = gen_atomic_compare_and_swapqi_1;
25033 : 18 : break;
25034 : 0 : default:
25035 : 0 : gcc_unreachable ();
25036 : : }
25037 : :
25038 : : /* Compare mem value with expected value. */
25039 : 72 : if (doubleword)
25040 : : {
25041 : 0 : rtx low_new_mem = gen_lowpart (hmode, new_mem);
25042 : 0 : rtx low_exp_input = gen_lowpart (hmode, exp_input);
25043 : 0 : rtx high_new_mem = gen_highpart (hmode, new_mem);
25044 : 0 : rtx high_exp_input = gen_highpart (hmode, exp_input);
25045 : 0 : emit_cmp_and_jump_insns (low_new_mem, low_exp_input, NE, NULL_RTX,
25046 : : hmode, 1, cmp_label,
25047 : : profile_probability::guessed_never ());
25048 : 0 : emit_cmp_and_jump_insns (high_new_mem, high_exp_input, NE, NULL_RTX,
25049 : : hmode, 1, cmp_label,
25050 : : profile_probability::guessed_never ());
25051 : : }
25052 : : else
25053 : 72 : emit_cmp_and_jump_insns (new_mem, exp_input, NE, NULL_RTX,
25054 : 72 : GET_MODE (exp_input), 1, cmp_label,
25055 : : profile_probability::guessed_never ());
25056 : :
25057 : : /* Directly emits cmpxchg here. */
25058 : 72 : if (doubleword)
25059 : 0 : emit_insn (gendw (target_val, mem, exp_input,
25060 : 0 : gen_lowpart (hmode, new_input),
25061 : : gen_highpart (hmode, new_input),
25062 : : mem_model));
25063 : : else
25064 : 72 : emit_insn (gen (target_val, mem, exp_input, new_input, mem_model));
25065 : :
25066 : 72 : if (!loop_label)
25067 : : {
25068 : 8 : emit_jump_insn (gen_jump (done_label));
25069 : 8 : emit_barrier ();
25070 : 8 : emit_label (cmp_label);
25071 : 8 : emit_move_insn (target_val, new_mem);
25072 : 8 : emit_label (done_label);
25073 : 8 : ix86_expand_setcc (target_bool, EQ, gen_rtx_REG (CCZmode, FLAGS_REG),
25074 : : const0_rtx);
25075 : : }
25076 : : else
25077 : : {
25078 : 64 : ix86_expand_setcc (target_bool, EQ, gen_rtx_REG (CCZmode, FLAGS_REG),
25079 : : const0_rtx);
25080 : 64 : emit_cmp_and_jump_insns (target_bool, const0_rtx, EQ, const0_rtx,
25081 : 64 : GET_MODE (target_bool), 1, loop_label,
25082 : : profile_probability::guessed_never ());
25083 : 64 : emit_jump_insn (gen_jump (done_label));
25084 : 64 : emit_barrier ();
25085 : :
25086 : : /* If mem is not expected, pause and loop back. */
25087 : 64 : emit_label (cmp_label);
25088 : 64 : emit_move_insn (target_val, new_mem);
25089 : 64 : emit_insn (gen_pause ());
25090 : 64 : emit_jump_insn (gen_jump (loop_label));
25091 : 64 : emit_barrier ();
25092 : 64 : emit_label (done_label);
25093 : : }
25094 : :
25095 : 72 : *ptarget_bool = target_bool;
25096 : 72 : }
25097 : :
25098 : : /* Convert a BFmode VAL to SFmode without signaling sNaNs.
25099 : : This is done by returning SF SUBREG of ((HI SUBREG) (VAL)) << 16. */
25100 : :
25101 : : rtx
25102 : 1360 : ix86_expand_fast_convert_bf_to_sf (rtx val)
25103 : : {
25104 : 1360 : rtx op = gen_lowpart (HImode, val), ret;
25105 : 1360 : if (CONST_INT_P (op))
25106 : : {
25107 : 332 : ret = simplify_const_unary_operation (FLOAT_EXTEND, SFmode,
25108 : : val, BFmode);
25109 : 332 : if (ret)
25110 : : return ret;
25111 : : /* FLOAT_EXTEND simplification will fail if VAL is a sNaN. */
25112 : 1 : ret = gen_reg_rtx (SImode);
25113 : 1 : emit_move_insn (ret, GEN_INT (INTVAL (op) & 0xffff));
25114 : 1 : emit_insn (gen_ashlsi3 (ret, ret, GEN_INT (16)));
25115 : 1 : return gen_lowpart (SFmode, ret);
25116 : : }
25117 : :
25118 : 1028 : ret = gen_reg_rtx (SFmode);
25119 : 1028 : emit_insn (gen_extendbfsf2_1 (ret, force_reg (BFmode, val)));
25120 : 1028 : return ret;
25121 : : }
25122 : :
25123 : : #include "gt-i386-expand.h"
|