OSDN Git Service

2011-07-01 Richard Guenther <rguenther@suse.de>
[pf3gnuchains/gcc-fork.git] / gcc / tree-vect-stmts.c
1 /* Statement Analysis and Transformation for Vectorization
2    Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
3    Free Software Foundation, Inc.
4    Contributed by Dorit Naishlos <dorit@il.ibm.com>
5    and Ira Rosen <irar@il.ibm.com>
6
7 This file is part of GCC.
8
9 GCC is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 3, or (at your option) any later
12 version.
13
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
17 for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3.  If not see
21 <http://www.gnu.org/licenses/>.  */
22
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "tm.h"
27 #include "ggc.h"
28 #include "tree.h"
29 #include "target.h"
30 #include "basic-block.h"
31 #include "tree-pretty-print.h"
32 #include "gimple-pretty-print.h"
33 #include "tree-flow.h"
34 #include "tree-dump.h"
35 #include "cfgloop.h"
36 #include "cfglayout.h"
37 #include "expr.h"
38 #include "recog.h"
39 #include "optabs.h"
40 #include "diagnostic-core.h"
41 #include "tree-vectorizer.h"
42 #include "langhooks.h"
43
44
45 /* Return a variable of type ELEM_TYPE[NELEMS].  */
46
47 static tree
48 create_vector_array (tree elem_type, unsigned HOST_WIDE_INT nelems)
49 {
50   return create_tmp_var (build_array_type_nelts (elem_type, nelems),
51                          "vect_array");
52 }
53
54 /* ARRAY is an array of vectors created by create_vector_array.
55    Return an SSA_NAME for the vector in index N.  The reference
56    is part of the vectorization of STMT and the vector is associated
57    with scalar destination SCALAR_DEST.  */
58
59 static tree
60 read_vector_array (gimple stmt, gimple_stmt_iterator *gsi, tree scalar_dest,
61                    tree array, unsigned HOST_WIDE_INT n)
62 {
63   tree vect_type, vect, vect_name, array_ref;
64   gimple new_stmt;
65
66   gcc_assert (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE);
67   vect_type = TREE_TYPE (TREE_TYPE (array));
68   vect = vect_create_destination_var (scalar_dest, vect_type);
69   array_ref = build4 (ARRAY_REF, vect_type, array,
70                       build_int_cst (size_type_node, n),
71                       NULL_TREE, NULL_TREE);
72
73   new_stmt = gimple_build_assign (vect, array_ref);
74   vect_name = make_ssa_name (vect, new_stmt);
75   gimple_assign_set_lhs (new_stmt, vect_name);
76   vect_finish_stmt_generation (stmt, new_stmt, gsi);
77   mark_symbols_for_renaming (new_stmt);
78
79   return vect_name;
80 }
81
82 /* ARRAY is an array of vectors created by create_vector_array.
83    Emit code to store SSA_NAME VECT in index N of the array.
84    The store is part of the vectorization of STMT.  */
85
86 static void
87 write_vector_array (gimple stmt, gimple_stmt_iterator *gsi, tree vect,
88                     tree array, unsigned HOST_WIDE_INT n)
89 {
90   tree array_ref;
91   gimple new_stmt;
92
93   array_ref = build4 (ARRAY_REF, TREE_TYPE (vect), array,
94                       build_int_cst (size_type_node, n),
95                       NULL_TREE, NULL_TREE);
96
97   new_stmt = gimple_build_assign (array_ref, vect);
98   vect_finish_stmt_generation (stmt, new_stmt, gsi);
99   mark_symbols_for_renaming (new_stmt);
100 }
101
102 /* PTR is a pointer to an array of type TYPE.  Return a representation
103    of *PTR.  The memory reference replaces those in FIRST_DR
104    (and its group).  */
105
106 static tree
107 create_array_ref (tree type, tree ptr, struct data_reference *first_dr)
108 {
109   struct ptr_info_def *pi;
110   tree mem_ref, alias_ptr_type;
111
112   alias_ptr_type = reference_alias_ptr_type (DR_REF (first_dr));
113   mem_ref = build2 (MEM_REF, type, ptr, build_int_cst (alias_ptr_type, 0));
114   /* Arrays have the same alignment as their type.  */
115   pi = get_ptr_info (ptr);
116   pi->align = TYPE_ALIGN_UNIT (type);
117   pi->misalign = 0;
118   return mem_ref;
119 }
120
121 /* Utility functions used by vect_mark_stmts_to_be_vectorized.  */
122
123 /* Function vect_mark_relevant.
124
125    Mark STMT as "relevant for vectorization" and add it to WORKLIST.  */
126
127 static void
128 vect_mark_relevant (VEC(gimple,heap) **worklist, gimple stmt,
129                     enum vect_relevant relevant, bool live_p,
130                     bool used_in_pattern)
131 {
132   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
133   enum vect_relevant save_relevant = STMT_VINFO_RELEVANT (stmt_info);
134   bool save_live_p = STMT_VINFO_LIVE_P (stmt_info);
135   gimple pattern_stmt;
136
137   if (vect_print_dump_info (REPORT_DETAILS))
138     fprintf (vect_dump, "mark relevant %d, live %d.", relevant, live_p);
139
140   /* If this stmt is an original stmt in a pattern, we might need to mark its
141      related pattern stmt instead of the original stmt.  However, such stmts
142      may have their own uses that are not in any pattern, in such cases the
143      stmt itself should be marked.  */
144   if (STMT_VINFO_IN_PATTERN_P (stmt_info))
145     {
146       bool found = false;
147       if (!used_in_pattern)
148         {
149           imm_use_iterator imm_iter;
150           use_operand_p use_p;
151           gimple use_stmt;
152           tree lhs;
153
154           if (is_gimple_assign (stmt))
155             lhs = gimple_assign_lhs (stmt);
156           else
157             lhs = gimple_call_lhs (stmt);
158
159           /* This use is out of pattern use, if LHS has other uses that are
160              pattern uses, we should mark the stmt itself, and not the pattern
161              stmt.  */
162           FOR_EACH_IMM_USE_FAST (use_p, imm_iter, lhs)
163             {
164               if (is_gimple_debug (USE_STMT (use_p)))
165                 continue;
166               use_stmt = USE_STMT (use_p);
167
168               if (vinfo_for_stmt (use_stmt)
169                   && STMT_VINFO_IN_PATTERN_P (vinfo_for_stmt (use_stmt)))
170                 {
171                   found = true;
172                   break;
173                 }
174             }
175         }
176
177       if (!found)
178         {
179           /* This is the last stmt in a sequence that was detected as a
180              pattern that can potentially be vectorized.  Don't mark the stmt
181              as relevant/live because it's not going to be vectorized.
182              Instead mark the pattern-stmt that replaces it.  */
183
184           pattern_stmt = STMT_VINFO_RELATED_STMT (stmt_info);
185
186           if (vect_print_dump_info (REPORT_DETAILS))
187             fprintf (vect_dump, "last stmt in pattern. don't mark"
188                                 " relevant/live.");
189           stmt_info = vinfo_for_stmt (pattern_stmt);
190           gcc_assert (STMT_VINFO_RELATED_STMT (stmt_info) == stmt);
191           save_relevant = STMT_VINFO_RELEVANT (stmt_info);
192           save_live_p = STMT_VINFO_LIVE_P (stmt_info);
193           stmt = pattern_stmt;
194         }
195     }
196
197   STMT_VINFO_LIVE_P (stmt_info) |= live_p;
198   if (relevant > STMT_VINFO_RELEVANT (stmt_info))
199     STMT_VINFO_RELEVANT (stmt_info) = relevant;
200
201   if (STMT_VINFO_RELEVANT (stmt_info) == save_relevant
202       && STMT_VINFO_LIVE_P (stmt_info) == save_live_p)
203     {
204       if (vect_print_dump_info (REPORT_DETAILS))
205         fprintf (vect_dump, "already marked relevant/live.");
206       return;
207     }
208
209   VEC_safe_push (gimple, heap, *worklist, stmt);
210 }
211
212
213 /* Function vect_stmt_relevant_p.
214
215    Return true if STMT in loop that is represented by LOOP_VINFO is
216    "relevant for vectorization".
217
218    A stmt is considered "relevant for vectorization" if:
219    - it has uses outside the loop.
220    - it has vdefs (it alters memory).
221    - control stmts in the loop (except for the exit condition).
222
223    CHECKME: what other side effects would the vectorizer allow?  */
224
225 static bool
226 vect_stmt_relevant_p (gimple stmt, loop_vec_info loop_vinfo,
227                       enum vect_relevant *relevant, bool *live_p)
228 {
229   struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
230   ssa_op_iter op_iter;
231   imm_use_iterator imm_iter;
232   use_operand_p use_p;
233   def_operand_p def_p;
234
235   *relevant = vect_unused_in_scope;
236   *live_p = false;
237
238   /* cond stmt other than loop exit cond.  */
239   if (is_ctrl_stmt (stmt)
240       && STMT_VINFO_TYPE (vinfo_for_stmt (stmt))
241          != loop_exit_ctrl_vec_info_type)
242     *relevant = vect_used_in_scope;
243
244   /* changing memory.  */
245   if (gimple_code (stmt) != GIMPLE_PHI)
246     if (gimple_vdef (stmt))
247       {
248         if (vect_print_dump_info (REPORT_DETAILS))
249           fprintf (vect_dump, "vec_stmt_relevant_p: stmt has vdefs.");
250         *relevant = vect_used_in_scope;
251       }
252
253   /* uses outside the loop.  */
254   FOR_EACH_PHI_OR_STMT_DEF (def_p, stmt, op_iter, SSA_OP_DEF)
255     {
256       FOR_EACH_IMM_USE_FAST (use_p, imm_iter, DEF_FROM_PTR (def_p))
257         {
258           basic_block bb = gimple_bb (USE_STMT (use_p));
259           if (!flow_bb_inside_loop_p (loop, bb))
260             {
261               if (vect_print_dump_info (REPORT_DETAILS))
262                 fprintf (vect_dump, "vec_stmt_relevant_p: used out of loop.");
263
264               if (is_gimple_debug (USE_STMT (use_p)))
265                 continue;
266
267               /* We expect all such uses to be in the loop exit phis
268                  (because of loop closed form)   */
269               gcc_assert (gimple_code (USE_STMT (use_p)) == GIMPLE_PHI);
270               gcc_assert (bb == single_exit (loop)->dest);
271
272               *live_p = true;
273             }
274         }
275     }
276
277   return (*live_p || *relevant);
278 }
279
280
281 /* Function exist_non_indexing_operands_for_use_p
282
283    USE is one of the uses attached to STMT.  Check if USE is
284    used in STMT for anything other than indexing an array.  */
285
286 static bool
287 exist_non_indexing_operands_for_use_p (tree use, gimple stmt)
288 {
289   tree operand;
290   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
291
292   /* USE corresponds to some operand in STMT.  If there is no data
293      reference in STMT, then any operand that corresponds to USE
294      is not indexing an array.  */
295   if (!STMT_VINFO_DATA_REF (stmt_info))
296     return true;
297
298   /* STMT has a data_ref. FORNOW this means that its of one of
299      the following forms:
300      -1- ARRAY_REF = var
301      -2- var = ARRAY_REF
302      (This should have been verified in analyze_data_refs).
303
304      'var' in the second case corresponds to a def, not a use,
305      so USE cannot correspond to any operands that are not used
306      for array indexing.
307
308      Therefore, all we need to check is if STMT falls into the
309      first case, and whether var corresponds to USE.  */
310
311   if (!gimple_assign_copy_p (stmt))
312     return false;
313   if (TREE_CODE (gimple_assign_lhs (stmt)) == SSA_NAME)
314     return false;
315   operand = gimple_assign_rhs1 (stmt);
316   if (TREE_CODE (operand) != SSA_NAME)
317     return false;
318
319   if (operand == use)
320     return true;
321
322   return false;
323 }
324
325
326 /*
327    Function process_use.
328
329    Inputs:
330    - a USE in STMT in a loop represented by LOOP_VINFO
331    - LIVE_P, RELEVANT - enum values to be set in the STMT_VINFO of the stmt
332      that defined USE.  This is done by calling mark_relevant and passing it
333      the WORKLIST (to add DEF_STMT to the WORKLIST in case it is relevant).
334
335    Outputs:
336    Generally, LIVE_P and RELEVANT are used to define the liveness and
337    relevance info of the DEF_STMT of this USE:
338        STMT_VINFO_LIVE_P (DEF_STMT_info) <-- live_p
339        STMT_VINFO_RELEVANT (DEF_STMT_info) <-- relevant
340    Exceptions:
341    - case 1: If USE is used only for address computations (e.g. array indexing),
342    which does not need to be directly vectorized, then the liveness/relevance
343    of the respective DEF_STMT is left unchanged.
344    - case 2: If STMT is a reduction phi and DEF_STMT is a reduction stmt, we
345    skip DEF_STMT cause it had already been processed.
346    - case 3: If DEF_STMT and STMT are in different nests, then  "relevant" will
347    be modified accordingly.
348
349    Return true if everything is as expected. Return false otherwise.  */
350
351 static bool
352 process_use (gimple stmt, tree use, loop_vec_info loop_vinfo, bool live_p,
353              enum vect_relevant relevant, VEC(gimple,heap) **worklist)
354 {
355   struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
356   stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt);
357   stmt_vec_info dstmt_vinfo;
358   basic_block bb, def_bb;
359   tree def;
360   gimple def_stmt;
361   enum vect_def_type dt;
362
363   /* case 1: we are only interested in uses that need to be vectorized.  Uses
364      that are used for address computation are not considered relevant.  */
365   if (!exist_non_indexing_operands_for_use_p (use, stmt))
366      return true;
367
368   if (!vect_is_simple_use (use, loop_vinfo, NULL, &def_stmt, &def, &dt))
369     {
370       if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
371         fprintf (vect_dump, "not vectorized: unsupported use in stmt.");
372       return false;
373     }
374
375   if (!def_stmt || gimple_nop_p (def_stmt))
376     return true;
377
378   def_bb = gimple_bb (def_stmt);
379   if (!flow_bb_inside_loop_p (loop, def_bb))
380     {
381       if (vect_print_dump_info (REPORT_DETAILS))
382         fprintf (vect_dump, "def_stmt is out of loop.");
383       return true;
384     }
385
386   /* case 2: A reduction phi (STMT) defined by a reduction stmt (DEF_STMT).
387      DEF_STMT must have already been processed, because this should be the
388      only way that STMT, which is a reduction-phi, was put in the worklist,
389      as there should be no other uses for DEF_STMT in the loop.  So we just
390      check that everything is as expected, and we are done.  */
391   dstmt_vinfo = vinfo_for_stmt (def_stmt);
392   bb = gimple_bb (stmt);
393   if (gimple_code (stmt) == GIMPLE_PHI
394       && STMT_VINFO_DEF_TYPE (stmt_vinfo) == vect_reduction_def
395       && gimple_code (def_stmt) != GIMPLE_PHI
396       && STMT_VINFO_DEF_TYPE (dstmt_vinfo) == vect_reduction_def
397       && bb->loop_father == def_bb->loop_father)
398     {
399       if (vect_print_dump_info (REPORT_DETAILS))
400         fprintf (vect_dump, "reduc-stmt defining reduc-phi in the same nest.");
401       if (STMT_VINFO_IN_PATTERN_P (dstmt_vinfo))
402         dstmt_vinfo = vinfo_for_stmt (STMT_VINFO_RELATED_STMT (dstmt_vinfo));
403       gcc_assert (STMT_VINFO_RELEVANT (dstmt_vinfo) < vect_used_by_reduction);
404       gcc_assert (STMT_VINFO_LIVE_P (dstmt_vinfo)
405                   || STMT_VINFO_RELEVANT (dstmt_vinfo) > vect_unused_in_scope);
406       return true;
407     }
408
409   /* case 3a: outer-loop stmt defining an inner-loop stmt:
410         outer-loop-header-bb:
411                 d = def_stmt
412         inner-loop:
413                 stmt # use (d)
414         outer-loop-tail-bb:
415                 ...               */
416   if (flow_loop_nested_p (def_bb->loop_father, bb->loop_father))
417     {
418       if (vect_print_dump_info (REPORT_DETAILS))
419         fprintf (vect_dump, "outer-loop def-stmt defining inner-loop stmt.");
420
421       switch (relevant)
422         {
423         case vect_unused_in_scope:
424           relevant = (STMT_VINFO_DEF_TYPE (stmt_vinfo) == vect_nested_cycle) ?
425                       vect_used_in_scope : vect_unused_in_scope;
426           break;
427
428         case vect_used_in_outer_by_reduction:
429           gcc_assert (STMT_VINFO_DEF_TYPE (stmt_vinfo) != vect_reduction_def);
430           relevant = vect_used_by_reduction;
431           break;
432
433         case vect_used_in_outer:
434           gcc_assert (STMT_VINFO_DEF_TYPE (stmt_vinfo) != vect_reduction_def);
435           relevant = vect_used_in_scope;
436           break;
437
438         case vect_used_in_scope:
439           break;
440
441         default:
442           gcc_unreachable ();
443         }
444     }
445
446   /* case 3b: inner-loop stmt defining an outer-loop stmt:
447         outer-loop-header-bb:
448                 ...
449         inner-loop:
450                 d = def_stmt
451         outer-loop-tail-bb (or outer-loop-exit-bb in double reduction):
452                 stmt # use (d)          */
453   else if (flow_loop_nested_p (bb->loop_father, def_bb->loop_father))
454     {
455       if (vect_print_dump_info (REPORT_DETAILS))
456         fprintf (vect_dump, "inner-loop def-stmt defining outer-loop stmt.");
457
458       switch (relevant)
459         {
460         case vect_unused_in_scope:
461           relevant = (STMT_VINFO_DEF_TYPE (stmt_vinfo) == vect_reduction_def
462             || STMT_VINFO_DEF_TYPE (stmt_vinfo) == vect_double_reduction_def) ?
463                       vect_used_in_outer_by_reduction : vect_unused_in_scope;
464           break;
465
466         case vect_used_by_reduction:
467           relevant = vect_used_in_outer_by_reduction;
468           break;
469
470         case vect_used_in_scope:
471           relevant = vect_used_in_outer;
472           break;
473
474         default:
475           gcc_unreachable ();
476         }
477     }
478
479   vect_mark_relevant (worklist, def_stmt, relevant, live_p,
480                       is_pattern_stmt_p (stmt_vinfo));
481   return true;
482 }
483
484
485 /* Function vect_mark_stmts_to_be_vectorized.
486
487    Not all stmts in the loop need to be vectorized. For example:
488
489      for i...
490        for j...
491    1.    T0 = i + j
492    2.    T1 = a[T0]
493
494    3.    j = j + 1
495
496    Stmt 1 and 3 do not need to be vectorized, because loop control and
497    addressing of vectorized data-refs are handled differently.
498
499    This pass detects such stmts.  */
500
501 bool
502 vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo)
503 {
504   VEC(gimple,heap) *worklist;
505   struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
506   basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo);
507   unsigned int nbbs = loop->num_nodes;
508   gimple_stmt_iterator si;
509   gimple stmt;
510   unsigned int i;
511   stmt_vec_info stmt_vinfo;
512   basic_block bb;
513   gimple phi;
514   bool live_p;
515   enum vect_relevant relevant, tmp_relevant;
516   enum vect_def_type def_type;
517
518   if (vect_print_dump_info (REPORT_DETAILS))
519     fprintf (vect_dump, "=== vect_mark_stmts_to_be_vectorized ===");
520
521   worklist = VEC_alloc (gimple, heap, 64);
522
523   /* 1. Init worklist.  */
524   for (i = 0; i < nbbs; i++)
525     {
526       bb = bbs[i];
527       for (si = gsi_start_phis (bb); !gsi_end_p (si); gsi_next (&si))
528         {
529           phi = gsi_stmt (si);
530           if (vect_print_dump_info (REPORT_DETAILS))
531             {
532               fprintf (vect_dump, "init: phi relevant? ");
533               print_gimple_stmt (vect_dump, phi, 0, TDF_SLIM);
534             }
535
536           if (vect_stmt_relevant_p (phi, loop_vinfo, &relevant, &live_p))
537             vect_mark_relevant (&worklist, phi, relevant, live_p, false);
538         }
539       for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
540         {
541           stmt = gsi_stmt (si);
542           if (vect_print_dump_info (REPORT_DETAILS))
543             {
544               fprintf (vect_dump, "init: stmt relevant? ");
545               print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
546             }
547
548           if (vect_stmt_relevant_p (stmt, loop_vinfo, &relevant, &live_p))
549             vect_mark_relevant (&worklist, stmt, relevant, live_p, false);
550         }
551     }
552
553   /* 2. Process_worklist */
554   while (VEC_length (gimple, worklist) > 0)
555     {
556       use_operand_p use_p;
557       ssa_op_iter iter;
558
559       stmt = VEC_pop (gimple, worklist);
560       if (vect_print_dump_info (REPORT_DETAILS))
561         {
562           fprintf (vect_dump, "worklist: examine stmt: ");
563           print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
564         }
565
566       /* Examine the USEs of STMT. For each USE, mark the stmt that defines it
567          (DEF_STMT) as relevant/irrelevant and live/dead according to the
568          liveness and relevance properties of STMT.  */
569       stmt_vinfo = vinfo_for_stmt (stmt);
570       relevant = STMT_VINFO_RELEVANT (stmt_vinfo);
571       live_p = STMT_VINFO_LIVE_P (stmt_vinfo);
572
573       /* Generally, the liveness and relevance properties of STMT are
574          propagated as is to the DEF_STMTs of its USEs:
575           live_p <-- STMT_VINFO_LIVE_P (STMT_VINFO)
576           relevant <-- STMT_VINFO_RELEVANT (STMT_VINFO)
577
578          One exception is when STMT has been identified as defining a reduction
579          variable; in this case we set the liveness/relevance as follows:
580            live_p = false
581            relevant = vect_used_by_reduction
582          This is because we distinguish between two kinds of relevant stmts -
583          those that are used by a reduction computation, and those that are
584          (also) used by a regular computation.  This allows us later on to
585          identify stmts that are used solely by a reduction, and therefore the
586          order of the results that they produce does not have to be kept.  */
587
588       def_type = STMT_VINFO_DEF_TYPE (stmt_vinfo);
589       tmp_relevant = relevant;
590       switch (def_type)
591         {
592           case vect_reduction_def:
593             switch (tmp_relevant)
594               {
595                 case vect_unused_in_scope:
596                   relevant = vect_used_by_reduction;
597                   break;
598
599                 case vect_used_by_reduction:
600                   if (gimple_code (stmt) == GIMPLE_PHI)
601                     break;
602                   /* fall through */
603
604                 default:
605                   if (vect_print_dump_info (REPORT_DETAILS))
606                     fprintf (vect_dump, "unsupported use of reduction.");
607
608                   VEC_free (gimple, heap, worklist);
609                   return false;
610               }
611
612             live_p = false;
613             break;
614
615           case vect_nested_cycle:
616             if (tmp_relevant != vect_unused_in_scope
617                 && tmp_relevant != vect_used_in_outer_by_reduction
618                 && tmp_relevant != vect_used_in_outer)
619               {
620                 if (vect_print_dump_info (REPORT_DETAILS))
621                   fprintf (vect_dump, "unsupported use of nested cycle.");
622
623                 VEC_free (gimple, heap, worklist);
624                 return false;
625               }
626
627             live_p = false;
628             break;
629
630           case vect_double_reduction_def:
631             if (tmp_relevant != vect_unused_in_scope
632                 && tmp_relevant != vect_used_by_reduction)
633               {
634                 if (vect_print_dump_info (REPORT_DETAILS))
635                   fprintf (vect_dump, "unsupported use of double reduction.");
636
637                 VEC_free (gimple, heap, worklist);
638                 return false;
639               }
640
641             live_p = false;
642             break;
643
644           default:
645             break;
646         }
647
648       if (is_pattern_stmt_p (vinfo_for_stmt (stmt)))
649         {
650           /* Pattern statements are not inserted into the code, so
651              FOR_EACH_PHI_OR_STMT_USE optimizes their operands out, and we
652              have to scan the RHS or function arguments instead.  */
653           if (is_gimple_assign (stmt))
654             {
655               for (i = 1; i < gimple_num_ops (stmt); i++)
656                 {
657                   tree op = gimple_op (stmt, i);
658                   if (!process_use (stmt, op, loop_vinfo, live_p, relevant,
659                                     &worklist))
660                     {
661                       VEC_free (gimple, heap, worklist);
662                       return false;
663                     }
664                  }
665             }
666           else if (is_gimple_call (stmt))
667             {
668               for (i = 0; i < gimple_call_num_args (stmt); i++)
669                 {
670                   tree arg = gimple_call_arg (stmt, i);
671                   if (!process_use (stmt, arg, loop_vinfo, live_p, relevant,
672                                     &worklist))
673                     {
674                       VEC_free (gimple, heap, worklist);
675                       return false;
676                     }
677                 }
678             }
679         }
680       else
681         FOR_EACH_PHI_OR_STMT_USE (use_p, stmt, iter, SSA_OP_USE)
682           {
683             tree op = USE_FROM_PTR (use_p);
684             if (!process_use (stmt, op, loop_vinfo, live_p, relevant,
685                               &worklist))
686               {
687                 VEC_free (gimple, heap, worklist);
688                 return false;
689               }
690           }
691     } /* while worklist */
692
693   VEC_free (gimple, heap, worklist);
694   return true;
695 }
696
697
698 /* Get cost by calling cost target builtin.  */
699
700 static inline
701 int vect_get_stmt_cost (enum vect_cost_for_stmt type_of_cost)
702 {
703   tree dummy_type = NULL;
704   int dummy = 0;
705
706   return targetm.vectorize.builtin_vectorization_cost (type_of_cost,
707                                                        dummy_type, dummy);
708 }
709
710
711 /* Get cost for STMT.  */
712
713 int
714 cost_for_stmt (gimple stmt)
715 {
716   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
717
718   switch (STMT_VINFO_TYPE (stmt_info))
719   {
720   case load_vec_info_type:
721     return vect_get_stmt_cost (scalar_load);
722   case store_vec_info_type:
723     return vect_get_stmt_cost (scalar_store);
724   case op_vec_info_type:
725   case condition_vec_info_type:
726   case assignment_vec_info_type:
727   case reduc_vec_info_type:
728   case induc_vec_info_type:
729   case type_promotion_vec_info_type:
730   case type_demotion_vec_info_type:
731   case type_conversion_vec_info_type:
732   case call_vec_info_type:
733     return vect_get_stmt_cost (scalar_stmt);
734   case undef_vec_info_type:
735   default:
736     gcc_unreachable ();
737   }
738 }
739
740 /* Function vect_model_simple_cost.
741
742    Models cost for simple operations, i.e. those that only emit ncopies of a
743    single op.  Right now, this does not account for multiple insns that could
744    be generated for the single vector op.  We will handle that shortly.  */
745
746 void
747 vect_model_simple_cost (stmt_vec_info stmt_info, int ncopies,
748                         enum vect_def_type *dt, slp_tree slp_node)
749 {
750   int i;
751   int inside_cost = 0, outside_cost = 0;
752
753   /* The SLP costs were already calculated during SLP tree build.  */
754   if (PURE_SLP_STMT (stmt_info))
755     return;
756
757   inside_cost = ncopies * vect_get_stmt_cost (vector_stmt); 
758
759   /* FORNOW: Assuming maximum 2 args per stmts.  */
760   for (i = 0; i < 2; i++)
761     {
762       if (dt[i] == vect_constant_def || dt[i] == vect_external_def)
763         outside_cost += vect_get_stmt_cost (vector_stmt); 
764     }
765
766   if (vect_print_dump_info (REPORT_COST))
767     fprintf (vect_dump, "vect_model_simple_cost: inside_cost = %d, "
768              "outside_cost = %d .", inside_cost, outside_cost);
769
770   /* Set the costs either in STMT_INFO or SLP_NODE (if exists).  */
771   stmt_vinfo_set_inside_of_loop_cost (stmt_info, slp_node, inside_cost);
772   stmt_vinfo_set_outside_of_loop_cost (stmt_info, slp_node, outside_cost);
773 }
774
775
776 /* Function vect_cost_strided_group_size
777
778    For strided load or store, return the group_size only if it is the first
779    load or store of a group, else return 1.  This ensures that group size is
780    only returned once per group.  */
781
782 static int
783 vect_cost_strided_group_size (stmt_vec_info stmt_info)
784 {
785   gimple first_stmt = GROUP_FIRST_ELEMENT (stmt_info);
786
787   if (first_stmt == STMT_VINFO_STMT (stmt_info))
788     return GROUP_SIZE (stmt_info);
789
790   return 1;
791 }
792
793
794 /* Function vect_model_store_cost
795
796    Models cost for stores.  In the case of strided accesses, one access
797    has the overhead of the strided access attributed to it.  */
798
799 void
800 vect_model_store_cost (stmt_vec_info stmt_info, int ncopies,
801                        bool store_lanes_p, enum vect_def_type dt,
802                        slp_tree slp_node)
803 {
804   int group_size;
805   unsigned int inside_cost = 0, outside_cost = 0;
806   struct data_reference *first_dr;
807   gimple first_stmt;
808
809   /* The SLP costs were already calculated during SLP tree build.  */
810   if (PURE_SLP_STMT (stmt_info))
811     return;
812
813   if (dt == vect_constant_def || dt == vect_external_def)
814     outside_cost = vect_get_stmt_cost (scalar_to_vec); 
815
816   /* Strided access?  */
817   if (STMT_VINFO_STRIDED_ACCESS (stmt_info))
818     {
819       if (slp_node)
820         {
821           first_stmt = VEC_index (gimple, SLP_TREE_SCALAR_STMTS (slp_node), 0);
822           group_size = 1;
823         }
824       else
825         {
826           first_stmt = GROUP_FIRST_ELEMENT (stmt_info);
827           group_size = vect_cost_strided_group_size (stmt_info);
828         }
829
830       first_dr = STMT_VINFO_DATA_REF (vinfo_for_stmt (first_stmt));
831     }
832   /* Not a strided access.  */
833   else
834     {
835       group_size = 1;
836       first_dr = STMT_VINFO_DATA_REF (stmt_info);
837     }
838
839   /* We assume that the cost of a single store-lanes instruction is
840      equivalent to the cost of GROUP_SIZE separate stores.  If a strided
841      access is instead being provided by a permute-and-store operation,
842      include the cost of the permutes.  */
843   if (!store_lanes_p && group_size > 1)
844     {
845       /* Uses a high and low interleave operation for each needed permute.  */
846       inside_cost = ncopies * exact_log2(group_size) * group_size
847         * vect_get_stmt_cost (vector_stmt);
848
849       if (vect_print_dump_info (REPORT_COST))
850         fprintf (vect_dump, "vect_model_store_cost: strided group_size = %d .",
851                  group_size);
852
853     }
854
855   /* Costs of the stores.  */
856   vect_get_store_cost (first_dr, ncopies, &inside_cost);
857
858   if (vect_print_dump_info (REPORT_COST))
859     fprintf (vect_dump, "vect_model_store_cost: inside_cost = %d, "
860              "outside_cost = %d .", inside_cost, outside_cost);
861
862   /* Set the costs either in STMT_INFO or SLP_NODE (if exists).  */
863   stmt_vinfo_set_inside_of_loop_cost (stmt_info, slp_node, inside_cost);
864   stmt_vinfo_set_outside_of_loop_cost (stmt_info, slp_node, outside_cost);
865 }
866
867
868 /* Calculate cost of DR's memory access.  */
869 void
870 vect_get_store_cost (struct data_reference *dr, int ncopies,
871                      unsigned int *inside_cost)
872 {
873   int alignment_support_scheme = vect_supportable_dr_alignment (dr, false);
874
875   switch (alignment_support_scheme)
876     {
877     case dr_aligned:
878       {
879         *inside_cost += ncopies * vect_get_stmt_cost (vector_store);
880
881         if (vect_print_dump_info (REPORT_COST))
882           fprintf (vect_dump, "vect_model_store_cost: aligned.");
883
884         break;
885       }
886
887     case dr_unaligned_supported:
888       {
889         gimple stmt = DR_STMT (dr);
890         stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
891         tree vectype = STMT_VINFO_VECTYPE (stmt_info);
892
893         /* Here, we assign an additional cost for the unaligned store.  */
894         *inside_cost += ncopies
895           * targetm.vectorize.builtin_vectorization_cost (unaligned_store,
896                                  vectype, DR_MISALIGNMENT (dr));
897
898         if (vect_print_dump_info (REPORT_COST))
899           fprintf (vect_dump, "vect_model_store_cost: unaligned supported by "
900                    "hardware.");
901
902         break;
903       }
904
905     default:
906       gcc_unreachable ();
907     }
908 }
909
910
911 /* Function vect_model_load_cost
912
913    Models cost for loads.  In the case of strided accesses, the last access
914    has the overhead of the strided access attributed to it.  Since unaligned
915    accesses are supported for loads, we also account for the costs of the
916    access scheme chosen.  */
917
918 void
919 vect_model_load_cost (stmt_vec_info stmt_info, int ncopies, bool load_lanes_p,
920                       slp_tree slp_node)
921 {
922   int group_size;
923   gimple first_stmt;
924   struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info), *first_dr;
925   unsigned int inside_cost = 0, outside_cost = 0;
926
927   /* The SLP costs were already calculated during SLP tree build.  */
928   if (PURE_SLP_STMT (stmt_info))
929     return;
930
931   /* Strided accesses?  */
932   first_stmt = GROUP_FIRST_ELEMENT (stmt_info);
933   if (STMT_VINFO_STRIDED_ACCESS (stmt_info) && first_stmt && !slp_node)
934     {
935       group_size = vect_cost_strided_group_size (stmt_info);
936       first_dr = STMT_VINFO_DATA_REF (vinfo_for_stmt (first_stmt));
937     }
938   /* Not a strided access.  */
939   else
940     {
941       group_size = 1;
942       first_dr = dr;
943     }
944
945   /* We assume that the cost of a single load-lanes instruction is
946      equivalent to the cost of GROUP_SIZE separate loads.  If a strided
947      access is instead being provided by a load-and-permute operation,
948      include the cost of the permutes.  */
949   if (!load_lanes_p && group_size > 1)
950     {
951       /* Uses an even and odd extract operations for each needed permute.  */
952       inside_cost = ncopies * exact_log2(group_size) * group_size
953         * vect_get_stmt_cost (vector_stmt);
954
955       if (vect_print_dump_info (REPORT_COST))
956         fprintf (vect_dump, "vect_model_load_cost: strided group_size = %d .",
957                  group_size);
958     }
959
960   /* The loads themselves.  */
961   vect_get_load_cost (first_dr, ncopies,
962          ((!STMT_VINFO_STRIDED_ACCESS (stmt_info)) || group_size > 1
963           || slp_node),
964          &inside_cost, &outside_cost);
965
966   if (vect_print_dump_info (REPORT_COST))
967     fprintf (vect_dump, "vect_model_load_cost: inside_cost = %d, "
968              "outside_cost = %d .", inside_cost, outside_cost);
969
970   /* Set the costs either in STMT_INFO or SLP_NODE (if exists).  */
971   stmt_vinfo_set_inside_of_loop_cost (stmt_info, slp_node, inside_cost);
972   stmt_vinfo_set_outside_of_loop_cost (stmt_info, slp_node, outside_cost);
973 }
974
975
976 /* Calculate cost of DR's memory access.  */
977 void
978 vect_get_load_cost (struct data_reference *dr, int ncopies,
979                     bool add_realign_cost, unsigned int *inside_cost,
980                     unsigned int *outside_cost)
981 {
982   int alignment_support_scheme = vect_supportable_dr_alignment (dr, false);
983
984   switch (alignment_support_scheme)
985     {
986     case dr_aligned:
987       {
988         *inside_cost += ncopies * vect_get_stmt_cost (vector_load); 
989
990         if (vect_print_dump_info (REPORT_COST))
991           fprintf (vect_dump, "vect_model_load_cost: aligned.");
992
993         break;
994       }
995     case dr_unaligned_supported:
996       {
997         gimple stmt = DR_STMT (dr);
998         stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
999         tree vectype = STMT_VINFO_VECTYPE (stmt_info);
1000
1001         /* Here, we assign an additional cost for the unaligned load.  */
1002         *inside_cost += ncopies
1003           * targetm.vectorize.builtin_vectorization_cost (unaligned_load,
1004                                            vectype, DR_MISALIGNMENT (dr));
1005         if (vect_print_dump_info (REPORT_COST))
1006           fprintf (vect_dump, "vect_model_load_cost: unaligned supported by "
1007                    "hardware.");
1008
1009         break;
1010       }
1011     case dr_explicit_realign:
1012       {
1013         *inside_cost += ncopies * (2 * vect_get_stmt_cost (vector_load)
1014            + vect_get_stmt_cost (vector_stmt));
1015
1016         /* FIXME: If the misalignment remains fixed across the iterations of
1017            the containing loop, the following cost should be added to the
1018            outside costs.  */
1019         if (targetm.vectorize.builtin_mask_for_load)
1020           *inside_cost += vect_get_stmt_cost (vector_stmt);
1021
1022         break;
1023       }
1024     case dr_explicit_realign_optimized:
1025       {
1026         if (vect_print_dump_info (REPORT_COST))
1027           fprintf (vect_dump, "vect_model_load_cost: unaligned software "
1028                    "pipelined.");
1029
1030         /* Unaligned software pipeline has a load of an address, an initial
1031            load, and possibly a mask operation to "prime" the loop.  However,
1032            if this is an access in a group of loads, which provide strided
1033            access, then the above cost should only be considered for one
1034            access in the group.  Inside the loop, there is a load op
1035            and a realignment op.  */
1036
1037         if (add_realign_cost)
1038           {
1039             *outside_cost = 2 * vect_get_stmt_cost (vector_stmt);
1040             if (targetm.vectorize.builtin_mask_for_load)
1041               *outside_cost += vect_get_stmt_cost (vector_stmt);
1042           }
1043
1044         *inside_cost += ncopies * (vect_get_stmt_cost (vector_load)
1045           + vect_get_stmt_cost (vector_stmt));
1046         break;
1047       }
1048
1049     default:
1050       gcc_unreachable ();
1051     }
1052 }
1053
1054
1055 /* Function vect_init_vector.
1056
1057    Insert a new stmt (INIT_STMT) that initializes a new vector variable with
1058    the vector elements of VECTOR_VAR.  Place the initialization at BSI if it
1059    is not NULL.  Otherwise, place the initialization at the loop preheader.
1060    Return the DEF of INIT_STMT.
1061    It will be used in the vectorization of STMT.  */
1062
1063 tree
1064 vect_init_vector (gimple stmt, tree vector_var, tree vector_type,
1065                   gimple_stmt_iterator *gsi)
1066 {
1067   stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt);
1068   tree new_var;
1069   gimple init_stmt;
1070   tree vec_oprnd;
1071   edge pe;
1072   tree new_temp;
1073   basic_block new_bb;
1074
1075   new_var = vect_get_new_vect_var (vector_type, vect_simple_var, "cst_");
1076   add_referenced_var (new_var);
1077   init_stmt = gimple_build_assign  (new_var, vector_var);
1078   new_temp = make_ssa_name (new_var, init_stmt);
1079   gimple_assign_set_lhs (init_stmt, new_temp);
1080
1081   if (gsi)
1082     vect_finish_stmt_generation (stmt, init_stmt, gsi);
1083   else
1084     {
1085       loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
1086
1087       if (loop_vinfo)
1088         {
1089           struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
1090
1091           if (nested_in_vect_loop_p (loop, stmt))
1092             loop = loop->inner;
1093
1094           pe = loop_preheader_edge (loop);
1095           new_bb = gsi_insert_on_edge_immediate (pe, init_stmt);
1096           gcc_assert (!new_bb);
1097         }
1098       else
1099        {
1100           bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_vinfo);
1101           basic_block bb;
1102           gimple_stmt_iterator gsi_bb_start;
1103
1104           gcc_assert (bb_vinfo);
1105           bb = BB_VINFO_BB (bb_vinfo);
1106           gsi_bb_start = gsi_after_labels (bb);
1107           gsi_insert_before (&gsi_bb_start, init_stmt, GSI_SAME_STMT);
1108        }
1109     }
1110
1111   if (vect_print_dump_info (REPORT_DETAILS))
1112     {
1113       fprintf (vect_dump, "created new init_stmt: ");
1114       print_gimple_stmt (vect_dump, init_stmt, 0, TDF_SLIM);
1115     }
1116
1117   vec_oprnd = gimple_assign_lhs (init_stmt);
1118   return vec_oprnd;
1119 }
1120
1121
1122 /* Function vect_get_vec_def_for_operand.
1123
1124    OP is an operand in STMT.  This function returns a (vector) def that will be
1125    used in the vectorized stmt for STMT.
1126
1127    In the case that OP is an SSA_NAME which is defined in the loop, then
1128    STMT_VINFO_VEC_STMT of the defining stmt holds the relevant def.
1129
1130    In case OP is an invariant or constant, a new stmt that creates a vector def
1131    needs to be introduced.  */
1132
1133 tree
1134 vect_get_vec_def_for_operand (tree op, gimple stmt, tree *scalar_def)
1135 {
1136   tree vec_oprnd;
1137   gimple vec_stmt;
1138   gimple def_stmt;
1139   stmt_vec_info def_stmt_info = NULL;
1140   stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt);
1141   unsigned int nunits;
1142   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
1143   tree vec_inv;
1144   tree vec_cst;
1145   tree t = NULL_TREE;
1146   tree def;
1147   int i;
1148   enum vect_def_type dt;
1149   bool is_simple_use;
1150   tree vector_type;
1151
1152   if (vect_print_dump_info (REPORT_DETAILS))
1153     {
1154       fprintf (vect_dump, "vect_get_vec_def_for_operand: ");
1155       print_generic_expr (vect_dump, op, TDF_SLIM);
1156     }
1157
1158   is_simple_use = vect_is_simple_use (op, loop_vinfo, NULL, &def_stmt, &def,
1159                                       &dt);
1160   gcc_assert (is_simple_use);
1161   if (vect_print_dump_info (REPORT_DETAILS))
1162     {
1163       if (def)
1164         {
1165           fprintf (vect_dump, "def =  ");
1166           print_generic_expr (vect_dump, def, TDF_SLIM);
1167         }
1168       if (def_stmt)
1169         {
1170           fprintf (vect_dump, "  def_stmt =  ");
1171           print_gimple_stmt (vect_dump, def_stmt, 0, TDF_SLIM);
1172         }
1173     }
1174
1175   switch (dt)
1176     {
1177     /* Case 1: operand is a constant.  */
1178     case vect_constant_def:
1179       {
1180         vector_type = get_vectype_for_scalar_type (TREE_TYPE (op));
1181         gcc_assert (vector_type);
1182         nunits = TYPE_VECTOR_SUBPARTS (vector_type);
1183
1184         if (scalar_def)
1185           *scalar_def = op;
1186
1187         /* Create 'vect_cst_ = {cst,cst,...,cst}'  */
1188         if (vect_print_dump_info (REPORT_DETAILS))
1189           fprintf (vect_dump, "Create vector_cst. nunits = %d", nunits);
1190
1191         vec_cst = build_vector_from_val (vector_type, op);
1192         return vect_init_vector (stmt, vec_cst, vector_type, NULL);
1193       }
1194
1195     /* Case 2: operand is defined outside the loop - loop invariant.  */
1196     case vect_external_def:
1197       {
1198         vector_type = get_vectype_for_scalar_type (TREE_TYPE (def));
1199         gcc_assert (vector_type);
1200         nunits = TYPE_VECTOR_SUBPARTS (vector_type);
1201
1202         if (scalar_def)
1203           *scalar_def = def;
1204
1205         /* Create 'vec_inv = {inv,inv,..,inv}'  */
1206         if (vect_print_dump_info (REPORT_DETAILS))
1207           fprintf (vect_dump, "Create vector_inv.");
1208
1209         for (i = nunits - 1; i >= 0; --i)
1210           {
1211             t = tree_cons (NULL_TREE, def, t);
1212           }
1213
1214         /* FIXME: use build_constructor directly.  */
1215         vec_inv = build_constructor_from_list (vector_type, t);
1216         return vect_init_vector (stmt, vec_inv, vector_type, NULL);
1217       }
1218
1219     /* Case 3: operand is defined inside the loop.  */
1220     case vect_internal_def:
1221       {
1222         if (scalar_def)
1223           *scalar_def = NULL/* FIXME tuples: def_stmt*/;
1224
1225         /* Get the def from the vectorized stmt.  */
1226         def_stmt_info = vinfo_for_stmt (def_stmt);
1227
1228         vec_stmt = STMT_VINFO_VEC_STMT (def_stmt_info);
1229         /* Get vectorized pattern statement.  */
1230         if (!vec_stmt
1231             && STMT_VINFO_IN_PATTERN_P (def_stmt_info)
1232             && !STMT_VINFO_RELEVANT (def_stmt_info))
1233           vec_stmt = STMT_VINFO_VEC_STMT (vinfo_for_stmt (
1234                        STMT_VINFO_RELATED_STMT (def_stmt_info)));
1235         gcc_assert (vec_stmt);
1236         if (gimple_code (vec_stmt) == GIMPLE_PHI)
1237           vec_oprnd = PHI_RESULT (vec_stmt);
1238         else if (is_gimple_call (vec_stmt))
1239           vec_oprnd = gimple_call_lhs (vec_stmt);
1240         else
1241           vec_oprnd = gimple_assign_lhs (vec_stmt);
1242         return vec_oprnd;
1243       }
1244
1245     /* Case 4: operand is defined by a loop header phi - reduction  */
1246     case vect_reduction_def:
1247     case vect_double_reduction_def:
1248     case vect_nested_cycle:
1249       {
1250         struct loop *loop;
1251
1252         gcc_assert (gimple_code (def_stmt) == GIMPLE_PHI);
1253         loop = (gimple_bb (def_stmt))->loop_father;
1254
1255         /* Get the def before the loop  */
1256         op = PHI_ARG_DEF_FROM_EDGE (def_stmt, loop_preheader_edge (loop));
1257         return get_initial_def_for_reduction (stmt, op, scalar_def);
1258      }
1259
1260     /* Case 5: operand is defined by loop-header phi - induction.  */
1261     case vect_induction_def:
1262       {
1263         gcc_assert (gimple_code (def_stmt) == GIMPLE_PHI);
1264
1265         /* Get the def from the vectorized stmt.  */
1266         def_stmt_info = vinfo_for_stmt (def_stmt);
1267         vec_stmt = STMT_VINFO_VEC_STMT (def_stmt_info);
1268         if (gimple_code (vec_stmt) == GIMPLE_PHI)
1269           vec_oprnd = PHI_RESULT (vec_stmt);
1270         else
1271           vec_oprnd = gimple_get_lhs (vec_stmt);
1272         return vec_oprnd;
1273       }
1274
1275     default:
1276       gcc_unreachable ();
1277     }
1278 }
1279
1280
1281 /* Function vect_get_vec_def_for_stmt_copy
1282
1283    Return a vector-def for an operand.  This function is used when the
1284    vectorized stmt to be created (by the caller to this function) is a "copy"
1285    created in case the vectorized result cannot fit in one vector, and several
1286    copies of the vector-stmt are required.  In this case the vector-def is
1287    retrieved from the vector stmt recorded in the STMT_VINFO_RELATED_STMT field
1288    of the stmt that defines VEC_OPRND.
1289    DT is the type of the vector def VEC_OPRND.
1290
1291    Context:
1292         In case the vectorization factor (VF) is bigger than the number
1293    of elements that can fit in a vectype (nunits), we have to generate
1294    more than one vector stmt to vectorize the scalar stmt.  This situation
1295    arises when there are multiple data-types operated upon in the loop; the
1296    smallest data-type determines the VF, and as a result, when vectorizing
1297    stmts operating on wider types we need to create 'VF/nunits' "copies" of the
1298    vector stmt (each computing a vector of 'nunits' results, and together
1299    computing 'VF' results in each iteration).  This function is called when
1300    vectorizing such a stmt (e.g. vectorizing S2 in the illustration below, in
1301    which VF=16 and nunits=4, so the number of copies required is 4):
1302
1303    scalar stmt:         vectorized into:        STMT_VINFO_RELATED_STMT
1304
1305    S1: x = load         VS1.0:  vx.0 = memref0      VS1.1
1306                         VS1.1:  vx.1 = memref1      VS1.2
1307                         VS1.2:  vx.2 = memref2      VS1.3
1308                         VS1.3:  vx.3 = memref3
1309
1310    S2: z = x + ...      VSnew.0:  vz0 = vx.0 + ...  VSnew.1
1311                         VSnew.1:  vz1 = vx.1 + ...  VSnew.2
1312                         VSnew.2:  vz2 = vx.2 + ...  VSnew.3
1313                         VSnew.3:  vz3 = vx.3 + ...
1314
1315    The vectorization of S1 is explained in vectorizable_load.
1316    The vectorization of S2:
1317         To create the first vector-stmt out of the 4 copies - VSnew.0 -
1318    the function 'vect_get_vec_def_for_operand' is called to
1319    get the relevant vector-def for each operand of S2.  For operand x it
1320    returns  the vector-def 'vx.0'.
1321
1322         To create the remaining copies of the vector-stmt (VSnew.j), this
1323    function is called to get the relevant vector-def for each operand.  It is
1324    obtained from the respective VS1.j stmt, which is recorded in the
1325    STMT_VINFO_RELATED_STMT field of the stmt that defines VEC_OPRND.
1326
1327         For example, to obtain the vector-def 'vx.1' in order to create the
1328    vector stmt 'VSnew.1', this function is called with VEC_OPRND='vx.0'.
1329    Given 'vx0' we obtain the stmt that defines it ('VS1.0'); from the
1330    STMT_VINFO_RELATED_STMT field of 'VS1.0' we obtain the next copy - 'VS1.1',
1331    and return its def ('vx.1').
1332    Overall, to create the above sequence this function will be called 3 times:
1333         vx.1 = vect_get_vec_def_for_stmt_copy (dt, vx.0);
1334         vx.2 = vect_get_vec_def_for_stmt_copy (dt, vx.1);
1335         vx.3 = vect_get_vec_def_for_stmt_copy (dt, vx.2);  */
1336
1337 tree
1338 vect_get_vec_def_for_stmt_copy (enum vect_def_type dt, tree vec_oprnd)
1339 {
1340   gimple vec_stmt_for_operand;
1341   stmt_vec_info def_stmt_info;
1342
1343   /* Do nothing; can reuse same def.  */
1344   if (dt == vect_external_def || dt == vect_constant_def )
1345     return vec_oprnd;
1346
1347   vec_stmt_for_operand = SSA_NAME_DEF_STMT (vec_oprnd);
1348   def_stmt_info = vinfo_for_stmt (vec_stmt_for_operand);
1349   gcc_assert (def_stmt_info);
1350   vec_stmt_for_operand = STMT_VINFO_RELATED_STMT (def_stmt_info);
1351   gcc_assert (vec_stmt_for_operand);
1352   vec_oprnd = gimple_get_lhs (vec_stmt_for_operand);
1353   if (gimple_code (vec_stmt_for_operand) == GIMPLE_PHI)
1354     vec_oprnd = PHI_RESULT (vec_stmt_for_operand);
1355   else
1356     vec_oprnd = gimple_get_lhs (vec_stmt_for_operand);
1357   return vec_oprnd;
1358 }
1359
1360
1361 /* Get vectorized definitions for the operands to create a copy of an original
1362    stmt.  See vect_get_vec_def_for_stmt_copy () for details.  */
1363
1364 static void
1365 vect_get_vec_defs_for_stmt_copy (enum vect_def_type *dt,
1366                                  VEC(tree,heap) **vec_oprnds0,
1367                                  VEC(tree,heap) **vec_oprnds1)
1368 {
1369   tree vec_oprnd = VEC_pop (tree, *vec_oprnds0);
1370
1371   vec_oprnd = vect_get_vec_def_for_stmt_copy (dt[0], vec_oprnd);
1372   VEC_quick_push (tree, *vec_oprnds0, vec_oprnd);
1373
1374   if (vec_oprnds1 && *vec_oprnds1)
1375     {
1376       vec_oprnd = VEC_pop (tree, *vec_oprnds1);
1377       vec_oprnd = vect_get_vec_def_for_stmt_copy (dt[1], vec_oprnd);
1378       VEC_quick_push (tree, *vec_oprnds1, vec_oprnd);
1379     }
1380 }
1381
1382
1383 /* Get vectorized definitions for OP0 and OP1, or SLP_NODE if it is not
1384    NULL.  */
1385
1386 static void
1387 vect_get_vec_defs (tree op0, tree op1, gimple stmt,
1388                    VEC(tree,heap) **vec_oprnds0, VEC(tree,heap) **vec_oprnds1,
1389                    slp_tree slp_node)
1390 {
1391   if (slp_node)
1392     vect_get_slp_defs (op0, op1, slp_node, vec_oprnds0, vec_oprnds1, -1);
1393   else
1394     {
1395       tree vec_oprnd;
1396
1397       *vec_oprnds0 = VEC_alloc (tree, heap, 1);
1398       vec_oprnd = vect_get_vec_def_for_operand (op0, stmt, NULL);
1399       VEC_quick_push (tree, *vec_oprnds0, vec_oprnd);
1400
1401       if (op1)
1402         {
1403           *vec_oprnds1 = VEC_alloc (tree, heap, 1);
1404           vec_oprnd = vect_get_vec_def_for_operand (op1, stmt, NULL);
1405           VEC_quick_push (tree, *vec_oprnds1, vec_oprnd);
1406         }
1407     }
1408 }
1409
1410
1411 /* Function vect_finish_stmt_generation.
1412
1413    Insert a new stmt.  */
1414
1415 void
1416 vect_finish_stmt_generation (gimple stmt, gimple vec_stmt,
1417                              gimple_stmt_iterator *gsi)
1418 {
1419   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
1420   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
1421   bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
1422
1423   gcc_assert (gimple_code (stmt) != GIMPLE_LABEL);
1424
1425   gsi_insert_before (gsi, vec_stmt, GSI_SAME_STMT);
1426
1427   set_vinfo_for_stmt (vec_stmt, new_stmt_vec_info (vec_stmt, loop_vinfo,
1428                                                    bb_vinfo));
1429
1430   if (vect_print_dump_info (REPORT_DETAILS))
1431     {
1432       fprintf (vect_dump, "add new stmt: ");
1433       print_gimple_stmt (vect_dump, vec_stmt, 0, TDF_SLIM);
1434     }
1435
1436   gimple_set_location (vec_stmt, gimple_location (gsi_stmt (*gsi)));
1437 }
1438
1439 /* Checks if CALL can be vectorized in type VECTYPE.  Returns
1440    a function declaration if the target has a vectorized version
1441    of the function, or NULL_TREE if the function cannot be vectorized.  */
1442
1443 tree
1444 vectorizable_function (gimple call, tree vectype_out, tree vectype_in)
1445 {
1446   tree fndecl = gimple_call_fndecl (call);
1447
1448   /* We only handle functions that do not read or clobber memory -- i.e.
1449      const or novops ones.  */
1450   if (!(gimple_call_flags (call) & (ECF_CONST | ECF_NOVOPS)))
1451     return NULL_TREE;
1452
1453   if (!fndecl
1454       || TREE_CODE (fndecl) != FUNCTION_DECL
1455       || !DECL_BUILT_IN (fndecl))
1456     return NULL_TREE;
1457
1458   return targetm.vectorize.builtin_vectorized_function (fndecl, vectype_out,
1459                                                         vectype_in);
1460 }
1461
1462 /* Function vectorizable_call.
1463
1464    Check if STMT performs a function call that can be vectorized.
1465    If VEC_STMT is also passed, vectorize the STMT: create a vectorized
1466    stmt to replace it, put it in VEC_STMT, and insert it at BSI.
1467    Return FALSE if not a vectorizable STMT, TRUE otherwise.  */
1468
1469 static bool
1470 vectorizable_call (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt)
1471 {
1472   tree vec_dest;
1473   tree scalar_dest;
1474   tree op, type;
1475   tree vec_oprnd0 = NULL_TREE, vec_oprnd1 = NULL_TREE;
1476   stmt_vec_info stmt_info = vinfo_for_stmt (stmt), prev_stmt_info;
1477   tree vectype_out, vectype_in;
1478   int nunits_in;
1479   int nunits_out;
1480   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
1481   tree fndecl, new_temp, def, rhs_type;
1482   gimple def_stmt;
1483   enum vect_def_type dt[3]
1484     = {vect_unknown_def_type, vect_unknown_def_type, vect_unknown_def_type};
1485   gimple new_stmt = NULL;
1486   int ncopies, j;
1487   VEC(tree, heap) *vargs = NULL;
1488   enum { NARROW, NONE, WIDEN } modifier;
1489   size_t i, nargs;
1490   tree lhs;
1491
1492   /* FORNOW: unsupported in basic block SLP.  */
1493   gcc_assert (loop_vinfo);
1494
1495   if (!STMT_VINFO_RELEVANT_P (stmt_info))
1496     return false;
1497
1498   if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def)
1499     return false;
1500
1501   /* FORNOW: SLP not supported.  */
1502   if (STMT_SLP_TYPE (stmt_info))
1503     return false;
1504
1505   /* Is STMT a vectorizable call?   */
1506   if (!is_gimple_call (stmt))
1507     return false;
1508
1509   if (TREE_CODE (gimple_call_lhs (stmt)) != SSA_NAME)
1510     return false;
1511
1512   if (stmt_can_throw_internal (stmt))
1513     return false;
1514
1515   vectype_out = STMT_VINFO_VECTYPE (stmt_info);
1516
1517   /* Process function arguments.  */
1518   rhs_type = NULL_TREE;
1519   vectype_in = NULL_TREE;
1520   nargs = gimple_call_num_args (stmt);
1521
1522   /* Bail out if the function has more than three arguments, we do not have
1523      interesting builtin functions to vectorize with more than two arguments
1524      except for fma.  No arguments is also not good.  */
1525   if (nargs == 0 || nargs > 3)
1526     return false;
1527
1528   for (i = 0; i < nargs; i++)
1529     {
1530       tree opvectype;
1531
1532       op = gimple_call_arg (stmt, i);
1533
1534       /* We can only handle calls with arguments of the same type.  */
1535       if (rhs_type
1536           && !types_compatible_p (rhs_type, TREE_TYPE (op)))
1537         {
1538           if (vect_print_dump_info (REPORT_DETAILS))
1539             fprintf (vect_dump, "argument types differ.");
1540           return false;
1541         }
1542       if (!rhs_type)
1543         rhs_type = TREE_TYPE (op);
1544
1545       if (!vect_is_simple_use_1 (op, loop_vinfo, NULL,
1546                                  &def_stmt, &def, &dt[i], &opvectype))
1547         {
1548           if (vect_print_dump_info (REPORT_DETAILS))
1549             fprintf (vect_dump, "use not simple.");
1550           return false;
1551         }
1552
1553       if (!vectype_in)
1554         vectype_in = opvectype;
1555       else if (opvectype
1556                && opvectype != vectype_in)
1557         {
1558           if (vect_print_dump_info (REPORT_DETAILS))
1559             fprintf (vect_dump, "argument vector types differ.");
1560           return false;
1561         }
1562     }
1563   /* If all arguments are external or constant defs use a vector type with
1564      the same size as the output vector type.  */
1565   if (!vectype_in)
1566     vectype_in = get_same_sized_vectype (rhs_type, vectype_out);
1567   if (vec_stmt)
1568     gcc_assert (vectype_in);
1569   if (!vectype_in)
1570     {
1571       if (vect_print_dump_info (REPORT_DETAILS))
1572         {
1573           fprintf (vect_dump, "no vectype for scalar type ");
1574           print_generic_expr (vect_dump, rhs_type, TDF_SLIM);
1575         }
1576
1577       return false;
1578     }
1579
1580   /* FORNOW */
1581   nunits_in = TYPE_VECTOR_SUBPARTS (vectype_in);
1582   nunits_out = TYPE_VECTOR_SUBPARTS (vectype_out);
1583   if (nunits_in == nunits_out / 2)
1584     modifier = NARROW;
1585   else if (nunits_out == nunits_in)
1586     modifier = NONE;
1587   else if (nunits_out == nunits_in / 2)
1588     modifier = WIDEN;
1589   else
1590     return false;
1591
1592   /* For now, we only vectorize functions if a target specific builtin
1593      is available.  TODO -- in some cases, it might be profitable to
1594      insert the calls for pieces of the vector, in order to be able
1595      to vectorize other operations in the loop.  */
1596   fndecl = vectorizable_function (stmt, vectype_out, vectype_in);
1597   if (fndecl == NULL_TREE)
1598     {
1599       if (vect_print_dump_info (REPORT_DETAILS))
1600         fprintf (vect_dump, "function is not vectorizable.");
1601
1602       return false;
1603     }
1604
1605   gcc_assert (!gimple_vuse (stmt));
1606
1607   if (modifier == NARROW)
1608     ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits_out;
1609   else
1610     ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits_in;
1611
1612   /* Sanity check: make sure that at least one copy of the vectorized stmt
1613      needs to be generated.  */
1614   gcc_assert (ncopies >= 1);
1615
1616   if (!vec_stmt) /* transformation not required.  */
1617     {
1618       STMT_VINFO_TYPE (stmt_info) = call_vec_info_type;
1619       if (vect_print_dump_info (REPORT_DETAILS))
1620         fprintf (vect_dump, "=== vectorizable_call ===");
1621       vect_model_simple_cost (stmt_info, ncopies, dt, NULL);
1622       return true;
1623     }
1624
1625   /** Transform.  **/
1626
1627   if (vect_print_dump_info (REPORT_DETAILS))
1628     fprintf (vect_dump, "transform call.");
1629
1630   /* Handle def.  */
1631   scalar_dest = gimple_call_lhs (stmt);
1632   vec_dest = vect_create_destination_var (scalar_dest, vectype_out);
1633
1634   prev_stmt_info = NULL;
1635   switch (modifier)
1636     {
1637     case NONE:
1638       for (j = 0; j < ncopies; ++j)
1639         {
1640           /* Build argument list for the vectorized call.  */
1641           if (j == 0)
1642             vargs = VEC_alloc (tree, heap, nargs);
1643           else
1644             VEC_truncate (tree, vargs, 0);
1645
1646           for (i = 0; i < nargs; i++)
1647             {
1648               op = gimple_call_arg (stmt, i);
1649               if (j == 0)
1650                 vec_oprnd0
1651                   = vect_get_vec_def_for_operand (op, stmt, NULL);
1652               else
1653                 {
1654                   vec_oprnd0 = gimple_call_arg (new_stmt, i);
1655                   vec_oprnd0
1656                     = vect_get_vec_def_for_stmt_copy (dt[i], vec_oprnd0);
1657                 }
1658
1659               VEC_quick_push (tree, vargs, vec_oprnd0);
1660             }
1661
1662           new_stmt = gimple_build_call_vec (fndecl, vargs);
1663           new_temp = make_ssa_name (vec_dest, new_stmt);
1664           gimple_call_set_lhs (new_stmt, new_temp);
1665
1666           vect_finish_stmt_generation (stmt, new_stmt, gsi);
1667           mark_symbols_for_renaming (new_stmt);
1668
1669           if (j == 0)
1670             STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
1671           else
1672             STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
1673
1674           prev_stmt_info = vinfo_for_stmt (new_stmt);
1675         }
1676
1677       break;
1678
1679     case NARROW:
1680       for (j = 0; j < ncopies; ++j)
1681         {
1682           /* Build argument list for the vectorized call.  */
1683           if (j == 0)
1684             vargs = VEC_alloc (tree, heap, nargs * 2);
1685           else
1686             VEC_truncate (tree, vargs, 0);
1687
1688           for (i = 0; i < nargs; i++)
1689             {
1690               op = gimple_call_arg (stmt, i);
1691               if (j == 0)
1692                 {
1693                   vec_oprnd0
1694                     = vect_get_vec_def_for_operand (op, stmt, NULL);
1695                   vec_oprnd1
1696                     = vect_get_vec_def_for_stmt_copy (dt[i], vec_oprnd0);
1697                 }
1698               else
1699                 {
1700                   vec_oprnd1 = gimple_call_arg (new_stmt, 2*i);
1701                   vec_oprnd0
1702                     = vect_get_vec_def_for_stmt_copy (dt[i], vec_oprnd1);
1703                   vec_oprnd1
1704                     = vect_get_vec_def_for_stmt_copy (dt[i], vec_oprnd0);
1705                 }
1706
1707               VEC_quick_push (tree, vargs, vec_oprnd0);
1708               VEC_quick_push (tree, vargs, vec_oprnd1);
1709             }
1710
1711           new_stmt = gimple_build_call_vec (fndecl, vargs);
1712           new_temp = make_ssa_name (vec_dest, new_stmt);
1713           gimple_call_set_lhs (new_stmt, new_temp);
1714
1715           vect_finish_stmt_generation (stmt, new_stmt, gsi);
1716           mark_symbols_for_renaming (new_stmt);
1717
1718           if (j == 0)
1719             STMT_VINFO_VEC_STMT (stmt_info) = new_stmt;
1720           else
1721             STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
1722
1723           prev_stmt_info = vinfo_for_stmt (new_stmt);
1724         }
1725
1726       *vec_stmt = STMT_VINFO_VEC_STMT (stmt_info);
1727
1728       break;
1729
1730     case WIDEN:
1731       /* No current target implements this case.  */
1732       return false;
1733     }
1734
1735   VEC_free (tree, heap, vargs);
1736
1737   /* Update the exception handling table with the vector stmt if necessary.  */
1738   if (maybe_clean_or_replace_eh_stmt (stmt, *vec_stmt))
1739     gimple_purge_dead_eh_edges (gimple_bb (stmt));
1740
1741   /* The call in STMT might prevent it from being removed in dce.
1742      We however cannot remove it here, due to the way the ssa name
1743      it defines is mapped to the new definition.  So just replace
1744      rhs of the statement with something harmless.  */
1745
1746   type = TREE_TYPE (scalar_dest);
1747   if (is_pattern_stmt_p (stmt_info))
1748     lhs = gimple_call_lhs (STMT_VINFO_RELATED_STMT (stmt_info));
1749   else
1750     lhs = gimple_call_lhs (stmt);
1751   new_stmt = gimple_build_assign (lhs, build_zero_cst (type));
1752   set_vinfo_for_stmt (new_stmt, stmt_info);
1753   set_vinfo_for_stmt (stmt, NULL);
1754   STMT_VINFO_STMT (stmt_info) = new_stmt;
1755   gsi_replace (gsi, new_stmt, false);
1756   SSA_NAME_DEF_STMT (gimple_assign_lhs (new_stmt)) = new_stmt;
1757
1758   return true;
1759 }
1760
1761
1762 /* Function vect_gen_widened_results_half
1763
1764    Create a vector stmt whose code, type, number of arguments, and result
1765    variable are CODE, OP_TYPE, and VEC_DEST, and its arguments are
1766    VEC_OPRND0 and VEC_OPRND1.  The new vector stmt is to be inserted at BSI.
1767    In the case that CODE is a CALL_EXPR, this means that a call to DECL
1768    needs to be created (DECL is a function-decl of a target-builtin).
1769    STMT is the original scalar stmt that we are vectorizing.  */
1770
1771 static gimple
1772 vect_gen_widened_results_half (enum tree_code code,
1773                                tree decl,
1774                                tree vec_oprnd0, tree vec_oprnd1, int op_type,
1775                                tree vec_dest, gimple_stmt_iterator *gsi,
1776                                gimple stmt)
1777 {
1778   gimple new_stmt;
1779   tree new_temp;
1780
1781   /* Generate half of the widened result:  */
1782   if (code == CALL_EXPR)
1783     {
1784       /* Target specific support  */
1785       if (op_type == binary_op)
1786         new_stmt = gimple_build_call (decl, 2, vec_oprnd0, vec_oprnd1);
1787       else
1788         new_stmt = gimple_build_call (decl, 1, vec_oprnd0);
1789       new_temp = make_ssa_name (vec_dest, new_stmt);
1790       gimple_call_set_lhs (new_stmt, new_temp);
1791     }
1792   else
1793     {
1794       /* Generic support */
1795       gcc_assert (op_type == TREE_CODE_LENGTH (code));
1796       if (op_type != binary_op)
1797         vec_oprnd1 = NULL;
1798       new_stmt = gimple_build_assign_with_ops (code, vec_dest, vec_oprnd0,
1799                                                vec_oprnd1);
1800       new_temp = make_ssa_name (vec_dest, new_stmt);
1801       gimple_assign_set_lhs (new_stmt, new_temp);
1802     }
1803   vect_finish_stmt_generation (stmt, new_stmt, gsi);
1804
1805   return new_stmt;
1806 }
1807
1808
1809 /* Check if STMT performs a conversion operation, that can be vectorized.
1810    If VEC_STMT is also passed, vectorize the STMT: create a vectorized
1811    stmt to replace it, put it in VEC_STMT, and insert it at BSI.
1812    Return FALSE if not a vectorizable STMT, TRUE otherwise.  */
1813
1814 static bool
1815 vectorizable_conversion (gimple stmt, gimple_stmt_iterator *gsi,
1816                          gimple *vec_stmt, slp_tree slp_node)
1817 {
1818   tree vec_dest;
1819   tree scalar_dest;
1820   tree op0;
1821   tree vec_oprnd0 = NULL_TREE, vec_oprnd1 = NULL_TREE;
1822   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
1823   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
1824   enum tree_code code, code1 = ERROR_MARK, code2 = ERROR_MARK;
1825   tree decl1 = NULL_TREE, decl2 = NULL_TREE;
1826   tree new_temp;
1827   tree def;
1828   gimple def_stmt;
1829   enum vect_def_type dt[2] = {vect_unknown_def_type, vect_unknown_def_type};
1830   gimple new_stmt = NULL;
1831   stmt_vec_info prev_stmt_info;
1832   int nunits_in;
1833   int nunits_out;
1834   tree vectype_out, vectype_in;
1835   int ncopies, j;
1836   tree rhs_type;
1837   tree builtin_decl;
1838   enum { NARROW, NONE, WIDEN } modifier;
1839   int i;
1840   VEC(tree,heap) *vec_oprnds0 = NULL;
1841   tree vop0;
1842   VEC(tree,heap) *dummy = NULL;
1843   int dummy_int;
1844
1845   /* Is STMT a vectorizable conversion?   */
1846
1847   /* FORNOW: unsupported in basic block SLP.  */
1848   gcc_assert (loop_vinfo);
1849
1850   if (!STMT_VINFO_RELEVANT_P (stmt_info))
1851     return false;
1852
1853   if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def)
1854     return false;
1855
1856   if (!is_gimple_assign (stmt))
1857     return false;
1858
1859   if (TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME)
1860     return false;
1861
1862   code = gimple_assign_rhs_code (stmt);
1863   if (code != FIX_TRUNC_EXPR && code != FLOAT_EXPR)
1864     return false;
1865
1866   /* Check types of lhs and rhs.  */
1867   scalar_dest = gimple_assign_lhs (stmt);
1868   vectype_out = STMT_VINFO_VECTYPE (stmt_info);
1869
1870   op0 = gimple_assign_rhs1 (stmt);
1871   rhs_type = TREE_TYPE (op0);
1872   /* Check the operands of the operation.  */
1873   if (!vect_is_simple_use_1 (op0, loop_vinfo, NULL,
1874                              &def_stmt, &def, &dt[0], &vectype_in))
1875     {
1876       if (vect_print_dump_info (REPORT_DETAILS))
1877         fprintf (vect_dump, "use not simple.");
1878       return false;
1879     }
1880   /* If op0 is an external or constant defs use a vector type of
1881      the same size as the output vector type.  */
1882   if (!vectype_in)
1883     vectype_in = get_same_sized_vectype (rhs_type, vectype_out);
1884   if (vec_stmt)
1885     gcc_assert (vectype_in);
1886   if (!vectype_in)
1887     {
1888       if (vect_print_dump_info (REPORT_DETAILS))
1889         {
1890           fprintf (vect_dump, "no vectype for scalar type ");
1891           print_generic_expr (vect_dump, rhs_type, TDF_SLIM);
1892         }
1893
1894       return false;
1895     }
1896
1897   /* FORNOW */
1898   nunits_in = TYPE_VECTOR_SUBPARTS (vectype_in);
1899   nunits_out = TYPE_VECTOR_SUBPARTS (vectype_out);
1900   if (nunits_in == nunits_out / 2)
1901     modifier = NARROW;
1902   else if (nunits_out == nunits_in)
1903     modifier = NONE;
1904   else if (nunits_out == nunits_in / 2)
1905     modifier = WIDEN;
1906   else
1907     return false;
1908
1909   if (modifier == NARROW)
1910     ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits_out;
1911   else
1912     ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits_in;
1913
1914   /* Multiple types in SLP are handled by creating the appropriate number of
1915      vectorized stmts for each SLP node.  Hence, NCOPIES is always 1 in
1916      case of SLP.  */
1917   if (slp_node || PURE_SLP_STMT (stmt_info))
1918     ncopies = 1;
1919
1920   /* Sanity check: make sure that at least one copy of the vectorized stmt
1921      needs to be generated.  */
1922   gcc_assert (ncopies >= 1);
1923
1924   /* Supportable by target?  */
1925   if ((modifier == NONE
1926        && !targetm.vectorize.builtin_conversion (code, vectype_out, vectype_in))
1927       || (modifier == WIDEN
1928           && !supportable_widening_operation (code, stmt,
1929                                               vectype_out, vectype_in,
1930                                               &decl1, &decl2,
1931                                               &code1, &code2,
1932                                               &dummy_int, &dummy))
1933       || (modifier == NARROW
1934           && !supportable_narrowing_operation (code, vectype_out, vectype_in,
1935                                                &code1, &dummy_int, &dummy)))
1936     {
1937       if (vect_print_dump_info (REPORT_DETAILS))
1938         fprintf (vect_dump, "conversion not supported by target.");
1939       return false;
1940     }
1941
1942   if (modifier != NONE)
1943     {
1944       /* FORNOW: SLP not supported.  */
1945       if (STMT_SLP_TYPE (stmt_info))
1946         return false;
1947     }
1948
1949   if (!vec_stmt)                /* transformation not required.  */
1950     {
1951       STMT_VINFO_TYPE (stmt_info) = type_conversion_vec_info_type;
1952       return true;
1953     }
1954
1955   /** Transform.  **/
1956   if (vect_print_dump_info (REPORT_DETAILS))
1957     fprintf (vect_dump, "transform conversion.");
1958
1959   /* Handle def.  */
1960   vec_dest = vect_create_destination_var (scalar_dest, vectype_out);
1961
1962   if (modifier == NONE && !slp_node)
1963     vec_oprnds0 = VEC_alloc (tree, heap, 1);
1964
1965   prev_stmt_info = NULL;
1966   switch (modifier)
1967     {
1968     case NONE:
1969       for (j = 0; j < ncopies; j++)
1970         {
1971           if (j == 0)
1972             vect_get_vec_defs (op0, NULL, stmt, &vec_oprnds0, NULL, slp_node);
1973           else
1974             vect_get_vec_defs_for_stmt_copy (dt, &vec_oprnds0, NULL);
1975
1976           builtin_decl =
1977             targetm.vectorize.builtin_conversion (code,
1978                                                   vectype_out, vectype_in);
1979           FOR_EACH_VEC_ELT (tree, vec_oprnds0, i, vop0)
1980             {
1981               /* Arguments are ready. create the new vector stmt.  */
1982               new_stmt = gimple_build_call (builtin_decl, 1, vop0);
1983               new_temp = make_ssa_name (vec_dest, new_stmt);
1984               gimple_call_set_lhs (new_stmt, new_temp);
1985               vect_finish_stmt_generation (stmt, new_stmt, gsi);
1986               if (slp_node)
1987                 VEC_quick_push (gimple, SLP_TREE_VEC_STMTS (slp_node), new_stmt);
1988             }
1989
1990           if (j == 0)
1991             STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
1992           else
1993             STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
1994           prev_stmt_info = vinfo_for_stmt (new_stmt);
1995         }
1996       break;
1997
1998     case WIDEN:
1999       /* In case the vectorization factor (VF) is bigger than the number
2000          of elements that we can fit in a vectype (nunits), we have to
2001          generate more than one vector stmt - i.e - we need to "unroll"
2002          the vector stmt by a factor VF/nunits.  */
2003       for (j = 0; j < ncopies; j++)
2004         {
2005           if (j == 0)
2006             vec_oprnd0 = vect_get_vec_def_for_operand (op0, stmt, NULL);
2007           else
2008             vec_oprnd0 = vect_get_vec_def_for_stmt_copy (dt[0], vec_oprnd0);
2009
2010           /* Generate first half of the widened result:  */
2011           new_stmt
2012             = vect_gen_widened_results_half (code1, decl1,
2013                                              vec_oprnd0, vec_oprnd1,
2014                                              unary_op, vec_dest, gsi, stmt);
2015           if (j == 0)
2016             STMT_VINFO_VEC_STMT (stmt_info) = new_stmt;
2017           else
2018             STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
2019           prev_stmt_info = vinfo_for_stmt (new_stmt);
2020
2021           /* Generate second half of the widened result:  */
2022           new_stmt
2023             = vect_gen_widened_results_half (code2, decl2,
2024                                              vec_oprnd0, vec_oprnd1,
2025                                              unary_op, vec_dest, gsi, stmt);
2026           STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
2027           prev_stmt_info = vinfo_for_stmt (new_stmt);
2028         }
2029       break;
2030
2031     case NARROW:
2032       /* In case the vectorization factor (VF) is bigger than the number
2033          of elements that we can fit in a vectype (nunits), we have to
2034          generate more than one vector stmt - i.e - we need to "unroll"
2035          the vector stmt by a factor VF/nunits.  */
2036       for (j = 0; j < ncopies; j++)
2037         {
2038           /* Handle uses.  */
2039           if (j == 0)
2040             {
2041               vec_oprnd0 = vect_get_vec_def_for_operand (op0, stmt, NULL);
2042               vec_oprnd1 = vect_get_vec_def_for_stmt_copy (dt[0], vec_oprnd0);
2043             }
2044           else
2045             {
2046               vec_oprnd0 = vect_get_vec_def_for_stmt_copy (dt[0], vec_oprnd1);
2047               vec_oprnd1 = vect_get_vec_def_for_stmt_copy (dt[0], vec_oprnd0);
2048             }
2049
2050           /* Arguments are ready.  Create the new vector stmt.  */
2051           new_stmt = gimple_build_assign_with_ops (code1, vec_dest, vec_oprnd0,
2052                                                    vec_oprnd1);
2053           new_temp = make_ssa_name (vec_dest, new_stmt);
2054           gimple_assign_set_lhs (new_stmt, new_temp);
2055           vect_finish_stmt_generation (stmt, new_stmt, gsi);
2056
2057           if (j == 0)
2058             STMT_VINFO_VEC_STMT (stmt_info) = new_stmt;
2059           else
2060             STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
2061
2062           prev_stmt_info = vinfo_for_stmt (new_stmt);
2063         }
2064
2065       *vec_stmt = STMT_VINFO_VEC_STMT (stmt_info);
2066     }
2067
2068   if (vec_oprnds0)
2069     VEC_free (tree, heap, vec_oprnds0);
2070
2071   return true;
2072 }
2073
2074
2075 /* Function vectorizable_assignment.
2076
2077    Check if STMT performs an assignment (copy) that can be vectorized.
2078    If VEC_STMT is also passed, vectorize the STMT: create a vectorized
2079    stmt to replace it, put it in VEC_STMT, and insert it at BSI.
2080    Return FALSE if not a vectorizable STMT, TRUE otherwise.  */
2081
2082 static bool
2083 vectorizable_assignment (gimple stmt, gimple_stmt_iterator *gsi,
2084                          gimple *vec_stmt, slp_tree slp_node)
2085 {
2086   tree vec_dest;
2087   tree scalar_dest;
2088   tree op;
2089   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
2090   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
2091   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
2092   tree new_temp;
2093   tree def;
2094   gimple def_stmt;
2095   enum vect_def_type dt[2] = {vect_unknown_def_type, vect_unknown_def_type};
2096   unsigned int nunits = TYPE_VECTOR_SUBPARTS (vectype);
2097   int ncopies;
2098   int i, j;
2099   VEC(tree,heap) *vec_oprnds = NULL;
2100   tree vop;
2101   bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
2102   gimple new_stmt = NULL;
2103   stmt_vec_info prev_stmt_info = NULL;
2104   enum tree_code code;
2105   tree vectype_in;
2106
2107   /* Multiple types in SLP are handled by creating the appropriate number of
2108      vectorized stmts for each SLP node. Hence, NCOPIES is always 1 in
2109      case of SLP.  */
2110   if (slp_node || PURE_SLP_STMT (stmt_info))
2111     ncopies = 1;
2112   else
2113     ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits;
2114
2115   gcc_assert (ncopies >= 1);
2116
2117   if (!STMT_VINFO_RELEVANT_P (stmt_info) && !bb_vinfo)
2118     return false;
2119
2120   if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def)
2121     return false;
2122
2123   /* Is vectorizable assignment?  */
2124   if (!is_gimple_assign (stmt))
2125     return false;
2126
2127   scalar_dest = gimple_assign_lhs (stmt);
2128   if (TREE_CODE (scalar_dest) != SSA_NAME)
2129     return false;
2130
2131   code = gimple_assign_rhs_code (stmt);
2132   if (gimple_assign_single_p (stmt)
2133       || code == PAREN_EXPR
2134       || CONVERT_EXPR_CODE_P (code))
2135     op = gimple_assign_rhs1 (stmt);
2136   else
2137     return false;
2138
2139   if (code == VIEW_CONVERT_EXPR)
2140     op = TREE_OPERAND (op, 0);
2141
2142   if (!vect_is_simple_use_1 (op, loop_vinfo, bb_vinfo,
2143                              &def_stmt, &def, &dt[0], &vectype_in))
2144     {
2145       if (vect_print_dump_info (REPORT_DETAILS))
2146         fprintf (vect_dump, "use not simple.");
2147       return false;
2148     }
2149
2150   /* We can handle NOP_EXPR conversions that do not change the number
2151      of elements or the vector size.  */
2152   if ((CONVERT_EXPR_CODE_P (code)
2153        || code == VIEW_CONVERT_EXPR)
2154       && (!vectype_in
2155           || TYPE_VECTOR_SUBPARTS (vectype_in) != nunits
2156           || (GET_MODE_SIZE (TYPE_MODE (vectype))
2157               != GET_MODE_SIZE (TYPE_MODE (vectype_in)))))
2158     return false;
2159
2160   if (!vec_stmt) /* transformation not required.  */
2161     {
2162       STMT_VINFO_TYPE (stmt_info) = assignment_vec_info_type;
2163       if (vect_print_dump_info (REPORT_DETAILS))
2164         fprintf (vect_dump, "=== vectorizable_assignment ===");
2165       vect_model_simple_cost (stmt_info, ncopies, dt, NULL);
2166       return true;
2167     }
2168
2169   /** Transform.  **/
2170   if (vect_print_dump_info (REPORT_DETAILS))
2171     fprintf (vect_dump, "transform assignment.");
2172
2173   /* Handle def.  */
2174   vec_dest = vect_create_destination_var (scalar_dest, vectype);
2175
2176   /* Handle use.  */
2177   for (j = 0; j < ncopies; j++)
2178     {
2179       /* Handle uses.  */
2180       if (j == 0)
2181         vect_get_vec_defs (op, NULL, stmt, &vec_oprnds, NULL, slp_node);
2182       else
2183         vect_get_vec_defs_for_stmt_copy (dt, &vec_oprnds, NULL);
2184
2185       /* Arguments are ready. create the new vector stmt.  */
2186       FOR_EACH_VEC_ELT (tree, vec_oprnds, i, vop)
2187        {
2188          if (CONVERT_EXPR_CODE_P (code)
2189              || code == VIEW_CONVERT_EXPR)
2190            vop = build1 (VIEW_CONVERT_EXPR, vectype, vop);
2191          new_stmt = gimple_build_assign (vec_dest, vop);
2192          new_temp = make_ssa_name (vec_dest, new_stmt);
2193          gimple_assign_set_lhs (new_stmt, new_temp);
2194          vect_finish_stmt_generation (stmt, new_stmt, gsi);
2195          if (slp_node)
2196            VEC_quick_push (gimple, SLP_TREE_VEC_STMTS (slp_node), new_stmt);
2197        }
2198
2199       if (slp_node)
2200         continue;
2201
2202       if (j == 0)
2203         STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
2204       else
2205         STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
2206
2207       prev_stmt_info = vinfo_for_stmt (new_stmt);
2208     }
2209
2210   VEC_free (tree, heap, vec_oprnds);
2211   return true;
2212 }
2213
2214
2215 /* Function vectorizable_shift.
2216
2217    Check if STMT performs a shift operation that can be vectorized.
2218    If VEC_STMT is also passed, vectorize the STMT: create a vectorized
2219    stmt to replace it, put it in VEC_STMT, and insert it at BSI.
2220    Return FALSE if not a vectorizable STMT, TRUE otherwise.  */
2221
2222 static bool
2223 vectorizable_shift (gimple stmt, gimple_stmt_iterator *gsi,
2224                     gimple *vec_stmt, slp_tree slp_node)
2225 {
2226   tree vec_dest;
2227   tree scalar_dest;
2228   tree op0, op1 = NULL;
2229   tree vec_oprnd1 = NULL_TREE;
2230   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
2231   tree vectype;
2232   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
2233   enum tree_code code;
2234   enum machine_mode vec_mode;
2235   tree new_temp;
2236   optab optab;
2237   int icode;
2238   enum machine_mode optab_op2_mode;
2239   tree def;
2240   gimple def_stmt;
2241   enum vect_def_type dt[2] = {vect_unknown_def_type, vect_unknown_def_type};
2242   gimple new_stmt = NULL;
2243   stmt_vec_info prev_stmt_info;
2244   int nunits_in;
2245   int nunits_out;
2246   tree vectype_out;
2247   int ncopies;
2248   int j, i;
2249   VEC (tree, heap) *vec_oprnds0 = NULL, *vec_oprnds1 = NULL;
2250   tree vop0, vop1;
2251   unsigned int k;
2252   bool scalar_shift_arg = true;
2253   bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
2254   int vf;
2255
2256   if (!STMT_VINFO_RELEVANT_P (stmt_info) && !bb_vinfo)
2257     return false;
2258
2259   if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def)
2260     return false;
2261
2262   /* Is STMT a vectorizable binary/unary operation?   */
2263   if (!is_gimple_assign (stmt))
2264     return false;
2265
2266   if (TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME)
2267     return false;
2268
2269   code = gimple_assign_rhs_code (stmt);
2270
2271   if (!(code == LSHIFT_EXPR || code == RSHIFT_EXPR || code == LROTATE_EXPR
2272       || code == RROTATE_EXPR))
2273     return false;
2274
2275   scalar_dest = gimple_assign_lhs (stmt);
2276   vectype_out = STMT_VINFO_VECTYPE (stmt_info);
2277
2278   op0 = gimple_assign_rhs1 (stmt);
2279   if (!vect_is_simple_use_1 (op0, loop_vinfo, bb_vinfo,
2280                              &def_stmt, &def, &dt[0], &vectype))
2281     {
2282       if (vect_print_dump_info (REPORT_DETAILS))
2283         fprintf (vect_dump, "use not simple.");
2284       return false;
2285     }
2286   /* If op0 is an external or constant def use a vector type with
2287      the same size as the output vector type.  */
2288   if (!vectype)
2289     vectype = get_same_sized_vectype (TREE_TYPE (op0), vectype_out);
2290   if (vec_stmt)
2291     gcc_assert (vectype);
2292   if (!vectype)
2293     {
2294       if (vect_print_dump_info (REPORT_DETAILS))
2295         {
2296           fprintf (vect_dump, "no vectype for scalar type ");
2297           print_generic_expr (vect_dump, TREE_TYPE (op0), TDF_SLIM);
2298         }
2299
2300       return false;
2301     }
2302
2303   nunits_out = TYPE_VECTOR_SUBPARTS (vectype_out);
2304   nunits_in = TYPE_VECTOR_SUBPARTS (vectype);
2305   if (nunits_out != nunits_in)
2306     return false;
2307
2308   op1 = gimple_assign_rhs2 (stmt);
2309   if (!vect_is_simple_use (op1, loop_vinfo, bb_vinfo, &def_stmt, &def, &dt[1]))
2310     {
2311       if (vect_print_dump_info (REPORT_DETAILS))
2312         fprintf (vect_dump, "use not simple.");
2313       return false;
2314     }
2315
2316   if (loop_vinfo)
2317     vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
2318   else
2319     vf = 1;
2320
2321   /* Multiple types in SLP are handled by creating the appropriate number of
2322      vectorized stmts for each SLP node.  Hence, NCOPIES is always 1 in
2323      case of SLP.  */
2324   if (slp_node || PURE_SLP_STMT (stmt_info))
2325     ncopies = 1;
2326   else
2327     ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits_in;
2328
2329   gcc_assert (ncopies >= 1);
2330
2331   /* Determine whether the shift amount is a vector, or scalar.  If the
2332      shift/rotate amount is a vector, use the vector/vector shift optabs.  */
2333
2334   if (dt[1] == vect_internal_def && !slp_node)
2335     scalar_shift_arg = false;
2336   else if (dt[1] == vect_constant_def
2337            || dt[1] == vect_external_def
2338            || dt[1] == vect_internal_def)
2339     {
2340       /* In SLP, need to check whether the shift count is the same,
2341          in loops if it is a constant or invariant, it is always
2342          a scalar shift.  */
2343       if (slp_node)
2344         {
2345           VEC (gimple, heap) *stmts = SLP_TREE_SCALAR_STMTS (slp_node);
2346           gimple slpstmt;
2347
2348           FOR_EACH_VEC_ELT (gimple, stmts, k, slpstmt)
2349             if (!operand_equal_p (gimple_assign_rhs2 (slpstmt), op1, 0))
2350               scalar_shift_arg = false;
2351         }
2352     }
2353   else
2354     {
2355       if (vect_print_dump_info (REPORT_DETAILS))
2356         fprintf (vect_dump, "operand mode requires invariant argument.");
2357       return false;
2358     }
2359
2360   /* Vector shifted by vector.  */
2361   if (!scalar_shift_arg)
2362     {
2363       optab = optab_for_tree_code (code, vectype, optab_vector);
2364       if (vect_print_dump_info (REPORT_DETAILS))
2365         fprintf (vect_dump, "vector/vector shift/rotate found.");
2366     }
2367   /* See if the machine has a vector shifted by scalar insn and if not
2368      then see if it has a vector shifted by vector insn.  */
2369   else
2370     {
2371       optab = optab_for_tree_code (code, vectype, optab_scalar);
2372       if (optab
2373           && optab_handler (optab, TYPE_MODE (vectype)) != CODE_FOR_nothing)
2374         {
2375           if (vect_print_dump_info (REPORT_DETAILS))
2376             fprintf (vect_dump, "vector/scalar shift/rotate found.");
2377         }
2378       else
2379         {
2380           optab = optab_for_tree_code (code, vectype, optab_vector);
2381           if (optab
2382                && (optab_handler (optab, TYPE_MODE (vectype))
2383                       != CODE_FOR_nothing))
2384             {
2385               scalar_shift_arg = false;
2386
2387               if (vect_print_dump_info (REPORT_DETAILS))
2388                 fprintf (vect_dump, "vector/vector shift/rotate found.");
2389
2390               /* Unlike the other binary operators, shifts/rotates have
2391                  the rhs being int, instead of the same type as the lhs,
2392                  so make sure the scalar is the right type if we are
2393                  dealing with vectors of short/char.  */
2394               if (dt[1] == vect_constant_def)
2395                 op1 = fold_convert (TREE_TYPE (vectype), op1);
2396             }
2397         }
2398     }
2399
2400   /* Supportable by target?  */
2401   if (!optab)
2402     {
2403       if (vect_print_dump_info (REPORT_DETAILS))
2404         fprintf (vect_dump, "no optab.");
2405       return false;
2406     }
2407   vec_mode = TYPE_MODE (vectype);
2408   icode = (int) optab_handler (optab, vec_mode);
2409   if (icode == CODE_FOR_nothing)
2410     {
2411       if (vect_print_dump_info (REPORT_DETAILS))
2412         fprintf (vect_dump, "op not supported by target.");
2413       /* Check only during analysis.  */
2414       if (GET_MODE_SIZE (vec_mode) != UNITS_PER_WORD
2415           || (vf < vect_min_worthwhile_factor (code)
2416               && !vec_stmt))
2417         return false;
2418       if (vect_print_dump_info (REPORT_DETAILS))
2419         fprintf (vect_dump, "proceeding using word mode.");
2420     }
2421
2422   /* Worthwhile without SIMD support?  Check only during analysis.  */
2423   if (!VECTOR_MODE_P (TYPE_MODE (vectype))
2424       && vf < vect_min_worthwhile_factor (code)
2425       && !vec_stmt)
2426     {
2427       if (vect_print_dump_info (REPORT_DETAILS))
2428         fprintf (vect_dump, "not worthwhile without SIMD support.");
2429       return false;
2430     }
2431
2432   if (!vec_stmt) /* transformation not required.  */
2433     {
2434       STMT_VINFO_TYPE (stmt_info) = shift_vec_info_type;
2435       if (vect_print_dump_info (REPORT_DETAILS))
2436         fprintf (vect_dump, "=== vectorizable_shift ===");
2437       vect_model_simple_cost (stmt_info, ncopies, dt, NULL);
2438       return true;
2439     }
2440
2441   /** Transform.  **/
2442
2443   if (vect_print_dump_info (REPORT_DETAILS))
2444     fprintf (vect_dump, "transform binary/unary operation.");
2445
2446   /* Handle def.  */
2447   vec_dest = vect_create_destination_var (scalar_dest, vectype);
2448
2449   /* Allocate VECs for vector operands.  In case of SLP, vector operands are
2450      created in the previous stages of the recursion, so no allocation is
2451      needed, except for the case of shift with scalar shift argument.  In that
2452      case we store the scalar operand in VEC_OPRNDS1 for every vector stmt to
2453      be created to vectorize the SLP group, i.e., SLP_NODE->VEC_STMTS_SIZE.
2454      In case of loop-based vectorization we allocate VECs of size 1.  We
2455      allocate VEC_OPRNDS1 only in case of binary operation.  */
2456   if (!slp_node)
2457     {
2458       vec_oprnds0 = VEC_alloc (tree, heap, 1);
2459       vec_oprnds1 = VEC_alloc (tree, heap, 1);
2460     }
2461   else if (scalar_shift_arg)
2462     vec_oprnds1 = VEC_alloc (tree, heap, slp_node->vec_stmts_size);
2463
2464   prev_stmt_info = NULL;
2465   for (j = 0; j < ncopies; j++)
2466     {
2467       /* Handle uses.  */
2468       if (j == 0)
2469         {
2470           if (scalar_shift_arg)
2471             {
2472               /* Vector shl and shr insn patterns can be defined with scalar
2473                  operand 2 (shift operand).  In this case, use constant or loop
2474                  invariant op1 directly, without extending it to vector mode
2475                  first.  */
2476               optab_op2_mode = insn_data[icode].operand[2].mode;
2477               if (!VECTOR_MODE_P (optab_op2_mode))
2478                 {
2479                   if (vect_print_dump_info (REPORT_DETAILS))
2480                     fprintf (vect_dump, "operand 1 using scalar mode.");
2481                   vec_oprnd1 = op1;
2482                   VEC_quick_push (tree, vec_oprnds1, vec_oprnd1);
2483                   if (slp_node)
2484                     {
2485                       /* Store vec_oprnd1 for every vector stmt to be created
2486                          for SLP_NODE.  We check during the analysis that all
2487                          the shift arguments are the same.
2488                          TODO: Allow different constants for different vector
2489                          stmts generated for an SLP instance.  */
2490                       for (k = 0; k < slp_node->vec_stmts_size - 1; k++)
2491                         VEC_quick_push (tree, vec_oprnds1, vec_oprnd1);
2492                     }
2493                 }
2494             }
2495
2496           /* vec_oprnd1 is available if operand 1 should be of a scalar-type
2497              (a special case for certain kind of vector shifts); otherwise,
2498              operand 1 should be of a vector type (the usual case).  */
2499           if (vec_oprnd1)
2500             vect_get_vec_defs (op0, NULL_TREE, stmt, &vec_oprnds0, NULL,
2501                                slp_node);
2502           else
2503             vect_get_vec_defs (op0, op1, stmt, &vec_oprnds0, &vec_oprnds1,
2504                                slp_node);
2505         }
2506       else
2507         vect_get_vec_defs_for_stmt_copy (dt, &vec_oprnds0, &vec_oprnds1);
2508
2509       /* Arguments are ready.  Create the new vector stmt.  */
2510       FOR_EACH_VEC_ELT (tree, vec_oprnds0, i, vop0)
2511         {
2512           vop1 = VEC_index (tree, vec_oprnds1, i);
2513           new_stmt = gimple_build_assign_with_ops (code, vec_dest, vop0, vop1);
2514           new_temp = make_ssa_name (vec_dest, new_stmt);
2515           gimple_assign_set_lhs (new_stmt, new_temp);
2516           vect_finish_stmt_generation (stmt, new_stmt, gsi);
2517           if (slp_node)
2518             VEC_quick_push (gimple, SLP_TREE_VEC_STMTS (slp_node), new_stmt);
2519         }
2520
2521       if (slp_node)
2522         continue;
2523
2524       if (j == 0)
2525         STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
2526       else
2527         STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
2528       prev_stmt_info = vinfo_for_stmt (new_stmt);
2529     }
2530
2531   VEC_free (tree, heap, vec_oprnds0);
2532   VEC_free (tree, heap, vec_oprnds1);
2533
2534   return true;
2535 }
2536
2537
2538 /* Function vectorizable_operation.
2539
2540    Check if STMT performs a binary, unary or ternary operation that can
2541    be vectorized.
2542    If VEC_STMT is also passed, vectorize the STMT: create a vectorized
2543    stmt to replace it, put it in VEC_STMT, and insert it at BSI.
2544    Return FALSE if not a vectorizable STMT, TRUE otherwise.  */
2545
2546 static bool
2547 vectorizable_operation (gimple stmt, gimple_stmt_iterator *gsi,
2548                         gimple *vec_stmt, slp_tree slp_node)
2549 {
2550   tree vec_dest;
2551   tree scalar_dest;
2552   tree op0, op1 = NULL_TREE, op2 = NULL_TREE;
2553   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
2554   tree vectype;
2555   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
2556   enum tree_code code;
2557   enum machine_mode vec_mode;
2558   tree new_temp;
2559   int op_type;
2560   optab optab;
2561   int icode;
2562   tree def;
2563   gimple def_stmt;
2564   enum vect_def_type dt[3]
2565     = {vect_unknown_def_type, vect_unknown_def_type, vect_unknown_def_type};
2566   gimple new_stmt = NULL;
2567   stmt_vec_info prev_stmt_info;
2568   int nunits_in;
2569   int nunits_out;
2570   tree vectype_out;
2571   int ncopies;
2572   int j, i;
2573   VEC(tree,heap) *vec_oprnds0 = NULL, *vec_oprnds1 = NULL, *vec_oprnds2 = NULL;
2574   tree vop0, vop1, vop2;
2575   bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
2576   int vf;
2577
2578   if (!STMT_VINFO_RELEVANT_P (stmt_info) && !bb_vinfo)
2579     return false;
2580
2581   if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def)
2582     return false;
2583
2584   /* Is STMT a vectorizable binary/unary operation?   */
2585   if (!is_gimple_assign (stmt))
2586     return false;
2587
2588   if (TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME)
2589     return false;
2590
2591   code = gimple_assign_rhs_code (stmt);
2592
2593   /* For pointer addition, we should use the normal plus for
2594      the vector addition.  */
2595   if (code == POINTER_PLUS_EXPR)
2596     code = PLUS_EXPR;
2597
2598   /* Support only unary or binary operations.  */
2599   op_type = TREE_CODE_LENGTH (code);
2600   if (op_type != unary_op && op_type != binary_op && op_type != ternary_op)
2601     {
2602       if (vect_print_dump_info (REPORT_DETAILS))
2603         fprintf (vect_dump, "num. args = %d (not unary/binary/ternary op).",
2604                  op_type);
2605       return false;
2606     }
2607
2608   scalar_dest = gimple_assign_lhs (stmt);
2609   vectype_out = STMT_VINFO_VECTYPE (stmt_info);
2610
2611   op0 = gimple_assign_rhs1 (stmt);
2612   if (!vect_is_simple_use_1 (op0, loop_vinfo, bb_vinfo,
2613                              &def_stmt, &def, &dt[0], &vectype))
2614     {
2615       if (vect_print_dump_info (REPORT_DETAILS))
2616         fprintf (vect_dump, "use not simple.");
2617       return false;
2618     }
2619   /* If op0 is an external or constant def use a vector type with
2620      the same size as the output vector type.  */
2621   if (!vectype)
2622     vectype = get_same_sized_vectype (TREE_TYPE (op0), vectype_out);
2623   if (vec_stmt)
2624     gcc_assert (vectype);
2625   if (!vectype)
2626     {
2627       if (vect_print_dump_info (REPORT_DETAILS))
2628         {
2629           fprintf (vect_dump, "no vectype for scalar type ");
2630           print_generic_expr (vect_dump, TREE_TYPE (op0), TDF_SLIM);
2631         }
2632
2633       return false;
2634     }
2635
2636   nunits_out = TYPE_VECTOR_SUBPARTS (vectype_out);
2637   nunits_in = TYPE_VECTOR_SUBPARTS (vectype);
2638   if (nunits_out != nunits_in)
2639     return false;
2640
2641   if (op_type == binary_op || op_type == ternary_op)
2642     {
2643       op1 = gimple_assign_rhs2 (stmt);
2644       if (!vect_is_simple_use (op1, loop_vinfo, bb_vinfo, &def_stmt, &def,
2645                                &dt[1]))
2646         {
2647           if (vect_print_dump_info (REPORT_DETAILS))
2648             fprintf (vect_dump, "use not simple.");
2649           return false;
2650         }
2651     }
2652   if (op_type == ternary_op)
2653     {
2654       op2 = gimple_assign_rhs3 (stmt);
2655       if (!vect_is_simple_use (op2, loop_vinfo, bb_vinfo, &def_stmt, &def,
2656                                &dt[2]))
2657         {
2658           if (vect_print_dump_info (REPORT_DETAILS))
2659             fprintf (vect_dump, "use not simple.");
2660           return false;
2661         }
2662     }
2663
2664   if (loop_vinfo)
2665     vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
2666   else
2667     vf = 1;
2668
2669   /* Multiple types in SLP are handled by creating the appropriate number of
2670      vectorized stmts for each SLP node.  Hence, NCOPIES is always 1 in
2671      case of SLP.  */
2672   if (slp_node || PURE_SLP_STMT (stmt_info))
2673     ncopies = 1;
2674   else
2675     ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits_in;
2676
2677   gcc_assert (ncopies >= 1);
2678
2679   /* Shifts are handled in vectorizable_shift ().  */
2680   if (code == LSHIFT_EXPR || code == RSHIFT_EXPR || code == LROTATE_EXPR
2681       || code == RROTATE_EXPR)
2682    return false;
2683
2684   optab = optab_for_tree_code (code, vectype, optab_default);
2685
2686   /* Supportable by target?  */
2687   if (!optab)
2688     {
2689       if (vect_print_dump_info (REPORT_DETAILS))
2690         fprintf (vect_dump, "no optab.");
2691       return false;
2692     }
2693   vec_mode = TYPE_MODE (vectype);
2694   icode = (int) optab_handler (optab, vec_mode);
2695   if (icode == CODE_FOR_nothing)
2696     {
2697       if (vect_print_dump_info (REPORT_DETAILS))
2698         fprintf (vect_dump, "op not supported by target.");
2699       /* Check only during analysis.  */
2700       if (GET_MODE_SIZE (vec_mode) != UNITS_PER_WORD
2701           || (vf < vect_min_worthwhile_factor (code)
2702               && !vec_stmt))
2703         return false;
2704       if (vect_print_dump_info (REPORT_DETAILS))
2705         fprintf (vect_dump, "proceeding using word mode.");
2706     }
2707
2708   /* Worthwhile without SIMD support?  Check only during analysis.  */
2709   if (!VECTOR_MODE_P (TYPE_MODE (vectype))
2710       && vf < vect_min_worthwhile_factor (code)
2711       && !vec_stmt)
2712     {
2713       if (vect_print_dump_info (REPORT_DETAILS))
2714         fprintf (vect_dump, "not worthwhile without SIMD support.");
2715       return false;
2716     }
2717
2718   if (!vec_stmt) /* transformation not required.  */
2719     {
2720       STMT_VINFO_TYPE (stmt_info) = op_vec_info_type;
2721       if (vect_print_dump_info (REPORT_DETAILS))
2722         fprintf (vect_dump, "=== vectorizable_operation ===");
2723       vect_model_simple_cost (stmt_info, ncopies, dt, NULL);
2724       return true;
2725     }
2726
2727   /** Transform.  **/
2728
2729   if (vect_print_dump_info (REPORT_DETAILS))
2730     fprintf (vect_dump, "transform binary/unary operation.");
2731
2732   /* Handle def.  */
2733   vec_dest = vect_create_destination_var (scalar_dest, vectype);
2734
2735   /* Allocate VECs for vector operands.  In case of SLP, vector operands are
2736      created in the previous stages of the recursion, so no allocation is
2737      needed, except for the case of shift with scalar shift argument.  In that
2738      case we store the scalar operand in VEC_OPRNDS1 for every vector stmt to
2739      be created to vectorize the SLP group, i.e., SLP_NODE->VEC_STMTS_SIZE.
2740      In case of loop-based vectorization we allocate VECs of size 1.  We
2741      allocate VEC_OPRNDS1 only in case of binary operation.  */
2742   if (!slp_node)
2743     {
2744       vec_oprnds0 = VEC_alloc (tree, heap, 1);
2745       if (op_type == binary_op || op_type == ternary_op)
2746         vec_oprnds1 = VEC_alloc (tree, heap, 1);
2747       if (op_type == ternary_op)
2748         vec_oprnds2 = VEC_alloc (tree, heap, 1);
2749     }
2750
2751   /* In case the vectorization factor (VF) is bigger than the number
2752      of elements that we can fit in a vectype (nunits), we have to generate
2753      more than one vector stmt - i.e - we need to "unroll" the
2754      vector stmt by a factor VF/nunits.  In doing so, we record a pointer
2755      from one copy of the vector stmt to the next, in the field
2756      STMT_VINFO_RELATED_STMT.  This is necessary in order to allow following
2757      stages to find the correct vector defs to be used when vectorizing
2758      stmts that use the defs of the current stmt.  The example below
2759      illustrates the vectorization process when VF=16 and nunits=4 (i.e.,
2760      we need to create 4 vectorized stmts):
2761
2762      before vectorization:
2763                                 RELATED_STMT    VEC_STMT
2764         S1:     x = memref      -               -
2765         S2:     z = x + 1       -               -
2766
2767      step 1: vectorize stmt S1 (done in vectorizable_load. See more details
2768              there):
2769                                 RELATED_STMT    VEC_STMT
2770         VS1_0:  vx0 = memref0   VS1_1           -
2771         VS1_1:  vx1 = memref1   VS1_2           -
2772         VS1_2:  vx2 = memref2   VS1_3           -
2773         VS1_3:  vx3 = memref3   -               -
2774         S1:     x = load        -               VS1_0
2775         S2:     z = x + 1       -               -
2776
2777      step2: vectorize stmt S2 (done here):
2778         To vectorize stmt S2 we first need to find the relevant vector
2779         def for the first operand 'x'.  This is, as usual, obtained from
2780         the vector stmt recorded in the STMT_VINFO_VEC_STMT of the stmt
2781         that defines 'x' (S1).  This way we find the stmt VS1_0, and the
2782         relevant vector def 'vx0'.  Having found 'vx0' we can generate
2783         the vector stmt VS2_0, and as usual, record it in the
2784         STMT_VINFO_VEC_STMT of stmt S2.
2785         When creating the second copy (VS2_1), we obtain the relevant vector
2786         def from the vector stmt recorded in the STMT_VINFO_RELATED_STMT of
2787         stmt VS1_0.  This way we find the stmt VS1_1 and the relevant
2788         vector def 'vx1'.  Using 'vx1' we create stmt VS2_1 and record a
2789         pointer to it in the STMT_VINFO_RELATED_STMT of the vector stmt VS2_0.
2790         Similarly when creating stmts VS2_2 and VS2_3.  This is the resulting
2791         chain of stmts and pointers:
2792                                 RELATED_STMT    VEC_STMT
2793         VS1_0:  vx0 = memref0   VS1_1           -
2794         VS1_1:  vx1 = memref1   VS1_2           -
2795         VS1_2:  vx2 = memref2   VS1_3           -
2796         VS1_3:  vx3 = memref3   -               -
2797         S1:     x = load        -               VS1_0
2798         VS2_0:  vz0 = vx0 + v1  VS2_1           -
2799         VS2_1:  vz1 = vx1 + v1  VS2_2           -
2800         VS2_2:  vz2 = vx2 + v1  VS2_3           -
2801         VS2_3:  vz3 = vx3 + v1  -               -
2802         S2:     z = x + 1       -               VS2_0  */
2803
2804   prev_stmt_info = NULL;
2805   for (j = 0; j < ncopies; j++)
2806     {
2807       /* Handle uses.  */
2808       if (j == 0)
2809         {
2810           if (op_type == binary_op || op_type == ternary_op)
2811             vect_get_vec_defs (op0, op1, stmt, &vec_oprnds0, &vec_oprnds1,
2812                                slp_node);
2813           else
2814             vect_get_vec_defs (op0, NULL_TREE, stmt, &vec_oprnds0, NULL,
2815                                slp_node);
2816           if (op_type == ternary_op)
2817             {
2818               vec_oprnds2 = VEC_alloc (tree, heap, 1);
2819               VEC_quick_push (tree, vec_oprnds2,
2820                               vect_get_vec_def_for_operand (op2, stmt, NULL));
2821             }
2822         }
2823       else
2824         {
2825           vect_get_vec_defs_for_stmt_copy (dt, &vec_oprnds0, &vec_oprnds1);
2826           if (op_type == ternary_op)
2827             {
2828               tree vec_oprnd = VEC_pop (tree, vec_oprnds2);
2829               VEC_quick_push (tree, vec_oprnds2,
2830                               vect_get_vec_def_for_stmt_copy (dt[2],
2831                                                               vec_oprnd));
2832             }
2833         }
2834
2835       /* Arguments are ready.  Create the new vector stmt.  */
2836       FOR_EACH_VEC_ELT (tree, vec_oprnds0, i, vop0)
2837         {
2838           vop1 = ((op_type == binary_op || op_type == ternary_op)
2839                   ? VEC_index (tree, vec_oprnds1, i) : NULL_TREE);
2840           vop2 = ((op_type == ternary_op)
2841                   ? VEC_index (tree, vec_oprnds2, i) : NULL_TREE);
2842           new_stmt = gimple_build_assign_with_ops3 (code, vec_dest,
2843                                                     vop0, vop1, vop2);
2844           new_temp = make_ssa_name (vec_dest, new_stmt);
2845           gimple_assign_set_lhs (new_stmt, new_temp);
2846           vect_finish_stmt_generation (stmt, new_stmt, gsi);
2847           if (slp_node)
2848             VEC_quick_push (gimple, SLP_TREE_VEC_STMTS (slp_node), new_stmt);
2849         }
2850
2851       if (slp_node)
2852         continue;
2853
2854       if (j == 0)
2855         STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
2856       else
2857         STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
2858       prev_stmt_info = vinfo_for_stmt (new_stmt);
2859     }
2860
2861   VEC_free (tree, heap, vec_oprnds0);
2862   if (vec_oprnds1)
2863     VEC_free (tree, heap, vec_oprnds1);
2864   if (vec_oprnds2)
2865     VEC_free (tree, heap, vec_oprnds2);
2866
2867   return true;
2868 }
2869
2870
2871 /* Get vectorized definitions for loop-based vectorization.  For the first
2872    operand we call vect_get_vec_def_for_operand() (with OPRND containing
2873    scalar operand), and for the rest we get a copy with
2874    vect_get_vec_def_for_stmt_copy() using the previous vector definition
2875    (stored in OPRND). See vect_get_vec_def_for_stmt_copy() for details.
2876    The vectors are collected into VEC_OPRNDS.  */
2877
2878 static void
2879 vect_get_loop_based_defs (tree *oprnd, gimple stmt, enum vect_def_type dt,
2880                           VEC (tree, heap) **vec_oprnds, int multi_step_cvt)
2881 {
2882   tree vec_oprnd;
2883
2884   /* Get first vector operand.  */
2885   /* All the vector operands except the very first one (that is scalar oprnd)
2886      are stmt copies.  */
2887   if (TREE_CODE (TREE_TYPE (*oprnd)) != VECTOR_TYPE)
2888     vec_oprnd = vect_get_vec_def_for_operand (*oprnd, stmt, NULL);
2889   else
2890     vec_oprnd = vect_get_vec_def_for_stmt_copy (dt, *oprnd);
2891
2892   VEC_quick_push (tree, *vec_oprnds, vec_oprnd);
2893
2894   /* Get second vector operand.  */
2895   vec_oprnd = vect_get_vec_def_for_stmt_copy (dt, vec_oprnd);
2896   VEC_quick_push (tree, *vec_oprnds, vec_oprnd);
2897
2898   *oprnd = vec_oprnd;
2899
2900   /* For conversion in multiple steps, continue to get operands
2901      recursively.  */
2902   if (multi_step_cvt)
2903     vect_get_loop_based_defs (oprnd, stmt, dt, vec_oprnds,  multi_step_cvt - 1);
2904 }
2905
2906
2907 /* Create vectorized demotion statements for vector operands from VEC_OPRNDS.
2908    For multi-step conversions store the resulting vectors and call the function
2909    recursively.  */
2910
2911 static void
2912 vect_create_vectorized_demotion_stmts (VEC (tree, heap) **vec_oprnds,
2913                                        int multi_step_cvt, gimple stmt,
2914                                        VEC (tree, heap) *vec_dsts,
2915                                        gimple_stmt_iterator *gsi,
2916                                        slp_tree slp_node, enum tree_code code,
2917                                        stmt_vec_info *prev_stmt_info)
2918 {
2919   unsigned int i;
2920   tree vop0, vop1, new_tmp, vec_dest;
2921   gimple new_stmt;
2922   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
2923
2924   vec_dest = VEC_pop (tree, vec_dsts);
2925
2926   for (i = 0; i < VEC_length (tree, *vec_oprnds); i += 2)
2927     {
2928       /* Create demotion operation.  */
2929       vop0 = VEC_index (tree, *vec_oprnds, i);
2930       vop1 = VEC_index (tree, *vec_oprnds, i + 1);
2931       new_stmt = gimple_build_assign_with_ops (code, vec_dest, vop0, vop1);
2932       new_tmp = make_ssa_name (vec_dest, new_stmt);
2933       gimple_assign_set_lhs (new_stmt, new_tmp);
2934       vect_finish_stmt_generation (stmt, new_stmt, gsi);
2935
2936       if (multi_step_cvt)
2937         /* Store the resulting vector for next recursive call.  */
2938         VEC_replace (tree, *vec_oprnds, i/2, new_tmp);
2939       else
2940         {
2941           /* This is the last step of the conversion sequence. Store the
2942              vectors in SLP_NODE or in vector info of the scalar statement
2943              (or in STMT_VINFO_RELATED_STMT chain).  */
2944           if (slp_node)
2945             VEC_quick_push (gimple, SLP_TREE_VEC_STMTS (slp_node), new_stmt);
2946           else
2947             {
2948               if (!*prev_stmt_info)
2949                 STMT_VINFO_VEC_STMT (stmt_info) = new_stmt;
2950               else
2951                 STMT_VINFO_RELATED_STMT (*prev_stmt_info) = new_stmt;
2952
2953               *prev_stmt_info = vinfo_for_stmt (new_stmt);
2954             }
2955         }
2956     }
2957
2958   /* For multi-step demotion operations we first generate demotion operations
2959      from the source type to the intermediate types, and then combine the
2960      results (stored in VEC_OPRNDS) in demotion operation to the destination
2961      type.  */
2962   if (multi_step_cvt)
2963     {
2964       /* At each level of recursion we have have of the operands we had at the
2965          previous level.  */
2966       VEC_truncate (tree, *vec_oprnds, (i+1)/2);
2967       vect_create_vectorized_demotion_stmts (vec_oprnds, multi_step_cvt - 1,
2968                                              stmt, vec_dsts, gsi, slp_node,
2969                                              code, prev_stmt_info);
2970     }
2971 }
2972
2973
2974 /* Function vectorizable_type_demotion
2975
2976    Check if STMT performs a binary or unary operation that involves
2977    type demotion, and if it can be vectorized.
2978    If VEC_STMT is also passed, vectorize the STMT: create a vectorized
2979    stmt to replace it, put it in VEC_STMT, and insert it at BSI.
2980    Return FALSE if not a vectorizable STMT, TRUE otherwise.  */
2981
2982 static bool
2983 vectorizable_type_demotion (gimple stmt, gimple_stmt_iterator *gsi,
2984                             gimple *vec_stmt, slp_tree slp_node)
2985 {
2986   tree vec_dest;
2987   tree scalar_dest;
2988   tree op0;
2989   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
2990   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
2991   enum tree_code code, code1 = ERROR_MARK;
2992   tree def;
2993   gimple def_stmt;
2994   enum vect_def_type dt[2] = {vect_unknown_def_type, vect_unknown_def_type};
2995   stmt_vec_info prev_stmt_info;
2996   int nunits_in;
2997   int nunits_out;
2998   tree vectype_out;
2999   int ncopies;
3000   int j, i;
3001   tree vectype_in;
3002   int multi_step_cvt = 0;
3003   VEC (tree, heap) *vec_oprnds0 = NULL;
3004   VEC (tree, heap) *vec_dsts = NULL, *interm_types = NULL, *tmp_vec_dsts = NULL;
3005   tree last_oprnd, intermediate_type;
3006
3007   /* FORNOW: not supported by basic block SLP vectorization.  */
3008   gcc_assert (loop_vinfo);
3009
3010   if (!STMT_VINFO_RELEVANT_P (stmt_info))
3011     return false;
3012
3013   if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def)
3014     return false;
3015
3016   /* Is STMT a vectorizable type-demotion operation?  */
3017   if (!is_gimple_assign (stmt))
3018     return false;
3019
3020   if (TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME)
3021     return false;
3022
3023   code = gimple_assign_rhs_code (stmt);
3024   if (!CONVERT_EXPR_CODE_P (code))
3025     return false;
3026
3027   scalar_dest = gimple_assign_lhs (stmt);
3028   vectype_out = STMT_VINFO_VECTYPE (stmt_info);
3029
3030   /* Check the operands of the operation.  */
3031   op0 = gimple_assign_rhs1 (stmt);
3032   if (! ((INTEGRAL_TYPE_P (TREE_TYPE (scalar_dest))
3033           && INTEGRAL_TYPE_P (TREE_TYPE (op0)))
3034          || (SCALAR_FLOAT_TYPE_P (TREE_TYPE (scalar_dest))
3035              && SCALAR_FLOAT_TYPE_P (TREE_TYPE (op0))
3036              && CONVERT_EXPR_CODE_P (code))))
3037     return false;
3038   if (!vect_is_simple_use_1 (op0, loop_vinfo, NULL,
3039                              &def_stmt, &def, &dt[0], &vectype_in))
3040     {
3041       if (vect_print_dump_info (REPORT_DETAILS))
3042         fprintf (vect_dump, "use not simple.");
3043       return false;
3044     }
3045   /* If op0 is an external def use a vector type with the
3046      same size as the output vector type if possible.  */
3047   if (!vectype_in)
3048     vectype_in = get_same_sized_vectype (TREE_TYPE (op0), vectype_out);
3049   if (vec_stmt)
3050     gcc_assert (vectype_in);
3051   if (!vectype_in)
3052     {
3053       if (vect_print_dump_info (REPORT_DETAILS))
3054         {
3055           fprintf (vect_dump, "no vectype for scalar type ");
3056           print_generic_expr (vect_dump, TREE_TYPE (op0), TDF_SLIM);
3057         }
3058
3059       return false;
3060     }
3061
3062   nunits_in = TYPE_VECTOR_SUBPARTS (vectype_in);
3063   nunits_out = TYPE_VECTOR_SUBPARTS (vectype_out);
3064   if (nunits_in >= nunits_out)
3065     return false;
3066
3067   /* Multiple types in SLP are handled by creating the appropriate number of
3068      vectorized stmts for each SLP node.  Hence, NCOPIES is always 1 in
3069      case of SLP.  */
3070   if (slp_node || PURE_SLP_STMT (stmt_info))
3071     ncopies = 1;
3072   else
3073     ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits_out;
3074   gcc_assert (ncopies >= 1);
3075
3076   /* Supportable by target?  */
3077   if (!supportable_narrowing_operation (code, vectype_out, vectype_in,
3078                                         &code1, &multi_step_cvt, &interm_types))
3079     return false;
3080
3081   if (!vec_stmt) /* transformation not required.  */
3082     {
3083       STMT_VINFO_TYPE (stmt_info) = type_demotion_vec_info_type;
3084       if (vect_print_dump_info (REPORT_DETAILS))
3085         fprintf (vect_dump, "=== vectorizable_demotion ===");
3086       vect_model_simple_cost (stmt_info, ncopies, dt, NULL);
3087       return true;
3088     }
3089
3090   /** Transform.  **/
3091   if (vect_print_dump_info (REPORT_DETAILS))
3092     fprintf (vect_dump, "transform type demotion operation. ncopies = %d.",
3093              ncopies);
3094
3095   /* In case of multi-step demotion, we first generate demotion operations to
3096      the intermediate types, and then from that types to the final one.
3097      We create vector destinations for the intermediate type (TYPES) received
3098      from supportable_narrowing_operation, and store them in the correct order
3099      for future use in vect_create_vectorized_demotion_stmts().  */
3100   if (multi_step_cvt)
3101     vec_dsts = VEC_alloc (tree, heap, multi_step_cvt + 1);
3102   else
3103     vec_dsts = VEC_alloc (tree, heap, 1);
3104
3105   vec_dest = vect_create_destination_var (scalar_dest, vectype_out);
3106   VEC_quick_push (tree, vec_dsts, vec_dest);
3107
3108   if (multi_step_cvt)
3109     {
3110       for (i = VEC_length (tree, interm_types) - 1;
3111            VEC_iterate (tree, interm_types, i, intermediate_type); i--)
3112         {
3113           vec_dest = vect_create_destination_var (scalar_dest,
3114                                                   intermediate_type);
3115           VEC_quick_push (tree, vec_dsts, vec_dest);
3116         }
3117     }
3118
3119   /* In case the vectorization factor (VF) is bigger than the number
3120      of elements that we can fit in a vectype (nunits), we have to generate
3121      more than one vector stmt - i.e - we need to "unroll" the
3122      vector stmt by a factor VF/nunits.   */
3123   last_oprnd = op0;
3124   prev_stmt_info = NULL;
3125   for (j = 0; j < ncopies; j++)
3126     {
3127       /* Handle uses.  */
3128       if (slp_node)
3129         vect_get_slp_defs (op0, NULL_TREE, slp_node, &vec_oprnds0, NULL, -1);
3130       else
3131         {
3132           VEC_free (tree, heap, vec_oprnds0);
3133           vec_oprnds0 = VEC_alloc (tree, heap,
3134                         (multi_step_cvt ? vect_pow2 (multi_step_cvt) * 2 : 2));
3135           vect_get_loop_based_defs (&last_oprnd, stmt, dt[0], &vec_oprnds0,
3136                                     vect_pow2 (multi_step_cvt) - 1);
3137         }
3138
3139       /* Arguments are ready.  Create the new vector stmts.  */
3140       tmp_vec_dsts = VEC_copy (tree, heap, vec_dsts);
3141       vect_create_vectorized_demotion_stmts (&vec_oprnds0,
3142                                              multi_step_cvt, stmt, tmp_vec_dsts,
3143                                              gsi, slp_node, code1,
3144                                              &prev_stmt_info);
3145     }
3146
3147   VEC_free (tree, heap, vec_oprnds0);
3148   VEC_free (tree, heap, vec_dsts);
3149   VEC_free (tree, heap, tmp_vec_dsts);
3150   VEC_free (tree, heap, interm_types);
3151
3152   *vec_stmt = STMT_VINFO_VEC_STMT (stmt_info);
3153   return true;
3154 }
3155
3156
3157 /* Create vectorized promotion statements for vector operands from VEC_OPRNDS0
3158    and VEC_OPRNDS1 (for binary operations).  For multi-step conversions store
3159    the resulting vectors and call the function recursively.  */
3160
3161 static void
3162 vect_create_vectorized_promotion_stmts (VEC (tree, heap) **vec_oprnds0,
3163                                         VEC (tree, heap) **vec_oprnds1,
3164                                         int multi_step_cvt, gimple stmt,
3165                                         VEC (tree, heap) *vec_dsts,
3166                                         gimple_stmt_iterator *gsi,
3167                                         slp_tree slp_node, enum tree_code code1,
3168                                         enum tree_code code2, tree decl1,
3169                                         tree decl2, int op_type,
3170                                         stmt_vec_info *prev_stmt_info)
3171 {
3172   int i;
3173   tree vop0, vop1, new_tmp1, new_tmp2, vec_dest;
3174   gimple new_stmt1, new_stmt2;
3175   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
3176   VEC (tree, heap) *vec_tmp;
3177
3178   vec_dest = VEC_pop (tree, vec_dsts);
3179   vec_tmp = VEC_alloc (tree, heap, VEC_length (tree, *vec_oprnds0) * 2);
3180
3181   FOR_EACH_VEC_ELT (tree, *vec_oprnds0, i, vop0)
3182     {
3183       if (op_type == binary_op)
3184         vop1 = VEC_index (tree, *vec_oprnds1, i);
3185       else
3186         vop1 = NULL_TREE;
3187
3188       /* Generate the two halves of promotion operation.  */
3189       new_stmt1 = vect_gen_widened_results_half (code1, decl1, vop0, vop1,
3190                                                  op_type, vec_dest, gsi, stmt);
3191       new_stmt2 = vect_gen_widened_results_half (code2, decl2, vop0, vop1,
3192                                                  op_type, vec_dest, gsi, stmt);
3193       if (is_gimple_call (new_stmt1))
3194         {
3195           new_tmp1 = gimple_call_lhs (new_stmt1);
3196           new_tmp2 = gimple_call_lhs (new_stmt2);
3197         }
3198       else
3199         {
3200           new_tmp1 = gimple_assign_lhs (new_stmt1);
3201           new_tmp2 = gimple_assign_lhs (new_stmt2);
3202         }
3203
3204       if (multi_step_cvt)
3205         {
3206           /* Store the results for the recursive call.  */
3207           VEC_quick_push (tree, vec_tmp, new_tmp1);
3208           VEC_quick_push (tree, vec_tmp, new_tmp2);
3209         }
3210       else
3211         {
3212           /* Last step of promotion sequience - store the results.  */
3213           if (slp_node)
3214             {
3215               VEC_quick_push (gimple, SLP_TREE_VEC_STMTS (slp_node), new_stmt1);
3216               VEC_quick_push (gimple, SLP_TREE_VEC_STMTS (slp_node), new_stmt2);
3217             }
3218           else
3219             {
3220               if (!*prev_stmt_info)
3221                 STMT_VINFO_VEC_STMT (stmt_info) = new_stmt1;
3222               else
3223                 STMT_VINFO_RELATED_STMT (*prev_stmt_info) = new_stmt1;
3224
3225               *prev_stmt_info = vinfo_for_stmt (new_stmt1);
3226               STMT_VINFO_RELATED_STMT (*prev_stmt_info) = new_stmt2;
3227               *prev_stmt_info = vinfo_for_stmt (new_stmt2);
3228             }
3229         }
3230     }
3231
3232   if (multi_step_cvt)
3233     {
3234       /* For multi-step promotion operation we first generate we call the
3235          function recurcively for every stage.  We start from the input type,
3236          create promotion operations to the intermediate types, and then
3237          create promotions to the output type.  */
3238       *vec_oprnds0 = VEC_copy (tree, heap, vec_tmp);
3239       vect_create_vectorized_promotion_stmts (vec_oprnds0, vec_oprnds1,
3240                                               multi_step_cvt - 1, stmt,
3241                                               vec_dsts, gsi, slp_node, code1,
3242                                               code2, decl2, decl2, op_type,
3243                                               prev_stmt_info);
3244     }
3245
3246   VEC_free (tree, heap, vec_tmp);
3247 }
3248
3249
3250 /* Function vectorizable_type_promotion
3251
3252    Check if STMT performs a binary or unary operation that involves
3253    type promotion, and if it can be vectorized.
3254    If VEC_STMT is also passed, vectorize the STMT: create a vectorized
3255    stmt to replace it, put it in VEC_STMT, and insert it at BSI.
3256    Return FALSE if not a vectorizable STMT, TRUE otherwise.  */
3257
3258 static bool
3259 vectorizable_type_promotion (gimple stmt, gimple_stmt_iterator *gsi,
3260                              gimple *vec_stmt, slp_tree slp_node)
3261 {
3262   tree vec_dest;
3263   tree scalar_dest;
3264   tree op0, op1 = NULL;
3265   tree vec_oprnd0=NULL, vec_oprnd1=NULL;
3266   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
3267   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
3268   enum tree_code code, code1 = ERROR_MARK, code2 = ERROR_MARK;
3269   tree decl1 = NULL_TREE, decl2 = NULL_TREE;
3270   int op_type;
3271   tree def;
3272   gimple def_stmt;
3273   enum vect_def_type dt[2] = {vect_unknown_def_type, vect_unknown_def_type};
3274   stmt_vec_info prev_stmt_info;
3275   int nunits_in;
3276   int nunits_out;
3277   tree vectype_out;
3278   int ncopies;
3279   int j, i;
3280   tree vectype_in;
3281   tree intermediate_type = NULL_TREE;
3282   int multi_step_cvt = 0;
3283   VEC (tree, heap) *vec_oprnds0 = NULL, *vec_oprnds1 = NULL;
3284   VEC (tree, heap) *vec_dsts = NULL, *interm_types = NULL, *tmp_vec_dsts = NULL;
3285
3286   /* FORNOW: not supported by basic block SLP vectorization.  */
3287   gcc_assert (loop_vinfo);
3288
3289   if (!STMT_VINFO_RELEVANT_P (stmt_info))
3290     return false;
3291
3292   if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def)
3293     return false;
3294
3295   /* Is STMT a vectorizable type-promotion operation?  */
3296   if (!is_gimple_assign (stmt))
3297     return false;
3298
3299   if (TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME)
3300     return false;
3301
3302   code = gimple_assign_rhs_code (stmt);
3303   if (!CONVERT_EXPR_CODE_P (code)
3304       && code != WIDEN_MULT_EXPR)
3305     return false;
3306
3307   scalar_dest = gimple_assign_lhs (stmt);
3308   vectype_out = STMT_VINFO_VECTYPE (stmt_info);
3309
3310   /* Check the operands of the operation.  */
3311   op0 = gimple_assign_rhs1 (stmt);
3312   if (! ((INTEGRAL_TYPE_P (TREE_TYPE (scalar_dest))
3313           && INTEGRAL_TYPE_P (TREE_TYPE (op0)))
3314          || (SCALAR_FLOAT_TYPE_P (TREE_TYPE (scalar_dest))
3315              && SCALAR_FLOAT_TYPE_P (TREE_TYPE (op0))
3316              && CONVERT_EXPR_CODE_P (code))))
3317     return false;
3318   if (!vect_is_simple_use_1 (op0, loop_vinfo, NULL,
3319                              &def_stmt, &def, &dt[0], &vectype_in))
3320     {
3321       if (vect_print_dump_info (REPORT_DETAILS))
3322         fprintf (vect_dump, "use not simple.");
3323       return false;
3324     }
3325
3326   op_type = TREE_CODE_LENGTH (code);
3327   if (op_type == binary_op)
3328     {
3329       bool ok;
3330
3331       op1 = gimple_assign_rhs2 (stmt);
3332       if (code == WIDEN_MULT_EXPR)
3333         {
3334           /* For WIDEN_MULT_EXPR, if OP0 is a constant, use the type of
3335              OP1.  */
3336           if (CONSTANT_CLASS_P (op0))
3337             ok = vect_is_simple_use_1 (op1, loop_vinfo, NULL,
3338                              &def_stmt, &def, &dt[1], &vectype_in);
3339           else
3340             ok = vect_is_simple_use (op1, loop_vinfo, NULL, &def_stmt, &def,
3341                                      &dt[1]);
3342
3343           if (!ok)
3344             {
3345               if (vect_print_dump_info (REPORT_DETAILS))
3346                 fprintf (vect_dump, "use not simple.");
3347               return false;
3348             }
3349         }        
3350     }
3351
3352   /* If op0 is an external or constant def use a vector type with
3353      the same size as the output vector type.  */
3354   if (!vectype_in)
3355     vectype_in = get_same_sized_vectype (TREE_TYPE (op0), vectype_out);
3356   if (vec_stmt)
3357     gcc_assert (vectype_in);
3358   if (!vectype_in)
3359     {
3360       if (vect_print_dump_info (REPORT_DETAILS))
3361         {
3362           fprintf (vect_dump, "no vectype for scalar type ");
3363           print_generic_expr (vect_dump, TREE_TYPE (op0), TDF_SLIM);
3364         }
3365
3366       return false;
3367     }
3368
3369   nunits_in = TYPE_VECTOR_SUBPARTS (vectype_in);
3370   nunits_out = TYPE_VECTOR_SUBPARTS (vectype_out);
3371   if (nunits_in <= nunits_out)
3372     return false;
3373
3374   /* Multiple types in SLP are handled by creating the appropriate number of
3375      vectorized stmts for each SLP node.  Hence, NCOPIES is always 1 in
3376      case of SLP.  */
3377   if (slp_node || PURE_SLP_STMT (stmt_info))
3378     ncopies = 1;
3379   else
3380     ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits_in;
3381
3382   gcc_assert (ncopies >= 1);
3383
3384   /* Supportable by target?  */
3385   if (!supportable_widening_operation (code, stmt, vectype_out, vectype_in,
3386                                        &decl1, &decl2, &code1, &code2,
3387                                        &multi_step_cvt, &interm_types))
3388     return false;
3389
3390   /* Binary widening operation can only be supported directly by the
3391      architecture.  */
3392   gcc_assert (!(multi_step_cvt && op_type == binary_op));
3393
3394   if (!vec_stmt) /* transformation not required.  */
3395     {
3396       STMT_VINFO_TYPE (stmt_info) = type_promotion_vec_info_type;
3397       if (vect_print_dump_info (REPORT_DETAILS))
3398         fprintf (vect_dump, "=== vectorizable_promotion ===");
3399       vect_model_simple_cost (stmt_info, 2*ncopies, dt, NULL);
3400       return true;
3401     }
3402
3403   /** Transform.  **/
3404
3405   if (vect_print_dump_info (REPORT_DETAILS))
3406     fprintf (vect_dump, "transform type promotion operation. ncopies = %d.",
3407                         ncopies);
3408
3409   if (code == WIDEN_MULT_EXPR)
3410     {
3411       if (CONSTANT_CLASS_P (op0))
3412         op0 = fold_convert (TREE_TYPE (op1), op0);
3413       else if (CONSTANT_CLASS_P (op1))
3414         op1 = fold_convert (TREE_TYPE (op0), op1);
3415     }
3416
3417   /* Handle def.  */
3418   /* In case of multi-step promotion, we first generate promotion operations
3419      to the intermediate types, and then from that types to the final one.
3420      We store vector destination in VEC_DSTS in the correct order for
3421      recursive creation of promotion operations in
3422      vect_create_vectorized_promotion_stmts(). Vector destinations are created
3423      according to TYPES recieved from supportable_widening_operation().   */
3424   if (multi_step_cvt)
3425     vec_dsts = VEC_alloc (tree, heap, multi_step_cvt + 1);
3426   else
3427     vec_dsts = VEC_alloc (tree, heap, 1);
3428
3429   vec_dest = vect_create_destination_var (scalar_dest, vectype_out);
3430   VEC_quick_push (tree, vec_dsts, vec_dest);
3431
3432   if (multi_step_cvt)
3433     {
3434       for (i = VEC_length (tree, interm_types) - 1;
3435            VEC_iterate (tree, interm_types, i, intermediate_type); i--)
3436         {
3437           vec_dest = vect_create_destination_var (scalar_dest,
3438                                                   intermediate_type);
3439           VEC_quick_push (tree, vec_dsts, vec_dest);
3440         }
3441     }
3442
3443   if (!slp_node)
3444     {
3445       vec_oprnds0 = VEC_alloc (tree, heap,
3446                             (multi_step_cvt ? vect_pow2 (multi_step_cvt) : 1));
3447       if (op_type == binary_op)
3448         vec_oprnds1 = VEC_alloc (tree, heap, 1);
3449     }
3450
3451   /* In case the vectorization factor (VF) is bigger than the number
3452      of elements that we can fit in a vectype (nunits), we have to generate
3453      more than one vector stmt - i.e - we need to "unroll" the
3454      vector stmt by a factor VF/nunits.   */
3455
3456   prev_stmt_info = NULL;
3457   for (j = 0; j < ncopies; j++)
3458     {
3459       /* Handle uses.  */
3460       if (j == 0)
3461         {
3462           if (slp_node)
3463               vect_get_slp_defs (op0, op1, slp_node, &vec_oprnds0,
3464                                  &vec_oprnds1, -1);
3465           else
3466             {
3467               vec_oprnd0 = vect_get_vec_def_for_operand (op0, stmt, NULL);
3468               VEC_quick_push (tree, vec_oprnds0, vec_oprnd0);
3469               if (op_type == binary_op)
3470                 {
3471                   vec_oprnd1 = vect_get_vec_def_for_operand (op1, stmt, NULL);
3472                   VEC_quick_push (tree, vec_oprnds1, vec_oprnd1);
3473                 }
3474             }
3475         }
3476       else
3477         {
3478           vec_oprnd0 = vect_get_vec_def_for_stmt_copy (dt[0], vec_oprnd0);
3479           VEC_replace (tree, vec_oprnds0, 0, vec_oprnd0);
3480           if (op_type == binary_op)
3481             {
3482               vec_oprnd1 = vect_get_vec_def_for_stmt_copy (dt[1], vec_oprnd1);
3483               VEC_replace (tree, vec_oprnds1, 0, vec_oprnd1);
3484             }
3485         }
3486
3487       /* Arguments are ready.  Create the new vector stmts.  */
3488       tmp_vec_dsts = VEC_copy (tree, heap, vec_dsts);
3489       vect_create_vectorized_promotion_stmts (&vec_oprnds0, &vec_oprnds1,
3490                                               multi_step_cvt, stmt,
3491                                               tmp_vec_dsts,
3492                                               gsi, slp_node, code1, code2,
3493                                               decl1, decl2, op_type,
3494                                               &prev_stmt_info);
3495     }
3496
3497   VEC_free (tree, heap, vec_dsts);
3498   VEC_free (tree, heap, tmp_vec_dsts);
3499   VEC_free (tree, heap, interm_types);
3500   VEC_free (tree, heap, vec_oprnds0);
3501   VEC_free (tree, heap, vec_oprnds1);
3502
3503   *vec_stmt = STMT_VINFO_VEC_STMT (stmt_info);
3504   return true;
3505 }
3506
3507
3508 /* Function vectorizable_store.
3509
3510    Check if STMT defines a non scalar data-ref (array/pointer/structure) that
3511    can be vectorized.
3512    If VEC_STMT is also passed, vectorize the STMT: create a vectorized
3513    stmt to replace it, put it in VEC_STMT, and insert it at BSI.
3514    Return FALSE if not a vectorizable STMT, TRUE otherwise.  */
3515
3516 static bool
3517 vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
3518                     slp_tree slp_node)
3519 {
3520   tree scalar_dest;
3521   tree data_ref;
3522   tree op;
3523   tree vec_oprnd = NULL_TREE;
3524   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
3525   struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info), *first_dr = NULL;
3526   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
3527   tree elem_type;
3528   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
3529   struct loop *loop = NULL;
3530   enum machine_mode vec_mode;
3531   tree dummy;
3532   enum dr_alignment_support alignment_support_scheme;
3533   tree def;
3534   gimple def_stmt;
3535   enum vect_def_type dt;
3536   stmt_vec_info prev_stmt_info = NULL;
3537   tree dataref_ptr = NULL_TREE;
3538   int nunits = TYPE_VECTOR_SUBPARTS (vectype);
3539   int ncopies;
3540   int j;
3541   gimple next_stmt, first_stmt = NULL;
3542   bool strided_store = false;
3543   bool store_lanes_p = false;
3544   unsigned int group_size, i;
3545   VEC(tree,heap) *dr_chain = NULL, *oprnds = NULL, *result_chain = NULL;
3546   bool inv_p;
3547   VEC(tree,heap) *vec_oprnds = NULL;
3548   bool slp = (slp_node != NULL);
3549   unsigned int vec_num;
3550   bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
3551   tree aggr_type;
3552
3553   if (loop_vinfo)
3554     loop = LOOP_VINFO_LOOP (loop_vinfo);
3555
3556   /* Multiple types in SLP are handled by creating the appropriate number of
3557      vectorized stmts for each SLP node. Hence, NCOPIES is always 1 in
3558      case of SLP.  */
3559   if (slp || PURE_SLP_STMT (stmt_info))
3560     ncopies = 1;
3561   else
3562     ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits;
3563
3564   gcc_assert (ncopies >= 1);
3565
3566   /* FORNOW. This restriction should be relaxed.  */
3567   if (loop && nested_in_vect_loop_p (loop, stmt) && ncopies > 1)
3568     {
3569       if (vect_print_dump_info (REPORT_DETAILS))
3570         fprintf (vect_dump, "multiple types in nested loop.");
3571       return false;
3572     }
3573
3574   if (!STMT_VINFO_RELEVANT_P (stmt_info) && !bb_vinfo)
3575     return false;
3576
3577   if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def)
3578     return false;
3579
3580   /* Is vectorizable store? */
3581
3582   if (!is_gimple_assign (stmt))
3583     return false;
3584
3585   scalar_dest = gimple_assign_lhs (stmt);
3586   if (TREE_CODE (scalar_dest) != ARRAY_REF
3587       && TREE_CODE (scalar_dest) != INDIRECT_REF
3588       && TREE_CODE (scalar_dest) != COMPONENT_REF
3589       && TREE_CODE (scalar_dest) != IMAGPART_EXPR
3590       && TREE_CODE (scalar_dest) != REALPART_EXPR
3591       && TREE_CODE (scalar_dest) != MEM_REF)
3592     return false;
3593
3594   gcc_assert (gimple_assign_single_p (stmt));
3595   op = gimple_assign_rhs1 (stmt);
3596   if (!vect_is_simple_use (op, loop_vinfo, bb_vinfo, &def_stmt, &def, &dt))
3597     {
3598       if (vect_print_dump_info (REPORT_DETAILS))
3599         fprintf (vect_dump, "use not simple.");
3600       return false;
3601     }
3602
3603   /* The scalar rhs type needs to be trivially convertible to the vector
3604      component type.  This should always be the case.  */
3605   elem_type = TREE_TYPE (vectype);
3606   if (!useless_type_conversion_p (elem_type, TREE_TYPE (op)))
3607     {
3608       if (vect_print_dump_info (REPORT_DETAILS))
3609         fprintf (vect_dump, "???  operands of different types");
3610       return false;
3611     }
3612
3613   vec_mode = TYPE_MODE (vectype);
3614   /* FORNOW. In some cases can vectorize even if data-type not supported
3615      (e.g. - array initialization with 0).  */
3616   if (optab_handler (mov_optab, vec_mode) == CODE_FOR_nothing)
3617     return false;
3618
3619   if (!STMT_VINFO_DATA_REF (stmt_info))
3620     return false;
3621
3622   if (tree_int_cst_compare (DR_STEP (dr), size_zero_node) < 0)
3623     {
3624       if (vect_print_dump_info (REPORT_DETAILS))
3625         fprintf (vect_dump, "negative step for store.");
3626       return false;
3627     }
3628
3629   if (STMT_VINFO_STRIDED_ACCESS (stmt_info))
3630     {
3631       strided_store = true;
3632       first_stmt = GROUP_FIRST_ELEMENT (stmt_info);
3633       if (!slp && !PURE_SLP_STMT (stmt_info))
3634         {
3635           group_size = GROUP_SIZE (vinfo_for_stmt (first_stmt));
3636           if (vect_store_lanes_supported (vectype, group_size))
3637             store_lanes_p = true;
3638           else if (!vect_strided_store_supported (vectype, group_size))
3639             return false;
3640         }
3641
3642       if (first_stmt == stmt)
3643         {
3644           /* STMT is the leader of the group. Check the operands of all the
3645              stmts of the group.  */
3646           next_stmt = GROUP_NEXT_ELEMENT (stmt_info);
3647           while (next_stmt)
3648             {
3649               gcc_assert (gimple_assign_single_p (next_stmt));
3650               op = gimple_assign_rhs1 (next_stmt);
3651               if (!vect_is_simple_use (op, loop_vinfo, bb_vinfo, &def_stmt,
3652                                        &def, &dt))
3653                 {
3654                   if (vect_print_dump_info (REPORT_DETAILS))
3655                     fprintf (vect_dump, "use not simple.");
3656                   return false;
3657                 }
3658               next_stmt = GROUP_NEXT_ELEMENT (vinfo_for_stmt (next_stmt));
3659             }
3660         }
3661     }
3662
3663   if (!vec_stmt) /* transformation not required.  */
3664     {
3665       STMT_VINFO_TYPE (stmt_info) = store_vec_info_type;
3666       vect_model_store_cost (stmt_info, ncopies, store_lanes_p, dt, NULL);
3667       return true;
3668     }
3669
3670   /** Transform.  **/
3671
3672   if (strided_store)
3673     {
3674       first_dr = STMT_VINFO_DATA_REF (vinfo_for_stmt (first_stmt));
3675       group_size = GROUP_SIZE (vinfo_for_stmt (first_stmt));
3676
3677       GROUP_STORE_COUNT (vinfo_for_stmt (first_stmt))++;
3678
3679       /* FORNOW */
3680       gcc_assert (!loop || !nested_in_vect_loop_p (loop, stmt));
3681
3682       /* We vectorize all the stmts of the interleaving group when we
3683          reach the last stmt in the group.  */
3684       if (GROUP_STORE_COUNT (vinfo_for_stmt (first_stmt))
3685           < GROUP_SIZE (vinfo_for_stmt (first_stmt))
3686           && !slp)
3687         {
3688           *vec_stmt = NULL;
3689           return true;
3690         }
3691
3692       if (slp)
3693         {
3694           strided_store = false;
3695           /* VEC_NUM is the number of vect stmts to be created for this 
3696              group.  */
3697           vec_num = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node);
3698           first_stmt = VEC_index (gimple, SLP_TREE_SCALAR_STMTS (slp_node), 0); 
3699           first_dr = STMT_VINFO_DATA_REF (vinfo_for_stmt (first_stmt));
3700         } 
3701       else
3702         /* VEC_NUM is the number of vect stmts to be created for this 
3703            group.  */
3704         vec_num = group_size;
3705     }
3706   else
3707     {
3708       first_stmt = stmt;
3709       first_dr = dr;
3710       group_size = vec_num = 1;
3711     }
3712
3713   if (vect_print_dump_info (REPORT_DETAILS))
3714     fprintf (vect_dump, "transform store. ncopies = %d",ncopies);
3715
3716   dr_chain = VEC_alloc (tree, heap, group_size);
3717   oprnds = VEC_alloc (tree, heap, group_size);
3718
3719   alignment_support_scheme = vect_supportable_dr_alignment (first_dr, false);
3720   gcc_assert (alignment_support_scheme);
3721   /* Targets with store-lane instructions must not require explicit
3722      realignment.  */
3723   gcc_assert (!store_lanes_p
3724               || alignment_support_scheme == dr_aligned
3725               || alignment_support_scheme == dr_unaligned_supported);
3726
3727   if (store_lanes_p)
3728     aggr_type = build_array_type_nelts (elem_type, vec_num * nunits);
3729   else
3730     aggr_type = vectype;
3731
3732   /* In case the vectorization factor (VF) is bigger than the number
3733      of elements that we can fit in a vectype (nunits), we have to generate
3734      more than one vector stmt - i.e - we need to "unroll" the
3735      vector stmt by a factor VF/nunits.  For more details see documentation in
3736      vect_get_vec_def_for_copy_stmt.  */
3737
3738   /* In case of interleaving (non-unit strided access):
3739
3740         S1:  &base + 2 = x2
3741         S2:  &base = x0
3742         S3:  &base + 1 = x1
3743         S4:  &base + 3 = x3
3744
3745      We create vectorized stores starting from base address (the access of the
3746      first stmt in the chain (S2 in the above example), when the last store stmt
3747      of the chain (S4) is reached:
3748
3749         VS1: &base = vx2
3750         VS2: &base + vec_size*1 = vx0
3751         VS3: &base + vec_size*2 = vx1
3752         VS4: &base + vec_size*3 = vx3
3753
3754      Then permutation statements are generated:
3755
3756         VS5: vx5 = VEC_INTERLEAVE_HIGH_EXPR < vx0, vx3 >
3757         VS6: vx6 = VEC_INTERLEAVE_LOW_EXPR < vx0, vx3 >
3758         ...
3759
3760      And they are put in STMT_VINFO_VEC_STMT of the corresponding scalar stmts
3761      (the order of the data-refs in the output of vect_permute_store_chain
3762      corresponds to the order of scalar stmts in the interleaving chain - see
3763      the documentation of vect_permute_store_chain()).
3764
3765      In case of both multiple types and interleaving, above vector stores and
3766      permutation stmts are created for every copy.  The result vector stmts are
3767      put in STMT_VINFO_VEC_STMT for the first copy and in the corresponding
3768      STMT_VINFO_RELATED_STMT for the next copies.
3769   */
3770
3771   prev_stmt_info = NULL;
3772   for (j = 0; j < ncopies; j++)
3773     {
3774       gimple new_stmt;
3775       gimple ptr_incr;
3776
3777       if (j == 0)
3778         {
3779           if (slp)
3780             {
3781               /* Get vectorized arguments for SLP_NODE.  */
3782               vect_get_slp_defs (NULL_TREE, NULL_TREE, slp_node, &vec_oprnds,
3783                                  NULL, -1);
3784
3785               vec_oprnd = VEC_index (tree, vec_oprnds, 0);
3786             }
3787           else
3788             {
3789               /* For interleaved stores we collect vectorized defs for all the
3790                  stores in the group in DR_CHAIN and OPRNDS. DR_CHAIN is then
3791                  used as an input to vect_permute_store_chain(), and OPRNDS as
3792                  an input to vect_get_vec_def_for_stmt_copy() for the next copy.
3793
3794                  If the store is not strided, GROUP_SIZE is 1, and DR_CHAIN and
3795                  OPRNDS are of size 1.  */
3796               next_stmt = first_stmt;
3797               for (i = 0; i < group_size; i++)
3798                 {
3799                   /* Since gaps are not supported for interleaved stores,
3800                      GROUP_SIZE is the exact number of stmts in the chain.
3801                      Therefore, NEXT_STMT can't be NULL_TREE.  In case that
3802                      there is no interleaving, GROUP_SIZE is 1, and only one
3803                      iteration of the loop will be executed.  */
3804                   gcc_assert (next_stmt
3805                               && gimple_assign_single_p (next_stmt));
3806                   op = gimple_assign_rhs1 (next_stmt);
3807
3808                   vec_oprnd = vect_get_vec_def_for_operand (op, next_stmt,
3809                                                             NULL);
3810                   VEC_quick_push(tree, dr_chain, vec_oprnd);
3811                   VEC_quick_push(tree, oprnds, vec_oprnd);
3812                   next_stmt = GROUP_NEXT_ELEMENT (vinfo_for_stmt (next_stmt));
3813                 }
3814             }
3815
3816           /* We should have catched mismatched types earlier.  */
3817           gcc_assert (useless_type_conversion_p (vectype,
3818                                                  TREE_TYPE (vec_oprnd)));
3819           dataref_ptr = vect_create_data_ref_ptr (first_stmt, aggr_type, NULL,
3820                                                   NULL_TREE, &dummy, gsi,
3821                                                   &ptr_incr, false, &inv_p);
3822           gcc_assert (bb_vinfo || !inv_p);
3823         }
3824       else
3825         {
3826           /* For interleaved stores we created vectorized defs for all the
3827              defs stored in OPRNDS in the previous iteration (previous copy).
3828              DR_CHAIN is then used as an input to vect_permute_store_chain(),
3829              and OPRNDS as an input to vect_get_vec_def_for_stmt_copy() for the
3830              next copy.
3831              If the store is not strided, GROUP_SIZE is 1, and DR_CHAIN and
3832              OPRNDS are of size 1.  */
3833           for (i = 0; i < group_size; i++)
3834             {
3835               op = VEC_index (tree, oprnds, i);
3836               vect_is_simple_use (op, loop_vinfo, bb_vinfo, &def_stmt, &def,
3837                                   &dt);
3838               vec_oprnd = vect_get_vec_def_for_stmt_copy (dt, op);
3839               VEC_replace(tree, dr_chain, i, vec_oprnd);
3840               VEC_replace(tree, oprnds, i, vec_oprnd);
3841             }
3842           dataref_ptr = bump_vector_ptr (dataref_ptr, ptr_incr, gsi, stmt,
3843                                          TYPE_SIZE_UNIT (aggr_type));
3844         }
3845
3846       if (store_lanes_p)
3847         {
3848           tree vec_array;
3849
3850           /* Combine all the vectors into an array.  */
3851           vec_array = create_vector_array (vectype, vec_num);
3852           for (i = 0; i < vec_num; i++)
3853             {
3854               vec_oprnd = VEC_index (tree, dr_chain, i);
3855               write_vector_array (stmt, gsi, vec_oprnd, vec_array, i);
3856             }
3857
3858           /* Emit:
3859                MEM_REF[...all elements...] = STORE_LANES (VEC_ARRAY).  */
3860           data_ref = create_array_ref (aggr_type, dataref_ptr, first_dr);
3861           new_stmt = gimple_build_call_internal (IFN_STORE_LANES, 1, vec_array);
3862           gimple_call_set_lhs (new_stmt, data_ref);
3863           vect_finish_stmt_generation (stmt, new_stmt, gsi);
3864           mark_symbols_for_renaming (new_stmt);
3865         }
3866       else
3867         {
3868           new_stmt = NULL;
3869           if (strided_store)
3870             {
3871               result_chain = VEC_alloc (tree, heap, group_size);
3872               /* Permute.  */
3873               vect_permute_store_chain (dr_chain, group_size, stmt, gsi,
3874                                         &result_chain);
3875             }
3876
3877           next_stmt = first_stmt;
3878           for (i = 0; i < vec_num; i++)
3879             {
3880               struct ptr_info_def *pi;
3881
3882               if (i > 0)
3883                 /* Bump the vector pointer.  */
3884                 dataref_ptr = bump_vector_ptr (dataref_ptr, ptr_incr, gsi,
3885                                                stmt, NULL_TREE);
3886
3887               if (slp)
3888                 vec_oprnd = VEC_index (tree, vec_oprnds, i);
3889               else if (strided_store)
3890                 /* For strided stores vectorized defs are interleaved in
3891                    vect_permute_store_chain().  */
3892                 vec_oprnd = VEC_index (tree, result_chain, i);
3893
3894               data_ref = build2 (MEM_REF, TREE_TYPE (vec_oprnd), dataref_ptr,
3895                                  build_int_cst (reference_alias_ptr_type
3896                                                 (DR_REF (first_dr)), 0));
3897               pi = get_ptr_info (dataref_ptr);
3898               pi->align = TYPE_ALIGN_UNIT (vectype);
3899               if (aligned_access_p (first_dr))
3900                 pi->misalign = 0;
3901               else if (DR_MISALIGNMENT (first_dr) == -1)
3902                 {
3903                   TREE_TYPE (data_ref)
3904                     = build_aligned_type (TREE_TYPE (data_ref),
3905                                           TYPE_ALIGN (elem_type));
3906                   pi->align = TYPE_ALIGN_UNIT (elem_type);
3907                   pi->misalign = 0;
3908                 }
3909               else
3910                 {
3911                   TREE_TYPE (data_ref)
3912                     = build_aligned_type (TREE_TYPE (data_ref),
3913                                           TYPE_ALIGN (elem_type));
3914                   pi->misalign = DR_MISALIGNMENT (first_dr);
3915                 }
3916
3917               /* Arguments are ready.  Create the new vector stmt.  */
3918               new_stmt = gimple_build_assign (data_ref, vec_oprnd);
3919               vect_finish_stmt_generation (stmt, new_stmt, gsi);
3920               mark_symbols_for_renaming (new_stmt);
3921
3922               if (slp)
3923                 continue;
3924
3925               next_stmt = GROUP_NEXT_ELEMENT (vinfo_for_stmt (next_stmt));
3926               if (!next_stmt)
3927                 break;
3928             }
3929         }
3930       if (!slp)
3931         {
3932           if (j == 0)
3933             STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
3934           else
3935             STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
3936           prev_stmt_info = vinfo_for_stmt (new_stmt);
3937         }
3938     }
3939
3940   VEC_free (tree, heap, dr_chain);
3941   VEC_free (tree, heap, oprnds);
3942   if (result_chain)
3943     VEC_free (tree, heap, result_chain);
3944   if (vec_oprnds)
3945     VEC_free (tree, heap, vec_oprnds);
3946
3947   return true;
3948 }
3949
3950 /* Given a vector type VECTYPE returns a builtin DECL to be used
3951    for vector permutation and stores a mask into *MASK that implements
3952    reversal of the vector elements.  If that is impossible to do
3953    returns NULL (and *MASK is unchanged).  */
3954
3955 static tree
3956 perm_mask_for_reverse (tree vectype, tree *mask)
3957 {
3958   tree builtin_decl;
3959   tree mask_element_type, mask_type;
3960   tree mask_vec = NULL;
3961   int i;
3962   int nunits;
3963   if (!targetm.vectorize.builtin_vec_perm)
3964     return NULL;
3965
3966   builtin_decl = targetm.vectorize.builtin_vec_perm (vectype,
3967                                                      &mask_element_type);
3968   if (!builtin_decl || !mask_element_type)
3969     return NULL;
3970
3971   mask_type = get_vectype_for_scalar_type (mask_element_type);
3972   nunits = TYPE_VECTOR_SUBPARTS (vectype);
3973   if (!mask_type
3974       || TYPE_VECTOR_SUBPARTS (vectype) != TYPE_VECTOR_SUBPARTS (mask_type))
3975     return NULL;
3976
3977   for (i = 0; i < nunits; i++)
3978     mask_vec = tree_cons (NULL, build_int_cst (mask_element_type, i), mask_vec);
3979   mask_vec = build_vector (mask_type, mask_vec);
3980
3981   if (!targetm.vectorize.builtin_vec_perm_ok (vectype, mask_vec))
3982     return NULL;
3983   if (mask)
3984     *mask = mask_vec;
3985   return builtin_decl;
3986 }
3987
3988 /* Given a vector variable X, that was generated for the scalar LHS of
3989    STMT, generate instructions to reverse the vector elements of X,
3990    insert them a *GSI and return the permuted vector variable.  */
3991
3992 static tree
3993 reverse_vec_elements (tree x, gimple stmt, gimple_stmt_iterator *gsi)
3994 {
3995   tree vectype = TREE_TYPE (x);
3996   tree mask_vec, builtin_decl;
3997   tree perm_dest, data_ref;
3998   gimple perm_stmt;
3999
4000   builtin_decl = perm_mask_for_reverse (vectype, &mask_vec);
4001
4002   perm_dest = vect_create_destination_var (gimple_assign_lhs (stmt), vectype);
4003
4004   /* Generate the permute statement.  */
4005   perm_stmt = gimple_build_call (builtin_decl, 3, x, x, mask_vec);
4006   if (!useless_type_conversion_p (vectype,
4007                                   TREE_TYPE (TREE_TYPE (builtin_decl))))
4008     {
4009       tree tem = create_tmp_reg (TREE_TYPE (TREE_TYPE (builtin_decl)), NULL);
4010       tem = make_ssa_name (tem, perm_stmt);
4011       gimple_call_set_lhs (perm_stmt, tem);
4012       vect_finish_stmt_generation (stmt, perm_stmt, gsi);
4013       perm_stmt = gimple_build_assign (NULL_TREE,
4014                                        build1 (VIEW_CONVERT_EXPR,
4015                                                vectype, tem));
4016     }
4017   data_ref = make_ssa_name (perm_dest, perm_stmt);
4018   gimple_set_lhs (perm_stmt, data_ref);
4019   vect_finish_stmt_generation (stmt, perm_stmt, gsi);
4020
4021   return data_ref;
4022 }
4023
4024 /* vectorizable_load.
4025
4026    Check if STMT reads a non scalar data-ref (array/pointer/structure) that
4027    can be vectorized.
4028    If VEC_STMT is also passed, vectorize the STMT: create a vectorized
4029    stmt to replace it, put it in VEC_STMT, and insert it at BSI.
4030    Return FALSE if not a vectorizable STMT, TRUE otherwise.  */
4031
4032 static bool
4033 vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
4034                    slp_tree slp_node, slp_instance slp_node_instance)
4035 {
4036   tree scalar_dest;
4037   tree vec_dest = NULL;
4038   tree data_ref = NULL;
4039   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
4040   stmt_vec_info prev_stmt_info;
4041   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
4042   struct loop *loop = NULL;
4043   struct loop *containing_loop = (gimple_bb (stmt))->loop_father;
4044   bool nested_in_vect_loop = false;
4045   struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info), *first_dr;
4046   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
4047   tree elem_type;
4048   tree new_temp;
4049   enum machine_mode mode;
4050   gimple new_stmt = NULL;
4051   tree dummy;
4052   enum dr_alignment_support alignment_support_scheme;
4053   tree dataref_ptr = NULL_TREE;
4054   gimple ptr_incr;
4055   int nunits = TYPE_VECTOR_SUBPARTS (vectype);
4056   int ncopies;
4057   int i, j, group_size;
4058   tree msq = NULL_TREE, lsq;
4059   tree offset = NULL_TREE;
4060   tree realignment_token = NULL_TREE;
4061   gimple phi = NULL;
4062   VEC(tree,heap) *dr_chain = NULL;
4063   bool strided_load = false;
4064   bool load_lanes_p = false;
4065   gimple first_stmt;
4066   tree scalar_type;
4067   bool inv_p;
4068   bool negative;
4069   bool compute_in_loop = false;
4070   struct loop *at_loop;
4071   int vec_num;
4072   bool slp = (slp_node != NULL);
4073   bool slp_perm = false;
4074   enum tree_code code;
4075   bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
4076   int vf;
4077   tree aggr_type;
4078
4079   if (loop_vinfo)
4080     {
4081       loop = LOOP_VINFO_LOOP (loop_vinfo);
4082       nested_in_vect_loop = nested_in_vect_loop_p (loop, stmt);
4083       vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
4084     }
4085   else
4086     vf = 1;
4087
4088   /* Multiple types in SLP are handled by creating the appropriate number of
4089      vectorized stmts for each SLP node.  Hence, NCOPIES is always 1 in
4090      case of SLP.  */
4091   if (slp || PURE_SLP_STMT (stmt_info))
4092     ncopies = 1;
4093   else
4094     ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits;
4095
4096   gcc_assert (ncopies >= 1);
4097
4098   /* FORNOW. This restriction should be relaxed.  */
4099   if (nested_in_vect_loop && ncopies > 1)
4100     {
4101       if (vect_print_dump_info (REPORT_DETAILS))
4102         fprintf (vect_dump, "multiple types in nested loop.");
4103       return false;
4104     }
4105
4106   if (!STMT_VINFO_RELEVANT_P (stmt_info) && !bb_vinfo)
4107     return false;
4108
4109   if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def)
4110     return false;
4111
4112   /* Is vectorizable load? */
4113   if (!is_gimple_assign (stmt))
4114     return false;
4115
4116   scalar_dest = gimple_assign_lhs (stmt);
4117   if (TREE_CODE (scalar_dest) != SSA_NAME)
4118     return false;
4119
4120   code = gimple_assign_rhs_code (stmt);
4121   if (code != ARRAY_REF
4122       && code != INDIRECT_REF
4123       && code != COMPONENT_REF
4124       && code != IMAGPART_EXPR
4125       && code != REALPART_EXPR
4126       && code != MEM_REF
4127       && TREE_CODE_CLASS (code) != tcc_declaration)
4128     return false;
4129
4130   if (!STMT_VINFO_DATA_REF (stmt_info))
4131     return false;
4132
4133   negative = tree_int_cst_compare (DR_STEP (dr), size_zero_node) < 0;
4134   if (negative && ncopies > 1)
4135     {
4136       if (vect_print_dump_info (REPORT_DETAILS))
4137         fprintf (vect_dump, "multiple types with negative step.");
4138       return false;
4139     }
4140
4141   scalar_type = TREE_TYPE (DR_REF (dr));
4142   mode = TYPE_MODE (vectype);
4143
4144   /* FORNOW. In some cases can vectorize even if data-type not supported
4145     (e.g. - data copies).  */
4146   if (optab_handler (mov_optab, mode) == CODE_FOR_nothing)
4147     {
4148       if (vect_print_dump_info (REPORT_DETAILS))
4149         fprintf (vect_dump, "Aligned load, but unsupported type.");
4150       return false;
4151     }
4152
4153   /* The vector component type needs to be trivially convertible to the
4154      scalar lhs.  This should always be the case.  */
4155   elem_type = TREE_TYPE (vectype);
4156   if (!useless_type_conversion_p (TREE_TYPE (scalar_dest), elem_type))
4157     {
4158       if (vect_print_dump_info (REPORT_DETAILS))
4159         fprintf (vect_dump, "???  operands of different types");
4160       return false;
4161     }
4162
4163   /* Check if the load is a part of an interleaving chain.  */
4164   if (STMT_VINFO_STRIDED_ACCESS (stmt_info))
4165     {
4166       strided_load = true;
4167       /* FORNOW */
4168       gcc_assert (! nested_in_vect_loop);
4169
4170       first_stmt = GROUP_FIRST_ELEMENT (stmt_info);
4171       if (!slp && !PURE_SLP_STMT (stmt_info))
4172         {
4173           group_size = GROUP_SIZE (vinfo_for_stmt (first_stmt));
4174           if (vect_load_lanes_supported (vectype, group_size))
4175             load_lanes_p = true;
4176           else if (!vect_strided_load_supported (vectype, group_size))
4177             return false;
4178         }
4179     }
4180
4181   if (negative)
4182     {
4183       gcc_assert (!strided_load);
4184       alignment_support_scheme = vect_supportable_dr_alignment (dr, false);
4185       if (alignment_support_scheme != dr_aligned
4186           && alignment_support_scheme != dr_unaligned_supported)
4187         {
4188           if (vect_print_dump_info (REPORT_DETAILS))
4189             fprintf (vect_dump, "negative step but alignment required.");
4190           return false;
4191         }
4192       if (!perm_mask_for_reverse (vectype, NULL))
4193         {
4194           if (vect_print_dump_info (REPORT_DETAILS))
4195             fprintf (vect_dump, "negative step and reversing not supported.");
4196           return false;
4197         }
4198     }
4199
4200   if (!vec_stmt) /* transformation not required.  */
4201     {
4202       STMT_VINFO_TYPE (stmt_info) = load_vec_info_type;
4203       vect_model_load_cost (stmt_info, ncopies, load_lanes_p, NULL);
4204       return true;
4205     }
4206
4207   if (vect_print_dump_info (REPORT_DETAILS))
4208     fprintf (vect_dump, "transform load. ncopies = %d", ncopies);
4209
4210   /** Transform.  **/
4211
4212   if (strided_load)
4213     {
4214       first_stmt = GROUP_FIRST_ELEMENT (stmt_info);
4215       /* Check if the chain of loads is already vectorized.  */
4216       if (STMT_VINFO_VEC_STMT (vinfo_for_stmt (first_stmt)))
4217         {
4218           *vec_stmt = STMT_VINFO_VEC_STMT (stmt_info);
4219           return true;
4220         }
4221       first_dr = STMT_VINFO_DATA_REF (vinfo_for_stmt (first_stmt));
4222       group_size = GROUP_SIZE (vinfo_for_stmt (first_stmt));
4223
4224       /* VEC_NUM is the number of vect stmts to be created for this group.  */
4225       if (slp)
4226         {
4227           strided_load = false;
4228           vec_num = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node);
4229           if (SLP_INSTANCE_LOAD_PERMUTATION (slp_node_instance))
4230             slp_perm = true;
4231         }
4232       else
4233         vec_num = group_size;
4234     }
4235   else
4236     {
4237       first_stmt = stmt;
4238       first_dr = dr;
4239       group_size = vec_num = 1;
4240     }
4241
4242   alignment_support_scheme = vect_supportable_dr_alignment (first_dr, false);
4243   gcc_assert (alignment_support_scheme);
4244   /* Targets with load-lane instructions must not require explicit
4245      realignment.  */
4246   gcc_assert (!load_lanes_p
4247               || alignment_support_scheme == dr_aligned
4248               || alignment_support_scheme == dr_unaligned_supported);
4249
4250   /* In case the vectorization factor (VF) is bigger than the number
4251      of elements that we can fit in a vectype (nunits), we have to generate
4252      more than one vector stmt - i.e - we need to "unroll" the
4253      vector stmt by a factor VF/nunits.  In doing so, we record a pointer
4254      from one copy of the vector stmt to the next, in the field
4255      STMT_VINFO_RELATED_STMT.  This is necessary in order to allow following
4256      stages to find the correct vector defs to be used when vectorizing
4257      stmts that use the defs of the current stmt.  The example below
4258      illustrates the vectorization process when VF=16 and nunits=4 (i.e., we
4259      need to create 4 vectorized stmts):
4260
4261      before vectorization:
4262                                 RELATED_STMT    VEC_STMT
4263         S1:     x = memref      -               -
4264         S2:     z = x + 1       -               -
4265
4266      step 1: vectorize stmt S1:
4267         We first create the vector stmt VS1_0, and, as usual, record a
4268         pointer to it in the STMT_VINFO_VEC_STMT of the scalar stmt S1.
4269         Next, we create the vector stmt VS1_1, and record a pointer to
4270         it in the STMT_VINFO_RELATED_STMT of the vector stmt VS1_0.
4271         Similarly, for VS1_2 and VS1_3.  This is the resulting chain of
4272         stmts and pointers:
4273                                 RELATED_STMT    VEC_STMT
4274         VS1_0:  vx0 = memref0   VS1_1           -
4275         VS1_1:  vx1 = memref1   VS1_2           -
4276         VS1_2:  vx2 = memref2   VS1_3           -
4277         VS1_3:  vx3 = memref3   -               -
4278         S1:     x = load        -               VS1_0
4279         S2:     z = x + 1       -               -
4280
4281      See in documentation in vect_get_vec_def_for_stmt_copy for how the
4282      information we recorded in RELATED_STMT field is used to vectorize
4283      stmt S2.  */
4284
4285   /* In case of interleaving (non-unit strided access):
4286
4287      S1:  x2 = &base + 2
4288      S2:  x0 = &base
4289      S3:  x1 = &base + 1
4290      S4:  x3 = &base + 3
4291
4292      Vectorized loads are created in the order of memory accesses
4293      starting from the access of the first stmt of the chain:
4294
4295      VS1: vx0 = &base
4296      VS2: vx1 = &base + vec_size*1
4297      VS3: vx3 = &base + vec_size*2
4298      VS4: vx4 = &base + vec_size*3
4299
4300      Then permutation statements are generated:
4301
4302      VS5: vx5 = VEC_EXTRACT_EVEN_EXPR < vx0, vx1 >
4303      VS6: vx6 = VEC_EXTRACT_ODD_EXPR < vx0, vx1 >
4304        ...
4305
4306      And they are put in STMT_VINFO_VEC_STMT of the corresponding scalar stmts
4307      (the order of the data-refs in the output of vect_permute_load_chain
4308      corresponds to the order of scalar stmts in the interleaving chain - see
4309      the documentation of vect_permute_load_chain()).
4310      The generation of permutation stmts and recording them in
4311      STMT_VINFO_VEC_STMT is done in vect_transform_strided_load().
4312
4313      In case of both multiple types and interleaving, the vector loads and
4314      permutation stmts above are created for every copy.  The result vector
4315      stmts are put in STMT_VINFO_VEC_STMT for the first copy and in the
4316      corresponding STMT_VINFO_RELATED_STMT for the next copies.  */
4317
4318   /* If the data reference is aligned (dr_aligned) or potentially unaligned
4319      on a target that supports unaligned accesses (dr_unaligned_supported)
4320      we generate the following code:
4321          p = initial_addr;
4322          indx = 0;
4323          loop {
4324            p = p + indx * vectype_size;
4325            vec_dest = *(p);
4326            indx = indx + 1;
4327          }
4328
4329      Otherwise, the data reference is potentially unaligned on a target that
4330      does not support unaligned accesses (dr_explicit_realign_optimized) -
4331      then generate the following code, in which the data in each iteration is
4332      obtained by two vector loads, one from the previous iteration, and one
4333      from the current iteration:
4334          p1 = initial_addr;
4335          msq_init = *(floor(p1))
4336          p2 = initial_addr + VS - 1;
4337          realignment_token = call target_builtin;
4338          indx = 0;
4339          loop {
4340            p2 = p2 + indx * vectype_size
4341            lsq = *(floor(p2))
4342            vec_dest = realign_load (msq, lsq, realignment_token)
4343            indx = indx + 1;
4344            msq = lsq;
4345          }   */
4346
4347   /* If the misalignment remains the same throughout the execution of the
4348      loop, we can create the init_addr and permutation mask at the loop
4349      preheader.  Otherwise, it needs to be created inside the loop.
4350      This can only occur when vectorizing memory accesses in the inner-loop
4351      nested within an outer-loop that is being vectorized.  */
4352
4353   if (loop && nested_in_vect_loop_p (loop, stmt)
4354       && (TREE_INT_CST_LOW (DR_STEP (dr))
4355           % GET_MODE_SIZE (TYPE_MODE (vectype)) != 0))
4356     {
4357       gcc_assert (alignment_support_scheme != dr_explicit_realign_optimized);
4358       compute_in_loop = true;
4359     }
4360
4361   if ((alignment_support_scheme == dr_explicit_realign_optimized
4362        || alignment_support_scheme == dr_explicit_realign)
4363       && !compute_in_loop)
4364     {
4365       msq = vect_setup_realignment (first_stmt, gsi, &realignment_token,
4366                                     alignment_support_scheme, NULL_TREE,
4367                                     &at_loop);
4368       if (alignment_support_scheme == dr_explicit_realign_optimized)
4369         {
4370           phi = SSA_NAME_DEF_STMT (msq);
4371           offset = size_int (TYPE_VECTOR_SUBPARTS (vectype) - 1);
4372         }
4373     }
4374   else
4375     at_loop = loop;
4376
4377   if (negative)
4378     offset = size_int (-TYPE_VECTOR_SUBPARTS (vectype) + 1);
4379
4380   if (load_lanes_p)
4381     aggr_type = build_array_type_nelts (elem_type, vec_num * nunits);
4382   else
4383     aggr_type = vectype;
4384
4385   prev_stmt_info = NULL;
4386   for (j = 0; j < ncopies; j++)
4387     {
4388       /* 1. Create the vector or array pointer update chain.  */
4389       if (j == 0)
4390         dataref_ptr = vect_create_data_ref_ptr (first_stmt, aggr_type, at_loop,
4391                                                 offset, &dummy, gsi,
4392                                                 &ptr_incr, false, &inv_p);
4393       else
4394         dataref_ptr = bump_vector_ptr (dataref_ptr, ptr_incr, gsi, stmt,
4395                                        TYPE_SIZE_UNIT (aggr_type));
4396
4397       if (strided_load || slp_perm)
4398         dr_chain = VEC_alloc (tree, heap, vec_num);
4399
4400       if (load_lanes_p)
4401         {
4402           tree vec_array;
4403
4404           vec_array = create_vector_array (vectype, vec_num);
4405
4406           /* Emit:
4407                VEC_ARRAY = LOAD_LANES (MEM_REF[...all elements...]).  */
4408           data_ref = create_array_ref (aggr_type, dataref_ptr, first_dr);
4409           new_stmt = gimple_build_call_internal (IFN_LOAD_LANES, 1, data_ref);
4410           gimple_call_set_lhs (new_stmt, vec_array);
4411           vect_finish_stmt_generation (stmt, new_stmt, gsi);
4412           mark_symbols_for_renaming (new_stmt);
4413
4414           /* Extract each vector into an SSA_NAME.  */
4415           for (i = 0; i < vec_num; i++)
4416             {
4417               new_temp = read_vector_array (stmt, gsi, scalar_dest,
4418                                             vec_array, i);
4419               VEC_quick_push (tree, dr_chain, new_temp);
4420             }
4421
4422           /* Record the mapping between SSA_NAMEs and statements.  */
4423           vect_record_strided_load_vectors (stmt, dr_chain);
4424         }
4425       else
4426         {
4427           for (i = 0; i < vec_num; i++)
4428             {
4429               if (i > 0)
4430                 dataref_ptr = bump_vector_ptr (dataref_ptr, ptr_incr, gsi,
4431                                                stmt, NULL_TREE);
4432
4433               /* 2. Create the vector-load in the loop.  */
4434               switch (alignment_support_scheme)
4435                 {
4436                 case dr_aligned:
4437                 case dr_unaligned_supported:
4438                   {
4439                     struct ptr_info_def *pi;
4440                     data_ref
4441                       = build2 (MEM_REF, vectype, dataref_ptr,
4442                                 build_int_cst (reference_alias_ptr_type
4443                                                (DR_REF (first_dr)), 0));
4444                     pi = get_ptr_info (dataref_ptr);
4445                     pi->align = TYPE_ALIGN_UNIT (vectype);
4446                     if (alignment_support_scheme == dr_aligned)
4447                       {
4448                         gcc_assert (aligned_access_p (first_dr));
4449                         pi->misalign = 0;
4450                       }
4451                     else if (DR_MISALIGNMENT (first_dr) == -1)
4452                       {
4453                         TREE_TYPE (data_ref)
4454                           = build_aligned_type (TREE_TYPE (data_ref),
4455                                                 TYPE_ALIGN (elem_type));
4456                         pi->align = TYPE_ALIGN_UNIT (elem_type);
4457                         pi->misalign = 0;
4458                       }
4459                     else
4460                       {
4461                         TREE_TYPE (data_ref)
4462                           = build_aligned_type (TREE_TYPE (data_ref),
4463                                                 TYPE_ALIGN (elem_type));
4464                         pi->misalign = DR_MISALIGNMENT (first_dr);
4465                       }
4466                     break;
4467                   }
4468                 case dr_explicit_realign:
4469                   {
4470                     tree ptr, bump;
4471                     tree vs_minus_1;
4472
4473                     vs_minus_1 = size_int (TYPE_VECTOR_SUBPARTS (vectype) - 1);
4474
4475                     if (compute_in_loop)
4476                       msq = vect_setup_realignment (first_stmt, gsi,
4477                                                     &realignment_token,
4478                                                     dr_explicit_realign,
4479                                                     dataref_ptr, NULL);
4480
4481                     new_stmt = gimple_build_assign_with_ops
4482                                  (BIT_AND_EXPR, NULL_TREE, dataref_ptr,
4483                                   build_int_cst
4484                                   (TREE_TYPE (dataref_ptr),
4485                                    -(HOST_WIDE_INT)TYPE_ALIGN_UNIT (vectype)));
4486                     ptr = make_ssa_name (SSA_NAME_VAR (dataref_ptr), new_stmt);
4487                     gimple_assign_set_lhs (new_stmt, ptr);
4488                     vect_finish_stmt_generation (stmt, new_stmt, gsi);
4489                     data_ref
4490                       = build2 (MEM_REF, vectype, ptr,
4491                                 build_int_cst (reference_alias_ptr_type
4492                                                  (DR_REF (first_dr)), 0));
4493                     vec_dest = vect_create_destination_var (scalar_dest,
4494                                                             vectype);
4495                     new_stmt = gimple_build_assign (vec_dest, data_ref);
4496                     new_temp = make_ssa_name (vec_dest, new_stmt);
4497                     gimple_assign_set_lhs (new_stmt, new_temp);
4498                     gimple_set_vdef (new_stmt, gimple_vdef (stmt));
4499                     gimple_set_vuse (new_stmt, gimple_vuse (stmt));
4500                     vect_finish_stmt_generation (stmt, new_stmt, gsi);
4501                     msq = new_temp;
4502
4503                     bump = size_binop (MULT_EXPR, vs_minus_1,
4504                                        TYPE_SIZE_UNIT (scalar_type));
4505                     ptr = bump_vector_ptr (dataref_ptr, NULL, gsi, stmt, bump);
4506                     new_stmt = gimple_build_assign_with_ops
4507                                  (BIT_AND_EXPR, NULL_TREE, ptr,
4508                                   build_int_cst
4509                                   (TREE_TYPE (ptr),
4510                                    -(HOST_WIDE_INT)TYPE_ALIGN_UNIT (vectype)));
4511                     ptr = make_ssa_name (SSA_NAME_VAR (dataref_ptr), new_stmt);
4512                     gimple_assign_set_lhs (new_stmt, ptr);
4513                     vect_finish_stmt_generation (stmt, new_stmt, gsi);
4514                     data_ref
4515                       = build2 (MEM_REF, vectype, ptr,
4516                                 build_int_cst (reference_alias_ptr_type
4517                                                  (DR_REF (first_dr)), 0));
4518                     break;
4519                   }
4520                 case dr_explicit_realign_optimized:
4521                   new_stmt = gimple_build_assign_with_ops
4522                                (BIT_AND_EXPR, NULL_TREE, dataref_ptr,
4523                                 build_int_cst
4524                                   (TREE_TYPE (dataref_ptr),
4525                                    -(HOST_WIDE_INT)TYPE_ALIGN_UNIT (vectype)));
4526                   new_temp = make_ssa_name (SSA_NAME_VAR (dataref_ptr),
4527                                             new_stmt);
4528                   gimple_assign_set_lhs (new_stmt, new_temp);
4529                   vect_finish_stmt_generation (stmt, new_stmt, gsi);
4530                   data_ref
4531                     = build2 (MEM_REF, vectype, new_temp,
4532                               build_int_cst (reference_alias_ptr_type
4533                                                (DR_REF (first_dr)), 0));
4534                   break;
4535                 default:
4536                   gcc_unreachable ();
4537                 }
4538               vec_dest = vect_create_destination_var (scalar_dest, vectype);
4539               new_stmt = gimple_build_assign (vec_dest, data_ref);
4540               new_temp = make_ssa_name (vec_dest, new_stmt);
4541               gimple_assign_set_lhs (new_stmt, new_temp);
4542               vect_finish_stmt_generation (stmt, new_stmt, gsi);
4543               mark_symbols_for_renaming (new_stmt);
4544
4545               /* 3. Handle explicit realignment if necessary/supported.
4546                  Create in loop:
4547                    vec_dest = realign_load (msq, lsq, realignment_token)  */
4548               if (alignment_support_scheme == dr_explicit_realign_optimized
4549                   || alignment_support_scheme == dr_explicit_realign)
4550                 {
4551                   lsq = gimple_assign_lhs (new_stmt);
4552                   if (!realignment_token)
4553                     realignment_token = dataref_ptr;
4554                   vec_dest = vect_create_destination_var (scalar_dest, vectype);
4555                   new_stmt
4556                     = gimple_build_assign_with_ops3 (REALIGN_LOAD_EXPR,
4557                                                      vec_dest, msq, lsq,
4558                                                      realignment_token);
4559                   new_temp = make_ssa_name (vec_dest, new_stmt);
4560                   gimple_assign_set_lhs (new_stmt, new_temp);
4561                   vect_finish_stmt_generation (stmt, new_stmt, gsi);
4562
4563                   if (alignment_support_scheme == dr_explicit_realign_optimized)
4564                     {
4565                       gcc_assert (phi);
4566                       if (i == vec_num - 1 && j == ncopies - 1)
4567                         add_phi_arg (phi, lsq,
4568                                      loop_latch_edge (containing_loop),
4569                                      UNKNOWN_LOCATION);
4570                       msq = lsq;
4571                     }
4572                 }
4573
4574               /* 4. Handle invariant-load.  */
4575               if (inv_p && !bb_vinfo)
4576                 {
4577                   tree vec_inv;
4578                   gimple_stmt_iterator gsi2 = *gsi;
4579                   gcc_assert (!strided_load);
4580                   gsi_next (&gsi2);
4581                   vec_inv = build_vector_from_val (vectype, scalar_dest);
4582                   new_temp = vect_init_vector (stmt, vec_inv,
4583                                                vectype, &gsi2);
4584                   new_stmt = SSA_NAME_DEF_STMT (new_temp);
4585                 }
4586
4587               if (negative)
4588                 {
4589                   new_temp = reverse_vec_elements (new_temp, stmt, gsi);
4590                   new_stmt = SSA_NAME_DEF_STMT (new_temp);
4591                 }
4592
4593               /* Collect vector loads and later create their permutation in
4594                  vect_transform_strided_load ().  */
4595               if (strided_load || slp_perm)
4596                 VEC_quick_push (tree, dr_chain, new_temp);
4597
4598               /* Store vector loads in the corresponding SLP_NODE.  */
4599               if (slp && !slp_perm)
4600                 VEC_quick_push (gimple, SLP_TREE_VEC_STMTS (slp_node),
4601                                 new_stmt);
4602             }
4603         }
4604
4605       if (slp && !slp_perm)
4606         continue;
4607
4608       if (slp_perm)
4609         {
4610           if (!vect_transform_slp_perm_load (stmt, dr_chain, gsi, vf,
4611                                              slp_node_instance, false))
4612             {
4613               VEC_free (tree, heap, dr_chain);
4614               return false;
4615             }
4616         }
4617       else
4618         {
4619           if (strided_load)
4620             {
4621               if (!load_lanes_p)
4622                 vect_transform_strided_load (stmt, dr_chain, group_size, gsi);
4623               *vec_stmt = STMT_VINFO_VEC_STMT (stmt_info);
4624             }
4625           else
4626             {
4627               if (j == 0)
4628                 STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
4629               else
4630                 STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
4631               prev_stmt_info = vinfo_for_stmt (new_stmt);
4632             }
4633         }
4634       if (dr_chain)
4635         VEC_free (tree, heap, dr_chain);
4636     }
4637
4638   return true;
4639 }
4640
4641 /* Function vect_is_simple_cond.
4642
4643    Input:
4644    LOOP - the loop that is being vectorized.
4645    COND - Condition that is checked for simple use.
4646
4647    Returns whether a COND can be vectorized.  Checks whether
4648    condition operands are supportable using vec_is_simple_use.  */
4649
4650 static bool
4651 vect_is_simple_cond (tree cond, loop_vec_info loop_vinfo)
4652 {
4653   tree lhs, rhs;
4654   tree def;
4655   enum vect_def_type dt;
4656
4657   if (!COMPARISON_CLASS_P (cond))
4658     return false;
4659
4660   lhs = TREE_OPERAND (cond, 0);
4661   rhs = TREE_OPERAND (cond, 1);
4662
4663   if (TREE_CODE (lhs) == SSA_NAME)
4664     {
4665       gimple lhs_def_stmt = SSA_NAME_DEF_STMT (lhs);
4666       if (!vect_is_simple_use (lhs, loop_vinfo, NULL, &lhs_def_stmt, &def,
4667                                &dt))
4668         return false;
4669     }
4670   else if (TREE_CODE (lhs) != INTEGER_CST && TREE_CODE (lhs) != REAL_CST
4671            && TREE_CODE (lhs) != FIXED_CST)
4672     return false;
4673
4674   if (TREE_CODE (rhs) == SSA_NAME)
4675     {
4676       gimple rhs_def_stmt = SSA_NAME_DEF_STMT (rhs);
4677       if (!vect_is_simple_use (rhs, loop_vinfo, NULL, &rhs_def_stmt, &def,
4678                                &dt))
4679         return false;
4680     }
4681   else if (TREE_CODE (rhs) != INTEGER_CST  && TREE_CODE (rhs) != REAL_CST
4682            && TREE_CODE (rhs) != FIXED_CST)
4683     return false;
4684
4685   return true;
4686 }
4687
4688 /* vectorizable_condition.
4689
4690    Check if STMT is conditional modify expression that can be vectorized.
4691    If VEC_STMT is also passed, vectorize the STMT: create a vectorized
4692    stmt using VEC_COND_EXPR  to replace it, put it in VEC_STMT, and insert it
4693    at GSI.
4694
4695    When STMT is vectorized as nested cycle, REDUC_DEF is the vector variable
4696    to be used at REDUC_INDEX (in then clause if REDUC_INDEX is 1, and in
4697    else caluse if it is 2).
4698
4699    Return FALSE if not a vectorizable STMT, TRUE otherwise.  */
4700
4701 bool
4702 vectorizable_condition (gimple stmt, gimple_stmt_iterator *gsi,
4703                         gimple *vec_stmt, tree reduc_def, int reduc_index)
4704 {
4705   tree scalar_dest = NULL_TREE;
4706   tree vec_dest = NULL_TREE;
4707   tree op = NULL_TREE;
4708   tree cond_expr, then_clause, else_clause;
4709   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
4710   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
4711   tree vec_cond_lhs = NULL_TREE, vec_cond_rhs = NULL_TREE;
4712   tree vec_then_clause = NULL_TREE, vec_else_clause = NULL_TREE;
4713   tree vec_compare, vec_cond_expr;
4714   tree new_temp;
4715   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
4716   enum machine_mode vec_mode;
4717   tree def;
4718   enum vect_def_type dt, dts[4];
4719   int nunits = TYPE_VECTOR_SUBPARTS (vectype);
4720   int ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits;
4721   enum tree_code code;
4722   stmt_vec_info prev_stmt_info = NULL;
4723   int j;
4724
4725   /* FORNOW: unsupported in basic block SLP.  */
4726   gcc_assert (loop_vinfo);
4727
4728   /* FORNOW: SLP not supported.  */
4729   if (STMT_SLP_TYPE (stmt_info))
4730     return false;
4731
4732   gcc_assert (ncopies >= 1);
4733   if (reduc_index && ncopies > 1)
4734     return false; /* FORNOW */
4735
4736   if (!STMT_VINFO_RELEVANT_P (stmt_info))
4737     return false;
4738
4739   if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def
4740       && !(STMT_VINFO_DEF_TYPE (stmt_info) == vect_nested_cycle
4741            && reduc_def))
4742     return false;
4743
4744   /* FORNOW: not yet supported.  */
4745   if (STMT_VINFO_LIVE_P (stmt_info))
4746     {
4747       if (vect_print_dump_info (REPORT_DETAILS))
4748         fprintf (vect_dump, "value used after loop.");
4749       return false;
4750     }
4751
4752   /* Is vectorizable conditional operation?  */
4753   if (!is_gimple_assign (stmt))
4754     return false;
4755
4756   code = gimple_assign_rhs_code (stmt);
4757
4758   if (code != COND_EXPR)
4759     return false;
4760
4761   gcc_assert (gimple_assign_single_p (stmt));
4762   op = gimple_assign_rhs1 (stmt);
4763   cond_expr = TREE_OPERAND (op, 0);
4764   then_clause = TREE_OPERAND (op, 1);
4765   else_clause = TREE_OPERAND (op, 2);
4766
4767   if (!vect_is_simple_cond (cond_expr, loop_vinfo))
4768     return false;
4769
4770   /* We do not handle two different vector types for the condition
4771      and the values.  */
4772   if (!types_compatible_p (TREE_TYPE (TREE_OPERAND (cond_expr, 0)),
4773                            TREE_TYPE (vectype)))
4774     return false;
4775
4776   if (TREE_CODE (then_clause) == SSA_NAME)
4777     {
4778       gimple then_def_stmt = SSA_NAME_DEF_STMT (then_clause);
4779       if (!vect_is_simple_use (then_clause, loop_vinfo, NULL,
4780                                &then_def_stmt, &def, &dt))
4781         return false;
4782     }
4783   else if (TREE_CODE (then_clause) != INTEGER_CST
4784            && TREE_CODE (then_clause) != REAL_CST
4785            && TREE_CODE (then_clause) != FIXED_CST)
4786     return false;
4787
4788   if (TREE_CODE (else_clause) == SSA_NAME)
4789     {
4790       gimple else_def_stmt = SSA_NAME_DEF_STMT (else_clause);
4791       if (!vect_is_simple_use (else_clause, loop_vinfo, NULL,
4792                                &else_def_stmt, &def, &dt))
4793         return false;
4794     }
4795   else if (TREE_CODE (else_clause) != INTEGER_CST
4796            && TREE_CODE (else_clause) != REAL_CST
4797            && TREE_CODE (else_clause) != FIXED_CST)
4798     return false;
4799
4800
4801   vec_mode = TYPE_MODE (vectype);
4802
4803   if (!vec_stmt)
4804     {
4805       STMT_VINFO_TYPE (stmt_info) = condition_vec_info_type;
4806       return expand_vec_cond_expr_p (TREE_TYPE (op), vec_mode);
4807     }
4808
4809   /* Transform */
4810
4811   /* Handle def.  */
4812   scalar_dest = gimple_assign_lhs (stmt);
4813   vec_dest = vect_create_destination_var (scalar_dest, vectype);
4814
4815   /* Handle cond expr.  */
4816   for (j = 0; j < ncopies; j++)
4817     {
4818       gimple new_stmt;
4819       if (j == 0)
4820         {
4821           gimple gtemp;
4822           vec_cond_lhs =
4823               vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 0),
4824                                             stmt, NULL);
4825           vect_is_simple_use (TREE_OPERAND (cond_expr, 0), loop_vinfo,
4826                               NULL, &gtemp, &def, &dts[0]);
4827           vec_cond_rhs =
4828               vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 1),
4829                                             stmt, NULL);
4830           vect_is_simple_use (TREE_OPERAND (cond_expr, 1), loop_vinfo,
4831                               NULL, &gtemp, &def, &dts[1]);
4832           if (reduc_index == 1)
4833             vec_then_clause = reduc_def;
4834           else
4835             {
4836               vec_then_clause = vect_get_vec_def_for_operand (then_clause,
4837                                                               stmt, NULL);
4838               vect_is_simple_use (then_clause, loop_vinfo,
4839                                   NULL, &gtemp, &def, &dts[2]);
4840             }
4841           if (reduc_index == 2)
4842             vec_else_clause = reduc_def;
4843           else
4844             {
4845               vec_else_clause = vect_get_vec_def_for_operand (else_clause,
4846                                                               stmt, NULL);
4847               vect_is_simple_use (else_clause, loop_vinfo,
4848                                   NULL, &gtemp, &def, &dts[3]);
4849             }
4850         }
4851       else
4852         {
4853           vec_cond_lhs = vect_get_vec_def_for_stmt_copy (dts[0], vec_cond_lhs);
4854           vec_cond_rhs = vect_get_vec_def_for_stmt_copy (dts[1], vec_cond_rhs);
4855           vec_then_clause = vect_get_vec_def_for_stmt_copy (dts[2],
4856                                                             vec_then_clause);
4857           vec_else_clause = vect_get_vec_def_for_stmt_copy (dts[3],
4858                                                             vec_else_clause);
4859         }
4860
4861       /* Arguments are ready.  Create the new vector stmt.  */
4862       vec_compare = build2 (TREE_CODE (cond_expr), vectype,
4863                             vec_cond_lhs, vec_cond_rhs);
4864       vec_cond_expr = build3 (VEC_COND_EXPR, vectype,
4865                               vec_compare, vec_then_clause, vec_else_clause);
4866
4867       new_stmt = gimple_build_assign (vec_dest, vec_cond_expr);
4868       new_temp = make_ssa_name (vec_dest, new_stmt);
4869       gimple_assign_set_lhs (new_stmt, new_temp);
4870       vect_finish_stmt_generation (stmt, new_stmt, gsi);
4871       if (j == 0)
4872         STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
4873       else
4874         STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
4875
4876       prev_stmt_info = vinfo_for_stmt (new_stmt);
4877     }
4878
4879   return true;
4880 }
4881
4882
4883 /* Make sure the statement is vectorizable.  */
4884
4885 bool
4886 vect_analyze_stmt (gimple stmt, bool *need_to_vectorize, slp_tree node)
4887 {
4888   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
4889   bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
4890   enum vect_relevant relevance = STMT_VINFO_RELEVANT (stmt_info);
4891   bool ok;
4892   tree scalar_type, vectype;
4893   gimple pattern_stmt;
4894
4895   if (vect_print_dump_info (REPORT_DETAILS))
4896     {
4897       fprintf (vect_dump, "==> examining statement: ");
4898       print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
4899     }
4900
4901   if (gimple_has_volatile_ops (stmt))
4902     {
4903       if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
4904         fprintf (vect_dump, "not vectorized: stmt has volatile operands");
4905
4906       return false;
4907     }
4908
4909   /* Skip stmts that do not need to be vectorized. In loops this is expected
4910      to include:
4911      - the COND_EXPR which is the loop exit condition
4912      - any LABEL_EXPRs in the loop
4913      - computations that are used only for array indexing or loop control.
4914      In basic blocks we only analyze statements that are a part of some SLP
4915      instance, therefore, all the statements are relevant.
4916
4917      Pattern statement need to be analyzed instead of the original statement
4918      if the original statement is not relevant.  Otherwise, we analyze both
4919      statements.  */
4920
4921   pattern_stmt = STMT_VINFO_RELATED_STMT (stmt_info);
4922   if (!STMT_VINFO_RELEVANT_P (stmt_info)
4923       && !STMT_VINFO_LIVE_P (stmt_info))
4924     {
4925       if (STMT_VINFO_IN_PATTERN_P (stmt_info)
4926           && pattern_stmt
4927           && (STMT_VINFO_RELEVANT_P (vinfo_for_stmt (pattern_stmt))
4928               || STMT_VINFO_LIVE_P (vinfo_for_stmt (pattern_stmt))))
4929         {
4930           /* Analyze PATTERN_STMT instead of the original stmt.  */
4931           stmt = pattern_stmt;
4932           stmt_info = vinfo_for_stmt (pattern_stmt);
4933           if (vect_print_dump_info (REPORT_DETAILS))
4934             {
4935               fprintf (vect_dump, "==> examining pattern statement: ");
4936               print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
4937             }
4938         }
4939       else
4940         {
4941           if (vect_print_dump_info (REPORT_DETAILS))
4942             fprintf (vect_dump, "irrelevant.");
4943
4944           return true;
4945         }
4946     }
4947   else if (STMT_VINFO_IN_PATTERN_P (stmt_info)
4948            && pattern_stmt
4949            && (STMT_VINFO_RELEVANT_P (vinfo_for_stmt (pattern_stmt))
4950                || STMT_VINFO_LIVE_P (vinfo_for_stmt (pattern_stmt))))
4951     {
4952       /* Analyze PATTERN_STMT too.  */
4953       if (vect_print_dump_info (REPORT_DETAILS))
4954         {
4955           fprintf (vect_dump, "==> examining pattern statement: ");
4956           print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
4957         }
4958
4959       if (!vect_analyze_stmt (pattern_stmt, need_to_vectorize, node))
4960         return false;
4961    }
4962
4963   switch (STMT_VINFO_DEF_TYPE (stmt_info))
4964     {
4965       case vect_internal_def:
4966         break;
4967
4968       case vect_reduction_def:
4969       case vect_nested_cycle:
4970          gcc_assert (!bb_vinfo && (relevance == vect_used_in_outer
4971                      || relevance == vect_used_in_outer_by_reduction
4972                      || relevance == vect_unused_in_scope));
4973          break;
4974
4975       case vect_induction_def:
4976       case vect_constant_def:
4977       case vect_external_def:
4978       case vect_unknown_def_type:
4979       default:
4980         gcc_unreachable ();
4981     }
4982
4983   if (bb_vinfo)
4984     {
4985       gcc_assert (PURE_SLP_STMT (stmt_info));
4986
4987       scalar_type = TREE_TYPE (gimple_get_lhs (stmt));
4988       if (vect_print_dump_info (REPORT_DETAILS))
4989         {
4990           fprintf (vect_dump, "get vectype for scalar type:  ");
4991           print_generic_expr (vect_dump, scalar_type, TDF_SLIM);
4992         }
4993
4994       vectype = get_vectype_for_scalar_type (scalar_type);
4995       if (!vectype)
4996         {
4997           if (vect_print_dump_info (REPORT_DETAILS))
4998             {
4999                fprintf (vect_dump, "not SLPed: unsupported data-type ");
5000                print_generic_expr (vect_dump, scalar_type, TDF_SLIM);
5001             }
5002           return false;
5003         }
5004
5005       if (vect_print_dump_info (REPORT_DETAILS))
5006         {
5007           fprintf (vect_dump, "vectype:  ");
5008           print_generic_expr (vect_dump, vectype, TDF_SLIM);
5009         }
5010
5011       STMT_VINFO_VECTYPE (stmt_info) = vectype;
5012    }
5013
5014   if (STMT_VINFO_RELEVANT_P (stmt_info))
5015     {
5016       gcc_assert (!VECTOR_MODE_P (TYPE_MODE (gimple_expr_type (stmt))));
5017       gcc_assert (STMT_VINFO_VECTYPE (stmt_info));
5018       *need_to_vectorize = true;
5019     }
5020
5021    ok = true;
5022    if (!bb_vinfo
5023        && (STMT_VINFO_RELEVANT_P (stmt_info)
5024            || STMT_VINFO_DEF_TYPE (stmt_info) == vect_reduction_def))
5025       ok = (vectorizable_type_promotion (stmt, NULL, NULL, NULL)
5026             || vectorizable_type_demotion (stmt, NULL, NULL, NULL)
5027             || vectorizable_conversion (stmt, NULL, NULL, NULL)
5028             || vectorizable_shift (stmt, NULL, NULL, NULL)
5029             || vectorizable_operation (stmt, NULL, NULL, NULL)
5030             || vectorizable_assignment (stmt, NULL, NULL, NULL)
5031             || vectorizable_load (stmt, NULL, NULL, NULL, NULL)
5032             || vectorizable_call (stmt, NULL, NULL)
5033             || vectorizable_store (stmt, NULL, NULL, NULL)
5034             || vectorizable_reduction (stmt, NULL, NULL, NULL)
5035             || vectorizable_condition (stmt, NULL, NULL, NULL, 0));
5036     else
5037       {
5038         if (bb_vinfo)
5039           ok = (vectorizable_shift (stmt, NULL, NULL, node)
5040                 || vectorizable_operation (stmt, NULL, NULL, node)
5041                 || vectorizable_assignment (stmt, NULL, NULL, node)
5042                 || vectorizable_load (stmt, NULL, NULL, node, NULL)
5043                 || vectorizable_store (stmt, NULL, NULL, node));
5044       }
5045
5046   if (!ok)
5047     {
5048       if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
5049         {
5050           fprintf (vect_dump, "not vectorized: relevant stmt not ");
5051           fprintf (vect_dump, "supported: ");
5052           print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
5053         }
5054
5055       return false;
5056     }
5057
5058   if (bb_vinfo)
5059     return true;
5060
5061   /* Stmts that are (also) "live" (i.e. - that are used out of the loop)
5062       need extra handling, except for vectorizable reductions.  */
5063   if (STMT_VINFO_LIVE_P (stmt_info)
5064       && STMT_VINFO_TYPE (stmt_info) != reduc_vec_info_type)
5065     ok = vectorizable_live_operation (stmt, NULL, NULL);
5066
5067   if (!ok)
5068     {
5069       if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
5070         {
5071           fprintf (vect_dump, "not vectorized: live stmt not ");
5072           fprintf (vect_dump, "supported: ");
5073           print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
5074         }
5075
5076        return false;
5077     }
5078
5079   return true;
5080 }
5081
5082
5083 /* Function vect_transform_stmt.
5084
5085    Create a vectorized stmt to replace STMT, and insert it at BSI.  */
5086
5087 bool
5088 vect_transform_stmt (gimple stmt, gimple_stmt_iterator *gsi,
5089                      bool *strided_store, slp_tree slp_node,
5090                      slp_instance slp_node_instance)
5091 {
5092   bool is_store = false;
5093   gimple vec_stmt = NULL;
5094   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
5095   bool done;
5096
5097   switch (STMT_VINFO_TYPE (stmt_info))
5098     {
5099     case type_demotion_vec_info_type:
5100       done = vectorizable_type_demotion (stmt, gsi, &vec_stmt, slp_node);
5101       gcc_assert (done);
5102       break;
5103
5104     case type_promotion_vec_info_type:
5105       done = vectorizable_type_promotion (stmt, gsi, &vec_stmt, slp_node);
5106       gcc_assert (done);
5107       break;
5108
5109     case type_conversion_vec_info_type:
5110       done = vectorizable_conversion (stmt, gsi, &vec_stmt, slp_node);
5111       gcc_assert (done);
5112       break;
5113
5114     case induc_vec_info_type:
5115       gcc_assert (!slp_node);
5116       done = vectorizable_induction (stmt, gsi, &vec_stmt);
5117       gcc_assert (done);
5118       break;
5119
5120     case shift_vec_info_type:
5121       done = vectorizable_shift (stmt, gsi, &vec_stmt, slp_node);
5122       gcc_assert (done);
5123       break;
5124
5125     case op_vec_info_type:
5126       done = vectorizable_operation (stmt, gsi, &vec_stmt, slp_node);
5127       gcc_assert (done);
5128       break;
5129
5130     case assignment_vec_info_type:
5131       done = vectorizable_assignment (stmt, gsi, &vec_stmt, slp_node);
5132       gcc_assert (done);
5133       break;
5134
5135     case load_vec_info_type:
5136       done = vectorizable_load (stmt, gsi, &vec_stmt, slp_node,
5137                                 slp_node_instance);
5138       gcc_assert (done);
5139       break;
5140
5141     case store_vec_info_type:
5142       done = vectorizable_store (stmt, gsi, &vec_stmt, slp_node);
5143       gcc_assert (done);
5144       if (STMT_VINFO_STRIDED_ACCESS (stmt_info) && !slp_node)
5145         {
5146           /* In case of interleaving, the whole chain is vectorized when the
5147              last store in the chain is reached.  Store stmts before the last
5148              one are skipped, and there vec_stmt_info shouldn't be freed
5149              meanwhile.  */
5150           *strided_store = true;
5151           if (STMT_VINFO_VEC_STMT (stmt_info))
5152             is_store = true;
5153           }
5154       else
5155         is_store = true;
5156       break;
5157
5158     case condition_vec_info_type:
5159       gcc_assert (!slp_node);
5160       done = vectorizable_condition (stmt, gsi, &vec_stmt, NULL, 0);
5161       gcc_assert (done);
5162       break;
5163
5164     case call_vec_info_type:
5165       gcc_assert (!slp_node);
5166       done = vectorizable_call (stmt, gsi, &vec_stmt);
5167       stmt = gsi_stmt (*gsi);
5168       break;
5169
5170     case reduc_vec_info_type:
5171       done = vectorizable_reduction (stmt, gsi, &vec_stmt, slp_node);
5172       gcc_assert (done);
5173       break;
5174
5175     default:
5176       if (!STMT_VINFO_LIVE_P (stmt_info))
5177         {
5178           if (vect_print_dump_info (REPORT_DETAILS))
5179             fprintf (vect_dump, "stmt not supported.");
5180           gcc_unreachable ();
5181         }
5182     }
5183
5184   /* Handle inner-loop stmts whose DEF is used in the loop-nest that
5185      is being vectorized, but outside the immediately enclosing loop.  */
5186   if (vec_stmt
5187       && STMT_VINFO_LOOP_VINFO (stmt_info)
5188       && nested_in_vect_loop_p (LOOP_VINFO_LOOP (
5189                                 STMT_VINFO_LOOP_VINFO (stmt_info)), stmt)
5190       && STMT_VINFO_TYPE (stmt_info) != reduc_vec_info_type
5191       && (STMT_VINFO_RELEVANT (stmt_info) == vect_used_in_outer
5192           || STMT_VINFO_RELEVANT (stmt_info) ==
5193                                            vect_used_in_outer_by_reduction))
5194     {
5195       struct loop *innerloop = LOOP_VINFO_LOOP (
5196                                 STMT_VINFO_LOOP_VINFO (stmt_info))->inner;
5197       imm_use_iterator imm_iter;
5198       use_operand_p use_p;
5199       tree scalar_dest;
5200       gimple exit_phi;
5201
5202       if (vect_print_dump_info (REPORT_DETAILS))
5203         fprintf (vect_dump, "Record the vdef for outer-loop vectorization.");
5204
5205       /* Find the relevant loop-exit phi-node, and reord the vec_stmt there
5206         (to be used when vectorizing outer-loop stmts that use the DEF of
5207         STMT).  */
5208       if (gimple_code (stmt) == GIMPLE_PHI)
5209         scalar_dest = PHI_RESULT (stmt);
5210       else
5211         scalar_dest = gimple_assign_lhs (stmt);
5212
5213       FOR_EACH_IMM_USE_FAST (use_p, imm_iter, scalar_dest)
5214        {
5215          if (!flow_bb_inside_loop_p (innerloop, gimple_bb (USE_STMT (use_p))))
5216            {
5217              exit_phi = USE_STMT (use_p);
5218              STMT_VINFO_VEC_STMT (vinfo_for_stmt (exit_phi)) = vec_stmt;
5219            }
5220        }
5221     }
5222
5223   /* Handle stmts whose DEF is used outside the loop-nest that is
5224      being vectorized.  */
5225   if (STMT_VINFO_LIVE_P (stmt_info)
5226       && STMT_VINFO_TYPE (stmt_info) != reduc_vec_info_type)
5227     {
5228       done = vectorizable_live_operation (stmt, gsi, &vec_stmt);
5229       gcc_assert (done);
5230     }
5231
5232   if (vec_stmt)
5233     STMT_VINFO_VEC_STMT (stmt_info) = vec_stmt;
5234
5235   return is_store;
5236 }
5237
5238
5239 /* Remove a group of stores (for SLP or interleaving), free their
5240    stmt_vec_info.  */
5241
5242 void
5243 vect_remove_stores (gimple first_stmt)
5244 {
5245   gimple next = first_stmt;
5246   gimple tmp;
5247   gimple_stmt_iterator next_si;
5248
5249   while (next)
5250     {
5251       /* Free the attached stmt_vec_info and remove the stmt.  */
5252       next_si = gsi_for_stmt (next);
5253       gsi_remove (&next_si, true);
5254       tmp = GROUP_NEXT_ELEMENT (vinfo_for_stmt (next));
5255       free_stmt_vec_info (next);
5256       next = tmp;
5257     }
5258 }
5259
5260
5261 /* Function new_stmt_vec_info.
5262
5263    Create and initialize a new stmt_vec_info struct for STMT.  */
5264
5265 stmt_vec_info
5266 new_stmt_vec_info (gimple stmt, loop_vec_info loop_vinfo,
5267                    bb_vec_info bb_vinfo)
5268 {
5269   stmt_vec_info res;
5270   res = (stmt_vec_info) xcalloc (1, sizeof (struct _stmt_vec_info));
5271
5272   STMT_VINFO_TYPE (res) = undef_vec_info_type;
5273   STMT_VINFO_STMT (res) = stmt;
5274   STMT_VINFO_LOOP_VINFO (res) = loop_vinfo;
5275   STMT_VINFO_BB_VINFO (res) = bb_vinfo;
5276   STMT_VINFO_RELEVANT (res) = vect_unused_in_scope;
5277   STMT_VINFO_LIVE_P (res) = false;
5278   STMT_VINFO_VECTYPE (res) = NULL;
5279   STMT_VINFO_VEC_STMT (res) = NULL;
5280   STMT_VINFO_VECTORIZABLE (res) = true;
5281   STMT_VINFO_IN_PATTERN_P (res) = false;
5282   STMT_VINFO_RELATED_STMT (res) = NULL;
5283   STMT_VINFO_DATA_REF (res) = NULL;
5284
5285   STMT_VINFO_DR_BASE_ADDRESS (res) = NULL;
5286   STMT_VINFO_DR_OFFSET (res) = NULL;
5287   STMT_VINFO_DR_INIT (res) = NULL;
5288   STMT_VINFO_DR_STEP (res) = NULL;
5289   STMT_VINFO_DR_ALIGNED_TO (res) = NULL;
5290
5291   if (gimple_code (stmt) == GIMPLE_PHI
5292       && is_loop_header_bb_p (gimple_bb (stmt)))
5293     STMT_VINFO_DEF_TYPE (res) = vect_unknown_def_type;
5294   else
5295     STMT_VINFO_DEF_TYPE (res) = vect_internal_def;
5296
5297   STMT_VINFO_SAME_ALIGN_REFS (res) = VEC_alloc (dr_p, heap, 5);
5298   STMT_VINFO_INSIDE_OF_LOOP_COST (res) = 0;
5299   STMT_VINFO_OUTSIDE_OF_LOOP_COST (res) = 0;
5300   STMT_SLP_TYPE (res) = loop_vect;
5301   GROUP_FIRST_ELEMENT (res) = NULL;
5302   GROUP_NEXT_ELEMENT (res) = NULL;
5303   GROUP_SIZE (res) = 0;
5304   GROUP_STORE_COUNT (res) = 0;
5305   GROUP_GAP (res) = 0;
5306   GROUP_SAME_DR_STMT (res) = NULL;
5307   GROUP_READ_WRITE_DEPENDENCE (res) = false;
5308
5309   return res;
5310 }
5311
5312
5313 /* Create a hash table for stmt_vec_info. */
5314
5315 void
5316 init_stmt_vec_info_vec (void)
5317 {
5318   gcc_assert (!stmt_vec_info_vec);
5319   stmt_vec_info_vec = VEC_alloc (vec_void_p, heap, 50);
5320 }
5321
5322
5323 /* Free hash table for stmt_vec_info. */
5324
5325 void
5326 free_stmt_vec_info_vec (void)
5327 {
5328   gcc_assert (stmt_vec_info_vec);
5329   VEC_free (vec_void_p, heap, stmt_vec_info_vec);
5330 }
5331
5332
5333 /* Free stmt vectorization related info.  */
5334
5335 void
5336 free_stmt_vec_info (gimple stmt)
5337 {
5338   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
5339
5340   if (!stmt_info)
5341     return;
5342
5343   VEC_free (dr_p, heap, STMT_VINFO_SAME_ALIGN_REFS (stmt_info));
5344   set_vinfo_for_stmt (stmt, NULL);
5345   free (stmt_info);
5346 }
5347
5348
5349 /* Function get_vectype_for_scalar_type_and_size.
5350
5351    Returns the vector type corresponding to SCALAR_TYPE  and SIZE as supported
5352    by the target.  */
5353
5354 static tree
5355 get_vectype_for_scalar_type_and_size (tree scalar_type, unsigned size)
5356 {
5357   enum machine_mode inner_mode = TYPE_MODE (scalar_type);
5358   enum machine_mode simd_mode;
5359   unsigned int nbytes = GET_MODE_SIZE (inner_mode);
5360   int nunits;
5361   tree vectype;
5362
5363   if (nbytes == 0)
5364     return NULL_TREE;
5365
5366   /* We can't build a vector type of elements with alignment bigger than
5367      their size.  */
5368   if (nbytes < TYPE_ALIGN_UNIT (scalar_type))
5369     return NULL_TREE;
5370
5371   /* If we'd build a vector type of elements whose mode precision doesn't
5372      match their types precision we'll get mismatched types on vector
5373      extracts via BIT_FIELD_REFs.  This effectively means we disable
5374      vectorization of bool and/or enum types in some languages.  */
5375   if (INTEGRAL_TYPE_P (scalar_type)
5376       && GET_MODE_BITSIZE (inner_mode) != TYPE_PRECISION (scalar_type))
5377     return NULL_TREE;
5378
5379   if (GET_MODE_CLASS (inner_mode) != MODE_INT
5380       && GET_MODE_CLASS (inner_mode) != MODE_FLOAT)
5381     return NULL_TREE;
5382
5383   /* We shouldn't end up building VECTOR_TYPEs of non-scalar components.
5384      When the component mode passes the above test simply use a type
5385      corresponding to that mode.  The theory is that any use that
5386      would cause problems with this will disable vectorization anyway.  */
5387   if (!SCALAR_FLOAT_TYPE_P (scalar_type)
5388       && !INTEGRAL_TYPE_P (scalar_type)
5389       && !POINTER_TYPE_P (scalar_type))
5390     scalar_type = lang_hooks.types.type_for_mode (inner_mode, 1);
5391
5392   /* If no size was supplied use the mode the target prefers.   Otherwise
5393      lookup a vector mode of the specified size.  */
5394   if (size == 0)
5395     simd_mode = targetm.vectorize.preferred_simd_mode (inner_mode);
5396   else
5397     simd_mode = mode_for_vector (inner_mode, size / nbytes);
5398   nunits = GET_MODE_SIZE (simd_mode) / nbytes;
5399   if (nunits <= 1)
5400     return NULL_TREE;
5401
5402   vectype = build_vector_type (scalar_type, nunits);
5403   if (vect_print_dump_info (REPORT_DETAILS))
5404     {
5405       fprintf (vect_dump, "get vectype with %d units of type ", nunits);
5406       print_generic_expr (vect_dump, scalar_type, TDF_SLIM);
5407     }
5408
5409   if (!vectype)
5410     return NULL_TREE;
5411
5412   if (vect_print_dump_info (REPORT_DETAILS))
5413     {
5414       fprintf (vect_dump, "vectype: ");
5415       print_generic_expr (vect_dump, vectype, TDF_SLIM);
5416     }
5417
5418   if (!VECTOR_MODE_P (TYPE_MODE (vectype))
5419       && !INTEGRAL_MODE_P (TYPE_MODE (vectype)))
5420     {
5421       if (vect_print_dump_info (REPORT_DETAILS))
5422         fprintf (vect_dump, "mode not supported by target.");
5423       return NULL_TREE;
5424     }
5425
5426   return vectype;
5427 }
5428
5429 unsigned int current_vector_size;
5430
5431 /* Function get_vectype_for_scalar_type.
5432
5433    Returns the vector type corresponding to SCALAR_TYPE as supported
5434    by the target.  */
5435
5436 tree
5437 get_vectype_for_scalar_type (tree scalar_type)
5438 {
5439   tree vectype;
5440   vectype = get_vectype_for_scalar_type_and_size (scalar_type,
5441                                                   current_vector_size);
5442   if (vectype
5443       && current_vector_size == 0)
5444     current_vector_size = GET_MODE_SIZE (TYPE_MODE (vectype));
5445   return vectype;
5446 }
5447
5448 /* Function get_same_sized_vectype
5449
5450    Returns a vector type corresponding to SCALAR_TYPE of size
5451    VECTOR_TYPE if supported by the target.  */
5452
5453 tree
5454 get_same_sized_vectype (tree scalar_type, tree vector_type)
5455 {
5456   return get_vectype_for_scalar_type_and_size
5457            (scalar_type, GET_MODE_SIZE (TYPE_MODE (vector_type)));
5458 }
5459
5460 /* Function vect_is_simple_use.
5461
5462    Input:
5463    LOOP_VINFO - the vect info of the loop that is being vectorized.
5464    BB_VINFO - the vect info of the basic block that is being vectorized.
5465    OPERAND - operand of a stmt in the loop or bb.
5466    DEF - the defining stmt in case OPERAND is an SSA_NAME.
5467
5468    Returns whether a stmt with OPERAND can be vectorized.
5469    For loops, supportable operands are constants, loop invariants, and operands
5470    that are defined by the current iteration of the loop.  Unsupportable
5471    operands are those that are defined by a previous iteration of the loop (as
5472    is the case in reduction/induction computations).
5473    For basic blocks, supportable operands are constants and bb invariants.
5474    For now, operands defined outside the basic block are not supported.  */
5475
5476 bool
5477 vect_is_simple_use (tree operand, loop_vec_info loop_vinfo,
5478                     bb_vec_info bb_vinfo, gimple *def_stmt,
5479                     tree *def, enum vect_def_type *dt)
5480 {
5481   basic_block bb;
5482   stmt_vec_info stmt_vinfo;
5483   struct loop *loop = NULL;
5484
5485   if (loop_vinfo)
5486     loop = LOOP_VINFO_LOOP (loop_vinfo);
5487
5488   *def_stmt = NULL;
5489   *def = NULL_TREE;
5490
5491   if (vect_print_dump_info (REPORT_DETAILS))
5492     {
5493       fprintf (vect_dump, "vect_is_simple_use: operand ");
5494       print_generic_expr (vect_dump, operand, TDF_SLIM);
5495     }
5496
5497   if (TREE_CODE (operand) == INTEGER_CST || TREE_CODE (operand) == REAL_CST)
5498     {
5499       *dt = vect_constant_def;
5500       return true;
5501     }
5502
5503   if (is_gimple_min_invariant (operand))
5504     {
5505       *def = operand;
5506       *dt = vect_external_def;
5507       return true;
5508     }
5509
5510   if (TREE_CODE (operand) == PAREN_EXPR)
5511     {
5512       if (vect_print_dump_info (REPORT_DETAILS))
5513         fprintf (vect_dump, "non-associatable copy.");
5514       operand = TREE_OPERAND (operand, 0);
5515     }
5516
5517   if (TREE_CODE (operand) != SSA_NAME)
5518     {
5519       if (vect_print_dump_info (REPORT_DETAILS))
5520         fprintf (vect_dump, "not ssa-name.");
5521       return false;
5522     }
5523
5524   *def_stmt = SSA_NAME_DEF_STMT (operand);
5525   if (*def_stmt == NULL)
5526     {
5527       if (vect_print_dump_info (REPORT_DETAILS))
5528         fprintf (vect_dump, "no def_stmt.");
5529       return false;
5530     }
5531
5532   if (vect_print_dump_info (REPORT_DETAILS))
5533     {
5534       fprintf (vect_dump, "def_stmt: ");
5535       print_gimple_stmt (vect_dump, *def_stmt, 0, TDF_SLIM);
5536     }
5537
5538   /* Empty stmt is expected only in case of a function argument.
5539      (Otherwise - we expect a phi_node or a GIMPLE_ASSIGN).  */
5540   if (gimple_nop_p (*def_stmt))
5541     {
5542       *def = operand;
5543       *dt = vect_external_def;
5544       return true;
5545     }
5546
5547   bb = gimple_bb (*def_stmt);
5548
5549   if ((loop && !flow_bb_inside_loop_p (loop, bb))
5550       || (!loop && bb != BB_VINFO_BB (bb_vinfo))
5551       || (!loop && gimple_code (*def_stmt) == GIMPLE_PHI))
5552     *dt = vect_external_def;
5553   else
5554     {
5555       stmt_vinfo = vinfo_for_stmt (*def_stmt);
5556       *dt = STMT_VINFO_DEF_TYPE (stmt_vinfo);
5557     }
5558
5559   if (*dt == vect_unknown_def_type)
5560     {
5561       if (vect_print_dump_info (REPORT_DETAILS))
5562         fprintf (vect_dump, "Unsupported pattern.");
5563       return false;
5564     }
5565
5566   if (vect_print_dump_info (REPORT_DETAILS))
5567     fprintf (vect_dump, "type of def: %d.",*dt);
5568
5569   switch (gimple_code (*def_stmt))
5570     {
5571     case GIMPLE_PHI:
5572       *def = gimple_phi_result (*def_stmt);
5573       break;
5574
5575     case GIMPLE_ASSIGN:
5576       *def = gimple_assign_lhs (*def_stmt);
5577       break;
5578
5579     case GIMPLE_CALL:
5580       *def = gimple_call_lhs (*def_stmt);
5581       if (*def != NULL)
5582         break;
5583       /* FALLTHRU */
5584     default:
5585       if (vect_print_dump_info (REPORT_DETAILS))
5586         fprintf (vect_dump, "unsupported defining stmt: ");
5587       return false;
5588     }
5589
5590   return true;
5591 }
5592
5593 /* Function vect_is_simple_use_1.
5594
5595    Same as vect_is_simple_use_1 but also determines the vector operand
5596    type of OPERAND and stores it to *VECTYPE.  If the definition of
5597    OPERAND is vect_uninitialized_def, vect_constant_def or
5598    vect_external_def *VECTYPE will be set to NULL_TREE and the caller
5599    is responsible to compute the best suited vector type for the
5600    scalar operand.  */
5601
5602 bool
5603 vect_is_simple_use_1 (tree operand, loop_vec_info loop_vinfo,
5604                       bb_vec_info bb_vinfo, gimple *def_stmt,
5605                       tree *def, enum vect_def_type *dt, tree *vectype)
5606 {
5607   if (!vect_is_simple_use (operand, loop_vinfo, bb_vinfo, def_stmt, def, dt))
5608     return false;
5609
5610   /* Now get a vector type if the def is internal, otherwise supply
5611      NULL_TREE and leave it up to the caller to figure out a proper
5612      type for the use stmt.  */
5613   if (*dt == vect_internal_def
5614       || *dt == vect_induction_def
5615       || *dt == vect_reduction_def
5616       || *dt == vect_double_reduction_def
5617       || *dt == vect_nested_cycle)
5618     {
5619       stmt_vec_info stmt_info = vinfo_for_stmt (*def_stmt);
5620
5621       if (STMT_VINFO_IN_PATTERN_P (stmt_info)
5622           && !STMT_VINFO_RELEVANT (stmt_info)
5623           && !STMT_VINFO_LIVE_P (stmt_info))
5624         stmt_info = vinfo_for_stmt (STMT_VINFO_RELATED_STMT (stmt_info));
5625
5626       *vectype = STMT_VINFO_VECTYPE (stmt_info);
5627       gcc_assert (*vectype != NULL_TREE);
5628     }
5629   else if (*dt == vect_uninitialized_def
5630            || *dt == vect_constant_def
5631            || *dt == vect_external_def)
5632     *vectype = NULL_TREE;
5633   else
5634     gcc_unreachable ();
5635
5636   return true;
5637 }
5638
5639
5640 /* Function supportable_widening_operation
5641
5642    Check whether an operation represented by the code CODE is a
5643    widening operation that is supported by the target platform in
5644    vector form (i.e., when operating on arguments of type VECTYPE_IN
5645    producing a result of type VECTYPE_OUT).
5646
5647    Widening operations we currently support are NOP (CONVERT), FLOAT
5648    and WIDEN_MULT.  This function checks if these operations are supported
5649    by the target platform either directly (via vector tree-codes), or via
5650    target builtins.
5651
5652    Output:
5653    - CODE1 and CODE2 are codes of vector operations to be used when
5654    vectorizing the operation, if available.
5655    - DECL1 and DECL2 are decls of target builtin functions to be used
5656    when vectorizing the operation, if available.  In this case,
5657    CODE1 and CODE2 are CALL_EXPR.
5658    - MULTI_STEP_CVT determines the number of required intermediate steps in
5659    case of multi-step conversion (like char->short->int - in that case
5660    MULTI_STEP_CVT will be 1).
5661    - INTERM_TYPES contains the intermediate type required to perform the
5662    widening operation (short in the above example).  */
5663
5664 bool
5665 supportable_widening_operation (enum tree_code code, gimple stmt,
5666                                 tree vectype_out, tree vectype_in,
5667                                 tree *decl1, tree *decl2,
5668                                 enum tree_code *code1, enum tree_code *code2,
5669                                 int *multi_step_cvt,
5670                                 VEC (tree, heap) **interm_types)
5671 {
5672   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
5673   loop_vec_info loop_info = STMT_VINFO_LOOP_VINFO (stmt_info);
5674   struct loop *vect_loop = LOOP_VINFO_LOOP (loop_info);
5675   bool ordered_p;
5676   enum machine_mode vec_mode;
5677   enum insn_code icode1, icode2;
5678   optab optab1, optab2;
5679   tree vectype = vectype_in;
5680   tree wide_vectype = vectype_out;
5681   enum tree_code c1, c2;
5682
5683   /* The result of a vectorized widening operation usually requires two vectors
5684      (because the widened results do not fit int one vector). The generated
5685      vector results would normally be expected to be generated in the same
5686      order as in the original scalar computation, i.e. if 8 results are
5687      generated in each vector iteration, they are to be organized as follows:
5688         vect1: [res1,res2,res3,res4], vect2: [res5,res6,res7,res8].
5689
5690      However, in the special case that the result of the widening operation is
5691      used in a reduction computation only, the order doesn't matter (because
5692      when vectorizing a reduction we change the order of the computation).
5693      Some targets can take advantage of this and generate more efficient code.
5694      For example, targets like Altivec, that support widen_mult using a sequence
5695      of {mult_even,mult_odd} generate the following vectors:
5696         vect1: [res1,res3,res5,res7], vect2: [res2,res4,res6,res8].
5697
5698      When vectorizing outer-loops, we execute the inner-loop sequentially
5699      (each vectorized inner-loop iteration contributes to VF outer-loop
5700      iterations in parallel).  We therefore don't allow to change the order
5701      of the computation in the inner-loop during outer-loop vectorization.  */
5702
5703    if (STMT_VINFO_RELEVANT (stmt_info) == vect_used_by_reduction
5704        && !nested_in_vect_loop_p (vect_loop, stmt))
5705      ordered_p = false;
5706    else
5707      ordered_p = true;
5708
5709   if (!ordered_p
5710       && code == WIDEN_MULT_EXPR
5711       && targetm.vectorize.builtin_mul_widen_even
5712       && targetm.vectorize.builtin_mul_widen_even (vectype)
5713       && targetm.vectorize.builtin_mul_widen_odd
5714       && targetm.vectorize.builtin_mul_widen_odd (vectype))
5715     {
5716       if (vect_print_dump_info (REPORT_DETAILS))
5717         fprintf (vect_dump, "Unordered widening operation detected.");
5718
5719       *code1 = *code2 = CALL_EXPR;
5720       *decl1 = targetm.vectorize.builtin_mul_widen_even (vectype);
5721       *decl2 = targetm.vectorize.builtin_mul_widen_odd (vectype);
5722       return true;
5723     }
5724
5725   switch (code)
5726     {
5727     case WIDEN_MULT_EXPR:
5728       if (BYTES_BIG_ENDIAN)
5729         {
5730           c1 = VEC_WIDEN_MULT_HI_EXPR;
5731           c2 = VEC_WIDEN_MULT_LO_EXPR;
5732         }
5733       else
5734         {
5735           c2 = VEC_WIDEN_MULT_HI_EXPR;
5736           c1 = VEC_WIDEN_MULT_LO_EXPR;
5737         }
5738       break;
5739
5740     CASE_CONVERT:
5741       if (BYTES_BIG_ENDIAN)
5742         {
5743           c1 = VEC_UNPACK_HI_EXPR;
5744           c2 = VEC_UNPACK_LO_EXPR;
5745         }
5746       else
5747         {
5748           c2 = VEC_UNPACK_HI_EXPR;
5749           c1 = VEC_UNPACK_LO_EXPR;
5750         }
5751       break;
5752
5753     case FLOAT_EXPR:
5754       if (BYTES_BIG_ENDIAN)
5755         {
5756           c1 = VEC_UNPACK_FLOAT_HI_EXPR;
5757           c2 = VEC_UNPACK_FLOAT_LO_EXPR;
5758         }
5759       else
5760         {
5761           c2 = VEC_UNPACK_FLOAT_HI_EXPR;
5762           c1 = VEC_UNPACK_FLOAT_LO_EXPR;
5763         }
5764       break;
5765
5766     case FIX_TRUNC_EXPR:
5767       /* ??? Not yet implemented due to missing VEC_UNPACK_FIX_TRUNC_HI_EXPR/
5768          VEC_UNPACK_FIX_TRUNC_LO_EXPR tree codes and optabs used for
5769          computing the operation.  */
5770       return false;
5771
5772     default:
5773       gcc_unreachable ();
5774     }
5775
5776   if (code == FIX_TRUNC_EXPR)
5777     {
5778       /* The signedness is determined from output operand.  */
5779       optab1 = optab_for_tree_code (c1, vectype_out, optab_default);
5780       optab2 = optab_for_tree_code (c2, vectype_out, optab_default);
5781     }
5782   else
5783     {
5784       optab1 = optab_for_tree_code (c1, vectype, optab_default);
5785       optab2 = optab_for_tree_code (c2, vectype, optab_default);
5786     }
5787
5788   if (!optab1 || !optab2)
5789     return false;
5790
5791   vec_mode = TYPE_MODE (vectype);
5792   if ((icode1 = optab_handler (optab1, vec_mode)) == CODE_FOR_nothing
5793        || (icode2 = optab_handler (optab2, vec_mode)) == CODE_FOR_nothing)
5794     return false;
5795
5796   /* Check if it's a multi-step conversion that can be done using intermediate
5797      types.  */
5798   if (insn_data[icode1].operand[0].mode != TYPE_MODE (wide_vectype)
5799        || insn_data[icode2].operand[0].mode != TYPE_MODE (wide_vectype))
5800     {
5801       int i;
5802       tree prev_type = vectype, intermediate_type;
5803       enum machine_mode intermediate_mode, prev_mode = vec_mode;
5804       optab optab3, optab4;
5805
5806       if (!CONVERT_EXPR_CODE_P (code))
5807         return false;
5808
5809       *code1 = c1;
5810       *code2 = c2;
5811
5812       /* We assume here that there will not be more than MAX_INTERM_CVT_STEPS
5813          intermediate steps in promotion sequence.  We try
5814          MAX_INTERM_CVT_STEPS to get to NARROW_VECTYPE, and fail if we do
5815          not.  */
5816       *interm_types = VEC_alloc (tree, heap, MAX_INTERM_CVT_STEPS);
5817       for (i = 0; i < 3; i++)
5818         {
5819           intermediate_mode = insn_data[icode1].operand[0].mode;
5820           intermediate_type = lang_hooks.types.type_for_mode (intermediate_mode,
5821                                                      TYPE_UNSIGNED (prev_type));
5822           optab3 = optab_for_tree_code (c1, intermediate_type, optab_default);
5823           optab4 = optab_for_tree_code (c2, intermediate_type, optab_default);
5824
5825           if (!optab3 || !optab4
5826               || ((icode1 = optab_handler (optab1, prev_mode))
5827                   == CODE_FOR_nothing)
5828               || insn_data[icode1].operand[0].mode != intermediate_mode
5829               || ((icode2 = optab_handler (optab2, prev_mode))
5830                   == CODE_FOR_nothing)
5831               || insn_data[icode2].operand[0].mode != intermediate_mode
5832               || ((icode1 = optab_handler (optab3, intermediate_mode))
5833                   == CODE_FOR_nothing)
5834               || ((icode2 = optab_handler (optab4, intermediate_mode))
5835                   == CODE_FOR_nothing))
5836             return false;
5837
5838           VEC_quick_push (tree, *interm_types, intermediate_type);
5839           (*multi_step_cvt)++;
5840
5841           if (insn_data[icode1].operand[0].mode == TYPE_MODE (wide_vectype)
5842               && insn_data[icode2].operand[0].mode == TYPE_MODE (wide_vectype))
5843             return true;
5844
5845           prev_type = intermediate_type;
5846           prev_mode = intermediate_mode;
5847         }
5848
5849        return false;
5850     }
5851
5852   *code1 = c1;
5853   *code2 = c2;
5854   return true;
5855 }
5856
5857
5858 /* Function supportable_narrowing_operation
5859
5860    Check whether an operation represented by the code CODE is a
5861    narrowing operation that is supported by the target platform in
5862    vector form (i.e., when operating on arguments of type VECTYPE_IN
5863    and producing a result of type VECTYPE_OUT).
5864
5865    Narrowing operations we currently support are NOP (CONVERT) and
5866    FIX_TRUNC.  This function checks if these operations are supported by
5867    the target platform directly via vector tree-codes.
5868
5869    Output:
5870    - CODE1 is the code of a vector operation to be used when
5871    vectorizing the operation, if available.
5872    - MULTI_STEP_CVT determines the number of required intermediate steps in
5873    case of multi-step conversion (like int->short->char - in that case
5874    MULTI_STEP_CVT will be 1).
5875    - INTERM_TYPES contains the intermediate type required to perform the
5876    narrowing operation (short in the above example).   */
5877
5878 bool
5879 supportable_narrowing_operation (enum tree_code code,
5880                                  tree vectype_out, tree vectype_in,
5881                                  enum tree_code *code1, int *multi_step_cvt,
5882                                  VEC (tree, heap) **interm_types)
5883 {
5884   enum machine_mode vec_mode;
5885   enum insn_code icode1;
5886   optab optab1, interm_optab;
5887   tree vectype = vectype_in;
5888   tree narrow_vectype = vectype_out;
5889   enum tree_code c1;
5890   tree intermediate_type, prev_type;
5891   int i;
5892
5893   switch (code)
5894     {
5895     CASE_CONVERT:
5896       c1 = VEC_PACK_TRUNC_EXPR;
5897       break;
5898
5899     case FIX_TRUNC_EXPR:
5900       c1 = VEC_PACK_FIX_TRUNC_EXPR;
5901       break;
5902
5903     case FLOAT_EXPR:
5904       /* ??? Not yet implemented due to missing VEC_PACK_FLOAT_EXPR
5905          tree code and optabs used for computing the operation.  */
5906       return false;
5907
5908     default:
5909       gcc_unreachable ();
5910     }
5911
5912   if (code == FIX_TRUNC_EXPR)
5913     /* The signedness is determined from output operand.  */
5914     optab1 = optab_for_tree_code (c1, vectype_out, optab_default);
5915   else
5916     optab1 = optab_for_tree_code (c1, vectype, optab_default);
5917
5918   if (!optab1)
5919     return false;
5920
5921   vec_mode = TYPE_MODE (vectype);
5922   if ((icode1 = optab_handler (optab1, vec_mode)) == CODE_FOR_nothing)
5923     return false;
5924
5925   /* Check if it's a multi-step conversion that can be done using intermediate
5926      types.  */
5927   if (insn_data[icode1].operand[0].mode != TYPE_MODE (narrow_vectype))
5928     {
5929       enum machine_mode intermediate_mode, prev_mode = vec_mode;
5930
5931       *code1 = c1;
5932       prev_type = vectype;
5933       /* We assume here that there will not be more than MAX_INTERM_CVT_STEPS
5934          intermediate steps in promotion sequence.  We try
5935          MAX_INTERM_CVT_STEPS to get to NARROW_VECTYPE, and fail if we do
5936          not.  */
5937       *interm_types = VEC_alloc (tree, heap, MAX_INTERM_CVT_STEPS);
5938       for (i = 0; i < 3; i++)
5939         {
5940           intermediate_mode = insn_data[icode1].operand[0].mode;
5941           intermediate_type = lang_hooks.types.type_for_mode (intermediate_mode,
5942                                                      TYPE_UNSIGNED (prev_type));
5943           interm_optab = optab_for_tree_code (c1, intermediate_type,
5944                                               optab_default);
5945           if (!interm_optab
5946               || ((icode1 = optab_handler (optab1, prev_mode))
5947                   == CODE_FOR_nothing)
5948               || insn_data[icode1].operand[0].mode != intermediate_mode
5949               || ((icode1 = optab_handler (interm_optab, intermediate_mode))
5950                   == CODE_FOR_nothing))
5951             return false;
5952
5953           VEC_quick_push (tree, *interm_types, intermediate_type);
5954           (*multi_step_cvt)++;
5955
5956           if (insn_data[icode1].operand[0].mode == TYPE_MODE (narrow_vectype))
5957             return true;
5958
5959           prev_type = intermediate_type;
5960           prev_mode = intermediate_mode;
5961         }
5962
5963       return false;
5964     }
5965
5966   *code1 = c1;
5967   return true;
5968 }