OSDN Git Service

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