OSDN Git Service

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