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