OSDN Git Service

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