]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/tree-vect-generic.c
tree-ssa.h: Remove all #include's
[thirdparty/gcc.git] / gcc / tree-vect-generic.c
CommitLineData
2b725155 1/* Lower vector operations to scalar operations.
d1e082c2 2 Copyright (C) 2004-2013 Free Software Foundation, Inc.
2b725155
RH
3
4This file is part of GCC.
b8698a0f 5
2b725155
RH
6GCC is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
9dcd6f09 8Free Software Foundation; either version 3, or (at your option) any
2b725155 9later version.
b8698a0f 10
2b725155
RH
11GCC is distributed in the hope that it will be useful, but WITHOUT
12ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14for more details.
b8698a0f 15
2b725155 16You should have received a copy of the GNU General Public License
9dcd6f09
NC
17along with GCC; see the file COPYING3. If not see
18<http://www.gnu.org/licenses/>. */
2b725155
RH
19
20#include "config.h"
21#include "system.h"
22#include "coretypes.h"
23#include "tree.h"
24#include "tm.h"
2b725155 25#include "langhooks.h"
726a989a 26#include "gimple.h"
442b4905
AM
27#include "gimple-ssa.h"
28#include "tree-cfg.h"
29#include "tree-ssanames.h"
2b725155
RH
30#include "tree-iterator.h"
31#include "tree-pass.h"
32#include "flags.h"
33#include "ggc.h"
f90e8e2e 34#include "diagnostic.h"
0fcc85cd 35#include "target.h"
2b725155 36
2eb79bbb
SB
37/* Need to include rtl.h, expr.h, etc. for optabs. */
38#include "expr.h"
39#include "optabs.h"
2b725155 40
d246ab4f
AS
41
42static void expand_vector_operations_1 (gimple_stmt_iterator *);
43
44
2b725155
RH
45/* Build a constant of type TYPE, made of VALUE's bits replicated
46 every TYPE_SIZE (INNER_TYPE) bits to fit TYPE's precision. */
47static tree
48build_replicated_const (tree type, tree inner_type, HOST_WIDE_INT value)
49{
50 int width = tree_low_cst (TYPE_SIZE (inner_type), 1);
51 int n = HOST_BITS_PER_WIDE_INT / width;
52 unsigned HOST_WIDE_INT low, high, mask;
53 tree ret;
54
55 gcc_assert (n);
56
57 if (width == HOST_BITS_PER_WIDE_INT)
58 low = value;
59 else
60 {
61 mask = ((HOST_WIDE_INT)1 << width) - 1;
62 low = (unsigned HOST_WIDE_INT) ~0 / mask * (value & mask);
63 }
64
65 if (TYPE_PRECISION (type) < HOST_BITS_PER_WIDE_INT)
66 low &= ((HOST_WIDE_INT)1 << TYPE_PRECISION (type)) - 1, high = 0;
67 else if (TYPE_PRECISION (type) == HOST_BITS_PER_WIDE_INT)
68 high = 0;
49ab6098 69 else if (TYPE_PRECISION (type) == HOST_BITS_PER_DOUBLE_INT)
2b725155
RH
70 high = low;
71 else
72 gcc_unreachable ();
73
74 ret = build_int_cst_wide (type, low, high);
75 return ret;
76}
77
78static GTY(()) tree vector_inner_type;
79static GTY(()) tree vector_last_type;
80static GTY(()) int vector_last_nunits;
81
82/* Return a suitable vector types made of SUBPARTS units each of mode
83 "word_mode" (the global variable). */
84static tree
85build_word_mode_vector_type (int nunits)
86{
87 if (!vector_inner_type)
88 vector_inner_type = lang_hooks.types.type_for_mode (word_mode, 1);
89 else if (vector_last_nunits == nunits)
90 {
91 gcc_assert (TREE_CODE (vector_last_type) == VECTOR_TYPE);
92 return vector_last_type;
93 }
94
95 /* We build a new type, but we canonicalize it nevertheless,
96 because it still saves some memory. */
97 vector_last_nunits = nunits;
98 vector_last_type = type_hash_canon (nunits,
99 build_vector_type (vector_inner_type,
100 nunits));
101 return vector_last_type;
102}
103
726a989a 104typedef tree (*elem_op_func) (gimple_stmt_iterator *,
2b725155
RH
105 tree, tree, tree, tree, tree, enum tree_code);
106
107static inline tree
726a989a 108tree_vec_extract (gimple_stmt_iterator *gsi, tree type,
2b725155
RH
109 tree t, tree bitsize, tree bitpos)
110{
111 if (bitpos)
726a989a 112 return gimplify_build3 (gsi, BIT_FIELD_REF, type, t, bitsize, bitpos);
2b725155 113 else
726a989a 114 return gimplify_build1 (gsi, VIEW_CONVERT_EXPR, type, t);
2b725155
RH
115}
116
117static tree
726a989a 118do_unop (gimple_stmt_iterator *gsi, tree inner_type, tree a,
2b725155
RH
119 tree b ATTRIBUTE_UNUSED, tree bitpos, tree bitsize,
120 enum tree_code code)
121{
726a989a
RB
122 a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
123 return gimplify_build1 (gsi, code, inner_type, a);
2b725155
RH
124}
125
126static tree
726a989a 127do_binop (gimple_stmt_iterator *gsi, tree inner_type, tree a, tree b,
2b725155
RH
128 tree bitpos, tree bitsize, enum tree_code code)
129{
362235e9
RG
130 if (TREE_CODE (TREE_TYPE (a)) == VECTOR_TYPE)
131 a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
132 if (TREE_CODE (TREE_TYPE (b)) == VECTOR_TYPE)
133 b = tree_vec_extract (gsi, inner_type, b, bitsize, bitpos);
726a989a 134 return gimplify_build2 (gsi, code, inner_type, a, b);
2b725155
RH
135}
136
d246ab4f
AS
137/* Construct expression (A[BITPOS] code B[BITPOS]) ? -1 : 0
138
139 INNER_TYPE is the type of A and B elements
140
141 returned expression is of signed integer type with the
142 size equal to the size of INNER_TYPE. */
143static tree
144do_compare (gimple_stmt_iterator *gsi, tree inner_type, tree a, tree b,
145 tree bitpos, tree bitsize, enum tree_code code)
146{
147 tree comp_type;
148
149 a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
150 b = tree_vec_extract (gsi, inner_type, b, bitsize, bitpos);
151
152 comp_type = build_nonstandard_integer_type
153 (GET_MODE_BITSIZE (TYPE_MODE (inner_type)), 0);
154
155 return gimplify_build3 (gsi, COND_EXPR, comp_type,
156 fold_build2 (code, boolean_type_node, a, b),
157 build_int_cst (comp_type, -1),
158 build_int_cst (comp_type, 0));
159}
160
2b725155
RH
161/* Expand vector addition to scalars. This does bit twiddling
162 in order to increase parallelism:
163
164 a + b = (((int) a & 0x7f7f7f7f) + ((int) b & 0x7f7f7f7f)) ^
165 (a ^ b) & 0x80808080
166
167 a - b = (((int) a | 0x80808080) - ((int) b & 0x7f7f7f7f)) ^
168 (a ^ ~b) & 0x80808080
169
170 -b = (0x80808080 - ((int) b & 0x7f7f7f7f)) ^ (~b & 0x80808080)
171
172 This optimization should be done only if 4 vector items or more
173 fit into a word. */
174static tree
726a989a 175do_plus_minus (gimple_stmt_iterator *gsi, tree word_type, tree a, tree b,
2b725155
RH
176 tree bitpos ATTRIBUTE_UNUSED, tree bitsize ATTRIBUTE_UNUSED,
177 enum tree_code code)
178{
179 tree inner_type = TREE_TYPE (TREE_TYPE (a));
180 unsigned HOST_WIDE_INT max;
181 tree low_bits, high_bits, a_low, b_low, result_low, signs;
182
183 max = GET_MODE_MASK (TYPE_MODE (inner_type));
184 low_bits = build_replicated_const (word_type, inner_type, max >> 1);
185 high_bits = build_replicated_const (word_type, inner_type, max & ~(max >> 1));
186
726a989a
RB
187 a = tree_vec_extract (gsi, word_type, a, bitsize, bitpos);
188 b = tree_vec_extract (gsi, word_type, b, bitsize, bitpos);
2b725155 189
726a989a
RB
190 signs = gimplify_build2 (gsi, BIT_XOR_EXPR, word_type, a, b);
191 b_low = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, b, low_bits);
2b725155 192 if (code == PLUS_EXPR)
726a989a 193 a_low = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, a, low_bits);
2b725155
RH
194 else
195 {
726a989a
RB
196 a_low = gimplify_build2 (gsi, BIT_IOR_EXPR, word_type, a, high_bits);
197 signs = gimplify_build1 (gsi, BIT_NOT_EXPR, word_type, signs);
2b725155
RH
198 }
199
726a989a
RB
200 signs = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, signs, high_bits);
201 result_low = gimplify_build2 (gsi, code, word_type, a_low, b_low);
202 return gimplify_build2 (gsi, BIT_XOR_EXPR, word_type, result_low, signs);
2b725155
RH
203}
204
205static tree
726a989a 206do_negate (gimple_stmt_iterator *gsi, tree word_type, tree b,
2b725155
RH
207 tree unused ATTRIBUTE_UNUSED, tree bitpos ATTRIBUTE_UNUSED,
208 tree bitsize ATTRIBUTE_UNUSED,
209 enum tree_code code ATTRIBUTE_UNUSED)
210{
211 tree inner_type = TREE_TYPE (TREE_TYPE (b));
212 HOST_WIDE_INT max;
213 tree low_bits, high_bits, b_low, result_low, signs;
214
215 max = GET_MODE_MASK (TYPE_MODE (inner_type));
216 low_bits = build_replicated_const (word_type, inner_type, max >> 1);
217 high_bits = build_replicated_const (word_type, inner_type, max & ~(max >> 1));
218
726a989a 219 b = tree_vec_extract (gsi, word_type, b, bitsize, bitpos);
2b725155 220
726a989a
RB
221 b_low = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, b, low_bits);
222 signs = gimplify_build1 (gsi, BIT_NOT_EXPR, word_type, b);
223 signs = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, signs, high_bits);
224 result_low = gimplify_build2 (gsi, MINUS_EXPR, word_type, high_bits, b_low);
225 return gimplify_build2 (gsi, BIT_XOR_EXPR, word_type, result_low, signs);
2b725155
RH
226}
227
228/* Expand a vector operation to scalars, by using many operations
229 whose type is the vector type's inner type. */
230static tree
726a989a 231expand_vector_piecewise (gimple_stmt_iterator *gsi, elem_op_func f,
2b725155
RH
232 tree type, tree inner_type,
233 tree a, tree b, enum tree_code code)
234{
9771b263 235 vec<constructor_elt, va_gc> *v;
2b725155
RH
236 tree part_width = TYPE_SIZE (inner_type);
237 tree index = bitsize_int (0);
238 int nunits = TYPE_VECTOR_SUBPARTS (type);
239 int delta = tree_low_cst (part_width, 1)
240 / tree_low_cst (TYPE_SIZE (TREE_TYPE (type)), 1);
241 int i;
cdbb5ba3
AS
242 location_t loc = gimple_location (gsi_stmt (*gsi));
243
244 if (types_compatible_p (gimple_expr_type (gsi_stmt (*gsi)), type))
245 warning_at (loc, OPT_Wvector_operation_performance,
246 "vector operation will be expanded piecewise");
247 else
248 warning_at (loc, OPT_Wvector_operation_performance,
249 "vector operation will be expanded in parallel");
2b725155 250
9771b263 251 vec_alloc (v, (nunits + delta - 1) / delta);
2b725155 252 for (i = 0; i < nunits;
d35936ab 253 i += delta, index = int_const_binop (PLUS_EXPR, index, part_width))
2b725155 254 {
726a989a 255 tree result = f (gsi, inner_type, a, b, index, part_width, code);
f32682ca 256 constructor_elt ce = {NULL_TREE, result};
9771b263 257 v->quick_push (ce);
2b725155
RH
258 }
259
4038c495 260 return build_constructor (type, v);
2b725155
RH
261}
262
263/* Expand a vector operation to scalars with the freedom to use
264 a scalar integer type, or to use a different size for the items
265 in the vector type. */
266static tree
726a989a 267expand_vector_parallel (gimple_stmt_iterator *gsi, elem_op_func f, tree type,
2b725155
RH
268 tree a, tree b,
269 enum tree_code code)
270{
271 tree result, compute_type;
272 enum machine_mode mode;
273 int n_words = tree_low_cst (TYPE_SIZE_UNIT (type), 1) / UNITS_PER_WORD;
cdbb5ba3 274 location_t loc = gimple_location (gsi_stmt (*gsi));
2b725155
RH
275
276 /* We have three strategies. If the type is already correct, just do
277 the operation an element at a time. Else, if the vector is wider than
278 one word, do it a word at a time; finally, if the vector is smaller
279 than one word, do it as a scalar. */
280 if (TYPE_MODE (TREE_TYPE (type)) == word_mode)
726a989a 281 return expand_vector_piecewise (gsi, f,
2b725155
RH
282 type, TREE_TYPE (type),
283 a, b, code);
284 else if (n_words > 1)
285 {
286 tree word_type = build_word_mode_vector_type (n_words);
726a989a 287 result = expand_vector_piecewise (gsi, f,
2b725155
RH
288 word_type, TREE_TYPE (word_type),
289 a, b, code);
726a989a
RB
290 result = force_gimple_operand_gsi (gsi, result, true, NULL, true,
291 GSI_SAME_STMT);
2b725155
RH
292 }
293 else
294 {
295 /* Use a single scalar operation with a mode no wider than word_mode. */
296 mode = mode_for_size (tree_low_cst (TYPE_SIZE (type), 1), MODE_INT, 0);
297 compute_type = lang_hooks.types.type_for_mode (mode, 1);
726a989a 298 result = f (gsi, compute_type, a, b, NULL_TREE, NULL_TREE, code);
cdbb5ba3
AS
299 warning_at (loc, OPT_Wvector_operation_performance,
300 "vector operation will be expanded with a "
301 "single scalar operation");
2b725155
RH
302 }
303
304 return result;
305}
306
307/* Expand a vector operation to scalars; for integer types we can use
308 special bit twiddling tricks to do the sums a word at a time, using
309 function F_PARALLEL instead of F. These tricks are done only if
310 they can process at least four items, that is, only if the vector
311 holds at least four items and if a word can hold four items. */
312static tree
726a989a 313expand_vector_addition (gimple_stmt_iterator *gsi,
2b725155
RH
314 elem_op_func f, elem_op_func f_parallel,
315 tree type, tree a, tree b, enum tree_code code)
316{
317 int parts_per_word = UNITS_PER_WORD
318 / tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (type)), 1);
319
320 if (INTEGRAL_TYPE_P (TREE_TYPE (type))
321 && parts_per_word >= 4
322 && TYPE_VECTOR_SUBPARTS (type) >= 4)
726a989a 323 return expand_vector_parallel (gsi, f_parallel,
2b725155
RH
324 type, a, b, code);
325 else
726a989a 326 return expand_vector_piecewise (gsi, f,
2b725155
RH
327 type, TREE_TYPE (type),
328 a, b, code);
329}
330
d246ab4f
AS
331/* Try to expand vector comparison expression OP0 CODE OP1 by
332 querying optab if the following expression:
333 VEC_COND_EXPR< OP0 CODE OP1, {-1,...}, {0,...}>
334 can be expanded. */
335static tree
336expand_vector_comparison (gimple_stmt_iterator *gsi, tree type, tree op0,
337 tree op1, enum tree_code code)
338{
339 tree t;
340 if (! expand_vec_cond_expr_p (type, TREE_TYPE (op0)))
341 t = expand_vector_piecewise (gsi, do_compare, type,
342 TREE_TYPE (TREE_TYPE (op0)), op0, op1, code);
343 else
344 t = NULL_TREE;
345
346 return t;
347}
348
4ee4c52c
JJ
349/* Helper function of expand_vector_divmod. Gimplify a RSHIFT_EXPR in type
350 of OP0 with shift counts in SHIFTCNTS array and return the temporary holding
351 the result if successful, otherwise return NULL_TREE. */
352static tree
353add_rshift (gimple_stmt_iterator *gsi, tree type, tree op0, int *shiftcnts)
354{
355 optab op;
356 unsigned int i, nunits = TYPE_VECTOR_SUBPARTS (type);
357 bool scalar_shift = true;
358
359 for (i = 1; i < nunits; i++)
360 {
361 if (shiftcnts[i] != shiftcnts[0])
362 scalar_shift = false;
363 }
364
365 if (scalar_shift && shiftcnts[0] == 0)
366 return op0;
367
368 if (scalar_shift)
369 {
370 op = optab_for_tree_code (RSHIFT_EXPR, type, optab_scalar);
2225b9f2 371 if (op != unknown_optab
4ee4c52c
JJ
372 && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
373 return gimplify_build2 (gsi, RSHIFT_EXPR, type, op0,
374 build_int_cst (NULL_TREE, shiftcnts[0]));
375 }
376
377 op = optab_for_tree_code (RSHIFT_EXPR, type, optab_vector);
2225b9f2 378 if (op != unknown_optab
4ee4c52c
JJ
379 && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
380 {
381 tree *vec = XALLOCAVEC (tree, nunits);
382 for (i = 0; i < nunits; i++)
383 vec[i] = build_int_cst (TREE_TYPE (type), shiftcnts[i]);
384 return gimplify_build2 (gsi, RSHIFT_EXPR, type, op0,
385 build_vector (type, vec));
386 }
387
388 return NULL_TREE;
389}
390
391/* Try to expand integer vector division by constant using
392 widening multiply, shifts and additions. */
393static tree
394expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, tree op0,
395 tree op1, enum tree_code code)
396{
397 bool use_pow2 = true;
398 bool has_vector_shift = true;
399 int mode = -1, this_mode;
400 int pre_shift = -1, post_shift;
401 unsigned int nunits = TYPE_VECTOR_SUBPARTS (type);
402 int *shifts = XALLOCAVEC (int, nunits * 4);
403 int *pre_shifts = shifts + nunits;
404 int *post_shifts = pre_shifts + nunits;
405 int *shift_temps = post_shifts + nunits;
406 unsigned HOST_WIDE_INT *mulc = XALLOCAVEC (unsigned HOST_WIDE_INT, nunits);
407 int prec = TYPE_PRECISION (TREE_TYPE (type));
408 int dummy_int;
409 unsigned int i, unsignedp = TYPE_UNSIGNED (TREE_TYPE (type));
410 unsigned HOST_WIDE_INT mask = GET_MODE_MASK (TYPE_MODE (TREE_TYPE (type)));
4ee4c52c 411 tree *vec;
00f07b86
RH
412 tree cur_op, mulcst, tem;
413 optab op;
4ee4c52c
JJ
414
415 if (prec > HOST_BITS_PER_WIDE_INT)
416 return NULL_TREE;
417
418 op = optab_for_tree_code (RSHIFT_EXPR, type, optab_vector);
2225b9f2 419 if (op == unknown_optab
4ee4c52c
JJ
420 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
421 has_vector_shift = false;
422
423 /* Analysis phase. Determine if all op1 elements are either power
424 of two and it is possible to expand it using shifts (or for remainder
425 using masking). Additionally compute the multiplicative constants
426 and pre and post shifts if the division is to be expanded using
427 widening or high part multiplication plus shifts. */
428 for (i = 0; i < nunits; i++)
429 {
430 tree cst = VECTOR_CST_ELT (op1, i);
431 unsigned HOST_WIDE_INT ml;
432
433 if (!host_integerp (cst, unsignedp) || integer_zerop (cst))
434 return NULL_TREE;
435 pre_shifts[i] = 0;
436 post_shifts[i] = 0;
437 mulc[i] = 0;
438 if (use_pow2
439 && (!integer_pow2p (cst) || tree_int_cst_sgn (cst) != 1))
440 use_pow2 = false;
441 if (use_pow2)
442 {
443 shifts[i] = tree_log2 (cst);
444 if (shifts[i] != shifts[0]
445 && code == TRUNC_DIV_EXPR
446 && !has_vector_shift)
447 use_pow2 = false;
448 }
449 if (mode == -2)
450 continue;
451 if (unsignedp)
452 {
453 unsigned HOST_WIDE_INT mh;
454 unsigned HOST_WIDE_INT d = tree_low_cst (cst, 1) & mask;
455
456 if (d >= ((unsigned HOST_WIDE_INT) 1 << (prec - 1)))
457 /* FIXME: Can transform this into op0 >= op1 ? 1 : 0. */
458 return NULL_TREE;
459
460 if (d <= 1)
461 {
462 mode = -2;
463 continue;
464 }
465
466 /* Find a suitable multiplier and right shift count
467 instead of multiplying with D. */
468 mh = choose_multiplier (d, prec, prec, &ml, &post_shift, &dummy_int);
469
470 /* If the suggested multiplier is more than SIZE bits, we can
471 do better for even divisors, using an initial right shift. */
472 if ((mh != 0 && (d & 1) == 0)
473 || (!has_vector_shift && pre_shift != -1))
474 {
475 if (has_vector_shift)
476 pre_shift = floor_log2 (d & -d);
477 else if (pre_shift == -1)
478 {
479 unsigned int j;
480 for (j = 0; j < nunits; j++)
481 {
482 tree cst2 = VECTOR_CST_ELT (op1, j);
483 unsigned HOST_WIDE_INT d2;
484 int this_pre_shift;
485
486 if (!host_integerp (cst2, 1))
487 return NULL_TREE;
488 d2 = tree_low_cst (cst2, 1) & mask;
489 if (d2 == 0)
490 return NULL_TREE;
491 this_pre_shift = floor_log2 (d2 & -d2);
492 if (pre_shift == -1 || this_pre_shift < pre_shift)
493 pre_shift = this_pre_shift;
494 }
495 if (i != 0 && pre_shift != 0)
496 {
497 /* Restart. */
498 i = -1U;
499 mode = -1;
500 continue;
501 }
502 }
503 if (pre_shift != 0)
504 {
505 if ((d >> pre_shift) <= 1)
506 {
507 mode = -2;
508 continue;
509 }
510 mh = choose_multiplier (d >> pre_shift, prec,
511 prec - pre_shift,
512 &ml, &post_shift, &dummy_int);
513 gcc_assert (!mh);
514 pre_shifts[i] = pre_shift;
515 }
516 }
517 if (!mh)
518 this_mode = 0;
519 else
520 this_mode = 1;
521 }
522 else
523 {
524 HOST_WIDE_INT d = tree_low_cst (cst, 0);
525 unsigned HOST_WIDE_INT abs_d;
526
527 if (d == -1)
528 return NULL_TREE;
529
530 /* Since d might be INT_MIN, we have to cast to
531 unsigned HOST_WIDE_INT before negating to avoid
532 undefined signed overflow. */
533 abs_d = (d >= 0
534 ? (unsigned HOST_WIDE_INT) d
535 : - (unsigned HOST_WIDE_INT) d);
536
537 /* n rem d = n rem -d */
538 if (code == TRUNC_MOD_EXPR && d < 0)
539 d = abs_d;
540 else if (abs_d == (unsigned HOST_WIDE_INT) 1 << (prec - 1))
541 {
542 /* This case is not handled correctly below. */
543 mode = -2;
544 continue;
545 }
546 if (abs_d <= 1)
547 {
548 mode = -2;
549 continue;
550 }
551
552 choose_multiplier (abs_d, prec, prec - 1, &ml,
553 &post_shift, &dummy_int);
554 if (ml >= (unsigned HOST_WIDE_INT) 1 << (prec - 1))
555 {
556 this_mode = 4 + (d < 0);
557 ml |= (~(unsigned HOST_WIDE_INT) 0) << (prec - 1);
558 }
559 else
560 this_mode = 2 + (d < 0);
561 }
562 mulc[i] = ml;
563 post_shifts[i] = post_shift;
564 if ((i && !has_vector_shift && post_shifts[0] != post_shift)
565 || post_shift >= prec
566 || pre_shifts[i] >= prec)
567 this_mode = -2;
568
569 if (i == 0)
570 mode = this_mode;
571 else if (mode != this_mode)
572 mode = -2;
573 }
574
575 vec = XALLOCAVEC (tree, nunits);
576
577 if (use_pow2)
578 {
579 tree addend = NULL_TREE;
580 if (!unsignedp)
581 {
582 tree uns_type;
583
584 /* Both division and remainder sequences need
585 op0 < 0 ? mask : 0 computed. It can be either computed as
586 (type) (((uns_type) (op0 >> (prec - 1))) >> (prec - shifts[i]))
587 if none of the shifts is 0, or as the conditional. */
588 for (i = 0; i < nunits; i++)
589 if (shifts[i] == 0)
590 break;
591 uns_type
592 = build_vector_type (build_nonstandard_integer_type (prec, 1),
593 nunits);
594 if (i == nunits && TYPE_MODE (uns_type) == TYPE_MODE (type))
595 {
596 for (i = 0; i < nunits; i++)
597 shift_temps[i] = prec - 1;
598 cur_op = add_rshift (gsi, type, op0, shift_temps);
599 if (cur_op != NULL_TREE)
600 {
601 cur_op = gimplify_build1 (gsi, VIEW_CONVERT_EXPR,
602 uns_type, cur_op);
603 for (i = 0; i < nunits; i++)
604 shift_temps[i] = prec - shifts[i];
605 cur_op = add_rshift (gsi, uns_type, cur_op, shift_temps);
606 if (cur_op != NULL_TREE)
607 addend = gimplify_build1 (gsi, VIEW_CONVERT_EXPR,
608 type, cur_op);
609 }
610 }
611 if (addend == NULL_TREE
612 && expand_vec_cond_expr_p (type, type))
613 {
614 tree zero, cst, cond;
615 gimple stmt;
616
617 zero = build_zero_cst (type);
618 cond = build2 (LT_EXPR, type, op0, zero);
619 for (i = 0; i < nunits; i++)
620 vec[i] = build_int_cst (TREE_TYPE (type),
621 ((unsigned HOST_WIDE_INT) 1
622 << shifts[i]) - 1);
623 cst = build_vector (type, vec);
83d5977e 624 addend = make_ssa_name (type, NULL);
73804b12
RG
625 stmt = gimple_build_assign_with_ops (VEC_COND_EXPR, addend,
626 cond, cst, zero);
4ee4c52c
JJ
627 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
628 }
629 }
630 if (code == TRUNC_DIV_EXPR)
631 {
632 if (unsignedp)
633 {
634 /* q = op0 >> shift; */
635 cur_op = add_rshift (gsi, type, op0, shifts);
636 if (cur_op != NULL_TREE)
637 return cur_op;
638 }
639 else if (addend != NULL_TREE)
640 {
641 /* t1 = op0 + addend;
642 q = t1 >> shift; */
643 op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
2225b9f2 644 if (op != unknown_optab
4ee4c52c
JJ
645 && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
646 {
647 cur_op = gimplify_build2 (gsi, PLUS_EXPR, type, op0, addend);
648 cur_op = add_rshift (gsi, type, cur_op, shifts);
649 if (cur_op != NULL_TREE)
650 return cur_op;
651 }
652 }
653 }
654 else
655 {
656 tree mask;
657 for (i = 0; i < nunits; i++)
658 vec[i] = build_int_cst (TREE_TYPE (type),
659 ((unsigned HOST_WIDE_INT) 1
660 << shifts[i]) - 1);
661 mask = build_vector (type, vec);
662 op = optab_for_tree_code (BIT_AND_EXPR, type, optab_default);
2225b9f2 663 if (op != unknown_optab
4ee4c52c
JJ
664 && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
665 {
666 if (unsignedp)
667 /* r = op0 & mask; */
668 return gimplify_build2 (gsi, BIT_AND_EXPR, type, op0, mask);
669 else if (addend != NULL_TREE)
670 {
671 /* t1 = op0 + addend;
672 t2 = t1 & mask;
673 r = t2 - addend; */
674 op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
2225b9f2 675 if (op != unknown_optab
4ee4c52c
JJ
676 && optab_handler (op, TYPE_MODE (type))
677 != CODE_FOR_nothing)
678 {
679 cur_op = gimplify_build2 (gsi, PLUS_EXPR, type, op0,
680 addend);
681 cur_op = gimplify_build2 (gsi, BIT_AND_EXPR, type,
682 cur_op, mask);
683 op = optab_for_tree_code (MINUS_EXPR, type,
684 optab_default);
2225b9f2 685 if (op != unknown_optab
4ee4c52c
JJ
686 && optab_handler (op, TYPE_MODE (type))
687 != CODE_FOR_nothing)
688 return gimplify_build2 (gsi, MINUS_EXPR, type,
689 cur_op, addend);
690 }
691 }
692 }
693 }
694 }
695
696 if (mode == -2 || BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN)
697 return NULL_TREE;
698
00f07b86
RH
699 if (!can_mult_highpart_p (TYPE_MODE (type), TYPE_UNSIGNED (type)))
700 return NULL_TREE;
4ee4c52c
JJ
701
702 cur_op = op0;
703
704 switch (mode)
705 {
706 case 0:
707 gcc_assert (unsignedp);
708 /* t1 = oprnd0 >> pre_shift;
c9ba3307 709 t2 = t1 h* ml;
4ee4c52c
JJ
710 q = t2 >> post_shift; */
711 cur_op = add_rshift (gsi, type, cur_op, pre_shifts);
712 if (cur_op == NULL_TREE)
713 return NULL_TREE;
714 break;
715 case 1:
716 gcc_assert (unsignedp);
717 for (i = 0; i < nunits; i++)
718 {
719 shift_temps[i] = 1;
720 post_shifts[i]--;
721 }
722 break;
723 case 2:
724 case 3:
725 case 4:
726 case 5:
727 gcc_assert (!unsignedp);
728 for (i = 0; i < nunits; i++)
729 shift_temps[i] = prec - 1;
730 break;
731 default:
732 return NULL_TREE;
733 }
734
735 for (i = 0; i < nunits; i++)
736 vec[i] = build_int_cst (TREE_TYPE (type), mulc[i]);
737 mulcst = build_vector (type, vec);
0fcc85cd 738
00f07b86 739 cur_op = gimplify_build2 (gsi, MULT_HIGHPART_EXPR, type, cur_op, mulcst);
4ee4c52c
JJ
740
741 switch (mode)
742 {
743 case 0:
744 /* t1 = oprnd0 >> pre_shift;
c9ba3307 745 t2 = t1 h* ml;
4ee4c52c
JJ
746 q = t2 >> post_shift; */
747 cur_op = add_rshift (gsi, type, cur_op, post_shifts);
748 break;
749 case 1:
c9ba3307 750 /* t1 = oprnd0 h* ml;
4ee4c52c
JJ
751 t2 = oprnd0 - t1;
752 t3 = t2 >> 1;
753 t4 = t1 + t3;
754 q = t4 >> (post_shift - 1); */
755 op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
2225b9f2 756 if (op == unknown_optab
4ee4c52c
JJ
757 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
758 return NULL_TREE;
759 tem = gimplify_build2 (gsi, MINUS_EXPR, type, op0, cur_op);
760 tem = add_rshift (gsi, type, tem, shift_temps);
761 op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
2225b9f2 762 if (op == unknown_optab
4ee4c52c
JJ
763 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
764 return NULL_TREE;
765 tem = gimplify_build2 (gsi, PLUS_EXPR, type, cur_op, tem);
766 cur_op = add_rshift (gsi, type, tem, post_shifts);
767 if (cur_op == NULL_TREE)
768 return NULL_TREE;
769 break;
770 case 2:
771 case 3:
772 case 4:
773 case 5:
c9ba3307 774 /* t1 = oprnd0 h* ml;
4ee4c52c
JJ
775 t2 = t1; [ iff (mode & 2) != 0 ]
776 t2 = t1 + oprnd0; [ iff (mode & 2) == 0 ]
777 t3 = t2 >> post_shift;
778 t4 = oprnd0 >> (prec - 1);
779 q = t3 - t4; [ iff (mode & 1) == 0 ]
780 q = t4 - t3; [ iff (mode & 1) != 0 ] */
781 if ((mode & 2) == 0)
782 {
783 op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
2225b9f2 784 if (op == unknown_optab
4ee4c52c
JJ
785 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
786 return NULL_TREE;
787 cur_op = gimplify_build2 (gsi, PLUS_EXPR, type, cur_op, op0);
788 }
789 cur_op = add_rshift (gsi, type, cur_op, post_shifts);
790 if (cur_op == NULL_TREE)
791 return NULL_TREE;
792 tem = add_rshift (gsi, type, op0, shift_temps);
793 if (tem == NULL_TREE)
794 return NULL_TREE;
795 op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
2225b9f2 796 if (op == unknown_optab
4ee4c52c
JJ
797 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
798 return NULL_TREE;
799 if ((mode & 1) == 0)
800 cur_op = gimplify_build2 (gsi, MINUS_EXPR, type, cur_op, tem);
801 else
802 cur_op = gimplify_build2 (gsi, MINUS_EXPR, type, tem, cur_op);
803 break;
804 default:
805 gcc_unreachable ();
806 }
807
808 if (code == TRUNC_DIV_EXPR)
809 return cur_op;
810
811 /* We divided. Now finish by:
812 t1 = q * oprnd1;
813 r = oprnd0 - t1; */
814 op = optab_for_tree_code (MULT_EXPR, type, optab_default);
2225b9f2 815 if (op == unknown_optab
4ee4c52c
JJ
816 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
817 return NULL_TREE;
818 tem = gimplify_build2 (gsi, MULT_EXPR, type, cur_op, op1);
819 op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
2225b9f2 820 if (op == unknown_optab
4ee4c52c
JJ
821 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
822 return NULL_TREE;
823 return gimplify_build2 (gsi, MINUS_EXPR, type, op0, tem);
824}
825
374ab2d7
MG
826/* Expand a vector condition to scalars, by using many conditions
827 on the vector's elements. */
828static void
829expand_vector_condition (gimple_stmt_iterator *gsi)
830{
831 gimple stmt = gsi_stmt (*gsi);
832 tree type = gimple_expr_type (stmt);
833 tree a = gimple_assign_rhs1 (stmt);
834 tree a1 = a;
835 tree a2;
836 bool a_is_comparison = false;
837 tree b = gimple_assign_rhs2 (stmt);
838 tree c = gimple_assign_rhs3 (stmt);
9771b263 839 vec<constructor_elt, va_gc> *v;
374ab2d7
MG
840 tree constr;
841 tree inner_type = TREE_TYPE (type);
842 tree cond_type = TREE_TYPE (TREE_TYPE (a));
843 tree comp_inner_type = cond_type;
844 tree width = TYPE_SIZE (inner_type);
845 tree index = bitsize_int (0);
846 int nunits = TYPE_VECTOR_SUBPARTS (type);
847 int i;
848 location_t loc = gimple_location (gsi_stmt (*gsi));
849
784fb9b3 850 if (!is_gimple_val (a))
374ab2d7
MG
851 {
852 gcc_assert (COMPARISON_CLASS_P (a));
853 a_is_comparison = true;
854 a1 = TREE_OPERAND (a, 0);
855 a2 = TREE_OPERAND (a, 1);
856 comp_inner_type = TREE_TYPE (TREE_TYPE (a1));
857 }
858
859 if (expand_vec_cond_expr_p (type, TREE_TYPE (a1)))
860 return;
861
862 /* TODO: try and find a smaller vector type. */
863
864 warning_at (loc, OPT_Wvector_operation_performance,
865 "vector condition will be expanded piecewise");
866
9771b263 867 vec_alloc (v, nunits);
374ab2d7
MG
868 for (i = 0; i < nunits;
869 i++, index = int_const_binop (PLUS_EXPR, index, width))
870 {
871 tree aa, result;
872 tree bb = tree_vec_extract (gsi, inner_type, b, width, index);
873 tree cc = tree_vec_extract (gsi, inner_type, c, width, index);
874 if (a_is_comparison)
875 {
876 tree aa1 = tree_vec_extract (gsi, comp_inner_type, a1, width, index);
877 tree aa2 = tree_vec_extract (gsi, comp_inner_type, a2, width, index);
878 aa = build2 (TREE_CODE (a), cond_type, aa1, aa2);
879 }
880 else
881 aa = tree_vec_extract (gsi, cond_type, a, width, index);
882 result = gimplify_build3 (gsi, COND_EXPR, inner_type, aa, bb, cc);
883 constructor_elt ce = {NULL_TREE, result};
9771b263 884 v->quick_push (ce);
374ab2d7
MG
885 }
886
887 constr = build_constructor (type, v);
888 gimple_assign_set_rhs_from_tree (gsi, constr);
889 update_stmt (gsi_stmt (*gsi));
890}
891
2b725155 892static tree
726a989a
RB
893expand_vector_operation (gimple_stmt_iterator *gsi, tree type, tree compute_type,
894 gimple assign, enum tree_code code)
2b725155
RH
895{
896 enum machine_mode compute_mode = TYPE_MODE (compute_type);
897
898 /* If the compute mode is not a vector mode (hence we are not decomposing
899 a BLKmode vector to smaller, hardware-supported vectors), we may want
900 to expand the operations in parallel. */
901 if (GET_MODE_CLASS (compute_mode) != MODE_VECTOR_INT
325217ed
CF
902 && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_FLOAT
903 && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_FRACT
904 && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_UFRACT
905 && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_ACCUM
906 && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_UACCUM)
2b725155
RH
907 switch (code)
908 {
909 case PLUS_EXPR:
910 case MINUS_EXPR:
eeef0e45 911 if (!TYPE_OVERFLOW_TRAPS (type))
cdbb5ba3
AS
912 return expand_vector_addition (gsi, do_binop, do_plus_minus, type,
913 gimple_assign_rhs1 (assign),
726a989a 914 gimple_assign_rhs2 (assign), code);
2b725155
RH
915 break;
916
917 case NEGATE_EXPR:
eeef0e45 918 if (!TYPE_OVERFLOW_TRAPS (type))
726a989a
RB
919 return expand_vector_addition (gsi, do_unop, do_negate, type,
920 gimple_assign_rhs1 (assign),
2b725155
RH
921 NULL_TREE, code);
922 break;
923
924 case BIT_AND_EXPR:
925 case BIT_IOR_EXPR:
926 case BIT_XOR_EXPR:
726a989a
RB
927 return expand_vector_parallel (gsi, do_binop, type,
928 gimple_assign_rhs1 (assign),
929 gimple_assign_rhs2 (assign), code);
2b725155
RH
930
931 case BIT_NOT_EXPR:
726a989a
RB
932 return expand_vector_parallel (gsi, do_unop, type,
933 gimple_assign_rhs1 (assign),
d246ab4f
AS
934 NULL_TREE, code);
935 case EQ_EXPR:
936 case NE_EXPR:
937 case GT_EXPR:
938 case LT_EXPR:
939 case GE_EXPR:
940 case LE_EXPR:
941 case UNEQ_EXPR:
942 case UNGT_EXPR:
943 case UNLT_EXPR:
944 case UNGE_EXPR:
945 case UNLE_EXPR:
946 case LTGT_EXPR:
947 case ORDERED_EXPR:
948 case UNORDERED_EXPR:
949 {
950 tree rhs1 = gimple_assign_rhs1 (assign);
951 tree rhs2 = gimple_assign_rhs2 (assign);
2b725155 952
d246ab4f
AS
953 return expand_vector_comparison (gsi, type, rhs1, rhs2, code);
954 }
4ee4c52c
JJ
955
956 case TRUNC_DIV_EXPR:
957 case TRUNC_MOD_EXPR:
958 {
959 tree rhs1 = gimple_assign_rhs1 (assign);
960 tree rhs2 = gimple_assign_rhs2 (assign);
961 tree ret;
962
963 if (!optimize
964 || !VECTOR_INTEGER_TYPE_P (type)
965 || TREE_CODE (rhs2) != VECTOR_CST)
966 break;
967
968 ret = expand_vector_divmod (gsi, type, rhs1, rhs2, code);
969 if (ret != NULL_TREE)
970 return ret;
971 break;
972 }
973
2b725155
RH
974 default:
975 break;
976 }
977
978 if (TREE_CODE_CLASS (code) == tcc_unary)
726a989a
RB
979 return expand_vector_piecewise (gsi, do_unop, type, compute_type,
980 gimple_assign_rhs1 (assign),
2b725155
RH
981 NULL_TREE, code);
982 else
726a989a
RB
983 return expand_vector_piecewise (gsi, do_binop, type, compute_type,
984 gimple_assign_rhs1 (assign),
985 gimple_assign_rhs2 (assign), code);
2b725155
RH
986}
987\f
995ec132
RG
988/* Return a type for the widest vector mode whose components are of type
989 TYPE, or NULL_TREE if none is found. */
325217ed 990
2b725155 991static tree
995ec132 992type_for_widest_vector_mode (tree type, optab op)
2b725155 993{
995ec132 994 enum machine_mode inner_mode = TYPE_MODE (type);
2b725155
RH
995 enum machine_mode best_mode = VOIDmode, mode;
996 int best_nunits = 0;
997
3d8bf70f 998 if (SCALAR_FLOAT_MODE_P (inner_mode))
2b725155 999 mode = MIN_MODE_VECTOR_FLOAT;
325217ed
CF
1000 else if (SCALAR_FRACT_MODE_P (inner_mode))
1001 mode = MIN_MODE_VECTOR_FRACT;
1002 else if (SCALAR_UFRACT_MODE_P (inner_mode))
1003 mode = MIN_MODE_VECTOR_UFRACT;
1004 else if (SCALAR_ACCUM_MODE_P (inner_mode))
1005 mode = MIN_MODE_VECTOR_ACCUM;
1006 else if (SCALAR_UACCUM_MODE_P (inner_mode))
1007 mode = MIN_MODE_VECTOR_UACCUM;
2b725155
RH
1008 else
1009 mode = MIN_MODE_VECTOR_INT;
1010
1011 for (; mode != VOIDmode; mode = GET_MODE_WIDER_MODE (mode))
1012 if (GET_MODE_INNER (mode) == inner_mode
1013 && GET_MODE_NUNITS (mode) > best_nunits
947131ba 1014 && optab_handler (op, mode) != CODE_FOR_nothing)
2b725155
RH
1015 best_mode = mode, best_nunits = GET_MODE_NUNITS (mode);
1016
1017 if (best_mode == VOIDmode)
1018 return NULL_TREE;
1019 else
995ec132 1020 return build_vector_type_for_mode (type, best_mode);
2b725155
RH
1021}
1022
f90e8e2e
AS
1023
1024/* Build a reference to the element of the vector VECT. Function
1025 returns either the element itself, either BIT_FIELD_REF, or an
1026 ARRAY_REF expression.
1027
073a8998 1028 GSI is required to insert temporary variables while building a
f90e8e2e
AS
1029 refernece to the element of the vector VECT.
1030
1031 PTMPVEC is a pointer to the temporary variable for caching
1032 purposes. In case when PTMPVEC is NULL new temporary variable
1033 will be created. */
1034static tree
1035vector_element (gimple_stmt_iterator *gsi, tree vect, tree idx, tree *ptmpvec)
1036{
067f5960 1037 tree vect_type, vect_elt_type;
f90e8e2e
AS
1038 gimple asgn;
1039 tree tmpvec;
1040 tree arraytype;
1041 bool need_asgn = true;
067f5960 1042 unsigned int elements;
f90e8e2e 1043
067f5960
RH
1044 vect_type = TREE_TYPE (vect);
1045 vect_elt_type = TREE_TYPE (vect_type);
1046 elements = TYPE_VECTOR_SUBPARTS (vect_type);
f90e8e2e 1047
f90e8e2e
AS
1048 if (TREE_CODE (idx) == INTEGER_CST)
1049 {
1050 unsigned HOST_WIDE_INT index;
1051
067f5960
RH
1052 /* Given that we're about to compute a binary modulus,
1053 we don't care about the high bits of the value. */
1054 index = TREE_INT_CST_LOW (idx);
1055 if (!host_integerp (idx, 1) || index >= elements)
1056 {
1057 index &= elements - 1;
1058 idx = build_int_cst (TREE_TYPE (idx), index);
1059 }
f90e8e2e 1060
bc622b2a
RG
1061 /* When lowering a vector statement sequence do some easy
1062 simplification by looking through intermediate vector results. */
1063 if (TREE_CODE (vect) == SSA_NAME)
1064 {
1065 gimple def_stmt = SSA_NAME_DEF_STMT (vect);
1066 if (is_gimple_assign (def_stmt)
1067 && (gimple_assign_rhs_code (def_stmt) == VECTOR_CST
1068 || gimple_assign_rhs_code (def_stmt) == CONSTRUCTOR))
1069 vect = gimple_assign_rhs1 (def_stmt);
1070 }
1071
f90e8e2e 1072 if (TREE_CODE (vect) == VECTOR_CST)
d2a12ae7 1073 return VECTOR_CST_ELT (vect, index);
4a2c20cc
JJ
1074 else if (TREE_CODE (vect) == CONSTRUCTOR
1075 && (CONSTRUCTOR_NELTS (vect) == 0
1076 || TREE_CODE (TREE_TYPE (CONSTRUCTOR_ELT (vect, 0)->value))
1077 != VECTOR_TYPE))
f90e8e2e 1078 {
4a2c20cc
JJ
1079 if (index < CONSTRUCTOR_NELTS (vect))
1080 return CONSTRUCTOR_ELT (vect, index)->value;
067f5960 1081 return build_zero_cst (vect_elt_type);
f90e8e2e 1082 }
067f5960 1083 else
f90e8e2e 1084 {
067f5960 1085 tree size = TYPE_SIZE (vect_elt_type);
26a7fca2
JJ
1086 tree pos = fold_build2 (MULT_EXPR, bitsizetype, bitsize_int (index),
1087 size);
1088 return fold_build3 (BIT_FIELD_REF, vect_elt_type, vect, size, pos);
f90e8e2e 1089 }
f90e8e2e
AS
1090 }
1091
1092 if (!ptmpvec)
067f5960 1093 tmpvec = create_tmp_var (vect_type, "vectmp");
f90e8e2e 1094 else if (!*ptmpvec)
067f5960 1095 tmpvec = *ptmpvec = create_tmp_var (vect_type, "vectmp");
f90e8e2e
AS
1096 else
1097 {
1098 tmpvec = *ptmpvec;
1099 need_asgn = false;
1100 }
1101
1102 if (need_asgn)
1103 {
1104 TREE_ADDRESSABLE (tmpvec) = 1;
1105 asgn = gimple_build_assign (tmpvec, vect);
1106 gsi_insert_before (gsi, asgn, GSI_SAME_STMT);
1107 }
1108
067f5960
RH
1109 arraytype = build_array_type_nelts (vect_elt_type, elements);
1110 return build4 (ARRAY_REF, vect_elt_type,
f90e8e2e
AS
1111 build1 (VIEW_CONVERT_EXPR, arraytype, tmpvec),
1112 idx, NULL_TREE, NULL_TREE);
1113}
1114
2205ed25 1115/* Check if VEC_PERM_EXPR within the given setting is supported
067f5960 1116 by hardware, or lower it piecewise.
f90e8e2e 1117
2205ed25
RH
1118 When VEC_PERM_EXPR has the same first and second operands:
1119 VEC_PERM_EXPR <v0, v0, mask> the lowered version would be
f90e8e2e
AS
1120 {v0[mask[0]], v0[mask[1]], ...}
1121 MASK and V0 must have the same number of elements.
1122
2205ed25 1123 Otherwise VEC_PERM_EXPR <v0, v1, mask> is lowered to
f90e8e2e
AS
1124 {mask[0] < len(v0) ? v0[mask[0]] : v1[mask[0]], ...}
1125 V0 and V1 must have the same type. MASK, V0, V1 must have the
1126 same number of arguments. */
f90e8e2e 1127
067f5960 1128static void
2205ed25 1129lower_vec_perm (gimple_stmt_iterator *gsi)
067f5960 1130{
f90e8e2e
AS
1131 gimple stmt = gsi_stmt (*gsi);
1132 tree mask = gimple_assign_rhs3 (stmt);
1133 tree vec0 = gimple_assign_rhs1 (stmt);
1134 tree vec1 = gimple_assign_rhs2 (stmt);
067f5960
RH
1135 tree vect_type = TREE_TYPE (vec0);
1136 tree mask_type = TREE_TYPE (mask);
1137 tree vect_elt_type = TREE_TYPE (vect_type);
1138 tree mask_elt_type = TREE_TYPE (mask_type);
1139 unsigned int elements = TYPE_VECTOR_SUBPARTS (vect_type);
9771b263 1140 vec<constructor_elt, va_gc> *v;
067f5960
RH
1141 tree constr, t, si, i_val;
1142 tree vec0tmp = NULL_TREE, vec1tmp = NULL_TREE, masktmp = NULL_TREE;
1143 bool two_operand_p = !operand_equal_p (vec0, vec1, 0);
cdbb5ba3 1144 location_t loc = gimple_location (gsi_stmt (*gsi));
067f5960 1145 unsigned i;
f90e8e2e 1146
273d260f
RR
1147 if (TREE_CODE (mask) == SSA_NAME)
1148 {
1149 gimple def_stmt = SSA_NAME_DEF_STMT (mask);
1150 if (is_gimple_assign (def_stmt)
1151 && gimple_assign_rhs_code (def_stmt) == VECTOR_CST)
1152 mask = gimple_assign_rhs1 (def_stmt);
1153 }
1154
22e4dee7
RH
1155 if (TREE_CODE (mask) == VECTOR_CST)
1156 {
1157 unsigned char *sel_int = XALLOCAVEC (unsigned char, elements);
22e4dee7 1158
d2a12ae7
RG
1159 for (i = 0; i < elements; ++i)
1160 sel_int[i] = (TREE_INT_CST_LOW (VECTOR_CST_ELT (mask, i))
1161 & (2 * elements - 1));
22e4dee7
RH
1162
1163 if (can_vec_perm_p (TYPE_MODE (vect_type), false, sel_int))
273d260f
RR
1164 {
1165 gimple_assign_set_rhs3 (stmt, mask);
1166 update_stmt (stmt);
1167 return;
1168 }
22e4dee7
RH
1169 }
1170 else if (can_vec_perm_p (TYPE_MODE (vect_type), true, NULL))
067f5960 1171 return;
cdbb5ba3
AS
1172
1173 warning_at (loc, OPT_Wvector_operation_performance,
1174 "vector shuffling operation will be expanded piecewise");
1175
9771b263 1176 vec_alloc (v, elements);
067f5960 1177 for (i = 0; i < elements; i++)
f90e8e2e 1178 {
067f5960
RH
1179 si = size_int (i);
1180 i_val = vector_element (gsi, mask, si, &masktmp);
f90e8e2e 1181
067f5960 1182 if (TREE_CODE (i_val) == INTEGER_CST)
f90e8e2e 1183 {
067f5960 1184 unsigned HOST_WIDE_INT index;
f90e8e2e 1185
067f5960
RH
1186 index = TREE_INT_CST_LOW (i_val);
1187 if (!host_integerp (i_val, 1) || index >= elements)
1188 i_val = build_int_cst (mask_elt_type, index & (elements - 1));
f90e8e2e 1189
067f5960
RH
1190 if (two_operand_p && (index & elements) != 0)
1191 t = vector_element (gsi, vec1, i_val, &vec1tmp);
1192 else
1193 t = vector_element (gsi, vec0, i_val, &vec0tmp);
f90e8e2e 1194
067f5960
RH
1195 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE,
1196 true, GSI_SAME_STMT);
f90e8e2e 1197 }
067f5960 1198 else
f90e8e2e 1199 {
067f5960
RH
1200 tree cond = NULL_TREE, v0_val;
1201
1202 if (two_operand_p)
1203 {
1204 cond = fold_build2 (BIT_AND_EXPR, mask_elt_type, i_val,
1205 build_int_cst (mask_elt_type, elements));
1206 cond = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE,
1207 true, GSI_SAME_STMT);
1208 }
1209
1210 i_val = fold_build2 (BIT_AND_EXPR, mask_elt_type, i_val,
1211 build_int_cst (mask_elt_type, elements - 1));
1212 i_val = force_gimple_operand_gsi (gsi, i_val, true, NULL_TREE,
1213 true, GSI_SAME_STMT);
1214
1215 v0_val = vector_element (gsi, vec0, i_val, &vec0tmp);
1216 v0_val = force_gimple_operand_gsi (gsi, v0_val, true, NULL_TREE,
1217 true, GSI_SAME_STMT);
1218
1219 if (two_operand_p)
1220 {
1221 tree v1_val;
1222
1223 v1_val = vector_element (gsi, vec1, i_val, &vec1tmp);
1224 v1_val = force_gimple_operand_gsi (gsi, v1_val, true, NULL_TREE,
1225 true, GSI_SAME_STMT);
1226
1227 cond = fold_build2 (EQ_EXPR, boolean_type_node,
1228 cond, build_zero_cst (mask_elt_type));
1229 cond = fold_build3 (COND_EXPR, vect_elt_type,
1230 cond, v0_val, v1_val);
1231 t = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE,
1232 true, GSI_SAME_STMT);
f90e8e2e 1233 }
067f5960
RH
1234 else
1235 t = v0_val;
f90e8e2e 1236 }
067f5960 1237
4a2c20cc 1238 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, t);
f90e8e2e
AS
1239 }
1240
067f5960 1241 constr = build_constructor (vect_type, v);
f90e8e2e 1242 gimple_assign_set_rhs_from_tree (gsi, constr);
067f5960 1243 update_stmt (gsi_stmt (*gsi));
f90e8e2e
AS
1244}
1245
2b725155
RH
1246/* Process one statement. If we identify a vector operation, expand it. */
1247
1248static void
726a989a 1249expand_vector_operations_1 (gimple_stmt_iterator *gsi)
2b725155 1250{
726a989a
RB
1251 gimple stmt = gsi_stmt (*gsi);
1252 tree lhs, rhs1, rhs2 = NULL, type, compute_type;
2b725155
RH
1253 enum tree_code code;
1254 enum machine_mode compute_mode;
2225b9f2 1255 optab op = unknown_optab;
726a989a
RB
1256 enum gimple_rhs_class rhs_class;
1257 tree new_rhs;
2b725155 1258
726a989a
RB
1259 if (gimple_code (stmt) != GIMPLE_ASSIGN)
1260 return;
2b725155 1261
726a989a
RB
1262 code = gimple_assign_rhs_code (stmt);
1263 rhs_class = get_gimple_rhs_class (code);
d246ab4f 1264 lhs = gimple_assign_lhs (stmt);
2b725155 1265
2205ed25 1266 if (code == VEC_PERM_EXPR)
f90e8e2e 1267 {
2205ed25 1268 lower_vec_perm (gsi);
067f5960 1269 return;
f90e8e2e
AS
1270 }
1271
374ab2d7
MG
1272 if (code == VEC_COND_EXPR)
1273 {
1274 expand_vector_condition (gsi);
1275 return;
1276 }
726a989a
RB
1277 if (rhs_class != GIMPLE_UNARY_RHS && rhs_class != GIMPLE_BINARY_RHS)
1278 return;
2b725155 1279
726a989a
RB
1280 rhs1 = gimple_assign_rhs1 (stmt);
1281 type = gimple_expr_type (stmt);
1282 if (rhs_class == GIMPLE_BINARY_RHS)
1283 rhs2 = gimple_assign_rhs2 (stmt);
2b725155 1284
2b725155
RH
1285 if (TREE_CODE (type) != VECTOR_TYPE)
1286 return;
1287
b8698a0f 1288 if (code == NOP_EXPR
f57d17f1
TM
1289 || code == FLOAT_EXPR
1290 || code == FIX_TRUNC_EXPR
1291 || code == VIEW_CONVERT_EXPR)
2b725155 1292 return;
b8698a0f 1293
2b725155 1294 gcc_assert (code != CONVERT_EXPR);
9f106823
UB
1295
1296 /* The signedness is determined from input argument. */
1297 if (code == VEC_UNPACK_FLOAT_HI_EXPR
1298 || code == VEC_UNPACK_FLOAT_LO_EXPR)
726a989a 1299 type = TREE_TYPE (rhs1);
9f106823 1300
3f30a9a6
RH
1301 /* For widening/narrowing vector operations, the relevant type is of the
1302 arguments, not the widened result. VEC_UNPACK_FLOAT_*_EXPR is
1303 calculated in the same way above. */
1304 if (code == WIDEN_SUM_EXPR
1305 || code == VEC_WIDEN_MULT_HI_EXPR
1306 || code == VEC_WIDEN_MULT_LO_EXPR
1307 || code == VEC_WIDEN_MULT_EVEN_EXPR
1308 || code == VEC_WIDEN_MULT_ODD_EXPR
1309 || code == VEC_UNPACK_HI_EXPR
1310 || code == VEC_UNPACK_LO_EXPR
1311 || code == VEC_PACK_TRUNC_EXPR
1312 || code == VEC_PACK_SAT_EXPR
1313 || code == VEC_PACK_FIX_TRUNC_EXPR
1314 || code == VEC_WIDEN_LSHIFT_HI_EXPR
1315 || code == VEC_WIDEN_LSHIFT_LO_EXPR)
1316 type = TREE_TYPE (rhs1);
1317
71d46ca5
MM
1318 /* Choose between vector shift/rotate by vector and vector shift/rotate by
1319 scalar */
b8698a0f
L
1320 if (code == LSHIFT_EXPR
1321 || code == RSHIFT_EXPR
726a989a 1322 || code == LROTATE_EXPR
71d46ca5
MM
1323 || code == RROTATE_EXPR)
1324 {
0f3d6c10
RH
1325 optab opv;
1326
bdc3ee5d
RH
1327 /* Check whether we have vector <op> {x,x,x,x} where x
1328 could be a scalar variable or a constant. Transform
1329 vector <op> {x,x,x,x} ==> vector <op> scalar. */
0f3d6c10 1330 if (VECTOR_INTEGER_TYPE_P (TREE_TYPE (rhs2)))
47853c73
AS
1331 {
1332 tree first;
1333 gimple def_stmt;
1334
bdc3ee5d
RH
1335 if ((TREE_CODE (rhs2) == VECTOR_CST
1336 && (first = uniform_vector_p (rhs2)) != NULL_TREE)
1337 || (TREE_CODE (rhs2) == SSA_NAME
1338 && (def_stmt = SSA_NAME_DEF_STMT (rhs2))
1339 && gimple_assign_single_p (def_stmt)
1340 && (first = uniform_vector_p
1341 (gimple_assign_rhs1 (def_stmt))) != NULL_TREE))
47853c73
AS
1342 {
1343 gimple_assign_set_rhs2 (stmt, first);
1344 update_stmt (stmt);
1345 rhs2 = first;
1346 }
47853c73 1347 }
f90e8e2e 1348
0f3d6c10
RH
1349 opv = optab_for_tree_code (code, type, optab_vector);
1350 if (VECTOR_INTEGER_TYPE_P (TREE_TYPE (rhs2)))
1351 op = opv;
bdc3ee5d 1352 else
2fa6eeff 1353 {
bdc3ee5d 1354 op = optab_for_tree_code (code, type, optab_scalar);
2fa6eeff 1355
bdc3ee5d
RH
1356 /* The rtl expander will expand vector/scalar as vector/vector
1357 if necessary. Don't bother converting the stmt here. */
0f3d6c10
RH
1358 if (optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing
1359 && optab_handler (opv, TYPE_MODE (type)) != CODE_FOR_nothing)
1360 return;
2fa6eeff 1361 }
71d46ca5
MM
1362 }
1363 else
1364 op = optab_for_tree_code (code, type, optab_default);
2b725155
RH
1365
1366 /* Optabs will try converting a negation into a subtraction, so
1367 look for it as well. TODO: negation of floating-point vectors
1368 might be turned into an exclusive OR toggling the sign bit. */
2225b9f2 1369 if (op == unknown_optab
2b725155
RH
1370 && code == NEGATE_EXPR
1371 && INTEGRAL_TYPE_P (TREE_TYPE (type)))
71d46ca5 1372 op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
2b725155
RH
1373
1374 /* For very wide vectors, try using a smaller vector mode. */
1375 compute_type = type;
0f3d6c10 1376 if (!VECTOR_MODE_P (TYPE_MODE (type)) && op)
2b725155
RH
1377 {
1378 tree vector_compute_type
995ec132 1379 = type_for_widest_vector_mode (TREE_TYPE (type), op);
1e9ae5ab
UB
1380 if (vector_compute_type != NULL_TREE
1381 && (TYPE_VECTOR_SUBPARTS (vector_compute_type)
0f3d6c10
RH
1382 < TYPE_VECTOR_SUBPARTS (compute_type))
1383 && (optab_handler (op, TYPE_MODE (vector_compute_type))
1384 != CODE_FOR_nothing))
1e9ae5ab 1385 compute_type = vector_compute_type;
2b725155
RH
1386 }
1387
1388 /* If we are breaking a BLKmode vector into smaller pieces,
1389 type_for_widest_vector_mode has already looked into the optab,
1390 so skip these checks. */
1391 if (compute_type == type)
1392 {
1393 compute_mode = TYPE_MODE (compute_type);
00f07b86
RH
1394 if (VECTOR_MODE_P (compute_mode))
1395 {
1396 if (op && optab_handler (op, compute_mode) != CODE_FOR_nothing)
1397 return;
1398 if (code == MULT_HIGHPART_EXPR
1399 && can_mult_highpart_p (compute_mode,
1400 TYPE_UNSIGNED (compute_type)))
1401 return;
1402 }
1403 /* There is no operation in hardware, so fall back to scalars. */
1404 compute_type = TREE_TYPE (type);
2b725155
RH
1405 }
1406
a6b46ba2 1407 gcc_assert (code != VEC_LSHIFT_EXPR && code != VEC_RSHIFT_EXPR);
726a989a 1408 new_rhs = expand_vector_operation (gsi, type, compute_type, stmt, code);
d246ab4f
AS
1409
1410 /* Leave expression untouched for later expansion. */
1411 if (new_rhs == NULL_TREE)
1412 return;
1413
726a989a
RB
1414 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (new_rhs)))
1415 new_rhs = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, TREE_TYPE (lhs),
1416 new_rhs);
1417
1418 /* NOTE: We should avoid using gimple_assign_set_rhs_from_tree. One
1419 way to do it is change expand_vector_operation and its callees to
1420 return a tree_code, RHS1 and RHS2 instead of a tree. */
1421 gimple_assign_set_rhs_from_tree (gsi, new_rhs);
3865a06f 1422 update_stmt (gsi_stmt (*gsi));
2b725155
RH
1423}
1424\f
1425/* Use this to lower vector operations introduced by the vectorizer,
1426 if it may need the bit-twiddling tricks implemented in this file. */
1427
1428static bool
f90e8e2e 1429gate_expand_vector_operations_ssa (void)
2b725155 1430{
6f37411d 1431 return !(cfun->curr_properties & PROP_gimple_lvec);
2b725155
RH
1432}
1433
c2924966 1434static unsigned int
2b725155
RH
1435expand_vector_operations (void)
1436{
726a989a 1437 gimple_stmt_iterator gsi;
2b725155 1438 basic_block bb;
3865a06f 1439 bool cfg_changed = false;
2b725155
RH
1440
1441 FOR_EACH_BB (bb)
1442 {
726a989a 1443 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
2b725155 1444 {
726a989a 1445 expand_vector_operations_1 (&gsi);
3865a06f
RG
1446 /* ??? If we do not cleanup EH then we will ICE in
1447 verification. But in reality we have created wrong-code
1448 as we did not properly transition EH info and edges to
1449 the piecewise computations. */
1450 if (maybe_clean_eh_stmt (gsi_stmt (gsi))
1451 && gimple_purge_dead_eh_edges (bb))
1452 cfg_changed = true;
2b725155
RH
1453 }
1454 }
3865a06f
RG
1455
1456 return cfg_changed ? TODO_cleanup_cfg : 0;
2b725155
RH
1457}
1458
27a4cd48
DM
1459namespace {
1460
1461const pass_data pass_data_lower_vector =
2b725155 1462{
27a4cd48
DM
1463 GIMPLE_PASS, /* type */
1464 "veclower", /* name */
1465 OPTGROUP_VEC, /* optinfo_flags */
1466 true, /* has_gate */
1467 true, /* has_execute */
1468 TV_NONE, /* tv_id */
1469 PROP_cfg, /* properties_required */
1470 PROP_gimple_lvec, /* properties_provided */
1471 0, /* properties_destroyed */
1472 0, /* todo_flags_start */
1473 ( TODO_update_ssa | TODO_verify_ssa
1474 | TODO_verify_stmts
1475 | TODO_verify_flow
1476 | TODO_cleanup_cfg ), /* todo_flags_finish */
2b725155
RH
1477};
1478
27a4cd48
DM
1479class pass_lower_vector : public gimple_opt_pass
1480{
1481public:
c3284718
RS
1482 pass_lower_vector (gcc::context *ctxt)
1483 : gimple_opt_pass (pass_data_lower_vector, ctxt)
27a4cd48
DM
1484 {}
1485
1486 /* opt_pass methods: */
1487 bool gate () { return gate_expand_vector_operations_ssa (); }
1488 unsigned int execute () { return expand_vector_operations (); }
1489
1490}; // class pass_lower_vector
1491
1492} // anon namespace
1493
1494gimple_opt_pass *
1495make_pass_lower_vector (gcc::context *ctxt)
1496{
1497 return new pass_lower_vector (ctxt);
1498}
1499
1500namespace {
1501
1502const pass_data pass_data_lower_vector_ssa =
2b725155 1503{
27a4cd48
DM
1504 GIMPLE_PASS, /* type */
1505 "veclower2", /* name */
1506 OPTGROUP_VEC, /* optinfo_flags */
1507 false, /* has_gate */
1508 true, /* has_execute */
1509 TV_NONE, /* tv_id */
1510 PROP_cfg, /* properties_required */
1511 PROP_gimple_lvec, /* properties_provided */
1512 0, /* properties_destroyed */
1513 0, /* todo_flags_start */
1514 ( TODO_update_ssa | TODO_verify_ssa
1515 | TODO_verify_stmts
1516 | TODO_verify_flow
1517 | TODO_cleanup_cfg ), /* todo_flags_finish */
2b725155
RH
1518};
1519
27a4cd48
DM
1520class pass_lower_vector_ssa : public gimple_opt_pass
1521{
1522public:
c3284718
RS
1523 pass_lower_vector_ssa (gcc::context *ctxt)
1524 : gimple_opt_pass (pass_data_lower_vector_ssa, ctxt)
27a4cd48
DM
1525 {}
1526
1527 /* opt_pass methods: */
65d3284b 1528 opt_pass * clone () { return new pass_lower_vector_ssa (m_ctxt); }
27a4cd48
DM
1529 unsigned int execute () { return expand_vector_operations (); }
1530
1531}; // class pass_lower_vector_ssa
1532
1533} // anon namespace
1534
1535gimple_opt_pass *
1536make_pass_lower_vector_ssa (gcc::context *ctxt)
1537{
1538 return new pass_lower_vector_ssa (ctxt);
1539}
1540
2b725155 1541#include "gt-tree-vect-generic.h"