OSDN Git Service

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