OSDN Git Service

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