OSDN Git Service

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