Require target lra in gcc.c-torture/compile/asmgoto-6.c
[official-gcc.git] / gcc / tree-vect-generic.cc
bloba7e6cb87a5e31e3dd2a893ea5652eeebf8d5d214
1 /* Lower vector operations to scalar operations.
2 Copyright (C) 2004-2023 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 */
47 #include "optabs-libfuncs.h"
50 /* Build a ternary operation and gimplify it. Emit code before GSI.
51 Return the gimple_val holding the result. */
53 static tree
54 gimplify_build3 (gimple_stmt_iterator *gsi, enum tree_code code,
55 tree type, tree a, tree b, tree c)
57 location_t loc = gimple_location (gsi_stmt (*gsi));
58 return gimple_build (gsi, true, GSI_SAME_STMT, loc, code, type, a, b, c);
61 /* Build a binary operation and gimplify it. Emit code before GSI.
62 Return the gimple_val holding the result. */
64 static tree
65 gimplify_build2 (gimple_stmt_iterator *gsi, enum tree_code code,
66 tree type, tree a, tree b)
68 location_t loc = gimple_location (gsi_stmt (*gsi));
69 return gimple_build (gsi, true, GSI_SAME_STMT, loc, code, type, a, b);
72 /* Build a unary operation and gimplify it. Emit code before GSI.
73 Return the gimple_val holding the result. */
75 static tree
76 gimplify_build1 (gimple_stmt_iterator *gsi, enum tree_code code, tree type,
77 tree a)
79 location_t loc = gimple_location (gsi_stmt (*gsi));
80 return gimple_build (gsi, true, GSI_SAME_STMT, loc, code, type, a);
84 static void expand_vector_operations_1 (gimple_stmt_iterator *, bitmap);
86 /* Return the number of elements in a vector type TYPE that we have
87 already decided needs to be expanded piecewise. We don't support
88 this kind of expansion for variable-length vectors, since we should
89 always check for target support before introducing uses of those. */
90 static unsigned int
91 nunits_for_known_piecewise_op (const_tree type)
93 return TYPE_VECTOR_SUBPARTS (type).to_constant ();
96 /* Return true if TYPE1 has more elements than TYPE2, where either
97 type may be a vector or a scalar. */
99 static inline bool
100 subparts_gt (tree type1, tree type2)
102 poly_uint64 n1 = VECTOR_TYPE_P (type1) ? TYPE_VECTOR_SUBPARTS (type1) : 1;
103 poly_uint64 n2 = VECTOR_TYPE_P (type2) ? TYPE_VECTOR_SUBPARTS (type2) : 1;
104 return known_gt (n1, n2);
107 static GTY(()) tree vector_inner_type;
108 static GTY(()) tree vector_last_type;
109 static GTY(()) int vector_last_nunits;
111 /* Return a suitable vector types made of SUBPARTS units each of mode
112 "word_mode" (the global variable). */
113 static tree
114 build_word_mode_vector_type (int nunits)
116 if (!vector_inner_type)
117 vector_inner_type = lang_hooks.types.type_for_mode (word_mode, 1);
118 else if (vector_last_nunits == nunits)
120 gcc_assert (TREE_CODE (vector_last_type) == VECTOR_TYPE);
121 return vector_last_type;
124 vector_last_nunits = nunits;
125 vector_last_type = build_vector_type (vector_inner_type, nunits);
126 return vector_last_type;
129 typedef tree (*elem_op_func) (gimple_stmt_iterator *,
130 tree, tree, tree, tree, tree, enum tree_code,
131 tree);
133 /* Extract the vector element of type TYPE at BITPOS with BITSIZE from T
134 and return it. */
136 tree
137 tree_vec_extract (gimple_stmt_iterator *gsi, tree type,
138 tree t, tree bitsize, tree bitpos)
140 /* We're using the resimplify API and maybe_push_res_to_seq to
141 simplify the BIT_FIELD_REF but restrict the simplification to
142 a single stmt while at the same time following SSA edges for
143 simplification with already emitted CTORs. */
144 gimple_match_op opr;
145 opr.set_op (BIT_FIELD_REF, type, t, bitsize, bitpos);
146 opr.resimplify (NULL, follow_all_ssa_edges);
147 gimple_seq stmts = NULL;
148 tree res = maybe_push_res_to_seq (&opr, &stmts);
149 if (!res)
151 /* This can happen if SSA_NAME_OCCURS_IN_ABNORMAL_PHI are
152 used. Build BIT_FIELD_REF manually otherwise. */
153 t = build3 (BIT_FIELD_REF, type, t, bitsize, bitpos);
154 res = make_ssa_name (type);
155 gimple *g = gimple_build_assign (res, t);
156 gsi_insert_before (gsi, g, GSI_SAME_STMT);
157 return res;
159 gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
160 return res;
163 static tree
164 do_unop (gimple_stmt_iterator *gsi, tree inner_type, tree a,
165 tree b ATTRIBUTE_UNUSED, tree bitpos, tree bitsize,
166 enum tree_code code, tree type ATTRIBUTE_UNUSED)
168 a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
169 return gimplify_build1 (gsi, code, inner_type, a);
172 static tree
173 do_binop (gimple_stmt_iterator *gsi, tree inner_type, tree a, tree b,
174 tree bitpos, tree bitsize, enum tree_code code,
175 tree type ATTRIBUTE_UNUSED)
177 if (VECTOR_TYPE_P (TREE_TYPE (a)))
178 a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
179 if (VECTOR_TYPE_P (TREE_TYPE (b)))
180 b = tree_vec_extract (gsi, inner_type, b, bitsize, bitpos);
181 return gimplify_build2 (gsi, code, inner_type, a, b);
184 /* Construct expression (A[BITPOS] code B[BITPOS]) ? -1 : 0
186 INNER_TYPE is the type of A and B elements
188 returned expression is of signed integer type with the
189 size equal to the size of INNER_TYPE. */
190 static tree
191 do_compare (gimple_stmt_iterator *gsi, tree inner_type, tree a, tree b,
192 tree bitpos, tree bitsize, enum tree_code code, tree type)
194 tree stype = TREE_TYPE (type);
195 tree cst_false = build_zero_cst (stype);
196 tree cst_true = build_all_ones_cst (stype);
197 tree cmp;
199 a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
200 b = tree_vec_extract (gsi, inner_type, b, bitsize, bitpos);
202 cmp = build2 (code, boolean_type_node, a, b);
203 return gimplify_build3 (gsi, COND_EXPR, stype, cmp, cst_true, cst_false);
206 /* Expand vector addition to scalars. This does bit twiddling
207 in order to increase parallelism:
209 a + b = (((int) a & 0x7f7f7f7f) + ((int) b & 0x7f7f7f7f)) ^
210 (a ^ b) & 0x80808080
212 a - b = (((int) a | 0x80808080) - ((int) b & 0x7f7f7f7f)) ^
213 (a ^ ~b) & 0x80808080
215 -b = (0x80808080 - ((int) b & 0x7f7f7f7f)) ^ (~b & 0x80808080)
217 This optimization should be done only if 4 vector items or more
218 fit into a word. */
219 static tree
220 do_plus_minus (gimple_stmt_iterator *gsi, tree word_type, tree a, tree b,
221 tree bitpos ATTRIBUTE_UNUSED, tree bitsize ATTRIBUTE_UNUSED,
222 enum tree_code code, tree type ATTRIBUTE_UNUSED)
224 unsigned int width = vector_element_bits (TREE_TYPE (a));
225 tree inner_type = TREE_TYPE (TREE_TYPE (a));
226 unsigned HOST_WIDE_INT max;
227 tree low_bits, high_bits, a_low, b_low, result_low, signs;
229 max = GET_MODE_MASK (TYPE_MODE (inner_type));
230 low_bits = build_replicated_int_cst (word_type, width, max >> 1);
231 high_bits = build_replicated_int_cst (word_type, width, max & ~(max >> 1));
233 a = tree_vec_extract (gsi, word_type, a, bitsize, bitpos);
234 b = tree_vec_extract (gsi, word_type, b, bitsize, bitpos);
236 signs = gimplify_build2 (gsi, BIT_XOR_EXPR, word_type, a, b);
237 b_low = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, b, low_bits);
238 if (code == PLUS_EXPR)
239 a_low = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, a, low_bits);
240 else
242 a_low = gimplify_build2 (gsi, BIT_IOR_EXPR, word_type, a, high_bits);
243 signs = gimplify_build1 (gsi, BIT_NOT_EXPR, word_type, signs);
246 signs = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, signs, high_bits);
247 result_low = gimplify_build2 (gsi, code, word_type, a_low, b_low);
248 return gimplify_build2 (gsi, BIT_XOR_EXPR, word_type, result_low, signs);
251 static tree
252 do_negate (gimple_stmt_iterator *gsi, tree word_type, tree b,
253 tree unused ATTRIBUTE_UNUSED, tree bitpos ATTRIBUTE_UNUSED,
254 tree bitsize ATTRIBUTE_UNUSED,
255 enum tree_code code ATTRIBUTE_UNUSED,
256 tree type ATTRIBUTE_UNUSED)
258 unsigned int width = vector_element_bits (TREE_TYPE (b));
259 tree inner_type = TREE_TYPE (TREE_TYPE (b));
260 HOST_WIDE_INT max;
261 tree low_bits, high_bits, b_low, result_low, signs;
263 max = GET_MODE_MASK (TYPE_MODE (inner_type));
264 low_bits = build_replicated_int_cst (word_type, width, max >> 1);
265 high_bits = build_replicated_int_cst (word_type, width, max & ~(max >> 1));
267 b = tree_vec_extract (gsi, word_type, b, bitsize, bitpos);
269 b_low = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, b, low_bits);
270 signs = gimplify_build1 (gsi, BIT_NOT_EXPR, word_type, b);
271 signs = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, signs, high_bits);
272 result_low = gimplify_build2 (gsi, MINUS_EXPR, word_type, high_bits, b_low);
273 return gimplify_build2 (gsi, BIT_XOR_EXPR, word_type, result_low, signs);
276 /* Expand a vector operation to scalars, by using many operations
277 whose type is the vector type's inner type. */
278 static tree
279 expand_vector_piecewise (gimple_stmt_iterator *gsi, elem_op_func f,
280 tree type, tree inner_type,
281 tree a, tree b, enum tree_code code,
282 bool parallel_p, tree ret_type = NULL_TREE)
284 vec<constructor_elt, va_gc> *v;
285 tree part_width = TYPE_SIZE (inner_type);
286 tree index = bitsize_int (0);
287 int nunits = nunits_for_known_piecewise_op (type);
288 int delta = tree_to_uhwi (part_width) / vector_element_bits (type);
289 int i;
290 location_t loc = gimple_location (gsi_stmt (*gsi));
292 if (nunits == 1
293 || warning_suppressed_p (gsi_stmt (*gsi),
294 OPT_Wvector_operation_performance))
295 /* Do not diagnose decomposing single element vectors or when
296 decomposing vectorizer produced operations. */
298 else if (ret_type || !parallel_p)
299 warning_at (loc, OPT_Wvector_operation_performance,
300 "vector operation will be expanded piecewise");
301 else
302 warning_at (loc, OPT_Wvector_operation_performance,
303 "vector operation will be expanded in parallel");
305 if (!ret_type)
306 ret_type = type;
307 vec_alloc (v, (nunits + delta - 1) / delta);
308 bool constant_p = true;
309 for (i = 0; i < nunits;
310 i += delta, index = int_const_binop (PLUS_EXPR, index, part_width))
312 tree result = f (gsi, inner_type, a, b, index, part_width, code,
313 ret_type);
314 if (!CONSTANT_CLASS_P (result))
315 constant_p = false;
316 constructor_elt ce = {NULL_TREE, result};
317 v->quick_push (ce);
320 if (constant_p)
321 return build_vector_from_ctor (ret_type, v);
322 else
323 return build_constructor (ret_type, v);
326 /* Expand a vector operation to scalars with the freedom to use
327 a scalar integer type, or to use a different size for the items
328 in the vector type. */
329 static tree
330 expand_vector_parallel (gimple_stmt_iterator *gsi, elem_op_func f, tree type,
331 tree a, tree b, enum tree_code code)
333 tree result, compute_type;
334 int n_words = tree_to_uhwi (TYPE_SIZE_UNIT (type)) / UNITS_PER_WORD;
335 location_t loc = gimple_location (gsi_stmt (*gsi));
337 /* We have three strategies. If the type is already correct, just do
338 the operation an element at a time. Else, if the vector is wider than
339 one word, do it a word at a time; finally, if the vector is smaller
340 than one word, do it as a scalar. */
341 if (TYPE_MODE (TREE_TYPE (type)) == word_mode)
342 return expand_vector_piecewise (gsi, f,
343 type, TREE_TYPE (type),
344 a, b, code, true);
345 else if (n_words > 1)
347 tree word_type = build_word_mode_vector_type (n_words);
348 result = expand_vector_piecewise (gsi, f,
349 word_type, TREE_TYPE (word_type),
350 a, b, code, true);
351 result = force_gimple_operand_gsi (gsi, result, true, NULL, true,
352 GSI_SAME_STMT);
354 else
356 /* Use a single scalar operation with a mode no wider than word_mode. */
357 if (!warning_suppressed_p (gsi_stmt (*gsi),
358 OPT_Wvector_operation_performance))
359 warning_at (loc, OPT_Wvector_operation_performance,
360 "vector operation will be expanded with a "
361 "single scalar operation");
362 scalar_int_mode mode
363 = int_mode_for_size (tree_to_uhwi (TYPE_SIZE (type)), 0).require ();
364 compute_type = lang_hooks.types.type_for_mode (mode, 1);
365 result = f (gsi, compute_type, a, b, bitsize_zero_node,
366 TYPE_SIZE (compute_type), code, type);
369 return result;
372 /* Expand a vector operation to scalars; for integer types we can use
373 special bit twiddling tricks to do the sums a word at a time, using
374 function F_PARALLEL instead of F. These tricks are done only if
375 they can process at least four items, that is, only if the vector
376 holds at least four items and if a word can hold four items. */
377 static tree
378 expand_vector_addition (gimple_stmt_iterator *gsi,
379 elem_op_func f, elem_op_func f_parallel,
380 tree type, tree a, tree b, enum tree_code code)
382 int parts_per_word = BITS_PER_WORD / vector_element_bits (type);
384 if (INTEGRAL_TYPE_P (TREE_TYPE (type))
385 && parts_per_word >= 4
386 && nunits_for_known_piecewise_op (type) >= 4)
387 return expand_vector_parallel (gsi, f_parallel,
388 type, a, b, code);
389 else
390 return expand_vector_piecewise (gsi, f,
391 type, TREE_TYPE (type),
392 a, b, code, false);
395 static bool
396 expand_vector_condition (gimple_stmt_iterator *gsi, bitmap dce_ssa_names);
398 /* Try to expand vector comparison expression OP0 CODE OP1 by
399 querying optab if the following expression:
400 VEC_COND_EXPR< OP0 CODE OP1, {-1,...}, {0,...}>
401 can be expanded. */
402 static tree
403 expand_vector_comparison (gimple_stmt_iterator *gsi, tree type, tree op0,
404 tree op1, enum tree_code code,
405 bitmap dce_ssa_names)
407 tree lhs = gimple_assign_lhs (gsi_stmt (*gsi));
408 use_operand_p use_p;
409 imm_use_iterator iterator;
410 bool vec_cond_expr_only = true;
412 /* As seen in PR95830, we should not expand comparisons that are only
413 feeding a VEC_COND_EXPR statement. */
414 auto_vec<gimple *> uses;
415 FOR_EACH_IMM_USE_FAST (use_p, iterator, lhs)
417 gimple *use = USE_STMT (use_p);
418 if (is_gimple_debug (use))
419 continue;
420 if (is_gimple_assign (use)
421 && gimple_assign_rhs_code (use) == VEC_COND_EXPR
422 && gimple_assign_rhs1 (use) == lhs
423 && gimple_assign_rhs2 (use) != lhs
424 && gimple_assign_rhs3 (use) != lhs)
425 uses.safe_push (use);
426 else
427 vec_cond_expr_only = false;
430 if (vec_cond_expr_only)
431 for (gimple *use : uses)
433 gimple_stmt_iterator it = gsi_for_stmt (use);
434 if (!expand_vector_condition (&it, dce_ssa_names))
436 vec_cond_expr_only = false;
437 break;
441 if (!uses.is_empty () && vec_cond_expr_only)
442 return NULL_TREE;
444 tree t;
445 if (!expand_vec_cmp_expr_p (TREE_TYPE (op0), type, code))
447 if (VECTOR_BOOLEAN_TYPE_P (type)
448 && SCALAR_INT_MODE_P (TYPE_MODE (type))
449 && known_lt (GET_MODE_BITSIZE (TYPE_MODE (type)),
450 TYPE_VECTOR_SUBPARTS (type)
451 * GET_MODE_BITSIZE (SCALAR_TYPE_MODE
452 (TREE_TYPE (type)))))
454 tree inner_type = TREE_TYPE (TREE_TYPE (op0));
455 tree part_width = vector_element_bits_tree (TREE_TYPE (op0));
456 tree index = bitsize_int (0);
457 int nunits = nunits_for_known_piecewise_op (TREE_TYPE (op0));
458 int prec = GET_MODE_PRECISION (SCALAR_TYPE_MODE (type));
459 tree ret_type = build_nonstandard_integer_type (prec, 1);
460 tree ret_inner_type = boolean_type_node;
461 int i;
462 location_t loc = gimple_location (gsi_stmt (*gsi));
463 t = build_zero_cst (ret_type);
465 if (TYPE_PRECISION (ret_inner_type) != 1)
466 ret_inner_type = build_nonstandard_integer_type (1, 1);
467 if (!warning_suppressed_p (gsi_stmt (*gsi),
468 OPT_Wvector_operation_performance))
469 warning_at (loc, OPT_Wvector_operation_performance,
470 "vector operation will be expanded piecewise");
471 for (i = 0; i < nunits;
472 i++, index = int_const_binop (PLUS_EXPR, index, part_width))
474 tree a = tree_vec_extract (gsi, inner_type, op0, part_width,
475 index);
476 tree b = tree_vec_extract (gsi, inner_type, op1, part_width,
477 index);
478 tree result = gimplify_build2 (gsi, code, ret_inner_type, a, b);
479 t = gimplify_build3 (gsi, BIT_INSERT_EXPR, ret_type, t, result,
480 bitsize_int (i));
482 t = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, type, t);
484 else
485 t = expand_vector_piecewise (gsi, do_compare, type,
486 TREE_TYPE (TREE_TYPE (op0)), op0, op1,
487 code, false);
489 else
490 t = NULL_TREE;
492 return t;
495 /* Helper function of expand_vector_divmod. Gimplify a RSHIFT_EXPR in type
496 of OP0 with shift counts in SHIFTCNTS array and return the temporary holding
497 the result if successful, otherwise return NULL_TREE. */
498 static tree
499 add_rshift (gimple_stmt_iterator *gsi, tree type, tree op0, int *shiftcnts)
501 optab op;
502 unsigned int i, nunits = nunits_for_known_piecewise_op (type);
503 bool scalar_shift = true;
505 for (i = 1; i < nunits; i++)
507 if (shiftcnts[i] != shiftcnts[0])
508 scalar_shift = false;
511 if (scalar_shift && shiftcnts[0] == 0)
512 return op0;
514 if (scalar_shift)
516 op = optab_for_tree_code (RSHIFT_EXPR, type, optab_scalar);
517 if (op != unknown_optab
518 && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
519 return gimplify_build2 (gsi, RSHIFT_EXPR, type, op0,
520 build_int_cst (NULL_TREE, shiftcnts[0]));
523 op = optab_for_tree_code (RSHIFT_EXPR, type, optab_vector);
524 if (op != unknown_optab
525 && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
527 tree_vector_builder vec (type, nunits, 1);
528 for (i = 0; i < nunits; i++)
529 vec.quick_push (build_int_cst (TREE_TYPE (type), shiftcnts[i]));
530 return gimplify_build2 (gsi, RSHIFT_EXPR, type, op0, vec.build ());
533 return NULL_TREE;
536 /* Try to expand integer vector division by constant using
537 widening multiply, shifts and additions. */
538 static tree
539 expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, tree op0,
540 tree op1, enum tree_code code)
542 bool use_pow2 = true;
543 bool has_vector_shift = true;
544 bool use_abs_op1 = false;
545 int mode = -1, this_mode;
546 int pre_shift = -1, post_shift;
547 unsigned int nunits = nunits_for_known_piecewise_op (type);
548 int *shifts = XALLOCAVEC (int, nunits * 4);
549 int *pre_shifts = shifts + nunits;
550 int *post_shifts = pre_shifts + nunits;
551 int *shift_temps = post_shifts + nunits;
552 unsigned HOST_WIDE_INT *mulc = XALLOCAVEC (unsigned HOST_WIDE_INT, nunits);
553 int prec = TYPE_PRECISION (TREE_TYPE (type));
554 int dummy_int;
555 unsigned int i;
556 signop sign_p = TYPE_SIGN (TREE_TYPE (type));
557 unsigned HOST_WIDE_INT mask = GET_MODE_MASK (TYPE_MODE (TREE_TYPE (type)));
558 tree cur_op, mulcst, tem;
559 optab op;
561 if (prec > HOST_BITS_PER_WIDE_INT)
562 return NULL_TREE;
564 op = optab_for_tree_code (RSHIFT_EXPR, type, optab_vector);
565 if (op == unknown_optab
566 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
567 has_vector_shift = false;
569 /* Analysis phase. Determine if all op1 elements are either power
570 of two and it is possible to expand it using shifts (or for remainder
571 using masking). Additionally compute the multiplicative constants
572 and pre and post shifts if the division is to be expanded using
573 widening or high part multiplication plus shifts. */
574 for (i = 0; i < nunits; i++)
576 tree cst = VECTOR_CST_ELT (op1, i);
577 unsigned HOST_WIDE_INT ml;
579 if (TREE_CODE (cst) != INTEGER_CST || integer_zerop (cst))
580 return NULL_TREE;
581 pre_shifts[i] = 0;
582 post_shifts[i] = 0;
583 mulc[i] = 0;
584 if (use_pow2
585 && (!integer_pow2p (cst) || tree_int_cst_sgn (cst) != 1))
586 use_pow2 = false;
587 if (use_pow2)
589 shifts[i] = tree_log2 (cst);
590 if (shifts[i] != shifts[0]
591 && code == TRUNC_DIV_EXPR
592 && !has_vector_shift)
593 use_pow2 = false;
595 if (mode == -2)
596 continue;
597 if (sign_p == UNSIGNED)
599 unsigned HOST_WIDE_INT mh;
600 unsigned HOST_WIDE_INT d = TREE_INT_CST_LOW (cst) & mask;
602 if (d >= (HOST_WIDE_INT_1U << (prec - 1)))
603 /* FIXME: Can transform this into op0 >= op1 ? 1 : 0. */
604 return NULL_TREE;
606 if (d <= 1)
608 mode = -2;
609 continue;
612 /* Find a suitable multiplier and right shift count
613 instead of multiplying with D. */
614 mh = choose_multiplier (d, prec, prec, &ml, &post_shift, &dummy_int);
616 /* If the suggested multiplier is more than SIZE bits, we can
617 do better for even divisors, using an initial right shift. */
618 if ((mh != 0 && (d & 1) == 0)
619 || (!has_vector_shift && pre_shift != -1))
621 if (has_vector_shift)
622 pre_shift = ctz_or_zero (d);
623 else if (pre_shift == -1)
625 unsigned int j;
626 for (j = 0; j < nunits; j++)
628 tree cst2 = VECTOR_CST_ELT (op1, j);
629 unsigned HOST_WIDE_INT d2;
630 int this_pre_shift;
632 if (!tree_fits_uhwi_p (cst2))
633 return NULL_TREE;
634 d2 = tree_to_uhwi (cst2) & mask;
635 if (d2 == 0)
636 return NULL_TREE;
637 this_pre_shift = floor_log2 (d2 & -d2);
638 if (pre_shift == -1 || this_pre_shift < pre_shift)
639 pre_shift = this_pre_shift;
641 if (i != 0 && pre_shift != 0)
643 /* Restart. */
644 i = -1U;
645 mode = -1;
646 continue;
649 if (pre_shift != 0)
651 if ((d >> pre_shift) <= 1)
653 mode = -2;
654 continue;
656 mh = choose_multiplier (d >> pre_shift, prec,
657 prec - pre_shift,
658 &ml, &post_shift, &dummy_int);
659 gcc_assert (!mh);
660 pre_shifts[i] = pre_shift;
663 if (!mh)
664 this_mode = 0;
665 else
666 this_mode = 1;
668 else
670 HOST_WIDE_INT d = TREE_INT_CST_LOW (cst);
671 unsigned HOST_WIDE_INT abs_d;
673 if (d == -1)
674 return NULL_TREE;
676 /* Since d might be INT_MIN, we have to cast to
677 unsigned HOST_WIDE_INT before negating to avoid
678 undefined signed overflow. */
679 abs_d = (d >= 0
680 ? (unsigned HOST_WIDE_INT) d
681 : - (unsigned HOST_WIDE_INT) d);
683 /* n rem d = n rem -d */
684 if (code == TRUNC_MOD_EXPR && d < 0)
686 d = abs_d;
687 use_abs_op1 = true;
689 if (abs_d == HOST_WIDE_INT_1U << (prec - 1))
691 /* This case is not handled correctly below. */
692 mode = -2;
693 continue;
695 if (abs_d <= 1)
697 mode = -2;
698 continue;
701 choose_multiplier (abs_d, prec, prec - 1, &ml,
702 &post_shift, &dummy_int);
703 if (ml >= HOST_WIDE_INT_1U << (prec - 1))
705 this_mode = 4 + (d < 0);
706 ml |= HOST_WIDE_INT_M1U << (prec - 1);
708 else
709 this_mode = 2 + (d < 0);
711 mulc[i] = ml;
712 post_shifts[i] = post_shift;
713 if ((i && !has_vector_shift && post_shifts[0] != post_shift)
714 || post_shift >= prec
715 || pre_shifts[i] >= prec)
716 this_mode = -2;
718 if (i == 0)
719 mode = this_mode;
720 else if (mode != this_mode)
721 mode = -2;
724 if (use_pow2)
726 tree addend = NULL_TREE;
727 if (sign_p == SIGNED)
729 tree uns_type;
731 /* Both division and remainder sequences need
732 op0 < 0 ? mask : 0 computed. It can be either computed as
733 (type) (((uns_type) (op0 >> (prec - 1))) >> (prec - shifts[i]))
734 if none of the shifts is 0, or as the conditional. */
735 for (i = 0; i < nunits; i++)
736 if (shifts[i] == 0)
737 break;
738 uns_type
739 = build_vector_type (build_nonstandard_integer_type (prec, 1),
740 nunits);
741 if (i == nunits && TYPE_MODE (uns_type) == TYPE_MODE (type))
743 for (i = 0; i < nunits; i++)
744 shift_temps[i] = prec - 1;
745 cur_op = add_rshift (gsi, type, op0, shift_temps);
746 if (cur_op != NULL_TREE)
748 cur_op = gimplify_build1 (gsi, VIEW_CONVERT_EXPR,
749 uns_type, cur_op);
750 for (i = 0; i < nunits; i++)
751 shift_temps[i] = prec - shifts[i];
752 cur_op = add_rshift (gsi, uns_type, cur_op, shift_temps);
753 if (cur_op != NULL_TREE)
754 addend = gimplify_build1 (gsi, VIEW_CONVERT_EXPR,
755 type, cur_op);
758 if (addend == NULL_TREE
759 && expand_vec_cond_expr_p (type, type, LT_EXPR))
761 tree zero, cst, mask_type, mask;
762 gimple *stmt, *cond;
764 mask_type = truth_type_for (type);
765 zero = build_zero_cst (type);
766 mask = make_ssa_name (mask_type);
767 cond = gimple_build_assign (mask, LT_EXPR, op0, zero);
768 gsi_insert_before (gsi, cond, GSI_SAME_STMT);
769 tree_vector_builder vec (type, nunits, 1);
770 for (i = 0; i < nunits; i++)
771 vec.quick_push (build_int_cst (TREE_TYPE (type),
772 (HOST_WIDE_INT_1U
773 << shifts[i]) - 1));
774 cst = vec.build ();
775 addend = make_ssa_name (type);
776 stmt
777 = gimple_build_assign (addend, VEC_COND_EXPR, mask, cst, zero);
778 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
781 if (code == TRUNC_DIV_EXPR)
783 if (sign_p == UNSIGNED)
785 /* q = op0 >> shift; */
786 cur_op = add_rshift (gsi, type, op0, shifts);
787 if (cur_op != NULL_TREE)
788 return cur_op;
790 else if (addend != NULL_TREE)
792 /* t1 = op0 + addend;
793 q = t1 >> shift; */
794 op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
795 if (op != unknown_optab
796 && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
798 cur_op = gimplify_build2 (gsi, PLUS_EXPR, type, op0, addend);
799 cur_op = add_rshift (gsi, type, cur_op, shifts);
800 if (cur_op != NULL_TREE)
801 return cur_op;
805 else
807 tree mask;
808 tree_vector_builder vec (type, nunits, 1);
809 for (i = 0; i < nunits; i++)
810 vec.quick_push (build_int_cst (TREE_TYPE (type),
811 (HOST_WIDE_INT_1U
812 << shifts[i]) - 1));
813 mask = vec.build ();
814 op = optab_for_tree_code (BIT_AND_EXPR, type, optab_default);
815 if (op != unknown_optab
816 && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
818 if (sign_p == UNSIGNED)
819 /* r = op0 & mask; */
820 return gimplify_build2 (gsi, BIT_AND_EXPR, type, op0, mask);
821 else if (addend != NULL_TREE)
823 /* t1 = op0 + addend;
824 t2 = t1 & mask;
825 r = t2 - addend; */
826 op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
827 if (op != unknown_optab
828 && optab_handler (op, TYPE_MODE (type))
829 != CODE_FOR_nothing)
831 cur_op = gimplify_build2 (gsi, PLUS_EXPR, type, op0,
832 addend);
833 cur_op = gimplify_build2 (gsi, BIT_AND_EXPR, type,
834 cur_op, mask);
835 op = optab_for_tree_code (MINUS_EXPR, type,
836 optab_default);
837 if (op != unknown_optab
838 && optab_handler (op, TYPE_MODE (type))
839 != CODE_FOR_nothing)
840 return gimplify_build2 (gsi, MINUS_EXPR, type,
841 cur_op, addend);
848 if (mode == -2 || BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN)
849 return NULL_TREE;
851 if (!can_mult_highpart_p (TYPE_MODE (type), TYPE_UNSIGNED (type)))
852 return NULL_TREE;
854 cur_op = op0;
856 switch (mode)
858 case 0:
859 gcc_assert (sign_p == UNSIGNED);
860 /* t1 = oprnd0 >> pre_shift;
861 t2 = t1 h* ml;
862 q = t2 >> post_shift; */
863 cur_op = add_rshift (gsi, type, cur_op, pre_shifts);
864 if (cur_op == NULL_TREE)
865 return NULL_TREE;
866 break;
867 case 1:
868 gcc_assert (sign_p == UNSIGNED);
869 for (i = 0; i < nunits; i++)
871 shift_temps[i] = 1;
872 post_shifts[i]--;
874 break;
875 case 2:
876 case 3:
877 case 4:
878 case 5:
879 gcc_assert (sign_p == SIGNED);
880 for (i = 0; i < nunits; i++)
881 shift_temps[i] = prec - 1;
882 break;
883 default:
884 return NULL_TREE;
887 tree_vector_builder vec (type, nunits, 1);
888 for (i = 0; i < nunits; i++)
889 vec.quick_push (build_int_cst (TREE_TYPE (type), mulc[i]));
890 mulcst = vec.build ();
892 cur_op = gimplify_build2 (gsi, MULT_HIGHPART_EXPR, type, cur_op, mulcst);
894 switch (mode)
896 case 0:
897 /* t1 = oprnd0 >> pre_shift;
898 t2 = t1 h* ml;
899 q = t2 >> post_shift; */
900 cur_op = add_rshift (gsi, type, cur_op, post_shifts);
901 break;
902 case 1:
903 /* t1 = oprnd0 h* ml;
904 t2 = oprnd0 - t1;
905 t3 = t2 >> 1;
906 t4 = t1 + t3;
907 q = t4 >> (post_shift - 1); */
908 op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
909 if (op == unknown_optab
910 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
911 return NULL_TREE;
912 tem = gimplify_build2 (gsi, MINUS_EXPR, type, op0, cur_op);
913 tem = add_rshift (gsi, type, tem, shift_temps);
914 op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
915 if (op == unknown_optab
916 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
917 return NULL_TREE;
918 tem = gimplify_build2 (gsi, PLUS_EXPR, type, cur_op, tem);
919 cur_op = add_rshift (gsi, type, tem, post_shifts);
920 if (cur_op == NULL_TREE)
921 return NULL_TREE;
922 break;
923 case 2:
924 case 3:
925 case 4:
926 case 5:
927 /* t1 = oprnd0 h* ml;
928 t2 = t1; [ iff (mode & 2) != 0 ]
929 t2 = t1 + oprnd0; [ iff (mode & 2) == 0 ]
930 t3 = t2 >> post_shift;
931 t4 = oprnd0 >> (prec - 1);
932 q = t3 - t4; [ iff (mode & 1) == 0 ]
933 q = t4 - t3; [ iff (mode & 1) != 0 ] */
934 if ((mode & 2) == 0)
936 op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
937 if (op == unknown_optab
938 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
939 return NULL_TREE;
940 cur_op = gimplify_build2 (gsi, PLUS_EXPR, type, cur_op, op0);
942 cur_op = add_rshift (gsi, type, cur_op, post_shifts);
943 if (cur_op == NULL_TREE)
944 return NULL_TREE;
945 tem = add_rshift (gsi, type, op0, shift_temps);
946 if (tem == NULL_TREE)
947 return NULL_TREE;
948 op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
949 if (op == unknown_optab
950 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
951 return NULL_TREE;
952 if ((mode & 1) == 0)
953 cur_op = gimplify_build2 (gsi, MINUS_EXPR, type, cur_op, tem);
954 else
955 cur_op = gimplify_build2 (gsi, MINUS_EXPR, type, tem, cur_op);
956 break;
957 default:
958 gcc_unreachable ();
961 if (code == TRUNC_DIV_EXPR)
962 return cur_op;
964 /* We divided. Now finish by:
965 t1 = q * oprnd1;
966 r = oprnd0 - t1; */
967 op = optab_for_tree_code (MULT_EXPR, type, optab_default);
968 if (op == unknown_optab
969 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
970 return NULL_TREE;
971 if (use_abs_op1)
973 tree_vector_builder elts;
974 if (!elts.new_unary_operation (type, op1, false))
975 return NULL_TREE;
976 unsigned int count = elts.encoded_nelts ();
977 for (unsigned int i = 0; i < count; ++i)
979 tree elem1 = VECTOR_CST_ELT (op1, i);
981 tree elt = const_unop (ABS_EXPR, TREE_TYPE (elem1), elem1);
982 if (elt == NULL_TREE)
983 return NULL_TREE;
984 elts.quick_push (elt);
986 op1 = elts.build ();
988 tem = gimplify_build2 (gsi, MULT_EXPR, type, cur_op, op1);
989 op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
990 if (op == unknown_optab
991 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
992 return NULL_TREE;
993 return gimplify_build2 (gsi, MINUS_EXPR, type, op0, tem);
996 /* Expand a vector condition to scalars, by using many conditions
997 on the vector's elements. */
999 static bool
1000 expand_vector_condition (gimple_stmt_iterator *gsi, bitmap dce_ssa_names)
1002 gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
1003 tree type = TREE_TYPE (gimple_assign_lhs (stmt));
1004 tree a = gimple_assign_rhs1 (stmt);
1005 tree a1 = a;
1006 tree a2 = NULL_TREE;
1007 bool a_is_comparison = false;
1008 bool a_is_scalar_bitmask = false;
1009 tree b = gimple_assign_rhs2 (stmt);
1010 tree c = gimple_assign_rhs3 (stmt);
1011 vec<constructor_elt, va_gc> *v;
1012 tree constr;
1013 tree inner_type = TREE_TYPE (type);
1014 tree width = vector_element_bits_tree (type);
1015 tree cond_type = TREE_TYPE (TREE_TYPE (a));
1016 tree comp_inner_type = cond_type;
1017 tree index = bitsize_int (0);
1018 tree comp_width = width;
1019 tree comp_index = index;
1020 location_t loc = gimple_location (gsi_stmt (*gsi));
1021 tree_code code = TREE_CODE (a);
1022 gassign *assign = NULL;
1024 if (code == SSA_NAME)
1026 assign = dyn_cast<gassign *> (SSA_NAME_DEF_STMT (a));
1027 if (assign != NULL
1028 && TREE_CODE_CLASS (gimple_assign_rhs_code (assign)) == tcc_comparison)
1030 a_is_comparison = true;
1031 a1 = gimple_assign_rhs1 (assign);
1032 a2 = gimple_assign_rhs2 (assign);
1033 code = gimple_assign_rhs_code (assign);
1034 comp_inner_type = TREE_TYPE (TREE_TYPE (a1));
1035 comp_width = vector_element_bits_tree (TREE_TYPE (a1));
1039 if (expand_vec_cond_expr_p (type, TREE_TYPE (a1), code)
1040 || (integer_all_onesp (b) && integer_zerop (c)
1041 && expand_vec_cmp_expr_p (type, TREE_TYPE (a1), code)))
1043 gcc_assert (TREE_CODE (a) == SSA_NAME || TREE_CODE (a) == VECTOR_CST);
1044 return true;
1047 /* If a has vector boolean type and is a comparison, above
1048 expand_vec_cond_expr_p might fail, even if both the comparison and
1049 VEC_COND_EXPR could be supported individually. See PR109176. */
1050 if (a_is_comparison
1051 && VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (a))
1052 && expand_vec_cond_expr_p (type, TREE_TYPE (a), SSA_NAME)
1053 && expand_vec_cmp_expr_p (TREE_TYPE (a1), TREE_TYPE (a), code))
1054 return true;
1056 /* Handle vector boolean types with bitmasks. If there is a comparison
1057 and we can expand the comparison into the vector boolean bitmask,
1058 or otherwise if it is compatible with type, we can transform
1059 vbfld_1 = x_2 < y_3 ? vbfld_4 : vbfld_5;
1060 into
1061 tmp_6 = x_2 < y_3;
1062 tmp_7 = tmp_6 & vbfld_4;
1063 tmp_8 = ~tmp_6;
1064 tmp_9 = tmp_8 & vbfld_5;
1065 vbfld_1 = tmp_7 | tmp_9;
1066 Similarly for vbfld_10 instead of x_2 < y_3. */
1067 if (VECTOR_BOOLEAN_TYPE_P (type)
1068 && SCALAR_INT_MODE_P (TYPE_MODE (type))
1069 && known_lt (GET_MODE_BITSIZE (TYPE_MODE (type)),
1070 TYPE_VECTOR_SUBPARTS (type)
1071 * GET_MODE_BITSIZE (SCALAR_TYPE_MODE (TREE_TYPE (type))))
1072 && (a_is_comparison
1073 ? useless_type_conversion_p (type, TREE_TYPE (a))
1074 : expand_vec_cmp_expr_p (TREE_TYPE (a1), type, TREE_CODE (a))))
1076 if (a_is_comparison)
1077 a = gimplify_build2 (gsi, code, type, a1, a2);
1078 a1 = gimplify_build2 (gsi, BIT_AND_EXPR, type, a, b);
1079 a2 = gimplify_build1 (gsi, BIT_NOT_EXPR, type, a);
1080 a2 = gimplify_build2 (gsi, BIT_AND_EXPR, type, a2, c);
1081 a = gimplify_build2 (gsi, BIT_IOR_EXPR, type, a1, a2);
1082 gimple_assign_set_rhs_from_tree (gsi, a);
1083 update_stmt (gsi_stmt (*gsi));
1084 return true;
1087 /* TODO: try and find a smaller vector type. */
1089 if (!warning_suppressed_p (stmt, OPT_Wvector_operation_performance))
1090 warning_at (loc, OPT_Wvector_operation_performance,
1091 "vector condition will be expanded piecewise");
1093 if (!a_is_comparison
1094 && VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (a))
1095 && SCALAR_INT_MODE_P (TYPE_MODE (TREE_TYPE (a)))
1096 && known_lt (GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (a))),
1097 TYPE_VECTOR_SUBPARTS (TREE_TYPE (a))
1098 * GET_MODE_BITSIZE (SCALAR_TYPE_MODE
1099 (TREE_TYPE (TREE_TYPE (a))))))
1101 a_is_scalar_bitmask = true;
1102 int prec = GET_MODE_PRECISION (SCALAR_TYPE_MODE (TREE_TYPE (a)));
1103 tree atype = build_nonstandard_integer_type (prec, 1);
1104 a = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, atype, a);
1106 else if (!a_is_comparison
1107 && VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (a)))
1108 comp_width = vector_element_bits_tree (TREE_TYPE (a));
1110 int nunits = nunits_for_known_piecewise_op (type);
1111 vec_alloc (v, nunits);
1112 bool constant_p = true;
1113 for (int i = 0; i < nunits; i++)
1115 tree aa, result;
1116 tree bb = tree_vec_extract (gsi, inner_type, b, width, index);
1117 tree cc = tree_vec_extract (gsi, inner_type, c, width, index);
1118 if (a_is_comparison)
1120 tree aa1 = tree_vec_extract (gsi, comp_inner_type, a1,
1121 comp_width, comp_index);
1122 tree aa2 = tree_vec_extract (gsi, comp_inner_type, a2,
1123 comp_width, comp_index);
1124 aa = gimplify_build2 (gsi, code, boolean_type_node, aa1, aa2);
1126 else if (a_is_scalar_bitmask)
1128 wide_int w = wi::set_bit_in_zero (i, TYPE_PRECISION (TREE_TYPE (a)));
1129 result = gimplify_build2 (gsi, BIT_AND_EXPR, TREE_TYPE (a),
1130 a, wide_int_to_tree (TREE_TYPE (a), w));
1131 aa = gimplify_build2 (gsi, NE_EXPR, boolean_type_node, result,
1132 build_zero_cst (TREE_TYPE (a)));
1134 else
1136 result = tree_vec_extract (gsi, cond_type, a, comp_width, comp_index);
1137 aa = gimplify_build2 (gsi, NE_EXPR, boolean_type_node, result,
1138 build_zero_cst (cond_type));
1140 result = gimplify_build3 (gsi, COND_EXPR, inner_type, aa, bb, cc);
1141 if (!CONSTANT_CLASS_P (result))
1142 constant_p = false;
1143 constructor_elt ce = {NULL_TREE, result};
1144 v->quick_push (ce);
1145 index = int_const_binop (PLUS_EXPR, index, width);
1146 if (width == comp_width)
1147 comp_index = index;
1148 else
1149 comp_index = int_const_binop (PLUS_EXPR, comp_index, comp_width);
1152 if (constant_p)
1153 constr = build_vector_from_ctor (type, v);
1154 else
1155 constr = build_constructor (type, v);
1156 gimple_assign_set_rhs_from_tree (gsi, constr);
1157 update_stmt (gsi_stmt (*gsi));
1159 if (a_is_comparison)
1160 bitmap_set_bit (dce_ssa_names,
1161 SSA_NAME_VERSION (gimple_assign_lhs (assign)));
1163 return false;
1166 static tree
1167 expand_vector_operation (gimple_stmt_iterator *gsi, tree type, tree compute_type,
1168 gassign *assign, enum tree_code code,
1169 bitmap dce_ssa_names)
1171 machine_mode compute_mode = TYPE_MODE (compute_type);
1173 /* If the compute mode is not a vector mode (hence we are not decomposing
1174 a BLKmode vector to smaller, hardware-supported vectors), we may want
1175 to expand the operations in parallel. */
1176 if (!VECTOR_MODE_P (compute_mode))
1177 switch (code)
1179 case PLUS_EXPR:
1180 case MINUS_EXPR:
1181 if (ANY_INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_TRAPS (type))
1182 return expand_vector_addition (gsi, do_binop, do_plus_minus, type,
1183 gimple_assign_rhs1 (assign),
1184 gimple_assign_rhs2 (assign), code);
1185 break;
1187 case NEGATE_EXPR:
1188 if (ANY_INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_TRAPS (type))
1189 return expand_vector_addition (gsi, do_unop, do_negate, type,
1190 gimple_assign_rhs1 (assign),
1191 NULL_TREE, code);
1192 break;
1194 case BIT_AND_EXPR:
1195 case BIT_IOR_EXPR:
1196 case BIT_XOR_EXPR:
1197 return expand_vector_parallel (gsi, do_binop, type,
1198 gimple_assign_rhs1 (assign),
1199 gimple_assign_rhs2 (assign), code);
1201 case BIT_NOT_EXPR:
1202 return expand_vector_parallel (gsi, do_unop, type,
1203 gimple_assign_rhs1 (assign),
1204 NULL_TREE, code);
1205 case EQ_EXPR:
1206 case NE_EXPR:
1207 case GT_EXPR:
1208 case LT_EXPR:
1209 case GE_EXPR:
1210 case LE_EXPR:
1211 case UNEQ_EXPR:
1212 case UNGT_EXPR:
1213 case UNLT_EXPR:
1214 case UNGE_EXPR:
1215 case UNLE_EXPR:
1216 case LTGT_EXPR:
1217 case ORDERED_EXPR:
1218 case UNORDERED_EXPR:
1220 tree rhs1 = gimple_assign_rhs1 (assign);
1221 tree rhs2 = gimple_assign_rhs2 (assign);
1223 return expand_vector_comparison (gsi, type, rhs1, rhs2, code,
1224 dce_ssa_names);
1227 case TRUNC_DIV_EXPR:
1228 case TRUNC_MOD_EXPR:
1230 tree rhs1 = gimple_assign_rhs1 (assign);
1231 tree rhs2 = gimple_assign_rhs2 (assign);
1232 tree ret;
1234 if (!optimize
1235 || !VECTOR_INTEGER_TYPE_P (type)
1236 || TREE_CODE (rhs2) != VECTOR_CST
1237 || !VECTOR_MODE_P (TYPE_MODE (type)))
1238 break;
1240 ret = expand_vector_divmod (gsi, type, rhs1, rhs2, code);
1241 if (ret != NULL_TREE)
1242 return ret;
1243 break;
1246 default:
1247 break;
1250 if (TREE_CODE_CLASS (code) == tcc_unary)
1251 return expand_vector_piecewise (gsi, do_unop, type, compute_type,
1252 gimple_assign_rhs1 (assign),
1253 NULL_TREE, code, false);
1254 else
1255 return expand_vector_piecewise (gsi, do_binop, type, compute_type,
1256 gimple_assign_rhs1 (assign),
1257 gimple_assign_rhs2 (assign), code, false);
1260 /* Try to optimize
1261 a_5 = { b_7, b_7 + 3, b_7 + 6, b_7 + 9 };
1262 style stmts into:
1263 _9 = { b_7, b_7, b_7, b_7 };
1264 a_5 = _9 + { 0, 3, 6, 9 };
1265 because vector splat operation is usually more efficient
1266 than piecewise initialization of the vector. */
1268 static void
1269 optimize_vector_constructor (gimple_stmt_iterator *gsi)
1271 gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
1272 tree lhs = gimple_assign_lhs (stmt);
1273 tree rhs = gimple_assign_rhs1 (stmt);
1274 tree type = TREE_TYPE (rhs);
1275 unsigned int i, j;
1276 unsigned HOST_WIDE_INT nelts;
1277 bool all_same = true;
1278 constructor_elt *elt;
1279 gimple *g;
1280 tree base = NULL_TREE;
1281 optab op;
1283 if (!TYPE_VECTOR_SUBPARTS (type).is_constant (&nelts)
1284 || nelts <= 2
1285 || CONSTRUCTOR_NELTS (rhs) != nelts)
1286 return;
1287 op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
1288 if (op == unknown_optab
1289 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
1290 return;
1291 FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (rhs), i, elt)
1292 if (TREE_CODE (elt->value) != SSA_NAME
1293 || TREE_CODE (TREE_TYPE (elt->value)) == VECTOR_TYPE)
1294 return;
1295 else
1297 tree this_base = elt->value;
1298 if (this_base != CONSTRUCTOR_ELT (rhs, 0)->value)
1299 all_same = false;
1300 for (j = 0; j < nelts + 1; j++)
1302 g = SSA_NAME_DEF_STMT (this_base);
1303 if (is_gimple_assign (g)
1304 && gimple_assign_rhs_code (g) == PLUS_EXPR
1305 && TREE_CODE (gimple_assign_rhs2 (g)) == INTEGER_CST
1306 && TREE_CODE (gimple_assign_rhs1 (g)) == SSA_NAME
1307 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_assign_rhs1 (g)))
1308 this_base = gimple_assign_rhs1 (g);
1309 else
1310 break;
1312 if (i == 0)
1313 base = this_base;
1314 else if (this_base != base)
1315 return;
1317 if (all_same)
1318 return;
1319 tree_vector_builder cst (type, nelts, 1);
1320 for (i = 0; i < nelts; i++)
1322 tree this_base = CONSTRUCTOR_ELT (rhs, i)->value;
1323 tree elt = build_zero_cst (TREE_TYPE (base));
1324 while (this_base != base)
1326 g = SSA_NAME_DEF_STMT (this_base);
1327 elt = fold_binary (PLUS_EXPR, TREE_TYPE (base),
1328 elt, gimple_assign_rhs2 (g));
1329 if (elt == NULL_TREE
1330 || TREE_CODE (elt) != INTEGER_CST
1331 || TREE_OVERFLOW (elt))
1332 return;
1333 this_base = gimple_assign_rhs1 (g);
1335 cst.quick_push (elt);
1337 for (i = 0; i < nelts; i++)
1338 CONSTRUCTOR_ELT (rhs, i)->value = base;
1339 g = gimple_build_assign (make_ssa_name (type), rhs);
1340 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1341 g = gimple_build_assign (lhs, PLUS_EXPR, gimple_assign_lhs (g),
1342 cst.build ());
1343 gsi_replace (gsi, g, false);
1346 /* Return a type for the widest vector mode whose components are of type
1347 TYPE, or NULL_TREE if none is found. */
1349 static tree
1350 type_for_widest_vector_mode (tree type, optab op)
1352 machine_mode inner_mode = TYPE_MODE (type);
1353 machine_mode best_mode = VOIDmode, mode;
1354 poly_int64 best_nunits = 0;
1356 if (SCALAR_FLOAT_MODE_P (inner_mode))
1357 mode = MIN_MODE_VECTOR_FLOAT;
1358 else if (SCALAR_FRACT_MODE_P (inner_mode))
1359 mode = MIN_MODE_VECTOR_FRACT;
1360 else if (SCALAR_UFRACT_MODE_P (inner_mode))
1361 mode = MIN_MODE_VECTOR_UFRACT;
1362 else if (SCALAR_ACCUM_MODE_P (inner_mode))
1363 mode = MIN_MODE_VECTOR_ACCUM;
1364 else if (SCALAR_UACCUM_MODE_P (inner_mode))
1365 mode = MIN_MODE_VECTOR_UACCUM;
1366 else if (inner_mode == BImode)
1367 mode = MIN_MODE_VECTOR_BOOL;
1368 else
1369 mode = MIN_MODE_VECTOR_INT;
1371 FOR_EACH_MODE_FROM (mode, mode)
1372 if (GET_MODE_INNER (mode) == inner_mode
1373 && maybe_gt (GET_MODE_NUNITS (mode), best_nunits)
1374 && optab_handler (op, mode) != CODE_FOR_nothing)
1375 best_mode = mode, best_nunits = GET_MODE_NUNITS (mode);
1377 if (best_mode == VOIDmode)
1378 return NULL_TREE;
1379 else
1380 return build_vector_type_for_mode (type, best_mode);
1384 /* Build a reference to the element of the vector VECT. Function
1385 returns either the element itself, either BIT_FIELD_REF, or an
1386 ARRAY_REF expression.
1388 GSI is required to insert temporary variables while building a
1389 refernece to the element of the vector VECT.
1391 PTMPVEC is a pointer to the temporary variable for caching
1392 purposes. In case when PTMPVEC is NULL new temporary variable
1393 will be created. */
1394 static tree
1395 vector_element (gimple_stmt_iterator *gsi, tree vect, tree idx, tree *ptmpvec)
1397 tree vect_type, vect_elt_type;
1398 gimple *asgn;
1399 tree tmpvec;
1400 tree arraytype;
1401 bool need_asgn = true;
1402 unsigned int elements;
1404 vect_type = TREE_TYPE (vect);
1405 vect_elt_type = TREE_TYPE (vect_type);
1406 elements = nunits_for_known_piecewise_op (vect_type);
1408 if (TREE_CODE (idx) == INTEGER_CST)
1410 unsigned HOST_WIDE_INT index;
1412 /* Given that we're about to compute a binary modulus,
1413 we don't care about the high bits of the value. */
1414 index = TREE_INT_CST_LOW (idx);
1415 if (!tree_fits_uhwi_p (idx) || index >= elements)
1417 index &= elements - 1;
1418 idx = build_int_cst (TREE_TYPE (idx), index);
1421 /* When lowering a vector statement sequence do some easy
1422 simplification by looking through intermediate vector results. */
1423 if (TREE_CODE (vect) == SSA_NAME)
1425 gimple *def_stmt = SSA_NAME_DEF_STMT (vect);
1426 if (is_gimple_assign (def_stmt)
1427 && (gimple_assign_rhs_code (def_stmt) == VECTOR_CST
1428 || gimple_assign_rhs_code (def_stmt) == CONSTRUCTOR))
1429 vect = gimple_assign_rhs1 (def_stmt);
1432 if (TREE_CODE (vect) == VECTOR_CST)
1433 return VECTOR_CST_ELT (vect, index);
1434 else if (TREE_CODE (vect) == CONSTRUCTOR
1435 && (CONSTRUCTOR_NELTS (vect) == 0
1436 || TREE_CODE (TREE_TYPE (CONSTRUCTOR_ELT (vect, 0)->value))
1437 != VECTOR_TYPE))
1439 if (index < CONSTRUCTOR_NELTS (vect))
1440 return CONSTRUCTOR_ELT (vect, index)->value;
1441 return build_zero_cst (vect_elt_type);
1443 else
1445 tree size = vector_element_bits_tree (vect_type);
1446 tree pos = fold_build2 (MULT_EXPR, bitsizetype, bitsize_int (index),
1447 size);
1448 return fold_build3 (BIT_FIELD_REF, vect_elt_type, vect, size, pos);
1452 if (!ptmpvec)
1453 tmpvec = create_tmp_var (vect_type, "vectmp");
1454 else if (!*ptmpvec)
1455 tmpvec = *ptmpvec = create_tmp_var (vect_type, "vectmp");
1456 else
1458 tmpvec = *ptmpvec;
1459 need_asgn = false;
1462 if (need_asgn)
1464 TREE_ADDRESSABLE (tmpvec) = 1;
1465 asgn = gimple_build_assign (tmpvec, vect);
1466 gsi_insert_before (gsi, asgn, GSI_SAME_STMT);
1469 arraytype = build_array_type_nelts (vect_elt_type, elements);
1470 return build4 (ARRAY_REF, vect_elt_type,
1471 build1 (VIEW_CONVERT_EXPR, arraytype, tmpvec),
1472 idx, NULL_TREE, NULL_TREE);
1475 /* Check if VEC_PERM_EXPR within the given setting is supported
1476 by hardware, or lower it piecewise.
1478 When VEC_PERM_EXPR has the same first and second operands:
1479 VEC_PERM_EXPR <v0, v0, mask> the lowered version would be
1480 {v0[mask[0]], v0[mask[1]], ...}
1481 MASK and V0 must have the same number of elements.
1483 Otherwise VEC_PERM_EXPR <v0, v1, mask> is lowered to
1484 {mask[0] < len(v0) ? v0[mask[0]] : v1[mask[0]], ...}
1485 V0 and V1 must have the same type. MASK, V0, V1 must have the
1486 same number of arguments. */
1488 static void
1489 lower_vec_perm (gimple_stmt_iterator *gsi)
1491 gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
1492 tree mask = gimple_assign_rhs3 (stmt);
1493 tree vec0 = gimple_assign_rhs1 (stmt);
1494 tree vec1 = gimple_assign_rhs2 (stmt);
1495 tree vect_type = TREE_TYPE (vec0);
1496 tree mask_type = TREE_TYPE (mask);
1497 tree vect_elt_type = TREE_TYPE (vect_type);
1498 tree mask_elt_type = TREE_TYPE (mask_type);
1499 unsigned HOST_WIDE_INT elements;
1500 vec<constructor_elt, va_gc> *v;
1501 tree constr, t, si, i_val;
1502 tree vec0tmp = NULL_TREE, vec1tmp = NULL_TREE, masktmp = NULL_TREE;
1503 bool two_operand_p = !operand_equal_p (vec0, vec1, 0);
1504 location_t loc = gimple_location (gsi_stmt (*gsi));
1505 unsigned i;
1507 if (!TYPE_VECTOR_SUBPARTS (vect_type).is_constant (&elements))
1508 return;
1510 if (TREE_CODE (mask) == SSA_NAME)
1512 gimple *def_stmt = SSA_NAME_DEF_STMT (mask);
1513 if (is_gimple_assign (def_stmt)
1514 && gimple_assign_rhs_code (def_stmt) == VECTOR_CST)
1515 mask = gimple_assign_rhs1 (def_stmt);
1518 vec_perm_builder sel_int;
1520 if (TREE_CODE (mask) == VECTOR_CST
1521 && tree_to_vec_perm_builder (&sel_int, mask))
1523 vec_perm_indices indices (sel_int, 2, elements);
1524 machine_mode vmode = TYPE_MODE (vect_type);
1525 tree lhs_type = TREE_TYPE (gimple_assign_lhs (stmt));
1526 machine_mode lhs_mode = TYPE_MODE (lhs_type);
1527 if (can_vec_perm_const_p (lhs_mode, vmode, indices))
1529 gimple_assign_set_rhs3 (stmt, mask);
1530 update_stmt (stmt);
1531 return;
1533 /* Also detect vec_shr pattern - VEC_PERM_EXPR with zero
1534 vector as VEC1 and a right element shift MASK. */
1535 if (optab_handler (vec_shr_optab, TYPE_MODE (vect_type))
1536 != CODE_FOR_nothing
1537 && TREE_CODE (vec1) == VECTOR_CST
1538 && initializer_zerop (vec1)
1539 && maybe_ne (indices[0], 0)
1540 && known_lt (poly_uint64 (indices[0]), elements))
1542 bool ok_p = indices.series_p (0, 1, indices[0], 1);
1543 if (!ok_p)
1545 for (i = 1; i < elements; ++i)
1547 poly_uint64 actual = indices[i];
1548 poly_uint64 expected = i + indices[0];
1549 /* Indices into the second vector are all equivalent. */
1550 if (maybe_lt (actual, elements)
1551 ? maybe_ne (actual, expected)
1552 : maybe_lt (expected, elements))
1553 break;
1555 ok_p = i == elements;
1557 if (ok_p)
1559 gimple_assign_set_rhs3 (stmt, mask);
1560 update_stmt (stmt);
1561 return;
1564 /* And similarly vec_shl pattern. */
1565 if (optab_handler (vec_shl_optab, TYPE_MODE (vect_type))
1566 != CODE_FOR_nothing
1567 && TREE_CODE (vec0) == VECTOR_CST
1568 && initializer_zerop (vec0))
1570 unsigned int first = 0;
1571 for (i = 0; i < elements; ++i)
1572 if (known_eq (poly_uint64 (indices[i]), elements))
1574 if (i == 0 || first)
1575 break;
1576 first = i;
1578 else if (first
1579 ? maybe_ne (poly_uint64 (indices[i]),
1580 elements + i - first)
1581 : maybe_ge (poly_uint64 (indices[i]), elements))
1582 break;
1583 if (first && i == elements)
1585 gimple_assign_set_rhs3 (stmt, mask);
1586 update_stmt (stmt);
1587 return;
1591 else if (can_vec_perm_var_p (TYPE_MODE (vect_type)))
1592 return;
1594 if (!warning_suppressed_p (stmt, OPT_Wvector_operation_performance))
1595 warning_at (loc, OPT_Wvector_operation_performance,
1596 "vector shuffling operation will be expanded piecewise");
1598 vec_alloc (v, elements);
1599 bool constant_p = true;
1600 for (i = 0; i < elements; i++)
1602 si = size_int (i);
1603 i_val = vector_element (gsi, mask, si, &masktmp);
1605 if (TREE_CODE (i_val) == INTEGER_CST)
1607 unsigned HOST_WIDE_INT index;
1609 index = TREE_INT_CST_LOW (i_val);
1610 if (!tree_fits_uhwi_p (i_val) || index >= elements)
1611 i_val = build_int_cst (mask_elt_type, index & (elements - 1));
1613 if (two_operand_p && (index & elements) != 0)
1614 t = vector_element (gsi, vec1, i_val, &vec1tmp);
1615 else
1616 t = vector_element (gsi, vec0, i_val, &vec0tmp);
1618 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE,
1619 true, GSI_SAME_STMT);
1621 else
1623 tree cond = NULL_TREE, v0_val;
1625 if (two_operand_p)
1627 cond = fold_build2 (BIT_AND_EXPR, mask_elt_type, i_val,
1628 build_int_cst (mask_elt_type, elements));
1629 cond = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE,
1630 true, GSI_SAME_STMT);
1633 i_val = fold_build2 (BIT_AND_EXPR, mask_elt_type, i_val,
1634 build_int_cst (mask_elt_type, elements - 1));
1635 i_val = force_gimple_operand_gsi (gsi, i_val, true, NULL_TREE,
1636 true, GSI_SAME_STMT);
1638 v0_val = vector_element (gsi, vec0, i_val, &vec0tmp);
1639 v0_val = force_gimple_operand_gsi (gsi, v0_val, true, NULL_TREE,
1640 true, GSI_SAME_STMT);
1642 if (two_operand_p)
1644 tree v1_val;
1646 v1_val = vector_element (gsi, vec1, i_val, &vec1tmp);
1647 v1_val = force_gimple_operand_gsi (gsi, v1_val, true, NULL_TREE,
1648 true, GSI_SAME_STMT);
1650 cond = fold_build2 (EQ_EXPR, boolean_type_node,
1651 cond, build_zero_cst (mask_elt_type));
1652 cond = fold_build3 (COND_EXPR, vect_elt_type,
1653 cond, v0_val, v1_val);
1654 t = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE,
1655 true, GSI_SAME_STMT);
1657 else
1658 t = v0_val;
1661 if (!CONSTANT_CLASS_P (t))
1662 constant_p = false;
1663 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, t);
1666 if (constant_p)
1667 constr = build_vector_from_ctor (vect_type, v);
1668 else
1669 constr = build_constructor (vect_type, v);
1670 gimple_assign_set_rhs_from_tree (gsi, constr);
1671 update_stmt (gsi_stmt (*gsi));
1674 /* If OP is a uniform vector return the element it is a splat from. */
1676 static tree
1677 ssa_uniform_vector_p (tree op)
1679 if (TREE_CODE (op) == VECTOR_CST
1680 || TREE_CODE (op) == VEC_DUPLICATE_EXPR
1681 || TREE_CODE (op) == CONSTRUCTOR)
1682 return uniform_vector_p (op);
1683 if (TREE_CODE (op) == SSA_NAME)
1685 gimple *def_stmt = SSA_NAME_DEF_STMT (op);
1686 if (gimple_assign_single_p (def_stmt))
1687 return uniform_vector_p (gimple_assign_rhs1 (def_stmt));
1689 return NULL_TREE;
1692 /* Return type in which CODE operation with optab OP can be
1693 computed. */
1695 static tree
1696 get_compute_type (enum tree_code code, optab op, tree type)
1698 /* For very wide vectors, try using a smaller vector mode. */
1699 tree compute_type = type;
1700 if (op
1701 && (!VECTOR_MODE_P (TYPE_MODE (type))
1702 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing))
1704 tree vector_compute_type
1705 = type_for_widest_vector_mode (TREE_TYPE (type), op);
1706 if (vector_compute_type != NULL_TREE
1707 && subparts_gt (compute_type, vector_compute_type)
1708 && maybe_ne (TYPE_VECTOR_SUBPARTS (vector_compute_type), 1U)
1709 && (optab_handler (op, TYPE_MODE (vector_compute_type))
1710 != CODE_FOR_nothing))
1711 compute_type = vector_compute_type;
1714 /* If we are breaking a BLKmode vector into smaller pieces,
1715 type_for_widest_vector_mode has already looked into the optab,
1716 so skip these checks. */
1717 if (compute_type == type)
1719 machine_mode compute_mode = TYPE_MODE (compute_type);
1720 if (VECTOR_MODE_P (compute_mode))
1722 if (op
1723 && (optab_handler (op, compute_mode) != CODE_FOR_nothing
1724 || optab_libfunc (op, compute_mode)))
1725 return compute_type;
1726 if (code == MULT_HIGHPART_EXPR
1727 && can_mult_highpart_p (compute_mode,
1728 TYPE_UNSIGNED (compute_type)))
1729 return compute_type;
1731 /* There is no operation in hardware, so fall back to scalars. */
1732 compute_type = TREE_TYPE (type);
1735 return compute_type;
1738 static tree
1739 do_cond (gimple_stmt_iterator *gsi, tree inner_type, tree a, tree b,
1740 tree bitpos, tree bitsize, enum tree_code code,
1741 tree type ATTRIBUTE_UNUSED)
1743 if (VECTOR_TYPE_P (TREE_TYPE (a)))
1744 a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
1745 if (VECTOR_TYPE_P (TREE_TYPE (b)))
1746 b = tree_vec_extract (gsi, inner_type, b, bitsize, bitpos);
1747 tree cond = gimple_assign_rhs1 (gsi_stmt (*gsi));
1748 return gimplify_build3 (gsi, code, inner_type, unshare_expr (cond), a, b);
1751 /* Expand a vector COND_EXPR to scalars, piecewise. */
1752 static void
1753 expand_vector_scalar_condition (gimple_stmt_iterator *gsi)
1755 gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
1756 tree lhs = gimple_assign_lhs (stmt);
1757 tree type = TREE_TYPE (lhs);
1758 tree compute_type = get_compute_type (COND_EXPR, mov_optab, type);
1759 machine_mode compute_mode = TYPE_MODE (compute_type);
1760 gcc_assert (compute_mode != BLKmode);
1761 tree rhs2 = gimple_assign_rhs2 (stmt);
1762 tree rhs3 = gimple_assign_rhs3 (stmt);
1763 tree new_rhs;
1765 /* If the compute mode is not a vector mode (hence we are not decomposing
1766 a BLKmode vector to smaller, hardware-supported vectors), we may want
1767 to expand the operations in parallel. */
1768 if (!VECTOR_MODE_P (compute_mode))
1769 new_rhs = expand_vector_parallel (gsi, do_cond, type, rhs2, rhs3,
1770 COND_EXPR);
1771 else
1772 new_rhs = expand_vector_piecewise (gsi, do_cond, type, compute_type,
1773 rhs2, rhs3, COND_EXPR, false);
1774 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (new_rhs)))
1775 new_rhs = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, TREE_TYPE (lhs),
1776 new_rhs);
1778 /* NOTE: We should avoid using gimple_assign_set_rhs_from_tree. One
1779 way to do it is change expand_vector_operation and its callees to
1780 return a tree_code, RHS1 and RHS2 instead of a tree. */
1781 gimple_assign_set_rhs_from_tree (gsi, new_rhs);
1782 update_stmt (gsi_stmt (*gsi));
1785 /* Callback for expand_vector_piecewise to do VEC_CONVERT ifn call
1786 lowering. If INNER_TYPE is not a vector type, this is a scalar
1787 fallback. */
1789 static tree
1790 do_vec_conversion (gimple_stmt_iterator *gsi, tree inner_type, tree a,
1791 tree decl, tree bitpos, tree bitsize,
1792 enum tree_code code, tree type)
1794 a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
1795 if (!VECTOR_TYPE_P (inner_type))
1796 return gimplify_build1 (gsi, code, TREE_TYPE (type), a);
1797 if (code == CALL_EXPR)
1799 gimple *g = gimple_build_call (decl, 1, a);
1800 tree lhs = make_ssa_name (TREE_TYPE (TREE_TYPE (decl)));
1801 gimple_call_set_lhs (g, lhs);
1802 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1803 return lhs;
1805 else
1807 tree outer_type = build_vector_type (TREE_TYPE (type),
1808 TYPE_VECTOR_SUBPARTS (inner_type));
1809 return gimplify_build1 (gsi, code, outer_type, a);
1813 /* Similarly, but for narrowing conversion. */
1815 static tree
1816 do_vec_narrow_conversion (gimple_stmt_iterator *gsi, tree inner_type, tree a,
1817 tree, tree bitpos, tree, enum tree_code code,
1818 tree type)
1820 tree itype = build_vector_type (TREE_TYPE (inner_type),
1821 exact_div (TYPE_VECTOR_SUBPARTS (inner_type),
1822 2));
1823 tree b = tree_vec_extract (gsi, itype, a, TYPE_SIZE (itype), bitpos);
1824 tree c = tree_vec_extract (gsi, itype, a, TYPE_SIZE (itype),
1825 int_const_binop (PLUS_EXPR, bitpos,
1826 TYPE_SIZE (itype)));
1827 tree outer_type = build_vector_type (TREE_TYPE (type),
1828 TYPE_VECTOR_SUBPARTS (inner_type));
1829 return gimplify_build2 (gsi, code, outer_type, b, c);
1832 /* Expand VEC_CONVERT ifn call. */
1834 static void
1835 expand_vector_conversion (gimple_stmt_iterator *gsi)
1837 gimple *stmt = gsi_stmt (*gsi);
1838 gimple *g;
1839 tree lhs = gimple_call_lhs (stmt);
1840 if (lhs == NULL_TREE)
1842 g = gimple_build_nop ();
1843 gsi_replace (gsi, g, false);
1844 return;
1846 tree arg = gimple_call_arg (stmt, 0);
1847 tree ret_type = TREE_TYPE (lhs);
1848 tree arg_type = TREE_TYPE (arg);
1849 tree new_rhs, compute_type = TREE_TYPE (arg_type);
1850 enum tree_code code = NOP_EXPR;
1851 enum tree_code code1 = ERROR_MARK;
1852 enum { NARROW, NONE, WIDEN } modifier = NONE;
1853 optab optab1 = unknown_optab;
1855 gcc_checking_assert (VECTOR_TYPE_P (ret_type) && VECTOR_TYPE_P (arg_type));
1856 if (INTEGRAL_TYPE_P (TREE_TYPE (ret_type))
1857 && SCALAR_FLOAT_TYPE_P (TREE_TYPE (arg_type)))
1858 code = FIX_TRUNC_EXPR;
1859 else if (INTEGRAL_TYPE_P (TREE_TYPE (arg_type))
1860 && SCALAR_FLOAT_TYPE_P (TREE_TYPE (ret_type)))
1861 code = FLOAT_EXPR;
1862 unsigned int ret_elt_bits = vector_element_bits (ret_type);
1863 unsigned int arg_elt_bits = vector_element_bits (arg_type);
1864 if (ret_elt_bits < arg_elt_bits)
1865 modifier = NARROW;
1866 else if (ret_elt_bits > arg_elt_bits)
1867 modifier = WIDEN;
1869 if (modifier == NONE && (code == FIX_TRUNC_EXPR || code == FLOAT_EXPR))
1871 if (supportable_convert_operation (code, ret_type, arg_type, &code1))
1873 g = gimple_build_assign (lhs, code1, arg);
1874 gsi_replace (gsi, g, false);
1875 return;
1877 /* Can't use get_compute_type here, as supportable_convert_operation
1878 doesn't necessarily use an optab and needs two arguments. */
1879 tree vec_compute_type
1880 = type_for_widest_vector_mode (TREE_TYPE (arg_type), mov_optab);
1881 if (vec_compute_type
1882 && VECTOR_MODE_P (TYPE_MODE (vec_compute_type))
1883 && subparts_gt (arg_type, vec_compute_type))
1885 unsigned HOST_WIDE_INT nelts
1886 = constant_lower_bound (TYPE_VECTOR_SUBPARTS (vec_compute_type));
1887 while (nelts > 1)
1889 tree ret1_type = build_vector_type (TREE_TYPE (ret_type), nelts);
1890 tree arg1_type = build_vector_type (TREE_TYPE (arg_type), nelts);
1891 if (supportable_convert_operation (code, ret1_type, arg1_type,
1892 &code1))
1894 new_rhs = expand_vector_piecewise (gsi, do_vec_conversion,
1895 ret_type, arg1_type, arg,
1896 NULL_TREE, code1, false);
1897 g = gimple_build_assign (lhs, new_rhs);
1898 gsi_replace (gsi, g, false);
1899 return;
1901 nelts = nelts / 2;
1905 else if (modifier == NARROW)
1907 switch (code)
1909 CASE_CONVERT:
1910 code1 = VEC_PACK_TRUNC_EXPR;
1911 optab1 = optab_for_tree_code (code1, arg_type, optab_default);
1912 break;
1913 case FIX_TRUNC_EXPR:
1914 code1 = VEC_PACK_FIX_TRUNC_EXPR;
1915 /* The signedness is determined from output operand. */
1916 optab1 = optab_for_tree_code (code1, ret_type, optab_default);
1917 break;
1918 case FLOAT_EXPR:
1919 code1 = VEC_PACK_FLOAT_EXPR;
1920 optab1 = optab_for_tree_code (code1, arg_type, optab_default);
1921 break;
1922 default:
1923 gcc_unreachable ();
1926 if (optab1)
1927 compute_type = get_compute_type (code1, optab1, arg_type);
1928 enum insn_code icode1;
1929 if (VECTOR_TYPE_P (compute_type)
1930 && ((icode1 = optab_handler (optab1, TYPE_MODE (compute_type)))
1931 != CODE_FOR_nothing)
1932 && VECTOR_MODE_P (insn_data[icode1].operand[0].mode))
1934 tree cretd_type
1935 = build_vector_type (TREE_TYPE (ret_type),
1936 TYPE_VECTOR_SUBPARTS (compute_type) * 2);
1937 if (insn_data[icode1].operand[0].mode == TYPE_MODE (cretd_type))
1939 if (compute_type == arg_type)
1941 new_rhs = gimplify_build2 (gsi, code1, cretd_type,
1942 arg, build_zero_cst (arg_type));
1943 new_rhs = tree_vec_extract (gsi, ret_type, new_rhs,
1944 TYPE_SIZE (ret_type),
1945 bitsize_int (0));
1946 g = gimple_build_assign (lhs, new_rhs);
1947 gsi_replace (gsi, g, false);
1948 return;
1950 tree dcompute_type
1951 = build_vector_type (TREE_TYPE (compute_type),
1952 TYPE_VECTOR_SUBPARTS (compute_type) * 2);
1953 if (TYPE_MAIN_VARIANT (dcompute_type)
1954 == TYPE_MAIN_VARIANT (arg_type))
1955 new_rhs = do_vec_narrow_conversion (gsi, dcompute_type, arg,
1956 NULL_TREE, bitsize_int (0),
1957 NULL_TREE, code1,
1958 ret_type);
1959 else
1960 new_rhs = expand_vector_piecewise (gsi,
1961 do_vec_narrow_conversion,
1962 arg_type, dcompute_type,
1963 arg, NULL_TREE, code1,
1964 false, ret_type);
1965 g = gimple_build_assign (lhs, new_rhs);
1966 gsi_replace (gsi, g, false);
1967 return;
1971 else if (modifier == WIDEN)
1973 enum tree_code code2 = ERROR_MARK;
1974 optab optab2 = unknown_optab;
1975 switch (code)
1977 CASE_CONVERT:
1978 code1 = VEC_UNPACK_LO_EXPR;
1979 code2 = VEC_UNPACK_HI_EXPR;
1980 break;
1981 case FIX_TRUNC_EXPR:
1982 code1 = VEC_UNPACK_FIX_TRUNC_LO_EXPR;
1983 code2 = VEC_UNPACK_FIX_TRUNC_HI_EXPR;
1984 break;
1985 case FLOAT_EXPR:
1986 code1 = VEC_UNPACK_FLOAT_LO_EXPR;
1987 code2 = VEC_UNPACK_FLOAT_HI_EXPR;
1988 break;
1989 default:
1990 gcc_unreachable ();
1992 if (BYTES_BIG_ENDIAN)
1993 std::swap (code1, code2);
1995 if (code == FIX_TRUNC_EXPR)
1997 /* The signedness is determined from output operand. */
1998 optab1 = optab_for_tree_code (code1, ret_type, optab_default);
1999 optab2 = optab_for_tree_code (code2, ret_type, optab_default);
2001 else
2003 optab1 = optab_for_tree_code (code1, arg_type, optab_default);
2004 optab2 = optab_for_tree_code (code2, arg_type, optab_default);
2007 if (optab1 && optab2)
2008 compute_type = get_compute_type (code1, optab1, arg_type);
2010 enum insn_code icode1, icode2;
2011 if (VECTOR_TYPE_P (compute_type)
2012 && ((icode1 = optab_handler (optab1, TYPE_MODE (compute_type)))
2013 != CODE_FOR_nothing)
2014 && ((icode2 = optab_handler (optab2, TYPE_MODE (compute_type)))
2015 != CODE_FOR_nothing)
2016 && VECTOR_MODE_P (insn_data[icode1].operand[0].mode)
2017 && (insn_data[icode1].operand[0].mode
2018 == insn_data[icode2].operand[0].mode))
2020 poly_uint64 nunits
2021 = exact_div (TYPE_VECTOR_SUBPARTS (compute_type), 2);
2022 tree cretd_type = build_vector_type (TREE_TYPE (ret_type), nunits);
2023 if (insn_data[icode1].operand[0].mode == TYPE_MODE (cretd_type))
2025 vec<constructor_elt, va_gc> *v;
2026 tree part_width = TYPE_SIZE (compute_type);
2027 tree index = bitsize_int (0);
2028 int nunits = nunits_for_known_piecewise_op (arg_type);
2029 int delta = tree_to_uhwi (part_width) / arg_elt_bits;
2030 int i;
2031 location_t loc = gimple_location (gsi_stmt (*gsi));
2033 if (compute_type != arg_type)
2035 if (!warning_suppressed_p (gsi_stmt (*gsi),
2036 OPT_Wvector_operation_performance))
2037 warning_at (loc, OPT_Wvector_operation_performance,
2038 "vector operation will be expanded piecewise");
2040 else
2042 nunits = 1;
2043 delta = 1;
2046 vec_alloc (v, (nunits + delta - 1) / delta * 2);
2047 bool constant_p = true;
2048 for (i = 0; i < nunits;
2049 i += delta, index = int_const_binop (PLUS_EXPR, index,
2050 part_width))
2052 tree a = arg;
2053 if (compute_type != arg_type)
2054 a = tree_vec_extract (gsi, compute_type, a, part_width,
2055 index);
2056 tree result = gimplify_build1 (gsi, code1, cretd_type, a);
2057 constructor_elt ce = { NULL_TREE, result };
2058 if (!CONSTANT_CLASS_P (ce.value))
2059 constant_p = false;
2060 v->quick_push (ce);
2061 ce.value = gimplify_build1 (gsi, code2, cretd_type, a);
2062 if (!CONSTANT_CLASS_P (ce.value))
2063 constant_p = false;
2064 v->quick_push (ce);
2067 if (constant_p)
2068 new_rhs = build_vector_from_ctor (ret_type, v);
2069 else
2070 new_rhs = build_constructor (ret_type, v);
2071 g = gimple_build_assign (lhs, new_rhs);
2072 gsi_replace (gsi, g, false);
2073 return;
2078 new_rhs = expand_vector_piecewise (gsi, do_vec_conversion, arg_type,
2079 TREE_TYPE (arg_type), arg,
2080 NULL_TREE, code, false, ret_type);
2081 g = gimple_build_assign (lhs, new_rhs);
2082 gsi_replace (gsi, g, false);
2085 /* Process one statement. If we identify a vector operation, expand it. */
2087 static void
2088 expand_vector_operations_1 (gimple_stmt_iterator *gsi,
2089 bitmap dce_ssa_names)
2091 tree lhs, rhs1, rhs2 = NULL, type, compute_type = NULL_TREE;
2092 enum tree_code code;
2093 optab op = unknown_optab;
2094 enum gimple_rhs_class rhs_class;
2095 tree new_rhs;
2097 /* Only consider code == GIMPLE_ASSIGN. */
2098 gassign *stmt = dyn_cast <gassign *> (gsi_stmt (*gsi));
2099 if (!stmt)
2101 if (gimple_call_internal_p (gsi_stmt (*gsi), IFN_VEC_CONVERT))
2102 expand_vector_conversion (gsi);
2103 return;
2106 code = gimple_assign_rhs_code (stmt);
2107 rhs_class = get_gimple_rhs_class (code);
2108 lhs = gimple_assign_lhs (stmt);
2110 if (code == VEC_PERM_EXPR)
2112 lower_vec_perm (gsi);
2113 return;
2116 if (code == VEC_COND_EXPR)
2118 expand_vector_condition (gsi, dce_ssa_names);
2119 return;
2122 if (code == COND_EXPR
2123 && TREE_CODE (TREE_TYPE (gimple_assign_lhs (stmt))) == VECTOR_TYPE
2124 && TYPE_MODE (TREE_TYPE (gimple_assign_lhs (stmt))) == BLKmode)
2126 expand_vector_scalar_condition (gsi);
2127 return;
2130 if (code == CONSTRUCTOR
2131 && TREE_CODE (lhs) == SSA_NAME
2132 && VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (lhs)))
2133 && !gimple_clobber_p (stmt)
2134 && optimize)
2136 optimize_vector_constructor (gsi);
2137 return;
2140 if (rhs_class != GIMPLE_UNARY_RHS && rhs_class != GIMPLE_BINARY_RHS)
2141 return;
2143 rhs1 = gimple_assign_rhs1 (stmt);
2144 if (rhs_class == GIMPLE_BINARY_RHS)
2145 rhs2 = gimple_assign_rhs2 (stmt);
2147 type = TREE_TYPE (lhs);
2148 if (!VECTOR_TYPE_P (type)
2149 || !VECTOR_TYPE_P (TREE_TYPE (rhs1)))
2150 return;
2152 /* A scalar operation pretending to be a vector one. */
2153 if (VECTOR_BOOLEAN_TYPE_P (type)
2154 && !VECTOR_MODE_P (TYPE_MODE (type))
2155 && TYPE_MODE (type) != BLKmode
2156 && (TREE_CODE_CLASS (gimple_assign_rhs_code (stmt)) != tcc_comparison
2157 || (VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (rhs1))
2158 && !VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (rhs1)))
2159 && TYPE_MODE (TREE_TYPE (rhs1)) != BLKmode)))
2160 return;
2162 /* If the vector operation is operating on all same vector elements
2163 implement it with a scalar operation and a splat if the target
2164 supports the scalar operation. */
2165 tree srhs1, srhs2 = NULL_TREE;
2166 if ((srhs1 = ssa_uniform_vector_p (rhs1)) != NULL_TREE
2167 && (rhs2 == NULL_TREE
2168 || (! VECTOR_TYPE_P (TREE_TYPE (rhs2))
2169 && (srhs2 = rhs2))
2170 || (srhs2 = ssa_uniform_vector_p (rhs2)) != NULL_TREE)
2171 /* As we query direct optabs restrict to non-convert operations. */
2172 && TYPE_MODE (TREE_TYPE (type)) == TYPE_MODE (TREE_TYPE (srhs1)))
2174 op = optab_for_tree_code (code, TREE_TYPE (type), optab_scalar);
2175 if (op >= FIRST_NORM_OPTAB && op <= LAST_NORM_OPTAB
2176 && optab_handler (op, TYPE_MODE (TREE_TYPE (type))) != CODE_FOR_nothing)
2178 tree stype = TREE_TYPE (TREE_TYPE (lhs));
2179 tree slhs = (rhs2 != NULL_TREE)
2180 ? gimplify_build2 (gsi, code, stype, srhs1, srhs2)
2181 : gimplify_build1 (gsi, code, stype, srhs1);
2182 gimple_assign_set_rhs_from_tree (gsi,
2183 build_vector_from_val (type, slhs));
2184 update_stmt (stmt);
2185 return;
2189 if (CONVERT_EXPR_CODE_P (code)
2190 || code == FLOAT_EXPR
2191 || code == FIX_TRUNC_EXPR
2192 || code == VIEW_CONVERT_EXPR)
2193 return;
2195 /* The signedness is determined from input argument. */
2196 if (code == VEC_UNPACK_FLOAT_HI_EXPR
2197 || code == VEC_UNPACK_FLOAT_LO_EXPR
2198 || code == VEC_PACK_FLOAT_EXPR)
2200 /* We do not know how to scalarize those. */
2201 return;
2204 /* For widening/narrowing vector operations, the relevant type is of the
2205 arguments, not the widened result. VEC_UNPACK_FLOAT_*_EXPR is
2206 calculated in the same way above. */
2207 if (code == WIDEN_SUM_EXPR
2208 || code == VEC_WIDEN_MULT_HI_EXPR
2209 || code == VEC_WIDEN_MULT_LO_EXPR
2210 || code == VEC_WIDEN_MULT_EVEN_EXPR
2211 || code == VEC_WIDEN_MULT_ODD_EXPR
2212 || code == VEC_UNPACK_HI_EXPR
2213 || code == VEC_UNPACK_LO_EXPR
2214 || code == VEC_UNPACK_FIX_TRUNC_HI_EXPR
2215 || code == VEC_UNPACK_FIX_TRUNC_LO_EXPR
2216 || code == VEC_PACK_TRUNC_EXPR
2217 || code == VEC_PACK_SAT_EXPR
2218 || code == VEC_PACK_FIX_TRUNC_EXPR
2219 || code == VEC_WIDEN_LSHIFT_HI_EXPR
2220 || code == VEC_WIDEN_LSHIFT_LO_EXPR)
2222 /* We do not know how to scalarize those. */
2223 return;
2226 /* Choose between vector shift/rotate by vector and vector shift/rotate by
2227 scalar */
2228 if (code == LSHIFT_EXPR
2229 || code == RSHIFT_EXPR
2230 || code == LROTATE_EXPR
2231 || code == RROTATE_EXPR)
2233 optab opv;
2235 /* Check whether we have vector <op> {x,x,x,x} where x
2236 could be a scalar variable or a constant. Transform
2237 vector <op> {x,x,x,x} ==> vector <op> scalar. */
2238 if (VECTOR_INTEGER_TYPE_P (TREE_TYPE (rhs2)))
2240 tree first;
2242 if ((first = ssa_uniform_vector_p (rhs2)) != NULL_TREE)
2244 gimple_assign_set_rhs2 (stmt, first);
2245 update_stmt (stmt);
2246 rhs2 = first;
2250 opv = optab_for_tree_code (code, type, optab_vector);
2251 if (VECTOR_INTEGER_TYPE_P (TREE_TYPE (rhs2)))
2252 op = opv;
2253 else
2255 op = optab_for_tree_code (code, type, optab_scalar);
2257 compute_type = get_compute_type (code, op, type);
2258 if (compute_type == type)
2259 return;
2260 /* The rtl expander will expand vector/scalar as vector/vector
2261 if necessary. Pick one with wider vector type. */
2262 tree compute_vtype = get_compute_type (code, opv, type);
2263 if (subparts_gt (compute_vtype, compute_type))
2265 compute_type = compute_vtype;
2266 op = opv;
2270 if (code == LROTATE_EXPR || code == RROTATE_EXPR)
2272 if (compute_type == NULL_TREE)
2273 compute_type = get_compute_type (code, op, type);
2274 if (compute_type == type)
2275 return;
2276 /* Before splitting vector rotates into scalar rotates,
2277 see if we can't use vector shifts and BIT_IOR_EXPR
2278 instead. For vector by vector rotates we'd also
2279 need to check BIT_AND_EXPR and NEGATE_EXPR, punt there
2280 for now, fold doesn't seem to create such rotates anyway. */
2281 if (compute_type == TREE_TYPE (type)
2282 && !VECTOR_INTEGER_TYPE_P (TREE_TYPE (rhs2)))
2284 optab oplv = vashl_optab, opl = ashl_optab;
2285 optab oprv = vlshr_optab, opr = lshr_optab, opo = ior_optab;
2286 tree compute_lvtype = get_compute_type (LSHIFT_EXPR, oplv, type);
2287 tree compute_rvtype = get_compute_type (RSHIFT_EXPR, oprv, type);
2288 tree compute_otype = get_compute_type (BIT_IOR_EXPR, opo, type);
2289 tree compute_ltype = get_compute_type (LSHIFT_EXPR, opl, type);
2290 tree compute_rtype = get_compute_type (RSHIFT_EXPR, opr, type);
2291 /* The rtl expander will expand vector/scalar as vector/vector
2292 if necessary. Pick one with wider vector type. */
2293 if (subparts_gt (compute_lvtype, compute_ltype))
2295 compute_ltype = compute_lvtype;
2296 opl = oplv;
2298 if (subparts_gt (compute_rvtype, compute_rtype))
2300 compute_rtype = compute_rvtype;
2301 opr = oprv;
2303 /* Pick the narrowest type from LSHIFT_EXPR, RSHIFT_EXPR and
2304 BIT_IOR_EXPR. */
2305 compute_type = compute_ltype;
2306 if (subparts_gt (compute_type, compute_rtype))
2307 compute_type = compute_rtype;
2308 if (subparts_gt (compute_type, compute_otype))
2309 compute_type = compute_otype;
2310 /* Verify all 3 operations can be performed in that type. */
2311 if (compute_type != TREE_TYPE (type))
2313 if (optab_handler (opl, TYPE_MODE (compute_type))
2314 == CODE_FOR_nothing
2315 || optab_handler (opr, TYPE_MODE (compute_type))
2316 == CODE_FOR_nothing
2317 || optab_handler (opo, TYPE_MODE (compute_type))
2318 == CODE_FOR_nothing)
2319 compute_type = TREE_TYPE (type);
2324 else
2325 op = optab_for_tree_code (code, type, optab_default);
2327 /* Optabs will try converting a negation into a subtraction, so
2328 look for it as well. TODO: negation of floating-point vectors
2329 might be turned into an exclusive OR toggling the sign bit. */
2330 if (op == unknown_optab
2331 && code == NEGATE_EXPR
2332 && INTEGRAL_TYPE_P (TREE_TYPE (type)))
2333 op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
2335 if (compute_type == NULL_TREE)
2336 compute_type = get_compute_type (code, op, type);
2337 if (compute_type == type)
2338 return;
2340 new_rhs = expand_vector_operation (gsi, type, compute_type, stmt, code,
2341 dce_ssa_names);
2343 /* Leave expression untouched for later expansion. */
2344 if (new_rhs == NULL_TREE)
2345 return;
2347 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (new_rhs)))
2348 new_rhs = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, TREE_TYPE (lhs),
2349 new_rhs);
2351 /* NOTE: We should avoid using gimple_assign_set_rhs_from_tree. One
2352 way to do it is change expand_vector_operation and its callees to
2353 return a tree_code, RHS1 and RHS2 instead of a tree. */
2354 gimple_assign_set_rhs_from_tree (gsi, new_rhs);
2355 update_stmt (gsi_stmt (*gsi));
2358 /* Use this to lower vector operations introduced by the vectorizer,
2359 if it may need the bit-twiddling tricks implemented in this file. */
2361 static unsigned int
2362 expand_vector_operations (void)
2364 gimple_stmt_iterator gsi;
2365 basic_block bb;
2366 bool cfg_changed = false;
2368 auto_bitmap dce_ssa_names;
2370 FOR_EACH_BB_FN (bb, cfun)
2372 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
2374 expand_vector_operations_1 (&gsi, dce_ssa_names);
2375 /* ??? If we do not cleanup EH then we will ICE in
2376 verification. But in reality we have created wrong-code
2377 as we did not properly transition EH info and edges to
2378 the piecewise computations. */
2379 if (maybe_clean_eh_stmt (gsi_stmt (gsi))
2380 && gimple_purge_dead_eh_edges (bb))
2381 cfg_changed = true;
2382 /* If a .LOOP_DIST_ALIAS call prevailed loops got elided
2383 before vectorization got a chance to get at them. Simply
2384 fold as if loop distribution wasn't performed. */
2385 if (gimple_call_internal_p (gsi_stmt (gsi), IFN_LOOP_DIST_ALIAS))
2387 fold_loop_internal_call (gsi_stmt (gsi), boolean_false_node);
2388 cfg_changed = true;
2393 simple_dce_from_worklist (dce_ssa_names);
2395 return cfg_changed ? TODO_cleanup_cfg : 0;
2398 namespace {
2400 const pass_data pass_data_lower_vector =
2402 GIMPLE_PASS, /* type */
2403 "veclower", /* name */
2404 OPTGROUP_VEC, /* optinfo_flags */
2405 TV_NONE, /* tv_id */
2406 PROP_cfg, /* properties_required */
2407 PROP_gimple_lvec, /* properties_provided */
2408 0, /* properties_destroyed */
2409 0, /* todo_flags_start */
2410 TODO_update_ssa, /* todo_flags_finish */
2413 class pass_lower_vector : public gimple_opt_pass
2415 public:
2416 pass_lower_vector (gcc::context *ctxt)
2417 : gimple_opt_pass (pass_data_lower_vector, ctxt)
2420 /* opt_pass methods: */
2421 bool gate (function *fun) final override
2423 return !(fun->curr_properties & PROP_gimple_lvec);
2426 unsigned int execute (function *) final override
2428 return expand_vector_operations ();
2431 }; // class pass_lower_vector
2433 } // anon namespace
2435 gimple_opt_pass *
2436 make_pass_lower_vector (gcc::context *ctxt)
2438 return new pass_lower_vector (ctxt);
2441 namespace {
2443 const pass_data pass_data_lower_vector_ssa =
2445 GIMPLE_PASS, /* type */
2446 "veclower2", /* name */
2447 OPTGROUP_VEC, /* optinfo_flags */
2448 TV_NONE, /* tv_id */
2449 PROP_cfg, /* properties_required */
2450 PROP_gimple_lvec, /* properties_provided */
2451 0, /* properties_destroyed */
2452 0, /* todo_flags_start */
2453 ( TODO_update_ssa
2454 | TODO_cleanup_cfg ), /* todo_flags_finish */
2457 class pass_lower_vector_ssa : public gimple_opt_pass
2459 public:
2460 pass_lower_vector_ssa (gcc::context *ctxt)
2461 : gimple_opt_pass (pass_data_lower_vector_ssa, ctxt)
2464 /* opt_pass methods: */
2465 opt_pass * clone () final override
2467 return new pass_lower_vector_ssa (m_ctxt);
2469 unsigned int execute (function *) final override
2471 return expand_vector_operations ();
2474 }; // class pass_lower_vector_ssa
2476 } // anon namespace
2478 gimple_opt_pass *
2479 make_pass_lower_vector_ssa (gcc::context *ctxt)
2481 return new pass_lower_vector_ssa (ctxt);
2484 #include "gt-tree-vect-generic.h"