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