OSDN Git Service

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