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