]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/tree-vect-generic.c
a7fe83da0e3810c0a2c6b6c26a15417dd284ef5f
[thirdparty/gcc.git] / gcc / tree-vect-generic.c
1 /* Lower vector operations to scalar operations.
2 Copyright (C) 2004-2020 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
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.
10
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.
15
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/>. */
19
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"
40 #include "tree-vector-builder.h"
41 #include "vec-perm-indices.h"
42 #include "insn-config.h"
43 #include "recog.h" /* FIXME: for insn_data */
44
45
46 static void expand_vector_operations_1 (gimple_stmt_iterator *);
47
48 /* Return the number of elements in a vector type TYPE that we have
49 already decided needs to be expanded piecewise. We don't support
50 this kind of expansion for variable-length vectors, since we should
51 always check for target support before introducing uses of those. */
52 static unsigned int
53 nunits_for_known_piecewise_op (const_tree type)
54 {
55 return TYPE_VECTOR_SUBPARTS (type).to_constant ();
56 }
57
58 /* Return true if TYPE1 has more elements than TYPE2, where either
59 type may be a vector or a scalar. */
60
61 static inline bool
62 subparts_gt (tree type1, tree type2)
63 {
64 poly_uint64 n1 = VECTOR_TYPE_P (type1) ? TYPE_VECTOR_SUBPARTS (type1) : 1;
65 poly_uint64 n2 = VECTOR_TYPE_P (type2) ? TYPE_VECTOR_SUBPARTS (type2) : 1;
66 return known_gt (n1, n2);
67 }
68
69 /* Build a constant of type TYPE, made of VALUE's bits replicated
70 every WIDTH bits to fit TYPE's precision. */
71 static tree
72 build_replicated_const (tree type, unsigned int width, HOST_WIDE_INT value)
73 {
74 int n = (TYPE_PRECISION (type) + HOST_BITS_PER_WIDE_INT - 1)
75 / HOST_BITS_PER_WIDE_INT;
76 unsigned HOST_WIDE_INT low, mask;
77 HOST_WIDE_INT a[WIDE_INT_MAX_ELTS];
78 int i;
79
80 gcc_assert (n && n <= WIDE_INT_MAX_ELTS);
81
82 if (width == HOST_BITS_PER_WIDE_INT)
83 low = value;
84 else
85 {
86 mask = ((HOST_WIDE_INT)1 << width) - 1;
87 low = (unsigned HOST_WIDE_INT) ~0 / mask * (value & mask);
88 }
89
90 for (i = 0; i < n; i++)
91 a[i] = low;
92
93 gcc_assert (TYPE_PRECISION (type) <= MAX_BITSIZE_MODE_ANY_INT);
94 return wide_int_to_tree
95 (type, wide_int::from_array (a, n, TYPE_PRECISION (type)));
96 }
97
98 static GTY(()) tree vector_inner_type;
99 static GTY(()) tree vector_last_type;
100 static GTY(()) int vector_last_nunits;
101
102 /* Return a suitable vector types made of SUBPARTS units each of mode
103 "word_mode" (the global variable). */
104 static tree
105 build_word_mode_vector_type (int nunits)
106 {
107 if (!vector_inner_type)
108 vector_inner_type = lang_hooks.types.type_for_mode (word_mode, 1);
109 else if (vector_last_nunits == nunits)
110 {
111 gcc_assert (TREE_CODE (vector_last_type) == VECTOR_TYPE);
112 return vector_last_type;
113 }
114
115 vector_last_nunits = nunits;
116 vector_last_type = build_vector_type (vector_inner_type, nunits);
117 return vector_last_type;
118 }
119
120 typedef tree (*elem_op_func) (gimple_stmt_iterator *,
121 tree, tree, tree, tree, tree, enum tree_code,
122 tree);
123
124 tree
125 tree_vec_extract (gimple_stmt_iterator *gsi, tree type,
126 tree t, tree bitsize, tree bitpos)
127 {
128 if (TREE_CODE (t) == SSA_NAME)
129 {
130 gimple *def_stmt = SSA_NAME_DEF_STMT (t);
131 if (is_gimple_assign (def_stmt)
132 && (gimple_assign_rhs_code (def_stmt) == VECTOR_CST
133 || (bitpos
134 && gimple_assign_rhs_code (def_stmt) == CONSTRUCTOR)))
135 t = gimple_assign_rhs1 (def_stmt);
136 }
137 if (bitpos)
138 {
139 if (TREE_CODE (type) == BOOLEAN_TYPE)
140 {
141 tree itype
142 = build_nonstandard_integer_type (tree_to_uhwi (bitsize), 0);
143 tree field = gimplify_build3 (gsi, BIT_FIELD_REF, itype, t,
144 bitsize, bitpos);
145 return gimplify_build2 (gsi, NE_EXPR, type, field,
146 build_zero_cst (itype));
147 }
148 else
149 return gimplify_build3 (gsi, BIT_FIELD_REF, type, t, bitsize, bitpos);
150 }
151 else
152 return gimplify_build1 (gsi, VIEW_CONVERT_EXPR, type, t);
153 }
154
155 static tree
156 do_unop (gimple_stmt_iterator *gsi, tree inner_type, tree a,
157 tree b ATTRIBUTE_UNUSED, tree bitpos, tree bitsize,
158 enum tree_code code, tree type ATTRIBUTE_UNUSED)
159 {
160 a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
161 return gimplify_build1 (gsi, code, inner_type, a);
162 }
163
164 static tree
165 do_binop (gimple_stmt_iterator *gsi, tree inner_type, tree a, tree b,
166 tree bitpos, tree bitsize, enum tree_code code,
167 tree type ATTRIBUTE_UNUSED)
168 {
169 if (TREE_CODE (TREE_TYPE (a)) == VECTOR_TYPE)
170 a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
171 if (TREE_CODE (TREE_TYPE (b)) == VECTOR_TYPE)
172 b = tree_vec_extract (gsi, inner_type, b, bitsize, bitpos);
173 return gimplify_build2 (gsi, code, inner_type, a, b);
174 }
175
176 /* Construct expression (A[BITPOS] code B[BITPOS]) ? -1 : 0
177
178 INNER_TYPE is the type of A and B elements
179
180 returned expression is of signed integer type with the
181 size equal to the size of INNER_TYPE. */
182 static tree
183 do_compare (gimple_stmt_iterator *gsi, tree inner_type, tree a, tree b,
184 tree bitpos, tree bitsize, enum tree_code code, tree type)
185 {
186 tree stype = TREE_TYPE (type);
187 tree cst_false = build_zero_cst (stype);
188 tree cst_true = build_all_ones_cst (stype);
189 tree cmp;
190
191 a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
192 b = tree_vec_extract (gsi, inner_type, b, bitsize, bitpos);
193
194 cmp = build2 (code, boolean_type_node, a, b);
195 return gimplify_build3 (gsi, COND_EXPR, stype, cmp, cst_true, cst_false);
196 }
197
198 /* Expand vector addition to scalars. This does bit twiddling
199 in order to increase parallelism:
200
201 a + b = (((int) a & 0x7f7f7f7f) + ((int) b & 0x7f7f7f7f)) ^
202 (a ^ b) & 0x80808080
203
204 a - b = (((int) a | 0x80808080) - ((int) b & 0x7f7f7f7f)) ^
205 (a ^ ~b) & 0x80808080
206
207 -b = (0x80808080 - ((int) b & 0x7f7f7f7f)) ^ (~b & 0x80808080)
208
209 This optimization should be done only if 4 vector items or more
210 fit into a word. */
211 static tree
212 do_plus_minus (gimple_stmt_iterator *gsi, tree word_type, tree a, tree b,
213 tree bitpos ATTRIBUTE_UNUSED, tree bitsize ATTRIBUTE_UNUSED,
214 enum tree_code code, tree type ATTRIBUTE_UNUSED)
215 {
216 unsigned int width = vector_element_bits (TREE_TYPE (a));
217 tree inner_type = TREE_TYPE (TREE_TYPE (a));
218 unsigned HOST_WIDE_INT max;
219 tree low_bits, high_bits, a_low, b_low, result_low, signs;
220
221 max = GET_MODE_MASK (TYPE_MODE (inner_type));
222 low_bits = build_replicated_const (word_type, width, max >> 1);
223 high_bits = build_replicated_const (word_type, width, max & ~(max >> 1));
224
225 a = tree_vec_extract (gsi, word_type, a, bitsize, bitpos);
226 b = tree_vec_extract (gsi, word_type, b, bitsize, bitpos);
227
228 signs = gimplify_build2 (gsi, BIT_XOR_EXPR, word_type, a, b);
229 b_low = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, b, low_bits);
230 if (code == PLUS_EXPR)
231 a_low = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, a, low_bits);
232 else
233 {
234 a_low = gimplify_build2 (gsi, BIT_IOR_EXPR, word_type, a, high_bits);
235 signs = gimplify_build1 (gsi, BIT_NOT_EXPR, word_type, signs);
236 }
237
238 signs = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, signs, high_bits);
239 result_low = gimplify_build2 (gsi, code, word_type, a_low, b_low);
240 return gimplify_build2 (gsi, BIT_XOR_EXPR, word_type, result_low, signs);
241 }
242
243 static tree
244 do_negate (gimple_stmt_iterator *gsi, tree word_type, tree b,
245 tree unused ATTRIBUTE_UNUSED, tree bitpos ATTRIBUTE_UNUSED,
246 tree bitsize ATTRIBUTE_UNUSED,
247 enum tree_code code ATTRIBUTE_UNUSED,
248 tree type ATTRIBUTE_UNUSED)
249 {
250 unsigned int width = vector_element_bits (TREE_TYPE (b));
251 tree inner_type = TREE_TYPE (TREE_TYPE (b));
252 HOST_WIDE_INT max;
253 tree low_bits, high_bits, b_low, result_low, signs;
254
255 max = GET_MODE_MASK (TYPE_MODE (inner_type));
256 low_bits = build_replicated_const (word_type, width, max >> 1);
257 high_bits = build_replicated_const (word_type, width, max & ~(max >> 1));
258
259 b = tree_vec_extract (gsi, word_type, b, bitsize, bitpos);
260
261 b_low = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, b, low_bits);
262 signs = gimplify_build1 (gsi, BIT_NOT_EXPR, word_type, b);
263 signs = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, signs, high_bits);
264 result_low = gimplify_build2 (gsi, MINUS_EXPR, word_type, high_bits, b_low);
265 return gimplify_build2 (gsi, BIT_XOR_EXPR, word_type, result_low, signs);
266 }
267
268 /* Expand a vector operation to scalars, by using many operations
269 whose type is the vector type's inner type. */
270 static tree
271 expand_vector_piecewise (gimple_stmt_iterator *gsi, elem_op_func f,
272 tree type, tree inner_type,
273 tree a, tree b, enum tree_code code,
274 tree ret_type = NULL_TREE)
275 {
276 vec<constructor_elt, va_gc> *v;
277 tree part_width = TYPE_SIZE (inner_type);
278 tree index = bitsize_int (0);
279 int nunits = nunits_for_known_piecewise_op (type);
280 int delta = tree_to_uhwi (part_width) / vector_element_bits (type);
281 int i;
282 location_t loc = gimple_location (gsi_stmt (*gsi));
283
284 if (ret_type
285 || types_compatible_p (gimple_expr_type (gsi_stmt (*gsi)), type))
286 warning_at (loc, OPT_Wvector_operation_performance,
287 "vector operation will be expanded piecewise");
288 else
289 warning_at (loc, OPT_Wvector_operation_performance,
290 "vector operation will be expanded in parallel");
291
292 if (!ret_type)
293 ret_type = type;
294 vec_alloc (v, (nunits + delta - 1) / delta);
295 for (i = 0; i < nunits;
296 i += delta, index = int_const_binop (PLUS_EXPR, index, part_width))
297 {
298 tree result = f (gsi, inner_type, a, b, index, part_width, code,
299 ret_type);
300 constructor_elt ce = {NULL_TREE, result};
301 v->quick_push (ce);
302 }
303
304 return build_constructor (ret_type, v);
305 }
306
307 /* Expand a vector operation to scalars with the freedom to use
308 a scalar integer type, or to use a different size for the items
309 in the vector type. */
310 static tree
311 expand_vector_parallel (gimple_stmt_iterator *gsi, elem_op_func f, tree type,
312 tree a, tree b, enum tree_code code)
313 {
314 tree result, compute_type;
315 int n_words = tree_to_uhwi (TYPE_SIZE_UNIT (type)) / UNITS_PER_WORD;
316 location_t loc = gimple_location (gsi_stmt (*gsi));
317
318 /* We have three strategies. If the type is already correct, just do
319 the operation an element at a time. Else, if the vector is wider than
320 one word, do it a word at a time; finally, if the vector is smaller
321 than one word, do it as a scalar. */
322 if (TYPE_MODE (TREE_TYPE (type)) == word_mode)
323 return expand_vector_piecewise (gsi, f,
324 type, TREE_TYPE (type),
325 a, b, code);
326 else if (n_words > 1)
327 {
328 tree word_type = build_word_mode_vector_type (n_words);
329 result = expand_vector_piecewise (gsi, f,
330 word_type, TREE_TYPE (word_type),
331 a, b, code);
332 result = force_gimple_operand_gsi (gsi, result, true, NULL, true,
333 GSI_SAME_STMT);
334 }
335 else
336 {
337 /* Use a single scalar operation with a mode no wider than word_mode. */
338 scalar_int_mode mode
339 = int_mode_for_size (tree_to_uhwi (TYPE_SIZE (type)), 0).require ();
340 compute_type = lang_hooks.types.type_for_mode (mode, 1);
341 result = f (gsi, compute_type, a, b, NULL_TREE, NULL_TREE, code, type);
342 warning_at (loc, OPT_Wvector_operation_performance,
343 "vector operation will be expanded with a "
344 "single scalar operation");
345 }
346
347 return result;
348 }
349
350 /* Expand a vector operation to scalars; for integer types we can use
351 special bit twiddling tricks to do the sums a word at a time, using
352 function F_PARALLEL instead of F. These tricks are done only if
353 they can process at least four items, that is, only if the vector
354 holds at least four items and if a word can hold four items. */
355 static tree
356 expand_vector_addition (gimple_stmt_iterator *gsi,
357 elem_op_func f, elem_op_func f_parallel,
358 tree type, tree a, tree b, enum tree_code code)
359 {
360 int parts_per_word = BITS_PER_WORD / vector_element_bits (type);
361
362 if (INTEGRAL_TYPE_P (TREE_TYPE (type))
363 && parts_per_word >= 4
364 && nunits_for_known_piecewise_op (type) >= 4)
365 return expand_vector_parallel (gsi, f_parallel,
366 type, a, b, code);
367 else
368 return expand_vector_piecewise (gsi, f,
369 type, TREE_TYPE (type),
370 a, b, code);
371 }
372
373 /* Try to expand vector comparison expression OP0 CODE OP1 by
374 querying optab if the following expression:
375 VEC_COND_EXPR< OP0 CODE OP1, {-1,...}, {0,...}>
376 can be expanded. */
377 static tree
378 expand_vector_comparison (gimple_stmt_iterator *gsi, tree type, tree op0,
379 tree op1, enum tree_code code)
380 {
381 tree t;
382 if (!expand_vec_cmp_expr_p (TREE_TYPE (op0), type, code)
383 && !expand_vec_cond_expr_p (type, TREE_TYPE (op0), code))
384 {
385 if (VECTOR_BOOLEAN_TYPE_P (type)
386 && SCALAR_INT_MODE_P (TYPE_MODE (type))
387 && known_lt (GET_MODE_BITSIZE (TYPE_MODE (type)),
388 TYPE_VECTOR_SUBPARTS (type)
389 * GET_MODE_BITSIZE (SCALAR_TYPE_MODE
390 (TREE_TYPE (type)))))
391 {
392 tree inner_type = TREE_TYPE (TREE_TYPE (op0));
393 tree part_width = vector_element_bits_tree (TREE_TYPE (op0));
394 tree index = bitsize_int (0);
395 int nunits = nunits_for_known_piecewise_op (TREE_TYPE (op0));
396 int prec = GET_MODE_PRECISION (SCALAR_TYPE_MODE (type));
397 tree ret_type = build_nonstandard_integer_type (prec, 1);
398 tree ret_inner_type = boolean_type_node;
399 int i;
400 location_t loc = gimple_location (gsi_stmt (*gsi));
401 t = build_zero_cst (ret_type);
402
403 if (TYPE_PRECISION (ret_inner_type) != 1)
404 ret_inner_type = build_nonstandard_integer_type (1, 1);
405 warning_at (loc, OPT_Wvector_operation_performance,
406 "vector operation will be expanded piecewise");
407 for (i = 0; i < nunits;
408 i++, index = int_const_binop (PLUS_EXPR, index, part_width))
409 {
410 tree a = tree_vec_extract (gsi, inner_type, op0, part_width,
411 index);
412 tree b = tree_vec_extract (gsi, inner_type, op1, part_width,
413 index);
414 tree result = gimplify_build2 (gsi, code, ret_inner_type, a, b);
415 t = gimplify_build3 (gsi, BIT_INSERT_EXPR, ret_type, t, result,
416 bitsize_int (i));
417 }
418 t = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, type, t);
419 }
420 else
421 t = expand_vector_piecewise (gsi, do_compare, type,
422 TREE_TYPE (TREE_TYPE (op0)), op0, op1,
423 code);
424 }
425 else
426 t = NULL_TREE;
427
428 return t;
429 }
430
431 /* Helper function of expand_vector_divmod. Gimplify a RSHIFT_EXPR in type
432 of OP0 with shift counts in SHIFTCNTS array and return the temporary holding
433 the result if successful, otherwise return NULL_TREE. */
434 static tree
435 add_rshift (gimple_stmt_iterator *gsi, tree type, tree op0, int *shiftcnts)
436 {
437 optab op;
438 unsigned int i, nunits = nunits_for_known_piecewise_op (type);
439 bool scalar_shift = true;
440
441 for (i = 1; i < nunits; i++)
442 {
443 if (shiftcnts[i] != shiftcnts[0])
444 scalar_shift = false;
445 }
446
447 if (scalar_shift && shiftcnts[0] == 0)
448 return op0;
449
450 if (scalar_shift)
451 {
452 op = optab_for_tree_code (RSHIFT_EXPR, type, optab_scalar);
453 if (op != unknown_optab
454 && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
455 return gimplify_build2 (gsi, RSHIFT_EXPR, type, op0,
456 build_int_cst (NULL_TREE, shiftcnts[0]));
457 }
458
459 op = optab_for_tree_code (RSHIFT_EXPR, type, optab_vector);
460 if (op != unknown_optab
461 && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
462 {
463 tree_vector_builder vec (type, nunits, 1);
464 for (i = 0; i < nunits; i++)
465 vec.quick_push (build_int_cst (TREE_TYPE (type), shiftcnts[i]));
466 return gimplify_build2 (gsi, RSHIFT_EXPR, type, op0, vec.build ());
467 }
468
469 return NULL_TREE;
470 }
471
472 /* Try to expand integer vector division by constant using
473 widening multiply, shifts and additions. */
474 static tree
475 expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, tree op0,
476 tree op1, enum tree_code code)
477 {
478 bool use_pow2 = true;
479 bool has_vector_shift = true;
480 bool use_abs_op1 = false;
481 int mode = -1, this_mode;
482 int pre_shift = -1, post_shift;
483 unsigned int nunits = nunits_for_known_piecewise_op (type);
484 int *shifts = XALLOCAVEC (int, nunits * 4);
485 int *pre_shifts = shifts + nunits;
486 int *post_shifts = pre_shifts + nunits;
487 int *shift_temps = post_shifts + nunits;
488 unsigned HOST_WIDE_INT *mulc = XALLOCAVEC (unsigned HOST_WIDE_INT, nunits);
489 int prec = TYPE_PRECISION (TREE_TYPE (type));
490 int dummy_int;
491 unsigned int i;
492 signop sign_p = TYPE_SIGN (TREE_TYPE (type));
493 unsigned HOST_WIDE_INT mask = GET_MODE_MASK (TYPE_MODE (TREE_TYPE (type)));
494 tree cur_op, mulcst, tem;
495 optab op;
496
497 if (prec > HOST_BITS_PER_WIDE_INT)
498 return NULL_TREE;
499
500 op = optab_for_tree_code (RSHIFT_EXPR, type, optab_vector);
501 if (op == unknown_optab
502 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
503 has_vector_shift = false;
504
505 /* Analysis phase. Determine if all op1 elements are either power
506 of two and it is possible to expand it using shifts (or for remainder
507 using masking). Additionally compute the multiplicative constants
508 and pre and post shifts if the division is to be expanded using
509 widening or high part multiplication plus shifts. */
510 for (i = 0; i < nunits; i++)
511 {
512 tree cst = VECTOR_CST_ELT (op1, i);
513 unsigned HOST_WIDE_INT ml;
514
515 if (TREE_CODE (cst) != INTEGER_CST || integer_zerop (cst))
516 return NULL_TREE;
517 pre_shifts[i] = 0;
518 post_shifts[i] = 0;
519 mulc[i] = 0;
520 if (use_pow2
521 && (!integer_pow2p (cst) || tree_int_cst_sgn (cst) != 1))
522 use_pow2 = false;
523 if (use_pow2)
524 {
525 shifts[i] = tree_log2 (cst);
526 if (shifts[i] != shifts[0]
527 && code == TRUNC_DIV_EXPR
528 && !has_vector_shift)
529 use_pow2 = false;
530 }
531 if (mode == -2)
532 continue;
533 if (sign_p == UNSIGNED)
534 {
535 unsigned HOST_WIDE_INT mh;
536 unsigned HOST_WIDE_INT d = TREE_INT_CST_LOW (cst) & mask;
537
538 if (d >= (HOST_WIDE_INT_1U << (prec - 1)))
539 /* FIXME: Can transform this into op0 >= op1 ? 1 : 0. */
540 return NULL_TREE;
541
542 if (d <= 1)
543 {
544 mode = -2;
545 continue;
546 }
547
548 /* Find a suitable multiplier and right shift count
549 instead of multiplying with D. */
550 mh = choose_multiplier (d, prec, prec, &ml, &post_shift, &dummy_int);
551
552 /* If the suggested multiplier is more than SIZE bits, we can
553 do better for even divisors, using an initial right shift. */
554 if ((mh != 0 && (d & 1) == 0)
555 || (!has_vector_shift && pre_shift != -1))
556 {
557 if (has_vector_shift)
558 pre_shift = ctz_or_zero (d);
559 else if (pre_shift == -1)
560 {
561 unsigned int j;
562 for (j = 0; j < nunits; j++)
563 {
564 tree cst2 = VECTOR_CST_ELT (op1, j);
565 unsigned HOST_WIDE_INT d2;
566 int this_pre_shift;
567
568 if (!tree_fits_uhwi_p (cst2))
569 return NULL_TREE;
570 d2 = tree_to_uhwi (cst2) & mask;
571 if (d2 == 0)
572 return NULL_TREE;
573 this_pre_shift = floor_log2 (d2 & -d2);
574 if (pre_shift == -1 || this_pre_shift < pre_shift)
575 pre_shift = this_pre_shift;
576 }
577 if (i != 0 && pre_shift != 0)
578 {
579 /* Restart. */
580 i = -1U;
581 mode = -1;
582 continue;
583 }
584 }
585 if (pre_shift != 0)
586 {
587 if ((d >> pre_shift) <= 1)
588 {
589 mode = -2;
590 continue;
591 }
592 mh = choose_multiplier (d >> pre_shift, prec,
593 prec - pre_shift,
594 &ml, &post_shift, &dummy_int);
595 gcc_assert (!mh);
596 pre_shifts[i] = pre_shift;
597 }
598 }
599 if (!mh)
600 this_mode = 0;
601 else
602 this_mode = 1;
603 }
604 else
605 {
606 HOST_WIDE_INT d = TREE_INT_CST_LOW (cst);
607 unsigned HOST_WIDE_INT abs_d;
608
609 if (d == -1)
610 return NULL_TREE;
611
612 /* Since d might be INT_MIN, we have to cast to
613 unsigned HOST_WIDE_INT before negating to avoid
614 undefined signed overflow. */
615 abs_d = (d >= 0
616 ? (unsigned HOST_WIDE_INT) d
617 : - (unsigned HOST_WIDE_INT) d);
618
619 /* n rem d = n rem -d */
620 if (code == TRUNC_MOD_EXPR && d < 0)
621 {
622 d = abs_d;
623 use_abs_op1 = true;
624 }
625 if (abs_d == HOST_WIDE_INT_1U << (prec - 1))
626 {
627 /* This case is not handled correctly below. */
628 mode = -2;
629 continue;
630 }
631 if (abs_d <= 1)
632 {
633 mode = -2;
634 continue;
635 }
636
637 choose_multiplier (abs_d, prec, prec - 1, &ml,
638 &post_shift, &dummy_int);
639 if (ml >= HOST_WIDE_INT_1U << (prec - 1))
640 {
641 this_mode = 4 + (d < 0);
642 ml |= HOST_WIDE_INT_M1U << (prec - 1);
643 }
644 else
645 this_mode = 2 + (d < 0);
646 }
647 mulc[i] = ml;
648 post_shifts[i] = post_shift;
649 if ((i && !has_vector_shift && post_shifts[0] != post_shift)
650 || post_shift >= prec
651 || pre_shifts[i] >= prec)
652 this_mode = -2;
653
654 if (i == 0)
655 mode = this_mode;
656 else if (mode != this_mode)
657 mode = -2;
658 }
659
660 if (use_pow2)
661 {
662 tree addend = NULL_TREE;
663 if (sign_p == SIGNED)
664 {
665 tree uns_type;
666
667 /* Both division and remainder sequences need
668 op0 < 0 ? mask : 0 computed. It can be either computed as
669 (type) (((uns_type) (op0 >> (prec - 1))) >> (prec - shifts[i]))
670 if none of the shifts is 0, or as the conditional. */
671 for (i = 0; i < nunits; i++)
672 if (shifts[i] == 0)
673 break;
674 uns_type
675 = build_vector_type (build_nonstandard_integer_type (prec, 1),
676 nunits);
677 if (i == nunits && TYPE_MODE (uns_type) == TYPE_MODE (type))
678 {
679 for (i = 0; i < nunits; i++)
680 shift_temps[i] = prec - 1;
681 cur_op = add_rshift (gsi, type, op0, shift_temps);
682 if (cur_op != NULL_TREE)
683 {
684 cur_op = gimplify_build1 (gsi, VIEW_CONVERT_EXPR,
685 uns_type, cur_op);
686 for (i = 0; i < nunits; i++)
687 shift_temps[i] = prec - shifts[i];
688 cur_op = add_rshift (gsi, uns_type, cur_op, shift_temps);
689 if (cur_op != NULL_TREE)
690 addend = gimplify_build1 (gsi, VIEW_CONVERT_EXPR,
691 type, cur_op);
692 }
693 }
694 if (addend == NULL_TREE
695 && expand_vec_cond_expr_p (type, type, LT_EXPR))
696 {
697 tree zero, cst, cond, mask_type;
698 gimple *stmt;
699
700 mask_type = truth_type_for (type);
701 zero = build_zero_cst (type);
702 cond = build2 (LT_EXPR, mask_type, op0, zero);
703 tree_vector_builder vec (type, nunits, 1);
704 for (i = 0; i < nunits; i++)
705 vec.quick_push (build_int_cst (TREE_TYPE (type),
706 (HOST_WIDE_INT_1U
707 << shifts[i]) - 1));
708 cst = vec.build ();
709 addend = make_ssa_name (type);
710 stmt = gimple_build_assign (addend, VEC_COND_EXPR, cond,
711 cst, zero);
712 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
713 }
714 }
715 if (code == TRUNC_DIV_EXPR)
716 {
717 if (sign_p == UNSIGNED)
718 {
719 /* q = op0 >> shift; */
720 cur_op = add_rshift (gsi, type, op0, shifts);
721 if (cur_op != NULL_TREE)
722 return cur_op;
723 }
724 else if (addend != NULL_TREE)
725 {
726 /* t1 = op0 + addend;
727 q = t1 >> shift; */
728 op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
729 if (op != unknown_optab
730 && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
731 {
732 cur_op = gimplify_build2 (gsi, PLUS_EXPR, type, op0, addend);
733 cur_op = add_rshift (gsi, type, cur_op, shifts);
734 if (cur_op != NULL_TREE)
735 return cur_op;
736 }
737 }
738 }
739 else
740 {
741 tree mask;
742 tree_vector_builder vec (type, nunits, 1);
743 for (i = 0; i < nunits; i++)
744 vec.quick_push (build_int_cst (TREE_TYPE (type),
745 (HOST_WIDE_INT_1U
746 << shifts[i]) - 1));
747 mask = vec.build ();
748 op = optab_for_tree_code (BIT_AND_EXPR, type, optab_default);
749 if (op != unknown_optab
750 && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
751 {
752 if (sign_p == UNSIGNED)
753 /* r = op0 & mask; */
754 return gimplify_build2 (gsi, BIT_AND_EXPR, type, op0, mask);
755 else if (addend != NULL_TREE)
756 {
757 /* t1 = op0 + addend;
758 t2 = t1 & mask;
759 r = t2 - addend; */
760 op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
761 if (op != unknown_optab
762 && optab_handler (op, TYPE_MODE (type))
763 != CODE_FOR_nothing)
764 {
765 cur_op = gimplify_build2 (gsi, PLUS_EXPR, type, op0,
766 addend);
767 cur_op = gimplify_build2 (gsi, BIT_AND_EXPR, type,
768 cur_op, mask);
769 op = optab_for_tree_code (MINUS_EXPR, type,
770 optab_default);
771 if (op != unknown_optab
772 && optab_handler (op, TYPE_MODE (type))
773 != CODE_FOR_nothing)
774 return gimplify_build2 (gsi, MINUS_EXPR, type,
775 cur_op, addend);
776 }
777 }
778 }
779 }
780 }
781
782 if (mode == -2 || BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN)
783 return NULL_TREE;
784
785 if (!can_mult_highpart_p (TYPE_MODE (type), TYPE_UNSIGNED (type)))
786 return NULL_TREE;
787
788 cur_op = op0;
789
790 switch (mode)
791 {
792 case 0:
793 gcc_assert (sign_p == UNSIGNED);
794 /* t1 = oprnd0 >> pre_shift;
795 t2 = t1 h* ml;
796 q = t2 >> post_shift; */
797 cur_op = add_rshift (gsi, type, cur_op, pre_shifts);
798 if (cur_op == NULL_TREE)
799 return NULL_TREE;
800 break;
801 case 1:
802 gcc_assert (sign_p == UNSIGNED);
803 for (i = 0; i < nunits; i++)
804 {
805 shift_temps[i] = 1;
806 post_shifts[i]--;
807 }
808 break;
809 case 2:
810 case 3:
811 case 4:
812 case 5:
813 gcc_assert (sign_p == SIGNED);
814 for (i = 0; i < nunits; i++)
815 shift_temps[i] = prec - 1;
816 break;
817 default:
818 return NULL_TREE;
819 }
820
821 tree_vector_builder vec (type, nunits, 1);
822 for (i = 0; i < nunits; i++)
823 vec.quick_push (build_int_cst (TREE_TYPE (type), mulc[i]));
824 mulcst = vec.build ();
825
826 cur_op = gimplify_build2 (gsi, MULT_HIGHPART_EXPR, type, cur_op, mulcst);
827
828 switch (mode)
829 {
830 case 0:
831 /* t1 = oprnd0 >> pre_shift;
832 t2 = t1 h* ml;
833 q = t2 >> post_shift; */
834 cur_op = add_rshift (gsi, type, cur_op, post_shifts);
835 break;
836 case 1:
837 /* t1 = oprnd0 h* ml;
838 t2 = oprnd0 - t1;
839 t3 = t2 >> 1;
840 t4 = t1 + t3;
841 q = t4 >> (post_shift - 1); */
842 op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
843 if (op == unknown_optab
844 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
845 return NULL_TREE;
846 tem = gimplify_build2 (gsi, MINUS_EXPR, type, op0, cur_op);
847 tem = add_rshift (gsi, type, tem, shift_temps);
848 op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
849 if (op == unknown_optab
850 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
851 return NULL_TREE;
852 tem = gimplify_build2 (gsi, PLUS_EXPR, type, cur_op, tem);
853 cur_op = add_rshift (gsi, type, tem, post_shifts);
854 if (cur_op == NULL_TREE)
855 return NULL_TREE;
856 break;
857 case 2:
858 case 3:
859 case 4:
860 case 5:
861 /* t1 = oprnd0 h* ml;
862 t2 = t1; [ iff (mode & 2) != 0 ]
863 t2 = t1 + oprnd0; [ iff (mode & 2) == 0 ]
864 t3 = t2 >> post_shift;
865 t4 = oprnd0 >> (prec - 1);
866 q = t3 - t4; [ iff (mode & 1) == 0 ]
867 q = t4 - t3; [ iff (mode & 1) != 0 ] */
868 if ((mode & 2) == 0)
869 {
870 op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
871 if (op == unknown_optab
872 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
873 return NULL_TREE;
874 cur_op = gimplify_build2 (gsi, PLUS_EXPR, type, cur_op, op0);
875 }
876 cur_op = add_rshift (gsi, type, cur_op, post_shifts);
877 if (cur_op == NULL_TREE)
878 return NULL_TREE;
879 tem = add_rshift (gsi, type, op0, shift_temps);
880 if (tem == NULL_TREE)
881 return NULL_TREE;
882 op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
883 if (op == unknown_optab
884 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
885 return NULL_TREE;
886 if ((mode & 1) == 0)
887 cur_op = gimplify_build2 (gsi, MINUS_EXPR, type, cur_op, tem);
888 else
889 cur_op = gimplify_build2 (gsi, MINUS_EXPR, type, tem, cur_op);
890 break;
891 default:
892 gcc_unreachable ();
893 }
894
895 if (code == TRUNC_DIV_EXPR)
896 return cur_op;
897
898 /* We divided. Now finish by:
899 t1 = q * oprnd1;
900 r = oprnd0 - t1; */
901 op = optab_for_tree_code (MULT_EXPR, type, optab_default);
902 if (op == unknown_optab
903 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
904 return NULL_TREE;
905 if (use_abs_op1)
906 {
907 tree_vector_builder elts;
908 if (!elts.new_unary_operation (type, op1, false))
909 return NULL_TREE;
910 unsigned int count = elts.encoded_nelts ();
911 for (unsigned int i = 0; i < count; ++i)
912 {
913 tree elem1 = VECTOR_CST_ELT (op1, i);
914
915 tree elt = const_unop (ABS_EXPR, TREE_TYPE (elem1), elem1);
916 if (elt == NULL_TREE)
917 return NULL_TREE;
918 elts.quick_push (elt);
919 }
920 op1 = elts.build ();
921 }
922 tem = gimplify_build2 (gsi, MULT_EXPR, type, cur_op, op1);
923 op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
924 if (op == unknown_optab
925 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
926 return NULL_TREE;
927 return gimplify_build2 (gsi, MINUS_EXPR, type, op0, tem);
928 }
929
930 /* Expand a vector condition to scalars, by using many conditions
931 on the vector's elements. */
932 static void
933 expand_vector_condition (gimple_stmt_iterator *gsi)
934 {
935 gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
936 tree type = gimple_expr_type (stmt);
937 tree a = gimple_assign_rhs1 (stmt);
938 tree a1 = a;
939 tree a2 = NULL_TREE;
940 bool a_is_comparison = false;
941 bool a_is_scalar_bitmask = false;
942 tree b = gimple_assign_rhs2 (stmt);
943 tree c = gimple_assign_rhs3 (stmt);
944 vec<constructor_elt, va_gc> *v;
945 tree constr;
946 tree inner_type = TREE_TYPE (type);
947 tree width = vector_element_bits_tree (type);
948 tree cond_type = TREE_TYPE (TREE_TYPE (a));
949 tree comp_inner_type = cond_type;
950 tree index = bitsize_int (0);
951 tree comp_width = width;
952 tree comp_index = index;
953 int i;
954 location_t loc = gimple_location (gsi_stmt (*gsi));
955
956 if (!is_gimple_val (a))
957 {
958 gcc_assert (COMPARISON_CLASS_P (a));
959 a_is_comparison = true;
960 a1 = TREE_OPERAND (a, 0);
961 a2 = TREE_OPERAND (a, 1);
962 comp_inner_type = TREE_TYPE (TREE_TYPE (a1));
963 comp_width = vector_element_bits_tree (TREE_TYPE (a1));
964 }
965
966 if (expand_vec_cond_expr_p (type, TREE_TYPE (a1), TREE_CODE (a)))
967 return;
968
969 /* Handle vector boolean types with bitmasks. If there is a comparison
970 and we can expand the comparison into the vector boolean bitmask,
971 or otherwise if it is compatible with type, we can transform
972 vbfld_1 = x_2 < y_3 ? vbfld_4 : vbfld_5;
973 into
974 tmp_6 = x_2 < y_3;
975 tmp_7 = tmp_6 & vbfld_4;
976 tmp_8 = ~tmp_6;
977 tmp_9 = tmp_8 & vbfld_5;
978 vbfld_1 = tmp_7 | tmp_9;
979 Similarly for vbfld_10 instead of x_2 < y_3. */
980 if (VECTOR_BOOLEAN_TYPE_P (type)
981 && SCALAR_INT_MODE_P (TYPE_MODE (type))
982 && known_lt (GET_MODE_BITSIZE (TYPE_MODE (type)),
983 TYPE_VECTOR_SUBPARTS (type)
984 * GET_MODE_BITSIZE (SCALAR_TYPE_MODE (TREE_TYPE (type))))
985 && (a_is_comparison
986 ? useless_type_conversion_p (type, TREE_TYPE (a))
987 : expand_vec_cmp_expr_p (TREE_TYPE (a1), type, TREE_CODE (a))))
988 {
989 if (a_is_comparison)
990 a = gimplify_build2 (gsi, TREE_CODE (a), type, a1, a2);
991 a1 = gimplify_build2 (gsi, BIT_AND_EXPR, type, a, b);
992 a2 = gimplify_build1 (gsi, BIT_NOT_EXPR, type, a);
993 a2 = gimplify_build2 (gsi, BIT_AND_EXPR, type, a2, c);
994 a = gimplify_build2 (gsi, BIT_IOR_EXPR, type, a1, a2);
995 gimple_assign_set_rhs_from_tree (gsi, a);
996 update_stmt (gsi_stmt (*gsi));
997 return;
998 }
999
1000 /* TODO: try and find a smaller vector type. */
1001
1002 warning_at (loc, OPT_Wvector_operation_performance,
1003 "vector condition will be expanded piecewise");
1004
1005 if (!a_is_comparison
1006 && VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (a))
1007 && SCALAR_INT_MODE_P (TYPE_MODE (TREE_TYPE (a)))
1008 && known_lt (GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (a))),
1009 TYPE_VECTOR_SUBPARTS (TREE_TYPE (a))
1010 * GET_MODE_BITSIZE (SCALAR_TYPE_MODE
1011 (TREE_TYPE (TREE_TYPE (a))))))
1012 {
1013 a_is_scalar_bitmask = true;
1014 int prec = GET_MODE_PRECISION (SCALAR_TYPE_MODE (TREE_TYPE (a)));
1015 tree atype = build_nonstandard_integer_type (prec, 1);
1016 a = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, atype, a);
1017 }
1018
1019 int nunits = nunits_for_known_piecewise_op (type);
1020 vec_alloc (v, nunits);
1021 for (i = 0; i < nunits; i++)
1022 {
1023 tree aa, result;
1024 tree bb = tree_vec_extract (gsi, inner_type, b, width, index);
1025 tree cc = tree_vec_extract (gsi, inner_type, c, width, index);
1026 if (a_is_comparison)
1027 {
1028 tree aa1 = tree_vec_extract (gsi, comp_inner_type, a1,
1029 comp_width, comp_index);
1030 tree aa2 = tree_vec_extract (gsi, comp_inner_type, a2,
1031 comp_width, comp_index);
1032 aa = fold_build2 (TREE_CODE (a), cond_type, aa1, aa2);
1033 }
1034 else if (a_is_scalar_bitmask)
1035 {
1036 wide_int w = wi::set_bit_in_zero (i, TYPE_PRECISION (TREE_TYPE (a)));
1037 result = gimplify_build2 (gsi, BIT_AND_EXPR, TREE_TYPE (a),
1038 a, wide_int_to_tree (TREE_TYPE (a), w));
1039 aa = fold_build2 (NE_EXPR, boolean_type_node, result,
1040 build_zero_cst (TREE_TYPE (a)));
1041 }
1042 else
1043 aa = tree_vec_extract (gsi, cond_type, a, width, index);
1044 result = gimplify_build3 (gsi, COND_EXPR, inner_type, aa, bb, cc);
1045 constructor_elt ce = {NULL_TREE, result};
1046 v->quick_push (ce);
1047 index = int_const_binop (PLUS_EXPR, index, width);
1048 if (width == comp_width)
1049 comp_index = index;
1050 else
1051 comp_index = int_const_binop (PLUS_EXPR, comp_index, comp_width);
1052 }
1053
1054 constr = build_constructor (type, v);
1055 gimple_assign_set_rhs_from_tree (gsi, constr);
1056 update_stmt (gsi_stmt (*gsi));
1057 }
1058
1059 static tree
1060 expand_vector_operation (gimple_stmt_iterator *gsi, tree type, tree compute_type,
1061 gassign *assign, enum tree_code code)
1062 {
1063 machine_mode compute_mode = TYPE_MODE (compute_type);
1064
1065 /* If the compute mode is not a vector mode (hence we are not decomposing
1066 a BLKmode vector to smaller, hardware-supported vectors), we may want
1067 to expand the operations in parallel. */
1068 if (!VECTOR_MODE_P (compute_mode))
1069 switch (code)
1070 {
1071 case PLUS_EXPR:
1072 case MINUS_EXPR:
1073 if (ANY_INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_TRAPS (type))
1074 return expand_vector_addition (gsi, do_binop, do_plus_minus, type,
1075 gimple_assign_rhs1 (assign),
1076 gimple_assign_rhs2 (assign), code);
1077 break;
1078
1079 case NEGATE_EXPR:
1080 if (ANY_INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_TRAPS (type))
1081 return expand_vector_addition (gsi, do_unop, do_negate, type,
1082 gimple_assign_rhs1 (assign),
1083 NULL_TREE, code);
1084 break;
1085
1086 case BIT_AND_EXPR:
1087 case BIT_IOR_EXPR:
1088 case BIT_XOR_EXPR:
1089 return expand_vector_parallel (gsi, do_binop, type,
1090 gimple_assign_rhs1 (assign),
1091 gimple_assign_rhs2 (assign), code);
1092
1093 case BIT_NOT_EXPR:
1094 return expand_vector_parallel (gsi, do_unop, type,
1095 gimple_assign_rhs1 (assign),
1096 NULL_TREE, code);
1097 case EQ_EXPR:
1098 case NE_EXPR:
1099 case GT_EXPR:
1100 case LT_EXPR:
1101 case GE_EXPR:
1102 case LE_EXPR:
1103 case UNEQ_EXPR:
1104 case UNGT_EXPR:
1105 case UNLT_EXPR:
1106 case UNGE_EXPR:
1107 case UNLE_EXPR:
1108 case LTGT_EXPR:
1109 case ORDERED_EXPR:
1110 case UNORDERED_EXPR:
1111 {
1112 tree rhs1 = gimple_assign_rhs1 (assign);
1113 tree rhs2 = gimple_assign_rhs2 (assign);
1114
1115 return expand_vector_comparison (gsi, type, rhs1, rhs2, code);
1116 }
1117
1118 case TRUNC_DIV_EXPR:
1119 case TRUNC_MOD_EXPR:
1120 {
1121 tree rhs1 = gimple_assign_rhs1 (assign);
1122 tree rhs2 = gimple_assign_rhs2 (assign);
1123 tree ret;
1124
1125 if (!optimize
1126 || !VECTOR_INTEGER_TYPE_P (type)
1127 || TREE_CODE (rhs2) != VECTOR_CST
1128 || !VECTOR_MODE_P (TYPE_MODE (type)))
1129 break;
1130
1131 ret = expand_vector_divmod (gsi, type, rhs1, rhs2, code);
1132 if (ret != NULL_TREE)
1133 return ret;
1134 break;
1135 }
1136
1137 default:
1138 break;
1139 }
1140
1141 if (TREE_CODE_CLASS (code) == tcc_unary)
1142 return expand_vector_piecewise (gsi, do_unop, type, compute_type,
1143 gimple_assign_rhs1 (assign),
1144 NULL_TREE, code);
1145 else
1146 return expand_vector_piecewise (gsi, do_binop, type, compute_type,
1147 gimple_assign_rhs1 (assign),
1148 gimple_assign_rhs2 (assign), code);
1149 }
1150
1151 /* Try to optimize
1152 a_5 = { b_7, b_7 + 3, b_7 + 6, b_7 + 9 };
1153 style stmts into:
1154 _9 = { b_7, b_7, b_7, b_7 };
1155 a_5 = _9 + { 0, 3, 6, 9 };
1156 because vector splat operation is usually more efficient
1157 than piecewise initialization of the vector. */
1158
1159 static void
1160 optimize_vector_constructor (gimple_stmt_iterator *gsi)
1161 {
1162 gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
1163 tree lhs = gimple_assign_lhs (stmt);
1164 tree rhs = gimple_assign_rhs1 (stmt);
1165 tree type = TREE_TYPE (rhs);
1166 unsigned int i, j;
1167 unsigned HOST_WIDE_INT nelts;
1168 bool all_same = true;
1169 constructor_elt *elt;
1170 gimple *g;
1171 tree base = NULL_TREE;
1172 optab op;
1173
1174 if (!TYPE_VECTOR_SUBPARTS (type).is_constant (&nelts)
1175 || nelts <= 2
1176 || CONSTRUCTOR_NELTS (rhs) != nelts)
1177 return;
1178 op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
1179 if (op == unknown_optab
1180 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
1181 return;
1182 FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (rhs), i, elt)
1183 if (TREE_CODE (elt->value) != SSA_NAME
1184 || TREE_CODE (TREE_TYPE (elt->value)) == VECTOR_TYPE)
1185 return;
1186 else
1187 {
1188 tree this_base = elt->value;
1189 if (this_base != CONSTRUCTOR_ELT (rhs, 0)->value)
1190 all_same = false;
1191 for (j = 0; j < nelts + 1; j++)
1192 {
1193 g = SSA_NAME_DEF_STMT (this_base);
1194 if (is_gimple_assign (g)
1195 && gimple_assign_rhs_code (g) == PLUS_EXPR
1196 && TREE_CODE (gimple_assign_rhs2 (g)) == INTEGER_CST
1197 && TREE_CODE (gimple_assign_rhs1 (g)) == SSA_NAME
1198 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_assign_rhs1 (g)))
1199 this_base = gimple_assign_rhs1 (g);
1200 else
1201 break;
1202 }
1203 if (i == 0)
1204 base = this_base;
1205 else if (this_base != base)
1206 return;
1207 }
1208 if (all_same)
1209 return;
1210 tree_vector_builder cst (type, nelts, 1);
1211 for (i = 0; i < nelts; i++)
1212 {
1213 tree this_base = CONSTRUCTOR_ELT (rhs, i)->value;
1214 tree elt = build_zero_cst (TREE_TYPE (base));
1215 while (this_base != base)
1216 {
1217 g = SSA_NAME_DEF_STMT (this_base);
1218 elt = fold_binary (PLUS_EXPR, TREE_TYPE (base),
1219 elt, gimple_assign_rhs2 (g));
1220 if (elt == NULL_TREE
1221 || TREE_CODE (elt) != INTEGER_CST
1222 || TREE_OVERFLOW (elt))
1223 return;
1224 this_base = gimple_assign_rhs1 (g);
1225 }
1226 cst.quick_push (elt);
1227 }
1228 for (i = 0; i < nelts; i++)
1229 CONSTRUCTOR_ELT (rhs, i)->value = base;
1230 g = gimple_build_assign (make_ssa_name (type), rhs);
1231 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1232 g = gimple_build_assign (lhs, PLUS_EXPR, gimple_assign_lhs (g),
1233 cst.build ());
1234 gsi_replace (gsi, g, false);
1235 }
1236 \f
1237 /* Return a type for the widest vector mode whose components are of type
1238 TYPE, or NULL_TREE if none is found. */
1239
1240 static tree
1241 type_for_widest_vector_mode (tree type, optab op)
1242 {
1243 machine_mode inner_mode = TYPE_MODE (type);
1244 machine_mode best_mode = VOIDmode, mode;
1245 poly_int64 best_nunits = 0;
1246
1247 if (SCALAR_FLOAT_MODE_P (inner_mode))
1248 mode = MIN_MODE_VECTOR_FLOAT;
1249 else if (SCALAR_FRACT_MODE_P (inner_mode))
1250 mode = MIN_MODE_VECTOR_FRACT;
1251 else if (SCALAR_UFRACT_MODE_P (inner_mode))
1252 mode = MIN_MODE_VECTOR_UFRACT;
1253 else if (SCALAR_ACCUM_MODE_P (inner_mode))
1254 mode = MIN_MODE_VECTOR_ACCUM;
1255 else if (SCALAR_UACCUM_MODE_P (inner_mode))
1256 mode = MIN_MODE_VECTOR_UACCUM;
1257 else if (inner_mode == BImode)
1258 mode = MIN_MODE_VECTOR_BOOL;
1259 else
1260 mode = MIN_MODE_VECTOR_INT;
1261
1262 FOR_EACH_MODE_FROM (mode, mode)
1263 if (GET_MODE_INNER (mode) == inner_mode
1264 && maybe_gt (GET_MODE_NUNITS (mode), best_nunits)
1265 && optab_handler (op, mode) != CODE_FOR_nothing)
1266 best_mode = mode, best_nunits = GET_MODE_NUNITS (mode);
1267
1268 if (best_mode == VOIDmode)
1269 return NULL_TREE;
1270 else
1271 return build_vector_type_for_mode (type, best_mode);
1272 }
1273
1274
1275 /* Build a reference to the element of the vector VECT. Function
1276 returns either the element itself, either BIT_FIELD_REF, or an
1277 ARRAY_REF expression.
1278
1279 GSI is required to insert temporary variables while building a
1280 refernece to the element of the vector VECT.
1281
1282 PTMPVEC is a pointer to the temporary variable for caching
1283 purposes. In case when PTMPVEC is NULL new temporary variable
1284 will be created. */
1285 static tree
1286 vector_element (gimple_stmt_iterator *gsi, tree vect, tree idx, tree *ptmpvec)
1287 {
1288 tree vect_type, vect_elt_type;
1289 gimple *asgn;
1290 tree tmpvec;
1291 tree arraytype;
1292 bool need_asgn = true;
1293 unsigned int elements;
1294
1295 vect_type = TREE_TYPE (vect);
1296 vect_elt_type = TREE_TYPE (vect_type);
1297 elements = nunits_for_known_piecewise_op (vect_type);
1298
1299 if (TREE_CODE (idx) == INTEGER_CST)
1300 {
1301 unsigned HOST_WIDE_INT index;
1302
1303 /* Given that we're about to compute a binary modulus,
1304 we don't care about the high bits of the value. */
1305 index = TREE_INT_CST_LOW (idx);
1306 if (!tree_fits_uhwi_p (idx) || index >= elements)
1307 {
1308 index &= elements - 1;
1309 idx = build_int_cst (TREE_TYPE (idx), index);
1310 }
1311
1312 /* When lowering a vector statement sequence do some easy
1313 simplification by looking through intermediate vector results. */
1314 if (TREE_CODE (vect) == SSA_NAME)
1315 {
1316 gimple *def_stmt = SSA_NAME_DEF_STMT (vect);
1317 if (is_gimple_assign (def_stmt)
1318 && (gimple_assign_rhs_code (def_stmt) == VECTOR_CST
1319 || gimple_assign_rhs_code (def_stmt) == CONSTRUCTOR))
1320 vect = gimple_assign_rhs1 (def_stmt);
1321 }
1322
1323 if (TREE_CODE (vect) == VECTOR_CST)
1324 return VECTOR_CST_ELT (vect, index);
1325 else if (TREE_CODE (vect) == CONSTRUCTOR
1326 && (CONSTRUCTOR_NELTS (vect) == 0
1327 || TREE_CODE (TREE_TYPE (CONSTRUCTOR_ELT (vect, 0)->value))
1328 != VECTOR_TYPE))
1329 {
1330 if (index < CONSTRUCTOR_NELTS (vect))
1331 return CONSTRUCTOR_ELT (vect, index)->value;
1332 return build_zero_cst (vect_elt_type);
1333 }
1334 else
1335 {
1336 tree size = vector_element_bits_tree (vect_type);
1337 tree pos = fold_build2 (MULT_EXPR, bitsizetype, bitsize_int (index),
1338 size);
1339 return fold_build3 (BIT_FIELD_REF, vect_elt_type, vect, size, pos);
1340 }
1341 }
1342
1343 if (!ptmpvec)
1344 tmpvec = create_tmp_var (vect_type, "vectmp");
1345 else if (!*ptmpvec)
1346 tmpvec = *ptmpvec = create_tmp_var (vect_type, "vectmp");
1347 else
1348 {
1349 tmpvec = *ptmpvec;
1350 need_asgn = false;
1351 }
1352
1353 if (need_asgn)
1354 {
1355 TREE_ADDRESSABLE (tmpvec) = 1;
1356 asgn = gimple_build_assign (tmpvec, vect);
1357 gsi_insert_before (gsi, asgn, GSI_SAME_STMT);
1358 }
1359
1360 arraytype = build_array_type_nelts (vect_elt_type, elements);
1361 return build4 (ARRAY_REF, vect_elt_type,
1362 build1 (VIEW_CONVERT_EXPR, arraytype, tmpvec),
1363 idx, NULL_TREE, NULL_TREE);
1364 }
1365
1366 /* Check if VEC_PERM_EXPR within the given setting is supported
1367 by hardware, or lower it piecewise.
1368
1369 When VEC_PERM_EXPR has the same first and second operands:
1370 VEC_PERM_EXPR <v0, v0, mask> the lowered version would be
1371 {v0[mask[0]], v0[mask[1]], ...}
1372 MASK and V0 must have the same number of elements.
1373
1374 Otherwise VEC_PERM_EXPR <v0, v1, mask> is lowered to
1375 {mask[0] < len(v0) ? v0[mask[0]] : v1[mask[0]], ...}
1376 V0 and V1 must have the same type. MASK, V0, V1 must have the
1377 same number of arguments. */
1378
1379 static void
1380 lower_vec_perm (gimple_stmt_iterator *gsi)
1381 {
1382 gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
1383 tree mask = gimple_assign_rhs3 (stmt);
1384 tree vec0 = gimple_assign_rhs1 (stmt);
1385 tree vec1 = gimple_assign_rhs2 (stmt);
1386 tree vect_type = TREE_TYPE (vec0);
1387 tree mask_type = TREE_TYPE (mask);
1388 tree vect_elt_type = TREE_TYPE (vect_type);
1389 tree mask_elt_type = TREE_TYPE (mask_type);
1390 unsigned HOST_WIDE_INT elements;
1391 vec<constructor_elt, va_gc> *v;
1392 tree constr, t, si, i_val;
1393 tree vec0tmp = NULL_TREE, vec1tmp = NULL_TREE, masktmp = NULL_TREE;
1394 bool two_operand_p = !operand_equal_p (vec0, vec1, 0);
1395 location_t loc = gimple_location (gsi_stmt (*gsi));
1396 unsigned i;
1397
1398 if (!TYPE_VECTOR_SUBPARTS (vect_type).is_constant (&elements))
1399 return;
1400
1401 if (TREE_CODE (mask) == SSA_NAME)
1402 {
1403 gimple *def_stmt = SSA_NAME_DEF_STMT (mask);
1404 if (is_gimple_assign (def_stmt)
1405 && gimple_assign_rhs_code (def_stmt) == VECTOR_CST)
1406 mask = gimple_assign_rhs1 (def_stmt);
1407 }
1408
1409 vec_perm_builder sel_int;
1410
1411 if (TREE_CODE (mask) == VECTOR_CST
1412 && tree_to_vec_perm_builder (&sel_int, mask))
1413 {
1414 vec_perm_indices indices (sel_int, 2, elements);
1415 if (can_vec_perm_const_p (TYPE_MODE (vect_type), indices))
1416 {
1417 gimple_assign_set_rhs3 (stmt, mask);
1418 update_stmt (stmt);
1419 return;
1420 }
1421 /* Also detect vec_shr pattern - VEC_PERM_EXPR with zero
1422 vector as VEC1 and a right element shift MASK. */
1423 if (optab_handler (vec_shr_optab, TYPE_MODE (vect_type))
1424 != CODE_FOR_nothing
1425 && TREE_CODE (vec1) == VECTOR_CST
1426 && initializer_zerop (vec1)
1427 && maybe_ne (indices[0], 0)
1428 && known_lt (poly_uint64 (indices[0]), elements))
1429 {
1430 bool ok_p = indices.series_p (0, 1, indices[0], 1);
1431 if (!ok_p)
1432 {
1433 for (i = 1; i < elements; ++i)
1434 {
1435 poly_uint64 actual = indices[i];
1436 poly_uint64 expected = i + indices[0];
1437 /* Indices into the second vector are all equivalent. */
1438 if (maybe_lt (actual, elements)
1439 ? maybe_ne (actual, expected)
1440 : maybe_lt (expected, elements))
1441 break;
1442 }
1443 ok_p = i == elements;
1444 }
1445 if (ok_p)
1446 {
1447 gimple_assign_set_rhs3 (stmt, mask);
1448 update_stmt (stmt);
1449 return;
1450 }
1451 }
1452 /* And similarly vec_shl pattern. */
1453 if (optab_handler (vec_shl_optab, TYPE_MODE (vect_type))
1454 != CODE_FOR_nothing
1455 && TREE_CODE (vec0) == VECTOR_CST
1456 && initializer_zerop (vec0))
1457 {
1458 unsigned int first = 0;
1459 for (i = 0; i < elements; ++i)
1460 if (known_eq (poly_uint64 (indices[i]), elements))
1461 {
1462 if (i == 0 || first)
1463 break;
1464 first = i;
1465 }
1466 else if (first
1467 ? maybe_ne (poly_uint64 (indices[i]),
1468 elements + i - first)
1469 : maybe_ge (poly_uint64 (indices[i]), elements))
1470 break;
1471 if (i == elements)
1472 {
1473 gimple_assign_set_rhs3 (stmt, mask);
1474 update_stmt (stmt);
1475 return;
1476 }
1477 }
1478 }
1479 else if (can_vec_perm_var_p (TYPE_MODE (vect_type)))
1480 return;
1481
1482 warning_at (loc, OPT_Wvector_operation_performance,
1483 "vector shuffling operation will be expanded piecewise");
1484
1485 vec_alloc (v, elements);
1486 for (i = 0; i < elements; i++)
1487 {
1488 si = size_int (i);
1489 i_val = vector_element (gsi, mask, si, &masktmp);
1490
1491 if (TREE_CODE (i_val) == INTEGER_CST)
1492 {
1493 unsigned HOST_WIDE_INT index;
1494
1495 index = TREE_INT_CST_LOW (i_val);
1496 if (!tree_fits_uhwi_p (i_val) || index >= elements)
1497 i_val = build_int_cst (mask_elt_type, index & (elements - 1));
1498
1499 if (two_operand_p && (index & elements) != 0)
1500 t = vector_element (gsi, vec1, i_val, &vec1tmp);
1501 else
1502 t = vector_element (gsi, vec0, i_val, &vec0tmp);
1503
1504 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE,
1505 true, GSI_SAME_STMT);
1506 }
1507 else
1508 {
1509 tree cond = NULL_TREE, v0_val;
1510
1511 if (two_operand_p)
1512 {
1513 cond = fold_build2 (BIT_AND_EXPR, mask_elt_type, i_val,
1514 build_int_cst (mask_elt_type, elements));
1515 cond = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE,
1516 true, GSI_SAME_STMT);
1517 }
1518
1519 i_val = fold_build2 (BIT_AND_EXPR, mask_elt_type, i_val,
1520 build_int_cst (mask_elt_type, elements - 1));
1521 i_val = force_gimple_operand_gsi (gsi, i_val, true, NULL_TREE,
1522 true, GSI_SAME_STMT);
1523
1524 v0_val = vector_element (gsi, vec0, i_val, &vec0tmp);
1525 v0_val = force_gimple_operand_gsi (gsi, v0_val, true, NULL_TREE,
1526 true, GSI_SAME_STMT);
1527
1528 if (two_operand_p)
1529 {
1530 tree v1_val;
1531
1532 v1_val = vector_element (gsi, vec1, i_val, &vec1tmp);
1533 v1_val = force_gimple_operand_gsi (gsi, v1_val, true, NULL_TREE,
1534 true, GSI_SAME_STMT);
1535
1536 cond = fold_build2 (EQ_EXPR, boolean_type_node,
1537 cond, build_zero_cst (mask_elt_type));
1538 cond = fold_build3 (COND_EXPR, vect_elt_type,
1539 cond, v0_val, v1_val);
1540 t = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE,
1541 true, GSI_SAME_STMT);
1542 }
1543 else
1544 t = v0_val;
1545 }
1546
1547 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, t);
1548 }
1549
1550 constr = build_constructor (vect_type, v);
1551 gimple_assign_set_rhs_from_tree (gsi, constr);
1552 update_stmt (gsi_stmt (*gsi));
1553 }
1554
1555 /* If OP is a uniform vector return the element it is a splat from. */
1556
1557 static tree
1558 ssa_uniform_vector_p (tree op)
1559 {
1560 if (TREE_CODE (op) == VECTOR_CST
1561 || TREE_CODE (op) == VEC_DUPLICATE_EXPR
1562 || TREE_CODE (op) == CONSTRUCTOR)
1563 return uniform_vector_p (op);
1564 if (TREE_CODE (op) == SSA_NAME)
1565 {
1566 gimple *def_stmt = SSA_NAME_DEF_STMT (op);
1567 if (gimple_assign_single_p (def_stmt))
1568 return uniform_vector_p (gimple_assign_rhs1 (def_stmt));
1569 }
1570 return NULL_TREE;
1571 }
1572
1573 /* Return type in which CODE operation with optab OP can be
1574 computed. */
1575
1576 static tree
1577 get_compute_type (enum tree_code code, optab op, tree type)
1578 {
1579 /* For very wide vectors, try using a smaller vector mode. */
1580 tree compute_type = type;
1581 if (op
1582 && (!VECTOR_MODE_P (TYPE_MODE (type))
1583 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing))
1584 {
1585 tree vector_compute_type
1586 = type_for_widest_vector_mode (TREE_TYPE (type), op);
1587 if (vector_compute_type != NULL_TREE
1588 && subparts_gt (compute_type, vector_compute_type)
1589 && maybe_ne (TYPE_VECTOR_SUBPARTS (vector_compute_type), 1U)
1590 && (optab_handler (op, TYPE_MODE (vector_compute_type))
1591 != CODE_FOR_nothing))
1592 compute_type = vector_compute_type;
1593 }
1594
1595 /* If we are breaking a BLKmode vector into smaller pieces,
1596 type_for_widest_vector_mode has already looked into the optab,
1597 so skip these checks. */
1598 if (compute_type == type)
1599 {
1600 machine_mode compute_mode = TYPE_MODE (compute_type);
1601 if (VECTOR_MODE_P (compute_mode))
1602 {
1603 if (op && optab_handler (op, compute_mode) != CODE_FOR_nothing)
1604 return compute_type;
1605 if (code == MULT_HIGHPART_EXPR
1606 && can_mult_highpart_p (compute_mode,
1607 TYPE_UNSIGNED (compute_type)))
1608 return compute_type;
1609 }
1610 /* There is no operation in hardware, so fall back to scalars. */
1611 compute_type = TREE_TYPE (type);
1612 }
1613
1614 return compute_type;
1615 }
1616
1617 static tree
1618 do_cond (gimple_stmt_iterator *gsi, tree inner_type, tree a, tree b,
1619 tree bitpos, tree bitsize, enum tree_code code,
1620 tree type ATTRIBUTE_UNUSED)
1621 {
1622 if (TREE_CODE (TREE_TYPE (a)) == VECTOR_TYPE)
1623 a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
1624 if (TREE_CODE (TREE_TYPE (b)) == VECTOR_TYPE)
1625 b = tree_vec_extract (gsi, inner_type, b, bitsize, bitpos);
1626 tree cond = gimple_assign_rhs1 (gsi_stmt (*gsi));
1627 return gimplify_build3 (gsi, code, inner_type, unshare_expr (cond), a, b);
1628 }
1629
1630 /* Expand a vector COND_EXPR to scalars, piecewise. */
1631 static void
1632 expand_vector_scalar_condition (gimple_stmt_iterator *gsi)
1633 {
1634 gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
1635 tree type = gimple_expr_type (stmt);
1636 tree compute_type = get_compute_type (COND_EXPR, mov_optab, type);
1637 machine_mode compute_mode = TYPE_MODE (compute_type);
1638 gcc_assert (compute_mode != BLKmode);
1639 tree lhs = gimple_assign_lhs (stmt);
1640 tree rhs2 = gimple_assign_rhs2 (stmt);
1641 tree rhs3 = gimple_assign_rhs3 (stmt);
1642 tree new_rhs;
1643
1644 /* If the compute mode is not a vector mode (hence we are not decomposing
1645 a BLKmode vector to smaller, hardware-supported vectors), we may want
1646 to expand the operations in parallel. */
1647 if (!VECTOR_MODE_P (compute_mode))
1648 new_rhs = expand_vector_parallel (gsi, do_cond, type, rhs2, rhs3,
1649 COND_EXPR);
1650 else
1651 new_rhs = expand_vector_piecewise (gsi, do_cond, type, compute_type,
1652 rhs2, rhs3, COND_EXPR);
1653 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (new_rhs)))
1654 new_rhs = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, TREE_TYPE (lhs),
1655 new_rhs);
1656
1657 /* NOTE: We should avoid using gimple_assign_set_rhs_from_tree. One
1658 way to do it is change expand_vector_operation and its callees to
1659 return a tree_code, RHS1 and RHS2 instead of a tree. */
1660 gimple_assign_set_rhs_from_tree (gsi, new_rhs);
1661 update_stmt (gsi_stmt (*gsi));
1662 }
1663
1664 /* Callback for expand_vector_piecewise to do VEC_CONVERT ifn call
1665 lowering. If INNER_TYPE is not a vector type, this is a scalar
1666 fallback. */
1667
1668 static tree
1669 do_vec_conversion (gimple_stmt_iterator *gsi, tree inner_type, tree a,
1670 tree decl, tree bitpos, tree bitsize,
1671 enum tree_code code, tree type)
1672 {
1673 a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
1674 if (!VECTOR_TYPE_P (inner_type))
1675 return gimplify_build1 (gsi, code, TREE_TYPE (type), a);
1676 if (code == CALL_EXPR)
1677 {
1678 gimple *g = gimple_build_call (decl, 1, a);
1679 tree lhs = make_ssa_name (TREE_TYPE (TREE_TYPE (decl)));
1680 gimple_call_set_lhs (g, lhs);
1681 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1682 return lhs;
1683 }
1684 else
1685 {
1686 tree outer_type = build_vector_type (TREE_TYPE (type),
1687 TYPE_VECTOR_SUBPARTS (inner_type));
1688 return gimplify_build1 (gsi, code, outer_type, a);
1689 }
1690 }
1691
1692 /* Similarly, but for narrowing conversion. */
1693
1694 static tree
1695 do_vec_narrow_conversion (gimple_stmt_iterator *gsi, tree inner_type, tree a,
1696 tree, tree bitpos, tree, enum tree_code code,
1697 tree type)
1698 {
1699 tree itype = build_vector_type (TREE_TYPE (inner_type),
1700 exact_div (TYPE_VECTOR_SUBPARTS (inner_type),
1701 2));
1702 tree b = tree_vec_extract (gsi, itype, a, TYPE_SIZE (itype), bitpos);
1703 tree c = tree_vec_extract (gsi, itype, a, TYPE_SIZE (itype),
1704 int_const_binop (PLUS_EXPR, bitpos,
1705 TYPE_SIZE (itype)));
1706 tree outer_type = build_vector_type (TREE_TYPE (type),
1707 TYPE_VECTOR_SUBPARTS (inner_type));
1708 return gimplify_build2 (gsi, code, outer_type, b, c);
1709 }
1710
1711 /* Expand VEC_CONVERT ifn call. */
1712
1713 static void
1714 expand_vector_conversion (gimple_stmt_iterator *gsi)
1715 {
1716 gimple *stmt = gsi_stmt (*gsi);
1717 gimple *g;
1718 tree lhs = gimple_call_lhs (stmt);
1719 tree arg = gimple_call_arg (stmt, 0);
1720 tree ret_type = TREE_TYPE (lhs);
1721 tree arg_type = TREE_TYPE (arg);
1722 tree new_rhs, compute_type = TREE_TYPE (arg_type);
1723 enum tree_code code = NOP_EXPR;
1724 enum tree_code code1 = ERROR_MARK;
1725 enum { NARROW, NONE, WIDEN } modifier = NONE;
1726 optab optab1 = unknown_optab;
1727
1728 gcc_checking_assert (VECTOR_TYPE_P (ret_type) && VECTOR_TYPE_P (arg_type));
1729 if (INTEGRAL_TYPE_P (TREE_TYPE (ret_type))
1730 && SCALAR_FLOAT_TYPE_P (TREE_TYPE (arg_type)))
1731 code = FIX_TRUNC_EXPR;
1732 else if (INTEGRAL_TYPE_P (TREE_TYPE (arg_type))
1733 && SCALAR_FLOAT_TYPE_P (TREE_TYPE (ret_type)))
1734 code = FLOAT_EXPR;
1735 unsigned int ret_elt_bits = vector_element_bits (ret_type);
1736 unsigned int arg_elt_bits = vector_element_bits (arg_type);
1737 if (ret_elt_bits < arg_elt_bits)
1738 modifier = NARROW;
1739 else if (ret_elt_bits > arg_elt_bits)
1740 modifier = WIDEN;
1741
1742 if (modifier == NONE && (code == FIX_TRUNC_EXPR || code == FLOAT_EXPR))
1743 {
1744 if (supportable_convert_operation (code, ret_type, arg_type, &code1))
1745 {
1746 g = gimple_build_assign (lhs, code1, arg);
1747 gsi_replace (gsi, g, false);
1748 return;
1749 }
1750 /* Can't use get_compute_type here, as supportable_convert_operation
1751 doesn't necessarily use an optab and needs two arguments. */
1752 tree vec_compute_type
1753 = type_for_widest_vector_mode (TREE_TYPE (arg_type), mov_optab);
1754 if (vec_compute_type
1755 && VECTOR_MODE_P (TYPE_MODE (vec_compute_type))
1756 && subparts_gt (arg_type, vec_compute_type))
1757 {
1758 unsigned HOST_WIDE_INT nelts
1759 = constant_lower_bound (TYPE_VECTOR_SUBPARTS (vec_compute_type));
1760 while (nelts > 1)
1761 {
1762 tree ret1_type = build_vector_type (TREE_TYPE (ret_type), nelts);
1763 tree arg1_type = build_vector_type (TREE_TYPE (arg_type), nelts);
1764 if (supportable_convert_operation (code, ret1_type, arg1_type,
1765 &code1))
1766 {
1767 new_rhs = expand_vector_piecewise (gsi, do_vec_conversion,
1768 ret_type, arg1_type, arg,
1769 NULL_TREE, code1);
1770 g = gimple_build_assign (lhs, new_rhs);
1771 gsi_replace (gsi, g, false);
1772 return;
1773 }
1774 nelts = nelts / 2;
1775 }
1776 }
1777 }
1778 else if (modifier == NARROW)
1779 {
1780 switch (code)
1781 {
1782 CASE_CONVERT:
1783 code1 = VEC_PACK_TRUNC_EXPR;
1784 optab1 = optab_for_tree_code (code1, arg_type, optab_default);
1785 break;
1786 case FIX_TRUNC_EXPR:
1787 code1 = VEC_PACK_FIX_TRUNC_EXPR;
1788 /* The signedness is determined from output operand. */
1789 optab1 = optab_for_tree_code (code1, ret_type, optab_default);
1790 break;
1791 case FLOAT_EXPR:
1792 code1 = VEC_PACK_FLOAT_EXPR;
1793 optab1 = optab_for_tree_code (code1, arg_type, optab_default);
1794 break;
1795 default:
1796 gcc_unreachable ();
1797 }
1798
1799 if (optab1)
1800 compute_type = get_compute_type (code1, optab1, arg_type);
1801 enum insn_code icode1;
1802 if (VECTOR_TYPE_P (compute_type)
1803 && ((icode1 = optab_handler (optab1, TYPE_MODE (compute_type)))
1804 != CODE_FOR_nothing)
1805 && VECTOR_MODE_P (insn_data[icode1].operand[0].mode))
1806 {
1807 tree cretd_type
1808 = build_vector_type (TREE_TYPE (ret_type),
1809 TYPE_VECTOR_SUBPARTS (compute_type) * 2);
1810 if (insn_data[icode1].operand[0].mode == TYPE_MODE (cretd_type))
1811 {
1812 if (compute_type == arg_type)
1813 {
1814 new_rhs = gimplify_build2 (gsi, code1, cretd_type,
1815 arg, build_zero_cst (arg_type));
1816 new_rhs = tree_vec_extract (gsi, ret_type, new_rhs,
1817 TYPE_SIZE (ret_type),
1818 bitsize_int (0));
1819 g = gimple_build_assign (lhs, new_rhs);
1820 gsi_replace (gsi, g, false);
1821 return;
1822 }
1823 tree dcompute_type
1824 = build_vector_type (TREE_TYPE (compute_type),
1825 TYPE_VECTOR_SUBPARTS (compute_type) * 2);
1826 if (TYPE_MAIN_VARIANT (dcompute_type)
1827 == TYPE_MAIN_VARIANT (arg_type))
1828 new_rhs = do_vec_narrow_conversion (gsi, dcompute_type, arg,
1829 NULL_TREE, bitsize_int (0),
1830 NULL_TREE, code1,
1831 ret_type);
1832 else
1833 new_rhs = expand_vector_piecewise (gsi,
1834 do_vec_narrow_conversion,
1835 arg_type, dcompute_type,
1836 arg, NULL_TREE, code1,
1837 ret_type);
1838 g = gimple_build_assign (lhs, new_rhs);
1839 gsi_replace (gsi, g, false);
1840 return;
1841 }
1842 }
1843 }
1844 else if (modifier == WIDEN)
1845 {
1846 enum tree_code code2 = ERROR_MARK;
1847 optab optab2 = unknown_optab;
1848 switch (code)
1849 {
1850 CASE_CONVERT:
1851 code1 = VEC_UNPACK_LO_EXPR;
1852 code2 = VEC_UNPACK_HI_EXPR;
1853 break;
1854 case FIX_TRUNC_EXPR:
1855 code1 = VEC_UNPACK_FIX_TRUNC_LO_EXPR;
1856 code2 = VEC_UNPACK_FIX_TRUNC_HI_EXPR;
1857 break;
1858 case FLOAT_EXPR:
1859 code1 = VEC_UNPACK_FLOAT_LO_EXPR;
1860 code2 = VEC_UNPACK_FLOAT_HI_EXPR;
1861 break;
1862 default:
1863 gcc_unreachable ();
1864 }
1865 if (BYTES_BIG_ENDIAN)
1866 std::swap (code1, code2);
1867
1868 if (code == FIX_TRUNC_EXPR)
1869 {
1870 /* The signedness is determined from output operand. */
1871 optab1 = optab_for_tree_code (code1, ret_type, optab_default);
1872 optab2 = optab_for_tree_code (code2, ret_type, optab_default);
1873 }
1874 else
1875 {
1876 optab1 = optab_for_tree_code (code1, arg_type, optab_default);
1877 optab2 = optab_for_tree_code (code2, arg_type, optab_default);
1878 }
1879
1880 if (optab1 && optab2)
1881 compute_type = get_compute_type (code1, optab1, arg_type);
1882
1883 enum insn_code icode1, icode2;
1884 if (VECTOR_TYPE_P (compute_type)
1885 && ((icode1 = optab_handler (optab1, TYPE_MODE (compute_type)))
1886 != CODE_FOR_nothing)
1887 && ((icode2 = optab_handler (optab2, TYPE_MODE (compute_type)))
1888 != CODE_FOR_nothing)
1889 && VECTOR_MODE_P (insn_data[icode1].operand[0].mode)
1890 && (insn_data[icode1].operand[0].mode
1891 == insn_data[icode2].operand[0].mode))
1892 {
1893 poly_uint64 nunits
1894 = exact_div (TYPE_VECTOR_SUBPARTS (compute_type), 2);
1895 tree cretd_type = build_vector_type (TREE_TYPE (ret_type), nunits);
1896 if (insn_data[icode1].operand[0].mode == TYPE_MODE (cretd_type))
1897 {
1898 vec<constructor_elt, va_gc> *v;
1899 tree part_width = TYPE_SIZE (compute_type);
1900 tree index = bitsize_int (0);
1901 int nunits = nunits_for_known_piecewise_op (arg_type);
1902 int delta = tree_to_uhwi (part_width) / arg_elt_bits;
1903 int i;
1904 location_t loc = gimple_location (gsi_stmt (*gsi));
1905
1906 if (compute_type != arg_type)
1907 warning_at (loc, OPT_Wvector_operation_performance,
1908 "vector operation will be expanded piecewise");
1909 else
1910 {
1911 nunits = 1;
1912 delta = 1;
1913 }
1914
1915 vec_alloc (v, (nunits + delta - 1) / delta * 2);
1916 for (i = 0; i < nunits;
1917 i += delta, index = int_const_binop (PLUS_EXPR, index,
1918 part_width))
1919 {
1920 tree a = arg;
1921 if (compute_type != arg_type)
1922 a = tree_vec_extract (gsi, compute_type, a, part_width,
1923 index);
1924 tree result = gimplify_build1 (gsi, code1, cretd_type, a);
1925 constructor_elt ce = { NULL_TREE, result };
1926 v->quick_push (ce);
1927 ce.value = gimplify_build1 (gsi, code2, cretd_type, a);
1928 v->quick_push (ce);
1929 }
1930
1931 new_rhs = build_constructor (ret_type, v);
1932 g = gimple_build_assign (lhs, new_rhs);
1933 gsi_replace (gsi, g, false);
1934 return;
1935 }
1936 }
1937 }
1938
1939 new_rhs = expand_vector_piecewise (gsi, do_vec_conversion, arg_type,
1940 TREE_TYPE (arg_type), arg,
1941 NULL_TREE, code, ret_type);
1942 g = gimple_build_assign (lhs, new_rhs);
1943 gsi_replace (gsi, g, false);
1944 }
1945
1946 /* Process one statement. If we identify a vector operation, expand it. */
1947
1948 static void
1949 expand_vector_operations_1 (gimple_stmt_iterator *gsi)
1950 {
1951 tree lhs, rhs1, rhs2 = NULL, type, compute_type = NULL_TREE;
1952 enum tree_code code;
1953 optab op = unknown_optab;
1954 enum gimple_rhs_class rhs_class;
1955 tree new_rhs;
1956
1957 /* Only consider code == GIMPLE_ASSIGN. */
1958 gassign *stmt = dyn_cast <gassign *> (gsi_stmt (*gsi));
1959 if (!stmt)
1960 {
1961 if (gimple_call_internal_p (gsi_stmt (*gsi), IFN_VEC_CONVERT))
1962 expand_vector_conversion (gsi);
1963 return;
1964 }
1965
1966 code = gimple_assign_rhs_code (stmt);
1967 rhs_class = get_gimple_rhs_class (code);
1968 lhs = gimple_assign_lhs (stmt);
1969
1970 if (code == VEC_PERM_EXPR)
1971 {
1972 lower_vec_perm (gsi);
1973 return;
1974 }
1975
1976 if (code == VEC_COND_EXPR)
1977 {
1978 expand_vector_condition (gsi);
1979 return;
1980 }
1981
1982 if (code == COND_EXPR
1983 && TREE_CODE (TREE_TYPE (gimple_assign_lhs (stmt))) == VECTOR_TYPE
1984 && TYPE_MODE (TREE_TYPE (gimple_assign_lhs (stmt))) == BLKmode)
1985 {
1986 expand_vector_scalar_condition (gsi);
1987 return;
1988 }
1989
1990 if (code == CONSTRUCTOR
1991 && TREE_CODE (lhs) == SSA_NAME
1992 && VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (lhs)))
1993 && !gimple_clobber_p (stmt)
1994 && optimize)
1995 {
1996 optimize_vector_constructor (gsi);
1997 return;
1998 }
1999
2000 if (rhs_class != GIMPLE_UNARY_RHS && rhs_class != GIMPLE_BINARY_RHS)
2001 return;
2002
2003 rhs1 = gimple_assign_rhs1 (stmt);
2004 type = gimple_expr_type (stmt);
2005 if (rhs_class == GIMPLE_BINARY_RHS)
2006 rhs2 = gimple_assign_rhs2 (stmt);
2007
2008 if (!VECTOR_TYPE_P (type)
2009 || !VECTOR_TYPE_P (TREE_TYPE (rhs1)))
2010 return;
2011
2012 /* A scalar operation pretending to be a vector one. */
2013 if (VECTOR_BOOLEAN_TYPE_P (type)
2014 && !VECTOR_MODE_P (TYPE_MODE (type))
2015 && TYPE_MODE (type) != BLKmode
2016 && (TREE_CODE_CLASS (gimple_assign_rhs_code (stmt)) != tcc_comparison
2017 || (VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (rhs1))
2018 && !VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (rhs1)))
2019 && TYPE_MODE (TREE_TYPE (rhs1)) != BLKmode)))
2020 return;
2021
2022 /* If the vector operation is operating on all same vector elements
2023 implement it with a scalar operation and a splat if the target
2024 supports the scalar operation. */
2025 tree srhs1, srhs2 = NULL_TREE;
2026 if ((srhs1 = ssa_uniform_vector_p (rhs1)) != NULL_TREE
2027 && (rhs2 == NULL_TREE
2028 || (! VECTOR_TYPE_P (TREE_TYPE (rhs2))
2029 && (srhs2 = rhs2))
2030 || (srhs2 = ssa_uniform_vector_p (rhs2)) != NULL_TREE)
2031 /* As we query direct optabs restrict to non-convert operations. */
2032 && TYPE_MODE (TREE_TYPE (type)) == TYPE_MODE (TREE_TYPE (srhs1)))
2033 {
2034 op = optab_for_tree_code (code, TREE_TYPE (type), optab_scalar);
2035 if (op >= FIRST_NORM_OPTAB && op <= LAST_NORM_OPTAB
2036 && optab_handler (op, TYPE_MODE (TREE_TYPE (type))) != CODE_FOR_nothing)
2037 {
2038 tree slhs = make_ssa_name (TREE_TYPE (srhs1));
2039 gimple *repl = gimple_build_assign (slhs, code, srhs1, srhs2);
2040 gsi_insert_before (gsi, repl, GSI_SAME_STMT);
2041 gimple_assign_set_rhs_from_tree (gsi,
2042 build_vector_from_val (type, slhs));
2043 update_stmt (stmt);
2044 return;
2045 }
2046 }
2047
2048 if (CONVERT_EXPR_CODE_P (code)
2049 || code == FLOAT_EXPR
2050 || code == FIX_TRUNC_EXPR
2051 || code == VIEW_CONVERT_EXPR)
2052 return;
2053
2054 /* The signedness is determined from input argument. */
2055 if (code == VEC_UNPACK_FLOAT_HI_EXPR
2056 || code == VEC_UNPACK_FLOAT_LO_EXPR
2057 || code == VEC_PACK_FLOAT_EXPR)
2058 {
2059 /* We do not know how to scalarize those. */
2060 return;
2061 }
2062
2063 /* For widening/narrowing vector operations, the relevant type is of the
2064 arguments, not the widened result. VEC_UNPACK_FLOAT_*_EXPR is
2065 calculated in the same way above. */
2066 if (code == WIDEN_SUM_EXPR
2067 || code == VEC_WIDEN_MULT_HI_EXPR
2068 || code == VEC_WIDEN_MULT_LO_EXPR
2069 || code == VEC_WIDEN_MULT_EVEN_EXPR
2070 || code == VEC_WIDEN_MULT_ODD_EXPR
2071 || code == VEC_UNPACK_HI_EXPR
2072 || code == VEC_UNPACK_LO_EXPR
2073 || code == VEC_UNPACK_FIX_TRUNC_HI_EXPR
2074 || code == VEC_UNPACK_FIX_TRUNC_LO_EXPR
2075 || code == VEC_PACK_TRUNC_EXPR
2076 || code == VEC_PACK_SAT_EXPR
2077 || code == VEC_PACK_FIX_TRUNC_EXPR
2078 || code == VEC_WIDEN_LSHIFT_HI_EXPR
2079 || code == VEC_WIDEN_LSHIFT_LO_EXPR)
2080 {
2081 /* We do not know how to scalarize those. */
2082 return;
2083 }
2084
2085 /* Choose between vector shift/rotate by vector and vector shift/rotate by
2086 scalar */
2087 if (code == LSHIFT_EXPR
2088 || code == RSHIFT_EXPR
2089 || code == LROTATE_EXPR
2090 || code == RROTATE_EXPR)
2091 {
2092 optab opv;
2093
2094 /* Check whether we have vector <op> {x,x,x,x} where x
2095 could be a scalar variable or a constant. Transform
2096 vector <op> {x,x,x,x} ==> vector <op> scalar. */
2097 if (VECTOR_INTEGER_TYPE_P (TREE_TYPE (rhs2)))
2098 {
2099 tree first;
2100
2101 if ((first = ssa_uniform_vector_p (rhs2)) != NULL_TREE)
2102 {
2103 gimple_assign_set_rhs2 (stmt, first);
2104 update_stmt (stmt);
2105 rhs2 = first;
2106 }
2107 }
2108
2109 opv = optab_for_tree_code (code, type, optab_vector);
2110 if (VECTOR_INTEGER_TYPE_P (TREE_TYPE (rhs2)))
2111 op = opv;
2112 else
2113 {
2114 op = optab_for_tree_code (code, type, optab_scalar);
2115
2116 compute_type = get_compute_type (code, op, type);
2117 if (compute_type == type)
2118 return;
2119 /* The rtl expander will expand vector/scalar as vector/vector
2120 if necessary. Pick one with wider vector type. */
2121 tree compute_vtype = get_compute_type (code, opv, type);
2122 if (subparts_gt (compute_vtype, compute_type))
2123 {
2124 compute_type = compute_vtype;
2125 op = opv;
2126 }
2127 }
2128
2129 if (code == LROTATE_EXPR || code == RROTATE_EXPR)
2130 {
2131 if (compute_type == NULL_TREE)
2132 compute_type = get_compute_type (code, op, type);
2133 if (compute_type == type)
2134 return;
2135 /* Before splitting vector rotates into scalar rotates,
2136 see if we can't use vector shifts and BIT_IOR_EXPR
2137 instead. For vector by vector rotates we'd also
2138 need to check BIT_AND_EXPR and NEGATE_EXPR, punt there
2139 for now, fold doesn't seem to create such rotates anyway. */
2140 if (compute_type == TREE_TYPE (type)
2141 && !VECTOR_INTEGER_TYPE_P (TREE_TYPE (rhs2)))
2142 {
2143 optab oplv = vashl_optab, opl = ashl_optab;
2144 optab oprv = vlshr_optab, opr = lshr_optab, opo = ior_optab;
2145 tree compute_lvtype = get_compute_type (LSHIFT_EXPR, oplv, type);
2146 tree compute_rvtype = get_compute_type (RSHIFT_EXPR, oprv, type);
2147 tree compute_otype = get_compute_type (BIT_IOR_EXPR, opo, type);
2148 tree compute_ltype = get_compute_type (LSHIFT_EXPR, opl, type);
2149 tree compute_rtype = get_compute_type (RSHIFT_EXPR, opr, type);
2150 /* The rtl expander will expand vector/scalar as vector/vector
2151 if necessary. Pick one with wider vector type. */
2152 if (subparts_gt (compute_lvtype, compute_ltype))
2153 {
2154 compute_ltype = compute_lvtype;
2155 opl = oplv;
2156 }
2157 if (subparts_gt (compute_rvtype, compute_rtype))
2158 {
2159 compute_rtype = compute_rvtype;
2160 opr = oprv;
2161 }
2162 /* Pick the narrowest type from LSHIFT_EXPR, RSHIFT_EXPR and
2163 BIT_IOR_EXPR. */
2164 compute_type = compute_ltype;
2165 if (subparts_gt (compute_type, compute_rtype))
2166 compute_type = compute_rtype;
2167 if (subparts_gt (compute_type, compute_otype))
2168 compute_type = compute_otype;
2169 /* Verify all 3 operations can be performed in that type. */
2170 if (compute_type != TREE_TYPE (type))
2171 {
2172 if (optab_handler (opl, TYPE_MODE (compute_type))
2173 == CODE_FOR_nothing
2174 || optab_handler (opr, TYPE_MODE (compute_type))
2175 == CODE_FOR_nothing
2176 || optab_handler (opo, TYPE_MODE (compute_type))
2177 == CODE_FOR_nothing)
2178 compute_type = TREE_TYPE (type);
2179 }
2180 }
2181 }
2182 }
2183 else
2184 op = optab_for_tree_code (code, type, optab_default);
2185
2186 /* Optabs will try converting a negation into a subtraction, so
2187 look for it as well. TODO: negation of floating-point vectors
2188 might be turned into an exclusive OR toggling the sign bit. */
2189 if (op == unknown_optab
2190 && code == NEGATE_EXPR
2191 && INTEGRAL_TYPE_P (TREE_TYPE (type)))
2192 op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
2193
2194 if (compute_type == NULL_TREE)
2195 compute_type = get_compute_type (code, op, type);
2196 if (compute_type == type)
2197 return;
2198
2199 new_rhs = expand_vector_operation (gsi, type, compute_type, stmt, code);
2200
2201 /* Leave expression untouched for later expansion. */
2202 if (new_rhs == NULL_TREE)
2203 return;
2204
2205 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (new_rhs)))
2206 new_rhs = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, TREE_TYPE (lhs),
2207 new_rhs);
2208
2209 /* NOTE: We should avoid using gimple_assign_set_rhs_from_tree. One
2210 way to do it is change expand_vector_operation and its callees to
2211 return a tree_code, RHS1 and RHS2 instead of a tree. */
2212 gimple_assign_set_rhs_from_tree (gsi, new_rhs);
2213 update_stmt (gsi_stmt (*gsi));
2214 }
2215 \f
2216 /* Use this to lower vector operations introduced by the vectorizer,
2217 if it may need the bit-twiddling tricks implemented in this file. */
2218
2219 static unsigned int
2220 expand_vector_operations (void)
2221 {
2222 gimple_stmt_iterator gsi;
2223 basic_block bb;
2224 bool cfg_changed = false;
2225
2226 FOR_EACH_BB_FN (bb, cfun)
2227 {
2228 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
2229 {
2230 expand_vector_operations_1 (&gsi);
2231 /* ??? If we do not cleanup EH then we will ICE in
2232 verification. But in reality we have created wrong-code
2233 as we did not properly transition EH info and edges to
2234 the piecewise computations. */
2235 if (maybe_clean_eh_stmt (gsi_stmt (gsi))
2236 && gimple_purge_dead_eh_edges (bb))
2237 cfg_changed = true;
2238 }
2239 }
2240
2241 return cfg_changed ? TODO_cleanup_cfg : 0;
2242 }
2243
2244 namespace {
2245
2246 const pass_data pass_data_lower_vector =
2247 {
2248 GIMPLE_PASS, /* type */
2249 "veclower", /* name */
2250 OPTGROUP_VEC, /* optinfo_flags */
2251 TV_NONE, /* tv_id */
2252 PROP_cfg, /* properties_required */
2253 PROP_gimple_lvec, /* properties_provided */
2254 0, /* properties_destroyed */
2255 0, /* todo_flags_start */
2256 TODO_update_ssa, /* todo_flags_finish */
2257 };
2258
2259 class pass_lower_vector : public gimple_opt_pass
2260 {
2261 public:
2262 pass_lower_vector (gcc::context *ctxt)
2263 : gimple_opt_pass (pass_data_lower_vector, ctxt)
2264 {}
2265
2266 /* opt_pass methods: */
2267 virtual bool gate (function *fun)
2268 {
2269 return !(fun->curr_properties & PROP_gimple_lvec);
2270 }
2271
2272 virtual unsigned int execute (function *)
2273 {
2274 return expand_vector_operations ();
2275 }
2276
2277 }; // class pass_lower_vector
2278
2279 } // anon namespace
2280
2281 gimple_opt_pass *
2282 make_pass_lower_vector (gcc::context *ctxt)
2283 {
2284 return new pass_lower_vector (ctxt);
2285 }
2286
2287 namespace {
2288
2289 const pass_data pass_data_lower_vector_ssa =
2290 {
2291 GIMPLE_PASS, /* type */
2292 "veclower2", /* name */
2293 OPTGROUP_VEC, /* optinfo_flags */
2294 TV_NONE, /* tv_id */
2295 PROP_cfg, /* properties_required */
2296 PROP_gimple_lvec, /* properties_provided */
2297 0, /* properties_destroyed */
2298 0, /* todo_flags_start */
2299 ( TODO_update_ssa
2300 | TODO_cleanup_cfg ), /* todo_flags_finish */
2301 };
2302
2303 class pass_lower_vector_ssa : public gimple_opt_pass
2304 {
2305 public:
2306 pass_lower_vector_ssa (gcc::context *ctxt)
2307 : gimple_opt_pass (pass_data_lower_vector_ssa, ctxt)
2308 {}
2309
2310 /* opt_pass methods: */
2311 opt_pass * clone () { return new pass_lower_vector_ssa (m_ctxt); }
2312 virtual unsigned int execute (function *)
2313 {
2314 return expand_vector_operations ();
2315 }
2316
2317 }; // class pass_lower_vector_ssa
2318
2319 } // anon namespace
2320
2321 gimple_opt_pass *
2322 make_pass_lower_vector_ssa (gcc::context *ctxt)
2323 {
2324 return new pass_lower_vector_ssa (ctxt);
2325 }
2326
2327 #include "gt-tree-vect-generic.h"