OSDN Git Service

2011-01-13 Tobias Burnus <burnus@net-b.de>
[pf3gnuchains/gcc-fork.git] / gcc / tree-vect-generic.c
1 /* Lower vector operations to scalar operations.
2    Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010
3    Free Software Foundation, Inc.
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3, or (at your option) any
10 later version.
11
12 GCC is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3.  If not see
19 <http://www.gnu.org/licenses/>.  */
20
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tree.h"
25 #include "tm.h"
26 #include "langhooks.h"
27 #include "tree-flow.h"
28 #include "gimple.h"
29 #include "tree-iterator.h"
30 #include "tree-pass.h"
31 #include "flags.h"
32 #include "ggc.h"
33
34 /* Need to include rtl.h, expr.h, etc. for optabs.  */
35 #include "expr.h"
36 #include "optabs.h"
37
38 /* Build a constant of type TYPE, made of VALUE's bits replicated
39    every TYPE_SIZE (INNER_TYPE) bits to fit TYPE's precision.  */
40 static tree
41 build_replicated_const (tree type, tree inner_type, HOST_WIDE_INT value)
42 {
43   int width = tree_low_cst (TYPE_SIZE (inner_type), 1);
44   int n = HOST_BITS_PER_WIDE_INT / width;
45   unsigned HOST_WIDE_INT low, high, mask;
46   tree ret;
47
48   gcc_assert (n);
49
50   if (width == HOST_BITS_PER_WIDE_INT)
51     low = value;
52   else
53     {
54       mask = ((HOST_WIDE_INT)1 << width) - 1;
55       low = (unsigned HOST_WIDE_INT) ~0 / mask * (value & mask);
56     }
57
58   if (TYPE_PRECISION (type) < HOST_BITS_PER_WIDE_INT)
59     low &= ((HOST_WIDE_INT)1 << TYPE_PRECISION (type)) - 1, high = 0;
60   else if (TYPE_PRECISION (type) == HOST_BITS_PER_WIDE_INT)
61     high = 0;
62   else if (TYPE_PRECISION (type) == 2 * HOST_BITS_PER_WIDE_INT)
63     high = low;
64   else
65     gcc_unreachable ();
66
67   ret = build_int_cst_wide (type, low, high);
68   return ret;
69 }
70
71 static GTY(()) tree vector_inner_type;
72 static GTY(()) tree vector_last_type;
73 static GTY(()) int vector_last_nunits;
74
75 /* Return a suitable vector types made of SUBPARTS units each of mode
76    "word_mode" (the global variable).  */
77 static tree
78 build_word_mode_vector_type (int nunits)
79 {
80   if (!vector_inner_type)
81     vector_inner_type = lang_hooks.types.type_for_mode (word_mode, 1);
82   else if (vector_last_nunits == nunits)
83     {
84       gcc_assert (TREE_CODE (vector_last_type) == VECTOR_TYPE);
85       return vector_last_type;
86     }
87
88   /* We build a new type, but we canonicalize it nevertheless,
89      because it still saves some memory.  */
90   vector_last_nunits = nunits;
91   vector_last_type = type_hash_canon (nunits,
92                                       build_vector_type (vector_inner_type,
93                                                          nunits));
94   return vector_last_type;
95 }
96
97 typedef tree (*elem_op_func) (gimple_stmt_iterator *,
98                               tree, tree, tree, tree, tree, enum tree_code);
99
100 static inline tree
101 tree_vec_extract (gimple_stmt_iterator *gsi, tree type,
102                   tree t, tree bitsize, tree bitpos)
103 {
104   if (bitpos)
105     return gimplify_build3 (gsi, BIT_FIELD_REF, type, t, bitsize, bitpos);
106   else
107     return gimplify_build1 (gsi, VIEW_CONVERT_EXPR, type, t);
108 }
109
110 static tree
111 do_unop (gimple_stmt_iterator *gsi, tree inner_type, tree a,
112          tree b ATTRIBUTE_UNUSED, tree bitpos, tree bitsize,
113          enum tree_code code)
114 {
115   a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
116   return gimplify_build1 (gsi, code, inner_type, a);
117 }
118
119 static tree
120 do_binop (gimple_stmt_iterator *gsi, tree inner_type, tree a, tree b,
121           tree bitpos, tree bitsize, enum tree_code code)
122 {
123   a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
124   b = tree_vec_extract (gsi, inner_type, b, bitsize, bitpos);
125   return gimplify_build2 (gsi, code, inner_type, a, b);
126 }
127
128 /* Expand vector addition to scalars.  This does bit twiddling
129    in order to increase parallelism:
130
131    a + b = (((int) a & 0x7f7f7f7f) + ((int) b & 0x7f7f7f7f)) ^
132            (a ^ b) & 0x80808080
133
134    a - b =  (((int) a | 0x80808080) - ((int) b & 0x7f7f7f7f)) ^
135             (a ^ ~b) & 0x80808080
136
137    -b = (0x80808080 - ((int) b & 0x7f7f7f7f)) ^ (~b & 0x80808080)
138
139    This optimization should be done only if 4 vector items or more
140    fit into a word.  */
141 static tree
142 do_plus_minus (gimple_stmt_iterator *gsi, tree word_type, tree a, tree b,
143                tree bitpos ATTRIBUTE_UNUSED, tree bitsize ATTRIBUTE_UNUSED,
144                enum tree_code code)
145 {
146   tree inner_type = TREE_TYPE (TREE_TYPE (a));
147   unsigned HOST_WIDE_INT max;
148   tree low_bits, high_bits, a_low, b_low, result_low, signs;
149
150   max = GET_MODE_MASK (TYPE_MODE (inner_type));
151   low_bits = build_replicated_const (word_type, inner_type, max >> 1);
152   high_bits = build_replicated_const (word_type, inner_type, max & ~(max >> 1));
153
154   a = tree_vec_extract (gsi, word_type, a, bitsize, bitpos);
155   b = tree_vec_extract (gsi, word_type, b, bitsize, bitpos);
156
157   signs = gimplify_build2 (gsi, BIT_XOR_EXPR, word_type, a, b);
158   b_low = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, b, low_bits);
159   if (code == PLUS_EXPR)
160     a_low = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, a, low_bits);
161   else
162     {
163       a_low = gimplify_build2 (gsi, BIT_IOR_EXPR, word_type, a, high_bits);
164       signs = gimplify_build1 (gsi, BIT_NOT_EXPR, word_type, signs);
165     }
166
167   signs = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, signs, high_bits);
168   result_low = gimplify_build2 (gsi, code, word_type, a_low, b_low);
169   return gimplify_build2 (gsi, BIT_XOR_EXPR, word_type, result_low, signs);
170 }
171
172 static tree
173 do_negate (gimple_stmt_iterator *gsi, tree word_type, tree b,
174            tree unused ATTRIBUTE_UNUSED, tree bitpos ATTRIBUTE_UNUSED,
175            tree bitsize ATTRIBUTE_UNUSED,
176            enum tree_code code ATTRIBUTE_UNUSED)
177 {
178   tree inner_type = TREE_TYPE (TREE_TYPE (b));
179   HOST_WIDE_INT max;
180   tree low_bits, high_bits, b_low, result_low, signs;
181
182   max = GET_MODE_MASK (TYPE_MODE (inner_type));
183   low_bits = build_replicated_const (word_type, inner_type, max >> 1);
184   high_bits = build_replicated_const (word_type, inner_type, max & ~(max >> 1));
185
186   b = tree_vec_extract (gsi, word_type, b, bitsize, bitpos);
187
188   b_low = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, b, low_bits);
189   signs = gimplify_build1 (gsi, BIT_NOT_EXPR, word_type, b);
190   signs = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, signs, high_bits);
191   result_low = gimplify_build2 (gsi, MINUS_EXPR, word_type, high_bits, b_low);
192   return gimplify_build2 (gsi, BIT_XOR_EXPR, word_type, result_low, signs);
193 }
194
195 /* Expand a vector operation to scalars, by using many operations
196    whose type is the vector type's inner type.  */
197 static tree
198 expand_vector_piecewise (gimple_stmt_iterator *gsi, elem_op_func f,
199                          tree type, tree inner_type,
200                          tree a, tree b, enum tree_code code)
201 {
202   VEC(constructor_elt,gc) *v;
203   tree part_width = TYPE_SIZE (inner_type);
204   tree index = bitsize_int (0);
205   int nunits = TYPE_VECTOR_SUBPARTS (type);
206   int delta = tree_low_cst (part_width, 1)
207               / tree_low_cst (TYPE_SIZE (TREE_TYPE (type)), 1);
208   int i;
209
210   v = VEC_alloc(constructor_elt, gc, (nunits + delta - 1) / delta);
211   for (i = 0; i < nunits;
212        i += delta, index = int_const_binop (PLUS_EXPR, index, part_width, 0))
213     {
214       tree result = f (gsi, inner_type, a, b, index, part_width, code);
215       constructor_elt *ce = VEC_quick_push (constructor_elt, v, NULL);
216       ce->index = NULL_TREE;
217       ce->value = result;
218     }
219
220   return build_constructor (type, v);
221 }
222
223 /* Expand a vector operation to scalars with the freedom to use
224    a scalar integer type, or to use a different size for the items
225    in the vector type.  */
226 static tree
227 expand_vector_parallel (gimple_stmt_iterator *gsi, elem_op_func f, tree type,
228                         tree a, tree b,
229                         enum tree_code code)
230 {
231   tree result, compute_type;
232   enum machine_mode mode;
233   int n_words = tree_low_cst (TYPE_SIZE_UNIT (type), 1) / UNITS_PER_WORD;
234
235   /* We have three strategies.  If the type is already correct, just do
236      the operation an element at a time.  Else, if the vector is wider than
237      one word, do it a word at a time; finally, if the vector is smaller
238      than one word, do it as a scalar.  */
239   if (TYPE_MODE (TREE_TYPE (type)) == word_mode)
240      return expand_vector_piecewise (gsi, f,
241                                      type, TREE_TYPE (type),
242                                      a, b, code);
243   else if (n_words > 1)
244     {
245       tree word_type = build_word_mode_vector_type (n_words);
246       result = expand_vector_piecewise (gsi, f,
247                                         word_type, TREE_TYPE (word_type),
248                                         a, b, code);
249       result = force_gimple_operand_gsi (gsi, result, true, NULL, true,
250                                          GSI_SAME_STMT);
251     }
252   else
253     {
254       /* Use a single scalar operation with a mode no wider than word_mode.  */
255       mode = mode_for_size (tree_low_cst (TYPE_SIZE (type), 1), MODE_INT, 0);
256       compute_type = lang_hooks.types.type_for_mode (mode, 1);
257       result = f (gsi, compute_type, a, b, NULL_TREE, NULL_TREE, code);
258     }
259
260   return result;
261 }
262
263 /* Expand a vector operation to scalars; for integer types we can use
264    special bit twiddling tricks to do the sums a word at a time, using
265    function F_PARALLEL instead of F.  These tricks are done only if
266    they can process at least four items, that is, only if the vector
267    holds at least four items and if a word can hold four items.  */
268 static tree
269 expand_vector_addition (gimple_stmt_iterator *gsi,
270                         elem_op_func f, elem_op_func f_parallel,
271                         tree type, tree a, tree b, enum tree_code code)
272 {
273   int parts_per_word = UNITS_PER_WORD
274                        / tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (type)), 1);
275
276   if (INTEGRAL_TYPE_P (TREE_TYPE (type))
277       && parts_per_word >= 4
278       && TYPE_VECTOR_SUBPARTS (type) >= 4)
279     return expand_vector_parallel (gsi, f_parallel,
280                                    type, a, b, code);
281   else
282     return expand_vector_piecewise (gsi, f,
283                                     type, TREE_TYPE (type),
284                                     a, b, code);
285 }
286
287 /* Check if vector VEC consists of all the equal elements and
288    that the number of elements corresponds to the type of VEC.
289    The function returns first element of the vector
290    or NULL_TREE if the vector is not uniform.  */
291 static tree
292 uniform_vector_p (tree vec)
293 {
294   tree first, t, els;
295   unsigned i;
296
297   if (vec == NULL_TREE)
298     return NULL_TREE;
299
300   if (TREE_CODE (vec) == VECTOR_CST)
301     {
302       els = TREE_VECTOR_CST_ELTS (vec);
303       first = TREE_VALUE (els);
304       els = TREE_CHAIN (els);
305
306       for (t = els; t; t = TREE_CHAIN (t))
307         if (!operand_equal_p (first, TREE_VALUE (t), 0))
308           return NULL_TREE;
309
310       return first;
311     }
312
313   else if (TREE_CODE (vec) == CONSTRUCTOR)
314     {
315       first = error_mark_node;
316
317       FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (vec), i, t)
318         {
319           if (i == 0)
320             {
321               first = t;
322               continue;
323             }
324           if (!operand_equal_p (first, t, 0))
325             return NULL_TREE;
326         }
327       if (i != TYPE_VECTOR_SUBPARTS (TREE_TYPE (vec)))
328         return NULL_TREE;
329       
330       return first;
331     }
332   
333   return NULL_TREE;
334 }
335
336 static tree
337 expand_vector_operation (gimple_stmt_iterator *gsi, tree type, tree compute_type,
338                          gimple assign, enum tree_code code)
339 {
340   enum machine_mode compute_mode = TYPE_MODE (compute_type);
341
342   /* If the compute mode is not a vector mode (hence we are not decomposing
343      a BLKmode vector to smaller, hardware-supported vectors), we may want
344      to expand the operations in parallel.  */
345   if (GET_MODE_CLASS (compute_mode) != MODE_VECTOR_INT
346       && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_FLOAT
347       && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_FRACT
348       && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_UFRACT
349       && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_ACCUM
350       && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_UACCUM)
351     switch (code)
352       {
353       case PLUS_EXPR:
354       case MINUS_EXPR:
355         if (!TYPE_OVERFLOW_TRAPS (type))
356           return expand_vector_addition (gsi, do_binop, do_plus_minus, type,
357                                          gimple_assign_rhs1 (assign),
358                                          gimple_assign_rhs2 (assign), code);
359         break;
360
361       case NEGATE_EXPR:
362         if (!TYPE_OVERFLOW_TRAPS (type))
363           return expand_vector_addition (gsi, do_unop, do_negate, type,
364                                          gimple_assign_rhs1 (assign),
365                                          NULL_TREE, code);
366         break;
367
368       case BIT_AND_EXPR:
369       case BIT_IOR_EXPR:
370       case BIT_XOR_EXPR:
371         return expand_vector_parallel (gsi, do_binop, type,
372                                        gimple_assign_rhs1 (assign),
373                                        gimple_assign_rhs2 (assign), code);
374
375       case BIT_NOT_EXPR:
376         return expand_vector_parallel (gsi, do_unop, type,
377                                        gimple_assign_rhs1 (assign),
378                                        NULL_TREE, code);
379
380       default:
381         break;
382       }
383
384   if (TREE_CODE_CLASS (code) == tcc_unary)
385     return expand_vector_piecewise (gsi, do_unop, type, compute_type,
386                                     gimple_assign_rhs1 (assign),
387                                     NULL_TREE, code);
388   else
389     return expand_vector_piecewise (gsi, do_binop, type, compute_type,
390                                     gimple_assign_rhs1 (assign),
391                                     gimple_assign_rhs2 (assign), code);
392 }
393 \f
394 /* Return a type for the widest vector mode whose components are of mode
395    INNER_MODE, or NULL_TREE if none is found.
396    SATP is true for saturating fixed-point types.  */
397
398 static tree
399 type_for_widest_vector_mode (enum machine_mode inner_mode, optab op, int satp)
400 {
401   enum machine_mode best_mode = VOIDmode, mode;
402   int best_nunits = 0;
403
404   if (SCALAR_FLOAT_MODE_P (inner_mode))
405     mode = MIN_MODE_VECTOR_FLOAT;
406   else if (SCALAR_FRACT_MODE_P (inner_mode))
407     mode = MIN_MODE_VECTOR_FRACT;
408   else if (SCALAR_UFRACT_MODE_P (inner_mode))
409     mode = MIN_MODE_VECTOR_UFRACT;
410   else if (SCALAR_ACCUM_MODE_P (inner_mode))
411     mode = MIN_MODE_VECTOR_ACCUM;
412   else if (SCALAR_UACCUM_MODE_P (inner_mode))
413     mode = MIN_MODE_VECTOR_UACCUM;
414   else
415     mode = MIN_MODE_VECTOR_INT;
416
417   for (; mode != VOIDmode; mode = GET_MODE_WIDER_MODE (mode))
418     if (GET_MODE_INNER (mode) == inner_mode
419         && GET_MODE_NUNITS (mode) > best_nunits
420         && optab_handler (op, mode) != CODE_FOR_nothing)
421       best_mode = mode, best_nunits = GET_MODE_NUNITS (mode);
422
423   if (best_mode == VOIDmode)
424     return NULL_TREE;
425   else
426     {
427       /* For fixed-point modes, we need to pass satp as the 2nd parameter.  */
428       if (ALL_FIXED_POINT_MODE_P (best_mode))
429         return lang_hooks.types.type_for_mode (best_mode, satp);
430
431       return lang_hooks.types.type_for_mode (best_mode, 1);
432     }
433 }
434
435 /* Process one statement.  If we identify a vector operation, expand it.  */
436
437 static void
438 expand_vector_operations_1 (gimple_stmt_iterator *gsi)
439 {
440   gimple stmt = gsi_stmt (*gsi);
441   tree lhs, rhs1, rhs2 = NULL, type, compute_type;
442   enum tree_code code;
443   enum machine_mode compute_mode;
444   optab op = NULL;
445   enum gimple_rhs_class rhs_class;
446   tree new_rhs;
447
448   if (gimple_code (stmt) != GIMPLE_ASSIGN)
449     return;
450
451   code = gimple_assign_rhs_code (stmt);
452   rhs_class = get_gimple_rhs_class (code);
453
454   if (rhs_class != GIMPLE_UNARY_RHS && rhs_class != GIMPLE_BINARY_RHS)
455     return;
456
457   lhs = gimple_assign_lhs (stmt);
458   rhs1 = gimple_assign_rhs1 (stmt);
459   type = gimple_expr_type (stmt);
460   if (rhs_class == GIMPLE_BINARY_RHS)
461     rhs2 = gimple_assign_rhs2 (stmt);
462
463   if (TREE_CODE (type) != VECTOR_TYPE)
464     return;
465
466   if (code == NOP_EXPR
467       || code == FLOAT_EXPR
468       || code == FIX_TRUNC_EXPR
469       || code == VIEW_CONVERT_EXPR)
470     return;
471
472   gcc_assert (code != CONVERT_EXPR);
473
474   /* The signedness is determined from input argument.  */
475   if (code == VEC_UNPACK_FLOAT_HI_EXPR
476       || code == VEC_UNPACK_FLOAT_LO_EXPR)
477     type = TREE_TYPE (rhs1);
478
479   /* Choose between vector shift/rotate by vector and vector shift/rotate by
480      scalar */
481   if (code == LSHIFT_EXPR
482       || code == RSHIFT_EXPR
483       || code == LROTATE_EXPR
484       || code == RROTATE_EXPR)
485     {
486       bool vector_scalar_shift;
487       op = optab_for_tree_code (code, type, optab_scalar);
488       
489       /* Vector/Scalar shift is supported.  */
490       vector_scalar_shift = (op && (optab_handler (op, TYPE_MODE (type)) 
491                                     != CODE_FOR_nothing));
492
493       /* If the 2nd argument is vector, we need a vector/vector shift.
494          Except all the elements in the second vector are the same.  */
495       if (VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (rhs2))))
496         {
497           tree first;
498           gimple def_stmt;
499
500           /* Check whether we have vector <op> {x,x,x,x} where x
501              could be a scalar variable or a constant. Transform
502              vector <op> {x,x,x,x} ==> vector <op> scalar.  */
503           if (vector_scalar_shift 
504               && ((TREE_CODE (rhs2) == VECTOR_CST
505                    && (first = uniform_vector_p (rhs2)) != NULL_TREE)
506                   || (TREE_CODE (rhs2) == SSA_NAME 
507                       && (def_stmt = SSA_NAME_DEF_STMT (rhs2))
508                       && gimple_assign_single_p (def_stmt)
509                       && (first = uniform_vector_p
510                             (gimple_assign_rhs1 (def_stmt))) != NULL_TREE)))
511             {
512               gimple_assign_set_rhs2 (stmt, first);
513               update_stmt (stmt);
514               rhs2 = first;
515             }
516           else
517             op = optab_for_tree_code (code, type, optab_vector);
518         }
519     
520       /* Try for a vector/scalar shift, and if we don't have one, see if we
521          have a vector/vector shift */
522       else if (!vector_scalar_shift)
523         {
524           op = optab_for_tree_code (code, type, optab_vector);
525
526           if (op && (optab_handler (op, TYPE_MODE (type)) 
527                      != CODE_FOR_nothing))
528             {
529               /* Transform vector <op> scalar => vector <op> {x,x,x,x}.  */
530               int n_parts = TYPE_VECTOR_SUBPARTS (type);
531               int part_size = tree_low_cst (TYPE_SIZE (TREE_TYPE (type)), 1);
532               tree part_type = lang_hooks.types.type_for_size (part_size, 1);
533               tree vect_type = build_vector_type (part_type, n_parts);
534
535               rhs2 = fold_convert (part_type, rhs2);
536               rhs2 = build_vector_from_val (vect_type, rhs2);
537               gimple_assign_set_rhs2 (stmt, rhs2);
538               update_stmt (stmt);
539             }
540         }
541     }
542   else
543     op = optab_for_tree_code (code, type, optab_default);
544
545   /* For widening/narrowing vector operations, the relevant type is of the
546      arguments, not the widened result.  VEC_UNPACK_FLOAT_*_EXPR is
547      calculated in the same way above.  */
548   if (code == WIDEN_SUM_EXPR
549       || code == VEC_WIDEN_MULT_HI_EXPR
550       || code == VEC_WIDEN_MULT_LO_EXPR
551       || code == VEC_UNPACK_HI_EXPR
552       || code == VEC_UNPACK_LO_EXPR
553       || code == VEC_PACK_TRUNC_EXPR
554       || code == VEC_PACK_SAT_EXPR
555       || code == VEC_PACK_FIX_TRUNC_EXPR)
556     type = TREE_TYPE (rhs1);
557
558   /* Optabs will try converting a negation into a subtraction, so
559      look for it as well.  TODO: negation of floating-point vectors
560      might be turned into an exclusive OR toggling the sign bit.  */
561   if (op == NULL
562       && code == NEGATE_EXPR
563       && INTEGRAL_TYPE_P (TREE_TYPE (type)))
564     op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
565
566   /* For very wide vectors, try using a smaller vector mode.  */
567   compute_type = type;
568   if (TYPE_MODE (type) == BLKmode && op)
569     {
570       tree vector_compute_type
571         = type_for_widest_vector_mode (TYPE_MODE (TREE_TYPE (type)), op,
572                                        TYPE_SATURATING (TREE_TYPE (type)));
573       if (vector_compute_type != NULL_TREE
574           && (TYPE_VECTOR_SUBPARTS (vector_compute_type)
575               < TYPE_VECTOR_SUBPARTS (compute_type)))
576         compute_type = vector_compute_type;
577     }
578
579   /* If we are breaking a BLKmode vector into smaller pieces,
580      type_for_widest_vector_mode has already looked into the optab,
581      so skip these checks.  */
582   if (compute_type == type)
583     {
584       compute_mode = TYPE_MODE (compute_type);
585       if ((GET_MODE_CLASS (compute_mode) == MODE_VECTOR_INT
586            || GET_MODE_CLASS (compute_mode) == MODE_VECTOR_FLOAT
587            || GET_MODE_CLASS (compute_mode) == MODE_VECTOR_FRACT
588            || GET_MODE_CLASS (compute_mode) == MODE_VECTOR_UFRACT
589            || GET_MODE_CLASS (compute_mode) == MODE_VECTOR_ACCUM
590            || GET_MODE_CLASS (compute_mode) == MODE_VECTOR_UACCUM)
591           && op != NULL
592           && optab_handler (op, compute_mode) != CODE_FOR_nothing)
593         return;
594       else
595         /* There is no operation in hardware, so fall back to scalars.  */
596         compute_type = TREE_TYPE (type);
597     }
598
599   gcc_assert (code != VEC_LSHIFT_EXPR && code != VEC_RSHIFT_EXPR);
600   new_rhs = expand_vector_operation (gsi, type, compute_type, stmt, code);
601   if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (new_rhs)))
602     new_rhs = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, TREE_TYPE (lhs),
603                                new_rhs);
604
605   /* NOTE:  We should avoid using gimple_assign_set_rhs_from_tree. One
606      way to do it is change expand_vector_operation and its callees to
607      return a tree_code, RHS1 and RHS2 instead of a tree. */
608   gimple_assign_set_rhs_from_tree (gsi, new_rhs);
609
610   gimple_set_modified (gsi_stmt (*gsi), true);
611 }
612 \f
613 /* Use this to lower vector operations introduced by the vectorizer,
614    if it may need the bit-twiddling tricks implemented in this file.  */
615
616 static bool
617 gate_expand_vector_operations (void)
618 {
619   return flag_tree_vectorize != 0;
620 }
621
622 static unsigned int
623 expand_vector_operations (void)
624 {
625   gimple_stmt_iterator gsi;
626   basic_block bb;
627
628   FOR_EACH_BB (bb)
629     {
630       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
631         {
632           expand_vector_operations_1 (&gsi);
633           update_stmt_if_modified (gsi_stmt (gsi));
634         }
635     }
636   return 0;
637 }
638
639 struct gimple_opt_pass pass_lower_vector =
640 {
641  {
642   GIMPLE_PASS,
643   "veclower",                           /* name */
644   0,                                    /* gate */
645   expand_vector_operations,             /* execute */
646   NULL,                                 /* sub */
647   NULL,                                 /* next */
648   0,                                    /* static_pass_number */
649   TV_NONE,                              /* tv_id */
650   PROP_cfg,                             /* properties_required */
651   0,                                    /* properties_provided */
652   0,                                    /* properties_destroyed */
653   0,                                    /* todo_flags_start */
654   TODO_dump_func | TODO_update_ssa      /* todo_flags_finish */
655     | TODO_verify_ssa
656     | TODO_verify_stmts | TODO_verify_flow
657  }
658 };
659
660 struct gimple_opt_pass pass_lower_vector_ssa =
661 {
662  {
663   GIMPLE_PASS,
664   "veclower2",                          /* name */
665   gate_expand_vector_operations,        /* gate */
666   expand_vector_operations,             /* execute */
667   NULL,                                 /* sub */
668   NULL,                                 /* next */
669   0,                                    /* static_pass_number */
670   TV_NONE,                              /* tv_id */
671   PROP_cfg,                             /* properties_required */
672   0,                                    /* properties_provided */
673   0,                                    /* properties_destroyed */
674   0,                                    /* todo_flags_start */
675   TODO_dump_func | TODO_update_ssa      /* todo_flags_finish */
676     | TODO_verify_ssa
677     | TODO_verify_stmts | TODO_verify_flow
678  }
679 };
680
681 #include "gt-tree-vect-generic.h"