PR rtl-optimization/82913
[official-gcc.git] / gcc / tree-vect-generic.c
blobb114ff09006d824cc684f5046570c7f82cbc55ab
1 /* Lower vector operations to scalar operations.
2 Copyright (C) 2004-2017 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 3, or (at your option) any
9 later version.
11 GCC is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 for more details.
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
20 #include "config.h"
21 #include "system.h"
22 #include "coretypes.h"
23 #include "backend.h"
24 #include "rtl.h"
25 #include "tree.h"
26 #include "gimple.h"
27 #include "tree-pass.h"
28 #include "ssa.h"
29 #include "expmed.h"
30 #include "optabs-tree.h"
31 #include "diagnostic.h"
32 #include "fold-const.h"
33 #include "stor-layout.h"
34 #include "langhooks.h"
35 #include "tree-eh.h"
36 #include "gimple-iterator.h"
37 #include "gimplify-me.h"
38 #include "gimplify.h"
39 #include "tree-cfg.h"
42 static void expand_vector_operations_1 (gimple_stmt_iterator *);
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. */
47 static tree
48 build_replicated_const (tree type, tree inner_type, HOST_WIDE_INT value)
50 int width = tree_to_uhwi (TYPE_SIZE (inner_type));
51 int n = (TYPE_PRECISION (type) + HOST_BITS_PER_WIDE_INT - 1)
52 / HOST_BITS_PER_WIDE_INT;
53 unsigned HOST_WIDE_INT low, mask;
54 HOST_WIDE_INT a[WIDE_INT_MAX_ELTS];
55 int i;
57 gcc_assert (n && n <= WIDE_INT_MAX_ELTS);
59 if (width == HOST_BITS_PER_WIDE_INT)
60 low = value;
61 else
63 mask = ((HOST_WIDE_INT)1 << width) - 1;
64 low = (unsigned HOST_WIDE_INT) ~0 / mask * (value & mask);
67 for (i = 0; i < n; i++)
68 a[i] = low;
70 gcc_assert (TYPE_PRECISION (type) <= MAX_BITSIZE_MODE_ANY_INT);
71 return wide_int_to_tree
72 (type, wide_int::from_array (a, n, TYPE_PRECISION (type)));
75 static GTY(()) tree vector_inner_type;
76 static GTY(()) tree vector_last_type;
77 static GTY(()) int vector_last_nunits;
79 /* Return a suitable vector types made of SUBPARTS units each of mode
80 "word_mode" (the global variable). */
81 static tree
82 build_word_mode_vector_type (int nunits)
84 if (!vector_inner_type)
85 vector_inner_type = lang_hooks.types.type_for_mode (word_mode, 1);
86 else if (vector_last_nunits == nunits)
88 gcc_assert (TREE_CODE (vector_last_type) == VECTOR_TYPE);
89 return vector_last_type;
92 /* We build a new type, but we canonicalize it nevertheless,
93 because it still saves some memory. */
94 vector_last_nunits = nunits;
95 vector_last_type = type_hash_canon (nunits,
96 build_vector_type (vector_inner_type,
97 nunits));
98 return vector_last_type;
101 typedef tree (*elem_op_func) (gimple_stmt_iterator *,
102 tree, tree, tree, tree, tree, enum tree_code,
103 tree);
105 static inline tree
106 tree_vec_extract (gimple_stmt_iterator *gsi, tree type,
107 tree t, tree bitsize, tree bitpos)
109 if (TREE_CODE (t) == SSA_NAME)
111 gimple *def_stmt = SSA_NAME_DEF_STMT (t);
112 if (is_gimple_assign (def_stmt)
113 && (gimple_assign_rhs_code (def_stmt) == VECTOR_CST
114 || (bitpos
115 && gimple_assign_rhs_code (def_stmt) == CONSTRUCTOR)))
116 t = gimple_assign_rhs1 (def_stmt);
118 if (bitpos)
120 if (TREE_CODE (type) == BOOLEAN_TYPE)
122 tree itype
123 = build_nonstandard_integer_type (tree_to_uhwi (bitsize), 0);
124 tree field = gimplify_build3 (gsi, BIT_FIELD_REF, itype, t,
125 bitsize, bitpos);
126 return gimplify_build2 (gsi, NE_EXPR, type, field,
127 build_zero_cst (itype));
129 else
130 return gimplify_build3 (gsi, BIT_FIELD_REF, type, t, bitsize, bitpos);
132 else
133 return gimplify_build1 (gsi, VIEW_CONVERT_EXPR, type, t);
136 static tree
137 do_unop (gimple_stmt_iterator *gsi, tree inner_type, tree a,
138 tree b ATTRIBUTE_UNUSED, tree bitpos, tree bitsize,
139 enum tree_code code, tree type ATTRIBUTE_UNUSED)
141 a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
142 return gimplify_build1 (gsi, code, inner_type, a);
145 static tree
146 do_binop (gimple_stmt_iterator *gsi, tree inner_type, tree a, tree b,
147 tree bitpos, tree bitsize, enum tree_code code,
148 tree type ATTRIBUTE_UNUSED)
150 if (TREE_CODE (TREE_TYPE (a)) == VECTOR_TYPE)
151 a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
152 if (TREE_CODE (TREE_TYPE (b)) == VECTOR_TYPE)
153 b = tree_vec_extract (gsi, inner_type, b, bitsize, bitpos);
154 return gimplify_build2 (gsi, code, inner_type, a, b);
157 /* Construct expression (A[BITPOS] code B[BITPOS]) ? -1 : 0
159 INNER_TYPE is the type of A and B elements
161 returned expression is of signed integer type with the
162 size equal to the size of INNER_TYPE. */
163 static tree
164 do_compare (gimple_stmt_iterator *gsi, tree inner_type, tree a, tree b,
165 tree bitpos, tree bitsize, enum tree_code code, tree type)
167 tree stype = TREE_TYPE (type);
168 tree cst_false = build_zero_cst (stype);
169 tree cst_true = build_all_ones_cst (stype);
170 tree cmp;
172 a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
173 b = tree_vec_extract (gsi, inner_type, b, bitsize, bitpos);
175 cmp = build2 (code, boolean_type_node, a, b);
176 return gimplify_build3 (gsi, COND_EXPR, stype, cmp, cst_true, cst_false);
179 /* Expand vector addition to scalars. This does bit twiddling
180 in order to increase parallelism:
182 a + b = (((int) a & 0x7f7f7f7f) + ((int) b & 0x7f7f7f7f)) ^
183 (a ^ b) & 0x80808080
185 a - b = (((int) a | 0x80808080) - ((int) b & 0x7f7f7f7f)) ^
186 (a ^ ~b) & 0x80808080
188 -b = (0x80808080 - ((int) b & 0x7f7f7f7f)) ^ (~b & 0x80808080)
190 This optimization should be done only if 4 vector items or more
191 fit into a word. */
192 static tree
193 do_plus_minus (gimple_stmt_iterator *gsi, tree word_type, tree a, tree b,
194 tree bitpos ATTRIBUTE_UNUSED, tree bitsize ATTRIBUTE_UNUSED,
195 enum tree_code code, tree type ATTRIBUTE_UNUSED)
197 tree inner_type = TREE_TYPE (TREE_TYPE (a));
198 unsigned HOST_WIDE_INT max;
199 tree low_bits, high_bits, a_low, b_low, result_low, signs;
201 max = GET_MODE_MASK (TYPE_MODE (inner_type));
202 low_bits = build_replicated_const (word_type, inner_type, max >> 1);
203 high_bits = build_replicated_const (word_type, inner_type, max & ~(max >> 1));
205 a = tree_vec_extract (gsi, word_type, a, bitsize, bitpos);
206 b = tree_vec_extract (gsi, word_type, b, bitsize, bitpos);
208 signs = gimplify_build2 (gsi, BIT_XOR_EXPR, word_type, a, b);
209 b_low = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, b, low_bits);
210 if (code == PLUS_EXPR)
211 a_low = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, a, low_bits);
212 else
214 a_low = gimplify_build2 (gsi, BIT_IOR_EXPR, word_type, a, high_bits);
215 signs = gimplify_build1 (gsi, BIT_NOT_EXPR, word_type, signs);
218 signs = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, signs, high_bits);
219 result_low = gimplify_build2 (gsi, code, word_type, a_low, b_low);
220 return gimplify_build2 (gsi, BIT_XOR_EXPR, word_type, result_low, signs);
223 static tree
224 do_negate (gimple_stmt_iterator *gsi, tree word_type, tree b,
225 tree unused ATTRIBUTE_UNUSED, tree bitpos ATTRIBUTE_UNUSED,
226 tree bitsize ATTRIBUTE_UNUSED,
227 enum tree_code code ATTRIBUTE_UNUSED,
228 tree type ATTRIBUTE_UNUSED)
230 tree inner_type = TREE_TYPE (TREE_TYPE (b));
231 HOST_WIDE_INT max;
232 tree low_bits, high_bits, b_low, result_low, signs;
234 max = GET_MODE_MASK (TYPE_MODE (inner_type));
235 low_bits = build_replicated_const (word_type, inner_type, max >> 1);
236 high_bits = build_replicated_const (word_type, inner_type, max & ~(max >> 1));
238 b = tree_vec_extract (gsi, word_type, b, bitsize, bitpos);
240 b_low = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, b, low_bits);
241 signs = gimplify_build1 (gsi, BIT_NOT_EXPR, word_type, b);
242 signs = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, signs, high_bits);
243 result_low = gimplify_build2 (gsi, MINUS_EXPR, word_type, high_bits, b_low);
244 return gimplify_build2 (gsi, BIT_XOR_EXPR, word_type, result_low, signs);
247 /* Expand a vector operation to scalars, by using many operations
248 whose type is the vector type's inner type. */
249 static tree
250 expand_vector_piecewise (gimple_stmt_iterator *gsi, elem_op_func f,
251 tree type, tree inner_type,
252 tree a, tree b, enum tree_code code)
254 vec<constructor_elt, va_gc> *v;
255 tree part_width = TYPE_SIZE (inner_type);
256 tree index = bitsize_int (0);
257 int nunits = TYPE_VECTOR_SUBPARTS (type);
258 int delta = tree_to_uhwi (part_width)
259 / tree_to_uhwi (TYPE_SIZE (TREE_TYPE (type)));
260 int i;
261 location_t loc = gimple_location (gsi_stmt (*gsi));
263 if (types_compatible_p (gimple_expr_type (gsi_stmt (*gsi)), type))
264 warning_at (loc, OPT_Wvector_operation_performance,
265 "vector operation will be expanded piecewise");
266 else
267 warning_at (loc, OPT_Wvector_operation_performance,
268 "vector operation will be expanded in parallel");
270 vec_alloc (v, (nunits + delta - 1) / delta);
271 for (i = 0; i < nunits;
272 i += delta, index = int_const_binop (PLUS_EXPR, index, part_width))
274 tree result = f (gsi, inner_type, a, b, index, part_width, code, type);
275 constructor_elt ce = {NULL_TREE, result};
276 v->quick_push (ce);
279 return build_constructor (type, v);
282 /* Expand a vector operation to scalars with the freedom to use
283 a scalar integer type, or to use a different size for the items
284 in the vector type. */
285 static tree
286 expand_vector_parallel (gimple_stmt_iterator *gsi, elem_op_func f, tree type,
287 tree a, tree b,
288 enum tree_code code)
290 tree result, compute_type;
291 int n_words = tree_to_uhwi (TYPE_SIZE_UNIT (type)) / UNITS_PER_WORD;
292 location_t loc = gimple_location (gsi_stmt (*gsi));
294 /* We have three strategies. If the type is already correct, just do
295 the operation an element at a time. Else, if the vector is wider than
296 one word, do it a word at a time; finally, if the vector is smaller
297 than one word, do it as a scalar. */
298 if (TYPE_MODE (TREE_TYPE (type)) == word_mode)
299 return expand_vector_piecewise (gsi, f,
300 type, TREE_TYPE (type),
301 a, b, code);
302 else if (n_words > 1)
304 tree word_type = build_word_mode_vector_type (n_words);
305 result = expand_vector_piecewise (gsi, f,
306 word_type, TREE_TYPE (word_type),
307 a, b, code);
308 result = force_gimple_operand_gsi (gsi, result, true, NULL, true,
309 GSI_SAME_STMT);
311 else
313 /* Use a single scalar operation with a mode no wider than word_mode. */
314 scalar_int_mode mode
315 = int_mode_for_size (tree_to_uhwi (TYPE_SIZE (type)), 0).require ();
316 compute_type = lang_hooks.types.type_for_mode (mode, 1);
317 result = f (gsi, compute_type, a, b, NULL_TREE, NULL_TREE, code, type);
318 warning_at (loc, OPT_Wvector_operation_performance,
319 "vector operation will be expanded with a "
320 "single scalar operation");
323 return result;
326 /* Expand a vector operation to scalars; for integer types we can use
327 special bit twiddling tricks to do the sums a word at a time, using
328 function F_PARALLEL instead of F. These tricks are done only if
329 they can process at least four items, that is, only if the vector
330 holds at least four items and if a word can hold four items. */
331 static tree
332 expand_vector_addition (gimple_stmt_iterator *gsi,
333 elem_op_func f, elem_op_func f_parallel,
334 tree type, tree a, tree b, enum tree_code code)
336 int parts_per_word = UNITS_PER_WORD
337 / tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (type)));
339 if (INTEGRAL_TYPE_P (TREE_TYPE (type))
340 && parts_per_word >= 4
341 && TYPE_VECTOR_SUBPARTS (type) >= 4)
342 return expand_vector_parallel (gsi, f_parallel,
343 type, a, b, code);
344 else
345 return expand_vector_piecewise (gsi, f,
346 type, TREE_TYPE (type),
347 a, b, code);
350 /* Try to expand vector comparison expression OP0 CODE OP1 by
351 querying optab if the following expression:
352 VEC_COND_EXPR< OP0 CODE OP1, {-1,...}, {0,...}>
353 can be expanded. */
354 static tree
355 expand_vector_comparison (gimple_stmt_iterator *gsi, tree type, tree op0,
356 tree op1, enum tree_code code)
358 tree t;
359 if (!expand_vec_cmp_expr_p (TREE_TYPE (op0), type, code)
360 && !expand_vec_cond_expr_p (type, TREE_TYPE (op0), code))
361 t = expand_vector_piecewise (gsi, do_compare, type,
362 TREE_TYPE (TREE_TYPE (op0)), op0, op1, code);
363 else
364 t = NULL_TREE;
366 return t;
369 /* Helper function of expand_vector_divmod. Gimplify a RSHIFT_EXPR in type
370 of OP0 with shift counts in SHIFTCNTS array and return the temporary holding
371 the result if successful, otherwise return NULL_TREE. */
372 static tree
373 add_rshift (gimple_stmt_iterator *gsi, tree type, tree op0, int *shiftcnts)
375 optab op;
376 unsigned int i, nunits = TYPE_VECTOR_SUBPARTS (type);
377 bool scalar_shift = true;
379 for (i = 1; i < nunits; i++)
381 if (shiftcnts[i] != shiftcnts[0])
382 scalar_shift = false;
385 if (scalar_shift && shiftcnts[0] == 0)
386 return op0;
388 if (scalar_shift)
390 op = optab_for_tree_code (RSHIFT_EXPR, type, optab_scalar);
391 if (op != unknown_optab
392 && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
393 return gimplify_build2 (gsi, RSHIFT_EXPR, type, op0,
394 build_int_cst (NULL_TREE, shiftcnts[0]));
397 op = optab_for_tree_code (RSHIFT_EXPR, type, optab_vector);
398 if (op != unknown_optab
399 && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
401 auto_vec<tree, 32> vec (nunits);
402 for (i = 0; i < nunits; i++)
403 vec.quick_push (build_int_cst (TREE_TYPE (type), shiftcnts[i]));
404 return gimplify_build2 (gsi, RSHIFT_EXPR, type, op0,
405 build_vector (type, vec));
408 return NULL_TREE;
411 /* Try to expand integer vector division by constant using
412 widening multiply, shifts and additions. */
413 static tree
414 expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, tree op0,
415 tree op1, enum tree_code code)
417 bool use_pow2 = true;
418 bool has_vector_shift = true;
419 int mode = -1, this_mode;
420 int pre_shift = -1, post_shift;
421 unsigned int nunits = TYPE_VECTOR_SUBPARTS (type);
422 int *shifts = XALLOCAVEC (int, nunits * 4);
423 int *pre_shifts = shifts + nunits;
424 int *post_shifts = pre_shifts + nunits;
425 int *shift_temps = post_shifts + nunits;
426 unsigned HOST_WIDE_INT *mulc = XALLOCAVEC (unsigned HOST_WIDE_INT, nunits);
427 int prec = TYPE_PRECISION (TREE_TYPE (type));
428 int dummy_int;
429 unsigned int i;
430 signop sign_p = TYPE_SIGN (TREE_TYPE (type));
431 unsigned HOST_WIDE_INT mask = GET_MODE_MASK (TYPE_MODE (TREE_TYPE (type)));
432 tree cur_op, mulcst, tem;
433 optab op;
435 if (prec > HOST_BITS_PER_WIDE_INT)
436 return NULL_TREE;
438 op = optab_for_tree_code (RSHIFT_EXPR, type, optab_vector);
439 if (op == unknown_optab
440 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
441 has_vector_shift = false;
443 /* Analysis phase. Determine if all op1 elements are either power
444 of two and it is possible to expand it using shifts (or for remainder
445 using masking). Additionally compute the multiplicative constants
446 and pre and post shifts if the division is to be expanded using
447 widening or high part multiplication plus shifts. */
448 for (i = 0; i < nunits; i++)
450 tree cst = VECTOR_CST_ELT (op1, i);
451 unsigned HOST_WIDE_INT ml;
453 if (TREE_CODE (cst) != INTEGER_CST || integer_zerop (cst))
454 return NULL_TREE;
455 pre_shifts[i] = 0;
456 post_shifts[i] = 0;
457 mulc[i] = 0;
458 if (use_pow2
459 && (!integer_pow2p (cst) || tree_int_cst_sgn (cst) != 1))
460 use_pow2 = false;
461 if (use_pow2)
463 shifts[i] = tree_log2 (cst);
464 if (shifts[i] != shifts[0]
465 && code == TRUNC_DIV_EXPR
466 && !has_vector_shift)
467 use_pow2 = false;
469 if (mode == -2)
470 continue;
471 if (sign_p == UNSIGNED)
473 unsigned HOST_WIDE_INT mh;
474 unsigned HOST_WIDE_INT d = TREE_INT_CST_LOW (cst) & mask;
476 if (d >= (HOST_WIDE_INT_1U << (prec - 1)))
477 /* FIXME: Can transform this into op0 >= op1 ? 1 : 0. */
478 return NULL_TREE;
480 if (d <= 1)
482 mode = -2;
483 continue;
486 /* Find a suitable multiplier and right shift count
487 instead of multiplying with D. */
488 mh = choose_multiplier (d, prec, prec, &ml, &post_shift, &dummy_int);
490 /* If the suggested multiplier is more than SIZE bits, we can
491 do better for even divisors, using an initial right shift. */
492 if ((mh != 0 && (d & 1) == 0)
493 || (!has_vector_shift && pre_shift != -1))
495 if (has_vector_shift)
496 pre_shift = ctz_or_zero (d);
497 else if (pre_shift == -1)
499 unsigned int j;
500 for (j = 0; j < nunits; j++)
502 tree cst2 = VECTOR_CST_ELT (op1, j);
503 unsigned HOST_WIDE_INT d2;
504 int this_pre_shift;
506 if (!tree_fits_uhwi_p (cst2))
507 return NULL_TREE;
508 d2 = tree_to_uhwi (cst2) & mask;
509 if (d2 == 0)
510 return NULL_TREE;
511 this_pre_shift = floor_log2 (d2 & -d2);
512 if (pre_shift == -1 || this_pre_shift < pre_shift)
513 pre_shift = this_pre_shift;
515 if (i != 0 && pre_shift != 0)
517 /* Restart. */
518 i = -1U;
519 mode = -1;
520 continue;
523 if (pre_shift != 0)
525 if ((d >> pre_shift) <= 1)
527 mode = -2;
528 continue;
530 mh = choose_multiplier (d >> pre_shift, prec,
531 prec - pre_shift,
532 &ml, &post_shift, &dummy_int);
533 gcc_assert (!mh);
534 pre_shifts[i] = pre_shift;
537 if (!mh)
538 this_mode = 0;
539 else
540 this_mode = 1;
542 else
544 HOST_WIDE_INT d = TREE_INT_CST_LOW (cst);
545 unsigned HOST_WIDE_INT abs_d;
547 if (d == -1)
548 return NULL_TREE;
550 /* Since d might be INT_MIN, we have to cast to
551 unsigned HOST_WIDE_INT before negating to avoid
552 undefined signed overflow. */
553 abs_d = (d >= 0
554 ? (unsigned HOST_WIDE_INT) d
555 : - (unsigned HOST_WIDE_INT) d);
557 /* n rem d = n rem -d */
558 if (code == TRUNC_MOD_EXPR && d < 0)
559 d = abs_d;
560 else if (abs_d == HOST_WIDE_INT_1U << (prec - 1))
562 /* This case is not handled correctly below. */
563 mode = -2;
564 continue;
566 if (abs_d <= 1)
568 mode = -2;
569 continue;
572 choose_multiplier (abs_d, prec, prec - 1, &ml,
573 &post_shift, &dummy_int);
574 if (ml >= HOST_WIDE_INT_1U << (prec - 1))
576 this_mode = 4 + (d < 0);
577 ml |= HOST_WIDE_INT_M1U << (prec - 1);
579 else
580 this_mode = 2 + (d < 0);
582 mulc[i] = ml;
583 post_shifts[i] = post_shift;
584 if ((i && !has_vector_shift && post_shifts[0] != post_shift)
585 || post_shift >= prec
586 || pre_shifts[i] >= prec)
587 this_mode = -2;
589 if (i == 0)
590 mode = this_mode;
591 else if (mode != this_mode)
592 mode = -2;
595 if (use_pow2)
597 tree addend = NULL_TREE;
598 if (sign_p == SIGNED)
600 tree uns_type;
602 /* Both division and remainder sequences need
603 op0 < 0 ? mask : 0 computed. It can be either computed as
604 (type) (((uns_type) (op0 >> (prec - 1))) >> (prec - shifts[i]))
605 if none of the shifts is 0, or as the conditional. */
606 for (i = 0; i < nunits; i++)
607 if (shifts[i] == 0)
608 break;
609 uns_type
610 = build_vector_type (build_nonstandard_integer_type (prec, 1),
611 nunits);
612 if (i == nunits && TYPE_MODE (uns_type) == TYPE_MODE (type))
614 for (i = 0; i < nunits; i++)
615 shift_temps[i] = prec - 1;
616 cur_op = add_rshift (gsi, type, op0, shift_temps);
617 if (cur_op != NULL_TREE)
619 cur_op = gimplify_build1 (gsi, VIEW_CONVERT_EXPR,
620 uns_type, cur_op);
621 for (i = 0; i < nunits; i++)
622 shift_temps[i] = prec - shifts[i];
623 cur_op = add_rshift (gsi, uns_type, cur_op, shift_temps);
624 if (cur_op != NULL_TREE)
625 addend = gimplify_build1 (gsi, VIEW_CONVERT_EXPR,
626 type, cur_op);
629 if (addend == NULL_TREE
630 && expand_vec_cond_expr_p (type, type, LT_EXPR))
632 tree zero, cst, cond, mask_type;
633 gimple *stmt;
635 mask_type = build_same_sized_truth_vector_type (type);
636 zero = build_zero_cst (type);
637 cond = build2 (LT_EXPR, mask_type, op0, zero);
638 auto_vec<tree, 32> vec (nunits);
639 for (i = 0; i < nunits; i++)
640 vec.quick_push (build_int_cst (TREE_TYPE (type),
641 (HOST_WIDE_INT_1U
642 << shifts[i]) - 1));
643 cst = build_vector (type, vec);
644 addend = make_ssa_name (type);
645 stmt = gimple_build_assign (addend, VEC_COND_EXPR, cond,
646 cst, zero);
647 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
650 if (code == TRUNC_DIV_EXPR)
652 if (sign_p == UNSIGNED)
654 /* q = op0 >> shift; */
655 cur_op = add_rshift (gsi, type, op0, shifts);
656 if (cur_op != NULL_TREE)
657 return cur_op;
659 else if (addend != NULL_TREE)
661 /* t1 = op0 + addend;
662 q = t1 >> shift; */
663 op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
664 if (op != unknown_optab
665 && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
667 cur_op = gimplify_build2 (gsi, PLUS_EXPR, type, op0, addend);
668 cur_op = add_rshift (gsi, type, cur_op, shifts);
669 if (cur_op != NULL_TREE)
670 return cur_op;
674 else
676 tree mask;
677 auto_vec<tree, 32> vec (nunits);
678 for (i = 0; i < nunits; i++)
679 vec.quick_push (build_int_cst (TREE_TYPE (type),
680 (HOST_WIDE_INT_1U
681 << shifts[i]) - 1));
682 mask = build_vector (type, vec);
683 op = optab_for_tree_code (BIT_AND_EXPR, type, optab_default);
684 if (op != unknown_optab
685 && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
687 if (sign_p == UNSIGNED)
688 /* r = op0 & mask; */
689 return gimplify_build2 (gsi, BIT_AND_EXPR, type, op0, mask);
690 else if (addend != NULL_TREE)
692 /* t1 = op0 + addend;
693 t2 = t1 & mask;
694 r = t2 - addend; */
695 op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
696 if (op != unknown_optab
697 && optab_handler (op, TYPE_MODE (type))
698 != CODE_FOR_nothing)
700 cur_op = gimplify_build2 (gsi, PLUS_EXPR, type, op0,
701 addend);
702 cur_op = gimplify_build2 (gsi, BIT_AND_EXPR, type,
703 cur_op, mask);
704 op = optab_for_tree_code (MINUS_EXPR, type,
705 optab_default);
706 if (op != unknown_optab
707 && optab_handler (op, TYPE_MODE (type))
708 != CODE_FOR_nothing)
709 return gimplify_build2 (gsi, MINUS_EXPR, type,
710 cur_op, addend);
717 if (mode == -2 || BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN)
718 return NULL_TREE;
720 if (!can_mult_highpart_p (TYPE_MODE (type), TYPE_UNSIGNED (type)))
721 return NULL_TREE;
723 cur_op = op0;
725 switch (mode)
727 case 0:
728 gcc_assert (sign_p == UNSIGNED);
729 /* t1 = oprnd0 >> pre_shift;
730 t2 = t1 h* ml;
731 q = t2 >> post_shift; */
732 cur_op = add_rshift (gsi, type, cur_op, pre_shifts);
733 if (cur_op == NULL_TREE)
734 return NULL_TREE;
735 break;
736 case 1:
737 gcc_assert (sign_p == UNSIGNED);
738 for (i = 0; i < nunits; i++)
740 shift_temps[i] = 1;
741 post_shifts[i]--;
743 break;
744 case 2:
745 case 3:
746 case 4:
747 case 5:
748 gcc_assert (sign_p == SIGNED);
749 for (i = 0; i < nunits; i++)
750 shift_temps[i] = prec - 1;
751 break;
752 default:
753 return NULL_TREE;
756 auto_vec<tree, 32> vec (nunits);
757 for (i = 0; i < nunits; i++)
758 vec.quick_push (build_int_cst (TREE_TYPE (type), mulc[i]));
759 mulcst = build_vector (type, vec);
761 cur_op = gimplify_build2 (gsi, MULT_HIGHPART_EXPR, type, cur_op, mulcst);
763 switch (mode)
765 case 0:
766 /* t1 = oprnd0 >> pre_shift;
767 t2 = t1 h* ml;
768 q = t2 >> post_shift; */
769 cur_op = add_rshift (gsi, type, cur_op, post_shifts);
770 break;
771 case 1:
772 /* t1 = oprnd0 h* ml;
773 t2 = oprnd0 - t1;
774 t3 = t2 >> 1;
775 t4 = t1 + t3;
776 q = t4 >> (post_shift - 1); */
777 op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
778 if (op == unknown_optab
779 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
780 return NULL_TREE;
781 tem = gimplify_build2 (gsi, MINUS_EXPR, type, op0, cur_op);
782 tem = add_rshift (gsi, type, tem, shift_temps);
783 op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
784 if (op == unknown_optab
785 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
786 return NULL_TREE;
787 tem = gimplify_build2 (gsi, PLUS_EXPR, type, cur_op, tem);
788 cur_op = add_rshift (gsi, type, tem, post_shifts);
789 if (cur_op == NULL_TREE)
790 return NULL_TREE;
791 break;
792 case 2:
793 case 3:
794 case 4:
795 case 5:
796 /* t1 = oprnd0 h* ml;
797 t2 = t1; [ iff (mode & 2) != 0 ]
798 t2 = t1 + oprnd0; [ iff (mode & 2) == 0 ]
799 t3 = t2 >> post_shift;
800 t4 = oprnd0 >> (prec - 1);
801 q = t3 - t4; [ iff (mode & 1) == 0 ]
802 q = t4 - t3; [ iff (mode & 1) != 0 ] */
803 if ((mode & 2) == 0)
805 op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
806 if (op == unknown_optab
807 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
808 return NULL_TREE;
809 cur_op = gimplify_build2 (gsi, PLUS_EXPR, type, cur_op, op0);
811 cur_op = add_rshift (gsi, type, cur_op, post_shifts);
812 if (cur_op == NULL_TREE)
813 return NULL_TREE;
814 tem = add_rshift (gsi, type, op0, shift_temps);
815 if (tem == NULL_TREE)
816 return NULL_TREE;
817 op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
818 if (op == unknown_optab
819 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
820 return NULL_TREE;
821 if ((mode & 1) == 0)
822 cur_op = gimplify_build2 (gsi, MINUS_EXPR, type, cur_op, tem);
823 else
824 cur_op = gimplify_build2 (gsi, MINUS_EXPR, type, tem, cur_op);
825 break;
826 default:
827 gcc_unreachable ();
830 if (code == TRUNC_DIV_EXPR)
831 return cur_op;
833 /* We divided. Now finish by:
834 t1 = q * oprnd1;
835 r = oprnd0 - t1; */
836 op = optab_for_tree_code (MULT_EXPR, type, optab_default);
837 if (op == unknown_optab
838 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
839 return NULL_TREE;
840 tem = gimplify_build2 (gsi, MULT_EXPR, type, cur_op, op1);
841 op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
842 if (op == unknown_optab
843 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
844 return NULL_TREE;
845 return gimplify_build2 (gsi, MINUS_EXPR, type, op0, tem);
848 /* Expand a vector condition to scalars, by using many conditions
849 on the vector's elements. */
850 static void
851 expand_vector_condition (gimple_stmt_iterator *gsi)
853 gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
854 tree type = gimple_expr_type (stmt);
855 tree a = gimple_assign_rhs1 (stmt);
856 tree a1 = a;
857 tree a2 = NULL_TREE;
858 bool a_is_comparison = false;
859 tree b = gimple_assign_rhs2 (stmt);
860 tree c = gimple_assign_rhs3 (stmt);
861 vec<constructor_elt, va_gc> *v;
862 tree constr;
863 tree inner_type = TREE_TYPE (type);
864 tree cond_type = TREE_TYPE (TREE_TYPE (a));
865 tree comp_inner_type = cond_type;
866 tree width = TYPE_SIZE (inner_type);
867 tree index = bitsize_int (0);
868 tree comp_width = width;
869 tree comp_index = index;
870 int nunits = TYPE_VECTOR_SUBPARTS (type);
871 int i;
872 location_t loc = gimple_location (gsi_stmt (*gsi));
874 if (!is_gimple_val (a))
876 gcc_assert (COMPARISON_CLASS_P (a));
877 a_is_comparison = true;
878 a1 = TREE_OPERAND (a, 0);
879 a2 = TREE_OPERAND (a, 1);
880 comp_inner_type = TREE_TYPE (TREE_TYPE (a1));
881 comp_width = TYPE_SIZE (comp_inner_type);
884 if (expand_vec_cond_expr_p (type, TREE_TYPE (a1), TREE_CODE (a)))
885 return;
887 /* Handle vector boolean types with bitmasks. If there is a comparison
888 and we can expand the comparison into the vector boolean bitmask,
889 or otherwise if it is compatible with type, we can transform
890 vbfld_1 = x_2 < y_3 ? vbfld_4 : vbfld_5;
891 into
892 tmp_6 = x_2 < y_3;
893 tmp_7 = tmp_6 & vbfld_4;
894 tmp_8 = ~tmp_6;
895 tmp_9 = tmp_8 & vbfld_5;
896 vbfld_1 = tmp_7 | tmp_9;
897 Similarly for vbfld_10 instead of x_2 < y_3. */
898 if (VECTOR_BOOLEAN_TYPE_P (type)
899 && SCALAR_INT_MODE_P (TYPE_MODE (type))
900 && (GET_MODE_BITSIZE (TYPE_MODE (type))
901 < (TYPE_VECTOR_SUBPARTS (type)
902 * GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (type)))))
903 && (a_is_comparison
904 ? useless_type_conversion_p (type, TREE_TYPE (a))
905 : expand_vec_cmp_expr_p (TREE_TYPE (a1), type, TREE_CODE (a))))
907 if (a_is_comparison)
908 a = gimplify_build2 (gsi, TREE_CODE (a), type, a1, a2);
909 a1 = gimplify_build2 (gsi, BIT_AND_EXPR, type, a, b);
910 a2 = gimplify_build1 (gsi, BIT_NOT_EXPR, type, a);
911 a2 = gimplify_build2 (gsi, BIT_AND_EXPR, type, a2, c);
912 a = gimplify_build2 (gsi, BIT_IOR_EXPR, type, a1, a2);
913 gimple_assign_set_rhs_from_tree (gsi, a);
914 update_stmt (gsi_stmt (*gsi));
915 return;
918 /* TODO: try and find a smaller vector type. */
920 warning_at (loc, OPT_Wvector_operation_performance,
921 "vector condition will be expanded piecewise");
923 vec_alloc (v, nunits);
924 for (i = 0; i < nunits; i++)
926 tree aa, result;
927 tree bb = tree_vec_extract (gsi, inner_type, b, width, index);
928 tree cc = tree_vec_extract (gsi, inner_type, c, width, index);
929 if (a_is_comparison)
931 tree aa1 = tree_vec_extract (gsi, comp_inner_type, a1,
932 comp_width, comp_index);
933 tree aa2 = tree_vec_extract (gsi, comp_inner_type, a2,
934 comp_width, comp_index);
935 aa = fold_build2 (TREE_CODE (a), cond_type, aa1, aa2);
937 else
938 aa = tree_vec_extract (gsi, cond_type, a, width, index);
939 result = gimplify_build3 (gsi, COND_EXPR, inner_type, aa, bb, cc);
940 constructor_elt ce = {NULL_TREE, result};
941 v->quick_push (ce);
942 index = int_const_binop (PLUS_EXPR, index, width);
943 if (width == comp_width)
944 comp_index = index;
945 else
946 comp_index = int_const_binop (PLUS_EXPR, comp_index, comp_width);
949 constr = build_constructor (type, v);
950 gimple_assign_set_rhs_from_tree (gsi, constr);
951 update_stmt (gsi_stmt (*gsi));
954 static tree
955 expand_vector_operation (gimple_stmt_iterator *gsi, tree type, tree compute_type,
956 gassign *assign, enum tree_code code)
958 machine_mode compute_mode = TYPE_MODE (compute_type);
960 /* If the compute mode is not a vector mode (hence we are not decomposing
961 a BLKmode vector to smaller, hardware-supported vectors), we may want
962 to expand the operations in parallel. */
963 if (GET_MODE_CLASS (compute_mode) != MODE_VECTOR_INT
964 && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_FLOAT
965 && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_FRACT
966 && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_UFRACT
967 && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_ACCUM
968 && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_UACCUM)
969 switch (code)
971 case PLUS_EXPR:
972 case MINUS_EXPR:
973 if (ANY_INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_TRAPS (type))
974 return expand_vector_addition (gsi, do_binop, do_plus_minus, type,
975 gimple_assign_rhs1 (assign),
976 gimple_assign_rhs2 (assign), code);
977 break;
979 case NEGATE_EXPR:
980 if (ANY_INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_TRAPS (type))
981 return expand_vector_addition (gsi, do_unop, do_negate, type,
982 gimple_assign_rhs1 (assign),
983 NULL_TREE, code);
984 break;
986 case BIT_AND_EXPR:
987 case BIT_IOR_EXPR:
988 case BIT_XOR_EXPR:
989 return expand_vector_parallel (gsi, do_binop, type,
990 gimple_assign_rhs1 (assign),
991 gimple_assign_rhs2 (assign), code);
993 case BIT_NOT_EXPR:
994 return expand_vector_parallel (gsi, do_unop, type,
995 gimple_assign_rhs1 (assign),
996 NULL_TREE, code);
997 case EQ_EXPR:
998 case NE_EXPR:
999 case GT_EXPR:
1000 case LT_EXPR:
1001 case GE_EXPR:
1002 case LE_EXPR:
1003 case UNEQ_EXPR:
1004 case UNGT_EXPR:
1005 case UNLT_EXPR:
1006 case UNGE_EXPR:
1007 case UNLE_EXPR:
1008 case LTGT_EXPR:
1009 case ORDERED_EXPR:
1010 case UNORDERED_EXPR:
1012 tree rhs1 = gimple_assign_rhs1 (assign);
1013 tree rhs2 = gimple_assign_rhs2 (assign);
1015 return expand_vector_comparison (gsi, type, rhs1, rhs2, code);
1018 case TRUNC_DIV_EXPR:
1019 case TRUNC_MOD_EXPR:
1021 tree rhs1 = gimple_assign_rhs1 (assign);
1022 tree rhs2 = gimple_assign_rhs2 (assign);
1023 tree ret;
1025 if (!optimize
1026 || !VECTOR_INTEGER_TYPE_P (type)
1027 || TREE_CODE (rhs2) != VECTOR_CST
1028 || !VECTOR_MODE_P (TYPE_MODE (type)))
1029 break;
1031 ret = expand_vector_divmod (gsi, type, rhs1, rhs2, code);
1032 if (ret != NULL_TREE)
1033 return ret;
1034 break;
1037 default:
1038 break;
1041 if (TREE_CODE_CLASS (code) == tcc_unary)
1042 return expand_vector_piecewise (gsi, do_unop, type, compute_type,
1043 gimple_assign_rhs1 (assign),
1044 NULL_TREE, code);
1045 else
1046 return expand_vector_piecewise (gsi, do_binop, type, compute_type,
1047 gimple_assign_rhs1 (assign),
1048 gimple_assign_rhs2 (assign), code);
1051 /* Try to optimize
1052 a_5 = { b_7, b_7 + 3, b_7 + 6, b_7 + 9 };
1053 style stmts into:
1054 _9 = { b_7, b_7, b_7, b_7 };
1055 a_5 = _9 + { 0, 3, 6, 9 };
1056 because vector splat operation is usually more efficient
1057 than piecewise initialization of the vector. */
1059 static void
1060 optimize_vector_constructor (gimple_stmt_iterator *gsi)
1062 gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
1063 tree lhs = gimple_assign_lhs (stmt);
1064 tree rhs = gimple_assign_rhs1 (stmt);
1065 tree type = TREE_TYPE (rhs);
1066 unsigned int i, j, nelts = TYPE_VECTOR_SUBPARTS (type);
1067 bool all_same = true;
1068 constructor_elt *elt;
1069 gimple *g;
1070 tree base = NULL_TREE;
1071 optab op;
1073 if (nelts <= 2 || CONSTRUCTOR_NELTS (rhs) != nelts)
1074 return;
1075 op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
1076 if (op == unknown_optab
1077 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
1078 return;
1079 FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (rhs), i, elt)
1080 if (TREE_CODE (elt->value) != SSA_NAME
1081 || TREE_CODE (TREE_TYPE (elt->value)) == VECTOR_TYPE)
1082 return;
1083 else
1085 tree this_base = elt->value;
1086 if (this_base != CONSTRUCTOR_ELT (rhs, 0)->value)
1087 all_same = false;
1088 for (j = 0; j < nelts + 1; j++)
1090 g = SSA_NAME_DEF_STMT (this_base);
1091 if (is_gimple_assign (g)
1092 && gimple_assign_rhs_code (g) == PLUS_EXPR
1093 && TREE_CODE (gimple_assign_rhs2 (g)) == INTEGER_CST
1094 && TREE_CODE (gimple_assign_rhs1 (g)) == SSA_NAME
1095 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_assign_rhs1 (g)))
1096 this_base = gimple_assign_rhs1 (g);
1097 else
1098 break;
1100 if (i == 0)
1101 base = this_base;
1102 else if (this_base != base)
1103 return;
1105 if (all_same)
1106 return;
1107 auto_vec<tree, 32> cst (nelts);
1108 for (i = 0; i < nelts; i++)
1110 tree this_base = CONSTRUCTOR_ELT (rhs, i)->value;
1111 tree elt = build_zero_cst (TREE_TYPE (base));
1112 while (this_base != base)
1114 g = SSA_NAME_DEF_STMT (this_base);
1115 elt = fold_binary (PLUS_EXPR, TREE_TYPE (base),
1116 elt, gimple_assign_rhs2 (g));
1117 if (elt == NULL_TREE
1118 || TREE_CODE (elt) != INTEGER_CST
1119 || TREE_OVERFLOW (elt))
1120 return;
1121 this_base = gimple_assign_rhs1 (g);
1123 cst.quick_push (elt);
1125 for (i = 0; i < nelts; i++)
1126 CONSTRUCTOR_ELT (rhs, i)->value = base;
1127 g = gimple_build_assign (make_ssa_name (type), rhs);
1128 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1129 g = gimple_build_assign (lhs, PLUS_EXPR, gimple_assign_lhs (g),
1130 build_vector (type, cst));
1131 gsi_replace (gsi, g, false);
1134 /* Return a type for the widest vector mode whose components are of type
1135 TYPE, or NULL_TREE if none is found. */
1137 static tree
1138 type_for_widest_vector_mode (tree type, optab op)
1140 machine_mode inner_mode = TYPE_MODE (type);
1141 machine_mode best_mode = VOIDmode, mode;
1142 int best_nunits = 0;
1144 if (SCALAR_FLOAT_MODE_P (inner_mode))
1145 mode = MIN_MODE_VECTOR_FLOAT;
1146 else if (SCALAR_FRACT_MODE_P (inner_mode))
1147 mode = MIN_MODE_VECTOR_FRACT;
1148 else if (SCALAR_UFRACT_MODE_P (inner_mode))
1149 mode = MIN_MODE_VECTOR_UFRACT;
1150 else if (SCALAR_ACCUM_MODE_P (inner_mode))
1151 mode = MIN_MODE_VECTOR_ACCUM;
1152 else if (SCALAR_UACCUM_MODE_P (inner_mode))
1153 mode = MIN_MODE_VECTOR_UACCUM;
1154 else
1155 mode = MIN_MODE_VECTOR_INT;
1157 FOR_EACH_MODE_FROM (mode, mode)
1158 if (GET_MODE_INNER (mode) == inner_mode
1159 && GET_MODE_NUNITS (mode) > best_nunits
1160 && optab_handler (op, mode) != CODE_FOR_nothing)
1161 best_mode = mode, best_nunits = GET_MODE_NUNITS (mode);
1163 if (best_mode == VOIDmode)
1164 return NULL_TREE;
1165 else
1166 return build_vector_type_for_mode (type, best_mode);
1170 /* Build a reference to the element of the vector VECT. Function
1171 returns either the element itself, either BIT_FIELD_REF, or an
1172 ARRAY_REF expression.
1174 GSI is required to insert temporary variables while building a
1175 refernece to the element of the vector VECT.
1177 PTMPVEC is a pointer to the temporary variable for caching
1178 purposes. In case when PTMPVEC is NULL new temporary variable
1179 will be created. */
1180 static tree
1181 vector_element (gimple_stmt_iterator *gsi, tree vect, tree idx, tree *ptmpvec)
1183 tree vect_type, vect_elt_type;
1184 gimple *asgn;
1185 tree tmpvec;
1186 tree arraytype;
1187 bool need_asgn = true;
1188 unsigned int elements;
1190 vect_type = TREE_TYPE (vect);
1191 vect_elt_type = TREE_TYPE (vect_type);
1192 elements = TYPE_VECTOR_SUBPARTS (vect_type);
1194 if (TREE_CODE (idx) == INTEGER_CST)
1196 unsigned HOST_WIDE_INT index;
1198 /* Given that we're about to compute a binary modulus,
1199 we don't care about the high bits of the value. */
1200 index = TREE_INT_CST_LOW (idx);
1201 if (!tree_fits_uhwi_p (idx) || index >= elements)
1203 index &= elements - 1;
1204 idx = build_int_cst (TREE_TYPE (idx), index);
1207 /* When lowering a vector statement sequence do some easy
1208 simplification by looking through intermediate vector results. */
1209 if (TREE_CODE (vect) == SSA_NAME)
1211 gimple *def_stmt = SSA_NAME_DEF_STMT (vect);
1212 if (is_gimple_assign (def_stmt)
1213 && (gimple_assign_rhs_code (def_stmt) == VECTOR_CST
1214 || gimple_assign_rhs_code (def_stmt) == CONSTRUCTOR))
1215 vect = gimple_assign_rhs1 (def_stmt);
1218 if (TREE_CODE (vect) == VECTOR_CST)
1219 return VECTOR_CST_ELT (vect, index);
1220 else if (TREE_CODE (vect) == CONSTRUCTOR
1221 && (CONSTRUCTOR_NELTS (vect) == 0
1222 || TREE_CODE (TREE_TYPE (CONSTRUCTOR_ELT (vect, 0)->value))
1223 != VECTOR_TYPE))
1225 if (index < CONSTRUCTOR_NELTS (vect))
1226 return CONSTRUCTOR_ELT (vect, index)->value;
1227 return build_zero_cst (vect_elt_type);
1229 else
1231 tree size = TYPE_SIZE (vect_elt_type);
1232 tree pos = fold_build2 (MULT_EXPR, bitsizetype, bitsize_int (index),
1233 size);
1234 return fold_build3 (BIT_FIELD_REF, vect_elt_type, vect, size, pos);
1238 if (!ptmpvec)
1239 tmpvec = create_tmp_var (vect_type, "vectmp");
1240 else if (!*ptmpvec)
1241 tmpvec = *ptmpvec = create_tmp_var (vect_type, "vectmp");
1242 else
1244 tmpvec = *ptmpvec;
1245 need_asgn = false;
1248 if (need_asgn)
1250 TREE_ADDRESSABLE (tmpvec) = 1;
1251 asgn = gimple_build_assign (tmpvec, vect);
1252 gsi_insert_before (gsi, asgn, GSI_SAME_STMT);
1255 arraytype = build_array_type_nelts (vect_elt_type, elements);
1256 return build4 (ARRAY_REF, vect_elt_type,
1257 build1 (VIEW_CONVERT_EXPR, arraytype, tmpvec),
1258 idx, NULL_TREE, NULL_TREE);
1261 /* Check if VEC_PERM_EXPR within the given setting is supported
1262 by hardware, or lower it piecewise.
1264 When VEC_PERM_EXPR has the same first and second operands:
1265 VEC_PERM_EXPR <v0, v0, mask> the lowered version would be
1266 {v0[mask[0]], v0[mask[1]], ...}
1267 MASK and V0 must have the same number of elements.
1269 Otherwise VEC_PERM_EXPR <v0, v1, mask> is lowered to
1270 {mask[0] < len(v0) ? v0[mask[0]] : v1[mask[0]], ...}
1271 V0 and V1 must have the same type. MASK, V0, V1 must have the
1272 same number of arguments. */
1274 static void
1275 lower_vec_perm (gimple_stmt_iterator *gsi)
1277 gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
1278 tree mask = gimple_assign_rhs3 (stmt);
1279 tree vec0 = gimple_assign_rhs1 (stmt);
1280 tree vec1 = gimple_assign_rhs2 (stmt);
1281 tree vect_type = TREE_TYPE (vec0);
1282 tree mask_type = TREE_TYPE (mask);
1283 tree vect_elt_type = TREE_TYPE (vect_type);
1284 tree mask_elt_type = TREE_TYPE (mask_type);
1285 unsigned int elements = TYPE_VECTOR_SUBPARTS (vect_type);
1286 vec<constructor_elt, va_gc> *v;
1287 tree constr, t, si, i_val;
1288 tree vec0tmp = NULL_TREE, vec1tmp = NULL_TREE, masktmp = NULL_TREE;
1289 bool two_operand_p = !operand_equal_p (vec0, vec1, 0);
1290 location_t loc = gimple_location (gsi_stmt (*gsi));
1291 unsigned i;
1293 if (TREE_CODE (mask) == SSA_NAME)
1295 gimple *def_stmt = SSA_NAME_DEF_STMT (mask);
1296 if (is_gimple_assign (def_stmt)
1297 && gimple_assign_rhs_code (def_stmt) == VECTOR_CST)
1298 mask = gimple_assign_rhs1 (def_stmt);
1301 if (TREE_CODE (mask) == VECTOR_CST)
1303 auto_vec_perm_indices sel_int (elements);
1305 for (i = 0; i < elements; ++i)
1306 sel_int.quick_push (TREE_INT_CST_LOW (VECTOR_CST_ELT (mask, i))
1307 & (2 * elements - 1));
1309 if (can_vec_perm_p (TYPE_MODE (vect_type), false, &sel_int))
1311 gimple_assign_set_rhs3 (stmt, mask);
1312 update_stmt (stmt);
1313 return;
1315 /* Also detect vec_shr pattern - VEC_PERM_EXPR with zero
1316 vector as VEC1 and a right element shift MASK. */
1317 if (optab_handler (vec_shr_optab, TYPE_MODE (vect_type))
1318 != CODE_FOR_nothing
1319 && TREE_CODE (vec1) == VECTOR_CST
1320 && initializer_zerop (vec1)
1321 && sel_int[0]
1322 && sel_int[0] < elements)
1324 for (i = 1; i < elements; ++i)
1326 unsigned int expected = i + sel_int[0];
1327 /* Indices into the second vector are all equivalent. */
1328 if (MIN (elements, (unsigned) sel_int[i])
1329 != MIN (elements, expected))
1330 break;
1332 if (i == elements)
1334 gimple_assign_set_rhs3 (stmt, mask);
1335 update_stmt (stmt);
1336 return;
1340 else if (can_vec_perm_p (TYPE_MODE (vect_type), true, NULL))
1341 return;
1343 warning_at (loc, OPT_Wvector_operation_performance,
1344 "vector shuffling operation will be expanded piecewise");
1346 vec_alloc (v, elements);
1347 for (i = 0; i < elements; i++)
1349 si = size_int (i);
1350 i_val = vector_element (gsi, mask, si, &masktmp);
1352 if (TREE_CODE (i_val) == INTEGER_CST)
1354 unsigned HOST_WIDE_INT index;
1356 index = TREE_INT_CST_LOW (i_val);
1357 if (!tree_fits_uhwi_p (i_val) || index >= elements)
1358 i_val = build_int_cst (mask_elt_type, index & (elements - 1));
1360 if (two_operand_p && (index & elements) != 0)
1361 t = vector_element (gsi, vec1, i_val, &vec1tmp);
1362 else
1363 t = vector_element (gsi, vec0, i_val, &vec0tmp);
1365 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE,
1366 true, GSI_SAME_STMT);
1368 else
1370 tree cond = NULL_TREE, v0_val;
1372 if (two_operand_p)
1374 cond = fold_build2 (BIT_AND_EXPR, mask_elt_type, i_val,
1375 build_int_cst (mask_elt_type, elements));
1376 cond = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE,
1377 true, GSI_SAME_STMT);
1380 i_val = fold_build2 (BIT_AND_EXPR, mask_elt_type, i_val,
1381 build_int_cst (mask_elt_type, elements - 1));
1382 i_val = force_gimple_operand_gsi (gsi, i_val, true, NULL_TREE,
1383 true, GSI_SAME_STMT);
1385 v0_val = vector_element (gsi, vec0, i_val, &vec0tmp);
1386 v0_val = force_gimple_operand_gsi (gsi, v0_val, true, NULL_TREE,
1387 true, GSI_SAME_STMT);
1389 if (two_operand_p)
1391 tree v1_val;
1393 v1_val = vector_element (gsi, vec1, i_val, &vec1tmp);
1394 v1_val = force_gimple_operand_gsi (gsi, v1_val, true, NULL_TREE,
1395 true, GSI_SAME_STMT);
1397 cond = fold_build2 (EQ_EXPR, boolean_type_node,
1398 cond, build_zero_cst (mask_elt_type));
1399 cond = fold_build3 (COND_EXPR, vect_elt_type,
1400 cond, v0_val, v1_val);
1401 t = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE,
1402 true, GSI_SAME_STMT);
1404 else
1405 t = v0_val;
1408 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, t);
1411 constr = build_constructor (vect_type, v);
1412 gimple_assign_set_rhs_from_tree (gsi, constr);
1413 update_stmt (gsi_stmt (*gsi));
1416 /* If OP is a uniform vector return the element it is a splat from. */
1418 static tree
1419 ssa_uniform_vector_p (tree op)
1421 if (TREE_CODE (op) == VECTOR_CST
1422 || TREE_CODE (op) == CONSTRUCTOR)
1423 return uniform_vector_p (op);
1424 if (TREE_CODE (op) == SSA_NAME)
1426 gimple *def_stmt = SSA_NAME_DEF_STMT (op);
1427 if (gimple_assign_single_p (def_stmt))
1428 return uniform_vector_p (gimple_assign_rhs1 (def_stmt));
1430 return NULL_TREE;
1433 /* Return type in which CODE operation with optab OP can be
1434 computed. */
1436 static tree
1437 get_compute_type (enum tree_code code, optab op, tree type)
1439 /* For very wide vectors, try using a smaller vector mode. */
1440 tree compute_type = type;
1441 if (op
1442 && (!VECTOR_MODE_P (TYPE_MODE (type))
1443 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing))
1445 tree vector_compute_type
1446 = type_for_widest_vector_mode (TREE_TYPE (type), op);
1447 if (vector_compute_type != NULL_TREE
1448 && (TYPE_VECTOR_SUBPARTS (vector_compute_type)
1449 < TYPE_VECTOR_SUBPARTS (compute_type))
1450 && TYPE_VECTOR_SUBPARTS (vector_compute_type) > 1
1451 && (optab_handler (op, TYPE_MODE (vector_compute_type))
1452 != CODE_FOR_nothing))
1453 compute_type = vector_compute_type;
1456 /* If we are breaking a BLKmode vector into smaller pieces,
1457 type_for_widest_vector_mode has already looked into the optab,
1458 so skip these checks. */
1459 if (compute_type == type)
1461 machine_mode compute_mode = TYPE_MODE (compute_type);
1462 if (VECTOR_MODE_P (compute_mode))
1464 if (op && optab_handler (op, compute_mode) != CODE_FOR_nothing)
1465 return compute_type;
1466 if (code == MULT_HIGHPART_EXPR
1467 && can_mult_highpart_p (compute_mode,
1468 TYPE_UNSIGNED (compute_type)))
1469 return compute_type;
1471 /* There is no operation in hardware, so fall back to scalars. */
1472 compute_type = TREE_TYPE (type);
1475 return compute_type;
1478 /* Helper function of expand_vector_operations_1. Return number of
1479 vector elements for vector types or 1 for other types. */
1481 static inline int
1482 count_type_subparts (tree type)
1484 return VECTOR_TYPE_P (type) ? TYPE_VECTOR_SUBPARTS (type) : 1;
1487 static tree
1488 do_cond (gimple_stmt_iterator *gsi, tree inner_type, tree a, tree b,
1489 tree bitpos, tree bitsize, enum tree_code code,
1490 tree type ATTRIBUTE_UNUSED)
1492 if (TREE_CODE (TREE_TYPE (a)) == VECTOR_TYPE)
1493 a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
1494 if (TREE_CODE (TREE_TYPE (b)) == VECTOR_TYPE)
1495 b = tree_vec_extract (gsi, inner_type, b, bitsize, bitpos);
1496 tree cond = gimple_assign_rhs1 (gsi_stmt (*gsi));
1497 return gimplify_build3 (gsi, code, inner_type, unshare_expr (cond), a, b);
1500 /* Expand a vector COND_EXPR to scalars, piecewise. */
1501 static void
1502 expand_vector_scalar_condition (gimple_stmt_iterator *gsi)
1504 gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
1505 tree type = gimple_expr_type (stmt);
1506 tree compute_type = get_compute_type (COND_EXPR, mov_optab, type);
1507 machine_mode compute_mode = TYPE_MODE (compute_type);
1508 gcc_assert (compute_mode != BLKmode);
1509 tree lhs = gimple_assign_lhs (stmt);
1510 tree rhs2 = gimple_assign_rhs2 (stmt);
1511 tree rhs3 = gimple_assign_rhs3 (stmt);
1512 tree new_rhs;
1514 /* If the compute mode is not a vector mode (hence we are not decomposing
1515 a BLKmode vector to smaller, hardware-supported vectors), we may want
1516 to expand the operations in parallel. */
1517 if (GET_MODE_CLASS (compute_mode) != MODE_VECTOR_INT
1518 && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_FLOAT
1519 && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_FRACT
1520 && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_UFRACT
1521 && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_ACCUM
1522 && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_UACCUM)
1523 new_rhs = expand_vector_parallel (gsi, do_cond, type, rhs2, rhs3,
1524 COND_EXPR);
1525 else
1526 new_rhs = expand_vector_piecewise (gsi, do_cond, type, compute_type,
1527 rhs2, rhs3, COND_EXPR);
1528 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (new_rhs)))
1529 new_rhs = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, TREE_TYPE (lhs),
1530 new_rhs);
1532 /* NOTE: We should avoid using gimple_assign_set_rhs_from_tree. One
1533 way to do it is change expand_vector_operation and its callees to
1534 return a tree_code, RHS1 and RHS2 instead of a tree. */
1535 gimple_assign_set_rhs_from_tree (gsi, new_rhs);
1536 update_stmt (gsi_stmt (*gsi));
1539 /* Process one statement. If we identify a vector operation, expand it. */
1541 static void
1542 expand_vector_operations_1 (gimple_stmt_iterator *gsi)
1544 tree lhs, rhs1, rhs2 = NULL, type, compute_type = NULL_TREE;
1545 enum tree_code code;
1546 optab op = unknown_optab;
1547 enum gimple_rhs_class rhs_class;
1548 tree new_rhs;
1550 /* Only consider code == GIMPLE_ASSIGN. */
1551 gassign *stmt = dyn_cast <gassign *> (gsi_stmt (*gsi));
1552 if (!stmt)
1553 return;
1555 code = gimple_assign_rhs_code (stmt);
1556 rhs_class = get_gimple_rhs_class (code);
1557 lhs = gimple_assign_lhs (stmt);
1559 if (code == VEC_PERM_EXPR)
1561 lower_vec_perm (gsi);
1562 return;
1565 if (code == VEC_COND_EXPR)
1567 expand_vector_condition (gsi);
1568 return;
1571 if (code == COND_EXPR
1572 && TREE_CODE (TREE_TYPE (gimple_assign_lhs (stmt))) == VECTOR_TYPE
1573 && TYPE_MODE (TREE_TYPE (gimple_assign_lhs (stmt))) == BLKmode)
1575 expand_vector_scalar_condition (gsi);
1576 return;
1579 if (code == CONSTRUCTOR
1580 && TREE_CODE (lhs) == SSA_NAME
1581 && VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (lhs)))
1582 && !gimple_clobber_p (stmt)
1583 && optimize)
1585 optimize_vector_constructor (gsi);
1586 return;
1589 if (rhs_class != GIMPLE_UNARY_RHS && rhs_class != GIMPLE_BINARY_RHS)
1590 return;
1592 rhs1 = gimple_assign_rhs1 (stmt);
1593 type = gimple_expr_type (stmt);
1594 if (rhs_class == GIMPLE_BINARY_RHS)
1595 rhs2 = gimple_assign_rhs2 (stmt);
1597 if (TREE_CODE (type) != VECTOR_TYPE)
1598 return;
1600 /* If the vector operation is operating on all same vector elements
1601 implement it with a scalar operation and a splat if the target
1602 supports the scalar operation. */
1603 tree srhs1, srhs2 = NULL_TREE;
1604 if ((srhs1 = ssa_uniform_vector_p (rhs1)) != NULL_TREE
1605 && (rhs2 == NULL_TREE
1606 || (! VECTOR_TYPE_P (TREE_TYPE (rhs2))
1607 && (srhs2 = rhs2))
1608 || (srhs2 = ssa_uniform_vector_p (rhs2)) != NULL_TREE)
1609 /* As we query direct optabs restrict to non-convert operations. */
1610 && TYPE_MODE (TREE_TYPE (type)) == TYPE_MODE (TREE_TYPE (srhs1)))
1612 op = optab_for_tree_code (code, TREE_TYPE (type), optab_scalar);
1613 if (op >= FIRST_NORM_OPTAB && op <= LAST_NORM_OPTAB
1614 && optab_handler (op, TYPE_MODE (TREE_TYPE (type))) != CODE_FOR_nothing)
1616 tree slhs = make_ssa_name (TREE_TYPE (srhs1));
1617 gimple *repl = gimple_build_assign (slhs, code, srhs1, srhs2);
1618 gsi_insert_before (gsi, repl, GSI_SAME_STMT);
1619 gimple_assign_set_rhs_from_tree (gsi,
1620 build_vector_from_val (type, slhs));
1621 update_stmt (stmt);
1622 return;
1626 /* A scalar operation pretending to be a vector one. */
1627 if (VECTOR_BOOLEAN_TYPE_P (type)
1628 && !VECTOR_MODE_P (TYPE_MODE (type))
1629 && TYPE_MODE (type) != BLKmode)
1630 return;
1632 if (CONVERT_EXPR_CODE_P (code)
1633 || code == FLOAT_EXPR
1634 || code == FIX_TRUNC_EXPR
1635 || code == VIEW_CONVERT_EXPR)
1636 return;
1638 /* The signedness is determined from input argument. */
1639 if (code == VEC_UNPACK_FLOAT_HI_EXPR
1640 || code == VEC_UNPACK_FLOAT_LO_EXPR)
1642 type = TREE_TYPE (rhs1);
1643 /* We do not know how to scalarize those. */
1644 return;
1647 /* For widening/narrowing vector operations, the relevant type is of the
1648 arguments, not the widened result. VEC_UNPACK_FLOAT_*_EXPR is
1649 calculated in the same way above. */
1650 if (code == WIDEN_SUM_EXPR
1651 || code == VEC_WIDEN_MULT_HI_EXPR
1652 || code == VEC_WIDEN_MULT_LO_EXPR
1653 || code == VEC_WIDEN_MULT_EVEN_EXPR
1654 || code == VEC_WIDEN_MULT_ODD_EXPR
1655 || code == VEC_UNPACK_HI_EXPR
1656 || code == VEC_UNPACK_LO_EXPR
1657 || code == VEC_PACK_TRUNC_EXPR
1658 || code == VEC_PACK_SAT_EXPR
1659 || code == VEC_PACK_FIX_TRUNC_EXPR
1660 || code == VEC_WIDEN_LSHIFT_HI_EXPR
1661 || code == VEC_WIDEN_LSHIFT_LO_EXPR)
1663 type = TREE_TYPE (rhs1);
1664 /* We do not know how to scalarize those. */
1665 return;
1668 /* Choose between vector shift/rotate by vector and vector shift/rotate by
1669 scalar */
1670 if (code == LSHIFT_EXPR
1671 || code == RSHIFT_EXPR
1672 || code == LROTATE_EXPR
1673 || code == RROTATE_EXPR)
1675 optab opv;
1677 /* Check whether we have vector <op> {x,x,x,x} where x
1678 could be a scalar variable or a constant. Transform
1679 vector <op> {x,x,x,x} ==> vector <op> scalar. */
1680 if (VECTOR_INTEGER_TYPE_P (TREE_TYPE (rhs2)))
1682 tree first;
1684 if ((first = ssa_uniform_vector_p (rhs2)) != NULL_TREE)
1686 gimple_assign_set_rhs2 (stmt, first);
1687 update_stmt (stmt);
1688 rhs2 = first;
1692 opv = optab_for_tree_code (code, type, optab_vector);
1693 if (VECTOR_INTEGER_TYPE_P (TREE_TYPE (rhs2)))
1694 op = opv;
1695 else
1697 op = optab_for_tree_code (code, type, optab_scalar);
1699 compute_type = get_compute_type (code, op, type);
1700 if (compute_type == type)
1701 return;
1702 /* The rtl expander will expand vector/scalar as vector/vector
1703 if necessary. Pick one with wider vector type. */
1704 tree compute_vtype = get_compute_type (code, opv, type);
1705 if (count_type_subparts (compute_vtype)
1706 > count_type_subparts (compute_type))
1708 compute_type = compute_vtype;
1709 op = opv;
1713 if (code == LROTATE_EXPR || code == RROTATE_EXPR)
1715 if (compute_type == NULL_TREE)
1716 compute_type = get_compute_type (code, op, type);
1717 if (compute_type == type)
1718 return;
1719 /* Before splitting vector rotates into scalar rotates,
1720 see if we can't use vector shifts and BIT_IOR_EXPR
1721 instead. For vector by vector rotates we'd also
1722 need to check BIT_AND_EXPR and NEGATE_EXPR, punt there
1723 for now, fold doesn't seem to create such rotates anyway. */
1724 if (compute_type == TREE_TYPE (type)
1725 && !VECTOR_INTEGER_TYPE_P (TREE_TYPE (rhs2)))
1727 optab oplv = vashl_optab, opl = ashl_optab;
1728 optab oprv = vlshr_optab, opr = lshr_optab, opo = ior_optab;
1729 tree compute_lvtype = get_compute_type (LSHIFT_EXPR, oplv, type);
1730 tree compute_rvtype = get_compute_type (RSHIFT_EXPR, oprv, type);
1731 tree compute_otype = get_compute_type (BIT_IOR_EXPR, opo, type);
1732 tree compute_ltype = get_compute_type (LSHIFT_EXPR, opl, type);
1733 tree compute_rtype = get_compute_type (RSHIFT_EXPR, opr, type);
1734 /* The rtl expander will expand vector/scalar as vector/vector
1735 if necessary. Pick one with wider vector type. */
1736 if (count_type_subparts (compute_lvtype)
1737 > count_type_subparts (compute_ltype))
1739 compute_ltype = compute_lvtype;
1740 opl = oplv;
1742 if (count_type_subparts (compute_rvtype)
1743 > count_type_subparts (compute_rtype))
1745 compute_rtype = compute_rvtype;
1746 opr = oprv;
1748 /* Pick the narrowest type from LSHIFT_EXPR, RSHIFT_EXPR and
1749 BIT_IOR_EXPR. */
1750 compute_type = compute_ltype;
1751 if (count_type_subparts (compute_type)
1752 > count_type_subparts (compute_rtype))
1753 compute_type = compute_rtype;
1754 if (count_type_subparts (compute_type)
1755 > count_type_subparts (compute_otype))
1756 compute_type = compute_otype;
1757 /* Verify all 3 operations can be performed in that type. */
1758 if (compute_type != TREE_TYPE (type))
1760 if (optab_handler (opl, TYPE_MODE (compute_type))
1761 == CODE_FOR_nothing
1762 || optab_handler (opr, TYPE_MODE (compute_type))
1763 == CODE_FOR_nothing
1764 || optab_handler (opo, TYPE_MODE (compute_type))
1765 == CODE_FOR_nothing)
1766 compute_type = TREE_TYPE (type);
1771 else
1772 op = optab_for_tree_code (code, type, optab_default);
1774 /* Optabs will try converting a negation into a subtraction, so
1775 look for it as well. TODO: negation of floating-point vectors
1776 might be turned into an exclusive OR toggling the sign bit. */
1777 if (op == unknown_optab
1778 && code == NEGATE_EXPR
1779 && INTEGRAL_TYPE_P (TREE_TYPE (type)))
1780 op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
1782 if (compute_type == NULL_TREE)
1783 compute_type = get_compute_type (code, op, type);
1784 if (compute_type == type)
1785 return;
1787 new_rhs = expand_vector_operation (gsi, type, compute_type, stmt, code);
1789 /* Leave expression untouched for later expansion. */
1790 if (new_rhs == NULL_TREE)
1791 return;
1793 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (new_rhs)))
1794 new_rhs = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, TREE_TYPE (lhs),
1795 new_rhs);
1797 /* NOTE: We should avoid using gimple_assign_set_rhs_from_tree. One
1798 way to do it is change expand_vector_operation and its callees to
1799 return a tree_code, RHS1 and RHS2 instead of a tree. */
1800 gimple_assign_set_rhs_from_tree (gsi, new_rhs);
1801 update_stmt (gsi_stmt (*gsi));
1804 /* Use this to lower vector operations introduced by the vectorizer,
1805 if it may need the bit-twiddling tricks implemented in this file. */
1807 static unsigned int
1808 expand_vector_operations (void)
1810 gimple_stmt_iterator gsi;
1811 basic_block bb;
1812 bool cfg_changed = false;
1814 FOR_EACH_BB_FN (bb, cfun)
1816 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
1818 expand_vector_operations_1 (&gsi);
1819 /* ??? If we do not cleanup EH then we will ICE in
1820 verification. But in reality we have created wrong-code
1821 as we did not properly transition EH info and edges to
1822 the piecewise computations. */
1823 if (maybe_clean_eh_stmt (gsi_stmt (gsi))
1824 && gimple_purge_dead_eh_edges (bb))
1825 cfg_changed = true;
1829 return cfg_changed ? TODO_cleanup_cfg : 0;
1832 namespace {
1834 const pass_data pass_data_lower_vector =
1836 GIMPLE_PASS, /* type */
1837 "veclower", /* name */
1838 OPTGROUP_VEC, /* optinfo_flags */
1839 TV_NONE, /* tv_id */
1840 PROP_cfg, /* properties_required */
1841 PROP_gimple_lvec, /* properties_provided */
1842 0, /* properties_destroyed */
1843 0, /* todo_flags_start */
1844 TODO_update_ssa, /* todo_flags_finish */
1847 class pass_lower_vector : public gimple_opt_pass
1849 public:
1850 pass_lower_vector (gcc::context *ctxt)
1851 : gimple_opt_pass (pass_data_lower_vector, ctxt)
1854 /* opt_pass methods: */
1855 virtual bool gate (function *fun)
1857 return !(fun->curr_properties & PROP_gimple_lvec);
1860 virtual unsigned int execute (function *)
1862 return expand_vector_operations ();
1865 }; // class pass_lower_vector
1867 } // anon namespace
1869 gimple_opt_pass *
1870 make_pass_lower_vector (gcc::context *ctxt)
1872 return new pass_lower_vector (ctxt);
1875 namespace {
1877 const pass_data pass_data_lower_vector_ssa =
1879 GIMPLE_PASS, /* type */
1880 "veclower2", /* name */
1881 OPTGROUP_VEC, /* optinfo_flags */
1882 TV_NONE, /* tv_id */
1883 PROP_cfg, /* properties_required */
1884 PROP_gimple_lvec, /* properties_provided */
1885 0, /* properties_destroyed */
1886 0, /* todo_flags_start */
1887 ( TODO_update_ssa
1888 | TODO_cleanup_cfg ), /* todo_flags_finish */
1891 class pass_lower_vector_ssa : public gimple_opt_pass
1893 public:
1894 pass_lower_vector_ssa (gcc::context *ctxt)
1895 : gimple_opt_pass (pass_data_lower_vector_ssa, ctxt)
1898 /* opt_pass methods: */
1899 opt_pass * clone () { return new pass_lower_vector_ssa (m_ctxt); }
1900 virtual unsigned int execute (function *)
1902 return expand_vector_operations ();
1905 }; // class pass_lower_vector_ssa
1907 } // anon namespace
1909 gimple_opt_pass *
1910 make_pass_lower_vector_ssa (gcc::context *ctxt)
1912 return new pass_lower_vector_ssa (ctxt);
1915 #include "gt-tree-vect-generic.h"