OSDN Git Service

* tree-vect-transform.c (vect_get_slp_defs): Don't build a vector
[pf3gnuchains/gcc-fork.git] / gcc / tree-vect-transform.c
1 /* Transformation Utilities for Loop Vectorization.
2    Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
3    Contributed by Dorit Naishlos <dorit@il.ibm.com>
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
10 version.
11
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3.  If not see
19 <http://www.gnu.org/licenses/>.  */
20
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "ggc.h"
26 #include "tree.h"
27 #include "target.h"
28 #include "rtl.h"
29 #include "basic-block.h"
30 #include "diagnostic.h"
31 #include "tree-flow.h"
32 #include "tree-dump.h"
33 #include "timevar.h"
34 #include "cfgloop.h"
35 #include "expr.h"
36 #include "optabs.h"
37 #include "params.h"
38 #include "recog.h"
39 #include "tree-data-ref.h"
40 #include "tree-chrec.h"
41 #include "tree-scalar-evolution.h"
42 #include "tree-vectorizer.h"
43 #include "langhooks.h"
44 #include "tree-pass.h"
45 #include "toplev.h"
46 #include "real.h"
47
48 /* Utility functions for the code transformation.  */
49 static bool vect_transform_stmt (tree, block_stmt_iterator *, bool *, slp_tree);
50 static tree vect_create_destination_var (tree, tree);
51 static tree vect_create_data_ref_ptr 
52   (tree, struct loop*, tree, tree *, tree *, bool, tree, bool *); 
53 static tree vect_create_addr_base_for_vector_ref 
54   (tree, tree *, tree, struct loop *);
55 static tree vect_get_new_vect_var (tree, enum vect_var_kind, const char *);
56 static tree vect_get_vec_def_for_operand (tree, tree, tree *);
57 static tree vect_init_vector (tree, tree, tree, block_stmt_iterator *);
58 static void vect_finish_stmt_generation 
59   (tree stmt, tree vec_stmt, block_stmt_iterator *);
60 static bool vect_is_simple_cond (tree, loop_vec_info); 
61 static void vect_create_epilog_for_reduction (tree, tree, enum tree_code, tree);
62 static tree get_initial_def_for_reduction (tree, tree, tree *);
63
64 /* Utility function dealing with loop peeling (not peeling itself).  */
65 static void vect_generate_tmps_on_preheader 
66   (loop_vec_info, tree *, tree *, tree *);
67 static tree vect_build_loop_niters (loop_vec_info);
68 static void vect_update_ivs_after_vectorizer (loop_vec_info, tree, edge); 
69 static tree vect_gen_niters_for_prolog_loop (loop_vec_info, tree);
70 static void vect_update_init_of_dr (struct data_reference *, tree niters);
71 static void vect_update_inits_of_drs (loop_vec_info, tree);
72 static int vect_min_worthwhile_factor (enum tree_code);
73
74
75 static int
76 cost_for_stmt (tree stmt)
77 {
78   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
79
80   switch (STMT_VINFO_TYPE (stmt_info))
81   {
82   case load_vec_info_type:
83     return TARG_SCALAR_LOAD_COST;
84   case store_vec_info_type:
85     return TARG_SCALAR_STORE_COST;
86   case op_vec_info_type:
87   case condition_vec_info_type:
88   case assignment_vec_info_type:
89   case reduc_vec_info_type:
90   case induc_vec_info_type:
91   case type_promotion_vec_info_type:
92   case type_demotion_vec_info_type:
93   case type_conversion_vec_info_type:
94   case call_vec_info_type:
95     return TARG_SCALAR_STMT_COST;
96   case undef_vec_info_type:
97   default:
98     gcc_unreachable ();
99   }
100 }
101
102
103 /* Function vect_estimate_min_profitable_iters
104
105    Return the number of iterations required for the vector version of the
106    loop to be profitable relative to the cost of the scalar version of the
107    loop.
108
109    TODO: Take profile info into account before making vectorization
110    decisions, if available.  */
111
112 int
113 vect_estimate_min_profitable_iters (loop_vec_info loop_vinfo)
114 {
115   int i;
116   int min_profitable_iters;
117   int peel_iters_prologue;
118   int peel_iters_epilogue;
119   int vec_inside_cost = 0;
120   int vec_outside_cost = 0;
121   int scalar_single_iter_cost = 0;
122   int vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
123   struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
124   basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo);
125   int nbbs = loop->num_nodes;
126   int byte_misalign;
127   int peel_guard_costs = 0;
128   int innerloop_iters = 0, factor;
129   VEC (slp_instance, heap) *slp_instances;
130   slp_instance instance;
131
132   /* Cost model disabled.  */
133   if (!flag_vect_cost_model)
134     {
135       if (vect_print_dump_info (REPORT_DETAILS))
136         fprintf (vect_dump, "cost model disabled.");      
137       return 0;
138     }
139
140   /* Requires loop versioning tests to handle misalignment.
141      FIXME: Make cost depend on number of stmts in may_misalign list.  */
142
143   if (VEC_length (tree, LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo)))
144     {
145       vec_outside_cost += TARG_COND_TAKEN_BRANCH_COST;
146       if (vect_print_dump_info (REPORT_DETAILS))
147         fprintf (vect_dump, "cost model: Adding cost of checks for loop "
148                  "versioning.\n");
149     }
150
151   /* Count statements in scalar loop.  Using this as scalar cost for a single
152      iteration for now.
153
154      TODO: Add outer loop support.
155
156      TODO: Consider assigning different costs to different scalar
157      statements.  */
158
159   /* FORNOW.  */
160   if (loop->inner)
161     innerloop_iters = 50; /* FIXME */
162
163   for (i = 0; i < nbbs; i++)
164     {
165       block_stmt_iterator si;
166       basic_block bb = bbs[i];
167
168       if (bb->loop_father == loop->inner)
169         factor = innerloop_iters;
170       else
171         factor = 1;
172
173       for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
174         {
175           tree stmt = bsi_stmt (si);
176           stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
177           if (!STMT_VINFO_RELEVANT_P (stmt_info)
178               && !STMT_VINFO_LIVE_P (stmt_info))
179             continue;
180           scalar_single_iter_cost += cost_for_stmt (stmt) * factor;
181           vec_inside_cost += STMT_VINFO_INSIDE_OF_LOOP_COST (stmt_info) * factor;
182           /* FIXME: for stmts in the inner-loop in outer-loop vectorization,
183              some of the "outside" costs are generated inside the outer-loop.  */
184           vec_outside_cost += STMT_VINFO_OUTSIDE_OF_LOOP_COST (stmt_info);
185         }
186     }
187
188   /* Add additional cost for the peeled instructions in prologue and epilogue
189      loop.
190
191      FORNOW: If we dont know the value of peel_iters for prologue or epilogue
192      at compile-time - we assume it's vf/2 (the worst would be vf-1).
193
194      TODO: Build an expression that represents peel_iters for prologue and
195      epilogue to be used in a run-time test.  */
196
197   byte_misalign = LOOP_PEELING_FOR_ALIGNMENT (loop_vinfo);
198
199   if (byte_misalign < 0)
200     {
201       peel_iters_prologue = vf/2;
202       if (vect_print_dump_info (REPORT_DETAILS))
203         fprintf (vect_dump, "cost model: "
204                  "prologue peel iters set to vf/2.");
205
206       /* If peeling for alignment is unknown, loop bound of main loop becomes
207          unknown.  */
208       peel_iters_epilogue = vf/2;
209       if (vect_print_dump_info (REPORT_DETAILS))
210         fprintf (vect_dump, "cost model: "
211                  "epilogue peel iters set to vf/2 because "
212                  "peeling for alignment is unknown .");
213
214       /* If peeled iterations are unknown, count a taken branch and a not taken
215          branch per peeled loop. Even if scalar loop iterations are known, 
216          vector iterations are not known since peeled prologue iterations are
217          not known. Hence guards remain the same.  */
218       peel_guard_costs +=  2 * (TARG_COND_TAKEN_BRANCH_COST
219                                + TARG_COND_NOT_TAKEN_BRANCH_COST);
220
221     }
222   else 
223     {
224       if (byte_misalign)
225         {
226           struct data_reference *dr = LOOP_VINFO_UNALIGNED_DR (loop_vinfo);
227           int element_size = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (DR_REF (dr))));
228           tree vectype = STMT_VINFO_VECTYPE (vinfo_for_stmt (DR_STMT (dr)));
229           int nelements = TYPE_VECTOR_SUBPARTS (vectype);
230
231           peel_iters_prologue = nelements - (byte_misalign / element_size);
232         }
233       else
234         peel_iters_prologue = 0;
235
236       if (!LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo))
237         {
238           peel_iters_epilogue = vf/2;
239           if (vect_print_dump_info (REPORT_DETAILS))
240             fprintf (vect_dump, "cost model: "
241                      "epilogue peel iters set to vf/2 because "
242                      "loop iterations are unknown .");
243
244           /* If peeled iterations are known but number of scalar loop
245              iterations are unknown, count a taken branch per peeled loop.  */
246           peel_guard_costs +=  2 * TARG_COND_TAKEN_BRANCH_COST;
247
248         }
249       else      
250         {
251           int niters = LOOP_VINFO_INT_NITERS (loop_vinfo);
252           peel_iters_prologue = niters < peel_iters_prologue ? 
253                                         niters : peel_iters_prologue;
254           peel_iters_epilogue = (niters - peel_iters_prologue) % vf;
255         }
256     }
257
258   vec_outside_cost += (peel_iters_prologue * scalar_single_iter_cost)
259                       + (peel_iters_epilogue * scalar_single_iter_cost)
260                       + peel_guard_costs;
261
262   /* Allow targets add additional (outside-of-loop) costs. FORNOW, the only
263      information we provide for the target is whether testing against the
264      threshold involves a runtime test.  */
265   if (targetm.vectorize.builtin_vectorization_cost)
266     {
267       bool runtime_test = false;
268
269       /* If the number of iterations is unknown, or the
270          peeling-for-misalignment amount is unknown, we eill have to generate
271          a runtime test to test the loop count against the threshold.  */
272       if (!LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
273           || (byte_misalign < 0))
274         runtime_test = true;
275       vec_outside_cost +=
276         targetm.vectorize.builtin_vectorization_cost (runtime_test);
277       if (vect_print_dump_info (REPORT_DETAILS))
278         fprintf (vect_dump, "cost model : Adding target out-of-loop cost = %d",
279                   targetm.vectorize.builtin_vectorization_cost (runtime_test));
280     }
281
282   /* Add SLP costs.  */
283   slp_instances = LOOP_VINFO_SLP_INSTANCES (loop_vinfo);
284   for (i = 0; VEC_iterate (slp_instance, slp_instances, i, instance); i++)
285     {
286       vec_outside_cost += SLP_INSTANCE_OUTSIDE_OF_LOOP_COST (instance);
287       vec_inside_cost += SLP_INSTANCE_INSIDE_OF_LOOP_COST (instance);
288     }
289
290   /* Calculate number of iterations required to make the vector version 
291      profitable, relative to the loop bodies only. The following condition
292      must hold true: ((SIC*VF)-VIC)*niters > VOC*VF, where
293      SIC = scalar iteration cost, VIC = vector iteration cost,
294      VOC = vector outside cost and VF = vectorization factor.  */
295
296   if ((scalar_single_iter_cost * vf) > vec_inside_cost)
297     {
298       if (vec_outside_cost <= 0)
299         min_profitable_iters = 1;
300       else
301         {
302           min_profitable_iters = (vec_outside_cost * vf 
303                                   - vec_inside_cost * peel_iters_prologue
304                                   - vec_inside_cost * peel_iters_epilogue)
305                                  / ((scalar_single_iter_cost * vf)
306                                     - vec_inside_cost);
307
308           if ((scalar_single_iter_cost * vf * min_profitable_iters)
309               <= ((vec_inside_cost * min_profitable_iters)
310                   + (vec_outside_cost * vf)))
311             min_profitable_iters++;
312         }
313     }
314   /* vector version will never be profitable.  */
315   else
316     {
317       if (vect_print_dump_info (REPORT_DETAILS))
318         fprintf (vect_dump, "cost model: vector iteration cost = %d "
319                  "is divisible by scalar iteration cost = %d by a factor "
320                  "greater than or equal to the vectorization factor = %d .",
321                  vec_inside_cost, scalar_single_iter_cost, vf);
322       return -1;
323     }
324
325   if (vect_print_dump_info (REPORT_DETAILS))
326     {
327       fprintf (vect_dump, "Cost model analysis: \n");
328       fprintf (vect_dump, "  Vector inside of loop cost: %d\n",
329                vec_inside_cost);
330       fprintf (vect_dump, "  Vector outside of loop cost: %d\n",
331                vec_outside_cost);
332       fprintf (vect_dump, "  Scalar cost: %d\n", scalar_single_iter_cost);
333       fprintf (vect_dump, "  prologue iterations: %d\n",
334                peel_iters_prologue);
335       fprintf (vect_dump, "  epilogue iterations: %d\n",
336                peel_iters_epilogue);
337       fprintf (vect_dump, "  Calculated minimum iters for profitability: %d\n",
338                min_profitable_iters);
339     }
340
341   min_profitable_iters = 
342         min_profitable_iters < vf ? vf : min_profitable_iters;
343
344   /* Because the condition we create is:
345      if (niters <= min_profitable_iters)
346        then skip the vectorized loop.  */
347   min_profitable_iters--;
348
349   if (vect_print_dump_info (REPORT_DETAILS))
350     fprintf (vect_dump, "  Profitability threshold = %d\n",
351              min_profitable_iters);
352     
353   return min_profitable_iters;
354 }
355
356
357 /* TODO: Close dependency between vect_model_*_cost and vectorizable_* 
358    functions. Design better to avoid maintenance issues.  */
359     
360 /* Function vect_model_reduction_cost.  
361
362    Models cost for a reduction operation, including the vector ops 
363    generated within the strip-mine loop, the initial definition before
364    the loop, and the epilogue code that must be generated.  */
365
366 static void
367 vect_model_reduction_cost (stmt_vec_info stmt_info, enum tree_code reduc_code,
368                            int ncopies)
369 {
370   int outer_cost = 0;
371   enum tree_code code;
372   optab optab;
373   tree vectype;
374   tree orig_stmt;
375   tree reduction_op;
376   enum machine_mode mode;
377   tree operation = GIMPLE_STMT_OPERAND (STMT_VINFO_STMT (stmt_info), 1);
378   int op_type = TREE_CODE_LENGTH (TREE_CODE (operation));
379   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
380   struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
381
382   /* Cost of reduction op inside loop.  */
383   STMT_VINFO_INSIDE_OF_LOOP_COST (stmt_info) += ncopies * TARG_VEC_STMT_COST;
384
385   reduction_op = TREE_OPERAND (operation, op_type-1);
386   vectype = get_vectype_for_scalar_type (TREE_TYPE (reduction_op));
387   mode = TYPE_MODE (vectype);
388   orig_stmt = STMT_VINFO_RELATED_STMT (stmt_info);
389
390   if (!orig_stmt) 
391     orig_stmt = STMT_VINFO_STMT (stmt_info);
392
393   code = TREE_CODE (GIMPLE_STMT_OPERAND (orig_stmt, 1));
394
395   /* Add in cost for initial definition.  */
396   outer_cost += TARG_SCALAR_TO_VEC_COST;
397
398   /* Determine cost of epilogue code.
399
400      We have a reduction operator that will reduce the vector in one statement.
401      Also requires scalar extract.  */
402
403   if (!nested_in_vect_loop_p (loop, orig_stmt))
404     {
405       if (reduc_code < NUM_TREE_CODES) 
406         outer_cost += TARG_VEC_STMT_COST + TARG_VEC_TO_SCALAR_COST;
407       else 
408         {
409           int vec_size_in_bits = tree_low_cst (TYPE_SIZE (vectype), 1);
410           tree bitsize =
411             TYPE_SIZE (TREE_TYPE ( GIMPLE_STMT_OPERAND (orig_stmt, 0)));
412           int element_bitsize = tree_low_cst (bitsize, 1);
413           int nelements = vec_size_in_bits / element_bitsize;
414
415           optab = optab_for_tree_code (code, vectype);
416
417           /* We have a whole vector shift available.  */
418           if (VECTOR_MODE_P (mode)
419               && optab_handler (optab, mode)->insn_code != CODE_FOR_nothing
420               && optab_handler (vec_shr_optab, mode)->insn_code != CODE_FOR_nothing)
421             /* Final reduction via vector shifts and the reduction operator. Also
422                requires scalar extract.  */
423             outer_cost += ((exact_log2(nelements) * 2) * TARG_VEC_STMT_COST
424                                 + TARG_VEC_TO_SCALAR_COST); 
425           else
426             /* Use extracts and reduction op for final reduction.  For N elements,
427                we have N extracts and N-1 reduction ops.  */
428             outer_cost += ((nelements + nelements - 1) * TARG_VEC_STMT_COST);
429         }
430     }
431
432   STMT_VINFO_OUTSIDE_OF_LOOP_COST (stmt_info) = outer_cost;
433
434   if (vect_print_dump_info (REPORT_DETAILS))
435     fprintf (vect_dump, "vect_model_reduction_cost: inside_cost = %d, "
436              "outside_cost = %d .", STMT_VINFO_INSIDE_OF_LOOP_COST (stmt_info),
437              STMT_VINFO_OUTSIDE_OF_LOOP_COST (stmt_info));
438 }
439
440
441 /* Function vect_model_induction_cost.
442
443    Models cost for induction operations.  */
444
445 static void
446 vect_model_induction_cost (stmt_vec_info stmt_info, int ncopies)
447 {
448   /* loop cost for vec_loop.  */
449   STMT_VINFO_INSIDE_OF_LOOP_COST (stmt_info) = ncopies * TARG_VEC_STMT_COST;
450   /* prologue cost for vec_init and vec_step.  */
451   STMT_VINFO_OUTSIDE_OF_LOOP_COST (stmt_info) = 2 * TARG_SCALAR_TO_VEC_COST;
452   
453   if (vect_print_dump_info (REPORT_DETAILS))
454     fprintf (vect_dump, "vect_model_induction_cost: inside_cost = %d, "
455              "outside_cost = %d .", STMT_VINFO_INSIDE_OF_LOOP_COST (stmt_info),
456              STMT_VINFO_OUTSIDE_OF_LOOP_COST (stmt_info));
457 }
458
459
460 /* Function vect_model_simple_cost.  
461
462    Models cost for simple operations, i.e. those that only emit ncopies of a 
463    single op.  Right now, this does not account for multiple insns that could
464    be generated for the single vector op.  We will handle that shortly.  */
465
466 void
467 vect_model_simple_cost (stmt_vec_info stmt_info, int ncopies, 
468                         enum vect_def_type *dt, slp_tree slp_node)
469 {
470   int i;
471   int inside_cost = 0, outside_cost = 0;
472
473   inside_cost = ncopies * TARG_VEC_STMT_COST;
474
475   /* FORNOW: Assuming maximum 2 args per stmts.  */
476   for (i = 0; i < 2; i++)
477     {
478       if (dt[i] == vect_constant_def || dt[i] == vect_invariant_def)
479         outside_cost += TARG_SCALAR_TO_VEC_COST; 
480     }
481   
482   if (vect_print_dump_info (REPORT_DETAILS))
483     fprintf (vect_dump, "vect_model_simple_cost: inside_cost = %d, "
484              "outside_cost = %d .", inside_cost, outside_cost);
485
486   /* Set the costs either in STMT_INFO or SLP_NODE (if exists).  */
487   stmt_vinfo_set_inside_of_loop_cost (stmt_info, slp_node, inside_cost);
488   stmt_vinfo_set_outside_of_loop_cost (stmt_info, slp_node, outside_cost);
489 }
490
491
492 /* Function vect_cost_strided_group_size 
493  
494    For strided load or store, return the group_size only if it is the first
495    load or store of a group, else return 1.  This ensures that group size is
496    only returned once per group.  */
497
498 static int
499 vect_cost_strided_group_size (stmt_vec_info stmt_info)
500 {
501   tree first_stmt = DR_GROUP_FIRST_DR (stmt_info);
502
503   if (first_stmt == STMT_VINFO_STMT (stmt_info))
504     return DR_GROUP_SIZE (stmt_info);
505
506   return 1;
507 }
508
509
510 /* Function vect_model_store_cost
511
512    Models cost for stores.  In the case of strided accesses, one access
513    has the overhead of the strided access attributed to it.  */
514
515 void
516 vect_model_store_cost (stmt_vec_info stmt_info, int ncopies, 
517                        enum vect_def_type dt, slp_tree slp_node)
518 {
519   int group_size;
520   int inside_cost = 0, outside_cost = 0;
521
522   if (dt == vect_constant_def || dt == vect_invariant_def)
523     outside_cost = TARG_SCALAR_TO_VEC_COST;
524
525   /* Strided access?  */
526   if (DR_GROUP_FIRST_DR (stmt_info)) 
527     group_size = vect_cost_strided_group_size (stmt_info);
528   /* Not a strided access.  */
529   else
530     group_size = 1;
531
532   /* Is this an access in a group of stores, which provide strided access?  
533      If so, add in the cost of the permutes.  */
534   if (group_size > 1) 
535     {
536       /* Uses a high and low interleave operation for each needed permute.  */
537       inside_cost = ncopies * exact_log2(group_size) * group_size 
538              * TARG_VEC_STMT_COST;
539
540       if (vect_print_dump_info (REPORT_DETAILS))
541         fprintf (vect_dump, "vect_model_store_cost: strided group_size = %d .",
542                  group_size);
543
544     }
545
546   /* Costs of the stores.  */
547   inside_cost += ncopies * TARG_VEC_STORE_COST;
548
549   if (vect_print_dump_info (REPORT_DETAILS))
550     fprintf (vect_dump, "vect_model_store_cost: inside_cost = %d, "
551              "outside_cost = %d .", inside_cost, outside_cost);
552
553   /* Set the costs either in STMT_INFO or SLP_NODE (if exists).  */
554   stmt_vinfo_set_inside_of_loop_cost (stmt_info, slp_node, inside_cost);
555   stmt_vinfo_set_outside_of_loop_cost (stmt_info, slp_node, outside_cost);
556 }
557
558
559 /* Function vect_model_load_cost
560
561    Models cost for loads.  In the case of strided accesses, the last access
562    has the overhead of the strided access attributed to it.  Since unaligned
563    accesses are supported for loads, we also account for the costs of the 
564    access scheme chosen.  */
565
566 void
567 vect_model_load_cost (stmt_vec_info stmt_info, int ncopies, slp_tree slp_node)
568                  
569 {
570   int group_size;
571   int alignment_support_cheme;
572   tree first_stmt;
573   struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info), *first_dr;
574   int inside_cost = 0, outside_cost = 0;
575
576   /* Strided accesses?  */
577   first_stmt = DR_GROUP_FIRST_DR (stmt_info);
578   if (first_stmt && !slp_node)
579     {
580       group_size = vect_cost_strided_group_size (stmt_info);
581       first_dr = STMT_VINFO_DATA_REF (vinfo_for_stmt (first_stmt));
582     }
583   /* Not a strided access.  */
584   else
585     {
586       group_size = 1;
587       first_dr = dr;
588     }
589
590   alignment_support_cheme = vect_supportable_dr_alignment (first_dr);
591
592   /* Is this an access in a group of loads providing strided access?  
593      If so, add in the cost of the permutes.  */
594   if (group_size > 1) 
595     {
596       /* Uses an even and odd extract operations for each needed permute.  */
597       inside_cost = ncopies * exact_log2(group_size) * group_size
598         * TARG_VEC_STMT_COST;
599
600       if (vect_print_dump_info (REPORT_DETAILS))
601         fprintf (vect_dump, "vect_model_load_cost: strided group_size = %d .",
602                  group_size);
603
604     }
605
606   /* The loads themselves.  */
607   switch (alignment_support_cheme)
608     {
609     case dr_aligned:
610       {
611         inside_cost += ncopies * TARG_VEC_LOAD_COST;
612
613         if (vect_print_dump_info (REPORT_DETAILS))
614           fprintf (vect_dump, "vect_model_load_cost: aligned.");
615
616         break;
617       }
618     case dr_unaligned_supported:
619       {
620         /* Here, we assign an additional cost for the unaligned load.  */
621         inside_cost += ncopies * TARG_VEC_UNALIGNED_LOAD_COST;
622
623         if (vect_print_dump_info (REPORT_DETAILS))
624           fprintf (vect_dump, "vect_model_load_cost: unaligned supported by "
625                    "hardware.");
626
627         break;
628       }
629     case dr_explicit_realign:
630       {
631         inside_cost += ncopies * (2*TARG_VEC_LOAD_COST + TARG_VEC_STMT_COST);
632
633         /* FIXME: If the misalignment remains fixed across the iterations of
634            the containing loop, the following cost should be added to the
635            outside costs.  */
636         if (targetm.vectorize.builtin_mask_for_load)
637           inside_cost += TARG_VEC_STMT_COST;
638
639         break;
640       }
641     case dr_explicit_realign_optimized:
642       {
643         if (vect_print_dump_info (REPORT_DETAILS))
644           fprintf (vect_dump, "vect_model_load_cost: unaligned software "
645                    "pipelined.");
646
647         /* Unaligned software pipeline has a load of an address, an initial
648            load, and possibly a mask operation to "prime" the loop. However,
649            if this is an access in a group of loads, which provide strided
650            access, then the above cost should only be considered for one
651            access in the group. Inside the loop, there is a load op
652            and a realignment op.  */
653
654         if ((!DR_GROUP_FIRST_DR (stmt_info)) || group_size > 1 || slp_node)
655           {
656             outside_cost = 2*TARG_VEC_STMT_COST;
657             if (targetm.vectorize.builtin_mask_for_load)
658               outside_cost += TARG_VEC_STMT_COST;
659           }
660
661         inside_cost += ncopies * (TARG_VEC_LOAD_COST + TARG_VEC_STMT_COST);
662
663         break;
664       }
665
666     default:
667       gcc_unreachable ();
668     }
669   
670   if (vect_print_dump_info (REPORT_DETAILS))
671     fprintf (vect_dump, "vect_model_load_cost: inside_cost = %d, "
672              "outside_cost = %d .", inside_cost, outside_cost);
673
674   /* Set the costs either in STMT_INFO or SLP_NODE (if exists).  */
675   stmt_vinfo_set_inside_of_loop_cost (stmt_info, slp_node, inside_cost);
676   stmt_vinfo_set_outside_of_loop_cost (stmt_info, slp_node, outside_cost);
677 }
678
679
680 /* Function vect_get_new_vect_var.
681
682    Returns a name for a new variable. The current naming scheme appends the 
683    prefix "vect_" or "vect_p" (depending on the value of VAR_KIND) to 
684    the name of vectorizer generated variables, and appends that to NAME if 
685    provided.  */
686
687 static tree
688 vect_get_new_vect_var (tree type, enum vect_var_kind var_kind, const char *name)
689 {
690   const char *prefix;
691   tree new_vect_var;
692
693   switch (var_kind)
694   {
695   case vect_simple_var:
696     prefix = "vect_";
697     break;
698   case vect_scalar_var:
699     prefix = "stmp_";
700     break;
701   case vect_pointer_var:
702     prefix = "vect_p";
703     break;
704   default:
705     gcc_unreachable ();
706   }
707
708   if (name)
709     {
710       char* tmp = concat (prefix, name, NULL);
711       new_vect_var = create_tmp_var (type, tmp);
712       free (tmp);
713     }
714   else
715     new_vect_var = create_tmp_var (type, prefix);
716
717   /* Mark vector typed variable as a gimple register variable.  */
718   if (TREE_CODE (type) == VECTOR_TYPE)
719     DECL_GIMPLE_REG_P (new_vect_var) = true;
720
721   return new_vect_var;
722 }
723
724
725 /* Function vect_create_addr_base_for_vector_ref.
726
727    Create an expression that computes the address of the first memory location
728    that will be accessed for a data reference.
729
730    Input:
731    STMT: The statement containing the data reference.
732    NEW_STMT_LIST: Must be initialized to NULL_TREE or a statement list.
733    OFFSET: Optional. If supplied, it is be added to the initial address.
734    LOOP:    Specify relative to which loop-nest should the address be computed.
735             For example, when the dataref is in an inner-loop nested in an
736             outer-loop that is now being vectorized, LOOP can be either the
737             outer-loop, or the inner-loop. The first memory location accessed
738             by the following dataref ('in' points to short):
739
740                 for (i=0; i<N; i++)
741                    for (j=0; j<M; j++)
742                      s += in[i+j]
743
744             is as follows:
745             if LOOP=i_loop:     &in             (relative to i_loop)
746             if LOOP=j_loop:     &in+i*2B        (relative to j_loop)
747
748    Output:
749    1. Return an SSA_NAME whose value is the address of the memory location of 
750       the first vector of the data reference.
751    2. If new_stmt_list is not NULL_TREE after return then the caller must insert
752       these statement(s) which define the returned SSA_NAME.
753
754    FORNOW: We are only handling array accesses with step 1.  */
755
756 static tree
757 vect_create_addr_base_for_vector_ref (tree stmt,
758                                       tree *new_stmt_list,
759                                       tree offset,
760                                       struct loop *loop)
761 {
762   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
763   struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
764   struct loop *containing_loop = (bb_for_stmt (stmt))->loop_father;
765   tree data_ref_base = unshare_expr (DR_BASE_ADDRESS (dr));
766   tree base_name;
767   tree data_ref_base_var;
768   tree new_base_stmt;
769   tree vec_stmt;
770   tree addr_base, addr_expr;
771   tree dest, new_stmt;
772   tree base_offset = unshare_expr (DR_OFFSET (dr));
773   tree init = unshare_expr (DR_INIT (dr));
774   tree vect_ptr_type, addr_expr2;
775   tree step = TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dr)));
776
777   gcc_assert (loop);
778   if (loop != containing_loop)
779     {
780       loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
781       struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
782
783       gcc_assert (nested_in_vect_loop_p (loop, stmt));
784
785       data_ref_base = unshare_expr (STMT_VINFO_DR_BASE_ADDRESS (stmt_info));
786       base_offset = unshare_expr (STMT_VINFO_DR_OFFSET (stmt_info));
787       init = unshare_expr (STMT_VINFO_DR_INIT (stmt_info));
788     }
789
790   /* Create data_ref_base */
791   base_name = build_fold_indirect_ref (data_ref_base);
792   data_ref_base_var = create_tmp_var (TREE_TYPE (data_ref_base), "batmp");
793   add_referenced_var (data_ref_base_var);
794   data_ref_base = force_gimple_operand (data_ref_base, &new_base_stmt,
795                                         true, data_ref_base_var);
796   append_to_statement_list_force(new_base_stmt, new_stmt_list);
797
798   /* Create base_offset */
799   base_offset = size_binop (PLUS_EXPR, base_offset, init);
800   base_offset = fold_convert (sizetype, base_offset);
801   dest = create_tmp_var (TREE_TYPE (base_offset), "base_off");
802   add_referenced_var (dest);
803   base_offset = force_gimple_operand (base_offset, &new_stmt, true, dest); 
804   append_to_statement_list_force (new_stmt, new_stmt_list);
805
806   if (offset)
807     {
808       tree tmp = create_tmp_var (sizetype, "offset");
809
810       add_referenced_var (tmp);
811       offset = fold_build2 (MULT_EXPR, TREE_TYPE (offset), offset, step);
812       base_offset = fold_build2 (PLUS_EXPR, TREE_TYPE (base_offset),
813                                  base_offset, offset);
814       base_offset = force_gimple_operand (base_offset, &new_stmt, false, tmp);
815       append_to_statement_list_force (new_stmt, new_stmt_list);
816     }
817   
818   /* base + base_offset */
819   addr_base = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (data_ref_base), 
820                            data_ref_base, base_offset);
821
822   vect_ptr_type = build_pointer_type (STMT_VINFO_VECTYPE (stmt_info));
823
824   /* addr_expr = addr_base */
825   addr_expr = vect_get_new_vect_var (vect_ptr_type, vect_pointer_var,
826                                      get_name (base_name));
827   add_referenced_var (addr_expr);
828   vec_stmt = fold_convert (vect_ptr_type, addr_base);
829   addr_expr2 = vect_get_new_vect_var (vect_ptr_type, vect_pointer_var,
830                                      get_name (base_name));
831   add_referenced_var (addr_expr2);
832   vec_stmt = force_gimple_operand (vec_stmt, &new_stmt, false, addr_expr2);
833   append_to_statement_list_force (new_stmt, new_stmt_list);
834
835   if (vect_print_dump_info (REPORT_DETAILS))
836     {
837       fprintf (vect_dump, "created ");
838       print_generic_expr (vect_dump, vec_stmt, TDF_SLIM);
839     }
840   return vec_stmt;
841 }
842
843
844 /* Function vect_create_data_ref_ptr.
845
846    Create a new pointer to vector type (vp), that points to the first location
847    accessed in the loop by STMT, along with the def-use update chain to 
848    appropriately advance the pointer through the loop iterations. Also set
849    aliasing information for the pointer.  This vector pointer is used by the
850    callers to this function to create a memory reference expression for vector
851    load/store access.
852
853    Input:
854    1. STMT: a stmt that references memory. Expected to be of the form
855          GIMPLE_MODIFY_STMT <name, data-ref> or
856          GIMPLE_MODIFY_STMT <data-ref, name>.
857    2. AT_LOOP: the loop where the vector memref is to be created.
858    3. OFFSET (optional): an offset to be added to the initial address accessed
859         by the data-ref in STMT.
860    4. ONLY_INIT: indicate if vp is to be updated in the loop, or remain
861         pointing to the initial address.
862    5. TYPE: if not NULL indicates the required type of the data-ref
863
864    Output:
865    1. Declare a new ptr to vector_type, and have it point to the base of the
866       data reference (initial addressed accessed by the data reference).
867       For example, for vector of type V8HI, the following code is generated:
868
869       v8hi *vp;
870       vp = (v8hi *)initial_address;
871
872       if OFFSET is not supplied:
873          initial_address = &a[init];
874       if OFFSET is supplied:
875          initial_address = &a[init + OFFSET];
876
877       Return the initial_address in INITIAL_ADDRESS.
878
879    2. If ONLY_INIT is true, just return the initial pointer.  Otherwise, also
880       update the pointer in each iteration of the loop.  
881
882       Return the increment stmt that updates the pointer in PTR_INCR.
883
884    3. Set INV_P to true if the access pattern of the data reference in the 
885       vectorized loop is invariant. Set it to false otherwise.
886
887    4. Return the pointer.  */
888
889 static tree
890 vect_create_data_ref_ptr (tree stmt, struct loop *at_loop,
891                           tree offset, tree *initial_address, tree *ptr_incr,
892                           bool only_init, tree type, bool *inv_p)
893 {
894   tree base_name;
895   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
896   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
897   struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
898   bool nested_in_vect_loop = nested_in_vect_loop_p (loop, stmt);
899   struct loop *containing_loop = (bb_for_stmt (stmt))->loop_father;
900   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
901   tree vect_ptr_type;
902   tree vect_ptr;
903   tree tag;
904   tree new_temp;
905   tree vec_stmt;
906   tree new_stmt_list = NULL_TREE;
907   edge pe;
908   basic_block new_bb;
909   tree vect_ptr_init;
910   struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
911   tree vptr;
912   block_stmt_iterator incr_bsi;
913   bool insert_after;
914   tree indx_before_incr, indx_after_incr;
915   tree incr;
916   tree step;
917
918   /* Check the step (evolution) of the load in LOOP, and record
919      whether it's invariant.  */
920   if (nested_in_vect_loop)
921     step = STMT_VINFO_DR_STEP (stmt_info);
922   else
923     step = DR_STEP (STMT_VINFO_DATA_REF (stmt_info));
924     
925   if (tree_int_cst_compare (step, size_zero_node) == 0)
926     *inv_p = true;
927   else
928     *inv_p = false;
929
930   /* Create an expression for the first address accessed by this load
931      in LOOP.  */ 
932   base_name =  build_fold_indirect_ref (unshare_expr (DR_BASE_ADDRESS (dr)));
933
934   if (vect_print_dump_info (REPORT_DETAILS))
935     {
936       tree data_ref_base = base_name;
937       fprintf (vect_dump, "create vector-pointer variable to type: ");
938       print_generic_expr (vect_dump, vectype, TDF_SLIM);
939       if (TREE_CODE (data_ref_base) == VAR_DECL)
940         fprintf (vect_dump, "  vectorizing a one dimensional array ref: ");
941       else if (TREE_CODE (data_ref_base) == ARRAY_REF)
942         fprintf (vect_dump, "  vectorizing a multidimensional array ref: ");
943       else if (TREE_CODE (data_ref_base) == COMPONENT_REF)
944         fprintf (vect_dump, "  vectorizing a record based array ref: ");
945       else if (TREE_CODE (data_ref_base) == SSA_NAME)
946         fprintf (vect_dump, "  vectorizing a pointer ref: ");
947       print_generic_expr (vect_dump, base_name, TDF_SLIM);
948     }
949
950   /** (1) Create the new vector-pointer variable:  **/
951   if (type)  
952     vect_ptr_type = build_pointer_type (type);
953   else
954     vect_ptr_type = build_pointer_type (vectype);
955   vect_ptr = vect_get_new_vect_var (vect_ptr_type, vect_pointer_var,
956                                     get_name (base_name));
957   add_referenced_var (vect_ptr);
958
959   /** (2) Add aliasing information to the new vector-pointer:
960           (The points-to info (DR_PTR_INFO) may be defined later.)  **/
961   
962   tag = DR_SYMBOL_TAG (dr);
963   gcc_assert (tag);
964
965   /* If tag is a variable (and NOT_A_TAG) than a new symbol memory
966      tag must be created with tag added to its may alias list.  */
967   if (!MTAG_P (tag))
968     new_type_alias (vect_ptr, tag, DR_REF (dr));
969   else
970     set_symbol_mem_tag (vect_ptr, tag);
971
972   var_ann (vect_ptr)->subvars = DR_SUBVARS (dr);
973
974   /** Note: If the dataref is in an inner-loop nested in LOOP, and we are
975       vectorizing LOOP (i.e. outer-loop vectorization), we need to create two
976       def-use update cycles for the pointer: One relative to the outer-loop
977       (LOOP), which is what steps (3) and (4) below do. The other is relative
978       to the inner-loop (which is the inner-most loop containing the dataref),
979       and this is done be step (5) below. 
980
981       When vectorizing inner-most loops, the vectorized loop (LOOP) is also the
982       inner-most loop, and so steps (3),(4) work the same, and step (5) is
983       redundant.  Steps (3),(4) create the following:
984
985         vp0 = &base_addr;
986         LOOP:   vp1 = phi(vp0,vp2)
987                 ...  
988                 ...
989                 vp2 = vp1 + step
990                 goto LOOP
991                         
992       If there is an inner-loop nested in loop, then step (5) will also be
993       applied, and an additional update in the inner-loop will be created:
994
995         vp0 = &base_addr;
996         LOOP:   vp1 = phi(vp0,vp2)
997                 ...
998         inner:     vp3 = phi(vp1,vp4)
999                    vp4 = vp3 + inner_step
1000                    if () goto inner
1001                 ...
1002                 vp2 = vp1 + step
1003                 if () goto LOOP   */
1004
1005   /** (3) Calculate the initial address the vector-pointer, and set
1006           the vector-pointer to point to it before the loop:  **/
1007
1008   /* Create: (&(base[init_val+offset]) in the loop preheader.  */
1009
1010   new_temp = vect_create_addr_base_for_vector_ref (stmt, &new_stmt_list,
1011                                                    offset, loop);
1012   pe = loop_preheader_edge (loop);
1013   new_bb = bsi_insert_on_edge_immediate (pe, new_stmt_list);
1014   gcc_assert (!new_bb);
1015   *initial_address = new_temp;
1016
1017   /* Create: p = (vectype *) initial_base  */
1018   vec_stmt = fold_convert (vect_ptr_type, new_temp);
1019   vec_stmt = build_gimple_modify_stmt (vect_ptr, vec_stmt);
1020   vect_ptr_init = make_ssa_name (vect_ptr, vec_stmt);
1021   GIMPLE_STMT_OPERAND (vec_stmt, 0) = vect_ptr_init;
1022   new_bb = bsi_insert_on_edge_immediate (pe, vec_stmt);
1023   gcc_assert (!new_bb);
1024
1025
1026   /** (4) Handle the updating of the vector-pointer inside the loop.
1027           This is needed when ONLY_INIT is false, and also when AT_LOOP
1028           is the inner-loop nested in LOOP (during outer-loop vectorization).
1029    **/
1030
1031   if (only_init && at_loop == loop) /* No update in loop is required.  */
1032     {
1033       /* Copy the points-to information if it exists. */
1034       if (DR_PTR_INFO (dr))
1035         duplicate_ssa_name_ptr_info (vect_ptr_init, DR_PTR_INFO (dr));
1036       vptr = vect_ptr_init;
1037     }
1038   else
1039     {
1040       /* The step of the vector pointer is the Vector Size.  */
1041       tree step = TYPE_SIZE_UNIT (vectype);
1042       /* One exception to the above is when the scalar step of the load in 
1043          LOOP is zero. In this case the step here is also zero.  */
1044       if (*inv_p)
1045         step = size_zero_node;
1046
1047       standard_iv_increment_position (loop, &incr_bsi, &insert_after);
1048
1049       create_iv (vect_ptr_init,
1050                  fold_convert (vect_ptr_type, step),
1051                  NULL_TREE, loop, &incr_bsi, insert_after,
1052                  &indx_before_incr, &indx_after_incr);
1053       incr = bsi_stmt (incr_bsi);
1054       set_stmt_info (stmt_ann (incr),
1055                      new_stmt_vec_info (incr, loop_vinfo));
1056
1057       /* Copy the points-to information if it exists. */
1058       if (DR_PTR_INFO (dr))
1059         {
1060           duplicate_ssa_name_ptr_info (indx_before_incr, DR_PTR_INFO (dr));
1061           duplicate_ssa_name_ptr_info (indx_after_incr, DR_PTR_INFO (dr));
1062         }
1063       merge_alias_info (vect_ptr_init, indx_before_incr);
1064       merge_alias_info (vect_ptr_init, indx_after_incr);
1065       if (ptr_incr)
1066         *ptr_incr = incr;
1067
1068       vptr = indx_before_incr;
1069     }
1070
1071   if (!nested_in_vect_loop || only_init)
1072     return vptr;
1073
1074
1075   /** (5) Handle the updating of the vector-pointer inside the inner-loop
1076           nested in LOOP, if exists: **/
1077
1078   gcc_assert (nested_in_vect_loop);
1079   if (!only_init)
1080     {
1081       standard_iv_increment_position (containing_loop, &incr_bsi, 
1082                                       &insert_after);
1083       create_iv (vptr, fold_convert (vect_ptr_type, DR_STEP (dr)), NULL_TREE, 
1084                  containing_loop, &incr_bsi, insert_after, &indx_before_incr, 
1085                  &indx_after_incr);
1086       incr = bsi_stmt (incr_bsi);
1087       set_stmt_info (stmt_ann (incr), new_stmt_vec_info (incr, loop_vinfo));
1088
1089       /* Copy the points-to information if it exists. */
1090       if (DR_PTR_INFO (dr))
1091         {
1092           duplicate_ssa_name_ptr_info (indx_before_incr, DR_PTR_INFO (dr));
1093           duplicate_ssa_name_ptr_info (indx_after_incr, DR_PTR_INFO (dr));
1094         }
1095       merge_alias_info (vect_ptr_init, indx_before_incr);
1096       merge_alias_info (vect_ptr_init, indx_after_incr);
1097       if (ptr_incr)
1098         *ptr_incr = incr;
1099
1100       return indx_before_incr; 
1101     }
1102   else
1103     gcc_unreachable ();
1104 }
1105
1106
1107 /* Function bump_vector_ptr
1108
1109    Increment a pointer (to a vector type) by vector-size. If requested,
1110    i.e. if PTR-INCR is given, then also connect the new increment stmt 
1111    to the existing def-use update-chain of the pointer, by modifying
1112    the PTR_INCR as illustrated below:
1113
1114    The pointer def-use update-chain before this function:
1115                         DATAREF_PTR = phi (p_0, p_2)
1116                         ....
1117         PTR_INCR:       p_2 = DATAREF_PTR + step 
1118
1119    The pointer def-use update-chain after this function:
1120                         DATAREF_PTR = phi (p_0, p_2)
1121                         ....
1122                         NEW_DATAREF_PTR = DATAREF_PTR + BUMP
1123                         ....
1124         PTR_INCR:       p_2 = NEW_DATAREF_PTR + step
1125
1126    Input:
1127    DATAREF_PTR - ssa_name of a pointer (to vector type) that is being updated 
1128                  in the loop.
1129    PTR_INCR - optional. The stmt that updates the pointer in each iteration of 
1130               the loop.  The increment amount across iterations is expected
1131               to be vector_size.      
1132    BSI - location where the new update stmt is to be placed.
1133    STMT - the original scalar memory-access stmt that is being vectorized.
1134    BUMP - optional. The offset by which to bump the pointer. If not given,
1135           the offset is assumed to be vector_size.
1136
1137    Output: Return NEW_DATAREF_PTR as illustrated above.
1138    
1139 */
1140
1141 static tree
1142 bump_vector_ptr (tree dataref_ptr, tree ptr_incr, block_stmt_iterator *bsi,
1143                  tree stmt, tree bump)
1144 {
1145   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
1146   struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
1147   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
1148   tree vptr_type = TREE_TYPE (dataref_ptr);
1149   tree ptr_var = SSA_NAME_VAR (dataref_ptr);
1150   tree update = TYPE_SIZE_UNIT (vectype);
1151   tree incr_stmt;
1152   ssa_op_iter iter;
1153   use_operand_p use_p;
1154   tree new_dataref_ptr;
1155
1156   if (bump)
1157     update = bump;
1158     
1159   incr_stmt = build_gimple_modify_stmt (ptr_var,
1160                                         build2 (POINTER_PLUS_EXPR, vptr_type,
1161                                                 dataref_ptr, update));
1162   new_dataref_ptr = make_ssa_name (ptr_var, incr_stmt);
1163   GIMPLE_STMT_OPERAND (incr_stmt, 0) = new_dataref_ptr;
1164   vect_finish_stmt_generation (stmt, incr_stmt, bsi);
1165
1166   /* Copy the points-to information if it exists. */
1167   if (DR_PTR_INFO (dr))
1168     duplicate_ssa_name_ptr_info (new_dataref_ptr, DR_PTR_INFO (dr));
1169   merge_alias_info (new_dataref_ptr, dataref_ptr);
1170
1171   if (!ptr_incr)
1172     return new_dataref_ptr;
1173
1174   /* Update the vector-pointer's cross-iteration increment.  */
1175   FOR_EACH_SSA_USE_OPERAND (use_p, ptr_incr, iter, SSA_OP_USE)
1176     {
1177       tree use = USE_FROM_PTR (use_p);
1178
1179       if (use == dataref_ptr)
1180         SET_USE (use_p, new_dataref_ptr);
1181       else
1182         gcc_assert (tree_int_cst_compare (use, update) == 0);
1183     }
1184
1185   return new_dataref_ptr;
1186 }
1187
1188
1189 /* Function vect_create_destination_var.
1190
1191    Create a new temporary of type VECTYPE.  */
1192
1193 static tree
1194 vect_create_destination_var (tree scalar_dest, tree vectype)
1195 {
1196   tree vec_dest;
1197   const char *new_name;
1198   tree type;
1199   enum vect_var_kind kind;
1200
1201   kind = vectype ? vect_simple_var : vect_scalar_var;
1202   type = vectype ? vectype : TREE_TYPE (scalar_dest);
1203
1204   gcc_assert (TREE_CODE (scalar_dest) == SSA_NAME);
1205
1206   new_name = get_name (scalar_dest);
1207   if (!new_name)
1208     new_name = "var_";
1209   vec_dest = vect_get_new_vect_var (type, kind, new_name);
1210   add_referenced_var (vec_dest);
1211
1212   return vec_dest;
1213 }
1214
1215
1216 /* Function vect_init_vector.
1217
1218    Insert a new stmt (INIT_STMT) that initializes a new vector variable with
1219    the vector elements of VECTOR_VAR. Place the initialization at BSI if it
1220    is not NULL. Otherwise, place the initialization at the loop preheader.
1221    Return the DEF of INIT_STMT. 
1222    It will be used in the vectorization of STMT.  */
1223
1224 static tree
1225 vect_init_vector (tree stmt, tree vector_var, tree vector_type,
1226                   block_stmt_iterator *bsi)
1227 {
1228   stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt);
1229   tree new_var;
1230   tree init_stmt;
1231   tree vec_oprnd;
1232   edge pe;
1233   tree new_temp;
1234   basic_block new_bb;
1235  
1236   new_var = vect_get_new_vect_var (vector_type, vect_simple_var, "cst_");
1237   add_referenced_var (new_var); 
1238   init_stmt = build_gimple_modify_stmt (new_var, vector_var);
1239   new_temp = make_ssa_name (new_var, init_stmt);
1240   GIMPLE_STMT_OPERAND (init_stmt, 0) = new_temp;
1241
1242   if (bsi)
1243     vect_finish_stmt_generation (stmt, init_stmt, bsi);
1244   else
1245     {
1246       loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
1247       struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
1248
1249       if (nested_in_vect_loop_p (loop, stmt))
1250         loop = loop->inner;
1251       pe = loop_preheader_edge (loop);
1252       new_bb = bsi_insert_on_edge_immediate (pe, init_stmt);
1253       gcc_assert (!new_bb);
1254     }
1255
1256   if (vect_print_dump_info (REPORT_DETAILS))
1257     {
1258       fprintf (vect_dump, "created new init_stmt: ");
1259       print_generic_expr (vect_dump, init_stmt, TDF_SLIM);
1260     }
1261
1262   vec_oprnd = GIMPLE_STMT_OPERAND (init_stmt, 0);
1263   return vec_oprnd;
1264 }
1265
1266
1267 /* For constant and loop invariant defs of SLP_NODE this function returns 
1268    (vector) defs (VEC_OPRNDS) that will be used in the vectorized stmts.  
1269    OP_NUM determines if we gather defs for operand 0 or operand 1 of the scalar
1270    stmts.  */
1271
1272 static void
1273 vect_get_constant_vectors (slp_tree slp_node, VEC(tree,heap) **vec_oprnds,
1274                            unsigned int op_num)
1275 {
1276   VEC (tree, heap) *stmts = SLP_TREE_SCALAR_STMTS (slp_node);
1277   tree stmt = VEC_index (tree, stmts, 0);
1278   stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt);
1279   tree vectype = STMT_VINFO_VECTYPE (stmt_vinfo);
1280   int nunits = TYPE_VECTOR_SUBPARTS (vectype);
1281   tree vec_cst;
1282   tree t = NULL_TREE;
1283   int j, number_of_places_left_in_vector;
1284   tree vector_type;
1285   tree op, vop, operation;
1286   int group_size = VEC_length (tree, stmts);
1287   unsigned int vec_num, i;
1288   int number_of_copies = 1;
1289   bool is_store = false;
1290   unsigned int number_of_vectors = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node);
1291   VEC (tree, heap) *voprnds = VEC_alloc (tree, heap, number_of_vectors);
1292
1293   if (STMT_VINFO_DATA_REF (stmt_vinfo))
1294     is_store = true;
1295
1296   /* NUMBER_OF_COPIES is the number of times we need to use the same values in
1297      created vectors. It is greater than 1 if unrolling is performed. 
1298
1299      For example, we have two scalar operands, s1 and s2 (e.g., group of
1300      strided accesses of size two), while NUINTS is four (i.e., four scalars
1301      of this type can be packed in a vector). The output vector will contain
1302      two copies of each scalar operand: {s1, s2, s1, s2}. (NUMBER_OF_COPIES
1303      will be 2).
1304
1305      If GROUP_SIZE > NUNITS, the scalars will be split into several vectors 
1306      containing the operands.
1307
1308      For example, NUINTS is four as before, and the group size is 8 
1309      (s1, s2, ..., s8). We will create two vectors {s1, s2, s3, s4} and
1310      {s5, s6, s7, s8}.  */
1311     
1312   number_of_copies = least_common_multiple (nunits, group_size) / group_size;
1313
1314   number_of_places_left_in_vector = nunits;
1315   for (j = 0; j < number_of_copies; j++)
1316     {
1317       for (i = group_size - 1; VEC_iterate (tree, stmts, i, stmt); i--)
1318         {
1319           operation = GIMPLE_STMT_OPERAND (stmt, 1);
1320           if (is_store)
1321             op = operation;
1322           else
1323             op = TREE_OPERAND (operation, op_num);
1324
1325           /* Create 'vect_ = {op0,op1,...,opn}'.  */
1326           t = tree_cons (NULL_TREE, op, t);
1327
1328           number_of_places_left_in_vector--;
1329
1330           if (number_of_places_left_in_vector == 0)
1331             {
1332               number_of_places_left_in_vector = nunits;
1333
1334               vector_type = get_vectype_for_scalar_type (TREE_TYPE (op));
1335               vec_cst = build_constructor_from_list (vector_type, t);
1336               VEC_quick_push (tree, voprnds,
1337                               vect_init_vector (stmt, vec_cst, vector_type,
1338                                                 NULL));
1339               t = NULL_TREE;
1340             }
1341         }
1342     }
1343
1344   /* Since the vectors are created in the reverse order, we should invert 
1345      them.  */
1346   vec_num = VEC_length (tree, voprnds);
1347   for (j = vec_num - 1; j >= 0; j--)
1348     {
1349       vop = VEC_index (tree, voprnds, j);
1350       VEC_quick_push (tree, *vec_oprnds, vop);
1351     }
1352
1353   VEC_free (tree, heap, voprnds);
1354
1355   /* In case that VF is greater than the unrolling factor needed for the SLP
1356      group of stmts, NUMBER_OF_VECTORS to be created is greater than 
1357      NUMBER_OF_SCALARS/NUNITS or NUNITS/NUMBER_OF_SCALARS, and hence we have 
1358      to replicate the vectors.  */
1359   while (number_of_vectors > VEC_length (tree, *vec_oprnds))
1360     {
1361       for (i = 0; VEC_iterate (tree, *vec_oprnds, i, vop) && i < vec_num; i++)
1362         VEC_quick_push (tree, *vec_oprnds, vop);
1363     }
1364 }
1365
1366
1367 /* Get vectorized defintions from SLP_NODE that contains corresponding
1368    vectorized def-stmts.  */
1369  
1370 static void
1371 vect_get_slp_vect_defs (slp_tree slp_node, VEC (tree,heap) **vec_oprnds)
1372 {
1373   tree vec_oprnd;
1374   tree vec_def_stmt;
1375   unsigned int i;
1376
1377   gcc_assert (SLP_TREE_VEC_STMTS (slp_node));
1378
1379   for (i = 0; 
1380        VEC_iterate (tree, SLP_TREE_VEC_STMTS (slp_node), i, vec_def_stmt); 
1381        i++)
1382     {
1383       gcc_assert (vec_def_stmt);
1384       vec_oprnd = GIMPLE_STMT_OPERAND (vec_def_stmt, 0);
1385       VEC_quick_push (tree, *vec_oprnds, vec_oprnd);
1386     }
1387 }
1388
1389
1390 /* Get vectorized definitions for SLP_NODE. 
1391    If the scalar definitions are loop invariants or constants, collect them and 
1392    call vect_get_constant_vectors() to create vector stmts.
1393    Otherwise, the def-stmts must be already vectorized and the vectorized stmts
1394    must be stored in the LEFT/RIGHT node of SLP_NODE, and we call
1395    vect_get_slp_vect_defs() to retrieve them.  
1396    If VEC_OPRNDS1 is NULL, don't get vector defs for the second operand (from
1397    the right node. This is used when the second operand must remain scalar.  */
1398  
1399 static void
1400 vect_get_slp_defs (slp_tree slp_node, VEC (tree,heap) **vec_oprnds0,
1401                    VEC (tree,heap) **vec_oprnds1)
1402 {
1403   tree operation, first_stmt;
1404
1405   /* Allocate memory for vectorized defs.  */
1406   *vec_oprnds0 = VEC_alloc (tree, heap, 
1407                             SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node));
1408
1409   /* SLP_NODE corresponds either to a group of stores or to a group of 
1410      unary/binary operations. We don't call this function for loads.  */
1411   if (SLP_TREE_LEFT (slp_node)) 
1412     /* The defs are already vectorized.  */ 
1413     vect_get_slp_vect_defs (SLP_TREE_LEFT (slp_node), vec_oprnds0);
1414   else
1415     /* Build vectors from scalar defs.  */
1416     vect_get_constant_vectors (slp_node, vec_oprnds0, 0);
1417
1418   first_stmt = VEC_index (tree, SLP_TREE_SCALAR_STMTS (slp_node), 0);
1419   if (STMT_VINFO_DATA_REF (vinfo_for_stmt (first_stmt)))
1420     /* Since we don't call this function with loads, this is a group of 
1421        stores.  */
1422     return;
1423
1424   operation = GIMPLE_STMT_OPERAND (first_stmt, 1);
1425   if (TREE_OPERAND_LENGTH (operation) == unary_op || !vec_oprnds1)
1426     return;
1427
1428   *vec_oprnds1 = VEC_alloc (tree, heap, 
1429                             SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node));
1430
1431   if (SLP_TREE_RIGHT (slp_node))
1432     /* The defs are already vectorized.  */ 
1433     vect_get_slp_vect_defs (SLP_TREE_RIGHT (slp_node), vec_oprnds1);
1434   else
1435     /* Build vectors from scalar defs.  */
1436     vect_get_constant_vectors (slp_node, vec_oprnds1, 1);
1437 }
1438
1439
1440 /* Function get_initial_def_for_induction
1441
1442    Input:
1443    STMT - a stmt that performs an induction operation in the loop.
1444    IV_PHI - the initial value of the induction variable
1445
1446    Output:
1447    Return a vector variable, initialized with the first VF values of
1448    the induction variable. E.g., for an iv with IV_PHI='X' and
1449    evolution S, for a vector of 4 units, we want to return: 
1450    [X, X + S, X + 2*S, X + 3*S].  */
1451
1452 static tree
1453 get_initial_def_for_induction (tree iv_phi)
1454 {
1455   stmt_vec_info stmt_vinfo = vinfo_for_stmt (iv_phi);
1456   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
1457   struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
1458   tree scalar_type = TREE_TYPE (PHI_RESULT_TREE (iv_phi));
1459   tree vectype = get_vectype_for_scalar_type (scalar_type);
1460   int nunits =  TYPE_VECTOR_SUBPARTS (vectype);
1461   edge pe = loop_preheader_edge (loop);
1462   struct loop *iv_loop;
1463   basic_block new_bb;
1464   tree vec, vec_init, vec_step, t;
1465   tree access_fn;
1466   tree new_var;
1467   tree new_name;
1468   tree init_stmt;
1469   tree induction_phi, induc_def, new_stmt, vec_def, vec_dest;
1470   tree init_expr, step_expr;
1471   int vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
1472   int i;
1473   bool ok;
1474   int ncopies = vf / nunits;
1475   tree expr;
1476   stmt_vec_info phi_info = vinfo_for_stmt (iv_phi);
1477   bool nested_in_vect_loop = false;
1478   tree stmts;
1479   imm_use_iterator imm_iter;
1480   use_operand_p use_p;
1481   tree exit_phi;
1482   edge latch_e;
1483   tree loop_arg;
1484   block_stmt_iterator si;
1485   basic_block bb = bb_for_stmt (iv_phi);
1486
1487   gcc_assert (phi_info);
1488   gcc_assert (ncopies >= 1);
1489
1490   /* Find the first insertion point in the BB.  */
1491   si = bsi_after_labels (bb);
1492
1493   if (INTEGRAL_TYPE_P (scalar_type))
1494     step_expr = build_int_cst (scalar_type, 0);
1495   else
1496     step_expr = build_real (scalar_type, dconst0);
1497
1498   /* Is phi in an inner-loop, while vectorizing an enclosing outer-loop?  */
1499   if (nested_in_vect_loop_p (loop, iv_phi))
1500     {
1501       nested_in_vect_loop = true;
1502       iv_loop = loop->inner;
1503     }
1504   else
1505     iv_loop = loop;
1506   gcc_assert (iv_loop == (bb_for_stmt (iv_phi))->loop_father);
1507
1508   latch_e = loop_latch_edge (iv_loop);
1509   loop_arg = PHI_ARG_DEF_FROM_EDGE (iv_phi, latch_e);
1510
1511   access_fn = analyze_scalar_evolution (iv_loop, PHI_RESULT (iv_phi));
1512   gcc_assert (access_fn);
1513   ok = vect_is_simple_iv_evolution (iv_loop->num, access_fn,
1514                                   &init_expr, &step_expr);
1515   gcc_assert (ok);
1516   pe = loop_preheader_edge (iv_loop);
1517
1518   /* Create the vector that holds the initial_value of the induction.  */
1519   if (nested_in_vect_loop)
1520     {
1521       /* iv_loop is nested in the loop to be vectorized.  init_expr had already
1522          been created during vectorization of previous stmts; We obtain it from
1523          the STMT_VINFO_VEC_STMT of the defining stmt. */
1524       tree iv_def = PHI_ARG_DEF_FROM_EDGE (iv_phi, loop_preheader_edge (iv_loop));
1525       vec_init = vect_get_vec_def_for_operand (iv_def, iv_phi, NULL);
1526     }
1527   else
1528     {
1529       /* iv_loop is the loop to be vectorized. Create:
1530          vec_init = [X, X+S, X+2*S, X+3*S] (S = step_expr, X = init_expr)  */
1531       new_var = vect_get_new_vect_var (scalar_type, vect_scalar_var, "var_");
1532       add_referenced_var (new_var);
1533
1534       new_name = force_gimple_operand (init_expr, &stmts, false, new_var);
1535       if (stmts)
1536         {
1537           new_bb = bsi_insert_on_edge_immediate (pe, stmts);
1538           gcc_assert (!new_bb);
1539         }
1540
1541       t = NULL_TREE;
1542       t = tree_cons (NULL_TREE, init_expr, t);
1543       for (i = 1; i < nunits; i++)
1544         {
1545           tree tmp;
1546
1547           /* Create: new_name_i = new_name + step_expr  */
1548           tmp = fold_build2 (PLUS_EXPR, scalar_type, new_name, step_expr);
1549           init_stmt = build_gimple_modify_stmt (new_var, tmp);
1550           new_name = make_ssa_name (new_var, init_stmt);
1551           GIMPLE_STMT_OPERAND (init_stmt, 0) = new_name;
1552
1553           new_bb = bsi_insert_on_edge_immediate (pe, init_stmt);
1554           gcc_assert (!new_bb);
1555
1556           if (vect_print_dump_info (REPORT_DETAILS))
1557             {
1558               fprintf (vect_dump, "created new init_stmt: ");
1559               print_generic_expr (vect_dump, init_stmt, TDF_SLIM);
1560             }
1561           t = tree_cons (NULL_TREE, new_name, t);
1562         }
1563       /* Create a vector from [new_name_0, new_name_1, ..., new_name_nunits-1]  */
1564       vec = build_constructor_from_list (vectype, nreverse (t));
1565       vec_init = vect_init_vector (iv_phi, vec, vectype, NULL);
1566     }
1567
1568
1569   /* Create the vector that holds the step of the induction.  */
1570   if (nested_in_vect_loop)
1571     /* iv_loop is nested in the loop to be vectorized. Generate:
1572        vec_step = [S, S, S, S]  */
1573     new_name = step_expr;
1574   else
1575     {
1576       /* iv_loop is the loop to be vectorized. Generate:
1577           vec_step = [VF*S, VF*S, VF*S, VF*S]  */
1578       expr = build_int_cst (scalar_type, vf);
1579       new_name = fold_build2 (MULT_EXPR, scalar_type, expr, step_expr);
1580     }
1581
1582   t = NULL_TREE;
1583   for (i = 0; i < nunits; i++)
1584     t = tree_cons (NULL_TREE, unshare_expr (new_name), t);
1585   vec = build_constructor_from_list (vectype, t);
1586   vec_step = vect_init_vector (iv_phi, vec, vectype, NULL);
1587
1588
1589   /* Create the following def-use cycle:
1590      loop prolog:
1591          vec_init = ...
1592          vec_step = ...
1593      loop:
1594          vec_iv = PHI <vec_init, vec_loop>
1595          ...
1596          STMT
1597          ...
1598          vec_loop = vec_iv + vec_step;  */
1599
1600   /* Create the induction-phi that defines the induction-operand.  */
1601   vec_dest = vect_get_new_vect_var (vectype, vect_simple_var, "vec_iv_");
1602   add_referenced_var (vec_dest);
1603   induction_phi = create_phi_node (vec_dest, iv_loop->header);
1604   set_stmt_info (get_stmt_ann (induction_phi),
1605                  new_stmt_vec_info (induction_phi, loop_vinfo));
1606   induc_def = PHI_RESULT (induction_phi);
1607
1608   /* Create the iv update inside the loop  */
1609   new_stmt = build_gimple_modify_stmt (NULL_TREE,
1610                                        build2 (PLUS_EXPR, vectype,
1611                                                induc_def, vec_step));
1612   vec_def = make_ssa_name (vec_dest, new_stmt);
1613   GIMPLE_STMT_OPERAND (new_stmt, 0) = vec_def;
1614   bsi_insert_before (&si, new_stmt, BSI_SAME_STMT);
1615   set_stmt_info (get_stmt_ann (new_stmt),
1616                  new_stmt_vec_info (new_stmt, loop_vinfo));
1617
1618   /* Set the arguments of the phi node:  */
1619   add_phi_arg (induction_phi, vec_init, pe);
1620   add_phi_arg (induction_phi, vec_def, loop_latch_edge (iv_loop));
1621
1622
1623   /* In case that vectorization factor (VF) is bigger than the number
1624      of elements that we can fit in a vectype (nunits), we have to generate
1625      more than one vector stmt - i.e - we need to "unroll" the
1626      vector stmt by a factor VF/nunits.  For more details see documentation
1627      in vectorizable_operation.  */
1628   
1629   if (ncopies > 1)
1630     {
1631       stmt_vec_info prev_stmt_vinfo;
1632       /* FORNOW. This restriction should be relaxed.  */
1633       gcc_assert (!nested_in_vect_loop);
1634
1635       /* Create the vector that holds the step of the induction.  */
1636       expr = build_int_cst (scalar_type, nunits);
1637       new_name = fold_build2 (MULT_EXPR, scalar_type, expr, step_expr);
1638       t = NULL_TREE;
1639       for (i = 0; i < nunits; i++)
1640         t = tree_cons (NULL_TREE, unshare_expr (new_name), t);
1641       vec = build_constructor_from_list (vectype, t);
1642       vec_step = vect_init_vector (iv_phi, vec, vectype, NULL);
1643
1644       vec_def = induc_def;
1645       prev_stmt_vinfo = vinfo_for_stmt (induction_phi);
1646       for (i = 1; i < ncopies; i++)
1647         {
1648           tree tmp;
1649
1650           /* vec_i = vec_prev + vec_step  */
1651           tmp = build2 (PLUS_EXPR, vectype, vec_def, vec_step);
1652           new_stmt = build_gimple_modify_stmt (NULL_TREE, tmp);
1653           vec_def = make_ssa_name (vec_dest, new_stmt);
1654           GIMPLE_STMT_OPERAND (new_stmt, 0) = vec_def;
1655           bsi_insert_before (&si, new_stmt, BSI_SAME_STMT);
1656           set_stmt_info (get_stmt_ann (new_stmt),
1657                          new_stmt_vec_info (new_stmt, loop_vinfo));
1658           STMT_VINFO_RELATED_STMT (prev_stmt_vinfo) = new_stmt;
1659           prev_stmt_vinfo = vinfo_for_stmt (new_stmt); 
1660         }
1661     }
1662
1663   if (nested_in_vect_loop)
1664     {
1665       /* Find the loop-closed exit-phi of the induction, and record
1666          the final vector of induction results:  */
1667       exit_phi = NULL;
1668       FOR_EACH_IMM_USE_FAST (use_p, imm_iter, loop_arg)
1669         {
1670           if (!flow_bb_inside_loop_p (iv_loop, bb_for_stmt (USE_STMT (use_p))))
1671             {
1672               exit_phi = USE_STMT (use_p);
1673               break;
1674             }
1675         }
1676       if (exit_phi) 
1677         {
1678           stmt_vec_info stmt_vinfo = vinfo_for_stmt (exit_phi);
1679           /* FORNOW. Currently not supporting the case that an inner-loop induction
1680              is not used in the outer-loop (i.e. only outside the outer-loop).  */
1681           gcc_assert (STMT_VINFO_RELEVANT_P (stmt_vinfo)
1682                       && !STMT_VINFO_LIVE_P (stmt_vinfo));
1683
1684           STMT_VINFO_VEC_STMT (stmt_vinfo) = new_stmt;
1685           if (vect_print_dump_info (REPORT_DETAILS))
1686             {
1687               fprintf (vect_dump, "vector of inductions after inner-loop:");
1688               print_generic_expr (vect_dump, new_stmt, TDF_SLIM);
1689             }
1690         }
1691     }
1692
1693
1694   if (vect_print_dump_info (REPORT_DETAILS))
1695     {
1696       fprintf (vect_dump, "transform induction: created def-use cycle:");
1697       print_generic_expr (vect_dump, induction_phi, TDF_SLIM);
1698       fprintf (vect_dump, "\n");
1699       print_generic_expr (vect_dump, SSA_NAME_DEF_STMT (vec_def), TDF_SLIM);
1700     }
1701
1702   STMT_VINFO_VEC_STMT (phi_info) = induction_phi;
1703   return induc_def;
1704 }
1705
1706
1707 /* Function vect_get_vec_def_for_operand.
1708
1709    OP is an operand in STMT. This function returns a (vector) def that will be
1710    used in the vectorized stmt for STMT.
1711
1712    In the case that OP is an SSA_NAME which is defined in the loop, then
1713    STMT_VINFO_VEC_STMT of the defining stmt holds the relevant def.
1714
1715    In case OP is an invariant or constant, a new stmt that creates a vector def
1716    needs to be introduced.  */
1717
1718 static tree
1719 vect_get_vec_def_for_operand (tree op, tree stmt, tree *scalar_def)
1720 {
1721   tree vec_oprnd;
1722   tree vec_stmt;
1723   tree def_stmt;
1724   stmt_vec_info def_stmt_info = NULL;
1725   stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt);
1726   tree vectype = STMT_VINFO_VECTYPE (stmt_vinfo);
1727   int nunits = TYPE_VECTOR_SUBPARTS (vectype);
1728   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
1729   tree vec_inv;
1730   tree vec_cst;
1731   tree t = NULL_TREE;
1732   tree def;
1733   int i;
1734   enum vect_def_type dt;
1735   bool is_simple_use;
1736   tree vector_type;
1737
1738   if (vect_print_dump_info (REPORT_DETAILS))
1739     {
1740       fprintf (vect_dump, "vect_get_vec_def_for_operand: ");
1741       print_generic_expr (vect_dump, op, TDF_SLIM);
1742     }
1743
1744   is_simple_use = vect_is_simple_use (op, loop_vinfo, &def_stmt, &def, &dt);
1745   gcc_assert (is_simple_use);
1746   if (vect_print_dump_info (REPORT_DETAILS))
1747     {
1748       if (def)
1749         {
1750           fprintf (vect_dump, "def =  ");
1751           print_generic_expr (vect_dump, def, TDF_SLIM);
1752         }
1753       if (def_stmt)
1754         {
1755           fprintf (vect_dump, "  def_stmt =  ");
1756           print_generic_expr (vect_dump, def_stmt, TDF_SLIM);
1757         }
1758     }
1759
1760   switch (dt)
1761     {
1762     /* Case 1: operand is a constant.  */
1763     case vect_constant_def:
1764       {
1765         if (scalar_def) 
1766           *scalar_def = op;
1767
1768         /* Create 'vect_cst_ = {cst,cst,...,cst}'  */
1769         if (vect_print_dump_info (REPORT_DETAILS))
1770           fprintf (vect_dump, "Create vector_cst. nunits = %d", nunits);
1771
1772         for (i = nunits - 1; i >= 0; --i)
1773           {
1774             t = tree_cons (NULL_TREE, op, t);
1775           }
1776         vector_type = get_vectype_for_scalar_type (TREE_TYPE (op));
1777         vec_cst = build_vector (vector_type, t);
1778
1779         return vect_init_vector (stmt, vec_cst, vector_type, NULL);
1780       }
1781
1782     /* Case 2: operand is defined outside the loop - loop invariant.  */
1783     case vect_invariant_def:
1784       {
1785         if (scalar_def) 
1786           *scalar_def = def;
1787
1788         /* Create 'vec_inv = {inv,inv,..,inv}'  */
1789         if (vect_print_dump_info (REPORT_DETAILS))
1790           fprintf (vect_dump, "Create vector_inv.");
1791
1792         for (i = nunits - 1; i >= 0; --i)
1793           {
1794             t = tree_cons (NULL_TREE, def, t);
1795           }
1796
1797         /* FIXME: use build_constructor directly.  */
1798         vector_type = get_vectype_for_scalar_type (TREE_TYPE (def));
1799         vec_inv = build_constructor_from_list (vector_type, t);
1800         return vect_init_vector (stmt, vec_inv, vector_type, NULL);
1801       }
1802
1803     /* Case 3: operand is defined inside the loop.  */
1804     case vect_loop_def:
1805       {
1806         if (scalar_def) 
1807           *scalar_def = def_stmt;
1808
1809         /* Get the def from the vectorized stmt.  */
1810         def_stmt_info = vinfo_for_stmt (def_stmt);
1811         vec_stmt = STMT_VINFO_VEC_STMT (def_stmt_info);
1812         gcc_assert (vec_stmt);
1813         if (TREE_CODE (vec_stmt) == PHI_NODE)
1814           vec_oprnd = PHI_RESULT (vec_stmt);
1815         else
1816           vec_oprnd = GIMPLE_STMT_OPERAND (vec_stmt, 0);
1817         return vec_oprnd;
1818       }
1819
1820     /* Case 4: operand is defined by a loop header phi - reduction  */
1821     case vect_reduction_def:
1822       {
1823         struct loop *loop;
1824
1825         gcc_assert (TREE_CODE (def_stmt) == PHI_NODE);
1826         loop = (bb_for_stmt (def_stmt))->loop_father; 
1827
1828         /* Get the def before the loop  */
1829         op = PHI_ARG_DEF_FROM_EDGE (def_stmt, loop_preheader_edge (loop));
1830         return get_initial_def_for_reduction (stmt, op, scalar_def);
1831      }
1832
1833     /* Case 5: operand is defined by loop-header phi - induction.  */
1834     case vect_induction_def:
1835       {
1836         gcc_assert (TREE_CODE (def_stmt) == PHI_NODE);
1837
1838         /* Get the def from the vectorized stmt.  */
1839         def_stmt_info = vinfo_for_stmt (def_stmt);
1840         vec_stmt = STMT_VINFO_VEC_STMT (def_stmt_info);
1841         gcc_assert (vec_stmt && (TREE_CODE (vec_stmt) == PHI_NODE));
1842         vec_oprnd = PHI_RESULT (vec_stmt);
1843         return vec_oprnd;
1844       }
1845
1846     default:
1847       gcc_unreachable ();
1848     }
1849 }
1850
1851
1852 /* Function vect_get_vec_def_for_stmt_copy
1853
1854    Return a vector-def for an operand. This function is used when the 
1855    vectorized stmt to be created (by the caller to this function) is a "copy" 
1856    created in case the vectorized result cannot fit in one vector, and several 
1857    copies of the vector-stmt are required. In this case the vector-def is 
1858    retrieved from the vector stmt recorded in the STMT_VINFO_RELATED_STMT field
1859    of the stmt that defines VEC_OPRND. 
1860    DT is the type of the vector def VEC_OPRND.
1861
1862    Context:
1863         In case the vectorization factor (VF) is bigger than the number
1864    of elements that can fit in a vectype (nunits), we have to generate
1865    more than one vector stmt to vectorize the scalar stmt. This situation
1866    arises when there are multiple data-types operated upon in the loop; the 
1867    smallest data-type determines the VF, and as a result, when vectorizing
1868    stmts operating on wider types we need to create 'VF/nunits' "copies" of the
1869    vector stmt (each computing a vector of 'nunits' results, and together
1870    computing 'VF' results in each iteration).  This function is called when 
1871    vectorizing such a stmt (e.g. vectorizing S2 in the illustration below, in
1872    which VF=16 and nunits=4, so the number of copies required is 4):
1873
1874    scalar stmt:         vectorized into:        STMT_VINFO_RELATED_STMT
1875  
1876    S1: x = load         VS1.0:  vx.0 = memref0      VS1.1
1877                         VS1.1:  vx.1 = memref1      VS1.2
1878                         VS1.2:  vx.2 = memref2      VS1.3
1879                         VS1.3:  vx.3 = memref3 
1880
1881    S2: z = x + ...      VSnew.0:  vz0 = vx.0 + ...  VSnew.1
1882                         VSnew.1:  vz1 = vx.1 + ...  VSnew.2
1883                         VSnew.2:  vz2 = vx.2 + ...  VSnew.3
1884                         VSnew.3:  vz3 = vx.3 + ...
1885
1886    The vectorization of S1 is explained in vectorizable_load.
1887    The vectorization of S2:
1888         To create the first vector-stmt out of the 4 copies - VSnew.0 - 
1889    the function 'vect_get_vec_def_for_operand' is called to 
1890    get the relevant vector-def for each operand of S2. For operand x it
1891    returns  the vector-def 'vx.0'.
1892
1893         To create the remaining copies of the vector-stmt (VSnew.j), this 
1894    function is called to get the relevant vector-def for each operand.  It is 
1895    obtained from the respective VS1.j stmt, which is recorded in the 
1896    STMT_VINFO_RELATED_STMT field of the stmt that defines VEC_OPRND.
1897
1898         For example, to obtain the vector-def 'vx.1' in order to create the 
1899    vector stmt 'VSnew.1', this function is called with VEC_OPRND='vx.0'. 
1900    Given 'vx0' we obtain the stmt that defines it ('VS1.0'); from the 
1901    STMT_VINFO_RELATED_STMT field of 'VS1.0' we obtain the next copy - 'VS1.1',
1902    and return its def ('vx.1').
1903    Overall, to create the above sequence this function will be called 3 times:
1904         vx.1 = vect_get_vec_def_for_stmt_copy (dt, vx.0);
1905         vx.2 = vect_get_vec_def_for_stmt_copy (dt, vx.1);
1906         vx.3 = vect_get_vec_def_for_stmt_copy (dt, vx.2);  */
1907
1908 static tree
1909 vect_get_vec_def_for_stmt_copy (enum vect_def_type dt, tree vec_oprnd)
1910 {
1911   tree vec_stmt_for_operand;
1912   stmt_vec_info def_stmt_info;
1913
1914   /* Do nothing; can reuse same def.  */
1915   if (dt == vect_invariant_def || dt == vect_constant_def )
1916     return vec_oprnd;
1917
1918   vec_stmt_for_operand = SSA_NAME_DEF_STMT (vec_oprnd);
1919   def_stmt_info = vinfo_for_stmt (vec_stmt_for_operand);
1920   gcc_assert (def_stmt_info);
1921   vec_stmt_for_operand = STMT_VINFO_RELATED_STMT (def_stmt_info);
1922   gcc_assert (vec_stmt_for_operand);
1923   vec_oprnd = GIMPLE_STMT_OPERAND (vec_stmt_for_operand, 0);
1924   return vec_oprnd;
1925 }
1926
1927
1928 /* Get vectorized definitions for the operands to create a copy of an original
1929    stmt. See vect_get_vec_def_for_stmt_copy() for details.  */
1930
1931 static void
1932 vect_get_vec_defs_for_stmt_copy (enum vect_def_type *dt, 
1933                                  VEC(tree,heap) **vec_oprnds0, 
1934                                  VEC(tree,heap) **vec_oprnds1)
1935 {
1936   tree vec_oprnd = VEC_pop (tree, *vec_oprnds0);
1937
1938   vec_oprnd = vect_get_vec_def_for_stmt_copy (dt[0], vec_oprnd);
1939   VEC_quick_push (tree, *vec_oprnds0, vec_oprnd);
1940
1941   if (vec_oprnds1)
1942     {
1943       vec_oprnd = VEC_pop (tree, *vec_oprnds1);
1944       vec_oprnd = vect_get_vec_def_for_stmt_copy (dt[1], vec_oprnd);
1945       VEC_quick_push (tree, *vec_oprnds1, vec_oprnd);
1946     }
1947 }
1948
1949
1950 /* Get vectorized definitions for OP0 and OP1, or SLP_NODE if it is not NULL.  */
1951
1952 static void
1953 vect_get_vec_defs (tree op0, tree op1, tree stmt, VEC(tree,heap) **vec_oprnds0, 
1954                    VEC(tree,heap) **vec_oprnds1, slp_tree slp_node)
1955 {
1956   if (slp_node)
1957     vect_get_slp_defs (slp_node, vec_oprnds0, vec_oprnds1);
1958   else
1959     {
1960       tree vec_oprnd;
1961
1962       *vec_oprnds0 = VEC_alloc (tree, heap, 1); 
1963       vec_oprnd = vect_get_vec_def_for_operand (op0, stmt, NULL);      
1964       VEC_quick_push (tree, *vec_oprnds0, vec_oprnd);
1965
1966       if (op1)
1967         {
1968           *vec_oprnds1 = VEC_alloc (tree, heap, 1);     
1969           vec_oprnd = vect_get_vec_def_for_operand (op1, stmt, NULL);      
1970           VEC_quick_push (tree, *vec_oprnds1, vec_oprnd);
1971         }
1972     }
1973 }
1974
1975
1976 /* Function vect_finish_stmt_generation.
1977
1978    Insert a new stmt.  */
1979
1980 static void
1981 vect_finish_stmt_generation (tree stmt, tree vec_stmt, 
1982                              block_stmt_iterator *bsi)
1983 {
1984   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
1985   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
1986
1987   gcc_assert (stmt == bsi_stmt (*bsi));
1988   gcc_assert (TREE_CODE (stmt) != LABEL_EXPR);
1989
1990   bsi_insert_before (bsi, vec_stmt, BSI_SAME_STMT);
1991
1992   set_stmt_info (get_stmt_ann (vec_stmt), 
1993                  new_stmt_vec_info (vec_stmt, loop_vinfo)); 
1994
1995   if (vect_print_dump_info (REPORT_DETAILS))
1996     {
1997       fprintf (vect_dump, "add new stmt: ");
1998       print_generic_expr (vect_dump, vec_stmt, TDF_SLIM);
1999     }
2000
2001   /* Make sure bsi points to the stmt that is being vectorized.  */
2002   gcc_assert (stmt == bsi_stmt (*bsi));
2003
2004 #ifdef USE_MAPPED_LOCATION
2005   SET_EXPR_LOCATION (vec_stmt, EXPR_LOCATION (stmt));
2006 #else
2007   SET_EXPR_LOCUS (vec_stmt, EXPR_LOCUS (stmt));
2008 #endif
2009 }
2010
2011
2012 /* Function get_initial_def_for_reduction
2013
2014    Input:
2015    STMT - a stmt that performs a reduction operation in the loop.
2016    INIT_VAL - the initial value of the reduction variable
2017
2018    Output:
2019    ADJUSTMENT_DEF - a tree that holds a value to be added to the final result
2020         of the reduction (used for adjusting the epilog - see below).
2021    Return a vector variable, initialized according to the operation that STMT
2022         performs. This vector will be used as the initial value of the
2023         vector of partial results.
2024
2025    Option1 (adjust in epilog): Initialize the vector as follows:
2026      add:         [0,0,...,0,0]
2027      mult:        [1,1,...,1,1]
2028      min/max:     [init_val,init_val,..,init_val,init_val]
2029      bit and/or:  [init_val,init_val,..,init_val,init_val]
2030    and when necessary (e.g. add/mult case) let the caller know
2031    that it needs to adjust the result by init_val.
2032
2033    Option2: Initialize the vector as follows:
2034      add:         [0,0,...,0,init_val]
2035      mult:        [1,1,...,1,init_val]
2036      min/max:     [init_val,init_val,...,init_val]
2037      bit and/or:  [init_val,init_val,...,init_val]
2038    and no adjustments are needed.
2039
2040    For example, for the following code:
2041
2042    s = init_val;
2043    for (i=0;i<n;i++)
2044      s = s + a[i];
2045
2046    STMT is 's = s + a[i]', and the reduction variable is 's'.
2047    For a vector of 4 units, we want to return either [0,0,0,init_val],
2048    or [0,0,0,0] and let the caller know that it needs to adjust
2049    the result at the end by 'init_val'.
2050
2051    FORNOW, we are using the 'adjust in epilog' scheme, because this way the
2052    initialization vector is simpler (same element in all entries).
2053    A cost model should help decide between these two schemes.  */
2054
2055 static tree
2056 get_initial_def_for_reduction (tree stmt, tree init_val, tree *adjustment_def)
2057 {
2058   stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt);
2059   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
2060   struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
2061   tree vectype = STMT_VINFO_VECTYPE (stmt_vinfo);
2062   int nunits =  TYPE_VECTOR_SUBPARTS (vectype);
2063   enum tree_code code = TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 1));
2064   tree type = TREE_TYPE (init_val);
2065   tree vecdef;
2066   tree def_for_init;
2067   tree init_def;
2068   tree t = NULL_TREE;
2069   int i;
2070   tree vector_type;
2071   bool nested_in_vect_loop = false; 
2072
2073   gcc_assert (INTEGRAL_TYPE_P (type) || SCALAR_FLOAT_TYPE_P (type));
2074   if (nested_in_vect_loop_p (loop, stmt))
2075     nested_in_vect_loop = true;
2076   else
2077     gcc_assert (loop == (bb_for_stmt (stmt))->loop_father);
2078
2079   vecdef = vect_get_vec_def_for_operand (init_val, stmt, NULL);
2080
2081   switch (code)
2082   {
2083   case WIDEN_SUM_EXPR:
2084   case DOT_PROD_EXPR:
2085   case PLUS_EXPR:
2086       if (nested_in_vect_loop)
2087         *adjustment_def = vecdef;
2088       else
2089         *adjustment_def = init_val;
2090     /* Create a vector of zeros for init_def.  */
2091     if (INTEGRAL_TYPE_P (type))
2092       def_for_init = build_int_cst (type, 0);
2093     else
2094       def_for_init = build_real (type, dconst0);
2095       for (i = nunits - 1; i >= 0; --i)
2096     t = tree_cons (NULL_TREE, def_for_init, t);
2097     vector_type = get_vectype_for_scalar_type (TREE_TYPE (def_for_init));
2098     init_def = build_vector (vector_type, t);
2099     break;
2100
2101   case MIN_EXPR:
2102   case MAX_EXPR:
2103     *adjustment_def = NULL_TREE;
2104     init_def = vecdef;
2105     break;
2106
2107   default:
2108     gcc_unreachable ();
2109   }
2110
2111   return init_def;
2112 }
2113
2114
2115 /* Function vect_create_epilog_for_reduction
2116     
2117    Create code at the loop-epilog to finalize the result of a reduction
2118    computation. 
2119   
2120    VECT_DEF is a vector of partial results. 
2121    REDUC_CODE is the tree-code for the epilog reduction.
2122    STMT is the scalar reduction stmt that is being vectorized.
2123    REDUCTION_PHI is the phi-node that carries the reduction computation.
2124
2125    This function:
2126    1. Creates the reduction def-use cycle: sets the arguments for 
2127       REDUCTION_PHI:
2128       The loop-entry argument is the vectorized initial-value of the reduction.
2129       The loop-latch argument is VECT_DEF - the vector of partial sums.
2130    2. "Reduces" the vector of partial results VECT_DEF into a single result,
2131       by applying the operation specified by REDUC_CODE if available, or by 
2132       other means (whole-vector shifts or a scalar loop).
2133       The function also creates a new phi node at the loop exit to preserve 
2134       loop-closed form, as illustrated below.
2135   
2136      The flow at the entry to this function:
2137     
2138         loop:
2139           vec_def = phi <null, null>            # REDUCTION_PHI
2140           VECT_DEF = vector_stmt                # vectorized form of STMT
2141           s_loop = scalar_stmt                  # (scalar) STMT
2142         loop_exit:
2143           s_out0 = phi <s_loop>                 # (scalar) EXIT_PHI
2144           use <s_out0>
2145           use <s_out0>
2146
2147      The above is transformed by this function into:
2148
2149         loop:
2150           vec_def = phi <vec_init, VECT_DEF>    # REDUCTION_PHI
2151           VECT_DEF = vector_stmt                # vectorized form of STMT
2152           s_loop = scalar_stmt                  # (scalar) STMT 
2153         loop_exit:
2154           s_out0 = phi <s_loop>                 # (scalar) EXIT_PHI
2155           v_out1 = phi <VECT_DEF>               # NEW_EXIT_PHI
2156           v_out2 = reduce <v_out1>
2157           s_out3 = extract_field <v_out2, 0>
2158           s_out4 = adjust_result <s_out3>
2159           use <s_out4>
2160           use <s_out4>
2161 */
2162
2163 static void
2164 vect_create_epilog_for_reduction (tree vect_def, tree stmt,
2165                                   enum tree_code reduc_code, tree reduction_phi)
2166 {
2167   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
2168   tree vectype;
2169   enum machine_mode mode;
2170   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
2171   struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
2172   basic_block exit_bb;
2173   tree scalar_dest;
2174   tree scalar_type;
2175   tree new_phi;
2176   block_stmt_iterator exit_bsi;
2177   tree vec_dest;
2178   tree new_temp = NULL_TREE;
2179   tree new_name;
2180   tree epilog_stmt = NULL_TREE;
2181   tree new_scalar_dest, exit_phi, new_dest;
2182   tree bitsize, bitpos, bytesize; 
2183   enum tree_code code = TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 1));
2184   tree adjustment_def;
2185   tree vec_initial_def;
2186   tree orig_name;
2187   imm_use_iterator imm_iter;
2188   use_operand_p use_p;
2189   bool extract_scalar_result = false;
2190   tree reduction_op, expr;
2191   tree orig_stmt;
2192   tree use_stmt;
2193   tree operation = GIMPLE_STMT_OPERAND (stmt, 1);
2194   bool nested_in_vect_loop = false;
2195   int op_type;
2196   VEC(tree,heap) *phis = NULL;
2197   int i;
2198   
2199   if (nested_in_vect_loop_p (loop, stmt))
2200     {
2201       loop = loop->inner;
2202       nested_in_vect_loop = true;
2203     }
2204   
2205   op_type = TREE_OPERAND_LENGTH (operation);
2206   reduction_op = TREE_OPERAND (operation, op_type-1);
2207   vectype = get_vectype_for_scalar_type (TREE_TYPE (reduction_op));
2208   mode = TYPE_MODE (vectype);
2209
2210   /*** 1. Create the reduction def-use cycle  ***/
2211   
2212   /* 1.1 set the loop-entry arg of the reduction-phi:  */
2213   /* For the case of reduction, vect_get_vec_def_for_operand returns
2214      the scalar def before the loop, that defines the initial value
2215      of the reduction variable.  */
2216   vec_initial_def = vect_get_vec_def_for_operand (reduction_op, stmt,
2217                                                   &adjustment_def);
2218   add_phi_arg (reduction_phi, vec_initial_def, loop_preheader_edge (loop));
2219
2220   /* 1.2 set the loop-latch arg for the reduction-phi:  */
2221   add_phi_arg (reduction_phi, vect_def, loop_latch_edge (loop));
2222
2223   if (vect_print_dump_info (REPORT_DETAILS))
2224     {
2225       fprintf (vect_dump, "transform reduction: created def-use cycle:");
2226       print_generic_expr (vect_dump, reduction_phi, TDF_SLIM);
2227       fprintf (vect_dump, "\n");
2228       print_generic_expr (vect_dump, SSA_NAME_DEF_STMT (vect_def), TDF_SLIM);
2229     }
2230
2231
2232   /*** 2. Create epilog code
2233           The reduction epilog code operates across the elements of the vector
2234           of partial results computed by the vectorized loop.
2235           The reduction epilog code consists of:
2236           step 1: compute the scalar result in a vector (v_out2)
2237           step 2: extract the scalar result (s_out3) from the vector (v_out2)
2238           step 3: adjust the scalar result (s_out3) if needed.
2239
2240           Step 1 can be accomplished using one the following three schemes:
2241           (scheme 1) using reduc_code, if available.
2242           (scheme 2) using whole-vector shifts, if available.
2243           (scheme 3) using a scalar loop. In this case steps 1+2 above are 
2244                      combined.
2245                 
2246           The overall epilog code looks like this:
2247
2248           s_out0 = phi <s_loop>         # original EXIT_PHI
2249           v_out1 = phi <VECT_DEF>       # NEW_EXIT_PHI
2250           v_out2 = reduce <v_out1>              # step 1
2251           s_out3 = extract_field <v_out2, 0>    # step 2
2252           s_out4 = adjust_result <s_out3>       # step 3
2253
2254           (step 3 is optional, and step2 1 and 2 may be combined).
2255           Lastly, the uses of s_out0 are replaced by s_out4.
2256
2257           ***/
2258
2259   /* 2.1 Create new loop-exit-phi to preserve loop-closed form:
2260         v_out1 = phi <v_loop>  */
2261
2262   exit_bb = single_exit (loop)->dest;
2263   new_phi = create_phi_node (SSA_NAME_VAR (vect_def), exit_bb);
2264   SET_PHI_ARG_DEF (new_phi, single_exit (loop)->dest_idx, vect_def);
2265   exit_bsi = bsi_after_labels (exit_bb);
2266
2267   /* 2.2 Get the relevant tree-code to use in the epilog for schemes 2,3 
2268          (i.e. when reduc_code is not available) and in the final adjustment
2269          code (if needed).  Also get the original scalar reduction variable as
2270          defined in the loop.  In case STMT is a "pattern-stmt" (i.e. - it 
2271          represents a reduction pattern), the tree-code and scalar-def are 
2272          taken from the original stmt that the pattern-stmt (STMT) replaces.  
2273          Otherwise (it is a regular reduction) - the tree-code and scalar-def
2274          are taken from STMT.  */ 
2275
2276   orig_stmt = STMT_VINFO_RELATED_STMT (stmt_info);
2277   if (!orig_stmt)
2278     {
2279       /* Regular reduction  */
2280       orig_stmt = stmt;
2281     }
2282   else
2283     {
2284       /* Reduction pattern  */
2285       stmt_vec_info stmt_vinfo = vinfo_for_stmt (orig_stmt);
2286       gcc_assert (STMT_VINFO_IN_PATTERN_P (stmt_vinfo));
2287       gcc_assert (STMT_VINFO_RELATED_STMT (stmt_vinfo) == stmt);
2288     }
2289   code = TREE_CODE (GIMPLE_STMT_OPERAND (orig_stmt, 1));
2290   scalar_dest = GIMPLE_STMT_OPERAND (orig_stmt, 0);
2291   scalar_type = TREE_TYPE (scalar_dest);
2292   new_scalar_dest = vect_create_destination_var (scalar_dest, NULL);
2293   bitsize = TYPE_SIZE (scalar_type);
2294   bytesize = TYPE_SIZE_UNIT (scalar_type);
2295
2296
2297   /* In case this is a reduction in an inner-loop while vectorizing an outer
2298      loop - we don't need to extract a single scalar result at the end of the
2299      inner-loop.  The final vector of partial results will be used in the
2300      vectorized outer-loop, or reduced to a scalar result at the end of the
2301      outer-loop.  */
2302   if (nested_in_vect_loop)
2303     goto vect_finalize_reduction;
2304
2305   /* 2.3 Create the reduction code, using one of the three schemes described
2306          above.  */
2307
2308   if (reduc_code < NUM_TREE_CODES)
2309     {
2310       tree tmp;
2311
2312       /*** Case 1:  Create:
2313            v_out2 = reduc_expr <v_out1>  */
2314
2315       if (vect_print_dump_info (REPORT_DETAILS))
2316         fprintf (vect_dump, "Reduce using direct vector reduction.");
2317
2318       vec_dest = vect_create_destination_var (scalar_dest, vectype);
2319       tmp = build1 (reduc_code, vectype,  PHI_RESULT (new_phi));
2320       epilog_stmt = build_gimple_modify_stmt (vec_dest, tmp);
2321       new_temp = make_ssa_name (vec_dest, epilog_stmt);
2322       GIMPLE_STMT_OPERAND (epilog_stmt, 0) = new_temp;
2323       bsi_insert_before (&exit_bsi, epilog_stmt, BSI_SAME_STMT);
2324
2325       extract_scalar_result = true;
2326     }
2327   else
2328     {
2329       enum tree_code shift_code = 0;
2330       bool have_whole_vector_shift = true;
2331       int bit_offset;
2332       int element_bitsize = tree_low_cst (bitsize, 1);
2333       int vec_size_in_bits = tree_low_cst (TYPE_SIZE (vectype), 1);
2334       tree vec_temp;
2335
2336       if (optab_handler (vec_shr_optab, mode)->insn_code != CODE_FOR_nothing)
2337         shift_code = VEC_RSHIFT_EXPR;
2338       else
2339         have_whole_vector_shift = false;
2340
2341       /* Regardless of whether we have a whole vector shift, if we're
2342          emulating the operation via tree-vect-generic, we don't want
2343          to use it.  Only the first round of the reduction is likely
2344          to still be profitable via emulation.  */
2345       /* ??? It might be better to emit a reduction tree code here, so that
2346          tree-vect-generic can expand the first round via bit tricks.  */
2347       if (!VECTOR_MODE_P (mode))
2348         have_whole_vector_shift = false;
2349       else
2350         {
2351           optab optab = optab_for_tree_code (code, vectype);
2352           if (optab_handler (optab, mode)->insn_code == CODE_FOR_nothing)
2353             have_whole_vector_shift = false;
2354         }
2355
2356       if (have_whole_vector_shift)
2357         {
2358           /*** Case 2: Create:
2359              for (offset = VS/2; offset >= element_size; offset/=2)
2360                 {
2361                   Create:  va' = vec_shift <va, offset>
2362                   Create:  va = vop <va, va'>
2363                 }  */
2364
2365           if (vect_print_dump_info (REPORT_DETAILS))
2366             fprintf (vect_dump, "Reduce using vector shifts");
2367
2368           vec_dest = vect_create_destination_var (scalar_dest, vectype);
2369           new_temp = PHI_RESULT (new_phi);
2370
2371           for (bit_offset = vec_size_in_bits/2;
2372                bit_offset >= element_bitsize;
2373                bit_offset /= 2)
2374             {
2375               tree bitpos = size_int (bit_offset);
2376               tree tmp = build2 (shift_code, vectype, new_temp, bitpos);
2377               epilog_stmt = build_gimple_modify_stmt (vec_dest, tmp);
2378               new_name = make_ssa_name (vec_dest, epilog_stmt);
2379               GIMPLE_STMT_OPERAND (epilog_stmt, 0) = new_name;
2380               bsi_insert_before (&exit_bsi, epilog_stmt, BSI_SAME_STMT);
2381
2382               tmp = build2 (code, vectype, new_name, new_temp);
2383               epilog_stmt = build_gimple_modify_stmt (vec_dest, tmp);
2384               new_temp = make_ssa_name (vec_dest, epilog_stmt);
2385               GIMPLE_STMT_OPERAND (epilog_stmt, 0) = new_temp;
2386               bsi_insert_before (&exit_bsi, epilog_stmt, BSI_SAME_STMT);
2387             }
2388
2389           extract_scalar_result = true;
2390         }
2391       else
2392         {
2393           tree rhs;
2394
2395           /*** Case 3: Create:  
2396              s = extract_field <v_out2, 0>
2397              for (offset = element_size; 
2398                   offset < vector_size; 
2399                   offset += element_size;)
2400                {
2401                  Create:  s' = extract_field <v_out2, offset>
2402                  Create:  s = op <s, s'>
2403                }  */
2404
2405           if (vect_print_dump_info (REPORT_DETAILS))
2406             fprintf (vect_dump, "Reduce using scalar code. ");
2407
2408           vec_temp = PHI_RESULT (new_phi);
2409           vec_size_in_bits = tree_low_cst (TYPE_SIZE (vectype), 1);
2410           rhs = build3 (BIT_FIELD_REF, scalar_type, vec_temp, bitsize,
2411                          bitsize_zero_node);
2412           BIT_FIELD_REF_UNSIGNED (rhs) = TYPE_UNSIGNED (scalar_type);
2413           epilog_stmt = build_gimple_modify_stmt (new_scalar_dest, rhs);
2414           new_temp = make_ssa_name (new_scalar_dest, epilog_stmt);
2415           GIMPLE_STMT_OPERAND (epilog_stmt, 0) = new_temp;
2416           bsi_insert_before (&exit_bsi, epilog_stmt, BSI_SAME_STMT);
2417               
2418           for (bit_offset = element_bitsize;
2419                bit_offset < vec_size_in_bits;
2420                bit_offset += element_bitsize)
2421             { 
2422               tree tmp;
2423               tree bitpos = bitsize_int (bit_offset);
2424               tree rhs = build3 (BIT_FIELD_REF, scalar_type, vec_temp, bitsize,
2425                                  bitpos);
2426                 
2427               BIT_FIELD_REF_UNSIGNED (rhs) = TYPE_UNSIGNED (scalar_type);
2428               epilog_stmt = build_gimple_modify_stmt (new_scalar_dest, rhs);
2429               new_name = make_ssa_name (new_scalar_dest, epilog_stmt);
2430               GIMPLE_STMT_OPERAND (epilog_stmt, 0) = new_name;
2431               bsi_insert_before (&exit_bsi, epilog_stmt, BSI_SAME_STMT);
2432
2433               tmp = build2 (code, scalar_type, new_name, new_temp);
2434               epilog_stmt = build_gimple_modify_stmt (new_scalar_dest, tmp);
2435               new_temp = make_ssa_name (new_scalar_dest, epilog_stmt);
2436               GIMPLE_STMT_OPERAND (epilog_stmt, 0) = new_temp;
2437               bsi_insert_before (&exit_bsi, epilog_stmt, BSI_SAME_STMT);
2438             }
2439
2440           extract_scalar_result = false;
2441         }
2442     }
2443
2444   /* 2.4  Extract the final scalar result.  Create:
2445          s_out3 = extract_field <v_out2, bitpos>  */
2446   
2447   if (extract_scalar_result)
2448     {
2449       tree rhs;
2450
2451       gcc_assert (!nested_in_vect_loop);
2452       if (vect_print_dump_info (REPORT_DETAILS))
2453         fprintf (vect_dump, "extract scalar result");
2454
2455       if (BYTES_BIG_ENDIAN)
2456         bitpos = size_binop (MULT_EXPR,
2457                        bitsize_int (TYPE_VECTOR_SUBPARTS (vectype) - 1),
2458                        TYPE_SIZE (scalar_type));
2459       else
2460         bitpos = bitsize_zero_node;
2461
2462       rhs = build3 (BIT_FIELD_REF, scalar_type, new_temp, bitsize, bitpos);
2463       BIT_FIELD_REF_UNSIGNED (rhs) = TYPE_UNSIGNED (scalar_type);
2464       epilog_stmt = build_gimple_modify_stmt (new_scalar_dest, rhs);
2465       new_temp = make_ssa_name (new_scalar_dest, epilog_stmt);
2466       GIMPLE_STMT_OPERAND (epilog_stmt, 0) = new_temp; 
2467       bsi_insert_before (&exit_bsi, epilog_stmt, BSI_SAME_STMT);
2468     }
2469
2470 vect_finalize_reduction:
2471
2472   /* 2.5 Adjust the final result by the initial value of the reduction
2473          variable. (When such adjustment is not needed, then
2474          'adjustment_def' is zero).  For example, if code is PLUS we create:
2475          new_temp = loop_exit_def + adjustment_def  */
2476
2477   if (adjustment_def)
2478     {
2479       if (nested_in_vect_loop)
2480         {
2481           gcc_assert (TREE_CODE (TREE_TYPE (adjustment_def)) == VECTOR_TYPE);
2482           expr = build2 (code, vectype, PHI_RESULT (new_phi), adjustment_def);
2483           new_dest = vect_create_destination_var (scalar_dest, vectype);
2484         }
2485       else
2486         {
2487           gcc_assert (TREE_CODE (TREE_TYPE (adjustment_def)) != VECTOR_TYPE);
2488           expr = build2 (code, scalar_type, new_temp, adjustment_def);
2489           new_dest = vect_create_destination_var (scalar_dest, scalar_type);
2490         }
2491       epilog_stmt = build_gimple_modify_stmt (new_dest, expr);
2492       new_temp = make_ssa_name (new_dest, epilog_stmt);
2493       GIMPLE_STMT_OPERAND (epilog_stmt, 0) = new_temp;
2494       bsi_insert_before (&exit_bsi, epilog_stmt, BSI_SAME_STMT);
2495     }
2496
2497
2498   /* 2.6  Handle the loop-exit phi  */
2499
2500   /* Replace uses of s_out0 with uses of s_out3:
2501      Find the loop-closed-use at the loop exit of the original scalar result.
2502      (The reduction result is expected to have two immediate uses - one at the 
2503      latch block, and one at the loop exit).  */
2504   phis = VEC_alloc (tree, heap, 10);
2505   FOR_EACH_IMM_USE_FAST (use_p, imm_iter, scalar_dest)
2506     {
2507       if (!flow_bb_inside_loop_p (loop, bb_for_stmt (USE_STMT (use_p))))
2508         {
2509           exit_phi = USE_STMT (use_p);
2510           VEC_quick_push (tree, phis, exit_phi);
2511         }
2512     }
2513   /* We expect to have found an exit_phi because of loop-closed-ssa form.  */
2514   gcc_assert (!VEC_empty (tree, phis));
2515
2516   for (i = 0; VEC_iterate (tree, phis, i, exit_phi); i++)
2517     {
2518       if (nested_in_vect_loop)
2519         {
2520           stmt_vec_info stmt_vinfo = vinfo_for_stmt (exit_phi);
2521
2522           /* FORNOW. Currently not supporting the case that an inner-loop reduction
2523              is not used in the outer-loop (but only outside the outer-loop).  */
2524           gcc_assert (STMT_VINFO_RELEVANT_P (stmt_vinfo) 
2525                       && !STMT_VINFO_LIVE_P (stmt_vinfo));
2526
2527           epilog_stmt = adjustment_def ? epilog_stmt :  new_phi;
2528           STMT_VINFO_VEC_STMT (stmt_vinfo) = epilog_stmt;
2529           set_stmt_info (get_stmt_ann (epilog_stmt),
2530           new_stmt_vec_info (epilog_stmt, loop_vinfo));
2531           continue;
2532         }
2533
2534       /* Replace the uses:  */
2535       orig_name = PHI_RESULT (exit_phi);
2536       FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter, orig_name)
2537         FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter)
2538           SET_USE (use_p, new_temp);
2539     }
2540   VEC_free (tree, heap, phis);
2541
2542
2543
2544 /* Function vectorizable_reduction.
2545
2546    Check if STMT performs a reduction operation that can be vectorized.
2547    If VEC_STMT is also passed, vectorize the STMT: create a vectorized
2548    stmt to replace it, put it in VEC_STMT, and insert it at BSI.
2549    Return FALSE if not a vectorizable STMT, TRUE otherwise.
2550
2551    This function also handles reduction idioms (patterns) that have been 
2552    recognized in advance during vect_pattern_recog. In this case, STMT may be
2553    of this form:
2554      X = pattern_expr (arg0, arg1, ..., X)
2555    and it's STMT_VINFO_RELATED_STMT points to the last stmt in the original
2556    sequence that had been detected and replaced by the pattern-stmt (STMT).
2557   
2558    In some cases of reduction patterns, the type of the reduction variable X is
2559    different than the type of the other arguments of STMT.
2560    In such cases, the vectype that is used when transforming STMT into a vector
2561    stmt is different than the vectype that is used to determine the
2562    vectorization factor, because it consists of a different number of elements 
2563    than the actual number of elements that are being operated upon in parallel.
2564
2565    For example, consider an accumulation of shorts into an int accumulator.
2566    On some targets it's possible to vectorize this pattern operating on 8
2567    shorts at a time (hence, the vectype for purposes of determining the
2568    vectorization factor should be V8HI); on the other hand, the vectype that
2569    is used to create the vector form is actually V4SI (the type of the result).
2570
2571    Upon entry to this function, STMT_VINFO_VECTYPE records the vectype that
2572    indicates what is the actual level of parallelism (V8HI in the example), so
2573    that the right vectorization factor would be derived. This vectype
2574    corresponds to the type of arguments to the reduction stmt, and should *NOT*
2575    be used to create the vectorized stmt. The right vectype for the vectorized
2576    stmt is obtained from the type of the result X:
2577         get_vectype_for_scalar_type (TREE_TYPE (X))
2578
2579    This means that, contrary to "regular" reductions (or "regular" stmts in
2580    general), the following equation:
2581       STMT_VINFO_VECTYPE == get_vectype_for_scalar_type (TREE_TYPE (X))
2582    does *NOT* necessarily hold for reduction patterns.  */
2583
2584 bool
2585 vectorizable_reduction (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt)
2586 {
2587   tree vec_dest;
2588   tree scalar_dest;
2589   tree op;
2590   tree loop_vec_def0 = NULL_TREE, loop_vec_def1 = NULL_TREE;
2591   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
2592   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
2593   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
2594   struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
2595   tree operation;
2596   enum tree_code code, orig_code, epilog_reduc_code = 0;
2597   enum machine_mode vec_mode;
2598   int op_type;
2599   optab optab, reduc_optab;
2600   tree new_temp = NULL_TREE;
2601   tree def, def_stmt;
2602   enum vect_def_type dt;
2603   tree new_phi;
2604   tree scalar_type;
2605   bool is_simple_use;
2606   tree orig_stmt;
2607   stmt_vec_info orig_stmt_info;
2608   tree expr = NULL_TREE;
2609   int i;
2610   int nunits = TYPE_VECTOR_SUBPARTS (vectype);
2611   int ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits;
2612   stmt_vec_info prev_stmt_info;
2613   tree reduc_def;
2614   tree new_stmt = NULL_TREE;
2615   int j;
2616
2617   if (nested_in_vect_loop_p (loop, stmt))
2618     {
2619       loop = loop->inner;
2620       /* FORNOW. This restriction should be relaxed.  */
2621       if (ncopies > 1)
2622         {
2623           if (vect_print_dump_info (REPORT_DETAILS))
2624             fprintf (vect_dump, "multiple types in nested loop.");
2625           return false;
2626         }
2627     }
2628
2629   gcc_assert (ncopies >= 1);
2630
2631   /* FORNOW: SLP not supported.  */
2632   if (STMT_SLP_TYPE (stmt_info))
2633     return false;
2634
2635   /* 1. Is vectorizable reduction?  */
2636
2637   /* Not supportable if the reduction variable is used in the loop.  */
2638   if (STMT_VINFO_RELEVANT (stmt_info) > vect_used_in_outer)
2639     return false;
2640
2641   /* Reductions that are not used even in an enclosing outer-loop,
2642      are expected to be "live" (used out of the loop).  */
2643   if (STMT_VINFO_RELEVANT (stmt_info) == vect_unused_in_loop
2644       && !STMT_VINFO_LIVE_P (stmt_info))
2645     return false;
2646
2647   /* Make sure it was already recognized as a reduction computation.  */
2648   if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_reduction_def)
2649     return false;
2650
2651   /* 2. Has this been recognized as a reduction pattern? 
2652
2653      Check if STMT represents a pattern that has been recognized
2654      in earlier analysis stages.  For stmts that represent a pattern,
2655      the STMT_VINFO_RELATED_STMT field records the last stmt in
2656      the original sequence that constitutes the pattern.  */
2657
2658   orig_stmt = STMT_VINFO_RELATED_STMT (stmt_info);
2659   if (orig_stmt)
2660     {
2661       orig_stmt_info = vinfo_for_stmt (orig_stmt);
2662       gcc_assert (STMT_VINFO_RELATED_STMT (orig_stmt_info) == stmt);
2663       gcc_assert (STMT_VINFO_IN_PATTERN_P (orig_stmt_info));
2664       gcc_assert (!STMT_VINFO_IN_PATTERN_P (stmt_info));
2665     }
2666  
2667   /* 3. Check the operands of the operation. The first operands are defined
2668         inside the loop body. The last operand is the reduction variable,
2669         which is defined by the loop-header-phi.  */
2670
2671   gcc_assert (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT);
2672
2673   operation = GIMPLE_STMT_OPERAND (stmt, 1);
2674   code = TREE_CODE (operation);
2675   op_type = TREE_OPERAND_LENGTH (operation);
2676   if (op_type != binary_op && op_type != ternary_op)
2677     return false;
2678   scalar_dest = GIMPLE_STMT_OPERAND (stmt, 0);
2679   scalar_type = TREE_TYPE (scalar_dest);
2680
2681   /* All uses but the last are expected to be defined in the loop.
2682      The last use is the reduction variable.  */
2683   for (i = 0; i < op_type-1; i++)
2684     {
2685       op = TREE_OPERAND (operation, i);
2686       is_simple_use = vect_is_simple_use (op, loop_vinfo, &def_stmt, &def, &dt);
2687       gcc_assert (is_simple_use);
2688       if (dt != vect_loop_def
2689           && dt != vect_invariant_def
2690           && dt != vect_constant_def
2691           && dt != vect_induction_def)
2692         return false;
2693     }
2694
2695   op = TREE_OPERAND (operation, i);
2696   is_simple_use = vect_is_simple_use (op, loop_vinfo, &def_stmt, &def, &dt);
2697   gcc_assert (is_simple_use);
2698   gcc_assert (dt == vect_reduction_def);
2699   gcc_assert (TREE_CODE (def_stmt) == PHI_NODE);
2700   if (orig_stmt) 
2701     gcc_assert (orig_stmt == vect_is_simple_reduction (loop_vinfo, def_stmt));
2702   else
2703     gcc_assert (stmt == vect_is_simple_reduction (loop_vinfo, def_stmt));
2704   
2705   if (STMT_VINFO_LIVE_P (vinfo_for_stmt (def_stmt)))
2706     return false;
2707
2708   /* 4. Supportable by target?  */
2709
2710   /* 4.1. check support for the operation in the loop  */
2711   optab = optab_for_tree_code (code, vectype);
2712   if (!optab)
2713     {
2714       if (vect_print_dump_info (REPORT_DETAILS))
2715         fprintf (vect_dump, "no optab.");
2716       return false;
2717     }
2718   vec_mode = TYPE_MODE (vectype);
2719   if (optab_handler (optab, vec_mode)->insn_code == CODE_FOR_nothing)
2720     {
2721       if (vect_print_dump_info (REPORT_DETAILS))
2722         fprintf (vect_dump, "op not supported by target.");
2723       if (GET_MODE_SIZE (vec_mode) != UNITS_PER_WORD
2724           || LOOP_VINFO_VECT_FACTOR (loop_vinfo)
2725              < vect_min_worthwhile_factor (code))
2726         return false;
2727       if (vect_print_dump_info (REPORT_DETAILS))
2728         fprintf (vect_dump, "proceeding using word mode.");
2729     }
2730
2731   /* Worthwhile without SIMD support?  */
2732   if (!VECTOR_MODE_P (TYPE_MODE (vectype))
2733       && LOOP_VINFO_VECT_FACTOR (loop_vinfo)
2734          < vect_min_worthwhile_factor (code))
2735     {
2736       if (vect_print_dump_info (REPORT_DETAILS))
2737         fprintf (vect_dump, "not worthwhile without SIMD support.");
2738       return false;
2739     }
2740
2741   /* 4.2. Check support for the epilog operation.
2742
2743           If STMT represents a reduction pattern, then the type of the
2744           reduction variable may be different than the type of the rest
2745           of the arguments.  For example, consider the case of accumulation
2746           of shorts into an int accumulator; The original code:
2747                         S1: int_a = (int) short_a;
2748           orig_stmt->   S2: int_acc = plus <int_a ,int_acc>;
2749
2750           was replaced with:
2751                         STMT: int_acc = widen_sum <short_a, int_acc>
2752
2753           This means that:
2754           1. The tree-code that is used to create the vector operation in the 
2755              epilog code (that reduces the partial results) is not the 
2756              tree-code of STMT, but is rather the tree-code of the original 
2757              stmt from the pattern that STMT is replacing. I.e, in the example 
2758              above we want to use 'widen_sum' in the loop, but 'plus' in the 
2759              epilog.
2760           2. The type (mode) we use to check available target support
2761              for the vector operation to be created in the *epilog*, is 
2762              determined by the type of the reduction variable (in the example 
2763              above we'd check this: plus_optab[vect_int_mode]).
2764              However the type (mode) we use to check available target support
2765              for the vector operation to be created *inside the loop*, is
2766              determined by the type of the other arguments to STMT (in the
2767              example we'd check this: widen_sum_optab[vect_short_mode]).
2768   
2769           This is contrary to "regular" reductions, in which the types of all 
2770           the arguments are the same as the type of the reduction variable. 
2771           For "regular" reductions we can therefore use the same vector type 
2772           (and also the same tree-code) when generating the epilog code and
2773           when generating the code inside the loop.  */
2774
2775   if (orig_stmt)
2776     {
2777       /* This is a reduction pattern: get the vectype from the type of the
2778          reduction variable, and get the tree-code from orig_stmt.  */
2779       orig_code = TREE_CODE (GIMPLE_STMT_OPERAND (orig_stmt, 1));
2780       vectype = get_vectype_for_scalar_type (TREE_TYPE (def));
2781       vec_mode = TYPE_MODE (vectype);
2782     }
2783   else
2784     {
2785       /* Regular reduction: use the same vectype and tree-code as used for
2786          the vector code inside the loop can be used for the epilog code. */
2787       orig_code = code;
2788     }
2789
2790   if (!reduction_code_for_scalar_code (orig_code, &epilog_reduc_code))
2791     return false;
2792   reduc_optab = optab_for_tree_code (epilog_reduc_code, vectype);
2793   if (!reduc_optab)
2794     {
2795       if (vect_print_dump_info (REPORT_DETAILS))
2796         fprintf (vect_dump, "no optab for reduction.");
2797       epilog_reduc_code = NUM_TREE_CODES;
2798     }
2799   if (optab_handler (reduc_optab, vec_mode)->insn_code == CODE_FOR_nothing)
2800     {
2801       if (vect_print_dump_info (REPORT_DETAILS))
2802         fprintf (vect_dump, "reduc op not supported by target.");
2803       epilog_reduc_code = NUM_TREE_CODES;
2804     }
2805  
2806   if (!vec_stmt) /* transformation not required.  */
2807     {
2808       STMT_VINFO_TYPE (stmt_info) = reduc_vec_info_type;
2809       vect_model_reduction_cost (stmt_info, epilog_reduc_code, ncopies);
2810       return true;
2811     }
2812
2813   /** Transform.  **/
2814
2815   if (vect_print_dump_info (REPORT_DETAILS))
2816     fprintf (vect_dump, "transform reduction.");
2817
2818   /* Create the destination vector  */
2819   vec_dest = vect_create_destination_var (scalar_dest, vectype);
2820
2821   /* Create the reduction-phi that defines the reduction-operand.  */
2822   new_phi = create_phi_node (vec_dest, loop->header);
2823
2824   /* In case the vectorization factor (VF) is bigger than the number
2825      of elements that we can fit in a vectype (nunits), we have to generate
2826      more than one vector stmt - i.e - we need to "unroll" the
2827      vector stmt by a factor VF/nunits.  For more details see documentation
2828      in vectorizable_operation.  */
2829
2830   prev_stmt_info = NULL;
2831   for (j = 0; j < ncopies; j++)
2832     {
2833       /* Handle uses.  */
2834       if (j == 0)
2835         {
2836           op = TREE_OPERAND (operation, 0);
2837           loop_vec_def0 = vect_get_vec_def_for_operand (op, stmt, NULL);
2838           if (op_type == ternary_op)
2839             {
2840               op = TREE_OPERAND (operation, 1);
2841               loop_vec_def1 = vect_get_vec_def_for_operand (op, stmt, NULL);
2842             }
2843
2844           /* Get the vector def for the reduction variable from the phi node */
2845           reduc_def = PHI_RESULT (new_phi);
2846         }
2847       else
2848         {
2849           enum vect_def_type dt = vect_unknown_def_type; /* Dummy */
2850           loop_vec_def0 = vect_get_vec_def_for_stmt_copy (dt, loop_vec_def0);
2851           if (op_type == ternary_op)
2852             loop_vec_def1 = vect_get_vec_def_for_stmt_copy (dt, loop_vec_def1);
2853
2854           /* Get the vector def for the reduction variable from the vectorized
2855              reduction operation generated in the previous iteration (j-1)  */
2856           reduc_def = GIMPLE_STMT_OPERAND (new_stmt ,0);
2857         }
2858
2859       /* Arguments are ready. create the new vector stmt.  */
2860       if (op_type == binary_op)
2861         expr = build2 (code, vectype, loop_vec_def0, reduc_def);
2862       else
2863         expr = build3 (code, vectype, loop_vec_def0, loop_vec_def1, 
2864                        reduc_def);
2865       new_stmt = build_gimple_modify_stmt (vec_dest, expr);
2866       new_temp = make_ssa_name (vec_dest, new_stmt);
2867       GIMPLE_STMT_OPERAND (new_stmt, 0) = new_temp;
2868       vect_finish_stmt_generation (stmt, new_stmt, bsi);
2869
2870       if (j == 0)
2871         STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
2872       else
2873         STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
2874       prev_stmt_info = vinfo_for_stmt (new_stmt);
2875     }
2876
2877   /* Finalize the reduction-phi (set it's arguments) and create the
2878      epilog reduction code.  */
2879   vect_create_epilog_for_reduction (new_temp, stmt, epilog_reduc_code, new_phi);
2880   return true;
2881 }
2882
2883 /* Checks if CALL can be vectorized in type VECTYPE.  Returns
2884    a function declaration if the target has a vectorized version
2885    of the function, or NULL_TREE if the function cannot be vectorized.  */
2886
2887 tree
2888 vectorizable_function (tree call, tree vectype_out, tree vectype_in)
2889 {
2890   tree fndecl = get_callee_fndecl (call);
2891   enum built_in_function code;
2892
2893   /* We only handle functions that do not read or clobber memory -- i.e.
2894      const or novops ones.  */
2895   if (!(call_expr_flags (call) & (ECF_CONST | ECF_NOVOPS)))
2896     return NULL_TREE;
2897
2898   if (!fndecl
2899       || TREE_CODE (fndecl) != FUNCTION_DECL
2900       || !DECL_BUILT_IN (fndecl))
2901     return NULL_TREE;
2902
2903   code = DECL_FUNCTION_CODE (fndecl);
2904   return targetm.vectorize.builtin_vectorized_function (code, vectype_out,
2905                                                         vectype_in);
2906 }
2907
2908 /* Function vectorizable_call.
2909
2910    Check if STMT performs a function call that can be vectorized. 
2911    If VEC_STMT is also passed, vectorize the STMT: create a vectorized 
2912    stmt to replace it, put it in VEC_STMT, and insert it at BSI.
2913    Return FALSE if not a vectorizable STMT, TRUE otherwise.  */
2914
2915 bool
2916 vectorizable_call (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt)
2917 {
2918   tree vec_dest;
2919   tree scalar_dest;
2920   tree operation;
2921   tree op, type;
2922   tree vec_oprnd0 = NULL_TREE, vec_oprnd1 = NULL_TREE;
2923   stmt_vec_info stmt_info = vinfo_for_stmt (stmt), prev_stmt_info;
2924   tree vectype_out, vectype_in;
2925   int nunits_in;
2926   int nunits_out;
2927   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
2928   struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
2929   tree fndecl, rhs, new_temp, def, def_stmt, rhs_type, lhs_type;
2930   enum vect_def_type dt[2] = {vect_unknown_def_type, vect_unknown_def_type};
2931   tree new_stmt;
2932   int ncopies, j, nargs;
2933   call_expr_arg_iterator iter;
2934   tree vargs;
2935   enum { NARROW, NONE, WIDEN } modifier;
2936
2937   if (!STMT_VINFO_RELEVANT_P (stmt_info))
2938     return false;
2939
2940   if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_loop_def)
2941     return false;
2942
2943   /* FORNOW: SLP not supported.  */
2944   if (STMT_SLP_TYPE (stmt_info))
2945     return false;
2946
2947   /* FORNOW: not yet supported.  */
2948   if (STMT_VINFO_LIVE_P (stmt_info))
2949     {
2950       if (vect_print_dump_info (REPORT_DETAILS))
2951         fprintf (vect_dump, "value used after loop.");
2952       return false;
2953     }
2954
2955   /* Is STMT a vectorizable call?   */
2956   if (TREE_CODE (stmt) != GIMPLE_MODIFY_STMT)
2957     return false;
2958
2959   if (TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 0)) != SSA_NAME)
2960     return false;
2961
2962   operation = GIMPLE_STMT_OPERAND (stmt, 1);
2963   if (TREE_CODE (operation) != CALL_EXPR)
2964     return false;
2965
2966   /* Process function arguments.  */
2967   rhs_type = NULL_TREE;
2968   nargs = 0;
2969   FOR_EACH_CALL_EXPR_ARG (op, iter, operation)
2970     {
2971       /* Bail out if the function has more than two arguments, we
2972          do not have interesting builtin functions to vectorize with
2973          more than two arguments.  */
2974       if (nargs >= 2)
2975         return false;
2976
2977       /* We can only handle calls with arguments of the same type.  */
2978       if (rhs_type
2979           && rhs_type != TREE_TYPE (op))
2980         {
2981           if (vect_print_dump_info (REPORT_DETAILS))
2982             fprintf (vect_dump, "argument types differ.");
2983           return false;
2984         }
2985       rhs_type = TREE_TYPE (op);
2986
2987       if (!vect_is_simple_use (op, loop_vinfo, &def_stmt, &def, &dt[nargs]))
2988         {
2989           if (vect_print_dump_info (REPORT_DETAILS))
2990             fprintf (vect_dump, "use not simple.");
2991           return false;
2992         }
2993
2994       ++nargs;
2995     }
2996
2997   /* No arguments is also not good.  */
2998   if (nargs == 0)
2999     return false;
3000
3001   vectype_in = get_vectype_for_scalar_type (rhs_type);
3002   nunits_in = TYPE_VECTOR_SUBPARTS (vectype_in);
3003
3004   lhs_type = TREE_TYPE (GIMPLE_STMT_OPERAND (stmt, 0));
3005   vectype_out = get_vectype_for_scalar_type (lhs_type);
3006   nunits_out = TYPE_VECTOR_SUBPARTS (vectype_out);
3007
3008   /* FORNOW */
3009   if (nunits_in == nunits_out / 2)
3010     modifier = NARROW;
3011   else if (nunits_out == nunits_in)
3012     modifier = NONE;
3013   else if (nunits_out == nunits_in / 2)
3014     modifier = WIDEN;
3015   else
3016     return false;
3017
3018   /* For now, we only vectorize functions if a target specific builtin
3019      is available.  TODO -- in some cases, it might be profitable to
3020      insert the calls for pieces of the vector, in order to be able
3021      to vectorize other operations in the loop.  */
3022   fndecl = vectorizable_function (operation, vectype_out, vectype_in);
3023   if (fndecl == NULL_TREE)
3024     {
3025       if (vect_print_dump_info (REPORT_DETAILS))
3026         fprintf (vect_dump, "function is not vectorizable.");
3027
3028       return false;
3029     }
3030
3031   gcc_assert (ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS));
3032
3033   if (modifier == NARROW)
3034     ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits_out;
3035   else
3036     ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits_in;
3037
3038   /* Sanity check: make sure that at least one copy of the vectorized stmt
3039      needs to be generated.  */
3040   gcc_assert (ncopies >= 1);
3041
3042   /* FORNOW. This restriction should be relaxed.  */
3043   if (nested_in_vect_loop_p (loop, stmt) && ncopies > 1)
3044     {
3045       if (vect_print_dump_info (REPORT_DETAILS))
3046       fprintf (vect_dump, "multiple types in nested loop.");
3047       return false;
3048     }
3049
3050   if (!vec_stmt) /* transformation not required.  */
3051     {
3052       STMT_VINFO_TYPE (stmt_info) = call_vec_info_type;
3053       if (vect_print_dump_info (REPORT_DETAILS))
3054         fprintf (vect_dump, "=== vectorizable_call ===");
3055       vect_model_simple_cost (stmt_info, ncopies, dt, NULL);
3056       return true;
3057     }
3058
3059   /** Transform.  **/
3060
3061   if (vect_print_dump_info (REPORT_DETAILS))
3062     fprintf (vect_dump, "transform operation.");
3063
3064   /* FORNOW. This restriction should be relaxed.  */
3065   if (nested_in_vect_loop_p (loop, stmt) && ncopies > 1)
3066     {
3067       if (vect_print_dump_info (REPORT_DETAILS))
3068         fprintf (vect_dump, "multiple types in nested loop.");
3069       return false;
3070     }
3071
3072   /* Handle def.  */
3073   scalar_dest = GIMPLE_STMT_OPERAND (stmt, 0);
3074   vec_dest = vect_create_destination_var (scalar_dest, vectype_out);
3075
3076   prev_stmt_info = NULL;
3077   switch (modifier)
3078     {
3079     case NONE:
3080       for (j = 0; j < ncopies; ++j)
3081         {
3082           /* Build argument list for the vectorized call.  */
3083           /* FIXME: Rewrite this so that it doesn't
3084              construct a temporary list.  */
3085           vargs = NULL_TREE;
3086           nargs = 0;
3087           FOR_EACH_CALL_EXPR_ARG (op, iter, operation)
3088             {
3089               if (j == 0)
3090                 vec_oprnd0
3091                   = vect_get_vec_def_for_operand (op, stmt, NULL);
3092               else
3093                 vec_oprnd0
3094                   = vect_get_vec_def_for_stmt_copy (dt[nargs], vec_oprnd0);
3095
3096               vargs = tree_cons (NULL_TREE, vec_oprnd0, vargs);
3097
3098               ++nargs;
3099             }
3100           vargs = nreverse (vargs);
3101
3102           rhs = build_function_call_expr (fndecl, vargs);
3103           new_stmt = build_gimple_modify_stmt (vec_dest, rhs);
3104           new_temp = make_ssa_name (vec_dest, new_stmt);
3105           GIMPLE_STMT_OPERAND (new_stmt, 0) = new_temp;
3106
3107           vect_finish_stmt_generation (stmt, new_stmt, bsi);
3108
3109           if (j == 0)
3110             STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
3111           else
3112             STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
3113
3114           prev_stmt_info = vinfo_for_stmt (new_stmt);
3115         }
3116
3117       break;
3118
3119     case NARROW:
3120       for (j = 0; j < ncopies; ++j)
3121         {
3122           /* Build argument list for the vectorized call.  */
3123           /* FIXME: Rewrite this so that it doesn't
3124              construct a temporary list.  */
3125           vargs = NULL_TREE;
3126           nargs = 0;
3127           FOR_EACH_CALL_EXPR_ARG (op, iter, operation)
3128             {
3129               if (j == 0)
3130                 {
3131                   vec_oprnd0
3132                     = vect_get_vec_def_for_operand (op, stmt, NULL);
3133                   vec_oprnd1
3134                     = vect_get_vec_def_for_stmt_copy (dt[nargs], vec_oprnd0);
3135                 }
3136               else
3137                 {
3138                   vec_oprnd0
3139                     = vect_get_vec_def_for_stmt_copy (dt[nargs], vec_oprnd1);
3140                   vec_oprnd1
3141                     = vect_get_vec_def_for_stmt_copy (dt[nargs], vec_oprnd0);
3142                 }
3143
3144               vargs = tree_cons (NULL_TREE, vec_oprnd0, vargs);
3145               vargs = tree_cons (NULL_TREE, vec_oprnd1, vargs);
3146
3147               ++nargs;
3148             }
3149           vargs = nreverse (vargs);
3150
3151           rhs = build_function_call_expr (fndecl, vargs);
3152           new_stmt = build_gimple_modify_stmt (vec_dest, rhs);
3153           new_temp = make_ssa_name (vec_dest, new_stmt);
3154           GIMPLE_STMT_OPERAND (new_stmt, 0) = new_temp;
3155
3156           vect_finish_stmt_generation (stmt, new_stmt, bsi);
3157
3158           if (j == 0)
3159             STMT_VINFO_VEC_STMT (stmt_info) = new_stmt;
3160           else
3161             STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
3162
3163           prev_stmt_info = vinfo_for_stmt (new_stmt);
3164         }
3165
3166       *vec_stmt = STMT_VINFO_VEC_STMT (stmt_info);
3167
3168       break;
3169
3170     case WIDEN:
3171       /* No current target implements this case.  */
3172       return false;
3173     }
3174
3175   /* The call in STMT might prevent it from being removed in dce.
3176      We however cannot remove it here, due to the way the ssa name
3177      it defines is mapped to the new definition.  So just replace
3178      rhs of the statement with something harmless.  */
3179   type = TREE_TYPE (scalar_dest);
3180   GIMPLE_STMT_OPERAND (stmt, 1) = fold_convert (type, integer_zero_node);
3181   update_stmt (stmt);
3182
3183   return true;
3184 }
3185
3186
3187 /* Function vect_gen_widened_results_half
3188
3189    Create a vector stmt whose code, type, number of arguments, and result
3190    variable are CODE, VECTYPE, OP_TYPE, and VEC_DEST, and its arguments are 
3191    VEC_OPRND0 and VEC_OPRND1. The new vector stmt is to be inserted at BSI.
3192    In the case that CODE is a CALL_EXPR, this means that a call to DECL
3193    needs to be created (DECL is a function-decl of a target-builtin).
3194    STMT is the original scalar stmt that we are vectorizing.  */
3195
3196 static tree
3197 vect_gen_widened_results_half (enum tree_code code, tree vectype, tree decl,
3198                                tree vec_oprnd0, tree vec_oprnd1, int op_type,
3199                                tree vec_dest, block_stmt_iterator *bsi,
3200                                tree stmt)
3201
3202   tree expr; 
3203   tree new_stmt; 
3204   tree new_temp; 
3205   tree sym; 
3206   ssa_op_iter iter;
3207  
3208   /* Generate half of the widened result:  */ 
3209   if (code == CALL_EXPR) 
3210     {  
3211       /* Target specific support  */ 
3212       if (op_type == binary_op)
3213         expr = build_call_expr (decl, 2, vec_oprnd0, vec_oprnd1);
3214       else
3215         expr = build_call_expr (decl, 1, vec_oprnd0);
3216     } 
3217   else 
3218     { 
3219       /* Generic support */ 
3220       gcc_assert (op_type == TREE_CODE_LENGTH (code)); 
3221       if (op_type == binary_op) 
3222         expr = build2 (code, vectype, vec_oprnd0, vec_oprnd1); 
3223       else  
3224         expr = build1 (code, vectype, vec_oprnd0); 
3225     } 
3226   new_stmt = build_gimple_modify_stmt (vec_dest, expr);
3227   new_temp = make_ssa_name (vec_dest, new_stmt); 
3228   GIMPLE_STMT_OPERAND (new_stmt, 0) = new_temp; 
3229   vect_finish_stmt_generation (stmt, new_stmt, bsi); 
3230
3231   if (code == CALL_EXPR)
3232     {
3233       FOR_EACH_SSA_TREE_OPERAND (sym, new_stmt, iter, SSA_OP_ALL_VIRTUALS)
3234         {
3235           if (TREE_CODE (sym) == SSA_NAME)
3236             sym = SSA_NAME_VAR (sym);
3237           mark_sym_for_renaming (sym);
3238         }
3239     }
3240
3241   return new_stmt;
3242 }
3243
3244
3245 /* Check if STMT performs a conversion operation, that can be vectorized. 
3246    If VEC_STMT is also passed, vectorize the STMT: create a vectorized 
3247    stmt to replace it, put it in VEC_STMT, and insert it at BSI.
3248    Return FALSE if not a vectorizable STMT, TRUE otherwise.  */
3249
3250 bool
3251 vectorizable_conversion (tree stmt, block_stmt_iterator *bsi,
3252                          tree *vec_stmt, slp_tree slp_node)
3253 {
3254   tree vec_dest;
3255   tree scalar_dest;
3256   tree operation;
3257   tree op0;
3258   tree vec_oprnd0 = NULL_TREE, vec_oprnd1 = NULL_TREE;
3259   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
3260   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
3261   struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
3262   enum tree_code code, code1 = ERROR_MARK, code2 = ERROR_MARK;
3263   tree decl1 = NULL_TREE, decl2 = NULL_TREE;
3264   tree new_temp;
3265   tree def, def_stmt;
3266   enum vect_def_type dt[2] = {vect_unknown_def_type, vect_unknown_def_type};
3267   tree new_stmt = NULL_TREE;
3268   stmt_vec_info prev_stmt_info;
3269   int nunits_in;
3270   int nunits_out;
3271   tree vectype_out, vectype_in;
3272   int ncopies, j;
3273   tree expr;
3274   tree rhs_type, lhs_type;
3275   tree builtin_decl;
3276   enum { NARROW, NONE, WIDEN } modifier;
3277   int i;
3278   VEC(tree,heap) *vec_oprnds0 = NULL;
3279   tree vop0;
3280
3281   /* Is STMT a vectorizable conversion?   */
3282
3283   if (!STMT_VINFO_RELEVANT_P (stmt_info))
3284     return false;
3285
3286   if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_loop_def)
3287     return false;
3288
3289   if (STMT_VINFO_LIVE_P (stmt_info))
3290     {
3291       /* FORNOW: not yet supported.  */
3292       if (vect_print_dump_info (REPORT_DETAILS))
3293         fprintf (vect_dump, "value used after loop.");
3294       return false;
3295     }
3296
3297   if (TREE_CODE (stmt) != GIMPLE_MODIFY_STMT)
3298     return false;
3299
3300   if (TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 0)) != SSA_NAME)
3301     return false;
3302
3303   operation = GIMPLE_STMT_OPERAND (stmt, 1);
3304   code = TREE_CODE (operation);
3305   if (code != FIX_TRUNC_EXPR && code != FLOAT_EXPR)
3306     return false;
3307
3308   /* Check types of lhs and rhs.  */
3309   op0 = TREE_OPERAND (operation, 0);
3310   rhs_type = TREE_TYPE (op0);
3311   vectype_in = get_vectype_for_scalar_type (rhs_type);
3312   nunits_in = TYPE_VECTOR_SUBPARTS (vectype_in);
3313
3314   scalar_dest = GIMPLE_STMT_OPERAND (stmt, 0);
3315   lhs_type = TREE_TYPE (scalar_dest);
3316   vectype_out = get_vectype_for_scalar_type (lhs_type);
3317   nunits_out = TYPE_VECTOR_SUBPARTS (vectype_out);
3318
3319   /* FORNOW */
3320   if (nunits_in == nunits_out / 2)
3321     modifier = NARROW;
3322   else if (nunits_out == nunits_in)
3323     modifier = NONE;
3324   else if (nunits_out == nunits_in / 2)
3325     modifier = WIDEN;
3326   else
3327     return false;
3328
3329   if (modifier == NONE)
3330     gcc_assert (STMT_VINFO_VECTYPE (stmt_info) == vectype_out);
3331
3332   /* Bail out if the types are both integral or non-integral.  */
3333   if ((INTEGRAL_TYPE_P (rhs_type) && INTEGRAL_TYPE_P (lhs_type))
3334       || (!INTEGRAL_TYPE_P (rhs_type) && !INTEGRAL_TYPE_P (lhs_type)))
3335     return false;
3336
3337   if (modifier == NARROW)
3338     ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits_out;
3339   else
3340     ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits_in;
3341
3342   /* FORNOW: SLP with multiple types is not supported. The SLP analysis verifies
3343      this, so we can safely override NCOPIES with 1 here.  */
3344   if (slp_node)
3345     ncopies = 1;
3346   
3347   /* Sanity check: make sure that at least one copy of the vectorized stmt
3348      needs to be generated.  */
3349   gcc_assert (ncopies >= 1);
3350
3351   /* FORNOW. This restriction should be relaxed.  */
3352   if (nested_in_vect_loop_p (loop, stmt) && ncopies > 1)
3353     {
3354       if (vect_print_dump_info (REPORT_DETAILS))
3355       fprintf (vect_dump, "multiple types in nested loop.");
3356       return false;
3357     }
3358
3359   /* Check the operands of the operation.  */
3360   if (!vect_is_simple_use (op0, loop_vinfo, &def_stmt, &def, &dt[0]))
3361     {
3362       if (vect_print_dump_info (REPORT_DETAILS))
3363         fprintf (vect_dump, "use not simple.");
3364       return false;
3365     }
3366
3367   /* Supportable by target?  */
3368   if ((modifier == NONE
3369        && !targetm.vectorize.builtin_conversion (code, vectype_in))
3370       || (modifier == WIDEN
3371           && !supportable_widening_operation (code, stmt, vectype_in,
3372                                               &decl1, &decl2,
3373                                               &code1, &code2))
3374       || (modifier == NARROW
3375           && !supportable_narrowing_operation (code, stmt, vectype_in,
3376                                                &code1)))
3377     {
3378       if (vect_print_dump_info (REPORT_DETAILS))
3379         fprintf (vect_dump, "op not supported by target.");
3380       return false;
3381     }
3382
3383   if (modifier != NONE)
3384     {
3385       STMT_VINFO_VECTYPE (stmt_info) = vectype_in;
3386       /* FORNOW: SLP not supported.  */
3387       if (STMT_SLP_TYPE (stmt_info))
3388         return false;      
3389     }
3390
3391   if (!vec_stmt)                /* transformation not required.  */
3392     {
3393       STMT_VINFO_TYPE (stmt_info) = type_conversion_vec_info_type;
3394       return true;
3395     }
3396
3397   /** Transform.  **/
3398   if (vect_print_dump_info (REPORT_DETAILS))
3399     fprintf (vect_dump, "transform conversion.");
3400
3401   /* Handle def.  */
3402   vec_dest = vect_create_destination_var (scalar_dest, vectype_out);
3403
3404   if (modifier == NONE && !slp_node)
3405     vec_oprnds0 = VEC_alloc (tree, heap, 1);
3406
3407   prev_stmt_info = NULL;
3408   switch (modifier)
3409     {
3410     case NONE:
3411       for (j = 0; j < ncopies; j++)
3412         {
3413           tree sym;
3414           ssa_op_iter iter;
3415
3416           if (j == 0)
3417             vect_get_vec_defs (op0, NULL, stmt, &vec_oprnds0, NULL, slp_node);
3418           else
3419             vect_get_vec_defs_for_stmt_copy (dt, &vec_oprnds0, NULL);
3420
3421           builtin_decl =
3422             targetm.vectorize.builtin_conversion (code, vectype_in);
3423           for (i = 0; VEC_iterate (tree, vec_oprnds0, i, vop0); i++)
3424             { 
3425               new_stmt = build_call_expr (builtin_decl, 1, vop0);
3426
3427               /* Arguments are ready. create the new vector stmt.  */
3428               new_stmt = build_gimple_modify_stmt (vec_dest, new_stmt);
3429               new_temp = make_ssa_name (vec_dest, new_stmt);
3430               GIMPLE_STMT_OPERAND (new_stmt, 0) = new_temp;
3431               vect_finish_stmt_generation (stmt, new_stmt, bsi);
3432               FOR_EACH_SSA_TREE_OPERAND (sym, new_stmt, iter, 
3433                                          SSA_OP_ALL_VIRTUALS)
3434                 {
3435                   if (TREE_CODE (sym) == SSA_NAME)
3436                     sym = SSA_NAME_VAR (sym);
3437                   mark_sym_for_renaming (sym);
3438                 }
3439               if (slp_node)
3440                 VEC_quick_push (tree, SLP_TREE_VEC_STMTS (slp_node), new_stmt);
3441             }
3442
3443           if (j == 0)
3444             STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
3445           else
3446             STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
3447           prev_stmt_info = vinfo_for_stmt (new_stmt);
3448         }
3449       break;
3450
3451     case WIDEN:
3452       /* In case the vectorization factor (VF) is bigger than the number
3453          of elements that we can fit in a vectype (nunits), we have to
3454          generate more than one vector stmt - i.e - we need to "unroll"
3455          the vector stmt by a factor VF/nunits.  */
3456       for (j = 0; j < ncopies; j++)
3457         {
3458           if (j == 0)
3459             vec_oprnd0 = vect_get_vec_def_for_operand (op0, stmt, NULL);
3460           else
3461             vec_oprnd0 = vect_get_vec_def_for_stmt_copy (dt[0], vec_oprnd0);
3462
3463           STMT_VINFO_VECTYPE (stmt_info) = vectype_in;
3464
3465           /* Generate first half of the widened result:  */
3466           new_stmt
3467             = vect_gen_widened_results_half (code1, vectype_out, decl1, 
3468                                              vec_oprnd0, vec_oprnd1,
3469                                              unary_op, vec_dest, bsi, stmt);
3470           if (j == 0)
3471             STMT_VINFO_VEC_STMT (stmt_info) = new_stmt;
3472           else
3473             STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
3474           prev_stmt_info = vinfo_for_stmt (new_stmt);
3475
3476           /* Generate second half of the widened result:  */
3477           new_stmt
3478             = vect_gen_widened_results_half (code2, vectype_out, decl2,
3479                                              vec_oprnd0, vec_oprnd1,
3480                                              unary_op, vec_dest, bsi, stmt);
3481           STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
3482           prev_stmt_info = vinfo_for_stmt (new_stmt);
3483         }
3484       break;
3485
3486     case NARROW:
3487       /* In case the vectorization factor (VF) is bigger than the number
3488          of elements that we can fit in a vectype (nunits), we have to
3489          generate more than one vector stmt - i.e - we need to "unroll"
3490          the vector stmt by a factor VF/nunits.  */
3491       for (j = 0; j < ncopies; j++)
3492         {
3493           /* Handle uses.  */
3494           if (j == 0)
3495             {
3496               vec_oprnd0 = vect_get_vec_def_for_operand (op0, stmt, NULL);
3497               vec_oprnd1 = vect_get_vec_def_for_stmt_copy (dt[0], vec_oprnd0);
3498             }
3499           else
3500             {
3501               vec_oprnd0 = vect_get_vec_def_for_stmt_copy (dt[0], vec_oprnd1);
3502               vec_oprnd1 = vect_get_vec_def_for_stmt_copy (dt[0], vec_oprnd0);
3503             }
3504
3505           /* Arguments are ready. Create the new vector stmt.  */
3506           expr = build2 (code1, vectype_out, vec_oprnd0, vec_oprnd1);
3507           new_stmt = build_gimple_modify_stmt (vec_dest, expr);
3508           new_temp = make_ssa_name (vec_dest, new_stmt);
3509           GIMPLE_STMT_OPERAND (new_stmt, 0) = new_temp;
3510           vect_finish_stmt_generation (stmt, new_stmt, bsi);
3511
3512           if (j == 0)
3513             STMT_VINFO_VEC_STMT (stmt_info) = new_stmt;
3514           else
3515             STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
3516
3517           prev_stmt_info = vinfo_for_stmt (new_stmt);
3518         }
3519
3520       *vec_stmt = STMT_VINFO_VEC_STMT (stmt_info);
3521     }
3522
3523   return true;
3524 }
3525
3526
3527 /* Function vectorizable_assignment.
3528
3529    Check if STMT performs an assignment (copy) that can be vectorized. 
3530    If VEC_STMT is also passed, vectorize the STMT: create a vectorized 
3531    stmt to replace it, put it in VEC_STMT, and insert it at BSI.
3532    Return FALSE if not a vectorizable STMT, TRUE otherwise.  */
3533
3534 bool
3535 vectorizable_assignment (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt, 
3536                          slp_tree slp_node)
3537 {
3538   tree vec_dest;
3539   tree scalar_dest;
3540   tree op;
3541   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
3542   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
3543   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
3544   tree new_temp;
3545   tree def, def_stmt;
3546   enum vect_def_type dt[2] = {vect_unknown_def_type, vect_unknown_def_type};
3547   int nunits = TYPE_VECTOR_SUBPARTS (vectype);
3548   int ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits;
3549   int i;
3550   VEC(tree,heap) *vec_oprnds = NULL;
3551   tree vop;
3552
3553   gcc_assert (ncopies >= 1);
3554   if (ncopies > 1)
3555     return false; /* FORNOW */
3556
3557   if (!STMT_VINFO_RELEVANT_P (stmt_info))
3558     return false;
3559
3560   if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_loop_def)
3561     return false;
3562
3563   /* FORNOW: not yet supported.  */
3564   if (STMT_VINFO_LIVE_P (stmt_info))
3565     {
3566       if (vect_print_dump_info (REPORT_DETAILS))
3567         fprintf (vect_dump, "value used after loop.");
3568       return false;
3569     }
3570
3571   /* Is vectorizable assignment?  */
3572   if (TREE_CODE (stmt) != GIMPLE_MODIFY_STMT)
3573     return false;
3574
3575   scalar_dest = GIMPLE_STMT_OPERAND (stmt, 0);
3576   if (TREE_CODE (scalar_dest) != SSA_NAME)
3577     return false;
3578
3579   op = GIMPLE_STMT_OPERAND (stmt, 1);
3580   if (!vect_is_simple_use (op, loop_vinfo, &def_stmt, &def, &dt[0]))
3581     {
3582       if (vect_print_dump_info (REPORT_DETAILS))
3583         fprintf (vect_dump, "use not simple.");
3584       return false;
3585     }
3586
3587   if (!vec_stmt) /* transformation not required.  */
3588     {
3589       STMT_VINFO_TYPE (stmt_info) = assignment_vec_info_type;
3590       if (vect_print_dump_info (REPORT_DETAILS))
3591         fprintf (vect_dump, "=== vectorizable_assignment ===");
3592       vect_model_simple_cost (stmt_info, ncopies, dt, NULL);
3593       return true;
3594     }
3595
3596   /** Transform.  **/
3597   if (vect_print_dump_info (REPORT_DETAILS))
3598     fprintf (vect_dump, "transform assignment.");
3599
3600   /* Handle def.  */
3601   vec_dest = vect_create_destination_var (scalar_dest, vectype);
3602
3603   /* Handle use.  */
3604   vect_get_vec_defs (op, NULL, stmt, &vec_oprnds, NULL, slp_node);
3605
3606   /* Arguments are ready. create the new vector stmt.  */
3607   for (i = 0; VEC_iterate (tree, vec_oprnds, i, vop); i++)
3608     {
3609       *vec_stmt = build_gimple_modify_stmt (vec_dest, vop);
3610       new_temp = make_ssa_name (vec_dest, *vec_stmt);
3611       GIMPLE_STMT_OPERAND (*vec_stmt, 0) = new_temp;
3612       vect_finish_stmt_generation (stmt, *vec_stmt, bsi);
3613       STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt;
3614
3615       if (slp_node)
3616         VEC_quick_push (tree, SLP_TREE_VEC_STMTS (slp_node), *vec_stmt);
3617    }
3618   
3619   VEC_free (tree, heap, vec_oprnds);       
3620   return true;
3621 }
3622
3623
3624 /* Function vect_min_worthwhile_factor.
3625
3626    For a loop where we could vectorize the operation indicated by CODE,
3627    return the minimum vectorization factor that makes it worthwhile
3628    to use generic vectors.  */
3629 static int
3630 vect_min_worthwhile_factor (enum tree_code code)
3631 {
3632   switch (code)
3633     {
3634     case PLUS_EXPR:
3635     case MINUS_EXPR:
3636     case NEGATE_EXPR:
3637       return 4;
3638
3639     case BIT_AND_EXPR:
3640     case BIT_IOR_EXPR:
3641     case BIT_XOR_EXPR:
3642     case BIT_NOT_EXPR:
3643       return 2;
3644
3645     default:
3646       return INT_MAX;
3647     }
3648 }
3649
3650
3651 /* Function vectorizable_induction
3652
3653    Check if PHI performs an induction computation that can be vectorized.
3654    If VEC_STMT is also passed, vectorize the induction PHI: create a vectorized
3655    phi to replace it, put it in VEC_STMT, and add it to the same basic block.
3656    Return FALSE if not a vectorizable STMT, TRUE otherwise.  */
3657
3658 bool
3659 vectorizable_induction (tree phi, block_stmt_iterator *bsi ATTRIBUTE_UNUSED,
3660                         tree *vec_stmt)
3661 {
3662   stmt_vec_info stmt_info = vinfo_for_stmt (phi);
3663   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
3664   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
3665   int nunits = TYPE_VECTOR_SUBPARTS (vectype);
3666   int ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits;
3667   tree vec_def;
3668
3669   gcc_assert (ncopies >= 1);
3670
3671   if (!STMT_VINFO_RELEVANT_P (stmt_info))
3672     return false;
3673
3674   /* FORNOW: SLP not supported.  */
3675   if (STMT_SLP_TYPE (stmt_info))
3676     return false;
3677
3678   gcc_assert (STMT_VINFO_DEF_TYPE (stmt_info) == vect_induction_def);
3679
3680   if (STMT_VINFO_LIVE_P (stmt_info))
3681     {
3682       /* FORNOW: not yet supported.  */
3683       if (vect_print_dump_info (REPORT_DETAILS))
3684         fprintf (vect_dump, "value used after loop.");
3685       return false;
3686     }
3687
3688   if (TREE_CODE (phi) != PHI_NODE)
3689     return false;
3690
3691   if (!vec_stmt) /* transformation not required.  */
3692     {
3693       STMT_VINFO_TYPE (stmt_info) = induc_vec_info_type;
3694       if (vect_print_dump_info (REPORT_DETAILS))
3695         fprintf (vect_dump, "=== vectorizable_induction ===");
3696       vect_model_induction_cost (stmt_info, ncopies);
3697       return true;
3698     }
3699
3700   /** Transform.  **/
3701
3702   if (vect_print_dump_info (REPORT_DETAILS))
3703     fprintf (vect_dump, "transform induction phi.");
3704
3705   vec_def = get_initial_def_for_induction (phi);
3706   *vec_stmt = SSA_NAME_DEF_STMT (vec_def);
3707   return true;
3708 }
3709
3710
3711 /* Function vectorizable_operation.
3712
3713    Check if STMT performs a binary or unary operation that can be vectorized. 
3714    If VEC_STMT is also passed, vectorize the STMT: create a vectorized 
3715    stmt to replace it, put it in VEC_STMT, and insert it at BSI.
3716    Return FALSE if not a vectorizable STMT, TRUE otherwise.  */
3717
3718 bool
3719 vectorizable_operation (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt, 
3720                         slp_tree slp_node)
3721 {
3722   tree vec_dest;
3723   tree scalar_dest;
3724   tree operation;
3725   tree op0, op1 = NULL;
3726   tree vec_oprnd1 = NULL_TREE;
3727   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
3728   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
3729   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
3730   struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
3731   enum tree_code code;
3732   enum machine_mode vec_mode;
3733   tree new_temp;
3734   int op_type;
3735   optab optab;
3736   int icode;
3737   enum machine_mode optab_op2_mode;
3738   tree def, def_stmt;
3739   enum vect_def_type dt[2] = {vect_unknown_def_type, vect_unknown_def_type};
3740   tree new_stmt = NULL_TREE;
3741   stmt_vec_info prev_stmt_info;
3742   int nunits_in = TYPE_VECTOR_SUBPARTS (vectype);
3743   int nunits_out;
3744   tree vectype_out;
3745   int ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits_in;
3746   int j, i;
3747   VEC(tree,heap) *vec_oprnds0 = NULL, *vec_oprnds1 = NULL;
3748   tree vop0, vop1;
3749
3750   /* FORNOW: SLP with multiple types is not supported. The SLP analysis verifies
3751      this, so we can safely override NCOPIES with 1 here.  */
3752   if (slp_node)
3753     ncopies = 1;
3754   gcc_assert (ncopies >= 1);
3755   /* FORNOW. This restriction should be relaxed.  */
3756   if (nested_in_vect_loop_p (loop, stmt) && ncopies > 1)
3757     {
3758       if (vect_print_dump_info (REPORT_DETAILS))
3759         fprintf (vect_dump, "multiple types in nested loop.");
3760       return false;
3761     }
3762
3763   if (!STMT_VINFO_RELEVANT_P (stmt_info))
3764     return false;
3765
3766   if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_loop_def)
3767     return false;
3768
3769   /* FORNOW: not yet supported.  */
3770   if (STMT_VINFO_LIVE_P (stmt_info))
3771     {
3772       if (vect_print_dump_info (REPORT_DETAILS))
3773         fprintf (vect_dump, "value used after loop.");
3774       return false;
3775     }
3776
3777   /* Is STMT a vectorizable binary/unary operation?   */
3778   if (TREE_CODE (stmt) != GIMPLE_MODIFY_STMT)
3779     return false;
3780
3781   if (TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 0)) != SSA_NAME)
3782     return false;
3783
3784   scalar_dest = GIMPLE_STMT_OPERAND (stmt, 0);
3785   vectype_out = get_vectype_for_scalar_type (TREE_TYPE (scalar_dest));
3786   nunits_out = TYPE_VECTOR_SUBPARTS (vectype_out);
3787   if (nunits_out != nunits_in)
3788     return false;
3789
3790   operation = GIMPLE_STMT_OPERAND (stmt, 1);
3791   code = TREE_CODE (operation);
3792
3793   /* For pointer addition, we should use the normal plus for
3794      the vector addition.  */
3795   if (code == POINTER_PLUS_EXPR)
3796     code = PLUS_EXPR;
3797
3798   optab = optab_for_tree_code (code, vectype);
3799
3800   /* Support only unary or binary operations.  */
3801   op_type = TREE_OPERAND_LENGTH (operation);
3802   if (op_type != unary_op && op_type != binary_op)
3803     {
3804       if (vect_print_dump_info (REPORT_DETAILS))
3805         fprintf (vect_dump, "num. args = %d (not unary/binary op).", op_type);
3806       return false;
3807     }
3808
3809   op0 = TREE_OPERAND (operation, 0);
3810   if (!vect_is_simple_use (op0, loop_vinfo, &def_stmt, &def, &dt[0]))
3811     {
3812       if (vect_print_dump_info (REPORT_DETAILS))
3813         fprintf (vect_dump, "use not simple.");
3814       return false;
3815     }
3816
3817   if (op_type == binary_op)
3818     {
3819       op1 = TREE_OPERAND (operation, 1);
3820       if (!vect_is_simple_use (op1, loop_vinfo, &def_stmt, &def, &dt[1]))
3821         {
3822           if (vect_print_dump_info (REPORT_DETAILS))
3823             fprintf (vect_dump, "use not simple.");
3824           return false;
3825         }
3826     }
3827
3828   /* Supportable by target?  */
3829   if (!optab)
3830     {
3831       if (vect_print_dump_info (REPORT_DETAILS))
3832         fprintf (vect_dump, "no optab.");
3833       return false;
3834     }
3835   vec_mode = TYPE_MODE (vectype);
3836   icode = (int) optab_handler (optab, vec_mode)->insn_code;
3837   if (icode == CODE_FOR_nothing)
3838     {
3839       if (vect_print_dump_info (REPORT_DETAILS))
3840         fprintf (vect_dump, "op not supported by target.");
3841       if (GET_MODE_SIZE (vec_mode) != UNITS_PER_WORD
3842           || LOOP_VINFO_VECT_FACTOR (loop_vinfo)
3843              < vect_min_worthwhile_factor (code))
3844         return false;
3845       if (vect_print_dump_info (REPORT_DETAILS))
3846         fprintf (vect_dump, "proceeding using word mode.");
3847     }
3848
3849   /* Worthwhile without SIMD support?  */
3850   if (!VECTOR_MODE_P (TYPE_MODE (vectype))
3851       && LOOP_VINFO_VECT_FACTOR (loop_vinfo)
3852          < vect_min_worthwhile_factor (code))
3853     {
3854       if (vect_print_dump_info (REPORT_DETAILS))
3855         fprintf (vect_dump, "not worthwhile without SIMD support.");
3856       return false;
3857     }
3858
3859   if (code == LSHIFT_EXPR || code == RSHIFT_EXPR)
3860     {
3861       /* FORNOW: not yet supported.  */
3862       if (!VECTOR_MODE_P (vec_mode))
3863         return false;
3864
3865       /* Invariant argument is needed for a vector shift
3866          by a scalar shift operand.  */
3867       optab_op2_mode = insn_data[icode].operand[2].mode;
3868       if (! (VECTOR_MODE_P (optab_op2_mode)
3869              || dt[1] == vect_constant_def
3870              || dt[1] == vect_invariant_def))
3871         {
3872           if (vect_print_dump_info (REPORT_DETAILS))
3873             fprintf (vect_dump, "operand mode requires invariant argument.");
3874           return false;
3875         }
3876     }
3877
3878   if (!vec_stmt) /* transformation not required.  */
3879     {
3880       STMT_VINFO_TYPE (stmt_info) = op_vec_info_type;
3881       if (vect_print_dump_info (REPORT_DETAILS))
3882         fprintf (vect_dump, "=== vectorizable_operation ===");
3883       vect_model_simple_cost (stmt_info, ncopies, dt, NULL);
3884       return true;
3885     }
3886
3887   /** Transform.  **/
3888
3889   if (vect_print_dump_info (REPORT_DETAILS))
3890     fprintf (vect_dump, "transform binary/unary operation.");
3891
3892   /* Handle def.  */
3893   vec_dest = vect_create_destination_var (scalar_dest, vectype);
3894
3895   if (!slp_node)
3896     vec_oprnds0 = VEC_alloc (tree, heap, 1);
3897   if (op_type == binary_op)
3898     vec_oprnds1 = VEC_alloc (tree, heap, 1);
3899
3900   /* In case the vectorization factor (VF) is bigger than the number
3901      of elements that we can fit in a vectype (nunits), we have to generate
3902      more than one vector stmt - i.e - we need to "unroll" the
3903      vector stmt by a factor VF/nunits. In doing so, we record a pointer
3904      from one copy of the vector stmt to the next, in the field
3905      STMT_VINFO_RELATED_STMT. This is necessary in order to allow following
3906      stages to find the correct vector defs to be used when vectorizing
3907      stmts that use the defs of the current stmt. The example below illustrates
3908      the vectorization process when VF=16 and nunits=4 (i.e - we need to create
3909      4 vectorized stmts):
3910
3911      before vectorization:
3912                                 RELATED_STMT    VEC_STMT
3913         S1:     x = memref      -               -
3914         S2:     z = x + 1       -               -
3915
3916      step 1: vectorize stmt S1 (done in vectorizable_load. See more details
3917              there):
3918                                 RELATED_STMT    VEC_STMT
3919         VS1_0:  vx0 = memref0   VS1_1           -
3920         VS1_1:  vx1 = memref1   VS1_2           -
3921         VS1_2:  vx2 = memref2   VS1_3           -
3922         VS1_3:  vx3 = memref3   -               -
3923         S1:     x = load        -               VS1_0
3924         S2:     z = x + 1       -               -
3925
3926      step2: vectorize stmt S2 (done here):
3927         To vectorize stmt S2 we first need to find the relevant vector
3928         def for the first operand 'x'. This is, as usual, obtained from
3929         the vector stmt recorded in the STMT_VINFO_VEC_STMT of the stmt
3930         that defines 'x' (S1). This way we find the stmt VS1_0, and the
3931         relevant vector def 'vx0'. Having found 'vx0' we can generate
3932         the vector stmt VS2_0, and as usual, record it in the
3933         STMT_VINFO_VEC_STMT of stmt S2.
3934         When creating the second copy (VS2_1), we obtain the relevant vector
3935         def from the vector stmt recorded in the STMT_VINFO_RELATED_STMT of
3936         stmt VS1_0. This way we find the stmt VS1_1 and the relevant
3937         vector def 'vx1'. Using 'vx1' we create stmt VS2_1 and record a
3938         pointer to it in the STMT_VINFO_RELATED_STMT of the vector stmt VS2_0.
3939         Similarly when creating stmts VS2_2 and VS2_3. This is the resulting
3940         chain of stmts and pointers:
3941                                 RELATED_STMT    VEC_STMT
3942         VS1_0:  vx0 = memref0   VS1_1           -
3943         VS1_1:  vx1 = memref1   VS1_2           -
3944         VS1_2:  vx2 = memref2   VS1_3           -
3945         VS1_3:  vx3 = memref3   -               -
3946         S1:     x = load        -               VS1_0
3947         VS2_0:  vz0 = vx0 + v1  VS2_1           -
3948         VS2_1:  vz1 = vx1 + v1  VS2_2           -
3949         VS2_2:  vz2 = vx2 + v1  VS2_3           -
3950         VS2_3:  vz3 = vx3 + v1  -               -
3951         S2:     z = x + 1       -               VS2_0  */
3952
3953   prev_stmt_info = NULL;
3954   for (j = 0; j < ncopies; j++)
3955     {
3956       /* Handle uses.  */
3957       if (j == 0)
3958         {
3959           if (op_type == binary_op
3960               && (code == LSHIFT_EXPR || code == RSHIFT_EXPR))
3961             {
3962               /* Vector shl and shr insn patterns can be defined with scalar 
3963                  operand 2 (shift operand). In this case, use constant or loop 
3964                  invariant op1 directly, without extending it to vector mode 
3965                  first.  */
3966               optab_op2_mode = insn_data[icode].operand[2].mode;
3967               if (!VECTOR_MODE_P (optab_op2_mode))
3968                 {
3969                   if (vect_print_dump_info (REPORT_DETAILS))
3970                     fprintf (vect_dump, "operand 1 using scalar mode.");
3971                   vec_oprnd1 = op1;
3972                   VEC_quick_push (tree, vec_oprnds1, vec_oprnd1);
3973                 }
3974             }
3975          
3976           /* vec_oprnd is available if operand 1 should be of a scalar-type 
3977              (a special case for certain kind of vector shifts); otherwise, 
3978              operand 1 should be of a vector type (the usual case).  */
3979           if (op_type == binary_op && !vec_oprnd1)
3980             vect_get_vec_defs (op0, op1, stmt, &vec_oprnds0, &vec_oprnds1, 
3981                                slp_node);
3982           else
3983             vect_get_vec_defs (op0, NULL_TREE, stmt, &vec_oprnds0, NULL, 
3984                                slp_node);
3985         }
3986       else
3987         vect_get_vec_defs_for_stmt_copy (dt, &vec_oprnds0, &vec_oprnds1);
3988
3989       /* Arguments are ready. Create the new vector stmt.  */
3990       for (i = 0; VEC_iterate (tree, vec_oprnds0, i, vop0); i++)
3991         {
3992           if (op_type == binary_op)
3993             {
3994               vop1 = VEC_index (tree, vec_oprnds1, i);
3995               new_stmt = build_gimple_modify_stmt (vec_dest,
3996                                          build2 (code, vectype, vop0, vop1));
3997             }
3998           else
3999             new_stmt = build_gimple_modify_stmt (vec_dest,
4000                                     build1 (code, vectype, vop0));
4001
4002           new_temp = make_ssa_name (vec_dest, new_stmt);
4003           GIMPLE_STMT_OPERAND (new_stmt, 0) = new_temp;
4004           vect_finish_stmt_generation (stmt, new_stmt, bsi);
4005           if (slp_node)
4006             VEC_quick_push (tree, SLP_TREE_VEC_STMTS (slp_node), new_stmt);
4007         }
4008
4009       if (j == 0)
4010         STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
4011       else
4012         STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
4013       prev_stmt_info = vinfo_for_stmt (new_stmt);
4014     }
4015
4016   VEC_free (tree, heap, vec_oprnds0);
4017   if (vec_oprnds1)
4018     VEC_free (tree, heap, vec_oprnds1);
4019
4020   return true;
4021 }
4022
4023
4024 /* Function vectorizable_type_demotion
4025
4026    Check if STMT performs a binary or unary operation that involves
4027    type demotion, and if it can be vectorized.
4028    If VEC_STMT is also passed, vectorize the STMT: create a vectorized
4029    stmt to replace it, put it in VEC_STMT, and insert it at BSI.
4030    Return FALSE if not a vectorizable STMT, TRUE otherwise.  */
4031
4032 bool
4033 vectorizable_type_demotion (tree stmt, block_stmt_iterator *bsi,
4034                             tree *vec_stmt)
4035 {
4036   tree vec_dest;
4037   tree scalar_dest;
4038   tree operation;
4039   tree op0;
4040   tree vec_oprnd0=NULL, vec_oprnd1=NULL;
4041   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
4042   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
4043   struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
4044   enum tree_code code, code1 = ERROR_MARK;
4045   tree new_temp;
4046   tree def, def_stmt;
4047   enum vect_def_type dt[2] = {vect_unknown_def_type, vect_unknown_def_type};
4048   tree new_stmt;
4049   stmt_vec_info prev_stmt_info;
4050   int nunits_in;
4051   int nunits_out;
4052   tree vectype_out;
4053   int ncopies;
4054   int j;
4055   tree expr;
4056   tree vectype_in;
4057
4058   if (!STMT_VINFO_RELEVANT_P (stmt_info))
4059     return false;
4060
4061   if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_loop_def)
4062     return false;
4063
4064   /* FORNOW: not yet supported.  */
4065   if (STMT_VINFO_LIVE_P (stmt_info))
4066     {
4067       if (vect_print_dump_info (REPORT_DETAILS))
4068         fprintf (vect_dump, "value used after loop.");
4069       return false;
4070     }
4071
4072   /* Is STMT a vectorizable type-demotion operation?  */
4073   if (TREE_CODE (stmt) != GIMPLE_MODIFY_STMT)
4074     return false;
4075
4076   if (TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 0)) != SSA_NAME)
4077     return false;
4078
4079   operation = GIMPLE_STMT_OPERAND (stmt, 1);
4080   code = TREE_CODE (operation);
4081   if (code != NOP_EXPR && code != CONVERT_EXPR)
4082     return false;
4083
4084   op0 = TREE_OPERAND (operation, 0);
4085   vectype_in = get_vectype_for_scalar_type (TREE_TYPE (op0));
4086   nunits_in = TYPE_VECTOR_SUBPARTS (vectype_in);
4087
4088   scalar_dest = GIMPLE_STMT_OPERAND (stmt, 0);
4089   vectype_out = get_vectype_for_scalar_type (TREE_TYPE (scalar_dest));
4090   nunits_out = TYPE_VECTOR_SUBPARTS (vectype_out);
4091   if (nunits_in != nunits_out / 2) /* FORNOW */
4092     return false;
4093
4094   ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits_out;
4095   gcc_assert (ncopies >= 1);
4096   /* FORNOW. This restriction should be relaxed.  */
4097   if (nested_in_vect_loop_p (loop, stmt) && ncopies > 1)
4098     {
4099       if (vect_print_dump_info (REPORT_DETAILS))
4100         fprintf (vect_dump, "multiple types in nested loop.");
4101       return false;
4102     }
4103
4104   if (! ((INTEGRAL_TYPE_P (TREE_TYPE (scalar_dest))
4105           && INTEGRAL_TYPE_P (TREE_TYPE (op0)))
4106          || (SCALAR_FLOAT_TYPE_P (TREE_TYPE (scalar_dest))
4107              && SCALAR_FLOAT_TYPE_P (TREE_TYPE (op0))
4108              && (code == NOP_EXPR || code == CONVERT_EXPR))))
4109     return false;
4110
4111   /* Check the operands of the operation.  */
4112   if (!vect_is_simple_use (op0, loop_vinfo, &def_stmt, &def, &dt[0]))
4113     {
4114       if (vect_print_dump_info (REPORT_DETAILS))
4115         fprintf (vect_dump, "use not simple.");
4116       return false;
4117     }
4118
4119   /* Supportable by target?  */
4120   if (!supportable_narrowing_operation (code, stmt, vectype_in, &code1))
4121     return false;
4122
4123   STMT_VINFO_VECTYPE (stmt_info) = vectype_in;
4124
4125   if (!vec_stmt) /* transformation not required.  */
4126     {
4127       STMT_VINFO_TYPE (stmt_info) = type_demotion_vec_info_type;
4128       if (vect_print_dump_info (REPORT_DETAILS))
4129         fprintf (vect_dump, "=== vectorizable_demotion ===");
4130       vect_model_simple_cost (stmt_info, ncopies, dt, NULL);
4131       return true;
4132     }
4133
4134   /** Transform.  **/
4135   if (vect_print_dump_info (REPORT_DETAILS))
4136     fprintf (vect_dump, "transform type demotion operation. ncopies = %d.",
4137              ncopies);
4138
4139   /* Handle def.  */
4140   vec_dest = vect_create_destination_var (scalar_dest, vectype_out);
4141   
4142   /* In case the vectorization factor (VF) is bigger than the number
4143      of elements that we can fit in a vectype (nunits), we have to generate
4144      more than one vector stmt - i.e - we need to "unroll" the
4145      vector stmt by a factor VF/nunits.   */
4146   prev_stmt_info = NULL;
4147   for (j = 0; j < ncopies; j++)
4148     {
4149       /* Handle uses.  */
4150       if (j == 0)
4151         {
4152           vec_oprnd0 = vect_get_vec_def_for_operand (op0, stmt, NULL);
4153           vec_oprnd1 = vect_get_vec_def_for_stmt_copy (dt[0], vec_oprnd0);
4154         }
4155       else
4156         {
4157           vec_oprnd0 = vect_get_vec_def_for_stmt_copy (dt[0], vec_oprnd1);
4158           vec_oprnd1 = vect_get_vec_def_for_stmt_copy (dt[0], vec_oprnd0);
4159         }
4160
4161       /* Arguments are ready. Create the new vector stmt.  */
4162       expr = build2 (code1, vectype_out, vec_oprnd0, vec_oprnd1);
4163       new_stmt = build_gimple_modify_stmt (vec_dest, expr);
4164       new_temp = make_ssa_name (vec_dest, new_stmt);
4165       GIMPLE_STMT_OPERAND (new_stmt, 0) = new_temp;
4166       vect_finish_stmt_generation (stmt, new_stmt, bsi);
4167
4168       if (j == 0)
4169         STMT_VINFO_VEC_STMT (stmt_info) = new_stmt;
4170       else
4171         STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
4172
4173       prev_stmt_info = vinfo_for_stmt (new_stmt);
4174     }
4175
4176   *vec_stmt = STMT_VINFO_VEC_STMT (stmt_info);
4177   return true;
4178 }
4179
4180
4181 /* Function vectorizable_type_promotion
4182
4183    Check if STMT performs a binary or unary operation that involves
4184    type promotion, and if it can be vectorized.
4185    If VEC_STMT is also passed, vectorize the STMT: create a vectorized
4186    stmt to replace it, put it in VEC_STMT, and insert it at BSI.
4187    Return FALSE if not a vectorizable STMT, TRUE otherwise.  */
4188
4189 bool
4190 vectorizable_type_promotion (tree stmt, block_stmt_iterator *bsi,
4191                              tree *vec_stmt)
4192 {
4193   tree vec_dest;
4194   tree scalar_dest;
4195   tree operation;
4196   tree op0, op1 = NULL;
4197   tree vec_oprnd0=NULL, vec_oprnd1=NULL;
4198   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
4199   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
4200   struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
4201   enum tree_code code, code1 = ERROR_MARK, code2 = ERROR_MARK;
4202   tree decl1 = NULL_TREE, decl2 = NULL_TREE;
4203   int op_type; 
4204   tree def, def_stmt;
4205   enum vect_def_type dt[2] = {vect_unknown_def_type, vect_unknown_def_type};
4206   tree new_stmt;
4207   stmt_vec_info prev_stmt_info;
4208   int nunits_in;
4209   int nunits_out;
4210   tree vectype_out;
4211   int ncopies;
4212   int j;
4213   tree vectype_in;
4214   
4215   if (!STMT_VINFO_RELEVANT_P (stmt_info))
4216     return false;
4217
4218   if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_loop_def)
4219     return false;
4220
4221   /* FORNOW: not yet supported.  */
4222   if (STMT_VINFO_LIVE_P (stmt_info))
4223     {
4224       if (vect_print_dump_info (REPORT_DETAILS))
4225         fprintf (vect_dump, "value used after loop.");
4226       return false;
4227     }
4228
4229   /* Is STMT a vectorizable type-promotion operation?  */
4230   if (TREE_CODE (stmt) != GIMPLE_MODIFY_STMT)
4231     return false;
4232
4233   if (TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 0)) != SSA_NAME)
4234     return false;
4235
4236   operation = GIMPLE_STMT_OPERAND (stmt, 1);
4237   code = TREE_CODE (operation);
4238   if (code != NOP_EXPR && code != CONVERT_EXPR
4239       && code != WIDEN_MULT_EXPR)
4240     return false;
4241
4242   op0 = TREE_OPERAND (operation, 0);
4243   vectype_in = get_vectype_for_scalar_type (TREE_TYPE (op0));
4244   nunits_in = TYPE_VECTOR_SUBPARTS (vectype_in);
4245
4246   scalar_dest = GIMPLE_STMT_OPERAND (stmt, 0);
4247   vectype_out = get_vectype_for_scalar_type (TREE_TYPE (scalar_dest));
4248   nunits_out = TYPE_VECTOR_SUBPARTS (vectype_out);
4249   if (nunits_out != nunits_in / 2) /* FORNOW */
4250     return false;
4251
4252   ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits_in;
4253   gcc_assert (ncopies >= 1);
4254   /* FORNOW. This restriction should be relaxed.  */
4255   if (nested_in_vect_loop_p (loop, stmt) && ncopies > 1)
4256     {
4257       if (vect_print_dump_info (REPORT_DETAILS))
4258         fprintf (vect_dump, "multiple types in nested loop.");
4259       return false;
4260     }
4261
4262   if (! ((INTEGRAL_TYPE_P (TREE_TYPE (scalar_dest))
4263           && INTEGRAL_TYPE_P (TREE_TYPE (op0)))
4264          || (SCALAR_FLOAT_TYPE_P (TREE_TYPE (scalar_dest))
4265              && SCALAR_FLOAT_TYPE_P (TREE_TYPE (op0))
4266              && (code == CONVERT_EXPR || code == NOP_EXPR))))
4267     return false;
4268
4269   /* Check the operands of the operation.  */
4270   if (!vect_is_simple_use (op0, loop_vinfo, &def_stmt, &def, &dt[0]))
4271     {
4272       if (vect_print_dump_info (REPORT_DETAILS))
4273         fprintf (vect_dump, "use not simple.");
4274       return false;
4275     }
4276
4277   op_type = TREE_CODE_LENGTH (code);
4278   if (op_type == binary_op)
4279     {
4280       op1 = TREE_OPERAND (operation, 1);
4281       if (!vect_is_simple_use (op1, loop_vinfo, &def_stmt, &def, &dt[1]))
4282         {
4283           if (vect_print_dump_info (REPORT_DETAILS))
4284             fprintf (vect_dump, "use not simple.");
4285           return false;
4286         }
4287     }
4288
4289   /* Supportable by target?  */
4290   if (!supportable_widening_operation (code, stmt, vectype_in,
4291                                        &decl1, &decl2, &code1, &code2))
4292     return false;
4293
4294   STMT_VINFO_VECTYPE (stmt_info) = vectype_in;
4295
4296   if (!vec_stmt) /* transformation not required.  */
4297     {
4298       STMT_VINFO_TYPE (stmt_info) = type_promotion_vec_info_type;
4299       if (vect_print_dump_info (REPORT_DETAILS))
4300         fprintf (vect_dump, "=== vectorizable_promotion ===");
4301       vect_model_simple_cost (stmt_info, 2*ncopies, dt, NULL);
4302       return true;
4303     }
4304
4305   /** Transform.  **/
4306
4307   if (vect_print_dump_info (REPORT_DETAILS))
4308     fprintf (vect_dump, "transform type promotion operation. ncopies = %d.",
4309                         ncopies);
4310
4311   /* Handle def.  */
4312   vec_dest = vect_create_destination_var (scalar_dest, vectype_out);
4313
4314   /* In case the vectorization factor (VF) is bigger than the number
4315      of elements that we can fit in a vectype (nunits), we have to generate
4316      more than one vector stmt - i.e - we need to "unroll" the
4317      vector stmt by a factor VF/nunits.   */
4318
4319   prev_stmt_info = NULL;
4320   for (j = 0; j < ncopies; j++)
4321     {
4322       /* Handle uses.  */
4323       if (j == 0)
4324         {
4325           vec_oprnd0 = vect_get_vec_def_for_operand (op0, stmt, NULL);
4326           if (op_type == binary_op)
4327             vec_oprnd1 = vect_get_vec_def_for_operand (op1, stmt, NULL);
4328         }
4329       else
4330         {
4331           vec_oprnd0 = vect_get_vec_def_for_stmt_copy (dt[0], vec_oprnd0);
4332           if (op_type == binary_op)
4333             vec_oprnd1 = vect_get_vec_def_for_stmt_copy (dt[1], vec_oprnd1);
4334         }
4335
4336       /* Arguments are ready. Create the new vector stmt.  We are creating 
4337          two vector defs because the widened result does not fit in one vector.
4338          The vectorized stmt can be expressed as a call to a taregt builtin,
4339          or a using a tree-code.  */
4340       /* Generate first half of the widened result:  */
4341       new_stmt = vect_gen_widened_results_half (code1, vectype_out, decl1, 
4342                         vec_oprnd0, vec_oprnd1, op_type, vec_dest, bsi, stmt);
4343       if (j == 0)
4344         STMT_VINFO_VEC_STMT (stmt_info) = new_stmt;
4345       else
4346         STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
4347       prev_stmt_info = vinfo_for_stmt (new_stmt);
4348
4349       /* Generate second half of the widened result:  */
4350       new_stmt = vect_gen_widened_results_half (code2, vectype_out, decl2,
4351                         vec_oprnd0, vec_oprnd1, op_type, vec_dest, bsi, stmt);
4352       STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
4353       prev_stmt_info = vinfo_for_stmt (new_stmt);
4354
4355     }
4356
4357   *vec_stmt = STMT_VINFO_VEC_STMT (stmt_info);
4358   return true;
4359 }
4360
4361
4362 /* Function vect_strided_store_supported.
4363
4364    Returns TRUE is INTERLEAVE_HIGH and INTERLEAVE_LOW operations are supported,
4365    and FALSE otherwise.  */
4366
4367 static bool
4368 vect_strided_store_supported (tree vectype)
4369 {
4370   optab interleave_high_optab, interleave_low_optab;
4371   int mode;
4372
4373   mode = (int) TYPE_MODE (vectype);
4374       
4375   /* Check that the operation is supported.  */
4376   interleave_high_optab = optab_for_tree_code (VEC_INTERLEAVE_HIGH_EXPR, 
4377                                                vectype);
4378   interleave_low_optab = optab_for_tree_code (VEC_INTERLEAVE_LOW_EXPR, 
4379                                               vectype);
4380   if (!interleave_high_optab || !interleave_low_optab)
4381     {
4382       if (vect_print_dump_info (REPORT_DETAILS))
4383         fprintf (vect_dump, "no optab for interleave.");
4384       return false;
4385     }
4386
4387   if (optab_handler (interleave_high_optab, mode)->insn_code 
4388       == CODE_FOR_nothing
4389       || optab_handler (interleave_low_optab, mode)->insn_code 
4390       == CODE_FOR_nothing)
4391     {
4392       if (vect_print_dump_info (REPORT_DETAILS))
4393         fprintf (vect_dump, "interleave op not supported by target.");
4394       return false;
4395     }
4396
4397   return true;
4398 }
4399
4400
4401 /* Function vect_permute_store_chain.
4402
4403    Given a chain of interleaved stores in DR_CHAIN of LENGTH that must be
4404    a power of 2, generate interleave_high/low stmts to reorder the data 
4405    correctly for the stores. Return the final references for stores in
4406    RESULT_CHAIN.
4407
4408    E.g., LENGTH is 4 and the scalar type is short, i.e., VF is 8.
4409    The input is 4 vectors each containing 8 elements. We assign a number to each
4410    element, the input sequence is:
4411
4412    1st vec:   0  1  2  3  4  5  6  7
4413    2nd vec:   8  9 10 11 12 13 14 15
4414    3rd vec:  16 17 18 19 20 21 22 23 
4415    4th vec:  24 25 26 27 28 29 30 31
4416
4417    The output sequence should be:
4418
4419    1st vec:  0  8 16 24  1  9 17 25
4420    2nd vec:  2 10 18 26  3 11 19 27
4421    3rd vec:  4 12 20 28  5 13 21 30
4422    4th vec:  6 14 22 30  7 15 23 31
4423
4424    i.e., we interleave the contents of the four vectors in their order.
4425
4426    We use interleave_high/low instructions to create such output. The input of 
4427    each interleave_high/low operation is two vectors:
4428    1st vec    2nd vec 
4429    0 1 2 3    4 5 6 7 
4430    the even elements of the result vector are obtained left-to-right from the 
4431    high/low elements of the first vector. The odd elements of the result are 
4432    obtained left-to-right from the high/low elements of the second vector.
4433    The output of interleave_high will be:   0 4 1 5
4434    and of interleave_low:                   2 6 3 7
4435
4436    
4437    The permutation is done in log LENGTH stages. In each stage interleave_high
4438    and interleave_low stmts are created for each pair of vectors in DR_CHAIN, 
4439    where the first argument is taken from the first half of DR_CHAIN and the 
4440    second argument from it's second half. 
4441    In our example, 
4442
4443    I1: interleave_high (1st vec, 3rd vec)
4444    I2: interleave_low (1st vec, 3rd vec)
4445    I3: interleave_high (2nd vec, 4th vec)
4446    I4: interleave_low (2nd vec, 4th vec)
4447
4448    The output for the first stage is:
4449
4450    I1:  0 16  1 17  2 18  3 19
4451    I2:  4 20  5 21  6 22  7 23
4452    I3:  8 24  9 25 10 26 11 27
4453    I4: 12 28 13 29 14 30 15 31
4454
4455    The output of the second stage, i.e. the final result is:
4456
4457    I1:  0  8 16 24  1  9 17 25
4458    I2:  2 10 18 26  3 11 19 27
4459    I3:  4 12 20 28  5 13 21 30
4460    I4:  6 14 22 30  7 15 23 31.  */
4461  
4462 static bool
4463 vect_permute_store_chain (VEC(tree,heap) *dr_chain, 
4464                           unsigned int length, 
4465                           tree stmt, 
4466                           block_stmt_iterator *bsi,
4467                           VEC(tree,heap) **result_chain)
4468 {
4469   tree perm_dest, perm_stmt, vect1, vect2, high, low;
4470   tree vectype = STMT_VINFO_VECTYPE (vinfo_for_stmt (stmt));
4471   tree scalar_dest, tmp;
4472   int i;
4473   unsigned int j;
4474   VEC(tree,heap) *first, *second;
4475   
4476   scalar_dest = GIMPLE_STMT_OPERAND (stmt, 0);
4477   first = VEC_alloc (tree, heap, length/2);
4478   second = VEC_alloc (tree, heap, length/2);
4479
4480   /* Check that the operation is supported.  */
4481   if (!vect_strided_store_supported (vectype))
4482     return false;
4483
4484   *result_chain = VEC_copy (tree, heap, dr_chain);
4485
4486   for (i = 0; i < exact_log2 (length); i++)
4487     {
4488       for (j = 0; j < length/2; j++)
4489         {
4490           vect1 = VEC_index (tree, dr_chain, j);
4491           vect2 = VEC_index (tree, dr_chain, j+length/2);
4492
4493           /* Create interleaving stmt:
4494              in the case of big endian: 
4495                                 high = interleave_high (vect1, vect2) 
4496              and in the case of little endian: 
4497                                 high = interleave_low (vect1, vect2).  */
4498           perm_dest = create_tmp_var (vectype, "vect_inter_high");
4499           DECL_GIMPLE_REG_P (perm_dest) = 1;
4500           add_referenced_var (perm_dest);
4501           if (BYTES_BIG_ENDIAN)
4502             tmp = build2 (VEC_INTERLEAVE_HIGH_EXPR, vectype, vect1, vect2); 
4503           else
4504             tmp = build2 (VEC_INTERLEAVE_LOW_EXPR, vectype, vect1, vect2);
4505           perm_stmt = build_gimple_modify_stmt (perm_dest, tmp);
4506           high = make_ssa_name (perm_dest, perm_stmt);
4507           GIMPLE_STMT_OPERAND (perm_stmt, 0) = high;
4508           vect_finish_stmt_generation (stmt, perm_stmt, bsi);
4509           VEC_replace (tree, *result_chain, 2*j, high);
4510
4511           /* Create interleaving stmt:
4512              in the case of big endian:
4513                                low  = interleave_low (vect1, vect2) 
4514              and in the case of little endian:
4515                                low  = interleave_high (vect1, vect2).  */     
4516           perm_dest = create_tmp_var (vectype, "vect_inter_low");
4517           DECL_GIMPLE_REG_P (perm_dest) = 1;
4518           add_referenced_var (perm_dest);
4519           if (BYTES_BIG_ENDIAN)
4520             tmp = build2 (VEC_INTERLEAVE_LOW_EXPR, vectype, vect1, vect2);
4521           else
4522             tmp = build2 (VEC_INTERLEAVE_HIGH_EXPR, vectype, vect1, vect2);
4523           perm_stmt = build_gimple_modify_stmt (perm_dest, tmp);
4524           low = make_ssa_name (perm_dest, perm_stmt);
4525           GIMPLE_STMT_OPERAND (perm_stmt, 0) = low;
4526           vect_finish_stmt_generation (stmt, perm_stmt, bsi);
4527           VEC_replace (tree, *result_chain, 2*j+1, low);
4528         }
4529       dr_chain = VEC_copy (tree, heap, *result_chain);
4530     }
4531   return true;
4532 }
4533
4534
4535 /* Function vectorizable_store.
4536
4537    Check if STMT defines a non scalar data-ref (array/pointer/structure) that 
4538    can be vectorized. 
4539    If VEC_STMT is also passed, vectorize the STMT: create a vectorized 
4540    stmt to replace it, put it in VEC_STMT, and insert it at BSI.
4541    Return FALSE if not a vectorizable STMT, TRUE otherwise.  */
4542
4543 bool
4544 vectorizable_store (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt,
4545                     slp_tree slp_node)
4546 {
4547   tree scalar_dest;
4548   tree data_ref;
4549   tree op;
4550   tree vec_oprnd = NULL_TREE;
4551   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
4552   struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info), *first_dr = NULL;
4553   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
4554   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
4555   struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
4556   enum machine_mode vec_mode;
4557   tree dummy;
4558   enum dr_alignment_support alignment_support_scheme;
4559   tree def, def_stmt;
4560   enum vect_def_type dt;
4561   stmt_vec_info prev_stmt_info = NULL;
4562   tree dataref_ptr = NULL_TREE;
4563   int nunits = TYPE_VECTOR_SUBPARTS (vectype);
4564   int ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits;
4565   int j;
4566   tree next_stmt, first_stmt;
4567   bool strided_store = false;
4568   unsigned int group_size, i;
4569   VEC(tree,heap) *dr_chain = NULL, *oprnds = NULL, *result_chain = NULL;
4570   bool inv_p;
4571   VEC(tree,heap) *vec_oprnds = NULL;
4572   bool slp = (slp_node != NULL);
4573   stmt_vec_info first_stmt_vinfo;
4574   unsigned int vec_num;
4575
4576    /* FORNOW: SLP with multiple types is not supported. The SLP analysis verifies
4577       this, so we can safely override NCOPIES with 1 here.  */
4578   if (slp)
4579     ncopies = 1;
4580
4581   gcc_assert (ncopies >= 1);
4582
4583   /* FORNOW. This restriction should be relaxed.  */
4584   if (nested_in_vect_loop_p (loop, stmt) && ncopies > 1)
4585     {
4586       if (vect_print_dump_info (REPORT_DETAILS))
4587         fprintf (vect_dump, "multiple types in nested loop.");
4588       return false;
4589     }
4590
4591   if (!STMT_VINFO_RELEVANT_P (stmt_info))
4592     return false;
4593
4594   if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_loop_def)
4595     return false;
4596
4597   if (STMT_VINFO_LIVE_P (stmt_info))
4598     {
4599       if (vect_print_dump_info (REPORT_DETAILS))
4600         fprintf (vect_dump, "value used after loop.");
4601       return false;
4602     }
4603
4604   /* Is vectorizable store? */
4605
4606   if (TREE_CODE (stmt) != GIMPLE_MODIFY_STMT)
4607     return false;
4608
4609   scalar_dest = GIMPLE_STMT_OPERAND (stmt, 0);
4610   if (TREE_CODE (scalar_dest) != ARRAY_REF
4611       && TREE_CODE (scalar_dest) != INDIRECT_REF
4612       && !STMT_VINFO_STRIDED_ACCESS (stmt_info))
4613     return false;
4614
4615   op = GIMPLE_STMT_OPERAND (stmt, 1);
4616   if (!vect_is_simple_use (op, loop_vinfo, &def_stmt, &def, &dt))
4617     {
4618       if (vect_print_dump_info (REPORT_DETAILS))
4619         fprintf (vect_dump, "use not simple.");
4620       return false;
4621     }
4622
4623   vec_mode = TYPE_MODE (vectype);
4624   /* FORNOW. In some cases can vectorize even if data-type not supported
4625      (e.g. - array initialization with 0).  */
4626   if (optab_handler (mov_optab, (int)vec_mode)->insn_code == CODE_FOR_nothing)
4627     return false;
4628
4629   if (!STMT_VINFO_DATA_REF (stmt_info))
4630     return false;
4631
4632   if (STMT_VINFO_STRIDED_ACCESS (stmt_info))
4633     {
4634       strided_store = true;
4635       if (!vect_strided_store_supported (vectype)
4636           && !PURE_SLP_STMT (stmt_info) && !slp)
4637         return false;      
4638     }
4639
4640   if (!vec_stmt) /* transformation not required.  */
4641     {
4642       STMT_VINFO_TYPE (stmt_info) = store_vec_info_type;
4643       if (!PURE_SLP_STMT (stmt_info))
4644         vect_model_store_cost (stmt_info, ncopies, dt, NULL);
4645       return true;
4646     }
4647
4648   /** Transform.  **/
4649
4650   if (strided_store)
4651     {
4652       first_stmt = DR_GROUP_FIRST_DR (stmt_info);
4653       first_dr = STMT_VINFO_DATA_REF (vinfo_for_stmt (first_stmt));
4654       group_size = DR_GROUP_SIZE (vinfo_for_stmt (first_stmt));
4655
4656       DR_GROUP_STORE_COUNT (vinfo_for_stmt (first_stmt))++;
4657
4658       /* FORNOW */
4659       gcc_assert (!nested_in_vect_loop_p (loop, stmt));
4660
4661       /* We vectorize all the stmts of the interleaving group when we
4662          reach the last stmt in the group.  */
4663       if (DR_GROUP_STORE_COUNT (vinfo_for_stmt (first_stmt)) 
4664           < DR_GROUP_SIZE (vinfo_for_stmt (first_stmt))
4665           && !slp)
4666         {
4667           *vec_stmt = NULL_TREE;
4668           return true;
4669         }
4670
4671       if (slp)
4672         strided_store = false;
4673
4674       /* VEC_NUM is the number of vect stmts to be created for this group.  */
4675       if (slp && SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node) < group_size)
4676         vec_num = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node);
4677       else
4678         vec_num = group_size;
4679     }
4680   else 
4681     {
4682       first_stmt = stmt;
4683       first_dr = dr;
4684       group_size = vec_num = 1;
4685       first_stmt_vinfo = stmt_info;
4686     }
4687   
4688   if (vect_print_dump_info (REPORT_DETAILS))
4689     fprintf (vect_dump, "transform store. ncopies = %d",ncopies);
4690
4691   dr_chain = VEC_alloc (tree, heap, group_size);
4692   oprnds = VEC_alloc (tree, heap, group_size);
4693
4694   alignment_support_scheme = vect_supportable_dr_alignment (first_dr);
4695   gcc_assert (alignment_support_scheme);
4696   gcc_assert (alignment_support_scheme == dr_aligned);  /* FORNOW */
4697
4698   /* In case the vectorization factor (VF) is bigger than the number
4699      of elements that we can fit in a vectype (nunits), we have to generate
4700      more than one vector stmt - i.e - we need to "unroll" the
4701      vector stmt by a factor VF/nunits.  For more details see documentation in 
4702      vect_get_vec_def_for_copy_stmt.  */
4703
4704   /* In case of interleaving (non-unit strided access):
4705
4706         S1:  &base + 2 = x2
4707         S2:  &base = x0
4708         S3:  &base + 1 = x1
4709         S4:  &base + 3 = x3
4710
4711      We create vectorized stores starting from base address (the access of the
4712      first stmt in the chain (S2 in the above example), when the last store stmt
4713      of the chain (S4) is reached:
4714
4715         VS1: &base = vx2
4716         VS2: &base + vec_size*1 = vx0
4717         VS3: &base + vec_size*2 = vx1
4718         VS4: &base + vec_size*3 = vx3
4719
4720      Then permutation statements are generated:
4721
4722         VS5: vx5 = VEC_INTERLEAVE_HIGH_EXPR < vx0, vx3 >
4723         VS6: vx6 = VEC_INTERLEAVE_LOW_EXPR < vx0, vx3 >
4724         ...
4725         
4726      And they are put in STMT_VINFO_VEC_STMT of the corresponding scalar stmts
4727      (the order of the data-refs in the output of vect_permute_store_chain
4728      corresponds to the order of scalar stmts in the interleaving chain - see
4729      the documentation of vect_permute_store_chain()).
4730
4731      In case of both multiple types and interleaving, above vector stores and
4732      permutation stmts are created for every copy. The result vector stmts are
4733      put in STMT_VINFO_VEC_STMT for the first copy and in the corresponding
4734      STMT_VINFO_RELATED_STMT for the next copies.     
4735   */
4736
4737   prev_stmt_info = NULL;
4738   for (j = 0; j < ncopies; j++)
4739     {
4740       tree new_stmt;
4741       tree ptr_incr;
4742
4743       if (j == 0)
4744         {
4745           if (slp)
4746             {
4747               /* Get vectorized arguments for SLP_NODE.  */
4748               vect_get_slp_defs (slp_node, &vec_oprnds, NULL);
4749
4750               vec_oprnd = VEC_index (tree, vec_oprnds, 0);
4751             }
4752           else
4753             {
4754               /* For interleaved stores we collect vectorized defs for all the 
4755                  stores in the group in DR_CHAIN and OPRNDS. DR_CHAIN is then 
4756                  used as an input to vect_permute_store_chain(), and OPRNDS as 
4757                  an input to vect_get_vec_def_for_stmt_copy() for the next copy.
4758
4759                  If the store is not strided, GROUP_SIZE is 1, and DR_CHAIN and
4760                  OPRNDS are of size 1.  */
4761               next_stmt = first_stmt;     
4762               for (i = 0; i < group_size; i++)
4763                 {
4764                   /* Since gaps are not supported for interleaved stores, 
4765                      GROUP_SIZE is the exact number of stmts in the chain. 
4766                      Therefore, NEXT_STMT can't be NULL_TREE.  In case that 
4767                      there is no interleaving, GROUP_SIZE is 1, and only one 
4768                      iteration of the loop will be executed.  */
4769                   gcc_assert (next_stmt);
4770                   op = GIMPLE_STMT_OPERAND (next_stmt, 1);
4771
4772                   vec_oprnd = vect_get_vec_def_for_operand (op, next_stmt, 
4773                                                             NULL);
4774                   VEC_quick_push(tree, dr_chain, vec_oprnd); 
4775                   VEC_quick_push(tree, oprnds, vec_oprnd); 
4776                   next_stmt = DR_GROUP_NEXT_DR (vinfo_for_stmt (next_stmt));
4777                 }
4778             }
4779           dataref_ptr = vect_create_data_ref_ptr (first_stmt, NULL, NULL_TREE, 
4780                                                   &dummy, &ptr_incr, false,
4781                                                   TREE_TYPE (vec_oprnd), &inv_p);
4782           gcc_assert (!inv_p);
4783         }
4784       else 
4785         {
4786           /* FORNOW SLP doesn't work for multiple types.  */
4787           gcc_assert (!slp);
4788
4789           /* For interleaved stores we created vectorized defs for all the 
4790              defs stored in OPRNDS in the previous iteration (previous copy). 
4791              DR_CHAIN is then used as an input to vect_permute_store_chain(), 
4792              and OPRNDS as an input to vect_get_vec_def_for_stmt_copy() for the
4793              next copy.
4794              If the store is not strided, GROUP_SIZE is 1, and DR_CHAIN and
4795              OPRNDS are of size 1.  */
4796           for (i = 0; i < group_size; i++)
4797             {
4798               vec_oprnd = vect_get_vec_def_for_stmt_copy (dt, 
4799                                                    VEC_index (tree, oprnds, i));
4800               VEC_replace(tree, dr_chain, i, vec_oprnd);
4801               VEC_replace(tree, oprnds, i, vec_oprnd);
4802             }
4803           dataref_ptr = 
4804                 bump_vector_ptr (dataref_ptr, ptr_incr, bsi, stmt, NULL_TREE);
4805         }
4806
4807       if (strided_store)
4808         {
4809           result_chain = VEC_alloc (tree, heap, group_size);     
4810           /* Permute.  */
4811           if (!vect_permute_store_chain (dr_chain, group_size, stmt, bsi, 
4812                                          &result_chain))
4813             return false;
4814         }
4815
4816       next_stmt = first_stmt;
4817       for (i = 0; i < vec_num; i++)
4818         {
4819           if (i > 0)
4820             /* Bump the vector pointer.  */
4821             dataref_ptr = bump_vector_ptr (dataref_ptr, ptr_incr, bsi, stmt,
4822                                            NULL_TREE);
4823
4824           if (slp)
4825             vec_oprnd = VEC_index (tree, vec_oprnds, i);
4826           else if (strided_store)
4827             /* For strided stores vectorized defs are interleaved in 
4828                vect_permute_store_chain().  */
4829             vec_oprnd = VEC_index (tree, result_chain, i);
4830
4831           data_ref = build_fold_indirect_ref (dataref_ptr);
4832           /* Arguments are ready. Create the new vector stmt.  */
4833           new_stmt = build_gimple_modify_stmt (data_ref, vec_oprnd);
4834           vect_finish_stmt_generation (stmt, new_stmt, bsi);
4835           mark_symbols_for_renaming (new_stmt);
4836           
4837           if (j == 0)
4838             STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt =  new_stmt;
4839           else
4840             STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
4841
4842           prev_stmt_info = vinfo_for_stmt (new_stmt);
4843           next_stmt = DR_GROUP_NEXT_DR (vinfo_for_stmt (next_stmt));
4844           if (!next_stmt)
4845             break;
4846         }
4847     }
4848
4849   return true;
4850 }
4851
4852
4853 /* Function vect_setup_realignment
4854   
4855    This function is called when vectorizing an unaligned load using
4856    the dr_explicit_realign[_optimized] scheme.
4857    This function generates the following code at the loop prolog:
4858
4859       p = initial_addr;
4860    x  msq_init = *(floor(p));   # prolog load
4861       realignment_token = call target_builtin; 
4862     loop:
4863    x  msq = phi (msq_init, ---)
4864
4865    The stmts marked with x are generated only for the case of 
4866    dr_explicit_realign_optimized.
4867
4868    The code above sets up a new (vector) pointer, pointing to the first 
4869    location accessed by STMT, and a "floor-aligned" load using that pointer.
4870    It also generates code to compute the "realignment-token" (if the relevant
4871    target hook was defined), and creates a phi-node at the loop-header bb
4872    whose arguments are the result of the prolog-load (created by this
4873    function) and the result of a load that takes place in the loop (to be
4874    created by the caller to this function).
4875
4876    For the case of dr_explicit_realign_optimized:
4877    The caller to this function uses the phi-result (msq) to create the 
4878    realignment code inside the loop, and sets up the missing phi argument,
4879    as follows:
4880     loop: 
4881       msq = phi (msq_init, lsq)
4882       lsq = *(floor(p'));        # load in loop
4883       result = realign_load (msq, lsq, realignment_token);
4884
4885    For the case of dr_explicit_realign:
4886     loop:
4887       msq = *(floor(p));        # load in loop
4888       p' = p + (VS-1);
4889       lsq = *(floor(p'));       # load in loop
4890       result = realign_load (msq, lsq, realignment_token);
4891
4892    Input:
4893    STMT - (scalar) load stmt to be vectorized. This load accesses
4894           a memory location that may be unaligned.
4895    BSI - place where new code is to be inserted.
4896    ALIGNMENT_SUPPORT_SCHEME - which of the two misalignment handling schemes
4897                               is used.  
4898    
4899    Output:
4900    REALIGNMENT_TOKEN - the result of a call to the builtin_mask_for_load
4901                        target hook, if defined.
4902    Return value - the result of the loop-header phi node.  */
4903
4904 static tree
4905 vect_setup_realignment (tree stmt, block_stmt_iterator *bsi,
4906                         tree *realignment_token,
4907                         enum dr_alignment_support alignment_support_scheme,
4908                         tree init_addr,
4909                         struct loop **at_loop)
4910 {
4911   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
4912   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
4913   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
4914   struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
4915   edge pe;
4916   tree scalar_dest = GIMPLE_STMT_OPERAND (stmt, 0);
4917   tree vec_dest;
4918   tree inc;
4919   tree ptr;
4920   tree data_ref;
4921   tree new_stmt;
4922   basic_block new_bb;
4923   tree msq_init = NULL_TREE;
4924   tree new_temp;
4925   tree phi_stmt;
4926   tree msq = NULL_TREE;
4927   tree stmts = NULL_TREE;
4928   bool inv_p;
4929   bool compute_in_loop = false;
4930   bool nested_in_vect_loop = nested_in_vect_loop_p (loop, stmt);
4931   struct loop *containing_loop = (bb_for_stmt (stmt))->loop_father;
4932   struct loop *loop_for_initial_load;
4933
4934   gcc_assert (alignment_support_scheme == dr_explicit_realign
4935               || alignment_support_scheme == dr_explicit_realign_optimized);
4936
4937   /* We need to generate three things:
4938      1. the misalignment computation
4939      2. the extra vector load (for the optimized realignment scheme).
4940      3. the phi node for the two vectors from which the realignment is
4941       done (for the optimized realignment scheme).
4942    */
4943
4944   /* 1. Determine where to generate the misalignment computation.
4945
4946      If INIT_ADDR is NULL_TREE, this indicates that the misalignment
4947      calculation will be generated by this function, outside the loop (in the
4948      preheader).  Otherwise, INIT_ADDR had already been computed for us by the
4949      caller, inside the loop.
4950
4951      Background: If the misalignment remains fixed throughout the iterations of
4952      the loop, then both realignment schemes are applicable, and also the
4953      misalignment computation can be done outside LOOP.  This is because we are
4954      vectorizing LOOP, and so the memory accesses in LOOP advance in steps that
4955      are a multiple of VS (the Vector Size), and therefore the misalignment in
4956      different vectorized LOOP iterations is always the same.
4957      The problem arises only if the memory access is in an inner-loop nested
4958      inside LOOP, which is now being vectorized using outer-loop vectorization.
4959      This is the only case when the misalignment of the memory access may not
4960      remain fixed throughout the iterations of the inner-loop (as explained in
4961      detail in vect_supportable_dr_alignment).  In this case, not only is the
4962      optimized realignment scheme not applicable, but also the misalignment
4963      computation (and generation of the realignment token that is passed to
4964      REALIGN_LOAD) have to be done inside the loop.
4965
4966      In short, INIT_ADDR indicates whether we are in a COMPUTE_IN_LOOP mode
4967      or not, which in turn determines if the misalignment is computed inside
4968      the inner-loop, or outside LOOP.  */
4969
4970   if (init_addr != NULL_TREE)
4971     {
4972       compute_in_loop = true;
4973       gcc_assert (alignment_support_scheme == dr_explicit_realign);
4974     }
4975
4976
4977   /* 2. Determine where to generate the extra vector load.
4978
4979      For the optimized realignment scheme, instead of generating two vector
4980      loads in each iteration, we generate a single extra vector load in the
4981      preheader of the loop, and in each iteration reuse the result of the
4982      vector load from the previous iteration.  In case the memory access is in
4983      an inner-loop nested inside LOOP, which is now being vectorized using
4984      outer-loop vectorization, we need to determine whether this initial vector
4985      load should be generated at the preheader of the inner-loop, or can be
4986      generated at the preheader of LOOP.  If the memory access has no evolution
4987      in LOOP, it can be generated in the preheader of LOOP. Otherwise, it has
4988      to be generated inside LOOP (in the preheader of the inner-loop).  */
4989
4990   if (nested_in_vect_loop)
4991     {
4992       tree outerloop_step = STMT_VINFO_DR_STEP (stmt_info);
4993       bool invariant_in_outerloop =
4994             (tree_int_cst_compare (outerloop_step, size_zero_node) == 0);
4995       loop_for_initial_load = (invariant_in_outerloop ? loop : loop->inner);
4996     }
4997   else
4998     loop_for_initial_load = loop;
4999   if (at_loop)
5000     *at_loop = loop_for_initial_load;
5001
5002   /* 3. For the case of the optimized realignment, create the first vector
5003       load at the loop preheader.  */
5004
5005   if (alignment_support_scheme == dr_explicit_realign_optimized)
5006     {
5007       /* Create msq_init = *(floor(p1)) in the loop preheader  */
5008
5009       gcc_assert (!compute_in_loop);
5010       pe = loop_preheader_edge (loop_for_initial_load);
5011       vec_dest = vect_create_destination_var (scalar_dest, vectype);
5012       ptr = vect_create_data_ref_ptr (stmt, loop_for_initial_load, NULL_TREE,
5013                                 &init_addr, &inc, true, NULL_TREE, &inv_p);
5014       data_ref = build1 (ALIGN_INDIRECT_REF, vectype, ptr);
5015       new_stmt = build_gimple_modify_stmt (vec_dest, data_ref);
5016       new_temp = make_ssa_name (vec_dest, new_stmt);
5017       GIMPLE_STMT_OPERAND (new_stmt, 0) = new_temp;
5018       new_bb = bsi_insert_on_edge_immediate (pe, new_stmt);
5019       gcc_assert (!new_bb);
5020       msq_init = GIMPLE_STMT_OPERAND (new_stmt, 0);
5021     }
5022
5023   /* 4. Create realignment token using a target builtin, if available.
5024       It is done either inside the containing loop, or before LOOP (as
5025       determined above).  */
5026
5027   if (targetm.vectorize.builtin_mask_for_load)
5028     {
5029       tree builtin_decl;
5030
5031       /* Compute INIT_ADDR - the initial addressed accessed by this memref.  */
5032       if (compute_in_loop)
5033         gcc_assert (init_addr); /* already computed by the caller.  */
5034       else
5035         {
5036           /* Generate the INIT_ADDR computation outside LOOP.  */
5037           init_addr = vect_create_addr_base_for_vector_ref (stmt, &stmts,
5038                                                         NULL_TREE, loop);
5039           pe = loop_preheader_edge (loop);
5040           new_bb = bsi_insert_on_edge_immediate (pe, stmts);
5041           gcc_assert (!new_bb);
5042         }
5043
5044       builtin_decl = targetm.vectorize.builtin_mask_for_load ();
5045       new_stmt = build_call_expr (builtin_decl, 1, init_addr);
5046       vec_dest = vect_create_destination_var (scalar_dest, 
5047                                               TREE_TYPE (new_stmt));
5048       new_stmt = build_gimple_modify_stmt (vec_dest, new_stmt);
5049       new_temp = make_ssa_name (vec_dest, new_stmt);
5050       GIMPLE_STMT_OPERAND (new_stmt, 0) = new_temp;
5051
5052       if (compute_in_loop)
5053         bsi_insert_before (bsi, new_stmt, BSI_SAME_STMT);
5054       else
5055         {
5056           /* Generate the misalignment computation outside LOOP.  */
5057           pe = loop_preheader_edge (loop);
5058           new_bb = bsi_insert_on_edge_immediate (pe, new_stmt);
5059           gcc_assert (!new_bb);
5060         }
5061
5062       *realignment_token = GIMPLE_STMT_OPERAND (new_stmt, 0);
5063
5064       /* The result of the CALL_EXPR to this builtin is determined from
5065          the value of the parameter and no global variables are touched
5066          which makes the builtin a "const" function.  Requiring the
5067          builtin to have the "const" attribute makes it unnecessary
5068          to call mark_call_clobbered.  */
5069       gcc_assert (TREE_READONLY (builtin_decl));
5070     }
5071
5072   if (alignment_support_scheme == dr_explicit_realign)
5073     return msq;
5074
5075   gcc_assert (!compute_in_loop);
5076   gcc_assert (alignment_support_scheme == dr_explicit_realign_optimized);
5077
5078
5079   /* 5. Create msq = phi <msq_init, lsq> in loop  */
5080
5081   pe = loop_preheader_edge (containing_loop);
5082   vec_dest = vect_create_destination_var (scalar_dest, vectype);
5083   msq = make_ssa_name (vec_dest, NULL_TREE);
5084   phi_stmt = create_phi_node (msq, containing_loop->header);
5085   SSA_NAME_DEF_STMT (msq) = phi_stmt;
5086   add_phi_arg (phi_stmt, msq_init, pe);
5087
5088   return msq;
5089 }
5090
5091
5092 /* Function vect_strided_load_supported.
5093
5094    Returns TRUE is EXTRACT_EVEN and EXTRACT_ODD operations are supported,
5095    and FALSE otherwise.  */
5096
5097 static bool
5098 vect_strided_load_supported (tree vectype)
5099 {
5100   optab perm_even_optab, perm_odd_optab;
5101   int mode;
5102
5103   mode = (int) TYPE_MODE (vectype);
5104
5105   perm_even_optab = optab_for_tree_code (VEC_EXTRACT_EVEN_EXPR, vectype);
5106   if (!perm_even_optab)
5107     {
5108       if (vect_print_dump_info (REPORT_DETAILS))
5109         fprintf (vect_dump, "no optab for perm_even.");
5110       return false;
5111     }
5112
5113   if (optab_handler (perm_even_optab, mode)->insn_code == CODE_FOR_nothing)
5114     {
5115       if (vect_print_dump_info (REPORT_DETAILS))
5116         fprintf (vect_dump, "perm_even op not supported by target.");
5117       return false;
5118     }
5119
5120   perm_odd_optab = optab_for_tree_code (VEC_EXTRACT_ODD_EXPR, vectype);
5121   if (!perm_odd_optab)
5122     {
5123       if (vect_print_dump_info (REPORT_DETAILS))
5124         fprintf (vect_dump, "no optab for perm_odd.");
5125       return false;
5126     }
5127
5128   if (optab_handler (perm_odd_optab, mode)->insn_code == CODE_FOR_nothing)
5129     {
5130       if (vect_print_dump_info (REPORT_DETAILS))
5131         fprintf (vect_dump, "perm_odd op not supported by target.");
5132       return false;
5133     }
5134   return true;
5135 }
5136
5137
5138 /* Function vect_permute_load_chain.
5139
5140    Given a chain of interleaved loads in DR_CHAIN of LENGTH that must be
5141    a power of 2, generate extract_even/odd stmts to reorder the input data 
5142    correctly. Return the final references for loads in RESULT_CHAIN.
5143
5144    E.g., LENGTH is 4 and the scalar type is short, i.e., VF is 8.
5145    The input is 4 vectors each containing 8 elements. We assign a number to each
5146    element, the input sequence is:
5147
5148    1st vec:   0  1  2  3  4  5  6  7
5149    2nd vec:   8  9 10 11 12 13 14 15
5150    3rd vec:  16 17 18 19 20 21 22 23 
5151    4th vec:  24 25 26 27 28 29 30 31
5152
5153    The output sequence should be:
5154
5155    1st vec:  0 4  8 12 16 20 24 28
5156    2nd vec:  1 5  9 13 17 21 25 29
5157    3rd vec:  2 6 10 14 18 22 26 30 
5158    4th vec:  3 7 11 15 19 23 27 31
5159
5160    i.e., the first output vector should contain the first elements of each
5161    interleaving group, etc.
5162
5163    We use extract_even/odd instructions to create such output. The input of each
5164    extract_even/odd operation is two vectors
5165    1st vec    2nd vec 
5166    0 1 2 3    4 5 6 7 
5167
5168    and the output is the vector of extracted even/odd elements. The output of 
5169    extract_even will be:   0 2 4 6
5170    and of extract_odd:     1 3 5 7
5171
5172    
5173    The permutation is done in log LENGTH stages. In each stage extract_even and
5174    extract_odd stmts are created for each pair of vectors in DR_CHAIN in their 
5175    order. In our example, 
5176
5177    E1: extract_even (1st vec, 2nd vec)
5178    E2: extract_odd (1st vec, 2nd vec)
5179    E3: extract_even (3rd vec, 4th vec)
5180    E4: extract_odd (3rd vec, 4th vec)
5181
5182    The output for the first stage will be:
5183
5184    E1:  0  2  4  6  8 10 12 14
5185    E2:  1  3  5  7  9 11 13 15
5186    E3: 16 18 20 22 24 26 28 30 
5187    E4: 17 19 21 23 25 27 29 31
5188
5189    In order to proceed and create the correct sequence for the next stage (or
5190    for the correct output, if the second stage is the last one, as in our 
5191    example), we first put the output of extract_even operation and then the 
5192    output of extract_odd in RESULT_CHAIN (which is then copied to DR_CHAIN).
5193    The input for the second stage is:
5194
5195    1st vec (E1):  0  2  4  6  8 10 12 14
5196    2nd vec (E3): 16 18 20 22 24 26 28 30  
5197    3rd vec (E2):  1  3  5  7  9 11 13 15    
5198    4th vec (E4): 17 19 21 23 25 27 29 31
5199
5200    The output of the second stage:
5201
5202    E1: 0 4  8 12 16 20 24 28
5203    E2: 2 6 10 14 18 22 26 30
5204    E3: 1 5  9 13 17 21 25 29
5205    E4: 3 7 11 15 19 23 27 31
5206
5207    And RESULT_CHAIN after reordering:
5208
5209    1st vec (E1):  0 4  8 12 16 20 24 28
5210    2nd vec (E3):  1 5  9 13 17 21 25 29
5211    3rd vec (E2):  2 6 10 14 18 22 26 30 
5212    4th vec (E4):  3 7 11 15 19 23 27 31.  */
5213
5214 static bool
5215 vect_permute_load_chain (VEC(tree,heap) *dr_chain, 
5216                          unsigned int length, 
5217                          tree stmt, 
5218                          block_stmt_iterator *bsi,
5219                          VEC(tree,heap) **result_chain)
5220 {
5221   tree perm_dest, perm_stmt, data_ref, first_vect, second_vect;
5222   tree vectype = STMT_VINFO_VECTYPE (vinfo_for_stmt (stmt));
5223   tree tmp;
5224   int i;
5225   unsigned int j;
5226
5227   /* Check that the operation is supported.  */
5228   if (!vect_strided_load_supported (vectype))
5229     return false;
5230
5231   *result_chain = VEC_copy (tree, heap, dr_chain);
5232   for (i = 0; i < exact_log2 (length); i++)
5233     {
5234       for (j = 0; j < length; j +=2)
5235         {
5236           first_vect = VEC_index (tree, dr_chain, j);
5237           second_vect = VEC_index (tree, dr_chain, j+1);
5238
5239           /* data_ref = permute_even (first_data_ref, second_data_ref);  */
5240           perm_dest = create_tmp_var (vectype, "vect_perm_even");
5241           DECL_GIMPLE_REG_P (perm_dest) = 1;
5242           add_referenced_var (perm_dest);
5243
5244           tmp = build2 (VEC_EXTRACT_EVEN_EXPR, vectype,
5245                         first_vect, second_vect);
5246           perm_stmt = build_gimple_modify_stmt (perm_dest, tmp);
5247
5248           data_ref = make_ssa_name (perm_dest, perm_stmt);
5249           GIMPLE_STMT_OPERAND (perm_stmt, 0) = data_ref;
5250           vect_finish_stmt_generation (stmt, perm_stmt, bsi);
5251           mark_symbols_for_renaming (perm_stmt);
5252
5253           VEC_replace (tree, *result_chain, j/2, data_ref);           
5254               
5255           /* data_ref = permute_odd (first_data_ref, second_data_ref);  */
5256           perm_dest = create_tmp_var (vectype, "vect_perm_odd");
5257           DECL_GIMPLE_REG_P (perm_dest) = 1;
5258           add_referenced_var (perm_dest);
5259
5260           tmp = build2 (VEC_EXTRACT_ODD_EXPR, vectype, 
5261                         first_vect, second_vect);
5262           perm_stmt = build_gimple_modify_stmt (perm_dest, tmp);
5263           data_ref = make_ssa_name (perm_dest, perm_stmt);
5264           GIMPLE_STMT_OPERAND (perm_stmt, 0) = data_ref;
5265           vect_finish_stmt_generation (stmt, perm_stmt, bsi);
5266           mark_symbols_for_renaming (perm_stmt);
5267
5268           VEC_replace (tree, *result_chain, j/2+length/2, data_ref);
5269         }
5270       dr_chain = VEC_copy (tree, heap, *result_chain);
5271     }
5272   return true;
5273 }
5274
5275
5276 /* Function vect_transform_strided_load.
5277
5278    Given a chain of input interleaved data-refs (in DR_CHAIN), build statements
5279    to perform their permutation and ascribe the result vectorized statements to
5280    the scalar statements.
5281 */
5282
5283 static bool
5284 vect_transform_strided_load (tree stmt, VEC(tree,heap) *dr_chain, int size,
5285                              block_stmt_iterator *bsi)
5286 {
5287   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
5288   tree first_stmt = DR_GROUP_FIRST_DR (stmt_info);
5289   tree next_stmt, new_stmt;
5290   VEC(tree,heap) *result_chain = NULL;
5291   unsigned int i, gap_count;
5292   tree tmp_data_ref;
5293
5294   /* DR_CHAIN contains input data-refs that are a part of the interleaving. 
5295      RESULT_CHAIN is the output of vect_permute_load_chain, it contains permuted 
5296      vectors, that are ready for vector computation.  */
5297   result_chain = VEC_alloc (tree, heap, size);
5298   /* Permute.  */
5299   if (!vect_permute_load_chain (dr_chain, size, stmt, bsi, &result_chain))
5300     return false;
5301
5302   /* Put a permuted data-ref in the VECTORIZED_STMT field.  
5303      Since we scan the chain starting from it's first node, their order 
5304      corresponds the order of data-refs in RESULT_CHAIN.  */
5305   next_stmt = first_stmt;
5306   gap_count = 1;
5307   for (i = 0; VEC_iterate (tree, result_chain, i, tmp_data_ref); i++)
5308     {
5309       if (!next_stmt)
5310         break;
5311
5312       /* Skip the gaps. Loads created for the gaps will be removed by dead
5313        code elimination pass later.
5314        DR_GROUP_GAP is the number of steps in elements from the previous
5315        access (if there is no gap DR_GROUP_GAP is 1). We skip loads that
5316        correspond to the gaps.
5317       */
5318       if (gap_count < DR_GROUP_GAP (vinfo_for_stmt (next_stmt)))
5319       {
5320         gap_count++;
5321         continue;
5322       }
5323
5324       while (next_stmt)
5325         {
5326           new_stmt = SSA_NAME_DEF_STMT (tmp_data_ref);
5327           /* We assume that if VEC_STMT is not NULL, this is a case of multiple
5328              copies, and we put the new vector statement in the first available
5329              RELATED_STMT.  */
5330           if (!STMT_VINFO_VEC_STMT (vinfo_for_stmt (next_stmt)))
5331             STMT_VINFO_VEC_STMT (vinfo_for_stmt (next_stmt)) = new_stmt;
5332           else
5333             {
5334               tree prev_stmt = STMT_VINFO_VEC_STMT (vinfo_for_stmt (next_stmt));
5335               tree rel_stmt = STMT_VINFO_RELATED_STMT (
5336                                                        vinfo_for_stmt (prev_stmt));
5337               while (rel_stmt)
5338                 {
5339                   prev_stmt = rel_stmt;
5340                   rel_stmt = STMT_VINFO_RELATED_STMT (vinfo_for_stmt (rel_stmt));
5341                 }
5342               STMT_VINFO_RELATED_STMT (vinfo_for_stmt (prev_stmt)) = new_stmt;
5343             }
5344           next_stmt = DR_GROUP_NEXT_DR (vinfo_for_stmt (next_stmt));
5345           gap_count = 1;
5346           /* If NEXT_STMT accesses the same DR as the previous statement,
5347              put the same TMP_DATA_REF as its vectorized statement; otherwise
5348              get the next data-ref from RESULT_CHAIN.  */
5349           if (!next_stmt || !DR_GROUP_SAME_DR_STMT (vinfo_for_stmt (next_stmt)))
5350             break;
5351         }
5352     }
5353   return true;
5354 }
5355
5356
5357 /* vectorizable_load.
5358
5359    Check if STMT reads a non scalar data-ref (array/pointer/structure) that 
5360    can be vectorized. 
5361    If VEC_STMT is also passed, vectorize the STMT: create a vectorized 
5362    stmt to replace it, put it in VEC_STMT, and insert it at BSI.
5363    Return FALSE if not a vectorizable STMT, TRUE otherwise.  */
5364
5365 bool
5366 vectorizable_load (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt, 
5367                    slp_tree slp_node)
5368 {
5369   tree scalar_dest;
5370   tree vec_dest = NULL;
5371   tree data_ref = NULL;
5372   tree op;
5373   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
5374   stmt_vec_info prev_stmt_info; 
5375   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
5376   struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
5377   struct loop *containing_loop = (bb_for_stmt (stmt))->loop_father;
5378   bool nested_in_vect_loop = nested_in_vect_loop_p (loop, stmt);
5379   struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info), *first_dr;
5380   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
5381   tree new_temp;
5382   int mode;
5383   tree new_stmt = NULL_TREE;
5384   tree dummy;
5385   enum dr_alignment_support alignment_support_scheme;
5386   tree dataref_ptr = NULL_TREE;
5387   tree ptr_incr;
5388   int nunits = TYPE_VECTOR_SUBPARTS (vectype);
5389   int ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits;
5390   int i, j, group_size;
5391   tree msq = NULL_TREE, lsq;
5392   tree offset = NULL_TREE;
5393   tree realignment_token = NULL_TREE;
5394   tree phi = NULL_TREE;
5395   VEC(tree,heap) *dr_chain = NULL;
5396   bool strided_load = false;
5397   tree first_stmt;
5398   tree scalar_type;
5399   bool inv_p;
5400   bool compute_in_loop = false;
5401   struct loop *at_loop;
5402   int vec_num;
5403   bool slp = (slp_node != NULL);
5404
5405   /* FORNOW: SLP with multiple types is not supported. The SLP analysis verifies
5406       this, so we can safely override NCOPIES with 1 here.  */
5407   if (slp)
5408     ncopies = 1;
5409
5410   gcc_assert (ncopies >= 1);
5411
5412   /* FORNOW. This restriction should be relaxed.  */
5413   if (nested_in_vect_loop && ncopies > 1)
5414     {
5415       if (vect_print_dump_info (REPORT_DETAILS))
5416         fprintf (vect_dump, "multiple types in nested loop.");
5417       return false;
5418     }
5419
5420   if (!STMT_VINFO_RELEVANT_P (stmt_info))
5421     return false;
5422
5423   if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_loop_def)
5424     return false;
5425
5426   /* FORNOW: not yet supported.  */
5427   if (STMT_VINFO_LIVE_P (stmt_info))
5428     {
5429       if (vect_print_dump_info (REPORT_DETAILS))
5430         fprintf (vect_dump, "value used after loop.");
5431       return false;
5432     }
5433
5434   /* Is vectorizable load? */
5435   if (TREE_CODE (stmt) != GIMPLE_MODIFY_STMT)
5436     return false;
5437
5438   scalar_dest = GIMPLE_STMT_OPERAND (stmt, 0);
5439   if (TREE_CODE (scalar_dest) != SSA_NAME)
5440     return false;
5441
5442   op = GIMPLE_STMT_OPERAND (stmt, 1);
5443   if (TREE_CODE (op) != ARRAY_REF 
5444       && TREE_CODE (op) != INDIRECT_REF
5445       && !STMT_VINFO_STRIDED_ACCESS (stmt_info))
5446     return false;
5447
5448   if (!STMT_VINFO_DATA_REF (stmt_info))
5449     return false;
5450
5451   scalar_type = TREE_TYPE (DR_REF (dr));
5452   mode = (int) TYPE_MODE (vectype);
5453
5454   /* FORNOW. In some cases can vectorize even if data-type not supported
5455     (e.g. - data copies).  */
5456   if (optab_handler (mov_optab, mode)->insn_code == CODE_FOR_nothing)
5457     {
5458       if (vect_print_dump_info (REPORT_DETAILS))
5459         fprintf (vect_dump, "Aligned load, but unsupported type.");
5460       return false;
5461     }
5462
5463   /* Check if the load is a part of an interleaving chain.  */
5464   if (STMT_VINFO_STRIDED_ACCESS (stmt_info))
5465     {
5466       strided_load = true;
5467       /* FORNOW */
5468       gcc_assert (! nested_in_vect_loop);
5469
5470       /* Check if interleaving is supported.  */
5471       if (!vect_strided_load_supported (vectype)
5472           && !PURE_SLP_STMT (stmt_info) && !slp)
5473         return false;
5474     }
5475
5476   if (!vec_stmt) /* transformation not required.  */
5477     {
5478       STMT_VINFO_TYPE (stmt_info) = load_vec_info_type;
5479       vect_model_load_cost (stmt_info, ncopies, NULL);
5480       return true;
5481     }
5482
5483   if (vect_print_dump_info (REPORT_DETAILS))
5484     fprintf (vect_dump, "transform load.");
5485
5486   /** Transform.  **/
5487
5488   if (strided_load)
5489     {
5490       first_stmt = DR_GROUP_FIRST_DR (stmt_info);
5491       /* Check if the chain of loads is already vectorized.  */
5492       if (STMT_VINFO_VEC_STMT (vinfo_for_stmt (first_stmt)))
5493         {
5494           *vec_stmt = STMT_VINFO_VEC_STMT (stmt_info);
5495           return true;
5496         }
5497       first_dr = STMT_VINFO_DATA_REF (vinfo_for_stmt (first_stmt));
5498       group_size = DR_GROUP_SIZE (vinfo_for_stmt (first_stmt));
5499       dr_chain = VEC_alloc (tree, heap, group_size);
5500
5501       /* VEC_NUM is the number of vect stmts to be created for this group.  */
5502       if (slp)
5503         {
5504           strided_load = false;
5505           vec_num = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node);
5506         }
5507       else
5508         vec_num = group_size;
5509     }
5510   else
5511     {
5512       first_stmt = stmt;
5513       first_dr = dr;
5514       group_size = vec_num = 1;
5515     }
5516
5517   alignment_support_scheme = vect_supportable_dr_alignment (first_dr);
5518   gcc_assert (alignment_support_scheme);
5519
5520   /* In case the vectorization factor (VF) is bigger than the number
5521      of elements that we can fit in a vectype (nunits), we have to generate
5522      more than one vector stmt - i.e - we need to "unroll" the
5523      vector stmt by a factor VF/nunits. In doing so, we record a pointer
5524      from one copy of the vector stmt to the next, in the field
5525      STMT_VINFO_RELATED_STMT. This is necessary in order to allow following
5526      stages to find the correct vector defs to be used when vectorizing
5527      stmts that use the defs of the current stmt. The example below illustrates
5528      the vectorization process when VF=16 and nunits=4 (i.e - we need to create
5529      4 vectorized stmts):
5530
5531      before vectorization:
5532                                 RELATED_STMT    VEC_STMT
5533         S1:     x = memref      -               -
5534         S2:     z = x + 1       -               -
5535
5536      step 1: vectorize stmt S1:
5537         We first create the vector stmt VS1_0, and, as usual, record a
5538         pointer to it in the STMT_VINFO_VEC_STMT of the scalar stmt S1.
5539         Next, we create the vector stmt VS1_1, and record a pointer to
5540         it in the STMT_VINFO_RELATED_STMT of the vector stmt VS1_0.
5541         Similarly, for VS1_2 and VS1_3. This is the resulting chain of
5542         stmts and pointers:
5543                                 RELATED_STMT    VEC_STMT
5544         VS1_0:  vx0 = memref0   VS1_1           -
5545         VS1_1:  vx1 = memref1   VS1_2           -
5546         VS1_2:  vx2 = memref2   VS1_3           -
5547         VS1_3:  vx3 = memref3   -               -
5548         S1:     x = load        -               VS1_0
5549         S2:     z = x + 1       -               -
5550
5551      See in documentation in vect_get_vec_def_for_stmt_copy for how the 
5552      information we recorded in RELATED_STMT field is used to vectorize 
5553      stmt S2.  */
5554
5555   /* In case of interleaving (non-unit strided access):
5556
5557      S1:  x2 = &base + 2
5558      S2:  x0 = &base
5559      S3:  x1 = &base + 1
5560      S4:  x3 = &base + 3
5561
5562      Vectorized loads are created in the order of memory accesses 
5563      starting from the access of the first stmt of the chain:
5564
5565      VS1: vx0 = &base
5566      VS2: vx1 = &base + vec_size*1
5567      VS3: vx3 = &base + vec_size*2
5568      VS4: vx4 = &base + vec_size*3
5569
5570      Then permutation statements are generated:
5571
5572      VS5: vx5 = VEC_EXTRACT_EVEN_EXPR < vx0, vx1 >
5573      VS6: vx6 = VEC_EXTRACT_ODD_EXPR < vx0, vx1 >
5574        ...
5575
5576      And they are put in STMT_VINFO_VEC_STMT of the corresponding scalar stmts
5577      (the order of the data-refs in the output of vect_permute_load_chain
5578      corresponds to the order of scalar stmts in the interleaving chain - see
5579      the documentation of vect_permute_load_chain()).
5580      The generation of permutation stmts and recording them in
5581      STMT_VINFO_VEC_STMT is done in vect_transform_strided_load().
5582
5583      In case of both multiple types and interleaving, the vector loads and 
5584      permutation stmts above are created for every copy. The result vector stmts
5585      are put in STMT_VINFO_VEC_STMT for the first copy and in the corresponding
5586      STMT_VINFO_RELATED_STMT for the next copies.  */
5587
5588   /* If the data reference is aligned (dr_aligned) or potentially unaligned
5589      on a target that supports unaligned accesses (dr_unaligned_supported)
5590      we generate the following code:
5591          p = initial_addr;
5592          indx = 0;
5593          loop {
5594            p = p + indx * vectype_size;
5595            vec_dest = *(p);
5596            indx = indx + 1;
5597          }
5598
5599      Otherwise, the data reference is potentially unaligned on a target that
5600      does not support unaligned accesses (dr_explicit_realign_optimized) - 
5601      then generate the following code, in which the data in each iteration is
5602      obtained by two vector loads, one from the previous iteration, and one
5603      from the current iteration:
5604          p1 = initial_addr;
5605          msq_init = *(floor(p1))
5606          p2 = initial_addr + VS - 1;
5607          realignment_token = call target_builtin;
5608          indx = 0;
5609          loop {
5610            p2 = p2 + indx * vectype_size
5611            lsq = *(floor(p2))
5612            vec_dest = realign_load (msq, lsq, realignment_token)
5613            indx = indx + 1;
5614            msq = lsq;
5615          }   */
5616
5617   /* If the misalignment remains the same throughout the execution of the
5618      loop, we can create the init_addr and permutation mask at the loop
5619      preheader. Otherwise, it needs to be created inside the loop.
5620      This can only occur when vectorizing memory accesses in the inner-loop
5621      nested within an outer-loop that is being vectorized.  */
5622
5623   if (nested_in_vect_loop_p (loop, stmt)
5624       && (TREE_INT_CST_LOW (DR_STEP (dr)) % UNITS_PER_SIMD_WORD != 0))
5625     {
5626       gcc_assert (alignment_support_scheme != dr_explicit_realign_optimized);
5627       compute_in_loop = true;
5628     }
5629
5630   if ((alignment_support_scheme == dr_explicit_realign_optimized
5631        || alignment_support_scheme == dr_explicit_realign)
5632       && !compute_in_loop)
5633     {
5634       msq = vect_setup_realignment (first_stmt, bsi, &realignment_token,
5635                                     alignment_support_scheme, NULL_TREE,
5636                                     &at_loop);
5637       if (alignment_support_scheme == dr_explicit_realign_optimized)
5638         {
5639           phi = SSA_NAME_DEF_STMT (msq);
5640           offset = size_int (TYPE_VECTOR_SUBPARTS (vectype) - 1);
5641         }
5642     }
5643   else
5644     at_loop = loop;
5645
5646   prev_stmt_info = NULL;
5647   for (j = 0; j < ncopies; j++)
5648     { 
5649       /* 1. Create the vector pointer update chain.  */
5650       if (j == 0)
5651         dataref_ptr = vect_create_data_ref_ptr (first_stmt,
5652                                                 at_loop, offset, 
5653                                                 &dummy, &ptr_incr, false, 
5654                                                 NULL_TREE, &inv_p);
5655       else
5656         dataref_ptr = 
5657                 bump_vector_ptr (dataref_ptr, ptr_incr, bsi, stmt, NULL_TREE);
5658
5659       for (i = 0; i < vec_num; i++)
5660         {
5661           if (i > 0)
5662             dataref_ptr = bump_vector_ptr (dataref_ptr, ptr_incr, bsi, stmt,
5663                                            NULL_TREE);
5664
5665           /* 2. Create the vector-load in the loop.  */
5666           switch (alignment_support_scheme)
5667             {
5668             case dr_aligned:
5669               gcc_assert (aligned_access_p (first_dr));
5670               data_ref = build_fold_indirect_ref (dataref_ptr);
5671               break;
5672             case dr_unaligned_supported:
5673               {
5674                 int mis = DR_MISALIGNMENT (first_dr);
5675                 tree tmis = (mis == -1 ? size_zero_node : size_int (mis));
5676
5677                 tmis = size_binop (MULT_EXPR, tmis, size_int(BITS_PER_UNIT));
5678                 data_ref =
5679                   build2 (MISALIGNED_INDIRECT_REF, vectype, dataref_ptr, tmis);
5680                 break;
5681               }
5682             case dr_explicit_realign:
5683               {
5684                 tree ptr, bump;
5685                 tree vs_minus_1 = size_int (TYPE_VECTOR_SUBPARTS (vectype) - 1);
5686
5687                 if (compute_in_loop)
5688                   msq = vect_setup_realignment (first_stmt, bsi, 
5689                                                 &realignment_token,
5690                                                 dr_explicit_realign, 
5691                                                 dataref_ptr, NULL);
5692
5693                 data_ref = build1 (ALIGN_INDIRECT_REF, vectype, dataref_ptr);
5694                 vec_dest = vect_create_destination_var (scalar_dest, vectype);
5695                 new_stmt = build_gimple_modify_stmt (vec_dest, data_ref);
5696                 new_temp = make_ssa_name (vec_dest, new_stmt);
5697                 GIMPLE_STMT_OPERAND (new_stmt, 0) = new_temp;
5698                 vect_finish_stmt_generation (stmt, new_stmt, bsi);
5699                 copy_virtual_operands (new_stmt, stmt);
5700                 mark_symbols_for_renaming (new_stmt);
5701                 msq = new_temp;
5702
5703                 bump = size_binop (MULT_EXPR, vs_minus_1,
5704                                    TYPE_SIZE_UNIT (scalar_type));
5705                 ptr = bump_vector_ptr (dataref_ptr, NULL_TREE, bsi, stmt, bump);
5706                 data_ref = build1 (ALIGN_INDIRECT_REF, vectype, ptr);
5707                 break;
5708               }
5709             case dr_explicit_realign_optimized:
5710               data_ref = build1 (ALIGN_INDIRECT_REF, vectype, dataref_ptr);
5711               break;
5712             default:
5713               gcc_unreachable ();
5714             }
5715           vec_dest = vect_create_destination_var (scalar_dest, vectype);
5716           new_stmt = build_gimple_modify_stmt (vec_dest, data_ref);
5717           new_temp = make_ssa_name (vec_dest, new_stmt);
5718           GIMPLE_STMT_OPERAND (new_stmt, 0) = new_temp;
5719           vect_finish_stmt_generation (stmt, new_stmt, bsi);
5720           mark_symbols_for_renaming (new_stmt);
5721
5722           /* 3. Handle explicit realignment if necessary/supported. Create in
5723                 loop: vec_dest = realign_load (msq, lsq, realignment_token)  */
5724           if (alignment_support_scheme == dr_explicit_realign_optimized
5725               || alignment_support_scheme == dr_explicit_realign)
5726             {
5727               lsq = GIMPLE_STMT_OPERAND (new_stmt, 0);
5728               if (!realignment_token)
5729                 realignment_token = dataref_ptr;
5730               vec_dest = vect_create_destination_var (scalar_dest, vectype);
5731               new_stmt = build3 (REALIGN_LOAD_EXPR, vectype, msq, lsq, 
5732                                  realignment_token);
5733               new_stmt = build_gimple_modify_stmt (vec_dest, new_stmt);
5734               new_temp = make_ssa_name (vec_dest, new_stmt);
5735               GIMPLE_STMT_OPERAND (new_stmt, 0) = new_temp;
5736               vect_finish_stmt_generation (stmt, new_stmt, bsi);
5737
5738               if (alignment_support_scheme == dr_explicit_realign_optimized)
5739                 {
5740                   if (i == vec_num - 1 && j == ncopies - 1)
5741                     add_phi_arg (phi, lsq, loop_latch_edge (containing_loop));
5742                   msq = lsq;
5743                 }
5744             }
5745
5746           /* 4. Handle invariant-load.  */
5747           if (inv_p)
5748             {
5749               gcc_assert (!strided_load);
5750               gcc_assert (nested_in_vect_loop_p (loop, stmt));
5751               if (j == 0)
5752                 {
5753                   int k;
5754                   tree t = NULL_TREE;
5755                   tree vec_inv, bitpos, bitsize = TYPE_SIZE (scalar_type);
5756
5757                   /* CHECKME: bitpos depends on endianess?  */
5758                   bitpos = bitsize_zero_node;
5759                   vec_inv = build3 (BIT_FIELD_REF, scalar_type, new_temp, 
5760                                                             bitsize, bitpos);
5761                   BIT_FIELD_REF_UNSIGNED (vec_inv) = 
5762                                                  TYPE_UNSIGNED (scalar_type);
5763                   vec_dest = 
5764                         vect_create_destination_var (scalar_dest, NULL_TREE);
5765                   new_stmt = build_gimple_modify_stmt (vec_dest, vec_inv);
5766                   new_temp = make_ssa_name (vec_dest, new_stmt);
5767                   GIMPLE_STMT_OPERAND (new_stmt, 0) = new_temp;
5768                   vect_finish_stmt_generation (stmt, new_stmt, bsi);
5769
5770                   for (k = nunits - 1; k >= 0; --k)
5771                     t = tree_cons (NULL_TREE, new_temp, t);
5772                   /* FIXME: use build_constructor directly.  */
5773                   vec_inv = build_constructor_from_list (vectype, t);
5774                   new_temp = vect_init_vector (stmt, vec_inv, vectype, bsi);
5775                   new_stmt = SSA_NAME_DEF_STMT (new_temp);
5776                 }
5777               else
5778                 gcc_unreachable (); /* FORNOW. */
5779             }
5780
5781           /* Collect vector loads and later create their permutation in
5782              vect_transform_strided_load ().  */
5783           if (strided_load)
5784             VEC_quick_push (tree, dr_chain, new_temp);
5785
5786          /* Store vector loads in the corresponding SLP_NODE.  */
5787           if (slp)
5788             VEC_quick_push (tree, SLP_TREE_VEC_STMTS (slp_node), new_stmt);
5789         }
5790
5791       /* FORNOW: SLP with multiple types is unsupported.  */
5792       if (slp)
5793         return true;
5794
5795       if (strided_load)
5796         {
5797           if (!vect_transform_strided_load (stmt, dr_chain, group_size, bsi))
5798             return false;         
5799           *vec_stmt = STMT_VINFO_VEC_STMT (stmt_info);
5800           dr_chain = VEC_alloc (tree, heap, group_size);
5801         }
5802       else
5803         {
5804           if (j == 0)
5805             STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
5806           else
5807             STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
5808           prev_stmt_info = vinfo_for_stmt (new_stmt);
5809         }
5810     }
5811
5812   return true;
5813 }
5814
5815
5816 /* Function vectorizable_live_operation.
5817
5818    STMT computes a value that is used outside the loop. Check if 
5819    it can be supported.  */
5820
5821 bool
5822 vectorizable_live_operation (tree stmt,
5823                              block_stmt_iterator *bsi ATTRIBUTE_UNUSED,
5824                              tree *vec_stmt ATTRIBUTE_UNUSED)
5825 {
5826   tree operation;
5827   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
5828   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
5829   struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
5830   int i;
5831   int op_type;
5832   tree op;
5833   tree def, def_stmt;
5834   enum vect_def_type dt; 
5835
5836   gcc_assert (STMT_VINFO_LIVE_P (stmt_info));
5837
5838   if (STMT_VINFO_DEF_TYPE (stmt_info) == vect_reduction_def)
5839     return false;
5840
5841   if (TREE_CODE (stmt) != GIMPLE_MODIFY_STMT)
5842     return false;
5843
5844   if (TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 0)) != SSA_NAME)
5845     return false;
5846
5847   /* FORNOW. CHECKME. */
5848   if (nested_in_vect_loop_p (loop, stmt))
5849     return false;
5850
5851   operation = GIMPLE_STMT_OPERAND (stmt, 1);
5852   op_type = TREE_OPERAND_LENGTH (operation);
5853
5854   /* FORNOW: support only if all uses are invariant. This means
5855      that the scalar operations can remain in place, unvectorized.
5856      The original last scalar value that they compute will be used.  */
5857
5858   for (i = 0; i < op_type; i++)
5859     {
5860       op = TREE_OPERAND (operation, i);
5861       if (!vect_is_simple_use (op, loop_vinfo, &def_stmt, &def, &dt))
5862         {
5863           if (vect_print_dump_info (REPORT_DETAILS))
5864             fprintf (vect_dump, "use not simple.");
5865           return false;
5866         }
5867
5868       if (dt != vect_invariant_def && dt != vect_constant_def)
5869         return false;
5870     }
5871
5872   /* No transformation is required for the cases we currently support.  */
5873   return true;
5874 }
5875
5876
5877 /* Function vect_is_simple_cond.
5878   
5879    Input:
5880    LOOP - the loop that is being vectorized.
5881    COND - Condition that is checked for simple use.
5882
5883    Returns whether a COND can be vectorized.  Checks whether
5884    condition operands are supportable using vec_is_simple_use.  */
5885
5886 static bool
5887 vect_is_simple_cond (tree cond, loop_vec_info loop_vinfo)
5888 {
5889   tree lhs, rhs;
5890   tree def;
5891   enum vect_def_type dt;
5892
5893   if (!COMPARISON_CLASS_P (cond))
5894     return false;
5895
5896   lhs = TREE_OPERAND (cond, 0);
5897   rhs = TREE_OPERAND (cond, 1);
5898
5899   if (TREE_CODE (lhs) == SSA_NAME)
5900     {
5901       tree lhs_def_stmt = SSA_NAME_DEF_STMT (lhs);
5902       if (!vect_is_simple_use (lhs, loop_vinfo, &lhs_def_stmt, &def, &dt))
5903         return false;
5904     }
5905   else if (TREE_CODE (lhs) != INTEGER_CST && TREE_CODE (lhs) != REAL_CST
5906            && TREE_CODE (lhs) != FIXED_CST)
5907     return false;
5908
5909   if (TREE_CODE (rhs) == SSA_NAME)
5910     {
5911       tree rhs_def_stmt = SSA_NAME_DEF_STMT (rhs);
5912       if (!vect_is_simple_use (rhs, loop_vinfo, &rhs_def_stmt, &def, &dt))
5913         return false;
5914     }
5915   else if (TREE_CODE (rhs) != INTEGER_CST  && TREE_CODE (rhs) != REAL_CST
5916            && TREE_CODE (rhs) != FIXED_CST)
5917     return false;
5918
5919   return true;
5920 }
5921
5922 /* vectorizable_condition.
5923
5924    Check if STMT is conditional modify expression that can be vectorized. 
5925    If VEC_STMT is also passed, vectorize the STMT: create a vectorized 
5926    stmt using VEC_COND_EXPR  to replace it, put it in VEC_STMT, and insert it 
5927    at BSI.
5928
5929    Return FALSE if not a vectorizable STMT, TRUE otherwise.  */
5930
5931 bool
5932 vectorizable_condition (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt)
5933 {
5934   tree scalar_dest = NULL_TREE;
5935   tree vec_dest = NULL_TREE;
5936   tree op = NULL_TREE;
5937   tree cond_expr, then_clause, else_clause;
5938   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
5939   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
5940   tree vec_cond_lhs, vec_cond_rhs, vec_then_clause, vec_else_clause;
5941   tree vec_compare, vec_cond_expr;
5942   tree new_temp;
5943   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
5944   enum machine_mode vec_mode;
5945   tree def;
5946   enum vect_def_type dt;
5947   int nunits = TYPE_VECTOR_SUBPARTS (vectype);
5948   int ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits;
5949
5950   gcc_assert (ncopies >= 1);
5951   if (ncopies > 1)
5952     return false; /* FORNOW */
5953
5954   if (!STMT_VINFO_RELEVANT_P (stmt_info))
5955     return false;
5956
5957   if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_loop_def)
5958     return false;
5959
5960   /* FORNOW: SLP not supported.  */
5961   if (STMT_SLP_TYPE (stmt_info))
5962     return false;
5963
5964   /* FORNOW: not yet supported.  */
5965   if (STMT_VINFO_LIVE_P (stmt_info))
5966     {
5967       if (vect_print_dump_info (REPORT_DETAILS))
5968         fprintf (vect_dump, "value used after loop.");
5969       return false;
5970     }
5971
5972   /* Is vectorizable conditional operation?  */
5973   if (TREE_CODE (stmt) != GIMPLE_MODIFY_STMT)
5974     return false;
5975
5976   op = GIMPLE_STMT_OPERAND (stmt, 1);
5977
5978   if (TREE_CODE (op) != COND_EXPR)
5979     return false;
5980
5981   cond_expr = TREE_OPERAND (op, 0);
5982   then_clause = TREE_OPERAND (op, 1);
5983   else_clause = TREE_OPERAND (op, 2);
5984
5985   if (!vect_is_simple_cond (cond_expr, loop_vinfo))
5986     return false;
5987
5988   /* We do not handle two different vector types for the condition
5989      and the values.  */
5990   if (TREE_TYPE (TREE_OPERAND (cond_expr, 0)) != TREE_TYPE (vectype))
5991     return false;
5992
5993   if (TREE_CODE (then_clause) == SSA_NAME)
5994     {
5995       tree then_def_stmt = SSA_NAME_DEF_STMT (then_clause);
5996       if (!vect_is_simple_use (then_clause, loop_vinfo, 
5997                                &then_def_stmt, &def, &dt))
5998         return false;
5999     }
6000   else if (TREE_CODE (then_clause) != INTEGER_CST 
6001            && TREE_CODE (then_clause) != REAL_CST
6002            && TREE_CODE (then_clause) != FIXED_CST)
6003     return false;
6004
6005   if (TREE_CODE (else_clause) == SSA_NAME)
6006     {
6007       tree else_def_stmt = SSA_NAME_DEF_STMT (else_clause);
6008       if (!vect_is_simple_use (else_clause, loop_vinfo, 
6009                                &else_def_stmt, &def, &dt))
6010         return false;
6011     }
6012   else if (TREE_CODE (else_clause) != INTEGER_CST 
6013            && TREE_CODE (else_clause) != REAL_CST
6014            && TREE_CODE (else_clause) != FIXED_CST)
6015     return false;
6016
6017
6018   vec_mode = TYPE_MODE (vectype);
6019
6020   if (!vec_stmt) 
6021     {
6022       STMT_VINFO_TYPE (stmt_info) = condition_vec_info_type;
6023       return expand_vec_cond_expr_p (op, vec_mode);
6024     }
6025
6026   /* Transform */
6027
6028   /* Handle def.  */
6029   scalar_dest = GIMPLE_STMT_OPERAND (stmt, 0);
6030   vec_dest = vect_create_destination_var (scalar_dest, vectype);
6031
6032   /* Handle cond expr.  */
6033   vec_cond_lhs = 
6034     vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 0), stmt, NULL);
6035   vec_cond_rhs = 
6036     vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 1), stmt, NULL);
6037   vec_then_clause = vect_get_vec_def_for_operand (then_clause, stmt, NULL);
6038   vec_else_clause = vect_get_vec_def_for_operand (else_clause, stmt, NULL);
6039
6040   /* Arguments are ready. create the new vector stmt.  */
6041   vec_compare = build2 (TREE_CODE (cond_expr), vectype, 
6042                         vec_cond_lhs, vec_cond_rhs);
6043   vec_cond_expr = build3 (VEC_COND_EXPR, vectype, 
6044                           vec_compare, vec_then_clause, vec_else_clause);
6045
6046   *vec_stmt = build_gimple_modify_stmt (vec_dest, vec_cond_expr);
6047   new_temp = make_ssa_name (vec_dest, *vec_stmt);
6048   GIMPLE_STMT_OPERAND (*vec_stmt, 0) = new_temp;
6049   vect_finish_stmt_generation (stmt, *vec_stmt, bsi);
6050   
6051   return true;
6052 }
6053
6054
6055 /* Function vect_transform_stmt.
6056
6057    Create a vectorized stmt to replace STMT, and insert it at BSI.  */
6058
6059 static bool
6060 vect_transform_stmt (tree stmt, block_stmt_iterator *bsi, bool *strided_store, 
6061                      slp_tree slp_node)
6062 {
6063   bool is_store = false;
6064   tree vec_stmt = NULL_TREE;
6065   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
6066   tree orig_stmt_in_pattern;
6067   bool done;
6068
6069   switch (STMT_VINFO_TYPE (stmt_info))
6070     {
6071     case type_demotion_vec_info_type:
6072       gcc_assert (!slp_node);
6073       done = vectorizable_type_demotion (stmt, bsi, &vec_stmt);
6074       gcc_assert (done);
6075       break;
6076
6077     case type_promotion_vec_info_type:
6078       gcc_assert (!slp_node);
6079       done = vectorizable_type_promotion (stmt, bsi, &vec_stmt);
6080       gcc_assert (done);
6081       break;
6082
6083     case type_conversion_vec_info_type:
6084       done = vectorizable_conversion (stmt, bsi, &vec_stmt, slp_node);
6085       gcc_assert (done);
6086       break;
6087
6088     case induc_vec_info_type:
6089       gcc_assert (!slp_node);
6090       done = vectorizable_induction (stmt, bsi, &vec_stmt);
6091       gcc_assert (done);
6092       break;
6093
6094     case op_vec_info_type:
6095       done = vectorizable_operation (stmt, bsi, &vec_stmt, slp_node);
6096       gcc_assert (done);
6097       break;
6098
6099     case assignment_vec_info_type:
6100       done = vectorizable_assignment (stmt, bsi, &vec_stmt, slp_node);
6101       gcc_assert (done);
6102       break;
6103
6104     case load_vec_info_type:
6105       done = vectorizable_load (stmt, bsi, &vec_stmt, slp_node);
6106       gcc_assert (done);
6107       break;
6108
6109     case store_vec_info_type:
6110       done = vectorizable_store (stmt, bsi, &vec_stmt, slp_node);
6111       gcc_assert (done);
6112       if (STMT_VINFO_STRIDED_ACCESS (stmt_info))
6113         {
6114           /* In case of interleaving, the whole chain is vectorized when the
6115              last store in the chain is reached. Store stmts before the last
6116              one are skipped, and there vec_stmt_info shouldn't be freed
6117              meanwhile.  */
6118           *strided_store = true;
6119           if (STMT_VINFO_VEC_STMT (stmt_info))
6120             is_store = true;
6121           }
6122       else
6123         is_store = true;
6124       break;
6125
6126     case condition_vec_info_type:
6127       gcc_assert (!slp_node);
6128       done = vectorizable_condition (stmt, bsi, &vec_stmt);
6129       gcc_assert (done);
6130       break;
6131
6132     case call_vec_info_type:
6133       gcc_assert (!slp_node);
6134       done = vectorizable_call (stmt, bsi, &vec_stmt);
6135       break;
6136
6137     case reduc_vec_info_type:
6138       gcc_assert (!slp_node);
6139       done = vectorizable_reduction (stmt, bsi, &vec_stmt);
6140       gcc_assert (done);
6141       break;
6142
6143     default:
6144       if (!STMT_VINFO_LIVE_P (stmt_info))
6145         {
6146           if (vect_print_dump_info (REPORT_DETAILS))
6147             fprintf (vect_dump, "stmt not supported.");
6148           gcc_unreachable ();
6149         }
6150     }
6151
6152   if (STMT_VINFO_LIVE_P (stmt_info)
6153       && STMT_VINFO_TYPE (stmt_info) != reduc_vec_info_type)
6154     {
6155       done = vectorizable_live_operation (stmt, bsi, &vec_stmt);
6156       gcc_assert (done);
6157     }
6158
6159   if (vec_stmt)
6160     {
6161       STMT_VINFO_VEC_STMT (stmt_info) = vec_stmt;
6162       orig_stmt_in_pattern = STMT_VINFO_RELATED_STMT (stmt_info);
6163       if (orig_stmt_in_pattern)
6164         {
6165           stmt_vec_info stmt_vinfo = vinfo_for_stmt (orig_stmt_in_pattern);
6166           /* STMT was inserted by the vectorizer to replace a computation idiom.
6167              ORIG_STMT_IN_PATTERN is a stmt in the original sequence that 
6168              computed this idiom.  We need to record a pointer to VEC_STMT in 
6169              the stmt_info of ORIG_STMT_IN_PATTERN.  See more details in the 
6170              documentation of vect_pattern_recog.  */
6171           if (STMT_VINFO_IN_PATTERN_P (stmt_vinfo))
6172             {
6173               gcc_assert (STMT_VINFO_RELATED_STMT (stmt_vinfo) == stmt);
6174               STMT_VINFO_VEC_STMT (stmt_vinfo) = vec_stmt;
6175             }
6176         }
6177     }
6178
6179   return is_store; 
6180 }
6181
6182
6183 /* This function builds ni_name = number of iterations loop executes
6184    on the loop preheader.  */
6185
6186 static tree
6187 vect_build_loop_niters (loop_vec_info loop_vinfo)
6188 {
6189   tree ni_name, stmt, var;
6190   edge pe;
6191   struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
6192   tree ni = unshare_expr (LOOP_VINFO_NITERS (loop_vinfo));
6193
6194   var = create_tmp_var (TREE_TYPE (ni), "niters");
6195   add_referenced_var (var);
6196   ni_name = force_gimple_operand (ni, &stmt, false, var);
6197
6198   pe = loop_preheader_edge (loop);
6199   if (stmt)
6200     {
6201       basic_block new_bb = bsi_insert_on_edge_immediate (pe, stmt);
6202       gcc_assert (!new_bb);
6203     }
6204       
6205   return ni_name;
6206 }
6207
6208
6209 /* This function generates the following statements:
6210
6211  ni_name = number of iterations loop executes
6212  ratio = ni_name / vf
6213  ratio_mult_vf_name = ratio * vf
6214
6215  and places them at the loop preheader edge.  */
6216
6217 static void 
6218 vect_generate_tmps_on_preheader (loop_vec_info loop_vinfo, 
6219                                  tree *ni_name_ptr,
6220                                  tree *ratio_mult_vf_name_ptr, 
6221                                  tree *ratio_name_ptr)
6222 {
6223
6224   edge pe;
6225   basic_block new_bb;
6226   tree stmt, ni_name;
6227   tree var;
6228   tree ratio_name;
6229   tree ratio_mult_vf_name;
6230   struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
6231   tree ni = LOOP_VINFO_NITERS (loop_vinfo);
6232   int vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
6233   tree log_vf;
6234
6235   pe = loop_preheader_edge (loop);
6236
6237   /* Generate temporary variable that contains 
6238      number of iterations loop executes.  */
6239
6240   ni_name = vect_build_loop_niters (loop_vinfo);
6241   log_vf = build_int_cst (TREE_TYPE (ni), exact_log2 (vf));
6242
6243   /* Create: ratio = ni >> log2(vf) */
6244
6245   ratio_name = fold_build2 (RSHIFT_EXPR, TREE_TYPE (ni_name), ni_name, log_vf);
6246   if (!is_gimple_val (ratio_name))
6247     {
6248       var = create_tmp_var (TREE_TYPE (ni), "bnd");
6249       add_referenced_var (var);
6250
6251       ratio_name = force_gimple_operand (ratio_name, &stmt, true, var);
6252       pe = loop_preheader_edge (loop);
6253       new_bb = bsi_insert_on_edge_immediate (pe, stmt);
6254       gcc_assert (!new_bb);
6255     }
6256        
6257   /* Create: ratio_mult_vf = ratio << log2 (vf).  */
6258
6259   ratio_mult_vf_name = fold_build2 (LSHIFT_EXPR, TREE_TYPE (ratio_name),
6260                                     ratio_name, log_vf);
6261   if (!is_gimple_val (ratio_mult_vf_name))
6262     {
6263       var = create_tmp_var (TREE_TYPE (ni), "ratio_mult_vf");
6264       add_referenced_var (var);
6265
6266       ratio_mult_vf_name = force_gimple_operand (ratio_mult_vf_name, &stmt,
6267                                                  true, var);
6268       pe = loop_preheader_edge (loop);
6269       new_bb = bsi_insert_on_edge_immediate (pe, stmt);
6270       gcc_assert (!new_bb);
6271     }
6272
6273   *ni_name_ptr = ni_name;
6274   *ratio_mult_vf_name_ptr = ratio_mult_vf_name;
6275   *ratio_name_ptr = ratio_name;
6276     
6277   return;  
6278 }
6279
6280
6281 /*   Function vect_update_ivs_after_vectorizer.
6282
6283      "Advance" the induction variables of LOOP to the value they should take
6284      after the execution of LOOP.  This is currently necessary because the
6285      vectorizer does not handle induction variables that are used after the
6286      loop.  Such a situation occurs when the last iterations of LOOP are
6287      peeled, because:
6288      1. We introduced new uses after LOOP for IVs that were not originally used
6289         after LOOP: the IVs of LOOP are now used by an epilog loop.
6290      2. LOOP is going to be vectorized; this means that it will iterate N/VF
6291         times, whereas the loop IVs should be bumped N times.
6292
6293      Input:
6294      - LOOP - a loop that is going to be vectorized. The last few iterations
6295               of LOOP were peeled.
6296      - NITERS - the number of iterations that LOOP executes (before it is
6297                 vectorized). i.e, the number of times the ivs should be bumped.
6298      - UPDATE_E - a successor edge of LOOP->exit that is on the (only) path
6299                   coming out from LOOP on which there are uses of the LOOP ivs
6300                   (this is the path from LOOP->exit to epilog_loop->preheader).
6301
6302                   The new definitions of the ivs are placed in LOOP->exit.
6303                   The phi args associated with the edge UPDATE_E in the bb
6304                   UPDATE_E->dest are updated accordingly.
6305
6306      Assumption 1: Like the rest of the vectorizer, this function assumes
6307      a single loop exit that has a single predecessor.
6308
6309      Assumption 2: The phi nodes in the LOOP header and in update_bb are
6310      organized in the same order.
6311
6312      Assumption 3: The access function of the ivs is simple enough (see
6313      vect_can_advance_ivs_p).  This assumption will be relaxed in the future.
6314
6315      Assumption 4: Exactly one of the successors of LOOP exit-bb is on a path
6316      coming out of LOOP on which the ivs of LOOP are used (this is the path 
6317      that leads to the epilog loop; other paths skip the epilog loop).  This
6318      path starts with the edge UPDATE_E, and its destination (denoted update_bb)
6319      needs to have its phis updated.
6320  */
6321
6322 static void
6323 vect_update_ivs_after_vectorizer (loop_vec_info loop_vinfo, tree niters, 
6324                                   edge update_e)
6325 {
6326   struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
6327   basic_block exit_bb = single_exit (loop)->dest;
6328   tree phi, phi1;
6329   basic_block update_bb = update_e->dest;
6330
6331   /* gcc_assert (vect_can_advance_ivs_p (loop_vinfo)); */
6332
6333   /* Make sure there exists a single-predecessor exit bb:  */
6334   gcc_assert (single_pred_p (exit_bb));
6335
6336   for (phi = phi_nodes (loop->header), phi1 = phi_nodes (update_bb); 
6337        phi && phi1; 
6338        phi = PHI_CHAIN (phi), phi1 = PHI_CHAIN (phi1))
6339     {
6340       tree access_fn = NULL;
6341       tree evolution_part;
6342       tree init_expr;
6343       tree step_expr;
6344       tree var, ni, ni_name;
6345       block_stmt_iterator last_bsi;
6346
6347       if (vect_print_dump_info (REPORT_DETAILS))
6348         {
6349           fprintf (vect_dump, "vect_update_ivs_after_vectorizer: phi: ");
6350           print_generic_expr (vect_dump, phi, TDF_SLIM);
6351         }
6352
6353       /* Skip virtual phi's.  */
6354       if (!is_gimple_reg (SSA_NAME_VAR (PHI_RESULT (phi))))
6355         {
6356           if (vect_print_dump_info (REPORT_DETAILS))
6357             fprintf (vect_dump, "virtual phi. skip.");
6358           continue;
6359         }
6360
6361       /* Skip reduction phis.  */
6362       if (STMT_VINFO_DEF_TYPE (vinfo_for_stmt (phi)) == vect_reduction_def)
6363         { 
6364           if (vect_print_dump_info (REPORT_DETAILS))
6365             fprintf (vect_dump, "reduc phi. skip.");
6366           continue;
6367         } 
6368
6369       access_fn = analyze_scalar_evolution (loop, PHI_RESULT (phi)); 
6370       gcc_assert (access_fn);
6371       evolution_part =
6372          unshare_expr (evolution_part_in_loop_num (access_fn, loop->num));
6373       gcc_assert (evolution_part != NULL_TREE);
6374       
6375       /* FORNOW: We do not support IVs whose evolution function is a polynomial
6376          of degree >= 2 or exponential.  */
6377       gcc_assert (!tree_is_chrec (evolution_part));
6378
6379       step_expr = evolution_part;
6380       init_expr = unshare_expr (initial_condition_in_loop_num (access_fn, 
6381                                                                loop->num));
6382
6383       if (POINTER_TYPE_P (TREE_TYPE (init_expr)))
6384         ni = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (init_expr), 
6385                           init_expr, 
6386                           fold_convert (sizetype, 
6387                                         fold_build2 (MULT_EXPR, TREE_TYPE (niters),
6388                                                      niters, step_expr)));
6389       else
6390         ni = fold_build2 (PLUS_EXPR, TREE_TYPE (init_expr),
6391                           fold_build2 (MULT_EXPR, TREE_TYPE (init_expr),
6392                                        fold_convert (TREE_TYPE (init_expr),
6393                                                      niters),
6394                                        step_expr),
6395                           init_expr);
6396
6397
6398
6399       var = create_tmp_var (TREE_TYPE (init_expr), "tmp");
6400       add_referenced_var (var);
6401
6402       last_bsi = bsi_last (exit_bb);
6403       ni_name = force_gimple_operand_bsi (&last_bsi, ni, false, var,
6404                                           true, BSI_SAME_STMT);
6405       
6406       /* Fix phi expressions in the successor bb.  */
6407       SET_PHI_ARG_DEF (phi1, update_e->dest_idx, ni_name);
6408     }
6409 }
6410
6411
6412 /* Function vect_do_peeling_for_loop_bound
6413
6414    Peel the last iterations of the loop represented by LOOP_VINFO.
6415    The peeled iterations form a new epilog loop.  Given that the loop now 
6416    iterates NITERS times, the new epilog loop iterates
6417    NITERS % VECTORIZATION_FACTOR times.
6418    
6419    The original loop will later be made to iterate 
6420    NITERS / VECTORIZATION_FACTOR times (this value is placed into RATIO).  */
6421
6422 static void 
6423 vect_do_peeling_for_loop_bound (loop_vec_info loop_vinfo, tree *ratio)
6424 {
6425   tree ni_name, ratio_mult_vf_name;
6426   struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
6427   struct loop *new_loop;
6428   edge update_e;
6429   basic_block preheader;
6430   int loop_num;
6431   unsigned int th;
6432   int min_scalar_loop_bound;
6433   int min_profitable_iters;
6434
6435   if (vect_print_dump_info (REPORT_DETAILS))
6436     fprintf (vect_dump, "=== vect_do_peeling_for_loop_bound ===");
6437
6438   initialize_original_copy_tables ();
6439
6440   /* Generate the following variables on the preheader of original loop:
6441          
6442      ni_name = number of iteration the original loop executes
6443      ratio = ni_name / vf
6444      ratio_mult_vf_name = ratio * vf  */
6445   vect_generate_tmps_on_preheader (loop_vinfo, &ni_name,
6446                                    &ratio_mult_vf_name, ratio);
6447
6448   loop_num  = loop->num; 
6449
6450   /* Analyze cost to set threshhold for vectorized loop.  */
6451   min_profitable_iters = LOOP_VINFO_COST_MODEL_MIN_ITERS (loop_vinfo);
6452   min_scalar_loop_bound = ((PARAM_VALUE (PARAM_MIN_VECT_LOOP_BOUND)
6453                             * LOOP_VINFO_VECT_FACTOR (loop_vinfo)) - 1);
6454
6455   /* Use the cost model only if it is more conservative than user specified
6456      threshold.  */
6457
6458   th = (unsigned) min_scalar_loop_bound;
6459   if (min_profitable_iters
6460       && (!min_scalar_loop_bound
6461           || min_profitable_iters > min_scalar_loop_bound))
6462     th = (unsigned) min_profitable_iters;
6463
6464   if (((LOOP_PEELING_FOR_ALIGNMENT (loop_vinfo) < 0)
6465       || !LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo))
6466       && vect_print_dump_info (REPORT_DETAILS))
6467     fprintf (vect_dump, "vectorization may not be profitable.");
6468
6469   new_loop = slpeel_tree_peel_loop_to_edge (loop, single_exit (loop),
6470                                             ratio_mult_vf_name, ni_name, false,
6471                                             th);
6472   gcc_assert (new_loop);
6473   gcc_assert (loop_num == loop->num);
6474 #ifdef ENABLE_CHECKING
6475   slpeel_verify_cfg_after_peeling (loop, new_loop);
6476 #endif
6477
6478   /* A guard that controls whether the new_loop is to be executed or skipped
6479      is placed in LOOP->exit.  LOOP->exit therefore has two successors - one
6480      is the preheader of NEW_LOOP, where the IVs from LOOP are used.  The other
6481      is a bb after NEW_LOOP, where these IVs are not used.  Find the edge that
6482      is on the path where the LOOP IVs are used and need to be updated.  */
6483
6484   preheader = loop_preheader_edge (new_loop)->src;
6485   if (EDGE_PRED (preheader, 0)->src == single_exit (loop)->dest)
6486     update_e = EDGE_PRED (preheader, 0);
6487   else
6488     update_e = EDGE_PRED (preheader, 1);
6489
6490   /* Update IVs of original loop as if they were advanced 
6491      by ratio_mult_vf_name steps.  */
6492   vect_update_ivs_after_vectorizer (loop_vinfo, ratio_mult_vf_name, update_e); 
6493
6494   /* After peeling we have to reset scalar evolution analyzer.  */
6495   scev_reset ();
6496
6497   free_original_copy_tables ();
6498 }
6499
6500
6501 /* Function vect_gen_niters_for_prolog_loop
6502
6503    Set the number of iterations for the loop represented by LOOP_VINFO
6504    to the minimum between LOOP_NITERS (the original iteration count of the loop)
6505    and the misalignment of DR - the data reference recorded in
6506    LOOP_VINFO_UNALIGNED_DR (LOOP_VINFO).  As a result, after the execution of 
6507    this loop, the data reference DR will refer to an aligned location.
6508
6509    The following computation is generated:
6510
6511    If the misalignment of DR is known at compile time:
6512      addr_mis = int mis = DR_MISALIGNMENT (dr);
6513    Else, compute address misalignment in bytes:
6514      addr_mis = addr & (vectype_size - 1)
6515
6516    prolog_niters = min ( LOOP_NITERS , (VF - addr_mis/elem_size)&(VF-1) )
6517    
6518    (elem_size = element type size; an element is the scalar element 
6519         whose type is the inner type of the vectype)  
6520
6521    For interleaving,
6522
6523    prolog_niters = min ( LOOP_NITERS , 
6524                         (VF/group_size - addr_mis/elem_size)&(VF/group_size-1) )
6525          where group_size is the size of the interleaved group.
6526
6527    The above formulas assume that VF == number of elements in the vector. This
6528    may not hold when there are multiple-types in the loop.
6529    In this case, for some data-references in the loop the VF does not represent
6530    the number of elements that fit in the vector.  Therefore, instead of VF we
6531    use TYPE_VECTOR_SUBPARTS.  */
6532
6533 static tree 
6534 vect_gen_niters_for_prolog_loop (loop_vec_info loop_vinfo, tree loop_niters)
6535 {
6536   struct data_reference *dr = LOOP_VINFO_UNALIGNED_DR (loop_vinfo);
6537   struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
6538   tree var, stmt;
6539   tree iters, iters_name;
6540   edge pe;
6541   basic_block new_bb;
6542   tree dr_stmt = DR_STMT (dr);
6543   stmt_vec_info stmt_info = vinfo_for_stmt (dr_stmt);
6544   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
6545   int vectype_align = TYPE_ALIGN (vectype) / BITS_PER_UNIT;
6546   tree niters_type = TREE_TYPE (loop_niters);
6547   int group_size = 1;
6548   int element_size = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (DR_REF (dr))));
6549   int nelements = TYPE_VECTOR_SUBPARTS (vectype);
6550
6551   if (STMT_VINFO_STRIDED_ACCESS (stmt_info))
6552     {
6553       /* For interleaved access element size must be multiplied by the size of
6554          the interleaved group.  */
6555       group_size = DR_GROUP_SIZE (vinfo_for_stmt (
6556                                                DR_GROUP_FIRST_DR (stmt_info)));
6557       element_size *= group_size;
6558     }
6559
6560   pe = loop_preheader_edge (loop); 
6561
6562   if (LOOP_PEELING_FOR_ALIGNMENT (loop_vinfo) > 0)
6563     {
6564       int byte_misalign = LOOP_PEELING_FOR_ALIGNMENT (loop_vinfo);
6565       int elem_misalign = byte_misalign / element_size;
6566
6567       if (vect_print_dump_info (REPORT_DETAILS))
6568         fprintf (vect_dump, "known alignment = %d.", byte_misalign);
6569       iters = build_int_cst (niters_type, 
6570                              (nelements - elem_misalign)&(nelements/group_size-1));
6571     }
6572   else
6573     {
6574       tree new_stmts = NULL_TREE;
6575       tree start_addr = vect_create_addr_base_for_vector_ref (dr_stmt, 
6576                                                 &new_stmts, NULL_TREE, loop);
6577       tree ptr_type = TREE_TYPE (start_addr);
6578       tree size = TYPE_SIZE (ptr_type);
6579       tree type = lang_hooks.types.type_for_size (tree_low_cst (size, 1), 1);
6580       tree vectype_size_minus_1 = build_int_cst (type, vectype_align - 1);
6581       tree elem_size_log =
6582         build_int_cst (type, exact_log2 (vectype_align/nelements));
6583       tree nelements_minus_1 = build_int_cst (type, nelements - 1);
6584       tree nelements_tree = build_int_cst (type, nelements);
6585       tree byte_misalign;
6586       tree elem_misalign;
6587
6588       new_bb = bsi_insert_on_edge_immediate (pe, new_stmts);
6589       gcc_assert (!new_bb);
6590   
6591       /* Create:  byte_misalign = addr & (vectype_size - 1)  */
6592       byte_misalign = 
6593         fold_build2 (BIT_AND_EXPR, type, fold_convert (type, start_addr), vectype_size_minus_1);
6594   
6595       /* Create:  elem_misalign = byte_misalign / element_size  */
6596       elem_misalign =
6597         fold_build2 (RSHIFT_EXPR, type, byte_misalign, elem_size_log);
6598
6599       /* Create:  (niters_type) (nelements - elem_misalign)&(nelements - 1)  */
6600       iters = fold_build2 (MINUS_EXPR, type, nelements_tree, elem_misalign);
6601       iters = fold_build2 (BIT_AND_EXPR, type, iters, nelements_minus_1);
6602       iters = fold_convert (niters_type, iters);
6603     }
6604
6605   /* Create:  prolog_loop_niters = min (iters, loop_niters) */
6606   /* If the loop bound is known at compile time we already verified that it is
6607      greater than vf; since the misalignment ('iters') is at most vf, there's
6608      no need to generate the MIN_EXPR in this case.  */
6609   if (TREE_CODE (loop_niters) != INTEGER_CST)
6610     iters = fold_build2 (MIN_EXPR, niters_type, iters, loop_niters);
6611
6612   if (vect_print_dump_info (REPORT_DETAILS))
6613     {
6614       fprintf (vect_dump, "niters for prolog loop: ");
6615       print_generic_expr (vect_dump, iters, TDF_SLIM);
6616     }
6617
6618   var = create_tmp_var (niters_type, "prolog_loop_niters");
6619   add_referenced_var (var);
6620   iters_name = force_gimple_operand (iters, &stmt, false, var);
6621
6622   /* Insert stmt on loop preheader edge.  */
6623   if (stmt)
6624     {
6625       basic_block new_bb = bsi_insert_on_edge_immediate (pe, stmt);
6626       gcc_assert (!new_bb);
6627     }
6628
6629   return iters_name; 
6630 }
6631
6632
6633 /* Function vect_update_init_of_dr
6634
6635    NITERS iterations were peeled from LOOP.  DR represents a data reference
6636    in LOOP.  This function updates the information recorded in DR to
6637    account for the fact that the first NITERS iterations had already been 
6638    executed.  Specifically, it updates the OFFSET field of DR.  */
6639
6640 static void
6641 vect_update_init_of_dr (struct data_reference *dr, tree niters)
6642 {
6643   tree offset = DR_OFFSET (dr);
6644       
6645   niters = fold_build2 (MULT_EXPR, TREE_TYPE (niters), niters, DR_STEP (dr));
6646   offset = fold_build2 (PLUS_EXPR, TREE_TYPE (offset), offset, niters);
6647   DR_OFFSET (dr) = offset;
6648 }
6649
6650
6651 /* Function vect_update_inits_of_drs
6652
6653    NITERS iterations were peeled from the loop represented by LOOP_VINFO.  
6654    This function updates the information recorded for the data references in 
6655    the loop to account for the fact that the first NITERS iterations had 
6656    already been executed.  Specifically, it updates the initial_condition of
6657    the access_function of all the data_references in the loop.  */
6658
6659 static void
6660 vect_update_inits_of_drs (loop_vec_info loop_vinfo, tree niters)
6661 {
6662   unsigned int i;
6663   VEC (data_reference_p, heap) *datarefs = LOOP_VINFO_DATAREFS (loop_vinfo);
6664   struct data_reference *dr;
6665
6666   if (vect_print_dump_info (REPORT_DETAILS))
6667     fprintf (vect_dump, "=== vect_update_inits_of_dr ===");
6668
6669   for (i = 0; VEC_iterate (data_reference_p, datarefs, i, dr); i++)
6670     vect_update_init_of_dr (dr, niters);
6671 }
6672
6673
6674 /* Function vect_do_peeling_for_alignment
6675
6676    Peel the first 'niters' iterations of the loop represented by LOOP_VINFO.
6677    'niters' is set to the misalignment of one of the data references in the
6678    loop, thereby forcing it to refer to an aligned location at the beginning
6679    of the execution of this loop.  The data reference for which we are
6680    peeling is recorded in LOOP_VINFO_UNALIGNED_DR.  */
6681
6682 static void
6683 vect_do_peeling_for_alignment (loop_vec_info loop_vinfo)
6684 {
6685   struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
6686   tree niters_of_prolog_loop, ni_name;
6687   tree n_iters;
6688   struct loop *new_loop;
6689
6690   if (vect_print_dump_info (REPORT_DETAILS))
6691     fprintf (vect_dump, "=== vect_do_peeling_for_alignment ===");
6692
6693   initialize_original_copy_tables ();
6694
6695   ni_name = vect_build_loop_niters (loop_vinfo);
6696   niters_of_prolog_loop = vect_gen_niters_for_prolog_loop (loop_vinfo, ni_name);
6697   
6698   /* Peel the prolog loop and iterate it niters_of_prolog_loop.  */
6699   new_loop = 
6700         slpeel_tree_peel_loop_to_edge (loop, loop_preheader_edge (loop), 
6701                                        niters_of_prolog_loop, ni_name, true, 0); 
6702   gcc_assert (new_loop);
6703 #ifdef ENABLE_CHECKING
6704   slpeel_verify_cfg_after_peeling (new_loop, loop);
6705 #endif
6706
6707   /* Update number of times loop executes.  */
6708   n_iters = LOOP_VINFO_NITERS (loop_vinfo);
6709   LOOP_VINFO_NITERS (loop_vinfo) = fold_build2 (MINUS_EXPR,
6710                 TREE_TYPE (n_iters), n_iters, niters_of_prolog_loop);
6711
6712   /* Update the init conditions of the access functions of all data refs.  */
6713   vect_update_inits_of_drs (loop_vinfo, niters_of_prolog_loop);
6714
6715   /* After peeling we have to reset scalar evolution analyzer.  */
6716   scev_reset ();
6717
6718   free_original_copy_tables ();
6719 }
6720
6721
6722 /* Function vect_create_cond_for_align_checks.
6723
6724    Create a conditional expression that represents the alignment checks for
6725    all of data references (array element references) whose alignment must be
6726    checked at runtime.
6727
6728    Input:
6729    LOOP_VINFO - two fields of the loop information are used.
6730                 LOOP_VINFO_PTR_MASK is the mask used to check the alignment.
6731                 LOOP_VINFO_MAY_MISALIGN_STMTS contains the refs to be checked.
6732
6733    Output:
6734    COND_EXPR_STMT_LIST - statements needed to construct the conditional
6735                          expression.
6736    The returned value is the conditional expression to be used in the if
6737    statement that controls which version of the loop gets executed at runtime.
6738
6739    The algorithm makes two assumptions:
6740      1) The number of bytes "n" in a vector is a power of 2.
6741      2) An address "a" is aligned if a%n is zero and that this
6742         test can be done as a&(n-1) == 0.  For example, for 16
6743         byte vectors the test is a&0xf == 0.  */
6744
6745 static tree
6746 vect_create_cond_for_align_checks (loop_vec_info loop_vinfo,
6747                                    tree *cond_expr_stmt_list)
6748 {
6749   struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
6750   VEC(tree,heap) *may_misalign_stmts
6751     = LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo);
6752   tree ref_stmt, tmp;
6753   int mask = LOOP_VINFO_PTR_MASK (loop_vinfo);
6754   tree mask_cst;
6755   unsigned int i;
6756   tree psize;
6757   tree int_ptrsize_type;
6758   char tmp_name[20];
6759   tree or_tmp_name = NULL_TREE;
6760   tree and_tmp, and_tmp_name, and_stmt;
6761   tree ptrsize_zero;
6762
6763   /* Check that mask is one less than a power of 2, i.e., mask is
6764      all zeros followed by all ones.  */
6765   gcc_assert ((mask != 0) && ((mask & (mask+1)) == 0));
6766
6767   /* CHECKME: what is the best integer or unsigned type to use to hold a
6768      cast from a pointer value?  */
6769   psize = TYPE_SIZE (ptr_type_node);
6770   int_ptrsize_type
6771     = lang_hooks.types.type_for_size (tree_low_cst (psize, 1), 0);
6772
6773   /* Create expression (mask & (dr_1 || ... || dr_n)) where dr_i is the address
6774      of the first vector of the i'th data reference. */
6775
6776   for (i = 0; VEC_iterate (tree, may_misalign_stmts, i, ref_stmt); i++)
6777     {
6778       tree new_stmt_list = NULL_TREE;   
6779       tree addr_base;
6780       tree addr_tmp, addr_tmp_name, addr_stmt;
6781       tree or_tmp, new_or_tmp_name, or_stmt;
6782
6783       /* create: addr_tmp = (int)(address_of_first_vector) */
6784       addr_base = vect_create_addr_base_for_vector_ref (ref_stmt, 
6785                                         &new_stmt_list, NULL_TREE, loop);
6786
6787       if (new_stmt_list != NULL_TREE)
6788         append_to_statement_list_force (new_stmt_list, cond_expr_stmt_list);
6789
6790       sprintf (tmp_name, "%s%d", "addr2int", i);
6791       addr_tmp = create_tmp_var (int_ptrsize_type, tmp_name);
6792       add_referenced_var (addr_tmp);
6793       addr_tmp_name = make_ssa_name (addr_tmp, NULL_TREE);
6794       addr_stmt = fold_convert (int_ptrsize_type, addr_base);
6795       addr_stmt = build_gimple_modify_stmt (addr_tmp_name, addr_stmt);
6796       SSA_NAME_DEF_STMT (addr_tmp_name) = addr_stmt;
6797       append_to_statement_list_force (addr_stmt, cond_expr_stmt_list);
6798
6799       /* The addresses are OR together.  */
6800
6801       if (or_tmp_name != NULL_TREE)
6802         {
6803           /* create: or_tmp = or_tmp | addr_tmp */
6804           sprintf (tmp_name, "%s%d", "orptrs", i);
6805           or_tmp = create_tmp_var (int_ptrsize_type, tmp_name);
6806           add_referenced_var (or_tmp);
6807           new_or_tmp_name = make_ssa_name (or_tmp, NULL_TREE);
6808           tmp = build2 (BIT_IOR_EXPR, int_ptrsize_type,
6809                         or_tmp_name, addr_tmp_name);
6810           or_stmt = build_gimple_modify_stmt (new_or_tmp_name, tmp);
6811           SSA_NAME_DEF_STMT (new_or_tmp_name) = or_stmt;
6812           append_to_statement_list_force (or_stmt, cond_expr_stmt_list);
6813           or_tmp_name = new_or_tmp_name;
6814         }
6815       else
6816         or_tmp_name = addr_tmp_name;
6817
6818     } /* end for i */
6819
6820   mask_cst = build_int_cst (int_ptrsize_type, mask);
6821
6822   /* create: and_tmp = or_tmp & mask  */
6823   and_tmp = create_tmp_var (int_ptrsize_type, "andmask" );
6824   add_referenced_var (and_tmp);
6825   and_tmp_name = make_ssa_name (and_tmp, NULL_TREE);
6826
6827   tmp = build2 (BIT_AND_EXPR, int_ptrsize_type, or_tmp_name, mask_cst);
6828   and_stmt = build_gimple_modify_stmt (and_tmp_name, tmp);
6829   SSA_NAME_DEF_STMT (and_tmp_name) = and_stmt;
6830   append_to_statement_list_force (and_stmt, cond_expr_stmt_list);
6831
6832   /* Make and_tmp the left operand of the conditional test against zero.
6833      if and_tmp has a nonzero bit then some address is unaligned.  */
6834   ptrsize_zero = build_int_cst (int_ptrsize_type, 0);
6835   return build2 (EQ_EXPR, boolean_type_node,
6836                  and_tmp_name, ptrsize_zero);
6837 }
6838
6839 /* Function vect_vfa_segment_size.
6840
6841    Create an expression that computes the size of segment
6842    that will be accessed for a data reference.  The functions takes into
6843    account that realignment loads may access one more vector.
6844
6845    Input:
6846      DR: The data reference.
6847      VECT_FACTOR: vectorization factor.
6848
6849    Return an expression whose value is the size of segment which will be
6850    accessed by DR.  */
6851
6852 static tree
6853 vect_vfa_segment_size (struct data_reference *dr, tree vect_factor)
6854 {
6855   tree segment_length;
6856
6857   if (vect_supportable_dr_alignment (dr) == dr_explicit_realign_optimized)
6858     {
6859       tree vector_size =
6860         build_int_cst (integer_type_node,
6861           GET_MODE_SIZE (TYPE_MODE (STMT_VINFO_VECTYPE
6862             (vinfo_for_stmt (DR_STMT (dr))))));
6863
6864       segment_length =
6865         fold_convert (sizetype,
6866           fold_build2 (PLUS_EXPR, integer_type_node,
6867             fold_build2 (MULT_EXPR, integer_type_node, DR_STEP (dr),
6868                          vect_factor),
6869             vector_size));
6870     }
6871   else
6872     {
6873       segment_length =
6874         fold_convert (sizetype,
6875           fold_build2 (MULT_EXPR, integer_type_node, DR_STEP (dr),
6876                        vect_factor));
6877     }
6878
6879     return segment_length;
6880 }
6881
6882 /* Function vect_create_cond_for_alias_checks.
6883
6884    Create a conditional expression that represents the run-time checks for
6885    overlapping of address ranges represented by a list of data references
6886    relations passed as input.
6887
6888    Input:
6889    COND_EXPR  - input conditional expression.  New conditions will be chained
6890                 with logical and operation.
6891    LOOP_VINFO - field LOOP_VINFO_MAY_ALIAS_STMTS contains the list of ddrs
6892                 to be checked.
6893
6894    Output:
6895    COND_EXPR - conditional expression.
6896    COND_EXPR_STMT_LIST - statements needed to construct the conditional
6897                          expression.
6898    The returned value is the conditional expression to be used in the if
6899    statement that controls which version of the loop gets executed at runtime.
6900 */
6901
6902 static void
6903 vect_create_cond_for_alias_checks (loop_vec_info loop_vinfo,
6904                                    tree * cond_expr,
6905                                    tree * cond_expr_stmt_list)
6906 {
6907   struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
6908   VEC (ddr_p, heap) * may_alias_ddrs =
6909     LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo);
6910   tree vect_factor =
6911     build_int_cst (integer_type_node, LOOP_VINFO_VECT_FACTOR (loop_vinfo));
6912
6913   ddr_p ddr;
6914   unsigned int i;
6915   tree part_cond_expr;
6916
6917   /* Create expression
6918      ((store_ptr_0 + store_segment_length_0) < load_ptr_0)
6919      || (load_ptr_0 + load_segment_length_0) < store_ptr_0))
6920      &&         
6921      ...
6922      &&
6923      ((store_ptr_n + store_segment_length_n) < load_ptr_n)
6924      || (load_ptr_n + load_segment_length_n) < store_ptr_n))  */
6925
6926   if (VEC_empty (ddr_p, may_alias_ddrs))
6927     return;
6928
6929   for (i = 0; VEC_iterate (ddr_p, may_alias_ddrs, i, ddr); i++)
6930     {
6931       tree stmt_a = DR_STMT (DDR_A (ddr));
6932       tree stmt_b = DR_STMT (DDR_B (ddr));
6933
6934       tree addr_base_a =
6935         vect_create_addr_base_for_vector_ref (stmt_a, cond_expr_stmt_list,
6936                                               NULL_TREE, loop);
6937       tree addr_base_b =
6938         vect_create_addr_base_for_vector_ref (stmt_b, cond_expr_stmt_list,
6939                                               NULL_TREE, loop);
6940
6941       tree segment_length_a = vect_vfa_segment_size (DDR_A (ddr), vect_factor);
6942       tree segment_length_b = vect_vfa_segment_size (DDR_B (ddr), vect_factor);
6943
6944       if (vect_print_dump_info (REPORT_DR_DETAILS))
6945         {
6946           fprintf (vect_dump,
6947                    "create runtime check for data references ");
6948           print_generic_expr (vect_dump, DR_REF (DDR_A (ddr)), TDF_SLIM);
6949           fprintf (vect_dump, " and ");
6950           print_generic_expr (vect_dump, DR_REF (DDR_B (ddr)), TDF_SLIM);
6951         }
6952
6953
6954       part_cond_expr = 
6955         fold_build2 (TRUTH_OR_EXPR, boolean_type_node,
6956           fold_build2 (LT_EXPR, boolean_type_node,
6957             fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (addr_base_a),
6958               addr_base_a,
6959               segment_length_a),
6960             addr_base_b),
6961           fold_build2 (LT_EXPR, boolean_type_node,
6962             fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (addr_base_b),
6963               addr_base_b,
6964               segment_length_b),
6965             addr_base_a));
6966       
6967       if (*cond_expr)
6968         *cond_expr = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
6969                                   *cond_expr, part_cond_expr);
6970       else
6971         *cond_expr = part_cond_expr;
6972     }
6973     if (vect_print_dump_info (REPORT_VECTORIZED_LOOPS))
6974       fprintf (vect_dump, "created %u versioning for alias checks.\n",
6975                VEC_length (ddr_p, may_alias_ddrs));
6976
6977 }
6978
6979 /* Remove a group of stores (for SLP or interleaving), free their 
6980    stmt_vec_info.  */
6981
6982 static void
6983 vect_remove_stores (tree first_stmt)
6984 {
6985   stmt_ann_t ann;
6986   tree next = first_stmt;
6987   tree tmp;
6988   stmt_vec_info next_stmt_info;
6989   block_stmt_iterator next_si;
6990
6991   while (next)
6992     {
6993       /* Free the attached stmt_vec_info and remove the stmt.  */
6994       next_si = bsi_for_stmt (next);
6995       bsi_remove (&next_si, true);
6996       next_stmt_info = vinfo_for_stmt (next);
6997       ann = stmt_ann (next);
6998       tmp = DR_GROUP_NEXT_DR (next_stmt_info);
6999       free (next_stmt_info);
7000       set_stmt_info (ann, NULL);
7001       next = tmp;
7002     }
7003 }
7004
7005
7006 /* Vectorize SLP instance tree in postorder.  */
7007
7008 static bool
7009 vect_schedule_slp_instance (slp_tree node, unsigned int vec_stmts_size)
7010 {
7011   tree stmt;
7012   bool strided_store, is_store;
7013   block_stmt_iterator si;
7014   stmt_vec_info stmt_info;
7015
7016   if (!node)
7017     return false;
7018
7019   vect_schedule_slp_instance (SLP_TREE_LEFT (node), vec_stmts_size);
7020   vect_schedule_slp_instance (SLP_TREE_RIGHT (node), vec_stmts_size);
7021   
7022   stmt = VEC_index(tree, SLP_TREE_SCALAR_STMTS (node), 0);
7023   stmt_info = vinfo_for_stmt (stmt);
7024   SLP_TREE_VEC_STMTS (node) = VEC_alloc (tree, heap, vec_stmts_size);
7025   SLP_TREE_NUMBER_OF_VEC_STMTS (node) = vec_stmts_size;
7026
7027   if (vect_print_dump_info (REPORT_DETAILS))
7028     {
7029       fprintf (vect_dump, "------>vectorizing SLP node starting from: ");
7030       print_generic_expr (vect_dump, stmt, TDF_SLIM);
7031     }   
7032
7033   si = bsi_for_stmt (stmt);
7034   is_store = vect_transform_stmt (stmt, &si, &strided_store, node);
7035   if (is_store)
7036     {
7037       if (DR_GROUP_FIRST_DR (stmt_info))
7038         /* If IS_STORE is TRUE, the vectorization of the
7039            interleaving chain was completed - free all the stores in
7040            the chain.  */
7041         vect_remove_stores (DR_GROUP_FIRST_DR (stmt_info));
7042       else
7043         /* FORNOW: SLP originates only from strided stores.  */
7044         gcc_unreachable ();
7045
7046       return true;
7047     }
7048
7049   /* FORNOW: SLP originates only from strided stores.  */
7050   return false;
7051 }
7052
7053
7054 static bool
7055 vect_schedule_slp (loop_vec_info loop_vinfo, unsigned int nunits)
7056 {
7057   VEC (slp_instance, heap) *slp_instances = 
7058     LOOP_VINFO_SLP_INSTANCES (loop_vinfo);
7059   slp_instance instance;
7060   unsigned int vec_stmts_size;
7061   unsigned int group_size, i;
7062   unsigned int vectorization_factor = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
7063   bool is_store = false;
7064
7065   for (i = 0; VEC_iterate (slp_instance, slp_instances, i, instance); i++)
7066     {
7067       group_size = SLP_INSTANCE_GROUP_SIZE (instance);
7068       /* For each SLP instance calculate number of vector stmts to be created 
7069          for the scalar stmts in each node of the SLP tree. Number of vector 
7070          elements in one vector iteration is the number of scalar elements in 
7071          one scalar iteration (GROUP_SIZE) multiplied by VF divided by vector 
7072          size.  */                    
7073       vec_stmts_size = vectorization_factor * group_size / nunits;
7074                           
7075       /* Schedule the tree of INSTANCE.  */
7076       is_store = vect_schedule_slp_instance (SLP_INSTANCE_TREE (instance), 
7077                                              vec_stmts_size);
7078                      
7079       if (vect_print_dump_info (REPORT_VECTORIZED_LOOPS)
7080           || vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS))
7081         fprintf (vect_dump, "vectorizing stmts using SLP.");
7082     }
7083
7084   return is_store;
7085 }
7086
7087
7088 /* Function vect_transform_loop.
7089
7090    The analysis phase has determined that the loop is vectorizable.
7091    Vectorize the loop - created vectorized stmts to replace the scalar
7092    stmts in the loop, and update the loop exit condition.  */
7093
7094 void
7095 vect_transform_loop (loop_vec_info loop_vinfo)
7096 {
7097   struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
7098   basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo);
7099   int nbbs = loop->num_nodes;
7100   block_stmt_iterator si, next_si;
7101   int i;
7102   tree ratio = NULL;
7103   int vectorization_factor = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
7104   bool strided_store;
7105   bool slp_scheduled = false;
7106   unsigned int nunits;
7107
7108   if (vect_print_dump_info (REPORT_DETAILS))
7109     fprintf (vect_dump, "=== vec_transform_loop ===");
7110
7111   /* If the loop has data references that may or may not be aligned or/and
7112      has data reference relations whose independence was not proven then
7113      two versions of the loop need to be generated, one which is vectorized
7114      and one which isn't.  A test is then generated to control which of the
7115      loops is executed.  The test checks for the alignment of all of the
7116      data references that may or may not be aligned.  An additional
7117      sequence of runtime tests is generated for each pairs of DDRs whose
7118      independence was not proven.  The vectorized version of loop is 
7119      executed only if both alias and alignment tests are passed.  */
7120
7121   if (VEC_length (tree, LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo))
7122       || VEC_length (ddr_p, LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo)))
7123     {
7124       struct loop *nloop;
7125       tree cond_expr = NULL_TREE;
7126       tree cond_expr_stmt_list = NULL_TREE;
7127       basic_block condition_bb;
7128       block_stmt_iterator cond_exp_bsi;
7129       basic_block merge_bb;
7130       basic_block new_exit_bb;
7131       edge new_exit_e, e;
7132       tree orig_phi, new_phi, arg;
7133       unsigned prob = 4 * REG_BR_PROB_BASE / 5;
7134       tree gimplify_stmt_list;
7135
7136       if (VEC_length (tree, LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo)))
7137         cond_expr =
7138           vect_create_cond_for_align_checks (loop_vinfo, &cond_expr_stmt_list);
7139
7140       if (VEC_length (ddr_p, LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo)))
7141         vect_create_cond_for_alias_checks (loop_vinfo, &cond_expr,
7142                                                      &cond_expr_stmt_list);
7143
7144       cond_expr =
7145         fold_build2 (NE_EXPR, boolean_type_node, cond_expr, integer_zero_node);
7146       cond_expr =
7147         force_gimple_operand (cond_expr, &gimplify_stmt_list, true,
7148                               NULL_TREE);
7149       append_to_statement_list (gimplify_stmt_list, &cond_expr_stmt_list);
7150
7151       initialize_original_copy_tables ();
7152       nloop = loop_version (loop, cond_expr, &condition_bb,
7153                             prob, prob, REG_BR_PROB_BASE - prob, true);
7154       free_original_copy_tables();
7155
7156       /** Loop versioning violates an assumption we try to maintain during 
7157          vectorization - that the loop exit block has a single predecessor.
7158          After versioning, the exit block of both loop versions is the same
7159          basic block (i.e. it has two predecessors). Just in order to simplify
7160          following transformations in the vectorizer, we fix this situation
7161          here by adding a new (empty) block on the exit-edge of the loop,
7162          with the proper loop-exit phis to maintain loop-closed-form.  **/
7163       
7164       merge_bb = single_exit (loop)->dest;
7165       gcc_assert (EDGE_COUNT (merge_bb->preds) == 2);
7166       new_exit_bb = split_edge (single_exit (loop));
7167       new_exit_e = single_exit (loop);
7168       e = EDGE_SUCC (new_exit_bb, 0);
7169
7170       for (orig_phi = phi_nodes (merge_bb); orig_phi; 
7171            orig_phi = PHI_CHAIN (orig_phi))
7172         {
7173           new_phi = create_phi_node (SSA_NAME_VAR (PHI_RESULT (orig_phi)),
7174                                      new_exit_bb);
7175           arg = PHI_ARG_DEF_FROM_EDGE (orig_phi, e);
7176           add_phi_arg (new_phi, arg, new_exit_e);
7177           SET_PHI_ARG_DEF (orig_phi, e->dest_idx, PHI_RESULT (new_phi));
7178         } 
7179
7180       /** end loop-exit-fixes after versioning  **/
7181
7182       update_ssa (TODO_update_ssa);
7183       cond_exp_bsi = bsi_last (condition_bb);
7184       bsi_insert_before (&cond_exp_bsi, cond_expr_stmt_list, BSI_SAME_STMT);
7185     }
7186
7187   /* CHECKME: we wouldn't need this if we called update_ssa once
7188      for all loops.  */
7189   bitmap_zero (vect_memsyms_to_rename);
7190
7191   /* Peel the loop if there are data refs with unknown alignment.
7192      Only one data ref with unknown store is allowed.  */
7193
7194   if (LOOP_PEELING_FOR_ALIGNMENT (loop_vinfo))
7195     vect_do_peeling_for_alignment (loop_vinfo);
7196   
7197   /* If the loop has a symbolic number of iterations 'n' (i.e. it's not a
7198      compile time constant), or it is a constant that doesn't divide by the
7199      vectorization factor, then an epilog loop needs to be created.
7200      We therefore duplicate the loop: the original loop will be vectorized,
7201      and will compute the first (n/VF) iterations. The second copy of the loop
7202      will remain scalar and will compute the remaining (n%VF) iterations.
7203      (VF is the vectorization factor).  */
7204
7205   if (!LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
7206       || (LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
7207           && LOOP_VINFO_INT_NITERS (loop_vinfo) % vectorization_factor != 0))
7208     vect_do_peeling_for_loop_bound (loop_vinfo, &ratio);
7209   else
7210     ratio = build_int_cst (TREE_TYPE (LOOP_VINFO_NITERS (loop_vinfo)),
7211                 LOOP_VINFO_INT_NITERS (loop_vinfo) / vectorization_factor);
7212
7213   /* 1) Make sure the loop header has exactly two entries
7214      2) Make sure we have a preheader basic block.  */
7215
7216   gcc_assert (EDGE_COUNT (loop->header->preds) == 2);
7217
7218   split_edge (loop_preheader_edge (loop));
7219
7220   /* FORNOW: the vectorizer supports only loops which body consist
7221      of one basic block (header + empty latch). When the vectorizer will 
7222      support more involved loop forms, the order by which the BBs are 
7223      traversed need to be reconsidered.  */
7224
7225   for (i = 0; i < nbbs; i++)
7226     {
7227       basic_block bb = bbs[i];
7228       stmt_vec_info stmt_info;
7229       tree phi;
7230
7231       for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
7232         {
7233           if (vect_print_dump_info (REPORT_DETAILS))
7234             {
7235               fprintf (vect_dump, "------>vectorizing phi: ");
7236               print_generic_expr (vect_dump, phi, TDF_SLIM);
7237             }
7238           stmt_info = vinfo_for_stmt (phi);
7239           if (!stmt_info)
7240             continue;
7241
7242           if (!STMT_VINFO_RELEVANT_P (stmt_info)
7243               && !STMT_VINFO_LIVE_P (stmt_info))
7244             continue;
7245
7246           if ((TYPE_VECTOR_SUBPARTS (STMT_VINFO_VECTYPE (stmt_info))
7247                 != (unsigned HOST_WIDE_INT) vectorization_factor)
7248               && vect_print_dump_info (REPORT_DETAILS))
7249             fprintf (vect_dump, "multiple-types.");
7250
7251           if (STMT_VINFO_DEF_TYPE (stmt_info) == vect_induction_def)
7252             {
7253               if (vect_print_dump_info (REPORT_DETAILS))
7254                 fprintf (vect_dump, "transform phi.");
7255               vect_transform_stmt (phi, NULL, NULL, NULL);
7256             }
7257         }
7258
7259       for (si = bsi_start (bb); !bsi_end_p (si);)
7260         {
7261           tree stmt = bsi_stmt (si);
7262           bool is_store;
7263
7264           if (vect_print_dump_info (REPORT_DETAILS))
7265             {
7266               fprintf (vect_dump, "------>vectorizing statement: ");
7267               print_generic_expr (vect_dump, stmt, TDF_SLIM);
7268             }   
7269
7270           stmt_info = vinfo_for_stmt (stmt);
7271
7272           /* vector stmts created in the outer-loop during vectorization of
7273              stmts in an inner-loop may not have a stmt_info, and do not
7274              need to be vectorized.  */
7275           if (!stmt_info)
7276             {
7277               bsi_next (&si);
7278               continue;
7279             }
7280
7281           if (!STMT_VINFO_RELEVANT_P (stmt_info)
7282               && !STMT_VINFO_LIVE_P (stmt_info))
7283             {
7284               bsi_next (&si);
7285               continue;
7286             }
7287
7288           gcc_assert (STMT_VINFO_VECTYPE (stmt_info));
7289           nunits =
7290             (unsigned int) TYPE_VECTOR_SUBPARTS (STMT_VINFO_VECTYPE (stmt_info));
7291           if (!STMT_SLP_TYPE (stmt_info)
7292               && nunits != (unsigned int) vectorization_factor
7293               && vect_print_dump_info (REPORT_DETAILS))
7294             /* For SLP VF is set according to unrolling factor, and not to
7295                vector size, hence for SLP this print is not valid.  */
7296             fprintf (vect_dump, "multiple-types.");
7297
7298           /* SLP. Schedule all the SLP instances when the first SLP stmt is
7299              reached.  */
7300           if (STMT_SLP_TYPE (stmt_info))
7301             {
7302               if (!slp_scheduled)
7303                 {
7304                   slp_scheduled = true;
7305
7306                   if (vect_print_dump_info (REPORT_DETAILS))
7307                     fprintf (vect_dump, "=== scheduling SLP instances ===");
7308
7309                   is_store = vect_schedule_slp (loop_vinfo, nunits);
7310
7311                   /* IS_STORE is true if STMT is a store. Stores cannot be of
7312                      hybrid SLP type. They are removed in
7313                      vect_schedule_slp_instance and their vinfo is destroyed. */
7314                   if (is_store)
7315                     {
7316                       bsi_next (&si);
7317                       continue;
7318                     }
7319                 }
7320
7321               /* Hybrid SLP stmts must be vectorized in addition to SLP.  */
7322               if (PURE_SLP_STMT (stmt_info))
7323                 {
7324                   bsi_next (&si);
7325                   continue;
7326                 }
7327             }
7328           
7329           /* -------- vectorize statement ------------ */
7330           if (vect_print_dump_info (REPORT_DETAILS))
7331             fprintf (vect_dump, "transform statement.");
7332
7333           strided_store = false;
7334           is_store = vect_transform_stmt (stmt, &si, &strided_store, NULL);
7335           if (is_store)
7336             {
7337               stmt_ann_t ann;
7338               if (STMT_VINFO_STRIDED_ACCESS (stmt_info))
7339                 {
7340                   /* Interleaving. If IS_STORE is TRUE, the vectorization of the
7341                      interleaving chain was completed - free all the stores in
7342                      the chain.  */
7343                   tree next = DR_GROUP_FIRST_DR (stmt_info);
7344                   tree tmp;
7345                   stmt_vec_info next_stmt_info;
7346
7347                   while (next)
7348                     {
7349                       next_si = bsi_for_stmt (next);
7350                       next_stmt_info = vinfo_for_stmt (next);
7351                       /* Free the attached stmt_vec_info and remove the stmt.  */
7352                       ann = stmt_ann (next);
7353                       tmp = DR_GROUP_NEXT_DR (next_stmt_info);
7354                       free (next_stmt_info);
7355                       set_stmt_info (ann, NULL);
7356                       bsi_remove (&next_si, true);
7357                       next = tmp;
7358                     }
7359                   bsi_remove (&si, true);
7360                   continue;
7361                 }
7362               else
7363                 {
7364                   /* Free the attached stmt_vec_info and remove the stmt.  */
7365                   ann = stmt_ann (stmt);
7366                   free (stmt_info);
7367                   set_stmt_info (ann, NULL);
7368                   bsi_remove (&si, true);
7369                   continue;
7370                 }
7371             }
7372           bsi_next (&si);
7373         }                       /* stmts in BB */
7374     }                           /* BBs in loop */
7375
7376   slpeel_make_loop_iterate_ntimes (loop, ratio);
7377
7378   mark_set_for_renaming (vect_memsyms_to_rename);
7379
7380   /* The memory tags and pointers in vectorized statements need to
7381      have their SSA forms updated.  FIXME, why can't this be delayed
7382      until all the loops have been transformed?  */
7383   update_ssa (TODO_update_ssa);
7384
7385   if (vect_print_dump_info (REPORT_VECTORIZED_LOOPS))
7386     fprintf (vect_dump, "LOOP VECTORIZED.");
7387   if (loop->inner && vect_print_dump_info (REPORT_VECTORIZED_LOOPS))
7388     fprintf (vect_dump, "OUTER LOOP VECTORIZED.");
7389 }