OSDN Git Service

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