OSDN Git Service

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