OSDN Git Service

PR rtl-optimization/50249
[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, 2011
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 (stmt));
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 + 1);
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 /* Return TRUE if CODE (a shift operation) is supported for SCALAR_TYPE
2216    either as shift by a scalar or by a vector.  */
2217
2218 bool
2219 vect_supportable_shift (enum tree_code code, tree scalar_type)
2220 {
2221
2222   enum machine_mode vec_mode;
2223   optab optab;
2224   int icode;
2225   tree vectype;
2226
2227   vectype = get_vectype_for_scalar_type (scalar_type);
2228   if (!vectype)
2229     return false;
2230
2231   optab = optab_for_tree_code (code, vectype, optab_scalar);
2232   if (!optab
2233       || optab_handler (optab, TYPE_MODE (vectype)) == CODE_FOR_nothing)
2234     {
2235       optab = optab_for_tree_code (code, vectype, optab_vector);
2236       if (!optab
2237           || (optab_handler (optab, TYPE_MODE (vectype))
2238                       == CODE_FOR_nothing))
2239         return false;
2240     }
2241
2242   vec_mode = TYPE_MODE (vectype);
2243   icode = (int) optab_handler (optab, vec_mode);
2244   if (icode == CODE_FOR_nothing)
2245     return false;
2246
2247   return true;
2248 }
2249
2250
2251 /* Function vectorizable_shift.
2252
2253    Check if STMT performs a shift operation that can be vectorized.
2254    If VEC_STMT is also passed, vectorize the STMT: create a vectorized
2255    stmt to replace it, put it in VEC_STMT, and insert it at BSI.
2256    Return FALSE if not a vectorizable STMT, TRUE otherwise.  */
2257
2258 static bool
2259 vectorizable_shift (gimple stmt, gimple_stmt_iterator *gsi,
2260                     gimple *vec_stmt, slp_tree slp_node)
2261 {
2262   tree vec_dest;
2263   tree scalar_dest;
2264   tree op0, op1 = NULL;
2265   tree vec_oprnd1 = NULL_TREE;
2266   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
2267   tree vectype;
2268   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
2269   enum tree_code code;
2270   enum machine_mode vec_mode;
2271   tree new_temp;
2272   optab optab;
2273   int icode;
2274   enum machine_mode optab_op2_mode;
2275   tree def;
2276   gimple def_stmt;
2277   enum vect_def_type dt[2] = {vect_unknown_def_type, vect_unknown_def_type};
2278   gimple new_stmt = NULL;
2279   stmt_vec_info prev_stmt_info;
2280   int nunits_in;
2281   int nunits_out;
2282   tree vectype_out;
2283   int ncopies;
2284   int j, i;
2285   VEC (tree, heap) *vec_oprnds0 = NULL, *vec_oprnds1 = NULL;
2286   tree vop0, vop1;
2287   unsigned int k;
2288   bool scalar_shift_arg = true;
2289   bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
2290   int vf;
2291
2292   if (!STMT_VINFO_RELEVANT_P (stmt_info) && !bb_vinfo)
2293     return false;
2294
2295   if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def)
2296     return false;
2297
2298   /* Is STMT a vectorizable binary/unary operation?   */
2299   if (!is_gimple_assign (stmt))
2300     return false;
2301
2302   if (TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME)
2303     return false;
2304
2305   code = gimple_assign_rhs_code (stmt);
2306
2307   if (!(code == LSHIFT_EXPR || code == RSHIFT_EXPR || code == LROTATE_EXPR
2308       || code == RROTATE_EXPR))
2309     return false;
2310
2311   scalar_dest = gimple_assign_lhs (stmt);
2312   vectype_out = STMT_VINFO_VECTYPE (stmt_info);
2313
2314   op0 = gimple_assign_rhs1 (stmt);
2315   if (!vect_is_simple_use_1 (op0, loop_vinfo, bb_vinfo,
2316                              &def_stmt, &def, &dt[0], &vectype))
2317     {
2318       if (vect_print_dump_info (REPORT_DETAILS))
2319         fprintf (vect_dump, "use not simple.");
2320       return false;
2321     }
2322   /* If op0 is an external or constant def use a vector type with
2323      the same size as the output vector type.  */
2324   if (!vectype)
2325     vectype = get_same_sized_vectype (TREE_TYPE (op0), vectype_out);
2326   if (vec_stmt)
2327     gcc_assert (vectype);
2328   if (!vectype)
2329     {
2330       if (vect_print_dump_info (REPORT_DETAILS))
2331         {
2332           fprintf (vect_dump, "no vectype for scalar type ");
2333           print_generic_expr (vect_dump, TREE_TYPE (op0), TDF_SLIM);
2334         }
2335
2336       return false;
2337     }
2338
2339   nunits_out = TYPE_VECTOR_SUBPARTS (vectype_out);
2340   nunits_in = TYPE_VECTOR_SUBPARTS (vectype);
2341   if (nunits_out != nunits_in)
2342     return false;
2343
2344   op1 = gimple_assign_rhs2 (stmt);
2345   if (!vect_is_simple_use (op1, loop_vinfo, bb_vinfo, &def_stmt, &def, &dt[1]))
2346     {
2347       if (vect_print_dump_info (REPORT_DETAILS))
2348         fprintf (vect_dump, "use not simple.");
2349       return false;
2350     }
2351
2352   if (loop_vinfo)
2353     vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
2354   else
2355     vf = 1;
2356
2357   /* Multiple types in SLP are handled by creating the appropriate number of
2358      vectorized stmts for each SLP node.  Hence, NCOPIES is always 1 in
2359      case of SLP.  */
2360   if (slp_node || PURE_SLP_STMT (stmt_info))
2361     ncopies = 1;
2362   else
2363     ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits_in;
2364
2365   gcc_assert (ncopies >= 1);
2366
2367   /* Determine whether the shift amount is a vector, or scalar.  If the
2368      shift/rotate amount is a vector, use the vector/vector shift optabs.  */
2369
2370   if (dt[1] == vect_internal_def && !slp_node)
2371     scalar_shift_arg = false;
2372   else if (dt[1] == vect_constant_def
2373            || dt[1] == vect_external_def
2374            || dt[1] == vect_internal_def)
2375     {
2376       /* In SLP, need to check whether the shift count is the same,
2377          in loops if it is a constant or invariant, it is always
2378          a scalar shift.  */
2379       if (slp_node)
2380         {
2381           VEC (gimple, heap) *stmts = SLP_TREE_SCALAR_STMTS (slp_node);
2382           gimple slpstmt;
2383
2384           FOR_EACH_VEC_ELT (gimple, stmts, k, slpstmt)
2385             if (!operand_equal_p (gimple_assign_rhs2 (slpstmt), op1, 0))
2386               scalar_shift_arg = false;
2387         }
2388     }
2389   else
2390     {
2391       if (vect_print_dump_info (REPORT_DETAILS))
2392         fprintf (vect_dump, "operand mode requires invariant argument.");
2393       return false;
2394     }
2395
2396   /* Vector shifted by vector.  */
2397   if (!scalar_shift_arg)
2398     {
2399       optab = optab_for_tree_code (code, vectype, optab_vector);
2400       if (vect_print_dump_info (REPORT_DETAILS))
2401         fprintf (vect_dump, "vector/vector shift/rotate found.");
2402     }
2403   /* See if the machine has a vector shifted by scalar insn and if not
2404      then see if it has a vector shifted by vector insn.  */
2405   else
2406     {
2407       optab = optab_for_tree_code (code, vectype, optab_scalar);
2408       if (optab
2409           && optab_handler (optab, TYPE_MODE (vectype)) != CODE_FOR_nothing)
2410         {
2411           if (vect_print_dump_info (REPORT_DETAILS))
2412             fprintf (vect_dump, "vector/scalar shift/rotate found.");
2413         }
2414       else
2415         {
2416           optab = optab_for_tree_code (code, vectype, optab_vector);
2417           if (optab
2418                && (optab_handler (optab, TYPE_MODE (vectype))
2419                       != CODE_FOR_nothing))
2420             {
2421               scalar_shift_arg = false;
2422
2423               if (vect_print_dump_info (REPORT_DETAILS))
2424                 fprintf (vect_dump, "vector/vector shift/rotate found.");
2425
2426               /* Unlike the other binary operators, shifts/rotates have
2427                  the rhs being int, instead of the same type as the lhs,
2428                  so make sure the scalar is the right type if we are
2429                  dealing with vectors of short/char.  */
2430               if (dt[1] == vect_constant_def)
2431                 op1 = fold_convert (TREE_TYPE (vectype), op1);
2432             }
2433         }
2434     }
2435
2436   /* Supportable by target?  */
2437   if (!optab)
2438     {
2439       if (vect_print_dump_info (REPORT_DETAILS))
2440         fprintf (vect_dump, "no optab.");
2441       return false;
2442     }
2443   vec_mode = TYPE_MODE (vectype);
2444   icode = (int) optab_handler (optab, vec_mode);
2445   if (icode == CODE_FOR_nothing)
2446     {
2447       if (vect_print_dump_info (REPORT_DETAILS))
2448         fprintf (vect_dump, "op not supported by target.");
2449       /* Check only during analysis.  */
2450       if (GET_MODE_SIZE (vec_mode) != UNITS_PER_WORD
2451           || (vf < vect_min_worthwhile_factor (code)
2452               && !vec_stmt))
2453         return false;
2454       if (vect_print_dump_info (REPORT_DETAILS))
2455         fprintf (vect_dump, "proceeding using word mode.");
2456     }
2457
2458   /* Worthwhile without SIMD support?  Check only during analysis.  */
2459   if (!VECTOR_MODE_P (TYPE_MODE (vectype))
2460       && vf < vect_min_worthwhile_factor (code)
2461       && !vec_stmt)
2462     {
2463       if (vect_print_dump_info (REPORT_DETAILS))
2464         fprintf (vect_dump, "not worthwhile without SIMD support.");
2465       return false;
2466     }
2467
2468   if (!vec_stmt) /* transformation not required.  */
2469     {
2470       STMT_VINFO_TYPE (stmt_info) = shift_vec_info_type;
2471       if (vect_print_dump_info (REPORT_DETAILS))
2472         fprintf (vect_dump, "=== vectorizable_shift ===");
2473       vect_model_simple_cost (stmt_info, ncopies, dt, NULL);
2474       return true;
2475     }
2476
2477   /** Transform.  **/
2478
2479   if (vect_print_dump_info (REPORT_DETAILS))
2480     fprintf (vect_dump, "transform binary/unary operation.");
2481
2482   /* Handle def.  */
2483   vec_dest = vect_create_destination_var (scalar_dest, vectype);
2484
2485   /* Allocate VECs for vector operands.  In case of SLP, vector operands are
2486      created in the previous stages of the recursion, so no allocation is
2487      needed, except for the case of shift with scalar shift argument.  In that
2488      case we store the scalar operand in VEC_OPRNDS1 for every vector stmt to
2489      be created to vectorize the SLP group, i.e., SLP_NODE->VEC_STMTS_SIZE.
2490      In case of loop-based vectorization we allocate VECs of size 1.  We
2491      allocate VEC_OPRNDS1 only in case of binary operation.  */
2492   if (!slp_node)
2493     {
2494       vec_oprnds0 = VEC_alloc (tree, heap, 1);
2495       vec_oprnds1 = VEC_alloc (tree, heap, 1);
2496     }
2497   else if (scalar_shift_arg)
2498     vec_oprnds1 = VEC_alloc (tree, heap, slp_node->vec_stmts_size);
2499
2500   prev_stmt_info = NULL;
2501   for (j = 0; j < ncopies; j++)
2502     {
2503       /* Handle uses.  */
2504       if (j == 0)
2505         {
2506           if (scalar_shift_arg)
2507             {
2508               /* Vector shl and shr insn patterns can be defined with scalar
2509                  operand 2 (shift operand).  In this case, use constant or loop
2510                  invariant op1 directly, without extending it to vector mode
2511                  first.  */
2512               optab_op2_mode = insn_data[icode].operand[2].mode;
2513               if (!VECTOR_MODE_P (optab_op2_mode))
2514                 {
2515                   if (vect_print_dump_info (REPORT_DETAILS))
2516                     fprintf (vect_dump, "operand 1 using scalar mode.");
2517                   vec_oprnd1 = op1;
2518                   VEC_quick_push (tree, vec_oprnds1, vec_oprnd1);
2519                   if (slp_node)
2520                     {
2521                       /* Store vec_oprnd1 for every vector stmt to be created
2522                          for SLP_NODE.  We check during the analysis that all
2523                          the shift arguments are the same.
2524                          TODO: Allow different constants for different vector
2525                          stmts generated for an SLP instance.  */
2526                       for (k = 0; k < slp_node->vec_stmts_size - 1; k++)
2527                         VEC_quick_push (tree, vec_oprnds1, vec_oprnd1);
2528                     }
2529                 }
2530             }
2531
2532           /* vec_oprnd1 is available if operand 1 should be of a scalar-type
2533              (a special case for certain kind of vector shifts); otherwise,
2534              operand 1 should be of a vector type (the usual case).  */
2535           if (vec_oprnd1)
2536             vect_get_vec_defs (op0, NULL_TREE, stmt, &vec_oprnds0, NULL,
2537                                slp_node);
2538           else
2539             vect_get_vec_defs (op0, op1, stmt, &vec_oprnds0, &vec_oprnds1,
2540                                slp_node);
2541         }
2542       else
2543         vect_get_vec_defs_for_stmt_copy (dt, &vec_oprnds0, &vec_oprnds1);
2544
2545       /* Arguments are ready.  Create the new vector stmt.  */
2546       FOR_EACH_VEC_ELT (tree, vec_oprnds0, i, vop0)
2547         {
2548           vop1 = VEC_index (tree, vec_oprnds1, i);
2549           new_stmt = gimple_build_assign_with_ops (code, vec_dest, vop0, vop1);
2550           new_temp = make_ssa_name (vec_dest, new_stmt);
2551           gimple_assign_set_lhs (new_stmt, new_temp);
2552           vect_finish_stmt_generation (stmt, new_stmt, gsi);
2553           if (slp_node)
2554             VEC_quick_push (gimple, SLP_TREE_VEC_STMTS (slp_node), new_stmt);
2555         }
2556
2557       if (slp_node)
2558         continue;
2559
2560       if (j == 0)
2561         STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
2562       else
2563         STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
2564       prev_stmt_info = vinfo_for_stmt (new_stmt);
2565     }
2566
2567   VEC_free (tree, heap, vec_oprnds0);
2568   VEC_free (tree, heap, vec_oprnds1);
2569
2570   return true;
2571 }
2572
2573
2574 /* Function vectorizable_operation.
2575
2576    Check if STMT performs a binary, unary or ternary operation that can
2577    be vectorized.
2578    If VEC_STMT is also passed, vectorize the STMT: create a vectorized
2579    stmt to replace it, put it in VEC_STMT, and insert it at BSI.
2580    Return FALSE if not a vectorizable STMT, TRUE otherwise.  */
2581
2582 static bool
2583 vectorizable_operation (gimple stmt, gimple_stmt_iterator *gsi,
2584                         gimple *vec_stmt, slp_tree slp_node)
2585 {
2586   tree vec_dest;
2587   tree scalar_dest;
2588   tree op0, op1 = NULL_TREE, op2 = NULL_TREE;
2589   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
2590   tree vectype;
2591   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
2592   enum tree_code code;
2593   enum machine_mode vec_mode;
2594   tree new_temp;
2595   int op_type;
2596   optab optab;
2597   int icode;
2598   tree def;
2599   gimple def_stmt;
2600   enum vect_def_type dt[3]
2601     = {vect_unknown_def_type, vect_unknown_def_type, vect_unknown_def_type};
2602   gimple new_stmt = NULL;
2603   stmt_vec_info prev_stmt_info;
2604   int nunits_in;
2605   int nunits_out;
2606   tree vectype_out;
2607   int ncopies;
2608   int j, i;
2609   VEC(tree,heap) *vec_oprnds0 = NULL, *vec_oprnds1 = NULL, *vec_oprnds2 = NULL;
2610   tree vop0, vop1, vop2;
2611   bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
2612   int vf;
2613
2614   if (!STMT_VINFO_RELEVANT_P (stmt_info) && !bb_vinfo)
2615     return false;
2616
2617   if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def)
2618     return false;
2619
2620   /* Is STMT a vectorizable binary/unary operation?   */
2621   if (!is_gimple_assign (stmt))
2622     return false;
2623
2624   if (TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME)
2625     return false;
2626
2627   code = gimple_assign_rhs_code (stmt);
2628
2629   /* For pointer addition, we should use the normal plus for
2630      the vector addition.  */
2631   if (code == POINTER_PLUS_EXPR)
2632     code = PLUS_EXPR;
2633
2634   /* Support only unary or binary operations.  */
2635   op_type = TREE_CODE_LENGTH (code);
2636   if (op_type != unary_op && op_type != binary_op && op_type != ternary_op)
2637     {
2638       if (vect_print_dump_info (REPORT_DETAILS))
2639         fprintf (vect_dump, "num. args = %d (not unary/binary/ternary op).",
2640                  op_type);
2641       return false;
2642     }
2643
2644   scalar_dest = gimple_assign_lhs (stmt);
2645   vectype_out = STMT_VINFO_VECTYPE (stmt_info);
2646
2647   op0 = gimple_assign_rhs1 (stmt);
2648   if (!vect_is_simple_use_1 (op0, loop_vinfo, bb_vinfo,
2649                              &def_stmt, &def, &dt[0], &vectype))
2650     {
2651       if (vect_print_dump_info (REPORT_DETAILS))
2652         fprintf (vect_dump, "use not simple.");
2653       return false;
2654     }
2655   /* If op0 is an external or constant def use a vector type with
2656      the same size as the output vector type.  */
2657   if (!vectype)
2658     vectype = get_same_sized_vectype (TREE_TYPE (op0), vectype_out);
2659   if (vec_stmt)
2660     gcc_assert (vectype);
2661   if (!vectype)
2662     {
2663       if (vect_print_dump_info (REPORT_DETAILS))
2664         {
2665           fprintf (vect_dump, "no vectype for scalar type ");
2666           print_generic_expr (vect_dump, TREE_TYPE (op0), TDF_SLIM);
2667         }
2668
2669       return false;
2670     }
2671
2672   nunits_out = TYPE_VECTOR_SUBPARTS (vectype_out);
2673   nunits_in = TYPE_VECTOR_SUBPARTS (vectype);
2674   if (nunits_out != nunits_in)
2675     return false;
2676
2677   if (op_type == binary_op || op_type == ternary_op)
2678     {
2679       op1 = gimple_assign_rhs2 (stmt);
2680       if (!vect_is_simple_use (op1, loop_vinfo, bb_vinfo, &def_stmt, &def,
2681                                &dt[1]))
2682         {
2683           if (vect_print_dump_info (REPORT_DETAILS))
2684             fprintf (vect_dump, "use not simple.");
2685           return false;
2686         }
2687     }
2688   if (op_type == ternary_op)
2689     {
2690       op2 = gimple_assign_rhs3 (stmt);
2691       if (!vect_is_simple_use (op2, loop_vinfo, bb_vinfo, &def_stmt, &def,
2692                                &dt[2]))
2693         {
2694           if (vect_print_dump_info (REPORT_DETAILS))
2695             fprintf (vect_dump, "use not simple.");
2696           return false;
2697         }
2698     }
2699
2700   if (loop_vinfo)
2701     vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
2702   else
2703     vf = 1;
2704
2705   /* Multiple types in SLP are handled by creating the appropriate number of
2706      vectorized stmts for each SLP node.  Hence, NCOPIES is always 1 in
2707      case of SLP.  */
2708   if (slp_node || PURE_SLP_STMT (stmt_info))
2709     ncopies = 1;
2710   else
2711     ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits_in;
2712
2713   gcc_assert (ncopies >= 1);
2714
2715   /* Shifts are handled in vectorizable_shift ().  */
2716   if (code == LSHIFT_EXPR || code == RSHIFT_EXPR || code == LROTATE_EXPR
2717       || code == RROTATE_EXPR)
2718    return false;
2719
2720   optab = optab_for_tree_code (code, vectype, optab_default);
2721
2722   /* Supportable by target?  */
2723   if (!optab)
2724     {
2725       if (vect_print_dump_info (REPORT_DETAILS))
2726         fprintf (vect_dump, "no optab.");
2727       return false;
2728     }
2729   vec_mode = TYPE_MODE (vectype);
2730   icode = (int) optab_handler (optab, vec_mode);
2731   if (icode == CODE_FOR_nothing)
2732     {
2733       if (vect_print_dump_info (REPORT_DETAILS))
2734         fprintf (vect_dump, "op not supported by target.");
2735       /* Check only during analysis.  */
2736       if (GET_MODE_SIZE (vec_mode) != UNITS_PER_WORD
2737           || (vf < vect_min_worthwhile_factor (code)
2738               && !vec_stmt))
2739         return false;
2740       if (vect_print_dump_info (REPORT_DETAILS))
2741         fprintf (vect_dump, "proceeding using word mode.");
2742     }
2743
2744   /* Worthwhile without SIMD support?  Check only during analysis.  */
2745   if (!VECTOR_MODE_P (TYPE_MODE (vectype))
2746       && vf < vect_min_worthwhile_factor (code)
2747       && !vec_stmt)
2748     {
2749       if (vect_print_dump_info (REPORT_DETAILS))
2750         fprintf (vect_dump, "not worthwhile without SIMD support.");
2751       return false;
2752     }
2753
2754   if (!vec_stmt) /* transformation not required.  */
2755     {
2756       STMT_VINFO_TYPE (stmt_info) = op_vec_info_type;
2757       if (vect_print_dump_info (REPORT_DETAILS))
2758         fprintf (vect_dump, "=== vectorizable_operation ===");
2759       vect_model_simple_cost (stmt_info, ncopies, dt, NULL);
2760       return true;
2761     }
2762
2763   /** Transform.  **/
2764
2765   if (vect_print_dump_info (REPORT_DETAILS))
2766     fprintf (vect_dump, "transform binary/unary operation.");
2767
2768   /* Handle def.  */
2769   vec_dest = vect_create_destination_var (scalar_dest, vectype);
2770
2771   /* Allocate VECs for vector operands.  In case of SLP, vector operands are
2772      created in the previous stages of the recursion, so no allocation is
2773      needed, except for the case of shift with scalar shift argument.  In that
2774      case we store the scalar operand in VEC_OPRNDS1 for every vector stmt to
2775      be created to vectorize the SLP group, i.e., SLP_NODE->VEC_STMTS_SIZE.
2776      In case of loop-based vectorization we allocate VECs of size 1.  We
2777      allocate VEC_OPRNDS1 only in case of binary operation.  */
2778   if (!slp_node)
2779     {
2780       vec_oprnds0 = VEC_alloc (tree, heap, 1);
2781       if (op_type == binary_op || op_type == ternary_op)
2782         vec_oprnds1 = VEC_alloc (tree, heap, 1);
2783       if (op_type == ternary_op)
2784         vec_oprnds2 = VEC_alloc (tree, heap, 1);
2785     }
2786
2787   /* In case the vectorization factor (VF) is bigger than the number
2788      of elements that we can fit in a vectype (nunits), we have to generate
2789      more than one vector stmt - i.e - we need to "unroll" the
2790      vector stmt by a factor VF/nunits.  In doing so, we record a pointer
2791      from one copy of the vector stmt to the next, in the field
2792      STMT_VINFO_RELATED_STMT.  This is necessary in order to allow following
2793      stages to find the correct vector defs to be used when vectorizing
2794      stmts that use the defs of the current stmt.  The example below
2795      illustrates the vectorization process when VF=16 and nunits=4 (i.e.,
2796      we need to create 4 vectorized stmts):
2797
2798      before vectorization:
2799                                 RELATED_STMT    VEC_STMT
2800         S1:     x = memref      -               -
2801         S2:     z = x + 1       -               -
2802
2803      step 1: vectorize stmt S1 (done in vectorizable_load. See more details
2804              there):
2805                                 RELATED_STMT    VEC_STMT
2806         VS1_0:  vx0 = memref0   VS1_1           -
2807         VS1_1:  vx1 = memref1   VS1_2           -
2808         VS1_2:  vx2 = memref2   VS1_3           -
2809         VS1_3:  vx3 = memref3   -               -
2810         S1:     x = load        -               VS1_0
2811         S2:     z = x + 1       -               -
2812
2813      step2: vectorize stmt S2 (done here):
2814         To vectorize stmt S2 we first need to find the relevant vector
2815         def for the first operand 'x'.  This is, as usual, obtained from
2816         the vector stmt recorded in the STMT_VINFO_VEC_STMT of the stmt
2817         that defines 'x' (S1).  This way we find the stmt VS1_0, and the
2818         relevant vector def 'vx0'.  Having found 'vx0' we can generate
2819         the vector stmt VS2_0, and as usual, record it in the
2820         STMT_VINFO_VEC_STMT of stmt S2.
2821         When creating the second copy (VS2_1), we obtain the relevant vector
2822         def from the vector stmt recorded in the STMT_VINFO_RELATED_STMT of
2823         stmt VS1_0.  This way we find the stmt VS1_1 and the relevant
2824         vector def 'vx1'.  Using 'vx1' we create stmt VS2_1 and record a
2825         pointer to it in the STMT_VINFO_RELATED_STMT of the vector stmt VS2_0.
2826         Similarly when creating stmts VS2_2 and VS2_3.  This is the resulting
2827         chain of stmts and pointers:
2828                                 RELATED_STMT    VEC_STMT
2829         VS1_0:  vx0 = memref0   VS1_1           -
2830         VS1_1:  vx1 = memref1   VS1_2           -
2831         VS1_2:  vx2 = memref2   VS1_3           -
2832         VS1_3:  vx3 = memref3   -               -
2833         S1:     x = load        -               VS1_0
2834         VS2_0:  vz0 = vx0 + v1  VS2_1           -
2835         VS2_1:  vz1 = vx1 + v1  VS2_2           -
2836         VS2_2:  vz2 = vx2 + v1  VS2_3           -
2837         VS2_3:  vz3 = vx3 + v1  -               -
2838         S2:     z = x + 1       -               VS2_0  */
2839
2840   prev_stmt_info = NULL;
2841   for (j = 0; j < ncopies; j++)
2842     {
2843       /* Handle uses.  */
2844       if (j == 0)
2845         {
2846           if (op_type == binary_op || op_type == ternary_op)
2847             vect_get_vec_defs (op0, op1, stmt, &vec_oprnds0, &vec_oprnds1,
2848                                slp_node);
2849           else
2850             vect_get_vec_defs (op0, NULL_TREE, stmt, &vec_oprnds0, NULL,
2851                                slp_node);
2852           if (op_type == ternary_op)
2853             {
2854               vec_oprnds2 = VEC_alloc (tree, heap, 1);
2855               VEC_quick_push (tree, vec_oprnds2,
2856                               vect_get_vec_def_for_operand (op2, stmt, NULL));
2857             }
2858         }
2859       else
2860         {
2861           vect_get_vec_defs_for_stmt_copy (dt, &vec_oprnds0, &vec_oprnds1);
2862           if (op_type == ternary_op)
2863             {
2864               tree vec_oprnd = VEC_pop (tree, vec_oprnds2);
2865               VEC_quick_push (tree, vec_oprnds2,
2866                               vect_get_vec_def_for_stmt_copy (dt[2],
2867                                                               vec_oprnd));
2868             }
2869         }
2870
2871       /* Arguments are ready.  Create the new vector stmt.  */
2872       FOR_EACH_VEC_ELT (tree, vec_oprnds0, i, vop0)
2873         {
2874           vop1 = ((op_type == binary_op || op_type == ternary_op)
2875                   ? VEC_index (tree, vec_oprnds1, i) : NULL_TREE);
2876           vop2 = ((op_type == ternary_op)
2877                   ? VEC_index (tree, vec_oprnds2, i) : NULL_TREE);
2878           new_stmt = gimple_build_assign_with_ops3 (code, vec_dest,
2879                                                     vop0, vop1, vop2);
2880           new_temp = make_ssa_name (vec_dest, new_stmt);
2881           gimple_assign_set_lhs (new_stmt, new_temp);
2882           vect_finish_stmt_generation (stmt, new_stmt, gsi);
2883           if (slp_node)
2884             VEC_quick_push (gimple, SLP_TREE_VEC_STMTS (slp_node), new_stmt);
2885         }
2886
2887       if (slp_node)
2888         continue;
2889
2890       if (j == 0)
2891         STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
2892       else
2893         STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
2894       prev_stmt_info = vinfo_for_stmt (new_stmt);
2895     }
2896
2897   VEC_free (tree, heap, vec_oprnds0);
2898   if (vec_oprnds1)
2899     VEC_free (tree, heap, vec_oprnds1);
2900   if (vec_oprnds2)
2901     VEC_free (tree, heap, vec_oprnds2);
2902
2903   return true;
2904 }
2905
2906
2907 /* Get vectorized definitions for loop-based vectorization.  For the first
2908    operand we call vect_get_vec_def_for_operand() (with OPRND containing
2909    scalar operand), and for the rest we get a copy with
2910    vect_get_vec_def_for_stmt_copy() using the previous vector definition
2911    (stored in OPRND). See vect_get_vec_def_for_stmt_copy() for details.
2912    The vectors are collected into VEC_OPRNDS.  */
2913
2914 static void
2915 vect_get_loop_based_defs (tree *oprnd, gimple stmt, enum vect_def_type dt,
2916                           VEC (tree, heap) **vec_oprnds, int multi_step_cvt)
2917 {
2918   tree vec_oprnd;
2919
2920   /* Get first vector operand.  */
2921   /* All the vector operands except the very first one (that is scalar oprnd)
2922      are stmt copies.  */
2923   if (TREE_CODE (TREE_TYPE (*oprnd)) != VECTOR_TYPE)
2924     vec_oprnd = vect_get_vec_def_for_operand (*oprnd, stmt, NULL);
2925   else
2926     vec_oprnd = vect_get_vec_def_for_stmt_copy (dt, *oprnd);
2927
2928   VEC_quick_push (tree, *vec_oprnds, vec_oprnd);
2929
2930   /* Get second vector operand.  */
2931   vec_oprnd = vect_get_vec_def_for_stmt_copy (dt, vec_oprnd);
2932   VEC_quick_push (tree, *vec_oprnds, vec_oprnd);
2933
2934   *oprnd = vec_oprnd;
2935
2936   /* For conversion in multiple steps, continue to get operands
2937      recursively.  */
2938   if (multi_step_cvt)
2939     vect_get_loop_based_defs (oprnd, stmt, dt, vec_oprnds,  multi_step_cvt - 1);
2940 }
2941
2942
2943 /* Create vectorized demotion statements for vector operands from VEC_OPRNDS.
2944    For multi-step conversions store the resulting vectors and call the function
2945    recursively.  */
2946
2947 static void
2948 vect_create_vectorized_demotion_stmts (VEC (tree, heap) **vec_oprnds,
2949                                        int multi_step_cvt, gimple stmt,
2950                                        VEC (tree, heap) *vec_dsts,
2951                                        gimple_stmt_iterator *gsi,
2952                                        slp_tree slp_node, enum tree_code code,
2953                                        stmt_vec_info *prev_stmt_info)
2954 {
2955   unsigned int i;
2956   tree vop0, vop1, new_tmp, vec_dest;
2957   gimple new_stmt;
2958   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
2959
2960   vec_dest = VEC_pop (tree, vec_dsts);
2961
2962   for (i = 0; i < VEC_length (tree, *vec_oprnds); i += 2)
2963     {
2964       /* Create demotion operation.  */
2965       vop0 = VEC_index (tree, *vec_oprnds, i);
2966       vop1 = VEC_index (tree, *vec_oprnds, i + 1);
2967       new_stmt = gimple_build_assign_with_ops (code, vec_dest, vop0, vop1);
2968       new_tmp = make_ssa_name (vec_dest, new_stmt);
2969       gimple_assign_set_lhs (new_stmt, new_tmp);
2970       vect_finish_stmt_generation (stmt, new_stmt, gsi);
2971
2972       if (multi_step_cvt)
2973         /* Store the resulting vector for next recursive call.  */
2974         VEC_replace (tree, *vec_oprnds, i/2, new_tmp);
2975       else
2976         {
2977           /* This is the last step of the conversion sequence. Store the
2978              vectors in SLP_NODE or in vector info of the scalar statement
2979              (or in STMT_VINFO_RELATED_STMT chain).  */
2980           if (slp_node)
2981             VEC_quick_push (gimple, SLP_TREE_VEC_STMTS (slp_node), new_stmt);
2982           else
2983             {
2984               if (!*prev_stmt_info)
2985                 STMT_VINFO_VEC_STMT (stmt_info) = new_stmt;
2986               else
2987                 STMT_VINFO_RELATED_STMT (*prev_stmt_info) = new_stmt;
2988
2989               *prev_stmt_info = vinfo_for_stmt (new_stmt);
2990             }
2991         }
2992     }
2993
2994   /* For multi-step demotion operations we first generate demotion operations
2995      from the source type to the intermediate types, and then combine the
2996      results (stored in VEC_OPRNDS) in demotion operation to the destination
2997      type.  */
2998   if (multi_step_cvt)
2999     {
3000       /* At each level of recursion we have have of the operands we had at the
3001          previous level.  */
3002       VEC_truncate (tree, *vec_oprnds, (i+1)/2);
3003       vect_create_vectorized_demotion_stmts (vec_oprnds, multi_step_cvt - 1,
3004                                              stmt, vec_dsts, gsi, slp_node,
3005                                              code, prev_stmt_info);
3006     }
3007 }
3008
3009
3010 /* Function vectorizable_type_demotion
3011
3012    Check if STMT performs a binary or unary operation that involves
3013    type demotion, and if it can be vectorized.
3014    If VEC_STMT is also passed, vectorize the STMT: create a vectorized
3015    stmt to replace it, put it in VEC_STMT, and insert it at BSI.
3016    Return FALSE if not a vectorizable STMT, TRUE otherwise.  */
3017
3018 static bool
3019 vectorizable_type_demotion (gimple stmt, gimple_stmt_iterator *gsi,
3020                             gimple *vec_stmt, slp_tree slp_node)
3021 {
3022   tree vec_dest;
3023   tree scalar_dest;
3024   tree op0;
3025   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
3026   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
3027   enum tree_code code, code1 = ERROR_MARK;
3028   tree def;
3029   gimple def_stmt;
3030   enum vect_def_type dt[2] = {vect_unknown_def_type, vect_unknown_def_type};
3031   stmt_vec_info prev_stmt_info;
3032   int nunits_in;
3033   int nunits_out;
3034   tree vectype_out;
3035   int ncopies;
3036   int j, i;
3037   tree vectype_in;
3038   int multi_step_cvt = 0;
3039   VEC (tree, heap) *vec_oprnds0 = NULL;
3040   VEC (tree, heap) *vec_dsts = NULL, *interm_types = NULL, *tmp_vec_dsts = NULL;
3041   tree last_oprnd, intermediate_type;
3042   bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
3043
3044   if (!STMT_VINFO_RELEVANT_P (stmt_info) && !bb_vinfo)
3045     return false;
3046
3047   if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def)
3048     return false;
3049
3050   /* Is STMT a vectorizable type-demotion operation?  */
3051   if (!is_gimple_assign (stmt))
3052     return false;
3053
3054   if (TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME)
3055     return false;
3056
3057   code = gimple_assign_rhs_code (stmt);
3058   if (!CONVERT_EXPR_CODE_P (code))
3059     return false;
3060
3061   scalar_dest = gimple_assign_lhs (stmt);
3062   vectype_out = STMT_VINFO_VECTYPE (stmt_info);
3063
3064   /* Check the operands of the operation.  */
3065   op0 = gimple_assign_rhs1 (stmt);
3066   if (! ((INTEGRAL_TYPE_P (TREE_TYPE (scalar_dest))
3067           && INTEGRAL_TYPE_P (TREE_TYPE (op0)))
3068          || (SCALAR_FLOAT_TYPE_P (TREE_TYPE (scalar_dest))
3069              && SCALAR_FLOAT_TYPE_P (TREE_TYPE (op0))
3070              && CONVERT_EXPR_CODE_P (code))))
3071     return false;
3072   if (!vect_is_simple_use_1 (op0, loop_vinfo, bb_vinfo,
3073                              &def_stmt, &def, &dt[0], &vectype_in))
3074     {
3075       if (vect_print_dump_info (REPORT_DETAILS))
3076         fprintf (vect_dump, "use not simple.");
3077       return false;
3078     }
3079   /* If op0 is an external def use a vector type with the
3080      same size as the output vector type if possible.  */
3081   if (!vectype_in)
3082     vectype_in = get_same_sized_vectype (TREE_TYPE (op0), vectype_out);
3083   if (vec_stmt)
3084     gcc_assert (vectype_in);
3085   if (!vectype_in)
3086     {
3087       if (vect_print_dump_info (REPORT_DETAILS))
3088         {
3089           fprintf (vect_dump, "no vectype for scalar type ");
3090           print_generic_expr (vect_dump, TREE_TYPE (op0), TDF_SLIM);
3091         }
3092
3093       return false;
3094     }
3095
3096   nunits_in = TYPE_VECTOR_SUBPARTS (vectype_in);
3097   nunits_out = TYPE_VECTOR_SUBPARTS (vectype_out);
3098   if (nunits_in >= nunits_out)
3099     return false;
3100
3101   /* Multiple types in SLP are handled by creating the appropriate number of
3102      vectorized stmts for each SLP node.  Hence, NCOPIES is always 1 in
3103      case of SLP.  */
3104   if (slp_node || PURE_SLP_STMT (stmt_info))
3105     ncopies = 1;
3106   else
3107     ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits_out;
3108   gcc_assert (ncopies >= 1);
3109
3110   /* Supportable by target?  */
3111   if (!supportable_narrowing_operation (code, vectype_out, vectype_in,
3112                                         &code1, &multi_step_cvt, &interm_types))
3113     return false;
3114
3115   if (!vec_stmt) /* transformation not required.  */
3116     {
3117       STMT_VINFO_TYPE (stmt_info) = type_demotion_vec_info_type;
3118       if (vect_print_dump_info (REPORT_DETAILS))
3119         fprintf (vect_dump, "=== vectorizable_demotion ===");
3120       vect_model_simple_cost (stmt_info, ncopies, dt, NULL);
3121       return true;
3122     }
3123
3124   /** Transform.  **/
3125   if (vect_print_dump_info (REPORT_DETAILS))
3126     fprintf (vect_dump, "transform type demotion operation. ncopies = %d.",
3127              ncopies);
3128
3129   /* In case of multi-step demotion, we first generate demotion operations to
3130      the intermediate types, and then from that types to the final one.
3131      We create vector destinations for the intermediate type (TYPES) received
3132      from supportable_narrowing_operation, and store them in the correct order
3133      for future use in vect_create_vectorized_demotion_stmts().  */
3134   if (multi_step_cvt)
3135     vec_dsts = VEC_alloc (tree, heap, multi_step_cvt + 1);
3136   else
3137     vec_dsts = VEC_alloc (tree, heap, 1);
3138
3139   vec_dest = vect_create_destination_var (scalar_dest, vectype_out);
3140   VEC_quick_push (tree, vec_dsts, vec_dest);
3141
3142   if (multi_step_cvt)
3143     {
3144       for (i = VEC_length (tree, interm_types) - 1;
3145            VEC_iterate (tree, interm_types, i, intermediate_type); i--)
3146         {
3147           vec_dest = vect_create_destination_var (scalar_dest,
3148                                                   intermediate_type);
3149           VEC_quick_push (tree, vec_dsts, vec_dest);
3150         }
3151     }
3152
3153   /* In case the vectorization factor (VF) is bigger than the number
3154      of elements that we can fit in a vectype (nunits), we have to generate
3155      more than one vector stmt - i.e - we need to "unroll" the
3156      vector stmt by a factor VF/nunits.   */
3157   last_oprnd = op0;
3158   prev_stmt_info = NULL;
3159   for (j = 0; j < ncopies; j++)
3160     {
3161       /* Handle uses.  */
3162       if (slp_node)
3163         vect_get_slp_defs (op0, NULL_TREE, slp_node, &vec_oprnds0, NULL, -1);
3164       else
3165         {
3166           VEC_free (tree, heap, vec_oprnds0);
3167           vec_oprnds0 = VEC_alloc (tree, heap,
3168                         (multi_step_cvt ? vect_pow2 (multi_step_cvt) * 2 : 2));
3169           vect_get_loop_based_defs (&last_oprnd, stmt, dt[0], &vec_oprnds0,
3170                                     vect_pow2 (multi_step_cvt) - 1);
3171         }
3172
3173       /* Arguments are ready.  Create the new vector stmts.  */
3174       tmp_vec_dsts = VEC_copy (tree, heap, vec_dsts);
3175       vect_create_vectorized_demotion_stmts (&vec_oprnds0,
3176                                              multi_step_cvt, stmt, tmp_vec_dsts,
3177                                              gsi, slp_node, code1,
3178                                              &prev_stmt_info);
3179     }
3180
3181   VEC_free (tree, heap, vec_oprnds0);
3182   VEC_free (tree, heap, vec_dsts);
3183   VEC_free (tree, heap, tmp_vec_dsts);
3184   VEC_free (tree, heap, interm_types);
3185
3186   *vec_stmt = STMT_VINFO_VEC_STMT (stmt_info);
3187   return true;
3188 }
3189
3190
3191 /* Create vectorized promotion statements for vector operands from VEC_OPRNDS0
3192    and VEC_OPRNDS1 (for binary operations).  For multi-step conversions store
3193    the resulting vectors and call the function recursively.  */
3194
3195 static void
3196 vect_create_vectorized_promotion_stmts (VEC (tree, heap) **vec_oprnds0,
3197                                         VEC (tree, heap) **vec_oprnds1,
3198                                         int multi_step_cvt, gimple stmt,
3199                                         VEC (tree, heap) *vec_dsts,
3200                                         gimple_stmt_iterator *gsi,
3201                                         slp_tree slp_node, enum tree_code code1,
3202                                         enum tree_code code2, tree decl1,
3203                                         tree decl2, int op_type,
3204                                         stmt_vec_info *prev_stmt_info)
3205 {
3206   int i;
3207   tree vop0, vop1, new_tmp1, new_tmp2, vec_dest;
3208   gimple new_stmt1, new_stmt2;
3209   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
3210   VEC (tree, heap) *vec_tmp;
3211
3212   vec_dest = VEC_pop (tree, vec_dsts);
3213   vec_tmp = VEC_alloc (tree, heap, VEC_length (tree, *vec_oprnds0) * 2);
3214
3215   FOR_EACH_VEC_ELT (tree, *vec_oprnds0, i, vop0)
3216     {
3217       if (op_type == binary_op)
3218         vop1 = VEC_index (tree, *vec_oprnds1, i);
3219       else
3220         vop1 = NULL_TREE;
3221
3222       /* Generate the two halves of promotion operation.  */
3223       new_stmt1 = vect_gen_widened_results_half (code1, decl1, vop0, vop1,
3224                                                  op_type, vec_dest, gsi, stmt);
3225       new_stmt2 = vect_gen_widened_results_half (code2, decl2, vop0, vop1,
3226                                                  op_type, vec_dest, gsi, stmt);
3227       if (is_gimple_call (new_stmt1))
3228         {
3229           new_tmp1 = gimple_call_lhs (new_stmt1);
3230           new_tmp2 = gimple_call_lhs (new_stmt2);
3231         }
3232       else
3233         {
3234           new_tmp1 = gimple_assign_lhs (new_stmt1);
3235           new_tmp2 = gimple_assign_lhs (new_stmt2);
3236         }
3237
3238       if (multi_step_cvt)
3239         {
3240           /* Store the results for the recursive call.  */
3241           VEC_quick_push (tree, vec_tmp, new_tmp1);
3242           VEC_quick_push (tree, vec_tmp, new_tmp2);
3243         }
3244       else
3245         {
3246           /* Last step of promotion sequience - store the results.  */
3247           if (slp_node)
3248             {
3249               VEC_quick_push (gimple, SLP_TREE_VEC_STMTS (slp_node), new_stmt1);
3250               VEC_quick_push (gimple, SLP_TREE_VEC_STMTS (slp_node), new_stmt2);
3251             }
3252           else
3253             {
3254               if (!*prev_stmt_info)
3255                 STMT_VINFO_VEC_STMT (stmt_info) = new_stmt1;
3256               else
3257                 STMT_VINFO_RELATED_STMT (*prev_stmt_info) = new_stmt1;
3258
3259               *prev_stmt_info = vinfo_for_stmt (new_stmt1);
3260               STMT_VINFO_RELATED_STMT (*prev_stmt_info) = new_stmt2;
3261               *prev_stmt_info = vinfo_for_stmt (new_stmt2);
3262             }
3263         }
3264     }
3265
3266   if (multi_step_cvt)
3267     {
3268       /* For multi-step promotion operation we first generate we call the
3269          function recurcively for every stage.  We start from the input type,
3270          create promotion operations to the intermediate types, and then
3271          create promotions to the output type.  */
3272       *vec_oprnds0 = VEC_copy (tree, heap, vec_tmp);
3273       vect_create_vectorized_promotion_stmts (vec_oprnds0, vec_oprnds1,
3274                                               multi_step_cvt - 1, stmt,
3275                                               vec_dsts, gsi, slp_node, code1,
3276                                               code2, decl2, decl2, op_type,
3277                                               prev_stmt_info);
3278     }
3279
3280   VEC_free (tree, heap, vec_tmp);
3281 }
3282
3283
3284 /* Function vectorizable_type_promotion
3285
3286    Check if STMT performs a binary or unary operation that involves
3287    type promotion, and if it can be vectorized.
3288    If VEC_STMT is also passed, vectorize the STMT: create a vectorized
3289    stmt to replace it, put it in VEC_STMT, and insert it at BSI.
3290    Return FALSE if not a vectorizable STMT, TRUE otherwise.  */
3291
3292 static bool
3293 vectorizable_type_promotion (gimple stmt, gimple_stmt_iterator *gsi,
3294                              gimple *vec_stmt, slp_tree slp_node)
3295 {
3296   tree vec_dest;
3297   tree scalar_dest;
3298   tree op0, op1 = NULL;
3299   tree vec_oprnd0=NULL, vec_oprnd1=NULL;
3300   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
3301   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
3302   enum tree_code code, code1 = ERROR_MARK, code2 = ERROR_MARK;
3303   tree decl1 = NULL_TREE, decl2 = NULL_TREE;
3304   int op_type;
3305   tree def;
3306   gimple def_stmt;
3307   enum vect_def_type dt[2] = {vect_unknown_def_type, vect_unknown_def_type};
3308   stmt_vec_info prev_stmt_info;
3309   int nunits_in;
3310   int nunits_out;
3311   tree vectype_out;
3312   int ncopies;
3313   int j, i;
3314   tree vectype_in;
3315   tree intermediate_type = NULL_TREE;
3316   int multi_step_cvt = 0;
3317   VEC (tree, heap) *vec_oprnds0 = NULL, *vec_oprnds1 = NULL;
3318   VEC (tree, heap) *vec_dsts = NULL, *interm_types = NULL, *tmp_vec_dsts = NULL;
3319   bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
3320
3321   if (!STMT_VINFO_RELEVANT_P (stmt_info) && !bb_vinfo)
3322     return false;
3323
3324   if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def)
3325     return false;
3326
3327   /* Is STMT a vectorizable type-promotion operation?  */
3328   if (!is_gimple_assign (stmt))
3329     return false;
3330
3331   if (TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME)
3332     return false;
3333
3334   code = gimple_assign_rhs_code (stmt);
3335   if (!CONVERT_EXPR_CODE_P (code)
3336       && code != WIDEN_MULT_EXPR)
3337     return false;
3338
3339   scalar_dest = gimple_assign_lhs (stmt);
3340   vectype_out = STMT_VINFO_VECTYPE (stmt_info);
3341
3342   /* Check the operands of the operation.  */
3343   op0 = gimple_assign_rhs1 (stmt);
3344   if (! ((INTEGRAL_TYPE_P (TREE_TYPE (scalar_dest))
3345           && INTEGRAL_TYPE_P (TREE_TYPE (op0)))
3346          || (SCALAR_FLOAT_TYPE_P (TREE_TYPE (scalar_dest))
3347              && SCALAR_FLOAT_TYPE_P (TREE_TYPE (op0))
3348              && CONVERT_EXPR_CODE_P (code))))
3349     return false;
3350   if (!vect_is_simple_use_1 (op0, loop_vinfo, bb_vinfo,
3351                              &def_stmt, &def, &dt[0], &vectype_in))
3352     {
3353       if (vect_print_dump_info (REPORT_DETAILS))
3354         fprintf (vect_dump, "use not simple.");
3355       return false;
3356     }
3357
3358   op_type = TREE_CODE_LENGTH (code);
3359   if (op_type == binary_op)
3360     {
3361       bool ok;
3362
3363       op1 = gimple_assign_rhs2 (stmt);
3364       if (code == WIDEN_MULT_EXPR)
3365         {
3366           /* For WIDEN_MULT_EXPR, if OP0 is a constant, use the type of
3367              OP1.  */
3368           if (CONSTANT_CLASS_P (op0))
3369             ok = vect_is_simple_use_1 (op1, loop_vinfo, NULL,
3370                              &def_stmt, &def, &dt[1], &vectype_in);
3371           else
3372             ok = vect_is_simple_use (op1, loop_vinfo, NULL, &def_stmt, &def,
3373                                      &dt[1]);
3374
3375           if (!ok)
3376             {
3377               if (vect_print_dump_info (REPORT_DETAILS))
3378                 fprintf (vect_dump, "use not simple.");
3379               return false;
3380             }
3381         }        
3382     }
3383
3384   /* If op0 is an external or constant def use a vector type with
3385      the same size as the output vector type.  */
3386   if (!vectype_in)
3387     vectype_in = get_same_sized_vectype (TREE_TYPE (op0), vectype_out);
3388   if (vec_stmt)
3389     gcc_assert (vectype_in);
3390   if (!vectype_in)
3391     {
3392       if (vect_print_dump_info (REPORT_DETAILS))
3393         {
3394           fprintf (vect_dump, "no vectype for scalar type ");
3395           print_generic_expr (vect_dump, TREE_TYPE (op0), TDF_SLIM);
3396         }
3397
3398       return false;
3399     }
3400
3401   nunits_in = TYPE_VECTOR_SUBPARTS (vectype_in);
3402   nunits_out = TYPE_VECTOR_SUBPARTS (vectype_out);
3403   if (nunits_in <= nunits_out)
3404     return false;
3405
3406   /* Multiple types in SLP are handled by creating the appropriate number of
3407      vectorized stmts for each SLP node.  Hence, NCOPIES is always 1 in
3408      case of SLP.  */
3409   if (slp_node || PURE_SLP_STMT (stmt_info))
3410     ncopies = 1;
3411   else
3412     ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits_in;
3413
3414   gcc_assert (ncopies >= 1);
3415
3416   /* Supportable by target?  */
3417   if (!supportable_widening_operation (code, stmt, vectype_out, vectype_in,
3418                                        &decl1, &decl2, &code1, &code2,
3419                                        &multi_step_cvt, &interm_types))
3420     return false;
3421
3422   /* Binary widening operation can only be supported directly by the
3423      architecture.  */
3424   gcc_assert (!(multi_step_cvt && op_type == binary_op));
3425
3426   if (!vec_stmt) /* transformation not required.  */
3427     {
3428       STMT_VINFO_TYPE (stmt_info) = type_promotion_vec_info_type;
3429       if (vect_print_dump_info (REPORT_DETAILS))
3430         fprintf (vect_dump, "=== vectorizable_promotion ===");
3431       vect_model_simple_cost (stmt_info, 2*ncopies, dt, NULL);
3432       return true;
3433     }
3434
3435   /** Transform.  **/
3436
3437   if (vect_print_dump_info (REPORT_DETAILS))
3438     fprintf (vect_dump, "transform type promotion operation. ncopies = %d.",
3439                         ncopies);
3440
3441   if (code == WIDEN_MULT_EXPR)
3442     {
3443       if (CONSTANT_CLASS_P (op0))
3444         op0 = fold_convert (TREE_TYPE (op1), op0);
3445       else if (CONSTANT_CLASS_P (op1))
3446         op1 = fold_convert (TREE_TYPE (op0), op1);
3447     }
3448
3449   /* Handle def.  */
3450   /* In case of multi-step promotion, we first generate promotion operations
3451      to the intermediate types, and then from that types to the final one.
3452      We store vector destination in VEC_DSTS in the correct order for
3453      recursive creation of promotion operations in
3454      vect_create_vectorized_promotion_stmts(). Vector destinations are created
3455      according to TYPES recieved from supportable_widening_operation().   */
3456   if (multi_step_cvt)
3457     vec_dsts = VEC_alloc (tree, heap, multi_step_cvt + 1);
3458   else
3459     vec_dsts = VEC_alloc (tree, heap, 1);
3460
3461   vec_dest = vect_create_destination_var (scalar_dest, vectype_out);
3462   VEC_quick_push (tree, vec_dsts, vec_dest);
3463
3464   if (multi_step_cvt)
3465     {
3466       for (i = VEC_length (tree, interm_types) - 1;
3467            VEC_iterate (tree, interm_types, i, intermediate_type); i--)
3468         {
3469           vec_dest = vect_create_destination_var (scalar_dest,
3470                                                   intermediate_type);
3471           VEC_quick_push (tree, vec_dsts, vec_dest);
3472         }
3473     }
3474
3475   if (!slp_node)
3476     {
3477       vec_oprnds0 = VEC_alloc (tree, heap,
3478                             (multi_step_cvt ? vect_pow2 (multi_step_cvt) : 1));
3479       if (op_type == binary_op)
3480         vec_oprnds1 = VEC_alloc (tree, heap, 1);
3481     }
3482
3483   /* In case the vectorization factor (VF) is bigger than the number
3484      of elements that we can fit in a vectype (nunits), we have to generate
3485      more than one vector stmt - i.e - we need to "unroll" the
3486      vector stmt by a factor VF/nunits.   */
3487
3488   prev_stmt_info = NULL;
3489   for (j = 0; j < ncopies; j++)
3490     {
3491       /* Handle uses.  */
3492       if (j == 0)
3493         {
3494           if (slp_node)
3495               vect_get_slp_defs (op0, op1, slp_node, &vec_oprnds0,
3496                                  &vec_oprnds1, -1);
3497           else
3498             {
3499               vec_oprnd0 = vect_get_vec_def_for_operand (op0, stmt, NULL);
3500               VEC_quick_push (tree, vec_oprnds0, vec_oprnd0);
3501               if (op_type == binary_op)
3502                 {
3503                   vec_oprnd1 = vect_get_vec_def_for_operand (op1, stmt, NULL);
3504                   VEC_quick_push (tree, vec_oprnds1, vec_oprnd1);
3505                 }
3506             }
3507         }
3508       else
3509         {
3510           vec_oprnd0 = vect_get_vec_def_for_stmt_copy (dt[0], vec_oprnd0);
3511           VEC_replace (tree, vec_oprnds0, 0, vec_oprnd0);
3512           if (op_type == binary_op)
3513             {
3514               vec_oprnd1 = vect_get_vec_def_for_stmt_copy (dt[1], vec_oprnd1);
3515               VEC_replace (tree, vec_oprnds1, 0, vec_oprnd1);
3516             }
3517         }
3518
3519       /* Arguments are ready.  Create the new vector stmts.  */
3520       tmp_vec_dsts = VEC_copy (tree, heap, vec_dsts);
3521       vect_create_vectorized_promotion_stmts (&vec_oprnds0, &vec_oprnds1,
3522                                               multi_step_cvt, stmt,
3523                                               tmp_vec_dsts,
3524                                               gsi, slp_node, code1, code2,
3525                                               decl1, decl2, op_type,
3526                                               &prev_stmt_info);
3527     }
3528
3529   VEC_free (tree, heap, vec_dsts);
3530   VEC_free (tree, heap, tmp_vec_dsts);
3531   VEC_free (tree, heap, interm_types);
3532   VEC_free (tree, heap, vec_oprnds0);
3533   VEC_free (tree, heap, vec_oprnds1);
3534
3535   *vec_stmt = STMT_VINFO_VEC_STMT (stmt_info);
3536   return true;
3537 }
3538
3539
3540 /* Function vectorizable_store.
3541
3542    Check if STMT defines a non scalar data-ref (array/pointer/structure) that
3543    can be vectorized.
3544    If VEC_STMT is also passed, vectorize the STMT: create a vectorized
3545    stmt to replace it, put it in VEC_STMT, and insert it at BSI.
3546    Return FALSE if not a vectorizable STMT, TRUE otherwise.  */
3547
3548 static bool
3549 vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
3550                     slp_tree slp_node)
3551 {
3552   tree scalar_dest;
3553   tree data_ref;
3554   tree op;
3555   tree vec_oprnd = NULL_TREE;
3556   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
3557   struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info), *first_dr = NULL;
3558   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
3559   tree elem_type;
3560   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
3561   struct loop *loop = NULL;
3562   enum machine_mode vec_mode;
3563   tree dummy;
3564   enum dr_alignment_support alignment_support_scheme;
3565   tree def;
3566   gimple def_stmt;
3567   enum vect_def_type dt;
3568   stmt_vec_info prev_stmt_info = NULL;
3569   tree dataref_ptr = NULL_TREE;
3570   int nunits = TYPE_VECTOR_SUBPARTS (vectype);
3571   int ncopies;
3572   int j;
3573   gimple next_stmt, first_stmt = NULL;
3574   bool strided_store = false;
3575   bool store_lanes_p = false;
3576   unsigned int group_size, i;
3577   VEC(tree,heap) *dr_chain = NULL, *oprnds = NULL, *result_chain = NULL;
3578   bool inv_p;
3579   VEC(tree,heap) *vec_oprnds = NULL;
3580   bool slp = (slp_node != NULL);
3581   unsigned int vec_num;
3582   bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
3583   tree aggr_type;
3584
3585   if (loop_vinfo)
3586     loop = LOOP_VINFO_LOOP (loop_vinfo);
3587
3588   /* Multiple types in SLP are handled by creating the appropriate number of
3589      vectorized stmts for each SLP node. Hence, NCOPIES is always 1 in
3590      case of SLP.  */
3591   if (slp || PURE_SLP_STMT (stmt_info))
3592     ncopies = 1;
3593   else
3594     ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits;
3595
3596   gcc_assert (ncopies >= 1);
3597
3598   /* FORNOW. This restriction should be relaxed.  */
3599   if (loop && nested_in_vect_loop_p (loop, stmt) && ncopies > 1)
3600     {
3601       if (vect_print_dump_info (REPORT_DETAILS))
3602         fprintf (vect_dump, "multiple types in nested loop.");
3603       return false;
3604     }
3605
3606   if (!STMT_VINFO_RELEVANT_P (stmt_info) && !bb_vinfo)
3607     return false;
3608
3609   if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def)
3610     return false;
3611
3612   /* Is vectorizable store? */
3613
3614   if (!is_gimple_assign (stmt))
3615     return false;
3616
3617   scalar_dest = gimple_assign_lhs (stmt);
3618   if (TREE_CODE (scalar_dest) != ARRAY_REF
3619       && TREE_CODE (scalar_dest) != INDIRECT_REF
3620       && TREE_CODE (scalar_dest) != COMPONENT_REF
3621       && TREE_CODE (scalar_dest) != IMAGPART_EXPR
3622       && TREE_CODE (scalar_dest) != REALPART_EXPR
3623       && TREE_CODE (scalar_dest) != MEM_REF)
3624     return false;
3625
3626   gcc_assert (gimple_assign_single_p (stmt));
3627   op = gimple_assign_rhs1 (stmt);
3628   if (!vect_is_simple_use (op, loop_vinfo, bb_vinfo, &def_stmt, &def, &dt))
3629     {
3630       if (vect_print_dump_info (REPORT_DETAILS))
3631         fprintf (vect_dump, "use not simple.");
3632       return false;
3633     }
3634
3635   /* The scalar rhs type needs to be trivially convertible to the vector
3636      component type.  This should always be the case.  */
3637   elem_type = TREE_TYPE (vectype);
3638   if (!useless_type_conversion_p (elem_type, TREE_TYPE (op)))
3639     {
3640       if (vect_print_dump_info (REPORT_DETAILS))
3641         fprintf (vect_dump, "???  operands of different types");
3642       return false;
3643     }
3644
3645   vec_mode = TYPE_MODE (vectype);
3646   /* FORNOW. In some cases can vectorize even if data-type not supported
3647      (e.g. - array initialization with 0).  */
3648   if (optab_handler (mov_optab, vec_mode) == CODE_FOR_nothing)
3649     return false;
3650
3651   if (!STMT_VINFO_DATA_REF (stmt_info))
3652     return false;
3653
3654   if (tree_int_cst_compare (DR_STEP (dr), size_zero_node) < 0)
3655     {
3656       if (vect_print_dump_info (REPORT_DETAILS))
3657         fprintf (vect_dump, "negative step for store.");
3658       return false;
3659     }
3660
3661   if (STMT_VINFO_STRIDED_ACCESS (stmt_info))
3662     {
3663       strided_store = true;
3664       first_stmt = GROUP_FIRST_ELEMENT (stmt_info);
3665       if (!slp && !PURE_SLP_STMT (stmt_info))
3666         {
3667           group_size = GROUP_SIZE (vinfo_for_stmt (first_stmt));
3668           if (vect_store_lanes_supported (vectype, group_size))
3669             store_lanes_p = true;
3670           else if (!vect_strided_store_supported (vectype, group_size))
3671             return false;
3672         }
3673
3674       if (first_stmt == stmt)
3675         {
3676           /* STMT is the leader of the group. Check the operands of all the
3677              stmts of the group.  */
3678           next_stmt = GROUP_NEXT_ELEMENT (stmt_info);
3679           while (next_stmt)
3680             {
3681               gcc_assert (gimple_assign_single_p (next_stmt));
3682               op = gimple_assign_rhs1 (next_stmt);
3683               if (!vect_is_simple_use (op, loop_vinfo, bb_vinfo, &def_stmt,
3684                                        &def, &dt))
3685                 {
3686                   if (vect_print_dump_info (REPORT_DETAILS))
3687                     fprintf (vect_dump, "use not simple.");
3688                   return false;
3689                 }
3690               next_stmt = GROUP_NEXT_ELEMENT (vinfo_for_stmt (next_stmt));
3691             }
3692         }
3693     }
3694
3695   if (!vec_stmt) /* transformation not required.  */
3696     {
3697       STMT_VINFO_TYPE (stmt_info) = store_vec_info_type;
3698       vect_model_store_cost (stmt_info, ncopies, store_lanes_p, dt, NULL);
3699       return true;
3700     }
3701
3702   /** Transform.  **/
3703
3704   if (strided_store)
3705     {
3706       first_dr = STMT_VINFO_DATA_REF (vinfo_for_stmt (first_stmt));
3707       group_size = GROUP_SIZE (vinfo_for_stmt (first_stmt));
3708
3709       GROUP_STORE_COUNT (vinfo_for_stmt (first_stmt))++;
3710
3711       /* FORNOW */
3712       gcc_assert (!loop || !nested_in_vect_loop_p (loop, stmt));
3713
3714       /* We vectorize all the stmts of the interleaving group when we
3715          reach the last stmt in the group.  */
3716       if (GROUP_STORE_COUNT (vinfo_for_stmt (first_stmt))
3717           < GROUP_SIZE (vinfo_for_stmt (first_stmt))
3718           && !slp)
3719         {
3720           *vec_stmt = NULL;
3721           return true;
3722         }
3723
3724       if (slp)
3725         {
3726           strided_store = false;
3727           /* VEC_NUM is the number of vect stmts to be created for this 
3728              group.  */
3729           vec_num = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node);
3730           first_stmt = VEC_index (gimple, SLP_TREE_SCALAR_STMTS (slp_node), 0); 
3731           first_dr = STMT_VINFO_DATA_REF (vinfo_for_stmt (first_stmt));
3732         } 
3733       else
3734         /* VEC_NUM is the number of vect stmts to be created for this 
3735            group.  */
3736         vec_num = group_size;
3737     }
3738   else
3739     {
3740       first_stmt = stmt;
3741       first_dr = dr;
3742       group_size = vec_num = 1;
3743     }
3744
3745   if (vect_print_dump_info (REPORT_DETAILS))
3746     fprintf (vect_dump, "transform store. ncopies = %d",ncopies);
3747
3748   dr_chain = VEC_alloc (tree, heap, group_size);
3749   oprnds = VEC_alloc (tree, heap, group_size);
3750
3751   alignment_support_scheme = vect_supportable_dr_alignment (first_dr, false);
3752   gcc_assert (alignment_support_scheme);
3753   /* Targets with store-lane instructions must not require explicit
3754      realignment.  */
3755   gcc_assert (!store_lanes_p
3756               || alignment_support_scheme == dr_aligned
3757               || alignment_support_scheme == dr_unaligned_supported);
3758
3759   if (store_lanes_p)
3760     aggr_type = build_array_type_nelts (elem_type, vec_num * nunits);
3761   else
3762     aggr_type = vectype;
3763
3764   /* In case the vectorization factor (VF) is bigger than the number
3765      of elements that we can fit in a vectype (nunits), we have to generate
3766      more than one vector stmt - i.e - we need to "unroll" the
3767      vector stmt by a factor VF/nunits.  For more details see documentation in
3768      vect_get_vec_def_for_copy_stmt.  */
3769
3770   /* In case of interleaving (non-unit strided access):
3771
3772         S1:  &base + 2 = x2
3773         S2:  &base = x0
3774         S3:  &base + 1 = x1
3775         S4:  &base + 3 = x3
3776
3777      We create vectorized stores starting from base address (the access of the
3778      first stmt in the chain (S2 in the above example), when the last store stmt
3779      of the chain (S4) is reached:
3780
3781         VS1: &base = vx2
3782         VS2: &base + vec_size*1 = vx0
3783         VS3: &base + vec_size*2 = vx1
3784         VS4: &base + vec_size*3 = vx3
3785
3786      Then permutation statements are generated:
3787
3788         VS5: vx5 = VEC_INTERLEAVE_HIGH_EXPR < vx0, vx3 >
3789         VS6: vx6 = VEC_INTERLEAVE_LOW_EXPR < vx0, vx3 >
3790         ...
3791
3792      And they are put in STMT_VINFO_VEC_STMT of the corresponding scalar stmts
3793      (the order of the data-refs in the output of vect_permute_store_chain
3794      corresponds to the order of scalar stmts in the interleaving chain - see
3795      the documentation of vect_permute_store_chain()).
3796
3797      In case of both multiple types and interleaving, above vector stores and
3798      permutation stmts are created for every copy.  The result vector stmts are
3799      put in STMT_VINFO_VEC_STMT for the first copy and in the corresponding
3800      STMT_VINFO_RELATED_STMT for the next copies.
3801   */
3802
3803   prev_stmt_info = NULL;
3804   for (j = 0; j < ncopies; j++)
3805     {
3806       gimple new_stmt;
3807       gimple ptr_incr;
3808
3809       if (j == 0)
3810         {
3811           if (slp)
3812             {
3813               /* Get vectorized arguments for SLP_NODE.  */
3814               vect_get_slp_defs (NULL_TREE, NULL_TREE, slp_node, &vec_oprnds,
3815                                  NULL, -1);
3816
3817               vec_oprnd = VEC_index (tree, vec_oprnds, 0);
3818             }
3819           else
3820             {
3821               /* For interleaved stores we collect vectorized defs for all the
3822                  stores in the group in DR_CHAIN and OPRNDS. DR_CHAIN is then
3823                  used as an input to vect_permute_store_chain(), and OPRNDS as
3824                  an input to vect_get_vec_def_for_stmt_copy() for the next copy.
3825
3826                  If the store is not strided, GROUP_SIZE is 1, and DR_CHAIN and
3827                  OPRNDS are of size 1.  */
3828               next_stmt = first_stmt;
3829               for (i = 0; i < group_size; i++)
3830                 {
3831                   /* Since gaps are not supported for interleaved stores,
3832                      GROUP_SIZE is the exact number of stmts in the chain.
3833                      Therefore, NEXT_STMT can't be NULL_TREE.  In case that
3834                      there is no interleaving, GROUP_SIZE is 1, and only one
3835                      iteration of the loop will be executed.  */
3836                   gcc_assert (next_stmt
3837                               && gimple_assign_single_p (next_stmt));
3838                   op = gimple_assign_rhs1 (next_stmt);
3839
3840                   vec_oprnd = vect_get_vec_def_for_operand (op, next_stmt,
3841                                                             NULL);
3842                   VEC_quick_push(tree, dr_chain, vec_oprnd);
3843                   VEC_quick_push(tree, oprnds, vec_oprnd);
3844                   next_stmt = GROUP_NEXT_ELEMENT (vinfo_for_stmt (next_stmt));
3845                 }
3846             }
3847
3848           /* We should have catched mismatched types earlier.  */
3849           gcc_assert (useless_type_conversion_p (vectype,
3850                                                  TREE_TYPE (vec_oprnd)));
3851           dataref_ptr = vect_create_data_ref_ptr (first_stmt, aggr_type, NULL,
3852                                                   NULL_TREE, &dummy, gsi,
3853                                                   &ptr_incr, false, &inv_p);
3854           gcc_assert (bb_vinfo || !inv_p);
3855         }
3856       else
3857         {
3858           /* For interleaved stores we created vectorized defs for all the
3859              defs stored in OPRNDS in the previous iteration (previous copy).
3860              DR_CHAIN is then used as an input to vect_permute_store_chain(),
3861              and OPRNDS as an input to vect_get_vec_def_for_stmt_copy() for the
3862              next copy.
3863              If the store is not strided, GROUP_SIZE is 1, and DR_CHAIN and
3864              OPRNDS are of size 1.  */
3865           for (i = 0; i < group_size; i++)
3866             {
3867               op = VEC_index (tree, oprnds, i);
3868               vect_is_simple_use (op, loop_vinfo, bb_vinfo, &def_stmt, &def,
3869                                   &dt);
3870               vec_oprnd = vect_get_vec_def_for_stmt_copy (dt, op);
3871               VEC_replace(tree, dr_chain, i, vec_oprnd);
3872               VEC_replace(tree, oprnds, i, vec_oprnd);
3873             }
3874           dataref_ptr = bump_vector_ptr (dataref_ptr, ptr_incr, gsi, stmt,
3875                                          TYPE_SIZE_UNIT (aggr_type));
3876         }
3877
3878       if (store_lanes_p)
3879         {
3880           tree vec_array;
3881
3882           /* Combine all the vectors into an array.  */
3883           vec_array = create_vector_array (vectype, vec_num);
3884           for (i = 0; i < vec_num; i++)
3885             {
3886               vec_oprnd = VEC_index (tree, dr_chain, i);
3887               write_vector_array (stmt, gsi, vec_oprnd, vec_array, i);
3888             }
3889
3890           /* Emit:
3891                MEM_REF[...all elements...] = STORE_LANES (VEC_ARRAY).  */
3892           data_ref = create_array_ref (aggr_type, dataref_ptr, first_dr);
3893           new_stmt = gimple_build_call_internal (IFN_STORE_LANES, 1, vec_array);
3894           gimple_call_set_lhs (new_stmt, data_ref);
3895           vect_finish_stmt_generation (stmt, new_stmt, gsi);
3896           mark_symbols_for_renaming (new_stmt);
3897         }
3898       else
3899         {
3900           new_stmt = NULL;
3901           if (strided_store)
3902             {
3903               result_chain = VEC_alloc (tree, heap, group_size);
3904               /* Permute.  */
3905               vect_permute_store_chain (dr_chain, group_size, stmt, gsi,
3906                                         &result_chain);
3907             }
3908
3909           next_stmt = first_stmt;
3910           for (i = 0; i < vec_num; i++)
3911             {
3912               struct ptr_info_def *pi;
3913
3914               if (i > 0)
3915                 /* Bump the vector pointer.  */
3916                 dataref_ptr = bump_vector_ptr (dataref_ptr, ptr_incr, gsi,
3917                                                stmt, NULL_TREE);
3918
3919               if (slp)
3920                 vec_oprnd = VEC_index (tree, vec_oprnds, i);
3921               else if (strided_store)
3922                 /* For strided stores vectorized defs are interleaved in
3923                    vect_permute_store_chain().  */
3924                 vec_oprnd = VEC_index (tree, result_chain, i);
3925
3926               data_ref = build2 (MEM_REF, TREE_TYPE (vec_oprnd), dataref_ptr,
3927                                  build_int_cst (reference_alias_ptr_type
3928                                                 (DR_REF (first_dr)), 0));
3929               pi = get_ptr_info (dataref_ptr);
3930               pi->align = TYPE_ALIGN_UNIT (vectype);
3931               if (aligned_access_p (first_dr))
3932                 pi->misalign = 0;
3933               else if (DR_MISALIGNMENT (first_dr) == -1)
3934                 {
3935                   TREE_TYPE (data_ref)
3936                     = build_aligned_type (TREE_TYPE (data_ref),
3937                                           TYPE_ALIGN (elem_type));
3938                   pi->align = TYPE_ALIGN_UNIT (elem_type);
3939                   pi->misalign = 0;
3940                 }
3941               else
3942                 {
3943                   TREE_TYPE (data_ref)
3944                     = build_aligned_type (TREE_TYPE (data_ref),
3945                                           TYPE_ALIGN (elem_type));
3946                   pi->misalign = DR_MISALIGNMENT (first_dr);
3947                 }
3948
3949               /* Arguments are ready.  Create the new vector stmt.  */
3950               new_stmt = gimple_build_assign (data_ref, vec_oprnd);
3951               vect_finish_stmt_generation (stmt, new_stmt, gsi);
3952               mark_symbols_for_renaming (new_stmt);
3953
3954               if (slp)
3955                 continue;
3956
3957               next_stmt = GROUP_NEXT_ELEMENT (vinfo_for_stmt (next_stmt));
3958               if (!next_stmt)
3959                 break;
3960             }
3961         }
3962       if (!slp)
3963         {
3964           if (j == 0)
3965             STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
3966           else
3967             STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
3968           prev_stmt_info = vinfo_for_stmt (new_stmt);
3969         }
3970     }
3971
3972   VEC_free (tree, heap, dr_chain);
3973   VEC_free (tree, heap, oprnds);
3974   if (result_chain)
3975     VEC_free (tree, heap, result_chain);
3976   if (vec_oprnds)
3977     VEC_free (tree, heap, vec_oprnds);
3978
3979   return true;
3980 }
3981
3982 /* Given a vector type VECTYPE returns a builtin DECL to be used
3983    for vector permutation and stores a mask into *MASK that implements
3984    reversal of the vector elements.  If that is impossible to do
3985    returns NULL (and *MASK is unchanged).  */
3986
3987 static tree
3988 perm_mask_for_reverse (tree vectype, tree *mask)
3989 {
3990   tree builtin_decl;
3991   tree mask_element_type, mask_type;
3992   tree mask_vec = NULL;
3993   int i;
3994   int nunits;
3995   if (!targetm.vectorize.builtin_vec_perm)
3996     return NULL;
3997
3998   builtin_decl = targetm.vectorize.builtin_vec_perm (vectype,
3999                                                      &mask_element_type);
4000   if (!builtin_decl || !mask_element_type)
4001     return NULL;
4002
4003   mask_type = get_vectype_for_scalar_type (mask_element_type);
4004   nunits = TYPE_VECTOR_SUBPARTS (vectype);
4005   if (!mask_type
4006       || TYPE_VECTOR_SUBPARTS (vectype) != TYPE_VECTOR_SUBPARTS (mask_type))
4007     return NULL;
4008
4009   for (i = 0; i < nunits; i++)
4010     mask_vec = tree_cons (NULL, build_int_cst (mask_element_type, i), mask_vec);
4011   mask_vec = build_vector (mask_type, mask_vec);
4012
4013   if (!targetm.vectorize.builtin_vec_perm_ok (vectype, mask_vec))
4014     return NULL;
4015   if (mask)
4016     *mask = mask_vec;
4017   return builtin_decl;
4018 }
4019
4020 /* Given a vector variable X, that was generated for the scalar LHS of
4021    STMT, generate instructions to reverse the vector elements of X,
4022    insert them a *GSI and return the permuted vector variable.  */
4023
4024 static tree
4025 reverse_vec_elements (tree x, gimple stmt, gimple_stmt_iterator *gsi)
4026 {
4027   tree vectype = TREE_TYPE (x);
4028   tree mask_vec, builtin_decl;
4029   tree perm_dest, data_ref;
4030   gimple perm_stmt;
4031
4032   builtin_decl = perm_mask_for_reverse (vectype, &mask_vec);
4033
4034   perm_dest = vect_create_destination_var (gimple_assign_lhs (stmt), vectype);
4035
4036   /* Generate the permute statement.  */
4037   perm_stmt = gimple_build_call (builtin_decl, 3, x, x, mask_vec);
4038   if (!useless_type_conversion_p (vectype,
4039                                   TREE_TYPE (TREE_TYPE (builtin_decl))))
4040     {
4041       tree tem = create_tmp_reg (TREE_TYPE (TREE_TYPE (builtin_decl)), NULL);
4042       tem = make_ssa_name (tem, perm_stmt);
4043       gimple_call_set_lhs (perm_stmt, tem);
4044       vect_finish_stmt_generation (stmt, perm_stmt, gsi);
4045       perm_stmt = gimple_build_assign (NULL_TREE,
4046                                        build1 (VIEW_CONVERT_EXPR,
4047                                                vectype, tem));
4048     }
4049   data_ref = make_ssa_name (perm_dest, perm_stmt);
4050   gimple_set_lhs (perm_stmt, data_ref);
4051   vect_finish_stmt_generation (stmt, perm_stmt, gsi);
4052
4053   return data_ref;
4054 }
4055
4056 /* vectorizable_load.
4057
4058    Check if STMT reads a non scalar data-ref (array/pointer/structure) that
4059    can be vectorized.
4060    If VEC_STMT is also passed, vectorize the STMT: create a vectorized
4061    stmt to replace it, put it in VEC_STMT, and insert it at BSI.
4062    Return FALSE if not a vectorizable STMT, TRUE otherwise.  */
4063
4064 static bool
4065 vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
4066                    slp_tree slp_node, slp_instance slp_node_instance)
4067 {
4068   tree scalar_dest;
4069   tree vec_dest = NULL;
4070   tree data_ref = NULL;
4071   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
4072   stmt_vec_info prev_stmt_info;
4073   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
4074   struct loop *loop = NULL;
4075   struct loop *containing_loop = (gimple_bb (stmt))->loop_father;
4076   bool nested_in_vect_loop = false;
4077   struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info), *first_dr;
4078   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
4079   tree elem_type;
4080   tree new_temp;
4081   enum machine_mode mode;
4082   gimple new_stmt = NULL;
4083   tree dummy;
4084   enum dr_alignment_support alignment_support_scheme;
4085   tree dataref_ptr = NULL_TREE;
4086   gimple ptr_incr;
4087   int nunits = TYPE_VECTOR_SUBPARTS (vectype);
4088   int ncopies;
4089   int i, j, group_size;
4090   tree msq = NULL_TREE, lsq;
4091   tree offset = NULL_TREE;
4092   tree realignment_token = NULL_TREE;
4093   gimple phi = NULL;
4094   VEC(tree,heap) *dr_chain = NULL;
4095   bool strided_load = false;
4096   bool load_lanes_p = false;
4097   gimple first_stmt;
4098   tree scalar_type;
4099   bool inv_p;
4100   bool negative;
4101   bool compute_in_loop = false;
4102   struct loop *at_loop;
4103   int vec_num;
4104   bool slp = (slp_node != NULL);
4105   bool slp_perm = false;
4106   enum tree_code code;
4107   bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
4108   int vf;
4109   tree aggr_type;
4110
4111   if (loop_vinfo)
4112     {
4113       loop = LOOP_VINFO_LOOP (loop_vinfo);
4114       nested_in_vect_loop = nested_in_vect_loop_p (loop, stmt);
4115       vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
4116     }
4117   else
4118     vf = 1;
4119
4120   /* Multiple types in SLP are handled by creating the appropriate number of
4121      vectorized stmts for each SLP node.  Hence, NCOPIES is always 1 in
4122      case of SLP.  */
4123   if (slp || PURE_SLP_STMT (stmt_info))
4124     ncopies = 1;
4125   else
4126     ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits;
4127
4128   gcc_assert (ncopies >= 1);
4129
4130   /* FORNOW. This restriction should be relaxed.  */
4131   if (nested_in_vect_loop && ncopies > 1)
4132     {
4133       if (vect_print_dump_info (REPORT_DETAILS))
4134         fprintf (vect_dump, "multiple types in nested loop.");
4135       return false;
4136     }
4137
4138   if (!STMT_VINFO_RELEVANT_P (stmt_info) && !bb_vinfo)
4139     return false;
4140
4141   if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def)
4142     return false;
4143
4144   /* Is vectorizable load? */
4145   if (!is_gimple_assign (stmt))
4146     return false;
4147
4148   scalar_dest = gimple_assign_lhs (stmt);
4149   if (TREE_CODE (scalar_dest) != SSA_NAME)
4150     return false;
4151
4152   code = gimple_assign_rhs_code (stmt);
4153   if (code != ARRAY_REF
4154       && code != INDIRECT_REF
4155       && code != COMPONENT_REF
4156       && code != IMAGPART_EXPR
4157       && code != REALPART_EXPR
4158       && code != MEM_REF
4159       && TREE_CODE_CLASS (code) != tcc_declaration)
4160     return false;
4161
4162   if (!STMT_VINFO_DATA_REF (stmt_info))
4163     return false;
4164
4165   negative = tree_int_cst_compare (DR_STEP (dr), size_zero_node) < 0;
4166   if (negative && ncopies > 1)
4167     {
4168       if (vect_print_dump_info (REPORT_DETAILS))
4169         fprintf (vect_dump, "multiple types with negative step.");
4170       return false;
4171     }
4172
4173   scalar_type = TREE_TYPE (DR_REF (dr));
4174   mode = TYPE_MODE (vectype);
4175
4176   /* FORNOW. In some cases can vectorize even if data-type not supported
4177     (e.g. - data copies).  */
4178   if (optab_handler (mov_optab, mode) == CODE_FOR_nothing)
4179     {
4180       if (vect_print_dump_info (REPORT_DETAILS))
4181         fprintf (vect_dump, "Aligned load, but unsupported type.");
4182       return false;
4183     }
4184
4185   /* The vector component type needs to be trivially convertible to the
4186      scalar lhs.  This should always be the case.  */
4187   elem_type = TREE_TYPE (vectype);
4188   if (!useless_type_conversion_p (TREE_TYPE (scalar_dest), elem_type))
4189     {
4190       if (vect_print_dump_info (REPORT_DETAILS))
4191         fprintf (vect_dump, "???  operands of different types");
4192       return false;
4193     }
4194
4195   /* Check if the load is a part of an interleaving chain.  */
4196   if (STMT_VINFO_STRIDED_ACCESS (stmt_info))
4197     {
4198       strided_load = true;
4199       /* FORNOW */
4200       gcc_assert (! nested_in_vect_loop);
4201
4202       first_stmt = GROUP_FIRST_ELEMENT (stmt_info);
4203       if (!slp && !PURE_SLP_STMT (stmt_info))
4204         {
4205           group_size = GROUP_SIZE (vinfo_for_stmt (first_stmt));
4206           if (vect_load_lanes_supported (vectype, group_size))
4207             load_lanes_p = true;
4208           else if (!vect_strided_load_supported (vectype, group_size))
4209             return false;
4210         }
4211     }
4212
4213   if (negative)
4214     {
4215       gcc_assert (!strided_load);
4216       alignment_support_scheme = vect_supportable_dr_alignment (dr, false);
4217       if (alignment_support_scheme != dr_aligned
4218           && alignment_support_scheme != dr_unaligned_supported)
4219         {
4220           if (vect_print_dump_info (REPORT_DETAILS))
4221             fprintf (vect_dump, "negative step but alignment required.");
4222           return false;
4223         }
4224       if (!perm_mask_for_reverse (vectype, NULL))
4225         {
4226           if (vect_print_dump_info (REPORT_DETAILS))
4227             fprintf (vect_dump, "negative step and reversing not supported.");
4228           return false;
4229         }
4230     }
4231
4232   if (!vec_stmt) /* transformation not required.  */
4233     {
4234       STMT_VINFO_TYPE (stmt_info) = load_vec_info_type;
4235       vect_model_load_cost (stmt_info, ncopies, load_lanes_p, NULL);
4236       return true;
4237     }
4238
4239   if (vect_print_dump_info (REPORT_DETAILS))
4240     fprintf (vect_dump, "transform load. ncopies = %d", ncopies);
4241
4242   /** Transform.  **/
4243
4244   if (strided_load)
4245     {
4246       first_stmt = GROUP_FIRST_ELEMENT (stmt_info);
4247       /* Check if the chain of loads is already vectorized.  */
4248       if (STMT_VINFO_VEC_STMT (vinfo_for_stmt (first_stmt)))
4249         {
4250           *vec_stmt = STMT_VINFO_VEC_STMT (stmt_info);
4251           return true;
4252         }
4253       first_dr = STMT_VINFO_DATA_REF (vinfo_for_stmt (first_stmt));
4254       group_size = GROUP_SIZE (vinfo_for_stmt (first_stmt));
4255
4256       /* VEC_NUM is the number of vect stmts to be created for this group.  */
4257       if (slp)
4258         {
4259           strided_load = false;
4260           vec_num = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node);
4261           if (SLP_INSTANCE_LOAD_PERMUTATION (slp_node_instance))
4262             slp_perm = true;
4263         }
4264       else
4265         vec_num = group_size;
4266     }
4267   else
4268     {
4269       first_stmt = stmt;
4270       first_dr = dr;
4271       group_size = vec_num = 1;
4272     }
4273
4274   alignment_support_scheme = vect_supportable_dr_alignment (first_dr, false);
4275   gcc_assert (alignment_support_scheme);
4276   /* Targets with load-lane instructions must not require explicit
4277      realignment.  */
4278   gcc_assert (!load_lanes_p
4279               || alignment_support_scheme == dr_aligned
4280               || alignment_support_scheme == dr_unaligned_supported);
4281
4282   /* In case the vectorization factor (VF) is bigger than the number
4283      of elements that we can fit in a vectype (nunits), we have to generate
4284      more than one vector stmt - i.e - we need to "unroll" the
4285      vector stmt by a factor VF/nunits.  In doing so, we record a pointer
4286      from one copy of the vector stmt to the next, in the field
4287      STMT_VINFO_RELATED_STMT.  This is necessary in order to allow following
4288      stages to find the correct vector defs to be used when vectorizing
4289      stmts that use the defs of the current stmt.  The example below
4290      illustrates the vectorization process when VF=16 and nunits=4 (i.e., we
4291      need to create 4 vectorized stmts):
4292
4293      before vectorization:
4294                                 RELATED_STMT    VEC_STMT
4295         S1:     x = memref      -               -
4296         S2:     z = x + 1       -               -
4297
4298      step 1: vectorize stmt S1:
4299         We first create the vector stmt VS1_0, and, as usual, record a
4300         pointer to it in the STMT_VINFO_VEC_STMT of the scalar stmt S1.
4301         Next, we create the vector stmt VS1_1, and record a pointer to
4302         it in the STMT_VINFO_RELATED_STMT of the vector stmt VS1_0.
4303         Similarly, for VS1_2 and VS1_3.  This is the resulting chain of
4304         stmts and pointers:
4305                                 RELATED_STMT    VEC_STMT
4306         VS1_0:  vx0 = memref0   VS1_1           -
4307         VS1_1:  vx1 = memref1   VS1_2           -
4308         VS1_2:  vx2 = memref2   VS1_3           -
4309         VS1_3:  vx3 = memref3   -               -
4310         S1:     x = load        -               VS1_0
4311         S2:     z = x + 1       -               -
4312
4313      See in documentation in vect_get_vec_def_for_stmt_copy for how the
4314      information we recorded in RELATED_STMT field is used to vectorize
4315      stmt S2.  */
4316
4317   /* In case of interleaving (non-unit strided access):
4318
4319      S1:  x2 = &base + 2
4320      S2:  x0 = &base
4321      S3:  x1 = &base + 1
4322      S4:  x3 = &base + 3
4323
4324      Vectorized loads are created in the order of memory accesses
4325      starting from the access of the first stmt of the chain:
4326
4327      VS1: vx0 = &base
4328      VS2: vx1 = &base + vec_size*1
4329      VS3: vx3 = &base + vec_size*2
4330      VS4: vx4 = &base + vec_size*3
4331
4332      Then permutation statements are generated:
4333
4334      VS5: vx5 = VEC_EXTRACT_EVEN_EXPR < vx0, vx1 >
4335      VS6: vx6 = VEC_EXTRACT_ODD_EXPR < vx0, vx1 >
4336        ...
4337
4338      And they are put in STMT_VINFO_VEC_STMT of the corresponding scalar stmts
4339      (the order of the data-refs in the output of vect_permute_load_chain
4340      corresponds to the order of scalar stmts in the interleaving chain - see
4341      the documentation of vect_permute_load_chain()).
4342      The generation of permutation stmts and recording them in
4343      STMT_VINFO_VEC_STMT is done in vect_transform_strided_load().
4344
4345      In case of both multiple types and interleaving, the vector loads and
4346      permutation stmts above are created for every copy.  The result vector
4347      stmts are put in STMT_VINFO_VEC_STMT for the first copy and in the
4348      corresponding STMT_VINFO_RELATED_STMT for the next copies.  */
4349
4350   /* If the data reference is aligned (dr_aligned) or potentially unaligned
4351      on a target that supports unaligned accesses (dr_unaligned_supported)
4352      we generate the following code:
4353          p = initial_addr;
4354          indx = 0;
4355          loop {
4356            p = p + indx * vectype_size;
4357            vec_dest = *(p);
4358            indx = indx + 1;
4359          }
4360
4361      Otherwise, the data reference is potentially unaligned on a target that
4362      does not support unaligned accesses (dr_explicit_realign_optimized) -
4363      then generate the following code, in which the data in each iteration is
4364      obtained by two vector loads, one from the previous iteration, and one
4365      from the current iteration:
4366          p1 = initial_addr;
4367          msq_init = *(floor(p1))
4368          p2 = initial_addr + VS - 1;
4369          realignment_token = call target_builtin;
4370          indx = 0;
4371          loop {
4372            p2 = p2 + indx * vectype_size
4373            lsq = *(floor(p2))
4374            vec_dest = realign_load (msq, lsq, realignment_token)
4375            indx = indx + 1;
4376            msq = lsq;
4377          }   */
4378
4379   /* If the misalignment remains the same throughout the execution of the
4380      loop, we can create the init_addr and permutation mask at the loop
4381      preheader.  Otherwise, it needs to be created inside the loop.
4382      This can only occur when vectorizing memory accesses in the inner-loop
4383      nested within an outer-loop that is being vectorized.  */
4384
4385   if (loop && nested_in_vect_loop_p (loop, stmt)
4386       && (TREE_INT_CST_LOW (DR_STEP (dr))
4387           % GET_MODE_SIZE (TYPE_MODE (vectype)) != 0))
4388     {
4389       gcc_assert (alignment_support_scheme != dr_explicit_realign_optimized);
4390       compute_in_loop = true;
4391     }
4392
4393   if ((alignment_support_scheme == dr_explicit_realign_optimized
4394        || alignment_support_scheme == dr_explicit_realign)
4395       && !compute_in_loop)
4396     {
4397       msq = vect_setup_realignment (first_stmt, gsi, &realignment_token,
4398                                     alignment_support_scheme, NULL_TREE,
4399                                     &at_loop);
4400       if (alignment_support_scheme == dr_explicit_realign_optimized)
4401         {
4402           phi = SSA_NAME_DEF_STMT (msq);
4403           offset = size_int (TYPE_VECTOR_SUBPARTS (vectype) - 1);
4404         }
4405     }
4406   else
4407     at_loop = loop;
4408
4409   if (negative)
4410     offset = size_int (-TYPE_VECTOR_SUBPARTS (vectype) + 1);
4411
4412   if (load_lanes_p)
4413     aggr_type = build_array_type_nelts (elem_type, vec_num * nunits);
4414   else
4415     aggr_type = vectype;
4416
4417   prev_stmt_info = NULL;
4418   for (j = 0; j < ncopies; j++)
4419     {
4420       /* 1. Create the vector or array pointer update chain.  */
4421       if (j == 0)
4422         dataref_ptr = vect_create_data_ref_ptr (first_stmt, aggr_type, at_loop,
4423                                                 offset, &dummy, gsi,
4424                                                 &ptr_incr, false, &inv_p);
4425       else
4426         dataref_ptr = bump_vector_ptr (dataref_ptr, ptr_incr, gsi, stmt,
4427                                        TYPE_SIZE_UNIT (aggr_type));
4428
4429       if (strided_load || slp_perm)
4430         dr_chain = VEC_alloc (tree, heap, vec_num);
4431
4432       if (load_lanes_p)
4433         {
4434           tree vec_array;
4435
4436           vec_array = create_vector_array (vectype, vec_num);
4437
4438           /* Emit:
4439                VEC_ARRAY = LOAD_LANES (MEM_REF[...all elements...]).  */
4440           data_ref = create_array_ref (aggr_type, dataref_ptr, first_dr);
4441           new_stmt = gimple_build_call_internal (IFN_LOAD_LANES, 1, data_ref);
4442           gimple_call_set_lhs (new_stmt, vec_array);
4443           vect_finish_stmt_generation (stmt, new_stmt, gsi);
4444           mark_symbols_for_renaming (new_stmt);
4445
4446           /* Extract each vector into an SSA_NAME.  */
4447           for (i = 0; i < vec_num; i++)
4448             {
4449               new_temp = read_vector_array (stmt, gsi, scalar_dest,
4450                                             vec_array, i);
4451               VEC_quick_push (tree, dr_chain, new_temp);
4452             }
4453
4454           /* Record the mapping between SSA_NAMEs and statements.  */
4455           vect_record_strided_load_vectors (stmt, dr_chain);
4456         }
4457       else
4458         {
4459           for (i = 0; i < vec_num; i++)
4460             {
4461               if (i > 0)
4462                 dataref_ptr = bump_vector_ptr (dataref_ptr, ptr_incr, gsi,
4463                                                stmt, NULL_TREE);
4464
4465               /* 2. Create the vector-load in the loop.  */
4466               switch (alignment_support_scheme)
4467                 {
4468                 case dr_aligned:
4469                 case dr_unaligned_supported:
4470                   {
4471                     struct ptr_info_def *pi;
4472                     data_ref
4473                       = build2 (MEM_REF, vectype, dataref_ptr,
4474                                 build_int_cst (reference_alias_ptr_type
4475                                                (DR_REF (first_dr)), 0));
4476                     pi = get_ptr_info (dataref_ptr);
4477                     pi->align = TYPE_ALIGN_UNIT (vectype);
4478                     if (alignment_support_scheme == dr_aligned)
4479                       {
4480                         gcc_assert (aligned_access_p (first_dr));
4481                         pi->misalign = 0;
4482                       }
4483                     else if (DR_MISALIGNMENT (first_dr) == -1)
4484                       {
4485                         TREE_TYPE (data_ref)
4486                           = build_aligned_type (TREE_TYPE (data_ref),
4487                                                 TYPE_ALIGN (elem_type));
4488                         pi->align = TYPE_ALIGN_UNIT (elem_type);
4489                         pi->misalign = 0;
4490                       }
4491                     else
4492                       {
4493                         TREE_TYPE (data_ref)
4494                           = build_aligned_type (TREE_TYPE (data_ref),
4495                                                 TYPE_ALIGN (elem_type));
4496                         pi->misalign = DR_MISALIGNMENT (first_dr);
4497                       }
4498                     break;
4499                   }
4500                 case dr_explicit_realign:
4501                   {
4502                     tree ptr, bump;
4503                     tree vs_minus_1;
4504
4505                     vs_minus_1 = size_int (TYPE_VECTOR_SUBPARTS (vectype) - 1);
4506
4507                     if (compute_in_loop)
4508                       msq = vect_setup_realignment (first_stmt, gsi,
4509                                                     &realignment_token,
4510                                                     dr_explicit_realign,
4511                                                     dataref_ptr, NULL);
4512
4513                     new_stmt = gimple_build_assign_with_ops
4514                                  (BIT_AND_EXPR, NULL_TREE, dataref_ptr,
4515                                   build_int_cst
4516                                   (TREE_TYPE (dataref_ptr),
4517                                    -(HOST_WIDE_INT)TYPE_ALIGN_UNIT (vectype)));
4518                     ptr = make_ssa_name (SSA_NAME_VAR (dataref_ptr), new_stmt);
4519                     gimple_assign_set_lhs (new_stmt, ptr);
4520                     vect_finish_stmt_generation (stmt, new_stmt, gsi);
4521                     data_ref
4522                       = build2 (MEM_REF, vectype, ptr,
4523                                 build_int_cst (reference_alias_ptr_type
4524                                                  (DR_REF (first_dr)), 0));
4525                     vec_dest = vect_create_destination_var (scalar_dest,
4526                                                             vectype);
4527                     new_stmt = gimple_build_assign (vec_dest, data_ref);
4528                     new_temp = make_ssa_name (vec_dest, new_stmt);
4529                     gimple_assign_set_lhs (new_stmt, new_temp);
4530                     gimple_set_vdef (new_stmt, gimple_vdef (stmt));
4531                     gimple_set_vuse (new_stmt, gimple_vuse (stmt));
4532                     vect_finish_stmt_generation (stmt, new_stmt, gsi);
4533                     msq = new_temp;
4534
4535                     bump = size_binop (MULT_EXPR, vs_minus_1,
4536                                        TYPE_SIZE_UNIT (scalar_type));
4537                     ptr = bump_vector_ptr (dataref_ptr, NULL, gsi, stmt, bump);
4538                     new_stmt = gimple_build_assign_with_ops
4539                                  (BIT_AND_EXPR, NULL_TREE, ptr,
4540                                   build_int_cst
4541                                   (TREE_TYPE (ptr),
4542                                    -(HOST_WIDE_INT)TYPE_ALIGN_UNIT (vectype)));
4543                     ptr = make_ssa_name (SSA_NAME_VAR (dataref_ptr), new_stmt);
4544                     gimple_assign_set_lhs (new_stmt, ptr);
4545                     vect_finish_stmt_generation (stmt, new_stmt, gsi);
4546                     data_ref
4547                       = build2 (MEM_REF, vectype, ptr,
4548                                 build_int_cst (reference_alias_ptr_type
4549                                                  (DR_REF (first_dr)), 0));
4550                     break;
4551                   }
4552                 case dr_explicit_realign_optimized:
4553                   new_stmt = gimple_build_assign_with_ops
4554                                (BIT_AND_EXPR, NULL_TREE, dataref_ptr,
4555                                 build_int_cst
4556                                   (TREE_TYPE (dataref_ptr),
4557                                    -(HOST_WIDE_INT)TYPE_ALIGN_UNIT (vectype)));
4558                   new_temp = make_ssa_name (SSA_NAME_VAR (dataref_ptr),
4559                                             new_stmt);
4560                   gimple_assign_set_lhs (new_stmt, new_temp);
4561                   vect_finish_stmt_generation (stmt, new_stmt, gsi);
4562                   data_ref
4563                     = build2 (MEM_REF, vectype, new_temp,
4564                               build_int_cst (reference_alias_ptr_type
4565                                                (DR_REF (first_dr)), 0));
4566                   break;
4567                 default:
4568                   gcc_unreachable ();
4569                 }
4570               vec_dest = vect_create_destination_var (scalar_dest, vectype);
4571               new_stmt = gimple_build_assign (vec_dest, data_ref);
4572               new_temp = make_ssa_name (vec_dest, new_stmt);
4573               gimple_assign_set_lhs (new_stmt, new_temp);
4574               vect_finish_stmt_generation (stmt, new_stmt, gsi);
4575               mark_symbols_for_renaming (new_stmt);
4576
4577               /* 3. Handle explicit realignment if necessary/supported.
4578                  Create in loop:
4579                    vec_dest = realign_load (msq, lsq, realignment_token)  */
4580               if (alignment_support_scheme == dr_explicit_realign_optimized
4581                   || alignment_support_scheme == dr_explicit_realign)
4582                 {
4583                   lsq = gimple_assign_lhs (new_stmt);
4584                   if (!realignment_token)
4585                     realignment_token = dataref_ptr;
4586                   vec_dest = vect_create_destination_var (scalar_dest, vectype);
4587                   new_stmt
4588                     = gimple_build_assign_with_ops3 (REALIGN_LOAD_EXPR,
4589                                                      vec_dest, msq, lsq,
4590                                                      realignment_token);
4591                   new_temp = make_ssa_name (vec_dest, new_stmt);
4592                   gimple_assign_set_lhs (new_stmt, new_temp);
4593                   vect_finish_stmt_generation (stmt, new_stmt, gsi);
4594
4595                   if (alignment_support_scheme == dr_explicit_realign_optimized)
4596                     {
4597                       gcc_assert (phi);
4598                       if (i == vec_num - 1 && j == ncopies - 1)
4599                         add_phi_arg (phi, lsq,
4600                                      loop_latch_edge (containing_loop),
4601                                      UNKNOWN_LOCATION);
4602                       msq = lsq;
4603                     }
4604                 }
4605
4606               /* 4. Handle invariant-load.  */
4607               if (inv_p && !bb_vinfo)
4608                 {
4609                   tree vec_inv;
4610                   gimple_stmt_iterator gsi2 = *gsi;
4611                   gcc_assert (!strided_load);
4612                   gsi_next (&gsi2);
4613                   vec_inv = build_vector_from_val (vectype, scalar_dest);
4614                   new_temp = vect_init_vector (stmt, vec_inv,
4615                                                vectype, &gsi2);
4616                   new_stmt = SSA_NAME_DEF_STMT (new_temp);
4617                 }
4618
4619               if (negative)
4620                 {
4621                   new_temp = reverse_vec_elements (new_temp, stmt, gsi);
4622                   new_stmt = SSA_NAME_DEF_STMT (new_temp);
4623                 }
4624
4625               /* Collect vector loads and later create their permutation in
4626                  vect_transform_strided_load ().  */
4627               if (strided_load || slp_perm)
4628                 VEC_quick_push (tree, dr_chain, new_temp);
4629
4630               /* Store vector loads in the corresponding SLP_NODE.  */
4631               if (slp && !slp_perm)
4632                 VEC_quick_push (gimple, SLP_TREE_VEC_STMTS (slp_node),
4633                                 new_stmt);
4634             }
4635         }
4636
4637       if (slp && !slp_perm)
4638         continue;
4639
4640       if (slp_perm)
4641         {
4642           if (!vect_transform_slp_perm_load (stmt, dr_chain, gsi, vf,
4643                                              slp_node_instance, false))
4644             {
4645               VEC_free (tree, heap, dr_chain);
4646               return false;
4647             }
4648         }
4649       else
4650         {
4651           if (strided_load)
4652             {
4653               if (!load_lanes_p)
4654                 vect_transform_strided_load (stmt, dr_chain, group_size, gsi);
4655               *vec_stmt = STMT_VINFO_VEC_STMT (stmt_info);
4656             }
4657           else
4658             {
4659               if (j == 0)
4660                 STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
4661               else
4662                 STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
4663               prev_stmt_info = vinfo_for_stmt (new_stmt);
4664             }
4665         }
4666       if (dr_chain)
4667         VEC_free (tree, heap, dr_chain);
4668     }
4669
4670   return true;
4671 }
4672
4673 /* Function vect_is_simple_cond.
4674
4675    Input:
4676    LOOP - the loop that is being vectorized.
4677    COND - Condition that is checked for simple use.
4678
4679    Output:
4680    *COMP_VECTYPE - the vector type for the comparison.
4681
4682    Returns whether a COND can be vectorized.  Checks whether
4683    condition operands are supportable using vec_is_simple_use.  */
4684
4685 static bool
4686 vect_is_simple_cond (tree cond, loop_vec_info loop_vinfo, tree *comp_vectype)
4687 {
4688   tree lhs, rhs;
4689   tree def;
4690   enum vect_def_type dt;
4691   tree vectype1 = NULL_TREE, vectype2 = NULL_TREE;
4692
4693   if (!COMPARISON_CLASS_P (cond))
4694     return false;
4695
4696   lhs = TREE_OPERAND (cond, 0);
4697   rhs = TREE_OPERAND (cond, 1);
4698
4699   if (TREE_CODE (lhs) == SSA_NAME)
4700     {
4701       gimple lhs_def_stmt = SSA_NAME_DEF_STMT (lhs);
4702       if (!vect_is_simple_use_1 (lhs, loop_vinfo, NULL, &lhs_def_stmt, &def,
4703                                  &dt, &vectype1))
4704         return false;
4705     }
4706   else if (TREE_CODE (lhs) != INTEGER_CST && TREE_CODE (lhs) != REAL_CST
4707            && TREE_CODE (lhs) != FIXED_CST)
4708     return false;
4709
4710   if (TREE_CODE (rhs) == SSA_NAME)
4711     {
4712       gimple rhs_def_stmt = SSA_NAME_DEF_STMT (rhs);
4713       if (!vect_is_simple_use_1 (rhs, loop_vinfo, NULL, &rhs_def_stmt, &def,
4714                                  &dt, &vectype2))
4715         return false;
4716     }
4717   else if (TREE_CODE (rhs) != INTEGER_CST  && TREE_CODE (rhs) != REAL_CST
4718            && TREE_CODE (rhs) != FIXED_CST)
4719     return false;
4720
4721   *comp_vectype = vectype1 ? vectype1 : vectype2;
4722   return true;
4723 }
4724
4725 /* vectorizable_condition.
4726
4727    Check if STMT is conditional modify expression that can be vectorized.
4728    If VEC_STMT is also passed, vectorize the STMT: create a vectorized
4729    stmt using VEC_COND_EXPR  to replace it, put it in VEC_STMT, and insert it
4730    at GSI.
4731
4732    When STMT is vectorized as nested cycle, REDUC_DEF is the vector variable
4733    to be used at REDUC_INDEX (in then clause if REDUC_INDEX is 1, and in
4734    else caluse if it is 2).
4735
4736    Return FALSE if not a vectorizable STMT, TRUE otherwise.  */
4737
4738 bool
4739 vectorizable_condition (gimple stmt, gimple_stmt_iterator *gsi,
4740                         gimple *vec_stmt, tree reduc_def, int reduc_index)
4741 {
4742   tree scalar_dest = NULL_TREE;
4743   tree vec_dest = NULL_TREE;
4744   tree cond_expr, then_clause, else_clause;
4745   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
4746   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
4747   tree comp_vectype;
4748   tree vec_cond_lhs = NULL_TREE, vec_cond_rhs = NULL_TREE;
4749   tree vec_then_clause = NULL_TREE, vec_else_clause = NULL_TREE;
4750   tree vec_compare, vec_cond_expr;
4751   tree new_temp;
4752   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
4753   tree def;
4754   enum vect_def_type dt, dts[4];
4755   int nunits = TYPE_VECTOR_SUBPARTS (vectype);
4756   int ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits;
4757   enum tree_code code;
4758   stmt_vec_info prev_stmt_info = NULL;
4759   int j;
4760
4761   /* FORNOW: unsupported in basic block SLP.  */
4762   gcc_assert (loop_vinfo);
4763
4764   /* FORNOW: SLP not supported.  */
4765   if (STMT_SLP_TYPE (stmt_info))
4766     return false;
4767
4768   gcc_assert (ncopies >= 1);
4769   if (reduc_index && ncopies > 1)
4770     return false; /* FORNOW */
4771
4772   if (!STMT_VINFO_RELEVANT_P (stmt_info))
4773     return false;
4774
4775   if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def
4776       && !(STMT_VINFO_DEF_TYPE (stmt_info) == vect_nested_cycle
4777            && reduc_def))
4778     return false;
4779
4780   /* FORNOW: not yet supported.  */
4781   if (STMT_VINFO_LIVE_P (stmt_info))
4782     {
4783       if (vect_print_dump_info (REPORT_DETAILS))
4784         fprintf (vect_dump, "value used after loop.");
4785       return false;
4786     }
4787
4788   /* Is vectorizable conditional operation?  */
4789   if (!is_gimple_assign (stmt))
4790     return false;
4791
4792   code = gimple_assign_rhs_code (stmt);
4793
4794   if (code != COND_EXPR)
4795     return false;
4796
4797   cond_expr = gimple_assign_rhs1 (stmt);
4798   then_clause = gimple_assign_rhs2 (stmt);
4799   else_clause = gimple_assign_rhs3 (stmt);
4800
4801   if (!vect_is_simple_cond (cond_expr, loop_vinfo, &comp_vectype)
4802       || !comp_vectype)
4803     return false;
4804
4805   if (TREE_CODE (then_clause) == SSA_NAME)
4806     {
4807       gimple then_def_stmt = SSA_NAME_DEF_STMT (then_clause);
4808       if (!vect_is_simple_use (then_clause, loop_vinfo, NULL,
4809                                &then_def_stmt, &def, &dt))
4810         return false;
4811     }
4812   else if (TREE_CODE (then_clause) != INTEGER_CST
4813            && TREE_CODE (then_clause) != REAL_CST
4814            && TREE_CODE (then_clause) != FIXED_CST)
4815     return false;
4816
4817   if (TREE_CODE (else_clause) == SSA_NAME)
4818     {
4819       gimple else_def_stmt = SSA_NAME_DEF_STMT (else_clause);
4820       if (!vect_is_simple_use (else_clause, loop_vinfo, NULL,
4821                                &else_def_stmt, &def, &dt))
4822         return false;
4823     }
4824   else if (TREE_CODE (else_clause) != INTEGER_CST
4825            && TREE_CODE (else_clause) != REAL_CST
4826            && TREE_CODE (else_clause) != FIXED_CST)
4827     return false;
4828
4829   if (!vec_stmt)
4830     {
4831       STMT_VINFO_TYPE (stmt_info) = condition_vec_info_type;
4832       return expand_vec_cond_expr_p (vectype, comp_vectype);
4833     }
4834
4835   /* Transform */
4836
4837   /* Handle def.  */
4838   scalar_dest = gimple_assign_lhs (stmt);
4839   vec_dest = vect_create_destination_var (scalar_dest, vectype);
4840
4841   /* Handle cond expr.  */
4842   for (j = 0; j < ncopies; j++)
4843     {
4844       gimple new_stmt;
4845       if (j == 0)
4846         {
4847           gimple gtemp;
4848           vec_cond_lhs =
4849               vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 0),
4850                                             stmt, NULL);
4851           vect_is_simple_use (TREE_OPERAND (cond_expr, 0), loop_vinfo,
4852                               NULL, &gtemp, &def, &dts[0]);
4853           vec_cond_rhs =
4854               vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 1),
4855                                             stmt, NULL);
4856           vect_is_simple_use (TREE_OPERAND (cond_expr, 1), loop_vinfo,
4857                               NULL, &gtemp, &def, &dts[1]);
4858           if (reduc_index == 1)
4859             vec_then_clause = reduc_def;
4860           else
4861             {
4862               vec_then_clause = vect_get_vec_def_for_operand (then_clause,
4863                                                               stmt, NULL);
4864               vect_is_simple_use (then_clause, loop_vinfo,
4865                                   NULL, &gtemp, &def, &dts[2]);
4866             }
4867           if (reduc_index == 2)
4868             vec_else_clause = reduc_def;
4869           else
4870             {
4871               vec_else_clause = vect_get_vec_def_for_operand (else_clause,
4872                                                               stmt, NULL);
4873               vect_is_simple_use (else_clause, loop_vinfo,
4874                                   NULL, &gtemp, &def, &dts[3]);
4875             }
4876         }
4877       else
4878         {
4879           vec_cond_lhs = vect_get_vec_def_for_stmt_copy (dts[0], vec_cond_lhs);
4880           vec_cond_rhs = vect_get_vec_def_for_stmt_copy (dts[1], vec_cond_rhs);
4881           vec_then_clause = vect_get_vec_def_for_stmt_copy (dts[2],
4882                                                             vec_then_clause);
4883           vec_else_clause = vect_get_vec_def_for_stmt_copy (dts[3],
4884                                                             vec_else_clause);
4885         }
4886
4887       /* Arguments are ready.  Create the new vector stmt.  */
4888       vec_compare = build2 (TREE_CODE (cond_expr), vectype,
4889                             vec_cond_lhs, vec_cond_rhs);
4890       vec_cond_expr = build3 (VEC_COND_EXPR, vectype,
4891                               vec_compare, vec_then_clause, vec_else_clause);
4892
4893       new_stmt = gimple_build_assign (vec_dest, vec_cond_expr);
4894       new_temp = make_ssa_name (vec_dest, new_stmt);
4895       gimple_assign_set_lhs (new_stmt, new_temp);
4896       vect_finish_stmt_generation (stmt, new_stmt, gsi);
4897       if (j == 0)
4898         STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
4899       else
4900         STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
4901
4902       prev_stmt_info = vinfo_for_stmt (new_stmt);
4903     }
4904
4905   return true;
4906 }
4907
4908
4909 /* Make sure the statement is vectorizable.  */
4910
4911 bool
4912 vect_analyze_stmt (gimple stmt, bool *need_to_vectorize, slp_tree node)
4913 {
4914   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
4915   bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
4916   enum vect_relevant relevance = STMT_VINFO_RELEVANT (stmt_info);
4917   bool ok;
4918   tree scalar_type, vectype;
4919   gimple pattern_stmt, pattern_def_stmt;
4920
4921   if (vect_print_dump_info (REPORT_DETAILS))
4922     {
4923       fprintf (vect_dump, "==> examining statement: ");
4924       print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
4925     }
4926
4927   if (gimple_has_volatile_ops (stmt))
4928     {
4929       if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
4930         fprintf (vect_dump, "not vectorized: stmt has volatile operands");
4931
4932       return false;
4933     }
4934
4935   /* Skip stmts that do not need to be vectorized. In loops this is expected
4936      to include:
4937      - the COND_EXPR which is the loop exit condition
4938      - any LABEL_EXPRs in the loop
4939      - computations that are used only for array indexing or loop control.
4940      In basic blocks we only analyze statements that are a part of some SLP
4941      instance, therefore, all the statements are relevant.
4942
4943      Pattern statement need to be analyzed instead of the original statement
4944      if the original statement is not relevant.  Otherwise, we analyze both
4945      statements.  */
4946
4947   pattern_stmt = STMT_VINFO_RELATED_STMT (stmt_info);
4948   if (!STMT_VINFO_RELEVANT_P (stmt_info)
4949       && !STMT_VINFO_LIVE_P (stmt_info))
4950     {
4951       if (STMT_VINFO_IN_PATTERN_P (stmt_info)
4952           && pattern_stmt
4953           && (STMT_VINFO_RELEVANT_P (vinfo_for_stmt (pattern_stmt))
4954               || STMT_VINFO_LIVE_P (vinfo_for_stmt (pattern_stmt))))
4955         {
4956           /* Analyze PATTERN_STMT instead of the original stmt.  */
4957           stmt = pattern_stmt;
4958           stmt_info = vinfo_for_stmt (pattern_stmt);
4959           if (vect_print_dump_info (REPORT_DETAILS))
4960             {
4961               fprintf (vect_dump, "==> examining pattern statement: ");
4962               print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
4963             }
4964         }
4965       else
4966         {
4967           if (vect_print_dump_info (REPORT_DETAILS))
4968             fprintf (vect_dump, "irrelevant.");
4969
4970           return true;
4971         }
4972     }
4973   else if (STMT_VINFO_IN_PATTERN_P (stmt_info)
4974            && pattern_stmt
4975            && (STMT_VINFO_RELEVANT_P (vinfo_for_stmt (pattern_stmt))
4976                || STMT_VINFO_LIVE_P (vinfo_for_stmt (pattern_stmt))))
4977     {
4978       /* Analyze PATTERN_STMT too.  */
4979       if (vect_print_dump_info (REPORT_DETAILS))
4980         {
4981           fprintf (vect_dump, "==> examining pattern statement: ");
4982           print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
4983         }
4984
4985       if (!vect_analyze_stmt (pattern_stmt, need_to_vectorize, node))
4986         return false;
4987    }
4988
4989   if (is_pattern_stmt_p (stmt_info)
4990       && (pattern_def_stmt = STMT_VINFO_PATTERN_DEF_STMT (stmt_info))
4991       && (STMT_VINFO_RELEVANT_P (vinfo_for_stmt (pattern_def_stmt))
4992           || STMT_VINFO_LIVE_P (vinfo_for_stmt (pattern_def_stmt))))
4993     {
4994       /* Analyze def stmt of STMT if it's a pattern stmt.  */
4995       if (vect_print_dump_info (REPORT_DETAILS))
4996         {
4997           fprintf (vect_dump, "==> examining pattern def statement: ");
4998           print_gimple_stmt (vect_dump, pattern_def_stmt, 0, TDF_SLIM);
4999         }
5000
5001       if (!vect_analyze_stmt (pattern_def_stmt, need_to_vectorize, node))
5002         return false;
5003    }
5004
5005
5006   switch (STMT_VINFO_DEF_TYPE (stmt_info))
5007     {
5008       case vect_internal_def:
5009         break;
5010
5011       case vect_reduction_def:
5012       case vect_nested_cycle:
5013          gcc_assert (!bb_vinfo && (relevance == vect_used_in_outer
5014                      || relevance == vect_used_in_outer_by_reduction
5015                      || relevance == vect_unused_in_scope));
5016          break;
5017
5018       case vect_induction_def:
5019       case vect_constant_def:
5020       case vect_external_def:
5021       case vect_unknown_def_type:
5022       default:
5023         gcc_unreachable ();
5024     }
5025
5026   if (bb_vinfo)
5027     {
5028       gcc_assert (PURE_SLP_STMT (stmt_info));
5029
5030       scalar_type = TREE_TYPE (gimple_get_lhs (stmt));
5031       if (vect_print_dump_info (REPORT_DETAILS))
5032         {
5033           fprintf (vect_dump, "get vectype for scalar type:  ");
5034           print_generic_expr (vect_dump, scalar_type, TDF_SLIM);
5035         }
5036
5037       vectype = get_vectype_for_scalar_type (scalar_type);
5038       if (!vectype)
5039         {
5040           if (vect_print_dump_info (REPORT_DETAILS))
5041             {
5042                fprintf (vect_dump, "not SLPed: unsupported data-type ");
5043                print_generic_expr (vect_dump, scalar_type, TDF_SLIM);
5044             }
5045           return false;
5046         }
5047
5048       if (vect_print_dump_info (REPORT_DETAILS))
5049         {
5050           fprintf (vect_dump, "vectype:  ");
5051           print_generic_expr (vect_dump, vectype, TDF_SLIM);
5052         }
5053
5054       STMT_VINFO_VECTYPE (stmt_info) = vectype;
5055    }
5056
5057   if (STMT_VINFO_RELEVANT_P (stmt_info))
5058     {
5059       gcc_assert (!VECTOR_MODE_P (TYPE_MODE (gimple_expr_type (stmt))));
5060       gcc_assert (STMT_VINFO_VECTYPE (stmt_info));
5061       *need_to_vectorize = true;
5062     }
5063
5064    ok = true;
5065    if (!bb_vinfo
5066        && (STMT_VINFO_RELEVANT_P (stmt_info)
5067            || STMT_VINFO_DEF_TYPE (stmt_info) == vect_reduction_def))
5068       ok = (vectorizable_type_promotion (stmt, NULL, NULL, NULL)
5069             || vectorizable_type_demotion (stmt, NULL, NULL, NULL)
5070             || vectorizable_conversion (stmt, NULL, NULL, NULL)
5071             || vectorizable_shift (stmt, NULL, NULL, NULL)
5072             || vectorizable_operation (stmt, NULL, NULL, NULL)
5073             || vectorizable_assignment (stmt, NULL, NULL, NULL)
5074             || vectorizable_load (stmt, NULL, NULL, NULL, NULL)
5075             || vectorizable_call (stmt, NULL, NULL)
5076             || vectorizable_store (stmt, NULL, NULL, NULL)
5077             || vectorizable_reduction (stmt, NULL, NULL, NULL)
5078             || vectorizable_condition (stmt, NULL, NULL, NULL, 0));
5079     else
5080       {
5081         if (bb_vinfo)
5082           ok = (vectorizable_type_promotion (stmt, NULL, NULL, node)
5083                 || vectorizable_type_demotion (stmt, NULL, NULL, node)
5084                || vectorizable_shift (stmt, NULL, NULL, node)
5085                 || vectorizable_operation (stmt, NULL, NULL, node)
5086                 || vectorizable_assignment (stmt, NULL, NULL, node)
5087                 || vectorizable_load (stmt, NULL, NULL, node, NULL)
5088                 || vectorizable_store (stmt, NULL, NULL, node));
5089       }
5090
5091   if (!ok)
5092     {
5093       if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
5094         {
5095           fprintf (vect_dump, "not vectorized: relevant stmt not ");
5096           fprintf (vect_dump, "supported: ");
5097           print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
5098         }
5099
5100       return false;
5101     }
5102
5103   if (bb_vinfo)
5104     return true;
5105
5106   /* Stmts that are (also) "live" (i.e. - that are used out of the loop)
5107       need extra handling, except for vectorizable reductions.  */
5108   if (STMT_VINFO_LIVE_P (stmt_info)
5109       && STMT_VINFO_TYPE (stmt_info) != reduc_vec_info_type)
5110     ok = vectorizable_live_operation (stmt, NULL, NULL);
5111
5112   if (!ok)
5113     {
5114       if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
5115         {
5116           fprintf (vect_dump, "not vectorized: live stmt not ");
5117           fprintf (vect_dump, "supported: ");
5118           print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
5119         }
5120
5121        return false;
5122     }
5123
5124   return true;
5125 }
5126
5127
5128 /* Function vect_transform_stmt.
5129
5130    Create a vectorized stmt to replace STMT, and insert it at BSI.  */
5131
5132 bool
5133 vect_transform_stmt (gimple stmt, gimple_stmt_iterator *gsi,
5134                      bool *strided_store, slp_tree slp_node,
5135                      slp_instance slp_node_instance)
5136 {
5137   bool is_store = false;
5138   gimple vec_stmt = NULL;
5139   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
5140   bool done;
5141
5142   switch (STMT_VINFO_TYPE (stmt_info))
5143     {
5144     case type_demotion_vec_info_type:
5145       done = vectorizable_type_demotion (stmt, gsi, &vec_stmt, slp_node);
5146       gcc_assert (done);
5147       break;
5148
5149     case type_promotion_vec_info_type:
5150       done = vectorizable_type_promotion (stmt, gsi, &vec_stmt, slp_node);
5151       gcc_assert (done);
5152       break;
5153
5154     case type_conversion_vec_info_type:
5155       done = vectorizable_conversion (stmt, gsi, &vec_stmt, slp_node);
5156       gcc_assert (done);
5157       break;
5158
5159     case induc_vec_info_type:
5160       gcc_assert (!slp_node);
5161       done = vectorizable_induction (stmt, gsi, &vec_stmt);
5162       gcc_assert (done);
5163       break;
5164
5165     case shift_vec_info_type:
5166       done = vectorizable_shift (stmt, gsi, &vec_stmt, slp_node);
5167       gcc_assert (done);
5168       break;
5169
5170     case op_vec_info_type:
5171       done = vectorizable_operation (stmt, gsi, &vec_stmt, slp_node);
5172       gcc_assert (done);
5173       break;
5174
5175     case assignment_vec_info_type:
5176       done = vectorizable_assignment (stmt, gsi, &vec_stmt, slp_node);
5177       gcc_assert (done);
5178       break;
5179
5180     case load_vec_info_type:
5181       done = vectorizable_load (stmt, gsi, &vec_stmt, slp_node,
5182                                 slp_node_instance);
5183       gcc_assert (done);
5184       break;
5185
5186     case store_vec_info_type:
5187       done = vectorizable_store (stmt, gsi, &vec_stmt, slp_node);
5188       gcc_assert (done);
5189       if (STMT_VINFO_STRIDED_ACCESS (stmt_info) && !slp_node)
5190         {
5191           /* In case of interleaving, the whole chain is vectorized when the
5192              last store in the chain is reached.  Store stmts before the last
5193              one are skipped, and there vec_stmt_info shouldn't be freed
5194              meanwhile.  */
5195           *strided_store = true;
5196           if (STMT_VINFO_VEC_STMT (stmt_info))
5197             is_store = true;
5198           }
5199       else
5200         is_store = true;
5201       break;
5202
5203     case condition_vec_info_type:
5204       gcc_assert (!slp_node);
5205       done = vectorizable_condition (stmt, gsi, &vec_stmt, NULL, 0);
5206       gcc_assert (done);
5207       break;
5208
5209     case call_vec_info_type:
5210       gcc_assert (!slp_node);
5211       done = vectorizable_call (stmt, gsi, &vec_stmt);
5212       stmt = gsi_stmt (*gsi);
5213       break;
5214
5215     case reduc_vec_info_type:
5216       done = vectorizable_reduction (stmt, gsi, &vec_stmt, slp_node);
5217       gcc_assert (done);
5218       break;
5219
5220     default:
5221       if (!STMT_VINFO_LIVE_P (stmt_info))
5222         {
5223           if (vect_print_dump_info (REPORT_DETAILS))
5224             fprintf (vect_dump, "stmt not supported.");
5225           gcc_unreachable ();
5226         }
5227     }
5228
5229   /* Handle inner-loop stmts whose DEF is used in the loop-nest that
5230      is being vectorized, but outside the immediately enclosing loop.  */
5231   if (vec_stmt
5232       && STMT_VINFO_LOOP_VINFO (stmt_info)
5233       && nested_in_vect_loop_p (LOOP_VINFO_LOOP (
5234                                 STMT_VINFO_LOOP_VINFO (stmt_info)), stmt)
5235       && STMT_VINFO_TYPE (stmt_info) != reduc_vec_info_type
5236       && (STMT_VINFO_RELEVANT (stmt_info) == vect_used_in_outer
5237           || STMT_VINFO_RELEVANT (stmt_info) ==
5238                                            vect_used_in_outer_by_reduction))
5239     {
5240       struct loop *innerloop = LOOP_VINFO_LOOP (
5241                                 STMT_VINFO_LOOP_VINFO (stmt_info))->inner;
5242       imm_use_iterator imm_iter;
5243       use_operand_p use_p;
5244       tree scalar_dest;
5245       gimple exit_phi;
5246
5247       if (vect_print_dump_info (REPORT_DETAILS))
5248         fprintf (vect_dump, "Record the vdef for outer-loop vectorization.");
5249
5250       /* Find the relevant loop-exit phi-node, and reord the vec_stmt there
5251         (to be used when vectorizing outer-loop stmts that use the DEF of
5252         STMT).  */
5253       if (gimple_code (stmt) == GIMPLE_PHI)
5254         scalar_dest = PHI_RESULT (stmt);
5255       else
5256         scalar_dest = gimple_assign_lhs (stmt);
5257
5258       FOR_EACH_IMM_USE_FAST (use_p, imm_iter, scalar_dest)
5259        {
5260          if (!flow_bb_inside_loop_p (innerloop, gimple_bb (USE_STMT (use_p))))
5261            {
5262              exit_phi = USE_STMT (use_p);
5263              STMT_VINFO_VEC_STMT (vinfo_for_stmt (exit_phi)) = vec_stmt;
5264            }
5265        }
5266     }
5267
5268   /* Handle stmts whose DEF is used outside the loop-nest that is
5269      being vectorized.  */
5270   if (STMT_VINFO_LIVE_P (stmt_info)
5271       && STMT_VINFO_TYPE (stmt_info) != reduc_vec_info_type)
5272     {
5273       done = vectorizable_live_operation (stmt, gsi, &vec_stmt);
5274       gcc_assert (done);
5275     }
5276
5277   if (vec_stmt)
5278     STMT_VINFO_VEC_STMT (stmt_info) = vec_stmt;
5279
5280   return is_store;
5281 }
5282
5283
5284 /* Remove a group of stores (for SLP or interleaving), free their
5285    stmt_vec_info.  */
5286
5287 void
5288 vect_remove_stores (gimple first_stmt)
5289 {
5290   gimple next = first_stmt;
5291   gimple tmp;
5292   gimple_stmt_iterator next_si;
5293
5294   while (next)
5295     {
5296       /* Free the attached stmt_vec_info and remove the stmt.  */
5297       next_si = gsi_for_stmt (next);
5298       gsi_remove (&next_si, true);
5299       tmp = GROUP_NEXT_ELEMENT (vinfo_for_stmt (next));
5300       free_stmt_vec_info (next);
5301       next = tmp;
5302     }
5303 }
5304
5305
5306 /* Function new_stmt_vec_info.
5307
5308    Create and initialize a new stmt_vec_info struct for STMT.  */
5309
5310 stmt_vec_info
5311 new_stmt_vec_info (gimple stmt, loop_vec_info loop_vinfo,
5312                    bb_vec_info bb_vinfo)
5313 {
5314   stmt_vec_info res;
5315   res = (stmt_vec_info) xcalloc (1, sizeof (struct _stmt_vec_info));
5316
5317   STMT_VINFO_TYPE (res) = undef_vec_info_type;
5318   STMT_VINFO_STMT (res) = stmt;
5319   STMT_VINFO_LOOP_VINFO (res) = loop_vinfo;
5320   STMT_VINFO_BB_VINFO (res) = bb_vinfo;
5321   STMT_VINFO_RELEVANT (res) = vect_unused_in_scope;
5322   STMT_VINFO_LIVE_P (res) = false;
5323   STMT_VINFO_VECTYPE (res) = NULL;
5324   STMT_VINFO_VEC_STMT (res) = NULL;
5325   STMT_VINFO_VECTORIZABLE (res) = true;
5326   STMT_VINFO_IN_PATTERN_P (res) = false;
5327   STMT_VINFO_RELATED_STMT (res) = NULL;
5328   STMT_VINFO_PATTERN_DEF_STMT (res) = NULL;
5329   STMT_VINFO_DATA_REF (res) = NULL;
5330
5331   STMT_VINFO_DR_BASE_ADDRESS (res) = NULL;
5332   STMT_VINFO_DR_OFFSET (res) = NULL;
5333   STMT_VINFO_DR_INIT (res) = NULL;
5334   STMT_VINFO_DR_STEP (res) = NULL;
5335   STMT_VINFO_DR_ALIGNED_TO (res) = NULL;
5336
5337   if (gimple_code (stmt) == GIMPLE_PHI
5338       && is_loop_header_bb_p (gimple_bb (stmt)))
5339     STMT_VINFO_DEF_TYPE (res) = vect_unknown_def_type;
5340   else
5341     STMT_VINFO_DEF_TYPE (res) = vect_internal_def;
5342
5343   STMT_VINFO_SAME_ALIGN_REFS (res) = VEC_alloc (dr_p, heap, 5);
5344   STMT_VINFO_INSIDE_OF_LOOP_COST (res) = 0;
5345   STMT_VINFO_OUTSIDE_OF_LOOP_COST (res) = 0;
5346   STMT_SLP_TYPE (res) = loop_vect;
5347   GROUP_FIRST_ELEMENT (res) = NULL;
5348   GROUP_NEXT_ELEMENT (res) = NULL;
5349   GROUP_SIZE (res) = 0;
5350   GROUP_STORE_COUNT (res) = 0;
5351   GROUP_GAP (res) = 0;
5352   GROUP_SAME_DR_STMT (res) = NULL;
5353   GROUP_READ_WRITE_DEPENDENCE (res) = false;
5354
5355   return res;
5356 }
5357
5358
5359 /* Create a hash table for stmt_vec_info. */
5360
5361 void
5362 init_stmt_vec_info_vec (void)
5363 {
5364   gcc_assert (!stmt_vec_info_vec);
5365   stmt_vec_info_vec = VEC_alloc (vec_void_p, heap, 50);
5366 }
5367
5368
5369 /* Free hash table for stmt_vec_info. */
5370
5371 void
5372 free_stmt_vec_info_vec (void)
5373 {
5374   gcc_assert (stmt_vec_info_vec);
5375   VEC_free (vec_void_p, heap, stmt_vec_info_vec);
5376 }
5377
5378
5379 /* Free stmt vectorization related info.  */
5380
5381 void
5382 free_stmt_vec_info (gimple stmt)
5383 {
5384   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
5385
5386   if (!stmt_info)
5387     return;
5388
5389   VEC_free (dr_p, heap, STMT_VINFO_SAME_ALIGN_REFS (stmt_info));
5390   set_vinfo_for_stmt (stmt, NULL);
5391   free (stmt_info);
5392 }
5393
5394
5395 /* Function get_vectype_for_scalar_type_and_size.
5396
5397    Returns the vector type corresponding to SCALAR_TYPE  and SIZE as supported
5398    by the target.  */
5399
5400 static tree
5401 get_vectype_for_scalar_type_and_size (tree scalar_type, unsigned size)
5402 {
5403   enum machine_mode inner_mode = TYPE_MODE (scalar_type);
5404   enum machine_mode simd_mode;
5405   unsigned int nbytes = GET_MODE_SIZE (inner_mode);
5406   int nunits;
5407   tree vectype;
5408
5409   if (nbytes == 0)
5410     return NULL_TREE;
5411
5412   /* We can't build a vector type of elements with alignment bigger than
5413      their size.  */
5414   if (nbytes < TYPE_ALIGN_UNIT (scalar_type))
5415     return NULL_TREE;
5416
5417   /* If we'd build a vector type of elements whose mode precision doesn't
5418      match their types precision we'll get mismatched types on vector
5419      extracts via BIT_FIELD_REFs.  This effectively means we disable
5420      vectorization of bool and/or enum types in some languages.  */
5421   if (INTEGRAL_TYPE_P (scalar_type)
5422       && GET_MODE_BITSIZE (inner_mode) != TYPE_PRECISION (scalar_type))
5423     return NULL_TREE;
5424
5425   if (GET_MODE_CLASS (inner_mode) != MODE_INT
5426       && GET_MODE_CLASS (inner_mode) != MODE_FLOAT)
5427     return NULL_TREE;
5428
5429   /* We shouldn't end up building VECTOR_TYPEs of non-scalar components.
5430      When the component mode passes the above test simply use a type
5431      corresponding to that mode.  The theory is that any use that
5432      would cause problems with this will disable vectorization anyway.  */
5433   if (!SCALAR_FLOAT_TYPE_P (scalar_type)
5434       && !INTEGRAL_TYPE_P (scalar_type)
5435       && !POINTER_TYPE_P (scalar_type))
5436     scalar_type = lang_hooks.types.type_for_mode (inner_mode, 1);
5437
5438   /* If no size was supplied use the mode the target prefers.   Otherwise
5439      lookup a vector mode of the specified size.  */
5440   if (size == 0)
5441     simd_mode = targetm.vectorize.preferred_simd_mode (inner_mode);
5442   else
5443     simd_mode = mode_for_vector (inner_mode, size / nbytes);
5444   nunits = GET_MODE_SIZE (simd_mode) / nbytes;
5445   if (nunits <= 1)
5446     return NULL_TREE;
5447
5448   vectype = build_vector_type (scalar_type, nunits);
5449   if (vect_print_dump_info (REPORT_DETAILS))
5450     {
5451       fprintf (vect_dump, "get vectype with %d units of type ", nunits);
5452       print_generic_expr (vect_dump, scalar_type, TDF_SLIM);
5453     }
5454
5455   if (!vectype)
5456     return NULL_TREE;
5457
5458   if (vect_print_dump_info (REPORT_DETAILS))
5459     {
5460       fprintf (vect_dump, "vectype: ");
5461       print_generic_expr (vect_dump, vectype, TDF_SLIM);
5462     }
5463
5464   if (!VECTOR_MODE_P (TYPE_MODE (vectype))
5465       && !INTEGRAL_MODE_P (TYPE_MODE (vectype)))
5466     {
5467       if (vect_print_dump_info (REPORT_DETAILS))
5468         fprintf (vect_dump, "mode not supported by target.");
5469       return NULL_TREE;
5470     }
5471
5472   return vectype;
5473 }
5474
5475 unsigned int current_vector_size;
5476
5477 /* Function get_vectype_for_scalar_type.
5478
5479    Returns the vector type corresponding to SCALAR_TYPE as supported
5480    by the target.  */
5481
5482 tree
5483 get_vectype_for_scalar_type (tree scalar_type)
5484 {
5485   tree vectype;
5486   vectype = get_vectype_for_scalar_type_and_size (scalar_type,
5487                                                   current_vector_size);
5488   if (vectype
5489       && current_vector_size == 0)
5490     current_vector_size = GET_MODE_SIZE (TYPE_MODE (vectype));
5491   return vectype;
5492 }
5493
5494 /* Function get_same_sized_vectype
5495
5496    Returns a vector type corresponding to SCALAR_TYPE of size
5497    VECTOR_TYPE if supported by the target.  */
5498
5499 tree
5500 get_same_sized_vectype (tree scalar_type, tree vector_type)
5501 {
5502   return get_vectype_for_scalar_type_and_size
5503            (scalar_type, GET_MODE_SIZE (TYPE_MODE (vector_type)));
5504 }
5505
5506 /* Function vect_is_simple_use.
5507
5508    Input:
5509    LOOP_VINFO - the vect info of the loop that is being vectorized.
5510    BB_VINFO - the vect info of the basic block that is being vectorized.
5511    OPERAND - operand of a stmt in the loop or bb.
5512    DEF - the defining stmt in case OPERAND is an SSA_NAME.
5513
5514    Returns whether a stmt with OPERAND can be vectorized.
5515    For loops, supportable operands are constants, loop invariants, and operands
5516    that are defined by the current iteration of the loop.  Unsupportable
5517    operands are those that are defined by a previous iteration of the loop (as
5518    is the case in reduction/induction computations).
5519    For basic blocks, supportable operands are constants and bb invariants.
5520    For now, operands defined outside the basic block are not supported.  */
5521
5522 bool
5523 vect_is_simple_use (tree operand, loop_vec_info loop_vinfo,
5524                     bb_vec_info bb_vinfo, gimple *def_stmt,
5525                     tree *def, enum vect_def_type *dt)
5526 {
5527   basic_block bb;
5528   stmt_vec_info stmt_vinfo;
5529   struct loop *loop = NULL;
5530
5531   if (loop_vinfo)
5532     loop = LOOP_VINFO_LOOP (loop_vinfo);
5533
5534   *def_stmt = NULL;
5535   *def = NULL_TREE;
5536
5537   if (vect_print_dump_info (REPORT_DETAILS))
5538     {
5539       fprintf (vect_dump, "vect_is_simple_use: operand ");
5540       print_generic_expr (vect_dump, operand, TDF_SLIM);
5541     }
5542
5543   if (TREE_CODE (operand) == INTEGER_CST || TREE_CODE (operand) == REAL_CST)
5544     {
5545       *dt = vect_constant_def;
5546       return true;
5547     }
5548
5549   if (is_gimple_min_invariant (operand))
5550     {
5551       *def = operand;
5552       *dt = vect_external_def;
5553       return true;
5554     }
5555
5556   if (TREE_CODE (operand) == PAREN_EXPR)
5557     {
5558       if (vect_print_dump_info (REPORT_DETAILS))
5559         fprintf (vect_dump, "non-associatable copy.");
5560       operand = TREE_OPERAND (operand, 0);
5561     }
5562
5563   if (TREE_CODE (operand) != SSA_NAME)
5564     {
5565       if (vect_print_dump_info (REPORT_DETAILS))
5566         fprintf (vect_dump, "not ssa-name.");
5567       return false;
5568     }
5569
5570   *def_stmt = SSA_NAME_DEF_STMT (operand);
5571   if (*def_stmt == NULL)
5572     {
5573       if (vect_print_dump_info (REPORT_DETAILS))
5574         fprintf (vect_dump, "no def_stmt.");
5575       return false;
5576     }
5577
5578   if (vect_print_dump_info (REPORT_DETAILS))
5579     {
5580       fprintf (vect_dump, "def_stmt: ");
5581       print_gimple_stmt (vect_dump, *def_stmt, 0, TDF_SLIM);
5582     }
5583
5584   /* Empty stmt is expected only in case of a function argument.
5585      (Otherwise - we expect a phi_node or a GIMPLE_ASSIGN).  */
5586   if (gimple_nop_p (*def_stmt))
5587     {
5588       *def = operand;
5589       *dt = vect_external_def;
5590       return true;
5591     }
5592
5593   bb = gimple_bb (*def_stmt);
5594
5595   if ((loop && !flow_bb_inside_loop_p (loop, bb))
5596       || (!loop && bb != BB_VINFO_BB (bb_vinfo))
5597       || (!loop && gimple_code (*def_stmt) == GIMPLE_PHI))
5598     *dt = vect_external_def;
5599   else
5600     {
5601       stmt_vinfo = vinfo_for_stmt (*def_stmt);
5602       *dt = STMT_VINFO_DEF_TYPE (stmt_vinfo);
5603     }
5604
5605   if (*dt == vect_unknown_def_type)
5606     {
5607       if (vect_print_dump_info (REPORT_DETAILS))
5608         fprintf (vect_dump, "Unsupported pattern.");
5609       return false;
5610     }
5611
5612   if (vect_print_dump_info (REPORT_DETAILS))
5613     fprintf (vect_dump, "type of def: %d.",*dt);
5614
5615   switch (gimple_code (*def_stmt))
5616     {
5617     case GIMPLE_PHI:
5618       *def = gimple_phi_result (*def_stmt);
5619       break;
5620
5621     case GIMPLE_ASSIGN:
5622       *def = gimple_assign_lhs (*def_stmt);
5623       break;
5624
5625     case GIMPLE_CALL:
5626       *def = gimple_call_lhs (*def_stmt);
5627       if (*def != NULL)
5628         break;
5629       /* FALLTHRU */
5630     default:
5631       if (vect_print_dump_info (REPORT_DETAILS))
5632         fprintf (vect_dump, "unsupported defining stmt: ");
5633       return false;
5634     }
5635
5636   return true;
5637 }
5638
5639 /* Function vect_is_simple_use_1.
5640
5641    Same as vect_is_simple_use_1 but also determines the vector operand
5642    type of OPERAND and stores it to *VECTYPE.  If the definition of
5643    OPERAND is vect_uninitialized_def, vect_constant_def or
5644    vect_external_def *VECTYPE will be set to NULL_TREE and the caller
5645    is responsible to compute the best suited vector type for the
5646    scalar operand.  */
5647
5648 bool
5649 vect_is_simple_use_1 (tree operand, loop_vec_info loop_vinfo,
5650                       bb_vec_info bb_vinfo, gimple *def_stmt,
5651                       tree *def, enum vect_def_type *dt, tree *vectype)
5652 {
5653   if (!vect_is_simple_use (operand, loop_vinfo, bb_vinfo, def_stmt, def, dt))
5654     return false;
5655
5656   /* Now get a vector type if the def is internal, otherwise supply
5657      NULL_TREE and leave it up to the caller to figure out a proper
5658      type for the use stmt.  */
5659   if (*dt == vect_internal_def
5660       || *dt == vect_induction_def
5661       || *dt == vect_reduction_def
5662       || *dt == vect_double_reduction_def
5663       || *dt == vect_nested_cycle)
5664     {
5665       stmt_vec_info stmt_info = vinfo_for_stmt (*def_stmt);
5666
5667       if (STMT_VINFO_IN_PATTERN_P (stmt_info)
5668           && !STMT_VINFO_RELEVANT (stmt_info)
5669           && !STMT_VINFO_LIVE_P (stmt_info))
5670         stmt_info = vinfo_for_stmt (STMT_VINFO_RELATED_STMT (stmt_info));
5671
5672       *vectype = STMT_VINFO_VECTYPE (stmt_info);
5673       gcc_assert (*vectype != NULL_TREE);
5674     }
5675   else if (*dt == vect_uninitialized_def
5676            || *dt == vect_constant_def
5677            || *dt == vect_external_def)
5678     *vectype = NULL_TREE;
5679   else
5680     gcc_unreachable ();
5681
5682   return true;
5683 }
5684
5685
5686 /* Function supportable_widening_operation
5687
5688    Check whether an operation represented by the code CODE is a
5689    widening operation that is supported by the target platform in
5690    vector form (i.e., when operating on arguments of type VECTYPE_IN
5691    producing a result of type VECTYPE_OUT).
5692
5693    Widening operations we currently support are NOP (CONVERT), FLOAT
5694    and WIDEN_MULT.  This function checks if these operations are supported
5695    by the target platform either directly (via vector tree-codes), or via
5696    target builtins.
5697
5698    Output:
5699    - CODE1 and CODE2 are codes of vector operations to be used when
5700    vectorizing the operation, if available.
5701    - DECL1 and DECL2 are decls of target builtin functions to be used
5702    when vectorizing the operation, if available.  In this case,
5703    CODE1 and CODE2 are CALL_EXPR.
5704    - MULTI_STEP_CVT determines the number of required intermediate steps in
5705    case of multi-step conversion (like char->short->int - in that case
5706    MULTI_STEP_CVT will be 1).
5707    - INTERM_TYPES contains the intermediate type required to perform the
5708    widening operation (short in the above example).  */
5709
5710 bool
5711 supportable_widening_operation (enum tree_code code, gimple stmt,
5712                                 tree vectype_out, tree vectype_in,
5713                                 tree *decl1, tree *decl2,
5714                                 enum tree_code *code1, enum tree_code *code2,
5715                                 int *multi_step_cvt,
5716                                 VEC (tree, heap) **interm_types)
5717 {
5718   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
5719   loop_vec_info loop_info = STMT_VINFO_LOOP_VINFO (stmt_info);
5720   struct loop *vect_loop = NULL;
5721   bool ordered_p;
5722   enum machine_mode vec_mode;
5723   enum insn_code icode1, icode2;
5724   optab optab1, optab2;
5725   tree vectype = vectype_in;
5726   tree wide_vectype = vectype_out;
5727   enum tree_code c1, c2;
5728
5729   if (loop_info)
5730     vect_loop = LOOP_VINFO_LOOP (loop_info);
5731
5732   /* The result of a vectorized widening operation usually requires two vectors
5733      (because the widened results do not fit int one vector). The generated
5734      vector results would normally be expected to be generated in the same
5735      order as in the original scalar computation, i.e. if 8 results are
5736      generated in each vector iteration, they are to be organized as follows:
5737         vect1: [res1,res2,res3,res4], vect2: [res5,res6,res7,res8].
5738
5739      However, in the special case that the result of the widening operation is
5740      used in a reduction computation only, the order doesn't matter (because
5741      when vectorizing a reduction we change the order of the computation).
5742      Some targets can take advantage of this and generate more efficient code.
5743      For example, targets like Altivec, that support widen_mult using a sequence
5744      of {mult_even,mult_odd} generate the following vectors:
5745         vect1: [res1,res3,res5,res7], vect2: [res2,res4,res6,res8].
5746
5747      When vectorizing outer-loops, we execute the inner-loop sequentially
5748      (each vectorized inner-loop iteration contributes to VF outer-loop
5749      iterations in parallel).  We therefore don't allow to change the order
5750      of the computation in the inner-loop during outer-loop vectorization.  */
5751
5752    if (vect_loop
5753        && STMT_VINFO_RELEVANT (stmt_info) == vect_used_by_reduction
5754        && !nested_in_vect_loop_p (vect_loop, stmt))
5755      ordered_p = false;
5756    else
5757      ordered_p = true;
5758
5759   if (!ordered_p
5760       && code == WIDEN_MULT_EXPR
5761       && targetm.vectorize.builtin_mul_widen_even
5762       && targetm.vectorize.builtin_mul_widen_even (vectype)
5763       && targetm.vectorize.builtin_mul_widen_odd
5764       && targetm.vectorize.builtin_mul_widen_odd (vectype))
5765     {
5766       if (vect_print_dump_info (REPORT_DETAILS))
5767         fprintf (vect_dump, "Unordered widening operation detected.");
5768
5769       *code1 = *code2 = CALL_EXPR;
5770       *decl1 = targetm.vectorize.builtin_mul_widen_even (vectype);
5771       *decl2 = targetm.vectorize.builtin_mul_widen_odd (vectype);
5772       return true;
5773     }
5774
5775   switch (code)
5776     {
5777     case WIDEN_MULT_EXPR:
5778       if (BYTES_BIG_ENDIAN)
5779         {
5780           c1 = VEC_WIDEN_MULT_HI_EXPR;
5781           c2 = VEC_WIDEN_MULT_LO_EXPR;
5782         }
5783       else
5784         {
5785           c2 = VEC_WIDEN_MULT_HI_EXPR;
5786           c1 = VEC_WIDEN_MULT_LO_EXPR;
5787         }
5788       break;
5789
5790     CASE_CONVERT:
5791       if (BYTES_BIG_ENDIAN)
5792         {
5793           c1 = VEC_UNPACK_HI_EXPR;
5794           c2 = VEC_UNPACK_LO_EXPR;
5795         }
5796       else
5797         {
5798           c2 = VEC_UNPACK_HI_EXPR;
5799           c1 = VEC_UNPACK_LO_EXPR;
5800         }
5801       break;
5802
5803     case FLOAT_EXPR:
5804       if (BYTES_BIG_ENDIAN)
5805         {
5806           c1 = VEC_UNPACK_FLOAT_HI_EXPR;
5807           c2 = VEC_UNPACK_FLOAT_LO_EXPR;
5808         }
5809       else
5810         {
5811           c2 = VEC_UNPACK_FLOAT_HI_EXPR;
5812           c1 = VEC_UNPACK_FLOAT_LO_EXPR;
5813         }
5814       break;
5815
5816     case FIX_TRUNC_EXPR:
5817       /* ??? Not yet implemented due to missing VEC_UNPACK_FIX_TRUNC_HI_EXPR/
5818          VEC_UNPACK_FIX_TRUNC_LO_EXPR tree codes and optabs used for
5819          computing the operation.  */
5820       return false;
5821
5822     default:
5823       gcc_unreachable ();
5824     }
5825
5826   if (code == FIX_TRUNC_EXPR)
5827     {
5828       /* The signedness is determined from output operand.  */
5829       optab1 = optab_for_tree_code (c1, vectype_out, optab_default);
5830       optab2 = optab_for_tree_code (c2, vectype_out, optab_default);
5831     }
5832   else
5833     {
5834       optab1 = optab_for_tree_code (c1, vectype, optab_default);
5835       optab2 = optab_for_tree_code (c2, vectype, optab_default);
5836     }
5837
5838   if (!optab1 || !optab2)
5839     return false;
5840
5841   vec_mode = TYPE_MODE (vectype);
5842   if ((icode1 = optab_handler (optab1, vec_mode)) == CODE_FOR_nothing
5843        || (icode2 = optab_handler (optab2, vec_mode)) == CODE_FOR_nothing)
5844     return false;
5845
5846   /* Check if it's a multi-step conversion that can be done using intermediate
5847      types.  */
5848   if (insn_data[icode1].operand[0].mode != TYPE_MODE (wide_vectype)
5849        || insn_data[icode2].operand[0].mode != TYPE_MODE (wide_vectype))
5850     {
5851       int i;
5852       tree prev_type = vectype, intermediate_type;
5853       enum machine_mode intermediate_mode, prev_mode = vec_mode;
5854       optab optab3, optab4;
5855
5856       if (!CONVERT_EXPR_CODE_P (code))
5857         return false;
5858
5859       *code1 = c1;
5860       *code2 = c2;
5861
5862       /* We assume here that there will not be more than MAX_INTERM_CVT_STEPS
5863          intermediate steps in promotion sequence.  We try
5864          MAX_INTERM_CVT_STEPS to get to NARROW_VECTYPE, and fail if we do
5865          not.  */
5866       *interm_types = VEC_alloc (tree, heap, MAX_INTERM_CVT_STEPS);
5867       for (i = 0; i < 3; i++)
5868         {
5869           intermediate_mode = insn_data[icode1].operand[0].mode;
5870           intermediate_type = lang_hooks.types.type_for_mode (intermediate_mode,
5871                                                      TYPE_UNSIGNED (prev_type));
5872           optab3 = optab_for_tree_code (c1, intermediate_type, optab_default);
5873           optab4 = optab_for_tree_code (c2, intermediate_type, optab_default);
5874
5875           if (!optab3 || !optab4
5876               || ((icode1 = optab_handler (optab1, prev_mode))
5877                   == CODE_FOR_nothing)
5878               || insn_data[icode1].operand[0].mode != intermediate_mode
5879               || ((icode2 = optab_handler (optab2, prev_mode))
5880                   == CODE_FOR_nothing)
5881               || insn_data[icode2].operand[0].mode != intermediate_mode
5882               || ((icode1 = optab_handler (optab3, intermediate_mode))
5883                   == CODE_FOR_nothing)
5884               || ((icode2 = optab_handler (optab4, intermediate_mode))
5885                   == CODE_FOR_nothing))
5886             return false;
5887
5888           VEC_quick_push (tree, *interm_types, intermediate_type);
5889           (*multi_step_cvt)++;
5890
5891           if (insn_data[icode1].operand[0].mode == TYPE_MODE (wide_vectype)
5892               && insn_data[icode2].operand[0].mode == TYPE_MODE (wide_vectype))
5893             return true;
5894
5895           prev_type = intermediate_type;
5896           prev_mode = intermediate_mode;
5897         }
5898
5899        return false;
5900     }
5901
5902   *code1 = c1;
5903   *code2 = c2;
5904   return true;
5905 }
5906
5907
5908 /* Function supportable_narrowing_operation
5909
5910    Check whether an operation represented by the code CODE is a
5911    narrowing operation that is supported by the target platform in
5912    vector form (i.e., when operating on arguments of type VECTYPE_IN
5913    and producing a result of type VECTYPE_OUT).
5914
5915    Narrowing operations we currently support are NOP (CONVERT) and
5916    FIX_TRUNC.  This function checks if these operations are supported by
5917    the target platform directly via vector tree-codes.
5918
5919    Output:
5920    - CODE1 is the code of a vector operation to be used when
5921    vectorizing the operation, if available.
5922    - MULTI_STEP_CVT determines the number of required intermediate steps in
5923    case of multi-step conversion (like int->short->char - in that case
5924    MULTI_STEP_CVT will be 1).
5925    - INTERM_TYPES contains the intermediate type required to perform the
5926    narrowing operation (short in the above example).   */
5927
5928 bool
5929 supportable_narrowing_operation (enum tree_code code,
5930                                  tree vectype_out, tree vectype_in,
5931                                  enum tree_code *code1, int *multi_step_cvt,
5932                                  VEC (tree, heap) **interm_types)
5933 {
5934   enum machine_mode vec_mode;
5935   enum insn_code icode1;
5936   optab optab1, interm_optab;
5937   tree vectype = vectype_in;
5938   tree narrow_vectype = vectype_out;
5939   enum tree_code c1;
5940   tree intermediate_type, prev_type;
5941   int i;
5942
5943   switch (code)
5944     {
5945     CASE_CONVERT:
5946       c1 = VEC_PACK_TRUNC_EXPR;
5947       break;
5948
5949     case FIX_TRUNC_EXPR:
5950       c1 = VEC_PACK_FIX_TRUNC_EXPR;
5951       break;
5952
5953     case FLOAT_EXPR:
5954       /* ??? Not yet implemented due to missing VEC_PACK_FLOAT_EXPR
5955          tree code and optabs used for computing the operation.  */
5956       return false;
5957
5958     default:
5959       gcc_unreachable ();
5960     }
5961
5962   if (code == FIX_TRUNC_EXPR)
5963     /* The signedness is determined from output operand.  */
5964     optab1 = optab_for_tree_code (c1, vectype_out, optab_default);
5965   else
5966     optab1 = optab_for_tree_code (c1, vectype, optab_default);
5967
5968   if (!optab1)
5969     return false;
5970
5971   vec_mode = TYPE_MODE (vectype);
5972   if ((icode1 = optab_handler (optab1, vec_mode)) == CODE_FOR_nothing)
5973     return false;
5974
5975   /* Check if it's a multi-step conversion that can be done using intermediate
5976      types.  */
5977   if (insn_data[icode1].operand[0].mode != TYPE_MODE (narrow_vectype))
5978     {
5979       enum machine_mode intermediate_mode, prev_mode = vec_mode;
5980
5981       *code1 = c1;
5982       prev_type = vectype;
5983       /* We assume here that there will not be more than MAX_INTERM_CVT_STEPS
5984          intermediate steps in promotion sequence.  We try
5985          MAX_INTERM_CVT_STEPS to get to NARROW_VECTYPE, and fail if we do
5986          not.  */
5987       *interm_types = VEC_alloc (tree, heap, MAX_INTERM_CVT_STEPS);
5988       for (i = 0; i < 3; i++)
5989         {
5990           intermediate_mode = insn_data[icode1].operand[0].mode;
5991           intermediate_type = lang_hooks.types.type_for_mode (intermediate_mode,
5992                                                      TYPE_UNSIGNED (prev_type));
5993           interm_optab = optab_for_tree_code (c1, intermediate_type,
5994                                               optab_default);
5995           if (!interm_optab
5996               || ((icode1 = optab_handler (optab1, prev_mode))
5997                   == CODE_FOR_nothing)
5998               || insn_data[icode1].operand[0].mode != intermediate_mode
5999               || ((icode1 = optab_handler (interm_optab, intermediate_mode))
6000                   == CODE_FOR_nothing))
6001             return false;
6002
6003           VEC_quick_push (tree, *interm_types, intermediate_type);
6004           (*multi_step_cvt)++;
6005
6006           if (insn_data[icode1].operand[0].mode == TYPE_MODE (narrow_vectype))
6007             return true;
6008
6009           prev_type = intermediate_type;
6010           prev_mode = intermediate_mode;
6011         }
6012
6013       return false;
6014     }
6015
6016   *code1 = c1;
6017   return true;
6018 }