OSDN Git Service

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