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 : 11229 : gimplify_build3 (gimple_stmt_iterator *gsi, enum tree_code code,
56 : : tree type, tree a, tree b, tree c)
57 : : {
58 : 11229 : location_t loc = gimple_location (gsi_stmt (*gsi));
59 : 11229 : 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 : 17811 : gimplify_build2 (gimple_stmt_iterator *gsi, enum tree_code code,
67 : : tree type, tree a, tree b)
68 : : {
69 : 17811 : location_t loc = gimple_location (gsi_stmt (*gsi));
70 : 17811 : 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 : 18711 : gimplify_build1 (gimple_stmt_iterator *gsi, enum tree_code code, tree type,
78 : : tree a)
79 : : {
80 : 18711 : location_t loc = gimple_location (gsi_stmt (*gsi));
81 : 18711 : 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 : 109918 : nunits_for_known_piecewise_op (const_tree type)
91 : : {
92 : 109024 : 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 : 66785 : 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 : 66785 : gimple_match_op opr;
144 : 66785 : opr.set_op (BIT_FIELD_REF, type, t, bitsize, bitpos);
145 : 66785 : opr.resimplify (NULL, follow_all_ssa_edges);
146 : 66785 : gimple_seq stmts = NULL;
147 : 66785 : tree res = maybe_push_res_to_seq (&opr, &stmts);
148 : 66785 : 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 : 66721 : gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
159 : 66721 : 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 : 10295 : 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 : 10295 : if (VECTOR_TYPE_P (TREE_TYPE (a)))
185 : 10295 : a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
186 : 10295 : if (VECTOR_TYPE_P (TREE_TYPE (b)))
187 : 9985 : b = tree_vec_extract (gsi, inner_type, b, bitsize, bitpos);
188 : 10295 : 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 : 5629 : 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 : 5629 : tree stype = TREE_TYPE (type);
202 : 5629 : tree cst_false = build_zero_cst (stype);
203 : 5629 : tree cst_true = build_all_ones_cst (stype);
204 : 5629 : tree cmp;
205 : :
206 : 5629 : a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
207 : 5629 : b = tree_vec_extract (gsi, inner_type, b, bitsize, bitpos);
208 : :
209 : 5629 : cmp = build2 (code, boolean_type_node, a, b);
210 : 5629 : 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 : 2826 : 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 : 2826 : vec<constructor_elt, va_gc> *v;
292 : 2826 : tree part_width = TYPE_SIZE (inner_type);
293 : 2826 : tree index = bitsize_int (0);
294 : 2826 : int nunits = nunits_for_known_piecewise_op (type);
295 : 2826 : int delta = (VECTOR_TYPE_P (inner_type)
296 : 3720 : ? nunits_for_known_piecewise_op (inner_type) : 1);
297 : 2826 : int i;
298 : 2826 : location_t loc = gimple_location (gsi_stmt (*gsi));
299 : :
300 : 2826 : if (nunits == 1
301 : 2826 : || 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 : 2496 : else if (ret_type || !parallel_p)
307 : 2444 : 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 : 2826 : if (!ret_type)
314 : 2739 : ret_type = type;
315 : 2826 : vec_alloc (v, (nunits + delta - 1) / delta);
316 : 2826 : bool constant_p = true;
317 : 37102 : for (i = 0; i < nunits;
318 : 34276 : i += delta, index = int_const_binop (PLUS_EXPR, index, part_width))
319 : : {
320 : 34276 : tree result = f (gsi, inner_type, a, b, index, part_width, code,
321 : : ret_type);
322 : 34276 : if (!CONSTANT_CLASS_P (result))
323 : 33844 : constant_p = false;
324 : 34276 : constructor_elt ce = {NULL_TREE, result};
325 : 34276 : v->quick_push (ce);
326 : : }
327 : :
328 : 2826 : if (constant_p)
329 : 2 : return build_vector_from_ctor (ret_type, v);
330 : : else
331 : 2824 : 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 : 23695 : expand_vector_comparison (gimple_stmt_iterator *gsi, tree type, tree op0,
408 : : tree op1, enum tree_code code)
409 : : {
410 : 23695 : if (expand_vec_cmp_expr_p (TREE_TYPE (op0), type, code))
411 : : return NULL_TREE;
412 : :
413 : 584 : tree t;
414 : 584 : if (VECTOR_BOOLEAN_TYPE_P (type)
415 : 584 : && SCALAR_INT_MODE_P (TYPE_MODE (type))
416 : 710 : && 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 : 584 : t = expand_vector_piecewise (gsi, do_compare, type,
453 : 584 : 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 : :
501 : : /* Verify that the target has optabs of VECTYPE to perform all the steps
502 : : needed by the multiplication-by-immediate synthesis algorithm described by
503 : : ALG and VAR. Return true iff the target supports all the steps. */
504 : : static bool
505 : 0 : target_supports_mult_synth_alg (struct algorithm *alg, mult_variant var,
506 : : tree vectype)
507 : : {
508 : 0 : if (alg->op[0] != alg_zero && alg->op[0] != alg_m)
509 : : return false;
510 : :
511 : 0 : bool plus_supported_p = target_supports_op_p (vectype, PLUS_EXPR,
512 : : optab_vector);
513 : 0 : bool minus_supported_p = target_supports_op_p (vectype, MINUS_EXPR,
514 : : optab_vector);
515 : 0 : bool negate_supported_p = target_supports_op_p (vectype, NEGATE_EXPR,
516 : : optab_vector);
517 : :
518 : 0 : if ((var == negate_variant && !negate_supported_p)
519 : 0 : || (var == add_variant && !plus_supported_p))
520 : : return false;
521 : :
522 : 0 : bool lshift_supported_p
523 : 0 : = (target_supports_op_p (vectype, LSHIFT_EXPR, optab_scalar)
524 : 0 : || target_supports_op_p (vectype, LSHIFT_EXPR, optab_vector));
525 : :
526 : 0 : for (int i = 1; i < alg->ops; i++)
527 : : {
528 : 0 : switch (alg->op[i])
529 : : {
530 : 0 : case alg_shift:
531 : 0 : if (!lshift_supported_p)
532 : : return false;
533 : : break;
534 : 0 : case alg_add_t_m2:
535 : 0 : case alg_add_t2_m:
536 : 0 : case alg_add_factor:
537 : 0 : if (!plus_supported_p || !lshift_supported_p)
538 : : return false;
539 : : break;
540 : 0 : case alg_sub_t_m2:
541 : 0 : case alg_sub_t2_m:
542 : 0 : case alg_sub_factor:
543 : 0 : if (!minus_supported_p || !lshift_supported_p)
544 : : return false;
545 : : break;
546 : : case alg_unknown:
547 : : case alg_m:
548 : : case alg_zero:
549 : : case alg_impossible:
550 : : return false;
551 : 0 : default:
552 : 0 : gcc_unreachable ();
553 : : }
554 : : }
555 : :
556 : : return true;
557 : : }
558 : : /* For integer multiplications with exact power of 2, use left shifts.
559 : : In constant is a uniform vector, then check if it can be synthesized with
560 : : shifts and adds/subs. Use scalar multiplication cost to compare with the
561 : : synthesized vector code as done in expmed.cc. */
562 : : static tree
563 : 0 : expand_vector_mult (gimple_stmt_iterator *gsi, tree type, tree op0,
564 : : tree op1)
565 : : {
566 : 0 : if (!CONSTANT_CLASS_P (op1))
567 : : return NULL_TREE;
568 : 0 : unsigned int nunits = nunits_for_known_piecewise_op (type);
569 : 0 : int *shifts = XALLOCAVEC (int, nunits);
570 : :
571 : 0 : bool perfect_pow2_p = true;
572 : 0 : bool uniform_const_p = true;
573 : 0 : unsigned HOST_WIDE_INT first_cst, const_elt;
574 : 0 : for (unsigned int i = 0; i < nunits; i++)
575 : : {
576 : 0 : tree cst = VECTOR_CST_ELT (op1, i);
577 : 0 : if (TREE_CODE (cst) != INTEGER_CST || tree_int_cst_sgn (cst) <= 0)
578 : 0 : return NULL_TREE;
579 : :
580 : 0 : perfect_pow2_p &= integer_pow2p (cst);
581 : :
582 : 0 : if (uniform_const_p && tree_fits_uhwi_p (cst))
583 : : {
584 : 0 : const_elt = TREE_INT_CST_LOW (cst);
585 : 0 : if (i == 0)
586 : : first_cst = const_elt;
587 : 0 : else if (first_cst != const_elt)
588 : 0 : uniform_const_p = false;
589 : : }
590 : : else
591 : : uniform_const_p = false;
592 : :
593 : 0 : shifts[i] = tree_log2 (cst);
594 : : }
595 : 0 : if (perfect_pow2_p)
596 : 0 : return add_shift (gsi, type, op0, shifts, LSHIFT_EXPR);
597 : 0 : else if (uniform_const_p)
598 : : {
599 : 0 : tree scalar_type = type;
600 : 0 : gcc_assert (TREE_CODE (type) == VECTOR_TYPE);
601 : 0 : scalar_type = TREE_TYPE (type);
602 : :
603 : : // handle signed ints
604 : 0 : bool cast_to_unsigned_p = !TYPE_OVERFLOW_WRAPS (scalar_type);
605 : 0 : tree multtype = cast_to_unsigned_p
606 : 0 : ? unsigned_type_for (scalar_type) : scalar_type;
607 : 0 : tree vectype = cast_to_unsigned_p ? unsigned_type_for (type) : type;
608 : :
609 : : // estimate the scalar MULT cost by generating dummy rtx insns
610 : 0 : machine_mode mode = TYPE_MODE (multtype);
611 : 0 : rtx rop0 = gen_rtx_REG (mode, 0);
612 : 0 : rtx rop1 = gen_rtx_REG (mode, 1);
613 : 0 : rtx mult_rtx = gen_rtx_MULT (mode, rop0, rop1);
614 : 0 : int max_cost = nunits * set_src_cost (mult_rtx, mode, true);
615 : :
616 : 0 : struct algorithm alg;
617 : 0 : mult_variant variant;
618 : :
619 : 0 : bool possible = choose_mult_variant (TYPE_MODE (vectype), const_elt, &alg,
620 : : &variant, max_cost);
621 : 0 : if (!possible || !target_supports_mult_synth_alg (&alg, variant, vectype))
622 : 0 : return NULL_TREE;
623 : 0 : if (cast_to_unsigned_p)
624 : : {
625 : 0 : tree tmp_op = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, vectype, op0);
626 : 0 : op0 = tmp_op;
627 : : }
628 : 0 : tree accumulator, tmp_var;
629 : 0 : if (alg.op[0] == alg_zero)
630 : 0 : accumulator = build_int_cst (vectype, 0);
631 : : else
632 : : accumulator = op0;
633 : :
634 : 0 : for (int i = 1; i < alg.ops; i++)
635 : : {
636 : 0 : for (unsigned int j = 0; j < nunits; j++)
637 : 0 : shifts[j] = alg.log[i];
638 : :
639 : 0 : switch (alg.op[i])
640 : : {
641 : 0 : case alg_shift:
642 : 0 : accumulator = add_shift (gsi, vectype, accumulator, shifts,
643 : : LSHIFT_EXPR);
644 : 0 : break;
645 : 0 : case alg_add_t_m2:
646 : 0 : tmp_var = add_shift (gsi, vectype, op0, shifts, LSHIFT_EXPR);
647 : 0 : accumulator = gimplify_build2 (gsi, PLUS_EXPR, vectype, tmp_var,
648 : : accumulator);
649 : 0 : break;
650 : 0 : case alg_sub_t_m2:
651 : 0 : tmp_var = add_shift (gsi, vectype, op0, shifts, LSHIFT_EXPR);
652 : 0 : accumulator = gimplify_build2 (gsi, MINUS_EXPR, vectype,
653 : : accumulator, tmp_var);
654 : 0 : break;
655 : 0 : case alg_add_t2_m:
656 : 0 : tmp_var = add_shift (gsi, vectype, accumulator, shifts,
657 : : LSHIFT_EXPR);
658 : 0 : accumulator = gimplify_build2 (gsi, PLUS_EXPR, vectype, tmp_var,
659 : : op0);
660 : 0 : break;
661 : 0 : case alg_sub_t2_m:
662 : 0 : tmp_var = add_shift (gsi, vectype, accumulator, shifts,
663 : : LSHIFT_EXPR);
664 : 0 : accumulator = gimplify_build2 (gsi, MINUS_EXPR, vectype,
665 : : tmp_var, op0);
666 : 0 : break;
667 : 0 : case alg_add_factor:
668 : 0 : tmp_var = add_shift (gsi, vectype, accumulator, shifts,
669 : : LSHIFT_EXPR);
670 : 0 : accumulator = gimplify_build2 (gsi, PLUS_EXPR, vectype,
671 : : accumulator, tmp_var);
672 : 0 : break;
673 : 0 : case alg_sub_factor:
674 : 0 : tmp_var = add_shift (gsi, vectype, accumulator, shifts,
675 : : LSHIFT_EXPR);
676 : 0 : accumulator = gimplify_build2 (gsi, MINUS_EXPR, vectype,
677 : : accumulator, tmp_var);
678 : 0 : break;
679 : 0 : default:
680 : 0 : gcc_unreachable ();
681 : : }
682 : : }
683 : 0 : if (variant == negate_variant)
684 : 0 : accumulator = gimplify_build1 (gsi, NEGATE_EXPR, vectype, accumulator);
685 : 0 : else if (variant == add_variant)
686 : 0 : accumulator = gimplify_build2 (gsi, PLUS_EXPR, vectype, accumulator,
687 : : op0);
688 : :
689 : 0 : if (cast_to_unsigned_p)
690 : 0 : accumulator = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, vectype,
691 : : accumulator);
692 : 0 : return accumulator;
693 : : }
694 : : return NULL_TREE;
695 : : }
696 : : /* Try to expand integer vector division by constant using
697 : : widening multiply, shifts and additions. */
698 : : static tree
699 : 448 : expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, tree op0,
700 : : tree op1, enum tree_code code)
701 : : {
702 : 448 : bool use_pow2 = true;
703 : 448 : bool has_vector_shift = true;
704 : 448 : bool use_abs_op1 = false;
705 : 448 : int mode = -1, this_mode;
706 : 448 : int pre_shift = -1, post_shift;
707 : 448 : unsigned int nunits = nunits_for_known_piecewise_op (type);
708 : 448 : int *shifts = XALLOCAVEC (int, nunits * 4);
709 : 448 : int *pre_shifts = shifts + nunits;
710 : 448 : int *post_shifts = pre_shifts + nunits;
711 : 448 : int *shift_temps = post_shifts + nunits;
712 : 448 : unsigned HOST_WIDE_INT *mulc = XALLOCAVEC (unsigned HOST_WIDE_INT, nunits);
713 : 448 : int prec = TYPE_PRECISION (TREE_TYPE (type));
714 : 448 : unsigned int i;
715 : 448 : signop sign_p = TYPE_SIGN (TREE_TYPE (type));
716 : 448 : unsigned HOST_WIDE_INT mask = GET_MODE_MASK (TYPE_MODE (TREE_TYPE (type)));
717 : 448 : tree cur_op, mulcst, tem;
718 : 448 : optab op;
719 : :
720 : 448 : if (prec > HOST_BITS_PER_WIDE_INT)
721 : : return NULL_TREE;
722 : :
723 : 447 : op = optab_for_tree_code (RSHIFT_EXPR, type, optab_vector);
724 : 447 : if (op == unknown_optab
725 : 447 : || !can_implement_p (op, TYPE_MODE (type)))
726 : : has_vector_shift = false;
727 : :
728 : : /* Analysis phase. Determine if all op1 elements are either power
729 : : of two and it is possible to expand it using shifts (or for remainder
730 : : using masking). Additionally compute the multiplicative constants
731 : : and pre and post shifts if the division is to be expanded using
732 : : widening or high part multiplication plus shifts. */
733 : 3189 : for (i = 0; i < nunits; i++)
734 : : {
735 : 2752 : tree cst = VECTOR_CST_ELT (op1, i);
736 : 2752 : unsigned HOST_WIDE_INT ml;
737 : :
738 : 2752 : if (TREE_CODE (cst) != INTEGER_CST || integer_zerop (cst))
739 : 10 : return NULL_TREE;
740 : 2744 : pre_shifts[i] = 0;
741 : 2744 : post_shifts[i] = 0;
742 : 2744 : mulc[i] = 0;
743 : 2744 : if (use_pow2
744 : 2744 : && (!integer_pow2p (cst) || tree_int_cst_sgn (cst) != 1))
745 : : use_pow2 = false;
746 : 2457 : if (use_pow2)
747 : : {
748 : 824 : shifts[i] = tree_log2 (cst);
749 : 824 : if (shifts[i] != shifts[0]
750 : 192 : && code == TRUNC_DIV_EXPR
751 : 192 : && !has_vector_shift)
752 : 1952 : use_pow2 = false;
753 : : }
754 : 2744 : if (mode == -2)
755 : 1000 : continue;
756 : 1861 : if (sign_p == UNSIGNED)
757 : : {
758 : 814 : unsigned HOST_WIDE_INT mh;
759 : 814 : unsigned HOST_WIDE_INT d = TREE_INT_CST_LOW (cst) & mask;
760 : :
761 : 814 : if (d >= (HOST_WIDE_INT_1U << (prec - 1)))
762 : : /* FIXME: Can transform this into op0 >= op1 ? 1 : 0. */
763 : : return NULL_TREE;
764 : :
765 : 812 : if (d <= 1)
766 : : {
767 : 32 : mode = -2;
768 : 32 : continue;
769 : : }
770 : :
771 : : /* Find a suitable multiplier and right shift count instead of
772 : : directly dividing by D. */
773 : 780 : mh = choose_multiplier (d, prec, prec, &ml, &post_shift);
774 : :
775 : : /* If the suggested multiplier is more than PREC bits, we can
776 : : do better for even divisors, using an initial right shift. */
777 : 780 : if ((mh != 0 && (d & 1) == 0)
778 : 638 : || (!has_vector_shift && pre_shift != -1))
779 : : {
780 : 142 : if (has_vector_shift)
781 : 0 : pre_shift = ctz_or_zero (d);
782 : 174 : else if (pre_shift == -1)
783 : : {
784 : : unsigned int j;
785 : 518 : for (j = 0; j < nunits; j++)
786 : : {
787 : 440 : tree cst2 = VECTOR_CST_ELT (op1, j);
788 : 440 : unsigned HOST_WIDE_INT d2;
789 : 440 : int this_pre_shift;
790 : :
791 : 440 : if (!tree_fits_uhwi_p (cst2))
792 : : return NULL_TREE;
793 : 440 : d2 = tree_to_uhwi (cst2) & mask;
794 : 440 : if (d2 == 0)
795 : : return NULL_TREE;
796 : 440 : this_pre_shift = floor_log2 (d2 & -d2);
797 : 440 : if (pre_shift == -1 || this_pre_shift < pre_shift)
798 : 78 : pre_shift = this_pre_shift;
799 : : }
800 : 78 : if (i != 0 && pre_shift != 0)
801 : : {
802 : : /* Restart. */
803 : 0 : i = -1U;
804 : 0 : mode = -1;
805 : 0 : continue;
806 : : }
807 : : }
808 : 174 : if (pre_shift != 0)
809 : : {
810 : 174 : if ((d >> pre_shift) <= 1)
811 : : {
812 : 46 : mode = -2;
813 : 46 : continue;
814 : : }
815 : 128 : mh = choose_multiplier (d >> pre_shift, prec,
816 : : prec - pre_shift,
817 : : &ml, &post_shift);
818 : 128 : gcc_assert (!mh);
819 : 128 : pre_shifts[i] = pre_shift;
820 : : }
821 : : }
822 : 734 : if (!mh)
823 : : this_mode = 0;
824 : : else
825 : 192 : this_mode = 1;
826 : : }
827 : : else
828 : : {
829 : 1047 : HOST_WIDE_INT d = TREE_INT_CST_LOW (cst);
830 : 1047 : unsigned HOST_WIDE_INT abs_d;
831 : :
832 : 1047 : if (d == -1)
833 : : return NULL_TREE;
834 : :
835 : : /* Since d might be INT_MIN, we have to cast to
836 : : unsigned HOST_WIDE_INT before negating to avoid
837 : : undefined signed overflow. */
838 : 1047 : abs_d = (d >= 0
839 : : ? (unsigned HOST_WIDE_INT) d
840 : : : - (unsigned HOST_WIDE_INT) d);
841 : :
842 : : /* n rem d = n rem -d */
843 : 1047 : if (code == TRUNC_MOD_EXPR && d < 0)
844 : : {
845 : 119 : d = abs_d;
846 : 119 : use_abs_op1 = true;
847 : : }
848 : 1047 : if (abs_d == HOST_WIDE_INT_1U << (prec - 1))
849 : : {
850 : : /* This case is not handled correctly below. */
851 : 7 : mode = -2;
852 : 7 : continue;
853 : : }
854 : 1040 : if (abs_d <= 1)
855 : : {
856 : 32 : mode = -2;
857 : 32 : continue;
858 : : }
859 : :
860 : 1008 : choose_multiplier (abs_d, prec, prec - 1, &ml,
861 : : &post_shift);
862 : 1008 : if (ml >= HOST_WIDE_INT_1U << (prec - 1))
863 : : {
864 : 432 : this_mode = 4 + (d < 0);
865 : 432 : ml |= HOST_WIDE_INT_M1U << (prec - 1);
866 : : }
867 : : else
868 : 576 : this_mode = 2 + (d < 0);
869 : : }
870 : 1742 : mulc[i] = ml;
871 : 1742 : post_shifts[i] = post_shift;
872 : 1742 : if ((i && !has_vector_shift && post_shifts[0] != post_shift)
873 : 1646 : || post_shift >= prec
874 : 1646 : || pre_shifts[i] >= prec)
875 : 96 : this_mode = -2;
876 : :
877 : 1742 : if (i == 0)
878 : : mode = this_mode;
879 : 1416 : else if (mode != this_mode)
880 : 96 : mode = -2;
881 : : }
882 : :
883 : 437 : if (use_pow2)
884 : : {
885 : 126 : tree addend = NULL_TREE;
886 : 126 : if (sign_p == SIGNED)
887 : : {
888 : : tree uns_type;
889 : :
890 : : /* Both division and remainder sequences need
891 : : op0 < 0 ? mask : 0 computed. It can be either computed as
892 : : (type) (((uns_type) (op0 >> (prec - 1))) >> (prec - shifts[i]))
893 : : if none of the shifts is 0, or as the conditional. */
894 : 384 : for (i = 0; i < nunits; i++)
895 : 336 : if (shifts[i] == 0)
896 : : break;
897 : 64 : uns_type
898 : 64 : = build_vector_type (build_nonstandard_integer_type (prec, 1),
899 : 64 : nunits);
900 : 64 : if (i == nunits && TYPE_MODE (uns_type) == TYPE_MODE (type))
901 : : {
902 : 368 : for (i = 0; i < nunits; i++)
903 : 320 : shift_temps[i] = prec - 1;
904 : 48 : cur_op = add_shift (gsi, type, op0, shift_temps, RSHIFT_EXPR);
905 : 48 : if (cur_op != NULL_TREE)
906 : : {
907 : 48 : cur_op = gimplify_build1 (gsi, VIEW_CONVERT_EXPR,
908 : : uns_type, cur_op);
909 : 416 : for (i = 0; i < nunits; i++)
910 : 320 : shift_temps[i] = prec - shifts[i];
911 : 48 : cur_op = add_shift (gsi, uns_type, cur_op, shift_temps,
912 : : RSHIFT_EXPR);
913 : 48 : if (cur_op != NULL_TREE)
914 : 48 : addend = gimplify_build1 (gsi, VIEW_CONVERT_EXPR,
915 : : type, cur_op);
916 : : }
917 : : }
918 : 64 : tree mask_type = truth_type_for (type);
919 : 64 : if (addend == NULL_TREE
920 : 16 : && expand_vec_cmp_expr_p (type, mask_type, LT_EXPR)
921 : 80 : && expand_vec_cond_expr_p (type, mask_type))
922 : : {
923 : 16 : tree zero, cst, mask_type, mask;
924 : 16 : gimple *stmt, *cond;
925 : :
926 : 16 : mask_type = truth_type_for (type);
927 : 16 : zero = build_zero_cst (type);
928 : 16 : mask = make_ssa_name (mask_type);
929 : 16 : cond = gimple_build_assign (mask, LT_EXPR, op0, zero);
930 : 16 : gsi_insert_before (gsi, cond, GSI_SAME_STMT);
931 : 16 : tree_vector_builder vec (type, nunits, 1);
932 : 128 : for (i = 0; i < nunits; i++)
933 : 96 : vec.quick_push (build_int_cst (TREE_TYPE (type),
934 : : (HOST_WIDE_INT_1U
935 : 96 : << shifts[i]) - 1));
936 : 16 : cst = vec.build ();
937 : 16 : addend = make_ssa_name (type);
938 : 16 : stmt
939 : 16 : = gimple_build_assign (addend, VEC_COND_EXPR, mask, cst, zero);
940 : 16 : gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
941 : 16 : }
942 : : }
943 : 126 : if (code == TRUNC_DIV_EXPR)
944 : : {
945 : 54 : if (sign_p == UNSIGNED)
946 : : {
947 : : /* q = op0 >> shift; */
948 : 30 : cur_op = add_shift (gsi, type, op0, shifts, RSHIFT_EXPR);
949 : 30 : if (cur_op != NULL_TREE)
950 : : return cur_op;
951 : : }
952 : 24 : else if (addend != NULL_TREE)
953 : : {
954 : : /* t1 = op0 + addend;
955 : : q = t1 >> shift; */
956 : 24 : op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
957 : 24 : if (op != unknown_optab
958 : 24 : && can_implement_p (op, TYPE_MODE (type)))
959 : : {
960 : 24 : cur_op = gimplify_build2 (gsi, PLUS_EXPR, type, op0, addend);
961 : 24 : cur_op = add_shift (gsi, type, cur_op, shifts, RSHIFT_EXPR);
962 : 24 : if (cur_op != NULL_TREE)
963 : : return cur_op;
964 : : }
965 : : }
966 : : }
967 : : else
968 : : {
969 : 72 : tree mask;
970 : 72 : tree_vector_builder vec (type, nunits, 1);
971 : 592 : for (i = 0; i < nunits; i++)
972 : 448 : vec.quick_push (build_int_cst (TREE_TYPE (type),
973 : : (HOST_WIDE_INT_1U
974 : 448 : << shifts[i]) - 1));
975 : 72 : mask = vec.build ();
976 : 72 : op = optab_for_tree_code (BIT_AND_EXPR, type, optab_default);
977 : 72 : if (op != unknown_optab
978 : 72 : && can_implement_p (op, TYPE_MODE (type)))
979 : : {
980 : 72 : if (sign_p == UNSIGNED)
981 : : /* r = op0 & mask; */
982 : 32 : return gimplify_build2 (gsi, BIT_AND_EXPR, type, op0, mask);
983 : 40 : else if (addend != NULL_TREE)
984 : : {
985 : : /* t1 = op0 + addend;
986 : : t2 = t1 & mask;
987 : : r = t2 - addend; */
988 : 40 : op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
989 : 40 : if (op != unknown_optab
990 : 40 : && can_implement_p (op, TYPE_MODE (type)))
991 : : {
992 : 40 : cur_op = gimplify_build2 (gsi, PLUS_EXPR, type, op0,
993 : : addend);
994 : 40 : cur_op = gimplify_build2 (gsi, BIT_AND_EXPR, type,
995 : : cur_op, mask);
996 : 40 : op = optab_for_tree_code (MINUS_EXPR, type,
997 : : optab_default);
998 : 40 : if (op != unknown_optab
999 : 40 : && can_implement_p (op, TYPE_MODE (type)))
1000 : 40 : return gimplify_build2 (gsi, MINUS_EXPR, type,
1001 : 40 : cur_op, addend);
1002 : : }
1003 : : }
1004 : : }
1005 : 72 : }
1006 : : }
1007 : :
1008 : 311 : if (mode == -2 || BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN)
1009 : : return NULL_TREE;
1010 : :
1011 : 176 : if (!can_mult_highpart_p (TYPE_MODE (type), TYPE_UNSIGNED (type)))
1012 : : return NULL_TREE;
1013 : :
1014 : 170 : cur_op = op0;
1015 : :
1016 : 170 : switch (mode)
1017 : : {
1018 : 67 : case 0:
1019 : 67 : gcc_assert (sign_p == UNSIGNED);
1020 : : /* t1 = oprnd0 >> pre_shift;
1021 : : t2 = t1 h* ml;
1022 : : q = t2 >> post_shift; */
1023 : 67 : cur_op = add_shift (gsi, type, cur_op, pre_shifts, RSHIFT_EXPR);
1024 : 67 : if (cur_op == NULL_TREE)
1025 : : return NULL_TREE;
1026 : : break;
1027 : 32 : case 1:
1028 : 32 : gcc_assert (sign_p == UNSIGNED);
1029 : 224 : for (i = 0; i < nunits; i++)
1030 : : {
1031 : 192 : shift_temps[i] = 1;
1032 : 192 : post_shifts[i]--;
1033 : : }
1034 : : break;
1035 : 71 : case 2:
1036 : 71 : case 3:
1037 : 71 : case 4:
1038 : 71 : case 5:
1039 : 71 : gcc_assert (sign_p == SIGNED);
1040 : 567 : for (i = 0; i < nunits; i++)
1041 : 496 : shift_temps[i] = prec - 1;
1042 : : break;
1043 : : default:
1044 : : return NULL_TREE;
1045 : : }
1046 : :
1047 : 170 : tree_vector_builder vec (type, nunits, 1);
1048 : 1424 : for (i = 0; i < nunits; i++)
1049 : 1084 : vec.quick_push (build_int_cst (TREE_TYPE (type), mulc[i]));
1050 : 170 : mulcst = vec.build ();
1051 : :
1052 : 170 : cur_op = gimplify_build2 (gsi, MULT_HIGHPART_EXPR, type, cur_op, mulcst);
1053 : :
1054 : 170 : switch (mode)
1055 : : {
1056 : 67 : case 0:
1057 : : /* t1 = oprnd0 >> pre_shift;
1058 : : t2 = t1 h* ml;
1059 : : q = t2 >> post_shift; */
1060 : 67 : cur_op = add_shift (gsi, type, cur_op, post_shifts, RSHIFT_EXPR);
1061 : 67 : break;
1062 : 32 : case 1:
1063 : : /* t1 = oprnd0 h* ml;
1064 : : t2 = oprnd0 - t1;
1065 : : t3 = t2 >> 1;
1066 : : t4 = t1 + t3;
1067 : : q = t4 >> (post_shift - 1); */
1068 : 32 : op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
1069 : 32 : if (op == unknown_optab
1070 : 32 : || !can_implement_p (op, TYPE_MODE (type)))
1071 : 0 : return NULL_TREE;
1072 : 32 : tem = gimplify_build2 (gsi, MINUS_EXPR, type, op0, cur_op);
1073 : 32 : tem = add_shift (gsi, type, tem, shift_temps, RSHIFT_EXPR);
1074 : 32 : op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
1075 : 32 : if (op == unknown_optab
1076 : 32 : || !can_implement_p (op, TYPE_MODE (type)))
1077 : 0 : return NULL_TREE;
1078 : 32 : tem = gimplify_build2 (gsi, PLUS_EXPR, type, cur_op, tem);
1079 : 32 : cur_op = add_shift (gsi, type, tem, post_shifts, RSHIFT_EXPR);
1080 : 32 : if (cur_op == NULL_TREE)
1081 : : return NULL_TREE;
1082 : : break;
1083 : 71 : case 2:
1084 : 71 : case 3:
1085 : 71 : case 4:
1086 : 71 : case 5:
1087 : : /* t1 = oprnd0 h* ml;
1088 : : t2 = t1; [ iff (mode & 2) != 0 ]
1089 : : t2 = t1 + oprnd0; [ iff (mode & 2) == 0 ]
1090 : : t3 = t2 >> post_shift;
1091 : : t4 = oprnd0 >> (prec - 1);
1092 : : q = t3 - t4; [ iff (mode & 1) == 0 ]
1093 : : q = t4 - t3; [ iff (mode & 1) != 0 ] */
1094 : 71 : if ((mode & 2) == 0)
1095 : : {
1096 : 16 : op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
1097 : 16 : if (op == unknown_optab
1098 : 16 : || !can_implement_p (op, TYPE_MODE (type)))
1099 : 0 : return NULL_TREE;
1100 : 16 : cur_op = gimplify_build2 (gsi, PLUS_EXPR, type, cur_op, op0);
1101 : : }
1102 : 71 : cur_op = add_shift (gsi, type, cur_op, post_shifts, RSHIFT_EXPR);
1103 : 71 : if (cur_op == NULL_TREE)
1104 : : return NULL_TREE;
1105 : 71 : tem = add_shift (gsi, type, op0, shift_temps, RSHIFT_EXPR);
1106 : 71 : if (tem == NULL_TREE)
1107 : : return NULL_TREE;
1108 : 71 : op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
1109 : 71 : if (op == unknown_optab
1110 : 71 : || !can_implement_p (op, TYPE_MODE (type)))
1111 : 0 : return NULL_TREE;
1112 : 71 : if ((mode & 1) == 0)
1113 : 71 : cur_op = gimplify_build2 (gsi, MINUS_EXPR, type, cur_op, tem);
1114 : : else
1115 : 0 : cur_op = gimplify_build2 (gsi, MINUS_EXPR, type, tem, cur_op);
1116 : : break;
1117 : : default:
1118 : : gcc_unreachable ();
1119 : : }
1120 : :
1121 : 170 : if (code == TRUNC_DIV_EXPR)
1122 : : return cur_op;
1123 : :
1124 : : /* We divided. Now finish by:
1125 : : t1 = q * oprnd1;
1126 : : r = oprnd0 - t1; */
1127 : 87 : op = optab_for_tree_code (MULT_EXPR, type, optab_default);
1128 : 87 : if (op == unknown_optab
1129 : 87 : || !can_implement_p (op, TYPE_MODE (type)))
1130 : 0 : return NULL_TREE;
1131 : 87 : if (use_abs_op1)
1132 : : {
1133 : 7 : tree_vector_builder elts;
1134 : 7 : if (!elts.new_unary_operation (type, op1, false))
1135 : : return NULL_TREE;
1136 : 7 : unsigned int count = elts.encoded_nelts ();
1137 : 14 : for (unsigned int i = 0; i < count; ++i)
1138 : : {
1139 : 7 : tree elem1 = VECTOR_CST_ELT (op1, i);
1140 : :
1141 : 7 : tree elt = const_unop (ABS_EXPR, TREE_TYPE (elem1), elem1);
1142 : 7 : if (elt == NULL_TREE)
1143 : 0 : return NULL_TREE;
1144 : 7 : elts.quick_push (elt);
1145 : : }
1146 : 7 : op1 = elts.build ();
1147 : 7 : }
1148 : 87 : tem = gimplify_build2 (gsi, MULT_EXPR, type, cur_op, op1);
1149 : 87 : op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
1150 : 87 : if (op == unknown_optab
1151 : 87 : || !can_implement_p (op, TYPE_MODE (type)))
1152 : 0 : return NULL_TREE;
1153 : 87 : return gimplify_build2 (gsi, MINUS_EXPR, type, op0, tem);
1154 : : }
1155 : :
1156 : : /* Expand a vector condition to scalars, by using many conditions
1157 : : on the vector's elements. */
1158 : :
1159 : : static bool
1160 : 20449 : expand_vector_condition (gimple_stmt_iterator *gsi)
1161 : : {
1162 : 20449 : gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
1163 : 20449 : tree type = TREE_TYPE (gimple_assign_lhs (stmt));
1164 : 20449 : tree a = gimple_assign_rhs1 (stmt);
1165 : 20449 : tree a1 = a;
1166 : 20449 : tree a2 = NULL_TREE;
1167 : 20449 : bool a_is_scalar_bitmask = false;
1168 : 20449 : tree b = gimple_assign_rhs2 (stmt);
1169 : 20449 : tree c = gimple_assign_rhs3 (stmt);
1170 : 20449 : vec<constructor_elt, va_gc> *v;
1171 : 20449 : tree constr;
1172 : 20449 : tree inner_type = TREE_TYPE (type);
1173 : 20449 : tree width = vector_element_bits_tree (type);
1174 : 20449 : tree cond_type = TREE_TYPE (TREE_TYPE (a));
1175 : 20449 : tree index = bitsize_int (0);
1176 : 20449 : tree comp_width = width;
1177 : 20449 : tree comp_index = index;
1178 : 20449 : location_t loc = gimple_location (gsi_stmt (*gsi));
1179 : :
1180 : 20449 : gcc_assert (VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (a)));
1181 : :
1182 : 20449 : if (expand_vec_cond_expr_p (type, TREE_TYPE (a)))
1183 : : return true;
1184 : :
1185 : : /* Handle vector boolean types with bitmasks. We can transform
1186 : : vbfld_1 = tmp_6 ? vbfld_4 : vbfld_5;
1187 : : into
1188 : : tmp_7 = tmp_6 & vbfld_4;
1189 : : tmp_8 = ~tmp_6;
1190 : : tmp_9 = tmp_8 & vbfld_5;
1191 : : vbfld_1 = tmp_7 | tmp_9; */
1192 : 510 : if (VECTOR_BOOLEAN_TYPE_P (type)
1193 : 0 : && SCALAR_INT_MODE_P (TYPE_MODE (type))
1194 : 510 : && useless_type_conversion_p (type, TREE_TYPE (a)))
1195 : : {
1196 : 0 : a1 = gimplify_build2 (gsi, BIT_AND_EXPR, type, a, b);
1197 : 0 : a2 = gimplify_build1 (gsi, BIT_NOT_EXPR, type, a);
1198 : 0 : a2 = gimplify_build2 (gsi, BIT_AND_EXPR, type, a2, c);
1199 : 0 : a = gimplify_build2 (gsi, BIT_IOR_EXPR, type, a1, a2);
1200 : 0 : gimple_assign_set_rhs_from_tree (gsi, a);
1201 : 0 : update_stmt (gsi_stmt (*gsi));
1202 : 0 : return true;
1203 : : }
1204 : :
1205 : : /* TODO: try and find a smaller vector type. */
1206 : :
1207 : 510 : if (!warning_suppressed_p (stmt, OPT_Wvector_operation_performance))
1208 : 510 : warning_at (loc, OPT_Wvector_operation_performance,
1209 : : "vector condition will be expanded piecewise");
1210 : :
1211 : 984 : if (SCALAR_INT_MODE_P (TYPE_MODE (TREE_TYPE (a)))
1212 : 582 : && known_lt (GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (a))),
1213 : : TYPE_VECTOR_SUBPARTS (TREE_TYPE (a))
1214 : : * GET_MODE_BITSIZE (SCALAR_TYPE_MODE
1215 : : (TREE_TYPE (TREE_TYPE (a))))))
1216 : : {
1217 : 0 : a_is_scalar_bitmask = true;
1218 : 0 : int prec = GET_MODE_PRECISION (SCALAR_TYPE_MODE (TREE_TYPE (a)));
1219 : 0 : tree atype = build_nonstandard_integer_type (prec, 1);
1220 : 0 : a = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, atype, a);
1221 : : }
1222 : : else
1223 : 510 : comp_width = vector_element_bits_tree (TREE_TYPE (a));
1224 : :
1225 : 510 : int nunits = nunits_for_known_piecewise_op (type);
1226 : 510 : vec_alloc (v, nunits);
1227 : 510 : bool constant_p = true;
1228 : 6096 : for (int i = 0; i < nunits; i++)
1229 : : {
1230 : 5586 : tree aa, result;
1231 : 5586 : tree bb = tree_vec_extract (gsi, inner_type, b, width, index);
1232 : 5586 : tree cc = tree_vec_extract (gsi, inner_type, c, width, index);
1233 : 5586 : if (a_is_scalar_bitmask)
1234 : : {
1235 : 0 : wide_int w = wi::set_bit_in_zero (i, TYPE_PRECISION (TREE_TYPE (a)));
1236 : 0 : result = gimplify_build2 (gsi, BIT_AND_EXPR, TREE_TYPE (a),
1237 : 0 : a, wide_int_to_tree (TREE_TYPE (a), w));
1238 : 0 : aa = gimplify_build2 (gsi, NE_EXPR, boolean_type_node, result,
1239 : 0 : build_zero_cst (TREE_TYPE (a)));
1240 : 0 : }
1241 : : else
1242 : : {
1243 : 5586 : result = tree_vec_extract (gsi, cond_type, a, comp_width, comp_index);
1244 : 5586 : aa = gimplify_build2 (gsi, NE_EXPR, boolean_type_node, result,
1245 : : build_zero_cst (cond_type));
1246 : : }
1247 : 5586 : result = gimplify_build3 (gsi, COND_EXPR, inner_type, aa, bb, cc);
1248 : 5586 : if (!CONSTANT_CLASS_P (result))
1249 : 5502 : constant_p = false;
1250 : 5586 : constructor_elt ce = {NULL_TREE, result};
1251 : 5586 : v->quick_push (ce);
1252 : 5586 : index = int_const_binop (PLUS_EXPR, index, width);
1253 : 5586 : if (width == comp_width)
1254 : : comp_index = index;
1255 : : else
1256 : 0 : comp_index = int_const_binop (PLUS_EXPR, comp_index, comp_width);
1257 : : }
1258 : :
1259 : 510 : if (constant_p)
1260 : 0 : constr = build_vector_from_ctor (type, v);
1261 : : else
1262 : 510 : constr = build_constructor (type, v);
1263 : 510 : gimple_assign_set_rhs_from_tree (gsi, constr);
1264 : 510 : update_stmt (gsi_stmt (*gsi));
1265 : :
1266 : 510 : return false;
1267 : : }
1268 : :
1269 : : static tree
1270 : 26177 : expand_vector_operation (gimple_stmt_iterator *gsi, tree type, tree compute_type,
1271 : : gassign *assign, enum tree_code code)
1272 : : {
1273 : 26177 : machine_mode compute_mode = TYPE_MODE (compute_type);
1274 : :
1275 : : /* If the compute mode is not a vector mode (hence we are not decomposing
1276 : : a BLKmode vector to smaller, hardware-supported vectors), we may want
1277 : : to expand the operations in parallel. */
1278 : 26177 : if (!VECTOR_MODE_P (compute_mode))
1279 : 25292 : switch (code)
1280 : : {
1281 : 348 : case PLUS_EXPR:
1282 : 348 : case MINUS_EXPR:
1283 : 348 : if (ANY_INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_TRAPS (type))
1284 : 398 : return expand_vector_addition (gsi, do_binop, do_plus_minus, type,
1285 : : gimple_assign_rhs1 (assign),
1286 : 199 : gimple_assign_rhs2 (assign), code);
1287 : : break;
1288 : :
1289 : 3 : case NEGATE_EXPR:
1290 : 3 : if (ANY_INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_TRAPS (type))
1291 : 2 : return expand_vector_addition (gsi, do_unop, do_negate, type,
1292 : : gimple_assign_rhs1 (assign),
1293 : 2 : NULL_TREE, code);
1294 : : break;
1295 : :
1296 : 80 : case BIT_AND_EXPR:
1297 : 80 : case BIT_IOR_EXPR:
1298 : 80 : case BIT_XOR_EXPR:
1299 : 160 : return expand_vector_parallel (gsi, do_binop, type,
1300 : : gimple_assign_rhs1 (assign),
1301 : 80 : gimple_assign_rhs2 (assign), code);
1302 : :
1303 : 9 : case BIT_NOT_EXPR:
1304 : 9 : return expand_vector_parallel (gsi, do_unop, type,
1305 : : gimple_assign_rhs1 (assign),
1306 : 9 : NULL_TREE, code);
1307 : 23695 : case EQ_EXPR:
1308 : 23695 : case NE_EXPR:
1309 : 23695 : case GT_EXPR:
1310 : 23695 : case LT_EXPR:
1311 : 23695 : case GE_EXPR:
1312 : 23695 : case LE_EXPR:
1313 : 23695 : case UNEQ_EXPR:
1314 : 23695 : case UNGT_EXPR:
1315 : 23695 : case UNLT_EXPR:
1316 : 23695 : case UNGE_EXPR:
1317 : 23695 : case UNLE_EXPR:
1318 : 23695 : case LTGT_EXPR:
1319 : 23695 : case ORDERED_EXPR:
1320 : 23695 : case UNORDERED_EXPR:
1321 : 23695 : {
1322 : 23695 : tree rhs1 = gimple_assign_rhs1 (assign);
1323 : 23695 : tree rhs2 = gimple_assign_rhs2 (assign);
1324 : :
1325 : 23695 : return expand_vector_comparison (gsi, type, rhs1, rhs2, code);
1326 : : }
1327 : :
1328 : 761 : case TRUNC_DIV_EXPR:
1329 : 761 : case TRUNC_MOD_EXPR:
1330 : 761 : {
1331 : 761 : tree rhs1 = gimple_assign_rhs1 (assign);
1332 : 761 : tree rhs2 = gimple_assign_rhs2 (assign);
1333 : 761 : tree ret;
1334 : :
1335 : 761 : if (!optimize
1336 : 668 : || !VECTOR_INTEGER_TYPE_P (type)
1337 : 668 : || TREE_CODE (rhs2) != VECTOR_CST
1338 : 1215 : || !VECTOR_MODE_P (TYPE_MODE (type)))
1339 : : break;
1340 : :
1341 : 448 : ret = expand_vector_divmod (gsi, type, rhs1, rhs2, code);
1342 : 448 : if (ret != NULL_TREE)
1343 : : return ret;
1344 : : break;
1345 : : }
1346 : 102 : case MULT_EXPR:
1347 : 102 : {
1348 : 102 : tree rhs1 = gimple_assign_rhs1 (assign);
1349 : 102 : tree rhs2 = gimple_assign_rhs2 (assign);
1350 : 102 : tree ret;
1351 : :
1352 : 102 : if (!optimize
1353 : 81 : || !VECTOR_INTEGER_TYPE_P (type)
1354 : 60 : || TREE_CODE (rhs2) != VECTOR_CST
1355 : 104 : || !VECTOR_MODE_P (TYPE_MODE (type)))
1356 : : break;
1357 : :
1358 : 0 : ret = expand_vector_mult (gsi, type, rhs1, rhs2);
1359 : 0 : if (ret != NULL_TREE)
1360 : : return ret;
1361 : : break;
1362 : : }
1363 : : default:
1364 : : break;
1365 : : }
1366 : :
1367 : 1896 : if (TREE_CODE_CLASS (code) == tcc_unary)
1368 : 94 : return expand_vector_piecewise (gsi, do_unop, type, compute_type,
1369 : : gimple_assign_rhs1 (assign),
1370 : 94 : NULL_TREE, code, false);
1371 : : else
1372 : 3604 : return expand_vector_piecewise (gsi, do_binop, type, compute_type,
1373 : : gimple_assign_rhs1 (assign),
1374 : 1802 : gimple_assign_rhs2 (assign), code, false);
1375 : : }
1376 : :
1377 : : /* Try to optimize
1378 : : a_5 = { b_7, b_7 + 3, b_7 + 6, b_7 + 9 };
1379 : : style stmts into:
1380 : : _9 = { b_7, b_7, b_7, b_7 };
1381 : : a_5 = _9 + { 0, 3, 6, 9 };
1382 : : because vector splat operation is usually more efficient
1383 : : than piecewise initialization of the vector. */
1384 : :
1385 : : static void
1386 : 147789 : optimize_vector_constructor (gimple_stmt_iterator *gsi)
1387 : : {
1388 : 147789 : gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
1389 : 147789 : tree lhs = gimple_assign_lhs (stmt);
1390 : 147789 : tree rhs = gimple_assign_rhs1 (stmt);
1391 : 147789 : tree type = TREE_TYPE (rhs);
1392 : 147789 : unsigned int i, j;
1393 : 147789 : unsigned HOST_WIDE_INT nelts;
1394 : 147789 : bool all_same = true;
1395 : 147789 : constructor_elt *elt;
1396 : 147789 : gimple *g;
1397 : 147789 : tree base = NULL_TREE;
1398 : 147789 : optab op;
1399 : :
1400 : 147789 : if (!TYPE_VECTOR_SUBPARTS (type).is_constant (&nelts)
1401 : 147789 : || nelts <= 2
1402 : 44042 : || CONSTRUCTOR_NELTS (rhs) != nelts)
1403 : 147785 : return;
1404 : 20809 : op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
1405 : 20809 : if (op == unknown_optab
1406 : 20809 : || !can_implement_p (op, TYPE_MODE (type)))
1407 : 510 : return;
1408 : 101153 : FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (rhs), i, elt)
1409 : 89734 : if (TREE_CODE (elt->value) != SSA_NAME
1410 : 89734 : || TREE_CODE (TREE_TYPE (elt->value)) == VECTOR_TYPE)
1411 : : return;
1412 : : else
1413 : : {
1414 : 87851 : tree this_base = elt->value;
1415 : 87851 : if (this_base != CONSTRUCTOR_ELT (rhs, 0)->value)
1416 : 7009 : all_same = false;
1417 : 88844 : for (j = 0; j < nelts + 1; j++)
1418 : : {
1419 : 88844 : g = SSA_NAME_DEF_STMT (this_base);
1420 : 88844 : if (is_gimple_assign (g)
1421 : 56721 : && gimple_assign_rhs_code (g) == PLUS_EXPR
1422 : 2512 : && TREE_CODE (gimple_assign_rhs2 (g)) == INTEGER_CST
1423 : 993 : && TREE_CODE (gimple_assign_rhs1 (g)) == SSA_NAME
1424 : 89837 : && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_assign_rhs1 (g)))
1425 : 993 : this_base = gimple_assign_rhs1 (g);
1426 : : else
1427 : : break;
1428 : : }
1429 : 87851 : if (i == 0)
1430 : : base = this_base;
1431 : 67989 : else if (this_base != base)
1432 : : return;
1433 : : }
1434 : 11419 : if (all_same)
1435 : : return;
1436 : 4 : tree_vector_builder cst (type, nelts, 1);
1437 : 20 : for (i = 0; i < nelts; i++)
1438 : : {
1439 : 16 : tree this_base = CONSTRUCTOR_ELT (rhs, i)->value;
1440 : 16 : tree elt = build_zero_cst (TREE_TYPE (base));
1441 : 29 : while (this_base != base)
1442 : : {
1443 : 13 : g = SSA_NAME_DEF_STMT (this_base);
1444 : 13 : elt = fold_binary (PLUS_EXPR, TREE_TYPE (base),
1445 : : elt, gimple_assign_rhs2 (g));
1446 : 13 : if (elt == NULL_TREE
1447 : 13 : || TREE_CODE (elt) != INTEGER_CST
1448 : 26 : || TREE_OVERFLOW (elt))
1449 : 0 : return;
1450 : 13 : this_base = gimple_assign_rhs1 (g);
1451 : : }
1452 : 16 : cst.quick_push (elt);
1453 : : }
1454 : 20 : for (i = 0; i < nelts; i++)
1455 : 16 : CONSTRUCTOR_ELT (rhs, i)->value = base;
1456 : 4 : g = gimple_build_assign (make_ssa_name (type), rhs);
1457 : 4 : gsi_insert_before (gsi, g, GSI_SAME_STMT);
1458 : 4 : g = gimple_build_assign (lhs, PLUS_EXPR, gimple_assign_lhs (g),
1459 : : cst.build ());
1460 : 4 : gsi_replace (gsi, g, false);
1461 : 4 : }
1462 : :
1463 : : /* Return a type for the widest vector mode with the same element type as
1464 : : type ORIGINAL_VECTOR_TYPE, with at most the same number of elements as type
1465 : : ORIGINAL_VECTOR_TYPE and that is supported by the target for an operation
1466 : : with optab OP, or return NULL_TREE if none is found. */
1467 : :
1468 : : static tree
1469 : 2834 : type_for_widest_vector_mode (tree original_vector_type, optab op)
1470 : : {
1471 : 2834 : gcc_assert (VECTOR_TYPE_P (original_vector_type));
1472 : 2834 : tree type = TREE_TYPE (original_vector_type);
1473 : 2834 : machine_mode inner_mode = TYPE_MODE (type);
1474 : 2834 : machine_mode best_mode = VOIDmode, mode;
1475 : 2834 : poly_int64 best_nunits = 0;
1476 : :
1477 : 2834 : if (SCALAR_FLOAT_MODE_P (inner_mode))
1478 : : mode = MIN_MODE_VECTOR_FLOAT;
1479 : 2478 : else if (SCALAR_FRACT_MODE_P (inner_mode))
1480 : : mode = MIN_MODE_VECTOR_FRACT;
1481 : 2478 : else if (SCALAR_UFRACT_MODE_P (inner_mode))
1482 : : mode = MIN_MODE_VECTOR_UFRACT;
1483 : 2478 : else if (SCALAR_ACCUM_MODE_P (inner_mode))
1484 : : mode = MIN_MODE_VECTOR_ACCUM;
1485 : 2478 : else if (SCALAR_UACCUM_MODE_P (inner_mode))
1486 : : mode = MIN_MODE_VECTOR_UACCUM;
1487 : 2478 : else if (inner_mode == BImode)
1488 : : mode = MIN_MODE_VECTOR_BOOL;
1489 : : else
1490 : 2834 : mode = MIN_MODE_VECTOR_INT;
1491 : :
1492 : 88552 : FOR_EACH_MODE_FROM (mode, mode)
1493 : 85718 : if (GET_MODE_INNER (mode) == inner_mode
1494 : 33000 : && maybe_gt (GET_MODE_NUNITS (mode), best_nunits)
1495 : 16500 : && can_implement_p (op, mode)
1496 : 104765 : && known_le (GET_MODE_NUNITS (mode),
1497 : : TYPE_VECTOR_SUBPARTS (original_vector_type)))
1498 : 4064 : best_mode = mode, best_nunits = GET_MODE_NUNITS (mode);
1499 : :
1500 : 2834 : if (best_mode == VOIDmode)
1501 : : return NULL_TREE;
1502 : : else
1503 : 1070 : return build_vector_type_for_mode (type, best_mode);
1504 : : }
1505 : :
1506 : :
1507 : : /* Build a reference to the element of the vector VECT. Function
1508 : : returns either the element itself, either BIT_FIELD_REF, or an
1509 : : ARRAY_REF expression.
1510 : :
1511 : : GSI is required to insert temporary variables while building a
1512 : : refernece to the element of the vector VECT.
1513 : :
1514 : : PTMPVEC is a pointer to the temporary variable for caching
1515 : : purposes. In case when PTMPVEC is NULL new temporary variable
1516 : : will be created. */
1517 : : static tree
1518 : 104711 : vector_element (gimple_stmt_iterator *gsi, tree vect, tree idx, tree *ptmpvec)
1519 : : {
1520 : 104711 : tree vect_type, vect_elt_type;
1521 : 104711 : gimple *asgn;
1522 : 104711 : tree tmpvec;
1523 : 104711 : tree arraytype;
1524 : 104711 : bool need_asgn = true;
1525 : 104711 : unsigned int elements;
1526 : :
1527 : 104711 : vect_type = TREE_TYPE (vect);
1528 : 104711 : vect_elt_type = TREE_TYPE (vect_type);
1529 : 104711 : elements = nunits_for_known_piecewise_op (vect_type);
1530 : :
1531 : 104711 : if (TREE_CODE (idx) == INTEGER_CST)
1532 : : {
1533 : 97118 : unsigned HOST_WIDE_INT index;
1534 : :
1535 : : /* Given that we're about to compute a binary modulus,
1536 : : we don't care about the high bits of the value. */
1537 : 97118 : index = TREE_INT_CST_LOW (idx);
1538 : 97118 : if (!tree_fits_uhwi_p (idx) || index >= elements)
1539 : : {
1540 : 0 : index &= elements - 1;
1541 : 0 : idx = build_int_cst (TREE_TYPE (idx), index);
1542 : : }
1543 : :
1544 : : /* When lowering a vector statement sequence do some easy
1545 : : simplification by looking through intermediate vector results. */
1546 : 97118 : if (TREE_CODE (vect) == SSA_NAME)
1547 : : {
1548 : 50949 : gimple *def_stmt = SSA_NAME_DEF_STMT (vect);
1549 : 50949 : if (is_gimple_assign (def_stmt)
1550 : 50949 : && (gimple_assign_rhs_code (def_stmt) == VECTOR_CST
1551 : 49822 : || gimple_assign_rhs_code (def_stmt) == CONSTRUCTOR))
1552 : 2107 : vect = gimple_assign_rhs1 (def_stmt);
1553 : : }
1554 : :
1555 : 97118 : if (TREE_CODE (vect) == VECTOR_CST)
1556 : 47200 : return VECTOR_CST_ELT (vect, index);
1557 : 49918 : else if (TREE_CODE (vect) == CONSTRUCTOR
1558 : 49918 : && (CONSTRUCTOR_NELTS (vect) == 0
1559 : 1076 : || TREE_CODE (TREE_TYPE (CONSTRUCTOR_ELT (vect, 0)->value))
1560 : : != VECTOR_TYPE))
1561 : : {
1562 : 169 : if (index < CONSTRUCTOR_NELTS (vect))
1563 : 169 : return CONSTRUCTOR_ELT (vect, index)->value;
1564 : 0 : return build_zero_cst (vect_elt_type);
1565 : : }
1566 : : else
1567 : : {
1568 : 49749 : tree size = vector_element_bits_tree (vect_type);
1569 : 49749 : tree pos = fold_build2 (MULT_EXPR, bitsizetype, bitsize_int (index),
1570 : : size);
1571 : 49749 : return fold_build3 (BIT_FIELD_REF, vect_elt_type, vect, size, pos);
1572 : : }
1573 : : }
1574 : :
1575 : 7593 : if (!ptmpvec)
1576 : 0 : tmpvec = create_tmp_var (vect_type, "vectmp");
1577 : 7593 : else if (!*ptmpvec)
1578 : 1280 : tmpvec = *ptmpvec = create_tmp_var (vect_type, "vectmp");
1579 : : else
1580 : : {
1581 : : tmpvec = *ptmpvec;
1582 : : need_asgn = false;
1583 : : }
1584 : :
1585 : 1280 : if (need_asgn)
1586 : : {
1587 : 1280 : TREE_ADDRESSABLE (tmpvec) = 1;
1588 : 1280 : asgn = gimple_build_assign (tmpvec, vect);
1589 : 1280 : gsi_insert_before (gsi, asgn, GSI_SAME_STMT);
1590 : : }
1591 : :
1592 : 7593 : arraytype = build_array_type_nelts (vect_elt_type, elements);
1593 : 7593 : return build4 (ARRAY_REF, vect_elt_type,
1594 : : build1 (VIEW_CONVERT_EXPR, arraytype, tmpvec),
1595 : 7593 : idx, NULL_TREE, NULL_TREE);
1596 : : }
1597 : :
1598 : : /* Check if VEC_PERM_EXPR within the given setting is supported
1599 : : by hardware, or lower it piecewise.
1600 : :
1601 : : When VEC_PERM_EXPR has the same first and second operands:
1602 : : VEC_PERM_EXPR <v0, v0, mask> the lowered version would be
1603 : : {v0[mask[0]], v0[mask[1]], ...}
1604 : : MASK and V0 must have the same number of elements.
1605 : :
1606 : : Otherwise VEC_PERM_EXPR <v0, v1, mask> is lowered to
1607 : : {mask[0] < len(v0) ? v0[mask[0]] : v1[mask[0]], ...}
1608 : : V0 and V1 must have the same type. MASK, V0, V1 must have the
1609 : : same number of arguments. */
1610 : :
1611 : : static void
1612 : 87362 : lower_vec_perm (gimple_stmt_iterator *gsi)
1613 : : {
1614 : 87362 : gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
1615 : 87362 : tree mask = gimple_assign_rhs3 (stmt);
1616 : 87362 : tree vec0 = gimple_assign_rhs1 (stmt);
1617 : 87362 : tree vec1 = gimple_assign_rhs2 (stmt);
1618 : 87362 : tree res_vect_type = TREE_TYPE (gimple_assign_lhs (stmt));
1619 : 87362 : tree vect_type = TREE_TYPE (vec0);
1620 : 87362 : tree mask_type = TREE_TYPE (mask);
1621 : 87362 : tree vect_elt_type = TREE_TYPE (vect_type);
1622 : 87362 : tree mask_elt_type = TREE_TYPE (mask_type);
1623 : 87362 : unsigned HOST_WIDE_INT elements;
1624 : 87362 : vec<constructor_elt, va_gc> *v;
1625 : 87362 : tree constr, t, si, i_val;
1626 : 87362 : tree vec0tmp = NULL_TREE, vec1tmp = NULL_TREE, masktmp = NULL_TREE;
1627 : 87362 : bool two_operand_p = !operand_equal_p (vec0, vec1, 0);
1628 : 87362 : location_t loc = gimple_location (gsi_stmt (*gsi));
1629 : 87362 : unsigned i;
1630 : :
1631 : 87362 : if (!TYPE_VECTOR_SUBPARTS (res_vect_type).is_constant (&elements))
1632 : 78445 : return;
1633 : :
1634 : 87362 : if (TREE_CODE (mask) == SSA_NAME)
1635 : : {
1636 : 876 : gimple *def_stmt = SSA_NAME_DEF_STMT (mask);
1637 : 876 : if (is_gimple_assign (def_stmt)
1638 : 876 : && gimple_assign_rhs_code (def_stmt) == VECTOR_CST)
1639 : 12 : mask = gimple_assign_rhs1 (def_stmt);
1640 : : }
1641 : :
1642 : 87362 : vec_perm_builder sel_int;
1643 : :
1644 : 87362 : if (TREE_CODE (mask) == VECTOR_CST
1645 : 87362 : && tree_to_vec_perm_builder (&sel_int, mask))
1646 : : {
1647 : 86497 : vec_perm_indices indices (sel_int, 2, elements);
1648 : 86497 : machine_mode vmode = TYPE_MODE (vect_type);
1649 : 86497 : tree lhs_type = TREE_TYPE (gimple_assign_lhs (stmt));
1650 : 86497 : machine_mode lhs_mode = TYPE_MODE (lhs_type);
1651 : 86497 : if (can_vec_perm_const_p (lhs_mode, vmode, indices))
1652 : : {
1653 : 78406 : gimple_assign_set_rhs3 (stmt, mask);
1654 : 78406 : update_stmt (stmt);
1655 : 78406 : return;
1656 : : }
1657 : : /* Also detect vec_shr pattern - VEC_PERM_EXPR with zero
1658 : : vector as VEC1 and a right element shift MASK. */
1659 : 8091 : if (can_implement_p (vec_shr_optab, TYPE_MODE (vect_type))
1660 : 7335 : && TREE_CODE (vec1) == VECTOR_CST
1661 : 27 : && initializer_zerop (vec1)
1662 : 27 : && maybe_ne (indices[0], 0)
1663 : 15426 : && known_lt (poly_uint64 (indices[0]), elements))
1664 : : {
1665 : 24 : bool ok_p = indices.series_p (0, 1, indices[0], 1);
1666 : 24 : if (!ok_p)
1667 : : {
1668 : 1 : for (i = 1; i < elements; ++i)
1669 : : {
1670 : 1 : poly_uint64 actual = indices[i];
1671 : 1 : poly_uint64 expected = i + indices[0];
1672 : : /* Indices into the second vector are all equivalent. */
1673 : 1 : if (maybe_lt (actual, elements)
1674 : 1 : ? maybe_ne (actual, expected)
1675 : 1 : : maybe_lt (expected, elements))
1676 : : break;
1677 : : }
1678 : 1 : ok_p = i == elements;
1679 : : }
1680 : 1 : if (ok_p)
1681 : : {
1682 : 23 : gimple_assign_set_rhs3 (stmt, mask);
1683 : 23 : update_stmt (stmt);
1684 : 23 : return;
1685 : : }
1686 : : }
1687 : : /* And similarly vec_shl pattern. */
1688 : 8068 : if (can_implement_p (vec_shl_optab, TYPE_MODE (vect_type))
1689 : 7312 : && TREE_CODE (vec0) == VECTOR_CST
1690 : 8075 : && initializer_zerop (vec0))
1691 : : {
1692 : : unsigned int first = 0;
1693 : 47 : for (i = 0; i < elements; ++i)
1694 : 40 : if (known_eq (poly_uint64 (indices[i]), elements))
1695 : : {
1696 : 5 : if (i == 0 || first)
1697 : : break;
1698 : : first = i;
1699 : : }
1700 : 70 : else if (first
1701 : 70 : ? maybe_ne (poly_uint64 (indices[i]),
1702 : 14 : elements + i - first)
1703 : 35 : : maybe_ge (poly_uint64 (indices[i]), elements))
1704 : : break;
1705 : 7 : if (first && i == elements)
1706 : : {
1707 : 5 : gimple_assign_set_rhs3 (stmt, mask);
1708 : 5 : update_stmt (stmt);
1709 : 5 : return;
1710 : : }
1711 : : }
1712 : 86497 : }
1713 : 865 : else if (can_vec_perm_var_p (TYPE_MODE (vect_type)))
1714 : : return;
1715 : :
1716 : 8917 : if (!warning_suppressed_p (stmt, OPT_Wvector_operation_performance))
1717 : 8917 : warning_at (loc, OPT_Wvector_operation_performance,
1718 : : "vector shuffling operation will be expanded piecewise");
1719 : :
1720 : 8917 : vec_alloc (v, elements);
1721 : 8917 : bool constant_p = true;
1722 : 60033 : for (i = 0; i < elements; i++)
1723 : : {
1724 : 51116 : si = size_int (i);
1725 : 51116 : i_val = vector_element (gsi, mask, si, &masktmp);
1726 : :
1727 : 51116 : if (TREE_CODE (i_val) == INTEGER_CST)
1728 : : {
1729 : 46002 : unsigned HOST_WIDE_INT index;
1730 : :
1731 : 46002 : index = TREE_INT_CST_LOW (i_val);
1732 : 46002 : if (!tree_fits_uhwi_p (i_val) || index >= elements)
1733 : 14354 : i_val = build_int_cst (mask_elt_type, index & (elements - 1));
1734 : :
1735 : 46002 : if (two_operand_p && (index & elements) != 0)
1736 : 14340 : t = vector_element (gsi, vec1, i_val, &vec1tmp);
1737 : : else
1738 : 31662 : t = vector_element (gsi, vec0, i_val, &vec0tmp);
1739 : :
1740 : 46002 : t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE,
1741 : : true, GSI_SAME_STMT);
1742 : : }
1743 : : else
1744 : : {
1745 : 5114 : tree cond = NULL_TREE, v0_val;
1746 : :
1747 : 5114 : if (two_operand_p)
1748 : : {
1749 : 2479 : cond = fold_build2 (BIT_AND_EXPR, mask_elt_type, i_val,
1750 : : build_int_cst (mask_elt_type, elements));
1751 : 2479 : cond = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE,
1752 : : true, GSI_SAME_STMT);
1753 : : }
1754 : :
1755 : 5114 : i_val = fold_build2 (BIT_AND_EXPR, mask_elt_type, i_val,
1756 : : build_int_cst (mask_elt_type, elements - 1));
1757 : 5114 : i_val = force_gimple_operand_gsi (gsi, i_val, true, NULL_TREE,
1758 : : true, GSI_SAME_STMT);
1759 : :
1760 : 5114 : v0_val = vector_element (gsi, vec0, i_val, &vec0tmp);
1761 : 5114 : v0_val = force_gimple_operand_gsi (gsi, v0_val, true, NULL_TREE,
1762 : : true, GSI_SAME_STMT);
1763 : :
1764 : 5114 : if (two_operand_p)
1765 : : {
1766 : 2479 : tree v1_val;
1767 : :
1768 : 2479 : v1_val = vector_element (gsi, vec1, i_val, &vec1tmp);
1769 : 2479 : v1_val = force_gimple_operand_gsi (gsi, v1_val, true, NULL_TREE,
1770 : : true, GSI_SAME_STMT);
1771 : :
1772 : 2479 : cond = fold_build2 (EQ_EXPR, boolean_type_node,
1773 : : cond, build_zero_cst (mask_elt_type));
1774 : 2479 : cond = fold_build3 (COND_EXPR, vect_elt_type,
1775 : : cond, v0_val, v1_val);
1776 : 2479 : t = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE,
1777 : : true, GSI_SAME_STMT);
1778 : : }
1779 : : else
1780 : : t = v0_val;
1781 : : }
1782 : :
1783 : 51116 : if (!CONSTANT_CLASS_P (t))
1784 : 49297 : constant_p = false;
1785 : 51116 : CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, t);
1786 : : }
1787 : :
1788 : 8917 : if (constant_p)
1789 : 6 : constr = build_vector_from_ctor (res_vect_type, v);
1790 : : else
1791 : 8911 : constr = build_constructor (res_vect_type, v);
1792 : 8917 : gimple_assign_set_rhs_from_tree (gsi, constr);
1793 : 8917 : update_stmt (gsi_stmt (*gsi));
1794 : 87362 : }
1795 : :
1796 : : /* Return the type that should be used to implement OP on type TYPE.
1797 : : This is TYPE itself if the target can do the operation directly,
1798 : : otherwise it is a scalar type or a smaller vector type. */
1799 : :
1800 : : static tree
1801 : 213596 : get_compute_type (optab op, tree type)
1802 : : {
1803 : 213596 : if (op)
1804 : : {
1805 : 379802 : if (VECTOR_MODE_P (TYPE_MODE (type))
1806 : 378312 : && can_implement_p (op, TYPE_MODE (type)))
1807 : : return type;
1808 : :
1809 : : /* For very wide vectors, try using a smaller vector mode. */
1810 : 2763 : tree vector_compute_type = type_for_widest_vector_mode (type, op);
1811 : 2763 : if (vector_compute_type != NULL_TREE
1812 : 2763 : && maybe_ne (TYPE_VECTOR_SUBPARTS (vector_compute_type), 1U)
1813 : 3707 : && can_implement_p (op, TYPE_MODE (vector_compute_type)))
1814 : 944 : return vector_compute_type;
1815 : : }
1816 : :
1817 : : /* There is no operation in hardware, so fall back to scalars. */
1818 : 25514 : return TREE_TYPE (type);
1819 : : }
1820 : :
1821 : : static tree
1822 : 14 : do_cond (gimple_stmt_iterator *gsi, tree inner_type, tree a, tree b,
1823 : : tree bitpos, tree bitsize, enum tree_code code,
1824 : : tree type ATTRIBUTE_UNUSED)
1825 : : {
1826 : 14 : if (VECTOR_TYPE_P (TREE_TYPE (a)))
1827 : 14 : a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
1828 : 14 : if (VECTOR_TYPE_P (TREE_TYPE (b)))
1829 : 14 : b = tree_vec_extract (gsi, inner_type, b, bitsize, bitpos);
1830 : 14 : tree cond = gimple_assign_rhs1 (gsi_stmt (*gsi));
1831 : 14 : return gimplify_build3 (gsi, code, inner_type, unshare_expr (cond), a, b);
1832 : : }
1833 : :
1834 : : /* Expand a vector COND_EXPR to scalars, piecewise. */
1835 : : static void
1836 : 7 : expand_vector_scalar_condition (gimple_stmt_iterator *gsi)
1837 : : {
1838 : 7 : gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
1839 : 7 : tree lhs = gimple_assign_lhs (stmt);
1840 : 7 : tree type = TREE_TYPE (lhs);
1841 : 7 : tree compute_type = get_compute_type (mov_optab, type);
1842 : 7 : machine_mode compute_mode = TYPE_MODE (compute_type);
1843 : 7 : gcc_assert (compute_mode != BLKmode);
1844 : 7 : tree rhs2 = gimple_assign_rhs2 (stmt);
1845 : 7 : tree rhs3 = gimple_assign_rhs3 (stmt);
1846 : 7 : tree new_rhs;
1847 : :
1848 : : /* If the compute mode is not a vector mode (hence we are not decomposing
1849 : : a BLKmode vector to smaller, hardware-supported vectors), we may want
1850 : : to expand the operations in parallel. */
1851 : 7 : if (!VECTOR_MODE_P (compute_mode))
1852 : 0 : new_rhs = expand_vector_parallel (gsi, do_cond, type, rhs2, rhs3,
1853 : : COND_EXPR);
1854 : : else
1855 : 7 : new_rhs = expand_vector_piecewise (gsi, do_cond, type, compute_type,
1856 : : rhs2, rhs3, COND_EXPR, false);
1857 : 7 : if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (new_rhs)))
1858 : 0 : new_rhs = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, TREE_TYPE (lhs),
1859 : : new_rhs);
1860 : :
1861 : : /* NOTE: We should avoid using gimple_assign_set_rhs_from_tree. One
1862 : : way to do it is change expand_vector_operation and its callees to
1863 : : return a tree_code, RHS1 and RHS2 instead of a tree. */
1864 : 7 : gimple_assign_set_rhs_from_tree (gsi, new_rhs);
1865 : 7 : update_stmt (gsi_stmt (*gsi));
1866 : 7 : }
1867 : :
1868 : : /* Callback for expand_vector_piecewise to do VEC_CONVERT ifn call
1869 : : lowering. If INNER_TYPE is not a vector type, this is a scalar
1870 : : fallback. */
1871 : :
1872 : : static tree
1873 : 17996 : do_vec_conversion (gimple_stmt_iterator *gsi, tree inner_type, tree a,
1874 : : tree decl, tree bitpos, tree bitsize,
1875 : : enum tree_code code, tree type)
1876 : : {
1877 : 17996 : a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
1878 : 17996 : if (!VECTOR_TYPE_P (inner_type))
1879 : 17996 : return gimplify_build1 (gsi, code, TREE_TYPE (type), a);
1880 : 0 : if (code == CALL_EXPR)
1881 : : {
1882 : 0 : gimple *g = gimple_build_call (decl, 1, a);
1883 : 0 : tree lhs = make_ssa_name (TREE_TYPE (TREE_TYPE (decl)));
1884 : 0 : gimple_call_set_lhs (g, lhs);
1885 : 0 : gsi_insert_before (gsi, g, GSI_SAME_STMT);
1886 : 0 : return lhs;
1887 : : }
1888 : : else
1889 : : {
1890 : 0 : tree outer_type = build_vector_type (TREE_TYPE (type),
1891 : 0 : TYPE_VECTOR_SUBPARTS (inner_type));
1892 : 0 : return gimplify_build1 (gsi, code, outer_type, a);
1893 : : }
1894 : : }
1895 : :
1896 : : /* Similarly, but for narrowing conversion. */
1897 : :
1898 : : static tree
1899 : 29 : do_vec_narrow_conversion (gimple_stmt_iterator *gsi, tree inner_type, tree a,
1900 : : tree, tree bitpos, tree, enum tree_code code,
1901 : : tree type)
1902 : : {
1903 : 29 : tree itype = build_vector_type (TREE_TYPE (inner_type),
1904 : 29 : exact_div (TYPE_VECTOR_SUBPARTS (inner_type),
1905 : : 2));
1906 : 29 : tree b = tree_vec_extract (gsi, itype, a, TYPE_SIZE (itype), bitpos);
1907 : 29 : tree c = tree_vec_extract (gsi, itype, a, TYPE_SIZE (itype),
1908 : : int_const_binop (PLUS_EXPR, bitpos,
1909 : 29 : TYPE_SIZE (itype)));
1910 : 29 : tree outer_type = build_vector_type (TREE_TYPE (type),
1911 : 29 : TYPE_VECTOR_SUBPARTS (inner_type));
1912 : 29 : return gimplify_build2 (gsi, code, outer_type, b, c);
1913 : : }
1914 : :
1915 : : /* Expand VEC_CONVERT ifn call. */
1916 : :
1917 : : static void
1918 : 449 : expand_vector_conversion (gimple_stmt_iterator *gsi)
1919 : : {
1920 : 449 : gimple *stmt = gsi_stmt (*gsi);
1921 : 449 : gimple *g;
1922 : 449 : tree lhs = gimple_call_lhs (stmt);
1923 : 449 : if (lhs == NULL_TREE)
1924 : : {
1925 : 1 : g = gimple_build_nop ();
1926 : 1 : gsi_replace (gsi, g, false);
1927 : 365 : return;
1928 : : }
1929 : 448 : tree arg = gimple_call_arg (stmt, 0);
1930 : 448 : tree ret_type = TREE_TYPE (lhs);
1931 : 448 : tree arg_type = TREE_TYPE (arg);
1932 : 448 : tree new_rhs, new_lhs, compute_type = TREE_TYPE (arg_type);
1933 : 448 : enum tree_code code = NOP_EXPR;
1934 : 448 : enum tree_code code1 = ERROR_MARK;
1935 : 448 : enum { NARROW, NONE, WIDEN } modifier = NONE;
1936 : 448 : optab optab1 = unknown_optab;
1937 : :
1938 : 448 : gcc_checking_assert (VECTOR_TYPE_P (ret_type) && VECTOR_TYPE_P (arg_type));
1939 : 896 : if (INTEGRAL_TYPE_P (TREE_TYPE (ret_type))
1940 : 720 : && SCALAR_FLOAT_TYPE_P (TREE_TYPE (arg_type)))
1941 : : code = FIX_TRUNC_EXPR;
1942 : 590 : else if (INTEGRAL_TYPE_P (TREE_TYPE (arg_type))
1943 : 538 : && SCALAR_FLOAT_TYPE_P (TREE_TYPE (ret_type)))
1944 : : code = FLOAT_EXPR;
1945 : 448 : unsigned int ret_elt_bits = vector_element_bits (ret_type);
1946 : 448 : unsigned int arg_elt_bits = vector_element_bits (arg_type);
1947 : 448 : if (ret_elt_bits < arg_elt_bits)
1948 : : modifier = NARROW;
1949 : 256 : else if (ret_elt_bits > arg_elt_bits)
1950 : 114 : modifier = WIDEN;
1951 : :
1952 : 448 : auto_vec<std::pair<tree, tree_code>, 2> converts;
1953 : 448 : if (supportable_indirect_convert_operation (code, ret_type, arg_type,
1954 : : converts))
1955 : : {
1956 : 282 : new_rhs = arg;
1957 : 282 : gcc_assert (!converts.is_empty ());
1958 : 660 : for (unsigned int i = 0; i < converts.length () - 1; i++)
1959 : : {
1960 : 48 : new_lhs = make_ssa_name (converts[i].first);
1961 : 48 : g = gimple_build_assign (new_lhs, converts[i].second, new_rhs);
1962 : 48 : new_rhs = new_lhs;
1963 : 48 : gsi_insert_before (gsi, g, GSI_SAME_STMT);
1964 : : }
1965 : 846 : g = gimple_build_assign (lhs,
1966 : 282 : converts[converts.length() - 1].second,
1967 : : new_rhs);
1968 : 282 : gsi_replace (gsi, g, false);
1969 : 282 : return;
1970 : : }
1971 : :
1972 : 166 : if (modifier == NONE && (code == FIX_TRUNC_EXPR || code == FLOAT_EXPR))
1973 : : {
1974 : : /* Can't use get_compute_type here, as supportable_convert_operation
1975 : : doesn't necessarily use an optab and needs two arguments. */
1976 : 71 : tree vec_compute_type
1977 : 71 : = type_for_widest_vector_mode (arg_type, mov_optab);
1978 : 71 : if (vec_compute_type
1979 : 71 : && VECTOR_MODE_P (TYPE_MODE (vec_compute_type)))
1980 : : {
1981 : 71 : unsigned HOST_WIDE_INT nelts
1982 : 71 : = constant_lower_bound (TYPE_VECTOR_SUBPARTS (vec_compute_type));
1983 : 144 : while (nelts > 1)
1984 : : {
1985 : 73 : tree ret1_type = build_vector_type (TREE_TYPE (ret_type), nelts);
1986 : 73 : tree arg1_type = build_vector_type (TREE_TYPE (arg_type), nelts);
1987 : 73 : if (supportable_convert_operation (code, ret1_type, arg1_type,
1988 : : &code1))
1989 : : {
1990 : 0 : new_rhs = expand_vector_piecewise (gsi, do_vec_conversion,
1991 : : ret_type, arg1_type, arg,
1992 : : NULL_TREE, code1, false);
1993 : 0 : g = gimple_build_assign (lhs, new_rhs);
1994 : 0 : gsi_replace (gsi, g, false);
1995 : 0 : return;
1996 : : }
1997 : 73 : nelts = nelts / 2;
1998 : : }
1999 : : }
2000 : : }
2001 : 95 : else if (modifier == NARROW)
2002 : : {
2003 : 59 : switch (code)
2004 : : {
2005 : 29 : CASE_CONVERT:
2006 : 29 : code1 = VEC_PACK_TRUNC_EXPR;
2007 : 29 : optab1 = optab_for_tree_code (code1, arg_type, optab_default);
2008 : 29 : break;
2009 : 26 : case FIX_TRUNC_EXPR:
2010 : 26 : code1 = VEC_PACK_FIX_TRUNC_EXPR;
2011 : : /* The signedness is determined from output operand. */
2012 : 26 : optab1 = optab_for_tree_code (code1, ret_type, optab_default);
2013 : 26 : break;
2014 : 4 : case FLOAT_EXPR:
2015 : 4 : code1 = VEC_PACK_FLOAT_EXPR;
2016 : 4 : optab1 = optab_for_tree_code (code1, arg_type, optab_default);
2017 : 4 : break;
2018 : 0 : default:
2019 : 0 : gcc_unreachable ();
2020 : : }
2021 : :
2022 : 59 : if (optab1)
2023 : 59 : compute_type = get_compute_type (optab1, arg_type);
2024 : 59 : enum insn_code icode1;
2025 : 59 : if (VECTOR_TYPE_P (compute_type)
2026 : 54 : && ((icode1 = optab_handler (optab1, TYPE_MODE (compute_type)))
2027 : : != CODE_FOR_nothing)
2028 : 113 : && VECTOR_MODE_P (insn_data[icode1].operand[0].mode))
2029 : : {
2030 : 54 : tree cretd_type
2031 : 54 : = build_vector_type (TREE_TYPE (ret_type),
2032 : 54 : TYPE_VECTOR_SUBPARTS (compute_type) * 2);
2033 : 54 : if (insn_data[icode1].operand[0].mode == TYPE_MODE (cretd_type))
2034 : : {
2035 : 52 : if (compute_type == arg_type)
2036 : : {
2037 : 23 : new_rhs = gimplify_build2 (gsi, code1, cretd_type,
2038 : : arg, build_zero_cst (arg_type));
2039 : 46 : new_rhs = tree_vec_extract (gsi, ret_type, new_rhs,
2040 : 23 : TYPE_SIZE (ret_type),
2041 : : bitsize_int (0));
2042 : 23 : g = gimple_build_assign (lhs, new_rhs);
2043 : 23 : gsi_replace (gsi, g, false);
2044 : 23 : return;
2045 : : }
2046 : 29 : tree dcompute_type
2047 : 29 : = build_vector_type (TREE_TYPE (compute_type),
2048 : 29 : TYPE_VECTOR_SUBPARTS (compute_type) * 2);
2049 : 29 : if (TYPE_MAIN_VARIANT (dcompute_type)
2050 : 29 : == TYPE_MAIN_VARIANT (arg_type))
2051 : 27 : new_rhs = do_vec_narrow_conversion (gsi, dcompute_type, arg,
2052 : : NULL_TREE, bitsize_int (0),
2053 : : NULL_TREE, code1,
2054 : : ret_type);
2055 : : else
2056 : 2 : new_rhs = expand_vector_piecewise (gsi,
2057 : : do_vec_narrow_conversion,
2058 : : arg_type, dcompute_type,
2059 : : arg, NULL_TREE, code1,
2060 : : false, ret_type);
2061 : 29 : g = gimple_build_assign (lhs, new_rhs);
2062 : 29 : gsi_replace (gsi, g, false);
2063 : 29 : return;
2064 : : }
2065 : : }
2066 : : }
2067 : 36 : else if (modifier == WIDEN)
2068 : : {
2069 : 33 : enum tree_code code2 = ERROR_MARK;
2070 : 33 : optab optab2 = unknown_optab;
2071 : 33 : switch (code)
2072 : : {
2073 : 3 : CASE_CONVERT:
2074 : 3 : code1 = VEC_UNPACK_LO_EXPR;
2075 : 3 : code2 = VEC_UNPACK_HI_EXPR;
2076 : 3 : break;
2077 : 0 : case FIX_TRUNC_EXPR:
2078 : 0 : code1 = VEC_UNPACK_FIX_TRUNC_LO_EXPR;
2079 : 0 : code2 = VEC_UNPACK_FIX_TRUNC_HI_EXPR;
2080 : 0 : break;
2081 : 30 : case FLOAT_EXPR:
2082 : 30 : code1 = VEC_UNPACK_FLOAT_LO_EXPR;
2083 : 30 : code2 = VEC_UNPACK_FLOAT_HI_EXPR;
2084 : 30 : break;
2085 : 0 : default:
2086 : 0 : gcc_unreachable ();
2087 : : }
2088 : 33 : if (BYTES_BIG_ENDIAN)
2089 : : std::swap (code1, code2);
2090 : :
2091 : 33 : if (code == FIX_TRUNC_EXPR)
2092 : : {
2093 : : /* The signedness is determined from output operand. */
2094 : 0 : optab1 = optab_for_tree_code (code1, ret_type, optab_default);
2095 : 0 : optab2 = optab_for_tree_code (code2, ret_type, optab_default);
2096 : : }
2097 : : else
2098 : : {
2099 : 33 : optab1 = optab_for_tree_code (code1, arg_type, optab_default);
2100 : 33 : optab2 = optab_for_tree_code (code2, arg_type, optab_default);
2101 : : }
2102 : :
2103 : 33 : if (optab1 && optab2)
2104 : 33 : compute_type = get_compute_type (optab1, arg_type);
2105 : :
2106 : 33 : enum insn_code icode1, icode2;
2107 : 33 : if (VECTOR_TYPE_P (compute_type)
2108 : 29 : && ((icode1 = optab_handler (optab1, TYPE_MODE (compute_type)))
2109 : : != CODE_FOR_nothing)
2110 : 29 : && ((icode2 = optab_handler (optab2, TYPE_MODE (compute_type)))
2111 : : != CODE_FOR_nothing)
2112 : 29 : && VECTOR_MODE_P (insn_data[icode1].operand[0].mode)
2113 : 33 : && (insn_data[icode1].operand[0].mode
2114 : 29 : == insn_data[icode2].operand[0].mode))
2115 : : {
2116 : 29 : poly_uint64 nunits
2117 : 29 : = exact_div (TYPE_VECTOR_SUBPARTS (compute_type), 2);
2118 : 29 : tree cretd_type = build_vector_type (TREE_TYPE (ret_type), nunits);
2119 : 29 : if (insn_data[icode1].operand[0].mode == TYPE_MODE (cretd_type))
2120 : : {
2121 : 29 : vec<constructor_elt, va_gc> *v;
2122 : 29 : tree part_width = TYPE_SIZE (compute_type);
2123 : 29 : tree index = bitsize_int (0);
2124 : 29 : int nunits = nunits_for_known_piecewise_op (arg_type);
2125 : 29 : int delta = tree_to_uhwi (part_width) / arg_elt_bits;
2126 : 29 : int i;
2127 : 29 : location_t loc = gimple_location (gsi_stmt (*gsi));
2128 : :
2129 : 29 : if (compute_type != arg_type)
2130 : : {
2131 : 0 : if (!warning_suppressed_p (gsi_stmt (*gsi),
2132 : : OPT_Wvector_operation_performance))
2133 : 0 : warning_at (loc, OPT_Wvector_operation_performance,
2134 : : "vector operation will be expanded piecewise");
2135 : : }
2136 : : else
2137 : : {
2138 : : nunits = 1;
2139 : : delta = 1;
2140 : : }
2141 : :
2142 : 29 : vec_alloc (v, (nunits + delta - 1) / delta * 2);
2143 : 29 : bool constant_p = true;
2144 : 58 : for (i = 0; i < nunits;
2145 : 29 : i += delta, index = int_const_binop (PLUS_EXPR, index,
2146 : : part_width))
2147 : : {
2148 : 29 : tree a = arg;
2149 : 29 : if (compute_type != arg_type)
2150 : 0 : a = tree_vec_extract (gsi, compute_type, a, part_width,
2151 : : index);
2152 : 29 : tree result = gimplify_build1 (gsi, code1, cretd_type, a);
2153 : 29 : constructor_elt ce = { NULL_TREE, result };
2154 : 29 : if (!CONSTANT_CLASS_P (ce.value))
2155 : 29 : constant_p = false;
2156 : 29 : v->quick_push (ce);
2157 : 29 : ce.value = gimplify_build1 (gsi, code2, cretd_type, a);
2158 : 29 : if (!CONSTANT_CLASS_P (ce.value))
2159 : 29 : constant_p = false;
2160 : 29 : v->quick_push (ce);
2161 : : }
2162 : :
2163 : 29 : if (constant_p)
2164 : 0 : new_rhs = build_vector_from_ctor (ret_type, v);
2165 : : else
2166 : 29 : new_rhs = build_constructor (ret_type, v);
2167 : 29 : g = gimple_build_assign (lhs, new_rhs);
2168 : 29 : gsi_replace (gsi, g, false);
2169 : 29 : return;
2170 : : }
2171 : : }
2172 : : }
2173 : :
2174 : 85 : new_rhs = expand_vector_piecewise (gsi, do_vec_conversion, arg_type,
2175 : 85 : TREE_TYPE (arg_type), arg,
2176 : : NULL_TREE, code, false, ret_type);
2177 : 85 : g = gimple_build_assign (lhs, new_rhs);
2178 : 85 : gsi_replace (gsi, g, false);
2179 : 448 : }
2180 : :
2181 : : /* Process one statement. If we identify a vector operation, expand it. */
2182 : :
2183 : : static void
2184 : 97972907 : expand_vector_operations_1 (gimple_stmt_iterator *gsi)
2185 : : {
2186 : 97972907 : tree lhs, rhs1, rhs2 = NULL, type, compute_type = NULL_TREE;
2187 : 97972907 : enum tree_code code;
2188 : 97972907 : optab op = unknown_optab;
2189 : 97972907 : enum gimple_rhs_class rhs_class;
2190 : 97972907 : tree new_rhs;
2191 : :
2192 : : /* Only consider code == GIMPLE_ASSIGN. */
2193 : 97972907 : gassign *stmt = dyn_cast <gassign *> (gsi_stmt (*gsi));
2194 : 97972907 : if (!stmt)
2195 : : {
2196 : 64465497 : if (gimple_call_internal_p (gsi_stmt (*gsi), IFN_VEC_CONVERT))
2197 : 449 : expand_vector_conversion (gsi);
2198 : 64465497 : return;
2199 : : }
2200 : :
2201 : 33507410 : code = gimple_assign_rhs_code (stmt);
2202 : 33507410 : rhs_class = get_gimple_rhs_class (code);
2203 : 33507410 : lhs = gimple_assign_lhs (stmt);
2204 : :
2205 : 33507410 : if (code == VEC_PERM_EXPR)
2206 : : {
2207 : 87362 : lower_vec_perm (gsi);
2208 : 87362 : return;
2209 : : }
2210 : :
2211 : 33420048 : if (code == VEC_COND_EXPR)
2212 : : {
2213 : 20449 : expand_vector_condition (gsi);
2214 : 20449 : return;
2215 : : }
2216 : :
2217 : 33399599 : if (code == COND_EXPR
2218 : 12989 : && TREE_CODE (TREE_TYPE (gimple_assign_lhs (stmt))) == VECTOR_TYPE
2219 : 33399606 : && TYPE_MODE (TREE_TYPE (gimple_assign_lhs (stmt))) == BLKmode)
2220 : : {
2221 : 7 : expand_vector_scalar_condition (gsi);
2222 : 7 : return;
2223 : : }
2224 : :
2225 : 33399592 : if (code == CONSTRUCTOR
2226 : 1824527 : && TREE_CODE (lhs) == SSA_NAME
2227 : 150301 : && VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (lhs)))
2228 : 149749 : && !gimple_clobber_p (stmt)
2229 : 33549341 : && optimize)
2230 : : {
2231 : 147789 : optimize_vector_constructor (gsi);
2232 : 147789 : return;
2233 : : }
2234 : :
2235 : 33251803 : if (rhs_class != GIMPLE_UNARY_RHS && rhs_class != GIMPLE_BINARY_RHS)
2236 : : return;
2237 : :
2238 : 12136927 : rhs1 = gimple_assign_rhs1 (stmt);
2239 : 12136927 : if (rhs_class == GIMPLE_BINARY_RHS)
2240 : 8226736 : rhs2 = gimple_assign_rhs2 (stmt);
2241 : :
2242 : 12136927 : type = TREE_TYPE (lhs);
2243 : 12136927 : if (!VECTOR_TYPE_P (type)
2244 : 12136927 : || !VECTOR_TYPE_P (TREE_TYPE (rhs1)))
2245 : : return;
2246 : :
2247 : : /* A scalar operation pretending to be a vector one. */
2248 : 252904 : if (VECTOR_BOOLEAN_TYPE_P (type)
2249 : 34474 : && !VECTOR_MODE_P (TYPE_MODE (type))
2250 : 11806 : && TYPE_MODE (type) != BLKmode
2251 : 11502 : && (TREE_CODE_CLASS (gimple_assign_rhs_code (stmt)) != tcc_comparison
2252 : 6518 : || (VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (rhs1))
2253 : 0 : && !VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (rhs1)))
2254 : 0 : && TYPE_MODE (TREE_TYPE (rhs1)) != BLKmode)))
2255 : 4984 : return;
2256 : :
2257 : : /* If the vector operation is operating on all same vector elements
2258 : : implement it with a scalar operation and a splat if the target
2259 : : supports the scalar operation. */
2260 : 247920 : tree srhs1, srhs2 = NULL_TREE;
2261 : 247920 : if ((srhs1 = ssa_uniform_vector_p (rhs1)) != NULL_TREE
2262 : 15447 : && (rhs2 == NULL_TREE
2263 : 15207 : || (! VECTOR_TYPE_P (TREE_TYPE (rhs2))
2264 : : && (srhs2 = rhs2))
2265 : 15151 : || (srhs2 = ssa_uniform_vector_p (rhs2)) != NULL_TREE)
2266 : : /* As we query direct optabs restrict to non-convert operations. */
2267 : 249201 : && TYPE_MODE (TREE_TYPE (type)) == TYPE_MODE (TREE_TYPE (srhs1)))
2268 : : {
2269 : 1150 : op = optab_for_tree_code (code, TREE_TYPE (type), optab_scalar);
2270 : 1150 : if (op >= FIRST_NORM_OPTAB && op <= LAST_NORM_OPTAB
2271 : 1150 : && can_implement_p (op, TYPE_MODE (TREE_TYPE (type))))
2272 : : {
2273 : 875 : tree stype = TREE_TYPE (TREE_TYPE (lhs));
2274 : 875 : tree slhs = (rhs2 != NULL_TREE)
2275 : 875 : ? gimplify_build2 (gsi, code, stype, srhs1, srhs2)
2276 : 95 : : gimplify_build1 (gsi, code, stype, srhs1);
2277 : 875 : gimple_assign_set_rhs_from_tree (gsi,
2278 : : build_vector_from_val (type, slhs));
2279 : 875 : update_stmt (stmt);
2280 : 875 : return;
2281 : : }
2282 : : }
2283 : :
2284 : : /* Plain moves do not need lowering. */
2285 : 247045 : if (code == SSA_NAME
2286 : 247045 : || code == VIEW_CONVERT_EXPR
2287 : : || code == PAREN_EXPR)
2288 : : return;
2289 : :
2290 : : if (CONVERT_EXPR_CODE_P (code)
2291 : : || code == FLOAT_EXPR
2292 : : || code == FIX_TRUNC_EXPR)
2293 : : return;
2294 : :
2295 : : /* The signedness is determined from input argument. */
2296 : : if (code == VEC_UNPACK_FLOAT_HI_EXPR
2297 : : || code == VEC_UNPACK_FLOAT_LO_EXPR
2298 : : || code == VEC_PACK_FLOAT_EXPR)
2299 : : {
2300 : : /* We do not know how to scalarize those. */
2301 : : return;
2302 : : }
2303 : :
2304 : : /* For widening/narrowing vector operations, the relevant type is of the
2305 : : arguments, not the widened result. VEC_UNPACK_FLOAT_*_EXPR is
2306 : : calculated in the same way above. */
2307 : : if (code == WIDEN_SUM_EXPR
2308 : : || code == VEC_WIDEN_MULT_HI_EXPR
2309 : : || code == VEC_WIDEN_MULT_LO_EXPR
2310 : : || code == VEC_WIDEN_MULT_EVEN_EXPR
2311 : : || code == VEC_WIDEN_MULT_ODD_EXPR
2312 : : || code == VEC_UNPACK_HI_EXPR
2313 : : || code == VEC_UNPACK_LO_EXPR
2314 : : || code == VEC_UNPACK_FIX_TRUNC_HI_EXPR
2315 : : || code == VEC_UNPACK_FIX_TRUNC_LO_EXPR
2316 : : || code == VEC_PACK_TRUNC_EXPR
2317 : : || code == VEC_PACK_SAT_EXPR
2318 : : || code == VEC_PACK_FIX_TRUNC_EXPR
2319 : : || code == VEC_WIDEN_LSHIFT_HI_EXPR
2320 : : || code == VEC_WIDEN_LSHIFT_LO_EXPR)
2321 : : {
2322 : : /* We do not know how to scalarize those. */
2323 : : return;
2324 : : }
2325 : :
2326 : : /* Choose between vector shift/rotate by vector and vector shift/rotate by
2327 : : scalar */
2328 : : if (code == LSHIFT_EXPR
2329 : : || code == RSHIFT_EXPR
2330 : : || code == LROTATE_EXPR
2331 : : || code == RROTATE_EXPR)
2332 : : {
2333 : 9078 : optab opv;
2334 : :
2335 : : /* Check whether we have vector <op> {x,x,x,x} where x
2336 : : could be a scalar variable or a constant. Transform
2337 : : vector <op> {x,x,x,x} ==> vector <op> scalar. */
2338 : 9078 : if (VECTOR_INTEGER_TYPE_P (TREE_TYPE (rhs2)))
2339 : : {
2340 : 1545 : tree first;
2341 : :
2342 : 1545 : if ((first = ssa_uniform_vector_p (rhs2)) != NULL_TREE)
2343 : : {
2344 : 7 : gimple_assign_set_rhs2 (stmt, first);
2345 : 7 : update_stmt (stmt);
2346 : 7 : rhs2 = first;
2347 : : }
2348 : : }
2349 : :
2350 : 9078 : opv = optab_for_tree_code (code, type, optab_vector);
2351 : 9078 : if (VECTOR_INTEGER_TYPE_P (TREE_TYPE (rhs2)))
2352 : : op = opv;
2353 : : else
2354 : : {
2355 : 7540 : op = optab_for_tree_code (code, type, optab_scalar);
2356 : :
2357 : 7540 : compute_type = get_compute_type (op, type);
2358 : 7540 : if (compute_type == type)
2359 : : return;
2360 : : /* The rtl expander will expand vector/scalar as vector/vector
2361 : : if necessary. Pick one with wider vector type. */
2362 : 172 : tree compute_vtype = get_compute_type (opv, type);
2363 : 172 : if (subparts_gt (compute_vtype, compute_type))
2364 : : {
2365 : 0 : compute_type = compute_vtype;
2366 : 0 : op = opv;
2367 : : }
2368 : : }
2369 : :
2370 : 1710 : if (code == LROTATE_EXPR || code == RROTATE_EXPR)
2371 : : {
2372 : 39 : if (compute_type == NULL_TREE)
2373 : 6 : compute_type = get_compute_type (op, type);
2374 : 39 : if (compute_type == type)
2375 : : return;
2376 : : /* Before splitting vector rotates into scalar rotates,
2377 : : see if we can't use vector shifts and BIT_IOR_EXPR
2378 : : instead. For vector by vector rotates we'd also
2379 : : need to check BIT_AND_EXPR and NEGATE_EXPR, punt there
2380 : : for now, fold doesn't seem to create such rotates anyway. */
2381 : 33 : if (compute_type == TREE_TYPE (type)
2382 : 33 : && !VECTOR_INTEGER_TYPE_P (TREE_TYPE (rhs2)))
2383 : : {
2384 : 30 : optab oplv = vashl_optab, opl = ashl_optab;
2385 : 30 : optab oprv = vlshr_optab, opr = lshr_optab, opo = ior_optab;
2386 : 30 : tree compute_lvtype = get_compute_type (oplv, type);
2387 : 30 : tree compute_rvtype = get_compute_type (oprv, type);
2388 : 30 : tree compute_otype = get_compute_type (opo, type);
2389 : 30 : tree compute_ltype = get_compute_type (opl, type);
2390 : 30 : tree compute_rtype = get_compute_type (opr, type);
2391 : : /* The rtl expander will expand vector/scalar as vector/vector
2392 : : if necessary. Pick one with wider vector type. */
2393 : 30 : if (subparts_gt (compute_lvtype, compute_ltype))
2394 : : {
2395 : 0 : compute_ltype = compute_lvtype;
2396 : 0 : opl = oplv;
2397 : : }
2398 : 30 : if (subparts_gt (compute_rvtype, compute_rtype))
2399 : : {
2400 : 0 : compute_rtype = compute_rvtype;
2401 : 0 : opr = oprv;
2402 : : }
2403 : : /* Pick the narrowest type from LSHIFT_EXPR, RSHIFT_EXPR and
2404 : : BIT_IOR_EXPR. */
2405 : 30 : compute_type = compute_ltype;
2406 : 30 : if (subparts_gt (compute_type, compute_rtype))
2407 : 0 : compute_type = compute_rtype;
2408 : 30 : if (subparts_gt (compute_type, compute_otype))
2409 : 0 : compute_type = compute_otype;
2410 : : /* Verify all 3 operations can be performed in that type. */
2411 : 30 : if (compute_type != TREE_TYPE (type))
2412 : : {
2413 : 30 : if (!can_implement_p (opl, TYPE_MODE (compute_type))
2414 : 30 : || !can_implement_p (opr, TYPE_MODE (compute_type))
2415 : 60 : || !can_implement_p (opo, TYPE_MODE (compute_type)))
2416 : 0 : compute_type = TREE_TYPE (type);
2417 : : }
2418 : : }
2419 : : }
2420 : : }
2421 : : else
2422 : 204097 : op = optab_for_tree_code (code, type, optab_default);
2423 : :
2424 : : /* Optabs will try converting a negation into a subtraction, so
2425 : : look for it as well. TODO: negation of floating-point vectors
2426 : : might be turned into an exclusive OR toggling the sign bit. */
2427 : 205801 : if (op == unknown_optab
2428 : 205801 : && code == NEGATE_EXPR
2429 : 205801 : && INTEGRAL_TYPE_P (TREE_TYPE (type)))
2430 : 0 : op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
2431 : :
2432 : 205801 : if (compute_type == NULL_TREE)
2433 : 205629 : compute_type = get_compute_type (op, type);
2434 : 205801 : if (compute_type == type)
2435 : : return;
2436 : :
2437 : 26177 : new_rhs = expand_vector_operation (gsi, type, compute_type, stmt, code);
2438 : :
2439 : : /* Leave expression untouched for later expansion. */
2440 : 26177 : if (new_rhs == NULL_TREE)
2441 : : return;
2442 : :
2443 : 3066 : if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (new_rhs)))
2444 : 90 : new_rhs = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, TREE_TYPE (lhs),
2445 : : new_rhs);
2446 : :
2447 : : /* NOTE: We should avoid using gimple_assign_set_rhs_from_tree. One
2448 : : way to do it is change expand_vector_operation and its callees to
2449 : : return a tree_code, RHS1 and RHS2 instead of a tree. */
2450 : 3066 : gimple_assign_set_rhs_from_tree (gsi, new_rhs);
2451 : 3066 : update_stmt (gsi_stmt (*gsi));
2452 : : }
2453 : :
2454 : : /* Use this to lower vector operations introduced by the vectorizer,
2455 : : if it may need the bit-twiddling tricks implemented in this file. */
2456 : :
2457 : : static unsigned int
2458 : 1478988 : expand_vector_operations (void)
2459 : : {
2460 : 1478988 : gimple_stmt_iterator gsi;
2461 : 1478988 : basic_block bb;
2462 : 1478988 : bool cfg_changed = false;
2463 : :
2464 : 16094706 : FOR_EACH_BB_FN (bb, cfun)
2465 : : {
2466 : 127204343 : for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
2467 : : {
2468 : 97972907 : expand_vector_operations_1 (&gsi);
2469 : : /* ??? If we do not cleanup EH then we will ICE in
2470 : : verification. But in reality we have created wrong-code
2471 : : as we did not properly transition EH info and edges to
2472 : : the piecewise computations. */
2473 : 97972907 : if (maybe_clean_eh_stmt (gsi_stmt (gsi))
2474 : 97972907 : && gimple_purge_dead_eh_edges (bb))
2475 : : cfg_changed = true;
2476 : : /* If a .LOOP_DIST_ALIAS call prevailed loops got elided
2477 : : before vectorization got a chance to get at them. Simply
2478 : : fold as if loop distribution wasn't performed. */
2479 : 97972907 : if (gimple_call_internal_p (gsi_stmt (gsi), IFN_LOOP_DIST_ALIAS))
2480 : : {
2481 : 0 : fold_loop_internal_call (gsi_stmt (gsi), boolean_false_node);
2482 : 0 : cfg_changed = true;
2483 : : }
2484 : : }
2485 : : }
2486 : :
2487 : 1478988 : return cfg_changed ? TODO_cleanup_cfg : 0;
2488 : : }
2489 : :
2490 : : namespace {
2491 : :
2492 : : const pass_data pass_data_lower_vector =
2493 : : {
2494 : : GIMPLE_PASS, /* type */
2495 : : "veclower", /* name */
2496 : : OPTGROUP_VEC, /* optinfo_flags */
2497 : : TV_NONE, /* tv_id */
2498 : : PROP_cfg, /* properties_required */
2499 : : PROP_gimple_lvec, /* properties_provided */
2500 : : 0, /* properties_destroyed */
2501 : : 0, /* todo_flags_start */
2502 : : TODO_update_ssa, /* todo_flags_finish */
2503 : : };
2504 : :
2505 : : class pass_lower_vector : public gimple_opt_pass
2506 : : {
2507 : : public:
2508 : 290033 : pass_lower_vector (gcc::context *ctxt)
2509 : 580066 : : gimple_opt_pass (pass_data_lower_vector, ctxt)
2510 : : {}
2511 : :
2512 : : /* opt_pass methods: */
2513 : 1478885 : bool gate (function *fun) final override
2514 : : {
2515 : 1478885 : return !(fun->curr_properties & PROP_gimple_lvec);
2516 : : }
2517 : :
2518 : 432478 : unsigned int execute (function *) final override
2519 : : {
2520 : 432478 : return expand_vector_operations ();
2521 : : }
2522 : :
2523 : : }; // class pass_lower_vector
2524 : :
2525 : : } // anon namespace
2526 : :
2527 : : gimple_opt_pass *
2528 : 290033 : make_pass_lower_vector (gcc::context *ctxt)
2529 : : {
2530 : 290033 : return new pass_lower_vector (ctxt);
2531 : : }
2532 : :
2533 : : namespace {
2534 : :
2535 : : const pass_data pass_data_lower_vector_ssa =
2536 : : {
2537 : : GIMPLE_PASS, /* type */
2538 : : "veclower2", /* name */
2539 : : OPTGROUP_VEC, /* optinfo_flags */
2540 : : TV_NONE, /* tv_id */
2541 : : PROP_cfg, /* properties_required */
2542 : : PROP_gimple_lvec, /* properties_provided */
2543 : : 0, /* properties_destroyed */
2544 : : 0, /* todo_flags_start */
2545 : : ( TODO_update_ssa
2546 : : | TODO_cleanup_cfg ), /* todo_flags_finish */
2547 : : };
2548 : :
2549 : : class pass_lower_vector_ssa : public gimple_opt_pass
2550 : : {
2551 : : public:
2552 : 580066 : pass_lower_vector_ssa (gcc::context *ctxt)
2553 : 1160132 : : gimple_opt_pass (pass_data_lower_vector_ssa, ctxt)
2554 : : {}
2555 : :
2556 : : /* opt_pass methods: */
2557 : 290033 : opt_pass * clone () final override
2558 : : {
2559 : 290033 : return new pass_lower_vector_ssa (m_ctxt);
2560 : : }
2561 : 1046510 : unsigned int execute (function *) final override
2562 : : {
2563 : 1046510 : return expand_vector_operations ();
2564 : : }
2565 : :
2566 : : }; // class pass_lower_vector_ssa
2567 : :
2568 : : } // anon namespace
2569 : :
2570 : : gimple_opt_pass *
2571 : 290033 : make_pass_lower_vector_ssa (gcc::context *ctxt)
2572 : : {
2573 : 290033 : return new pass_lower_vector_ssa (ctxt);
2574 : : }
2575 : :
2576 : : #include "gt-tree-vect-generic.h"
|