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