OSDN Git Service

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