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