* builtins.def (BUILT_IN_LCEIL, BUILT_IN_LCEILF, BUILT_IN_LCEILL)
[official-gcc.git] / gcc / tree-vect-transform.c
blob0d14c13143bc402b03e26913f843ad608a781cf5
1 /* Transformation Utilities for Loop Vectorization.
2 Copyright (C) 2003,2004,2005 Free Software Foundation, Inc.
3 Contributed by Dorit Naishlos <dorit@il.ibm.com>
5 This file is part of GCC.
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.
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.
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, 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA. */
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "errors.h"
27 #include "ggc.h"
28 #include "tree.h"
29 #include "target.h"
30 #include "rtl.h"
31 #include "basic-block.h"
32 #include "diagnostic.h"
33 #include "tree-flow.h"
34 #include "tree-dump.h"
35 #include "timevar.h"
36 #include "cfgloop.h"
37 #include "expr.h"
38 #include "optabs.h"
39 #include "tree-data-ref.h"
40 #include "tree-chrec.h"
41 #include "tree-scalar-evolution.h"
42 #include "tree-vectorizer.h"
43 #include "langhooks.h"
44 #include "tree-pass.h"
45 #include "toplev.h"
47 /* Utility functions for the code transformation. */
48 static bool vect_transform_stmt (tree, block_stmt_iterator *);
49 static void vect_align_data_ref (tree);
50 static tree vect_create_destination_var (tree, tree);
51 static tree vect_create_data_ref_ptr
52 (tree, block_stmt_iterator *, tree, tree *, bool);
53 static tree vect_create_index_for_vector_ref (loop_vec_info);
54 static tree vect_create_addr_base_for_vector_ref (tree, tree *, tree);
55 static tree vect_get_new_vect_var (tree, enum vect_var_kind, const char *);
56 static tree vect_get_vec_def_for_operand (tree, tree);
57 static tree vect_init_vector (tree, tree);
58 static void vect_finish_stmt_generation
59 (tree stmt, tree vec_stmt, block_stmt_iterator *bsi);
60 static void update_vuses_to_preheader (tree, struct loop*);
62 /* Utility function dealing with loop peeling (not peeling itself). */
63 static void vect_generate_tmps_on_preheader
64 (loop_vec_info, tree *, tree *, tree *);
65 static tree vect_build_loop_niters (loop_vec_info);
66 static void vect_update_ivs_after_vectorizer (loop_vec_info, tree, edge);
67 static tree vect_gen_niters_for_prolog_loop (loop_vec_info, tree);
68 static void vect_update_init_of_dr (struct data_reference *, tree niters);
69 static void vect_update_inits_of_drs (loop_vec_info, tree);
70 static void vect_do_peeling_for_alignment (loop_vec_info, struct loops *);
71 static void vect_do_peeling_for_loop_bound
72 (loop_vec_info, tree *, struct loops *);
75 /* Function vect_get_new_vect_var.
77 Returns a name for a new variable. The current naming scheme appends the
78 prefix "vect_" or "vect_p" (depending on the value of VAR_KIND) to
79 the name of vectorizer generated variables, and appends that to NAME if
80 provided. */
82 static tree
83 vect_get_new_vect_var (tree type, enum vect_var_kind var_kind, const char *name)
85 const char *prefix;
86 tree new_vect_var;
88 if (var_kind == vect_simple_var)
89 prefix = "vect_";
90 else
91 prefix = "vect_p";
93 if (name)
94 new_vect_var = create_tmp_var (type, concat (prefix, name, NULL));
95 else
96 new_vect_var = create_tmp_var (type, prefix);
98 return new_vect_var;
102 /* Function vect_create_index_for_vector_ref.
104 Create (and return) an index variable, along with it's update chain in the
105 loop. This variable will be used to access a memory location in a vector
106 operation.
108 Input:
109 LOOP: The loop being vectorized.
110 BSI: The block_stmt_iterator where STMT is. Any new stmts created by this
111 function can be added here, or in the loop pre-header.
113 Output:
114 Return an index that will be used to index a vector array. It is expected
115 that a pointer to the first vector will be used as the base address for the
116 indexed reference.
118 FORNOW: we are not trying to be efficient, just creating a new index each
119 time from scratch. At this time all vector references could use the same
120 index.
122 TODO: create only one index to be used by all vector references. Record
123 the index in the LOOP_VINFO the first time this procedure is called and
124 return it on subsequent calls. The increment of this index must be placed
125 just before the conditional expression that ends the single block loop. */
127 static tree
128 vect_create_index_for_vector_ref (loop_vec_info loop_vinfo)
130 tree init, step;
131 block_stmt_iterator incr_bsi;
132 bool insert_after;
133 tree indx_before_incr, indx_after_incr;
134 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
135 tree incr;
137 /* It is assumed that the base pointer used for vectorized access contains
138 the address of the first vector. Therefore the index used for vectorized
139 access must be initialized to zero and incremented by 1. */
141 init = integer_zero_node;
142 step = integer_one_node;
144 standard_iv_increment_position (loop, &incr_bsi, &insert_after);
145 create_iv (init, step, NULL_TREE, loop, &incr_bsi, insert_after,
146 &indx_before_incr, &indx_after_incr);
147 incr = bsi_stmt (incr_bsi);
148 get_stmt_operands (incr);
149 set_stmt_info (stmt_ann (incr), new_stmt_vec_info (incr, loop_vinfo));
151 return indx_before_incr;
155 /* Function vect_create_addr_base_for_vector_ref.
157 Create an expression that computes the address of the first memory location
158 that will be accessed for a data reference.
160 Input:
161 STMT: The statement containing the data reference.
162 NEW_STMT_LIST: Must be initialized to NULL_TREE or a statement list.
163 OFFSET: Optional. If supplied, it is be added to the initial address.
165 Output:
166 1. Return an SSA_NAME whose value is the address of the memory location of
167 the first vector of the data reference.
168 2. If new_stmt_list is not NULL_TREE after return then the caller must insert
169 these statement(s) which define the returned SSA_NAME.
171 FORNOW: We are only handling array accesses with step 1. */
173 static tree
174 vect_create_addr_base_for_vector_ref (tree stmt,
175 tree *new_stmt_list,
176 tree offset)
178 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
179 struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
180 tree data_ref_base =
181 unshare_expr (STMT_VINFO_VECT_DR_BASE_ADDRESS (stmt_info));
182 tree base_name = build_fold_indirect_ref (data_ref_base);
183 tree ref = DR_REF (dr);
184 tree scalar_type = TREE_TYPE (ref);
185 tree scalar_ptr_type = build_pointer_type (scalar_type);
186 tree vec_stmt;
187 tree new_temp;
188 tree addr_base, addr_expr;
189 tree dest, new_stmt;
190 tree base_offset = unshare_expr (STMT_VINFO_VECT_INIT_OFFSET (stmt_info));
192 /* Create base_offset */
193 dest = create_tmp_var (TREE_TYPE (base_offset), "base_off");
194 add_referenced_tmp_var (dest);
195 base_offset = force_gimple_operand (base_offset, &new_stmt, false, dest);
196 append_to_statement_list_force (new_stmt, new_stmt_list);
198 if (offset)
200 tree tmp = create_tmp_var (TREE_TYPE (base_offset), "offset");
201 add_referenced_tmp_var (tmp);
202 offset = fold (build2 (MULT_EXPR, TREE_TYPE (offset), offset,
203 STMT_VINFO_VECT_STEP (stmt_info)));
204 base_offset = fold (build2 (PLUS_EXPR, TREE_TYPE (base_offset),
205 base_offset, offset));
206 base_offset = force_gimple_operand (base_offset, &new_stmt, false, tmp);
207 append_to_statement_list_force (new_stmt, new_stmt_list);
210 /* base + base_offset */
211 addr_base = fold (build2 (PLUS_EXPR, TREE_TYPE (data_ref_base), data_ref_base,
212 base_offset));
214 /* addr_expr = addr_base */
215 addr_expr = vect_get_new_vect_var (scalar_ptr_type, vect_pointer_var,
216 get_name (base_name));
217 add_referenced_tmp_var (addr_expr);
218 vec_stmt = build2 (MODIFY_EXPR, void_type_node, addr_expr, addr_base);
219 new_temp = make_ssa_name (addr_expr, vec_stmt);
220 TREE_OPERAND (vec_stmt, 0) = new_temp;
221 append_to_statement_list_force (vec_stmt, new_stmt_list);
223 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
225 fprintf (vect_dump, "created ");
226 print_generic_expr (vect_dump, vec_stmt, TDF_SLIM);
228 return new_temp;
232 /* Function vect_align_data_ref.
234 Handle mislignment of a memory accesses.
236 FORNOW: Can't handle misaligned accesses.
237 Make sure that the dataref is aligned. */
239 static void
240 vect_align_data_ref (tree stmt)
242 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
243 struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
245 /* FORNOW: can't handle misaligned accesses;
246 all accesses expected to be aligned. */
247 gcc_assert (aligned_access_p (dr));
251 /* Function vect_create_data_ref_ptr.
253 Create a memory reference expression for vector access, to be used in a
254 vector load/store stmt. The reference is based on a new pointer to vector
255 type (vp).
257 Input:
258 1. STMT: a stmt that references memory. Expected to be of the form
259 MODIFY_EXPR <name, data-ref> or MODIFY_EXPR <data-ref, name>.
260 2. BSI: block_stmt_iterator where new stmts can be added.
261 3. OFFSET (optional): an offset to be added to the initial address accessed
262 by the data-ref in STMT.
263 4. ONLY_INIT: indicate if vp is to be updated in the loop, or remain
264 pointing to the initial address.
266 Output:
267 1. Declare a new ptr to vector_type, and have it point to the base of the
268 data reference (initial addressed accessed by the data reference).
269 For example, for vector of type V8HI, the following code is generated:
271 v8hi *vp;
272 vp = (v8hi *)initial_address;
274 if OFFSET is not supplied:
275 initial_address = &a[init];
276 if OFFSET is supplied:
277 initial_address = &a[init + OFFSET];
279 Return the initial_address in INITIAL_ADDRESS.
281 2. Create a data-reference in the loop based on the new vector pointer vp,
282 and using a new index variable 'idx' as follows:
284 vp' = vp + update
286 where if ONLY_INIT is true:
287 update = zero
288 and otherwise
289 update = idx + vector_type_size
291 Return the pointer vp'.
294 FORNOW: handle only aligned and consecutive accesses. */
296 static tree
297 vect_create_data_ref_ptr (tree stmt, block_stmt_iterator *bsi, tree offset,
298 tree *initial_address, bool only_init)
300 tree base_name;
301 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
302 loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
303 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
304 tree vectype = STMT_VINFO_VECTYPE (stmt_info);
305 tree vect_ptr_type;
306 tree vect_ptr;
307 tree tag;
308 tree new_temp;
309 tree vec_stmt;
310 tree new_stmt_list = NULL_TREE;
311 tree idx;
312 edge pe = loop_preheader_edge (loop);
313 basic_block new_bb;
314 tree vect_ptr_init;
315 tree vectype_size;
316 tree ptr_update;
317 tree data_ref_ptr;
318 tree type, tmp, size;
320 base_name = build_fold_indirect_ref (unshare_expr (
321 STMT_VINFO_VECT_DR_BASE_ADDRESS (stmt_info)));
323 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
325 tree data_ref_base = base_name;
326 fprintf (vect_dump, "create array_ref of type: ");
327 print_generic_expr (vect_dump, vectype, TDF_SLIM);
328 if (TREE_CODE (data_ref_base) == VAR_DECL)
329 fprintf (vect_dump, " vectorizing a one dimensional array ref: ");
330 else if (TREE_CODE (data_ref_base) == ARRAY_REF)
331 fprintf (vect_dump, " vectorizing a multidimensional array ref: ");
332 else if (TREE_CODE (data_ref_base) == COMPONENT_REF)
333 fprintf (vect_dump, " vectorizing a record based array ref: ");
334 else if (TREE_CODE (data_ref_base) == SSA_NAME)
335 fprintf (vect_dump, " vectorizing a pointer ref: ");
336 print_generic_expr (vect_dump, base_name, TDF_SLIM);
339 /** (1) Create the new vector-pointer variable: **/
341 vect_ptr_type = build_pointer_type (vectype);
342 vect_ptr = vect_get_new_vect_var (vect_ptr_type, vect_pointer_var,
343 get_name (base_name));
344 add_referenced_tmp_var (vect_ptr);
347 /** (2) Add aliasing information to the new vector-pointer:
348 (The points-to info (SSA_NAME_PTR_INFO) may be defined later.) **/
350 tag = STMT_VINFO_MEMTAG (stmt_info);
351 gcc_assert (tag);
353 /* If the memory tag of the original reference was not a type tag or
354 if the pointed-to type of VECT_PTR has an alias set number
355 different than TAG's, then we need to create a new type tag for
356 VECT_PTR and add TAG to its alias set. */
357 if (var_ann (tag)->mem_tag_kind == NOT_A_TAG
358 || get_alias_set (tag) != get_alias_set (TREE_TYPE (vect_ptr_type)))
359 add_type_alias (vect_ptr, tag);
360 else
361 var_ann (vect_ptr)->type_mem_tag = tag;
363 var_ann (vect_ptr)->subvars = STMT_VINFO_SUBVARS (stmt_info);
365 /** (3) Calculate the initial address the vector-pointer, and set
366 the vector-pointer to point to it before the loop: **/
368 /* Create: (&(base[init_val+offset]) in the loop preheader. */
369 new_temp = vect_create_addr_base_for_vector_ref (stmt, &new_stmt_list,
370 offset);
371 pe = loop_preheader_edge (loop);
372 new_bb = bsi_insert_on_edge_immediate (pe, new_stmt_list);
373 gcc_assert (!new_bb);
374 *initial_address = new_temp;
376 /* Create: p = (vectype *) initial_base */
377 vec_stmt = fold_convert (vect_ptr_type, new_temp);
378 vec_stmt = build2 (MODIFY_EXPR, void_type_node, vect_ptr, vec_stmt);
379 new_temp = make_ssa_name (vect_ptr, vec_stmt);
380 TREE_OPERAND (vec_stmt, 0) = new_temp;
381 new_bb = bsi_insert_on_edge_immediate (pe, vec_stmt);
382 gcc_assert (!new_bb);
383 vect_ptr_init = TREE_OPERAND (vec_stmt, 0);
386 /** (4) Handle the updating of the vector-pointer inside the loop: **/
388 if (only_init) /* No update in loop is required. */
390 /* Copy the points-to information if it exists. */
391 if (STMT_VINFO_PTR_INFO (stmt_info))
392 duplicate_ssa_name_ptr_info (vect_ptr_init,
393 STMT_VINFO_PTR_INFO (stmt_info));
394 return vect_ptr_init;
397 idx = vect_create_index_for_vector_ref (loop_vinfo);
399 /* Create: update = idx * vectype_size */
400 tmp = create_tmp_var (integer_type_node, "update");
401 add_referenced_tmp_var (tmp);
402 size = TYPE_SIZE (vect_ptr_type);
403 type = lang_hooks.types.type_for_size (tree_low_cst (size, 1), 1);
404 ptr_update = create_tmp_var (type, "update");
405 add_referenced_tmp_var (ptr_update);
406 vectype_size = TYPE_SIZE_UNIT (vectype);
407 vec_stmt = build2 (MULT_EXPR, integer_type_node, idx, vectype_size);
408 vec_stmt = build2 (MODIFY_EXPR, void_type_node, tmp, vec_stmt);
409 new_temp = make_ssa_name (tmp, vec_stmt);
410 TREE_OPERAND (vec_stmt, 0) = new_temp;
411 bsi_insert_before (bsi, vec_stmt, BSI_SAME_STMT);
412 vec_stmt = fold_convert (type, new_temp);
413 vec_stmt = build2 (MODIFY_EXPR, void_type_node, ptr_update, vec_stmt);
414 new_temp = make_ssa_name (ptr_update, vec_stmt);
415 TREE_OPERAND (vec_stmt, 0) = new_temp;
416 bsi_insert_before (bsi, vec_stmt, BSI_SAME_STMT);
418 /* Create: data_ref_ptr = vect_ptr_init + update */
419 vec_stmt = build2 (PLUS_EXPR, vect_ptr_type, vect_ptr_init, new_temp);
420 vec_stmt = build2 (MODIFY_EXPR, void_type_node, vect_ptr, vec_stmt);
421 new_temp = make_ssa_name (vect_ptr, vec_stmt);
422 TREE_OPERAND (vec_stmt, 0) = new_temp;
423 bsi_insert_before (bsi, vec_stmt, BSI_SAME_STMT);
424 data_ref_ptr = TREE_OPERAND (vec_stmt, 0);
426 /* Copy the points-to information if it exists. */
427 if (STMT_VINFO_PTR_INFO (stmt_info))
428 duplicate_ssa_name_ptr_info (data_ref_ptr, STMT_VINFO_PTR_INFO (stmt_info));
429 return data_ref_ptr;
433 /* Function vect_create_destination_var.
435 Create a new temporary of type VECTYPE. */
437 static tree
438 vect_create_destination_var (tree scalar_dest, tree vectype)
440 tree vec_dest;
441 const char *new_name;
443 gcc_assert (TREE_CODE (scalar_dest) == SSA_NAME);
445 new_name = get_name (scalar_dest);
446 if (!new_name)
447 new_name = "var_";
448 vec_dest = vect_get_new_vect_var (vectype, vect_simple_var, new_name);
449 add_referenced_tmp_var (vec_dest);
451 return vec_dest;
455 /* Function vect_init_vector.
457 Insert a new stmt (INIT_STMT) that initializes a new vector variable with
458 the vector elements of VECTOR_VAR. Return the DEF of INIT_STMT. It will be
459 used in the vectorization of STMT. */
461 static tree
462 vect_init_vector (tree stmt, tree vector_var)
464 stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt);
465 loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
466 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
467 tree new_var;
468 tree init_stmt;
469 tree vectype = STMT_VINFO_VECTYPE (stmt_vinfo);
470 tree vec_oprnd;
471 edge pe;
472 tree new_temp;
473 basic_block new_bb;
475 new_var = vect_get_new_vect_var (vectype, vect_simple_var, "cst_");
476 add_referenced_tmp_var (new_var);
478 init_stmt = build2 (MODIFY_EXPR, vectype, new_var, vector_var);
479 new_temp = make_ssa_name (new_var, init_stmt);
480 TREE_OPERAND (init_stmt, 0) = new_temp;
482 pe = loop_preheader_edge (loop);
483 new_bb = bsi_insert_on_edge_immediate (pe, init_stmt);
484 gcc_assert (!new_bb);
486 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
488 fprintf (vect_dump, "created new init_stmt: ");
489 print_generic_expr (vect_dump, init_stmt, TDF_SLIM);
492 vec_oprnd = TREE_OPERAND (init_stmt, 0);
493 return vec_oprnd;
497 /* Function vect_get_vec_def_for_operand.
499 OP is an operand in STMT. This function returns a (vector) def that will be
500 used in the vectorized stmt for STMT.
502 In the case that OP is an SSA_NAME which is defined in the loop, then
503 STMT_VINFO_VEC_STMT of the defining stmt holds the relevant def.
505 In case OP is an invariant or constant, a new stmt that creates a vector def
506 needs to be introduced. */
508 static tree
509 vect_get_vec_def_for_operand (tree op, tree stmt)
511 tree vec_oprnd;
512 tree vec_stmt;
513 tree def_stmt;
514 stmt_vec_info def_stmt_info = NULL;
515 stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt);
516 tree vectype = STMT_VINFO_VECTYPE (stmt_vinfo);
517 int nunits = GET_MODE_NUNITS (TYPE_MODE (vectype));
518 loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
519 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
520 basic_block bb;
521 tree vec_inv;
522 tree t = NULL_TREE;
523 tree def;
524 int i;
526 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
528 fprintf (vect_dump, "vect_get_vec_def_for_operand: ");
529 print_generic_expr (vect_dump, op, TDF_SLIM);
532 /** ===> Case 1: operand is a constant. **/
534 if (TREE_CODE (op) == INTEGER_CST || TREE_CODE (op) == REAL_CST)
536 /* Create 'vect_cst_ = {cst,cst,...,cst}' */
538 tree vec_cst;
540 /* Build a tree with vector elements. */
541 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
542 fprintf (vect_dump, "Create vector_cst. nunits = %d", nunits);
544 for (i = nunits - 1; i >= 0; --i)
546 t = tree_cons (NULL_TREE, op, t);
548 vec_cst = build_vector (vectype, t);
549 return vect_init_vector (stmt, vec_cst);
552 gcc_assert (TREE_CODE (op) == SSA_NAME);
554 /** ===> Case 2: operand is an SSA_NAME - find the stmt that defines it. **/
556 def_stmt = SSA_NAME_DEF_STMT (op);
557 def_stmt_info = vinfo_for_stmt (def_stmt);
559 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
561 fprintf (vect_dump, "vect_get_vec_def_for_operand: def_stmt: ");
562 print_generic_expr (vect_dump, def_stmt, TDF_SLIM);
566 /** ==> Case 2.1: operand is defined inside the loop. **/
568 if (def_stmt_info)
570 /* Get the def from the vectorized stmt. */
572 vec_stmt = STMT_VINFO_VEC_STMT (def_stmt_info);
573 gcc_assert (vec_stmt);
574 vec_oprnd = TREE_OPERAND (vec_stmt, 0);
575 return vec_oprnd;
579 /** ==> Case 2.2: operand is defined by the loop-header phi-node -
580 it is a reduction/induction. **/
582 bb = bb_for_stmt (def_stmt);
583 if (TREE_CODE (def_stmt) == PHI_NODE && flow_bb_inside_loop_p (loop, bb))
585 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
586 fprintf (vect_dump, "reduction/induction - unsupported.");
587 internal_error ("no support for reduction/induction"); /* FORNOW */
591 /** ==> Case 2.3: operand is defined outside the loop -
592 it is a loop invariant. */
594 switch (TREE_CODE (def_stmt))
596 case PHI_NODE:
597 def = PHI_RESULT (def_stmt);
598 break;
599 case MODIFY_EXPR:
600 def = TREE_OPERAND (def_stmt, 0);
601 break;
602 case NOP_EXPR:
603 def = TREE_OPERAND (def_stmt, 0);
604 gcc_assert (IS_EMPTY_STMT (def_stmt));
605 def = op;
606 break;
607 default:
608 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
610 fprintf (vect_dump, "unsupported defining stmt: ");
611 print_generic_expr (vect_dump, def_stmt, TDF_SLIM);
613 internal_error ("unsupported defining stmt");
616 /* Build a tree with vector elements.
617 Create 'vec_inv = {inv,inv,..,inv}' */
619 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
620 fprintf (vect_dump, "Create vector_inv.");
622 for (i = nunits - 1; i >= 0; --i)
624 t = tree_cons (NULL_TREE, def, t);
627 vec_inv = build_constructor (vectype, t);
628 return vect_init_vector (stmt, vec_inv);
632 /* Function vect_finish_stmt_generation.
634 Insert a new stmt. */
636 static void
637 vect_finish_stmt_generation (tree stmt, tree vec_stmt, block_stmt_iterator *bsi)
639 bsi_insert_before (bsi, vec_stmt, BSI_SAME_STMT);
641 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
643 fprintf (vect_dump, "add new stmt: ");
644 print_generic_expr (vect_dump, vec_stmt, TDF_SLIM);
647 #ifdef ENABLE_CHECKING
648 /* Make sure bsi points to the stmt that is being vectorized. */
649 gcc_assert (stmt == bsi_stmt (*bsi));
650 #endif
652 #ifdef USE_MAPPED_LOCATION
653 SET_EXPR_LOCATION (vec_stmt, EXPR_LOCATION (stmt));
654 #else
655 SET_EXPR_LOCUS (vec_stmt, EXPR_LOCUS (stmt));
656 #endif
660 /* Function vectorizable_assignment.
662 Check if STMT performs an assignment (copy) that can be vectorized.
663 If VEC_STMT is also passed, vectorize the STMT: create a vectorized
664 stmt to replace it, put it in VEC_STMT, and insert it at BSI.
665 Return FALSE if not a vectorizable STMT, TRUE otherwise. */
667 bool
668 vectorizable_assignment (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt)
670 tree vec_dest;
671 tree scalar_dest;
672 tree op;
673 tree vec_oprnd;
674 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
675 tree vectype = STMT_VINFO_VECTYPE (stmt_info);
676 loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
677 tree new_temp;
679 /* Is vectorizable assignment? */
681 if (TREE_CODE (stmt) != MODIFY_EXPR)
682 return false;
684 scalar_dest = TREE_OPERAND (stmt, 0);
685 if (TREE_CODE (scalar_dest) != SSA_NAME)
686 return false;
688 op = TREE_OPERAND (stmt, 1);
689 if (!vect_is_simple_use (op, loop_vinfo, NULL))
691 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
692 fprintf (vect_dump, "use not simple.");
693 return false;
696 if (!vec_stmt) /* transformation not required. */
698 STMT_VINFO_TYPE (stmt_info) = assignment_vec_info_type;
699 return true;
702 /** Transform. **/
703 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
704 fprintf (vect_dump, "transform assignment.");
706 /* Handle def. */
707 vec_dest = vect_create_destination_var (scalar_dest, vectype);
709 /* Handle use. */
710 op = TREE_OPERAND (stmt, 1);
711 vec_oprnd = vect_get_vec_def_for_operand (op, stmt);
713 /* Arguments are ready. create the new vector stmt. */
714 *vec_stmt = build2 (MODIFY_EXPR, vectype, vec_dest, vec_oprnd);
715 new_temp = make_ssa_name (vec_dest, *vec_stmt);
716 TREE_OPERAND (*vec_stmt, 0) = new_temp;
717 vect_finish_stmt_generation (stmt, *vec_stmt, bsi);
719 return true;
723 /* Function vectorizable_operation.
725 Check if STMT performs a binary or unary operation that can be vectorized.
726 If VEC_STMT is also passed, vectorize the STMT: create a vectorized
727 stmt to replace it, put it in VEC_STMT, and insert it at BSI.
728 Return FALSE if not a vectorizable STMT, TRUE otherwise. */
730 bool
731 vectorizable_operation (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt)
733 tree vec_dest;
734 tree scalar_dest;
735 tree operation;
736 tree op0, op1 = NULL;
737 tree vec_oprnd0, vec_oprnd1=NULL;
738 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
739 tree vectype = STMT_VINFO_VECTYPE (stmt_info);
740 loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
741 int i;
742 enum tree_code code;
743 enum machine_mode vec_mode;
744 tree new_temp;
745 int op_type;
746 tree op;
747 optab optab;
749 /* Is STMT a vectorizable binary/unary operation? */
750 if (TREE_CODE (stmt) != MODIFY_EXPR)
751 return false;
753 if (TREE_CODE (TREE_OPERAND (stmt, 0)) != SSA_NAME)
754 return false;
756 operation = TREE_OPERAND (stmt, 1);
757 code = TREE_CODE (operation);
758 optab = optab_for_tree_code (code, vectype);
760 /* Support only unary or binary operations. */
761 op_type = TREE_CODE_LENGTH (code);
762 if (op_type != unary_op && op_type != binary_op)
764 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
765 fprintf (vect_dump, "num. args = %d (not unary/binary op).", op_type);
766 return false;
769 for (i = 0; i < op_type; i++)
771 op = TREE_OPERAND (operation, i);
772 if (!vect_is_simple_use (op, loop_vinfo, NULL))
774 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
775 fprintf (vect_dump, "use not simple.");
776 return false;
780 /* Supportable by target? */
781 if (!optab)
783 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
784 fprintf (vect_dump, "no optab.");
785 return false;
787 vec_mode = TYPE_MODE (vectype);
788 if (optab->handlers[(int) vec_mode].insn_code == CODE_FOR_nothing)
790 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
791 fprintf (vect_dump, "op not supported by target.");
792 return false;
795 if (!vec_stmt) /* transformation not required. */
797 STMT_VINFO_TYPE (stmt_info) = op_vec_info_type;
798 return true;
801 /** Transform. **/
803 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
804 fprintf (vect_dump, "transform binary/unary operation.");
806 /* Handle def. */
807 scalar_dest = TREE_OPERAND (stmt, 0);
808 vec_dest = vect_create_destination_var (scalar_dest, vectype);
810 /* Handle uses. */
811 op0 = TREE_OPERAND (operation, 0);
812 vec_oprnd0 = vect_get_vec_def_for_operand (op0, stmt);
814 if (op_type == binary_op)
816 op1 = TREE_OPERAND (operation, 1);
817 vec_oprnd1 = vect_get_vec_def_for_operand (op1, stmt);
820 /* Arguments are ready. create the new vector stmt. */
822 if (op_type == binary_op)
823 *vec_stmt = build2 (MODIFY_EXPR, vectype, vec_dest,
824 build2 (code, vectype, vec_oprnd0, vec_oprnd1));
825 else
826 *vec_stmt = build2 (MODIFY_EXPR, vectype, vec_dest,
827 build1 (code, vectype, vec_oprnd0));
828 new_temp = make_ssa_name (vec_dest, *vec_stmt);
829 TREE_OPERAND (*vec_stmt, 0) = new_temp;
830 vect_finish_stmt_generation (stmt, *vec_stmt, bsi);
832 return true;
836 /* Function vectorizable_store.
838 Check if STMT defines a non scalar data-ref (array/pointer/structure) that
839 can be vectorized.
840 If VEC_STMT is also passed, vectorize the STMT: create a vectorized
841 stmt to replace it, put it in VEC_STMT, and insert it at BSI.
842 Return FALSE if not a vectorizable STMT, TRUE otherwise. */
844 bool
845 vectorizable_store (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt)
847 tree scalar_dest;
848 tree data_ref;
849 tree op;
850 tree vec_oprnd1;
851 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
852 struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
853 tree vectype = STMT_VINFO_VECTYPE (stmt_info);
854 loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
855 enum machine_mode vec_mode;
856 tree dummy;
857 enum dr_alignment_support alignment_support_cheme;
858 v_may_def_optype v_may_defs;
859 int nv_may_defs, i;
861 /* Is vectorizable store? */
863 if (TREE_CODE (stmt) != MODIFY_EXPR)
864 return false;
866 scalar_dest = TREE_OPERAND (stmt, 0);
867 if (TREE_CODE (scalar_dest) != ARRAY_REF
868 && TREE_CODE (scalar_dest) != INDIRECT_REF)
869 return false;
871 op = TREE_OPERAND (stmt, 1);
872 if (!vect_is_simple_use (op, loop_vinfo, NULL))
874 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
875 fprintf (vect_dump, "use not simple.");
876 return false;
879 vec_mode = TYPE_MODE (vectype);
880 /* FORNOW. In some cases can vectorize even if data-type not supported
881 (e.g. - array initialization with 0). */
882 if (mov_optab->handlers[(int)vec_mode].insn_code == CODE_FOR_nothing)
883 return false;
885 if (!STMT_VINFO_DATA_REF (stmt_info))
886 return false;
889 if (!vec_stmt) /* transformation not required. */
891 STMT_VINFO_TYPE (stmt_info) = store_vec_info_type;
892 return true;
895 /** Transform. **/
897 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
898 fprintf (vect_dump, "transform store");
900 alignment_support_cheme = vect_supportable_dr_alignment (dr);
901 gcc_assert (alignment_support_cheme);
902 gcc_assert (alignment_support_cheme == dr_aligned); /* FORNOW */
904 /* Handle use - get the vectorized def from the defining stmt. */
905 vec_oprnd1 = vect_get_vec_def_for_operand (op, stmt);
907 /* Handle def. */
908 /* FORNOW: make sure the data reference is aligned. */
909 vect_align_data_ref (stmt);
910 data_ref = vect_create_data_ref_ptr (stmt, bsi, NULL_TREE, &dummy, false);
911 data_ref = build_fold_indirect_ref (data_ref);
913 /* Arguments are ready. create the new vector stmt. */
914 *vec_stmt = build2 (MODIFY_EXPR, vectype, data_ref, vec_oprnd1);
915 vect_finish_stmt_generation (stmt, *vec_stmt, bsi);
917 /* Copy the V_MAY_DEFS representing the aliasing of the original array
918 element's definition to the vector's definition then update the
919 defining statement. The original is being deleted so the same
920 SSA_NAMEs can be used. */
921 copy_virtual_operands (*vec_stmt, stmt);
922 v_may_defs = STMT_V_MAY_DEF_OPS (*vec_stmt);
923 nv_may_defs = NUM_V_MAY_DEFS (v_may_defs);
925 for (i = 0; i < nv_may_defs; i++)
927 tree ssa_name = V_MAY_DEF_RESULT (v_may_defs, i);
928 SSA_NAME_DEF_STMT (ssa_name) = *vec_stmt;
931 return true;
935 /* vectorizable_load.
937 Check if STMT reads a non scalar data-ref (array/pointer/structure) that
938 can be vectorized.
939 If VEC_STMT is also passed, vectorize the STMT: create a vectorized
940 stmt to replace it, put it in VEC_STMT, and insert it at BSI.
941 Return FALSE if not a vectorizable STMT, TRUE otherwise. */
943 bool
944 vectorizable_load (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt)
946 tree scalar_dest;
947 tree vec_dest = NULL;
948 tree data_ref = NULL;
949 tree op;
950 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
951 struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
952 tree vectype = STMT_VINFO_VECTYPE (stmt_info);
953 tree new_temp;
954 int mode;
955 tree init_addr;
956 tree new_stmt;
957 tree dummy;
958 basic_block new_bb;
959 loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
960 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
961 edge pe = loop_preheader_edge (loop);
962 enum dr_alignment_support alignment_support_cheme;
964 /* Is vectorizable load? */
966 if (TREE_CODE (stmt) != MODIFY_EXPR)
967 return false;
969 scalar_dest = TREE_OPERAND (stmt, 0);
970 if (TREE_CODE (scalar_dest) != SSA_NAME)
971 return false;
973 op = TREE_OPERAND (stmt, 1);
974 if (TREE_CODE (op) != ARRAY_REF && TREE_CODE (op) != INDIRECT_REF)
975 return false;
977 if (!STMT_VINFO_DATA_REF (stmt_info))
978 return false;
980 mode = (int) TYPE_MODE (vectype);
982 /* FORNOW. In some cases can vectorize even if data-type not supported
983 (e.g. - data copies). */
984 if (mov_optab->handlers[mode].insn_code == CODE_FOR_nothing)
986 if (vect_print_dump_info (REPORT_DETAILS, LOOP_LOC (loop_vinfo)))
987 fprintf (vect_dump, "Aligned load, but unsupported type.");
988 return false;
991 if (!vec_stmt) /* transformation not required. */
993 STMT_VINFO_TYPE (stmt_info) = load_vec_info_type;
994 return true;
997 /** Transform. **/
999 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
1000 fprintf (vect_dump, "transform load.");
1002 alignment_support_cheme = vect_supportable_dr_alignment (dr);
1003 gcc_assert (alignment_support_cheme);
1005 if (alignment_support_cheme == dr_aligned
1006 || alignment_support_cheme == dr_unaligned_supported)
1008 /* Create:
1009 p = initial_addr;
1010 indx = 0;
1011 loop {
1012 vec_dest = *(p);
1013 indx = indx + 1;
1017 vec_dest = vect_create_destination_var (scalar_dest, vectype);
1018 data_ref = vect_create_data_ref_ptr (stmt, bsi, NULL_TREE, &dummy, false);
1019 if (aligned_access_p (dr))
1020 data_ref = build_fold_indirect_ref (data_ref);
1021 else
1023 int mis = DR_MISALIGNMENT (dr);
1024 tree tmis = (mis == -1 ? size_zero_node : size_int (mis));
1025 tmis = size_binop (MULT_EXPR, tmis, size_int(BITS_PER_UNIT));
1026 data_ref = build2 (MISALIGNED_INDIRECT_REF, vectype, data_ref, tmis);
1028 new_stmt = build2 (MODIFY_EXPR, vectype, vec_dest, data_ref);
1029 new_temp = make_ssa_name (vec_dest, new_stmt);
1030 TREE_OPERAND (new_stmt, 0) = new_temp;
1031 vect_finish_stmt_generation (stmt, new_stmt, bsi);
1032 copy_virtual_operands (new_stmt, stmt);
1034 else if (alignment_support_cheme == dr_unaligned_software_pipeline)
1036 /* Create:
1037 p1 = initial_addr;
1038 msq_init = *(floor(p1))
1039 p2 = initial_addr + VS - 1;
1040 magic = have_builtin ? builtin_result : initial_address;
1041 indx = 0;
1042 loop {
1043 p2' = p2 + indx * vectype_size
1044 lsq = *(floor(p2'))
1045 vec_dest = realign_load (msq, lsq, magic)
1046 indx = indx + 1;
1047 msq = lsq;
1051 tree offset;
1052 tree magic;
1053 tree phi_stmt;
1054 tree msq_init;
1055 tree msq, lsq;
1056 tree dataref_ptr;
1057 tree params;
1059 /* <1> Create msq_init = *(floor(p1)) in the loop preheader */
1060 vec_dest = vect_create_destination_var (scalar_dest, vectype);
1061 data_ref = vect_create_data_ref_ptr (stmt, bsi, NULL_TREE,
1062 &init_addr, true);
1063 data_ref = build1 (ALIGN_INDIRECT_REF, vectype, data_ref);
1064 new_stmt = build2 (MODIFY_EXPR, vectype, vec_dest, data_ref);
1065 new_temp = make_ssa_name (vec_dest, new_stmt);
1066 TREE_OPERAND (new_stmt, 0) = new_temp;
1067 new_bb = bsi_insert_on_edge_immediate (pe, new_stmt);
1068 gcc_assert (!new_bb);
1069 msq_init = TREE_OPERAND (new_stmt, 0);
1070 copy_virtual_operands (new_stmt, stmt);
1071 update_vuses_to_preheader (new_stmt, loop);
1074 /* <2> Create lsq = *(floor(p2')) in the loop */
1075 offset = build_int_cst (integer_type_node,
1076 GET_MODE_NUNITS (TYPE_MODE (vectype)));
1077 offset = int_const_binop (MINUS_EXPR, offset, integer_one_node, 1);
1078 vec_dest = vect_create_destination_var (scalar_dest, vectype);
1079 dataref_ptr = vect_create_data_ref_ptr (stmt, bsi, offset, &dummy, false);
1080 data_ref = build1 (ALIGN_INDIRECT_REF, vectype, dataref_ptr);
1081 new_stmt = build2 (MODIFY_EXPR, vectype, vec_dest, data_ref);
1082 new_temp = make_ssa_name (vec_dest, new_stmt);
1083 TREE_OPERAND (new_stmt, 0) = new_temp;
1084 vect_finish_stmt_generation (stmt, new_stmt, bsi);
1085 lsq = TREE_OPERAND (new_stmt, 0);
1086 copy_virtual_operands (new_stmt, stmt);
1089 /* <3> */
1090 if (targetm.vectorize.builtin_mask_for_load)
1092 /* Create permutation mask, if required, in loop preheader. */
1093 tree builtin_decl;
1094 params = build_tree_list (NULL_TREE, init_addr);
1095 vec_dest = vect_create_destination_var (scalar_dest, vectype);
1096 builtin_decl = targetm.vectorize.builtin_mask_for_load ();
1097 new_stmt = build_function_call_expr (builtin_decl, params);
1098 new_stmt = build2 (MODIFY_EXPR, vectype, vec_dest, new_stmt);
1099 new_temp = make_ssa_name (vec_dest, new_stmt);
1100 TREE_OPERAND (new_stmt, 0) = new_temp;
1101 new_bb = bsi_insert_on_edge_immediate (pe, new_stmt);
1102 gcc_assert (!new_bb);
1103 magic = TREE_OPERAND (new_stmt, 0);
1105 /* The result of the CALL_EXPR to this builtin is determined from
1106 the value of the parameter and no global variables are touched
1107 which makes the builtin a "const" function. Requiring the
1108 builtin to have the "const" attribute makes it unnecessary
1109 to call mark_call_clobbered_vars_to_rename. */
1110 gcc_assert (TREE_READONLY (builtin_decl));
1112 else
1114 /* Use current address instead of init_addr for reduced reg pressure.
1116 magic = dataref_ptr;
1120 /* <4> Create msq = phi <msq_init, lsq> in loop */
1121 vec_dest = vect_create_destination_var (scalar_dest, vectype);
1122 msq = make_ssa_name (vec_dest, NULL_TREE);
1123 phi_stmt = create_phi_node (msq, loop->header); /* CHECKME */
1124 SSA_NAME_DEF_STMT (msq) = phi_stmt;
1125 add_phi_arg (phi_stmt, msq_init, loop_preheader_edge (loop));
1126 add_phi_arg (phi_stmt, lsq, loop_latch_edge (loop));
1129 /* <5> Create <vec_dest = realign_load (msq, lsq, magic)> in loop */
1130 vec_dest = vect_create_destination_var (scalar_dest, vectype);
1131 new_stmt = build3 (REALIGN_LOAD_EXPR, vectype, msq, lsq, magic);
1132 new_stmt = build2 (MODIFY_EXPR, vectype, vec_dest, new_stmt);
1133 new_temp = make_ssa_name (vec_dest, new_stmt);
1134 TREE_OPERAND (new_stmt, 0) = new_temp;
1135 vect_finish_stmt_generation (stmt, new_stmt, bsi);
1137 else
1138 gcc_unreachable ();
1140 *vec_stmt = new_stmt;
1141 return true;
1145 /* Function vect_transform_stmt.
1147 Create a vectorized stmt to replace STMT, and insert it at BSI. */
1149 bool
1150 vect_transform_stmt (tree stmt, block_stmt_iterator *bsi)
1152 bool is_store = false;
1153 tree vec_stmt = NULL_TREE;
1154 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
1155 bool done;
1157 switch (STMT_VINFO_TYPE (stmt_info))
1159 case op_vec_info_type:
1160 done = vectorizable_operation (stmt, bsi, &vec_stmt);
1161 gcc_assert (done);
1162 break;
1164 case assignment_vec_info_type:
1165 done = vectorizable_assignment (stmt, bsi, &vec_stmt);
1166 gcc_assert (done);
1167 break;
1169 case load_vec_info_type:
1170 done = vectorizable_load (stmt, bsi, &vec_stmt);
1171 gcc_assert (done);
1172 break;
1174 case store_vec_info_type:
1175 done = vectorizable_store (stmt, bsi, &vec_stmt);
1176 gcc_assert (done);
1177 is_store = true;
1178 break;
1179 default:
1180 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
1181 fprintf (vect_dump, "stmt not supported.");
1182 gcc_unreachable ();
1185 STMT_VINFO_VEC_STMT (stmt_info) = vec_stmt;
1187 return is_store;
1191 /* This function builds ni_name = number of iterations loop executes
1192 on the loop preheader. */
1194 static tree
1195 vect_build_loop_niters (loop_vec_info loop_vinfo)
1197 tree ni_name, stmt, var;
1198 edge pe;
1199 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
1200 tree ni = unshare_expr (LOOP_VINFO_NITERS (loop_vinfo));
1202 var = create_tmp_var (TREE_TYPE (ni), "niters");
1203 add_referenced_tmp_var (var);
1204 ni_name = force_gimple_operand (ni, &stmt, false, var);
1206 pe = loop_preheader_edge (loop);
1207 if (stmt)
1209 basic_block new_bb = bsi_insert_on_edge_immediate (pe, stmt);
1210 gcc_assert (!new_bb);
1213 return ni_name;
1217 /* This function generates the following statements:
1219 ni_name = number of iterations loop executes
1220 ratio = ni_name / vf
1221 ratio_mult_vf_name = ratio * vf
1223 and places them at the loop preheader edge. */
1225 static void
1226 vect_generate_tmps_on_preheader (loop_vec_info loop_vinfo,
1227 tree *ni_name_ptr,
1228 tree *ratio_mult_vf_name_ptr,
1229 tree *ratio_name_ptr)
1232 edge pe;
1233 basic_block new_bb;
1234 tree stmt, ni_name;
1235 tree var;
1236 tree ratio_name;
1237 tree ratio_mult_vf_name;
1238 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
1239 tree ni = LOOP_VINFO_NITERS (loop_vinfo);
1240 int vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
1241 tree log_vf = build_int_cst (unsigned_type_node, exact_log2 (vf));
1243 pe = loop_preheader_edge (loop);
1245 /* Generate temporary variable that contains
1246 number of iterations loop executes. */
1248 ni_name = vect_build_loop_niters (loop_vinfo);
1250 /* Create: ratio = ni >> log2(vf) */
1252 var = create_tmp_var (TREE_TYPE (ni), "bnd");
1253 add_referenced_tmp_var (var);
1254 ratio_name = make_ssa_name (var, NULL_TREE);
1255 stmt = build2 (MODIFY_EXPR, void_type_node, ratio_name,
1256 build2 (RSHIFT_EXPR, TREE_TYPE (ni_name), ni_name, log_vf));
1257 SSA_NAME_DEF_STMT (ratio_name) = stmt;
1259 pe = loop_preheader_edge (loop);
1260 new_bb = bsi_insert_on_edge_immediate (pe, stmt);
1261 gcc_assert (!new_bb);
1263 /* Create: ratio_mult_vf = ratio << log2 (vf). */
1265 var = create_tmp_var (TREE_TYPE (ni), "ratio_mult_vf");
1266 add_referenced_tmp_var (var);
1267 ratio_mult_vf_name = make_ssa_name (var, NULL_TREE);
1268 stmt = build2 (MODIFY_EXPR, void_type_node, ratio_mult_vf_name,
1269 build2 (LSHIFT_EXPR, TREE_TYPE (ratio_name), ratio_name, log_vf));
1270 SSA_NAME_DEF_STMT (ratio_mult_vf_name) = stmt;
1272 pe = loop_preheader_edge (loop);
1273 new_bb = bsi_insert_on_edge_immediate (pe, stmt);
1274 gcc_assert (!new_bb);
1276 *ni_name_ptr = ni_name;
1277 *ratio_mult_vf_name_ptr = ratio_mult_vf_name;
1278 *ratio_name_ptr = ratio_name;
1280 return;
1284 /* Function update_vuses_to_preheader.
1286 Input:
1287 STMT - a statement with potential VUSEs.
1288 LOOP - the loop whose preheader will contain STMT.
1290 It's possible to vectorize a loop even though an SSA_NAME from a VUSE
1291 appears to be defined in a V_MAY_DEF in another statement in a loop.
1292 One such case is when the VUSE is at the dereference of a __restricted__
1293 pointer in a load and the V_MAY_DEF is at the dereference of a different
1294 __restricted__ pointer in a store. Vectorization may result in
1295 copy_virtual_uses being called to copy the problematic VUSE to a new
1296 statement that is being inserted in the loop preheader. This procedure
1297 is called to change the SSA_NAME in the new statement's VUSE from the
1298 SSA_NAME updated in the loop to the related SSA_NAME available on the
1299 path entering the loop.
1301 When this function is called, we have the following situation:
1303 # vuse <name1>
1304 S1: vload
1305 do {
1306 # name1 = phi < name0 , name2>
1308 # vuse <name1>
1309 S2: vload
1311 # name2 = vdef <name1>
1312 S3: vstore
1314 }while...
1316 Stmt S1 was created in the loop preheader block as part of misaligned-load
1317 handling. This function fixes the name of the vuse of S1 from 'name1' to
1318 'name0'. */
1320 static void
1321 update_vuses_to_preheader (tree stmt, struct loop *loop)
1323 basic_block header_bb = loop->header;
1324 edge preheader_e = loop_preheader_edge (loop);
1325 vuse_optype vuses = STMT_VUSE_OPS (stmt);
1326 int nvuses = NUM_VUSES (vuses);
1327 int i;
1329 for (i = 0; i < nvuses; i++)
1331 tree ssa_name = VUSE_OP (vuses, i);
1332 tree def_stmt = SSA_NAME_DEF_STMT (ssa_name);
1333 tree name_var = SSA_NAME_VAR (ssa_name);
1334 basic_block bb = bb_for_stmt (def_stmt);
1336 /* For a use before any definitions, def_stmt is a NOP_EXPR. */
1337 if (!IS_EMPTY_STMT (def_stmt)
1338 && flow_bb_inside_loop_p (loop, bb))
1340 /* If the block containing the statement defining the SSA_NAME
1341 is in the loop then it's necessary to find the definition
1342 outside the loop using the PHI nodes of the header. */
1343 tree phi;
1344 bool updated = false;
1346 for (phi = phi_nodes (header_bb); phi; phi = TREE_CHAIN (phi))
1348 if (SSA_NAME_VAR (PHI_RESULT (phi)) == name_var)
1350 SET_VUSE_OP (vuses, i,
1351 PHI_ARG_DEF (phi, preheader_e->dest_idx));
1352 updated = true;
1353 break;
1356 gcc_assert (updated);
1362 /* Function vect_update_ivs_after_vectorizer.
1364 "Advance" the induction variables of LOOP to the value they should take
1365 after the execution of LOOP. This is currently necessary because the
1366 vectorizer does not handle induction variables that are used after the
1367 loop. Such a situation occurs when the last iterations of LOOP are
1368 peeled, because:
1369 1. We introduced new uses after LOOP for IVs that were not originally used
1370 after LOOP: the IVs of LOOP are now used by an epilog loop.
1371 2. LOOP is going to be vectorized; this means that it will iterate N/VF
1372 times, whereas the loop IVs should be bumped N times.
1374 Input:
1375 - LOOP - a loop that is going to be vectorized. The last few iterations
1376 of LOOP were peeled.
1377 - NITERS - the number of iterations that LOOP executes (before it is
1378 vectorized). i.e, the number of times the ivs should be bumped.
1379 - UPDATE_E - a successor edge of LOOP->exit that is on the (only) path
1380 coming out from LOOP on which there are uses of the LOOP ivs
1381 (this is the path from LOOP->exit to epilog_loop->preheader).
1383 The new definitions of the ivs are placed in LOOP->exit.
1384 The phi args associated with the edge UPDATE_E in the bb
1385 UPDATE_E->dest are updated accordingly.
1387 Assumption 1: Like the rest of the vectorizer, this function assumes
1388 a single loop exit that has a single predecessor.
1390 Assumption 2: The phi nodes in the LOOP header and in update_bb are
1391 organized in the same order.
1393 Assumption 3: The access function of the ivs is simple enough (see
1394 vect_can_advance_ivs_p). This assumption will be relaxed in the future.
1396 Assumption 4: Exactly one of the successors of LOOP exit-bb is on a path
1397 coming out of LOOP on which the ivs of LOOP are used (this is the path
1398 that leads to the epilog loop; other paths skip the epilog loop). This
1399 path starts with the edge UPDATE_E, and its destination (denoted update_bb)
1400 needs to have its phis updated.
1403 static void
1404 vect_update_ivs_after_vectorizer (loop_vec_info loop_vinfo, tree niters,
1405 edge update_e)
1407 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
1408 basic_block exit_bb = loop->single_exit->dest;
1409 tree phi, phi1;
1410 basic_block update_bb = update_e->dest;
1412 /* gcc_assert (vect_can_advance_ivs_p (loop_vinfo)); */
1414 /* Make sure there exists a single-predecessor exit bb: */
1415 gcc_assert (single_pred_p (exit_bb));
1417 for (phi = phi_nodes (loop->header), phi1 = phi_nodes (update_bb);
1418 phi && phi1;
1419 phi = PHI_CHAIN (phi), phi1 = PHI_CHAIN (phi1))
1421 tree access_fn = NULL;
1422 tree evolution_part;
1423 tree init_expr;
1424 tree step_expr;
1425 tree var, stmt, ni, ni_name;
1426 block_stmt_iterator last_bsi;
1428 /* Skip virtual phi's. */
1429 if (!is_gimple_reg (SSA_NAME_VAR (PHI_RESULT (phi))))
1431 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
1432 fprintf (vect_dump, "virtual phi. skip.");
1433 continue;
1436 access_fn = analyze_scalar_evolution (loop, PHI_RESULT (phi));
1437 gcc_assert (access_fn);
1438 evolution_part =
1439 unshare_expr (evolution_part_in_loop_num (access_fn, loop->num));
1440 gcc_assert (evolution_part != NULL_TREE);
1442 /* FORNOW: We do not support IVs whose evolution function is a polynomial
1443 of degree >= 2 or exponential. */
1444 gcc_assert (!tree_is_chrec (evolution_part));
1446 step_expr = evolution_part;
1447 init_expr = unshare_expr (initial_condition_in_loop_num (access_fn,
1448 loop->num));
1450 ni = build2 (PLUS_EXPR, TREE_TYPE (init_expr),
1451 build2 (MULT_EXPR, TREE_TYPE (niters),
1452 niters, step_expr), init_expr);
1454 var = create_tmp_var (TREE_TYPE (init_expr), "tmp");
1455 add_referenced_tmp_var (var);
1457 ni_name = force_gimple_operand (ni, &stmt, false, var);
1459 /* Insert stmt into exit_bb. */
1460 last_bsi = bsi_last (exit_bb);
1461 if (stmt)
1462 bsi_insert_before (&last_bsi, stmt, BSI_SAME_STMT);
1464 /* Fix phi expressions in the successor bb. */
1465 SET_PHI_ARG_DEF (phi1, update_e->dest_idx, ni_name);
1470 /* Function vect_do_peeling_for_loop_bound
1472 Peel the last iterations of the loop represented by LOOP_VINFO.
1473 The peeled iterations form a new epilog loop. Given that the loop now
1474 iterates NITERS times, the new epilog loop iterates
1475 NITERS % VECTORIZATION_FACTOR times.
1477 The original loop will later be made to iterate
1478 NITERS / VECTORIZATION_FACTOR times (this value is placed into RATIO). */
1480 static void
1481 vect_do_peeling_for_loop_bound (loop_vec_info loop_vinfo, tree *ratio,
1482 struct loops *loops)
1485 tree ni_name, ratio_mult_vf_name;
1486 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
1487 struct loop *new_loop;
1488 edge update_e;
1489 basic_block preheader;
1490 #ifdef ENABLE_CHECKING
1491 int loop_num;
1492 #endif
1494 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
1495 fprintf (vect_dump, "=== vect_transtorm_for_unknown_loop_bound ===");
1497 /* Generate the following variables on the preheader of original loop:
1499 ni_name = number of iteration the original loop executes
1500 ratio = ni_name / vf
1501 ratio_mult_vf_name = ratio * vf */
1502 vect_generate_tmps_on_preheader (loop_vinfo, &ni_name,
1503 &ratio_mult_vf_name, ratio);
1505 #ifdef ENABLE_CHECKING
1506 loop_num = loop->num;
1507 #endif
1508 new_loop = slpeel_tree_peel_loop_to_edge (loop, loops, loop->single_exit,
1509 ratio_mult_vf_name, ni_name, false);
1510 #ifdef ENABLE_CHECKING
1511 gcc_assert (new_loop);
1512 gcc_assert (loop_num == loop->num);
1513 slpeel_verify_cfg_after_peeling (loop, new_loop);
1514 #endif
1516 /* A guard that controls whether the new_loop is to be executed or skipped
1517 is placed in LOOP->exit. LOOP->exit therefore has two successors - one
1518 is the preheader of NEW_LOOP, where the IVs from LOOP are used. The other
1519 is a bb after NEW_LOOP, where these IVs are not used. Find the edge that
1520 is on the path where the LOOP IVs are used and need to be updated. */
1522 preheader = loop_preheader_edge (new_loop)->src;
1523 if (EDGE_PRED (preheader, 0)->src == loop->single_exit->dest)
1524 update_e = EDGE_PRED (preheader, 0);
1525 else
1526 update_e = EDGE_PRED (preheader, 1);
1528 /* Update IVs of original loop as if they were advanced
1529 by ratio_mult_vf_name steps. */
1530 vect_update_ivs_after_vectorizer (loop_vinfo, ratio_mult_vf_name, update_e);
1532 /* After peeling we have to reset scalar evolution analyzer. */
1533 scev_reset ();
1535 return;
1539 /* Function vect_gen_niters_for_prolog_loop
1541 Set the number of iterations for the loop represented by LOOP_VINFO
1542 to the minimum between LOOP_NITERS (the original iteration count of the loop)
1543 and the misalignment of DR - the data reference recorded in
1544 LOOP_VINFO_UNALIGNED_DR (LOOP_VINFO). As a result, after the execution of
1545 this loop, the data reference DR will refer to an aligned location.
1547 The following computation is generated:
1549 If the misalignment of DR is known at compile time:
1550 addr_mis = int mis = DR_MISALIGNMENT (dr);
1551 Else, compute address misalignment in bytes:
1552 addr_mis = addr & (vectype_size - 1)
1554 prolog_niters = min ( LOOP_NITERS , (VF - addr_mis/elem_size)&(VF-1) )
1556 (elem_size = element type size; an element is the scalar element
1557 whose type is the inner type of the vectype) */
1559 static tree
1560 vect_gen_niters_for_prolog_loop (loop_vec_info loop_vinfo, tree loop_niters)
1562 struct data_reference *dr = LOOP_VINFO_UNALIGNED_DR (loop_vinfo);
1563 int vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
1564 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
1565 tree var, stmt;
1566 tree iters, iters_name;
1567 edge pe;
1568 basic_block new_bb;
1569 tree dr_stmt = DR_STMT (dr);
1570 stmt_vec_info stmt_info = vinfo_for_stmt (dr_stmt);
1571 tree vectype = STMT_VINFO_VECTYPE (stmt_info);
1572 int vectype_align = TYPE_ALIGN (vectype) / BITS_PER_UNIT;
1573 tree vf_minus_1 = build_int_cst (unsigned_type_node, vf - 1);
1574 tree niters_type = TREE_TYPE (loop_niters);
1576 pe = loop_preheader_edge (loop);
1578 if (LOOP_PEELING_FOR_ALIGNMENT (loop_vinfo) > 0)
1580 int byte_misalign = LOOP_PEELING_FOR_ALIGNMENT (loop_vinfo);
1581 int element_size = vectype_align/vf;
1582 int elem_misalign = byte_misalign / element_size;
1584 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
1585 fprintf (vect_dump, "known alignment = %d.", byte_misalign);
1586 iters = build_int_cst (niters_type, (vf - elem_misalign)&(vf-1));
1588 else
1590 tree new_stmts = NULL_TREE;
1591 tree start_addr =
1592 vect_create_addr_base_for_vector_ref (dr_stmt, &new_stmts, NULL_TREE);
1593 tree ptr_type = TREE_TYPE (start_addr);
1594 tree size = TYPE_SIZE (ptr_type);
1595 tree type = lang_hooks.types.type_for_size (tree_low_cst (size, 1), 1);
1596 tree vectype_size_minus_1 = build_int_cst (type, vectype_align - 1);
1597 tree elem_size_log =
1598 build_int_cst (unsigned_type_node, exact_log2 (vectype_align/vf));
1599 tree vf_tree = build_int_cst (unsigned_type_node, vf);
1600 tree byte_misalign;
1601 tree elem_misalign;
1603 new_bb = bsi_insert_on_edge_immediate (pe, new_stmts);
1604 gcc_assert (!new_bb);
1606 /* Create: byte_misalign = addr & (vectype_size - 1) */
1607 byte_misalign =
1608 build2 (BIT_AND_EXPR, type, start_addr, vectype_size_minus_1);
1610 /* Create: elem_misalign = byte_misalign / element_size */
1611 elem_misalign =
1612 build2 (RSHIFT_EXPR, unsigned_type_node, byte_misalign, elem_size_log);
1614 /* Create: (niters_type) (VF - elem_misalign)&(VF - 1) */
1615 iters = build2 (MINUS_EXPR, unsigned_type_node, vf_tree, elem_misalign);
1616 iters = build2 (BIT_AND_EXPR, unsigned_type_node, iters, vf_minus_1);
1617 iters = fold_convert (niters_type, iters);
1620 /* Create: prolog_loop_niters = min (iters, loop_niters) */
1621 /* If the loop bound is known at compile time we already verified that it is
1622 greater than vf; since the misalignment ('iters') is at most vf, there's
1623 no need to generate the MIN_EXPR in this case. */
1624 if (TREE_CODE (loop_niters) != INTEGER_CST)
1625 iters = build2 (MIN_EXPR, niters_type, iters, loop_niters);
1627 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
1629 fprintf (vect_dump, "niters for prolog loop: ");
1630 print_generic_expr (vect_dump, iters, TDF_SLIM);
1633 var = create_tmp_var (niters_type, "prolog_loop_niters");
1634 add_referenced_tmp_var (var);
1635 iters_name = force_gimple_operand (iters, &stmt, false, var);
1637 /* Insert stmt on loop preheader edge. */
1638 if (stmt)
1640 basic_block new_bb = bsi_insert_on_edge_immediate (pe, stmt);
1641 gcc_assert (!new_bb);
1644 return iters_name;
1648 /* Function vect_update_init_of_dr
1650 NITERS iterations were peeled from LOOP. DR represents a data reference
1651 in LOOP. This function updates the information recorded in DR to
1652 account for the fact that the first NITERS iterations had already been
1653 executed. Specifically, it updates the OFFSET field of stmt_info. */
1655 static void
1656 vect_update_init_of_dr (struct data_reference *dr, tree niters)
1658 stmt_vec_info stmt_info = vinfo_for_stmt (DR_STMT (dr));
1659 tree offset = STMT_VINFO_VECT_INIT_OFFSET (stmt_info);
1661 niters = fold (build2 (MULT_EXPR, TREE_TYPE (niters), niters,
1662 STMT_VINFO_VECT_STEP (stmt_info)));
1663 offset = fold (build2 (PLUS_EXPR, TREE_TYPE (offset), offset, niters));
1664 STMT_VINFO_VECT_INIT_OFFSET (stmt_info) = offset;
1668 /* Function vect_update_inits_of_drs
1670 NITERS iterations were peeled from the loop represented by LOOP_VINFO.
1671 This function updates the information recorded for the data references in
1672 the loop to account for the fact that the first NITERS iterations had
1673 already been executed. Specifically, it updates the initial_condition of the
1674 access_function of all the data_references in the loop. */
1676 static void
1677 vect_update_inits_of_drs (loop_vec_info loop_vinfo, tree niters)
1679 unsigned int i;
1680 varray_type loop_write_datarefs = LOOP_VINFO_DATAREF_WRITES (loop_vinfo);
1681 varray_type loop_read_datarefs = LOOP_VINFO_DATAREF_READS (loop_vinfo);
1683 if (vect_dump && (dump_flags & TDF_DETAILS))
1684 fprintf (vect_dump, "=== vect_update_inits_of_dr ===");
1686 for (i = 0; i < VARRAY_ACTIVE_SIZE (loop_write_datarefs); i++)
1688 struct data_reference *dr = VARRAY_GENERIC_PTR (loop_write_datarefs, i);
1689 vect_update_init_of_dr (dr, niters);
1692 for (i = 0; i < VARRAY_ACTIVE_SIZE (loop_read_datarefs); i++)
1694 struct data_reference *dr = VARRAY_GENERIC_PTR (loop_read_datarefs, i);
1695 vect_update_init_of_dr (dr, niters);
1700 /* Function vect_do_peeling_for_alignment
1702 Peel the first 'niters' iterations of the loop represented by LOOP_VINFO.
1703 'niters' is set to the misalignment of one of the data references in the
1704 loop, thereby forcing it to refer to an aligned location at the beginning
1705 of the execution of this loop. The data reference for which we are
1706 peeling is recorded in LOOP_VINFO_UNALIGNED_DR. */
1708 static void
1709 vect_do_peeling_for_alignment (loop_vec_info loop_vinfo, struct loops *loops)
1711 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
1712 tree niters_of_prolog_loop, ni_name;
1713 tree n_iters;
1714 struct loop *new_loop;
1716 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
1717 fprintf (vect_dump, "=== vect_do_peeling_for_alignment ===");
1719 ni_name = vect_build_loop_niters (loop_vinfo);
1720 niters_of_prolog_loop = vect_gen_niters_for_prolog_loop (loop_vinfo, ni_name);
1722 /* Peel the prolog loop and iterate it niters_of_prolog_loop. */
1723 new_loop =
1724 slpeel_tree_peel_loop_to_edge (loop, loops, loop_preheader_edge (loop),
1725 niters_of_prolog_loop, ni_name, true);
1726 #ifdef ENABLE_CHECKING
1727 gcc_assert (new_loop);
1728 slpeel_verify_cfg_after_peeling (new_loop, loop);
1729 #endif
1731 /* Update number of times loop executes. */
1732 n_iters = LOOP_VINFO_NITERS (loop_vinfo);
1733 LOOP_VINFO_NITERS (loop_vinfo) = fold (build2 (MINUS_EXPR,
1734 TREE_TYPE (n_iters), n_iters, niters_of_prolog_loop));
1736 /* Update the init conditions of the access functions of all data refs. */
1737 vect_update_inits_of_drs (loop_vinfo, niters_of_prolog_loop);
1739 /* After peeling we have to reset scalar evolution analyzer. */
1740 scev_reset ();
1742 return;
1746 /* Function vect_transform_loop.
1748 The analysis phase has determined that the loop is vectorizable.
1749 Vectorize the loop - created vectorized stmts to replace the scalar
1750 stmts in the loop, and update the loop exit condition. */
1752 void
1753 vect_transform_loop (loop_vec_info loop_vinfo,
1754 struct loops *loops ATTRIBUTE_UNUSED)
1756 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
1757 basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo);
1758 int nbbs = loop->num_nodes;
1759 block_stmt_iterator si;
1760 int i;
1761 tree ratio = NULL;
1762 int vectorization_factor = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
1764 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
1765 fprintf (vect_dump, "=== vec_transform_loop ===");
1768 /* Peel the loop if there are data refs with unknown alignment.
1769 Only one data ref with unknown store is allowed. */
1771 if (LOOP_PEELING_FOR_ALIGNMENT (loop_vinfo))
1772 vect_do_peeling_for_alignment (loop_vinfo, loops);
1774 /* If the loop has a symbolic number of iterations 'n' (i.e. it's not a
1775 compile time constant), or it is a constant that doesn't divide by the
1776 vectorization factor, then an epilog loop needs to be created.
1777 We therefore duplicate the loop: the original loop will be vectorized,
1778 and will compute the first (n/VF) iterations. The second copy of the loop
1779 will remain scalar and will compute the remaining (n%VF) iterations.
1780 (VF is the vectorization factor). */
1782 if (!LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
1783 || (LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
1784 && LOOP_VINFO_INT_NITERS (loop_vinfo) % vectorization_factor != 0))
1785 vect_do_peeling_for_loop_bound (loop_vinfo, &ratio, loops);
1786 else
1787 ratio = build_int_cst (TREE_TYPE (LOOP_VINFO_NITERS (loop_vinfo)),
1788 LOOP_VINFO_INT_NITERS (loop_vinfo) / vectorization_factor);
1790 /* 1) Make sure the loop header has exactly two entries
1791 2) Make sure we have a preheader basic block. */
1793 gcc_assert (EDGE_COUNT (loop->header->preds) == 2);
1795 loop_split_edge_with (loop_preheader_edge (loop), NULL);
1798 /* FORNOW: the vectorizer supports only loops which body consist
1799 of one basic block (header + empty latch). When the vectorizer will
1800 support more involved loop forms, the order by which the BBs are
1801 traversed need to be reconsidered. */
1803 for (i = 0; i < nbbs; i++)
1805 basic_block bb = bbs[i];
1807 for (si = bsi_start (bb); !bsi_end_p (si);)
1809 tree stmt = bsi_stmt (si);
1810 stmt_vec_info stmt_info;
1811 bool is_store;
1813 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
1815 fprintf (vect_dump, "------>vectorizing statement: ");
1816 print_generic_expr (vect_dump, stmt, TDF_SLIM);
1818 stmt_info = vinfo_for_stmt (stmt);
1819 gcc_assert (stmt_info);
1820 if (!STMT_VINFO_RELEVANT_P (stmt_info))
1822 bsi_next (&si);
1823 continue;
1825 #ifdef ENABLE_CHECKING
1826 /* FORNOW: Verify that all stmts operate on the same number of
1827 units and no inner unrolling is necessary. */
1828 gcc_assert
1829 (GET_MODE_NUNITS (TYPE_MODE (STMT_VINFO_VECTYPE (stmt_info)))
1830 == vectorization_factor);
1831 #endif
1832 /* -------- vectorize statement ------------ */
1833 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
1834 fprintf (vect_dump, "transform statement.");
1836 is_store = vect_transform_stmt (stmt, &si);
1837 if (is_store)
1839 /* free the attached stmt_vec_info and remove the stmt. */
1840 stmt_ann_t ann = stmt_ann (stmt);
1841 free (stmt_info);
1842 set_stmt_info (ann, NULL);
1843 bsi_remove (&si);
1844 continue;
1847 bsi_next (&si);
1848 } /* stmts in BB */
1849 } /* BBs in loop */
1851 slpeel_make_loop_iterate_ntimes (loop, ratio);
1853 if (vect_print_dump_info (REPORT_VECTORIZED_LOOPS, LOOP_LOC (loop_vinfo)))
1854 fprintf (vect_dump, "LOOP VECTORIZED.");